diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..729d9451 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +** @cosmos/stack-team diff --git a/.github/workflows/bsr-push.yml b/.github/workflows/bsr-push.yml index 1156101c..086b2d80 100644 --- a/.github/workflows/bsr-push.yml +++ b/.github/workflows/bsr-push.yml @@ -1,9 +1,16 @@ name: Push to Buf Schema Registry -# This workflow runs when a new version tag is pushed to the repository. -# It then pushes the Protobuf files corresponding to that tag on to the -# Buf Schema Registry at https://buf.build/cosmos/evm +# This workflow publishes Protobuf files to the Buf Schema Registry at +# https://buf.build/cosmos/evm when proto files change on main or a version tag +# is pushed. on: push: + branches: + - main + paths: + - "proto/**" + - "buf.work.yaml" + - "buf.gen.yaml" + - "buf.gen.proto.yaml" tags: - "v*.*.*" permissions: read-all diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..b680ac69 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,100 @@ +name: Build + +on: + workflow_dispatch: + push: + branches: + - main + - feat/krakatoa + +concurrency: + group: build-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + build: + timeout-minutes: 15 + runs-on: ${{ matrix.runner }} + strategy: + fail-fast: false + matrix: + include: + - goarch: amd64 + runner: depot-ubuntu-22.04-4 + - goarch: arm64 + runner: depot-ubuntu-22.04-arm-4 + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Required for git describe to get version tags + + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version: "1.25" + check-latest: true + cache: true + cache-dependency-path: | + go.sum + evmd/go.sum + + - name: Get version info + id: version + shell: bash + run: | + VERSION=$(git describe --tags --always | sed 's/^v//') + COMMIT=$(git log -1 --format='%H') + COMMIT_SHORT=$(git log -1 --format='%h') + TMVERSION=$(go list -m github.com/cometbft/cometbft | sed 's:.* ::') + BRANCH_NAME=$(echo "${{ github.ref_name }}" | sed 's|/|-|g') + + echo "version=${VERSION}" >> "$GITHUB_OUTPUT" + echo "commit=${COMMIT}" >> "$GITHUB_OUTPUT" + echo "commit_short=${COMMIT_SHORT}" >> "$GITHUB_OUTPUT" + echo "tmversion=${TMVERSION}" >> "$GITHUB_OUTPUT" + echo "branch=${BRANCH_NAME}" >> "$GITHUB_OUTPUT" + + - name: Build evmd + working-directory: evmd + env: + GOOS: linux + GOARCH: ${{ matrix.goarch }} + CGO_ENABLED: "1" + shell: bash + run: | + BINARY_NAME="evmd-${{ steps.version.outputs.branch }}-${{ steps.version.outputs.commit_short }}-linux-${{ matrix.goarch }}" + + go build \ + -trimpath \ + -tags "netgo" \ + -ldflags "-w -s \ + -X github.com/cosmos/cosmos-sdk/version.Name=evmd \ + -X github.com/cosmos/cosmos-sdk/version.AppName=evmd \ + -X github.com/cosmos/cosmos-sdk/version.Version=${{ steps.version.outputs.version }} \ + -X github.com/cosmos/cosmos-sdk/version.Commit=${{ steps.version.outputs.commit }} \ + -X github.com/cometbft/cometbft/version.TMCoreSemVer=${{ steps.version.outputs.tmversion }} \ + -X github.com/cosmos/cosmos-sdk/version.BuildTags=netgo" \ + -o "${BINARY_NAME}" \ + ./cmd/evmd + + - name: Generate checksum + working-directory: evmd + shell: bash + run: | + BINARY_NAME="evmd-${{ steps.version.outputs.branch }}-${{ steps.version.outputs.commit_short }}-linux-${{ matrix.goarch }}" + sha256sum "${BINARY_NAME}" > "${BINARY_NAME}.sha256" + + - name: Upload binary + uses: actions/upload-artifact@v4 + with: + name: evmd-${{ steps.version.outputs.branch }}-${{ steps.version.outputs.commit_short }}-linux-${{ matrix.goarch }} + path: | + evmd/evmd-${{ steps.version.outputs.branch }}-${{ steps.version.outputs.commit_short }}-linux-${{ matrix.goarch }} + evmd/evmd-${{ steps.version.outputs.branch }}-${{ steps.version.outputs.commit_short }}-linux-${{ matrix.goarch }}.sha256 + retention-days: 30 + if-no-files-found: error diff --git a/.github/workflows/check-changelog.yml b/.github/workflows/check-changelog.yml deleted file mode 100644 index 27ee6709..00000000 --- a/.github/workflows/check-changelog.yml +++ /dev/null @@ -1,53 +0,0 @@ -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/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml deleted file mode 100644 index fdf7e8e2..00000000 --- a/.github/workflows/codeql-analysis.yml +++ /dev/null @@ -1,80 +0,0 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. -# -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. -# -# ******** NOTE ******** -# We have attempted to detect the languages in your repository. Please check -# the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. -# -name: "CodeQL" - -on: - pull_request: -permissions: read-all - -jobs: - analyze: - name: Analyze - runs-on: depot-ubuntu-24.04-8 - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: ['go', 'javascript', 'python'] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] - # Learn more: - # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - uses: technote-space/get-diff-action@v6.1.2 - with: - PATTERNS: | - **/**.go - go.mod - go.sum - *.toml - **/**.py - **/**.js - **/**.ts - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v3 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: ./path/to/local/query, your-org/your-repo/queries@main - queries: crypto-com/cosmos-sdk-codeql@main,security-and-quality - if: env.GIT_DIFF - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - - name: Autobuild - uses: github/codeql-action/autobuild@v3 - if: env.GIT_DIFF - - # ℹ️ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl - - # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language - - # - run: | - # make bootstrap - # make release - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 - if: env.GIT_DIFF diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml index 9cc7b7bc..b9554b3a 100644 --- a/.github/workflows/dependencies.yml +++ b/.github/workflows/dependencies.yml @@ -14,7 +14,7 @@ jobs: steps: - uses: actions/setup-go@v5 with: - go-version: '1.23.6' + go-version: '1.25' check-latest: true - name: "Checkout Repository" uses: actions/checkout@v4 diff --git a/.github/workflows/jsonrpc-compatibility.yml b/.github/workflows/jsonrpc-compatibility.yml index 3d2b6323..1ca28df4 100644 --- a/.github/workflows/jsonrpc-compatibility.yml +++ b/.github/workflows/jsonrpc-compatibility.yml @@ -33,7 +33,7 @@ jobs: steps: - uses: actions/setup-go@v5 with: - go-version: "1.22" + go-version: "1.25" check-latest: true - uses: actions/checkout@v4 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index f5333647..d05f0f4e 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -21,7 +21,7 @@ jobs: steps: - uses: actions/setup-go@v5 with: - go-version: "1.24" + go-version: "1.25" check-latest: true - uses: actions/checkout@v4 diff --git a/.github/workflows/pr_title.yml b/.github/workflows/pr_title.yml index f86d7c76..14f39038 100644 --- a/.github/workflows/pr_title.yml +++ b/.github/workflows/pr_title.yml @@ -6,6 +6,9 @@ on: jobs: validate-pr-title: + permissions: + contents: read + pull-requests: read runs-on: ubuntu-latest steps: - name: PR Conventional Commit Validation diff --git a/.github/workflows/solidity-test.yml b/.github/workflows/solidity-test.yml index 7c074aad..532a509c 100644 --- a/.github/workflows/solidity-test.yml +++ b/.github/workflows/solidity-test.yml @@ -14,7 +14,7 @@ jobs: steps: - uses: actions/setup-go@v5 with: - go-version: '1.22' + go-version: '1.25' check-latest: true - uses: actions/checkout@v4 - uses: technote-space/get-diff-action@v6.1.2 diff --git a/.github/workflows/system-test.yml b/.github/workflows/system-test.yml index 1704bac9..ed3553f7 100644 --- a/.github/workflows/system-test.yml +++ b/.github/workflows/system-test.yml @@ -18,11 +18,11 @@ jobs: if: "!startsWith(github.ref, 'refs/tags/') && github.ref != 'refs/heads/main'" test-system: - runs-on: ubuntu-latest + runs-on: depot-ubuntu-24.04-16 steps: - uses: actions/setup-go@v5 with: - go-version: "1.22" + go-version: "1.25" check-latest: true - name: Install Foundry (forge/cast/anvil) uses: foundry-rs/foundry-toolchain@v1 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5b7d7e00..98204812 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,7 +22,7 @@ jobs: steps: - uses: actions/setup-go@v5 with: - go-version: "1.22" + go-version: "1.25" check-latest: true - uses: actions/checkout@v4 - uses: technote-space/get-diff-action@v6.1.2 @@ -75,24 +75,3 @@ jobs: make test-scripts if: env.GIT_DIFF - test-fuzz: - runs-on: depot-ubuntu-24.04-4 - steps: - - uses: actions/setup-go@v5 - with: - go-version: "1.22" - check-latest: true - - uses: actions/checkout@v4 - - uses: technote-space/get-diff-action@v6.1.2 - with: - PATTERNS: | - .github/workflows/test.yml - **/**.sol - **/**.go - go.mod - go.sum - *.toml - - name: run fuzz tests - run: | - make test-fuzz - if: env.GIT_DIFF diff --git a/.github/workflows/tests-compatibility-foundry-uniswap-v3.yml b/.github/workflows/tests-compatibility-foundry-uniswap-v3.yml index e53cad0b..fb15473f 100644 --- a/.github/workflows/tests-compatibility-foundry-uniswap-v3.yml +++ b/.github/workflows/tests-compatibility-foundry-uniswap-v3.yml @@ -35,7 +35,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: '1.22' + go-version: '1.25' - name: Install system dependencies run: | diff --git a/.github/workflows/tests-compatibility-foundry.yml b/.github/workflows/tests-compatibility-foundry.yml index 09c9f5bd..9cc2a454 100644 --- a/.github/workflows/tests-compatibility-foundry.yml +++ b/.github/workflows/tests-compatibility-foundry.yml @@ -35,7 +35,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: '1.22' + go-version: '1.25' - name: Install system dependencies run: | diff --git a/.github/workflows/tests-compatibility-hardhat.yml b/.github/workflows/tests-compatibility-hardhat.yml index 1a82d2b7..ac121cac 100644 --- a/.github/workflows/tests-compatibility-hardhat.yml +++ b/.github/workflows/tests-compatibility-hardhat.yml @@ -35,7 +35,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: '1.22' + go-version: '1.25' - name: Install system dependencies run: | diff --git a/.github/workflows/tests-compatibility-viem.yml b/.github/workflows/tests-compatibility-viem.yml index e9ab4084..2bb3c6e9 100644 --- a/.github/workflows/tests-compatibility-viem.yml +++ b/.github/workflows/tests-compatibility-viem.yml @@ -35,7 +35,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: '1.22' + go-version: '1.25' - name: Install system dependencies run: | diff --git a/.github/workflows/tests-compatibility-web3js.yml b/.github/workflows/tests-compatibility-web3js.yml index 44ab68c7..cf8534c8 100644 --- a/.github/workflows/tests-compatibility-web3js.yml +++ b/.github/workflows/tests-compatibility-web3js.yml @@ -35,7 +35,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: '1.22' + go-version: '1.25' - name: Install system dependencies run: | diff --git a/.github/workflows/trigger-docs-update.yml b/.github/workflows/trigger-docs-update.yml index 5680d2e9..d89d3958 100644 --- a/.github/workflows/trigger-docs-update.yml +++ b/.github/workflows/trigger-docs-update.yml @@ -1,5 +1,7 @@ # .github/workflows/trigger-docs-update.yml name: Trigger Docs Changelog Update +permissions: + contents: read on: release: diff --git a/.golangci.yml b/.golangci.yml index e1b0b763..5715ddfc 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -43,7 +43,6 @@ linters: - name: exported - name: if-return - name: increment-decrement - - name: var-naming - name: var-declaration - name: range - name: receiver-naming @@ -91,6 +90,10 @@ linters: - linters: - stylecheck text: 'ST1001:' + # todo: krakatoa specific (using deprecated metrics) + - linters: + - staticcheck + text: 'SA1019:.*(telemetry\.New|NewLabel|SetGaugeWithLabels|IncrCounterWithLabels|SetGauge|OpenTelemetry|IncrCounter)' paths: - x/vm/core - mempool/txpool @@ -117,7 +120,6 @@ formatters: - prefix(cosmossdk.io) - prefix(github.com/cosmos/cosmos-sdk) - prefix(github.com/CosmWasm/wasmd) - - prefix(github.com/cosmos/gaia) custom-order: true exclusions: generated: lax diff --git a/.mergify.yml b/.mergify.yml index 70b95c3d..5870a4d4 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -28,3 +28,12 @@ pull_request_rules: backport: branches: - release/v0.4.x + - name: backport patches to v0.5.x branch + conditions: + - base=main + - label=backport/0.5.x + actions: + backport: + branches: + - release/v0.5.x + diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..3be0230a --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,149 @@ +# AGENTS.md + +Guidance for AI coding agents working in the Cosmos EVM repository. + +## Project Overview + +Cosmos EVM adds EVM compatibility to Cosmos SDK chains. It exposes Ethereum +JSON-RPC, runs Solidity contracts, and integrates Cosmos modules (IBC, staking, +bank, etc.) via precompiles. `evmd` is the example chain used for testing and +local development. + +Docs: https://evm.cosmos.network/ + +## Repository Layout + +This repo is two Go modules: + +- `./` — `github.com/cosmos/evm` — library code (modules, precompiles, RPC). +- `./evmd/` — `github.com/cosmos/evm/evmd` — example chain binary and + integration tests. Has its own `go.mod`/`go.sum`. + +Top-level directories: + +- `x/` — Cosmos SDK modules: `vm` (EVM), `erc20`, `feemarket`, `ibc`. +- `precompiles/` — Solidity-callable precompiles bridging into Cosmos modules + (`bank`, `staking`, `distribution`, `gov`, `ics20`, `ics02`, `slashing`, + `bech32`, `p256`, `callbacks`, `werc20`, `erc20`). +- `ante/` — Ante handlers for EVM and Cosmos transactions. +- `mempool/` — Custom EVM-aware mempool. +- `rpc/` — Ethereum JSON-RPC server. +- `indexer/` — Block/tx indexer backing JSON-RPC. +- `ethereum/`, `crypto/`, `encoding/`, `server/`, `client/` — supporting + packages. +- `testutil/` — shared test helpers (network harness, factories, keyring). +- `tests/` — top-level tests: `integration/`, `jsonrpc/`, `solidity/`, + `systemtests/`, `speedtest/`. +- `evmd/tests/integration/` — integration tests that run against a real + `evmd` app instance. +- `proto/` — protobuf definitions; generated code lives next to the modules. +- `contracts/` — Solidity sources compiled via `scripts/compile_smart_contracts`. +- `docs/` — including `docs/migrations` for upgrade guides. + +## Toolchain + +- Go: see `go.mod` (currently 1.25.x). +- CGO required for builds (`CGO_ENABLED=1`). +- `golangci-lint` v2.10.1 (pinned in Makefile). +- Docker required for protobuf generation, localnet, and rpc-compat tests. +- Foundry (`forge`) required for `tests/systemtests/Counter`. +- Python (pylint, flake8, black, isort) for scripts. +- `solhint` for Solidity contracts. + +## Common Commands + +Run from the repo root unless noted. + +Build and install: + +```bash +make build # builds ./build/evmd +make install # installs evmd to $GOPATH/bin +make build-linux # cross-compile linux/amd64 +``` + +Tests: + +```bash +make test-unit # unit tests for the root module +make test-evmd # tests under ./evmd (run from evmd/, with -race) +make test-race # root module with -race +make test-all # both modules +make test-unit-cover # coverage for both modules +make test-solidity # hardhat/forge tests +make test-system # system tests (requires forge + builds v0.6 + current) +make test-rpc-compat # JSON-RPC compatibility (Docker) +make benchmark +``` + +All Go tests use the `test` build tag (`-tags=test`). Tests under `evmd/` +must be invoked from that directory because it is a separate module: + +```bash +cd evmd && go test -tags=test ./tests/integration/... +``` + +Lint and format: + +```bash +make lint # go + python + contracts +make lint-fix # auto-fix Go issues +make format # gofumpt + black + isort + shfmt +``` + +Protobuf and mocks (require Docker / Go tooling): + +```bash +make proto-all # format + lint + gen +make proto-gen +make mocks +``` + +Localnet: + +```bash +make localnet-start # 4-node docker testnet +make localnet-stop +./local_node.sh # single-node dev chain +``` + +## Conventions + +- **Two modules, one repo.** When changing public types in the root module + that `evmd` consumes, run tests in both modules. `go.work` is not used by + default — be explicit with `cd evmd` for evmd-side changes. +- **Build tag `test`.** Test-only helpers and constructors live behind + `//go:build test`. Forgetting the tag will produce confusing "undefined" + errors. +- **No generated edits.** Do not hand-edit `*.pb.go`, `*.pb.gw.go`, or + `*.pulsar.go`; regenerate with `make proto-gen`. +- **Signed, conventional commits.** PRs require signed commits and titles in + [conventional commit](https://www.conventionalcommits.org/) form + (`feat:`, `fix:`, `chore:`, `refactor:`, `test:`, `docs:`). Every PR must + link an existing GitHub issue (see `CONTRIBUTING.md`). +- **Migrations.** Any breaking change to chain state, module params, or + storage requires a corresponding migration and a doc entry under + `docs/migrations`. +- **Precompile changes** must update both Go bindings and the corresponding + Solidity ABI in `precompiles/*/abi.json` — they are checked at startup. +- **Don't add features beyond the task.** Match the change to what was + asked; don't refactor adjacent code or add unused abstractions. + +## Where to Look First + +- New module wiring: `evmd/app.go`. +- EVM keeper / state transitions: `x/vm/keeper/`. +- Adding a precompile: pattern under `precompiles//` plus registration + in `precompiles/types/` and `evmd/app.go`. +- JSON-RPC namespaces: `rpc/namespaces/ethereum/`. +- Ante handler order: `ante/`. +- Integration test patterns: `evmd/tests/integration/` and + `testutil/integration/evm/network/`. + +## Things to Avoid + +- Hand-editing `coverage.txt`, `go.sum`, or vendored / generated files. +- Skipping git hooks (`--no-verify`) or amending merged commits. +- Pushing to `main` directly; PRs only. +- Touching `tests/systemtests/Counter/lib/forge-std` (git submodule). +- Running `find` from `/` — search from the repo root. diff --git a/CHANGELOG.md b/CHANGELOG.md index f150ea70..208ee9fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,113 @@ ### DEPENDENCIES +### API-BREAKING + +### IMPROVEMENTS + +### FEATURES + +### BUG FIXES + +## v0.7.2 + +### IMPROVEMENTS +- [\#1243](https://github.com/cosmos/evm/pull/1243) Deploy contracts from an EOA rather than a module account in the test helpers. It is also now required: contract creation bumps the sender's nonce, `SetAccount` persists nonce and balance together, and the EVM commit path may not write a module account's balance. + +## v0.7.1 + +### IMPROVEMENTS +- [\#1239](https://github.com/cosmos/evm/pull/1239) Validate ICS-20 acknowledgement encoding in the erc20 IBC v2 middleware. + +### BUG FIXES +- [\#1223](https://github.com/cosmos/evm/pull/1223) Reject EVM txs below the base fee at mempool insert instead of silently queuing them. + +## v0.7.0 + +Follow the [migration document](docs/migrations/v0.6.x_to_v0.7.0.md) for upgrade instructions. + +### API-BREAKING +- [\#1146](https://github.com/cosmos/evm/pull/1146) Remove `EndBlocker` based mempool updates, use `PrepareCheckStater` instead. + +### IMPROVEMENTS + +- [\#758](https://github.com/cosmos/evm/pull/758) Cleanup precompiles abi.json. +- [\#810](https://github.com/cosmos/evm/pull/810) Fix integration test suite to resolve lock contention problem from external app injection +- [\#811](https://github.com/cosmos/evm/pull/811) Use sdk's DefaultBondDenom for default evm denom in genesis. +- [\#823](https://github.com/cosmos/evm/pull/823) Remove authz dependency from test suite and EvmApp interface +- [\#829](https://github.com/cosmos/evm/pull/829) Seperate test app interface +- [\#968](https://github.com/cosmos/evm/pull/968) Use normal gas config in ibc transfer to prevent potential DoS attack +- [\#1029](https://github.com/cosmos/evm/pull/1029) Mark EvmCoinInfo.Decimals field as deprecated +- [\#1079](https://github.com/cosmos/evm/pull/1079) Access Control List is now case-insensitive +- [\#1103](https://github.com/cosmos/evm/pull/1103) Align normal gas metering in ibc erc20 callback. +- [\#1108](https://github.com/cosmos/evm/pull/1108) Add json-rpc http server request body limit. +- [\#1118](https://github.com/cosmos/evm/pull/1118) Cache chain denom for evm mempool +- [\#1008](https://github.com/cosmos/evm/pull/1008) Stop enforcing JSON-RPC global filter cap and allow reclaim filters via configurable idle timeout. +- [\#1130](https://github.com/cosmos/evm/pull/1130) Use `sdk.ValidateAuthority` in `x/vm`, `x/erc20`, and `x/feemarket` `MsgServer` handlers so authority can optionally be centralized via the consensus `AuthorityParams` introduced in cosmos-sdk v0.54. +- [\#1164](https://github.com/cosmos/evm/pull/1164) Remove zero gas config from `ics20.transferWithStateDB` so inner KV ops in ICS20 transfer execution are metered, mirroring [\#1103](https://github.com/cosmos/evm/pull/1103). + +### FEATURES + +- New application evm+cosmos mempool ("Krakatoa") +- [\#589](https://github.com/cosmos/evm/pull/589) Remove parallelization blockers via migration from transient to object store, refactoring of gas, indexing, and bloom utilities. +- [\#768](https://github.com/cosmos/evm/pull/768) Added ICS-02 Client Router precompile +- [\#815](https://github.com/cosmos/evm/pull/815) Support for multi gRPC query clients serve with old binary. +- [\#1082](https://github.com/cosmos/evm/pull/1082) Enable incarnation cache for verify result. +- [\#1096](https://github.com/cosmos/evm/pull/1096) Allow eth_call overrides work with static precompiles. + +### BUG FIXES + +- [\#1047](https://github.com/cosmos/evm/pull/1047) Resolve EthTxIndex -1 sentinel before uint cast in ReceiptsFromCometBlock, preventing transactionIndex overflow to MaxUint64. +- [\#965](https://github.com/cosmos/evm/pull/965) Fix gas double charging on EVM calls in IBCOnTimeoutPacketCallback. +- [\#869](https://github.com/cosmos/evm/pull/869) Fix erc20 IBC callbacks to check for native token transfer before parsing recipient. +- [\#860](https://github.com/cosmos/evm/pull/860) Fix EIP-712 signature verification to use configured EVM chain ID instead of parsing cosmos chain ID string and replace legacytx.StdSignBytes with the aminojson sign mode handler. +- [\#794](https://github.com/cosmos/evm/pull/794) Fix mempool.max-txs flag not using desired default of 0 +- [\#748](https://github.com/cosmos/evm/pull/748) Fix DynamicFeeChecker in Cosmos ante handler to respect NoBaseFee feemarkets' parameter. +- [\#690](https://github.com/cosmos/evm/pull/690) Fix Ledger hardware wallet support for coin type 60. +- [\#769](https://github.com/cosmos/evm/pull/769) Fix erc20 ibc middleware to not to validate sender address format. +- [\#756](https://github.com/cosmos/evm/pull/756) Fix error message typo in NewMsgCancelProposal. +- [\#772](https://github.com/cosmos/evm/pull/772) Avoid panic on close if evm mempool not used. +- [\#774](https://github.com/cosmos/evm/pull/774) Emit proper allowance amount in erc20 event. +- [\#790](https://github.com/cosmos/evm/pull/790) fix panic in historical query due to missing EvmCoinInfo. +- [\#800](https://github.com/cosmos/evm/pull/800) Fix denom exponent validation in virtual fee deduct in vm module. +- [\#1132](https://github.com/cosmos/evm/pull/1132) Patch block-cumulative `log.Index` and eth-only `log.TxIndex` post-execution to fix indexing under BlockSTM. +- [\#817](https://github.com/cosmos/evm/pull/817) Align GetCoinbaseAddress to handle empty proposer address in contexts like CheckTx where proposer doesn't exist. +- [\#814](https://github.com/cosmos/evm/pull/814) Fix duplicated events in post tx processor. +- [\#816](https://github.com/cosmos/evm/pull/816) Avoid nil pointer when RPC requests execute before evmCoinInfo initialization in PreBlock with defaultEvmCoinInfo fallback. +- [\#828](https://github.com/cosmos/evm/pull/828) Validate decimals before conversion to prevent panic when coininfo is missing in historical queries. +- [\#905](https://github.com/cosmos/evm/pull/905) Fix EIP-6780 selfdestruct to properly delete contracts at pre-funded addresses by persisting code and account before DeleteAccount's IsContract check. +- [\#920](https://github.com/cosmos/evm/pull/920) Fix GetCoinbaseAddress to correctly convert validator operator address from Bech32 format to Ethereum address for block.coinbase opcode. +- [\#705](https://github.com/cosmos/evm/pull/705) Fix dynamic precompiles being disabled when EVM state overrides are used in eth_call. +- [\#967](https://github.com/cosmos/evm/pull/967) Fix return value of erc20 ibcv2 middleware to properly reflect application success and middleware failure. +- [\#992](https://github.com/cosmos/evm/pull/992) Respect the provided `gasCap` in `CallEVMWithData` instead of always used the default cap. +- [\#993](https://github.com/cosmos/evm/pull/993) Enforce `src_callback` contract address to match the packet sender for IBC acknowledgement and timeout callbacks to prevent arbitrary contract execution. +- [\#1061](https://github.com/cosmos/evm/pull/1061) Block nested ICS20 forwarding in source callbacks. +- [\#1050](https://github.com/cosmos/evm/pull/1050) Align precompile gas calculation with expected EVM gas semantics. +- [\#1107](https://github.com/cosmos/evm/pull/1107) Skip StateDB commit error transactions during receipt conversion to prevent `invalid message index` errors in block RPCs. + + +## v0.6.0 + +Follow the [migration document](docs/migrations/v0.5.x_to_v0.6.0.md) for upgrade instructions. + +### BREAKING CHANGES +- Removed IBC Transfer wrapper. Users are now required to use the precompile to transfer ERC20 tokens. +- Added StateDB as a parameter to internal EVM calls. + +### DEPENDENCIES + +### IMPROVEMENTS + +### FEATURES + +### BUG FIXES + +## v0.5.1 + +## v0.5.0 + +### DEPENDENCIES + ### BUG FIXES - [\#471](https://github.com/cosmos/evm/pull/471) Notify new block for mempool in time @@ -22,13 +129,14 @@ - [\#687](https://github.com/cosmos/evm/pull/687) Avoid blocking node shutdown when evm indexer is enabled, log startup failures instead of using errgroup. - [\#689](https://github.com/cosmos/evm/pull/689) Align debug addr for hex address. - [\#668](https://github.com/cosmos/evm/pull/668) Fix panic in legacy mempool when Reset() was called with a skipped header between old and new block. -- [\#723](https://github.com/cosmos/evm/pull/723) Fix TransactionIndex in receipt generation to use actual EthTxIndex instead of loop index. +- [\#723](https://github.com/cosmos/evm/pull/723), [\#806](https://github.com/cosmos/evm/pull/806) Fix TransactionIndex in receipt generation to use actual EthTxIndex instead of loop index. - [\#729](https://github.com/cosmos/evm/pull/729) Remove non-deterministic state mutation from EVM pre-blocker. - [\#725](https://github.com/cosmos/evm/pull/725) Fix inconsistent block hash in json-rpc. - [\#727](https://github.com/cosmos/evm/pull/727) Avoid nil pointer for `tx evm raw` due to uninitialized EVM coin info. - [\#730](https://github.com/cosmos/evm/pull/730) Fix panic if evm mempool not used. - [\#733](https://github.com/cosmos/evm/pull/733) Avoid rejecting tx with unsupported extension option for ExtensionOptionDynamicFeeTx. - [\#736](https://github.com/cosmos/evm/pull/736) Add InitEvmCoinInfo upgrade to avoid panic when denom is not registered. +- [\#732](https://github.com/cosmos/evm/pull/732) Fix gas meter race condition in integration tests ### IMPROVEMENTS @@ -65,8 +173,9 @@ - [\#709](https://github.com/cosmos/evm/pull/709) Fix mempool e2e test - [\#710](https://github.com/cosmos/evm/pull/710) Fix EoA-CA Identification logic - [\#711](https://github.com/cosmos/evm/pull/711) Add debug_traceCall api +- [\#720](https://github.com/cosmos/evm/pull/720) Refactor systemtests - [\#734](https://github.com/cosmos/evm/pull/734) Disable evm mempool if max-txs set to -1. - +- [\#743](https://github.com/cosmos/evm/pull/743) Apply state overrides to eth_estimateGas api ### FEATURES @@ -86,7 +195,6 @@ - [\#577](https://github.com/cosmos/evm/pull/577) Changed the way to create a stateful precompile based on the cmn.Precompile, change `NewPrecompile` to not return error. - [\#661](https://github.com/cosmos/evm/pull/661) Removes evmAppOptions from the repository and moves initialization to genesis. Chains must now have a display and denom metadata set for the defined EVM denom in the bank module's metadata. - ## v0.4.1 ### DEPENDENCIES diff --git a/Makefile b/Makefile index cda314b6..e4c1c504 100644 --- a/Makefile +++ b/Makefile @@ -43,6 +43,10 @@ build_tags = netgo ifeq (cleveldb,$(findstring cleveldb,$(COSMOS_BUILD_OPTIONS))) build_tags += gcc endif +ifeq (rocksdb,$(findstring rocksdb,$(COSMOS_BUILD_OPTIONS))) + build_tags += gcc + build_tags += rocksdb +endif build_tags += $(BUILD_TAGS) build_tags := $(strip $(build_tags)) @@ -58,6 +62,9 @@ ldflags = -X github.com/cosmos/cosmos-sdk/version.Name=os \ ifeq (cleveldb,$(findstring cleveldb,$(COSMOS_BUILD_OPTIONS))) ldflags += -X github.com/cosmos/cosmos-sdk/types.DBBackend=cleveldb endif +ifeq (rocksdb,$(findstring rocksdb,$(COSMOS_BUILD_OPTIONS))) + ldflags += -X github.com/cosmos/cosmos-sdk/types.DBBackend=rocksdb +endif # add build tags to linker flags whitespace := $(subst ,, ) @@ -89,8 +96,9 @@ endif # Build into $(BUILDDIR) build: go.sum $(BUILDDIR)/ - @echo "🏗️ Building evmd to $(BUILDDIR)/$(EXAMPLE_BINARY) ..." - @cd $(EVMD_DIR) && CGO_ENABLED="1" \ + echo "🏗️ Building evmd to $(BUILDDIR)/$(EXAMPLE_BINARY) ..." + echo "BUILD_FLAGS: $(BUILD_FLAGS)" + cd $(EVMD_DIR) && CGO_ENABLED="1" \ go build $(BUILD_FLAGS) -o $(BUILDDIR)/$(EXAMPLE_BINARY) $(EVMD_MAIN_PKG) # Cross-compile for Linux AMD64 @@ -100,6 +108,7 @@ build-linux: # Install into $(BINDIR) install: go.sum @echo "🚚 Installing evmd to $(BINDIR) ..." + @echo "BUILD_FLAGS: $(BUILD_FLAGS)" @cd $(EVMD_DIR) && CGO_ENABLED="1" \ go install $(BUILD_FLAGS) $(EVMD_MAIN_PKG) @@ -147,7 +156,7 @@ test-race: run-tests test-evmd: ARGS=-timeout=15m test-evmd: - @cd evmd && go test -race -tags=test -mod=readonly $(ARGS) $(EXTRA_ARGS) $(PACKAGES_EVMD) + @cd evmd && go test -count=1 -race -tags=test -mod=readonly $(ARGS) $(EXTRA_ARGS) $(PACKAGES_EVMD) test-unit-cover: ARGS=-timeout=15m -coverprofile=coverage.txt -covermode=atomic test-unit-cover: TEST_PACKAGES=$(PACKAGES_UNIT) @@ -160,8 +169,6 @@ test-unit-cover: run-tests @tail -n +2 evmd/coverage_evmd.txt >> coverage.txt && rm evmd/coverage_evmd.txt @echo "🧹 Filtering ignored files from coverage.txt..." @grep -v -E '/cmd/|/client/|/proto/|/testutil/|/mocks/|/test_.*\.go:|\.pb\.go:|\.pb\.gw\.go:|/x/[^/]+/module\.go:|/scripts/|/ibc/testing/|/version/|\.md:|\.pulsar\.go:' coverage.txt > tmp_coverage.txt && mv tmp_coverage.txt coverage.txt - @echo "📊 Coverage summary:" - @go tool cover -func=coverage.txt test: test-unit @@ -173,22 +180,11 @@ test-all: run-tests: ifneq (,$(shell which tparse 2>/dev/null)) - go test -race -tags=test -mod=readonly -json $(ARGS) $(EXTRA_ARGS) $(TEST_PACKAGES) | tparse + go test -count=1 -race -tags=test -mod=readonly -json $(ARGS) $(EXTRA_ARGS) $(TEST_PACKAGES) | tparse else - go test -race -tags=test -mod=readonly $(ARGS) $(EXTRA_ARGS) $(TEST_PACKAGES) -endif - -# Use the old Apple linker to workaround broken xcode - https://github.com/golang/go/issues/65169 -ifeq ($(OS_FAMILY),Darwin) - FUZZLDFLAGS := -ldflags=-extldflags=-Wl,-ld_classic + go test -count=1 -race -tags=test -mod=readonly $(ARGS) $(EXTRA_ARGS) $(TEST_PACKAGES) endif -test-fuzz: - go test -race -tags=test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzMintCoins ./x/precisebank/keeper - go test -race -tags=test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzBurnCoins ./x/precisebank/keeper - go test -race -tags=test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzSendCoins ./x/precisebank/keeper - go test -race -tags=test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzGenesisStateValidate_NonZeroRemainder ./x/precisebank/types - go test -race -tags=test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzGenesisStateValidate_ZeroRemainder ./x/precisebank/types test-scripts: @echo "Running scripts tests" @@ -209,7 +205,7 @@ benchmark: ### Linting ### ############################################################################### golangci_lint_cmd=golangci-lint -golangci_version=v2.2.2 +golangci_version=v2.10.1 lint: lint-go lint-python lint-contracts @@ -256,7 +252,7 @@ format-shell: ### Protobuf ### ############################################################################### -protoVer=0.14.0 +protoVer=0.18.1 protoImageName=ghcr.io/cosmos/proto-builder:$(protoVer) protoImage=$(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace --user 0 $(protoImageName) @@ -376,19 +372,19 @@ test-rpc-compat: test-rpc-compat-stop: cd tests/jsonrpc && docker compose down -.PHONY: localnet-start localnet-stop localnet-build-env localnet-build-nodes test-rpc-compat test-rpc-compat-stop +.PHONY: localnet-start localnet-stop localnet-build-env localnet-build-nodes test-rpc-compat test-rpc-compat-stop mocks -test-system: build-v04 build +test-system: build-v06 build mkdir -p ./tests/systemtests/binaries/ cp $(BUILDDIR)/evmd ./tests/systemtests/binaries/ cd tests/systemtests/Counter && forge build $(MAKE) -C tests/systemtests test -build-v04: - mkdir -p ./tests/systemtests/binaries/v0.4 - git checkout v0.4.1 +build-v06: + mkdir -p ./tests/systemtests/binaries/v0.6 + git checkout v0.6.0 make build - cp $(BUILDDIR)/evmd ./tests/systemtests/binaries/v0.4 + cp $(BUILDDIR)/evmd ./tests/systemtests/binaries/v0.6 git checkout - mocks: diff --git a/NOTICE b/NOTICE new file mode 100644 index 00000000..332778b3 --- /dev/null +++ b/NOTICE @@ -0,0 +1,13 @@ +NOTICE + +About Cosmos Labs + +Cosmos Labs is the development and growth organization behind the Cosmos stack of technologies and ecosystem, the world leading blockchain platform powering more than 200 production chains in finance, payments, and real-world assets. Cosmos Labs leads the development of the Cosmos technology stack, including the Cosmos SDK, CometBFT, and IBC protocols that enable sovereign, interoperable blockchains, in tandem with the Interchain Foundation. Cosmos Labs offers blockchain solutions for enterprises and finance, learn more by visiting: https://cosmos.network/, https://cosmoslabs.io/ + +Licence + +This product This product includes software developed by Cosmos Labs and is licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with the License. You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + +Attribution + +If you distribute this software or derivative works, you must include a copy of this NOTICE file (or equivalent attribution) in your distribution, as required by Section 4(d) of the Apache License, Version 2.0. diff --git a/README.md b/README.md index d6a56a48..27a2f32c 100644 --- a/README.md +++ b/README.md @@ -3,18 +3,18 @@ src="repo_header.svg" alt="Cosmos EVM - A plug-and-play solution that adds EVM compatibility and customizability to your chain" /> +## What is Cosmos EVM? + +Cosmos EVM is a plug-and-play solution that adds EVM compatibility and customizability to your Cosmos SDK chain. Cosmos EVM is used by Ondo, Mezo, Mantra, XRP sidechain, Telegram Application Chain (TAC), Stable, and others. Cosmos EVM equips Cosmos chains with complete Ethereum capabilities: Solidity smart contracts, Ethereum JSON-RPC, native support for the EVM wallet/token/user experience, and access to the entire Ethereum developer ecosystem. Its precompiles and extensions allow developers to leverage modules like [IBC](https://github.com/cosmos/ibc-go) with EVM and get native ERC-20 support for tokens on Cosmos. + +Cosmos EVM is customizable for your business use case, chain architecture, and performance needs. + **Please note**: This repo is undergoing changes while the code is being audited and tested. For the time being we will be making v0.x releases. Some breaking changes might occur. Cosmos Labs will only mark the Cosmos EVM repository as stable with a v1 release after the audit, key stability features and benchmarking are completed. **Visit the official documentation for Cosmos EVM**: [evm.cosmos.network](https://evm.cosmos.network/) -## What is Cosmos EVM? - -Cosmos EVM is a plug-and-play solution that adds EVM compatibility and customizability to your Cosmos SDK chain. Cosmos EVM equips Cosmos chains with complete Ethereum capabilities: Solidity smart contracts, Ethereum JSON-RPC, native support for the EVM wallet/token/user experience, and access to the entire Ethereum developer ecosystem. Its precompiles and extensions allow developers to leverage modules like [IBC](https://github.com/cosmos/ibc-go) with EVM and get native ERC-20 support for tokens on Cosmos. - -Cosmos EVM is customizable for your business use case, chain architecture, and performance needs. - ## Integration diff --git a/SECURITY.md b/SECURITY.md index eddc823b..8b540169 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -24,13 +24,13 @@ the vulnerability can be reproduced on either one of those. | Reporting methods | Bounty eligible | |---------------------------------------------------------------|-----------------| | [HackerOne program][h1] | no | -| [security@interchain.io](mailto:security@interchain.io) | no | +| [security@cosmoslabs.io](mailto:security@cosmoslabs.io) | no | Issues identified in this repository may be eligible for a [bug bounty][h1]. For your report to be bounty eligible it must be reported exclusively through the [HackerOne Bug Bounty][h1]. If you do not wish to be eligible for a bounty or do not want to use the HackerOne platform to report an -issue, please send your report via email to [security@interchain.io](mailto:security@interchain.io) with +issue, please send your report via email to [security@cosmoslabs.io](mailto:security@cosmoslabs.io) with reproduction steps and details of the issue. ### Guidelines diff --git a/ante/ante.go b/ante/ante.go index 15609516..4db31337 100644 --- a/ante/ante.go +++ b/ante/ante.go @@ -2,18 +2,21 @@ package ante import ( anteinterfaces "github.com/cosmos/evm/ante/interfaces" - ibckeeper "github.com/cosmos/ibc-go/v10/modules/core/keeper" + antetypes "github.com/cosmos/evm/ante/types" + "github.com/cosmos/evm/x/vm/types" + "github.com/cosmos/gogoproto/proto" + ibckeeper "github.com/cosmos/ibc-go/v11/modules/core/keeper" errorsmod "cosmossdk.io/errors" - storetypes "cosmossdk.io/store/types" - txsigning "cosmossdk.io/x/tx/signing" "github.com/cosmos/cosmos-sdk/codec" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" errortypes "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/types/tx/signing" "github.com/cosmos/cosmos-sdk/x/auth/ante" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + txsigning "github.com/cosmos/cosmos-sdk/x/tx/signing" ) // HandlerOptions defines the list of module keepers required to run the Cosmos EVM @@ -72,6 +75,8 @@ func (options HandlerOptions) Validate() error { // transaction-level processing (e.g. fee payment, signature verification) before // being passed onto it's respective handler. func NewAnteHandler(options HandlerOptions) sdk.AnteHandler { + extensionOptionsEthereumTx := "/" + proto.MessageName(&types.ExtensionOptionsEthereumTx{}) + extensionOptionsDynamicFeeTx := "/" + proto.MessageName(&antetypes.ExtensionOptionDynamicFeeTx{}) return func( ctx sdk.Context, tx sdk.Tx, sim bool, ) (newCtx sdk.Context, err error) { @@ -82,10 +87,10 @@ func NewAnteHandler(options HandlerOptions) sdk.AnteHandler { opts := txWithExtensions.GetExtensionOptions() if len(opts) > 0 { switch typeURL := opts[0].GetTypeUrl(); typeURL { - case "/cosmos.evm.vm.v1.ExtensionOptionsEthereumTx": + case extensionOptionsEthereumTx: // handle as *evmtypes.MsgEthereumTx anteHandler = newMonoEVMAnteHandler(ctx, options) - case "/cosmos.evm.ante.v1.ExtensionOptionDynamicFeeTx": + case extensionOptionsDynamicFeeTx: // cosmos-sdk tx with dynamic fee extension anteHandler = newCosmosAnteHandler(ctx, options) default: diff --git a/ante/cosmos.go b/ante/cosmos.go index 1820bd79..d1bad06a 100644 --- a/ante/cosmos.go +++ b/ante/cosmos.go @@ -4,7 +4,7 @@ import ( cosmosante "github.com/cosmos/evm/ante/cosmos" evmante "github.com/cosmos/evm/ante/evm" evmtypes "github.com/cosmos/evm/x/vm/types" - ibcante "github.com/cosmos/ibc-go/v10/modules/core/ante" + ibcante "github.com/cosmos/ibc-go/v11/modules/core/ante" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth/ante" @@ -40,6 +40,5 @@ func newCosmosAnteHandler(ctx sdk.Context, options HandlerOptions) sdk.AnteHandl ante.NewSigVerificationDecorator(options.AccountKeeper, options.SignModeHandler), ante.NewIncrementSequenceDecorator(options.AccountKeeper), ibcante.NewRedundantRelayDecorator(options.IBCKeeper), - evmante.NewGasWantedDecorator(options.EvmKeeper, options.FeeMarketKeeper, &feemarketParams), ) } diff --git a/ante/cosmos/eip712.go b/ante/cosmos/eip712.go index e800cee0..a246d368 100644 --- a/ante/cosmos/eip712.go +++ b/ante/cosmos/eip712.go @@ -1,8 +1,8 @@ package cosmos import ( + "context" "fmt" - "strconv" ethcrypto "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto/secp256k1" @@ -11,7 +11,9 @@ import ( anteinterfaces "github.com/cosmos/evm/ante/interfaces" "github.com/cosmos/evm/crypto/ethsecp256k1" "github.com/cosmos/evm/ethereum/eip712" + evmtypes "github.com/cosmos/evm/x/vm/types" + txv1beta1 "cosmossdk.io/api/cosmos/tx/v1beta1" errorsmod "cosmossdk.io/errors" "github.com/cosmos/cosmos-sdk/codec" @@ -21,11 +23,12 @@ import ( errortypes "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/types/tx/signing" authante "github.com/cosmos/cosmos-sdk/x/auth/ante" - "github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx" authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" + txsigning "github.com/cosmos/cosmos-sdk/x/tx/signing" + "github.com/cosmos/cosmos-sdk/x/tx/signing/aminojson" ) -var evmCodec codec.ProtoCodecMarshaler +var evmCodec codec.Codec func init() { registry := codectypes.NewInterfaceRegistry() @@ -136,6 +139,7 @@ func (svd LegacyEip712SigVerificationDecorator) AnteHandle(ctx sdk.Context, ChainID: chainID, AccountNumber: accNum, Sequence: acc.GetSequence(), + Address: acc.GetAddress().String(), } if simulate { @@ -177,22 +181,41 @@ func VerifySignature( return errorsmod.Wrap(errortypes.ErrNoSignatures, "tx doesn't contain any msgs to verify signature") } - txBytes := legacytx.StdSignBytes( - signerData.ChainID, - signerData.AccountNumber, - signerData.Sequence, - tx.GetTimeoutHeight(), - legacytx.StdFee{ - Amount: tx.GetFee(), - Gas: tx.GetGas(), + anyMsgs, err := eip712.ToAnyMsgs(msgs) + if err != nil { + return err + } + feeAmount := eip712.ToFeeAmount(tx.GetFee()) + txData := txsigning.TxData{ + Body: &txv1beta1.TxBody{ + Messages: anyMsgs, + Memo: tx.GetMemo(), + TimeoutHeight: tx.GetTimeoutHeight(), }, - msgs, tx.GetMemo(), - ) - - signerChainID, err := strconv.ParseUint(signerData.ChainID, 10, 64) + AuthInfo: &txv1beta1.AuthInfo{ + Fee: &txv1beta1.Fee{ + Amount: feeAmount, + GasLimit: tx.GetGas(), + }, + }, + } + signModeHandler := aminojson.NewSignModeHandler(aminojson.SignModeHandlerOptions{}) + signer := txsigning.SignerData{ + ChainID: signerData.ChainID, + AccountNumber: signerData.AccountNumber, + Sequence: signerData.Sequence, + Address: signerData.Address, + } + txBytes, err := signModeHandler.GetSignBytes(context.Background(), signer, txData) if err != nil { - return errorsmod.Wrapf(err, "failed to parse chain-id: %s", signerData.ChainID) + return errorsmod.Wrap(err, "failed to get sign bytes using aminojson") + } + + ethChainID := evmtypes.GetEthChainConfig().ChainID + if ethChainID == nil { + return errorsmod.Wrap(errortypes.ErrInvalidChainID, "eth chain ID not configured") } + signerChainID := ethChainID.Uint64() txWithExtensions, ok := tx.(authante.HasExtensionOptionsTx) if !ok { diff --git a/ante/evm/01_setup_ctx.go b/ante/evm/01_setup_ctx.go index 6357e7eb..96448614 100644 --- a/ante/evm/01_setup_ctx.go +++ b/ante/evm/01_setup_ctx.go @@ -1,12 +1,11 @@ package evm import ( - anteinterfaces "github.com/cosmos/evm/ante/interfaces" evmante "github.com/cosmos/evm/x/vm/ante" errorsmod "cosmossdk.io/errors" - storetypes "cosmossdk.io/store/types" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdktypes "github.com/cosmos/cosmos-sdk/types" errortypes "github.com/cosmos/cosmos-sdk/types/errors" authante "github.com/cosmos/cosmos-sdk/x/auth/ante" @@ -16,18 +15,10 @@ var _ sdktypes.AnteDecorator = &EthSetupContextDecorator{} // EthSetupContextDecorator is adapted from SetUpContextDecorator from cosmos-sdk, it ignores gas consumption // by setting the gas meter to infinite -type EthSetupContextDecorator struct { - evmKeeper anteinterfaces.EVMKeeper -} - -func NewEthSetUpContextDecorator(evmKeeper anteinterfaces.EVMKeeper) EthSetupContextDecorator { - return EthSetupContextDecorator{ - evmKeeper: evmKeeper, - } -} +type EthSetupContextDecorator struct{} func (esc EthSetupContextDecorator) AnteHandle(ctx sdktypes.Context, tx sdktypes.Tx, simulate bool, next sdktypes.AnteHandler) (newCtx sdktypes.Context, err error) { - newCtx, err = SetupContextAndResetTransientGas(ctx, tx, esc.evmKeeper) + newCtx, err = SetupContextAndResetTransientGas(ctx, tx) if err != nil { return ctx, err } @@ -37,7 +28,7 @@ func (esc EthSetupContextDecorator) AnteHandle(ctx sdktypes.Context, tx sdktypes // SetupContextAndResetTransientGas modifies the context to be used in the // execution of the ante handler associated with an EVM transaction. Previous // gas consumed is reset in the transient store. -func SetupContextAndResetTransientGas(ctx sdktypes.Context, tx sdktypes.Tx, evmKeeper anteinterfaces.EVMKeeper) (sdktypes.Context, error) { +func SetupContextAndResetTransientGas(ctx sdktypes.Context, tx sdktypes.Tx) (sdktypes.Context, error) { // all transactions must implement GasTx _, ok := tx.(authante.GasTx) if !ok { @@ -50,12 +41,5 @@ func SetupContextAndResetTransientGas(ctx sdktypes.Context, tx sdktypes.Tx, evmK newCtx := evmante.BuildEvmExecutionCtx(ctx). WithGasMeter(storetypes.NewInfiniteGasMeter()) - // Reset transient gas used to prepare the execution of current cosmos tx. - // Transient gas-used is necessary to sum the gas-used of cosmos tx, when it contains multiple eth msgs. - // - // TODO: add more context here to explain why gas used is reset. Not clear - // from docstring. - evmKeeper.ResetTransientGasUsed(ctx) - return newCtx, nil } diff --git a/ante/evm/04_validate.go b/ante/evm/04_validate.go index 611d7845..e3cd478e 100644 --- a/ante/evm/04_validate.go +++ b/ante/evm/04_validate.go @@ -88,10 +88,18 @@ func ValidateTx(tx sdktypes.Tx) (*tx.Fee, error) { return nil, errorsmod.Wrap(errortypes.ErrInvalidRequest, "for eth tx AuthInfo SignerInfos should be empty") } + if authInfo.Fee == nil { + return nil, errorsmod.Wrap(errortypes.ErrInvalidRequest, "authInfo.Fee should not be nil") + } + if authInfo.Fee.Payer != "" || authInfo.Fee.Granter != "" { return nil, errorsmod.Wrap(errortypes.ErrInvalidRequest, "for eth tx AuthInfo Fee payer and granter should be empty") } + if authInfo.Tip != nil { + return nil, errorsmod.Wrap(errortypes.ErrInvalidRequest, "authInfo.Tip must be nil") + } + sigs := protoTx.Signatures if len(sigs) > 0 { return nil, errorsmod.Wrap(errortypes.ErrInvalidRequest, "for eth tx Signatures should be empty") diff --git a/ante/evm/05_signature_verification.go b/ante/evm/05_signature_verification.go index 4c2dd914..39cb0e02 100644 --- a/ante/evm/05_signature_verification.go +++ b/ante/evm/05_signature_verification.go @@ -1,6 +1,7 @@ package evm import ( + "fmt" "math/big" ethtypes "github.com/ethereum/go-ethereum/core/types" @@ -14,6 +15,10 @@ import ( errortypes "github.com/cosmos/cosmos-sdk/types/errors" ) +// EthSigVerificationResultCacheKey caches sig verification per incarnation, +// since the result is a pure function of the tx bytes and signer. +const EthSigVerificationResultCacheKey = "ante:EthSigVerificationResult" + // EthSigVerificationDecorator validates an ethereum signatures type EthSigVerificationDecorator struct { evmKeeper anteinterfaces.EVMKeeper @@ -32,6 +37,17 @@ 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) { + if v, ok := ctx.GetIncarnationCache(EthSigVerificationResultCacheKey); ok { + if v != nil { + cachedErr, ok := v.(error) + if !ok { + return ctx, fmt.Errorf("unexpected type %T cached under %s, want error", v, EthSigVerificationResultCacheKey) + } + return ctx, cachedErr + } + return next(ctx, tx, simulate) + } + 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 @@ -44,15 +60,20 @@ func (esvd EthSigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, s for _, msg := range msgs { msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx) if !ok { - return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil)) + err = errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil)) + ctx.SetIncarnationCache(EthSigVerificationResultCacheKey, err) + return ctx, err } - err := SignatureVerification(msgEthTx, msgEthTx.AsTransaction(), signer) + err = SignatureVerification(msgEthTx, msgEthTx.AsTransaction(), signer) if err != nil { + ctx.SetIncarnationCache(EthSigVerificationResultCacheKey, err) return ctx, err } } + ctx.SetIncarnationCache(EthSigVerificationResultCacheKey, nil) + return next(ctx, tx, simulate) } @@ -60,11 +81,7 @@ func (esvd EthSigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, s // that the signer address matches the one defined on the message. // The function set the field from of the given message equal to the sender // computed from the signature of the Ethereum transaction. -func SignatureVerification( - msg *evmtypes.MsgEthereumTx, - ethTx *ethtypes.Transaction, - signer ethtypes.Signer, -) error { +func SignatureVerification(msg *evmtypes.MsgEthereumTx, _ *ethtypes.Transaction, signer ethtypes.Signer) error { if err := msg.VerifySender(signer); err != nil { return errorsmod.Wrapf(errortypes.ErrorInvalidSigner, "signature verification failed: %s", err.Error()) } diff --git a/ante/evm/05_signature_verification_test.go b/ante/evm/05_signature_verification_test.go new file mode 100644 index 00000000..7f808a84 --- /dev/null +++ b/ante/evm/05_signature_verification_test.go @@ -0,0 +1,54 @@ +package evm_test + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/require" + + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + + "github.com/cosmos/evm/ante/evm" + + "cosmossdk.io/log/v2" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func TestEthSigVerificationDecorator_CacheHit(t *testing.T) { + dec := evm.NewEthSigVerificationDecorator(nil) + var tx sdk.Tx + newCtx := func() sdk.Context { + return sdk.NewContext(nil, tmproto.Header{}, false, log.NewNopLogger()). + WithIncarnationCache(map[string]any{}) + } + next := func(c sdk.Context, _ sdk.Tx, _ bool) (sdk.Context, error) { return c, nil } + cachedErr := errors.New("cached sig verification failure") + + t.Run("cached error short-circuits", func(t *testing.T) { + ctx := newCtx() + ctx.SetIncarnationCache(evm.EthSigVerificationResultCacheKey, cachedErr) + _, err := dec.AnteHandle(ctx, tx, true, next) + require.ErrorIs(t, err, cachedErr) + }) + + t.Run("non-error cached value returns explicit error", func(t *testing.T) { + ctx := newCtx() + ctx.SetIncarnationCache(evm.EthSigVerificationResultCacheKey, "not-an-error") + _, err := dec.AnteHandle(ctx, tx, true, next) + require.ErrorContains(t, err, "unexpected type string") + }) + + t.Run("cached nil success calls next without re-verifying", func(t *testing.T) { + ctx := newCtx() + ctx.SetIncarnationCache(evm.EthSigVerificationResultCacheKey, nil) + + nextCalled := false + _, err := dec.AnteHandle(ctx, tx, true, func(c sdk.Context, _ sdk.Tx, _ bool) (sdk.Context, error) { + nextCalled = true + return c, nil + }) + require.NoError(t, err) + require.True(t, nextCalled, "next handler must run when cache holds a nil success") + }) +} diff --git a/ante/evm/10_gas_wanted.go b/ante/evm/10_gas_wanted.go deleted file mode 100644 index ef07c0ec..00000000 --- a/ante/evm/10_gas_wanted.go +++ /dev/null @@ -1,85 +0,0 @@ -package evm - -import ( - "math/big" - - anteinterfaces "github.com/cosmos/evm/ante/interfaces" - "github.com/cosmos/evm/ante/types" - feemarkettypes "github.com/cosmos/evm/x/feemarket/types" - evmtypes "github.com/cosmos/evm/x/vm/types" - - errorsmod "cosmossdk.io/errors" - - sdk "github.com/cosmos/cosmos-sdk/types" - errortypes "github.com/cosmos/cosmos-sdk/types/errors" -) - -// GasWantedDecorator keeps track of the gasWanted amount on the current block in transient store -// for BaseFee calculation. -// NOTE: This decorator does not perform any validation -type GasWantedDecorator struct { - evmKeeper anteinterfaces.EVMKeeper - feeMarketKeeper anteinterfaces.FeeMarketKeeper - feemarketParams *feemarkettypes.Params -} - -// NewGasWantedDecorator creates a new NewGasWantedDecorator -func NewGasWantedDecorator( - evmKeeper anteinterfaces.EVMKeeper, - feeMarketKeeper anteinterfaces.FeeMarketKeeper, - feemarketParams *feemarkettypes.Params, -) GasWantedDecorator { - return GasWantedDecorator{ - evmKeeper, - feeMarketKeeper, - feemarketParams, - } -} - -func (gwd GasWantedDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { - ethCfg := evmtypes.GetEthChainConfig() - - blockHeight := big.NewInt(ctx.BlockHeight()) - isLondon := ethCfg.IsLondon(blockHeight) - - if err := CheckGasWanted(ctx, gwd.feeMarketKeeper, tx, isLondon, gwd.feemarketParams); err != nil { - return ctx, err - } - - return next(ctx, tx, simulate) -} - -func CheckGasWanted(ctx sdk.Context, feeMarketKeeper anteinterfaces.FeeMarketKeeper, tx sdk.Tx, isLondon bool, feemarketParams *feemarkettypes.Params) error { - if !isLondon { - return nil - } - - feeTx, ok := tx.(sdk.FeeTx) - if !ok { - return nil - } - - gasWanted := feeTx.GetGas() - - // return error if the tx gas is greater than the block limit (max gas) - blockGasLimit := types.BlockGasLimit(ctx) - if gasWanted > blockGasLimit { - return errorsmod.Wrapf( - errortypes.ErrOutOfGas, - "tx gas (%d) exceeds block gas limit (%d)", - gasWanted, - blockGasLimit, - ) - } - - if !feemarketParams.IsBaseFeeEnabled(ctx.BlockHeight()) { - return nil - } - - // Add total gasWanted to cumulative in block transientStore in FeeMarket module - if _, err := feeMarketKeeper.AddTransientGasWanted(ctx, gasWanted); err != nil { - return errorsmod.Wrapf(err, "failed to add gas wanted to transient store") - } - - return nil -} diff --git a/ante/evm/11_emit_event.go b/ante/evm/11_emit_event.go index 26431302..dfc832bc 100644 --- a/ante/evm/11_emit_event.go +++ b/ante/evm/11_emit_event.go @@ -3,62 +3,20 @@ package evm import ( "strconv" - anteinterfaces "github.com/cosmos/evm/ante/interfaces" evmtypes "github.com/cosmos/evm/x/vm/types" - errorsmod "cosmossdk.io/errors" - sdk "github.com/cosmos/cosmos-sdk/types" - errortypes "github.com/cosmos/cosmos-sdk/types/errors" ) -// EthEmitEventDecorator emit events in ante handler in case of tx execution failed (out of block gas limit). -type EthEmitEventDecorator struct { - evmKeeper anteinterfaces.EVMKeeper -} - -// NewEthEmitEventDecorator creates a new EthEmitEventDecorator -func NewEthEmitEventDecorator(evmKeeper anteinterfaces.EVMKeeper) EthEmitEventDecorator { - return EthEmitEventDecorator{evmKeeper} -} - -// AnteHandle emits some basic events for the eth messages -func (eeed EthEmitEventDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { - // After eth tx passed ante handler, the fee is deducted and nonce increased, it shouldn't be ignored by json-rpc, - // we need to emit some basic events at the very end of ante handler to be indexed by CometBFT. - blockTxIndex := eeed.evmKeeper.GetTxIndexTransient(ctx) - - msgs := tx.GetMsgs() - if msgs == nil { - return ctx, errorsmod.Wrap(errortypes.ErrUnknownRequest, "invalid transaction. Transaction without messages") - } - - for i, msg := range msgs { - msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx) - if !ok { - return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil)) - } - - txIdx := uint64(i) //nolint:gosec // G115 // won't exceed uint64 - EmitTxHashEvent(ctx, msgEthTx, blockTxIndex, txIdx) - } - - return next(ctx, tx, simulate) -} - -// EmitTxHashEvent emits the Ethereum tx -// -// FIXME: This is Technical debt. Ideally the sdk.Tx hash should be the Ethereum -// tx hash (msg.Hash) instead of using events for indexing Eth txs. -// TxIndex should be included in the header vote extension as part of ABCI++ -func EmitTxHashEvent(ctx sdk.Context, msg *evmtypes.MsgEthereumTx, blockTxIndex, msgIndex uint64) { - // emit ethereum tx hash as an event so that it can be indexed by CometBFT for query purposes - // it's emitted in ante handler, so we can query failed transaction (out of block gas limit). +// EmitTxHashEvent emits the ethereum_tx event with the tx hash and the +// cosmos-tx index from ctx.TxIndex(). Emitting from the ante handler ensures +// expected-failure txs still produce the event for indexer lookups. +func EmitTxHashEvent(ctx sdk.Context, msg *evmtypes.MsgEthereumTx, blockTxIndex uint64) { ctx.EventManager().EmitEvent( sdk.NewEvent( evmtypes.EventTypeEthereumTx, sdk.NewAttribute(evmtypes.AttributeKeyEthereumTxHash, msg.Hash().String()), - sdk.NewAttribute(evmtypes.AttributeKeyTxIndex, strconv.FormatUint(blockTxIndex+msgIndex, 10)), // #nosec G115 + sdk.NewAttribute(evmtypes.AttributeKeyTxIndex, strconv.FormatUint(blockTxIndex, 10)), // #nosec G115 ), ) } diff --git a/ante/evm/fee_checker.go b/ante/evm/fee_checker.go index a31c1f01..b2d57075 100644 --- a/ante/evm/fee_checker.go +++ b/ante/evm/fee_checker.go @@ -58,10 +58,9 @@ func FeeChecker( } baseFee := feemarketParams.BaseFee - // if baseFee is nil because it is disabled - // or not found, consider it as 0 + // if baseFee is not enabled, consider it 0 // so the DynamicFeeTx logic can be applied - if baseFee.IsNil() { + if baseFee.IsNil() || !feemarketParams.IsBaseFeeEnabled(ctx.BlockHeight()) { baseFee = sdkmath.LegacyZeroDec() } @@ -93,7 +92,7 @@ func FeeChecker( } feeCoins := feeTx.GetFee() - feeAmtDec := sdkmath.LegacyNewDecFromInt(feeCoins.AmountOfNoDenomValidation(denom)) + feeAmtDec := sdkmath.LegacyNewDecFromInt(feeCoins.AmountOf(denom)) feeCap := feeAmtDec.QuoInt(gas) if feeCap.LT(baseFee) { diff --git a/ante/evm/fee_checker_test.go b/ante/evm/fee_checker_test.go index 0c83002c..ca21b7d8 100644 --- a/ante/evm/fee_checker_test.go +++ b/ante/evm/fee_checker_test.go @@ -10,13 +10,12 @@ import ( "github.com/cosmos/evm/ante/evm" "github.com/cosmos/evm/ante/types" - "github.com/cosmos/evm/config" "github.com/cosmos/evm/encoding" testconstants "github.com/cosmos/evm/testutil/constants" feemarkettypes "github.com/cosmos/evm/x/feemarket/types" evmtypes "github.com/cosmos/evm/x/vm/types" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" "cosmossdk.io/math" codectypes "github.com/cosmos/cosmos-sdk/codec/types" @@ -34,7 +33,7 @@ func TestSDKTxFeeChecker(t *testing.T) { // with extension option // without extension option // london hardfork enableness - chainID := uint64(config.EighteenDecimalsChainID) + chainID := uint64(testconstants.EighteenDecimalsChainID) encodingConfig := encoding.MakeConfig(chainID) //nolint:staticcheck // this is used configurator := evmtypes.NewEVMConfigurator() @@ -47,7 +46,7 @@ func TestSDKTxFeeChecker(t *testing.T) { err := configurator. WithExtendedEips(evmtypes.DefaultCosmosEVMActivators). // NOTE: we're using the 18 decimals default for the example chain - WithEVMCoinInfo(config.ChainsCoinInfo[chainID]). + WithEVMCoinInfo(testconstants.ChainsCoinInfo[chainID]). Configure() require.NoError(t, err) if err != nil { diff --git a/ante/evm/mono_decorator.go b/ante/evm/mono_decorator.go index ba460155..f60f87a7 100644 --- a/ante/evm/mono_decorator.go +++ b/ante/evm/mono_decorator.go @@ -1,6 +1,7 @@ package evm import ( + "fmt" "math" "math/big" @@ -79,7 +80,7 @@ func (md MonoDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, ne evmDenom := evmtypes.GetEVMCoinDenom() // 1. setup ctx - ctx, err = SetupContextAndResetTransientGas(ctx, tx, md.evmKeeper) + ctx, err = SetupContextAndResetTransientGas(ctx, tx) if err != nil { return ctx, err } @@ -96,9 +97,8 @@ func (md MonoDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, ne if len(msgs) != 1 { return ctx, errorsmod.Wrapf(errortypes.ErrInvalidRequest, "expected 1 message, got %d", len(msgs)) } - msgIndex := 0 - ethMsg, ethTx, err := evmtypes.UnpackEthMsg(msgs[msgIndex]) + ethMsg, ethTx, err := evmtypes.UnpackEthMsg(msgs[0]) if err != nil { return ctx, err } @@ -155,20 +155,25 @@ func (md MonoDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, ne } // 4. validate msg contents - if err := ValidateMsg( - decUtils.EvmParams, - ethTx, - ); err != nil { + if err := ValidateMsg(decUtils.EvmParams, ethTx); err != nil { return ctx, err } // 5. signature verification - if err := SignatureVerification( - ethMsg, - ethTx, - decUtils.Signer, - ); err != nil { - return ctx, err + if v, ok := ctx.GetIncarnationCache(EthSigVerificationResultCacheKey); ok { + if v != nil { + cachedErr, ok := v.(error) + if !ok { + return ctx, fmt.Errorf("unexpected type %T cached under %s, want error", v, EthSigVerificationResultCacheKey) + } + return ctx, cachedErr + } + } else { + err = SignatureVerification(ethMsg, ethTx, decUtils.Signer) + ctx.SetIncarnationCache(EthSigVerificationResultCacheKey, err) + if err != nil { + return ctx, err + } } from := ethMsg.GetFrom() @@ -265,14 +270,7 @@ func (md MonoDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, ne return ctx, err } - // 10. gas wanted - if err := CheckGasWanted(ctx, md.feeMarketKeeper, tx, decUtils.Rules.IsLondon, md.feemarketParams); err != nil { - return ctx, err - } - - // 11. emit events - txIdx := uint64(msgIndex) //nolint:gosec // G115 - EmitTxHashEvent(ctx, ethMsg, decUtils.BlockTxIndex, txIdx) + EmitTxHashEvent(ctx, ethMsg, uint64(ctx.TxIndex())) // #nosec G115 -- no overflow here if err := CheckTxFee(txFeeInfo, decUtils.TxFee, decUtils.TxGasLimit); err != nil { return ctx, err diff --git a/ante/evm/mono_decorator_test.go b/ante/evm/mono_decorator_test.go index 72e20599..c96d0a5b 100644 --- a/ante/evm/mono_decorator_test.go +++ b/ante/evm/mono_decorator_test.go @@ -2,6 +2,7 @@ package evm_test import ( "context" + "errors" "math/big" "testing" "time" @@ -17,9 +18,9 @@ import ( tmproto "github.com/cometbft/cometbft/proto/tendermint/types" "github.com/cosmos/evm/ante/evm" - "github.com/cosmos/evm/config" "github.com/cosmos/evm/crypto/ethsecp256k1" "github.com/cosmos/evm/encoding" + "github.com/cosmos/evm/testutil/constants" utiltx "github.com/cosmos/evm/testutil/tx" feemarkettypes "github.com/cosmos/evm/x/feemarket/types" "github.com/cosmos/evm/x/vm/statedb" @@ -27,10 +28,10 @@ import ( vmtypes "github.com/cosmos/evm/x/vm/types/mocks" "cosmossdk.io/core/address" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" "cosmossdk.io/math" - storetypes "cosmossdk.io/store/types" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" ) @@ -62,13 +63,11 @@ func (k *ExtendedEVMKeeper) SpendableCoin(ctx sdk.Context, addr common.Address) return uint256.NewInt(0) } -func (k *ExtendedEVMKeeper) ResetTransientGasUsed(_ sdk.Context) {} func (k *ExtendedEVMKeeper) GetParams(_ sdk.Context) evmsdktypes.Params { return evmsdktypes.DefaultParams() } func (k *ExtendedEVMKeeper) GetBaseFee(_ sdk.Context) *big.Int { return big.NewInt(0) } func (k *ExtendedEVMKeeper) GetMinGasPrice(_ sdk.Context) math.LegacyDec { return math.LegacyZeroDec() } -func (k *ExtendedEVMKeeper) GetTxIndexTransient(_ sdk.Context) uint64 { return 0 } // only methods called by EVMMonoDecorator type MockFeeMarketKeeper struct{} @@ -79,9 +78,6 @@ func (m MockFeeMarketKeeper) GetParams(ctx sdk.Context) feemarkettypes.Params { return param } -func (m MockFeeMarketKeeper) AddTransientGasWanted(_ sdk.Context, _ uint64) (uint64, error) { - return 0, nil -} func (m MockFeeMarketKeeper) GetBaseFeeEnabled(_ sdk.Context) bool { return true } func (m MockFeeMarketKeeper) GetBaseFee(_ sdk.Context) math.LegacyDec { return math.LegacyZeroDec() } @@ -145,49 +141,78 @@ func toMsgSlice(msgs []*evmsdktypes.MsgEthereumTx) []sdk.Msg { return out } -func TestMonoDecorator(t *testing.T) { - chainID := uint64(config.EighteenDecimalsChainID) - cfg := encoding.MakeConfig(chainID) +type monoTestEnv struct { + dec evm.MonoDecorator + privKey *ethsecp256k1.PrivKey + cfg encoding.Config +} + +func setupMonoEnv(t *testing.T) monoTestEnv { + t.Helper() + configurator := evmsdktypes.NewEVMConfigurator() + configurator.ResetTestConfig() + require.NoError(t, evmsdktypes.SetChainConfig(evmsdktypes.DefaultChainConfig(evmsdktypes.DefaultEVMChainID))) + require.NoError(t, configurator. + WithExtendedEips(evmsdktypes.DefaultCosmosEVMActivators). + WithEVMCoinInfo(evmsdktypes.EvmCoinInfo{ + Denom: evmsdktypes.DefaultEVMExtendedDenom, + ExtendedDenom: evmsdktypes.DefaultEVMExtendedDenom, + DisplayDenom: evmsdktypes.DefaultEVMDisplayDenom, + Decimals: 18, + }). + Configure()) + + privKey, _ := ethsecp256k1.GenerateKey() + keeper, cosmosAddr := setupFundedKeeper(t, privKey) + accountKeeper := MockAccountKeeper{FundedAddr: cosmosAddr} + feeMarketKeeper := MockFeeMarketKeeper{} + params := keeper.GetParams(sdk.Context{}) + feemarketParams := feeMarketKeeper.GetParams(sdk.Context{}) + + return monoTestEnv{ + dec: evm.NewEVMMonoDecorator(accountKeeper, feeMarketKeeper, keeper, 0, ¶ms, &feemarketParams), + privKey: privKey, + cfg: encoding.MakeConfig(uint64(constants.EighteenDecimalsChainID)), + } +} + +func newMonoCtx() sdk.Context { + return sdk.NewContext(nil, tmproto.Header{}, false, log.NewNopLogger()). + WithBlockGasMeter(storetypes.NewGasMeter(1e19)). + WithConsensusParams(tmproto.ConsensusParams{Block: &tmproto.BlockParams{MaxBytes: 200000, MaxGas: 81500000}}) +} + +func defaultEthTxArgs() *evmsdktypes.EvmTxArgs { + return &evmsdktypes.EvmTxArgs{ + Nonce: 0, + GasLimit: 100000, + GasPrice: big.NewInt(1), + Input: []byte("test"), + } +} +func TestMonoDecorator(t *testing.T) { testCases := []struct { name string - simulate bool - buildMsgs func(privKey *ethsecp256k1.PrivKey) []*evmsdktypes.MsgEthereumTx + buildMsgs func(env monoTestEnv) []*evmsdktypes.MsgEthereumTx expErr string }{ { "success with one evm tx", - true, - func(privKey *ethsecp256k1.PrivKey) []*evmsdktypes.MsgEthereumTx { - args := &evmsdktypes.EvmTxArgs{ - Nonce: 0, - GasLimit: 100000, - GasPrice: big.NewInt(1), - Input: []byte("test"), - } - return []*evmsdktypes.MsgEthereumTx{signMsgEthereumTx(t, privKey, args)} + func(env monoTestEnv) []*evmsdktypes.MsgEthereumTx { + return []*evmsdktypes.MsgEthereumTx{signMsgEthereumTx(t, env.privKey, defaultEthTxArgs())} }, "", }, { "failure with two evm txs", - true, - func(privKey *ethsecp256k1.PrivKey) []*evmsdktypes.MsgEthereumTx { - args1 := &evmsdktypes.EvmTxArgs{ - Nonce: 0, - GasLimit: 100000, - GasPrice: big.NewInt(1), - Input: []byte("test"), - } - args2 := &evmsdktypes.EvmTxArgs{ - Nonce: 1, - GasLimit: 100000, - GasPrice: big.NewInt(1), - Input: []byte("test2"), - } + func(env monoTestEnv) []*evmsdktypes.MsgEthereumTx { + args2 := defaultEthTxArgs() + args2.Nonce = 1 + args2.Input = []byte("test2") return []*evmsdktypes.MsgEthereumTx{ - signMsgEthereumTx(t, privKey, args1), - signMsgEthereumTx(t, privKey, args2), + signMsgEthereumTx(t, env.privKey, defaultEthTxArgs()), + signMsgEthereumTx(t, env.privKey, args2), } }, "expected 1 message, got 2", @@ -196,38 +221,11 @@ func TestMonoDecorator(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - configurator := evmsdktypes.NewEVMConfigurator() - configurator.ResetTestConfig() - chainConfig := evmsdktypes.DefaultChainConfig(evmsdktypes.DefaultEVMChainID) - err := evmsdktypes.SetChainConfig(chainConfig) - require.NoError(t, err) - coinInfo := evmsdktypes.EvmCoinInfo{ - Denom: evmsdktypes.DefaultEVMExtendedDenom, - ExtendedDenom: evmsdktypes.DefaultEVMExtendedDenom, - DisplayDenom: evmsdktypes.DefaultEVMDisplayDenom, - Decimals: 18, - } - err = configurator. - WithExtendedEips(evmsdktypes.DefaultCosmosEVMActivators). - // NOTE: we're using the 18 decimals default for the example chain - WithEVMCoinInfo(coinInfo). - Configure() - require.NoError(t, err) - privKey, _ := ethsecp256k1.GenerateKey() - keeper, cosmosAddr := setupFundedKeeper(t, privKey) - accountKeeper := MockAccountKeeper{FundedAddr: cosmosAddr} - feeMarketKeeper := MockFeeMarketKeeper{} - params := keeper.GetParams(sdk.Context{}) - feemarketParams := feeMarketKeeper.GetParams(sdk.Context{}) - monoDec := evm.NewEVMMonoDecorator(accountKeeper, feeMarketKeeper, keeper, 0, ¶ms, &feemarketParams) - ctx := sdk.NewContext(nil, tmproto.Header{}, false, log.NewNopLogger()) - ctx = ctx.WithBlockGasMeter(storetypes.NewGasMeter(1e19)) - - msgs := tc.buildMsgs(privKey) - tx, err := utiltx.PrepareEthTx(cfg.TxConfig, nil, toMsgSlice(msgs)...) + env := setupMonoEnv(t) + tx, err := utiltx.PrepareEthTx(env.cfg.TxConfig, nil, toMsgSlice(tc.buildMsgs(env))...) require.NoError(t, err) - newCtx, err := monoDec.AnteHandle(ctx, tx, tc.simulate, func(ctx sdk.Context, _ sdk.Tx, _ bool) (sdk.Context, error) { return ctx, nil }) + newCtx, err := env.dec.AnteHandle(newMonoCtx(), tx, true, func(ctx sdk.Context, _ sdk.Tx, _ bool) (sdk.Context, error) { return ctx, nil }) if tc.expErr == "" { require.NoError(t, err) require.NotNil(t, newCtx) @@ -237,3 +235,28 @@ func TestMonoDecorator(t *testing.T) { }) } } + +func TestMonoDecorator_SigVerificationCacheHit(t *testing.T) { + env := setupMonoEnv(t) + dec := env.dec + msgs := []*evmsdktypes.MsgEthereumTx{signMsgEthereumTx(t, env.privKey, defaultEthTxArgs())} + tx, err := utiltx.PrepareEthTx(env.cfg.TxConfig, nil, toMsgSlice(msgs)...) + require.NoError(t, err) + newCtx := func() sdk.Context { return newMonoCtx().WithIncarnationCache(map[string]any{}) } + next := func(c sdk.Context, _ sdk.Tx, _ bool) (sdk.Context, error) { return c, nil } + cachedErr := errors.New("cached sig verification failure") + + t.Run("cached error short-circuits", func(t *testing.T) { + ctx := newCtx() + ctx.SetIncarnationCache(evm.EthSigVerificationResultCacheKey, cachedErr) + _, err := dec.AnteHandle(ctx, tx, true, next) + require.ErrorIs(t, err, cachedErr) + }) + + t.Run("non-error cached value returns explicit error", func(t *testing.T) { + ctx := newCtx() + ctx.SetIncarnationCache(evm.EthSigVerificationResultCacheKey, "not-an-error") + _, err := dec.AnteHandle(ctx, tx, true, next) + require.ErrorContains(t, err, "unexpected type string") + }) +} diff --git a/ante/evm/nonce_limit_test.go b/ante/evm/nonce_limit_test.go index a6c3b8c3..b8403724 100644 --- a/ante/evm/nonce_limit_test.go +++ b/ante/evm/nonce_limit_test.go @@ -34,7 +34,7 @@ func (m *mockAccountKeeper) GetAccount(ctx context.Context, addr sdk.AccAddress) } func (m *mockAccountKeeper) SetAccount(ctx context.Context, account sdk.AccountI) { m.last = account } func (m *mockAccountKeeper) RemoveAccount(ctx context.Context, account sdk.AccountI) {} -func (m *mockAccountKeeper) GetParams(ctx context.Context) (params authtypes.Params) { return } +func (m *mockAccountKeeper) GetParams(ctx context.Context) (params authtypes.Params) { return params } func (m *mockAccountKeeper) GetSequence(ctx context.Context, addr sdk.AccAddress) (uint64, error) { if m.last == nil { return 0, nil diff --git a/ante/evm/utils.go b/ante/evm/utils.go index 48e45ebe..e43468c5 100644 --- a/ante/evm/utils.go +++ b/ante/evm/utils.go @@ -26,7 +26,6 @@ type DecoratorUtils struct { BaseFee *big.Int MempoolMinGasPrice sdkmath.LegacyDec GlobalMinGasPrice sdkmath.LegacyDec - BlockTxIndex uint64 TxGasLimit uint64 GasWanted uint64 MinPriority int64 @@ -66,14 +65,16 @@ func NewMonoDecoratorUtils( // If it is already a 18 decimal token, this is a no-op. mempoolMinGasPrice := evmtypes.ConvertAmountTo18DecimalsLegacy(ctx.MinGasPrices().AmountOf(evmDenom)) + //#nosec G115 -- int overflow is not a concern here + signer := ethtypes.MakeSigner(ethCfg, blockHeight, uint64(ctx.BlockTime().Unix())) + return &DecoratorUtils{ EvmParams: *evmParams, Rules: rules, - Signer: ethtypes.MakeSigner(ethCfg, blockHeight, uint64(ctx.BlockTime().Unix())), //#nosec G115 -- int overflow is not a concern here + Signer: signer, BaseFee: baseFee, MempoolMinGasPrice: mempoolMinGasPrice, GlobalMinGasPrice: globalMinGasPrice, - BlockTxIndex: ek.GetTxIndexTransient(ctx), GasWanted: 0, MinPriority: int64(math.MaxInt64), // TxGasLimit and TxFee are set to zero because they are updated diff --git a/ante/interfaces/evm.go b/ante/interfaces/evm.go index d296e7b7..d6477912 100644 --- a/ante/interfaces/evm.go +++ b/ante/interfaces/evm.go @@ -23,15 +23,12 @@ type EVMKeeper interface { stateDB vm.StateDB) *vm.EVM DeductTxCostsFromUserBalance(ctx sdk.Context, fees sdk.Coins, from common.Address) error SpendableCoin(ctx sdk.Context, addr common.Address) *uint256.Int - ResetTransientGasUsed(ctx sdk.Context) - GetTxIndexTransient(ctx sdk.Context) uint64 GetParams(ctx sdk.Context) evmtypes.Params } // FeeMarketKeeper exposes the required feemarket keeper interface required for ante handlers type FeeMarketKeeper interface { GetParams(ctx sdk.Context) (params feemarkettypes.Params) - AddTransientGasWanted(ctx sdk.Context, gasWanted uint64) (uint64, error) } type ProtoTxProvider interface { diff --git a/ante/sigverify.go b/ante/sigverify.go index 62b1c6b3..27105739 100644 --- a/ante/sigverify.go +++ b/ante/sigverify.go @@ -6,11 +6,11 @@ import ( "github.com/cosmos/evm/crypto/ethsecp256k1" errorsmod "cosmossdk.io/errors" - storetypes "cosmossdk.io/store/types" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/cosmos/cosmos-sdk/crypto/types/multisig" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" errortypes "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/types/tx/signing" authante "github.com/cosmos/cosmos-sdk/x/auth/ante" diff --git a/ante/sigverify_test.go b/ante/sigverify_test.go index dce22274..6de83936 100644 --- a/ante/sigverify_test.go +++ b/ante/sigverify_test.go @@ -10,14 +10,13 @@ import ( "github.com/cosmos/evm/encoding" "github.com/cosmos/evm/server/config" - storetypes "cosmossdk.io/store/types" - "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256r1" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" "github.com/cosmos/cosmos-sdk/crypto/types/multisig" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" "github.com/cosmos/cosmos-sdk/types/tx/signing" "github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" diff --git a/ante/types/block.go b/ante/types/block.go index b235da52..0fc68642 100644 --- a/ante/types/block.go +++ b/ante/types/block.go @@ -10,13 +10,6 @@ import ( // set, it returns the max gas from the application consensus params. // NOTE: see https://github.com/cosmos/cosmos-sdk/issues/9514 for full reference func BlockGasLimit(ctx sdk.Context) uint64 { - blockGasMeter := ctx.BlockGasMeter() - - // Get the limit from the gas meter only if its not null and not an InfiniteGasMeter - if blockGasMeter != nil && blockGasMeter.Limit() != 0 { - return blockGasMeter.Limit() - } - // Otherwise get from the consensus parameters cp := ctx.ConsensusParams() if cp.Block == nil { diff --git a/ante/utils_test.go b/ante/utils_test.go index dd31c792..00890aa9 100644 --- a/ante/utils_test.go +++ b/ante/utils_test.go @@ -19,7 +19,7 @@ func generatePubKeysAndSignatures(n int, msg []byte, _ bool) (pubkeys []cryptoty pubkeys[i] = privkey.PubKey() signatures[i], _ = privkey.Sign(msg) } - return + return pubkeys, signatures } func expectedGasCostByKeys(pubkeys []cryptotypes.PubKey) uint64 { diff --git a/api/cosmos/evm/erc20/v1/erc20.pulsar.go b/api/cosmos/evm/erc20/v1/erc20.pulsar.go index 38811715..006824e6 100644 --- a/api/cosmos/evm/erc20/v1/erc20.pulsar.go +++ b/api/cosmos/evm/erc20/v1/erc20.pulsar.go @@ -3550,8 +3550,9 @@ func (Owner) EnumDescriptor() ([]byte, []int) { return file_cosmos_evm_erc20_v1_erc20_proto_rawDescGZIP(), []int{0} } -// 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. +// 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/query_grpc.pb.go b/api/cosmos/evm/erc20/v1/query_grpc.pb.go index c3135549..f9512121 100644 --- a/api/cosmos/evm/erc20/v1/query_grpc.pb.go +++ b/api/cosmos/evm/erc20/v1/query_grpc.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.3.0 +// - protoc-gen-go-grpc v1.6.0 // - protoc (unknown) // source: cosmos/evm/erc20/v1/query.proto @@ -15,8 +15,8 @@ import ( // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.32.0 or later. -const _ = grpc.SupportPackageIsVersion7 +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 const ( Query_TokenPairs_FullMethodName = "/cosmos.evm.erc20.v1.Query/TokenPairs" @@ -27,6 +27,8 @@ const ( // QueryClient is the client API for Query service. // // 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. +// +// Query defines the gRPC querier service. type QueryClient interface { // TokenPairs retrieves registered token pairs (mappings)x TokenPairs(ctx context.Context, in *QueryTokenPairsRequest, opts ...grpc.CallOption) (*QueryTokenPairsResponse, error) @@ -45,8 +47,9 @@ func NewQueryClient(cc grpc.ClientConnInterface) QueryClient { } func (c *queryClient) TokenPairs(ctx context.Context, in *QueryTokenPairsRequest, opts ...grpc.CallOption) (*QueryTokenPairsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(QueryTokenPairsResponse) - err := c.cc.Invoke(ctx, Query_TokenPairs_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Query_TokenPairs_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -54,8 +57,9 @@ func (c *queryClient) TokenPairs(ctx context.Context, in *QueryTokenPairsRequest } func (c *queryClient) TokenPair(ctx context.Context, in *QueryTokenPairRequest, opts ...grpc.CallOption) (*QueryTokenPairResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(QueryTokenPairResponse) - err := c.cc.Invoke(ctx, Query_TokenPair_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Query_TokenPair_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -63,8 +67,9 @@ func (c *queryClient) TokenPair(ctx context.Context, in *QueryTokenPairRequest, } func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(QueryParamsResponse) - err := c.cc.Invoke(ctx, Query_Params_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Query_Params_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -73,7 +78,9 @@ func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts . // QueryServer is the server API for Query service. // All implementations must embed UnimplementedQueryServer -// for forward compatibility +// for forward compatibility. +// +// Query defines the gRPC querier service. type QueryServer interface { // TokenPairs retrieves registered token pairs (mappings)x TokenPairs(context.Context, *QueryTokenPairsRequest) (*QueryTokenPairsResponse, error) @@ -84,20 +91,24 @@ type QueryServer interface { mustEmbedUnimplementedQueryServer() } -// UnimplementedQueryServer must be embedded to have forward compatible implementations. -type UnimplementedQueryServer struct { -} +// UnimplementedQueryServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedQueryServer struct{} func (UnimplementedQueryServer) TokenPairs(context.Context, *QueryTokenPairsRequest) (*QueryTokenPairsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method TokenPairs not implemented") + return nil, status.Error(codes.Unimplemented, "method TokenPairs not implemented") } func (UnimplementedQueryServer) TokenPair(context.Context, *QueryTokenPairRequest) (*QueryTokenPairResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method TokenPair not implemented") + return nil, status.Error(codes.Unimplemented, "method TokenPair not implemented") } func (UnimplementedQueryServer) Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Params not implemented") + return nil, status.Error(codes.Unimplemented, "method Params not implemented") } func (UnimplementedQueryServer) mustEmbedUnimplementedQueryServer() {} +func (UnimplementedQueryServer) testEmbeddedByValue() {} // UnsafeQueryServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to QueryServer will @@ -107,6 +118,13 @@ type UnsafeQueryServer interface { } func RegisterQueryServer(s grpc.ServiceRegistrar, srv QueryServer) { + // If the following call panics, it indicates UnimplementedQueryServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } s.RegisterService(&Query_ServiceDesc, srv) } diff --git a/api/cosmos/evm/erc20/v1/tx_grpc.pb.go b/api/cosmos/evm/erc20/v1/tx_grpc.pb.go index b78f770e..bb743458 100644 --- a/api/cosmos/evm/erc20/v1/tx_grpc.pb.go +++ b/api/cosmos/evm/erc20/v1/tx_grpc.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.3.0 +// - protoc-gen-go-grpc v1.6.0 // - protoc (unknown) // source: cosmos/evm/erc20/v1/tx.proto @@ -15,8 +15,8 @@ import ( // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.32.0 or later. -const _ = grpc.SupportPackageIsVersion7 +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 const ( Msg_ConvertERC20_FullMethodName = "/cosmos.evm.erc20.v1.Msg/ConvertERC20" @@ -29,6 +29,8 @@ const ( // MsgClient is the client API for Msg service. // // 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. +// +// Msg defines the erc20 Msg service. type MsgClient interface { // ConvertERC20 mints a native Cosmos coin representation of the ERC20 token // contract that is registered on the token mapping. @@ -59,8 +61,9 @@ func NewMsgClient(cc grpc.ClientConnInterface) MsgClient { } func (c *msgClient) ConvertERC20(ctx context.Context, in *MsgConvertERC20, opts ...grpc.CallOption) (*MsgConvertERC20Response, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(MsgConvertERC20Response) - err := c.cc.Invoke(ctx, Msg_ConvertERC20_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Msg_ConvertERC20_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -68,8 +71,9 @@ func (c *msgClient) ConvertERC20(ctx context.Context, in *MsgConvertERC20, opts } func (c *msgClient) ConvertCoin(ctx context.Context, in *MsgConvertCoin, opts ...grpc.CallOption) (*MsgConvertCoinResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(MsgConvertCoinResponse) - err := c.cc.Invoke(ctx, Msg_ConvertCoin_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Msg_ConvertCoin_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -77,8 +81,9 @@ func (c *msgClient) ConvertCoin(ctx context.Context, in *MsgConvertCoin, opts .. } func (c *msgClient) UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(MsgUpdateParamsResponse) - err := c.cc.Invoke(ctx, Msg_UpdateParams_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Msg_UpdateParams_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -86,8 +91,9 @@ func (c *msgClient) UpdateParams(ctx context.Context, in *MsgUpdateParams, opts } func (c *msgClient) RegisterERC20(ctx context.Context, in *MsgRegisterERC20, opts ...grpc.CallOption) (*MsgRegisterERC20Response, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(MsgRegisterERC20Response) - err := c.cc.Invoke(ctx, Msg_RegisterERC20_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Msg_RegisterERC20_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -95,8 +101,9 @@ func (c *msgClient) RegisterERC20(ctx context.Context, in *MsgRegisterERC20, opt } func (c *msgClient) ToggleConversion(ctx context.Context, in *MsgToggleConversion, opts ...grpc.CallOption) (*MsgToggleConversionResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(MsgToggleConversionResponse) - err := c.cc.Invoke(ctx, Msg_ToggleConversion_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Msg_ToggleConversion_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -105,7 +112,9 @@ func (c *msgClient) ToggleConversion(ctx context.Context, in *MsgToggleConversio // MsgServer is the server API for Msg service. // All implementations must embed UnimplementedMsgServer -// for forward compatibility +// for forward compatibility. +// +// Msg defines the erc20 Msg service. type MsgServer interface { // ConvertERC20 mints a native Cosmos coin representation of the ERC20 token // contract that is registered on the token mapping. @@ -128,26 +137,30 @@ type MsgServer interface { mustEmbedUnimplementedMsgServer() } -// UnimplementedMsgServer must be embedded to have forward compatible implementations. -type UnimplementedMsgServer struct { -} +// UnimplementedMsgServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedMsgServer struct{} func (UnimplementedMsgServer) ConvertERC20(context.Context, *MsgConvertERC20) (*MsgConvertERC20Response, error) { - return nil, status.Errorf(codes.Unimplemented, "method ConvertERC20 not implemented") + return nil, status.Error(codes.Unimplemented, "method ConvertERC20 not implemented") } func (UnimplementedMsgServer) ConvertCoin(context.Context, *MsgConvertCoin) (*MsgConvertCoinResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ConvertCoin not implemented") + return nil, status.Error(codes.Unimplemented, "method ConvertCoin not implemented") } func (UnimplementedMsgServer) UpdateParams(context.Context, *MsgUpdateParams) (*MsgUpdateParamsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method UpdateParams not implemented") + return nil, status.Error(codes.Unimplemented, "method UpdateParams not implemented") } func (UnimplementedMsgServer) RegisterERC20(context.Context, *MsgRegisterERC20) (*MsgRegisterERC20Response, error) { - return nil, status.Errorf(codes.Unimplemented, "method RegisterERC20 not implemented") + return nil, status.Error(codes.Unimplemented, "method RegisterERC20 not implemented") } func (UnimplementedMsgServer) ToggleConversion(context.Context, *MsgToggleConversion) (*MsgToggleConversionResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ToggleConversion not implemented") + return nil, status.Error(codes.Unimplemented, "method ToggleConversion not implemented") } func (UnimplementedMsgServer) mustEmbedUnimplementedMsgServer() {} +func (UnimplementedMsgServer) testEmbeddedByValue() {} // UnsafeMsgServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to MsgServer will @@ -157,6 +170,13 @@ type UnsafeMsgServer interface { } func RegisterMsgServer(s grpc.ServiceRegistrar, srv MsgServer) { + // If the following call panics, it indicates UnimplementedMsgServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } s.RegisterService(&Msg_ServiceDesc, srv) } diff --git a/api/cosmos/evm/feemarket/v1/query_grpc.pb.go b/api/cosmos/evm/feemarket/v1/query_grpc.pb.go index e26ca803..d395a751 100644 --- a/api/cosmos/evm/feemarket/v1/query_grpc.pb.go +++ b/api/cosmos/evm/feemarket/v1/query_grpc.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.3.0 +// - protoc-gen-go-grpc v1.6.0 // - protoc (unknown) // source: cosmos/evm/feemarket/v1/query.proto @@ -15,8 +15,8 @@ import ( // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.32.0 or later. -const _ = grpc.SupportPackageIsVersion7 +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 const ( Query_Params_FullMethodName = "/cosmos.evm.feemarket.v1.Query/Params" @@ -27,6 +27,8 @@ const ( // QueryClient is the client API for Query service. // // 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. +// +// Query defines the gRPC querier service. type QueryClient interface { // Params queries the parameters of x/feemarket module. Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) @@ -45,8 +47,9 @@ func NewQueryClient(cc grpc.ClientConnInterface) QueryClient { } func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(QueryParamsResponse) - err := c.cc.Invoke(ctx, Query_Params_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Query_Params_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -54,8 +57,9 @@ func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts . } func (c *queryClient) BaseFee(ctx context.Context, in *QueryBaseFeeRequest, opts ...grpc.CallOption) (*QueryBaseFeeResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(QueryBaseFeeResponse) - err := c.cc.Invoke(ctx, Query_BaseFee_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Query_BaseFee_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -63,8 +67,9 @@ func (c *queryClient) BaseFee(ctx context.Context, in *QueryBaseFeeRequest, opts } func (c *queryClient) BlockGas(ctx context.Context, in *QueryBlockGasRequest, opts ...grpc.CallOption) (*QueryBlockGasResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(QueryBlockGasResponse) - err := c.cc.Invoke(ctx, Query_BlockGas_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Query_BlockGas_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -73,7 +78,9 @@ func (c *queryClient) BlockGas(ctx context.Context, in *QueryBlockGasRequest, op // QueryServer is the server API for Query service. // All implementations must embed UnimplementedQueryServer -// for forward compatibility +// for forward compatibility. +// +// Query defines the gRPC querier service. type QueryServer interface { // Params queries the parameters of x/feemarket module. Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) @@ -84,20 +91,24 @@ type QueryServer interface { mustEmbedUnimplementedQueryServer() } -// UnimplementedQueryServer must be embedded to have forward compatible implementations. -type UnimplementedQueryServer struct { -} +// UnimplementedQueryServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedQueryServer struct{} func (UnimplementedQueryServer) Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Params not implemented") + return nil, status.Error(codes.Unimplemented, "method Params not implemented") } func (UnimplementedQueryServer) BaseFee(context.Context, *QueryBaseFeeRequest) (*QueryBaseFeeResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method BaseFee not implemented") + return nil, status.Error(codes.Unimplemented, "method BaseFee not implemented") } func (UnimplementedQueryServer) BlockGas(context.Context, *QueryBlockGasRequest) (*QueryBlockGasResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method BlockGas not implemented") + return nil, status.Error(codes.Unimplemented, "method BlockGas not implemented") } func (UnimplementedQueryServer) mustEmbedUnimplementedQueryServer() {} +func (UnimplementedQueryServer) testEmbeddedByValue() {} // UnsafeQueryServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to QueryServer will @@ -107,6 +118,13 @@ type UnsafeQueryServer interface { } func RegisterQueryServer(s grpc.ServiceRegistrar, srv QueryServer) { + // If the following call panics, it indicates UnimplementedQueryServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } s.RegisterService(&Query_ServiceDesc, srv) } diff --git a/api/cosmos/evm/feemarket/v1/tx_grpc.pb.go b/api/cosmos/evm/feemarket/v1/tx_grpc.pb.go index c8dc66ad..85962719 100644 --- a/api/cosmos/evm/feemarket/v1/tx_grpc.pb.go +++ b/api/cosmos/evm/feemarket/v1/tx_grpc.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.3.0 +// - protoc-gen-go-grpc v1.6.0 // - protoc (unknown) // source: cosmos/evm/feemarket/v1/tx.proto @@ -15,8 +15,8 @@ import ( // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.32.0 or later. -const _ = grpc.SupportPackageIsVersion7 +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 const ( Msg_UpdateParams_FullMethodName = "/cosmos.evm.feemarket.v1.Msg/UpdateParams" @@ -25,6 +25,8 @@ const ( // MsgClient is the client API for Msg service. // // 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. +// +// Msg defines the feemarket Msg service. type MsgClient interface { // UpdateParams defined a governance operation for updating the x/feemarket // module parameters. The authority is hard-coded to the Cosmos SDK x/gov @@ -41,8 +43,9 @@ func NewMsgClient(cc grpc.ClientConnInterface) MsgClient { } func (c *msgClient) UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(MsgUpdateParamsResponse) - err := c.cc.Invoke(ctx, Msg_UpdateParams_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Msg_UpdateParams_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -51,7 +54,9 @@ func (c *msgClient) UpdateParams(ctx context.Context, in *MsgUpdateParams, opts // MsgServer is the server API for Msg service. // All implementations must embed UnimplementedMsgServer -// for forward compatibility +// for forward compatibility. +// +// Msg defines the feemarket Msg service. type MsgServer interface { // UpdateParams defined a governance operation for updating the x/feemarket // module parameters. The authority is hard-coded to the Cosmos SDK x/gov @@ -60,14 +65,18 @@ type MsgServer interface { mustEmbedUnimplementedMsgServer() } -// UnimplementedMsgServer must be embedded to have forward compatible implementations. -type UnimplementedMsgServer struct { -} +// UnimplementedMsgServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedMsgServer struct{} func (UnimplementedMsgServer) UpdateParams(context.Context, *MsgUpdateParams) (*MsgUpdateParamsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method UpdateParams not implemented") + return nil, status.Error(codes.Unimplemented, "method UpdateParams not implemented") } func (UnimplementedMsgServer) mustEmbedUnimplementedMsgServer() {} +func (UnimplementedMsgServer) testEmbeddedByValue() {} // UnsafeMsgServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to MsgServer will @@ -77,6 +86,13 @@ type UnsafeMsgServer interface { } func RegisterMsgServer(s grpc.ServiceRegistrar, srv MsgServer) { + // If the following call panics, it indicates UnimplementedMsgServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } s.RegisterService(&Msg_ServiceDesc, srv) } diff --git a/api/cosmos/evm/precisebank/v1/genesis.pulsar.go b/api/cosmos/evm/precisebank/v1/genesis.pulsar.go deleted file mode 100644 index ac1d34c5..00000000 --- a/api/cosmos/evm/precisebank/v1/genesis.pulsar.go +++ /dev/null @@ -1,1292 +0,0 @@ -// Code generated by protoc-gen-go-pulsar. DO NOT EDIT. -package precisebankv1 - -import ( - fmt "fmt" - _ "github.com/cosmos/cosmos-proto" - runtime "github.com/cosmos/cosmos-proto/runtime" - _ "github.com/cosmos/gogoproto/gogoproto" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoiface "google.golang.org/protobuf/runtime/protoiface" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - io "io" - reflect "reflect" - sync "sync" -) - -var _ protoreflect.List = (*_GenesisState_1_list)(nil) - -type _GenesisState_1_list struct { - list *[]*FractionalBalance -} - -func (x *_GenesisState_1_list) Len() int { - if x.list == nil { - return 0 - } - return len(*x.list) -} - -func (x *_GenesisState_1_list) Get(i int) protoreflect.Value { - return protoreflect.ValueOfMessage((*x.list)[i].ProtoReflect()) -} - -func (x *_GenesisState_1_list) Set(i int, value protoreflect.Value) { - valueUnwrapped := value.Message() - concreteValue := valueUnwrapped.Interface().(*FractionalBalance) - (*x.list)[i] = concreteValue -} - -func (x *_GenesisState_1_list) Append(value protoreflect.Value) { - valueUnwrapped := value.Message() - concreteValue := valueUnwrapped.Interface().(*FractionalBalance) - *x.list = append(*x.list, concreteValue) -} - -func (x *_GenesisState_1_list) AppendMutable() protoreflect.Value { - v := new(FractionalBalance) - *x.list = append(*x.list, v) - return protoreflect.ValueOfMessage(v.ProtoReflect()) -} - -func (x *_GenesisState_1_list) Truncate(n int) { - for i := n; i < len(*x.list); i++ { - (*x.list)[i] = nil - } - *x.list = (*x.list)[:n] -} - -func (x *_GenesisState_1_list) NewElement() protoreflect.Value { - v := new(FractionalBalance) - return protoreflect.ValueOfMessage(v.ProtoReflect()) -} - -func (x *_GenesisState_1_list) IsValid() bool { - return x.list != nil -} - -var ( - md_GenesisState protoreflect.MessageDescriptor - fd_GenesisState_balances protoreflect.FieldDescriptor - fd_GenesisState_remainder protoreflect.FieldDescriptor -) - -func init() { - file_cosmos_evm_precisebank_v1_genesis_proto_init() - md_GenesisState = File_cosmos_evm_precisebank_v1_genesis_proto.Messages().ByName("GenesisState") - fd_GenesisState_balances = md_GenesisState.Fields().ByName("balances") - fd_GenesisState_remainder = md_GenesisState.Fields().ByName("remainder") -} - -var _ protoreflect.Message = (*fastReflection_GenesisState)(nil) - -type fastReflection_GenesisState GenesisState - -func (x *GenesisState) ProtoReflect() protoreflect.Message { - return (*fastReflection_GenesisState)(x) -} - -func (x *GenesisState) slowProtoReflect() protoreflect.Message { - mi := &file_cosmos_evm_precisebank_v1_genesis_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -var _fastReflection_GenesisState_messageType fastReflection_GenesisState_messageType -var _ protoreflect.MessageType = fastReflection_GenesisState_messageType{} - -type fastReflection_GenesisState_messageType struct{} - -func (x fastReflection_GenesisState_messageType) Zero() protoreflect.Message { - return (*fastReflection_GenesisState)(nil) -} -func (x fastReflection_GenesisState_messageType) New() protoreflect.Message { - return new(fastReflection_GenesisState) -} -func (x fastReflection_GenesisState_messageType) Descriptor() protoreflect.MessageDescriptor { - return md_GenesisState -} - -// Descriptor returns message descriptor, which contains only the protobuf -// type information for the message. -func (x *fastReflection_GenesisState) Descriptor() protoreflect.MessageDescriptor { - return md_GenesisState -} - -// Type returns the message type, which encapsulates both Go and protobuf -// type information. If the Go type information is not needed, -// it is recommended that the message descriptor be used instead. -func (x *fastReflection_GenesisState) Type() protoreflect.MessageType { - return _fastReflection_GenesisState_messageType -} - -// New returns a newly allocated and mutable empty message. -func (x *fastReflection_GenesisState) New() protoreflect.Message { - return new(fastReflection_GenesisState) -} - -// Interface unwraps the message reflection interface and -// returns the underlying ProtoMessage interface. -func (x *fastReflection_GenesisState) Interface() protoreflect.ProtoMessage { - return (*GenesisState)(x) -} - -// Range iterates over every populated field in an undefined order, -// calling f for each field descriptor and value encountered. -// Range returns immediately if f returns false. -// While iterating, mutating operations may only be performed -// on the current field descriptor. -func (x *fastReflection_GenesisState) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { - if len(x.Balances) != 0 { - value := protoreflect.ValueOfList(&_GenesisState_1_list{list: &x.Balances}) - if !f(fd_GenesisState_balances, value) { - return - } - } - if x.Remainder != "" { - value := protoreflect.ValueOfString(x.Remainder) - if !f(fd_GenesisState_remainder, value) { - return - } - } -} - -// Has reports whether a field is populated. -// -// Some fields have the property of nullability where it is possible to -// distinguish between the default value of a field and whether the field -// was explicitly populated with the default value. Singular message fields, -// member fields of a oneof, and proto2 scalar fields are nullable. Such -// fields are populated only if explicitly set. -// -// In other cases (aside from the nullable cases above), -// a proto3 scalar field is populated if it contains a non-zero value, and -// a repeated field is populated if it is non-empty. -func (x *fastReflection_GenesisState) Has(fd protoreflect.FieldDescriptor) bool { - switch fd.FullName() { - case "cosmos.evm.precisebank.v1.GenesisState.balances": - return len(x.Balances) != 0 - case "cosmos.evm.precisebank.v1.GenesisState.remainder": - return x.Remainder != "" - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.GenesisState")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.GenesisState does not contain field %s", fd.FullName())) - } -} - -// Clear clears the field such that a subsequent Has call reports false. -// -// Clearing an extension field clears both the extension type and value -// associated with the given field number. -// -// Clear is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_GenesisState) Clear(fd protoreflect.FieldDescriptor) { - switch fd.FullName() { - case "cosmos.evm.precisebank.v1.GenesisState.balances": - x.Balances = nil - case "cosmos.evm.precisebank.v1.GenesisState.remainder": - x.Remainder = "" - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.GenesisState")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.GenesisState does not contain field %s", fd.FullName())) - } -} - -// Get retrieves the value for a field. -// -// For unpopulated scalars, it returns the default value, where -// the default value of a bytes scalar is guaranteed to be a copy. -// For unpopulated composite types, it returns an empty, read-only view -// of the value; to obtain a mutable reference, use Mutable. -func (x *fastReflection_GenesisState) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { - switch descriptor.FullName() { - case "cosmos.evm.precisebank.v1.GenesisState.balances": - if len(x.Balances) == 0 { - return protoreflect.ValueOfList(&_GenesisState_1_list{}) - } - listValue := &_GenesisState_1_list{list: &x.Balances} - return protoreflect.ValueOfList(listValue) - case "cosmos.evm.precisebank.v1.GenesisState.remainder": - value := x.Remainder - return protoreflect.ValueOfString(value) - default: - if descriptor.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.GenesisState")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.GenesisState does not contain field %s", descriptor.FullName())) - } -} - -// Set stores the value for a field. -// -// For a field belonging to a oneof, it implicitly clears any other field -// that may be currently set within the same oneof. -// For extension fields, it implicitly stores the provided ExtensionType. -// When setting a composite type, it is unspecified whether the stored value -// aliases the source's memory in any way. If the composite value is an -// empty, read-only value, then it panics. -// -// Set is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_GenesisState) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { - switch fd.FullName() { - case "cosmos.evm.precisebank.v1.GenesisState.balances": - lv := value.List() - clv := lv.(*_GenesisState_1_list) - x.Balances = *clv.list - case "cosmos.evm.precisebank.v1.GenesisState.remainder": - x.Remainder = value.Interface().(string) - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.GenesisState")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.GenesisState does not contain field %s", fd.FullName())) - } -} - -// Mutable returns a mutable reference to a composite type. -// -// If the field is unpopulated, it may allocate a composite value. -// For a field belonging to a oneof, it implicitly clears any other field -// that may be currently set within the same oneof. -// For extension fields, it implicitly stores the provided ExtensionType -// if not already stored. -// It panics if the field does not contain a composite type. -// -// Mutable is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_GenesisState) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { - switch fd.FullName() { - case "cosmos.evm.precisebank.v1.GenesisState.balances": - if x.Balances == nil { - x.Balances = []*FractionalBalance{} - } - value := &_GenesisState_1_list{list: &x.Balances} - return protoreflect.ValueOfList(value) - case "cosmos.evm.precisebank.v1.GenesisState.remainder": - panic(fmt.Errorf("field remainder of message cosmos.evm.precisebank.v1.GenesisState is not mutable")) - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.GenesisState")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.GenesisState does not contain field %s", fd.FullName())) - } -} - -// NewField returns a new value that is assignable to the field -// for the given descriptor. For scalars, this returns the default value. -// For lists, maps, and messages, this returns a new, empty, mutable value. -func (x *fastReflection_GenesisState) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { - switch fd.FullName() { - case "cosmos.evm.precisebank.v1.GenesisState.balances": - list := []*FractionalBalance{} - return protoreflect.ValueOfList(&_GenesisState_1_list{list: &list}) - case "cosmos.evm.precisebank.v1.GenesisState.remainder": - return protoreflect.ValueOfString("") - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.GenesisState")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.GenesisState does not contain field %s", fd.FullName())) - } -} - -// WhichOneof reports which field within the oneof is populated, -// returning nil if none are populated. -// It panics if the oneof descriptor does not belong to this message. -func (x *fastReflection_GenesisState) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { - switch d.FullName() { - default: - panic(fmt.Errorf("%s is not a oneof field in cosmos.evm.precisebank.v1.GenesisState", d.FullName())) - } - panic("unreachable") -} - -// GetUnknown retrieves the entire list of unknown fields. -// The caller may only mutate the contents of the RawFields -// if the mutated bytes are stored back into the message with SetUnknown. -func (x *fastReflection_GenesisState) GetUnknown() protoreflect.RawFields { - return x.unknownFields -} - -// SetUnknown stores an entire list of unknown fields. -// The raw fields must be syntactically valid according to the wire format. -// An implementation may panic if this is not the case. -// Once stored, the caller must not mutate the content of the RawFields. -// An empty RawFields may be passed to clear the fields. -// -// SetUnknown is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_GenesisState) SetUnknown(fields protoreflect.RawFields) { - x.unknownFields = fields -} - -// IsValid reports whether the message is valid. -// -// An invalid message is an empty, read-only value. -// -// An invalid message often corresponds to a nil pointer of the concrete -// message type, but the details are implementation dependent. -// Validity is not part of the protobuf data model, and may not -// be preserved in marshaling or other operations. -func (x *fastReflection_GenesisState) IsValid() bool { - return x != nil -} - -// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations. -// This method may return nil. -// -// The returned methods type is identical to -// "google.golang.org/protobuf/runtime/protoiface".Methods. -// Consult the protoiface package documentation for details. -func (x *fastReflection_GenesisState) ProtoMethods() *protoiface.Methods { - size := func(input protoiface.SizeInput) protoiface.SizeOutput { - x := input.Message.Interface().(*GenesisState) - if x == nil { - return protoiface.SizeOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Size: 0, - } - } - options := runtime.SizeInputToOptions(input) - _ = options - var n int - var l int - _ = l - if len(x.Balances) > 0 { - for _, e := range x.Balances { - l = options.Size(e) - n += 1 + l + runtime.Sov(uint64(l)) - } - } - l = len(x.Remainder) - if l > 0 { - n += 1 + l + runtime.Sov(uint64(l)) - } - if x.unknownFields != nil { - n += len(x.unknownFields) - } - return protoiface.SizeOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Size: n, - } - } - - marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { - x := input.Message.Interface().(*GenesisState) - if x == nil { - return protoiface.MarshalOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Buf: input.Buf, - }, nil - } - options := runtime.MarshalInputToOptions(input) - _ = options - size := options.Size(x) - dAtA := make([]byte, size) - i := len(dAtA) - _ = i - var l int - _ = l - if x.unknownFields != nil { - i -= len(x.unknownFields) - copy(dAtA[i:], x.unknownFields) - } - if len(x.Remainder) > 0 { - i -= len(x.Remainder) - copy(dAtA[i:], x.Remainder) - i = runtime.EncodeVarint(dAtA, i, uint64(len(x.Remainder))) - i-- - dAtA[i] = 0x12 - } - if len(x.Balances) > 0 { - for iNdEx := len(x.Balances) - 1; iNdEx >= 0; iNdEx-- { - encoded, err := options.Marshal(x.Balances[iNdEx]) - if err != nil { - return protoiface.MarshalOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Buf: input.Buf, - }, err - } - i -= len(encoded) - copy(dAtA[i:], encoded) - i = runtime.EncodeVarint(dAtA, i, uint64(len(encoded))) - i-- - dAtA[i] = 0xa - } - } - if input.Buf != nil { - input.Buf = append(input.Buf, dAtA...) - } else { - input.Buf = dAtA - } - return protoiface.MarshalOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Buf: input.Buf, - }, nil - } - unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { - x := input.Message.Interface().(*GenesisState) - if x == nil { - return protoiface.UnmarshalOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Flags: input.Flags, - }, nil - } - options := runtime.UnmarshalInputToOptions(input) - _ = options - dAtA := input.Buf - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - 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++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: GenesisState: wiretype end group for non-group") - } - if fieldNum <= 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Balances", wireType) - } - var msglen 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++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - postIndex := iNdEx + msglen - 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.Balances = append(x.Balances, &FractionalBalance{}) - if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.Balances[len(x.Balances)-1]); err != nil { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Remainder", wireType) - } - var stringLen uint64 - 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++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - postIndex := iNdEx + intStringLen - 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.Remainder = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := runtime.Skip(dAtA[iNdEx:]) - if err != nil { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - if (iNdEx + skippy) > l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - if !options.DiscardUnknown { - x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) - } - iNdEx += skippy - } - } - - if iNdEx > l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil - } - return &protoiface.Methods{ - NoUnkeyedLiterals: struct{}{}, - Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, - Size: size, - Marshal: marshal, - Unmarshal: unmarshal, - Merge: nil, - CheckInitialized: nil, - } -} - -var ( - md_FractionalBalance protoreflect.MessageDescriptor - fd_FractionalBalance_address protoreflect.FieldDescriptor - fd_FractionalBalance_amount protoreflect.FieldDescriptor -) - -func init() { - file_cosmos_evm_precisebank_v1_genesis_proto_init() - md_FractionalBalance = File_cosmos_evm_precisebank_v1_genesis_proto.Messages().ByName("FractionalBalance") - fd_FractionalBalance_address = md_FractionalBalance.Fields().ByName("address") - fd_FractionalBalance_amount = md_FractionalBalance.Fields().ByName("amount") -} - -var _ protoreflect.Message = (*fastReflection_FractionalBalance)(nil) - -type fastReflection_FractionalBalance FractionalBalance - -func (x *FractionalBalance) ProtoReflect() protoreflect.Message { - return (*fastReflection_FractionalBalance)(x) -} - -func (x *FractionalBalance) slowProtoReflect() protoreflect.Message { - mi := &file_cosmos_evm_precisebank_v1_genesis_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -var _fastReflection_FractionalBalance_messageType fastReflection_FractionalBalance_messageType -var _ protoreflect.MessageType = fastReflection_FractionalBalance_messageType{} - -type fastReflection_FractionalBalance_messageType struct{} - -func (x fastReflection_FractionalBalance_messageType) Zero() protoreflect.Message { - return (*fastReflection_FractionalBalance)(nil) -} -func (x fastReflection_FractionalBalance_messageType) New() protoreflect.Message { - return new(fastReflection_FractionalBalance) -} -func (x fastReflection_FractionalBalance_messageType) Descriptor() protoreflect.MessageDescriptor { - return md_FractionalBalance -} - -// Descriptor returns message descriptor, which contains only the protobuf -// type information for the message. -func (x *fastReflection_FractionalBalance) Descriptor() protoreflect.MessageDescriptor { - return md_FractionalBalance -} - -// Type returns the message type, which encapsulates both Go and protobuf -// type information. If the Go type information is not needed, -// it is recommended that the message descriptor be used instead. -func (x *fastReflection_FractionalBalance) Type() protoreflect.MessageType { - return _fastReflection_FractionalBalance_messageType -} - -// New returns a newly allocated and mutable empty message. -func (x *fastReflection_FractionalBalance) New() protoreflect.Message { - return new(fastReflection_FractionalBalance) -} - -// Interface unwraps the message reflection interface and -// returns the underlying ProtoMessage interface. -func (x *fastReflection_FractionalBalance) Interface() protoreflect.ProtoMessage { - return (*FractionalBalance)(x) -} - -// Range iterates over every populated field in an undefined order, -// calling f for each field descriptor and value encountered. -// Range returns immediately if f returns false. -// While iterating, mutating operations may only be performed -// on the current field descriptor. -func (x *fastReflection_FractionalBalance) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { - if x.Address != "" { - value := protoreflect.ValueOfString(x.Address) - if !f(fd_FractionalBalance_address, value) { - return - } - } - if x.Amount != "" { - value := protoreflect.ValueOfString(x.Amount) - if !f(fd_FractionalBalance_amount, value) { - return - } - } -} - -// Has reports whether a field is populated. -// -// Some fields have the property of nullability where it is possible to -// distinguish between the default value of a field and whether the field -// was explicitly populated with the default value. Singular message fields, -// member fields of a oneof, and proto2 scalar fields are nullable. Such -// fields are populated only if explicitly set. -// -// In other cases (aside from the nullable cases above), -// a proto3 scalar field is populated if it contains a non-zero value, and -// a repeated field is populated if it is non-empty. -func (x *fastReflection_FractionalBalance) Has(fd protoreflect.FieldDescriptor) bool { - switch fd.FullName() { - case "cosmos.evm.precisebank.v1.FractionalBalance.address": - return x.Address != "" - case "cosmos.evm.precisebank.v1.FractionalBalance.amount": - return x.Amount != "" - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.FractionalBalance")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.FractionalBalance does not contain field %s", fd.FullName())) - } -} - -// Clear clears the field such that a subsequent Has call reports false. -// -// Clearing an extension field clears both the extension type and value -// associated with the given field number. -// -// Clear is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_FractionalBalance) Clear(fd protoreflect.FieldDescriptor) { - switch fd.FullName() { - case "cosmos.evm.precisebank.v1.FractionalBalance.address": - x.Address = "" - case "cosmos.evm.precisebank.v1.FractionalBalance.amount": - x.Amount = "" - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.FractionalBalance")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.FractionalBalance does not contain field %s", fd.FullName())) - } -} - -// Get retrieves the value for a field. -// -// For unpopulated scalars, it returns the default value, where -// the default value of a bytes scalar is guaranteed to be a copy. -// For unpopulated composite types, it returns an empty, read-only view -// of the value; to obtain a mutable reference, use Mutable. -func (x *fastReflection_FractionalBalance) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { - switch descriptor.FullName() { - case "cosmos.evm.precisebank.v1.FractionalBalance.address": - value := x.Address - return protoreflect.ValueOfString(value) - case "cosmos.evm.precisebank.v1.FractionalBalance.amount": - value := x.Amount - return protoreflect.ValueOfString(value) - default: - if descriptor.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.FractionalBalance")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.FractionalBalance does not contain field %s", descriptor.FullName())) - } -} - -// Set stores the value for a field. -// -// For a field belonging to a oneof, it implicitly clears any other field -// that may be currently set within the same oneof. -// For extension fields, it implicitly stores the provided ExtensionType. -// When setting a composite type, it is unspecified whether the stored value -// aliases the source's memory in any way. If the composite value is an -// empty, read-only value, then it panics. -// -// Set is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_FractionalBalance) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { - switch fd.FullName() { - case "cosmos.evm.precisebank.v1.FractionalBalance.address": - x.Address = value.Interface().(string) - case "cosmos.evm.precisebank.v1.FractionalBalance.amount": - x.Amount = value.Interface().(string) - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.FractionalBalance")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.FractionalBalance does not contain field %s", fd.FullName())) - } -} - -// Mutable returns a mutable reference to a composite type. -// -// If the field is unpopulated, it may allocate a composite value. -// For a field belonging to a oneof, it implicitly clears any other field -// that may be currently set within the same oneof. -// For extension fields, it implicitly stores the provided ExtensionType -// if not already stored. -// It panics if the field does not contain a composite type. -// -// Mutable is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_FractionalBalance) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { - switch fd.FullName() { - case "cosmos.evm.precisebank.v1.FractionalBalance.address": - panic(fmt.Errorf("field address of message cosmos.evm.precisebank.v1.FractionalBalance is not mutable")) - case "cosmos.evm.precisebank.v1.FractionalBalance.amount": - panic(fmt.Errorf("field amount of message cosmos.evm.precisebank.v1.FractionalBalance is not mutable")) - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.FractionalBalance")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.FractionalBalance does not contain field %s", fd.FullName())) - } -} - -// NewField returns a new value that is assignable to the field -// for the given descriptor. For scalars, this returns the default value. -// For lists, maps, and messages, this returns a new, empty, mutable value. -func (x *fastReflection_FractionalBalance) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { - switch fd.FullName() { - case "cosmos.evm.precisebank.v1.FractionalBalance.address": - return protoreflect.ValueOfString("") - case "cosmos.evm.precisebank.v1.FractionalBalance.amount": - return protoreflect.ValueOfString("") - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.FractionalBalance")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.FractionalBalance does not contain field %s", fd.FullName())) - } -} - -// WhichOneof reports which field within the oneof is populated, -// returning nil if none are populated. -// It panics if the oneof descriptor does not belong to this message. -func (x *fastReflection_FractionalBalance) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { - switch d.FullName() { - default: - panic(fmt.Errorf("%s is not a oneof field in cosmos.evm.precisebank.v1.FractionalBalance", d.FullName())) - } - panic("unreachable") -} - -// GetUnknown retrieves the entire list of unknown fields. -// The caller may only mutate the contents of the RawFields -// if the mutated bytes are stored back into the message with SetUnknown. -func (x *fastReflection_FractionalBalance) GetUnknown() protoreflect.RawFields { - return x.unknownFields -} - -// SetUnknown stores an entire list of unknown fields. -// The raw fields must be syntactically valid according to the wire format. -// An implementation may panic if this is not the case. -// Once stored, the caller must not mutate the content of the RawFields. -// An empty RawFields may be passed to clear the fields. -// -// SetUnknown is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_FractionalBalance) SetUnknown(fields protoreflect.RawFields) { - x.unknownFields = fields -} - -// IsValid reports whether the message is valid. -// -// An invalid message is an empty, read-only value. -// -// An invalid message often corresponds to a nil pointer of the concrete -// message type, but the details are implementation dependent. -// Validity is not part of the protobuf data model, and may not -// be preserved in marshaling or other operations. -func (x *fastReflection_FractionalBalance) IsValid() bool { - return x != nil -} - -// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations. -// This method may return nil. -// -// The returned methods type is identical to -// "google.golang.org/protobuf/runtime/protoiface".Methods. -// Consult the protoiface package documentation for details. -func (x *fastReflection_FractionalBalance) ProtoMethods() *protoiface.Methods { - size := func(input protoiface.SizeInput) protoiface.SizeOutput { - x := input.Message.Interface().(*FractionalBalance) - if x == nil { - return protoiface.SizeOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Size: 0, - } - } - options := runtime.SizeInputToOptions(input) - _ = options - var n int - var l int - _ = l - l = len(x.Address) - if l > 0 { - n += 1 + l + runtime.Sov(uint64(l)) - } - l = len(x.Amount) - if l > 0 { - n += 1 + l + runtime.Sov(uint64(l)) - } - if x.unknownFields != nil { - n += len(x.unknownFields) - } - return protoiface.SizeOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Size: n, - } - } - - marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { - x := input.Message.Interface().(*FractionalBalance) - if x == nil { - return protoiface.MarshalOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Buf: input.Buf, - }, nil - } - options := runtime.MarshalInputToOptions(input) - _ = options - size := options.Size(x) - dAtA := make([]byte, size) - i := len(dAtA) - _ = i - var l int - _ = l - if x.unknownFields != nil { - i -= len(x.unknownFields) - copy(dAtA[i:], x.unknownFields) - } - if len(x.Amount) > 0 { - i -= len(x.Amount) - copy(dAtA[i:], x.Amount) - i = runtime.EncodeVarint(dAtA, i, uint64(len(x.Amount))) - i-- - dAtA[i] = 0x12 - } - if len(x.Address) > 0 { - i -= len(x.Address) - copy(dAtA[i:], x.Address) - i = runtime.EncodeVarint(dAtA, i, uint64(len(x.Address))) - i-- - dAtA[i] = 0xa - } - if input.Buf != nil { - input.Buf = append(input.Buf, dAtA...) - } else { - input.Buf = dAtA - } - return protoiface.MarshalOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Buf: input.Buf, - }, nil - } - unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { - x := input.Message.Interface().(*FractionalBalance) - if x == nil { - return protoiface.UnmarshalOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Flags: input.Flags, - }, nil - } - options := runtime.UnmarshalInputToOptions(input) - _ = options - dAtA := input.Buf - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - 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++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: FractionalBalance: wiretype end group for non-group") - } - if fieldNum <= 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: FractionalBalance: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) - } - var stringLen uint64 - 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++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - postIndex := iNdEx + intStringLen - 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.Address = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) - } - var stringLen uint64 - 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++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - postIndex := iNdEx + intStringLen - 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.Amount = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := runtime.Skip(dAtA[iNdEx:]) - if err != nil { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - if (iNdEx + skippy) > l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - if !options.DiscardUnknown { - x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) - } - iNdEx += skippy - } - } - - if iNdEx > l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil - } - return &protoiface.Methods{ - NoUnkeyedLiterals: struct{}{}, - Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, - Size: size, - Marshal: marshal, - Unmarshal: unmarshal, - Merge: nil, - CheckInitialized: nil, - } -} - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.27.0 -// protoc (unknown) -// source: cosmos/evm/precisebank/v1/genesis.proto - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// GenesisState defines the precisebank module's genesis state. -type GenesisState struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // balances is a list of all the balances in the precisebank module. - Balances []*FractionalBalance `protobuf:"bytes,1,rep,name=balances,proto3" json:"balances,omitempty"` - // remainder is an internal value of how much extra fractional digits are - // still backed by the reserve, but not assigned to any account. - Remainder string `protobuf:"bytes,2,opt,name=remainder,proto3" json:"remainder,omitempty"` -} - -func (x *GenesisState) Reset() { - *x = GenesisState{} - if protoimpl.UnsafeEnabled { - mi := &file_cosmos_evm_precisebank_v1_genesis_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GenesisState) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GenesisState) ProtoMessage() {} - -// Deprecated: Use GenesisState.ProtoReflect.Descriptor instead. -func (*GenesisState) Descriptor() ([]byte, []int) { - return file_cosmos_evm_precisebank_v1_genesis_proto_rawDescGZIP(), []int{0} -} - -func (x *GenesisState) GetBalances() []*FractionalBalance { - if x != nil { - return x.Balances - } - return nil -} - -func (x *GenesisState) GetRemainder() string { - if x != nil { - return x.Remainder - } - return "" -} - -// FractionalBalance defines the fractional portion of an account balance -type FractionalBalance struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // address is the address of the balance holder. - Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` - // amount indicates amount of only the fractional balance owned by the - // address. FractionalBalance currently only supports tracking 1 single asset, - // e.g. fractional balances of uatom. - Amount string `protobuf:"bytes,2,opt,name=amount,proto3" json:"amount,omitempty"` -} - -func (x *FractionalBalance) Reset() { - *x = FractionalBalance{} - if protoimpl.UnsafeEnabled { - mi := &file_cosmos_evm_precisebank_v1_genesis_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FractionalBalance) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FractionalBalance) ProtoMessage() {} - -// Deprecated: Use FractionalBalance.ProtoReflect.Descriptor instead. -func (*FractionalBalance) Descriptor() ([]byte, []int) { - return file_cosmos_evm_precisebank_v1_genesis_proto_rawDescGZIP(), []int{1} -} - -func (x *FractionalBalance) GetAddress() string { - if x != nil { - return x.Address - } - return "" -} - -func (x *FractionalBalance) GetAmount() string { - if x != nil { - return x.Amount - } - return "" -} - -var File_cosmos_evm_precisebank_v1_genesis_proto protoreflect.FileDescriptor - -var file_cosmos_evm_precisebank_v1_genesis_proto_rawDesc = []byte{ - 0x0a, 0x27, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x65, 0x76, 0x6d, 0x2f, 0x70, 0x72, 0x65, - 0x63, 0x69, 0x73, 0x65, 0x62, 0x61, 0x6e, 0x6b, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x6e, 0x65, - 0x73, 0x69, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x19, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x65, 0x62, 0x61, 0x6e, - 0x6b, 0x2e, 0x76, 0x31, 0x1a, 0x19, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 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, 0xbf, 0x01, 0x0a, 0x0c, 0x47, 0x65, 0x6e, 0x65, 0x73, 0x69, - 0x73, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x64, 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, - 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x65, 0x62, 0x61, 0x6e, - 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x42, - 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x42, 0x1a, 0xc8, 0xde, 0x1f, 0x00, 0xaa, 0xdf, 0x1f, 0x12, - 0x46, 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, - 0x65, 0x73, 0x52, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x49, 0x0a, 0x09, - 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x2b, 0xc8, 0xde, 0x1f, 0x00, 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, 0xd2, 0xb4, - 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x52, 0x09, 0x72, 0x65, - 0x6d, 0x61, 0x69, 0x6e, 0x64, 0x65, 0x72, 0x22, 0x96, 0x01, 0x0a, 0x11, 0x46, 0x72, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x32, 0x0a, - 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 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, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x12, 0x43, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x2b, 0xc8, 0xde, 0x1f, 0x00, 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, - 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x52, 0x06, - 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x3a, 0x08, 0x88, 0xa0, 0x1f, 0x00, 0xe8, 0xa0, 0x1f, 0x00, - 0x42, 0xee, 0x01, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, - 0x65, 0x76, 0x6d, 0x2e, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x65, 0x62, 0x61, 0x6e, 0x6b, 0x2e, - 0x76, 0x31, 0x42, 0x0c, 0x47, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x50, 0x01, 0x5a, 0x38, 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, - 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x65, 0x62, 0x61, 0x6e, 0x6b, 0x2f, 0x76, 0x31, 0x3b, 0x70, - 0x72, 0x65, 0x63, 0x69, 0x73, 0x65, 0x62, 0x61, 0x6e, 0x6b, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x43, - 0x45, 0x50, 0xaa, 0x02, 0x19, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x45, 0x76, 0x6d, 0x2e, - 0x50, 0x72, 0x65, 0x63, 0x69, 0x73, 0x65, 0x62, 0x61, 0x6e, 0x6b, 0x2e, 0x56, 0x31, 0xca, 0x02, - 0x19, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x45, 0x76, 0x6d, 0x5c, 0x50, 0x72, 0x65, 0x63, - 0x69, 0x73, 0x65, 0x62, 0x61, 0x6e, 0x6b, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x25, 0x43, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x5c, 0x45, 0x76, 0x6d, 0x5c, 0x50, 0x72, 0x65, 0x63, 0x69, 0x73, 0x65, 0x62, - 0x61, 0x6e, 0x6b, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0xea, 0x02, 0x1c, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x45, 0x76, 0x6d, - 0x3a, 0x3a, 0x50, 0x72, 0x65, 0x63, 0x69, 0x73, 0x65, 0x62, 0x61, 0x6e, 0x6b, 0x3a, 0x3a, 0x56, - 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_cosmos_evm_precisebank_v1_genesis_proto_rawDescOnce sync.Once - file_cosmos_evm_precisebank_v1_genesis_proto_rawDescData = file_cosmos_evm_precisebank_v1_genesis_proto_rawDesc -) - -func file_cosmos_evm_precisebank_v1_genesis_proto_rawDescGZIP() []byte { - file_cosmos_evm_precisebank_v1_genesis_proto_rawDescOnce.Do(func() { - file_cosmos_evm_precisebank_v1_genesis_proto_rawDescData = protoimpl.X.CompressGZIP(file_cosmos_evm_precisebank_v1_genesis_proto_rawDescData) - }) - return file_cosmos_evm_precisebank_v1_genesis_proto_rawDescData -} - -var file_cosmos_evm_precisebank_v1_genesis_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_cosmos_evm_precisebank_v1_genesis_proto_goTypes = []interface{}{ - (*GenesisState)(nil), // 0: cosmos.evm.precisebank.v1.GenesisState - (*FractionalBalance)(nil), // 1: cosmos.evm.precisebank.v1.FractionalBalance -} -var file_cosmos_evm_precisebank_v1_genesis_proto_depIdxs = []int32{ - 1, // 0: cosmos.evm.precisebank.v1.GenesisState.balances:type_name -> cosmos.evm.precisebank.v1.FractionalBalance - 1, // [1:1] is the sub-list for method output_type - 1, // [1:1] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name -} - -func init() { file_cosmos_evm_precisebank_v1_genesis_proto_init() } -func file_cosmos_evm_precisebank_v1_genesis_proto_init() { - if File_cosmos_evm_precisebank_v1_genesis_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_cosmos_evm_precisebank_v1_genesis_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GenesisState); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_cosmos_evm_precisebank_v1_genesis_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FractionalBalance); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_cosmos_evm_precisebank_v1_genesis_proto_rawDesc, - NumEnums: 0, - NumMessages: 2, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_cosmos_evm_precisebank_v1_genesis_proto_goTypes, - DependencyIndexes: file_cosmos_evm_precisebank_v1_genesis_proto_depIdxs, - MessageInfos: file_cosmos_evm_precisebank_v1_genesis_proto_msgTypes, - }.Build() - File_cosmos_evm_precisebank_v1_genesis_proto = out.File - file_cosmos_evm_precisebank_v1_genesis_proto_rawDesc = nil - file_cosmos_evm_precisebank_v1_genesis_proto_goTypes = nil - file_cosmos_evm_precisebank_v1_genesis_proto_depIdxs = nil -} diff --git a/api/cosmos/evm/precisebank/v1/query.pulsar.go b/api/cosmos/evm/precisebank/v1/query.pulsar.go deleted file mode 100644 index df42cde1..00000000 --- a/api/cosmos/evm/precisebank/v1/query.pulsar.go +++ /dev/null @@ -1,1997 +0,0 @@ -// Code generated by protoc-gen-go-pulsar. DO NOT EDIT. -package precisebankv1 - -import ( - v1beta1 "cosmossdk.io/api/cosmos/base/v1beta1" - fmt "fmt" - runtime "github.com/cosmos/cosmos-proto/runtime" - _ "github.com/cosmos/gogoproto/gogoproto" - _ "google.golang.org/genproto/googleapis/api/annotations" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoiface "google.golang.org/protobuf/runtime/protoiface" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - io "io" - reflect "reflect" - sync "sync" -) - -var ( - md_QueryRemainderRequest protoreflect.MessageDescriptor -) - -func init() { - file_cosmos_evm_precisebank_v1_query_proto_init() - md_QueryRemainderRequest = File_cosmos_evm_precisebank_v1_query_proto.Messages().ByName("QueryRemainderRequest") -} - -var _ protoreflect.Message = (*fastReflection_QueryRemainderRequest)(nil) - -type fastReflection_QueryRemainderRequest QueryRemainderRequest - -func (x *QueryRemainderRequest) ProtoReflect() protoreflect.Message { - return (*fastReflection_QueryRemainderRequest)(x) -} - -func (x *QueryRemainderRequest) slowProtoReflect() protoreflect.Message { - mi := &file_cosmos_evm_precisebank_v1_query_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -var _fastReflection_QueryRemainderRequest_messageType fastReflection_QueryRemainderRequest_messageType -var _ protoreflect.MessageType = fastReflection_QueryRemainderRequest_messageType{} - -type fastReflection_QueryRemainderRequest_messageType struct{} - -func (x fastReflection_QueryRemainderRequest_messageType) Zero() protoreflect.Message { - return (*fastReflection_QueryRemainderRequest)(nil) -} -func (x fastReflection_QueryRemainderRequest_messageType) New() protoreflect.Message { - return new(fastReflection_QueryRemainderRequest) -} -func (x fastReflection_QueryRemainderRequest_messageType) Descriptor() protoreflect.MessageDescriptor { - return md_QueryRemainderRequest -} - -// Descriptor returns message descriptor, which contains only the protobuf -// type information for the message. -func (x *fastReflection_QueryRemainderRequest) Descriptor() protoreflect.MessageDescriptor { - return md_QueryRemainderRequest -} - -// Type returns the message type, which encapsulates both Go and protobuf -// type information. If the Go type information is not needed, -// it is recommended that the message descriptor be used instead. -func (x *fastReflection_QueryRemainderRequest) Type() protoreflect.MessageType { - return _fastReflection_QueryRemainderRequest_messageType -} - -// New returns a newly allocated and mutable empty message. -func (x *fastReflection_QueryRemainderRequest) New() protoreflect.Message { - return new(fastReflection_QueryRemainderRequest) -} - -// Interface unwraps the message reflection interface and -// returns the underlying ProtoMessage interface. -func (x *fastReflection_QueryRemainderRequest) Interface() protoreflect.ProtoMessage { - return (*QueryRemainderRequest)(x) -} - -// Range iterates over every populated field in an undefined order, -// calling f for each field descriptor and value encountered. -// Range returns immediately if f returns false. -// While iterating, mutating operations may only be performed -// on the current field descriptor. -func (x *fastReflection_QueryRemainderRequest) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { -} - -// Has reports whether a field is populated. -// -// Some fields have the property of nullability where it is possible to -// distinguish between the default value of a field and whether the field -// was explicitly populated with the default value. Singular message fields, -// member fields of a oneof, and proto2 scalar fields are nullable. Such -// fields are populated only if explicitly set. -// -// In other cases (aside from the nullable cases above), -// a proto3 scalar field is populated if it contains a non-zero value, and -// a repeated field is populated if it is non-empty. -func (x *fastReflection_QueryRemainderRequest) Has(fd protoreflect.FieldDescriptor) bool { - switch fd.FullName() { - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.QueryRemainderRequest")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.QueryRemainderRequest does not contain field %s", fd.FullName())) - } -} - -// Clear clears the field such that a subsequent Has call reports false. -// -// Clearing an extension field clears both the extension type and value -// associated with the given field number. -// -// Clear is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_QueryRemainderRequest) Clear(fd protoreflect.FieldDescriptor) { - switch fd.FullName() { - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.QueryRemainderRequest")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.QueryRemainderRequest does not contain field %s", fd.FullName())) - } -} - -// Get retrieves the value for a field. -// -// For unpopulated scalars, it returns the default value, where -// the default value of a bytes scalar is guaranteed to be a copy. -// For unpopulated composite types, it returns an empty, read-only view -// of the value; to obtain a mutable reference, use Mutable. -func (x *fastReflection_QueryRemainderRequest) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { - switch descriptor.FullName() { - default: - if descriptor.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.QueryRemainderRequest")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.QueryRemainderRequest does not contain field %s", descriptor.FullName())) - } -} - -// Set stores the value for a field. -// -// For a field belonging to a oneof, it implicitly clears any other field -// that may be currently set within the same oneof. -// For extension fields, it implicitly stores the provided ExtensionType. -// When setting a composite type, it is unspecified whether the stored value -// aliases the source's memory in any way. If the composite value is an -// empty, read-only value, then it panics. -// -// Set is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_QueryRemainderRequest) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { - switch fd.FullName() { - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.QueryRemainderRequest")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.QueryRemainderRequest does not contain field %s", fd.FullName())) - } -} - -// Mutable returns a mutable reference to a composite type. -// -// If the field is unpopulated, it may allocate a composite value. -// For a field belonging to a oneof, it implicitly clears any other field -// that may be currently set within the same oneof. -// For extension fields, it implicitly stores the provided ExtensionType -// if not already stored. -// It panics if the field does not contain a composite type. -// -// Mutable is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_QueryRemainderRequest) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { - switch fd.FullName() { - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.QueryRemainderRequest")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.QueryRemainderRequest does not contain field %s", fd.FullName())) - } -} - -// NewField returns a new value that is assignable to the field -// for the given descriptor. For scalars, this returns the default value. -// For lists, maps, and messages, this returns a new, empty, mutable value. -func (x *fastReflection_QueryRemainderRequest) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { - switch fd.FullName() { - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.QueryRemainderRequest")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.QueryRemainderRequest does not contain field %s", fd.FullName())) - } -} - -// WhichOneof reports which field within the oneof is populated, -// returning nil if none are populated. -// It panics if the oneof descriptor does not belong to this message. -func (x *fastReflection_QueryRemainderRequest) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { - switch d.FullName() { - default: - panic(fmt.Errorf("%s is not a oneof field in cosmos.evm.precisebank.v1.QueryRemainderRequest", d.FullName())) - } - panic("unreachable") -} - -// GetUnknown retrieves the entire list of unknown fields. -// The caller may only mutate the contents of the RawFields -// if the mutated bytes are stored back into the message with SetUnknown. -func (x *fastReflection_QueryRemainderRequest) GetUnknown() protoreflect.RawFields { - return x.unknownFields -} - -// SetUnknown stores an entire list of unknown fields. -// The raw fields must be syntactically valid according to the wire format. -// An implementation may panic if this is not the case. -// Once stored, the caller must not mutate the content of the RawFields. -// An empty RawFields may be passed to clear the fields. -// -// SetUnknown is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_QueryRemainderRequest) SetUnknown(fields protoreflect.RawFields) { - x.unknownFields = fields -} - -// IsValid reports whether the message is valid. -// -// An invalid message is an empty, read-only value. -// -// An invalid message often corresponds to a nil pointer of the concrete -// message type, but the details are implementation dependent. -// Validity is not part of the protobuf data model, and may not -// be preserved in marshaling or other operations. -func (x *fastReflection_QueryRemainderRequest) IsValid() bool { - return x != nil -} - -// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations. -// This method may return nil. -// -// The returned methods type is identical to -// "google.golang.org/protobuf/runtime/protoiface".Methods. -// Consult the protoiface package documentation for details. -func (x *fastReflection_QueryRemainderRequest) ProtoMethods() *protoiface.Methods { - size := func(input protoiface.SizeInput) protoiface.SizeOutput { - x := input.Message.Interface().(*QueryRemainderRequest) - if x == nil { - return protoiface.SizeOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Size: 0, - } - } - options := runtime.SizeInputToOptions(input) - _ = options - var n int - var l int - _ = l - if x.unknownFields != nil { - n += len(x.unknownFields) - } - return protoiface.SizeOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Size: n, - } - } - - marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { - x := input.Message.Interface().(*QueryRemainderRequest) - if x == nil { - return protoiface.MarshalOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Buf: input.Buf, - }, nil - } - options := runtime.MarshalInputToOptions(input) - _ = options - size := options.Size(x) - dAtA := make([]byte, size) - i := len(dAtA) - _ = i - var l int - _ = l - if x.unknownFields != nil { - i -= len(x.unknownFields) - copy(dAtA[i:], x.unknownFields) - } - if input.Buf != nil { - input.Buf = append(input.Buf, dAtA...) - } else { - input.Buf = dAtA - } - return protoiface.MarshalOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Buf: input.Buf, - }, nil - } - unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { - x := input.Message.Interface().(*QueryRemainderRequest) - if x == nil { - return protoiface.UnmarshalOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Flags: input.Flags, - }, nil - } - options := runtime.UnmarshalInputToOptions(input) - _ = options - dAtA := input.Buf - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - 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++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryRemainderRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryRemainderRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - default: - iNdEx = preIndex - skippy, err := runtime.Skip(dAtA[iNdEx:]) - if err != nil { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - if (iNdEx + skippy) > l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - if !options.DiscardUnknown { - x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) - } - iNdEx += skippy - } - } - - if iNdEx > l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil - } - return &protoiface.Methods{ - NoUnkeyedLiterals: struct{}{}, - Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, - Size: size, - Marshal: marshal, - Unmarshal: unmarshal, - Merge: nil, - CheckInitialized: nil, - } -} - -var ( - md_QueryRemainderResponse protoreflect.MessageDescriptor - fd_QueryRemainderResponse_remainder protoreflect.FieldDescriptor -) - -func init() { - file_cosmos_evm_precisebank_v1_query_proto_init() - md_QueryRemainderResponse = File_cosmos_evm_precisebank_v1_query_proto.Messages().ByName("QueryRemainderResponse") - fd_QueryRemainderResponse_remainder = md_QueryRemainderResponse.Fields().ByName("remainder") -} - -var _ protoreflect.Message = (*fastReflection_QueryRemainderResponse)(nil) - -type fastReflection_QueryRemainderResponse QueryRemainderResponse - -func (x *QueryRemainderResponse) ProtoReflect() protoreflect.Message { - return (*fastReflection_QueryRemainderResponse)(x) -} - -func (x *QueryRemainderResponse) slowProtoReflect() protoreflect.Message { - mi := &file_cosmos_evm_precisebank_v1_query_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -var _fastReflection_QueryRemainderResponse_messageType fastReflection_QueryRemainderResponse_messageType -var _ protoreflect.MessageType = fastReflection_QueryRemainderResponse_messageType{} - -type fastReflection_QueryRemainderResponse_messageType struct{} - -func (x fastReflection_QueryRemainderResponse_messageType) Zero() protoreflect.Message { - return (*fastReflection_QueryRemainderResponse)(nil) -} -func (x fastReflection_QueryRemainderResponse_messageType) New() protoreflect.Message { - return new(fastReflection_QueryRemainderResponse) -} -func (x fastReflection_QueryRemainderResponse_messageType) Descriptor() protoreflect.MessageDescriptor { - return md_QueryRemainderResponse -} - -// Descriptor returns message descriptor, which contains only the protobuf -// type information for the message. -func (x *fastReflection_QueryRemainderResponse) Descriptor() protoreflect.MessageDescriptor { - return md_QueryRemainderResponse -} - -// Type returns the message type, which encapsulates both Go and protobuf -// type information. If the Go type information is not needed, -// it is recommended that the message descriptor be used instead. -func (x *fastReflection_QueryRemainderResponse) Type() protoreflect.MessageType { - return _fastReflection_QueryRemainderResponse_messageType -} - -// New returns a newly allocated and mutable empty message. -func (x *fastReflection_QueryRemainderResponse) New() protoreflect.Message { - return new(fastReflection_QueryRemainderResponse) -} - -// Interface unwraps the message reflection interface and -// returns the underlying ProtoMessage interface. -func (x *fastReflection_QueryRemainderResponse) Interface() protoreflect.ProtoMessage { - return (*QueryRemainderResponse)(x) -} - -// Range iterates over every populated field in an undefined order, -// calling f for each field descriptor and value encountered. -// Range returns immediately if f returns false. -// While iterating, mutating operations may only be performed -// on the current field descriptor. -func (x *fastReflection_QueryRemainderResponse) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { - if x.Remainder != nil { - value := protoreflect.ValueOfMessage(x.Remainder.ProtoReflect()) - if !f(fd_QueryRemainderResponse_remainder, value) { - return - } - } -} - -// Has reports whether a field is populated. -// -// Some fields have the property of nullability where it is possible to -// distinguish between the default value of a field and whether the field -// was explicitly populated with the default value. Singular message fields, -// member fields of a oneof, and proto2 scalar fields are nullable. Such -// fields are populated only if explicitly set. -// -// In other cases (aside from the nullable cases above), -// a proto3 scalar field is populated if it contains a non-zero value, and -// a repeated field is populated if it is non-empty. -func (x *fastReflection_QueryRemainderResponse) Has(fd protoreflect.FieldDescriptor) bool { - switch fd.FullName() { - case "cosmos.evm.precisebank.v1.QueryRemainderResponse.remainder": - return x.Remainder != nil - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.QueryRemainderResponse")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.QueryRemainderResponse does not contain field %s", fd.FullName())) - } -} - -// Clear clears the field such that a subsequent Has call reports false. -// -// Clearing an extension field clears both the extension type and value -// associated with the given field number. -// -// Clear is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_QueryRemainderResponse) Clear(fd protoreflect.FieldDescriptor) { - switch fd.FullName() { - case "cosmos.evm.precisebank.v1.QueryRemainderResponse.remainder": - x.Remainder = nil - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.QueryRemainderResponse")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.QueryRemainderResponse does not contain field %s", fd.FullName())) - } -} - -// Get retrieves the value for a field. -// -// For unpopulated scalars, it returns the default value, where -// the default value of a bytes scalar is guaranteed to be a copy. -// For unpopulated composite types, it returns an empty, read-only view -// of the value; to obtain a mutable reference, use Mutable. -func (x *fastReflection_QueryRemainderResponse) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { - switch descriptor.FullName() { - case "cosmos.evm.precisebank.v1.QueryRemainderResponse.remainder": - value := x.Remainder - return protoreflect.ValueOfMessage(value.ProtoReflect()) - default: - if descriptor.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.QueryRemainderResponse")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.QueryRemainderResponse does not contain field %s", descriptor.FullName())) - } -} - -// Set stores the value for a field. -// -// For a field belonging to a oneof, it implicitly clears any other field -// that may be currently set within the same oneof. -// For extension fields, it implicitly stores the provided ExtensionType. -// When setting a composite type, it is unspecified whether the stored value -// aliases the source's memory in any way. If the composite value is an -// empty, read-only value, then it panics. -// -// Set is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_QueryRemainderResponse) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { - switch fd.FullName() { - case "cosmos.evm.precisebank.v1.QueryRemainderResponse.remainder": - x.Remainder = value.Message().Interface().(*v1beta1.Coin) - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.QueryRemainderResponse")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.QueryRemainderResponse does not contain field %s", fd.FullName())) - } -} - -// Mutable returns a mutable reference to a composite type. -// -// If the field is unpopulated, it may allocate a composite value. -// For a field belonging to a oneof, it implicitly clears any other field -// that may be currently set within the same oneof. -// For extension fields, it implicitly stores the provided ExtensionType -// if not already stored. -// It panics if the field does not contain a composite type. -// -// Mutable is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_QueryRemainderResponse) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { - switch fd.FullName() { - case "cosmos.evm.precisebank.v1.QueryRemainderResponse.remainder": - if x.Remainder == nil { - x.Remainder = new(v1beta1.Coin) - } - return protoreflect.ValueOfMessage(x.Remainder.ProtoReflect()) - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.QueryRemainderResponse")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.QueryRemainderResponse does not contain field %s", fd.FullName())) - } -} - -// NewField returns a new value that is assignable to the field -// for the given descriptor. For scalars, this returns the default value. -// For lists, maps, and messages, this returns a new, empty, mutable value. -func (x *fastReflection_QueryRemainderResponse) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { - switch fd.FullName() { - case "cosmos.evm.precisebank.v1.QueryRemainderResponse.remainder": - m := new(v1beta1.Coin) - return protoreflect.ValueOfMessage(m.ProtoReflect()) - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.QueryRemainderResponse")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.QueryRemainderResponse does not contain field %s", fd.FullName())) - } -} - -// WhichOneof reports which field within the oneof is populated, -// returning nil if none are populated. -// It panics if the oneof descriptor does not belong to this message. -func (x *fastReflection_QueryRemainderResponse) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { - switch d.FullName() { - default: - panic(fmt.Errorf("%s is not a oneof field in cosmos.evm.precisebank.v1.QueryRemainderResponse", d.FullName())) - } - panic("unreachable") -} - -// GetUnknown retrieves the entire list of unknown fields. -// The caller may only mutate the contents of the RawFields -// if the mutated bytes are stored back into the message with SetUnknown. -func (x *fastReflection_QueryRemainderResponse) GetUnknown() protoreflect.RawFields { - return x.unknownFields -} - -// SetUnknown stores an entire list of unknown fields. -// The raw fields must be syntactically valid according to the wire format. -// An implementation may panic if this is not the case. -// Once stored, the caller must not mutate the content of the RawFields. -// An empty RawFields may be passed to clear the fields. -// -// SetUnknown is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_QueryRemainderResponse) SetUnknown(fields protoreflect.RawFields) { - x.unknownFields = fields -} - -// IsValid reports whether the message is valid. -// -// An invalid message is an empty, read-only value. -// -// An invalid message often corresponds to a nil pointer of the concrete -// message type, but the details are implementation dependent. -// Validity is not part of the protobuf data model, and may not -// be preserved in marshaling or other operations. -func (x *fastReflection_QueryRemainderResponse) IsValid() bool { - return x != nil -} - -// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations. -// This method may return nil. -// -// The returned methods type is identical to -// "google.golang.org/protobuf/runtime/protoiface".Methods. -// Consult the protoiface package documentation for details. -func (x *fastReflection_QueryRemainderResponse) ProtoMethods() *protoiface.Methods { - size := func(input protoiface.SizeInput) protoiface.SizeOutput { - x := input.Message.Interface().(*QueryRemainderResponse) - if x == nil { - return protoiface.SizeOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Size: 0, - } - } - options := runtime.SizeInputToOptions(input) - _ = options - var n int - var l int - _ = l - if x.Remainder != nil { - l = options.Size(x.Remainder) - n += 1 + l + runtime.Sov(uint64(l)) - } - if x.unknownFields != nil { - n += len(x.unknownFields) - } - return protoiface.SizeOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Size: n, - } - } - - marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { - x := input.Message.Interface().(*QueryRemainderResponse) - if x == nil { - return protoiface.MarshalOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Buf: input.Buf, - }, nil - } - options := runtime.MarshalInputToOptions(input) - _ = options - size := options.Size(x) - dAtA := make([]byte, size) - i := len(dAtA) - _ = i - var l int - _ = l - if x.unknownFields != nil { - i -= len(x.unknownFields) - copy(dAtA[i:], x.unknownFields) - } - if x.Remainder != nil { - encoded, err := options.Marshal(x.Remainder) - if err != nil { - return protoiface.MarshalOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Buf: input.Buf, - }, err - } - i -= len(encoded) - copy(dAtA[i:], encoded) - i = runtime.EncodeVarint(dAtA, i, uint64(len(encoded))) - i-- - dAtA[i] = 0xa - } - if input.Buf != nil { - input.Buf = append(input.Buf, dAtA...) - } else { - input.Buf = dAtA - } - return protoiface.MarshalOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Buf: input.Buf, - }, nil - } - unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { - x := input.Message.Interface().(*QueryRemainderResponse) - if x == nil { - return protoiface.UnmarshalOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Flags: input.Flags, - }, nil - } - options := runtime.UnmarshalInputToOptions(input) - _ = options - dAtA := input.Buf - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - 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++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryRemainderResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryRemainderResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Remainder", wireType) - } - var msglen 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++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - postIndex := iNdEx + msglen - 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 - } - if x.Remainder == nil { - x.Remainder = &v1beta1.Coin{} - } - if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.Remainder); err != nil { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := runtime.Skip(dAtA[iNdEx:]) - if err != nil { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - if (iNdEx + skippy) > l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - if !options.DiscardUnknown { - x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) - } - iNdEx += skippy - } - } - - if iNdEx > l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil - } - return &protoiface.Methods{ - NoUnkeyedLiterals: struct{}{}, - Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, - Size: size, - Marshal: marshal, - Unmarshal: unmarshal, - Merge: nil, - CheckInitialized: nil, - } -} - -var ( - md_QueryFractionalBalanceRequest protoreflect.MessageDescriptor - fd_QueryFractionalBalanceRequest_address protoreflect.FieldDescriptor -) - -func init() { - file_cosmos_evm_precisebank_v1_query_proto_init() - md_QueryFractionalBalanceRequest = File_cosmos_evm_precisebank_v1_query_proto.Messages().ByName("QueryFractionalBalanceRequest") - fd_QueryFractionalBalanceRequest_address = md_QueryFractionalBalanceRequest.Fields().ByName("address") -} - -var _ protoreflect.Message = (*fastReflection_QueryFractionalBalanceRequest)(nil) - -type fastReflection_QueryFractionalBalanceRequest QueryFractionalBalanceRequest - -func (x *QueryFractionalBalanceRequest) ProtoReflect() protoreflect.Message { - return (*fastReflection_QueryFractionalBalanceRequest)(x) -} - -func (x *QueryFractionalBalanceRequest) slowProtoReflect() protoreflect.Message { - mi := &file_cosmos_evm_precisebank_v1_query_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -var _fastReflection_QueryFractionalBalanceRequest_messageType fastReflection_QueryFractionalBalanceRequest_messageType -var _ protoreflect.MessageType = fastReflection_QueryFractionalBalanceRequest_messageType{} - -type fastReflection_QueryFractionalBalanceRequest_messageType struct{} - -func (x fastReflection_QueryFractionalBalanceRequest_messageType) Zero() protoreflect.Message { - return (*fastReflection_QueryFractionalBalanceRequest)(nil) -} -func (x fastReflection_QueryFractionalBalanceRequest_messageType) New() protoreflect.Message { - return new(fastReflection_QueryFractionalBalanceRequest) -} -func (x fastReflection_QueryFractionalBalanceRequest_messageType) Descriptor() protoreflect.MessageDescriptor { - return md_QueryFractionalBalanceRequest -} - -// Descriptor returns message descriptor, which contains only the protobuf -// type information for the message. -func (x *fastReflection_QueryFractionalBalanceRequest) Descriptor() protoreflect.MessageDescriptor { - return md_QueryFractionalBalanceRequest -} - -// Type returns the message type, which encapsulates both Go and protobuf -// type information. If the Go type information is not needed, -// it is recommended that the message descriptor be used instead. -func (x *fastReflection_QueryFractionalBalanceRequest) Type() protoreflect.MessageType { - return _fastReflection_QueryFractionalBalanceRequest_messageType -} - -// New returns a newly allocated and mutable empty message. -func (x *fastReflection_QueryFractionalBalanceRequest) New() protoreflect.Message { - return new(fastReflection_QueryFractionalBalanceRequest) -} - -// Interface unwraps the message reflection interface and -// returns the underlying ProtoMessage interface. -func (x *fastReflection_QueryFractionalBalanceRequest) Interface() protoreflect.ProtoMessage { - return (*QueryFractionalBalanceRequest)(x) -} - -// Range iterates over every populated field in an undefined order, -// calling f for each field descriptor and value encountered. -// Range returns immediately if f returns false. -// While iterating, mutating operations may only be performed -// on the current field descriptor. -func (x *fastReflection_QueryFractionalBalanceRequest) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { - if x.Address != "" { - value := protoreflect.ValueOfString(x.Address) - if !f(fd_QueryFractionalBalanceRequest_address, value) { - return - } - } -} - -// Has reports whether a field is populated. -// -// Some fields have the property of nullability where it is possible to -// distinguish between the default value of a field and whether the field -// was explicitly populated with the default value. Singular message fields, -// member fields of a oneof, and proto2 scalar fields are nullable. Such -// fields are populated only if explicitly set. -// -// In other cases (aside from the nullable cases above), -// a proto3 scalar field is populated if it contains a non-zero value, and -// a repeated field is populated if it is non-empty. -func (x *fastReflection_QueryFractionalBalanceRequest) Has(fd protoreflect.FieldDescriptor) bool { - switch fd.FullName() { - case "cosmos.evm.precisebank.v1.QueryFractionalBalanceRequest.address": - return x.Address != "" - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.QueryFractionalBalanceRequest")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.QueryFractionalBalanceRequest does not contain field %s", fd.FullName())) - } -} - -// Clear clears the field such that a subsequent Has call reports false. -// -// Clearing an extension field clears both the extension type and value -// associated with the given field number. -// -// Clear is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_QueryFractionalBalanceRequest) Clear(fd protoreflect.FieldDescriptor) { - switch fd.FullName() { - case "cosmos.evm.precisebank.v1.QueryFractionalBalanceRequest.address": - x.Address = "" - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.QueryFractionalBalanceRequest")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.QueryFractionalBalanceRequest does not contain field %s", fd.FullName())) - } -} - -// Get retrieves the value for a field. -// -// For unpopulated scalars, it returns the default value, where -// the default value of a bytes scalar is guaranteed to be a copy. -// For unpopulated composite types, it returns an empty, read-only view -// of the value; to obtain a mutable reference, use Mutable. -func (x *fastReflection_QueryFractionalBalanceRequest) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { - switch descriptor.FullName() { - case "cosmos.evm.precisebank.v1.QueryFractionalBalanceRequest.address": - value := x.Address - return protoreflect.ValueOfString(value) - default: - if descriptor.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.QueryFractionalBalanceRequest")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.QueryFractionalBalanceRequest does not contain field %s", descriptor.FullName())) - } -} - -// Set stores the value for a field. -// -// For a field belonging to a oneof, it implicitly clears any other field -// that may be currently set within the same oneof. -// For extension fields, it implicitly stores the provided ExtensionType. -// When setting a composite type, it is unspecified whether the stored value -// aliases the source's memory in any way. If the composite value is an -// empty, read-only value, then it panics. -// -// Set is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_QueryFractionalBalanceRequest) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { - switch fd.FullName() { - case "cosmos.evm.precisebank.v1.QueryFractionalBalanceRequest.address": - x.Address = value.Interface().(string) - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.QueryFractionalBalanceRequest")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.QueryFractionalBalanceRequest does not contain field %s", fd.FullName())) - } -} - -// Mutable returns a mutable reference to a composite type. -// -// If the field is unpopulated, it may allocate a composite value. -// For a field belonging to a oneof, it implicitly clears any other field -// that may be currently set within the same oneof. -// For extension fields, it implicitly stores the provided ExtensionType -// if not already stored. -// It panics if the field does not contain a composite type. -// -// Mutable is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_QueryFractionalBalanceRequest) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { - switch fd.FullName() { - case "cosmos.evm.precisebank.v1.QueryFractionalBalanceRequest.address": - panic(fmt.Errorf("field address of message cosmos.evm.precisebank.v1.QueryFractionalBalanceRequest is not mutable")) - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.QueryFractionalBalanceRequest")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.QueryFractionalBalanceRequest does not contain field %s", fd.FullName())) - } -} - -// NewField returns a new value that is assignable to the field -// for the given descriptor. For scalars, this returns the default value. -// For lists, maps, and messages, this returns a new, empty, mutable value. -func (x *fastReflection_QueryFractionalBalanceRequest) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { - switch fd.FullName() { - case "cosmos.evm.precisebank.v1.QueryFractionalBalanceRequest.address": - return protoreflect.ValueOfString("") - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.QueryFractionalBalanceRequest")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.QueryFractionalBalanceRequest does not contain field %s", fd.FullName())) - } -} - -// WhichOneof reports which field within the oneof is populated, -// returning nil if none are populated. -// It panics if the oneof descriptor does not belong to this message. -func (x *fastReflection_QueryFractionalBalanceRequest) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { - switch d.FullName() { - default: - panic(fmt.Errorf("%s is not a oneof field in cosmos.evm.precisebank.v1.QueryFractionalBalanceRequest", d.FullName())) - } - panic("unreachable") -} - -// GetUnknown retrieves the entire list of unknown fields. -// The caller may only mutate the contents of the RawFields -// if the mutated bytes are stored back into the message with SetUnknown. -func (x *fastReflection_QueryFractionalBalanceRequest) GetUnknown() protoreflect.RawFields { - return x.unknownFields -} - -// SetUnknown stores an entire list of unknown fields. -// The raw fields must be syntactically valid according to the wire format. -// An implementation may panic if this is not the case. -// Once stored, the caller must not mutate the content of the RawFields. -// An empty RawFields may be passed to clear the fields. -// -// SetUnknown is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_QueryFractionalBalanceRequest) SetUnknown(fields protoreflect.RawFields) { - x.unknownFields = fields -} - -// IsValid reports whether the message is valid. -// -// An invalid message is an empty, read-only value. -// -// An invalid message often corresponds to a nil pointer of the concrete -// message type, but the details are implementation dependent. -// Validity is not part of the protobuf data model, and may not -// be preserved in marshaling or other operations. -func (x *fastReflection_QueryFractionalBalanceRequest) IsValid() bool { - return x != nil -} - -// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations. -// This method may return nil. -// -// The returned methods type is identical to -// "google.golang.org/protobuf/runtime/protoiface".Methods. -// Consult the protoiface package documentation for details. -func (x *fastReflection_QueryFractionalBalanceRequest) ProtoMethods() *protoiface.Methods { - size := func(input protoiface.SizeInput) protoiface.SizeOutput { - x := input.Message.Interface().(*QueryFractionalBalanceRequest) - if x == nil { - return protoiface.SizeOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Size: 0, - } - } - options := runtime.SizeInputToOptions(input) - _ = options - var n int - var l int - _ = l - l = len(x.Address) - if l > 0 { - n += 1 + l + runtime.Sov(uint64(l)) - } - if x.unknownFields != nil { - n += len(x.unknownFields) - } - return protoiface.SizeOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Size: n, - } - } - - marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { - x := input.Message.Interface().(*QueryFractionalBalanceRequest) - if x == nil { - return protoiface.MarshalOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Buf: input.Buf, - }, nil - } - options := runtime.MarshalInputToOptions(input) - _ = options - size := options.Size(x) - dAtA := make([]byte, size) - i := len(dAtA) - _ = i - var l int - _ = l - if x.unknownFields != nil { - i -= len(x.unknownFields) - copy(dAtA[i:], x.unknownFields) - } - if len(x.Address) > 0 { - i -= len(x.Address) - copy(dAtA[i:], x.Address) - i = runtime.EncodeVarint(dAtA, i, uint64(len(x.Address))) - i-- - dAtA[i] = 0xa - } - if input.Buf != nil { - input.Buf = append(input.Buf, dAtA...) - } else { - input.Buf = dAtA - } - return protoiface.MarshalOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Buf: input.Buf, - }, nil - } - unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { - x := input.Message.Interface().(*QueryFractionalBalanceRequest) - if x == nil { - return protoiface.UnmarshalOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Flags: input.Flags, - }, nil - } - options := runtime.UnmarshalInputToOptions(input) - _ = options - dAtA := input.Buf - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - 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++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryFractionalBalanceRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryFractionalBalanceRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) - } - var stringLen uint64 - 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++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - postIndex := iNdEx + intStringLen - 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.Address = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := runtime.Skip(dAtA[iNdEx:]) - if err != nil { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - if (iNdEx + skippy) > l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - if !options.DiscardUnknown { - x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) - } - iNdEx += skippy - } - } - - if iNdEx > l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil - } - return &protoiface.Methods{ - NoUnkeyedLiterals: struct{}{}, - Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, - Size: size, - Marshal: marshal, - Unmarshal: unmarshal, - Merge: nil, - CheckInitialized: nil, - } -} - -var ( - md_QueryFractionalBalanceResponse protoreflect.MessageDescriptor - fd_QueryFractionalBalanceResponse_fractional_balance protoreflect.FieldDescriptor -) - -func init() { - file_cosmos_evm_precisebank_v1_query_proto_init() - md_QueryFractionalBalanceResponse = File_cosmos_evm_precisebank_v1_query_proto.Messages().ByName("QueryFractionalBalanceResponse") - fd_QueryFractionalBalanceResponse_fractional_balance = md_QueryFractionalBalanceResponse.Fields().ByName("fractional_balance") -} - -var _ protoreflect.Message = (*fastReflection_QueryFractionalBalanceResponse)(nil) - -type fastReflection_QueryFractionalBalanceResponse QueryFractionalBalanceResponse - -func (x *QueryFractionalBalanceResponse) ProtoReflect() protoreflect.Message { - return (*fastReflection_QueryFractionalBalanceResponse)(x) -} - -func (x *QueryFractionalBalanceResponse) slowProtoReflect() protoreflect.Message { - mi := &file_cosmos_evm_precisebank_v1_query_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -var _fastReflection_QueryFractionalBalanceResponse_messageType fastReflection_QueryFractionalBalanceResponse_messageType -var _ protoreflect.MessageType = fastReflection_QueryFractionalBalanceResponse_messageType{} - -type fastReflection_QueryFractionalBalanceResponse_messageType struct{} - -func (x fastReflection_QueryFractionalBalanceResponse_messageType) Zero() protoreflect.Message { - return (*fastReflection_QueryFractionalBalanceResponse)(nil) -} -func (x fastReflection_QueryFractionalBalanceResponse_messageType) New() protoreflect.Message { - return new(fastReflection_QueryFractionalBalanceResponse) -} -func (x fastReflection_QueryFractionalBalanceResponse_messageType) Descriptor() protoreflect.MessageDescriptor { - return md_QueryFractionalBalanceResponse -} - -// Descriptor returns message descriptor, which contains only the protobuf -// type information for the message. -func (x *fastReflection_QueryFractionalBalanceResponse) Descriptor() protoreflect.MessageDescriptor { - return md_QueryFractionalBalanceResponse -} - -// Type returns the message type, which encapsulates both Go and protobuf -// type information. If the Go type information is not needed, -// it is recommended that the message descriptor be used instead. -func (x *fastReflection_QueryFractionalBalanceResponse) Type() protoreflect.MessageType { - return _fastReflection_QueryFractionalBalanceResponse_messageType -} - -// New returns a newly allocated and mutable empty message. -func (x *fastReflection_QueryFractionalBalanceResponse) New() protoreflect.Message { - return new(fastReflection_QueryFractionalBalanceResponse) -} - -// Interface unwraps the message reflection interface and -// returns the underlying ProtoMessage interface. -func (x *fastReflection_QueryFractionalBalanceResponse) Interface() protoreflect.ProtoMessage { - return (*QueryFractionalBalanceResponse)(x) -} - -// Range iterates over every populated field in an undefined order, -// calling f for each field descriptor and value encountered. -// Range returns immediately if f returns false. -// While iterating, mutating operations may only be performed -// on the current field descriptor. -func (x *fastReflection_QueryFractionalBalanceResponse) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { - if x.FractionalBalance != nil { - value := protoreflect.ValueOfMessage(x.FractionalBalance.ProtoReflect()) - if !f(fd_QueryFractionalBalanceResponse_fractional_balance, value) { - return - } - } -} - -// Has reports whether a field is populated. -// -// Some fields have the property of nullability where it is possible to -// distinguish between the default value of a field and whether the field -// was explicitly populated with the default value. Singular message fields, -// member fields of a oneof, and proto2 scalar fields are nullable. Such -// fields are populated only if explicitly set. -// -// In other cases (aside from the nullable cases above), -// a proto3 scalar field is populated if it contains a non-zero value, and -// a repeated field is populated if it is non-empty. -func (x *fastReflection_QueryFractionalBalanceResponse) Has(fd protoreflect.FieldDescriptor) bool { - switch fd.FullName() { - case "cosmos.evm.precisebank.v1.QueryFractionalBalanceResponse.fractional_balance": - return x.FractionalBalance != nil - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.QueryFractionalBalanceResponse")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.QueryFractionalBalanceResponse does not contain field %s", fd.FullName())) - } -} - -// Clear clears the field such that a subsequent Has call reports false. -// -// Clearing an extension field clears both the extension type and value -// associated with the given field number. -// -// Clear is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_QueryFractionalBalanceResponse) Clear(fd protoreflect.FieldDescriptor) { - switch fd.FullName() { - case "cosmos.evm.precisebank.v1.QueryFractionalBalanceResponse.fractional_balance": - x.FractionalBalance = nil - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.QueryFractionalBalanceResponse")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.QueryFractionalBalanceResponse does not contain field %s", fd.FullName())) - } -} - -// Get retrieves the value for a field. -// -// For unpopulated scalars, it returns the default value, where -// the default value of a bytes scalar is guaranteed to be a copy. -// For unpopulated composite types, it returns an empty, read-only view -// of the value; to obtain a mutable reference, use Mutable. -func (x *fastReflection_QueryFractionalBalanceResponse) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { - switch descriptor.FullName() { - case "cosmos.evm.precisebank.v1.QueryFractionalBalanceResponse.fractional_balance": - value := x.FractionalBalance - return protoreflect.ValueOfMessage(value.ProtoReflect()) - default: - if descriptor.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.QueryFractionalBalanceResponse")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.QueryFractionalBalanceResponse does not contain field %s", descriptor.FullName())) - } -} - -// Set stores the value for a field. -// -// For a field belonging to a oneof, it implicitly clears any other field -// that may be currently set within the same oneof. -// For extension fields, it implicitly stores the provided ExtensionType. -// When setting a composite type, it is unspecified whether the stored value -// aliases the source's memory in any way. If the composite value is an -// empty, read-only value, then it panics. -// -// Set is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_QueryFractionalBalanceResponse) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { - switch fd.FullName() { - case "cosmos.evm.precisebank.v1.QueryFractionalBalanceResponse.fractional_balance": - x.FractionalBalance = value.Message().Interface().(*v1beta1.Coin) - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.QueryFractionalBalanceResponse")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.QueryFractionalBalanceResponse does not contain field %s", fd.FullName())) - } -} - -// Mutable returns a mutable reference to a composite type. -// -// If the field is unpopulated, it may allocate a composite value. -// For a field belonging to a oneof, it implicitly clears any other field -// that may be currently set within the same oneof. -// For extension fields, it implicitly stores the provided ExtensionType -// if not already stored. -// It panics if the field does not contain a composite type. -// -// Mutable is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_QueryFractionalBalanceResponse) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { - switch fd.FullName() { - case "cosmos.evm.precisebank.v1.QueryFractionalBalanceResponse.fractional_balance": - if x.FractionalBalance == nil { - x.FractionalBalance = new(v1beta1.Coin) - } - return protoreflect.ValueOfMessage(x.FractionalBalance.ProtoReflect()) - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.QueryFractionalBalanceResponse")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.QueryFractionalBalanceResponse does not contain field %s", fd.FullName())) - } -} - -// NewField returns a new value that is assignable to the field -// for the given descriptor. For scalars, this returns the default value. -// For lists, maps, and messages, this returns a new, empty, mutable value. -func (x *fastReflection_QueryFractionalBalanceResponse) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { - switch fd.FullName() { - case "cosmos.evm.precisebank.v1.QueryFractionalBalanceResponse.fractional_balance": - m := new(v1beta1.Coin) - return protoreflect.ValueOfMessage(m.ProtoReflect()) - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.precisebank.v1.QueryFractionalBalanceResponse")) - } - panic(fmt.Errorf("message cosmos.evm.precisebank.v1.QueryFractionalBalanceResponse does not contain field %s", fd.FullName())) - } -} - -// WhichOneof reports which field within the oneof is populated, -// returning nil if none are populated. -// It panics if the oneof descriptor does not belong to this message. -func (x *fastReflection_QueryFractionalBalanceResponse) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { - switch d.FullName() { - default: - panic(fmt.Errorf("%s is not a oneof field in cosmos.evm.precisebank.v1.QueryFractionalBalanceResponse", d.FullName())) - } - panic("unreachable") -} - -// GetUnknown retrieves the entire list of unknown fields. -// The caller may only mutate the contents of the RawFields -// if the mutated bytes are stored back into the message with SetUnknown. -func (x *fastReflection_QueryFractionalBalanceResponse) GetUnknown() protoreflect.RawFields { - return x.unknownFields -} - -// SetUnknown stores an entire list of unknown fields. -// The raw fields must be syntactically valid according to the wire format. -// An implementation may panic if this is not the case. -// Once stored, the caller must not mutate the content of the RawFields. -// An empty RawFields may be passed to clear the fields. -// -// SetUnknown is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_QueryFractionalBalanceResponse) SetUnknown(fields protoreflect.RawFields) { - x.unknownFields = fields -} - -// IsValid reports whether the message is valid. -// -// An invalid message is an empty, read-only value. -// -// An invalid message often corresponds to a nil pointer of the concrete -// message type, but the details are implementation dependent. -// Validity is not part of the protobuf data model, and may not -// be preserved in marshaling or other operations. -func (x *fastReflection_QueryFractionalBalanceResponse) IsValid() bool { - return x != nil -} - -// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations. -// This method may return nil. -// -// The returned methods type is identical to -// "google.golang.org/protobuf/runtime/protoiface".Methods. -// Consult the protoiface package documentation for details. -func (x *fastReflection_QueryFractionalBalanceResponse) ProtoMethods() *protoiface.Methods { - size := func(input protoiface.SizeInput) protoiface.SizeOutput { - x := input.Message.Interface().(*QueryFractionalBalanceResponse) - if x == nil { - return protoiface.SizeOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Size: 0, - } - } - options := runtime.SizeInputToOptions(input) - _ = options - var n int - var l int - _ = l - if x.FractionalBalance != nil { - l = options.Size(x.FractionalBalance) - n += 1 + l + runtime.Sov(uint64(l)) - } - if x.unknownFields != nil { - n += len(x.unknownFields) - } - return protoiface.SizeOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Size: n, - } - } - - marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { - x := input.Message.Interface().(*QueryFractionalBalanceResponse) - if x == nil { - return protoiface.MarshalOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Buf: input.Buf, - }, nil - } - options := runtime.MarshalInputToOptions(input) - _ = options - size := options.Size(x) - dAtA := make([]byte, size) - i := len(dAtA) - _ = i - var l int - _ = l - if x.unknownFields != nil { - i -= len(x.unknownFields) - copy(dAtA[i:], x.unknownFields) - } - if x.FractionalBalance != nil { - encoded, err := options.Marshal(x.FractionalBalance) - if err != nil { - return protoiface.MarshalOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Buf: input.Buf, - }, err - } - i -= len(encoded) - copy(dAtA[i:], encoded) - i = runtime.EncodeVarint(dAtA, i, uint64(len(encoded))) - i-- - dAtA[i] = 0xa - } - if input.Buf != nil { - input.Buf = append(input.Buf, dAtA...) - } else { - input.Buf = dAtA - } - return protoiface.MarshalOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Buf: input.Buf, - }, nil - } - unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { - x := input.Message.Interface().(*QueryFractionalBalanceResponse) - if x == nil { - return protoiface.UnmarshalOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Flags: input.Flags, - }, nil - } - options := runtime.UnmarshalInputToOptions(input) - _ = options - dAtA := input.Buf - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - 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++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryFractionalBalanceResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryFractionalBalanceResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field FractionalBalance", wireType) - } - var msglen 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++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - postIndex := iNdEx + msglen - 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 - } - if x.FractionalBalance == nil { - x.FractionalBalance = &v1beta1.Coin{} - } - if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.FractionalBalance); err != nil { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := runtime.Skip(dAtA[iNdEx:]) - if err != nil { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - if (iNdEx + skippy) > l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - if !options.DiscardUnknown { - x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) - } - iNdEx += skippy - } - } - - if iNdEx > l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil - } - return &protoiface.Methods{ - NoUnkeyedLiterals: struct{}{}, - Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, - Size: size, - Marshal: marshal, - Unmarshal: unmarshal, - Merge: nil, - CheckInitialized: nil, - } -} - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.27.0 -// protoc (unknown) -// source: cosmos/evm/precisebank/v1/query.proto - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// QueryRemainderRequest defines the request type for Query/Remainder method. -type QueryRemainderRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *QueryRemainderRequest) Reset() { - *x = QueryRemainderRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_cosmos_evm_precisebank_v1_query_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *QueryRemainderRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*QueryRemainderRequest) ProtoMessage() {} - -// Deprecated: Use QueryRemainderRequest.ProtoReflect.Descriptor instead. -func (*QueryRemainderRequest) Descriptor() ([]byte, []int) { - return file_cosmos_evm_precisebank_v1_query_proto_rawDescGZIP(), []int{0} -} - -// QueryRemainderResponse defines the response type for Query/Remainder method. -type QueryRemainderResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // remainder is the amount backed by the reserve, but not yet owned by any - // account, i.e. not in circulation. - Remainder *v1beta1.Coin `protobuf:"bytes,1,opt,name=remainder,proto3" json:"remainder,omitempty"` -} - -func (x *QueryRemainderResponse) Reset() { - *x = QueryRemainderResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_cosmos_evm_precisebank_v1_query_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *QueryRemainderResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*QueryRemainderResponse) ProtoMessage() {} - -// Deprecated: Use QueryRemainderResponse.ProtoReflect.Descriptor instead. -func (*QueryRemainderResponse) Descriptor() ([]byte, []int) { - return file_cosmos_evm_precisebank_v1_query_proto_rawDescGZIP(), []int{1} -} - -func (x *QueryRemainderResponse) GetRemainder() *v1beta1.Coin { - if x != nil { - return x.Remainder - } - return nil -} - -// QueryFractionalBalanceRequest defines the request type for -// Query/FractionalBalance method. -type QueryFractionalBalanceRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // address is the account address to query fractional balance for. - Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` -} - -func (x *QueryFractionalBalanceRequest) Reset() { - *x = QueryFractionalBalanceRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_cosmos_evm_precisebank_v1_query_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *QueryFractionalBalanceRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*QueryFractionalBalanceRequest) ProtoMessage() {} - -// Deprecated: Use QueryFractionalBalanceRequest.ProtoReflect.Descriptor instead. -func (*QueryFractionalBalanceRequest) Descriptor() ([]byte, []int) { - return file_cosmos_evm_precisebank_v1_query_proto_rawDescGZIP(), []int{2} -} - -func (x *QueryFractionalBalanceRequest) GetAddress() string { - if x != nil { - return x.Address - } - return "" -} - -// QueryFractionalBalanceResponse defines the response type for -// Query/FractionalBalance method. -type QueryFractionalBalanceResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // fractional_balance is the fractional balance of the address. - FractionalBalance *v1beta1.Coin `protobuf:"bytes,1,opt,name=fractional_balance,json=fractionalBalance,proto3" json:"fractional_balance,omitempty"` -} - -func (x *QueryFractionalBalanceResponse) Reset() { - *x = QueryFractionalBalanceResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_cosmos_evm_precisebank_v1_query_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *QueryFractionalBalanceResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*QueryFractionalBalanceResponse) ProtoMessage() {} - -// Deprecated: Use QueryFractionalBalanceResponse.ProtoReflect.Descriptor instead. -func (*QueryFractionalBalanceResponse) Descriptor() ([]byte, []int) { - return file_cosmos_evm_precisebank_v1_query_proto_rawDescGZIP(), []int{3} -} - -func (x *QueryFractionalBalanceResponse) GetFractionalBalance() *v1beta1.Coin { - if x != nil { - return x.FractionalBalance - } - return nil -} - -var File_cosmos_evm_precisebank_v1_query_proto protoreflect.FileDescriptor - -var file_cosmos_evm_precisebank_v1_query_proto_rawDesc = []byte{ - 0x0a, 0x25, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x65, 0x76, 0x6d, 0x2f, 0x70, 0x72, 0x65, - 0x63, 0x69, 0x73, 0x65, 0x62, 0x61, 0x6e, 0x6b, 0x2f, 0x76, 0x31, 0x2f, 0x71, 0x75, 0x65, 0x72, - 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x19, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, - 0x65, 0x76, 0x6d, 0x2e, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x65, 0x62, 0x61, 0x6e, 0x6b, 0x2e, - 0x76, 0x31, 0x1a, 0x1e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x62, 0x61, 0x73, 0x65, 0x2f, - 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x63, 0x6f, 0x69, 0x6e, 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, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x17, 0x0a, 0x15, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, - 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, - 0x57, 0x0a, 0x16, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x64, 0x65, - 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x09, 0x72, 0x65, 0x6d, - 0x61, 0x69, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x09, 0x72, - 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x64, 0x65, 0x72, 0x22, 0x39, 0x0a, 0x1d, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x46, 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, - 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x22, 0x70, 0x0a, 0x1e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x72, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x12, 0x66, 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x61, 0x6c, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, - 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x42, 0x04, 0xc8, 0xde, - 0x1f, 0x00, 0x52, 0x11, 0x66, 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x42, 0x61, - 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x32, 0xf4, 0x02, 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, - 0x9e, 0x01, 0x0a, 0x09, 0x52, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x30, 0x2e, - 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x70, 0x72, 0x65, 0x63, 0x69, - 0x73, 0x65, 0x62, 0x61, 0x6e, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, - 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x31, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x70, 0x72, 0x65, - 0x63, 0x69, 0x73, 0x65, 0x62, 0x61, 0x6e, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x52, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x2c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x12, 0x24, 0x2f, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x2f, 0x65, 0x76, 0x6d, 0x2f, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x65, 0x62, - 0x61, 0x6e, 0x6b, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x64, 0x65, 0x72, - 0x12, 0xc9, 0x01, 0x0a, 0x11, 0x46, 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x42, - 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x38, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, - 0x65, 0x76, 0x6d, 0x2e, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x65, 0x62, 0x61, 0x6e, 0x6b, 0x2e, - 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x61, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x39, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x70, 0x72, - 0x65, 0x63, 0x69, 0x73, 0x65, 0x62, 0x61, 0x6e, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, - 0x72, 0x79, 0x46, 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x42, 0x61, 0x6c, 0x61, - 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3f, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x39, 0x12, 0x37, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x65, 0x76, 0x6d, - 0x2f, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x65, 0x62, 0x61, 0x6e, 0x6b, 0x2f, 0x76, 0x31, 0x2f, - 0x66, 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, - 0x63, 0x65, 0x2f, 0x7b, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x7d, 0x42, 0xf0, 0x01, 0x0a, - 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, - 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x65, 0x62, 0x61, 0x6e, 0x6b, 0x2e, 0x76, 0x31, 0x42, 0x0a, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x38, 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, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, - 0x65, 0x62, 0x61, 0x6e, 0x6b, 0x2f, 0x76, 0x31, 0x3b, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x65, - 0x62, 0x61, 0x6e, 0x6b, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x43, 0x45, 0x50, 0xaa, 0x02, 0x19, 0x43, - 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x45, 0x76, 0x6d, 0x2e, 0x50, 0x72, 0x65, 0x63, 0x69, 0x73, - 0x65, 0x62, 0x61, 0x6e, 0x6b, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x19, 0x43, 0x6f, 0x73, 0x6d, 0x6f, - 0x73, 0x5c, 0x45, 0x76, 0x6d, 0x5c, 0x50, 0x72, 0x65, 0x63, 0x69, 0x73, 0x65, 0x62, 0x61, 0x6e, - 0x6b, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x25, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x45, 0x76, - 0x6d, 0x5c, 0x50, 0x72, 0x65, 0x63, 0x69, 0x73, 0x65, 0x62, 0x61, 0x6e, 0x6b, 0x5c, 0x56, 0x31, - 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x1c, 0x43, - 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x45, 0x76, 0x6d, 0x3a, 0x3a, 0x50, 0x72, 0x65, 0x63, - 0x69, 0x73, 0x65, 0x62, 0x61, 0x6e, 0x6b, 0x3a, 0x3a, 0x56, 0x31, 0xc8, 0xe1, 0x1e, 0x00, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_cosmos_evm_precisebank_v1_query_proto_rawDescOnce sync.Once - file_cosmos_evm_precisebank_v1_query_proto_rawDescData = file_cosmos_evm_precisebank_v1_query_proto_rawDesc -) - -func file_cosmos_evm_precisebank_v1_query_proto_rawDescGZIP() []byte { - file_cosmos_evm_precisebank_v1_query_proto_rawDescOnce.Do(func() { - file_cosmos_evm_precisebank_v1_query_proto_rawDescData = protoimpl.X.CompressGZIP(file_cosmos_evm_precisebank_v1_query_proto_rawDescData) - }) - return file_cosmos_evm_precisebank_v1_query_proto_rawDescData -} - -var file_cosmos_evm_precisebank_v1_query_proto_msgTypes = make([]protoimpl.MessageInfo, 4) -var file_cosmos_evm_precisebank_v1_query_proto_goTypes = []interface{}{ - (*QueryRemainderRequest)(nil), // 0: cosmos.evm.precisebank.v1.QueryRemainderRequest - (*QueryRemainderResponse)(nil), // 1: cosmos.evm.precisebank.v1.QueryRemainderResponse - (*QueryFractionalBalanceRequest)(nil), // 2: cosmos.evm.precisebank.v1.QueryFractionalBalanceRequest - (*QueryFractionalBalanceResponse)(nil), // 3: cosmos.evm.precisebank.v1.QueryFractionalBalanceResponse - (*v1beta1.Coin)(nil), // 4: cosmos.base.v1beta1.Coin -} -var file_cosmos_evm_precisebank_v1_query_proto_depIdxs = []int32{ - 4, // 0: cosmos.evm.precisebank.v1.QueryRemainderResponse.remainder:type_name -> cosmos.base.v1beta1.Coin - 4, // 1: cosmos.evm.precisebank.v1.QueryFractionalBalanceResponse.fractional_balance:type_name -> cosmos.base.v1beta1.Coin - 0, // 2: cosmos.evm.precisebank.v1.Query.Remainder:input_type -> cosmos.evm.precisebank.v1.QueryRemainderRequest - 2, // 3: cosmos.evm.precisebank.v1.Query.FractionalBalance:input_type -> cosmos.evm.precisebank.v1.QueryFractionalBalanceRequest - 1, // 4: cosmos.evm.precisebank.v1.Query.Remainder:output_type -> cosmos.evm.precisebank.v1.QueryRemainderResponse - 3, // 5: cosmos.evm.precisebank.v1.Query.FractionalBalance:output_type -> cosmos.evm.precisebank.v1.QueryFractionalBalanceResponse - 4, // [4:6] is the sub-list for method output_type - 2, // [2:4] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name -} - -func init() { file_cosmos_evm_precisebank_v1_query_proto_init() } -func file_cosmos_evm_precisebank_v1_query_proto_init() { - if File_cosmos_evm_precisebank_v1_query_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_cosmos_evm_precisebank_v1_query_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryRemainderRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_cosmos_evm_precisebank_v1_query_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryRemainderResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_cosmos_evm_precisebank_v1_query_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryFractionalBalanceRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_cosmos_evm_precisebank_v1_query_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryFractionalBalanceResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_cosmos_evm_precisebank_v1_query_proto_rawDesc, - NumEnums: 0, - NumMessages: 4, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_cosmos_evm_precisebank_v1_query_proto_goTypes, - DependencyIndexes: file_cosmos_evm_precisebank_v1_query_proto_depIdxs, - MessageInfos: file_cosmos_evm_precisebank_v1_query_proto_msgTypes, - }.Build() - File_cosmos_evm_precisebank_v1_query_proto = out.File - file_cosmos_evm_precisebank_v1_query_proto_rawDesc = nil - file_cosmos_evm_precisebank_v1_query_proto_goTypes = nil - file_cosmos_evm_precisebank_v1_query_proto_depIdxs = nil -} diff --git a/api/cosmos/evm/precisebank/v1/query_grpc.pb.go b/api/cosmos/evm/precisebank/v1/query_grpc.pb.go deleted file mode 100644 index d49ae44a..00000000 --- a/api/cosmos/evm/precisebank/v1/query_grpc.pb.go +++ /dev/null @@ -1,154 +0,0 @@ -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-grpc v1.3.0 -// - protoc (unknown) -// source: cosmos/evm/precisebank/v1/query.proto - -package precisebankv1 - -import ( - context "context" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.32.0 or later. -const _ = grpc.SupportPackageIsVersion7 - -const ( - Query_Remainder_FullMethodName = "/cosmos.evm.precisebank.v1.Query/Remainder" - Query_FractionalBalance_FullMethodName = "/cosmos.evm.precisebank.v1.Query/FractionalBalance" -) - -// QueryClient is the client API for Query service. -// -// 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 { - // Remainder returns the amount backed by the reserve, but not yet owned by - // any account, i.e. not in circulation. - Remainder(ctx context.Context, in *QueryRemainderRequest, opts ...grpc.CallOption) (*QueryRemainderResponse, error) - // FractionalBalance returns only the fractional balance of an address. This - // does not include any integer balance. - FractionalBalance(ctx context.Context, in *QueryFractionalBalanceRequest, opts ...grpc.CallOption) (*QueryFractionalBalanceResponse, error) -} - -type queryClient struct { - cc grpc.ClientConnInterface -} - -func NewQueryClient(cc grpc.ClientConnInterface) QueryClient { - return &queryClient{cc} -} - -func (c *queryClient) Remainder(ctx context.Context, in *QueryRemainderRequest, opts ...grpc.CallOption) (*QueryRemainderResponse, error) { - out := new(QueryRemainderResponse) - err := c.cc.Invoke(ctx, Query_Remainder_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *queryClient) FractionalBalance(ctx context.Context, in *QueryFractionalBalanceRequest, opts ...grpc.CallOption) (*QueryFractionalBalanceResponse, error) { - out := new(QueryFractionalBalanceResponse) - err := c.cc.Invoke(ctx, Query_FractionalBalance_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// QueryServer is the server API for Query service. -// All implementations must embed UnimplementedQueryServer -// for forward compatibility -type QueryServer interface { - // Remainder returns the amount backed by the reserve, but not yet owned by - // any account, i.e. not in circulation. - Remainder(context.Context, *QueryRemainderRequest) (*QueryRemainderResponse, error) - // FractionalBalance returns only the fractional balance of an address. This - // does not include any integer balance. - FractionalBalance(context.Context, *QueryFractionalBalanceRequest) (*QueryFractionalBalanceResponse, error) - mustEmbedUnimplementedQueryServer() -} - -// UnimplementedQueryServer must be embedded to have forward compatible implementations. -type UnimplementedQueryServer struct { -} - -func (UnimplementedQueryServer) Remainder(context.Context, *QueryRemainderRequest) (*QueryRemainderResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Remainder not implemented") -} -func (UnimplementedQueryServer) FractionalBalance(context.Context, *QueryFractionalBalanceRequest) (*QueryFractionalBalanceResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method FractionalBalance not implemented") -} -func (UnimplementedQueryServer) mustEmbedUnimplementedQueryServer() {} - -// UnsafeQueryServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to QueryServer will -// result in compilation errors. -type UnsafeQueryServer interface { - mustEmbedUnimplementedQueryServer() -} - -func RegisterQueryServer(s grpc.ServiceRegistrar, srv QueryServer) { - s.RegisterService(&Query_ServiceDesc, srv) -} - -func _Query_Remainder_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryRemainderRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).Remainder(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: Query_Remainder_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).Remainder(ctx, req.(*QueryRemainderRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Query_FractionalBalance_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryFractionalBalanceRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).FractionalBalance(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: Query_FractionalBalance_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).FractionalBalance(ctx, req.(*QueryFractionalBalanceRequest)) - } - return interceptor(ctx, in, info, handler) -} - -// Query_ServiceDesc is the grpc.ServiceDesc for Query service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var Query_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "cosmos.evm.precisebank.v1.Query", - HandlerType: (*QueryServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Remainder", - Handler: _Query_Remainder_Handler, - }, - { - MethodName: "FractionalBalance", - Handler: _Query_FractionalBalance_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "cosmos/evm/precisebank/v1/query.proto", -} diff --git a/api/cosmos/evm/vm/v1/evm.pulsar.go b/api/cosmos/evm/vm/v1/evm.pulsar.go index 7e5c9a62..2839bba4 100644 --- a/api/cosmos/evm/vm/v1/evm.pulsar.go +++ b/api/cosmos/evm/vm/v1/evm.pulsar.go @@ -10933,7 +10933,11 @@ type EvmCoinInfo struct { Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"` ExtendedDenom string `protobuf:"bytes,2,opt,name=extended_denom,json=extendedDenom,proto3" json:"extended_denom,omitempty"` DisplayDenom string `protobuf:"bytes,3,opt,name=display_denom,json=displayDenom,proto3" json:"display_denom,omitempty"` - Decimals uint32 `protobuf:"varint,4,opt,name=decimals,proto3" json:"decimals,omitempty"` + // decimals is now deprecated and will be removed in a future release. When it is removed we will assume + // the evm token denom is 18 decimal precision. + // + // Deprecated: Do not use. + Decimals uint32 `protobuf:"varint,4,opt,name=decimals,proto3" json:"decimals,omitempty"` } func (x *EvmCoinInfo) Reset() { @@ -10977,6 +10981,7 @@ func (x *EvmCoinInfo) GetDisplayDenom() string { return "" } +// Deprecated: Do not use. func (x *EvmCoinInfo) GetDecimals() uint32 { if x != nil { return x.Decimals @@ -11279,39 +11284,39 @@ var file_cosmos_evm_vm_v1_evm_proto_rawDesc = []byte{ 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, - 0x22, 0x8b, 0x01, 0x0a, 0x0b, 0x45, 0x76, 0x6d, 0x43, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x66, 0x6f, + 0x22, 0x8f, 0x01, 0x0a, 0x0b, 0x45, 0x76, 0x6d, 0x43, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x12, 0x25, 0x0a, 0x0e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x44, 0x65, 0x6e, 0x6f, 0x6d, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x44, 0x65, 0x6e, - 0x6f, 0x6d, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x73, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x73, 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, + 0x6f, 0x6d, 0x12, 0x1e, 0x0a, 0x08, 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x73, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0d, 0x42, 0x02, 0x18, 0x01, 0x52, 0x08, 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, + 0x6c, 0x73, 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/query_grpc.pb.go b/api/cosmos/evm/vm/v1/query_grpc.pb.go index fd130cf3..14b1b7fe 100644 --- a/api/cosmos/evm/vm/v1/query_grpc.pb.go +++ b/api/cosmos/evm/vm/v1/query_grpc.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.3.0 +// - protoc-gen-go-grpc v1.6.0 // - protoc (unknown) // source: cosmos/evm/vm/v1/query.proto @@ -15,8 +15,8 @@ import ( // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.32.0 or later. -const _ = grpc.SupportPackageIsVersion7 +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 const ( Query_Account_FullMethodName = "/cosmos.evm.vm.v1.Query/Account" @@ -39,6 +39,8 @@ const ( // QueryClient is the client API for Query service. // // 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. +// +// Query defines the gRPC querier service. type QueryClient interface { // Account queries an Ethereum account. Account(ctx context.Context, in *QueryAccountRequest, opts ...grpc.CallOption) (*QueryAccountResponse, error) @@ -89,8 +91,9 @@ func NewQueryClient(cc grpc.ClientConnInterface) QueryClient { } func (c *queryClient) Account(ctx context.Context, in *QueryAccountRequest, opts ...grpc.CallOption) (*QueryAccountResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(QueryAccountResponse) - err := c.cc.Invoke(ctx, Query_Account_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Query_Account_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -98,8 +101,9 @@ func (c *queryClient) Account(ctx context.Context, in *QueryAccountRequest, opts } func (c *queryClient) CosmosAccount(ctx context.Context, in *QueryCosmosAccountRequest, opts ...grpc.CallOption) (*QueryCosmosAccountResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(QueryCosmosAccountResponse) - err := c.cc.Invoke(ctx, Query_CosmosAccount_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Query_CosmosAccount_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -107,8 +111,9 @@ func (c *queryClient) CosmosAccount(ctx context.Context, in *QueryCosmosAccountR } func (c *queryClient) ValidatorAccount(ctx context.Context, in *QueryValidatorAccountRequest, opts ...grpc.CallOption) (*QueryValidatorAccountResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(QueryValidatorAccountResponse) - err := c.cc.Invoke(ctx, Query_ValidatorAccount_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Query_ValidatorAccount_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -116,8 +121,9 @@ func (c *queryClient) ValidatorAccount(ctx context.Context, in *QueryValidatorAc } func (c *queryClient) Balance(ctx context.Context, in *QueryBalanceRequest, opts ...grpc.CallOption) (*QueryBalanceResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(QueryBalanceResponse) - err := c.cc.Invoke(ctx, Query_Balance_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Query_Balance_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -125,8 +131,9 @@ func (c *queryClient) Balance(ctx context.Context, in *QueryBalanceRequest, opts } func (c *queryClient) Storage(ctx context.Context, in *QueryStorageRequest, opts ...grpc.CallOption) (*QueryStorageResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(QueryStorageResponse) - err := c.cc.Invoke(ctx, Query_Storage_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Query_Storage_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -134,8 +141,9 @@ func (c *queryClient) Storage(ctx context.Context, in *QueryStorageRequest, opts } func (c *queryClient) Code(ctx context.Context, in *QueryCodeRequest, opts ...grpc.CallOption) (*QueryCodeResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(QueryCodeResponse) - err := c.cc.Invoke(ctx, Query_Code_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Query_Code_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -143,8 +151,9 @@ func (c *queryClient) Code(ctx context.Context, in *QueryCodeRequest, opts ...gr } func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(QueryParamsResponse) - err := c.cc.Invoke(ctx, Query_Params_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Query_Params_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -152,8 +161,9 @@ func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts . } func (c *queryClient) EthCall(ctx context.Context, in *EthCallRequest, opts ...grpc.CallOption) (*MsgEthereumTxResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(MsgEthereumTxResponse) - err := c.cc.Invoke(ctx, Query_EthCall_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Query_EthCall_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -161,8 +171,9 @@ func (c *queryClient) EthCall(ctx context.Context, in *EthCallRequest, opts ...g } func (c *queryClient) EstimateGas(ctx context.Context, in *EthCallRequest, opts ...grpc.CallOption) (*EstimateGasResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(EstimateGasResponse) - err := c.cc.Invoke(ctx, Query_EstimateGas_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Query_EstimateGas_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -170,8 +181,9 @@ func (c *queryClient) EstimateGas(ctx context.Context, in *EthCallRequest, opts } func (c *queryClient) TraceTx(ctx context.Context, in *QueryTraceTxRequest, opts ...grpc.CallOption) (*QueryTraceTxResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(QueryTraceTxResponse) - err := c.cc.Invoke(ctx, Query_TraceTx_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Query_TraceTx_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -179,8 +191,9 @@ func (c *queryClient) TraceTx(ctx context.Context, in *QueryTraceTxRequest, opts } func (c *queryClient) TraceBlock(ctx context.Context, in *QueryTraceBlockRequest, opts ...grpc.CallOption) (*QueryTraceBlockResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(QueryTraceBlockResponse) - err := c.cc.Invoke(ctx, Query_TraceBlock_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Query_TraceBlock_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -188,8 +201,9 @@ func (c *queryClient) TraceBlock(ctx context.Context, in *QueryTraceBlockRequest } func (c *queryClient) TraceCall(ctx context.Context, in *QueryTraceCallRequest, opts ...grpc.CallOption) (*QueryTraceCallResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(QueryTraceCallResponse) - err := c.cc.Invoke(ctx, Query_TraceCall_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Query_TraceCall_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -197,8 +211,9 @@ func (c *queryClient) TraceCall(ctx context.Context, in *QueryTraceCallRequest, } func (c *queryClient) BaseFee(ctx context.Context, in *QueryBaseFeeRequest, opts ...grpc.CallOption) (*QueryBaseFeeResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(QueryBaseFeeResponse) - err := c.cc.Invoke(ctx, Query_BaseFee_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Query_BaseFee_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -206,8 +221,9 @@ func (c *queryClient) BaseFee(ctx context.Context, in *QueryBaseFeeRequest, opts } func (c *queryClient) Config(ctx context.Context, in *QueryConfigRequest, opts ...grpc.CallOption) (*QueryConfigResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(QueryConfigResponse) - err := c.cc.Invoke(ctx, Query_Config_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Query_Config_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -215,8 +231,9 @@ func (c *queryClient) Config(ctx context.Context, in *QueryConfigRequest, opts . } func (c *queryClient) GlobalMinGasPrice(ctx context.Context, in *QueryGlobalMinGasPriceRequest, opts ...grpc.CallOption) (*QueryGlobalMinGasPriceResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(QueryGlobalMinGasPriceResponse) - err := c.cc.Invoke(ctx, Query_GlobalMinGasPrice_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Query_GlobalMinGasPrice_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -225,7 +242,9 @@ func (c *queryClient) GlobalMinGasPrice(ctx context.Context, in *QueryGlobalMinG // QueryServer is the server API for Query service. // All implementations must embed UnimplementedQueryServer -// for forward compatibility +// for forward compatibility. +// +// Query defines the gRPC querier service. type QueryServer interface { // Account queries an Ethereum account. Account(context.Context, *QueryAccountRequest) (*QueryAccountResponse, error) @@ -268,56 +287,60 @@ type QueryServer interface { mustEmbedUnimplementedQueryServer() } -// UnimplementedQueryServer must be embedded to have forward compatible implementations. -type UnimplementedQueryServer struct { -} +// UnimplementedQueryServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedQueryServer struct{} func (UnimplementedQueryServer) Account(context.Context, *QueryAccountRequest) (*QueryAccountResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Account not implemented") + return nil, status.Error(codes.Unimplemented, "method Account not implemented") } func (UnimplementedQueryServer) CosmosAccount(context.Context, *QueryCosmosAccountRequest) (*QueryCosmosAccountResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method CosmosAccount not implemented") + return nil, status.Error(codes.Unimplemented, "method CosmosAccount not implemented") } func (UnimplementedQueryServer) ValidatorAccount(context.Context, *QueryValidatorAccountRequest) (*QueryValidatorAccountResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ValidatorAccount not implemented") + return nil, status.Error(codes.Unimplemented, "method ValidatorAccount not implemented") } func (UnimplementedQueryServer) Balance(context.Context, *QueryBalanceRequest) (*QueryBalanceResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Balance not implemented") + return nil, status.Error(codes.Unimplemented, "method Balance not implemented") } func (UnimplementedQueryServer) Storage(context.Context, *QueryStorageRequest) (*QueryStorageResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Storage not implemented") + return nil, status.Error(codes.Unimplemented, "method Storage not implemented") } func (UnimplementedQueryServer) Code(context.Context, *QueryCodeRequest) (*QueryCodeResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Code not implemented") + return nil, status.Error(codes.Unimplemented, "method Code not implemented") } func (UnimplementedQueryServer) Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Params not implemented") + return nil, status.Error(codes.Unimplemented, "method Params not implemented") } func (UnimplementedQueryServer) EthCall(context.Context, *EthCallRequest) (*MsgEthereumTxResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method EthCall not implemented") + return nil, status.Error(codes.Unimplemented, "method EthCall not implemented") } func (UnimplementedQueryServer) EstimateGas(context.Context, *EthCallRequest) (*EstimateGasResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method EstimateGas not implemented") + return nil, status.Error(codes.Unimplemented, "method EstimateGas not implemented") } func (UnimplementedQueryServer) TraceTx(context.Context, *QueryTraceTxRequest) (*QueryTraceTxResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method TraceTx not implemented") + return nil, status.Error(codes.Unimplemented, "method TraceTx not implemented") } func (UnimplementedQueryServer) TraceBlock(context.Context, *QueryTraceBlockRequest) (*QueryTraceBlockResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method TraceBlock not implemented") + return nil, status.Error(codes.Unimplemented, "method TraceBlock not implemented") } func (UnimplementedQueryServer) TraceCall(context.Context, *QueryTraceCallRequest) (*QueryTraceCallResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method TraceCall not implemented") + return nil, status.Error(codes.Unimplemented, "method TraceCall not implemented") } func (UnimplementedQueryServer) BaseFee(context.Context, *QueryBaseFeeRequest) (*QueryBaseFeeResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method BaseFee not implemented") + return nil, status.Error(codes.Unimplemented, "method BaseFee not implemented") } func (UnimplementedQueryServer) Config(context.Context, *QueryConfigRequest) (*QueryConfigResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Config not implemented") + return nil, status.Error(codes.Unimplemented, "method Config not implemented") } func (UnimplementedQueryServer) GlobalMinGasPrice(context.Context, *QueryGlobalMinGasPriceRequest) (*QueryGlobalMinGasPriceResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GlobalMinGasPrice not implemented") + return nil, status.Error(codes.Unimplemented, "method GlobalMinGasPrice not implemented") } func (UnimplementedQueryServer) mustEmbedUnimplementedQueryServer() {} +func (UnimplementedQueryServer) testEmbeddedByValue() {} // UnsafeQueryServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to QueryServer will @@ -327,6 +350,13 @@ type UnsafeQueryServer interface { } func RegisterQueryServer(s grpc.ServiceRegistrar, srv QueryServer) { + // If the following call panics, it indicates UnimplementedQueryServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } s.RegisterService(&Query_ServiceDesc, srv) } diff --git a/api/cosmos/evm/vm/v1/tx.pulsar.go b/api/cosmos/evm/vm/v1/tx.pulsar.go index f39f7451..46df45cb 100644 --- a/api/cosmos/evm/vm/v1/tx.pulsar.go +++ b/api/cosmos/evm/vm/v1/tx.pulsar.go @@ -3636,7 +3636,8 @@ 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 + // 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"` diff --git a/api/cosmos/evm/vm/v1/tx_grpc.pb.go b/api/cosmos/evm/vm/v1/tx_grpc.pb.go index 0ed13e4b..d1108fcb 100644 --- a/api/cosmos/evm/vm/v1/tx_grpc.pb.go +++ b/api/cosmos/evm/vm/v1/tx_grpc.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.3.0 +// - protoc-gen-go-grpc v1.6.0 // - protoc (unknown) // source: cosmos/evm/vm/v1/tx.proto @@ -15,8 +15,8 @@ import ( // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.32.0 or later. -const _ = grpc.SupportPackageIsVersion7 +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 const ( Msg_EthereumTx_FullMethodName = "/cosmos.evm.vm.v1.Msg/EthereumTx" @@ -27,6 +27,8 @@ const ( // MsgClient is the client API for Msg service. // // 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. +// +// Msg defines the evm Msg service. type MsgClient interface { // EthereumTx defines a method submitting Ethereum transactions. EthereumTx(ctx context.Context, in *MsgEthereumTx, opts ...grpc.CallOption) (*MsgEthereumTxResponse, error) @@ -49,8 +51,9 @@ func NewMsgClient(cc grpc.ClientConnInterface) MsgClient { } func (c *msgClient) EthereumTx(ctx context.Context, in *MsgEthereumTx, opts ...grpc.CallOption) (*MsgEthereumTxResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(MsgEthereumTxResponse) - err := c.cc.Invoke(ctx, Msg_EthereumTx_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Msg_EthereumTx_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -58,8 +61,9 @@ func (c *msgClient) EthereumTx(ctx context.Context, in *MsgEthereumTx, opts ...g } func (c *msgClient) UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(MsgUpdateParamsResponse) - err := c.cc.Invoke(ctx, Msg_UpdateParams_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Msg_UpdateParams_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -67,8 +71,9 @@ func (c *msgClient) UpdateParams(ctx context.Context, in *MsgUpdateParams, opts } func (c *msgClient) RegisterPreinstalls(ctx context.Context, in *MsgRegisterPreinstalls, opts ...grpc.CallOption) (*MsgRegisterPreinstallsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(MsgRegisterPreinstallsResponse) - err := c.cc.Invoke(ctx, Msg_RegisterPreinstalls_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Msg_RegisterPreinstalls_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -77,7 +82,9 @@ func (c *msgClient) RegisterPreinstalls(ctx context.Context, in *MsgRegisterPrei // MsgServer is the server API for Msg service. // All implementations must embed UnimplementedMsgServer -// for forward compatibility +// for forward compatibility. +// +// Msg defines the evm Msg service. type MsgServer interface { // EthereumTx defines a method submitting Ethereum transactions. EthereumTx(context.Context, *MsgEthereumTx) (*MsgEthereumTxResponse, error) @@ -92,20 +99,24 @@ type MsgServer interface { mustEmbedUnimplementedMsgServer() } -// UnimplementedMsgServer must be embedded to have forward compatible implementations. -type UnimplementedMsgServer struct { -} +// UnimplementedMsgServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedMsgServer struct{} func (UnimplementedMsgServer) EthereumTx(context.Context, *MsgEthereumTx) (*MsgEthereumTxResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method EthereumTx not implemented") + return nil, status.Error(codes.Unimplemented, "method EthereumTx not implemented") } func (UnimplementedMsgServer) UpdateParams(context.Context, *MsgUpdateParams) (*MsgUpdateParamsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method UpdateParams not implemented") + return nil, status.Error(codes.Unimplemented, "method UpdateParams not implemented") } func (UnimplementedMsgServer) RegisterPreinstalls(context.Context, *MsgRegisterPreinstalls) (*MsgRegisterPreinstallsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method RegisterPreinstalls not implemented") + return nil, status.Error(codes.Unimplemented, "method RegisterPreinstalls not implemented") } func (UnimplementedMsgServer) mustEmbedUnimplementedMsgServer() {} +func (UnimplementedMsgServer) testEmbeddedByValue() {} // UnsafeMsgServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to MsgServer will @@ -115,6 +126,13 @@ type UnsafeMsgServer interface { } func RegisterMsgServer(s grpc.ServiceRegistrar, srv MsgServer) { + // If the following call panics, it indicates UnimplementedMsgServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } s.RegisterService(&Msg_ServiceDesc, srv) } diff --git a/client/debug/debug.go b/client/debug/debug.go index 62faedda..cb644120 100644 --- a/client/debug/debug.go +++ b/client/debug/debug.go @@ -153,6 +153,7 @@ func RawBytesCmd() *cobra.Command { if err != nil { return err } + // #nosec G115 -- ParseInt(..., 10, 8) constrains to 0-255 byteArray = append(byteArray, byte(b)) } fmt.Printf("%X\n", byteArray) diff --git a/client/keys/add.go b/client/keys/add.go index 54df6875..c6fc0549 100644 --- a/client/keys/add.go +++ b/client/keys/add.go @@ -5,6 +5,7 @@ import ( "bytes" "encoding/json" "errors" + "flag" "fmt" "io" "os" @@ -13,7 +14,9 @@ import ( "github.com/spf13/cobra" cryptohd "github.com/cosmos/evm/crypto/hd" + evmkeyring "github.com/cosmos/evm/crypto/keyring" bip39 "github.com/cosmos/go-bip39" + ledger "github.com/cosmos/ledger-cosmos-go" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" @@ -22,6 +25,8 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + cosmosLedger "github.com/cosmos/cosmos-sdk/crypto/ledger" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -172,7 +177,37 @@ func RunAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf // If we're using ledger, only thing we need is the path and the bech32 prefix. if useLedger { bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix() - + needHardware := flag.Lookup("test.v") == nil && os.Getenv("GO_TEST") != "1" + if needHardware { + switch coinType { + case 60: + cosmosLedger.SetDiscoverLedger(func() (cosmosLedger.SECP256K1, error) { + return evmkeyring.LedgerDerivation() + }) + cosmosLedger.SetCreatePubkey(func(key []byte) cryptotypes.PubKey { + return evmkeyring.CreatePubkey(key) + }) + cosmosLedger.SetAppName(evmkeyring.AppName) + cosmosLedger.SetDERConversion(false) + case 118: + cosmosLedger.SetDiscoverLedger(func() (cosmosLedger.SECP256K1, error) { + device, err := ledger.FindLedgerCosmosUserApp() + if err != nil { + return nil, err + } + return device, nil + }) + cosmosLedger.SetCreatePubkey(func(key []byte) cryptotypes.PubKey { + return &secp256k1.PubKey{Key: key} + }) + cosmosLedger.SetAppName(cosmosLedger.AppName) + cosmosLedger.SetDERConversion(true) + default: + return fmt.Errorf( + "unsupported coin type %d for Ledger. Supported coin types: 60 (Ethereum app), 118 (Cosmos app)", coinType, + ) + } + } // use the provided algo to save the ledger key k, err := kb.SaveLedgerKey(name, algo, bech32PrefixAccAddr, coinType, account, index) if err != nil { @@ -281,6 +316,7 @@ func printCreate(cmd *cobra.Command, k *keyring.Record, showMnemonic bool, mnemo // print mnemonic unless requested not to. if showMnemonic { + // #nosec G705 -- CLI output to stderr, not HTML if _, err := fmt.Fprintf(cmd.ErrOrStderr(), "\n**Important** write this mnemonic phrase in a safe place.\nIt is the only way to recover your account if you ever forget your password.\n\n%s\n\n", //nolint:lll mnemonic); err != nil { diff --git a/client/keys/utils.go b/client/keys/utils.go index dd99119f..ad5425ab 100644 --- a/client/keys/utils.go +++ b/client/keys/utils.go @@ -37,6 +37,7 @@ func printKeyringRecord(w io.Writer, k *cryptokeyring.Record, bechKeyOut bechKey return err } + // #nosec G705 -- CLI output, not HTML if _, err := fmt.Fprintln(w, string(out)); err != nil { return err } @@ -51,6 +52,7 @@ func printTextRecords(w io.Writer, kos []keys.KeyOutput) error { return err } + // #nosec G705 -- CLI output, not HTML if _, err := fmt.Fprintln(w, string(out)); err != nil { return err } diff --git a/codecov.yml b/codecov.yml index 589de7f2..a2593652 100644 --- a/codecov.yml +++ b/codecov.yml @@ -13,7 +13,7 @@ coverage: project: default: threshold: 1% # allow this much decrease on project - target: 90% + target: auto changes: false comment: diff --git a/config/chain_id.go b/config/chain_id.go deleted file mode 100644 index 8de2e454..00000000 --- a/config/chain_id.go +++ /dev/null @@ -1,29 +0,0 @@ -package config - -import ( - "path/filepath" - - "github.com/spf13/viper" - - "github.com/cosmos/cosmos-sdk/client/config" -) - -// GetChainIDFromHome returns the chain ID from the client configuration -// in the given home directory. -func GetChainIDFromHome(home string) (string, error) { - v := viper.New() - v.AddConfigPath(filepath.Join(home, "config")) - v.SetConfigName("client") - v.SetConfigType("toml") - - if err := v.ReadInConfig(); err != nil { - return "", err - } - conf := new(config.ClientConfig) - - if err := v.Unmarshal(conf); err != nil { - return "", err - } - - return conf.ChainID, nil -} diff --git a/config/constants.go b/config/constants.go deleted file mode 100644 index e7180db4..00000000 --- a/config/constants.go +++ /dev/null @@ -1,29 +0,0 @@ -package config - -const ( // TODO:VLAD - Clean this up - // ExampleChainDenom is the denomination of the Cosmos EVM example chain's base coin. - ExampleChainDenom = "aatom" - - // ExampleDisplayDenom is the display denomination of the Cosmos EVM example chain's base coin. - ExampleDisplayDenom = "atom" - - // EighteenDecimalsChainID is the chain ID for the 18 decimals chain. - EighteenDecimalsChainID = 9001 - - // SixDecimalsChainID is the chain ID for the 6 decimals chain. - SixDecimalsChainID = 9002 - - // TwelveDecimalsChainID is the chain ID for the 12 decimals chain. - TwelveDecimalsChainID = 9003 - - // TwoDecimalsChainID is the chain ID for the 2 decimals chain. - TwoDecimalsChainID = 9004 - - // TestChainID1 is test chain IDs for IBC E2E test - TestChainID1 = 9005 - // TestChainID2 is test chain IDs for IBC E2E test - TestChainID2 = 9006 - - // WEVMOSContractMainnet is the WEVMOS contract address for mainnet - WEVMOSContractMainnet = "0xD4949664cD82660AaE99bEdc034a0deA8A0bd517" -) diff --git a/config/evmd_config.go b/config/evmd_config.go deleted file mode 100644 index 2f930369..00000000 --- a/config/evmd_config.go +++ /dev/null @@ -1,130 +0,0 @@ -package config - -import ( - "maps" - "sort" - - corevm "github.com/ethereum/go-ethereum/core/vm" - - cosmosevmserverconfig "github.com/cosmos/evm/server/config" - cosmosevmutils "github.com/cosmos/evm/utils" - erc20types "github.com/cosmos/evm/x/erc20/types" - feemarkettypes "github.com/cosmos/evm/x/feemarket/types" - precisebanktypes "github.com/cosmos/evm/x/precisebank/types" - evmtypes "github.com/cosmos/evm/x/vm/types" - ibctransfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - - clienthelpers "cosmossdk.io/client/v2/helpers" - - serverconfig "github.com/cosmos/cosmos-sdk/server/config" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - 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" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" -) - -func MustGetDefaultNodeHome() string { - defaultNodeHome, err := clienthelpers.GetNodeHomeDirectory(".evmd") - if err != nil { - panic(err) - } - return defaultNodeHome -} - -// module account permissions -var maccPerms = map[string][]string{ - authtypes.FeeCollectorName: nil, - distrtypes.ModuleName: nil, - ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner}, - minttypes.ModuleName: {authtypes.Minter}, - stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking}, - stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, - govtypes.ModuleName: {authtypes.Burner}, - - // Cosmos EVM modules - evmtypes.ModuleName: {authtypes.Minter, authtypes.Burner}, - feemarkettypes.ModuleName: nil, - erc20types.ModuleName: {authtypes.Minter, authtypes.Burner}, - precisebanktypes.ModuleName: {authtypes.Minter, authtypes.Burner}, -} - -// BlockedAddresses returns all the app's blocked account addresses. -// -// Note, this includes: -// - module accounts -// - Ethereum's native precompiled smart contracts -// - Cosmos EVM' available static precompiled contracts -func BlockedAddresses() map[string]bool { - blockedAddrs := make(map[string]bool) - - maccPerms := GetMaccPerms() - accs := make([]string, 0, len(maccPerms)) - for acc := range maccPerms { - accs = append(accs, acc) - } - sort.Strings(accs) - - for _, acc := range accs { - blockedAddrs[authtypes.NewModuleAddress(acc).String()] = true - } - - blockedPrecompilesHex := evmtypes.AvailableStaticPrecompiles - for _, addr := range corevm.PrecompiledAddressesPrague { - blockedPrecompilesHex = append(blockedPrecompilesHex, addr.Hex()) - } - - for _, precompile := range blockedPrecompilesHex { - blockedAddrs[cosmosevmutils.Bech32StringFromHexAddress(precompile)] = true - } - - return blockedAddrs -} - -// GetMaccPerms returns a copy of the module account permissions -func GetMaccPerms() map[string][]string { - return maps.Clone(maccPerms) -} - -type EVMAppConfig struct { - serverconfig.Config - - EVM cosmosevmserverconfig.EVMConfig - JSONRPC cosmosevmserverconfig.JSONRPCConfig - TLS cosmosevmserverconfig.TLSConfig -} - -// InitAppConfig helps to override default appConfig template and configs. -// return "", nil if no custom configuration is required for the application. -func InitAppConfig(denom string, evmChainID uint64) (string, interface{}) { - // Optionally allow the chain developer to overwrite the SDK's default - // server config. - srvCfg := serverconfig.DefaultConfig() - // The SDK's default minimum gas price is set to "" (empty value) inside - // app.toml. If left empty by validators, the node will halt on startup. - // However, the chain developer can set a default app.toml value for their - // validators here. - // - // In summary: - // - if you leave srvCfg.MinGasPrices = "", all validators MUST tweak their - // own app.toml config, - // - if you set srvCfg.MinGasPrices non-empty, validators CAN tweak their - // own app.toml to override, or use this default value. - // - // In this example application, we set the min gas prices to 0. - srvCfg.MinGasPrices = "0" + denom - - evmCfg := cosmosevmserverconfig.DefaultEVMConfig() - evmCfg.EVMChainID = evmChainID - - customAppConfig := EVMAppConfig{ - Config: *srvCfg, - EVM: *evmCfg, - JSONRPC: *cosmosevmserverconfig.DefaultJSONRPCConfig(), - TLS: *cosmosevmserverconfig.DefaultTLSConfig(), - } - - return EVMAppTemplate, customAppConfig -} - -const EVMAppTemplate = serverconfig.DefaultConfigTemplate + cosmosevmserverconfig.DefaultEVMConfigTemplate diff --git a/contracts/contract_creation_tester.go b/contracts/contract_creation_tester.go new file mode 100644 index 00000000..8732ea4a --- /dev/null +++ b/contracts/contract_creation_tester.go @@ -0,0 +1,10 @@ +package contracts + +import ( + contractutils "github.com/cosmos/evm/contracts/utils" + evmtypes "github.com/cosmos/evm/x/vm/types" +) + +func LoadContractCreationTester() (evmtypes.CompiledContract, error) { + return contractutils.LoadContractFromJSONFile("solidity/ContractCreationTester.json") +} diff --git a/contracts/erc20_with_native_transfers.go b/contracts/erc20_with_native_transfers.go new file mode 100644 index 00000000..9509af1e --- /dev/null +++ b/contracts/erc20_with_native_transfers.go @@ -0,0 +1,10 @@ +package contracts + +import ( + contractutils "github.com/cosmos/evm/contracts/utils" + evmtypes "github.com/cosmos/evm/x/vm/types" +) + +func LoadERC20WithNativeTransfers() (evmtypes.CompiledContract, error) { + return contractutils.LoadContractFromJSONFile("solidity/ERC20WithNativeTransfers.json") +} diff --git a/contracts/hardhat.config.js b/contracts/hardhat.config.js index c0e73823..7be09191 100644 --- a/contracts/hardhat.config.js +++ b/contracts/hardhat.config.js @@ -1,5 +1,5 @@ /** @type import('hardhat/config').HardhatUserConfig */ -module.exports = { +export default { solidity: { compilers: [ { diff --git a/contracts/ics20_sequential_precompile_calls.go b/contracts/ics20_sequential_precompile_calls.go new file mode 100644 index 00000000..e25291bc --- /dev/null +++ b/contracts/ics20_sequential_precompile_calls.go @@ -0,0 +1,10 @@ +package contracts + +import ( + contractutils "github.com/cosmos/evm/contracts/utils" + evmtypes "github.com/cosmos/evm/x/vm/types" +) + +func LoadSequentialICS20Sender() (evmtypes.CompiledContract, error) { + return contractutils.LoadContractFromJSONFile("solidity/SequentialICS20Sender.json") +} diff --git a/contracts/ics20_transfer_tester.go b/contracts/ics20_transfer_tester.go new file mode 100644 index 00000000..b8902008 --- /dev/null +++ b/contracts/ics20_transfer_tester.go @@ -0,0 +1,10 @@ +package contracts + +import ( + contractutils "github.com/cosmos/evm/contracts/utils" + evmtypes "github.com/cosmos/evm/x/vm/types" +) + +func LoadICS20TransferTester() (evmtypes.CompiledContract, error) { + return contractutils.LoadContractFromJSONFile("solidity/ICS20TransferTester.json") +} diff --git a/contracts/package-lock.json b/contracts/package-lock.json index d1002d67..04d9eb0d 100644 --- a/contracts/package-lock.json +++ b/contracts/package-lock.json @@ -13,7 +13,7 @@ }, "devDependencies": { "@openzeppelin/contracts": "^4.9.6", - "hardhat": "^2.22.2" + "hardhat": "^3.0.15" } }, "node_modules/@account-abstraction/contracts": { @@ -22,720 +22,602 @@ "integrity": "sha512-8ooRJuR7XzohMDM4MV34I12Ci2bmxfE9+cixakRL7lA4BAwJKQ3ahvd8FbJa9kiwkUPCUNtj+/zxDQWYYalLMQ==", "license": "MIT" }, - "node_modules/@ethersproject/abi": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz", - "integrity": "sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==", + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } + "license": "MIT", + "optional": true, + "os": [ + "aix" ], - "dependencies": { - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "node_modules/@ethersproject/abstract-provider": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz", - "integrity": "sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" ], - "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/networks": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/web": "^5.7.0" - } - }, - "node_modules/@ethersproject/abstract-signer": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz", - "integrity": "sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" ], - "dependencies": { - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0" - } - }, - "node_modules/@ethersproject/address": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz", - "integrity": "sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" ], - "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/rlp": "^5.7.0" - } - }, - "node_modules/@ethersproject/base64": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz", - "integrity": "sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0" + "engines": { + "node": ">=18" } }, - "node_modules/@ethersproject/bignumber": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz", - "integrity": "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==", + "node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } + "license": "MIT", + "optional": true, + "os": [ + "android" ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "bn.js": "^5.2.1" + "engines": { + "node": ">=18" } }, - "node_modules/@ethersproject/bytes": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz", - "integrity": "sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==", + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } + "license": "MIT", + "optional": true, + "os": [ + "darwin" ], - "dependencies": { - "@ethersproject/logger": "^5.7.0" + "engines": { + "node": ">=18" } }, - "node_modules/@ethersproject/constants": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz", - "integrity": "sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==", + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } + "license": "MIT", + "optional": true, + "os": [ + "darwin" ], - "dependencies": { - "@ethersproject/bignumber": "^5.7.0" + "engines": { + "node": ">=18" } }, - "node_modules/@ethersproject/hash": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz", - "integrity": "sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" ], - "dependencies": { - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/base64": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "node_modules/@ethersproject/keccak256": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz", - "integrity": "sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "js-sha3": "0.8.0" + "engines": { + "node": ">=18" } }, - "node_modules/@ethersproject/logger": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz", - "integrity": "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==", + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ] + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/@ethersproject/networks": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz", - "integrity": "sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==", + "node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } + "license": "MIT", + "optional": true, + "os": [ + "linux" ], - "dependencies": { - "@ethersproject/logger": "^5.7.0" + "engines": { + "node": ">=18" } }, - "node_modules/@ethersproject/properties": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz", - "integrity": "sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==", + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } + "license": "MIT", + "optional": true, + "os": [ + "linux" ], - "dependencies": { - "@ethersproject/logger": "^5.7.0" + "engines": { + "node": ">=18" } }, - "node_modules/@ethersproject/rlp": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz", - "integrity": "sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==", + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } + "license": "MIT", + "optional": true, + "os": [ + "linux" ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0" + "engines": { + "node": ">=18" } }, - "node_modules/@ethersproject/signing-key": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz", - "integrity": "sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "bn.js": "^5.2.1", - "elliptic": "6.5.4", - "hash.js": "1.1.7" - } - }, - "node_modules/@ethersproject/strings": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz", - "integrity": "sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0" + "engines": { + "node": ">=18" } }, - "node_modules/@ethersproject/transactions": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz", - "integrity": "sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" ], - "dependencies": { - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/rlp": "^5.7.0", - "@ethersproject/signing-key": "^5.7.0" - } - }, - "node_modules/@ethersproject/web": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz", - "integrity": "sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" ], - "dependencies": { - "@ethersproject/base64": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" + "engines": { + "node": ">=18" } }, - "node_modules/@fastify/busboy": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", - "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" + "node": ">=18" } }, - "node_modules/@metamask/eth-sig-util": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz", - "integrity": "sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ==", + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], "dev": true, - "dependencies": { - "ethereumjs-abi": "^0.6.8", - "ethereumjs-util": "^6.2.1", - "ethjs-util": "^0.1.6", - "tweetnacl": "^1.0.3", - "tweetnacl-util": "^0.15.1" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12.0.0" + "node": ">=18" } }, - "node_modules/@noble/hashes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz", - "integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ] - }, - "node_modules/@noble/secp256k1": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz", - "integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==", + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ] + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/@nomicfoundation/edr": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.3.3.tgz", - "integrity": "sha512-zP+e+3B1nEUx6bW5BPnIzCQbkhmYfdMBJdiVggTqqTfAA82sOkdOG7wsOMcz5qF3fYfx/irNRM1kgc9HVFIbpQ==", + "node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 18" - }, - "optionalDependencies": { - "@nomicfoundation/edr-darwin-arm64": "0.3.3", - "@nomicfoundation/edr-darwin-x64": "0.3.3", - "@nomicfoundation/edr-linux-arm64-gnu": "0.3.3", - "@nomicfoundation/edr-linux-arm64-musl": "0.3.3", - "@nomicfoundation/edr-linux-x64-gnu": "0.3.3", - "@nomicfoundation/edr-linux-x64-musl": "0.3.3", - "@nomicfoundation/edr-win32-arm64-msvc": "0.3.3", - "@nomicfoundation/edr-win32-ia32-msvc": "0.3.3", - "@nomicfoundation/edr-win32-x64-msvc": "0.3.3" + "node": ">=18" } }, - "node_modules/@nomicfoundation/edr-darwin-arm64": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.3.3.tgz", - "integrity": "sha512-E9VGsUD+1Ga4mn/5ooHsMi8JEfhZbKP6CXN/BhJ8kXbIC10NqTD1RuhCKGRtYq4vqH/3Nfq25Xg8E8RWOF4KBQ==", + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ - "darwin" + "netbsd" ], "engines": { - "node": ">= 18" + "node": ">=18" } }, - "node_modules/@nomicfoundation/edr-darwin-x64": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.3.3.tgz", - "integrity": "sha512-vkZXZ1ydPg+Ijb2iyqENA+KCkxGTCUWG5itCSliiA0Li2YE7ujDMGhheEpFp1WVlZadviz0bfk1rZXbCqlirpg==", + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ - "darwin" + "netbsd" ], "engines": { - "node": ">= 18" + "node": ">=18" } }, - "node_modules/@nomicfoundation/edr-linux-arm64-gnu": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.3.3.tgz", - "integrity": "sha512-gdIg0Yj1qqS9wVuywc5B/+DqKylfUGB6/CQn/shMqwAfsAVAVpchkhy66PR+REEx7fh/GkNctxLlENXPeLzDiA==", + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ - "linux" + "openbsd" ], "engines": { - "node": ">= 18" + "node": ">=18" } }, - "node_modules/@nomicfoundation/edr-linux-arm64-musl": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.3.3.tgz", - "integrity": "sha512-AXZ08MFvhNeBZbOBNmz1SJ/DMrMOE2mHEJtaNnsctlxIunjxfrWww4q+WXB34jbr9iaVYYlPsaWe5sueuw6s3Q==", + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", "cpu": [ - "arm64" + "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ - "linux" + "openbsd" ], "engines": { - "node": ">= 18" + "node": ">=18" } }, - "node_modules/@nomicfoundation/edr-linux-x64-gnu": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.3.3.tgz", - "integrity": "sha512-xElOs1U+E6lBLtv1mnJ+E8nr2MxZgKiLo8bZAgBboy9odYtmkDVwhMjtsFKSuZbGxFtsSyGRT4cXw3JAbtUDeA==", + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", "cpu": [ - "x64" + "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ - "linux" + "openharmony" ], "engines": { - "node": ">= 18" + "node": ">=18" } }, - "node_modules/@nomicfoundation/edr-linux-x64-musl": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.3.3.tgz", - "integrity": "sha512-2Fe6gwm1RAGQ/PfMYiaSba2OrFp8zzYWh+am9lYObOFjV9D+A1zhIzfy0UC74glPks5eV8eY4pBPrVR042m2Nw==", + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ - "linux" + "sunos" ], "engines": { - "node": ">= 18" + "node": ">=18" } }, - "node_modules/@nomicfoundation/edr-win32-arm64-msvc": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-arm64-msvc/-/edr-win32-arm64-msvc-0.3.3.tgz", - "integrity": "sha512-8NHyxIsFrl0ufSQ/ErqF2lKIa/gz1gaaa1a2vKkDEqvqCUcPhBTYhA5NHgTPhLETFTnCFr0z+YbctFCyjh4qrA==", + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">= 10" + "node": ">=18" } }, - "node_modules/@nomicfoundation/edr-win32-ia32-msvc": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-ia32-msvc/-/edr-win32-ia32-msvc-0.3.3.tgz", - "integrity": "sha512-0F6hM0kGia4dQVb/kauho9JcP1ozWisY2/She+ISR5ceuhzmAwQJluM0g+0TYDME0LtxBxiMPq/yPiZMQeq31w==", + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">= 18" + "node": ">=18" } }, - "node_modules/@nomicfoundation/edr-win32-x64-msvc": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.3.3.tgz", - "integrity": "sha512-d75q1uaMb6z9i+GQZoblbOfFBvlBnWc+5rB13UWRkCOJSnoYwyFWhGJx5GeM59gC7aIblc5VD9qOAhHuvM9N+w==", + "node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">= 18" + "node": ">=18" } }, - "node_modules/@nomicfoundation/ethereumjs-common": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.4.tgz", - "integrity": "sha512-9Rgb658lcWsjiicr5GzNCjI1llow/7r0k50dLL95OJ+6iZJcVbi15r3Y0xh2cIO+zgX0WIHcbzIu6FeQf9KPrg==", + "node_modules/@noble/curves": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", "dev": true, + "license": "MIT", "dependencies": { - "@nomicfoundation/ethereumjs-util": "9.0.4" + "@noble/hashes": "1.4.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@nomicfoundation/ethereumjs-rlp": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.4.tgz", - "integrity": "sha512-8H1S3s8F6QueOc/X92SdrA4RDenpiAEqMg5vJH99kcQaCy/a3Q6fgseo75mgWlbanGJXSlAPtnCeG9jvfTYXlw==", + "node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", "dev": true, - "bin": { - "rlp": "bin/rlp.cjs" - }, + "license": "MIT", "engines": { - "node": ">=18" + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@nomicfoundation/ethereumjs-tx": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.4.tgz", - "integrity": "sha512-Xjv8wAKJGMrP1f0n2PeyfFCCojHd7iS3s/Ab7qzF1S64kxZ8Z22LCMynArYsVqiFx6rzYy548HNVEyI+AYN/kw==", + "node_modules/@nomicfoundation/edr": { + "version": "0.12.0-next.14", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.12.0-next.14.tgz", + "integrity": "sha512-MGHY2x7JaNdkqlQxFBYoM7Miw2EqsQrI3ReVZMwLP5mULSRTAOnt3hCw6cnjXxGi991HnejNAedJofke6OdqqA==", "dev": true, + "license": "MIT", "dependencies": { - "@nomicfoundation/ethereumjs-common": "4.0.4", - "@nomicfoundation/ethereumjs-rlp": "5.0.4", - "@nomicfoundation/ethereumjs-util": "9.0.4", - "ethereum-cryptography": "0.1.3" + "@nomicfoundation/edr-darwin-arm64": "0.12.0-next.14", + "@nomicfoundation/edr-darwin-x64": "0.12.0-next.14", + "@nomicfoundation/edr-linux-arm64-gnu": "0.12.0-next.14", + "@nomicfoundation/edr-linux-arm64-musl": "0.12.0-next.14", + "@nomicfoundation/edr-linux-x64-gnu": "0.12.0-next.14", + "@nomicfoundation/edr-linux-x64-musl": "0.12.0-next.14", + "@nomicfoundation/edr-win32-x64-msvc": "0.12.0-next.14" }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "c-kzg": "^2.1.2" - }, - "peerDependenciesMeta": { - "c-kzg": { - "optional": true - } + "node": ">= 20" } }, - "node_modules/@nomicfoundation/ethereumjs-tx/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "dev": true, - "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" - } - }, - "node_modules/@nomicfoundation/ethereumjs-util": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.4.tgz", - "integrity": "sha512-sLOzjnSrlx9Bb9EFNtHzK/FJFsfg2re6bsGqinFinH1gCqVfz9YYlXiMWwDM4C/L4ywuHFCYwfKTVr/QHQcU0Q==", + "node_modules/@nomicfoundation/edr-darwin-arm64": { + "version": "0.12.0-next.14", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.12.0-next.14.tgz", + "integrity": "sha512-sl0DibKSUOS7JXhUtaQ6FJUY+nk+uq5gx+Fyd9iiqs8awZPNn6KSuvV1EbWCi+yd3mrxgZ/wO8E77C1Dxj4xQA==", "dev": true, - "dependencies": { - "@nomicfoundation/ethereumjs-rlp": "5.0.4", - "ethereum-cryptography": "0.1.3" - }, + "license": "MIT", "engines": { - "node": ">=18" - }, - "peerDependencies": { - "c-kzg": "^2.1.2" - }, - "peerDependenciesMeta": { - "c-kzg": { - "optional": true - } + "node": ">= 20" } }, - "node_modules/@nomicfoundation/ethereumjs-util/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "node_modules/@nomicfoundation/edr-darwin-x64": { + "version": "0.12.0-next.14", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.12.0-next.14.tgz", + "integrity": "sha512-lfmatc1MSOaw0rDFB+ynnAGz5TWm3hSeY/+zDpPZghMODZelXm4JCqF41CQ6paLsW3X/pXcHM1HUGCUBWeoI/A==", "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + } + }, + "node_modules/@nomicfoundation/edr-linux-arm64-gnu": { + "version": "0.12.0-next.14", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.12.0-next.14.tgz", + "integrity": "sha512-sWun3PhVgat8d4lg1d5MAXSIsFlSMBzvrpMSDFNOU9hPJEclSHbHBMRcarQuGqwm/5ZBzTwCS25u78A+UATTrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + } + }, + "node_modules/@nomicfoundation/edr-linux-arm64-musl": { + "version": "0.12.0-next.14", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.12.0-next.14.tgz", + "integrity": "sha512-omWKioD8fFp7ayCeSDu2CqvG78+oYw8zdVECDwZVmE0jpszRCsTufNYflWRQnlGqH6GqjEUwq2c3yLxFgOTjFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + } + }, + "node_modules/@nomicfoundation/edr-linux-x64-gnu": { + "version": "0.12.0-next.14", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.12.0-next.14.tgz", + "integrity": "sha512-vk0s4SaC7s1wa98W24a4zqunTK/yIcSEnsSLRM/Nl+JJs6iqS8tvmnh/BbFINORMBJ065OWc10qw2Lsbu/rxtg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + } + }, + "node_modules/@nomicfoundation/edr-linux-x64-musl": { + "version": "0.12.0-next.14", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.12.0-next.14.tgz", + "integrity": "sha512-/xKQD6c2RXQBIb30iTeh/NrMdYvHs6Nd+2UXS6wxlfX7GzRPOkpVDiDGD7Sda82JI459KH67dADOD6CpX8cpHQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + } + }, + "node_modules/@nomicfoundation/edr-win32-x64-msvc": { + "version": "0.12.0-next.14", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.12.0-next.14.tgz", + "integrity": "sha512-GZcyGdOoLWnUtfPU+6B1vUi4fwf3bouSRf3xuKFHz3p/WNhpDK+8Esq3UmOmYAZWRgFT0ZR6XUk9H2owGDTVvQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + } + }, + "node_modules/@nomicfoundation/hardhat-errors": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-errors/-/hardhat-errors-3.0.5.tgz", + "integrity": "sha512-8Ayqf6hFM1glmrSxrXgX6n2pn5uTlHNxEB8N5Me0DOeOGB67PRIrQdiO+RzUhrNW5YgWUNWBevOLQbW06uQ79g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nomicfoundation/hardhat-utils": "^3.0.1" + } + }, + "node_modules/@nomicfoundation/hardhat-utils": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-utils/-/hardhat-utils-3.0.5.tgz", + "integrity": "sha512-5zkQSuSxkwK7fQxKswJ1GGc/3AuWBSmxA7GhczTPLx28dAXQnubRU8nA48SkCkKesJq5x4TROP+XheSE2VkLUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@streamparser/json-node": "^0.0.22", + "debug": "^4.3.2", + "env-paths": "^2.2.0", + "ethereum-cryptography": "^2.2.1", + "fast-equals": "^5.0.1", + "json-stream-stringify": "^3.1.6", + "rfdc": "^1.3.1", + "undici": "^6.16.1" + } + }, + "node_modules/@nomicfoundation/hardhat-zod-utils": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-zod-utils/-/hardhat-zod-utils-3.0.1.tgz", + "integrity": "sha512-I6/pyYiS9p2lLkzQuedr1ScMocH+ew8l233xTi+LP92gjEiviJDxselpkzgU01MUM0t6BPpfP8yMO958LDEJVg==", + "dev": true, + "license": "MIT", "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" + "@nomicfoundation/hardhat-errors": "^3.0.0", + "@nomicfoundation/hardhat-utils": "^3.0.2" + }, + "peerDependencies": { + "zod": "^3.23.8" } }, "node_modules/@nomicfoundation/solidity-analyzer": { @@ -927,2543 +809,494 @@ "license": "MIT" }, "node_modules/@scure/base": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.6.tgz", - "integrity": "sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g==", + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", + "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", "dev": true, + "license": "MIT", "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/@scure/bip32": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.5.tgz", - "integrity": "sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", + "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", + "dev": true, + "license": "MIT", "dependencies": { - "@noble/hashes": "~1.2.0", - "@noble/secp256k1": "~1.7.0", - "@scure/base": "~1.1.0" + "@noble/curves": "~1.4.0", + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, "node_modules/@scure/bip39": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.1.tgz", - "integrity": "sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", + "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", + "dev": true, + "license": "MIT", "dependencies": { - "@noble/hashes": "~1.2.0", - "@scure/base": "~1.1.0" + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, "node_modules/@sentry/core": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.30.0.tgz", - "integrity": "sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg==", + "version": "9.47.1", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.47.1.tgz", + "integrity": "sha512-KX62+qIt4xgy8eHKHiikfhz2p5fOciXd0Cl+dNzhgPFq8klq4MGMNaf148GB3M/vBqP4nw/eFvRMAayFCgdRQw==", "dev": true, - "dependencies": { - "@sentry/hub": "5.30.0", - "@sentry/minimal": "5.30.0", - "@sentry/types": "5.30.0", - "@sentry/utils": "5.30.0", - "tslib": "^1.9.3" - }, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=18" } }, - "node_modules/@sentry/hub": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.30.0.tgz", - "integrity": "sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ==", + "node_modules/@streamparser/json": { + "version": "0.0.22", + "resolved": "https://registry.npmjs.org/@streamparser/json/-/json-0.0.22.tgz", + "integrity": "sha512-b6gTSBjJ8G8SuO3Gbbj+zXbVx8NSs1EbpbMKpzGLWMdkR+98McH9bEjSz3+0mPJf68c5nxa3CrJHp5EQNXM6zQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@streamparser/json-node": { + "version": "0.0.22", + "resolved": "https://registry.npmjs.org/@streamparser/json-node/-/json-node-0.0.22.tgz", + "integrity": "sha512-sJT2ptNRwqB1lIsQrQlCoWk5rF4tif9wDh+7yluAGijJamAhrHGYpFB/Zg3hJeceoZypi74ftXk8DHzwYpbZSg==", "dev": true, + "license": "MIT", "dependencies": { - "@sentry/types": "5.30.0", - "@sentry/utils": "5.30.0", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" + "@streamparser/json": "^0.0.22" } }, - "node_modules/@sentry/minimal": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.30.0.tgz", - "integrity": "sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw==", + "node_modules/adm-zip": { + "version": "0.4.16", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", + "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", "dev": true, - "dependencies": { - "@sentry/hub": "5.30.0", - "@sentry/types": "5.30.0", - "tslib": "^1.9.3" - }, "engines": { - "node": ">=6" + "node": ">=0.3.0" } }, - "node_modules/@sentry/node": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-5.30.0.tgz", - "integrity": "sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg==", + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "dev": true, - "dependencies": { - "@sentry/core": "5.30.0", - "@sentry/hub": "5.30.0", - "@sentry/tracing": "5.30.0", - "@sentry/types": "5.30.0", - "@sentry/utils": "5.30.0", - "cookie": "^0.4.1", - "https-proxy-agent": "^5.0.0", - "lru_map": "^0.3.3", - "tslib": "^1.9.3" - }, "engines": { "node": ">=6" } }, - "node_modules/@sentry/tracing": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-5.30.0.tgz", - "integrity": "sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw==", + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, - "dependencies": { - "@sentry/hub": "5.30.0", - "@sentry/minimal": "5.30.0", - "@sentry/types": "5.30.0", - "@sentry/utils": "5.30.0", - "tslib": "^1.9.3" - }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/@sentry/types": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.30.0.tgz", - "integrity": "sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==", + "node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6" + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@sentry/utils": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.30.0.tgz", - "integrity": "sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==", + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, + "license": "MIT", "dependencies": { - "@sentry/types": "5.30.0", - "tslib": "^1.9.3" + "readdirp": "^4.0.1" }, "engines": { - "node": ">=6" + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@types/bn.js": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.5.tgz", - "integrity": "sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A==", + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, + "license": "MIT", "dependencies": { - "@types/node": "*" + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/@types/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==", - "dev": true - }, - "node_modules/@types/node": { - "version": "20.12.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.5.tgz", - "integrity": "sha512-BD+BjQ9LS/D8ST9p5uqBxghlN+S42iuNxjsUGjeZobe/ciXzk2qb1B6IXc6AnRLS+yFJRpN2IPEHMzwspfDJNw==", + "node_modules/enquirer": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", + "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", "dev": true, "dependencies": { - "undici-types": "~5.26.4" + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" } }, - "node_modules/@types/pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew==", + "node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", "dev": true, - "dependencies": { - "@types/node": "*" + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" } }, - "node_modules/@types/secp256k1": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.6.tgz", - "integrity": "sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==", + "node_modules/ethereum-cryptography": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", + "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", "dev": true, + "license": "MIT", "dependencies": { - "@types/node": "*" + "@noble/curves": "1.4.2", + "@noble/hashes": "1.4.0", + "@scure/bip32": "1.4.0", + "@scure/bip39": "1.3.0" } }, - "node_modules/adm-zip": { - "version": "0.4.16", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", - "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", + "node_modules/fast-equals": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.3.3.tgz", + "integrity": "sha512-/boTcHZeIAQ2r/tL11voclBHDeP9WPxLt+tyAbVSyyXuUFyh0Tne7gJZTqGbxnvj79TjLdCXLOY7UIPhyG5MTw==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.3.0" + "node": ">=6.0.0" } }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, - "dependencies": { - "debug": "4" - }, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">= 6.0.0" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "node_modules/get-tsconfig": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", + "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", "dev": true, + "license": "MIT", "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" + "resolve-pkg-maps": "^1.0.0" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "dev": true, - "dependencies": { - "string-width": "^4.1.0" + "node_modules/hardhat": { + "version": "3.0.15", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-3.0.15.tgz", + "integrity": "sha512-cXxaeSxFJ+u0MfbvWsS3Gdr7/uP7wjo4xviYcGdu9AKtwY6YsU+v0quK/j1NWmvO1Y4gk350SdZzQw++hJy4LA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nomicfoundation/edr": "0.12.0-next.14", + "@nomicfoundation/hardhat-errors": "^3.0.4", + "@nomicfoundation/hardhat-utils": "^3.0.5", + "@nomicfoundation/hardhat-zod-utils": "^3.0.1", + "@nomicfoundation/solidity-analyzer": "^0.1.1", + "@sentry/core": "^9.4.0", + "adm-zip": "^0.4.16", + "chalk": "^5.3.0", + "chokidar": "^4.0.3", + "debug": "^4.3.2", + "enquirer": "^2.3.0", + "ethereum-cryptography": "^2.2.1", + "micro-eth-signer": "^0.14.0", + "p-map": "^7.0.2", + "resolve.exports": "^2.0.3", + "semver": "^7.6.3", + "tsx": "^4.19.3", + "ws": "^8.18.0", + "zod": "^3.23.8" + }, + "bin": { + "hardhat": "dist/src/cli.js" } }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "node_modules/json-stream-stringify": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/json-stream-stringify/-/json-stream-stringify-3.1.6.tgz", + "integrity": "sha512-x7fpwxOkbhFCaJDJ8vb1fBY3DdSa4AlITaz+HHILQJzdPMnHEFjxPwVUi1ALIbcIxDE0PNe/0i7frnY8QnBQog==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=7.10.1" + } + }, + "node_modules/micro-eth-signer": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/micro-eth-signer/-/micro-eth-signer-0.14.0.tgz", + "integrity": "sha512-5PLLzHiVYPWClEvZIXXFu5yutzpadb73rnQCpUqIHu3No3coFuWQNfE5tkBQJ7djuLYl6aRLaS0MgWJYGoqiBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.8.1", + "@noble/hashes": "~1.7.1", + "micro-packed": "~0.7.2" } }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "node_modules/micro-eth-signer/node_modules/@noble/curves": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.2.tgz", + "integrity": "sha512-vnI7V6lFNe0tLAuJMu+2sX+FcL14TaCWy1qiczg1VwRmPrpQCdq5ESXQMqUc2tluRNf6irBXrWbl1mGN8uaU/g==", "dev": true, + "license": "MIT", "dependencies": { - "type-fest": "^0.21.3" + "@noble/hashes": "1.7.2" }, "engines": { - "node": ">=8" + "node": "^14.21.3 || >=16" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://paulmillr.com/funding/" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/micro-eth-signer/node_modules/@noble/hashes": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.2.tgz", + "integrity": "sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/micro-packed": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/micro-packed/-/micro-packed-0.7.3.tgz", + "integrity": "sha512-2Milxs+WNC00TRlem41oRswvw31146GiSaoCT7s3Xi2gMUglW5QBeqlQaZeHr5tJx9nm3i57LNXPqxOOaWtTYg==", "dev": true, + "license": "MIT", "dependencies": { - "color-convert": "^1.9.0" + "@scure/base": "~1.2.5" }, - "engines": { - "node": ">=4" + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "node_modules/micro-packed/node_modules/@scure/base": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz", + "integrity": "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==", "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/base-x": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", - "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, - "dependencies": { - "safe-buffer": "^5.0.1" - } + "license": "MIT" }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "node_modules/p-map": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", + "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/blakejs": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", - "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==", - "dev": true - }, - "node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", - "dev": true - }, - "node_modules/boxen": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", - "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", "dev": true, - "dependencies": { - "ansi-align": "^3.0.0", - "camelcase": "^6.2.0", - "chalk": "^4.1.0", - "cli-boxes": "^2.2.1", - "string-width": "^4.2.2", - "type-fest": "^0.20.2", - "widest-line": "^3.1.0", - "wrap-ansi": "^7.0.0" - }, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">= 14.18.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, - "node_modules/boxen/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, + "license": "MIT", "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, - "node_modules/boxen/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/resolve.exports": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, + "license": "MIT", "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/boxen/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", "dev": true, - "dependencies": { - "color-name": "~1.1.4" + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=7.0.0" + "node": ">=10" } }, - "node_modules/boxen/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/boxen/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, "engines": { "node": ">=8" } }, - "node_modules/boxen/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/tsx": { + "version": "4.20.6", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.6.tgz", + "integrity": "sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==", "dev": true, + "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "esbuild": "~0.25.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" }, "engines": { - "node": ">=8" + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" } }, - "node_modules/boxen/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/undici": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.24.1.tgz", + "integrity": "sha512-sC+b0tB1whOCzbtlx20fx3WgCXwkW627p4EA9uM+/tNNPkSS+eSEld6pAs9nDv7WbY1UUljBMYPtu9BCOrCWKA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=18.17" } }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", - "dev": true - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true, - "dependencies": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", - "dev": true, - "dependencies": { - "base-x": "^3.0.2" - } - }, - "node_modules/bs58check": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", - "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", - "dev": true, - "dependencies": { - "bs58": "^4.0.0", - "create-hash": "^1.1.0", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", - "dev": true - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - }, - "node_modules/cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/command-exists": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", - "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", - "dev": true - }, - "node_modules/commander": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", - "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "node_modules/create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true, - "dependencies": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/enquirer": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", - "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", - "dev": true, - "dependencies": { - "ansi-colors": "^4.1.1", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/ethereum-cryptography": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz", - "integrity": "sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==", - "dev": true, - "dependencies": { - "@noble/hashes": "1.2.0", - "@noble/secp256k1": "1.7.1", - "@scure/bip32": "1.1.5", - "@scure/bip39": "1.1.1" - } - }, - "node_modules/ethereumjs-abi": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz", - "integrity": "sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.8", - "ethereumjs-util": "^6.0.0" - } - }, - "node_modules/ethereumjs-abi/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/ethereumjs-util": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", - "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "dev": true, - "dependencies": { - "@types/bn.js": "^4.11.3", - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "0.1.6", - "rlp": "^2.2.3" - } - }, - "node_modules/ethereumjs-util/node_modules/@types/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/ethereumjs-util/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/ethereumjs-util/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "dev": true, - "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" - } - }, - "node_modules/ethjs-util": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", - "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", - "dev": true, - "dependencies": { - "is-hex-prefixed": "1.0.0", - "strip-hex-prefix": "1.0.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, - "dependencies": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", - "dev": true, - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/fp-ts": { - "version": "1.19.3", - "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-1.19.3.tgz", - "integrity": "sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==", - "dev": true - }, - "node_modules/fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/hardhat": { - "version": "2.22.2", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.22.2.tgz", - "integrity": "sha512-0xZ7MdCZ5sJem4MrvpQWLR3R3zGDoHw5lsR+pBFimqwagimIOn3bWuZv69KA+veXClwI1s/zpqgwPwiFrd4Dxw==", - "dev": true, - "dependencies": { - "@ethersproject/abi": "^5.1.2", - "@metamask/eth-sig-util": "^4.0.0", - "@nomicfoundation/edr": "^0.3.1", - "@nomicfoundation/ethereumjs-common": "4.0.4", - "@nomicfoundation/ethereumjs-tx": "5.0.4", - "@nomicfoundation/ethereumjs-util": "9.0.4", - "@nomicfoundation/solidity-analyzer": "^0.1.0", - "@sentry/node": "^5.18.1", - "@types/bn.js": "^5.1.0", - "@types/lru-cache": "^5.1.0", - "adm-zip": "^0.4.16", - "aggregate-error": "^3.0.0", - "ansi-escapes": "^4.3.0", - "boxen": "^5.1.2", - "chalk": "^2.4.2", - "chokidar": "^3.4.0", - "ci-info": "^2.0.0", - "debug": "^4.1.1", - "enquirer": "^2.3.0", - "env-paths": "^2.2.0", - "ethereum-cryptography": "^1.0.3", - "ethereumjs-abi": "^0.6.8", - "find-up": "^2.1.0", - "fp-ts": "1.19.3", - "fs-extra": "^7.0.1", - "glob": "7.2.0", - "immutable": "^4.0.0-rc.12", - "io-ts": "1.10.4", - "keccak": "^3.0.2", - "lodash": "^4.17.11", - "mnemonist": "^0.38.0", - "mocha": "^10.0.0", - "p-map": "^4.0.0", - "raw-body": "^2.4.1", - "resolve": "1.17.0", - "semver": "^6.3.0", - "solc": "0.7.3", - "source-map-support": "^0.5.13", - "stacktrace-parser": "^0.1.10", - "tsort": "0.0.1", - "undici": "^5.14.0", - "uuid": "^8.3.2", - "ws": "^7.4.6" - }, - "bin": { - "hardhat": "internal/cli/bootstrap.js" - }, - "peerDependencies": { - "ts-node": "*", - "typescript": "*" - }, - "peerDependenciesMeta": { - "ts-node": { - "optional": true - }, - "typescript": { - "optional": true - } - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", - "dev": true, - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/immutable": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz", - "integrity": "sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==", - "dev": true - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/io-ts": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-1.10.4.tgz", - "integrity": "sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g==", - "dev": true, - "dependencies": { - "fp-ts": "^1.0.0" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-hex-prefixed": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", - "integrity": "sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==", - "dev": true, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/keccak": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.4.tgz", - "integrity": "sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/klaw": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", - "integrity": "sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.9" - } - }, - "node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", - "dev": true, - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/log-symbols/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/log-symbols/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lru_map": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", - "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==", - "dev": true - }, - "node_modules/md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dev": true, - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/memorystream": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", - "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", - "dev": true, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", - "dev": true - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mnemonist": { - "version": "0.38.5", - "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.5.tgz", - "integrity": "sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg==", - "dev": true, - "dependencies": { - "obliterator": "^2.0.0" - } - }, - "node_modules/mocha": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.4.0.tgz", - "integrity": "sha512-eqhGB8JKapEYcC4ytX/xrzKforgEc3j1pGlAXVy3eRwrtAy5/nIfT1SvgGzfN0XZZxeLq0aQWkOUAmqIJiv+bA==", - "dev": true, - "dependencies": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "8.1.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/mocha/node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/mocha/node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/mocha/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/mocha/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/node-addon-api": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", - "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", - "dev": true - }, - "node_modules/node-gyp-build": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.0.tgz", - "integrity": "sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==", - "dev": true, - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/obliterator": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz", - "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==", - "dev": true - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", - "dev": true, - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", - "dev": true, - "dependencies": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, - "dependencies": { - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/rlp": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.7.tgz", - "integrity": "sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==", - "dev": true, - "dependencies": { - "bn.js": "^5.2.0" - }, - "bin": { - "rlp": "bin/rlp" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/scrypt-js": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", - "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==", - "dev": true - }, - "node_modules/secp256k1": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.4.tgz", - "integrity": "sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "elliptic": "^6.5.7", - "node-addon-api": "^5.0.0", - "node-gyp-build": "^4.2.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/secp256k1/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/secp256k1/node_modules/elliptic": { - "version": "6.5.7", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.7.tgz", - "integrity": "sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/secp256k1/node_modules/node-addon-api": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", - "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", - "dev": true - }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "dev": true - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" - } - }, - "node_modules/solc": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/solc/-/solc-0.7.3.tgz", - "integrity": "sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA==", - "dev": true, - "dependencies": { - "command-exists": "^1.2.8", - "commander": "3.0.2", - "follow-redirects": "^1.12.1", - "fs-extra": "^0.30.0", - "js-sha3": "0.8.0", - "memorystream": "^0.3.1", - "require-from-string": "^2.0.0", - "semver": "^5.5.0", - "tmp": "0.0.33" - }, - "bin": { - "solcjs": "solcjs" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/solc/node_modules/fs-extra": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", - "integrity": "sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0", - "path-is-absolute": "^1.0.0", - "rimraf": "^2.2.8" - } - }, - "node_modules/solc/node_modules/jsonfile": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/solc/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/stacktrace-parser": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz", - "integrity": "sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==", - "dev": true, - "dependencies": { - "type-fest": "^0.7.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/stacktrace-parser/node_modules/type-fest": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", - "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-hex-prefix": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", - "integrity": "sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==", - "dev": true, - "dependencies": { - "is-hex-prefixed": "1.0.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "dependencies": { - "os-tmpdir": "~1.0.2" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/tsort": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/tsort/-/tsort-0.0.1.tgz", - "integrity": "sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==", - "dev": true - }, - "node_modules/tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", - "dev": true - }, - "node_modules/tweetnacl-util": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz", - "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==", - "dev": true - }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/undici": { - "version": "5.28.4", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", - "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", - "dev": true, - "dependencies": { - "@fastify/busboy": "^2.0.0" - }, - "engines": { - "node": ">=14.0" - } - }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true - }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", - "dev": true, - "dependencies": { - "string-width": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8.3.0" + "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { @@ -3474,67 +1307,14 @@ } } }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "dev": true, - "engines": { - "node": ">=10" - }, + "license": "MIT", "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/colinhacks" } } } diff --git a/contracts/package.json b/contracts/package.json index f6d6b8e3..3acaf6ee 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -4,7 +4,7 @@ "description": "A collection of smart contracts used in the development of the Cosmos EVM blockchain.", "devDependencies": { "@openzeppelin/contracts": "^4.9.6", - "hardhat": "^2.22.2" + "hardhat": "^3.0.15" }, "scripts": { "test": "echo \"Error: no test specified\" && exit 1" @@ -19,6 +19,7 @@ "url": "https://github.com/cosmos/evm/issues" }, "homepage": "https://github.com/cosmos/evm#readme", + "type": "module", "dependencies": { "@account-abstraction/contracts": "^0.6.0" } diff --git a/contracts/sequential_operations_tester.go b/contracts/sequential_operations_tester.go new file mode 100644 index 00000000..f3659e30 --- /dev/null +++ b/contracts/sequential_operations_tester.go @@ -0,0 +1,10 @@ +package contracts + +import ( + contractutils "github.com/cosmos/evm/contracts/utils" + evmtypes "github.com/cosmos/evm/x/vm/types" +) + +func LoadSequentialOperationsTester() (evmtypes.CompiledContract, error) { + return contractutils.LoadContractFromJSONFile("solidity/SequentialOperationsTester.json") +} diff --git a/contracts/solidity/ContractCreationTester.json b/contracts/solidity/ContractCreationTester.json new file mode 100644 index 00000000..561535a9 --- /dev/null +++ b/contracts/solidity/ContractCreationTester.json @@ -0,0 +1,285 @@ +{ + "_format": "hh3-artifact-1", + "contractName": "ContractCreationTester", + "sourceName": "solidity/ContractCreationTester.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contractAddr", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "ContractCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "operation", + "type": "string" + }, + { + "indexed": false, + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "name": "OperationCompleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ValueSent", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "creationValue", + "type": "uint256" + } + ], + "name": "createAndRevert", + "outputs": [ + { + "internalType": "contract SimpleReceiver", + "name": "", + "type": "address" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "createdContracts", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getCreatedContract", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCreatedContractsCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "validatorAddr", + "type": "string" + }, + { + "internalType": "uint256", + "name": "delegateAmount1", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "creationValue", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "delegateAmount2", + "type": "uint256" + } + ], + "name": "scenario4_delegateCreateDelegate", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "validatorAddr", + "type": "string" + }, + { + "internalType": "uint256", + "name": "delegateAmount1", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "creationValue", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "delegateAmount2", + "type": "uint256" + } + ], + "name": "scenario5_delegateCreateRevertDelegate", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "creationValue1", + "type": "uint256" + }, + { + "internalType": "string", + "name": "validatorAddr", + "type": "string" + }, + { + "internalType": "uint256", + "name": "delegateAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "creationValue2", + "type": "uint256" + } + ], + "name": "scenario6_createRevertDelegateCreateRevert", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "creationValue", + "type": "uint256" + }, + { + "internalType": "string", + "name": "validatorAddr", + "type": "string" + }, + { + "internalType": "uint256", + "name": "delegateAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sendAmount", + "type": "uint256" + } + ], + "name": "scenario7_createDelegateRevertSend", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "revertCreationValue", + "type": "uint256" + }, + { + "internalType": "string", + "name": "validatorAddr", + "type": "string" + }, + { + "internalType": "uint256", + "name": "delegateAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "successCreationValue", + "type": "uint256" + } + ], + "name": "scenario8_createRevertDelegateCreateSuccess", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x6080806040523461001657611004908161001b8239f35b5f80fdfe60406080815260048036101561001e575b5050361561001c575f80fd5b005b5f91823560e01c80630881139714610a9b5780637a0aaa5b146108a25780637d5b95391461076d578063aabf108614610595578063b203934e14610578578063c242737f146104fa578063c53e5ae31461044b578063e71b671a1461025e5763edab92991461008d5750610010565b61009636610bc9565b919290948451906353266bbb60e01b808352826100b96020978630868501610c1a565b0392868161080095818d885af1801561025457610237575b508651975f80516020610faf83398151915289806100ef839c610c74565b0390a187516101e9808201908282106001600160401b03831117610224579189818e9593829a99989795610da6833986815203019082f087816101e4575050508960808a518b815260068c8201526563726561746560d01b60608201528489820152a15b61016a895197889687958694855230908501610c1a565b03925af180156101da576101ac575b5050516040808252600990820152683232b632b3b0ba329960b91b60608201526001602082015280608081015b0390a180f35b816101cb92903d106101d3575b6101c38183610af5565b810190610c02565b505f80610179565b503d6101b9565b83513d87823e3d90fd5b6001600160a01b03909116915f80516020610f8f833981519152919061020984610c9f565b8c51908152a28989518061021c81610cda565b0390a1610153565b634e487b7160e01b8d526041865260248dfd5b61024d90873d89116101d3576101c38183610af5565b505f6100d1565b88513d8c823e3d90fd5b506102d761026b36610b8f565b93919085519163c53e5ae360e01b83528488840152602094838680826024829886305af18c928161041c575b506103cf575050505f80516020610faf8339815191528751806102b981610d4a565b0390a15b86516353266bbb60e01b81529384928392308b8501610c1a565b0381896108005af180156103c5576103a8575b508251935f80516020610faf83398151915285806103088398610d7b565b0390a18351906101e9808301918383106001600160401b03841117610395575083918391610da6833988815203019083f080156101da576001600160a01b0316915f80516020610f8f833981519152919061036284610c9f565b8451908152a25160408082526007908201526631b932b0ba329960c91b60608201526001602082015280608081016101a6565b634e487b7160e01b895260419052602488fd5b6103be90823d84116101d3576101c38183610af5565b505f6102ea565b84513d88823e3d90fd5b6001600160a01b03909116915f80516020610f8f83398151915291906103f484610c9f565b8a51908152a25f80516020610faf83398151915287518061041481610d21565b0390a16102bd565b61043d919350823d8411610444575b6104358183610af5565b810190610d02565b915f610297565b503d61042b565b508260203660031901126104f75781516101e9808201908282106001600160401b038311176104e4576020918391610da683398481520301908435f0156104d957815162461bcd60e51b8152602081850152602160248201527f496e74656e74696f6e616c20726576657274206166746572206372656174696f6044820152603760f91b6064820152608490fd5b9051903d90823e3d90fd5b634e487b7160e01b845260418652602484fd5b80fd5b50919034610574576020366003190112610574578035915482101561053b5760208361052584610ac9565b905491519160018060a01b039160031b1c168152f35b606490602084519162461bcd60e51b83528201526013602482015272496e646578206f7574206f6620626f756e647360681b6044820152fd5b5080fd5b838234610574578160031936011261057457602091549051908152f35b5061061290836105a436610b8f565b91959085519063c53e5ae360e01b97888352858a84015260209583878082602482988d305af18a928161074e575b50610701575050505f80516020610faf8339815191528851806105f481610d4a565b0390a15b87516353266bbb60e01b81529384928392308d8501610c1a565b0381876108005af180156106f7576106da575b50808451965f80516020610faf8339815191528880610644839b610d7b565b0390a18551968752860152818560248186305af1809584966106bb575b5061069657506080935060108351938085528401526f18dc99585d194c97dc995d995c9d195960821b6060840152820152a180f35b92936001600160a01b0316925f80516020610f8f833981519152925061036284610c9f565b6106d3919650833d8511610444576104358183610af5565b945f610661565b6106f090833d85116101d3576101c38183610af5565b505f610625565b85513d86823e3d90fd5b6001600160a01b03909116915f80516020610f8f833981519152919061072684610c9f565b8b51908152a25f80516020610faf83398151915288518061074681610d21565b0390a16105f8565b610766919350823d8411610444576104358183610af5565b915f6105d2565b509061077836610bc9565b90949283516353266bbb60e01b958682528161079a6020968530858501610c1a565b0391858161080094818d875af180156108985761087b575b508551965f80516020610faf83398151915288806107d0839b610c74565b0390a186516101e9808201908282106001600160401b0383111761086857828d9493928a92610da683398581520301908bf0998a1561085e575f80516020610f8f83398151915288809a9b9c60018060a09c9b9c1b03169261083184610c9f565b8c51908152a28989518061084481610cda565b0390a161016a895197889687958694855230908501610c1a565b88513d84823e3d90fd5b634e487b7160e01b8d526041855260248dfd5b61089190863d88116101d3576101c38183610af5565b505f6107b2565b87513d8c823e3d90fd5b506108ac36610b8f565b908495929551936101e9808601908682106001600160401b03831117610a8857908691610da68339898152602096879103019082f08015610a7e576001600160a01b031692916109559186919085905f80516020610f8f83398151915290849061091584610c9f565b8b51908152a28751985f80516020610faf8339815191528a80610938839d610cda565b0390a188516353266bbb60e01b81529384928392308a8501610c1a565b03818b6108005af19081610a61575b50610a4c5785608086518781526008888201526764656c656761746560c01b60608201528987820152a15b8680808084865af13d15610a47573d6109a781610b2a565b906109b488519283610af5565b815288863d92013e5b15610a10579183917ffb17d0033e42e6a76759d2c7c2795a304dfbba80679160ae60dc91aad4966e52869560019560809851908152a2835193808552840152631cd95b9960e21b6060840152820152a180f35b845162461bcd60e51b8152808401859052601160248201527015985b1d59481cd95b990819985a5b1959607a1b6044820152606490fd5b6109bd565b85855180610a5981610d7b565b0390a161098f565b610a7790863d88116101d3576101c38183610af5565b505f610964565b86513d8a823e3d90fd5b634e487b7160e01b8a526041865260248afd5b509034610ac5576020366003190112610ac557359180548310156104f75750610525602092610ac9565b8280fd5b905f918254811015610ae15782805260208320019190565b634e487b7160e01b83526032600452602483fd5b90601f801991011681019081106001600160401b03821117610b1657604052565b634e487b7160e01b5f52604160045260245ffd5b6001600160401b038111610b1657601f01601f191660200190565b81601f82011215610b8b57803590610b5c82610b2a565b92610b6a6040519485610af5565b82845260208383010111610b8b57815f926020809301838601378301015290565b5f80fd5b906080600319830112610b8b5760043591602435906001600160401b038211610b8b57610bbe91600401610b45565b906044359060643590565b6080600319820112610b8b57600435906001600160401b038211610b8b57610bf391600401610b45565b90602435906044359060643590565b90816020910312610b8b57518015158103610b8b5790565b9392919060018060a01b0316845260206060818601528151918260608701525f5b838110610c60575050506080815f8260409488010152601f8019910116850101930152565b818101830151878201608001528201610c3b565b9060408252600960408301526864656c65676174653160b81b60608301526001602060808401930152565b5f54600160401b811015610b1657806001610cbc92015f55610ac9565b819291549060031b9160018060a01b03809116831b921b1916179055565b9060408252600660408301526563726561746560d01b60608301526001602060808401930152565b90816020910312610b8b57516001600160a01b0381168103610b8b5790565b906040825260076040830152666372656174653160c81b60608301526001602060808401930152565b9060408252601060408301526f18dc99585d194c57dc995d995c9d195960821b60608301525f602060808401930152565b9060408252600860408301526764656c656761746560c01b6060830152600160206080840193015256fe6080601f6101e938819003918201601f19168301916001600160401b038311848410176100de578084926020946040528339810103126100da575180151581036100da57610095573360018060a01b03196001541617600155345f556040513481527fb263f5c1dda4b5b44a8d5658a105c64b6ec61c79463b79a1d0052a834d00fdc460203392a260405160f690816100f38239f35b60405162461bcd60e51b815260206004820152601e60248201527f496e74656e74696f6e616c20636f6e7374727563746f722072657665727400006044820152606490fd5b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe6080806040526004361015603b575b5036156018575f80fd5b5f543481018091116027575f55005b634e487b7160e01b5f52601160045260245ffd5b5f90813560e01c90816302d05d3f146099575080632096525514607e57633fa4f24503600e5734607b5780600319360112607b5760209054604051908152f35b80fd5b5034607b5780600319360112607b5760209054604051908152f35b90503460bc578160031936011260bc576001546001600160a01b03168152602090f35b5080fdfea2646970667358221220ce8e9db4668f7bbb9824eaabdca215a30e571bb0f48c2cb0f698a8e8abc681ae64736f6c634300081400331dc05c1d6a563dddb6c22082af72b54ec2f0207ceb55db5d13cdabc208f303a99f4d25774676d497fe3d8c1e43709b68b186fad01b05798c1410a178ff4ed7d0a264697066735822122054c08ab623063accdd988fb07fb40e2096d7699b58c373540b6cebeb2760914164736f6c63430008140033", + "deployedBytecode": "0x60406080815260048036101561001e575b5050361561001c575f80fd5b005b5f91823560e01c80630881139714610a9b5780637a0aaa5b146108a25780637d5b95391461076d578063aabf108614610595578063b203934e14610578578063c242737f146104fa578063c53e5ae31461044b578063e71b671a1461025e5763edab92991461008d5750610010565b61009636610bc9565b919290948451906353266bbb60e01b808352826100b96020978630868501610c1a565b0392868161080095818d885af1801561025457610237575b508651975f80516020610faf83398151915289806100ef839c610c74565b0390a187516101e9808201908282106001600160401b03831117610224579189818e9593829a99989795610da6833986815203019082f087816101e4575050508960808a518b815260068c8201526563726561746560d01b60608201528489820152a15b61016a895197889687958694855230908501610c1a565b03925af180156101da576101ac575b5050516040808252600990820152683232b632b3b0ba329960b91b60608201526001602082015280608081015b0390a180f35b816101cb92903d106101d3575b6101c38183610af5565b810190610c02565b505f80610179565b503d6101b9565b83513d87823e3d90fd5b6001600160a01b03909116915f80516020610f8f833981519152919061020984610c9f565b8c51908152a28989518061021c81610cda565b0390a1610153565b634e487b7160e01b8d526041865260248dfd5b61024d90873d89116101d3576101c38183610af5565b505f6100d1565b88513d8c823e3d90fd5b506102d761026b36610b8f565b93919085519163c53e5ae360e01b83528488840152602094838680826024829886305af18c928161041c575b506103cf575050505f80516020610faf8339815191528751806102b981610d4a565b0390a15b86516353266bbb60e01b81529384928392308b8501610c1a565b0381896108005af180156103c5576103a8575b508251935f80516020610faf83398151915285806103088398610d7b565b0390a18351906101e9808301918383106001600160401b03841117610395575083918391610da6833988815203019083f080156101da576001600160a01b0316915f80516020610f8f833981519152919061036284610c9f565b8451908152a25160408082526007908201526631b932b0ba329960c91b60608201526001602082015280608081016101a6565b634e487b7160e01b895260419052602488fd5b6103be90823d84116101d3576101c38183610af5565b505f6102ea565b84513d88823e3d90fd5b6001600160a01b03909116915f80516020610f8f83398151915291906103f484610c9f565b8a51908152a25f80516020610faf83398151915287518061041481610d21565b0390a16102bd565b61043d919350823d8411610444575b6104358183610af5565b810190610d02565b915f610297565b503d61042b565b508260203660031901126104f75781516101e9808201908282106001600160401b038311176104e4576020918391610da683398481520301908435f0156104d957815162461bcd60e51b8152602081850152602160248201527f496e74656e74696f6e616c20726576657274206166746572206372656174696f6044820152603760f91b6064820152608490fd5b9051903d90823e3d90fd5b634e487b7160e01b845260418652602484fd5b80fd5b50919034610574576020366003190112610574578035915482101561053b5760208361052584610ac9565b905491519160018060a01b039160031b1c168152f35b606490602084519162461bcd60e51b83528201526013602482015272496e646578206f7574206f6620626f756e647360681b6044820152fd5b5080fd5b838234610574578160031936011261057457602091549051908152f35b5061061290836105a436610b8f565b91959085519063c53e5ae360e01b97888352858a84015260209583878082602482988d305af18a928161074e575b50610701575050505f80516020610faf8339815191528851806105f481610d4a565b0390a15b87516353266bbb60e01b81529384928392308d8501610c1a565b0381876108005af180156106f7576106da575b50808451965f80516020610faf8339815191528880610644839b610d7b565b0390a18551968752860152818560248186305af1809584966106bb575b5061069657506080935060108351938085528401526f18dc99585d194c97dc995d995c9d195960821b6060840152820152a180f35b92936001600160a01b0316925f80516020610f8f833981519152925061036284610c9f565b6106d3919650833d8511610444576104358183610af5565b945f610661565b6106f090833d85116101d3576101c38183610af5565b505f610625565b85513d86823e3d90fd5b6001600160a01b03909116915f80516020610f8f833981519152919061072684610c9f565b8b51908152a25f80516020610faf83398151915288518061074681610d21565b0390a16105f8565b610766919350823d8411610444576104358183610af5565b915f6105d2565b509061077836610bc9565b90949283516353266bbb60e01b958682528161079a6020968530858501610c1a565b0391858161080094818d875af180156108985761087b575b508551965f80516020610faf83398151915288806107d0839b610c74565b0390a186516101e9808201908282106001600160401b0383111761086857828d9493928a92610da683398581520301908bf0998a1561085e575f80516020610f8f83398151915288809a9b9c60018060a09c9b9c1b03169261083184610c9f565b8c51908152a28989518061084481610cda565b0390a161016a895197889687958694855230908501610c1a565b88513d84823e3d90fd5b634e487b7160e01b8d526041855260248dfd5b61089190863d88116101d3576101c38183610af5565b505f6107b2565b87513d8c823e3d90fd5b506108ac36610b8f565b908495929551936101e9808601908682106001600160401b03831117610a8857908691610da68339898152602096879103019082f08015610a7e576001600160a01b031692916109559186919085905f80516020610f8f83398151915290849061091584610c9f565b8b51908152a28751985f80516020610faf8339815191528a80610938839d610cda565b0390a188516353266bbb60e01b81529384928392308a8501610c1a565b03818b6108005af19081610a61575b50610a4c5785608086518781526008888201526764656c656761746560c01b60608201528987820152a15b8680808084865af13d15610a47573d6109a781610b2a565b906109b488519283610af5565b815288863d92013e5b15610a10579183917ffb17d0033e42e6a76759d2c7c2795a304dfbba80679160ae60dc91aad4966e52869560019560809851908152a2835193808552840152631cd95b9960e21b6060840152820152a180f35b845162461bcd60e51b8152808401859052601160248201527015985b1d59481cd95b990819985a5b1959607a1b6044820152606490fd5b6109bd565b85855180610a5981610d7b565b0390a161098f565b610a7790863d88116101d3576101c38183610af5565b505f610964565b86513d8a823e3d90fd5b634e487b7160e01b8a526041865260248afd5b509034610ac5576020366003190112610ac557359180548310156104f75750610525602092610ac9565b8280fd5b905f918254811015610ae15782805260208320019190565b634e487b7160e01b83526032600452602483fd5b90601f801991011681019081106001600160401b03821117610b1657604052565b634e487b7160e01b5f52604160045260245ffd5b6001600160401b038111610b1657601f01601f191660200190565b81601f82011215610b8b57803590610b5c82610b2a565b92610b6a6040519485610af5565b82845260208383010111610b8b57815f926020809301838601378301015290565b5f80fd5b906080600319830112610b8b5760043591602435906001600160401b038211610b8b57610bbe91600401610b45565b906044359060643590565b6080600319820112610b8b57600435906001600160401b038211610b8b57610bf391600401610b45565b90602435906044359060643590565b90816020910312610b8b57518015158103610b8b5790565b9392919060018060a01b0316845260206060818601528151918260608701525f5b838110610c60575050506080815f8260409488010152601f8019910116850101930152565b818101830151878201608001528201610c3b565b9060408252600960408301526864656c65676174653160b81b60608301526001602060808401930152565b5f54600160401b811015610b1657806001610cbc92015f55610ac9565b819291549060031b9160018060a01b03809116831b921b1916179055565b9060408252600660408301526563726561746560d01b60608301526001602060808401930152565b90816020910312610b8b57516001600160a01b0381168103610b8b5790565b906040825260076040830152666372656174653160c81b60608301526001602060808401930152565b9060408252601060408301526f18dc99585d194c57dc995d995c9d195960821b60608301525f602060808401930152565b9060408252600860408301526764656c656761746560c01b6060830152600160206080840193015256fe6080601f6101e938819003918201601f19168301916001600160401b038311848410176100de578084926020946040528339810103126100da575180151581036100da57610095573360018060a01b03196001541617600155345f556040513481527fb263f5c1dda4b5b44a8d5658a105c64b6ec61c79463b79a1d0052a834d00fdc460203392a260405160f690816100f38239f35b60405162461bcd60e51b815260206004820152601e60248201527f496e74656e74696f6e616c20636f6e7374727563746f722072657665727400006044820152606490fd5b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe6080806040526004361015603b575b5036156018575f80fd5b5f543481018091116027575f55005b634e487b7160e01b5f52601160045260245ffd5b5f90813560e01c90816302d05d3f146099575080632096525514607e57633fa4f24503600e5734607b5780600319360112607b5760209054604051908152f35b80fd5b5034607b5780600319360112607b5760209054604051908152f35b90503460bc578160031936011260bc576001546001600160a01b03168152602090f35b5080fdfea2646970667358221220ce8e9db4668f7bbb9824eaabdca215a30e571bb0f48c2cb0f698a8e8abc681ae64736f6c634300081400331dc05c1d6a563dddb6c22082af72b54ec2f0207ceb55db5d13cdabc208f303a99f4d25774676d497fe3d8c1e43709b68b186fad01b05798c1410a178ff4ed7d0a264697066735822122054c08ab623063accdd988fb07fb40e2096d7699b58c373540b6cebeb2760914164736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": {}, + "inputSourceName": "project/solidity/ContractCreationTester.sol", + "buildInfoId": "solc-0_8_20-a1f91ec3b065d50730c0367f861277c93634d90c" +} \ No newline at end of file diff --git a/contracts/solidity/ContractCreationTester.sol b/contracts/solidity/ContractCreationTester.sol new file mode 100644 index 00000000..b66b6ce3 --- /dev/null +++ b/contracts/solidity/ContractCreationTester.sol @@ -0,0 +1,236 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "./precompiles/staking/StakingI.sol"; +import "./precompiles/common/Types.sol"; + +/** + * @dev Simple contract that can be created and receive value + */ +contract SimpleReceiver { + uint256 public value; + address public creator; + + event ReceiverCreated(address indexed creator, uint256 initialValue); + + constructor(bool shouldRevert) payable { + if (shouldRevert) { + revert("Intentional constructor revert"); + } + creator = msg.sender; + value = msg.value; + emit ReceiverCreated(msg.sender, msg.value); + } + + receive() external payable { + value += msg.value; + } + + function getValue() external view returns (uint256) { + return value; + } +} + +/** + * @dev Contract to test contract creation with precompile calls + * Tests scenarios 4-7 with various combinations of CREATE and precompile operations + */ +contract ContractCreationTester { + event OperationCompleted(string operation, bool success); + event ContractCreated(address indexed contractAddr, uint256 value); + event ValueSent(address indexed recipient, uint256 amount); + + address[] public createdContracts; + + /// @dev Helper function that creates a contract and then reverts + /// @dev Used for testing reverted contract creation scenarios + function createAndRevert(uint256 creationValue) public payable returns (SimpleReceiver) { + SimpleReceiver newContract = new SimpleReceiver{value: creationValue}(false); + revert("Intentional revert after creation"); + } + + /// @dev Scenario 4: Precompile -> Create Contract -> Precompile + function scenario4_delegateCreateDelegate( + string memory validatorAddr, + uint256 delegateAmount1, + uint256 creationValue, + uint256 delegateAmount2 + ) external payable { + // 1. Precompile call (delegate) - convert from wei to base denom + uint256 delegateAmount1BaseDenom = delegateAmount1; + STAKING_CONTRACT.delegate( + address(this), + validatorAddr, + delegateAmount1BaseDenom + ); + emit OperationCompleted("delegate1", true); + + // 2. Create another contract with value (shouldRevert = false) + SimpleReceiver newContract = new SimpleReceiver{value: creationValue}(false); + createdContracts.push(address(newContract)); + emit ContractCreated(address(newContract), creationValue); + emit OperationCompleted("create", true); + + // 3. Precompile call (delegate again) - convert from wei to base denom + uint256 delegateAmount2BaseDenom = delegateAmount2; + STAKING_CONTRACT.delegate( + address(this), + validatorAddr, + delegateAmount2BaseDenom + ); + emit OperationCompleted("delegate2", true); + } + + /// @dev Scenario 5: Precompile -> Create Contract (reverted & caught) -> Precompile + function scenario5_delegateCreateRevertDelegate( + string memory validatorAddr, + uint256 delegateAmount1, + uint256 creationValue, + uint256 delegateAmount2 + ) external payable { + // 1. Precompile call (delegate) - convert from wei to base denom + uint256 delegateAmount1BaseDenom = delegateAmount1; + STAKING_CONTRACT.delegate( + address(this), + validatorAddr, + delegateAmount1BaseDenom + ); + emit OperationCompleted("delegate1", true); + + // 2. Try to create contract (will revert if insufficient value, catch it) + try new SimpleReceiver{value: creationValue}(false) returns (SimpleReceiver newContract) { + createdContracts.push(address(newContract)); + emit ContractCreated(address(newContract), creationValue); + emit OperationCompleted("create", true); + } catch { + emit OperationCompleted("create", false); + } + + // 3. Precompile call (delegate again) - convert from wei to base denom + uint256 delegateAmount2BaseDenom = delegateAmount2; + STAKING_CONTRACT.delegate( + address(this), + validatorAddr, + delegateAmount2BaseDenom + ); + emit OperationCompleted("delegate2", true); + } + + /// @dev Scenario 6: Create+Revert (caught) -> Precompile -> Create+Revert (caught) + /// @dev Creates fail because the helper function reverts after creation, testing auto-flush with reverted creations + function scenario6_createRevertDelegateCreateRevert( + uint256 creationValue1, + string memory validatorAddr, + uint256 delegateAmount, + uint256 creationValue2 + ) external payable { + // 1. Try to create contract (will revert after creation, catch it) + try this.createAndRevert(creationValue1) returns (SimpleReceiver newContract1) { + // This won't execute because createAndRevert reverts + createdContracts.push(address(newContract1)); + emit ContractCreated(address(newContract1), creationValue1); + emit OperationCompleted("create1", true); + } catch { + emit OperationCompleted("create1_reverted", false); + } + + // 2. Precompile call - convert from wei to base denom + uint256 delegateAmountBaseDenom = delegateAmount; + STAKING_CONTRACT.delegate( + address(this), + validatorAddr, + delegateAmountBaseDenom + ); + emit OperationCompleted("delegate", true); + + // 3. Try to create contract again (will revert after creation, catch it) + try this.createAndRevert(creationValue2) returns (SimpleReceiver newContract2) { + // This won't execute because createAndRevert reverts + createdContracts.push(address(newContract2)); + emit ContractCreated(address(newContract2), creationValue2); + emit OperationCompleted("create2", true); + } catch { + emit OperationCompleted("create2_reverted", false); + } + } + + /// @dev Scenario 7: Create+Send -> Precompile (reverted & caught) -> Send more + function scenario7_createDelegateRevertSend( + uint256 creationValue, + string memory validatorAddr, + uint256 delegateAmount, + uint256 sendAmount + ) external payable { + // 1. Create contract and send it value (shouldRevert = false) + SimpleReceiver newContract = new SimpleReceiver{value: creationValue}(false); + createdContracts.push(address(newContract)); + emit ContractCreated(address(newContract), creationValue); + emit OperationCompleted("create", true); + + // 2. Precompile call (delegate) - convert from wei to base denom, reverted and caught + uint256 delegateAmountBaseDenom = delegateAmount; + try STAKING_CONTRACT.delegate( + address(this), + validatorAddr, + delegateAmountBaseDenom + ) { + emit OperationCompleted("delegate", true); + } catch { + emit OperationCompleted("delegate", false); + } + + // 3. Send more value to the created contract + (bool success, ) = address(newContract).call{value: sendAmount}(""); + require(success, "Value send failed"); + emit ValueSent(address(newContract), sendAmount); + emit OperationCompleted("send", true); + } + + /// @dev Scenario 8: Create+Revert (caught) -> Delegate -> Create+Success + /// @dev Tests that reverted creation doesn't prevent successful creation after delegation + function scenario8_createRevertDelegateCreateSuccess( + uint256 revertCreationValue, + string memory validatorAddr, + uint256 delegateAmount, + uint256 successCreationValue + ) external payable { + // 1. Try to create contract (will revert after creation, catch it) + try this.createAndRevert{value: revertCreationValue} + (revertCreationValue) returns (SimpleReceiver newContract1) { + // This won't execute because createAndRevert reverts + createdContracts.push(address(newContract1)); + emit ContractCreated(address(newContract1), revertCreationValue); + emit OperationCompleted("create1", true); + } catch { + emit OperationCompleted("create1_reverted", false); + } + + // 2. Precompile call - convert from wei to base denom + uint256 delegateAmountBaseDenom = delegateAmount; + STAKING_CONTRACT.delegate( + address(this), + validatorAddr, + delegateAmountBaseDenom + ); + emit OperationCompleted("delegate", true); + + // 3. Create contract successfully (shouldRevert = false) + SimpleReceiver newContract2 = new SimpleReceiver{value: successCreationValue}(false); + createdContracts.push(address(newContract2)); + emit ContractCreated(address(newContract2), successCreationValue); + emit OperationCompleted("create2", true); + } + + /// @dev Get count of created contracts + function getCreatedContractsCount() external view returns (uint256) { + return createdContracts.length; + } + + /// @dev Get created contract at index + function getCreatedContract(uint256 index) external view returns (address) { + require(index < createdContracts.length, "Index out of bounds"); + return createdContracts[index]; + } + + receive() external payable {} +} diff --git a/contracts/solidity/ERC20WithNativeTransfers.json b/contracts/solidity/ERC20WithNativeTransfers.json new file mode 100644 index 00000000..6d6ab695 --- /dev/null +++ b/contracts/solidity/ERC20WithNativeTransfers.json @@ -0,0 +1,813 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC20WithNativeTransfers", + "sourceName": "solidity/ERC20WithNativeTransfers.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "BeforeTransferHookTriggered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "available", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ContractBalanceCheck", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "DelegateCompleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "step", + "type": "uint256" + } + ], + "name": "NativeTransferCompleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MINTER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_recipient1", + "type": "address" + }, + { + "internalType": "address", + "name": "_recipient2", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_transferAmount", + "type": "uint256" + }, + { + "internalType": "string", + "name": "_validatorAddr", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_delegateAmount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "_enableHook", + "type": "bool" + } + ], + "name": "configureHook", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "delegateAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "enableHook", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "recipient1", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "recipient2", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "transferAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "validatorAddr", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x604060808152346200043857620027cc803803806200001e816200043d565b9283398101606082820312620004385781516001600160401b0391908281116200043857816200005091850162000463565b9160209182850151828111620004385786916200006f91870162000463565b9401519360ff8516809503620004385783518281116200034f576005918254916001968784811c941680156200042d575b878510146200032e578190601f94858111620003d9575b508790858311600114620003715760009262000365575b5050600019600383901b1c191690871b1783555b80519384116200034f576006548681811c9116801562000344575b868210146200032e578493838211620002d4575b5050849183116001146200026a576000926200025e575b5050600019600383901b1c191690831b176006555b60008052600081528360002033600052815260ff8460002054161562000221575b60008052818152620001743385600020620004d5565b507f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a680600052600082528460002033600052825260ff85600020541615620001e4575b60005252620001ca3383600020620004d5565b5060ff196007541617600755516122499081620005638239f35b806000526000825284600020336000528252846000208360ff19825416179055333382600080516020620027ac833981519152600080a4620001b7565b600080526000815283600020336000528152836000208260ff1982541617905533336000600080516020620027ac8339815191528180a46200015e565b01519050388062000128565b90859350601f198316916006600052856000209260005b87828210620002bd5750508411620002a3575b505050811b016006556200013d565b015160001960f88460031b161c1916905538808062000294565b838501518655899790950194938401930162000281565b90919293506006600052856000209084808701821c83019388881062000324575b9187968a93969594929601901c01915b82811062000314575062000111565b6000815586955088910162000305565b93508293620002f5565b634e487b7160e01b600052602260045260246000fd5b90607f1690620000fd565b634e487b7160e01b600052604160045260246000fd5b015190503880620000ce565b90899350601f1983169187600052896000209260005b8b828210620003c25750508411620003a8575b505050811b018355620000e2565b015160001960f88460031b161c191690553880806200039a565b8385015186558d9790950194938401930162000387565b909150856000528760002085808501881c8201928a861062000423575b918b918695949301891c01915b82811062000413575050620000b7565b600081558594508b910162000403565b92508192620003f6565b93607f1693620000a0565b600080fd5b6040519190601f01601f191682016001600160401b038111838210176200034f57604052565b919080601f84011215620004385782516001600160401b0381116200034f5760209062000499601f8201601f191683016200043d565b92818452828287010111620004385760005b818110620004c157508260009394955001015290565b8581018301518482018401528201620004ab565b919060018301600090828252806020526040822054156000146200055c57845494680100000000000000008610156200054857600186018082558610156200053457836040949596828552602085200155549382526020522055600190565b634e487b7160e01b83526032600452602483fd5b634e487b7160e01b83526041600452602483fd5b5092505056fe6080604081815260049182361015610022575b505050361561002057600080fd5b005b600092833560e01c91826301ffc9a714610fe3575081630688b13514610fba57816306fdde0314610f14578163095ea7b314610eea57816318160ddd14610ecc57816323b872dd14610e8f578163248a9ca314610e655781632f2ff15d14610db1578163313ce56714610d8f57816336568abe14610cfd5781633950935114610cad57816340c10f191461083e57816342966c6814610820578163504d27fd1461080157816370a08231146107c957816379cc6790146107995781639010d07c1461075857816391d148541461071257816395d89b41146106435781639f35c7e714610609578163a217fddf146105ee578163a457c2d714610546578163a9059cbb14610515578163aa3744bd146104e8578163b64bdb34146104c9578163ba84e217146104a5578163bd3fddd714610277578163ca15c8731461024f578163d539139314610214578163d547741f146101d2575063dd62ed3e146101875780610012565b346101ce57806003193601126101ce57806020926101a361109f565b6101ab6110ba565b6001600160a01b0391821683526003865283832091168252845220549051908152f35b5080fd5b9190503461021057806003193601126102105761020d913561020860016101f76110ba565b9383875286602052862001546111c7565b6114ef565b80f35b8280fd5b5050346101ce57816003193601126101ce57602090517f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a68152f35b9050346102105760203660031901126102105760209282913581526001845220549051908152f35b839150346101ce5760c03660031901126101ce5761029361109f565b61029b6110ba565b9060643567ffffffffffffffff928382116104a157366023830112156104a157818501359384116104a1576024923684868501011161049d5760a4359586151580970361049957878052602098888a52808920338a528a5260ff818a2054161561046157505060078054610100600160a81b031916600892831b610100600160a81b031617905580546001600160a01b0319166001600160a01b0392909216919091179055604435600955600a54610352906110d0565b601f811161041d575b508495601f84116001146103b15750948495839495936103a4575b5050508160011b916000199060031b1c191617600a555b608435600b5560ff8019600c5416911617600c5580f35b0101359050848080610376565b91601f19841696600a87528387209387905b898210610403575050846001969798106103e7575b50505050811b01600a5561038d565b60001960f88660031b161c1992010135169055848080806103d8565b8060018497868395968901013581550196019201906103c3565b600a8652868620601f850160051c810191888610610457575b601f0160051c01905b81811061044c575061035b565b86815560010161043f565b9091508190610436565b5162461bcd60e51b8152908101899052601481860152734d75737420686176652061646d696e20726f6c6560601b6044820152606490fd5b8780fd5b8680fd5b8580fd5b5050346101ce57816003193601126101ce5760209060ff600c541690519015158152f35b5050346101ce57816003193601126101ce57602090600b549051908152f35b5050346101ce57816003193601126101ce57600754905160089190911c6001600160a01b03168152602090f35b5050346101ce57806003193601126101ce5760209061053f61053561109f565b6024359033611599565b5160018152f35b905082346105eb57826003193601126105eb5761056161109f565b918360243592338152600360205281812060018060a01b038616825260205220549082821061059a5760208561053f8585038733611a14565b608490602086519162461bcd60e51b8352820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152fd5b80fd5b5050346101ce57816003193601126101ce5751908152602090f35b5050346101ce57816003193601126101ce57805161063f916106358261062e8161110a565b038361118f565b5191829182611073565b0390f35b5050346101ce57816003193601126101ce5780519082600654610665816110d0565b808552906001908181169081156106ea5750600114610691575b5050506106358261063f94038361118f565b60068352602095507ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f5b8284106106d7575050508261063f94610635928201019461067f565b80548685018801529286019281016106bb565b61063f97506106359450602092508693915060ff191682840152151560051b8201019461067f565b9050346102105781600319360112610210578160209360ff926107336110ba565b903582528186528282206001600160a01b039091168252855220549151911615158152f35b9050346102105781600319360112610210576020926107839135815260018452826024359120611f7a565b905491519160018060a01b039160031b1c168152f35b5050346101ce573660031901126105eb5761020d6107b561109f565b602435906107c4823383611b16565b611bae565b5050346101ce5760203660031901126101ce5760209181906001600160a01b036107f161109f565b1681526002845220549051908152f35b5050346101ce57816003193601126101ce576020906009549051908152f35b8390346101ce5760203660031901126101ce5761020d903533611bae565b90503461021057816003193601126102105761085861109f565b906024928335917f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a68652602093868552828720338852855260ff838820541615610c6c576001600160a01b03908116958615610c2b5760ff600c541680610c24575b80610c1c575b610900575b505091859391836108e6836000805160206121948339815191529654611576565b90558585526002835280852082815401905551908152a380f35b60008051602061213483398151915260608593999897959694965189815288878201528585820152a16009548015801580610bff575b610a6e575b5050869750600b969495965480151580610a5b575b610961575b508193959294506108c5565b909193809693955084518080936353266bbb60e01b8252308783015260608683015261098f6064830161110a565b90604483015203818b6108005af1908115610a51578891610a1b575b50156109e75750918391600080516020612194833981519152936000805160206121f48339815191528896600b548451908152a1949338610955565b60119085606494519362461bcd60e51b85528401528201527011195b1959d85d1a5bdb8819985a5b1959607a1b6044820152fd5b90508581813d8311610a4a575b610a32818361118f565b810103126104995751801515810361049957386109ab565b503d610a28565b84513d8a823e3d90fd5b50610a67600a546110d0565b1515610950565b8160011b908282046002141715610bed5747600080516020612154833981519152858051838152848a820152a110610ba25787808080938c60075460081c165af1610ab76120f3565b5015610b61576060878080808c60075460081c16600954908851908152818b820152600189820152600080516020612174833981519152968791a18d600854165af1610b016120f3565b5015610b3157606088996008999798995416600954855191825287820152600285820152a138809796959761093b565b825162461bcd60e51b8152808701869052601d818401526000805160206121d48339815191526044820152606490fd5b601c859185606494519362461bcd60e51b85528401528201527f4669727374206e6174697665207472616e73666572206661696c6564000000006044820152fd5b825162461bcd60e51b81528087018690526032818401526000805160206121b483398151915260448201527172206e6174697665207472616e736665727360701b6064820152608490fd5b634e487b7160e01b8952601187528289fd5b5060075460081c8a16151580610936575089600854161515610936565b5060016108c0565b50876108ba565b601f915085606494519362461bcd60e51b85528401528201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152fd5b50601d8585606494519362461bcd60e51b85528401528201527f4d7573742068617665206d696e74657220726f6c6520746f206d696e740000006044820152fd5b5050346101ce57806003193601126101ce5761053f602092610cf6610cd061109f565b338352600386528483206001600160a01b03821684528652918490205460243590611576565b9033611a14565b839150346101ce57826003193601126101ce57610d186110ba565b90336001600160a01b03831603610d34579061020d91356114ef565b608490602085519162461bcd60e51b8352820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152fd5b5050346101ce57816003193601126101ce5760209060ff600754169051908152f35b91905034610210578060031936011261021057610e1a9135906001610dd46110ba565b92808652602090868252610dec8385892001546111c7565b80875286825283872094838060a01b031694858852825260ff848820541615610e1e575b8652528320611f92565b5080f35b8087528682528387208588528252838720805460ff1916841790553385827f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d8a80a4610e10565b90503461021057602036600319011261021057816020936001923581528085522001549051908152f35b5050346101ce5760603660031901126101ce5760209061053f610eb061109f565b610eb86110ba565b60443591610ec7833383611b16565b611599565b90503461021057826003193601126102105760209250549051908152f35b5050346101ce57806003193601126101ce5760209061053f610f0a61109f565b6024359033611a14565b5050346101ce57816003193601126101ce5780519082600554610f36816110d0565b808552906001908181169081156106ea5750600114610f61575050506106358261063f94038361118f565b60058352602095507f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db05b828410610fa7575050508261063f94610635928201019461067f565b8054868501880152928601928101610f8b565b5050346101ce57816003193601126101ce5760085490516001600160a01b039091168152602090f35b849134610210576020366003190112610210573563ffffffff60e01b81168091036102105760209250635a05180f60e01b8114908115611025575b5015158152f35b637965db0b60e01b81149150811561103f575b508361101e565b6301ffc9a760e01b14905083611038565b60005b8381106110635750506000910152565b8181015183820152602001611053565b604091602082526110938151809281602086015260208686019101611050565b601f01601f1916010190565b600435906001600160a01b03821682036110b557565b600080fd5b602435906001600160a01b03821682036110b557565b90600182811c92168015611100575b60208310146110ea57565b634e487b7160e01b600052602260045260246000fd5b91607f16916110df565b600a546000929161111a826110d0565b908181526001928381169081600014611174575060011461113a57505050565b90929350600a6000526020928360002092846000945b8386106111605750505050010190565b805485870183015294019385908201611150565b91935050602093945060ff191683830152151560051b010190565b90601f8019910116810190811067ffffffffffffffff8211176111b157604052565b634e487b7160e01b600052604160045260246000fd5b6000818152602090808252604092838220338352835260ff8483205416156111ef5750505050565b835167ffffffffffffffff91903360608201848111838210176114db578752602a825285820192873685378251156114c757603084538251916001928310156114b3576078602185015360295b838111611449575061140757908751946080860190868210908211176113f3578852604285528685019560603688378551156113df576030875385518210156113df5790607860218701536041915b8183116113715750505061132f57938593611315936113066048946112dd76020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b9961132b9b519a8b978801525180926037880190611050565b8401917001034b99036b4b9b9b4b733903937b6329607d1b603784015251809386840190611050565b0103602881018552018361118f565b5162461bcd60e51b815291829160048301611073565b0390fd5b60648587519062461bcd60e51b825280600483015260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152fd5b909192600f811660108110156113cb576f181899199a1a9b1b9c1cb0b131b232b360811b901a6113a18589611f53565b5360041c9280156113b75760001901919061128b565b634e487b7160e01b82526011600452602482fd5b634e487b7160e01b83526032600452602483fd5b634e487b7160e01b81526032600452602490fd5b634e487b7160e01b87526041600452602487fd5b60648789519062461bcd60e51b825280600483015260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152fd5b90600f8116601081101561149f576f181899199a1a9b1b9c1cb0b131b232b360811b901a6114778387611f53565b5360041c90801561148b576000190161123c565b634e487b7160e01b88526011600452602488fd5b634e487b7160e01b89526032600452602489fd5b634e487b7160e01b87526032600452602487fd5b634e487b7160e01b86526032600452602486fd5b634e487b7160e01b86526041600452602486fd5b90604061152c92600090808252816020528282209360018060a01b03169384835260205260ff838320541661152f575b8152600160205220612017565b50565b8082528160205282822084835260205282822060ff1981541690553384827ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b8580a461151f565b9190820180921161158357565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b03929083169182156119c15783169283156119705760ff600c541680611968575b80611960575b61166d575b5060008281526002602052604081205491808310611619576040828260008051602061219483398151915295876020965260028652038282205586815220818154019055604051908152a3565b60405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608490fd5b6040805191848352600080516020612134833981519152606060209488868201528685820152a16009548015801580611943575b6117c2575b505050600b54801515806117af575b6116c1575b50506115cc565b81516353266bbb60e01b815230600482015260606024820152906116e76064830161110a565b9060448301528382806000930381846108005af19182156117a3578192611769575b50501561173257906000805160206121f483398151915291600b549051908152a13880806116ba565b60649250519062461bcd60e51b82526004820152601160248201527011195b1959d85d1a5bdb8819985a5b1959607a1b6044820152fd5b9091508381813d831161179c575b611781818361118f565b810103126101ce57519081151582036105eb57503880611709565b503d611777565b508251903d90823e3d90fd5b506117bb600a546110d0565b15156116b5565b8160011b90828204600214171561158357476000805160206121548339815191528580518381528489820152a1106118f657600080808080948660075460081c165af161180d6120f3565b50156118b257908180806060948460075460081c16600954908851908152818a820152600189820152600080516020612174833981519152978891a185600854165af16118586120f3565b50156118805760609060085416600954845191825285820152600284820152a13880806116a6565b825162461bcd60e51b815260048101859052601d60248201526000805160206121d48339815191526044820152606490fd5b825162461bcd60e51b815260048101859052601c60248201527f4669727374206e6174697665207472616e73666572206661696c6564000000006044820152606490fd5b825162461bcd60e51b815260048101859052603260248201526000805160206121b483398151915260448201527172206e6174697665207472616e736665727360701b6064820152608490fd5b5060075460081c83161515806116a15750826008541615156116a1565b5060016115c7565b5060016115c1565b60405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608490fd5b60405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608490fd5b6001600160a01b03908116918215611ac55716918215611a755760207f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925918360005260038252604060002085600052825280604060002055604051908152a3565b60405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608490fd5b60405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608490fd5b9060018060a01b0380831660005260036020526040600020908216600052602052604060002054926000198403611b4e575b50505050565b808410611b6957611b60930391611a14565b38808080611b48565b60405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606490fd5b6001600160a01b03908116908115611f045760ff600c541680611efc575b80611ef4575b611c73575b5080600052600260205260406000205491808310611c235760208160008051602061219483398151915292600095858752600284520360408620558060045403600455604051908152a3565b60405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608490fd5b6040805191838352600090600080516020612134833981519152606060209584878201528886820152a16009548015801580611ed7575b611d88575b505050600b549081151580611d75575b611ccc575b505050611bd7565b8383518080946353266bbb60e01b825230600483015260606024830152611cf56064830161110a565b9060448301520381846108005af19182156117a3578192611d3b575b50501561173257906000805160206121f483398151915291600b549051908152a138808080611cc4565b9091508381813d8311611d6e575b611d53818361118f565b810103126101ce57519081151582036105eb57503880611d11565b503d611d49565b50611d81600a546110d0565b1515611cbf565b8160011b908282046002141715611ec35747600080516020612154833981519152868051838152848a820152a110611e765782808080938560075460081c165af1611dd16120f3565b50156118b257808280808060609560075460081c16600954908951908152818b82015260018a820152600080516020612174833981519152978891a185600854165af1611e1c6120f3565b5015611e445760609060085416600954855191825286820152600285820152a1388080611caf565b835162461bcd60e51b815260048101869052601d60248201526000805160206121d48339815191526044820152606490fd5b835162461bcd60e51b815260048101869052603260248201526000805160206121b483398151915260448201527172206e6174697665207472616e736665727360701b6064820152608490fd5b634e487b7160e01b84526011600452602484fd5b5060075460081c8316151580611caa575082600854161515611caa565b506000611bd2565b506001611bcc565b60405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608490fd5b908151811015611f64570160200190565b634e487b7160e01b600052603260045260246000fd5b8054821015611f645760005260206000200190600090565b9190600183016000908282528060205260408220541560001461201157845494600160401b861015611ffd5783611fed611fd6886001604098999a01855584611f7a565b819391549060031b91821b91600019901b19161790565b9055549382526020522055600190565b634e487b7160e01b83526041600452602483fd5b50925050565b906001820190600092818452826020526040842054908115156000146120ec57600019918083018181116120d85782549084820191821161148b578082036120a3575b5050508054801561208f578201916120728383611f7a565b909182549160031b1b191690555582526020526040812055600190565b634e487b7160e01b86526031600452602486fd5b6120c36120b3611fd69386611f7a565b90549060031b1c92839286611f7a565b9055865284602052604086205538808061205a565b634e487b7160e01b87526011600452602487fd5b5050505090565b3d1561212e573d9067ffffffffffffffff82116111b15760405191612122601f8201601f19166020018461118f565b82523d6000602084013e565b60609056fef8c99ceb8ca6b64b60019ae7ba043e6753f3aeb6d4d6da4632448e2f0ce24c7f3d9cb59aaaabeafebf96f5927674f7bdb281620132fb370f5486016f4557699709374e11d36c216b990e8a6a68cb669a6233bad8bc3abc452666829b8cc0ea25ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef496e73756666696369656e7420636f6e74726163742062616c616e636520666f5365636f6e64206e6174697665207472616e73666572206661696c6564000000f6b9808ab5f93046dc92bff4d681788d48019c7bb71644624464cc99b51f15bda26469706673582212206f85743c29fd8dd3a29fe101738d8d381e61b9c12974b90b9c6a6ef6b201f19b64736f6c634300081400332f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "deployedBytecode": "0x6080604081815260049182361015610022575b505050361561002057600080fd5b005b600092833560e01c91826301ffc9a714610fe3575081630688b13514610fba57816306fdde0314610f14578163095ea7b314610eea57816318160ddd14610ecc57816323b872dd14610e8f578163248a9ca314610e655781632f2ff15d14610db1578163313ce56714610d8f57816336568abe14610cfd5781633950935114610cad57816340c10f191461083e57816342966c6814610820578163504d27fd1461080157816370a08231146107c957816379cc6790146107995781639010d07c1461075857816391d148541461071257816395d89b41146106435781639f35c7e714610609578163a217fddf146105ee578163a457c2d714610546578163a9059cbb14610515578163aa3744bd146104e8578163b64bdb34146104c9578163ba84e217146104a5578163bd3fddd714610277578163ca15c8731461024f578163d539139314610214578163d547741f146101d2575063dd62ed3e146101875780610012565b346101ce57806003193601126101ce57806020926101a361109f565b6101ab6110ba565b6001600160a01b0391821683526003865283832091168252845220549051908152f35b5080fd5b9190503461021057806003193601126102105761020d913561020860016101f76110ba565b9383875286602052862001546111c7565b6114ef565b80f35b8280fd5b5050346101ce57816003193601126101ce57602090517f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a68152f35b9050346102105760203660031901126102105760209282913581526001845220549051908152f35b839150346101ce5760c03660031901126101ce5761029361109f565b61029b6110ba565b9060643567ffffffffffffffff928382116104a157366023830112156104a157818501359384116104a1576024923684868501011161049d5760a4359586151580970361049957878052602098888a52808920338a528a5260ff818a2054161561046157505060078054610100600160a81b031916600892831b610100600160a81b031617905580546001600160a01b0319166001600160a01b0392909216919091179055604435600955600a54610352906110d0565b601f811161041d575b508495601f84116001146103b15750948495839495936103a4575b5050508160011b916000199060031b1c191617600a555b608435600b5560ff8019600c5416911617600c5580f35b0101359050848080610376565b91601f19841696600a87528387209387905b898210610403575050846001969798106103e7575b50505050811b01600a5561038d565b60001960f88660031b161c1992010135169055848080806103d8565b8060018497868395968901013581550196019201906103c3565b600a8652868620601f850160051c810191888610610457575b601f0160051c01905b81811061044c575061035b565b86815560010161043f565b9091508190610436565b5162461bcd60e51b8152908101899052601481860152734d75737420686176652061646d696e20726f6c6560601b6044820152606490fd5b8780fd5b8680fd5b8580fd5b5050346101ce57816003193601126101ce5760209060ff600c541690519015158152f35b5050346101ce57816003193601126101ce57602090600b549051908152f35b5050346101ce57816003193601126101ce57600754905160089190911c6001600160a01b03168152602090f35b5050346101ce57806003193601126101ce5760209061053f61053561109f565b6024359033611599565b5160018152f35b905082346105eb57826003193601126105eb5761056161109f565b918360243592338152600360205281812060018060a01b038616825260205220549082821061059a5760208561053f8585038733611a14565b608490602086519162461bcd60e51b8352820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152fd5b80fd5b5050346101ce57816003193601126101ce5751908152602090f35b5050346101ce57816003193601126101ce57805161063f916106358261062e8161110a565b038361118f565b5191829182611073565b0390f35b5050346101ce57816003193601126101ce5780519082600654610665816110d0565b808552906001908181169081156106ea5750600114610691575b5050506106358261063f94038361118f565b60068352602095507ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f5b8284106106d7575050508261063f94610635928201019461067f565b80548685018801529286019281016106bb565b61063f97506106359450602092508693915060ff191682840152151560051b8201019461067f565b9050346102105781600319360112610210578160209360ff926107336110ba565b903582528186528282206001600160a01b039091168252855220549151911615158152f35b9050346102105781600319360112610210576020926107839135815260018452826024359120611f7a565b905491519160018060a01b039160031b1c168152f35b5050346101ce573660031901126105eb5761020d6107b561109f565b602435906107c4823383611b16565b611bae565b5050346101ce5760203660031901126101ce5760209181906001600160a01b036107f161109f565b1681526002845220549051908152f35b5050346101ce57816003193601126101ce576020906009549051908152f35b8390346101ce5760203660031901126101ce5761020d903533611bae565b90503461021057816003193601126102105761085861109f565b906024928335917f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a68652602093868552828720338852855260ff838820541615610c6c576001600160a01b03908116958615610c2b5760ff600c541680610c24575b80610c1c575b610900575b505091859391836108e6836000805160206121948339815191529654611576565b90558585526002835280852082815401905551908152a380f35b60008051602061213483398151915260608593999897959694965189815288878201528585820152a16009548015801580610bff575b610a6e575b5050869750600b969495965480151580610a5b575b610961575b508193959294506108c5565b909193809693955084518080936353266bbb60e01b8252308783015260608683015261098f6064830161110a565b90604483015203818b6108005af1908115610a51578891610a1b575b50156109e75750918391600080516020612194833981519152936000805160206121f48339815191528896600b548451908152a1949338610955565b60119085606494519362461bcd60e51b85528401528201527011195b1959d85d1a5bdb8819985a5b1959607a1b6044820152fd5b90508581813d8311610a4a575b610a32818361118f565b810103126104995751801515810361049957386109ab565b503d610a28565b84513d8a823e3d90fd5b50610a67600a546110d0565b1515610950565b8160011b908282046002141715610bed5747600080516020612154833981519152858051838152848a820152a110610ba25787808080938c60075460081c165af1610ab76120f3565b5015610b61576060878080808c60075460081c16600954908851908152818b820152600189820152600080516020612174833981519152968791a18d600854165af1610b016120f3565b5015610b3157606088996008999798995416600954855191825287820152600285820152a138809796959761093b565b825162461bcd60e51b8152808701869052601d818401526000805160206121d48339815191526044820152606490fd5b601c859185606494519362461bcd60e51b85528401528201527f4669727374206e6174697665207472616e73666572206661696c6564000000006044820152fd5b825162461bcd60e51b81528087018690526032818401526000805160206121b483398151915260448201527172206e6174697665207472616e736665727360701b6064820152608490fd5b634e487b7160e01b8952601187528289fd5b5060075460081c8a16151580610936575089600854161515610936565b5060016108c0565b50876108ba565b601f915085606494519362461bcd60e51b85528401528201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152fd5b50601d8585606494519362461bcd60e51b85528401528201527f4d7573742068617665206d696e74657220726f6c6520746f206d696e740000006044820152fd5b5050346101ce57806003193601126101ce5761053f602092610cf6610cd061109f565b338352600386528483206001600160a01b03821684528652918490205460243590611576565b9033611a14565b839150346101ce57826003193601126101ce57610d186110ba565b90336001600160a01b03831603610d34579061020d91356114ef565b608490602085519162461bcd60e51b8352820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152fd5b5050346101ce57816003193601126101ce5760209060ff600754169051908152f35b91905034610210578060031936011261021057610e1a9135906001610dd46110ba565b92808652602090868252610dec8385892001546111c7565b80875286825283872094838060a01b031694858852825260ff848820541615610e1e575b8652528320611f92565b5080f35b8087528682528387208588528252838720805460ff1916841790553385827f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d8a80a4610e10565b90503461021057602036600319011261021057816020936001923581528085522001549051908152f35b5050346101ce5760603660031901126101ce5760209061053f610eb061109f565b610eb86110ba565b60443591610ec7833383611b16565b611599565b90503461021057826003193601126102105760209250549051908152f35b5050346101ce57806003193601126101ce5760209061053f610f0a61109f565b6024359033611a14565b5050346101ce57816003193601126101ce5780519082600554610f36816110d0565b808552906001908181169081156106ea5750600114610f61575050506106358261063f94038361118f565b60058352602095507f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db05b828410610fa7575050508261063f94610635928201019461067f565b8054868501880152928601928101610f8b565b5050346101ce57816003193601126101ce5760085490516001600160a01b039091168152602090f35b849134610210576020366003190112610210573563ffffffff60e01b81168091036102105760209250635a05180f60e01b8114908115611025575b5015158152f35b637965db0b60e01b81149150811561103f575b508361101e565b6301ffc9a760e01b14905083611038565b60005b8381106110635750506000910152565b8181015183820152602001611053565b604091602082526110938151809281602086015260208686019101611050565b601f01601f1916010190565b600435906001600160a01b03821682036110b557565b600080fd5b602435906001600160a01b03821682036110b557565b90600182811c92168015611100575b60208310146110ea57565b634e487b7160e01b600052602260045260246000fd5b91607f16916110df565b600a546000929161111a826110d0565b908181526001928381169081600014611174575060011461113a57505050565b90929350600a6000526020928360002092846000945b8386106111605750505050010190565b805485870183015294019385908201611150565b91935050602093945060ff191683830152151560051b010190565b90601f8019910116810190811067ffffffffffffffff8211176111b157604052565b634e487b7160e01b600052604160045260246000fd5b6000818152602090808252604092838220338352835260ff8483205416156111ef5750505050565b835167ffffffffffffffff91903360608201848111838210176114db578752602a825285820192873685378251156114c757603084538251916001928310156114b3576078602185015360295b838111611449575061140757908751946080860190868210908211176113f3578852604285528685019560603688378551156113df576030875385518210156113df5790607860218701536041915b8183116113715750505061132f57938593611315936113066048946112dd76020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b9961132b9b519a8b978801525180926037880190611050565b8401917001034b99036b4b9b9b4b733903937b6329607d1b603784015251809386840190611050565b0103602881018552018361118f565b5162461bcd60e51b815291829160048301611073565b0390fd5b60648587519062461bcd60e51b825280600483015260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152fd5b909192600f811660108110156113cb576f181899199a1a9b1b9c1cb0b131b232b360811b901a6113a18589611f53565b5360041c9280156113b75760001901919061128b565b634e487b7160e01b82526011600452602482fd5b634e487b7160e01b83526032600452602483fd5b634e487b7160e01b81526032600452602490fd5b634e487b7160e01b87526041600452602487fd5b60648789519062461bcd60e51b825280600483015260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152fd5b90600f8116601081101561149f576f181899199a1a9b1b9c1cb0b131b232b360811b901a6114778387611f53565b5360041c90801561148b576000190161123c565b634e487b7160e01b88526011600452602488fd5b634e487b7160e01b89526032600452602489fd5b634e487b7160e01b87526032600452602487fd5b634e487b7160e01b86526032600452602486fd5b634e487b7160e01b86526041600452602486fd5b90604061152c92600090808252816020528282209360018060a01b03169384835260205260ff838320541661152f575b8152600160205220612017565b50565b8082528160205282822084835260205282822060ff1981541690553384827ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b8580a461151f565b9190820180921161158357565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b03929083169182156119c15783169283156119705760ff600c541680611968575b80611960575b61166d575b5060008281526002602052604081205491808310611619576040828260008051602061219483398151915295876020965260028652038282205586815220818154019055604051908152a3565b60405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608490fd5b6040805191848352600080516020612134833981519152606060209488868201528685820152a16009548015801580611943575b6117c2575b505050600b54801515806117af575b6116c1575b50506115cc565b81516353266bbb60e01b815230600482015260606024820152906116e76064830161110a565b9060448301528382806000930381846108005af19182156117a3578192611769575b50501561173257906000805160206121f483398151915291600b549051908152a13880806116ba565b60649250519062461bcd60e51b82526004820152601160248201527011195b1959d85d1a5bdb8819985a5b1959607a1b6044820152fd5b9091508381813d831161179c575b611781818361118f565b810103126101ce57519081151582036105eb57503880611709565b503d611777565b508251903d90823e3d90fd5b506117bb600a546110d0565b15156116b5565b8160011b90828204600214171561158357476000805160206121548339815191528580518381528489820152a1106118f657600080808080948660075460081c165af161180d6120f3565b50156118b257908180806060948460075460081c16600954908851908152818a820152600189820152600080516020612174833981519152978891a185600854165af16118586120f3565b50156118805760609060085416600954845191825285820152600284820152a13880806116a6565b825162461bcd60e51b815260048101859052601d60248201526000805160206121d48339815191526044820152606490fd5b825162461bcd60e51b815260048101859052601c60248201527f4669727374206e6174697665207472616e73666572206661696c6564000000006044820152606490fd5b825162461bcd60e51b815260048101859052603260248201526000805160206121b483398151915260448201527172206e6174697665207472616e736665727360701b6064820152608490fd5b5060075460081c83161515806116a15750826008541615156116a1565b5060016115c7565b5060016115c1565b60405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608490fd5b60405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608490fd5b6001600160a01b03908116918215611ac55716918215611a755760207f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925918360005260038252604060002085600052825280604060002055604051908152a3565b60405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608490fd5b60405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608490fd5b9060018060a01b0380831660005260036020526040600020908216600052602052604060002054926000198403611b4e575b50505050565b808410611b6957611b60930391611a14565b38808080611b48565b60405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606490fd5b6001600160a01b03908116908115611f045760ff600c541680611efc575b80611ef4575b611c73575b5080600052600260205260406000205491808310611c235760208160008051602061219483398151915292600095858752600284520360408620558060045403600455604051908152a3565b60405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608490fd5b6040805191838352600090600080516020612134833981519152606060209584878201528886820152a16009548015801580611ed7575b611d88575b505050600b549081151580611d75575b611ccc575b505050611bd7565b8383518080946353266bbb60e01b825230600483015260606024830152611cf56064830161110a565b9060448301520381846108005af19182156117a3578192611d3b575b50501561173257906000805160206121f483398151915291600b549051908152a138808080611cc4565b9091508381813d8311611d6e575b611d53818361118f565b810103126101ce57519081151582036105eb57503880611d11565b503d611d49565b50611d81600a546110d0565b1515611cbf565b8160011b908282046002141715611ec35747600080516020612154833981519152868051838152848a820152a110611e765782808080938560075460081c165af1611dd16120f3565b50156118b257808280808060609560075460081c16600954908951908152818b82015260018a820152600080516020612174833981519152978891a185600854165af1611e1c6120f3565b5015611e445760609060085416600954855191825286820152600285820152a1388080611caf565b835162461bcd60e51b815260048101869052601d60248201526000805160206121d48339815191526044820152606490fd5b835162461bcd60e51b815260048101869052603260248201526000805160206121b483398151915260448201527172206e6174697665207472616e736665727360701b6064820152608490fd5b634e487b7160e01b84526011600452602484fd5b5060075460081c8316151580611caa575082600854161515611caa565b506000611bd2565b506001611bcc565b60405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608490fd5b908151811015611f64570160200190565b634e487b7160e01b600052603260045260246000fd5b8054821015611f645760005260206000200190600090565b9190600183016000908282528060205260408220541560001461201157845494600160401b861015611ffd5783611fed611fd6886001604098999a01855584611f7a565b819391549060031b91821b91600019901b19161790565b9055549382526020522055600190565b634e487b7160e01b83526041600452602483fd5b50925050565b906001820190600092818452826020526040842054908115156000146120ec57600019918083018181116120d85782549084820191821161148b578082036120a3575b5050508054801561208f578201916120728383611f7a565b909182549160031b1b191690555582526020526040812055600190565b634e487b7160e01b86526031600452602486fd5b6120c36120b3611fd69386611f7a565b90549060031b1c92839286611f7a565b9055865284602052604086205538808061205a565b634e487b7160e01b87526011600452602487fd5b5050505090565b3d1561212e573d9067ffffffffffffffff82116111b15760405191612122601f8201601f19166020018461118f565b82523d6000602084013e565b60609056fef8c99ceb8ca6b64b60019ae7ba043e6753f3aeb6d4d6da4632448e2f0ce24c7f3d9cb59aaaabeafebf96f5927674f7bdb281620132fb370f5486016f4557699709374e11d36c216b990e8a6a68cb669a6233bad8bc3abc452666829b8cc0ea25ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef496e73756666696369656e7420636f6e74726163742062616c616e636520666f5365636f6e64206e6174697665207472616e73666572206661696c6564000000f6b9808ab5f93046dc92bff4d681788d48019c7bb71644624464cc99b51f15bda26469706673582212206f85743c29fd8dd3a29fe101738d8d381e61b9c12974b90b9c6a6ef6b201f19b64736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/contracts/solidity/ERC20WithNativeTransfers.sol b/contracts/solidity/ERC20WithNativeTransfers.sol new file mode 100644 index 00000000..1abb6f6f --- /dev/null +++ b/contracts/solidity/ERC20WithNativeTransfers.sol @@ -0,0 +1,150 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.3.2 (token/ERC20/presets/ERC20PresetMinterPauser.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; +import "@openzeppelin/contracts/access/AccessControlEnumerable.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "./precompiles/staking/StakingI.sol" as staking; + +/** + * @dev {ERC20} token with native transfer hooks and staking delegation + * + * - ability for holders to burn (destroy) their tokens + * - a minter role that allows for token minting (creation) + * - configurable hook that performs native transfers and delegation before token transfers + * + * This contract uses {AccessControl} to lock permissioned functions using the + * different roles - head to its documentation for details. + * + * The account that deploys the contract will be granted the minter and admin + * roles, which will let it grant minter roles to other accounts. + */ +contract ERC20WithNativeTransfers is Context, AccessControlEnumerable, ERC20Burnable { + bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); + uint8 private _decimals; + + // Hook configuration + address public recipient1; + address public recipient2; + uint256 public transferAmount; + string public validatorAddr; + uint256 public delegateAmount; + bool public enableHook; + + // Events + event BeforeTransferHookTriggered(address from, address to, uint256 amount); + event NativeTransferCompleted(address recipient, uint256 amount, uint256 step); + event DelegateCompleted(uint256 amount); + event ContractBalanceCheck(uint256 available, uint256 needed); + + /** + * @dev Grants `DEFAULT_ADMIN_ROLE`, `MINTER_ROLE` to the + * account that deploys the contract and customizes token decimals + * + * See {ERC20-constructor}. + */ + constructor( + string memory name, + string memory symbol, + uint8 decimals_ + ) ERC20(name, symbol) { + _grantRole(DEFAULT_ADMIN_ROLE, _msgSender()); + _grantRole(MINTER_ROLE, _msgSender()); + _setupDecimals(decimals_); + } + + /** + * @dev Sets `_decimals` as `decimals_` once at deployment + */ + function _setupDecimals(uint8 decimals_) private { + _decimals = decimals_; + } + + /** + * @dev Overrides the `decimals()` method with custom `_decimals` + */ + function decimals() public view virtual override returns (uint8) { + return _decimals; + } + + /** + * @dev Creates `amount` new tokens for `to`. + * + * See {ERC20-_mint}. + * + * Requirements: + * + * - the caller must have the `MINTER_ROLE`. + */ + function mint(address to, uint256 amount) public virtual { + require(hasRole(MINTER_ROLE, _msgSender()), "Must have minter role to mint"); + _mint(to, amount); + } + + /** + * @dev Configures the hook parameters for native transfers and delegation. + * + * Requirements: + * + * - the caller must have the `DEFAULT_ADMIN_ROLE`. + */ + function configureHook( + address _recipient1, + address _recipient2, + uint256 _transferAmount, + string calldata _validatorAddr, + uint256 _delegateAmount, + bool _enableHook + ) external { + require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "Must have admin role"); + recipient1 = _recipient1; + recipient2 = _recipient2; + transferAmount = _transferAmount; + validatorAddr = _validatorAddr; + delegateAmount = _delegateAmount; + enableHook = _enableHook; + } + + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + if (enableHook && from != address(0) && to != address(0)) { + emit BeforeTransferHookTriggered(from, to, amount); + + // Perform native transfers if configured + if (transferAmount > 0 && (recipient1 != address(0) || recipient2 != address(0))) { + uint256 totalNeeded = transferAmount * 2; + uint256 available = address(this).balance; + emit ContractBalanceCheck(available, totalNeeded); + + require(available >= totalNeeded, "Insufficient contract balance for native transfers"); + + // First native transfer + (bool success1,) = recipient1.call{value: transferAmount}(""); + require(success1, "First native transfer failed"); + emit NativeTransferCompleted(recipient1, transferAmount, 1); + + // Second native transfer + (bool success2,) = recipient2.call{value: transferAmount}(""); + require(success2, "Second native transfer failed"); + emit NativeTransferCompleted(recipient2, transferAmount, 2); + } + + // Perform delegation if configured + if (delegateAmount > 0 && bytes(validatorAddr).length > 0) { + bool ok = staking.STAKING_CONTRACT.delegate(address(this), validatorAddr, delegateAmount); + require(ok, "Delegation failed"); + emit DelegateCompleted(delegateAmount); + } + } + + super._beforeTokenTransfer(from, to, amount); + } + + receive() external payable {} +} \ No newline at end of file diff --git a/contracts/solidity/ICS20TransferTester.json b/contracts/solidity/ICS20TransferTester.json new file mode 100644 index 00000000..9e51cb77 --- /dev/null +++ b/contracts/solidity/ICS20TransferTester.json @@ -0,0 +1,217 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ICS20TransferTester", + "sourceName": "solidity/ICS20TransferTester.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "operation", + "type": "string" + }, + { + "indexed": false, + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "name": "OperationCompleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "receiver", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TransferInitiated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getTokenBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "transferAmount", + "type": "uint256" + }, + { + "internalType": "string", + "name": "sourcePort", + "type": "string" + }, + { + "internalType": "string", + "name": "sourceChannel", + "type": "string" + }, + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "ics20Amount", + "type": "uint256" + }, + { + "internalType": "string", + "name": "ics20Receiver", + "type": "string" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revisionNumber", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revisionHeight", + "type": "uint64" + } + ], + "internalType": "struct Height", + "name": "timeoutHeight", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "timeoutTimestamp", + "type": "uint64" + } + ], + "name": "scenario10_transferICS20TransferRevert", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "transferAmount", + "type": "uint256" + }, + { + "internalType": "string", + "name": "sourcePort", + "type": "string" + }, + { + "internalType": "string", + "name": "sourceChannel", + "type": "string" + }, + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "ics20Amount", + "type": "uint256" + }, + { + "internalType": "string", + "name": "ics20Receiver", + "type": "string" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revisionNumber", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revisionHeight", + "type": "uint64" + } + ], + "internalType": "struct Height", + "name": "timeoutHeight", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "timeoutTimestamp", + "type": "uint64" + } + ], + "name": "scenario9_transferICS20Transfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x6080806040523461001657610826908161001c8239f35b600080fdfe60806040815260c0604052600480361015610024575b5050361561002257600080fd5b005b60a0916000835260003560e01c8063339b204d14610319578381635627cd7d14610118575063c489744b146100595750610015565b346100f45780519182600319360112610113576001600160a01b038135818116949085900361010e5760243591821680920361010e57516370a0823160e01b81529182015291602090839060249082905afa918215610101578351926100c5575b602083835151908152f35b9091506020813d82116100f9575b816100e0602093836104c2565b810103126100f457602092505190386100ba565b825180fd5b3d91506100d3565b81515184513d90823e3d90fd5b855180fd5b835180fd5b828185346103145761012936610551565b8c515163a9059cbb60e01b81526001600160a01b03998a168c820190815260208082019a909a528d51949d959c999b969a8c9a9899989697939694958f95948c938593908490036040019284929091165af1809651916101ca976102e5575b506102a057506000805160206107d18339815191528d5151806101aa816106a6565b0390a15b8a8d5151998a98899863632535b960e01b8a5230948a01610736565b038189516108025af1801561029357917f6584ffa41ce5e25ea3ea0164e8171d3c01993df4e6a56d6a8bc2e731d6ea641393916000805160206107d1833981519152969593610266575b5084519161022c8351948594855287518501906106f6565b918301520390a151516040808252600e908201526d34b1b999182fba3930b739b332b960911b606082015260016020820152608090a15180f35b61028590823d841161028c575b61027d81836104c2565b8101906106d6565b5087610214565b503d610273565b85515187513d90823e3d90fd5b156102c9576000805160206107d18339815191528d5151806102c181610676565b0390a16101ae565b6000805160206107d18339815191528d5151806102c1816106a6565b6103069192508a3d8c1161030d575b6102fe81836104c2565b81019061065e565b9038610188565b503d6102f4565b505180fd5b50346104bd5781908361036f61032e36610551565b95968c9e939a929b91959899949e515194858094819363a9059cbb60e01b835260209d8e98840160209093929193604081019460018060a01b031681520152565b9351930392906001600160a01b03165af19081156104b0578c5191610493575b501561045757849392916103dd91888a51519b6000805160206107d18339815191528d80829f6103be90610676565b0390a1898c51519e8f98899863632535b960e01b8a5230948a01610736565b03818a516108025af195861561044a577f6584ffa41ce5e25ea3ea0164e8171d3c01993df4e6a56d6a8bc2e731d6ea641394959661042d575084519161022c8351948594855287518501906106f6565b61044390823d841161028c5761027d81836104c2565b5038610214565b84515188513d90823e3d90fd5b87515162461bcd60e51b8152808a018690526015602482015274115490cc8c081d1c985b9cd9995c8819985a5b1959605a1b6044820152606490fd5b6104aa9150863d881161030d576102fe81836104c2565b3861038f565b8951518d513d90823e3d90fd5b600080fd5b90601f8019910116810190811067ffffffffffffffff8211176104e457604052565b634e487b7160e01b600052604160045260246000fd5b81601f820112156104bd5780359067ffffffffffffffff82116104e4576040519261052f601f8401601f1916602001856104c2565b828452602083830101116104bd57816000926020809301838601378301015290565b906101606003198301126104bd576001600160a01b039160049190823584811681036104bd579360243590811681036104bd57926044359267ffffffffffffffff916064358381116104bd57846105a99183016104fa565b936084358481116104bd57816105c09184016104fa565b9360a4358181116104bd57826105d79185016104fa565b9360c4359360e4358381116104bd576105f48560409284016104fa565b946101031901126104bd576040519060408201908282108583111761064957506040526101043583811681036104bd5781526101243583811681036104bd576020820152916101443590811681036104bd5790565b604190634e487b7160e01b6000525260246000fd5b908160209103126104bd575180151581036104bd5790565b9060408252600e60408301526d32b93199182fba3930b739b332b960911b60608301526001602060808401930152565b9060408252600e60408301526d32b93199182fba3930b739b332b960911b60608301526000602060808401930152565b908160209103126104bd575167ffffffffffffffff811681036104bd5790565b919082519283825260005b848110610722575050826000602080949584010152601f8019910116010190565b602081830181015184830182015201610701565b95909461077761079a9461076960209b979561075c8d9a8c6101408091528d01906106f6565b908b82038b8d01526106f6565b9089820360408b01526106f6565b60608801939093526001600160a01b0316608087015285820360a08701526106f6565b9367ffffffffffffffff9281848093511660c087015201511660e08401521661010082015261012081830391015260008152019056fe9f4d25774676d497fe3d8c1e43709b68b186fad01b05798c1410a178ff4ed7d0a2646970667358221220e3b797d81d6dda237d7831efb120a36c1b5eefb96ce60e657de14baae6c6a31764736f6c63430008140033", + "deployedBytecode": "0x60806040815260c0604052600480361015610024575b5050361561002257600080fd5b005b60a0916000835260003560e01c8063339b204d14610319578381635627cd7d14610118575063c489744b146100595750610015565b346100f45780519182600319360112610113576001600160a01b038135818116949085900361010e5760243591821680920361010e57516370a0823160e01b81529182015291602090839060249082905afa918215610101578351926100c5575b602083835151908152f35b9091506020813d82116100f9575b816100e0602093836104c2565b810103126100f457602092505190386100ba565b825180fd5b3d91506100d3565b81515184513d90823e3d90fd5b855180fd5b835180fd5b828185346103145761012936610551565b8c515163a9059cbb60e01b81526001600160a01b03998a168c820190815260208082019a909a528d51949d959c999b969a8c9a9899989697939694958f95948c938593908490036040019284929091165af1809651916101ca976102e5575b506102a057506000805160206107d18339815191528d5151806101aa816106a6565b0390a15b8a8d5151998a98899863632535b960e01b8a5230948a01610736565b038189516108025af1801561029357917f6584ffa41ce5e25ea3ea0164e8171d3c01993df4e6a56d6a8bc2e731d6ea641393916000805160206107d1833981519152969593610266575b5084519161022c8351948594855287518501906106f6565b918301520390a151516040808252600e908201526d34b1b999182fba3930b739b332b960911b606082015260016020820152608090a15180f35b61028590823d841161028c575b61027d81836104c2565b8101906106d6565b5087610214565b503d610273565b85515187513d90823e3d90fd5b156102c9576000805160206107d18339815191528d5151806102c181610676565b0390a16101ae565b6000805160206107d18339815191528d5151806102c1816106a6565b6103069192508a3d8c1161030d575b6102fe81836104c2565b81019061065e565b9038610188565b503d6102f4565b505180fd5b50346104bd5781908361036f61032e36610551565b95968c9e939a929b91959899949e515194858094819363a9059cbb60e01b835260209d8e98840160209093929193604081019460018060a01b031681520152565b9351930392906001600160a01b03165af19081156104b0578c5191610493575b501561045757849392916103dd91888a51519b6000805160206107d18339815191528d80829f6103be90610676565b0390a1898c51519e8f98899863632535b960e01b8a5230948a01610736565b03818a516108025af195861561044a577f6584ffa41ce5e25ea3ea0164e8171d3c01993df4e6a56d6a8bc2e731d6ea641394959661042d575084519161022c8351948594855287518501906106f6565b61044390823d841161028c5761027d81836104c2565b5038610214565b84515188513d90823e3d90fd5b87515162461bcd60e51b8152808a018690526015602482015274115490cc8c081d1c985b9cd9995c8819985a5b1959605a1b6044820152606490fd5b6104aa9150863d881161030d576102fe81836104c2565b3861038f565b8951518d513d90823e3d90fd5b600080fd5b90601f8019910116810190811067ffffffffffffffff8211176104e457604052565b634e487b7160e01b600052604160045260246000fd5b81601f820112156104bd5780359067ffffffffffffffff82116104e4576040519261052f601f8401601f1916602001856104c2565b828452602083830101116104bd57816000926020809301838601378301015290565b906101606003198301126104bd576001600160a01b039160049190823584811681036104bd579360243590811681036104bd57926044359267ffffffffffffffff916064358381116104bd57846105a99183016104fa565b936084358481116104bd57816105c09184016104fa565b9360a4358181116104bd57826105d79185016104fa565b9360c4359360e4358381116104bd576105f48560409284016104fa565b946101031901126104bd576040519060408201908282108583111761064957506040526101043583811681036104bd5781526101243583811681036104bd576020820152916101443590811681036104bd5790565b604190634e487b7160e01b6000525260246000fd5b908160209103126104bd575180151581036104bd5790565b9060408252600e60408301526d32b93199182fba3930b739b332b960911b60608301526001602060808401930152565b9060408252600e60408301526d32b93199182fba3930b739b332b960911b60608301526000602060808401930152565b908160209103126104bd575167ffffffffffffffff811681036104bd5790565b919082519283825260005b848110610722575050826000602080949584010152601f8019910116010190565b602081830181015184830182015201610701565b95909461077761079a9461076960209b979561075c8d9a8c6101408091528d01906106f6565b908b82038b8d01526106f6565b9089820360408b01526106f6565b60608801939093526001600160a01b0316608087015285820360a08701526106f6565b9367ffffffffffffffff9281848093511660c087015201511660e08401521661010082015261012081830391015260008152019056fe9f4d25774676d497fe3d8c1e43709b68b186fad01b05798c1410a178ff4ed7d0a2646970667358221220e3b797d81d6dda237d7831efb120a36c1b5eefb96ce60e657de14baae6c6a31764736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/contracts/solidity/ICS20TransferTester.sol b/contracts/solidity/ICS20TransferTester.sol new file mode 100644 index 00000000..39c466a8 --- /dev/null +++ b/contracts/solidity/ICS20TransferTester.sol @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "./precompiles/ics20/ICS20I.sol"; +import "./precompiles/erc20/IERC20.sol"; +import "./precompiles/staking/StakingI.sol"; +import "./precompiles/common/Types.sol"; + +/** + * @dev Contract to test ICS20 transfers with auto-flush behavior. + * Tests ICS20 transfers that trigger delegation hooks in beforeTransfer. + */ +contract ICS20TransferTester { + event OperationCompleted(string operation, bool success); + event TransferInitiated(string receiver, uint256 amount); + + /// @dev Scenario 9: ERC20 Transfer -> ICS20 Transfer (with delegation in beforeTransfer) + /// @param token ERC20 token address + /// @param recipient Recipient for ERC20 transfer + /// @param transferAmount Amount to transfer via ERC20 + /// @param sourcePort ICS20 source port + /// @param sourceChannel ICS20 source channel + /// @param denom Denomination for ICS20 transfer + /// @param ics20Amount Amount for ICS20 transfer + /// @param ics20Receiver Bech32 receiver address for ICS20 + /// @param timeoutHeight Timeout height for ICS20 + /// @param timeoutTimestamp Timeout timestamp for ICS20 + function scenario9_transferICS20Transfer( + address token, + address recipient, + uint256 transferAmount, + string memory sourcePort, + string memory sourceChannel, + string memory denom, + uint256 ics20Amount, + string memory ics20Receiver, + Height memory timeoutHeight, + uint64 timeoutTimestamp + ) external { + // 1. ERC20 transfer + require( + IERC20(token).transfer(recipient, transferAmount), + "ERC20 transfer failed" + ); + emit OperationCompleted("erc20_transfer", true); + + // 2. ICS20 transfer (this will trigger delegation in beforeTransfer hook) + uint64 sequence = ICS20_CONTRACT.transfer( + sourcePort, + sourceChannel, + denom, + ics20Amount, + address(this), + ics20Receiver, + timeoutHeight, + timeoutTimestamp, + "" // empty memo + ); + emit TransferInitiated(ics20Receiver, ics20Amount); + emit OperationCompleted("ics20_transfer", true); + } + + /// @dev Scenario 10: ERC20 Transfer -> ICS20 Transfer (reverted & caught, with delegation in beforeTransfer) + /// @param token ERC20 token address + /// @param recipient Recipient for ERC20 transfer + /// @param transferAmount Amount to transfer via ERC20 + /// @param sourcePort ICS20 source port + /// @param sourceChannel ICS20 source channel + /// @param denom Denomination for ICS20 transfer + /// @param ics20Amount Amount for ICS20 transfer (will be excessive to cause revert) + /// @param ics20Receiver Bech32 receiver address for ICS20 + /// @param timeoutHeight Timeout height for ICS20 + /// @param timeoutTimestamp Timeout timestamp for ICS20 + function scenario10_transferICS20TransferRevert( + address token, + address recipient, + uint256 transferAmount, + string memory sourcePort, + string memory sourceChannel, + string memory denom, + uint256 ics20Amount, + string memory ics20Receiver, + Height memory timeoutHeight, + uint64 timeoutTimestamp + ) external { + // 1. Try ERC20 transfer (will revert if insufficient balance, catch it) + try IERC20(token).transfer(recipient, transferAmount) returns (bool success) { + if (success) { + emit OperationCompleted("erc20_transfer", true); + } else { + emit OperationCompleted("erc20_transfer", false); + } + } catch { + emit OperationCompleted("erc20_transfer", false); + } + + // 2. ICS20 transfer (should succeed with delegation in beforeTransfer hook) + uint64 sequence = ICS20_CONTRACT.transfer( + sourcePort, + sourceChannel, + denom, + ics20Amount, + address(this), + ics20Receiver, + timeoutHeight, + timeoutTimestamp, + "" // empty memo + ); + emit TransferInitiated(ics20Receiver, ics20Amount); + emit OperationCompleted("ics20_transfer", true); + } + + /// @dev Get balance of ERC20 token + function getTokenBalance(address token, address account) external view returns (uint256) { + return IERC20(token).balanceOf(account); + } + + /// @dev Receive function to accept native tokens + receive() external payable {} +} diff --git a/contracts/solidity/SequentialICS20Sender.json b/contracts/solidity/SequentialICS20Sender.json new file mode 100644 index 00000000..95270047 --- /dev/null +++ b/contracts/solidity/SequentialICS20Sender.json @@ -0,0 +1,168 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "SequentialICS20Sender", + "sourceName": "solidity/SequentialICS20Sender.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "name": "BalanceQueried", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "attempt", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "name": "ICS20SendAttempt", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "attempt", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "SequentialSendReverted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensReturned", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "getBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "string", + "name": "sourcePort", + "type": "string" + }, + { + "internalType": "string", + "name": "sourceChannel", + "type": "string" + }, + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "string", + "name": "receiver", + "type": "string" + }, + { + "internalType": "uint64", + "name": "timeoutHeight", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "receiveAndSendTwice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6080806040523461001657610581908161001c8239f35b600080fdfe6040608081526004908136101561001557600080fd5b600090813560e01c806365ab4537146100d45763f8b2cb4f1461003757600080fd5b346100d057602092836003193601126100cc57836001600160a01b0361005b61038d565b169160248451809481936370a0823160e01b835230908301525afa9283156100c157809361008c575b505051908152f35b909192508382813d83116100ba575b6100a581836103da565b810103126100b7575051903880610084565b80fd5b503d61009b565b8251903d90823e3d90fd5b8280fd5b5080fd5b508290346100cc5760e03660031901126100cc576100f061038d565b67ffffffffffffffff91906024358381116103895761011290369086016103fc565b906044358481116103855761012a90369087016103fc565b906064358581116103815761014290369088016103fc565b9260843586811161037d5761015a90369089016103fc565b9560a43590811680910361037d5785516323b872dd60e01b8152338982015230602482015260c43560448201819052602098909490916001600160a01b039091169089816064818f865af1908115610373578c91610339575b5015610301578389969594938c9389938b519081528b888b8301527f5a0ebf9442637ca6e817894481a6de0c29715a73efc9e02bb7ef4ed52843362d91a18c8b516101fd816103a8565b60018152838b8201528c51948591848c8c63632535b960e01b9a8b8752309288880196610229976104b3565b03978a856108029a818a8d5af194610269956102e4575b508c519361024d856103a8565b600185528b8501528c519b8c9a8b998a988952309489016104b3565b03925af190816102b7575b506102b3575162461bcd60e51b815291820152601660248201527514d958dbdb9908151c985b9cd9995c8811985a5b195960521b604482015260649150fd5b8380f35b6102d690843d86116102dd575b6102ce81836103da565b810190610453565b5085610274565b503d6102c4565b6102fa908c8d3d106102dd576102ce81836103da565b5038610240565b875162461bcd60e51b8152808b018a90526012602482015271151c985b9cd9995c881a5b8819985a5b195960721b6044820152606490fd5b90508981813d831161036c575b61035081836103da565b8101031261036857518015158103610368578c6101b3565b8b80fd5b503d610346565b89513d8e823e3d90fd5b8880fd5b8780fd5b8680fd5b8580fd5b600435906001600160a01b03821682036103a357565b600080fd5b6040810190811067ffffffffffffffff8211176103c457604052565b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff8211176103c457604052565b81601f820112156103a35780359067ffffffffffffffff82116103c45760405192610431601f8401601f1916602001856103da565b828452602083830101116103a357816000926020809301838601378301015290565b908160209103126103a3575167ffffffffffffffff811681036103a35790565b919082519283825260005b84811061049f575050826000602080949584010152601f8019910116010190565b60208183018101518483018201520161047e565b949061051594936104e460209998946104d76104f294610140808c528b0190610473565b908982038c8b0152610473565b908782036040890152610473565b60608601939093526001600160a01b0316608085015283820360a0850152610473565b918367ffffffffffffffff918281511660c085015201511660e0820152600061010082015261012081830391015260008152019056fea26469706673582212205e4dfe16435cdbcf4051376984524968aeb3cd20e6678b3eee0c9c4e0db664b564736f6c63430008140033", + "deployedBytecode": "0x6040608081526004908136101561001557600080fd5b600090813560e01c806365ab4537146100d45763f8b2cb4f1461003757600080fd5b346100d057602092836003193601126100cc57836001600160a01b0361005b61038d565b169160248451809481936370a0823160e01b835230908301525afa9283156100c157809361008c575b505051908152f35b909192508382813d83116100ba575b6100a581836103da565b810103126100b7575051903880610084565b80fd5b503d61009b565b8251903d90823e3d90fd5b8280fd5b5080fd5b508290346100cc5760e03660031901126100cc576100f061038d565b67ffffffffffffffff91906024358381116103895761011290369086016103fc565b906044358481116103855761012a90369087016103fc565b906064358581116103815761014290369088016103fc565b9260843586811161037d5761015a90369089016103fc565b9560a43590811680910361037d5785516323b872dd60e01b8152338982015230602482015260c43560448201819052602098909490916001600160a01b039091169089816064818f865af1908115610373578c91610339575b5015610301578389969594938c9389938b519081528b888b8301527f5a0ebf9442637ca6e817894481a6de0c29715a73efc9e02bb7ef4ed52843362d91a18c8b516101fd816103a8565b60018152838b8201528c51948591848c8c63632535b960e01b9a8b8752309288880196610229976104b3565b03978a856108029a818a8d5af194610269956102e4575b508c519361024d856103a8565b600185528b8501528c519b8c9a8b998a988952309489016104b3565b03925af190816102b7575b506102b3575162461bcd60e51b815291820152601660248201527514d958dbdb9908151c985b9cd9995c8811985a5b195960521b604482015260649150fd5b8380f35b6102d690843d86116102dd575b6102ce81836103da565b810190610453565b5085610274565b503d6102c4565b6102fa908c8d3d106102dd576102ce81836103da565b5038610240565b875162461bcd60e51b8152808b018a90526012602482015271151c985b9cd9995c881a5b8819985a5b195960721b6044820152606490fd5b90508981813d831161036c575b61035081836103da565b8101031261036857518015158103610368578c6101b3565b8b80fd5b503d610346565b89513d8e823e3d90fd5b8880fd5b8780fd5b8680fd5b8580fd5b600435906001600160a01b03821682036103a357565b600080fd5b6040810190811067ffffffffffffffff8211176103c457604052565b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff8211176103c457604052565b81601f820112156103a35780359067ffffffffffffffff82116103c45760405192610431601f8401601f1916602001856103da565b828452602083830101116103a357816000926020809301838601378301015290565b908160209103126103a3575167ffffffffffffffff811681036103a35790565b919082519283825260005b84811061049f575050826000602080949584010152601f8019910116010190565b60208183018101518483018201520161047e565b949061051594936104e460209998946104d76104f294610140808c528b0190610473565b908982038c8b0152610473565b908782036040890152610473565b60608601939093526001600160a01b0316608085015283820360a0850152610473565b918367ffffffffffffffff918281511660c085015201511660e0820152600061010082015261012081830391015260008152019056fea26469706673582212205e4dfe16435cdbcf4051376984524968aeb3cd20e6678b3eee0c9c4e0db664b564736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/contracts/solidity/SequentialICS20Sender.sol b/contracts/solidity/SequentialICS20Sender.sol new file mode 100644 index 00000000..db73679a --- /dev/null +++ b/contracts/solidity/SequentialICS20Sender.sol @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "./precompiles/ics20/ICS20I.sol"; +import "./precompiles/erc20/IERC20.sol"; +import "./precompiles/common/Types.sol"; + +/** + * @dev Contract that receives ERC20 tokens and performs sequential max ICS20 sends. + * Used to test that two sequential max balance sends revert properly. + */ +contract SequentialICS20Sender { + event ICS20SendAttempt(uint256 indexed attempt, uint256 amount, bool success); + event SequentialSendReverted(uint256 indexed attempt, string reason); + event BalanceQueried(uint256 balance); + event TokensReceived(address token, uint256 amount); + event TokensReturned(address token, uint256 amount); + + /// @dev Receive tokens, perform two sequential ICS20 sends, return remaining tokens. + /// Mirrors production flow: transfer in -> ICS20 sends -> transfer out. + /// @param token ERC20 token address + /// @param sourcePort IBC source port + /// @param sourceChannel IBC source channel + /// @param denom Token denomination (e.g., "erc20:0x...") + /// @param receiver Bech32 receiver address on destination chain + /// @param timeoutHeight IBC timeout height + /// @param amount The amount to transfer in and send in each ICS20 transfer + function receiveAndSendTwice( + address token, + string memory sourcePort, + string memory sourceChannel, + string memory denom, + string memory receiver, + uint64 timeoutHeight, + uint256 amount + ) external { + // 1. Transfer tokens from sender to this contract + require( + IERC20(token).transferFrom(msg.sender, address(this), amount), + "Transfer in failed" + ); + emit TokensReceived(token, amount); + + // 2. First ICS20 send + try ICS20_CONTRACT.transfer( + sourcePort, + sourceChannel, + denom, + amount, + address(this), + receiver, + Height({revisionNumber: 1, revisionHeight: timeoutHeight}), + 0, + "" + ) returns (uint64) { + } catch { + } + + // 3. Second ICS20 send + try ICS20_CONTRACT.transfer( + sourcePort, + sourceChannel, + denom, + amount, + address(this), + receiver, + Height({revisionNumber: 1, revisionHeight: timeoutHeight}), + 0, + "" + ) returns (uint64) { + } catch { + revert("Second Transfer Failed"); + } + } + + + /// @dev Query balance of an ERC20 token for this contract + function getBalance(address token) external view returns (uint256) { + return IERC20(token).balanceOf(address(this)); + } +} diff --git a/contracts/solidity/SequentialOperationsTester.json b/contracts/solidity/SequentialOperationsTester.json new file mode 100644 index 00000000..1d7de80a --- /dev/null +++ b/contracts/solidity/SequentialOperationsTester.json @@ -0,0 +1,277 @@ +{ + "_format": "hh3-artifact-1", + "contractName": "SequentialOperationsTester", + "sourceName": "solidity/SequentialOperationsTester.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "name": "BalanceChecked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "count", + "type": "uint256" + } + ], + "name": "EventCountChecked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "operation", + "type": "string" + }, + { + "indexed": false, + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "name": "OperationCompleted", + "type": "event" + }, + { + "inputs": [], + "name": "getContractBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getNativeBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getTokenBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "string", + "name": "validatorAddr", + "type": "string" + }, + { + "internalType": "uint256", + "name": "delegateAmount", + "type": "uint256" + } + ], + "name": "scenario1_transferDelegateTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "string", + "name": "validatorAddr", + "type": "string" + }, + { + "internalType": "uint256", + "name": "delegateAmount", + "type": "uint256" + } + ], + "name": "scenario2_transferDelegateRevertTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "string", + "name": "validatorAddr", + "type": "string" + }, + { + "internalType": "uint256", + "name": "delegateAmount", + "type": "uint256" + } + ], + "name": "scenario3_nativeTransferDelegateNativeTransfer", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "string", + "name": "validatorAddr", + "type": "string" + }, + { + "internalType": "uint256", + "name": "delegateAmount", + "type": "uint256" + } + ], + "name": "scenario4_nativeTransferDelegateRevertNativeTransfer", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "testNativeTransfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x6080806040523461001657610ab0908161001b8239f35b5f80fdfe6040608081526004908136101561001f575b5050361561001d575f80fd5b005b5f91823560e01c908163456503c8146105625781635b3d97d5146104a05781635c3f86c9146103875781636e348ad6146101ad5781636f9fb98a14610192578163c489744b146100e257508063e1f756c3146100a75763efd8be620361001157346100a35760203660031901126100a35760209061009b610692565b319051908152f35b5080fd5b50806003193601126100a3578180806020946100c1610692565b602435906001600160a01b03165af1906100d9610961565b50519015158152f35b919050346101785780600319360112610178576100fd610692565b916024356001600160a01b038181169182900361018e57602092602491855196879485936370a0823160e01b8552840152165afa918215610184578392610149575b6020838351908152f35b9091506020813d821161017c575b81610164602093836106ac565b81010312610178576020925051905f61013f565b8280fd5b3d9150610157565b81513d85823e3d90fd5b8580fd5b5050346100a357816003193601126100a35751478152602090f35b905034610178576101bd36610744565b865163a9059cbb60e01b8082526001600160a01b038681168984019081526020808201889052949a959995989497959490911693928b9291889082908190604001038186895af190811561037d579a610222899261025c9d8691610360575b50610800565b89519a5f80516020610a5b8339815191528c8061023f839f610844565b0390a18a516353266bbb60e01b81529c8d9283923089850161086f565b0381856108005af1998a15610356578798999a979697610339575b5089895180610285816108c9565b0390a16102b28951978896879586948552840160209093929193604081019460018060a01b031681520152565b03925af191821561032f57906102d192918692610302575b505061091c565b516040808252600990820152683a3930b739b332b91960b91b60608201526001602082015280608081015b0390a180f35b6103219250803d10610328575b61031981836106ac565b8101906107e8565b5f806102ca565b503d61030f565b83513d87823e3d90fd5b61034f90873d89116103285761031981836106ac565b505f610277565b88513d84823e3d90fd5b6103779150843d86116103285761031981836106ac565b5f61021c565b89513d85823e3d90fd5b91905061043783808080602061039c3661079e565b91936001600160a01b0390931692906103c48680808089895af16103be610961565b50610990565b8a519b5f80516020610a5b8339815191528d80829f6103e2906109dc565b0390a16104028c5194859384936353266bbb60e01b85523090850161086f565b0381876108005af19081610482575b5061046d5788885180610423816108f3565b0390a15b5af1610431610961565b50610a0e565b5160408082526010908201526f3730ba34bb32afba3930b739b332b91960811b60608201526001602082015280608081016102fc565b8888518061047a816108c9565b0390a1610427565b6104999060203d81116103285761031981836106ac565b505f610411565b9190508260206104af3661079e565b91936001600160a01b0390931692906104d18680808089895af16103be610961565b8651975f80516020610a5b83398151915289806104ee839c6109dc565b0390a161050e885194859384936353266bbb60e01b85523090850161086f565b0381876108005af1801561055857938093819382936104379761053a575b5088885180610423816108c9565b6105519060203d81116103285761031981836106ac565b505f61052c565b85513d86823e3d90fd5b9050346101785761057236610744565b865163a9059cbb60e01b8082526001600160a01b038681168984019081526020808201889052949a959995989497959490911693928b9291889082908190604001038186895af190811561037d579780999a9b6105db61061593839a9b87916103605750610800565b8b519c5f80516020610a5b8339815191528e819f6105f881610844565b0390a18c516353266bbb60e01b81529384928392308a850161086f565b0381866108005af19081610675575b506106605789895180610285816108f3565b6102b28951978896879586948552840160209093929193604081019460018060a01b031681520152565b8989518061066d816108c9565b0390a1610636565b61068b90883d8a116103285761031981836106ac565b505f610624565b600435906001600160a01b03821682036106a857565b5f80fd5b90601f8019910116810190811067ffffffffffffffff8211176106ce57604052565b634e487b7160e01b5f52604160045260245ffd5b67ffffffffffffffff81116106ce57601f01601f191660200190565b81601f820112156106a857803590610715826106e2565b9261072360405194856106ac565b828452602083830101116106a857815f926020809301838601378301015290565b9060a06003198301126106a8576001600160a01b039160043583811681036106a8579260243590811681036106a85791604435916064359067ffffffffffffffff82116106a857610797916004016106fe565b9060843590565b60806003198201126106a8576004356001600160a01b03811681036106a85791602435916044359067ffffffffffffffff82116106a8576107e1916004016106fe565b9060643590565b908160209103126106a8575180151581036106a85790565b1561080757565b60405162461bcd60e51b8152602060048201526015602482015274119a5c9cdd081d1c985b9cd9995c8819985a5b1959605a1b6044820152606490fd5b906040825260096040830152687472616e736665723160b81b60608301526001602060808401930152565b9392919060018060a01b0316845260206060818601528151918260608701525f5b8381106108b5575050506080815f8260409488010152601f8019910116850101930152565b818101830151878201608001528201610890565b9060408252600860408301526764656c656761746560c01b60608301526001602060808401930152565b9060408252600860408301526764656c656761746560c01b60608301525f602060808401930152565b1561092357565b60405162461bcd60e51b815260206004820152601660248201527514d958dbdb99081d1c985b9cd9995c8819985a5b195960521b6044820152606490fd5b3d1561098b573d90610972826106e2565b9161098060405193846106ac565b82523d5f602084013e565b606090565b1561099757565b60405162461bcd60e51b815260206004820152601c60248201527f4669727374206e6174697665207472616e73666572206661696c6564000000006044820152606490fd5b9060408252601060408301526f6e61746976655f7472616e736665723160801b60608301526001602060808401930152565b15610a1557565b60405162461bcd60e51b815260206004820152601d60248201527f5365636f6e64206e6174697665207472616e73666572206661696c65640000006044820152606490fdfe9f4d25774676d497fe3d8c1e43709b68b186fad01b05798c1410a178ff4ed7d0a26469706673582212209828da0fad34acc382c5f6e2e016ef5f88bf747fdacc2b9ec5f0431514fe5aba64736f6c63430008140033", + "deployedBytecode": "0x6040608081526004908136101561001f575b5050361561001d575f80fd5b005b5f91823560e01c908163456503c8146105625781635b3d97d5146104a05781635c3f86c9146103875781636e348ad6146101ad5781636f9fb98a14610192578163c489744b146100e257508063e1f756c3146100a75763efd8be620361001157346100a35760203660031901126100a35760209061009b610692565b319051908152f35b5080fd5b50806003193601126100a3578180806020946100c1610692565b602435906001600160a01b03165af1906100d9610961565b50519015158152f35b919050346101785780600319360112610178576100fd610692565b916024356001600160a01b038181169182900361018e57602092602491855196879485936370a0823160e01b8552840152165afa918215610184578392610149575b6020838351908152f35b9091506020813d821161017c575b81610164602093836106ac565b81010312610178576020925051905f61013f565b8280fd5b3d9150610157565b81513d85823e3d90fd5b8580fd5b5050346100a357816003193601126100a35751478152602090f35b905034610178576101bd36610744565b865163a9059cbb60e01b8082526001600160a01b038681168984019081526020808201889052949a959995989497959490911693928b9291889082908190604001038186895af190811561037d579a610222899261025c9d8691610360575b50610800565b89519a5f80516020610a5b8339815191528c8061023f839f610844565b0390a18a516353266bbb60e01b81529c8d9283923089850161086f565b0381856108005af1998a15610356578798999a979697610339575b5089895180610285816108c9565b0390a16102b28951978896879586948552840160209093929193604081019460018060a01b031681520152565b03925af191821561032f57906102d192918692610302575b505061091c565b516040808252600990820152683a3930b739b332b91960b91b60608201526001602082015280608081015b0390a180f35b6103219250803d10610328575b61031981836106ac565b8101906107e8565b5f806102ca565b503d61030f565b83513d87823e3d90fd5b61034f90873d89116103285761031981836106ac565b505f610277565b88513d84823e3d90fd5b6103779150843d86116103285761031981836106ac565b5f61021c565b89513d85823e3d90fd5b91905061043783808080602061039c3661079e565b91936001600160a01b0390931692906103c48680808089895af16103be610961565b50610990565b8a519b5f80516020610a5b8339815191528d80829f6103e2906109dc565b0390a16104028c5194859384936353266bbb60e01b85523090850161086f565b0381876108005af19081610482575b5061046d5788885180610423816108f3565b0390a15b5af1610431610961565b50610a0e565b5160408082526010908201526f3730ba34bb32afba3930b739b332b91960811b60608201526001602082015280608081016102fc565b8888518061047a816108c9565b0390a1610427565b6104999060203d81116103285761031981836106ac565b505f610411565b9190508260206104af3661079e565b91936001600160a01b0390931692906104d18680808089895af16103be610961565b8651975f80516020610a5b83398151915289806104ee839c6109dc565b0390a161050e885194859384936353266bbb60e01b85523090850161086f565b0381876108005af1801561055857938093819382936104379761053a575b5088885180610423816108c9565b6105519060203d81116103285761031981836106ac565b505f61052c565b85513d86823e3d90fd5b9050346101785761057236610744565b865163a9059cbb60e01b8082526001600160a01b038681168984019081526020808201889052949a959995989497959490911693928b9291889082908190604001038186895af190811561037d579780999a9b6105db61061593839a9b87916103605750610800565b8b519c5f80516020610a5b8339815191528e819f6105f881610844565b0390a18c516353266bbb60e01b81529384928392308a850161086f565b0381866108005af19081610675575b506106605789895180610285816108f3565b6102b28951978896879586948552840160209093929193604081019460018060a01b031681520152565b8989518061066d816108c9565b0390a1610636565b61068b90883d8a116103285761031981836106ac565b505f610624565b600435906001600160a01b03821682036106a857565b5f80fd5b90601f8019910116810190811067ffffffffffffffff8211176106ce57604052565b634e487b7160e01b5f52604160045260245ffd5b67ffffffffffffffff81116106ce57601f01601f191660200190565b81601f820112156106a857803590610715826106e2565b9261072360405194856106ac565b828452602083830101116106a857815f926020809301838601378301015290565b9060a06003198301126106a8576001600160a01b039160043583811681036106a8579260243590811681036106a85791604435916064359067ffffffffffffffff82116106a857610797916004016106fe565b9060843590565b60806003198201126106a8576004356001600160a01b03811681036106a85791602435916044359067ffffffffffffffff82116106a8576107e1916004016106fe565b9060643590565b908160209103126106a8575180151581036106a85790565b1561080757565b60405162461bcd60e51b8152602060048201526015602482015274119a5c9cdd081d1c985b9cd9995c8819985a5b1959605a1b6044820152606490fd5b906040825260096040830152687472616e736665723160b81b60608301526001602060808401930152565b9392919060018060a01b0316845260206060818601528151918260608701525f5b8381106108b5575050506080815f8260409488010152601f8019910116850101930152565b818101830151878201608001528201610890565b9060408252600860408301526764656c656761746560c01b60608301526001602060808401930152565b9060408252600860408301526764656c656761746560c01b60608301525f602060808401930152565b1561092357565b60405162461bcd60e51b815260206004820152601660248201527514d958dbdb99081d1c985b9cd9995c8819985a5b195960521b6044820152606490fd5b3d1561098b573d90610972826106e2565b9161098060405193846106ac565b82523d5f602084013e565b606090565b1561099757565b60405162461bcd60e51b815260206004820152601c60248201527f4669727374206e6174697665207472616e73666572206661696c6564000000006044820152606490fd5b9060408252601060408301526f6e61746976655f7472616e736665723160801b60608301526001602060808401930152565b15610a1557565b60405162461bcd60e51b815260206004820152601d60248201527f5365636f6e64206e6174697665207472616e73666572206661696c65640000006044820152606490fdfe9f4d25774676d497fe3d8c1e43709b68b186fad01b05798c1410a178ff4ed7d0a26469706673582212209828da0fad34acc382c5f6e2e016ef5f88bf747fdacc2b9ec5f0431514fe5aba64736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": {}, + "inputSourceName": "project/solidity/SequentialOperationsTester.sol", + "buildInfoId": "solc-0_8_20-a1f91ec3b065d50730c0367f861277c93634d90c" +} \ No newline at end of file diff --git a/contracts/solidity/SequentialOperationsTester.sol b/contracts/solidity/SequentialOperationsTester.sol new file mode 100644 index 00000000..c17a58c0 --- /dev/null +++ b/contracts/solidity/SequentialOperationsTester.sol @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "./precompiles/staking/StakingI.sol"; +import "./precompiles/erc20/IERC20.sol"; +import "./precompiles/bech32/Bech32I.sol"; +import "./precompiles/common/Types.sol"; + +/** + * @dev Contract to test sequential operations with auto-flush behavior. + * Tests combinations of ERC20 transfers, staking operations, and state changes. + */ +contract SequentialOperationsTester { + event OperationCompleted(string operation, bool success); + event BalanceChecked(string label, uint256 balance); + event EventCountChecked(string label, uint256 count); + + /// @dev Scenario 1: Transfer ERC20 -> Delegate -> Transfer ERC20 + /// @param token ERC20 token address + /// @param recipient Recipient for ERC20 transfers + /// @param amount Amount to transfer + /// @param validatorAddr Validator address (EVM format) + /// @param delegateAmount Amount to delegate + function scenario1_transferDelegateTransfer( + address token, + address recipient, + uint256 amount, + string memory validatorAddr, + uint256 delegateAmount + ) external { + // 1. Transfer ERC20 + require( + IERC20(token).transfer(recipient, amount), + "First transfer failed" + ); + emit OperationCompleted("transfer1", true); + + // 2. Staking delegate - convert from wei (18 decimals) to base denom (6 decimals) + uint256 delegateAmountBaseDenom = delegateAmount; + STAKING_CONTRACT.delegate( + address(this), + validatorAddr, + delegateAmountBaseDenom + ); + emit OperationCompleted("delegate", true); + + // 3. Transfer ERC20 again + require( + IERC20(token).transfer(recipient, amount), + "Second transfer failed" + ); + emit OperationCompleted("transfer2", true); + } + + /// @dev Scenario 2: Transfer ERC20 -> Delegate (reverted & caught) -> Transfer ERC20 + /// @param token ERC20 token address + /// @param recipient Recipient for ERC20 transfers + /// @param amount Amount to transfer + /// @param validatorAddr Validator address (EVM format) + /// @param delegateAmount Amount to delegate (will revert) + function scenario2_transferDelegateRevertTransfer( + address token, + address recipient, + uint256 amount, + string memory validatorAddr, + uint256 delegateAmount + ) external { + // 1. Transfer ERC20 + require( + IERC20(token).transfer(recipient, amount), + "First transfer failed" + ); + emit OperationCompleted("transfer1", true); + + // 2. Try to delegate (will revert, catch it) + uint256 delegateAmountBaseDenom = delegateAmount; + try STAKING_CONTRACT.delegate( + address(this), + validatorAddr, + delegateAmountBaseDenom + ) { + emit OperationCompleted("delegate", true); + } catch { + emit OperationCompleted("delegate", false); + } + + // 3. Transfer ERC20 again + require( + IERC20(token).transfer(recipient, amount), + "Second transfer failed" + ); + emit OperationCompleted("transfer2", true); + } + + /// @dev Scenario 3: Native transfer -> Delegate -> Native transfer + /// @param recipient Recipient for native transfers + /// @param amount Amount of native tokens to transfer (in wei) + /// @param validatorAddr Validator address + /// @param delegateAmount Amount to delegate (in wei, will be converted to base denom) + function scenario3_nativeTransferDelegateNativeTransfer( + address payable recipient, + uint256 amount, + string memory validatorAddr, + uint256 delegateAmount + ) external payable { + // 1. Transfer native tokens + (bool success1, ) = recipient.call{value: amount}(""); + require(success1, "First native transfer failed"); + emit OperationCompleted("native_transfer1", true); + + // 2. Staking delegate - convert from wei (18 decimals) to base denom (6 decimals) + uint256 delegateAmountBaseDenom = delegateAmount; + STAKING_CONTRACT.delegate( + address(this), + validatorAddr, + delegateAmountBaseDenom + ); + emit OperationCompleted("delegate", true); + + // 3. Transfer native tokens again + (bool success2, ) = recipient.call{value: amount}(""); + require(success2, "Second native transfer failed"); + emit OperationCompleted("native_transfer2", true); + } + + /// @dev Scenario 4: Native transfer -> Delegate (reverted & caught) -> Native transfer + /// @param recipient Recipient for native transfers + /// @param amount Amount of native tokens to transfer (in wei) + /// @param validatorAddr Validator address + /// @param delegateAmount Amount to delegate (in wei, will be converted to base denom, will revert) + function scenario4_nativeTransferDelegateRevertNativeTransfer( + address payable recipient, + uint256 amount, + string memory validatorAddr, + uint256 delegateAmount + ) external payable { + // 1. Transfer native tokens + (bool success1, ) = recipient.call{value: amount}(""); + require(success1, "First native transfer failed"); + emit OperationCompleted("native_transfer1", true); + + // 2. Try to delegate - convert from wei (18 decimals) to base denom (6 decimals) + uint256 delegateAmountBaseDenom = delegateAmount; + try STAKING_CONTRACT.delegate( + address(this), + validatorAddr, + delegateAmountBaseDenom + ) { + emit OperationCompleted("delegate", true); + } catch { + emit OperationCompleted("delegate", false); + } + + // 3. Transfer native tokens again + (bool success2, ) = recipient.call{value: amount}(""); + require(success2, "Second native transfer failed"); + emit OperationCompleted("native_transfer2", true); + } + + /// @dev Get balance of ERC20 token + function getTokenBalance(address token, address account) external view returns (uint256) { + return IERC20(token).balanceOf(account); + } + + /// @dev Get native balance + function getNativeBalance(address account) external view returns (uint256) { + return account.balance; + } + + /// @dev Test function to check contract balance + function getContractBalance() external view returns (uint256) { + return address(this).balance; + } + + /// @dev Simple native transfer test + function testNativeTransfer(address payable recipient, uint256 amount) external payable returns (bool) { + (bool success, ) = recipient.call{value: amount}(""); + return success; + } + + /// @dev Receive function to accept native tokens + receive() external payable {} +} diff --git a/contracts/solidity/StaticCallTester.json b/contracts/solidity/StaticCallTester.json new file mode 100644 index 00000000..541a4da7 --- /dev/null +++ b/contracts/solidity/StaticCallTester.json @@ -0,0 +1,172 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "StaticCallTester", + "sourceName": "solidity/StaticCallTester.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_werc20", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "counter", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "doIncrement", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "doPrecompileTransfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getCounter", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "nonStaticIncrement", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "nonStaticPrecompileTransfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "staticIncrement", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "staticPrecompileTransfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "werc20", + "outputs": [ + { + "internalType": "contract IWERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x60803461007457601f61041838819003918201601f19168301916001600160401b038311848410176100795780849260209460405283398101031261007457516001600160a01b0381169081900361007457600080546001600160a01b03191691909117905560405161038890816100908239f35b600080fd5b634e487b7160e01b600052604160045260246000fdfe604060808152600436101561001357600080fd5b600090813560e01c80631cfa8b101461017d5780634d751fbf146101a95780634ebbe1cf146101a95780635741229c1461018257806361bc221a1461015f578063677d4eca1461017d5780638ada066e1461015f578063dfe9a695146100f55763eae6bdeb1461008257600080fd5b346100f157816003193601126100f1578051634ebbe1cf60e01b6020820190815260048252929080830167ffffffffffffffff8111828210176100dd57835251602093829190305afa906100d4610312565b50519015158152f35b634e487b7160e01b83526041600452602483fd5b5080fd5b50346100f1578160209261015161014361010e366101ae565b86516301cfa8b160e41b8982019081526001600160a01b03909316602482015260448101919091529092909182906064820190565b03601f1981018352826102da565b5190305afa906100d4610312565b50346100f157816003193601126100f1576020906001549051908152f35b6101d9565b50346100f157816003193601126100f157905490516001600160a01b039091168152602090f35b610295565b60409060031901126101d4576004356001600160a01b03811681036101d4579060243590565b600080fd5b346101d457602061022d6101ec366101ae565b6000805460405163a9059cbb60e01b81526001600160a01b039485166004820152602481019390935290949193919284929116908290869082906044820190565b03925af190811561028a57829161024c575b6020826040519015158152f35b90506020813d8211610282575b81610266602093836102da565b810103126100f1575180151581036100f157602091503861023f565b3d9150610259565b6040513d84823e3d90fd5b346101d45760003660031901126101d45760015460001981146102c45760016020910180600155604051908152f35b634e487b7160e01b600052601160045260246000fd5b90601f8019910116810190811067ffffffffffffffff8211176102fc57604052565b634e487b7160e01b600052604160045260246000fd5b3d1561034d573d9067ffffffffffffffff82116102fc5760405191610341601f8201601f1916602001846102da565b82523d6000602084013e565b60609056fea2646970667358221220e77e9a7f006cac4b937c19161fc0535b14d5ddad274962e4884498f23ba333cc64736f6c63430008140033", + "deployedBytecode": "0x604060808152600436101561001357600080fd5b600090813560e01c80631cfa8b101461017d5780634d751fbf146101a95780634ebbe1cf146101a95780635741229c1461018257806361bc221a1461015f578063677d4eca1461017d5780638ada066e1461015f578063dfe9a695146100f55763eae6bdeb1461008257600080fd5b346100f157816003193601126100f1578051634ebbe1cf60e01b6020820190815260048252929080830167ffffffffffffffff8111828210176100dd57835251602093829190305afa906100d4610312565b50519015158152f35b634e487b7160e01b83526041600452602483fd5b5080fd5b50346100f1578160209261015161014361010e366101ae565b86516301cfa8b160e41b8982019081526001600160a01b03909316602482015260448101919091529092909182906064820190565b03601f1981018352826102da565b5190305afa906100d4610312565b50346100f157816003193601126100f1576020906001549051908152f35b6101d9565b50346100f157816003193601126100f157905490516001600160a01b039091168152602090f35b610295565b60409060031901126101d4576004356001600160a01b03811681036101d4579060243590565b600080fd5b346101d457602061022d6101ec366101ae565b6000805460405163a9059cbb60e01b81526001600160a01b039485166004820152602481019390935290949193919284929116908290869082906044820190565b03925af190811561028a57829161024c575b6020826040519015158152f35b90506020813d8211610282575b81610266602093836102da565b810103126100f1575180151581036100f157602091503861023f565b3d9150610259565b6040513d84823e3d90fd5b346101d45760003660031901126101d45760015460001981146102c45760016020910180600155604051908152f35b634e487b7160e01b600052601160045260246000fd5b90601f8019910116810190811067ffffffffffffffff8211176102fc57604052565b634e487b7160e01b600052604160045260246000fd5b3d1561034d573d9067ffffffffffffffff82116102fc5760405191610341601f8201601f1916602001846102da565b82523d6000602084013e565b60609056fea2646970667358221220e77e9a7f006cac4b937c19161fc0535b14d5ddad274962e4884498f23ba333cc64736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/contracts/solidity/StaticCallTester.sol b/contracts/solidity/StaticCallTester.sol new file mode 100644 index 00000000..50506c49 --- /dev/null +++ b/contracts/solidity/StaticCallTester.sol @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IWERC20 { + function transfer(address to, uint256 amount) external returns (bool); + function transferFrom(address from, address to, uint256 amount) external returns (bool); + function approve(address spender, uint256 amount) external returns (bool); + function balanceOf(address account) external view returns (uint256); + function deposit() external payable; +} + +/// @notice Interface with a view function that will be called via STATICCALL. +interface ICallback { + function callback() external view returns (string memory); +} + +/// @notice Contract that attempts state changes when called via a view interface. +/// When ViewCaller calls ICallback(target).callback(), Solidity uses STATICCALL because +/// the ICallback interface declares callback() as view. Inside that static context, this +/// contract attempts to call werc20.transfer(). +/// +/// KEY: The interface declares view, but this implementation does NOT. +/// This compiles fine, but when called via the interface, STATICCALL is used. +contract StaticCallbackTarget { + IWERC20 public werc20; + address public transferTarget; + uint256 public transferAmount; + + constructor(address _werc20) { + werc20 = IWERC20(_werc20); + } + + function setTransferParams(address target, uint256 amount) external { + transferTarget = target; + transferAmount = amount; + } + + /// @notice NOT marked as view here, but ICallback interface declares it as view. + /// When called via ICallback(this).callback(), the caller uses STATICCALL. + /// Inside that static context, we attempt a state-changing precompile call. + function callback() external returns (string memory) { + // Attempt transfer inside static context - use low-level call to capture success. + // Note: We use a regular CALL here (not staticcall) to test if the EVM + // correctly propagates the static flag to precompile calls. + (bool success, ) = address(werc20).call( + abi.encodeWithSelector(IWERC20.transfer.selector, transferTarget, transferAmount) + ); + + if (success) { + return "TRANSFER_SUCCEEDED"; + } + return "TRANSFER_FAILED"; + } +} + +/// @notice Contract that invokes a view function on another contract. +contract ViewCaller { + /// @notice Calls callback() on the target using STATICCALL (implicit because it's view). + /// Returns the result string from the view call. + function callViewFunction(address target) external view returns (string memory) { + return ICallback(target).callback(); + } + + /// @notice Non-view version that executes the staticcall and returns result. + function callViewAndReturn(address target) external returns (string memory) { + return ICallback(target).callback(); + } +} + +/// @notice Simple test contract for basic STATICCALL + SSTORE protection. +contract StaticCallTester { + IWERC20 public werc20; + uint256 public counter; + + constructor(address _werc20) { + werc20 = IWERC20(_werc20); + } + + /// @notice Direct WERC20 transfer (non-static context). + function nonStaticPrecompileTransfer(address to, uint256 amount) external returns (bool) { + return werc20.transfer(to, amount); + } + + /// @notice Helper called via staticcall by staticPrecompileTransfer. + function doPrecompileTransfer(address to, uint256 amount) external returns (bool) { + return werc20.transfer(to, amount); + } + + /// @notice Attempts WERC20 transfer inside a STATICCALL context. + function staticPrecompileTransfer(address to, uint256 amount) external returns (bool) { + (bool success, ) = address(this).staticcall( + abi.encodeWithSelector(this.doPrecompileTransfer.selector, to, amount) + ); + return success; + } + + /// @notice Direct counter increment (non-static context). + function nonStaticIncrement() external returns (uint256) { + counter++; + return counter; + } + + /// @notice Helper called via staticcall by staticIncrement. + function doIncrement() external returns (uint256) { + counter++; + return counter; + } + + /// @notice Attempts counter increment inside a STATICCALL context. + function staticIncrement() external returns (bool) { + (bool success, ) = address(this).staticcall( + abi.encodeWithSelector(this.doIncrement.selector) + ); + return success; + } + + function getCounter() external view returns (uint256) { + return counter; + } +} diff --git a/contracts/solidity/StaticCallbackTarget.json b/contracts/solidity/StaticCallbackTarget.json new file mode 100644 index 00000000..9203672c --- /dev/null +++ b/contracts/solidity/StaticCallbackTarget.json @@ -0,0 +1,92 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "StaticCallbackTarget", + "sourceName": "solidity/StaticCallTester.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_werc20", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "callback", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "setTransferParams", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "transferAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "transferTarget", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "werc20", + "outputs": [ + { + "internalType": "contract IWERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x60803461007457601f61039d38819003918201601f19168301916001600160401b038311848410176100795780849260209460405283398101031261007457516001600160a01b0381169081900361007457600080546001600160a01b03191691909117905560405161030d90816100908239f35b600080fd5b634e487b7160e01b600052604160045260246000fdfe604060808152600436101561001357600080fd5b600090813560e01c8063083b27321461010b5780633d165d42146100c657806341ae9b581461009e578063504d27fd1461008057635741229c1461005657600080fd5b3461007c578160031936011261007c57905490516001600160a01b039091168152602090f35b5080fd5b503461007c578160031936011261007c576020906002549051908152f35b503461007c578160031936011261007c5760015490516001600160a01b039091168152602090f35b503461007c57366003190112610108576004356001600160a01b0381169081900361007c57600180546001600160a01b03191691909117905560243560025580f35b80fd5b503461007c578160031936011261007c5761012461019f565b91815192839160208084528251928382860152825b84811061015757505050828201840152601f01601f19168101030190f35b8181018301518882018801528795508201610139565b6040810190811067ffffffffffffffff82111761018957604052565b634e487b7160e01b600052604160045260246000fd5b600080546001546002546040805163a9059cbb60e01b602082019081526001600160a01b03948516602483015260448083019490945292815290949367ffffffffffffffff9316919060808101848111828210176102c357865251849283929083905af1913d156102bc573d8281116102a857845192601f8201601f19908116603f0116840190811184821017610294578552825260203d92013e5b61026857516102498161016d565b600f81526e1514905394d1915497d19052531151608a1b602082015290565b516102728161016d565b60128152711514905394d1915497d4d550d0d15151115160721b602082015290565b634e487b7160e01b83526041600452602483fd5b634e487b7160e01b82526041600452602482fd5b505061023b565b634e487b7160e01b86526041600452602486fdfea2646970667358221220790024c0a8cf9f5b5ccb5cbb4fb06d5aeb9edf3d3c4a5eee7f3a15ff456d6fbf64736f6c63430008140033", + "deployedBytecode": "0x604060808152600436101561001357600080fd5b600090813560e01c8063083b27321461010b5780633d165d42146100c657806341ae9b581461009e578063504d27fd1461008057635741229c1461005657600080fd5b3461007c578160031936011261007c57905490516001600160a01b039091168152602090f35b5080fd5b503461007c578160031936011261007c576020906002549051908152f35b503461007c578160031936011261007c5760015490516001600160a01b039091168152602090f35b503461007c57366003190112610108576004356001600160a01b0381169081900361007c57600180546001600160a01b03191691909117905560243560025580f35b80fd5b503461007c578160031936011261007c5761012461019f565b91815192839160208084528251928382860152825b84811061015757505050828201840152601f01601f19168101030190f35b8181018301518882018801528795508201610139565b6040810190811067ffffffffffffffff82111761018957604052565b634e487b7160e01b600052604160045260246000fd5b600080546001546002546040805163a9059cbb60e01b602082019081526001600160a01b03948516602483015260448083019490945292815290949367ffffffffffffffff9316919060808101848111828210176102c357865251849283929083905af1913d156102bc573d8281116102a857845192601f8201601f19908116603f0116840190811184821017610294578552825260203d92013e5b61026857516102498161016d565b600f81526e1514905394d1915497d19052531151608a1b602082015290565b516102728161016d565b60128152711514905394d1915497d4d550d0d15151115160721b602082015290565b634e487b7160e01b83526041600452602483fd5b634e487b7160e01b82526041600452602482fd5b505061023b565b634e487b7160e01b86526041600452602486fdfea2646970667358221220790024c0a8cf9f5b5ccb5cbb4fb06d5aeb9edf3d3c4a5eee7f3a15ff456d6fbf64736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/contracts/solidity/ViewCaller.json b/contracts/solidity/ViewCaller.json new file mode 100644 index 00000000..07c14426 --- /dev/null +++ b/contracts/solidity/ViewCaller.json @@ -0,0 +1,49 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ViewCaller", + "sourceName": "solidity/StaticCallTester.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "callViewAndReturn", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "callViewFunction", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x60808060405234610016576101f7908161001c8239f35b600080fdfe6080604052600436101561001257600080fd5b60003560e01c80637539f146146100325763fc61abd91461003257600080fd5b61005a565b60005b83811061004a5750506000910152565b818101518382015260200161003a565b3461018457602080600319360112610184576004356001600160a01b0381169190829003610184576040908151809363041d939960e11b825281600460009384935afa9081156101795780916100db575b506100cd93508251938285938452825192818480938701528686019101610037565b601f01601f19168101030190f35b90503d8082863e6100ec8186610189565b840190828583031261015e57845167ffffffffffffffff9586821161017557019082601f8301121561015e57815195861161016157845192610137601f8801601f1916860185610189565b86845284878401011161015e57506100cd9461015891848085019101610037565b386100ab565b80fd5b634e487b7160e01b81526041600452602490fd5b8280fd5b8351903d90823e3d90fd5b600080fd5b90601f8019910116810190811067ffffffffffffffff8211176101ab57604052565b634e487b7160e01b600052604160045260246000fdfea2646970667358221220b1147e751527d97b2fe436736723e36b7fa65857a2d0fc889252a1aa2e2b843264736f6c63430008140033", + "deployedBytecode": "0x6080604052600436101561001257600080fd5b60003560e01c80637539f146146100325763fc61abd91461003257600080fd5b61005a565b60005b83811061004a5750506000910152565b818101518382015260200161003a565b3461018457602080600319360112610184576004356001600160a01b0381169190829003610184576040908151809363041d939960e11b825281600460009384935afa9081156101795780916100db575b506100cd93508251938285938452825192818480938701528686019101610037565b601f01601f19168101030190f35b90503d8082863e6100ec8186610189565b840190828583031261015e57845167ffffffffffffffff9586821161017557019082601f8301121561015e57815195861161016157845192610137601f8801601f1916860185610189565b86845284878401011161015e57506100cd9461015891848085019101610037565b386100ab565b80fd5b634e487b7160e01b81526041600452602490fd5b8280fd5b8351903d90823e3d90fd5b600080fd5b90601f8019910116810190811067ffffffffffffffff8211176101ab57604052565b634e487b7160e01b600052604160045260246000fdfea2646970667358221220b1147e751527d97b2fe436736723e36b7fa65857a2d0fc889252a1aa2e2b843264736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/contracts/solidity/eips/testdata/Counter.sol b/contracts/solidity/eips/testdata/Counter.sol new file mode 100644 index 00000000..30ba0869 --- /dev/null +++ b/contracts/solidity/eips/testdata/Counter.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: LGPL-3.0-only + +pragma solidity >=0.7.0 <0.9.0; + +contract Counter { + uint256 public counter = 1; + + function increment() external { + counter++; + } + + function decrement() external { + counter--; + } +} diff --git a/contracts/solidity/eips/testdata/CounterFactory.sol b/contracts/solidity/eips/testdata/CounterFactory.sol new file mode 100644 index 00000000..7b64412d --- /dev/null +++ b/contracts/solidity/eips/testdata/CounterFactory.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: LGPL-3.0-only + +pragma solidity >=0.7.0 <0.9.0; + +import "./Counter.sol"; + +contract Counterfactory { + Counter public counterInstance; + + constructor() { + counterInstance = new Counter(); + } + + function incrementCounter() public { + counterInstance.increment(); + } + + function decrementCounter() public { + counterInstance.decrement(); + } + + function getCounterValue() public view returns (uint256) { + return counterInstance.counter(); + } +} diff --git a/contracts/solidity/precompiles/bank/testdata/BankCaller.sol b/contracts/solidity/precompiles/bank/testdata/BankCaller.sol index 7322fe11..f9ed0a7b 100644 --- a/contracts/solidity/precompiles/bank/testdata/BankCaller.sol +++ b/contracts/solidity/precompiles/bank/testdata/BankCaller.sol @@ -16,4 +16,14 @@ contract BankCaller { function callSupplyOf(address erc20Address) external view returns (uint256) { return IBANK_CONTRACT.supplyOf(erc20Address); } + + // Calls totalSupply with explicit gas forwarding and measures the gas consumed + // by the inner call. Returns whether the call succeeded and the actual gas used. + function callTotalSupplyWithGas(uint256 gasForward) external view returns (bool success, uint256 innerGasUsed) { + uint256 gasBefore = gasleft(); + (success, ) = IBANK_PRECOMPILE_ADDRESS.staticcall{gas: gasForward}( + abi.encodeWithSelector(IBank.totalSupply.selector) + ); + innerGasUsed = gasBefore - gasleft(); + } } \ No newline at end of file diff --git a/contracts/solidity/tests/contracts/7702/DelegationTarget.sol b/contracts/solidity/tests/contracts/7702/DelegationTarget.sol new file mode 100644 index 00000000..b236d1cb --- /dev/null +++ b/contracts/solidity/tests/contracts/7702/DelegationTarget.sol @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +/** + * @title DelegationTarget + * @notice Minimal contract for EIP-7702 delegation that allows deploying other contracts + * @dev This contract can be set as a delegation target for an EOA via EIP-7702 + */ +contract DelegationTarget { + // Storage slot where the counter (last offset) is stored + uint256 constant COUNTER_SLOT = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; + + event ContractDeployed(address indexed deployed, bytes32 salt); + event ContractDestroyed(address indexed destroyed, uint256 index, bool success); + event CodeHash(address indexed deployed, bytes32 codeHash); + + /** + * @notice Deploy a contract using CREATE + * @param bytecode The bytecode of the contract to deploy + * @return deployed The address of the deployed contract + * @dev Stores deployed addresses at slots 0, 1, 2, ... and counter at COUNTER_SLOT + */ + function deploy(bytes memory bytecode) external returns (address deployed) { + assembly { + deployed := create(0, add(bytecode, 0x20), mload(bytecode)) + // Load current counter from COUNTER_SLOT + let currentSlot := sload(COUNTER_SLOT) + // Store deployed address at slot currentSlot (0, 1, 2, ...) + sstore(currentSlot, deployed) + // Increment counter and store back + sstore(COUNTER_SLOT, add(currentSlot, 1)) + } + require(deployed != address(0), "Deployment failed"); + emit ContractDeployed(deployed, bytes32(0)); + } + + /** + * @notice Get the deployed address at a given index + * @param index The index (slot) to read from + * @return addr The deployed address + */ + function getDeployedAt(uint256 index) external view returns (address addr) { + assembly { + addr := sload(index) + } + } + + /** + * @notice Get the current counter (number of deployments) + * @return count The number of deployed contracts + */ + function getDeploymentCount() external view returns (uint256 count) { + assembly { + count := sload(COUNTER_SLOT) + } + } + + /** + * @notice Selfdestruct all deployed contracts + * @dev Calls destroy() on each deployed contract. Contracts must implement destroy() with selfdestruct + */ + function selfdestructAll() external { + uint256 count; + assembly { + count := sload(COUNTER_SLOT) + } + + for (uint256 i = 0; i < count; i++) { + address target; + assembly { + target := sload(i) + } + // Call destroy() selector: 0x83197ef0 + (bool success,) = target.call(abi.encodeWithSelector(MinimalContract.selfDestruct.selector)); + emit ContractDestroyed(target, i, success); + } + } + + function emitAllCodeHashes() external { + uint256 count; + assembly { + count := sload(COUNTER_SLOT) + } + + for (uint256 i = 0; i < count; i++) { + address target; + assembly { + target := sload(i) + } + bytes32 codeHash; + assembly { + codeHash := extcodehash(target) + } + emit CodeHash(target, codeHash); + } + } + + /** + * @notice Execute arbitrary call (useful for delegated EOA) + * @param target The target address + * @param data The calldata + * @return success Whether the call succeeded + * @return result The return data + */ + function execute(address target, bytes calldata data) external payable returns (bool success, bytes memory result) { + (success, result) = target.call{value: msg.value}(data); + } + + receive() external payable {} +} + + + + +/** + * @title MinimalContract + * @notice A minimal contract that gets deployed by MaliciousDeployer + */ +contract MinimalContract { + address public immutable creator; + uint256 public value; + + constructor() { + creator = msg.sender; + } + + function setValue(uint256 _value) external { + value = _value; + } + + function selfDestruct() external { + selfdestruct(payable(creator)); + } +} + +/** + * @title FinalContract + * @notice The final contract that gets deployed by MaliciousDeployer + */ +contract FinalContract { + address public immutable creator; + uint256 public value; + + constructor() { + creator = msg.sender; + } + + function singletonFunction() external pure returns (string memory) { + return "I am the final contract!"; + } +} \ No newline at end of file diff --git a/contracts/solidity/tests/contracts/7702/MaliciousDeployer.sol b/contracts/solidity/tests/contracts/7702/MaliciousDeployer.sol new file mode 100644 index 00000000..cdbf424e --- /dev/null +++ b/contracts/solidity/tests/contracts/7702/MaliciousDeployer.sol @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "./DelegationTarget.sol"; + +/** + * @title MaliciousDeployer + * @notice Contract that during deployment calls back the deployer (with EIP-7702 delegation) + * and deploys contracts through the delegated EOA + * @dev The constructor performs the callback attack during deployment + */ +contract MaliciousDeployer { + address public immutable deployer; + address[] public deployedContracts; + + event CallbackExecuted(address indexed delegatedEOA, bool success); + event ContractDeployedViaCallback(address indexed deployed); + + /** + * @notice Constructor that calls back the deployer and deploys contracts + * @param delegatedEOA The EOA with EIP-7702 delegation (should be tx.origin or specified) + * @param numContracts Number of contracts to deploy via callback + */ + constructor(address delegatedEOA, uint256 numContracts, uint256 step) { + deployer = msg.sender; + + // Attempt to call back the delegated EOA and deploy contracts through it + for (uint256 i = 0; i < numContracts; i++) { + // Get bytecode for MinimalContract + bytes memory bytecode; + if (step == 1) { + bytecode = type(MinimalContract).creationCode; + } else { + bytecode = type(FinalContract).creationCode; + } + + // Call the deploy function on the delegated EOA (which has DelegationTarget code) + (bool success, bytes memory result) = delegatedEOA.call( + abi.encodeWithSelector(DelegationTarget.deploy.selector, bytecode) + ); + + emit CallbackExecuted(delegatedEOA, success); + address deployed; + if (success && result.length >= 32) { + deployed = abi.decode(result, (address)); + deployedContracts.push(deployed); + } + } + + delegatedEOA.call(abi.encodeWithSelector(DelegationTarget.emitAllCodeHashes.selector)); + + + // @audit at this point, the attacker can make external calls + + + // Call the deploy function on the delegated EOA (which has DelegationTarget code) + if (step == 1) { + delegatedEOA.call( + abi.encodeWithSelector(DelegationTarget.selfdestructAll.selector) + ); + } + } + + /** + * @notice Get the number of contracts deployed via callback + */ + function getDeployedCount() external view returns (uint256) { + return deployedContracts.length; + } + + /** + * @notice Get all deployed contract addresses + */ + function getDeployedContracts() external view returns (address[] memory) { + return deployedContracts; + } +} diff --git a/contracts/static_call_tester.go b/contracts/static_call_tester.go new file mode 100644 index 00000000..ec044ef3 --- /dev/null +++ b/contracts/static_call_tester.go @@ -0,0 +1,55 @@ +package contracts + +import ( + _ "embed" + + contractutils "github.com/cosmos/evm/contracts/utils" + evmtypes "github.com/cosmos/evm/x/vm/types" +) + +var ( + // StaticCallTesterJSON are the compiled bytes of the StaticCallTesterContract + // + //go:embed solidity/StaticCallTester.json + StaticCallTesterJSON []byte + + // StaticCallTesterContract is the compiled StaticCallTester contract + StaticCallTesterContract evmtypes.CompiledContract + + // StaticCallbackTargetJSON are the compiled bytes of the StaticCallbackTarget contract + // + //go:embed solidity/StaticCallbackTarget.json + StaticCallbackTargetJSON []byte + + // StaticCallbackTargetContract is the compiled contract for cross-contract static call testing + StaticCallbackTargetContract evmtypes.CompiledContract + + // ViewCallerJSON are the compiled bytes of the ViewCaller contract + // + //go:embed solidity/ViewCaller.json + ViewCallerJSON []byte + + // ViewCallerContract is the compiled contract for invoking view functions + ViewCallerContract evmtypes.CompiledContract +) + +func init() { + var err error + if StaticCallTesterContract, err = contractutils.ConvertHardhatBytesToCompiledContract( + StaticCallTesterJSON, + ); err != nil { + panic(err) + } + + if StaticCallbackTargetContract, err = contractutils.ConvertHardhatBytesToCompiledContract( + StaticCallbackTargetJSON, + ); err != nil { + panic(err) + } + + if ViewCallerContract, err = contractutils.ConvertHardhatBytesToCompiledContract( + ViewCallerJSON, + ); err != nil { + panic(err) + } +} diff --git a/contracts/utils/utils.go b/contracts/utils/utils.go index de438dac..9ceda68b 100644 --- a/contracts/utils/utils.go +++ b/contracts/utils/utils.go @@ -82,23 +82,6 @@ func ConvertHardhatBytesToCompiledContract(bz []byte) (evmtypes.CompiledContract return compiledContract, nil } -// ConvertPrecompileHardhatBytesToCompiledContract is a helper method to convert the embedded bytes from a -// Hardhat JSON file into an instance of the CompiledContract type. -// -// NOTE: The precompile implementations have to special property that the binary data is empty. -func ConvertPrecompileHardhatBytesToCompiledContract(bz []byte) (evmtypes.CompiledContract, error) { - compiledContract, err := convertHardhatBzToCompiledContract(bz) - if err != nil { - return evmtypes.CompiledContract{}, err - } - - if len(compiledContract.Bin) != 0 { - return evmtypes.CompiledContract{}, errors.New("expected binary data to be empty for precompile contract") - } - - return compiledContract, nil -} - // convertHardhatBzToCompiledContract is a helper method to convert the embedded bytes from a // Hardhat JSON file into an instance of the CompiledContract type. func convertHardhatBzToCompiledContract(bz []byte) (evmtypes.CompiledContract, error) { diff --git a/x/precisebank/README.md b/contrib/x/precisebank/README.md similarity index 100% rename from x/precisebank/README.md rename to contrib/x/precisebank/README.md diff --git a/x/precisebank/client/cli/query.go b/contrib/x/precisebank/client/cli/query.go similarity index 97% rename from x/precisebank/client/cli/query.go rename to contrib/x/precisebank/client/cli/query.go index 253a12aa..68d9f4e7 100644 --- a/x/precisebank/client/cli/query.go +++ b/contrib/x/precisebank/client/cli/query.go @@ -3,7 +3,7 @@ package cli import ( "github.com/spf13/cobra" - "github.com/cosmos/evm/x/precisebank/types" + "github.com/cosmos/evm/contrib/x/precisebank/types" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" diff --git a/x/precisebank/genesis.go b/contrib/x/precisebank/genesis.go similarity index 96% rename from x/precisebank/genesis.go rename to contrib/x/precisebank/genesis.go index 171dd89e..30d31bb6 100644 --- a/x/precisebank/genesis.go +++ b/contrib/x/precisebank/genesis.go @@ -3,8 +3,8 @@ package precisebank import ( "fmt" - "github.com/cosmos/evm/x/precisebank/keeper" - "github.com/cosmos/evm/x/precisebank/types" + "github.com/cosmos/evm/contrib/x/precisebank/keeper" + "github.com/cosmos/evm/contrib/x/precisebank/types" sdkmath "cosmossdk.io/math" diff --git a/x/precisebank/keeper/burn.go b/contrib/x/precisebank/keeper/burn.go similarity index 99% rename from x/precisebank/keeper/burn.go rename to contrib/x/precisebank/keeper/burn.go index f971f4d2..10df0fe0 100644 --- a/x/precisebank/keeper/burn.go +++ b/contrib/x/precisebank/keeper/burn.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - "github.com/cosmos/evm/x/precisebank/types" + "github.com/cosmos/evm/contrib/x/precisebank/types" errorsmod "cosmossdk.io/errors" sdkmath "cosmossdk.io/math" diff --git a/x/precisebank/keeper/burn_test.go b/contrib/x/precisebank/keeper/burn_test.go similarity index 98% rename from x/precisebank/keeper/burn_test.go rename to contrib/x/precisebank/keeper/burn_test.go index 4905b916..a7da9aa8 100644 --- a/x/precisebank/keeper/burn_test.go +++ b/contrib/x/precisebank/keeper/burn_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/require" - "github.com/cosmos/evm/x/precisebank/types" + "github.com/cosmos/evm/contrib/x/precisebank/types" sdkmath "cosmossdk.io/math" diff --git a/x/precisebank/keeper/fractional_balance.go b/contrib/x/precisebank/keeper/fractional_balance.go similarity index 96% rename from x/precisebank/keeper/fractional_balance.go rename to contrib/x/precisebank/keeper/fractional_balance.go index 5f54c5a7..aa94cd07 100644 --- a/x/precisebank/keeper/fractional_balance.go +++ b/contrib/x/precisebank/keeper/fractional_balance.go @@ -4,11 +4,11 @@ import ( "errors" "fmt" - "github.com/cosmos/evm/x/precisebank/types" + "github.com/cosmos/evm/contrib/x/precisebank/types" sdkmath "cosmossdk.io/math" - "cosmossdk.io/store/prefix" + "github.com/cosmos/cosmos-sdk/store/v2/prefix" sdk "github.com/cosmos/cosmos-sdk/types" ) diff --git a/x/precisebank/keeper/fractional_balance_test.go b/contrib/x/precisebank/keeper/fractional_balance_test.go similarity index 97% rename from x/precisebank/keeper/fractional_balance_test.go rename to contrib/x/precisebank/keeper/fractional_balance_test.go index 89b7afd0..4f8bd495 100644 --- a/x/precisebank/keeper/fractional_balance_test.go +++ b/contrib/x/precisebank/keeper/fractional_balance_test.go @@ -5,11 +5,11 @@ import ( "github.com/stretchr/testify/require" - "github.com/cosmos/evm/x/precisebank/types" + "github.com/cosmos/evm/contrib/x/precisebank/types" sdkmath "cosmossdk.io/math" - "cosmossdk.io/store/prefix" + "github.com/cosmos/cosmos-sdk/store/v2/prefix" sdk "github.com/cosmos/cosmos-sdk/types" ) diff --git a/x/precisebank/keeper/grpc_query.go b/contrib/x/precisebank/keeper/grpc_query.go similarity index 96% rename from x/precisebank/keeper/grpc_query.go rename to contrib/x/precisebank/keeper/grpc_query.go index c95b6b4e..bd1a837e 100644 --- a/x/precisebank/keeper/grpc_query.go +++ b/contrib/x/precisebank/keeper/grpc_query.go @@ -3,7 +3,7 @@ package keeper import ( "context" - "github.com/cosmos/evm/x/precisebank/types" + "github.com/cosmos/evm/contrib/x/precisebank/types" sdk "github.com/cosmos/cosmos-sdk/types" ) diff --git a/x/precisebank/keeper/keeper.go b/contrib/x/precisebank/keeper/keeper.go similarity index 53% rename from x/precisebank/keeper/keeper.go rename to contrib/x/precisebank/keeper/keeper.go index 1185ea51..a0a19e95 100644 --- a/x/precisebank/keeper/keeper.go +++ b/contrib/x/precisebank/keeper/keeper.go @@ -3,12 +3,11 @@ package keeper import ( "context" - "github.com/cosmos/evm/x/precisebank/types" + "github.com/cosmos/evm/contrib/x/precisebank/types" evmtypes "github.com/cosmos/evm/x/vm/types" - storetypes "cosmossdk.io/store/types" - "github.com/cosmos/cosmos-sdk/codec" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -40,6 +39,17 @@ func NewKeeper( } // BANK KEEPER INTERFACE PASSTHROUGHS +func (k Keeper) SendCoinsFromModuleToAccountVirtual(ctx context.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error { + return k.bk.SendCoinsFromModuleToAccountVirtual(ctx, senderModule, recipientAddr, amt) +} + +func (k Keeper) SendCoinsFromAccountToModuleVirtual(ctx context.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error { + return k.bk.SendCoinsFromAccountToModuleVirtual(ctx, senderAddr, recipientModule, amt) +} + +func (k Keeper) UncheckedSetBalance(ctx context.Context, addr sdk.AccAddress, amt sdk.Coin) error { + return k.bk.UncheckedSetBalance(ctx, addr, amt) +} func (k Keeper) IterateTotalSupply(ctx context.Context, cb func(coin sdk.Coin) bool) { k.bk.IterateTotalSupply(ctx, cb) @@ -48,3 +58,7 @@ func (k Keeper) IterateTotalSupply(ctx context.Context, cb func(coin sdk.Coin) b func (k Keeper) GetSupply(ctx context.Context, denom string) sdk.Coin { return k.bk.GetSupply(ctx, denom) } + +func (k Keeper) LockedCoins(ctx context.Context, addr sdk.AccAddress) sdk.Coins { + return k.bk.LockedCoins(ctx, addr) +} diff --git a/x/precisebank/keeper/keeper_test.go b/contrib/x/precisebank/keeper/keeper_test.go similarity index 89% rename from x/precisebank/keeper/keeper_test.go rename to contrib/x/precisebank/keeper/keeper_test.go index b1ac4b23..e5f2305a 100644 --- a/x/precisebank/keeper/keeper_test.go +++ b/contrib/x/precisebank/keeper/keeper_test.go @@ -5,16 +5,16 @@ import ( "github.com/stretchr/testify/require" + "github.com/cosmos/evm/contrib/x/precisebank/keeper" + "github.com/cosmos/evm/contrib/x/precisebank/types" + "github.com/cosmos/evm/contrib/x/precisebank/types/mocks" evmencoding "github.com/cosmos/evm/encoding" testconstants "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/x/precisebank/keeper" - "github.com/cosmos/evm/x/precisebank/types" - "github.com/cosmos/evm/x/precisebank/types/mocks" vmtypes "github.com/cosmos/evm/x/vm/types" sdkmath "cosmossdk.io/math" - storetypes "cosmossdk.io/store/types" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" "github.com/cosmos/cosmos-sdk/testutil" sdk "github.com/cosmos/cosmos-sdk/types" ) diff --git a/x/precisebank/keeper/mint.go b/contrib/x/precisebank/keeper/mint.go similarity index 99% rename from x/precisebank/keeper/mint.go rename to contrib/x/precisebank/keeper/mint.go index 2b3ca449..46826c27 100644 --- a/x/precisebank/keeper/mint.go +++ b/contrib/x/precisebank/keeper/mint.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - "github.com/cosmos/evm/x/precisebank/types" + "github.com/cosmos/evm/contrib/x/precisebank/types" errorsmod "cosmossdk.io/errors" sdkmath "cosmossdk.io/math" diff --git a/x/precisebank/keeper/mint_test.go b/contrib/x/precisebank/keeper/mint_test.go similarity index 99% rename from x/precisebank/keeper/mint_test.go rename to contrib/x/precisebank/keeper/mint_test.go index 3c0f9f93..952c3918 100644 --- a/x/precisebank/keeper/mint_test.go +++ b/contrib/x/precisebank/keeper/mint_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/require" - "github.com/cosmos/evm/x/precisebank/types" + "github.com/cosmos/evm/contrib/x/precisebank/types" sdkmath "cosmossdk.io/math" diff --git a/x/precisebank/keeper/remainder_amount.go b/contrib/x/precisebank/keeper/remainder_amount.go similarity index 96% rename from x/precisebank/keeper/remainder_amount.go rename to contrib/x/precisebank/keeper/remainder_amount.go index 0c4eacdf..d7d121c9 100644 --- a/x/precisebank/keeper/remainder_amount.go +++ b/contrib/x/precisebank/keeper/remainder_amount.go @@ -3,7 +3,7 @@ package keeper import ( "fmt" - "github.com/cosmos/evm/x/precisebank/types" + "github.com/cosmos/evm/contrib/x/precisebank/types" sdkmath "cosmossdk.io/math" diff --git a/x/precisebank/keeper/remainder_amount_test.go b/contrib/x/precisebank/keeper/remainder_amount_test.go similarity index 97% rename from x/precisebank/keeper/remainder_amount_test.go rename to contrib/x/precisebank/keeper/remainder_amount_test.go index 98e1c3c3..2c8ffb3a 100644 --- a/x/precisebank/keeper/remainder_amount_test.go +++ b/contrib/x/precisebank/keeper/remainder_amount_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/require" - "github.com/cosmos/evm/x/precisebank/types" + "github.com/cosmos/evm/contrib/x/precisebank/types" sdkmath "cosmossdk.io/math" ) diff --git a/x/precisebank/keeper/send.go b/contrib/x/precisebank/keeper/send.go similarity index 99% rename from x/precisebank/keeper/send.go rename to contrib/x/precisebank/keeper/send.go index 93862292..a5f64b7c 100644 --- a/x/precisebank/keeper/send.go +++ b/contrib/x/precisebank/keeper/send.go @@ -7,7 +7,7 @@ import ( "github.com/hashicorp/go-metrics" - "github.com/cosmos/evm/x/precisebank/types" + "github.com/cosmos/evm/contrib/x/precisebank/types" evmtypes "github.com/cosmos/evm/x/vm/types" errorsmod "cosmossdk.io/errors" diff --git a/x/precisebank/keeper/send_test.go b/contrib/x/precisebank/keeper/send_test.go similarity index 96% rename from x/precisebank/keeper/send_test.go rename to contrib/x/precisebank/keeper/send_test.go index 2560160f..4205f4a8 100644 --- a/x/precisebank/keeper/send_test.go +++ b/contrib/x/precisebank/keeper/send_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/require" - "github.com/cosmos/evm/x/precisebank/types" + "github.com/cosmos/evm/contrib/x/precisebank/types" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" diff --git a/x/precisebank/keeper/view.go b/contrib/x/precisebank/keeper/view.go similarity index 98% rename from x/precisebank/keeper/view.go rename to contrib/x/precisebank/keeper/view.go index b83f6ca4..997fdf35 100644 --- a/x/precisebank/keeper/view.go +++ b/contrib/x/precisebank/keeper/view.go @@ -3,7 +3,7 @@ package keeper import ( "context" - "github.com/cosmos/evm/x/precisebank/types" + "github.com/cosmos/evm/contrib/x/precisebank/types" sdkmath "cosmossdk.io/math" diff --git a/x/precisebank/keeper/view_test.go b/contrib/x/precisebank/keeper/view_test.go similarity index 99% rename from x/precisebank/keeper/view_test.go rename to contrib/x/precisebank/keeper/view_test.go index 6172a80d..cfbd956a 100644 --- a/x/precisebank/keeper/view_test.go +++ b/contrib/x/precisebank/keeper/view_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/require" - "github.com/cosmos/evm/x/precisebank/types" + "github.com/cosmos/evm/contrib/x/precisebank/types" sdkmath "cosmossdk.io/math" diff --git a/x/precisebank/module.go b/contrib/x/precisebank/module.go similarity index 94% rename from x/precisebank/module.go rename to contrib/x/precisebank/module.go index 5da71ceb..26678e52 100644 --- a/x/precisebank/module.go +++ b/contrib/x/precisebank/module.go @@ -9,9 +9,9 @@ import ( abci "github.com/cometbft/cometbft/abci/types" - "github.com/cosmos/evm/x/precisebank/client/cli" - "github.com/cosmos/evm/x/precisebank/keeper" - "github.com/cosmos/evm/x/precisebank/types" + "github.com/cosmos/evm/contrib/x/precisebank/client/cli" + "github.com/cosmos/evm/contrib/x/precisebank/keeper" + "github.com/cosmos/evm/contrib/x/precisebank/types" "cosmossdk.io/core/appmodule" @@ -26,7 +26,7 @@ import ( const ConsensusVersion = 1 var ( - _ module.AppModule = AppModule{} + _ module.AppModule = AppModule{} //nolint:staticcheck // keep for legacy purposes _ module.AppModuleBasic = AppModuleBasic{} _ module.HasABCIGenesis = AppModule{} diff --git a/x/precisebank/testutil/fractional_balances.go b/contrib/x/precisebank/testutil/fractional_balances.go similarity index 98% rename from x/precisebank/testutil/fractional_balances.go rename to contrib/x/precisebank/testutil/fractional_balances.go index 927183af..58477bfb 100644 --- a/x/precisebank/testutil/fractional_balances.go +++ b/contrib/x/precisebank/testutil/fractional_balances.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/require" - "github.com/cosmos/evm/x/precisebank/types" + "github.com/cosmos/evm/contrib/x/precisebank/types" sdkmath "cosmossdk.io/math" diff --git a/x/precisebank/types/codec.go b/contrib/x/precisebank/types/codec.go similarity index 100% rename from x/precisebank/types/codec.go rename to contrib/x/precisebank/types/codec.go diff --git a/x/precisebank/types/events.go b/contrib/x/precisebank/types/events.go similarity index 100% rename from x/precisebank/types/events.go rename to contrib/x/precisebank/types/events.go diff --git a/x/precisebank/types/extended_balance.go b/contrib/x/precisebank/types/extended_balance.go similarity index 100% rename from x/precisebank/types/extended_balance.go rename to contrib/x/precisebank/types/extended_balance.go diff --git a/x/precisebank/types/extended_balance_test.go b/contrib/x/precisebank/types/extended_balance_test.go similarity index 96% rename from x/precisebank/types/extended_balance_test.go rename to contrib/x/precisebank/types/extended_balance_test.go index d0a013f1..fb238e31 100644 --- a/x/precisebank/types/extended_balance_test.go +++ b/contrib/x/precisebank/types/extended_balance_test.go @@ -5,8 +5,8 @@ import ( "github.com/stretchr/testify/require" + "github.com/cosmos/evm/contrib/x/precisebank/types" testconstants "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/x/precisebank/types" evmtypes "github.com/cosmos/evm/x/vm/types" sdkmath "cosmossdk.io/math" diff --git a/x/precisebank/types/fractional_balance.go b/contrib/x/precisebank/types/fractional_balance.go similarity index 100% rename from x/precisebank/types/fractional_balance.go rename to contrib/x/precisebank/types/fractional_balance.go diff --git a/x/precisebank/types/fractional_balance_test.go b/contrib/x/precisebank/types/fractional_balance_test.go similarity index 98% rename from x/precisebank/types/fractional_balance_test.go rename to contrib/x/precisebank/types/fractional_balance_test.go index 8bfc8c73..1a214dba 100644 --- a/x/precisebank/types/fractional_balance_test.go +++ b/contrib/x/precisebank/types/fractional_balance_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/require" - "github.com/cosmos/evm/x/precisebank/types" + "github.com/cosmos/evm/contrib/x/precisebank/types" sdkmath "cosmossdk.io/math" ) diff --git a/x/precisebank/types/fractional_balances.go b/contrib/x/precisebank/types/fractional_balances.go similarity index 100% rename from x/precisebank/types/fractional_balances.go rename to contrib/x/precisebank/types/fractional_balances.go diff --git a/x/precisebank/types/fractional_balances_test.go b/contrib/x/precisebank/types/fractional_balances_test.go similarity index 98% rename from x/precisebank/types/fractional_balances_test.go rename to contrib/x/precisebank/types/fractional_balances_test.go index 00ea4ac4..1b7df9ba 100644 --- a/x/precisebank/types/fractional_balances_test.go +++ b/contrib/x/precisebank/types/fractional_balances_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/require" - "github.com/cosmos/evm/x/precisebank/types" + "github.com/cosmos/evm/contrib/x/precisebank/types" sdkmath "cosmossdk.io/math" diff --git a/x/precisebank/types/genesis.go b/contrib/x/precisebank/types/genesis.go similarity index 100% rename from x/precisebank/types/genesis.go rename to contrib/x/precisebank/types/genesis.go diff --git a/x/precisebank/types/genesis.pb.go b/contrib/x/precisebank/types/genesis.pb.go similarity index 100% rename from x/precisebank/types/genesis.pb.go rename to contrib/x/precisebank/types/genesis.pb.go diff --git a/x/precisebank/types/genesis_test.go b/contrib/x/precisebank/types/genesis_test.go similarity index 98% rename from x/precisebank/types/genesis_test.go rename to contrib/x/precisebank/types/genesis_test.go index bd92f3e0..08b29edb 100644 --- a/x/precisebank/types/genesis_test.go +++ b/contrib/x/precisebank/types/genesis_test.go @@ -5,9 +5,9 @@ import ( "github.com/stretchr/testify/require" + "github.com/cosmos/evm/contrib/x/precisebank/testutil" + "github.com/cosmos/evm/contrib/x/precisebank/types" testconstants "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/x/precisebank/testutil" - "github.com/cosmos/evm/x/precisebank/types" evmtypes "github.com/cosmos/evm/x/vm/types" sdkmath "cosmossdk.io/math" diff --git a/x/precisebank/types/interfaces.go b/contrib/x/precisebank/types/interfaces.go similarity index 83% rename from x/precisebank/types/interfaces.go rename to contrib/x/precisebank/types/interfaces.go index bcae3df1..eec1e02d 100644 --- a/x/precisebank/types/interfaces.go +++ b/contrib/x/precisebank/types/interfaces.go @@ -25,6 +25,7 @@ type BankKeeper interface { GetBalance(ctx context.Context, addr sdk.AccAddress, denom string) sdk.Coin GetSupply(ctx context.Context, denom string) sdk.Coin SpendableCoin(ctx context.Context, addr sdk.AccAddress, denom string) sdk.Coin + LockedCoins(ctx context.Context, addr sdk.AccAddress) sdk.Coins BlockedAddr(addr sdk.AccAddress) bool @@ -32,6 +33,9 @@ type BankKeeper interface { SendCoinsFromAccountToModule(ctx context.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error SendCoinsFromModuleToAccount(ctx context.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error SendCoinsFromModuleToModule(ctx context.Context, senderModule string, recipientModule string, amt sdk.Coins) error + SendCoinsFromModuleToAccountVirtual(ctx context.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error + SendCoinsFromAccountToModuleVirtual(ctx context.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error + UncheckedSetBalance(ctx context.Context, addr sdk.AccAddress, amt sdk.Coin) error MintCoins(ctx context.Context, moduleName string, amt sdk.Coins) error BurnCoins(ctx context.Context, moduleName string, amt sdk.Coins) error diff --git a/x/precisebank/types/keys.go b/contrib/x/precisebank/types/keys.go similarity index 100% rename from x/precisebank/types/keys.go rename to contrib/x/precisebank/types/keys.go diff --git a/x/precisebank/types/keys_test.go b/contrib/x/precisebank/types/keys_test.go similarity index 88% rename from x/precisebank/types/keys_test.go rename to contrib/x/precisebank/types/keys_test.go index 5c7313cc..23ebf956 100644 --- a/x/precisebank/types/keys_test.go +++ b/contrib/x/precisebank/types/keys_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/require" - "github.com/cosmos/evm/x/precisebank/types" + "github.com/cosmos/evm/contrib/x/precisebank/types" sdk "github.com/cosmos/cosmos-sdk/types" ) diff --git a/x/precisebank/types/mocks/MockAccountKeeper.go b/contrib/x/precisebank/types/mocks/MockAccountKeeper.go similarity index 95% rename from x/precisebank/types/mocks/MockAccountKeeper.go rename to contrib/x/precisebank/types/mocks/MockAccountKeeper.go index 6de608c3..053bd62d 100644 --- a/x/precisebank/types/mocks/MockAccountKeeper.go +++ b/contrib/x/precisebank/types/mocks/MockAccountKeeper.go @@ -100,7 +100,7 @@ type AccountKeeper_GetModuleAccount_Call struct { // GetModuleAccount is a helper method to define mock.On call // - ctx context.Context // - moduleName string -func (_e *AccountKeeper_Expecter) GetModuleAccount(ctx interface{}, moduleName interface{}) *AccountKeeper_GetModuleAccount_Call { +func (_e *AccountKeeper_Expecter) GetModuleAccount(ctx any, moduleName any) *AccountKeeper_GetModuleAccount_Call { return &AccountKeeper_GetModuleAccount_Call{Call: _e.mock.On("GetModuleAccount", ctx, moduleName)} } @@ -148,7 +148,7 @@ type AccountKeeper_GetModuleAddress_Call struct { // GetModuleAddress is a helper method to define mock.On call // - moduleName string -func (_e *AccountKeeper_Expecter) GetModuleAddress(moduleName interface{}) *AccountKeeper_GetModuleAddress_Call { +func (_e *AccountKeeper_Expecter) GetModuleAddress(moduleName any) *AccountKeeper_GetModuleAddress_Call { return &AccountKeeper_GetModuleAddress_Call{Call: _e.mock.On("GetModuleAddress", moduleName)} } @@ -205,7 +205,7 @@ type AccountKeeper_GetSequence_Call struct { // GetSequence is a helper method to define mock.On call // - _a0 context.Context // - _a1 cosmos_sdktypes.AccAddress -func (_e *AccountKeeper_Expecter) GetSequence(_a0 interface{}, _a1 interface{}) *AccountKeeper_GetSequence_Call { +func (_e *AccountKeeper_Expecter) GetSequence(_a0 any, _a1 any) *AccountKeeper_GetSequence_Call { return &AccountKeeper_GetSequence_Call{Call: _e.mock.On("GetSequence", _a0, _a1)} } diff --git a/x/precisebank/types/mocks/MockBankKeeper.go b/contrib/x/precisebank/types/mocks/MockBankKeeper.go similarity index 79% rename from x/precisebank/types/mocks/MockBankKeeper.go rename to contrib/x/precisebank/types/mocks/MockBankKeeper.go index c82096a1..6376ac2e 100644 --- a/x/precisebank/types/mocks/MockBankKeeper.go +++ b/contrib/x/precisebank/types/mocks/MockBankKeeper.go @@ -531,6 +531,55 @@ func (_c *BankKeeper_IterateTotalSupply_Call) RunAndReturn(run func(context.Cont return _c } +// LockedCoins provides a mock function with given fields: ctx, addr +func (_m *BankKeeper) LockedCoins(ctx context.Context, addr types.AccAddress) types.Coins { + ret := _m.Called(ctx, addr) + + if len(ret) == 0 { + panic("no return value specified for LockedCoins") + } + + var r0 types.Coins + if rf, ok := ret.Get(0).(func(context.Context, types.AccAddress) types.Coins); ok { + r0 = rf(ctx, addr) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(types.Coins) + } + } + + return r0 +} + +// BankKeeper_LockedCoins_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'LockedCoins' +type BankKeeper_LockedCoins_Call struct { + *mock.Call +} + +// LockedCoins is a helper method to define mock.On call +// - ctx context.Context +// - addr types.AccAddress +func (_e *BankKeeper_Expecter) LockedCoins(ctx interface{}, addr interface{}) *BankKeeper_LockedCoins_Call { + return &BankKeeper_LockedCoins_Call{Call: _e.mock.On("LockedCoins", ctx, addr)} +} + +func (_c *BankKeeper_LockedCoins_Call) Run(run func(ctx context.Context, addr types.AccAddress)) *BankKeeper_LockedCoins_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(types.AccAddress)) + }) + return _c +} + +func (_c *BankKeeper_LockedCoins_Call) Return(_a0 types.Coins) *BankKeeper_LockedCoins_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *BankKeeper_LockedCoins_Call) RunAndReturn(run func(context.Context, types.AccAddress) types.Coins) *BankKeeper_LockedCoins_Call { + _c.Call.Return(run) + return _c +} + // 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) @@ -677,6 +726,55 @@ func (_c *BankKeeper_SendCoinsFromAccountToModule_Call) RunAndReturn(run func(co return _c } +// SendCoinsFromAccountToModuleVirtual provides a mock function with given fields: ctx, senderAddr, recipientModule, amt +func (_m *BankKeeper) SendCoinsFromAccountToModuleVirtual(ctx context.Context, senderAddr types.AccAddress, recipientModule string, amt types.Coins) error { + ret := _m.Called(ctx, senderAddr, recipientModule, amt) + + if len(ret) == 0 { + panic("no return value specified for SendCoinsFromAccountToModuleVirtual") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, types.AccAddress, string, types.Coins) error); ok { + r0 = rf(ctx, senderAddr, recipientModule, amt) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// BankKeeper_SendCoinsFromAccountToModuleVirtual_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendCoinsFromAccountToModuleVirtual' +type BankKeeper_SendCoinsFromAccountToModuleVirtual_Call struct { + *mock.Call +} + +// SendCoinsFromAccountToModuleVirtual is a helper method to define mock.On call +// - ctx context.Context +// - senderAddr types.AccAddress +// - recipientModule string +// - amt types.Coins +func (_e *BankKeeper_Expecter) SendCoinsFromAccountToModuleVirtual(ctx interface{}, senderAddr interface{}, recipientModule interface{}, amt interface{}) *BankKeeper_SendCoinsFromAccountToModuleVirtual_Call { + return &BankKeeper_SendCoinsFromAccountToModuleVirtual_Call{Call: _e.mock.On("SendCoinsFromAccountToModuleVirtual", ctx, senderAddr, recipientModule, amt)} +} + +func (_c *BankKeeper_SendCoinsFromAccountToModuleVirtual_Call) Run(run func(ctx context.Context, senderAddr types.AccAddress, recipientModule string, amt types.Coins)) *BankKeeper_SendCoinsFromAccountToModuleVirtual_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(types.AccAddress), args[2].(string), args[3].(types.Coins)) + }) + return _c +} + +func (_c *BankKeeper_SendCoinsFromAccountToModuleVirtual_Call) Return(_a0 error) *BankKeeper_SendCoinsFromAccountToModuleVirtual_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *BankKeeper_SendCoinsFromAccountToModuleVirtual_Call) RunAndReturn(run func(context.Context, types.AccAddress, string, types.Coins) error) *BankKeeper_SendCoinsFromAccountToModuleVirtual_Call { + _c.Call.Return(run) + return _c +} + // 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) @@ -726,6 +824,55 @@ func (_c *BankKeeper_SendCoinsFromModuleToAccount_Call) RunAndReturn(run func(co return _c } +// SendCoinsFromModuleToAccountVirtual provides a mock function with given fields: ctx, senderModule, recipientAddr, amt +func (_m *BankKeeper) SendCoinsFromModuleToAccountVirtual(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 SendCoinsFromModuleToAccountVirtual") + } + + 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 +} + +// BankKeeper_SendCoinsFromModuleToAccountVirtual_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendCoinsFromModuleToAccountVirtual' +type BankKeeper_SendCoinsFromModuleToAccountVirtual_Call struct { + *mock.Call +} + +// SendCoinsFromModuleToAccountVirtual is a helper method to define mock.On call +// - ctx context.Context +// - senderModule string +// - recipientAddr types.AccAddress +// - amt types.Coins +func (_e *BankKeeper_Expecter) SendCoinsFromModuleToAccountVirtual(ctx interface{}, senderModule interface{}, recipientAddr interface{}, amt interface{}) *BankKeeper_SendCoinsFromModuleToAccountVirtual_Call { + return &BankKeeper_SendCoinsFromModuleToAccountVirtual_Call{Call: _e.mock.On("SendCoinsFromModuleToAccountVirtual", ctx, senderModule, recipientAddr, amt)} +} + +func (_c *BankKeeper_SendCoinsFromModuleToAccountVirtual_Call) Run(run func(ctx context.Context, senderModule string, recipientAddr types.AccAddress, amt types.Coins)) *BankKeeper_SendCoinsFromModuleToAccountVirtual_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string), args[2].(types.AccAddress), args[3].(types.Coins)) + }) + return _c +} + +func (_c *BankKeeper_SendCoinsFromModuleToAccountVirtual_Call) Return(_a0 error) *BankKeeper_SendCoinsFromModuleToAccountVirtual_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *BankKeeper_SendCoinsFromModuleToAccountVirtual_Call) RunAndReturn(run func(context.Context, string, types.AccAddress, types.Coins) error) *BankKeeper_SendCoinsFromModuleToAccountVirtual_Call { + _c.Call.Return(run) + return _c +} + // 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) @@ -857,12 +1004,61 @@ func (_c *BankKeeper_SpendableCoin_Call) RunAndReturn(run func(context.Context, return _c } +// UncheckedSetBalance provides a mock function with given fields: ctx, addr, amt +func (_m *BankKeeper) UncheckedSetBalance(ctx context.Context, addr types.AccAddress, amt types.Coin) error { + ret := _m.Called(ctx, addr, amt) + + if len(ret) == 0 { + panic("no return value specified for UncheckedSetBalance") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, types.AccAddress, types.Coin) error); ok { + r0 = rf(ctx, addr, amt) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// BankKeeper_UncheckedSetBalance_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UncheckedSetBalance' +type BankKeeper_UncheckedSetBalance_Call struct { + *mock.Call +} + +// UncheckedSetBalance is a helper method to define mock.On call +// - ctx context.Context +// - addr types.AccAddress +// - amt types.Coin +func (_e *BankKeeper_Expecter) UncheckedSetBalance(ctx interface{}, addr interface{}, amt interface{}) *BankKeeper_UncheckedSetBalance_Call { + return &BankKeeper_UncheckedSetBalance_Call{Call: _e.mock.On("UncheckedSetBalance", ctx, addr, amt)} +} + +func (_c *BankKeeper_UncheckedSetBalance_Call) Run(run func(ctx context.Context, addr types.AccAddress, amt types.Coin)) *BankKeeper_UncheckedSetBalance_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(types.AccAddress), args[2].(types.Coin)) + }) + return _c +} + +func (_c *BankKeeper_UncheckedSetBalance_Call) Return(_a0 error) *BankKeeper_UncheckedSetBalance_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *BankKeeper_UncheckedSetBalance_Call) RunAndReturn(run func(context.Context, types.AccAddress, types.Coin) error) *BankKeeper_UncheckedSetBalance_Call { + _c.Call.Return(run) + return _c +} + // 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/x/precisebank/types/query.pb.go b/contrib/x/precisebank/types/query.pb.go similarity index 99% rename from x/precisebank/types/query.pb.go rename to contrib/x/precisebank/types/query.pb.go index 20f66187..ec173c0c 100644 --- a/x/precisebank/types/query.pb.go +++ b/contrib/x/precisebank/types/query.pb.go @@ -336,6 +336,7 @@ func _Query_FractionalBalance_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } +var Query_serviceDesc = _Query_serviceDesc var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "cosmos.evm.precisebank.v1.Query", HandlerType: (*QueryServer)(nil), diff --git a/x/precisebank/types/query.pb.gw.go b/contrib/x/precisebank/types/query.pb.gw.go similarity index 100% rename from x/precisebank/types/query.pb.gw.go rename to contrib/x/precisebank/types/query.pb.gw.go diff --git a/crypto/secp256r1/verify.go b/crypto/secp256r1/verify.go index 9b4ba868..d1002b7b 100644 --- a/crypto/secp256r1/verify.go +++ b/crypto/secp256r1/verify.go @@ -40,7 +40,7 @@ func Verify(hash []byte, r, s, x, y *big.Int) bool { // newECDSAPublicKey creates an ECDSA P256 public key from the given coordinates func newECDSAPublicKey(x, y *big.Int) *ecdsa.PublicKey { // Check if the given coordinates are valid and in the reference point (infinity) - if x == nil || y == nil || x.Sign() == 0 && y.Sign() == 0 || !elliptic.P256().IsOnCurve(x, y) { + if x == nil || y == nil || x.Sign() == 0 && y.Sign() == 0 || !elliptic.P256().IsOnCurve(x, y) { //nolint:staticcheck // SA1019: legacy key validation return nil } diff --git a/docs/migrations/v0.4.0_to_v0.5.0_UNRELEASED.md b/docs/migrations/v0.4.0_to_v0.5.0.md similarity index 80% rename from docs/migrations/v0.4.0_to_v0.5.0_UNRELEASED.md rename to docs/migrations/v0.4.0_to_v0.5.0.md index 8911f656..22ac2ced 100644 --- a/docs/migrations/v0.4.0_to_v0.5.0_UNRELEASED.md +++ b/docs/migrations/v0.4.0_to_v0.5.0.md @@ -1,4 +1,4 @@ -# Cosmos EVM v0.4.0 → v0.5.0 Migration (UNRELEASED) +# Cosmos EVM v0.4.0 → v0.5.0 Migration ## 0) Prep @@ -77,9 +77,35 @@ following list includes references within `evmd` that have been moved. ### Mempool -#### Minimal setups: nothing to change +#### Custom initializer + +The mempool configuration can now be handled by a helper function. If you prefer to use the configuration from `app.toml` and CLI flags, you can refactor your mempool setup: + +- **Before**: Manual configuration in app.go +```go +mempoolConfig := &evmmempool.EVMMempoolConfig{ + AnteHandler: app.GetAnteHandler(), + BlockGasLimit: blockGasLimit, + MinTip: minTip, +} +evmMempool := evmmempool.NewExperimentalEVMMempool( + app.CreateQueryContext, logger, app.EVMKeeper, app.FeeMarketKeeper, + app.txConfig, app.clientCtx, mempoolConfig, +) +``` +- **After**: Using helper function (optional). See https://github.com/cosmos/evm/blob/42e1141c9b00432020e69945e565f60f80ab501d/evmd/mempool.go for the reference implementation +```go +if err := app.configureEVMMempool(appOpts, logger); err != nil { + panic(fmt.Sprintf("failed to configure EVM mempool: %s", err.Error())) +} +``` + +The helper function reads configuration from `appOpts` or applies defaults if omitted. Note that `NewExperimentalEVMMempool` now takes an additional `cosmosPoolMaxTx` parameter, with a recommended default value being `4096` or `0` (uncapped). -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. + +#### Simple config migration + +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{ @@ -181,42 +207,37 @@ These options can also be set via CLI flags: ##### Cosmos Mempool Max Transactions -A new flag `--mempool.max-txs` allows limiting the maximum number of transactions in the Cosmos mempool. Set to 0 or -1 for unbounded (default: 0). +The --mempool.max-txs SDK flag is now actually ingested into the Cosmos mempool (`ExtMempool`) config inside `ExperimentalEVMMempool` (this was previously always a zeroed `int` value and could not be overridden). This allows limiting the maximum number of transactions in the Cosmos mempool. Set to -1 (disabled, no-op), 0 (unbounded), or positive integer. The [default value here](https://github.com/cosmos/evm/blob/f6ce772cd8dabfc5804aeb94ee21c63cc3d112fa/server/start.go#L189-L192) is `0`, which differs from the default SDK value of `-1`, since we want the mempool enabled by default. -##### Simplified Mempool Setup - -The mempool configuration can now be handled by a helper function. If you prefer to use the configuration from `app.toml` and CLI flags, you can refactor your mempool setup: +The function signature for `NewExperimentalEVMMempool` also changed to add a cosmosPoolMaxTx field: -```go -// Before: Manual configuration in app.go -mempoolConfig := &evmmempool.EVMMempoolConfig{ - AnteHandler: app.GetAnteHandler(), - BlockGasLimit: blockGasLimit, - MinTip: minTip, -} -evmMempool := evmmempool.NewExperimentalEVMMempool( - app.CreateQueryContext, logger, app.EVMKeeper, app.FeeMarketKeeper, - app.txConfig, app.clientCtx, mempoolConfig, +```diff +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, ++ cosmosPoolMaxTx int, ) - -// After: Using helper function (optional) -// See evmd/mempool.go for reference implementation -if err := app.configureEVMMempool(appOpts, logger); err != nil { - panic(fmt.Sprintf("failed to configure EVM mempool: %s", err.Error())) -} ``` -The helper function reads configuration from `appOpts` and applies defaults where needed. Note that `NewExperimentalEVMMempool` now takes an additional `cosmosPoolMaxTx` parameter. - -### Default Precompiles +#### EVM Chain ID -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: +The EVM chain ID is now retrieved directly from `appOpts` instead of being passed as a parameter. In `app.go`, the chain ID is obtained using: ```go - app.EVMKeeper = evmkeeper.NewKeeper( +evmChainID := cast.ToUint64(appOpts.Get(srvflags.EVMChainID)) +``` + +See `evmd/app.go:216` for the reference implementation. + +The EVM Keeper now also takes in evmChainID as a parameter: + +```diff +app.EVMKeeper = evmkeeper.NewKeeper( appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey], keys, authtypes.NewModuleAddress(govtypes.ModuleName), app.AccountKeeper, @@ -225,39 +246,11 @@ function can now happen *alongside the keeper instantiation*, and not after. The app.FeeMarketKeeper, &app.ConsensusParamsKeeper, &app.Erc20Keeper, ++ evmChainID, tracer, - ).WithStaticPrecompiles( - precompiletypes.DefaultStaticPrecompiles( - *app.StakingKeeper, - app.DistrKeeper, - app.PreciseBankKeeper, - &app.Erc20Keeper, // UPDATED - &app.TransferKeeper, // UPDATED - app.IBCKeeper.ChannelKeeper, - app.GovKeeper, - app.SlashingKeeper, - appCodec, - ), ) ``` -### Denom Configs - -[#661](https://github.com/cosmos/evm/pull/661) removes the instantiation of chain configs via app.go -and moves them to state or genesis. -It is critical to remove any use of EvmAppOptions as calling the configurator will panic the chain -at runtime during startup. - -#### EVM Chain ID - -The EVM chain ID is now retrieved directly from `appOpts` instead of being passed as a parameter. In `app.go`, the chain ID is obtained using: - -```go -evmChainID := cast.ToUint64(appOpts.Get(srvflags.EVMChainID)) -``` - -See `evmd/app.go:216` for the reference implementation. - #### Function Signature Changes In `app.go`, remove evmChainID and evmAppOptions from the NewApp signature. @@ -304,6 +297,47 @@ Then, remove any reference of evmAppOptions being called: `evmd_config.go`, `chain_id.go`, `config.go`, `constants.go` have been moved to `github.com/cosmos/evm/config` and may be removed to your repo. +### Denom Configs + +[#661](https://github.com/cosmos/evm/pull/661) removes the instantiation of chain configs via app.go +and moves them to state or genesis. +It is critical to remove any use of EvmAppOptions as calling the configurator will panic the chain +at runtime during startup. + +### 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, + evmChainID, + tracer, + ).WithStaticPrecompiles( + precompiletypes.DefaultStaticPrecompiles( + *app.StakingKeeper, + app.DistrKeeper, + app.PreciseBankKeeper, + &app.Erc20Keeper, // UPDATED + &app.TransferKeeper, // UPDATED + app.IBCKeeper.ChannelKeeper, + app.GovKeeper, + app.SlashingKeeper, + appCodec, + ), + ) +``` + #### UpgradeHandler As the configs have been moved to state and genesis, you must include an UpgradeHandler if your chain does @@ -318,12 +352,20 @@ In your UpgradeHandler: - **If your chain does not have DenomMetadata set for the EVM Denom, you must include it.** - **If your chain's EVM denom is *not* 18 decimals, you must add ExtendedDenomOptions to your `x/vm` params.** +- **After setting metadata, initialize EVM coin info:** + +```go +// After setting denom metadata +if err := app.EVMKeeper.InitEvmCoinInfo(ctx); err != nil { + return nil, err +} +``` -Please refer to the [upgrade example](https://github.com/cosmos/evm/blob/0995962c2fd77a7a23e93001d5a531abbb1b61e5/evmd/upgrades.go) for more information. +Please refer to the [upgrade example](https://github.com/cosmos/evm/blob/main/evmd/upgrades.go) for the complete implementation. --- -## 3) Build & quick tests +## 4) Build & quick tests ```bash go build ./... diff --git a/docs/migrations/v0.5.x_to_v0.6.0.md b/docs/migrations/v0.5.x_to_v0.6.0.md new file mode 100644 index 00000000..3aa74f2a --- /dev/null +++ b/docs/migrations/v0.5.x_to_v0.6.0.md @@ -0,0 +1,491 @@ +# Cosmos EVM v0.5.x → v0.6.0 Migration + +## 0) Prep + +- Create a branch: `git switch -c upgrade/evm-v0.6`. +- 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.6.0 and run: + +```bash +go mod tidy +``` + +--- + +## 2) App Wiring Changes + +### IBC Transfer Module + +v0.6.0 removes the custom IBC transfer keeper override and now uses the official IBC-Go transfer keeper directly. This means that **ERC20 conversions via Cosmos IBC transfer transactions are not possible**. These are now only handled in the ICS20 precompile, and any ERC20 transfer must be initiated through there. + +**Changes required in `app.go`:** + +1. **Update imports** - Replace custom transfer imports with official IBC-Go imports: + +```diff +- import ( +- "github.com/cosmos/evm/x/ibc/transfer" +- transferkeeper "github.com/cosmos/evm/x/ibc/transfer/keeper" +- transferv2 "github.com/cosmos/evm/x/ibc/transfer/v2" +- ibctransfer "github.com/cosmos/ibc-go/v11/modules/apps/transfer" +- ibctransfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" +- ) ++ import ( ++ transfer "github.com/cosmos/ibc-go/v11/modules/apps/transfer" ++ transferkeeper "github.com/cosmos/ibc-go/v11/modules/apps/transfer/keeper" ++ ibctransfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" ++ transferv2 "github.com/cosmos/ibc-go/v11/modules/apps/transfer/v2" ++ ) +``` + +2. **Update TransferKeeper initialization** - Remove ERC20 keeper parameter: + +```diff + app.TransferKeeper = transferkeeper.NewKeeper( + appCodec, + runtime.NewKVStoreService(keys[ibctransfertypes.StoreKey]), ++ nil, // ICS4Wrapper param + app.IBCKeeper.ChannelKeeper, + app.IBCKeeper.ChannelKeeper, + app.MsgServiceRouter(), + app.AccountKeeper, + app.BankKeeper, +- app.Erc20Keeper, // Remove: no longer passed to transfer keeper + authAddr, + ) +``` + +3. **Update module registration** - Use official transfer module: + +```diff + app.BasicModuleManager = module.NewBasicManager( + // ... other modules +- ibctransfertypes.ModuleName: transfer.AppModuleBasic{AppModuleBasic: &ibctransfer.AppModuleBasic{}}, ++ ibctransfertypes.ModuleName: transfer.AppModuleBasic{}, + ) +``` + +4. **Update ICS20 precompile wiring** - Pass ERC20 keeper to ICS20 precompile: + +```diff + precompiletypes.DefaultStaticPrecompiles( + *app.StakingKeeper, + app.DistrKeeper, + app.PreciseBankKeeper, + &app.Erc20Keeper, + &app.TransferKeeper, + app.IBCKeeper.ChannelKeeper, + app.GovKeeper, + app.SlashingKeeper, + appCodec, + ) +``` + +The ICS20 precompile now takes the ERC20 keeper as a parameter (instead of the transfer keeper receiving it). This allows the precompile to handle ERC20 conversions directly. + +--- + +## 3) Breaking API Changes + +### StateDB Requirements + +v0.6.0 introduces significant changes to event tracking and state management. All EVM execution functions now require an explicit `stateDB` parameter and a `callFromPrecompile` flag to properly handle event management and state transitions. + +**NOTE:** The only function calls affected are `CallEVM`, `CallEVMWithData`, `ApplyMessage`, and `ApplyMessageWithConfig`. These are typically used in common precompiles and logic that calls back into the EVM from the SDK. If your project does not use these functions, then no steps need to be taken for the upgrade. + +#### Advanced Changes + +The following functions have updated signatures: + +##### `CallEVM` + +**Before (v0.5.x):** +```go +func (k Keeper) CallEVM( + ctx sdk.Context, + abi abi.ABI, + from, contract common.Address, + commit bool, + gasCap *big.Int, + method string, + args ...interface{}, +) (*types.MsgEthereumTxResponse, error) +``` + +**After (v0.6.0):** +```go +func (k Keeper) CallEVM( + ctx sdk.Context, + stateDB *statedb.StateDB, + abi abi.ABI, + from, contract common.Address, + commit bool, + callFromPrecompile bool, + gasCap *big.Int, + method string, + args ...interface{}, +) (*types.MsgEthereumTxResponse, error) +``` + +##### `CallEVMWithData` + +**Before (v0.5.x):** +```go +func (k Keeper) CallEVMWithData( + ctx sdk.Context, + from common.Address, + contract *common.Address, + data []byte, + commit bool, + gasCap *big.Int, +) (*types.MsgEthereumTxResponse, error) +``` + +**After (v0.6.0):** +```go +func (k Keeper) CallEVMWithData( + ctx sdk.Context, + stateDB *statedb.StateDB, + from common.Address, + contract *common.Address, + data []byte, + commit bool, + callFromPrecompile bool, + gasCap *big.Int, +) (*types.MsgEthereumTxResponse, error) +``` + +##### `ApplyMessage` + +**Before (v0.5.x):** +```go +func (k *Keeper) ApplyMessage( + ctx sdk.Context, + msg core.Message, + tracer *tracing.Hooks, + commit bool, + internal bool, +) (*types.MsgEthereumTxResponse, error) +``` + +**After (v0.6.0):** +```go +func (k *Keeper) ApplyMessage( + ctx sdk.Context, + stateDB *statedb.StateDB, + msg core.Message, + tracer *tracing.Hooks, + commit bool, + callFromPrecompile bool, + internal bool, +) (*types.MsgEthereumTxResponse, error) +``` + +##### `ApplyMessageWithConfig` + +**Before (v0.5.x):** +```go +func (k *Keeper) ApplyMessageWithConfig( + ctx sdk.Context, + msg core.Message, + tracer *tracing.Hooks, + commit bool, + cfg *statedb.EVMConfig, + txConfig statedb.TxConfig, + internal bool, + overrides *rpctypes.StateOverride, +) (*types.MsgEthereumTxResponse, error) +``` + +**After (v0.6.0):** +```go +func (k *Keeper) ApplyMessageWithConfig( + ctx sdk.Context, + stateDB *statedb.StateDB, + msg core.Message, + tracer *tracing.Hooks, + commit bool, + callFromPrecompile bool, + cfg *statedb.EVMConfig, + txConfig statedb.TxConfig, + internal bool, + overrides *rpctypes.StateOverride, +) (*types.MsgEthereumTxResponse, error) +``` + +### Migration Steps + +#### For Non-Precompile Contexts + +If you're calling EVM functions from **outside** a precompile (e.g., from a module keeper, message server, or query handler): + +1. Create a new `stateDB` before calling EVM functions +2. Pass `false` for the `callFromPrecompile` parameter + +**Example:** + +```go +import ( + "github.com/cosmos/evm/x/vm/statedb" +) + +// Before (v0.5.x) +res, err := k.evmKeeper.CallEVM( + ctx, + abi, + from, + contract, + false, // commit + nil, // gasCap + "balanceOf", + account, +) + +// After (v0.6.0) +stateDB := statedb.New(ctx, k.evmKeeper, statedb.NewEmptyTxConfig()) +res, err := k.evmKeeper.CallEVM( + ctx, + stateDB, + abi, + from, + contract, + false, // commit + false, // callFromPrecompile + nil, // gasCap + "balanceOf", + account, +) +``` + +#### For Precompile Contexts + +If you're calling EVM functions from **within** a precompile: + +1. **Reuse the existing `stateDB`** from your precompile context (do not create a new one) +2. Pass `true` for the `callFromPrecompile` parameter +3. The existing `stateDB` is typically available as a parameter in your precompile function + +**Example:** + +```go +// In your precompile's Run() method, you'll have access to stateDB +func (p *MyPrecompile) Run( + evm *vm.EVM, + contract *vm.Contract, + readOnly bool, +) ([]byte, error) { + stateDB := evm.StateDB.(*statedb.StateDB) + + // Use the existing stateDB and set callFromPrecompile=true + res, err := p.evmKeeper.CallEVM( + ctx, + stateDB, // reuse existing stateDB + abi, + from, + contract, + true, // commit (will flush to cache context) + true, // callFromPrecompile + nil, // gasCap + "transfer", + recipient, + amount, + ) +} +``` + +### Important Notes + +- **Never pass `nil` for `stateDB`**: This will return `ErrNilStateDB` error +- **Commit behavior in precompiles**: When `commit=true` and `callFromPrecompile=true`, the state changes are flushed to the cache context rather than fully committed. This prevents collapsing the cache stack in nested call scenarios. + +### EVMKeeper Interface Changes + +If you implement or mock the `EVMKeeper` interface, update your implementation: + +```go +type EVMKeeper interface { + // Updated signatures + ApplyMessage( + ctx sdk.Context, + stateDB *statedb.StateDB, + msg core.Message, + tracer *tracing.Hooks, + commit, callFromPrecompile, internal bool, + ) (*evmtypes.MsgEthereumTxResponse, error) + + CallEVM( + ctx sdk.Context, + stateDB *statedb.StateDB, + abi abi.ABI, + from, contract common.Address, + commit, callFromPrecompile bool, + gasCap *big.Int, + method string, + args ...interface{}, + ) (*evmtypes.MsgEthereumTxResponse, error) + + CallEVMWithData( + ctx sdk.Context, + stateDB *statedb.StateDB, + from common.Address, + contract *common.Address, + data []byte, + commit bool, + callFromPrecompile bool, + gasCap *big.Int, + ) (*evmtypes.MsgEthereumTxResponse, error) + + // ... other methods +} +``` + +--- + +## 4) ERC20 Keeper Interface Changes + +The `ERC20Keeper` interface has new methods: + +```go +type ERC20Keeper interface { + // ... existing methods + + // New methods in v0.6.0 + IsERC20Enabled(ctx sdk.Context) bool + GetTokenPairID(ctx sdk.Context, token string) []byte + ConvertERC20IntoCoinsForNativeToken( + ctx sdk.Context, + stateDB *statedb.StateDB, + contract ethcommon.Address, + amount math.Int, + receiver sdk.AccAddress, + sender ethcommon.Address, + commit bool, + callFromPrecompile bool, + ) (*erc20types.MsgConvertERC20Response, error) +} +``` + +If you implement this interface, add these methods to your implementation. + +--- + +## 5) Error Handling + +A new error type has been added: + +```go +var ErrNilStateDB = errorsmod.Register(ModuleName, codeErrNilStateDB, "stateDB cannot be nil") +``` + +This error is returned when `nil` is passed as the `stateDB` parameter to EVM functions. + +--- + +## 6) Build & Tests + +```bash +go build ./... +go test ./... +``` + +### Testing Checklist + +After migration, verify: +- [ ] All EVM calls pass a valid `stateDB` +- [ ] Non-precompile calls use `callFromPrecompile=false` +- [ ] Precompile calls reuse existing `stateDB` and use `callFromPrecompile=true` +- [ ] Event emission works correctly in both success and revert scenarios +- [ ] State changes are properly committed or reverted + +--- + +## Common Migration Examples + +### Example 1: Module Keeper Query + +```go +// Before (v0.5.x) +func (k Keeper) QueryBalance(ctx sdk.Context, addr common.Address) (*big.Int, error) { + res, err := k.evmKeeper.CallEVM( + ctx, erc20ABI, moduleAddr, contract, false, nil, "balanceOf", addr, + ) + // ... +} + +// After (v0.6.0) +func (k Keeper) QueryBalance(ctx sdk.Context, addr common.Address) (*big.Int, error) { + stateDB := statedb.New(ctx, k.evmKeeper, statedb.NewEmptyTxConfig()) + res, err := k.evmKeeper.CallEVM( + ctx, stateDB, erc20ABI, moduleAddr, contract, false, false, nil, "balanceOf", addr, + ) + // ... +} +``` + +### Example 2: Message Server Transaction + +```go +// Before (v0.5.x) +func (ms msgServer) ConvertCoin( + goCtx context.Context, + msg *types.MsgConvertCoin + ) (*types.MsgConvertCoinResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + // ... + res, err := ms.evmKeeper.CallEVMWithData( + ctx, moduleAddr, &contract, data, true, nil, + ) + // ... +} + +// After (v0.6.0) +func (ms msgServer) ConvertCoin( + goCtx context.Context, + msg *types.MsgConvertCoin + ) (*types.MsgConvertCoinResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + // ... + stateDB := statedb.New(ctx, ms.evmKeeper, statedb.NewEmptyTxConfig()) + res, err := ms.evmKeeper.CallEVMWithData( + ctx, stateDB, moduleAddr, &contract, data, true, false, nil, + ) + // ... +} +``` + +### Example 3: Precompile Internal Call + +```go +// Before (v0.5.x) +func (p *StakingPrecompile) delegate( + ctx sdk.Context, + evm *vm.EVM, + // ... +) ([]byte, error) { + // ... delegate logic ... + res, err := p.evmKeeper.CallEVM( + ctx, delegationABI, from, contract, true, nil, "afterDelegate", + ) + // ... +} + +// After (v0.6.0) +func (p *StakingPrecompile) delegate( + ctx sdk.Context, + evm *vm.EVM, + stateDB *statedb.StateDB, // typically passed from Run() + // ... +) ([]byte, error) { + // ... delegate logic ... + res, err := p.evmKeeper.CallEVM( + ctx, stateDB, delegationABI, from, contract, true, true, nil, "afterDelegate", + ) + // ... +} +``` \ No newline at end of file diff --git a/docs/migrations/v0.6.x_to_v0.7.0.md b/docs/migrations/v0.6.x_to_v0.7.0.md new file mode 100644 index 00000000..61bdfd4e --- /dev/null +++ b/docs/migrations/v0.6.x_to_v0.7.0.md @@ -0,0 +1,726 @@ +# Cosmos EVM v0.6.x → v0.7.0 Migration + +v0.7.0 ships two new headline features — the **Krakatoa application-layer mempool** and **BlockSTM parallel execution** (with virtual fee collection) — plus a large dependency-stack bump (cosmos-sdk v0.54, cometbft v0.39, ibc-go v11, geth 1.17, Go 1.25). The two features are independent of each other. BlockSTM is always opt-in; Krakatoa is required for forks that already wired the v0.6 `ExperimentalEVMMempool` (the type is gone in v0.7) and optional for forks on CometBFT's stock mempool. The unconditional migration work is the dependency bump and the keeper-signature shuffle that comes with it. + +Optional headline features (each enables a distinct path; see Step 5): + +- **Krakatoa mempool** (#1030, #1053, #1112) — moves the EVM mempool out of CometBFT and into the application layer. The chain gets full control over `CheckTx` / `RecheckTx`, sudo-rechecking on promote/demote, reapable-list filtering, and pool-level lifecycle hooks. Krakatoa is the only app-side EVM mempool in v0.7; the v0.6 `ExperimentalEVMMempool` type is gone. **If your v0.6 fork wired `ExperimentalEVMMempool`, migrating to Krakatoa is required** — see Step 5a. **If your v0.6 fork ran on CometBFT's stock mempool**, Krakatoa is optional and you can stay on stock CometBFT. +- **BlockSTM parallel execution** (#589, #1082, #1132) — parallel state-transition function under a software-transactional-memory scheduler, with per-tx object stores for bloom / log indexing / gas accounting and an incarnation cache for signature/auth verification. **Includes virtual fee collection** (`EndBlock` fee settlement via per-tx bank object store, 18-decimal chains only) — virtual fees are bundled with BlockSTM, not a standalone feature. Chains that don't wire the STM runner keep sequential execution. + +Other features in this release (unconditional): + +- **ICS-02 client-router precompile** (#768) — Solidity contracts can now manage IBC light clients. +- **Authority params** (#1130) — `x/vm`, `x/erc20`, `x/feemarket` `MsgServer` handlers consult `AuthorityParams` from the consensus module before falling back to per-module gov authority. +- **OpenTelemetry tracing** (#871, #863) — spans across `x/vm` and the JSON-RPC layer. +- **JSON-RPC filter lifecycle overhaul** (#1008) — idle-timeout reclamation replacing the old global filter cap. + +Secondary breaking changes — IBC callback hardening, EIP-712 verification, the `x/precisebank` deprecation, the `abi.json` strict-ABI requirement (#758) — round out the upgrade. + +The reference `evmd` also enables [optimistic execution](https://docs.cosmos.network/main/build/building-apps/optimistic-execution) (`baseapp.SetOptimisticExecution()`). That's an SDK-level feature, not new in v0.7, but if your fork hasn't turned it on yet the upgrade is a convenient time — see Step 5c for the wiring. + +For deeper background on the new features, see: + +- Krakatoa overview — *TODO: link* +- [BlockSTM and parallel execution](https://docs.cosmos.network/sdk/latest/experimental/blockstm#block-stm-parallel-transaction-execution) + +If you're skipping a release, read the [v0.5.x → v0.6.0 guide](./v0.5.x_to_v0.6.0.md) first — its StateDB / `callFromPrecompile` API break still applies. + +--- + +## Table of contents + +The migration steps split into three groups. Required steps apply to every fork; the Krakatoa and BlockSTM groups are independent and either may be skipped. (Step 5c covers optimistic execution — an SDK feature unrelated to v0.7 — for forks that haven't wired it.) + +**Required (every fork)** + +- [Step 1: Bump dependencies](#step-1-bump-dependencies) +- [Step 1.5: Migrate import paths](#step-15-migrate-import-paths) +- [Step 2: Update store keys in `app.go`](#step-2-update-store-keys-in-appgo) +- [Step 3: Update `EVMD` struct fields](#step-3-update-evmd-struct-fields) +- [Step 4: Update `NewExampleApp` and keeper constructors in `app.go`](#step-4-update-newexampleapp-and-keeper-constructors-in-appgo) +- [Step 6: Drop `x/precisebank` (18-decimal chains)](#step-6-drop-xprecisebank-18-decimal-chains) +- [Step 7: Update custom code](#step-7-update-custom-code) +- [Step 8: Coordinate the upgrade](#step-8-coordinate-the-upgrade) +- [Step 9: Verify](#step-9-verify) + +**Krakatoa application-layer mempool (required if you previously used `ExperimentalEVMMempool`; otherwise optional)** + +- [Step 5a: Krakatoa application-layer mempool](#5a-krakatoa-application-layer-mempool) + +**BlockSTM parallel execution (optional, bundled with virtual fee collection)** + +- [Step 5b: BlockSTM parallel execution and virtual fee collection](#5b-optional-blockstm-parallel-execution-and-virtual-fee-collection) + +**Optimistic execution (SDK feature, not v0.7-specific — opt-in)** + +- [Step 5c: Optimistic execution](#5c-optional-optimistic-execution) + +--- + +## Step 1: Bump dependencies + +```bash +go get github.com/cosmos/evm@v0.7.0 +go mod tidy +``` + +> **Audit every `go.mod` in your tree.** Forks with nested submodules (e.g., a separate `tests/systemtests/go.mod`) need the dependency bumps applied independently and `go mod tidy` run separately in each — root-only bumps leave the nested modules with stale `cosmossdk.io/log`, `cosmossdk.io/store` resolutions that fail to compile. + +v0.7.0 transitively bumps the entire stack. The minimum versions you need: + +| Dependency | v0.6.x | v0.7.0 | Upstream guide | +| ------------- | ------- | --------------------------------- | ------------------- | +| Go toolchain | 1.23 | **1.25** | — | +| `cosmos-sdk` | v0.53.x | **v0.54.x** (#1072) | [SDK][sdk-upgrade] | +| `cometbft` | v0.38.x | **v0.39.x** (#1112) | *TODO* | +| `ibc-go` | v10 | **v11** (#762) | [v10→v11][ibc-v11] | +| `go-ethereum` | v1.15 | **v1.17** via Cosmos fork (#1122) | [release notes][gh] | + +[sdk-upgrade]: https://github.com/cosmos/cosmos-sdk/blob/main/UPGRADING.md +[ibc-v11]: https://github.com/cosmos/ibc-go/blob/main/docs/docs/05-migrations/14-v10-to-v11.md +[gh]: https://github.com/ethereum/go-ethereum/releases + +Read the SDK and ibc-go guides end-to-end before starting — many of the keeper-signature edits in Step 4 are direct consequences of those upstream changes, and the upstream docs cover edge cases (capability migration, store/v2 nuances, gov vote-tally extension points) that this guide only summarizes. + +The geth bump uses a fork pin. Add (or update) the replace directive in your `go.mod`: + +``` +replace github.com/ethereum/go-ethereum => github.com/cosmos/go-ethereum v1.17.2-cosmos-0 +``` + +If you depend on geth APIs directly (custom tracers, custom precompiles importing `core/vm`), expect compile errors and follow the geth 1.16 → 1.17 changelog for shim updates. + +## Step 1.5: Migrate import paths + +A large block of `cosmossdk.io/...` packages moved into `github.com/cosmos/cosmos-sdk/...` in SDK v0.54, and `store` is now `store/v2`. Run these find-and-replaces across your fork: + +| Old import | New import | +| ------------------------------------------- | ---------------------------------------------------------- | +| `cosmossdk.io/store` | `github.com/cosmos/cosmos-sdk/store/v2` | +| `cosmossdk.io/store/types` | `github.com/cosmos/cosmos-sdk/store/v2/types` | +| `cosmossdk.io/store/snapshots/types` | `github.com/cosmos/cosmos-sdk/store/v2/snapshots/types` | +| `cosmossdk.io/store/prefix` | `github.com/cosmos/cosmos-sdk/store/v2/prefix` | +| `cosmossdk.io/log` | `cosmossdk.io/log/v2` | +| `cosmossdk.io/x/upgrade{,/keeper,/types}` | `github.com/cosmos/cosmos-sdk/x/upgrade/...` | +| `cosmossdk.io/x/evidence{,/keeper,/types}` | `github.com/cosmos/cosmos-sdk/x/evidence/...` | +| `cosmossdk.io/x/feegrant{,/keeper,/module}` | `github.com/cosmos/cosmos-sdk/x/feegrant/...` | +| `cosmossdk.io/x/tx/signing` | `github.com/cosmos/cosmos-sdk/x/tx/signing` | +| `cosmossdk.io/systemtests` | `github.com/cosmos/cosmos-sdk/tools/systemtests` | +| `github.com/cosmos/ibc-go/v10/...` | `github.com/cosmos/ibc-go/v11/...` | + +If your fork has a separate `tests/systemtests/go.mod` (recommended pattern), apply the rename there too and run `go mod tidy` in that submodule independently of the main module. + +Internal Cosmos EVM relocations — the top-level `github.com/cosmos/evm/config` package was deleted and its symbols redistributed: + +| v0.6 symbol | v0.7 location | +| --------------------------------- | ------------------------------------------------------ | +| `config.MustGetDefaultNodeHome` | `evmd/config.MustGetDefaultNodeHome` | +| `config.InitAppConfig` | `evmd/config.InitAppConfig` | +| `config.BlockedAddresses` | `evmd/config.BlockedAddresses` | +| `config.GetMaccPerms` | `evmd/config.GetMaccPerms` | +| `config.SetBip44CoinType` | `evmd/config.SetBip44CoinType` | +| `config.GetChainIDFromHome` | `utils.GetChainIDFromHome` | +| `config.EVMChainID` (constant) | removed — use `evmtypes.DefaultEVMChainID` | +| `config.GetCosmosPoolMaxTx` | `server.GetCosmosPoolMaxTx` | +| `config.GetLegacyPoolConfig` etc. | folded into `server.ResolveMempoolConfig` (see Step 5a)| + +The example-app helpers (`MustGetDefaultNodeHome`, `InitAppConfig`, `BlockedAddresses`, `GetMaccPerms`) moved from `github.com/cosmos/evm/config` to `github.com/cosmos/evm/evmd/config`. Mempool / chain-id helpers moved to `github.com/cosmos/evm/server` and `github.com/cosmos/evm/utils`. Update every import in `evmd/cmd/evmd/cmd/root.go`, `evmd/cmd/evmd/main.go`, and `evmd/cmd/evmd/cmd/testnet.go` accordingly. + +## Step 2: Update store keys in `app.go` + +The transient stores `evmtypes.TransientKey` and `feemarkettypes.TransientKey` were both removed. The EVM keeper still needs a per-tx scratch store for tx bloom and gas accounting, so it now consumes `evmtypes.ObjectKey` (an object store) instead. This change is **unconditional** — it applies even on the sequential path. + +Replace the transient-store declaration, mount the new object store, and build a `nonTransientKeys` slice for the EVM keeper: + +```diff + keys := storetypes.NewKVStoreKeys(/* ... */) +- tkeys := storetypes.NewTransientStoreKeys(evmtypes.TransientKey, feemarkettypes.TransientKey) ++ oKeys := storetypes.NewObjectStoreKeys(evmtypes.ObjectKey) ++ ++ var nonTransientKeys []storetypes.StoreKey ++ for _, k := range keys { ++ nonTransientKeys = append(nonTransientKeys, k) ++ } ++ for _, k := range oKeys { ++ nonTransientKeys = append(nonTransientKeys, k) ++ } + +- app.MountTransientStores(tkeys) ++ app.MountObjectStores(oKeys) +``` + +`nonTransientKeys` is the 4th argument to `evmkeeper.NewKeeper` (Step 4) and the EVM keeper uses it for cross-module store access. Step 5 reuses the same slice if you wire the BlockSTM runner. + +> **Step 5 (parallel path) extends `oKeys`** with `banktypes.ObjectStoreKey` and wires it into the bank keeper. Skip if you're not adopting virtual fee collection. + +(The matching `EVMD` struct field rename is in Step 3.) + +## Step 3: Update `EVMD` struct fields + +```diff + type EVMD struct { + // ... +- keys map[string]*storetypes.KVStoreKey +- tkeys map[string]*storetypes.TransientStoreKey +- memKeys map[string]*storetypes.MemoryStoreKey ++ keys map[string]*storetypes.KVStoreKey ++ oKeys map[string]*storetypes.ObjectStoreKey + +- clientCtx client.Context +- + // ... +- TransferKeeper transferkeeper.Keeper ++ TransferKeeper *transferkeeper.Keeper + +- EVMMempool *evmmempool.ExperimentalEVMMempool ++ EVMMempool sdkmempool.ExtMempool +- +- PreciseBankKeeper precisebankkeeper.Keeper + } +``` + +`TransferKeeper` is now stored as a pointer (ibc-go v11). `EVMMempool`'s field type was widened to the `ExtMempool` interface to permit Krakatoa or any future custom subpool. If you have getters/setters keyed on these field types (e.g. `GetTransferKeeper`, `SetTransferKeeper`), update their signatures too. + +The `Close()` method on `EVMD` does a type assertion against the old mempool type — update it to the new one (or remove if you're not wiring an EVM mempool): + +```diff + func (app *EVMD) Close() error { + var err error +- if m, ok := app.GetMempool().(*evmmempool.ExperimentalEVMMempool); ok { ++ if m, ok := app.EVMMempool.(*evmmempool.Mempool); ok && m != nil { + app.Logger().Info("Shutting down mempool") + err = m.Close() + } + // ... + } +``` + +## Step 4: Update `NewExampleApp` and keeper constructors in `app.go` + +### `NewExampleApp` signature — drop `traceStore` + +The `traceStore io.Writer` parameter is gone. Update the function signature **and every call site of your app constructor** — CLI commands (`newApp`, `appExport`, the `appCreator` callback in your root cmd), test-network fixtures (e.g., `NewTestNetworkFixture`), and any custom integration-test bootstrapping. `nil`-passing call sites need to drop the `nil` argument too. + +```diff + func NewExampleApp( + logger log.Logger, + db dbm.DB, +- traceStore io.Writer, + loadLatest bool, + appOpts servertypes.AppOptions, + baseAppOptions ...func(*baseapp.BaseApp), + ) *EVMD { +``` + +Inside, drop the corresponding tracer wiring: + +```diff +- bApp.SetCommitMultiStoreTracer(traceStore) +``` + +### `feemarketkeeper.NewKeeper` — drop transient key + +```diff + app.FeeMarketKeeper = feemarketkeeper.NewKeeper( + appCodec, authtypes.NewModuleAddress(govtypes.ModuleName), + keys[feemarkettypes.StoreKey], +- tkeys[feemarkettypes.TransientKey], + ) +``` + +### `ibckeeper.NewKeeper` — drop capability keeper + +ibc-go v11 removed the capability-keeper argument. Existing chains have nothing to migrate — the parameter was already nil — but the call must lose it: + +```diff + app.IBCKeeper = ibckeeper.NewKeeper( + appCodec, + runtime.NewKVStoreService(keys[ibcexported.StoreKey]), +- nil, + app.UpgradeKeeper, + authAddr, + ) +``` + +### `govkeeper.NewKeeper` — reordered args, new vote-results function + +Cosmos SDK v0.54 reordered the constructor and added a final pluggable vote-tally function: + +```diff + govKeeper := govkeeper.NewKeeper( + appCodec, + runtime.NewKVStoreService(keys[govtypes.StoreKey]), + app.AccountKeeper, + app.BankKeeper, +- app.StakingKeeper, + app.DistrKeeper, + app.MsgServiceRouter(), + govConfig, + authAddr, ++ govkeeper.NewDefaultCalculateVoteResultsAndVotingPower(app.StakingKeeper), + ) +``` + +### `transferkeeper.NewKeeper` — pointer return, inline address codec, drop ICS4Wrapper / duplicate ChannelKeeper + +ibc-go v11 returns `*transferkeeper.Keeper`. The constructor also takes the EVM address codec inline (no more `SetAddressCodec`) and drops the duplicate ICS4Wrapper / ChannelKeeper params: + +```diff + app.TransferKeeper = transferkeeper.NewKeeper( + appCodec, ++ evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()), + runtime.NewKVStoreService(keys[ibctransfertypes.StoreKey]), +- nil, // ICS4Wrapper param +- app.IBCKeeper.ChannelKeeper, + app.IBCKeeper.ChannelKeeper, + app.MsgServiceRouter(), + app.AccountKeeper, + app.BankKeeper, + authAddr, + ) +- app.TransferKeeper.SetAddressCodec(evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix())) +``` + +> ⚠️ The reference `evmd` instantiates `TransferKeeper` **before** `EVMKeeper` so static precompiles receive a non-nil reference. v0.6 constructs them in the opposite order (EVMKeeper, then Erc20Keeper consuming `&app.TransferKeeper`, then TransferKeeper). To swap, you'll also need to move `Erc20Keeper` so it's constructed *after* `TransferKeeper` — and `Erc20Keeper` itself now takes the pointer-typed `app.TransferKeeper` directly, no `&`. Walk the three keeper constructions as a unit, not individually. + +### IBC callbacks middleware — wrap with setter calls + +ibc-go v11 split the constructor and the wrapping. Replace the single-line `NewIBCMiddleware` with the three-step setter form: + +```diff +- transferStack = ibccallbacks.NewIBCMiddleware(transferStack, app.IBCKeeper.ChannelKeeper, app.CallbackKeeper, maxCallbackGas) ++ callbacksMiddleware := ibccallbacks.NewIBCMiddleware(app.CallbackKeeper, maxCallbackGas) ++ callbacksMiddleware.SetICS4Wrapper(app.IBCKeeper.ChannelKeeper) ++ callbacksMiddleware.SetUnderlyingApplication(transferStack) ++ transferStack = callbacksMiddleware +``` + +Both setters are required — `NewIBCMiddleware` itself doesn't accept either argument anymore. A middleware constructed without `SetICS4Wrapper` or `SetUnderlyingApplication` compiles but panics with a nil-pointer dereference on the first packet send / receive (the constructor does panic on a nil contract keeper or zero gas, but the wrapper / underlying-app fields are checked at use, not construction). + +### `evmkeeper.NewKeeper` — object store key, store-key slice, BankKeeper replaces PreciseBankKeeper + +The third arg is the new EVM object-store key (Step 2). The fourth changed from `map[string]*storetypes.KVStoreKey` to `[]storetypes.StoreKey` — the keeper uses it for cross-module store access. Pass the `nonTransientKeys` slice from Step 2; the same slice is also what the STM runner tracks if you opt into Step 5. + +```diff + app.EVMKeeper = evmkeeper.NewKeeper( +- appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey], keys, ++ appCodec, keys[evmtypes.StoreKey], oKeys[evmtypes.ObjectKey], nonTransientKeys, + authtypes.NewModuleAddress(govtypes.ModuleName), + app.AccountKeeper, +- app.PreciseBankKeeper, ++ app.BankKeeper, + app.StakingKeeper, + app.FeeMarketKeeper, + &app.ConsensusParamsKeeper, + &app.Erc20Keeper, + evmChainID, + tracer, + ) +``` + +### `DefaultStaticPrecompiles` — Bank, dereferenced TransferKeeper, ClientKeeper + +`TransferKeeper` is already a pointer (Step 3); pass it directly. `IBCKeeper.ClientKeeper` is the new dependency — it backs the ICS-02 client-router precompile (#768): + +```diff + precompiletypes.DefaultStaticPrecompiles( + *app.StakingKeeper, + app.DistrKeeper, +- app.PreciseBankKeeper, ++ app.BankKeeper, + &app.Erc20Keeper, +- &app.TransferKeeper, ++ app.TransferKeeper, + app.IBCKeeper.ChannelKeeper, ++ app.IBCKeeper.ClientKeeper, + app.GovKeeper, + app.SlashingKeeper, + appCodec, + ) +``` + +### `erc20keeper.NewKeeper` — Bank, dereferenced TransferKeeper + +```diff + app.Erc20Keeper = erc20keeper.NewKeeper( + keys[erc20types.StoreKey], + appCodec, + authtypes.NewModuleAddress(govtypes.ModuleName), + app.AccountKeeper, +- app.PreciseBankKeeper, ++ app.BankKeeper, + app.EVMKeeper, + app.StakingKeeper, +- &app.TransferKeeper, ++ app.TransferKeeper, + ) +``` + +### `node.RegisterNodeService` — earliest-version callback + +```diff + func (app *EVMD) RegisterNodeService(clientCtx client.Context, cfg config.Config) { +- node.RegisterNodeService(clientCtx, app.GRPCQueryRouter(), cfg) ++ node.RegisterNodeService(clientCtx, app.GRPCQueryRouter(), cfg, func() int64 { ++ return app.CommitMultiStore().EarliestVersion() ++ }) + } +``` + +### Hydrate EVM globals on restart (#1126) + +Required regardless of which path you choose. After `LoadLatestVersion` (inside `if loadLatest`), hydrate the EVM globals from KV so `evmCoinInfo` is populated before any RPC handler runs: + +```diff ++ ctx := app.NewContextLegacy(true, cmtproto.Header{ ++ Height: app.LastBlockHeight(), ++ ChainID: app.ChainID(), ++ }) ++ vmModule.HydrateGlobals(ctx) +``` + +Without this, RPC calls that arrive before `PreBlock` panic on a nil `evmCoinInfo`. + +`vmModule` here is the value returned by `vm.NewAppModule(...)`. v0.6 calls `vm.NewAppModule(...)` inline inside `app.ModuleManager = module.NewManager(...)`, so before the `HydrateGlobals` call you'll need to refactor: bind the result to a local first, then pass that local into `module.NewManager`: + +```diff +- app.ModuleManager = module.NewManager( +- // ... other modules +- vm.NewAppModule(app.EVMKeeper, app.AccountKeeper, app.BankKeeper, app.AccountKeeper.AddressCodec()), +- // ... +- ) ++ vmModule := vm.NewAppModule(app.EVMKeeper, app.AccountKeeper, app.BankKeeper, app.AccountKeeper.AddressCodec()) ++ ++ app.ModuleManager = module.NewManager( ++ // ... other modules ++ vmModule, ++ // ... ++ ) +``` + +Imports to add: `cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"`. + +### Wire the EVM tx runner (#1132) + +Required regardless of path. `vmrunner.SetRunner` installs the baseapp tx runner wrapped with the EVM module's `PatchTxResponses` post-execution log/tx index fix-up. Without it, `log.Index` and `transactionIndex` on receipts are wrong (the bug #1132 corrected). The wrapper works for both sequential and parallel inner runners — only the inner runner choice differs by path: + +- **Sequential (default)** — pass `txnrunner.NewDefaultRunner(txDecoder)`. +- **Parallel** — pass `txnrunner.NewSTMRunner(...)` (see Step 5b). + +Bind the tx decoder to a local at the top of `NewExampleApp` so it can be reused by the runner (and by `bApp := baseapp.NewBaseApp(...)` if you want to share it): + +```diff + txConfig := encodingConfig.TxConfig ++ txDecoder := encodingConfig.TxConfig.TxDecoder() +``` + +Then add the runner call just before `return app`. The sequential form: + +```diff ++ vmrunner.SetRunner(bApp, txnrunner.NewDefaultRunner(txDecoder)) +``` + +Imports to add: `"github.com/cosmos/cosmos-sdk/baseapp/txnrunner"`, `vmrunner "github.com/cosmos/evm/x/vm/runner"`. + +### Removed `EVMD` methods + +These were deleted; remove any callers: + +- `GetTKey`, `GetMemKey` — transient/mem stores no longer exist as separate maps. +- `GetAuthzKeeper` — the helper was redundant; expose `app.AuthzKeeper` directly if you need it. +- `GetPreciseBankKeeper` — module is removed (Step 6). +- `SetClientCtx` and the `clientCtx` field — unused. + +## Step 5: Enable Krakatoa and/or BlockSTM + +Two independent v0.7 opt-ins: + +- **Krakatoa (5a)** is required for forks that already used the v0.6 `ExperimentalEVMMempool` (the type was removed); optional for forks on CometBFT's stock mempool. +- **BlockSTM with virtual fee collection (5b)** is always opt-in. Skip 5b to keep sequential execution. + +Step 5c documents `baseapp.SetOptimisticExecution()` separately — it's an SDK-level feature, not new in v0.7, but the reference `evmd/app.go` enables it and forks that haven't yet adopted it can use this upgrade as the moment to do so. + +> **State-breaking features.** Each ships as part of the binary; adopting or dropping any of them requires a coordinated `MsgSoftwareUpgrade` and a binary swap, the same as any other consensus change. + +### 5a. Krakatoa application-layer mempool + +Krakatoa is the only app-side EVM mempool in v0.7. The `ExperimentalEVMMempool` type from v0.6 is gone, so optionality depends on what your v0.6 fork already used: + +- **If you wired `ExperimentalEVMMempool` in v0.6**: this step is **required**. The construction signature changed and the handler set was redesigned; you must migrate or your fork won't compile. +- **If you ran on CometBFT's stock mempool in v0.6** (no app-side EVM mempool): this step is **optional**. Adopt Krakatoa to gain app-level `CheckTx` / `RecheckTx` control, or skip it and stay on stock CometBFT. + +Independent of BlockSTM either way. + +To migrate from `ExperimentalEVMMempool`, replace the construction with `evmmempool.NewMempool` and the new handler set. The full reference is `evmd/mempool.go`'s `configureEVMMempool` — read it before applying the diff below; the local variables it constructs (`mpConfig`, `txEncoder`, `evmRechecker`, `cosmosRechecker`, `cosmosPoolMaxTx`, `checkTxTimeout`) are what the new `NewMempool` signature consumes: + +```go +// Setup block (in evmd/mempool.go's configureEVMMempool, all required): +mpConfig := server.ResolveMempoolConfig(app.GetAnteHandler(), appOpts, logger) +txEncoder := evmmempool.NewTxEncoder(app.txConfig) +evmRechecker := evmmempool.NewTxRechecker(mpConfig.AnteHandler, txEncoder) +cosmosRechecker := evmmempool.NewTxRechecker(mpConfig.AnteHandler, txEncoder) +cosmosPoolMaxTx := server.GetCosmosPoolMaxTx(appOpts, logger) +checkTxTimeout := server.GetMempoolCheckTxTimeout(appOpts, logger) +``` + +`server.ResolveMempoolConfig`, `server.GetCosmosPoolMaxTx`, and `server.GetMempoolCheckTxTimeout` are all in `github.com/cosmos/evm/server`; the `evmconfig.GetLegacyPoolConfig` / `GetBlockGasLimit` / `GetMinTip` helpers from v0.6 collapsed into `ResolveMempoolConfig`. `app.TxDecode` and the `SetInsertTxHandler` / `SetReapTxsHandler` setters are new in cosmos-sdk v0.54 baseapp. + +> **Ordering: `app.SetAnteHandler(...)` must run before `configureEVMMempool`.** `ResolveMempoolConfig` calls `app.GetAnteHandler()` and stashes the result on `mpConfig.AnteHandler`, which the recheckers then close over. If the ante handler hasn't been set yet, `GetAnteHandler` returns nil and the chain panics on first `RecheckTx`. There's no compile-time signal — get the ordering right. +> **`evmRechecker` and `cosmosRechecker` must be distinct instances**, even though they wrap identical config. They feed different subpools (the EVM eth-tx pool vs. the Cosmos pool) and need independent state for promotion/demotion bookkeeping. Sharing one instance compiles fine but produces silent cross-pool state interference at promote/demote time. + +Then replace the construction and handler wiring: + +```diff +- evmMempool := evmmempool.NewExperimentalEVMMempool( +- app.CreateQueryContext, logger, +- app.EVMKeeper, app.FeeMarketKeeper, app.txConfig, app.clientCtx, +- mempoolConfig, cosmosPoolMaxTx, +- ) +- app.EVMMempool = evmMempool +- app.SetMempool(evmMempool) +- checkTxHandler := evmmempool.NewCheckTxHandler(evmMempool) +- app.SetCheckTxHandler(checkTxHandler) +- abciProposalHandler := baseapp.NewDefaultProposalHandler(evmMempool, app) +- abciProposalHandler.SetSignerExtractionAdapter(/* ... */) +- app.SetPrepareProposal(abciProposalHandler.PrepareProposalHandler()) ++ mempool := evmmempool.NewMempool( ++ app.CreateQueryContext, logger, ++ app.EVMKeeper, app.FeeMarketKeeper, app.txConfig, ++ evmRechecker, cosmosRechecker, mpConfig, cosmosPoolMaxTx, ++ ) ++ app.EVMMempool = mempool ++ app.SetPrepareProposal(baseapp.NewDefaultProposalHandler(mempool, NewNoCheckProposalTxVerifier(app.BaseApp)).PrepareProposalHandler()) ++ app.SetInsertTxHandler(mempool.NewInsertTxHandler(app.TxDecode)) ++ app.SetReapTxsHandler(mempool.NewReapTxsHandler()) ++ app.SetCheckTxHandler(mempool.NewCheckTxHandler(app.TxDecode, checkTxTimeout)) ++ app.SetMempool(mempool) +``` + +> The reference application uses a `NewNoCheckProposalTxVerifier` at proposal time when verifying the txs in a given proposal. This is a performance optimization since with the Krakatoa mempool, it is a requirement that every tx within the proposal has already been validated, thus this check is redundant. If you choose to adopt this pattern as well copy the reference `NewNoCheckProposalTxVerifier` and pass this to your `PrepareProposalHandler`. + +To opt out entirely, drop the `configureEVMMempool(...)` call from `NewExampleApp`, or set `mempool.max-txs=-1` in `app.toml` (the SDK `FlagMempoolMaxTxs` — note this is the top-level `[mempool]` key, not `evm.mempool.max-txs`). `configureEVMMempool` reads it via `server.GetCosmosPoolMaxTx`, bails out on a negative value, and falls back to CometBFT's stock mempool. + +> ⚠️ **Set `mempool.type = "app"` in `config.toml`.** CometBFT v0.39 requires the app-side mempool type whenever the application supplies an EVM mempool. The default is `"flood"`; Krakatoa errors out at startup if it's left as the default. This is a one-line patch to each validator's `config.toml` (or your fork's equivalent), applied at the same time as the binary swap. Forks that opt out of Krakatoa (the previous paragraph) don't need this. +> Note that by setting `mempool.type = "app"` in `config.toml`, there are additional configuration parameters you may want to configure that will affect Krakatoa mempool operations. Please see the CometBFT application mempool documentation for more info. — *TODO: link* + +### 5b. (Optional) BlockSTM parallel execution and virtual fee collection + +BlockSTM enables parallel execution of the state-transition function and bundles virtual fee collection (per-tx bank-balance accounting reduced at `EndBlock`). **Not** required — chains that skip this section keep sequential execution. Independent of Krakatoa, and independent of optimistic execution (5c). + +The two pieces below are wired together; you opt into the bundle, not into individual lines. + +#### Swap the inner tx runner to BlockSTM + +Step 4 already wired `vmrunner.SetRunner(bApp, ...)` with the sequential `txnrunner.NewDefaultRunner(txDecoder)` as the inner runner. To opt into parallel execution, swap the inner runner for `txnrunner.NewSTMRunner(...)`: + +```diff +- vmrunner.SetRunner(bApp, txnrunner.NewDefaultRunner(txDecoder)) ++ vmrunner.SetRunner(bApp, txnrunner.NewSTMRunner( ++ txDecoder, ++ nonTransientKeys, ++ min(goruntime.GOMAXPROCS(0), goruntime.NumCPU()), ++ true, ++ func(ms storetypes.MultiStore) string { ++ return app.EVMKeeper.GetParams(sdk.NewContext(ms, cmtproto.Header{}, false, log.NewNopLogger())).EvmDenom ++ }, ++ )) +``` + +The EvmDenom callback reads from EVM params on the live multi-store; do not hard-code `sdk.DefaultBondDenom` — chains that customized their EVM denom will diverge. + +Additional import: `goruntime "runtime"`. + +#### Virtual fee collection (18-decimal chains only) + +Virtual fee collection is part of the BlockSTM bundle — it's what lets fee settlement happen in parallel without contending the fee collector account on every tx. Two pieces are required. + +First, extend the `oKeys` declaration from Step 2 with `banktypes.ObjectStoreKey` and wire it into the bank keeper. **Order matters**: the `oKeys` declaration must include `banktypes.ObjectStoreKey` *before* the `for _, k := range oKeys` loop that builds `nonTransientKeys`, otherwise the bank object store won't be in the slice the EVM keeper sees. Apply the change at the Step 2 declaration site, not later: + +```diff +- oKeys := storetypes.NewObjectStoreKeys(evmtypes.ObjectKey) ++ oKeys := storetypes.NewObjectStoreKeys(banktypes.ObjectStoreKey, evmtypes.ObjectKey) +``` + +Then, after `BankKeeper` is constructed, wire the object-store key into it: + +```diff ++ app.BankKeeper = app.BankKeeper.WithObjStoreKey(oKeys[banktypes.ObjectStoreKey]) +``` + +`WithObjStoreKey(storetypes.StoreKey) BaseKeeper` is part of the `bankkeeper.Keeper` interface in cosmos-sdk v0.54, so the call works whether your `EVMD.BankKeeper` field is the interface (`bankkeeper.Keeper`, the reference default) or the concrete `bankkeeper.BaseKeeper`. The method returns `BaseKeeper`, but `BaseKeeper` satisfies `Keeper`, so assigning the result back to an interface-typed field type-checks. No field-widening required. + +Then, after `WithStaticPrecompiles`, enable virtual fees on the EVM keeper: + +```diff + app.EVMKeeper = evmkeeper.NewKeeper(/* ... */).WithStaticPrecompiles(/* ... */) ++ app.EVMKeeper.EnableVirtualFeeCollection() +``` + +> ⚠️ **Do not call `EnableVirtualFeeCollection()` if your gas token is not 18-decimal.** `x/vm/keeper.DeductFees` reads the EVM denom's bank metadata and panics if the display-denom unit's exponent is not 18 (`x/vm/keeper/fees.go:156`). See Step 6. A non-18-decimal chain that still wants BlockSTM has to skip this final piece — but the parallel path's main throughput win comes from virtual fees, so the practical recommendation is to migrate to 18 decimals first. + +### 5c. (Optional) Optimistic execution + +**Not new in v0.7** — `baseapp.SetOptimisticExecution()` has been an SDK feature since v0.50. Documented here because the reference `evmd/app.go` ships with it enabled, and forks that haven't yet adopted it can fold the wiring into this upgrade. Independent of BlockSTM and Krakatoa. + +The feature overlaps `FinalizeBlock` for height `H` with `ProcessProposal` for height `H+1`: while CometBFT is still finalizing the current block, the app speculatively executes the next proposed block. If the speculative result matches what `FinalizeBlock` is later asked to commit, the result is reused; if it diverges, the speculative state is discarded and execution falls back to the standard path. + +The reference `evmd/app.go` enables it. Add the option to `baseAppOptions` **before** `baseapp.NewBaseApp(...)` is called — append after the `baseAppOptions ...func(*baseapp.BaseApp)` parameter is in scope but before the constructor consumes it: + +```diff + func NewExampleApp( + logger log.Logger, + db dbm.DB, + loadLatest bool, + appOpts servertypes.AppOptions, + baseAppOptions ...func(*baseapp.BaseApp), + ) *EVMD { + // ... encoding/txDecoder setup ... + ++ // enable optimistic execution ++ baseAppOptions = append( ++ baseAppOptions, ++ baseapp.SetOptimisticExecution(), ++ ) + + bApp := baseapp.NewBaseApp( + appName, logger, db, txDecoder, + baseAppOptions..., + ) +``` + +Operational notes: + +- **Determinism is preserved.** Speculative execution uses a sandboxed cache; on a mismatch the state is dropped, not committed. The user-visible behavior is identical to non-optimistic execution — only the latency of `FinalizeBlock` shifts. +- **Composes with BlockSTM (5b) and Krakatoa (5a).** Optimistic execution runs the speculative block through whichever runner is wired (`vmrunner.SetRunner`), so you get parallel-on-speculative + parallel-on-final when 5b is also enabled. +- **State-breaking.** Like 5a and 5b, this is baked into the binary. Adopting or dropping it requires a coordinated `MsgSoftwareUpgrade`, not a runtime toggle. See Step 8. +- **Resource cost.** The speculative path uses an extra goroutine and an extra working state cache per height. On memory-tight nodes you may prefer to disable it; the SDK doc linked at the top of this guide covers the trade-offs. + +## Step 6: Drop `x/precisebank` + +`x/precisebank` is deprecated (#1019). It only ever made sense for non-18-decimal gas tokens — it bridged them into the EVM's 18-decimal world. The reference v0.6 `evmd/app.go` wired it unconditionally despite the inline comment "PreciseBank is not needed if SDK use 18 decimals for gas coin", so most v0.6 forks have it threaded through `evmkeeper`, `erc20keeper`, and the precompiles regardless of their gas token's decimals. + +In v0.7 the module is gone from the main tree. `EvmCoinInfo.Decimals` is also marked deprecated (#1029). + +> **Non-18-decimal chains are not fully supported going forward.** v0.7.0 still ships precisebank under `contrib/x/precisebank`, but future EVM releases will not test or maintain it. Either stay on v0.6.x until you can migrate to 18 decimals, or pin `cosmos/evm/contrib/x/precisebank` and **do not** enable virtual fee collection (5b). + +If your fork wired `PreciseBankKeeper` (whether or not your gas token is 18-decimal), unwire it: + +```diff + type EVMD struct { + // ... other keepers +- PreciseBankKeeper precisebankkeeper.Keeper + } + +- // Set up PreciseBank keeper +- app.PreciseBankKeeper = precisebankkeeper.NewKeeper(/* ... */) + + app.ModuleManager = module.NewManager( + // ... other modules +- precisebank.NewAppModule(app.PreciseBankKeeper, app.BankKeeper, app.AccountKeeper), + ) + +- func (app *EVMD) GetPreciseBankKeeper() *precisebankkeeper.Keeper { /* ... */ } +``` + +Also drop `precisebanktypes.StoreKey` from the `keys` declaration and the module name from your `SetOrderBeginBlockers` / `SetOrderEndBlockers` / `SetOrderInitGenesis` lists. + +Replace every `app.PreciseBankKeeper` reference (in `evmkeeper.NewKeeper`, `erc20keeper.NewKeeper`, `DefaultStaticPrecompiles`, and any custom modules) with `app.BankKeeper`. Verify decimal expectations at each call site — anywhere your code assumed the precisebank denom translation was happening, you now need to either operate on 18-decimal values directly or do the conversion yourself. + +Tests that referenced precisebank also need cleanup. In the reference repo this meant deleting `evmd/tests/integration/x_precisebank_test.go` and removing `PreciseBankMintEventCount` / `PreciseBankBurnEventCount` and their consumers from `evmd/tests/ibc/helper.go`. Audit your fork's test tree for any `precisebank` symbols and drop them — the code won't compile against v0.7 with them present. + +## Step 7: Update custom code + +### Custom ante handlers / mempool plugins + +The transient stores backing gas accounting and the feemarket are gone. Read gas-wanted from the SDK context instead — `ctx.GasMeter().GasConsumed()`. If your decorator wrote to the feemarket transient store, remove that logic — `feemarkettypes.TransientKey` and the keeper methods `GetTransientGasWanted`, `SetTransientBlockGasWanted`, `AddTransientGasWanted` are all gone. The same applies to the EVM keeper: `GetBlockBloomTransient`, `SetBlockBloomTransient`, `GetTxIndexTransient`, `SetTxIndexTransient`, and `WithDefaultEvmCoinInfo` were removed. + +### Custom `BankKeeper` / `BankWrapper` implementations + +The interfaces in `x/vm/types/interfaces.go` changed. Any fork that supplies a non-default bank wrapper must update. + +`BankKeeper` gained five methods to support virtual fee collection and parallel-safe balance accounting: + +```go +SendCoinsFromModuleToAccountVirtual( + ctx context.Context, senderModule string, + recipientAddr sdk.AccAddress, amt sdk.Coins, +) error +SendCoinsFromAccountToModuleVirtual( + ctx context.Context, senderAddr sdk.AccAddress, + recipientModule string, amt sdk.Coins, +) error +UncheckedSetBalance(ctx context.Context, addr sdk.AccAddress, amt sdk.Coin) error +LockedCoins(ctx context.Context, addr sdk.AccAddress) sdk.Coins +BlockedAddr(addr sdk.AccAddress) bool +``` + +`BankWrapper` is a hard API break: `MintAmountToAccount` and `BurnAmountFromAccount` were **removed** and replaced by a single `SetBalance(ctx, account, amt *big.Int) error`. Callers and implementations must both change. + +`EmitBlockBloomEvent`'s argument type changed from `ethtypes.Bloom` to `[]byte`. + +A new `VMKeeper` interface (`GetEvmCoinInfo`) was added; some helpers now take it instead of a concrete keeper. + +### Custom indexers / receipt consumers + +- Read `log.Index` and `log.TxIndex` only after post-execution patching (#1132). Recomputing from raw event order will diverge from canonical receipts. +- Drop any workaround that special-cased the `MaxUint64` overflow on `transactionIndex` — fixed in #1047. +- Don't assume tx counts in receipt arrays match raw block tx counts. StateDB-error txs are now skipped during receipt conversion (#1107). + +### Forks of precompile `abi.json` + +PR #758 made the precompile ABI files strict — only valid Ethereum ABI fields are accepted. Forks that vendor or override `abi.json` for any precompile must remove non-ABI extension fields, or they will fail to parse at startup. + +### Removed helpers + +- `Params.GetActiveStaticPrecompilesAddrs()` is gone — derive `[]common.Address` yourself if you used it. + +### Mocks of `EVMKeeper` + +Regenerate against v0.7.0 — the constructor signature (Step 4) and static-precompile dependencies (Step 4) shifted. + +## Step 8: Coordinate the upgrade + +This is a normal Cosmos consensus-breaking upgrade. + +- **All validators must run the same v0.7 binary post-upgrade.** Mixing v0.6 and v0.7 binaries will fork. +- **Step 5 (Krakatoa, BlockSTM + virtual fees, optimistic execution) is state-breaking.** Each is baked into the binary — adopting or dropping any of them later is another coordinated `MsgSoftwareUpgrade`, not a runtime toggle. +- **There is no on-chain governance flag** for these toggles. Switching paths later requires a new binary release and another `MsgSoftwareUpgrade`. + +Update the upgrade handler's `UpgradeName` constant **and its doc comment** to match the new release. The doc-comment drift between releases is a recurring foot-gun — the system test reads the constant verbatim, but readers and downstream handlers grep the comment for context: + +```diff + // evmd/upgrades.go (or wherever your fork keeps its upgrade name) +- // 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.5.0-to-v0.6.0" ++ // NOTE: This upgrade defines a reference implementation of what an upgrade ++ // could look like when an application is migrating from EVMD version ++ // v0.6.x to v0.7.0 ++ const UpgradeName = "v0.6.0-to-v0.7.0" +``` + +The reference upgrade handler runs `RunMigrations` with empty `StoreUpgrades` — no module schema changes. Submit a `MsgSoftwareUpgrade` with `name: "v0.6.0-to-v0.7.0"` at your target height and swap the binary at the halt height. + +## Step 9: Verify + +```bash +go build ./... +go test ./... +``` + +### Sanity check the upgrade path + +```bash +make test-system +``` + +Drives a `MsgSoftwareUpgrade` for `v0.6.0-to-v0.7.0`, swaps to the v0.7 binary at the halt height, and runs a contended-account workload (many txs hitting the same hot contract per block). On the parallel path this exercises the BlockSTM scheduler's conflict detection across the upgrade boundary; on the sequential path it's still a useful end-to-end smoke test. + +The test reads a v0.6-era binary from `tests/systemtests/binaries/v0.6/evmd`. **For your fork, that binary is your own chain build pinned to the v0.6 cosmos-evm dependency** — not a generic `cosmos/evm@v0.6.0` binary. The legacy build's keepers, ante decorators, and module set must match what your validators are actually running pre-upgrade, otherwise the test exercises the wrong starting state. + +Wire whatever `make` (or shell) target you use for this — the key constraints are: + +- Output goes to `tests/systemtests/binaries/v0.6/evmd` (or wherever your `chainupgrade/v6_v7.go` reads from). +- Your `test-system` Make target (or equivalent) depends on it and on the current binary, in that order. +- If your previous release had a `build-v05` target chained from `test-system`, retarget that dependency to the new `build-v06` (or whatever you name it). diff --git a/encoding/address/address_codec_test.go b/encoding/address/address_codec_test.go index d4e690c6..13a90cdd 100644 --- a/encoding/address/address_codec_test.go +++ b/encoding/address/address_codec_test.go @@ -8,8 +8,6 @@ import ( evmaddress "github.com/cosmos/evm/encoding/address" - "cosmossdk.io/core/address" - sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) @@ -118,7 +116,7 @@ func TestBytesToString(t *testing.T) { addrBz := common.HexToAddress(hex).Bytes() // 20 bytes // Helper codec (used only where we want to derive bytes from the bech32 string) - var cdc address.Codec + cdc := evmaddress.NewEvmCodec("cosmos") type tc struct { name string diff --git a/encoding/config.go b/encoding/config.go index 4e1d897f..352c829b 100644 --- a/encoding/config.go +++ b/encoding/config.go @@ -10,14 +10,13 @@ import ( evmtypes "github.com/cosmos/evm/x/vm/types" "github.com/cosmos/gogoproto/proto" - "cosmossdk.io/x/tx/signing" - "github.com/cosmos/cosmos-sdk/client" amino "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx" "github.com/cosmos/cosmos-sdk/x/auth/tx" + "github.com/cosmos/cosmos-sdk/x/tx/signing" ) // Config specifies the concrete encoding types to use for a given app. diff --git a/ethereum/eip712/encoding.go b/ethereum/eip712/encoding.go index 5292fa4e..b052fc98 100644 --- a/ethereum/eip712/encoding.go +++ b/ethereum/eip712/encoding.go @@ -1,20 +1,28 @@ package eip712 import ( + "context" "errors" "fmt" + "strconv" apitypes "github.com/ethereum/go-ethereum/signer/core/apitypes" + txv1beta1 "cosmossdk.io/api/cosmos/tx/v1beta1" + errorsmod "cosmossdk.io/errors" + "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/types" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" txTypes "github.com/cosmos/cosmos-sdk/types/tx" "github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx" + txsigning "github.com/cosmos/cosmos-sdk/x/tx/signing" + "github.com/cosmos/cosmos-sdk/x/tx/signing/aminojson" ) var ( - protoCodec codec.ProtoCodecMarshaler + protoCodec codec.Codec aminoCodec *codec.LegacyAmino eip155ChainID uint64 ) @@ -102,7 +110,7 @@ func decodeAminoSignDoc(signDocBytes []byte) (apitypes.TypedData, error) { } typedData, err := WrapTxToTypedData( - eip155ChainID, + chainIDFromSignDoc(aminoDoc.ChainID), signDocBytes, ) if err != nil { @@ -159,25 +167,44 @@ func decodeProtobufSignDoc(signDocBytes []byte) (apitypes.TypedData, error) { } signerInfo := authInfo.SignerInfos[0] - - stdFee := &legacytx.StdFee{ - Amount: authInfo.Fee.Amount, - Gas: authInfo.Fee.GasLimit, + var pubKey cryptotypes.PubKey + err := protoCodec.UnpackAny(signerInfo.PublicKey, &pubKey) + if err != nil { + return apitypes.TypedData{}, errorsmod.Wrap(err, "failed to unpack signer public key") } - // WrapTxToTypedData expects the payload as an Amino Sign Doc - signBytes := legacytx.StdSignBytes( - signDoc.ChainId, - signDoc.AccountNumber, - signerInfo.Sequence, - body.TimeoutHeight, - *stdFee, - msgs, - body.Memo, - ) + anyMsgs, err := ToAnyMsgs(msgs) + if err != nil { + return apitypes.TypedData{}, err + } + feeAmount := ToFeeAmount(authInfo.Fee.Amount) + txData := txsigning.TxData{ + Body: &txv1beta1.TxBody{ + Messages: anyMsgs, + Memo: body.Memo, + TimeoutHeight: body.TimeoutHeight, + }, + AuthInfo: &txv1beta1.AuthInfo{ + Fee: &txv1beta1.Fee{ + Amount: feeAmount, + GasLimit: authInfo.Fee.GasLimit, + }, + }, + } + signModeHandler := aminojson.NewSignModeHandler(aminojson.SignModeHandlerOptions{}) + signer := txsigning.SignerData{ + ChainID: signDoc.ChainId, + AccountNumber: signDoc.AccountNumber, + Sequence: signerInfo.Sequence, + Address: pubKey.Address().String(), + } + signBytes, err := signModeHandler.GetSignBytes(context.Background(), signer, txData) + if err != nil { + return apitypes.TypedData{}, errorsmod.Wrap(err, "failed to get sign bytes using aminojson") + } typedData, err := WrapTxToTypedData( - eip155ChainID, + chainIDFromSignDoc(signDoc.ChainId), signBytes, ) if err != nil { @@ -187,6 +214,19 @@ func decodeProtobufSignDoc(signDocBytes []byte) (apitypes.TypedData, error) { return typedData, nil } +// chainIDFromSignDoc uses the chain id on the sign doc when it parses as a uint64. +// Otherwise it falls back to the configured EVM chain id. +func chainIDFromSignDoc(chainIDStr string) uint64 { + if chainIDStr == "" { + return eip155ChainID + } + parsed, err := strconv.ParseUint(chainIDStr, 10, 64) + if err != nil { + return eip155ChainID + } + return parsed +} + // validateCodecInit ensures that both Amino and Protobuf encoding codecs have been set on app init, // so the module does not panic if either codec is not found. func validateCodecInit() error { diff --git a/ethereum/eip712/encoding_legacy.go b/ethereum/eip712/encoding_legacy.go index d0efecf5..49376225 100644 --- a/ethereum/eip712/encoding_legacy.go +++ b/ethereum/eip712/encoding_legacy.go @@ -1,15 +1,22 @@ package eip712 import ( + "context" "encoding/json" "errors" "fmt" apitypes "github.com/ethereum/go-ethereum/signer/core/apitypes" + txv1beta1 "cosmossdk.io/api/cosmos/tx/v1beta1" + errorsmod "cosmossdk.io/errors" + + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" txTypes "github.com/cosmos/cosmos-sdk/types/tx" "github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx" + txsigning "github.com/cosmos/cosmos-sdk/x/tx/signing" + "github.com/cosmos/cosmos-sdk/x/tx/signing/aminojson" ) type aminoMessage struct { @@ -157,14 +164,12 @@ func legacyDecodeProtobufSignDoc(signDocBytes []byte, eip155ChainID uint64) (api // Use first message for fee payer and type inference msg := msgs[0] - signerInfo := authInfo.SignerInfos[0] - - stdFee := &legacytx.StdFee{ - Amount: authInfo.Fee.Amount, - Gas: authInfo.Fee.GasLimit, + var pubKey cryptotypes.PubKey + err := protoCodec.UnpackAny(signerInfo.PublicKey, &pubKey) + if err != nil { + return apitypes.TypedData{}, errorsmod.Wrap(err, "failed to unpack signer public key") } - signers, _, err := protoCodec.GetMsgV1Signers(msg) if err != nil { return apitypes.TypedData{}, err @@ -175,15 +180,36 @@ func legacyDecodeProtobufSignDoc(signDocBytes []byte, eip155ChainID uint64) (api } // WrapTxToTypedData expects the payload as an Amino Sign Doc - signBytes := legacytx.StdSignBytes( - signDoc.ChainId, - signDoc.AccountNumber, - signerInfo.Sequence, - body.TimeoutHeight, - *stdFee, - msgs, - body.Memo, - ) + anyMsgs, err := ToAnyMsgs(msgs) + if err != nil { + return apitypes.TypedData{}, err + } + feeAmount := ToFeeAmount(authInfo.Fee.Amount) + txData := txsigning.TxData{ + Body: &txv1beta1.TxBody{ + Messages: anyMsgs, + Memo: body.Memo, + TimeoutHeight: body.TimeoutHeight, + }, + AuthInfo: &txv1beta1.AuthInfo{ + Fee: &txv1beta1.Fee{ + Amount: feeAmount, + GasLimit: authInfo.Fee.GasLimit, + }, + }, + } + + signModeHandler := aminojson.NewSignModeHandler(aminojson.SignModeHandlerOptions{}) + signer := txsigning.SignerData{ + ChainID: signDoc.ChainId, + AccountNumber: signDoc.AccountNumber, + Sequence: signerInfo.Sequence, + Address: pubKey.Address().String(), + } + signBytes, err := signModeHandler.GetSignBytes(context.Background(), signer, txData) + if err != nil { + return apitypes.TypedData{}, errorsmod.Wrap(err, "failed to get sign bytes using aminojson") + } typedData, err := LegacyWrapTxToTypedData( protoCodec, diff --git a/ethereum/eip712/preprocess_test.go b/ethereum/eip712/preprocess_test.go index d379e5d9..6cb298ec 100644 --- a/ethereum/eip712/preprocess_test.go +++ b/ethereum/eip712/preprocess_test.go @@ -29,7 +29,7 @@ import ( // Testing Constants var ( // chainID is used in EIP-712 tests. - chainID = uint64(constants.ExampleEIP155ChainID) + chainID = uint64(constants.EighteenDecimalsChainID) ctx = client.Context{}.WithTxConfig( encoding.MakeConfig(chainID).TxConfig, diff --git a/ethereum/eip712/types.go b/ethereum/eip712/types.go index ad6db98f..c1fa251b 100644 --- a/ethereum/eip712/types.go +++ b/ethereum/eip712/types.go @@ -10,9 +10,13 @@ import ( "github.com/tidwall/gjson" "golang.org/x/text/cases" "golang.org/x/text/language" + "google.golang.org/protobuf/types/known/anypb" + basev1beta1 "cosmossdk.io/api/cosmos/base/v1beta1" errorsmod "cosmossdk.io/errors" + "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" errortypes "github.com/cosmos/cosmos-sdk/types/errors" ) @@ -387,3 +391,25 @@ func doRecover(err *error) { *err = fmt.Errorf("%v", r) } } + +// ToAnyMsgs helps to convert sdk.Msg slice to []*anypb.Any +func ToAnyMsgs(msgs []sdk.Msg) ([]*anypb.Any, error) { + anyMsgs := make([]*anypb.Any, len(msgs)) + for i, msg := range msgs { + anyMsg, err := types.NewAnyWithValue(msg) + if err != nil { + return nil, errorsmod.Wrap(err, "failed to convert sdk.Msg to Any") + } + anyMsgs[i] = &anypb.Any{TypeUrl: anyMsg.TypeUrl, Value: anyMsg.Value} + } + return anyMsgs, nil +} + +// ToFeeAmount helps to convert sdk.Coins to []*basev1beta1.Coin +func ToFeeAmount(coins sdk.Coins) []*basev1beta1.Coin { + feeAmount := make([]*basev1beta1.Coin, len(coins)) + for i, coin := range coins { + feeAmount[i] = &basev1beta1.Coin{Denom: coin.Denom, Amount: coin.Amount.String()} + } + return feeAmount +} diff --git a/ethereum/eip712/types_test.go b/ethereum/eip712/types_test.go new file mode 100644 index 00000000..3b411c85 --- /dev/null +++ b/ethereum/eip712/types_test.go @@ -0,0 +1,96 @@ +package eip712 + +import ( + "testing" + + "github.com/stretchr/testify/require" + + basev1beta1 "cosmossdk.io/api/cosmos/base/v1beta1" + "cosmossdk.io/math" + + "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +func TestToAnyMsgs(t *testing.T) { + msg := &banktypes.MsgSend{ + FromAddress: "cosmos1x8fhpj9nmhqk8z9kpgjt95ck2xwyue0ptzkucp", + ToAddress: "cosmos1dx67l23hz9l0k9hcher8xz04uj7wf3yu26l2yn", + Amount: sdk.Coins{sdk.Coin{Amount: math.NewInt(10), Denom: "atest"}}, + } + expectedAny, err := types.NewAnyWithValue(msg) + require.NoError(t, err) + testCases := []struct { + name string + msgs []sdk.Msg + wantLen int + wantError bool + }{ + { + name: "single valid message", + msgs: []sdk.Msg{msg}, + wantLen: 1, + wantError: false, + }, + { + name: "empty slice", + msgs: []sdk.Msg{}, + wantLen: 0, + wantError: false, + }, + { + name: "invalid message (nil)", + msgs: []sdk.Msg{nil}, + wantLen: 0, + wantError: true, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + anyMsgs, err := ToAnyMsgs(tc.msgs) + if tc.wantError { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Len(t, anyMsgs, tc.wantLen) + if tc.wantLen == 1 { + require.Equal(t, expectedAny.TypeUrl, anyMsgs[0].TypeUrl) + require.Equal(t, expectedAny.Value, anyMsgs[0].Value) + } + } + }) + } +} + +func TestToFeeAmount(t *testing.T) { + const denom1 = "atest1" + const denom2 = "atest2" + testCases := []struct { + name string + coins sdk.Coins + expected []*basev1beta1.Coin + }{ + { + name: "single coin", + coins: sdk.NewCoins(sdk.NewInt64Coin(denom1, 100)), + expected: []*basev1beta1.Coin{{Denom: denom1, Amount: "100"}}, + }, + { + name: "multiple coins", + coins: sdk.NewCoins(sdk.NewInt64Coin(denom1, 100), sdk.NewInt64Coin(denom2, 50)), + expected: []*basev1beta1.Coin{{Denom: denom1, Amount: "100"}, {Denom: denom2, Amount: "50"}}, + }, + { + name: "empty coins", + coins: sdk.NewCoins(), + expected: []*basev1beta1.Coin{}, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + result := ToFeeAmount(tc.coins) + require.Equal(t, tc.expected, result) + }) + } +} diff --git a/evmd/app.go b/evmd/app.go index f07b0a47..204345c2 100644 --- a/evmd/app.go +++ b/evmd/app.go @@ -4,28 +4,28 @@ import ( "encoding/json" "errors" "fmt" - - "io" - "os" + goruntime "runtime" + "github.com/ethereum/go-ethereum/common" "github.com/spf13/cast" // Force-load the tracer engines to trigger registration due to Go-Ethereum v1.10.15 changes - "github.com/ethereum/go-ethereum/common" _ "github.com/ethereum/go-ethereum/eth/tracers/js" _ "github.com/ethereum/go-ethereum/eth/tracers/native" abci "github.com/cometbft/cometbft/abci/types" + cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" dbm "github.com/cosmos/cosmos-db" evmante "github.com/cosmos/evm/ante" antetypes "github.com/cosmos/evm/ante/types" - evmconfig "github.com/cosmos/evm/config" evmencoding "github.com/cosmos/evm/encoding" evmaddress "github.com/cosmos/evm/encoding/address" + evmconfig "github.com/cosmos/evm/evmd/config" evmmempool "github.com/cosmos/evm/mempool" precompiletypes "github.com/cosmos/evm/precompiles/types" + cosmosevmserver "github.com/cosmos/evm/server" srvflags "github.com/cosmos/evm/server/flags" "github.com/cosmos/evm/utils" "github.com/cosmos/evm/x/erc20" @@ -36,45 +36,32 @@ import ( feemarketkeeper "github.com/cosmos/evm/x/feemarket/keeper" feemarkettypes "github.com/cosmos/evm/x/feemarket/types" ibccallbackskeeper "github.com/cosmos/evm/x/ibc/callbacks/keeper" - - "github.com/cosmos/evm/x/ibc/transfer" - transferkeeper "github.com/cosmos/evm/x/ibc/transfer/keeper" - transferv2 "github.com/cosmos/evm/x/ibc/transfer/v2" - "github.com/cosmos/evm/x/precisebank" - precisebankkeeper "github.com/cosmos/evm/x/precisebank/keeper" - precisebanktypes "github.com/cosmos/evm/x/precisebank/types" "github.com/cosmos/evm/x/vm" evmkeeper "github.com/cosmos/evm/x/vm/keeper" + vmrunner "github.com/cosmos/evm/x/vm/runner" evmtypes "github.com/cosmos/evm/x/vm/types" "github.com/cosmos/gogoproto/proto" - ibccallbacks "github.com/cosmos/ibc-go/v10/modules/apps/callbacks" - 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" - 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" - ibckeeper "github.com/cosmos/ibc-go/v10/modules/core/keeper" - ibctm "github.com/cosmos/ibc-go/v10/modules/light-clients/07-tendermint" - ibctesting "github.com/cosmos/ibc-go/v10/testing" + ibccallbacks "github.com/cosmos/ibc-go/v11/modules/apps/callbacks" + transfer "github.com/cosmos/ibc-go/v11/modules/apps/transfer" + transferkeeper "github.com/cosmos/ibc-go/v11/modules/apps/transfer/keeper" + ibctransfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + transferv2 "github.com/cosmos/ibc-go/v11/modules/apps/transfer/v2" + ibc "github.com/cosmos/ibc-go/v11/modules/core" + porttypes "github.com/cosmos/ibc-go/v11/modules/core/05-port/types" + ibcapi "github.com/cosmos/ibc-go/v11/modules/core/api" + ibcexported "github.com/cosmos/ibc-go/v11/modules/core/exported" + ibckeeper "github.com/cosmos/ibc-go/v11/modules/core/keeper" + ibctm "github.com/cosmos/ibc-go/v11/modules/light-clients/07-tendermint" + ibctesting "github.com/cosmos/ibc-go/v11/testing" autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" reflectionv1 "cosmossdk.io/api/cosmos/reflection/v1" "cosmossdk.io/client/v2/autocli" "cosmossdk.io/core/appmodule" - "cosmossdk.io/log" - storetypes "cosmossdk.io/store/types" - "cosmossdk.io/x/evidence" - evidencekeeper "cosmossdk.io/x/evidence/keeper" - evidencetypes "cosmossdk.io/x/evidence/types" - "cosmossdk.io/x/feegrant" - feegrantkeeper "cosmossdk.io/x/feegrant/keeper" - feegrantmodule "cosmossdk.io/x/feegrant/module" - "cosmossdk.io/x/upgrade" - upgradekeeper "cosmossdk.io/x/upgrade/keeper" - upgradetypes "cosmossdk.io/x/upgrade/types" + "cosmossdk.io/log/v2" "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/baseapp/txnrunner" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/grpc/cmtservice" @@ -87,6 +74,7 @@ import ( "github.com/cosmos/cosmos-sdk/server/api" "github.com/cosmos/cosmos-sdk/server/config" servertypes "github.com/cosmos/cosmos-sdk/server/types" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" testdata_pulsar "github.com/cosmos/cosmos-sdk/testutil/testdata/testpb" sdk "github.com/cosmos/cosmos-sdk/types" sdkmempool "github.com/cosmos/cosmos-sdk/types/mempool" @@ -115,6 +103,12 @@ import ( distr "github.com/cosmos/cosmos-sdk/x/distribution" distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" + "github.com/cosmos/cosmos-sdk/x/evidence" + evidencekeeper "github.com/cosmos/cosmos-sdk/x/evidence/keeper" + evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types" + "github.com/cosmos/cosmos-sdk/x/feegrant" + feegrantkeeper "github.com/cosmos/cosmos-sdk/x/feegrant/keeper" + feegrantmodule "github.com/cosmos/cosmos-sdk/x/feegrant/module" "github.com/cosmos/cosmos-sdk/x/genutil" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" "github.com/cosmos/cosmos-sdk/x/gov" @@ -129,7 +123,9 @@ import ( "github.com/cosmos/cosmos-sdk/x/staking" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - cosmosevmserver "github.com/cosmos/evm/server" + "github.com/cosmos/cosmos-sdk/x/upgrade" + upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" ) func init() { @@ -158,14 +154,12 @@ type EVMD struct { appCodec codec.Codec interfaceRegistry types.InterfaceRegistry txConfig client.TxConfig - clientCtx client.Context pendingTxListeners []evmante.PendingTxListener // keys to access the substores - keys map[string]*storetypes.KVStoreKey - tkeys map[string]*storetypes.TransientStoreKey - memKeys map[string]*storetypes.MemoryStoreKey + keys map[string]*storetypes.KVStoreKey + oKeys map[string]*storetypes.ObjectStoreKey // keepers AccountKeeper authkeeper.AccountKeeper @@ -183,15 +177,14 @@ type EVMD struct { // IBC keepers IBCKeeper *ibckeeper.Keeper // IBC Keeper must be a pointer in the app, so we can SetRouter on it correctly - TransferKeeper transferkeeper.Keeper + TransferKeeper *transferkeeper.Keeper CallbackKeeper ibccallbackskeeper.ContractKeeper // Cosmos EVM keepers - FeeMarketKeeper feemarketkeeper.Keeper - EVMKeeper *evmkeeper.Keeper - Erc20Keeper erc20keeper.Keeper - PreciseBankKeeper precisebankkeeper.Keeper - EVMMempool *evmmempool.ExperimentalEVMMempool + FeeMarketKeeper feemarketkeeper.Keeper + EVMKeeper *evmkeeper.Keeper + Erc20Keeper erc20keeper.Keeper + EVMMempool sdkmempool.ExtMempool // the module manager ModuleManager *module.Manager @@ -208,7 +201,6 @@ type EVMD struct { func NewExampleApp( logger log.Logger, db dbm.DB, - traceStore io.Writer, loadLatest bool, appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp), @@ -220,16 +212,22 @@ func NewExampleApp( legacyAmino := encodingConfig.Amino interfaceRegistry := encodingConfig.InterfaceRegistry txConfig := encodingConfig.TxConfig + txDecoder := encodingConfig.TxConfig.TxDecoder() + + // enable optimistic execution + baseAppOptions = append( + baseAppOptions, + baseapp.SetOptimisticExecution(), + ) bApp := baseapp.NewBaseApp( appName, logger, db, // use transaction decoder to support the sdk.Tx interface instead of sdk.StdTx - encodingConfig.TxConfig.TxDecoder(), + txDecoder, baseAppOptions..., ) - bApp.SetCommitMultiStoreTracer(traceStore) bApp.SetVersion(version.Version) bApp.SetInterfaceRegistry(interfaceRegistry) bApp.SetTxEncoder(txConfig.TxEncoder()) @@ -242,10 +240,20 @@ func NewExampleApp( // ibc keys ibcexported.StoreKey, ibctransfertypes.StoreKey, // Cosmos EVM store keys - evmtypes.StoreKey, feemarkettypes.StoreKey, erc20types.StoreKey, precisebanktypes.StoreKey, + evmtypes.StoreKey, feemarkettypes.StoreKey, erc20types.StoreKey, ) + oKeys := storetypes.NewObjectStoreKeys(banktypes.ObjectStoreKey, evmtypes.ObjectKey) + + var nonTransientKeys []storetypes.StoreKey + for _, k := range keys { + nonTransientKeys = append(nonTransientKeys, k) + } + for _, k := range oKeys { + nonTransientKeys = append(nonTransientKeys, k) + } - tkeys := storetypes.NewTransientStoreKeys(evmtypes.TransientKey, feemarkettypes.TransientKey) + // disable block gas meter + bApp.SetDisableBlockGasMeter(true) // load state streaming if enabled if err := bApp.RegisterStreamingServices(appOpts, keys); err != nil { @@ -265,7 +273,7 @@ func NewExampleApp( txConfig: txConfig, interfaceRegistry: interfaceRegistry, keys: keys, - tkeys: tkeys, + oKeys: oKeys, } // removed x/params: no ParamsKeeper initialization @@ -299,6 +307,7 @@ func NewExampleApp( authAddr, logger, ) + app.BankKeeper = app.BankKeeper.WithObjStoreKey(oKeys[banktypes.ObjectStoreKey]) // optional: enable sign mode textual by overwriting the default tx config (after setting the bank keeper) enabledSignModes := append(authtx.DefaultSignModes, signingtypes.SignMode_SIGN_MODE_TEXTUAL) //nolint:gocritic @@ -388,7 +397,6 @@ func NewExampleApp( app.IBCKeeper = ibckeeper.NewKeeper( appCodec, runtime.NewKVStoreService(keys[ibcexported.StoreKey]), - nil, app.UpgradeKeeper, authAddr, ) @@ -399,13 +407,20 @@ func NewExampleApp( govConfig.MaxMetadataLen = 10000 */ govKeeper := govkeeper.NewKeeper( - appCodec, runtime.NewKVStoreService(keys[govtypes.StoreKey]), app.AccountKeeper, app.BankKeeper, - app.StakingKeeper, app.DistrKeeper, app.MsgServiceRouter(), govConfig, authAddr, + appCodec, + runtime.NewKVStoreService(keys[govtypes.StoreKey]), + app.AccountKeeper, + app.BankKeeper, + app.DistrKeeper, + app.MsgServiceRouter(), + govConfig, + authAddr, + govkeeper.NewDefaultCalculateVoteResultsAndVotingPower(app.StakingKeeper), ) app.GovKeeper = *govKeeper.SetHooks( govtypes.NewMultiGovHooks( - // register the governance hooks + // register the governance hooks ), ) @@ -425,17 +440,18 @@ func NewExampleApp( app.FeeMarketKeeper = feemarketkeeper.NewKeeper( appCodec, authtypes.NewModuleAddress(govtypes.ModuleName), keys[feemarkettypes.StoreKey], - tkeys[feemarkettypes.TransientKey], ) - // Set up PreciseBank keeper - // - // NOTE: PreciseBank is not needed if SDK use 18 decimals for gas coin. Use BankKeeper instead. - app.PreciseBankKeeper = precisebankkeeper.NewKeeper( + // instantiate IBC transfer keeper before the EVM keeper so precompiles receive a non-nil reference + app.TransferKeeper = transferkeeper.NewKeeper( appCodec, - keys[precisebanktypes.StoreKey], - app.BankKeeper, + evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()), + runtime.NewKVStoreService(keys[ibctransfertypes.StoreKey]), + app.IBCKeeper.ChannelKeeper, + app.MsgServiceRouter(), app.AccountKeeper, + app.BankKeeper, + authAddr, ) // Set up EVM keeper @@ -444,10 +460,10 @@ func NewExampleApp( // NOTE: it's required to set up the EVM keeper before the ERC-20 keeper, because it is used in its instantiation. app.EVMKeeper = evmkeeper.NewKeeper( // TODO: check why this is not adjusted to use the runtime module methods like SDK native keepers - appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey], keys, + appCodec, keys[evmtypes.StoreKey], oKeys[evmtypes.ObjectKey], nonTransientKeys, authtypes.NewModuleAddress(govtypes.ModuleName), app.AccountKeeper, - app.PreciseBankKeeper, + app.BankKeeper, app.StakingKeeper, app.FeeMarketKeeper, &app.ConsensusParamsKeeper, @@ -458,40 +474,30 @@ func NewExampleApp( precompiletypes.DefaultStaticPrecompiles( *app.StakingKeeper, app.DistrKeeper, - app.PreciseBankKeeper, + app.BankKeeper, &app.Erc20Keeper, - &app.TransferKeeper, + app.TransferKeeper, app.IBCKeeper.ChannelKeeper, + app.IBCKeeper.ClientKeeper, app.GovKeeper, app.SlashingKeeper, appCodec, ), ) + // enable virtual fee collection + app.EVMKeeper.EnableVirtualFeeCollection() + app.Erc20Keeper = erc20keeper.NewKeeper( keys[erc20types.StoreKey], appCodec, authtypes.NewModuleAddress(govtypes.ModuleName), app.AccountKeeper, - app.PreciseBankKeeper, + app.BankKeeper, app.EVMKeeper, app.StakingKeeper, - &app.TransferKeeper, - ) - - // instantiate IBC transfer keeper AFTER the ERC-20 keeper to use it in the instantiation - app.TransferKeeper = transferkeeper.NewKeeper( - appCodec, - runtime.NewKVStoreService(keys[ibctransfertypes.StoreKey]), - app.IBCKeeper.ChannelKeeper, - app.IBCKeeper.ChannelKeeper, - app.MsgServiceRouter(), - app.AccountKeeper, - app.BankKeeper, - app.Erc20Keeper, // Add ERC20 Keeper for ERC20 transfers - authAddr, + app.TransferKeeper, ) - app.TransferKeeper.SetAddressCodec(evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix())) /* Create Transfer Stack @@ -519,7 +525,10 @@ func NewExampleApp( app.EVMKeeper, app.Erc20Keeper, ) - transferStack = ibccallbacks.NewIBCMiddleware(transferStack, app.IBCKeeper.ChannelKeeper, app.CallbackKeeper, maxCallbackGas) + callbacksMiddleware := ibccallbacks.NewIBCMiddleware(app.CallbackKeeper, maxCallbackGas) + callbacksMiddleware.SetICS4Wrapper(app.IBCKeeper.ChannelKeeper) + callbacksMiddleware.SetUnderlyingApplication(transferStack) + transferStack = callbacksMiddleware var transferStackV2 ibcapi.IBCModule transferStackV2 = transferv2.NewIBCModule(app.TransferKeeper) @@ -542,6 +551,8 @@ func NewExampleApp( // Override the ICS20 app module transferModule := transfer.NewAppModule(app.TransferKeeper) + vmModule := vm.NewAppModule(app.EVMKeeper, app.AccountKeeper, app.BankKeeper, app.AccountKeeper.AddressCodec()) + /**** Module Options ****/ // NOTE: Any module instantiated in the module manager that is later modified @@ -569,10 +580,9 @@ func NewExampleApp( ibctm.NewAppModule(tmLightClientModule), transferModule, // Cosmos EVM modules - vm.NewAppModule(app.EVMKeeper, app.AccountKeeper, app.BankKeeper, app.AccountKeeper.AddressCodec()), + vmModule, feemarket.NewAppModule(app.FeeMarketKeeper), erc20.NewAppModule(app.Erc20Keeper, app.AccountKeeper), - precisebank.NewAppModule(app.PreciseBankKeeper, app.BankKeeper, app.AccountKeeper), ) // BasicModuleManager defines the module BasicManager which is in charge of setting up basic, @@ -585,7 +595,7 @@ func NewExampleApp( genutiltypes.ModuleName: genutil.NewAppModuleBasic(genutiltypes.DefaultMessageValidator), stakingtypes.ModuleName: staking.AppModuleBasic{}, govtypes.ModuleName: gov.NewAppModuleBasic(nil), - ibctransfertypes.ModuleName: transfer.AppModuleBasic{AppModuleBasic: &ibctransfer.AppModuleBasic{}}, + ibctransfertypes.ModuleName: transfer.AppModuleBasic{}, }, ) app.BasicModuleManager.RegisterLegacyAminoCodec(legacyAmino) @@ -620,15 +630,16 @@ func NewExampleApp( authtypes.ModuleName, banktypes.ModuleName, govtypes.ModuleName, genutiltypes.ModuleName, authz.ModuleName, feegrant.ModuleName, consensusparamtypes.ModuleName, - precisebanktypes.ModuleName, vestingtypes.ModuleName, ) // NOTE: the feemarket module should go last in order of end blockers that are actually doing something, // to get the full block gas used. app.ModuleManager.SetOrderEndBlockers( - govtypes.ModuleName, stakingtypes.ModuleName, - authtypes.ModuleName, banktypes.ModuleName, + banktypes.ModuleName, + govtypes.ModuleName, + stakingtypes.ModuleName, + authtypes.ModuleName, // Cosmos EVM EndBlockers evmtypes.ModuleName, erc20types.ModuleName, feemarkettypes.ModuleName, @@ -639,7 +650,6 @@ func NewExampleApp( slashingtypes.ModuleName, minttypes.ModuleName, genutiltypes.ModuleName, evidencetypes.ModuleName, authz.ModuleName, feegrant.ModuleName, upgradetypes.ModuleName, consensusparamtypes.ModuleName, - precisebanktypes.ModuleName, vestingtypes.ModuleName, ) @@ -659,7 +669,6 @@ func NewExampleApp( evmtypes.ModuleName, feemarkettypes.ModuleName, erc20types.ModuleName, - precisebanktypes.ModuleName, ibctransfertypes.ModuleName, genutiltypes.ModuleName, evidencetypes.ModuleName, authz.ModuleName, @@ -704,7 +713,7 @@ func NewExampleApp( // initialize stores app.MountKVStores(keys) - app.MountTransientStores(tkeys) + app.MountObjectStores(oKeys) maxGasWanted := cast.ToUint64(appOpts.Get(srvflags.EVMMaxTxGasWanted)) @@ -760,8 +769,26 @@ func NewExampleApp( logger.Error("error on loading last version", "err", err) os.Exit(1) } + + ctx := app.NewContextLegacy(true, cmtproto.Header{ + Height: app.LastBlockHeight(), + ChainID: app.ChainID(), + }) + + // set global evm variables from KV store + vmModule.HydrateGlobals(ctx) } + vmrunner.SetRunner(bApp, txnrunner.NewSTMRunner( + txDecoder, + nonTransientKeys, + min(goruntime.GOMAXPROCS(0), goruntime.NumCPU()), + true, + func(ms storetypes.MultiStore) string { + return app.EVMKeeper.GetParams(sdk.NewContext(ms, cmtproto.Header{}, false, log.NewNopLogger())).EvmDenom + }, + )) + return app } @@ -905,20 +932,6 @@ func (app *EVMD) GetKey(storeKey string) *storetypes.KVStoreKey { return app.keys[storeKey] } -// GetTKey returns the TransientStoreKey for the provided store key. -// -// NOTE: This is solely to be used for testing purposes. -func (app *EVMD) GetTKey(storeKey string) *storetypes.TransientStoreKey { - return app.tkeys[storeKey] -} - -// GetMemKey returns the MemStoreKey for the provided mem key. -// -// NOTE: This is solely used for testing purposes. -func (app *EVMD) GetMemKey(storeKey string) *storetypes.MemoryStoreKey { - return app.memKeys[storeKey] -} - // SimulationManager implements the SimulationApp interface func (app *EVMD) SimulationManager() *module.SimulationManager { return app.sm @@ -962,7 +975,9 @@ func (app *EVMD) RegisterTendermintService(clientCtx client.Context) { } func (app *EVMD) RegisterNodeService(clientCtx client.Context, cfg config.Config) { - node.RegisterNodeService(clientCtx, app.GRPCQueryRouter(), cfg) + node.RegisterNodeService(clientCtx, app.GRPCQueryRouter(), cfg, func() int64 { + return app.CommitMultiStore().EarliestVersion() + }) } // --------------------------------------------- @@ -1028,10 +1043,6 @@ func (app *EVMD) GetAccountKeeper() authkeeper.AccountKeeper { return app.AccountKeeper } -func (app *EVMD) GetAuthzKeeper() authzkeeper.Keeper { - return app.AuthzKeeper -} - func (app *EVMD) GetDistrKeeper() distrkeeper.Keeper { return app.DistrKeeper } @@ -1044,19 +1055,15 @@ func (app *EVMD) GetMintKeeper() mintkeeper.Keeper { return app.MintKeeper } -func (app *EVMD) GetPreciseBankKeeper() *precisebankkeeper.Keeper { - return &app.PreciseBankKeeper -} - func (app *EVMD) GetCallbackKeeper() ibccallbackskeeper.ContractKeeper { return app.CallbackKeeper } -func (app *EVMD) GetTransferKeeper() transferkeeper.Keeper { +func (app *EVMD) GetTransferKeeper() *transferkeeper.Keeper { return app.TransferKeeper } -func (app *EVMD) SetTransferKeeper(transferKeeper transferkeeper.Keeper) { +func (app *EVMD) SetTransferKeeper(transferKeeper *transferkeeper.Keeper) { app.TransferKeeper = transferKeeper } @@ -1065,7 +1072,7 @@ func (app *EVMD) GetMempool() sdkmempool.ExtMempool { } func (app *EVMD) GetAnteHandler() sdk.AnteHandler { - return app.BaseApp.AnteHandler() + return app.AnteHandler() } // GetTxConfig implements the TestingApp interface. @@ -1073,14 +1080,10 @@ func (app *EVMD) GetTxConfig() client.TxConfig { return app.txConfig } -func (app *EVMD) SetClientCtx(clientCtx client.Context) { // TODO:VLAD - Remove this if possible - 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 { + if m, ok := app.EVMMempool.(*evmmempool.Mempool); ok && m != nil { app.Logger().Info("Shutting down mempool") err = m.Close() } diff --git a/evmd/cmd/evmd/cmd/creator.go b/evmd/cmd/evmd/cmd/creator.go index 8ba418dc..c723ad21 100644 --- a/evmd/cmd/evmd/cmd/creator.go +++ b/evmd/cmd/evmd/cmd/creator.go @@ -5,22 +5,24 @@ import ( "io" "path/filepath" + "github.com/spf13/cast" + "github.com/spf13/viper" + dbm "github.com/cosmos/cosmos-db" + "github.com/cosmos/evm/evmd" + + "cosmossdk.io/log/v2" + "github.com/cosmos/cosmos-sdk/store/v2" + "github.com/cosmos/cosmos-sdk/store/v2/snapshots" + snapshottypes "github.com/cosmos/cosmos-sdk/store/v2/snapshots/types" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" + "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/server" servertypes "github.com/cosmos/cosmos-sdk/server/types" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" - "github.com/cosmos/evm/evmd" - "github.com/spf13/cast" - "github.com/spf13/viper" - - "cosmossdk.io/log" - "cosmossdk.io/store" - "cosmossdk.io/store/snapshots" - snapshottypes "cosmossdk.io/store/snapshots/types" - storetypes "cosmossdk.io/store/types" ) type appCreator struct{} @@ -90,7 +92,6 @@ func (a appCreator) newApp( return evmd.NewExampleApp( logger, db, - traceStore, true, simtestutil.EmptyAppOptions{}, baseappOptions..., @@ -131,7 +132,6 @@ func (a appCreator) appExport( evmApp = evmd.NewExampleApp( logger, db, - traceStore, loadLatest, appOpts, ) diff --git a/evmd/cmd/evmd/cmd/root.go b/evmd/cmd/evmd/cmd/root.go index f535093b..4da3349d 100644 --- a/evmd/cmd/evmd/cmd/root.go +++ b/evmd/cmd/evmd/cmd/root.go @@ -2,11 +2,8 @@ package cmd import ( "errors" - "github.com/cosmos/evm/x/vm/types" - "io" "os" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/spf13/cast" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -17,17 +14,19 @@ import ( dbm "github.com/cosmos/cosmos-db" cosmosevmcmd "github.com/cosmos/evm/client" evmdebug "github.com/cosmos/evm/client/debug" - "github.com/cosmos/evm/config" - cosmosevmkeyring "github.com/cosmos/evm/crypto/keyring" + "github.com/cosmos/evm/crypto/hd" "github.com/cosmos/evm/evmd" + "github.com/cosmos/evm/evmd/config" cosmosevmserver "github.com/cosmos/evm/server" srvflags "github.com/cosmos/evm/server/flags" + "github.com/cosmos/evm/utils" + "github.com/cosmos/evm/x/vm/types" - "cosmossdk.io/log" - "cosmossdk.io/store" - snapshottypes "cosmossdk.io/store/snapshots/types" - storetypes "cosmossdk.io/store/types" + "cosmossdk.io/log/v2" confixcmd "cosmossdk.io/tools/confix/cmd" + "github.com/cosmos/cosmos-sdk/store/v2" + snapshottypes "github.com/cosmos/cosmos-sdk/store/v2/snapshots/types" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/client" @@ -46,6 +45,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth/tx" txmodule "github.com/cosmos/cosmos-sdk/x/auth/tx/config" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli" ) @@ -58,7 +58,6 @@ func NewRootCmd() *cobra.Command { tempApp := evmd.NewExampleApp( log.NewNopLogger(), dbm.NewMemDB(), - nil, true, simtestutil.EmptyAppOptions{}, ) @@ -80,7 +79,7 @@ func NewRootCmd() *cobra.Command { WithHomeDir(config.MustGetDefaultNodeHome()). WithViper(""). // In simapp, we don't use any prefix for env variables. // Cosmos EVM specific setup - WithKeyringOptions(cosmosevmkeyring.Option()). + WithKeyringOptions(hd.EthSecp256k1Option()). WithLedgerHasProtobuf(true) rootCmd := &cobra.Command{ @@ -126,7 +125,7 @@ func NewRootCmd() *cobra.Command { return err } - customAppTemplate, customAppConfig := config.InitAppConfig(types.DefaultEVMExtendedDenom, config.EVMChainID) // TODO:VLAD - Remove this + customAppTemplate, customAppConfig := config.InitAppConfig(types.DefaultEVMExtendedDenom, types.DefaultEVMChainID) // TODO:VLAD - Remove this customTMConfig := initCometConfig() return sdkserver.InterceptConfigsPreRunHandler(cmd, customAppTemplate, customAppConfig, customTMConfig) @@ -163,8 +162,8 @@ func initRootCmd(rootCmd *cobra.Command, evmApp *evmd.EVMD) { cfg.Seal() defaultNodeHome := config.MustGetDefaultNodeHome() - sdkAppCreator := func(l log.Logger, d dbm.DB, w io.Writer, ao servertypes.AppOptions) servertypes.Application { - return newApp(l, d, w, ao) + sdkAppCreator := func(l log.Logger, d dbm.DB, ao servertypes.AppOptions) servertypes.Application { + return newApp(l, d, ao) } rootCmd.AddCommand( genutilcli.InitCmd(evmApp.BasicModuleManager, defaultNodeHome), @@ -261,7 +260,6 @@ func txCommand() *cobra.Command { func newApp( logger log.Logger, db dbm.DB, - traceStore io.Writer, appOpts servertypes.AppOptions, ) cosmosevmserver.Application { var cache storetypes.MultiStorePersistentCache @@ -308,7 +306,7 @@ func newApp( } return evmd.NewExampleApp( - logger, db, traceStore, true, + logger, db, true, appOpts, baseappOptions..., ) @@ -318,7 +316,6 @@ func newApp( func appExport( logger log.Logger, db dbm.DB, - traceStore io.Writer, height int64, forZeroHeight bool, jailAllowedAddrs []string, @@ -350,13 +347,13 @@ func appExport( } if height != -1 { - exampleApp = evmd.NewExampleApp(logger, db, traceStore, false, appOpts, baseapp.SetChainID(chainID)) + exampleApp = evmd.NewExampleApp(logger, db, false, appOpts, baseapp.SetChainID(chainID)) if err := exampleApp.LoadHeight(height); err != nil { return servertypes.ExportedApp{}, err } } else { - exampleApp = evmd.NewExampleApp(logger, db, traceStore, true, appOpts, baseapp.SetChainID(chainID)) // TODO:VLAD - Remove // TODO:VLAD - Remove appoptions and evmchainid + exampleApp = evmd.NewExampleApp(logger, db, true, appOpts, baseapp.SetChainID(chainID)) // TODO:VLAD - Remove // TODO:VLAD - Remove appoptions and evmchainid } return exampleApp.ExportAppStateAndValidators(forZeroHeight, jailAllowedAddrs, modulesToExport) @@ -371,11 +368,11 @@ func getChainIDFromOpts(appOpts servertypes.AppOptions) (chainID string, err err if chainID == "" { // If not available load from home homeDir := cast.ToString(appOpts.Get(flags.FlagHome)) - chainID, err = config.GetChainIDFromHome(homeDir) + chainID, err = utils.GetChainIDFromHome(homeDir) if err != nil { return "", err } } - return + return chainID, err } diff --git a/evmd/cmd/evmd/cmd/testnet.go b/evmd/cmd/evmd/cmd/testnet.go index 11b35c34..d8c04f94 100644 --- a/evmd/cmd/evmd/cmd/testnet.go +++ b/evmd/cmd/evmd/cmd/testnet.go @@ -9,12 +9,6 @@ import ( "path/filepath" "time" - "github.com/cosmos/evm/config" - - cosmosevmhd "github.com/cosmos/evm/crypto/hd" - cosmosevmkeyring "github.com/cosmos/evm/crypto/keyring" - "github.com/cosmos/evm/evmd" - cosmosevmserverconfig "github.com/cosmos/evm/server/config" "github.com/spf13/cobra" "github.com/spf13/pflag" @@ -23,8 +17,16 @@ import ( tmtime "github.com/cometbft/cometbft/types/time" dbm "github.com/cosmos/cosmos-db" + cosmosevmhd "github.com/cosmos/evm/crypto/hd" + cosmosevmkeyring "github.com/cosmos/evm/crypto/keyring" + "github.com/cosmos/evm/evmd" + "github.com/cosmos/evm/evmd/config" + customnetwork "github.com/cosmos/evm/evmd/tests/network" + cosmosevmserverconfig "github.com/cosmos/evm/server/config" + evmnetwork "github.com/cosmos/evm/testutil/integration/evm/network" + evmtypes "github.com/cosmos/evm/x/vm/types" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" "cosmossdk.io/math" "github.com/cosmos/cosmos-sdk/client" @@ -47,10 +49,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/genutil" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - - customnetwork "github.com/cosmos/evm/evmd/tests/network" - evmnetwork "github.com/cosmos/evm/testutil/integration/evm/network" - evmtypes "github.com/cosmos/evm/x/vm/types" ) var ( @@ -324,7 +322,7 @@ func initTestnetFiles( appConfig.Telemetry.EnableHostnameLabel = false appConfig.Telemetry.GlobalLabels = [][]string{{"chain_id", args.chainID}} evm := cosmosevmserverconfig.DefaultEVMConfig() - evm.EVMChainID = config.EVMChainID + evm.EVMChainID = evmtypes.DefaultEVMChainID evmCfg := config.EVMAppConfig{ Config: *appConfig, EVM: *evm, @@ -572,7 +570,7 @@ func initGenFiles( var bankGenState banktypes.GenesisState clientCtx.Codec.MustUnmarshalJSON(appGenState[banktypes.ModuleName], &bankGenState) - bankGenState.DenomMetadata = append(bankGenState.DenomMetadata, evmnetwork.GenerateBankGenesisMetadata(config.EVMChainID)...) + bankGenState.DenomMetadata = append(bankGenState.DenomMetadata, evmnetwork.GenerateBankGenesisMetadata(evmtypes.DefaultEVMChainID)...) bankGenState.Balances = banktypes.SanitizeGenesisBalances(genBalances) for _, bal := range bankGenState.Balances { @@ -759,7 +757,6 @@ func NewTestNetworkFixture() sdknetwork.TestFixture { app := evmd.NewExampleApp( log.NewNopLogger(), dbm.NewMemDB(), - nil, true, simtestutil.EmptyAppOptions{}, ) @@ -768,7 +765,6 @@ func NewTestNetworkFixture() sdknetwork.TestFixture { return evmd.NewExampleApp( log.NewNopLogger(), dbm.NewMemDB(), - nil, true, simtestutil.EmptyAppOptions{}, ) diff --git a/evmd/cmd/evmd/main.go b/evmd/cmd/evmd/main.go index 1ede2c86..2a5d62fa 100644 --- a/evmd/cmd/evmd/main.go +++ b/evmd/cmd/evmd/main.go @@ -6,8 +6,8 @@ import ( svrcmd "github.com/cosmos/cosmos-sdk/server/cmd" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/evm/config" "github.com/cosmos/evm/evmd/cmd/evmd/cmd" + "github.com/cosmos/evm/evmd/config" ) func main() { diff --git a/config/config.go b/evmd/config/bech32.go similarity index 50% rename from config/config.go rename to evmd/config/bech32.go index 6c09e056..3c2cd384 100644 --- a/config/config.go +++ b/evmd/config/bech32.go @@ -1,62 +1,10 @@ package config import ( - "github.com/cosmos/evm/crypto/hd" - evmtypes "github.com/cosmos/evm/x/vm/types" - sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/evm/crypto/hd" ) -// ChainsCoinInfo is a map of the chain id and its corresponding EvmCoinInfo -// that allows initializing the app with different coin info based on the -// chain id -var ChainsCoinInfo = map[uint64]evmtypes.EvmCoinInfo{ // TODO:VLAD - Remove this - EighteenDecimalsChainID: { - Denom: ExampleChainDenom, - ExtendedDenom: ExampleChainDenom, - DisplayDenom: ExampleDisplayDenom, - Decimals: evmtypes.EighteenDecimals.Uint32(), - }, - // SixDecimalsChainID provides a chain ID which is being set up with 6 decimals - SixDecimalsChainID: { - Denom: "utest", - ExtendedDenom: "atest", - DisplayDenom: "test", - Decimals: evmtypes.SixDecimals.Uint32(), - }, - // EVMChainID provides a chain ID used for internal testing - EVMChainID: { - Denom: "atest", - ExtendedDenom: "atest", - DisplayDenom: "test", - Decimals: evmtypes.EighteenDecimals.Uint32(), - }, - TwelveDecimalsChainID: { - Denom: "ptest2", - ExtendedDenom: "atest2", - DisplayDenom: "test2", - Decimals: evmtypes.TwelveDecimals.Uint32(), - }, - TwoDecimalsChainID: { - Denom: "ctest3", - ExtendedDenom: "atest3", - DisplayDenom: "test3", - Decimals: evmtypes.TwoDecimals.Uint32(), - }, - TestChainID1: { - Denom: ExampleChainDenom, - ExtendedDenom: ExampleChainDenom, - DisplayDenom: ExampleChainDenom, - Decimals: evmtypes.EighteenDecimals.Uint32(), - }, - TestChainID2: { - Denom: ExampleChainDenom, - ExtendedDenom: ExampleChainDenom, - DisplayDenom: ExampleChainDenom, - Decimals: evmtypes.EighteenDecimals.Uint32(), - }, -} - const ( // Bech32Prefix defines the Bech32 prefix used for accounts on the exemplary Cosmos EVM blockchain. Bech32Prefix = "cosmos" @@ -72,10 +20,6 @@ const ( Bech32PrefixConsAddr = Bech32Prefix + sdk.PrefixValidator + sdk.PrefixConsensus // Bech32PrefixConsPub defines the Bech32 prefix of a consensus node public key. Bech32PrefixConsPub = Bech32Prefix + sdk.PrefixValidator + sdk.PrefixConsensus + sdk.PrefixPublic - // BaseDenomUnit defines the precision of the base denomination. - BaseDenomUnit = 18 - // EVMChainID defines the EIP-155 replay-protection chain id for the current ethereum chain config. - EVMChainID = 262144 ) // SetBech32Prefixes sets the global prefixes to be used when serializing addresses and public keys to Bech32 strings. diff --git a/evmd/config/config.go b/evmd/config/config.go new file mode 100644 index 00000000..37161612 --- /dev/null +++ b/evmd/config/config.go @@ -0,0 +1,58 @@ +package config + +import ( + clienthelpers "cosmossdk.io/client/v2/helpers" + serverconfig "github.com/cosmos/cosmos-sdk/server/config" + cosmosevmserverconfig "github.com/cosmos/evm/server/config" +) + +func MustGetDefaultNodeHome() string { + defaultNodeHome, err := clienthelpers.GetNodeHomeDirectory(".evmd") + if err != nil { + panic(err) + } + return defaultNodeHome +} + +// InitAppConfig helps to override default appConfig template and configs. +// return "", nil if no custom configuration is required for the application. +func InitAppConfig(denom string, evmChainID uint64) (string, interface{}) { + // Optionally allow the chain developer to overwrite the SDK's default + // server config. + srvCfg := serverconfig.DefaultConfig() + // The SDK's default minimum gas price is set to "" (empty value) inside + // app.toml. If left empty by validators, the node will halt on startup. + // However, the chain developer can set a default app.toml value for their + // validators here. + // + // In summary: + // - if you leave srvCfg.MinGasPrices = "", all validators MUST tweak their + // own app.toml config, + // - if you set srvCfg.MinGasPrices non-empty, validators CAN tweak their + // own app.toml to override, or use this default value. + // + // In this example application, we set the min gas prices to 0. + srvCfg.MinGasPrices = "0" + denom + + evmCfg := cosmosevmserverconfig.DefaultEVMConfig() + evmCfg.EVMChainID = evmChainID + + customAppConfig := EVMAppConfig{ + Config: *srvCfg, + EVM: *evmCfg, + JSONRPC: *cosmosevmserverconfig.DefaultJSONRPCConfig(), + TLS: *cosmosevmserverconfig.DefaultTLSConfig(), + } + + return EVMAppTemplate, customAppConfig +} + +type EVMAppConfig struct { + serverconfig.Config + + EVM cosmosevmserverconfig.EVMConfig + JSONRPC cosmosevmserverconfig.JSONRPCConfig + TLS cosmosevmserverconfig.TLSConfig +} + +const EVMAppTemplate = serverconfig.DefaultConfigTemplate + cosmosevmserverconfig.DefaultEVMConfigTemplate diff --git a/evmd/config/permissions.go b/evmd/config/permissions.go new file mode 100644 index 00000000..312b5219 --- /dev/null +++ b/evmd/config/permissions.go @@ -0,0 +1,71 @@ +package config + +import ( + "maps" + "sort" + + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + 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" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + cosmosevmutils "github.com/cosmos/evm/utils" + erc20types "github.com/cosmos/evm/x/erc20/types" + feemarkettypes "github.com/cosmos/evm/x/feemarket/types" + vmtypes "github.com/cosmos/evm/x/vm/types" + transfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + corevm "github.com/ethereum/go-ethereum/core/vm" +) + +// BlockedAddresses returns all the app's blocked account addresses. +// +// Note, this includes: +// - module accounts +// - Ethereum's native precompiled smart contracts +// - Cosmos EVM' available static precompiled contracts +func BlockedAddresses() map[string]bool { + blockedAddrs := make(map[string]bool) + + maccPerms := GetMaccPerms() + accs := make([]string, 0, len(maccPerms)) + for acc := range maccPerms { + accs = append(accs, acc) + } + sort.Strings(accs) + + for _, acc := range accs { + blockedAddrs[authtypes.NewModuleAddress(acc).String()] = true + } + + blockedPrecompilesHex := vmtypes.AvailableStaticPrecompiles + for _, addr := range corevm.PrecompiledAddressesPrague { + blockedPrecompilesHex = append(blockedPrecompilesHex, addr.Hex()) + } + + for _, precompile := range blockedPrecompilesHex { + blockedAddrs[cosmosevmutils.Bech32StringFromHexAddress(precompile)] = true + } + + return blockedAddrs +} + +// module account permissions +var maccPerms = map[string][]string{ + authtypes.FeeCollectorName: nil, + distrtypes.ModuleName: nil, + transfertypes.ModuleName: {authtypes.Minter, authtypes.Burner}, + minttypes.ModuleName: {authtypes.Minter}, + stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking}, + stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, + govtypes.ModuleName: {authtypes.Burner}, + + // Cosmos EVM modules + vmtypes.ModuleName: {authtypes.Minter, authtypes.Burner}, + feemarkettypes.ModuleName: nil, + erc20types.ModuleName: {authtypes.Minter, authtypes.Burner}, +} + +// GetMaccPerms returns a copy of the module account permissions +func GetMaccPerms() map[string][]string { + return maps.Clone(maccPerms) +} diff --git a/evmd/export.go b/evmd/export.go index 096f5eb2..9fdd8eff 100644 --- a/evmd/export.go +++ b/evmd/export.go @@ -7,9 +7,8 @@ import ( tmproto "github.com/cometbft/cometbft/proto/tendermint/types" - storetypes "cosmossdk.io/store/types" - servertypes "github.com/cosmos/cosmos-sdk/server/types" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" "github.com/cosmos/cosmos-sdk/x/staking" diff --git a/evmd/genesis.go b/evmd/genesis.go index 27f7727c..27cc9837 100644 --- a/evmd/genesis.go +++ b/evmd/genesis.go @@ -2,7 +2,7 @@ package evmd import ( "encoding/json" - "github.com/cosmos/evm/config" + testconstants "github.com/cosmos/evm/testutil/constants" erc20types "github.com/cosmos/evm/x/erc20/types" feemarkettypes "github.com/cosmos/evm/x/feemarket/types" @@ -49,8 +49,8 @@ func NewErc20GenesisState() *erc20types.GenesisState { // NOTE: for the example chain implementation we are also adding a default minter. func NewMintGenesisState() *minttypes.GenesisState { mintGenState := minttypes.DefaultGenesisState() - mintGenState.Params.MintDenom = config.ExampleChainDenom + mintGenState.Params.MintDenom = testconstants.ExampleAttoDenom return mintGenState } diff --git a/evmd/go.mod b/evmd/go.mod index 9a3dfb23..e503386e 100644 --- a/evmd/go.mod +++ b/evmd/go.mod @@ -1,159 +1,181 @@ module github.com/cosmos/evm/evmd -go 1.23.8 +go 1.25.9 require ( - cosmossdk.io/api v0.9.2 - cosmossdk.io/client/v2 v2.0.0-beta.7 - cosmossdk.io/core v0.11.3 - cosmossdk.io/errors v1.0.2 - cosmossdk.io/log v1.6.1 + cosmossdk.io/api v1.0.0 + cosmossdk.io/client/v2 v2.0.0-beta.10.0.20260227212600-39d4711b8970 + cosmossdk.io/core v1.1.0 + cosmossdk.io/errors v1.1.0 + cosmossdk.io/log/v2 v2.1.0 cosmossdk.io/math v1.5.3 - cosmossdk.io/store v1.1.2 cosmossdk.io/tools/confix v0.1.2 - cosmossdk.io/x/evidence v0.2.0 - cosmossdk.io/x/feegrant v0.2.0 - cosmossdk.io/x/upgrade v0.2.0 - github.com/cometbft/cometbft v0.38.18 + github.com/cometbft/cometbft v0.39.3 github.com/cosmos/cosmos-db v1.1.3 - github.com/cosmos/cosmos-sdk v0.53.4 + github.com/cosmos/cosmos-sdk v0.54.3 + github.com/cosmos/cosmos-sdk/store/v2 v2.0.0 github.com/cosmos/evm v0.2.0 - github.com/cosmos/gogoproto v1.7.0 - github.com/cosmos/ibc-go/v10 v10.3.1-0.20250909102629-ed3b125c7b6f - github.com/ethereum/go-ethereum v1.15.11 + github.com/cosmos/gogoproto v1.7.2 + github.com/cosmos/ibc-go/v11 v11.0.0 + github.com/ethereum/go-ethereum v1.16.8 github.com/onsi/ginkgo/v2 v2.23.4 github.com/onsi/gomega v1.38.0 - github.com/spf13/cast v1.9.2 - github.com/spf13/cobra v1.10.1 - github.com/spf13/pflag v1.0.9 - github.com/spf13/viper v1.20.1 + github.com/spf13/cast v1.10.0 + github.com/spf13/cobra v1.10.2 + github.com/spf13/pflag v1.0.10 + github.com/spf13/viper v1.21.0 github.com/stretchr/testify v1.11.1 - golang.org/x/sync v0.16.0 - google.golang.org/grpc v1.75.0 + golang.org/x/sync v0.20.0 + google.golang.org/grpc v1.80.0 ) require ( - cel.dev/expr v0.24.0 // indirect - cloud.google.com/go v0.116.0 // indirect - cloud.google.com/go/auth v0.14.1 // indirect - cloud.google.com/go/auth/oauth2adapt v0.2.7 // indirect - cloud.google.com/go/compute/metadata v0.7.0 // indirect - cloud.google.com/go/iam v1.2.2 // indirect - cloud.google.com/go/monitoring v1.21.2 // indirect - cloud.google.com/go/storage v1.49.0 // indirect - cosmossdk.io/collections v1.2.1 // indirect + cel.dev/expr v0.25.1 // indirect + cloud.google.com/go v0.123.0 // indirect + cloud.google.com/go/auth v0.20.0 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect + cloud.google.com/go/compute/metadata v0.9.0 // indirect + cloud.google.com/go/iam v1.9.0 // indirect + cloud.google.com/go/monitoring v1.27.0 // indirect + cloud.google.com/go/storage v1.62.1 // indirect + cosmossdk.io/collections v1.4.0 // indirect cosmossdk.io/depinject v1.2.1 // indirect cosmossdk.io/schema v1.1.0 // indirect - cosmossdk.io/x/tx v0.14.0 // indirect - filippo.io/edwards25519 v1.1.0 // indirect + filippo.io/edwards25519 v1.2.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // 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/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0 // indirect - github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 // indirect - github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.32.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.56.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.56.0 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/StackExchange/wmi v1.2.1 // indirect - github.com/VictoriaMetrics/fastcache v1.12.2 // indirect - github.com/aws/aws-sdk-go v1.49.0 // indirect + github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260116142910-60249400e523 // indirect + github.com/RoaringBitmap/roaring/v2 v2.18.0 // indirect + github.com/VictoriaMetrics/fastcache v1.13.0 // indirect + github.com/aws/aws-sdk-go-v2 v1.41.6 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.9 // indirect + github.com/aws/aws-sdk-go-v2/config v1.32.14 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.19.14 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.22 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.22 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.23 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.8 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.14 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.22 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.22 // indirect + github.com/aws/aws-sdk-go-v2/service/s3 v1.100.0 // indirect + github.com/aws/aws-sdk-go-v2/service/signin v1.0.9 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.30.15 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.19 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.41.10 // indirect + github.com/aws/smithy-go v1.25.0 // indirect + github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/bgentry/speakeasy v0.2.0 // indirect - github.com/bits-and-blooms/bitset v1.22.0 // indirect + github.com/bits-and-blooms/bitset v1.24.4 // indirect github.com/btcsuite/btcd v0.24.2 // indirect - github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.5 // indirect github.com/btcsuite/btcd/btcutil v1.1.6 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect - github.com/bytedance/sonic v1.14.0 // indirect - github.com/bytedance/sonic/loader v0.3.0 // indirect + github.com/bytedance/gopkg v0.1.4 // indirect + github.com/bytedance/sonic v1.15.0 // indirect + github.com/bytedance/sonic/loader v0.5.1 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cenkalti/backoff/v5 v5.0.3 // indirect github.com/cespare/xxhash/v2 v2.3.0 // 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 - 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/cloudwego/base64x v0.1.6 // indirect + github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 // indirect + github.com/cockroachdb/errors v1.13.0 // indirect + github.com/cockroachdb/fifo v0.0.0-20240816210425-c5d0cb0b6fc0 // 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 - github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect - github.com/cometbft/cometbft-db v0.14.1 // indirect - github.com/consensys/gnark-crypto v0.18.0 // indirect + github.com/cockroachdb/redact v1.1.8 // indirect + github.com/cockroachdb/tokenbucket v0.0.0-20250429170803-42689b6311bb // indirect + github.com/cometbft/cometbft-db v1.0.4 // indirect + github.com/consensys/gnark-crypto v0.18.1 // indirect github.com/cosmos/btcutil v1.0.5 // indirect + github.com/cosmos/btree v1.0.0 // indirect github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect 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/iavl v1.2.8 // 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/creachadair/atomicfile v0.3.7 // indirect - github.com/creachadair/tomledit v0.0.28 // indirect - github.com/danieljoos/wincred v1.2.1 // indirect + github.com/cosmos/ledger-cosmos-go v1.0.0 // indirect + github.com/crate-crypto/go-eth-kzg v1.5.0 // indirect + github.com/creachadair/atomicfile v0.3.8 // indirect + github.com/creachadair/tomledit v0.0.29 // indirect + github.com/danieljoos/wincred v1.2.3 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.1 // indirect github.com/desertbit/timer v1.0.1 // indirect - github.com/dgraph-io/badger/v4 v4.2.0 // indirect - github.com/dgraph-io/ristretto v0.1.1 // indirect + github.com/dgraph-io/badger/v4 v4.9.1 // indirect + github.com/dgraph-io/ristretto/v2 v2.4.0 // indirect github.com/dlclark/regexp2 v1.7.0 // indirect github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 // indirect + github.com/dunglas/httpsfv v1.1.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect - github.com/dvsekhvalnov/jose2go v1.7.0 // indirect - github.com/emicklei/dot v1.6.2 // indirect - github.com/envoyproxy/go-control-plane/envoy v1.32.4 // indirect - github.com/envoyproxy/protoc-gen-validate v1.2.1 // 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.17.0 // indirect + github.com/dvsekhvalnov/jose2go v1.8.0 // indirect + github.com/ebitengine/purego v0.10.0 // indirect + github.com/emicklei/dot v1.11.0 // indirect + github.com/envoyproxy/go-control-plane/envoy v1.37.0 // indirect + github.com/envoyproxy/protoc-gen-validate v1.3.3 // indirect + github.com/ethereum/c-kzg-4844/v2 v2.1.6 // indirect + github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab // indirect + github.com/fatih/color v1.18.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/ferranbt/fastssz v0.1.4 // indirect + github.com/flynn/noise v1.1.0 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect - github.com/getsentry/sentry-go v0.32.0 // indirect - github.com/go-jose/go-jose/v4 v4.1.1 // indirect + github.com/gammazero/deque v1.2.0 // indirect + github.com/getsentry/sentry-go v0.46.0 // indirect + github.com/go-jose/go-jose/v4 v4.1.4 // indirect github.com/go-kit/kit v0.13.0 // indirect github.com/go-kit/log v0.2.1 // indirect - github.com/go-logfmt/logfmt v0.6.0 // indirect + github.com/go-logfmt/logfmt v0.6.1 // 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-sourcemap/sourcemap v2.1.3+incompatible // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect - github.com/go-viper/mapstructure/v2 v2.2.1 // indirect + github.com/go-viper/mapstructure/v2 v2.5.0 // indirect 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/protobuf v1.5.4 // indirect - github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e // indirect + github.com/golang/snappy v1.0.0 // indirect github.com/google/btree v1.1.3 // indirect - github.com/google/flatbuffers v24.3.25+incompatible // indirect + github.com/google/flatbuffers v25.2.10+incompatible // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/orderedcode v0.0.1 // indirect github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect github.com/google/s2a-go v0.1.9 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect - github.com/googleapis/gax-go/v2 v2.14.1 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.14 // indirect + github.com/googleapis/gax-go/v2 v2.22.0 // indirect github.com/gorilla/handlers v1.5.2 // indirect github.com/gorilla/mux v1.8.1 // indirect github.com/gorilla/websocket v1.5.3 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect + github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.72 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-getter v1.7.8 // indirect + github.com/hashicorp/go-getter v1.8.6 // indirect github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-metrics v0.5.4 // indirect - github.com/hashicorp/go-plugin v1.6.3 // indirect - github.com/hashicorp/go-safetemp v1.0.0 // indirect - github.com/hashicorp/go-version v1.6.0 // indirect + github.com/hashicorp/go-plugin v1.7.0 // indirect + github.com/hashicorp/go-uuid v1.0.3 // indirect + github.com/hashicorp/go-version v1.9.0 // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hashicorp/yamux v0.1.2 // indirect @@ -165,108 +187,183 @@ require ( 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 + github.com/ipfs/go-cid v0.5.0 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect - github.com/jmespath/go-jmespath v0.4.0 // indirect + github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect - github.com/klauspost/compress v1.18.0 // indirect - github.com/klauspost/cpuid/v2 v2.2.10 // indirect + github.com/klauspost/compress v1.18.5 // indirect + github.com/klauspost/cpuid/v2 v2.3.0 // indirect + github.com/koron/go-ssdp v0.0.6 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect - github.com/lib/pq v1.10.9 // indirect - github.com/linxGnu/grocksdb v1.9.2 // indirect + github.com/lib/pq v1.12.3 // indirect + github.com/libp2p/go-buffer-pool v0.1.0 // indirect + github.com/libp2p/go-flow-metrics v0.2.0 // indirect + github.com/libp2p/go-libp2p v0.47.0 // indirect + github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect + github.com/libp2p/go-msgio v0.3.0 // indirect + github.com/libp2p/go-netroute v0.3.0 // indirect + github.com/libp2p/go-reuseport v0.4.0 // indirect + github.com/libp2p/go-yamux/v5 v5.0.1 // indirect + github.com/linxGnu/grocksdb v1.10.7 // indirect + github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e // indirect github.com/manifoldco/promptui v0.9.0 // indirect + github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect github.com/mattn/go-colorable v0.1.14 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/mattn/go-isatty v0.0.22 // indirect github.com/mdp/qrterminal/v3 v3.2.1 // indirect - github.com/minio/highwayhash v1.0.3 // indirect - github.com/minio/sha256-simd v1.0.0 // indirect + github.com/miekg/dns v1.1.66 // indirect + github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect + github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect + github.com/minio/highwayhash v1.0.4 // indirect + github.com/minio/sha256-simd v1.0.1 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/mr-tron/base58 v1.3.0 // indirect + github.com/mschoch/smat v0.2.0 // indirect github.com/mtibben/percent v0.2.1 // indirect + github.com/multiformats/go-base32 v0.1.0 // indirect + github.com/multiformats/go-base36 v0.2.0 // indirect + github.com/multiformats/go-multiaddr v0.16.1 // indirect + github.com/multiformats/go-multiaddr-dns v0.4.1 // indirect + github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect + github.com/multiformats/go-multibase v0.2.0 // indirect + github.com/multiformats/go-multicodec v0.9.1 // indirect + github.com/multiformats/go-multihash v0.2.3 // indirect + github.com/multiformats/go-multistream v0.6.1 // indirect + github.com/multiformats/go-varint v0.0.7 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a // indirect - github.com/oklog/run v1.1.0 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/oasisprotocol/curve25519-voi v0.0.0-20251114093237-2ab5a27a1729 // indirect + github.com/oklog/run v1.2.0 // indirect + github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect - github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect - github.com/pion/dtls/v2 v2.2.7 // indirect - github.com/pion/logging v0.2.2 // indirect + github.com/petermattis/goid v0.0.0-20260113132338-7c7de50cc741 // indirect + github.com/pion/datachannel v1.5.10 // indirect + github.com/pion/dtls/v2 v2.2.12 // indirect + github.com/pion/dtls/v3 v3.1.2 // indirect + github.com/pion/ice/v4 v4.0.10 // indirect + github.com/pion/interceptor v0.1.40 // indirect + github.com/pion/logging v0.2.4 // indirect + github.com/pion/mdns/v2 v2.0.7 // indirect + github.com/pion/randutil v0.1.0 // indirect + github.com/pion/rtcp v1.2.15 // indirect + github.com/pion/rtp v1.8.19 // indirect + github.com/pion/sctp v1.8.39 // indirect + github.com/pion/sdp/v3 v3.0.13 // indirect + github.com/pion/srtp/v3 v3.0.6 // indirect + github.com/pion/stun v0.6.1 // indirect github.com/pion/stun/v2 v2.0.0 // indirect - github.com/pion/transport/v2 v2.2.1 // indirect - github.com/pion/transport/v3 v3.0.1 // indirect + github.com/pion/stun/v3 v3.0.0 // indirect + github.com/pion/transport/v2 v2.2.10 // indirect + github.com/pion/transport/v3 v3.0.7 // indirect + github.com/pion/transport/v4 v4.0.1 // indirect + github.com/pion/turn/v4 v4.0.2 // indirect + github.com/pion/webrtc/v4 v4.1.2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.22.0 // indirect - github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.63.0 // indirect - github.com/prometheus/procfs v0.15.1 // indirect - github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect - github.com/rivo/uniseg v0.2.0 // indirect + github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect + github.com/prometheus/client_golang v1.23.2 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/common v0.67.5 // indirect + github.com/prometheus/procfs v0.20.1 // indirect + github.com/quic-go/qpack v0.6.0 // indirect + github.com/quic-go/quic-go v0.59.0 // indirect + github.com/quic-go/webtransport-go v0.10.0 // indirect + github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/rs/cors v1.11.1 // indirect - 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/spiffe/go-spiffe/v2 v2.5.0 // indirect - github.com/stretchr/objx v0.5.2 // indirect + github.com/rs/zerolog v1.35.0 // indirect + github.com/sagikazarmark/locafero v0.12.0 // indirect + github.com/sasha-s/go-deadlock v0.3.9 // indirect + github.com/shirou/gopsutil v3.21.11+incompatible // indirect + github.com/shirou/gopsutil/v4 v4.26.4 // indirect + github.com/spaolacci/murmur3 v1.1.0 // indirect + github.com/spf13/afero v1.15.0 // indirect + github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect + github.com/stretchr/objx v0.5.3 // indirect github.com/subosito/gotenv v1.6.0 // indirect - github.com/supranational/blst v0.3.14 // indirect + github.com/supranational/blst v0.3.16 // 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/btree v1.8.1 // 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/match v1.2.0 // indirect + github.com/tidwall/pretty v1.2.1 // 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/tklauser/go-sysconf v0.3.16 // indirect + github.com/tklauser/numcpus v0.11.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/tyler-smith/go-bip39 v1.1.0 // indirect - github.com/ulikunitz/xz v0.5.11 // indirect - github.com/zeebo/errs v1.4.0 // indirect + github.com/ulikunitz/xz v0.5.15 // indirect + github.com/wlynxg/anet v0.0.5 // indirect + github.com/yusufpapurcu/wmi v1.2.4 // indirect + github.com/zondax/golem v0.27.0 // 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-alpha.1 // indirect - go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/contrib/detectors/gcp v1.36.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect - go.opentelemetry.io/otel v1.37.0 // indirect - go.opentelemetry.io/otel/metric v1.37.0 // indirect - go.opentelemetry.io/otel/sdk v1.37.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.37.0 // indirect - go.opentelemetry.io/otel/trace v1.37.0 // indirect + github.com/zondax/ledger-go v1.0.1 // indirect + go.etcd.io/bbolt v1.4.3 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/contrib/bridges/otelslog v0.18.0 // indirect + go.opentelemetry.io/contrib/detectors/gcp v1.43.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 // indirect + go.opentelemetry.io/contrib/instrumentation/host v0.68.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 // indirect + go.opentelemetry.io/contrib/instrumentation/runtime v0.68.0 // indirect + go.opentelemetry.io/contrib/otelconf v0.23.0 // indirect + go.opentelemetry.io/contrib/propagators/autoprop v0.68.0 // indirect + go.opentelemetry.io/contrib/propagators/aws v1.43.0 // indirect + go.opentelemetry.io/contrib/propagators/b3 v1.43.0 // indirect + go.opentelemetry.io/contrib/propagators/jaeger v1.43.0 // indirect + go.opentelemetry.io/contrib/propagators/ot v1.43.0 // indirect + go.opentelemetry.io/otel v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.19.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.19.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.43.0 // indirect + go.opentelemetry.io/otel/log v0.19.0 // indirect + go.opentelemetry.io/otel/metric v1.43.0 // indirect + go.opentelemetry.io/otel/sdk v1.43.0 // indirect + go.opentelemetry.io/otel/sdk/log v0.19.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.43.0 // indirect + go.opentelemetry.io/otel/trace v1.43.0 // indirect + go.opentelemetry.io/proto/otlp v1.10.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect - go.uber.org/mock v0.5.2 // indirect + go.uber.org/dig v1.19.0 // indirect + go.uber.org/fx v1.24.0 // indirect + go.uber.org/mock v0.6.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.41.0 // indirect - golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect - golang.org/x/net v0.43.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 - golang.org/x/text v0.28.0 // indirect - golang.org/x/time v0.10.0 // indirect - golang.org/x/tools v0.35.0 // indirect - google.golang.org/api v0.222.0 // indirect - google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 // indirect - google.golang.org/protobuf v1.36.8 // indirect + go.uber.org/zap v1.27.1 // indirect + go.yaml.in/yaml/v2 v2.4.4 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect + golang.org/x/arch v0.26.0 // indirect + golang.org/x/crypto v0.50.0 // indirect + golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90 // indirect + golang.org/x/mod v0.34.0 // indirect + golang.org/x/net v0.53.0 // indirect + golang.org/x/oauth2 v0.36.0 // indirect + golang.org/x/sys v0.43.0 // indirect + golang.org/x/telemetry v0.0.0-20260311193753-579e4da9a98c // indirect + golang.org/x/term v0.42.0 // indirect + golang.org/x/text v0.36.0 // indirect + golang.org/x/time v0.15.0 // indirect + golang.org/x/tools v0.43.0 // indirect + google.golang.org/api v0.276.0 // indirect + google.golang.org/genproto v0.0.0-20260414002931-afd174a4e478 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 // indirect + google.golang.org/protobuf v1.36.11 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.2 // indirect - nhooyr.io/websocket v1.8.11 // indirect - pgregory.net/rapid v1.2.0 // indirect + lukechampine.com/blake3 v1.4.1 // indirect + nhooyr.io/websocket v1.8.17 // indirect + pgregory.net/rapid v1.3.0 // indirect rsc.io/qr v0.2.0 // indirect sigs.k8s.io/yaml v1.6.0 // indirect ) @@ -276,10 +373,12 @@ replace ( github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 github.com/cosmos/evm => ../ // use Cosmos geth fork - // branch: release/1.16 - github.com/ethereum/go-ethereum => github.com/cosmos/go-ethereum v1.16.2-cosmos-1 + // branch: release/1.17 + github.com/ethereum/go-ethereum => github.com/cosmos/go-ethereum v1.17.2-cosmos-0 // 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 github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 + // use btree fork for bstm + github.com/tidwall/btree => github.com/cosmos/btree v0.0.0-20250924232609-2c6195d95951 ) diff --git a/evmd/go.sum b/evmd/go.sum index 61062dbe..92d6f82c 100644 --- a/evmd/go.sum +++ b/evmd/go.sum @@ -1,658 +1,54 @@ -cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY= -cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw= +cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4= +cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= 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.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= -cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= -cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= -cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= -cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= -cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= -cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= -cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= -cloud.google.com/go v0.100.1/go.mod h1:fs4QogzfH5n2pBXBP9vRiU+eCny7lD2vmFZy79Iuw1U= -cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= -cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= -cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= -cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= -cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= -cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= -cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= -cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= -cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= -cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= -cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= -cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= -cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o= -cloud.google.com/go/accesscontextmanager v1.4.0/go.mod h1:/Kjh7BBu/Gh83sv+K60vN9QE5NJcd80sU33vIe2IFPE= -cloud.google.com/go/accesscontextmanager v1.6.0/go.mod h1:8XCvZWfYw3K/ji0iVnp+6pu7huxoQTLmxAbVjbloTtM= -cloud.google.com/go/accesscontextmanager v1.7.0/go.mod h1:CEGLewx8dwa33aDAZQujl7Dx+uYhS0eay198wB/VumQ= -cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= -cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= -cloud.google.com/go/aiplatform v1.27.0/go.mod h1:Bvxqtl40l0WImSb04d0hXFU7gDOiq9jQmorivIiWcKg= -cloud.google.com/go/aiplatform v1.35.0/go.mod h1:7MFT/vCaOyZT/4IIFfxH4ErVg/4ku6lKv3w0+tFTgXQ= -cloud.google.com/go/aiplatform v1.36.1/go.mod h1:WTm12vJRPARNvJ+v6P52RDHCNe4AhvjcIZ/9/RRHy/k= -cloud.google.com/go/aiplatform v1.37.0/go.mod h1:IU2Cv29Lv9oCn/9LkFiiuKfwrRTq+QQMbW+hPCxJGZw= -cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= -cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= -cloud.google.com/go/analytics v0.17.0/go.mod h1:WXFa3WSym4IZ+JiKmavYdJwGG/CvpqiqczmL59bTD9M= -cloud.google.com/go/analytics v0.18.0/go.mod h1:ZkeHGQlcIPkw0R/GW+boWHhCOR43xz9RN/jn7WcqfIE= -cloud.google.com/go/analytics v0.19.0/go.mod h1:k8liqf5/HCnOUkbawNtrWWc+UAzyDlW89doe8TtoDsE= -cloud.google.com/go/apigateway v1.3.0/go.mod h1:89Z8Bhpmxu6AmUxuVRg/ECRGReEdiP3vQtk4Z1J9rJk= -cloud.google.com/go/apigateway v1.4.0/go.mod h1:pHVY9MKGaH9PQ3pJ4YLzoj6U5FUDeDFBllIz7WmzJoc= -cloud.google.com/go/apigateway v1.5.0/go.mod h1:GpnZR3Q4rR7LVu5951qfXPJCHquZt02jf7xQx7kpqN8= -cloud.google.com/go/apigeeconnect v1.3.0/go.mod h1:G/AwXFAKo0gIXkPTVfZDd2qA1TxBXJ3MgMRBQkIi9jc= -cloud.google.com/go/apigeeconnect v1.4.0/go.mod h1:kV4NwOKqjvt2JYR0AoIWo2QGfoRtn/pkS3QlHp0Ni04= -cloud.google.com/go/apigeeconnect v1.5.0/go.mod h1:KFaCqvBRU6idyhSNyn3vlHXc8VMDJdRmwDF6JyFRqZ8= -cloud.google.com/go/apigeeregistry v0.4.0/go.mod h1:EUG4PGcsZvxOXAdyEghIdXwAEi/4MEaoqLMLDMIwKXY= -cloud.google.com/go/apigeeregistry v0.5.0/go.mod h1:YR5+s0BVNZfVOUkMa5pAR2xGd0A473vA5M7j247o1wM= -cloud.google.com/go/apigeeregistry v0.6.0/go.mod h1:BFNzW7yQVLZ3yj0TKcwzb8n25CFBri51GVGOEUcgQsc= -cloud.google.com/go/apikeys v0.4.0/go.mod h1:XATS/yqZbaBK0HOssf+ALHp8jAlNHUgyfprvNcBIszU= -cloud.google.com/go/apikeys v0.5.0/go.mod h1:5aQfwY4D+ewMMWScd3hm2en3hCj+BROlyrt3ytS7KLI= -cloud.google.com/go/apikeys v0.6.0/go.mod h1:kbpXu5upyiAlGkKrJgQl8A0rKNNJ7dQ377pdroRSSi8= -cloud.google.com/go/appengine v1.4.0/go.mod h1:CS2NhuBuDXM9f+qscZ6V86m1MIIqPj3WC/UoEuR1Sno= -cloud.google.com/go/appengine v1.5.0/go.mod h1:TfasSozdkFI0zeoxW3PTBLiNqRmzraodCWatWI9Dmak= -cloud.google.com/go/appengine v1.6.0/go.mod h1:hg6i0J/BD2cKmDJbaFSYHFyZkgBEfQrDg/X0V5fJn84= -cloud.google.com/go/appengine v1.7.0/go.mod h1:eZqpbHFCqRGa2aCdope7eC0SWLV1j0neb/QnMJVWx6A= -cloud.google.com/go/appengine v1.7.1/go.mod h1:IHLToyb/3fKutRysUlFO0BPt5j7RiQ45nrzEJmKTo6E= -cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4= -cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0= -cloud.google.com/go/area120 v0.7.0/go.mod h1:a3+8EUD1SX5RUcCs3MY5YasiO1z6yLiNLRiFrykbynY= -cloud.google.com/go/area120 v0.7.1/go.mod h1:j84i4E1RboTWjKtZVWXPqvK5VHQFJRF2c1Nm69pWm9k= -cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ= -cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk= -cloud.google.com/go/artifactregistry v1.8.0/go.mod h1:w3GQXkJX8hiKN0v+at4b0qotwijQbYUqF2GWkZzAhC0= -cloud.google.com/go/artifactregistry v1.9.0/go.mod h1:2K2RqvA2CYvAeARHRkLDhMDJ3OXy26h3XW+3/Jh2uYc= -cloud.google.com/go/artifactregistry v1.11.1/go.mod h1:lLYghw+Itq9SONbCa1YWBoWs1nOucMH0pwXN1rOBZFI= -cloud.google.com/go/artifactregistry v1.11.2/go.mod h1:nLZns771ZGAwVLzTX/7Al6R9ehma4WUEhZGWV6CeQNQ= -cloud.google.com/go/artifactregistry v1.12.0/go.mod h1:o6P3MIvtzTOnmvGagO9v/rOjjA0HmhJ+/6KAXrmYDCI= -cloud.google.com/go/artifactregistry v1.13.0/go.mod h1:uy/LNfoOIivepGhooAUpL1i30Hgee3Cu0l4VTWHUC08= -cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o= -cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s= -cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0= -cloud.google.com/go/asset v1.9.0/go.mod h1:83MOE6jEJBMqFKadM9NLRcs80Gdw76qGuHn8m3h8oHQ= -cloud.google.com/go/asset v1.10.0/go.mod h1:pLz7uokL80qKhzKr4xXGvBQXnzHn5evJAEAtZiIb0wY= -cloud.google.com/go/asset v1.11.1/go.mod h1:fSwLhbRvC9p9CXQHJ3BgFeQNM4c9x10lqlrdEUYXlJo= -cloud.google.com/go/asset v1.12.0/go.mod h1:h9/sFOa4eDIyKmH6QMpm4eUK3pDojWnUhTgJlk762Hg= -cloud.google.com/go/asset v1.13.0/go.mod h1:WQAMyYek/b7NBpYq/K4KJWcRqzoalEsxz/t/dTk4THw= -cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY= -cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw= -cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI= -cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEarXQk6WEKkxYfL6kGIo= -cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0= -cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E= -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/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= -cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= -cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8= -cloud.google.com/go/automl v1.8.0/go.mod h1:xWx7G/aPEe/NP+qzYXktoBSDfjO+vnKMGgsApGJJquM= -cloud.google.com/go/automl v1.12.0/go.mod h1:tWDcHDp86aMIuHmyvjuKeeHEGq76lD7ZqfGLN6B0NuU= -cloud.google.com/go/baremetalsolution v0.3.0/go.mod h1:XOrocE+pvK1xFfleEnShBlNAXf+j5blPPxrhjKgnIFc= -cloud.google.com/go/baremetalsolution v0.4.0/go.mod h1:BymplhAadOO/eBa7KewQ0Ppg4A4Wplbn+PsFKRLo0uI= -cloud.google.com/go/baremetalsolution v0.5.0/go.mod h1:dXGxEkmR9BMwxhzBhV0AioD0ULBmuLZI8CdwalUxuss= -cloud.google.com/go/batch v0.3.0/go.mod h1:TR18ZoAekj1GuirsUsR1ZTKN3FC/4UDnScjT8NXImFE= -cloud.google.com/go/batch v0.4.0/go.mod h1:WZkHnP43R/QCGQsZ+0JyG4i79ranE2u8xvjq/9+STPE= -cloud.google.com/go/batch v0.7.0/go.mod h1:vLZN95s6teRUqRQ4s3RLDsH8PvboqBK+rn1oevL159g= -cloud.google.com/go/beyondcorp v0.2.0/go.mod h1:TB7Bd+EEtcw9PCPQhCJtJGjk/7TC6ckmnSFS+xwTfm4= -cloud.google.com/go/beyondcorp v0.3.0/go.mod h1:E5U5lcrcXMsCuoDNyGrpyTm/hn7ne941Jz2vmksAxW8= -cloud.google.com/go/beyondcorp v0.4.0/go.mod h1:3ApA0mbhHx6YImmuubf5pyW8srKnCEPON32/5hj+RmM= -cloud.google.com/go/beyondcorp v0.5.0/go.mod h1:uFqj9X+dSfrheVp7ssLTaRHd2EHqSL4QZmH4e8WXGGU= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA= -cloud.google.com/go/bigquery v1.43.0/go.mod h1:ZMQcXHsl+xmU1z36G2jNGZmKp9zNY5BUua5wDgmNCfw= -cloud.google.com/go/bigquery v1.44.0/go.mod h1:0Y33VqXTEsbamHJvJHdFmtqHvMIY28aK1+dFsvaChGc= -cloud.google.com/go/bigquery v1.47.0/go.mod h1:sA9XOgy0A8vQK9+MWhEQTY6Tix87M/ZurWFIxmF9I/E= -cloud.google.com/go/bigquery v1.48.0/go.mod h1:QAwSz+ipNgfL5jxiaK7weyOhzdoAy1zFm0Nf1fysJac= -cloud.google.com/go/bigquery v1.49.0/go.mod h1:Sv8hMmTFFYBlt/ftw2uN6dFdQPzBlREY9yBh7Oy7/4Q= -cloud.google.com/go/bigquery v1.50.0/go.mod h1:YrleYEh2pSEbgTBZYMJ5SuSr0ML3ypjRB1zgf7pvQLU= -cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY= -cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= -cloud.google.com/go/billing v1.6.0/go.mod h1:WoXzguj+BeHXPbKfNWkqVtDdzORazmCjraY+vrxcyvI= -cloud.google.com/go/billing v1.7.0/go.mod h1:q457N3Hbj9lYwwRbnlD7vUpyjq6u5U1RAOArInEiD5Y= -cloud.google.com/go/billing v1.12.0/go.mod h1:yKrZio/eu+okO/2McZEbch17O5CB5NpZhhXG6Z766ss= -cloud.google.com/go/billing v1.13.0/go.mod h1:7kB2W9Xf98hP9Sr12KfECgfGclsH3CQR0R08tnRlRbc= -cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM= -cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI= -cloud.google.com/go/binaryauthorization v1.3.0/go.mod h1:lRZbKgjDIIQvzYQS1p99A7/U1JqvqeZg0wiI5tp6tg0= -cloud.google.com/go/binaryauthorization v1.4.0/go.mod h1:tsSPQrBd77VLplV70GUhBf/Zm3FsKmgSqgm4UmiDItk= -cloud.google.com/go/binaryauthorization v1.5.0/go.mod h1:OSe4OU1nN/VswXKRBmciKpo9LulY41gch5c68htf3/Q= -cloud.google.com/go/certificatemanager v1.3.0/go.mod h1:n6twGDvcUBFu9uBgt4eYvvf3sQ6My8jADcOVwHmzadg= -cloud.google.com/go/certificatemanager v1.4.0/go.mod h1:vowpercVFyqs8ABSmrdV+GiFf2H/ch3KyudYQEMM590= -cloud.google.com/go/certificatemanager v1.6.0/go.mod h1:3Hh64rCKjRAX8dXgRAyOcY5vQ/fE1sh8o+Mdd6KPgY8= -cloud.google.com/go/channel v1.8.0/go.mod h1:W5SwCXDJsq/rg3tn3oG0LOxpAo6IMxNa09ngphpSlnk= -cloud.google.com/go/channel v1.9.0/go.mod h1:jcu05W0my9Vx4mt3/rEHpfxc9eKi9XwsdDL8yBMbKUk= -cloud.google.com/go/channel v1.11.0/go.mod h1:IdtI0uWGqhEeatSB62VOoJ8FSUhJ9/+iGkJVqp74CGE= -cloud.google.com/go/channel v1.12.0/go.mod h1:VkxCGKASi4Cq7TbXxlaBezonAYpp1GCnKMY6tnMQnLU= -cloud.google.com/go/cloudbuild v1.3.0/go.mod h1:WequR4ULxlqvMsjDEEEFnOG5ZSRSgWOywXYDb1vPE6U= -cloud.google.com/go/cloudbuild v1.4.0/go.mod h1:5Qwa40LHiOXmz3386FrjrYM93rM/hdRr7b53sySrTqA= -cloud.google.com/go/cloudbuild v1.6.0/go.mod h1:UIbc/w9QCbH12xX+ezUsgblrWv+Cv4Tw83GiSMHOn9M= -cloud.google.com/go/cloudbuild v1.7.0/go.mod h1:zb5tWh2XI6lR9zQmsm1VRA+7OCuve5d8S+zJUul8KTg= -cloud.google.com/go/cloudbuild v1.9.0/go.mod h1:qK1d7s4QlO0VwfYn5YuClDGg2hfmLZEb4wQGAbIgL1s= -cloud.google.com/go/clouddms v1.3.0/go.mod h1:oK6XsCDdW4Ib3jCCBugx+gVjevp2TMXFtgxvPSee3OM= -cloud.google.com/go/clouddms v1.4.0/go.mod h1:Eh7sUGCC+aKry14O1NRljhjyrr0NFC0G2cjwX0cByRk= -cloud.google.com/go/clouddms v1.5.0/go.mod h1:QSxQnhikCLUw13iAbffF2CZxAER3xDGNHjsTAkQJcQA= -cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY= -cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI= -cloud.google.com/go/cloudtasks v1.7.0/go.mod h1:ImsfdYWwlWNJbdgPIIGJWC+gemEGTBK/SunNQQNCAb4= -cloud.google.com/go/cloudtasks v1.8.0/go.mod h1:gQXUIwCSOI4yPVK7DgTVFiiP0ZW/eQkydWzwVMdHxrI= -cloud.google.com/go/cloudtasks v1.9.0/go.mod h1:w+EyLsVkLWHcOaqNEyvcKAsWp9p29dL6uL9Nst1cI7Y= -cloud.google.com/go/cloudtasks v1.10.0/go.mod h1:NDSoTLkZ3+vExFEWu2UJV1arUyzVDAiZtdWcsUyNwBs= -cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= -cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= -cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= -cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= -cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= -cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= -cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= -cloud.google.com/go/compute v1.12.0/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= -cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= -cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE= -cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= -cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= -cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= -cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= -cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= -cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= -cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= -cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= -cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -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/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= -cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= -cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= -cloud.google.com/go/container v1.6.0/go.mod h1:Xazp7GjJSeUYo688S+6J5V+n/t+G5sKBTFkKNudGRxg= -cloud.google.com/go/container v1.7.0/go.mod h1:Dp5AHtmothHGX3DwwIHPgq45Y8KmNsgN3amoYfxVkLo= -cloud.google.com/go/container v1.13.1/go.mod h1:6wgbMPeQRw9rSnKBCAJXnds3Pzj03C4JHamr8asWKy4= -cloud.google.com/go/container v1.14.0/go.mod h1:3AoJMPhHfLDxLvrlVWaK57IXzaPnLaZq63WX59aQBfM= -cloud.google.com/go/container v1.15.0/go.mod h1:ft+9S0WGjAyjDggg5S06DXj+fHJICWg8L7isCQe9pQA= -cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= -cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= -cloud.google.com/go/containeranalysis v0.7.0/go.mod h1:9aUL+/vZ55P2CXfuZjS4UjQ9AgXoSw8Ts6lemfmxBxI= -cloud.google.com/go/containeranalysis v0.9.0/go.mod h1:orbOANbwk5Ejoom+s+DUCTTJ7IBdBQJDcSylAx/on9s= -cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= -cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs= -cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc= -cloud.google.com/go/datacatalog v1.7.0/go.mod h1:9mEl4AuDYWw81UGc41HonIHH7/sn52H0/tc8f8ZbZIE= -cloud.google.com/go/datacatalog v1.8.0/go.mod h1:KYuoVOv9BM8EYz/4eMFxrr4DUKhGIOXxZoKYF5wdISM= -cloud.google.com/go/datacatalog v1.8.1/go.mod h1:RJ58z4rMp3gvETA465Vg+ag8BGgBdnRPEMMSTr5Uv+M= -cloud.google.com/go/datacatalog v1.12.0/go.mod h1:CWae8rFkfp6LzLumKOnmVh4+Zle4A3NXLzVJ1d1mRm0= -cloud.google.com/go/datacatalog v1.13.0/go.mod h1:E4Rj9a5ZtAxcQJlEBTLgMTphfP11/lNaAshpoBgemX8= -cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM= -cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ= -cloud.google.com/go/dataflow v0.8.0/go.mod h1:Rcf5YgTKPtQyYz8bLYhFoIV/vP39eL7fWNcSOyFfLJE= -cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo= -cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE= -cloud.google.com/go/dataform v0.5.0/go.mod h1:GFUYRe8IBa2hcomWplodVmUx/iTL0FrsauObOM3Ipr0= -cloud.google.com/go/dataform v0.6.0/go.mod h1:QPflImQy33e29VuapFdf19oPbE4aYTJxr31OAPV+ulA= -cloud.google.com/go/dataform v0.7.0/go.mod h1:7NulqnVozfHvWUBpMDfKMUESr+85aJsC/2O0o3jWPDE= -cloud.google.com/go/datafusion v1.4.0/go.mod h1:1Zb6VN+W6ALo85cXnM1IKiPw+yQMKMhB9TsTSRDo/38= -cloud.google.com/go/datafusion v1.5.0/go.mod h1:Kz+l1FGHB0J+4XF2fud96WMmRiq/wj8N9u007vyXZ2w= -cloud.google.com/go/datafusion v1.6.0/go.mod h1:WBsMF8F1RhSXvVM8rCV3AeyWVxcC2xY6vith3iw3S+8= -cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I= -cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ= -cloud.google.com/go/datalabeling v0.7.0/go.mod h1:WPQb1y08RJbmpM3ww0CSUAGweL0SxByuW2E+FU+wXcM= -cloud.google.com/go/dataplex v1.3.0/go.mod h1:hQuRtDg+fCiFgC8j0zV222HvzFQdRd+SVX8gdmFcZzA= -cloud.google.com/go/dataplex v1.4.0/go.mod h1:X51GfLXEMVJ6UN47ESVqvlsRplbLhcsAt0kZCCKsU0A= -cloud.google.com/go/dataplex v1.5.2/go.mod h1:cVMgQHsmfRoI5KFYq4JtIBEUbYwc3c7tXmIDhRmNNVQ= -cloud.google.com/go/dataplex v1.6.0/go.mod h1:bMsomC/aEJOSpHXdFKFGQ1b0TDPIeL28nJObeO1ppRs= -cloud.google.com/go/dataproc v1.7.0/go.mod h1:CKAlMjII9H90RXaMpSxQ8EU6dQx6iAYNPcYPOkSbi8s= -cloud.google.com/go/dataproc v1.8.0/go.mod h1:5OW+zNAH0pMpw14JVrPONsxMQYMBqJuzORhIBfBn9uI= -cloud.google.com/go/dataproc v1.12.0/go.mod h1:zrF3aX0uV3ikkMz6z4uBbIKyhRITnxvr4i3IjKsKrw4= -cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo= -cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA= -cloud.google.com/go/dataqna v0.7.0/go.mod h1:Lx9OcIIeqCrw1a6KdO3/5KMP1wAmTc0slZWwP12Qq3c= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/datastore v1.10.0/go.mod h1:PC5UzAmDEkAmkfaknstTYbNpgE49HAgW2J1gcgUfmdM= -cloud.google.com/go/datastore v1.11.0/go.mod h1:TvGxBIHCS50u8jzG+AW/ppf87v1of8nwzFNgEZU1D3c= -cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo= -cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ= -cloud.google.com/go/datastream v1.4.0/go.mod h1:h9dpzScPhDTs5noEMQVWP8Wx8AFBRyS0s8KWPx/9r0g= -cloud.google.com/go/datastream v1.5.0/go.mod h1:6TZMMNPwjUqZHBKPQ1wwXpb0d5VDVPl2/XoS5yi88q4= -cloud.google.com/go/datastream v1.6.0/go.mod h1:6LQSuswqLa7S4rPAOZFVjHIG3wJIjZcZrw8JDEDJuIs= -cloud.google.com/go/datastream v1.7.0/go.mod h1:uxVRMm2elUSPuh65IbZpzJNMbuzkcvu5CjMqVIUHrww= -cloud.google.com/go/deploy v1.4.0/go.mod h1:5Xghikd4VrmMLNaF6FiRFDlHb59VM59YoDQnOUdsH/c= -cloud.google.com/go/deploy v1.5.0/go.mod h1:ffgdD0B89tToyW/U/D2eL0jN2+IEV/3EMuXHA0l4r+s= -cloud.google.com/go/deploy v1.6.0/go.mod h1:f9PTHehG/DjCom3QH0cntOVRm93uGBDt2vKzAPwpXQI= -cloud.google.com/go/deploy v1.8.0/go.mod h1:z3myEJnA/2wnB4sgjqdMfgxCA0EqC3RBTNcVPs93mtQ= -cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4= -cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0= -cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8= -cloud.google.com/go/dialogflow v1.18.0/go.mod h1:trO7Zu5YdyEuR+BhSNOqJezyFQ3aUzz0njv7sMx/iek= -cloud.google.com/go/dialogflow v1.19.0/go.mod h1:JVmlG1TwykZDtxtTXujec4tQ+D8SBFMoosgy+6Gn0s0= -cloud.google.com/go/dialogflow v1.29.0/go.mod h1:b+2bzMe+k1s9V+F2jbJwpHPzrnIyHihAdRFMtn2WXuM= -cloud.google.com/go/dialogflow v1.31.0/go.mod h1:cuoUccuL1Z+HADhyIA7dci3N5zUssgpBJmCzI6fNRB4= -cloud.google.com/go/dialogflow v1.32.0/go.mod h1:jG9TRJl8CKrDhMEcvfcfFkkpp8ZhgPz3sBGmAUYJ2qE= -cloud.google.com/go/dlp v1.6.0/go.mod h1:9eyB2xIhpU0sVwUixfBubDoRwP+GjeUoxxeueZmqvmM= -cloud.google.com/go/dlp v1.7.0/go.mod h1:68ak9vCiMBjbasxeVD17hVPxDEck+ExiHavX8kiHG+Q= -cloud.google.com/go/dlp v1.9.0/go.mod h1:qdgmqgTyReTz5/YNSSuueR8pl7hO0o9bQ39ZhtgkWp4= -cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU= -cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU= -cloud.google.com/go/documentai v1.9.0/go.mod h1:FS5485S8R00U10GhgBC0aNGrJxBP8ZVpEeJ7PQDZd6k= -cloud.google.com/go/documentai v1.10.0/go.mod h1:vod47hKQIPeCfN2QS/jULIvQTugbmdc0ZvxxfQY1bg4= -cloud.google.com/go/documentai v1.16.0/go.mod h1:o0o0DLTEZ+YnJZ+J4wNfTxmDVyrkzFvttBXXtYRMHkM= -cloud.google.com/go/documentai v1.18.0/go.mod h1:F6CK6iUH8J81FehpskRmhLq/3VlwQvb7TvwOceQ2tbs= -cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y= -cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= -cloud.google.com/go/domains v0.8.0/go.mod h1:M9i3MMDzGFXsydri9/vW+EWz9sWb4I6WyHqdlAk0idE= -cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk= -cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= -cloud.google.com/go/edgecontainer v0.3.0/go.mod h1:FLDpP4nykgwwIfcLt6zInhprzw0lEi2P1fjO6Ie0qbc= -cloud.google.com/go/edgecontainer v1.0.0/go.mod h1:cttArqZpBB2q58W/upSG++ooo6EsblxDIolxa3jSjbY= -cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= -cloud.google.com/go/essentialcontacts v1.3.0/go.mod h1:r+OnHa5jfj90qIfZDO/VztSFqbQan7HV75p8sA+mdGI= -cloud.google.com/go/essentialcontacts v1.4.0/go.mod h1:8tRldvHYsmnBCHdFpvU+GL75oWiBKl80BiqlFh9tp+8= -cloud.google.com/go/essentialcontacts v1.5.0/go.mod h1:ay29Z4zODTuwliK7SnX8E86aUF2CTzdNtvv42niCX0M= -cloud.google.com/go/eventarc v1.7.0/go.mod h1:6ctpF3zTnaQCxUjHUdcfgcA1A2T309+omHZth7gDfmc= -cloud.google.com/go/eventarc v1.8.0/go.mod h1:imbzxkyAU4ubfsaKYdQg04WS1NvncblHEup4kvF+4gw= -cloud.google.com/go/eventarc v1.10.0/go.mod h1:u3R35tmZ9HvswGRBnF48IlYgYeBcPUCjkr4BTdem2Kw= -cloud.google.com/go/eventarc v1.11.0/go.mod h1:PyUjsUKPWoRBCHeOxZd/lbOOjahV41icXyUY5kSTvVY= -cloud.google.com/go/filestore v1.3.0/go.mod h1:+qbvHGvXU1HaKX2nD0WEPo92TP/8AQuCVEBXNY9z0+w= -cloud.google.com/go/filestore v1.4.0/go.mod h1:PaG5oDfo9r224f8OYXURtAsY+Fbyq/bLYoINEK8XQAI= -cloud.google.com/go/filestore v1.5.0/go.mod h1:FqBXDWBp4YLHqRnVGveOkHDf8svj9r5+mUDLupOWEDs= -cloud.google.com/go/filestore v1.6.0/go.mod h1:di5unNuss/qfZTw2U9nhFqo8/ZDSc466dre85Kydllg= -cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE= -cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk= -cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= -cloud.google.com/go/functions v1.8.0/go.mod h1:RTZ4/HsQjIqIYP9a9YPbU+QFoQsAlYgrwOXJWHn1POY= -cloud.google.com/go/functions v1.9.0/go.mod h1:Y+Dz8yGguzO3PpIjhLTbnqV1CWmgQ5UwtlpzoyquQ08= -cloud.google.com/go/functions v1.10.0/go.mod h1:0D3hEOe3DbEvCXtYOZHQZmD+SzYsi1YbI7dGvHfldXw= -cloud.google.com/go/functions v1.12.0/go.mod h1:AXWGrF3e2C/5ehvwYo/GH6O5s09tOPksiKhz+hH8WkA= -cloud.google.com/go/functions v1.13.0/go.mod h1:EU4O007sQm6Ef/PwRsI8N2umygGqPBS/IZQKBQBcJ3c= -cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM= -cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA= -cloud.google.com/go/gaming v1.7.0/go.mod h1:LrB8U7MHdGgFG851iHAfqUdLcKBdQ55hzXy9xBJz0+w= -cloud.google.com/go/gaming v1.8.0/go.mod h1:xAqjS8b7jAVW0KFYeRUxngo9My3f33kFmua++Pi+ggM= -cloud.google.com/go/gaming v1.9.0/go.mod h1:Fc7kEmCObylSWLO334NcO+O9QMDyz+TKC4v1D7X+Bc0= -cloud.google.com/go/gkebackup v0.2.0/go.mod h1:XKvv/4LfG829/B8B7xRkk8zRrOEbKtEam6yNfuQNH60= -cloud.google.com/go/gkebackup v0.3.0/go.mod h1:n/E671i1aOQvUxT541aTkCwExO/bTer2HDlj4TsBRAo= -cloud.google.com/go/gkebackup v0.4.0/go.mod h1:byAyBGUwYGEEww7xsbnUTBHIYcOPy/PgUWUtOeRm9Vg= -cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o= -cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A= -cloud.google.com/go/gkeconnect v0.7.0/go.mod h1:SNfmVqPkaEi3bF/B3CNZOAYPYdg7sU+obZ+QTky2Myw= -cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0= -cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0= -cloud.google.com/go/gkehub v0.11.0/go.mod h1:JOWHlmN+GHyIbuWQPl47/C2RFhnFKH38jH9Ascu3n0E= -cloud.google.com/go/gkehub v0.12.0/go.mod h1:djiIwwzTTBrF5NaXCGv3mf7klpEMcST17VBTVVDcuaw= -cloud.google.com/go/gkemulticloud v0.3.0/go.mod h1:7orzy7O0S+5kq95e4Hpn7RysVA7dPs8W/GgfUtsPbrA= -cloud.google.com/go/gkemulticloud v0.4.0/go.mod h1:E9gxVBnseLWCk24ch+P9+B2CoDFJZTyIgLKSalC7tuI= -cloud.google.com/go/gkemulticloud v0.5.0/go.mod h1:W0JDkiyi3Tqh0TJr//y19wyb1yf8llHVto2Htf2Ja3Y= -cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= -cloud.google.com/go/gsuiteaddons v1.3.0/go.mod h1:EUNK/J1lZEZO8yPtykKxLXI6JSVN2rg9bN8SXOa0bgM= -cloud.google.com/go/gsuiteaddons v1.4.0/go.mod h1:rZK5I8hht7u7HxFQcFei0+AtfS9uSushomRlg+3ua1o= -cloud.google.com/go/gsuiteaddons v1.5.0/go.mod h1:TFCClYLd64Eaa12sFVmUyG62tk4mdIsI7pAnSXRkcFo= -cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c= -cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= -cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= -cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc= -cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= -cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= -cloud.google.com/go/iam v0.11.0/go.mod h1:9PiLDanza5D+oWFZiH1uG+RnRCfEGKoyl6yo4cgWZGY= -cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= -cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= -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/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc= -cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A= -cloud.google.com/go/iap v1.6.0/go.mod h1:NSuvI9C/j7UdjGjIde7t7HBz+QTwBcapPE07+sSRcLk= -cloud.google.com/go/iap v1.7.0/go.mod h1:beqQx56T9O1G1yNPph+spKpNibDlYIiIixiqsQXxLIo= -cloud.google.com/go/iap v1.7.1/go.mod h1:WapEwPc7ZxGt2jFGB/C/bm+hP0Y6NXzOYGjpPnmMS74= -cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM= -cloud.google.com/go/ids v1.2.0/go.mod h1:5WXvp4n25S0rA/mQWAg1YEEBBq6/s+7ml1RDCW1IrcY= -cloud.google.com/go/ids v1.3.0/go.mod h1:JBdTYwANikFKaDP6LtW5JAi4gubs57SVNQjemdt6xV4= -cloud.google.com/go/iot v1.3.0/go.mod h1:r7RGh2B61+B8oz0AGE+J72AhA0G7tdXItODWsaA2oLs= -cloud.google.com/go/iot v1.4.0/go.mod h1:dIDxPOn0UvNDUMD8Ger7FIaTuvMkj+aGk94RPP0iV+g= -cloud.google.com/go/iot v1.5.0/go.mod h1:mpz5259PDl3XJthEmh9+ap0affn/MqNSP4My77Qql9o= -cloud.google.com/go/iot v1.6.0/go.mod h1:IqdAsmE2cTYYNO1Fvjfzo9po179rAtJeVGUvkLN3rLE= -cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA= -cloud.google.com/go/kms v1.5.0/go.mod h1:QJS2YY0eJGBg3mnDfuaCyLauWwBJiHRboYxJ++1xJNg= -cloud.google.com/go/kms v1.6.0/go.mod h1:Jjy850yySiasBUDi6KFUwUv2n1+o7QZFyuUJg6OgjA0= -cloud.google.com/go/kms v1.8.0/go.mod h1:4xFEhYFqvW+4VMELtZyxomGSYtSQKzM178ylFW4jMAg= -cloud.google.com/go/kms v1.9.0/go.mod h1:qb1tPTgfF9RQP8e1wq4cLFErVuTJv7UsSC915J8dh3w= -cloud.google.com/go/kms v1.10.0/go.mod h1:ng3KTUtQQU9bPX3+QGLsflZIHlkbn8amFAMY63m8d24= -cloud.google.com/go/kms v1.10.1/go.mod h1:rIWk/TryCkR59GMC3YtHtXeLzd634lBbKenvyySAyYI= -cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= -cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= -cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiPzPCJa2MIE= -cloud.google.com/go/language v1.8.0/go.mod h1:qYPVHf7SPoNNiCL2Dr0FfEFNil1qi3pQEyygwpgVKB8= -cloud.google.com/go/language v1.9.0/go.mod h1:Ns15WooPM5Ad/5no/0n81yUetis74g3zrbeJBE+ptUY= -cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= -cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= -cloud.google.com/go/lifesciences v0.8.0/go.mod h1:lFxiEOMqII6XggGbOnKiyZ7IBwoIqA84ClvoezaA/bo= -cloud.google.com/go/logging v1.6.1/go.mod h1:5ZO0mHHbvm8gEmeEUHrmDlTDSu5imF6MUP9OfilNXBw= -cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeNqVNkzY8M= -cloud.google.com/go/logging v1.12.0 h1:ex1igYcGFd4S/RZWOCU51StlIEuey5bjqwH9ZYjHibk= -cloud.google.com/go/logging v1.12.0/go.mod h1:wwYBt5HlYP1InnrtYI0wtwttpVU1rifnMT7RejksUAM= -cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE= -cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= -cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= -cloud.google.com/go/longrunning v0.6.2 h1:xjDfh1pQcWPEvnfjZmwjKQEcHnpz6lHjfy7Fo0MK+hc= -cloud.google.com/go/longrunning v0.6.2/go.mod h1:k/vIs83RN4bE3YCswdXC5PFfWVILjm3hpEUlSko4PiI= -cloud.google.com/go/managedidentities v1.3.0/go.mod h1:UzlW3cBOiPrzucO5qWkNkh0w33KFtBJU281hacNvsdE= -cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtqOsxY1ZrGM+9RgDqInM= -cloud.google.com/go/managedidentities v1.5.0/go.mod h1:+dWcZ0JlUmpuxpIDfyP5pP5y0bLdRwOS4Lp7gMni/LA= -cloud.google.com/go/maps v0.1.0/go.mod h1:BQM97WGyfw9FWEmQMpZ5T6cpovXXSd1cGmFma94eubI= -cloud.google.com/go/maps v0.6.0/go.mod h1:o6DAMMfb+aINHz/p/jbcY+mYeXBoZoxTfdSQ8VAJaCw= -cloud.google.com/go/maps v0.7.0/go.mod h1:3GnvVl3cqeSvgMcpRlQidXsPYuDGQ8naBis7MVzpXsY= -cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= -cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= -cloud.google.com/go/mediatranslation v0.7.0/go.mod h1:LCnB/gZr90ONOIQLgSXagp8XUW1ODs2UmUMvcgMfI2I= -cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= -cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM= -cloud.google.com/go/memcache v1.6.0/go.mod h1:XS5xB0eQZdHtTuTF9Hf8eJkKtR3pVRCcvJwtm68T3rA= -cloud.google.com/go/memcache v1.7.0/go.mod h1:ywMKfjWhNtkQTxrWxCkCFkoPjLHPW6A7WOTVI8xy3LY= -cloud.google.com/go/memcache v1.9.0/go.mod h1:8oEyzXCu+zo9RzlEaEjHl4KkgjlNDaXbCQeQWlzNFJM= -cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY= -cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s= -cloud.google.com/go/metastore v1.7.0/go.mod h1:s45D0B4IlsINu87/AsWiEVYbLaIMeUSoxlKKDqBGFS8= -cloud.google.com/go/metastore v1.8.0/go.mod h1:zHiMc4ZUpBiM7twCIFQmJ9JMEkDSyZS9U12uf7wHqSI= -cloud.google.com/go/metastore v1.10.0/go.mod h1:fPEnH3g4JJAk+gMRnrAnoqyv2lpUCqJPWOodSaf45Eo= -cloud.google.com/go/monitoring v1.7.0/go.mod h1:HpYse6kkGo//7p6sT0wsIC6IBDET0RhIsnmlA53dvEk= -cloud.google.com/go/monitoring v1.8.0/go.mod h1:E7PtoMJ1kQXWxPjB6mv2fhC5/15jInuulFdYYtlcvT4= -cloud.google.com/go/monitoring v1.12.0/go.mod h1:yx8Jj2fZNEkL/GYZyTLS4ZtZEZN8WtDEiEqG4kLK50w= -cloud.google.com/go/monitoring v1.13.0/go.mod h1:k2yMBAB1H9JT/QETjNkgdCGD9bPF712XiLTVr+cBrpw= -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/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA= -cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o= -cloud.google.com/go/networkconnectivity v1.6.0/go.mod h1:OJOoEXW+0LAxHh89nXd64uGG+FbQoeH8DtxCHVOMlaM= -cloud.google.com/go/networkconnectivity v1.7.0/go.mod h1:RMuSbkdbPwNMQjB5HBWD5MpTBnNm39iAVpC3TmsExt8= -cloud.google.com/go/networkconnectivity v1.10.0/go.mod h1:UP4O4sWXJG13AqrTdQCD9TnLGEbtNRqjuaaA7bNjF5E= -cloud.google.com/go/networkconnectivity v1.11.0/go.mod h1:iWmDD4QF16VCDLXUqvyspJjIEtBR/4zq5hwnY2X3scM= -cloud.google.com/go/networkmanagement v1.4.0/go.mod h1:Q9mdLLRn60AsOrPc8rs8iNV6OHXaGcDdsIQe1ohekq8= -cloud.google.com/go/networkmanagement v1.5.0/go.mod h1:ZnOeZ/evzUdUsnvRt792H0uYEnHQEMaz+REhhzJRcf4= -cloud.google.com/go/networkmanagement v1.6.0/go.mod h1:5pKPqyXjB/sgtvB5xqOemumoQNB7y95Q7S+4rjSOPYY= -cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ= -cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU= -cloud.google.com/go/networksecurity v0.7.0/go.mod h1:mAnzoxx/8TBSyXEeESMy9OOYwo1v+gZ5eMRnsT5bC8k= -cloud.google.com/go/networksecurity v0.8.0/go.mod h1:B78DkqsxFG5zRSVuwYFRZ9Xz8IcQ5iECsNrPn74hKHU= -cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY= -cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34= -cloud.google.com/go/notebooks v1.4.0/go.mod h1:4QPMngcwmgb6uw7Po99B2xv5ufVoIQ7nOGDyL4P8AgA= -cloud.google.com/go/notebooks v1.5.0/go.mod h1:q8mwhnP9aR8Hpfnrc5iN5IBhrXUy8S2vuYs+kBJ/gu0= -cloud.google.com/go/notebooks v1.7.0/go.mod h1:PVlaDGfJgj1fl1S3dUwhFMXFgfYGhYQt2164xOMONmE= -cloud.google.com/go/notebooks v1.8.0/go.mod h1:Lq6dYKOYOWUCTvw5t2q1gp1lAp0zxAxRycayS0iJcqQ= -cloud.google.com/go/optimization v1.1.0/go.mod h1:5po+wfvX5AQlPznyVEZjGJTMr4+CAkJf2XSTQOOl9l4= -cloud.google.com/go/optimization v1.2.0/go.mod h1:Lr7SOHdRDENsh+WXVmQhQTrzdu9ybg0NecjHidBq6xs= -cloud.google.com/go/optimization v1.3.1/go.mod h1:IvUSefKiwd1a5p0RgHDbWCIbDFgKuEdB+fPPuP0IDLI= -cloud.google.com/go/orchestration v1.3.0/go.mod h1:Sj5tq/JpWiB//X/q3Ngwdl5K7B7Y0KZ7bfv0wL6fqVA= -cloud.google.com/go/orchestration v1.4.0/go.mod h1:6W5NLFWs2TlniBphAViZEVhrXRSMgUGDfW7vrWKvsBk= -cloud.google.com/go/orchestration v1.6.0/go.mod h1:M62Bevp7pkxStDfFfTuCOaXgaaqRAga1yKyoMtEoWPQ= -cloud.google.com/go/orgpolicy v1.4.0/go.mod h1:xrSLIV4RePWmP9P3tBl8S93lTmlAxjm06NSm2UTmKvE= -cloud.google.com/go/orgpolicy v1.5.0/go.mod h1:hZEc5q3wzwXJaKrsx5+Ewg0u1LxJ51nNFlext7Tanwc= -cloud.google.com/go/orgpolicy v1.10.0/go.mod h1:w1fo8b7rRqlXlIJbVhOMPrwVljyuW5mqssvBtU18ONc= -cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs= -cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg= -cloud.google.com/go/osconfig v1.9.0/go.mod h1:Yx+IeIZJ3bdWmzbQU4fxNl8xsZ4amB+dygAwFPlvnNo= -cloud.google.com/go/osconfig v1.10.0/go.mod h1:uMhCzqC5I8zfD9zDEAfvgVhDS8oIjySWh+l4WK6GnWw= -cloud.google.com/go/osconfig v1.11.0/go.mod h1:aDICxrur2ogRd9zY5ytBLV89KEgT2MKB2L/n6x1ooPw= -cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E= -cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU= -cloud.google.com/go/oslogin v1.6.0/go.mod h1:zOJ1O3+dTU8WPlGEkFSh7qeHPPSoxrcMbbK1Nm2iX70= -cloud.google.com/go/oslogin v1.7.0/go.mod h1:e04SN0xO1UNJ1M5GP0vzVBFicIe4O53FOfcixIqTyXo= -cloud.google.com/go/oslogin v1.9.0/go.mod h1:HNavntnH8nzrn8JCTT5fj18FuJLFJc4NaZJtBnQtKFs= -cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0= -cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA= -cloud.google.com/go/phishingprotection v0.7.0/go.mod h1:8qJI4QKHoda/sb/7/YmMQ2omRLSLYSu9bU0EKCNI+Lk= -cloud.google.com/go/policytroubleshooter v1.3.0/go.mod h1:qy0+VwANja+kKrjlQuOzmlvscn4RNsAc0e15GGqfMxg= -cloud.google.com/go/policytroubleshooter v1.4.0/go.mod h1:DZT4BcRw3QoO8ota9xw/LKtPa8lKeCByYeKTIf/vxdE= -cloud.google.com/go/policytroubleshooter v1.5.0/go.mod h1:Rz1WfV+1oIpPdN2VvvuboLVRsB1Hclg3CKQ53j9l8vw= -cloud.google.com/go/policytroubleshooter v1.6.0/go.mod h1:zYqaPTsmfvpjm5ULxAyD/lINQxJ0DDsnWOP/GZ7xzBc= -cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0= -cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI= -cloud.google.com/go/privatecatalog v0.7.0/go.mod h1:2s5ssIFO69F5csTXcwBP7NPFTZvps26xGzvQ2PQaBYg= -cloud.google.com/go/privatecatalog v0.8.0/go.mod h1:nQ6pfaegeDAq/Q5lrfCQzQLhubPiZhSaNhIgfJlnIXs= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/pubsub v1.26.0/go.mod h1:QgBH3U/jdJy/ftjPhTkyXNj543Tin1pRYcdcPRnFIRI= -cloud.google.com/go/pubsub v1.27.1/go.mod h1:hQN39ymbV9geqBnfQq6Xf63yNhUAhv9CZhzp5O6qsW0= -cloud.google.com/go/pubsub v1.28.0/go.mod h1:vuXFpwaVoIPQMGXqRyUQigu/AX1S3IWugR9xznmcXX8= -cloud.google.com/go/pubsub v1.30.0/go.mod h1:qWi1OPS0B+b5L+Sg6Gmc9zD1Y+HaM0MdUr7LsupY1P4= -cloud.google.com/go/pubsublite v1.5.0/go.mod h1:xapqNQ1CuLfGi23Yda/9l4bBCKz/wC3KIJ5gKcxveZg= -cloud.google.com/go/pubsublite v1.6.0/go.mod h1:1eFCS0U11xlOuMFV/0iBqw3zP12kddMeCbj/F3FSj9k= -cloud.google.com/go/pubsublite v1.7.0/go.mod h1:8hVMwRXfDfvGm3fahVbtDbiLePT3gpoiJYJY+vxWxVM= -cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4= -cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o= -cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk= -cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7dd5NwwNQUErSgEDit1DLNTdo= -cloud.google.com/go/recaptchaenterprise/v2 v2.4.0/go.mod h1:Am3LHfOuBstrLrNCBrlI5sbwx9LBg3te2N6hGvHn2mE= -cloud.google.com/go/recaptchaenterprise/v2 v2.5.0/go.mod h1:O8LzcHXN3rz0j+LBC91jrwI3R+1ZSZEWrfL7XHgNo9U= -cloud.google.com/go/recaptchaenterprise/v2 v2.6.0/go.mod h1:RPauz9jeLtB3JVzg6nCbe12qNoaa8pXc4d/YukAmcnA= -cloud.google.com/go/recaptchaenterprise/v2 v2.7.0/go.mod h1:19wVj/fs5RtYtynAPJdDTb69oW0vNHYDBTbB4NvMD9c= -cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg= -cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4= -cloud.google.com/go/recommendationengine v0.7.0/go.mod h1:1reUcE3GIu6MeBz/h5xZJqNLuuVjNg1lmWMPyjatzac= -cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg= -cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c= -cloud.google.com/go/recommender v1.7.0/go.mod h1:XLHs/W+T8olwlGOgfQenXBTbIseGclClff6lhFVe9Bs= -cloud.google.com/go/recommender v1.8.0/go.mod h1:PkjXrTT05BFKwxaUxQmtIlrtj0kph108r02ZZQ5FE70= -cloud.google.com/go/recommender v1.9.0/go.mod h1:PnSsnZY7q+VL1uax2JWkt/UegHssxjUVVCrX52CuEmQ= -cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y= -cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A= -cloud.google.com/go/redis v1.9.0/go.mod h1:HMYQuajvb2D0LvMgZmLDZW8V5aOC/WxstZHiy4g8OiA= -cloud.google.com/go/redis v1.10.0/go.mod h1:ThJf3mMBQtW18JzGgh41/Wld6vnDDc/F/F35UolRZPM= -cloud.google.com/go/redis v1.11.0/go.mod h1:/X6eicana+BWcUda5PpwZC48o37SiFVTFSs0fWAJ7uQ= -cloud.google.com/go/resourcemanager v1.3.0/go.mod h1:bAtrTjZQFJkiWTPDb1WBjzvc6/kifjj4QBYuKCCoqKA= -cloud.google.com/go/resourcemanager v1.4.0/go.mod h1:MwxuzkumyTX7/a3n37gmsT3py7LIXwrShilPh3P1tR0= -cloud.google.com/go/resourcemanager v1.5.0/go.mod h1:eQoXNAiAvCf5PXxWxXjhKQoTMaUSNrEfg+6qdf/wots= -cloud.google.com/go/resourcemanager v1.6.0/go.mod h1:YcpXGRs8fDzcUl1Xw8uOVmI8JEadvhRIkoXXUNVYcVo= -cloud.google.com/go/resourcemanager v1.7.0/go.mod h1:HlD3m6+bwhzj9XCouqmeiGuni95NTrExfhoSrkC/3EI= -cloud.google.com/go/resourcesettings v1.3.0/go.mod h1:lzew8VfESA5DQ8gdlHwMrqZs1S9V87v3oCnKCWoOuQU= -cloud.google.com/go/resourcesettings v1.4.0/go.mod h1:ldiH9IJpcrlC3VSuCGvjR5of/ezRrOxFtpJoJo5SmXg= -cloud.google.com/go/resourcesettings v1.5.0/go.mod h1:+xJF7QSG6undsQDfsCJyqWXyBwUoJLhetkRMDRnIoXA= -cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4= -cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY= -cloud.google.com/go/retail v1.10.0/go.mod h1:2gDk9HsL4HMS4oZwz6daui2/jmKvqShXKQuB2RZ+cCc= -cloud.google.com/go/retail v1.11.0/go.mod h1:MBLk1NaWPmh6iVFSz9MeKG/Psyd7TAgm6y/9L2B4x9Y= -cloud.google.com/go/retail v1.12.0/go.mod h1:UMkelN/0Z8XvKymXFbD4EhFJlYKRx1FGhQkVPU5kF14= -cloud.google.com/go/run v0.2.0/go.mod h1:CNtKsTA1sDcnqqIFR3Pb5Tq0usWxJJvsWOCPldRU3Do= -cloud.google.com/go/run v0.3.0/go.mod h1:TuyY1+taHxTjrD0ZFk2iAR+xyOXEA0ztb7U3UNA0zBo= -cloud.google.com/go/run v0.8.0/go.mod h1:VniEnuBwqjigv0A7ONfQUaEItaiCRVujlMqerPPiktM= -cloud.google.com/go/run v0.9.0/go.mod h1:Wwu+/vvg8Y+JUApMwEDfVfhetv30hCG4ZwDR/IXl2Qg= -cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s= -cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI= -cloud.google.com/go/scheduler v1.6.0/go.mod h1:SgeKVM7MIwPn3BqtcBntpLyrIJftQISRrYB5ZtT+KOk= -cloud.google.com/go/scheduler v1.7.0/go.mod h1:jyCiBqWW956uBjjPMMuX09n3x37mtyPJegEWKxRsn44= -cloud.google.com/go/scheduler v1.8.0/go.mod h1:TCET+Y5Gp1YgHT8py4nlg2Sew8nUHMqcpousDgXJVQc= -cloud.google.com/go/scheduler v1.9.0/go.mod h1:yexg5t+KSmqu+njTIh3b7oYPheFtBWGcbVUYF1GGMIc= -cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA= -cloud.google.com/go/secretmanager v1.8.0/go.mod h1:hnVgi/bN5MYHd3Gt0SPuTPPp5ENina1/LxM+2W9U9J4= -cloud.google.com/go/secretmanager v1.9.0/go.mod h1:b71qH2l1yHmWQHt9LC80akm86mX8AL6X1MA01dW8ht4= -cloud.google.com/go/secretmanager v1.10.0/go.mod h1:MfnrdvKMPNra9aZtQFvBcvRU54hbPD8/HayQdlUgJpU= -cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4= -cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0= -cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU= -cloud.google.com/go/security v1.9.0/go.mod h1:6Ta1bO8LXI89nZnmnsZGp9lVoVWXqsVbIq/t9dzI+2Q= -cloud.google.com/go/security v1.10.0/go.mod h1:QtOMZByJVlibUT2h9afNDWRZ1G96gVywH8T5GUSb9IA= -cloud.google.com/go/security v1.12.0/go.mod h1:rV6EhrpbNHrrxqlvW0BWAIawFWq3X90SduMJdFwtLB8= -cloud.google.com/go/security v1.13.0/go.mod h1:Q1Nvxl1PAgmeW0y3HTt54JYIvUdtcpYKVfIB8AOMZ+0= -cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU= -cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc= -cloud.google.com/go/securitycenter v1.15.0/go.mod h1:PeKJ0t8MoFmmXLXWm41JidyzI3PJjd8sXWaVqg43WWk= -cloud.google.com/go/securitycenter v1.16.0/go.mod h1:Q9GMaLQFUD+5ZTabrbujNWLtSLZIZF7SAR0wWECrjdk= -cloud.google.com/go/securitycenter v1.18.1/go.mod h1:0/25gAzCM/9OL9vVx4ChPeM/+DlfGQJDwBy/UC8AKK0= -cloud.google.com/go/securitycenter v1.19.0/go.mod h1:LVLmSg8ZkkyaNy4u7HCIshAngSQ8EcIRREP3xBnyfag= -cloud.google.com/go/servicecontrol v1.4.0/go.mod h1:o0hUSJ1TXJAmi/7fLJAedOovnujSEvjKCAFNXPQ1RaU= -cloud.google.com/go/servicecontrol v1.5.0/go.mod h1:qM0CnXHhyqKVuiZnGKrIurvVImCs8gmqWsDoqe9sU1s= -cloud.google.com/go/servicecontrol v1.10.0/go.mod h1:pQvyvSRh7YzUF2efw7H87V92mxU8FnFDawMClGCNuAA= -cloud.google.com/go/servicecontrol v1.11.0/go.mod h1:kFmTzYzTUIuZs0ycVqRHNaNhgR+UMUpw9n02l/pY+mc= -cloud.google.com/go/servicecontrol v1.11.1/go.mod h1:aSnNNlwEFBY+PWGQ2DoM0JJ/QUXqV5/ZD9DOLB7SnUk= -cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs= -cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg= -cloud.google.com/go/servicedirectory v1.6.0/go.mod h1:pUlbnWsLH9c13yGkxCmfumWEPjsRs1RlmJ4pqiNjVL4= -cloud.google.com/go/servicedirectory v1.7.0/go.mod h1:5p/U5oyvgYGYejufvxhgwjL8UVXjkuw7q5XcG10wx1U= -cloud.google.com/go/servicedirectory v1.8.0/go.mod h1:srXodfhY1GFIPvltunswqXpVxFPpZjf8nkKQT7XcXaY= -cloud.google.com/go/servicedirectory v1.9.0/go.mod h1:29je5JjiygNYlmsGz8k6o+OZ8vd4f//bQLtvzkPPT/s= -cloud.google.com/go/servicemanagement v1.4.0/go.mod h1:d8t8MDbezI7Z2R1O/wu8oTggo3BI2GKYbdG4y/SJTco= -cloud.google.com/go/servicemanagement v1.5.0/go.mod h1:XGaCRe57kfqu4+lRxaFEAuqmjzF0r+gWHjWqKqBvKFo= -cloud.google.com/go/servicemanagement v1.6.0/go.mod h1:aWns7EeeCOtGEX4OvZUWCCJONRZeFKiptqKf1D0l/Jc= -cloud.google.com/go/servicemanagement v1.8.0/go.mod h1:MSS2TDlIEQD/fzsSGfCdJItQveu9NXnUniTrq/L8LK4= -cloud.google.com/go/serviceusage v1.3.0/go.mod h1:Hya1cozXM4SeSKTAgGXgj97GlqUvF5JaoXacR1JTP/E= -cloud.google.com/go/serviceusage v1.4.0/go.mod h1:SB4yxXSaYVuUBYUml6qklyONXNLt83U0Rb+CXyhjEeU= -cloud.google.com/go/serviceusage v1.5.0/go.mod h1:w8U1JvqUqwJNPEOTQjrMHkw3IaIFLoLsPLvsE3xueec= -cloud.google.com/go/serviceusage v1.6.0/go.mod h1:R5wwQcbOWsyuOfbP9tGdAnCAc6B9DRwPG1xtWMDeuPA= -cloud.google.com/go/shell v1.3.0/go.mod h1:VZ9HmRjZBsjLGXusm7K5Q5lzzByZmJHf1d0IWHEN5X4= -cloud.google.com/go/shell v1.4.0/go.mod h1:HDxPzZf3GkDdhExzD/gs8Grqk+dmYcEjGShZgYa9URw= -cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+qE2f9A= -cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos= -cloud.google.com/go/spanner v1.44.0/go.mod h1:G8XIgYdOK+Fbcpbs7p2fiprDw4CaZX63whnSMLVBxjk= -cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M= -cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= -cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= -cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= -cloud.google.com/go/speech v1.9.0/go.mod h1:xQ0jTcmnRFFM2RfX/U+rk6FQNUF6DQlydUSyoooSpco= -cloud.google.com/go/speech v1.14.1/go.mod h1:gEosVRPJ9waG7zqqnsHpYTOoAS4KouMRLDFMekpJ0J0= -cloud.google.com/go/speech v1.15.0/go.mod h1:y6oH7GhqCaZANH7+Oe0BhgIogsNInLlz542tg3VqeYI= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= -cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= -cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= -cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y= -cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4= -cloud.google.com/go/storage v1.49.0 h1:zenOPBOWHCnojRd9aJZAyQXBYqkJkdQS42dxL55CIMw= -cloud.google.com/go/storage v1.49.0/go.mod h1:k1eHhhpLvrPjVGfo0mOUPEJ4Y2+a/Hv5PiwehZI9qGU= -cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w= -cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I= -cloud.google.com/go/storagetransfer v1.7.0/go.mod h1:8Giuj1QNb1kfLAiWM1bN6dHzfdlDAVC9rv9abHot2W4= -cloud.google.com/go/storagetransfer v1.8.0/go.mod h1:JpegsHHU1eXg7lMHkvf+KE5XDJ7EQu0GwNJbbVGanEw= -cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= -cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= -cloud.google.com/go/talent v1.3.0/go.mod h1:CmcxwJ/PKfRgd1pBjQgU6W3YBwiewmUzQYH5HHmSCmM= -cloud.google.com/go/talent v1.4.0/go.mod h1:ezFtAgVuRf8jRsvyE6EwmbTK5LKciD4KVnHuDEFmOOA= -cloud.google.com/go/talent v1.5.0/go.mod h1:G+ODMj9bsasAEJkQSzO2uHQWXHHXUomArjWQQYkqK6c= -cloud.google.com/go/texttospeech v1.4.0/go.mod h1:FX8HQHA6sEpJ7rCMSfXuzBcysDAuWusNNNvN9FELDd8= -cloud.google.com/go/texttospeech v1.5.0/go.mod h1:oKPLhR4n4ZdQqWKURdwxMy0uiTS1xU161C8W57Wkea4= -cloud.google.com/go/texttospeech v1.6.0/go.mod h1:YmwmFT8pj1aBblQOI3TfKmwibnsfvhIBzPXcW4EBovc= -cloud.google.com/go/tpu v1.3.0/go.mod h1:aJIManG0o20tfDQlRIej44FcwGGl/cD0oiRyMKG19IQ= -cloud.google.com/go/tpu v1.4.0/go.mod h1:mjZaX8p0VBgllCzF6wcU2ovUXN9TONFLd7iz227X2Xg= -cloud.google.com/go/tpu v1.5.0/go.mod h1:8zVo1rYDFuW2l4yZVY0R0fb/v44xLh3llq7RuV61fPM= -cloud.google.com/go/trace v1.3.0/go.mod h1:FFUE83d9Ca57C+K8rDl/Ih8LwOzWIV1krKgxg6N0G28= -cloud.google.com/go/trace v1.4.0/go.mod h1:UG0v8UBqzusp+z63o7FK74SdFE+AXpCLdFb1rshXG+Y= -cloud.google.com/go/trace v1.8.0/go.mod h1:zH7vcsbAhklH8hWFig58HvxcxyQbaIqMarMg9hn5ECA= -cloud.google.com/go/trace v1.9.0/go.mod h1:lOQqpE5IaWY0Ixg7/r2SjixMuc6lfTFeO4QGM4dQWOk= -cloud.google.com/go/trace v1.11.2 h1:4ZmaBdL8Ng/ajrgKqY5jfvzqMXbrDcBsUGXOT9aqTtI= -cloud.google.com/go/trace v1.11.2/go.mod h1:bn7OwXd4pd5rFuAnTrzBuoZ4ax2XQeG3qNgYmfCy0Io= -cloud.google.com/go/translate v1.3.0/go.mod h1:gzMUwRjvOqj5i69y/LYLd8RrNQk+hOmIXTi9+nb3Djs= -cloud.google.com/go/translate v1.4.0/go.mod h1:06Dn/ppvLD6WvA5Rhdp029IX2Mi3Mn7fpMRLPvXT5Wg= -cloud.google.com/go/translate v1.5.0/go.mod h1:29YDSYveqqpA1CQFD7NQuP49xymq17RXNaUDdc0mNu0= -cloud.google.com/go/translate v1.6.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= -cloud.google.com/go/translate v1.7.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= -cloud.google.com/go/video v1.8.0/go.mod h1:sTzKFc0bUSByE8Yoh8X0mn8bMymItVGPfTuUBUyRgxk= -cloud.google.com/go/video v1.9.0/go.mod h1:0RhNKFRF5v92f8dQt0yhaHrEuH95m068JYOvLZYnJSw= -cloud.google.com/go/video v1.12.0/go.mod h1:MLQew95eTuaNDEGriQdcYn0dTwf9oWiA4uYebxM5kdg= -cloud.google.com/go/video v1.13.0/go.mod h1:ulzkYlYgCp15N2AokzKjy7MQ9ejuynOJdf1tR5lGthk= -cloud.google.com/go/video v1.14.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= -cloud.google.com/go/video v1.15.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= -cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= -cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4= -cloud.google.com/go/videointelligence v1.8.0/go.mod h1:dIcCn4gVDdS7yte/w+koiXn5dWVplOZkE+xwG9FgK+M= -cloud.google.com/go/videointelligence v1.9.0/go.mod h1:29lVRMPDYHikk3v8EdPSaL8Ku+eMzDljjuvRs105XoU= -cloud.google.com/go/videointelligence v1.10.0/go.mod h1:LHZngX1liVtUhZvi2uNS0VQuOzNi2TkY1OakiuoUOjU= -cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0= -cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo= -cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo= -cloud.google.com/go/vision/v2 v2.4.0/go.mod h1:VtI579ll9RpVTrdKdkMzckdnwMyX2JILb+MhPqRbPsY= -cloud.google.com/go/vision/v2 v2.5.0/go.mod h1:MmaezXOOE+IWa+cS7OhRRLK2cNv1ZL98zhqFFZaaH2E= -cloud.google.com/go/vision/v2 v2.6.0/go.mod h1:158Hes0MvOS9Z/bDMSFpjwsUrZ5fPrdwuyyvKSGAGMY= -cloud.google.com/go/vision/v2 v2.7.0/go.mod h1:H89VysHy21avemp6xcf9b9JvZHVehWbET0uT/bcuY/0= -cloud.google.com/go/vmmigration v1.2.0/go.mod h1:IRf0o7myyWFSmVR1ItrBSFLFD/rJkfDCUTO4vLlJvsE= -cloud.google.com/go/vmmigration v1.3.0/go.mod h1:oGJ6ZgGPQOFdjHuocGcLqX4lc98YQ7Ygq8YQwHh9A7g= -cloud.google.com/go/vmmigration v1.5.0/go.mod h1:E4YQ8q7/4W9gobHjQg4JJSgXXSgY21nA5r8swQV+Xxc= -cloud.google.com/go/vmmigration v1.6.0/go.mod h1:bopQ/g4z+8qXzichC7GW1w2MjbErL54rk3/C843CjfY= -cloud.google.com/go/vmwareengine v0.1.0/go.mod h1:RsdNEf/8UDvKllXhMz5J40XxDrNJNN4sagiox+OI208= -cloud.google.com/go/vmwareengine v0.2.2/go.mod h1:sKdctNJxb3KLZkE/6Oui94iw/xs9PRNC2wnNLXsHvH8= -cloud.google.com/go/vmwareengine v0.3.0/go.mod h1:wvoyMvNWdIzxMYSpH/R7y2h5h3WFkx6d+1TIsP39WGY= -cloud.google.com/go/vpcaccess v1.4.0/go.mod h1:aQHVbTWDYUR1EbTApSVvMq1EnT57ppDmQzZ3imqIk4w= -cloud.google.com/go/vpcaccess v1.5.0/go.mod h1:drmg4HLk9NkZpGfCmZ3Tz0Bwnm2+DKqViEpeEpOq0m8= -cloud.google.com/go/vpcaccess v1.6.0/go.mod h1:wX2ILaNhe7TlVa4vC5xce1bCnqE3AeH27RV31lnmZes= -cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE= -cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= -cloud.google.com/go/webrisk v1.6.0/go.mod h1:65sW9V9rOosnc9ZY7A7jsy1zoHS5W9IAXv6dGqhMQMc= -cloud.google.com/go/webrisk v1.7.0/go.mod h1:mVMHgEYH0r337nmt1JyLthzMr6YxwN1aAIEc2fTcq7A= -cloud.google.com/go/webrisk v1.8.0/go.mod h1:oJPDuamzHXgUc+b8SiHRcVInZQuybnvEW72PqTc7sSg= -cloud.google.com/go/websecurityscanner v1.3.0/go.mod h1:uImdKm2wyeXQevQJXeh8Uun/Ym1VqworNDlBXQevGMo= -cloud.google.com/go/websecurityscanner v1.4.0/go.mod h1:ebit/Fp0a+FWu5j4JOmJEV8S8CzdTkAS77oDsiSqYWQ= -cloud.google.com/go/websecurityscanner v1.5.0/go.mod h1:Y6xdCPy81yi0SQnDY1xdNTNpfY1oAgXUlcfN3B3eSng= -cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= -cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M= -cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA= -cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw= -cosmossdk.io/api v0.9.2 h1:9i9ptOBdmoIEVEVWLtYYHjxZonlF/aOVODLFaxpmNtg= -cosmossdk.io/api v0.9.2/go.mod h1:CWt31nVohvoPMTlPv+mMNCtC0a7BqRdESjCsstHcTkU= -cosmossdk.io/client/v2 v2.0.0-beta.7 h1:O0PfZL5kC3Sp54wZASLNihQ612Gd6duMp11aM9wawNg= -cosmossdk.io/client/v2 v2.0.0-beta.7/go.mod h1:TzwwrzeK+AfSVSESVEIOYO/9xuCh1fPv0HgeocmfVnM= -cosmossdk.io/collections v1.2.1 h1:mAlNMs5vJwkda4TA+k5q/43p24RVAQ/qyDrjANu3BXE= -cosmossdk.io/collections v1.2.1/go.mod h1:PSsEJ/fqny0VPsHLFT6gXDj/2C1tBOTS9eByK0+PBFU= -cosmossdk.io/core v0.11.3 h1:mei+MVDJOwIjIniaKelE3jPDqShCc/F4LkNNHh+4yfo= -cosmossdk.io/core v0.11.3/go.mod h1:9rL4RE1uDt5AJ4Tg55sYyHWXA16VmpHgbe0PbJc6N2Y= +cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE= +cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= +cloud.google.com/go/auth v0.20.0 h1:kXTssoVb4azsVDoUiF8KvxAqrsQcQtB53DcSgta74CA= +cloud.google.com/go/auth v0.20.0/go.mod h1:942/yi/itH1SsmpyrbnTMDgGfdy2BUqIKyd0cyYLc5Q= +cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= +cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= +cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= +cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= +cloud.google.com/go/iam v1.9.0 h1:89wyjxT6DL4b5rk/Nk8eBC9DHqf+JiMstrn5IEYxFw4= +cloud.google.com/go/iam v1.9.0/go.mod h1:KP+nKGugNJW4LcLx1uEZcq1ok5sQHFaQehQNl4QDgV4= +cloud.google.com/go/logging v1.15.0 h1:6ooUEBNT6jdWh2b36+iuPn6b/R9qN/tHCbvGS5255gg= +cloud.google.com/go/logging v1.15.0/go.mod h1:ZGKnpBaURITh+g/uom2VhbiFoFWvejcrHPDhxFtU/gI= +cloud.google.com/go/longrunning v0.10.0 h1:4OWvp1BjCvoeSZTog3sRFDu6j4IrI9TI4/Y9N+8h25g= +cloud.google.com/go/longrunning v0.10.0/go.mod h1:8nqFBPOO1U/XkhWl0I19AMZEphrHi73VNABIpKYaTwM= +cloud.google.com/go/monitoring v1.27.0 h1:BhYwMqao+e5Nn7JtWMM9m6zRtKtVUK6kJWMizXChkLU= +cloud.google.com/go/monitoring v1.27.0/go.mod h1:72NOVjJXHY/HBfoLT0+qlCZBT059+9VXLeAnL2PeeVM= +cloud.google.com/go/storage v1.62.1 h1:Os0G3XbUbjZumkpDUf2Y0rLoXJTCF1kU2kWUujKYXD8= +cloud.google.com/go/storage v1.62.1/go.mod h1:cpYz/kRVZ+UQAF1uHeea10/9ewcRbxGoGNKsS9daSXA= +cloud.google.com/go/trace v1.13.0 h1:RfqsqPOiSCG8ql50UZt5F65KrVa1zbY9mJrO7xvZfbE= +cloud.google.com/go/trace v1.13.0/go.mod h1:r+bdAn16dKLSV1G2D5v3e58IlQlizfxWrUfjx7kM7X0= +cosmossdk.io/api v1.0.0 h1:qTV8OPVEwcBPwp2b9p4Qy4noZyihJ+sOMaWL/VT+RCc= +cosmossdk.io/api v1.0.0/go.mod h1:fKRljeYk+04p4T8Shdyv+uH2fSVyzHoWrvDAs/7OxfI= +cosmossdk.io/client/v2 v2.0.0-beta.10.0.20260227212600-39d4711b8970 h1:hRL2KLqyVnbOfb2UzNQUZ0IXdL8TsHSGeYyF3tbcfcM= +cosmossdk.io/client/v2 v2.0.0-beta.10.0.20260227212600-39d4711b8970/go.mod h1:cgdrvgMJ23AzeYIXQtcIyw283R9heNuGXHoHYJ5KvdM= +cosmossdk.io/collections v1.4.0 h1:b373bkxCxKiRbapxZ42TRmcKJEnBVBebdQVk9I5IkkE= +cosmossdk.io/collections v1.4.0/go.mod h1:gxbieVY3tjbvWlkm3yOXf7sGyDrVi12haZH+sek6whw= +cosmossdk.io/core v1.1.0 h1:iJ7j2DjNsFzg4/z4ImNQYzy2D4LfMCsaQ8Lrz1KCmxk= +cosmossdk.io/core v1.1.0/go.mod h1:qGmJxBFHobvG1k4bROQnueslotBU5MIKZLC57xVBYYI= 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.1 h1:YXNwAgbDwMEKwDlCdH8vPcoggma48MgZrTQXCfmMBeI= -cosmossdk.io/log v1.6.1/go.mod h1:gMwsWyyDBjpdG9u2avCFdysXqxq28WJapJvu+vF1y+E= +cosmossdk.io/errors v1.1.0 h1:X2DSt9JYgH7cuiaDr318aUqIl2z5Lfo/PdGzAtmczUU= +cosmossdk.io/errors v1.1.0/go.mod h1:lnjBmx7etZpMTLnxdspZupH0d9HGRWZhiezDZX2ayyI= +cosmossdk.io/log/v2 v2.1.0 h1:oWLWqZ1UObWu5hIS3dvTW7QyjtvlmSzC3LOy04U/hVI= +cosmossdk.io/log/v2 v2.1.0/go.mod h1:zDNpuRD2sWw4zuw1lZYg/jxKftVG+VizgcWAWkIorwY= 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= cosmossdk.io/schema v1.1.0/go.mod h1:Gb7pqO+tpR+jLW5qDcNOSv0KtppYs7881kfzakguhhI= -cosmossdk.io/store v1.1.2 h1:3HOZG8+CuThREKv6cn3WSohAc6yccxO3hLzwK6rBC7o= -cosmossdk.io/store v1.1.2/go.mod h1:60rAGzTHevGm592kFhiUVkNC9w7gooSEn5iUBPzHQ6A= cosmossdk.io/tools/confix v0.1.2 h1:2hoM1oFCNisd0ltSAAZw2i4ponARPmlhuNu3yy0VwI4= cosmossdk.io/tools/confix v0.1.2/go.mod h1:7XfcbK9sC/KNgVGxgLM0BrFbVcR/+6Dg7MFfpx7duYo= -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 v0.14.0 h1:hB3O25kIcyDW/7kMTLMaO8Ripj3yqs5imceVd6c/heA= -cosmossdk.io/x/tx v0.14.0/go.mod h1:Tn30rSRA1PRfdGB3Yz55W4Sn6EIutr9xtMKSHij+9PM= -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= -gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= -git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= +filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo= +filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc= 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/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/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= +github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/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/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= @@ -660,37 +56,33 @@ github.com/DataDog/datadog-go v4.8.3+incompatible h1:fNGaYSuObuQb5nzeTQqowRAd9bp 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.29.0 h1:UQUsRi8WTzhZntp5313l+CHIAT95ojUI2lpP/ExlZa4= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0/go.mod h1:Cz6ft6Dkn3Et6l2v2a9/RpN7epQ1GtDlO6lj8bEcOvw= -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/cloudmock v0.48.1 h1:oTX4vsorBZo/Zdum6OKPA4o7544hm6smoRv1QjpTwGo= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.48.1/go.mod h1:0wEl7vrAD8mehJyohS9HZy+WyEOaQO2mJx86Cvh93kM= -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/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.32.0 h1:rIkQfkCOVKc1OiRCNcSDD8ml5RJlZbH/Xsq7lbpynwc= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.32.0/go.mod h1:RD2SsorTmYhF6HkTmDw7KmPYQk8OBYwTkuasChwv7R4= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.56.0 h1:O2sXMyJh8b7devAGdE+163xtRurt0RVpB6DIzX5vGfg= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.56.0/go.mod h1:hEpiGU18xf70qb3jbTcIggWAiEfX/cOIVc2OTe4OegA= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.56.0 h1:ZIT85vKP7LBS84XJ0WdJ3dPOX3iz4j3c0+lpajGQMyo= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.56.0/go.mod h1:rqP9UEhOXv9WhQ7Gjz+G5y/pf8+BJZW5/Ts0AhE0PwE= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.56.0 h1:0YP0+/ixwu+Uqeu/FGiBZNQ19huiUxxiPXIc9WsLKuQ= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.56.0/go.mod h1:6ZZMQhZKDvUvkJw2rc+oDP90tMMzuU/J+5HG1ZmPOmE= 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= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260116142910-60249400e523 h1:pQUezn45oyv/8VcOQvPCg2851EIIusY0YKkJhAXsy2I= +github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260116142910-60249400e523/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI= +github.com/RoaringBitmap/roaring/v2 v2.18.0 h1:h7sS0VqCkfBMGgcHaudJFB4FE6Td71H6svRB2poRnGY= +github.com/RoaringBitmap/roaring/v2 v2.18.0/go.mod h1:eq4wdNXxtJIS/oikeCzdX1rBzek7ANzbth041hrU8Q4= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= -github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= -github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI= -github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI= +github.com/VictoriaMetrics/fastcache v1.13.0 h1:AW4mheMR5Vd9FkAPUv+NH6Nhw+fmbTMGMsNAoA/+4G0= +github.com/VictoriaMetrics/fastcache v1.13.0/go.mod h1:hHXhl4DA2fTL2HTZDJFXWgW0LNjo6B+4aj2Wmng3TjU= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= -github.com/adlio/schema v1.3.6 h1:k1/zc2jNfeiZBA5aFTRy37jlBIuCkXCm0XmvpzCKI9I= -github.com/adlio/schema v1.3.6/go.mod h1:qkxwLgPBd1FgLRHYVCmQT/rrBr3JH38J9LjmVzWNudg= +github.com/adlio/schema v1.4.0 h1:dekxG6P0my/bPvlyWzMULelR2Xej8RGErlnJcoY5ddw= +github.com/adlio/schema v1.4.0/go.mod h1:3/ojUldWBCWp4e+6VN9ets6unG5WdqbjF7vyzM0zTVQ= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= -github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= -github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= -github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= -github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -698,13 +90,9 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0= -github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= @@ -712,11 +100,48 @@ 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.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= -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/aws/aws-sdk-go-v2 v1.41.6 h1:1AX0AthnBQzMx1vbmir3Y4WsnJgiydmnJjiLu+LvXOg= +github.com/aws/aws-sdk-go-v2 v1.41.6/go.mod h1:dy0UzBIfwSeot4grGvY1AqFWN5zgziMmWGzysDnHFcQ= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.9 h1:adBsCIIpLbLmYnkQU+nAChU5yhVTvu5PerROm+/Kq2A= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.9/go.mod h1:uOYhgfgThm/ZyAuJGNQ5YgNyOlYfqnGpTHXvk3cpykg= +github.com/aws/aws-sdk-go-v2/config v1.32.14 h1:opVIRo/ZbbI8OIqSOKmpFaY7IwfFUOCCXBsUpJOwDdI= +github.com/aws/aws-sdk-go-v2/config v1.32.14/go.mod h1:U4/V0uKxh0Tl5sxmCBZ3AecYny4UNlVmObYjKuuaiOo= +github.com/aws/aws-sdk-go-v2/credentials v1.19.14 h1:n+UcGWAIZHkXzYt87uMFBv/l8THYELoX6gVcUvgl6fI= +github.com/aws/aws-sdk-go-v2/credentials v1.19.14/go.mod h1:cJKuyWB59Mqi0jM3nFYQRmnHVQIcgoxjEMAbLkpr62w= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21 h1:NUS3K4BTDArQqNu2ih7yeDLaS3bmHD0YndtA6UP884g= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21/go.mod h1:YWNWJQNjKigKY1RHVJCuupeWDrrHjRqHm0N9rdrWzYI= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.22 h1:GmLa5Kw1ESqtFpXsx5MmC84QWa/ZrLZvlJGa2y+4kcQ= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.22/go.mod h1:6sW9iWm9DK9YRpRGga/qzrzNLgKpT2cIxb7Vo2eNOp0= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.22 h1:dY4kWZiSaXIzxnKlj17nHnBcXXBfac6UlsAx2qL6XrU= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.22/go.mod h1:KIpEUx0JuRZLO7U6cbV204cWAEco2iC3l061IxlwLtI= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 h1:qYQ4pzQ2Oz6WpQ8T3HvGHnZydA72MnLuFK9tJwmrbHw= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6/go.mod h1:O3h0IK87yXci+kg6flUKzJnWeziQUKciKrLjcatSNcY= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.23 h1:FPXsW9+gMuIeKmz7j6ENWcWtBGTe1kH8r9thNt5Uxx4= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.23/go.mod h1:7J8iGMdRKk6lw2C+cMIphgAnT8uTwBwNOsGkyOCm80U= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.8 h1:HtOTYcbVcGABLOVuPYaIihj6IlkqubBwFj10K5fxRek= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.8/go.mod h1:VsK9abqQeGlzPgUr+isNWzPlK2vKe9INMLWnY65f5Xs= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.14 h1:xnvDEnw+pnj5mctWiYuFbigrEzSm35x7k4KS/ZkCANg= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.14/go.mod h1:yS5rNogD8e0Wu9+l3MUwr6eENBzEeGejvINpN5PAYfY= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.22 h1:PUmZeJU6Y1Lbvt9WFuJ0ugUK2xn6hIWUBBbKuOWF30s= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.22/go.mod h1:nO6egFBoAaoXze24a2C0NjQCvdpk8OueRoYimvEB9jo= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.22 h1:SE+aQ4DEqG53RRCAIHlCf//B2ycxGH7jFkpnAh/kKPM= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.22/go.mod h1:ES3ynECd7fYeJIL6+oax+uIEljmfps0S70BaQzbMd/o= +github.com/aws/aws-sdk-go-v2/service/s3 v1.100.0 h1:7G26Sae6PMKn4kMcU5JzNfrm1YrKwyOhowXPYR2WiWY= +github.com/aws/aws-sdk-go-v2/service/s3 v1.100.0/go.mod h1:Fw9aqhJicIVee1VytBBjH+l+5ov6/PhbtIK/u3rt/ls= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.9 h1:QKZH0S178gCmFEgst8hN0mCX1KxLgHBKKY/CLqwP8lg= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.9/go.mod h1:7yuQJoT+OoH8aqIxw9vwF+8KpvLZ8AWmvmUWHsGQZvI= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.15 h1:lFd1+ZSEYJZYvv9d6kXzhkZu07si3f+GQ1AaYwa2LUM= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.15/go.mod h1:WSvS1NLr7JaPunCXqpJnWk1Bjo7IxzZXrZi1QQCkuqM= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.19 h1:dzztQ1YmfPrxdrOiuZRMF6fuOwWlWpD2StNLTceKpys= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.19/go.mod h1:YO8TrYtFdl5w/4vmjL8zaBSsiNp3w0L1FfKVKenZT7w= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.10 h1:p8ogvvLugcR/zLBXTXrTkj0RYBUdErbMnAFFp12Lm/U= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.10/go.mod h1:60dv0eZJfeVXfbT1tFJinbHrDfSJ2GZl4Q//OSSNAVw= +github.com/aws/smithy-go v1.25.0 h1:Sz/XJ64rwuiKtB6j98nDIPyYrV1nVNJ4YU74gttcl5U= +github.com/aws/smithy-go v1.25.0/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= +github.com/benbjohnson/clock v1.3.5/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= @@ -726,10 +151,8 @@ github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ 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/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= -github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/bits-and-blooms/bitset v1.24.4 h1:95H15Og1clikBrKr/DuzMXkQzECs1M6hhoGXLwLQOZE= +github.com/bits-and-blooms/bitset v1.24.4/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= @@ -737,8 +160,8 @@ github.com/btcsuite/btcd v0.24.2 h1:aLmxPguqxza+4ag8R1I2nnJjSu2iFn/kqtHTIImswcY= github.com/btcsuite/btcd v0.24.2/go.mod h1:5C8ChTkl5ejr3WHj8tkQSCmydiMEPB0ZhQhehpq7Dgg= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= -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/btcec/v2 v2.3.5 h1:dpAlnAwmT1yIBm3exhT1/8iUSD98RDJM5vqJVQDQLiU= +github.com/btcsuite/btcd/btcec/v2 v2.3.5/go.mod h1:m22FrOAiuxl/tht9wIqAoGHcbnCCaPWyauO8y2LGGtQ= github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= @@ -757,32 +180,28 @@ github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -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/gopkg v0.1.4 h1:oZnQwnX82KAIWb7033bEwtxvTqXcYMxDBaQxo5JJHWM= +github.com/bytedance/gopkg v0.1.4/go.mod h1:v1zWfPm21Fb+OsyXN2VAHdL6TBb2L88anLQgdyje6R4= github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= -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.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA= -github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= +github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE= +github.com/bytedance/sonic v1.15.0/go.mod h1:tFkWrPz0/CUCLEF4ri4UkHekCIcdnkqXw9VduqpJh0k= +github.com/bytedance/sonic/loader v0.5.1 h1:Ygpfa9zwRCCKSlrp5bBP/b/Xzc3VxsAW+5NIYXrOOpI= +github.com/bytedance/sonic/loader v0.5.1/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= 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= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= +github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -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/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -801,188 +220,179 @@ github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6D github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4= -github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= -github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= +github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M= +github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 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-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/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/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 h1:aBangftG7EVZoUb69Os8IaYg++6uMOdKK83QtkkvJik= +github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2/go.mod h1:qwXFYgsP6T7XnJtbKlf1HP8AjxZZyzxMmc+Lq5GjlU4= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= 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/errors v1.13.0 h1:BoCcJeiP9hpBJDETkX19qi8Tb8So37srSsp3stTaDMQ= +github.com/cockroachdb/errors v1.13.0/go.mod h1:bjxt/4E5+OyuAnacpTIU9rn2mzPu1VlthvHP+xpROq0= +github.com/cockroachdb/fifo v0.0.0-20240816210425-c5d0cb0b6fc0 h1:pU88SPhIFid6/k0egdR5V6eALQYq2qbSmukrkgIh/0A= +github.com/cockroachdb/fifo v0.0.0-20240816210425-c5d0cb0b6fc0/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 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= -github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= +github.com/cockroachdb/redact v1.1.8 h1:8eVLLj6juKxiKrAEw2b8cJvNqWq++U8WOfQFuL7KTaA= +github.com/cockroachdb/redact v1.1.8/go.mod h1:GceHHpJ0rMDpYARL5In88Alq/xMBUtVlz7Qxix6ZVkw= +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 v0.14.1 h1:SxoamPghqICBAIcGpleHbmoPqy+crij/++eZz3DlerQ= -github.com/cometbft/cometbft-db v0.14.1/go.mod h1:KHP1YghilyGV/xjD5DP3+2hyigWx0WTp9X+0Gnx0RxQ= -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/cometbft/cometbft v0.39.3 h1:UegHXskZNomsijmm29nL5NkeXtnzkme6fg+q1hPQnEI= +github.com/cometbft/cometbft v0.39.3/go.mod h1:PmNfvtw256BC41ad0FABts236CSZnvZ0kjPOciBwTdM= +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/consensys/gnark-crypto v0.18.1 h1:RyLV6UhPRoYYzaFnPQA4qK3DyuDgkTgskDdoGqFt3fI= +github.com/consensys/gnark-crypto v0.18.1/go.mod h1:L3mXGFTe1ZN+RSJ+CLjUt9x7PNdx8ubaYfDROyp2Z8c= +github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4= +github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= +github.com/cosmos/btree v0.0.0-20250924232609-2c6195d95951 h1:dC3GJcS8bJiSEe7VAFDDFgFnVM1G9nBdGOgqJsmsZwM= +github.com/cosmos/btree v0.0.0-20250924232609-2c6195d95951/go.mod h1:jBbTdUWhSZClZWoDg54VnvV7/54modSOzDN7VXftj1A= +github.com/cosmos/btree v1.0.0 h1:V3OdIzTQw2yE7f6pD6FfA9j2/YLj1UpB9MdY0zU3v3k= +github.com/cosmos/btree v1.0.0/go.mod h1:BZML+flLn4d3MOa4POmzDWf5HQ7EGh0y1OLlfhh7A0k= github.com/cosmos/cosmos-db v1.1.3 h1:7QNT77+vkefostcKkhrzDK9uoIEryzFrU9eoMeaQOPY= github.com/cosmos/cosmos-db v1.1.3/go.mod h1:kN+wGsnwUJZYn8Sy5Q2O0vCYA99MJllkKASbs6Unb9U= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= -github.com/cosmos/cosmos-sdk v0.53.4 h1:kPF6vY68+/xi1/VebSZGpoxQqA52qkhUzqkrgeBn3Mg= -github.com/cosmos/cosmos-sdk v0.53.4/go.mod h1:7U3+WHZtI44dEOnU46+lDzBb2tFh1QlMvi8Z5JugopI= +github.com/cosmos/cosmos-sdk v0.54.3 h1:oUxbIACmHZV13IZXl59y+mIEOCFlUAjXV9p1rqrYcEg= +github.com/cosmos/cosmos-sdk v0.54.3/go.mod h1:Unt21RO+q1EebU6gcUPKYVzpAQSr4KIHjaOmjpz2twA= +github.com/cosmos/cosmos-sdk/store/v2 v2.0.0 h1:5CFXBU5cHIvxMpz5QBrTwR5DL/W3uZL2BYYMoDp4siY= +github.com/cosmos/cosmos-sdk/store/v2 v2.0.0/go.mod h1:XyRyi5fGjIcokBqS1cyA8/QVbVNy4ui8hmpk1gezuHo= 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 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/go-ethereum v1.17.2-cosmos-0 h1:V1vadF7/miUwwbNh3iiqNM51aHAG/5mzRCeIdcdostw= +github.com/cosmos/go-ethereum v1.17.2-cosmos-0/go.mod h1:KHcRXfGOUfUmKg51IhQ0IowiqZ6PqZf08CMtk0g5K1o= 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= -github.com/cosmos/gogoproto v1.7.0 h1:79USr0oyXAbxg3rspGh/m4SWNyoz/GLaAh0QlCe2fro= -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/v10 v10.3.1-0.20250909102629-ed3b125c7b6f h1:I5t5Tuewh6E9icYCtS4aSwyzIEvr2iBods08Hq+GBME= -github.com/cosmos/ibc-go/v10 v10.3.1-0.20250909102629-ed3b125c7b6f/go.mod h1:a74pAPUSJ7NewvmvELU74hUClJhwnmm5MGbEaiTw/kE= +github.com/cosmos/gogoproto v1.7.2 h1:5G25McIraOC0mRFv9TVO139Uh3OklV2hczr13KKVHCA= +github.com/cosmos/gogoproto v1.7.2/go.mod h1:8S7w53P1Y1cHwND64o0BnArT6RmdgIvsBuco6uTllsk= +github.com/cosmos/iavl v1.2.8 h1:55F96BGUJ7KT7h+Ky/cEqS+pEvhFqsU4O8Th3F0N1js= +github.com/cosmos/iavl v1.2.8/go.mod h1:FRHN4tO+6crf0p2zsqye+nAbsMgiwdkxpWm18DyP6+Y= +github.com/cosmos/ibc-go/v11 v11.0.0 h1:9EIehi88hNP1cCU83NC+J8UXNn+05YZt9eqmnzCQLSg= +github.com/cosmos/ibc-go/v11 v11.0.0/go.mod h1:iWlzLuCu+ctVbQwoVf5z51HE5e/NE8/pwnLVVDmP++4= 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= github.com/cosmos/keyring v1.2.0/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= -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/cosmos/ledger-cosmos-go v1.0.0 h1:jNKW89nPf0vR0EkjHG8Zz16h6p3zqwYEOxlHArwgYtw= +github.com/cosmos/ledger-cosmos-go v1.0.0/go.mod h1:mGaw2wDOf+Z6SfRJsMGxU9DIrBa4du0MAiPlpPhLAOE= 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/creachadair/atomicfile v0.3.7 h1:wdg8+Isz07NDMi2yZQAoI1EKB9SxuDhvo5MUii/ZqlM= -github.com/creachadair/atomicfile v0.3.7/go.mod h1:lUrZrE/XjMA7rJY/n8dF7/sSpy6KjtPaxPbrDambthA= -github.com/creachadair/mds v0.22.1 h1:Wink9jeYR7brBbOkOTVZVrd6vyb5W4ZBRhlZd96TSgU= -github.com/creachadair/mds v0.22.1/go.mod h1:ArfS0vPHoLV/SzuIzoqTEZfoYmac7n9Cj8XPANHocvw= -github.com/creachadair/tomledit v0.0.28 h1:aQJVwcNTzx4SZ/tSbkyGE69w4YQ6Gn+xhHHKtqMZwuw= -github.com/creachadair/tomledit v0.0.28/go.mod h1:pqb2HRQi0lMu6MBiUmTk/0XQ+SmPtq2QbUrG+eiLP5w= +github.com/crate-crypto/go-eth-kzg v1.5.0 h1:FYRiJMJG2iv+2Dy3fi14SVGjcPteZ5HAAUe4YWlJygc= +github.com/crate-crypto/go-eth-kzg v1.5.0/go.mod h1:J9/u5sWfznSObptgfa92Jq8rTswn6ahQWEuiLHOjCUI= +github.com/creachadair/atomicfile v0.3.8 h1:PyMIBZHZunTF+2+OSJCUg4XWO9nh6NwIacUBtF6tdg8= +github.com/creachadair/atomicfile v0.3.8/go.mod h1:oZrfNyYdwMjCD+eKNqsnPmdnQ54z4ujOoYvNTZyuJ2A= +github.com/creachadair/mds v0.24.1 h1:bzL4ItCtAUxxO9KkotP0PVzlw4tnJicAcjPu82v2mGs= +github.com/creachadair/mds v0.24.1/go.mod h1:ArfS0vPHoLV/SzuIzoqTEZfoYmac7n9Cj8XPANHocvw= +github.com/creachadair/tomledit v0.0.29 h1:dB5CbdwJMpn/fmfAPTAAleXF/KJwY0Ggc1eL/zvZRgk= +github.com/creachadair/tomledit v0.0.29/go.mod h1:4SoTXxzHgvzHRMIJPw+o6zK/yXii4VjLrb6/3gCQnyA= 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.2.1 h1:dl9cBrupW8+r5250DYkYxocLeZ1Y4vB1kxgtjxw8GQs= -github.com/danieljoos/wincred v1.2.1/go.mod h1:uGaFL9fDn3OLTvzCGulzE+SzjEe5NGlh5FdCcyfPwps= +github.com/danieljoos/wincred v1.2.3 h1:v7dZC2x32Ut3nEfRH+vhoZGvN72+dQ/snVXo/vMFLdQ= +github.com/danieljoos/wincred v1.2.3/go.mod h1:6qqX0WNrS4RzPZ1tnroDzq9kY3fu1KwE7MRLQK4X0bs= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= +github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= +github.com/dchest/siphash v1.2.3 h1:QXwFc8cFOR2dSa/gE6o/HokBMWtLUaNDVd+22aKHeEA= +github.com/dchest/siphash v1.2.3/go.mod h1:0NvQU092bT0ipiFN++/rXm69QG9tVxLAlQHIXMPAkHc= 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.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= 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.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -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/decred/dcrd/dcrec/secp256k1/v4 v4.4.1 h1:5RVFMOWjMyRy8cARdy79nAmgYw3hK/4HUq48LQ6Wwqo= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.1/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/deepmap/oapi-codegen v1.6.0 h1:w/d1ntwh91XI0b/8ja7+u5SvA4IFfM0UNNLmiDR1gg0= github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M= 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.2.0 h1:kJrlajbXXL9DFTNuhhu9yCx7JJa4qpYWxtE8BzuWsEs= -github.com/dgraph-io/badger/v4 v4.2.0/go.mod h1:qfCqhPoWDFJRx1gp5QwwyGo8xk1lbHUxvK9nK0OGAak= -github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= -github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= +github.com/dgraph-io/badger/v4 v4.9.1 h1:DocZXZkg5JJHJPtUErA0ibyHxOVUDVoXLSCV6t8NC8w= +github.com/dgraph-io/badger/v4 v4.9.1/go.mod h1:5/MEx97uzdPUHR4KtkNt8asfI2T4JiEiQlV7kWUo8c0= +github.com/dgraph-io/ristretto/v2 v2.4.0 h1:I/w09yLjhdcVD2QV192UJcq8dPBaAJb9pOuMyNy0XlU= +github.com/dgraph-io/ristretto/v2 v2.4.0/go.mod h1:0KsrXtXvnv0EqnzyowllbVJB8yBonswa2lTCK2gGo9E= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -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/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da h1:aIftn67I1fkbMa512G+w+Pxci9hJPB8oMnkcP3iZF38= +github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -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-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94= +github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE= 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/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjUQYeC8R4ILzVcIe8+5edAJJnE= github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= +github.com/dunglas/httpsfv v1.1.0 h1:Jw76nAyKWKZKFrpMMcL76y35tOpYHqQPzHQiwDvpe54= +github.com/dunglas/httpsfv v1.1.0/go.mod h1:zID2mqw9mFsnt7YC3vYQ9/cjq30q41W+1AnDwH8TiMg= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dustin/go-humanize v1.0.0/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.7.0 h1:bnQc8+GMnidJZA8zc6lLEAb4xNrIqHwO+9TzqvtQZPo= -github.com/dvsekhvalnov/jose2go v1.7.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= +github.com/dvsekhvalnov/jose2go v1.8.0 h1:LqkkVKAlHFfH9LOEl5fe4p/zL02OhWE7pCufMBG2jLA= +github.com/dvsekhvalnov/jose2go v1.8.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= +github.com/ebitengine/purego v0.10.0 h1:QIw4xfpWT6GWTzaW5XEKy3HXoqrJGx1ijYHzTF0/ISU= +github.com/ebitengine/purego v0.10.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= -github.com/emicklei/dot v1.6.2 h1:08GN+DD79cy/tzN6uLCT84+2Wk9u+wvqP+Hkx/dIR8A= -github.com/emicklei/dot v1.6.2/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= +github.com/emicklei/dot v1.11.0 h1:zsrhCuFHAJge/aZIC4N4LdHy5tqYu4tWEaUzIwdYj4Y= +github.com/emicklei/dot v1.11.0/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= 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.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= -github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q= -github.com/envoyproxy/go-control-plane v0.13.4 h1:zEqyPVyku6IvWCFwux4x9RxkLOMUL+1vC9xUFv5l2/M= -github.com/envoyproxy/go-control-plane v0.13.4/go.mod h1:kDfuBlDVsSj2MjrLEtRWtHlsWIFcGyB2RMO44Dc5GZA= -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/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA= +github.com/envoyproxy/go-control-plane v0.14.0/go.mod h1:NcS5X47pLl/hfqxU70yPwL9ZMkUlwlKxtAohpi2wBEU= +github.com/envoyproxy/go-control-plane/envoy v1.37.0 h1:u3riX6BoYRfF4Dr7dwSOroNfdSbEPe9Yyl09/B6wBrQ= +github.com/envoyproxy/go-control-plane/envoy v1.37.0/go.mod h1:DReE9MMrmecPy+YvQOAOHNYMALuowAnbjjEMkkWOi6A= github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 h1:/G9QYbddjL25KvtKTv3an9lx6VBE2cnb8wp1vEGNYGI= github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= -github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= -github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= -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-verkle v0.2.2 h1:I2W0WjnrFUIzzVPwm8ykY+7pL2d4VhlsePn4j7cnFk8= -github.com/ethereum/go-verkle v0.2.2/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk= +github.com/envoyproxy/protoc-gen-validate v1.3.3 h1:MVQghNeW+LZcmXe7SY1V36Z+WFMDjpqGAGacLe2T0ds= +github.com/envoyproxy/protoc-gen-validate v1.3.3/go.mod h1:TsndJ/ngyIdQRhMcVVGDDHINPLWB7C82oDArY51KfB0= +github.com/ethereum/c-kzg-4844/v2 v2.1.6 h1:xQymkKCT5E2Jiaoqf3v4wsNgjZLY0lRSkZn27fRjSls= +github.com/ethereum/c-kzg-4844/v2 v2.1.6/go.mod h1:8HMkUZ5JRv4hpw/XUrYWSQNAUzhHMg2UDb/U+5m+XNw= +github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab h1:rvv6MJhy07IMfEKuARQ9TKojGqLVNxQajaXEp/BoqSk= +github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab/go.mod h1:IuLm4IsPipXKF7CW5Lzf68PIbZ5yl7FFd74l/E0o9A8= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= -github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/ferranbt/fastssz v0.1.4 h1:OCDB+dYDEQDvAgtAGnTSidK1Pe2tW3nFV40XyMkTeDY= github.com/ferranbt/fastssz v0.1.4/go.mod h1:Ea3+oeoRGGLGm5shYAeDgu6PGUlcvQhE2fILyD9+tGg= -github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg= +github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= @@ -994,25 +404,20 @@ github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4 github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= +github.com/gammazero/deque v1.2.0 h1:scEFO8Uidhw6KDU5qg1HA5fYwM0+us2qdeJqm43bitU= +github.com/gammazero/deque v1.2.0/go.mod h1:JVrR+Bj1NMQbPnYclvDlvSX0nVGReLrQZ0aUMuWLctg= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= -github.com/getsentry/sentry-go v0.32.0 h1:YKs+//QmwE3DcYtfKRH8/KyOOF/I6Qnx7qYGNHCGmCY= -github.com/getsentry/sentry-go v0.32.0/go.mod h1:CYNcMMz73YigoHljQRG+qPF+eMq8gG72XcGN/p71BAY= +github.com/getsentry/sentry-go v0.46.0 h1:mbdDaarbUdOt9X+dx6kDdntkShLEX3/+KyOsVDTPDj0= +github.com/getsentry/sentry-go v0.46.0/go.mod h1:evVbw2qotNUdYG8KxXbAdjOQWWvWIwKxpjdZZIvcIPw= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= 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-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= -github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= -github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= -github.com/go-fonts/liberation v0.2.0/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= -github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-jose/go-jose/v4 v4.1.1 h1:JYhSgy4mXXzAdF3nUx3ygx347LRXJRrpgyU3adRmkAI= -github.com/go-jose/go-jose/v4 v4.1.1/go.mod h1:BdsZGqgdO3b6tTc6LSE56wcDbMMLuPsw5d4ZD5f94kA= +github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= +github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= 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= @@ -1021,23 +426,19 @@ github.com/go-kit/kit v0.13.0/go.mod h1:phqEHMMUbyrCFCTgH48JueqrM3md2HcAZ8N3XE4F 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-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= -github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk= 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-logfmt/logfmt v0.6.1 h1:4hvbpePJKnIzH1B+8OR/JPbTx37NktoI9LE2QZBBkvE= +github.com/go-logfmt/logfmt v0.6.1/go.mod h1:EV2pOAQoZaT1ZXZbqDl5hrymndi4SY9ED9/z6CO0XAk= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= 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.2.6/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-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= -github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= @@ -1048,16 +449,14 @@ github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= -github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro= +github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= -github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= 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.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= @@ -1070,28 +469,12 @@ 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/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI= +github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= -github.com/golang/glog v1.2.5 h1:DrW6hGnjIhtvhOIiAKT6Psh/Kd/ldepEa81DKeiRJ5I= -github.com/golang/glog v1.2.5/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= 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-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= 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= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -1099,7 +482,6 @@ github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -1110,70 +492,37 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 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.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e h1:4bw4WeyTYPp0smaXiJZCNnLrvVBqirQVreixayXezGc= -github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs= +github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= -github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= -github.com/google/flatbuffers v24.3.25+incompatible h1:CX395cjN9Kke9mmalRoL3d81AtFUxJM+yDthflgJGkI= -github.com/google/flatbuffers v24.3.25+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/flatbuffers v25.2.10+incompatible h1:F3vclr7C3HpB1k9mxCGRMXq6FdUalZ6H/pNX4FP1v0Q= +github.com/google/flatbuffers v25.2.10+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.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.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0/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= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 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/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= -github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc= github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8= github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= @@ -1182,31 +531,12 @@ 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.3.0/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.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= -github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= -github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= -github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= -github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= -github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw= -github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= -github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= -github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= -github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= -github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= -github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= -github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= -github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= -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/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +github.com/googleapis/enterprise-certificate-proxy v0.3.14 h1:yh8ncqsbUY4shRD5dA6RlzjJaT4hi3kII+zYw8wmLb8= +github.com/googleapis/enterprise-certificate-proxy v0.3.14/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg= +github.com/googleapis/gax-go/v2 v2.22.0 h1:PjIWBpgGIVKGoCXuiCoP64altEJCj3/Ei+kSU5vlZD4= +github.com/googleapis/gax-go/v2 v2.22.0/go.mod h1:irWBbALSr0Sk3qlqb9SyJ1h68WjgeFuiOzI4Rqw5+aY= 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= @@ -1220,6 +550,10 @@ github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grafana/pyroscope-go v1.2.7 h1:VWBBlqxjyR0Cwk2W6UrE8CdcdD80GOFNutj0Kb1T8ac= +github.com/grafana/pyroscope-go v1.2.7/go.mod h1:o/bpSLiJYYP6HQtvcoVKiE9s5RiNgjYTj1DhiddP2Pc= +github.com/grafana/pyroscope-go/godeltaprof v0.1.9 h1:c1Us8i6eSmkW+Ez05d3co8kasnuOY813tbMN8i/a3Og= +github.com/grafana/pyroscope-go/godeltaprof v0.1.9/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU= github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0= github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -1230,10 +564,12 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= +github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.72 h1:vTCWu1wbdYo7PEZFem/rlr01+Un+wwVmI7wiegFdRLk= +github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.72/go.mod h1:Vn+BBgKQHVQYdVQ4NZDICE1Brb+JfaONyDHr3q07oQc= 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= @@ -1243,8 +579,8 @@ github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng 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-getter v1.8.6 h1:9sQboWULaydVphxc4S64oAI4YqpuCk7nPmvbk131ebY= +github.com/hashicorp/go-getter v1.8.6/go.mod h1:nVH12eOV2P58dIiL3rsU6Fh3wLeJEKBOJzhMmzlSWoo= 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= @@ -1254,12 +590,10 @@ github.com/hashicorp/go-metrics v0.5.4 h1:8mmPiIJkTPPEbAiV97IxdAGNdRdaWwVap1BU6e github.com/hashicorp/go-metrics v0.5.4/go.mod h1:CG5yz4NZ/AI/aQt9Ucm/vdBnbh7fvmv4lxZ350i+QQI= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-plugin v1.6.3 h1:xgHB+ZUSYeuJi96WtxEjzi23uh7YQpznjGh0U0UUrwg= -github.com/hashicorp/go-plugin v1.6.3/go.mod h1:MRobyh+Wc/nYy1V4KAXUiYfzxoYhs7V1mlH1Z7iY2h0= +github.com/hashicorp/go-plugin v1.7.0 h1:YghfQH/0QmPNc/AZMTFE3ac8fipZyZECHdDPshfk+mA= +github.com/hashicorp/go-plugin v1.7.0/go.mod h1:BExt6KEaIYx804z8k4gRzRLEvxKVb+kn0NMcihqOqb8= 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= @@ -1267,8 +601,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.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= -github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.9.0 h1:CeOIz6k+LoN3qX9Z0tyQrPtiB1DFYRPfCIBtaXPSCnA= +github.com/hashicorp/go-version v1.9.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= @@ -1284,8 +618,8 @@ 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/billy v0.0.0-20250707135307-f2f9b9aae7db h1:IZUYC/xb3giYwBLMnr8d0TGTzPKFGNTCGgGLoyeX330= +github.com/holiman/billy v0.0.0-20250707135307-f2f9b9aae7db/go.mod h1:xTEYN9KCHxuYHs+NmrmzFcnvHMzLLNiGFafCb1n3Mfg= 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= @@ -1298,11 +632,8 @@ 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/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= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ= github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPtwNr0l57L4f878wP8= @@ -1316,17 +647,19 @@ github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c h1:qSH github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 h1:W9WBk7wlPfJLvMCdtV4zPulc4uCPrlywQOmbFOhgQNU= github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= +github.com/ipfs/go-cid v0.5.0 h1:goEKKhaGm0ul11IHA7I6p1GmKz8kEYniqFopaB5Otwg= +github.com/ipfs/go-cid v0.5.0/go.mod h1:0L7vmeNXpQpUS9vt+yEARkJ8rOg43DF3iPgn4GIN0mk= 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/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= +github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= 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/jhump/protoreflect v1.18.0 h1:TOz0MSR/0JOZ5kECB/0ufGnC2jdsgZ123Rd/k4Z5/2w= +github.com/jhump/protoreflect v1.18.0/go.mod h1:ezWcltJIVF4zYdIFM+D/sHV4Oh5LNU08ORzCGfwvTz8= +github.com/jhump/protoreflect/v2 v2.0.0-beta.1 h1:Dw1rslK/VotaUGYsv53XVWITr+5RCPXfvvlGrM/+B6w= +github.com/jhump/protoreflect/v2 v2.0.0-beta.1/go.mod h1:D9LBEowZyv8/iSu97FU2zmXG3JxVTmNw21mu63niFzU= 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/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= 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= @@ -1339,35 +672,26 @@ github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u 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/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= 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= -github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= -github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= -github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= -github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= -github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE= +github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= -github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= -github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= -github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= +github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/koron/go-ssdp v0.0.6 h1:Jb0h04599eq/CY7rB5YEqPS83HmRfHP2azkxMN2rFtU= +github.com/koron/go-ssdp v0.0.6/go.mod h1:0R9LfRJGek1zWTjN3JUNlm5INCDYGpRDfAptnct63fI= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -1383,57 +707,79 @@ github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+ 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.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= -github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= -github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.12.3 h1:tTWxr2YLKwIvK90ZXEw8GP7UFHtcbTtty8zsI+YjrfQ= +github.com/lib/pq v1.12.3/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA= +github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= +github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= +github.com/libp2p/go-flow-metrics v0.2.0 h1:EIZzjmeOE6c8Dav0sNv35vhZxATIXWZg6j/C08XmmDw= +github.com/libp2p/go-flow-metrics v0.2.0/go.mod h1:st3qqfu8+pMfh+9Mzqb2GTiwrAGjIPszEjZmtksN8Jc= +github.com/libp2p/go-libp2p v0.47.0 h1:qQpBjSCWNQFF0hjBbKirMXE9RHLtSuzTDkTfr1rw0yc= +github.com/libp2p/go-libp2p v0.47.0/go.mod h1:s8HPh7mMV933OtXzONaGFseCg/BE//m1V34p3x4EUOY= +github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94= +github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8= +github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= +github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg= +github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= +github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM= +github.com/libp2p/go-netroute v0.3.0 h1:nqPCXHmeNmgTJnktosJ/sIef9hvwYCrsLxXmfNks/oc= +github.com/libp2p/go-netroute v0.3.0/go.mod h1:Nkd5ShYgSMS5MUKy/MU2T57xFoOKvvLR92Lic48LEyA= +github.com/libp2p/go-reuseport v0.4.0 h1:nR5KU7hD0WxXCJbmw7r2rhRYruNRl2koHw8fQscQm2s= +github.com/libp2p/go-reuseport v0.4.0/go.mod h1:ZtI03j/wO5hZVDFo2jKywN6bYKWLOy8Se6DrI2E1cLU= +github.com/libp2p/go-yamux/v5 v5.0.1 h1:f0WoX/bEF2E8SbE4c/k1Mo+/9z0O4oC/hWEA+nfYRSg= +github.com/libp2p/go-yamux/v5 v5.0.1/go.mod h1:en+3cdX51U0ZslwRdRLrvQsdayFt3TSUKvBGErzpWbU= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= -github.com/linxGnu/grocksdb v1.9.2 h1:O3mzvO0wuzQ9mtlHbDrShixyVjVbmuqTjFrzlf43wZ8= -github.com/linxGnu/grocksdb v1.9.2/go.mod h1:QYiYypR2d4v63Wj1adOOfzglnoII0gLj3PNh4fZkcFA= -github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= -github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= -github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o= +github.com/linxGnu/grocksdb v1.10.7 h1:fCi4qvZWo04VgFwGWmO8HQJgUVounJBy+C2TMVPU/ho= +github.com/linxGnu/grocksdb v1.10.7/go.mod h1:OLQKZwiKwaJiAVCsOzWKvwiLwfZ5Vz8Md5TYR7t7pM8= +github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e h1:Q6MvJtQK/iRcRtzAscm/zF23XxJlbECiGPyRicsX+Ak= +github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= +github.com/marcopolo/simnet v0.0.4 h1:50Kx4hS9kFGSRIbrt9xUS3NJX33EyPqHVmpXvaKLqrY= +github.com/marcopolo/simnet v0.0.4/go.mod h1:tfQF1u2DmaB6WHODMtQaLtClEf3a296CKQLq5gAsIS0= +github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= +github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -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-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4= +github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= 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/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mdp/qrterminal/v3 v3.2.1 h1:6+yQjiiOsSuXT5n9/m60E54vdgFsw0zhADHhHLrFet4= github.com/mdp/qrterminal/v3 v3.2.1/go.mod h1:jOTmXvnBsMy5xqLniO0R++Jmjs2sTm9dFSuQ5kpz/SU= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= -github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= -github.com/minio/highwayhash v1.0.3 h1:kbnuUMoHYyVl7szWjSxJnxw11k2U709jqFPPmIUyD6Q= -github.com/minio/highwayhash v1.0.3/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ= -github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= -github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= +github.com/miekg/dns v1.1.66 h1:FeZXOS3VCVsKnEAd+wBkjMC3D2K+ww66Cq3VnCINuJE= +github.com/miekg/dns v1.1.66/go.mod h1:jGFzBsSNbJw6z1HYut1RKBKHA9PBdxeHrZG8J+gC2WE= +github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= +github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms= +github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= +github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b/go.mod h1:lxPUiZwKoFL8DUUmalo2yJJUCxbPKtm8OKfqr2/FTNU= +github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdnNMiD9ZejrlswWrCpBEZgWOiTrc= +github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s= +github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= +github.com/minio/highwayhash v1.0.4 h1:asJizugGgchQod2ja9NJlGOWq4s7KsAWr5XUc9Clgl4= +github.com/minio/highwayhash v1.0.4/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= +github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= 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= @@ -1442,13 +788,42 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua 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/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs= +github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 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/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mr-tron/base58 v1.3.0 h1:K6Y13R2h+dku0wOqKtecgRnBUBPrZzLZy5aIj8lCcJI= +github.com/mr-tron/base58 v1.3.0/go.mod h1:2BuubE67DCSWwVfx37JWNG8emOC0sHEU4/HpcYgCLX8= +github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM= +github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw= 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/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= +github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= +github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= +github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= +github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= +github.com/multiformats/go-multiaddr v0.16.1 h1:fgJ0Pitow+wWXzN9do+1b8Pyjmo8m5WhGfzpL82MpCw= +github.com/multiformats/go-multiaddr v0.16.1/go.mod h1:JSVUmXDjsVFiW7RjIFMP7+Ev+h1DTbiJgVeTV/tcmP0= +github.com/multiformats/go-multiaddr-dns v0.4.1 h1:whi/uCLbDS3mSEUMb1MsoT4uzUeZB0N32yzufqS0i5M= +github.com/multiformats/go-multiaddr-dns v0.4.1/go.mod h1:7hfthtB4E4pQwirrz+J0CcDUfbWzTqEzVyYKKIKpgkc= +github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= +github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= +github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= +github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk= +github.com/multiformats/go-multicodec v0.9.1 h1:x/Fuxr7ZuR4jJV4Os5g444F7xC4XmyUaT/FWtE+9Zjo= +github.com/multiformats/go-multicodec v0.9.1/go.mod h1:LLWNMtyV5ithSBUo3vFIMaeDy+h3EbkMTek1m+Fybbo= +github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= +github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U= +github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= +github.com/multiformats/go-multistream v0.6.1 h1:4aoX5v6T+yWmc2raBHsTvzmFhOI8WVOer28DeBBEYdQ= +github.com/multiformats/go-multistream v0.6.1/go.mod h1:ksQf6kqHAb6zIsyw7Zm+gAuVo57Qbq84E27YlYqavqw= +github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= +github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -1464,17 +839,15 @@ github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= -github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= -github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a h1:dlRvE5fWabOchtH7znfiFCcOvmIYgOeAS5ifBXBlh9Q= -github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oasisprotocol/curve25519-voi v0.0.0-20251114093237-2ab5a27a1729 h1:yfQ2sO9WJXUAIUR+g7NUkxJSKCAFJcR5sUDu+ZmjTZI= +github.com/oasisprotocol/curve25519-voi v0.0.0-20251114093237-2ab5a27a1729/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= -github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= +github.com/oklog/run v1.2.0 h1:O8x3yXwah4A73hJdlrwo/2X6J62gE5qTMusH0dvz60E= +github.com/oklog/run v1.2.0/go.mod h1:mgDbKRSwPhJfesJ4PntqFUbKQRZ50NgmZTSPlFA0YFk= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= @@ -1492,10 +865,10 @@ github.com/onsi/gomega v1.38.0/go.mod h1:OcXcwId0b9QsE7Y49u+BTrL4IdKOBOKnD6VQNTJ 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= -github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= -github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= -github.com/opencontainers/runc v1.1.12 h1:BOIssBaW1La0/qbNZHXOOa71dZfZEQOzW7dqQf3phss= -github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma/O44Ekby9FK8= +github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= +github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= +github.com/opencontainers/runc v1.2.8 h1:RnEICeDReapbZ5lZEgHvj7E9Q3Eex9toYmaGBsbvU5Q= +github.com/opencontainers/runc v1.2.8/go.mod h1:cC0YkmZcuvr+rtBZ6T7NBoVbMGNAdLa/21vIElJDOzI= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= @@ -1512,6 +885,8 @@ github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIw github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= @@ -1519,40 +894,74 @@ github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8 github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 h1:oYW+YCJ1pachXTQmzR3rNLYGGz4g/UgFcjb28p/viDM= github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= -github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 h1:Dx7Ovyv/SFnMFw3fD4oEoeorXc6saIiQ23LrGLth0Gw= -github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= -github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= -github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= -github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= +github.com/petermattis/goid v0.0.0-20250813065127-a731cc31b4fe/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/petermattis/goid v0.0.0-20260113132338-7c7de50cc741 h1:KPpdlQLZcHfTMQRi6bFQ7ogNO0ltFT4PmtwTLW4W+14= +github.com/petermattis/goid v0.0.0-20260113132338-7c7de50cc741/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= 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/datachannel v1.5.10 h1:ly0Q26K1i6ZkGf42W7D4hQYR90pZwzFOjTq5AuCKk4o= +github.com/pion/datachannel v1.5.10/go.mod h1:p/jJfC9arb29W7WrxyKbepTU20CFgyx5oLo8Rs4Py/M= 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/dtls/v2 v2.2.12 h1:KP7H5/c1EiVAAKUmXyCzPiQe5+bCJrpOeKg/L05dunk= +github.com/pion/dtls/v2 v2.2.12/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE= +github.com/pion/dtls/v3 v3.1.2 h1:gqEdOUXLtCGW+afsBLO0LtDD8GnuBBjEy6HRtyofZTc= +github.com/pion/dtls/v3 v3.1.2/go.mod h1:Hw/igcX4pdY69z1Hgv5x7wJFrUkdgHwAn/Q/uo7YHRo= +github.com/pion/ice/v4 v4.0.10 h1:P59w1iauC/wPk9PdY8Vjl4fOFL5B+USq1+xbDcN6gT4= +github.com/pion/ice/v4 v4.0.10/go.mod h1:y3M18aPhIxLlcO/4dn9X8LzLLSma84cx6emMSu14FGw= +github.com/pion/interceptor v0.1.40 h1:e0BjnPcGpr2CFQgKhrQisBU7V3GXK6wrfYrGYaU6Jq4= +github.com/pion/interceptor v0.1.40/go.mod h1:Z6kqH7M/FYirg3frjGJ21VLSRJGBXB/KqaTIrdqnOic= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= +github.com/pion/logging v0.2.4 h1:tTew+7cmQ+Mc1pTBLKH2puKsOvhm32dROumOZ655zB8= +github.com/pion/logging v0.2.4/go.mod h1:DffhXTKYdNZU+KtJ5pyQDjvOAh/GsNSyv1lbkFbe3so= +github.com/pion/mdns/v2 v2.0.7 h1:c9kM8ewCgjslaAmicYMFQIde2H9/lrZpjBkN8VwoVtM= +github.com/pion/mdns/v2 v2.0.7/go.mod h1:vAdSYNAT0Jy3Ru0zl2YiW3Rm/fJCwIeM0nToenfOJKA= +github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= +github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= +github.com/pion/rtcp v1.2.15 h1:LZQi2JbdipLOj4eBjK4wlVoQWfrZbh3Q6eHtWtJBZBo= +github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0= +github.com/pion/rtp v1.8.19 h1:jhdO/3XhL/aKm/wARFVmvTfq0lC/CvN1xwYKmduly3c= +github.com/pion/rtp v1.8.19/go.mod h1:bAu2UFKScgzyFqvUKmbvzSdPr+NGbZtv6UB2hesqXBk= +github.com/pion/sctp v1.8.39 h1:PJma40vRHa3UTO3C4MyeJDQ+KIobVYRZQZ0Nt7SjQnE= +github.com/pion/sctp v1.8.39/go.mod h1:cNiLdchXra8fHQwmIoqw0MbLLMs+f7uQ+dGMG2gWebE= +github.com/pion/sdp/v3 v3.0.13 h1:uN3SS2b+QDZnWXgdr69SM8KB4EbcnPnPf2Laxhty/l4= +github.com/pion/sdp/v3 v3.0.13/go.mod h1:88GMahN5xnScv1hIMTqLdu/cOcUkj6a9ytbncwMCq2E= +github.com/pion/srtp/v3 v3.0.6 h1:E2gyj1f5X10sB/qILUGIkL4C2CqK269Xq167PbGCc/4= +github.com/pion/srtp/v3 v3.0.6/go.mod h1:BxvziG3v/armJHAaJ87euvkhHqWe9I7iiOy50K2QkhY= +github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4= +github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8= 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/stun/v3 v3.0.0 h1:4h1gwhWLWuZWOJIJR9s2ferRO+W3zA/b6ijOI6mKzUw= +github.com/pion/stun/v3 v3.0.0/go.mod h1:HvCN8txt8mwi4FBvS3EmDghW6aQJ24T+y+1TKjB5jyU= 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/v2 v2.2.4/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0= +github.com/pion/transport/v2 v2.2.10 h1:ucLBLE8nuxiHfvkFKnkDQRYWYfp8ejf4YBOPfaQpw6Q= +github.com/pion/transport/v2 v2.2.10/go.mod h1:sq1kSLWs+cHW9E+2fJP95QudkzbK7wscs8yYgQToO5E= github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0= +github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0= +github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo= +github.com/pion/transport/v4 v4.0.1 h1:sdROELU6BZ63Ab7FrOLn13M6YdJLY20wldXW2Cu2k8o= +github.com/pion/transport/v4 v4.0.1/go.mod h1:nEuEA4AD5lPdcIegQDpVLgNoDGreqM/YqmEx3ovP4jM= +github.com/pion/turn/v4 v4.0.2 h1:ZqgQ3+MjP32ug30xAbD6Mn+/K4Sxi3SdNOTFf+7mpps= +github.com/pion/turn/v4 v4.0.2/go.mod h1:pMMKP/ieNAG/fN5cZiN4SDuyKsXtNTr0ccN7IToA1zs= +github.com/pion/webrtc/v4 v4.1.2 h1:mpuUo/EJ1zMNKGE79fAdYNFZBX790KE7kQQpLMjjR54= +github.com/pion/webrtc/v4 v4.1.2/go.mod h1:xsCXiNAmMEjIdFxAYU0MbB3RwRieJsegSB2JZsGN+8U= 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/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= -github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= 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= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -1562,17 +971,16 @@ github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeD github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= -github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= +github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= +github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= -github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= @@ -1580,8 +988,8 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k= -github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18= +github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= +github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -1589,14 +997,19 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc= +github.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo= github.com/prysmaticlabs/gohashtree v0.0.4-beta h1:H/EbCuXPeTV3lpKeXGPpEV9gsUpkqOOVnWapUyeWro4= github.com/prysmaticlabs/gohashtree v0.0.4-beta/go.mod h1:BFdtALS+Ffhg3lGQIHv9HDWuHS8cTvHZzrHWxwOtGOs= +github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8= +github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII= +github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw= +github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU= +github.com/quic-go/webtransport-go v0.10.0 h1:LqXXPOXuETY5Xe8ITdGisBzTYmUOy5eSj+9n4hLTjHI= +github.com/quic-go/webtransport-go v0.10.0/go.mod h1:LeGIXr5BQKE3UsynwVBeQrU1TPrbh73MGoC6jd+V7ow= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= -github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 h1:bsUq1dX0N8AOIL7EB/X911+m4EHsnWEHeJ0c+3TTBrg= +github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= @@ -1609,23 +1022,22 @@ github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7 github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= -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/rs/zerolog v1.35.0 h1:VD0ykx7HMiMJytqINBsKcbLS+BJ4WYjz+05us+LRTdI= +github.com/rs/zerolog v1.35.0/go.mod h1:EjML9kdfa/RMA7h/6z6pYmq1ykOuA8/mjWaEvGI+jcw= 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/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= -github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= 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= -github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= +github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88eegjfxfHb4= +github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9tLLBmM4eneO6WwsI= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= -github.com/sasha-s/go-deadlock v0.3.5 h1:tNCOEEDG6tBqrNDOX35j/7hL5FcFViG6awUGROb2NsU= -github.com/sasha-s/go-deadlock v0.3.5/go.mod h1:bugP6EGbdGYObIlx7pUZtWqlvo8k9H6vCBBsiChJQ5U= +github.com/sasha-s/go-deadlock v0.3.9 h1:fiaT9rB7g5sr5ddNZvlwheclN9IP86eFW9WgqlEQV+w= +github.com/sasha-s/go-deadlock v0.3.9/go.mod h1:KuZj51ZFmx42q/mPaYbRk0P1xcwe697zsJKE03vD4/Y= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= -github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= +github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil/v4 v4.26.4 h1:B4SXVbcwTyrocPHEmWBC4uCYr4Xcu3MK1TXqbprAOWY= +github.com/shirou/gopsutil/v4 v4.26.4/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -1637,27 +1049,24 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1 github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= -github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= -github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= -github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= -github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= -github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE= -github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= +github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= +github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= +github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= +github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s= -github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0= +github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= +github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= 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.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= github.com/spf13/pflag v1.0.9/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/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= +github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= +github.com/spiffe/go-spiffe/v2 v2.6.0 h1:l+DolpxNWYgruGQVV0xsfeya3CsC7m8iBzDnMpsbLuo= +github.com/spiffe/go-spiffe/v2 v2.6.0/go.mod h1:gm2SeUoMZEtpnzPNs2Csc0D/gX33k1xIx7lEzqblHEs= 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= @@ -1665,8 +1074,9 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4= +github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -1680,31 +1090,34 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= -github.com/supranational/blst v0.3.14 h1:xNMoHRJOTwMn63ip6qoWJ2Ymgvj7E2b9jY2FAwY+qRo= -github.com/supranational/blst v0.3.14/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/supranational/blst v0.3.16 h1:bTDadT+3fK497EvLdWRQEjiGnUtzJ7jjIUMF0jqwYhE= +github.com/supranational/blst v0.3.16/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= 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/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI= -github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= +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/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= -github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= -github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= +github.com/tidwall/match v1.2.0 h1:0pt8FlkOwjN2fPt4bIl4BoNxb98gGHN2ObFEDkrfZnM= +github.com/tidwall/match v1.2.0/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= -github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= -github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= -github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= -github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/tklauser/go-sysconf v0.3.16 h1:frioLaCQSsF5Cy1jgRBrzr6t502KIIwQ0MArYICU0nA= +github.com/tklauser/go-sysconf v0.3.16/go.mod h1:/qNL9xxDhc7tx3HSRsLWNnuzbVfh3e7gh/BmM179nYI= +github.com/tklauser/numcpus v0.11.0 h1:nSTwhKH5e1dMNsCdVBukSZrURJRoHbSEQjdEbY+9RXw= +github.com/tklauser/numcpus v0.11.0/go.mod h1:z+LwcLq54uWZTX0u/bGobaV34u6V7KNlTZejzM6/3MQ= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= 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= @@ -1712,81 +1125,117 @@ github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2 github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= -github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -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/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY= +github.com/ulikunitz/xz v0.5.15/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/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= +github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU= +github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= 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.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= -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/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +github.com/zondax/golem v0.27.0 h1:IbBjGIXF3SoGOZHsILJvIM/F/ylwJzMcHAcggiqniPw= +github.com/zondax/golem v0.27.0/go.mod h1:AmorCgJPt00L8xN1VrMBe13PSifoZksnQ1Ge906bu4A= 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= -github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= +github.com/zondax/ledger-go v1.0.1 h1:Ks/2tz/dOF+dbRynfZ0dEhcdL1lqw43Sa0zMXHpQ3aQ= +github.com/zondax/ledger-go v1.0.1/go.mod h1:j7IgMY39f30apthJYMd1YsHZRqdyu4KbVmUp0nU78X0= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.4.0-alpha.1 h1:3yrqQzbRRPFPdOMWS/QQIVxVnzSkAZQYeWlZFv1kbj4= -go.etcd.io/bbolt v1.4.0-alpha.1/go.mod h1:S/Z/Nm3iuOnyO1W4XuFfPci51Gj6F1Hv0z8hisyYYOw= +go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo= +go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= 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.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -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/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.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= -go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0 h1:WDdP9acbMYjbKIyJUhTvtzj601sVJOqgWdUxSdR/Ysc= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0/go.mod h1:BLbf7zbNIONBLPwvFnwNHGj4zge8uTCM/UPIVW1Mq2I= -go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= -go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= -go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= -go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= -go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= -go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= -go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= -go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/contrib/bridges/otelslog v0.18.0 h1:hhPGP3zvvy1xWT9RTy970wlniSxFttBIsAK1gvMguJM= +go.opentelemetry.io/contrib/bridges/otelslog v0.18.0/go.mod h1:twJF7inoMza6kxMcF8JOdL3mPmtOZu7GEr34CUNE6Dg= +go.opentelemetry.io/contrib/detectors/gcp v1.43.0 h1:62yY3dT7/ShwOxzA0RsKRgshBmfElKI4d/Myu2OxDFU= +go.opentelemetry.io/contrib/detectors/gcp v1.43.0/go.mod h1:RyaZMFY7yi1kAs45S6mbFGz8O8rqB0dTY14uzvG4LCs= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 h1:0Qx7VGBacMm9ZENQ7TnNObTYI4ShC+lHI16seduaxZo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0/go.mod h1:Sje3i3MjSPKTSPvVWCaL8ugBzJwik3u4smCjUeuupqg= +go.opentelemetry.io/contrib/instrumentation/host v0.68.0 h1:0BfTRAHtFpIlIY7cw1qg9nODUwblutIqx7Cn6NPD+2s= +go.opentelemetry.io/contrib/instrumentation/host v0.68.0/go.mod h1:SmgEeGNt1+gp8bmzB5LLyUlCObWcWrRbYMIiDii3NH8= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 h1:CqXxU8VOmDefoh0+ztfGaymYbhdB/tT3zs79QaZTNGY= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0/go.mod h1:BuhAPThV8PBHBvg8ZzZ/Ok3idOdhWIodywz2xEcRbJo= +go.opentelemetry.io/contrib/instrumentation/runtime v0.68.0 h1:jhVIQEprwUTV+KfzzliLidclhoTOoHTgdz96kAyR8mU= +go.opentelemetry.io/contrib/instrumentation/runtime v0.68.0/go.mod h1:4HsdbLUbernaTnA8CNaNE+1g026SciXb3juRYe3l8EY= +go.opentelemetry.io/contrib/otelconf v0.23.0 h1:s3C7KdMYiutf4rC8hKFA0WOIDG+gIru8ajjQKS59ir8= +go.opentelemetry.io/contrib/otelconf v0.23.0/go.mod h1:0kN2tcccZS82e7IZlo045gkcL8/8dup1k25sf9ypGxM= +go.opentelemetry.io/contrib/propagators/autoprop v0.68.0 h1:wLGFvNBPqQhzBn0QRBZjrriH8lZ9gqtTz8ufHEjLg7k= +go.opentelemetry.io/contrib/propagators/autoprop v0.68.0/go.mod h1:evWK9nCqCzH8nhclTlpkdUzmxrmJQ2mrWCdKIvyOYec= +go.opentelemetry.io/contrib/propagators/aws v1.43.0 h1:EwnsB3cXRLAh7/Nr/9rMuGw73nfb3z6uAvVDjRrbeUg= +go.opentelemetry.io/contrib/propagators/aws v1.43.0/go.mod h1:CJjTym6F87tEdm61Qvnz5xrV8vKlH4C92djiqcn62k8= +go.opentelemetry.io/contrib/propagators/b3 v1.43.0 h1:CETqV3QLLPTy5yNrqyMr41VnAOOD4lsRved7n4QG00A= +go.opentelemetry.io/contrib/propagators/b3 v1.43.0/go.mod h1:Q4mCiCdziYzpNR0g+6UqVotAlCDZdzz6L8jwY4knOrw= +go.opentelemetry.io/contrib/propagators/jaeger v1.43.0 h1:peiLMz1+aqJE+3L4mOVtR9wlmv+yh/JVYXCBjqmzJJE= +go.opentelemetry.io/contrib/propagators/jaeger v1.43.0/go.mod h1:Agvif+4A8p/3UtZzJ0MCcDEuQwgtrzM71DueU41DCs8= +go.opentelemetry.io/contrib/propagators/ot v1.43.0 h1:Hh1HahlGc81AOE7siqi1tVOlbanY/UxMMWedpb0d5oQ= +go.opentelemetry.io/contrib/propagators/ot v1.43.0/go.mod h1:58MlyS7lghzYvAm5LN9gGmZpCMQEMB5vpZp9SRgOyE4= +go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= +go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.19.0 h1:Dn8rkudDzY6KV9dr/D/bTUuWgqDf9xe0rr4G2elrn0Y= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.19.0/go.mod h1:gMk9F0xDgyN9M/3Ed5Y1wKcx/9mlU91NXY2SNq7RQuU= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0 h1:HIBTQ3VO5aupLKjC90JgMqpezVXwFuq6Ryjn0/izoag= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0/go.mod h1:ji9vId85hMxqfvICA0Jt8JqEdrXaAkcpkI9HPXya0ro= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.43.0 h1:8UQVDcZxOJLtX6gxtDt3vY2WTgvZqMQRzjsqiIHQdkc= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.43.0/go.mod h1:2lmweYCiHYpEjQ/lSJBYhj9jP1zvCvQW4BqL9dnT7FQ= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0 h1:w1K+pCJoPpQifuVpsKamUdn9U0zM3xUziVOqsGksUrY= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0/go.mod h1:HBy4BjzgVE8139ieRI75oXm3EcDN+6GhD88JT1Kjvxg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 h1:88Y4s2C8oTui1LGM6bTWkw0ICGcOLCAI5l6zsD1j20k= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0/go.mod h1:Vl1/iaggsuRlrHf/hfPJPvVag77kKyvrLeD10kpMl+A= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 h1:RAE+JPfvEmvy+0LzyUA25/SGawPwIUbZ6u0Wug54sLc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0/go.mod h1:AGmbycVGEsRx9mXMZ75CsOyhSP6MFIcj/6dnG+vhVjk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 h1:3iZJKlCZufyRzPzlQhUIWVmfltrXuGyfjREgGP3UUjc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0/go.mod h1:/G+nUPfhq2e+qiXMGxMwumDrP5jtzU+mWN7/sjT2rak= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.19.0 h1:GJkybS+crDMdExT/BUNCEgfrmfboztcS6PhvSo88HKM= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.19.0/go.mod h1:NuAyxRYIG2lKX3YQkB+83StTxM7s52PUUkRRiC0wnYI= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.43.0 h1:TC+BewnDpeiAmcscXbGMfxkO+mwYUwE/VySwvw88PfA= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.43.0/go.mod h1:J/ZyF4vfPwsSr9xJSPyQ4LqtcTPULFR64KwTikGLe+A= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.43.0 h1:mS47AX77OtFfKG4vtp+84kuGSFZHTyxtXIN269vChY0= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.43.0/go.mod h1:PJnsC41lAGncJlPUniSwM81gc80GkgWJWr3cu2nKEtU= +go.opentelemetry.io/otel/log v0.19.0 h1:KUZs/GOsw79TBBMfDWsXS+KZ4g2Ckzksd1ymzsIEbo4= +go.opentelemetry.io/otel/log v0.19.0/go.mod h1:5DQYeGmxVIr4n0/BcJvF4upsraHjg6vudJJpnkL6Ipk= +go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= +go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= +go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= +go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= +go.opentelemetry.io/otel/sdk/log v0.19.0 h1:scYVLqT22D2gqXItnWiocLUKGH9yvkkeql5dBDiXyko= +go.opentelemetry.io/otel/sdk/log v0.19.0/go.mod h1:vFBowwXGLlW9AvpuF7bMgnNI95LiW10szrOdvzBHlAg= +go.opentelemetry.io/otel/sdk/log/logtest v0.19.0 h1:BEbF7ZBB6qQloV/Ub1+3NQoOUnVtcGkU3XX4Ws3GQfk= +go.opentelemetry.io/otel/sdk/log/logtest v0.19.0/go.mod h1:Lua81/3yM0wOmoHTokLj9y9ADeA02v1naRrVrkAZuKk= +go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= +go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= +go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= +go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= +go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g= +go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk= 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= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= +go.uber.org/dig v1.19.0 h1:BACLhebsYdpQ7IROQ1AGPjrXcP5dF80U3gKoFzbaq/4= +go.uber.org/dig v1.19.0/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE= +go.uber.org/fx v1.24.0 h1:wE8mruvpg2kiiL1Vqd0CC+tr0/24XIB10Iwp2lLWzkg= +go.uber.org/fx v1.24.0/go.mod h1:AmDeGyS+ZARGKM4tlH4FY2Jr63VjbEDJHtqXTGP5hbo= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko= -go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o= +go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= +go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= @@ -1796,101 +1245,58 @@ 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= +go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= +go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= +go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/arch v0.17.0 h1:4O3dfLzd+lQewptAHqjewQZQDyEdejz3VwgeYwkZneU= -golang.org/x/arch v0.17.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk= +golang.org/x/arch v0.26.0 h1:jZ6dpec5haP/fUv1kLCbuJy6dnRrfX6iVK08lZBFpk4= +golang.org/x/arch v0.26.0/go.mod h1:0X+GdSIP+kL5wPmpK7sdkEVTt2XoYP0cSjQSbZBwOi8= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 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.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= -golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= -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-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= +golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/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-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= -golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= -golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw= -golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM= -golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= +golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90 h1:jiDhWWeC7jfWqR9c/uplMOqJ0sbNlNWv0UkzE0vX1MA= +golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90/go.mod h1:xE1HEv6b+1SCZ5/uscMRjUBKtIxworgEcEi+/n9NQDQ= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.0.0-20220302094943-723b81ca9867/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -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.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI= +golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY= 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= @@ -1904,124 +1310,49 @@ golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= -golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= -golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= +golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= -golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= -golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= -golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= -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/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= +golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= 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= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= -golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= 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= @@ -2035,9 +1366,6 @@ golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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= @@ -2046,503 +1374,150 @@ golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7w 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= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/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-20210806184541-e5e7981a1069/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-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/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-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/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-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.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.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= -golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= +golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= +golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/telemetry v0.0.0-20260311193753-579e4da9a98c h1:6a8FdnNk6bTXBjR4AGKFgUKuo+7GnR3FX5L7CbveeZc= +golang.org/x/telemetry v0.0.0-20260311193753-579e4da9a98c/go.mod h1:TpUTTEp9frx7rTdLpC9gFG9kdI7zVLFTFFlqaH2Cncw= 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.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= -golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= -golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= -golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= -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.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= +golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/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.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= -golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= +golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.3.0/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/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= +golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= -golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= +golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s= +golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= -gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= -gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= -gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA= -gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= -gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= -gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= -gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= -gonum.org/v1/plot v0.10.1/go.mod h1:VZW5OlhkL1mysU9vaqNHnsy86inf6Ot+jB3r+BczCEo= +gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= +gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= -google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= -google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= -google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= -google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= -google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= -google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= -google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= -google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= -google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= -google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= -google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= -google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= -google.golang.org/api v0.77.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= -google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= -google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= -google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= -google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6FO2g= -google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= -google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= -google.golang.org/api v0.95.0/go.mod h1:eADj+UBuxkh5zlrSntJghuNeg8HwQ1w5lTKkuqaETEI= -google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.99.0/go.mod h1:1YOf74vkVndF7pG6hIHuINsM7eWwpVTAfNMNiL91A08= -google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= -google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo= -google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= -google.golang.org/api v0.106.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.107.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= -google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= -google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= -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/api v0.276.0 h1:nVArUtfLEihtW+b0DdcqRGK1xoEm2+ltAihyztq7MKY= +google.golang.org/api v0.276.0/go.mod h1:Fnag/EWUPIcJXuIkP1pjoTgS5vdxlk3eeemL7Do6bvw= 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= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= -google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= -google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= -google.golang.org/genproto v0.0.0-20220329172620-7be39ac1afc7/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220722212130-b98a9ff5e252/go.mod h1:GkXuJDJ6aQ7lnJcRF+SJVgFdQhypqgl3LB1C9vabdRE= -google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc= -google.golang.org/genproto v0.0.0-20220815135757-37a418bb8959/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220817144833-d7fd3f11b9b1/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220829144015-23454907ede3/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220829175752-36a9c930ecbf/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220913154956-18f8339a66a5/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220914142337-ca0e39ece12f/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220915135415-7fd63a7952de/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220916172020-2692e8806bfa/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220919141832-68c03719ef51/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar2npT/g4vkk7O0WYS1sHOHbdujxbEp7CJWbw= -google.golang.org/genproto v0.0.0-20220926165614-551eb538f295/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= -google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= -google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U= -google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= -google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= -google.golang.org/genproto v0.0.0-20221024153911-1573dae28c9c/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo= -google.golang.org/genproto v0.0.0-20221109142239-94d6d90a7d66/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221117204609-8f9c96812029/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221201204527-e3fa12d562f3/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE= -google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230112194545-e10362b5ecf9/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230113154510-dbe35b8444a5/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230123190316-2c411cf9d197/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230124163310-31e0e69b6fc2/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230125152338-dcaf20b6aeaa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230127162408-596548ed4efa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44/go.mod h1:8B0gmkoRebU8ukX6HP+4wrVQUY1+6PkQ44BSyIlflHA= -google.golang.org/genproto v0.0.0-20230222225845-10f96fb3dbec/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= -google.golang.org/genproto v0.0.0-20230223222841-637eb2293923/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= -google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA= -google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= -google.golang.org/genproto v0.0.0-20230320184635-7606e756e683/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= -google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= -google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 h1:ToEetK57OidYuqD4Q5w+vfEnPvPpuTwedCNVohYJfNk= -google.golang.org/genproto v0.0.0-20241118233622-e639e219e697/go.mod h1:JJrvXBWRZaFMxBufik1a4RpFw4HhgVtBBWQeQgUj2cc= -google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 h1:FiusG7LWj+4byqhbvmB+Q93B/mOxJLN2DTozDuZm4EU= -google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:kXqgZtrWaf6qS3jZOCnCH7WYfrvFjkC51bM8fz3RsCA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 h1:pFyd6EwwL2TqFf8emdthzeX+gZE1ElRq3iM8pui4KBY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto v0.0.0-20260414002931-afd174a4e478 h1:aLsVTW0lZ8+IY5u/ERjZSCvAmhuR7slKzyha3YikDNA= +google.golang.org/genproto v0.0.0-20260414002931-afd174a4e478/go.mod h1:YJAzKjfHIUHb9T+bfu8L7mthAp7VVXQBUs1PLdBWS7M= +google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 h1:yQugLulqltosq0B/f8l4w9VryjV+N/5gcW0jQ3N8Qec= +google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478/go.mod h1:C6ADNqOxbgdUUeRTU+LCHDPB9ttAMCTff6auwCVa4uc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 h1:RmoJA1ujG+/lRGNfUnOMfhCy5EipVMyvUE+KNbPbTlw= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= -google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= -google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= -google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= -google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= -google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4= -google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= +google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= +google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= 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= @@ -2556,13 +1531,10 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc= -google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= 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= @@ -2571,7 +1543,6 @@ gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8 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/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= -gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= 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= @@ -2599,59 +1570,18 @@ gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/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= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= -lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= -lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= -modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= -modernc.org/cc/v3 v3.36.2/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= -modernc.org/cc/v3 v3.36.3/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= -modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc= -modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw= -modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= -modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= -modernc.org/ccgo/v3 v3.16.8/go.mod h1:zNjwkizS+fIFDrDjIAgBSCLkWbJuHF+ar3QRn+Z9aws= -modernc.org/ccgo/v3 v3.16.9/go.mod h1:zNMzC9A9xeNUepy6KuZBbugn3c0Mc9TeiJO4lgvkJDo= -modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= -modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= -modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= -modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A= -modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU= -modernc.org/libc v1.16.17/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU= -modernc.org/libc v1.16.19/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= -modernc.org/libc v1.17.0/go.mod h1:XsgLldpP4aWlPlsjqKRdHPqCxCjISdHfM/yeWC5GyW0= -modernc.org/libc v1.17.1/go.mod h1:FZ23b+8LjxZs7XtFMbSzL/EhPxNbfZbErxEHc7cbD9s= -modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= -modernc.org/memory v1.2.0/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= -modernc.org/memory v1.2.1/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= -modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= -modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= -modernc.org/sqlite v1.18.1/go.mod h1:6ho+Gow7oX5V+OiOQ6Tr4xeqbx13UZ6t+Fw9IRUG4d4= -modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= -modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= -modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw= -modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= -modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8= +lukechampine.com/blake3 v1.4.1 h1:I3Smz7gso8w4/TunLKec6K2fn+kyKtDxr/xcQEN84Wg= +lukechampine.com/blake3 v1.4.1/go.mod h1:QFosUxmjB8mnrWFSNwKmvxHpfY72bmD2tQ0kBMM3kwo= 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/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +nhooyr.io/websocket v1.8.17 h1:KEVeLJkUywCKVsnLIDlD/5gtayKp8VoCkksHCGGfT9Y= +nhooyr.io/websocket v1.8.17/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c= +pgregory.net/rapid v1.3.0 h1:vBvO0VSqti75J1jjYqpgPNBLKMd1+gxa9fYo7vk/Exc= +pgregory.net/rapid v1.3.0/go.mod h1:dPlE4OBBxgXPqkP79flB6sJL1dx5azpI7HQ9MY9Z7uk= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/qr v0.2.0 h1:6vBLea5/NRMVTz8V66gipeLycZMl/+UlFmk8DvqQ6WY= rsc.io/qr v0.2.0/go.mod h1:IF+uZjkb9fqyeF/4tlBoynqmQxUoPfWEKh921coOuXs= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= diff --git a/evmd/mempool.go b/evmd/mempool.go index 7ed654b7..d6af75fa 100644 --- a/evmd/mempool.go +++ b/evmd/mempool.go @@ -1,17 +1,15 @@ package evmd import ( - "fmt" + evmmempool "github.com/cosmos/evm/mempool" + "github.com/cosmos/evm/server" + evmtypes "github.com/cosmos/evm/x/vm/types" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" "github.com/cosmos/cosmos-sdk/baseapp" servertypes "github.com/cosmos/cosmos-sdk/server/types" - sdkmempool "github.com/cosmos/cosmos-sdk/types/mempool" - - evmconfig "github.com/cosmos/evm/config" - evmmempool "github.com/cosmos/evm/mempool" - evmtypes "github.com/cosmos/evm/x/vm/types" + sdk "github.com/cosmos/cosmos-sdk/types" ) // configureEVMMempool sets up the EVM mempool and related handlers using viper configuration. @@ -21,50 +19,61 @@ func (app *EVMD) configureEVMMempool(appOpts servertypes.AppOptions, logger log. return nil } - cosmosPoolMaxTx := evmconfig.GetCosmosPoolMaxTx(appOpts, logger) + var ( + mpConfig = server.ResolveMempoolConfig(app.GetAnteHandler(), appOpts, logger) + + txEncoder = evmmempool.NewTxEncoder(app.txConfig) + evmRechecker = evmmempool.NewTxRechecker(mpConfig.AnteHandler, txEncoder) + cosmosRechecker = evmmempool.NewTxRechecker(mpConfig.AnteHandler, txEncoder) + cosmosPoolMaxTx = server.GetCosmosPoolMaxTx(appOpts, logger) + checkTxTimeout = server.GetMempoolCheckTxTimeout(appOpts, logger) + ) + if cosmosPoolMaxTx < 0 { - logger.Debug("app-side mempool is disabled, skipping evm mempool configuration") + logger.Debug("evm mempool is disabled, skipping configuration") return nil } - mempoolConfig, err := app.createMempoolConfig(appOpts, logger) - if err != nil { - return fmt.Errorf("failed to get mempool config: %w", err) + if err := server.ValidateReapBounds(appOpts, mpConfig.BlockGasLimit); err != nil { + return err } - evmMempool := evmmempool.NewExperimentalEVMMempool( + // create mempool + mempool := evmmempool.NewMempool( app.CreateQueryContext, logger, app.EVMKeeper, app.FeeMarketKeeper, app.txConfig, - app.clientCtx, - mempoolConfig, + evmRechecker, + cosmosRechecker, + mpConfig, cosmosPoolMaxTx, ) - app.EVMMempool = evmMempool - app.SetMempool(evmMempool) - checkTxHandler := evmmempool.NewCheckTxHandler(evmMempool) + + app.EVMMempool = mempool + + // create ABCI handlers + proposalHandler := baseapp.NewDefaultProposalHandler(mempool, NewNoCheckProposalTxVerifier(app.BaseApp)) + + insertTxHandler := mempool.NewInsertTxHandler(app.TxDecode) + reapTxsHandler := mempool.NewReapTxsHandler() + checkTxHandler := mempool.NewCheckTxHandler(app.TxDecode, checkTxTimeout) + + // set handlers and the mempool + app.SetPrepareProposal(proposalHandler.PrepareProposalHandler()) + app.SetProcessProposal(proposalHandler.ProcessProposalHandler()) + app.SetInsertTxHandler(insertTxHandler) + app.SetReapTxsHandler(reapTxsHandler) app.SetCheckTxHandler(checkTxHandler) - abciProposalHandler := baseapp.NewDefaultProposalHandler(evmMempool, app) - abciProposalHandler.SetSignerExtractionAdapter( - evmmempool.NewEthSignerExtractionAdapter( - sdkmempool.NewDefaultSignerExtractionAdapter(), - ), - ) - app.SetPrepareProposal(abciProposalHandler.PrepareProposalHandler()) + app.SetMempool(mempool) - return nil -} + app.SetPrepareCheckStater(func(_ sdk.Context) { + if !mempool.HasEventBus() { + mempool.NotifyNewBlock() + } + }) -// createMempoolConfig creates a new EVMMempoolConfig with the default configuration -// and overrides it with values from appOpts if they exist and are non-zero. -func (app *EVMD) createMempoolConfig(appOpts servertypes.AppOptions, logger log.Logger) (*evmmempool.EVMMempoolConfig, error) { - return &evmmempool.EVMMempoolConfig{ - AnteHandler: app.GetAnteHandler(), - LegacyPoolConfig: evmconfig.GetLegacyPoolConfig(appOpts, logger), - BlockGasLimit: evmconfig.GetBlockGasLimit(appOpts, logger), - MinTip: evmconfig.GetMinTip(appOpts, logger), - }, nil + return nil } diff --git a/evmd/test_helpers.go b/evmd/test_helpers.go index b8fb1386..f8349fc1 100644 --- a/evmd/test_helpers.go +++ b/evmd/test_helpers.go @@ -3,9 +3,6 @@ package evmd import ( "encoding/json" "fmt" - "github.com/cosmos/evm/config" - "github.com/cosmos/evm/testutil/integration/evm/network" - "github.com/cosmos/evm/x/vm/types" "testing" "github.com/stretchr/testify/require" @@ -14,10 +11,14 @@ import ( cmttypes "github.com/cometbft/cometbft/types" dbm "github.com/cosmos/cosmos-db" + "github.com/cosmos/evm/evmd/config" + testconstants "github.com/cosmos/evm/testutil/constants" + "github.com/cosmos/evm/testutil/integration/evm/network" feemarkettypes "github.com/cosmos/evm/x/feemarket/types" - ibctesting "github.com/cosmos/ibc-go/v10/testing" + "github.com/cosmos/evm/x/vm/types" + ibctesting "github.com/cosmos/ibc-go/v11/testing" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" "cosmossdk.io/math" "github.com/cosmos/cosmos-sdk/baseapp" @@ -56,7 +57,7 @@ func setup(withGenesis bool, invCheckPeriod uint, chainID string, evmChainID uin appOptions[flags.FlagHome] = defaultNodeHome appOptions[server.FlagInvCheckPeriod] = invCheckPeriod - app := NewExampleApp(log.NewNopLogger(), db, nil, true, appOptions, baseapp.SetChainID(chainID)) + app := NewExampleApp(log.NewNopLogger(), db, true, appOptions, baseapp.SetChainID(chainID)) if withGenesis { return app, app.DefaultGenesis() } @@ -103,7 +104,10 @@ func SetupWithGenesisValSet(t *testing.T, chainID string, evmChainID uint64, val require.NoError(t, err) bankGenesis.DenomMetadata = network.GenerateBankGenesisMetadata(evmChainID) genesisState[banktypes.ModuleName] = app.AppCodec().MustMarshalJSON(&bankGenesis) - require.NoError(t, err) + var evmGenesis types.GenesisState + app.AppCodec().MustUnmarshalJSON(genesisState[types.ModuleName], &evmGenesis) + evmGenesis.Params.EvmDenom = testconstants.ChainsCoinInfo[evmChainID].Denom + genesisState[types.ModuleName] = app.AppCodec().MustMarshalJSON(&evmGenesis) stateBytes, err := json.MarshalIndent(genesisState, "", " ") require.NoError(t, err) @@ -135,7 +139,7 @@ func SetupTestingApp(chainID string) func() (ibctesting.TestingApp, map[string]j db := dbm.NewMemDB() app := NewExampleApp( log.NewNopLogger(), - db, nil, true, + db, true, simtestutil.NewAppOptionsWithFlagHome(defaultNodeHome), baseapp.SetChainID(chainID), ) diff --git a/evmd/tests/ibc/autoflush_test.go b/evmd/tests/ibc/autoflush_test.go new file mode 100644 index 00000000..bbd09b6f --- /dev/null +++ b/evmd/tests/ibc/autoflush_test.go @@ -0,0 +1,958 @@ +package ibc + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/contracts" + "github.com/cosmos/evm/evmd" + "github.com/cosmos/evm/evmd/tests/integration" + "github.com/cosmos/evm/testutil" + evmibctesting "github.com/cosmos/evm/testutil/ibc" + testutiltypes "github.com/cosmos/evm/testutil/types" + erc20types "github.com/cosmos/evm/x/erc20/types" + evmtypes "github.com/cosmos/evm/x/vm/types" + + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// Test constants +const ( + AutoFlushInitialTokenAmount int64 = 1_000_000_000_000_000_000 // 1 token with 18 decimals + AutoFlushDelegationAmount int64 = 100_000_000_000_000_000 // 0.1 token for delegation + AutoFlushTransferAmount int64 = 50_000_000_000_000_000 // 0.05 token for transfers + AutoFlushNativeAmount int64 = 1_000_000_000_000_000_000 // 1 native token (larger to avoid fractional issues) + AutoFlushSenderIndex = 1 +) + +// Test suite for auto-flush behavior with various operation combinations +type AutoFlushTestSuite struct { + suite.Suite + + coordinator *evmibctesting.Coordinator + chain *evmibctesting.TestChain +} + +func (suite *AutoFlushTestSuite) SetupTest() { + suite.coordinator = evmibctesting.NewCoordinator(suite.T(), 1, 0, integration.SetupEvmd) + suite.chain = suite.coordinator.GetChain(evmibctesting.GetEvmChainID(1)) +} + +func TestAutoFlushTestSuite(t *testing.T) { + suite.Run(t, new(AutoFlushTestSuite)) +} + +// Helper: Deploy and setup ERC20 token +func (suite *AutoFlushTestSuite) deployAndRegisterERC20(name, symbol string) (common.Address, evmtypes.CompiledContract) { + evmApp := suite.chain.App.(*evmd.EVMD) + + // Deploy ERC20 + erc20ContractData := contracts.ERC20MinterBurnerDecimalsContract + deploymentData := testutiltypes.ContractDeploymentData{ + Contract: erc20ContractData, + ConstructorArgs: []interface{}{name, symbol, uint8(18)}, + } + + erc20Addr, err := DeployContract(suite.T(), suite.chain, deploymentData) + suite.chain.NextBlock() + suite.Require().NoError(err) + + // Register ERC20 + _, err = evmApp.Erc20Keeper.RegisterERC20(suite.chain.GetContext(), &erc20types.MsgRegisterERC20{ + Signer: evmApp.AccountKeeper.GetModuleAddress("gov").String(), + Erc20Addresses: []string{erc20Addr.Hex()}, + }) + suite.Require().NoError(err) + suite.chain.NextBlock() + + return erc20Addr, erc20ContractData +} + +// Helper: Get validator address +func (suite *AutoFlushTestSuite) getValidatorAddress() string { + evmApp := suite.chain.App.(*evmd.EVMD) + ctx := suite.chain.GetContext() + + vals, err := evmApp.StakingKeeper.GetAllValidators(ctx) + suite.Require().NoError(err) + suite.Require().Greater(len(vals), 0, "no validators found") + + return vals[0].OperatorAddress +} + +// Helper: Mint tokens to address +func (suite *AutoFlushTestSuite) mintTokens(tokenAddr common.Address, erc20Data evmtypes.CompiledContract, recipient common.Address, amount *big.Int) { + evmApp := suite.chain.App.(*evmd.EVMD) + deployerAddr := common.BytesToAddress(suite.chain.SenderPrivKey.PubKey().Address().Bytes()) + + ctx := suite.chain.GetContext() + stateDB := testutil.NewStateDB(ctx, evmApp.EVMKeeper) + _, err := evmApp.GetEVMKeeper().CallEVM( + ctx, + stateDB, + erc20Data.ABI, + deployerAddr, + tokenAddr, + true, + false, + nil, + "mint", + recipient, + amount, + ) + suite.Require().NoError(err) + suite.chain.NextBlock() +} + +// Helper: Fund contract with native tokens +func (suite *AutoFlushTestSuite) fundContractNative(contractAddr sdk.AccAddress, amount sdkmath.Int) { + evmApp := suite.chain.App.(*evmd.EVMD) + ctx := suite.chain.GetContext() + bondDenom, err := evmApp.StakingKeeper.BondDenom(ctx) + suite.Require().NoError(err) + + coins := sdk.NewCoins(sdk.NewCoin(bondDenom, amount)) + err = evmApp.GetBankKeeper().MintCoins(ctx, "mint", coins) + suite.Require().NoError(err) + + err = evmApp.GetBankKeeper().SendCoinsFromModuleToAccount( + ctx, + "mint", + contractAddr, + coins, + ) + suite.Require().NoError(err) + suite.chain.NextBlock() +} + +// Helper: Count events and print them +func (suite *AutoFlushTestSuite) countEvents(ctx sdk.Context) int { + return len(ctx.EventManager().Events()) +} + +// Helper: Check balances and events +func (suite *AutoFlushTestSuite) verifyState( + label string, + expectedEventCount int, + expectedBalances map[common.Address]map[common.Address]*big.Int, // tokenAddr -> holderAddr -> balance + expectedNativeBalances map[string]sdkmath.Int, // bech32 address -> balance + expectedAccountsCreated int, +) { + evmApp := suite.chain.App.(*evmd.EVMD) + ctx := suite.chain.GetContext() + + // Check event count + actualEventCount := suite.countEvents(ctx) + suite.Require().Equal(expectedEventCount, actualEventCount, + "%s: event count mismatch - expected %d, got %d", label, expectedEventCount, actualEventCount) + + // Check ERC20 balances + for tokenAddr, holders := range expectedBalances { + tokenPairID := evmApp.Erc20Keeper.GetTokenPairID(ctx, "erc20:"+tokenAddr.Hex()) + tokenPair, found := evmApp.Erc20Keeper.GetTokenPair(ctx, tokenPairID) + suite.Require().True(found, "%s: token pair not found for %s", label, tokenAddr.Hex()) + + erc20Data := contracts.ERC20MinterBurnerDecimalsContract + for holderAddr, expectedBal := range holders { + actualBal := evmApp.GetErc20Keeper().BalanceOf(ctx, erc20Data.ABI, tokenPair.GetERC20Contract(), holderAddr) + suite.Require().Equal(expectedBal.String(), actualBal.String(), + "%s: ERC20 balance mismatch for %s holding %s", label, holderAddr.Hex(), tokenAddr.Hex()) + } + } + + // Check native balances + for addrStr, expectedBal := range expectedNativeBalances { + bondDenom, err := evmApp.StakingKeeper.BondDenom(ctx) + suite.Require().NoError(err) + + addr, err := sdk.AccAddressFromBech32(addrStr) + suite.Require().NoError(err) + + actualBal := evmApp.GetBankKeeper().GetBalance(ctx, addr, bondDenom) + suite.Require().Equal(expectedBal.String(), actualBal.Amount.String(), + "%s: native balance mismatch for %s", label, addrStr) + } + + // TODO: Check account creation count if needed + _ = expectedAccountsCreated +} + +// Scenario 1: Transfer ERC20 -> Delegate -> Transfer ERC20 +func (suite *AutoFlushTestSuite) TestScenario1_TransferDelegateTransfer() { + suite.SetupTest() + + evmApp := suite.chain.App.(*evmd.EVMD) + ctx := suite.chain.GetContext() + + // Deploy test contract + contractData, err := contracts.LoadSequentialOperationsTester() + suite.Require().NoError(err) + + deploymentData := testutiltypes.ContractDeploymentData{ + Contract: contractData, + ConstructorArgs: []interface{}{}, + } + + contractAddr, err := DeployContract(suite.T(), suite.chain, deploymentData) + suite.chain.NextBlock() + suite.Require().NoError(err) + + contractAddrSDK := sdk.AccAddress(contractAddr.Bytes()) + + // Deploy and register ERC20 + tokenAddr, erc20Data := suite.deployAndRegisterERC20("TestToken", "TT") + + // Mint tokens to contract + suite.mintTokens(tokenAddr, erc20Data, contractAddr, big.NewInt(AutoFlushInitialTokenAmount)) + + // Fund contract with native tokens for delegation + suite.fundContractNative(contractAddrSDK, sdkmath.NewInt(AutoFlushDelegationAmount*2)) + + // Get recipient and validator + senderAccount := suite.chain.SenderAccounts[AutoFlushSenderIndex] + recipientAddr := common.BytesToAddress(senderAccount.SenderAccount.GetAddress().Bytes()) + validatorAddr := suite.getValidatorAddress() + + // Get balances before + ctx = suite.chain.GetContext() + contractBalBefore := evmApp.GetErc20Keeper().BalanceOf(ctx, erc20Data.ABI, tokenAddr, contractAddr) + recipientBalBefore := evmApp.GetErc20Keeper().BalanceOf(ctx, erc20Data.ABI, tokenAddr, recipientAddr) + + // Pack the call data + callData, err := contractData.ABI.Pack( + "scenario1_transferDelegateTransfer", + tokenAddr, + recipientAddr, + big.NewInt(AutoFlushTransferAmount), + validatorAddr, + big.NewInt(AutoFlushDelegationAmount), + ) + suite.Require().NoError(err) + + // Execute via SendEvmTx to get proper event tracking + res, _, _, err := suite.chain.SendEvmTx( + senderAccount, + AutoFlushSenderIndex, + contractAddr, + big.NewInt(0), + callData, + 0, + ) + suite.Require().NoError(err) + + // Get balances after + ctx = suite.chain.GetContext() + contractBalAfter := evmApp.GetErc20Keeper().BalanceOf(ctx, erc20Data.ABI, tokenAddr, contractAddr) + recipientBalAfter := evmApp.GetErc20Keeper().BalanceOf(ctx, erc20Data.ABI, tokenAddr, recipientAddr) + + expectedDelta := new(big.Int).Mul(big.NewInt(AutoFlushTransferAmount), big.NewInt(2)) + actualDelta := new(big.Int).Sub(contractBalBefore, contractBalAfter) + + // Verify balances + suite.Require().Equal(expectedDelta.String(), actualDelta.String(), "transfer amount mismatch") + suite.Require().Equal( + new(big.Int).Mul(big.NewInt(AutoFlushTransferAmount), big.NewInt(2)).String(), + new(big.Int).Sub(recipientBalAfter, recipientBalBefore).String(), + "recipient should receive 2x transfer amount", + ) + + // Verify delegation occurred + delegations, err := evmApp.StakingKeeper.GetAllDelegatorDelegations(ctx, contractAddrSDK) + suite.Require().NoError(err) + suite.Require().Equal(len(delegations), 1, "should have at 1 delegation") + bondedTokens, err := evmApp.StakingKeeper.GetDelegatorBonded(suite.chain.GetContext(), contractAddrSDK) + suite.Require().NoError(err) + suite.Require().Equal(AutoFlushDelegationAmount, bondedTokens.Int64()) + + suite.Require().Equal(DelegationEventCount+EVMEventCount, len(res.Events)) // 8 events, no gas token transfer +} + +// Scenario 2: Transfer ERC20 -> Delegate (reverted & caught) -> Transfer ERC20 +func (suite *AutoFlushTestSuite) TestScenario2_TransferDelegateRevertTransfer() { + suite.SetupTest() + + evmApp := suite.chain.App.(*evmd.EVMD) + ctx := suite.chain.GetContext() + + // Deploy test contract + contractData, err := contracts.LoadSequentialOperationsTester() + suite.Require().NoError(err) + + deploymentData := testutiltypes.ContractDeploymentData{ + Contract: contractData, + ConstructorArgs: []interface{}{}, + } + + contractAddr, err := DeployContract(suite.T(), suite.chain, deploymentData) + suite.chain.NextBlock() + suite.Require().NoError(err) + + // Deploy and register ERC20 + tokenAddr, erc20Data := suite.deployAndRegisterERC20("TestToken2", "TT2") + + // Mint tokens to contract + suite.mintTokens(tokenAddr, erc20Data, contractAddr, big.NewInt(AutoFlushInitialTokenAmount)) + + // Get recipient and validator + senderAccount := suite.chain.SenderAccounts[AutoFlushSenderIndex] + recipientAddr := common.BytesToAddress(senderAccount.SenderAccount.GetAddress().Bytes()) + validatorAddr := suite.getValidatorAddress() + + // Get balances before + ctx = suite.chain.GetContext() + contractBalBefore := evmApp.GetErc20Keeper().BalanceOf(ctx, erc20Data.ABI, tokenAddr, contractAddr) + recipientBalBefore := evmApp.GetErc20Keeper().BalanceOf(ctx, erc20Data.ABI, tokenAddr, recipientAddr) + + // Pack the call data with excessive delegation amount (will revert and be caught) + excessiveAmount := new(big.Int).Mul(big.NewInt(AutoFlushDelegationAmount), big.NewInt(1000)) + callData, err := contractData.ABI.Pack( + "scenario2_transferDelegateRevertTransfer", + tokenAddr, + recipientAddr, + big.NewInt(AutoFlushTransferAmount), + validatorAddr, + excessiveAmount, // Will fail - insufficient balance + ) + suite.Require().NoError(err) + + // Execute via SendEvmTx to get proper event tracking + res, _, _, err := suite.chain.SendEvmTx( + senderAccount, + AutoFlushSenderIndex, + contractAddr, + big.NewInt(0), + callData, + 0, + ) + suite.Require().NoError(err) + + // Get balances after + ctx = suite.chain.GetContext() + contractBalAfter := evmApp.GetErc20Keeper().BalanceOf(ctx, erc20Data.ABI, tokenAddr, contractAddr) + recipientBalAfter := evmApp.GetErc20Keeper().BalanceOf(ctx, erc20Data.ABI, tokenAddr, recipientAddr) + + expectedDelta := new(big.Int).Mul(big.NewInt(AutoFlushTransferAmount), big.NewInt(2)) + actualDelta := new(big.Int).Sub(contractBalBefore, contractBalAfter) + + // Verify balances - both transfers should succeed even though delegate failed + suite.Require().Equal(expectedDelta.String(), actualDelta.String(), "transfer amount mismatch") + suite.Require().Equal( + new(big.Int).Mul(big.NewInt(AutoFlushTransferAmount), big.NewInt(2)).String(), + new(big.Int).Sub(recipientBalAfter, recipientBalBefore).String(), + "recipient should receive 2x transfer amount", + ) + + // Verify NO delegation occurred (it was reverted) + contractAddrSDK := sdk.AccAddress(contractAddr.Bytes()) + delegations, err := evmApp.StakingKeeper.GetAllDelegatorDelegations(ctx, contractAddrSDK) + suite.Require().NoError(err) + suite.Require().Equal(0, len(delegations), "should have no delegations since it reverted") + bondedTokens, err := evmApp.StakingKeeper.GetDelegatorBonded(suite.chain.GetContext(), contractAddrSDK) + suite.Require().NoError(err) + suite.Require().Equal(int64(0), bondedTokens.Int64()) + + suite.Require().Equal(EVMEventCount, len(res.Events)) +} + +// Scenario 3: Native transfer -> Delegate -> Native transfer +func (suite *AutoFlushTestSuite) TestScenario3_NativeTransferDelegateNativeTransfer() { + suite.SetupTest() + + evmApp := suite.chain.App.(*evmd.EVMD) + ctx := suite.chain.GetContext() + + // Deploy test contract + contractData, err := contracts.LoadSequentialOperationsTester() + suite.Require().NoError(err) + + deploymentData := testutiltypes.ContractDeploymentData{ + Contract: contractData, + ConstructorArgs: []interface{}{}, + } + + contractAddr, err := DeployContract(suite.T(), suite.chain, deploymentData) + suite.chain.NextBlock() + suite.Require().NoError(err) + + contractAddrSDK := sdk.AccAddress(contractAddr.Bytes()) + senderAccount := suite.chain.SenderAccounts[AutoFlushSenderIndex] + + // Fund contract via bank module for all operations (both native transfers and delegation) + // Convert from wei (18 decimals) to aatom (6 decimals) by dividing by 1e12 + totalAmountWei := AutoFlushNativeAmount*2 + AutoFlushDelegationAmount + totalAmountAatom := sdkmath.NewInt(totalAmountWei) + suite.fundContractNative(contractAddrSDK, totalAmountAatom) + + // Get recipient and validator + recipientAddr := common.BytesToAddress(senderAccount.SenderAccount.GetAddress().Bytes()) + recipientAddrSDK := senderAccount.SenderAccount.GetAddress() + validatorAddr := suite.getValidatorAddress() + + // Get balances before + ctx = suite.chain.GetContext() + bondDenom, err := evmApp.StakingKeeper.BondDenom(ctx) + suite.Require().NoError(err) + + contractBalBefore := evmApp.GetBankKeeper().GetBalance(ctx, contractAddrSDK, bondDenom) + recipientBalBefore := evmApp.GetBankKeeper().GetBalance(ctx, recipientAddrSDK, bondDenom) + + // Pack the call data + callData, err := contractData.ABI.Pack( + "scenario3_nativeTransferDelegateNativeTransfer", + recipientAddr, + big.NewInt(AutoFlushNativeAmount), + validatorAddr, + big.NewInt(AutoFlushDelegationAmount), + ) + suite.Require().NoError(err) + + // Execute via SendEvmTx to get proper event tracking + res, _, _, err := suite.chain.SendEvmTx( + senderAccount, + AutoFlushSenderIndex, + contractAddr, + big.NewInt(0), + callData, + 0, + ) + suite.Require().NoError(err) + + // Get balances after + ctx = suite.chain.GetContext() + contractBalAfter := evmApp.GetBankKeeper().GetBalance(ctx, contractAddrSDK, bondDenom) + recipientBalAfter := evmApp.GetBankKeeper().GetBalance(ctx, recipientAddrSDK, bondDenom) + + // Verify balances - contract should lose 2x native transfer + delegation (in bank units) + expectedContractDeltaWei := sdkmath.NewInt(AutoFlushNativeAmount*2 + AutoFlushDelegationAmount) + actualContractDelta := contractBalBefore.Amount.Sub(contractBalAfter.Amount) + + // Verify recipient received 2x native amount (in bank units) + expectedRecipientDeltaWei := sdkmath.NewInt(AutoFlushNativeAmount * 2) + actualRecipientDelta := recipientBalAfter.Amount.Sub(recipientBalBefore.Amount) + + suite.Require().Equal(expectedContractDeltaWei.String(), actualContractDelta.String(), "contract balance delta mismatch") + suite.Require().Equal(expectedRecipientDeltaWei.String(), actualRecipientDelta.String(), "recipient should receive 2x native amount") + + // Verify delegation occurred + delegations, err := evmApp.StakingKeeper.GetAllDelegatorDelegations(ctx, contractAddrSDK) + suite.Require().NoError(err) + suite.Require().Equal(len(delegations), 1, "should have 1 delegation") + bondedTokens, err := evmApp.StakingKeeper.GetDelegatorBonded(suite.chain.GetContext(), contractAddrSDK) + suite.Require().NoError(err) + suite.Require().Equal(AutoFlushDelegationAmount, bondedTokens.Int64()) + + suite.Require().Equal(DelegationEventCount+EVMEventCount, len(res.Events)) +} + +// Scenario 4: Native transfer -> Delegate (reverted & caught) -> Native transfer +func (suite *AutoFlushTestSuite) TestScenario4_NativeTransferDelegateRevertNativeTransfer() { + suite.SetupTest() + + evmApp := suite.chain.App.(*evmd.EVMD) + ctx := suite.chain.GetContext() + + // Deploy test contract + contractData, err := contracts.LoadSequentialOperationsTester() + suite.Require().NoError(err) + + deploymentData := testutiltypes.ContractDeploymentData{ + Contract: contractData, + ConstructorArgs: []interface{}{}, + } + + contractAddr, err := DeployContract(suite.T(), suite.chain, deploymentData) + suite.chain.NextBlock() + suite.Require().NoError(err) + + contractAddrSDK := sdk.AccAddress(contractAddr.Bytes()) + + // Fund contract with native tokens for transfers via direct EVM transfer + senderAccount := suite.chain.SenderAccounts[AutoFlushSenderIndex] + nativeTransferValue := big.NewInt(AutoFlushNativeAmount * 2) // 2x transfers + _, _, _, err = suite.chain.SendEvmTx( + senderAccount, + AutoFlushSenderIndex, + contractAddr, + nativeTransferValue, + nil, // no data, just value transfer + 0, + ) + suite.Require().NoError(err) + suite.chain.NextBlock() + + // Get recipient and validator + recipientAddr := common.BytesToAddress(senderAccount.SenderAccount.GetAddress().Bytes()) + recipientAddrSDK := senderAccount.SenderAccount.GetAddress() + validatorAddr := suite.getValidatorAddress() + + // Get balances before + bondDenom, err := evmApp.StakingKeeper.BondDenom(ctx) + suite.Require().NoError(err) + + contractBalBefore := evmApp.GetBankKeeper().GetBalance(ctx, contractAddrSDK, bondDenom) + recipientBalBefore := evmApp.GetBankKeeper().GetBalance(ctx, recipientAddrSDK, bondDenom) + + // Pack the call data with excessive delegation amount (will revert and be caught) + excessiveAmount := new(big.Int).Mul(big.NewInt(AutoFlushDelegationAmount), big.NewInt(1000)) + callData, err := contractData.ABI.Pack( + "scenario4_nativeTransferDelegateRevertNativeTransfer", + recipientAddr, + big.NewInt(AutoFlushNativeAmount), + validatorAddr, + excessiveAmount, // Will fail - insufficient balance + ) + suite.Require().NoError(err) + + // Execute via SendEvmTx to get proper event tracking + res, _, _, err := suite.chain.SendEvmTx( + senderAccount, + AutoFlushSenderIndex, + contractAddr, + big.NewInt(0), + callData, + 0, + ) + suite.Require().NoError(err) + + // Get balances after + ctx = suite.chain.GetContext() + contractBalAfter := evmApp.GetBankKeeper().GetBalance(ctx, contractAddrSDK, bondDenom) + recipientBalAfter := evmApp.GetBankKeeper().GetBalance(ctx, recipientAddrSDK, bondDenom) + + // Bank balances are in Cosmos units (6 decimals), EVM amounts are in wei (18 decimals) + + // Verify balances - contract should lose only 2x native transfer (delegation reverted, in bank units) + expectedContractDeltaWei := sdkmath.NewInt(AutoFlushNativeAmount * 2) + actualContractDelta := contractBalBefore.Amount.Sub(contractBalAfter.Amount) + + // Verify recipient received 2x native amount (in bank units) + expectedRecipientDeltaWei := sdkmath.NewInt(AutoFlushNativeAmount * 2) + actualRecipientDelta := recipientBalAfter.Amount.Sub(recipientBalBefore.Amount) + + suite.Require().Equal(expectedContractDeltaWei.String(), actualContractDelta.String(), "contract balance delta mismatch") + suite.Require().Equal(expectedRecipientDeltaWei.String(), actualRecipientDelta.String(), "recipient should receive 2x native amount") + + // Verify NO delegation occurred (it was reverted) + delegations, err := evmApp.StakingKeeper.GetAllDelegatorDelegations(ctx, contractAddrSDK) + suite.Require().NoError(err) + suite.Require().Equal(0, len(delegations), "should have no delegations since it reverted") + bondedTokens, err := evmApp.StakingKeeper.GetDelegatorBonded(suite.chain.GetContext(), contractAddrSDK) + suite.Require().NoError(err) + suite.Require().Equal(int64(0), bondedTokens.Int64()) + + suite.Require().Equal(EVMEventCount, len(res.Events)) // no delegation in middle, so we bundle the two events transfer events into one +} + +// Scenario 5: Delegate -> Create Contract -> Delegate +func (suite *AutoFlushTestSuite) TestScenario5_DelegateCreateDelegate() { + suite.SetupTest() + + evmApp := suite.chain.App.(*evmd.EVMD) + ctx := suite.chain.GetContext() + + // Deploy test contract + contractData, err := contracts.LoadContractCreationTester() + suite.Require().NoError(err) + + deploymentData := testutiltypes.ContractDeploymentData{ + Contract: contractData, + ConstructorArgs: []interface{}{}, + } + + contractAddr, err := DeployContract(suite.T(), suite.chain, deploymentData) + suite.chain.NextBlock() + suite.Require().NoError(err) + + contractAddrSDK := sdk.AccAddress(contractAddr.Bytes()) + + // Fund contract for delegations via bank module + delegationAmountAatom := sdkmath.NewInt(int64(AutoFlushDelegationAmount * 2)) + suite.fundContractNative(contractAddrSDK, delegationAmountAatom) + + // Get validator + senderAccount := suite.chain.SenderAccounts[AutoFlushSenderIndex] + validatorAddr := suite.getValidatorAddress() + + // Value to send when creating the contract + creationValue := big.NewInt(AutoFlushNativeAmount) + + // Pack the call data + callData, err := contractData.ABI.Pack( + "scenario4_delegateCreateDelegate", + validatorAddr, + big.NewInt(AutoFlushDelegationAmount), + big.NewInt(1).Quo(creationValue, big.NewInt(10)), + big.NewInt(AutoFlushDelegationAmount), + ) + suite.Require().NoError(err) + + // Execute via SendEvmTx with value for contract creation + res, _, _, err := suite.chain.SendEvmTx( + senderAccount, + AutoFlushSenderIndex, + contractAddr, + creationValue, // Send value for the new contract creation + callData, + 0, + ) + suite.Require().NoError(err) + + // Verify 1 delegations occurred + delegations, err := evmApp.StakingKeeper.GetAllDelegatorDelegations(ctx, contractAddrSDK) + suite.Require().NoError(err) + suite.Require().Equal(1, len(delegations), "should have 1 delegation") + bondedTokens, err := evmApp.StakingKeeper.GetDelegatorBonded(suite.chain.GetContext(), contractAddrSDK) + suite.Require().NoError(err) + suite.Require().Equal(AutoFlushDelegationAmount*2, bondedTokens.Int64()) + + suite.Require().Equal(DelegationEventCount+DelegationEventCount+WithdrawalNoTokensEventCount+EVMEventCount, len(res.Events)) +} + +// Scenario 6: Delegate -> Create Contract (reverted & caught) -> Delegate +func (suite *AutoFlushTestSuite) TestScenario6_DelegateCreateRevertDelegate() { + suite.SetupTest() + + evmApp := suite.chain.App.(*evmd.EVMD) + ctx := suite.chain.GetContext() + + // Deploy test contract + contractData, err := contracts.LoadContractCreationTester() + suite.Require().NoError(err) + + deploymentData := testutiltypes.ContractDeploymentData{ + Contract: contractData, + ConstructorArgs: []interface{}{}, + } + + contractAddr, err := DeployContract(suite.T(), suite.chain, deploymentData) + suite.chain.NextBlock() + suite.Require().NoError(err) + + contractAddrSDK := sdk.AccAddress(contractAddr.Bytes()) + + // Fund contract for delegations via bank module + delegationAmountAatom := sdkmath.NewInt(int64(AutoFlushDelegationAmount * 2)) + suite.fundContractNative(contractAddrSDK, delegationAmountAatom) + + // Get validator + senderAccount := suite.chain.SenderAccounts[AutoFlushSenderIndex] + validatorAddr := suite.getValidatorAddress() + + // Excessive value that will cause contract creation to fail + excessiveValue := new(big.Int).Mul(big.NewInt(AutoFlushNativeAmount), big.NewInt(1000)) + + // Pack the call data + callData, err := contractData.ABI.Pack( + "scenario5_delegateCreateRevertDelegate", + validatorAddr, + big.NewInt(AutoFlushDelegationAmount), + excessiveValue, // Will fail - insufficient value + big.NewInt(AutoFlushDelegationAmount), + ) + suite.Require().NoError(err) + + // Execute via SendEvmTx + res, _, _, err := suite.chain.SendEvmTx( + senderAccount, + AutoFlushSenderIndex, + contractAddr, + big.NewInt(0), + callData, + 0, + ) + suite.Require().NoError(err) + + // Verify 1 delegation occurred + delegations, err := evmApp.StakingKeeper.GetAllDelegatorDelegations(ctx, contractAddrSDK) + suite.Require().NoError(err) + suite.Require().Equal(1, len(delegations), "should have 1 delegation") + bondedTokens, err := evmApp.StakingKeeper.GetDelegatorBonded(suite.chain.GetContext(), contractAddrSDK) + suite.Require().NoError(err) + suite.Require().Equal(AutoFlushDelegationAmount*2, bondedTokens.Int64()) + + suite.Require().Equal(DelegationEventCount+DelegationEventCount+WithdrawalNoTokensEventCount+EVMEventCount, len(res.Events)) +} + +// Scenario 7: Create+Revert (caught) -> Delegate -> Create+Revert (caught) +func (suite *AutoFlushTestSuite) TestScenario7_CreateRevertDelegateCreateRevert() { + suite.SetupTest() + + evmApp := suite.chain.App.(*evmd.EVMD) + ctx := suite.chain.GetContext() + + // Deploy test contract + contractData, err := contracts.LoadContractCreationTester() + suite.Require().NoError(err) + + deploymentData := testutiltypes.ContractDeploymentData{ + Contract: contractData, + ConstructorArgs: []interface{}{}, + } + + contractAddr, err := DeployContract(suite.T(), suite.chain, deploymentData) + suite.chain.NextBlock() + suite.Require().NoError(err) + + contractAddrSDK := sdk.AccAddress(contractAddr.Bytes()) + senderAccount := suite.chain.SenderAccounts[AutoFlushSenderIndex] + + // Fund contract for delegation via bank module + delegationAmountAatom := sdkmath.NewInt(int64(AutoFlushDelegationAmount)) + suite.fundContractNative(contractAddrSDK, delegationAmountAatom) + + // Fund contract with some EVM balance for contract creations (even though they revert) + // This is needed because the contract needs balance to create sub-contracts + fundingAmount := big.NewInt(AutoFlushNativeAmount) + _, _, _, err = suite.chain.SendEvmTx( + senderAccount, + AutoFlushSenderIndex, + contractAddr, + fundingAmount, + nil, + 0, + ) + suite.Require().NoError(err) + suite.chain.NextBlock() + + // Get validator + validatorAddr := suite.getValidatorAddress() + + // Values for contract creations (use 0 to avoid balance issues with reverts) + creationValue1 := big.NewInt(0) + creationValue2 := big.NewInt(0) + + // Pack the call data + callData, err := contractData.ABI.Pack( + "scenario6_createRevertDelegateCreateRevert", + creationValue1, + validatorAddr, + big.NewInt(AutoFlushDelegationAmount), + creationValue2, + ) + suite.Require().NoError(err) + + // Execute via SendEvmTx (no value needed since contract creations use 0 and revert) + res, _, _, err := suite.chain.SendEvmTx( + senderAccount, + AutoFlushSenderIndex, + contractAddr, + big.NewInt(0), + callData, + 0, + ) + suite.Require().NoError(err) + + // Verify 1 delegation occurred + delegations, err := evmApp.StakingKeeper.GetAllDelegatorDelegations(ctx, contractAddrSDK) + suite.Require().NoError(err) + suite.Require().Equal(1, len(delegations), "should have 1 delegation") + bondedTokens, err := evmApp.StakingKeeper.GetDelegatorBonded(suite.chain.GetContext(), contractAddrSDK) + suite.Require().NoError(err) + suite.Require().Equal(AutoFlushDelegationAmount, bondedTokens.Int64()) + + suite.Require().Equal(DelegationEventCount+EVMEventCount, len(res.Events)) +} + +// Scenario 8: Create+Send -> Delegate (reverted & caught) -> Send more +func (suite *AutoFlushTestSuite) TestScenario8_CreateDelegateRevertSend() { + suite.SetupTest() + + evmApp := suite.chain.App.(*evmd.EVMD) + ctx := suite.chain.GetContext() + + // Deploy test contract + contractData, err := contracts.LoadContractCreationTester() + suite.Require().NoError(err) + + deploymentData := testutiltypes.ContractDeploymentData{ + Contract: contractData, + ConstructorArgs: []interface{}{}, + } + + contractAddr, err := DeployContract(suite.T(), suite.chain, deploymentData) + suite.chain.NextBlock() + suite.Require().NoError(err) + + // Get validator + senderAccount := suite.chain.SenderAccounts[AutoFlushSenderIndex] + validatorAddr := suite.getValidatorAddress() + + // Values for operations + creationValue := big.NewInt(AutoFlushNativeAmount) + sendAmount := big.NewInt(AutoFlushNativeAmount / 2) + excessiveDelegateAmount := new(big.Int).Mul(big.NewInt(AutoFlushDelegationAmount), big.NewInt(1000)) + + // Pack the call data + callData, err := contractData.ABI.Pack( + "scenario7_createDelegateRevertSend", + creationValue, + validatorAddr, + excessiveDelegateAmount, // Will fail - insufficient balance + sendAmount, + ) + suite.Require().NoError(err) + + // Execute via SendEvmTx with value for contract creation and sends + totalValue := new(big.Int).Add(creationValue, sendAmount) + res, _, _, err := suite.chain.SendEvmTx( + senderAccount, + AutoFlushSenderIndex, + contractAddr, + totalValue, + callData, + 0, + ) + suite.Require().NoError(err) + + // Verify NO delegation occurred (it was reverted) + contractAddrSDK := sdk.AccAddress(contractAddr.Bytes()) + delegations, err := evmApp.StakingKeeper.GetAllDelegatorDelegations(ctx, contractAddrSDK) + suite.Require().NoError(err) + suite.Require().Equal(0, len(delegations), "should have no delegations since it reverted") + + suite.Require().Equal(EVMEventCount, len(res.Events)) +} + +// Scenario 9: Create+Revert (caught) -> Delegate -> Create+Success +func (suite *AutoFlushTestSuite) TestScenario9_CreateRevertDelegateCreateSuccess() { + suite.SetupTest() + + evmApp := suite.chain.App.(*evmd.EVMD) + + // Deploy test contract + contractData, err := contracts.LoadContractCreationTester() + suite.Require().NoError(err) + + deploymentData := testutiltypes.ContractDeploymentData{ + Contract: contractData, + ConstructorArgs: []interface{}{}, + } + + contractAddr, err := DeployContract(suite.T(), suite.chain, deploymentData) + suite.chain.NextBlock() + suite.Require().NoError(err) + + contractAddrSDK := sdk.AccAddress(contractAddr.Bytes()) + senderAccount := suite.chain.SenderAccounts[AutoFlushSenderIndex] + + // Fund contract for delegation via bank module + delegationAmountAatom := sdkmath.NewInt(int64(AutoFlushDelegationAmount)) + suite.fundContractNative(contractAddrSDK, delegationAmountAatom) + + // Fund contract with EVM balance for contract creations + // Need enough for the successful creation (reverted one returns the value) + fundingAmount := big.NewInt(AutoFlushNativeAmount * 2) // Extra buffer + _, _, _, err = suite.chain.SendEvmTx( + senderAccount, + AutoFlushSenderIndex, + contractAddr, + fundingAmount, + nil, + 0, + ) + suite.Require().NoError(err) + suite.chain.NextBlock() + + // Get validator + validatorAddr := suite.getValidatorAddress() + + // Values for operations + revertCreationValue := big.NewInt(AutoFlushNativeAmount / 2) + successCreationValue := big.NewInt(AutoFlushNativeAmount / 2) + + // Get balances before + ctx := suite.chain.GetContext() + bondDenom, err := evmApp.StakingKeeper.BondDenom(ctx) + suite.Require().NoError(err) + contractBalBefore := evmApp.GetBankKeeper().GetBalance(ctx, contractAddrSDK, bondDenom) + + // Pack the call data + callData, err := contractData.ABI.Pack( + "scenario8_createRevertDelegateCreateSuccess", + revertCreationValue, + validatorAddr, + big.NewInt(AutoFlushDelegationAmount), + successCreationValue, + ) + suite.Require().NoError(err) + + // Execute via SendEvmTx + res, _, _, err := suite.chain.SendEvmTx( + senderAccount, + AutoFlushSenderIndex, + contractAddr, + big.NewInt(0), + callData, + 0, + ) + suite.Require().NoError(err) + + // Verify final state + ctx = suite.chain.GetContext() + + // Check delegation occurred + delegations, err := evmApp.StakingKeeper.GetAllDelegatorDelegations(ctx, contractAddrSDK) + suite.Require().NoError(err) + suite.Require().Equal(1, len(delegations), "should have 1 delegation") + bondedTokens, err := evmApp.StakingKeeper.GetDelegatorBonded(suite.chain.GetContext(), contractAddrSDK) + suite.Require().NoError(err) + suite.Require().Equal(AutoFlushDelegationAmount, bondedTokens.Int64()) + + // Check created contracts count + stateDB := testutil.NewStateDB(ctx, evmApp.EVMKeeper) + + countResult, err := evmApp.GetEVMKeeper().CallEVM( + ctx, + stateDB, + contractData.ABI, + contractAddr, + contractAddr, + true, + false, + nil, + "getCreatedContractsCount", + ) + suite.Require().NoError(err) + + var createdCount *big.Int + err = contractData.ABI.UnpackIntoInterface(&createdCount, "getCreatedContractsCount", countResult.Ret) + suite.Require().NoError(err) + suite.Require().Equal(int64(1), createdCount.Int64(), "should have 1 created contract (reverted one doesn't count)") + + // Get the created contract address + addrResult, err := evmApp.GetEVMKeeper().CallEVM( + ctx, + stateDB, + contractData.ABI, + contractAddr, + contractAddr, + true, + false, + nil, + "getCreatedContract", + big.NewInt(0), + ) + suite.Require().NoError(err) + + var createdContractAddr common.Address + err = contractData.ABI.UnpackIntoInterface(&createdContractAddr, "getCreatedContract", addrResult.Ret) + suite.Require().NoError(err) + + // Check the created contract's balance + createdContractBalance := stateDB.GetBalance(createdContractAddr) + suite.Require().Equal(successCreationValue.String(), createdContractBalance.String(), + "created contract should have the creation value") + + // Check main contract's bank balance decreased by delegation + created contract value + contractBalAfter := evmApp.GetBankKeeper().GetBalance(ctx, contractAddrSDK, bondDenom) + // Delta = delegation amount + successful creation value (reverted creation returns the value) + expectedDelta := sdkmath.NewInt((AutoFlushDelegationAmount + successCreationValue.Int64())) + actualDelta := contractBalBefore.Amount.Sub(contractBalAfter.Amount) + suite.Require().Equal(expectedDelta.String(), actualDelta.String(), "bank balance should decrease by delegation + creation value") + + suite.Require().Equal(DelegationEventCount+EVMEventCount, len(res.Events)) +} diff --git a/evmd/tests/ibc/helper.go b/evmd/tests/ibc/helper.go index b7df9057..2f3461b8 100644 --- a/evmd/tests/ibc/helper.go +++ b/evmd/tests/ibc/helper.go @@ -1,10 +1,11 @@ package ibc import ( - "errors" + "fmt" "math/big" "testing" + abci "github.com/cometbft/cometbft/abci/types" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" @@ -14,15 +15,26 @@ import ( evmibctesting "github.com/cosmos/evm/testutil/ibc" testutiltypes "github.com/cosmos/evm/testutil/types" erc20types "github.com/cosmos/evm/x/erc20/types" - ibctesting "github.com/cosmos/ibc-go/v10/testing" + "github.com/cosmos/evm/x/vm/statedb" + "github.com/cosmos/evm/x/vm/types" + ibctesting "github.com/cosmos/ibc-go/v11/testing" errorsmod "cosmossdk.io/errors" + 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" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ) +// Event count constants for test assertions +const ( + DelegationEventCount = 3 // Staking delegation events + EVMEventCount = 5 // EVM transaction wrapper events + WithdrawalNoTokensEventCount = 1 // Withdrawal with no tokens + ICS20WithConversionEventCount = 15 // ERC20 conversion (7) + IBC packet (8) +) + // NativeErc20Info holds details about a deployed ERC20 token. type NativeErc20Info struct { Denom string @@ -36,24 +48,31 @@ type NativeErc20Info struct { func SetupNativeErc20(t *testing.T, chain *evmibctesting.TestChain, senderAcc evmibctesting.SenderAccount) *NativeErc20Info { t.Helper() - evmCtx := chain.GetContext() evmApp := chain.App.(evm.EvmApp) + ctx := chain.GetContext() + + // Deploy new ERC20 contract with default metadata. + // The deployer is a dedicated EOA. + deployer := common.BytesToAddress([]byte("erc20-test-deployer")) + deployerAccAddr := sdk.AccAddress(deployer.Bytes()) + if evmApp.GetAccountKeeper().GetAccount(ctx, deployerAccAddr) == nil { + evmApp.GetAccountKeeper().SetAccount(ctx, evmApp.GetAccountKeeper().NewAccountWithAddress(ctx, deployerAccAddr)) + } - // Deploy new ERC20 contract with default metadata - contractAddr, err := evmApp.GetErc20Keeper().DeployERC20Contract(evmCtx, banktypes.Metadata{ + stateDB := statedb.New(ctx, evmApp.GetEVMKeeper(), statedb.NewEmptyTxConfig()) + contractAddr, err := DeployERC20Contract(ctx, stateDB, evmApp.GetAccountKeeper(), evmApp.GetEVMKeeper(), banktypes.Metadata{ DenomUnits: []*banktypes.DenomUnit{ {Denom: "example", Exponent: 18}, }, Name: "Example", Symbol: "Ex", - }) + }, deployer) if err != nil { t.Fatalf("ERC20 deployment failed: %v", err) } - chain.NextBlock() // Register the contract - _, err = evmApp.GetErc20Keeper().RegisterERC20(evmCtx, &erc20types.MsgRegisterERC20{ + _, err = evmApp.GetErc20Keeper().RegisterERC20(ctx, &erc20types.MsgRegisterERC20{ Signer: authtypes.NewModuleAddress(govtypes.ModuleName).String(), // does not have to be gov Erc20Addresses: []string{contractAddr.Hex()}, }) @@ -67,12 +86,15 @@ func SetupNativeErc20(t *testing.T, chain *evmibctesting.TestChain, senderAcc ev sendAmt := ibctesting.DefaultCoinAmount senderAddr := senderAcc.SenderAccount.GetAddress() + stateDB = statedb.New(ctx, evmApp.GetEVMKeeper(), statedb.NewEmptyTxConfig()) _, err = evmApp.GetEVMKeeper().CallEVM( - evmCtx, + ctx, + stateDB, contractAbi, - erc20types.ModuleAddress, + deployer, contractAddr, true, + false, nil, "mint", common.BytesToAddress(senderAddr), @@ -83,10 +105,31 @@ func SetupNativeErc20(t *testing.T, chain *evmibctesting.TestChain, senderAcc ev } // Verify minted balance - bal := evmApp.GetErc20Keeper().BalanceOf(evmCtx, contractAbi, contractAddr, common.BytesToAddress(senderAddr)) + stateDB = statedb.New(ctx, evmApp.GetEVMKeeper(), statedb.NewEmptyTxConfig()) + ethRes, err := evmApp.GetEVMKeeper().CallEVM( + ctx, + stateDB, + contractAbi, + common.BytesToAddress(senderAddr), + contractAddr, + false, + false, + nil, + "balanceOf", + common.BytesToAddress(senderAddr), + ) + if err != nil { + t.Fatalf("balanceOf call failed: %v", err) + } + var bal *big.Int + err = contractAbi.UnpackIntoInterface(&bal, "balanceOf", ethRes.Ret) + if err != nil { + t.Fatalf("balanceOf call failed: %v", err) + } if bal.Cmp(big.NewInt(sendAmt.Int64())) != 0 { t.Fatalf("unexpected ERC20 balance; got %s, want %s", bal.String(), sendAmt.String()) } + chain.NextBlock() return &NativeErc20Info{ Denom: nativeDenom, @@ -97,15 +140,17 @@ func SetupNativeErc20(t *testing.T, chain *evmibctesting.TestChain, senderAcc ev } } -// SetupNativeErc20 deploys, registers, and mints a native ERC20 token on an EVM-based chain. +// DeployContract deploys an arbitrary contract on an EVM-based chain. +// Like DeployERC20Contract, the sender is an EOA rather than a module account. func DeployContract(t *testing.T, chain *evmibctesting.TestChain, deploymentData testutiltypes.ContractDeploymentData) (common.Address, error) { t.Helper() - // Get account's nonce to create contract hash + // Keep address derivation aligned with CallEVMWithData, which uses account sequence as nonce. from := common.BytesToAddress(chain.SenderPrivKey.PubKey().Address().Bytes()) - account := chain.App.(evm.EvmApp).GetEVMKeeper().GetAccount(chain.GetContext(), from) - if account == nil { - return common.Address{}, errors.New("account not found") + ctx := chain.GetContext() + nonce, err := chain.App.(evm.EvmApp).GetAccountKeeper().GetSequence(ctx, from.Bytes()) + if err != nil { + return common.Address{}, errorsmod.Wrap(err, "failed to get account sequence") } ctorArgs, err := deploymentData.Contract.ABI.Pack("", deploymentData.ConstructorArgs...) @@ -116,10 +161,75 @@ func DeployContract(t *testing.T, chain *evmibctesting.TestChain, deploymentData data := deploymentData.Contract.Bin data = append(data, ctorArgs...) - _, err = chain.App.(evm.EvmApp).GetEVMKeeper().CallEVMWithData(chain.GetContext(), from, nil, data, true, nil) + stateDB := statedb.New(ctx, chain.App.(evm.EvmApp).GetEVMKeeper(), statedb.NewEmptyTxConfig()) + + _, err = chain.App.(evm.EvmApp).GetEVMKeeper().CallEVMWithData(ctx, stateDB, from, nil, data, true, false, nil) if err != nil { return common.Address{}, errorsmod.Wrapf(err, "failed to deploy contract") } - return crypto.CreateAddress(from, account.Nonce), nil + return crypto.CreateAddress(from, nonce), nil +} + +// DeployERC20Contract creates and deploys an ERC20 contract on the EVM with +// deployer as owner. +// +// deployer must be an EOA. Do not pass a module account. +// It is also required in practice. Contract creation bumps the sender's nonce, +// SetAccount persists nonce and balance together, and the EVM commit path is +// not allowed to write a module account's balance. +func DeployERC20Contract( + ctx sdk.Context, + stateDB *statedb.StateDB, + accountKeeper erc20types.AccountKeeper, + evmKeeper erc20types.EVMKeeper, + coinMetadata banktypes.Metadata, + deployer common.Address, +) (common.Address, error) { + decimals := uint8(0) + if len(coinMetadata.DenomUnits) > 0 { + decimalsIdx := len(coinMetadata.DenomUnits) - 1 + decimals = uint8(coinMetadata.DenomUnits[decimalsIdx].Exponent) //#nosec G115 // exponent will not exceed uint8 + } + ctorArgs, err := contracts.ERC20MinterBurnerDecimalsContract.ABI.Pack( + "", + coinMetadata.Name, + coinMetadata.Symbol, + decimals, + ) + if err != nil { + return common.Address{}, errorsmod.Wrapf(types.ErrABIPack, "coin metadata is invalid %s: %s", coinMetadata.Name, err.Error()) + } + + data := make([]byte, len(contracts.ERC20MinterBurnerDecimalsContract.Bin)+len(ctorArgs)) + copy(data[:len(contracts.ERC20MinterBurnerDecimalsContract.Bin)], contracts.ERC20MinterBurnerDecimalsContract.Bin) + copy(data[len(contracts.ERC20MinterBurnerDecimalsContract.Bin):], ctorArgs) + + nonce, err := accountKeeper.GetSequence(ctx, deployer.Bytes()) + if err != nil { + return common.Address{}, err + } + + contractAddr := crypto.CreateAddress(deployer, nonce) + _, err = evmKeeper.CallEVMWithData(ctx, stateDB, deployer, nil, data, true, false, nil) + if err != nil { + return common.Address{}, errorsmod.Wrapf(err, "failed to deploy contract for %s", coinMetadata.Name) + } + + return contractAddr, nil +} + +// PrintEvents prints all events with their attributes for debugging +func PrintEvents(label string, events []abci.Event) { + fmt.Printf("\n========== Events for %s ==========\n", label) + fmt.Printf("Total Event Count: %d\n\n", len(events)) + + for i, event := range events { + fmt.Printf("[%d] Type: %s\n", i, event.Type) + for _, attr := range event.Attributes { + fmt.Printf(" %s: %s\n", attr.Key, attr.Value) + } + fmt.Println() + } + fmt.Printf("========================================\n\n") } diff --git a/evmd/tests/ibc/ibc_middleware_test.go b/evmd/tests/ibc/ibc_middleware_test.go index b930641d..a0f3c8dd 100644 --- a/evmd/tests/ibc/ibc_middleware_test.go +++ b/evmd/tests/ibc/ibc_middleware_test.go @@ -15,6 +15,7 @@ import ( "github.com/cosmos/evm/evmd" "github.com/cosmos/evm/evmd/tests/integration" "github.com/cosmos/evm/ibc" + ics20precompile "github.com/cosmos/evm/precompiles/ics20" "github.com/cosmos/evm/testutil" evmibctesting "github.com/cosmos/evm/testutil/ibc" testutiltypes "github.com/cosmos/evm/testutil/types" @@ -23,12 +24,13 @@ import ( "github.com/cosmos/evm/x/erc20/types" ibctestutil "github.com/cosmos/evm/x/ibc/callbacks/testutil" callbacktypes "github.com/cosmos/evm/x/ibc/callbacks/types" + "github.com/cosmos/evm/x/vm/statedb" evmtypes "github.com/cosmos/evm/x/vm/types" - ibctransfer "github.com/cosmos/ibc-go/v10/modules/apps/transfer" - transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" - channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types" - ibctesting "github.com/cosmos/ibc-go/v10/testing" + ibctransfer "github.com/cosmos/ibc-go/v11/modules/apps/transfer" + transfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/v11/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/v11/modules/core/04-channel/types" + ibctesting "github.com/cosmos/ibc-go/v11/testing" "cosmossdk.io/math" @@ -45,7 +47,8 @@ type MiddlewareTestSuite struct { evmChainA *evmibctesting.TestChain chainB *evmibctesting.TestChain - path *evmibctesting.Path + path *evmibctesting.Path + evmChainAPrecompile *ics20precompile.Precompile } // SetupTest initializes the coordinator and test chains before each test. @@ -65,6 +68,80 @@ func (suite *MiddlewareTestSuite) SetupTest() { // ensure the channel is found to verify proper setup _, found := suite.evmChainA.App.GetIBCKeeper().ChannelKeeper.GetChannel(suite.evmChainA.GetContext(), suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID) suite.Require().True(found) + + // Setup ICS20 precompile for evmChainA + evmAppA := suite.evmChainA.App.(*evmd.EVMD) + suite.evmChainAPrecompile = ics20precompile.NewPrecompile( + evmAppA.BankKeeper, + *evmAppA.StakingKeeper, + evmAppA.TransferKeeper, + evmAppA.IBCKeeper.ChannelKeeper, + evmAppA.Erc20Keeper, + ) +} + +// transferViaPrecompile sends an IBC transfer using the ICS20 precompile. +// This is required for native ERC20 tokens. +func (suite *MiddlewareTestSuite) transferViaPrecompile( + ctx sdk.Context, + sourcePort, sourceChannel string, + token sdk.Coin, + sender, receiver string, + timeoutHeight clienttypes.Height, + timeoutTimestamp uint64, + memo string, +) (uint64, error) { + evmApp := suite.evmChainA.App.(*evmd.EVMD) + + // Convert sender to address type + senderAddr := sdk.MustAccAddressFromBech32(sender) + senderEthAddr := common.BytesToAddress(senderAddr) + + // Create timeoutHeight struct matching the ABI + type Height struct { + RevisionNumber uint64 + RevisionHeight uint64 + } + timeoutHeightStruct := Height{ + RevisionNumber: timeoutHeight.RevisionNumber, + RevisionHeight: timeoutHeight.RevisionHeight, + } + + // Call the precompile through the EVM with correct parameter order and types + // ABI order: sourcePort, sourceChannel, denom, amount, sender (address), receiver, timeoutHeight (struct), timeoutTimestamp, memo + stateDB := statedb.New(suite.evmChainA.GetContext(), evmApp.GetEVMKeeper(), statedb.NewEmptyTxConfig()) + res, err := evmApp.EVMKeeper.CallEVM( + ctx, + stateDB, + ics20precompile.ABI, + senderEthAddr, + common.HexToAddress(evmtypes.ICS20PrecompileAddress), + true, + false, + nil, + "transfer", + sourcePort, + sourceChannel, + token.Denom, + token.Amount.BigInt(), + senderEthAddr, + receiver, + timeoutHeightStruct, + timeoutTimestamp, + memo, + ) + if err != nil { + return 0, err + } + + // Unpack the sequence from the result + var sequence uint64 + err = ics20precompile.ABI.UnpackIntoInterface(&sequence, "transfer", res.Ret) + if err != nil { + return 0, err + } + + return sequence, nil } func TestMiddlewareTestSuite(t *testing.T) { @@ -309,7 +386,6 @@ func (suite *MiddlewareTestSuite) TestOnRecvPacketWithCallback() { path = suite.path ctxB := suite.chainB.GetContext() - evmCtx := suite.evmChainA.GetContext() bondDenom, err := suite.chainB.GetSimApp().StakingKeeper.BondDenom(ctxB) suite.Require().NoError(err) @@ -370,12 +446,12 @@ func (suite *MiddlewareTestSuite) TestOnRecvPacketWithCallback() { transferStack, ok := suite.evmChainA.App.GetIBCKeeper().PortKeeper.Route(transfertypes.ModuleName) suite.Require().True(ok) - _, found := suite.evmChainA.App.GetIBCKeeper().ChannelKeeper.GetChannel(evmCtx, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) + _, found := suite.evmChainA.App.GetIBCKeeper().ChannelKeeper.GetChannel(suite.evmChainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) suite.Require().True(found) // Execute the packet ack := transferStack.OnRecvPacket( - evmCtx, + suite.evmChainA.GetContext(), sourceChan.Version, packet, suite.evmChainA.SenderAccount.GetAddress(), @@ -391,19 +467,19 @@ func (suite *MiddlewareTestSuite) TestOnRecvPacketWithCallback() { if tc.expError == "" { suite.Require().True(ack.Success(), "Expected success but got failure") - balAfterCallback := evmApp.Erc20Keeper.BalanceOf(evmCtx, contracts.ERC20MinterBurnerDecimalsContract.ABI, erc20Contract, contractAddr) + balAfterCallback := evmApp.Erc20Keeper.BalanceOf(suite.evmChainA.GetContext(), contracts.ERC20MinterBurnerDecimalsContract.ABI, erc20Contract, contractAddr) suite.Require().Equal(sendAmt.String(), balAfterCallback.String()) - tokenPair, found := evmApp.Erc20Keeper.GetTokenPair(evmCtx, singleTokenRepresentation.GetID()) + tokenPair, found := evmApp.Erc20Keeper.GetTokenPair(suite.evmChainA.GetContext(), singleTokenRepresentation.GetID()) suite.Require().True(found) suite.Require().Equal(voucherDenom, tokenPair.Denom) - available := evmApp.Erc20Keeper.IsDynamicPrecompileAvailable(evmCtx, common.HexToAddress(tokenPair.Erc20Address)) + available := evmApp.Erc20Keeper.IsDynamicPrecompileAvailable(suite.evmChainA.GetContext(), common.HexToAddress(tokenPair.Erc20Address)) suite.Require().True(available) } else { suite.Require().False(ack.Success(), "Expected failure but got success") - balAfterCallback := evmApp.Erc20Keeper.BalanceOf(evmCtx, contracts.ERC20MinterBurnerDecimalsContract.ABI, erc20Contract, contractAddr) + balAfterCallback := evmApp.Erc20Keeper.BalanceOf(suite.evmChainA.GetContext(), contracts.ERC20MinterBurnerDecimalsContract.ABI, erc20Contract, contractAddr) suite.Require().Equal("0", balAfterCallback.String()) ackObj, ok := ack.(channeltypes.Acknowledgement) @@ -524,11 +600,10 @@ func (suite *MiddlewareTestSuite) TestOnRecvPacket() { transferStack, ok := suite.evmChainA.App.GetIBCKeeper().PortKeeper.Route(transfertypes.ModuleName) suite.Require().True(ok) - ctxA := suite.evmChainA.GetContext() sourceChan := path.EndpointB.GetChannel() ack := transferStack.OnRecvPacket( - ctxA, + suite.evmChainA.GetContext(), sourceChan.Version, packet, suite.evmChainA.SenderAccount.GetAddress(), @@ -544,17 +619,17 @@ func (suite *MiddlewareTestSuite) TestOnRecvPacket() { voucherDenom := testutil.GetVoucherDenomFromPacketData(data, packet.GetDestPort(), packet.GetDestChannel()) evmApp := suite.evmChainA.App.(*evmd.EVMD) - voucherCoin := evmApp.BankKeeper.GetBalance(ctxA, receiver, voucherDenom) + voucherCoin := evmApp.BankKeeper.GetBalance(suite.evmChainA.GetContext(), receiver, voucherDenom) suite.Require().Equal(sendAmt.String(), voucherCoin.Amount.String()) // Make sure token pair is registered singleTokenRepresentation, err := types.NewTokenPairSTRv2(voucherDenom) suite.Require().NoError(err) - tokenPair, found := evmApp.Erc20Keeper.GetTokenPair(ctxA, singleTokenRepresentation.GetID()) + tokenPair, found := evmApp.Erc20Keeper.GetTokenPair(suite.evmChainA.GetContext(), singleTokenRepresentation.GetID()) suite.Require().True(found) suite.Require().Equal(voucherDenom, tokenPair.Denom) // Make sure dynamic precompile is registered - available := evmApp.Erc20Keeper.IsDynamicPrecompileAvailable(ctxA, common.HexToAddress(tokenPair.Erc20Address)) + available := evmApp.Erc20Keeper.IsDynamicPrecompileAvailable(suite.evmChainA.GetContext(), common.HexToAddress(tokenPair.Erc20Address)) suite.Require().True(available) } else { suite.Require().False(ack.Success()) @@ -605,7 +680,6 @@ func (suite *MiddlewareTestSuite) TestOnRecvPacketNativeErc20() { suite.SetupTest() nativeErc20 := SetupNativeErc20(suite.T(), suite.evmChainA, suite.evmChainA.SenderAccounts[0]) - evmCtx := suite.evmChainA.GetContext() evmApp := suite.evmChainA.App.(*evmd.EVMD) // Scenario: Native ERC20 token transfer from evmChainA to chainB @@ -617,20 +691,24 @@ func (suite *MiddlewareTestSuite) TestOnRecvPacketNativeErc20() { senderEthAddr := nativeErc20.Account sender := sdk.AccAddress(senderEthAddr.Bytes()) - // Transfer half the initial balance out + // Transfer half the initial balance out using the precompile // Sender transfers 50 out (escrowed) - msg := transfertypes.NewMsgTransfer( - path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, + _, err := suite.transferViaPrecompile( + suite.evmChainA.GetContext(), + path.EndpointA.ChannelConfig.PortID, + path.EndpointA.ChannelID, sdk.NewCoin(nativeErc20.Denom, sendAmt), - sender.String(), chainBAccount.String(), - timeoutHeight, 0, "", + sender.String(), + chainBAccount.String(), + timeoutHeight, + 0, + "", ) - - _, err := suite.evmChainA.SendMsgs(msg) suite.Require().NoError(err) // message committed + suite.evmChainA.NextBlock() // Balance after transfer should be initial balance - sendAmt - balAfterTransfer := evmApp.Erc20Keeper.BalanceOf(evmCtx, nativeErc20.ContractAbi, nativeErc20.ContractAddr, senderEthAddr) + balAfterTransfer := evmApp.Erc20Keeper.BalanceOf(suite.evmChainA.GetContext(), nativeErc20.ContractAbi, nativeErc20.ContractAddr, senderEthAddr) suite.Require().Equal( new(big.Int).Sub(nativeErc20.InitialBal, sendAmt.BigInt()).String(), balAfterTransfer.String(), @@ -650,7 +728,7 @@ func (suite *MiddlewareTestSuite) TestOnRecvPacketNativeErc20() { // Check native erc20 token is escrowed on evmChainA for sending to chainB. // Conversion of remaining 50 tokens to Bank token escrowAddr := transfertypes.GetEscrowAddress(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) - escrowedBal := evmApp.BankKeeper.GetBalance(evmCtx, escrowAddr, nativeErc20.Denom) + escrowedBal := evmApp.BankKeeper.GetBalance(suite.evmChainA.GetContext(), escrowAddr, nativeErc20.Denom) suite.Require().Equal(sendAmt.String(), escrowedBal.Amount.String()) // chainBNativeErc20Denom is the native erc20 token denom on chainB from evmChainA through IBC. @@ -730,8 +808,8 @@ func (suite *MiddlewareTestSuite) TestOnRecvPacketNativeErc20() { // SendEnabled=false will cause the conversion of bank tokens to erc20 tokens to fail, // but not send them back to escrow - evmApp.BankKeeper.SetSendEnabled(evmCtx, nativeErc20.Denom, false) - isSendEnabled := evmApp.BankKeeper.IsSendEnabledDenom(evmCtx, nativeErc20.Denom) + evmApp.BankKeeper.SetSendEnabled(suite.evmChainA.GetContext(), nativeErc20.Denom, false) + isSendEnabled := evmApp.BankKeeper.IsSendEnabledDenom(suite.evmChainA.GetContext(), nativeErc20.Denom) suite.Require().False(isSendEnabled) packet1 := channeltypes.Packet{ @@ -746,18 +824,17 @@ func (suite *MiddlewareTestSuite) TestOnRecvPacketNativeErc20() { } errAck := transferStack.OnRecvPacket( - evmCtx, + suite.evmChainA.GetContext(), sourceChan.Version, packet1, suite.evmChainA.SenderAccount.GetAddress(), ) suite.Require().False(errAck.Success()) - evmCtx = suite.evmChainA.GetContext() // SendEnabled=true causes our callback to succeed - evmApp.BankKeeper.SetSendEnabled(evmCtx, nativeErc20.Denom, true) - isSendEnabled = evmApp.BankKeeper.IsSendEnabledDenom(evmCtx, nativeErc20.Denom) + evmApp.BankKeeper.SetSendEnabled(suite.evmChainA.GetContext(), nativeErc20.Denom, true) + isSendEnabled = evmApp.BankKeeper.IsSendEnabledDenom(suite.evmChainA.GetContext(), nativeErc20.Denom) suite.Require().True(isSendEnabled) packet2 := channeltypes.Packet{ @@ -772,7 +849,7 @@ func (suite *MiddlewareTestSuite) TestOnRecvPacketNativeErc20() { } ack := transferStack.OnRecvPacket( - evmCtx, + suite.evmChainA.GetContext(), sourceChan.Version, packet2, suite.evmChainA.SenderAccount.GetAddress(), @@ -780,7 +857,7 @@ func (suite *MiddlewareTestSuite) TestOnRecvPacketNativeErc20() { suite.Require().True(ack.Success()) // Check un-escrowed balance on evmChainA after receiving the packet. - escrowedBal = evmApp.BankKeeper.GetBalance(evmCtx, escrowAddr, nativeErc20.Denom) + escrowedBal = evmApp.BankKeeper.GetBalance(suite.evmChainA.GetContext(), escrowAddr, nativeErc20.Denom) suite.Require().True(escrowedBal.IsZero(), "escrowed balance should be un-escrowed after receiving the packet") // recvAmt should be in the contractAddr upon successful recv callback @@ -793,10 +870,10 @@ func (suite *MiddlewareTestSuite) TestOnRecvPacketNativeErc20() { contractAddrStr := destCallback["address"].(string) contractAddr = common.HexToAddress(contractAddrStr) - balAfterUnescrow := evmApp.Erc20Keeper.BalanceOf(evmCtx, nativeErc20.ContractAbi, nativeErc20.ContractAddr, contractAddr) + balAfterUnescrow := evmApp.Erc20Keeper.BalanceOf(suite.evmChainA.GetContext(), nativeErc20.ContractAbi, nativeErc20.ContractAddr, contractAddr) suite.Require().Equal(recvAmt.String(), balAfterUnescrow.String()) - bankBalAfterUnescrow := evmApp.BankKeeper.GetBalance(evmCtx, sender, nativeErc20.Denom) + bankBalAfterUnescrow := evmApp.BankKeeper.GetBalance(suite.evmChainA.GetContext(), sender, nativeErc20.Denom) // InitialBalance half which was converted but not sent will be in the sending account's balance suite.Require().Equal(sendAmt.String(), bankBalAfterUnescrow.Amount.String()) @@ -804,7 +881,7 @@ func (suite *MiddlewareTestSuite) TestOnRecvPacketNativeErc20() { // and will be in the isolated address used to invoke the callback isolatedAddr := callbacktypes.GenerateIsolatedAddress(path.EndpointA.ChannelID, suite.chainB.SenderAccount.GetAddress().String()) - trappedBal := evmApp.BankKeeper.GetBalance(evmCtx, isolatedAddr, nativeErc20.Denom) + trappedBal := evmApp.BankKeeper.GetBalance(suite.evmChainA.GetContext(), isolatedAddr, nativeErc20.Denom) suite.Require().Equal(recvAmt.String(), trappedBal.Amount.String()) } else { // Simple case: no callback, just verify hex recipient receives ERC20 @@ -820,7 +897,7 @@ func (suite *MiddlewareTestSuite) TestOnRecvPacketNativeErc20() { } ack := transferStack.OnRecvPacket( - evmCtx, + suite.evmChainA.GetContext(), sourceChan.Version, packet, suite.evmChainA.SenderAccount.GetAddress(), @@ -829,7 +906,7 @@ func (suite *MiddlewareTestSuite) TestOnRecvPacketNativeErc20() { // Verify ERC20 was minted to the hex recipient bal := evmApp.Erc20Keeper.BalanceOf( - evmCtx, + suite.evmChainA.GetContext(), nativeErc20.ContractAbi, nativeErc20.ContractAddr, tc.expectedRecipientEVM, @@ -1091,10 +1168,9 @@ func (suite *MiddlewareTestSuite) TestOnAcknowledgementPacketWithCallback() { suite.Run(tc.name, func() { suite.SetupTest() - ctxA := suite.evmChainA.GetContext() evmApp := suite.evmChainA.App.(*evmd.EVMD) - bondDenom, err := evmApp.StakingKeeper.BondDenom(ctxA) + bondDenom, err := evmApp.StakingKeeper.BondDenom(suite.evmChainA.GetContext()) suite.Require().NoError(err) sendAmt := ibctesting.DefaultCoinAmount @@ -1152,7 +1228,7 @@ func (suite *MiddlewareTestSuite) TestOnAcknowledgementPacketWithCallback() { sourceChan := suite.path.EndpointA.GetChannel() - balBeforeTransfer := evmApp.BankKeeper.GetBalance(ctxA, sender, bondDenom) + balBeforeTransfer := evmApp.BankKeeper.GetBalance(suite.evmChainA.GetContext(), sender, bondDenom) // Execute send if required (for proper escrow setup) if tc.onSendRequired { timeoutHeight := clienttypes.NewHeight(1, 110) @@ -1170,7 +1246,7 @@ func (suite *MiddlewareTestSuite) TestOnAcknowledgementPacketWithCallback() { suite.Require().NoError(err) // message committed feeAmt := evmibctesting.FeeCoins().AmountOf(bondDenom) - balAfterTransfer := evmApp.BankKeeper.GetBalance(ctxA, sender, bondDenom) + balAfterTransfer := evmApp.BankKeeper.GetBalance(suite.evmChainA.GetContext(), sender, bondDenom) suite.Require().Equal( balBeforeTransfer.Amount.Sub(sendAmt).Sub(feeAmt).String(), balAfterTransfer.Amount.String(), @@ -1188,13 +1264,13 @@ func (suite *MiddlewareTestSuite) TestOnAcknowledgementPacketWithCallback() { // One for UpdateClient() and one for AcknowledgePacket() relayPacketFeeAmt := feeAmt.Mul(math.NewInt(2)) - balAfterRelayPacket := evmApp.BankKeeper.GetBalance(ctxA, sender, bondDenom) + balAfterRelayPacket := evmApp.BankKeeper.GetBalance(suite.evmChainA.GetContext(), sender, bondDenom) suite.Require().Equal( balAfterTransfer.Amount.Sub(relayPacketFeeAmt).String(), balAfterRelayPacket.Amount.String(), ) escrowAddr := transfertypes.GetEscrowAddress(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) - escrowedBal := evmApp.BankKeeper.GetBalance(ctxA, escrowAddr, bondDenom) + escrowedBal := evmApp.BankKeeper.GetBalance(suite.evmChainA.GetContext(), escrowAddr, bondDenom) suite.Require().Equal(sendAmt.String(), escrowedBal.Amount.String()) } @@ -1202,28 +1278,32 @@ func (suite *MiddlewareTestSuite) TestOnAcknowledgementPacketWithCallback() { packet = sentPacket } - beforeAckBal := evmApp.BankKeeper.GetBalance(ctxA, sender, bondDenom) + beforeAckBal := evmApp.BankKeeper.GetBalance(suite.evmChainA.GetContext(), sender, bondDenom) // Execute acknowledgement err = transferStack.OnAcknowledgementPacket( - ctxA, + suite.evmChainA.GetContext(), sourceChan.Version, packet, ack, receiver, ) + stateDB := statedb.New(suite.evmChainA.GetContext(), evmApp.GetEVMKeeper(), statedb.NewEmptyTxConfig()) // Validate results if tc.expError == "" { suite.Require().NoError(err, "Expected success but got error") - // Verify callback execution by checking counter increment if strings.Contains(tc.memo(), "src_callback") { + senderEVM := common.BytesToAddress(sender) + expectsCallbackExec := contractAddr == senderEVM counterRes, err := evmApp.EVMKeeper.CallEVM( - ctxA, + suite.evmChainA.GetContext(), + stateDB, contractData.ABI, common.BytesToAddress(suite.evmChainA.SenderAccount.GetAddress()), contractAddr, false, + false, big.NewInt(100000), "getCounter", ) @@ -1232,14 +1312,18 @@ func (suite *MiddlewareTestSuite) TestOnAcknowledgementPacketWithCallback() { var counter *big.Int err = contractData.ABI.UnpackIntoInterface(&counter, "getCounter", counterRes.Ret) suite.Require().NoError(err) - suite.Require().True(counter.Cmp(big.NewInt(1)) >= 0, "Counter should be incremented by callback") + if expectsCallbackExec { + suite.Require().True(counter.Cmp(big.NewInt(1)) >= 0, "Counter should be incremented by callback") + } else { + suite.Require().Equal(big.NewInt(0).String(), counter.String(), "Counter should remain 0 when callback is gated") + } } // Verify refund for error acknowledgements if tc.ackType == "error" && tc.onSendRequired { escrowAddr := transfertypes.GetEscrowAddress(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) - escrowedBal := evmApp.BankKeeper.GetBalance(ctxA, escrowAddr, bondDenom) - finalSenderBal := evmApp.BankKeeper.GetBalance(ctxA, sender, bondDenom) + escrowedBal := evmApp.BankKeeper.GetBalance(suite.evmChainA.GetContext(), escrowAddr, bondDenom) + finalSenderBal := evmApp.BankKeeper.GetBalance(suite.evmChainA.GetContext(), sender, bondDenom) // For error acks, tokens should be refunded suite.Require().True(escrowedBal.IsZero(), "Escrowed balance should be zero after refund") @@ -1249,11 +1333,13 @@ func (suite *MiddlewareTestSuite) TestOnAcknowledgementPacketWithCallback() { // For ack failures, verify that counter was NOT incremented counterRes, err := evmApp.EVMKeeper.CallEVM( - ctxA, + suite.evmChainA.GetContext(), + stateDB, contractData.ABI, common.BytesToAddress(suite.evmChainA.SenderAccount.GetAddress()), contractAddr, false, + false, big.NewInt(100000), "getCounter", ) @@ -1319,10 +1405,9 @@ func (suite *MiddlewareTestSuite) TestOnAcknowledgementPacket() { suite.Run(tc.name, func() { suite.SetupTest() - ctxA := suite.evmChainA.GetContext() evmApp := suite.evmChainA.App.(*evmd.EVMD) - bondDenom, err := evmApp.StakingKeeper.BondDenom(ctxA) + bondDenom, err := evmApp.StakingKeeper.BondDenom(suite.evmChainA.GetContext()) suite.Require().NoError(err) sendAmt := ibctesting.DefaultCoinAmount @@ -1360,7 +1445,7 @@ func (suite *MiddlewareTestSuite) TestOnAcknowledgementPacket() { sourceChan := suite.path.EndpointA.GetChannel() onAck := func() error { return transferStack.OnAcknowledgementPacket( - ctxA, + suite.evmChainA.GetContext(), sourceChan.Version, packet, ack, @@ -1377,12 +1462,12 @@ func (suite *MiddlewareTestSuite) TestOnAcknowledgementPacket() { receiver.String(), timeoutHeight, 0, "", ) - balBeforeTransfer := evmApp.BankKeeper.GetBalance(ctxA, sender, bondDenom) + balBeforeTransfer := evmApp.BankKeeper.GetBalance(suite.evmChainA.GetContext(), sender, bondDenom) res, err := suite.evmChainA.SendMsgs(msg) suite.Require().NoError(err) // message committed feeAmt := evmibctesting.FeeCoins().AmountOf(bondDenom) - balAfterTransfer := evmApp.BankKeeper.GetBalance(ctxA, sender, bondDenom) + balAfterTransfer := evmApp.BankKeeper.GetBalance(suite.evmChainA.GetContext(), sender, bondDenom) suite.Require().Equal( balBeforeTransfer.Amount.Sub(sendAmt).Sub(feeAmt).String(), balAfterTransfer.Amount.String(), @@ -1399,13 +1484,13 @@ func (suite *MiddlewareTestSuite) TestOnAcknowledgementPacket() { relayPacketFeeAmt := feeAmt.Mul(math.NewInt(2)) // ensure the ibc token is escrowed. - balAfterRelayPacket := evmApp.BankKeeper.GetBalance(ctxA, sender, bondDenom) + balAfterRelayPacket := evmApp.BankKeeper.GetBalance(suite.evmChainA.GetContext(), sender, bondDenom) suite.Require().Equal( balAfterTransfer.Amount.Sub(relayPacketFeeAmt).String(), balAfterRelayPacket.Amount.String(), ) escrowAddr := transfertypes.GetEscrowAddress(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) - escrowedBal := evmApp.BankKeeper.GetBalance(ctxA, escrowAddr, bondDenom) + escrowedBal := evmApp.BankKeeper.GetBalance(suite.evmChainA.GetContext(), escrowAddr, bondDenom) suite.Require().Equal(sendAmt.String(), escrowedBal.Amount.String()) } @@ -1471,7 +1556,6 @@ func (suite *MiddlewareTestSuite) TestOnAcknowledgementPacketNativeErc20() { suite.SetupTest() nativeErc20 := SetupNativeErc20(suite.T(), suite.evmChainA, suite.evmChainA.SenderAccounts[0]) - evmCtx := suite.evmChainA.GetContext() evmApp := suite.evmChainA.App.(*evmd.EVMD) timeoutHeight := clienttypes.NewHeight(1, 110) @@ -1483,37 +1567,42 @@ func (suite *MiddlewareTestSuite) TestOnAcknowledgementPacketNativeErc20() { sender := sdk.AccAddress(senderEthAddr.Bytes()) receiver := suite.chainB.SenderAccount.GetAddress() - // Send the native erc20 token from evmChainA to chainB. - msg := transfertypes.NewMsgTransfer( - path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, - sdk.NewCoin(nativeErc20.Denom, sendAmt), sender.String(), receiver.String(), - timeoutHeight, 0, "", - ) - escrowAddr := transfertypes.GetEscrowAddress(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) // checkEscrow is a check function to ensure the native erc20 token is escrowed. checkEscrow := func() { - erc20BalAfterIbcTransfer := evmApp.Erc20Keeper.BalanceOf(evmCtx, nativeErc20.ContractAbi, nativeErc20.ContractAddr, senderEthAddr) + erc20BalAfterIbcTransfer := evmApp.Erc20Keeper.BalanceOf(suite.evmChainA.GetContext(), nativeErc20.ContractAbi, nativeErc20.ContractAddr, senderEthAddr) suite.Require().Equal( new(big.Int).Sub(nativeErc20.InitialBal, sendAmt.BigInt()).String(), erc20BalAfterIbcTransfer.String(), ) - escrowedBal := evmApp.BankKeeper.GetBalance(evmCtx, escrowAddr, nativeErc20.Denom) + escrowedBal := evmApp.BankKeeper.GetBalance(suite.evmChainA.GetContext(), escrowAddr, nativeErc20.Denom) suite.Require().Equal(sendAmt.String(), escrowedBal.Amount.String()) } // checkRefund is a check function to ensure refund is processed. checkRefund := func() { - escrowedBal := evmApp.BankKeeper.GetBalance(evmCtx, escrowAddr, nativeErc20.Denom) + escrowedBal := evmApp.BankKeeper.GetBalance(suite.evmChainA.GetContext(), escrowAddr, nativeErc20.Denom) suite.Require().True(escrowedBal.IsZero()) // Check erc20 balance is same as initial balance after refund. - erc20BalAfterIbcTransfer := evmApp.Erc20Keeper.BalanceOf(evmCtx, nativeErc20.ContractAbi, nativeErc20.ContractAddr, senderEthAddr) + erc20BalAfterIbcTransfer := evmApp.Erc20Keeper.BalanceOf(suite.evmChainA.GetContext(), nativeErc20.ContractAbi, nativeErc20.ContractAddr, senderEthAddr) suite.Require().Equal(nativeErc20.InitialBal.String(), erc20BalAfterIbcTransfer.String()) } - _, err := suite.evmChainA.SendMsgs(msg) + // Send the native erc20 token from evmChainA to chainB using the precompile. + _, err := suite.transferViaPrecompile( + suite.evmChainA.GetContext(), + path.EndpointA.ChannelConfig.PortID, + path.EndpointA.ChannelID, + sdk.NewCoin(nativeErc20.Denom, sendAmt), + sender.String(), + receiver.String(), + timeoutHeight, + 0, + "", + ) suite.Require().NoError(err) // message committed + suite.evmChainA.NextBlock() checkEscrow() transferStack, ok := suite.evmChainA.App.GetIBCKeeper().PortKeeper.Route(transfertypes.ModuleName) @@ -1545,7 +1634,7 @@ func (suite *MiddlewareTestSuite) TestOnAcknowledgementPacketNativeErc20() { sourceChan := path.EndpointA.GetChannel() onAck := func() error { return transferStack.OnAcknowledgementPacket( - evmCtx, + suite.evmChainA.GetContext(), sourceChan.Version, packet, ack, @@ -1600,9 +1689,8 @@ func (suite *MiddlewareTestSuite) TestOnTimeoutPacket() { suite.Run(tc.name, func() { suite.SetupTest() - ctxA := suite.evmChainA.GetContext() evmApp := suite.evmChainA.App.(*evmd.EVMD) - bondDenom, err := evmApp.StakingKeeper.BondDenom(ctxA) + bondDenom, err := evmApp.StakingKeeper.BondDenom(suite.evmChainA.GetContext()) suite.Require().NoError(err) sendAmt := ibctesting.DefaultCoinAmount @@ -1639,14 +1727,14 @@ func (suite *MiddlewareTestSuite) TestOnTimeoutPacket() { sourceChan := suite.path.EndpointA.GetChannel() onTimeout := func() error { return transferStack.OnTimeoutPacket( - ctxA, + suite.evmChainA.GetContext(), sourceChan.Version, packet, sender, ) } - balBeforeTransfer := evmApp.BankKeeper.GetBalance(ctxA, sender, bondDenom) + balBeforeTransfer := evmApp.BankKeeper.GetBalance(suite.evmChainA.GetContext(), sender, bondDenom) var balAfterRelayPacket sdk.Coin feeAmt := evmibctesting.FeeCoins().AmountOf(bondDenom) if tc.onSendRequired { @@ -1663,7 +1751,7 @@ func (suite *MiddlewareTestSuite) TestOnTimeoutPacket() { res, err := suite.evmChainA.SendMsgs(msg) suite.Require().NoError(err) // message committed - balAfterTransfer := evmApp.BankKeeper.GetBalance(ctxA, sender, bondDenom) + balAfterTransfer := evmApp.BankKeeper.GetBalance(suite.evmChainA.GetContext(), sender, bondDenom) suite.Require().Equal( balBeforeTransfer.Amount.Sub(sendAmt).Sub(feeAmt).String(), balAfterTransfer.Amount.String(), @@ -1678,7 +1766,7 @@ func (suite *MiddlewareTestSuite) TestOnTimeoutPacket() { // One for UpdateClient() and one for AcknowledgePacket() relayPacketFeeAmt := feeAmt.Mul(math.NewInt(2)) - balAfterRelayPacket = evmApp.BankKeeper.GetBalance(ctxA, sender, bondDenom) + balAfterRelayPacket = evmApp.BankKeeper.GetBalance(suite.evmChainA.GetContext(), sender, bondDenom) suite.Require().Equal( balAfterTransfer.Amount.Sub(relayPacketFeeAmt).String(), balAfterRelayPacket.Amount.String(), @@ -1686,7 +1774,7 @@ func (suite *MiddlewareTestSuite) TestOnTimeoutPacket() { } err = onTimeout() - balAfterTimeout := evmApp.BankKeeper.GetBalance(ctxA, sender, bondDenom) + balAfterTimeout := evmApp.BankKeeper.GetBalance(suite.evmChainA.GetContext(), sender, bondDenom) if tc.onSendRequired { suite.Require().Equal( balAfterRelayPacket.Amount.Add(sendAmt).String(), @@ -1701,7 +1789,7 @@ func (suite *MiddlewareTestSuite) TestOnTimeoutPacket() { // ensure that the escrowed coins were refunded on timeout. escrowAddr := transfertypes.GetEscrowAddress(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) - escrowedBal := evmApp.BankKeeper.GetBalance(ctxA, escrowAddr, bondDenom) + escrowedBal := evmApp.BankKeeper.GetBalance(suite.evmChainA.GetContext(), escrowAddr, bondDenom) suite.Require().Equal(escrowedBal.Amount.String(), math.ZeroInt().String()) if tc.expError == "" { @@ -1918,10 +2006,9 @@ func (suite *MiddlewareTestSuite) TestOnTimeoutPacketWithCallback() { suite.Run(tc.name, func() { suite.SetupTest() - ctxA := suite.evmChainA.GetContext() evmApp := suite.evmChainA.App.(*evmd.EVMD) - bondDenom, err := evmApp.StakingKeeper.BondDenom(ctxA) + bondDenom, err := evmApp.StakingKeeper.BondDenom(suite.evmChainA.GetContext()) suite.Require().NoError(err) sendAmt := ibctesting.DefaultCoinAmount @@ -1969,7 +2056,7 @@ func (suite *MiddlewareTestSuite) TestOnTimeoutPacketWithCallback() { transferStack, ok := evmApp.GetIBCKeeper().PortKeeper.Route(transfertypes.ModuleName) suite.Require().True(ok) - balBeforeTransfer := evmApp.BankKeeper.GetBalance(ctxA, sender, bondDenom) + balBeforeTransfer := evmApp.BankKeeper.GetBalance(suite.evmChainA.GetContext(), sender, bondDenom) balAfterTransfer := balBeforeTransfer feeAmt := evmibctesting.FeeCoins().AmountOf(bondDenom) // Execute send if required (for proper escrow setup) @@ -1991,13 +2078,13 @@ func (suite *MiddlewareTestSuite) TestOnTimeoutPacketWithCallback() { sentPacket, err := ibctesting.ParseV1PacketFromEvents(res.Events) suite.Require().NoError(err) - balAfterTransfer = evmApp.BankKeeper.GetBalance(ctxA, sender, bondDenom) + balAfterTransfer = evmApp.BankKeeper.GetBalance(suite.evmChainA.GetContext(), sender, bondDenom) suite.Require().Equal( balBeforeTransfer.Amount.Sub(sendAmt).Sub(feeAmt).String(), balAfterTransfer.Amount.String(), ) escrowAddr := transfertypes.GetEscrowAddress(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) - escrowedBal := evmApp.BankKeeper.GetBalance(ctxA, escrowAddr, bondDenom) + escrowedBal := evmApp.BankKeeper.GetBalance(suite.evmChainA.GetContext(), escrowAddr, bondDenom) suite.Require().Equal(sendAmt.String(), escrowedBal.Amount.String()) // Use the actually sent packet for timeout @@ -2006,12 +2093,13 @@ func (suite *MiddlewareTestSuite) TestOnTimeoutPacketWithCallback() { sourceChan := path.EndpointA.GetChannel() err = transferStack.OnTimeoutPacket( - ctxA, + suite.evmChainA.GetContext(), sourceChan.Version, packet, receiver, ) - balAfterTimeout := evmApp.BankKeeper.GetBalance(ctxA, sender, bondDenom) + balAfterTimeout := evmApp.BankKeeper.GetBalance(suite.evmChainA.GetContext(), sender, bondDenom) + stateDB := statedb.New(suite.evmChainA.GetContext(), evmApp.GetEVMKeeper(), statedb.NewEmptyTxConfig()) // Validate results if tc.expError == "" { @@ -2021,12 +2109,16 @@ func (suite *MiddlewareTestSuite) TestOnTimeoutPacketWithCallback() { // The onPacketTimeout function in the contract doesn't modify the counter, // so we verify the callback was executed by checking the counter remains unchanged if strings.Contains(tc.memo(), "src_callback") { + senderEVM := common.BytesToAddress(sender) + expectsCallbackExec := contractAddr == senderEVM counterRes, err := evmApp.EVMKeeper.CallEVM( - ctxA, + suite.evmChainA.GetContext(), + stateDB, contractData.ABI, common.BytesToAddress(suite.evmChainA.SenderAccount.GetAddress()), contractAddr, false, + false, big.NewInt(100000), "getCounter", ) @@ -2036,15 +2128,19 @@ func (suite *MiddlewareTestSuite) TestOnTimeoutPacketWithCallback() { err = contractData.ABI.UnpackIntoInterface(&counter, "getCounter", counterRes.Ret) suite.Require().NoError(err) - // For timeout callbacks, counter should be -1 - // This verifies the callback was executed without error, but didn't change the counter - suite.Require().Equal(big.NewInt(-1).String(), counter.String(), "Counter should be -1 for timeout callbacks") + if expectsCallbackExec { + // For timeout callbacks, counter should be -1 + // This verifies the callback was executed without error, but didn't change the counter + suite.Require().Equal(big.NewInt(-1).String(), counter.String(), "Counter should be -1 for timeout callbacks") + } else { + suite.Require().Equal(big.NewInt(0).String(), counter.String(), "Counter should remain 0 when callback is gated") + } } // Verify refund for timeouts (tokens should always be refunded on timeout) if tc.onSendRequired { escrowAddr := transfertypes.GetEscrowAddress(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) - escrowedBal := evmApp.BankKeeper.GetBalance(ctxA, escrowAddr, bondDenom) + escrowedBal := evmApp.BankKeeper.GetBalance(suite.evmChainA.GetContext(), escrowAddr, bondDenom) // For timeouts, tokens should always be refunded suite.Require().True(escrowedBal.IsZero(), "Escrowed balance should be zero after timeout refund") @@ -2054,11 +2150,13 @@ func (suite *MiddlewareTestSuite) TestOnTimeoutPacketWithCallback() { // For timeout callback failures, verify that counter was NOT changed if strings.Contains(tc.memo(), "src_callback") && strings.Contains(tc.expError, "ABCI code") { counterRes, err := evmApp.EVMKeeper.CallEVM( - ctxA, + suite.evmChainA.GetContext(), + stateDB, contractData.ABI, common.BytesToAddress(suite.evmChainA.SenderAccount.GetAddress()), contractAddr, false, + false, big.NewInt(100000), "getCounter", ) @@ -2077,7 +2175,7 @@ func (suite *MiddlewareTestSuite) TestOnTimeoutPacketWithCallback() { if tc.onSendRequired && !strings.Contains(tc.expError, "cannot unmarshal") { // Even if callback fails, the timeout refund should still happen escrowAddr := transfertypes.GetEscrowAddress(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) - escrowedBal := evmApp.BankKeeper.GetBalance(ctxA, escrowAddr, bondDenom) + escrowedBal := evmApp.BankKeeper.GetBalance(suite.evmChainA.GetContext(), escrowAddr, bondDenom) suite.Require().True(escrowedBal.IsZero(), "Escrowed balance should be zero after timeout refund even with callback failure") suite.Require().Equal(balAfterTransfer.Amount.Add(sendAmt).String(), balAfterTimeout.Amount.String(), "Sender balance should be refunded on timeout") @@ -2118,7 +2216,6 @@ func (suite *MiddlewareTestSuite) TestOnTimeoutPacketNativeErc20() { suite.SetupTest() nativeErc20 := SetupNativeErc20(suite.T(), suite.evmChainA, suite.evmChainA.SenderAccounts[0]) - evmCtx := suite.evmChainA.GetContext() evmApp := suite.evmChainA.App.(*evmd.EVMD) timeoutHeight := clienttypes.NewHeight(1, 110) @@ -2130,35 +2227,42 @@ func (suite *MiddlewareTestSuite) TestOnTimeoutPacketNativeErc20() { sender := sdk.AccAddress(senderEthAddr.Bytes()) receiver := suite.chainB.SenderAccount.GetAddress() - msg := transfertypes.NewMsgTransfer( - path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, - sdk.NewCoin(nativeErc20.Denom, sendAmt), sender.String(), receiver.String(), - timeoutHeight, 0, "", - ) - escrowAddr := transfertypes.GetEscrowAddress(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) // checkEscrow is a check function to ensure the native erc20 token is escrowed. checkEscrow := func() { - erc20BalAfterIbcTransfer := evmApp.Erc20Keeper.BalanceOf(evmCtx, nativeErc20.ContractAbi, nativeErc20.ContractAddr, senderEthAddr) + erc20BalAfterIbcTransfer := evmApp.Erc20Keeper.BalanceOf(suite.evmChainA.GetContext(), nativeErc20.ContractAbi, nativeErc20.ContractAddr, senderEthAddr) suite.Require().Equal( new(big.Int).Sub(nativeErc20.InitialBal, sendAmt.BigInt()).String(), erc20BalAfterIbcTransfer.String(), ) - escrowedBal := evmApp.BankKeeper.GetBalance(evmCtx, escrowAddr, nativeErc20.Denom) + escrowedBal := evmApp.BankKeeper.GetBalance(suite.evmChainA.GetContext(), escrowAddr, nativeErc20.Denom) suite.Require().Equal(sendAmt.String(), escrowedBal.Amount.String()) } // checkRefund is a check function to ensure refund is processed. checkRefund := func() { - escrowedBal := evmApp.BankKeeper.GetBalance(evmCtx, escrowAddr, nativeErc20.Denom) + escrowedBal := evmApp.BankKeeper.GetBalance(suite.evmChainA.GetContext(), escrowAddr, nativeErc20.Denom) suite.Require().True(escrowedBal.IsZero()) // Check erc20 balance is same as initial balance after refund. - erc20BalAfterIbcTransfer := evmApp.Erc20Keeper.BalanceOf(evmCtx, nativeErc20.ContractAbi, nativeErc20.ContractAddr, senderEthAddr) + erc20BalAfterIbcTransfer := evmApp.Erc20Keeper.BalanceOf(suite.evmChainA.GetContext(), nativeErc20.ContractAbi, nativeErc20.ContractAddr, senderEthAddr) suite.Require().Equal(nativeErc20.InitialBal.String(), erc20BalAfterIbcTransfer.String()) } - _, err := suite.evmChainA.SendMsgs(msg) + + // Send the native erc20 token from evmChainA to chainB using the precompile. + _, err := suite.transferViaPrecompile( + suite.evmChainA.GetContext(), + path.EndpointA.ChannelConfig.PortID, + path.EndpointA.ChannelID, + sdk.NewCoin(nativeErc20.Denom, sendAmt), + sender.String(), + receiver.String(), + timeoutHeight, + 0, + "", + ) suite.Require().NoError(err) // message committed + suite.evmChainA.NextBlock() checkEscrow() transferStack, ok := suite.evmChainA.App.GetIBCKeeper().PortKeeper.Route(transfertypes.ModuleName) @@ -2188,7 +2292,7 @@ func (suite *MiddlewareTestSuite) TestOnTimeoutPacketNativeErc20() { sourceChan := path.EndpointA.GetChannel() err = transferStack.OnTimeoutPacket( - evmCtx, + suite.evmChainA.GetContext(), sourceChan.Version, packet, receiver, diff --git a/evmd/tests/ibc/ics02_precompile_client_test.go b/evmd/tests/ibc/ics02_precompile_client_test.go new file mode 100644 index 00000000..84a9fa87 --- /dev/null +++ b/evmd/tests/ibc/ics02_precompile_client_test.go @@ -0,0 +1,1016 @@ +package ibc + +import ( + "fmt" + "math/big" + "testing" + "time" + + "github.com/stretchr/testify/suite" + + abci "github.com/cometbft/cometbft/abci/types" + + "github.com/cosmos/evm/evmd" + "github.com/cosmos/evm/evmd/tests/integration" + "github.com/cosmos/evm/precompiles/ics02" + evmibctesting "github.com/cosmos/evm/testutil/ibc" + "github.com/cosmos/gogoproto/proto" + clienttypes "github.com/cosmos/ibc-go/v11/modules/core/02-client/types" + commitmenttypesv2 "github.com/cosmos/ibc-go/v11/modules/core/23-commitment/types/v2" + ibchost "github.com/cosmos/ibc-go/v11/modules/core/24-host" + ibcexported "github.com/cosmos/ibc-go/v11/modules/core/exported" + ibctm "github.com/cosmos/ibc-go/v11/modules/light-clients/07-tendermint" + ibctesting "github.com/cosmos/ibc-go/v11/testing" +) + +type ICS02ClientTestSuite struct { + suite.Suite + + coordinator *evmibctesting.Coordinator + + // testing chains used for convenience and readability + chainA *evmibctesting.TestChain + chainAPrecompile *ics02.Precompile + chainB *evmibctesting.TestChain + chainBPrecompile *ics02.Precompile + + pathBToA *evmibctesting.Path +} + +func (s *ICS02ClientTestSuite) SetupTest() { + s.coordinator = evmibctesting.NewCoordinator(s.T(), 2, 0, integration.SetupEvmd) + s.chainA = s.coordinator.GetChain(evmibctesting.GetEvmChainID(1)) + s.chainB = s.coordinator.GetChain(evmibctesting.GetEvmChainID(2)) + + s.pathBToA = evmibctesting.NewTransferPath(s.chainB, s.chainA) + s.pathBToA.Setup() + + evmAppA := s.chainA.App.(*evmd.EVMD) + s.chainAPrecompile = ics02.NewPrecompile( + evmAppA.AppCodec(), + evmAppA.IBCKeeper.ClientKeeper, + ) + evmAppB := s.chainB.App.(*evmd.EVMD) + s.chainBPrecompile = ics02.NewPrecompile( + evmAppA.AppCodec(), + evmAppB.IBCKeeper.ClientKeeper, + ) +} + +func (s *ICS02ClientTestSuite) TestGetClientState() { + var ( + calldata []byte + expClientState []byte + expErr bool + ) + + testCases := []struct { + name string + malleate func() + }{ + { + name: "success", + malleate: func() { + clientID := ibctesting.FirstClientID + clientState, found := s.chainA.App.(*evmd.EVMD).IBCKeeper.ClientKeeper.GetClientState( + s.chainA.GetContext(), + clientID, + ) + s.Require().True(found) + + var err error + calldata, err = s.chainAPrecompile.Pack(ics02.GetClientStateMethod, clientID) + s.Require().NoError(err) + + expClientState, err = proto.Marshal(clientState) + s.Require().NoError(err) + }, + }, + { + name: "failure: invalid client ID", + malleate: func() { + var err error + calldata, err = s.chainAPrecompile.Pack(ics02.GetClientStateMethod, ibctesting.InvalidID) + s.Require().NoError(err) + expErr = true + }, + }, + { + name: "failure: client not found", + malleate: func() { + var err error + calldata, err = s.chainAPrecompile.Pack(ics02.GetClientStateMethod, ibctesting.SecondClientID) + s.Require().NoError(err) + expErr = true + }, + }, + { + name: "failure: invalid calldata", + malleate: func() { + calldata = []byte(ibctesting.InvalidID) + expErr = true + }, + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + // == reset test state == + s.SetupTest() + + expClientState = nil + expErr = false + // ==== + + senderIdx := 1 + senderAccount := s.chainA.SenderAccounts[senderIdx] + + // setup + tc.malleate() + + _, _, resp, err := s.chainA.SendEvmTx(senderAccount, senderIdx, s.chainAPrecompile.Address(), big.NewInt(0), calldata, 100_000) + if expErr { + s.Require().Error(err) + return + } + s.Require().NoError(err) + + // decode result + out, err := s.chainAPrecompile.Unpack(ics02.GetClientStateMethod, resp.Ret) + s.Require().NoError(err) + + clientStateBz, ok := out[0].([]byte) + s.Require().True(ok) + s.Require().Equal(expClientState, clientStateBz) + }) + } +} + +func (s *ICS02ClientTestSuite) TestUpdateClient() { + var ( + expResult uint8 + calldata []byte + expErr bool + ) + + testCases := []struct { + name string + malleate func() + }{ + { + name: "success: update client", + malleate: func() { + clientID := ibctesting.FirstClientID + // == construct update header == + // 1. Update chain B to have new header + s.chainB.Coordinator.CommitBlock(s.chainB, s.chainA) + // 2. Construct update header + trustedHeight := s.chainA.App.(*evmd.EVMD).IBCKeeper.ClientKeeper.GetClientLatestHeight( + s.chainA.GetContext(), + clientID, + ) + header, err := s.pathBToA.EndpointA.Chain.IBCClientHeader(s.pathBToA.EndpointA.Chain.LatestCommittedHeader, trustedHeight) + s.Require().NoError(err) + + anyHeader, err := clienttypes.PackClientMessage(header) + s.Require().NoError(err) + + updateBz, err := anyHeader.Marshal() + s.Require().NoError(err) + + calldata, err = s.chainAPrecompile.Pack(ics02.UpdateClientMethod, clientID, updateBz) + s.Require().NoError(err) + // ==== + + expResult = ics02.UpdateResultSuccess + }, + }, + { + name: "success: noop", + malleate: func() { + clientID := ibctesting.FirstClientID + // == construct update header == + // 1. Update chain B to have new header + s.chainB.Coordinator.CommitBlock(s.chainB, s.chainA) + // 2. Construct update header + trustedHeight := s.chainA.App.(*evmd.EVMD).IBCKeeper.ClientKeeper.GetClientLatestHeight( + s.chainA.GetContext(), + clientID, + ) + header, err := s.pathBToA.EndpointA.Chain.IBCClientHeader(s.pathBToA.EndpointA.Chain.LatestCommittedHeader, trustedHeight) + s.Require().NoError(err) + + anyHeader, err := clienttypes.PackClientMessage(header) + s.Require().NoError(err) + + updateBz, err := anyHeader.Marshal() + s.Require().NoError(err) + + calldata, err = s.chainAPrecompile.Pack(ics02.UpdateClientMethod, clientID, updateBz) + s.Require().NoError(err) + // ==== + + err = s.chainA.App.(*evmd.EVMD).IBCKeeper.ClientKeeper.UpdateClient(s.chainA.GetContext(), clientID, header) + s.Require().NoError(err) + + expResult = ics02.UpdateResultSuccess + }, + }, + { + name: "success: valid fork misbehaviour", + malleate: func() { + clientID := ibctesting.FirstClientID + // == construct update header == + trustedHeight := s.chainA.App.(*evmd.EVMD).IBCKeeper.ClientKeeper.GetClientLatestHeight( + s.chainA.GetContext(), + clientID, + ) + trustedVals, ok := s.chainB.TrustedValidators[trustedHeight.RevisionHeight] + s.Require().True(ok) + + err := s.pathBToA.EndpointB.UpdateClient() + s.Require().NoError(err) + + height := s.chainA.App.(*evmd.EVMD).IBCKeeper.ClientKeeper.GetClientLatestHeight( + s.chainA.GetContext(), + clientID, + ) + + misbehaviour := &ibctm.Misbehaviour{ + ClientId: clientID, + Header1: s.chainB.CreateTMClientHeader(s.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, s.chainB.ProposedHeader.Time.Add(time.Minute), s.chainB.Vals, s.chainB.NextVals, trustedVals, s.chainB.Signers), + Header2: s.chainB.CreateTMClientHeader(s.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, s.chainB.ProposedHeader.Time, s.chainB.Vals, s.chainB.NextVals, trustedVals, s.chainB.Signers), + } + + anyMisbehavior, err := clienttypes.PackClientMessage(misbehaviour) + s.Require().NoError(err) + + updateBz, err := anyMisbehavior.Marshal() + s.Require().NoError(err) + + calldata, err = s.chainAPrecompile.Pack(ics02.UpdateClientMethod, clientID, updateBz) + s.Require().NoError(err) + // ==== + + expResult = ics02.UpdateResultMisbehaviour + }, + }, + { + name: "failure: invalid client ID", + malleate: func() { + clientID := ibctesting.FirstClientID + // == construct update header == + // 1. Update chain B to have new header + s.chainB.Coordinator.CommitBlock(s.chainB, s.chainA) + // 2. Construct update header + trustedHeight := s.chainA.App.(*evmd.EVMD).IBCKeeper.ClientKeeper.GetClientLatestHeight( + s.chainA.GetContext(), + clientID, + ) + header, err := s.pathBToA.EndpointA.Chain.IBCClientHeader(s.pathBToA.EndpointA.Chain.LatestCommittedHeader, trustedHeight) + s.Require().NoError(err) + + anyHeader, err := clienttypes.PackClientMessage(header) + s.Require().NoError(err) + + updateBz, err := anyHeader.Marshal() + s.Require().NoError(err) + + // use invalid client ID + calldata, err = s.chainAPrecompile.Pack(ics02.UpdateClientMethod, ibctesting.InvalidID, updateBz) + s.Require().NoError(err) + // ==== + expErr = true + }, + }, + { + name: "failure: invalid client message", + malleate: func() { + clientID := ibctesting.FirstClientID + + var err error + calldata, err = s.chainAPrecompile.Pack(ics02.UpdateClientMethod, clientID, []byte(ibctesting.InvalidID)) + s.Require().NoError(err) + // ==== + expErr = true + }, + }, + { + name: "failure: invalid calldata", + malleate: func() { + calldata = []byte(ibctesting.InvalidID) + expErr = true + }, + }, + { + name: "failure: invalid header update", + malleate: func() { + clientID := ibctesting.FirstClientID + // == construct update header == + // 1. Update chain B to have new header + s.chainB.Coordinator.CommitBlock(s.chainB, s.chainA) + // 2. Construct update header + trustedHeight := s.chainA.App.(*evmd.EVMD).IBCKeeper.ClientKeeper.GetClientLatestHeight( + s.chainA.GetContext(), + clientID, + ) + header, err := s.pathBToA.EndpointA.Chain.IBCClientHeader(s.pathBToA.EndpointA.Chain.LatestCommittedHeader, trustedHeight) + s.Require().NoError(err) + + // modify header to be invalid + header.Header.Time = header.Header.Time.Add(10 * time.Second) + + anyHeader, err := clienttypes.PackClientMessage(header) + s.Require().NoError(err) + + updateBz, err := anyHeader.Marshal() + s.Require().NoError(err) + + calldata, err = s.chainAPrecompile.Pack(ics02.UpdateClientMethod, clientID, updateBz) + s.Require().NoError(err) + // ==== + + expErr = true + }, + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + // == reset test state == + s.SetupTest() + + expResult = 0 + expErr = false + calldata = nil + // ==== + + senderIdx := 1 + senderAccount := s.chainA.SenderAccounts[senderIdx] + + // setup + tc.malleate() + + _, _, resp, err := s.chainA.SendEvmTx(senderAccount, senderIdx, s.chainAPrecompile.Address(), big.NewInt(0), calldata, 500_000) + if expErr { + s.Require().Error(err) + return + } + if err != nil { + s.FailNow("failed to send tx", "error: %v", err, "vmerror: %v", resp.VmError) + } + + // decode result + out, err := s.chainAPrecompile.Unpack(ics02.UpdateClientMethod, resp.Ret) + s.Require().NoError(err) + + res, ok := out[0].(uint8) + s.Require().True(ok) + s.Require().Equal(expResult, res) + }) + } +} + +func (s *ICS02ClientTestSuite) TestVerifyMembership() { + var ( + calldata []byte + expErr bool + expResult *big.Int + ) + + testCases := []struct { + name string + malleate func() + }{ + { + name: "success: prove membership of clientState", + malleate: func() { + clientID := ibctesting.FirstClientID + trustedHeight := s.chainA.App.(*evmd.EVMD).IBCKeeper.ClientKeeper.GetClientLatestHeight( + s.chainA.GetContext(), + clientID, + ) + + clientKey := ibchost.FullClientStateKey(clientID) + clientProof, proofHeight := s.pathBToA.EndpointA.QueryProofAtHeight(clientKey, trustedHeight.RevisionHeight) + + // get pure value from chain B + res, err := s.chainB.App.Query( + s.chainB.GetContext().Context(), + &abci.RequestQuery{ + Path: fmt.Sprintf("store/%s/key", ibcexported.StoreKey), + Height: int64(trustedHeight.RevisionHeight - 1), //nolint:gosec + Data: clientKey, + }) + s.Require().NoError(err) + value := res.Value + + pathBz := [][]byte{[]byte(ibcexported.StoreKey), clientKey} + calldata, err = s.chainAPrecompile.Pack(ics02.VerifyMembershipMethod, + clientID, + clientProof, + trustedHeight, + pathBz, + value, + ) + s.Require().NoError(err) + + timestampNano, err := s.chainA.App.(*evmd.EVMD).IBCKeeper.ClientKeeper.GetClientTimestampAtHeight(s.chainA.GetContext(), clientID, proofHeight) + s.Require().NoError(err) + + expResult = big.NewInt(int64(timestampNano / 1_000_000_000)) //nolint:gosec + + // verify membership on-chain to ensure proof is valid + path := commitmenttypesv2.NewMerklePath(pathBz...) + err = s.chainA.App.(*evmd.EVMD).IBCKeeper.ClientKeeper.VerifyMembership( + s.chainA.GetContext(), + clientID, + proofHeight, + 0, + 0, + clientProof, + path, + value, + ) + s.Require().NoError(err) + }, + }, + { + name: "failure: pass non-membership proof as membership proof", + malleate: func() { + existingClientID := ibctesting.FirstClientID + missingClientID := ibctesting.SecondClientID // NOTE: use a non-existent client ID + trustedHeight := s.chainA.App.(*evmd.EVMD).IBCKeeper.ClientKeeper.GetClientLatestHeight( + s.chainA.GetContext(), + existingClientID, + ) + + clientKey := ibchost.FullClientStateKey(missingClientID) + clientProof, _ := s.pathBToA.EndpointA.QueryProofAtHeight(clientKey, trustedHeight.RevisionHeight) + + // get pure value from chain B (for the existing client) + res, err := s.chainB.App.Query( + s.chainB.GetContext().Context(), + &abci.RequestQuery{ + Path: fmt.Sprintf("store/%s/key", ibcexported.StoreKey), + Height: int64(trustedHeight.RevisionHeight - 1), //nolint:gosec + Data: ibchost.FullClientStateKey(existingClientID), + }) + s.Require().NoError(err) + value := res.Value + + pathBz := [][]byte{[]byte(ibcexported.StoreKey), clientKey} + calldata, err = s.chainAPrecompile.Pack(ics02.VerifyMembershipMethod, + existingClientID, + clientProof, + trustedHeight, + pathBz, + value, + ) + s.Require().NoError(err) + + expErr = true + }, + }, + { + name: "failure: invalid client ID", + malleate: func() { + clientID := ibctesting.FirstClientID + trustedHeight := s.chainA.App.(*evmd.EVMD).IBCKeeper.ClientKeeper.GetClientLatestHeight( + s.chainA.GetContext(), + clientID, + ) + + clientKey := ibchost.FullClientStateKey(clientID) + clientProof, _ := s.pathBToA.EndpointA.QueryProofAtHeight(clientKey, trustedHeight.RevisionHeight) + + // get pure value from chain B + res, err := s.chainB.App.Query( + s.chainB.GetContext().Context(), + &abci.RequestQuery{ + Path: fmt.Sprintf("store/%s/key", ibcexported.StoreKey), + Height: int64(trustedHeight.RevisionHeight - 1), //nolint:gosec + Data: clientKey, + }) + s.Require().NoError(err) + value := res.Value + + pathBz := [][]byte{[]byte(ibcexported.StoreKey), clientKey} + calldata, err = s.chainAPrecompile.Pack(ics02.VerifyMembershipMethod, + ibctesting.InvalidID, // use invalid client ID + clientProof, + trustedHeight, + pathBz, + value, + ) + s.Require().NoError(err) + + expErr = true + }, + }, + { + name: "failure: invalid proof", + malleate: func() { + clientID := ibctesting.FirstClientID + trustedHeight := s.chainA.App.(*evmd.EVMD).IBCKeeper.ClientKeeper.GetClientLatestHeight( + s.chainA.GetContext(), + clientID, + ) + + clientKey := ibchost.FullClientStateKey(clientID) + // get pure value from chain B + res, err := s.chainB.App.Query( + s.chainB.GetContext().Context(), + &abci.RequestQuery{ + Path: fmt.Sprintf("store/%s/key", ibcexported.StoreKey), + Height: int64(trustedHeight.RevisionHeight - 1), //nolint:gosec + Data: clientKey, + }) + s.Require().NoError(err) + value := res.Value + + pathBz := [][]byte{[]byte(ibcexported.StoreKey), clientKey} + calldata, err = s.chainAPrecompile.Pack(ics02.VerifyMembershipMethod, + clientID, + []byte(ibctesting.InvalidID), // use invalid client proof + trustedHeight, + pathBz, + value, + ) + s.Require().NoError(err) + + expErr = true + }, + }, + { + name: "failure: invalid height", + malleate: func() { + clientID := ibctesting.FirstClientID + trustedHeight := s.chainA.App.(*evmd.EVMD).IBCKeeper.ClientKeeper.GetClientLatestHeight( + s.chainA.GetContext(), + clientID, + ) + + clientKey := ibchost.FullClientStateKey(clientID) + clientProof, _ := s.pathBToA.EndpointA.QueryProofAtHeight(clientKey, trustedHeight.RevisionHeight) + + // get pure value from chain B + res, err := s.chainB.App.Query( + s.chainB.GetContext().Context(), + &abci.RequestQuery{ + Path: fmt.Sprintf("store/%s/key", ibcexported.StoreKey), + Height: int64(trustedHeight.RevisionHeight - 1), //nolint:gosec + Data: clientKey, + }) + s.Require().NoError(err) + value := res.Value + + pathBz := [][]byte{[]byte(ibcexported.StoreKey), clientKey} + calldata, err = s.chainAPrecompile.Pack(ics02.VerifyMembershipMethod, + clientID, + clientProof, + clienttypes.NewHeight(69, 420), // use invalid height + pathBz, + value, + ) + s.Require().NoError(err) + + expErr = true + }, + }, + { + name: "failure: invalid path", + malleate: func() { + clientID := ibctesting.FirstClientID + trustedHeight := s.chainA.App.(*evmd.EVMD).IBCKeeper.ClientKeeper.GetClientLatestHeight( + s.chainA.GetContext(), + clientID, + ) + + clientKey := ibchost.FullClientStateKey(clientID) + clientProof, _ := s.pathBToA.EndpointA.QueryProofAtHeight(clientKey, trustedHeight.RevisionHeight) + + // get pure value from chain B + res, err := s.chainB.App.Query( + s.chainB.GetContext().Context(), + &abci.RequestQuery{ + Path: fmt.Sprintf("store/%s/key", ibcexported.StoreKey), + Height: int64(trustedHeight.RevisionHeight - 1), //nolint:gosec + Data: clientKey, + }) + s.Require().NoError(err) + value := res.Value + + pathBz := [][]byte{[]byte(ibctesting.InvalidID), clientKey} // use invalid path + calldata, err = s.chainAPrecompile.Pack(ics02.VerifyMembershipMethod, + clientID, + clientProof, + trustedHeight, + pathBz, + value, + ) + s.Require().NoError(err) + + expErr = true + }, + }, + { + name: "failure: invalid value", + malleate: func() { + clientID := ibctesting.FirstClientID + trustedHeight := s.chainA.App.(*evmd.EVMD).IBCKeeper.ClientKeeper.GetClientLatestHeight( + s.chainA.GetContext(), + clientID, + ) + + clientKey := ibchost.FullClientStateKey(clientID) + clientProof, _ := s.pathBToA.EndpointA.QueryProofAtHeight(clientKey, trustedHeight.RevisionHeight) + + pathBz := [][]byte{[]byte(ibcexported.StoreKey), clientKey} + var err error + calldata, err = s.chainAPrecompile.Pack(ics02.VerifyMembershipMethod, + clientID, + clientProof, + trustedHeight, + pathBz, + []byte(ibctesting.InvalidID), // use invalid value + ) + s.Require().NoError(err) + + expErr = true + }, + }, + { + name: "failure: invalid calldata", + malleate: func() { + calldata = []byte(ibctesting.InvalidID) + expErr = true + }, + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + // == reset test state == + s.SetupTest() + + expErr = false + calldata = nil + // ==== + + senderIdx := 1 + senderAccount := s.chainA.SenderAccounts[senderIdx] + + // setup + tc.malleate() + + _, _, resp, err := s.chainA.SendEvmTx(senderAccount, senderIdx, s.chainAPrecompile.Address(), big.NewInt(0), calldata, 100_000) + if expErr { + s.Require().Error(err) + return + } + s.Require().NoError(err) + + // decode result + out, err := s.chainAPrecompile.Unpack(ics02.VerifyMembershipMethod, resp.Ret) + s.Require().NoError(err) + + res, ok := out[0].(*big.Int) + s.Require().True(ok) + s.Require().Equal(expResult, res) + }) + } +} + +func (s *ICS02ClientTestSuite) TestVerifyNonMembership() { + var ( + calldata []byte + expErr bool + expResult *big.Int + ) + + testCases := []struct { + name string + malleate func() + }{ + { + name: "success: prove non-membership of clientState", + malleate: func() { + existingClientID := ibctesting.FirstClientID + missingClientID := ibctesting.SecondClientID // NOTE: use a non-existent client ID + trustedHeight := s.chainA.App.(*evmd.EVMD).IBCKeeper.ClientKeeper.GetClientLatestHeight( + s.chainA.GetContext(), + existingClientID, + ) + + clientKey := ibchost.FullClientStateKey(missingClientID) + clientProof, proofHeight := s.pathBToA.EndpointA.QueryProofAtHeight(clientKey, trustedHeight.RevisionHeight) + + pathBz := [][]byte{[]byte(ibcexported.StoreKey), clientKey} + var err error + calldata, err = s.chainAPrecompile.Pack(ics02.VerifyNonMembershipMethod, + existingClientID, + clientProof, + trustedHeight, + pathBz, + ) + s.Require().NoError(err) + + timestampNano, err := s.chainA.App.(*evmd.EVMD).IBCKeeper.ClientKeeper.GetClientTimestampAtHeight(s.chainA.GetContext(), existingClientID, proofHeight) + s.Require().NoError(err) + + expResult = big.NewInt(int64(timestampNano / 1_000_000_000)) //nolint:gosec + + // verify non-membership on-chain to ensure proof is valid + path := commitmenttypesv2.NewMerklePath(pathBz...) + err = s.chainA.App.(*evmd.EVMD).IBCKeeper.ClientKeeper.VerifyNonMembership( + s.chainA.GetContext(), + existingClientID, + proofHeight, + 0, + 0, + clientProof, + path, + ) + s.Require().NoError(err) + }, + }, + { + name: "failure: pass membership proof as non-membership proof", + malleate: func() { + clientID := ibctesting.FirstClientID + trustedHeight := s.chainA.App.(*evmd.EVMD).IBCKeeper.ClientKeeper.GetClientLatestHeight( + s.chainA.GetContext(), + clientID, + ) + + clientKey := ibchost.FullClientStateKey(clientID) + clientProof, _ := s.pathBToA.EndpointA.QueryProofAtHeight(clientKey, trustedHeight.RevisionHeight) + + pathBz := [][]byte{[]byte(ibcexported.StoreKey), clientKey} + var err error + calldata, err = s.chainAPrecompile.Pack(ics02.VerifyNonMembershipMethod, + clientID, + clientProof, + trustedHeight, + pathBz, + ) + s.Require().NoError(err) + + expErr = true + }, + }, + { + name: "failure: invalid client ID", + malleate: func() { + existingClientID := ibctesting.FirstClientID + missingClientID := ibctesting.SecondClientID // NOTE: use a non-existent client ID + trustedHeight := s.chainA.App.(*evmd.EVMD).IBCKeeper.ClientKeeper.GetClientLatestHeight( + s.chainA.GetContext(), + existingClientID, + ) + + clientKey := ibchost.FullClientStateKey(missingClientID) + clientProof, _ := s.pathBToA.EndpointA.QueryProofAtHeight(clientKey, trustedHeight.RevisionHeight) + + pathBz := [][]byte{[]byte(ibcexported.StoreKey), clientKey} + var err error + calldata, err = s.chainAPrecompile.Pack(ics02.VerifyNonMembershipMethod, + ibctesting.InvalidID, // use invalid client ID + clientProof, + trustedHeight, + pathBz, + ) + s.Require().NoError(err) + + expErr = true + }, + }, + { + name: "failure: invalid proof", + malleate: func() { + existingClientID := ibctesting.FirstClientID + missingClientID := ibctesting.SecondClientID // NOTE: use a non-existent client ID + trustedHeight := s.chainA.App.(*evmd.EVMD).IBCKeeper.ClientKeeper.GetClientLatestHeight( + s.chainA.GetContext(), + existingClientID, + ) + + clientKey := ibchost.FullClientStateKey(missingClientID) + pathBz := [][]byte{[]byte(ibcexported.StoreKey), clientKey} + var err error + calldata, err = s.chainAPrecompile.Pack(ics02.VerifyNonMembershipMethod, + existingClientID, + []byte(ibctesting.InvalidID), // use invalid client proof + trustedHeight, + pathBz, + ) + s.Require().NoError(err) + + expErr = true + }, + }, + { + name: "failure: invalid height", + malleate: func() { + existingClientID := ibctesting.FirstClientID + missingClientID := ibctesting.SecondClientID // NOTE: use a non-existent client ID + trustedHeight := s.chainA.App.(*evmd.EVMD).IBCKeeper.ClientKeeper.GetClientLatestHeight( + s.chainA.GetContext(), + existingClientID, + ) + + clientKey := ibchost.FullClientStateKey(missingClientID) + clientProof, _ := s.pathBToA.EndpointA.QueryProofAtHeight(clientKey, trustedHeight.RevisionHeight) + + pathBz := [][]byte{[]byte(ibcexported.StoreKey), clientKey} + var err error + calldata, err = s.chainAPrecompile.Pack(ics02.VerifyNonMembershipMethod, + existingClientID, + clientProof, + clienttypes.NewHeight(69, 420), // use invalid height + pathBz, + ) + s.Require().NoError(err) + + expErr = true + }, + }, + { + name: "failure: invalid path", + malleate: func() { + existingClientID := ibctesting.FirstClientID + missingClientID := ibctesting.SecondClientID // NOTE: use a non-existent client ID + trustedHeight := s.chainA.App.(*evmd.EVMD).IBCKeeper.ClientKeeper.GetClientLatestHeight( + s.chainA.GetContext(), + existingClientID, + ) + + clientKey := ibchost.FullClientStateKey(missingClientID) + clientProof, _ := s.pathBToA.EndpointA.QueryProofAtHeight(clientKey, trustedHeight.RevisionHeight) + + pathBz := [][]byte{[]byte(ibctesting.InvalidID), clientKey} // use invalid path + var err error + calldata, err = s.chainAPrecompile.Pack(ics02.VerifyNonMembershipMethod, + existingClientID, + clientProof, + trustedHeight, + pathBz, + ) + s.Require().NoError(err) + + expErr = true + }, + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + // == reset test state == + s.SetupTest() + + expErr = false + calldata = nil + // ==== + + senderIdx := 1 + senderAccount := s.chainA.SenderAccounts[senderIdx] + + // setup + tc.malleate() + + _, _, resp, err := s.chainA.SendEvmTx(senderAccount, senderIdx, s.chainAPrecompile.Address(), big.NewInt(0), calldata, 100_000) + if expErr { + s.Require().Error(err) + return + } + s.Require().NoError(err) + + // decode result + out, err := s.chainAPrecompile.Unpack(ics02.VerifyNonMembershipMethod, resp.Ret) + s.Require().NoError(err) + + res, ok := out[0].(*big.Int) + s.Require().True(ok) + s.Require().Equal(expResult, res) + }) + } +} + +func (s *ICS02ClientTestSuite) TestFalseMisbehaviourClientFreezeAttack() { + clientID := ibctesting.FirstClientID + evmAppA := s.chainA.App.(*evmd.EVMD) + + // --------------------------------------------------------------- + // Step 1: Record the current trusted height (the client's latest + // consensus state) and the trusted validators at that height. + // --------------------------------------------------------------- + trustedHeight := evmAppA.IBCKeeper.ClientKeeper.GetClientLatestHeight( + s.chainA.GetContext(), clientID, + ) + trustedVals, ok := s.chainB.TrustedValidators[trustedHeight.RevisionHeight] + s.Require().True(ok, "must have trusted validators at the client's latest height") + + // --------------------------------------------------------------- + // Step 2: Create Header 1 at height H (= trustedHeight + 1). + // This is a perfectly legitimate header from chainB, signed by + // chainB's current validator set. + // --------------------------------------------------------------- + heightH := int64(trustedHeight.RevisionHeight) + 1 + timeH := s.chainB.ProposedHeader.Time.Add(1 * time.Minute) + + header1 := s.chainB.CreateTMClientHeader( + s.chainB.ChainID, + heightH, + clienttypes.Height(trustedHeight), + timeH, + s.chainB.Vals, + s.chainB.NextVals, + trustedVals, + s.chainB.Signers, + ) + + // --------------------------------------------------------------- + // Step 3: Create Header 2 at height H+1 (higher than Header 1) + // with a later timestamp (normal BFT monotonic time). + // Both headers reference the same trustedHeight. + // --------------------------------------------------------------- + heightH1 := heightH + 1 + timeH1 := timeH.Add(1 * time.Minute) // later time for higher height (normal) + + header2 := s.chainB.CreateTMClientHeader( + s.chainB.ChainID, + heightH1, + clienttypes.Height(trustedHeight), + timeH1, + s.chainB.Vals, + s.chainB.NextVals, + trustedVals, + s.chainB.Signers, + ) + + // --------------------------------------------------------------- + // Step 4: Build the Misbehaviour with REVERSED ordering. + // + // Header1 = header at height H (LOWER) + // Header2 = header at height H+1 (HIGHER) + // + // ValidateBasic() requires Header1.Height >= Header2.Height. + // Here Header1.Height < Header2.Height -- invalid ordering. + // --------------------------------------------------------------- + misbehaviour := &ibctm.Misbehaviour{ + ClientId: clientID, + Header1: header1, // height H (lower) + Header2: header2, // height H+1 (higher) + } + + // --------------------------------------------------------------- + // Step 5: Serialize the misbehaviour as protobuf Any and marshal + // to bytes, exactly as the precompile will receive it. + // --------------------------------------------------------------- + anyMisbehaviour, err := clienttypes.PackClientMessage(misbehaviour) + s.Require().NoError(err) + + updateBz, err := anyMisbehaviour.Marshal() + s.Require().NoError(err) + + // ABI-encode the precompile call + calldata, err := s.chainAPrecompile.Pack( + ics02.UpdateClientMethod, clientID, updateBz, + ) + s.Require().NoError(err) + + // --------------------------------------------------------------- + // Step 6: Submit via an EVM transaction to the ICS02 precompile. + // The precompile deserializes the bytes and calls + // keeper.UpdateClient WITHOUT calling ValidateBasic(). + // --------------------------------------------------------------- + senderIdx := 1 + senderAccount := s.chainA.SenderAccounts[senderIdx] + + _, _, _, err = s.chainA.SendEvmTx( + senderAccount, senderIdx, + s.chainAPrecompile.Address(), + big.NewInt(0), + calldata, + 200_000, + ) + + // --------------------------------------------------------------- + // Step 7: Assert the attack failed. + // --------------------------------------------------------------- + s.Require().Error(err, "ValidateBasic error should be returned by precompile") + + // --------------------------------------------------------------- + // Step 8: Assert the client is still active (not frozen). + // --------------------------------------------------------------- + status := evmAppA.IBCKeeper.ClientKeeper.GetClientStatus( + s.chainA.GetContext(), clientID, + ) + s.Require().Equal(ibcexported.Active, status, + "client must be active after the failed attack") +} + +func TestICS02ClientTestSuite(t *testing.T) { + suite.Run(t, new(ICS02ClientTestSuite)) +} diff --git a/evmd/tests/ibc/ics20_erc20_conversion_test.go b/evmd/tests/ibc/ics20_erc20_conversion_test.go new file mode 100644 index 00000000..8f26b935 --- /dev/null +++ b/evmd/tests/ibc/ics20_erc20_conversion_test.go @@ -0,0 +1,500 @@ +package ibc + +import ( + "fmt" + "math/big" + "strings" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/evmd" + "github.com/cosmos/evm/evmd/tests/integration" + "github.com/cosmos/evm/precompiles/ics20" + evmibctesting "github.com/cosmos/evm/testutil/ibc" + erc20types "github.com/cosmos/evm/x/erc20/types" + transfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/v11/modules/core/02-client/types" + + sdkmath "cosmossdk.io/math" + + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" +) + +type ICS20ERC20ConversionTestSuite struct { + suite.Suite + + coordinator *evmibctesting.Coordinator + + chainA *evmibctesting.TestChain + chainAPrecompile *ics20.Precompile + chainB *evmibctesting.TestChain + chainBPrecompile *ics20.Precompile +} + +func (suite *ICS20ERC20ConversionTestSuite) SetupTest() { + suite.coordinator = evmibctesting.NewCoordinator(suite.T(), 2, 0, integration.SetupEvmd) + suite.chainA = suite.coordinator.GetChain(evmibctesting.GetEvmChainID(1)) + suite.chainB = suite.coordinator.GetChain(evmibctesting.GetEvmChainID(2)) + + evmAppA := suite.chainA.App.(*evmd.EVMD) + suite.chainAPrecompile = ics20.NewPrecompile( + evmAppA.BankKeeper, + *evmAppA.StakingKeeper, + evmAppA.TransferKeeper, + evmAppA.IBCKeeper.ChannelKeeper, + evmAppA.Erc20Keeper, + ) + evmAppB := suite.chainB.App.(*evmd.EVMD) + suite.chainBPrecompile = ics20.NewPrecompile( + evmAppB.BankKeeper, + *evmAppB.StakingKeeper, + evmAppB.TransferKeeper, + evmAppB.IBCKeeper.ChannelKeeper, + evmAppB.Erc20Keeper, + ) +} + +func TestICS20ERC20ConversionTestSuite(t *testing.T) { + suite.Run(t, new(ICS20ERC20ConversionTestSuite)) +} + +// TestTransferWithERC20Conversion tests IBC transfers with ERC20 token conversion +func (suite *ICS20ERC20ConversionTestSuite) TestTransferWithERC20Conversion() { + var ( + denom string + amount sdkmath.Int + sender common.Address + nativeErc20 *NativeErc20Info + path *evmibctesting.Path + ) + + receiver := suite.chainB.SenderAccount.GetAddress().String() + timeoutHeight := clienttypes.NewHeight(1, 110) + + testCases := []struct { + name string + malleate func() + expPass bool + }{ + { + "pass - no token pair", + func() { + evmAppA := suite.chainA.App.(*evmd.EVMD) + var err error + denom, err = evmAppA.StakingKeeper.BondDenom(suite.chainA.GetContext()) + suite.Require().NoError(err) + amount = sdkmath.NewInt(10) + sender = common.BytesToAddress(suite.chainA.SenderAccount.GetAddress().Bytes()) + }, + true, + }, + { + "no-op - disabled erc20 by params - sufficient sdk.Coins balance", + func() { + // Deploy and mint ERC20 + nativeErc20 = SetupNativeErc20(suite.T(), suite.chainA, suite.chainA.SenderAccounts[0]) + denom = nativeErc20.Denom + amount = sdkmath.NewInt(nativeErc20.InitialBal.Int64()) + + // Convert ERC20 to coins + evmAppA := suite.chainA.App.(*evmd.EVMD) + _, err := evmAppA.Erc20Keeper.ConvertERC20(suite.chainA.GetContext(), &erc20types.MsgConvertERC20{ + ContractAddress: nativeErc20.ContractAddr.Hex(), + Amount: amount, + Receiver: suite.chainA.SenderAccount.GetAddress().String(), + Sender: nativeErc20.Account.Hex(), + }) + suite.Require().NoError(err) + suite.chainA.NextBlock() + + // Disable ERC20 + params := evmAppA.Erc20Keeper.GetParams(suite.chainA.GetContext()) + params.EnableErc20 = false + err = evmAppA.Erc20Keeper.SetParams(suite.chainA.GetContext(), params) + suite.Require().NoError(err) + suite.chainA.NextBlock() + + sender = nativeErc20.Account + }, + true, + }, + { + "error - disabled erc20 by params - insufficient sdk.Coins balance", + func() { + // Deploy and mint ERC20 but don't convert + nativeErc20 = SetupNativeErc20(suite.T(), suite.chainA, suite.chainA.SenderAccounts[0]) + denom = nativeErc20.Denom + amount = sdkmath.NewInt(nativeErc20.InitialBal.Int64()) + + evmAppA := suite.chainA.App.(*evmd.EVMD) + ctx := suite.chainA.GetContext() + + // No conversion to IBC coin, so the balance is insufficient + suite.Require().EqualValues( + evmAppA.BankKeeper.GetBalance(ctx, suite.chainA.SenderAccount.GetAddress(), denom).Amount, + sdkmath.ZeroInt(), + "Bank balance should be zero since we didn't convert", + ) + + // Disable ERC20 without converting + params := evmAppA.Erc20Keeper.GetParams(ctx) + params.EnableErc20 = false + err := evmAppA.Erc20Keeper.SetParams(ctx, params) + suite.Require().NoError(err) + suite.chainA.NextBlock() + + sender = nativeErc20.Account + }, + false, + }, + { + "error - pair not registered", + func() { + denom = "unregistered" + amount = sdkmath.NewInt(10) + sender = common.BytesToAddress(suite.chainA.SenderAccount.GetAddress().Bytes()) + }, + false, + }, + { + "no-op - pair is disabled", + func() { + // Deploy and mint ERC20 + nativeErc20 = SetupNativeErc20(suite.T(), suite.chainA, suite.chainA.SenderAccounts[0]) + denom = nativeErc20.Denom + amount = sdkmath.NewInt(nativeErc20.InitialBal.Int64()) + + // Convert to coins first + evmAppA := suite.chainA.App.(*evmd.EVMD) + _, err := evmAppA.Erc20Keeper.ConvertERC20(suite.chainA.GetContext(), &erc20types.MsgConvertERC20{ + ContractAddress: nativeErc20.ContractAddr.Hex(), + Amount: amount, + Receiver: suite.chainA.SenderAccount.GetAddress().String(), + Sender: nativeErc20.Account.Hex(), + }) + suite.Require().NoError(err) + suite.chainA.NextBlock() + + // Disable the token pair + govAddr := authtypes.NewModuleAddress(govtypes.ModuleName).String() + _, err = evmAppA.Erc20Keeper.ToggleConversion(suite.chainA.GetContext(), &erc20types.MsgToggleConversion{ + Token: denom, + Authority: govAddr, + }) + suite.Require().NoError(err) + suite.chainA.NextBlock() + + sender = nativeErc20.Account + }, + true, + }, + { + "pass - has enough balance in erc20 - need to convert", + func() { + // Deploy and mint ERC20 but don't convert - transfer should auto-convert + nativeErc20 = SetupNativeErc20(suite.T(), suite.chainA, suite.chainA.SenderAccounts[0]) + denom = nativeErc20.Denom + amount = sdkmath.NewInt(nativeErc20.InitialBal.Int64()) + + // Verify denom format is correct + suite.Require().Equal( + erc20types.CreateDenom(nativeErc20.ContractAddr.String()), + denom, + "Denom should match the ERC20 contract address format", + ) + + sender = nativeErc20.Account + }, + true, + }, + { + "pass - has enough balance in coins", + func() { + // Deploy and mint ERC20 + nativeErc20 = SetupNativeErc20(suite.T(), suite.chainA, suite.chainA.SenderAccounts[0]) + denom = nativeErc20.Denom + amount = sdkmath.NewInt(nativeErc20.InitialBal.Int64()) + + // Convert to coins + evmAppA := suite.chainA.App.(*evmd.EVMD) + _, err := evmAppA.Erc20Keeper.ConvertERC20(suite.chainA.GetContext(), &erc20types.MsgConvertERC20{ + ContractAddress: nativeErc20.ContractAddr.Hex(), + Amount: amount, + Receiver: suite.chainA.SenderAccount.GetAddress().String(), + Sender: nativeErc20.Account.Hex(), + }) + suite.Require().NoError(err) + suite.chainA.NextBlock() + + sender = nativeErc20.Account + }, + true, + }, + { + "error - fail conversion - no balance in erc20", + func() { + // Deploy and register ERC20 but don't mint + nativeErc20 = SetupNativeErc20(suite.T(), suite.chainA, suite.chainA.SenderAccounts[0]) + denom = nativeErc20.Denom + // Request more than minted + amount = sdkmath.NewInt(nativeErc20.InitialBal.Int64() * 2) + sender = nativeErc20.Account + }, + false, + }, + { + "pass - verify correct prefix trimming for ERC20 native tokens", + func() { + // Deploy and mint ERC20 + nativeErc20 = SetupNativeErc20(suite.T(), suite.chainA, suite.chainA.SenderAccounts[0]) + denom = nativeErc20.Denom + amount = sdkmath.NewInt(nativeErc20.InitialBal.Int64()) + + evmAppA := suite.chainA.App.(*evmd.EVMD) + ctx := suite.chainA.GetContext() + + // Create a denom with erc20: prefix + erc20Denom := erc20types.CreateDenom(nativeErc20.ContractAddr.String()) + suite.Require().Equal(erc20types.Erc20NativeCoinDenomPrefix+nativeErc20.ContractAddr.String(), erc20Denom) + + // Verify that GetTokenPairID works correctly with the contract address (hex string) + pairIDFromAddress := evmAppA.Erc20Keeper.GetTokenPairID(ctx, nativeErc20.ContractAddr.String()) + suite.Require().NotEmpty(pairIDFromAddress) + + // Verify that GetTokenPairID works correctly with the full denom + pairIDFromDenom := evmAppA.Erc20Keeper.GetTokenPairID(ctx, erc20Denom) + suite.Require().NotEmpty(pairIDFromDenom) + + // Both should return the same pair ID + suite.Require().Equal(pairIDFromAddress, pairIDFromDenom) + + sender = nativeErc20.Account + }, + true, + }, + { + "no-op - fail transfer", + func() { + evmAppA := suite.chainA.App.(*evmd.EVMD) + ctx := suite.chainA.GetContext() + senderAcc := suite.chainA.SenderAccount.GetAddress() + + // Create a fake IBC voucher denom (IBC-transferred token) + denom = "ibc/DF63978F803A2E27CA5CC9B7631654CCF0BBC788B3B7F0A10200508E37C70992" + + // Register it as an ERC20 extension + _, err := evmAppA.Erc20Keeper.RegisterERC20Extension(ctx, denom) + suite.Require().NoError(err) + suite.chainA.NextBlock() + + // Verify the pair exists + pairID := evmAppA.Erc20Keeper.GetTokenPairID(ctx, denom) + suite.Require().NotEmpty(pairID, "Token pair should be registered") + + pair, found := evmAppA.Erc20Keeper.GetTokenPair(ctx, pairID) + suite.Require().True(found) + suite.Require().Equal(pair.Denom, denom) + + // Try to transfer without having any balance (should fail) + amount = sdkmath.NewInt(10) + sender = common.BytesToAddress(senderAcc) + }, + false, + }, + } + + for _, tc := range testCases { + suite.Run(fmt.Sprintf("Case %s", tc.name), func() { + suite.SetupTest() + + // Setup IBC path + path = evmibctesting.NewTransferPath(suite.chainA, suite.chainB) + path.Setup() + + // Run test-specific setup + tc.malleate() + + // Call precompile transfer + data, err := suite.chainAPrecompile.ABI.Pack( + "transfer", + transfertypes.PortID, + path.EndpointA.ChannelID, + denom, + amount.BigInt(), + sender, + receiver, + timeoutHeight, + uint64(0), + "", + ) + suite.Require().NoError(err) + + res, _, _, err := suite.chainA.SendEvmTx( + suite.chainA.SenderAccounts[0], + 0, + suite.chainAPrecompile.Address(), + big.NewInt(0), + data, + 0, + ) + + if tc.expPass { + suite.Require().NoError(err) + suite.Require().Equal(uint32(0), res.Code, res.Log) + } else { + suite.Require().Error(err) + } + }) + } +} + +// TestPrefixTrimming specifically tests that the erc20: prefix is correctly handled +func (suite *ICS20ERC20ConversionTestSuite) TestPrefixTrimming() { + var ( + denom string + amount sdkmath.Int + sender common.Address + nativeErc20 *NativeErc20Info + path *evmibctesting.Path + ) + + receiver := suite.chainB.SenderAccount.GetAddress().String() + timeoutHeight := clienttypes.NewHeight(1, 110) + + testCases := []struct { + name string + malleate func() + expPass bool + }{ + { + "pass - correct prefix trimming erc20:", + func() { + nativeErc20 = SetupNativeErc20(suite.T(), suite.chainA, suite.chainA.SenderAccounts[0]) + denom = nativeErc20.Denom + amount = sdkmath.NewInt(nativeErc20.InitialBal.Int64()) + + // Verify the denom has the correct prefix + suite.Require().Contains(denom, erc20types.Erc20NativeCoinDenomPrefix) + + evmAppA := suite.chainA.App.(*evmd.EVMD) + ctx := suite.chainA.GetContext() + + // TEST: Verify that the prefix trimming works correctly + // The Transfer method should trim "erc20:" prefix to get the hex address + expectedTrimmed := strings.TrimPrefix(denom, erc20types.Erc20NativeCoinDenomPrefix) + suite.Require().Equal(nativeErc20.ContractAddr.String(), expectedTrimmed, + "Correct: Trimming 'erc20:' yields the contract address") + + // TEST: Verify that incorrect prefix trimming would fail + // If we incorrectly trim "erc20/" instead of "erc20:", we'd get the wrong string + incorrectTrimmed := strings.TrimPrefix(denom, erc20types.ModuleName+"/") + suite.Require().NotEqual(nativeErc20.ContractAddr.String(), incorrectTrimmed, + "Bug: Trimming 'erc20/' does not yield the contract address") + suite.Require().Equal(denom, incorrectTrimmed, + "Since 'erc20/' is not in the string, TrimPrefix returns it unchanged") + + // Verify that GetTokenPairID works correctly with the contract address (hex string) + pairIDFromAddress := evmAppA.Erc20Keeper.GetTokenPairID(ctx, nativeErc20.ContractAddr.String()) + suite.Require().NotEmpty(pairIDFromAddress) + + // Verify that GetTokenPairID works correctly with the full denom + pairIDFromDenom := evmAppA.Erc20Keeper.GetTokenPairID(ctx, denom) + suite.Require().NotEmpty(pairIDFromDenom) + + // Both should return the same pair ID + suite.Require().Equal(pairIDFromAddress, pairIDFromDenom) + + sender = nativeErc20.Account + }, + true, + }, + { + "pass - demonstrate bug impact", + func() { + nativeErc20 = SetupNativeErc20(suite.T(), suite.chainA, suite.chainA.SenderAccounts[0]) + denom = nativeErc20.Denom + amount = sdkmath.NewInt(nativeErc20.InitialBal.Int64()) + + evmAppA := suite.chainA.App.(*evmd.EVMD) + ctx := suite.chainA.GetContext() + + // Demonstrate the bug's impact: incorrect vs correct prefix trimming + // The denom format is "erc20:0x1234..." where "erc20:" is the prefix + + // CORRECT trimming: trim "erc20:" to get the hex address + correctTrimmed := strings.TrimPrefix(denom, erc20types.Erc20NativeCoinDenomPrefix) + suite.Require().Equal(nativeErc20.ContractAddr.String(), correctTrimmed, + "Trimming 'erc20:' should yield the contract address") + + // INCORRECT trimming: trim "erc20/" instead (the bug) + // This doesn't match the actual prefix, so TrimPrefix returns the string unchanged + incorrectTrimmed := strings.TrimPrefix(denom, erc20types.ModuleName+"/") + suite.Require().Equal(denom, incorrectTrimmed, + "Trimming 'erc20/' should not change the string since prefix is 'erc20:'") + suite.Require().NotEqual(nativeErc20.ContractAddr.String(), incorrectTrimmed, + "Incorrect trimming does not yield the contract address") + + // Demonstrate why the bug wasn't caught earlier: + // Both lookups work due to dual mapping in the keeper + // The keeper maps both "0x1234..." and "erc20:0x1234..." to the same pair + pairIDFromCorrect := evmAppA.Erc20Keeper.GetTokenPairID(ctx, correctTrimmed) // "0x1234..." + pairIDFromIncorrect := evmAppA.Erc20Keeper.GetTokenPairID(ctx, incorrectTrimmed) // "erc20:0x1234..." + + suite.Require().NotEmpty(pairIDFromCorrect) + suite.Require().NotEmpty(pairIDFromIncorrect) + suite.Require().Equal(pairIDFromCorrect, pairIDFromIncorrect, + "Both lookups succeed due to dual mapping, masking the prefix bug") + + sender = nativeErc20.Account + }, + true, + }, + } + + for _, tc := range testCases { + suite.Run(fmt.Sprintf("Case %s", tc.name), func() { + suite.SetupTest() + + // Setup IBC path + path = evmibctesting.NewTransferPath(suite.chainA, suite.chainB) + path.Setup() + + // Run test-specific setup + tc.malleate() + + // Call precompile transfer + data, err := suite.chainAPrecompile.ABI.Pack( + "transfer", + transfertypes.PortID, + path.EndpointA.ChannelID, + denom, + amount.BigInt(), + sender, + receiver, + timeoutHeight, + uint64(0), + "", + ) + suite.Require().NoError(err) + + res, _, _, err := suite.chainA.SendEvmTx( + suite.chainA.SenderAccounts[0], + 0, + suite.chainAPrecompile.Address(), + big.NewInt(0), + data, + 0, + ) + + if tc.expPass { + suite.Require().NoError(err) + suite.Require().Equal(uint32(0), res.Code, res.Log) + } else { + suite.Require().Error(err) + } + }) + } +} diff --git a/evmd/tests/ibc/ics20_precompile_transfer_test.go b/evmd/tests/ibc/ics20_precompile_transfer_test.go index fcb1df32..9aef6ad8 100644 --- a/evmd/tests/ibc/ics20_precompile_transfer_test.go +++ b/evmd/tests/ibc/ics20_precompile_transfer_test.go @@ -13,14 +13,16 @@ import ( "github.com/ethereum/go-ethereum/core/vm" "github.com/stretchr/testify/suite" + "github.com/cosmos/evm" "github.com/cosmos/evm/evmd" "github.com/cosmos/evm/evmd/tests/integration" "github.com/cosmos/evm/precompiles/ics20" chainutil "github.com/cosmos/evm/testutil" evmibctesting "github.com/cosmos/evm/testutil/ibc" evmante "github.com/cosmos/evm/x/vm/ante" - transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" + "github.com/cosmos/evm/x/vm/statedb" + transfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/v11/modules/core/02-client/types" sdkmath "cosmossdk.io/math" @@ -51,6 +53,7 @@ func (suite *ICS20TransferTestSuite) SetupTest() { *evmAppA.StakingKeeper, evmAppA.TransferKeeper, evmAppA.IBCKeeper.ChannelKeeper, + evmAppA.Erc20Keeper, ) evmAppB := suite.chainB.App.(*evmd.EVMD) suite.chainBPrecompile = ics20.NewPrecompile( @@ -58,6 +61,7 @@ func (suite *ICS20TransferTestSuite) SetupTest() { *evmAppB.StakingKeeper, evmAppB.TransferKeeper, evmAppB.IBCKeeper.ChannelKeeper, + evmAppB.Erc20Keeper, ) } @@ -229,12 +233,15 @@ func (suite *ICS20TransferTestSuite) TestHandleMsgTransfer() { // denoms query method chainBAddr := common.BytesToAddress(suite.chainB.SenderAccount.GetAddress().Bytes()) ctxB := evmante.BuildEvmExecutionCtx(suite.chainB.GetContext()) + stateDB := statedb.New(ctxB, suite.chainB.App.(evm.EvmApp).GetEVMKeeper(), statedb.NewEmptyTxConfig()) evmRes, err := evmAppB.EVMKeeper.CallEVM( ctxB, + stateDB, suite.chainBPrecompile.ABI, chainBAddr, suite.chainBPrecompile.Address(), false, + false, nil, ics20.DenomsMethod, query.PageRequest{ @@ -254,10 +261,12 @@ func (suite *ICS20TransferTestSuite) TestHandleMsgTransfer() { // denom query method with result evmRes, err = evmAppB.EVMKeeper.CallEVM( ctxB, + stateDB, suite.chainBPrecompile.ABI, chainBAddr, suite.chainBPrecompile.Address(), false, + false, nil, ics20.DenomMethod, chainBDenom.Hash().String(), @@ -271,10 +280,12 @@ func (suite *ICS20TransferTestSuite) TestHandleMsgTransfer() { // denom query method not exists case evmRes, err = evmAppB.EVMKeeper.CallEVM( ctxB, + stateDB, suite.chainBPrecompile.ABI, chainBAddr, suite.chainBPrecompile.Address(), false, + false, nil, ics20.DenomMethod, "0000000000000000000000000000000000000000000000000000000000000000", @@ -288,10 +299,12 @@ func (suite *ICS20TransferTestSuite) TestHandleMsgTransfer() { // denom query method invalid error case evmRes, err = evmAppB.EVMKeeper.CallEVM( ctxB, + stateDB, suite.chainBPrecompile.ABI, chainBAddr, suite.chainBPrecompile.Address(), false, + false, nil, ics20.DenomMethod, "INVALID-DENOM-HASH", @@ -305,10 +318,12 @@ func (suite *ICS20TransferTestSuite) TestHandleMsgTransfer() { // denomHash query method evmRes, err = evmAppB.EVMKeeper.CallEVM( ctxB, + stateDB, suite.chainBPrecompile.ABI, chainBAddr, suite.chainBPrecompile.Address(), false, + false, nil, ics20.DenomHashMethod, chainBDenom.Path(), @@ -322,10 +337,12 @@ func (suite *ICS20TransferTestSuite) TestHandleMsgTransfer() { // denomHash query method not exists case evmRes, err = evmAppB.EVMKeeper.CallEVM( ctxB, + stateDB, suite.chainBPrecompile.ABI, chainBAddr, suite.chainBPrecompile.Address(), false, + false, nil, ics20.DenomHashMethod, "transfer/channel-0/erc20:not-exists-case", @@ -338,10 +355,12 @@ func (suite *ICS20TransferTestSuite) TestHandleMsgTransfer() { // denomHash query method invalid error case evmRes, err = evmAppB.EVMKeeper.CallEVM( ctxB, + stateDB, suite.chainBPrecompile.ABI, chainBAddr, suite.chainBPrecompile.Address(), false, + false, nil, ics20.DenomHashMethod, "", diff --git a/evmd/tests/ibc/ics20_recursive_precompile_calls_test.go b/evmd/tests/ibc/ics20_recursive_precompile_calls_test.go index 7af6ebee..2c942fe3 100644 --- a/evmd/tests/ibc/ics20_recursive_precompile_calls_test.go +++ b/evmd/tests/ibc/ics20_recursive_precompile_calls_test.go @@ -6,43 +6,41 @@ package ibc import ( - "fmt" "math/big" "testing" - distributionkeeper "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" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - "github.com/cosmos/evm/utils" - - "github.com/cosmos/evm/contracts" - testutiltypes "github.com/cosmos/evm/testutil/types" - erc20types "github.com/cosmos/evm/x/erc20/types" - evmtypes "github.com/cosmos/evm/x/vm/types" - "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/suite" + "github.com/cosmos/evm/contracts" "github.com/cosmos/evm/evmd" "github.com/cosmos/evm/evmd/tests/integration" "github.com/cosmos/evm/precompiles/ics20" evmibctesting "github.com/cosmos/evm/testutil/ibc" - transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" + testutiltypes "github.com/cosmos/evm/testutil/types" + "github.com/cosmos/evm/utils" + erc20types "github.com/cosmos/evm/x/erc20/types" + "github.com/cosmos/evm/x/vm/statedb" + evmtypes "github.com/cosmos/evm/x/vm/types" + transfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/v11/modules/core/02-client/types" sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" + distributionkeeper "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" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) // Test constants const ( // Token amounts - InitialTokenAmount = 1_000_000_000_000_000_000 // 1 token with 18 decimals - DelegationAmount = 1_000_000_000_000_000_000 // 1 token for delegation - RewardAmount = 100 // 100 base units for rewards - ExpectedRewards = "50.000000000000000000" // Expected reward amount after allocation + InitialTokenAmount int64 = 1_000_000_000_000_000_000 // 1 token with 18 decimals + DelegationAmount int64 = 1_000_000_000_000_000_000 // 1 token for delegation + RewardAmount = 100 // 100 base units for rewards + ExpectedRewards = "50.000000000000000000" // Expected reward amount after allocation // Test configuration SenderIndex = 1 @@ -115,13 +113,12 @@ func (suite *ICS20RecursivePrecompileCallsTestSuite) setupContractForTesting( senderAcc evmibctesting.SenderAccount, ) { evmAppA := suite.chainA.App.(*evmd.EVMD) - ctxA := suite.chainA.GetContext() senderAddr := senderAcc.SenderAccount.GetAddress() senderEVMAddr := common.BytesToAddress(senderAddr.Bytes()) deployerAddr := common.BytesToAddress(suite.chainA.SenderPrivKey.PubKey().Address().Bytes()) // Register ERC20 contract - _, err := evmAppA.Erc20Keeper.RegisterERC20(ctxA, &erc20types.MsgRegisterERC20{ + _, err := evmAppA.Erc20Keeper.RegisterERC20(suite.chainA.GetContext(), &erc20types.MsgRegisterERC20{ Signer: evmAppA.AccountKeeper.GetModuleAddress("gov").String(), Erc20Addresses: []string{contractAddr.Hex()}, }) @@ -129,14 +126,14 @@ func (suite *ICS20RecursivePrecompileCallsTestSuite) setupContractForTesting( suite.chainA.NextBlock() // Send native tokens to contract for delegation - bondDenom, err := evmAppA.StakingKeeper.BondDenom(ctxA) + bondDenom, err := evmAppA.StakingKeeper.BondDenom(suite.chainA.GetContext()) suite.Require().NoError(err) contractAddrBech32, err := sdk.AccAddressFromHexUnsafe(contractAddr.Hex()[2:]) suite.Require().NoError(err) deployerAddrBech32 := sdk.AccAddress(deployerAddr.Bytes()) - deployerBalance := evmAppA.BankKeeper.GetBalance(ctxA, deployerAddrBech32, bondDenom) + deployerBalance := evmAppA.BankKeeper.GetBalance(suite.chainA.GetContext(), deployerAddrBech32, bondDenom) // Send delegation amount to contract sendAmount := sdkmath.NewInt(DelegationAmount) @@ -145,7 +142,7 @@ func (suite *ICS20RecursivePrecompileCallsTestSuite) setupContractForTesting( } err = evmAppA.BankKeeper.SendCoins( - ctxA, + suite.chainA.GetContext(), deployerAddrBech32, contractAddrBech32, sdk.NewCoins(sdk.NewCoin(bondDenom, sendAmount)), @@ -153,12 +150,15 @@ func (suite *ICS20RecursivePrecompileCallsTestSuite) setupContractForTesting( suite.Require().NoError(err, "sending native tokens to contract should succeed") // Mint ERC20 tokens + stateDB := statedb.New(suite.chainA.GetContext(), evmAppA.GetEVMKeeper(), statedb.NewEmptyTxConfig()) _, err = evmAppA.GetEVMKeeper().CallEVM( suite.chainA.GetContext(), + stateDB, contractData.ABI, deployerAddr, contractAddr, true, + false, nil, "mint", senderEVMAddr, @@ -171,12 +171,15 @@ func (suite *ICS20RecursivePrecompileCallsTestSuite) setupContractForTesting( vals, err := evmAppA.StakingKeeper.GetAllValidators(suite.chainA.GetContext()) suite.Require().NoError(err) + stateDB = statedb.New(suite.chainA.GetContext(), evmAppA.GetEVMKeeper(), statedb.NewEmptyTxConfig()) _, err = evmAppA.GetEVMKeeper().CallEVM( - ctxA, + suite.chainA.GetContext(), + stateDB, contractData.ABI, deployerAddr, contractAddr, true, + false, nil, "delegate", vals[0].OperatorAddress, @@ -205,7 +208,22 @@ func (suite *ICS20RecursivePrecompileCallsTestSuite) setupContractForTesting( suite.chainA.NextBlock() // Verify minted balance - bal := evmAppA.GetErc20Keeper().BalanceOf(ctxA, contractData.ABI, contractAddr, common.BytesToAddress(senderAddr)) + stateDB = statedb.New(suite.chainA.GetContext(), evmAppA.GetEVMKeeper(), statedb.NewEmptyTxConfig()) + ethRes, err := evmAppA.GetEVMKeeper().CallEVM( + suite.chainA.GetContext(), + stateDB, + contractData.ABI, + common.BytesToAddress(senderAddr), + contractAddr, + false, + false, + nil, + "balanceOf", + common.BytesToAddress(senderAddr), + ) + var bal *big.Int + err = contractData.ABI.UnpackIntoInterface(&bal, "balanceOf", ethRes.Ret) + suite.Require().NoError(err) suite.Require().Equal(big.NewInt(InitialTokenAmount), bal, "unexpected ERC20 balance") } @@ -220,12 +238,13 @@ func (suite *ICS20RecursivePrecompileCallsTestSuite) SetupTest() { *evmAppA.StakingKeeper, evmAppA.TransferKeeper, evmAppA.IBCKeeper.ChannelKeeper, + evmAppA.Erc20Keeper, ) bondDenom, err := evmAppA.StakingKeeper.BondDenom(suite.chainA.GetContext()) suite.Require().NoError(err) evmAppA.Erc20Keeper.GetTokenPair(suite.chainA.GetContext(), evmAppA.Erc20Keeper.GetTokenPairID(suite.chainA.GetContext(), bondDenom)) - //evmAppA.Erc20Keeper.SetNativePrecompile(suite.chainA.GetContext(), werc20.Address()) + // evmAppA.Erc20Keeper.SetNativePrecompile(suite.chainA.GetContext(), werc20.Address()) avail := evmAppA.Erc20Keeper.IsNativePrecompileAvailable(suite.chainA.GetContext(), common.HexToAddress("0xD4949664cD82660AaE99bEdc034a0deA8A0bd517")) suite.Require().True(avail) @@ -236,6 +255,7 @@ func (suite *ICS20RecursivePrecompileCallsTestSuite) SetupTest() { *evmAppB.StakingKeeper, evmAppB.TransferKeeper, evmAppB.IBCKeeper.ChannelKeeper, + evmAppB.Erc20Keeper, ) } @@ -343,7 +363,7 @@ func (suite *ICS20RecursivePrecompileCallsTestSuite) TestHandleMsgTransfer() { suite.Require().NoError(err) contractBondDenomBalance := evmAppA.BankKeeper.GetBalance(suite.chainA.GetContext(), nativeErc20.ContractAddr.Bytes(), bondDenom) - suite.Require().Equal(contractBondDenomBalance.Amount, sdkmath.NewInt(50)) + suite.Require().Equal(sdkmath.NewInt(50), contractBondDenomBalance.Amount) // Check distribution rewards after transfer afterRewards, err := querier.DelegationRewards(suite.chainA.GetContext(), &distrtypes.QueryDelegationRewardsRequest{ @@ -429,7 +449,6 @@ func (suite *ICS20RecursivePrecompileCallsTestSuite) TestHandleMsgTransfer() { suite.Require().NoError(err) eventAmount := len(res.Events) - fmt.Println(res.Events) tc.postCheck(querier, vals[0].OperatorAddress, eventAmount) @@ -452,7 +471,7 @@ func (suite *ICS20RecursivePrecompileCallsTestSuite) TestHandleMsgTransfer() { relayerBalance := GetBalance(relayerAddr) // relay send - pathAToB.EndpointA.Chain.SenderAccount = evmAppA.AccountKeeper.GetAccount(suite.chainA.GetContext(), relayerAddr) //update account in the path as the sequence recorded in that object is out of date + pathAToB.EndpointA.Chain.SenderAccount = evmAppA.AccountKeeper.GetAccount(suite.chainA.GetContext(), relayerAddr) // update account in the path as the sequence recorded in that object is out of date err = pathAToB.RelayPacket(packet) suite.Require().NoError(err) // relay committed @@ -491,6 +510,425 @@ func (suite *ICS20RecursivePrecompileCallsTestSuite) TestHandleMsgTransfer() { } } +// TestContractICS20TransferWithDelegationHook tests a contract calling ICS20 transfer +// on an ERC20 token that has a delegation in the beforeTransfer hook +// Contract -> ICS20 Start -> ERC20 -> Delegate -> ICS20 End +func (suite *ICS20RecursivePrecompileCallsTestSuite) TestContractICS20TransferWithDelegationHook() { + suite.SetupTest() // reset + + pathAToB := evmibctesting.NewTransferPath(suite.chainA, suite.chainB) + pathAToB.Setup() + + senderAccount := suite.chainA.SenderAccounts[SenderIndex] + + // Deploy ICS20TransferTester contract + testerData, err := contracts.LoadICS20TransferTester() + suite.Require().NoError(err) + + testerDeploymentData := testutiltypes.ContractDeploymentData{ + Contract: testerData, + ConstructorArgs: []interface{}{}, + } + + testerAddr, err := DeployContract(suite.T(), suite.chainA, testerDeploymentData) + suite.chainA.NextBlock() + suite.Require().NoError(err) + + // Deploy regular ERC20 token (no hooks) for dummy transfer + regularTokenData := contracts.ERC20MinterBurnerDecimalsContract + + regularTokenDeploymentData := testutiltypes.ContractDeploymentData{ + Contract: regularTokenData, + ConstructorArgs: []interface{}{"DummyToken", "DT", uint8(18)}, + } + + regularTokenAddr, err := DeployContract(suite.T(), suite.chainA, regularTokenDeploymentData) + suite.chainA.NextBlock() + suite.Require().NoError(err) + + // Deploy ERC20WithNativeTransfers contract + hookTokenData, err := contracts.LoadERC20WithNativeTransfers() + suite.Require().NoError(err) + + hookTokenDeploymentData := testutiltypes.ContractDeploymentData{ + Contract: hookTokenData, + ConstructorArgs: []interface{}{"HookToken", "HT", uint8(18)}, + } + + hookTokenAddr, err := DeployContract(suite.T(), suite.chainA, hookTokenDeploymentData) + suite.chainA.NextBlock() + suite.Require().NoError(err) + + evmAppA := suite.chainA.App.(*evmd.EVMD) + + // Register both ERC20 contracts + _, err = evmAppA.Erc20Keeper.RegisterERC20(suite.chainA.GetContext(), &erc20types.MsgRegisterERC20{ + Signer: evmAppA.AccountKeeper.GetModuleAddress("gov").String(), + Erc20Addresses: []string{hookTokenAddr.Hex()}, + }) + suite.Require().NoError(err, "registering hook token should succeed") + suite.chainA.NextBlock() + + // Mint tokens to tester contract using CallEVM (setup function) + hookTokenAmount := big.NewInt(InitialTokenAmount) + mintData, err := hookTokenData.ABI.Pack("mint", testerAddr, hookTokenAmount) + suite.Require().NoError(err) + + stateDB := statedb.New(suite.chainA.GetContext(), evmAppA.GetEVMKeeper(), statedb.NewEmptyTxConfig()) + deployer := common.BytesToAddress(suite.chainA.SenderPrivKey.PubKey().Address().Bytes()) + _, err = evmAppA.GetEVMKeeper().CallEVMWithData(suite.chainA.GetContext(), stateDB, deployer, &hookTokenAddr, mintData, true, false, nil) + suite.Require().NoError(err) + suite.chainA.NextBlock() + + // Mint regular tokens to tester for the dummy transfer + regularTokenAmount := big.NewInt(1000) + stateDB = statedb.New(suite.chainA.GetContext(), evmAppA.GetEVMKeeper(), statedb.NewEmptyTxConfig()) + _, err = evmAppA.GetEVMKeeper().CallEVM( + suite.chainA.GetContext(), + stateDB, + regularTokenData.ABI, + deployer, + regularTokenAddr, + true, + false, + nil, + "mint", + testerAddr, + regularTokenAmount, + ) + suite.Require().NoError(err, "mint regular tokens to tester should succeed") + suite.chainA.NextBlock() + + // Configure hook to perform delegation + bondDenom, err := evmAppA.StakingKeeper.BondDenom(suite.chainA.GetContext()) + suite.Require().NoError(err) + + vals, err := evmAppA.StakingKeeper.GetAllValidators(suite.chainA.GetContext()) + suite.Require().NoError(err) + validatorAddr := vals[0].OperatorAddress + + // Fund hook token contract with native tokens for delegation using EVM transaction + hookTokenAddrSDK := sdk.AccAddress(hookTokenAddr.Bytes()) + delegationAmountSDK := sdkmath.NewInt(DelegationAmount) + // Fund exact amount: delegation + 2 native transfers (1 aatom each) + fundAmountAatom := delegationAmountSDK.AddRaw(2) // +2 for two 1 aatom native transfers + + // Send EVM transaction with value to fund the contract (updates both bank module and StateDB) + _, _, _, err = suite.chainA.SendEvmTx( + senderAccount, + 0, // senderAccIdx + hookTokenAddr, // to (not pointer) + big.NewInt(fundAmountAatom.Int64()), + []byte{}, // empty calldata + 0, // gasLimit (0 = auto) + ) + suite.Require().NoError(err) + suite.chainA.NextBlock() + + // Configure hook parameters + recipient1 := common.BytesToAddress(senderAccount.SenderAccount.GetAddress().Bytes()) + recipient2 := recipient1 + transferAmount := big.NewInt(1) + delegateAmount := big.NewInt(DelegationAmount) // Already in base denom + + configData, err := hookTokenData.ABI.Pack( + "configureHook", + recipient1, + recipient2, + transferAmount, + validatorAddr, + delegateAmount, + true, // enable hook + ) + suite.Require().NoError(err) + + // Use CallEVM for configuration (setup function) + stateDB = statedb.New(suite.chainA.GetContext(), evmAppA.GetEVMKeeper(), statedb.NewEmptyTxConfig()) + _, err = evmAppA.GetEVMKeeper().CallEVMWithData(suite.chainA.GetContext(), stateDB, deployer, &hookTokenAddr, configData, true, false, nil) + suite.Require().NoError(err) + suite.chainA.NextBlock() + + // Setup transfer parameters + timeoutHeight := clienttypes.NewHeight(1, TimeoutHeight) + hookTokenDenom := "erc20:" + hookTokenAddr.Hex() + transferTokenAmount := sdkmath.NewIntFromBigInt(big.NewInt(InitialTokenAmount / 2)) + + // Get balances before + testerHookBalBefore := evmAppA.Erc20Keeper.BalanceOf(suite.chainA.GetContext(), hookTokenData.ABI, hookTokenAddr, testerAddr) + hookTokenNativeBalBefore := evmAppA.GetBankKeeper().GetBalance(suite.chainA.GetContext(), hookTokenAddrSDK, bondDenom) + recipientAddrSDK := senderAccount.SenderAccount.GetAddress() + recipientNativeBalBefore := evmAppA.GetBankKeeper().GetBalance(suite.chainA.GetContext(), recipientAddrSDK, bondDenom) + + // Call scenario9_transferICS20Transfer from tester contract + callData, err := testerData.ABI.Pack( + "scenario9_transferICS20Transfer", + regularTokenAddr, // token (regular token without hooks) + recipient1, // recipient for dummy transfer + big.NewInt(100), // transferAmount (dummy transfer to avoid triggering hookToken hook) + pathAToB.EndpointA.ChannelConfig.PortID, // sourcePort + pathAToB.EndpointA.ChannelID, // sourceChannel + hookTokenDenom, // denom + transferTokenAmount.BigInt(), // ics20Amount + suite.chainB.SenderAccount.GetAddress().String(), // ics20Receiver + timeoutHeight, // timeoutHeight + uint64(0), // timeoutTimestamp + ) + suite.Require().NoError(err) + + // Execute transaction + res, _, _, err := suite.chainA.SendEvmTx(senderAccount, SenderIndex, testerAddr, big.NewInt(0), callData, 0) + suite.Require().NoError(err) + + // Get balances after + testerHookBalAfter := evmAppA.Erc20Keeper.BalanceOf(suite.chainA.GetContext(), hookTokenData.ABI, hookTokenAddr, testerAddr) + hookTokenNativeBalAfter := evmAppA.GetBankKeeper().GetBalance(suite.chainA.GetContext(), hookTokenAddrSDK, bondDenom) + recipientNativeBalAfter := evmAppA.GetBankKeeper().GetBalance(suite.chainA.GetContext(), recipientAddrSDK, bondDenom) + + // Verify ERC20 balance changes + expectedERC20Delta := transferTokenAmount.BigInt() + actualERC20Delta := new(big.Int).Sub(testerHookBalBefore, testerHookBalAfter) + suite.Require().Equal(expectedERC20Delta.String(), actualERC20Delta.String(), "hook token should be transferred via ICS20") + + // Verify native balance changes + // Hook contract should lose: delegation (1e6 aatom) + 2 native transfers (1 aatom each) = 1_000_002 aatom + expectedDelegationAatom := DelegationAmount + expectedTransferAatom := int64(2) + expectedHookNativeDelta := sdkmath.NewInt(expectedDelegationAatom + expectedTransferAatom) + actualHookNativeDelta := hookTokenNativeBalBefore.Amount.Sub(hookTokenNativeBalAfter.Amount) + suite.Require().Equal(expectedHookNativeDelta.String(), actualHookNativeDelta.String(), + "hook token contract should lose delegation + 2 native transfers") + + // Recipient should receive 2 native transfers (2 aatom) + expectedRecipientDelta := sdkmath.NewInt(expectedTransferAatom) + actualRecipientDelta := recipientNativeBalAfter.Amount.Sub(recipientNativeBalBefore.Amount) + suite.Require().Equal(expectedRecipientDelta.String(), actualRecipientDelta.String(), + "recipient should receive 2 native transfers") + + // Verify delegation occurred + delegations, err := evmAppA.StakingKeeper.GetAllDelegatorDelegations(suite.chainA.GetContext(), hookTokenAddrSDK) + suite.Require().NoError(err) + suite.Require().Equal(1, len(delegations), "should have 1 delegation from beforeTransfer hook") + + // Verify total bonded amount + bondedTokens, err := evmAppA.StakingKeeper.GetDelegatorBonded(suite.chainA.GetContext(), hookTokenAddrSDK) + suite.Require().NoError(err) + expectedBondedAmount := DelegationAmount // Convert wei to base denom + suite.Require().Equal(int64(expectedBondedAmount), bondedTokens.Int64(), + "bonded tokens should equal delegation amount") + + // Verify event count + suite.Require().Equal(DelegationEventCount+ICS20WithConversionEventCount+EVMEventCount, len(res.Events), "should have 41 events") +} + +// TestContractICS20TransferRevertWithDelegationHook tests a contract with reverted ERC20 transfer +// followed by ICS20 transfer on an ERC20 token that has a delegation in the beforeTransfer hook +func (suite *ICS20RecursivePrecompileCallsTestSuite) TestContractICS20TransferRevertWithDelegationHook() { + suite.SetupTest() // reset + + pathAToB := evmibctesting.NewTransferPath(suite.chainA, suite.chainB) + pathAToB.Setup() + + senderAccount := suite.chainA.SenderAccounts[SenderIndex] + + // Deploy ICS20TransferTester contract + testerData, err := contracts.LoadICS20TransferTester() + suite.Require().NoError(err) + + testerDeploymentData := testutiltypes.ContractDeploymentData{ + Contract: testerData, + ConstructorArgs: []interface{}{}, + } + + testerAddr, err := DeployContract(suite.T(), suite.chainA, testerDeploymentData) + suite.chainA.NextBlock() + suite.Require().NoError(err) + + // Deploy regular ERC20 token for the first transfer (that will revert) + regularTokenData := contracts.ERC20MinterBurnerDecimalsContract + + regularTokenDeploymentData := testutiltypes.ContractDeploymentData{ + Contract: regularTokenData, + ConstructorArgs: []interface{}{"RegularToken", "RT", uint8(18)}, + } + + regularTokenAddr, err := DeployContract(suite.T(), suite.chainA, regularTokenDeploymentData) + suite.chainA.NextBlock() + suite.Require().NoError(err) + + // Deploy ERC20WithNativeTransfers contract + hookTokenData, err := contracts.LoadERC20WithNativeTransfers() + suite.Require().NoError(err) + + hookTokenDeploymentData := testutiltypes.ContractDeploymentData{ + Contract: hookTokenData, + ConstructorArgs: []interface{}{"HookToken", "HT", uint8(18)}, + } + + hookTokenAddr, err := DeployContract(suite.T(), suite.chainA, hookTokenDeploymentData) + suite.chainA.NextBlock() + suite.Require().NoError(err) + + evmAppA := suite.chainA.App.(*evmd.EVMD) + + // Get deployer address for CallEVM + deployer := common.BytesToAddress(suite.chainA.SenderPrivKey.PubKey().Address().Bytes()) + + // Register both ERC20 contracts + _, err = evmAppA.Erc20Keeper.RegisterERC20(suite.chainA.GetContext(), &erc20types.MsgRegisterERC20{ + Signer: evmAppA.AccountKeeper.GetModuleAddress("gov").String(), + Erc20Addresses: []string{regularTokenAddr.Hex(), hookTokenAddr.Hex()}, + }) + suite.Require().NoError(err, "registering tokens should succeed") + suite.chainA.NextBlock() + + // Mint only a small amount of regular tokens to tester using CallEVM (setup function) + regularTokenAmount := big.NewInt(1000) + mintRegularData, err := regularTokenData.ABI.Pack("mint", testerAddr, regularTokenAmount) + suite.Require().NoError(err) + + stateDB := statedb.New(suite.chainA.GetContext(), evmAppA.GetEVMKeeper(), statedb.NewEmptyTxConfig()) + _, err = evmAppA.GetEVMKeeper().CallEVMWithData(suite.chainA.GetContext(), stateDB, deployer, ®ularTokenAddr, mintRegularData, true, false, nil) + suite.Require().NoError(err) + suite.chainA.NextBlock() + + // Mint tokens to tester contract (hook token) using CallEVM (setup function) + hookTokenAmount := big.NewInt(InitialTokenAmount) + mintHookData, err := hookTokenData.ABI.Pack("mint", testerAddr, hookTokenAmount) + suite.Require().NoError(err) + + stateDB = statedb.New(suite.chainA.GetContext(), evmAppA.GetEVMKeeper(), statedb.NewEmptyTxConfig()) + _, err = evmAppA.GetEVMKeeper().CallEVMWithData(suite.chainA.GetContext(), stateDB, deployer, &hookTokenAddr, mintHookData, true, false, nil) + suite.Require().NoError(err) + suite.chainA.NextBlock() + + vals, err := evmAppA.StakingKeeper.GetAllValidators(suite.chainA.GetContext()) + suite.Require().NoError(err) + validatorAddr := vals[0].OperatorAddress + + // Fund hook token contract with native tokens for delegation using EVM transaction + hookTokenAddrSDK := sdk.AccAddress(hookTokenAddr.Bytes()) + delegationAmountSDK := sdkmath.NewInt(DelegationAmount) // Convert from wei to base denom + // Fund exact amount: delegation + 2 native transfers (1 aatom each) + fundAmountAatom := delegationAmountSDK.AddRaw(2) // +2 for two 1 aatom native transfers + + // Send EVM transaction with value to fund the contract (updates both bank module and StateDB) + _, _, _, err = suite.chainA.SendEvmTx( + senderAccount, + 0, // senderAccIdx + hookTokenAddr, // to (not pointer) + big.NewInt(fundAmountAatom.Int64()), + []byte{}, // empty calldata + 0, // gasLimit (0 = auto) + ) + suite.Require().NoError(err) + suite.chainA.NextBlock() + + // Configure hook parameters + recipient1 := common.BytesToAddress(senderAccount.SenderAccount.GetAddress().Bytes()) + recipient2 := recipient1 + transferAmount := big.NewInt(1) + delegateAmount := big.NewInt(DelegationAmount) // Already in base denom + + configData, err := hookTokenData.ABI.Pack( + "configureHook", + recipient1, + recipient2, + transferAmount, + validatorAddr, + delegateAmount, + true, // enable hook + ) + suite.Require().NoError(err) + + // Use CallEVM for configuration (setup function) + stateDB = statedb.New(suite.chainA.GetContext(), evmAppA.GetEVMKeeper(), statedb.NewEmptyTxConfig()) + _, err = evmAppA.GetEVMKeeper().CallEVMWithData(suite.chainA.GetContext(), stateDB, deployer, &hookTokenAddr, configData, true, false, nil) + suite.Require().NoError(err) + suite.chainA.NextBlock() + + // Setup transfer parameters + timeoutHeight := clienttypes.NewHeight(1, TimeoutHeight) + hookTokenDenom := "erc20:" + hookTokenAddr.Hex() + transferTokenAmount := sdkmath.NewIntFromBigInt(big.NewInt(InitialTokenAmount / 2)) + + // Get balances before + bondDenom, err := evmAppA.StakingKeeper.BondDenom(suite.chainA.GetContext()) + suite.Require().NoError(err) + regularTokenBalBefore := evmAppA.Erc20Keeper.BalanceOf(suite.chainA.GetContext(), regularTokenData.ABI, regularTokenAddr, testerAddr) + testerHookBalBefore := evmAppA.Erc20Keeper.BalanceOf(suite.chainA.GetContext(), hookTokenData.ABI, hookTokenAddr, testerAddr) + hookTokenNativeBalBefore := evmAppA.GetBankKeeper().GetBalance(suite.chainA.GetContext(), hookTokenAddrSDK, bondDenom) + recipientAddrSDK := senderAccount.SenderAccount.GetAddress() + recipientNativeBalBefore := evmAppA.GetBankKeeper().GetBalance(suite.chainA.GetContext(), recipientAddrSDK, bondDenom) + + // Call scenario10_transferICS20TransferRevert from tester contract + // First transfer will revert due to excessive amount + excessiveAmount := big.NewInt(InitialTokenAmount) // More than the minted amount + callData, err := testerData.ABI.Pack( + "scenario10_transferICS20TransferRevert", + regularTokenAddr, // token (will revert) + recipient1, // recipient + excessiveAmount, // excessive transferAmount (will revert) + pathAToB.EndpointA.ChannelConfig.PortID, // sourcePort + pathAToB.EndpointA.ChannelID, // sourceChannel + hookTokenDenom, // denom + transferTokenAmount.BigInt(), // ics20Amount + suite.chainB.SenderAccount.GetAddress().String(), // ics20Receiver + timeoutHeight, // timeoutHeight + uint64(0), // timeoutTimestamp + ) + suite.Require().NoError(err) + + // Execute contract call + res, _, _, err := suite.chainA.SendEvmTx(senderAccount, SenderIndex, testerAddr, big.NewInt(0), callData, 0) + suite.Require().NoError(err) + + // Get balances after + regularTokenBalAfter := evmAppA.Erc20Keeper.BalanceOf(suite.chainA.GetContext(), regularTokenData.ABI, regularTokenAddr, testerAddr) + testerHookBalAfter := evmAppA.Erc20Keeper.BalanceOf(suite.chainA.GetContext(), hookTokenData.ABI, hookTokenAddr, testerAddr) + hookTokenNativeBalAfter := evmAppA.GetBankKeeper().GetBalance(suite.chainA.GetContext(), hookTokenAddrSDK, bondDenom) + recipientNativeBalAfter := evmAppA.GetBankKeeper().GetBalance(suite.chainA.GetContext(), recipientAddrSDK, bondDenom) + + // Verify regular token balance unchanged (transfer reverted) + suite.Require().Equal(regularTokenBalBefore.String(), regularTokenBalAfter.String(), + "regular token balance should be unchanged since transfer reverted") + + // Verify hook token balance changed (ICS20 transfer succeeded) + expectedERC20Delta := transferTokenAmount.BigInt() + actualERC20Delta := new(big.Int).Sub(testerHookBalBefore, testerHookBalAfter) + suite.Require().Equal(expectedERC20Delta.String(), actualERC20Delta.String(), + "hook token should be transferred via ICS20") + + // Verify native balance changes + // Hook contract should lose: delegation (1e6 aatom) + 2 native transfers (1 aatom each) = 1_000_002 aatom + expectedDelegationAatom := DelegationAmount + expectedTransferAatom := int64(2) + expectedHookNativeDelta := sdkmath.NewInt(expectedDelegationAatom + expectedTransferAatom) + actualHookNativeDelta := hookTokenNativeBalBefore.Amount.Sub(hookTokenNativeBalAfter.Amount) + suite.Require().Equal(expectedHookNativeDelta.String(), actualHookNativeDelta.String(), + "hook token contract should lose delegation + 2 native transfers") + + // Recipient should receive 2 native transfers (2 aatom) + expectedRecipientDelta := sdkmath.NewInt(expectedTransferAatom) + actualRecipientDelta := recipientNativeBalAfter.Amount.Sub(recipientNativeBalBefore.Amount) + suite.Require().Equal(expectedRecipientDelta.String(), actualRecipientDelta.String(), + "recipient should receive 2 native transfers") + + // Verify delegation occurred (from beforeTransfer hook) + delegations, err := evmAppA.StakingKeeper.GetAllDelegatorDelegations(suite.chainA.GetContext(), hookTokenAddrSDK) + suite.Require().NoError(err) + suite.Require().Equal(1, len(delegations), "should have 1 delegation from beforeTransfer hook") + + // Verify total bonded amount + bondedTokens, err := evmAppA.StakingKeeper.GetDelegatorBonded(suite.chainA.GetContext(), hookTokenAddrSDK) + suite.Require().NoError(err) + expectedBondedAmount := DelegationAmount // Convert wei to base denom + suite.Require().Equal(int64(expectedBondedAmount), bondedTokens.Int64(), + "bonded tokens should equal delegation amount") + + // Verify event count + suite.Require().Equal(DelegationEventCount+ICS20WithConversionEventCount+EVMEventCount, len(res.Events), "should have 41 events") +} + func TestICS20RecursivePrecompileCallsTestSuite(t *testing.T) { suite.Run(t, new(ICS20RecursivePrecompileCallsTestSuite)) } diff --git a/evmd/tests/ibc/ics20_sequential_precompile_calls_test.go b/evmd/tests/ibc/ics20_sequential_precompile_calls_test.go new file mode 100644 index 00000000..59335cf5 --- /dev/null +++ b/evmd/tests/ibc/ics20_sequential_precompile_calls_test.go @@ -0,0 +1,203 @@ +package ibc + +import ( + "fmt" + "math/big" + "testing" + + "github.com/cosmos/evm/testutil" + + "github.com/cosmos/evm/contracts" + testutiltypes "github.com/cosmos/evm/testutil/types" + erc20types "github.com/cosmos/evm/x/erc20/types" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/evmd" + "github.com/cosmos/evm/evmd/tests/integration" + "github.com/cosmos/evm/precompiles/ics20" + evmibctesting "github.com/cosmos/evm/testutil/ibc" +) + +// Test constants for sequential ICS20 sends +const ( + SeqICS20InitialTokenAmount = 1_000_000_000_000_000_000 // 1 token with 18 decimals + SeqICS20SenderIndex = 1 + SeqICS20TimeoutHeight = 110 +) + +// Test suite for ICS20 sequential max sends +type ICS20SequentialPrecompileCallsTestSuite struct { + suite.Suite + + coordinator *evmibctesting.Coordinator + + chainA *evmibctesting.TestChain + chainAPrecompile *ics20.Precompile + chainB *evmibctesting.TestChain + chainBPrecompile *ics20.Precompile +} + +func (suite *ICS20SequentialPrecompileCallsTestSuite) SetupTest() { + suite.coordinator = evmibctesting.NewCoordinator(suite.T(), 2, 0, integration.SetupEvmd) + suite.chainA = suite.coordinator.GetChain(evmibctesting.GetEvmChainID(1)) + suite.chainB = suite.coordinator.GetChain(evmibctesting.GetEvmChainID(2)) + + evmAppA := suite.chainA.App.(*evmd.EVMD) + suite.chainAPrecompile = ics20.NewPrecompile( + evmAppA.BankKeeper, + *evmAppA.StakingKeeper, + evmAppA.TransferKeeper, + evmAppA.IBCKeeper.ChannelKeeper, + evmAppA.Erc20Keeper, + ) + bondDenom, err := evmAppA.StakingKeeper.BondDenom(suite.chainA.GetContext()) + suite.Require().NoError(err) + + evmAppA.Erc20Keeper.GetTokenPair(suite.chainA.GetContext(), evmAppA.Erc20Keeper.GetTokenPairID(suite.chainA.GetContext(), bondDenom)) + + avail := evmAppA.Erc20Keeper.IsNativePrecompileAvailable(suite.chainA.GetContext(), common.HexToAddress("0xD4949664cD82660AaE99bEdc034a0deA8A0bd517")) + suite.Require().True(avail) + + evmAppB := suite.chainB.App.(*evmd.EVMD) + suite.chainBPrecompile = ics20.NewPrecompile( + evmAppB.BankKeeper, + *evmAppB.StakingKeeper, + evmAppB.TransferKeeper, + evmAppB.IBCKeeper.ChannelKeeper, + evmAppB.Erc20Keeper, + ) +} + +// TestReceiveAndSendTwice tests the production flow: transfer tokens in -> ICS20 sends -> transfer out +// This mirrors the actual transaction pattern seen on-chain. +func (suite *ICS20SequentialPrecompileCallsTestSuite) TestReceiveAndSendTwice() { + suite.SetupTest() + + pathAToB := evmibctesting.NewTransferPath(suite.chainA, suite.chainB) + pathAToB.Setup() + + evmAppA := suite.chainA.App.(*evmd.EVMD) + // Deployer has MINTER_ROLE - use it for minting + deployerAddr := common.BytesToAddress(suite.chainA.SenderPrivKey.PubKey().Address().Bytes()) + // Use a different account for the actual test tx + senderAccount := suite.chainA.SenderAccounts[SeqICS20SenderIndex] + senderAddr := common.BytesToAddress(senderAccount.SenderAccount.GetAddress().Bytes()) + + // 1. Deploy ERC20 contract + erc20ContractData := contracts.ERC20MinterBurnerDecimalsContract + erc20DeploymentData := testutiltypes.ContractDeploymentData{ + Contract: erc20ContractData, + ConstructorArgs: []interface{}{"TestToken", "TT", uint8(18)}, + } + erc20Addr, err := DeployContract(suite.T(), suite.chainA, erc20DeploymentData) + suite.chainA.NextBlock() + suite.Require().NoError(err) + fmt.Printf("ERC20 contract deployed at: %s\n", erc20Addr.Hex()) + + // 2. Register the ERC20 + ctx := suite.chainA.GetContext() + _, err = evmAppA.Erc20Keeper.RegisterERC20(ctx, &erc20types.MsgRegisterERC20{ + Signer: evmAppA.AccountKeeper.GetModuleAddress("gov").String(), + Erc20Addresses: []string{erc20Addr.Hex()}, + }) + suite.Require().NoError(err) + suite.chainA.NextBlock() + + // 3. Deploy the Sender contract + senderContractData, err := contracts.LoadSequentialICS20Sender() + suite.Require().NoError(err) + senderDeploymentData := testutiltypes.ContractDeploymentData{ + Contract: senderContractData, + ConstructorArgs: []interface{}{}, + } + contractAddr, err := DeployContract(suite.T(), suite.chainA, senderDeploymentData) + suite.chainA.NextBlock() + suite.Require().NoError(err) + fmt.Printf("Sender contract deployed at: %s\n", contractAddr.Hex()) + + // 4. Mint ERC20 tokens to the test sender using deployer (who has MINTER_ROLE) + ctx = suite.chainA.GetContext() + mintStateDB := testutil.NewStateDB(ctx, evmAppA.EVMKeeper) + _, err = evmAppA.GetEVMKeeper().CallEVM(ctx, mintStateDB, erc20ContractData.ABI, deployerAddr, erc20Addr, true, false, nil, "mint", senderAddr, big.NewInt(SeqICS20InitialTokenAmount)) + suite.Require().NoError(err) + suite.chainA.NextBlock() + + // Verify minted balance + senderBal := evmAppA.GetErc20Keeper().BalanceOf(suite.chainA.GetContext(), erc20ContractData.ABI, erc20Addr, senderAddr) + suite.Require().Equal(big.NewInt(SeqICS20InitialTokenAmount), senderBal) + fmt.Printf("Sender balance before: %s\n", senderBal.String()) + + // 5. Approve the contract to spend tokens (called by sender) + ctx = suite.chainA.GetContext() + approveStateDB := testutil.NewStateDB(ctx, evmAppA.EVMKeeper) + _, err = evmAppA.GetEVMKeeper().CallEVM(ctx, approveStateDB, erc20ContractData.ABI, senderAddr, erc20Addr, true, false, nil, "approve", contractAddr, big.NewInt(SeqICS20InitialTokenAmount*2)) + suite.Require().NoError(err) + suite.chainA.NextBlock() + + // Get balances before + senderBalBefore := evmAppA.GetErc20Keeper().BalanceOf(suite.chainA.GetContext(), erc20ContractData.ABI, erc20Addr, senderAddr) + contractBalBefore := evmAppA.GetErc20Keeper().BalanceOf(suite.chainA.GetContext(), erc20ContractData.ABI, erc20Addr, contractAddr) + fmt.Printf("Before tx - Sender: %s, Contract: %s\n", senderBalBefore.String(), contractBalBefore.String()) + + // 6. Call receiveAndSendTwice - this should: + // - Transfer tokens from sender to contract + // - Attempt first ICS20 send (should succeed) + // - Attempt second ICS20 send (should fail - no balance) + // - Revert and return tokens + denom := "erc20:" + erc20Addr.Hex() + data, err := senderContractData.ABI.Pack( + "receiveAndSendTwice", + erc20Addr, + pathAToB.EndpointA.ChannelConfig.PortID, + pathAToB.EndpointA.ChannelID, + denom, + suite.chainB.SenderAccount.GetAddress().String(), + uint64(SeqICS20TimeoutHeight), + big.NewInt(SeqICS20InitialTokenAmount), + ) + suite.Require().NoError(err) + + res, _, _, err := suite.chainA.SendEvmTx(senderAccount, SeqICS20SenderIndex, contractAddr, big.NewInt(0), data, 0) + + // Log events + if res != nil { + fmt.Printf("Total events: %d\n", len(res.Events)) + for i, event := range res.Events { + fmt.Printf("Event %d: type=%s\n", i, event.Type) + for _, attr := range event.Attributes { + fmt.Printf(" %s: %s\n", attr.Key, attr.Value) + } + } + } + + // Check for revert + hasRevertEvent := false + if res != nil { + for _, event := range res.Events { + if event.Type == "ethereum_tx" { + for _, attr := range event.Attributes { + if attr.Key == "ethereumTxFailed" { + hasRevertEvent = true + fmt.Printf("Found revert: %s\n", attr.Value) + } + } + } + } + } + + // Get balances after + senderBalAfter := evmAppA.GetErc20Keeper().BalanceOf(suite.chainA.GetContext(), erc20ContractData.ABI, erc20Addr, senderAddr) + contractBalAfter := evmAppA.GetErc20Keeper().BalanceOf(suite.chainA.GetContext(), erc20ContractData.ABI, erc20Addr, contractAddr) + fmt.Printf("After tx - Sender: %s, Contract: %s\n", senderBalAfter.String(), contractBalAfter.String()) + + // The second ICS20 send should have failed, causing a revert + // Sender balance should be unchanged (tokens returned on revert) + suite.Require().True(hasRevertEvent || err != nil, "expected transaction to revert on second ICS20 send") + suite.Require().Equal(senderBalBefore.String(), senderBalAfter.String(), "sender balance should be unchanged after revert") + suite.Require().Equal(contractBalBefore.String(), contractBalAfter.String(), "contract balance should be unchanged after revert") +} + +func TestICS20SequentialPrecompileCallsTestSuite(t *testing.T) { + suite.Run(t, new(ICS20SequentialPrecompileCallsTestSuite)) +} diff --git a/evmd/tests/ibc/transfer_test.go b/evmd/tests/ibc/transfer_test.go index a386e1e6..a03c541f 100644 --- a/evmd/tests/ibc/transfer_test.go +++ b/evmd/tests/ibc/transfer_test.go @@ -13,8 +13,8 @@ import ( "github.com/cosmos/evm/evmd" "github.com/cosmos/evm/evmd/tests/integration" evmibctesting "github.com/cosmos/evm/testutil/ibc" - "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" + "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/v11/modules/core/02-client/types" sdkmath "cosmossdk.io/math" diff --git a/evmd/tests/ibc/v2_ibc_middleware_test.go b/evmd/tests/ibc/v2_ibc_middleware_test.go index 23f25c55..1b802ba4 100644 --- a/evmd/tests/ibc/v2_ibc_middleware_test.go +++ b/evmd/tests/ibc/v2_ibc_middleware_test.go @@ -17,11 +17,12 @@ import ( erc20Keeper "github.com/cosmos/evm/x/erc20/keeper" "github.com/cosmos/evm/x/erc20/types" v2 "github.com/cosmos/evm/x/erc20/v2" - transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types" - channeltypesv2 "github.com/cosmos/ibc-go/v10/modules/core/04-channel/v2/types" - ibctesting "github.com/cosmos/ibc-go/v10/testing" - ibcmockv2 "github.com/cosmos/ibc-go/v10/testing/mock/v2" + "github.com/cosmos/gogoproto/proto" + transfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + channeltypes "github.com/cosmos/ibc-go/v11/modules/core/04-channel/types" + channeltypesv2 "github.com/cosmos/ibc-go/v11/modules/core/04-channel/v2/types" + ibctesting "github.com/cosmos/ibc-go/v11/testing" + ibcmockv2 "github.com/cosmos/ibc-go/v11/testing/mock/v2" "cosmossdk.io/math" @@ -942,3 +943,102 @@ func (suite *MiddlewareV2TestSuite) TestOnTimeoutPacketNativeErc20() { }) } } + +func (suite *MiddlewareV2TestSuite) TestOnRecvPacketNativeERC20Rollback() { + suite.SetupTest() + nativeErc20 := SetupNativeErc20(suite.T(), suite.evmChainA, suite.evmChainA.SenderAccounts[0]) + senderEthAddr := nativeErc20.Account + sender := sdk.AccAddress(senderEthAddr.Bytes()) + sendAmt := math.NewIntFromBigInt(nativeErc20.InitialBal) + + evmCtx := suite.evmChainA.GetContext() + evmApp := suite.evmChainA.App.(*evmd.EVMD) + + _, err := evmApp.Erc20Keeper.ConvertERC20( + evmCtx, + types.NewMsgConvertERC20( + sendAmt, + sender, + nativeErc20.ContractAddr, + senderEthAddr, + ), + ) + suite.Require().NoError(err) + + path := suite.pathAToB + chainBAcc := suite.chainB.SenderAccount.GetAddress() + packetData := transfertypes.NewFungibleTokenPacketData( + nativeErc20.Denom, sendAmt.String(), + sender.String(), chainBAcc.String(), + "", + ) + payload := channeltypesv2.NewPayload( + transfertypes.PortID, transfertypes.PortID, + transfertypes.V1, transfertypes.EncodingJSON, + packetData.GetBytes(), + ) + timeoutTimestamp := uint64(suite.chainB.GetContext().BlockTime().Add(time.Hour).Unix()) //nolint:gosec // G115 + packet, err := path.EndpointA.MsgSendPacketWithSender(timeoutTimestamp, payload, evmibctesting.SenderAccount{ + SenderPrivKey: suite.evmChainA.SenderPrivKey, + SenderAccount: suite.evmChainA.SenderAccount, + }) + suite.Require().NoError(err) + + escrowAddr := transfertypes.GetEscrowAddress(transfertypes.PortID, path.EndpointA.ClientID) + escrowedBal := evmApp.BankKeeper.GetBalance(evmCtx, escrowAddr, nativeErc20.Denom) + suite.Require().Equal(sendAmt.String(), escrowedBal.Amount.String()) + + _, err = path.EndpointB.MsgRecvPacketWithResult(packet) + suite.Require().NoError(err) + + chainBNativeErc20Denom := transfertypes.NewDenom( + nativeErc20.Denom, + transfertypes.NewHop( + transfertypes.PortID, + path.EndpointB.ClientID, + ), + ) + receiver := suite.evmChainA.SenderAccount.GetAddress() + returnData := transfertypes.NewFungibleTokenPacketData( + chainBNativeErc20Denom.Path(), sendAmt.String(), + chainBAcc.String(), receiver.String(), "", + ) + returnPayload := channeltypesv2.NewPayload( + transfertypes.PortID, transfertypes.PortID, + transfertypes.V1, transfertypes.EncodingJSON, + returnData.GetBytes(), + ) + reversePath := path.Reversed() + returnTimeout := uint64(suite.chainB.GetContext().BlockTime().Add(time.Hour).Unix()) //nolint:gosec // G115 + returnPacket, err := reversePath.EndpointA.MsgSendPacketWithSender(returnTimeout, returnPayload, evmibctesting.SenderAccount{ + SenderPrivKey: suite.chainB.SenderPrivKey, + SenderAccount: suite.chainB.SenderAccount, + }) + suite.Require().NoError(err) + + evmCtx = suite.evmChainA.GetContext() + // Set SendEnabled = false on our denom to trigger failure in middleware keeper call + evmApp.BankKeeper.SetSendEnabled(evmCtx, nativeErc20.Denom, false) + + res, err := reversePath.EndpointB.MsgRecvPacketWithResult(returnPacket) + suite.Require().NoError(err) + + ackBytes, err := evmibctesting.ParseAckV2FromEvents(res.Events) + suite.Require().NoError(err) + var ack channeltypesv2.Acknowledgement + err = proto.Unmarshal(ackBytes, &ack) + suite.Require().NoError(err) + suite.Require().Equal(1, len(ack.AppAcknowledgements)) + + // Verify packet was successfully received in bank keeper but not received by erc20 contract resulting in ErrAck + suite.Require().Equal([][]byte{channeltypesv2.ErrorAcknowledgement[:]}, ack.AppAcknowledgements) + evmCtx = suite.evmChainA.GetContext() + escrowedBal = evmApp.BankKeeper.GetBalance(evmCtx, escrowAddr, nativeErc20.Denom) + suite.Require().Equal(sendAmt.String(), escrowedBal.Amount.String()) + + erc20BalAfterRecv := evmApp.Erc20Keeper.BalanceOf(evmCtx, nativeErc20.ContractAbi, nativeErc20.ContractAddr, senderEthAddr) + suite.Require().Equal("0", erc20BalAfterRecv.String()) + + bankBalAfterRecv := evmApp.BankKeeper.GetBalance(evmCtx, receiver, nativeErc20.Denom) + suite.Require().Equal("0", bankBalAfterRecv.Amount.String()) +} diff --git a/evmd/tests/ibc/v2_ics20_precompile_transfer_test.go b/evmd/tests/ibc/v2_ics20_precompile_transfer_test.go index 27c7c456..0815c8c4 100644 --- a/evmd/tests/ibc/v2_ics20_precompile_transfer_test.go +++ b/evmd/tests/ibc/v2_ics20_precompile_transfer_test.go @@ -14,14 +14,16 @@ import ( "github.com/ethereum/go-ethereum/core/vm" "github.com/stretchr/testify/suite" + "github.com/cosmos/evm" "github.com/cosmos/evm/evmd" "github.com/cosmos/evm/evmd/tests/integration" "github.com/cosmos/evm/precompiles/ics20" chainutil "github.com/cosmos/evm/testutil" evmibctesting "github.com/cosmos/evm/testutil/ibc" evmante "github.com/cosmos/evm/x/vm/ante" - transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" + "github.com/cosmos/evm/x/vm/statedb" + transfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/v11/modules/core/02-client/types" sdkmath "cosmossdk.io/math" @@ -52,6 +54,7 @@ func (suite *ICS20TransferV2TestSuite) SetupTest() { *evmAppA.StakingKeeper, evmAppA.TransferKeeper, evmAppA.IBCKeeper.ChannelKeeper, + evmAppA.Erc20Keeper, ) evmAppB := suite.chainB.App.(*evmd.EVMD) suite.chainBPrecompile = ics20.NewPrecompile( @@ -59,6 +62,7 @@ func (suite *ICS20TransferV2TestSuite) SetupTest() { *evmAppB.StakingKeeper, evmAppB.TransferKeeper, evmAppB.IBCKeeper.ChannelKeeper, + evmAppB.Erc20Keeper, ) } @@ -235,12 +239,15 @@ func (suite *ICS20TransferV2TestSuite) TestHandleMsgTransfer() { // denoms query method chainBAddr := common.BytesToAddress(suite.chainB.SenderAccount.GetAddress().Bytes()) ctxB := evmante.BuildEvmExecutionCtx(suite.chainB.GetContext()) + stateDB := statedb.New(ctxB, suite.chainB.App.(evm.EvmApp).GetEVMKeeper(), statedb.NewEmptyTxConfig()) evmRes, err := evmAppB.EVMKeeper.CallEVM( ctxB, + stateDB, suite.chainBPrecompile.ABI, chainBAddr, suite.chainBPrecompile.Address(), false, + false, nil, ics20.DenomsMethod, query.PageRequest{ @@ -260,10 +267,12 @@ func (suite *ICS20TransferV2TestSuite) TestHandleMsgTransfer() { // denom query method evmRes, err = evmAppB.EVMKeeper.CallEVM( ctxB, + stateDB, suite.chainBPrecompile.ABI, chainBAddr, suite.chainBPrecompile.Address(), false, + false, nil, ics20.DenomMethod, chainBDenom.Hash().String(), @@ -277,10 +286,12 @@ func (suite *ICS20TransferV2TestSuite) TestHandleMsgTransfer() { // denom query method not exists case evmRes, err = evmAppB.EVMKeeper.CallEVM( ctxB, + stateDB, suite.chainBPrecompile.ABI, chainBAddr, suite.chainBPrecompile.Address(), false, + false, nil, ics20.DenomMethod, "0000000000000000000000000000000000000000000000000000000000000000", @@ -294,10 +305,12 @@ func (suite *ICS20TransferV2TestSuite) TestHandleMsgTransfer() { // denom query method invalid error case evmRes, err = evmAppB.EVMKeeper.CallEVM( ctxB, + stateDB, suite.chainBPrecompile.ABI, chainBAddr, suite.chainBPrecompile.Address(), false, + false, nil, ics20.DenomMethod, "INVALID-DENOM-HASH", @@ -310,10 +323,12 @@ func (suite *ICS20TransferV2TestSuite) TestHandleMsgTransfer() { // denomHash query method evmRes, err = evmAppB.EVMKeeper.CallEVM( ctxB, + stateDB, suite.chainBPrecompile.ABI, chainBAddr, suite.chainBPrecompile.Address(), false, + false, nil, ics20.DenomHashMethod, chainBDenom.Path(), @@ -327,10 +342,12 @@ func (suite *ICS20TransferV2TestSuite) TestHandleMsgTransfer() { // denomHash query method not exists case evmRes, err = evmAppB.EVMKeeper.CallEVM( ctxB, + stateDB, suite.chainBPrecompile.ABI, chainBAddr, suite.chainBPrecompile.Address(), false, + false, nil, ics20.DenomHashMethod, "transfer/channel-0/erc20:not-exists-case", @@ -343,10 +360,12 @@ func (suite *ICS20TransferV2TestSuite) TestHandleMsgTransfer() { // denomHash query method invalid error case evmRes, err = evmAppB.EVMKeeper.CallEVM( ctxB, + stateDB, suite.chainBPrecompile.ABI, chainBAddr, suite.chainBPrecompile.Address(), false, + false, nil, ics20.DenomHashMethod, "", diff --git a/evmd/tests/ibc/v2_transfer_test.go b/evmd/tests/ibc/v2_transfer_test.go index efcf5fc9..26840a43 100644 --- a/evmd/tests/ibc/v2_transfer_test.go +++ b/evmd/tests/ibc/v2_transfer_test.go @@ -22,10 +22,10 @@ import ( "github.com/cosmos/evm/evmd" "github.com/cosmos/evm/evmd/tests/integration" evmibctesting "github.com/cosmos/evm/testutil/ibc" - "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" - channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types" - channeltypesv2 "github.com/cosmos/ibc-go/v10/modules/core/04-channel/v2/types" + "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/v11/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/v11/modules/core/04-channel/types" + channeltypesv2 "github.com/cosmos/ibc-go/v11/modules/core/04-channel/v2/types" sdkmath "cosmossdk.io/math" diff --git a/evmd/tests/integration/ante/ante_test.go b/evmd/tests/integration/ante/ante_test.go index 19a5aa7e..d590438f 100644 --- a/evmd/tests/integration/ante/ante_test.go +++ b/evmd/tests/integration/ante/ante_test.go @@ -3,19 +3,24 @@ package ante import ( "testing" + evm "github.com/cosmos/evm" "github.com/cosmos/evm/evmd/tests/integration" "github.com/cosmos/evm/tests/integration/ante" + testapp "github.com/cosmos/evm/testutil/app" ) func TestAnte_Integration(t *testing.T) { - ante.TestIntegrationAnteHandler(t, integration.CreateEvmd) + create := testapp.ToEvmAppCreator[evm.AnteIntegrationApp](integration.CreateEvmd, "evm.AnteIntegrationApp") + ante.TestIntegrationAnteHandler(t, create) } func BenchmarkAnteHandler(b *testing.B) { + create := testapp.ToEvmAppCreator[evm.AnteIntegrationApp](integration.CreateEvmd, "evm.AnteIntegrationApp") // Run the benchmark with a mock EVM app - ante.RunBenchmarkAnteHandler(b, integration.CreateEvmd) + ante.RunBenchmarkAnteHandler(b, create) } func TestValidateHandlerOptions(t *testing.T) { - ante.RunValidateHandlerOptionsTest(t, integration.CreateEvmd) + create := testapp.ToEvmAppCreator[evm.AnteIntegrationApp](integration.CreateEvmd, "evm.AnteIntegrationApp") + ante.RunValidateHandlerOptionsTest(t, create) } diff --git a/evmd/tests/integration/ante/evm_unit_ante_test.go b/evmd/tests/integration/ante/evm_unit_ante_test.go index faea5906..a7b8ca47 100644 --- a/evmd/tests/integration/ante/evm_unit_ante_test.go +++ b/evmd/tests/integration/ante/evm_unit_ante_test.go @@ -3,12 +3,15 @@ package ante import ( "testing" + evm "github.com/cosmos/evm" "github.com/stretchr/testify/suite" "github.com/cosmos/evm/evmd/tests/integration" "github.com/cosmos/evm/tests/integration/ante" + testapp "github.com/cosmos/evm/testutil/app" ) func TestEvmUnitAnteTestSuite(t *testing.T) { - suite.Run(t, ante.NewEvmUnitAnteTestSuite(integration.CreateEvmd)) + create := testapp.ToEvmAppCreator[evm.AnteIntegrationApp](integration.CreateEvmd, "evm.AnteIntegrationApp") + suite.Run(t, ante.NewEvmUnitAnteTestSuite(create)) } diff --git a/evmd/tests/integration/backend_test.go b/evmd/tests/integration/backend_test.go index 541eed41..0585b122 100644 --- a/evmd/tests/integration/backend_test.go +++ b/evmd/tests/integration/backend_test.go @@ -5,10 +5,13 @@ import ( "github.com/stretchr/testify/suite" + evm "github.com/cosmos/evm" "github.com/cosmos/evm/tests/integration/rpc/backend" + testapp "github.com/cosmos/evm/testutil/app" ) func TestBackend(t *testing.T) { - s := backend.NewTestSuite(CreateEvmd) + create := testapp.ToEvmAppCreator[evm.IntegrationNetworkApp](CreateEvmd, "evm.IntegrationNetworkApp") + s := backend.NewTestSuite(create) suite.Run(t, s) } diff --git a/evmd/tests/integration/balance_handler/balance_handler_test.go b/evmd/tests/integration/balance_handler/balance_handler_test.go index a6309d64..5f5f3e3a 100644 --- a/evmd/tests/integration/balance_handler/balance_handler_test.go +++ b/evmd/tests/integration/balance_handler/balance_handler_test.go @@ -1,15 +1,9 @@ package balancehandler import ( - "fmt" - "math/big" "testing" - sdkmath "cosmossdk.io/math" - - "github.com/cosmos/cosmos-sdk/types" - "github.com/stretchr/testify/suite" "github.com/cosmos/evm" @@ -18,6 +12,10 @@ import ( debugprecompile "github.com/cosmos/evm/evmd/tests/testdata/debug" evmibctesting "github.com/cosmos/evm/testutil/ibc" testutiltypes "github.com/cosmos/evm/testutil/types" + + sdkmath "cosmossdk.io/math" + + "github.com/cosmos/cosmos-sdk/types" ) // BalanceHandlerTestSuite tests the balance handler bug where recursive precompile calls @@ -54,7 +52,7 @@ func (s *BalanceHandlerTestSuite) TestRecursivePrecompileCallsWithDebugPrecompil s.Require().NoError(err) a, b, c := evmApp.GetEVMKeeper().GetPrecompileInstance(ctx, debugPrec.Address()) - fmt.Println(a, b, c) + s.T().Logf("Precompile instance: %v, %v, %v", a, b, c) // Deploy caller contract callerContract, err := contracts.LoadDebugPrecompileCaller() @@ -91,15 +89,16 @@ func (s *BalanceHandlerTestSuite) TestRecursivePrecompileCallsWithDebugPrecompil ) s.Require().NoError(err, "callback transaction should succeed") s.Require().False(res.IsErr(), "callback should not fail: %s", res.Events) - s.Require().Equal(len(res.Events), 15, "callback should have 15 events") - debug_count := 0 + + debugCount := 0 for _, event := range res.Events { if event.Type == "debug_precompile" { - debug_count++ + debugCount++ } } - s.Require().Equal(10, debug_count, "callback should have 1 debug precompile") + + s.Require().Equal(10, debugCount, "callback should have 10 debug precompile events") // Advance to next block to finalize state s.chain.NextBlock() diff --git a/evmd/tests/integration/balance_handler/helper.go b/evmd/tests/integration/balance_handler/helper.go index 85c6a0a6..9eb21cf0 100644 --- a/evmd/tests/integration/balance_handler/helper.go +++ b/evmd/tests/integration/balance_handler/helper.go @@ -1,28 +1,29 @@ package balancehandler import ( - "errors" "testing" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" - errorsmod "cosmossdk.io/errors" - "github.com/cosmos/evm" - testutiltypes "github.com/cosmos/evm/testutil/types" evmibctesting "github.com/cosmos/evm/testutil/ibc" + testutiltypes "github.com/cosmos/evm/testutil/types" + "github.com/cosmos/evm/x/vm/statedb" + + errorsmod "cosmossdk.io/errors" ) // DeployContract deploys a contract to the test chain func DeployContract(t *testing.T, chain *evmibctesting.TestChain, deploymentData testutiltypes.ContractDeploymentData) (common.Address, error) { t.Helper() - // Get account's nonce to create contract hash + // Keep address derivation aligned with CallEVMWithData, which uses account sequence as nonce. from := common.BytesToAddress(chain.SenderPrivKey.PubKey().Address().Bytes()) - account := chain.App.(evm.EvmApp).GetEVMKeeper().GetAccount(chain.GetContext(), from) - if account == nil { - return common.Address{}, errors.New("account not found") + ctx := chain.GetContext() + nonce, err := chain.App.(evm.EvmApp).GetAccountKeeper().GetSequence(ctx, from.Bytes()) + if err != nil { + return common.Address{}, errorsmod.Wrap(err, "failed to get account sequence") } ctorArgs, err := deploymentData.Contract.ABI.Pack("", deploymentData.ConstructorArgs...) @@ -32,11 +33,12 @@ func DeployContract(t *testing.T, chain *evmibctesting.TestChain, deploymentData data := deploymentData.Contract.Bin data = append(data, ctorArgs...) + stateDB := statedb.New(ctx, chain.App.(evm.EvmApp).GetEVMKeeper(), statedb.NewEmptyTxConfig()) - _, err = chain.App.(evm.EvmApp).GetEVMKeeper().CallEVMWithData(chain.GetContext(), from, nil, data, true, nil) + _, err = chain.App.(evm.EvmApp).GetEVMKeeper().CallEVMWithData(ctx, stateDB, from, nil, data, true, false, nil) if err != nil { return common.Address{}, errorsmod.Wrapf(err, "failed to deploy contract") } - return crypto.CreateAddress(from, account.Nonce), nil + return crypto.CreateAddress(from, nonce), nil } diff --git a/evmd/tests/integration/create_app.go b/evmd/tests/integration/create_app.go index 5582468f..04ffb132 100644 --- a/evmd/tests/integration/create_app.go +++ b/evmd/tests/integration/create_app.go @@ -2,31 +2,31 @@ package integration import ( "encoding/json" - "github.com/cosmos/cosmos-sdk/client/flags" + "os" dbm "github.com/cosmos/cosmos-db" - ibctesting "github.com/cosmos/ibc-go/v10/testing" - "github.com/cosmos/evm" - "github.com/cosmos/evm/config" "github.com/cosmos/evm/evmd" srvflags "github.com/cosmos/evm/server/flags" "github.com/cosmos/evm/testutil/constants" feemarkettypes "github.com/cosmos/evm/x/feemarket/types" + ibctesting "github.com/cosmos/ibc-go/v11/testing" - clienthelpers "cosmossdk.io/client/v2/helpers" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" simutils "github.com/cosmos/cosmos-sdk/testutil/sims" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) -// CreateEvmd creates an evm app for regular integration tests (non-mempool) -// This version uses a noop mempool to avoid state issues during transaction processing +// CreateEvmd creates an evm app for integration tests func CreateEvmd(chainID string, evmChainID uint64, customBaseAppOptions ...func(*baseapp.BaseApp)) evm.EvmApp { - defaultNodeHome, err := clienthelpers.GetNodeHomeDirectory(".evmd") + // A temporary home directory is created and used to prevent race conditions + // related to home directory locks in chains that use the WASM module. + defaultNodeHome, err := os.MkdirTemp("", "evmd-temp-homedir") if err != nil { panic(err) } @@ -38,25 +38,41 @@ func CreateEvmd(chainID string, evmChainID uint64, customBaseAppOptions ...func( baseAppOptions := append(customBaseAppOptions, baseapp.SetChainID(chainID)) - return evmd.NewExampleApp( + // Start the app + app := evmd.NewExampleApp( logger, db, - nil, loadLatest, appOptions, baseAppOptions..., ) + + // Prepare the client context + clientCtx := client.Context{}.WithChainID(constants.ExampleChainID.ChainID). + WithHeight(1). + WithTxConfig(app.GetTxConfig()) + + // Get the mempool and set the client context if supported + if m, ok := app.GetMempool().(interface{ SetClientCtx(client.Context) }); ok && m != nil { + m.SetClientCtx(clientCtx) + } + + return app } // SetupEvmd initializes a new evmd app with default genesis state. // It is used in IBC integration tests to create a new evmd app instance. func SetupEvmd() (ibctesting.TestingApp, map[string]json.RawMessage) { + defaultNodeHome, err := os.MkdirTemp("", "evmd-temp-homedir") + if err != nil { + panic(err) + } + app := evmd.NewExampleApp( log.NewNopLogger(), dbm.NewMemDB(), - nil, true, - NewAppOptionsWithFlagHomeAndChainID("", constants.ExampleEIP155ChainID), + NewAppOptionsWithFlagHomeAndChainID(defaultNodeHome, constants.EighteenDecimalsChainID), ) // disable base fee for testing genesisState := app.DefaultGenesis() @@ -64,10 +80,10 @@ func SetupEvmd() (ibctesting.TestingApp, map[string]json.RawMessage) { fmGen.Params.NoBaseFee = true genesisState[feemarkettypes.ModuleName] = app.AppCodec().MustMarshalJSON(fmGen) stakingGen := stakingtypes.DefaultGenesisState() - stakingGen.Params.BondDenom = config.ExampleChainDenom + stakingGen.Params.BondDenom = constants.ExampleAttoDenom genesisState[stakingtypes.ModuleName] = app.AppCodec().MustMarshalJSON(stakingGen) mintGen := minttypes.DefaultGenesisState() - mintGen.Params.MintDenom = config.ExampleChainDenom + mintGen.Params.MintDenom = constants.ExampleAttoDenom genesisState[minttypes.ModuleName] = app.AppCodec().MustMarshalJSON(mintGen) return app, genesisState @@ -75,7 +91,9 @@ func SetupEvmd() (ibctesting.TestingApp, map[string]json.RawMessage) { func NewAppOptionsWithFlagHomeAndChainID(home string, evmChainID uint64) simutils.AppOptionsMap { return simutils.AppOptionsMap{ - flags.FlagHome: home, - srvflags.EVMChainID: evmChainID, + flags.FlagHome: home, + srvflags.EVMChainID: evmChainID, + srvflags.EVMMempoolInsertQueueSize: 5000, + srvflags.EVMMempoolPendingTxProposalTimeout: "250ms", } } diff --git a/evmd/tests/integration/eip712_test.go b/evmd/tests/integration/eip712_test.go index 777d8e08..a9cfd952 100644 --- a/evmd/tests/integration/eip712_test.go +++ b/evmd/tests/integration/eip712_test.go @@ -5,15 +5,18 @@ import ( "github.com/stretchr/testify/suite" + evm "github.com/cosmos/evm" "github.com/cosmos/evm/tests/integration/eip712" + testapp "github.com/cosmos/evm/testutil/app" ) func TestEIP712TestSuite(t *testing.T) { - s := eip712.NewTestSuite(CreateEvmd, false) + create := testapp.ToEvmAppCreator[evm.IntegrationNetworkApp](CreateEvmd, "evm.IntegrationNetworkApp") + s := eip712.NewTestSuite(create, false) suite.Run(t, s) // Note that we don't test the Legacy EIP-712 Extension, since that case // is sufficiently covered by the AnteHandler tests. - s = eip712.NewTestSuite(CreateEvmd, true) + s = eip712.NewTestSuite(create, true) suite.Run(t, s) } diff --git a/evmd/tests/integration/eip7702/eip7702_test.go b/evmd/tests/integration/eip7702/eip7702_test.go index 51ac4a40..0fadb274 100644 --- a/evmd/tests/integration/eip7702/eip7702_test.go +++ b/evmd/tests/integration/eip7702/eip7702_test.go @@ -3,10 +3,13 @@ package eip7702 import ( "testing" + evm "github.com/cosmos/evm" "github.com/cosmos/evm/evmd/tests/integration" "github.com/cosmos/evm/tests/integration/eip7702" + testapp "github.com/cosmos/evm/testutil/app" ) func TestEIP7702IntegrationTestSuite(t *testing.T) { - eip7702.TestEIP7702IntegrationTestSuite(t, integration.CreateEvmd) + create := testapp.ToEvmAppCreator[evm.IntegrationNetworkApp](integration.CreateEvmd, "evm.IntegrationNetworkApp") + eip7702.TestEIP7702IntegrationTestSuite(t, create) } diff --git a/evmd/tests/integration/eips/eips_test.go b/evmd/tests/integration/eips/eips_test.go index 1b283a8a..26bc483e 100644 --- a/evmd/tests/integration/eips/eips_test.go +++ b/evmd/tests/integration/eips/eips_test.go @@ -1,13 +1,17 @@ package eips_test import ( + "testing" + + evm "github.com/cosmos/evm" "github.com/cosmos/evm/evmd/tests/integration" "github.com/cosmos/evm/tests/integration/eips" - "testing" + testapp "github.com/cosmos/evm/testutil/app" //nolint:revive // dot imports are fine for Ginkgo //nolint:revive // dot imports are fine for Ginkgo ) func TestEIPs(t *testing.T) { - eips.RunTests(t, integration.CreateEvmd) + create := testapp.ToEvmAppCreator[evm.IntegrationNetworkApp](integration.CreateEvmd, "evm.IntegrationNetworkApp") + eips.RunTests(t, create) } diff --git a/evmd/tests/integration/ibc_callbacks_test.go b/evmd/tests/integration/ibc_callbacks_test.go index 725e883d..d4560f25 100644 --- a/evmd/tests/integration/ibc_callbacks_test.go +++ b/evmd/tests/integration/ibc_callbacks_test.go @@ -5,9 +5,12 @@ import ( "github.com/stretchr/testify/suite" + evm "github.com/cosmos/evm" "github.com/cosmos/evm/tests/integration/x/ibc/callbacks" + testapp "github.com/cosmos/evm/testutil/app" ) func TestIBCCallback(t *testing.T) { - suite.Run(t, callbacks.NewKeeperTestSuite(CreateEvmd)) + create := testapp.ToEvmAppCreator[evm.IBCCallbackIntegrationApp](CreateEvmd, "evm.IBCCallbackIntegrationApp") + suite.Run(t, callbacks.NewKeeperTestSuite(create)) } diff --git a/evmd/tests/integration/ibc_test.go b/evmd/tests/integration/ibc_test.go index 75048733..8f92f77c 100644 --- a/evmd/tests/integration/ibc_test.go +++ b/evmd/tests/integration/ibc_test.go @@ -5,10 +5,13 @@ import ( "github.com/stretchr/testify/suite" + evm "github.com/cosmos/evm" "github.com/cosmos/evm/tests/integration/x/ibc" + testapp "github.com/cosmos/evm/testutil/app" ) func TestIBCKeeperTestSuite(t *testing.T) { - s := ibc.NewKeeperTestSuite(CreateEvmd) + create := testapp.ToEvmAppCreator[evm.IBCIntegrationApp](CreateEvmd, "evm.IBCIntegrationApp") + s := ibc.NewKeeperTestSuite(create) suite.Run(t, s) } diff --git a/evmd/tests/integration/indexer_test.go b/evmd/tests/integration/indexer_test.go index 926d0786..75d29766 100644 --- a/evmd/tests/integration/indexer_test.go +++ b/evmd/tests/integration/indexer_test.go @@ -3,9 +3,12 @@ package integration import ( "testing" + evm "github.com/cosmos/evm" "github.com/cosmos/evm/tests/integration/indexer" + testapp "github.com/cosmos/evm/testutil/app" ) func TestKVIndexer(t *testing.T) { - indexer.TestKVIndexer(t, CreateEvmd) + create := testapp.ToEvmAppCreator[evm.IntegrationNetworkApp](CreateEvmd, "evm.IntegrationNetworkApp") + indexer.TestKVIndexer(t, create) } diff --git a/evmd/tests/integration/mempool/mempool_test.go b/evmd/tests/integration/mempool/mempool_test.go index 8c3830db..50090ea8 100644 --- a/evmd/tests/integration/mempool/mempool_test.go +++ b/evmd/tests/integration/mempool/mempool_test.go @@ -3,13 +3,15 @@ package mempool import ( "testing" - "github.com/cosmos/evm/evmd/tests/integration" - "github.com/stretchr/testify/suite" + evm "github.com/cosmos/evm" + "github.com/cosmos/evm/evmd/tests/integration" "github.com/cosmos/evm/tests/integration/mempool" + testapp "github.com/cosmos/evm/testutil/app" ) func TestMempoolIntegrationTestSuite(t *testing.T) { - suite.Run(t, mempool.NewMempoolIntegrationTestSuite(integration.CreateEvmd)) + create := testapp.ToEvmAppCreator[evm.IntegrationNetworkApp](integration.CreateEvmd, "evm.IntegrationNetworkApp") + suite.Run(t, mempool.NewMempoolIntegrationTestSuite(create)) } diff --git a/evmd/tests/integration/precompiles/bank/precompile_bank_test.go b/evmd/tests/integration/precompiles/bank/precompile_bank_test.go index 6f3c8acb..3b6aaadf 100644 --- a/evmd/tests/integration/precompiles/bank/precompile_bank_test.go +++ b/evmd/tests/integration/precompiles/bank/precompile_bank_test.go @@ -5,15 +5,19 @@ import ( "github.com/stretchr/testify/suite" + evm "github.com/cosmos/evm" "github.com/cosmos/evm/evmd/tests/integration" "github.com/cosmos/evm/tests/integration/precompiles/bank" + testapp "github.com/cosmos/evm/testutil/app" ) func TestBankPrecompileTestSuite(t *testing.T) { - s := bank.NewPrecompileTestSuite(integration.CreateEvmd) + create := testapp.ToEvmAppCreator[evm.BankPrecompileApp](integration.CreateEvmd, "evm.BankPrecompileApp") + s := bank.NewPrecompileTestSuite(create) suite.Run(t, s) } func TestBankPrecompileIntegrationTestSuite(t *testing.T) { - bank.TestIntegrationSuite(t, integration.CreateEvmd) + create := testapp.ToEvmAppCreator[evm.BankPrecompileApp](integration.CreateEvmd, "evm.BankPrecompileApp") + bank.TestIntegrationSuite(t, create) } diff --git a/evmd/tests/integration/precompiles/bech32/precompile_bech32_test.go b/evmd/tests/integration/precompiles/bech32/precompile_bech32_test.go index 8bbdcd7f..de02edcb 100644 --- a/evmd/tests/integration/precompiles/bech32/precompile_bech32_test.go +++ b/evmd/tests/integration/precompiles/bech32/precompile_bech32_test.go @@ -5,11 +5,14 @@ import ( "github.com/stretchr/testify/suite" + evm "github.com/cosmos/evm" "github.com/cosmos/evm/evmd/tests/integration" "github.com/cosmos/evm/tests/integration/precompiles/bech32" + testapp "github.com/cosmos/evm/testutil/app" ) func TestBech32PrecompileTestSuite(t *testing.T) { - s := bech32.NewPrecompileTestSuite(integration.CreateEvmd) + create := testapp.ToEvmAppCreator[evm.Bech32PrecompileApp](integration.CreateEvmd, "evm.Bech32PrecompileApp") + s := bech32.NewPrecompileTestSuite(create) suite.Run(t, s) } diff --git a/evmd/tests/integration/precompiles/common/precompile_common_test.go b/evmd/tests/integration/precompiles/common/precompile_common_test.go new file mode 100644 index 00000000..27a50bd4 --- /dev/null +++ b/evmd/tests/integration/precompiles/common/precompile_common_test.go @@ -0,0 +1,15 @@ +package common + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/evmd/tests/integration" + "github.com/cosmos/evm/tests/integration/precompiles/common" +) + +func TestStaticCallTestSuite(t *testing.T) { + s := common.NewStaticCallTestSuite(integration.CreateEvmd) + suite.Run(t, s) +} diff --git a/evmd/tests/integration/precompiles/distribution/precompile_distribution_test.go b/evmd/tests/integration/precompiles/distribution/precompile_distribution_test.go index 0b81df7d..92e502f5 100644 --- a/evmd/tests/integration/precompiles/distribution/precompile_distribution_test.go +++ b/evmd/tests/integration/precompiles/distribution/precompile_distribution_test.go @@ -5,15 +5,19 @@ import ( "github.com/stretchr/testify/suite" + evm "github.com/cosmos/evm" "github.com/cosmos/evm/evmd/tests/integration" "github.com/cosmos/evm/tests/integration/precompiles/distribution" + testapp "github.com/cosmos/evm/testutil/app" ) func TestDistributionPrecompileTestSuite(t *testing.T) { - s := distribution.NewPrecompileTestSuite(integration.CreateEvmd) + create := testapp.ToEvmAppCreator[evm.DistributionPrecompileApp](integration.CreateEvmd, "evm.DistributionPrecompileApp") + s := distribution.NewPrecompileTestSuite(create) suite.Run(t, s) } func TestDistributionPrecompileIntegrationTestSuite(t *testing.T) { - distribution.TestPrecompileIntegrationTestSuite(t, integration.CreateEvmd) + create := testapp.ToEvmAppCreator[evm.DistributionPrecompileApp](integration.CreateEvmd, "evm.DistributionPrecompileApp") + distribution.TestPrecompileIntegrationTestSuite(t, create) } diff --git a/evmd/tests/integration/precompiles/erc20/precompile_erc20_test.go b/evmd/tests/integration/precompiles/erc20/precompile_erc20_test.go index ba27ed04..68b29a83 100644 --- a/evmd/tests/integration/precompiles/erc20/precompile_erc20_test.go +++ b/evmd/tests/integration/precompiles/erc20/precompile_erc20_test.go @@ -5,15 +5,19 @@ import ( "github.com/stretchr/testify/suite" + evm "github.com/cosmos/evm" "github.com/cosmos/evm/evmd/tests/integration" - erc21 "github.com/cosmos/evm/tests/integration/precompiles/erc20" + "github.com/cosmos/evm/tests/integration/precompiles/erc20" + testapp "github.com/cosmos/evm/testutil/app" ) func TestErc20PrecompileTestSuite(t *testing.T) { - s := erc21.NewPrecompileTestSuite(integration.CreateEvmd) + create := testapp.ToEvmAppCreator[evm.Erc20PrecompileApp](integration.CreateEvmd, "evm.Erc20PrecompileApp") + s := erc20.NewPrecompileTestSuite(create) suite.Run(t, s) } func TestErc20IntegrationTestSuite(t *testing.T) { - erc21.TestIntegrationTestSuite(t, integration.CreateEvmd) + create := testapp.ToEvmAppCreator[evm.Erc20PrecompileApp](integration.CreateEvmd, "evm.Erc20PrecompileApp") + erc20.TestIntegrationTestSuite(t, create) } diff --git a/evmd/tests/integration/precompiles/gov/precompile_gov_test.go b/evmd/tests/integration/precompiles/gov/precompile_gov_test.go index 7b06fc34..bb55eaf2 100644 --- a/evmd/tests/integration/precompiles/gov/precompile_gov_test.go +++ b/evmd/tests/integration/precompiles/gov/precompile_gov_test.go @@ -5,15 +5,19 @@ import ( "github.com/stretchr/testify/suite" + evm "github.com/cosmos/evm" "github.com/cosmos/evm/evmd/tests/integration" "github.com/cosmos/evm/tests/integration/precompiles/gov" + testapp "github.com/cosmos/evm/testutil/app" ) func TestGovPrecompileTestSuite(t *testing.T) { - s := gov.NewPrecompileTestSuite(integration.CreateEvmd) + create := testapp.ToEvmAppCreator[evm.GovPrecompileApp](integration.CreateEvmd, "evm.GovPrecompileApp") + s := gov.NewPrecompileTestSuite(create) suite.Run(t, s) } func TestGovPrecompileIntegrationTestSuite(t *testing.T) { - gov.TestPrecompileIntegrationTestSuite(t, integration.CreateEvmd) + create := testapp.ToEvmAppCreator[evm.GovPrecompileApp](integration.CreateEvmd, "evm.GovPrecompileApp") + gov.TestPrecompileIntegrationTestSuite(t, create) } diff --git a/evmd/tests/integration/precompiles/ics20/precompile_ics20_test.go b/evmd/tests/integration/precompiles/ics20/precompile_ics20_test.go index 98a3583a..2b2ccfa4 100644 --- a/evmd/tests/integration/precompiles/ics20/precompile_ics20_test.go +++ b/evmd/tests/integration/precompiles/ics20/precompile_ics20_test.go @@ -5,15 +5,19 @@ import ( "github.com/stretchr/testify/suite" + "github.com/cosmos/evm" "github.com/cosmos/evm/evmd/tests/integration" "github.com/cosmos/evm/tests/integration/precompiles/ics20" + testapp "github.com/cosmos/evm/testutil/app" ) +var ibcAppCreator = testapp.ToIBCAppCreator[evm.ICS20PrecompileApp](integration.SetupEvmd, "evm.ICS20PrecompileApp") + func TestICS20PrecompileTestSuite(t *testing.T) { - s := ics20.NewPrecompileTestSuite(t, integration.SetupEvmd) + s := ics20.NewPrecompileTestSuite(t, ibcAppCreator) suite.Run(t, s) } func TestICS20PrecompileIntegrationTestSuite(t *testing.T) { - ics20.TestPrecompileIntegrationTestSuite(t, integration.SetupEvmd) + ics20.TestPrecompileIntegrationTestSuite(t, ibcAppCreator) } diff --git a/evmd/tests/integration/precompiles/p256/precompile_p256_test.go b/evmd/tests/integration/precompiles/p256/precompile_p256_test.go index 31a4e3d0..02947df1 100644 --- a/evmd/tests/integration/precompiles/p256/precompile_p256_test.go +++ b/evmd/tests/integration/precompiles/p256/precompile_p256_test.go @@ -5,15 +5,19 @@ import ( "github.com/stretchr/testify/suite" + evm "github.com/cosmos/evm" "github.com/cosmos/evm/evmd/tests/integration" "github.com/cosmos/evm/tests/integration/precompiles/p256" + testapp "github.com/cosmos/evm/testutil/app" ) func TestP256PrecompileTestSuite(t *testing.T) { - s := p256.NewPrecompileTestSuite(integration.CreateEvmd) + create := testapp.ToEvmAppCreator[evm.P256PrecompileApp](integration.CreateEvmd, "evm.P256PrecompileApp") + s := p256.NewPrecompileTestSuite(create) suite.Run(t, s) } func TestP256PrecompileIntegrationTestSuite(t *testing.T) { - p256.TestPrecompileIntegrationTestSuite(t, integration.CreateEvmd) + create := testapp.ToEvmAppCreator[evm.P256PrecompileApp](integration.CreateEvmd, "evm.P256PrecompileApp") + p256.TestPrecompileIntegrationTestSuite(t, create) } diff --git a/evmd/tests/integration/precompiles/slashing/precompile_slashing_test.go b/evmd/tests/integration/precompiles/slashing/precompile_slashing_test.go index c4c47e26..cbe3eb4a 100644 --- a/evmd/tests/integration/precompiles/slashing/precompile_slashing_test.go +++ b/evmd/tests/integration/precompiles/slashing/precompile_slashing_test.go @@ -5,15 +5,19 @@ import ( "github.com/stretchr/testify/suite" + evm "github.com/cosmos/evm" "github.com/cosmos/evm/evmd/tests/integration" "github.com/cosmos/evm/tests/integration/precompiles/slashing" + testapp "github.com/cosmos/evm/testutil/app" ) func TestSlashingPrecompileTestSuite(t *testing.T) { - s := slashing.NewPrecompileTestSuite(integration.CreateEvmd) + create := testapp.ToEvmAppCreator[evm.SlashingPrecompileApp](integration.CreateEvmd, "evm.SlashingPrecompileApp") + s := slashing.NewPrecompileTestSuite(create) suite.Run(t, s) } func TestStakingPrecompileIntegrationTestSuite(t *testing.T) { - slashing.TestPrecompileIntegrationTestSuite(t, integration.CreateEvmd) + create := testapp.ToEvmAppCreator[evm.SlashingPrecompileApp](integration.CreateEvmd, "evm.SlashingPrecompileApp") + slashing.TestPrecompileIntegrationTestSuite(t, create) } diff --git a/evmd/tests/integration/precompiles/staking/precompile_staking_test.go b/evmd/tests/integration/precompiles/staking/precompile_staking_test.go index 9b44eb22..13ee8b22 100644 --- a/evmd/tests/integration/precompiles/staking/precompile_staking_test.go +++ b/evmd/tests/integration/precompiles/staking/precompile_staking_test.go @@ -5,15 +5,19 @@ import ( "github.com/stretchr/testify/suite" + evm "github.com/cosmos/evm" "github.com/cosmos/evm/evmd/tests/integration" "github.com/cosmos/evm/tests/integration/precompiles/staking" + testapp "github.com/cosmos/evm/testutil/app" ) func TestStakingPrecompileTestSuite(t *testing.T) { - s := staking.NewPrecompileTestSuite(integration.CreateEvmd) + create := testapp.ToEvmAppCreator[evm.StakingPrecompileApp](integration.CreateEvmd, "evm.StakingPrecompileApp") + s := staking.NewPrecompileTestSuite(create) suite.Run(t, s) } func TestStakingPrecompileIntegrationTestSuite(t *testing.T) { - staking.TestPrecompileIntegrationTestSuite(t, integration.CreateEvmd) + create := testapp.ToEvmAppCreator[evm.StakingPrecompileApp](integration.CreateEvmd, "evm.StakingPrecompileApp") + staking.TestPrecompileIntegrationTestSuite(t, create) } diff --git a/evmd/tests/integration/precompiles/werc20/precompile_werc20_test.go b/evmd/tests/integration/precompiles/werc20/precompile_werc20_test.go index 011e605f..f2e4ed7e 100644 --- a/evmd/tests/integration/precompiles/werc20/precompile_werc20_test.go +++ b/evmd/tests/integration/precompiles/werc20/precompile_werc20_test.go @@ -5,15 +5,19 @@ import ( "github.com/stretchr/testify/suite" + evm "github.com/cosmos/evm" "github.com/cosmos/evm/evmd/tests/integration" "github.com/cosmos/evm/tests/integration/precompiles/werc20" + testapp "github.com/cosmos/evm/testutil/app" ) func TestWERC20PrecompileUnitTestSuite(t *testing.T) { - s := werc20.NewPrecompileUnitTestSuite(integration.CreateEvmd) + create := testapp.ToEvmAppCreator[evm.WERC20PrecompileApp](integration.CreateEvmd, "evm.WERC20PrecompileApp") + s := werc20.NewPrecompileUnitTestSuite(create) suite.Run(t, s) } func TestWERC20PrecompileIntegrationTestSuite(t *testing.T) { - werc20.TestPrecompileIntegrationTestSuite(t, integration.CreateEvmd) + create := testapp.ToEvmAppCreator[evm.WERC20PrecompileApp](integration.CreateEvmd, "evm.WERC20PrecompileApp") + werc20.TestPrecompileIntegrationTestSuite(t, create) } diff --git a/evmd/tests/integration/wallets_test.go b/evmd/tests/integration/wallets_test.go index c30584d5..f873fb1a 100644 --- a/evmd/tests/integration/wallets_test.go +++ b/evmd/tests/integration/wallets_test.go @@ -5,10 +5,13 @@ import ( "github.com/stretchr/testify/suite" + evm "github.com/cosmos/evm" "github.com/cosmos/evm/tests/integration/wallets" + testapp "github.com/cosmos/evm/testutil/app" ) func TestLedgerTestSuite(t *testing.T) { - s := wallets.NewLedgerTestSuite(CreateEvmd) + create := testapp.ToEvmAppCreator[evm.IntegrationNetworkApp](CreateEvmd, "evm.IntegrationNetworkApp") + s := wallets.NewLedgerTestSuite(create) suite.Run(t, s) } diff --git a/evmd/tests/integration/x_erc20_test.go b/evmd/tests/integration/x_erc20_test.go index 1a1e46b0..ef5c5569 100644 --- a/evmd/tests/integration/x_erc20_test.go +++ b/evmd/tests/integration/x_erc20_test.go @@ -5,18 +5,23 @@ import ( "github.com/stretchr/testify/suite" + evm "github.com/cosmos/evm" "github.com/cosmos/evm/tests/integration/x/erc20" + testapp "github.com/cosmos/evm/testutil/app" ) func TestERC20GenesisTestSuite(t *testing.T) { - suite.Run(t, erc20.NewGenesisTestSuite(CreateEvmd)) + create := testapp.ToEvmAppCreator[evm.Erc20IntegrationApp](CreateEvmd, "evm.Erc20IntegrationApp") + suite.Run(t, erc20.NewGenesisTestSuite(create)) } func TestERC20KeeperTestSuite(t *testing.T) { - s := erc20.NewKeeperTestSuite(CreateEvmd) + create := testapp.ToEvmAppCreator[evm.Erc20IntegrationApp](CreateEvmd, "evm.Erc20IntegrationApp") + s := erc20.NewKeeperTestSuite(create) suite.Run(t, s) } func TestERC20PrecompileIntegrationTestSuite(t *testing.T) { - erc20.TestPrecompileIntegrationTestSuite(t, CreateEvmd) + create := testapp.ToEvmAppCreator[evm.Erc20IntegrationApp](CreateEvmd, "evm.Erc20IntegrationApp") + erc20.TestPrecompileIntegrationTestSuite(t, create) } diff --git a/evmd/tests/integration/x_feemarket_test.go b/evmd/tests/integration/x_feemarket_test.go index 34cbcbd1..dd9ac06b 100644 --- a/evmd/tests/integration/x_feemarket_test.go +++ b/evmd/tests/integration/x_feemarket_test.go @@ -5,10 +5,13 @@ import ( "github.com/stretchr/testify/suite" + evm "github.com/cosmos/evm" "github.com/cosmos/evm/tests/integration/x/feemarket" + testapp "github.com/cosmos/evm/testutil/app" ) func TestFeeMarketKeeperTestSuite(t *testing.T) { - s := feemarket.NewTestKeeperTestSuite(CreateEvmd) + create := testapp.ToEvmAppCreator[evm.IntegrationNetworkApp](CreateEvmd, "evm.IntegrationNetworkApp") + s := feemarket.NewTestKeeperTestSuite(create) suite.Run(t, s) } diff --git a/evmd/tests/integration/x_precisebank_test.go b/evmd/tests/integration/x_precisebank_test.go deleted file mode 100644 index 950b473f..00000000 --- a/evmd/tests/integration/x_precisebank_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package integration - -import ( - "testing" - - "github.com/stretchr/testify/suite" - - "github.com/cosmos/evm/tests/integration/x/precisebank" -) - -func TestPreciseBankGenesis(t *testing.T) { - s := precisebank.NewGenesisTestSuite(CreateEvmd) - suite.Run(t, s) -} - -func TestPreciseBankKeeper(t *testing.T) { - s := precisebank.NewKeeperIntegrationTestSuite(CreateEvmd) - suite.Run(t, s) -} diff --git a/evmd/tests/integration/x_vm_test.go b/evmd/tests/integration/x_vm_test.go index e0ce08f0..1c2d91bf 100644 --- a/evmd/tests/integration/x_vm_test.go +++ b/evmd/tests/integration/x_vm_test.go @@ -4,8 +4,10 @@ import ( "encoding/json" "testing" + evm "github.com/cosmos/evm" "github.com/cosmos/evm/server/config" "github.com/cosmos/evm/tests/integration/x/vm" + testapp "github.com/cosmos/evm/testutil/app" "github.com/cosmos/evm/testutil/integration/evm/network" "github.com/cosmos/evm/testutil/keyring" feemarkettypes "github.com/cosmos/evm/x/feemarket/types" @@ -17,6 +19,7 @@ import ( ) func BenchmarkGasEstimation(b *testing.B) { + vmAppCreator := testapp.ToEvmAppCreator[evm.VMIntegrationApp](CreateEvmd, "evm.VMIntegrationApp") // Setup benchmark test environment keys := keyring.New(2) // Set custom balance based on test params @@ -28,7 +31,7 @@ func BenchmarkGasEstimation(b *testing.B) { network.WithPreFundedAccounts(keys.GetAllAccAddrs()...), network.WithCustomGenesis(customGenesis), } - nw := network.NewUnitTestNetwork(CreateEvmd, opts...) + nw := network.NewUnitTestNetwork(vmAppCreator, opts...) // gh := grpc.NewIntegrationHandler(nw) // tf := factory.New(nw, gh) @@ -84,27 +87,32 @@ func BenchmarkGasEstimation(b *testing.B) { } func TestKeeperTestSuite(t *testing.T) { - s := vm.NewKeeperTestSuite(CreateEvmd) + create := testapp.ToEvmAppCreator[evm.VMIntegrationApp](CreateEvmd, "evm.VMIntegrationApp") + s := vm.NewKeeperTestSuite(create) s.EnableFeemarket = false s.EnableLondonHF = true suite.Run(t, s) } func TestNestedEVMExtensionCallSuite(t *testing.T) { - s := vm.NewNestedEVMExtensionCallSuite(CreateEvmd) + create := testapp.ToEvmAppCreator[evm.VMIntegrationApp](CreateEvmd, "evm.VMIntegrationApp") + s := vm.NewNestedEVMExtensionCallSuite(create) suite.Run(t, s) } func TestGenesisTestSuite(t *testing.T) { - s := vm.NewGenesisTestSuite(CreateEvmd) + create := testapp.ToEvmAppCreator[evm.VMIntegrationApp](CreateEvmd, "evm.VMIntegrationApp") + s := vm.NewGenesisTestSuite(create) suite.Run(t, s) } func TestVmAnteTestSuite(t *testing.T) { - s := vm.NewEvmAnteTestSuite(CreateEvmd) + create := testapp.ToEvmAppCreator[evm.VMIntegrationApp](CreateEvmd, "evm.VMIntegrationApp") + s := vm.NewEvmAnteTestSuite(create) suite.Run(t, s) } func TestIterateContracts(t *testing.T) { - vm.TestIterateContracts(t, CreateEvmd) + create := testapp.ToEvmAppCreator[evm.VMIntegrationApp](CreateEvmd, "evm.VMIntegrationApp") + vm.TestIterateContracts(t, create) } diff --git a/evmd/tests/network/network.go b/evmd/tests/network/network.go index 40c00875..6b2c6867 100644 --- a/evmd/tests/network/network.go +++ b/evmd/tests/network/network.go @@ -17,8 +17,6 @@ import ( "testing" "time" - "github.com/cosmos/evm/utils" - "github.com/ethereum/go-ethereum/ethclient" "github.com/spf13/cobra" "golang.org/x/sync/errgroup" @@ -28,16 +26,17 @@ import ( cmtclient "github.com/cometbft/cometbft/rpc/client" dbm "github.com/cosmos/cosmos-db" - evmconfig "github.com/cosmos/evm/config" "github.com/cosmos/evm/crypto/hd" "github.com/cosmos/evm/evmd" + evmconfig "github.com/cosmos/evm/evmd/config" "github.com/cosmos/evm/server/config" evmtestutil "github.com/cosmos/evm/testutil" testconstants "github.com/cosmos/evm/testutil/constants" + "github.com/cosmos/evm/utils" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" "cosmossdk.io/math" - pruningtypes "cosmossdk.io/store/pruning/types" + pruningtypes "github.com/cosmos/cosmos-sdk/store/v2/pruning/types" "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/client" @@ -110,7 +109,7 @@ func DefaultConfig() Config { panic(fmt.Sprintf("failed creating temporary directory: %v", err)) } defer os.RemoveAll(dir) - tempApp := evmd.NewExampleApp(log.NewNopLogger(), dbm.NewMemDB(), nil, true, simutils.NewAppOptionsWithFlagHome(dir), baseapp.SetChainID(chainID)) + tempApp := evmd.NewExampleApp(log.NewNopLogger(), dbm.NewMemDB(), true, simutils.NewAppOptionsWithFlagHome(dir), baseapp.SetChainID(chainID)) cfg := Config{ Codec: tempApp.AppCodec(), @@ -141,7 +140,7 @@ func DefaultConfig() Config { func NewAppConstructor(chainID string) AppConstructor { return func(val Validator) servertypes.Application { return evmd.NewExampleApp( - val.Ctx.Logger, dbm.NewMemDB(), nil, true, + val.Ctx.Logger, dbm.NewMemDB(), true, simutils.NewAppOptionsWithFlagHome(val.Ctx.Config.RootDir), baseapp.SetPruning(pruningtypes.NewPruningOptionsFromString(val.AppConfig.Pruning)), baseapp.SetMinGasPrices(val.AppConfig.MinGasPrices), @@ -485,7 +484,7 @@ func New(l Logger, baseDir string, cfg Config) (*Network, error) { return nil, err } - customAppTemplate, _ := evmconfig.InitAppConfig(testconstants.ExampleAttoDenom, testconstants.ExampleEIP155ChainID) + customAppTemplate, _ := evmconfig.InitAppConfig(testconstants.ExampleAttoDenom, testconstants.EighteenDecimalsChainID) srvconfig.SetConfigTemplate(customAppTemplate) srvconfig.WriteConfigFile(filepath.Join(nodeDir, "config/app.toml"), appCfg) diff --git a/evmd/tests/network/util.go b/evmd/tests/network/util.go index fc4a538d..a3ac58a4 100644 --- a/evmd/tests/network/util.go +++ b/evmd/tests/network/util.go @@ -8,6 +8,7 @@ import ( "github.com/ethereum/go-ethereum/ethclient" "golang.org/x/sync/errgroup" + "google.golang.org/grpc" cmtcfg "github.com/cometbft/cometbft/config" tmos "github.com/cometbft/cometbft/libs/os" @@ -22,7 +23,7 @@ import ( "github.com/cosmos/evm/server" evmtypes "github.com/cosmos/evm/x/vm/types" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" sdkserver "github.com/cosmos/cosmos-sdk/server" "github.com/cosmos/cosmos-sdk/server/api" @@ -110,7 +111,9 @@ func startInProcess(cfg Config, val *Validator) error { } if val.AppConfig.GRPC.Enable { - grpcSrv, err := servergrpc.NewGRPCServer(val.ClientCtx, app, val.AppConfig.GRPC) + grpcLogger := logger.With(log.ModuleKey, "grpc-server") + var grpcSrv *grpc.Server + grpcSrv, val.ClientCtx, err = servergrpc.NewGRPCServerAndContext(val.ClientCtx, app, val.AppConfig.GRPC, grpcLogger) if err != nil { return err } @@ -118,7 +121,7 @@ func startInProcess(cfg Config, val *Validator) error { // Start the gRPC server in a goroutine. Note, the provided ctx will ensure // that the server is gracefully shut down. val.errGroup.Go(func() error { - return servergrpc.StartGRPCServer(ctx, logger.With(log.ModuleKey, "grpc-server"), val.AppConfig.GRPC, grpcSrv) + return servergrpc.StartGRPCServer(ctx, grpcLogger, val.AppConfig.GRPC, grpcSrv) }) val.grpc = grpcSrv @@ -128,7 +131,6 @@ func startInProcess(cfg Config, val *Validator) error { if val.Ctx == nil || val.Ctx.Viper == nil { return fmt.Errorf("validator %s context is nil", val.Moniker) } - val.jsonrpc, err = server.StartJSONRPC( ctx, val.Ctx, @@ -226,7 +228,6 @@ func initGenFiles(cfg Config, genAccounts []authtypes.GenesisAccount, genBalance inflationGenState.Params.MintDenom = cfg.BondDenom cfg.GenesisState[minttypes.ModuleName] = cfg.Codec.MustMarshalJSON(&inflationGenState) - var evmGenState evmtypes.GenesisState cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[evmtypes.ModuleName], &evmGenState) diff --git a/evmd/tests/testdata/debug/debug.go b/evmd/tests/testdata/debug/debug.go index 0cc02bfa..da2aa819 100644 --- a/evmd/tests/testdata/debug/debug.go +++ b/evmd/tests/testdata/debug/debug.go @@ -9,9 +9,12 @@ import ( "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/vm" - storetypes "cosmossdk.io/store/types" - sdk "github.com/cosmos/cosmos-sdk/types" cmn "github.com/cosmos/evm/precompiles/common" + "github.com/cosmos/evm/x/vm/statedb" + + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" + + sdk "github.com/cosmos/cosmos-sdk/types" ) // Precompile defines a debugging precompile for use in testing. @@ -35,6 +38,10 @@ func NewPrecompile(bankKeeper cmn.BankKeeper, evmKeeper EVMKeeper) *Precompile { } } +func (Precompile) Name() string { + return "debug-precompile" +} + func (p Precompile) RequiredGas(input []byte) uint64 { return 1000 } @@ -66,7 +73,12 @@ func (p Precompile) Call0(ctx sdk.Context, stateDB vm.StateDB, contract *vm.Cont caller := contract.Caller() fmt.Printf("Execute debug precompile %s, %p\n", caller.String(), p.BalanceHandlerFactory) - rsp, err := p.evmKeeper.CallEVMWithData(ctx, p.Address(), &caller, data, true, nil) + stateDBExp := stateDB.(*statedb.StateDB) + // Note: when called from within a precompile context, we do not set + // commit to true. Doing so will collapse the cache stack and subsequent + // reversions will panic. + rsp, err := p.evmKeeper.CallEVMWithData(ctx, stateDBExp, p.Address(), &caller, data, true, true, nil) + fmt.Println("callback response:", rsp.Ret, err) if err != nil { return nil, err diff --git a/evmd/tests/testdata/debug/interface.go b/evmd/tests/testdata/debug/interface.go index 2fc70e75..2a005283 100644 --- a/evmd/tests/testdata/debug/interface.go +++ b/evmd/tests/testdata/debug/interface.go @@ -1,21 +1,25 @@ package debug import ( + "math/big" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/evm/x/vm/statedb" evmtypes "github.com/cosmos/evm/x/vm/types" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" - "math/big" ) type EVMKeeper interface { - CallEVM(ctx sdk.Context, abi abi.ABI, from, contract common.Address, commit bool, gasCap *big.Int, method string, args ...interface{}) (*evmtypes.MsgEthereumTxResponse, error) + CallEVM(ctx sdk.Context, stateDB *statedb.StateDB, abi abi.ABI, from, contract common.Address, commit bool, callFromPrecompile bool, gasCap *big.Int, method string, args ...interface{}) (*evmtypes.MsgEthereumTxResponse, error) CallEVMWithData( ctx sdk.Context, + stateDB *statedb.StateDB, from common.Address, contract *common.Address, data []byte, commit bool, + callFromPrecompile bool, gasCap *big.Int, ) (*evmtypes.MsgEthereumTxResponse, error) } diff --git a/evmd/testutil/abci.go b/evmd/testutil/abci.go index c14f466c..5c364af0 100644 --- a/evmd/testutil/abci.go +++ b/evmd/testutil/abci.go @@ -256,7 +256,7 @@ func checkTxBytes(app evm.EvmApp, txEncoder sdk.TxEncoder, tx sdk.Tx) (abci.Resp } if res.Code != 0 { - return abci.ResponseCheckTx{}, errorsmod.Wrapf(errortypes.ErrInvalidRequest, res.Log) + return abci.ResponseCheckTx{}, errorsmod.Wrap(errortypes.ErrInvalidRequest, res.Log) } return *res, nil diff --git a/evmd/tx_verifier.go b/evmd/tx_verifier.go new file mode 100644 index 00000000..224d3abe --- /dev/null +++ b/evmd/tx_verifier.go @@ -0,0 +1,27 @@ +package evmd + +import ( + "github.com/cosmos/cosmos-sdk/baseapp" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var _ baseapp.ProposalTxVerifier = &NoCheckProposalTxVerifier{} + +type NoCheckProposalTxVerifier struct { + *baseapp.BaseApp +} + +func NewNoCheckProposalTxVerifier(b *baseapp.BaseApp) *NoCheckProposalTxVerifier { + return &NoCheckProposalTxVerifier{BaseApp: b} +} + +// PrepareProposalVerifyTx overrides the typical tx verification done in +// BaseApp's PrepareProposalHandler. The default PrepareProposalVerifyTx +// implementation encodes the tx to bytes, then calls runTx in 'checktx' mode, +// executing all antehandlers. +// +// We now override the implementation to only verify that the tx can be encoded +// to bytes, since we will guarantee that all txs selected are valid elsewhere. +func (txv *NoCheckProposalTxVerifier) PrepareProposalVerifyTx(tx sdk.Tx) ([]byte, error) { + return txv.TxEncode(tx) +} diff --git a/evmd/upgrades.go b/evmd/upgrades.go index 272428f6..b8e4d4d8 100644 --- a/evmd/upgrades.go +++ b/evmd/upgrades.go @@ -3,23 +3,19 @@ package evmd import ( "context" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - "github.com/cosmos/evm/x/vm/types" - + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" 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" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" ) // UpgradeName defines the on-chain upgrade name for the sample EVMD upgrade -// from v0.4.0 to v0.5.0. +// from v0.6.0 to v0.7.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" +// v0.6.x to v0.7.0. +const UpgradeName = "v0.6.0-to-v0.7.0" func (app EVMD) RegisterUpgradeHandlers() { app.UpgradeKeeper.SetUpgradeHandler( @@ -27,43 +23,6 @@ func (app EVMD) RegisterUpgradeHandlers() { func(ctx context.Context, _ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { sdkCtx := sdk.UnwrapSDKContext(ctx) sdkCtx.Logger().Debug("this is a debug level message to test that verbose logging mode has properly been enabled during a chain upgrade") - - app.BankKeeper.SetDenomMetaData(ctx, banktypes.Metadata{ - Description: "Example description", - DenomUnits: []*banktypes.DenomUnit{ - { - Denom: "atest", - Exponent: 0, - Aliases: nil, - }, - { - Denom: "test", - Exponent: 18, - Aliases: nil, - }, - }, - Base: "atest", - Display: "test", - Name: "Test Token", - Symbol: "TEST", - URI: "example_uri", - URIHash: "example_uri_hash", - }) - - // (Required for NON-18 denom chains *only) - // Update EVM params to add Extended denom options - // Ensure that this corresponds to the EVM denom - // (tyically the bond denom) - evmParams := app.EVMKeeper.GetParams(sdkCtx) - evmParams.ExtendedDenomOptions = &types.ExtendedDenomOptions{ExtendedDenom: "atest"} - err := app.EVMKeeper.SetParams(sdkCtx, evmParams) - if err != nil { - return nil, err - } - // Initialize EvmCoinInfo in the module store - if err := app.EVMKeeper.InitEvmCoinInfo(sdkCtx); err != nil { - return nil, err - } return app.ModuleManager.RunMigrations(ctx, app.Configurator(), fromVM) }, ) diff --git a/go.mod b/go.mod index ec6781f7..777e52d8 100644 --- a/go.mod +++ b/go.mod @@ -1,172 +1,197 @@ module github.com/cosmos/evm -go 1.23.8 +go 1.25.9 require ( - cosmossdk.io/api v0.9.2 - cosmossdk.io/client/v2 v2.0.0-beta.7 - cosmossdk.io/core v0.11.3 - cosmossdk.io/errors v1.0.2 - cosmossdk.io/log v1.6.1 + cosmossdk.io/api v1.0.0 + cosmossdk.io/core v1.1.0 + cosmossdk.io/errors v1.1.0 + cosmossdk.io/log/v2 v2.1.0 cosmossdk.io/math v1.5.3 - cosmossdk.io/store v1.1.2 cosmossdk.io/tools/confix v0.1.2 - cosmossdk.io/x/evidence v0.2.0 - cosmossdk.io/x/feegrant v0.2.0 - cosmossdk.io/x/tx v0.14.0 - cosmossdk.io/x/upgrade v0.2.0 github.com/btcsuite/btcd v0.24.2 github.com/btcsuite/btcd/btcutil v1.1.6 - github.com/cometbft/cometbft v0.38.18 + github.com/cometbft/cometbft v0.39.3 github.com/cosmos/cosmos-db v1.1.3 github.com/cosmos/cosmos-proto v1.0.0-beta.5 - github.com/cosmos/cosmos-sdk v0.53.4 + github.com/cosmos/cosmos-sdk v0.54.3 + github.com/cosmos/cosmos-sdk/store/v2 v2.0.0 github.com/cosmos/go-bip39 v1.0.0 - github.com/cosmos/gogoproto v1.7.0 - github.com/cosmos/ibc-go/v10 v10.3.1-0.20250909102629-ed3b125c7b6f - github.com/creachadair/tomledit v0.0.28 + github.com/cosmos/gogoproto v1.7.2 + github.com/cosmos/ibc-go/v11 v11.0.0 + github.com/cosmos/ledger-cosmos-go v1.0.0 + github.com/creachadair/tomledit v0.0.29 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc - github.com/ethereum/go-ethereum v1.15.11 + github.com/ethereum/go-ethereum v1.16.8 + github.com/gammazero/deque v1.2.0 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 github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/hashicorp/go-metrics v0.5.4 + github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/holiman/uint256 v1.3.2 github.com/improbable-eng/grpc-web v0.15.0 - github.com/linxGnu/grocksdb v1.9.2 + github.com/linxGnu/grocksdb v1.10.7 github.com/onsi/ginkgo/v2 v2.23.4 github.com/onsi/gomega v1.38.0 github.com/pkg/errors v0.9.1 github.com/rs/cors v1.11.1 - github.com/spf13/cast v1.9.2 - github.com/spf13/cobra v1.10.1 - github.com/spf13/viper v1.20.1 + github.com/spf13/cast v1.10.0 + github.com/spf13/cobra v1.10.2 + github.com/spf13/viper v1.21.0 github.com/stretchr/testify v1.11.1 github.com/tidwall/gjson v1.18.0 github.com/tidwall/sjson v1.2.5 github.com/tyler-smith/go-bip39 v1.1.0 github.com/zondax/hid v0.9.2 - go.uber.org/mock v0.5.2 - golang.org/x/crypto v0.41.0 - golang.org/x/net v0.43.0 - golang.org/x/sync v0.16.0 - golang.org/x/text v0.28.0 - google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 - google.golang.org/grpc v1.75.0 - google.golang.org/protobuf v1.36.8 + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 + go.opentelemetry.io/otel v1.43.0 + go.opentelemetry.io/otel/metric v1.43.0 + go.opentelemetry.io/otel/sdk/metric v1.43.0 + go.opentelemetry.io/otel/trace v1.43.0 + go.uber.org/mock v0.6.0 + golang.org/x/crypto v0.50.0 + golang.org/x/net v0.53.0 + golang.org/x/sync v0.20.0 + golang.org/x/text v0.36.0 + google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 + google.golang.org/grpc v1.80.0 + google.golang.org/protobuf v1.36.11 sigs.k8s.io/yaml v1.6.0 ) require ( - cel.dev/expr v0.24.0 // indirect - cloud.google.com/go v0.116.0 // indirect - cloud.google.com/go/auth v0.14.1 // indirect - cloud.google.com/go/auth/oauth2adapt v0.2.7 // indirect - cloud.google.com/go/compute/metadata v0.7.0 // indirect - cloud.google.com/go/iam v1.2.2 // indirect - cloud.google.com/go/monitoring v1.21.2 // indirect - cloud.google.com/go/storage v1.49.0 // indirect - cosmossdk.io/collections v1.2.1 // indirect + cel.dev/expr v0.25.1 // indirect + cloud.google.com/go v0.123.0 // indirect + cloud.google.com/go/auth v0.20.0 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect + cloud.google.com/go/compute/metadata v0.9.0 // indirect + cloud.google.com/go/iam v1.9.0 // indirect + cloud.google.com/go/monitoring v1.27.0 // indirect + cloud.google.com/go/storage v1.62.1 // indirect + cosmossdk.io/collections v1.4.0 // indirect cosmossdk.io/depinject v1.2.1 // indirect cosmossdk.io/schema v1.1.0 // indirect - filippo.io/edwards25519 v1.1.0 // indirect + filippo.io/edwards25519 v1.2.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // 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/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0 // indirect - github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 // indirect - github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.32.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.56.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.56.0 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/StackExchange/wmi v1.2.1 // indirect - github.com/VictoriaMetrics/fastcache v1.12.2 // indirect - github.com/aws/aws-sdk-go v1.49.0 // indirect + github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260116142910-60249400e523 // indirect + github.com/RoaringBitmap/roaring/v2 v2.18.0 // indirect + github.com/VictoriaMetrics/fastcache v1.13.0 // indirect + github.com/aws/aws-sdk-go-v2 v1.41.6 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.9 // indirect + github.com/aws/aws-sdk-go-v2/config v1.32.14 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.19.14 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.22 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.22 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.23 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.8 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.14 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.22 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.22 // indirect + github.com/aws/aws-sdk-go-v2/service/s3 v1.100.0 // indirect + github.com/aws/aws-sdk-go-v2/service/signin v1.0.9 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.30.15 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.19 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.41.10 // indirect + github.com/aws/smithy-go v1.25.0 // indirect + github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/bgentry/speakeasy v0.2.0 // indirect - github.com/bits-and-blooms/bitset v1.22.0 // indirect - github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/bits-and-blooms/bitset v1.24.4 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.5 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect - github.com/bytedance/sonic v1.14.0 // indirect - github.com/bytedance/sonic/loader v0.3.0 // indirect + github.com/bytedance/gopkg v0.1.4 // indirect + github.com/bytedance/sonic v1.15.0 // indirect + github.com/bytedance/sonic/loader v0.5.1 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cenkalti/backoff/v5 v5.0.3 // indirect github.com/cespare/xxhash/v2 v2.3.0 // 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 - 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/cloudwego/base64x v0.1.6 // indirect + github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 // indirect + github.com/cockroachdb/errors v1.13.0 // indirect + github.com/cockroachdb/fifo v0.0.0-20240816210425-c5d0cb0b6fc0 // 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 - github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect - github.com/cometbft/cometbft-db v0.14.1 // indirect - github.com/consensys/gnark-crypto v0.18.0 // indirect + github.com/cockroachdb/redact v1.1.8 // indirect + github.com/cockroachdb/tokenbucket v0.0.0-20250429170803-42689b6311bb // indirect + github.com/cometbft/cometbft-db v1.0.4 // indirect + github.com/consensys/gnark-crypto v0.18.1 // indirect github.com/cosmos/btcutil v1.0.5 // indirect + github.com/cosmos/btree v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect - github.com/cosmos/iavl v1.2.2 // indirect + github.com/cosmos/iavl v1.2.8 // 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/creachadair/atomicfile v0.3.7 // indirect - github.com/danieljoos/wincred v1.2.1 // indirect + github.com/crate-crypto/go-eth-kzg v1.5.0 // indirect + github.com/creachadair/atomicfile v0.3.8 // indirect + github.com/danieljoos/wincred v1.2.3 // indirect + github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.1 // indirect github.com/desertbit/timer v1.0.1 // indirect - github.com/dgraph-io/badger/v4 v4.2.0 // indirect - github.com/dgraph-io/ristretto v0.1.1 // indirect + github.com/dgraph-io/badger/v4 v4.9.1 // indirect + github.com/dgraph-io/ristretto/v2 v2.4.0 // indirect + github.com/dunglas/httpsfv v1.1.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect - github.com/dvsekhvalnov/jose2go v1.7.0 // indirect - github.com/emicklei/dot v1.6.2 // indirect - github.com/envoyproxy/go-control-plane/envoy v1.32.4 // indirect - github.com/envoyproxy/protoc-gen-validate v1.2.1 // 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.17.0 // indirect + github.com/dvsekhvalnov/jose2go v1.8.0 // indirect + github.com/ebitengine/purego v0.10.0 // indirect + github.com/emicklei/dot v1.11.0 // indirect + github.com/envoyproxy/go-control-plane/envoy v1.37.0 // indirect + github.com/envoyproxy/protoc-gen-validate v1.3.3 // indirect + github.com/ethereum/c-kzg-4844/v2 v2.1.6 // indirect + github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab // indirect + github.com/fatih/color v1.18.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/ferranbt/fastssz v0.1.4 // indirect + github.com/flynn/noise v1.1.0 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect - github.com/getsentry/sentry-go v0.32.0 // indirect - github.com/go-jose/go-jose/v4 v4.1.1 // indirect + github.com/getsentry/sentry-go v0.46.0 // indirect + github.com/go-jose/go-jose/v4 v4.1.4 // indirect github.com/go-kit/kit v0.13.0 // indirect github.com/go-kit/log v0.2.1 // indirect - github.com/go-logfmt/logfmt v0.6.0 // indirect + github.com/go-logfmt/logfmt v0.6.1 // 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-task/slim-sprig/v3 v3.0.0 // indirect - github.com/go-viper/mapstructure/v2 v2.2.1 // indirect + github.com/go-viper/mapstructure/v2 v2.5.0 // indirect 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/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 + github.com/golang/snappy v1.0.0 // indirect github.com/google/btree v1.1.3 // indirect - github.com/google/flatbuffers v24.3.25+incompatible // indirect + github.com/google/flatbuffers v25.2.10+incompatible // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/orderedcode v0.0.1 // indirect github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect github.com/google/s2a-go v0.1.9 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect - github.com/googleapis/gax-go/v2 v2.14.1 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.14 // indirect + github.com/googleapis/gax-go/v2 v2.22.0 // indirect github.com/gorilla/handlers v1.5.2 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect + github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.72 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-getter v1.7.8 // indirect + github.com/hashicorp/go-getter v1.8.6 // indirect github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect - github.com/hashicorp/go-plugin v1.6.3 // indirect - github.com/hashicorp/go-safetemp v1.0.0 // indirect - github.com/hashicorp/go-version v1.6.0 // indirect + github.com/hashicorp/go-plugin v1.7.0 // indirect + github.com/hashicorp/go-version v1.9.0 // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect - github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hashicorp/yamux v0.1.2 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect @@ -174,96 +199,167 @@ require ( github.com/huin/goupnp v1.3.0 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/ipfs/go-cid v0.5.0 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect - github.com/jmespath/go-jmespath v0.4.0 // indirect + github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect - github.com/klauspost/compress v1.18.0 // indirect - github.com/klauspost/cpuid/v2 v2.2.10 // indirect + github.com/klauspost/compress v1.18.5 // indirect + github.com/klauspost/cpuid/v2 v2.3.0 // indirect + github.com/koron/go-ssdp v0.0.6 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect - github.com/lib/pq v1.10.9 // indirect + github.com/lib/pq v1.12.3 // indirect + github.com/libp2p/go-buffer-pool v0.1.0 // indirect + github.com/libp2p/go-flow-metrics v0.2.0 // indirect + github.com/libp2p/go-libp2p v0.47.0 // indirect + github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect + github.com/libp2p/go-msgio v0.3.0 // indirect + github.com/libp2p/go-netroute v0.3.0 // indirect + github.com/libp2p/go-reuseport v0.4.0 // indirect + github.com/libp2p/go-yamux/v5 v5.0.1 // indirect + github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e // indirect github.com/manifoldco/promptui v0.9.0 // indirect + github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect github.com/mattn/go-colorable v0.1.14 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-isatty v0.0.22 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/mdp/qrterminal/v3 v3.2.1 // indirect - github.com/minio/highwayhash v1.0.3 // indirect - github.com/minio/sha256-simd v1.0.0 // indirect + github.com/miekg/dns v1.1.66 // indirect + github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect + github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect + github.com/minio/highwayhash v1.0.4 // indirect + github.com/minio/sha256-simd v1.0.1 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/mr-tron/base58 v1.3.0 // indirect + github.com/mschoch/smat v0.2.0 // indirect github.com/mtibben/percent v0.2.1 // indirect + github.com/multiformats/go-base32 v0.1.0 // indirect + github.com/multiformats/go-base36 v0.2.0 // indirect + github.com/multiformats/go-multiaddr v0.16.1 // indirect + github.com/multiformats/go-multiaddr-dns v0.4.1 // indirect + github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect + github.com/multiformats/go-multibase v0.2.0 // indirect + github.com/multiformats/go-multicodec v0.9.1 // indirect + github.com/multiformats/go-multihash v0.2.3 // indirect + github.com/multiformats/go-multistream v0.6.1 // indirect + github.com/multiformats/go-varint v0.0.7 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a // indirect - github.com/oklog/run v1.1.0 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/oasisprotocol/curve25519-voi v0.0.0-20251114093237-2ab5a27a1729 // indirect + github.com/oklog/run v1.2.0 // indirect + github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect - github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect - github.com/pion/dtls/v2 v2.2.7 // indirect - github.com/pion/logging v0.2.2 // indirect + github.com/petermattis/goid v0.0.0-20260113132338-7c7de50cc741 // indirect + github.com/pion/datachannel v1.5.10 // indirect + github.com/pion/dtls/v2 v2.2.12 // indirect + github.com/pion/dtls/v3 v3.1.2 // indirect + github.com/pion/ice/v4 v4.0.10 // indirect + github.com/pion/interceptor v0.1.40 // indirect + github.com/pion/logging v0.2.4 // indirect + github.com/pion/mdns/v2 v2.0.7 // indirect + github.com/pion/randutil v0.1.0 // indirect + github.com/pion/rtcp v1.2.15 // indirect + github.com/pion/rtp v1.8.19 // indirect + github.com/pion/sctp v1.8.39 // indirect + github.com/pion/sdp/v3 v3.0.13 // indirect + github.com/pion/srtp/v3 v3.0.6 // indirect + github.com/pion/stun v0.6.1 // indirect github.com/pion/stun/v2 v2.0.0 // indirect - github.com/pion/transport/v2 v2.2.1 // indirect - github.com/pion/transport/v3 v3.0.1 // indirect + github.com/pion/stun/v3 v3.0.0 // indirect + github.com/pion/transport/v2 v2.2.10 // indirect + github.com/pion/transport/v3 v3.0.7 // indirect + github.com/pion/transport/v4 v4.0.1 // indirect + github.com/pion/turn/v4 v4.0.2 // indirect + github.com/pion/webrtc/v4 v4.1.2 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.22.0 // indirect - github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.63.0 // indirect - github.com/prometheus/procfs v0.15.1 // indirect - github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect - github.com/rivo/uniseg v0.2.0 // indirect + github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect + github.com/prometheus/client_golang v1.23.2 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/common v0.67.5 // indirect + github.com/prometheus/procfs v0.20.1 // indirect + github.com/quic-go/qpack v0.6.0 // indirect + github.com/quic-go/quic-go v0.59.0 // indirect + github.com/quic-go/webtransport-go v0.10.0 // indirect + github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect - 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/pflag v1.0.9 // indirect - github.com/spiffe/go-spiffe/v2 v2.5.0 // indirect - github.com/stretchr/objx v0.5.2 // indirect + github.com/rs/zerolog v1.35.0 // indirect + github.com/sagikazarmark/locafero v0.12.0 // indirect + github.com/sasha-s/go-deadlock v0.3.9 // indirect + github.com/shirou/gopsutil v3.21.11+incompatible // indirect + github.com/shirou/gopsutil/v4 v4.26.4 // indirect + github.com/spaolacci/murmur3 v1.1.0 // indirect + github.com/spf13/afero v1.15.0 // indirect + github.com/spf13/pflag v1.0.10 // indirect + github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect + github.com/stretchr/objx v0.5.3 // indirect github.com/subosito/gotenv v1.6.0 // indirect - github.com/supranational/blst v0.3.14 // indirect + github.com/supranational/blst v0.3.16 // 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/match v1.1.1 // indirect - github.com/tidwall/pretty v1.2.0 // indirect - github.com/tklauser/go-sysconf v0.3.12 // indirect - github.com/tklauser/numcpus v0.6.1 // indirect + github.com/tidwall/btree v1.8.1 // indirect + github.com/tidwall/match v1.2.0 // indirect + github.com/tidwall/pretty v1.2.1 // indirect + github.com/tklauser/go-sysconf v0.3.16 // indirect + github.com/tklauser/numcpus v0.11.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect - github.com/ulikunitz/xz v0.5.11 // 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 - go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/contrib/detectors/gcp v1.36.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect - go.opentelemetry.io/otel v1.37.0 // indirect - go.opentelemetry.io/otel/metric v1.37.0 // indirect - go.opentelemetry.io/otel/sdk v1.37.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.37.0 // indirect - go.opentelemetry.io/otel/trace v1.37.0 // indirect + github.com/ulikunitz/xz v0.5.15 // indirect + github.com/wlynxg/anet v0.0.5 // indirect + github.com/yusufpapurcu/wmi v1.2.4 // indirect + github.com/zondax/golem v0.27.0 // indirect + github.com/zondax/ledger-go v1.0.1 // indirect + go.etcd.io/bbolt v1.4.3 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/contrib/bridges/otelslog v0.18.0 // indirect + go.opentelemetry.io/contrib/detectors/gcp v1.43.0 // indirect + go.opentelemetry.io/contrib/instrumentation/host v0.68.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 // indirect + go.opentelemetry.io/contrib/instrumentation/runtime v0.68.0 // indirect + go.opentelemetry.io/contrib/otelconf v0.23.0 // indirect + go.opentelemetry.io/contrib/propagators/autoprop v0.68.0 // indirect + go.opentelemetry.io/contrib/propagators/aws v1.43.0 // indirect + go.opentelemetry.io/contrib/propagators/b3 v1.43.0 // indirect + go.opentelemetry.io/contrib/propagators/jaeger v1.43.0 // indirect + go.opentelemetry.io/contrib/propagators/ot v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.19.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.19.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.43.0 // indirect + go.opentelemetry.io/otel/log v0.19.0 // indirect + go.opentelemetry.io/otel/sdk v1.43.0 // indirect + go.opentelemetry.io/otel/sdk/log v0.19.0 // indirect + go.opentelemetry.io/proto/otlp v1.10.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect + go.uber.org/dig v1.19.0 // indirect + go.uber.org/fx v1.24.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/exp v0.0.0-20250305212735-054e65f0b394 // 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 - golang.org/x/time v0.10.0 // indirect - golang.org/x/tools v0.35.0 // indirect - google.golang.org/api v0.222.0 // indirect - google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 // indirect + go.uber.org/zap v1.27.1 // indirect + go.yaml.in/yaml/v2 v2.4.4 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect + golang.org/x/arch v0.26.0 // indirect + golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90 // indirect + golang.org/x/mod v0.34.0 // indirect + golang.org/x/oauth2 v0.36.0 // indirect + golang.org/x/sys v0.43.0 // indirect + golang.org/x/telemetry v0.0.0-20260311193753-579e4da9a98c // indirect + golang.org/x/term v0.42.0 // indirect + golang.org/x/time v0.15.0 // indirect + golang.org/x/tools v0.43.0 // indirect + google.golang.org/api v0.276.0 // indirect + google.golang.org/genproto v0.0.0-20260414002931-afd174a4e478 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.2 // indirect - nhooyr.io/websocket v1.8.11 // indirect - pgregory.net/rapid v1.2.0 // indirect + lukechampine.com/blake3 v1.4.1 // indirect + nhooyr.io/websocket v1.8.17 // indirect + pgregory.net/rapid v1.3.0 // indirect rsc.io/qr v0.2.0 // indirect ) @@ -271,12 +367,14 @@ replace ( // use cosmos fork of keyring 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 v1.16.2-cosmos-1 + // branch: release/1.17 + github.com/ethereum/go-ethereum => github.com/cosmos/go-ethereum v1.17.2-cosmos-0 // 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 github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 + // use btree fork for bstm + github.com/tidwall/btree => github.com/cosmos/btree v0.0.0-20250924232609-2c6195d95951 ) retract v0.4.0 diff --git a/go.sum b/go.sum index 2ecc636b..11f8f59c 100644 --- a/go.sum +++ b/go.sum @@ -1,658 +1,52 @@ -cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY= -cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw= +cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4= +cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= 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.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= -cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= -cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= -cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= -cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= -cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= -cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= -cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= -cloud.google.com/go v0.100.1/go.mod h1:fs4QogzfH5n2pBXBP9vRiU+eCny7lD2vmFZy79Iuw1U= -cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= -cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= -cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= -cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= -cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= -cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= -cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= -cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= -cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= -cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= -cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= -cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= -cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o= -cloud.google.com/go/accesscontextmanager v1.4.0/go.mod h1:/Kjh7BBu/Gh83sv+K60vN9QE5NJcd80sU33vIe2IFPE= -cloud.google.com/go/accesscontextmanager v1.6.0/go.mod h1:8XCvZWfYw3K/ji0iVnp+6pu7huxoQTLmxAbVjbloTtM= -cloud.google.com/go/accesscontextmanager v1.7.0/go.mod h1:CEGLewx8dwa33aDAZQujl7Dx+uYhS0eay198wB/VumQ= -cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= -cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= -cloud.google.com/go/aiplatform v1.27.0/go.mod h1:Bvxqtl40l0WImSb04d0hXFU7gDOiq9jQmorivIiWcKg= -cloud.google.com/go/aiplatform v1.35.0/go.mod h1:7MFT/vCaOyZT/4IIFfxH4ErVg/4ku6lKv3w0+tFTgXQ= -cloud.google.com/go/aiplatform v1.36.1/go.mod h1:WTm12vJRPARNvJ+v6P52RDHCNe4AhvjcIZ/9/RRHy/k= -cloud.google.com/go/aiplatform v1.37.0/go.mod h1:IU2Cv29Lv9oCn/9LkFiiuKfwrRTq+QQMbW+hPCxJGZw= -cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= -cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= -cloud.google.com/go/analytics v0.17.0/go.mod h1:WXFa3WSym4IZ+JiKmavYdJwGG/CvpqiqczmL59bTD9M= -cloud.google.com/go/analytics v0.18.0/go.mod h1:ZkeHGQlcIPkw0R/GW+boWHhCOR43xz9RN/jn7WcqfIE= -cloud.google.com/go/analytics v0.19.0/go.mod h1:k8liqf5/HCnOUkbawNtrWWc+UAzyDlW89doe8TtoDsE= -cloud.google.com/go/apigateway v1.3.0/go.mod h1:89Z8Bhpmxu6AmUxuVRg/ECRGReEdiP3vQtk4Z1J9rJk= -cloud.google.com/go/apigateway v1.4.0/go.mod h1:pHVY9MKGaH9PQ3pJ4YLzoj6U5FUDeDFBllIz7WmzJoc= -cloud.google.com/go/apigateway v1.5.0/go.mod h1:GpnZR3Q4rR7LVu5951qfXPJCHquZt02jf7xQx7kpqN8= -cloud.google.com/go/apigeeconnect v1.3.0/go.mod h1:G/AwXFAKo0gIXkPTVfZDd2qA1TxBXJ3MgMRBQkIi9jc= -cloud.google.com/go/apigeeconnect v1.4.0/go.mod h1:kV4NwOKqjvt2JYR0AoIWo2QGfoRtn/pkS3QlHp0Ni04= -cloud.google.com/go/apigeeconnect v1.5.0/go.mod h1:KFaCqvBRU6idyhSNyn3vlHXc8VMDJdRmwDF6JyFRqZ8= -cloud.google.com/go/apigeeregistry v0.4.0/go.mod h1:EUG4PGcsZvxOXAdyEghIdXwAEi/4MEaoqLMLDMIwKXY= -cloud.google.com/go/apigeeregistry v0.5.0/go.mod h1:YR5+s0BVNZfVOUkMa5pAR2xGd0A473vA5M7j247o1wM= -cloud.google.com/go/apigeeregistry v0.6.0/go.mod h1:BFNzW7yQVLZ3yj0TKcwzb8n25CFBri51GVGOEUcgQsc= -cloud.google.com/go/apikeys v0.4.0/go.mod h1:XATS/yqZbaBK0HOssf+ALHp8jAlNHUgyfprvNcBIszU= -cloud.google.com/go/apikeys v0.5.0/go.mod h1:5aQfwY4D+ewMMWScd3hm2en3hCj+BROlyrt3ytS7KLI= -cloud.google.com/go/apikeys v0.6.0/go.mod h1:kbpXu5upyiAlGkKrJgQl8A0rKNNJ7dQ377pdroRSSi8= -cloud.google.com/go/appengine v1.4.0/go.mod h1:CS2NhuBuDXM9f+qscZ6V86m1MIIqPj3WC/UoEuR1Sno= -cloud.google.com/go/appengine v1.5.0/go.mod h1:TfasSozdkFI0zeoxW3PTBLiNqRmzraodCWatWI9Dmak= -cloud.google.com/go/appengine v1.6.0/go.mod h1:hg6i0J/BD2cKmDJbaFSYHFyZkgBEfQrDg/X0V5fJn84= -cloud.google.com/go/appengine v1.7.0/go.mod h1:eZqpbHFCqRGa2aCdope7eC0SWLV1j0neb/QnMJVWx6A= -cloud.google.com/go/appengine v1.7.1/go.mod h1:IHLToyb/3fKutRysUlFO0BPt5j7RiQ45nrzEJmKTo6E= -cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4= -cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0= -cloud.google.com/go/area120 v0.7.0/go.mod h1:a3+8EUD1SX5RUcCs3MY5YasiO1z6yLiNLRiFrykbynY= -cloud.google.com/go/area120 v0.7.1/go.mod h1:j84i4E1RboTWjKtZVWXPqvK5VHQFJRF2c1Nm69pWm9k= -cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ= -cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk= -cloud.google.com/go/artifactregistry v1.8.0/go.mod h1:w3GQXkJX8hiKN0v+at4b0qotwijQbYUqF2GWkZzAhC0= -cloud.google.com/go/artifactregistry v1.9.0/go.mod h1:2K2RqvA2CYvAeARHRkLDhMDJ3OXy26h3XW+3/Jh2uYc= -cloud.google.com/go/artifactregistry v1.11.1/go.mod h1:lLYghw+Itq9SONbCa1YWBoWs1nOucMH0pwXN1rOBZFI= -cloud.google.com/go/artifactregistry v1.11.2/go.mod h1:nLZns771ZGAwVLzTX/7Al6R9ehma4WUEhZGWV6CeQNQ= -cloud.google.com/go/artifactregistry v1.12.0/go.mod h1:o6P3MIvtzTOnmvGagO9v/rOjjA0HmhJ+/6KAXrmYDCI= -cloud.google.com/go/artifactregistry v1.13.0/go.mod h1:uy/LNfoOIivepGhooAUpL1i30Hgee3Cu0l4VTWHUC08= -cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o= -cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s= -cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0= -cloud.google.com/go/asset v1.9.0/go.mod h1:83MOE6jEJBMqFKadM9NLRcs80Gdw76qGuHn8m3h8oHQ= -cloud.google.com/go/asset v1.10.0/go.mod h1:pLz7uokL80qKhzKr4xXGvBQXnzHn5evJAEAtZiIb0wY= -cloud.google.com/go/asset v1.11.1/go.mod h1:fSwLhbRvC9p9CXQHJ3BgFeQNM4c9x10lqlrdEUYXlJo= -cloud.google.com/go/asset v1.12.0/go.mod h1:h9/sFOa4eDIyKmH6QMpm4eUK3pDojWnUhTgJlk762Hg= -cloud.google.com/go/asset v1.13.0/go.mod h1:WQAMyYek/b7NBpYq/K4KJWcRqzoalEsxz/t/dTk4THw= -cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY= -cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw= -cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI= -cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEarXQk6WEKkxYfL6kGIo= -cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0= -cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E= -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/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= -cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= -cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8= -cloud.google.com/go/automl v1.8.0/go.mod h1:xWx7G/aPEe/NP+qzYXktoBSDfjO+vnKMGgsApGJJquM= -cloud.google.com/go/automl v1.12.0/go.mod h1:tWDcHDp86aMIuHmyvjuKeeHEGq76lD7ZqfGLN6B0NuU= -cloud.google.com/go/baremetalsolution v0.3.0/go.mod h1:XOrocE+pvK1xFfleEnShBlNAXf+j5blPPxrhjKgnIFc= -cloud.google.com/go/baremetalsolution v0.4.0/go.mod h1:BymplhAadOO/eBa7KewQ0Ppg4A4Wplbn+PsFKRLo0uI= -cloud.google.com/go/baremetalsolution v0.5.0/go.mod h1:dXGxEkmR9BMwxhzBhV0AioD0ULBmuLZI8CdwalUxuss= -cloud.google.com/go/batch v0.3.0/go.mod h1:TR18ZoAekj1GuirsUsR1ZTKN3FC/4UDnScjT8NXImFE= -cloud.google.com/go/batch v0.4.0/go.mod h1:WZkHnP43R/QCGQsZ+0JyG4i79ranE2u8xvjq/9+STPE= -cloud.google.com/go/batch v0.7.0/go.mod h1:vLZN95s6teRUqRQ4s3RLDsH8PvboqBK+rn1oevL159g= -cloud.google.com/go/beyondcorp v0.2.0/go.mod h1:TB7Bd+EEtcw9PCPQhCJtJGjk/7TC6ckmnSFS+xwTfm4= -cloud.google.com/go/beyondcorp v0.3.0/go.mod h1:E5U5lcrcXMsCuoDNyGrpyTm/hn7ne941Jz2vmksAxW8= -cloud.google.com/go/beyondcorp v0.4.0/go.mod h1:3ApA0mbhHx6YImmuubf5pyW8srKnCEPON32/5hj+RmM= -cloud.google.com/go/beyondcorp v0.5.0/go.mod h1:uFqj9X+dSfrheVp7ssLTaRHd2EHqSL4QZmH4e8WXGGU= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA= -cloud.google.com/go/bigquery v1.43.0/go.mod h1:ZMQcXHsl+xmU1z36G2jNGZmKp9zNY5BUua5wDgmNCfw= -cloud.google.com/go/bigquery v1.44.0/go.mod h1:0Y33VqXTEsbamHJvJHdFmtqHvMIY28aK1+dFsvaChGc= -cloud.google.com/go/bigquery v1.47.0/go.mod h1:sA9XOgy0A8vQK9+MWhEQTY6Tix87M/ZurWFIxmF9I/E= -cloud.google.com/go/bigquery v1.48.0/go.mod h1:QAwSz+ipNgfL5jxiaK7weyOhzdoAy1zFm0Nf1fysJac= -cloud.google.com/go/bigquery v1.49.0/go.mod h1:Sv8hMmTFFYBlt/ftw2uN6dFdQPzBlREY9yBh7Oy7/4Q= -cloud.google.com/go/bigquery v1.50.0/go.mod h1:YrleYEh2pSEbgTBZYMJ5SuSr0ML3ypjRB1zgf7pvQLU= -cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY= -cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= -cloud.google.com/go/billing v1.6.0/go.mod h1:WoXzguj+BeHXPbKfNWkqVtDdzORazmCjraY+vrxcyvI= -cloud.google.com/go/billing v1.7.0/go.mod h1:q457N3Hbj9lYwwRbnlD7vUpyjq6u5U1RAOArInEiD5Y= -cloud.google.com/go/billing v1.12.0/go.mod h1:yKrZio/eu+okO/2McZEbch17O5CB5NpZhhXG6Z766ss= -cloud.google.com/go/billing v1.13.0/go.mod h1:7kB2W9Xf98hP9Sr12KfECgfGclsH3CQR0R08tnRlRbc= -cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM= -cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI= -cloud.google.com/go/binaryauthorization v1.3.0/go.mod h1:lRZbKgjDIIQvzYQS1p99A7/U1JqvqeZg0wiI5tp6tg0= -cloud.google.com/go/binaryauthorization v1.4.0/go.mod h1:tsSPQrBd77VLplV70GUhBf/Zm3FsKmgSqgm4UmiDItk= -cloud.google.com/go/binaryauthorization v1.5.0/go.mod h1:OSe4OU1nN/VswXKRBmciKpo9LulY41gch5c68htf3/Q= -cloud.google.com/go/certificatemanager v1.3.0/go.mod h1:n6twGDvcUBFu9uBgt4eYvvf3sQ6My8jADcOVwHmzadg= -cloud.google.com/go/certificatemanager v1.4.0/go.mod h1:vowpercVFyqs8ABSmrdV+GiFf2H/ch3KyudYQEMM590= -cloud.google.com/go/certificatemanager v1.6.0/go.mod h1:3Hh64rCKjRAX8dXgRAyOcY5vQ/fE1sh8o+Mdd6KPgY8= -cloud.google.com/go/channel v1.8.0/go.mod h1:W5SwCXDJsq/rg3tn3oG0LOxpAo6IMxNa09ngphpSlnk= -cloud.google.com/go/channel v1.9.0/go.mod h1:jcu05W0my9Vx4mt3/rEHpfxc9eKi9XwsdDL8yBMbKUk= -cloud.google.com/go/channel v1.11.0/go.mod h1:IdtI0uWGqhEeatSB62VOoJ8FSUhJ9/+iGkJVqp74CGE= -cloud.google.com/go/channel v1.12.0/go.mod h1:VkxCGKASi4Cq7TbXxlaBezonAYpp1GCnKMY6tnMQnLU= -cloud.google.com/go/cloudbuild v1.3.0/go.mod h1:WequR4ULxlqvMsjDEEEFnOG5ZSRSgWOywXYDb1vPE6U= -cloud.google.com/go/cloudbuild v1.4.0/go.mod h1:5Qwa40LHiOXmz3386FrjrYM93rM/hdRr7b53sySrTqA= -cloud.google.com/go/cloudbuild v1.6.0/go.mod h1:UIbc/w9QCbH12xX+ezUsgblrWv+Cv4Tw83GiSMHOn9M= -cloud.google.com/go/cloudbuild v1.7.0/go.mod h1:zb5tWh2XI6lR9zQmsm1VRA+7OCuve5d8S+zJUul8KTg= -cloud.google.com/go/cloudbuild v1.9.0/go.mod h1:qK1d7s4QlO0VwfYn5YuClDGg2hfmLZEb4wQGAbIgL1s= -cloud.google.com/go/clouddms v1.3.0/go.mod h1:oK6XsCDdW4Ib3jCCBugx+gVjevp2TMXFtgxvPSee3OM= -cloud.google.com/go/clouddms v1.4.0/go.mod h1:Eh7sUGCC+aKry14O1NRljhjyrr0NFC0G2cjwX0cByRk= -cloud.google.com/go/clouddms v1.5.0/go.mod h1:QSxQnhikCLUw13iAbffF2CZxAER3xDGNHjsTAkQJcQA= -cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY= -cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI= -cloud.google.com/go/cloudtasks v1.7.0/go.mod h1:ImsfdYWwlWNJbdgPIIGJWC+gemEGTBK/SunNQQNCAb4= -cloud.google.com/go/cloudtasks v1.8.0/go.mod h1:gQXUIwCSOI4yPVK7DgTVFiiP0ZW/eQkydWzwVMdHxrI= -cloud.google.com/go/cloudtasks v1.9.0/go.mod h1:w+EyLsVkLWHcOaqNEyvcKAsWp9p29dL6uL9Nst1cI7Y= -cloud.google.com/go/cloudtasks v1.10.0/go.mod h1:NDSoTLkZ3+vExFEWu2UJV1arUyzVDAiZtdWcsUyNwBs= -cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= -cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= -cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= -cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= -cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= -cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= -cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= -cloud.google.com/go/compute v1.12.0/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= -cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= -cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE= -cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= -cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= -cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= -cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= -cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= -cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= -cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= -cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= -cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -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/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= -cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= -cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= -cloud.google.com/go/container v1.6.0/go.mod h1:Xazp7GjJSeUYo688S+6J5V+n/t+G5sKBTFkKNudGRxg= -cloud.google.com/go/container v1.7.0/go.mod h1:Dp5AHtmothHGX3DwwIHPgq45Y8KmNsgN3amoYfxVkLo= -cloud.google.com/go/container v1.13.1/go.mod h1:6wgbMPeQRw9rSnKBCAJXnds3Pzj03C4JHamr8asWKy4= -cloud.google.com/go/container v1.14.0/go.mod h1:3AoJMPhHfLDxLvrlVWaK57IXzaPnLaZq63WX59aQBfM= -cloud.google.com/go/container v1.15.0/go.mod h1:ft+9S0WGjAyjDggg5S06DXj+fHJICWg8L7isCQe9pQA= -cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= -cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= -cloud.google.com/go/containeranalysis v0.7.0/go.mod h1:9aUL+/vZ55P2CXfuZjS4UjQ9AgXoSw8Ts6lemfmxBxI= -cloud.google.com/go/containeranalysis v0.9.0/go.mod h1:orbOANbwk5Ejoom+s+DUCTTJ7IBdBQJDcSylAx/on9s= -cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= -cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs= -cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc= -cloud.google.com/go/datacatalog v1.7.0/go.mod h1:9mEl4AuDYWw81UGc41HonIHH7/sn52H0/tc8f8ZbZIE= -cloud.google.com/go/datacatalog v1.8.0/go.mod h1:KYuoVOv9BM8EYz/4eMFxrr4DUKhGIOXxZoKYF5wdISM= -cloud.google.com/go/datacatalog v1.8.1/go.mod h1:RJ58z4rMp3gvETA465Vg+ag8BGgBdnRPEMMSTr5Uv+M= -cloud.google.com/go/datacatalog v1.12.0/go.mod h1:CWae8rFkfp6LzLumKOnmVh4+Zle4A3NXLzVJ1d1mRm0= -cloud.google.com/go/datacatalog v1.13.0/go.mod h1:E4Rj9a5ZtAxcQJlEBTLgMTphfP11/lNaAshpoBgemX8= -cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM= -cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ= -cloud.google.com/go/dataflow v0.8.0/go.mod h1:Rcf5YgTKPtQyYz8bLYhFoIV/vP39eL7fWNcSOyFfLJE= -cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo= -cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE= -cloud.google.com/go/dataform v0.5.0/go.mod h1:GFUYRe8IBa2hcomWplodVmUx/iTL0FrsauObOM3Ipr0= -cloud.google.com/go/dataform v0.6.0/go.mod h1:QPflImQy33e29VuapFdf19oPbE4aYTJxr31OAPV+ulA= -cloud.google.com/go/dataform v0.7.0/go.mod h1:7NulqnVozfHvWUBpMDfKMUESr+85aJsC/2O0o3jWPDE= -cloud.google.com/go/datafusion v1.4.0/go.mod h1:1Zb6VN+W6ALo85cXnM1IKiPw+yQMKMhB9TsTSRDo/38= -cloud.google.com/go/datafusion v1.5.0/go.mod h1:Kz+l1FGHB0J+4XF2fud96WMmRiq/wj8N9u007vyXZ2w= -cloud.google.com/go/datafusion v1.6.0/go.mod h1:WBsMF8F1RhSXvVM8rCV3AeyWVxcC2xY6vith3iw3S+8= -cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I= -cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ= -cloud.google.com/go/datalabeling v0.7.0/go.mod h1:WPQb1y08RJbmpM3ww0CSUAGweL0SxByuW2E+FU+wXcM= -cloud.google.com/go/dataplex v1.3.0/go.mod h1:hQuRtDg+fCiFgC8j0zV222HvzFQdRd+SVX8gdmFcZzA= -cloud.google.com/go/dataplex v1.4.0/go.mod h1:X51GfLXEMVJ6UN47ESVqvlsRplbLhcsAt0kZCCKsU0A= -cloud.google.com/go/dataplex v1.5.2/go.mod h1:cVMgQHsmfRoI5KFYq4JtIBEUbYwc3c7tXmIDhRmNNVQ= -cloud.google.com/go/dataplex v1.6.0/go.mod h1:bMsomC/aEJOSpHXdFKFGQ1b0TDPIeL28nJObeO1ppRs= -cloud.google.com/go/dataproc v1.7.0/go.mod h1:CKAlMjII9H90RXaMpSxQ8EU6dQx6iAYNPcYPOkSbi8s= -cloud.google.com/go/dataproc v1.8.0/go.mod h1:5OW+zNAH0pMpw14JVrPONsxMQYMBqJuzORhIBfBn9uI= -cloud.google.com/go/dataproc v1.12.0/go.mod h1:zrF3aX0uV3ikkMz6z4uBbIKyhRITnxvr4i3IjKsKrw4= -cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo= -cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA= -cloud.google.com/go/dataqna v0.7.0/go.mod h1:Lx9OcIIeqCrw1a6KdO3/5KMP1wAmTc0slZWwP12Qq3c= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/datastore v1.10.0/go.mod h1:PC5UzAmDEkAmkfaknstTYbNpgE49HAgW2J1gcgUfmdM= -cloud.google.com/go/datastore v1.11.0/go.mod h1:TvGxBIHCS50u8jzG+AW/ppf87v1of8nwzFNgEZU1D3c= -cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo= -cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ= -cloud.google.com/go/datastream v1.4.0/go.mod h1:h9dpzScPhDTs5noEMQVWP8Wx8AFBRyS0s8KWPx/9r0g= -cloud.google.com/go/datastream v1.5.0/go.mod h1:6TZMMNPwjUqZHBKPQ1wwXpb0d5VDVPl2/XoS5yi88q4= -cloud.google.com/go/datastream v1.6.0/go.mod h1:6LQSuswqLa7S4rPAOZFVjHIG3wJIjZcZrw8JDEDJuIs= -cloud.google.com/go/datastream v1.7.0/go.mod h1:uxVRMm2elUSPuh65IbZpzJNMbuzkcvu5CjMqVIUHrww= -cloud.google.com/go/deploy v1.4.0/go.mod h1:5Xghikd4VrmMLNaF6FiRFDlHb59VM59YoDQnOUdsH/c= -cloud.google.com/go/deploy v1.5.0/go.mod h1:ffgdD0B89tToyW/U/D2eL0jN2+IEV/3EMuXHA0l4r+s= -cloud.google.com/go/deploy v1.6.0/go.mod h1:f9PTHehG/DjCom3QH0cntOVRm93uGBDt2vKzAPwpXQI= -cloud.google.com/go/deploy v1.8.0/go.mod h1:z3myEJnA/2wnB4sgjqdMfgxCA0EqC3RBTNcVPs93mtQ= -cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4= -cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0= -cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8= -cloud.google.com/go/dialogflow v1.18.0/go.mod h1:trO7Zu5YdyEuR+BhSNOqJezyFQ3aUzz0njv7sMx/iek= -cloud.google.com/go/dialogflow v1.19.0/go.mod h1:JVmlG1TwykZDtxtTXujec4tQ+D8SBFMoosgy+6Gn0s0= -cloud.google.com/go/dialogflow v1.29.0/go.mod h1:b+2bzMe+k1s9V+F2jbJwpHPzrnIyHihAdRFMtn2WXuM= -cloud.google.com/go/dialogflow v1.31.0/go.mod h1:cuoUccuL1Z+HADhyIA7dci3N5zUssgpBJmCzI6fNRB4= -cloud.google.com/go/dialogflow v1.32.0/go.mod h1:jG9TRJl8CKrDhMEcvfcfFkkpp8ZhgPz3sBGmAUYJ2qE= -cloud.google.com/go/dlp v1.6.0/go.mod h1:9eyB2xIhpU0sVwUixfBubDoRwP+GjeUoxxeueZmqvmM= -cloud.google.com/go/dlp v1.7.0/go.mod h1:68ak9vCiMBjbasxeVD17hVPxDEck+ExiHavX8kiHG+Q= -cloud.google.com/go/dlp v1.9.0/go.mod h1:qdgmqgTyReTz5/YNSSuueR8pl7hO0o9bQ39ZhtgkWp4= -cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU= -cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU= -cloud.google.com/go/documentai v1.9.0/go.mod h1:FS5485S8R00U10GhgBC0aNGrJxBP8ZVpEeJ7PQDZd6k= -cloud.google.com/go/documentai v1.10.0/go.mod h1:vod47hKQIPeCfN2QS/jULIvQTugbmdc0ZvxxfQY1bg4= -cloud.google.com/go/documentai v1.16.0/go.mod h1:o0o0DLTEZ+YnJZ+J4wNfTxmDVyrkzFvttBXXtYRMHkM= -cloud.google.com/go/documentai v1.18.0/go.mod h1:F6CK6iUH8J81FehpskRmhLq/3VlwQvb7TvwOceQ2tbs= -cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y= -cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= -cloud.google.com/go/domains v0.8.0/go.mod h1:M9i3MMDzGFXsydri9/vW+EWz9sWb4I6WyHqdlAk0idE= -cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk= -cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= -cloud.google.com/go/edgecontainer v0.3.0/go.mod h1:FLDpP4nykgwwIfcLt6zInhprzw0lEi2P1fjO6Ie0qbc= -cloud.google.com/go/edgecontainer v1.0.0/go.mod h1:cttArqZpBB2q58W/upSG++ooo6EsblxDIolxa3jSjbY= -cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= -cloud.google.com/go/essentialcontacts v1.3.0/go.mod h1:r+OnHa5jfj90qIfZDO/VztSFqbQan7HV75p8sA+mdGI= -cloud.google.com/go/essentialcontacts v1.4.0/go.mod h1:8tRldvHYsmnBCHdFpvU+GL75oWiBKl80BiqlFh9tp+8= -cloud.google.com/go/essentialcontacts v1.5.0/go.mod h1:ay29Z4zODTuwliK7SnX8E86aUF2CTzdNtvv42niCX0M= -cloud.google.com/go/eventarc v1.7.0/go.mod h1:6ctpF3zTnaQCxUjHUdcfgcA1A2T309+omHZth7gDfmc= -cloud.google.com/go/eventarc v1.8.0/go.mod h1:imbzxkyAU4ubfsaKYdQg04WS1NvncblHEup4kvF+4gw= -cloud.google.com/go/eventarc v1.10.0/go.mod h1:u3R35tmZ9HvswGRBnF48IlYgYeBcPUCjkr4BTdem2Kw= -cloud.google.com/go/eventarc v1.11.0/go.mod h1:PyUjsUKPWoRBCHeOxZd/lbOOjahV41icXyUY5kSTvVY= -cloud.google.com/go/filestore v1.3.0/go.mod h1:+qbvHGvXU1HaKX2nD0WEPo92TP/8AQuCVEBXNY9z0+w= -cloud.google.com/go/filestore v1.4.0/go.mod h1:PaG5oDfo9r224f8OYXURtAsY+Fbyq/bLYoINEK8XQAI= -cloud.google.com/go/filestore v1.5.0/go.mod h1:FqBXDWBp4YLHqRnVGveOkHDf8svj9r5+mUDLupOWEDs= -cloud.google.com/go/filestore v1.6.0/go.mod h1:di5unNuss/qfZTw2U9nhFqo8/ZDSc466dre85Kydllg= -cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE= -cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk= -cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= -cloud.google.com/go/functions v1.8.0/go.mod h1:RTZ4/HsQjIqIYP9a9YPbU+QFoQsAlYgrwOXJWHn1POY= -cloud.google.com/go/functions v1.9.0/go.mod h1:Y+Dz8yGguzO3PpIjhLTbnqV1CWmgQ5UwtlpzoyquQ08= -cloud.google.com/go/functions v1.10.0/go.mod h1:0D3hEOe3DbEvCXtYOZHQZmD+SzYsi1YbI7dGvHfldXw= -cloud.google.com/go/functions v1.12.0/go.mod h1:AXWGrF3e2C/5ehvwYo/GH6O5s09tOPksiKhz+hH8WkA= -cloud.google.com/go/functions v1.13.0/go.mod h1:EU4O007sQm6Ef/PwRsI8N2umygGqPBS/IZQKBQBcJ3c= -cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM= -cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA= -cloud.google.com/go/gaming v1.7.0/go.mod h1:LrB8U7MHdGgFG851iHAfqUdLcKBdQ55hzXy9xBJz0+w= -cloud.google.com/go/gaming v1.8.0/go.mod h1:xAqjS8b7jAVW0KFYeRUxngo9My3f33kFmua++Pi+ggM= -cloud.google.com/go/gaming v1.9.0/go.mod h1:Fc7kEmCObylSWLO334NcO+O9QMDyz+TKC4v1D7X+Bc0= -cloud.google.com/go/gkebackup v0.2.0/go.mod h1:XKvv/4LfG829/B8B7xRkk8zRrOEbKtEam6yNfuQNH60= -cloud.google.com/go/gkebackup v0.3.0/go.mod h1:n/E671i1aOQvUxT541aTkCwExO/bTer2HDlj4TsBRAo= -cloud.google.com/go/gkebackup v0.4.0/go.mod h1:byAyBGUwYGEEww7xsbnUTBHIYcOPy/PgUWUtOeRm9Vg= -cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o= -cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A= -cloud.google.com/go/gkeconnect v0.7.0/go.mod h1:SNfmVqPkaEi3bF/B3CNZOAYPYdg7sU+obZ+QTky2Myw= -cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0= -cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0= -cloud.google.com/go/gkehub v0.11.0/go.mod h1:JOWHlmN+GHyIbuWQPl47/C2RFhnFKH38jH9Ascu3n0E= -cloud.google.com/go/gkehub v0.12.0/go.mod h1:djiIwwzTTBrF5NaXCGv3mf7klpEMcST17VBTVVDcuaw= -cloud.google.com/go/gkemulticloud v0.3.0/go.mod h1:7orzy7O0S+5kq95e4Hpn7RysVA7dPs8W/GgfUtsPbrA= -cloud.google.com/go/gkemulticloud v0.4.0/go.mod h1:E9gxVBnseLWCk24ch+P9+B2CoDFJZTyIgLKSalC7tuI= -cloud.google.com/go/gkemulticloud v0.5.0/go.mod h1:W0JDkiyi3Tqh0TJr//y19wyb1yf8llHVto2Htf2Ja3Y= -cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= -cloud.google.com/go/gsuiteaddons v1.3.0/go.mod h1:EUNK/J1lZEZO8yPtykKxLXI6JSVN2rg9bN8SXOa0bgM= -cloud.google.com/go/gsuiteaddons v1.4.0/go.mod h1:rZK5I8hht7u7HxFQcFei0+AtfS9uSushomRlg+3ua1o= -cloud.google.com/go/gsuiteaddons v1.5.0/go.mod h1:TFCClYLd64Eaa12sFVmUyG62tk4mdIsI7pAnSXRkcFo= -cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c= -cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= -cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= -cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc= -cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= -cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= -cloud.google.com/go/iam v0.11.0/go.mod h1:9PiLDanza5D+oWFZiH1uG+RnRCfEGKoyl6yo4cgWZGY= -cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= -cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= -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/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc= -cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A= -cloud.google.com/go/iap v1.6.0/go.mod h1:NSuvI9C/j7UdjGjIde7t7HBz+QTwBcapPE07+sSRcLk= -cloud.google.com/go/iap v1.7.0/go.mod h1:beqQx56T9O1G1yNPph+spKpNibDlYIiIixiqsQXxLIo= -cloud.google.com/go/iap v1.7.1/go.mod h1:WapEwPc7ZxGt2jFGB/C/bm+hP0Y6NXzOYGjpPnmMS74= -cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM= -cloud.google.com/go/ids v1.2.0/go.mod h1:5WXvp4n25S0rA/mQWAg1YEEBBq6/s+7ml1RDCW1IrcY= -cloud.google.com/go/ids v1.3.0/go.mod h1:JBdTYwANikFKaDP6LtW5JAi4gubs57SVNQjemdt6xV4= -cloud.google.com/go/iot v1.3.0/go.mod h1:r7RGh2B61+B8oz0AGE+J72AhA0G7tdXItODWsaA2oLs= -cloud.google.com/go/iot v1.4.0/go.mod h1:dIDxPOn0UvNDUMD8Ger7FIaTuvMkj+aGk94RPP0iV+g= -cloud.google.com/go/iot v1.5.0/go.mod h1:mpz5259PDl3XJthEmh9+ap0affn/MqNSP4My77Qql9o= -cloud.google.com/go/iot v1.6.0/go.mod h1:IqdAsmE2cTYYNO1Fvjfzo9po179rAtJeVGUvkLN3rLE= -cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA= -cloud.google.com/go/kms v1.5.0/go.mod h1:QJS2YY0eJGBg3mnDfuaCyLauWwBJiHRboYxJ++1xJNg= -cloud.google.com/go/kms v1.6.0/go.mod h1:Jjy850yySiasBUDi6KFUwUv2n1+o7QZFyuUJg6OgjA0= -cloud.google.com/go/kms v1.8.0/go.mod h1:4xFEhYFqvW+4VMELtZyxomGSYtSQKzM178ylFW4jMAg= -cloud.google.com/go/kms v1.9.0/go.mod h1:qb1tPTgfF9RQP8e1wq4cLFErVuTJv7UsSC915J8dh3w= -cloud.google.com/go/kms v1.10.0/go.mod h1:ng3KTUtQQU9bPX3+QGLsflZIHlkbn8amFAMY63m8d24= -cloud.google.com/go/kms v1.10.1/go.mod h1:rIWk/TryCkR59GMC3YtHtXeLzd634lBbKenvyySAyYI= -cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= -cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= -cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiPzPCJa2MIE= -cloud.google.com/go/language v1.8.0/go.mod h1:qYPVHf7SPoNNiCL2Dr0FfEFNil1qi3pQEyygwpgVKB8= -cloud.google.com/go/language v1.9.0/go.mod h1:Ns15WooPM5Ad/5no/0n81yUetis74g3zrbeJBE+ptUY= -cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= -cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= -cloud.google.com/go/lifesciences v0.8.0/go.mod h1:lFxiEOMqII6XggGbOnKiyZ7IBwoIqA84ClvoezaA/bo= -cloud.google.com/go/logging v1.6.1/go.mod h1:5ZO0mHHbvm8gEmeEUHrmDlTDSu5imF6MUP9OfilNXBw= -cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeNqVNkzY8M= -cloud.google.com/go/logging v1.12.0 h1:ex1igYcGFd4S/RZWOCU51StlIEuey5bjqwH9ZYjHibk= -cloud.google.com/go/logging v1.12.0/go.mod h1:wwYBt5HlYP1InnrtYI0wtwttpVU1rifnMT7RejksUAM= -cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE= -cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= -cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= -cloud.google.com/go/longrunning v0.6.2 h1:xjDfh1pQcWPEvnfjZmwjKQEcHnpz6lHjfy7Fo0MK+hc= -cloud.google.com/go/longrunning v0.6.2/go.mod h1:k/vIs83RN4bE3YCswdXC5PFfWVILjm3hpEUlSko4PiI= -cloud.google.com/go/managedidentities v1.3.0/go.mod h1:UzlW3cBOiPrzucO5qWkNkh0w33KFtBJU281hacNvsdE= -cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtqOsxY1ZrGM+9RgDqInM= -cloud.google.com/go/managedidentities v1.5.0/go.mod h1:+dWcZ0JlUmpuxpIDfyP5pP5y0bLdRwOS4Lp7gMni/LA= -cloud.google.com/go/maps v0.1.0/go.mod h1:BQM97WGyfw9FWEmQMpZ5T6cpovXXSd1cGmFma94eubI= -cloud.google.com/go/maps v0.6.0/go.mod h1:o6DAMMfb+aINHz/p/jbcY+mYeXBoZoxTfdSQ8VAJaCw= -cloud.google.com/go/maps v0.7.0/go.mod h1:3GnvVl3cqeSvgMcpRlQidXsPYuDGQ8naBis7MVzpXsY= -cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= -cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= -cloud.google.com/go/mediatranslation v0.7.0/go.mod h1:LCnB/gZr90ONOIQLgSXagp8XUW1ODs2UmUMvcgMfI2I= -cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= -cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM= -cloud.google.com/go/memcache v1.6.0/go.mod h1:XS5xB0eQZdHtTuTF9Hf8eJkKtR3pVRCcvJwtm68T3rA= -cloud.google.com/go/memcache v1.7.0/go.mod h1:ywMKfjWhNtkQTxrWxCkCFkoPjLHPW6A7WOTVI8xy3LY= -cloud.google.com/go/memcache v1.9.0/go.mod h1:8oEyzXCu+zo9RzlEaEjHl4KkgjlNDaXbCQeQWlzNFJM= -cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY= -cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s= -cloud.google.com/go/metastore v1.7.0/go.mod h1:s45D0B4IlsINu87/AsWiEVYbLaIMeUSoxlKKDqBGFS8= -cloud.google.com/go/metastore v1.8.0/go.mod h1:zHiMc4ZUpBiM7twCIFQmJ9JMEkDSyZS9U12uf7wHqSI= -cloud.google.com/go/metastore v1.10.0/go.mod h1:fPEnH3g4JJAk+gMRnrAnoqyv2lpUCqJPWOodSaf45Eo= -cloud.google.com/go/monitoring v1.7.0/go.mod h1:HpYse6kkGo//7p6sT0wsIC6IBDET0RhIsnmlA53dvEk= -cloud.google.com/go/monitoring v1.8.0/go.mod h1:E7PtoMJ1kQXWxPjB6mv2fhC5/15jInuulFdYYtlcvT4= -cloud.google.com/go/monitoring v1.12.0/go.mod h1:yx8Jj2fZNEkL/GYZyTLS4ZtZEZN8WtDEiEqG4kLK50w= -cloud.google.com/go/monitoring v1.13.0/go.mod h1:k2yMBAB1H9JT/QETjNkgdCGD9bPF712XiLTVr+cBrpw= -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/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA= -cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o= -cloud.google.com/go/networkconnectivity v1.6.0/go.mod h1:OJOoEXW+0LAxHh89nXd64uGG+FbQoeH8DtxCHVOMlaM= -cloud.google.com/go/networkconnectivity v1.7.0/go.mod h1:RMuSbkdbPwNMQjB5HBWD5MpTBnNm39iAVpC3TmsExt8= -cloud.google.com/go/networkconnectivity v1.10.0/go.mod h1:UP4O4sWXJG13AqrTdQCD9TnLGEbtNRqjuaaA7bNjF5E= -cloud.google.com/go/networkconnectivity v1.11.0/go.mod h1:iWmDD4QF16VCDLXUqvyspJjIEtBR/4zq5hwnY2X3scM= -cloud.google.com/go/networkmanagement v1.4.0/go.mod h1:Q9mdLLRn60AsOrPc8rs8iNV6OHXaGcDdsIQe1ohekq8= -cloud.google.com/go/networkmanagement v1.5.0/go.mod h1:ZnOeZ/evzUdUsnvRt792H0uYEnHQEMaz+REhhzJRcf4= -cloud.google.com/go/networkmanagement v1.6.0/go.mod h1:5pKPqyXjB/sgtvB5xqOemumoQNB7y95Q7S+4rjSOPYY= -cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ= -cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU= -cloud.google.com/go/networksecurity v0.7.0/go.mod h1:mAnzoxx/8TBSyXEeESMy9OOYwo1v+gZ5eMRnsT5bC8k= -cloud.google.com/go/networksecurity v0.8.0/go.mod h1:B78DkqsxFG5zRSVuwYFRZ9Xz8IcQ5iECsNrPn74hKHU= -cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY= -cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34= -cloud.google.com/go/notebooks v1.4.0/go.mod h1:4QPMngcwmgb6uw7Po99B2xv5ufVoIQ7nOGDyL4P8AgA= -cloud.google.com/go/notebooks v1.5.0/go.mod h1:q8mwhnP9aR8Hpfnrc5iN5IBhrXUy8S2vuYs+kBJ/gu0= -cloud.google.com/go/notebooks v1.7.0/go.mod h1:PVlaDGfJgj1fl1S3dUwhFMXFgfYGhYQt2164xOMONmE= -cloud.google.com/go/notebooks v1.8.0/go.mod h1:Lq6dYKOYOWUCTvw5t2q1gp1lAp0zxAxRycayS0iJcqQ= -cloud.google.com/go/optimization v1.1.0/go.mod h1:5po+wfvX5AQlPznyVEZjGJTMr4+CAkJf2XSTQOOl9l4= -cloud.google.com/go/optimization v1.2.0/go.mod h1:Lr7SOHdRDENsh+WXVmQhQTrzdu9ybg0NecjHidBq6xs= -cloud.google.com/go/optimization v1.3.1/go.mod h1:IvUSefKiwd1a5p0RgHDbWCIbDFgKuEdB+fPPuP0IDLI= -cloud.google.com/go/orchestration v1.3.0/go.mod h1:Sj5tq/JpWiB//X/q3Ngwdl5K7B7Y0KZ7bfv0wL6fqVA= -cloud.google.com/go/orchestration v1.4.0/go.mod h1:6W5NLFWs2TlniBphAViZEVhrXRSMgUGDfW7vrWKvsBk= -cloud.google.com/go/orchestration v1.6.0/go.mod h1:M62Bevp7pkxStDfFfTuCOaXgaaqRAga1yKyoMtEoWPQ= -cloud.google.com/go/orgpolicy v1.4.0/go.mod h1:xrSLIV4RePWmP9P3tBl8S93lTmlAxjm06NSm2UTmKvE= -cloud.google.com/go/orgpolicy v1.5.0/go.mod h1:hZEc5q3wzwXJaKrsx5+Ewg0u1LxJ51nNFlext7Tanwc= -cloud.google.com/go/orgpolicy v1.10.0/go.mod h1:w1fo8b7rRqlXlIJbVhOMPrwVljyuW5mqssvBtU18ONc= -cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs= -cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg= -cloud.google.com/go/osconfig v1.9.0/go.mod h1:Yx+IeIZJ3bdWmzbQU4fxNl8xsZ4amB+dygAwFPlvnNo= -cloud.google.com/go/osconfig v1.10.0/go.mod h1:uMhCzqC5I8zfD9zDEAfvgVhDS8oIjySWh+l4WK6GnWw= -cloud.google.com/go/osconfig v1.11.0/go.mod h1:aDICxrur2ogRd9zY5ytBLV89KEgT2MKB2L/n6x1ooPw= -cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E= -cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU= -cloud.google.com/go/oslogin v1.6.0/go.mod h1:zOJ1O3+dTU8WPlGEkFSh7qeHPPSoxrcMbbK1Nm2iX70= -cloud.google.com/go/oslogin v1.7.0/go.mod h1:e04SN0xO1UNJ1M5GP0vzVBFicIe4O53FOfcixIqTyXo= -cloud.google.com/go/oslogin v1.9.0/go.mod h1:HNavntnH8nzrn8JCTT5fj18FuJLFJc4NaZJtBnQtKFs= -cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0= -cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA= -cloud.google.com/go/phishingprotection v0.7.0/go.mod h1:8qJI4QKHoda/sb/7/YmMQ2omRLSLYSu9bU0EKCNI+Lk= -cloud.google.com/go/policytroubleshooter v1.3.0/go.mod h1:qy0+VwANja+kKrjlQuOzmlvscn4RNsAc0e15GGqfMxg= -cloud.google.com/go/policytroubleshooter v1.4.0/go.mod h1:DZT4BcRw3QoO8ota9xw/LKtPa8lKeCByYeKTIf/vxdE= -cloud.google.com/go/policytroubleshooter v1.5.0/go.mod h1:Rz1WfV+1oIpPdN2VvvuboLVRsB1Hclg3CKQ53j9l8vw= -cloud.google.com/go/policytroubleshooter v1.6.0/go.mod h1:zYqaPTsmfvpjm5ULxAyD/lINQxJ0DDsnWOP/GZ7xzBc= -cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0= -cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI= -cloud.google.com/go/privatecatalog v0.7.0/go.mod h1:2s5ssIFO69F5csTXcwBP7NPFTZvps26xGzvQ2PQaBYg= -cloud.google.com/go/privatecatalog v0.8.0/go.mod h1:nQ6pfaegeDAq/Q5lrfCQzQLhubPiZhSaNhIgfJlnIXs= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/pubsub v1.26.0/go.mod h1:QgBH3U/jdJy/ftjPhTkyXNj543Tin1pRYcdcPRnFIRI= -cloud.google.com/go/pubsub v1.27.1/go.mod h1:hQN39ymbV9geqBnfQq6Xf63yNhUAhv9CZhzp5O6qsW0= -cloud.google.com/go/pubsub v1.28.0/go.mod h1:vuXFpwaVoIPQMGXqRyUQigu/AX1S3IWugR9xznmcXX8= -cloud.google.com/go/pubsub v1.30.0/go.mod h1:qWi1OPS0B+b5L+Sg6Gmc9zD1Y+HaM0MdUr7LsupY1P4= -cloud.google.com/go/pubsublite v1.5.0/go.mod h1:xapqNQ1CuLfGi23Yda/9l4bBCKz/wC3KIJ5gKcxveZg= -cloud.google.com/go/pubsublite v1.6.0/go.mod h1:1eFCS0U11xlOuMFV/0iBqw3zP12kddMeCbj/F3FSj9k= -cloud.google.com/go/pubsublite v1.7.0/go.mod h1:8hVMwRXfDfvGm3fahVbtDbiLePT3gpoiJYJY+vxWxVM= -cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4= -cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o= -cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk= -cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7dd5NwwNQUErSgEDit1DLNTdo= -cloud.google.com/go/recaptchaenterprise/v2 v2.4.0/go.mod h1:Am3LHfOuBstrLrNCBrlI5sbwx9LBg3te2N6hGvHn2mE= -cloud.google.com/go/recaptchaenterprise/v2 v2.5.0/go.mod h1:O8LzcHXN3rz0j+LBC91jrwI3R+1ZSZEWrfL7XHgNo9U= -cloud.google.com/go/recaptchaenterprise/v2 v2.6.0/go.mod h1:RPauz9jeLtB3JVzg6nCbe12qNoaa8pXc4d/YukAmcnA= -cloud.google.com/go/recaptchaenterprise/v2 v2.7.0/go.mod h1:19wVj/fs5RtYtynAPJdDTb69oW0vNHYDBTbB4NvMD9c= -cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg= -cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4= -cloud.google.com/go/recommendationengine v0.7.0/go.mod h1:1reUcE3GIu6MeBz/h5xZJqNLuuVjNg1lmWMPyjatzac= -cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg= -cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c= -cloud.google.com/go/recommender v1.7.0/go.mod h1:XLHs/W+T8olwlGOgfQenXBTbIseGclClff6lhFVe9Bs= -cloud.google.com/go/recommender v1.8.0/go.mod h1:PkjXrTT05BFKwxaUxQmtIlrtj0kph108r02ZZQ5FE70= -cloud.google.com/go/recommender v1.9.0/go.mod h1:PnSsnZY7q+VL1uax2JWkt/UegHssxjUVVCrX52CuEmQ= -cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y= -cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A= -cloud.google.com/go/redis v1.9.0/go.mod h1:HMYQuajvb2D0LvMgZmLDZW8V5aOC/WxstZHiy4g8OiA= -cloud.google.com/go/redis v1.10.0/go.mod h1:ThJf3mMBQtW18JzGgh41/Wld6vnDDc/F/F35UolRZPM= -cloud.google.com/go/redis v1.11.0/go.mod h1:/X6eicana+BWcUda5PpwZC48o37SiFVTFSs0fWAJ7uQ= -cloud.google.com/go/resourcemanager v1.3.0/go.mod h1:bAtrTjZQFJkiWTPDb1WBjzvc6/kifjj4QBYuKCCoqKA= -cloud.google.com/go/resourcemanager v1.4.0/go.mod h1:MwxuzkumyTX7/a3n37gmsT3py7LIXwrShilPh3P1tR0= -cloud.google.com/go/resourcemanager v1.5.0/go.mod h1:eQoXNAiAvCf5PXxWxXjhKQoTMaUSNrEfg+6qdf/wots= -cloud.google.com/go/resourcemanager v1.6.0/go.mod h1:YcpXGRs8fDzcUl1Xw8uOVmI8JEadvhRIkoXXUNVYcVo= -cloud.google.com/go/resourcemanager v1.7.0/go.mod h1:HlD3m6+bwhzj9XCouqmeiGuni95NTrExfhoSrkC/3EI= -cloud.google.com/go/resourcesettings v1.3.0/go.mod h1:lzew8VfESA5DQ8gdlHwMrqZs1S9V87v3oCnKCWoOuQU= -cloud.google.com/go/resourcesettings v1.4.0/go.mod h1:ldiH9IJpcrlC3VSuCGvjR5of/ezRrOxFtpJoJo5SmXg= -cloud.google.com/go/resourcesettings v1.5.0/go.mod h1:+xJF7QSG6undsQDfsCJyqWXyBwUoJLhetkRMDRnIoXA= -cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4= -cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY= -cloud.google.com/go/retail v1.10.0/go.mod h1:2gDk9HsL4HMS4oZwz6daui2/jmKvqShXKQuB2RZ+cCc= -cloud.google.com/go/retail v1.11.0/go.mod h1:MBLk1NaWPmh6iVFSz9MeKG/Psyd7TAgm6y/9L2B4x9Y= -cloud.google.com/go/retail v1.12.0/go.mod h1:UMkelN/0Z8XvKymXFbD4EhFJlYKRx1FGhQkVPU5kF14= -cloud.google.com/go/run v0.2.0/go.mod h1:CNtKsTA1sDcnqqIFR3Pb5Tq0usWxJJvsWOCPldRU3Do= -cloud.google.com/go/run v0.3.0/go.mod h1:TuyY1+taHxTjrD0ZFk2iAR+xyOXEA0ztb7U3UNA0zBo= -cloud.google.com/go/run v0.8.0/go.mod h1:VniEnuBwqjigv0A7ONfQUaEItaiCRVujlMqerPPiktM= -cloud.google.com/go/run v0.9.0/go.mod h1:Wwu+/vvg8Y+JUApMwEDfVfhetv30hCG4ZwDR/IXl2Qg= -cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s= -cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI= -cloud.google.com/go/scheduler v1.6.0/go.mod h1:SgeKVM7MIwPn3BqtcBntpLyrIJftQISRrYB5ZtT+KOk= -cloud.google.com/go/scheduler v1.7.0/go.mod h1:jyCiBqWW956uBjjPMMuX09n3x37mtyPJegEWKxRsn44= -cloud.google.com/go/scheduler v1.8.0/go.mod h1:TCET+Y5Gp1YgHT8py4nlg2Sew8nUHMqcpousDgXJVQc= -cloud.google.com/go/scheduler v1.9.0/go.mod h1:yexg5t+KSmqu+njTIh3b7oYPheFtBWGcbVUYF1GGMIc= -cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA= -cloud.google.com/go/secretmanager v1.8.0/go.mod h1:hnVgi/bN5MYHd3Gt0SPuTPPp5ENina1/LxM+2W9U9J4= -cloud.google.com/go/secretmanager v1.9.0/go.mod h1:b71qH2l1yHmWQHt9LC80akm86mX8AL6X1MA01dW8ht4= -cloud.google.com/go/secretmanager v1.10.0/go.mod h1:MfnrdvKMPNra9aZtQFvBcvRU54hbPD8/HayQdlUgJpU= -cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4= -cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0= -cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU= -cloud.google.com/go/security v1.9.0/go.mod h1:6Ta1bO8LXI89nZnmnsZGp9lVoVWXqsVbIq/t9dzI+2Q= -cloud.google.com/go/security v1.10.0/go.mod h1:QtOMZByJVlibUT2h9afNDWRZ1G96gVywH8T5GUSb9IA= -cloud.google.com/go/security v1.12.0/go.mod h1:rV6EhrpbNHrrxqlvW0BWAIawFWq3X90SduMJdFwtLB8= -cloud.google.com/go/security v1.13.0/go.mod h1:Q1Nvxl1PAgmeW0y3HTt54JYIvUdtcpYKVfIB8AOMZ+0= -cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU= -cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc= -cloud.google.com/go/securitycenter v1.15.0/go.mod h1:PeKJ0t8MoFmmXLXWm41JidyzI3PJjd8sXWaVqg43WWk= -cloud.google.com/go/securitycenter v1.16.0/go.mod h1:Q9GMaLQFUD+5ZTabrbujNWLtSLZIZF7SAR0wWECrjdk= -cloud.google.com/go/securitycenter v1.18.1/go.mod h1:0/25gAzCM/9OL9vVx4ChPeM/+DlfGQJDwBy/UC8AKK0= -cloud.google.com/go/securitycenter v1.19.0/go.mod h1:LVLmSg8ZkkyaNy4u7HCIshAngSQ8EcIRREP3xBnyfag= -cloud.google.com/go/servicecontrol v1.4.0/go.mod h1:o0hUSJ1TXJAmi/7fLJAedOovnujSEvjKCAFNXPQ1RaU= -cloud.google.com/go/servicecontrol v1.5.0/go.mod h1:qM0CnXHhyqKVuiZnGKrIurvVImCs8gmqWsDoqe9sU1s= -cloud.google.com/go/servicecontrol v1.10.0/go.mod h1:pQvyvSRh7YzUF2efw7H87V92mxU8FnFDawMClGCNuAA= -cloud.google.com/go/servicecontrol v1.11.0/go.mod h1:kFmTzYzTUIuZs0ycVqRHNaNhgR+UMUpw9n02l/pY+mc= -cloud.google.com/go/servicecontrol v1.11.1/go.mod h1:aSnNNlwEFBY+PWGQ2DoM0JJ/QUXqV5/ZD9DOLB7SnUk= -cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs= -cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg= -cloud.google.com/go/servicedirectory v1.6.0/go.mod h1:pUlbnWsLH9c13yGkxCmfumWEPjsRs1RlmJ4pqiNjVL4= -cloud.google.com/go/servicedirectory v1.7.0/go.mod h1:5p/U5oyvgYGYejufvxhgwjL8UVXjkuw7q5XcG10wx1U= -cloud.google.com/go/servicedirectory v1.8.0/go.mod h1:srXodfhY1GFIPvltunswqXpVxFPpZjf8nkKQT7XcXaY= -cloud.google.com/go/servicedirectory v1.9.0/go.mod h1:29je5JjiygNYlmsGz8k6o+OZ8vd4f//bQLtvzkPPT/s= -cloud.google.com/go/servicemanagement v1.4.0/go.mod h1:d8t8MDbezI7Z2R1O/wu8oTggo3BI2GKYbdG4y/SJTco= -cloud.google.com/go/servicemanagement v1.5.0/go.mod h1:XGaCRe57kfqu4+lRxaFEAuqmjzF0r+gWHjWqKqBvKFo= -cloud.google.com/go/servicemanagement v1.6.0/go.mod h1:aWns7EeeCOtGEX4OvZUWCCJONRZeFKiptqKf1D0l/Jc= -cloud.google.com/go/servicemanagement v1.8.0/go.mod h1:MSS2TDlIEQD/fzsSGfCdJItQveu9NXnUniTrq/L8LK4= -cloud.google.com/go/serviceusage v1.3.0/go.mod h1:Hya1cozXM4SeSKTAgGXgj97GlqUvF5JaoXacR1JTP/E= -cloud.google.com/go/serviceusage v1.4.0/go.mod h1:SB4yxXSaYVuUBYUml6qklyONXNLt83U0Rb+CXyhjEeU= -cloud.google.com/go/serviceusage v1.5.0/go.mod h1:w8U1JvqUqwJNPEOTQjrMHkw3IaIFLoLsPLvsE3xueec= -cloud.google.com/go/serviceusage v1.6.0/go.mod h1:R5wwQcbOWsyuOfbP9tGdAnCAc6B9DRwPG1xtWMDeuPA= -cloud.google.com/go/shell v1.3.0/go.mod h1:VZ9HmRjZBsjLGXusm7K5Q5lzzByZmJHf1d0IWHEN5X4= -cloud.google.com/go/shell v1.4.0/go.mod h1:HDxPzZf3GkDdhExzD/gs8Grqk+dmYcEjGShZgYa9URw= -cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+qE2f9A= -cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos= -cloud.google.com/go/spanner v1.44.0/go.mod h1:G8XIgYdOK+Fbcpbs7p2fiprDw4CaZX63whnSMLVBxjk= -cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M= -cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= -cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= -cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= -cloud.google.com/go/speech v1.9.0/go.mod h1:xQ0jTcmnRFFM2RfX/U+rk6FQNUF6DQlydUSyoooSpco= -cloud.google.com/go/speech v1.14.1/go.mod h1:gEosVRPJ9waG7zqqnsHpYTOoAS4KouMRLDFMekpJ0J0= -cloud.google.com/go/speech v1.15.0/go.mod h1:y6oH7GhqCaZANH7+Oe0BhgIogsNInLlz542tg3VqeYI= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= -cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= -cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= -cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y= -cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4= -cloud.google.com/go/storage v1.49.0 h1:zenOPBOWHCnojRd9aJZAyQXBYqkJkdQS42dxL55CIMw= -cloud.google.com/go/storage v1.49.0/go.mod h1:k1eHhhpLvrPjVGfo0mOUPEJ4Y2+a/Hv5PiwehZI9qGU= -cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w= -cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I= -cloud.google.com/go/storagetransfer v1.7.0/go.mod h1:8Giuj1QNb1kfLAiWM1bN6dHzfdlDAVC9rv9abHot2W4= -cloud.google.com/go/storagetransfer v1.8.0/go.mod h1:JpegsHHU1eXg7lMHkvf+KE5XDJ7EQu0GwNJbbVGanEw= -cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= -cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= -cloud.google.com/go/talent v1.3.0/go.mod h1:CmcxwJ/PKfRgd1pBjQgU6W3YBwiewmUzQYH5HHmSCmM= -cloud.google.com/go/talent v1.4.0/go.mod h1:ezFtAgVuRf8jRsvyE6EwmbTK5LKciD4KVnHuDEFmOOA= -cloud.google.com/go/talent v1.5.0/go.mod h1:G+ODMj9bsasAEJkQSzO2uHQWXHHXUomArjWQQYkqK6c= -cloud.google.com/go/texttospeech v1.4.0/go.mod h1:FX8HQHA6sEpJ7rCMSfXuzBcysDAuWusNNNvN9FELDd8= -cloud.google.com/go/texttospeech v1.5.0/go.mod h1:oKPLhR4n4ZdQqWKURdwxMy0uiTS1xU161C8W57Wkea4= -cloud.google.com/go/texttospeech v1.6.0/go.mod h1:YmwmFT8pj1aBblQOI3TfKmwibnsfvhIBzPXcW4EBovc= -cloud.google.com/go/tpu v1.3.0/go.mod h1:aJIManG0o20tfDQlRIej44FcwGGl/cD0oiRyMKG19IQ= -cloud.google.com/go/tpu v1.4.0/go.mod h1:mjZaX8p0VBgllCzF6wcU2ovUXN9TONFLd7iz227X2Xg= -cloud.google.com/go/tpu v1.5.0/go.mod h1:8zVo1rYDFuW2l4yZVY0R0fb/v44xLh3llq7RuV61fPM= -cloud.google.com/go/trace v1.3.0/go.mod h1:FFUE83d9Ca57C+K8rDl/Ih8LwOzWIV1krKgxg6N0G28= -cloud.google.com/go/trace v1.4.0/go.mod h1:UG0v8UBqzusp+z63o7FK74SdFE+AXpCLdFb1rshXG+Y= -cloud.google.com/go/trace v1.8.0/go.mod h1:zH7vcsbAhklH8hWFig58HvxcxyQbaIqMarMg9hn5ECA= -cloud.google.com/go/trace v1.9.0/go.mod h1:lOQqpE5IaWY0Ixg7/r2SjixMuc6lfTFeO4QGM4dQWOk= -cloud.google.com/go/trace v1.11.2 h1:4ZmaBdL8Ng/ajrgKqY5jfvzqMXbrDcBsUGXOT9aqTtI= -cloud.google.com/go/trace v1.11.2/go.mod h1:bn7OwXd4pd5rFuAnTrzBuoZ4ax2XQeG3qNgYmfCy0Io= -cloud.google.com/go/translate v1.3.0/go.mod h1:gzMUwRjvOqj5i69y/LYLd8RrNQk+hOmIXTi9+nb3Djs= -cloud.google.com/go/translate v1.4.0/go.mod h1:06Dn/ppvLD6WvA5Rhdp029IX2Mi3Mn7fpMRLPvXT5Wg= -cloud.google.com/go/translate v1.5.0/go.mod h1:29YDSYveqqpA1CQFD7NQuP49xymq17RXNaUDdc0mNu0= -cloud.google.com/go/translate v1.6.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= -cloud.google.com/go/translate v1.7.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= -cloud.google.com/go/video v1.8.0/go.mod h1:sTzKFc0bUSByE8Yoh8X0mn8bMymItVGPfTuUBUyRgxk= -cloud.google.com/go/video v1.9.0/go.mod h1:0RhNKFRF5v92f8dQt0yhaHrEuH95m068JYOvLZYnJSw= -cloud.google.com/go/video v1.12.0/go.mod h1:MLQew95eTuaNDEGriQdcYn0dTwf9oWiA4uYebxM5kdg= -cloud.google.com/go/video v1.13.0/go.mod h1:ulzkYlYgCp15N2AokzKjy7MQ9ejuynOJdf1tR5lGthk= -cloud.google.com/go/video v1.14.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= -cloud.google.com/go/video v1.15.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= -cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= -cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4= -cloud.google.com/go/videointelligence v1.8.0/go.mod h1:dIcCn4gVDdS7yte/w+koiXn5dWVplOZkE+xwG9FgK+M= -cloud.google.com/go/videointelligence v1.9.0/go.mod h1:29lVRMPDYHikk3v8EdPSaL8Ku+eMzDljjuvRs105XoU= -cloud.google.com/go/videointelligence v1.10.0/go.mod h1:LHZngX1liVtUhZvi2uNS0VQuOzNi2TkY1OakiuoUOjU= -cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0= -cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo= -cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo= -cloud.google.com/go/vision/v2 v2.4.0/go.mod h1:VtI579ll9RpVTrdKdkMzckdnwMyX2JILb+MhPqRbPsY= -cloud.google.com/go/vision/v2 v2.5.0/go.mod h1:MmaezXOOE+IWa+cS7OhRRLK2cNv1ZL98zhqFFZaaH2E= -cloud.google.com/go/vision/v2 v2.6.0/go.mod h1:158Hes0MvOS9Z/bDMSFpjwsUrZ5fPrdwuyyvKSGAGMY= -cloud.google.com/go/vision/v2 v2.7.0/go.mod h1:H89VysHy21avemp6xcf9b9JvZHVehWbET0uT/bcuY/0= -cloud.google.com/go/vmmigration v1.2.0/go.mod h1:IRf0o7myyWFSmVR1ItrBSFLFD/rJkfDCUTO4vLlJvsE= -cloud.google.com/go/vmmigration v1.3.0/go.mod h1:oGJ6ZgGPQOFdjHuocGcLqX4lc98YQ7Ygq8YQwHh9A7g= -cloud.google.com/go/vmmigration v1.5.0/go.mod h1:E4YQ8q7/4W9gobHjQg4JJSgXXSgY21nA5r8swQV+Xxc= -cloud.google.com/go/vmmigration v1.6.0/go.mod h1:bopQ/g4z+8qXzichC7GW1w2MjbErL54rk3/C843CjfY= -cloud.google.com/go/vmwareengine v0.1.0/go.mod h1:RsdNEf/8UDvKllXhMz5J40XxDrNJNN4sagiox+OI208= -cloud.google.com/go/vmwareengine v0.2.2/go.mod h1:sKdctNJxb3KLZkE/6Oui94iw/xs9PRNC2wnNLXsHvH8= -cloud.google.com/go/vmwareengine v0.3.0/go.mod h1:wvoyMvNWdIzxMYSpH/R7y2h5h3WFkx6d+1TIsP39WGY= -cloud.google.com/go/vpcaccess v1.4.0/go.mod h1:aQHVbTWDYUR1EbTApSVvMq1EnT57ppDmQzZ3imqIk4w= -cloud.google.com/go/vpcaccess v1.5.0/go.mod h1:drmg4HLk9NkZpGfCmZ3Tz0Bwnm2+DKqViEpeEpOq0m8= -cloud.google.com/go/vpcaccess v1.6.0/go.mod h1:wX2ILaNhe7TlVa4vC5xce1bCnqE3AeH27RV31lnmZes= -cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE= -cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= -cloud.google.com/go/webrisk v1.6.0/go.mod h1:65sW9V9rOosnc9ZY7A7jsy1zoHS5W9IAXv6dGqhMQMc= -cloud.google.com/go/webrisk v1.7.0/go.mod h1:mVMHgEYH0r337nmt1JyLthzMr6YxwN1aAIEc2fTcq7A= -cloud.google.com/go/webrisk v1.8.0/go.mod h1:oJPDuamzHXgUc+b8SiHRcVInZQuybnvEW72PqTc7sSg= -cloud.google.com/go/websecurityscanner v1.3.0/go.mod h1:uImdKm2wyeXQevQJXeh8Uun/Ym1VqworNDlBXQevGMo= -cloud.google.com/go/websecurityscanner v1.4.0/go.mod h1:ebit/Fp0a+FWu5j4JOmJEV8S8CzdTkAS77oDsiSqYWQ= -cloud.google.com/go/websecurityscanner v1.5.0/go.mod h1:Y6xdCPy81yi0SQnDY1xdNTNpfY1oAgXUlcfN3B3eSng= -cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= -cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M= -cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA= -cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw= -cosmossdk.io/api v0.9.2 h1:9i9ptOBdmoIEVEVWLtYYHjxZonlF/aOVODLFaxpmNtg= -cosmossdk.io/api v0.9.2/go.mod h1:CWt31nVohvoPMTlPv+mMNCtC0a7BqRdESjCsstHcTkU= -cosmossdk.io/client/v2 v2.0.0-beta.7 h1:O0PfZL5kC3Sp54wZASLNihQ612Gd6duMp11aM9wawNg= -cosmossdk.io/client/v2 v2.0.0-beta.7/go.mod h1:TzwwrzeK+AfSVSESVEIOYO/9xuCh1fPv0HgeocmfVnM= -cosmossdk.io/collections v1.2.1 h1:mAlNMs5vJwkda4TA+k5q/43p24RVAQ/qyDrjANu3BXE= -cosmossdk.io/collections v1.2.1/go.mod h1:PSsEJ/fqny0VPsHLFT6gXDj/2C1tBOTS9eByK0+PBFU= -cosmossdk.io/core v0.11.3 h1:mei+MVDJOwIjIniaKelE3jPDqShCc/F4LkNNHh+4yfo= -cosmossdk.io/core v0.11.3/go.mod h1:9rL4RE1uDt5AJ4Tg55sYyHWXA16VmpHgbe0PbJc6N2Y= +cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE= +cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= +cloud.google.com/go/auth v0.20.0 h1:kXTssoVb4azsVDoUiF8KvxAqrsQcQtB53DcSgta74CA= +cloud.google.com/go/auth v0.20.0/go.mod h1:942/yi/itH1SsmpyrbnTMDgGfdy2BUqIKyd0cyYLc5Q= +cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= +cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= +cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= +cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= +cloud.google.com/go/iam v1.9.0 h1:89wyjxT6DL4b5rk/Nk8eBC9DHqf+JiMstrn5IEYxFw4= +cloud.google.com/go/iam v1.9.0/go.mod h1:KP+nKGugNJW4LcLx1uEZcq1ok5sQHFaQehQNl4QDgV4= +cloud.google.com/go/logging v1.15.0 h1:6ooUEBNT6jdWh2b36+iuPn6b/R9qN/tHCbvGS5255gg= +cloud.google.com/go/logging v1.15.0/go.mod h1:ZGKnpBaURITh+g/uom2VhbiFoFWvejcrHPDhxFtU/gI= +cloud.google.com/go/longrunning v0.10.0 h1:4OWvp1BjCvoeSZTog3sRFDu6j4IrI9TI4/Y9N+8h25g= +cloud.google.com/go/longrunning v0.10.0/go.mod h1:8nqFBPOO1U/XkhWl0I19AMZEphrHi73VNABIpKYaTwM= +cloud.google.com/go/monitoring v1.27.0 h1:BhYwMqao+e5Nn7JtWMM9m6zRtKtVUK6kJWMizXChkLU= +cloud.google.com/go/monitoring v1.27.0/go.mod h1:72NOVjJXHY/HBfoLT0+qlCZBT059+9VXLeAnL2PeeVM= +cloud.google.com/go/storage v1.62.1 h1:Os0G3XbUbjZumkpDUf2Y0rLoXJTCF1kU2kWUujKYXD8= +cloud.google.com/go/storage v1.62.1/go.mod h1:cpYz/kRVZ+UQAF1uHeea10/9ewcRbxGoGNKsS9daSXA= +cloud.google.com/go/trace v1.13.0 h1:RfqsqPOiSCG8ql50UZt5F65KrVa1zbY9mJrO7xvZfbE= +cloud.google.com/go/trace v1.13.0/go.mod h1:r+bdAn16dKLSV1G2D5v3e58IlQlizfxWrUfjx7kM7X0= +cosmossdk.io/api v1.0.0 h1:qTV8OPVEwcBPwp2b9p4Qy4noZyihJ+sOMaWL/VT+RCc= +cosmossdk.io/api v1.0.0/go.mod h1:fKRljeYk+04p4T8Shdyv+uH2fSVyzHoWrvDAs/7OxfI= +cosmossdk.io/collections v1.4.0 h1:b373bkxCxKiRbapxZ42TRmcKJEnBVBebdQVk9I5IkkE= +cosmossdk.io/collections v1.4.0/go.mod h1:gxbieVY3tjbvWlkm3yOXf7sGyDrVi12haZH+sek6whw= +cosmossdk.io/core v1.1.0 h1:iJ7j2DjNsFzg4/z4ImNQYzy2D4LfMCsaQ8Lrz1KCmxk= +cosmossdk.io/core v1.1.0/go.mod h1:qGmJxBFHobvG1k4bROQnueslotBU5MIKZLC57xVBYYI= 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.1 h1:YXNwAgbDwMEKwDlCdH8vPcoggma48MgZrTQXCfmMBeI= -cosmossdk.io/log v1.6.1/go.mod h1:gMwsWyyDBjpdG9u2avCFdysXqxq28WJapJvu+vF1y+E= +cosmossdk.io/errors v1.1.0 h1:X2DSt9JYgH7cuiaDr318aUqIl2z5Lfo/PdGzAtmczUU= +cosmossdk.io/errors v1.1.0/go.mod h1:lnjBmx7etZpMTLnxdspZupH0d9HGRWZhiezDZX2ayyI= +cosmossdk.io/log/v2 v2.1.0 h1:oWLWqZ1UObWu5hIS3dvTW7QyjtvlmSzC3LOy04U/hVI= +cosmossdk.io/log/v2 v2.1.0/go.mod h1:zDNpuRD2sWw4zuw1lZYg/jxKftVG+VizgcWAWkIorwY= 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= cosmossdk.io/schema v1.1.0/go.mod h1:Gb7pqO+tpR+jLW5qDcNOSv0KtppYs7881kfzakguhhI= -cosmossdk.io/store v1.1.2 h1:3HOZG8+CuThREKv6cn3WSohAc6yccxO3hLzwK6rBC7o= -cosmossdk.io/store v1.1.2/go.mod h1:60rAGzTHevGm592kFhiUVkNC9w7gooSEn5iUBPzHQ6A= cosmossdk.io/tools/confix v0.1.2 h1:2hoM1oFCNisd0ltSAAZw2i4ponARPmlhuNu3yy0VwI4= cosmossdk.io/tools/confix v0.1.2/go.mod h1:7XfcbK9sC/KNgVGxgLM0BrFbVcR/+6Dg7MFfpx7duYo= -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 v0.14.0 h1:hB3O25kIcyDW/7kMTLMaO8Ripj3yqs5imceVd6c/heA= -cosmossdk.io/x/tx v0.14.0/go.mod h1:Tn30rSRA1PRfdGB3Yz55W4Sn6EIutr9xtMKSHij+9PM= -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= -gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= -git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= +filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo= +filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc= 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/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/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= +github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/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/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= @@ -660,37 +54,33 @@ github.com/DataDog/datadog-go v4.8.3+incompatible h1:fNGaYSuObuQb5nzeTQqowRAd9bp 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.29.0 h1:UQUsRi8WTzhZntp5313l+CHIAT95ojUI2lpP/ExlZa4= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0/go.mod h1:Cz6ft6Dkn3Et6l2v2a9/RpN7epQ1GtDlO6lj8bEcOvw= -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/cloudmock v0.48.1 h1:oTX4vsorBZo/Zdum6OKPA4o7544hm6smoRv1QjpTwGo= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.48.1/go.mod h1:0wEl7vrAD8mehJyohS9HZy+WyEOaQO2mJx86Cvh93kM= -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/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.32.0 h1:rIkQfkCOVKc1OiRCNcSDD8ml5RJlZbH/Xsq7lbpynwc= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.32.0/go.mod h1:RD2SsorTmYhF6HkTmDw7KmPYQk8OBYwTkuasChwv7R4= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.56.0 h1:O2sXMyJh8b7devAGdE+163xtRurt0RVpB6DIzX5vGfg= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.56.0/go.mod h1:hEpiGU18xf70qb3jbTcIggWAiEfX/cOIVc2OTe4OegA= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.56.0 h1:ZIT85vKP7LBS84XJ0WdJ3dPOX3iz4j3c0+lpajGQMyo= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.56.0/go.mod h1:rqP9UEhOXv9WhQ7Gjz+G5y/pf8+BJZW5/Ts0AhE0PwE= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.56.0 h1:0YP0+/ixwu+Uqeu/FGiBZNQ19huiUxxiPXIc9WsLKuQ= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.56.0/go.mod h1:6ZZMQhZKDvUvkJw2rc+oDP90tMMzuU/J+5HG1ZmPOmE= 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= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260116142910-60249400e523 h1:pQUezn45oyv/8VcOQvPCg2851EIIusY0YKkJhAXsy2I= +github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260116142910-60249400e523/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI= +github.com/RoaringBitmap/roaring/v2 v2.18.0 h1:h7sS0VqCkfBMGgcHaudJFB4FE6Td71H6svRB2poRnGY= +github.com/RoaringBitmap/roaring/v2 v2.18.0/go.mod h1:eq4wdNXxtJIS/oikeCzdX1rBzek7ANzbth041hrU8Q4= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= -github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= -github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI= -github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI= +github.com/VictoriaMetrics/fastcache v1.13.0 h1:AW4mheMR5Vd9FkAPUv+NH6Nhw+fmbTMGMsNAoA/+4G0= +github.com/VictoriaMetrics/fastcache v1.13.0/go.mod h1:hHXhl4DA2fTL2HTZDJFXWgW0LNjo6B+4aj2Wmng3TjU= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= -github.com/adlio/schema v1.3.6 h1:k1/zc2jNfeiZBA5aFTRy37jlBIuCkXCm0XmvpzCKI9I= -github.com/adlio/schema v1.3.6/go.mod h1:qkxwLgPBd1FgLRHYVCmQT/rrBr3JH38J9LjmVzWNudg= +github.com/adlio/schema v1.4.0 h1:dekxG6P0my/bPvlyWzMULelR2Xej8RGErlnJcoY5ddw= +github.com/adlio/schema v1.4.0/go.mod h1:3/ojUldWBCWp4e+6VN9ets6unG5WdqbjF7vyzM0zTVQ= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= -github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= -github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= -github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= -github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -698,13 +88,9 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0= -github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= @@ -712,11 +98,48 @@ 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.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= -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/aws/aws-sdk-go-v2 v1.41.6 h1:1AX0AthnBQzMx1vbmir3Y4WsnJgiydmnJjiLu+LvXOg= +github.com/aws/aws-sdk-go-v2 v1.41.6/go.mod h1:dy0UzBIfwSeot4grGvY1AqFWN5zgziMmWGzysDnHFcQ= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.9 h1:adBsCIIpLbLmYnkQU+nAChU5yhVTvu5PerROm+/Kq2A= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.9/go.mod h1:uOYhgfgThm/ZyAuJGNQ5YgNyOlYfqnGpTHXvk3cpykg= +github.com/aws/aws-sdk-go-v2/config v1.32.14 h1:opVIRo/ZbbI8OIqSOKmpFaY7IwfFUOCCXBsUpJOwDdI= +github.com/aws/aws-sdk-go-v2/config v1.32.14/go.mod h1:U4/V0uKxh0Tl5sxmCBZ3AecYny4UNlVmObYjKuuaiOo= +github.com/aws/aws-sdk-go-v2/credentials v1.19.14 h1:n+UcGWAIZHkXzYt87uMFBv/l8THYELoX6gVcUvgl6fI= +github.com/aws/aws-sdk-go-v2/credentials v1.19.14/go.mod h1:cJKuyWB59Mqi0jM3nFYQRmnHVQIcgoxjEMAbLkpr62w= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21 h1:NUS3K4BTDArQqNu2ih7yeDLaS3bmHD0YndtA6UP884g= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21/go.mod h1:YWNWJQNjKigKY1RHVJCuupeWDrrHjRqHm0N9rdrWzYI= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.22 h1:GmLa5Kw1ESqtFpXsx5MmC84QWa/ZrLZvlJGa2y+4kcQ= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.22/go.mod h1:6sW9iWm9DK9YRpRGga/qzrzNLgKpT2cIxb7Vo2eNOp0= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.22 h1:dY4kWZiSaXIzxnKlj17nHnBcXXBfac6UlsAx2qL6XrU= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.22/go.mod h1:KIpEUx0JuRZLO7U6cbV204cWAEco2iC3l061IxlwLtI= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 h1:qYQ4pzQ2Oz6WpQ8T3HvGHnZydA72MnLuFK9tJwmrbHw= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6/go.mod h1:O3h0IK87yXci+kg6flUKzJnWeziQUKciKrLjcatSNcY= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.23 h1:FPXsW9+gMuIeKmz7j6ENWcWtBGTe1kH8r9thNt5Uxx4= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.23/go.mod h1:7J8iGMdRKk6lw2C+cMIphgAnT8uTwBwNOsGkyOCm80U= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.8 h1:HtOTYcbVcGABLOVuPYaIihj6IlkqubBwFj10K5fxRek= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.8/go.mod h1:VsK9abqQeGlzPgUr+isNWzPlK2vKe9INMLWnY65f5Xs= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.14 h1:xnvDEnw+pnj5mctWiYuFbigrEzSm35x7k4KS/ZkCANg= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.14/go.mod h1:yS5rNogD8e0Wu9+l3MUwr6eENBzEeGejvINpN5PAYfY= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.22 h1:PUmZeJU6Y1Lbvt9WFuJ0ugUK2xn6hIWUBBbKuOWF30s= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.22/go.mod h1:nO6egFBoAaoXze24a2C0NjQCvdpk8OueRoYimvEB9jo= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.22 h1:SE+aQ4DEqG53RRCAIHlCf//B2ycxGH7jFkpnAh/kKPM= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.22/go.mod h1:ES3ynECd7fYeJIL6+oax+uIEljmfps0S70BaQzbMd/o= +github.com/aws/aws-sdk-go-v2/service/s3 v1.100.0 h1:7G26Sae6PMKn4kMcU5JzNfrm1YrKwyOhowXPYR2WiWY= +github.com/aws/aws-sdk-go-v2/service/s3 v1.100.0/go.mod h1:Fw9aqhJicIVee1VytBBjH+l+5ov6/PhbtIK/u3rt/ls= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.9 h1:QKZH0S178gCmFEgst8hN0mCX1KxLgHBKKY/CLqwP8lg= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.9/go.mod h1:7yuQJoT+OoH8aqIxw9vwF+8KpvLZ8AWmvmUWHsGQZvI= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.15 h1:lFd1+ZSEYJZYvv9d6kXzhkZu07si3f+GQ1AaYwa2LUM= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.15/go.mod h1:WSvS1NLr7JaPunCXqpJnWk1Bjo7IxzZXrZi1QQCkuqM= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.19 h1:dzztQ1YmfPrxdrOiuZRMF6fuOwWlWpD2StNLTceKpys= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.19/go.mod h1:YO8TrYtFdl5w/4vmjL8zaBSsiNp3w0L1FfKVKenZT7w= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.10 h1:p8ogvvLugcR/zLBXTXrTkj0RYBUdErbMnAFFp12Lm/U= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.10/go.mod h1:60dv0eZJfeVXfbT1tFJinbHrDfSJ2GZl4Q//OSSNAVw= +github.com/aws/smithy-go v1.25.0 h1:Sz/XJ64rwuiKtB6j98nDIPyYrV1nVNJ4YU74gttcl5U= +github.com/aws/smithy-go v1.25.0/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= +github.com/benbjohnson/clock v1.3.5/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= @@ -726,10 +149,8 @@ github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ 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/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= -github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/bits-and-blooms/bitset v1.24.4 h1:95H15Og1clikBrKr/DuzMXkQzECs1M6hhoGXLwLQOZE= +github.com/bits-and-blooms/bitset v1.24.4/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= @@ -737,8 +158,8 @@ github.com/btcsuite/btcd v0.24.2 h1:aLmxPguqxza+4ag8R1I2nnJjSu2iFn/kqtHTIImswcY= github.com/btcsuite/btcd v0.24.2/go.mod h1:5C8ChTkl5ejr3WHj8tkQSCmydiMEPB0ZhQhehpq7Dgg= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= -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/btcec/v2 v2.3.5 h1:dpAlnAwmT1yIBm3exhT1/8iUSD98RDJM5vqJVQDQLiU= +github.com/btcsuite/btcd/btcec/v2 v2.3.5/go.mod h1:m22FrOAiuxl/tht9wIqAoGHcbnCCaPWyauO8y2LGGtQ= github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= @@ -757,32 +178,28 @@ github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -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/gopkg v0.1.4 h1:oZnQwnX82KAIWb7033bEwtxvTqXcYMxDBaQxo5JJHWM= +github.com/bytedance/gopkg v0.1.4/go.mod h1:v1zWfPm21Fb+OsyXN2VAHdL6TBb2L88anLQgdyje6R4= github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= -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.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA= -github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= +github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE= +github.com/bytedance/sonic v1.15.0/go.mod h1:tFkWrPz0/CUCLEF4ri4UkHekCIcdnkqXw9VduqpJh0k= +github.com/bytedance/sonic/loader v0.5.1 h1:Ygpfa9zwRCCKSlrp5bBP/b/Xzc3VxsAW+5NIYXrOOpI= +github.com/bytedance/sonic/loader v0.5.1/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= 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= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= +github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -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/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -798,180 +215,171 @@ github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6D github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4= -github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= -github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= +github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M= +github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 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-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/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/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 h1:aBangftG7EVZoUb69Os8IaYg++6uMOdKK83QtkkvJik= +github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2/go.mod h1:qwXFYgsP6T7XnJtbKlf1HP8AjxZZyzxMmc+Lq5GjlU4= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= 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/errors v1.13.0 h1:BoCcJeiP9hpBJDETkX19qi8Tb8So37srSsp3stTaDMQ= +github.com/cockroachdb/errors v1.13.0/go.mod h1:bjxt/4E5+OyuAnacpTIU9rn2mzPu1VlthvHP+xpROq0= +github.com/cockroachdb/fifo v0.0.0-20240816210425-c5d0cb0b6fc0 h1:pU88SPhIFid6/k0egdR5V6eALQYq2qbSmukrkgIh/0A= +github.com/cockroachdb/fifo v0.0.0-20240816210425-c5d0cb0b6fc0/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 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= -github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= +github.com/cockroachdb/redact v1.1.8 h1:8eVLLj6juKxiKrAEw2b8cJvNqWq++U8WOfQFuL7KTaA= +github.com/cockroachdb/redact v1.1.8/go.mod h1:GceHHpJ0rMDpYARL5In88Alq/xMBUtVlz7Qxix6ZVkw= +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 v0.14.1 h1:SxoamPghqICBAIcGpleHbmoPqy+crij/++eZz3DlerQ= -github.com/cometbft/cometbft-db v0.14.1/go.mod h1:KHP1YghilyGV/xjD5DP3+2hyigWx0WTp9X+0Gnx0RxQ= -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/cometbft/cometbft v0.39.3 h1:UegHXskZNomsijmm29nL5NkeXtnzkme6fg+q1hPQnEI= +github.com/cometbft/cometbft v0.39.3/go.mod h1:PmNfvtw256BC41ad0FABts236CSZnvZ0kjPOciBwTdM= +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/consensys/gnark-crypto v0.18.1 h1:RyLV6UhPRoYYzaFnPQA4qK3DyuDgkTgskDdoGqFt3fI= +github.com/consensys/gnark-crypto v0.18.1/go.mod h1:L3mXGFTe1ZN+RSJ+CLjUt9x7PNdx8ubaYfDROyp2Z8c= +github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4= +github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= +github.com/cosmos/btree v0.0.0-20250924232609-2c6195d95951 h1:dC3GJcS8bJiSEe7VAFDDFgFnVM1G9nBdGOgqJsmsZwM= +github.com/cosmos/btree v0.0.0-20250924232609-2c6195d95951/go.mod h1:jBbTdUWhSZClZWoDg54VnvV7/54modSOzDN7VXftj1A= +github.com/cosmos/btree v1.0.0 h1:V3OdIzTQw2yE7f6pD6FfA9j2/YLj1UpB9MdY0zU3v3k= +github.com/cosmos/btree v1.0.0/go.mod h1:BZML+flLn4d3MOa4POmzDWf5HQ7EGh0y1OLlfhh7A0k= github.com/cosmos/cosmos-db v1.1.3 h1:7QNT77+vkefostcKkhrzDK9uoIEryzFrU9eoMeaQOPY= github.com/cosmos/cosmos-db v1.1.3/go.mod h1:kN+wGsnwUJZYn8Sy5Q2O0vCYA99MJllkKASbs6Unb9U= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= -github.com/cosmos/cosmos-sdk v0.53.4 h1:kPF6vY68+/xi1/VebSZGpoxQqA52qkhUzqkrgeBn3Mg= -github.com/cosmos/cosmos-sdk v0.53.4/go.mod h1:7U3+WHZtI44dEOnU46+lDzBb2tFh1QlMvi8Z5JugopI= +github.com/cosmos/cosmos-sdk v0.54.3 h1:oUxbIACmHZV13IZXl59y+mIEOCFlUAjXV9p1rqrYcEg= +github.com/cosmos/cosmos-sdk v0.54.3/go.mod h1:Unt21RO+q1EebU6gcUPKYVzpAQSr4KIHjaOmjpz2twA= +github.com/cosmos/cosmos-sdk/store/v2 v2.0.0 h1:5CFXBU5cHIvxMpz5QBrTwR5DL/W3uZL2BYYMoDp4siY= +github.com/cosmos/cosmos-sdk/store/v2 v2.0.0/go.mod h1:XyRyi5fGjIcokBqS1cyA8/QVbVNy4ui8hmpk1gezuHo= 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 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/go-ethereum v1.17.2-cosmos-0 h1:V1vadF7/miUwwbNh3iiqNM51aHAG/5mzRCeIdcdostw= +github.com/cosmos/go-ethereum v1.17.2-cosmos-0/go.mod h1:KHcRXfGOUfUmKg51IhQ0IowiqZ6PqZf08CMtk0g5K1o= 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= -github.com/cosmos/gogoproto v1.7.0 h1:79USr0oyXAbxg3rspGh/m4SWNyoz/GLaAh0QlCe2fro= -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/v10 v10.3.1-0.20250909102629-ed3b125c7b6f h1:I5t5Tuewh6E9icYCtS4aSwyzIEvr2iBods08Hq+GBME= -github.com/cosmos/ibc-go/v10 v10.3.1-0.20250909102629-ed3b125c7b6f/go.mod h1:a74pAPUSJ7NewvmvELU74hUClJhwnmm5MGbEaiTw/kE= +github.com/cosmos/gogoproto v1.7.2 h1:5G25McIraOC0mRFv9TVO139Uh3OklV2hczr13KKVHCA= +github.com/cosmos/gogoproto v1.7.2/go.mod h1:8S7w53P1Y1cHwND64o0BnArT6RmdgIvsBuco6uTllsk= +github.com/cosmos/iavl v1.2.8 h1:55F96BGUJ7KT7h+Ky/cEqS+pEvhFqsU4O8Th3F0N1js= +github.com/cosmos/iavl v1.2.8/go.mod h1:FRHN4tO+6crf0p2zsqye+nAbsMgiwdkxpWm18DyP6+Y= +github.com/cosmos/ibc-go/v11 v11.0.0 h1:9EIehi88hNP1cCU83NC+J8UXNn+05YZt9eqmnzCQLSg= +github.com/cosmos/ibc-go/v11 v11.0.0/go.mod h1:iWlzLuCu+ctVbQwoVf5z51HE5e/NE8/pwnLVVDmP++4= 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= github.com/cosmos/keyring v1.2.0/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= -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/cosmos/ledger-cosmos-go v1.0.0 h1:jNKW89nPf0vR0EkjHG8Zz16h6p3zqwYEOxlHArwgYtw= +github.com/cosmos/ledger-cosmos-go v1.0.0/go.mod h1:mGaw2wDOf+Z6SfRJsMGxU9DIrBa4du0MAiPlpPhLAOE= 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/creachadair/atomicfile v0.3.7 h1:wdg8+Isz07NDMi2yZQAoI1EKB9SxuDhvo5MUii/ZqlM= -github.com/creachadair/atomicfile v0.3.7/go.mod h1:lUrZrE/XjMA7rJY/n8dF7/sSpy6KjtPaxPbrDambthA= -github.com/creachadair/mds v0.22.1 h1:Wink9jeYR7brBbOkOTVZVrd6vyb5W4ZBRhlZd96TSgU= -github.com/creachadair/mds v0.22.1/go.mod h1:ArfS0vPHoLV/SzuIzoqTEZfoYmac7n9Cj8XPANHocvw= -github.com/creachadair/tomledit v0.0.28 h1:aQJVwcNTzx4SZ/tSbkyGE69w4YQ6Gn+xhHHKtqMZwuw= -github.com/creachadair/tomledit v0.0.28/go.mod h1:pqb2HRQi0lMu6MBiUmTk/0XQ+SmPtq2QbUrG+eiLP5w= +github.com/crate-crypto/go-eth-kzg v1.5.0 h1:FYRiJMJG2iv+2Dy3fi14SVGjcPteZ5HAAUe4YWlJygc= +github.com/crate-crypto/go-eth-kzg v1.5.0/go.mod h1:J9/u5sWfznSObptgfa92Jq8rTswn6ahQWEuiLHOjCUI= +github.com/creachadair/atomicfile v0.3.8 h1:PyMIBZHZunTF+2+OSJCUg4XWO9nh6NwIacUBtF6tdg8= +github.com/creachadair/atomicfile v0.3.8/go.mod h1:oZrfNyYdwMjCD+eKNqsnPmdnQ54z4ujOoYvNTZyuJ2A= +github.com/creachadair/mds v0.24.1 h1:bzL4ItCtAUxxO9KkotP0PVzlw4tnJicAcjPu82v2mGs= +github.com/creachadair/mds v0.24.1/go.mod h1:ArfS0vPHoLV/SzuIzoqTEZfoYmac7n9Cj8XPANHocvw= +github.com/creachadair/tomledit v0.0.29 h1:dB5CbdwJMpn/fmfAPTAAleXF/KJwY0Ggc1eL/zvZRgk= +github.com/creachadair/tomledit v0.0.29/go.mod h1:4SoTXxzHgvzHRMIJPw+o6zK/yXii4VjLrb6/3gCQnyA= 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.2.1 h1:dl9cBrupW8+r5250DYkYxocLeZ1Y4vB1kxgtjxw8GQs= -github.com/danieljoos/wincred v1.2.1/go.mod h1:uGaFL9fDn3OLTvzCGulzE+SzjEe5NGlh5FdCcyfPwps= +github.com/danieljoos/wincred v1.2.3 h1:v7dZC2x32Ut3nEfRH+vhoZGvN72+dQ/snVXo/vMFLdQ= +github.com/danieljoos/wincred v1.2.3/go.mod h1:6qqX0WNrS4RzPZ1tnroDzq9kY3fu1KwE7MRLQK4X0bs= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= +github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= +github.com/dchest/siphash v1.2.3 h1:QXwFc8cFOR2dSa/gE6o/HokBMWtLUaNDVd+22aKHeEA= +github.com/dchest/siphash v1.2.3/go.mod h1:0NvQU092bT0ipiFN++/rXm69QG9tVxLAlQHIXMPAkHc= 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.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= 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.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -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/decred/dcrd/dcrec/secp256k1/v4 v4.4.1 h1:5RVFMOWjMyRy8cARdy79nAmgYw3hK/4HUq48LQ6Wwqo= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.1/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/deepmap/oapi-codegen v1.6.0 h1:w/d1ntwh91XI0b/8ja7+u5SvA4IFfM0UNNLmiDR1gg0= github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M= 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.2.0 h1:kJrlajbXXL9DFTNuhhu9yCx7JJa4qpYWxtE8BzuWsEs= -github.com/dgraph-io/badger/v4 v4.2.0/go.mod h1:qfCqhPoWDFJRx1gp5QwwyGo8xk1lbHUxvK9nK0OGAak= -github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= -github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= +github.com/dgraph-io/badger/v4 v4.9.1 h1:DocZXZkg5JJHJPtUErA0ibyHxOVUDVoXLSCV6t8NC8w= +github.com/dgraph-io/badger/v4 v4.9.1/go.mod h1:5/MEx97uzdPUHR4KtkNt8asfI2T4JiEiQlV7kWUo8c0= +github.com/dgraph-io/ristretto/v2 v2.4.0 h1:I/w09yLjhdcVD2QV192UJcq8dPBaAJb9pOuMyNy0XlU= +github.com/dgraph-io/ristretto/v2 v2.4.0/go.mod h1:0KsrXtXvnv0EqnzyowllbVJB8yBonswa2lTCK2gGo9E= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -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.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= -github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= +github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da h1:aIftn67I1fkbMa512G+w+Pxci9hJPB8oMnkcP3iZF38= +github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94= +github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE= 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/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/dunglas/httpsfv v1.1.0 h1:Jw76nAyKWKZKFrpMMcL76y35tOpYHqQPzHQiwDvpe54= +github.com/dunglas/httpsfv v1.1.0/go.mod h1:zID2mqw9mFsnt7YC3vYQ9/cjq30q41W+1AnDwH8TiMg= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dustin/go-humanize v1.0.0/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.7.0 h1:bnQc8+GMnidJZA8zc6lLEAb4xNrIqHwO+9TzqvtQZPo= -github.com/dvsekhvalnov/jose2go v1.7.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= +github.com/dvsekhvalnov/jose2go v1.8.0 h1:LqkkVKAlHFfH9LOEl5fe4p/zL02OhWE7pCufMBG2jLA= +github.com/dvsekhvalnov/jose2go v1.8.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= +github.com/ebitengine/purego v0.10.0 h1:QIw4xfpWT6GWTzaW5XEKy3HXoqrJGx1ijYHzTF0/ISU= +github.com/ebitengine/purego v0.10.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= -github.com/emicklei/dot v1.6.2 h1:08GN+DD79cy/tzN6uLCT84+2Wk9u+wvqP+Hkx/dIR8A= -github.com/emicklei/dot v1.6.2/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= +github.com/emicklei/dot v1.11.0 h1:zsrhCuFHAJge/aZIC4N4LdHy5tqYu4tWEaUzIwdYj4Y= +github.com/emicklei/dot v1.11.0/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= 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.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= -github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q= -github.com/envoyproxy/go-control-plane v0.13.4 h1:zEqyPVyku6IvWCFwux4x9RxkLOMUL+1vC9xUFv5l2/M= -github.com/envoyproxy/go-control-plane v0.13.4/go.mod h1:kDfuBlDVsSj2MjrLEtRWtHlsWIFcGyB2RMO44Dc5GZA= -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/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA= +github.com/envoyproxy/go-control-plane v0.14.0/go.mod h1:NcS5X47pLl/hfqxU70yPwL9ZMkUlwlKxtAohpi2wBEU= +github.com/envoyproxy/go-control-plane/envoy v1.37.0 h1:u3riX6BoYRfF4Dr7dwSOroNfdSbEPe9Yyl09/B6wBrQ= +github.com/envoyproxy/go-control-plane/envoy v1.37.0/go.mod h1:DReE9MMrmecPy+YvQOAOHNYMALuowAnbjjEMkkWOi6A= github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 h1:/G9QYbddjL25KvtKTv3an9lx6VBE2cnb8wp1vEGNYGI= github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= -github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= -github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= -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-verkle v0.2.2 h1:I2W0WjnrFUIzzVPwm8ykY+7pL2d4VhlsePn4j7cnFk8= -github.com/ethereum/go-verkle v0.2.2/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk= +github.com/envoyproxy/protoc-gen-validate v1.3.3 h1:MVQghNeW+LZcmXe7SY1V36Z+WFMDjpqGAGacLe2T0ds= +github.com/envoyproxy/protoc-gen-validate v1.3.3/go.mod h1:TsndJ/ngyIdQRhMcVVGDDHINPLWB7C82oDArY51KfB0= +github.com/ethereum/c-kzg-4844/v2 v2.1.6 h1:xQymkKCT5E2Jiaoqf3v4wsNgjZLY0lRSkZn27fRjSls= +github.com/ethereum/c-kzg-4844/v2 v2.1.6/go.mod h1:8HMkUZ5JRv4hpw/XUrYWSQNAUzhHMg2UDb/U+5m+XNw= +github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab h1:rvv6MJhy07IMfEKuARQ9TKojGqLVNxQajaXEp/BoqSk= +github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab/go.mod h1:IuLm4IsPipXKF7CW5Lzf68PIbZ5yl7FFd74l/E0o9A8= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= -github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/ferranbt/fastssz v0.1.4 h1:OCDB+dYDEQDvAgtAGnTSidK1Pe2tW3nFV40XyMkTeDY= github.com/ferranbt/fastssz v0.1.4/go.mod h1:Ea3+oeoRGGLGm5shYAeDgu6PGUlcvQhE2fILyD9+tGg= -github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg= +github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= @@ -983,25 +391,20 @@ github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4 github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= +github.com/gammazero/deque v1.2.0 h1:scEFO8Uidhw6KDU5qg1HA5fYwM0+us2qdeJqm43bitU= +github.com/gammazero/deque v1.2.0/go.mod h1:JVrR+Bj1NMQbPnYclvDlvSX0nVGReLrQZ0aUMuWLctg= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= -github.com/getsentry/sentry-go v0.32.0 h1:YKs+//QmwE3DcYtfKRH8/KyOOF/I6Qnx7qYGNHCGmCY= -github.com/getsentry/sentry-go v0.32.0/go.mod h1:CYNcMMz73YigoHljQRG+qPF+eMq8gG72XcGN/p71BAY= +github.com/getsentry/sentry-go v0.46.0 h1:mbdDaarbUdOt9X+dx6kDdntkShLEX3/+KyOsVDTPDj0= +github.com/getsentry/sentry-go v0.46.0/go.mod h1:evVbw2qotNUdYG8KxXbAdjOQWWvWIwKxpjdZZIvcIPw= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= 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-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= -github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= -github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= -github.com/go-fonts/liberation v0.2.0/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= -github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-jose/go-jose/v4 v4.1.1 h1:JYhSgy4mXXzAdF3nUx3ygx347LRXJRrpgyU3adRmkAI= -github.com/go-jose/go-jose/v4 v4.1.1/go.mod h1:BdsZGqgdO3b6tTc6LSE56wcDbMMLuPsw5d4ZD5f94kA= +github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= +github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= 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= @@ -1010,23 +413,19 @@ github.com/go-kit/kit v0.13.0/go.mod h1:phqEHMMUbyrCFCTgH48JueqrM3md2HcAZ8N3XE4F 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-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= -github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk= 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-logfmt/logfmt v0.6.1 h1:4hvbpePJKnIzH1B+8OR/JPbTx37NktoI9LE2QZBBkvE= +github.com/go-logfmt/logfmt v0.6.1/go.mod h1:EV2pOAQoZaT1ZXZbqDl5hrymndi4SY9ED9/z6CO0XAk= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= 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.2.6/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-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= -github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= @@ -1035,16 +434,14 @@ github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= -github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro= +github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= -github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= 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.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= @@ -1057,28 +454,12 @@ 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/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI= +github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= -github.com/golang/glog v1.2.5 h1:DrW6hGnjIhtvhOIiAKT6Psh/Kd/ldepEa81DKeiRJ5I= -github.com/golang/glog v1.2.5/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= 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-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= 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= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -1086,7 +467,6 @@ github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -1097,70 +477,37 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 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.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e h1:4bw4WeyTYPp0smaXiJZCNnLrvVBqirQVreixayXezGc= -github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs= +github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= -github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= -github.com/google/flatbuffers v24.3.25+incompatible h1:CX395cjN9Kke9mmalRoL3d81AtFUxJM+yDthflgJGkI= -github.com/google/flatbuffers v24.3.25+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/flatbuffers v25.2.10+incompatible h1:F3vclr7C3HpB1k9mxCGRMXq6FdUalZ6H/pNX4FP1v0Q= +github.com/google/flatbuffers v25.2.10+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.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.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0/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= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 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/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= -github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc= github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8= github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= @@ -1168,31 +515,12 @@ 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.3.0/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.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= -github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= -github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= -github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= -github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= -github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw= -github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= -github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= -github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= -github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= -github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= -github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= -github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= -github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= -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/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +github.com/googleapis/enterprise-certificate-proxy v0.3.14 h1:yh8ncqsbUY4shRD5dA6RlzjJaT4hi3kII+zYw8wmLb8= +github.com/googleapis/enterprise-certificate-proxy v0.3.14/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg= +github.com/googleapis/gax-go/v2 v2.22.0 h1:PjIWBpgGIVKGoCXuiCoP64altEJCj3/Ei+kSU5vlZD4= +github.com/googleapis/gax-go/v2 v2.22.0/go.mod h1:irWBbALSr0Sk3qlqb9SyJ1h68WjgeFuiOzI4Rqw5+aY= 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= @@ -1206,6 +534,10 @@ github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grafana/pyroscope-go v1.2.7 h1:VWBBlqxjyR0Cwk2W6UrE8CdcdD80GOFNutj0Kb1T8ac= +github.com/grafana/pyroscope-go v1.2.7/go.mod h1:o/bpSLiJYYP6HQtvcoVKiE9s5RiNgjYTj1DhiddP2Pc= +github.com/grafana/pyroscope-go/godeltaprof v0.1.9 h1:c1Us8i6eSmkW+Ez05d3co8kasnuOY813tbMN8i/a3Og= +github.com/grafana/pyroscope-go/godeltaprof v0.1.9/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU= github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0= github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -1216,10 +548,12 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= +github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.72 h1:vTCWu1wbdYo7PEZFem/rlr01+Un+wwVmI7wiegFdRLk= +github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.72/go.mod h1:Vn+BBgKQHVQYdVQ4NZDICE1Brb+JfaONyDHr3q07oQc= 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= @@ -1229,8 +563,8 @@ github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng 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-getter v1.8.6 h1:9sQboWULaydVphxc4S64oAI4YqpuCk7nPmvbk131ebY= +github.com/hashicorp/go-getter v1.8.6/go.mod h1:nVH12eOV2P58dIiL3rsU6Fh3wLeJEKBOJzhMmzlSWoo= 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= @@ -1240,21 +574,18 @@ github.com/hashicorp/go-metrics v0.5.4 h1:8mmPiIJkTPPEbAiV97IxdAGNdRdaWwVap1BU6e github.com/hashicorp/go-metrics v0.5.4/go.mod h1:CG5yz4NZ/AI/aQt9Ucm/vdBnbh7fvmv4lxZ350i+QQI= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-plugin v1.6.3 h1:xgHB+ZUSYeuJi96WtxEjzi23uh7YQpznjGh0U0UUrwg= -github.com/hashicorp/go-plugin v1.6.3/go.mod h1:MRobyh+Wc/nYy1V4KAXUiYfzxoYhs7V1mlH1Z7iY2h0= +github.com/hashicorp/go-plugin v1.7.0 h1:YghfQH/0QmPNc/AZMTFE3ac8fipZyZECHdDPshfk+mA= +github.com/hashicorp/go-plugin v1.7.0/go.mod h1:BExt6KEaIYx804z8k4gRzRLEvxKVb+kn0NMcihqOqb8= 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= +github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -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.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= -github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.9.0 h1:CeOIz6k+LoN3qX9Z0tyQrPtiB1DFYRPfCIBtaXPSCnA= +github.com/hashicorp/go-version v1.9.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= @@ -1270,8 +601,8 @@ 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/billy v0.0.0-20250707135307-f2f9b9aae7db h1:IZUYC/xb3giYwBLMnr8d0TGTzPKFGNTCGgGLoyeX330= +github.com/holiman/billy v0.0.0-20250707135307-f2f9b9aae7db/go.mod h1:xTEYN9KCHxuYHs+NmrmzFcnvHMzLLNiGFafCb1n3Mfg= 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= @@ -1284,11 +615,8 @@ 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/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= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ= github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPtwNr0l57L4f878wP8= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -1301,17 +629,19 @@ github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c h1:qSH github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 h1:W9WBk7wlPfJLvMCdtV4zPulc4uCPrlywQOmbFOhgQNU= github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= +github.com/ipfs/go-cid v0.5.0 h1:goEKKhaGm0ul11IHA7I6p1GmKz8kEYniqFopaB5Otwg= +github.com/ipfs/go-cid v0.5.0/go.mod h1:0L7vmeNXpQpUS9vt+yEARkJ8rOg43DF3iPgn4GIN0mk= 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/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= +github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= 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/jhump/protoreflect v1.18.0 h1:TOz0MSR/0JOZ5kECB/0ufGnC2jdsgZ123Rd/k4Z5/2w= +github.com/jhump/protoreflect v1.18.0/go.mod h1:ezWcltJIVF4zYdIFM+D/sHV4Oh5LNU08ORzCGfwvTz8= +github.com/jhump/protoreflect/v2 v2.0.0-beta.1 h1:Dw1rslK/VotaUGYsv53XVWITr+5RCPXfvvlGrM/+B6w= +github.com/jhump/protoreflect/v2 v2.0.0-beta.1/go.mod h1:D9LBEowZyv8/iSu97FU2zmXG3JxVTmNw21mu63niFzU= 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/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= 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= @@ -1324,39 +654,29 @@ github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u 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/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= 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= -github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= -github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= -github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= -github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= -github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE= +github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= -github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= -github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= -github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= +github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/koron/go-ssdp v0.0.6 h1:Jb0h04599eq/CY7rB5YEqPS83HmRfHP2azkxMN2rFtU= +github.com/koron/go-ssdp v0.0.6/go.mod h1:0R9LfRJGek1zWTjN3JUNlm5INCDYGpRDfAptnct63fI= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -1368,57 +688,79 @@ github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+ 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.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= -github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= -github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.12.3 h1:tTWxr2YLKwIvK90ZXEw8GP7UFHtcbTtty8zsI+YjrfQ= +github.com/lib/pq v1.12.3/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA= +github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= +github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= +github.com/libp2p/go-flow-metrics v0.2.0 h1:EIZzjmeOE6c8Dav0sNv35vhZxATIXWZg6j/C08XmmDw= +github.com/libp2p/go-flow-metrics v0.2.0/go.mod h1:st3qqfu8+pMfh+9Mzqb2GTiwrAGjIPszEjZmtksN8Jc= +github.com/libp2p/go-libp2p v0.47.0 h1:qQpBjSCWNQFF0hjBbKirMXE9RHLtSuzTDkTfr1rw0yc= +github.com/libp2p/go-libp2p v0.47.0/go.mod h1:s8HPh7mMV933OtXzONaGFseCg/BE//m1V34p3x4EUOY= +github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94= +github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8= +github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= +github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg= +github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= +github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM= +github.com/libp2p/go-netroute v0.3.0 h1:nqPCXHmeNmgTJnktosJ/sIef9hvwYCrsLxXmfNks/oc= +github.com/libp2p/go-netroute v0.3.0/go.mod h1:Nkd5ShYgSMS5MUKy/MU2T57xFoOKvvLR92Lic48LEyA= +github.com/libp2p/go-reuseport v0.4.0 h1:nR5KU7hD0WxXCJbmw7r2rhRYruNRl2koHw8fQscQm2s= +github.com/libp2p/go-reuseport v0.4.0/go.mod h1:ZtI03j/wO5hZVDFo2jKywN6bYKWLOy8Se6DrI2E1cLU= +github.com/libp2p/go-yamux/v5 v5.0.1 h1:f0WoX/bEF2E8SbE4c/k1Mo+/9z0O4oC/hWEA+nfYRSg= +github.com/libp2p/go-yamux/v5 v5.0.1/go.mod h1:en+3cdX51U0ZslwRdRLrvQsdayFt3TSUKvBGErzpWbU= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= -github.com/linxGnu/grocksdb v1.9.2 h1:O3mzvO0wuzQ9mtlHbDrShixyVjVbmuqTjFrzlf43wZ8= -github.com/linxGnu/grocksdb v1.9.2/go.mod h1:QYiYypR2d4v63Wj1adOOfzglnoII0gLj3PNh4fZkcFA= -github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= -github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= -github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o= +github.com/linxGnu/grocksdb v1.10.7 h1:fCi4qvZWo04VgFwGWmO8HQJgUVounJBy+C2TMVPU/ho= +github.com/linxGnu/grocksdb v1.10.7/go.mod h1:OLQKZwiKwaJiAVCsOzWKvwiLwfZ5Vz8Md5TYR7t7pM8= +github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e h1:Q6MvJtQK/iRcRtzAscm/zF23XxJlbECiGPyRicsX+Ak= +github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= +github.com/marcopolo/simnet v0.0.4 h1:50Kx4hS9kFGSRIbrt9xUS3NJX33EyPqHVmpXvaKLqrY= +github.com/marcopolo/simnet v0.0.4/go.mod h1:tfQF1u2DmaB6WHODMtQaLtClEf3a296CKQLq5gAsIS0= +github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= +github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -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-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4= +github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= 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/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mdp/qrterminal/v3 v3.2.1 h1:6+yQjiiOsSuXT5n9/m60E54vdgFsw0zhADHhHLrFet4= github.com/mdp/qrterminal/v3 v3.2.1/go.mod h1:jOTmXvnBsMy5xqLniO0R++Jmjs2sTm9dFSuQ5kpz/SU= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= -github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= -github.com/minio/highwayhash v1.0.3 h1:kbnuUMoHYyVl7szWjSxJnxw11k2U709jqFPPmIUyD6Q= -github.com/minio/highwayhash v1.0.3/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ= -github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= -github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= +github.com/miekg/dns v1.1.66 h1:FeZXOS3VCVsKnEAd+wBkjMC3D2K+ww66Cq3VnCINuJE= +github.com/miekg/dns v1.1.66/go.mod h1:jGFzBsSNbJw6z1HYut1RKBKHA9PBdxeHrZG8J+gC2WE= +github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= +github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms= +github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= +github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b/go.mod h1:lxPUiZwKoFL8DUUmalo2yJJUCxbPKtm8OKfqr2/FTNU= +github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdnNMiD9ZejrlswWrCpBEZgWOiTrc= +github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s= +github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= +github.com/minio/highwayhash v1.0.4 h1:asJizugGgchQod2ja9NJlGOWq4s7KsAWr5XUc9Clgl4= +github.com/minio/highwayhash v1.0.4/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= +github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= 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= @@ -1427,13 +769,42 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua 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/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs= +github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 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/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mr-tron/base58 v1.3.0 h1:K6Y13R2h+dku0wOqKtecgRnBUBPrZzLZy5aIj8lCcJI= +github.com/mr-tron/base58 v1.3.0/go.mod h1:2BuubE67DCSWwVfx37JWNG8emOC0sHEU4/HpcYgCLX8= +github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM= +github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw= 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/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= +github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= +github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= +github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= +github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= +github.com/multiformats/go-multiaddr v0.16.1 h1:fgJ0Pitow+wWXzN9do+1b8Pyjmo8m5WhGfzpL82MpCw= +github.com/multiformats/go-multiaddr v0.16.1/go.mod h1:JSVUmXDjsVFiW7RjIFMP7+Ev+h1DTbiJgVeTV/tcmP0= +github.com/multiformats/go-multiaddr-dns v0.4.1 h1:whi/uCLbDS3mSEUMb1MsoT4uzUeZB0N32yzufqS0i5M= +github.com/multiformats/go-multiaddr-dns v0.4.1/go.mod h1:7hfthtB4E4pQwirrz+J0CcDUfbWzTqEzVyYKKIKpgkc= +github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= +github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= +github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= +github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk= +github.com/multiformats/go-multicodec v0.9.1 h1:x/Fuxr7ZuR4jJV4Os5g444F7xC4XmyUaT/FWtE+9Zjo= +github.com/multiformats/go-multicodec v0.9.1/go.mod h1:LLWNMtyV5ithSBUo3vFIMaeDy+h3EbkMTek1m+Fybbo= +github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= +github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U= +github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= +github.com/multiformats/go-multistream v0.6.1 h1:4aoX5v6T+yWmc2raBHsTvzmFhOI8WVOer28DeBBEYdQ= +github.com/multiformats/go-multistream v0.6.1/go.mod h1:ksQf6kqHAb6zIsyw7Zm+gAuVo57Qbq84E27YlYqavqw= +github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= +github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -1449,17 +820,15 @@ github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= -github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= -github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a h1:dlRvE5fWabOchtH7znfiFCcOvmIYgOeAS5ifBXBlh9Q= -github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oasisprotocol/curve25519-voi v0.0.0-20251114093237-2ab5a27a1729 h1:yfQ2sO9WJXUAIUR+g7NUkxJSKCAFJcR5sUDu+ZmjTZI= +github.com/oasisprotocol/curve25519-voi v0.0.0-20251114093237-2ab5a27a1729/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= -github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= +github.com/oklog/run v1.2.0 h1:O8x3yXwah4A73hJdlrwo/2X6J62gE5qTMusH0dvz60E= +github.com/oklog/run v1.2.0/go.mod h1:mgDbKRSwPhJfesJ4PntqFUbKQRZ50NgmZTSPlFA0YFk= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= @@ -1477,10 +846,10 @@ github.com/onsi/gomega v1.38.0/go.mod h1:OcXcwId0b9QsE7Y49u+BTrL4IdKOBOKnD6VQNTJ 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= -github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= -github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= -github.com/opencontainers/runc v1.1.12 h1:BOIssBaW1La0/qbNZHXOOa71dZfZEQOzW7dqQf3phss= -github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma/O44Ekby9FK8= +github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= +github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= +github.com/opencontainers/runc v1.2.8 h1:RnEICeDReapbZ5lZEgHvj7E9Q3Eex9toYmaGBsbvU5Q= +github.com/opencontainers/runc v1.2.8/go.mod h1:cC0YkmZcuvr+rtBZ6T7NBoVbMGNAdLa/21vIElJDOzI= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= @@ -1497,6 +866,8 @@ github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIw github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= @@ -1504,40 +875,74 @@ github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8 github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 h1:oYW+YCJ1pachXTQmzR3rNLYGGz4g/UgFcjb28p/viDM= github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= -github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 h1:Dx7Ovyv/SFnMFw3fD4oEoeorXc6saIiQ23LrGLth0Gw= -github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= -github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= -github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= -github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= +github.com/petermattis/goid v0.0.0-20250813065127-a731cc31b4fe/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/petermattis/goid v0.0.0-20260113132338-7c7de50cc741 h1:KPpdlQLZcHfTMQRi6bFQ7ogNO0ltFT4PmtwTLW4W+14= +github.com/petermattis/goid v0.0.0-20260113132338-7c7de50cc741/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= 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/datachannel v1.5.10 h1:ly0Q26K1i6ZkGf42W7D4hQYR90pZwzFOjTq5AuCKk4o= +github.com/pion/datachannel v1.5.10/go.mod h1:p/jJfC9arb29W7WrxyKbepTU20CFgyx5oLo8Rs4Py/M= 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/dtls/v2 v2.2.12 h1:KP7H5/c1EiVAAKUmXyCzPiQe5+bCJrpOeKg/L05dunk= +github.com/pion/dtls/v2 v2.2.12/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE= +github.com/pion/dtls/v3 v3.1.2 h1:gqEdOUXLtCGW+afsBLO0LtDD8GnuBBjEy6HRtyofZTc= +github.com/pion/dtls/v3 v3.1.2/go.mod h1:Hw/igcX4pdY69z1Hgv5x7wJFrUkdgHwAn/Q/uo7YHRo= +github.com/pion/ice/v4 v4.0.10 h1:P59w1iauC/wPk9PdY8Vjl4fOFL5B+USq1+xbDcN6gT4= +github.com/pion/ice/v4 v4.0.10/go.mod h1:y3M18aPhIxLlcO/4dn9X8LzLLSma84cx6emMSu14FGw= +github.com/pion/interceptor v0.1.40 h1:e0BjnPcGpr2CFQgKhrQisBU7V3GXK6wrfYrGYaU6Jq4= +github.com/pion/interceptor v0.1.40/go.mod h1:Z6kqH7M/FYirg3frjGJ21VLSRJGBXB/KqaTIrdqnOic= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= +github.com/pion/logging v0.2.4 h1:tTew+7cmQ+Mc1pTBLKH2puKsOvhm32dROumOZ655zB8= +github.com/pion/logging v0.2.4/go.mod h1:DffhXTKYdNZU+KtJ5pyQDjvOAh/GsNSyv1lbkFbe3so= +github.com/pion/mdns/v2 v2.0.7 h1:c9kM8ewCgjslaAmicYMFQIde2H9/lrZpjBkN8VwoVtM= +github.com/pion/mdns/v2 v2.0.7/go.mod h1:vAdSYNAT0Jy3Ru0zl2YiW3Rm/fJCwIeM0nToenfOJKA= +github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= +github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= +github.com/pion/rtcp v1.2.15 h1:LZQi2JbdipLOj4eBjK4wlVoQWfrZbh3Q6eHtWtJBZBo= +github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0= +github.com/pion/rtp v1.8.19 h1:jhdO/3XhL/aKm/wARFVmvTfq0lC/CvN1xwYKmduly3c= +github.com/pion/rtp v1.8.19/go.mod h1:bAu2UFKScgzyFqvUKmbvzSdPr+NGbZtv6UB2hesqXBk= +github.com/pion/sctp v1.8.39 h1:PJma40vRHa3UTO3C4MyeJDQ+KIobVYRZQZ0Nt7SjQnE= +github.com/pion/sctp v1.8.39/go.mod h1:cNiLdchXra8fHQwmIoqw0MbLLMs+f7uQ+dGMG2gWebE= +github.com/pion/sdp/v3 v3.0.13 h1:uN3SS2b+QDZnWXgdr69SM8KB4EbcnPnPf2Laxhty/l4= +github.com/pion/sdp/v3 v3.0.13/go.mod h1:88GMahN5xnScv1hIMTqLdu/cOcUkj6a9ytbncwMCq2E= +github.com/pion/srtp/v3 v3.0.6 h1:E2gyj1f5X10sB/qILUGIkL4C2CqK269Xq167PbGCc/4= +github.com/pion/srtp/v3 v3.0.6/go.mod h1:BxvziG3v/armJHAaJ87euvkhHqWe9I7iiOy50K2QkhY= +github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4= +github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8= 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/stun/v3 v3.0.0 h1:4h1gwhWLWuZWOJIJR9s2ferRO+W3zA/b6ijOI6mKzUw= +github.com/pion/stun/v3 v3.0.0/go.mod h1:HvCN8txt8mwi4FBvS3EmDghW6aQJ24T+y+1TKjB5jyU= 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/v2 v2.2.4/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0= +github.com/pion/transport/v2 v2.2.10 h1:ucLBLE8nuxiHfvkFKnkDQRYWYfp8ejf4YBOPfaQpw6Q= +github.com/pion/transport/v2 v2.2.10/go.mod h1:sq1kSLWs+cHW9E+2fJP95QudkzbK7wscs8yYgQToO5E= github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0= +github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0= +github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo= +github.com/pion/transport/v4 v4.0.1 h1:sdROELU6BZ63Ab7FrOLn13M6YdJLY20wldXW2Cu2k8o= +github.com/pion/transport/v4 v4.0.1/go.mod h1:nEuEA4AD5lPdcIegQDpVLgNoDGreqM/YqmEx3ovP4jM= +github.com/pion/turn/v4 v4.0.2 h1:ZqgQ3+MjP32ug30xAbD6Mn+/K4Sxi3SdNOTFf+7mpps= +github.com/pion/turn/v4 v4.0.2/go.mod h1:pMMKP/ieNAG/fN5cZiN4SDuyKsXtNTr0ccN7IToA1zs= +github.com/pion/webrtc/v4 v4.1.2 h1:mpuUo/EJ1zMNKGE79fAdYNFZBX790KE7kQQpLMjjR54= +github.com/pion/webrtc/v4 v4.1.2/go.mod h1:xsCXiNAmMEjIdFxAYU0MbB3RwRieJsegSB2JZsGN+8U= 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/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= -github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= 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= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -1547,17 +952,16 @@ github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeD github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= -github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= +github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= +github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= -github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= @@ -1565,8 +969,8 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k= -github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18= +github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= +github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -1574,43 +978,46 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc= +github.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo= github.com/prysmaticlabs/gohashtree v0.0.4-beta h1:H/EbCuXPeTV3lpKeXGPpEV9gsUpkqOOVnWapUyeWro4= github.com/prysmaticlabs/gohashtree v0.0.4-beta/go.mod h1:BFdtALS+Ffhg3lGQIHv9HDWuHS8cTvHZzrHWxwOtGOs= +github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8= +github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII= +github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw= +github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU= +github.com/quic-go/webtransport-go v0.10.0 h1:LqXXPOXuETY5Xe8ITdGisBzTYmUOy5eSj+9n4hLTjHI= +github.com/quic-go/webtransport-go v0.10.0/go.mod h1:LeGIXr5BQKE3UsynwVBeQrU1TPrbh73MGoC6jd+V7ow= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= -github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 h1:bsUq1dX0N8AOIL7EB/X911+m4EHsnWEHeJ0c+3TTBrg= +github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= -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/rs/zerolog v1.35.0 h1:VD0ykx7HMiMJytqINBsKcbLS+BJ4WYjz+05us+LRTdI= +github.com/rs/zerolog v1.35.0/go.mod h1:EjML9kdfa/RMA7h/6z6pYmq1ykOuA8/mjWaEvGI+jcw= 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/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= -github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= 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= -github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= +github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88eegjfxfHb4= +github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9tLLBmM4eneO6WwsI= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= -github.com/sasha-s/go-deadlock v0.3.5 h1:tNCOEEDG6tBqrNDOX35j/7hL5FcFViG6awUGROb2NsU= -github.com/sasha-s/go-deadlock v0.3.5/go.mod h1:bugP6EGbdGYObIlx7pUZtWqlvo8k9H6vCBBsiChJQ5U= +github.com/sasha-s/go-deadlock v0.3.9 h1:fiaT9rB7g5sr5ddNZvlwheclN9IP86eFW9WgqlEQV+w= +github.com/sasha-s/go-deadlock v0.3.9/go.mod h1:KuZj51ZFmx42q/mPaYbRk0P1xcwe697zsJKE03vD4/Y= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= -github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= +github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil/v4 v4.26.4 h1:B4SXVbcwTyrocPHEmWBC4uCYr4Xcu3MK1TXqbprAOWY= +github.com/shirou/gopsutil/v4 v4.26.4/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -1622,27 +1029,24 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1 github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= -github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= -github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= -github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= -github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= -github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE= -github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= +github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= +github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= +github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= +github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s= -github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0= +github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= +github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= 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.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= github.com/spf13/pflag v1.0.9/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/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= +github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= +github.com/spiffe/go-spiffe/v2 v2.6.0 h1:l+DolpxNWYgruGQVV0xsfeya3CsC7m8iBzDnMpsbLuo= +github.com/spiffe/go-spiffe/v2 v2.6.0/go.mod h1:gm2SeUoMZEtpnzPNs2Csc0D/gX33k1xIx7lEzqblHEs= 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= @@ -1650,8 +1054,9 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4= +github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -1665,31 +1070,34 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= -github.com/supranational/blst v0.3.14 h1:xNMoHRJOTwMn63ip6qoWJ2Ymgvj7E2b9jY2FAwY+qRo= -github.com/supranational/blst v0.3.14/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/supranational/blst v0.3.16 h1:bTDadT+3fK497EvLdWRQEjiGnUtzJ7jjIUMF0jqwYhE= +github.com/supranational/blst v0.3.16/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= 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/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI= -github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= +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/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= -github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= -github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= +github.com/tidwall/match v1.2.0 h1:0pt8FlkOwjN2fPt4bIl4BoNxb98gGHN2ObFEDkrfZnM= +github.com/tidwall/match v1.2.0/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= -github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= -github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= -github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= -github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/tklauser/go-sysconf v0.3.16 h1:frioLaCQSsF5Cy1jgRBrzr6t502KIIwQ0MArYICU0nA= +github.com/tklauser/go-sysconf v0.3.16/go.mod h1:/qNL9xxDhc7tx3HSRsLWNnuzbVfh3e7gh/BmM179nYI= +github.com/tklauser/numcpus v0.11.0 h1:nSTwhKH5e1dMNsCdVBukSZrURJRoHbSEQjdEbY+9RXw= +github.com/tklauser/numcpus v0.11.0/go.mod h1:z+LwcLq54uWZTX0u/bGobaV34u6V7KNlTZejzM6/3MQ= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= 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= @@ -1697,81 +1105,117 @@ github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2 github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= -github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -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/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY= +github.com/ulikunitz/xz v0.5.15/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/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= +github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU= +github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= 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.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= -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/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +github.com/zondax/golem v0.27.0 h1:IbBjGIXF3SoGOZHsILJvIM/F/ylwJzMcHAcggiqniPw= +github.com/zondax/golem v0.27.0/go.mod h1:AmorCgJPt00L8xN1VrMBe13PSifoZksnQ1Ge906bu4A= 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= -github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= +github.com/zondax/ledger-go v1.0.1 h1:Ks/2tz/dOF+dbRynfZ0dEhcdL1lqw43Sa0zMXHpQ3aQ= +github.com/zondax/ledger-go v1.0.1/go.mod h1:j7IgMY39f30apthJYMd1YsHZRqdyu4KbVmUp0nU78X0= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.4.0-alpha.1 h1:3yrqQzbRRPFPdOMWS/QQIVxVnzSkAZQYeWlZFv1kbj4= -go.etcd.io/bbolt v1.4.0-alpha.1/go.mod h1:S/Z/Nm3iuOnyO1W4XuFfPci51Gj6F1Hv0z8hisyYYOw= +go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo= +go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= 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.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -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/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.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= -go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0 h1:WDdP9acbMYjbKIyJUhTvtzj601sVJOqgWdUxSdR/Ysc= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0/go.mod h1:BLbf7zbNIONBLPwvFnwNHGj4zge8uTCM/UPIVW1Mq2I= -go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= -go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= -go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= -go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= -go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= -go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= -go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= -go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/contrib/bridges/otelslog v0.18.0 h1:hhPGP3zvvy1xWT9RTy970wlniSxFttBIsAK1gvMguJM= +go.opentelemetry.io/contrib/bridges/otelslog v0.18.0/go.mod h1:twJF7inoMza6kxMcF8JOdL3mPmtOZu7GEr34CUNE6Dg= +go.opentelemetry.io/contrib/detectors/gcp v1.43.0 h1:62yY3dT7/ShwOxzA0RsKRgshBmfElKI4d/Myu2OxDFU= +go.opentelemetry.io/contrib/detectors/gcp v1.43.0/go.mod h1:RyaZMFY7yi1kAs45S6mbFGz8O8rqB0dTY14uzvG4LCs= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 h1:0Qx7VGBacMm9ZENQ7TnNObTYI4ShC+lHI16seduaxZo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0/go.mod h1:Sje3i3MjSPKTSPvVWCaL8ugBzJwik3u4smCjUeuupqg= +go.opentelemetry.io/contrib/instrumentation/host v0.68.0 h1:0BfTRAHtFpIlIY7cw1qg9nODUwblutIqx7Cn6NPD+2s= +go.opentelemetry.io/contrib/instrumentation/host v0.68.0/go.mod h1:SmgEeGNt1+gp8bmzB5LLyUlCObWcWrRbYMIiDii3NH8= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 h1:CqXxU8VOmDefoh0+ztfGaymYbhdB/tT3zs79QaZTNGY= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0/go.mod h1:BuhAPThV8PBHBvg8ZzZ/Ok3idOdhWIodywz2xEcRbJo= +go.opentelemetry.io/contrib/instrumentation/runtime v0.68.0 h1:jhVIQEprwUTV+KfzzliLidclhoTOoHTgdz96kAyR8mU= +go.opentelemetry.io/contrib/instrumentation/runtime v0.68.0/go.mod h1:4HsdbLUbernaTnA8CNaNE+1g026SciXb3juRYe3l8EY= +go.opentelemetry.io/contrib/otelconf v0.23.0 h1:s3C7KdMYiutf4rC8hKFA0WOIDG+gIru8ajjQKS59ir8= +go.opentelemetry.io/contrib/otelconf v0.23.0/go.mod h1:0kN2tcccZS82e7IZlo045gkcL8/8dup1k25sf9ypGxM= +go.opentelemetry.io/contrib/propagators/autoprop v0.68.0 h1:wLGFvNBPqQhzBn0QRBZjrriH8lZ9gqtTz8ufHEjLg7k= +go.opentelemetry.io/contrib/propagators/autoprop v0.68.0/go.mod h1:evWK9nCqCzH8nhclTlpkdUzmxrmJQ2mrWCdKIvyOYec= +go.opentelemetry.io/contrib/propagators/aws v1.43.0 h1:EwnsB3cXRLAh7/Nr/9rMuGw73nfb3z6uAvVDjRrbeUg= +go.opentelemetry.io/contrib/propagators/aws v1.43.0/go.mod h1:CJjTym6F87tEdm61Qvnz5xrV8vKlH4C92djiqcn62k8= +go.opentelemetry.io/contrib/propagators/b3 v1.43.0 h1:CETqV3QLLPTy5yNrqyMr41VnAOOD4lsRved7n4QG00A= +go.opentelemetry.io/contrib/propagators/b3 v1.43.0/go.mod h1:Q4mCiCdziYzpNR0g+6UqVotAlCDZdzz6L8jwY4knOrw= +go.opentelemetry.io/contrib/propagators/jaeger v1.43.0 h1:peiLMz1+aqJE+3L4mOVtR9wlmv+yh/JVYXCBjqmzJJE= +go.opentelemetry.io/contrib/propagators/jaeger v1.43.0/go.mod h1:Agvif+4A8p/3UtZzJ0MCcDEuQwgtrzM71DueU41DCs8= +go.opentelemetry.io/contrib/propagators/ot v1.43.0 h1:Hh1HahlGc81AOE7siqi1tVOlbanY/UxMMWedpb0d5oQ= +go.opentelemetry.io/contrib/propagators/ot v1.43.0/go.mod h1:58MlyS7lghzYvAm5LN9gGmZpCMQEMB5vpZp9SRgOyE4= +go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= +go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.19.0 h1:Dn8rkudDzY6KV9dr/D/bTUuWgqDf9xe0rr4G2elrn0Y= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.19.0/go.mod h1:gMk9F0xDgyN9M/3Ed5Y1wKcx/9mlU91NXY2SNq7RQuU= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0 h1:HIBTQ3VO5aupLKjC90JgMqpezVXwFuq6Ryjn0/izoag= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0/go.mod h1:ji9vId85hMxqfvICA0Jt8JqEdrXaAkcpkI9HPXya0ro= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.43.0 h1:8UQVDcZxOJLtX6gxtDt3vY2WTgvZqMQRzjsqiIHQdkc= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.43.0/go.mod h1:2lmweYCiHYpEjQ/lSJBYhj9jP1zvCvQW4BqL9dnT7FQ= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0 h1:w1K+pCJoPpQifuVpsKamUdn9U0zM3xUziVOqsGksUrY= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0/go.mod h1:HBy4BjzgVE8139ieRI75oXm3EcDN+6GhD88JT1Kjvxg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 h1:88Y4s2C8oTui1LGM6bTWkw0ICGcOLCAI5l6zsD1j20k= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0/go.mod h1:Vl1/iaggsuRlrHf/hfPJPvVag77kKyvrLeD10kpMl+A= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 h1:RAE+JPfvEmvy+0LzyUA25/SGawPwIUbZ6u0Wug54sLc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0/go.mod h1:AGmbycVGEsRx9mXMZ75CsOyhSP6MFIcj/6dnG+vhVjk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 h1:3iZJKlCZufyRzPzlQhUIWVmfltrXuGyfjREgGP3UUjc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0/go.mod h1:/G+nUPfhq2e+qiXMGxMwumDrP5jtzU+mWN7/sjT2rak= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.19.0 h1:GJkybS+crDMdExT/BUNCEgfrmfboztcS6PhvSo88HKM= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.19.0/go.mod h1:NuAyxRYIG2lKX3YQkB+83StTxM7s52PUUkRRiC0wnYI= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.43.0 h1:TC+BewnDpeiAmcscXbGMfxkO+mwYUwE/VySwvw88PfA= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.43.0/go.mod h1:J/ZyF4vfPwsSr9xJSPyQ4LqtcTPULFR64KwTikGLe+A= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.43.0 h1:mS47AX77OtFfKG4vtp+84kuGSFZHTyxtXIN269vChY0= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.43.0/go.mod h1:PJnsC41lAGncJlPUniSwM81gc80GkgWJWr3cu2nKEtU= +go.opentelemetry.io/otel/log v0.19.0 h1:KUZs/GOsw79TBBMfDWsXS+KZ4g2Ckzksd1ymzsIEbo4= +go.opentelemetry.io/otel/log v0.19.0/go.mod h1:5DQYeGmxVIr4n0/BcJvF4upsraHjg6vudJJpnkL6Ipk= +go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= +go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= +go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= +go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= +go.opentelemetry.io/otel/sdk/log v0.19.0 h1:scYVLqT22D2gqXItnWiocLUKGH9yvkkeql5dBDiXyko= +go.opentelemetry.io/otel/sdk/log v0.19.0/go.mod h1:vFBowwXGLlW9AvpuF7bMgnNI95LiW10szrOdvzBHlAg= +go.opentelemetry.io/otel/sdk/log/logtest v0.19.0 h1:BEbF7ZBB6qQloV/Ub1+3NQoOUnVtcGkU3XX4Ws3GQfk= +go.opentelemetry.io/otel/sdk/log/logtest v0.19.0/go.mod h1:Lua81/3yM0wOmoHTokLj9y9ADeA02v1naRrVrkAZuKk= +go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= +go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= +go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= +go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= +go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g= +go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk= 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= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= +go.uber.org/dig v1.19.0 h1:BACLhebsYdpQ7IROQ1AGPjrXcP5dF80U3gKoFzbaq/4= +go.uber.org/dig v1.19.0/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE= +go.uber.org/fx v1.24.0 h1:wE8mruvpg2kiiL1Vqd0CC+tr0/24XIB10Iwp2lLWzkg= +go.uber.org/fx v1.24.0/go.mod h1:AmDeGyS+ZARGKM4tlH4FY2Jr63VjbEDJHtqXTGP5hbo= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko= -go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o= +go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= +go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= @@ -1781,101 +1225,58 @@ 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= +go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= +go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= +go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/arch v0.17.0 h1:4O3dfLzd+lQewptAHqjewQZQDyEdejz3VwgeYwkZneU= -golang.org/x/arch v0.17.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk= +golang.org/x/arch v0.26.0 h1:jZ6dpec5haP/fUv1kLCbuJy6dnRrfX6iVK08lZBFpk4= +golang.org/x/arch v0.26.0/go.mod h1:0X+GdSIP+kL5wPmpK7sdkEVTt2XoYP0cSjQSbZBwOi8= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 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.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= -golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= -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-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= +golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/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-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= -golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= -golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw= -golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM= -golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= +golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90 h1:jiDhWWeC7jfWqR9c/uplMOqJ0sbNlNWv0UkzE0vX1MA= +golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90/go.mod h1:xE1HEv6b+1SCZ5/uscMRjUBKtIxworgEcEi+/n9NQDQ= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.0.0-20220302094943-723b81ca9867/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -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.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI= +golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY= 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= @@ -1889,124 +1290,49 @@ golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= -golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= -golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= +golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= -golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= -golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= -golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= -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/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= +golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= 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= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= -golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= 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= @@ -2020,9 +1346,6 @@ golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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= @@ -2031,503 +1354,150 @@ golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7w 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= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/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-20210806184541-e5e7981a1069/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-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/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-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/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-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.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.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= -golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= +golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= +golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/telemetry v0.0.0-20260311193753-579e4da9a98c h1:6a8FdnNk6bTXBjR4AGKFgUKuo+7GnR3FX5L7CbveeZc= +golang.org/x/telemetry v0.0.0-20260311193753-579e4da9a98c/go.mod h1:TpUTTEp9frx7rTdLpC9gFG9kdI7zVLFTFFlqaH2Cncw= 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.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= -golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= -golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= -golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= -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.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= +golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/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.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= -golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= +golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.3.0/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/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= +golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= -golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= +golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s= +golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= -gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= -gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= -gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA= -gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= -gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= -gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= -gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= -gonum.org/v1/plot v0.10.1/go.mod h1:VZW5OlhkL1mysU9vaqNHnsy86inf6Ot+jB3r+BczCEo= +gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= +gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= -google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= -google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= -google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= -google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= -google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= -google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= -google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= -google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= -google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= -google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= -google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= -google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= -google.golang.org/api v0.77.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= -google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= -google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= -google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= -google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6FO2g= -google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= -google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= -google.golang.org/api v0.95.0/go.mod h1:eADj+UBuxkh5zlrSntJghuNeg8HwQ1w5lTKkuqaETEI= -google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.99.0/go.mod h1:1YOf74vkVndF7pG6hIHuINsM7eWwpVTAfNMNiL91A08= -google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= -google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo= -google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= -google.golang.org/api v0.106.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.107.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= -google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= -google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= -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/api v0.276.0 h1:nVArUtfLEihtW+b0DdcqRGK1xoEm2+ltAihyztq7MKY= +google.golang.org/api v0.276.0/go.mod h1:Fnag/EWUPIcJXuIkP1pjoTgS5vdxlk3eeemL7Do6bvw= 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= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= -google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= -google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= -google.golang.org/genproto v0.0.0-20220329172620-7be39ac1afc7/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220722212130-b98a9ff5e252/go.mod h1:GkXuJDJ6aQ7lnJcRF+SJVgFdQhypqgl3LB1C9vabdRE= -google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc= -google.golang.org/genproto v0.0.0-20220815135757-37a418bb8959/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220817144833-d7fd3f11b9b1/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220829144015-23454907ede3/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220829175752-36a9c930ecbf/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220913154956-18f8339a66a5/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220914142337-ca0e39ece12f/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220915135415-7fd63a7952de/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220916172020-2692e8806bfa/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220919141832-68c03719ef51/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar2npT/g4vkk7O0WYS1sHOHbdujxbEp7CJWbw= -google.golang.org/genproto v0.0.0-20220926165614-551eb538f295/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= -google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= -google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U= -google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= -google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= -google.golang.org/genproto v0.0.0-20221024153911-1573dae28c9c/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo= -google.golang.org/genproto v0.0.0-20221109142239-94d6d90a7d66/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221117204609-8f9c96812029/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221201204527-e3fa12d562f3/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE= -google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230112194545-e10362b5ecf9/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230113154510-dbe35b8444a5/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230123190316-2c411cf9d197/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230124163310-31e0e69b6fc2/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230125152338-dcaf20b6aeaa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230127162408-596548ed4efa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44/go.mod h1:8B0gmkoRebU8ukX6HP+4wrVQUY1+6PkQ44BSyIlflHA= -google.golang.org/genproto v0.0.0-20230222225845-10f96fb3dbec/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= -google.golang.org/genproto v0.0.0-20230223222841-637eb2293923/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= -google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA= -google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= -google.golang.org/genproto v0.0.0-20230320184635-7606e756e683/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= -google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= -google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 h1:ToEetK57OidYuqD4Q5w+vfEnPvPpuTwedCNVohYJfNk= -google.golang.org/genproto v0.0.0-20241118233622-e639e219e697/go.mod h1:JJrvXBWRZaFMxBufik1a4RpFw4HhgVtBBWQeQgUj2cc= -google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 h1:FiusG7LWj+4byqhbvmB+Q93B/mOxJLN2DTozDuZm4EU= -google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:kXqgZtrWaf6qS3jZOCnCH7WYfrvFjkC51bM8fz3RsCA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 h1:pFyd6EwwL2TqFf8emdthzeX+gZE1ElRq3iM8pui4KBY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto v0.0.0-20260414002931-afd174a4e478 h1:aLsVTW0lZ8+IY5u/ERjZSCvAmhuR7slKzyha3YikDNA= +google.golang.org/genproto v0.0.0-20260414002931-afd174a4e478/go.mod h1:YJAzKjfHIUHb9T+bfu8L7mthAp7VVXQBUs1PLdBWS7M= +google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 h1:yQugLulqltosq0B/f8l4w9VryjV+N/5gcW0jQ3N8Qec= +google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478/go.mod h1:C6ADNqOxbgdUUeRTU+LCHDPB9ttAMCTff6auwCVa4uc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 h1:RmoJA1ujG+/lRGNfUnOMfhCy5EipVMyvUE+KNbPbTlw= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= -google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= -google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= -google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= -google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= -google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4= -google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= +google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= +google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= 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= @@ -2541,13 +1511,10 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc= -google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= 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= @@ -2556,7 +1523,6 @@ gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8 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/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= -gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= 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= @@ -2584,59 +1550,18 @@ gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/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= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= -lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= -lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= -modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= -modernc.org/cc/v3 v3.36.2/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= -modernc.org/cc/v3 v3.36.3/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= -modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc= -modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw= -modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= -modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= -modernc.org/ccgo/v3 v3.16.8/go.mod h1:zNjwkizS+fIFDrDjIAgBSCLkWbJuHF+ar3QRn+Z9aws= -modernc.org/ccgo/v3 v3.16.9/go.mod h1:zNMzC9A9xeNUepy6KuZBbugn3c0Mc9TeiJO4lgvkJDo= -modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= -modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= -modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= -modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A= -modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU= -modernc.org/libc v1.16.17/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU= -modernc.org/libc v1.16.19/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= -modernc.org/libc v1.17.0/go.mod h1:XsgLldpP4aWlPlsjqKRdHPqCxCjISdHfM/yeWC5GyW0= -modernc.org/libc v1.17.1/go.mod h1:FZ23b+8LjxZs7XtFMbSzL/EhPxNbfZbErxEHc7cbD9s= -modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= -modernc.org/memory v1.2.0/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= -modernc.org/memory v1.2.1/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= -modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= -modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= -modernc.org/sqlite v1.18.1/go.mod h1:6ho+Gow7oX5V+OiOQ6Tr4xeqbx13UZ6t+Fw9IRUG4d4= -modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= -modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= -modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw= -modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= -modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8= +lukechampine.com/blake3 v1.4.1 h1:I3Smz7gso8w4/TunLKec6K2fn+kyKtDxr/xcQEN84Wg= +lukechampine.com/blake3 v1.4.1/go.mod h1:QFosUxmjB8mnrWFSNwKmvxHpfY72bmD2tQ0kBMM3kwo= 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/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +nhooyr.io/websocket v1.8.17 h1:KEVeLJkUywCKVsnLIDlD/5gtayKp8VoCkksHCGGfT9Y= +nhooyr.io/websocket v1.8.17/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c= +pgregory.net/rapid v1.3.0 h1:vBvO0VSqti75J1jjYqpgPNBLKMd1+gxa9fYo7vk/Exc= +pgregory.net/rapid v1.3.0/go.mod h1:dPlE4OBBxgXPqkP79flB6sJL1dx5azpI7HQ9MY9Z7uk= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/qr v0.2.0 h1:6vBLea5/NRMVTz8V66gipeLycZMl/+UlFmk8DvqQ6WY= rsc.io/qr v0.2.0/go.mod h1:IF+uZjkb9fqyeF/4tlBoynqmQxUoPfWEKh921coOuXs= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= diff --git a/ibc/interfaces.go b/ibc/interfaces.go index b0198ac4..e108c780 100644 --- a/ibc/interfaces.go +++ b/ibc/interfaces.go @@ -3,7 +3,8 @@ package ibc import ( cmtbytes "github.com/cometbft/cometbft/libs/bytes" - ibctypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" + ibctypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + ibcexported "github.com/cosmos/ibc-go/v11/modules/core/exported" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -11,3 +12,19 @@ import ( type TransferKeeper interface { GetDenom(ctx sdk.Context, denomHash cmtbytes.HexBytes) (ibctypes.Denom, bool) } + +type ClientKeeper interface { + // VerifyMembership retrieves the light client module for the clientID and verifies the proof of the existence of a key-value pair at a specified height. + VerifyMembership(ctx sdk.Context, clientID string, height ibcexported.Height, delayTimePeriod uint64, delayBlockPeriod uint64, proof []byte, path ibcexported.Path, value []byte) error + // VerifyNonMembership retrieves the light client module for the clientID and verifies the absence of a given key at a specified height. + VerifyNonMembership(ctx sdk.Context, clientID string, height ibcexported.Height, delayTimePeriod uint64, delayBlockPeriod uint64, proof []byte, path ibcexported.Path) error + // UpdateClient updates the light client state with a new header + UpdateClient(ctx sdk.Context, clientID string, clientMsg ibcexported.ClientMessage) error + // GetClientStatus returns the status of a client given the client ID + GetClientStatus(ctx sdk.Context, clientID string) ibcexported.Status + // GetClientTimestampAtHeight returns the timestamp for a given height on the client + // given its client ID and height + GetClientTimestampAtHeight(ctx sdk.Context, clientID string, height ibcexported.Height) (uint64, error) + // GetClientState gets a particular client from the store + GetClientState(ctx sdk.Context, clientID string) (ibcexported.ClientState, bool) +} diff --git a/ibc/module.go b/ibc/module.go index f3d898cd..67af57c3 100644 --- a/ibc/module.go +++ b/ibc/module.go @@ -1,9 +1,9 @@ package ibc import ( - channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types" - porttypes "github.com/cosmos/ibc-go/v10/modules/core/05-port/types" - "github.com/cosmos/ibc-go/v10/modules/core/exported" + channeltypes "github.com/cosmos/ibc-go/v11/modules/core/04-channel/types" + porttypes "github.com/cosmos/ibc-go/v11/modules/core/05-port/types" + "github.com/cosmos/ibc-go/v11/modules/core/exported" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -133,3 +133,7 @@ func (im Module) UnmarshalPacketData(ctx sdk.Context, portID string, channelID s } return pd.UnmarshalPacketData(ctx, portID, channelID, bz) } + +func (im Module) SetICS4Wrapper(wrapper porttypes.ICS4Wrapper) { + im.app.SetICS4Wrapper(wrapper) +} diff --git a/ibc/module_test.go b/ibc/module_test.go index 4515dad8..f97fb92a 100644 --- a/ibc/module_test.go +++ b/ibc/module_test.go @@ -7,10 +7,10 @@ import ( "github.com/stretchr/testify/require" cosmosevmibc "github.com/cosmos/evm/ibc" - transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types" - porttypes "github.com/cosmos/ibc-go/v10/modules/core/05-port/types" - "github.com/cosmos/ibc-go/v10/modules/core/exported" + transfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + channeltypes "github.com/cosmos/ibc-go/v11/modules/core/04-channel/types" + porttypes "github.com/cosmos/ibc-go/v11/modules/core/05-port/types" + "github.com/cosmos/ibc-go/v11/modules/core/exported" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -27,9 +27,7 @@ type MockIBCModule struct { // It calls the underlying app's OnChanOpenInit callback. // // and escaping revive for unused parameters which are okay since they indicate the expected mocked interface -// -//nolint:all // escaping govet since we can copy locks here as it is a test -func (m MockIBCModule) OnChanOpenInit( +func (m *MockIBCModule) OnChanOpenInit( ctx sdk.Context, order channeltypes.Order, connectionHops []string, @@ -46,9 +44,7 @@ func (m MockIBCModule) OnChanOpenInit( // It calls the underlying app's OnChanOpenTry callback. // // and escaping revive for unused parameters which are okay since they indicate the expected mocked interface -// -//nolint:all // escaping govet since we can copy locks here as it is a test -func (m MockIBCModule) OnChanOpenTry( +func (m *MockIBCModule) OnChanOpenTry( ctx sdk.Context, order channeltypes.Order, connectionHops []string, @@ -65,9 +61,7 @@ func (m MockIBCModule) OnChanOpenTry( // It calls the underlying app's OnChanOpenAck callback. // // and escaping revive for unused parameters which are okay since they indicate the expected mocked interface -// -//nolint:all // escaping govet since we can copy locks here as it is a test -func (m MockIBCModule) OnChanOpenAck( +func (m *MockIBCModule) OnChanOpenAck( ctx sdk.Context, portID, channelID, @@ -82,9 +76,7 @@ func (m MockIBCModule) OnChanOpenAck( // It calls the underlying app's OnChanOpenConfirm callback. // // and escaping revive for unused parameters which are okay since they indicate the expected mocked interface -// -//nolint:all // escaping govet since we can copy locks here as it is a test -func (m MockIBCModule) OnChanOpenConfirm( +func (m *MockIBCModule) OnChanOpenConfirm( ctx sdk.Context, portID, channelID string, @@ -97,9 +89,7 @@ func (m MockIBCModule) OnChanOpenConfirm( // It calls the underlying app's OnChanCloseInit callback. // // and escaping revive for unused parameters which are okay since they indicate the expected mocked interface -// -//nolint:all // escaping govet since we can copy locks here as it is a test -func (m MockIBCModule) OnChanCloseInit( +func (m *MockIBCModule) OnChanCloseInit( ctx sdk.Context, portID, channelID string, @@ -112,9 +102,7 @@ func (m MockIBCModule) OnChanCloseInit( // It calls the underlying app's OnChanCloseConfirm callback. // // and escaping revive for unused parameters which are okay since they indicate the expected mocked interface -// -//nolint:all // escaping govet since we can copy locks here as it is a test -func (m MockIBCModule) OnChanCloseConfirm( +func (m *MockIBCModule) OnChanCloseConfirm( ctx sdk.Context, portID, channelID string, @@ -127,9 +115,7 @@ func (m MockIBCModule) OnChanCloseConfirm( // It calls the underlying app's OnRecvPacket callback. // // and escaping revive for unused parameters which are okay since they indicate the expected mocked interface -// -//nolint:all // escaping govet since we can copy locks here as it is a test -func (m MockIBCModule) OnRecvPacket( +func (m *MockIBCModule) OnRecvPacket( ctx sdk.Context, channelVersion string, packet channeltypes.Packet, @@ -143,9 +129,7 @@ func (m MockIBCModule) OnRecvPacket( // It calls the underlying app's OnAcknowledgementPacket callback. // // and escaping revive for unused parameters which are okay since they indicate the expected mocked interface -// -//nolint:all // escaping govet since we can copy locks here as it is a test -func (m MockIBCModule) OnAcknowledgementPacket( +func (m *MockIBCModule) OnAcknowledgementPacket( ctx sdk.Context, channelVersion string, packet channeltypes.Packet, @@ -160,9 +144,7 @@ func (m MockIBCModule) OnAcknowledgementPacket( // It calls the underlying app's OnTimeoutPacket callback. // // and escaping revive for unused parameters which are okay since they indicate the expected mocked interface -// -//nolint:all // escaping govet since we can copy locks here as it is a test -func (m MockIBCModule) OnTimeoutPacket( +func (m *MockIBCModule) OnTimeoutPacket( ctx sdk.Context, channelVersion string, packet channeltypes.Packet, @@ -172,6 +154,8 @@ func (m MockIBCModule) OnTimeoutPacket( return args.Error(0) } +func (m *MockIBCModule) SetICS4Wrapper(wrapper porttypes.ICS4Wrapper) {} + func TestModule(t *testing.T) { mockModule := &MockIBCModule{} mockModule.On("OnChanOpenInit").Return(nil) @@ -183,6 +167,7 @@ func TestModule(t *testing.T) { mockModule.On("OnRecvPacket").Return(channeltypes.NewResultAcknowledgement([]byte("ack"))) mockModule.On("OnAcknowledgementPacket").Return(nil) mockModule.On("OnTimeoutPacket").Return(nil) + mockModule.On("SetICS4Wrapper").Return() module := cosmosevmibc.NewModule(mockModule) @@ -205,4 +190,5 @@ func TestModule(t *testing.T) { require.NoError(t, err) err = module.OnTimeoutPacket(sdk.Context{}, "", channeltypes.Packet{}, nil) require.NoError(t, err) + module.SetICS4Wrapper(nil) } diff --git a/ibc/utils.go b/ibc/utils.go index 45c68139..c71ccb20 100644 --- a/ibc/utils.go +++ b/ibc/utils.go @@ -3,8 +3,8 @@ package ibc import ( "strings" - transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types" + transfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + channeltypes "github.com/cosmos/ibc-go/v11/modules/core/04-channel/types" errorsmod "cosmossdk.io/errors" "cosmossdk.io/math" diff --git a/ibc/utils_test.go b/ibc/utils_test.go index 1ae3bd22..dde86719 100644 --- a/ibc/utils_test.go +++ b/ibc/utils_test.go @@ -8,9 +8,9 @@ import ( cosmosevmibc "github.com/cosmos/evm/ibc" precompilestestutil "github.com/cosmos/evm/precompiles/testutil" testconstants "github.com/cosmos/evm/testutil/constants" - transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types" - ibctesting "github.com/cosmos/ibc-go/v10/testing" + transfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + channeltypes "github.com/cosmos/ibc-go/v11/modules/core/04-channel/types" + ibctesting "github.com/cosmos/ibc-go/v11/testing" "cosmossdk.io/math" diff --git a/indexer/kv_indexer.go b/indexer/kv_indexer.go index 9bf85ccd..b63f68ae 100644 --- a/indexer/kv_indexer.go +++ b/indexer/kv_indexer.go @@ -14,7 +14,7 @@ import ( evmtypes "github.com/cosmos/evm/x/vm/types" errorsmod "cosmossdk.io/errors" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" @@ -59,7 +59,7 @@ func (kv *KVIndexer) IndexBlock(block *cmttypes.Block, txResults []*abci.ExecTxR var ethTxIndex int32 for txIndex, tx := range block.Txs { result := txResults[txIndex] - if !rpctypes.TxSucessOrExpectedFailure(result) { + if !evmtypes.TxSucessOrExpectedFailure(result) { continue } diff --git a/interfaces.go b/interfaces.go index ecebf7e1..6a233f2b 100644 --- a/interfaces.go +++ b/interfaces.go @@ -6,59 +6,254 @@ import ( erc20keeper "github.com/cosmos/evm/x/erc20/keeper" feemarketkeeper "github.com/cosmos/evm/x/feemarket/keeper" "github.com/cosmos/evm/x/ibc/callbacks/keeper" - transferkeeper "github.com/cosmos/evm/x/ibc/transfer/keeper" - precisebankkeeper "github.com/cosmos/evm/x/precisebank/keeper" evmkeeper "github.com/cosmos/evm/x/vm/keeper" - ibctesting "github.com/cosmos/ibc-go/v10/testing" - - storetypes "cosmossdk.io/store/types" - evidencekeeper "cosmossdk.io/x/evidence/keeper" - feegrantkeeper "cosmossdk.io/x/feegrant/keeper" + transferkeeper "github.com/cosmos/ibc-go/v11/modules/apps/transfer/keeper" + ibckeeper "github.com/cosmos/ibc-go/v11/modules/core/keeper" + ibctesting "github.com/cosmos/ibc-go/v11/testing" "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/runtime" + servertypes "github.com/cosmos/cosmos-sdk/server/types" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/mempool" authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" - authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper" bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" consensusparamkeeper "github.com/cosmos/cosmos-sdk/x/consensus/keeper" distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" + evidencekeeper "github.com/cosmos/cosmos-sdk/x/evidence/keeper" + feegrantkeeper "github.com/cosmos/cosmos-sdk/x/feegrant/keeper" govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper" slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" ) -// EvmApp defines the interface for an EVM application. -type EvmApp interface { //nolint:revive - ibctesting.TestingApp +// TestApp captures the minimal functionality all test harnesses require. +type TestApp interface { + servertypes.Application runtime.AppI InterfaceRegistry() types.InterfaceRegistry + AppCodec() codec.Codec + GetTxConfig() client.TxConfig + LegacyAmino() *codec.LegacyAmino ChainID() string - GetEVMKeeper() *evmkeeper.Keeper - GetErc20Keeper() *erc20keeper.Keeper - SetErc20Keeper(erc20keeper.Keeper) - GetGovKeeper() govkeeper.Keeper - GetSlashingKeeper() slashingkeeper.Keeper - GetEvidenceKeeper() *evidencekeeper.Keeper - GetBankKeeper() bankkeeper.Keeper - GetFeeMarketKeeper() *feemarketkeeper.Keeper - GetAccountKeeper() authkeeper.AccountKeeper - GetAuthzKeeper() authzkeeper.Keeper - GetDistrKeeper() distrkeeper.Keeper - GetStakingKeeper() *stakingkeeper.Keeper - GetMintKeeper() mintkeeper.Keeper - GetPreciseBankKeeper() *precisebankkeeper.Keeper - GetFeeGrantKeeper() feegrantkeeper.Keeper - GetConsensusParamsKeeper() consensusparamkeeper.Keeper - GetCallbackKeeper() keeper.ContractKeeper - GetTransferKeeper() transferkeeper.Keeper - SetTransferKeeper(transferKeeper transferkeeper.Keeper) DefaultGenesis() map[string]json.RawMessage GetKey(storeKey string) *storetypes.KVStoreKey + GetBaseApp() *baseapp.BaseApp + LastCommitID() storetypes.CommitID + LastBlockHeight() int64 GetAnteHandler() sdk.AnteHandler MsgServiceRouter() *baseapp.MsgServiceRouter GetMempool() mempool.ExtMempool + + // keeper getters + VMKeeperProvider + BankKeeperProvider + StakingKeeperProvider } + +// EvmApp defines the interface for an EVM application. +type EvmApp interface { //nolint:revive + TestApp + AccountKeeperProvider + AnteHandlerProvider + CallbackKeeperProvider + ConsensusParamsKeeperProvider + DistrKeeperProvider + EvidenceKeeperProvider + Erc20KeeperProvider + Erc20KeeperSetter + FeeGrantKeeperProvider + FeeMarketKeeperProvider + GovKeeperProvider + KeyProvider + MempoolProvider + MintKeeperProvider + MsgServiceRouterProvider + SlashingKeeperProvider + TransferKeeperProvider + TransferKeeperSetter +} + +// Keeper provider interfaces allow tests to depend on the exact subset of +// keepers they need without requiring a fully fledged evmd application. +type ( + AccountKeeperProvider interface { + GetAccountKeeper() authkeeper.AccountKeeper + } + AnteHandlerProvider interface { + GetAnteHandler() sdk.AnteHandler + } + BankKeeperProvider interface { + GetBankKeeper() bankkeeper.Keeper + } + CallbackKeeperProvider interface { + GetCallbackKeeper() keeper.ContractKeeper + } + ChainIDProvider interface { + ChainID() string + } + ConsensusParamsKeeperProvider interface { + GetConsensusParamsKeeper() consensusparamkeeper.Keeper + } + DistrKeeperProvider interface { + GetDistrKeeper() distrkeeper.Keeper + } + EvidenceKeeperProvider interface { + GetEvidenceKeeper() *evidencekeeper.Keeper + } + VMKeeperProvider interface { + GetEVMKeeper() *evmkeeper.Keeper + } + IBCKeeperProvider interface { + GetIBCKeeper() *ibckeeper.Keeper + } + Erc20KeeperProvider interface { + GetErc20Keeper() *erc20keeper.Keeper + } + Erc20KeeperSetter interface { + SetErc20Keeper(erc20keeper.Keeper) + } + FeeGrantKeeperProvider interface { + GetFeeGrantKeeper() feegrantkeeper.Keeper + } + FeeMarketKeeperProvider interface { + GetFeeMarketKeeper() *feemarketkeeper.Keeper + } + GovKeeperProvider interface { + GetGovKeeper() govkeeper.Keeper + } + KeyProvider interface { + GetKey(storeKey string) *storetypes.KVStoreKey + } + MempoolProvider interface { + GetMempool() mempool.ExtMempool + } + MintKeeperProvider interface { + GetMintKeeper() mintkeeper.Keeper + } + MsgServiceRouterProvider interface { + MsgServiceRouter() *baseapp.MsgServiceRouter + } + SlashingKeeperProvider interface { + GetSlashingKeeper() slashingkeeper.Keeper + } + StakingKeeperProvider interface { + GetStakingKeeper() *stakingkeeper.Keeper + } + TransferKeeperProvider interface { + GetTransferKeeper() *transferkeeper.Keeper + } + TransferKeeperSetter interface { + SetTransferKeeper(*transferkeeper.Keeper) + } +) + +type ( + IBCTestApp interface { + TestApp + ibctesting.TestingApp + } + IBCApp interface { + EvmApp + IBCKeeperProvider + } + // Precompile-focused application interfaces describe the exact keepers that a + // given precompile test suite requires. External chains can implement only the + // interfaces relevant to the suites they wish to run. + BankPrecompileApp interface { + TestApp + BankKeeperProvider + Erc20KeeperProvider + } + Bech32PrecompileApp interface { + TestApp + } + DistributionPrecompileApp interface { + TestApp + DistrKeeperProvider + StakingKeeperProvider + } + Erc20PrecompileApp interface { + TestApp + AccountKeeperProvider + BankKeeperProvider + Erc20KeeperProvider + TransferKeeperProvider + } + GovPrecompileApp interface { + TestApp + GovKeeperProvider + } + ICS20PrecompileApp interface { + TestApp + ChainIDProvider + BankKeeperProvider + StakingKeeperProvider + TransferKeeperProvider + IBCKeeperProvider + } + P256PrecompileApp interface { + TestApp + } + SlashingPrecompileApp interface { + TestApp + SlashingKeeperProvider + StakingKeeperProvider + } + StakingPrecompileApp interface { + TestApp + AccountKeeperProvider + BankKeeperProvider + StakingKeeperProvider + } + WERC20PrecompileApp interface { + TestApp + BankKeeperProvider + Erc20KeeperProvider + TransferKeeperProvider + } + + // Base interface required by the integration network helpers. Any app used by + // evm/testutil/integration must satisfy these keeper providers so the shared + // network setup can access the necessary modules. + IntegrationNetworkApp interface { + TestApp + AccountKeeperProvider + DistrKeeperProvider + Erc20KeeperProvider + FeeMarketKeeperProvider + GovKeeperProvider + MintKeeperProvider + SlashingKeeperProvider + EvidenceKeeperProvider + } + Erc20IntegrationApp interface { + IntegrationNetworkApp + TransferKeeperProvider + IBCKeeperProvider + } + VMIntegrationApp interface { + IntegrationNetworkApp + ConsensusParamsKeeperProvider + } + AnteIntegrationApp interface { + IntegrationNetworkApp + FeeGrantKeeperProvider + IBCKeeperProvider + } + IBCIntegrationApp interface { + IntegrationNetworkApp + TransferKeeperProvider + IBCKeeperProvider + } + IBCCallbackIntegrationApp interface { + IntegrationNetworkApp + CallbackKeeperProvider + IBCKeeperProvider + } +) diff --git a/local_node.sh b/local_node.sh index a7e41082..b0725efb 100755 --- a/local_node.sh +++ b/local_node.sh @@ -266,6 +266,7 @@ if [[ $overwrite == "y" || $overwrite == "Y" ]]; then sed -i.bak 's/timeout_precommit_delta = "500ms"/timeout_precommit_delta = "200ms"/g' "$CONFIG_TOML" sed -i.bak 's/timeout_commit = "5s"/timeout_commit = "1s"/g' "$CONFIG_TOML" sed -i.bak 's/timeout_broadcast_tx_commit = "10s"/timeout_broadcast_tx_commit = "5s"/g' "$CONFIG_TOML" + sed -i.bak 's/type = "flood"/type = "app"/g' "$CONFIG_TOML" # enable prometheus metrics and all APIs for dev node sed -i.bak 's/prometheus = false/prometheus = true/' "$CONFIG_TOML" diff --git a/mempool/blockchain.go b/mempool/blockchain.go index 72b434f3..2c49042d 100644 --- a/mempool/blockchain.go +++ b/mempool/blockchain.go @@ -4,6 +4,7 @@ import ( "fmt" "math/big" "sync" + "sync/atomic" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" @@ -18,9 +19,9 @@ import ( evmtypes "github.com/cosmos/evm/x/vm/types" sdkerrors "cosmossdk.io/errors" - "cosmossdk.io/log" - sdktypes "cosmossdk.io/store/types" + "cosmossdk.io/log/v2" + sdktypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -44,6 +45,9 @@ type Blockchain struct { previousHeaderHash common.Hash latestCtx sdk.Context mu sync.RWMutex + coinInfo atomic.Pointer[evmtypes.EvmCoinInfo] + + testingCommitMu sync.RWMutex } // NewBlockchain creates a new Blockchain instance that bridges Cosmos SDK state with Ethereum mempools. @@ -81,7 +85,7 @@ 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.GetLatestContext() + ctx, err := b.newLatestContext() if err != nil { return b.zeroHeader } @@ -211,13 +215,34 @@ func (b *Blockchain) StateAt(hash common.Hash) (vm.StateDB, error) { 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()) + // Create a cache context to isolate the StateDB from concurrent commits. + // This prevents race conditions when the background txpool reorg goroutine + // reads state while the main thread is committing new blocks. + cacheCtx, _ := ctx.CacheContext() + // Use an infinite gas meter to avoid tracking gas for read-only state queries + cacheCtx = cacheCtx.WithGasMeter(sdktypes.NewInfiniteGasMeter()) + + appHash := cacheCtx.BlockHeader().AppHash + stateDB := statedb.New(cacheCtx, b.vmKeeper, statedb.NewEmptyTxConfig()) b.logger.Debug("StateDB created successfully", "app_hash", common.Hash(appHash).Hex()) return stateDB, nil } +// BeginCommit acquires an exclusive lock to prevent mempool state reads during Commit. +// This avoids data races in the underlying storage (e.g., IAVL) when tests run with -race. +func (b *Blockchain) BeginCommit() { b.testingCommitMu.Lock() } + +// EndCommit releases the exclusive lock acquired by BeginCommit. +func (b *Blockchain) EndCommit() { b.testingCommitMu.Unlock() } + +// BeginRead acquires a shared lock for background readers (e.g., txpool reorg). +// This enables optional coordination with Commit without importing the type. +func (b *Blockchain) BeginRead() { b.testingCommitMu.RLock() } + +// EndRead releases the shared read lock acquired by BeginRead. +func (b *Blockchain) EndRead() { b.testingCommitMu.RUnlock() } + func (b *Blockchain) getPreviousHeaderHash() common.Hash { b.mu.RLock() defer b.mu.RUnlock() @@ -268,3 +293,31 @@ func (b *Blockchain) newLatestContext() (sdk.Context, error) { return ctx, nil } + +// GetCoinDenom returns the coin denom used in the EVM. +// Note: return "" if height=0. +func (b *Blockchain) GetCoinDenom() string { + coinInfo, err := b.getEvmCoinInfo() + if err != nil { + b.logger.Error("Failed to get evm coin info", "error", err) + return "" + } + + return coinInfo.Denom +} + +func (b *Blockchain) getEvmCoinInfo() (*evmtypes.EvmCoinInfo, error) { + if coin := b.coinInfo.Load(); coin != nil { + return coin, nil + } + + ctx, err := b.GetLatestContext() + if err != nil { + return nil, err + } + + coinInfo := b.vmKeeper.GetEvmCoinInfo(ctx) + b.coinInfo.Store(&coinInfo) + + return &coinInfo, nil +} diff --git a/mempool/blockchain_test.go b/mempool/blockchain_test.go index 6e076867..ffc7f25d 100644 --- a/mempool/blockchain_test.go +++ b/mempool/blockchain_test.go @@ -12,24 +12,31 @@ import ( cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" - "github.com/cosmos/evm/config" "github.com/cosmos/evm/mempool" "github.com/cosmos/evm/mempool/mocks" + "github.com/cosmos/evm/testutil/constants" "github.com/cosmos/evm/x/vm/statedb" vmtypes "github.com/cosmos/evm/x/vm/types" - "cosmossdk.io/log" - storetypes "cosmossdk.io/store/types" + "cosmossdk.io/log/v2" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" + "github.com/cosmos/cosmos-sdk/testutil" sdk "github.com/cosmos/cosmos-sdk/types" ) -// createMockContext creates a basic mock context for testing +// createMockContext creates a basic mock context for testing with multistore func createMockContext() sdk.Context { - return sdk.Context{}. + // crate ctx with multistore so that CacheContext() can be used + storeKey := storetypes.NewKVStoreKey("test") + transientKey := storetypes.NewTransientStoreKey("transient_test") + ctx := testutil.DefaultContext(storeKey, transientKey) + + return ctx. WithBlockTime(time.Now()). WithBlockHeader(cmtproto.Header{AppHash: []byte("00000000000000000000000000000000")}). - WithBlockHeight(1) + WithBlockHeight(1). + WithEventManager(sdk.NewEventManager()) } // TestBlockchainRaceCondition tests concurrent access to NotifyNewBlock and StateAt @@ -38,10 +45,10 @@ func TestBlockchainRaceCondition(t *testing.T) { logger := log.NewNopLogger() // Create mock keepers using generated mocks - mockVMKeeper := mocks.NewVMKeeper(t) + mockVMKeeper := mocks.NewVMKeeperI(t) mockFeeMarketKeeper := mocks.NewFeeMarketKeeper(t) - ethCfg := vmtypes.DefaultChainConfig(config.EighteenDecimalsChainID) + ethCfg := vmtypes.DefaultChainConfig(constants.EighteenDecimalsChainID) if err := vmtypes.SetChainConfig(ethCfg); err != nil { panic(err) } @@ -57,9 +64,6 @@ func TestBlockchainRaceCondition(t *testing.T) { mockVMKeeper.On("ForEachStorage", mock.Anything, common.Address{}, mock.AnythingOfType("func(common.Hash, common.Hash) bool")).Maybe() mockVMKeeper.On("KVStoreKeys").Return(make(map[string]*storetypes.KVStoreKey)).Maybe() - err := vmtypes.NewEVMConfigurator().WithEVMCoinInfo(config.ChainsCoinInfo[config.EighteenDecimalsChainID]).Configure() - require.NoError(t, err) - // Mock context callback that returns a valid context getCtxCallback := func(height int64, prove bool) (sdk.Context, error) { return createMockContext(), nil diff --git a/mempool/check_tx.go b/mempool/check_tx.go deleted file mode 100644 index f42a024f..00000000 --- a/mempool/check_tx.go +++ /dev/null @@ -1,40 +0,0 @@ -package mempool - -import ( - "errors" - - abci "github.com/cometbft/cometbft/abci/types" - - "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" -) - -// NewCheckTxHandler creates a CheckTx handler that integrates with the EVM mempool for transaction validation. -// It wraps the standard transaction execution flow to handle EVM-specific nonce gap errors by routing -// transactions with higher tx sequence numbers to the mempool for potential future execution. -// Returns a handler function that processes ABCI CheckTx requests and manages EVM transaction sequencing. -func NewCheckTxHandler(mempool *ExperimentalEVMMempool) types.CheckTxHandler { - return func(runTx types.RunTx, request *abci.RequestCheckTx) (*abci.ResponseCheckTx, error) { - 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) || errors.Is(err, ErrNonceLow) { - // send it to the mempool for further triage - err := mempool.InsertInvalidNonce(request.Tx) - if err != nil { - return sdkerrors.ResponseCheckTxWithEvents(err, gInfo.GasWanted, gInfo.GasUsed, anteEvents, false), nil - } - } - // anything else, return regular error - return sdkerrors.ResponseCheckTxWithEvents(err, gInfo.GasWanted, gInfo.GasUsed, anteEvents, false), nil - } - - return &abci.ResponseCheckTx{ - GasWanted: int64(gInfo.GasWanted), // #nosec G115 -- this is copied from the Cosmos SDK - GasUsed: int64(gInfo.GasUsed), // #nosec G115 -- this is copied from the Cosmos SDK - Log: result.Log, - Data: result.Data, - Events: types.MarkEventsToIndex(result.Events, nil), - }, nil - } -} diff --git a/mempool/cosmos_ordering.go b/mempool/cosmos_ordering.go new file mode 100644 index 00000000..991c41c1 --- /dev/null +++ b/mempool/cosmos_ordering.go @@ -0,0 +1,174 @@ +package mempool + +import ( + "container/heap" + "strings" + + "github.com/holiman/uint256" + + cmath "cosmossdk.io/math" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkmempool "github.com/cosmos/cosmos-sdk/types/mempool" +) + +type cosmosTxWithPriority struct { + tx cosmosTxWithMetadata + signerKey string + fee *uint256.Int +} + +type cosmosTxByPriceAndNonce []*cosmosTxWithPriority + +func (h cosmosTxByPriceAndNonce) Len() int { return len(h) } + +func (h cosmosTxByPriceAndNonce) Less(i, j int) bool { + cmp := h[i].fee.Cmp(h[j].fee) + if cmp == 0 { + cmp = strings.Compare(h[i].signerKey, h[j].signerKey) + if cmp == 0 { + return compareCosmosTxWithMetadata(h[i].tx, h[j].tx) < 0 + } + return cmp < 0 + } + return cmp > 0 +} + +func (h cosmosTxByPriceAndNonce) Swap(i, j int) { h[i], h[j] = h[j], h[i] } + +func (h *cosmosTxByPriceAndNonce) Push(x any) { + *h = append(*h, x.(*cosmosTxWithPriority)) +} + +func (h *cosmosTxByPriceAndNonce) Pop() any { + old := *h + n := len(old) + item := old[n-1] + old[n-1] = nil + *h = old[:n-1] + return item +} + +// CosmosTransactionsByPriceAndNonce returns Cosmos transactions in fee-priority +// order while still honoring nonce ordering within each signer bucket. +type CosmosTransactionsByPriceAndNonce struct { + txs map[string][]cosmosTxWithMetadata + heads cosmosTxByPriceAndNonce + bondDenom string + baseFee *uint256.Int +} + +func NewCosmosTransactionsByPriceAndNonce( + txs map[string][]cosmosTxWithMetadata, + bondDenom string, + baseFee *uint256.Int, +) sdkmempool.Iterator { + heads := make(cosmosTxByPriceAndNonce, 0, len(txs)) + for signerKey, bucket := range txs { + if len(bucket) == 0 { + delete(txs, signerKey) + continue + } + + heads = append(heads, &cosmosTxWithPriority{ + tx: bucket[0], + signerKey: signerKey, + fee: extractCosmosEffectiveTip(bucket[0].tx, bondDenom, baseFee), + }) + txs[signerKey] = bucket[1:] + } + + if len(heads) == 0 { + return nil + } + + heap.Init(&heads) + return &CosmosTransactionsByPriceAndNonce{ + txs: txs, + heads: heads, + bondDenom: bondDenom, + baseFee: baseFee, + } +} + +func (t *CosmosTransactionsByPriceAndNonce) Tx() sdk.Tx { + if len(t.heads) == 0 { + return nil + } + return t.heads[0].tx.tx +} + +func (t *CosmosTransactionsByPriceAndNonce) Next() sdkmempool.Iterator { + if len(t.heads) == 0 { + return nil + } + + signerKey := t.heads[0].signerKey + if bucket := t.txs[signerKey]; len(bucket) > 0 { + t.heads[0] = &cosmosTxWithPriority{ + tx: bucket[0], + signerKey: signerKey, + fee: extractCosmosEffectiveTip(bucket[0].tx, t.bondDenom, t.baseFee), + } + t.txs[signerKey] = bucket[1:] + heap.Fix(&t.heads, 0) + } else { + heap.Pop(&t.heads) + } + + if len(t.heads) == 0 { + return nil + } + return t +} + +func (s *CosmosTxStore) OrderedIterator(bondDenom string, baseFee *uint256.Int) sdkmempool.Iterator { + s.mu.RLock() + defer s.mu.RUnlock() + + if len(s.txs) == 0 { + return nil + } + + snapshot := make(map[string][]cosmosTxWithMetadata, len(s.txs)) + for signerKey, bucket := range s.txs { + snapshot[signerKey] = append([]cosmosTxWithMetadata(nil), bucket.txs...) + } + + return NewCosmosTransactionsByPriceAndNonce(snapshot, bondDenom, baseFee) +} + +func extractCosmosEffectiveTip(tx sdk.Tx, bondDenom string, baseFee *uint256.Int) *uint256.Int { + feeTx, ok := tx.(sdk.FeeTx) + if !ok { + return uint256.NewInt(0) + } + + bondDenomFeeAmount := cmath.ZeroInt() + fees := feeTx.GetFee() + for _, coin := range fees { + if coin.Denom == bondDenom { + bondDenomFeeAmount = coin.Amount + } + } + + gas := feeTx.GetGas() + if gas == 0 { + return uint256.NewInt(0) + } + + gasPrice, overflow := uint256.FromBig(bondDenomFeeAmount.Quo(cmath.NewIntFromUint64(gas)).BigInt()) + if overflow { + return uint256.NewInt(0) + } + + if baseFee == nil { + return gasPrice + } + + if gasPrice.Cmp(baseFee) < 0 { + return uint256.NewInt(0) + } + + return new(uint256.Int).Sub(gasPrice, baseFee) +} diff --git a/mempool/encoding.go b/mempool/encoding.go new file mode 100644 index 00000000..b43c82d5 --- /dev/null +++ b/mempool/encoding.go @@ -0,0 +1,52 @@ +package mempool + +import ( + "fmt" + + ethtypes "github.com/ethereum/go-ethereum/core/types" + + evmtypes "github.com/cosmos/evm/x/vm/types" + + "github.com/cosmos/cosmos-sdk/client" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type TxEncoder struct { + txConfig client.TxConfig +} + +func NewTxEncoder(txConfig client.TxConfig) *TxEncoder { + return &TxEncoder{txConfig: txConfig} +} + +// EncodeEVMTx encodes an evm tx to its sdk representation as bytes. +func (e *TxEncoder) EVMTx(tx *ethtypes.Transaction) ([]byte, error) { + cosmosTx, err := e.EVMTxToCosmosTx(tx) + if err != nil { + return nil, err + } + return e.CosmosTx(cosmosTx) +} + +// EncodeCosmosTx encodes a cosmos tx to bytes. +func (e *TxEncoder) CosmosTx(tx sdk.Tx) ([]byte, error) { + return e.txConfig.TxEncoder()(tx) +} + +// EVMTxToCosmosTx converts an evm transaction to a cosmos transaction +func (e *TxEncoder) EVMTxToCosmosTx(tx *ethtypes.Transaction) (sdk.Tx, error) { + // Create MsgEthereumTx from the eth transaction + var msg evmtypes.MsgEthereumTx + signer := ethtypes.LatestSigner(evmtypes.GetEthChainConfig()) + if err := msg.FromSignedEthereumTx(tx, signer); err != nil { + return nil, fmt.Errorf("populating MsgEthereumTx from signed eth tx: %w", err) + } + + // Build cosmos tx + txBuilder := e.txConfig.NewTxBuilder() + cosmosTx, err := msg.BuildTx(txBuilder, evmtypes.GetEVMCoinDenom()) + if err != nil { + return nil, fmt.Errorf("failed to build cosmos tx from evm tx: %w", err) + } + return cosmosTx, nil +} diff --git a/mempool/errors.go b/mempool/errors.go index f42ddc53..01794211 100644 --- a/mempool/errors.go +++ b/mempool/errors.go @@ -1,12 +1,20 @@ package mempool -import "errors" +import ( + "errors" + + "github.com/cosmos/evm/mempool/internal/queue" +) var ( - ErrNoMessages = errors.New("transaction has no messages") - ErrExpectedOneMessage = errors.New("expected 1 message") - 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") + ErrNoMessages = errors.New("transaction has no messages") + ErrExpectedOneMessage = errors.New("expected 1 message") + ErrExpectedOneError = errors.New("expected 1 error") + ErrNotEVMTransaction = errors.New("transaction is not an EVM transaction") + ErrMultiMsgEthereumTransaction = errors.New("transaction contains multiple messages with an EVM msg") + ErrNonceGap = errors.New("tx nonce is higher than account nonce") + ErrNonceLow = errors.New("tx nonce is lower than account nonce") + // ErrQueueFull is aliased from the internal queue package so that external + // packages (e.g. evmd) can check for this error without importing internal/. + ErrQueueFull = queue.ErrQueueFull ) diff --git a/mempool/interface.go b/mempool/interface.go index b0984198..a2edb13a 100644 --- a/mempool/interface.go +++ b/mempool/interface.go @@ -8,8 +8,7 @@ import ( "github.com/cosmos/evm/x/vm/statedb" vmtypes "github.com/cosmos/evm/x/vm/types" - storetypes "cosmossdk.io/store/types" - + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -18,6 +17,7 @@ type VMKeeperI interface { GetParams(ctx sdk.Context) (params vmtypes.Params) GetEvmCoinInfo(ctx sdk.Context) (coinInfo vmtypes.EvmCoinInfo) GetAccount(ctx sdk.Context, addr common.Address) *statedb.Account + IsBaseAccountOrEmpty(ctx sdk.Context, addr common.Address) bool GetState(ctx sdk.Context, addr common.Address, key common.Hash) common.Hash GetCode(ctx sdk.Context, codeHash common.Hash) []byte GetCodeHash(ctx sdk.Context, addr common.Address) common.Hash @@ -28,8 +28,7 @@ type VMKeeperI interface { DeleteCode(ctx sdk.Context, codeHash []byte) SetCode(ctx sdk.Context, codeHash []byte, code []byte) DeleteAccount(ctx sdk.Context, addr common.Address) error - KVStoreKeys() map[string]*storetypes.KVStoreKey - SetEvmMempool(evmMempool *ExperimentalEVMMempool) + KVStoreKeys() map[string]storetypes.StoreKey } type FeeMarketKeeperI interface { diff --git a/mempool/internal/heightsync/heightsync.go b/mempool/internal/heightsync/heightsync.go new file mode 100644 index 00000000..7e83b5fc --- /dev/null +++ b/mempool/internal/heightsync/heightsync.go @@ -0,0 +1,270 @@ +package heightsync + +import ( + "context" + "fmt" + "math/big" + "sync" + "time" + + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/metric" + + "cosmossdk.io/log/v2" +) + +var meter = otel.Meter("github.com/cosmos/evm/mempool/internal/heightsync") + +var ( + // hsTimeout measures the number of times Get timed out before the value + // at a height was marked complete (partial or no results may be returned). + hsTimeout metric.Int64Counter + + // hsComplete measures the number of times Get returned after the value + // at a height was fully populated (EndCurrentHeight was called). + hsComplete metric.Int64Counter + + // hsHeightBehind measures the number of times Get was called for a height + // that the HeightSync had not yet reached. + hsHeightBehind metric.Int64Counter + + // hsDuration is the total time callers of Get spend from invocation to + // return. + hsDuration metric.Float64Histogram + + // hsHeights it the total number of heights progressed through on the + // height sync + hsHeights metric.Int64Counter +) + +func init() { + var err error + hsTimeout, err = meter.Int64Counter( + "height_sync.timeout", + metric.WithDescription("Number of times Get timed out before the value at a height was marked complete"), + ) + if err != nil { + panic(err) + } + hsComplete, err = meter.Int64Counter( + "height_sync.complete", + metric.WithDescription("Number of times Get returned after the value at a height was fully populated"), + ) + if err != nil { + panic(err) + } + hsHeightBehind, err = meter.Int64Counter( + "height_sync.height_behind", + metric.WithDescription("Number of times Get was called for a height that the HeightSync had not yet reached"), + ) + if err != nil { + panic(err) + } + hsDuration, err = meter.Float64Histogram( + "height_sync.duration", + metric.WithDescription("Total time callers of Get spend from invocation to return"), + metric.WithUnit("ms"), + ) + if err != nil { + panic(err) + } + hsHeights, err = meter.Int64Counter( + "height_sync.heights", + metric.WithDescription("Total number of heights progressed through on the HeightSync"), + ) + if err != nil { + panic(err) + } +} + +// HeightSync synchronizes access to a per-height tx store for mempool +// implementations. +// +// At every new block height, mempools need to revalidate (recheck) their +// transactions against the latest chain state. This rechecking happens +// asynchronously — txs are validated one by one and pushed into a store as +// they pass. Meanwhile, block proposers may need to read from that store to +// build the next block. +// +// HeightSync solves this coordination problem. It holds a Store per height +// that producers populate via Do (e.g. during rechecking), and that consumers +// read via GetStore. GetStore blocks until either all operations for the +// requested height are complete (EndCurrentHeight is called) or the caller's +// context times out, whichever comes first. This lets block builders wait for +// the full set of rechecked txs when time permits, while still returning +// partial results under time pressure rather than holding a lock on the +// mempool itself. +type HeightSync[Store any] struct { + // currentHeight is the height that the value is currently managed for + currentHeight *big.Int + + // reset is a function that returns a new store, called at every new height + reset func(logger log.Logger) *Store + + // store is the current Store that operations are happening on via Do and will + // be returned via Get until a new height is started via StartNewHeight + store *Store + + // heightChanged is closed when currentHeight is no longer being worked + heightChanged chan struct{} + + // done is closed when no more operations will happen on the value at + // currentHeight + done chan struct{} + + // mu protects all of the above fields; it does not protect internal + // fields of the Store itself + mu sync.RWMutex + + logger log.Logger +} + +// New creates a new HeightSync starting at the given height. +func New[Store any](startHeight *big.Int, reset func(logger log.Logger) *Store, logger log.Logger) *HeightSync[Store] { + hs := &HeightSync[Store]{ + currentHeight: startHeight, + reset: reset, + store: reset(logger), + heightChanged: make(chan struct{}), + done: make(chan struct{}), + logger: logger, + } + // initial height is considered immediately done + hs.EndCurrentHeight() + return hs +} + +// StartNewHeight resets the HeightSync for a new height, overwriting the +// previous Store with a fresh Store via the reset fn. +func (hs *HeightSync[Store]) StartNewHeight(height *big.Int) { + hs.mu.Lock() + defer hs.mu.Unlock() + + // ensure that the last height that was started has ended before starting a + // new height + if !hs.isHeightEnded() { + panic(fmt.Errorf("height %s not ended before starting new height %s", hs.currentHeight.String(), height.String())) + } + + // create new Store for this height + hs.currentHeight = new(big.Int).Set(height) + hs.store = hs.reset(hs.logger) + + // close old channel and create new one to wake up consumers + oldChan := hs.heightChanged + hs.heightChanged = make(chan struct{}) + hs.done = make(chan struct{}) + close(oldChan) +} + +// EndCurrentHeight marks the current heights operations as complete. This +// should be called when no more operations on the value via Do will be happen +// for this height. +// +// If operations are not marked as complete, callers of Get must wait for a +// context timeout in order to access the Store at this height. +func (hs *HeightSync[Store]) EndCurrentHeight() { + hs.mu.Lock() + defer hs.mu.Unlock() + if hs.isHeightEnded() { + panic(fmt.Errorf("height %s already ended", hs.currentHeight.String())) + } + hsHeights.Add(context.Background(), 1) + close(hs.done) +} + +// isHeightDone returns an true if the currentHeight has been ended, false +// otherwise. +func (hs *HeightSync[Store]) isHeightEnded() bool { + select { + case <-hs.done: + // reading from a closed channel will provide the zero value of the + // channel, done is closed if the height has ended + return true + default: + // were not able to get the zero value which means reading blocked and + // the done channel was not closed via EndCurrentHeight + return false + } +} + +// GetStore returns the store at the given height. If the HeightSync has not yet +// reached the target height, GetStore blocks until the height is reached or the +// context expires. If the height is reached, GetStore waits for EndCurrentHeight +// to be called (or for the context to expire) before returning. +func (hs *HeightSync[Store]) GetStore(ctx context.Context, height *big.Int) *Store { + genesis := big.NewInt(0) + + start := time.Now() + defer func(t0 time.Time) { + hsDuration.Record(ctx, float64(time.Since(t0).Milliseconds())) + }(start) + + for { + hs.mu.RLock() + + cmp := hs.currentHeight.Cmp(height) + + // should never see a situation where the HeightSync is ahead of + // the caller + if cmp > 0 { + defer hs.mu.RUnlock() // defer unlock since the panic will read + panic(fmt.Errorf("HeightSync.Get called for height %d, but current height is %d; cannot serve requests in the past", height, hs.currentHeight)) + } + + // if we're at the target height, wait for completion or timeout + if cmp == 0 { + value := hs.store + done := hs.done + + // at genesis, no completion signal will arrive, so return the + // value immediately + if hs.currentHeight.Cmp(genesis) == 0 { + hs.mu.RUnlock() + return value + } + hs.mu.RUnlock() + + // wait for EndCurrentHeight to signal that all operations on + // the value are complete, or for the context to expire + select { + case <-done: + hsComplete.Add(ctx, 1) + case <-ctx.Done(): + hsTimeout.Add(ctx, 1) + } + return value + } + + // current height is behind target, we cannot return the Store at the + // current height, so we must wait for the height to advance to the + // callers target height + heightChangedChan := hs.heightChanged + hs.mu.RUnlock() + + hsHeightBehind.Add(ctx, 1) + + // wait for height to advance or context to timeout + select { + case <-heightChangedChan: + // height changed, loop back to check if we've reached target + continue + case <-ctx.Done(): + // caller is done waiting, but we still do not have a Store at the + // correct height to return, return nil instead + hsTimeout.Add(ctx, 1) + return nil + } + } +} + +// Do executes fn with the current store. The store will be non-nil. +func (hs *HeightSync[Store]) Do(fn func(store *Store)) { + hs.mu.RLock() + defer hs.mu.RUnlock() + + if hs.store == nil { + return + } + fn(hs.store) +} diff --git a/mempool/internal/heightsync/heightsync_test.go b/mempool/internal/heightsync/heightsync_test.go new file mode 100644 index 00000000..ff747c70 --- /dev/null +++ b/mempool/internal/heightsync/heightsync_test.go @@ -0,0 +1,219 @@ +package heightsync_test + +import ( + "context" + "math/big" + "sync" + "testing" + "testing/synctest" + "time" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/evm/mempool/internal/heightsync" + + "cosmossdk.io/log/v2" +) + +// testStore is a simple store for testing the generic height-sync behavior. +type testStore struct { + items []string + mu sync.Mutex +} + +func newTestValue(_ log.Logger) *testStore { + return &testStore{} +} + +func (s *testStore) add(item string) { + s.mu.Lock() + defer s.mu.Unlock() + s.items = append(s.items, item) +} + +func (s *testStore) get() []string { + s.mu.Lock() + defer s.mu.Unlock() + return append([]string(nil), s.items...) +} + +func TestBasicGetAfterCompletion(t *testing.T) { + hv := heightsync.New(big.NewInt(1), newTestValue, log.NewNopLogger()) + + hv.StartNewHeight(big.NewInt(1)) + hv.Do(func(s *testStore) { + s.add("a") + s.add("b") + }) + hv.EndCurrentHeight() + + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + + value := hv.GetStore(ctx, big.NewInt(1)) + require.NotNil(t, value) + + items := value.get() + require.Len(t, items, 2) + require.Equal(t, "a", items[0]) + require.Equal(t, "b", items[1]) +} + +func TestGetTimeoutBeforeHeight(t *testing.T) { + hv := heightsync.New(big.NewInt(1), newTestValue, log.NewNopLogger()) + + // request height 3 but don't advance to it + ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) + defer cancel() + + value := hv.GetStore(ctx, big.NewInt(3)) + require.Nil(t, value) +} + +func TestGetPartialResults(t *testing.T) { + synctest.Test(t, func(t *testing.T) { + hv := heightsync.New(big.NewInt(1), newTestValue, log.NewNopLogger()) + + // start new height but don't call EndCurrentHeight + hv.StartNewHeight(big.NewInt(1)) + hv.Do(func(s *testStore) { + s.add("partial") + }) + + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + + value := hv.GetStore(ctx, big.NewInt(1)) + require.NotNil(t, value) + require.ErrorIs(t, ctx.Err(), context.DeadlineExceeded) // ensure we waiting for context to timeout + require.Equal(t, []string{"partial"}, value.get()) + }) +} + +func TestGetBehindByOneHeight(t *testing.T) { + synctest.Test(t, func(t *testing.T) { + hv := heightsync.New(big.NewInt(1), newTestValue, log.NewNopLogger()) + + hv.StartNewHeight(big.NewInt(1)) + hv.Do(func(s *testStore) { s.add("height1") }) + + // request height 2 in background + valueChan := make(chan *testStore) + go func() { + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) + defer cancel() + valueChan <- hv.GetStore(ctx, big.NewInt(2)) + }() + + time.Sleep(1 * time.Second) + + hv.EndCurrentHeight() + + // advance to height 2 + hv.StartNewHeight(big.NewInt(2)) + hv.Do(func(s *testStore) { s.add("height2") }) + hv.EndCurrentHeight() + + value := <-valueChan + require.NotNil(t, value) + require.Equal(t, []string{"height2"}, value.get()) + }) +} + +func TestGetBehindByTwoHeights(t *testing.T) { + synctest.Test(t, func(t *testing.T) { + hv := heightsync.New(big.NewInt(1), newTestValue, log.NewNopLogger()) + + hv.StartNewHeight(big.NewInt(1)) + hv.Do(func(s *testStore) { s.add("height1") }) + + // request height 3 in background + valueChan := make(chan *testStore) + go func() { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + valueChan <- hv.GetStore(ctx, big.NewInt(3)) + }() + + time.Sleep(1 * time.Second) + + // advance through height 2 + hv.EndCurrentHeight() + hv.StartNewHeight(big.NewInt(2)) + hv.Do(func(s *testStore) { s.add("height2") }) + + time.Sleep(1 * time.Second) + + // advance to height 3 + hv.EndCurrentHeight() + hv.StartNewHeight(big.NewInt(3)) + hv.Do(func(s *testStore) { s.add("height3") }) + hv.EndCurrentHeight() + + value := <-valueChan + require.NotNil(t, value) + require.Equal(t, []string{"height3"}, value.get()) + }) +} + +func TestPanicOnOldHeight(t *testing.T) { + hv := heightsync.New(big.NewInt(1), newTestValue, log.NewNopLogger()) + + hv.StartNewHeight(big.NewInt(1)) + hv.EndCurrentHeight() + hv.StartNewHeight(big.NewInt(2)) + + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + + require.Panics(t, func() { + hv.GetStore(ctx, big.NewInt(1)) + }) +} + +func TestStartNewHeightResetsValue(t *testing.T) { + hv := heightsync.New(big.NewInt(1), newTestValue, log.NewNopLogger()) + + hv.StartNewHeight(big.NewInt(1)) + hv.Do(func(s *testStore) { s.add("old") }) + hv.EndCurrentHeight() + + // advance to height 2 - should get a fresh store + hv.StartNewHeight(big.NewInt(2)) + hv.EndCurrentHeight() + + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + + result := hv.GetStore(ctx, big.NewInt(2)) + require.NotNil(t, result) + require.Empty(t, result.get()) +} + +func TestConcurrentDo(t *testing.T) { + hv := heightsync.New(big.NewInt(1), newTestValue, log.NewNopLogger()) + + hv.StartNewHeight(big.NewInt(1)) + + numOps := 100 + var wg sync.WaitGroup + for i := 0; i < numOps; i++ { + wg.Add(1) + go func() { + defer wg.Done() + hv.Do(func(s *testStore) { + s.add("x") + }) + }() + } + + wg.Wait() + hv.EndCurrentHeight() + + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + + result := hv.GetStore(ctx, big.NewInt(1)) + require.NotNil(t, result) + require.Len(t, result.get(), numOps) +} diff --git a/mempool/internal/queue/queue.go b/mempool/internal/queue/queue.go new file mode 100644 index 00000000..5ec4301a --- /dev/null +++ b/mempool/internal/queue/queue.go @@ -0,0 +1,211 @@ +package queue + +import ( + "context" + "errors" + "fmt" + "sync" + "time" + + "github.com/gammazero/deque" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/metric" +) + +var meter = otel.Meter("github.com/cosmos/evm/mempool/internal/queue") + +var ( + // queueSize is the current number of txs waiting to be inserted into the + // underlying mempool. + queueSize metric.Int64Gauge + + // insertDuration is the latency of a batch insert into the underlying + // mempool. + insertDuration metric.Float64Histogram +) + +func init() { + var err error + queueSize, err = meter.Int64Gauge( + "insert_queue.queue_size", + metric.WithDescription("Number of txs waiting in the inserter queue"), + ) + if err != nil { + panic(err) + } + + insertDuration, err = meter.Float64Histogram( + "insert_queue.add_duration", + metric.WithDescription("Time to insert a batch of txs into the underlying mempool"), + metric.WithUnit("ms"), + ) + if err != nil { + panic(err) + } +} + +// insertItem is an item in the queue that contains the user data (Tx) along +// with a subscription that the user is using to wait on the response from the +// insert. +type insertItem[Tx any] struct { + tx *Tx + sub chan<- error +} + +// Queue asynchronously inserts batches of txs in FIFO order. +type Queue[Tx any] struct { + // queue is a queue of Tx to be processed. Tx's are pushed onto the back, and + // popped from the front, FIFO. + queue deque.Deque[insertItem[Tx]] + lock sync.RWMutex + + // signal signals that there are Tx's available in the queue. Consumers of + // the queue should wait on this channel after they have popped all txs off + // the queue, to know when there are new txs available. + signal chan struct{} + + // insert inserts a batch of Tx's into the underlying mempool + insert func(txs []*Tx) []error + + // maxSize is the max amount of Tx's that can be in the queue before + // rejecting new additions + maxSize int + + // metricAttrs identifies this queue in emitted metrics. + metricAttrs metric.MeasurementOption + + done chan struct{} +} + +var ErrQueueFull = errors.New("queue full") + +// New creates a new queue. name distinguishes this queue's metrics from other +// queue instances (e.g. "evm" vs "cosmos"). +func New[Tx any](name string, insert func(txs []*Tx) []error, maxSize int) *Queue[Tx] { + iq := &Queue[Tx]{ + insert: insert, + maxSize: maxSize, + signal: make(chan struct{}, 1), + done: make(chan struct{}), + metricAttrs: metric.WithAttributeSet(attribute.NewSet(attribute.String("pool", name))), + } + + go iq.loop() + return iq +} + +// Push enqueues a Tx's to eventually be inserted. Returns a channel that will +// have an error pushed to it if an error occurs inserting the Tx. +func (iq *Queue[Tx]) Push(tx *Tx) <-chan error { + sub := make(chan error, 1) + + if tx == nil { + // TODO: when do we expect this to happen? + close(sub) + return sub + } + + iq.lock.Lock() + if iq.queue.Len() >= iq.maxSize { + iq.lock.Unlock() + sub <- ErrQueueFull + close(sub) + return sub + } + + iq.queue.PushBack(insertItem[Tx]{tx: tx, sub: sub}) + iq.lock.Unlock() + + // signal that there are Tx's available + select { + case iq.signal <- struct{}{}: + default: + } + + return sub +} + +// loop is the main loop of the Queue. This will pop Tx's off the front of the +// queue and try to insert them. +func (iq *Queue[Tx]) loop() { + for { + iq.lock.RLock() + numTxsAvailable := iq.queue.Len() + iq.lock.RUnlock() + + queueSize.Record(context.Background(), int64(numTxsAvailable), iq.metricAttrs) + + // if nothing is available, wait for new Tx's to become available + // before checking again + if numTxsAvailable == 0 { + if iq.waitForNewTxs() { + continue + } + return + } + + var ( + subscriptions []chan<- error + toInsert []*Tx + ) + + iq.lock.Lock() + for item := range iq.queue.IterPopFront() { + if item.tx == nil { + close(item.sub) + continue + } + + toInsert = append(toInsert, item.tx) + subscriptions = append(subscriptions, item.sub) + } + iq.lock.Unlock() + + errs := iq.insertTxs(toInsert) + + // push any potential errors out to subscribers + for i, err := range errs { + subscriptions[i] <- err + close(subscriptions[i]) + } + + // check if we have been told to cancel, if not, check for more Tx's to insert + select { + case <-iq.done: + return + default: + continue + } + } +} + +// waitForNewTxs blocks and waits for new txs to become available and returns +// true if that happens, or false if we have cancelled before then. +func (iq *Queue[Tx]) waitForNewTxs() bool { + select { + case <-iq.done: + return false + case <-iq.signal: + // new txs available + return true + } +} + +// insertTxs inserts Tx's, returning any errors that have occurred. +func (iq *Queue[Tx]) insertTxs(txs []*Tx) []error { + defer func(t0 time.Time) { + insertDuration.Record(context.Background(), float64(time.Since(t0).Milliseconds()), iq.metricAttrs) + }(time.Now()) + + errs := iq.insert(txs) + if len(errs) != len(txs) { + panic(fmt.Errorf("expected a %d errors from insert but instead got %d", len(txs), len(errs))) + } + return errs +} + +// Close stops the main loop of the queue. +func (iq *Queue[Tx]) Close() { + close(iq.done) +} diff --git a/mempool/internal/queue/queue_test.go b/mempool/internal/queue/queue_test.go new file mode 100644 index 00000000..2bc3de5d --- /dev/null +++ b/mempool/internal/queue/queue_test.go @@ -0,0 +1,193 @@ +package queue + +import ( + "sync" + "testing" + "time" + + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/require" +) + +// mockPool is a mock that records inserted transactions and optionally +// delegates to a custom function. +type mockPool struct { + mu sync.Mutex + insertFn func([]*ethtypes.Transaction) []error + txs []*ethtypes.Transaction +} + +func newMockPool() *mockPool { + return &mockPool{ + txs: make([]*ethtypes.Transaction, 0), + } +} + +func (m *mockPool) insert(txs []*ethtypes.Transaction) []error { + m.mu.Lock() + defer m.mu.Unlock() + + if m.insertFn != nil { + return m.insertFn(txs) + } + + errs := make([]error, len(txs)) + m.txs = append(m.txs, txs...) + return errs +} + +func (m *mockPool) getTxs() []*ethtypes.Transaction { + m.mu.Lock() + defer m.mu.Unlock() + return m.txs +} + +func (m *mockPool) setInsertFn(fn func([]*ethtypes.Transaction) []error) { + m.mu.Lock() + defer m.mu.Unlock() + m.insertFn = fn +} + +func TestInsertQueue_PushAndProcess(t *testing.T) { + pool := newMockPool() + iq := New[ethtypes.Transaction]("test", pool.insert, 1000) + defer iq.Close() + + // Create a test transaction + tx := ethtypes.NewTransaction(1, [20]byte{0x01}, nil, 21000, nil, nil) + + // Push transaction + _ = iq.Push(tx) + + // Wait for transaction to be processed + require.Eventually(t, func() bool { + return len(pool.getTxs()) == 1 + }, time.Second, 10*time.Millisecond, "transaction should be processed") + + // Verify the transaction was added + txs := pool.getTxs() + require.Len(t, txs, 1) + require.Equal(t, tx.Hash(), txs[0].Hash()) +} + +func TestInsertQueue_ProcessesMultipleTransactions(t *testing.T) { + pool := newMockPool() + iq := New[ethtypes.Transaction]("test", pool.insert, 1000) + defer iq.Close() + + // Create multiple test transactions + tx1 := ethtypes.NewTransaction(1, [20]byte{0x01}, nil, 21000, nil, nil) + tx2 := ethtypes.NewTransaction(2, [20]byte{0x02}, nil, 21000, nil, nil) + tx3 := ethtypes.NewTransaction(3, [20]byte{0x03}, nil, 21000, nil, nil) + + // Push transactions + _ = iq.Push(tx1) + _ = iq.Push(tx2) + _ = iq.Push(tx3) + + // Wait for all transactions to be processed + require.Eventually(t, func() bool { + return len(pool.getTxs()) == 3 + }, time.Second, 10*time.Millisecond, "all transactions should be processed") + + // Verify transactions were added in FIFO order + txs := pool.getTxs() + require.Len(t, txs, 3) + require.Equal(t, tx1.Hash(), txs[0].Hash()) + require.Equal(t, tx2.Hash(), txs[1].Hash()) + require.Equal(t, tx3.Hash(), txs[2].Hash()) +} + +func TestInsertQueue_IgnoresNilTransaction(t *testing.T) { + pool := newMockPool() + iq := New[ethtypes.Transaction]("test", pool.insert, 1000) + defer iq.Close() + + // Push nil transaction + _ = iq.Push(nil) + + // Wait a bit to ensure nothing is processed + time.Sleep(100 * time.Millisecond) + + // Verify no transaction was added + txs := pool.getTxs() + require.Len(t, txs, 0) +} + +func TestInsertQueue_SlowAddition(t *testing.T) { + pool := newMockPool() + + // Make insert slow to allow queue to back up + pool.setInsertFn(func(txs []*ethtypes.Transaction) []error { + time.Sleep(10 * time.Second) + return make([]error, len(txs)) + }) + + iq := New[ethtypes.Transaction]("test", pool.insert, 1000) + defer iq.Close() + + // Push first transaction to start processing + tx1 := ethtypes.NewTransaction(1, [20]byte{0x01}, nil, 21000, nil, nil) + _ = iq.Push(tx1) + + time.Sleep(100 * time.Millisecond) + + // Push a bunch of transactions and verify that we did not have to wait for + // the 200 ms to add the first tx. + start := time.Now() + var nonce uint64 + for nonce = 0; nonce < 100; nonce++ { + tx := ethtypes.NewTransaction(nonce+2, [20]byte{byte(nonce + 2)}, nil, 21000, nil, nil) + _ = iq.Push(tx) + } + require.Less(t, time.Since(start), 100*time.Millisecond, "pushes should not block") +} + +func TestInsertQueue_RejectsWhenFull(t *testing.T) { + pool := newMockPool() + + // when insertFn is called, push a value onto a channel to signal that a + // single tx has been popped from the queue, then block forever so no more + // txs can be popped, that means we can add 1 more tx then the queue will + // be at max capacity, and adding 1 after that will trigger an error + added := make(chan struct{}, 1) + pool.setInsertFn(func(txs []*ethtypes.Transaction) []error { + added <- struct{}{} + select {} // block forever + }) + + iq := New[ethtypes.Transaction]("test", pool.insert, 5) + defer iq.Close() + + // This first tx will be immediately popped and start processing (where it + // blocks) + nonce := uint64(0) + tx := ethtypes.NewTransaction(nonce, [20]byte{byte(nonce + 1)}, nil, 21000, nil, nil) + _ = iq.Push(tx) + nonce++ + + // wait for first tx to be popped and insertFn to be called and blocking + <-added + + // Fill the queue to capacity + for ; nonce <= 5; nonce++ { + tx := ethtypes.NewTransaction(nonce, [20]byte{byte(nonce + 1)}, nil, 21000, nil, nil) + _ = iq.Push(tx) + } + + // Try to push one more transaction with error channel, queue is now at max capacity + tx = ethtypes.NewTransaction(100, [20]byte{0x64}, nil, 21000, nil, nil) + _ = iq.Push(tx) + + // Push another tx into the full queue, should be rejected + fullTx := ethtypes.NewTransaction(101, [20]byte{0x64}, nil, 21000, nil, nil) + sub := iq.Push(fullTx) + + // Verify we got the queue full error + select { + case err := <-sub: + require.ErrorIs(t, err, ErrQueueFull, "should receive queue full error") + default: + t.Fatal("did not receive error from full queue") + } +} diff --git a/mempool/internal/reaplist/metrics.go b/mempool/internal/reaplist/metrics.go new file mode 100644 index 00000000..d14bddc1 --- /dev/null +++ b/mempool/internal/reaplist/metrics.go @@ -0,0 +1,88 @@ +package reaplist + +import ( + "context" + + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/metric" +) + +var meter = otel.Meter("github.com/cosmos/evm/mempool/internal/reaplist") + +// reapListMetrics are reapListMetrics specific to the reaplist +type reapListMetrics struct { + numTxs metric.Int64Gauge + numIndexTxs metric.Int64Gauge + pushedTxs metric.Int64Counter + droppedTxs metric.Int64Counter +} + +var metrics = reapListMetrics{} + +type txType string + +const ( + evmType txType = "evm" + cosmosType txType = "cosmos" +) + +// TxPushed records that a new tx was pushed into the reap list with type +// txType +func (rlm *reapListMetrics) TxPushed(txType txType) { + attributes := attribute.NewSet(attribute.String("tx_type", string(txType))) + rlm.pushedTxs.Add(context.Background(), 1, metric.WithAttributeSet(attributes)) +} + +// TxDropped records that a new tx was dropped from the reap list with type +// txType +func (rlm *reapListMetrics) TxDropped(txType txType) { + attributes := attribute.NewSet(attribute.String("tx_type", string(txType))) + rlm.droppedTxs.Add(context.Background(), 1, metric.WithAttributeSet(attributes)) +} + +// RecordNumTxs records the number of entires in txs +func (rlm *reapListMetrics) RecordNumTxs(txs []*txWithHash) { + rlm.numTxs.Record(context.Background(), int64(len(txs))) +} + +// RecordNumTxs records the number of entries in index +func (rlm *reapListMetrics) RecordNumIndexTxs(index map[string]int) { + rlm.numIndexTxs.Record(context.Background(), int64(len(index))) +} + +// initialize all metrics or panic +func init() { + var err error + metrics.numTxs, err = meter.Int64Gauge( + "reap_list.num_txs", + metric.WithDescription("Number of populated entries currently in the reap list (may be a nil tombstone)"), + ) + if err != nil { + panic(err) + } + + metrics.numIndexTxs, err = meter.Int64Gauge( + "reap_list.num_index_txs", + metric.WithDescription("Number of transactions currently in the reap list's index"), + ) + if err != nil { + panic(err) + } + + metrics.pushedTxs, err = meter.Int64Counter( + "reap_list.pushed_txs", + metric.WithDescription("Total number of transactions that have been pushed into the reap list"), + ) + if err != nil { + panic(err) + } + + metrics.droppedTxs, err = meter.Int64Counter( + "reap_list.dropped_txs", + metric.WithDescription("Total number of transactions that have been dropped from the reap list"), + ) + if err != nil { + panic(err) + } +} diff --git a/mempool/internal/reaplist/reaplist.go b/mempool/internal/reaplist/reaplist.go new file mode 100644 index 00000000..9cd8f451 --- /dev/null +++ b/mempool/internal/reaplist/reaplist.go @@ -0,0 +1,252 @@ +package reaplist + +import ( + "fmt" + "slices" + "sync" + + ethtypes "github.com/ethereum/go-ethereum/core/types" + + "github.com/cometbft/cometbft/crypto/tmhash" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type EVMCosmosTxEncoder interface { + EVMTx(tx *ethtypes.Transaction) ([]byte, error) + CosmosTx(tx sdk.Tx) ([]byte, error) +} + +type txWithHash struct { + bytes []byte + hash string + gas uint64 +} + +type ReapList struct { + // txs is a list of transactions and their respective hashes + // NOTE: this currently has unbound size + txs []*txWithHash + + // txIndex is a map of tx hashes to what index that tx is stored in inside + // of txs. This serves a dual purpose of allowing for fast drops from txs + // without iteration, and guarding txs from being added to the ReapList + // twice before they are explicitly dropped. + txIndex map[string]int + + // txsLock protects txLookup and txs. + txsLock sync.RWMutex + + // txEncoder encodes evm and cosmos txs to bytes. + txEncoder EVMCosmosTxEncoder +} + +func New(txEncoder EVMCosmosTxEncoder) *ReapList { + return &ReapList{ + txEncoder: txEncoder, + txIndex: make(map[string]int), + } +} + +// Reap returns a list of the oldest to newest transactions bytes from the reap +// list until either maxBytes or maxGas is reached for the list of transactions +// being returned. If maxBytes and maxGas are both 0 all txs will be returned. +// +// Callers MUST pass maxBytes >= comet's mempool.max_tx_bytes and maxGas >= +// consensus block.max_gas (or 0 for "no limit"). A tx larger than maxBytes/ +// maxGas wedges the head: Reap stops at it and returns nothing, even though +// txs behind it would fit. server.ValidateReapBounds enforces this at boot. +func (rl *ReapList) Reap(maxBytes uint64, maxGas uint64) [][]byte { + rl.txsLock.Lock() + defer rl.txsLock.Unlock() + + var ( + totalBytes uint64 + totalGas uint64 + result [][]byte + nextStart int + ) + + for idx, tx := range rl.txs { + if tx == nil { + // txs may have "holes" (nil) due to txs being invalidated and + // dropped while they are waiting in the reap list + nextStart = idx + 1 + continue + } + + txSize := uint64(len(tx.bytes)) + txGas := tx.gas + + // Check if adding this tx would exceed limits + if (maxBytes > 0 && totalBytes+txSize > maxBytes) || (maxGas > 0 && totalGas+txGas > maxGas) { + break + } + + result = append(result, tx.bytes) + totalBytes += txSize + totalGas += txGas + nextStart = idx + 1 + + // NOTE: We need to keep the txs that were just reaped in the txIndex, so + // that it can properly guard against these txs being added to the ReapList + // again. These txs are likely still in the mempool, and callers may try to + // add them to the ReapList again, which is not allowed. Removing from the + // txIndex will only be done during Drop. + if _, ok := rl.txIndex[tx.hash]; !ok { + panic("removed a tx that was not in the tx index, this should not happen") + } + rl.txIndex[tx.hash] = -1 + } + + if nextStart >= len(rl.txs) { + rl.txs = []*txWithHash{} + } else { + // In order to remove the txs that were returned from reap, we can simply + // reslice the list since all removed txs were from the start, and we saved + // where the next set of valid txs start in nextStart. + // + // Also compact away any nil values from the new slice. + rl.txs = slices.DeleteFunc(rl.txs[nextStart:], func(tx *txWithHash) bool { + return tx == nil + }) + } + metrics.RecordNumTxs(rl.txs) + + // rebuild the index since txs may have shifted indices + for i, tx := range rl.txs { + if _, ok := rl.txIndex[tx.hash]; !ok { + panic("tx that was not reaped is not in the tx index, this should not happen") + } + rl.txIndex[tx.hash] = i + } + metrics.RecordNumIndexTxs(rl.txIndex) + + return result +} + +// PushEVMTx enqueues an EVM tx into the reap list. +func (rl *ReapList) PushEVMTx(tx *ethtypes.Transaction) error { + hash := tx.Hash().String() + + rl.txsLock.Lock() + defer rl.txsLock.Unlock() + + if rl.exists(hash) { + return nil + } + + txBytes, err := rl.txEncoder.EVMTx(tx) + if err != nil { + return fmt.Errorf("encoding evm tx to bytes: %w", err) + } + + rl.push(hash, txBytes, tx.Gas()) + + metrics.TxPushed(evmType) + return nil +} + +// PushCosmosTx enqueues a cosmos tx into the reap list. +func (rl *ReapList) PushCosmosTx(tx sdk.Tx) error { + txBytes, err := rl.txEncoder.CosmosTx(tx) + if err != nil { + return fmt.Errorf("encoding cosmos tx to bytes: %w", err) + } + hash := cosmosHash(txBytes) + + rl.txsLock.Lock() + defer rl.txsLock.Unlock() + + if rl.exists(hash) { + return nil + } + + var gas uint64 + if feeTx, ok := tx.(sdk.FeeTx); ok { + gas = feeTx.GetGas() + } else { + return fmt.Errorf("error getting tx gas: cosmos tx must implement sdk.FeeTx") + } + + rl.push(hash, txBytes, gas) + + metrics.TxPushed(cosmosType) + return nil +} + +// push inserts a tx to the back of the reap list as the "newest" transaction +// (last to be returned if Reap was called now). push assumes that a tx is not +// already in the ReapList, this should be checked via exists. +// +// NOTE: this is not thread safe, callers should be holding the txsLock. +func (rl *ReapList) push(hash string, tx []byte, gas uint64) { + rl.txs = append(rl.txs, &txWithHash{tx, hash, gas}) + rl.txIndex[hash] = len(rl.txs) - 1 + + metrics.RecordNumTxs(rl.txs) + metrics.RecordNumIndexTxs(rl.txIndex) +} + +// exists returns true if a hash is in the index, false otherwise. +// +// NOTE: this is not thread safe, callers should be holding the txsLock. +func (rl *ReapList) exists(hash string) bool { + _, ok := rl.txIndex[hash] + return ok +} + +// DropEVMTx removes an EVM tx from the ReapList. This tx may or may not have +// already been reaped. This should only be called when a tx that was +// previously validated, becomes invalid. +func (rl *ReapList) DropEVMTx(tx *ethtypes.Transaction) { + dropped := rl.drop(tx.Hash().String()) + + if dropped { + metrics.TxDropped(evmType) + } +} + +// DropCosmosTx removes a Cosmos tx from the ReapList. This tx may or may not +// have already been reaped. This should only be called when a tx that was +// previously validated, becomes invalid. +func (rl *ReapList) DropCosmosTx(tx sdk.Tx) { + txBytes, err := rl.txEncoder.CosmosTx(tx) + if err != nil { + return + } + dropped := rl.drop(cosmosHash(txBytes)) + + if dropped { + metrics.TxDropped(cosmosType) + } +} + +// drop removes an individual tx from the reap list. If the tx is not in the +// list, no changes are made. Returns true if the tx was dropped, false +// otherwise. +func (rl *ReapList) drop(hash string) bool { + rl.txsLock.Lock() + defer rl.txsLock.Unlock() + + idx, ok := rl.txIndex[hash] + if !ok { + return false + } + delete(rl.txIndex, hash) + metrics.RecordNumIndexTxs(rl.txIndex) + + if idx < 0 || idx >= len(rl.txs) { + return false + } + + rl.txs[idx] = nil + // NOTE: Not updating numTxs metric here since that reports the size of the + // reap list **including** tombstones. We will update numTxs when the + // tombstone is removed via the next `Reap` call. + return true +} + +func cosmosHash(txBytes []byte) string { + return fmt.Sprintf("%X", tmhash.Sum(txBytes)) +} diff --git a/mempool/internal/reaplist/reaplist_test.go b/mempool/internal/reaplist/reaplist_test.go new file mode 100644 index 00000000..d5417d99 --- /dev/null +++ b/mempool/internal/reaplist/reaplist_test.go @@ -0,0 +1,840 @@ +package reaplist + +import ( + "crypto/ecdsa" + "encoding/binary" + "errors" + "fmt" + "math/big" + "sync" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/proto" + + "github.com/cometbft/cometbft/crypto/tmhash" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const txValue = 100 + +// mockEncoder implements the EVMCosmosTxEncoder interface for testing +type mockEncoder struct { + evmBytesPerTx uint64 + cosmosBytesPerTx uint64 + failEVMNonces map[uint64]bool + failCosmosHashes map[string]bool +} + +func (m *mockEncoder) EVMTx(tx *types.Transaction) ([]byte, error) { + if m.failEVMNonces != nil && m.failEVMNonces[tx.Nonce()] { + return nil, errors.New("encoding failed") + } + if m.evmBytesPerTx > 0 { + // Include unique tx hash prefix to avoid collisions + result := make([]byte, m.evmBytesPerTx) + hash := tx.Hash().Bytes() + copy(result, hash) + return result, nil + } + // Variable size based on nonce for some tests + return make([]byte, 100+(tx.Nonce()*10)), nil +} + +func (m *mockEncoder) CosmosTx(tx sdk.Tx) ([]byte, error) { + // Create a deterministic byte representation for testing + // Use the tx id to ensure uniqueness + mockTx, ok := tx.(*mockCosmosTx) + var txBytes []byte + if ok { + txBytes = []byte(fmt.Sprintf("cosmos-tx-%d", mockTx.id)) + } else { + txBytes = []byte(fmt.Sprintf("cosmos-tx-%p", tx)) + } + + hash := fmt.Sprintf("%X", tmhash.Sum(txBytes)) + + if m.failCosmosHashes != nil && m.failCosmosHashes[hash] { + return nil, errors.New("encoding failed") + } + if m.cosmosBytesPerTx > 0 { + // Create bytes with unique prefix to avoid hash collisions + result := make([]byte, m.cosmosBytesPerTx) + copy(result, txBytes) + return result, nil + } + return txBytes, nil +} + +func newDeterministicEncoder(evmBytesPerTx, cosmosBytesPerTx uint64) *mockEncoder { + return &mockEncoder{ + evmBytesPerTx: evmBytesPerTx, + cosmosBytesPerTx: cosmosBytesPerTx, + } +} + +func newFailingEVMEncoder(failNonces map[uint64]bool) *mockEncoder { + return &mockEncoder{ + failEVMNonces: failNonces, + } +} + +var _ sdk.FeeTx = &mockCosmosTx{} + +// mockCosmosTx implements sdk.Tx and sdk.FeeTx for testing +type mockCosmosTx struct { + gas uint64 + id int // unique identifier for each tx + msgs []sdk.Msg + feePayer sdk.AccAddress +} + +func (m *mockCosmosTx) GetMsgs() []sdk.Msg { + return m.msgs +} + +func (m *mockCosmosTx) GetMsgsV2() ([]proto.Message, error) { + return nil, nil +} + +func (m *mockCosmosTx) ValidateBasic() error { + return nil +} + +func (m *mockCosmosTx) GetGas() uint64 { + return m.gas +} + +func (m *mockCosmosTx) GetFee() sdk.Coins { + return sdk.NewCoins(sdk.NewInt64Coin("stake", 100)) +} + +func (m *mockCosmosTx) FeePayer() []byte { + return m.feePayer +} + +func (m *mockCosmosTx) FeeGranter() []byte { + return nil +} + +func newMockCosmosTx(id int, gas uint64) *mockCosmosTx { + return &mockCosmosTx{ + gas: gas, + id: id, + } +} + +// Helper function to create a test EVM transaction with specific gas +func testEVMTx(t *testing.T, key *ecdsa.PrivateKey, nonce uint64, gas uint64) *types.Transaction { + t.Helper() + + tx := types.NewTransaction( + nonce, + common.Address{}, + big.NewInt(txValue), + gas, + big.NewInt(1), + nil, + ) + signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, key) + require.NoError(t, err) + return signedTx +} + +func TestEmptyList(t *testing.T) { + rl := New(newDeterministicEncoder(100, 100)) + + result := rl.Reap(0, 0) + + require.Empty(t, result, "reaping empty list should return empty result") +} + +func TestSingleTransaction(t *testing.T) { + key, err := crypto.GenerateKey() + require.NoError(t, err) + + rl := New(newDeterministicEncoder(100, 100)) + tx := testEVMTx(t, key, 0, 21000) + err = rl.PushEVMTx(tx) + require.NoError(t, err) + + result := rl.Reap(0, 0) + + require.Len(t, result, 1, "should reap single transaction") + require.Len(t, result[0], 100, "transaction should have expected size") + + // Second reap should return empty as tx was removed + result = rl.Reap(0, 0) + require.Empty(t, result, "second reap should return empty") + + // Push the same tx again to ensure that it is not able to be reaped again + err = rl.PushEVMTx(tx) + require.NoError(t, err) + + result = rl.Reap(0, 0) + require.Len(t, result, 0, "should reap no transactions") +} + +func TestNoLimits(t *testing.T) { + key, err := crypto.GenerateKey() + require.NoError(t, err) + + rl := New(newDeterministicEncoder(100, 100)) + + // Add 10 transactions + for i := uint64(0); i < 10; i++ { + tx := testEVMTx(t, key, i, 21000) + err = rl.PushEVMTx(tx) + require.NoError(t, err) + } + + result := rl.Reap(0, 0) + + require.Len(t, result, 10, "should reap all transactions with no limits") +} + +func TestMaxBytesLimit(t *testing.T) { + key, err := crypto.GenerateKey() + require.NoError(t, err) + + // Each tx is 100 bytes + rl := New(newDeterministicEncoder(100, 100)) + + // Add 10 transactions + for i := uint64(0); i < 10; i++ { + tx := testEVMTx(t, key, i, 21000) + err = rl.PushEVMTx(tx) + require.NoError(t, err) + } + + // Limit to 350 bytes (should get 3 transactions) + result := rl.Reap(350, 0) + + require.Len(t, result, 3, "should reap 3 transactions with 350 byte limit") + + // Next reap should get remaining 7 + result = rl.Reap(0, 0) + require.Len(t, result, 7, "should have 7 transactions remaining") +} + +func TestMaxGasLimit(t *testing.T) { + key, err := crypto.GenerateKey() + require.NoError(t, err) + + rl := New(newDeterministicEncoder(100, 100)) + + // Add transactions with varying gas + txGases := []uint64{21000, 30000, 40000, 50000, 60000} + var nonce uint64 + for _, gas := range txGases { + tx := testEVMTx(t, key, nonce, gas) + err = rl.PushEVMTx(tx) + require.NoError(t, err) + nonce++ + } + + // Limit to 100000 gas (should get first 3 txs: 21000 + 30000 + 40000 = 91000) + result := rl.Reap(0, 100000) + + require.Len(t, result, 3, "should reap 3 transactions with 100000 gas limit") + + // Next reap should get remaining 2 + result = rl.Reap(0, 0) + require.Len(t, result, 2, "should have 2 transactions remaining") +} + +func TestBothLimits(t *testing.T) { + key, err := crypto.GenerateKey() + require.NoError(t, err) + + rl := New(newDeterministicEncoder(100, 100)) + + // Add transactions with varying gas + txGases := []uint64{21000, 30000, 40000, 50000, 60000} + var nonce uint64 + for _, gas := range txGases { + tx := testEVMTx(t, key, nonce, gas) + err = rl.PushEVMTx(tx) + require.NoError(t, err) + nonce++ + } + + // Limit to 250 bytes (2.5 txs) and 70000 gas (first 3 txs would be 91000) + // Should be limited by bytes, so only 2 transactions + result := rl.Reap(250, 70000) + + require.Len(t, result, 2, "should be limited by bytes, returning 2 transactions") + + // Next reap with gas limit should get next 2 txs (40000 + 50000 = 90000 < 100000) + result = rl.Reap(0, 100000) + require.Len(t, result, 2, "should reap next 2 transactions within gas limit") + + // Final reap should get last tx + result = rl.Reap(0, 0) + require.Len(t, result, 1, "should have 1 transaction remaining") +} + +func TestExactBytesLimit(t *testing.T) { + key, err := crypto.GenerateKey() + require.NoError(t, err) + + // Each tx is 100 bytes + rl := New(newDeterministicEncoder(100, 100)) + + // Add 5 transactions + for i := uint64(0); i < 5; i++ { + tx := testEVMTx(t, key, i, 21000) + err = rl.PushEVMTx(tx) + require.NoError(t, err) + } + + // Limit to exactly 300 bytes (should get exactly 3 transactions) + result := rl.Reap(300, 0) + + require.Len(t, result, 3, "should reap exactly 3 transactions with exact byte limit") +} + +func TestExactGasLimit(t *testing.T) { + key, err := crypto.GenerateKey() + require.NoError(t, err) + + rl := New(newDeterministicEncoder(100, 100)) + + // Add transactions with specific gas amounts + txGases := []uint64{21000, 30000, 40000} + var nonce uint64 + for _, gas := range txGases { + tx := testEVMTx(t, key, nonce, gas) + err = rl.PushEVMTx(tx) + require.NoError(t, err) + nonce++ + } + + // Limit to exactly 51000 gas (21000 + 30000 = 51000, exactly 2 txs) + result := rl.Reap(0, 51000) + + require.Len(t, result, 2, "should reap exactly 2 transactions with exact gas limit") +} + +func TestEncodingFailure(t *testing.T) { + key, err := crypto.GenerateKey() + require.NoError(t, err) + + // Create encoder that fails for nonce 1 and 3 + failNonces := map[uint64]bool{1: true, 3: true} + rl := New(newFailingEVMEncoder(failNonces)) + + // Add 5 transactions (nonces 0-4) + // Nonces 1 and 3 will fail during Push, so only 0, 2, 4 will be added + for i := uint64(0); i < 5; i++ { + tx := testEVMTx(t, key, i, 21000) + _ = rl.PushEVMTx(tx) // Ignore error for failing encodings + } + + result := rl.Reap(0, 0) + + // Should get 3 transactions (0, 2, 4) - nonces 1 and 3 fail encoding during Push + require.Len(t, result, 3, "should have 3 transactions that succeeded encoding") + + // Verify we got the correct transactions by checking sizes + // Nonce 0: size = 100 + 0*10 = 100 + // Nonce 2: size = 100 + 2*10 = 120 + // Nonce 4: size = 100 + 4*10 = 140 + require.Len(t, result[0], 100, "first tx should be nonce 0") + require.Len(t, result[1], 120, "second tx should be nonce 2") + require.Len(t, result[2], 140, "third tx should be nonce 4") +} + +// nonceEncoder embeds nonce in bytes for order verification testing +type nonceEncoder struct{} + +func (e *nonceEncoder) EVMTx(tx *types.Transaction) ([]byte, error) { + buf := make([]byte, 8) + binary.LittleEndian.PutUint64(buf, tx.Nonce()) + return buf, nil +} + +func (e *nonceEncoder) CosmosTx(tx sdk.Tx) ([]byte, error) { + return []byte("cosmos-tx"), nil +} + +func TestOrderPreservation(t *testing.T) { + key, err := crypto.GenerateKey() + require.NoError(t, err) + + // Create encoder that embeds nonce in the bytes for verification + rl := New(&nonceEncoder{}) + + // Add transactions in specific order + var nonce uint64 + for nonce = 0; nonce < 5; nonce++ { + tx := testEVMTx(t, key, nonce, 21000) + err = rl.PushEVMTx(tx) + require.NoError(t, err) + } + + result := rl.Reap(0, 0) + + require.Len(t, result, 5, "should reap all transactions") + + // Verify order is preserved (oldest to newest) + var expectedNonce uint64 + for expectedNonce = 0; expectedNonce < 5; expectedNonce++ { + actualNonce := binary.LittleEndian.Uint64(result[expectedNonce]) + require.Equal(t, expectedNonce, actualNonce, "transactions should be in order") + } +} + +func TestMultipleReaps(t *testing.T) { + key, err := crypto.GenerateKey() + require.NoError(t, err) + + rl := New(newDeterministicEncoder(100, 100)) + + // Add 10 transactions + var nonce uint64 + for nonce = 0; nonce < 10; nonce++ { + tx := testEVMTx(t, key, nonce, 21000) + err = rl.PushEVMTx(tx) + require.NoError(t, err) + } + + // First reap: get 3 + result := rl.Reap(300, 0) + require.Len(t, result, 3) + + // Second reap: get 2 + result = rl.Reap(200, 0) + require.Len(t, result, 2) + + // Third reap: get remaining 5 + result = rl.Reap(0, 0) + require.Len(t, result, 5) + + // Fourth reap: empty + result = rl.Reap(0, 0) + require.Empty(t, result) +} + +func TestPushAfterReap(t *testing.T) { + key, err := crypto.GenerateKey() + require.NoError(t, err) + + rl := New(newDeterministicEncoder(100, 100)) + + // Add 5 transactions + var nonce uint64 + for nonce = 0; nonce < 5; nonce++ { + tx := testEVMTx(t, key, nonce, 21000) + err = rl.PushEVMTx(tx) + require.NoError(t, err) + } + + // Reap 3 + result := rl.Reap(300, 0) + require.Len(t, result, 3) + + // Add 3 more + for nonce = 5; nonce < 8; nonce++ { + tx := testEVMTx(t, key, nonce, 21000) + err = rl.PushEVMTx(tx) + require.NoError(t, err) + } + + // Should have 5 total (2 remaining + 3 new) + result = rl.Reap(0, 0) + require.Len(t, result, 5) +} + +func TestConcurrentPushAndReap(t *testing.T) { + key, err := crypto.GenerateKey() + require.NoError(t, err) + + rl := New(newDeterministicEncoder(100, 100)) + + var wg sync.WaitGroup + var totalReaped int + var mu sync.Mutex + + // Pusher goroutine: continuously add transactions + wg.Add(1) + go func() { + defer wg.Done() + var nonce uint64 + for nonce = 0; nonce < 100; nonce++ { + tx := testEVMTx(t, key, nonce, 21000) + _ = rl.PushEVMTx(tx) + } + }() + + // Reaper goroutine: continuously reap transactions + wg.Add(1) + go func() { + defer wg.Done() + for i := 0; i < 50; i++ { + result := rl.Reap(200, 0) // Reap 2 at a time + mu.Lock() + totalReaped += len(result) + mu.Unlock() + } + }() + + wg.Wait() + + // Final reap to get any remaining + result := rl.Reap(0, 0) + totalReaped += len(result) + + // We should have reaped close to 100 transactions (may vary due to timing) + // The exact number depends on race timing, but should be reasonable + require.GreaterOrEqual(t, totalReaped, 50, "should reap at least half of pushed transactions") + require.LessOrEqual(t, totalReaped, 100, "should not reap more than pushed") +} + +func TestFirstTransactionExceedsLimit(t *testing.T) { + key, err := crypto.GenerateKey() + require.NoError(t, err) + + rl := New(newDeterministicEncoder(1000, 1000)) + + // Add transaction + tx := testEVMTx(t, key, 0, 21000) + err = rl.PushEVMTx(tx) + require.NoError(t, err) + + // Try to reap with limit smaller than first tx + result := rl.Reap(500, 0) + + // Should return empty as first tx exceeds limit + require.Empty(t, result, "should return empty when first tx exceeds limit") + + // Transaction should still be in list for next reap with higher limit + result = rl.Reap(1000, 0) + require.Len(t, result, 1, "transaction should still be available with higher limit") +} + +// alwaysFailEncoder always returns an error for encoding +type alwaysFailEncoder struct{} + +func (e *alwaysFailEncoder) EVMTx(tx *types.Transaction) ([]byte, error) { + return nil, errors.New("encoding always fails") +} + +func (e *alwaysFailEncoder) CosmosTx(tx sdk.Tx) ([]byte, error) { + return nil, errors.New("encoding always fails") +} + +func TestAllTransactionsFailEncoding(t *testing.T) { + key, err := crypto.GenerateKey() + require.NoError(t, err) + + // Encoder that always fails + rl := New(&alwaysFailEncoder{}) + + // Add transactions - all will fail during Push + var nonce uint64 + for nonce = 0; nonce < 5; nonce++ { + tx := testEVMTx(t, key, nonce, 21000) + _ = rl.PushEVMTx(tx) // Ignore errors + } + + result := rl.Reap(0, 0) + + // Should return empty as all encodings fail during Push + require.Empty(t, result, "should return empty when all transactions fail encoding") +} + +// Tests for Cosmos transactions + +func TestPushCosmosTx(t *testing.T) { + rl := New(newDeterministicEncoder(100, 150)) + + // Add Cosmos transactions + for i := 0; i < 5; i++ { + tx := newMockCosmosTx(i, 50000) + err := rl.PushCosmosTx(tx) + require.NoError(t, err) + } + + result := rl.Reap(0, 0) + + require.Len(t, result, 5, "should reap all Cosmos transactions") + // Each Cosmos tx should be 150 bytes + for _, txBytes := range result { + require.Len(t, txBytes, 150, "Cosmos tx should have expected size") + } +} + +func TestMixedEVMAndCosmosTx(t *testing.T) { + key, err := crypto.GenerateKey() + require.NoError(t, err) + + // EVM txs are 100 bytes, Cosmos txs are 150 bytes + rl := New(newDeterministicEncoder(100, 150)) + + // Add mixed transactions + evmTx1 := testEVMTx(t, key, 0, 21000) + err = rl.PushEVMTx(evmTx1) + require.NoError(t, err) + + cosmosTx1 := newMockCosmosTx(0, 50000) + err = rl.PushCosmosTx(cosmosTx1) + require.NoError(t, err) + + evmTx2 := testEVMTx(t, key, 1, 30000) + err = rl.PushEVMTx(evmTx2) + require.NoError(t, err) + + cosmosTx2 := newMockCosmosTx(1, 60000) + err = rl.PushCosmosTx(cosmosTx2) + require.NoError(t, err) + + // Reap with byte limit: 100 + 150 + 100 = 350, should get first 3 + result := rl.Reap(350, 0) + require.Len(t, result, 3, "should reap 3 mixed transactions") + + // Verify sizes: 100, 150, 100 + require.Len(t, result[0], 100, "first tx should be EVM (100 bytes)") + require.Len(t, result[1], 150, "second tx should be Cosmos (150 bytes)") + require.Len(t, result[2], 100, "third tx should be EVM (100 bytes)") + + // Reap remaining + result = rl.Reap(0, 0) + require.Len(t, result, 1, "should have 1 Cosmos tx remaining") + require.Len(t, result[0], 150, "remaining tx should be Cosmos (150 bytes)") +} + +func TestCosmosTxWithGasLimit(t *testing.T) { + rl := New(newDeterministicEncoder(100, 100)) + + // Add Cosmos transactions with varying gas + txGases := []uint64{30000, 40000, 50000, 60000} + for i, gas := range txGases { + tx := newMockCosmosTx(i, gas) + err := rl.PushCosmosTx(tx) + require.NoError(t, err) + } + + // Limit to 120000 gas (should get first 3: 30000 + 40000 + 50000 = 120000) + result := rl.Reap(0, 120000) + + require.Len(t, result, 3, "should reap 3 transactions within gas limit") +} + +// selectiveCosmosFailEncoder fails encoding for specific cosmos tx IDs +type selectiveCosmosFailEncoder struct { + failID int +} + +func (e *selectiveCosmosFailEncoder) EVMTx(tx *types.Transaction) ([]byte, error) { + hash := tx.Hash().Bytes() + result := make([]byte, 100) + copy(result, hash) + return result, nil +} + +func (e *selectiveCosmosFailEncoder) CosmosTx(tx sdk.Tx) ([]byte, error) { + mockTx, ok := tx.(*mockCosmosTx) + if ok && mockTx.id == e.failID { + return nil, errors.New("encoding failed for specific tx id") + } + + var txBytes []byte + if ok { + txBytes = []byte(fmt.Sprintf("cosmos-tx-%d", mockTx.id)) + } else { + txBytes = []byte(fmt.Sprintf("cosmos-tx-%p", tx)) + } + + result := make([]byte, 100) + copy(result, txBytes) + return result, nil +} + +func TestCosmosEncodingFailure(t *testing.T) { + // Create encoder that fails for tx with id=1 + failEncoder := &selectiveCosmosFailEncoder{failID: 1} + + rl := New(failEncoder) + + // Add Cosmos transactions - tx with id=1 will fail + for i := 0; i < 5; i++ { + tx := newMockCosmosTx(i, 50000) + _ = rl.PushCosmosTx(tx) // Ignore errors for failing encodings + } + + result := rl.Reap(0, 0) + + // Should get 4 transactions (all except the one that failed) + require.Len(t, result, 4, "should have 4 transactions that succeeded encoding") +} + +// Tests for Drop functionality + +func TestDropEVMTx(t *testing.T) { + key, err := crypto.GenerateKey() + require.NoError(t, err) + + rl := New(newDeterministicEncoder(100, 100)) + + // Add 5 EVM transactions + txs := make([]*types.Transaction, 5) + for i := uint64(0); i < 5; i++ { + tx := testEVMTx(t, key, i, 21000) + txs[i] = tx + err = rl.PushEVMTx(tx) + require.NoError(t, err) + } + + // Drop the middle transaction (index 2) + rl.DropEVMTx(txs[2]) + + // Reap should get 4 transactions (the dropped one should be skipped) + result := rl.Reap(0, 0) + require.Len(t, result, 4, "should reap 4 transactions after dropping 1") +} + +func TestDropCosmosTx(t *testing.T) { + rl := New(newDeterministicEncoder(100, 100)) + + // Add 5 Cosmos transactions + txs := make([]*mockCosmosTx, 5) + for i := 0; i < 5; i++ { + tx := newMockCosmosTx(i, 50000) + txs[i] = tx + err := rl.PushCosmosTx(tx) + require.NoError(t, err) + } + + // Drop the first and last transactions + rl.DropCosmosTx(txs[0]) + rl.DropCosmosTx(txs[4]) + + // Reap should get 3 transactions + result := rl.Reap(0, 0) + require.Len(t, result, 3, "should reap 3 transactions after dropping 2") +} + +func TestDropAfterReap(t *testing.T) { + key, err := crypto.GenerateKey() + require.NoError(t, err) + + rl := New(newDeterministicEncoder(100, 100)) + + // Add 5 transactions + txs := make([]*types.Transaction, 5) + for i := uint64(0); i < 5; i++ { + tx := testEVMTx(t, key, i, 21000) + txs[i] = tx + err = rl.PushEVMTx(tx) + require.NoError(t, err) + } + + // Reap first 3 + result := rl.Reap(300, 0) + require.Len(t, result, 3) + + // Drop one of the reaped transactions (should be no-op since already reaped) + rl.DropEVMTx(txs[1]) + + // Drop one of the remaining transactions + rl.DropEVMTx(txs[4]) + + // Reap remaining should get only 1 transaction (index 3, since 4 was dropped) + result = rl.Reap(0, 0) + require.Len(t, result, 1, "should have 1 transaction remaining after drop") +} + +func TestDropNonExistent(t *testing.T) { + key, err := crypto.GenerateKey() + require.NoError(t, err) + + rl := New(newDeterministicEncoder(100, 100)) + + // Add 3 transactions + for i := uint64(0); i < 3; i++ { + tx := testEVMTx(t, key, i, 21000) + err = rl.PushEVMTx(tx) + require.NoError(t, err) + } + + // Try to drop a transaction that was never added + nonExistentTx := testEVMTx(t, key, 99, 21000) + rl.DropEVMTx(nonExistentTx) + + // Should still have all 3 transactions + result := rl.Reap(0, 0) + require.Len(t, result, 3, "dropping non-existent tx should not affect list") +} + +func TestMixedDrops(t *testing.T) { + key, err := crypto.GenerateKey() + require.NoError(t, err) + + rl := New(newDeterministicEncoder(100, 150)) + + // Add mixed transactions + evmTxs := make([]*types.Transaction, 3) + for i := uint64(0); i < 3; i++ { + tx := testEVMTx(t, key, i, 21000) + evmTxs[i] = tx + err = rl.PushEVMTx(tx) + require.NoError(t, err) + } + + cosmosTxs := make([]*mockCosmosTx, 3) + for i := 0; i < 3; i++ { + tx := newMockCosmosTx(i, 50000) + cosmosTxs[i] = tx + err = rl.PushCosmosTx(tx) + require.NoError(t, err) + } + + // Drop one EVM and one Cosmos tx + rl.DropEVMTx(evmTxs[1]) + rl.DropCosmosTx(cosmosTxs[2]) + + // Should have 4 remaining (2 EVM + 2 Cosmos) + result := rl.Reap(0, 0) + require.Len(t, result, 4, "should have 4 transactions after mixed drops") +} + +// Regression test that verifies that racing PushEVMTx calls with the same hash +// cannot produce a duplicate entry or an orphaned slot. +func TestConcurrentSameHashPush(t *testing.T) { + const iterations = 200 + const workers = 32 + + for i := 0; i < iterations; i++ { + key, err := crypto.GenerateKey() + require.NoError(t, err) + + rl := New(newDeterministicEncoder(100, 100)) + tx := testEVMTx(t, key, 0, 21000) + + var wg sync.WaitGroup + start := make(chan struct{}) + for j := 0; j < workers; j++ { + wg.Add(1) + go func() { + defer wg.Done() + <-start + _ = rl.PushEVMTx(tx) + }() + } + close(start) + wg.Wait() + + result := rl.Reap(0, 0) + require.Lenf(t, result, 1, "iter %d: duplicate reap from concurrent same hash push", i) + + require.NotPanicsf(t, func() { + rl.DropEVMTx(tx) + _ = rl.Reap(0, 0) + }, "iter %d: drop after concurrent push must not orphan a slot", i) + } +} diff --git a/mempool/internal/txtracker/txtracker.go b/mempool/internal/txtracker/txtracker.go new file mode 100644 index 00000000..067287c8 --- /dev/null +++ b/mempool/internal/txtracker/txtracker.go @@ -0,0 +1,213 @@ +package txtracker + +import ( + "context" + "fmt" + "sync" + "time" + + "github.com/ethereum/go-ethereum/common" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/metric" +) + +var meter = otel.Meter("github.com/cosmos/evm/mempool/internal/txtracker") + +var ( + // chainInclusionLatency measures how long it takes for a transaction to go + // from initially being tracked to being included on chain. + chainInclusionLatency metric.Float64Histogram + + // queuedInclusionLatency measures how long it takes for a transaction to + // go from initially being tracked to being included in queued. + queuedInclusionLatency metric.Float64Histogram + + // pendingInclusionLatency measures how long it takes for a transaction to + // go from initially being tracked to being included in pending. + pendingInclusionLatency metric.Float64Histogram + + // queuedDuration is how long a transaction is in the queued pool for + // before exiting. Only recorded on exit (if a tx stays in the pool + // forever, this will not be recorded). + queuedDuration metric.Float64Histogram + + // pendingDuration is how long a transaction is in the pending pool for + // before exiting. Only recorded on exit (if a tx stays in the pool + // forever, this will not be recorded). + pendingDuration metric.Float64Histogram +) + +// Tracker tracks timestamps about important events in a transactions lifecycle +// and exposes metrics about these via prometheus. A no-op implementation is +// returned by NewNoop for use when tracking is disabled. +type Tracker interface { + Track(hash common.Hash) error + EnteredQueued(hash common.Hash) error + ExitedQueued(hash common.Hash) error + EnteredPending(hash common.Hash) error + ExitedPending(hash common.Hash) error + IncludedInBlock(hash common.Hash) error + RemovedFromPending(hash common.Hash) error + RemovedFromQueue(hash common.Hash) error +} + +func init() { + timer := func(name, desc string) metric.Float64Histogram { + m, err := meter.Float64Histogram(name, metric.WithDescription(desc), metric.WithUnit("ms")) + if err != nil { + panic(err) + } + return m + } + + chainInclusionLatency = timer("txpool.tracker.chain_inclusion_latency", "Time from initial tracking to inclusion on chain") + queuedInclusionLatency = timer("txpool.tracker.queued_inclusion_latency", "Time from initial tracking to entering the queued pool") + pendingInclusionLatency = timer("txpool.tracker.pending_inclusion_latency", "Time from initial tracking to entering the pending pool") + queuedDuration = timer("txpool.tracker.queued_duration", "Time spent in the queued pool before exit") + pendingDuration = timer("txpool.tracker.pending_duration", "Time spent in the pending pool before exit") +} + +func recordSince(h metric.Float64Histogram, start time.Time) { + h.Record(context.Background(), float64(time.Since(start).Milliseconds())) +} + +// TxTracker tracks timestamps about important events in a transactions +// lifecycle and exposes metrics about these via otel. +type TxTracker struct { + txCheckpoints map[common.Hash]*checkpoints + lock sync.RWMutex +} + +// New creates a new Tracker instance. +func New() *TxTracker { + return &TxTracker{ + txCheckpoints: make(map[common.Hash]*checkpoints), + } +} + +// Track initializes tracking for a tx. This should only be called from +// SendRawTransaction when a tx enters this node via a RPC. +func (t *TxTracker) Track(hash common.Hash) error { + t.lock.Lock() + defer t.lock.Unlock() + + if _, alreadyTracked := t.txCheckpoints[hash]; alreadyTracked { + return fmt.Errorf("tx %s already being tracked", hash) + } + + t.txCheckpoints[hash] = &checkpoints{TrackedAt: time.Now()} + return nil +} + +func (t *TxTracker) EnteredQueued(hash common.Hash) error { + checkpoints, err := t.getCheckpointsIfTracked(hash) + if err != nil { + return fmt.Errorf("getting checkpoints for hash %s: %w", hash, err) + } + + checkpoints.LastEnteredQueuedPoolAt = time.Now() + recordSince(queuedInclusionLatency, checkpoints.TrackedAt) + return nil +} + +func (t *TxTracker) ExitedQueued(hash common.Hash) error { + checkpoints, err := t.getCheckpointsIfTracked(hash) + if err != nil { + return fmt.Errorf("getting checkpoints for hash %s: %w", hash, err) + } + + if checkpoints.LastEnteredQueuedPoolAt.IsZero() { + // It is possible that a tx never entered the queued pool when we call + // this (directly replaced a tx in the pending pool). In this case we + // dont record the duration + return nil + } + recordSince(queuedDuration, checkpoints.LastEnteredQueuedPoolAt) + return nil +} + +func (t *TxTracker) EnteredPending(hash common.Hash) error { + checkpoints, err := t.getCheckpointsIfTracked(hash) + if err != nil { + return fmt.Errorf("getting checkpoints for hash %s: %w", hash, err) + } + + checkpoints.LastEnteredPendingPoolAt = time.Now() + recordSince(pendingInclusionLatency, checkpoints.TrackedAt) + return nil +} + +func (t *TxTracker) ExitedPending(hash common.Hash) error { + checkpoints, err := t.getCheckpointsIfTracked(hash) + if err != nil { + return fmt.Errorf("getting checkpoints for hash %s: %w", hash, err) + } + + recordSince(pendingDuration, checkpoints.LastEnteredPendingPoolAt) + return nil +} + +func (t *TxTracker) IncludedInBlock(hash common.Hash) error { + checkpoints, err := t.getCheckpointsIfTracked(hash) + if err != nil { + return fmt.Errorf("getting checkpoints for hash %s: %w", hash, err) + } + + recordSince(chainInclusionLatency, checkpoints.TrackedAt) + return nil +} + +func (t *TxTracker) RemovedFromPending(hash common.Hash) error { + defer t.removeTx(hash) + return t.ExitedPending(hash) +} + +func (t *TxTracker) RemovedFromQueue(hash common.Hash) error { + defer t.removeTx(hash) + return t.ExitedQueued(hash) +} + +func (t *TxTracker) getCheckpointsIfTracked(hash common.Hash) (*checkpoints, error) { + t.lock.RLock() + defer t.lock.RUnlock() + + checkpoints, alreadyTracked := t.txCheckpoints[hash] + if !alreadyTracked { + return nil, fmt.Errorf("tx not already being tracked") + } + return checkpoints, nil +} + +// removeTx removes a tx by hash. +func (t *TxTracker) removeTx(hash common.Hash) { + t.lock.Lock() + defer t.lock.Unlock() + delete(t.txCheckpoints, hash) +} + +// checkpoints is a set of important timestamps across a transactions lifecycle +// in the mempool. +type checkpoints struct { + TrackedAt time.Time + + LastEnteredQueuedPoolAt time.Time + + LastEnteredPendingPoolAt time.Time +} + +// noopTracker implements Tracker but performs no work. It is used when tx +// tracking is disabled via config so that callers can keep an unconditional +// tracker reference. +type noopTracker struct{} + +// NewNoop returns a Tracker that records nothing. +func NewNoop() Tracker { return noopTracker{} } + +func (noopTracker) Track(common.Hash) error { return nil } +func (noopTracker) EnteredQueued(common.Hash) error { return nil } +func (noopTracker) ExitedQueued(common.Hash) error { return nil } +func (noopTracker) EnteredPending(common.Hash) error { return nil } +func (noopTracker) ExitedPending(common.Hash) error { return nil } +func (noopTracker) IncludedInBlock(common.Hash) error { return nil } +func (noopTracker) RemovedFromPending(common.Hash) error { return nil } +func (noopTracker) RemovedFromQueue(common.Hash) error { return nil } diff --git a/mempool/iterator.go b/mempool/iterator.go index b7a75b91..39254487 100644 --- a/mempool/iterator.go +++ b/mempool/iterator.go @@ -1,6 +1,7 @@ package mempool import ( + "fmt" "math/big" ethtypes "github.com/ethereum/go-ethereum/core/types" @@ -10,14 +11,31 @@ import ( "github.com/cosmos/evm/mempool/txpool" msgtypes "github.com/cosmos/evm/x/vm/types" - "cosmossdk.io/log" - "cosmossdk.io/math" + "cosmossdk.io/log/v2" "github.com/cosmos/cosmos-sdk/client" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/mempool" ) +// nextAction is the type of action that the iterator should take based on the +// current transaction selection +type nextAction int + +const ( + // none signals that no action should be taken for this iterator + none nextAction = iota + + // advance signals to the iterator that it should move the iterator + // pointer to the next best tx + advance + + // skipAccount signals to the iterator that it should move the iterator + // pointer past all txs for this account, to the next best tx that is not + // for this account + skipAccount +) + var _ mempool.Iterator = &EVMMempoolIterator{} // EVMMempoolIterator provides a unified iterator over both EVM and Cosmos transactions in the mempool. @@ -29,6 +47,18 @@ type EVMMempoolIterator struct { evmIterator *miner.TransactionsByPriceAndNonce cosmosIterator mempool.Iterator + // currentTx is the preferred tx to return via Tx() based on the state of + // both internal iterators + currentTx sdk.Tx + + // nextEVMAction is the action that the evm iterator should take on the next + // call to Next() + nextEVMAction nextAction + + // nextCosmosAction is the action that the cosmos iterator should take on the next + // call to Next() + nextCosmosAction nextAction + /** Utils **/ logger log.Logger txConfig client.TxConfig @@ -36,143 +66,183 @@ type EVMMempoolIterator struct { /** Chain Params **/ bondDenom string chainID *big.Int - - /** Blockchain Access **/ - blockchain *Blockchain + baseFee *uint256.Int // cached on iterator creation + ethSigner ethtypes.Signer // cached on iterator creation } // NewEVMMempoolIterator creates a new unified iterator over EVM and Cosmos transactions. // It combines iterators from both transaction pools and selects transactions based on fee priority. // Returns nil if both iterators are empty or nil. The bondDenom parameter specifies the native // token denomination for fee comparisons, and chainId is used for EVM transaction conversion. -func NewEVMMempoolIterator(evmIterator *miner.TransactionsByPriceAndNonce, cosmosIterator mempool.Iterator, logger log.Logger, txConfig client.TxConfig, bondDenom string, chainID *big.Int, blockchain *Blockchain) mempool.Iterator { - // Check if we have any transactions at all +func NewEVMMempoolIterator( + evmIterator *miner.TransactionsByPriceAndNonce, + cosmosIterator mempool.Iterator, + logger log.Logger, + txConfig client.TxConfig, + blockchain *Blockchain, +) mempool.Iterator { hasEVM := evmIterator != nil && !evmIterator.Empty() hasCosmos := cosmosIterator != nil && cosmosIterator.Tx() != nil - // Add the iterator name to the logger - logger = logger.With(log.ModuleKey, "EVMMempoolIterator") - if !hasEVM && !hasCosmos { - logger.Debug("no transactions available in either mempool") return nil } - return &EVMMempoolIterator{ - evmIterator: evmIterator, - cosmosIterator: cosmosIterator, - logger: logger, - txConfig: txConfig, - bondDenom: bondDenom, - chainID: chainID, - blockchain: blockchain, + iter := &EVMMempoolIterator{ + evmIterator: evmIterator, + cosmosIterator: cosmosIterator, + nextEVMAction: none, + nextCosmosAction: none, + logger: logger, + txConfig: txConfig, + bondDenom: blockchain.GetCoinDenom(), + chainID: blockchain.Config().ChainID, + ethSigner: ethtypes.LatestSignerForChainID(blockchain.Config().ChainID), + baseFee: currentBaseFee(blockchain), } + + // setup internal currentTx state + iter.resolveCurrentTx() + + // if there is no currentTx, we have no txs to return + if iter.currentTx == nil { + return nil + } + + return iter } // Next advances the iterator to the next transaction and returns the updated iterator. // It determines which iterator (EVM or Cosmos) provided the current transaction and advances // that iterator accordingly. Returns nil when no more transactions are available. func (i *EVMMempoolIterator) Next() mempool.Iterator { - // Get next transactions on both iterators to determine which iterator to advance - nextEVMTx, _ := i.getNextEVMTx() - nextCosmosTx, _ := i.getNextCosmosTx() + // increment iterators forward based on action that was determined to be + // taken previous call to Next() + i.handleNextEVMAction() + i.handleNextCosmosAction() - // If no transactions available, we're done - if nextEVMTx == nil && nextCosmosTx == nil { - i.logger.Debug("no more transactions available, ending iteration") + // resolve the next preferred transaction + i.resolveCurrentTx() + + if i.currentTx == nil { return nil } - i.logger.Debug("advancing to next transaction", "has_evm", nextEVMTx != nil, "has_cosmos", nextCosmosTx != nil) - - // Advance the iterator that provided the current transaction - i.advanceCurrentIterator() + return i +} - // Check if we still have transactions after advancing - if !i.hasMoreTransactions() { - i.logger.Debug("no more transactions after advancing, ending iteration") - return nil +// handleNextEVMAction increments evm iterator state based on nextEVMAction +func (i *EVMMempoolIterator) handleNextEVMAction() { + switch i.nextEVMAction { + case advance: + if i.evmIterator != nil { + i.evmIterator.Shift() + } + case skipAccount: + if i.evmIterator != nil { + i.evmIterator.Pop() + } + case none: + // no action } + i.nextEVMAction = none +} - return i +// handleNextCosmosAction increments cosmos iterator state based on +// nextCosmosAction +func (i *EVMMempoolIterator) handleNextCosmosAction() { + switch i.nextCosmosAction { + case advance: + if i.cosmosIterator != nil { + i.cosmosIterator = i.cosmosIterator.Next() + } + case skipAccount: + // no action for cosmos + case none: + // no action + } + i.nextCosmosAction = none } // Tx returns the current transaction from the iterator. -// It selects between EVM and Cosmos transactions based on fee priority -// and converts EVM transactions to SDK format. func (i *EVMMempoolIterator) Tx() sdk.Tx { - // Get current transactions from both iterators - nextEVMTx, _ := i.getNextEVMTx() - nextCosmosTx, _ := i.getNextCosmosTx() + return i.currentTx +} - i.logger.Debug("getting current transaction", "has_evm", nextEVMTx != nil, "has_cosmos", nextCosmosTx != nil) +// resolveCurrentTx determines the preferred transaction between the EVM and Cosmos +// iterators and caches it. This is called once at construction and once after each +// advance, eliminating all redundant fee calculations and iterator peeks. +func (i *EVMMempoolIterator) resolveCurrentTx() { + evmTx, evmFee := i.peekEVM() + cosmosTx, cosmosFee := i.peekCosmos() + + if evmTx == nil && cosmosTx == nil { + i.nextEVMAction, i.nextCosmosAction = none, none + i.currentTx = nil + return + } - // Return the preferred transaction based on fee priority - tx := i.getPreferredTransaction(nextEVMTx, nextCosmosTx) + if i.shouldSelectEVMTx(evmTx, evmFee, cosmosTx, cosmosFee) { + sdkTx, err := i.convertEVMToSDKTx(evmTx) + if err == nil { + i.nextEVMAction = advance + i.currentTx = sdkTx + return + } + i.logger.Error("EVM transaction conversion failed, falling back to Cosmos transaction", "tx_hash", evmTx.Hash, "err", err) - if tx == nil { - i.logger.Debug("no preferred transaction available") - } else { - i.logger.Debug("returning preferred transaction") + // conversion failed, this tx will not be included in the list of + // returned txs by this iterator, therefore, fall future txs for this + // account will be invalid, thus we should skip all future txs for this + // account + i.nextEVMAction = skipAccount + + // we are skipping the above account, and falling back to using the + // current cosmos tx. technically, the next accounts evm tx may be a + // higher fee } - return tx + i.nextCosmosAction = advance + i.currentTx = cosmosTx } -// ============================================================================= -// UTILITY FUNCTIONS -// ============================================================================= - -// shouldUseEVM determines which transaction type to prioritize based on fee comparison. -// Returns true if the EVM transaction should be selected, false if Cosmos transaction should be used. -// EVM transactions will be prioritized in the following conditions: -// 1. Cosmos mempool has no transactions -// 2. EVM mempool has no transactions (fallback to Cosmos) -// 3. Cosmos transaction has no fee information -// 4. Cosmos transaction fee denomination doesn't match bond denom -// 5. Cosmos transaction fee is lower than the EVM transaction fee -// 6. Cosmos transaction fee overflows when converted to uint256 -func (i *EVMMempoolIterator) shouldUseEVM() bool { - // Get next transactions from both iterators - nextEVMTx, evmFee := i.getNextEVMTx() - nextCosmosTx, cosmosFee := i.getNextCosmosTx() - - // Handle cases where only one type is available - if nextEVMTx == nil { - i.logger.Debug("no EVM transaction available, preferring Cosmos") - return false // Use Cosmos when no EVM transaction available +// shouldSelectEVMTx determines if the EVM tx should be used based on a fee +// comparison. Returns true if the evmTx should be selected, false if the +// cosmosTx. +func (i *EVMMempoolIterator) shouldSelectEVMTx( + evmTx *txpool.LazyTransaction, + evmFee *uint256.Int, + cosmosTx sdk.Tx, + cosmosFee *uint256.Int, +) bool { + if evmTx == nil { + return false } - if nextCosmosTx == nil { - i.logger.Debug("no Cosmos transaction available, preferring EVM") - return true // Use EVM when no Cosmos transaction available + if cosmosTx == nil { + return true } - // Both have transactions - compare fees - // cosmosFee can never be nil, but can be zero if no valid fee found + // both have transactions - compare fees if cosmosFee.IsZero() { - i.logger.Debug("Cosmos transaction has no valid fee, preferring EVM", "evm_fee", evmFee.String()) - return true // Use EVM if Cosmos transaction has no valid fee + return true // use EVM if Cosmos transaction has no valid fee } - // Compare fees - prefer EVM unless Cosmos has higher fee - cosmosHigher := cosmosFee.Gt(evmFee) - i.logger.Debug("comparing transaction fees", - "evm_fee", evmFee.String(), - "cosmos_fee", cosmosFee.String()) - - return !cosmosHigher + // prefer EVM unless Cosmos has strictly higher fee + return !cosmosFee.Gt(evmFee) } -// getNextEVMTx retrieves the next EVM transaction and its fee -func (i *EVMMempoolIterator) getNextEVMTx() (*txpool.LazyTransaction, *uint256.Int) { +// peekEVM retrieves the next EVM transaction and its fee effective gas tip +// without advancing. +func (i *EVMMempoolIterator) peekEVM() (*txpool.LazyTransaction, *uint256.Int) { if i.evmIterator == nil { return nil, nil } return i.evmIterator.Peek() } -// getNextCosmosTx retrieves the next Cosmos transaction and its effective gas tip -func (i *EVMMempoolIterator) getNextCosmosTx() (sdk.Tx, *uint256.Int) { +// peekCosmos retrieves the next Cosmos transaction and its effective gas tip +// without advancing. +func (i *EVMMempoolIterator) peekCosmos() (sdk.Tx, *uint256.Int) { if i.cosmosIterator == nil { return nil, nil } @@ -182,176 +252,57 @@ func (i *EVMMempoolIterator) getNextCosmosTx() (sdk.Tx, *uint256.Int) { return nil, nil } - // Extract effective gas tip from the transaction (gas price - base fee) - cosmosEffectiveTip := i.extractCosmosEffectiveTip(tx) - if cosmosEffectiveTip == nil { - return tx, uint256.NewInt(0) // Return zero fee if no valid fee found + tip := i.extractCosmosEffectiveTip(tx) + if tip == nil { + return tx, uint256.NewInt(0) } - return tx, cosmosEffectiveTip -} - -// getPreferredTransaction returns the preferred transaction based on fee priority. -// Takes both transaction types as input and returns the preferred one, or nil if neither is available. -func (i *EVMMempoolIterator) getPreferredTransaction(nextEVMTx *txpool.LazyTransaction, nextCosmosTx sdk.Tx) sdk.Tx { - // If no transactions available, return nil - if nextEVMTx == nil && nextCosmosTx == nil { - i.logger.Debug("no transactions available from either mempool") - return nil - } - - // Determine which transaction type to prioritize based on fee comparison - useEVM := i.shouldUseEVM() - - if useEVM { - i.logger.Debug("preferring EVM transaction based on fee comparison") - // Prefer EVM transaction if available and convertible - if nextEVMTx != nil { - if evmTx := i.convertEVMToSDKTx(nextEVMTx); evmTx != nil { - return evmTx - } - } - // Fall back to Cosmos if EVM is not available or conversion fails - i.logger.Debug("EVM transaction conversion failed, falling back to Cosmos transaction") - return nextCosmosTx - } - - // Prefer Cosmos transaction - i.logger.Debug("preferring Cosmos transaction based on fee comparison") - return nextCosmosTx -} - -// advanceCurrentIterator advances the appropriate iterator based on which transaction was used -func (i *EVMMempoolIterator) advanceCurrentIterator() { - useEVM := i.shouldUseEVM() - - if useEVM { - i.logger.Debug("advancing EVM iterator") - // We used EVM transaction, advance EVM iterator - // NOTE: EVM transactions are automatically removed by the maintenance loop in the txpool - // so we shift instead of popping - if i.evmIterator != nil { - i.evmIterator.Shift() - } else { - i.logger.Error("EVM iterator is nil but shouldUseEVM returned true") - } - } else { - i.logger.Debug("advancing Cosmos iterator") - // We used Cosmos transaction (or EVM failed), advance Cosmos iterator - if i.cosmosIterator != nil { - i.cosmosIterator = i.cosmosIterator.Next() - } else { - i.logger.Error("Cosmos iterator is nil but shouldUseEVM returned false") - } - } + return tx, tip } // extractCosmosEffectiveTip extracts the effective gas tip from a Cosmos transaction // This aligns with EVM transaction prioritization by calculating: gas_price - base_fee func (i *EVMMempoolIterator) extractCosmosEffectiveTip(tx sdk.Tx) *uint256.Int { - feeTx, ok := tx.(sdk.FeeTx) - if !ok { - i.logger.Debug("Cosmos transaction doesn't implement FeeTx interface") - return nil // Transaction doesn't implement FeeTx interface - } - - bondDenomFeeAmount := math.ZeroInt() - fees := feeTx.GetFee() - for _, coin := range fees { - if coin.Denom == i.bondDenom { - i.logger.Debug("found fee in bond denomination", "denom", coin.Denom, "amount", coin.Amount.String()) - bondDenomFeeAmount = coin.Amount - } - } + return extractCosmosEffectiveTip(tx, i.bondDenom, i.baseFee) +} - // Calculate gas price: fee_amount / gas_limit - gasPrice, overflow := uint256.FromBig(bondDenomFeeAmount.Quo(math.NewIntFromUint64(feeTx.GetGas())).BigInt()) - if overflow { - i.logger.Debug("overflowed on gas price calculation") - return nil +// convertEVMToSDKTx converts an Ethereum transaction to a Cosmos SDK transaction. +// It wraps the EVM transaction in a MsgEthereumTx and builds a proper SDK transaction +// using the configured transaction builder and bond denomination for fees. +func (i *EVMMempoolIterator) convertEVMToSDKTx(nextEVMTx *txpool.LazyTransaction) (sdk.Tx, error) { + if nextEVMTx == nil { + return nil, fmt.Errorf("next evm tx is nil") } - // Get current base fee from blockchain StateDB - baseFee := i.getCurrentBaseFee() - if baseFee == nil { - // No base fee, return gas price as effective tip - i.logger.Debug("no base fee available, using gas price as effective tip", "gas_price", gasPrice.String()) - return gasPrice + var msgEthereumTx msgtypes.MsgEthereumTx + if err := msgEthereumTx.FromSignedEthereumTx(nextEVMTx.Tx, i.ethSigner); err != nil { + return nil, fmt.Errorf("converting signed evm transaction: %w", err) } - // Calculate effective tip: gas_price - base_fee - if gasPrice.Cmp(baseFee) < 0 { - // Gas price is lower than base fee, return zero effective tip - i.logger.Debug("gas price lower than base fee, effective tip is zero", "gas_price", gasPrice.String(), "base_fee", baseFee.String()) - return uint256.NewInt(0) + cosmosTx, err := msgEthereumTx.BuildTx(i.txConfig.NewTxBuilder(), i.bondDenom) + if err != nil { + return nil, fmt.Errorf("building cosmos tx from evm tx: %w", err) } - effectiveTip := new(uint256.Int).Sub(gasPrice, baseFee) - i.logger.Debug("calculated effective tip", "gas_price", gasPrice.String(), "base_fee", baseFee.String(), "effective_tip", effectiveTip.String()) - return effectiveTip + return cosmosTx, nil } -// getCurrentBaseFee retrieves the current base fee from the blockchain StateDB -func (i *EVMMempoolIterator) getCurrentBaseFee() *uint256.Int { - if i.blockchain == nil { - i.logger.Debug("blockchain not available, cannot get base fee") - return nil - } - - // Get the current block header to access the base fee - header := i.blockchain.CurrentBlock() - if header == nil { - i.logger.Debug("failed to get current block header") +// currentBaseFee gets the current baseFee from the Blockchain based on the +// latest block. +func currentBaseFee(blockchain *Blockchain) *uint256.Int { + if blockchain == nil { return nil } - // Get base fee from the header - baseFee := header.BaseFee - if baseFee == nil { - i.logger.Debug("no base fee in current block header") + header := blockchain.CurrentBlock() + if header == nil || header.BaseFee == nil { return nil } - // Convert to uint256 - baseFeeUint, overflow := uint256.FromBig(baseFee) + baseFeeUint, overflow := uint256.FromBig(header.BaseFee) if overflow { - i.logger.Debug("base fee overflow when converting to uint256") return nil } - i.logger.Debug("retrieved current base fee from blockchain", "base_fee", baseFeeUint.String()) return baseFeeUint } - -// hasMoreTransactions checks if there are more transactions available in either iterator -func (i *EVMMempoolIterator) hasMoreTransactions() bool { - nextEVMTx, _ := i.getNextEVMTx() - nextCosmosTx, _ := i.getNextCosmosTx() - return nextEVMTx != nil || nextCosmosTx != nil -} - -// convertEVMToSDKTx converts an Ethereum transaction to a Cosmos SDK transaction. -// It wraps the EVM transaction in a MsgEthereumTx and builds a proper SDK transaction -// using the configured transaction builder and bond denomination for fees. -func (i *EVMMempoolIterator) convertEVMToSDKTx(nextEVMTx *txpool.LazyTransaction) sdk.Tx { - if nextEVMTx == nil { - i.logger.Debug("EVM transaction is nil, skipping conversion") - return nil - } - - 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", 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", hash) - return nil - } - - i.logger.Debug("successfully converted EVM transaction to Cosmos transaction", "tx_hash", hash) - return cosmosTx -} diff --git a/mempool/iterator_bench_test.go b/mempool/iterator_bench_test.go new file mode 100644 index 00000000..0c92c2b5 --- /dev/null +++ b/mempool/iterator_bench_test.go @@ -0,0 +1,370 @@ +package mempool_test + +import ( + "context" + "crypto/ecdsa" + "math/big" + "strconv" + "testing" + "time" + + "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/holiman/uint256" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + cmttypes "github.com/cometbft/cometbft/types" + + "github.com/cosmos/evm/crypto/ethsecp256k1" + "github.com/cosmos/evm/encoding" + evmmempool "github.com/cosmos/evm/mempool" + "github.com/cosmos/evm/mempool/mocks" + "github.com/cosmos/evm/mempool/txpool/legacypool" + "github.com/cosmos/evm/testutil/constants" + testutiltx "github.com/cosmos/evm/testutil/tx" + "github.com/cosmos/evm/x/vm/statedb" + vmtypes "github.com/cosmos/evm/x/vm/types" + + "cosmossdk.io/log/v2" + sdkmath "cosmossdk.io/math" + + "github.com/cosmos/cosmos-sdk/client" + cosmostx "github.com/cosmos/cosmos-sdk/client/tx" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" + "github.com/cosmos/cosmos-sdk/testutil" + sdk "github.com/cosmos/cosmos-sdk/types" + sdktxsigning "github.com/cosmos/cosmos-sdk/types/tx/signing" + authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +const ( + benchBondDenom = "aatom" + benchEVMPerAccount = 250 + benchBlockGasLimit = 30_000_000 + benchTxGas = uint64(21_000) + benchBalance = uint64(1_000_000_000_000_000_000) // 1e18 +) + +// BenchmarkEVMMempoolIterator benchmarks the EVMMempoolIterator's SelectBy +// performance with mocked blockchain dependencies. +func BenchmarkEVMMempoolIterator(b *testing.B) { + cases := []struct { + name string + numEVM int + numCosmos int + }{ + {"EVM_50/Cosmos_0", 50, 0}, + {"EVM_500/Cosmos_0", 500, 0}, + {"EVM_1000/Cosmos_0", 1000, 0}, + {"EVM_2500/Cosmos_0", 2500, 0}, + {"EVM_5000/Cosmos_0", 5000, 0}, + {"EVM_10000/Cosmos_0", 10000, 0}, + {"EVM_0/Cosmos_50", 0, 50}, + {"EVM_0/Cosmos_500", 0, 500}, + {"EVM_0/Cosmos_1000", 0, 1000}, + {"EVM_0/Cosmos_2500", 0, 2500}, + {"EVM_0/Cosmos_5000", 0, 5000}, + {"EVM_0/Cosmos_10000", 0, 10000}, + {"EVM_50/Cosmos_50", 50, 50}, + {"EVM_500/Cosmos_500", 500, 500}, + {"EVM_1000/Cosmos_1000", 1000, 1000}, + {"EVM_2500/Cosmos_2500", 2500, 2500}, + {"EVM_5000/Cosmos_5000", 5000, 5000}, + } + + for _, tc := range cases { + b.Run(tc.name, func(b *testing.B) { + b.StopTimer() + + evmAccountCount := benchEVMAccountsNeeded(tc.numEVM) + cosmosAccountCount := tc.numCosmos + + // Generate all EVM account keys + evmAccounts := make([]benchAccount, evmAccountCount) + for i := range evmAccountCount { + key, err := crypto.GenerateKey() + require.NoError(b, err) + evmAccounts[i] = benchAccount{ + key: key, + address: crypto.PubkeyToAddress(key.PublicKey), + } + } + + // Generate all Cosmos account keys + cosmosAccounts := make([]benchAccount, cosmosAccountCount) + for i := range cosmosAccountCount { + key, err := crypto.GenerateKey() + require.NoError(b, err) + cosmosAccounts[i] = benchAccount{ + key: key, + address: crypto.PubkeyToAddress(key.PublicKey), + } + } + + ctx, txConfig, mpool := setupBenchMempool(b, evmAccounts, cosmosAccounts) + + recipientAddr, _ := testutiltx.NewAddrKey() + chainID := vmtypes.GetEthChainConfig().ChainID + ethSigner := ethtypes.LatestSignerForChainID(chainID) + gasPrice := big.NewInt(2_000_000_000) + + // Insert EVM transactions + for i, acc := range evmAccounts { + count := benchTxsForAccount(tc.numEVM, evmAccountCount, i) + for nonce := range count { + msgEthTx := vmtypes.NewTx(&vmtypes.EvmTxArgs{ + Nonce: uint64(nonce), //#nosec G115 + To: &recipientAddr, + Amount: big.NewInt(1000), + GasLimit: benchTxGas, + GasPrice: gasPrice, + ChainID: chainID, + }) + msgEthTx.From = acc.address.Bytes() + require.NoError(b, msgEthTx.Sign(ethSigner, testutiltx.NewSigner(benchPrivKeyToCosmos(b, acc.key)))) + + tx, err := msgEthTx.BuildTx(txConfig.NewTxBuilder(), benchBondDenom) + require.NoError(b, err) + require.NoError(b, mpool.Insert(ctx, tx)) + } + } + + // Insert Cosmos transactions + for _, acc := range cosmosAccounts { + cosmosPrivKey := benchPrivKeyToCosmos(b, acc.key) + fromAddr := sdk.AccAddress(cosmosPrivKey.PubKey().Address().Bytes()) + toAddr := sdk.AccAddress(recipientAddr.Bytes()) + + msg := banktypes.NewMsgSend(fromAddr, toAddr, + sdk.NewCoins(sdk.NewInt64Coin(benchBondDenom, 1000))) + + tx, err := buildBenchCosmosTx(txConfig, cosmosPrivKey, msg, gasPrice) + require.NoError(b, err) + require.NoError(b, mpool.Insert(ctx, tx)) + } + + expectedCount := tc.numEVM + tc.numCosmos + require.Equal(b, expectedCount, mpool.CountTx(), "mempool should contain all inserted transactions") + + selectCtx := ctx.WithBlockHeight(ctx.BlockHeight() + 1) + + b.Cleanup(func() { + _ = mpool.Close() + }) + + b.ReportAllocs() + b.StartTimer() + + for b.Loop() { + mpool.SelectBy(selectCtx, nil, func(sdk.Tx) bool { return true }) + } + }) + } +} + +type benchAccount struct { + key *ecdsa.PrivateKey + address common.Address +} + +// benchPrivKeyToCosmos converts an ECDSA private key to a Cosmos SDK private key. +func benchPrivKeyToCosmos(b *testing.B, key *ecdsa.PrivateKey) cryptotypes.PrivKey { + b.Helper() + privBytes := crypto.FromECDSA(key) + cosmosKey := ðsecp256k1.PrivKey{Key: privBytes} + return cosmosKey +} + +// setupBenchMempool creates an Mempool with mocked state. +func setupBenchMempool(b *testing.B, evmAccounts, cosmosAccounts []benchAccount) (sdk.Context, client.TxConfig, *evmmempool.Mempool) { + b.Helper() + + ethCfg := vmtypes.DefaultChainConfig(constants.EighteenDecimalsChainID) + _ = vmtypes.SetChainConfig(ethCfg) // ignore if already set + + _ = vmtypes.NewEVMConfigurator(). + WithEVMCoinInfo(constants.ChainsCoinInfo[constants.EighteenDecimalsChainID]). + Configure() // ignore if already configured + + mockVMKeeper := mocks.NewVMKeeperI(b) + mockVMKeeper.On("GetBaseFee", mock.Anything).Return(big.NewInt(1e9)).Maybe() + mockVMKeeper.On("GetParams", mock.Anything).Return(vmtypes.DefaultParams()).Maybe() + mockVMKeeper.On("GetEvmCoinInfo", mock.Anything).Return(constants.ChainsCoinInfo[constants.EighteenDecimalsChainID]).Maybe() + + mockFeeMarketKeeper := mocks.NewFeeMarketKeeper(b) + mockFeeMarketKeeper.On("GetBlockGasWanted", mock.Anything).Return(uint64(10_000_000)).Maybe() + + // Register each account with proper balance + for _, acc := range evmAccounts { + mockVMKeeper.On("GetAccount", mock.Anything, acc.address).Return(&statedb.Account{ + Nonce: 0, + Balance: uint256.NewInt(benchBalance), + }).Maybe() + mockVMKeeper.On("GetNonce", acc.address).Return(uint64(0)).Maybe() + mockVMKeeper.On("GetBalance", acc.address).Return(uint256.NewInt(benchBalance)).Maybe() + mockVMKeeper.On("GetCodeHash", acc.address).Return(common.Hash{}).Maybe() + } + for _, acc := range cosmosAccounts { + mockVMKeeper.On("GetAccount", mock.Anything, acc.address).Return(&statedb.Account{ + Nonce: 0, + Balance: uint256.NewInt(benchBalance), + }).Maybe() + mockVMKeeper.On("GetNonce", acc.address).Return(uint64(0)).Maybe() + mockVMKeeper.On("GetBalance", acc.address).Return(uint256.NewInt(benchBalance)).Maybe() + mockVMKeeper.On("GetCodeHash", acc.address).Return(common.Hash{}).Maybe() + } + + mockVMKeeper.On("GetState", mock.Anything, mock.Anything).Return(common.Hash{}).Maybe() + mockVMKeeper.On("GetCode", mock.Anything, mock.Anything).Return([]byte{}).Maybe() + mockVMKeeper.On("ForEachStorage", mock.Anything, mock.Anything, mock.Anything).Maybe() + mockVMKeeper.On("KVStoreKeys").Return(make(map[string]*storetypes.KVStoreKey)).Maybe() + mockVMKeeper.On("SetEvmMempool", mock.Anything).Maybe() + + var latestHeight int64 = 1 + + getCtxCallback := func(height int64, _ bool) (sdk.Context, error) { + storeKey := storetypes.NewKVStoreKey("test") + transientKey := storetypes.NewTransientStoreKey("transient_test") + ctx := testutil.DefaultContext(storeKey, transientKey) + if height == 0 { + height = latestHeight + } + return ctx. + WithBlockTime(time.Now()). + WithBlockHeader(cmtproto.Header{AppHash: []byte("00000000000000000000000000000000")}). + WithBlockHeight(height). + WithChainID(strconv.Itoa(constants.EighteenDecimalsChainID)), nil + } + + encodingConfig := encoding.MakeConfig(constants.EighteenDecimalsChainID) + vmtypes.RegisterInterfaces(encodingConfig.InterfaceRegistry) + txConfig := encodingConfig.TxConfig + + clientCtx := client.Context{}. + WithCodec(encodingConfig.Codec). + WithInterfaceRegistry(encodingConfig.InterfaceRegistry). + WithTxConfig(txConfig) + + legacyConfig := legacypool.DefaultConfig + legacyConfig.Journal = "" + legacyConfig.PriceLimit = 1 + legacyConfig.PriceBump = 10 + legacyConfig.GlobalSlots = 500_000 + legacyConfig.AccountSlots = 500_000 + + noopAnteHandler := func(ctx sdk.Context, _ sdk.Tx, _ bool) (sdk.Context, error) { + return ctx, nil + } + + config := &evmmempool.Config{ + LegacyPoolConfig: &legacyConfig, + BlockGasLimit: benchBlockGasLimit, + MinTip: uint256.NewInt(0), + AnteHandler: noopAnteHandler, + + PendingTxProposalTimeout: 200 * time.Millisecond, + InsertQueueSize: 10_000, + } + + txEncoder := evmmempool.NewTxEncoder(txConfig) + evmRechecker := evmmempool.NewTxRechecker(noopAnteHandler, txEncoder) + cosmosRechecker := evmmempool.NewTxRechecker(noopAnteHandler, txEncoder) + mpool := evmmempool.NewMempool( + getCtxCallback, + log.NewNopLogger(), + mockVMKeeper, + mockFeeMarketKeeper, + txConfig, + evmRechecker, + cosmosRechecker, + config, + 0, + ) + + mpool.SetClientCtx(clientCtx) + require.NotNil(b, mpool) + + // Start EventBus and attach to mempool (required for tx pool reorg loop) + eventBus := cmttypes.NewEventBus() + require.NoError(b, eventBus.Start()) + mpool.SetEventBus(eventBus) + + b.Cleanup(func() { + _ = eventBus.Stop() + }) + + ctx, err := getCtxCallback(latestHeight, false) + require.NoError(b, err) + + return ctx, txConfig, mpool +} + +// buildBenchCosmosTx creates a signed Cosmos SDK transaction without a running network. +func buildBenchCosmosTx(txConfig client.TxConfig, privKey cryptotypes.PrivKey, msg sdk.Msg, gasPrice *big.Int) (authsigning.Tx, error) { + txBuilder := txConfig.NewTxBuilder() + + if err := txBuilder.SetMsgs(msg); err != nil { + return nil, err + } + + txBuilder.SetGasLimit(benchTxGas) + feeAmount := new(big.Int).Mul(gasPrice, big.NewInt(int64(benchTxGas))) //#nosec G115 + txBuilder.SetFeeAmount(sdk.NewCoins(sdk.NewCoin(benchBondDenom, sdkmath.NewIntFromBigInt(feeAmount)))) + + signMode, err := authsigning.APISignModeToInternal(txConfig.SignModeHandler().DefaultMode()) + if err != nil { + return nil, err + } + + emptySignature := sdktxsigning.SignatureV2{ + PubKey: privKey.PubKey(), + Data: &sdktxsigning.SingleSignatureData{ + SignMode: signMode, + Signature: nil, + }, + Sequence: 0, + } + if err := txBuilder.SetSignatures(emptySignature); err != nil { + return nil, err + } + + signerData := authsigning.SignerData{ + ChainID: strconv.Itoa(constants.EighteenDecimalsChainID), + AccountNumber: 0, + Sequence: 0, + Address: sdk.AccAddress(privKey.PubKey().Address().Bytes()).String(), + PubKey: privKey.PubKey(), + } + + signature, err := cosmostx.SignWithPrivKey(context.TODO(), signMode, signerData, txBuilder, privKey, txConfig, 0) + if err != nil { + return nil, err + } + + if err := txBuilder.SetSignatures(signature); err != nil { + return nil, err + } + + return txBuilder.GetTx(), nil +} + +func benchEVMAccountsNeeded(numTxs int) int { + if numTxs == 0 { + return 0 + } + return (numTxs + benchEVMPerAccount - 1) / benchEVMPerAccount +} + +func benchTxsForAccount(totalTxs, numAccounts, accountIndex int) int { + perAccount := totalTxs / numAccounts + remainder := totalTxs % numAccounts + if accountIndex < remainder { + return perAccount + 1 + } + return perAccount +} diff --git a/mempool/iterator_test.go b/mempool/iterator_test.go new file mode 100644 index 00000000..cfa1506f --- /dev/null +++ b/mempool/iterator_test.go @@ -0,0 +1,878 @@ +package mempool + +import ( + "context" + "errors" + "math/big" + "strconv" + "testing" + "time" + + "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/holiman/uint256" + "github.com/stretchr/testify/require" + + "github.com/cosmos/evm/crypto/ethsecp256k1" + "github.com/cosmos/evm/encoding" + "github.com/cosmos/evm/mempool/miner" + "github.com/cosmos/evm/mempool/txpool" + "github.com/cosmos/evm/testutil/constants" + vmtypes "github.com/cosmos/evm/x/vm/types" + + "cosmossdk.io/log/v2" + sdkmath "cosmossdk.io/math" + + "github.com/cosmos/cosmos-sdk/client" + cosmostx "github.com/cosmos/cosmos-sdk/client/tx" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkmempool "github.com/cosmos/cosmos-sdk/types/mempool" + sdktxsigning "github.com/cosmos/cosmos-sdk/types/tx/signing" + authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +const ( + testBondDenom = "aatom" + testGas = uint64(21_000) +) + +func TestNewEVMMempoolIterator_BothEmpty(t *testing.T) { + txConfig, b := setupIteratorTest(t) + iter := NewEVMMempoolIterator(nil, nil, log.NewNopLogger(), txConfig, b) + require.Nil(t, iter) +} + +func TestNewEVMMempoolIterator_EmptyEVMIterator(t *testing.T) { + txConfig, b := setupIteratorTest(t) + evmIter := makeEVMIterator(map[common.Address][]*txpool.LazyTransaction{}, nil) + iter := NewEVMMempoolIterator(evmIter, nil, log.NewNopLogger(), txConfig, b) + require.Nil(t, iter) +} + +func TestNewEVMMempoolIterator_NilCosmosIterator(t *testing.T) { + txConfig, b := setupIteratorTest(t) + addr, key := newAddrKey(t) + + tx := buildEVMTx(t, key, 0, big.NewInt(2_000_000_000), big.NewInt(2_000_000_000), b.Config().ChainID) + + evmIter := makeEVMIterator(map[common.Address][]*txpool.LazyTransaction{addr: {tx}}, nil) + iter := NewEVMMempoolIterator(evmIter, nil, log.NewNopLogger(), txConfig, b) + require.NotNil(t, iter) +} + +func TestNewEVMMempoolIterator_NilEVMWithCosmosOnly(t *testing.T) { + txConfig, b := setupIteratorTest(t) + _, key := newAddrKey(t) + + pool := newCosmosPriorityPool() + cosmosTx := buildCosmosTx(t, txConfig, key, 1_000_000_000, testGas, testBondDenom) + cosmosIter := insertCosmosTxs(t, pool, cosmosTx) + + iter := NewEVMMempoolIterator(nil, cosmosIter, log.NewNopLogger(), txConfig, b) + require.NotNil(t, iter) +} + +func TestIterator_EVMOnly_SingleTx(t *testing.T) { + txConfig, b := setupIteratorTest(t) + addr, key := newAddrKey(t) + + tx := buildEVMTx(t, key, 0, big.NewInt(2_000_000_000), big.NewInt(2_000_000_000), b.Config().ChainID) + + evmIter := makeEVMIterator(map[common.Address][]*txpool.LazyTransaction{addr: {tx}}, nil) + iter := NewEVMMempoolIterator(evmIter, nil, log.NewNopLogger(), txConfig, b) + require.NotNil(t, iter) + + result := collectAll(t, iter) + require.Len(t, result, 1) + require.True(t, isEVMTx(result[0])) +} + +func TestIterator_EVMOnly_MultipleTxsSameAccount(t *testing.T) { + txConfig, b := setupIteratorTest(t) + addr, key := newAddrKey(t) + + var lazyTxs []*txpool.LazyTransaction + for nonce := uint64(0); nonce < 3; nonce++ { + tx := buildEVMTx(t, key, nonce, big.NewInt(2_000_000_000), big.NewInt(2_000_000_000), b.Config().ChainID) + lazyTxs = append(lazyTxs, tx) + } + + evmIter := makeEVMIterator(map[common.Address][]*txpool.LazyTransaction{addr: lazyTxs}, nil) + iter := NewEVMMempoolIterator(evmIter, nil, log.NewNopLogger(), txConfig, b) + require.NotNil(t, iter) + + result := collectAll(t, iter) + require.Len(t, result, 3) + for i, tx := range result { + require.True(t, isEVMTx(tx), "tx %d should be EVM", i) + } +} + +func TestIterator_EVMOnly_MultipleAccounts(t *testing.T) { + txConfig, b := setupIteratorTest(t) + txsByAddr := make(map[common.Address][]*txpool.LazyTransaction) + for i := 0; i < 3; i++ { + addr, key := newAddrKey(t) + tx := buildEVMTx(t, key, 0, big.NewInt(2_000_000_000), big.NewInt(2_000_000_000), b.Config().ChainID) + txsByAddr[addr] = []*txpool.LazyTransaction{tx} + } + + evmIter := makeEVMIterator(txsByAddr, nil) + iter := NewEVMMempoolIterator(evmIter, nil, log.NewNopLogger(), txConfig, b) + require.NotNil(t, iter) + + result := collectAll(t, iter) + require.Len(t, result, 3) +} + +func TestIterator_EVMMultipleAccountsDifferentPrices(t *testing.T) { + txConfig, b := setupIteratorTest(t) + gasPrices := []int64{10_000_000_000, 5_000_000_000, 1_000_000_000} + txsByAddr := make(map[common.Address][]*txpool.LazyTransaction) + for _, gp := range gasPrices { + addr, key := newAddrKey(t) + tx := buildEVMTx(t, key, 0, big.NewInt(gp), big.NewInt(gp), b.Config().ChainID) + txsByAddr[addr] = []*txpool.LazyTransaction{tx} + } + + evmIter := makeEVMIterator(txsByAddr, nil) + iter := NewEVMMempoolIterator(evmIter, nil, log.NewNopLogger(), txConfig, b) + require.NotNil(t, iter) + + result := collectAll(t, iter) + require.Len(t, result, 3) + for i, tx := range result { + require.True(t, isEVMTx(tx), "tx %d should be EVM", i) + require.Equal(t, big.NewInt(gasPrices[i]), txGasPrice(t, tx), "tx %d gas price", i) + } +} + +func TestIterator_CosmosOnly_SingleTx(t *testing.T) { + txConfig, b := setupIteratorTest(t) + _, key := newAddrKey(t) + + pool := newCosmosPriorityPool() + cosmosTx := buildCosmosTx(t, txConfig, key, 1_000_000_000, testGas, testBondDenom) + cosmosIter := insertCosmosTxs(t, pool, cosmosTx) + + iter := NewEVMMempoolIterator(nil, cosmosIter, log.NewNopLogger(), txConfig, b) + require.NotNil(t, iter) + + result := collectAll(t, iter) + require.Len(t, result, 1) + require.True(t, isCosmosTx(result[0])) +} + +func TestIterator_CosmosOnly_MultipleTxs(t *testing.T) { + txConfig, b := setupIteratorTest(t) + pool := newCosmosPriorityPool() + + // different accounts, different gas prices, ordered by priority + gasPrices := []int64{3_000_000_000, 2_000_000_000, 1_000_000_000} + for _, gp := range gasPrices { + _, key := newAddrKey(t) + tx := buildCosmosTx(t, txConfig, key, gp, testGas, testBondDenom) + ctx := sdk.Context{}.WithContext(context.Background()) + require.NoError(t, pool.Insert(ctx, tx)) + } + + ctx := sdk.Context{}.WithContext(context.Background()) + cosmosIter := pool.Select(ctx, nil) + iter := NewEVMMempoolIterator(nil, cosmosIter, log.NewNopLogger(), txConfig, b) + require.NotNil(t, iter) + + result := collectAll(t, iter) + require.Len(t, result, 3) + for i, tx := range result { + require.True(t, isCosmosTx(tx), "tx %d should be cosmos", i) + require.Equal(t, big.NewInt(gasPrices[i]), txGasPrice(t, tx), "tx %d gas price", i) + } +} + +func TestIterator_CosmosOnlyWithBaseFee(t *testing.T) { + txConfig, _ := setupIteratorTest(t) + baseFee := big.NewInt(1_000_000_000) + pool := newCosmosPriorityPool() + + gasPrices := []int64{10_000_000_000, 5_000_000_000, 2_000_000_000} + for _, gp := range gasPrices { + _, key := newAddrKey(t) + tx := buildCosmosTx(t, txConfig, key, gp, testGas, testBondDenom) + ctx := sdk.Context{}.WithContext(context.Background()) + require.NoError(t, pool.Insert(ctx, tx)) + } + + ctx := sdk.Context{}.WithContext(context.Background()) + cosmosIter := pool.Select(ctx, nil) + bc := makeBlockchain(t, baseFee) + iter := NewEVMMempoolIterator(nil, cosmosIter, log.NewNopLogger(), txConfig, bc) + require.NotNil(t, iter) + + result := collectAll(t, iter) + require.Len(t, result, 3) + for i, tx := range result { + require.True(t, isCosmosTx(tx), "tx %d should be cosmos", i) + require.Equal(t, big.NewInt(gasPrices[i]), txGasPrice(t, tx), "tx %d gas price", i) + } +} + +func TestIterator_Mixed_EVMHigherFee(t *testing.T) { + txConfig, b := setupIteratorTest(t) + evmAddr, evmKey := newAddrKey(t) + + tx := buildEVMTx(t, evmKey, 0, big.NewInt(10_000_000_000), big.NewInt(10_000_000_000), b.Config().ChainID) + evmIter := makeEVMIterator(map[common.Address][]*txpool.LazyTransaction{ + evmAddr: {tx}, + }, nil) + + _, cosmosKey := newAddrKey(t) + pool := newCosmosPriorityPool() + cosmosTx := buildCosmosTx(t, txConfig, cosmosKey, 1_000_000_000, testGas, testBondDenom) + cosmosIter := insertCosmosTxs(t, pool, cosmosTx) + + iter := NewEVMMempoolIterator(evmIter, cosmosIter, log.NewNopLogger(), txConfig, b) + require.NotNil(t, iter) + + result := collectAll(t, iter) + require.Len(t, result, 2) + require.True(t, isEVMTx(result[0]), "first tx should be EVM (higher fee)") + require.Equal(t, big.NewInt(10_000_000_000), txGasPrice(t, result[0])) + require.True(t, isCosmosTx(result[1]), "second tx should be cosmos") + require.Equal(t, big.NewInt(1_000_000_000), txGasPrice(t, result[1])) +} + +func TestIterator_Mixed_CosmosHigherFee(t *testing.T) { + txConfig, b := setupIteratorTest(t) + evmAddr, evmKey := newAddrKey(t) + + tx := buildEVMTx(t, evmKey, 0, big.NewInt(1_000_000_000), big.NewInt(1_000_000_000), b.Config().ChainID) + evmIter := makeEVMIterator(map[common.Address][]*txpool.LazyTransaction{ + evmAddr: {tx}, + }, nil) + + _, cosmosKey := newAddrKey(t) + pool := newCosmosPriorityPool() + cosmosTx := buildCosmosTx(t, txConfig, cosmosKey, 10_000_000_000, testGas, testBondDenom) + cosmosIter := insertCosmosTxs(t, pool, cosmosTx) + + iter := NewEVMMempoolIterator(evmIter, cosmosIter, log.NewNopLogger(), txConfig, b) + require.NotNil(t, iter) + + result := collectAll(t, iter) + require.Len(t, result, 2) + require.True(t, isCosmosTx(result[0]), "first tx should be cosmos (higher fee)") + require.Equal(t, big.NewInt(10_000_000_000), txGasPrice(t, result[0])) + require.True(t, isEVMTx(result[1]), "second tx should be EVM") + require.Equal(t, big.NewInt(1_000_000_000), txGasPrice(t, result[1])) +} + +func TestIterator_Mixed_EqualFees_PrefersEVM(t *testing.T) { + txConfig, b := setupIteratorTest(t) + evmAddr, evmKey := newAddrKey(t) + + tx := buildEVMTx(t, evmKey, 0, big.NewInt(5_000_000_000), big.NewInt(5_000_000_000), b.Config().ChainID) + evmIter := makeEVMIterator(map[common.Address][]*txpool.LazyTransaction{ + evmAddr: {tx}, + }, nil) + + _, cosmosKey := newAddrKey(t) + pool := newCosmosPriorityPool() + cosmosTx := buildCosmosTx(t, txConfig, cosmosKey, 5_000_000_000, testGas, testBondDenom) + cosmosIter := insertCosmosTxs(t, pool, cosmosTx) + + iter := NewEVMMempoolIterator(evmIter, cosmosIter, log.NewNopLogger(), txConfig, b) + require.NotNil(t, iter) + + result := collectAll(t, iter) + require.Len(t, result, 2) + require.True(t, isEVMTx(result[0]), "first tx should be EVM when fees are equal") + require.True(t, isCosmosTx(result[1])) +} + +func TestIterator_Mixed_InterleavedByFee(t *testing.T) { + txConfig, b := setupIteratorTest(t) + // EVM fees (tip): 8, 5, 2 gwei (3 accounts) + // Cosmos fees (no base fee, tip = gas price): 9, 6, 1 gwei (3 accounts) + // Expected: C(9), E(8), C(6), E(5), E(2), C(1) + + evmGasPrices := []int64{8_000_000_000, 5_000_000_000, 2_000_000_000} + txsByAddr := make(map[common.Address][]*txpool.LazyTransaction) + for _, gp := range evmGasPrices { + addr, key := newAddrKey(t) + tx := buildEVMTx(t, key, 0, big.NewInt(gp), big.NewInt(gp), b.Config().ChainID) + txsByAddr[addr] = []*txpool.LazyTransaction{tx} + } + evmIter := makeEVMIterator(txsByAddr, nil) + + cosmosGasPrices := []int64{9_000_000_000, 6_000_000_000, 1_000_000_000} + pool := newCosmosPriorityPool() + for _, gp := range cosmosGasPrices { + _, key := newAddrKey(t) + tx := buildCosmosTx(t, txConfig, key, gp, testGas, testBondDenom) + ctx := sdk.Context{}.WithContext(context.Background()) + require.NoError(t, pool.Insert(ctx, tx)) + } + ctx := sdk.Context{}.WithContext(context.Background()) + cosmosIter := pool.Select(ctx, nil) + + iter := NewEVMMempoolIterator(evmIter, cosmosIter, log.NewNopLogger(), txConfig, b) + require.NotNil(t, iter) + + result := collectAll(t, iter) + require.Len(t, result, 6, "should yield all 6 transactions") + + expectedEVM := []bool{false, true, false, true, true, false} // true = EVM + expectedGasPrices := []int64{9_000_000_000, 8_000_000_000, 6_000_000_000, 5_000_000_000, 2_000_000_000, 1_000_000_000} + for i, tx := range result { + if expectedEVM[i] { + require.True(t, isEVMTx(tx), "pos %d: expected EVM", i) + } else { + require.True(t, isCosmosTx(tx), "pos %d: expected cosmos", i) + } + require.Equal(t, big.NewInt(expectedGasPrices[i]), txGasPrice(t, tx), "pos %d gas price", i) + } +} + +func TestIterator_CosmosZeroFee_PrefersEVM(t *testing.T) { + txConfig, b := setupIteratorTest(t) + evmAddr, evmKey := newAddrKey(t) + + tx := buildEVMTx(t, evmKey, 0, big.NewInt(1_000_000_000), big.NewInt(1_000_000_000), b.Config().ChainID) + evmIter := makeEVMIterator(map[common.Address][]*txpool.LazyTransaction{ + evmAddr: {tx}, + }, nil) + + // Cosmos tx with zero gas price + _, cosmosKey := newAddrKey(t) + pool := newCosmosPriorityPool() + cosmosTx := buildCosmosTx(t, txConfig, cosmosKey, 0, testGas, testBondDenom) + cosmosIter := insertCosmosTxs(t, pool, cosmosTx) + + iter := NewEVMMempoolIterator(evmIter, cosmosIter, log.NewNopLogger(), txConfig, b) + require.NotNil(t, iter) + + result := collectAll(t, iter) + require.Len(t, result, 2) + require.True(t, isEVMTx(result[0]), "EVM should come first when cosmos has zero fee") + require.True(t, isCosmosTx(result[1])) +} + +func TestIterator_CosmosWrongDenom_PrefersEVM(t *testing.T) { + txConfig, b := setupIteratorTest(t) + evmAddr, evmKey := newAddrKey(t) + + tx := buildEVMTx(t, evmKey, 0, big.NewInt(1_000_000_000), big.NewInt(1_000_000_000), b.Config().ChainID) + evmIter := makeEVMIterator(map[common.Address][]*txpool.LazyTransaction{ + evmAddr: {tx}, + }, nil) + + // Cosmos tx with fees in "uosmo" instead of testBondDenom + _, cosmosKey := newAddrKey(t) + pool := newCosmosPriorityPool() + cosmosTx := buildCosmosTx(t, txConfig, cosmosKey, 100_000_000_000, testGas, "uosmo") + cosmosIter := insertCosmosTxs(t, pool, cosmosTx) + + iter := NewEVMMempoolIterator(evmIter, cosmosIter, log.NewNopLogger(), txConfig, b) + require.NotNil(t, iter) + + result := collectAll(t, iter) + require.Len(t, result, 2) + require.True(t, isEVMTx(result[0]), "EVM should come first when cosmos fee is in wrong denom") + require.True(t, isCosmosTx(result[1])) +} + +func TestIterator_WithBaseFee_CosmosEffectiveTip(t *testing.T) { + txConfig, _ := setupIteratorTest(t) + // base fee 1 gwei: + // EVM: gasFeeCap=gasTipCap=4 gwei, miner tip = min(4, 4-1) = 3 + // Cosmos: gasPrice=5 gwei, effective tip = 5 - 1 = 4 + // Cosmos tip (4) > EVM tip (3) → cosmos first + baseFee := big.NewInt(1_000_000_000) + bc := makeBlockchain(t, baseFee) + + evmAddr, evmKey := newAddrKey(t) + + tx := buildEVMTx(t, evmKey, 0, big.NewInt(4_000_000_000), big.NewInt(4_000_000_000), bc.Config().ChainID) + evmIter := makeEVMIterator(map[common.Address][]*txpool.LazyTransaction{ + evmAddr: {tx}, + }, baseFee) + + _, cosmosKey := newAddrKey(t) + pool := newCosmosPriorityPool() + cosmosTx := buildCosmosTx(t, txConfig, cosmosKey, 5_000_000_000, testGas, testBondDenom) + cosmosIter := insertCosmosTxs(t, pool, cosmosTx) + + iter := NewEVMMempoolIterator(evmIter, cosmosIter, log.NewNopLogger(), txConfig, bc) + require.NotNil(t, iter) + + result := collectAll(t, iter) + require.Len(t, result, 2) + require.True(t, isCosmosTx(result[0]), "cosmos should come first (effective tip 4 > 3)") + require.True(t, isEVMTx(result[1])) +} + +func TestIterator_WithBaseFee_CosmosBelowBaseFee(t *testing.T) { + txConfig, _ := setupIteratorTest(t) + // cosmos gas price 2 gwei < base fee 3 gwei → effective tip = 0 → EVM preferred + baseFee := big.NewInt(3_000_000_000) + bc := makeBlockchain(t, baseFee) + + evmAddr, evmKey := newAddrKey(t) + + tx := buildEVMTx(t, evmKey, 0, big.NewInt(5_000_000_000), big.NewInt(5_000_000_000), bc.Config().ChainID) + evmIter := makeEVMIterator(map[common.Address][]*txpool.LazyTransaction{ + evmAddr: {tx}, + }, baseFee) + + _, cosmosKey := newAddrKey(t) + pool := newCosmosPriorityPool() + cosmosTx := buildCosmosTx(t, txConfig, cosmosKey, 2_000_000_000, testGas, testBondDenom) + cosmosIter := insertCosmosTxs(t, pool, cosmosTx) + + iter := NewEVMMempoolIterator(evmIter, cosmosIter, log.NewNopLogger(), txConfig, bc) + require.NotNil(t, iter) + + result := collectAll(t, iter) + require.Len(t, result, 2) + require.True(t, isEVMTx(result[0]), "EVM should come first when cosmos gas price < base fee") + require.True(t, isCosmosTx(result[1])) +} + +func TestIterator_WithBaseFee_CosmosEqualToBaseFee(t *testing.T) { + txConfig, _ := setupIteratorTest(t) + // cosmos gas price == base fee → effective tip = 0 → EVM preferred + baseFee := big.NewInt(5_000_000_000) + bc := makeBlockchain(t, baseFee) + + evmAddr, evmKey := newAddrKey(t) + + tx := buildEVMTx(t, evmKey, 0, big.NewInt(6_000_000_000), big.NewInt(6_000_000_000), bc.Config().ChainID) + evmIter := makeEVMIterator(map[common.Address][]*txpool.LazyTransaction{ + evmAddr: {tx}, + }, baseFee) + + _, cosmosKey := newAddrKey(t) + pool := newCosmosPriorityPool() + cosmosTx := buildCosmosTx(t, txConfig, cosmosKey, 5_000_000_000, testGas, testBondDenom) + cosmosIter := insertCosmosTxs(t, pool, cosmosTx) + + iter := NewEVMMempoolIterator(evmIter, cosmosIter, log.NewNopLogger(), txConfig, bc) + require.NotNil(t, iter) + + result := collectAll(t, iter) + require.Len(t, result, 2) + require.True(t, isEVMTx(result[0]), "EVM should come first when cosmos effective tip is 0") + require.True(t, isCosmosTx(result[1])) +} + +func TestIterator_NoBaseFee_CosmosGasPriceUsedDirectly(t *testing.T) { + txConfig, b := setupIteratorTest(t) + // nil blockchain → no base fee → cosmos gas price used as effective tip + // Cosmos 10 gwei vs EVM 5 gwei → cosmos first + evmAddr, evmKey := newAddrKey(t) + + tx := buildEVMTx(t, evmKey, 0, big.NewInt(5_000_000_000), big.NewInt(5_000_000_000), b.Config().ChainID) + evmIter := makeEVMIterator(map[common.Address][]*txpool.LazyTransaction{ + evmAddr: {tx}, + }, nil) + + _, cosmosKey := newAddrKey(t) + pool := newCosmosPriorityPool() + cosmosTx := buildCosmosTx(t, txConfig, cosmosKey, 10_000_000_000, testGas, testBondDenom) + cosmosIter := insertCosmosTxs(t, pool, cosmosTx) + + iter := NewEVMMempoolIterator(evmIter, cosmosIter, log.NewNopLogger(), txConfig, b) + require.NotNil(t, iter) + + result := collectAll(t, iter) + require.Len(t, result, 2) + require.True(t, isCosmosTx(result[0]), "cosmos should come first (10 > 5, no base fee)") + require.True(t, isEVMTx(result[1])) +} + +func TestIterator_NilBaseFeeInHeader(t *testing.T) { + txConfig, _ := setupIteratorTest(t) + // blockchain exists but header has nil BaseFee → same as no base fee + bc := makeBlockchain(t, nil) + evmAddr, evmKey := newAddrKey(t) + + tx := buildEVMTx(t, evmKey, 0, big.NewInt(5_000_000_000), big.NewInt(5_000_000_000), bc.Config().ChainID) + evmIter := makeEVMIterator(map[common.Address][]*txpool.LazyTransaction{ + evmAddr: {tx}, + }, nil) + + _, cosmosKey := newAddrKey(t) + pool := newCosmosPriorityPool() + cosmosTx := buildCosmosTx(t, txConfig, cosmosKey, 10_000_000_000, testGas, testBondDenom) + cosmosIter := insertCosmosTxs(t, pool, cosmosTx) + + iter := NewEVMMempoolIterator(evmIter, cosmosIter, log.NewNopLogger(), txConfig, bc) + require.NotNil(t, iter) + + result := collectAll(t, iter) + require.Len(t, result, 2) + require.True(t, isCosmosTx(result[0]), "cosmos should win when base fee is nil in header") +} + +func TestIterator_MixedWithBaseFee_OrderingCorrect(t *testing.T) { + txConfig, _ := setupIteratorTest(t) + // EVM: gasFeeCap=10, gasTipCap=10, baseFee=2 → miner tip = min(10, 10-2) = 8 + // Cosmos: gasPrice=7, baseFee=2 → effective tip = 7 - 2 = 5 + // EVM tip (8) > Cosmos tip (5) → EVM first + baseFee := big.NewInt(2_000_000_000) + bc := makeBlockchain(t, baseFee) + + evmAddr, evmKey := newAddrKey(t) + + tx := buildEVMTx(t, evmKey, 0, big.NewInt(10_000_000_000), big.NewInt(10_000_000_000), bc.Config().ChainID) + evmIter := makeEVMIterator(map[common.Address][]*txpool.LazyTransaction{ + evmAddr: {tx}, + }, baseFee) + + _, cosmosKey := newAddrKey(t) + pool := newCosmosPriorityPool() + cosmosTx := buildCosmosTx(t, txConfig, cosmosKey, 7_000_000_000, testGas, testBondDenom) + cosmosIter := insertCosmosTxs(t, pool, cosmosTx) + + iter := NewEVMMempoolIterator(evmIter, cosmosIter, log.NewNopLogger(), txConfig, bc) + require.NotNil(t, iter) + + result := collectAll(t, iter) + require.Len(t, result, 2) + require.True(t, isEVMTx(result[0]), "EVM should come first (tip 8 > 5)") + require.True(t, isCosmosTx(result[1])) +} + +func TestIterator_CosmosExhaustedFirstThenEVM(t *testing.T) { + txConfig, b := setupIteratorTest(t) + // 1 cosmos tx with high fee, 2 EVM txs with lower fee + evmAddr, evmKey := newAddrKey(t) + + var lazyTxs []*txpool.LazyTransaction + for nonce := uint64(0); nonce < 2; nonce++ { + tx := buildEVMTx(t, evmKey, nonce, big.NewInt(1_000_000_000), big.NewInt(1_000_000_000), b.Config().ChainID) + lazyTxs = append(lazyTxs, tx) + } + evmIter := makeEVMIterator(map[common.Address][]*txpool.LazyTransaction{evmAddr: lazyTxs}, nil) + + _, cosmosKey := newAddrKey(t) + pool := newCosmosPriorityPool() + cosmosTx := buildCosmosTx(t, txConfig, cosmosKey, 50_000_000_000, testGas, testBondDenom) + cosmosIter := insertCosmosTxs(t, pool, cosmosTx) + + iter := NewEVMMempoolIterator(evmIter, cosmosIter, log.NewNopLogger(), txConfig, b) + require.NotNil(t, iter) + + result := collectAll(t, iter) + require.Len(t, result, 3) + require.True(t, isCosmosTx(result[0])) + require.Equal(t, big.NewInt(50_000_000_000), txGasPrice(t, result[0])) + require.True(t, isEVMTx(result[1])) + require.Equal(t, big.NewInt(1_000_000_000), txGasPrice(t, result[1])) + require.True(t, isEVMTx(result[2])) + require.Equal(t, big.NewInt(1_000_000_000), txGasPrice(t, result[2])) +} + +func TestIterator_EVMExhaustedFirstThenCosmos(t *testing.T) { + txConfig, b := setupIteratorTest(t) + // 1 EVM tx with high fee, 2 cosmos txs with lower fee + evmAddr, evmKey := newAddrKey(t) + + tx := buildEVMTx(t, evmKey, 0, big.NewInt(50_000_000_000), big.NewInt(50_000_000_000), b.Config().ChainID) + evmIter := makeEVMIterator(map[common.Address][]*txpool.LazyTransaction{ + evmAddr: {tx}, + }, nil) + + pool := newCosmosPriorityPool() + gasPrices := []int64{2_000_000_000, 1_000_000_000} + for _, gp := range gasPrices { + _, key := newAddrKey(t) + cosmosTx := buildCosmosTx(t, txConfig, key, gp, testGas, testBondDenom) + ctx := sdk.Context{}.WithContext(context.Background()) + require.NoError(t, pool.Insert(ctx, cosmosTx)) + } + ctx := sdk.Context{}.WithContext(context.Background()) + cosmosIter := pool.Select(ctx, nil) + + iter := NewEVMMempoolIterator(evmIter, cosmosIter, log.NewNopLogger(), txConfig, b) + require.NotNil(t, iter) + + result := collectAll(t, iter) + require.Len(t, result, 3) + require.True(t, isEVMTx(result[0])) + require.Equal(t, big.NewInt(50_000_000_000), txGasPrice(t, result[0])) + require.True(t, isCosmosTx(result[1])) + require.Equal(t, big.NewInt(2_000_000_000), txGasPrice(t, result[1])) + require.True(t, isCosmosTx(result[2])) + require.Equal(t, big.NewInt(1_000_000_000), txGasPrice(t, result[2])) +} + +func TestIterator_Tx_CalledMultipleTimesReturnsSameType(t *testing.T) { + txConfig, b := setupIteratorTest(t) + evmAddr, evmKey := newAddrKey(t) + + tx := buildEVMTx(t, evmKey, 0, big.NewInt(2_000_000_000), big.NewInt(2_000_000_000), b.Config().ChainID) + evmIter := makeEVMIterator(map[common.Address][]*txpool.LazyTransaction{ + evmAddr: {tx}, + }, nil) + + _, cosmosKey := newAddrKey(t) + pool := newCosmosPriorityPool() + cosmosTx := buildCosmosTx(t, txConfig, cosmosKey, 1_000_000_000, testGas, testBondDenom) + cosmosIter := insertCosmosTxs(t, pool, cosmosTx) + + iter := NewEVMMempoolIterator(evmIter, cosmosIter, log.NewNopLogger(), txConfig, b) + require.NotNil(t, iter) + + // Tx() should be idempotent + tx1 := iter.Tx() + tx2 := iter.Tx() + tx3 := iter.Tx() + require.True(t, isEVMTx(tx1)) + require.True(t, isEVMTx(tx2)) + require.True(t, isEVMTx(tx3)) +} + +func TestIterator_NextReturnsNilWhenExhausted(t *testing.T) { + txConfig, b := setupIteratorTest(t) + addr, key := newAddrKey(t) + + tx := buildEVMTx(t, key, 0, big.NewInt(2_000_000_000), big.NewInt(2_000_000_000), b.Config().ChainID) + evmIter := makeEVMIterator(map[common.Address][]*txpool.LazyTransaction{ + addr: {tx}, + }, nil) + + iter := NewEVMMempoolIterator(evmIter, nil, log.NewNopLogger(), txConfig, b) + require.NotNil(t, iter) + require.NotNil(t, iter.Tx()) + + next := iter.Next() + require.Nil(t, next) +} + +func setupIteratorTest(t *testing.T) (client.TxConfig, *Blockchain) { + t.Helper() + + chainID := uint64(constants.EighteenDecimalsChainID) + + configurator := vmtypes.NewEVMConfigurator() + configurator.ResetTestConfig() + + err := vmtypes.SetChainConfig(vmtypes.DefaultChainConfig(chainID)) + require.NoError(t, err) + + coinInfo := constants.ChainsCoinInfo[chainID] + coinInfo.Denom = testBondDenom + + err = configurator.WithEVMCoinInfo(coinInfo).Configure() + require.NoError(t, err) + + enc := encoding.MakeConfig(chainID) + vmtypes.RegisterInterfaces(enc.InterfaceRegistry) + + return enc.TxConfig, makeBlockchain(t, big.NewInt(20000)) +} + +// newAddrKey generates an Ethereum address and its corresponding private key. +func newAddrKey(t *testing.T) (common.Address, *ethsecp256k1.PrivKey) { + t.Helper() + privkey, err := ethsecp256k1.GenerateKey() + require.NoError(t, err) + ecdsaKey, err := privkey.ToECDSA() + require.NoError(t, err) + return crypto.PubkeyToAddress(ecdsaKey.PublicKey), privkey +} + +// makeEVMIterator builds a TransactionsByPriceAndNonce from txs grouped by address. +func makeEVMIterator(txsByAddr map[common.Address][]*txpool.LazyTransaction, baseFee *big.Int) *miner.TransactionsByPriceAndNonce { + return miner.NewTransactionsByPriceAndNonce(nil, txsByAddr, baseFee) +} + +// buildEVMTx creates a signed EVM send transaction. +func buildEVMTx( + t *testing.T, + key *ethsecp256k1.PrivKey, + nonce uint64, + gasFeeCap, + gasTipCap *big.Int, + chainID *big.Int, +) *txpool.LazyTransaction { + t.Helper() + ecdsaKey, err := key.ToECDSA() + require.NoError(t, err) + to := common.HexToAddress("0x0000000000000000000000000000000000000001") + tx := ethtypes.NewTx(ðtypes.DynamicFeeTx{ + ChainID: chainID, + Nonce: nonce, + To: &to, + Value: big.NewInt(1000), + Gas: testGas, + GasFeeCap: gasFeeCap, + GasTipCap: gasTipCap, + }) + signer := ethtypes.LatestSignerForChainID(chainID) + signed, err := ethtypes.SignTx(tx, signer, ecdsaKey) + require.NoError(t, err) + return &txpool.LazyTransaction{ + Hash: signed.Hash(), + Tx: signed, + Time: time.Now(), + GasFeeCap: uint256.MustFromBig(signed.GasFeeCap()), + GasTipCap: uint256.MustFromBig(signed.GasTipCap()), + Gas: signed.Gas(), + } +} + +// buildCosmosTx creates a signed Cosmos SDK bank send transaction. +func buildCosmosTx( + t *testing.T, + txConfig client.TxConfig, + privKey cryptotypes.PrivKey, + gasPriceWei int64, + gas uint64, + denom string, +) authsigning.Tx { + t.Helper() + fromAddr := sdk.AccAddress(privKey.PubKey().Address().Bytes()) + toAddr := sdk.AccAddress(common.HexToAddress("0x0000000000000000000000000000000000000002").Bytes()) + msg := banktypes.NewMsgSend(fromAddr, toAddr, sdk.NewCoins(sdk.NewInt64Coin(denom, 1000))) + + txBuilder := txConfig.NewTxBuilder() + require.NoError(t, txBuilder.SetMsgs(msg)) + + txBuilder.SetGasLimit(gas) + feeAmount := new(big.Int).Mul(big.NewInt(gasPriceWei), big.NewInt(int64(gas))) //nolint:gosec + txBuilder.SetFeeAmount(sdk.NewCoins(sdk.NewCoin(denom, sdkmath.NewIntFromBigInt(feeAmount)))) + + signMode, err := authsigning.APISignModeToInternal(txConfig.SignModeHandler().DefaultMode()) + require.NoError(t, err) + + require.NoError(t, txBuilder.SetSignatures(sdktxsigning.SignatureV2{ + PubKey: privKey.PubKey(), + Data: &sdktxsigning.SingleSignatureData{SignMode: signMode}, + })) + + // setting sequence doesnt actually matter for these tests + signerData := authsigning.SignerData{ + ChainID: strconv.Itoa(constants.EighteenDecimalsChainID), + Address: fromAddr.String(), + PubKey: privKey.PubKey(), + } + sig, err := cosmostx.SignWithPrivKey(context.TODO(), signMode, signerData, txBuilder, privKey, txConfig, 0) + require.NoError(t, err) + require.NoError(t, txBuilder.SetSignatures(sig)) + + return txBuilder.GetTx() +} + +// insertCosmosTxs inserts transactions into the pool and returns the Select +// iterator. +func insertCosmosTxs(t *testing.T, pool sdkmempool.ExtMempool, txs ...authsigning.Tx) sdkmempool.Iterator { + t.Helper() + ctx := sdk.Context{}.WithContext(context.Background()) + for _, tx := range txs { + require.NoError(t, pool.Insert(ctx, tx)) + } + return pool.Select(ctx, nil) +} + +// newCosmosPriorityPool creates a priority nonce mempool so that txs can be +// inserted into it, and iterated over using the priority nonce iterator in the +// tests +func newCosmosPriorityPool() sdkmempool.ExtMempool { + cfg := sdkmempool.PriorityNonceMempoolConfig[sdkmath.Int]{ + TxPriority: sdkmempool.TxPriority[sdkmath.Int]{ + GetTxPriority: func(_ context.Context, tx sdk.Tx) sdkmath.Int { + feeTx, ok := tx.(sdk.FeeTx) + if !ok { + return sdkmath.ZeroInt() + } + found, coin := feeTx.GetFee().Find(testBondDenom) + if !found { + return sdkmath.ZeroInt() + } + return coin.Amount.Quo(sdkmath.NewIntFromUint64(feeTx.GetGas())) + }, + Compare: func(a, b sdkmath.Int) int { + return a.BigInt().Cmp(b.BigInt()) + }, + MinValue: sdkmath.ZeroInt(), + }, + } + return sdkmempool.NewPriorityMempool(cfg) +} + +// makeBlockchain creates a minimal Blockchain whose CurrentBlock returns +// the given baseFee. If baseFee is nil, the header will have nil BaseFee. +func makeBlockchain(t *testing.T, baseFee *big.Int) *Blockchain { + t.Helper() + + coinInfo := constants.ChainsCoinInfo[constants.EighteenDecimalsChainID] + coinInfo.Denom = testBondDenom + + blockchain := &Blockchain{ + logger: log.NewNopLogger(), + blockGasLimit: 30_000_000, + getCtxCallback: func(_ int64, _ bool) (sdk.Context, error) { + return sdk.Context{}, errors.New("stub") + }, + zeroHeader: ðtypes.Header{ + Difficulty: big.NewInt(0), + Number: big.NewInt(0), + BaseFee: baseFee, + }, + } + + blockchain.coinInfo.Store(&coinInfo) + + return blockchain +} + +// collectAll drains an iterator, returning all transactions. +func collectAll(t *testing.T, iter sdkmempool.Iterator) []sdk.Tx { + t.Helper() + var result []sdk.Tx + for iter != nil { + tx := iter.Tx() + if tx == nil { + break + } + result = append(result, tx) + iter = iter.Next() + } + return result +} + +// txGasPrice extracts the gas price from either an EVM or Cosmos transaction. +func txGasPrice(t *testing.T, tx sdk.Tx) *big.Int { + t.Helper() + if isEVMTx(tx) { + return tx.GetMsgs()[0].(*vmtypes.MsgEthereumTx).Raw.GasPrice() + } + feeTx, ok := tx.(sdk.FeeTx) + require.True(t, ok, "expected FeeTx") + return feeTx.GetFee().AmountOf(testBondDenom).Quo(sdkmath.NewIntFromUint64(feeTx.GetGas())).BigInt() +} + +// isEVMTx returns true if the tx contains a MsgEthereumTx (converted from EVM). +func isEVMTx(tx sdk.Tx) bool { + msgs := tx.GetMsgs() + if len(msgs) != 1 { + return false + } + _, ok := msgs[0].(*vmtypes.MsgEthereumTx) + return ok +} + +// isCosmosTx returns true if the tx contains a MsgSend (standard Cosmos bank tx). +func isCosmosTx(tx sdk.Tx) bool { + msgs := tx.GetMsgs() + if len(msgs) != 1 { + return false + } + _, ok := msgs[0].(*banktypes.MsgSend) + return ok +} diff --git a/mempool/mempool.go b/mempool/mempool.go index 532631ed..74c2f896 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -4,20 +4,30 @@ import ( "context" "errors" "fmt" + "math/big" "sync" + "time" + "github.com/ethereum/go-ethereum/common" ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/holiman/uint256" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/metric" cmttypes "github.com/cometbft/cometbft/types" + "github.com/cosmos/evm/mempool/internal/heightsync" + "github.com/cosmos/evm/mempool/internal/queue" + "github.com/cosmos/evm/mempool/internal/reaplist" + "github.com/cosmos/evm/mempool/internal/txtracker" "github.com/cosmos/evm/mempool/miner" + "github.com/cosmos/evm/mempool/reserver" "github.com/cosmos/evm/mempool/txpool" "github.com/cosmos/evm/mempool/txpool/legacypool" "github.com/cosmos/evm/rpc/stream" evmtypes "github.com/cosmos/evm/x/vm/types" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" "cosmossdk.io/math" "github.com/cosmos/cosmos-sdk/client" @@ -26,81 +36,126 @@ import ( sdkmempool "github.com/cosmos/cosmos-sdk/types/mempool" ) -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 - // maintaining separate pools for EVM and Cosmos transactions. The mempool handles - // fee-based transaction prioritization and manages nonce sequencing for EVM transactions. - ExperimentalEVMMempool struct { - /** Keepers **/ - vmKeeper VMKeeperI + // cosmosReserverHandlerID is the id of the reserver handler for the cosmos pool + // 0+ are reserved for evm sub-pools + cosmosReserverHandlerID = -1 +) - /** Mempools **/ - txPool *txpool.TxPool - legacyTxPool *legacypool.LegacyPool - cosmosPool sdkmempool.ExtMempool +// AllowUnsafeSyncInsert indicates whether to perform synchronous inserts into the mempool +// for testing purposes. When true, Insert will block until the transaction is fully processed. +// This should be used only in tests to ensure deterministic behavior +var AllowUnsafeSyncInsert = false - /** Utils **/ - logger log.Logger - txConfig client.TxConfig - blockchain *Blockchain - blockGasLimit uint64 // Block gas limit from consensus parameters - minTip *uint256.Int +var meter = otel.Meter("github.com/cosmos/evm/mempool") - /** Verification **/ - anteHandler sdk.AnteHandler +var ( + selectByDuration metric.Float64Histogram + buildIteratorDuration metric.Float64Histogram +) - /** Concurrency **/ - mtx sync.Mutex +func init() { + var err error + selectByDuration, err = meter.Float64Histogram( + "mempool.selectby_duration", + metric.WithDescription("Time spent in SelectBy iterating over txs"), + metric.WithUnit("ms"), + ) + if err != nil { + panic(err) + } - eventBus *cmttypes.EventBus + buildIteratorDuration, err = meter.Float64Histogram( + "mempool.builditerator_duration", + metric.WithDescription("Time spent building the unified mempool iterator"), + metric.WithUnit("ms"), + ) + if err != nil { + panic(err) } -) +} -// EVMMempoolConfig contains configuration options for creating an EVMsdkmempool. -// It allows customization of the underlying mempools, verification functions, -// and broadcasting functions used by the sdkmempool. -type EVMMempoolConfig struct { +var _ sdkmempool.ExtMempool = (*Mempool)(nil) + +// Config defines the configuration for the EVM mempool. +type Config struct { 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 + + // Block gas limit from consensus parameters + BlockGasLimit uint64 + MinTip *uint256.Int + + // PendingTxProposalTimeout is the max amount of time to allocate to + // fetching (or waiting to fetch) pending txs from the evm mempool. + PendingTxProposalTimeout time.Duration + // InsertQueueSize is how many txs can be stored in the insert queue + // pending insertion into the mempool. Note the insert queue is only used + // for EVM txs. + InsertQueueSize int + // EnableTxTracker controls whether the mempool records per-tx lifecycle + // telemetry (queued/pending/included latencies). Defaults to false. + EnableTxTracker bool } -// NewExperimentalEVMMempool creates a new unified mempool for EVM and Cosmos transactions. -// It initializes both EVM and Cosmos transaction pools, sets up blockchain interfaces, -// and configures fee-based prioritization. The config parameter allows customization -// of pools and verification functions, with sensible defaults created if not provided. -func NewExperimentalEVMMempool( +// Mempool is an application side mempool implementation that operates +// in conjunction with the CometBFT 'app' configuration. The Mempool +// handles application side rechecking of txs and supports ABCI methods +// InesrtTx and ReapTxs. +type Mempool struct { + /** Keepers **/ + vmKeeper VMKeeperI + + /** Mempools **/ + txPool *txpool.TxPool + legacyTxPool *legacypool.LegacyPool + recheckCosmosPool *RecheckMempool + pendingTxProposalTimeout time.Duration + + /** Utils **/ + logger log.Logger + txConfig client.TxConfig + clientCtx client.Context + blockchain *Blockchain + blockGasLimit uint64 // Block gas limit from consensus parameters + minTip *uint256.Int + + eventBus *cmttypes.EventBus + + /** Transaction Reaping **/ + reapList *reaplist.ReapList + + /** Transaction Tracking **/ + txTracker txtracker.Tracker + + /** Transaction Inserting **/ + cosmosInsertQueue *queue.Queue[sdk.Tx] + evmInsertQueue *queue.Queue[ethtypes.Transaction] + + /** Signer extraction **/ + signerExtractor sdkmempool.SignerExtractionAdapter +} + +func NewMempool( getCtxCallback func(height int64, prove bool) (sdk.Context, error), logger log.Logger, vmKeeper VMKeeperI, feeMarketKeeper FeeMarketKeeperI, txConfig client.TxConfig, - clientCtx client.Context, - config *EVMMempoolConfig, + evmRechecker legacypool.Rechecker, + cosmosRechecker Rechecker, + config *Config, cosmosPoolMaxTx int, -) *ExperimentalEVMMempool { - var ( - cosmosPool sdkmempool.ExtMempool - blockchain *Blockchain - ) - - // add the mempool name to the logger - logger = logger.With(log.ModuleKey, "ExperimentalEVMMempool") - - logger.Debug("creating new EVM mempool") +) *Mempool { + logger = logger.With(log.ModuleKey, "Mempool") + logger.Debug("creating new mempool") if config == nil { panic("config must not be nil") @@ -111,34 +166,32 @@ func NewExperimentalEVMMempool( config.BlockGasLimit = fallbackBlockGasLimit } - blockchain = NewBlockchain(getCtxCallback, logger, vmKeeper, feeMarketKeeper, config.BlockGasLimit) + blockchain := NewBlockchain(getCtxCallback, logger, vmKeeper, feeMarketKeeper, config.BlockGasLimit) - // Create txPool from configuration legacyConfig := legacypool.DefaultConfig if config.LegacyPoolConfig != nil { legacyConfig = *config.LegacyPoolConfig } - 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) - } + reapList := reaplist.New(NewTxEncoder(txConfig)) + txTracker := txtracker.NewNoop() + if config.EnableTxTracker { + txTracker = txtracker.New() } + legacyPool := legacypool.New( + legacyConfig, + logger, + blockchain, + reapList, + txTracker, + legacypool.WithRecheck(evmRechecker), + ) - txPool, err := txpool.New(uint64(0), blockchain, []txpool.SubPool{legacyPool}) + reservationTracker := reserver.NewReservationTracker() + txPool, err := txpool.New(uint64(0), blockchain, reservationTracker, []txpool.SubPool{legacyPool}) if err != nil { panic(err) } - if len(txPool.Subpools) != 1 { panic("tx pool should contain one subpool") } @@ -146,256 +199,329 @@ func NewExperimentalEVMMempool( panic("tx pool should contain only legacypool") } - // TODO: move this logic to evmd.createMempoolConfig and set the max tx there - // 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 { - ctx := sdk.UnwrapSDKContext(goCtx) - cosmosTxFee, ok := tx.(sdk.FeeTx) - if !ok { - return math.ZeroInt() - } - found, coin := cosmosTxFee.GetFee().Find(vmKeeper.GetEvmCoinInfo(ctx).Denom) - if !found { - return math.ZeroInt() - } - - gasPrice := coin.Amount.Quo(math.NewIntFromUint64(cosmosTxFee.GetGas())) + heightSync := heightsync.New( + blockchain.CurrentBlock().Number, + NewCosmosTxStore, + logger.With("pool", "cosmos_recheck_mempool"), + ) - return gasPrice - }, - Compare: func(a, b math.Int) int { - return a.BigInt().Cmp(b.BigInt()) - }, - MinValue: math.ZeroInt(), - } - cosmosPoolConfig = &defaultConfig - } + reservationHandle := reservationTracker.NewHandle(cosmosReserverHandlerID, reserver.WithRefCounter()) + + recheckPool := NewRecheckMempool( + config.CosmosPoolConfig, + cosmosPoolMaxTx, + reservationHandle, + cosmosRechecker, + heightSync, + reapList, + blockchain, + logger, + ) - cosmosPoolConfig.MaxTx = cosmosPoolMaxTx - cosmosPool = sdkmempool.NewPriorityMempool(*cosmosPoolConfig) + mempool := &Mempool{ + vmKeeper: vmKeeper, + txPool: txPool, + legacyTxPool: txPool.Subpools[0].(*legacypool.LegacyPool), + recheckCosmosPool: recheckPool, + logger: logger, + txConfig: txConfig, + blockchain: blockchain, + blockGasLimit: config.BlockGasLimit, + minTip: config.MinTip, + pendingTxProposalTimeout: config.PendingTxProposalTimeout, + reapList: reapList, + txTracker: txTracker, + signerExtractor: NewEthSignerExtractionAdapter(sdkmempool.NewDefaultSignerExtractionAdapter()), + } + + // Setup queues + mempool.evmInsertQueue = queue.New( + "evm", + func(txs []*ethtypes.Transaction) []error { + return txPool.Add(txs, AllowUnsafeSyncInsert) + }, + config.InsertQueueSize, + ) - evmMempool := &ExperimentalEVMMempool{ - vmKeeper: vmKeeper, - txPool: txPool, - legacyTxPool: txPool.Subpools[0].(*legacypool.LegacyPool), - cosmosPool: cosmosPool, - logger: logger, - txConfig: txConfig, - blockchain: blockchain, - blockGasLimit: config.BlockGasLimit, - minTip: config.MinTip, - anteHandler: config.AnteHandler, - } + mempool.cosmosInsertQueue = queue.New( + "cosmos", + func(txs []*sdk.Tx) []error { + errs := make([]error, len(txs)) + for i, tx := range txs { + if tx == nil { + continue + } + errs[i] = recheckPool.Insert(context.Background(), *tx) + } + return errs + }, + config.InsertQueueSize, + ) - vmKeeper.SetEvmMempool(evmMempool) + // Start the cosmos pool recheck loop + mempool.recheckCosmosPool.Start(blockchain.CurrentBlock()) - return evmMempool + return mempool } // GetBlockchain returns the blockchain interface used for chain head event notifications. // This is primarily used to notify the mempool when new blocks are finalized. -func (m *ExperimentalEVMMempool) GetBlockchain() *Blockchain { +func (m *Mempool) GetBlockchain() *Blockchain { return m.blockchain } // GetTxPool returns the underlying EVM txpool. // This provides direct access to the EVM-specific transaction management functionality. -func (m *ExperimentalEVMMempool) GetTxPool() *txpool.TxPool { +func (m *Mempool) GetTxPool() *txpool.TxPool { return m.txPool } +// SetClientCtx sets the client context provider for broadcasting transactions +func (m *Mempool) SetClientCtx(clientCtx client.Context) { + m.clientCtx = clientCtx +} + // Insert adds a transaction to the appropriate mempool (EVM or Cosmos). // EVM transactions are routed to the EVM transaction pool, while all other -// transactions are inserted into the Cosmos sdkmempool. The method assumes -// transactions have already passed CheckTx validation. -func (m *ExperimentalEVMMempool) Insert(goCtx context.Context, tx sdk.Tx) error { - m.mtx.Lock() - defer m.mtx.Unlock() - - ctx := sdk.UnwrapSDKContext(goCtx) - blockHeight := ctx.BlockHeight() - - m.logger.Debug("inserting transaction into mempool", "block_height", blockHeight) - ethMsg, err := m.getEVMMessage(tx) - if err == nil { - // Insert into EVM pool - 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", hash) - return errs[0] - } - m.logger.Debug("EVM transaction inserted successfully", "tx_hash", hash) - return nil +// transactions are inserted into the Cosmos sdkmempool. +func (m *Mempool) Insert(ctx context.Context, tx sdk.Tx) error { + errC, err := m.insert(tx) + if err != nil { + return fmt.Errorf("inserting tx: %w", err) } - // Insert into cosmos pool for non-EVM transactions - m.logger.Debug("inserting Cosmos transaction", "error", err) - err = m.cosmosPool.Insert(goCtx, tx) - if err != nil { - m.logger.Error("failed to insert Cosmos transaction", "error", err) - } else { - m.logger.Debug("Cosmos transaction inserted successfully") + if errC != nil { + // if we got back a non nil async error channel, wait for that to + // resolve + select { + case err := <-errC: + return err + case <-ctx.Done(): + return ctx.Err() + } } - return err + return nil } -// InsertInvalidNonce handles transactions that failed with nonce gap errors. -// It attempts to insert EVM transactions into the pool as non-local transactions, -// allowing them to be queued for future execution when the nonce gap is filled. -// Non-EVM transactions are discarded as regular Cosmos flows do not support nonce gaps. -func (m *ExperimentalEVMMempool) InsertInvalidNonce(txBytes []byte) error { - tx, err := m.txConfig.TxDecoder()(txBytes) +// InsertAsync adds a transaction to the appropriate mempool (EVM or Cosmos). EVM +// transactions are routed to the EVM transaction pool, while all other +// transactions are inserted into the Cosmos sdkmempool. EVM transactions are +// inserted async, i.e. they are scheduled for promotion only, we do not wait +// for it to complete. +func (m *Mempool) InsertAsync(tx sdk.Tx) error { + errChan, err := m.insert(tx) if err != nil { - return err + return fmt.Errorf("inserting tx: %w", err) } - var ethTxs []*ethtypes.Transaction - msgs := tx.GetMsgs() - if len(msgs) != 1 { - return fmt.Errorf("%w, got %d", ErrExpectedOneMessage, len(msgs)) - } - for _, msg := range tx.GetMsgs() { - ethMsg, ok := msg.(*evmtypes.MsgEthereumTx) - if ok { - ethTxs = append(ethTxs, ethMsg.AsTransaction()) - continue - } + select { + case err := <-errChan: + // if we have a result immediately, ready on the channel returned from insert, + // return that (cosmos tx or unable to try and insert the tx due to parsing error). + return err + default: + // result was not ready immediately, return nil while async things happen + return nil } - errs := m.txPool.Add(ethTxs, false) - if errs != nil { - if len(errs) != 1 { - return fmt.Errorf("%w, got %d", ErrExpectedOneError, len(errs)) +} + +// insert inserts a tx into its respective mempool, returning a channel for any +// async errors that may happen later upon actual mempool insertion, and an +// error for any errors that occurred synchronously. +func (m *Mempool) insert(tx sdk.Tx) (<-chan error, error) { + ethMsg, err := evmTxFromCosmosTx(tx) + switch { + case err == nil: + ethTx := ethMsg.AsTransaction() + + // Reject txs below base fee up-front, which can never be included. + if baseFee := m.blockchain.CurrentBlock().BaseFee; baseFee != nil && ethTx.GasFeeCapIntCmp(baseFee) < 0 { + return nil, sdkerrors.ErrInsufficientFee.Wrapf( + "max fee per gas (%s) is lower than the base fee (%s)", + ethTx.GasFeeCap(), baseFee, + ) } - return errs[0] + + // we push the tx onto the evm insert queue so the tx will be inserted + // at a later point. We get back a subscription that the insert queue + // will use to notify the caller of any errors that occurred when + // inserting into the mempool. + return m.evmInsertQueue.Push(ethTx), nil + case errors.Is(err, ErrMultiMsgEthereumTransaction): + // there are multiple messages in this tx and one or more of them is an + // evm tx, this is invalid + return nil, err + default: + // we push the tx onto the cosmos insert queue so the tx will be + // inserted at a later point. We get back a subscription that the + // insert queue will use to notify the caller of any errors that + // occurred when inserting into the mempool. + return m.cosmosInsertQueue.Push(&tx), nil } - return nil +} + +// ReapNewValidTxs removes and returns the oldest transactions from the reap +// list until maxBytes or maxGas limits are reached. +func (m *Mempool) ReapNewValidTxs(maxBytes uint64, maxGas uint64) ([][]byte, error) { + m.logger.Debug("reaping transactions", "maxBytes", maxBytes, "maxGas", maxGas, "available_txs") + txs := m.reapList.Reap(maxBytes, maxGas) + m.logger.Debug("reap complete", "txs_reaped", len(txs)) + + return txs, nil } // Select returns a unified iterator over both EVM and Cosmos transactions. // The iterator prioritizes transactions based on their fees and manages proper // sequencing. The i parameter contains transaction hashes to exclude from selection. -func (m *ExperimentalEVMMempool) Select(goCtx context.Context, i [][]byte) sdkmempool.Iterator { - m.mtx.Lock() - defer m.mtx.Unlock() - ctx := sdk.UnwrapSDKContext(goCtx) +func (m *Mempool) Select(goCtx context.Context, i [][]byte) sdkmempool.Iterator { + return m.buildIterator(goCtx, i) +} + +// SelectBy iterates through transactions until the provided filter function returns false. +// It uses the same unified iterator as Select but allows early termination based on +// custom criteria defined by the filter function. +func (m *Mempool) SelectBy(goCtx context.Context, txs [][]byte, filter func(sdk.Tx) bool) { + defer func(t0 time.Time) { + selectByDuration.Record(goCtx, float64(time.Since(t0).Milliseconds())) + }(time.Now()) - evmIterator, cosmosIterator := m.getIterators(goCtx, i) + iter := m.buildIterator(goCtx, txs) - combinedIterator := NewEVMMempoolIterator(evmIterator, cosmosIterator, m.logger, m.txConfig, m.vmKeeper.GetEvmCoinInfo(ctx).Denom, m.blockchain.Config().ChainID, m.blockchain) + for iter != nil && filter(iter.Tx()) { + iter = iter.Next() + } +} - return combinedIterator +// buildIterator ensures that EVM mempool has checked txs for reorgs up to COMMITTED +// block height and then returns a combined iterator over EVM & Cosmos txs. +func (m *Mempool) buildIterator(ctx context.Context, txs [][]byte) sdkmempool.Iterator { + defer func(t0 time.Time) { + buildIteratorDuration.Record(ctx, float64(time.Since(t0).Milliseconds())) + }(time.Now()) + + evmIterator, cosmosIterator := m.getIterators(ctx, txs) + + return NewEVMMempoolIterator( + evmIterator, + cosmosIterator, + m.logger, + m.txConfig, + m.blockchain, + ) } // CountTx returns the total number of transactions in both EVM and Cosmos pools. // This provides a combined count across all mempool types. -func (m *ExperimentalEVMMempool) CountTx() int { +func (m *Mempool) CountTx() int { pending, _ := m.txPool.Stats() - return m.cosmosPool.CountTx() + pending + return m.recheckCosmosPool.CountTx() + pending } -// Remove removes a transaction from the appropriate sdkmempool. -// For EVM transactions, removal is typically handled automatically by the pool -// based on nonce progression. Cosmos transactions are removed from the Cosmos pool. -func (m *ExperimentalEVMMempool) Remove(tx sdk.Tx) error { - m.mtx.Lock() - defer m.mtx.Unlock() +// Remove fallbacks for RemoveWithReason +func (m *Mempool) Remove(tx sdk.Tx) error { + return m.RemoveWithReason(context.Background(), tx, sdkmempool.RemoveReason{ + Caller: "remove", + Error: nil, + }) +} - if m.blockchain.latestCtx.BlockHeight() == 0 { - return nil +// RemoveWithReason removes a transaction from the appropriate sdkmempool. +// +// NOTE #1: even if removal fails, side effects may have occurred like recording +// nonce increments. +// +// NOTE #2: This method might be called multiple times for the same tx: +// - during tx re-execution by BlockSTM +// - during tx execution by OptimisticExecution that fails +// and then inside another finalizeBlock() (e.g. consensus round increment) +func (m *Mempool) RemoveWithReason(_ context.Context, tx sdk.Tx, reason sdkmempool.RemoveReason) error { + msgEthereumTx, err := evmTxFromCosmosTx(tx) + switch { + case errors.Is(err, ErrNoMessages): + return err + case err != nil: + // unable to parse evm tx -> process as cosmos tx + return m.removeCosmosTx(tx, reason) + default: + return m.removeEVMTx(tx, msgEthereumTx, reason) } +} - m.logger.Debug("removing transaction from mempool") - - msg, err := m.getEVMMessage(tx) - if err == nil { - // Comet will attempt to remove transactions from the mempool after completing successfully. - // 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", hash) - m.legacyTxPool.RemoveTx(hash, false, true) - } else { - m.logger.Debug("skipping manual removal of EVM transaction, leaving to mempool to handle", "tx_hash", hash) - } - return nil - } +// removeCosmosTx removes a cosmos tx from the mempool. +// The RecheckMempool handles locking internally. +func (m *Mempool) removeCosmosTx(tx sdk.Tx, reason sdkmempool.RemoveReason) error { + m.logger.Debug("Removing Cosmos transaction") - if errors.Is(err, ErrNoMessages) { - return err + if reason.Caller == sdkmempool.CallerRunTxFinalize { + m.recordNonceAdvances(tx) } - m.logger.Debug("removing Cosmos transaction") - err = m.cosmosPool.Remove(tx) - if err != nil { - m.logger.Error("failed to remove Cosmos transaction", "error", err) - } else { - m.logger.Debug("Cosmos transaction removed successfully") + if err := m.recheckCosmosPool.Remove(tx); err != nil { + return fmt.Errorf("recheckCosmosPool.Remove: %w", err) } - return err + + m.logger.Debug("Cosmos transaction removed successfully") + + return nil } -// shouldRemoveFromEVMPool determines whether an EVM transaction should be manually removed. -// It uses the AnteHandler to check if the transaction failed for reasons -// other than nonce gaps or successful execution, in which case manual removal is needed. -func (m *ExperimentalEVMMempool) shouldRemoveFromEVMPool(tx sdk.Tx) bool { - if m.anteHandler == nil { - m.logger.Debug("no ante handler available, keeping transaction") - return false - } +// removeEVMTx removes a evm tx from the mempool. +func (m *Mempool) removeEVMTx(tx sdk.Tx, msgEthereumTx *evmtypes.MsgEthereumTx, reason sdkmempool.RemoveReason) error { + m.logger.Debug("Removing EVM transaction") - // 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.GetLatestContext() - if err != nil { - m.logger.Debug("cannot get latest context for validation, keeping transaction", "error", err) - return false // Cannot validate, keep transaction + hash := msgEthereumTx.Hash() + if reason.Caller == sdkmempool.CallerRunTxFinalize { + _ = m.txTracker.IncludedInBlock(hash) + m.recordNonceAdvances(tx) } - _, err = m.anteHandler(ctx, tx, true) - // Keep nonce gap transactions, remove others that fail validation - if errors.Is(err, ErrNonceGap) || errors.Is(err, sdkerrors.ErrInvalidSequence) || errors.Is(err, sdkerrors.ErrOutOfGas) { - m.logger.Debug("nonce gap detected, keeping transaction", "error", err) - return false + if m.shouldRemoveFromEVMPool(hash, reason) { + m.logger.Debug("Manually removing EVM transaction", "tx_hash", hash) + m.legacyTxPool.RemoveTx(hash, false, true, convertRemovalReason(reason.Caller)) } - if err != nil { - m.logger.Debug("transaction validation failed, should be removed", "error", err) - } else { - m.logger.Debug("transaction validation succeeded, should be kept") - } + m.logger.Debug("EVM transaction removed successfully") - return err != nil + return nil } -// SelectBy iterates through transactions until the provided filter function returns false. -// It uses the same unified iterator as Select but allows early termination based on -// custom criteria defined by the filter function. -func (m *ExperimentalEVMMempool) SelectBy(goCtx context.Context, i [][]byte, f func(sdk.Tx) bool) { - m.mtx.Lock() - defer m.mtx.Unlock() - ctx := sdk.UnwrapSDKContext(goCtx) - - evmIterator, cosmosIterator := m.getIterators(goCtx, i) +// recordNonceAdvances records the on chain nonce advance for every signer of +// tx in the legacypool. +func (m *Mempool) recordNonceAdvances(tx sdk.Tx) { + signers, err := m.signerExtractor.GetSigners(tx) + if err != nil { + m.logger.Warn("could not extract signers for nonce tracking", "err", err) + return + } + for _, s := range signers { + m.legacyTxPool.SetLatestNonce(common.BytesToAddress(s.Signer), s.Sequence) + } +} - combinedIterator := NewEVMMempoolIterator(evmIterator, cosmosIterator, m.logger, m.txConfig, m.vmKeeper.GetEvmCoinInfo(ctx).Denom, m.blockchain.Config().ChainID, m.blockchain) +// shouldRemoveFromEVMPool determines whether an EVM transaction should be manually removed. +func (m *Mempool) shouldRemoveFromEVMPool(hash common.Hash, reason sdkmempool.RemoveReason) bool { + if reason.Error == nil { + return false + } + // Comet will attempt to remove transactions from the mempool after completing successfully. + // 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. + isKnown := errors.Is(reason.Error, ErrNonceGap) || + errors.Is(reason.Error, sdkerrors.ErrInvalidSequence) || + errors.Is(reason.Error, sdkerrors.ErrOutOfGas) - for combinedIterator != nil && f(combinedIterator.Tx()) { - combinedIterator = combinedIterator.Next() + if isKnown { + m.logger.Debug("Transaction validation succeeded, should be kept", "tx_hash", hash, "caller", reason.Caller) + return false } + + m.logger.Debug("Transaction validation failed, should be removed", "tx_hash", hash, "caller", reason.Caller) + return true } // SetEventBus sets CometBFT event bus to listen for new block header event. -func (m *ExperimentalEVMMempool) SetEventBus(eventBus *cmttypes.EventBus) { +func (m *Mempool) SetEventBus(eventBus *cmttypes.EventBus) { if m.HasEventBus() { m.eventBus.Unsubscribe(context.Background(), SubscriberName, stream.NewBlockHeaderEvents) //nolint: errcheck } @@ -406,18 +532,24 @@ func (m *ExperimentalEVMMempool) SetEventBus(eventBus *cmttypes.EventBus) { } go func() { for range sub.Out() { - m.GetBlockchain().NotifyNewBlock() + m.NotifyNewBlock() } }() } +// NotifyNewBlock manually notifies that there has been a new block produced +// and it should update its internal data structures. +func (m *Mempool) NotifyNewBlock() { + m.blockchain.NotifyNewBlock() + m.recheckCosmosPool.TriggerRecheck(m.blockchain.CurrentBlock()) +} + // HasEventBus returns true if the blockchain is configured to use an event bus for block notifications. -func (m *ExperimentalEVMMempool) HasEventBus() bool { +func (m *Mempool) HasEventBus() bool { return m.eventBus != nil } -// Close unsubscribes from the CometBFT event bus and shuts down the mempool. -func (m *ExperimentalEVMMempool) Close() error { +func (m *Mempool) Close() error { var errs []error if m.eventBus != nil { if err := m.eventBus.Unsubscribe(context.Background(), SubscriberName, stream.NewBlockHeaderEvents); err != nil { @@ -425,6 +557,10 @@ func (m *ExperimentalEVMMempool) Close() error { } } + if err := m.recheckCosmosPool.Close(); err != nil { + errs = append(errs, fmt.Errorf("failed to close cosmos pool: %w", err)) + } + if err := m.txPool.Close(); err != nil { errs = append(errs, fmt.Errorf("failed to close txpool: %w", err)) } @@ -432,76 +568,141 @@ func (m *ExperimentalEVMMempool) Close() error { 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) { - msgs := tx.GetMsgs() - if len(msgs) == 0 { - return nil, ErrNoMessages - } - if len(msgs) != 1 { - return nil, fmt.Errorf("%w, got %d", ErrExpectedOneMessage, len(msgs)) - } - ethMsg, ok := msgs[0].(*evmtypes.MsgEthereumTx) - if !ok { - return nil, ErrNotEVMTransaction - } - return ethMsg, nil -} - // getIterators prepares iterators over pending EVM and Cosmos transactions. // It configures EVM transactions with proper base fee filtering and priority ordering, // while setting up the Cosmos iterator with the provided exclusion list. -func (m *ExperimentalEVMMempool) getIterators(goCtx context.Context, i [][]byte) (*miner.TransactionsByPriceAndNonce, sdkmempool.Iterator) { - ctx := sdk.UnwrapSDKContext(goCtx) - baseFee := m.vmKeeper.GetBaseFee(ctx) +func (m *Mempool) getIterators(ctx context.Context, _ [][]byte) (evm *miner.TransactionsByPriceAndNonce, cosmos sdkmempool.Iterator) { + var ( + evmIterator *miner.TransactionsByPriceAndNonce + cosmosIterator sdkmempool.Iterator + wg sync.WaitGroup + ) + + // using ctx.BlockHeight() - 1 since we want to get txs that have been + // validated at latest committed height, and ctx.BlockHeight() returns the + // latest uncommitted height + sdkctx := sdk.UnwrapSDKContext(ctx) + selectHeight := new(big.Int).SetInt64(sdkctx.BlockHeight() - 1) + + // Keeper reads consume gas on the SDK context. Fetch these inputs once + // before starting goroutines so we do not race on the shared gas meters. + baseFee := m.vmKeeper.GetBaseFee(sdkctx) + coinDenom := m.blockchain.GetCoinDenom() + cosmosBaseFee := currentBaseFee(m.blockchain) + + wg.Go(func() { + evmIterator = m.evmIterator(ctx, selectHeight, baseFee) + }) + + wg.Go(func() { + cosmosIterator = m.cosmosIterator(ctx, selectHeight, coinDenom, cosmosBaseFee) + }) + + wg.Wait() + + return evmIterator, cosmosIterator +} + +// evmIterator returns an iterator over the current valid txs in the evm +// mempool at height. +func (m *Mempool) evmIterator(ctx context.Context, height *big.Int, baseFee *big.Int) *miner.TransactionsByPriceAndNonce { var baseFeeUint *uint256.Int if baseFee != nil { baseFeeUint = uint256.MustFromBig(baseFee) } - m.logger.Debug("getting iterators") - - pendingFilter := txpool.PendingFilter{ + filter := txpool.PendingFilter{ MinTip: m.minTip, BaseFee: baseFeeUint, BlobFee: nil, OnlyPlainTxs: true, OnlyBlobTxs: false, } - evmPendingTxes := m.txPool.Pending(pendingFilter) - orderedEVMPendingTxes := miner.NewTransactionsByPriceAndNonce(nil, evmPendingTxes, baseFee) - cosmosPendingTxes := m.cosmosPool.Select(ctx, i) + if m.pendingTxProposalTimeout > 0 { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, m.pendingTxProposalTimeout) + defer cancel() + } + evmPendingTxs := m.txPool.Rechecked(ctx, height, filter) + return miner.NewTransactionsByPriceAndNonce(nil, evmPendingTxs, baseFee) +} - return orderedEVMPendingTxes, cosmosPendingTxes +// cosmosIterator returns an iterator over the current valid txs in the cosmos +// mempool at height. +func (m *Mempool) cosmosIterator( + ctx context.Context, + height *big.Int, + bondDenom string, + baseFee *uint256.Int, +) sdkmempool.Iterator { + if m.pendingTxProposalTimeout > 0 { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, m.pendingTxProposalTimeout) + defer cancel() + } + return m.recheckCosmosPool.OrderedRecheckedTxs(ctx, height, bondDenom, baseFee) } -// broadcastEVMTransactions converts Ethereum transactions to Cosmos SDK format and broadcasts them. -// This function wraps EVM transactions in MsgEthereumTx messages and submits them to the network -// using the provided client context. It handles encoding and error reporting for each transaction. -func broadcastEVMTransactions(clientCtx client.Context, txConfig client.TxConfig, ethTxs []*ethtypes.Transaction) error { - for _, ethTx := range ethTxs { - msg := &evmtypes.MsgEthereumTx{} - msg.FromEthereumTx(ethTx) +// TrackTx submits a tx to be tracked for its tx inclusion metrics. +func (m *Mempool) TrackTx(hash common.Hash) error { + return m.txTracker.Track(hash) +} - txBuilder := txConfig.NewTxBuilder() - if err := txBuilder.SetMsgs(msg); err != nil { - return fmt.Errorf("failed to set msg in tx builder: %w", err) - } +// RecheckEVMTxs triggers a synchronous recheck of evm transactions. +// This should only be used for testing. +func (m *Mempool) RecheckEVMTxs(newHead *ethtypes.Header) { + m.txPool.Reset(nil, newHead) +} - txBytes, err := txConfig.TxEncoder()(txBuilder.GetTx()) - if err != nil { - return fmt.Errorf("failed to encode transaction: %w", err) - } +// RecheckCosmosTxs triggers a synchronous recheck of cosmos transactions. +// This should only used for testing. +func (m *Mempool) RecheckCosmosTxs(newHead *ethtypes.Header) { + m.recheckCosmosPool.TriggerRecheckSync(newHead) +} - res, err := clientCtx.BroadcastTxSync(txBytes) - if err != nil { - return fmt.Errorf("failed to broadcast transaction %s: %w", ethTx.Hash().Hex(), err) - } - if res.Code != 0 { - return fmt.Errorf("transaction %s rejected by mempool: code=%d, log=%s", ethTx.Hash().Hex(), res.Code, res.RawLog) +// 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 evmTxFromCosmosTx(tx sdk.Tx) (*evmtypes.MsgEthereumTx, error) { + msgs := tx.GetMsgs() + if len(msgs) == 0 { + return nil, ErrNoMessages + } + + // ethereum txs should only contain a single msg that is a MsgEthereumTx + // type + if len(msgs) > 1 { + // transaction has > 1 msg, will be treated as a cosmos tx by the + // mempool. validate that none of the msgs are a MsgEthereumTx since + // those should only be used in the single msg case + for _, msg := range msgs { + if _, ok := msg.(*evmtypes.MsgEthereumTx); ok { + return nil, ErrMultiMsgEthereumTransaction + } } + + // transaction has > 1 msg, but none were ethereum txs, this is + // still not a valid eth tx + return nil, fmt.Errorf("%w, got %d", ErrExpectedOneMessage, len(msgs)) + } + + ethMsg, ok := msgs[0].(*evmtypes.MsgEthereumTx) + if !ok { + return nil, ErrNotEVMTransaction + } + return ethMsg, nil +} + +// convertRemovalReason converts a removal caller to a removal reason +func convertRemovalReason(caller sdkmempool.RemovalCaller) txpool.RemovalReason { + switch caller { + case sdkmempool.CallerRunTxRecheck: + return legacypool.RemovalReasonRunTxRecheck + case sdkmempool.CallerRunTxFinalize: + return legacypool.RemovalReasonRunTxFinalize + case sdkmempool.CallerPrepareProposalRemoveInvalid: + return legacypool.RemovalReasonPrepareProposalInvalid + default: + return txpool.RemovalReason("") } - return nil } diff --git a/mempool/mempool_handlers.go b/mempool/mempool_handlers.go new file mode 100644 index 00000000..eee781e8 --- /dev/null +++ b/mempool/mempool_handlers.go @@ -0,0 +1,113 @@ +package mempool + +import ( + "context" + "errors" + "fmt" + "time" + + abci "github.com/cometbft/cometbft/abci/types" + + errorsmod "cosmossdk.io/errors" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/evm/mempool/txpool" +) + +const ( + CodeTypeNoRetry = uint32(1) +) + +// NewReapTxsHandler is the handler for ABCI.ReapTxs. It's used by CometBFT +// to reap valid txs from the mempool and share them with other peers. Handles concurrent requests. +func (m *Mempool) NewReapTxsHandler() sdk.ReapTxsHandler { + return func(req *abci.RequestReapTxs) (*abci.ResponseReapTxs, error) { + maxBytes, maxGas := req.GetMaxBytes(), req.GetMaxGas() + + txs, err := m.ReapNewValidTxs(maxBytes, maxGas) + if err != nil { + return nil, fmt.Errorf( + "reaping new valid txs from evm mempool with %d max bytes and %d max gas: %w", + maxBytes, maxGas, err, + ) + } + + return &abci.ResponseReapTxs{Txs: txs}, nil + } +} + +// NewInsertTxHandler is the handler for ABCI.InsertTx. Used by CometBFT to asynchronously +// insert a new tx into the mempool. Supersedes ABCI.CheckTx. Handles concurrent requests +func (m *Mempool) NewInsertTxHandler(txDecoder sdk.TxDecoder) sdk.InsertTxHandler { + return func(req *abci.RequestInsertTx) (*abci.ResponseInsertTx, error) { + tx, err := txDecoder(req.GetTx()) + if err != nil { + return nil, fmt.Errorf("decoding tx: %w", err) + } + + code := abci.CodeTypeOK + + if err := m.InsertAsync(tx); err != nil { + // since we are using InsertAsync here, the only errors that will + // be returned are via the InsertQueue if it is full (for EVM txs), + // in which case we should retry, or some level of validation + // failed on a cosmos tx (CheckTx), invalid encoding, etc, in which + // case we should not retry + if errors.Is(err, ErrQueueFull) { + code = abci.CodeTypeRetry + } else { + code = CodeTypeNoRetry + } + } + + return &abci.ResponseInsertTx{Code: code}, nil + } +} + +// NewCheckTxHandler is the handler for ABCI.CheckTx. Note: it's async and doesn't expect the caller +// to acquire ABCI lock. Used ONLY to support BroadcastTxSync (cosmos rpc). All EVM txs +// should be inserted via InsertTx handler or EVM RPC. +func (m *Mempool) NewCheckTxHandler(txDecoder sdk.TxDecoder, timeout time.Duration) sdk.CheckTxHandler { + return func(_ sdk.RunTx, req *abci.RequestCheckTx) (*abci.ResponseCheckTx, error) { + if req.Type != abci.CheckTxType_New { + return nil, fmt.Errorf("unsupported abci.RequestCheckTx.Type: %s", req.Type) + } + + ctx, cancel := context.WithTimeout(context.Background(), timeout) + defer cancel() + + tx, err := txDecoder(req.GetTx()) + if err != nil { + return nil, fmt.Errorf("decoding tx: %w", err) + } + + err = m.Insert(ctx, tx) + + return ErrAsCheckTxResponse(err), nil + } +} + +// ErrAsCheckTxResponse converts an error to a ResponseCheckTx object, respecting error wrapping. +func ErrAsCheckTxResponse(err error) *abci.ResponseCheckTx { + if err == nil || errors.Is(err, txpool.ErrAlreadyKnown) { + // Already-known is success so a promoted nonce-gap tx can be re-gossiped. + return &abci.ResponseCheckTx{Code: abci.CodeTypeOK} + } + + space, code, log := errorsmod.ABCIInfo(err, false) + + // walk the wrap chain for the innermost sdk error + for e := errors.Unwrap(err); e != nil && space == errorsmod.UndefinedCodespace; e = errors.Unwrap(e) { + space, code, log = errorsmod.ABCIInfo(e, false) + } + + return &abci.ResponseCheckTx{ + Codespace: space, + Code: code, + Log: log, + GasWanted: 0, + GasUsed: 0, + Events: nil, + } +} diff --git a/mempool/mempool_handlers_test.go b/mempool/mempool_handlers_test.go new file mode 100644 index 00000000..914f6cf1 --- /dev/null +++ b/mempool/mempool_handlers_test.go @@ -0,0 +1,260 @@ +package mempool_test + +import ( + "fmt" + "math/big" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + abci "github.com/cometbft/cometbft/abci/types" + + "github.com/cosmos/evm/mempool" + vmtypes "github.com/cosmos/evm/x/vm/types" + + errorsmod "cosmossdk.io/errors" + + sdk "github.com/cosmos/cosmos-sdk/types" + errortypes "github.com/cosmos/cosmos-sdk/types/errors" +) + +func TestMempoolHandlers(t *testing.T) { + asEvmTx := func(t *testing.T, tx sdk.Tx) *vmtypes.EthereumTx { + t.Helper() + msg, ok := tx.GetMsgs()[0].(*vmtypes.MsgEthereumTx) + require.True(t, ok) + + return &msg.Raw + } + + t.Run("CheckTx", func(t *testing.T) { + t.Run("EVM", func(t *testing.T) { + // ARRANGE + // given the mempool + mp, deps := setupMempool(t, 2, 1) + + // given checkTxHandler + const timeout = time.Second + checkTxHandler := mp.NewCheckTxHandler(deps.txConfig.TxDecoder(), timeout) + + // given tx + tx := createMsgEthereumTx(t, deps.txConfig, deps.accounts[0].key, 0, big.NewInt(1e8)) + evmTx := asEvmTx(t, tx) + + txBytes, err := deps.txConfig.TxEncoder()(tx) + require.NoError(t, err) + + // ACT + resp, err := checkTxHandler(sdk.RunTx(nil), &abci.RequestCheckTx{ + Type: abci.CheckTxType_New, + Tx: txBytes, + }) + + // ASSERT + require.NoError(t, err) + require.Equal(t, abci.CodeTypeOK, resp.Code) + + mempoolTx := mp.GetTxPool().Get(evmTx.Hash()) + require.NotNil(t, mempoolTx) + + t.Run("Duplicate", func(t *testing.T) { + // ACT + // Add again + resp, err := checkTxHandler(sdk.RunTx(nil), &abci.RequestCheckTx{ + Type: abci.CheckTxType_New, + Tx: txBytes, + }) + + // ASSERT + require.NoError(t, err) + require.Equal(t, uint32(1), resp.Code) + require.Contains(t, resp.Log, "already known") + }) + + t.Run("TimedOut", func(t *testing.T) { + // ARRANGE + // Given a slow decoder + decoder := func(tx []byte) (sdk.Tx, error) { + time.Sleep(100 * time.Millisecond) + return deps.txConfig.TxDecoder()(tx) + } + + // Given a checkTxHandler that times out + checkTxHandler := mp.NewCheckTxHandler(decoder, 50*time.Millisecond) + + // Given tx2 + tx2 := createMsgEthereumTx(t, deps.txConfig, deps.accounts[1].key, 0, big.NewInt(1e8)) + tx2Bytes, err := deps.txConfig.TxEncoder()(tx2) + require.NoError(t, err) + + // ACT + resp, err := checkTxHandler(sdk.RunTx(nil), &abci.RequestCheckTx{ + Type: abci.CheckTxType_New, + Tx: tx2Bytes, + }) + + // ASSERT + require.NoError(t, err) + require.Equal(t, uint32(1), resp.Code) + require.Contains(t, resp.Log, "context deadline exceeded") + }) + }) + + t.Run("Cosmos", func(t *testing.T) { + // ARRANGE + // given the mempool + mp, deps := setupMempool(t, 2, 1000) + + // given checkTxHandler + const timeout = time.Second + checkTxHandler := mp.NewCheckTxHandler(deps.txConfig.TxDecoder(), timeout) + + // given a cosmos tx + tx := createTestCosmosTx(t, deps.txConfig, deps.accounts[0].key, 0) + txBytes, err := deps.txConfig.TxEncoder()(tx) + require.NoError(t, err) + + // ACT + resp, err := checkTxHandler(sdk.RunTx(nil), &abci.RequestCheckTx{ + Type: abci.CheckTxType_New, + Tx: txBytes, + }) + + // ASSERT + require.NoError(t, err) + require.Equal(t, abci.CodeTypeOK, resp.Code) + require.Equal(t, 1, mp.CountTx()) + + t.Run("TimedOut", func(t *testing.T) { + // ARRANGE + // Given a slow decoder + decoder := func(tx []byte) (sdk.Tx, error) { + time.Sleep(100 * time.Millisecond) + return deps.txConfig.TxDecoder()(tx) + } + + // Given a checkTxHandler that times out + checkTxHandler := mp.NewCheckTxHandler(decoder, 50*time.Millisecond) + + // Given a tx from a different signer so reserver doesn't collide + tx2 := createTestCosmosTx(t, deps.txConfig, deps.accounts[1].key, 0) + tx2Bytes, err := deps.txConfig.TxEncoder()(tx2) + require.NoError(t, err) + + // ACT + resp, err := checkTxHandler(sdk.RunTx(nil), &abci.RequestCheckTx{ + Type: abci.CheckTxType_New, + Tx: tx2Bytes, + }) + + // ASSERT + require.NoError(t, err) + assert.Equal(t, uint32(1), resp.Code) + assert.Contains(t, resp.Log, "context deadline exceeded") + }) + }) + + t.Run("Recheck", func(t *testing.T) { + // ARRANGE + mp, deps := setupMempool(t, 1, 1) + checkTxHandler := mp.NewCheckTxHandler(deps.txConfig.TxDecoder(), time.Second) + + // ACT + resp, err := checkTxHandler(sdk.RunTx(nil), &abci.RequestCheckTx{ + Type: abci.CheckTxType_Recheck, + Tx: []byte("anything"), + }) + + // ASSERT + require.Error(t, err) + assert.Contains(t, err.Error(), "unsupported") + assert.Nil(t, resp) + }) + + t.Run("DecodeError", func(t *testing.T) { + // ARRANGE + mp, deps := setupMempool(t, 1, 1) + checkTxHandler := mp.NewCheckTxHandler(deps.txConfig.TxDecoder(), time.Second) + + // ACT + resp, err := checkTxHandler(sdk.RunTx(nil), &abci.RequestCheckTx{ + Type: abci.CheckTxType_New, + Tx: []byte("not a valid tx"), + }) + + // ASSERT + require.Error(t, err) + assert.Contains(t, err.Error(), "decoding tx") + assert.Nil(t, resp) + }) + }) +} + +func TestErrAsCheckTxResponse(t *testing.T) { + assertResponse := func(codespace string, code uint32, log string) func(t *testing.T, resp *abci.ResponseCheckTx) { + return func(t *testing.T, resp *abci.ResponseCheckTx) { + t.Helper() + + require.Equal(t, codespace, resp.Codespace) + require.Equal(t, code, resp.Code) + require.Equal(t, log, resp.Log) + } + } + + for _, tt := range []struct { + name string + err error + assert func(t *testing.T, resp *abci.ResponseCheckTx) + }{ + { + name: "nil error", + err: nil, + assert: func(t *testing.T, resp *abci.ResponseCheckTx) { + t.Helper() + require.Equal(t, abci.CodeTypeOK, resp.Code) + }, + }, + { + name: "std error", + err: fmt.Errorf("oops"), + assert: assertResponse(errorsmod.UndefinedCodespace, 1, "oops"), + }, + { + name: "std wrapped error", + err: errorsmod.Wrap(fmt.Errorf("oops"), "wrapped"), + assert: assertResponse(errorsmod.UndefinedCodespace, 1, "oops"), + }, + { + name: "sdk error", + err: errortypes.ErrInsufficientFee, + assert: assertResponse(errortypes.RootCodespace, 13, "insufficient fee"), + }, + { + name: "wrapped sdk error", + err: errorsmod.Wrap(errortypes.ErrOutOfGas, "unable to exec tx"), + assert: assertResponse(errortypes.RootCodespace, 11, "unable to exec tx: out of gas"), + }, + { + name: "nested sdk wrapped sdk error", + err: errorsmod.Wrap(errorsmod.Wrap(errortypes.ErrOutOfGas, "unable to exec tx"), "wrapped"), + assert: assertResponse(errortypes.RootCodespace, 11, "wrapped: unable to exec tx: out of gas"), + }, + { + name: "std wrapped sdk error", + err: fmt.Errorf("something went wrong: %w", errortypes.ErrOutOfGas), + assert: assertResponse(errortypes.RootCodespace, 11, "out of gas"), + }, + { + name: "nested std wrapped sdk error", + err: fmt.Errorf("something went wrong: %w", fmt.Errorf("oops: %w", errortypes.ErrTxTimeout)), + assert: assertResponse(errortypes.RootCodespace, 42, "tx timeout"), + }, + } { + t.Run(tt.name, func(t *testing.T) { + resp := mempool.ErrAsCheckTxResponse(tt.err) + tt.assert(t, resp) + }) + } +} diff --git a/mempool/mempool_test.go b/mempool/mempool_test.go new file mode 100644 index 00000000..f27d1cf1 --- /dev/null +++ b/mempool/mempool_test.go @@ -0,0 +1,1275 @@ +package mempool_test + +import ( + "context" + "crypto/ecdsa" + "errors" + "fmt" + "math/big" + "strconv" + "sync" + "testing" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/holiman/uint256" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + cmttypes "github.com/cometbft/cometbft/types" + + "github.com/cosmos/evm/crypto/ethsecp256k1" + "github.com/cosmos/evm/encoding" + "github.com/cosmos/evm/mempool" + "github.com/cosmos/evm/mempool/mocks" + "github.com/cosmos/evm/mempool/reserver" + "github.com/cosmos/evm/mempool/txpool/legacypool" + "github.com/cosmos/evm/testutil/constants" + evmtestutiltx "github.com/cosmos/evm/testutil/tx" + "github.com/cosmos/evm/x/vm/statedb" + vmtypes "github.com/cosmos/evm/x/vm/types" + + "cosmossdk.io/log/v2" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" + "github.com/cosmos/cosmos-sdk/testutil" + sdk "github.com/cosmos/cosmos-sdk/types" + mempooltypes "github.com/cosmos/cosmos-sdk/types/mempool" + signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +func TestMempool_Reserver(t *testing.T) { + mp, s := setupMempoolWithAccounts(t, 3) + txConfig, accounts := s.txConfig, s.accounts + + accountKey := accounts[0].key + + // insert eth tx from account0 + ethTx := createMsgEthereumTx(t, txConfig, accountKey, 0, big.NewInt(1e8)) + err := mp.Insert(context.Background(), ethTx) + require.NoError(t, err) + + // insert cosmos tx from acount0, should error + cosmosTx := createTestCosmosTx(t, txConfig, accountKey, 0) + err = mp.Insert(context.Background(), cosmosTx) + require.ErrorIs(t, err, reserver.ErrAlreadyReserved) + + // remove the eth tx + err = mp.RemoveWithReason(context.Background(), ethTx, mempooltypes.RemoveReason{Error: errors.New("some error")}) + require.NoError(t, err) + + // pool should be clear + require.Equal(t, 0, mp.CountTx()) + + // should be able to insert the cosmos tx now + err = mp.Insert(context.Background(), cosmosTx) + require.NoError(t, err) + + // should be able to send another tx from the same account to the same pool. + cosmosTx2 := createTestCosmosTx(t, txConfig, accountKey, 1) + err = mp.Insert(context.Background(), cosmosTx2) + require.NoError(t, err) + + // there should be 2 txs at this point + require.Equal(t, 2, mp.CountTx()) + + // eth tx should now fail. + err = mp.Insert(context.Background(), ethTx) + require.ErrorIs(t, err, reserver.ErrAlreadyReserved) +} + +func TestMempool_ReserverMultiSigner(t *testing.T) { + mp, s := setupMempoolWithAccounts(t, 4) + txConfig, accounts := s.txConfig, s.accounts + + accountKey := accounts[0].key + + // insert eth tx from account0 + ethTx := createMsgEthereumTx(t, txConfig, accountKey, 0, big.NewInt(1e8)) + err := mp.Insert(context.Background(), ethTx) + require.NoError(t, err) + + // inserting accounts 1 & 2 should be fine. + cosmosTx := createTestMultiSignerCosmosTx(t, txConfig, accounts[1].key, accounts[2].key) + err = mp.Insert(context.Background(), cosmosTx) + require.NoError(t, err) + + // submitting account1 key should fail, since it was part of the signer group in the cosmos tx. + ethTx2 := createMsgEthereumTx(t, txConfig, accounts[1].key, 1, big.NewInt(1e8)) + err = mp.Insert(context.Background(), ethTx2) + require.ErrorIs(t, err, reserver.ErrAlreadyReserved) + + // account 0 already has ethTx in pool, should fail. + comsosTx := createTestMultiSignerCosmosTx(t, txConfig, accounts[3].key, accounts[0].key) + err = mp.Insert(context.Background(), comsosTx) + require.ErrorIs(t, err, reserver.ErrAlreadyReserved) +} + +// Ensures txs are not reaped multiple times when promoting and demoting the +// same tx +func TestMempool_ReapPromoteDemotePromote(t *testing.T) { + mp, s := setupMempoolWithAccounts(t, 3) + txConfig, rechecker, bus, accounts := s.txConfig, s.evmRechecker, s.eventBus, s.accounts + + err := bus.PublishEventNewBlockHeader(cmttypes.EventDataNewBlockHeader{ + Header: cmttypes.Header{ + Height: 1, + Time: time.Now(), + ChainID: strconv.Itoa(constants.EighteenDecimalsChainID), + }, + }) + require.NoError(t, err) + + // for a reset to happen for block 1 and wait for it + require.NoError(t, mp.GetTxPool().Sync()) + + // Account 0: Insert 3 sequential transactions (nonce 0, 1, 2) - should all go to pending + for nonce := uint64(0); nonce < 3; nonce++ { + tx := createMsgEthereumTx(t, txConfig, accounts[0].key, nonce, big.NewInt(1e8)) + err := mp.Insert(sdk.Context{}.WithContext(context.Background()), tx) + require.NoError(t, err, "failed to insert pending tx for account 0, nonce %d", nonce) + } + + // wait for another reset to make sure the pool processes the above txns into pending + require.NoError(t, mp.GetTxPool().Sync()) + require.Equal(t, 3, mp.CountTx()) + + // reap txs now and we should get back all txs since they were all validated + txs, err := mp.ReapNewValidTxs(0, 0) + require.NoError(t, err) + require.Len(t, txs, 3) + + // setup tx with nonce 1 to fail recheck. it will get kicked out of the + // pool and tx with nonce 2 will be demoted to queued (when tx 1 is + // resubmitted, it will be returned from reap again). + rechecker.SetEVMRecheck(func(ctx sdk.Context, tx *types.Transaction) (sdk.Context, error) { + if tx.Nonce() == 1 { + return sdk.Context{}, errors.New("recheck failed on tx with nonce 1") + } + return sdk.Context{}, nil + }) + + // sync the pool to make sure the above happens + require.NoError(t, mp.GetTxPool().Sync()) + legacyPool := mp.GetTxPool().Subpools[0].(*legacypool.LegacyPool) + pending, queued := legacyPool.ContentFrom(accounts[0].address) + require.Len(t, pending, 1) + require.Len(t, queued, 1) + + // reap should now return no txs, since no new txs have been validated + txs, err = mp.ReapNewValidTxs(0, 0) + require.NoError(t, err) + require.Len(t, txs, 0) + + // setup recheck to not fail any txs again, tx 2 will not fail this but + // it wont be promoted since it is nonce gapped from tx 1 + rechecker.SetEVMRecheck(func(ctx sdk.Context, tx *types.Transaction) (sdk.Context, error) { + return sdk.Context{}, nil + }) + + // sync the pool to make sure the above happens + require.NoError(t, mp.GetTxPool().Sync()) + pending, queued = legacyPool.ContentFrom(accounts[0].address) + require.Len(t, pending, 1) + require.Len(t, queued, 1) + + // reap should still not return any new valid txs, since even though tx + // with nonce 2 was validated again (but not promoted), we have already + // returned it from reap + txs, err = mp.ReapNewValidTxs(0, 0) + require.NoError(t, err) + require.Len(t, txs, 0) + + // re submit tx 1 to the mempool to fill the nonce gap, since this is + // now a new valid txn, it should be returned by reap again + tx := createMsgEthereumTx(t, txConfig, accounts[0].key, 1, big.NewInt(1e8)) + err = mp.Insert(sdk.Context{}.WithContext(context.Background()), tx) + require.NoError(t, err, "failed to insert pending tx for account 0, nonce %d", 1) + + // sync the pool tx 1 and 2 should now be promoted to pending + require.NoError(t, mp.GetTxPool().Sync()) + pending, queued = legacyPool.ContentFrom(accounts[0].address) + require.Len(t, pending, 3) + require.Len(t, queued, 0) + + // finally ensure reap still is not returning these txs since they have + // already been reaped, even though they were newly validated + txs, err = mp.ReapNewValidTxs(0, 0) + require.NoError(t, err) + require.Len(t, txs, 1) + require.Equal(t, uint64(1), getTxNonce(t, txConfig, txs[0])) +} + +func TestMempool_QueueInvalidWhenUsingPendingState(t *testing.T) { + mp, s := setupMempoolWithAccounts(t, 3) + txConfig, rechecker, bus, accounts := s.txConfig, s.evmRechecker, s.eventBus, s.accounts + err := bus.PublishEventNewBlockHeader(cmttypes.EventDataNewBlockHeader{ + Header: cmttypes.Header{ + Height: 1, + Time: time.Now(), + ChainID: strconv.Itoa(constants.EighteenDecimalsChainID), + }, + }) + require.NoError(t, err) + + // for a reset to happen for block 1 and wait for it + require.NoError(t, mp.GetTxPool().Sync()) + + legacyPool := mp.GetTxPool().Subpools[0].(*legacypool.LegacyPool) + rechecker.SetEVMRecheck(func(ctx sdk.Context, tx *types.Transaction) (sdk.Context, error) { + return sdk.Context{}, nil + }) + + // insert a tx that will make it into the pending pool and use up the + // accounts entire balance + account := accounts[0] + gasPrice := (account.initialBalance - txValue) / txGasLimit // assuming they divide evenly + pendingTx := createMsgEthereumTx(t, txConfig, accounts[0].key, 0, new(big.Int).SetUint64(gasPrice)) + require.NoError(t, mp.Insert(sdk.Context{}.WithContext(context.Background()), pendingTx)) + require.NoError(t, mp.GetTxPool().Sync()) + + pending, queued := legacyPool.ContentFrom(account.address) + require.Len(t, pending, 1) + require.Len(t, queued, 0) + + // we should write if we are not resetting from promote + // promoate should write if it is being called out side of the context of a + // new block (reset) but if it is in the context of a new blcok and we know + // we are about to run demote executables again on it, then we should not + // write + + // insert a tx that will be placed in queued due to a nonce gap. the above + // tx is using the entire balance though so this tx is not technically + // valid taking into account the contents of the pending pool. we need to + // ensure this tx does not make it into the pending pool, because it could + // then be selected for a proposal if a new block does not come in an cause + // it to be rechecked again and dropped. + + queuedTx := createMsgEthereumTx(t, txConfig, accounts[0].key, 2, new(big.Int).SetUint64(100)) + require.Error(t, mp.Insert(sdk.Context{}.WithContext(context.Background()), queuedTx)) + + pending, queued = legacyPool.ContentFrom(account.address) + require.Len(t, pending, 1) + var expectedNonce uint64 + require.Equal(t, expectedNonce, pending[0].Nonce()) + require.Len(t, queued, 0) +} + +func TestMempool_ReapPromoteDemoteReap(t *testing.T) { + mp, s := setupMempoolWithAccounts(t, 3) + txConfig, rechecker, bus, accounts := s.txConfig, s.evmRechecker, s.eventBus, s.accounts + err := bus.PublishEventNewBlockHeader(cmttypes.EventDataNewBlockHeader{ + Header: cmttypes.Header{ + Height: 1, + Time: time.Now(), + ChainID: strconv.Itoa(constants.EighteenDecimalsChainID), + }, + }) + require.NoError(t, err) + + // for a reset to happen for block 1 and wait for it + require.NoError(t, mp.GetTxPool().Sync()) + + // insert a single tx for an account at nonce 0 + tx := createMsgEthereumTx(t, txConfig, accounts[0].key, 0, big.NewInt(1e8)) + require.NoError(t, mp.Insert(sdk.Context{}.WithContext(context.Background()), tx)) + + // wait for another reset to make sure the pool processes the above + // txn into pending + require.NoError(t, mp.GetTxPool().Sync()) + require.Equal(t, 1, mp.CountTx()) + + // setup tx with nonce 0 to fail recheck. + legacyPool := mp.GetTxPool().Subpools[0].(*legacypool.LegacyPool) + rechecker.SetEVMRecheck(func(ctx sdk.Context, tx *types.Transaction) (sdk.Context, error) { + if tx.Nonce() == 0 { + return sdk.Context{}, errors.New("recheck failed on tx with nonce 0") + } + return sdk.Context{}, nil + }) + + // sync the pool to make sure the above happens + require.NoError(t, mp.GetTxPool().Sync()) + pending, queued := legacyPool.ContentFrom(accounts[0].address) + require.Len(t, pending, 0) + require.Len(t, queued, 0) + + // reap should now return no txs, since even though a new tx was + // validated since the last reap call, it was then invalidated and + // dropped before this reap call + txs, err := mp.ReapNewValidTxs(0, 0) + require.NoError(t, err) + require.Len(t, txs, 0) + + // recheck will pass for all txns again + rechecker.SetEVMRecheck(func(ctx sdk.Context, tx *types.Transaction) (sdk.Context, error) { + return sdk.Context{}, nil + }) + + // insert the same tx again and make sure the tx can still be returned + // from the next call to reap + tx = createMsgEthereumTx(t, txConfig, accounts[0].key, 0, big.NewInt(1e8)) + require.NoError(t, mp.Insert(sdk.Context{}.WithContext(context.Background()), tx)) + + // sync the pool to make sure its promoted to pending + require.NoError(t, mp.GetTxPool().Sync()) + pending, queued = legacyPool.ContentFrom(accounts[0].address) + require.Len(t, pending, 1) + require.Len(t, queued, 0) + + // reap should now return our tx again + txs, err = mp.ReapNewValidTxs(0, 0) + require.NoError(t, err) + require.Len(t, txs, 1) + require.Equal(t, uint64(0), getTxNonce(t, txConfig, txs[0])) +} + +func TestMempool_ReapNewBlock(t *testing.T) { + mp, s := setupMempoolWithAccounts(t, 3) + vmKeeper, txConfig, bus, accounts := s.vmKeeper, s.txConfig, s.eventBus, s.accounts + err := bus.PublishEventNewBlockHeader(cmttypes.EventDataNewBlockHeader{ + Header: cmttypes.Header{ + Height: 1, + Time: time.Now(), + ChainID: strconv.Itoa(constants.EighteenDecimalsChainID), + }, + }) + require.NoError(t, err) + + // for a reset to happen for block 1 and wait for it + require.NoError(t, mp.GetTxPool().Sync()) + + tx0 := createMsgEthereumTx(t, txConfig, accounts[0].key, 0, big.NewInt(1e8)) + require.NoError(t, mp.Insert(sdk.Context{}.WithContext(context.Background()), tx0)) + tx1 := createMsgEthereumTx(t, txConfig, accounts[0].key, 1, big.NewInt(1e8)) + require.NoError(t, mp.Insert(sdk.Context{}.WithContext(context.Background()), tx1)) + tx2 := createMsgEthereumTx(t, txConfig, accounts[0].key, 2, big.NewInt(1e8)) + require.NoError(t, mp.Insert(sdk.Context{}.WithContext(context.Background()), tx2)) + + // wait for another reset to make sure the pool processes the above + // txns into pending + require.NoError(t, mp.GetTxPool().Sync()) + legacyPool := mp.GetTxPool().Subpools[0].(*legacypool.LegacyPool) + require.Eventually(t, func() bool { + pending, queued := legacyPool.ContentFrom(accounts[0].address) + return len(pending) == 3 && len(queued) == 0 && mp.CountTx() == 3 + }, time.Second, 10*time.Millisecond) + + // simulate comet calling removeTx with RunTxFinalize for tx0 (the included + // tx), a new height being published, and our account's nonce incrementing + // to 1. On the next reset, ScheduleForRemoval drives tx0 out of the pool. + require.NoError(t, mp.RemoveWithReason(context.Background(), tx0, mempooltypes.RemoveReason{ + Caller: mempooltypes.CallerRunTxFinalize, + })) + vmKeeper.On("GetAccount", mock.Anything, accounts[0].address).Unset() + vmKeeper.On("GetAccount", mock.Anything, accounts[0].address).Return(&statedb.Account{ + Nonce: 1, + Balance: uint256.NewInt(1e18), + }) + err = bus.PublishEventNewBlockHeader(cmttypes.EventDataNewBlockHeader{ + Header: cmttypes.Header{ + Height: 2, + Time: time.Now(), + ChainID: strconv.Itoa(constants.EighteenDecimalsChainID), + }, + }) + require.NoError(t, err) + + // sync the pool to make sure the above happens, tx0 should be dropped + // from the pool and the reap list + require.NoError(t, mp.GetTxPool().Sync()) + require.Eventually(t, func() bool { + pending, queued := legacyPool.ContentFrom(accounts[0].address) + return len(pending) == 2 && len(queued) == 0 + }, time.Second, 10*time.Millisecond) + pending, queued := legacyPool.ContentFrom(accounts[0].address) + require.Len(t, pending, 2) + require.Len(t, queued, 0) + + // reap should return txs 1 and 2 + txs, err := mp.ReapNewValidTxs(0, 0) + require.NoError(t, err) + require.Len(t, txs, 2) + require.GreaterOrEqual(t, getTxNonce(t, txConfig, txs[0]), uint64(1)) // 1 or 2 + require.GreaterOrEqual(t, getTxNonce(t, txConfig, txs[1]), uint64(1)) // 1 or 2 +} + +func TestMempool_CosmosNonceAdvanceDropsStaleEVM(t *testing.T) { + mp, s := setupMempoolWithAccounts(t, 1) + txConfig, bus, accounts := s.txConfig, s.eventBus, s.accounts + account := accounts[0] + + require.NoError(t, bus.PublishEventNewBlockHeader(cmttypes.EventDataNewBlockHeader{ + Header: cmttypes.Header{ + Height: 1, + Time: time.Now(), + ChainID: strconv.Itoa(constants.EighteenDecimalsChainID), + }, + })) + require.NoError(t, mp.GetTxPool().Sync()) + + // seed the pool with two pending EVM txs at nonces 0 and 1 + for nonce := uint64(0); nonce < 2; nonce++ { + tx := createMsgEthereumTx(t, txConfig, account.key, nonce, big.NewInt(1e8)) + require.NoError(t, mp.Insert(context.Background(), tx)) + } + require.NoError(t, mp.GetTxPool().Sync()) + + // ensure initial state is correct + legacyPool := mp.GetTxPool().Subpools[0].(*legacypool.LegacyPool) + pending, queued := legacyPool.ContentFrom(account.address) + require.Equal(t, 2, len(pending), "expected 2 txs in the pending pool after setup") + require.Equal(t, 0, len(queued), "expected 0 txs in the queued pool after setup") + + // mock that another val had a cosmos tx with nonce 1 and included that on + // chain (note that this will never be our node doing this, since the + // reserver prevents us from having an evm tx and cosmos tx with the same + // signer(s) in the both pools at the same time) + cosmosTx := createTestCosmosTx(t, txConfig, account.key, 1) + err := mp.RemoveWithReason(context.Background(), cosmosTx, mempooltypes.RemoveReason{ + Caller: mempooltypes.CallerRunTxFinalize, + }) + require.NoError(t, err) + + // after we finish finalizing the above block, the chain will advance and + // the pool will reset + require.NoError(t, bus.PublishEventNewBlockHeader(cmttypes.EventDataNewBlockHeader{ + Header: cmttypes.Header{ + Height: 2, + Time: time.Now(), + ChainID: strconv.Itoa(constants.EighteenDecimalsChainID), + }, + })) + require.NoError(t, mp.GetTxPool().Sync()) + + // using eventually here since publishing a new block happens async + require.Eventually(t, func() bool { + pending, queued := legacyPool.ContentFrom(account.address) + return len(pending) == 0 && len(queued) == 0 + }, time.Second, 10*time.Millisecond, "expected pending and queued pools to drain after stale txs dropped") +} + +func TestMempool_InsertRejectsUnderpricedEVMTx(t *testing.T) { + mp, s := setupMempoolWithAccounts(t, 1) + txConfig, accounts := s.txConfig, s.accounts + + // Base fee is mocked at 1e8 (see setupMempool). 1e7 is below it. + underpriced := createMsgEthereumTx(t, txConfig, accounts[0].key, 0, big.NewInt(1e7)) + err := mp.Insert(context.Background(), underpriced) + require.Error(t, err) + require.Contains(t, err.Error(), "insufficient fee") + + // A tx priced at the base fee is accepted. + priced := createMsgEthereumTx(t, txConfig, accounts[0].key, 0, big.NewInt(1e8)) + require.NoError(t, mp.Insert(context.Background(), priced)) +} + +func TestMempool_InsertMultiMsgCosmosTx(t *testing.T) { + mp, s := setupMempoolWithAccounts(t, 3) + txConfig, bus := s.txConfig, s.eventBus + + err := bus.PublishEventNewBlockHeader(cmttypes.EventDataNewBlockHeader{ + Header: cmttypes.Header{ + Height: 1, + Time: time.Now(), + ChainID: strconv.Itoa(constants.EighteenDecimalsChainID), + }, + }) + require.NoError(t, err) + + // create a multimsg cosmos tx + txBuilder := txConfig.NewTxBuilder() + + fromAddr := sdk.AccAddress([]byte("from")) + toAddr1 := sdk.AccAddress([]byte("addr1")) + toAddr2 := sdk.AccAddress([]byte("addr2")) + + msg1 := banktypes.NewMsgSend( + fromAddr, + toAddr1, + sdk.NewCoins(sdk.NewInt64Coin("stake", 1000)), + ) + msg2 := banktypes.NewMsgSend( + fromAddr, + toAddr2, + sdk.NewCoins(sdk.NewInt64Coin("stake", 2000)), + ) + err = txBuilder.SetMsgs(msg1, msg2) + require.NoError(t, err) + + err = txBuilder.SetSignatures(signingtypes.SignatureV2{ + PubKey: secp256k1.GenPrivKey().PubKey(), + Data: &signingtypes.SingleSignatureData{ + SignMode: signingtypes.SignMode_SIGN_MODE_DIRECT, + Signature: []byte("signature"), + }, + Sequence: 0, + }) + require.NoError(t, err) + + multiMsgTx := txBuilder.GetTx() + + require.Len(t, multiMsgTx.GetMsgs(), 2, "transaction should have 2 messages") + + // create a context for the insert operation (must have a multistore on it + // for ante handler execution, so we have to use the more complicated + // setup) + storeKey := storetypes.NewKVStoreKey("test") + transientKey := storetypes.NewTransientStoreKey("transient_test") + ctx := testutil.DefaultContext(storeKey, transientKey) + + require.NoError(t, mp.Insert(ctx, multiMsgTx)) + require.Equal(t, 1, mp.CountTx(), "expected a single tx to be in the mempool") + + txs, err := mp.ReapNewValidTxs(0, 0) + require.NoError(t, err) + require.Len(t, txs, 1, "expected a single tx to be reaped") +} + +func TestMempool_InsertSynchronous(t *testing.T) { + mp, s := setupMempoolWithAccounts(t, 3) + txConfig, bus, accounts := s.txConfig, s.eventBus, s.accounts + err := bus.PublishEventNewBlockHeader(cmttypes.EventDataNewBlockHeader{ + Header: cmttypes.Header{ + Height: 1, + Time: time.Now(), + ChainID: strconv.Itoa(constants.EighteenDecimalsChainID), + }, + }) + require.NoError(t, err) + + // Wait for reset to happen for block 1 + require.NoError(t, mp.GetTxPool().Sync()) + + legacyPool := mp.GetTxPool().Subpools[0].(*legacypool.LegacyPool) + + // Insert a transaction using the synchronous Insert method + // This should wait for the transaction to be added to the pool before returning + tx := createMsgEthereumTx(t, txConfig, accounts[0].key, 0, big.NewInt(1e8)) + err = mp.Insert(sdk.Context{}.WithContext(context.Background()), tx) + require.NoError(t, err) + + // After Insert returns, the transaction should already be in the pool + // (either pending or queued). We don't need to call Sync() to wait. + pending, queued := legacyPool.ContentFrom(accounts[0].address) + totalTxs := len(pending) + len(queued) + require.Equal(t, 1, totalTxs, "transaction should be in pool immediately after Insert returns") + + // Create a transaction with a gas price that would exceed the account balance + // Account balance is 100000000000100, so set gas price extremely high + excessiveGasPrice := new(big.Int).SetUint64(accounts[0].initialBalance * 100) + tx = createMsgEthereumTx(t, txConfig, accounts[0].key, 0, excessiveGasPrice) + err = mp.Insert(sdk.Context{}.WithContext(context.Background()), tx) + + // The synchronous Insert should return the error from the tx pool + require.Error(t, err, "Insert should return error when tx pool rejects transaction") + require.Contains(t, err.Error(), "insufficient funds", "error should indicate insufficient funds") +} + +func TestMempool_InsertMultiMsgEthereumTx(t *testing.T) { + mp, s := setupMempoolWithAccounts(t, 3) + txConfig, bus := s.txConfig, s.eventBus + + err := bus.PublishEventNewBlockHeader(cmttypes.EventDataNewBlockHeader{ + Header: cmttypes.Header{ + Height: 1, + Time: time.Now(), + ChainID: strconv.Itoa(constants.EighteenDecimalsChainID), + }, + }) + require.NoError(t, err) + + txBuilder := txConfig.NewTxBuilder() + + msg1 := banktypes.NewMsgSend( + sdk.AccAddress([]byte("from")), + sdk.AccAddress([]byte("addr")), + sdk.NewCoins(sdk.NewInt64Coin("stake", 2000)), + ) + msg2 := &vmtypes.MsgEthereumTx{} + err = txBuilder.SetMsgs(msg1, msg2) + require.NoError(t, err) + + err = txBuilder.SetSignatures(signingtypes.SignatureV2{ + PubKey: secp256k1.GenPrivKey().PubKey(), + Data: &signingtypes.SingleSignatureData{ + SignMode: signingtypes.SignMode_SIGN_MODE_DIRECT, + Signature: []byte("signature"), + }, + Sequence: 0, + }) + require.NoError(t, err) + + multiMsgTx := txBuilder.GetTx() + require.Len(t, multiMsgTx.GetMsgs(), 2, "transaction should have 2 messages") + + storeKey := storetypes.NewKVStoreKey("test") + transientKey := storetypes.NewTransientStoreKey("transient_test") + ctx := testutil.DefaultContext(storeKey, transientKey) + + err = mp.Insert(ctx, multiMsgTx) + require.ErrorIs(t, err, mempool.ErrMultiMsgEthereumTransaction) + require.Equal(t, 0, mp.CountTx(), "expected no txs to be in the mempool") + + txs, err := mp.ReapNewValidTxs(0, 0) + require.NoError(t, err) + require.Len(t, txs, 0, "expected no txs to be reaped") +} + +// Helper types and functions + +const ( + txValue = 100 + txGasLimit = 50000 +) + +type testAccount struct { + key *ecdsa.PrivateKey + address common.Address + nonce uint64 + initialBalance uint64 +} + +type testMempoolDependencies struct { + vmKeeper *mocks.VMKeeperI + txConfig client.TxConfig + evmRechecker *MockRechecker + cosmosRechecker *MockRechecker + eventBus *cmttypes.EventBus + accounts []testAccount +} + +// AdvanceNonce updates the mock vmKeeper to return newNonce for GetNonce(addr) +// and a matching Account from GetAccount. Used to simulate chain-state advance +// between blocks so legacypool's reactive reset path can observe the change. +// +// Assumes prior GetNonce/GetAccount expectations were registered with a +// concrete common.Address argument (as setupMempool does). Expectations +// registered with mock.Anything or other non-Address matchers would not match +// the type assertion below and would survive — leaving stale entries that race +// with the new ones. +func (s *testMempoolDependencies) AdvanceNonce(t *testing.T, addr common.Address, newNonce uint64) { + t.Helper() + var toUnset []*mock.Call + for _, c := range s.vmKeeper.ExpectedCalls { + switch c.Method { + case "GetNonce": + if len(c.Arguments) >= 1 { + if a, ok := c.Arguments[0].(common.Address); ok && a == addr { + toUnset = append(toUnset, c) + } + } + case "GetAccount": + if len(c.Arguments) >= 2 { + if a, ok := c.Arguments[1].(common.Address); ok && a == addr { + toUnset = append(toUnset, c) + } + } + } + } + for _, c := range toUnset { + c.Unset() // acquires the mock's internal mutex + } + s.vmKeeper.On("GetNonce", addr).Return(newNonce).Maybe() + s.vmKeeper.On("GetAccount", mock.Anything, addr).Return(&statedb.Account{ + Nonce: newNonce, + Balance: uint256.NewInt(1e18), + }).Maybe() +} + +// InstallNonceCheckingRechecker wires the EVM rechecker to reject txs whose +// nonce is below the mock's GetAccount(sender).Nonce. Simulates the ante +// handler's sequence check during reset's demoteUnexecutables. +func (s *testMempoolDependencies) InstallNonceCheckingRechecker(t *testing.T) { + t.Helper() + signer := types.LatestSignerForChainID(big.NewInt(int64(constants.EighteenDecimalsChainID))) + s.evmRechecker.SetEVMRecheck(func(ctx sdk.Context, tx *types.Transaction) (sdk.Context, error) { + from, err := types.Sender(signer, tx) + if err != nil { + return ctx, nil + } + acc := s.vmKeeper.GetAccount(sdk.Context{}, from) + if acc == nil { + return ctx, nil + } + if tx.Nonce() < acc.Nonce { + return sdk.Context{}, fmt.Errorf("stale tx: nonce %d < chain %d", tx.Nonce(), acc.Nonce) + } + return ctx, nil + }) +} + +func setupMempoolWithAccounts(t *testing.T, numAccounts int) (*mempool.Mempool, testMempoolDependencies) { + t.Helper() + + return setupMempool(t, numAccounts, 1000) +} + +//nolint:unparam +func setupMempool(t *testing.T, numAccounts, insertQueueSize int) (*mempool.Mempool, testMempoolDependencies) { + t.Helper() + + // Create accounts + accounts := make([]testAccount, numAccounts) + for i := range numAccounts { + key, err := crypto.GenerateKey() + require.NoError(t, err) + accounts[i] = testAccount{ + key: key, + address: crypto.PubkeyToAddress(key.PublicKey), + nonce: 0, + initialBalance: 100000000000100, + } + } + + // Setup EVM chain config + vmtypes.NewEVMConfigurator().ResetTestConfig() + ethCfg := vmtypes.DefaultChainConfig(constants.EighteenDecimalsChainID) + require.NoError(t, vmtypes.SetChainConfig(ethCfg)) + + err := vmtypes.NewEVMConfigurator(). + WithEVMCoinInfo(constants.ChainsCoinInfo[constants.EighteenDecimalsChainID]). + Configure() + require.NoError(t, err) + + // Create mocks + mockVMKeeper := mocks.NewVMKeeperI(t) + mockFeeMarketKeeper := mocks.NewFeeMarketKeeper(t) + + // Setup mock expectations + // Base fee is set to 1e8 so the 1e8-priced txs used throughout these tests clear the insert-time fee gate. + mockVMKeeper.On("GetBaseFee", mock.Anything).Return(big.NewInt(1e8)).Maybe() + mockVMKeeper.On("GetParams", mock.Anything).Return(vmtypes.DefaultParams()).Maybe() + mockFeeMarketKeeper.On("GetBlockGasWanted", mock.Anything).Return(uint64(10000000)).Maybe() + mockVMKeeper.On("GetEvmCoinInfo", mock.Anything).Return(constants.ChainsCoinInfo[constants.EighteenDecimalsChainID]).Maybe() + + // Setup account mocks for all test accounts + for _, acc := range accounts { + mockVMKeeper.On("GetAccount", mock.Anything, acc.address).Return(&statedb.Account{ + Nonce: acc.nonce, + Balance: uint256.NewInt(acc.initialBalance), + }).Maybe() + mockVMKeeper.On("GetNonce", acc.address).Return(acc.nonce).Maybe() + mockVMKeeper.On("GetBalance", acc.address).Return(uint256.NewInt(1e18)).Maybe() // 1 ETH + mockVMKeeper.On("GetCodeHash", acc.address).Return(common.Hash{}).Maybe() + } + + mockVMKeeper.On("GetState", mock.Anything, mock.Anything).Return(common.Hash{}).Maybe() + mockVMKeeper.On("GetCode", mock.Anything, mock.Anything).Return([]byte{}).Maybe() + mockVMKeeper.On("ForEachStorage", mock.Anything, mock.Anything, mock.Anything).Maybe() + mockVMKeeper.On("KVStoreKeys").Return(make(map[string]*storetypes.KVStoreKey)).Maybe() + + mockVMKeeper.On("SetEvmMempool", mock.Anything).Maybe() + + // Track latest height for the context callback (height=0 means "latest") + var latestHeight int64 = 1 + + // Create context callback + getCtxCallback := func(height int64, prove bool) (sdk.Context, error) { + storeKey := storetypes.NewKVStoreKey("test") + transientKey := storetypes.NewTransientStoreKey("transient_test") + ctx := testutil.DefaultContext(storeKey, transientKey) + // height=0 means "latest" (matches SDK's CreateQueryContext behavior) + if height == 0 { + height = latestHeight + } + return ctx. + WithBlockTime(time.Now()). + WithBlockHeader(cmtproto.Header{AppHash: []byte("00000000000000000000000000000000")}). + WithBlockHeight(height). + WithChainID(strconv.Itoa(constants.EighteenDecimalsChainID)), nil + } + + // Create TxConfig using proper encoding config with address codec + encodingConfig := encoding.MakeConfig(constants.EighteenDecimalsChainID) + // Register vm types so MsgEthereumTx can be decoded + vmtypes.RegisterInterfaces(encodingConfig.InterfaceRegistry) + // Register bank types so cosmos MsgSend txs can be decoded + banktypes.RegisterInterfaces(encodingConfig.InterfaceRegistry) + txConfig := encodingConfig.TxConfig + + // Create client context + clientCtx := client.Context{}. + WithCodec(encodingConfig.Codec). + WithInterfaceRegistry(encodingConfig.InterfaceRegistry). + WithTxConfig(txConfig) + + // Create mempool config + legacyConfig := legacypool.DefaultConfig + legacyConfig.Journal = "" // Disable journal for tests + legacyConfig.PriceLimit = 1 + legacyConfig.PriceBump = 10 // 10% price bump for replacement + + config := &mempool.Config{ + LegacyPoolConfig: &legacyConfig, + BlockGasLimit: 30000000, + MinTip: uint256.NewInt(0), + InsertQueueSize: insertQueueSize, + } + + // Create mempool + evmRechecker := &MockRechecker{} + cosmosRechecker := &MockRechecker{} + mp := mempool.NewMempool( + getCtxCallback, + log.NewNopLogger(), + mockVMKeeper, + mockFeeMarketKeeper, + txConfig, + evmRechecker, + cosmosRechecker, + config, + 1000, // cosmos pool max tx + ) + require.NotNil(t, mp) + + mp.SetClientCtx(clientCtx) + + eventBus := cmttypes.NewEventBus() + require.NoError(t, eventBus.Start()) + mp.SetEventBus(eventBus) + + return mp, testMempoolDependencies{ + vmKeeper: mockVMKeeper, + txConfig: txConfig, + evmRechecker: evmRechecker, + cosmosRechecker: cosmosRechecker, + eventBus: eventBus, + accounts: accounts, + } +} + +func createMsgEthereumTx( + t *testing.T, + txConfig client.TxConfig, + key *ecdsa.PrivateKey, + nonce uint64, + gasPrice *big.Int, +) sdk.Tx { + t.Helper() + + to := common.Address{0x01} // dummy recipient + chainID := new(big.Int).SetUint64(vmtypes.GetChainConfig().ChainId) + msg := vmtypes.NewTx(&vmtypes.EvmTxArgs{ + ChainID: chainID, + Nonce: nonce, + To: &to, + Amount: big.NewInt(txValue), + GasLimit: txGasLimit, + GasPrice: gasPrice, + }) + msg.From = crypto.PubkeyToAddress(key.PublicKey).Bytes() + + priv := ðsecp256k1.PrivKey{Key: crypto.FromECDSA(key)} + cosmosTx, err := evmtestutiltx.PrepareEthTx(txConfig, priv, msg) + require.NoError(t, err) + return cosmosTx +} + +// createMsgEthereum7702Tx builds a cosmos-wrapped MsgEthereumTx of type-04 +// (EIP-7702 SetCode) signed by senderKey with the supplied authorization +// list. Each `auths` entry is signed by its `key` field with the embedded +// nonce. Returns the cosmos-signed sdk.Tx and the underlying ethereum tx +// for assertion convenience. +func createMsgEthereum7702Tx( + t *testing.T, + txConfig client.TxConfig, + senderKey *ecdsa.PrivateKey, + auths []types.SetCodeAuthorization, +) sdk.Tx { + t.Helper() + + chainID := vmtypes.GetEthChainConfig().ChainID + to := common.Address{0x55} + signedTx := types.MustSignNewTx(senderKey, types.LatestSignerForChainID(chainID), &types.SetCodeTx{ + ChainID: uint256.MustFromBig(chainID), + Nonce: 0, + GasTipCap: uint256.NewInt(1), + GasFeeCap: uint256.NewInt(1e9), + Gas: 250000, + To: to, + Value: uint256.NewInt(0), + AuthList: auths, + }) + + msg := &vmtypes.MsgEthereumTx{ + Raw: vmtypes.EthereumTx{Transaction: signedTx}, + From: crypto.PubkeyToAddress(senderKey.PublicKey).Bytes(), + } + + // priv=nil → PrepareEthTx skips re-signing (we already have a signed eth + // tx) and just wraps the message into a cosmos tx with the EVM extension + // option. + cosmosTx, err := evmtestutiltx.PrepareEthTx(txConfig, nil, msg) + require.NoError(t, err) + return cosmosTx +} + +// signSetCodeAuth is a small wrapper around types.SignSetCode for tests. +func signSetCodeAuth(t *testing.T, key *ecdsa.PrivateKey, nonce uint64) types.SetCodeAuthorization { + t.Helper() + chainID := vmtypes.GetEthChainConfig().ChainID + auth, err := types.SignSetCode(key, types.SetCodeAuthorization{ + ChainID: *uint256.MustFromBig(chainID), + Address: common.Address{0x42}, + Nonce: nonce, + }) + require.NoError(t, err) + return auth +} + +// TestStaleNonceHandling covers pool behavior on chain advance across +// scenarios where the eager mechanism can't or doesn't catch the new +// nonce. Cases assert reactive eviction via demoteUnexecutables → +// RecheckEVM, or queued-tx promotion when a 7702 authority bump closes +// a nonce gap. +func TestStaleNonceHandling(t *testing.T) { + type expect struct { + pending int + queued int + } + type scenario struct { + name string + numAccounts int + targetIdx int // account whose pool we observe + seedNonces []uint64 // pending seeds (sequential, no gaps) + seedQueuedNonces []uint64 // queued seeds (gapped from chain nonce) + finalize7702 func(t *testing.T, mp *mempool.Mempool, txConfig client.TxConfig, accs []testAccount) + advanceTo uint64 // chain nonce to set for accounts[targetIdx] + wantAfterReset expect // expected counts after the reset + // Eager-cache state for accounts[targetIdx] AFTER the test: + // expectsEager=false when no SetLatestNonce was triggered for the target; + // expectsEager=true with eagerNonce set when the eager path fired. + expectsEager bool + eagerNonce uint64 + } + + cases := []scenario{ + { + name: "stale-sender-no-7702", + numAccounts: 1, + targetIdx: 0, + seedNonces: []uint64{0}, + advanceTo: 1, + wantAfterReset: expect{pending: 0, queued: 0}, + // no RemoveWithReason call → eager cache untouched. + expectsEager: false, + }, + { + name: "authority-after-cross-account-7702", + numAccounts: 2, + targetIdx: 1, + seedNonces: []uint64{0}, + finalize7702: func(t *testing.T, mp *mempool.Mempool, txConfig client.TxConfig, accs []testAccount) { + t.Helper() + auths := []types.SetCodeAuthorization{signSetCodeAuth(t, accs[1].key, 1)} + cosmosTx := createMsgEthereum7702Tx(t, txConfig, accs[0].key, auths) + require.NoError(t, mp.RemoveWithReason(context.Background(), cosmosTx, mempooltypes.RemoveReason{ + Caller: mempooltypes.CallerRunTxFinalize, + })) + }, + advanceTo: 1, + wantAfterReset: expect{pending: 0, queued: 0}, + // Eager fires for sender (idx 0); authority (idx 1, the target) is invisible. + expectsEager: false, + }, + { + name: "sender-+1-gap-after-self-sponsored-7702", + numAccounts: 1, + targetIdx: 0, + seedNonces: []uint64{0, 1}, + finalize7702: func(t *testing.T, mp *mempool.Mempool, txConfig client.TxConfig, accs []testAccount) { + t.Helper() + auths := []types.SetCodeAuthorization{signSetCodeAuth(t, accs[0].key, 1)} + cosmosTx := createMsgEthereum7702Tx(t, txConfig, accs[0].key, auths) + require.NoError(t, mp.RemoveWithReason(context.Background(), cosmosTx, mempooltypes.RemoveReason{ + Caller: mempooltypes.CallerRunTxFinalize, + })) + }, + advanceTo: 2, + wantAfterReset: expect{pending: 0, queued: 0}, + // Eager fires for sender (== target) at tx.Nonce()=0; the +1 bump is reactive. + expectsEager: true, + eagerNonce: 0, + }, + { + // Queued tx whose nonce gap is closed by a self-sponsored 7702. + // Sender +1 plus 4 self-auth bumps brings chain nonce 0 -> 5, + // matching tx5's nonce. With nothing else in pending, the + // noncer falls through to statedb on reset and tx5 promotes. + name: "queued-promotes-after-self-sponsored-7702", + numAccounts: 1, + targetIdx: 0, + seedNonces: nil, + seedQueuedNonces: []uint64{5}, + finalize7702: func(t *testing.T, mp *mempool.Mempool, txConfig client.TxConfig, accs []testAccount) { + t.Helper() + auths := []types.SetCodeAuthorization{ + signSetCodeAuth(t, accs[0].key, 1), + signSetCodeAuth(t, accs[0].key, 2), + signSetCodeAuth(t, accs[0].key, 3), + signSetCodeAuth(t, accs[0].key, 4), + } + cosmosTx := createMsgEthereum7702Tx(t, txConfig, accs[0].key, auths) + require.NoError(t, mp.RemoveWithReason(context.Background(), cosmosTx, mempooltypes.RemoveReason{ + Caller: mempooltypes.CallerRunTxFinalize, + })) + }, + advanceTo: 5, + wantAfterReset: expect{pending: 1, queued: 0}, + expectsEager: true, + eagerNonce: 0, + }, + { + // Cross-account: acc0 sends 7702 authorizing acc1; the auth + // bump closes acc1's queued tx gap. Extractor only sees acc0 + // (sender), so acc1's eager LRU is never touched. tx1 promotes + // on first reset via the statedb fallback. + name: "queued-promotes-after-cross-account-7702", + numAccounts: 2, + targetIdx: 1, + seedNonces: nil, + seedQueuedNonces: []uint64{1}, + finalize7702: func(t *testing.T, mp *mempool.Mempool, txConfig client.TxConfig, accs []testAccount) { + t.Helper() + auths := []types.SetCodeAuthorization{signSetCodeAuth(t, accs[1].key, 0)} + cosmosTx := createMsgEthereum7702Tx(t, txConfig, accs[0].key, auths) + require.NoError(t, mp.RemoveWithReason(context.Background(), cosmosTx, mempooltypes.RemoveReason{ + Caller: mempooltypes.CallerRunTxFinalize, + })) + }, + advanceTo: 1, + wantAfterReset: expect{pending: 1, queued: 0}, + expectsEager: false, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + mp, s := setupMempoolWithAccounts(t, tc.numAccounts) + txConfig, bus, accounts := s.txConfig, s.eventBus, s.accounts + target := accounts[tc.targetIdx] + + require.NoError(t, bus.PublishEventNewBlockHeader(cmttypes.EventDataNewBlockHeader{ + Header: cmttypes.Header{Height: 1, Time: time.Now(), ChainID: strconv.Itoa(constants.EighteenDecimalsChainID)}, + })) + require.NoError(t, mp.GetTxPool().Sync()) + + for _, n := range tc.seedNonces { + tx := createMsgEthereumTx(t, txConfig, target.key, n, big.NewInt(1e8)) + require.NoError(t, mp.Insert(context.Background(), tx)) + } + for _, n := range tc.seedQueuedNonces { + tx := createMsgEthereumTx(t, txConfig, target.key, n, big.NewInt(1e8)) + require.NoError(t, mp.Insert(context.Background(), tx)) + } + require.NoError(t, mp.GetTxPool().Sync()) + + legacyPool := mp.GetTxPool().Subpools[0].(*legacypool.LegacyPool) + pending, queued := legacyPool.ContentFrom(target.address) + require.Len(t, pending, len(tc.seedNonces)) + require.Len(t, queued, len(tc.seedQueuedNonces)) + + if tc.finalize7702 != nil { + tc.finalize7702(t, mp, txConfig, accounts) + } + + s.InstallNonceCheckingRechecker(t) + s.AdvanceNonce(t, target.address, tc.advanceTo) + + require.NoError(t, bus.PublishEventNewBlockHeader(cmttypes.EventDataNewBlockHeader{ + Header: cmttypes.Header{Height: 2, Time: time.Now(), ChainID: strconv.Itoa(constants.EighteenDecimalsChainID)}, + })) + require.NoError(t, mp.GetTxPool().Sync()) + + require.Eventually(t, func() bool { + p, q := legacyPool.ContentFrom(target.address) + return len(p) == tc.wantAfterReset.pending && len(q) == tc.wantAfterReset.queued + }, time.Second, 10*time.Millisecond, "reset state mismatch") + + got, ok := legacyPool.LatestNonce(target.address) + if tc.expectsEager { + require.True(t, ok, "eager cache should have an entry for target") + require.Equal(t, tc.eagerNonce, got) + } else { + require.False(t, ok, "no eager signal expected; eviction proves reactive path") + } + }) + } +} + +// decodeTxBytes decodes transaction bytes returned from ReapNewValidTxs back into an Ethereum transaction +func decodeTxBytes(t *testing.T, txConfig client.TxConfig, txBytes []byte) *types.Transaction { + t.Helper() + + // Decode cosmos SDK tx + cosmosTx, err := txConfig.TxDecoder()(txBytes) + require.NoError(t, err, "failed to decode tx bytes") + + // Extract MsgEthereumTx + msgs := cosmosTx.GetMsgs() + require.Len(t, msgs, 1, "expected exactly one message in tx") + + ethMsg, ok := msgs[0].(*vmtypes.MsgEthereumTx) + require.True(t, ok, "expected message to be MsgEthereumTx") + + // Convert to Ethereum transaction + ethTx := ethMsg.AsTransaction() + require.NotNil(t, ethTx, "ethereum transaction should not be nil") + + return ethTx +} + +// getTxNonce extracts the nonce from transaction bytes +func getTxNonce(t *testing.T, txConfig client.TxConfig, txBytes []byte) uint64 { + t.Helper() + + ethTx := decodeTxBytes(t, txConfig, txBytes) + return ethTx.Nonce() +} + +type MockRechecker struct { + EVMRecheckFn func(ctx sdk.Context, tx *types.Transaction) (sdk.Context, error) + CosmosRecheckFn func(ctx sdk.Context, tx sdk.Tx) (sdk.Context, error) + ctx sdk.Context + lock sync.Mutex +} + +func (mr *MockRechecker) SetEVMRecheck(recheck func(ctx sdk.Context, tx *types.Transaction) (sdk.Context, error)) { + mr.lock.Lock() + defer mr.lock.Unlock() + + mr.EVMRecheckFn = recheck +} + +func (mr *MockRechecker) SetCosmosRecheck(recheck func(ctx sdk.Context, tx sdk.Tx) (sdk.Context, error)) { + mr.lock.Lock() + defer mr.lock.Unlock() + + mr.CosmosRecheckFn = recheck +} + +func (mr *MockRechecker) GetContext() (sdk.Context, func()) { + if mr.ctx.MultiStore() == nil { + return sdk.Context{}, func() {} + } + return mr.ctx.CacheContext() +} + +func (mr *MockRechecker) RecheckEVM(ctx sdk.Context, tx *types.Transaction) (sdk.Context, error) { + mr.lock.Lock() + defer mr.lock.Unlock() + + if mr.EVMRecheckFn != nil { + return mr.EVMRecheckFn(ctx, tx) + } + return sdk.Context{}, nil +} + +func (mr *MockRechecker) RecheckCosmos(ctx sdk.Context, tx sdk.Tx) (sdk.Context, error) { + mr.lock.Lock() + defer mr.lock.Unlock() + + if mr.CosmosRecheckFn != nil { + return mr.CosmosRecheckFn(ctx, tx) + } + return ctx, nil +} + +func (mr *MockRechecker) Update(ctx sdk.Context, _ *types.Header) { + mr.ctx = ctx +} + +// createTestCosmosTx creates a real Cosmos SDK transaction with the given signer +func createTestCosmosTx(t *testing.T, txConfig client.TxConfig, key *ecdsa.PrivateKey, sequence uint64) sdk.Tx { + t.Helper() + + pubKeyBytes := crypto.CompressPubkey(&key.PublicKey) + pubKey := ðsecp256k1.PubKey{Key: pubKeyBytes} + addr := pubKey.Address().Bytes() + addrStr := sdk.MustBech32ifyAddressBytes(constants.ExampleBech32Prefix, addr) + + // Create a simple bank send message + msg := &banktypes.MsgSend{ + FromAddress: addrStr, + ToAddress: addrStr, // send to self + Amount: sdk.NewCoins(sdk.NewInt64Coin("aevmos", 1000)), + } + + txBuilder := txConfig.NewTxBuilder() + err := txBuilder.SetMsgs(msg) + require.NoError(t, err) + + txBuilder.SetGasLimit(100000) + txBuilder.SetFeeAmount(sdk.NewCoins(sdk.NewInt64Coin("aevmos", 1000000))) + + // Set signature with pubkey (unsigned but has signer info) + sigData := &signingtypes.SingleSignatureData{ + SignMode: signingtypes.SignMode_SIGN_MODE_DIRECT, + Signature: nil, + } + sig := signingtypes.SignatureV2{ + PubKey: pubKey, + Data: sigData, + Sequence: sequence, + } + err = txBuilder.SetSignatures(sig) + require.NoError(t, err) + + return txBuilder.GetTx() +} + +// createTestMultiSignerCosmosTx creates a Cosmos SDK transaction with multiple signers. +// Each key produces one MsgSend from that signer. +func createTestMultiSignerCosmosTx(t *testing.T, txConfig client.TxConfig, keys ...*ecdsa.PrivateKey) sdk.Tx { + t.Helper() + require.NotEmpty(t, keys, "must provide at least one key") + + var msgs []sdk.Msg + var sigs []signingtypes.SignatureV2 + + for i, key := range keys { + pubKeyBytes := crypto.CompressPubkey(&key.PublicKey) + pubKey := ðsecp256k1.PubKey{Key: pubKeyBytes} + addr := pubKey.Address().Bytes() + addrStr := sdk.MustBech32ifyAddressBytes(constants.ExampleBech32Prefix, addr) + + // Each signer has their own MsgSend + msg := &banktypes.MsgSend{ + FromAddress: addrStr, + ToAddress: addrStr, // send to self + Amount: sdk.NewCoins(sdk.NewInt64Coin("aevmos", 1000)), + } + msgs = append(msgs, msg) + + // Create signature info for this signer + sigData := &signingtypes.SingleSignatureData{ + SignMode: signingtypes.SignMode_SIGN_MODE_DIRECT, + Signature: nil, + } + sig := signingtypes.SignatureV2{ + PubKey: pubKey, + Data: sigData, + Sequence: uint64(i), + } + sigs = append(sigs, sig) + } + + txBuilder := txConfig.NewTxBuilder() + err := txBuilder.SetMsgs(msgs...) + require.NoError(t, err) + + txBuilder.SetGasLimit(100000 * uint64(len(keys))) + txBuilder.SetFeeAmount(sdk.NewCoins(sdk.NewInt64Coin("aevmos", 1000000))) + + err = txBuilder.SetSignatures(sigs...) + require.NoError(t, err) + + return txBuilder.GetTx() +} diff --git a/mempool/mocks/FeeMarketKeeper.go b/mempool/mocks/FeeMarketKeeper.go index 99b90056..552364f1 100644 --- a/mempool/mocks/FeeMarketKeeper.go +++ b/mempool/mocks/FeeMarketKeeper.go @@ -35,7 +35,8 @@ func (_m *FeeMarketKeeper) GetBlockGasWanted(ctx types.Context) uint64 { func NewFeeMarketKeeper(t interface { mock.TestingT Cleanup(func()) -}) *FeeMarketKeeper { +}, +) *FeeMarketKeeper { mock := &FeeMarketKeeper{} mock.Mock.Test(t) diff --git a/mempool/mocks/VMKeeper.go b/mempool/mocks/VMKeeperI.go similarity index 66% rename from mempool/mocks/VMKeeper.go rename to mempool/mocks/VMKeeperI.go index 585af69d..835942a9 100644 --- a/mempool/mocks/VMKeeper.go +++ b/mempool/mocks/VMKeeperI.go @@ -1,31 +1,30 @@ -// Code generated by mockery v2.53.4. DO NOT EDIT. +// Code generated by mockery v2.53.5. DO NOT EDIT. package mocks import ( big "math/big" - mempool "github.com/cosmos/evm/mempool" common "github.com/ethereum/go-ethereum/common" mock "github.com/stretchr/testify/mock" statedb "github.com/cosmos/evm/x/vm/statedb" - storetypes "cosmossdk.io/store/types" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" types "github.com/cosmos/cosmos-sdk/types" vmtypes "github.com/cosmos/evm/x/vm/types" ) -// VMKeeper is an autogenerated mock type for the VMKeeper type -type VMKeeper struct { +// VMKeeperI is an autogenerated mock type for the VMKeeperI type +type VMKeeperI struct { mock.Mock } // DeleteAccount provides a mock function with given fields: ctx, addr -func (_m *VMKeeper) DeleteAccount(ctx types.Context, addr common.Address) error { +func (_m *VMKeeperI) DeleteAccount(ctx types.Context, addr common.Address) error { ret := _m.Called(ctx, addr) if len(ret) == 0 { @@ -43,22 +42,22 @@ func (_m *VMKeeper) DeleteAccount(ctx types.Context, addr common.Address) error } // DeleteCode provides a mock function with given fields: ctx, codeHash -func (_m *VMKeeper) DeleteCode(ctx types.Context, codeHash []byte) { +func (_m *VMKeeperI) DeleteCode(ctx types.Context, codeHash []byte) { _m.Called(ctx, codeHash) } // DeleteState provides a mock function with given fields: ctx, addr, key -func (_m *VMKeeper) DeleteState(ctx types.Context, addr common.Address, key common.Hash) { +func (_m *VMKeeperI) DeleteState(ctx types.Context, addr common.Address, key common.Hash) { _m.Called(ctx, addr, key) } // ForEachStorage provides a mock function with given fields: ctx, addr, cb -func (_m *VMKeeper) ForEachStorage(ctx types.Context, addr common.Address, cb func(common.Hash, common.Hash) bool) { +func (_m *VMKeeperI) ForEachStorage(ctx types.Context, addr common.Address, cb func(common.Hash, common.Hash) bool) { _m.Called(ctx, addr, cb) } // GetAccount provides a mock function with given fields: ctx, addr -func (_m *VMKeeper) GetAccount(ctx types.Context, addr common.Address) *statedb.Account { +func (_m *VMKeeperI) GetAccount(ctx types.Context, addr common.Address) *statedb.Account { ret := _m.Called(ctx, addr) if len(ret) == 0 { @@ -77,8 +76,26 @@ func (_m *VMKeeper) GetAccount(ctx types.Context, addr common.Address) *statedb. return r0 } +// IsBaseAccountOrEmpty provides a mock function with given fields: ctx, addr +func (_m *VMKeeperI) IsBaseAccountOrEmpty(ctx types.Context, addr common.Address) bool { + ret := _m.Called(ctx, addr) + + if len(ret) == 0 { + panic("no return value specified for IsBaseAccountOrEmpty") + } + + var r0 bool + if rf, ok := ret.Get(0).(func(types.Context, common.Address) bool); ok { + r0 = rf(ctx, addr) + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + // GetBaseFee provides a mock function with given fields: ctx -func (_m *VMKeeper) GetBaseFee(ctx types.Context) *big.Int { +func (_m *VMKeeperI) GetBaseFee(ctx types.Context) *big.Int { ret := _m.Called(ctx) if len(ret) == 0 { @@ -98,7 +115,7 @@ func (_m *VMKeeper) GetBaseFee(ctx types.Context) *big.Int { } // GetCode provides a mock function with given fields: ctx, codeHash -func (_m *VMKeeper) GetCode(ctx types.Context, codeHash common.Hash) []byte { +func (_m *VMKeeperI) GetCode(ctx types.Context, codeHash common.Hash) []byte { ret := _m.Called(ctx, codeHash) if len(ret) == 0 { @@ -118,7 +135,7 @@ func (_m *VMKeeper) GetCode(ctx types.Context, codeHash common.Hash) []byte { } // GetCodeHash provides a mock function with given fields: ctx, addr -func (_m *VMKeeper) GetCodeHash(ctx types.Context, addr common.Address) common.Hash { +func (_m *VMKeeperI) GetCodeHash(ctx types.Context, addr common.Address) common.Hash { ret := _m.Called(ctx, addr) if len(ret) == 0 { @@ -138,7 +155,7 @@ func (_m *VMKeeper) GetCodeHash(ctx types.Context, addr common.Address) common.H } // GetEvmCoinInfo provides a mock function with given fields: ctx -func (_m *VMKeeper) GetEvmCoinInfo(ctx types.Context) vmtypes.EvmCoinInfo { +func (_m *VMKeeperI) GetEvmCoinInfo(ctx types.Context) vmtypes.EvmCoinInfo { ret := _m.Called(ctx) if len(ret) == 0 { @@ -156,7 +173,7 @@ func (_m *VMKeeper) GetEvmCoinInfo(ctx types.Context) vmtypes.EvmCoinInfo { } // GetParams provides a mock function with given fields: ctx -func (_m *VMKeeper) GetParams(ctx types.Context) vmtypes.Params { +func (_m *VMKeeperI) GetParams(ctx types.Context) vmtypes.Params { ret := _m.Called(ctx) if len(ret) == 0 { @@ -174,7 +191,7 @@ func (_m *VMKeeper) GetParams(ctx types.Context) vmtypes.Params { } // GetState provides a mock function with given fields: ctx, addr, key -func (_m *VMKeeper) GetState(ctx types.Context, addr common.Address, key common.Hash) common.Hash { +func (_m *VMKeeperI) GetState(ctx types.Context, addr common.Address, key common.Hash) common.Hash { ret := _m.Called(ctx, addr, key) if len(ret) == 0 { @@ -194,19 +211,19 @@ func (_m *VMKeeper) GetState(ctx types.Context, addr common.Address, key common. } // KVStoreKeys provides a mock function with no fields -func (_m *VMKeeper) KVStoreKeys() map[string]*storetypes.KVStoreKey { +func (_m *VMKeeperI) KVStoreKeys() map[string]storetypes.StoreKey { ret := _m.Called() if len(ret) == 0 { panic("no return value specified for KVStoreKeys") } - var r0 map[string]*storetypes.KVStoreKey - if rf, ok := ret.Get(0).(func() map[string]*storetypes.KVStoreKey); ok { + var r0 map[string]storetypes.StoreKey + if rf, ok := ret.Get(0).(func() map[string]storetypes.StoreKey); ok { r0 = rf() } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(map[string]*storetypes.KVStoreKey) + r0 = ret.Get(0).(map[string]storetypes.StoreKey) } } @@ -214,7 +231,7 @@ func (_m *VMKeeper) KVStoreKeys() map[string]*storetypes.KVStoreKey { } // SetAccount provides a mock function with given fields: ctx, addr, account -func (_m *VMKeeper) SetAccount(ctx types.Context, addr common.Address, account statedb.Account) error { +func (_m *VMKeeperI) SetAccount(ctx types.Context, addr common.Address, account statedb.Account) error { ret := _m.Called(ctx, addr, account) if len(ret) == 0 { @@ -232,27 +249,23 @@ func (_m *VMKeeper) SetAccount(ctx types.Context, addr common.Address, account s } // SetCode provides a mock function with given fields: ctx, codeHash, code -func (_m *VMKeeper) SetCode(ctx types.Context, codeHash []byte, code []byte) { +func (_m *VMKeeperI) SetCode(ctx types.Context, codeHash []byte, code []byte) { _m.Called(ctx, codeHash, code) } -// SetEvmMempool provides a mock function with given fields: evmMempool -func (_m *VMKeeper) SetEvmMempool(evmMempool *mempool.ExperimentalEVMMempool) { - _m.Called(evmMempool) -} - // SetState provides a mock function with given fields: ctx, addr, key, value -func (_m *VMKeeper) SetState(ctx types.Context, addr common.Address, key common.Hash, value []byte) { +func (_m *VMKeeperI) SetState(ctx types.Context, addr common.Address, key common.Hash, value []byte) { _m.Called(ctx, addr, key, value) } -// NewVMKeeper creates a new instance of VMKeeper. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// NewVMKeeperI creates a new instance of VMKeeperI. 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 NewVMKeeper(t interface { +func NewVMKeeperI(t interface { mock.TestingT Cleanup(func()) -}) *VMKeeper { - mock := &VMKeeper{} +}, +) *VMKeeperI { + mock := &VMKeeperI{} mock.Mock.Test(t) t.Cleanup(func() { mock.AssertExpectations(t) }) diff --git a/mempool/recheck_pool.go b/mempool/recheck_pool.go new file mode 100644 index 00000000..5a38319a --- /dev/null +++ b/mempool/recheck_pool.go @@ -0,0 +1,657 @@ +package mempool + +import ( + "context" + "errors" + "fmt" + "math/big" + "sync" + "time" + + "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/holiman/uint256" + "go.opentelemetry.io/otel/metric" + + "github.com/cosmos/evm/mempool/internal/heightsync" + "github.com/cosmos/evm/mempool/internal/reaplist" + "github.com/cosmos/evm/mempool/reserver" + + "cosmossdk.io/log/v2" + "cosmossdk.io/math" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + sdkmempool "github.com/cosmos/cosmos-sdk/types/mempool" +) + +var ( + recheckDuration metric.Float64Histogram + recheckRemovals metric.Int64Histogram + recheckNumChecked metric.Int64Histogram +) + +func init() { + var err error + recheckDuration, err = meter.Float64Histogram( + "mempool.recheck.duration", + metric.WithDescription("Duration of cosmos mempool recheck loop"), + metric.WithUnit("ms"), + ) + if err != nil { + panic(err) + } + + recheckRemovals, err = meter.Int64Histogram( + "mempool.recheck.removals", + metric.WithDescription("Number of transactions that were removed from the pool per iteration"), + ) + if err != nil { + panic(err) + } + + recheckNumChecked, err = meter.Int64Histogram( + "mempool.recheck.num_checked", + metric.WithDescription("Number of transactions rechecked per iteration"), + ) + if err != nil { + panic(err) + } +} + +// Rechecker defines the minimal set of methods needed to recheck cosmos +// transactions and manage the context that the transactions are rechecked +// against. +type Rechecker interface { + // GetContext gets a branch of the current context that transactions should + // be rechecked against. Changes to ctx will only be persisted back to the + // Rechecker once the write function is invoked. + GetContext() (ctx sdk.Context, write func()) + + // RecheckCosmos performs validation of a cosmos tx against a context, and + // returns an updated context. + RecheckCosmos(ctx sdk.Context, tx sdk.Tx) (sdk.Context, error) + + // Update updates the recheckers context to be the ctx at headers height. + Update(ctx sdk.Context, header *ethtypes.Header) +} + +// RecheckMempool wraps an ExtMempool and provides block-driven rechecking +// of transactions when new blocks are committed. It mirrors the legacypool +// pattern but simplified for Cosmos mempool behavior (no reorgs, no queued/pending management). +// +// All pool mutations (Insert, Remove) and reads (Select, CountTx) are protected +// by a RWMutex to ensure thread-safety during recheck operations. +type RecheckMempool struct { + sdkmempool.ExtMempool + + // mu protects the pool during mutations and reads. + // Write lock: Insert, Remove, runRecheck + // Read lock: Select, CountTx + mu sync.RWMutex + + // reserver coordinates address reservations with other pools (i.e. legacypool) + reserver *reserver.ReservationHandle + + rechecker Rechecker + blockchain *Blockchain + signerExtractor sdkmempool.SignerExtractionAdapter + logger log.Logger + + // event channels + reqRecheckCh chan *recheckRequest // channel that schedules rechecking. + recheckDoneCh chan chan struct{} // channel that is returned to recheck callers that signals when a recheck is complete. + shutdownCh chan struct{} // shutdown channel to gracefully shutdown the recheck loop. + shutdownOnce sync.Once // ensures shutdown channel is only closed once. + recheckShutdown chan struct{} // closed when scheduleRecheckLoop exits + + // recheckedTxs is a height synced CosmosTxStore, used to collect txs that + // have been rechecked at a height, and discard of them once the chain. + recheckedTxs *heightsync.HeightSync[CosmosTxStore] + + reapList *reaplist.ReapList + + wg sync.WaitGroup +} + +// NewRecheckMempool creates a new RecheckMempool. +func NewRecheckMempool( + defaultCosmosPoolConfig *sdkmempool.PriorityNonceMempoolConfig[math.Int], + maxTxs int, + reserver *reserver.ReservationHandle, + rechecker Rechecker, + recheckedTxs *heightsync.HeightSync[CosmosTxStore], + reapList *reaplist.ReapList, + blockchain *Blockchain, + logger log.Logger, +) *RecheckMempool { + signerExtractor := sdkmempool.NewDefaultSignerExtractionAdapter() + cosmosMempoolConfig := cosmosPoolConfig( + blockchain, + defaultCosmosPoolConfig, + maxTxs, + onTransactionReplace(reapList, signerExtractor, reserver, logger), + ) + + return &RecheckMempool{ + ExtMempool: sdkmempool.NewPriorityMempool(cosmosMempoolConfig), + reserver: reserver, + rechecker: rechecker, + blockchain: blockchain, + signerExtractor: signerExtractor, + logger: logger.With(log.ModuleKey, "RecheckMempool"), + reqRecheckCh: make(chan *recheckRequest), + recheckDoneCh: make(chan chan struct{}), + shutdownCh: make(chan struct{}), + recheckShutdown: make(chan struct{}), + reapList: reapList, + recheckedTxs: recheckedTxs, + } +} + +// Start begins the background recheck loop and initializes the rechecker's +// context to the latest chain state. The initialHead is used for the first +// Rechecker.Update call before any recheck has been triggered. +func (m *RecheckMempool) Start(initialHead *ethtypes.Header) { + ctx, err := m.blockchain.GetLatestContext() + if err != nil { + m.logger.Error("failed to initialize rechecker context", "err", err) + } else { + m.rechecker.Update(ctx, initialHead) + } + + m.wg.Add(1) + go m.scheduleRecheckLoop() +} + +// Close gracefully shuts down the recheck loop. +func (m *RecheckMempool) Close() error { + m.shutdownOnce.Do(func() { + close(m.shutdownCh) + }) + m.wg.Wait() + return nil +} + +// Insert adds a transaction to the pool after running the ante handler. +// This is the main entry point for new cosmos transactions. +func (m *RecheckMempool) Insert(_ context.Context, tx sdk.Tx) (err error) { + // Reserve addresses to prevent conflicts with EVM pool + addrs, err := m.reserveTx(tx) + if err != nil { + return fmt.Errorf("acquiring reservations for tx: %w", err) + } + + defer func() { + if err == nil { + return + } + if errRelease := m.reserver.Release(addrs...); errRelease != nil { + m.logger.Error("Failed to release reservations (Insert)", "err", errRelease, "addrs", addrs) + } + }() + + m.mu.Lock() + defer m.mu.Unlock() + + // Branch from the Rechecker's internal ctx (post-recheck cache). + // This ctx has chain_state + all pending txs' nonce increments. + ctx, write := m.rechecker.GetContext() + if ctx.IsZero() { + m.logger.Warn("no context found in rechecker on insert, updating to latest") + // if this happens, we have not rechecked any txs yet, so this is safe + // to update + newCtx, err := m.blockchain.GetLatestContext() + if err != nil { + return fmt.Errorf("fetching latest context since rechecker has none: %w", err) + } + + m.rechecker.Update(newCtx, m.blockchain.CurrentBlock()) + ctx, write = m.rechecker.GetContext() + } + + if _, err := m.rechecker.RecheckCosmos(ctx, tx); err != nil { + return fmt.Errorf("ante handler failed: %w", err) + } + + if err := m.ExtMempool.Insert(ctx, tx); err != nil { + return err + } + + // since we have rechecked the tx via `rechecker.RecheckCosmos`, and this + // rechecks the tx on top of the state of all txs already rechecked in the + // mempool, this tx is valid and we can include it in the reaplist + if err := m.reapList.PushCosmosTx(tx); err != nil { + m.logger.Error("successfully inserted cosmos tx, but failed to insert into reap list", "err", err) + } + + write() + m.markTxInserted(tx) + + return nil +} + +// Remove is a noop for this pool. All removals are processed during the async +// recheck loop. +func (m *RecheckMempool) Remove(tx sdk.Tx) error { + // NOTE: processing the removal here produces a subtle bug for cosmos txs + // with multiple signers. the underlying mempool here (priority nonce + // mempool) identifies txs by only the first signer of multi signer txs. so + // when we see a tx included in a block (currently the only spot where we + // care about remove being called for this mempool) with for example, + // signer A at nonce 0, and we have a different tx in the mempool with + // signer A at nonce 0 and signer B at nonce 0, removing the tx in the + // block with only signer A will remove the tx in the mempool with both + // signers A and B. the priority nonce mempool gives us no hook to see what + // tx was actually removed. to account for this, we must not remove during + // FinalizeBlock, and process the removal during recheck where the multi + // signer tx will be dropped due to a nonce too low error on signer A. + // during recheck we know exactly which tx we are removing and why, and can + // properly unreserve the signer A's and signer B's address reservations. + return nil +} + +// RemoveWithReason is a noop for this pool. All removals are processed during +// the async recheck loop. This must be explicitly defined to prevent Go from +// promoting the embedded ExtMempool's RemoveWithReason. +func (m *RecheckMempool) RemoveWithReason(_ context.Context, tx sdk.Tx, _ sdkmempool.RemoveReason) error { + return m.Remove(tx) +} + +// reserveTx extracts the signers of tx and acquires their reserver +// holds. Returns any addresses who are now reserved, and any errors that occurred. +func (m *RecheckMempool) reserveTx(tx sdk.Tx) ([]common.Address, error) { + addrs, err := extractEVMAddresses(m.signerExtractor, tx) + if err != nil { + return nil, err + } + + if err := m.reserver.Hold(addrs...); err != nil { + return nil, fmt.Errorf("reserving %d addresses for cosmos recheck pool: %w", len(addrs), err) + } + + return addrs, nil +} + +// unreserveTx extracts the signers of tx and releases their +// reserver holds. Returns an error only if signer extraction fails; any +// error from the reserver itself is swallowed to preserve the prior +// best-effort cleanup semantics. +func (m *RecheckMempool) unreserveTx(tx sdk.Tx) error { + addrs, err := extractEVMAddresses(m.signerExtractor, tx) + if err != nil { + return fmt.Errorf("extractEVMAddresses: %w", err) + } + + if err := m.reserver.Release(addrs...); err != nil { + m.logger.Error("Failed to release reservations (unreserveTx)", "err", err, "addrs", addrs) + } + + return nil +} + +// Select returns an iterator over transactions in the pool. +func (m *RecheckMempool) Select(ctx context.Context, txs [][]byte) sdkmempool.Iterator { + m.mu.RLock() + defer m.mu.RUnlock() + return m.ExtMempool.Select(ctx, txs) +} + +// CountTx returns the number of transactions in the pool. +func (m *RecheckMempool) CountTx() int { + m.mu.RLock() + defer m.mu.RUnlock() + return m.ExtMempool.CountTx() +} + +type recheckRequest struct { + newHead *ethtypes.Header +} + +// TriggerRecheck signals that a new block arrived and returns a channel +// that closes when the recheck completes (or is superseded by another). +func (m *RecheckMempool) TriggerRecheck(newHead *ethtypes.Header) <-chan struct{} { + select { + case m.reqRecheckCh <- &recheckRequest{newHead: newHead}: + return <-m.recheckDoneCh + case <-m.recheckShutdown: + ch := make(chan struct{}) + close(ch) + return ch + } +} + +// TriggerRecheckSync triggers a recheck and blocks until complete. +func (m *RecheckMempool) TriggerRecheckSync(newHead *ethtypes.Header) { + <-m.TriggerRecheck(newHead) +} + +// RecheckedTxs returns the txs that have been rechecked for a height. The +// RecheckMempool must be currently operating on this height (i.e. recheck has +// been triggered on this height via TriggerRecheck). If height is in the past +// (TriggerRecheck has been called on height + 1), this will panic. If height +// is in the future, this will block until TriggerReset is called for height, +// or the context times out. +func (m *RecheckMempool) RecheckedTxs(ctx context.Context, height *big.Int) sdkmempool.Iterator { + txStore := m.recheckedTxs.GetStore(ctx, height) + if txStore == nil { + return nil + } + return txStore.Iterator() +} + +// OrderedRecheckedTxs returns the rechecked tx snapshot for a height using +// fee-priority ordering across signer buckets while still honoring nonce order +// within each bucket. +func (m *RecheckMempool) OrderedRecheckedTxs( + ctx context.Context, + height *big.Int, + bondDenom string, + baseFee *uint256.Int, +) sdkmempool.Iterator { + txStore := m.recheckedTxs.GetStore(ctx, height) + if txStore == nil { + return nil + } + return txStore.OrderedIterator(bondDenom, baseFee) +} + +// scheduleRecheckLoop is the main event loop that coordinates recheck execution. +// Only one recheck runs at a time. If a new block arrives while a recheck is +// running, the current recheck is cancelled and a new one is scheduled. +func (m *RecheckMempool) scheduleRecheckLoop() { + defer m.wg.Done() + defer close(m.recheckShutdown) + + var ( + curDone chan struct{} // non-nil while recheck is running + nextDone = make(chan struct{}) + launchNextRun bool + recheckReq *recheckRequest + cancelCh chan struct{} // closed to signal cancellation + ) + + for { + if curDone == nil && launchNextRun { + cancelCh = make(chan struct{}) + go m.runRecheck(nextDone, recheckReq.newHead, cancelCh) + + curDone, nextDone = nextDone, make(chan struct{}) + launchNextRun = false + recheckReq = nil + } + + select { + case req := <-m.reqRecheckCh: + if curDone != nil && cancelCh != nil { + close(cancelCh) + cancelCh = nil + } + recheckReq = req + launchNextRun = true + m.recheckDoneCh <- nextDone + + case <-curDone: + curDone = nil + cancelCh = nil + + case <-m.shutdownCh: + if curDone != nil { + if cancelCh != nil { + close(cancelCh) + } + <-curDone + } + close(nextDone) + return + } + } +} + +// runRecheck performs the actual recheck work. It holds the write lock for the +// entire duration, iterates through all txs, runs them through the ante handler, +// and removes any that fail (plus dependent txs with higher sequences). +func (m *RecheckMempool) runRecheck(done chan struct{}, newHead *ethtypes.Header, cancelled <-chan struct{}) { + defer close(done) + start := time.Now() + txsRemoved := 0 + txsChecked := 0 + defer func() { + recheckDuration.Record(context.Background(), float64(time.Since(start).Milliseconds())) + if txsRemoved > 0 { + recheckRemovals.Record(context.Background(), int64(txsRemoved)) + } + if txsChecked > 0 { + recheckNumChecked.Record(context.Background(), int64(txsChecked)) + } + }() + + m.mu.Lock() + defer m.mu.Unlock() + + m.recheckedTxs.StartNewHeight(newHead.Number) + defer m.recheckedTxs.EndCurrentHeight() + + latestCtx, err := m.blockchain.GetLatestContext() + if err != nil { + m.logger.Error("failed to get context for recheck", "err", err) + return + } + m.rechecker.Update(latestCtx, newHead) + + failedAtSequence := make(map[string]uint64) + removeTxs := make([]sdk.Tx, 0) + + // context.Background() safe to use here since ExtMempool is a + // PriorityNonceMempool and ctx is unused + iter := m.ExtMempool.Select(context.Background(), nil) + for iter != nil { + if isCancelled(cancelled) { + m.logger.Debug("recheck cancelled - new block arrived") + return + } + + txn := iter.Tx() + if txn == nil { + break + } + + txsChecked++ + signers, err := m.signerExtractor.GetSigners(txn) + if err != nil { + m.logger.Error("failed to extract signers", "err", err) + iter = iter.Next() + continue + } + + invalidTx := false + for _, s := range signers { + if failedSeq, ok := failedAtSequence[string(s.Signer)]; ok && failedSeq < s.Sequence { + invalidTx = true + break + } + } + + keepFuturesOnError := false + if !invalidTx { + ctx, write := m.rechecker.GetContext() + _, err := m.rechecker.RecheckCosmos(ctx, txn) + if err == nil { + write() + m.markTxRechecked(txn) + iter = iter.Next() + continue + } + + // we do not want to drop future txs for a signer if it had a tx + // fail due sequence mismatch. a sequence mismatch here means the + // nonce of this tx became too low compared to the chain state. we + // rerun ante handlers on insert to this pool, so at insert time, + // we know the nonce of the tx was not too high. since nonces only + // increase, ErrWrongSequence seen here must mean that the tx's + // nonce became too low. we still remove this tx, but we do not + // want to cascade and evict the signer's tx at nonce+1 since + // that may still be valid at the correct nonce. + if errors.Is(err, sdkerrors.ErrWrongSequence) { + keepFuturesOnError = true + } + } + + removeTxs = append(removeTxs, txn) + + if keepFuturesOnError { + iter = iter.Next() + continue + } + + // marks all future txs for this txs signers as invalid and we will + // drop them before they are even rechecked + for _, s := range signers { + key := string(s.Signer) + if existing, ok := failedAtSequence[key]; !ok || existing > s.Sequence { + failedAtSequence[key] = s.Sequence + } + } + + iter = iter.Next() + } + + if isCancelled(cancelled) { + m.logger.Debug("recheck cancelled before removal - new block arrived") + return + } + + for _, txn := range removeTxs { + if err := m.ExtMempool.Remove(txn); err != nil { + m.logger.Error("failed to remove tx during recheck", "err", err) + continue + } + m.reapList.DropCosmosTx(txn) + + if err := m.unreserveTx(txn); err != nil { + m.logger.Error("failed to release reservations", "err", err) + continue + } + } + txsRemoved = len(removeTxs) +} + +// markTxRechecked adds a tx into the height synced cosmos tx store. +func (m *RecheckMempool) markTxRechecked(txn sdk.Tx) { + m.recheckedTxs.Do(func(store *CosmosTxStore) { store.AddTx(txn) }) +} + +// markTxInserted conservatively updates the current height snapshot for live inserts. +// If the inserted tx replaces an existing tx, any other txs from the same sender with +// a higher nonce is dropped and rebuilt by the next recheck. +func (m *RecheckMempool) markTxInserted(txn sdk.Tx) { + m.recheckedTxs.Do(func(store *CosmosTxStore) { + // If we invalidate any txs we can't execute this txn's antehandler sequence until the next rechecker.Update. + // This is because the invalidated txns have written their state to the Store's cache context already. + if store.InvalidateFrom(txn) > 0 { + return + } + store.AddTx(txn) + }) +} + +// isCancelled checks if the cancellation channel has been closed. +func isCancelled(ch <-chan struct{}) bool { + select { + case <-ch: + return true + default: + return false + } +} + +func cosmosPoolConfig( + blockchain *Blockchain, + defaultConfig *sdkmempool.PriorityNonceMempoolConfig[math.Int], + maxTxs int, + onReplace func(oldTx, newTx sdk.Tx), +) sdkmempool.PriorityNonceMempoolConfig[math.Int] { + var config sdkmempool.PriorityNonceMempoolConfig[math.Int] + + if defaultConfig != nil { + // prioritize the default configs TxPriority struct if defined + config.TxPriority = defaultConfig.TxPriority + } else { + config.TxPriority = sdkmempool.TxPriority[math.Int]{ + GetTxPriority: func(_ context.Context, tx sdk.Tx) math.Int { + cosmosTxFee, ok := tx.(sdk.FeeTx) + if !ok { + return math.ZeroInt() + } + found, coin := cosmosTxFee.GetFee().Find(blockchain.GetCoinDenom()) + if !found { + return math.ZeroInt() + } + + gasPrice := coin.Amount.Quo(math.NewIntFromUint64(cosmosTxFee.GetGas())) + + return gasPrice + }, + Compare: func(a, b math.Int) int { + return a.BigInt().Cmp(b.BigInt()) + }, + MinValue: math.ZeroInt(), + } + } + + config.TxReplacement = func(oldPriority, newPriority math.Int, oldTx, newTx sdk.Tx) bool { + shouldReplace := true + + if defaultConfig != nil && defaultConfig.TxReplacement != nil { + // if the default config has a custom TxReplacement function, call + // that to determine if we should replace oldTx for newTx + shouldReplace = defaultConfig.TxReplacement(oldPriority, newPriority, oldTx, newTx) + } + + if shouldReplace { + onReplace(oldTx, newTx) + } + + return shouldReplace + } + + config.MaxTx = maxTxs + return config +} + +func onTransactionReplace( + reapList *reaplist.ReapList, + signerExtractor sdkmempool.SignerExtractionAdapter, + reserver *reserver.ReservationHandle, + logger log.Logger, +) func(oldTx, newTx sdk.Tx) { + return func(oldTx, _ sdk.Tx) { + // tx is being replaced, we need to drop the tx that is going to be removed + // from the reap list. we assume that the tx doing the replacing has + // already been inserted into the reaplist via the insert. + reapList.DropCosmosTx(oldTx) + + addrs, err := extractEVMAddresses(signerExtractor, oldTx) + if err != nil { + return + } + + if err := reserver.Release(addrs...); err != nil { + logger.Error("Failed to release reservations (onTransactionReplace)", "err", err, "addrs", addrs) + } + } +} + +func extractEVMAddresses(extractor sdkmempool.SignerExtractionAdapter, tx sdk.Tx) ([]common.Address, error) { + signers, err := extractor.GetSigners(tx) + if err != nil { + return nil, err + } + + addrs := make([]common.Address, len(signers)) + for i, s := range signers { + addrs[i] = common.BytesToAddress(s.Signer) + } + + return addrs, nil +} diff --git a/mempool/recheck_pool_test.go b/mempool/recheck_pool_test.go new file mode 100644 index 00000000..d5723345 --- /dev/null +++ b/mempool/recheck_pool_test.go @@ -0,0 +1,1273 @@ +package mempool_test + +import ( + "context" + "crypto/ecdsa" + "errors" + "fmt" + "math/big" + "sync" + "sync/atomic" + "testing" + "time" + + "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/proto" + + "github.com/cosmos/evm/crypto/ethsecp256k1" + "github.com/cosmos/evm/mempool" + "github.com/cosmos/evm/mempool/internal/heightsync" + "github.com/cosmos/evm/mempool/internal/reaplist" + "github.com/cosmos/evm/mempool/mocks" + "github.com/cosmos/evm/mempool/reserver" + "github.com/cosmos/evm/testutil/constants" + vmtypes "github.com/cosmos/evm/x/vm/types" + + "cosmossdk.io/log/v2" + sdkmath "cosmossdk.io/math" + + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" + "github.com/cosmos/cosmos-sdk/testutil" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkmempool "github.com/cosmos/cosmos-sdk/types/mempool" + signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" + authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" +) + +// ---------------------------------------------------------------------------- +// Mock Rechecker +// ---------------------------------------------------------------------------- + +// mockRechecker wraps an sdk.AnteHandler to implement the Rechecker interface +// for unit tests. +type mockRechecker struct { + ctx sdk.Context + anteHandler sdk.AnteHandler +} + +func newMockRechecker(ctx sdk.Context, anteHandler sdk.AnteHandler) *mockRechecker { + return &mockRechecker{ + ctx: ctx, + anteHandler: anteHandler, + } +} + +func (m *mockRechecker) GetContext() (sdk.Context, func()) { + if m.ctx.MultiStore() == nil { + return sdk.Context{}, func() {} + } + return m.ctx.CacheContext() +} + +func (m *mockRechecker) RecheckCosmos(ctx sdk.Context, tx sdk.Tx) (sdk.Context, error) { + return m.anteHandler(ctx, tx, false) +} + +func (m *mockRechecker) Update(ctx sdk.Context, _ *ethtypes.Header) { + m.ctx = ctx +} + +// ---------------------------------------------------------------------------- +// Test Blockchain +// ---------------------------------------------------------------------------- + +// newTestBlockchain creates a minimal *mempool.Blockchain for recheck-pool +// tests. GetLatestContext() returns the supplied ctx. +func newTestBlockchain(t *testing.T, ctx sdk.Context) *mempool.Blockchain { + t.Helper() + return newTestBlockchainWithGetter(t, func(_ int64, _ bool) (sdk.Context, error) { + return ctx, nil + }) +} + +// newTestBlockchainWithGetter lets a test control the behavior of the ctx +// callback (e.g., to simulate failures or return different contexts over +// time). +func newTestBlockchainWithGetter(t *testing.T, getCtx func(int64, bool) (sdk.Context, error)) *mempool.Blockchain { + t.Helper() + vmKeeper := mocks.NewVMKeeperI(t) + feeMarketKeeper := mocks.NewFeeMarketKeeper(t) + vmKeeper.On("GetBaseFee", mock.Anything).Return(big.NewInt(0)).Maybe() + vmKeeper.On("GetEvmCoinInfo", mock.Anything). + Return(vmtypes.EvmCoinInfo{Denom: recheckTestFeeDenom}).Maybe() + feeMarketKeeper.On("GetBlockGasWanted", mock.Anything).Return(uint64(0)).Maybe() + return mempool.NewBlockchain(getCtx, log.NewNopLogger(), vmKeeper, feeMarketKeeper, 30_000_000) +} + +// ---------------------------------------------------------------------------- +// Test ReapList + Encoder +// ---------------------------------------------------------------------------- + +type testTxEncoder struct{} + +func (testTxEncoder) EVMTx(tx *ethtypes.Transaction) ([]byte, error) { + return tx.Hash().Bytes(), nil +} + +func (testTxEncoder) CosmosTx(tx sdk.Tx) ([]byte, error) { + return []byte(fmt.Sprintf("%p", tx)), nil +} + +func newTestReapList() *reaplist.ReapList { + return reaplist.New(testTxEncoder{}) +} + +// testHeader creates a minimal header for testing with the given height. +func testHeader(height int64) *ethtypes.Header { + return ðtypes.Header{ + Number: big.NewInt(height), + GasLimit: 100_000_000, + } +} + +// ---------------------------------------------------------------------------- +// Insert +// ---------------------------------------------------------------------------- + +func TestRecheckMempool_Insert(t *testing.T) { + tests := []struct { + name string + setupReserver func(*reserver.ReservationTracker, common.Address) + anteErr error + expectErr error + expectCount int + expectHeld bool + }{ + { + name: "success", + expectErr: nil, + expectCount: 1, + expectHeld: true, + }, + { + name: "address already reserved by another pool", + setupReserver: func(tracker *reserver.ReservationTracker, addr common.Address) { + otherHandle := tracker.NewHandle(999) + require.NoError(t, otherHandle.Hold(addr)) + }, + expectErr: reserver.ErrAlreadyReserved, + expectCount: 0, + expectHeld: true, // still held by pool 999 + }, + { + name: "ante handler failure releases reservation", + anteErr: errors.New("insufficient funds"), + expectErr: errors.New("ante handler failed"), + expectCount: 0, + expectHeld: false, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + acc := newRecheckTestAccount(t) + tracker := reserver.NewReservationTracker() + handle := tracker.NewHandle(1) + + if tc.setupReserver != nil { + tc.setupReserver(tracker, acc.address) + } + + anteHandler := func(ctx sdk.Context, tx sdk.Tx, _ bool) (sdk.Context, error) { + if tc.anteErr != nil { + return sdk.Context{}, tc.anteErr + } + return ctx, nil + } + + ctx := newRecheckTestContext() + bc := newTestBlockchain(t, ctx) + rc := newMockRechecker(ctx, anteHandler) + + mp := mempool.NewRecheckMempool( + nil, 0, handle, rc, + newTestRecheckedTxs(), newTestReapList(), bc, log.NewNopLogger(), + ) + + tx := newRecheckTestTx(t, acc.key) + err := mp.Insert(ctx, tx) + + if tc.expectErr != nil { + require.Error(t, err) + require.Contains(t, err.Error(), tc.expectErr.Error()) + } else { + require.NoError(t, err) + } + + require.Equal(t, tc.expectCount, mp.CountTx()) + + // Verify reservation state using handle from a different pool + otherHandle := tracker.NewHandle(2) + if tc.expectHeld { + require.True(t, otherHandle.Has(acc.address), "address should be reserved by some pool") + } else { + require.False(t, otherHandle.Has(acc.address), "address should not be reserved") + } + }) + } +} + +func TestRecheckMempool_Insert_PoolCapacity(t *testing.T) { + tracker := reserver.NewReservationTracker() + handle := tracker.NewHandle(1) + + ctx := newRecheckTestContext() + bc := newTestBlockchain(t, ctx) + rc := newMockRechecker(ctx, noopAnteHandler) + + maxTxs := 1 + mp := mempool.NewRecheckMempool( + nil, maxTxs, handle, rc, + newTestRecheckedTxs(), newTestReapList(), bc, log.NewNopLogger(), + ) + + firstAcc := newRecheckTestAccount(t) + require.NoError(t, mp.Insert(ctx, newRecheckTestTx(t, firstAcc.key))) + + secondAcc := newRecheckTestAccount(t) + err := mp.Insert(ctx, newRecheckTestTx(t, secondAcc.key)) + require.Error(t, err) + + // Second signer should not remain reserved after failed insert. + otherHandle := tracker.NewHandle(2) + require.False(t, otherHandle.Has(secondAcc.address)) + require.True(t, otherHandle.Has(firstAcc.address)) +} + +// ---------------------------------------------------------------------------- +// Lifecycle +// ---------------------------------------------------------------------------- + +func TestRecheckMempool_StartClose(t *testing.T) { + tracker := reserver.NewReservationTracker() + handle := tracker.NewHandle(1) + ctx := newRecheckTestContext() + bc := newTestBlockchain(t, ctx) + rc := newMockRechecker(ctx, noopAnteHandler) + + mp := mempool.NewRecheckMempool( + nil, 0, handle, rc, + newTestRecheckedTxs(), newTestReapList(), bc, log.NewNopLogger(), + ) + + mp.Start(testHeader(0)) + + closeDone := make(chan error) + go func() { + closeDone <- mp.Close() + }() + + select { + case err := <-closeDone: + require.NoError(t, err) + case <-time.After(2 * time.Second): + t.Fatal("Close() did not return in time") + } +} + +func TestRecheckMempool_CloseIdempotent(t *testing.T) { + tracker := reserver.NewReservationTracker() + handle := tracker.NewHandle(1) + ctx := newRecheckTestContext() + bc := newTestBlockchain(t, ctx) + rc := newMockRechecker(ctx, noopAnteHandler) + + mp := mempool.NewRecheckMempool( + nil, 0, handle, rc, + newTestRecheckedTxs(), newTestReapList(), bc, log.NewNopLogger(), + ) + mp.Start(testHeader(0)) + + require.NoError(t, mp.Close()) + require.NoError(t, mp.Close()) +} + +func TestRecheckMempool_TriggerRecheckAfterShutdown(t *testing.T) { + tracker := reserver.NewReservationTracker() + handle := tracker.NewHandle(1) + ctx := newRecheckTestContext() + bc := newTestBlockchain(t, ctx) + rc := newMockRechecker(ctx, noopAnteHandler) + + mp := mempool.NewRecheckMempool( + nil, 0, handle, rc, + newTestRecheckedTxs(), newTestReapList(), bc, log.NewNopLogger(), + ) + mp.Start(testHeader(0)) + require.NoError(t, mp.Close()) + + done := mp.TriggerRecheck(testHeader(1)) + select { + case <-done: + // Expected - returns immediately after shutdown + case <-time.After(100 * time.Millisecond): + t.Fatal("TriggerRecheck after shutdown should return immediately") + } +} + +// ---------------------------------------------------------------------------- +// Cancellation Tests +// ---------------------------------------------------------------------------- + +func TestRecheckMempool_ShutdownDuringRecheck(t *testing.T) { + tracker := reserver.NewReservationTracker() + handle := tracker.NewHandle(1) + ctx := newRecheckTestContext() + bc := newTestBlockchain(t, ctx) + + gate := make(chan struct{}) + ready := make(chan struct{}) // signals when ante handler is waiting + var insertCount, recheckCount atomic.Int32 + + numTxsToInsert := int32(10) + + anteHandler := func(ctx sdk.Context, tx sdk.Tx, _ bool) (sdk.Context, error) { + if insertCount.Add(1) <= numTxsToInsert { + return ctx, nil + } + ready <- struct{}{} // signal we're waiting + <-gate + recheckCount.Add(1) + return ctx, nil + } + + rc := newMockRechecker(ctx, anteHandler) + + mp := mempool.NewRecheckMempool( + nil, 0, handle, rc, + newTestRecheckedTxs(), newTestReapList(), bc, log.NewNopLogger(), + ) + mp.Start(testHeader(0)) + + for range numTxsToInsert { + key, _ := crypto.GenerateKey() + tx := newRecheckTestTx(t, key) + require.NoError(t, mp.Insert(ctx, tx)) + } + + recheckDone := mp.TriggerRecheck(testHeader(1)) + + <-ready // tx 1 is waiting + gate <- struct{}{} // release tx 1 + <-ready // tx 2 is waiting + gate <- struct{}{} // release tx 2 + <-ready // tx 3 is waiting - now call Close + + closeDone := make(chan error) + go func() { + closeDone <- mp.Close() // this will close cancelCh, then wait for recheck + }() + + // Give Close() time to signal cancellation before unblocking + time.Sleep(10 * time.Millisecond) + + close(gate) // unblock tx 3 and any others + + select { + case err := <-closeDone: + require.NoError(t, err) + case <-time.After(2 * time.Second): + t.Fatal("Close() blocked during active recheck") + } + + <-recheckDone + + finalCount := recheckCount.Load() + require.GreaterOrEqual(t, finalCount, int32(2), "at least 2 txs should have been checked") + require.Less(t, finalCount, numTxsToInsert, "recheck should have been cancelled before all txs") +} + +// ---------------------------------------------------------------------------- +// Error Path Tests +// ---------------------------------------------------------------------------- + +func TestRecheckMempool_GetCtxError(t *testing.T) { + tracker := reserver.NewReservationTracker() + handle := tracker.NewHandle(1) + ctx := newRecheckTestContext() + + // Blockchain with a switchable ctx getter — healthy during insert, + // failing once we flip the flag before triggering recheck. + var getCtxFail atomic.Bool + bc := newTestBlockchainWithGetter(t, func(_ int64, _ bool) (sdk.Context, error) { + if getCtxFail.Load() { + return sdk.Context{}, errors.New("context unavailable") + } + return ctx, nil + }) + rc := newMockRechecker(ctx, noopAnteHandler) + + mp := mempool.NewRecheckMempool( + nil, 0, handle, rc, + newTestRecheckedTxs(), newTestReapList(), bc, log.NewNopLogger(), + ) + mp.Start(testHeader(0)) + defer mp.Close() + + acc := newRecheckTestAccount(t) + tx := newRecheckTestTx(t, acc.key) + require.NoError(t, mp.Insert(ctx, tx)) + require.Equal(t, 1, mp.CountTx()) + + getCtxFail.Store(true) + mp.TriggerRecheckSync(testHeader(1)) + + require.Equal(t, 1, mp.CountTx(), "tx should remain when getCtx fails") +} + +// ---------------------------------------------------------------------------- +// Concurrency Tests +// ---------------------------------------------------------------------------- + +func TestRecheckMempool_ConcurrentTriggers(t *testing.T) { + tracker := reserver.NewReservationTracker() + handle := tracker.NewHandle(1) + ctx := newRecheckTestContext() + bc := newTestBlockchain(t, ctx) + rc := newMockRechecker(ctx, noopAnteHandler) + + mp := mempool.NewRecheckMempool( + nil, 0, handle, rc, + newTestRecheckedTxs(), newTestReapList(), bc, log.NewNopLogger(), + ) + mp.Start(testHeader(0)) + defer mp.Close() + + numTxs := 5 + for range numTxs { + key, _ := crypto.GenerateKey() + tx := newRecheckTestTx(t, key) + require.NoError(t, mp.Insert(ctx, tx)) + } + + var wg sync.WaitGroup + var timeouts atomic.Int32 + numTriggers := 10 + for range numTriggers { + wg.Add(1) + go func() { + defer wg.Done() + done := mp.TriggerRecheck(testHeader(1)) + select { + case <-done: + // Expected - recheck completed + case <-time.After(5 * time.Second): + timeouts.Add(1) + } + }() + } + + wg.Wait() + require.Zero(t, timeouts.Load(), "some rechecks did not complete in time") +} + +// ---------------------------------------------------------------------------- +// Integration +// ---------------------------------------------------------------------------- + +func TestMempool_Recheck(t *testing.T) { + type accountTx struct { + account int + nonce uint64 + } + + tests := []struct { + name string + insertTxs []accountTx + failTxs []accountTx + expectedRemain []accountTx + }{ + { + name: "single account middle nonce fails - removes it and higher nonces", + insertTxs: []accountTx{ + {account: 0, nonce: 0}, + {account: 0, nonce: 1}, + {account: 0, nonce: 2}, + }, + failTxs: []accountTx{ + {account: 0, nonce: 1}, + }, + expectedRemain: []accountTx{ + {account: 0, nonce: 0}, + }, + }, + { + name: "single account first nonce fails - removes all", + insertTxs: []accountTx{ + {account: 0, nonce: 0}, + {account: 0, nonce: 1}, + {account: 0, nonce: 2}, + }, + failTxs: []accountTx{ + {account: 0, nonce: 0}, + }, + expectedRemain: []accountTx{}, + }, + { + name: "single account last nonce fails - keeps earlier nonces", + insertTxs: []accountTx{ + {account: 0, nonce: 0}, + {account: 0, nonce: 1}, + {account: 0, nonce: 2}, + }, + failTxs: []accountTx{ + {account: 0, nonce: 2}, + }, + expectedRemain: []accountTx{ + {account: 0, nonce: 0}, + {account: 0, nonce: 1}, + }, + }, + { + name: "multiple accounts - failure in one does not affect others", + insertTxs: []accountTx{ + {account: 0, nonce: 0}, + {account: 0, nonce: 1}, + {account: 0, nonce: 2}, + {account: 1, nonce: 0}, + {account: 1, nonce: 1}, + {account: 2, nonce: 0}, + }, + failTxs: []accountTx{ + {account: 0, nonce: 1}, + }, + expectedRemain: []accountTx{ + {account: 0, nonce: 0}, + {account: 1, nonce: 0}, + {account: 1, nonce: 1}, + {account: 2, nonce: 0}, + }, + }, + { + name: "multiple accounts with multiple failures", + insertTxs: []accountTx{ + {account: 0, nonce: 0}, + {account: 0, nonce: 1}, + {account: 1, nonce: 0}, + {account: 1, nonce: 1}, + {account: 2, nonce: 0}, + }, + failTxs: []accountTx{ + {account: 0, nonce: 0}, + {account: 1, nonce: 1}, + }, + expectedRemain: []accountTx{ + {account: 1, nonce: 0}, + {account: 2, nonce: 0}, + }, + }, + { + name: "no failures - all txs remain", + insertTxs: []accountTx{ + {account: 0, nonce: 0}, + {account: 0, nonce: 1}, + {account: 1, nonce: 0}, + }, + failTxs: []accountTx{}, + expectedRemain: []accountTx{ + {account: 0, nonce: 0}, + {account: 0, nonce: 1}, + {account: 1, nonce: 0}, + }, + }, + { + name: "all txs fail", + insertTxs: []accountTx{ + {account: 0, nonce: 0}, + {account: 1, nonce: 0}, + }, + failTxs: []accountTx{ + {account: 0, nonce: 0}, + {account: 1, nonce: 0}, + }, + expectedRemain: []accountTx{}, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + mp, s := setupMempoolWithAccounts(t, 3) + txConfig, cosmosRechecker, accounts := s.txConfig, s.cosmosRechecker, s.accounts + + getSignerAddr := func(accountIdx int) []byte { + pubKeyBytes := crypto.CompressPubkey(&accounts[accountIdx].key.PublicKey) + pubKey := ðsecp256k1.PubKey{Key: pubKeyBytes} + return pubKey.Address().Bytes() + } + + for _, tx := range tc.insertTxs { + cosmosTx := createTestCosmosTx(t, txConfig, accounts[tx.account].key, tx.nonce) + require.NoError(t, mp.Insert(context.Background(), cosmosTx)) + } + + require.Equal(t, len(tc.insertTxs), mp.CountTx(), "should have all txs inserted") + + failSet := make(map[string]bool) + for _, fail := range tc.failTxs { + signerAddr := getSignerAddr(fail.account) + failSet[fmt.Sprintf("%x-%d", signerAddr, fail.nonce)] = true + } + + cosmosRechecker.SetCosmosRecheck(func(ctx sdk.Context, tx sdk.Tx) (sdk.Context, error) { + if sigTx, ok := tx.(authsigning.SigVerifiableTx); ok { + signers, _ := sigTx.GetSigners() + sigs, _ := sigTx.GetSignaturesV2() + if len(signers) > 0 && len(sigs) > 0 { + key := fmt.Sprintf("%x-%d", signers[0], sigs[0].Sequence) + if failSet[key] { + return sdk.Context{}, errors.New("ante check failed") + } + } + } + return ctx, nil + }) + + mp.RecheckCosmosTxs(testHeader(1)) + + require.Equal(t, len(tc.expectedRemain), mp.CountTx(), + "expected %d txs to remain, got %d", len(tc.expectedRemain), mp.CountTx()) + }) + } +} + +// ---------------------------------------------------------------------------- +// Height Sync'd Store Tests +// ---------------------------------------------------------------------------- + +func TestRecheckMempool_RecheckedTxs(t *testing.T) { + tests := []struct { + name string + numTxs int + failTxIndices []int // which tx indices fail the ante handler on recheck + }{ + { + name: "all txs pass", + numTxs: 3, + failTxIndices: []int{}, + }, + { + name: "one tx fails on recheck", + numTxs: 3, + failTxIndices: []int{1}, + }, + { + name: "all txs fail on recheck", + numTxs: 3, + failTxIndices: []int{0, 1, 2}, + }, + { + name: "empty pool", + numTxs: 0, + failTxIndices: []int{}, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + tracker := reserver.NewReservationTracker() + handle := tracker.NewHandle(1) + ctx := newRecheckTestContext() + bc := newTestBlockchain(t, ctx) + recheckedTxs := newTestRecheckedTxs() + + failSet := make(map[sdk.Tx]bool) + failOnRecheck := false + anteHandler := func(ctx sdk.Context, tx sdk.Tx, _ bool) (sdk.Context, error) { + if failOnRecheck && failSet[tx] { + return sdk.Context{}, errors.New("recheck failed") + } + return ctx, nil + } + + rc := newMockRechecker(ctx, anteHandler) + + mp := mempool.NewRecheckMempool( + nil, 0, handle, rc, + recheckedTxs, newTestReapList(), bc, log.NewNopLogger(), + ) + mp.Start(testHeader(0)) + defer mp.Close() + + txs := make([]sdk.Tx, tc.numTxs) + for i := range tc.numTxs { + key, _ := crypto.GenerateKey() + txs[i] = newRecheckTestTx(t, key) + require.NoError(t, mp.Insert(ctx, txs[i])) + } + + for _, idx := range tc.failTxIndices { + failSet[txs[idx]] = true + } + failOnRecheck = true + + header := testHeader(1) + mp.TriggerRecheckSync(header) + + expectedCount := tc.numTxs - len(tc.failTxIndices) + require.Equal(t, expectedCount, mp.CountTx()) + + iter := mp.RecheckedTxs(context.Background(), header.Number) + rechecked := collectIteratorTxs(iter) + require.Len(t, rechecked, expectedCount) + + for i, tx := range txs { + if failSet[tx] { + require.NotContains(t, rechecked, tx, "failed tx %d should not be in rechecked store", i) + } else { + require.Contains(t, rechecked, tx, "passing tx %d should be in rechecked store", i) + } + } + }) + } +} + +func TestRecheckMempool_RecheckedTxsBlocksUntilComplete(t *testing.T) { + acc := newRecheckTestAccount(t) + tracker := reserver.NewReservationTracker() + handle := tracker.NewHandle(1) + ctx := newRecheckTestContext() + bc := newTestBlockchain(t, ctx) + recheckedTxs := newTestRecheckedTxs() + + var callCount atomic.Int32 + gate := make(chan struct{}) + anteHandler := func(ctx sdk.Context, tx sdk.Tx, _ bool) (sdk.Context, error) { + if callCount.Add(1) > 1 { + // Second call is from recheck - block until gate is released + <-gate + } + return ctx, nil + } + + rc := newMockRechecker(ctx, anteHandler) + + mp := mempool.NewRecheckMempool( + nil, 0, handle, rc, + recheckedTxs, newTestReapList(), bc, log.NewNopLogger(), + ) + mp.Start(testHeader(0)) + defer mp.Close() + + tx := newRecheckTestTx(t, acc.key) + require.NoError(t, mp.Insert(ctx, tx)) + + header := testHeader(1) + recheckDone := mp.TriggerRecheck(header) + + // RecheckedTxs should block because recheck is in progress + result := make(chan sdkmempool.Iterator, 1) + go func() { + result <- mp.RecheckedTxs(context.Background(), header.Number) + }() + + select { + case <-result: + t.Fatal("RecheckedTxs should block until recheck completes") + case <-time.After(100 * time.Millisecond): + // Expected - still blocking + } + + // Release the gate to let recheck complete + close(gate) + + select { + case iter := <-result: + rechecked := collectIteratorTxs(iter) + require.Len(t, rechecked, 1, "should have 1 rechecked tx") + require.Equal(t, tx, rechecked[0]) + case <-time.After(2 * time.Second): + t.Fatal("RecheckedTxs did not return after recheck completed") + } + + <-recheckDone +} + +func TestRecheckMempool_RecheckerNoContextOnInsert(t *testing.T) { + // setup mocks for blockchain fetching latest block + vmtypes.NewEVMConfigurator().ResetTestConfig() + require.NoError(t, vmtypes.SetChainConfig(vmtypes.DefaultChainConfig(constants.EighteenDecimalsChainID))) + require.NoError(t, vmtypes.NewEVMConfigurator(). + WithEVMCoinInfo(constants.ChainsCoinInfo[constants.EighteenDecimalsChainID]). + Configure()) + + acc := newRecheckTestAccount(t) + tracker := reserver.NewReservationTracker() + handle := tracker.NewHandle(1) + + // blockchain has a valid context ready + ctx := newRecheckTestContext() + bc := newTestBlockchain(t, ctx) + + // rechecker does not have a valid context + rc := newMockRechecker(sdk.Context{}, noopAnteHandler) + + recheckedTxs := newTestRecheckedTxs() + mp := mempool.NewRecheckMempool( + nil, 0, handle, rc, + recheckedTxs, newTestReapList(), bc, log.NewNopLogger(), + ) + + tx := newRecheckTestTx(t, acc.key) + require.NoError(t, mp.Insert(ctx, tx)) + require.Equal(t, 1, mp.CountTx()) +} + +// ---------------------------------------------------------------------------- +// Shared Insert/Recheck State Tests +// ---------------------------------------------------------------------------- + +func newRecheckTestTxWithNonce(t *testing.T, key *ecdsa.PrivateKey, nonce uint64) sdk.Tx { + t.Helper() + return &recheckTestTx{key: key, sequence: nonce} +} + +func newRecheckTestTxWithGasPrice(t *testing.T, key *ecdsa.PrivateKey, nonce uint64, gasPrice int64) sdk.Tx { + t.Helper() + return &recheckTestTx{ + key: key, + sequence: nonce, + gas: 100_000, + fee: sdk.NewCoins(sdk.NewInt64Coin(recheckTestFeeDenom, gasPrice*100_000)), + } +} + +// newNonceTrackingAnteHandler returns an ante handler that enforces sequential +// nonce ordering per account. Nonces are tracked in a map keyed by signer +// address — each successful call increments the expected nonce. +func newNonceTrackingAnteHandler() sdk.AnteHandler { + nonces := make(map[string]uint64) + return func(ctx sdk.Context, tx sdk.Tx, _ bool) (sdk.Context, error) { + sigTx, ok := tx.(authsigning.SigVerifiableTx) + if !ok { + return ctx, nil + } + sigs, err := sigTx.GetSignaturesV2() + if err != nil || len(sigs) == 0 { + return ctx, nil + } + for _, sig := range sigs { + addr := sig.PubKey.Address().String() + expected := nonces[addr] + if sig.Sequence != expected { + return sdk.Context{}, fmt.Errorf( + "account %s: expected nonce %d, got %d", + addr, expected, sig.Sequence, + ) + } + nonces[addr] = expected + 1 + } + return ctx, nil + } +} + +// TestRecheckMempool_InsertSequentialNonces verifies that inserting txs with +// sequential nonces from the same account succeeds, because each Insert +// commits the nonce increment back to the Rechecker's context. +func TestRecheckMempool_InsertSequentialNonces(t *testing.T) { + ctx := newRecheckTestContext() + tracker := reserver.NewReservationTracker() + handle := tracker.NewHandle(1) + bc := newTestBlockchain(t, ctx) + rc := newMockRechecker(ctx, newNonceTrackingAnteHandler()) + + mp := mempool.NewRecheckMempool( + nil, 0, handle, rc, + newTestRecheckedTxs(), newTestReapList(), bc, log.NewNopLogger(), + ) + + key, err := crypto.GenerateKey() + require.NoError(t, err) + + for nonce := uint64(0); nonce < 3; nonce++ { + tx := newRecheckTestTxWithNonce(t, key, nonce) + err := mp.Insert(ctx, tx) + require.NoError(t, err, "insert nonce %d should succeed", nonce) + } + require.Equal(t, 3, mp.CountTx()) +} + +// TestRecheckMempool_InsertNonceGapFails verifies that skipping a nonce is +// rejected by the Rechecker's ante handler. +func TestRecheckMempool_InsertNonceGapFails(t *testing.T) { + ctx := newRecheckTestContext() + tracker := reserver.NewReservationTracker() + handle := tracker.NewHandle(1) + bc := newTestBlockchain(t, ctx) + rc := newMockRechecker(ctx, newNonceTrackingAnteHandler()) + + mp := mempool.NewRecheckMempool( + nil, 0, handle, rc, + newTestRecheckedTxs(), newTestReapList(), bc, log.NewNopLogger(), + ) + + key, err := crypto.GenerateKey() + require.NoError(t, err) + + require.NoError(t, mp.Insert(ctx, newRecheckTestTxWithNonce(t, key, 0))) + + err = mp.Insert(ctx, newRecheckTestTxWithNonce(t, key, 2)) + require.Error(t, err) + require.Contains(t, err.Error(), "expected nonce 1, got 2") + require.Equal(t, 1, mp.CountTx()) +} + +// TestRecheckMempool_InsertAfterRecheck verifies that after a recheck commits +// surviving txs' state back to the Rechecker, a new insert at the next nonce +// succeeds. +func TestRecheckMempool_InsertAfterRecheck(t *testing.T) { + ctx := newRecheckTestContext() + tracker := reserver.NewReservationTracker() + handle := tracker.NewHandle(1) + bc := newTestBlockchain(t, ctx) + + // The nonce tracker is shared across insert and recheck calls. + // After recheck re-validates nonces 0 and 1, the tracker expects 2 next. + rc := newMockRechecker(ctx, newNonceTrackingAnteHandler()) + + mp := mempool.NewRecheckMempool( + nil, 0, handle, rc, + newTestRecheckedTxs(), newTestReapList(), bc, log.NewNopLogger(), + ) + mp.Start(testHeader(0)) + defer mp.Close() + + key, err := crypto.GenerateKey() + require.NoError(t, err) + + require.NoError(t, mp.Insert(ctx, newRecheckTestTxWithNonce(t, key, 0))) + require.NoError(t, mp.Insert(ctx, newRecheckTestTxWithNonce(t, key, 1))) + require.Equal(t, 2, mp.CountTx()) + + // Reset the ante handler — recheck must re-validate from nonce 0. + rc.anteHandler = newNonceTrackingAnteHandler() + + mp.TriggerRecheckSync(testHeader(1)) + require.Equal(t, 2, mp.CountTx()) + + // Insert nonce 2 — should succeed because the recheck re-established + // nonces 0→1, so the tracker now expects 2. + require.NoError(t, mp.Insert(ctx, newRecheckTestTxWithNonce(t, key, 2))) + require.Equal(t, 3, mp.CountTx()) +} + +func TestRecheckMempool_InsertReplacementInvalidatesRechecked(t *testing.T) { + ctx := newRecheckTestContext() + tracker := reserver.NewReservationTracker() + handle := tracker.NewHandle(1) + bc := newTestBlockchain(t, ctx) + rc := newMockRechecker(ctx, noopAnteHandler) + recheckedTxs := newTestRecheckedTxs() + + mp := mempool.NewRecheckMempool( + nil, 0, handle, rc, + recheckedTxs, newTestReapList(), bc, log.NewNopLogger(), + ) + mp.Start(testHeader(0)) + t.Cleanup(func() { + require.NoError(t, mp.Close()) + }) + + key, err := crypto.GenerateKey() + require.NoError(t, err) + + tx4 := newRecheckTestTxWithNonce(t, key, 4) + tx5 := newRecheckTestTxWithNonce(t, key, 5) + tx6 := newRecheckTestTxWithNonce(t, key, 6) + + recheckedTxs.Do(func(store *mempool.CosmosTxStore) { + store.AddTx(tx4) + store.AddTx(tx5) + store.AddTx(tx6) + }) + + replacement := newRecheckTestTxWithNonce(t, key, 4) + require.NoError(t, mp.Insert(ctx, replacement)) + + iter := mp.RecheckedTxs(context.Background(), big.NewInt(0)) + rechecked := collectIteratorTxs(iter) + require.Empty(t, rechecked) + require.Equal(t, 1, mp.CountTx()) +} + +// customReplacementConfig returns a PriorityNonceMempoolConfig whose +// TxReplacement allows replacement only when the new priority beats the old. +// Used by tests that exercise replacement behavior without relying on the +// default (reap-list-dropping) config. +func customReplacementConfig() *sdkmempool.PriorityNonceMempoolConfig[sdkmath.Int] { + return &sdkmempool.PriorityNonceMempoolConfig[sdkmath.Int]{ + TxPriority: sdkmempool.TxPriority[sdkmath.Int]{ + GetTxPriority: func(_ context.Context, tx sdk.Tx) sdkmath.Int { + cosmosTxFee, ok := tx.(sdk.FeeTx) + if !ok { + return sdkmath.ZeroInt() + } + found, coin := cosmosTxFee.GetFee().Find(recheckTestFeeDenom) + if !found { + return sdkmath.ZeroInt() + } + return coin.Amount.Quo(sdkmath.NewIntFromUint64(cosmosTxFee.GetGas())) + }, + Compare: func(a, b sdkmath.Int) int { + return a.BigInt().Cmp(b.BigInt()) + }, + MinValue: sdkmath.ZeroInt(), + }, + TxReplacement: func(op, np sdkmath.Int, _ sdk.Tx, _ sdk.Tx) bool { + return np.GT(op) + }, + } +} + +func TestRecheckMempool_RecheckRebuildsSnapshotAfterReplacement(t *testing.T) { + ctx := newRecheckTestContext() + tracker := reserver.NewReservationTracker() + handle := tracker.NewHandle(1) + bc := newTestBlockchain(t, ctx) + rc := newMockRechecker(ctx, noopAnteHandler) + recheckedTxs := newTestRecheckedTxs() + + mp := mempool.NewRecheckMempool( + customReplacementConfig(), 0, handle, rc, + recheckedTxs, newTestReapList(), bc, log.NewNopLogger(), + ) + mp.Start(testHeader(0)) + t.Cleanup(func() { + require.NoError(t, mp.Close()) + }) + + key, err := crypto.GenerateKey() + require.NoError(t, err) + + tx3 := newRecheckTestTxWithGasPrice(t, key, 3, 1) + tx4 := newRecheckTestTxWithGasPrice(t, key, 4, 1) + tx5 := newRecheckTestTxWithGasPrice(t, key, 5, 1) + tx6 := newRecheckTestTxWithGasPrice(t, key, 6, 1) + replacement := newRecheckTestTxWithGasPrice(t, key, 4, 2) + + for _, tx := range []sdk.Tx{tx3, tx4, tx5, tx6} { + require.NoError(t, mp.Insert(ctx, tx)) + } + + // insert the replacement, which should invalidate the other txs in the pool with greater nonce. + require.NoError(t, mp.Insert(ctx, replacement)) + + iter := mp.RecheckedTxs(context.Background(), big.NewInt(0)) + rechecked := collectIteratorTxs(iter) + require.Len(t, rechecked, 1) + require.Equal(t, tx3, rechecked[0]) + + mp.TriggerRecheckSync(testHeader(1)) + + iter = mp.RecheckedTxs(context.Background(), big.NewInt(1)) + rechecked = collectIteratorTxs(iter) + require.Equal(t, []sdk.Tx{tx3, replacement, tx5, tx6}, rechecked) +} + +// TestRecheckMempool_RecheckDropsFromReapList verifies that when a tx fails +// recheck and gets removed from the pool, it is also dropped from the reap +// list. Txs that pass recheck must remain reapable. +func TestRecheckMempool_RecheckDropsFromReapList(t *testing.T) { + ctx := newRecheckTestContext() + tracker := reserver.NewReservationTracker() + handle := tracker.NewHandle(1) + bc := newTestBlockchain(t, ctx) + reapList := newTestReapList() + + failSet := make(map[sdk.Tx]bool) + anteHandler := func(ctx sdk.Context, tx sdk.Tx, _ bool) (sdk.Context, error) { + if failSet[tx] { + return sdk.Context{}, errors.New("recheck failed") + } + return ctx, nil + } + rc := newMockRechecker(ctx, anteHandler) + + mp := mempool.NewRecheckMempool( + nil, 0, handle, rc, + newTestRecheckedTxs(), reapList, bc, log.NewNopLogger(), + ) + mp.Start(testHeader(0)) + t.Cleanup(func() { require.NoError(t, mp.Close()) }) + + // Three txs from independent signers: keepA, doomed, keepB. + keepA := newRecheckTestTx(t, mustGenKey(t)) + doomed := newRecheckTestTx(t, mustGenKey(t)) + keepB := newRecheckTestTx(t, mustGenKey(t)) + + for _, tx := range []sdk.Tx{keepA, doomed, keepB} { + require.NoError(t, mp.Insert(ctx, tx)) + } + + // Flip the doomed tx to fail on recheck. + failSet[doomed] = true + mp.TriggerRecheckSync(testHeader(1)) + + require.Equal(t, 2, mp.CountTx(), "failed tx should be removed from pool") + + reaped := reapList.Reap(0, 0) + require.Len(t, reaped, 2, "doomed tx's bytes should also be dropped from reap list") + + enc := testTxEncoder{} + doomedBytes, _ := enc.CosmosTx(doomed) + for _, b := range reaped { + require.NotEqual(t, doomedBytes, b, "doomed tx bytes should not appear in reap list") + } +} + +func mustGenKey(t *testing.T) *ecdsa.PrivateKey { + t.Helper() + k, err := crypto.GenerateKey() + require.NoError(t, err) + return k +} + +func TestRecheckMempool_ReplacementDropsFromReapList(t *testing.T) { + ctx := newRecheckTestContext() + tracker := reserver.NewReservationTracker() + handle := tracker.NewHandle(1) + bc := newTestBlockchain(t, ctx) + rc := newMockRechecker(ctx, noopAnteHandler) + reapList := newTestReapList() + + mp := mempool.NewRecheckMempool( + nil, 0, handle, rc, + newTestRecheckedTxs(), reapList, bc, log.NewNopLogger(), + ) + + key, err := crypto.GenerateKey() + require.NoError(t, err) + + original := newRecheckTestTxWithGasPrice(t, key, 5, 1) + require.NoError(t, mp.Insert(ctx, original)) + + // same sender + nonce, new gas price + replacement := newRecheckTestTxWithGasPrice(t, key, 5, 2) + require.NoError(t, mp.Insert(ctx, replacement)) + + require.Equal(t, 1, mp.CountTx(), "pool should hold exactly one tx after replacement") + + reaped := reapList.Reap(0, 0) + require.Len(t, reaped, 1, "reap list should only hold the replacement") + expected, err := testTxEncoder{}.CosmosTx(replacement) + require.NoError(t, err) + require.Equal(t, expected, reaped[0]) +} + +// newRecheckTestTx creates a minimal sdk.Tx for unit testing RecheckMempool. +func newRecheckTestTx(t *testing.T, key *ecdsa.PrivateKey) sdk.Tx { + t.Helper() + return &recheckTestTx{key: key} +} + +// recheckTestTx is a minimal sdk.Tx implementation for unit testing. +type recheckTestTx struct { + key *ecdsa.PrivateKey + sequence uint64 + gas uint64 + fee sdk.Coins +} + +const recheckTestFeeDenom = "atest" + +func (m *recheckTestTx) GetMsgs() []sdk.Msg { return nil } + +func (m *recheckTestTx) GetMsgsV2() ([]proto.Message, error) { + return nil, nil +} + +func (m *recheckTestTx) GetGas() uint64 { + if m.gas == 0 { + return 100_000 + } + return m.gas +} + +func (m *recheckTestTx) GetFee() sdk.Coins { + if len(m.fee) == 0 { + return sdk.NewCoins(sdk.NewInt64Coin(recheckTestFeeDenom, 100_000)) + } + return m.fee +} + +func (m *recheckTestTx) FeePayer() []byte { + signers, err := m.GetSigners() + if err != nil || len(signers) == 0 { + return nil + } + return signers[0] +} + +func (m *recheckTestTx) FeeGranter() []byte { + return nil +} + +func (m *recheckTestTx) GetSigners() ([][]byte, error) { + pubKeyBytes := crypto.CompressPubkey(&m.key.PublicKey) + pubKey := ðsecp256k1.PubKey{Key: pubKeyBytes} + return [][]byte{pubKey.Address().Bytes()}, nil +} + +func (m *recheckTestTx) GetPubKeys() ([]cryptotypes.PubKey, error) { + pubKeyBytes := crypto.CompressPubkey(&m.key.PublicKey) + pubKey := ðsecp256k1.PubKey{Key: pubKeyBytes} + return []cryptotypes.PubKey{pubKey}, nil +} + +func (m *recheckTestTx) GetSignaturesV2() ([]signingtypes.SignatureV2, error) { + pubKeyBytes := crypto.CompressPubkey(&m.key.PublicKey) + pubKey := ðsecp256k1.PubKey{Key: pubKeyBytes} + return []signingtypes.SignatureV2{ + { + PubKey: pubKey, + Sequence: m.sequence, + }, + }, nil +} + +// recheckTestAccount holds test account data. +type recheckTestAccount struct { + key *ecdsa.PrivateKey + address common.Address +} + +func newRecheckTestAccount(t *testing.T) recheckTestAccount { + t.Helper() + key, err := crypto.GenerateKey() + require.NoError(t, err) + addr := crypto.PubkeyToAddress(key.PublicKey) + return recheckTestAccount{key: key, address: addr} +} + +func newRecheckTestContext() sdk.Context { + storeKey := storetypes.NewKVStoreKey("test") + transientKey := storetypes.NewTransientStoreKey("transient_test") + return testutil.DefaultContext(storeKey, transientKey) +} + +func noopAnteHandler(ctx sdk.Context, _ sdk.Tx, _ bool) (sdk.Context, error) { + return ctx, nil +} + +// newTestRecheckedTxs creates a HeightSync[CosmosTxStore] for testing, starting at height 0. +func newTestRecheckedTxs() *heightsync.HeightSync[mempool.CosmosTxStore] { + return heightsync.New(big.NewInt(0), mempool.NewCosmosTxStore, log.NewNopLogger()) +} + +// collectIteratorTxs drains an sdkmempool.Iterator into a slice. +func collectIteratorTxs(iter sdkmempool.Iterator) []sdk.Tx { + var txs []sdk.Tx + for iter != nil { + tx := iter.Tx() + if tx == nil { + break + } + txs = append(txs, tx) + iter = iter.Next() + } + return txs +} diff --git a/mempool/rechecker.go b/mempool/rechecker.go new file mode 100644 index 00000000..abf53b34 --- /dev/null +++ b/mempool/rechecker.go @@ -0,0 +1,103 @@ +package mempool + +import ( + "fmt" + + ethtypes "github.com/ethereum/go-ethereum/core/types" + + cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + + "github.com/cosmos/evm/utils" + + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type TxConverter interface { + EVMTxToCosmosTx(tx *ethtypes.Transaction) (sdk.Tx, error) +} + +// TxRechecker runs recheckFn on pending and queued txs in the pool, given an +// sdk context via UpdateCtx. +// +// NOTE: None of the recheckers functions are thread safe. +type TxRechecker struct { + // ctx is the context that rechecks should be run on. Updated by calling + // the returned function from GetContext. + ctx sdk.Context + + anteHandler sdk.AnteHandler + txConverter TxConverter +} + +// NewTxRechecker creates a new rechecker that can recheck transactions. +func NewTxRechecker(anteHandler sdk.AnteHandler, txConverter TxConverter) *TxRechecker { + return &TxRechecker{ + anteHandler: anteHandler, + txConverter: txConverter, + } +} + +// GetContext returns a branched context. The caller can use the returned +// function in order to write updates applied to the returned context, back to +// the context stored by the rechecker for future callers to use. +// +// NOTE: This function is not thread safe with itself or any other Rechecker functions. +func (r *TxRechecker) GetContext() (sdk.Context, func()) { + if r.ctx.MultiStore() == nil { + return sdk.Context{}, func() {} + } + + // CacheContext behavior, but dont emit events back to parent manager, + // rechecking doesnt care about event and we will race on this if we do + cms := r.ctx.MultiStore().CacheMultiStore() + cc := r.ctx.WithMultiStore(cms).WithEventManager(sdk.NewEventManager()) + write := func() { + cms.Write() + } + return cc, write +} + +// RecheckEVM revalidates an EVM transaction against a context. It returns an updated +// context and an error that occurred while processing. +// +// NOTE: This function is not thread safe with itself or any other Rechecker functions. +func (r *TxRechecker) RecheckEVM(ctx sdk.Context, tx *ethtypes.Transaction) (sdk.Context, error) { + cosmosTx, err := r.txConverter.EVMTxToCosmosTx(tx) + if err != nil { + return sdk.Context{}, fmt.Errorf("converting evm tx %s to cosmos tx: %w", tx.Hash(), err) + } + return r.anteHandler(ctx, cosmosTx, false) +} + +// RecheckCosmos revalidates a Cosmos transaction against a context. It returns an updated +// context and an error that occurred while processing. +// +// NOTE: This function is not thread safe with itself or any other Rechecker functions. +func (r *TxRechecker) RecheckCosmos(ctx sdk.Context, tx sdk.Tx) (sdk.Context, error) { + return r.anteHandler(ctx, tx, false) +} + +// Update updates the base context for rechecks based on the latest chain +// state. The caller provides the context directly. +// +// NOTE: This function is not thread safe with itself or any other Rechecker functions. +func (r *TxRechecker) Update(ctx sdk.Context, header *ethtypes.Header) { + cached, _ := ctx.CacheContext() + cached = cached.WithBlockGasMeter(storetypes.NewGasMeter(header.GasLimit)) + cached = cached.WithGasMeter(storetypes.NewInfiniteGasMeter()) + if cached.ConsensusParams().Block == nil { + // On freshly-initialized contexts Block can be nil e.g. + // * the Start path before consensus params are populated + // * the EVM-side path where the ctx didn't come from CometBFT + // That would result in either dereference-panic or skipping the gas-wanted check during antehandler. + // Set the latest blocks gas limit as the max gas in cp to avoid this. + maxGas, err := utils.SafeInt64(header.GasLimit) + if err != nil { + panic(fmt.Errorf("converting evm block gas limit to int64: %w", err)) + } + cp := cmtproto.ConsensusParams{Block: &cmtproto.BlockParams{MaxGas: maxGas}} + cached = cached.WithConsensusParams(cp) + } + r.ctx = cached +} diff --git a/mempool/reserver/reserver.go b/mempool/reserver/reserver.go new file mode 100644 index 00000000..7b3f703e --- /dev/null +++ b/mempool/reserver/reserver.go @@ -0,0 +1,235 @@ +// Copyright 2025 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package reserver + +import ( + "context" + "fmt" + "strconv" + "sync" + + "github.com/ethereum/go-ethereum/common" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/metric" +) + +// ErrAlreadyReserved is returned if the sender address has a pending transaction +// in a different subpool. For example, this error is returned in response to any +// input transaction of non-blob type when a blob transaction from this sender +// remains pending (and vice-versa). +var ErrAlreadyReserved = fmt.Errorf("address already reserved") + +var ( + meter = otel.Meter("github.com/cosmos/evm/mempool/reserver") + + // reservationsGauge is a per-subpool address reservation count, tagged with + // the subpool id. + // + // This is mostly a sanity metric to ensure there's no bug that would make + // some subpool hog all the reservations due to mis-accounting. + reservationsGauge metric.Int64UpDownCounter +) + +// ReservationTracker is a struct shared between different Subpools. It is used to reserve +// the account and ensure that one address cannot initiate transactions, authorizations, +// and other state-changing behaviors in different pools at the same time. +type ReservationTracker struct { + // map account => subpool id + accounts map[common.Address]int + lock sync.RWMutex +} + +// HandlerOpt is an option for creating a ReservationHandle. +type HandlerOpt func(*ReservationHandle) + +// NewReservationTracker initializes the account reservation tracker. +func NewReservationTracker() *ReservationTracker { + return &ReservationTracker{ + accounts: make(map[common.Address]int), + } +} + +func WithRefCounter() HandlerOpt { + return func(h *ReservationHandle) { + h.enableRefCount = true + h.refsCounter = make(map[common.Address]int) + } +} + +// NewHandle creates a named handle on the ReservationTracker. The handle +// identifies the subpool so ownership of reservations can be determined. +func (r *ReservationTracker) NewHandle(id int, opts ...HandlerOpt) *ReservationHandle { + h := &ReservationHandle{ + tracker: r, + id: id, + } + + for _, opt := range opts { + opt(h) + } + + return h +} + +// Reserver is an interface for creating and releasing owned reservations in the +// ReservationTracker struct, which is shared between Subpools. +type Reserver interface { + // Hold attempts to reserve the specified account address for the given pool. + // Returns an error if the account is already reserved. + Hold(addr ...common.Address) error + + // Release attempts to release the reservation for the specified account. + // Returns an error if the address is not reserved or is reserved by another pool. + Release(addr ...common.Address) error + + // Has returns a flag indicating if the address has been reserved by a pool + // other than one with the current Reserver handle. + Has(address common.Address) bool +} + +// ReservationHandle is a named handle on ReservationTracker. It is held by sub-pools +// to make reservations for accounts it is tracking. The id is used to determine +// which sub-pool owns an address and disallows non-owners to hold or release +// addresses it doesn't own. +// +// Additionally, with enableRefCount, the handler will track the refs +// to an address and will only release the address when refs==0 +type ReservationHandle struct { + tracker *ReservationTracker + id int + + enableRefCount bool + + // map account => ref count + refsCounter map[common.Address]int +} + +// Hold atomically reserves all addresses or none. +// Ensure addrs have NO duplicates. +// In most cases addrs is a single item. +func (h *ReservationHandle) Hold(addrs ...common.Address) error { + h.tracker.lock.Lock() + defer h.tracker.lock.Unlock() + + // dry run + for _, addr := range addrs { + if err := h.canHold(addr); err != nil { + return err + } + } + + for _, addr := range addrs { + // add only if not already owned by us + if _, exists := h.tracker.accounts[addr]; !exists { + h.tracker.accounts[addr] = h.id + h.incReservations(1) + } + + if h.enableRefCount { + h.refsCounter[addr]++ + } + } + + return nil +} + +// Release atomically releases all addresses or none. +// Ensure addrs have NO duplicates. +// In most cases addrs is a single item. +func (h *ReservationHandle) Release(addrs ...common.Address) error { + h.tracker.lock.Lock() + defer h.tracker.lock.Unlock() + + // dry run + for _, addr := range addrs { + if err := h.canRelease(addr); err != nil { + return err + } + } + + for _, addr := range addrs { + // simple release + if !h.enableRefCount { + delete(h.tracker.accounts, addr) + h.incReservations(-1) + continue + } + + // release with refsCounter check + if refs, exists := h.refsCounter[addr]; !exists || refs <= 1 { + delete(h.tracker.accounts, addr) + delete(h.refsCounter, addr) + h.incReservations(-1) + } else { + // just decrease the ref count, don't release yet + h.refsCounter[addr]-- + } + } + + return nil +} + +// Has checks that address is already reserved by ANOTHER pool. +func (h *ReservationHandle) Has(address common.Address) bool { + h.tracker.lock.RLock() + defer h.tracker.lock.RUnlock() + + id, exists := h.tracker.accounts[address] + return exists && id != h.id +} + +func (h *ReservationHandle) canHold(addr common.Address) error { + owner, exists := h.tracker.accounts[addr] + + if exists && owner != h.id { + return fmt.Errorf("address %s: %w", addr.String(), ErrAlreadyReserved) + } + + // doesn't exist or already owned by this pool + return nil +} + +func (h *ReservationHandle) canRelease(addr common.Address) error { + owner, exists := h.tracker.accounts[addr] + if !exists { + return fmt.Errorf("address %s not reserved", addr.String()) + } + + if owner != h.id { + return fmt.Errorf("address %s not owned by sub-pool %d", addr.String(), h.id) + } + + return nil +} + +func (h *ReservationHandle) incReservations(n int) { + reservationsGauge.Add(context.Background(), int64(n), metric.WithAttributes( + attribute.String("subpool_id", strconv.Itoa(h.id))), + ) +} + +func init() { + var err error + reservationsGauge, err = meter.Int64UpDownCounter( + "txpool.reservations", + metric.WithDescription("Number of addresses currently reserved by a subpool"), + ) + if err != nil { + panic(err) + } +} diff --git a/mempool/reserver/reserver_test.go b/mempool/reserver/reserver_test.go new file mode 100644 index 00000000..17f2bf76 --- /dev/null +++ b/mempool/reserver/reserver_test.go @@ -0,0 +1,187 @@ +package reserver + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +//nolint:thelper +func TestReserver(t *testing.T) { + accA := common.HexToAddress("0x123") + accB := common.HexToAddress("0x456") + t.Run("Basic", func(t *testing.T) { + for _, tt := range []struct { + name string + run func(t *testing.T, tracker *ReservationTracker, cosmos, evm *ReservationHandle) + }{ + { + name: "holdAlreadyReserved", + run: func(t *testing.T, tracker *ReservationTracker, cosmos, evm *ReservationHandle) { + // ACT + require.NoError(t, evm.Hold(accA)) + err := cosmos.Hold(accA) + + // ASSERT + require.ErrorIs(t, err, ErrAlreadyReserved) + require.True(t, cosmos.Has(accA)) + require.False(t, evm.Has(accA)) + }, + }, + { + name: "releaseNotReserved", + run: func(t *testing.T, tracker *ReservationTracker, cosmos, evm *ReservationHandle) { + // ACT + err := cosmos.Release(accA) + + // ASSERT + require.ErrorContains(t, err, "not reserved") + require.False(t, cosmos.Has(accA)) + require.False(t, evm.Has(accA)) + }, + }, + { + name: "releaseNotOwned", + run: func(t *testing.T, tracker *ReservationTracker, cosmos, evm *ReservationHandle) { + // ACT + require.NoError(t, evm.Hold(accA)) + err := cosmos.Release(accA) + + // ASSERT + require.ErrorContains(t, err, "not owned by sub-pool") + require.True(t, cosmos.Has(accA)) + require.False(t, evm.Has(accA)) + }, + }, + { + name: "holdMultipleAlreadyReservedIsAtomic", + run: func(t *testing.T, tracker *ReservationTracker, cosmos, evm *ReservationHandle) { + // ACT + require.NoError(t, evm.Hold(accA)) + err := cosmos.Hold(accB, accA) + + // ASSERT + require.ErrorIs(t, err, ErrAlreadyReserved) + require.ErrorContains(t, err, accA.String()) + + require.True(t, cosmos.Has(accA)) + require.False(t, evm.Has(accA)) + require.False(t, cosmos.Has(accB)) + require.False(t, evm.Has(accB)) + }, + }, + { + name: "releaseMultipleNotOwnedIsAtomic", + run: func(t *testing.T, tracker *ReservationTracker, cosmos, evm *ReservationHandle) { + // ACT + require.NoError(t, evm.Hold(accA)) + require.NoError(t, cosmos.Hold(accB)) + err := cosmos.Release(accB, accA) + + // ASSERT + require.ErrorContains(t, err, "not owned by sub-pool") + require.True(t, cosmos.Has(accA)) + require.False(t, evm.Has(accA)) + require.False(t, cosmos.Has(accB)) + require.True(t, evm.Has(accB)) + }, + }, + { + name: "holdRelease", + run: func(t *testing.T, tracker *ReservationTracker, cosmos, evm *ReservationHandle) { + // ACT #1 + require.NoError(t, cosmos.Hold(accA)) + + // ASSERT #1 + require.False(t, cosmos.Has(accA)) + require.True(t, evm.Has(accA)) + + // ACT #2 + require.NoError(t, cosmos.Release(accA)) + + // ASSERT #2 + require.False(t, cosmos.Has(accA)) + require.False(t, evm.Has(accA)) + }, + }, + { + name: "holdSeparately", + run: func(t *testing.T, tracker *ReservationTracker, cosmos, evm *ReservationHandle) { + // ACT #1 + require.NoError(t, cosmos.Hold(accA)) + + // ASSERT #1 + require.False(t, cosmos.Has(accA)) + + // ACT #2 + require.NoError(t, evm.Hold(accB)) + + // ASSERT #2 + require.False(t, evm.Has(accB)) + + require.True(t, cosmos.Has(accB)) + require.True(t, evm.Has(accA)) + }, + }, + } { + t.Run(tt.name, func(t *testing.T) { + // ARRANGE + // Given reserver + tracker := NewReservationTracker() + + // Create handles + cosmosID, evmID := tracker.NewHandle(123), tracker.NewHandle(456) + + // ACT + tt.run(t, tracker, cosmosID, evmID) + }) + } + }) + + t.Run("WithRefCounter", func(t *testing.T) { + // ARRANGE + tracker := NewReservationTracker() + cosmos := tracker.NewHandle(123, WithRefCounter()) + evm := tracker.NewHandle(456) + + // ACT + // reserve A by cosmos x2 + err := cosmos.Hold(accA) + require.NoError(t, err) + + err = cosmos.Hold(accA) + require.NoError(t, err) + + // check that we have two reservations + require.Equal(t, 2, cosmos.refsCounter[accA]) + + // unreserve A by cosmos + err = cosmos.Release(accA) + require.NoError(t, err) + + // reserve by evm --> error + err = evm.Hold(accA) + require.ErrorIs(t, err, ErrAlreadyReserved) + + // check that we have one reservation + require.Equal(t, 1, cosmos.refsCounter[accA]) + require.True(t, evm.Has(accA)) + + // unserver by cosmos again + err = cosmos.Release(accA) + require.NoError(t, err) + + // reserve by evm -> OK + err = evm.Hold(accA) + require.NoError(t, err) + + // release by evm -> OK + err = evm.Release(accA) + require.NoError(t, err) + + // release by evm again -> error + err = evm.Release(accA) + require.ErrorContains(t, err, "not reserved") + }) +} diff --git a/mempool/signer.go b/mempool/signer.go index 9422ad3a..b262f980 100644 --- a/mempool/signer.go +++ b/mempool/signer.go @@ -21,8 +21,13 @@ func NewEthSignerExtractionAdapter(fallback mempool.SignerExtractionAdapter) Eth return EthSignerExtractionAdapter{fallback} } -// GetSigners implements the Adapter interface -// NOTE: only the first item is used by the mempool +// GetSigners returns the EVM tx sender. EIP-7702 authorities are NOT enumerated: +// whether each authorization succeeds on chain (and therefore actually bumps +// the authority's nonce) is unverifiable without chain state — a failed +// authorization does not increment the nonce. Eagerly reporting auth.Nonce +// would falsely evict legitimate pending txs from authorities whose auths +// failed. Async reset catches authority nonce advances instead. +// Non-EVM cosmos txs fall through to the SDK default. func (s EthSignerExtractionAdapter) GetSigners(tx sdk.Tx) ([]mempool.SignerData, error) { if txWithExtensions, ok := tx.(authante.HasExtensionOptionsTx); ok { opts := txWithExtensions.GetExtensionOptions() diff --git a/mempool/tx_store.go b/mempool/tx_store.go new file mode 100644 index 00000000..07724ec6 --- /dev/null +++ b/mempool/tx_store.go @@ -0,0 +1,329 @@ +package mempool + +import ( + "fmt" + "slices" + "strconv" + "strings" + "sync" + + "cosmossdk.io/log/v2" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkmempool "github.com/cosmos/cosmos-sdk/types/mempool" +) + +// CosmosTxStore is a set of cosmos transactions that can be added to or +// removed from. +type CosmosTxStore struct { + txs map[string]cosmosTxBucket + nextUnkeyed uint64 + logger log.Logger + signerExtractor sdkmempool.SignerExtractionAdapter + mu sync.RWMutex +} + +type cosmosTxBucket struct { + txs []cosmosTxWithMetadata + signers map[string]struct{} +} + +type cosmosTxWithMetadata struct { + tx sdk.Tx + nonceMap map[string]uint64 + nonceSum uint64 + signerKey string + txKey string +} + +// NewCosmosTxStore creates a new CosmosTxStore. +func NewCosmosTxStore(l log.Logger) *CosmosTxStore { + return &CosmosTxStore{ + txs: make(map[string]cosmosTxBucket), + logger: l, + signerExtractor: sdkmempool.NewDefaultSignerExtractionAdapter(), + } +} + +// AddTx adds a single tx to the store while constructing a validated snapshot. +func (s *CosmosTxStore) AddTx(tx sdk.Tx) { + s.mu.Lock() + defer s.mu.Unlock() + + storedTx := s.newCosmosTxWithMetadata(tx) + if storedTx.signerKey == "" { + storedTx.signerKey = unkeyedSignerKey + } + if storedTx.txKey == "" { + storedTx.txKey = s.newUnkeyedStoreKey() + } + + bucket := s.txs[storedTx.signerKey] + for _, existing := range bucket.txs { + if existing.txKey == storedTx.txKey { + // this should never happen. panicking for safety + s.logger.Warn("attempted to add duplicate tx to CosmosTxStore", "key", storedTx.txKey) + return + } + } + + if bucket.signers == nil { + bucket.signers = signerSetFromNonceMap(storedTx.nonceMap) + } + bucket.txs = append(bucket.txs, storedTx) + slices.SortFunc(bucket.txs, compareCosmosTxWithMetadata) + s.txs[storedTx.signerKey] = bucket +} + +// InvalidateFrom removes any stored tx that depends on the supplied tx's signer/nonces. +// It is used for live mempool replacements: once a tx at nonce N changes, any stored tx +// for the same signer(s) with nonce >= N can no longer be considered valid for proposal building. +func (s *CosmosTxStore) InvalidateFrom(tx sdk.Tx) int { + s.mu.Lock() + defer s.mu.Unlock() + + storedTx := s.newCosmosTxWithMetadata(tx) + + // first check if this tx is already here. If it isn't; no need to do anything. It's a fresh insert. + // If it is, we need to do the work of invaliding any txs from the same sender with a higher nonce. + // nonce thresholds for each signer. + if len(storedTx.nonceMap) == 0 || storedTx.signerKey == "" || storedTx.txKey == "" { + return 0 + } + + bucket, exists := s.txs[storedTx.signerKey] + if !exists { + return 0 + } + if !containsCosmosTx(bucket.txs, storedTx.txKey) { + return 0 + } + + removed := 0 + for signerKey, existingBucket := range s.txs { + if !bucketContainsAnySigner(existingBucket, storedTx.nonceMap) { + continue + } + + next := existingBucket.txs[:0] + for _, existing := range existingBucket.txs { + if invalidatesCosmosTx(existing, storedTx.nonceMap) { + removed++ + continue + } + next = append(next, existing) + } + + clear(existingBucket.txs[len(next):]) + if len(next) == 0 { + delete(s.txs, signerKey) + continue + } + existingBucket.txs = next + s.txs[signerKey] = existingBucket + } + + return removed +} + +func (s *CosmosTxStore) newCosmosTxWithMetadata(tx sdk.Tx) cosmosTxWithMetadata { + storedTx := cosmosTxWithMetadata{tx: tx} + + nonceMap, ok := s.cosmosTxNonceMap(tx) + if !ok { + return storedTx + } + + storedTx.nonceMap = nonceMap + storedTx.nonceSum = cosmosTxNonceSum(nonceMap) + storedTx.signerKey = cosmosTxSignerSetKey(nonceMap) + storedTx.txKey = cosmosTxKey(nonceMap) + return storedTx +} + +const unkeyedSignerKey = "unkeyed" + +func cosmosTxSignerSetKey(nonceMap map[string]uint64) string { + var b strings.Builder + for i, k := range sortedSignerKeys(nonceMap) { + if i > 0 { + b.WriteByte('|') + } + b.WriteString(k) + } + + return b.String() +} + +func cosmosTxKey(nonceMap map[string]uint64) string { + var b strings.Builder + for i, k := range sortedSignerKeys(nonceMap) { + if i > 0 { + b.WriteByte('|') + } + fmt.Fprintf(&b, "%s/%020d", k, nonceMap[k]) + } + + return b.String() +} + +func cosmosTxNonceSum(nonceMap map[string]uint64) uint64 { + var total uint64 + for _, nonce := range nonceMap { + total += nonce + } + return total +} + +// cosmosTxNonceMap extracts the signers from the transaction +// and returns a signer -> nonce map. +func (s *CosmosTxStore) cosmosTxNonceMap(tx sdk.Tx) (map[string]uint64, bool) { + signers, err := s.signerExtractor.GetSigners(tx) + if err != nil || len(signers) == 0 { + return nil, false + } + + nonceMap := make(map[string]uint64, len(signers)) + for _, sig := range signers { + nonce, err := sdkmempool.ChooseNonce(sig.Sequence, tx) + if err != nil { + return nil, false + } + nonceMap[string(sig.Signer)] = nonce + } + + return nonceMap, true +} + +func sortedSignerKeys(nonceMap map[string]uint64) []string { + keys := make([]string, 0, len(nonceMap)) + for k := range nonceMap { + keys = append(keys, k) + } + slices.Sort(keys) + return keys +} + +func invalidatesCosmosTx(tx cosmosTxWithMetadata, thresholds map[string]uint64) bool { + if len(tx.nonceMap) == 0 { + return false + } + + for account, threshold := range thresholds { + nonce, exists := tx.nonceMap[account] + if exists && nonce >= threshold { + return true + } + } + return false +} + +func signerSetFromNonceMap(nonceMap map[string]uint64) map[string]struct{} { + signers := make(map[string]struct{}, len(nonceMap)) + for signer := range nonceMap { + signers[signer] = struct{}{} + } + return signers +} + +func bucketContainsAnySigner(bucket cosmosTxBucket, thresholds map[string]uint64) bool { + for signer := range thresholds { + if _, ok := bucket.signers[signer]; ok { + return true + } + } + return false +} + +func compareCosmosTxWithMetadata(a, b cosmosTxWithMetadata) int { + if a.nonceSum < b.nonceSum { + return -1 + } + if a.nonceSum > b.nonceSum { + return 1 + } + return strings.Compare(a.txKey, b.txKey) +} + +func containsCosmosTx(bucket []cosmosTxWithMetadata, txKey string) bool { + for _, tx := range bucket { + if tx.txKey == txKey { + return true + } + } + return false +} + +func (s *CosmosTxStore) newUnkeyedStoreKey() string { + storeKey := "unkeyed/" + strconv.FormatUint(s.nextUnkeyed, 10) + s.nextUnkeyed++ + return storeKey +} + +func (s *CosmosTxStore) snapshotTxs() []sdk.Tx { + signerKeys := make([]string, 0, len(s.txs)) + for signerKey := range s.txs { + signerKeys = append(signerKeys, signerKey) + } + slices.Sort(signerKeys) + + txs := make([]sdk.Tx, 0) + for _, signerKey := range signerKeys { + bucket := s.txs[signerKey] + for _, tx := range bucket.txs { + txs = append(txs, tx.tx) + } + } + return txs +} + +// Txs returns a copy of the current set of txs in the store. +func (s *CosmosTxStore) Txs() []sdk.Tx { + s.mu.RLock() + defer s.mu.RUnlock() + + return s.snapshotTxs() +} + +// Iterator returns an sdkmempool.Iterator over the txs in the store. +func (s *CosmosTxStore) Iterator() sdkmempool.Iterator { + s.mu.RLock() + defer s.mu.RUnlock() + + if len(s.txs) == 0 { + return nil + } + + // copy the slice so the iterator is not affected by concurrent mutations + return &cosmosTxIterator{txs: s.snapshotTxs()} +} + +// Len returns the number of txs in the store. +func (s *CosmosTxStore) Len() int { + s.mu.RLock() + defer s.mu.RUnlock() + + var total int + for _, bucket := range s.txs { + total += len(bucket.txs) + } + return total +} + +// cosmosTxIterator implements sdkmempool.Iterator over a slice of cosmos txs. +type cosmosTxIterator struct { + txs []sdk.Tx + pos int +} + +func (it *cosmosTxIterator) Tx() sdk.Tx { + return it.txs[it.pos] +} + +func (it *cosmosTxIterator) Next() sdkmempool.Iterator { + if it.pos+1 >= len(it.txs) { + return nil + } + it.pos++ + return it +} diff --git a/mempool/tx_store_test.go b/mempool/tx_store_test.go new file mode 100644 index 00000000..f76510dc --- /dev/null +++ b/mempool/tx_store_test.go @@ -0,0 +1,402 @@ +package mempool + +import ( + "testing" + + "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/require" + protov2 "google.golang.org/protobuf/proto" + + "github.com/cosmos/evm/crypto/ethsecp256k1" + "github.com/cosmos/gogoproto/proto" + + "cosmossdk.io/log/v2" + + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" + signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" + authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" +) + +// mockTx is a minimal sdk.Tx implementation for testing. +type mockTx struct { + id int +} + +var _ sdk.Tx = (*mockTx)(nil) + +func (m *mockTx) GetMsgs() []proto.Message { return nil } +func (m *mockTx) GetMsgsV2() ([]protov2.Message, error) { return nil, nil } + +func newMockTx(id int) sdk.Tx { + return &mockTx{id: id} +} + +type keyedMockTx struct { + pubKey cryptotypes.PubKey + sequence uint64 +} + +type multiKeyedMockTx struct { + pubKeys []cryptotypes.PubKey + sequences []uint64 +} + +type feeKeyedMockTx struct { + pubKey cryptotypes.PubKey + sequence uint64 + gas uint64 + fee sdk.Coins +} + +var ( + _ sdk.Tx = (*keyedMockTx)(nil) + _ authsigning.SigVerifiableTx = (*keyedMockTx)(nil) + _ sdk.Tx = (*multiKeyedMockTx)(nil) + _ authsigning.SigVerifiableTx = (*multiKeyedMockTx)(nil) + _ sdk.Tx = (*feeKeyedMockTx)(nil) + _ authsigning.SigVerifiableTx = (*feeKeyedMockTx)(nil) + _ sdk.FeeTx = (*feeKeyedMockTx)(nil) +) + +func newKeyedMockTx(t *testing.T, sequence uint64) sdk.Tx { + t.Helper() + + key, err := crypto.GenerateKey() + require.NoError(t, err) + + pubKeyBytes := crypto.CompressPubkey(&key.PublicKey) + return newKeyedMockTxWithPubKey(pubKeyBytes, sequence) +} + +func newKeyedMockTxWithPubKey(pubKeyBytes []byte, sequence uint64) sdk.Tx { + return &keyedMockTx{ + pubKey: ðsecp256k1.PubKey{Key: pubKeyBytes}, + sequence: sequence, + } +} + +func (m *keyedMockTx) GetMsgs() []proto.Message { return nil } +func (m *keyedMockTx) GetMsgsV2() ([]protov2.Message, error) { return nil, nil } +func (m *keyedMockTx) GetSigners() ([][]byte, error) { + return [][]byte{m.pubKey.Address().Bytes()}, nil +} + +func (m *keyedMockTx) GetPubKeys() ([]cryptotypes.PubKey, error) { + return []cryptotypes.PubKey{m.pubKey}, nil +} + +func (m *keyedMockTx) GetSignaturesV2() ([]signingtypes.SignatureV2, error) { + return []signingtypes.SignatureV2{{ + PubKey: m.pubKey, + Sequence: m.sequence, + }}, nil +} + +func newMultiKeyedMockTx(pubKeyBytes [][]byte, sequences []uint64) sdk.Tx { + pubKeys := make([]cryptotypes.PubKey, 0, len(pubKeyBytes)) + for _, pubKey := range pubKeyBytes { + pubKeys = append(pubKeys, ðsecp256k1.PubKey{Key: pubKey}) + } + + return &multiKeyedMockTx{ + pubKeys: pubKeys, + sequences: sequences, + } +} + +func (m *multiKeyedMockTx) GetMsgs() []proto.Message { return nil } +func (m *multiKeyedMockTx) GetMsgsV2() ([]protov2.Message, error) { return nil, nil } +func (m *multiKeyedMockTx) GetSigners() ([][]byte, error) { + signers := make([][]byte, 0, len(m.pubKeys)) + for _, pubKey := range m.pubKeys { + signers = append(signers, pubKey.Address().Bytes()) + } + return signers, nil +} + +func (m *multiKeyedMockTx) GetPubKeys() ([]cryptotypes.PubKey, error) { + return m.pubKeys, nil +} + +func (m *multiKeyedMockTx) GetSignaturesV2() ([]signingtypes.SignatureV2, error) { + sigs := make([]signingtypes.SignatureV2, 0, len(m.pubKeys)) + for i, pubKey := range m.pubKeys { + sigs = append(sigs, signingtypes.SignatureV2{ + PubKey: pubKey, + Sequence: m.sequences[i], + }) + } + return sigs, nil +} + +const feeKeyedMockTxDenom = "atest" + +func newFeeKeyedMockTxWithPubKey(pubKeyBytes []byte, sequence uint64, gasPrice int64) sdk.Tx { + const gas uint64 = 100_000 + + return &feeKeyedMockTx{ + pubKey: ðsecp256k1.PubKey{Key: pubKeyBytes}, + sequence: sequence, + gas: gas, + fee: sdk.NewCoins(sdk.NewInt64Coin(feeKeyedMockTxDenom, gasPrice*int64(gas))), + } +} + +func (m *feeKeyedMockTx) GetMsgs() []proto.Message { return nil } +func (m *feeKeyedMockTx) GetMsgsV2() ([]protov2.Message, error) { return nil, nil } +func (m *feeKeyedMockTx) GetSigners() ([][]byte, error) { + return [][]byte{m.pubKey.Address().Bytes()}, nil +} + +func (m *feeKeyedMockTx) GetPubKeys() ([]cryptotypes.PubKey, error) { + return []cryptotypes.PubKey{m.pubKey}, nil +} + +func (m *feeKeyedMockTx) GetSignaturesV2() ([]signingtypes.SignatureV2, error) { + return []signingtypes.SignatureV2{{ + PubKey: m.pubKey, + Sequence: m.sequence, + }}, nil +} + +func (m *feeKeyedMockTx) GetGas() uint64 { + return m.gas +} + +func (m *feeKeyedMockTx) GetFee() sdk.Coins { + return m.fee +} + +func (m *feeKeyedMockTx) FeePayer() []byte { + return m.pubKey.Address().Bytes() +} + +func (m *feeKeyedMockTx) FeeGranter() []byte { + return nil +} + +func TestCosmosTxStoreAddAndGet(t *testing.T) { + store := NewCosmosTxStore(log.NewNopLogger()) + + tx1 := newMockTx(1) + tx2 := newMockTx(2) + tx3 := newMockTx(3) + + store.AddTx(tx1) + store.AddTx(tx2) + store.AddTx(tx3) + + txs := store.Txs() + require.Len(t, txs, 3) +} + +func TestCosmosTxStoreDedup(t *testing.T) { + store := NewCosmosTxStore(log.NewNopLogger()) + + tx := newKeyedMockTx(t, 1) + + store.AddTx(tx) + store.AddTx(tx) + store.AddTx(tx) + + require.Equal(t, 1, store.Len()) +} + +func TestCosmosTxStoreIterator(t *testing.T) { + store := NewCosmosTxStore(log.NewNopLogger()) + + tx1 := newMockTx(1) + tx2 := newMockTx(2) + tx3 := newMockTx(3) + + store.AddTx(tx1) + store.AddTx(tx2) + store.AddTx(tx3) + + iter := store.Iterator() + require.NotNil(t, iter) + + var collected []sdk.Tx + for ; iter != nil; iter = iter.Next() { + collected = append(collected, iter.Tx()) + } + require.Len(t, collected, 3) +} + +func TestCosmosTxStoreIteratorEmpty(t *testing.T) { + store := NewCosmosTxStore(log.NewNopLogger()) + require.Nil(t, store.Iterator()) +} + +func TestCosmosTxStoreIteratorSnapshotIsolation(t *testing.T) { + store := NewCosmosTxStore(log.NewNopLogger()) + + tx1 := newMockTx(1) + tx2 := newMockTx(2) + + store.AddTx(tx1) + store.AddTx(tx2) + + iter := store.Iterator() + require.NotNil(t, iter) + + // mutate the store after creating the iterator + store.AddTx(newMockTx(3)) + + // iterator should still see the original 2 txs + var count int + for ; iter != nil; iter = iter.Next() { + count++ + } + require.Equal(t, 2, count) +} + +func TestCosmosTxStoreOrdersBucketByNonceSum(t *testing.T) { + store := NewCosmosTxStore(log.NewNopLogger()) + + key, err := crypto.GenerateKey() + require.NoError(t, err) + + pubKeyBytes := crypto.CompressPubkey(&key.PublicKey) + tx3 := newKeyedMockTxWithPubKey(pubKeyBytes, 3) + tx1 := newKeyedMockTxWithPubKey(pubKeyBytes, 1) + tx2 := newKeyedMockTxWithPubKey(pubKeyBytes, 2) + + store.AddTx(tx3) + store.AddTx(tx1) + store.AddTx(tx2) + + require.Equal(t, []sdk.Tx{tx1, tx2, tx3}, store.Txs()) +} + +func TestCosmosTxStoreOrderedIteratorByPriceAndNonce(t *testing.T) { + store := NewCosmosTxStore(log.NewNopLogger()) + + keyA, err := crypto.GenerateKey() + require.NoError(t, err) + keyB, err := crypto.GenerateKey() + require.NoError(t, err) + + txA0 := newFeeKeyedMockTxWithPubKey(crypto.CompressPubkey(&keyA.PublicKey), 0, 1) + txA1 := newFeeKeyedMockTxWithPubKey(crypto.CompressPubkey(&keyA.PublicKey), 1, 100) + txB0 := newFeeKeyedMockTxWithPubKey(crypto.CompressPubkey(&keyB.PublicKey), 0, 5) + + store.AddTx(txA0) + store.AddTx(txA1) + store.AddTx(txB0) + + iter := store.OrderedIterator(feeKeyedMockTxDenom, nil) + var txs []sdk.Tx + for ; iter != nil; iter = iter.Next() { + txs = append(txs, iter.Tx()) + } + require.Equal(t, []sdk.Tx{txB0, txA0, txA1}, txs) +} + +func TestCosmosTxStoreInvalidateFromUsesStoredNonceMap(t *testing.T) { + store := NewCosmosTxStore(log.NewNopLogger()) + + key, err := crypto.GenerateKey() + require.NoError(t, err) + + pubKeyBytes := crypto.CompressPubkey(&key.PublicKey) + tx1 := newKeyedMockTxWithPubKey(pubKeyBytes, 1) + tx2 := newKeyedMockTxWithPubKey(pubKeyBytes, 2) + tx3 := newKeyedMockTxWithPubKey(pubKeyBytes, 3) + + store.AddTx(tx1) + store.AddTx(tx2) + store.AddTx(tx3) + + removed := store.InvalidateFrom(tx2) + require.Equal(t, 2, removed) + require.Equal(t, []sdk.Tx{tx1}, store.Txs()) +} + +func TestCosmosTxStoreInvalidateFromFreshTxNoOp(t *testing.T) { + store := NewCosmosTxStore(log.NewNopLogger()) + + key, err := crypto.GenerateKey() + require.NoError(t, err) + + pubKeyBytes := crypto.CompressPubkey(&key.PublicKey) + tx1 := newKeyedMockTxWithPubKey(pubKeyBytes, 1) + tx2 := newKeyedMockTxWithPubKey(pubKeyBytes, 2) + + store.AddTx(tx1) + + removed := store.InvalidateFrom(tx2) + require.Zero(t, removed) + require.Equal(t, []sdk.Tx{tx1}, store.Txs()) +} + +func TestCosmosTxStoreInvalidateFromCrossesSignerBuckets(t *testing.T) { + store := NewCosmosTxStore(log.NewNopLogger()) + + bobKey, err := crypto.GenerateKey() + require.NoError(t, err) + aliceKey, err := crypto.GenerateKey() + require.NoError(t, err) + + bobPubKey := crypto.CompressPubkey(&bobKey.PublicKey) + alicePubKey := crypto.CompressPubkey(&aliceKey.PublicKey) + + bobTx4 := newKeyedMockTxWithPubKey(bobPubKey, 4) + bobTx5 := newKeyedMockTxWithPubKey(bobPubKey, 5) + multiTx7 := newMultiKeyedMockTx([][]byte{alicePubKey, bobPubKey}, []uint64{7, 7}) + multiTx8 := newMultiKeyedMockTx([][]byte{alicePubKey, bobPubKey}, []uint64{8, 8}) + + store.AddTx(bobTx4) + store.AddTx(bobTx5) + store.AddTx(multiTx7) + store.AddTx(multiTx8) + + removed := store.InvalidateFrom(bobTx5) + require.Equal(t, 3, removed) + + txs := store.Txs() + require.Equal(t, []sdk.Tx{bobTx4}, txs) +} + +func TestCosmosTxStoreInvalidateFromMultiSignerEvictsSingleSigner(t *testing.T) { + store := NewCosmosTxStore(log.NewNopLogger()) + + aliceKey, err := crypto.GenerateKey() + require.NoError(t, err) + bobKey, err := crypto.GenerateKey() + require.NoError(t, err) + carolKey, err := crypto.GenerateKey() + require.NoError(t, err) + eveKey, err := crypto.GenerateKey() + require.NoError(t, err) + + alicePubKey := crypto.CompressPubkey(&aliceKey.PublicKey) + bobPubKey := crypto.CompressPubkey(&bobKey.PublicKey) + carolPubKey := crypto.CompressPubkey(&carolKey.PublicKey) + evePubKey := crypto.CompressPubkey(&eveKey.PublicKey) + + aliceTx5 := newKeyedMockTxWithPubKey(alicePubKey, 5) + bobTx3 := newKeyedMockTxWithPubKey(bobPubKey, 3) // below B-threshold; survives + bobTx5 := newKeyedMockTxWithPubKey(bobPubKey, 5) // at B-threshold; evicted + carolTx7 := newKeyedMockTxWithPubKey(carolPubKey, 7) // above C-threshold; evicted + eveTx9 := newKeyedMockTxWithPubKey(evePubKey, 9) // unrelated signer; survives + + multiTx := newMultiKeyedMockTx( + [][]byte{alicePubKey, bobPubKey, carolPubKey}, + []uint64{5, 5, 5}, + ) + + store.AddTx(aliceTx5) + store.AddTx(bobTx3) + store.AddTx(bobTx5) + store.AddTx(carolTx7) + store.AddTx(eveTx9) + store.AddTx(multiTx) + + removed := store.InvalidateFrom(multiTx) + // evicted: aliceTx5 (A:5>=5), bobTx5 (B:5>=5), carolTx7 (C:7>=5), multiTx itself. + require.Equal(t, 4, removed) + + require.ElementsMatch(t, []sdk.Tx{bobTx3, eveTx9}, store.Txs()) +} diff --git a/mempool/txpool/errors.go b/mempool/txpool/errors.go index 968c9d95..5afe0978 100644 --- a/mempool/txpool/errors.go +++ b/mempool/txpool/errors.go @@ -58,12 +58,6 @@ var ( // making the transaction invalid, rather a DOS protection. ErrOversizedData = errors.New("oversized data") - // ErrAlreadyReserved is returned if the sender address has a pending transaction - // in a different subpool. For example, this error is returned in response to any - // input transaction of non-blob type when a blob transaction from this sender - // remains pending (and vice-versa). - ErrAlreadyReserved = errors.New("address already reserved") - // ErrInflightTxLimitReached is returned when the maximum number of in-flight // transactions is reached for specific accounts. ErrInflightTxLimitReached = errors.New("in-flight transaction limit reached for delegated accounts") diff --git a/mempool/txpool/legacypool/commit_lock_default.go b/mempool/txpool/legacypool/commit_lock_default.go new file mode 100644 index 00000000..59074a98 --- /dev/null +++ b/mempool/txpool/legacypool/commit_lock_default.go @@ -0,0 +1,6 @@ +//go:build !race + +package legacypool + +// beginCommitRead is a no-op in non-race builds to avoid unnecessary overhead. +func beginCommitRead(_ any) func() { return func() {} } diff --git a/mempool/txpool/legacypool/commit_lock_race.go b/mempool/txpool/legacypool/commit_lock_race.go new file mode 100644 index 00000000..eea7c53d --- /dev/null +++ b/mempool/txpool/legacypool/commit_lock_race.go @@ -0,0 +1,21 @@ +//go:build race + +package legacypool + +// commitAwareChain is implemented by chains that expose optional commit RW locks. +// These are used to coordinate background readers with Commit in tests/race builds. +type commitAwareChain interface { + BeginRead() + EndRead() +} + +// beginCommitRead acquires a shared read lock when available and returns a +// function that releases it. In race/test builds this coordinates with Commit +// to avoid read/write races in storage. In non-race builds this is a no-op. +func beginCommitRead(chain any) func() { + if ca, ok := chain.(commitAwareChain); ok { + ca.BeginRead() + return func() { ca.EndRead() } + } + return func() {} +} diff --git a/mempool/txpool/legacypool/legacypool.go b/mempool/txpool/legacypool/legacypool.go index e82c260c..6de5d501 100644 --- a/mempool/txpool/legacypool/legacypool.go +++ b/mempool/txpool/legacypool/legacypool.go @@ -18,15 +18,25 @@ package legacypool import ( + "context" "errors" + "fmt" "maps" "math/big" "slices" "sort" + "strings" "sync" "sync/atomic" "time" + cosmoslog "cosmossdk.io/log/v2" + "github.com/cosmos/evm/mempool/internal/heightsync" + "github.com/cosmos/evm/mempool/internal/reaplist" + "github.com/cosmos/evm/mempool/internal/txtracker" + "github.com/cosmos/evm/mempool/reserver" + lru "github.com/hashicorp/golang-lru/v2" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/prque" "github.com/ethereum/go-ethereum/consensus/misc/eip1559" @@ -36,14 +46,18 @@ import ( "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/holiman/uint256" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/metric" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/evm/mempool/txpool" ) +var meter = otel.Meter("github.com/cosmos/evm/mempool/txpool/legacypool") + const ( // txSlotSize is used to calculate how many data slots a single transaction // takes up based on its size. The slots are used as DoS protection, ensuring @@ -82,41 +96,212 @@ var ( statsReportInterval = 8 * time.Second // Time interval to report transaction pool stats ) +const ( + RemovalReasonLifetime txpool.RemovalReason = "lifetime" // Tx has been in queued for too long + RemovalReasonBelowTip txpool.RemovalReason = "belowtip" // Min gas tip changed and these txs are too low + RemovalReasonTruncatedOverflow txpool.RemovalReason = "truncated_overflow" // We have to truncate a pool and this account has too many txs + RemovalReasonTruncatedLast txpool.RemovalReason = "truncated_last" // We have to truncate a pool and these txs are the last ones in so they are the first out + RemovalReasonUnderpricedFull txpool.RemovalReason = "underpriced_full" // New tx came in that has a better price. The pool is also full so we kicked a tx out to make room. + RemovalReasonCapExceeded txpool.RemovalReason = "capped" // Too many txs for this account + RemovalReasonRunTxRecheck txpool.RemovalReason = "runtx_recheck" + RemovalReasonRunTxFinalize txpool.RemovalReason = "runtx_finalize" + RemovalReasonPrepareProposalInvalid txpool.RemovalReason = "prepare_proposal_invalid" +) + var ( + // Specific removal metrics + // Queue pool + queuedRemovedLifetime metric.Int64Counter + queuedRemovedBelowTip metric.Int64Counter + queuedRemovedTruncatedOverflow metric.Int64Counter + queuedRemovedTruncatedLast metric.Int64Counter + queuedRemovedUnderpricedFull metric.Int64Counter + queuedRemovedOld metric.Int64Counter + queuedRemovedCapped metric.Int64Counter + queuedRemovedRunTxRecheck metric.Int64Counter + queuedRemovedRunTxFinalize metric.Int64Counter + queuedRemovedPrepareProposal metric.Int64Counter + queuedRemovedUnknown metric.Int64Counter + // Pending pool + pendingRemovedLifetime metric.Int64Counter + pendingRemovedBelowTip metric.Int64Counter + pendingRemovedTruncatedOverflow metric.Int64Counter + pendingRemovedTruncatedLast metric.Int64Counter + pendingRemovedUnderpricedFull metric.Int64Counter + pendingRemovedOld metric.Int64Counter + pendingRemovedCostly metric.Int64Counter + pendingRemovedCapped metric.Int64Counter + pendingRemovedRunTxRecheck metric.Int64Counter + pendingRemovedRunTxFinalize metric.Int64Counter + pendingRemovedPrepareProposal metric.Int64Counter + pendingRemovedUnknown metric.Int64Counter + // Metrics for the pending pool - pendingDiscardMeter = metrics.NewRegisteredMeter("txpool/pending/discard", nil) - pendingReplaceMeter = metrics.NewRegisteredMeter("txpool/pending/replace", nil) - pendingRateLimitMeter = metrics.NewRegisteredMeter("txpool/pending/ratelimit", nil) // Dropped due to rate limiting - pendingNofundsMeter = metrics.NewRegisteredMeter("txpool/pending/nofunds", nil) // Dropped due to out-of-funds + pendingDiscardMeter metric.Int64Counter + pendingReplaceMeter metric.Int64Counter + pendingRateLimitMeter metric.Int64Counter // Dropped due to rate limiting + pendingRecheckDropMeter metric.Int64Counter // Dropped due to recheck failing + pendingRecheckDurationTimer metric.Float64Histogram // How long rechecking txs in the pending pool takes (demoteUnexecutables) + pendingTruncateTimer metric.Float64Histogram // How long truncating the pending pool takes + pendingDemotedRecheck metric.Int64Counter // Demoted due to parent tx failing recheck + pendingDemotedRemoved metric.Int64Counter // Demoted due to parent tx being explicitly removed + pendingDemotedCancelled metric.Int64Counter // Demote loop cancelled due to a new block arriving + + // Metrics for queued promotions + queuedPromotedCancelled metric.Int64Counter // Promote loop cancelled due to a new block arriving // Metrics for the queued pool - queuedDiscardMeter = metrics.NewRegisteredMeter("txpool/queued/discard", nil) - queuedReplaceMeter = metrics.NewRegisteredMeter("txpool/queued/replace", nil) - queuedRateLimitMeter = metrics.NewRegisteredMeter("txpool/queued/ratelimit", nil) // Dropped due to rate limiting - queuedNofundsMeter = metrics.NewRegisteredMeter("txpool/queued/nofunds", nil) // Dropped due to out-of-funds - queuedEvictionMeter = metrics.NewRegisteredMeter("txpool/queued/eviction", nil) // Dropped due to lifetime + queuedDiscardMeter metric.Int64Counter + queuedReplaceMeter metric.Int64Counter + queuedRateLimitMeter metric.Int64Counter // Dropped due to rate limiting + queuedNofundsMeter metric.Int64Counter // Dropped due to out-of-funds + queuedEvictionMeter metric.Int64Counter // Dropped due to lifetime + queuedRecheckDropMeter metric.Int64Counter // Dropped due to antehandler failing + queuedRecheckDurationTimer metric.Float64Histogram // How long rechecking txs in the queued pool takes (promoteExecutables) + queuedNonReadies metric.Int64Counter // Number of txs that were not ready to be promoted due to a nonce gap during promote loop // General tx metrics - knownTxMeter = metrics.NewRegisteredMeter("txpool/known", nil) - validTxMeter = metrics.NewRegisteredMeter("txpool/valid", nil) - invalidTxMeter = metrics.NewRegisteredMeter("txpool/invalid", nil) - underpricedTxMeter = metrics.NewRegisteredMeter("txpool/underpriced", nil) - overflowedTxMeter = metrics.NewRegisteredMeter("txpool/overflowed", nil) + knownTxMeter metric.Int64Counter + validTxMeter metric.Int64Counter + invalidTxMeter metric.Int64Counter + underpricedTxMeter metric.Int64Counter + overflowedTxMeter metric.Int64Counter // throttleTxMeter counts how many transactions are rejected due to too-many-changes between // txpool reorgs. - throttleTxMeter = metrics.NewRegisteredMeter("txpool/throttle", nil) + throttleTxMeter metric.Int64Counter + // reorgDurationTimer measures how long time a txpool reorg takes. - reorgDurationTimer = metrics.NewRegisteredTimer("txpool/reorgtime", nil) + reorgDurationTimer metric.Float64Histogram + // reorgResetTimer measures how long a txpool reorg takes when it is resetting. + reorgResetTimer metric.Float64Histogram + // demoteTimer measures how long demoting transactions in the pending pool takes + demoteTimer metric.Float64Histogram + // dropBetweenReorgHistogram counts how many drops we experience between two reorg runs. It is expected // that this number is pretty low, since txpool reorgs happen very frequently. - dropBetweenReorgHistogram = metrics.NewRegisteredHistogram("txpool/dropbetweenreorg", nil, metrics.NewExpDecaySample(1028, 0.015)) + dropBetweenReorgHistogram metric.Int64Histogram - pendingGauge = metrics.NewRegisteredGauge("txpool/pending", nil) - queuedGauge = metrics.NewRegisteredGauge("txpool/queued", nil) - slotsGauge = metrics.NewRegisteredGauge("txpool/slots", nil) + pendingGauge metric.Int64UpDownCounter + queuedGauge metric.Int64UpDownCounter + slotsGauge metric.Int64Gauge - reheapTimer = metrics.NewRegisteredTimer("txpool/reheap", nil) + reheapTimer metric.Float64Histogram +) + +func init() { + counter := func(name, desc string) metric.Int64Counter { + m, err := meter.Int64Counter(name, metric.WithDescription(desc)) + if err != nil { + panic(err) + } + return m + } + timer := func(name, desc string) metric.Float64Histogram { + m, err := meter.Float64Histogram(name, metric.WithDescription(desc), metric.WithUnit("ms")) + if err != nil { + panic(err) + } + return m + } + + queuedRemovedLifetime = counter("txpool.queued.removed.lifetime", "Queued txs removed due to lifetime") + queuedRemovedBelowTip = counter("txpool.queued.removed.belowtip", "Queued txs removed due to min gas tip change") + queuedRemovedTruncatedOverflow = counter("txpool.queued.removed.truncated_overflow", "Queued txs removed due to truncation overflow") + queuedRemovedTruncatedLast = counter("txpool.queued.removed.truncated_last", "Queued txs removed as last-in during truncation") + queuedRemovedUnderpricedFull = counter("txpool.queued.removed.underpriced_full", "Queued txs removed to make room for better priced tx") + queuedRemovedOld = counter("txpool.queued.removed.old", "Queued txs removed due to nonce being too old") + queuedRemovedCapped = counter("txpool.queued.removed.capped", "Queued txs removed due to per-account cap") + queuedRemovedRunTxRecheck = counter("txpool.queued.removed.runtx_recheck", "Queued txs removed due to RunTx recheck failure") + queuedRemovedRunTxFinalize = counter("txpool.queued.removed.runtx_finalize", "Queued txs removed due to RunTx finalize") + queuedRemovedPrepareProposal = counter("txpool.queued.removed.prepare_proposal_invalid", "Queued txs removed as invalid during PrepareProposal") + queuedRemovedUnknown = counter("txpool.queued.removed.unknown", "Queued txs removed for an unknown reason") + + pendingRemovedLifetime = counter("txpool.pending.removed.lifetime", "Pending txs removed due to lifetime") + pendingRemovedBelowTip = counter("txpool.pending.removed.belowtip", "Pending txs removed due to min gas tip change") + pendingRemovedTruncatedOverflow = counter("txpool.pending.removed.truncated_overflow", "Pending txs removed due to truncation overflow") + pendingRemovedTruncatedLast = counter("txpool.pending.removed.truncated_last", "Pending txs removed as last-in during truncation") + pendingRemovedUnderpricedFull = counter("txpool.pending.removed.underpriced_full", "Pending txs removed to make room for better priced tx") + pendingRemovedOld = counter("txpool.pending.removed.old", "Pending txs removed due to nonce being too old") + pendingRemovedCostly = counter("txpool.pending.removed.costly", "Pending txs removed as too costly") + pendingRemovedCapped = counter("txpool.pending.removed.capped", "Pending txs removed due to per-account cap") + pendingRemovedRunTxRecheck = counter("txpool.pending.removed.runtx_recheck", "Pending txs removed due to RunTx recheck failure") + pendingRemovedRunTxFinalize = counter("txpool.pending.removed.runtx_finalize", "Pending txs removed due to RunTx finalize") + pendingRemovedPrepareProposal = counter("txpool.pending.removed.prepare_proposal_invalid", "Pending txs removed as invalid during PrepareProposal") + pendingRemovedUnknown = counter("txpool.pending.removed.unknown", "Pending txs removed for an unknown reason") + + pendingDiscardMeter = counter("txpool.pending.discard", "Pending txs discarded") + pendingReplaceMeter = counter("txpool.pending.replace", "Pending txs replaced") + pendingRateLimitMeter = counter("txpool.pending.ratelimit", "Pending txs dropped due to rate limiting") + pendingRecheckDropMeter = counter("txpool.pending.recheckdrop", "Pending txs dropped due to recheck failing") + pendingRecheckDurationTimer = timer("txpool.pending.rechecktime", "Time to recheck txs in the pending pool (demoteUnexecutables)") + pendingTruncateTimer = timer("txpool.pending.truncate", "Time to truncate the pending pool") + pendingDemotedRecheck = counter("txpool.pending.demoted.recheck", "Pending txs demoted due to parent tx failing recheck") + pendingDemotedRemoved = counter("txpool.pending.demoted.removed", "Pending txs demoted due to parent tx being explicitly removed") + pendingDemotedCancelled = counter("txpool.pending.demoted.cancelled", "Demote loop cancelled due to new block arrival") + + queuedPromotedCancelled = counter("txpool.queued.promoted.cancelled", "Promote loop cancelled due to new block arrival") + + queuedDiscardMeter = counter("txpool.queued.discard", "Queued txs discarded") + queuedReplaceMeter = counter("txpool.queued.replace", "Queued txs replaced") + queuedRateLimitMeter = counter("txpool.queued.ratelimit", "Queued txs dropped due to rate limiting") + queuedNofundsMeter = counter("txpool.queued.nofunds", "Queued txs dropped due to out-of-funds") + queuedEvictionMeter = counter("txpool.queued.eviction", "Queued txs dropped due to lifetime") + queuedRecheckDropMeter = counter("txpool.queued.recheckdrop", "Queued txs dropped due to antehandler failure") + queuedRecheckDurationTimer = timer("txpool.queued.rechecktime", "Time to recheck txs in the queued pool (promoteExecutables)") + queuedNonReadies = counter("txpool.queued.notready", "Queued txs not ready for promotion due to nonce gap") + + knownTxMeter = counter("txpool.known", "Txs discarded as already known") + validTxMeter = counter("txpool.valid", "Txs deemed valid by the pool") + invalidTxMeter = counter("txpool.invalid", "Txs discarded as invalid") + underpricedTxMeter = counter("txpool.underpriced", "Txs discarded as underpriced") + overflowedTxMeter = counter("txpool.overflowed", "Txs discarded due to pool overflow") + + throttleTxMeter = counter("txpool.throttle", "Txs rejected due to too-many-changes between reorgs") + + reorgDurationTimer = timer("txpool.reorgtime", "Time taken to run a txpool reorg") + reorgResetTimer = timer("txpool.resettime", "Time taken to reset state during a txpool reorg") + demoteTimer = timer("txpool.demotetime", "Time taken to demote txs in the pending pool") + + var err error + dropBetweenReorgHistogram, err = meter.Int64Histogram( + "txpool.dropbetweenreorg", + metric.WithDescription("Number of drops observed between two reorg runs"), + ) + if err != nil { + panic(err) + } + + pendingGauge, err = meter.Int64UpDownCounter( + "txpool.pending", + metric.WithDescription("Current number of txs in the pending pool"), + ) + if err != nil { + panic(err) + } + queuedGauge, err = meter.Int64UpDownCounter( + "txpool.queued", + metric.WithDescription("Current number of txs in the queued pool"), + ) + if err != nil { + panic(err) + } + slotsGauge, err = meter.Int64Gauge( + "txpool.slots", + metric.WithDescription("Current number of slots in use by tracked txs"), + ) + if err != nil { + panic(err) + } + + reheapTimer = timer("txpool.reheap", "Time taken to reheap the priced list") +} + +type PoolType string + +const ( + Pending PoolType = "pending" + Queue PoolType = "queue" ) // BlockChain defines the minimal set of methods needed to back a tx pool with @@ -133,6 +318,26 @@ type BlockChain interface { // StateAt returns a state database for a given root hash (generally the head). StateAt(root common.Hash) (vm.StateDB, error) + + // GetLatestContext returns the latest SDK context for the chain. + GetLatestContext() (sdk.Context, error) +} + +// Rechecker defines the minimal set of methods needed to recheck transactions +// and manage the context that the transactions are rechecked against. +type Rechecker interface { + // GetContext gets a branch of the current context that transactions should + // be rechecked against. Changes to ctx will only be persisted back to the + // Reckecker once the write function is invoked. + GetContext() (ctx sdk.Context, write func()) + + // RecheckEVM performs validation of an EVM tx against a context, and + // returns an updated context. + RecheckEVM(ctx sdk.Context, tx *types.Transaction) (sdk.Context, error) + + // Update updates the main context returned by GetContext to be the base + // chain context at header. The caller provides the SDK context directly. + Update(ctx sdk.Context, header *types.Header) } // Config are the configuration parameters of the transaction pool. @@ -151,6 +356,8 @@ type Config struct { GlobalQueue uint64 // Maximum number of non-executable transaction slots for all accounts Lifetime time.Duration // Maximum amount of time non-executable transaction are queued + + IncludedNonceCacheSize int // Max entries in the included nonce LRU cache } // DefaultConfig contains the default configurations for the transaction pool. @@ -167,6 +374,8 @@ var DefaultConfig = Config{ GlobalQueue: 1024, Lifetime: 3 * time.Hour, + + IncludedNonceCacheSize: 4096, // should be >= max txs expected in a block for best perf } // sanitize checks the provided user configurations and changes anything that's @@ -201,6 +410,10 @@ func (config *Config) sanitize() Config { log.Warn("Sanitizing invalid txpool lifetime", "provided", conf.Lifetime, "updated", DefaultConfig.Lifetime) conf.Lifetime = DefaultConfig.Lifetime } + if conf.IncludedNonceCacheSize < 1 { + log.Warn("Sanitizing invalid txpool included nonce cache size", "provided", conf.IncludedNonceCacheSize, "updated", DefaultConfig.IncludedNonceCacheSize) + conf.IncludedNonceCacheSize = DefaultConfig.IncludedNonceCacheSize + } return conf } @@ -234,10 +447,15 @@ type LegacyPool struct { signer types.Signer mu sync.RWMutex - currentHead atomic.Pointer[types.Header] // Current head of the blockchain - currentState vm.StateDB // Current state in the blockchain head - pendingNonces *noncer // Pending state tracking virtual nonces - reserver txpool.Reserver // Address reserver to ensure exclusivity across subpools + currentHead atomic.Pointer[types.Header] // Current head of the blockchain + currentState vm.StateDB // Current state in the blockchain head + pendingNonces *noncer // Pending state tracking virtual nonces + latestIncludedNonce *lru.Cache[common.Address, uint64] // Cache of latest nonce seen executed on chain for accounts + reserver reserver.Reserver // Address reserver to ensure exclusivity across subpools + rechecker Rechecker // Checks a tx for validity against the current state + + validPendingTxs *heightsync.HeightSync[TxStore] // Per height store of pending txs that have been validated + toReap map[common.Hash]struct{} // Transactions that should be reaped after their next recheck pending map[common.Address]*list // All currently processable transactions queue map[common.Address]*list // Queued but non-processable transactions @@ -245,51 +463,124 @@ type LegacyPool struct { all *lookup // All transactions to allow lookups priced *pricedList // All transactions sorted by price - reqResetCh chan *txpoolResetRequest - reqPromoteCh chan *accountSet - queueTxEventCh chan *types.Transaction - reorgDoneCh chan chan struct{} - reorgShutdownCh chan struct{} // requests shutdown of scheduleReorgLoop - wg sync.WaitGroup // tracks loop, scheduleReorgLoop - initDoneCh chan struct{} // is closed once the pool is initialized (for tests) + reqResetCh chan *txpoolResetRequest + reqPromoteCh chan *accountSet + reqCancelResetCh chan struct{} + queueTxEventCh chan *types.Transaction + reorgDoneCh chan chan struct{} + reorgShutdownCh chan struct{} // requests shutdown of scheduleReorgLoop + wg sync.WaitGroup // tracks loop, scheduleReorgLoop + initDoneCh chan struct{} // is closed once the pool is initialized (for tests) changesSinceReorg int // A counter for how many drops we've performed in-between reorg. - BroadcastTxFn func(txs []*types.Transaction) error + reapList *reaplist.ReapList // Queue of txs to be reaped by comet and gossiped + tracker txtracker.Tracker // Track tx lifecycle events for metrics } type txpoolResetRequest struct { oldHead, newHead *types.Header } +// Option is a function that sets an optional parameter on the legacypool +type Option func(pool *LegacyPool) + +// WithRecheck enables recheck evicting of transactions from the mempool. +func WithRecheck(rechecker Rechecker) Option { + return func(pool *LegacyPool) { + pool.rechecker = rechecker + } +} + // New creates a new transaction pool to gather, sort and filter inbound -// transactions from the network. -func New(config Config, chain BlockChain) *LegacyPool { +// transactions from the network. reapList and tracker are required: they +// observe every pending-pool transition and are load-bearing for both +// broadcast (reapList) and telemetry (tracker). +func New( + config Config, + logger cosmoslog.Logger, + chain BlockChain, + reapList *reaplist.ReapList, + tracker txtracker.Tracker, + opts ...Option, +) *LegacyPool { + if reapList == nil { + panic("legacypool: reapList must not be nil") + } + if tracker == nil { + panic("legacypool: tracker must not be nil") + } // Sanitize the input to ensure no vulnerable gas prices are set config = (&config).sanitize() + // only errors if size <= 0 and we have already validated this + nonceCache, _ := lru.New[common.Address, uint64](config.IncludedNonceCacheSize) + // Create the transaction pool with its initial settings pool := &LegacyPool{ - config: config, - chain: chain, - chainconfig: chain.Config(), - signer: types.LatestSigner(chain.Config()), - pending: make(map[common.Address]*list), - queue: make(map[common.Address]*list), - beats: make(map[common.Address]time.Time), - all: newLookup(), - reqResetCh: make(chan *txpoolResetRequest), - reqPromoteCh: make(chan *accountSet), - queueTxEventCh: make(chan *types.Transaction), - reorgDoneCh: make(chan chan struct{}), - reorgShutdownCh: make(chan struct{}), - initDoneCh: make(chan struct{}), + config: config, + chain: chain, + chainconfig: chain.Config(), + signer: types.LatestSigner(chain.Config()), + pending: make(map[common.Address]*list), + queue: make(map[common.Address]*list), + beats: make(map[common.Address]time.Time), + all: newLookup(), + rechecker: newNopRechecker(), + reapList: reapList, + tracker: tracker, + validPendingTxs: heightsync.New(chain.CurrentBlock().Number, NewTxStore, logger.With("pool", "legacypool")), + toReap: make(map[common.Hash]struct{}), + reqResetCh: make(chan *txpoolResetRequest), + reqPromoteCh: make(chan *accountSet), + reqCancelResetCh: make(chan struct{}), + queueTxEventCh: make(chan *types.Transaction), + reorgDoneCh: make(chan chan struct{}), + reorgShutdownCh: make(chan struct{}), + initDoneCh: make(chan struct{}), + latestIncludedNonce: nonceCache, } pool.priced = newPricedList(pool.all) + for _, opt := range opts { + opt(pool) + } + return pool } +// SetLatestNonce records the latest on chain nonce observed for an account. +func (pool *LegacyPool) SetLatestNonce(sender common.Address, nonce uint64) { + existing, ok := pool.latestIncludedNonce.Get(sender) + if !ok || nonce > existing { + pool.latestIncludedNonce.Add(sender, nonce) + } +} + +// LatestNonce returns the most recently recorded latest-included nonce for +// addr and whether an entry exists in the cache. Primarily useful for tests +// and debugging. +func (pool *LegacyPool) LatestNonce(addr common.Address) (uint64, bool) { + return pool.latestIncludedNonce.Get(addr) +} + +// removeOlds removes txs that have been scheduled for removals from +// list l for sender addr. Returns the txs successfully removed. +func (pool *LegacyPool) removeOlds(addr common.Address, l *list, poolType PoolType) types.Transactions { + latest, ok := pool.latestIncludedNonce.Get(addr) + if !ok { + return nil + } + + dropped := l.Forward(latest + 1) + for _, tx := range dropped { + pool.all.Remove(tx.Hash()) + pool.markTxRemoved(addr, tx, poolType) + } + + return dropped +} + // Filter returns whether the given transaction can be consumed by the legacy // pool, specifically, whether it is a Legacy, AccessList or Dynamic transaction. func (pool *LegacyPool) Filter(tx *types.Transaction) bool { @@ -304,7 +595,7 @@ func (pool *LegacyPool) Filter(tx *types.Transaction) bool { // Init sets the gas price needed to keep a transaction in the pool and the chain // head to allow balance / nonce checks. The internal // goroutines will be spun up and the pool deemed operational afterwards. -func (pool *LegacyPool) Init(gasTip uint64, head *types.Header, reserver txpool.Reserver) error { +func (pool *LegacyPool) Init(gasTip uint64, head *types.Header, reserver reserver.Reserver) error { // Set the address reserver to request exclusive access to pooled accounts pool.reserver = reserver @@ -377,9 +668,9 @@ func (pool *LegacyPool) loop() { if time.Since(pool.beats[addr]) > pool.config.Lifetime { list := pool.queue[addr].Flatten() for _, tx := range list { - pool.removeTx(tx.Hash(), true, true) + pool.removeTx(tx.Hash(), true, true, RemovalReasonLifetime) } - queuedEvictionMeter.Mark(int64(len(list))) + queuedEvictionMeter.Add(context.Background(), int64(len(list))) } } pool.mu.Unlock() @@ -394,6 +685,7 @@ func (pool *LegacyPool) Close() error { pool.wg.Wait() log.Info("Transaction pool stopped") + return nil } @@ -404,6 +696,18 @@ func (pool *LegacyPool) Reset(oldHead, newHead *types.Header) { <-wait } +// CancelReset implements txpool.SubPool, signals the legacypool to stop +// processing its current reset request since a new block arrived and the work +// it is doing to reset at the current height will be invalidated. +func (pool *LegacyPool) CancelReset() { + select { + case pool.reqCancelResetCh <- struct{}{}: + return + case <-pool.reorgShutdownCh: + return + } +} + // SubscribeTransactions registers a subscription for new transaction events, // supporting feeding only newly seen or also resurrected transactions. func (pool *LegacyPool) SubscribeTransactions(ch chan<- core.NewTxsEvent, reorgs bool) event.Subscription { @@ -430,7 +734,7 @@ func (pool *LegacyPool) SetGasTip(tip *big.Int) { // pool.priced is sorted by GasFeeCap, so we have to iterate through pool.all instead drop := pool.all.TxsBelowTip(tip) for _, tx := range drop { - pool.removeTx(tx.Hash(), false, true) + pool.removeTx(tx.Hash(), false, true, RemovalReasonBelowTip) } pool.priced.Removed(len(drop)) } @@ -503,12 +807,25 @@ func (pool *LegacyPool) ContentFrom(addr common.Address) ([]*types.Transaction, return pending, queued } +// Rechecked retrieves all currently rechecked transactions, grouped by origin +// account and sorted by nonce. +// +// The transactions can also be pre-filtered by the dynamic fee components to +// reduce allocations and load on downstream subsystems. +func (pool *LegacyPool) Rechecked(ctx context.Context, height *big.Int, filter txpool.PendingFilter) map[common.Address][]*txpool.LazyTransaction { + txStore := pool.validPendingTxs.GetStore(ctx, height) + if txStore == nil { + return nil + } + return txStore.Txs(ctx, filter) +} + // Pending retrieves all currently processable transactions, grouped by origin // account and sorted by nonce. // // The transactions can also be pre-filtered by the dynamic fee components to // reduce allocations and load on downstream subsystems. -func (pool *LegacyPool) Pending(filter txpool.PendingFilter) map[common.Address][]*txpool.LazyTransaction { +func (pool *LegacyPool) Pending(ctx context.Context, filter txpool.PendingFilter) map[common.Address][]*txpool.LazyTransaction { // If only blob transactions are requested, this pool is unsuitable as it // contains none, don't even bother. if filter.OnlyBlobTxs { @@ -517,48 +834,42 @@ func (pool *LegacyPool) Pending(filter txpool.PendingFilter) map[common.Address] pool.mu.Lock() defer pool.mu.Unlock() - // Convert the new uint256.Int types to the old big.Int ones used by the legacy pool - var ( - minTipBig *big.Int - baseFeeBig *big.Int - ) - if filter.MinTip != nil { - minTipBig = filter.MinTip.ToBig() - } - if filter.BaseFee != nil { - baseFeeBig = filter.BaseFee.ToBig() - } pending := make(map[common.Address][]*txpool.LazyTransaction, len(pool.pending)) for addr, list := range pool.pending { - txs := list.Flatten() + if lazies := filterAndWrapTxs(list.Flatten(), filter.MinTip, filter.BaseFee); len(lazies) > 0 { + pending[addr] = lazies + } + } + return pending +} - // If the miner requests tip enforcement, cap the lists now - if minTipBig != nil { - for i, tx := range txs { - if tx.EffectiveGasTipIntCmp(minTipBig, baseFeeBig) < 0 { - txs = txs[:i] - break - } +// filterAndWrapTxs applies tip filtering to txs and wraps the survivors into +// LazyTransactions. +func filterAndWrapTxs(txs []*types.Transaction, minTip, baseFee *uint256.Int) []*txpool.LazyTransaction { + if minTip != nil { + for i, tx := range txs { + if tx.EffectiveGasTipIntCmp(minTip, baseFee) < 0 { + txs = txs[:i] + break } } - if len(txs) > 0 { - lazies := make([]*txpool.LazyTransaction, len(txs)) - for i := 0; i < len(txs); i++ { - lazies[i] = &txpool.LazyTransaction{ - Pool: pool, - Hash: txs[i].Hash(), - Tx: txs[i], - Time: txs[i].Time(), - GasFeeCap: uint256.MustFromBig(txs[i].GasFeeCap()), - GasTipCap: uint256.MustFromBig(txs[i].GasTipCap()), - Gas: txs[i].Gas(), - BlobGas: txs[i].BlobGas(), - } - } - pending[addr] = lazies + } + if len(txs) == 0 { + return nil + } + lazies := make([]*txpool.LazyTransaction, len(txs)) + for i, tx := range txs { + lazies[i] = &txpool.LazyTransaction{ + Hash: tx.Hash(), + Tx: tx, + Time: tx.Time(), + GasFeeCap: uint256.MustFromBig(tx.GasFeeCap()), + GasTipCap: uint256.MustFromBig(tx.GasTipCap()), + Gas: tx.Gas(), + BlobGas: tx.BlobGas(), } } - return pending + return lazies } // ValidateTxBasics checks whether a transaction is valid according to the consensus @@ -680,14 +991,14 @@ func (pool *LegacyPool) add(tx *types.Transaction) (replaced bool, err error) { hash := tx.Hash() if pool.all.Get(hash) != nil { log.Trace("Discarding already known transaction", "hash", hash) - knownTxMeter.Mark(1) + knownTxMeter.Add(context.Background(), 1) return false, txpool.ErrAlreadyKnown } // If the transaction fails basic validation, discard it if err := pool.validateTx(tx); err != nil { log.Trace("Discarding invalid transaction", "hash", hash, "err", err) - invalidTxMeter.Mark(1) + invalidTxMeter.Add(context.Background(), 1) return false, err } // already validated by this point @@ -720,7 +1031,7 @@ func (pool *LegacyPool) add(tx *types.Transaction) (replaced bool, err error) { // If the new transaction is underpriced, don't accept it if pool.priced.Underpriced(tx) { log.Trace("Discarding underpriced transaction", "hash", hash, "gasTipCap", tx.GasTipCap(), "gasFeeCap", tx.GasFeeCap()) - underpricedTxMeter.Mark(1) + underpricedTxMeter.Add(context.Background(), 1) return false, txpool.ErrUnderpriced } @@ -729,7 +1040,7 @@ func (pool *LegacyPool) add(tx *types.Transaction) (replaced bool, err error) { // do too many replacements between reorg-runs, so we cap the number of // replacements to 25% of the slots if pool.changesSinceReorg > int(pool.config.GlobalSlots/4) { - throttleTxMeter.Mark(1) + throttleTxMeter.Add(context.Background(), 1) return false, ErrTxPoolOverflow } @@ -740,7 +1051,7 @@ func (pool *LegacyPool) add(tx *types.Transaction) (replaced bool, err error) { // Special case, we still can't make the room for the new remote one. if !success { log.Trace("Discarding overflown transaction", "hash", hash) - overflowedTxMeter.Mark(1) + overflowedTxMeter.Add(context.Background(), 1) return false, ErrTxPoolOverflow } @@ -767,10 +1078,10 @@ func (pool *LegacyPool) add(tx *types.Transaction) (replaced bool, err error) { // Kick out the underpriced remote transactions. for _, tx := range drop { log.Trace("Discarding freshly underpriced transaction", "hash", tx.Hash(), "gasTipCap", tx.GasTipCap(), "gasFeeCap", tx.GasFeeCap()) - underpricedTxMeter.Mark(1) + underpricedTxMeter.Add(context.Background(), 1) sender, _ := types.Sender(pool.signer, tx) - dropped := pool.removeTx(tx.Hash(), false, sender != from) // Don't unreserve the sender of the tx being added if last from the acc + dropped := pool.removeTx(tx.Hash(), false, sender != from, RemovalReasonUnderpricedFull) // Don't unreserve the sender of the tx being added if last from the acc pool.changesSinceReorg += dropped } @@ -781,18 +1092,23 @@ func (pool *LegacyPool) add(tx *types.Transaction) (replaced bool, err error) { // Nonce already pending, check if required price bump is met inserted, old := list.Add(tx, pool.config.PriceBump) if !inserted { - pendingDiscardMeter.Mark(1) + pendingDiscardMeter.Add(context.Background(), 1) return false, txpool.ErrReplaceUnderpriced } // New transaction is better, replace old one if old != nil { pool.all.Remove(old.Hash()) pool.priced.Removed(1) - pendingReplaceMeter.Mark(1) + pool.markTxRemoved(from, old, Pending) + pendingReplaceMeter.Add(context.Background(), 1) } pool.all.Add(tx) pool.priced.Put(tx) pool.queueTxEvent(tx) + + // tx went straight to the pending queue and bypassed the queue, mark + // it as replaced + pool.markTxReplaced(from, tx) log.Trace("Pooled new executable transaction", "hash", hash, "from", from, "to", tx.To()) // Successful promotion, bump the heartbeat @@ -845,17 +1161,18 @@ func (pool *LegacyPool) enqueueTx(hash common.Hash, tx *types.Transaction, addAl inserted, old := pool.queue[from].Add(tx, pool.config.PriceBump) if !inserted { // An older transaction was better, discard this - queuedDiscardMeter.Mark(1) + queuedDiscardMeter.Add(context.Background(), 1) return false, txpool.ErrReplaceUnderpriced } // Discard any previous transaction and mark this if old != nil { pool.all.Remove(old.Hash()) pool.priced.Removed(1) - queuedReplaceMeter.Mark(1) + queuedReplaceMeter.Add(context.Background(), 1) + pool.markTxRemoved(from, old, Queue) } else { // Nothing was replaced, bump the queued counter - queuedGauge.Inc(1) + queuedGauge.Add(context.Background(), 1) } // If the transaction isn't in lookup set but it's expected to be there, // show the error log. @@ -870,6 +1187,7 @@ func (pool *LegacyPool) enqueueTx(hash common.Hash, tx *types.Transaction, addAl if _, exist := pool.beats[from]; !exist { pool.beats[from] = time.Now() } + pool.markTxEnqueued(tx) return old != nil, nil } @@ -889,23 +1207,28 @@ func (pool *LegacyPool) promoteTx(addr common.Address, hash common.Hash, tx *typ // An older transaction was better, discard this pool.all.Remove(hash) pool.priced.Removed(1) - pendingDiscardMeter.Mark(1) + pool.markTxRemoved(addr, tx, Queue) + pendingDiscardMeter.Add(context.Background(), 1) return false } // Otherwise discard any previous transaction and mark this if old != nil { + // TODO: this tx that we are removing may be in the pending builder, we + // should remove it from there pool.all.Remove(old.Hash()) pool.priced.Removed(1) - pendingReplaceMeter.Mark(1) + pool.markTxRemoved(addr, old, Pending) + pendingReplaceMeter.Add(context.Background(), 1) } else { // Nothing was replaced, bump the pending counter - pendingGauge.Inc(1) + pendingGauge.Add(context.Background(), 1) } // Set the potentially new pending nonce and notify any subsystems of the new tx pool.pendingNonces.set(addr, tx.Nonce()+1) // Successful promotion, bump the heartbeat pool.beats[addr] = time.Now() + pool.markTxPromoted(addr, tx) return true } @@ -948,7 +1271,7 @@ func (pool *LegacyPool) Add(txs []*types.Transaction, sync bool) []error { // If the transaction is known, pre-set the error slot if pool.all.Get(tx.Hash()) != nil { errs[i] = txpool.ErrAlreadyKnown - knownTxMeter.Mark(1) + knownTxMeter.Add(context.Background(), 1) continue } // Exclude transactions with basic errors, e.g invalid signatures and @@ -957,7 +1280,7 @@ func (pool *LegacyPool) Add(txs []*types.Transaction, sync bool) []error { if err := pool.ValidateTxBasics(tx); err != nil { errs[i] = err log.Trace("Discarding invalid transaction", "hash", tx.Hash(), "err", err) - invalidTxMeter.Mark(1) + invalidTxMeter.Add(context.Background(), 1) continue } // Accumulate all unknown transactions for deeper processing @@ -1000,7 +1323,7 @@ func (pool *LegacyPool) addTxsLocked(txs []*types.Transaction) ([]error, *accoun dirty.addTx(tx) } } - validTxMeter.Mark(int64(len(dirty.accounts))) + validTxMeter.Add(context.Background(), int64(len(dirty.accounts))) return errs, dirty } @@ -1086,10 +1409,10 @@ func (pool *LegacyPool) Has(hash common.Hash) bool { // which could lead to a premature release of the lock. // // Returns the number of transactions removed from the pending queue. -func (pool *LegacyPool) RemoveTx(hash common.Hash, outofbound bool, unreserve bool) int { +func (pool *LegacyPool) RemoveTx(hash common.Hash, outofbound bool, unreserve bool, reason txpool.RemovalReason) int { pool.mu.Lock() defer pool.mu.Unlock() - return pool.removeTx(hash, outofbound, unreserve) + return pool.removeTx(hash, outofbound, unreserve, reason) } // removeTx removes a single transaction from the queue, moving all subsequent @@ -1103,7 +1426,7 @@ func (pool *LegacyPool) RemoveTx(hash common.Hash, outofbound bool, unreserve bo // Returns the number of transactions removed from the pending queue. // // The transaction pool lock must be held. -func (pool *LegacyPool) removeTx(hash common.Hash, outofbound bool, unreserve bool) int { +func (pool *LegacyPool) removeTx(hash common.Hash, outofbound bool, unreserve bool, reason txpool.RemovalReason) int { // Fetch the transaction we wish to delete tx := pool.all.Get(hash) if tx == nil { @@ -1133,6 +1456,9 @@ func (pool *LegacyPool) removeTx(hash common.Hash, outofbound bool, unreserve bo // Remove the transaction from the pending lists and reset the account nonce if pending := pool.pending[addr]; pending != nil { if removed, invalids := pending.Remove(tx); removed { + pool.markTxRemoved(addr, tx, Pending) + pendingRemovalMetric(reason).Add(context.Background(), 1) + // If no more pending transactions are left, remove the list if pending.Empty() { delete(pool.pending, addr) @@ -1145,15 +1471,19 @@ func (pool *LegacyPool) removeTx(hash common.Hash, outofbound bool, unreserve bo // Update the account nonce if needed pool.pendingNonces.setIfLower(addr, tx.Nonce()) // Reduce the pending counter - pendingGauge.Dec(int64(1 + len(invalids))) + pendingGauge.Add(context.Background(), -int64(1+len(invalids))) + pendingDemotedRemoved.Add(context.Background(), int64(len(invalids))) return 1 + len(invalids) } } // Transaction is in the future queue if future := pool.queue[addr]; future != nil { if removed, _ := future.Remove(tx); removed { + pool.markTxRemoved(addr, tx, Queue) + queueRemovalMetric(reason).Add(context.Background(), 1) + // Reduce the queued counter - queuedGauge.Dec(1) + queuedGauge.Add(context.Background(), -1) } if future.Empty() { delete(pool.queue, addr) @@ -1200,18 +1530,26 @@ func (pool *LegacyPool) scheduleReorgLoop() { defer pool.wg.Done() var ( - curDone chan struct{} // non-nil while runReorg is active - nextDone = make(chan struct{}) - launchNextRun bool - reset *txpoolResetRequest - dirtyAccounts *accountSet - queuedEvents = make(map[common.Address]*SortedMap) + curDone chan struct{} // non-nil while runReorg is active + nextDone = make(chan struct{}) + resetCancelled = make(chan struct{}) + launchNextRun bool + reset *txpoolResetRequest + dirtyAccounts *accountSet + queuedEvents = make(map[common.Address]*SortedMap) ) for { // Launch next background reorg if needed if curDone == nil && launchNextRun { // Run the background reorg and announcements - go pool.runReorg(nextDone, reset, dirtyAccounts, queuedEvents) + input := reorgInput{ + done: nextDone, + cancelReset: resetCancelled, + reset: reset, + dirtyAccounts: dirtyAccounts, + events: queuedEvents, + } + go pool.runReorg(input) // Prepare everything for the next round of reorg curDone, nextDone = nextDone, make(chan struct{}) @@ -1232,6 +1570,18 @@ func (pool *LegacyPool) scheduleReorgLoop() { launchNextRun = true pool.reorgDoneCh <- nextDone + case <-pool.reqCancelResetCh: + // Only process the request if the reorg loop is running (curDone + // != nil) and a cancel request for this reorg loop has not been + // processed already (resetCancelled != nil) + if resetCancelled != nil && curDone != nil { + close(resetCancelled) + // Set to nil to dedupe any future requests to cancel reset for + // this same reorg iteration. Once this run finishes, + // resetCancelled will be recreated as non nil chan and the + // next iteration will support being cancelled again. + resetCancelled = nil + } case req := <-pool.reqPromoteCh: // Promote request: update address set if request is already pending. if dirtyAccounts == nil { @@ -1250,9 +1600,9 @@ func (pool *LegacyPool) scheduleReorgLoop() { queuedEvents[addr] = NewSortedMap() } queuedEvents[addr].Put(tx) - case <-curDone: curDone = nil + resetCancelled = make(chan struct{}) case <-pool.reorgShutdownCh: // Wait for current run to finish. @@ -1265,30 +1615,88 @@ func (pool *LegacyPool) scheduleReorgLoop() { } } +type reorgInput struct { + done chan struct{} + cancelReset chan struct{} + reset *txpoolResetRequest + dirtyAccounts *accountSet + events map[common.Address]*SortedMap +} + +// computePendingTipNonces returns a mapping from account address to the next +// expected nonce, taking the pending pool entries into account, but not the +// queued pool entries. +func (pool *LegacyPool) computePendingTipNonces() map[common.Address]uint64 { + tips := make(map[common.Address]uint64, len(pool.pending)) + for addr, list := range pool.pending { + // get the next nonce that should be included on chain after last + // pending pool tx for this account lands + nextPendingNonce := list.LastElement().Nonce() + 1 + + // grab the latest nonce that we have observed on chain for this + // account if we have it cached + latestIncludedNonce, ok := pool.latestIncludedNonce.Get(addr) + if ok { + // if we have a cached on chain nonce for this account, it likely + // had a tx land in the latest block and its last pending pool + // element may be stale if we have not yet run demoteUnexecutables + // yet. thus, if the latestIncludedNonce + 1 is > nextPendingNonce, + // then that is actually what we should be using as the 'tip' of + // the pending pool for this account + // + // NOTE: latestIncludedNonce is a lru cache (lru to manage its + // growth). It is strongly recommended to the user to configure + // this cache size > the max number of unique accounts they expect + // to see in a block. If they do not do so, an issue could manifest + // here where a block has more accounts than entries in the + // latestIncludedNonce cache. If an entry gets evicted from + // latestIncludedNonce for an account that was included in H-1, + // then calling this function at H will use a stale + // nextPendingNonce value (when compared to statedb.GetNonce(addr)) + // if this function is called before demoteUnexecutables, causing a + // queued contiguous nonce tx (with respect to pending txs) to not + // be promoted if there is a race on resetting + promoting the + // queued tx after insert. This is unlikely and would require a + // misconfiguration by the user, but this is a documented possible + // scenario. + nextPendingNonce = max(nextPendingNonce, latestIncludedNonce+1) + } + tips[addr] = nextPendingNonce + } + return tips +} + // runReorg runs reset and promoteExecutables on behalf of scheduleReorgLoop. -func (pool *LegacyPool) runReorg(done chan struct{}, reset *txpoolResetRequest, dirtyAccounts *accountSet, events map[common.Address]*SortedMap) { +func (pool *LegacyPool) runReorg(input reorgInput) { defer func(t0 time.Time) { - reorgDurationTimer.Update(time.Since(t0)) + elapsedMS := float64(time.Since(t0).Milliseconds()) + reorgDurationTimer.Record(context.Background(), elapsedMS) + if input.reset != nil { + reorgResetTimer.Record(context.Background(), elapsedMS) + } }(time.Now()) - defer close(done) + defer close(input.done) var promoteAddrs []common.Address - if dirtyAccounts != nil && reset == nil { + // Optionally acquire a shared read lock to coordinate with Commit in tests. + unlock := beginCommitRead(any(pool.chain)) + defer unlock() + if input.dirtyAccounts != nil && input.reset == nil { // Only dirty accounts need to be promoted, unless we're resetting. // For resets, all addresses in the tx queue will be promoted and // the flatten operation can be avoided. - promoteAddrs = dirtyAccounts.flatten() + promoteAddrs = input.dirtyAccounts.flatten() } pool.mu.Lock() - if reset != nil { + if input.reset != nil { // Reset from the old head to the new, rescheduling any reorged transactions - pool.reset(reset.oldHead, reset.newHead) + pool.reset(input.reset.oldHead, input.reset.newHead) // Nonces were reset, discard any events that became stale - for addr := range events { - events[addr].Forward(pool.pendingNonces.get(addr)) - if events[addr].Len() == 0 { - delete(events, addr) + for addr := range input.events { + input.events[addr].Forward(pool.pendingNonces.get(addr)) + if input.events[addr].Len() == 0 { + delete(input.events, addr) } } // Reset needs promote for all addresses @@ -1297,62 +1705,64 @@ func (pool *LegacyPool) runReorg(done chan struct{}, reset *txpoolResetRequest, promoteAddrs = append(promoteAddrs, addr) } } + // Check for pending transactions for every account that sent new ones - promoted := pool.promoteExecutables(promoteAddrs) + promoted := pool.promoteExecutables(promoteAddrs, input.cancelReset, input.reset) // If a new block appeared, validate the pool of pending transactions. This will // remove any transaction that has been included in the block or was invalidated // because of another transaction (e.g. higher gas price). - if reset != nil { - pool.demoteUnexecutables() - if reset.newHead != nil { - if pool.chainconfig.IsLondon(new(big.Int).Add(reset.newHead.Number, big.NewInt(1))) { - pendingBaseFee := eip1559.CalcBaseFee(pool.chainconfig, reset.newHead) + if input.reset != nil { + pool.demoteUnexecutables(input.cancelReset, input.reset) + if input.reset.newHead != nil { + if pool.chainconfig.IsLondon(new(big.Int).Add(input.reset.newHead.Number, big.NewInt(1))) { + pendingBaseFee := eip1559.CalcBaseFee(pool.chainconfig, input.reset.newHead) pool.priced.SetBaseFee(pendingBaseFee) } else { pool.priced.Reheap() } } // Update all accounts to the latest known pending nonce - nonces := make(map[common.Address]uint64, len(pool.pending)) - for addr, list := range pool.pending { - highestPending := list.LastElement() - nonces[addr] = highestPending.Nonce() + 1 - } - pool.pendingNonces.setAll(nonces) + pool.pendingNonces.setAll(pool.computePendingTipNonces()) + pool.validPendingTxs.EndCurrentHeight() } + // Ensure pool.queue and pool.pending sizes stay within the configured limits. + // + // TODO: We are adding to the pending builder before this, then we may + // immediately drop some of the txs we put in pending via truncate. we will + // likely have to change this algorithm to truncate as we call demote + // unexecutables per account (currently it needs info on all accounts since + // it tries to truncate fairly across accounts). pool.truncatePending() pool.truncateQueue() - dropBetweenReorgHistogram.Update(int64(pool.changesSinceReorg)) + dropBetweenReorgHistogram.Record(context.Background(), int64(pool.changesSinceReorg)) pool.changesSinceReorg = 0 // Reset change counter pool.mu.Unlock() // Notify subsystems for newly added transactions for _, tx := range promoted { addr, _ := types.Sender(pool.signer, tx) - if _, ok := events[addr]; !ok { - events[addr] = NewSortedMap() + if _, ok := input.events[addr]; !ok { + input.events[addr] = NewSortedMap() } - events[addr].Put(tx) + input.events[addr].Put(tx) } - if len(events) > 0 { + if len(input.events) > 0 { var txs []*types.Transaction - for _, set := range events { + for _, set := range input.events { txs = append(txs, set.Flatten()...) } - // On successful transaction, broadcast the transaction through the Comet Mempool - // Two inefficiencies: - // 1. The transactions might have already been broadcasted, demoted, and repromoted - // a. tx_nonces_for_account: [1,2,3,4,5,6], [1,2,3] pass, [4] fails, [5,6] get demoted, [4] gets reinserted, [4,5,6] get re-promoted and thus rebroadcasted - // 2. The transaction will pass through Comet, into the appside mempool, and attempted to be reinserted - // It will not, because there is a check, but the attempt is there. - if pool.BroadcastTxFn != nil { - if err := pool.BroadcastTxFn(txs); err != nil { - log.Error("Failed to broadcast transactions", "err", err, "count", len(txs)) - } - } + + // NOTE: We are not calling PromoteTx here on txs with events queued + // for them (even though this does mean they were promoted), however it + // is possible that this tx was promoted a long time ago, but the + // runReorg was not scheduled until later, so the event has not been + // handled. Since this is a possible scenario we opt to call PromoteTx + // on site where the tx is inserted into the pending queue, not just + // when handling events. + pool.txFeed.Send(core.NewTxsEvent{Txs: txs}) } } @@ -1372,42 +1782,111 @@ func (pool *LegacyPool) resetInternalState(newHead *types.Header, reinject types pool.currentState = statedb pool.pendingNonces = newNoncer(statedb) + // a brand new noncer only knows the statedb's committed nonce, which may + // be behind the tip of pool.pending nonce wise. we need to reconcile + // the noncer with the current pending tip so that any subsequent + // promoteExecutables can still promote queued txs whose nonces are + // contiguous with pending. + // + // without this the following scenario is possible: + // - pool.pending = [tx0, tx1], pool.queue = [tx2]. + // - statedb nonce for this account is 0 (nothing included on chain). + // - reset runs **before** the async promotion gets scheduled, or they are batched together. + // - pendingNonces reset = newNoncer(statedb), noncer map empty so + // get(addr) falls back to nonce 0 from statedb. + // - promoteExecutables calls list.Ready(0) on pool.queue = [tx2], sees + // lowest nonce 2 > 0, returns a gap, promotes nothing. + // - tx2 stays stuck in queued even though it is contiguous with pending. + // - tx2 must wait for another insert from this account in order to be + // promoted, or the existing pending txs are included on chain. + pool.pendingNonces.setAll(pool.computePendingTipNonces()) + + ctx, err := pool.chain.GetLatestContext() + if err != nil { + panic(fmt.Errorf("failed to get latest context for rechecker: %w", err)) + } + pool.rechecker.Update(ctx, newHead) + pool.validPendingTxs.StartNewHeight(newHead.Number) + // Inject any transactions discarded due to reorgs log.Debug("Reinjecting stale transactions", "count", len(reinject)) core.SenderCacher().Recover(pool.signer, reinject) pool.addTxsLocked(reinject) } +// isResetCancelled returns true if the pool is resetting and it has been +// signaled to cancel the reset. +func isReorgCancelled(reset *txpoolResetRequest, cancelled chan struct{}) bool { + if reset != nil { + select { + case <-cancelled: + return true + default: + return false + } + } + return false +} + // promoteExecutables moves transactions that have become processable from the // future queue to the set of pending transactions. During this process, all // invalidated transactions (low nonce, low balance) are deleted. -func (pool *LegacyPool) promoteExecutables(accounts []common.Address) []*types.Transaction { +func (pool *LegacyPool) promoteExecutables(accounts []common.Address, cancelled chan struct{}, reset *txpoolResetRequest) []*types.Transaction { // Track the promoted transactions to broadcast them at once var promoted []*types.Transaction // Iterate over all accounts and promote any executable transactions - gasLimit := pool.currentHead.Load().GasLimit for _, addr := range accounts { + if isReorgCancelled(reset, cancelled) { + queuedPromotedCancelled.Add(context.Background(), 1) + return promoted + } list := pool.queue[addr] if list == nil { continue // Just in case someone calls with a non existing account } - // Drop all transactions that are deemed too old (low nonce) - forwards := list.Forward(pool.currentState.GetNonce(addr)) - for _, tx := range forwards { - pool.all.Remove(tx.Hash()) + + // Drop all transactions that are below the latest included nonce for + // this account based on what we have seen during the latest block + // execution. Only do this if we are resetting. + var olds types.Transactions + if reset != nil { + olds = pool.removeOlds(addr, list, Queue) + queuedRemovedOld.Add(context.Background(), int64(len(olds))) } - log.Trace("Removed old queued transactions", "count", len(forwards)) - // Drop all transactions that are too costly (low balance or out of gas) - drops, _ := list.Filter(pool.currentState.GetBalance(addr), gasLimit) - for _, tx := range drops { + + // Drop all transactions that now fail RecheckEVM with a non tolerated error + // + // NOTE: this is happening after the nonce removal above since this + // check is slower, we would like it to happen on the fewest txs as + // possible. + recheckStart := time.Now() + recheckDrops, _ := list.FilterSorted(func(tx *types.Transaction) bool { + ctx, write := pool.rechecker.GetContext() + _, err := pool.rechecker.RecheckEVM(ctx, tx) + + if err == nil && reset == nil { + // only write changes back to original context if we are not + // running in reset mode, i.e. a new block has not been seen + write() + } + + // do not drop txs if they fail due to a nonce gap error, this is + // expected for txs in the queued pool + return tolerateNonceGapErr(err) != nil + }) + for _, tx := range recheckDrops { pool.all.Remove(tx.Hash()) + pool.markTxRemoved(addr, tx, Queue) } - log.Trace("Removed unpayable queued transactions", "count", len(drops)) - queuedNofundsMeter.Mark(int64(len(drops))) + log.Trace("Removed queued transactions that failed recheck", "count", len(recheckDrops)) + queuedRecheckDropMeter.Add(context.Background(), int64(len(recheckDrops))) + queuedRecheckDurationTimer.Record(context.Background(), float64(time.Since(recheckStart).Milliseconds())) // Gather all executable transactions and promote them + listLen := list.Len() readies := list.Ready(pool.pendingNonces.get(addr)) + queuedNonReadies.Add(context.Background(), int64(listLen-len(readies))) for _, tx := range readies { hash := tx.Hash() if pool.promoteTx(addr, hash, tx) { @@ -1415,19 +1894,23 @@ func (pool *LegacyPool) promoteExecutables(accounts []common.Address) []*types.T } } log.Trace("Promoted queued transactions", "count", len(promoted)) - queuedGauge.Dec(int64(len(readies))) + queuedGauge.Add(context.Background(), -int64(len(readies))) // Drop all transactions over the allowed limit caps := list.Cap(int(pool.config.AccountQueue)) for _, tx := range caps { hash := tx.Hash() pool.all.Remove(hash) + pool.markTxRemoved(addr, tx, Queue) + queueRemovalMetric(RemovalReasonCapExceeded).Add(context.Background(), 1) log.Trace("Removed cap-exceeding queued transaction", "hash", hash) } - queuedRateLimitMeter.Mark(int64(len(caps))) + queuedRateLimitMeter.Add(context.Background(), int64(len(caps))) + // Mark all the items dropped as removed - pool.priced.Removed(len(forwards) + len(drops) + len(caps)) - queuedGauge.Dec(int64(len(forwards) + len(drops) + len(caps))) + totalDropped := len(recheckDrops) + len(caps) + len(olds) + pool.priced.Removed(totalDropped) + queuedGauge.Add(context.Background(), -int64(totalDropped)) // Delete the entire queue entry if it became empty. if list.Empty() { @@ -1445,6 +1928,9 @@ func (pool *LegacyPool) promoteExecutables(accounts []common.Address) []*types.T // pending limit. The algorithm tries to reduce transaction counts by an approximately // equal number for all for accounts with many pending transactions. func (pool *LegacyPool) truncatePending() { + defer func(t0 time.Time) { + pendingTruncateTimer.Record(context.Background(), float64(time.Since(t0).Milliseconds())) + }(time.Now()) pending := uint64(0) // Assemble a spam order to penalize large transactors first @@ -1484,13 +1970,15 @@ func (pool *LegacyPool) truncatePending() { // Drop the transaction from the global pools too hash := tx.Hash() pool.all.Remove(hash) + pool.markTxRemoved(offenders[i], tx, Pending) + pendingRemovalMetric(RemovalReasonCapExceeded).Add(context.Background(), 1) // Update the account nonce to the dropped transaction pool.pendingNonces.setIfLower(offenders[i], tx.Nonce()) log.Trace("Removed fairness-exceeding pending transaction", "hash", hash) } pool.priced.Removed(len(caps)) - pendingGauge.Dec(int64(len(caps))) + pendingGauge.Add(context.Background(), -int64(len(caps))) pending-- } @@ -1509,18 +1997,20 @@ func (pool *LegacyPool) truncatePending() { // Drop the transaction from the global pools too hash := tx.Hash() pool.all.Remove(hash) + pool.markTxRemoved(addr, tx, Pending) + pendingRemovalMetric(RemovalReasonCapExceeded).Add(context.Background(), 1) // Update the account nonce to the dropped transaction pool.pendingNonces.setIfLower(addr, tx.Nonce()) log.Trace("Removed fairness-exceeding pending transaction", "hash", hash) } pool.priced.Removed(len(caps)) - pendingGauge.Dec(int64(len(caps))) + pendingGauge.Add(context.Background(), -int64(len(caps))) pending-- } } } - pendingRateLimitMeter.Mark(int64(pendingBeforeCap - pending)) + pendingRateLimitMeter.Add(context.Background(), int64(pendingBeforeCap-pending)) } // truncateQueue drops the oldest transactions in the queue if the pool is above the global queue limit. @@ -1550,18 +2040,18 @@ func (pool *LegacyPool) truncateQueue() { // Drop all transactions if they are less than the overflow if size := uint64(list.Len()); size <= drop { for _, tx := range list.Flatten() { - pool.removeTx(tx.Hash(), true, true) + pool.removeTx(tx.Hash(), true, true, RemovalReasonTruncatedOverflow) } drop -= size - queuedRateLimitMeter.Mark(int64(size)) + queuedRateLimitMeter.Add(context.Background(), int64(size)) continue } // Otherwise drop only last few transactions txs := list.Flatten() for i := len(txs) - 1; i >= 0 && drop > 0; i-- { - pool.removeTx(txs[i].Hash(), true, true) + pool.removeTx(txs[i].Hash(), true, true, RemovalReasonTruncatedLast) drop-- - queuedRateLimitMeter.Mark(1) + queuedRateLimitMeter.Add(context.Background(), 1) } } } @@ -1573,28 +2063,84 @@ func (pool *LegacyPool) truncateQueue() { // Note: transactions are not marked as removed in the priced list because re-heaping // is always explicitly triggered by SetBaseFee and it would be unnecessary and wasteful // to trigger a re-heap is this function -func (pool *LegacyPool) demoteUnexecutables() { +func (pool *LegacyPool) demoteUnexecutables(cancelled chan struct{}, reset *txpoolResetRequest) { + defer func(t0 time.Time) { + demoteTimer.Record(context.Background(), float64(time.Since(t0).Milliseconds())) + }(time.Now()) + // Iterate over all accounts and demote any non-executable transactions - gasLimit := pool.currentHead.Load().GasLimit for addr, list := range pool.pending { - nonce := pool.currentState.GetNonce(addr) - - // Drop all transactions that are deemed too old (low nonce) - olds := list.Forward(nonce) - for _, tx := range olds { - hash := tx.Hash() - pool.all.Remove(hash) - log.Trace("Removed old pending transaction", "hash", hash) + if isReorgCancelled(reset, cancelled) { + // NOTE: are explicitly not clearing the toReap lookup since that + // may contain txs that have not been rechecked yet and still need + // to be reaped that we did not reach during this call since we + // cancelled early. we will attempt to reap them next reset after + // verification. + pendingDemotedCancelled.Add(context.Background(), 1) + return } - // Drop all transactions that are too costly (low balance or out of gas), and queue any invalids back for later - drops, invalids := list.Filter(pool.currentState.GetBalance(addr), gasLimit) - for _, tx := range drops { + + // Drop all transactions that are below the latest included nonce for + // this account based on what we have seen during the latest block + // execution. + olds := pool.removeOlds(addr, list, Pending) + pendingRemovedOld.Add(context.Background(), int64(len(olds))) + + // Drop all transactions that now fail RecheckEVM with a non tolerated error + // + // NOTE: this is happening after the nonce removal above since this + // check is slower, we would like it to happen on the fewest txs as + // possible. + recheckStart := time.Now() + var removedPrevious bool + recheckDrops, recheckInvalids := list.FilterSorted(func(tx *types.Transaction) bool { + ctx, write := pool.rechecker.GetContext() + _, err := pool.rechecker.RecheckEVM(ctx, tx) + if err == nil { + // successful recheck, make state changes available to + // rechecker's context. we always write state changes here even + // if we are resetting since we always want run new rechecks + // off of pending state (queued, new inserts, etc). + write() + return false + } + + // if we have previously removed a tx in this list during filter, + // we want to not remove future txs that fail due to a nonce gap + // error, since they will all fail recheck with this due to the + // first tx failing and not committing the nonce increment to the + // rechecker's context. + // + // for example say we have a list of txs [tx0, tx1, tx2], and tx0 + // has failed recheck for some reason (e.g. not enough balance). + // this means we have not written the nonce increment for tx0 back + // to the rechecker's context, causing the recheck for tx1 to always + // fail with a nonce gap error. however, this is expected and ok + // for evm txs and we want to keep this tx in the pool, but we want + // to demote to back to the queued pool (which will happen via the + // nonce invalidation that the filter does). + if removedPrevious { + return tolerateNonceGapErr(err) != nil + } + + // we have not previously removed a tx in this list and recheck + // returned an error, always remove this tx and mark that we have + // removed a tx in the list. + removedPrevious = true + return true + }) + + for _, tx := range recheckDrops { hash := tx.Hash() pool.all.Remove(hash) - log.Trace("Removed unpayable pending transaction", "hash", hash) + pool.markTxRemoved(addr, tx, Pending) + log.Trace("Removed pending transaction that failed recheck", "hash", hash) } - pendingNofundsMeter.Mark(int64(len(drops))) + pendingRecheckDropMeter.Add(context.Background(), int64(len(recheckDrops))) + pendingDemotedRecheck.Add(context.Background(), int64(len(recheckInvalids))) + pendingRecheckDurationTimer.Record(context.Background(), float64(time.Since(recheckStart).Milliseconds())) + invalids := recheckInvalids for _, tx := range invalids { hash := tx.Hash() log.Trace("Demoting pending transaction", "hash", hash) @@ -1602,28 +2148,41 @@ func (pool *LegacyPool) demoteUnexecutables() { // Internal shuffle shouldn't touch the lookup set. pool.enqueueTx(hash, tx, false) } - pendingGauge.Dec(int64(len(olds) + len(drops) + len(invalids))) + pendingGauge.Add(context.Background(), -int64(len(recheckDrops)+len(invalids)+len(olds))) - // If there's a gap in front, alert (should never happen) and postpone all transactions - if list.Len() > 0 && list.txs.Get(nonce) == nil { - gapped := list.Cap(0) - for _, tx := range gapped { - hash := tx.Hash() - log.Warn("Demoting invalidated transaction", "hash", hash) - - // Internal shuffle shouldn't touch the lookup set. - pool.enqueueTx(hash, tx, false) - } - pendingGauge.Dec(int64(len(gapped))) - } // Delete the entire pending entry if it became empty. if list.Empty() { delete(pool.pending, addr) if _, ok := pool.queue[addr]; !ok { pool.reserver.Release(addr) } + continue + } + + // list now contains only validated txs (txs that failed recheck have + // been dropped, and those now gapped have been moved back to queued) + validated := list.Flatten() + + // push validated txs into the validPendingTxs for this height + pool.validPendingTxs.Do(func(store *TxStore) { store.AddTxs(addr, validated) }) + + // if any of the validated txs are pending reap, reap them now + for _, tx := range validated { + hash := tx.Hash() + if _, ok := pool.toReap[hash]; !ok { + // tx does not need deferred reap, continue + continue + } + if err := pool.reapList.PushEVMTx(tx); err != nil { + log.Error("failed to push tx pending reap onto reap list", "err", err, "hash", hash) + } + delete(pool.toReap, hash) } } + + // we have removed txs that we have reaped, but there may be stale entires + // in cases where we replace a tx multiple times, clean them up here. + pool.toReap = make(map[common.Hash]struct{}) } // addressByHeartbeat is an account address tagged with its last activity timestamp. @@ -1756,7 +2315,7 @@ func (t *lookup) Add(tx *types.Transaction) { defer t.lock.Unlock() t.slots += numSlots(tx) - slotsGauge.Update(int64(t.slots)) + slotsGauge.Record(context.Background(), int64(t.slots)) t.txs[tx.Hash()] = tx t.addAuthorities(tx) @@ -1774,7 +2333,7 @@ func (t *lookup) Remove(hash common.Hash) { } t.removeAuthorities(tx) t.slots -= numSlots(tx) - slotsGauge.Update(int64(t.slots)) + slotsGauge.Record(context.Background(), int64(t.slots)) delete(t.txs, hash) } @@ -1890,6 +2449,7 @@ func (pool *LegacyPool) Clear() { pool.pending = make(map[common.Address]*list) pool.queue = make(map[common.Address]*list) pool.pendingNonces = newNoncer(pool.currentState) + pool.toReap = make(map[common.Hash]struct{}) } // HasPendingAuth returns a flag indicating whether there are pending @@ -1897,3 +2457,119 @@ func (pool *LegacyPool) Clear() { func (pool *LegacyPool) HasPendingAuth(addr common.Address) bool { return pool.all.hasAuth(addr) } + +// markTxPromoted adds the tx to the next valid pending txs set (i.e. to be +// included in the next block if selected by the application), pushes it onto +// the reap list so consensus picks it up, and records the pending-entry +// timestamps on the tracker. +func (pool *LegacyPool) markTxPromoted(addr common.Address, tx *types.Transaction) { + pool.validPendingTxs.Do(func(store *TxStore) { + store.AddTx(addr, tx) + }) + if err := pool.reapList.PushEVMTx(tx); err != nil { + log.Error("could not push promoted evm tx to ReapList", "err", err, "hash", tx.Hash()) + } + hash := tx.Hash() + _ = pool.tracker.ExitedQueued(hash) + _ = pool.tracker.EnteredPending(hash) +} + +// markTxReplaced runs the promotion side effects for a tx that bypassed the +// queued pool (replaced an existing pending tx at the same nonce). It does +// **not** include the tx in the valid pending txs set, since replacements +// must be revalidated by the Rechecker before we rely on them. +func (pool *LegacyPool) markTxReplaced(_ common.Address, tx *types.Transaction) { + // we are explicitly not adding this tx to the reap list here. this + // replacement tx has not been verified via the rechecker. thus we are + // deferring the reap to happen only after is has been verified during the + // next call to demoteUnexecutables. + hash := tx.Hash() + pool.toReap[hash] = struct{}{} + _ = pool.tracker.ExitedQueued(hash) + _ = pool.tracker.EnteredPending(hash) +} + +// markTxRemoved records a removal from the given pool: removes the tx from +// the pending snapshot (if applicable), drops it from the reap list, and +// records the final duration on the tracker. +func (pool *LegacyPool) markTxRemoved(addr common.Address, tx *types.Transaction, p PoolType) { + if p == Pending { + pool.validPendingTxs.Do(func(store *TxStore) { + store.RemoveTx(addr, tx) + }) + } + + pool.reapList.DropEVMTx(tx) + hash := tx.Hash() + switch p { + case Pending: + _ = pool.tracker.RemovedFromPending(hash) + case Queue: + _ = pool.tracker.RemovedFromQueue(hash) + } +} + +// markTxEnqueued records the queued-entry timestamp on the tracker. +func (pool *LegacyPool) markTxEnqueued(tx *types.Transaction) { + _ = pool.tracker.EnteredQueued(tx.Hash()) +} + +// tolerateNonceGapErr returns nil if err is an error string that should be +// ignored from recheck, i.e. we do not want to drop txs from the mempool if we +// have received specific errors from recheck. +func tolerateNonceGapErr(err error) error { + // TODO: Fix import cycle if we try and properly match on + // errors.Is(mempool.ErrNonceLow) + if err != nil && strings.Contains(err.Error(), "tx nonce is higher than account nonce") { + return nil + } + return err +} + +func pendingRemovalMetric(reason txpool.RemovalReason) metric.Int64Counter { + switch reason { + case RemovalReasonLifetime: + return pendingRemovedLifetime + case RemovalReasonBelowTip: + return pendingRemovedBelowTip + case RemovalReasonTruncatedOverflow: + return pendingRemovedTruncatedOverflow + case RemovalReasonTruncatedLast: + return pendingRemovedTruncatedLast + case RemovalReasonUnderpricedFull: + return pendingRemovedUnderpricedFull + case RemovalReasonCapExceeded: + return pendingRemovedCapped + case RemovalReasonRunTxRecheck: + return pendingRemovedRunTxRecheck + case RemovalReasonRunTxFinalize: + return pendingRemovedRunTxFinalize + case RemovalReasonPrepareProposalInvalid: + return pendingRemovedPrepareProposal + } + return pendingRemovedUnknown +} + +func queueRemovalMetric(reason txpool.RemovalReason) metric.Int64Counter { + switch reason { + case RemovalReasonLifetime: + return queuedRemovedLifetime + case RemovalReasonBelowTip: + return queuedRemovedBelowTip + case RemovalReasonTruncatedOverflow: + return queuedRemovedTruncatedOverflow + case RemovalReasonTruncatedLast: + return queuedRemovedTruncatedLast + case RemovalReasonUnderpricedFull: + return queuedRemovedUnderpricedFull + case RemovalReasonCapExceeded: + return queuedRemovedCapped + case RemovalReasonRunTxRecheck: + return queuedRemovedRunTxRecheck + case RemovalReasonRunTxFinalize: + return queuedRemovedRunTxFinalize + case RemovalReasonPrepareProposalInvalid: + return queuedRemovedPrepareProposal + } + return queuedRemovedUnknown +} diff --git a/mempool/txpool/legacypool/legacypool2_test.go b/mempool/txpool/legacypool/legacypool2_test.go index deb06aa6..a690c304 100644 --- a/mempool/txpool/legacypool/legacypool2_test.go +++ b/mempool/txpool/legacypool/legacypool2_test.go @@ -21,6 +21,9 @@ import ( "math/big" "testing" + "cosmossdk.io/log/v2" + "github.com/cosmos/evm/mempool/internal/reaplist" + "github.com/cosmos/evm/mempool/internal/txtracker" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/tracing" @@ -86,7 +89,7 @@ func TestTransactionFutureAttack(t *testing.T) { config := testTxPoolConfig config.GlobalQueue = 100 config.GlobalSlots = 100 - pool := New(config, blockchain) + pool := New(config, log.NewNopLogger(), blockchain, reaplist.New(testTxEncoder{}), txtracker.New()) pool.Init(config.PriceLimit, blockchain.CurrentBlock(), newReserver()) defer pool.Close() @@ -121,7 +124,7 @@ func TestTransactionFuture1559(t *testing.T) { // Create the pool to test the pricing enforcement with statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) blockchain := newTestBlockChain(eip1559Config, 1000000, statedb, new(event.Feed)) - pool := New(testTxPoolConfig, blockchain) + pool := New(testTxPoolConfig, log.NewNopLogger(), blockchain, reaplist.New(testTxEncoder{}), txtracker.New()) pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), newReserver()) defer pool.Close() @@ -154,7 +157,7 @@ func TestTransactionZAttack(t *testing.T) { // Create the pool to test the pricing enforcement with statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) blockchain := newTestBlockChain(eip1559Config, 1000000, statedb, new(event.Feed)) - pool := New(testTxPoolConfig, blockchain) + pool := New(testTxPoolConfig, log.NewNopLogger(), blockchain, reaplist.New(testTxEncoder{}), txtracker.New()) pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), newReserver()) defer pool.Close() // Create a number of test accounts, fund them and make transactions @@ -227,7 +230,7 @@ func BenchmarkFutureAttack(b *testing.B) { config := testTxPoolConfig config.GlobalQueue = 100 config.GlobalSlots = 100 - pool := New(config, blockchain) + pool := New(config, log.NewNopLogger(), blockchain, reaplist.New(testTxEncoder{}), txtracker.New()) pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), newReserver()) defer pool.Close() fillPool(b, pool) diff --git a/mempool/txpool/legacypool/legacypool_test.go b/mempool/txpool/legacypool/legacypool_test.go index f0ed2dfb..410b218d 100644 --- a/mempool/txpool/legacypool/legacypool_test.go +++ b/mempool/txpool/legacypool/legacypool_test.go @@ -17,6 +17,7 @@ package legacypool import ( + "context" "crypto/ecdsa" crand "crypto/rand" "errors" @@ -29,6 +30,8 @@ import ( "testing" "time" + "cosmossdk.io/log/v2" + reserver2 "github.com/cosmos/evm/mempool/reserver" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" @@ -40,10 +43,25 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/trie" "github.com/holiman/uint256" + "github.com/stretchr/testify/require" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/evm/mempool/internal/reaplist" + "github.com/cosmos/evm/mempool/internal/txtracker" "github.com/cosmos/evm/mempool/txpool" ) +// testTxEncoder is a stub for legacypool tests that don't exercise size. +// CosmosTx returns (nil, nil) — don't reuse for tests that exercise the +// reaplist's bytes axis. +type testTxEncoder struct{} + +func (testTxEncoder) EVMTx(tx *types.Transaction) ([]byte, error) { + return tx.Hash().Bytes(), nil +} + +func (testTxEncoder) CosmosTx(sdk.Tx) ([]byte, error) { return nil, nil } + var ( // testTxPoolConfig is a transaction pool configuration without stateful disk // sideeffects used during testing. @@ -96,6 +114,10 @@ func (bc *testBlockChain) StateAt(common.Hash) (vm.StateDB, error) { return bc.statedb, nil } +func (bc *testBlockChain) GetLatestContext() (sdk.Context, error) { + return sdk.Context{}, nil +} + func (bc *testBlockChain) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription { return bc.chainHeadFeed.Subscribe(ch) } @@ -125,7 +147,7 @@ func pricedDataTransaction(nonce uint64, gaslimit uint64, gasprice *big.Int, key var tx *types.Transaction // 10 attempts is statistically sufficient since leading zeros in ECDSA signatures are rare and randomly distributed. - var retryTimes = 10 + retryTimes := 10 for i := 0; i < retryTimes; i++ { data := make([]byte, dataBytes) crand.Read(data) @@ -191,57 +213,63 @@ func pricedSetCodeTxWithAuth(nonce uint64, gaslimit uint64, gasFee, tip *uint256 }) } -func setupPool() (*LegacyPool, *ecdsa.PrivateKey) { +func setupPool() (*LegacyPool, *MockRechecker, *ecdsa.PrivateKey) { return setupPoolWithConfig(params.TestChainConfig) } -// reserver is a utility struct to sanity check that accounts are +// dummyReserver is a utility struct to sanity check that accounts are // properly reserved by the blobpool (no duplicate reserves or unreserves). -type reserver struct { +type dummyReserver struct { accounts map[common.Address]struct{} lock sync.RWMutex } -func newReserver() txpool.Reserver { - return &reserver{accounts: make(map[common.Address]struct{})} +func newReserver() reserver2.Reserver { + return &dummyReserver{accounts: make(map[common.Address]struct{})} } -func (r *reserver) Hold(addr common.Address) error { +func (r *dummyReserver) Hold(addrs ...common.Address) error { r.lock.Lock() defer r.lock.Unlock() - if _, exists := r.accounts[addr]; exists { - panic("already reserved") + for _, addr := range addrs { + if _, exists := r.accounts[addr]; exists { + panic("already reserved") + } + r.accounts[addr] = struct{}{} } - r.accounts[addr] = struct{}{} + return nil } -func (r *reserver) Release(addr common.Address) error { +func (r *dummyReserver) Release(addrs ...common.Address) error { r.lock.Lock() defer r.lock.Unlock() - if _, exists := r.accounts[addr]; !exists { - panic("not reserved") + for _, addr := range addrs { + if _, exists := r.accounts[addr]; !exists { + panic("not reserved") + } + delete(r.accounts, addr) } - delete(r.accounts, addr) return nil } -func (r *reserver) Has(address common.Address) bool { - return false // reserver only supports a single pool +func (r *dummyReserver) Has(address common.Address) bool { + return false // dummyReserver only supports a single pool } -func setupPoolWithConfig(config *params.ChainConfig) (*LegacyPool, *ecdsa.PrivateKey) { +func setupPoolWithConfig(config *params.ChainConfig) (*LegacyPool, *MockRechecker, *ecdsa.PrivateKey) { statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) blockchain := newTestBlockChain(config, 10000000, statedb, new(event.Feed)) key, _ := crypto.GenerateKey() - pool := New(testTxPoolConfig, blockchain) + rechecker := &MockRechecker{} + pool := New(testTxPoolConfig, log.NewNopLogger(), blockchain, reaplist.New(testTxEncoder{}), txtracker.New(), WithRecheck(rechecker)) if err := pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), newReserver()); err != nil { panic(err) } // wait for the pool to initialize <-pool.initDoneCh - return pool, key + return pool, rechecker, key } // validatePoolInternals checks various consistency invariants within the pool. @@ -320,6 +348,132 @@ func validateEvents(events chan core.NewTxsEvent, count int) error { return nil } +// TestMarkTxRemovedInvalidatesPending tests that when you have txs with nonces 4,5,6, and you submit a replacement for 4, +// txs 5 and 6 need to be revalidated. +func TestMarkTxRemovedInvalidatesPending(t *testing.T) { + pool, _, key := setupPool() + defer pool.Close() + + addr := crypto.PubkeyToAddress(key.PublicKey) + tx4 := pricedTransaction(4, 100000, big.NewInt(1), key) + tx5 := pricedTransaction(5, 100000, big.NewInt(1), key) + tx6 := pricedTransaction(6, 100000, big.NewInt(1), key) + replacement := pricedTransaction(4, 100000, big.NewInt(2), key) + + testAddBalance(pool, addr, big.NewInt(100000000000000)) + testSetNonce(pool, addr, 4) + pool.chain.(*testBlockChain).statedb.SetNonce(addr, 4, tracing.NonceChangeUnspecified) + + pool.all.Add(tx4) + pool.priced.Put(tx4) + pool.promoteTx(addr, tx4.Hash(), tx4) + + pool.all.Add(tx5) + pool.priced.Put(tx5) + pool.promoteTx(addr, tx5.Hash(), tx5) + + pool.all.Add(tx6) + pool.priced.Put(tx6) + pool.promoteTx(addr, tx6.Hash(), tx6) + + height := pool.chain.CurrentBlock().Number + + pending := pool.Rechecked(context.Background(), height, txpool.PendingFilter{}) + require.Len(t, pending[addr], 3) // at this point, should have txs 4,5,6. + + replaced, err := pool.add(replacement) + require.NoError(t, err) + require.True(t, replaced) + + pending = pool.Rechecked(context.Background(), height, txpool.PendingFilter{}) + require.Empty(t, pending[addr]) // now should have nothing, since tx 4 is now a new tx, and 5,6 depended on 4. + + pool.Reset(nil, nil) // recheck + + pending = pool.Rechecked(context.Background(), height, txpool.PendingFilter{}) + require.Len(t, pending[addr], 3) + require.Equal(t, []uint64{4, 5, 6}, []uint64{ + pending[addr][0].Tx.Nonce(), + pending[addr][1].Tx.Nonce(), + pending[addr][2].Tx.Nonce(), + }) + require.Equal(t, replacement.Hash(), pending[addr][0].Tx.Hash()) +} + +// TestMarkTxRemovedInvalidatesPendingReplacementFailsRecheck tests that when a +// replacement for nonce 4 later fails recheck, the rechecked pending snapshot +// stays empty and the higher nonces are demoted back to queue. +func TestMarkTxRemovedInvalidatesPendingReplacementFailsRecheck(t *testing.T) { + pool, rechecker, key := setupPool() + defer pool.Close() + + initialDropped := readCounterTotal(t, "txpool.pending.recheckdrop") + initialInvalidated := readCounterTotal(t, "txpool.pending.demoted.recheck") + + addr := crypto.PubkeyToAddress(key.PublicKey) + tx4 := pricedTransaction(4, 100000, big.NewInt(1), key) + tx5 := pricedTransaction(5, 100000, big.NewInt(1), key) + tx6 := pricedTransaction(6, 100000, big.NewInt(1), key) + replacement := pricedTransaction(4, 100000, big.NewInt(2), key) + + testAddBalance(pool, addr, big.NewInt(100000000000000)) + testSetNonce(pool, addr, 4) + pool.chain.(*testBlockChain).statedb.SetNonce(addr, 4, tracing.NonceChangeUnspecified) + + pool.all.Add(tx4) + pool.priced.Put(tx4) + pool.promoteTx(addr, tx4.Hash(), tx4) + + pool.all.Add(tx5) + pool.priced.Put(tx5) + pool.promoteTx(addr, tx5.Hash(), tx5) + + pool.all.Add(tx6) + pool.priced.Put(tx6) + pool.promoteTx(addr, tx6.Hash(), tx6) + + height := pool.chain.CurrentBlock().Number + + pending := pool.Rechecked(context.Background(), height, txpool.PendingFilter{}) + require.Len(t, pending[addr], 3) + + replaced, err := pool.add(replacement) + require.NoError(t, err) + require.True(t, replaced) + + pending = pool.Rechecked(context.Background(), height, txpool.PendingFilter{}) + require.Empty(t, pending[addr]) + + rechecker.SetRecheck(func(_ sdk.Context, tx *types.Transaction) (sdk.Context, error) { + if tx.Hash() == replacement.Hash() { + return sdk.Context{}, errors.New("replacement failed recheck") + } + return sdk.Context{}, nil + }) + + pool.Reset(nil, nil) + + pending = pool.Rechecked(context.Background(), height, txpool.PendingFilter{}) + require.Empty(t, pending[addr]) + + pool.mu.RLock() + require.Nil(t, pool.pending[addr]) + require.NotNil(t, pool.queue[addr]) + require.Len(t, pool.queue[addr].Flatten(), 2) + require.Equal(t, []uint64{5, 6}, []uint64{ + pool.queue[addr].Flatten()[0].Nonce(), + pool.queue[addr].Flatten()[1].Nonce(), + }) + require.Nil(t, pool.all.Get(replacement.Hash())) + + dropped := readCounterTotal(t, "txpool.pending.recheckdrop") - initialDropped + require.Equal(t, int64(1), dropped) + + invalidated := readCounterTotal(t, "txpool.pending.demoted.recheck") - initialInvalidated + require.Equal(t, int64(2), invalidated) + pool.mu.RUnlock() +} + func deriveSender(tx *types.Transaction) (common.Address, error) { return types.Sender(types.HomesteadSigner{}, tx) } @@ -368,7 +522,7 @@ func TestStateChangeDuringReset(t *testing.T) { tx0 := transaction(0, 100000, key) tx1 := transaction(1, 100000, key) - pool := New(testTxPoolConfig, blockchain) + pool := New(testTxPoolConfig, log.NewNopLogger(), blockchain, reaplist.New(testTxEncoder{}), txtracker.New()) pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), newReserver()) defer pool.Close() @@ -409,7 +563,7 @@ func testSetNonce(pool *LegacyPool, addr common.Address, nonce uint64) { func TestInvalidTransactions(t *testing.T) { t.Parallel() - pool, key := setupPool() + pool, _, key := setupPool() defer pool.Close() tx := transaction(0, 100, key) @@ -444,9 +598,11 @@ func TestInvalidTransactions(t *testing.T) { func TestQueue(t *testing.T) { t.Parallel() - pool, key := setupPool() + pool, rechecker, key := setupPool() defer pool.Close() + rechecker.SetRecheck(stateValidatingRecheck(pool)) + tx := transaction(0, 100, key) from, _ := deriveSender(tx) testAddBalance(pool, from, big.NewInt(1000)) @@ -475,7 +631,7 @@ func TestQueue(t *testing.T) { func TestQueue2(t *testing.T) { t.Parallel() - pool, key := setupPool() + pool, _, key := setupPool() defer pool.Close() tx1 := transaction(0, 100, key) @@ -489,7 +645,7 @@ func TestQueue2(t *testing.T) { pool.enqueueTx(tx2.Hash(), tx2, true) pool.enqueueTx(tx3.Hash(), tx3, true) - pool.promoteExecutables([]common.Address{from}) + pool.promoteExecutables([]common.Address{from}, nil, nil) if len(pool.pending) != 1 { t.Error("expected pending length to be 1, got", len(pool.pending)) } @@ -501,7 +657,7 @@ func TestQueue2(t *testing.T) { func TestNegativeValue(t *testing.T) { t.Parallel() - pool, key := setupPool() + pool, _, key := setupPool() defer pool.Close() tx, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(-1), 100, big.NewInt(1), nil), types.HomesteadSigner{}, key) @@ -515,7 +671,7 @@ func TestNegativeValue(t *testing.T) { func TestTipAboveFeeCap(t *testing.T) { t.Parallel() - pool, key := setupPoolWithConfig(eip1559Config) + pool, _, key := setupPoolWithConfig(eip1559Config) defer pool.Close() tx := dynamicFeeTx(0, 100, big.NewInt(1), big.NewInt(2), key) @@ -528,7 +684,7 @@ func TestTipAboveFeeCap(t *testing.T) { func TestVeryHighValues(t *testing.T) { t.Parallel() - pool, key := setupPoolWithConfig(eip1559Config) + pool, _, key := setupPoolWithConfig(eip1559Config) defer pool.Close() veryBigNumber := big.NewInt(1) @@ -548,7 +704,7 @@ func TestVeryHighValues(t *testing.T) { func TestChainFork(t *testing.T) { t.Parallel() - pool, key := setupPool() + pool, _, key := setupPool() defer pool.Close() addr := crypto.PubkeyToAddress(key.PublicKey) @@ -565,7 +721,7 @@ func TestChainFork(t *testing.T) { if _, err := pool.add(tx); err != nil { t.Error("didn't expect error", err) } - pool.removeTx(tx.Hash(), true, true) + pool.removeTx(tx.Hash(), true, true, txpool.RemovalReason("")) // reset the pool's internal state resetState() @@ -577,7 +733,7 @@ func TestChainFork(t *testing.T) { func TestDoubleNonce(t *testing.T) { t.Parallel() - pool, key := setupPool() + pool, _, key := setupPool() defer pool.Close() addr := crypto.PubkeyToAddress(key.PublicKey) @@ -628,7 +784,7 @@ func TestDoubleNonce(t *testing.T) { func TestMissingNonce(t *testing.T) { t.Parallel() - pool, key := setupPool() + pool, _, key := setupPool() defer pool.Close() addr := crypto.PubkeyToAddress(key.PublicKey) @@ -652,9 +808,23 @@ func TestNonceRecovery(t *testing.T) { t.Parallel() const n = 10 - pool, key := setupPool() + pool, rechecker, key := setupPool() defer pool.Close() + // Rechecker fails any tx whose nonce does not equal the sender's current + // state nonce. + rechecker.SetRecheck(func(ctx sdk.Context, tx *types.Transaction) (sdk.Context, error) { + from, err := types.Sender(pool.signer, tx) + if err != nil { + return ctx, err + } + stateNonce := pool.currentState.GetNonce(from) + if tx.Nonce() != stateNonce { + return ctx, fmt.Errorf("nonce mismatch: tx=%d state=%d", tx.Nonce(), stateNonce) + } + return ctx, nil + }) + addr := crypto.PubkeyToAddress(key.PublicKey) testSetNonce(pool, addr, n) testAddBalance(pool, addr, big.NewInt(100000000000000)) @@ -672,15 +842,68 @@ func TestNonceRecovery(t *testing.T) { } } +func TestScheduleForRemoval(t *testing.T) { + t.Parallel() + + pool, _, key := setupPool() + defer pool.Close() + + addr := crypto.PubkeyToAddress(key.PublicKey) + testAddBalance(pool, addr, big.NewInt(1_000_000_000_000)) + <-pool.requestReset(nil, nil) + + txs := []*types.Transaction{ + transaction(0, 100000, key), + transaction(1, 100000, key), + transaction(2, 100000, key), + transaction(3, 100000, key), + } + queuedTx := transaction(10, 100000, key) + + for _, tx := range txs { + require.NoError(t, pool.addRemote(tx)) + } + require.NoError(t, pool.addRemote(queuedTx)) + <-pool.requestReset(nil, nil) + + pending, queued := pool.ContentFrom(addr) + require.Len(t, pending, 4, "precondition: four pending txs") + require.Len(t, queued, 1, "precondition: one queued tx") + + pool.SetLatestNonce(addr, txs[1].Nonce()) + <-pool.requestReset(nil, nil) + + pending, queued = pool.ContentFrom(addr) + require.Len(t, pending, 2) + require.Equal(t, uint64(2), pending[0].Nonce()) + require.Equal(t, uint64(3), pending[1].Nonce()) + require.Len(t, queued, 1, "queued tx@10 is above threshold and survives") + + pool.SetLatestNonce(addr, txs[0].Nonce()) + <-pool.requestReset(nil, nil) + + pending, _ = pool.ContentFrom(addr) + require.Len(t, pending, 2, "lower-nonce schedule must be a no-op") + + pool.SetLatestNonce(addr, queuedTx.Nonce()) + <-pool.requestReset(nil, nil) + + pending, queued = pool.ContentFrom(addr) + require.Empty(t, pending, "pending drained by SetLatestNonce at nonce 10") + require.Empty(t, queued, "queued tx@10 drained by SetLatestNonce") +} + // Tests that if an account runs out of funds, any pending and queued transactions // are dropped. func TestDropping(t *testing.T) { t.Parallel() // Create a test account and fund it - pool, key := setupPool() + pool, rechecker, key := setupPool() defer pool.Close() + rechecker.SetRecheck(stateValidatingRecheck(pool)) + account := crypto.PubkeyToAddress(key.PublicKey) testAddBalance(pool, account, big.NewInt(1000)) @@ -785,10 +1008,13 @@ func TestPostponing(t *testing.T) { statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) - pool := New(testTxPoolConfig, blockchain) + rechecker := &MockRechecker{} + pool := New(testTxPoolConfig, log.NewNopLogger(), blockchain, reaplist.New(testTxEncoder{}), txtracker.New(), WithRecheck(rechecker)) pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), newReserver()) defer pool.Close() + rechecker.SetRecheck(stateValidatingRecheck(pool)) + // Create two test accounts to produce different gap profiles with keys := make([]*ecdsa.PrivateKey, 2) accs := make([]common.Address, len(keys)) @@ -896,7 +1122,7 @@ func TestGapFilling(t *testing.T) { t.Parallel() // Create a test account and fund it - pool, key := setupPool() + pool, _, key := setupPool() defer pool.Close() account := crypto.PubkeyToAddress(key.PublicKey) @@ -950,7 +1176,7 @@ func TestQueueAccountLimiting(t *testing.T) { t.Parallel() // Create a test account and fund it - pool, key := setupPool() + pool, _, key := setupPool() defer pool.Close() account := crypto.PubkeyToAddress(key.PublicKey) @@ -995,7 +1221,7 @@ func TestQueueGlobalLimiting(t *testing.T) { config.NoLocals = true config.GlobalQueue = config.AccountQueue*3 - 1 // reduce the queue limits to shorten test time (-1 to make it non divisible) - pool := New(config, blockchain) + pool := New(config, log.NewNopLogger(), blockchain, reaplist.New(testTxEncoder{}), txtracker.New()) pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), newReserver()) defer pool.Close() @@ -1047,7 +1273,7 @@ func TestQueueTimeLimiting(t *testing.T) { config := testTxPoolConfig config.Lifetime = time.Second - pool := New(config, blockchain) + pool := New(config, log.NewNopLogger(), blockchain, reaplist.New(testTxEncoder{}), txtracker.New()) pool.Init(config.PriceLimit, blockchain.CurrentBlock(), newReserver()) defer pool.Close() @@ -1161,7 +1387,7 @@ func TestPendingLimiting(t *testing.T) { t.Parallel() // Create a test account and fund it - pool, key := setupPool() + pool, _, key := setupPool() defer pool.Close() account := crypto.PubkeyToAddress(key.PublicKey) @@ -1208,7 +1434,7 @@ func TestPendingGlobalLimiting(t *testing.T) { config := testTxPoolConfig config.GlobalSlots = config.AccountSlots * 10 - pool := New(config, blockchain) + pool := New(config, log.NewNopLogger(), blockchain, reaplist.New(testTxEncoder{}), txtracker.New()) pool.Init(config.PriceLimit, blockchain.CurrentBlock(), newReserver()) defer pool.Close() @@ -1251,7 +1477,7 @@ func TestAllowedTxSize(t *testing.T) { t.Parallel() // Create a test account and fund it - pool, key := setupPool() + pool, _, key := setupPool() defer pool.Close() account := crypto.PubkeyToAddress(key.PublicKey) @@ -1307,7 +1533,7 @@ func TestCapClearsFromAll(t *testing.T) { config.AccountQueue = 2 config.GlobalSlots = 8 - pool := New(config, blockchain) + pool := New(config, log.NewNopLogger(), blockchain, reaplist.New(testTxEncoder{}), txtracker.New()) pool.Init(config.PriceLimit, blockchain.CurrentBlock(), newReserver()) defer pool.Close() @@ -1340,7 +1566,7 @@ func TestPendingMinimumAllowance(t *testing.T) { config := testTxPoolConfig config.GlobalSlots = 1 - pool := New(config, blockchain) + pool := New(config, log.NewNopLogger(), blockchain, reaplist.New(testTxEncoder{}), txtracker.New()) pool.Init(config.PriceLimit, blockchain.CurrentBlock(), newReserver()) defer pool.Close() @@ -1384,7 +1610,7 @@ func TestRepricing(t *testing.T) { statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) - pool := New(testTxPoolConfig, blockchain) + pool := New(testTxPoolConfig, log.NewNopLogger(), blockchain, reaplist.New(testTxEncoder{}), txtracker.New()) pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), newReserver()) defer pool.Close() @@ -1489,7 +1715,7 @@ func TestMinGasPriceEnforced(t *testing.T) { txPoolConfig := DefaultConfig txPoolConfig.NoLocals = true - pool := New(txPoolConfig, blockchain) + pool := New(txPoolConfig, log.NewNopLogger(), blockchain, reaplist.New(testTxEncoder{}), txtracker.New()) pool.Init(txPoolConfig.PriceLimit, blockchain.CurrentBlock(), newReserver()) defer pool.Close() @@ -1520,7 +1746,7 @@ func TestRepricingDynamicFee(t *testing.T) { t.Parallel() // Create the pool to test the pricing enforcement with - pool, _ := setupPoolWithConfig(eip1559Config) + pool, _, _ := setupPoolWithConfig(eip1559Config) defer pool.Close() // Keep track of transaction events to ensure all executables get announced @@ -1638,7 +1864,7 @@ func TestUnderpricing(t *testing.T) { config.GlobalSlots = 2 config.GlobalQueue = 2 - pool := New(config, blockchain) + pool := New(config, log.NewNopLogger(), blockchain, reaplist.New(testTxEncoder{}), txtracker.New()) pool.Init(config.PriceLimit, blockchain.CurrentBlock(), newReserver()) defer pool.Close() @@ -1728,7 +1954,7 @@ func TestStableUnderpricing(t *testing.T) { config.GlobalSlots = 128 config.GlobalQueue = 0 - pool := New(config, blockchain) + pool := New(config, log.NewNopLogger(), blockchain, reaplist.New(testTxEncoder{}), txtracker.New()) pool.Init(config.PriceLimit, blockchain.CurrentBlock(), newReserver()) defer pool.Close() @@ -1788,7 +2014,7 @@ func TestStableUnderpricing(t *testing.T) { func TestUnderpricingDynamicFee(t *testing.T) { t.Parallel() - pool, _ := setupPoolWithConfig(eip1559Config) + pool, _, _ := setupPoolWithConfig(eip1559Config) defer pool.Close() pool.config.GlobalSlots = 2 @@ -1871,7 +2097,7 @@ func TestUnderpricingDynamicFee(t *testing.T) { func TestDualHeapEviction(t *testing.T) { t.Parallel() - pool, _ := setupPoolWithConfig(eip1559Config) + pool, _, _ := setupPoolWithConfig(eip1559Config) defer pool.Close() pool.config.GlobalSlots = 10 @@ -1931,7 +2157,7 @@ func TestDeduplication(t *testing.T) { statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) - pool := New(testTxPoolConfig, blockchain) + pool := New(testTxPoolConfig, log.NewNopLogger(), blockchain, reaplist.New(testTxEncoder{}), txtracker.New()) pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), newReserver()) defer pool.Close() @@ -1998,7 +2224,7 @@ func TestReplacement(t *testing.T) { statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) - pool := New(testTxPoolConfig, blockchain) + pool := New(testTxPoolConfig, log.NewNopLogger(), blockchain, reaplist.New(testTxEncoder{}), txtracker.New()) pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), newReserver()) defer pool.Close() @@ -2076,7 +2302,7 @@ func TestReplacementDynamicFee(t *testing.T) { t.Parallel() // Create the pool to test the pricing enforcement with - pool, key := setupPoolWithConfig(eip1559Config) + pool, _, key := setupPoolWithConfig(eip1559Config) defer pool.Close() testAddBalance(pool, crypto.PubkeyToAddress(key.PublicKey), big.NewInt(1000000000)) @@ -2190,7 +2416,7 @@ func TestStatusCheck(t *testing.T) { statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) - pool := New(testTxPoolConfig, blockchain) + pool := New(testTxPoolConfig, log.NewNopLogger(), blockchain, reaplist.New(testTxEncoder{}), txtracker.New()) pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), newReserver()) defer pool.Close() @@ -2263,7 +2489,7 @@ func TestSetCodeTransactions(t *testing.T) { statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) blockchain := newTestBlockChain(params.MergedTestChainConfig, 1000000, statedb, new(event.Feed)) - pool := New(testTxPoolConfig, blockchain) + pool := New(testTxPoolConfig, log.NewNopLogger(), blockchain, reaplist.New(testTxEncoder{}), txtracker.New()) pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), newReserver()) defer pool.Close() @@ -2293,8 +2519,8 @@ func TestSetCodeTransactions(t *testing.T) { pending: 1, run: func(name string) { aa := common.Address{0xaa, 0xaa} - statedb.SetCode(addrA, append(types.DelegationPrefix, aa.Bytes()...)) - statedb.SetCode(aa, []byte{byte(vm.ADDRESS), byte(vm.PUSH0), byte(vm.SSTORE)}) + statedb.SetCode(addrA, append(types.DelegationPrefix, aa.Bytes()...), 0x0) + statedb.SetCode(aa, []byte{byte(vm.ADDRESS), byte(vm.PUSH0), byte(vm.SSTORE)}, 0x0) // Send gapped transaction, it should be rejected. if err := pool.addRemoteSync(pricedTransaction(2, 100000, big.NewInt(1), keyA)); !errors.Is(err, ErrOutOfOrderTxFromDelegated) { @@ -2318,7 +2544,7 @@ func TestSetCodeTransactions(t *testing.T) { } // Reset the delegation, avoid leaking state into the other tests - statedb.SetCode(addrA, nil) + statedb.SetCode(addrA, nil, 0x0) }, }, { @@ -2561,10 +2787,13 @@ func TestSetCodeTransactionsReorg(t *testing.T) { statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) blockchain := newTestBlockChain(params.MergedTestChainConfig, 1000000, statedb, new(event.Feed)) - pool := New(testTxPoolConfig, blockchain) + rechecker := &MockRechecker{} + pool := New(testTxPoolConfig, log.NewNopLogger(), blockchain, reaplist.New(testTxEncoder{}), txtracker.New(), WithRecheck(rechecker)) pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), newReserver()) defer pool.Close() + rechecker.SetRecheck(stateValidatingRecheck(pool)) + // Create the test accounts var ( keyA, _ = crypto.GenerateKey() @@ -2584,7 +2813,7 @@ func TestSetCodeTransactionsReorg(t *testing.T) { } // Simulate the chain moving blockchain.statedb.SetNonce(addrA, 1, tracing.NonceChangeAuthorization) - blockchain.statedb.SetCode(addrA, types.AddressToDelegation(auth.Address)) + blockchain.statedb.SetCode(addrA, types.AddressToDelegation(auth.Address), 0x0) <-pool.requestReset(nil, nil) // Set an authorization for 0x00 auth, _ = types.SignSetCode(keyA, types.SetCodeAuthorization{ @@ -2602,7 +2831,7 @@ func TestSetCodeTransactionsReorg(t *testing.T) { } // Simulate the chain moving blockchain.statedb.SetNonce(addrA, 2, tracing.NonceChangeAuthorization) - blockchain.statedb.SetCode(addrA, nil) + blockchain.statedb.SetCode(addrA, nil, 0x0) <-pool.requestReset(nil, nil) // Now send two transactions from addrA if err := pool.addRemoteSync(pricedTransaction(2, 100000, big.NewInt(1000), keyA)); err != nil { @@ -2613,6 +2842,104 @@ func TestSetCodeTransactionsReorg(t *testing.T) { } } +func TestQueuedPromotionOnReset(t *testing.T) { + t.Parallel() + + pool, _, _ := setupPool() + defer pool.Close() + + // create transactions with sequential nonces + key, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(key.PublicKey) + + // mock the on chain nonce for this account as 0 + testSetNonce(pool, addr, 0) + testAddBalance(pool, addr, big.NewInt(1000000000000000)) + + // create two txs and add both transactions to the pool synchronously, so + // they will both go to pending + tx0 := transaction(0, 100000, key) + tx1 := transaction(1, 100000, key) + require.NoError(t, pool.addRemoteSync(tx0)) + require.NoError(t, pool.addRemoteSync(tx1)) + + // create another sequential tx based on the previous two, but only enqueue + // it + tx2 := transaction(2, 100000, key) + replaced, err := pool.enqueueTx(tx2.Hash(), tx2, true) + require.False(t, replaced, "enqueuing tx should not have replaced anything") + require.NoError(t, err) + + // ensure we have 2 txs in pending and 1 in queued + pending, queued := pool.Stats() + require.Equal(t, 2, pending, "incorrect amount of txs in the pending pool after setup") + require.Equal(t, 1, queued, "incorrect amount of txs in queued pool after setup") + + // now we reset the pool to a new height. this reset will trigger a mempool + // state reset, plus a promotion of our queued tx to pending + oldHead := pool.currentHead.Load() + oldHead.BaseFee = big.NewInt(100) // needed for testing + newHead := *oldHead + newHead.Number = new(big.Int).Add(oldHead.Number, big.NewInt(1)) + pool.Reset(oldHead, &newHead) + + pending, queued = pool.Stats() + require.Equal(t, 3, pending, "incorrect amount of txs in the pending pool after reset") + require.Equal(t, 0, queued, "incorrect amount of txs in queued pool after reset") +} + +func TestQueuedPromotionOnResetWithStalePending(t *testing.T) { + t.Parallel() + + pool, _, _ := setupPool() + defer pool.Close() + + // create transactions with sequential nonces + key, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(key.PublicKey) + + // mock the on chain nonce for this account as 0 + testSetNonce(pool, addr, 0) + testAddBalance(pool, addr, big.NewInt(1000000000000000)) + + // create two txs and add both transactions to the pool synchronously, so + // they will both go to pending + tx0 := transaction(0, 100000, key) + tx1 := transaction(1, 100000, key) + require.NoError(t, pool.addRemoteSync(tx0)) + require.NoError(t, pool.addRemoteSync(tx1)) + + // create another tx with a nonce gap from the previous two, this will stay + // enqueued. + tx3 := transaction(3, 100000, key) + require.NoError(t, pool.addRemoteSync(tx3)) + + // ensure we have 2 txs in pending and 1 in queued + pending, queued := pool.Stats() + require.Equal(t, 2, pending, "incorrect amount of txs in the pending pool after setup") + require.Equal(t, 1, queued, "incorrect amount of txs in queued pool after setup") + + // mock that tx0 and tx1 **AND** tx2 were included on chain (simulating + // that another node had tx2, and filled the nonce gap for us) + pool.SetLatestNonce(addr, tx0.Nonce()) + pool.SetLatestNonce(addr, tx1.Nonce()) + tx2 := transaction(2, 100000, key) + pool.SetLatestNonce(addr, tx2.Nonce()) + + // now we reset the pool to a new height. this reset will trigger a mempool + // state reset, plus a promotion of our queued tx to pending, and dropping + // the olds txs that were scheduled for removal + oldHead := pool.currentHead.Load() + oldHead.BaseFee = big.NewInt(100) // needed for testing + newHead := *oldHead + newHead.Number = new(big.Int).Add(oldHead.Number, big.NewInt(1)) + pool.Reset(oldHead, &newHead) + + pending, queued = pool.Stats() + require.Equal(t, 1, pending, "incorrect amount of txs in the pending pool after reset") + require.Equal(t, 0, queued, "incorrect amount of txs in queued pool after reset") +} + // TestRemoveTxTruncatePoolRace is a regression test for a race condition // between removing txs and runReorg loop. Run this with the -race flag to // ensure that there is no race condition between the two functions. @@ -2620,7 +2947,7 @@ func TestRemoveTxTruncatePoolRace(t *testing.T) { statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) blockchain := newTestBlockChain(params.MergedTestChainConfig, 1000000, statedb, new(event.Feed)) - pool := New(testTxPoolConfig, blockchain) + pool := New(testTxPoolConfig, log.NewNopLogger(), blockchain, reaplist.New(testTxEncoder{}), txtracker.New()) err := pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), newReserver()) if err != nil { t.Fatalf("failed to init pool: %v", err) @@ -2652,7 +2979,8 @@ func TestRemoveTxTruncatePoolRace(t *testing.T) { go func() { defer wg.Done() for range 5 { - pool.runReorg(make(chan struct{}), nil, nil, nil) + input := reorgInput{done: make(chan struct{})} + pool.runReorg(input) } }() @@ -2661,13 +2989,462 @@ func TestRemoveTxTruncatePoolRace(t *testing.T) { go func() { defer wg.Done() for _, hash := range hashes { - _ = pool.RemoveTx(hash, false, true) + _ = pool.RemoveTx(hash, false, true, "") } }() wg.Wait() } +// TestPromoteExecutablesRecheckTx tests that promoteExecutables properly removes +// a transaction from all pools if it fails the RecheckTxFn. +func TestPromoteExecutablesRecheckTx(t *testing.T) { + pool, rechecker, key := setupPool() + defer pool.Close() + + initialDropped := readCounterTotal(t, "txpool.queued.recheckdrop") + + // Create transactions with sequential nonces + tx0 := transaction(0, 100000, key) + tx1 := transaction(1, 100000, key) + tx2 := transaction(2, 100000, key) + + from, _ := deriveSender(tx0) + testAddBalance(pool, from, big.NewInt(100000000000000)) + + // Enqueue all txs + if _, err := pool.enqueueTx(tx0.Hash(), tx0, true); err != nil { + t.Error("error enqueuing tx0 to queued pool", "err", err) + } + if _, err := pool.enqueueTx(tx1.Hash(), tx1, true); err != nil { + t.Error("error enqueuing tx1 to queued pool", "err", err) + } + if _, err := pool.enqueueTx(tx2.Hash(), tx2, true); err != nil { + t.Error("error enqueuing tx2 to queued pool", "err", err) + } + + // Verify all transactions are in queued + pool.mu.RLock() + if pool.queue[from].Len() != 3 { + t.Errorf("queued transaction count mismatch: have %d, want %d", pool.queue[from].Len(), 3) + } + if pool.all.Count() != 3 { + t.Errorf("total transaction count mismatch: have %d, want %d", pool.all.Count(), 3) + } + pool.mu.RUnlock() + + // Set up recheckFn to fail tx1 + rechecker.SetRecheck(func(_ sdk.Context, tx *types.Transaction) (sdk.Context, error) { + if tx.Nonce() == 1 { + return sdk.Context{}, errors.New("recheck failed for tx1") + } + return sdk.Context{}, nil + }) + + // Reset will always try and promote executables from queued to go to + // pending. This will call pool.RecheckTxFn and block until the Reset is + // done. + pool.Reset(nil, nil) + + // Verify tx1 was removed from all pools (failed recheck) and tx2 stayed in + // queued, and tx0 got promoted to pending + pool.mu.RLock() + if pool.pending[from] == nil || pool.pending[from].Len() != 1 || pool.pending[from].txs.Get(tx0.Nonce()) == nil { + t.Errorf("pending pool should have only tx1 included") + } + if pool.queue[from] == nil || pool.queue[from].Len() != 1 || pool.queue[from].txs.Get(2) == nil { + t.Errorf("queued pool should have only tx2 included") + } + if pool.all.Get(tx1.Hash()) != nil { + t.Errorf("tx1 should be removed from all pools after failing recheck") + } + if pool.all.Get(tx0.Hash()) == nil { + t.Errorf("tx0 should still be in the all lookup") + } + if pool.all.Get(tx2.Hash()) == nil { + t.Errorf("tx2 should still be in the all lookup") + } + dropped := readCounterTotal(t, "txpool.queued.recheckdrop") - initialDropped + if dropped != 1 { + t.Error("1 queued recheck drops should have been recorded by meter delta, got", dropped) + } + pool.mu.RUnlock() +} + +// TestDemoteUnexecutablesRecheckTx tests that demoteUnexecutables properly +// removes a transaction from all pools if it fails the RecheckTxFn and that +// subsequent nonces are moved back into the queued pool. +func TestDemoteUnexecutablesRecheckTx(t *testing.T) { + pool, rechecker, _ := setupPool() + defer pool.Close() + + initialDropped := readCounterTotal(t, "txpool.pending.recheckdrop") + initialInvalidated := readCounterTotal(t, "txpool.pending.demoted.recheck") + + // Create transactions with sequential nonces + key1, _ := crypto.GenerateKey() + key2, _ := crypto.GenerateKey() + tx10, tx20 := transaction(0, 100000, key1), transaction(0, 100000, key2) + tx11, tx21 := transaction(1, 100000, key1), transaction(1, 100000, key2) + tx12, tx22 := transaction(2, 100000, key1), transaction(2, 100000, key2) + + from1, _ := deriveSender(tx10) + from2, _ := deriveSender(tx20) + testAddBalance(pool, from1, big.NewInt(100000000000000)) + testAddBalance(pool, from2, big.NewInt(100000000000000)) + + // Add all transactions to the pool, they should all go to queued, then + // this will internally call requestPromoteExecutables + pool.addRemoteSync(tx10) + pool.addRemoteSync(tx11) + pool.addRemoteSync(tx12) + pool.addRemoteSync(tx20) + pool.addRemoteSync(tx21) + pool.addRemoteSync(tx22) + + // Verify all transactions are in pending + pool.mu.RLock() + if pool.pending[from1].Len() != 3 { + t.Errorf("pending transaction count mismatch for from1: have %d, want %d", pool.pending[from1].Len(), 3) + } + if pool.queue[from1] != nil { + t.Errorf("queued transaction count mismatch for from1: have %d, want %d", pool.queue[from1].Len(), 0) + } + if pool.pending[from2].Len() != 3 { + t.Errorf("pending transaction count mismatch for from2: have %d, want %d", pool.pending[from1].Len(), 3) + } + if pool.queue[from2] != nil { + t.Errorf("queue transaction count mismatch for from2: have %d, want %d", pool.queue[from1].Len(), 0) + } + if pool.all.Count() != 6 { + t.Errorf("total transaction count mismatch: have %d, want %d", pool.all.Count(), 6) + } + pool.mu.RUnlock() + + // Set up recheckFn to fail tx10 and tx22 + rechecker.SetRecheck(func(_ sdk.Context, tx *types.Transaction) (sdk.Context, error) { + if tx == tx10 || tx == tx22 { + return sdk.Context{}, errors.New("recheck failed") + } + return sdk.Context{}, nil + }) + + // Trigger demoteUnexecutables via Reset + pool.Reset(nil, nil) + + // Verify tx10 and tx22 were removed from all pools (failed recheck). + // + // Since the pending pool is strict, all txs after the removed txs will + // also be invalidated and dropped back down to the queued pool + pool.mu.RLock() + if pool.all.Get(tx10.Hash()) != nil { + t.Errorf("tx10 should be removed from all pools after failing recheck") + } + if pool.all.Get(tx22.Hash()) != nil { + t.Errorf("tx22 should be removed from all pools after failing recheck") + } + + if pool.pending[from1] != nil { + t.Errorf("pending should have 0 txs from from1") + } + if pool.queue[from1].Len() != 2 { + t.Errorf("from1 should have 2 queued transactions") + } + + if pool.pending[from2].Len() != 2 { + t.Errorf("pending should have 2 txs from from2") + } + if pool.queue[from2] != nil { + t.Errorf("from2 should have no queued transactions") + } + + // tx10 and tx22 got dropped + dropped := readCounterTotal(t, "txpool.pending.recheckdrop") - initialDropped + if dropped != 2 { + t.Error("2 pending recheck drops should have been recorded by meter delta, got", dropped) + } + + // tx11 and tx12 were invalidated since a tx from the same sender with a + // lower nonce was just dropped, they need to be validated again before + // being moved to pending, so they are back in queued + invaliated := readCounterTotal(t, "txpool.pending.demoted.recheck") - initialInvalidated + if invaliated != 2 { + t.Error("2 pending recheck invalidate should have been recorded by meter delta, got", invaliated) + } + pool.mu.RUnlock() +} + +// TestResetCancellation tests that when a reset is in progress and CancelReset +// is called, resetting the pool is stopped. +func TestResetCancellation(t *testing.T) { + pool, rechecker, _ := setupPool() + defer pool.Close() + + // Create many accounts with multiple transactions each + numAccounts := 20 + txsPerAccount := 10 + accounts := make([]*ecdsa.PrivateKey, numAccounts) + + for i := 0; i < numAccounts; i++ { + key, _ := crypto.GenerateKey() + accounts[i] = key + addr := crypto.PubkeyToAddress(key.PublicKey) + testAddBalance(pool, addr, big.NewInt(100000000000000)) + + // Add transactions to pending + for j := 0; j < txsPerAccount; j++ { + tx := transaction(uint64(j), 100000, key) + pool.addRemoteSync(tx) + } + } + + // Verify all transactions are in pending + pool.mu.RLock() + totalPending := 0 + for _, key := range accounts { + addr := crypto.PubkeyToAddress(key.PublicKey) + if list := pool.pending[addr]; list != nil { + totalPending += list.Len() + } + } + expectedTotal := numAccounts * txsPerAccount + if totalPending != expectedTotal { + t.Fatalf("Expected %d pending transactions, got %d", expectedTotal, totalPending) + } + pool.mu.RUnlock() + + // Track how many transactions were processed + var processedCount atomic.Int64 + + // Set up rechecker to be slow so we can cancel mid-iteration + rechecker.SetRecheck(func(ctx sdk.Context, tx *types.Transaction) (sdk.Context, error) { + processedCount.Add(1) + time.Sleep(50 * time.Millisecond) // Make each recheck take time + return sdk.Context{}, nil + }) + + // Start reset in a goroutine + resetDone := make(chan struct{}) + go func() { + header := pool.currentHead.Load() + header.BaseFee = big.NewInt(100) + pool.Reset(header, header) + close(resetDone) + }() + + // Give reset time to start processing some transactions + time.Sleep(200 * time.Millisecond) + + // Cancel the reset while it's still processing + pool.CancelReset() + + // Wait for reset to complete + <-resetDone + + // Verify that not all transactions were processed (because we cancelled early) + processed := processedCount.Load() + if processed >= int64(expectedTotal) { + t.Errorf("Expected fewer than %d transactions to be processed due to cancellation, but %d were processed", expectedTotal, processed) + } + // Verify that at least some transactions were processed before cancellation + if processed == 0 { + t.Error("Expected some transactions to be processed before cancellation") + } +} + +func TestRecheckedFutureHeight(t *testing.T) { + t.Parallel() + + pool, _, _ := setupPool() + defer pool.Close() + + ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond) + defer cancel() + + result := pool.Rechecked(ctx, big.NewInt(999), txpool.PendingFilter{}) + if result != nil { + t.Fatalf("expected nil from Pending when HeightSync times out, got %v", result) + } +} + +func TestReplacementReapDeferral(t *testing.T) { + gasP := func(g int64) *int64 { return &g } + + cases := []struct { + name string + replacements func(key *ecdsa.PrivateKey) []*types.Transaction + failRecheckGasPrice *int64 + presentGasPrice *int64 + }{ + { + name: "replacement tx that fails recheck is never reaped", + replacements: func(key *ecdsa.PrivateKey) []*types.Transaction { + return []*types.Transaction{ + pricedTransaction(0, 100000, big.NewInt(2), key), + } + }, + failRecheckGasPrice: gasP(2), + }, + { + name: "replacement tx that passes recheck is reaped", + replacements: func(key *ecdsa.PrivateKey) []*types.Transaction { + return []*types.Transaction{ + pricedTransaction(0, 100000, big.NewInt(2), key), + } + }, + presentGasPrice: gasP(2), + }, + { + // Chain of replacements within one block: each supersedes the + // previous in pending. Exactly one push happens at demote + // time, for the latest hash; earlier hashes are silently + // discarded when toReap is cleared. + name: "multi replacement txs only reaps latest", + replacements: func(key *ecdsa.PrivateKey) []*types.Transaction { + return []*types.Transaction{ + pricedTransaction(0, 100000, big.NewInt(2), key), + pricedTransaction(0, 100000, big.NewInt(3), key), + pricedTransaction(0, 100000, big.NewInt(4), key), + pricedTransaction(0, 100000, big.NewInt(5), key), + } + }, + presentGasPrice: gasP(5), + }, + } + + // findByGasPrice returns the tx in txs whose gas price matches. + // Replacements within a chain have unique gas prices, so this picks + // out exactly one tx. + findByGasPrice := func(txs []*types.Transaction, gasPrice int64) *types.Transaction { + target := big.NewInt(gasPrice) + for _, tx := range txs { + if tx.GasPrice().Cmp(target) == 0 { + return tx + } + } + return nil + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + pool, rechecker, key := setupPool() + defer pool.Close() + + addr := crypto.PubkeyToAddress(key.PublicKey) + testAddBalance(pool, addr, big.NewInt(100000000000000)) + + replacements := tc.replacements(key) + + // base tx that replacements will be replacing + base := pricedTransaction(0, 100000, big.NewInt(1), key) + directPromoteToPending(t, pool, addr, base) + _ = reapAllHashes(pool) // drain initial promote push + + if tc.failRecheckGasPrice != nil { + fail := big.NewInt(*tc.failRecheckGasPrice) + rechecker.SetRecheck(func(_ sdk.Context, tx *types.Transaction) (sdk.Context, error) { + if tx.GasPrice().Cmp(fail) == 0 { + return sdk.Context{}, errors.New("recheck fails for gas price") + } + return sdk.Context{}, nil + }) + } + + for _, r := range replacements { + replaced, err := pool.add(r) + require.NoError(t, err) + require.True(t, replaced) + require.Contains(t, pool.toReap, r.Hash()) + } + require.Empty(t, reapAllHashes(pool), "replacements must be deferred until next demote") + + pool.Reset(nil, nil) + + reaped := reapAllHashes(pool) + require.Empty(t, pool.toReap) + + if tc.presentGasPrice != nil { + want := findByGasPrice(replacements, *tc.presentGasPrice) + require.NotNil(t, pool.all.Get(want.Hash()), "tx at presentGasPrice should remain in pool.all") + require.Contains(t, reaped, want.Hash(), "tx at presentGasPrice should be on the reap list") + } + + if tc.failRecheckGasPrice != nil { + want := findByGasPrice(replacements, *tc.failRecheckGasPrice) + require.Nil(t, pool.all.Get(want.Hash()), "tx at failRecheckGasPrice should be removed from pool.all") + require.NotContains(t, reaped, want.Hash(), "tx at failRecheckGasPrice should not be on the reap list") + } + }) + } +} + +func TestReplacementDemotedToQueueReapsViaPromote(t *testing.T) { + pool, rechecker, key := setupPool() + defer pool.Close() + + addr := crypto.PubkeyToAddress(key.PublicKey) + testAddBalance(pool, addr, big.NewInt(100000000000000)) + + tx0 := pricedTransaction(0, 100000, big.NewInt(1), key) + tx1 := pricedTransaction(1, 100000, big.NewInt(1), key) + directPromoteToPending(t, pool, addr, tx0) + directPromoteToPending(t, pool, addr, tx1) + _ = reapAllHashes(pool) + + replacement := pricedTransaction(1, 100000, big.NewInt(2), key) + replaced, err := pool.add(replacement) + require.NoError(t, err) + require.True(t, replaced) + require.Contains(t, pool.toReap, replacement.Hash()) + require.Empty(t, reapAllHashes(pool)) + + rechecker.SetRecheck(func(_ sdk.Context, tx *types.Transaction) (sdk.Context, error) { + if tx.Hash() == tx0.Hash() { + return sdk.Context{}, errors.New("tx0 fails") + } + return sdk.Context{}, nil + }) + pool.Reset(nil, nil) + + require.Nil(t, pool.all.Get(tx0.Hash())) + require.NotNil(t, pool.all.Get(replacement.Hash())) + require.Nil(t, pool.pending[addr]) + require.NotNil(t, pool.queue[addr]) + require.Equal(t, 1, pool.queue[addr].Len()) + require.Empty(t, pool.toReap) + require.Empty(t, reapAllHashes(pool), "replacement must not be reaped after demotion") + + // advance state nonce so the replacement is ready on the next reset. + testSetNonce(pool, addr, 1) + rechecker.SetRecheck(nil) + pool.Reset(nil, nil) + + // ensure we now reap the valid promoted tx + require.Equal(t, []common.Hash{replacement.Hash()}, reapAllHashes(pool)) + require.Empty(t, pool.toReap) +} + +func reapAllHashes(pool *LegacyPool) []common.Hash { + raw := pool.reapList.Reap(0, 0) + out := make([]common.Hash, 0, len(raw)) + for _, b := range raw { + out = append(out, common.BytesToHash(b)) + } + return out +} + +func directPromoteToPending(t *testing.T, pool *LegacyPool, addr common.Address, tx *types.Transaction) { + t.Helper() + if _, hasPending := pool.pending[addr]; !hasPending { + if _, hasQueue := pool.queue[addr]; !hasQueue { + require.NoError(t, pool.reserver.Hold(addr)) + } + } + pool.all.Add(tx) + pool.priced.Put(tx) + pool.promoteTx(addr, tx.Hash(), tx) +} + // Benchmarks the speed of validating the contents of the pending queue of the // transaction pool. func BenchmarkPendingDemotion100(b *testing.B) { benchmarkPendingDemotion(b, 100) } @@ -2676,7 +3453,7 @@ func BenchmarkPendingDemotion10000(b *testing.B) { benchmarkPendingDemotion(b, 1 func benchmarkPendingDemotion(b *testing.B, size int) { // Add a batch of transactions to a pool one by one - pool, key := setupPool() + pool, _, key := setupPool() defer pool.Close() account := crypto.PubkeyToAddress(key.PublicKey) @@ -2689,7 +3466,7 @@ func benchmarkPendingDemotion(b *testing.B, size int) { // Benchmark the speed of pool validation b.ResetTimer() for i := 0; i < b.N; i++ { - pool.demoteUnexecutables() + pool.demoteUnexecutables(nil, nil) } } @@ -2701,7 +3478,7 @@ func BenchmarkFuturePromotion10000(b *testing.B) { benchmarkFuturePromotion(b, 1 func benchmarkFuturePromotion(b *testing.B, size int) { // Add a batch of transactions to a pool one by one - pool, key := setupPool() + pool, _, key := setupPool() defer pool.Close() account := crypto.PubkeyToAddress(key.PublicKey) @@ -2714,7 +3491,7 @@ func benchmarkFuturePromotion(b *testing.B, size int) { // Benchmark the speed of pool validation b.ResetTimer() for i := 0; i < b.N; i++ { - pool.promoteExecutables(nil) + pool.promoteExecutables(nil, nil, nil) } } @@ -2725,7 +3502,7 @@ func BenchmarkBatchInsert10000(b *testing.B) { benchmarkBatchInsert(b, 10000) } func benchmarkBatchInsert(b *testing.B, size int) { // Generate a batch of transactions to enqueue into the pool - pool, key := setupPool() + pool, _, key := setupPool() defer pool.Close() account := crypto.PubkeyToAddress(key.PublicKey) @@ -2748,7 +3525,7 @@ func benchmarkBatchInsert(b *testing.B, size int) { // Benchmarks the speed of batch transaction insertion in case of multiple accounts. func BenchmarkMultiAccountBatchInsert(b *testing.B) { // Generate a batch of transactions to enqueue into the pool - pool, _ := setupPool() + pool, _, _ := setupPool() defer pool.Close() b.ReportAllocs() batches := make(types.Transactions, b.N) @@ -2765,3 +3542,56 @@ func BenchmarkMultiAccountBatchInsert(b *testing.B) { pool.addRemotesSync([]*types.Transaction{tx}) } } + +// stateValidatingRecheck returns a RecheckFn that mocks behavior these tests +// rely on, in a production environment it is safe to assume these checks would +// happen via the chains ante handler. +func stateValidatingRecheck(pool *LegacyPool) func(sdk.Context, *types.Transaction) (sdk.Context, error) { + return func(ctx sdk.Context, tx *types.Transaction) (sdk.Context, error) { + from, err := types.Sender(pool.signer, tx) + if err != nil { + return ctx, err + } + stateNonce := pool.currentState.GetNonce(from) + if tx.Nonce() < stateNonce { + return ctx, fmt.Errorf("nonce too low: tx=%d state=%d", tx.Nonce(), stateNonce) + } + gasLimit := pool.chain.(*testBlockChain).gasLimit.Load() + if tx.Gas() > gasLimit { + return ctx, fmt.Errorf("gas %d exceeds block limit %d", tx.Gas(), gasLimit) + } + balance := pool.currentState.GetBalance(from).ToBig() + if tx.Cost().Cmp(balance) > 0 { + return ctx, fmt.Errorf("insufficient funds: cost=%s balance=%s", tx.Cost(), balance) + } + return ctx, nil + } +} + +type MockRechecker struct { + RecheckFn func(ctx sdk.Context, tx *types.Transaction) (sdk.Context, error) + lock sync.Mutex +} + +func (mr *MockRechecker) SetRecheck(recheck func(ctx sdk.Context, tx *types.Transaction) (sdk.Context, error)) { + mr.lock.Lock() + defer mr.lock.Unlock() + + mr.RecheckFn = recheck +} + +func (mr *MockRechecker) GetContext() (sdk.Context, func()) { + return sdk.Context{}, func() {} +} + +func (mr *MockRechecker) RecheckEVM(ctx sdk.Context, tx *types.Transaction) (sdk.Context, error) { + mr.lock.Lock() + defer mr.lock.Unlock() + + if mr.RecheckFn != nil { + return mr.RecheckFn(ctx, tx) + } + return sdk.Context{}, nil +} + +func (mr *MockRechecker) Update(_ sdk.Context, _ *types.Header) {} diff --git a/mempool/txpool/legacypool/list.go b/mempool/txpool/legacypool/list.go index 736c28ec..31365ed9 100644 --- a/mempool/txpool/legacypool/list.go +++ b/mempool/txpool/legacypool/list.go @@ -18,6 +18,7 @@ package legacypool import ( "container/heap" + "context" "math" "math/big" "slices" @@ -121,6 +122,22 @@ func (m *SortedMap) Filter(filter func(*types.Transaction) bool) types.Transacti return removed } +// FilterSorted iterates over the list of transactions and removes all of them +// for which the specified function evaluates to true. FilterSorted iterates +// over transactions from lowest nonce to highest nonce. +// FilterSorted, as opposed to 'filterSorted', re-initialises the heap after +// the operation is done. If you want to do several consecutive filterings, +// it's therefore better to first do a .filterSorted(func1) followed by +// .FilterSorted(func2) or reheap() +func (m *SortedMap) FilterSorted(filter func(*types.Transaction) bool) types.Transactions { + removed := m.filterSorted(filter) + // If transactions were removed, the heap and cache are ruined + if len(removed) > 0 { + m.reheap() + } + return removed +} + func (m *SortedMap) reheap() { *m.index = make([]uint64, 0, len(m.items)) for nonce := range m.items { @@ -132,6 +149,27 @@ func (m *SortedMap) reheap() { m.cacheMu.Unlock() } +// filterSorted is the same as filter, but iteration over the transactions goes +// from lowest to highest nonce. +func (m *SortedMap) filterSorted(filter func(tx *types.Transaction) bool) types.Transactions { + var removed types.Transactions + + // Flatten sorts txs by nonce in ascending order + sorted := m.flatten() + for _, tx := range sorted { + if filter(tx) { + removed = append(removed, tx) + delete(m.items, tx.Nonce()) + } + } + if len(removed) > 0 { + m.cacheMu.Lock() + m.cache = nil + m.cacheMu.Unlock() + } + return removed +} + // filter is identical to Filter, but **does not** regenerate the heap. This method // should only be used if followed immediately by a call to Filter or reheap() func (m *SortedMap) filter(filter func(*types.Transaction) bool) types.Transactions { @@ -353,7 +391,7 @@ func (l *list) Forward(threshold uint64) types.Transactions { return txs } -// Filter removes all transactions from the list with a cost or gas limit higher +// CostFilter removes all transactions from the list with a cost or gas limit higher // than the provided thresholds. Every removed transaction is returned for any // post-removal maintenance. Strict-mode invalidated transactions are also // returned. @@ -362,7 +400,7 @@ func (l *list) Forward(threshold uint64) types.Transactions { // a point in calculating all the costs or if the balance covers all. If the threshold // is lower than the costgas cap, the caps will be reset to a new high after removing // the newly invalidated transactions. -func (l *list) Filter(costLimit *uint256.Int, gasLimit uint64) (types.Transactions, types.Transactions) { +func (l *list) CostFilter(costLimit *uint256.Int, gasLimit uint64) (removed types.Transactions, invalids types.Transactions) { // If all transactions are below the threshold, short circuit if l.costcap.Cmp(costLimit) <= 0 && l.gascap <= gasLimit { return nil, nil @@ -370,32 +408,67 @@ func (l *list) Filter(costLimit *uint256.Int, gasLimit uint64) (types.Transactio l.costcap = new(uint256.Int).Set(costLimit) // Lower the caps to the thresholds l.gascap = gasLimit - // Filter out all the transactions above the account's funds - removed := l.txs.Filter(func(tx *types.Transaction) bool { + return l.Filter(func(tx *types.Transaction) bool { return tx.Gas() > gasLimit || tx.Cost().Cmp(costLimit.ToBig()) > 0 }) +} +// FilterSorted iterates over txs in ascending nonce order and filters them by +// a filter function. If the filter fn returns true for a tx, it is removed. +func (l *list) FilterSorted(filterFn func(tx *types.Transaction) bool) (removed types.Transactions, invalids types.Transactions) { + removed = l.txs.filterSorted(filterFn) if len(removed) == 0 { return nil, nil } - var invalids types.Transactions + // If the list was strict, filter anything above the lowest nonce if l.strict { - lowest := uint64(math.MaxUint64) - for _, tx := range removed { - if nonce := tx.Nonce(); lowest > nonce { - lowest = nonce - } - } - invalids = l.txs.filter(func(tx *types.Transaction) bool { return tx.Nonce() > lowest }) + invalids = l.filterInvalids(removed) } + + // Reset total cost + l.subTotalCost(removed) + l.subTotalCost(invalids) + + l.txs.reheap() + return removed, invalids +} + +// Filter filters txs in the list by a filter function. If the filter fn +// returns true for a tx, it is removed. +func (l *list) Filter(filterFn func(tx *types.Transaction) bool) (removed types.Transactions, invalids types.Transactions) { + removed = l.txs.Filter(filterFn) + if len(removed) == 0 { + return nil, nil + } + + // If the list was strict, filter anything above the lowest nonce + if l.strict { + invalids = l.filterInvalids(removed) + } + // Reset total cost l.subTotalCost(removed) l.subTotalCost(invalids) + l.txs.reheap() return removed, invalids } +// filterInvalids removes any transactions with a nonce above the lowest nonce +// in the removed list. +// +// NOTE: reheap() must be called after this. +func (l *list) filterInvalids(removed types.Transactions) types.Transactions { + lowest := uint64(math.MaxUint64) + for _, tx := range removed { + if nonce := tx.Nonce(); lowest > nonce { + lowest = nonce + } + } + return l.txs.filter(func(tx *types.Transaction) bool { return tx.Nonce() > lowest }) +} + // Cap places a hard limit on the number of items, returning all transactions // exceeding that limit. func (l *list) Cap(threshold int) types.Transactions { @@ -475,7 +548,7 @@ func (l *list) subTotalCost(txs []*types.Transaction) { // then the heap is sorted based on the effective tip based on the given base fee. // If baseFee is nil then the sorting is based on gasFeeCap. type priceHeap struct { - baseFee *big.Int // heap should always be re-sorted after baseFee is changed + baseFee *uint256.Int // heap should always be re-sorted after baseFee is changed list []*types.Transaction } @@ -671,12 +744,16 @@ func (l *pricedList) Reheap() { l.floating.list[i] = heap.Pop(&l.urgent).(*types.Transaction) } heap.Init(&l.floating) - reheapTimer.Update(time.Since(start)) + reheapTimer.Record(context.Background(), float64(time.Since(start).Milliseconds())) } // SetBaseFee updates the base fee and triggers a re-heap. Note that Removed is not // necessary to call right before SetBaseFee when processing a new block. func (l *pricedList) SetBaseFee(baseFee *big.Int) { - l.urgent.baseFee = baseFee + base := new(uint256.Int) + if baseFee != nil { + base.SetFromBig(baseFee) + } + l.urgent.baseFee = base l.Reheap() } diff --git a/mempool/txpool/legacypool/list_test.go b/mempool/txpool/legacypool/list_test.go index 8587c66f..0991d022 100644 --- a/mempool/txpool/legacypool/list_test.go +++ b/mempool/txpool/legacypool/list_test.go @@ -83,7 +83,7 @@ func BenchmarkListAdd(b *testing.B) { list := newList(true) for _, v := range rand.Perm(len(txs)) { list.Add(txs[v], DefaultConfig.PriceBump) - list.Filter(priceLimit, DefaultConfig.PriceBump) + list.CostFilter(priceLimit, DefaultConfig.PriceBump) } } } diff --git a/mempool/txpool/legacypool/metrics_test.go b/mempool/txpool/legacypool/metrics_test.go new file mode 100644 index 00000000..0cfb15fb --- /dev/null +++ b/mempool/txpool/legacypool/metrics_test.go @@ -0,0 +1,48 @@ +package legacypool + +import ( + "context" + "os" + "testing" + + "go.opentelemetry.io/otel" + sdkmetric "go.opentelemetry.io/otel/sdk/metric" + "go.opentelemetry.io/otel/sdk/metric/metricdata" +) + +var testMetricReader *sdkmetric.ManualReader + +func TestMain(m *testing.M) { + testMetricReader = sdkmetric.NewManualReader() + provider := sdkmetric.NewMeterProvider(sdkmetric.WithReader(testMetricReader)) + otel.SetMeterProvider(provider) + os.Exit(m.Run()) +} + +// readCounterTotal returns the accumulated value for a named int64 sum +// (counter) instrument, summing across all data points. Returns 0 if the +// instrument has not recorded any measurement yet. +func readCounterTotal(t *testing.T, name string) int64 { + t.Helper() + var rm metricdata.ResourceMetrics + if err := testMetricReader.Collect(context.Background(), &rm); err != nil { + t.Fatalf("failed to collect metrics: %v", err) + } + for _, sm := range rm.ScopeMetrics { + for _, m := range sm.Metrics { + if m.Name != name { + continue + } + sum, ok := m.Data.(metricdata.Sum[int64]) + if !ok { + continue + } + var total int64 + for _, dp := range sum.DataPoints { + total += dp.Value + } + return total + } + } + return 0 +} diff --git a/mempool/txpool/legacypool/mocks/BlockChain.go b/mempool/txpool/legacypool/mocks/BlockChain.go index 4b341109..4aadf644 100644 --- a/mempool/txpool/legacypool/mocks/BlockChain.go +++ b/mempool/txpool/legacypool/mocks/BlockChain.go @@ -1,8 +1,9 @@ -// Code generated by mockery v2.53.5. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks import ( + sdk "github.com/cosmos/cosmos-sdk/types" common "github.com/ethereum/go-ethereum/common" mock "github.com/stretchr/testify/mock" @@ -79,6 +80,34 @@ func (_m *BlockChain) GetBlock(hash common.Hash, number uint64) *types.Block { return r0 } +// GetLatestContext provides a mock function with no fields +func (_m *BlockChain) GetLatestContext() (sdk.Context, error) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for GetLatestContext") + } + + var r0 sdk.Context + var r1 error + if rf, ok := ret.Get(0).(func() (sdk.Context, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() sdk.Context); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(sdk.Context) + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // StateAt provides a mock function with given fields: root func (_m *BlockChain) StateAt(root common.Hash) (vm.StateDB, error) { ret := _m.Called(root) @@ -114,7 +143,8 @@ func (_m *BlockChain) StateAt(root common.Hash) (vm.StateDB, error) { func NewBlockChain(t interface { mock.TestingT Cleanup(func()) -}) *BlockChain { +}, +) *BlockChain { mock := &BlockChain{} mock.Mock.Test(t) diff --git a/mempool/txpool/legacypool/nop_rechecker.go b/mempool/txpool/legacypool/nop_rechecker.go new file mode 100644 index 00000000..a654a818 --- /dev/null +++ b/mempool/txpool/legacypool/nop_rechecker.go @@ -0,0 +1,23 @@ +package legacypool + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/core/types" +) + +type nopRechecker struct{} + +func newNopRechecker() nopRechecker { + return nopRechecker{} +} + +func (nr nopRechecker) RecheckEVM(_ sdk.Context, _ *types.Transaction) (sdk.Context, error) { + return sdk.Context{}, nil +} + +func (nr nopRechecker) GetContext() (sdk.Context, func()) { + return sdk.Context{}, func() {} +} + +func (nr nopRechecker) Update(_ sdk.Context, _ *types.Header) { +} diff --git a/mempool/txpool/legacypool/reset_testing.go b/mempool/txpool/legacypool/reset_testing.go index 16a11a2a..b24088c3 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/mempool/txpool/legacypool/tx_store.go b/mempool/txpool/legacypool/tx_store.go new file mode 100644 index 00000000..a9c215ca --- /dev/null +++ b/mempool/txpool/legacypool/tx_store.go @@ -0,0 +1,148 @@ +package legacypool + +import ( + "context" + "sort" + "sync" + + "cosmossdk.io/log/v2" + "github.com/cosmos/evm/mempool/txpool" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "go.opentelemetry.io/otel/metric" +) + +// txsCollected is the total amount of txs returned by Collect. +var txsCollected metric.Int64Counter + +func init() { + var err error + txsCollected, err = meter.Int64Counter( + "legacypool.txstore.txs_collected", + metric.WithDescription("Total number of transactions returned by TxStore.Txs"), + ) + if err != nil { + panic(err) + } +} + +// TxStore is a set of transactions at a height that can be added to or +// removed from. +type TxStore struct { + txs map[common.Address]types.Transactions + + // lookup provides a fast lookup to determine if a tx is in the set or not + lookup map[common.Hash]struct{} + + total uint64 + + logger log.Logger + mu sync.RWMutex +} + +// NewTxStore creates a new TxStore. +func NewTxStore(logger log.Logger) *TxStore { + return &TxStore{ + txs: make(map[common.Address]types.Transactions), + total: 0, + lookup: make(map[common.Hash]struct{}), + logger: logger.With("txstore", "evm"), + } +} + +// Get returns the current set of txs in the store. +func (t *TxStore) Txs(ctx context.Context, filter txpool.PendingFilter) map[common.Address][]*txpool.LazyTransaction { + // Do not support blob txs + if filter.OnlyBlobTxs { + return nil + } + + t.mu.Lock() + defer t.mu.Unlock() + + numSelected := 0 + pending := make(map[common.Address][]*txpool.LazyTransaction, len(t.txs)) + + for addr, txs := range t.txs { + sort.Sort(types.TxByNonce(txs)) + + if lazies := filterAndWrapTxs(txs, filter.MinTip, filter.BaseFee); len(lazies) > 0 { + numSelected += len(lazies) + pending[addr] = lazies + } + } + + t.logger.Info("collected txs from evm tx store", "total_in_store", t.total, "num_selected", numSelected) + txsCollected.Add(ctx, int64(numSelected)) + return pending +} + +// AddTxs adds txs to the store. +func (t *TxStore) AddTxs(addr common.Address, txs types.Transactions) { + t.mu.Lock() + defer t.mu.Unlock() + + toAdd := make([]*types.Transaction, 0, len(txs)) + for _, tx := range txs { + if _, exists := t.lookup[tx.Hash()]; exists { + continue + } + toAdd = append(toAdd, tx) + t.lookup[tx.Hash()] = struct{}{} + } + + if existing, ok := t.txs[addr]; ok { + t.txs[addr] = append(existing, toAdd...) + } else { + t.txs[addr] = toAdd + } + + // mark the txs in the lookup + for _, tx := range toAdd { + t.lookup[tx.Hash()] = struct{}{} + } + + t.total += uint64(len(toAdd)) +} + +// AddTx adds a single tx to the store. +func (t *TxStore) AddTx(addr common.Address, tx *types.Transaction) { + t.AddTxs(addr, types.Transactions{tx}) +} + +// RemoveTx removes a tx for an address from the current set. +func (t *TxStore) RemoveTx(addr common.Address, tx *types.Transaction) { + t.RemoveTxsFromNonce(addr, tx.Nonce()) +} + +// RemoveTxsFromNonce removes all txs for addr whose nonce is >= minNonce. +func (t *TxStore) RemoveTxsFromNonce(addr common.Address, minNonce uint64) { + t.mu.Lock() + defer t.mu.Unlock() + + txs, ok := t.txs[addr] + if !ok { + return + } + + next := txs[:0] + numRemoved := 0 + for _, existing := range txs { + if existing.Nonce() >= minNonce { + delete(t.lookup, existing.Hash()) + numRemoved++ + continue + } + next = append(next, existing) + } + + // memory reclaim + clear(txs[len(next):]) + + t.total -= uint64(numRemoved) + if len(next) == 0 { + delete(t.txs, addr) + return + } + t.txs[addr] = next +} diff --git a/mempool/txpool/legacypool/tx_store_test.go b/mempool/txpool/legacypool/tx_store_test.go new file mode 100644 index 00000000..8f581ccb --- /dev/null +++ b/mempool/txpool/legacypool/tx_store_test.go @@ -0,0 +1,140 @@ +package legacypool + +import ( + "context" + "math/big" + "testing" + + "cosmossdk.io/log/v2" + "github.com/cosmos/evm/mempool/txpool" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/holiman/uint256" + "github.com/stretchr/testify/require" +) + +func createTestTx(nonce uint64, gasTipCap *big.Int, gasFeeCap *big.Int) *types.Transaction { + key, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(key.PublicKey) + + return types.NewTx(&types.DynamicFeeTx{ + Nonce: nonce, + GasTipCap: gasTipCap, + GasFeeCap: gasFeeCap, + Gas: 21000, + To: &addr, + Value: big.NewInt(100), + }) +} + +func TestTxStoreAddAndGet(t *testing.T) { + store := NewTxStore(log.NewNopLogger()) + + addr1 := common.HexToAddress("0x1") + addr2 := common.HexToAddress("0x2") + + tx1 := createTestTx(0, big.NewInt(1e9), big.NewInt(2e9)) + tx2 := createTestTx(1, big.NewInt(1e9), big.NewInt(2e9)) + tx3 := createTestTx(0, big.NewInt(1e9), big.NewInt(2e9)) + + store.AddTx(addr1, tx1) + store.AddTx(addr1, tx2) + store.AddTx(addr2, tx3) + + result := store.Txs(context.Background(),txpool.PendingFilter{}) + require.Len(t, result[addr1], 2) + require.Len(t, result[addr2], 1) +} + +func TestTxStoreMinTipFilter(t *testing.T) { + store := NewTxStore(log.NewNopLogger()) + + addr1 := common.HexToAddress("0x1") + + // nonce 0: 2 gwei tip, nonce 1: 0.1 gwei tip + txHighTip := createTestTx(0, big.NewInt(2e9), big.NewInt(3e9)) + txLowTip := createTestTx(1, big.NewInt(1e8), big.NewInt(2e9)) + + store.AddTx(addr1, txHighTip) + store.AddTx(addr1, txLowTip) + + filter := txpool.PendingFilter{ + MinTip: uint256.MustFromBig(big.NewInt(1e9)), + BaseFee: uint256.MustFromBig(big.NewInt(1e9)), + } + result := store.Txs(context.Background(),filter) + + // should only get the high tip tx (nonce 0), low tip at nonce 1 is + // filtered + require.Len(t, result[addr1], 1) + require.Equal(t, uint64(0), result[addr1][0].Tx.Nonce()) +} + +func TestTxStoreSortedByNonce(t *testing.T) { + store := NewTxStore(log.NewNopLogger()) + + addr1 := common.HexToAddress("0x1") + + // add in reverse nonce order + store.AddTx(addr1, createTestTx(2, big.NewInt(1e9), big.NewInt(2e9))) + store.AddTx(addr1, createTestTx(0, big.NewInt(1e9), big.NewInt(2e9))) + store.AddTx(addr1, createTestTx(1, big.NewInt(1e9), big.NewInt(2e9))) + + result := store.Txs(context.Background(),txpool.PendingFilter{}) + require.Len(t, result[addr1], 3) + + for i, lazy := range result[addr1] { + require.Equal(t, uint64(i), lazy.Tx.Nonce()) + } +} + +// TestTxStoreRetainsPreviousTxs tests that if you remove a middle nonce, the earlier nonce txs stay retained. +func TestTxStoreRetainsPreviousTxs(t *testing.T) { + store := NewTxStore(log.NewNopLogger()) + + addr1 := common.HexToAddress("0x1") + + tx1 := createTestTx(0, big.NewInt(1e9), big.NewInt(2e9)) + tx2 := createTestTx(1, big.NewInt(1e9), big.NewInt(2e9)) + tx3 := createTestTx(2, big.NewInt(1e9), big.NewInt(2e9)) + tx4 := createTestTx(3, big.NewInt(1e9), big.NewInt(2e9)) + tx5 := createTestTx(4, big.NewInt(1e9), big.NewInt(2e9)) + txs := []*types.Transaction{tx1, tx2, tx3, tx4, tx5} + for _, tx := range txs { + store.AddTx(addr1, tx) + } + + store.RemoveTx(addr1, tx4) + + result := store.Txs(context.Background(),txpool.PendingFilter{}) + require.Len(t, result[addr1], 3) // should just have 0,1,2. + for i, tx := range result[addr1] { + require.Equal(t, uint64(i), tx.Tx.Nonce()) + } +} + +func TestTxStoreRemoveTx(t *testing.T) { + store := NewTxStore(log.NewNopLogger()) + + addr1 := common.HexToAddress("0x1") + tx1 := createTestTx(0, big.NewInt(1e9), big.NewInt(2e9)) + tx2 := createTestTx(1, big.NewInt(1e9), big.NewInt(2e9)) + + store.AddTx(addr1, tx1) + store.AddTx(addr1, tx2) + store.RemoveTx(addr1, tx1) + + result := store.Txs(context.Background(),txpool.PendingFilter{}) + require.Len(t, result[addr1], 0) +} + +func TestTxStoreBlobTxsFiltered(t *testing.T) { + store := NewTxStore(log.NewNopLogger()) + + addr1 := common.HexToAddress("0x1") + store.AddTx(addr1, createTestTx(0, big.NewInt(1e9), big.NewInt(2e9))) + + result := store.Txs(context.Background(),txpool.PendingFilter{OnlyBlobTxs: true}) + require.Nil(t, result) +} diff --git a/mempool/txpool/mocks/BlockChain.go b/mempool/txpool/mocks/BlockChain.go index 539de145..74d9043f 100644 --- a/mempool/txpool/mocks/BlockChain.go +++ b/mempool/txpool/mocks/BlockChain.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.5. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks @@ -117,7 +117,8 @@ func (_m *BlockChain) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) eve func NewBlockChain(t interface { mock.TestingT Cleanup(func()) -}) *BlockChain { +}, +) *BlockChain { mock := &BlockChain{} mock.Mock.Test(t) diff --git a/mempool/txpool/mocks/SubPool.go b/mempool/txpool/mocks/SubPool.go index 3bedf9f5..d5cab1b3 100644 --- a/mempool/txpool/mocks/SubPool.go +++ b/mempool/txpool/mocks/SubPool.go @@ -1,11 +1,13 @@ -// Code generated by mockery v2.53.5. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks import ( + context "context" big "math/big" common "github.com/ethereum/go-ethereum/common" + core "github.com/ethereum/go-ethereum/core" event "github.com/ethereum/go-ethereum/event" @@ -14,6 +16,8 @@ import ( mock "github.com/stretchr/testify/mock" + reserver "github.com/cosmos/evm/mempool/reserver" + txpool "github.com/cosmos/evm/mempool/txpool" types "github.com/ethereum/go-ethereum/core/types" @@ -44,6 +48,11 @@ func (_m *SubPool) Add(txs []*types.Transaction, sync bool) []error { return r0 } +// CancelReset provides a mock function with no fields +func (_m *SubPool) CancelReset() { + _m.Called() +} + // Clear provides a mock function with no fields func (_m *SubPool) Clear() { _m.Called() @@ -259,17 +268,17 @@ func (_m *SubPool) Has(hash common.Hash) bool { return r0 } -// Init provides a mock function with given fields: gasTip, head, reserver -func (_m *SubPool) Init(gasTip uint64, head *types.Header, reserver txpool.Reserver) error { - ret := _m.Called(gasTip, head, reserver) +// Init provides a mock function with given fields: gasTip, head, _a2 +func (_m *SubPool) Init(gasTip uint64, head *types.Header, _a2 reserver.Reserver) error { + ret := _m.Called(gasTip, head, _a2) if len(ret) == 0 { panic("no return value specified for Init") } var r0 error - if rf, ok := ret.Get(0).(func(uint64, *types.Header, txpool.Reserver) error); ok { - r0 = rf(gasTip, head, reserver) + if rf, ok := ret.Get(0).(func(uint64, *types.Header, reserver.Reserver) error); ok { + r0 = rf(gasTip, head, _a2) } else { r0 = ret.Error(0) } @@ -295,17 +304,17 @@ func (_m *SubPool) Nonce(addr common.Address) uint64 { return r0 } -// Pending provides a mock function with given fields: filter -func (_m *SubPool) Pending(filter txpool.PendingFilter) map[common.Address][]*txpool.LazyTransaction { - ret := _m.Called(filter) +// Pending provides a mock function with given fields: ctx, filter +func (_m *SubPool) Pending(ctx context.Context, filter txpool.PendingFilter) map[common.Address][]*txpool.LazyTransaction { + ret := _m.Called(ctx, filter) if len(ret) == 0 { panic("no return value specified for Pending") } var r0 map[common.Address][]*txpool.LazyTransaction - if rf, ok := ret.Get(0).(func(txpool.PendingFilter) map[common.Address][]*txpool.LazyTransaction); ok { - r0 = rf(filter) + if rf, ok := ret.Get(0).(func(context.Context, txpool.PendingFilter) map[common.Address][]*txpool.LazyTransaction); ok { + r0 = rf(ctx, filter) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(map[common.Address][]*txpool.LazyTransaction) @@ -315,17 +324,17 @@ func (_m *SubPool) Pending(filter txpool.PendingFilter) map[common.Address][]*tx return r0 } -// RemoveTx provides a mock function with given fields: hash, outofbound, unreserve -func (_m *SubPool) RemoveTx(hash common.Hash, outofbound bool, unreserve bool) int { - ret := _m.Called(hash, outofbound, unreserve) +// RemoveTx provides a mock function with given fields: hash, outofbound, unreserve, reason +func (_m *SubPool) RemoveTx(hash common.Hash, outofbound bool, unreserve bool, reason txpool.RemovalReason) int { + ret := _m.Called(hash, outofbound, unreserve, reason) if len(ret) == 0 { panic("no return value specified for RemoveTx") } var r0 int - if rf, ok := ret.Get(0).(func(common.Hash, bool, bool) int); ok { - r0 = rf(hash, outofbound, unreserve) + if rf, ok := ret.Get(0).(func(common.Hash, bool, bool, txpool.RemovalReason) int); ok { + r0 = rf(hash, outofbound, unreserve, reason) } else { r0 = ret.Get(0).(int) } @@ -338,6 +347,26 @@ func (_m *SubPool) Reset(oldHead *types.Header, newHead *types.Header) { _m.Called(oldHead, newHead) } +// Rechecked provides a mock function with given fields: ctx, height, filter +func (_m *SubPool) Rechecked(ctx context.Context, height *big.Int, filter txpool.PendingFilter) map[common.Address][]*txpool.LazyTransaction { + ret := _m.Called(ctx, height, filter) + + if len(ret) == 0 { + panic("no return value specified for Rechecked") + } + + var r0 map[common.Address][]*txpool.LazyTransaction + if rf, ok := ret.Get(0).(func(context.Context, *big.Int, txpool.PendingFilter) map[common.Address][]*txpool.LazyTransaction); ok { + r0 = rf(ctx, height, filter) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(map[common.Address][]*txpool.LazyTransaction) + } + } + + return r0 +} + // SetGasTip provides a mock function with given fields: tip func (_m *SubPool) SetGasTip(tip *big.Int) { _m.Called(tip) @@ -432,7 +461,8 @@ func (_m *SubPool) ValidateTxBasics(tx *types.Transaction) error { func NewSubPool(t interface { mock.TestingT Cleanup(func()) -}) *SubPool { +}, +) *SubPool { mock := &SubPool{} mock.Mock.Test(t) diff --git a/mempool/txpool/reserver.go b/mempool/txpool/reserver.go deleted file mode 100644 index e65e2606..00000000 --- a/mempool/txpool/reserver.go +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright 2025 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package txpool - -import ( - "errors" - "fmt" - "sync" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/metrics" -) - -// reservationsGaugeName is the prefix of a per-subpool address reservation -// metric. -// -// This is mostly a sanity metric to ensure there's no bug that would make -// some subpool hog all the reservations due to mis-accounting. -var reservationsGaugeName = "txpool/reservations" - -// ReservationTracker is a struct shared between different Subpools. It is used to reserve -// the account and ensure that one address cannot initiate transactions, authorizations, -// and other state-changing behaviors in different pools at the same time. -type ReservationTracker struct { - accounts map[common.Address]int - lock sync.RWMutex -} - -// NewReservationTracker initializes the account reservation tracker. -func NewReservationTracker() *ReservationTracker { - return &ReservationTracker{ - accounts: make(map[common.Address]int), - } -} - -// NewHandle creates a named handle on the ReservationTracker. The handle -// identifies the subpool so ownership of reservations can be determined. -func (r *ReservationTracker) NewHandle(id int) *ReservationHandle { - return &ReservationHandle{r, id} -} - -// Reserver is an interface for creating and releasing owned reservations in the -// ReservationTracker struct, which is shared between Subpools. -type Reserver interface { - // Hold attempts to reserve the specified account address for the given pool. - // Returns an error if the account is already reserved. - Hold(addr common.Address) error - - // Release attempts to release the reservation for the specified account. - // Returns an error if the address is not reserved or is reserved by another pool. - Release(addr common.Address) error - - // Has returns a flag indicating if the address has been reserved by a pool - // other than one with the current Reserver handle. - Has(address common.Address) bool -} - -// ReservationHandle is a named handle on ReservationTracker. It is held by Subpools to -// make reservations for accounts it is tracking. The id is used to determine -// which pool owns an address and disallows non-owners to hold or release -// addresses it doesn't own. -type ReservationHandle struct { - tracker *ReservationTracker - id int -} - -// Hold implements the Reserver interface. -func (h *ReservationHandle) Hold(addr common.Address) error { - h.tracker.lock.Lock() - defer h.tracker.lock.Unlock() - - // Double reservations are forbidden even from the same pool to - // avoid subtle bugs in the long term. - owner, exists := h.tracker.accounts[addr] - if exists { - if owner == h.id { - log.Error("pool attempted to reserve already-owned address", "address", addr) - return nil // Ignore fault to give the pool a chance to recover while the bug gets fixed - } - return ErrAlreadyReserved - } - h.tracker.accounts[addr] = h.id - if metrics.Enabled() { - m := fmt.Sprintf("%s/%d", reservationsGaugeName, h.id) - metrics.GetOrRegisterGauge(m, nil).Inc(1) - } - return nil -} - -// Release implements the Reserver interface. -func (h *ReservationHandle) Release(addr common.Address) error { - h.tracker.lock.Lock() - defer h.tracker.lock.Unlock() - - // Ensure Subpools only attempt to unreserve their own owned addresses, - // otherwise flag as a programming error. - owner, exists := h.tracker.accounts[addr] - if !exists { - log.Error("pool attempted to unreserve non-reserved address", "address", addr) - return errors.New("address not reserved") - } - if owner != h.id { - log.Error("pool attempted to unreserve non-owned address", "address", addr) - return errors.New("address not owned") - } - delete(h.tracker.accounts, addr) - if metrics.Enabled() { - m := fmt.Sprintf("%s/%d", reservationsGaugeName, h.id) - metrics.GetOrRegisterGauge(m, nil).Dec(1) - } - return nil -} - -// Has implements the Reserver interface. -func (h *ReservationHandle) Has(address common.Address) bool { - h.tracker.lock.RLock() - defer h.tracker.lock.RUnlock() - - id, exists := h.tracker.accounts[address] - return exists && id != h.id -} diff --git a/mempool/txpool/subpool.go b/mempool/txpool/subpool.go index 03067e9d..226221ab 100644 --- a/mempool/txpool/subpool.go +++ b/mempool/txpool/subpool.go @@ -17,9 +17,11 @@ package txpool import ( + "context" "math/big" "time" + "github.com/cosmos/evm/mempool/reserver" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" @@ -32,7 +34,6 @@ import ( // enough for the miner and other APIs to handle large batches of transactions; // and supports pulling up the entire transaction when really needed. type LazyTransaction struct { - Pool LazyResolver // Transaction resolver to pull the real transaction up Hash common.Hash // Transaction hash to pull up if needed Tx *types.Transaction // Transaction if already resolved @@ -44,21 +45,6 @@ type LazyTransaction struct { BlobGas uint64 // Amount of blob gas required by the transaction } -// Resolve retrieves the full transaction belonging to a lazy handle if it is still -// maintained by the transaction pool. -// -// Note, the method will *not* cache the retrieved transaction if the original -// pool has not cached it. The idea being, that if the tx was too big to insert -// originally, silently saving it will cause more trouble down the line (and -// indeed seems to have caused a memory bloat in the original implementation -// which did just that). -func (ltx *LazyTransaction) Resolve() *types.Transaction { - if ltx.Tx != nil { - return ltx.Tx - } - return ltx.Pool.Get(ltx.Hash) -} - // LazyResolver is a minimal interface needed for a transaction pool to satisfy // resolving lazy transactions. It's mostly a helper to avoid the entire sub- // pool being injected into the lazy transaction. @@ -74,7 +60,7 @@ type LazyResolver interface { // a very specific call site in mind and each one can be evaluated very cheaply // by the pool implementations. Only add new ones that satisfy those constraints. type PendingFilter struct { - MinTip *uint256.Int // Minimum miner tip required to include a transaction + MinTip *uint256.Int // Minimum allowed miner tip for transactions BaseFee *uint256.Int // Minimum 1559 basefee needed to include a transaction BlobFee *uint256.Int // Minimum 4844 blobfee needed to include a blob transaction @@ -88,6 +74,9 @@ type TxMetadata struct { Size uint64 // The length of the 'rlp encoding' of a transaction } +// RemovalReason is a string describing why a tx is being removed. +type RemovalReason string + // SubPool represents a specialized transaction pool that lives on its own (e.g. // blob pool). Since independent of how many specialized pools we have, they do // need to be updated in lockstep and assemble into one coherent view for block @@ -105,7 +94,7 @@ type SubPool interface { // These should not be passed as a constructor argument - nor should the pools // start by themselves - in order to keep multiple Subpools in lockstep with // one another. - Init(gasTip uint64, head *types.Header, reserver Reserver) error + Init(gasTip uint64, head *types.Header, reserver reserver.Reserver) error // Close terminates any background processing threads and releases any held // resources. @@ -115,6 +104,11 @@ type SubPool interface { // of the transaction pool is valid with regard to the chain state. Reset(oldHead, newHead *types.Header) + // CancelReset signals the subpool to stop processing its current reset + // request since a new block arrived and the work it is doing to reset at + // the current height will be invalidated. + CancelReset() + // SetGasTip updates the minimum price required by the subpool for a new // transaction, and drops all transactions below this threshold. SetGasTip(tip *big.Int) @@ -149,12 +143,19 @@ type SubPool interface { // to a later point to batch multiple ones together. Add(txs []*types.Transaction, sync bool) []error - // Pending retrieves all currently processable transactions, grouped by origin + // Pending retrieves all currently pending transactions, grouped by origin + // account and sorted by nonce. + // + // The transactions can also be pre-filtered by the dynamic fee components to + // reduce allocations and load on downstream subsystems. + Pending(ctx context.Context, filter PendingFilter) map[common.Address][]*LazyTransaction + + // Rechecked retrieves all currently rechecked transactions, grouped by origin // account and sorted by nonce. // // The transactions can also be pre-filtered by the dynamic fee components to // reduce allocations and load on downstream subsystems. - Pending(filter PendingFilter) map[common.Address][]*LazyTransaction + Rechecked(ctx context.Context, height *big.Int, filter PendingFilter) map[common.Address][]*LazyTransaction // SubscribeTransactions subscribes to new transaction events. The subscriber // can decide whether to receive notifications only for newly seen transactions @@ -185,5 +186,5 @@ type SubPool interface { Clear() // RemoveTx removes a tracked transaction from the pool - RemoveTx(hash common.Hash, outofbound bool, unreserve bool) int + RemoveTx(hash common.Hash, outofbound bool, unreserve bool, reason RemovalReason) int } diff --git a/mempool/txpool/txpool.go b/mempool/txpool/txpool.go index 06605a87..9331feb4 100644 --- a/mempool/txpool/txpool.go +++ b/mempool/txpool/txpool.go @@ -17,11 +17,14 @@ package txpool import ( + "context" "errors" "fmt" + "maps" "math/big" "sync" + "github.com/cosmos/evm/mempool/reserver" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" @@ -80,7 +83,7 @@ type TxPool struct { // New creates a new transaction pool to gather, sort and filter inbound // transactions from the network. -func New(gasTip uint64, chain BlockChain, subpools []SubPool) (*TxPool, error) { +func New(gasTip uint64, chain BlockChain, tracker *reserver.ReservationTracker, subpools []SubPool) (*TxPool, error) { // Retrieve the current head so that all Subpools and this main coordinator // pool will have the same starting state, even if the chain moves forward // during initialization. @@ -105,9 +108,8 @@ func New(gasTip uint64, chain BlockChain, subpools []SubPool) (*TxPool, error) { term: make(chan struct{}), sync: make(chan chan error), } - reserver := NewReservationTracker() for i, subpool := range subpools { - if err := subpool.Init(gasTip, head, reserver.NewHandle(i)); err != nil { + if err := subpool.Init(gasTip, head, tracker.NewHandle(i)); err != nil { for j := i - 1; j >= 0; j-- { subpools[j].Close() } @@ -213,7 +215,16 @@ func (p *TxPool) loop(head *types.Header) { resetForced = false default: - // Reset already running, wait until it finishes. + // Only if we have seen a new block, then tell the subpools + // that are still processing the previous block, to cancel + // their work, since it will go to waste. + if newHead != oldHead { + for _, subpool := range p.Subpools { + subpool.CancelReset() + } + } + // Reset already running and we have not seen a new block, wait + // until it finishes. // // Note, this will not drop any forced reset request. If a forced // reset was requested, but we were busy, then when the currently @@ -373,17 +384,28 @@ func (p *TxPool) Add(txs []*types.Transaction, sync bool) []error { return errs } -// Pending retrieves all currently processable transactions, grouped by origin +// Pending retrieves all currently pending transactions, grouped by origin // account and sorted by nonce. // // The transactions can also be pre-filtered by the dynamic fee components to // reduce allocations and load on downstream subsystems. -func (p *TxPool) Pending(filter PendingFilter) map[common.Address][]*LazyTransaction { +func (p *TxPool) Pending(ctx context.Context, filter PendingFilter) map[common.Address][]*LazyTransaction { txs := make(map[common.Address][]*LazyTransaction) for _, subpool := range p.Subpools { - for addr, set := range subpool.Pending(filter) { - txs[addr] = set - } + maps.Copy(txs, subpool.Pending(ctx, filter)) + } + return txs +} + +// Rechecked retrieves all currently rechecked transactions, grouped by origin +// account and sorted by nonce. +// +// The transactions can also be pre-filtered by the dynamic fee components to +// reduce allocations and load on downstream subsystems. +func (p *TxPool) Rechecked(ctx context.Context, height *big.Int, filter PendingFilter) map[common.Address][]*LazyTransaction { + txs := make(map[common.Address][]*LazyTransaction) + for _, subpool := range p.Subpools { + maps.Copy(txs, subpool.Rechecked(ctx, height, filter)) } return txs } @@ -445,12 +467,8 @@ func (p *TxPool) Content() (map[common.Address][]*types.Transaction, map[common. for _, subpool := range p.Subpools { run, block := subpool.Content() - for addr, txs := range run { - runnable[addr] = txs - } - for addr, txs := range block { - blocked[addr] = txs - } + maps.Copy(runnable, run) + maps.Copy(blocked, block) } return runnable, blocked } @@ -495,6 +513,13 @@ func (p *TxPool) Sync() error { } } +// Reset synchronously resets each subpool at a given state. +func (p *TxPool) Reset(oldHead, newHead *types.Header) { + for _, subPool := range p.Subpools { + subPool.Reset(oldHead, newHead) + } +} + // Clear removes all tracked txs from the Subpools. // // Note, this method invokes Sync() and is only used for testing, because it is diff --git a/mempool/txpool/txpool_test.go b/mempool/txpool/txpool_test.go index e80805ba..2a9dfee9 100644 --- a/mempool/txpool/txpool_test.go +++ b/mempool/txpool/txpool_test.go @@ -1,11 +1,18 @@ package txpool_test import ( + "context" "math" "math/big" + "sync" "testing" "time" + "cosmossdk.io/log/v2" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/evm/mempool/internal/reaplist" + "github.com/cosmos/evm/mempool/internal/txtracker" + "github.com/cosmos/evm/mempool/reserver" "github.com/cosmos/evm/mempool/txpool" "github.com/cosmos/evm/mempool/txpool/legacypool" legacypool_mocks "github.com/cosmos/evm/mempool/txpool/legacypool/mocks" @@ -61,8 +68,10 @@ func TestTxPoolCosmosReorg(t *testing.T) { // called during legacypool initialization cfg := ¶ms.ChainConfig{ChainID: nil} legacyChain.On("Config").Return(cfg) + legacyChain.On("CurrentBlock").Return(&types.Header{Number: big.NewInt(0)}) chain.On("Config").Return(cfg) legacyChain.On("StateAt", genesisHeader.Root).Return(genesisState, nil) + legacyChain.On("GetLatestContext").Return(sdk.Context{}, nil).Maybe() chain.On("StateAt", genesisHeader.Root).Return(nil, nil) // starting the chain(s) at genesisHeader @@ -79,7 +88,8 @@ func TestTxPoolCosmosReorg(t *testing.T) { genesisState.On("GetNonce", mock.Anything).Return(uint64(1)) genesisState.On("GetCodeHash", mock.Anything).Return(types.EmptyCodeHash) - legacyPool := legacypool.New(legacypool.DefaultConfig, legacyChain) + recheckGuard := make(chan struct{}) + legacyPool := legacypool.New(legacypool.DefaultConfig, log.NewNopLogger(), legacyChain, reaplist.New(stubTxEncoder{}), txtracker.New(), legacypool.WithRecheck(&BlockingRechecker{guard: recheckGuard})) // handle txpool subscribing to new head events from the chain. grab the // reference to the chan that it is going to wait on so we can push mock @@ -91,21 +101,15 @@ func TestTxPoolCosmosReorg(t *testing.T) { waitForSubscription <- struct{}{} }).Return(event.NewSubscription(func(c <-chan struct{}) error { return nil })) - pool, err := txpool.New(gasTip, chain, []txpool.SubPool{legacyPool}) + tracker := reserver.NewReservationTracker() + pool, err := txpool.New(gasTip, chain, tracker, []txpool.SubPool{legacyPool}) require.NoError(t, err) defer pool.Close() // wait for newHeadCh to be initialized <-waitForSubscription - // override broadcast fn to wait until we advance the chain a few blocks - broadcastGuard := make(chan struct{}) - legacyPool.BroadcastTxFn = func(txs []*types.Transaction) error { - <-broadcastGuard - return nil - } - - // add tx1 to the pool so that the blocking broadcast fn will be called, + // add tx1 to the pool so that the blocking recheck fn will be called, // simulating a slow runReorg tx1, _ := types.SignTx(types.NewTransaction(1, common.Address{}, big.NewInt(100), 100_000, big.NewInt(int64(gasTip)+1), nil), signer, key) errs := pool.Add([]*types.Transaction{tx1}, false) @@ -113,7 +117,7 @@ func TestTxPoolCosmosReorg(t *testing.T) { require.NoError(t, err) } - // broadcast fn is now blocking, waiting for broadcastGuard + // recheck fn is now blocking, waiting for recheckGuard // during this time, we will simulate advancing the chain multiple times by // sending headers on the newHeadCh @@ -121,20 +125,148 @@ func TestTxPoolCosmosReorg(t *testing.T) { newHeadCh <- core.ChainHeadEvent{Header: height2Header} newHeadCh <- core.ChainHeadEvent{Header: height3Header} - // now that we have advanced the headers, unblock the broadcast fn - broadcastGuard <- struct{}{} + // now that we have advanced the headers, unblock the recheck fn + recheckGuard <- struct{}{} // a runReorg call will now be scheduled with oldHead=genesis and // newHead=height3 time.Sleep(500 * time.Millisecond) - // push another tx to make sure that runReorg was processed with the above - // headers - legacyPool.BroadcastTxFn = func(txs []*types.Transaction) error { return nil } - tx2, _ := types.SignTx(types.NewTransaction(2, common.Address{}, big.NewInt(100), 100_000, big.NewInt(int64(gasTip)+1), nil), signer, key) - errs = pool.Add([]*types.Transaction{tx2}, false) - for _, err := range errs { - require.NoError(t, err) - } + // sync the pool to make sure that runReorg has processed the above headers + require.NoError(t, pool.Sync()) +} + +type BlockingRechecker struct { + guard chan struct{} + once sync.Once +} + +func (mr *BlockingRechecker) GetContext() (sdk.Context, func()) { + return sdk.Context{}, func() {} +} + +func (mr *BlockingRechecker) RecheckEVM(ctx sdk.Context, tx *types.Transaction) (sdk.Context, error) { + mr.once.Do(func() { + <-mr.guard + }) + return sdk.Context{}, nil +} + +func (mr *BlockingRechecker) Update(ctx sdk.Context, header *types.Header) {} + +// newTxPool builds a TxPool with the given mock subpools, bypassing New() to +// avoid needing a full BlockChain mock. +func newTxPool(subpools ...txpool.SubPool) *txpool.TxPool { + return &txpool.TxPool{Subpools: subpools} +} + +func TestTxPoolPending_MergesSubpools(t *testing.T) { + addr1 := common.HexToAddress("0x1") + addr2 := common.HexToAddress("0x2") + filter := txpool.PendingFilter{} + ctx := context.Background() + + lazy1 := &txpool.LazyTransaction{} + lazy2 := &txpool.LazyTransaction{} + + sub1 := mocks.NewSubPool(t) + sub1.On("Pending", ctx, filter).Return(map[common.Address][]*txpool.LazyTransaction{addr1: {lazy1}}) + + sub2 := mocks.NewSubPool(t) + sub2.On("Pending", ctx, filter).Return(map[common.Address][]*txpool.LazyTransaction{addr2: {lazy2}}) + + result := newTxPool(sub1, sub2).Pending(ctx, filter) + + require.Len(t, result, 2) + require.Equal(t, []*txpool.LazyTransaction{lazy1}, result[addr1]) + require.Equal(t, []*txpool.LazyTransaction{lazy2}, result[addr2]) } + +func TestTxPoolPending_EmptySubpools(t *testing.T) { + filter := txpool.PendingFilter{} + ctx := context.Background() + + sub := mocks.NewSubPool(t) + sub.On("Pending", ctx, filter).Return(map[common.Address][]*txpool.LazyTransaction{}) + + require.Empty(t, newTxPool(sub).Pending(ctx, filter)) +} + +func TestTxPoolRechecked_MergesSubpools(t *testing.T) { + addr1 := common.HexToAddress("0x1") + addr2 := common.HexToAddress("0x2") + height := big.NewInt(10) + filter := txpool.PendingFilter{} + ctx := context.Background() + + lazy1 := &txpool.LazyTransaction{} + lazy2 := &txpool.LazyTransaction{} + + sub1 := mocks.NewSubPool(t) + sub1.On("Rechecked", ctx, height, filter).Return(map[common.Address][]*txpool.LazyTransaction{addr1: {lazy1}}) + + sub2 := mocks.NewSubPool(t) + sub2.On("Rechecked", ctx, height, filter).Return(map[common.Address][]*txpool.LazyTransaction{addr2: {lazy2}}) + + result := newTxPool(sub1, sub2).Rechecked(ctx, height, filter) + + require.Len(t, result, 2) + require.Equal(t, []*txpool.LazyTransaction{lazy1}, result[addr1]) + require.Equal(t, []*txpool.LazyTransaction{lazy2}, result[addr2]) +} + +func TestTxPoolRechecked_EmptySubpools(t *testing.T) { + height := big.NewInt(10) + filter := txpool.PendingFilter{} + ctx := context.Background() + + sub := mocks.NewSubPool(t) + sub.On("Rechecked", ctx, height, filter).Return(map[common.Address][]*txpool.LazyTransaction{}) + + require.Empty(t, newTxPool(sub).Rechecked(ctx, height, filter)) +} + +func TestTxPoolContent_MergesSubpools(t *testing.T) { + addr1 := common.HexToAddress("0x1") + addr2 := common.HexToAddress("0x2") + + tx1 := types.NewTransaction(0, addr1, big.NewInt(0), 21000, big.NewInt(1), nil) + tx2 := types.NewTransaction(0, addr2, big.NewInt(0), 21000, big.NewInt(1), nil) + + sub1 := mocks.NewSubPool(t) + sub1.On("Content").Return( + map[common.Address][]*types.Transaction{addr1: {tx1}}, + map[common.Address][]*types.Transaction{}, + ) + + sub2 := mocks.NewSubPool(t) + sub2.On("Content").Return( + map[common.Address][]*types.Transaction{}, + map[common.Address][]*types.Transaction{addr2: {tx2}}, + ) + + runnable, blocked := newTxPool(sub1, sub2).Content() + + require.Len(t, runnable, 1) + require.Equal(t, []*types.Transaction{tx1}, runnable[addr1]) + require.Len(t, blocked, 1) + require.Equal(t, []*types.Transaction{tx2}, blocked[addr2]) +} + +func TestTxPoolContent_EmptySubpools(t *testing.T) { + sub := mocks.NewSubPool(t) + sub.On("Content").Return( + map[common.Address][]*types.Transaction{}, + map[common.Address][]*types.Transaction{}, + ) + + runnable, blocked := newTxPool(sub).Content() + require.Empty(t, runnable) + require.Empty(t, blocked) +} +// minimal tx encoder to construct a testing reaplist +type stubTxEncoder struct{} + +func (stubTxEncoder) EVMTx(tx *types.Transaction) ([]byte, error) { return tx.Hash().Bytes(), nil } +func (stubTxEncoder) CosmosTx(sdk.Tx) ([]byte, error) { return nil, nil } diff --git a/mempool/txpool/validation.go b/mempool/txpool/validation.go index d0426fff..732f5624 100644 --- a/mempool/txpool/validation.go +++ b/mempool/txpool/validation.go @@ -82,7 +82,7 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types } // Check whether the init code size has been exceeded if rules.IsShanghai && tx.To() == nil && len(tx.Data()) > params.MaxInitCodeSize { - return fmt.Errorf("%w: code size %v, limit %v", core.ErrMaxInitCodeSizeExceeded, len(tx.Data()), params.MaxInitCodeSize) + return fmt.Errorf("%w: code size %v, limit %v", vm.ErrMaxInitCodeSizeExceeded, len(tx.Data()), params.MaxInitCodeSize) } // Transactions can't be negative. This may never happen using RLP decoded // transactions but may occur for transactions created using the RPC. diff --git a/metrics/geth.go b/metrics/geth.go index 44c05263..2ed740ed 100644 --- a/metrics/geth.go +++ b/metrics/geth.go @@ -9,11 +9,12 @@ import ( gethmetrics "github.com/ethereum/go-ethereum/metrics" gethprom "github.com/ethereum/go-ethereum/metrics/prometheus" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" ) // StartGethMetricServer starts the geth metrics server on the specified address. func StartGethMetricServer(ctx context.Context, log log.Logger, addr string) error { + gethmetrics.Enable() mux := http.NewServeMux() mux.Handle("/metrics", gethprom.Handler(gethmetrics.DefaultRegistry)) diff --git a/precompiles/bank/abi.json b/precompiles/bank/abi.json index f64400e2..2c7ad29c 100644 --- a/precompiles/bank/abi.json +++ b/precompiles/bank/abi.json @@ -1,86 +1,77 @@ -{ - "_format": "hh-sol-artifact-1", - "contractName": "IBank", - "sourceName": "solidity/precompiles/bank/IBank.sol", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balances", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "contractAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct Balance[]", - "name": "balances", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "erc20Address", - "type": "address" - } - ], - "name": "supplyOf", - "outputs": [ - { - "internalType": "uint256", - "name": "totalSupply", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "contractAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct Balance[]", - "name": "totalSupply", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "bytecode": "0x", - "deployedBytecode": "0x", - "linkReferences": {}, - "deployedLinkReferences": {} -} +[ + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balances", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Balance[]", + "name": "balances", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "erc20Address", + "type": "address" + } + ], + "name": "supplyOf", + "outputs": [ + { + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Balance[]", + "name": "totalSupply", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/precompiles/bank/bank.go b/precompiles/bank/bank.go index 376eb535..ab66bf32 100644 --- a/precompiles/bank/bank.go +++ b/precompiles/bank/bank.go @@ -6,18 +6,19 @@ package bank import ( - "embed" + "bytes" "fmt" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" + _ "embed" + cmn "github.com/cosmos/evm/precompiles/common" evmtypes "github.com/cosmos/evm/x/vm/types" - storetypes "cosmossdk.io/store/types" - + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -38,13 +39,13 @@ var ( // Embed abi json file to the executable binary. Needed when importing as dependency. // //go:embed abi.json - f embed.FS + f []byte ABI abi.ABI ) func init() { var err error - ABI, err = cmn.LoadABI(f, "abi.json") + ABI, err = abi.JSON(bytes.NewReader(f)) if err != nil { panic(err) } @@ -79,6 +80,10 @@ func NewPrecompile( } } +func (p Precompile) Name() string { + return "bank" +} + // RequiredGas calculates the precompiled contract's base gas rate. func (p Precompile) RequiredGas(input []byte) uint64 { // NOTE: This check avoid panicking when trying to decode the method ID diff --git a/precompiles/bank/testdata/BankCaller.json b/precompiles/bank/testdata/BankCaller.json index 049940cd..ae0f8dfe 100644 --- a/precompiles/bank/testdata/BankCaller.json +++ b/precompiles/bank/testdata/BankCaller.json @@ -77,10 +77,34 @@ ], "stateMutability": "view", "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "gasForward", + "type": "uint256" + } + ], + "name": "callTotalSupplyWithGas", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "innerGasUsed", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" } ], - "bytecode": "0x6080806040523461001657610378908161001c8239f35b600080fdfe60806040908082526004918236101561001757600080fd5b600091823560e01c90816389129c681461016257508063acab2f94146100e95763bba60ca01461004657600080fd5b346100e557602092836003193601126100e15780356001600160a01b038116908190036100dd578251631890039360e21b81529182015283816024816108045afa9283156100d257809361009d575b505051908152f35b909192508382813d83116100cb575b6100b68183610234565b810103126100c8575051903880610095565b80fd5b503d6100ac565b8251903d90823e3d90fd5b8380fd5b8280fd5b5080fd5b508290346100e157826003193601126100e15782815180936318160ddd60e01b8252816108045afa918215610158578361012f9493610133575b505051918291826101e1565b0390f35b6101509293503d8091833e6101488183610234565b81019061026c565b908380610123565b81513d85823e3d90fd5b92939050346100dd5760203660031901126100dd5780356001600160a01b03811691908290036101dd576327e235e360e01b845283015282826024816108045afa918215610158578361012f94936101c057505051918291826101e1565b6101d59293503d8091833e6101488183610234565b903880610123565b8480fd5b60208082019080835283518092528060408094019401926000905b83821061020b57505050505090565b845180516001600160a01b031687528301518684015294850194938201936001909101906101fc565b90601f8019910116810190811067ffffffffffffffff82111761025657604052565b634e487b7160e01b600052604160045260246000fd5b6020808284031261032857815167ffffffffffffffff9283821161032857019083601f83011215610328578151838111610256576040938451956102b5848460051b0188610234565b828752838088019360061b86010194818611610328578401925b8584106102e0575050505050505090565b8684830312610328578651908782018281108582111761032d5788528451906001600160a01b0382168203610328578287928a945282870151838201528152019301926102cf565b600080fd5b60246000634e487b7160e01b81526041600452fdfea2646970667358221220069405aa45fc21b29f725237543db2b8600a62c69a04e7a4c44dce45d314303e64736f6c63430008140033", - "deployedBytecode": "0x60806040908082526004918236101561001757600080fd5b600091823560e01c90816389129c681461016257508063acab2f94146100e95763bba60ca01461004657600080fd5b346100e557602092836003193601126100e15780356001600160a01b038116908190036100dd578251631890039360e21b81529182015283816024816108045afa9283156100d257809361009d575b505051908152f35b909192508382813d83116100cb575b6100b68183610234565b810103126100c8575051903880610095565b80fd5b503d6100ac565b8251903d90823e3d90fd5b8380fd5b8280fd5b5080fd5b508290346100e157826003193601126100e15782815180936318160ddd60e01b8252816108045afa918215610158578361012f9493610133575b505051918291826101e1565b0390f35b6101509293503d8091833e6101488183610234565b81019061026c565b908380610123565b81513d85823e3d90fd5b92939050346100dd5760203660031901126100dd5780356001600160a01b03811691908290036101dd576327e235e360e01b845283015282826024816108045afa918215610158578361012f94936101c057505051918291826101e1565b6101d59293503d8091833e6101488183610234565b903880610123565b8480fd5b60208082019080835283518092528060408094019401926000905b83821061020b57505050505090565b845180516001600160a01b031687528301518684015294850194938201936001909101906101fc565b90601f8019910116810190811067ffffffffffffffff82111761025657604052565b634e487b7160e01b600052604160045260246000fd5b6020808284031261032857815167ffffffffffffffff9283821161032857019083601f83011215610328578151838111610256576040938451956102b5848460051b0188610234565b828752838088019360061b86010194818611610328578401925b8584106102e0575050505050505090565b8684830312610328578651908782018281108582111761032d5788528451906001600160a01b0382168203610328578287928a945282870151838201528152019301926102cf565b600080fd5b60246000634e487b7160e01b81526041600452fdfea2646970667358221220069405aa45fc21b29f725237543db2b8600a62c69a04e7a4c44dce45d314303e64736f6c63430008140033", + "bytecode": "0x608080604052346100165761045b908161001c8239f35b600080fdfe60806040908082526004908136101561001757600080fd5b600090813560e01c90816389129c681461024557508063acab2f94146101cd578063bba60ca01461012b5763d47052031461005157600080fd5b34610128576020366003190112610128575a90835192602084016318160ddd60e01b81528185528585019467ffffffffffffffff95818110878211176101155787525183918291906108048535fa933d1561010f573d9081116100fc578551906100c5601f8201601f191660200183610317565b81528260203d92013e5b5a83039283116100e9575050825191151582526020820152f35b634e487b7160e01b825260119052602490fd5b634e487b7160e01b835260418252602483fd5b506100cf565b634e487b7160e01b855260418452602485fd5b80fd5b5082346101c957602092836003193601126101c55780356001600160a01b038116908190036101c1578251631890039360e21b81529182015283816024816108045afa9283156101b6578093610184575b505051908152f35b909192508382813d83116101af575b61019d8183610317565b8101031261012857505190838061017c565b503d610193565b8251903d90823e3d90fd5b8380fd5b8280fd5b5080fd5b5091346101c557826003193601126101c55782815180936318160ddd60e01b8252816108045afa91821561023b57836102129493610216575b505051918291826102c4565b0390f35b6102339293503d8091833e61022b8183610317565b81019061034f565b903880610206565b81513d85823e3d90fd5b90508383346101c15760203660031901126101c15780356001600160a01b03811691908290036102c0576327e235e360e01b845283015282826024816108045afa91821561023b578361021294936102a357505051918291826102c4565b6102b89293503d8091833e61022b8183610317565b908380610206565b8480fd5b60208082019080835283518092528060408094019401926000905b8382106102ee57505050505090565b845180516001600160a01b031687528301518684015294850194938201936001909101906102df565b90601f8019910116810190811067ffffffffffffffff82111761033957604052565b634e487b7160e01b600052604160045260246000fd5b6020808284031261040b57815167ffffffffffffffff9283821161040b57019083601f8301121561040b57815183811161033957604093845195610398848460051b0188610317565b828752838088019360061b8601019481861161040b578401925b8584106103c3575050505050505090565b868483031261040b57865190878201828110858211176104105788528451906001600160a01b038216820361040b578287928a945282870151838201528152019301926103b2565b600080fd5b60246000634e487b7160e01b81526041600452fdfea26469706673582212206291c412c52d95f56ebd6bcace337eb3149a918c5ed8398ed4845c859755136a64736f6c63430008140033", + "deployedBytecode": "0x60806040908082526004908136101561001757600080fd5b600090813560e01c90816389129c681461024557508063acab2f94146101cd578063bba60ca01461012b5763d47052031461005157600080fd5b34610128576020366003190112610128575a90835192602084016318160ddd60e01b81528185528585019467ffffffffffffffff95818110878211176101155787525183918291906108048535fa933d1561010f573d9081116100fc578551906100c5601f8201601f191660200183610317565b81528260203d92013e5b5a83039283116100e9575050825191151582526020820152f35b634e487b7160e01b825260119052602490fd5b634e487b7160e01b835260418252602483fd5b506100cf565b634e487b7160e01b855260418452602485fd5b80fd5b5082346101c957602092836003193601126101c55780356001600160a01b038116908190036101c1578251631890039360e21b81529182015283816024816108045afa9283156101b6578093610184575b505051908152f35b909192508382813d83116101af575b61019d8183610317565b8101031261012857505190838061017c565b503d610193565b8251903d90823e3d90fd5b8380fd5b8280fd5b5080fd5b5091346101c557826003193601126101c55782815180936318160ddd60e01b8252816108045afa91821561023b57836102129493610216575b505051918291826102c4565b0390f35b6102339293503d8091833e61022b8183610317565b81019061034f565b903880610206565b81513d85823e3d90fd5b90508383346101c15760203660031901126101c15780356001600160a01b03811691908290036102c0576327e235e360e01b845283015282826024816108045afa91821561023b578361021294936102a357505051918291826102c4565b6102b89293503d8091833e61022b8183610317565b908380610206565b8480fd5b60208082019080835283518092528060408094019401926000905b8382106102ee57505050505090565b845180516001600160a01b031687528301518684015294850194938201936001909101906102df565b90601f8019910116810190811067ffffffffffffffff82111761033957604052565b634e487b7160e01b600052604160045260246000fd5b6020808284031261040b57815167ffffffffffffffff9283821161040b57019083601f8301121561040b57815183811161033957604093845195610398848460051b0188610317565b828752838088019360061b8601019481861161040b578401925b8584106103c3575050505050505090565b868483031261040b57865190878201828110858211176104105788528451906001600160a01b038216820361040b578287928a945282870151838201528152019301926103b2565b600080fd5b60246000634e487b7160e01b81526041600452fdfea26469706673582212206291c412c52d95f56ebd6bcace337eb3149a918c5ed8398ed4845c859755136a64736f6c63430008140033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/precompiles/bank/testdata/BankCaller.sol b/precompiles/bank/testdata/BankCaller.sol index 7322fe11..f9ed0a7b 100644 --- a/precompiles/bank/testdata/BankCaller.sol +++ b/precompiles/bank/testdata/BankCaller.sol @@ -16,4 +16,14 @@ contract BankCaller { function callSupplyOf(address erc20Address) external view returns (uint256) { return IBANK_CONTRACT.supplyOf(erc20Address); } + + // Calls totalSupply with explicit gas forwarding and measures the gas consumed + // by the inner call. Returns whether the call succeeded and the actual gas used. + function callTotalSupplyWithGas(uint256 gasForward) external view returns (bool success, uint256 innerGasUsed) { + uint256 gasBefore = gasleft(); + (success, ) = IBANK_PRECOMPILE_ADDRESS.staticcall{gas: gasForward}( + abi.encodeWithSelector(IBank.totalSupply.selector) + ); + innerGasUsed = gasBefore - gasleft(); + } } \ No newline at end of file diff --git a/precompiles/bech32/abi.json b/precompiles/bech32/abi.json index de66134b..7d914475 100644 --- a/precompiles/bech32/abi.json +++ b/precompiles/bech32/abi.json @@ -1,54 +1,45 @@ -{ - "_format": "hh-sol-artifact-1", - "contractName": "Bech32I", - "sourceName": "solidity/precompiles/bech32/Bech32I.sol", - "abi": [ - { - "inputs": [ - { - "internalType": "string", - "name": "bech32Address", - "type": "string" - } - ], - "name": "bech32ToHex", - "outputs": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "string", - "name": "prefix", - "type": "string" - } - ], - "name": "hexToBech32", - "outputs": [ - { - "internalType": "string", - "name": "bech32Address", - "type": "string" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "bytecode": "0x", - "deployedBytecode": "0x", - "linkReferences": {}, - "deployedLinkReferences": {} -} +[ + { + "inputs": [ + { + "internalType": "string", + "name": "bech32Address", + "type": "string" + } + ], + "name": "bech32ToHex", + "outputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "string", + "name": "prefix", + "type": "string" + } + ], + "name": "hexToBech32", + "outputs": [ + { + "internalType": "string", + "name": "bech32Address", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/precompiles/bech32/bech32.go b/precompiles/bech32/bech32.go index 0d43d724..3d26798d 100644 --- a/precompiles/bech32/bech32.go +++ b/precompiles/bech32/bech32.go @@ -1,14 +1,15 @@ package bech32 import ( - "embed" + "bytes" "fmt" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" - cmn "github.com/cosmos/evm/precompiles/common" + _ "embed" + evmtypes "github.com/cosmos/evm/x/vm/types" ) @@ -18,13 +19,13 @@ var ( // Embed abi json file to the executable binary. Needed when importing as dependency. // //go:embed abi.json - f embed.FS + f []byte ABI abi.ABI ) func init() { var err error - ABI, err = cmn.LoadABI(f, "abi.json") + ABI, err = abi.JSON(bytes.NewReader(f)) if err != nil { panic(err) } @@ -49,6 +50,10 @@ func NewPrecompile(baseGas uint64) (*Precompile, error) { }, nil } +func (Precompile) Name() string { + return "bech32" +} + // Address defines the address of the bech32 precompiled contract. func (Precompile) Address() common.Address { return common.HexToAddress(evmtypes.Bech32PrecompileAddress) diff --git a/precompiles/callbacks/abi.go b/precompiles/callbacks/abi.go index d7b58a05..806c9294 100644 --- a/precompiles/callbacks/abi.go +++ b/precompiles/callbacks/abi.go @@ -1,23 +1,24 @@ package callbacks import ( - "embed" + "bytes" "github.com/ethereum/go-ethereum/accounts/abi" - cmn "github.com/cosmos/evm/precompiles/common" + _ "embed" ) // Embed abi json file to the executable binary. Needed when importing as dependency. -// -//go:embed abi.json -var f embed.FS +var ( + //go:embed abi.json + f []byte + ABI abi.ABI +) -func LoadABI() (*abi.ABI, error) { - newABI, err := cmn.LoadABI(f, "abi.json") +func init() { + var err error + ABI, err = abi.JSON(bytes.NewReader(f)) if err != nil { - return nil, err + panic(err) } - - return &newABI, nil } diff --git a/precompiles/callbacks/abi.json b/precompiles/callbacks/abi.json index adb74ca5..4cb6fcd7 100644 --- a/precompiles/callbacks/abi.json +++ b/precompiles/callbacks/abi.json @@ -1,72 +1,63 @@ -{ - "_format": "hh-sol-artifact-1", - "contractName": "ICallbacks", - "sourceName": "solidity/precompiles/callbacks/ICallbacks.sol", - "abi": [ - { - "inputs": [ - { - "internalType": "string", - "name": "channelId", - "type": "string" - }, - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "uint64", - "name": "sequence", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "acknowledgement", - "type": "bytes" - } - ], - "name": "onPacketAcknowledgement", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "channelId", - "type": "string" - }, - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "uint64", - "name": "sequence", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onPacketTimeout", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "bytecode": "0x", - "deployedBytecode": "0x", - "linkReferences": {}, - "deployedLinkReferences": {} -} +[ + { + "inputs": [ + { + "internalType": "string", + "name": "channelId", + "type": "string" + }, + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "acknowledgement", + "type": "bytes" + } + ], + "name": "onPacketAcknowledgement", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "channelId", + "type": "string" + }, + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onPacketTimeout", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/precompiles/common/abi.go b/precompiles/common/abi.go index a56cc59a..b4e71a78 100644 --- a/precompiles/common/abi.go +++ b/precompiles/common/abi.go @@ -1,7 +1,6 @@ package common import ( - "embed" "fmt" "math/big" "reflect" @@ -11,8 +10,6 @@ import ( "github.com/ethereum/go-ethereum/common/math" ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" - - contractutils "github.com/cosmos/evm/contracts/utils" ) // MakeTopic converts a filter query argument into a filter topic. @@ -110,6 +107,7 @@ func genIntType(rule int64, size uint) []byte { topic = [common.HashLength]byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255} } for i := uint(0); i < size; i++ { + // #nosec G115 -- low 8 bits of int64, size bounded by HashLength topic[common.HashLength-i-1] = byte(rule >> (i * 8)) } return topic[:] @@ -128,18 +126,3 @@ func PackNum(value reflect.Value) []byte { panic("abi: fatal error") } } - -// LoadABI read the ABI file described by the path and parse it as JSON. -func LoadABI(fs embed.FS, path string) (abi.ABI, error) { - abiBz, err := fs.ReadFile(path) - if err != nil { - return abi.ABI{}, fmt.Errorf("error loading the ABI %s", err) - } - - contract, err := contractutils.ConvertPrecompileHardhatBytesToCompiledContract(abiBz) - if err != nil { - return abi.ABI{}, fmt.Errorf(ErrInvalidABI, err) - } - - return contract.ABI, nil -} diff --git a/precompiles/common/balance_handler.go b/precompiles/common/balance_handler.go index 92f18276..396e5fb6 100644 --- a/precompiles/common/balance_handler.go +++ b/precompiles/common/balance_handler.go @@ -2,13 +2,10 @@ package common import ( "fmt" - "math/big" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/tracing" - "github.com/cosmos/evm/utils" - precisebanktypes "github.com/cosmos/evm/x/precisebank/types" "github.com/cosmos/evm/x/vm/statedb" sdk "github.com/cosmos/cosmos-sdk/types" @@ -54,10 +51,7 @@ func (bh *BalanceHandler) BeforeBalanceChange(ctx sdk.Context) { // NOTES: Balance change events involving BlockedAddresses are bypassed. // Native balances are handled separately to prevent cases where a bank coin transfer // initiated by a precompile is unintentionally overwritten by balance changes from within a contract. - // Typically, accounts registered as BlockedAddresses in app.go—such as module accounts—are not expected to receive coins. -// However, in modules like precisebank, it is common to borrow and repay integer balances -// from the module account to support fractional balance handling. // // As a result, even if a module account is marked as a BlockedAddress, a keeper-level SendCoins operation // can emit an x/bank event in which the module account appears as a spender or receiver. @@ -68,15 +62,22 @@ func (bh *BalanceHandler) BeforeBalanceChange(ctx sdk.Context) { func (bh *BalanceHandler) AfterBalanceChange(ctx sdk.Context, stateDB *statedb.StateDB) error { events := ctx.EventManager().Events() - for _, event := range events[bh.prevEventsLen:] { + for i, event := range events[bh.prevEventsLen:] { + eventIdx := bh.prevEventsLen + i + + // Skip events already processed by flushing before the precompile was called. + if stateDB.IsEventProcessed(eventIdx) { + continue + } + switch event.Type { case banktypes.EventTypeCoinSpent: spenderAddr, err := ParseAddress(event, banktypes.AttributeKeySpender) if err != nil { return fmt.Errorf("failed to parse spender address from event %q: %w", banktypes.EventTypeCoinSpent, err) } - if bh.bankKeeper.BlockedAddr(spenderAddr) { - // Bypass blocked addresses + if bh.bankKeeper.BlockedAddr(spenderAddr) || !isMirrorableEVMAddress(spenderAddr) { + // Bypass blocked addresses and accounts that are not 20 bytes. continue } @@ -92,8 +93,8 @@ func (bh *BalanceHandler) AfterBalanceChange(ctx sdk.Context, stateDB *statedb.S if err != nil { return fmt.Errorf("failed to parse receiver address from event %q: %w", banktypes.EventTypeCoinReceived, err) } - if bh.bankKeeper.BlockedAddr(receiverAddr) { - // Bypass blocked addresses + if bh.bankKeeper.BlockedAddr(receiverAddr) || !isMirrorableEVMAddress(receiverAddr) { + // Bypass blocked addresses and accounts that are not 20 bytes. continue } @@ -104,36 +105,15 @@ func (bh *BalanceHandler) AfterBalanceChange(ctx sdk.Context, stateDB *statedb.S stateDB.AddBalance(common.BytesToAddress(receiverAddr.Bytes()), amount, tracing.BalanceChangeUnspecified) - case precisebanktypes.EventTypeFractionalBalanceChange: - addr, err := ParseAddress(event, precisebanktypes.AttributeKeyAddress) - if err != nil { - return fmt.Errorf("failed to parse address from event %q: %w", precisebanktypes.EventTypeFractionalBalanceChange, err) - } - if bh.bankKeeper.BlockedAddr(addr) { - // Bypass blocked addresses - continue - } - - delta, err := ParseFractionalAmount(event) - if err != nil { - return fmt.Errorf("failed to parse amount from event %q: %w", precisebanktypes.EventTypeFractionalBalanceChange, err) - } - - deltaAbs, err := utils.Uint256FromBigInt(new(big.Int).Abs(delta)) - if err != nil { - return fmt.Errorf("failed to convert delta to Uint256: %w", err) - } - - if delta.Sign() == 1 { - stateDB.AddBalance(common.BytesToAddress(addr.Bytes()), deltaAbs, tracing.BalanceChangeUnspecified) - } else if delta.Sign() == -1 { - stateDB.SubBalance(common.BytesToAddress(addr.Bytes()), deltaAbs, tracing.BalanceChangeUnspecified) - } - default: + // Non-balance events are already marked as processed above continue } } return nil } + +func isMirrorableEVMAddress(addr sdk.AccAddress) bool { + return len(addr) == common.AddressLength +} diff --git a/precompiles/common/balance_handler_test.go b/precompiles/common/balance_handler_test.go index 0e6c7993..e7f70068 100644 --- a/precompiles/common/balance_handler_test.go +++ b/precompiles/common/balance_handler_test.go @@ -13,13 +13,11 @@ import ( cmnmocks "github.com/cosmos/evm/precompiles/common/mocks" testutil "github.com/cosmos/evm/testutil" testconstants "github.com/cosmos/evm/testutil/constants" - precisebanktypes "github.com/cosmos/evm/x/precisebank/types" "github.com/cosmos/evm/x/vm/statedb" evmtypes "github.com/cosmos/evm/x/vm/types" "github.com/cosmos/evm/x/vm/types/mocks" - storetypes "cosmossdk.io/store/types" - + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdktestutil "github.com/cosmos/cosmos-sdk/testutil" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -98,12 +96,14 @@ func TestParseAddress(t *testing.T) { func TestParseAmount(t *testing.T) { testCases := []struct { name string + chainID testconstants.ChainID maleate func() sdk.Event expAmt *uint256.Int expError bool }{ { - name: "valid amount", + name: "valid amount", + chainID: testconstants.ExampleChainID, maleate: func() sdk.Event { coinStr := sdk.NewCoins(sdk.NewInt64Coin(evmtypes.GetEVMCoinDenom(), 5)).String() return sdk.NewEvent("bank", sdk.NewAttribute(sdk.AttributeKeyAmount, coinStr)) @@ -111,14 +111,55 @@ func TestParseAmount(t *testing.T) { expAmt: uint256.NewInt(5), }, { - name: "missing amount", + name: "unrelated denom is ignored", + chainID: testconstants.ExampleChainID, + maleate: func() sdk.Event { + coinStr := sdk.NewCoins(sdk.NewInt64Coin("foobar", 7)).String() + return sdk.NewEvent("bank", sdk.NewAttribute(sdk.AttributeKeyAmount, coinStr)) + }, + expAmt: uint256.NewInt(0), + }, + { + name: "base denom is scaled to 18 decimals", + chainID: testconstants.SixDecimalsChainID, + maleate: func() sdk.Event { + coinStr := sdk.NewCoins(sdk.NewInt64Coin(evmtypes.GetEVMCoinDenom(), 100)).String() + return sdk.NewEvent("bank", sdk.NewAttribute(sdk.AttributeKeyAmount, coinStr)) + }, + expAmt: uint256.NewInt(100_000_000_000_000), + }, + { + name: "extended denom is taken as is", + chainID: testconstants.SixDecimalsChainID, + maleate: func() sdk.Event { + coinStr := sdk.NewCoins(sdk.NewInt64Coin(evmtypes.GetEVMCoinExtendedDenom(), 500)).String() + return sdk.NewEvent("bank", sdk.NewAttribute(sdk.AttributeKeyAmount, coinStr)) + }, + expAmt: uint256.NewInt(500), + }, + { + name: "base and extended denoms are summed", + chainID: testconstants.SixDecimalsChainID, + maleate: func() sdk.Event { + coinStr := sdk.NewCoins( + sdk.NewInt64Coin(evmtypes.GetEVMCoinDenom(), 100), + sdk.NewInt64Coin(evmtypes.GetEVMCoinExtendedDenom(), 500), + ).String() + return sdk.NewEvent("bank", sdk.NewAttribute(sdk.AttributeKeyAmount, coinStr)) + }, + expAmt: uint256.NewInt(100_000_000_000_500), + }, + { + name: "missing amount", + chainID: testconstants.ExampleChainID, maleate: func() sdk.Event { return sdk.NewEvent("bank") }, expError: true, }, { - name: "invalid coins", + name: "invalid coins", + chainID: testconstants.ExampleChainID, maleate: func() sdk.Event { return sdk.NewEvent("bank", sdk.NewAttribute(sdk.AttributeKeyAmount, "invalid")) }, @@ -128,7 +169,9 @@ func TestParseAmount(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - setupBalanceHandlerTest(t) + configurator := evmtypes.NewEVMConfigurator() + configurator.ResetTestConfig() + require.NoError(t, configurator.WithEVMCoinInfo(testconstants.ExampleChainCoinInfo[tc.chainID]).Configure()) amt, err := cmn.ParseAmount(tc.maleate()) if tc.expError { @@ -137,7 +180,7 @@ func TestParseAmount(t *testing.T) { } require.NoError(t, err) - require.True(t, amt.Eq(tc.expAmt)) + require.Equal(t, tc.expAmt.String(), amt.String()) }) } } @@ -162,12 +205,12 @@ func TestAfterBalanceChange(t *testing.T) { stateDB.AddBalance(spender, uint256.NewInt(5), tracing.BalanceChangeUnspecified) bankKeeper := cmnmocks.NewBankKeeper(t) - precisebankModuleAccAddr := authtypes.NewModuleAddress(precisebanktypes.ModuleName) + bankModuleAccAddr := authtypes.NewModuleAddress(banktypes.ModuleName) bankKeeper.Mock.On("BlockedAddr", mock.AnythingOfType("types.AccAddress")).Return(func(addr sdk.AccAddress) bool { // NOTE: In principle, all blockedAddresses configured in app.go should be checked. // However, for the sake of simplicity in this test, we assume a scenario where - // only the precisebank module account is treated as a blockedAddress. - return addr.Equals(precisebankModuleAccAddr) + // only the bank module account is treated as a blockedAddress. + return addr.Equals(bankModuleAccAddr) }) bhf := cmn.NewBalanceHandlerFactory(bankKeeper) bh := bhf.NewBalanceHandler() @@ -199,12 +242,12 @@ func TestAfterBalanceChangeErrors(t *testing.T) { addr := addrs[0] bankKeeper := cmnmocks.NewBankKeeper(t) - precisebankModuleAccAddr := authtypes.NewModuleAddress(precisebanktypes.ModuleName) + bankModuleAccAddr := authtypes.NewModuleAddress(banktypes.ModuleName) bankKeeper.Mock.On("BlockedAddr", mock.AnythingOfType("types.AccAddress")).Return(func(addr sdk.AccAddress) bool { // NOTE: In principle, all blockedAddresses configured in app.go should be checked. // However, for the sake of simplicity in this test, we assume a scenario where - // only the precisebank module account is treated as a blockedAddress. - return addr.Equals(precisebankModuleAccAddr) + // only the bank module account is treated as a blockedAddress. + return addr.Equals(bankModuleAccAddr) }) bhf := cmn.NewBalanceHandlerFactory(bankKeeper) bh := bhf.NewBalanceHandler() diff --git a/precompiles/common/interfaces.go b/precompiles/common/interfaces.go index e69e11d3..78d28bd0 100644 --- a/precompiles/common/interfaces.go +++ b/precompiles/common/interfaces.go @@ -6,9 +6,12 @@ import ( 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" + "github.com/cosmos/evm/x/vm/statedb" + ibctypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + connectiontypes "github.com/cosmos/ibc-go/v11/modules/core/03-connection/types" + channeltypes "github.com/cosmos/ibc-go/v11/modules/core/04-channel/types" + + "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" @@ -62,4 +65,7 @@ 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) + IsERC20Enabled(ctx sdk.Context) bool + GetTokenPairID(ctx sdk.Context, token string) []byte + ConvertERC20IntoCoinsForNativeToken(ctx sdk.Context, stateDB *statedb.StateDB, contract ethcommon.Address, amount math.Int, receiver sdk.AccAddress, sender ethcommon.Address, commit bool, callFromPrecompile bool) (*erc20types.MsgConvertERC20Response, error) } diff --git a/precompiles/common/mocks/BankKeeper.go b/precompiles/common/mocks/BankKeeper.go index a3c72593..6f92fb5e 100644 --- a/precompiles/common/mocks/BankKeeper.go +++ b/precompiles/common/mocks/BankKeeper.go @@ -155,7 +155,8 @@ func (_m *BankKeeper) SpendableCoin(ctx context.Context, addr types.AccAddress, 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 1554fe1b..a3ff7de3 100644 --- a/precompiles/common/precompile.go +++ b/precompiles/common/precompile.go @@ -10,8 +10,7 @@ import ( "github.com/cosmos/evm/x/vm/statedb" - storetypes "cosmossdk.io/store/types" - + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -48,6 +47,9 @@ func (p Precompile) RequiredGas(input []byte, isTransaction bool) uint64 { func (p Precompile) RunNativeAction(evm *vm.EVM, contract *vm.Contract, action NativeAction) ([]byte, error) { bz, err := p.runNativeAction(evm, contract, action) if err != nil { + if errors.Is(err, vm.ErrOutOfGas) { + return nil, vm.ErrOutOfGas + } return ReturnRevertError(evm, err) } @@ -69,30 +71,29 @@ func (p Precompile) runNativeAction(evm *vm.EVM, contract *vm.Contract, action N // take a snapshot of the current state before any changes // to be able to revert the changes snapshot := stateDB.MultiStoreSnapshot() - events := ctx.EventManager().Events() // add precompileCall entry on the stateDB journal // this allows to revert the changes within an evm tx - if err := stateDB.AddPrecompileFn(snapshot, events); err != nil { + if err := stateDB.AddPrecompileFn(snapshot); err != nil { return nil, err } // commit the current changes in the cache ctx // to get the updated state for the precompile call - if err := stateDB.CommitWithCacheCtx(); err != nil { + if err := stateDB.FlushToCacheCtx(); err != nil { return nil, err } initialGas := ctx.GasMeter().GasConsumed() - defer HandleGasError(ctx, contract, initialGas, &err)() - // set the default SDK gas configuration to track gas usage // we are changing the gas meter type, so it panics gracefully when out of gas ctx = ctx.WithGasMeter(storetypes.NewGasMeter(contract.Gas)). WithKVGasConfig(p.KvGasConfig). WithTransientKVGasConfig(p.TransientKVGasConfig) + defer HandleGasError(ctx, contract, initialGas, &err)() + // we need to consume the gas that was already used by the EVM ctx.GasMeter().ConsumeGas(initialGas, "creating a new gas meter") diff --git a/precompiles/common/revert.go b/precompiles/common/revert.go index 828248a6..595c88c6 100644 --- a/precompiles/common/revert.go +++ b/precompiles/common/revert.go @@ -21,7 +21,7 @@ func ReturnRevertError(evm *vm.EVM, err error) ([]byte, error) { if encErr != nil { return nil, vm.ErrExecutionReverted } - evm.Interpreter().SetReturnData(revertReasonBz) + evm.SetReturnData(revertReasonBz) return revertReasonBz, vm.ErrExecutionReverted } diff --git a/precompiles/common/utils.go b/precompiles/common/utils.go index 520dc5e0..36fb72e1 100644 --- a/precompiles/common/utils.go +++ b/precompiles/common/utils.go @@ -7,11 +7,8 @@ import ( "github.com/holiman/uint256" "github.com/cosmos/evm/utils" - precisebanktypes "github.com/cosmos/evm/x/precisebank/types" 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" ) @@ -42,24 +39,16 @@ func ParseAmount(event sdk.Event) (*uint256.Int, error) { return nil, fmt.Errorf("failed to parse coins from %q: %w", amountAttr.Value, err) } - amountBigInt := amountCoins.AmountOf(evmtypes.GetEVMCoinDenom()).BigInt() - amount, err := utils.Uint256FromBigInt(evmtypes.ConvertAmountTo18DecimalsBigInt(amountBigInt)) + baseAmount := amountCoins.AmountOf(evmtypes.GetEVMCoinDenom()).BigInt() + amountBigInt := evmtypes.ConvertAmountTo18DecimalsBigInt(baseAmount) + if evmtypes.GetEVMCoinExtendedDenom() != evmtypes.GetEVMCoinDenom() { + extendedAmount := amountCoins.AmountOf(evmtypes.GetEVMCoinExtendedDenom()).BigInt() + amountBigInt = new(big.Int).Add(amountBigInt, extendedAmount) + } + + amount, err := utils.Uint256FromBigInt(amountBigInt) if err != nil { return nil, fmt.Errorf("failed to convert coin amount to Uint256: %w", err) } return amount, nil } - -func ParseFractionalAmount(event sdk.Event) (*big.Int, error) { - deltaAttr, ok := event.GetAttribute(precisebanktypes.AttributeKeyDelta) - if !ok { - return nil, fmt.Errorf("event %q missing attribute %q", precisebanktypes.EventTypeFractionalBalanceChange, sdk.AttributeKeyAmount) - } - - delta, ok := sdkmath.NewIntFromString(deltaAttr.Value) - if !ok { - return nil, fmt.Errorf("failed to parse coins from %q", deltaAttr.Value) - } - - return delta.BigInt(), nil -} diff --git a/precompiles/distribution/abi.json b/precompiles/distribution/abi.json index 462f1a9f..32c28715 100644 --- a/precompiles/distribution/abi.json +++ b/precompiles/distribution/abi.json @@ -1,764 +1,755 @@ -{ - "_format": "hh-sol-artifact-1", - "contractName": "DistributionI", - "sourceName": "solidity/precompiles/distribution/DistributionI.sol", - "abi": [ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "delegatorAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "ClaimRewards", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "depositor", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "validatorAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "string", - "name": "denom", - "type": "string" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "DepositValidatorRewardsPool", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "depositor", - "type": "address" - }, - { - "indexed": false, - "internalType": "string", - "name": "denom", - "type": "string" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FundCommunityPool", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "caller", - "type": "address" - }, - { - "indexed": false, - "internalType": "string", - "name": "withdrawerAddress", - "type": "string" - } - ], - "name": "SetWithdrawerAddress", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "delegatorAddress", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "validatorAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "WithdrawDelegatorReward", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "string", - "name": "validatorAddress", - "type": "string" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "commission", - "type": "uint256" - } - ], - "name": "WithdrawValidatorCommission", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "delegatorAddress", - "type": "address" - }, - { - "internalType": "uint32", - "name": "maxRetrieve", - "type": "uint32" - } - ], - "name": "claimRewards", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "communityPool", - "outputs": [ - { - "components": [ - { - "internalType": "string", - "name": "denom", - "type": "string" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "precision", - "type": "uint8" - } - ], - "internalType": "struct DecCoin[]", - "name": "coins", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "delegatorAddress", - "type": "address" - }, - { - "internalType": "string", - "name": "validatorAddress", - "type": "string" - } - ], - "name": "delegationRewards", - "outputs": [ - { - "components": [ - { - "internalType": "string", - "name": "denom", - "type": "string" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "precision", - "type": "uint8" - } - ], - "internalType": "struct DecCoin[]", - "name": "rewards", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "delegatorAddress", - "type": "address" - } - ], - "name": "delegationTotalRewards", - "outputs": [ - { - "components": [ - { - "internalType": "string", - "name": "validatorAddress", - "type": "string" - }, - { - "components": [ - { - "internalType": "string", - "name": "denom", - "type": "string" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "precision", - "type": "uint8" - } - ], - "internalType": "struct DecCoin[]", - "name": "reward", - "type": "tuple[]" - } - ], - "internalType": "struct DelegationDelegatorReward[]", - "name": "rewards", - "type": "tuple[]" - }, - { - "components": [ - { - "internalType": "string", - "name": "denom", - "type": "string" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "precision", - "type": "uint8" - } - ], - "internalType": "struct DecCoin[]", - "name": "total", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "delegatorAddress", - "type": "address" - } - ], - "name": "delegatorValidators", - "outputs": [ - { - "internalType": "string[]", - "name": "validators", - "type": "string[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "delegatorAddress", - "type": "address" - } - ], - "name": "delegatorWithdrawAddress", - "outputs": [ - { - "internalType": "string", - "name": "withdrawAddress", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "depositor", - "type": "address" - }, - { - "internalType": "string", - "name": "validatorAddress", - "type": "string" - }, - { - "components": [ - { - "internalType": "string", - "name": "denom", - "type": "string" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct Coin[]", - "name": "amount", - "type": "tuple[]" - } - ], - "name": "depositValidatorRewardsPool", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "depositor", - "type": "address" - }, - { - "components": [ - { - "internalType": "string", - "name": "denom", - "type": "string" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct Coin[]", - "name": "amount", - "type": "tuple[]" - } - ], - "name": "fundCommunityPool", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "delegatorAddress", - "type": "address" - }, - { - "internalType": "string", - "name": "withdrawerAddress", - "type": "string" - } - ], - "name": "setWithdrawAddress", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "validatorAddress", - "type": "string" - } - ], - "name": "validatorCommission", - "outputs": [ - { - "components": [ - { - "internalType": "string", - "name": "denom", - "type": "string" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "precision", - "type": "uint8" - } - ], - "internalType": "struct DecCoin[]", - "name": "commission", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "validatorAddress", - "type": "string" - } - ], - "name": "validatorDistributionInfo", - "outputs": [ - { - "components": [ - { - "internalType": "string", - "name": "operatorAddress", - "type": "string" - }, - { - "components": [ - { - "internalType": "string", - "name": "denom", - "type": "string" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "precision", - "type": "uint8" - } - ], - "internalType": "struct DecCoin[]", - "name": "selfBondRewards", - "type": "tuple[]" - }, - { - "components": [ - { - "internalType": "string", - "name": "denom", - "type": "string" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "precision", - "type": "uint8" - } - ], - "internalType": "struct DecCoin[]", - "name": "commission", - "type": "tuple[]" - } - ], - "internalType": "struct ValidatorDistributionInfo", - "name": "distributionInfo", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "validatorAddress", - "type": "string" - } - ], - "name": "validatorOutstandingRewards", - "outputs": [ - { - "components": [ - { - "internalType": "string", - "name": "denom", - "type": "string" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "precision", - "type": "uint8" - } - ], - "internalType": "struct DecCoin[]", - "name": "rewards", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "validatorAddress", - "type": "string" - }, - { - "internalType": "uint64", - "name": "startingHeight", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "endingHeight", - "type": "uint64" - }, - { - "components": [ - { - "internalType": "bytes", - "name": "key", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offset", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "limit", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "countTotal", - "type": "bool" - }, - { - "internalType": "bool", - "name": "reverse", - "type": "bool" - } - ], - "internalType": "struct PageRequest", - "name": "pageRequest", - "type": "tuple" - } - ], - "name": "validatorSlashes", - "outputs": [ - { - "components": [ - { - "internalType": "uint64", - "name": "validatorPeriod", - "type": "uint64" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "precision", - "type": "uint8" - } - ], - "internalType": "struct Dec", - "name": "fraction", - "type": "tuple" - } - ], - "internalType": "struct ValidatorSlashEvent[]", - "name": "slashes", - "type": "tuple[]" - }, - { - "components": [ - { - "internalType": "bytes", - "name": "nextKey", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "total", - "type": "uint64" - } - ], - "internalType": "struct PageResponse", - "name": "pageResponse", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "delegatorAddress", - "type": "address" - }, - { - "internalType": "string", - "name": "validatorAddress", - "type": "string" - } - ], - "name": "withdrawDelegatorRewards", - "outputs": [ - { - "components": [ - { - "internalType": "string", - "name": "denom", - "type": "string" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct Coin[]", - "name": "amount", - "type": "tuple[]" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "validatorAddress", - "type": "string" - } - ], - "name": "withdrawValidatorCommission", - "outputs": [ - { - "components": [ - { - "internalType": "string", - "name": "denom", - "type": "string" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct Coin[]", - "name": "amount", - "type": "tuple[]" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "bytecode": "0x", - "deployedBytecode": "0x", - "linkReferences": {}, - "deployedLinkReferences": {} -} +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegatorAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ClaimRewards", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "depositor", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "validatorAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "DepositValidatorRewardsPool", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "depositor", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FundCommunityPool", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "withdrawerAddress", + "type": "string" + } + ], + "name": "SetWithdrawerAddress", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegatorAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "validatorAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "WithdrawDelegatorReward", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "string", + "name": "validatorAddress", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "commission", + "type": "uint256" + } + ], + "name": "WithdrawValidatorCommission", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatorAddress", + "type": "address" + }, + { + "internalType": "uint32", + "name": "maxRetrieve", + "type": "uint32" + } + ], + "name": "claimRewards", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "communityPool", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "precision", + "type": "uint8" + } + ], + "internalType": "struct DecCoin[]", + "name": "coins", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatorAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "validatorAddress", + "type": "string" + } + ], + "name": "delegationRewards", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "precision", + "type": "uint8" + } + ], + "internalType": "struct DecCoin[]", + "name": "rewards", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatorAddress", + "type": "address" + } + ], + "name": "delegationTotalRewards", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "validatorAddress", + "type": "string" + }, + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "precision", + "type": "uint8" + } + ], + "internalType": "struct DecCoin[]", + "name": "reward", + "type": "tuple[]" + } + ], + "internalType": "struct DelegationDelegatorReward[]", + "name": "rewards", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "precision", + "type": "uint8" + } + ], + "internalType": "struct DecCoin[]", + "name": "total", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatorAddress", + "type": "address" + } + ], + "name": "delegatorValidators", + "outputs": [ + { + "internalType": "string[]", + "name": "validators", + "type": "string[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatorAddress", + "type": "address" + } + ], + "name": "delegatorWithdrawAddress", + "outputs": [ + { + "internalType": "string", + "name": "withdrawAddress", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "depositor", + "type": "address" + }, + { + "internalType": "string", + "name": "validatorAddress", + "type": "string" + }, + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Coin[]", + "name": "amount", + "type": "tuple[]" + } + ], + "name": "depositValidatorRewardsPool", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "depositor", + "type": "address" + }, + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Coin[]", + "name": "amount", + "type": "tuple[]" + } + ], + "name": "fundCommunityPool", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatorAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "withdrawerAddress", + "type": "string" + } + ], + "name": "setWithdrawAddress", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "validatorAddress", + "type": "string" + } + ], + "name": "validatorCommission", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "precision", + "type": "uint8" + } + ], + "internalType": "struct DecCoin[]", + "name": "commission", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "validatorAddress", + "type": "string" + } + ], + "name": "validatorDistributionInfo", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "operatorAddress", + "type": "string" + }, + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "precision", + "type": "uint8" + } + ], + "internalType": "struct DecCoin[]", + "name": "selfBondRewards", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "precision", + "type": "uint8" + } + ], + "internalType": "struct DecCoin[]", + "name": "commission", + "type": "tuple[]" + } + ], + "internalType": "struct ValidatorDistributionInfo", + "name": "distributionInfo", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "validatorAddress", + "type": "string" + } + ], + "name": "validatorOutstandingRewards", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "precision", + "type": "uint8" + } + ], + "internalType": "struct DecCoin[]", + "name": "rewards", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "validatorAddress", + "type": "string" + }, + { + "internalType": "uint64", + "name": "startingHeight", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "endingHeight", + "type": "uint64" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offset", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "limit", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "countTotal", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reverse", + "type": "bool" + } + ], + "internalType": "struct PageRequest", + "name": "pageRequest", + "type": "tuple" + } + ], + "name": "validatorSlashes", + "outputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "validatorPeriod", + "type": "uint64" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "precision", + "type": "uint8" + } + ], + "internalType": "struct Dec", + "name": "fraction", + "type": "tuple" + } + ], + "internalType": "struct ValidatorSlashEvent[]", + "name": "slashes", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "nextKey", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "total", + "type": "uint64" + } + ], + "internalType": "struct PageResponse", + "name": "pageResponse", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatorAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "validatorAddress", + "type": "string" + } + ], + "name": "withdrawDelegatorRewards", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Coin[]", + "name": "amount", + "type": "tuple[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "validatorAddress", + "type": "string" + } + ], + "name": "withdrawValidatorCommission", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Coin[]", + "name": "amount", + "type": "tuple[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/precompiles/distribution/distribution.go b/precompiles/distribution/distribution.go index f363fa7c..fb315f70 100644 --- a/precompiles/distribution/distribution.go +++ b/precompiles/distribution/distribution.go @@ -1,19 +1,21 @@ package distribution import ( - "embed" + "bytes" "fmt" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" + _ "embed" + cmn "github.com/cosmos/evm/precompiles/common" evmtypes "github.com/cosmos/evm/x/vm/types" "cosmossdk.io/core/address" - storetypes "cosmossdk.io/store/types" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types" ) @@ -24,13 +26,13 @@ var ( // Embed abi json file to the executable binary. Needed when importing as dependency. // //go:embed abi.json - f embed.FS + f []byte ABI abi.ABI ) func init() { var err error - ABI, err = cmn.LoadABI(f, "abi.json") + ABI, err = abi.JSON(bytes.NewReader(f)) if err != nil { panic(err) } @@ -74,6 +76,10 @@ func NewPrecompile( } } +func (Precompile) Name() string { + return "distribution" +} + // RequiredGas calculates the precompiled contract's base gas rate. func (p Precompile) RequiredGas(input []byte) uint64 { // TODO: refactor this to be used in the common precompile method on a separate PR diff --git a/precompiles/distribution/tx.go b/precompiles/distribution/tx.go index 3dea64f0..bc1e9a04 100644 --- a/precompiles/distribution/tx.go +++ b/precompiles/distribution/tx.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" cmn "github.com/cosmos/evm/precompiles/common" @@ -102,6 +103,13 @@ func (p Precompile) SetWithdrawAddress( return nil, fmt.Errorf(cmn.ErrRequesterIsNotMsgSender, msgSender.String(), delegatorHexAddr.String()) } + if withdrawAddr, decErr := p.addrCdc.StringToBytes(msg.WithdrawAddress); decErr == nil && len(withdrawAddr) != common.AddressLength { + return nil, fmt.Errorf( + "withdraw address must be exactly %d bytes to be EVM-compatible; got %d bytes: %s", + common.AddressLength, len(withdrawAddr), msg.WithdrawAddress, + ) + } + if _, err = p.distributionMsgServer.SetWithdrawAddress(ctx, msg); err != nil { return nil, err } diff --git a/precompiles/erc20/abi.json b/precompiles/erc20/abi.json index ebb8c03b..177ac839 100644 --- a/precompiles/erc20/abi.json +++ b/precompiles/erc20/abi.json @@ -1,233 +1,224 @@ -{ - "_format": "hh-sol-artifact-1", - "contractName": "IERC20Metadata", - "sourceName": "solidity/precompiles/erc20/IERC20Metadata.sol", - "abi": [ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "bytecode": "0x", - "deployedBytecode": "0x", - "linkReferences": {}, - "deployedLinkReferences": {} -} +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/precompiles/erc20/erc20.go b/precompiles/erc20/erc20.go index 12121b7c..eeb46b8a 100644 --- a/precompiles/erc20/erc20.go +++ b/precompiles/erc20/erc20.go @@ -1,25 +1,23 @@ package erc20 import ( - "embed" + "bytes" "fmt" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/core/vm" + _ "embed" + ibcutils "github.com/cosmos/evm/ibc" cmn "github.com/cosmos/evm/precompiles/common" erc20types "github.com/cosmos/evm/x/erc20/types" - storetypes "cosmossdk.io/store/types" - + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" ) const ( - // abiPath defines the path to the ERC-20 precompile ABI JSON file. - abiPath = "abi.json" - // NOTE: These gas values have been derived from tests that have been concluded on a testing branch, which // is not being merged to the main branch. The reason for this was to not clutter the repository with the // necessary tests for this use case. @@ -42,13 +40,13 @@ var ( // Embed abi json file to the executable binary. Needed when importing as dependency. // //go:embed abi.json - f embed.FS + f []byte ABI abi.ABI ) func init() { var err error - ABI, err = cmn.LoadABI(f, abiPath) + ABI, err = abi.JSON(bytes.NewReader(f)) if err != nil { panic(err) } @@ -68,12 +66,6 @@ type Precompile struct { 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( @@ -97,6 +89,10 @@ func NewPrecompile( } } +func (p Precompile) Name() string { + return "erc20" +} + // RequiredGas calculates the contract gas used for the func (p Precompile) RequiredGas(input []byte) uint64 { // NOTE: This check avoid panicking when trying to decode the method ID @@ -192,7 +188,7 @@ func (p *Precompile) HandleMethod( bz, err = p.Approve(ctx, contract, stateDB, method, args) // ERC-20 queries case NameMethod: - bz, err = p.Name(ctx, contract, stateDB, method, args) + bz, err = p.TokenName(ctx, contract, stateDB, method, args) case SymbolMethod: bz, err = p.Symbol(ctx, contract, stateDB, method, args) case DecimalsMethod: diff --git a/precompiles/erc20/msgsrv.go b/precompiles/erc20/msgsrv.go index 00ba9223..ed60ab1f 100644 --- a/precompiles/erc20/msgsrv.go +++ b/precompiles/erc20/msgsrv.go @@ -4,7 +4,6 @@ import ( "context" cmn "github.com/cosmos/evm/precompiles/common" - precisebankkeeper "github.com/cosmos/evm/x/precisebank/keeper" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" @@ -38,16 +37,6 @@ func (m MsgServer) Send(goCtx context.Context, msg *banktypes.MsgSend) error { // 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/erc20/query.go b/precompiles/erc20/query.go index e0c7b72f..8c9a6ff3 100644 --- a/precompiles/erc20/query.go +++ b/precompiles/erc20/query.go @@ -38,7 +38,7 @@ const ( // Name returns the name of the token. If the token metadata is registered in the // bank module, it returns its name. Otherwise, it returns the base denomination of // the token capitalized (e.g. uatom -> Atom). -func (p Precompile) Name( +func (p Precompile) TokenName( ctx sdk.Context, _ *vm.Contract, _ vm.StateDB, diff --git a/precompiles/erc20/tx.go b/precompiles/erc20/tx.go index 173ca6cc..f1ed409f 100644 --- a/precompiles/erc20/tx.go +++ b/precompiles/erc20/tx.go @@ -87,14 +87,12 @@ func (p *Precompile) transfer( newAllowance := big.NewInt(0) if isTransferFrom { - spenderAddr := contract.Caller() - prevAllowance, err := p.erc20Keeper.GetAllowance(ctx, p.Address(), from, spenderAddr) if err != nil { return nil, ConvertErrToERC20Error(err) } - newAllowance := new(big.Int).Sub(prevAllowance, amount) + newAllowance = new(big.Int).Sub(prevAllowance, amount) if newAllowance.Sign() < 0 { return nil, ErrInsufficientAllowance } diff --git a/precompiles/gov/abi.json b/precompiles/gov/abi.json index 291e56e7..c318e6a2 100644 --- a/precompiles/gov/abi.json +++ b/precompiles/gov/abi.json @@ -1,1116 +1,1107 @@ -{ - "_format": "hh-sol-artifact-1", - "contractName": "IGov", - "sourceName": "solidity/precompiles/gov/IGov.sol", - "abi": [ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "proposer", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "proposalId", - "type": "uint64" - } - ], - "name": "CancelProposal", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "depositor", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "proposalId", - "type": "uint64" - }, - { - "components": [ - { - "internalType": "string", - "name": "denom", - "type": "string" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "indexed": false, - "internalType": "struct Coin[]", - "name": "amount", - "type": "tuple[]" - } - ], - "name": "Deposit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "proposer", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "proposalId", - "type": "uint64" - } - ], - "name": "SubmitProposal", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "voter", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "proposalId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "option", - "type": "uint8" - } - ], - "name": "Vote", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "voter", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "proposalId", - "type": "uint64" - }, - { - "components": [ - { - "internalType": "enum VoteOption", - "name": "option", - "type": "uint8" - }, - { - "internalType": "string", - "name": "weight", - "type": "string" - } - ], - "indexed": false, - "internalType": "struct WeightedVoteOption[]", - "name": "options", - "type": "tuple[]" - } - ], - "name": "VoteWeighted", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "proposer", - "type": "address" - }, - { - "internalType": "uint64", - "name": "proposalId", - "type": "uint64" - } - ], - "name": "cancelProposal", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "depositor", - "type": "address" - }, - { - "internalType": "uint64", - "name": "proposalId", - "type": "uint64" - }, - { - "components": [ - { - "internalType": "string", - "name": "denom", - "type": "string" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct Coin[]", - "name": "amount", - "type": "tuple[]" - } - ], - "name": "deposit", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getConstitution", - "outputs": [ - { - "internalType": "string", - "name": "constitution", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "proposalId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "depositor", - "type": "address" - } - ], - "name": "getDeposit", - "outputs": [ - { - "components": [ - { - "internalType": "uint64", - "name": "proposalId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "depositor", - "type": "address" - }, - { - "components": [ - { - "internalType": "string", - "name": "denom", - "type": "string" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct Coin[]", - "name": "amount", - "type": "tuple[]" - } - ], - "internalType": "struct DepositData", - "name": "deposit", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "proposalId", - "type": "uint64" - }, - { - "components": [ - { - "internalType": "bytes", - "name": "key", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offset", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "limit", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "countTotal", - "type": "bool" - }, - { - "internalType": "bool", - "name": "reverse", - "type": "bool" - } - ], - "internalType": "struct PageRequest", - "name": "pagination", - "type": "tuple" - } - ], - "name": "getDeposits", - "outputs": [ - { - "components": [ - { - "internalType": "uint64", - "name": "proposalId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "depositor", - "type": "address" - }, - { - "components": [ - { - "internalType": "string", - "name": "denom", - "type": "string" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct Coin[]", - "name": "amount", - "type": "tuple[]" - } - ], - "internalType": "struct DepositData[]", - "name": "deposits", - "type": "tuple[]" - }, - { - "components": [ - { - "internalType": "bytes", - "name": "nextKey", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "total", - "type": "uint64" - } - ], - "internalType": "struct PageResponse", - "name": "pageResponse", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getParams", - "outputs": [ - { - "components": [ - { - "internalType": "int64", - "name": "votingPeriod", - "type": "int64" - }, - { - "components": [ - { - "internalType": "string", - "name": "denom", - "type": "string" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct Coin[]", - "name": "minDeposit", - "type": "tuple[]" - }, - { - "internalType": "int64", - "name": "maxDepositPeriod", - "type": "int64" - }, - { - "internalType": "string", - "name": "quorum", - "type": "string" - }, - { - "internalType": "string", - "name": "threshold", - "type": "string" - }, - { - "internalType": "string", - "name": "vetoThreshold", - "type": "string" - }, - { - "internalType": "string", - "name": "minInitialDepositRatio", - "type": "string" - }, - { - "internalType": "string", - "name": "proposalCancelRatio", - "type": "string" - }, - { - "internalType": "string", - "name": "proposalCancelDest", - "type": "string" - }, - { - "internalType": "int64", - "name": "expeditedVotingPeriod", - "type": "int64" - }, - { - "internalType": "string", - "name": "expeditedThreshold", - "type": "string" - }, - { - "components": [ - { - "internalType": "string", - "name": "denom", - "type": "string" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct Coin[]", - "name": "expeditedMinDeposit", - "type": "tuple[]" - }, - { - "internalType": "bool", - "name": "burnVoteQuorum", - "type": "bool" - }, - { - "internalType": "bool", - "name": "burnProposalDepositPrevote", - "type": "bool" - }, - { - "internalType": "bool", - "name": "burnVoteVeto", - "type": "bool" - }, - { - "internalType": "string", - "name": "minDepositRatio", - "type": "string" - } - ], - "internalType": "struct Params", - "name": "params", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "proposalId", - "type": "uint64" - } - ], - "name": "getProposal", - "outputs": [ - { - "components": [ - { - "internalType": "uint64", - "name": "id", - "type": "uint64" - }, - { - "internalType": "string[]", - "name": "messages", - "type": "string[]" - }, - { - "internalType": "uint32", - "name": "status", - "type": "uint32" - }, - { - "components": [ - { - "internalType": "string", - "name": "yes", - "type": "string" - }, - { - "internalType": "string", - "name": "abstain", - "type": "string" - }, - { - "internalType": "string", - "name": "no", - "type": "string" - }, - { - "internalType": "string", - "name": "noWithVeto", - "type": "string" - } - ], - "internalType": "struct TallyResultData", - "name": "finalTallyResult", - "type": "tuple" - }, - { - "internalType": "uint64", - "name": "submitTime", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "depositEndTime", - "type": "uint64" - }, - { - "components": [ - { - "internalType": "string", - "name": "denom", - "type": "string" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct Coin[]", - "name": "totalDeposit", - "type": "tuple[]" - }, - { - "internalType": "uint64", - "name": "votingStartTime", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "votingEndTime", - "type": "uint64" - }, - { - "internalType": "string", - "name": "metadata", - "type": "string" - }, - { - "internalType": "string", - "name": "title", - "type": "string" - }, - { - "internalType": "string", - "name": "summary", - "type": "string" - }, - { - "internalType": "address", - "name": "proposer", - "type": "address" - } - ], - "internalType": "struct ProposalData", - "name": "proposal", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "proposalStatus", - "type": "uint32" - }, - { - "internalType": "address", - "name": "voter", - "type": "address" - }, - { - "internalType": "address", - "name": "depositor", - "type": "address" - }, - { - "components": [ - { - "internalType": "bytes", - "name": "key", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offset", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "limit", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "countTotal", - "type": "bool" - }, - { - "internalType": "bool", - "name": "reverse", - "type": "bool" - } - ], - "internalType": "struct PageRequest", - "name": "pagination", - "type": "tuple" - } - ], - "name": "getProposals", - "outputs": [ - { - "components": [ - { - "internalType": "uint64", - "name": "id", - "type": "uint64" - }, - { - "internalType": "string[]", - "name": "messages", - "type": "string[]" - }, - { - "internalType": "uint32", - "name": "status", - "type": "uint32" - }, - { - "components": [ - { - "internalType": "string", - "name": "yes", - "type": "string" - }, - { - "internalType": "string", - "name": "abstain", - "type": "string" - }, - { - "internalType": "string", - "name": "no", - "type": "string" - }, - { - "internalType": "string", - "name": "noWithVeto", - "type": "string" - } - ], - "internalType": "struct TallyResultData", - "name": "finalTallyResult", - "type": "tuple" - }, - { - "internalType": "uint64", - "name": "submitTime", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "depositEndTime", - "type": "uint64" - }, - { - "components": [ - { - "internalType": "string", - "name": "denom", - "type": "string" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct Coin[]", - "name": "totalDeposit", - "type": "tuple[]" - }, - { - "internalType": "uint64", - "name": "votingStartTime", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "votingEndTime", - "type": "uint64" - }, - { - "internalType": "string", - "name": "metadata", - "type": "string" - }, - { - "internalType": "string", - "name": "title", - "type": "string" - }, - { - "internalType": "string", - "name": "summary", - "type": "string" - }, - { - "internalType": "address", - "name": "proposer", - "type": "address" - } - ], - "internalType": "struct ProposalData[]", - "name": "proposals", - "type": "tuple[]" - }, - { - "components": [ - { - "internalType": "bytes", - "name": "nextKey", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "total", - "type": "uint64" - } - ], - "internalType": "struct PageResponse", - "name": "pageResponse", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "proposalId", - "type": "uint64" - } - ], - "name": "getTallyResult", - "outputs": [ - { - "components": [ - { - "internalType": "string", - "name": "yes", - "type": "string" - }, - { - "internalType": "string", - "name": "abstain", - "type": "string" - }, - { - "internalType": "string", - "name": "no", - "type": "string" - }, - { - "internalType": "string", - "name": "noWithVeto", - "type": "string" - } - ], - "internalType": "struct TallyResultData", - "name": "tallyResult", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "proposalId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "voter", - "type": "address" - } - ], - "name": "getVote", - "outputs": [ - { - "components": [ - { - "internalType": "uint64", - "name": "proposalId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "voter", - "type": "address" - }, - { - "components": [ - { - "internalType": "enum VoteOption", - "name": "option", - "type": "uint8" - }, - { - "internalType": "string", - "name": "weight", - "type": "string" - } - ], - "internalType": "struct WeightedVoteOption[]", - "name": "options", - "type": "tuple[]" - }, - { - "internalType": "string", - "name": "metadata", - "type": "string" - } - ], - "internalType": "struct WeightedVote", - "name": "vote", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "proposalId", - "type": "uint64" - }, - { - "components": [ - { - "internalType": "bytes", - "name": "key", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offset", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "limit", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "countTotal", - "type": "bool" - }, - { - "internalType": "bool", - "name": "reverse", - "type": "bool" - } - ], - "internalType": "struct PageRequest", - "name": "pagination", - "type": "tuple" - } - ], - "name": "getVotes", - "outputs": [ - { - "components": [ - { - "internalType": "uint64", - "name": "proposalId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "voter", - "type": "address" - }, - { - "components": [ - { - "internalType": "enum VoteOption", - "name": "option", - "type": "uint8" - }, - { - "internalType": "string", - "name": "weight", - "type": "string" - } - ], - "internalType": "struct WeightedVoteOption[]", - "name": "options", - "type": "tuple[]" - }, - { - "internalType": "string", - "name": "metadata", - "type": "string" - } - ], - "internalType": "struct WeightedVote[]", - "name": "votes", - "type": "tuple[]" - }, - { - "components": [ - { - "internalType": "bytes", - "name": "nextKey", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "total", - "type": "uint64" - } - ], - "internalType": "struct PageResponse", - "name": "pageResponse", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "proposer", - "type": "address" - }, - { - "internalType": "bytes", - "name": "jsonProposal", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "string", - "name": "denom", - "type": "string" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct Coin[]", - "name": "deposit", - "type": "tuple[]" - } - ], - "name": "submitProposal", - "outputs": [ - { - "internalType": "uint64", - "name": "proposalId", - "type": "uint64" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "voter", - "type": "address" - }, - { - "internalType": "uint64", - "name": "proposalId", - "type": "uint64" - }, - { - "internalType": "enum VoteOption", - "name": "option", - "type": "uint8" - }, - { - "internalType": "string", - "name": "metadata", - "type": "string" - } - ], - "name": "vote", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "voter", - "type": "address" - }, - { - "internalType": "uint64", - "name": "proposalId", - "type": "uint64" - }, - { - "components": [ - { - "internalType": "enum VoteOption", - "name": "option", - "type": "uint8" - }, - { - "internalType": "string", - "name": "weight", - "type": "string" - } - ], - "internalType": "struct WeightedVoteOption[]", - "name": "options", - "type": "tuple[]" - }, - { - "internalType": "string", - "name": "metadata", - "type": "string" - } - ], - "name": "voteWeighted", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "bytecode": "0x", - "deployedBytecode": "0x", - "linkReferences": {}, - "deployedLinkReferences": {} -} +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "proposalId", + "type": "uint64" + } + ], + "name": "CancelProposal", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "depositor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "proposalId", + "type": "uint64" + }, + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "indexed": false, + "internalType": "struct Coin[]", + "name": "amount", + "type": "tuple[]" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "proposalId", + "type": "uint64" + } + ], + "name": "SubmitProposal", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "proposalId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "option", + "type": "uint8" + } + ], + "name": "Vote", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "proposalId", + "type": "uint64" + }, + { + "components": [ + { + "internalType": "enum VoteOption", + "name": "option", + "type": "uint8" + }, + { + "internalType": "string", + "name": "weight", + "type": "string" + } + ], + "indexed": false, + "internalType": "struct WeightedVoteOption[]", + "name": "options", + "type": "tuple[]" + } + ], + "name": "VoteWeighted", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "internalType": "uint64", + "name": "proposalId", + "type": "uint64" + } + ], + "name": "cancelProposal", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "depositor", + "type": "address" + }, + { + "internalType": "uint64", + "name": "proposalId", + "type": "uint64" + }, + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Coin[]", + "name": "amount", + "type": "tuple[]" + } + ], + "name": "deposit", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getConstitution", + "outputs": [ + { + "internalType": "string", + "name": "constitution", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "proposalId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "depositor", + "type": "address" + } + ], + "name": "getDeposit", + "outputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "proposalId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "depositor", + "type": "address" + }, + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Coin[]", + "name": "amount", + "type": "tuple[]" + } + ], + "internalType": "struct DepositData", + "name": "deposit", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "proposalId", + "type": "uint64" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offset", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "limit", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "countTotal", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reverse", + "type": "bool" + } + ], + "internalType": "struct PageRequest", + "name": "pagination", + "type": "tuple" + } + ], + "name": "getDeposits", + "outputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "proposalId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "depositor", + "type": "address" + }, + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Coin[]", + "name": "amount", + "type": "tuple[]" + } + ], + "internalType": "struct DepositData[]", + "name": "deposits", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "nextKey", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "total", + "type": "uint64" + } + ], + "internalType": "struct PageResponse", + "name": "pageResponse", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getParams", + "outputs": [ + { + "components": [ + { + "internalType": "int64", + "name": "votingPeriod", + "type": "int64" + }, + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Coin[]", + "name": "minDeposit", + "type": "tuple[]" + }, + { + "internalType": "int64", + "name": "maxDepositPeriod", + "type": "int64" + }, + { + "internalType": "string", + "name": "quorum", + "type": "string" + }, + { + "internalType": "string", + "name": "threshold", + "type": "string" + }, + { + "internalType": "string", + "name": "vetoThreshold", + "type": "string" + }, + { + "internalType": "string", + "name": "minInitialDepositRatio", + "type": "string" + }, + { + "internalType": "string", + "name": "proposalCancelRatio", + "type": "string" + }, + { + "internalType": "string", + "name": "proposalCancelDest", + "type": "string" + }, + { + "internalType": "int64", + "name": "expeditedVotingPeriod", + "type": "int64" + }, + { + "internalType": "string", + "name": "expeditedThreshold", + "type": "string" + }, + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Coin[]", + "name": "expeditedMinDeposit", + "type": "tuple[]" + }, + { + "internalType": "bool", + "name": "burnVoteQuorum", + "type": "bool" + }, + { + "internalType": "bool", + "name": "burnProposalDepositPrevote", + "type": "bool" + }, + { + "internalType": "bool", + "name": "burnVoteVeto", + "type": "bool" + }, + { + "internalType": "string", + "name": "minDepositRatio", + "type": "string" + } + ], + "internalType": "struct Params", + "name": "params", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "proposalId", + "type": "uint64" + } + ], + "name": "getProposal", + "outputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "internalType": "string[]", + "name": "messages", + "type": "string[]" + }, + { + "internalType": "uint32", + "name": "status", + "type": "uint32" + }, + { + "components": [ + { + "internalType": "string", + "name": "yes", + "type": "string" + }, + { + "internalType": "string", + "name": "abstain", + "type": "string" + }, + { + "internalType": "string", + "name": "no", + "type": "string" + }, + { + "internalType": "string", + "name": "noWithVeto", + "type": "string" + } + ], + "internalType": "struct TallyResultData", + "name": "finalTallyResult", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "submitTime", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "depositEndTime", + "type": "uint64" + }, + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Coin[]", + "name": "totalDeposit", + "type": "tuple[]" + }, + { + "internalType": "uint64", + "name": "votingStartTime", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "votingEndTime", + "type": "uint64" + }, + { + "internalType": "string", + "name": "metadata", + "type": "string" + }, + { + "internalType": "string", + "name": "title", + "type": "string" + }, + { + "internalType": "string", + "name": "summary", + "type": "string" + }, + { + "internalType": "address", + "name": "proposer", + "type": "address" + } + ], + "internalType": "struct ProposalData", + "name": "proposal", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "proposalStatus", + "type": "uint32" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "address", + "name": "depositor", + "type": "address" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offset", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "limit", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "countTotal", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reverse", + "type": "bool" + } + ], + "internalType": "struct PageRequest", + "name": "pagination", + "type": "tuple" + } + ], + "name": "getProposals", + "outputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "internalType": "string[]", + "name": "messages", + "type": "string[]" + }, + { + "internalType": "uint32", + "name": "status", + "type": "uint32" + }, + { + "components": [ + { + "internalType": "string", + "name": "yes", + "type": "string" + }, + { + "internalType": "string", + "name": "abstain", + "type": "string" + }, + { + "internalType": "string", + "name": "no", + "type": "string" + }, + { + "internalType": "string", + "name": "noWithVeto", + "type": "string" + } + ], + "internalType": "struct TallyResultData", + "name": "finalTallyResult", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "submitTime", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "depositEndTime", + "type": "uint64" + }, + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Coin[]", + "name": "totalDeposit", + "type": "tuple[]" + }, + { + "internalType": "uint64", + "name": "votingStartTime", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "votingEndTime", + "type": "uint64" + }, + { + "internalType": "string", + "name": "metadata", + "type": "string" + }, + { + "internalType": "string", + "name": "title", + "type": "string" + }, + { + "internalType": "string", + "name": "summary", + "type": "string" + }, + { + "internalType": "address", + "name": "proposer", + "type": "address" + } + ], + "internalType": "struct ProposalData[]", + "name": "proposals", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "nextKey", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "total", + "type": "uint64" + } + ], + "internalType": "struct PageResponse", + "name": "pageResponse", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "proposalId", + "type": "uint64" + } + ], + "name": "getTallyResult", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "yes", + "type": "string" + }, + { + "internalType": "string", + "name": "abstain", + "type": "string" + }, + { + "internalType": "string", + "name": "no", + "type": "string" + }, + { + "internalType": "string", + "name": "noWithVeto", + "type": "string" + } + ], + "internalType": "struct TallyResultData", + "name": "tallyResult", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "proposalId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "getVote", + "outputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "proposalId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "components": [ + { + "internalType": "enum VoteOption", + "name": "option", + "type": "uint8" + }, + { + "internalType": "string", + "name": "weight", + "type": "string" + } + ], + "internalType": "struct WeightedVoteOption[]", + "name": "options", + "type": "tuple[]" + }, + { + "internalType": "string", + "name": "metadata", + "type": "string" + } + ], + "internalType": "struct WeightedVote", + "name": "vote", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "proposalId", + "type": "uint64" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offset", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "limit", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "countTotal", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reverse", + "type": "bool" + } + ], + "internalType": "struct PageRequest", + "name": "pagination", + "type": "tuple" + } + ], + "name": "getVotes", + "outputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "proposalId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "components": [ + { + "internalType": "enum VoteOption", + "name": "option", + "type": "uint8" + }, + { + "internalType": "string", + "name": "weight", + "type": "string" + } + ], + "internalType": "struct WeightedVoteOption[]", + "name": "options", + "type": "tuple[]" + }, + { + "internalType": "string", + "name": "metadata", + "type": "string" + } + ], + "internalType": "struct WeightedVote[]", + "name": "votes", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "nextKey", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "total", + "type": "uint64" + } + ], + "internalType": "struct PageResponse", + "name": "pageResponse", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "internalType": "bytes", + "name": "jsonProposal", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Coin[]", + "name": "deposit", + "type": "tuple[]" + } + ], + "name": "submitProposal", + "outputs": [ + { + "internalType": "uint64", + "name": "proposalId", + "type": "uint64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "uint64", + "name": "proposalId", + "type": "uint64" + }, + { + "internalType": "enum VoteOption", + "name": "option", + "type": "uint8" + }, + { + "internalType": "string", + "name": "metadata", + "type": "string" + } + ], + "name": "vote", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "uint64", + "name": "proposalId", + "type": "uint64" + }, + { + "components": [ + { + "internalType": "enum VoteOption", + "name": "option", + "type": "uint8" + }, + { + "internalType": "string", + "name": "weight", + "type": "string" + } + ], + "internalType": "struct WeightedVoteOption[]", + "name": "options", + "type": "tuple[]" + }, + { + "internalType": "string", + "name": "metadata", + "type": "string" + } + ], + "name": "voteWeighted", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/precompiles/gov/gov.go b/precompiles/gov/gov.go index baf84d22..24cd8fbf 100644 --- a/precompiles/gov/gov.go +++ b/precompiles/gov/gov.go @@ -1,20 +1,22 @@ package gov import ( - "embed" + "bytes" "fmt" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" + _ "embed" + cmn "github.com/cosmos/evm/precompiles/common" evmtypes "github.com/cosmos/evm/x/vm/types" "cosmossdk.io/core/address" - storetypes "cosmossdk.io/store/types" "github.com/cosmos/cosmos-sdk/codec" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1" ) @@ -25,13 +27,13 @@ var ( // Embed abi json file to the executable binary. Needed when importing as dependency. // //go:embed abi.json - f embed.FS + f []byte ABI abi.ABI ) func init() { var err error - ABI, err = cmn.LoadABI(f, "abi.json") + ABI, err = abi.JSON(bytes.NewReader(f)) if err != nil { panic(err) } @@ -72,6 +74,10 @@ func NewPrecompile( } } +func (Precompile) Name() string { + return "gov" +} + // RequiredGas calculates the precompiled contract's base gas rate. func (p Precompile) RequiredGas(input []byte) uint64 { // NOTE: This check avoid panicking when trying to decode the method ID diff --git a/precompiles/gov/types.go b/precompiles/gov/types.go index 8c0777bf..465ab940 100644 --- a/precompiles/gov/types.go +++ b/precompiles/gov/types.go @@ -23,20 +23,20 @@ import ( // EventVote defines the event data for the Vote transaction. type EventVote struct { Voter common.Address - ProposalId uint64 //nolint:revive + ProposalId uint64 Option uint8 } // EventVoteWeighted defines the event data for the VoteWeighted transaction. type EventVoteWeighted struct { Voter common.Address - ProposalId uint64 //nolint:revive + ProposalId uint64 Options WeightedVoteOptions } // VotesInput defines the input for the Votes query. type VotesInput struct { - ProposalId uint64 //nolint:revive + ProposalId uint64 Pagination query.PageRequest } @@ -53,7 +53,7 @@ type VoteOutput struct { // WeightedVote defines a struct of vote for vote split. type WeightedVote struct { - ProposalId uint64 //nolint:revive + ProposalId uint64 Voter common.Address Options []WeightedVoteOption Metadata string @@ -70,7 +70,7 @@ type WeightedVoteOptions []WeightedVoteOption // DepositInput defines the input for the Deposit query. type DepositInput struct { - ProposalId uint64 //nolint:revive + ProposalId uint64 Depositor common.Address } @@ -81,7 +81,7 @@ type DepositOutput struct { // DepositsInput defines the input for the Deposits query. type DepositsInput struct { - ProposalId uint64 //nolint:revive + ProposalId uint64 Pagination query.PageRequest } @@ -98,7 +98,7 @@ type TallyResultOutput struct { // DepositData represents information about a deposit on a proposal type DepositData struct { - ProposalId uint64 `abi:"proposalId"` //nolint:revive + ProposalId uint64 `abi:"proposalId"` Depositor common.Address `abi:"depositor"` Amount []cmn.Coin `abi:"amount"` } @@ -243,7 +243,7 @@ func NewMsgDeposit(args []interface{}, addrCdc address.Codec) (*govv1.MsgDeposit func NewMsgCancelProposal(args []interface{}, addrCdc address.Codec) (*govv1.MsgCancelProposal, common.Address, error) { emptyAddr := common.Address{} if len(args) != 2 { - return nil, emptyAddr, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 1, len(args)) + return nil, emptyAddr, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 2, len(args)) } proposer, ok := args[0].(common.Address) @@ -588,7 +588,7 @@ type ProposalsOutput struct { // ProposalData represents a governance proposal type ProposalData struct { - Id uint64 `abi:"id"` //nolint + Id uint64 `abi:"id"` Messages []string `abi:"messages"` Status uint32 `abi:"status"` FinalTallyResult TallyResultData `abi:"finalTallyResult"` diff --git a/precompiles/gov/types_test.go b/precompiles/gov/types_test.go index 64907876..52e81252 100644 --- a/precompiles/gov/types_test.go +++ b/precompiles/gov/types_test.go @@ -125,13 +125,13 @@ func TestNewMsgCancelProposal(t *testing.T) { name: "no arguments", args: []interface{}{}, wantErr: true, - errMsg: fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 1, 0), + errMsg: fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 2, 0), }, { name: "too many arguments", args: []interface{}{proposerAddr, proposalID, "extra"}, wantErr: true, - errMsg: fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 1, 3), + errMsg: fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 2, 3), }, { name: "invalid proposer type", diff --git a/precompiles/ics02/ICS02I.sol b/precompiles/ics02/ICS02I.sol new file mode 100644 index 00000000..9ddec82d --- /dev/null +++ b/precompiles/ics02/ICS02I.sol @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.18; + +import "../common/Types.sol"; + +/// @dev The ICS02I contract's address. +address constant ICS02_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000000807; + +/// @dev The ICS02 contract's instance. +ICS02I constant ICS02_CONTRACT = ICS02I(ICS02_PRECOMPILE_ADDRESS); + +/// @author CosmosLabs +/// @title ICS02 Client Router Precompile Interface +/// @dev The interface through which solidity contracts will interact with IBC Light Clients (ICS02) +/// @custom:address 0x0000000000000000000000000000000000000807 +interface ICS02I { + /// @notice The result of an update operation + enum UpdateResult { + /// The update was successful + Update, + /// A misbehaviour was detected + Misbehaviour + } + + /// @notice Updates the client with the given client identifier. + /// @param clientId The client identifier + /// @param updateMsg The encoded update message e.g., a protobuf any. + /// @return The result of the update operation + function updateClient(string calldata clientId, bytes calldata updateMsg) external returns (UpdateResult); + + /// @notice Querying the membership of a key-value pair + /// @dev Notice that this message is not view, as it may update the client state for caching purposes. + /// @param proof The proof of membership + /// @param proofHeight The height of the proof + /// @param path The path of the value in the Merkle tree + /// @param value The value in the Merkle tree + /// @return The unix timestamp of the verification height in the counterparty chain in seconds. + function verifyMembership( + string calldata clientId, + bytes calldata proof, + Height calldata proofHeight, + bytes[] calldata path, + bytes calldata value + ) external returns (uint256); + + /// @notice Querying the non-membership of a key + /// @dev Notice that this message is not view, as it may update the client state for caching purposes. + /// @param proof The proof of membership + /// @param proofHeight The height of the proof + /// @param path The path of the value in the Merkle tree + /// @return The unix timestamp of the verification height in the counterparty chain in seconds. + function verifyNonMembership( + string calldata clientId, + bytes calldata proof, + Height calldata proofHeight, + bytes[] calldata path + ) external returns (uint256); + + /// @notice Returns the client state. + /// @param clientId The client identifier + /// @return The client state. + function getClientState(string calldata clientId) external view returns (bytes memory); +} diff --git a/precompiles/ics02/README.md b/precompiles/ics02/README.md new file mode 100644 index 00000000..0931c994 --- /dev/null +++ b/precompiles/ics02/README.md @@ -0,0 +1,101 @@ +# ICS02 Precompile + +The ICS02 precompile provides an EVM interface to the IBC-Go's `02-client` module, +enabling smart contracts to interact with IBC light clients using the ICS-02 standard. + +## Address + +The precompile is available at the fixed address: `0x0000000000000000000000000000000000000807` + +## Interface + +### Data Structures + +```solidity +/// @notice The result of an update operation +enum UpdateResult { + /// The update was successful + Update, + /// A misbehaviour was detected + Misbehaviour +} +``` + +### Transaction Methods + +```solidity +/// @notice Updates the client with the given client identifier. +/// @param clientId The client identifier +/// @param updateMsg The encoded update message e.g., a protobuf any. +/// @return The result of the update operation +function updateClient(string calldata clientId, bytes calldata updateMsg) external returns (UpdateResult); + +/// @notice Querying the membership of a key-value pair +/// @dev Notice that this message is not view, as it may update the client state for caching purposes. +/// @param proof The proof of membership +/// @param proofHeight The height of the proof +/// @param path The path of the value in the Merkle tree +/// @param value The value in the Merkle tree +/// @return The unix timestamp of the verification height in the counterparty chain in seconds. +function verifyMembership( + string calldata clientId, + bytes calldata proof, + Height calldata proofHeight, + bytes[] calldata path, + bytes calldata value +) external returns (uint256); + +/// @notice Querying the non-membership of a key +/// @dev Notice that this message is not view, as it may update the client state for caching purposes. +/// @param proof The proof of membership +/// @param proofHeight The height of the proof +/// @param path The path of the value in the Merkle tree +/// @return The unix timestamp of the verification height in the counterparty chain in seconds. +function verifyNonMembership( + string calldata clientId, + bytes calldata proof, + Height calldata proofHeight, + bytes[] calldata path +) external returns (uint256); +``` + +### Query Methods + +```solidity +/// @notice Returns the client state. +/// @param clientId The client identifier +/// @return The client state. +function getClientState(string calldata clientId) external view returns (bytes memory); +``` + +## Gas Costs + +Gas costs are calculated dynamically based on: + +- Base gas for the method +- Additional gas for IBC operations +- Key-value storage operations + +The precompile uses standard gas configuration for storage operations. + +## Implementation Details + +### `GetClientState` + +This method is meant to be called by `solidity-ibc` relayers. It validates the client identifier and retrieves the protobuf encoded client state from the IBC-Go store. The relayer must decode the client state to correct type to use it. + +### `UpdateClient` + +This method allows updating the IBC light client state on-chain. It accepts a client identifier and an encoded client message (a protobuf Any). The method processes the update message, verifies it, and updates the client state accordingly. It returns an `UpdateResult` enum indicating whether the update was successful or if misbehaviour was detected. + +### `VerifyMembership` and `VerifyNonMembership` + +These methods allow smart contracts to verify the membership or non-membership of key-value pairs in the IBC light client's state. They accept a client identifier, a proof, proof height, and the path (and value for membership). The methods validate the proofs against the client state and return the unix timestamp (in seconds) of the verification height in the counterparty chain. + +## Events + +The ICS-02 precompile does not emit any events. Since it is meant to be called by other [`solidity-ibc`](https://github.com/cosmos/solidity-ibc-eureka) contracts, events should be emitted by the calling contract if needed. + +## Usage Example + +A usage example is to be included in `solidity-ibc` repository. For now, we link the tracking issue: [cosmos/solidity-ibc-eureka#794](https://github.com/cosmos/solidity-ibc-eureka/issues/794). diff --git a/precompiles/ics02/abi.json b/precompiles/ics02/abi.json new file mode 100644 index 00000000..71f457ae --- /dev/null +++ b/precompiles/ics02/abi.json @@ -0,0 +1,142 @@ +[ + { + "type": "function", + "name": "getClientState", + "inputs": [ + { + "name": "clientId", + "type": "string", + "internalType": "string" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes", + "internalType": "bytes" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "updateClient", + "inputs": [ + { + "name": "clientId", + "type": "string", + "internalType": "string" + }, + { + "name": "updateMsg", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [ + { + "name": "", + "type": "uint8", + "internalType": "enum ICS02I.UpdateResult" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "verifyMembership", + "inputs": [ + { + "name": "clientId", + "type": "string", + "internalType": "string" + }, + { + "name": "proof", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "proofHeight", + "type": "tuple", + "internalType": "struct Height", + "components": [ + { + "name": "revisionNumber", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "revisionHeight", + "type": "uint64", + "internalType": "uint64" + } + ] + }, + { + "name": "path", + "type": "bytes[]", + "internalType": "bytes[]" + }, + { + "name": "value", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "verifyNonMembership", + "inputs": [ + { + "name": "clientId", + "type": "string", + "internalType": "string" + }, + { + "name": "proof", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "proofHeight", + "type": "tuple", + "internalType": "struct Height", + "components": [ + { + "name": "revisionNumber", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "revisionHeight", + "type": "uint64", + "internalType": "uint64" + } + ] + }, + { + "name": "path", + "type": "bytes[]", + "internalType": "bytes[]" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "nonpayable" + } +] diff --git a/precompiles/ics02/ics02.go b/precompiles/ics02/ics02.go new file mode 100644 index 00000000..1d1d922a --- /dev/null +++ b/precompiles/ics02/ics02.go @@ -0,0 +1,134 @@ +package ics02 + +import ( + "bytes" + "fmt" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" + + _ "embed" + + ibcutils "github.com/cosmos/evm/ibc" + cmn "github.com/cosmos/evm/precompiles/common" + evmtypes "github.com/cosmos/evm/x/vm/types" + + "cosmossdk.io/log/v2" + + "github.com/cosmos/cosmos-sdk/codec" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var _ vm.PrecompiledContract = (*Precompile)(nil) + +var ( + // Embed abi json file to the executable binary. Needed when importing as dependency. + // + //go:embed abi.json + f []byte + ABI abi.ABI +) + +func init() { + var err error + ABI, err = abi.JSON(bytes.NewReader(f)) + if err != nil { + panic(err) + } +} + +// Precompile defines the precompiled contract for ICS02. +type Precompile struct { + cmn.Precompile + + abi.ABI + cdc codec.Codec + clientKeeper ibcutils.ClientKeeper +} + +// NewPrecompile creates a new Client Precompile instance as a +// PrecompiledContract interface. +func NewPrecompile( + cdc codec.Codec, + clientKeeper ibcutils.ClientKeeper, +) *Precompile { + return &Precompile{ + cdc: cdc, + Precompile: cmn.Precompile{ + KvGasConfig: storetypes.KVGasConfig(), + TransientKVGasConfig: storetypes.TransientGasConfig(), + ContractAddress: common.HexToAddress(evmtypes.ICS02PrecompileAddress), + }, + ABI: ABI, + clientKeeper: clientKeeper, + } +} + +func (Precompile) Name() string { + return "ics02" +} + +// RequiredGas calculates the precompiled contract's base gas rate. +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 { + // This should never happen since this method is going to fail during Run + return 0 + } + + return p.Precompile.RequiredGas(input, p.IsTransaction(method)) +} + +func (p Precompile) Run(evm *vm.EVM, contract *vm.Contract, readonly bool) ([]byte, error) { + return p.RunNativeAction(evm, contract, func(ctx sdk.Context) ([]byte, error) { + return p.Execute(ctx, evm.StateDB, contract, readonly) + }) +} + +func (p Precompile) Execute(ctx sdk.Context, stateDB vm.StateDB, contract *vm.Contract, readOnly bool) ([]byte, error) { + method, args, err := cmn.SetupABI(p.ABI, contract, readOnly, p.IsTransaction) + if err != nil { + return nil, err + } + + switch method.Name { + case UpdateClientMethod: + return p.UpdateClient(ctx, contract, stateDB, method, args) + case VerifyMembershipMethod: + return p.VerifyMembership(ctx, contract, stateDB, method, args) + case VerifyNonMembershipMethod: + return p.VerifyNonMembership(ctx, contract, stateDB, method, args) + // queries: + case GetClientStateMethod: + return p.GetClientState(ctx, contract, stateDB, method, args) + default: + return nil, fmt.Errorf(cmn.ErrUnknownMethod, method.Name) + } +} + +// IsTransaction checks if the given method name corresponds to a transaction or query. +func (Precompile) IsTransaction(method *abi.Method) bool { + switch method.Name { + case UpdateClientMethod, + VerifyMembershipMethod, + VerifyNonMembershipMethod: + return true + default: + // GetClientStateMethod is the only query method. + return false + } +} + +// Logger returns a precompile-specific logger. +func (p Precompile) Logger(ctx sdk.Context) log.Logger { + return ctx.Logger().With("evm extension", "ics02") +} diff --git a/precompiles/ics02/ics02_test.go b/precompiles/ics02/ics02_test.go new file mode 100644 index 00000000..3bf7eb8a --- /dev/null +++ b/precompiles/ics02/ics02_test.go @@ -0,0 +1,108 @@ +package ics02 + +import ( + "testing" + + "github.com/stretchr/testify/require" + + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" +) + +// TestRequiredGas guards against regression of the zero-gas DoS bypass where +// the precompile constructor zeroed KvGasConfig, causing RequiredGas to +// return 0 for every method regardless of calldata size. +func TestRequiredGas(t *testing.T) { + p := NewPrecompile(nil, nil) + kv := storetypes.KVGasConfig() + + height := struct { + RevisionNumber uint64 + RevisionHeight uint64 + }{RevisionNumber: 1, RevisionHeight: 100} + + tests := []struct { + name string + pack func(t *testing.T) []byte + isWrite bool + }{ + { + name: UpdateClientMethod, + pack: func(t *testing.T) []byte { + t.Helper() + in, err := p.Pack(UpdateClientMethod, "07-tendermint-0", []byte{0x01, 0x02, 0x03}) + require.NoError(t, err) + return in + }, + isWrite: true, + }, + { + name: VerifyMembershipMethod, + pack: func(t *testing.T) []byte { + t.Helper() + in, err := p.Pack( + VerifyMembershipMethod, + "07-tendermint-0", + []byte{0xaa, 0xbb}, + height, + [][]byte{[]byte("ibc"), []byte("clients/07-tendermint-0/clientState")}, + []byte("value"), + ) + require.NoError(t, err) + return in + }, + isWrite: true, + }, + { + name: VerifyNonMembershipMethod, + pack: func(t *testing.T) []byte { + t.Helper() + in, err := p.Pack( + VerifyNonMembershipMethod, + "07-tendermint-0", + []byte{0xaa, 0xbb}, + height, + [][]byte{[]byte("ibc"), []byte("clients/07-tendermint-0/clientState")}, + ) + require.NoError(t, err) + return in + }, + isWrite: true, + }, + { + name: GetClientStateMethod, + pack: func(t *testing.T) []byte { + t.Helper() + in, err := p.Pack(GetClientStateMethod, "07-tendermint-0") + require.NoError(t, err) + return in + }, + isWrite: false, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + input := tc.pack(t) + + var expected uint64 + if tc.isWrite { + expected = kv.WriteCostFlat + kv.WriteCostPerByte*uint64(len(input)) + } else { + expected = kv.ReadCostFlat + kv.ReadCostPerByte*uint64(len(input)) + } + + gas := p.RequiredGas(input) + require.Equal(t, expected, gas, "RequiredGas must match the SDK KV-cost formula") + require.Greater(t, gas, uint64(0), "RequiredGas must be non-zero (zero-gas DoS regression)") + }) + } + + t.Run("short input returns 0 without panic", func(t *testing.T) { + require.Equal(t, uint64(0), p.RequiredGas(nil)) + require.Equal(t, uint64(0), p.RequiredGas([]byte{0x01, 0x02, 0x03})) + }) + + t.Run("unknown method ID returns 0", func(t *testing.T) { + require.Equal(t, uint64(0), p.RequiredGas([]byte{0xde, 0xad, 0xbe, 0xef})) + }) +} diff --git a/precompiles/ics02/query.go b/precompiles/ics02/query.go new file mode 100644 index 00000000..5f69a249 --- /dev/null +++ b/precompiles/ics02/query.go @@ -0,0 +1,45 @@ +package ics02 + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/core/vm" + + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const ( + // GetClientStateMethod defines the get client state query method name. + GetClientStateMethod = "getClientState" +) + +// GetClientState returns the client state for the precompile's client ID. +func (p *Precompile) GetClientState( + ctx sdk.Context, + _ *vm.Contract, + _ vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + clientID, err := ParseGetClientStateArgs(args) + if err != nil { + return nil, err + } + + clientState, found := p.clientKeeper.GetClientState(ctx, clientID) + if !found { + return nil, fmt.Errorf("client state not found for client ID %s", clientID) + } + + clientStateAny, err := codectypes.NewAnyWithValue(clientState) + if err != nil { + return nil, err + } + if len(clientStateAny.Value) == 0 { + return nil, fmt.Errorf("client state not found for client ID %s", clientID) + } + + return method.Outputs.Pack(clientStateAny.Value) +} diff --git a/precompiles/ics02/tx.go b/precompiles/ics02/tx.go new file mode 100644 index 00000000..434af12e --- /dev/null +++ b/precompiles/ics02/tx.go @@ -0,0 +1,152 @@ +package ics02 + +import ( + "fmt" + "math" + "math/big" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/core/vm" + + clienttypes "github.com/cosmos/ibc-go/v11/modules/core/02-client/types" + commitmenttypesv2 "github.com/cosmos/ibc-go/v11/modules/core/23-commitment/types/v2" + host "github.com/cosmos/ibc-go/v11/modules/core/24-host" + ibcexported "github.com/cosmos/ibc-go/v11/modules/core/exported" + + errorsmod "cosmossdk.io/errors" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const ( + UpdateClientMethod = "updateClient" + VerifyMembershipMethod = "verifyMembership" + VerifyNonMembershipMethod = "verifyNonMembership" +) + +const ( + UpdateResultSuccess uint8 = 0 + UpdateResultMisbehaviour uint8 = 1 +) + +// UpdateClient implements the ICS02 UpdateClient transactions. +func (p *Precompile) UpdateClient( + ctx sdk.Context, + _ *vm.Contract, + _ vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + clientID, updateBz, err := ParseUpdateClientArgs(args) + if err != nil { + return nil, err + } + + if host.ClientIdentifierValidator(clientID) != nil { + return nil, errorsmod.Wrapf( + clienttypes.ErrInvalidClient, + "invalid client ID: %s", + clientID, + ) + } + + clientMsg, err := clienttypes.UnmarshalClientMessage(p.cdc, updateBz) + if err != nil { + return nil, err + } + + if err := clientMsg.ValidateBasic(); err != nil { + return nil, err + } + + if err := p.clientKeeper.UpdateClient(ctx, clientID, clientMsg); err != nil { + return nil, err + } + + if p.clientKeeper.GetClientStatus(ctx, clientID) == ibcexported.Frozen { + return method.Outputs.Pack(UpdateResultMisbehaviour) + } + + return method.Outputs.Pack(UpdateResultSuccess) +} + +// VerifyMembership implements the ICS02 VerifyMembership transactions. +func (p *Precompile) VerifyMembership( + ctx sdk.Context, + _ *vm.Contract, + _ vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + clientID, proof, proofHeight, pathBz, value, err := ParseVerifyMembershipArgs(method, args) + if err != nil { + return nil, err + } + + if host.ClientIdentifierValidator(clientID) != nil { + return nil, errorsmod.Wrapf( + clienttypes.ErrInvalidClient, + "invalid client ID: %s", + clientID, + ) + } + + path := commitmenttypesv2.NewMerklePath(pathBz...) + + if err := p.clientKeeper.VerifyMembership(ctx, clientID, proofHeight, 0, 0, proof, path, value); err != nil { + return nil, err + } + + timestampNano, err := p.clientKeeper.GetClientTimestampAtHeight(ctx, clientID, proofHeight) + if err != nil { + return nil, err + } + // Convert nanoseconds to seconds without overflow. + if timestampNano > math.MaxInt64 { + return nil, fmt.Errorf("timestamp in nanoseconds exceeds int64 max value") + } + timestampSeconds := time.Unix(0, int64(timestampNano)).Unix() + + return method.Outputs.Pack(big.NewInt(timestampSeconds)) +} + +// VerifyNonMembership implements the ICS02 VerifyNonMembership transactions. +func (p *Precompile) VerifyNonMembership( + ctx sdk.Context, + _ *vm.Contract, + _ vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + clientID, proof, proofHeight, pathBz, err := ParseVerifyNonMembershipArgs(method, args) + if err != nil { + return nil, err + } + + if host.ClientIdentifierValidator(clientID) != nil { + return nil, errorsmod.Wrapf( + clienttypes.ErrInvalidClient, + "invalid client ID: %s", + clientID, + ) + } + + path := commitmenttypesv2.NewMerklePath(pathBz...) + + if err := p.clientKeeper.VerifyNonMembership(ctx, clientID, proofHeight, 0, 0, proof, path); err != nil { + return nil, err + } + + timestampNano, err := p.clientKeeper.GetClientTimestampAtHeight(ctx, clientID, proofHeight) + if err != nil { + return nil, err + } + // Convert nanoseconds to seconds without overflow. + if timestampNano > math.MaxInt64 { + return nil, fmt.Errorf("timestamp in nanoseconds exceeds int64 max value") + } + timestampSeconds := time.Unix(0, int64(timestampNano)).Unix() + + return method.Outputs.Pack(big.NewInt(timestampSeconds)) +} diff --git a/precompiles/ics02/types.go b/precompiles/ics02/types.go new file mode 100644 index 00000000..4f22bee0 --- /dev/null +++ b/precompiles/ics02/types.go @@ -0,0 +1,112 @@ +package ics02 + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/accounts/abi" + + cmn "github.com/cosmos/evm/precompiles/common" + clienttypes "github.com/cosmos/ibc-go/v11/modules/core/02-client/types" +) + +// height is a struct used to parse the ProofHeight parameter used as input +// in the VerifyMembership and VerifyNonMembership methods. +type height struct { + ProofHeight clienttypes.Height +} + +// ParseGetClientStateArgs parses the arguments for the GetClientState method. +func ParseGetClientStateArgs(args []interface{}) (string, error) { + if len(args) != 1 { + return "", fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 1, len(args)) + } + + clientID, ok := args[0].(string) + if !ok { + return "", fmt.Errorf("invalid client id: %v", args[0]) + } + + return clientID, nil +} + +// ParseUpdateClientArgs parses the arguments for the UpdateClient method. +func ParseUpdateClientArgs(args []interface{}) (string, []byte, error) { + if len(args) != 2 { + return "", nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 2, len(args)) + } + + clientID, ok := args[0].(string) + if !ok { + return "", nil, fmt.Errorf("invalid client id: %v", args[0]) + } + updateBytes, ok := args[1].([]byte) + if !ok { + return "", nil, fmt.Errorf("invalid update client bytes: %v", args[1]) + } + + return clientID, updateBytes, nil +} + +// ParseVerifyMembershipArgs parses the arguments for the VerifyMembership method. +func ParseVerifyMembershipArgs(method *abi.Method, args []interface{}) (string, []byte, clienttypes.Height, [][]byte, []byte, error) { + if len(args) != 5 { + return "", nil, clienttypes.Height{}, nil, nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 5, len(args)) + } + + clientID, ok := args[0].(string) + if !ok { + return "", nil, clienttypes.Height{}, nil, nil, fmt.Errorf("invalid client id: %v", args[0]) + } + proof, ok := args[1].([]byte) + if !ok { + return "", nil, clienttypes.Height{}, nil, nil, fmt.Errorf("invalid proof bytes: %v", args[1]) + } + + var proofHeight height + heightArg := abi.Arguments{method.Inputs[2]} + if err := heightArg.Copy(&proofHeight, []interface{}{args[2]}); err != nil { + return "", nil, clienttypes.Height{}, nil, nil, fmt.Errorf("error while unpacking args to TransferInput struct: %s", err) + } + + path, ok := args[3].([][]byte) + if !ok { + return "", nil, clienttypes.Height{}, nil, nil, fmt.Errorf("invalid path: %v", args[3]) + } + + value, ok := args[4].([]byte) + if !ok { + return "", nil, clienttypes.Height{}, nil, nil, fmt.Errorf("invalid value: %v", args[4]) + } + + return clientID, proof, proofHeight.ProofHeight, path, value, nil +} + +// ParseVerifyNonMembershipArgs parses the arguments for the VerifyNonMembership method. +func ParseVerifyNonMembershipArgs(method *abi.Method, args []interface{}) (string, []byte, clienttypes.Height, [][]byte, error) { + if len(args) != 4 { + return "", nil, clienttypes.Height{}, nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 4, len(args)) + } + + clientID, ok := args[0].(string) + if !ok { + return "", nil, clienttypes.Height{}, nil, fmt.Errorf("invalid client id: %v", args[0]) + } + proof, ok := args[1].([]byte) + if !ok { + return "", nil, clienttypes.Height{}, nil, fmt.Errorf("invalid proof bytes: %v", args[1]) + } + + var proofHeight height + heightArg := abi.Arguments{method.Inputs[2]} + if err := heightArg.Copy(&proofHeight, []interface{}{args[2]}); err != nil { + return "", nil, clienttypes.Height{}, nil, fmt.Errorf("error while unpacking args to TransferInput struct: %s", err) + } + + // TODO: make sure path is deserilized like this + path, ok := args[3].([][]byte) + if !ok { + return "", nil, clienttypes.Height{}, nil, fmt.Errorf("invalid path: %v", args[3]) + } + + return clientID, proof, proofHeight.ProofHeight, path, nil +} diff --git a/precompiles/ics20/abi.json b/precompiles/ics20/abi.json index 4c92963b..1fc44348 100644 --- a/precompiles/ics20/abi.json +++ b/precompiles/ics20/abi.json @@ -1,280 +1,271 @@ -{ - "_format": "hh-sol-artifact-1", - "contractName": "ICS20I", - "sourceName": "solidity/precompiles/ics20/ICS20I.sol", - "abi": [ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": true, - "internalType": "string", - "name": "receiver", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "sourcePort", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "sourceChannel", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "denom", - "type": "string" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "string", - "name": "memo", - "type": "string" - } - ], - "name": "IBCTransfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "hash", - "type": "string" - } - ], - "name": "denom", - "outputs": [ - { - "components": [ - { - "internalType": "string", - "name": "base", - "type": "string" - }, - { - "components": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "string", - "name": "channelId", - "type": "string" - } - ], - "internalType": "struct Hop[]", - "name": "trace", - "type": "tuple[]" - } - ], - "internalType": "struct Denom", - "name": "denom", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "trace", - "type": "string" - } - ], - "name": "denomHash", - "outputs": [ - { - "internalType": "string", - "name": "hash", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes", - "name": "key", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offset", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "limit", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "countTotal", - "type": "bool" - }, - { - "internalType": "bool", - "name": "reverse", - "type": "bool" - } - ], - "internalType": "struct PageRequest", - "name": "pageRequest", - "type": "tuple" - } - ], - "name": "denoms", - "outputs": [ - { - "components": [ - { - "internalType": "string", - "name": "base", - "type": "string" - }, - { - "components": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "string", - "name": "channelId", - "type": "string" - } - ], - "internalType": "struct Hop[]", - "name": "trace", - "type": "tuple[]" - } - ], - "internalType": "struct Denom[]", - "name": "denoms", - "type": "tuple[]" - }, - { - "components": [ - { - "internalType": "bytes", - "name": "nextKey", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "total", - "type": "uint64" - } - ], - "internalType": "struct PageResponse", - "name": "pageResponse", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "sourcePort", - "type": "string" - }, - { - "internalType": "string", - "name": "sourceChannel", - "type": "string" - }, - { - "internalType": "string", - "name": "denom", - "type": "string" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "string", - "name": "receiver", - "type": "string" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "revisionNumber", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "revisionHeight", - "type": "uint64" - } - ], - "internalType": "struct Height", - "name": "timeoutHeight", - "type": "tuple" - }, - { - "internalType": "uint64", - "name": "timeoutTimestamp", - "type": "uint64" - }, - { - "internalType": "string", - "name": "memo", - "type": "string" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "uint64", - "name": "nextSequence", - "type": "uint64" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "bytecode": "0x", - "deployedBytecode": "0x", - "linkReferences": {}, - "deployedLinkReferences": {} -} +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "string", + "name": "receiver", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "sourcePort", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "sourceChannel", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "memo", + "type": "string" + } + ], + "name": "IBCTransfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "hash", + "type": "string" + } + ], + "name": "denom", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "base", + "type": "string" + }, + { + "components": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + } + ], + "internalType": "struct Hop[]", + "name": "trace", + "type": "tuple[]" + } + ], + "internalType": "struct Denom", + "name": "denom", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "trace", + "type": "string" + } + ], + "name": "denomHash", + "outputs": [ + { + "internalType": "string", + "name": "hash", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offset", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "limit", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "countTotal", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reverse", + "type": "bool" + } + ], + "internalType": "struct PageRequest", + "name": "pageRequest", + "type": "tuple" + } + ], + "name": "denoms", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "base", + "type": "string" + }, + { + "components": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + } + ], + "internalType": "struct Hop[]", + "name": "trace", + "type": "tuple[]" + } + ], + "internalType": "struct Denom[]", + "name": "denoms", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "nextKey", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "total", + "type": "uint64" + } + ], + "internalType": "struct PageResponse", + "name": "pageResponse", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "sourcePort", + "type": "string" + }, + { + "internalType": "string", + "name": "sourceChannel", + "type": "string" + }, + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "string", + "name": "receiver", + "type": "string" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revisionNumber", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revisionHeight", + "type": "uint64" + } + ], + "internalType": "struct Height", + "name": "timeoutHeight", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "timeoutTimestamp", + "type": "uint64" + }, + { + "internalType": "string", + "name": "memo", + "type": "string" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "uint64", + "name": "nextSequence", + "type": "uint64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/precompiles/ics20/ics20.go b/precompiles/ics20/ics20.go index b184fd67..4f1a8e6c 100644 --- a/precompiles/ics20/ics20.go +++ b/precompiles/ics20/ics20.go @@ -1,37 +1,35 @@ package ics20 import ( - "embed" + "bytes" "fmt" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" + _ "embed" + cmn "github.com/cosmos/evm/precompiles/common" evmtypes "github.com/cosmos/evm/x/vm/types" - storetypes "cosmossdk.io/store/types" - + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" ) -// PrecompileAddress of the ICS-20 EVM extension in hex format. -const PrecompileAddress = "0x0000000000000000000000000000000000000802" - var _ vm.PrecompiledContract = &Precompile{} var ( // Embed abi json file to the executable binary. Needed when importing as dependency. // //go:embed abi.json - f embed.FS + f []byte ABI abi.ABI ) func init() { var err error - ABI, err = cmn.LoadABI(f, "abi.json") + ABI, err = abi.JSON(bytes.NewReader(f)) if err != nil { panic(err) } @@ -45,6 +43,7 @@ type Precompile struct { stakingKeeper cmn.StakingKeeper transferKeeper cmn.TransferKeeper channelKeeper cmn.ChannelKeeper + erc20Keeper cmn.ERC20Keeper } // NewPrecompile creates a new ICS-20 Precompile instance as a @@ -54,6 +53,7 @@ func NewPrecompile( stakingKeeper cmn.StakingKeeper, transferKeeper cmn.TransferKeeper, channelKeeper cmn.ChannelKeeper, + erc20Keeper cmn.ERC20Keeper, ) *Precompile { return &Precompile{ Precompile: cmn.Precompile{ @@ -67,9 +67,14 @@ func NewPrecompile( transferKeeper: transferKeeper, channelKeeper: channelKeeper, stakingKeeper: stakingKeeper, + erc20Keeper: erc20Keeper, } } +func (Precompile) Name() string { + return "ics20" +} + // RequiredGas calculates the precompiled contract's base gas rate. func (p Precompile) RequiredGas(input []byte) uint64 { // NOTE: This check avoid panicking when trying to decode the method ID diff --git a/precompiles/ics20/query.go b/precompiles/ics20/query.go index 819553b1..58b28bbc 100644 --- a/precompiles/ics20/query.go +++ b/precompiles/ics20/query.go @@ -6,7 +6,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/core/vm" - transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" + transfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" sdk "github.com/cosmos/cosmos-sdk/types" ) diff --git a/precompiles/ics20/tx.go b/precompiles/ics20/tx.go index 6cea580c..e1779d98 100644 --- a/precompiles/ics20/tx.go +++ b/precompiles/ics20/tx.go @@ -2,18 +2,25 @@ package ics20 import ( "fmt" + "strings" "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" + "github.com/hashicorp/go-metrics" cmn "github.com/cosmos/evm/precompiles/common" - transfertypes "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" - host "github.com/cosmos/ibc-go/v10/modules/core/24-host" + erc20types "github.com/cosmos/evm/x/erc20/types" + callbackstypes "github.com/cosmos/evm/x/ibc/callbacks/types" + "github.com/cosmos/evm/x/vm/statedb" + transfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + connectiontypes "github.com/cosmos/ibc-go/v11/modules/core/03-connection/types" + channeltypes "github.com/cosmos/ibc-go/v11/modules/core/04-channel/types" + host "github.com/cosmos/ibc-go/v11/modules/core/24-host" errorsmod "cosmossdk.io/errors" + "github.com/cosmos/cosmos-sdk/telemetry" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -87,6 +94,78 @@ func (p *Precompile) validateV1TransferChannel(ctx sdk.Context, msg *transfertyp return nil } +// transferWithStateDB handles IBC transfers with ERC20 token conversion support. +// If user doesn't have enough balance of coin, it will attempt to convert +// ERC20 tokens to the coin denomination, and continue with a regular transfer. +func (p *Precompile) transferWithStateDB(ctx sdk.Context, stateDB *statedb.StateDB, msg *transfertypes.MsgTransfer) (*transfertypes.MsgTransferResponse, error) { + // use native denom or contract address + denom := strings.TrimPrefix(msg.Token.Denom, erc20types.Erc20NativeCoinDenomPrefix) + + pairID := p.erc20Keeper.GetTokenPairID(ctx, denom) + if len(pairID) == 0 { + // no-op: token is not registered so we can proceed with regular transfer + return p.transferKeeper.Transfer(ctx, msg) + } + + pair, _ := p.erc20Keeper.GetTokenPair(ctx, pairID) + if !pair.Enabled { + // no-op: pair is not enabled so we can proceed with regular transfer + return p.transferKeeper.Transfer(ctx, msg) + } + + sender := sdk.MustAccAddressFromBech32(msg.Sender) + + if !p.erc20Keeper.IsERC20Enabled(ctx) { + // no-op: continue with regular transfer + return p.transferKeeper.Transfer(ctx, msg) + } + + // update the msg denom to the token pair denom + msg.Token.Denom = pair.Denom + + if !pair.IsNativeERC20() { + return p.transferKeeper.Transfer(ctx, msg) + } + // if the user has enough balance of the Cosmos representation, then we don't need to Convert + balance := p.bankKeeper.SpendableCoin(ctx, sender, pair.Denom) + if balance.Amount.GTE(msg.Token.Amount) { + + defer func() { + telemetry.IncrCounterWithLabels( + []string{"erc20", "ibc", "transfer", "total"}, + 1, + []metrics.Label{ + telemetry.NewLabel("denom", pair.Denom), + }, + ) + }() + + return p.transferKeeper.Transfer(ctx, msg) + } + + // Only convert if the pair is a native ERC20 + // only convert the remaining difference + difference := msg.Token.Amount.Sub(balance.Amount) + + // Convert the ERC20 tokens to Cosmos IBC Coin + erc20Sender := common.BytesToAddress(sender.Bytes()) + if _, err := p.erc20Keeper.ConvertERC20IntoCoinsForNativeToken(ctx, stateDB, pair.GetERC20Contract(), difference, sender, erc20Sender, true, true); err != nil { + return nil, err + } + + defer func() { + telemetry.IncrCounterWithLabels( + []string{"erc20", "ibc", "transfer", "total"}, + 1, + []metrics.Label{ + telemetry.NewLabel("denom", pair.Denom), + }, + ) + }() + + return p.transferKeeper.Transfer(ctx, msg) +} + // Transfer implements the ICS20 transfer transactions. func (p *Precompile) Transfer( ctx sdk.Context, @@ -95,6 +174,11 @@ func (p *Precompile) Transfer( method *abi.Method, args []interface{}, ) ([]byte, error) { + // Marker is set in the callbacks keeper and propagates here via cacheCtx. + if callbackstypes.IsSourceCallbackExecution(ctx) { + return nil, callbackstypes.ErrNestedSourceCallbackTransfer + } + msg, sender, err := NewMsgTransfer(method, args) if err != nil { return nil, err @@ -119,7 +203,8 @@ func (p *Precompile) Transfer( return nil, fmt.Errorf(cmn.ErrRequesterIsNotMsgSender, msgSender.String(), sender.String()) } - res, err := p.transferKeeper.Transfer(ctx, msg) + stateDBExp := stateDB.(*statedb.StateDB) + res, err := p.transferWithStateDB(ctx, stateDBExp, msg) if err != nil { return nil, err } diff --git a/precompiles/ics20/tx_callback_guard_test.go b/precompiles/ics20/tx_callback_guard_test.go new file mode 100644 index 00000000..8867dff0 --- /dev/null +++ b/precompiles/ics20/tx_callback_guard_test.go @@ -0,0 +1,24 @@ +package ics20 + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/require" + + callbackstypes "github.com/cosmos/evm/x/ibc/callbacks/types" + + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" + sdktestutil "github.com/cosmos/cosmos-sdk/testutil" +) + +func TestTransfer_BlockedDuringSourceCallbackExecution(t *testing.T) { + storeKey := storetypes.NewKVStoreKey("test") + tKey := storetypes.NewTransientStoreKey("test_t") + ctx := sdktestutil.DefaultContext(storeKey, tKey) + ctx = callbackstypes.WithSourceCallbackExecution(ctx) + p := &Precompile{} + _, err := p.Transfer(ctx, nil, nil, nil, nil) + require.Error(t, err) + require.True(t, errors.Is(err, callbackstypes.ErrNestedSourceCallbackTransfer)) +} diff --git a/precompiles/ics20/types.go b/precompiles/ics20/types.go index 56b45331..e9bd9458 100644 --- a/precompiles/ics20/types.go +++ b/precompiles/ics20/types.go @@ -10,8 +10,8 @@ import ( "github.com/ethereum/go-ethereum/core/vm" cmn "github.com/cosmos/evm/precompiles/common" - transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" + transfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/v11/modules/core/02-client/types" errorsmod "cosmossdk.io/errors" "cosmossdk.io/math" @@ -239,5 +239,5 @@ func safeCopyInputs(method *abi.Method, args []interface{}, pageRequest *PageReq } }() err = method.Inputs.Copy(pageRequest, args) - return + return err } diff --git a/precompiles/p256/p256.go b/precompiles/p256/p256.go index 248962c8..5f4519cd 100644 --- a/precompiles/p256/p256.go +++ b/precompiles/p256/p256.go @@ -40,6 +40,10 @@ const ( // See https://github.com/ethereum/RIPs/blob/master/RIPS/rip-7212.md for details. type Precompile struct{} +func (Precompile) Name() string { + return "p256" +} + // Address defines the address of the p256 precompiled contract. func (Precompile) Address() common.Address { return common.HexToAddress(evmtypes.P256PrecompileAddress) diff --git a/precompiles/slashing/abi.json b/precompiles/slashing/abi.json index c842bbd9..04186657 100644 --- a/precompiles/slashing/abi.json +++ b/precompiles/slashing/abi.json @@ -1,265 +1,256 @@ -{ - "_format": "hh-sol-artifact-1", - "contractName": "ISlashing", - "sourceName": "solidity/precompiles/slashing/ISlashing.sol", - "abi": [ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "ValidatorUnjailed", - "type": "event" - }, - { - "inputs": [], - "name": "getParams", - "outputs": [ - { - "components": [ - { - "internalType": "int64", - "name": "signedBlocksWindow", - "type": "int64" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "precision", - "type": "uint8" - } - ], - "internalType": "struct Dec", - "name": "minSignedPerWindow", - "type": "tuple" - }, - { - "internalType": "int64", - "name": "downtimeJailDuration", - "type": "int64" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "precision", - "type": "uint8" - } - ], - "internalType": "struct Dec", - "name": "slashFractionDoubleSign", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "precision", - "type": "uint8" - } - ], - "internalType": "struct Dec", - "name": "slashFractionDowntime", - "type": "tuple" - } - ], - "internalType": "struct Params", - "name": "params", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "consAddress", - "type": "address" - } - ], - "name": "getSigningInfo", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "validatorAddress", - "type": "address" - }, - { - "internalType": "int64", - "name": "startHeight", - "type": "int64" - }, - { - "internalType": "int64", - "name": "indexOffset", - "type": "int64" - }, - { - "internalType": "int64", - "name": "jailedUntil", - "type": "int64" - }, - { - "internalType": "bool", - "name": "tombstoned", - "type": "bool" - }, - { - "internalType": "int64", - "name": "missedBlocksCounter", - "type": "int64" - } - ], - "internalType": "struct SigningInfo", - "name": "signingInfo", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes", - "name": "key", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offset", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "limit", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "countTotal", - "type": "bool" - }, - { - "internalType": "bool", - "name": "reverse", - "type": "bool" - } - ], - "internalType": "struct PageRequest", - "name": "pagination", - "type": "tuple" - } - ], - "name": "getSigningInfos", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "validatorAddress", - "type": "address" - }, - { - "internalType": "int64", - "name": "startHeight", - "type": "int64" - }, - { - "internalType": "int64", - "name": "indexOffset", - "type": "int64" - }, - { - "internalType": "int64", - "name": "jailedUntil", - "type": "int64" - }, - { - "internalType": "bool", - "name": "tombstoned", - "type": "bool" - }, - { - "internalType": "int64", - "name": "missedBlocksCounter", - "type": "int64" - } - ], - "internalType": "struct SigningInfo[]", - "name": "signingInfos", - "type": "tuple[]" - }, - { - "components": [ - { - "internalType": "bytes", - "name": "nextKey", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "total", - "type": "uint64" - } - ], - "internalType": "struct PageResponse", - "name": "pageResponse", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "validatorAddress", - "type": "address" - } - ], - "name": "unjail", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "bytecode": "0x", - "deployedBytecode": "0x", - "linkReferences": {}, - "deployedLinkReferences": {} -} +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "ValidatorUnjailed", + "type": "event" + }, + { + "inputs": [], + "name": "getParams", + "outputs": [ + { + "components": [ + { + "internalType": "int64", + "name": "signedBlocksWindow", + "type": "int64" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "precision", + "type": "uint8" + } + ], + "internalType": "struct Dec", + "name": "minSignedPerWindow", + "type": "tuple" + }, + { + "internalType": "int64", + "name": "downtimeJailDuration", + "type": "int64" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "precision", + "type": "uint8" + } + ], + "internalType": "struct Dec", + "name": "slashFractionDoubleSign", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "precision", + "type": "uint8" + } + ], + "internalType": "struct Dec", + "name": "slashFractionDowntime", + "type": "tuple" + } + ], + "internalType": "struct Params", + "name": "params", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "consAddress", + "type": "address" + } + ], + "name": "getSigningInfo", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "validatorAddress", + "type": "address" + }, + { + "internalType": "int64", + "name": "startHeight", + "type": "int64" + }, + { + "internalType": "int64", + "name": "indexOffset", + "type": "int64" + }, + { + "internalType": "int64", + "name": "jailedUntil", + "type": "int64" + }, + { + "internalType": "bool", + "name": "tombstoned", + "type": "bool" + }, + { + "internalType": "int64", + "name": "missedBlocksCounter", + "type": "int64" + } + ], + "internalType": "struct SigningInfo", + "name": "signingInfo", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offset", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "limit", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "countTotal", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reverse", + "type": "bool" + } + ], + "internalType": "struct PageRequest", + "name": "pagination", + "type": "tuple" + } + ], + "name": "getSigningInfos", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "validatorAddress", + "type": "address" + }, + { + "internalType": "int64", + "name": "startHeight", + "type": "int64" + }, + { + "internalType": "int64", + "name": "indexOffset", + "type": "int64" + }, + { + "internalType": "int64", + "name": "jailedUntil", + "type": "int64" + }, + { + "internalType": "bool", + "name": "tombstoned", + "type": "bool" + }, + { + "internalType": "int64", + "name": "missedBlocksCounter", + "type": "int64" + } + ], + "internalType": "struct SigningInfo[]", + "name": "signingInfos", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "nextKey", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "total", + "type": "uint64" + } + ], + "internalType": "struct PageResponse", + "name": "pageResponse", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validatorAddress", + "type": "address" + } + ], + "name": "unjail", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/precompiles/slashing/slashing.go b/precompiles/slashing/slashing.go index bc99e984..6db30558 100644 --- a/precompiles/slashing/slashing.go +++ b/precompiles/slashing/slashing.go @@ -1,21 +1,23 @@ package slashing import ( - "embed" + "bytes" "fmt" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" + _ "embed" + cmn "github.com/cosmos/evm/precompiles/common" evmtypes "github.com/cosmos/evm/x/vm/types" "cosmossdk.io/core/address" - "cosmossdk.io/log" - storetypes "cosmossdk.io/store/types" + "cosmossdk.io/log/v2" "github.com/cosmos/cosmos-sdk/runtime" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" ) @@ -26,13 +28,13 @@ var ( // Embed abi json file to the executable binary. Needed when importing as dependency. // //go:embed abi.json - f embed.FS + f []byte ABI abi.ABI ) func init() { var err error - ABI, err = cmn.LoadABI(f, "abi.json") + ABI, err = abi.JSON(bytes.NewReader(f)) if err != nil { panic(err) } @@ -72,6 +74,10 @@ func NewPrecompile( } } +func (Precompile) Name() string { + return "slashing" +} + // RequiredGas calculates the precompiled contract's base gas rate. func (p Precompile) RequiredGas(input []byte) uint64 { // NOTE: This check avoid panicking when trying to decode the method ID diff --git a/precompiles/staking/abi.json b/precompiles/staking/abi.json index 6e498ed0..7871943d 100644 --- a/precompiles/staking/abi.json +++ b/precompiles/staking/abi.json @@ -1,1070 +1,1061 @@ -{ - "_format": "hh-sol-artifact-1", - "contractName": "StakingI", - "sourceName": "solidity/precompiles/staking/StakingI.sol", - "abi": [ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "delegatorAddress", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "validatorAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "creationHeight", - "type": "uint256" - } - ], - "name": "CancelUnbondingDelegation", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "validatorAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "CreateValidator", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "delegatorAddress", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "validatorAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newShares", - "type": "uint256" - } - ], - "name": "Delegate", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "validatorAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "int256", - "name": "commissionRate", - "type": "int256" - }, - { - "indexed": false, - "internalType": "int256", - "name": "minSelfDelegation", - "type": "int256" - } - ], - "name": "EditValidator", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "delegatorAddress", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "validatorSrcAddress", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "validatorDstAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "completionTime", - "type": "uint256" - } - ], - "name": "Redelegate", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "delegatorAddress", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "validatorAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "completionTime", - "type": "uint256" - } - ], - "name": "Unbond", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "delegatorAddress", - "type": "address" - }, - { - "internalType": "string", - "name": "validatorAddress", - "type": "string" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "creationHeight", - "type": "uint256" - } - ], - "name": "cancelUnbondingDelegation", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "string", - "name": "moniker", - "type": "string" - }, - { - "internalType": "string", - "name": "identity", - "type": "string" - }, - { - "internalType": "string", - "name": "website", - "type": "string" - }, - { - "internalType": "string", - "name": "securityContact", - "type": "string" - }, - { - "internalType": "string", - "name": "details", - "type": "string" - } - ], - "internalType": "struct Description", - "name": "description", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "rate", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxRate", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxChangeRate", - "type": "uint256" - } - ], - "internalType": "struct CommissionRates", - "name": "commissionRates", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "minSelfDelegation", - "type": "uint256" - }, - { - "internalType": "address", - "name": "validatorAddress", - "type": "address" - }, - { - "internalType": "string", - "name": "pubkey", - "type": "string" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "createValidator", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "delegatorAddress", - "type": "address" - }, - { - "internalType": "string", - "name": "validatorAddress", - "type": "string" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "delegate", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "delegatorAddress", - "type": "address" - }, - { - "internalType": "string", - "name": "validatorAddress", - "type": "string" - } - ], - "name": "delegation", - "outputs": [ - { - "internalType": "uint256", - "name": "shares", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "string", - "name": "denom", - "type": "string" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct Coin", - "name": "balance", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "string", - "name": "moniker", - "type": "string" - }, - { - "internalType": "string", - "name": "identity", - "type": "string" - }, - { - "internalType": "string", - "name": "website", - "type": "string" - }, - { - "internalType": "string", - "name": "securityContact", - "type": "string" - }, - { - "internalType": "string", - "name": "details", - "type": "string" - } - ], - "internalType": "struct Description", - "name": "description", - "type": "tuple" - }, - { - "internalType": "address", - "name": "validatorAddress", - "type": "address" - }, - { - "internalType": "int256", - "name": "commissionRate", - "type": "int256" - }, - { - "internalType": "int256", - "name": "minSelfDelegation", - "type": "int256" - } - ], - "name": "editValidator", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "delegatorAddress", - "type": "address" - }, - { - "internalType": "string", - "name": "validatorSrcAddress", - "type": "string" - }, - { - "internalType": "string", - "name": "validatorDstAddress", - "type": "string" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "redelegate", - "outputs": [ - { - "internalType": "int64", - "name": "completionTime", - "type": "int64" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "delegatorAddress", - "type": "address" - }, - { - "internalType": "string", - "name": "srcValidatorAddress", - "type": "string" - }, - { - "internalType": "string", - "name": "dstValidatorAddress", - "type": "string" - } - ], - "name": "redelegation", - "outputs": [ - { - "components": [ - { - "internalType": "string", - "name": "delegatorAddress", - "type": "string" - }, - { - "internalType": "string", - "name": "validatorSrcAddress", - "type": "string" - }, - { - "internalType": "string", - "name": "validatorDstAddress", - "type": "string" - }, - { - "components": [ - { - "internalType": "int64", - "name": "creationHeight", - "type": "int64" - }, - { - "internalType": "int64", - "name": "completionTime", - "type": "int64" - }, - { - "internalType": "uint256", - "name": "initialBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "sharesDst", - "type": "uint256" - } - ], - "internalType": "struct RedelegationEntry[]", - "name": "entries", - "type": "tuple[]" - } - ], - "internalType": "struct RedelegationOutput", - "name": "redelegation", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "delegatorAddress", - "type": "address" - }, - { - "internalType": "string", - "name": "srcValidatorAddress", - "type": "string" - }, - { - "internalType": "string", - "name": "dstValidatorAddress", - "type": "string" - }, - { - "components": [ - { - "internalType": "bytes", - "name": "key", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offset", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "limit", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "countTotal", - "type": "bool" - }, - { - "internalType": "bool", - "name": "reverse", - "type": "bool" - } - ], - "internalType": "struct PageRequest", - "name": "pageRequest", - "type": "tuple" - } - ], - "name": "redelegations", - "outputs": [ - { - "components": [ - { - "components": [ - { - "internalType": "string", - "name": "delegatorAddress", - "type": "string" - }, - { - "internalType": "string", - "name": "validatorSrcAddress", - "type": "string" - }, - { - "internalType": "string", - "name": "validatorDstAddress", - "type": "string" - }, - { - "components": [ - { - "internalType": "int64", - "name": "creationHeight", - "type": "int64" - }, - { - "internalType": "int64", - "name": "completionTime", - "type": "int64" - }, - { - "internalType": "uint256", - "name": "initialBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "sharesDst", - "type": "uint256" - } - ], - "internalType": "struct RedelegationEntry[]", - "name": "entries", - "type": "tuple[]" - } - ], - "internalType": "struct Redelegation", - "name": "redelegation", - "type": "tuple" - }, - { - "components": [ - { - "components": [ - { - "internalType": "int64", - "name": "creationHeight", - "type": "int64" - }, - { - "internalType": "int64", - "name": "completionTime", - "type": "int64" - }, - { - "internalType": "uint256", - "name": "initialBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "sharesDst", - "type": "uint256" - } - ], - "internalType": "struct RedelegationEntry", - "name": "redelegationEntry", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "balance", - "type": "uint256" - } - ], - "internalType": "struct RedelegationEntryResponse[]", - "name": "entries", - "type": "tuple[]" - } - ], - "internalType": "struct RedelegationResponse[]", - "name": "response", - "type": "tuple[]" - }, - { - "components": [ - { - "internalType": "bytes", - "name": "nextKey", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "total", - "type": "uint64" - } - ], - "internalType": "struct PageResponse", - "name": "pageResponse", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "delegatorAddress", - "type": "address" - }, - { - "internalType": "string", - "name": "validatorAddress", - "type": "string" - } - ], - "name": "unbondingDelegation", - "outputs": [ - { - "components": [ - { - "internalType": "string", - "name": "delegatorAddress", - "type": "string" - }, - { - "internalType": "string", - "name": "validatorAddress", - "type": "string" - }, - { - "components": [ - { - "internalType": "int64", - "name": "creationHeight", - "type": "int64" - }, - { - "internalType": "int64", - "name": "completionTime", - "type": "int64" - }, - { - "internalType": "uint256", - "name": "initialBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "balance", - "type": "uint256" - }, - { - "internalType": "uint64", - "name": "unbondingId", - "type": "uint64" - }, - { - "internalType": "int64", - "name": "unbondingOnHoldRefCount", - "type": "int64" - } - ], - "internalType": "struct UnbondingDelegationEntry[]", - "name": "entries", - "type": "tuple[]" - } - ], - "internalType": "struct UnbondingDelegationOutput", - "name": "unbondingDelegation", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "delegatorAddress", - "type": "address" - }, - { - "internalType": "string", - "name": "validatorAddress", - "type": "string" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "undelegate", - "outputs": [ - { - "internalType": "int64", - "name": "completionTime", - "type": "int64" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "validatorAddress", - "type": "address" - } - ], - "name": "validator", - "outputs": [ - { - "components": [ - { - "internalType": "string", - "name": "operatorAddress", - "type": "string" - }, - { - "internalType": "string", - "name": "consensusPubkey", - "type": "string" - }, - { - "internalType": "bool", - "name": "jailed", - "type": "bool" - }, - { - "internalType": "enum BondStatus", - "name": "status", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "tokens", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "delegatorShares", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "string", - "name": "moniker", - "type": "string" - }, - { - "internalType": "string", - "name": "identity", - "type": "string" - }, - { - "internalType": "string", - "name": "website", - "type": "string" - }, - { - "internalType": "string", - "name": "securityContact", - "type": "string" - }, - { - "internalType": "string", - "name": "details", - "type": "string" - } - ], - "internalType": "struct Description", - "name": "description", - "type": "tuple" - }, - { - "internalType": "int64", - "name": "unbondingHeight", - "type": "int64" - }, - { - "internalType": "int64", - "name": "unbondingTime", - "type": "int64" - }, - { - "internalType": "uint256", - "name": "commission", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "minSelfDelegation", - "type": "uint256" - } - ], - "internalType": "struct Validator", - "name": "validator", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "status", - "type": "string" - }, - { - "components": [ - { - "internalType": "bytes", - "name": "key", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offset", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "limit", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "countTotal", - "type": "bool" - }, - { - "internalType": "bool", - "name": "reverse", - "type": "bool" - } - ], - "internalType": "struct PageRequest", - "name": "pageRequest", - "type": "tuple" - } - ], - "name": "validators", - "outputs": [ - { - "components": [ - { - "internalType": "string", - "name": "operatorAddress", - "type": "string" - }, - { - "internalType": "string", - "name": "consensusPubkey", - "type": "string" - }, - { - "internalType": "bool", - "name": "jailed", - "type": "bool" - }, - { - "internalType": "enum BondStatus", - "name": "status", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "tokens", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "delegatorShares", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "string", - "name": "moniker", - "type": "string" - }, - { - "internalType": "string", - "name": "identity", - "type": "string" - }, - { - "internalType": "string", - "name": "website", - "type": "string" - }, - { - "internalType": "string", - "name": "securityContact", - "type": "string" - }, - { - "internalType": "string", - "name": "details", - "type": "string" - } - ], - "internalType": "struct Description", - "name": "description", - "type": "tuple" - }, - { - "internalType": "int64", - "name": "unbondingHeight", - "type": "int64" - }, - { - "internalType": "int64", - "name": "unbondingTime", - "type": "int64" - }, - { - "internalType": "uint256", - "name": "commission", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "minSelfDelegation", - "type": "uint256" - } - ], - "internalType": "struct Validator[]", - "name": "validators", - "type": "tuple[]" - }, - { - "components": [ - { - "internalType": "bytes", - "name": "nextKey", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "total", - "type": "uint64" - } - ], - "internalType": "struct PageResponse", - "name": "pageResponse", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "bytecode": "0x", - "deployedBytecode": "0x", - "linkReferences": {}, - "deployedLinkReferences": {} -} +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegatorAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "validatorAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "creationHeight", + "type": "uint256" + } + ], + "name": "CancelUnbondingDelegation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validatorAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "CreateValidator", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegatorAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "validatorAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newShares", + "type": "uint256" + } + ], + "name": "Delegate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validatorAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "int256", + "name": "commissionRate", + "type": "int256" + }, + { + "indexed": false, + "internalType": "int256", + "name": "minSelfDelegation", + "type": "int256" + } + ], + "name": "EditValidator", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegatorAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "validatorSrcAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "validatorDstAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "completionTime", + "type": "uint256" + } + ], + "name": "Redelegate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegatorAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "validatorAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "completionTime", + "type": "uint256" + } + ], + "name": "Unbond", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatorAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "validatorAddress", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "creationHeight", + "type": "uint256" + } + ], + "name": "cancelUnbondingDelegation", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "moniker", + "type": "string" + }, + { + "internalType": "string", + "name": "identity", + "type": "string" + }, + { + "internalType": "string", + "name": "website", + "type": "string" + }, + { + "internalType": "string", + "name": "securityContact", + "type": "string" + }, + { + "internalType": "string", + "name": "details", + "type": "string" + } + ], + "internalType": "struct Description", + "name": "description", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "rate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxChangeRate", + "type": "uint256" + } + ], + "internalType": "struct CommissionRates", + "name": "commissionRates", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "minSelfDelegation", + "type": "uint256" + }, + { + "internalType": "address", + "name": "validatorAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "pubkey", + "type": "string" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "createValidator", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatorAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "validatorAddress", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "delegate", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatorAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "validatorAddress", + "type": "string" + } + ], + "name": "delegation", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Coin", + "name": "balance", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "moniker", + "type": "string" + }, + { + "internalType": "string", + "name": "identity", + "type": "string" + }, + { + "internalType": "string", + "name": "website", + "type": "string" + }, + { + "internalType": "string", + "name": "securityContact", + "type": "string" + }, + { + "internalType": "string", + "name": "details", + "type": "string" + } + ], + "internalType": "struct Description", + "name": "description", + "type": "tuple" + }, + { + "internalType": "address", + "name": "validatorAddress", + "type": "address" + }, + { + "internalType": "int256", + "name": "commissionRate", + "type": "int256" + }, + { + "internalType": "int256", + "name": "minSelfDelegation", + "type": "int256" + } + ], + "name": "editValidator", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatorAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "validatorSrcAddress", + "type": "string" + }, + { + "internalType": "string", + "name": "validatorDstAddress", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "redelegate", + "outputs": [ + { + "internalType": "int64", + "name": "completionTime", + "type": "int64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatorAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "srcValidatorAddress", + "type": "string" + }, + { + "internalType": "string", + "name": "dstValidatorAddress", + "type": "string" + } + ], + "name": "redelegation", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "delegatorAddress", + "type": "string" + }, + { + "internalType": "string", + "name": "validatorSrcAddress", + "type": "string" + }, + { + "internalType": "string", + "name": "validatorDstAddress", + "type": "string" + }, + { + "components": [ + { + "internalType": "int64", + "name": "creationHeight", + "type": "int64" + }, + { + "internalType": "int64", + "name": "completionTime", + "type": "int64" + }, + { + "internalType": "uint256", + "name": "initialBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sharesDst", + "type": "uint256" + } + ], + "internalType": "struct RedelegationEntry[]", + "name": "entries", + "type": "tuple[]" + } + ], + "internalType": "struct RedelegationOutput", + "name": "redelegation", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatorAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "srcValidatorAddress", + "type": "string" + }, + { + "internalType": "string", + "name": "dstValidatorAddress", + "type": "string" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offset", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "limit", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "countTotal", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reverse", + "type": "bool" + } + ], + "internalType": "struct PageRequest", + "name": "pageRequest", + "type": "tuple" + } + ], + "name": "redelegations", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "string", + "name": "delegatorAddress", + "type": "string" + }, + { + "internalType": "string", + "name": "validatorSrcAddress", + "type": "string" + }, + { + "internalType": "string", + "name": "validatorDstAddress", + "type": "string" + }, + { + "components": [ + { + "internalType": "int64", + "name": "creationHeight", + "type": "int64" + }, + { + "internalType": "int64", + "name": "completionTime", + "type": "int64" + }, + { + "internalType": "uint256", + "name": "initialBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sharesDst", + "type": "uint256" + } + ], + "internalType": "struct RedelegationEntry[]", + "name": "entries", + "type": "tuple[]" + } + ], + "internalType": "struct Redelegation", + "name": "redelegation", + "type": "tuple" + }, + { + "components": [ + { + "components": [ + { + "internalType": "int64", + "name": "creationHeight", + "type": "int64" + }, + { + "internalType": "int64", + "name": "completionTime", + "type": "int64" + }, + { + "internalType": "uint256", + "name": "initialBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sharesDst", + "type": "uint256" + } + ], + "internalType": "struct RedelegationEntry", + "name": "redelegationEntry", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "internalType": "struct RedelegationEntryResponse[]", + "name": "entries", + "type": "tuple[]" + } + ], + "internalType": "struct RedelegationResponse[]", + "name": "response", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "nextKey", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "total", + "type": "uint64" + } + ], + "internalType": "struct PageResponse", + "name": "pageResponse", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatorAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "validatorAddress", + "type": "string" + } + ], + "name": "unbondingDelegation", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "delegatorAddress", + "type": "string" + }, + { + "internalType": "string", + "name": "validatorAddress", + "type": "string" + }, + { + "components": [ + { + "internalType": "int64", + "name": "creationHeight", + "type": "int64" + }, + { + "internalType": "int64", + "name": "completionTime", + "type": "int64" + }, + { + "internalType": "uint256", + "name": "initialBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "unbondingId", + "type": "uint64" + }, + { + "internalType": "int64", + "name": "unbondingOnHoldRefCount", + "type": "int64" + } + ], + "internalType": "struct UnbondingDelegationEntry[]", + "name": "entries", + "type": "tuple[]" + } + ], + "internalType": "struct UnbondingDelegationOutput", + "name": "unbondingDelegation", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatorAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "validatorAddress", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "undelegate", + "outputs": [ + { + "internalType": "int64", + "name": "completionTime", + "type": "int64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validatorAddress", + "type": "address" + } + ], + "name": "validator", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "operatorAddress", + "type": "string" + }, + { + "internalType": "string", + "name": "consensusPubkey", + "type": "string" + }, + { + "internalType": "bool", + "name": "jailed", + "type": "bool" + }, + { + "internalType": "enum BondStatus", + "name": "status", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "delegatorShares", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "string", + "name": "moniker", + "type": "string" + }, + { + "internalType": "string", + "name": "identity", + "type": "string" + }, + { + "internalType": "string", + "name": "website", + "type": "string" + }, + { + "internalType": "string", + "name": "securityContact", + "type": "string" + }, + { + "internalType": "string", + "name": "details", + "type": "string" + } + ], + "internalType": "struct Description", + "name": "description", + "type": "tuple" + }, + { + "internalType": "int64", + "name": "unbondingHeight", + "type": "int64" + }, + { + "internalType": "int64", + "name": "unbondingTime", + "type": "int64" + }, + { + "internalType": "uint256", + "name": "commission", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minSelfDelegation", + "type": "uint256" + } + ], + "internalType": "struct Validator", + "name": "validator", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "status", + "type": "string" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offset", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "limit", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "countTotal", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reverse", + "type": "bool" + } + ], + "internalType": "struct PageRequest", + "name": "pageRequest", + "type": "tuple" + } + ], + "name": "validators", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "operatorAddress", + "type": "string" + }, + { + "internalType": "string", + "name": "consensusPubkey", + "type": "string" + }, + { + "internalType": "bool", + "name": "jailed", + "type": "bool" + }, + { + "internalType": "enum BondStatus", + "name": "status", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "delegatorShares", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "string", + "name": "moniker", + "type": "string" + }, + { + "internalType": "string", + "name": "identity", + "type": "string" + }, + { + "internalType": "string", + "name": "website", + "type": "string" + }, + { + "internalType": "string", + "name": "securityContact", + "type": "string" + }, + { + "internalType": "string", + "name": "details", + "type": "string" + } + ], + "internalType": "struct Description", + "name": "description", + "type": "tuple" + }, + { + "internalType": "int64", + "name": "unbondingHeight", + "type": "int64" + }, + { + "internalType": "int64", + "name": "unbondingTime", + "type": "int64" + }, + { + "internalType": "uint256", + "name": "commission", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minSelfDelegation", + "type": "uint256" + } + ], + "internalType": "struct Validator[]", + "name": "validators", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "nextKey", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "total", + "type": "uint64" + } + ], + "internalType": "struct PageResponse", + "name": "pageResponse", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/precompiles/staking/staking.go b/precompiles/staking/staking.go index 9dd71a6a..935b7e18 100644 --- a/precompiles/staking/staking.go +++ b/precompiles/staking/staking.go @@ -1,20 +1,22 @@ package staking import ( - "embed" + "bytes" "fmt" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" + _ "embed" + cmn "github.com/cosmos/evm/precompiles/common" evmtypes "github.com/cosmos/evm/x/vm/types" "cosmossdk.io/core/address" - "cosmossdk.io/log" - storetypes "cosmossdk.io/store/types" + "cosmossdk.io/log/v2" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) @@ -25,13 +27,13 @@ var ( // Embed abi json file to the executable binary. Needed when importing as dependency. // //go:embed abi.json - f embed.FS + f []byte ABI abi.ABI ) func init() { var err error - ABI, err = cmn.LoadABI(f, "abi.json") + ABI, err = abi.JSON(bytes.NewReader(f)) if err != nil { panic(err) } @@ -72,6 +74,10 @@ func NewPrecompile( } } +func (Precompile) Name() string { + return "staking" +} + // RequiredGas returns the required bare minimum gas to execute the precompile. func (p Precompile) RequiredGas(input []byte) uint64 { // NOTE: This check avoid panicking when trying to decode the method ID diff --git a/precompiles/staking/types.go b/precompiles/staking/types.go index 7c8baae5..090b94f7 100644 --- a/precompiles/staking/types.go +++ b/precompiles/staking/types.go @@ -544,7 +544,7 @@ type UnbondingDelegationEntry struct { CompletionTime int64 InitialBalance *big.Int Balance *big.Int - UnbondingId uint64 //nolint + UnbondingId uint64 UnbondingOnHoldRefCount int64 } diff --git a/precompiles/testutil/ibc.go b/precompiles/testutil/ibc.go index 476de91f..916c6799 100644 --- a/precompiles/testutil/ibc.go +++ b/precompiles/testutil/ibc.go @@ -1,7 +1,7 @@ package testutil import ( - transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" + transfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" ) var ( diff --git a/precompiles/testutil/testing.go b/precompiles/testutil/testing.go index 21ad3b40..fa7ec293 100644 --- a/precompiles/testutil/testing.go +++ b/precompiles/testutil/testing.go @@ -8,8 +8,7 @@ import ( "github.com/holiman/uint256" "github.com/stretchr/testify/require" - storetypes "cosmossdk.io/store/types" - + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" ) diff --git a/precompiles/testutil/tracking_multi_store.go b/precompiles/testutil/tracking_multi_store.go index 5fc0c9a8..d10cc846 100644 --- a/precompiles/testutil/tracking_multi_store.go +++ b/precompiles/testutil/tracking_multi_store.go @@ -1,13 +1,12 @@ package testutil import ( - "io" "testing" "time" "github.com/stretchr/testify/require" - storetypes "cosmossdk.io/store/types" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" ) // TrackingMultiStore implements the CacheMultiStore interface, but tracks calls to the Write interface as @@ -33,10 +32,6 @@ func (t *TrackingMultiStore) CacheWrap() storetypes.CacheWrap { return t.Store.CacheWrap() } -func (t *TrackingMultiStore) CacheWrapWithTrace(w io.Writer, tc storetypes.TraceContext) storetypes.CacheWrap { - return t.Store.CacheWrapWithTrace(w, tc) -} - func (t *TrackingMultiStore) CacheMultiStoreWithVersion(version int64) (storetypes.CacheMultiStore, error) { return t.Store.CacheMultiStoreWithVersion(version) } @@ -49,16 +44,8 @@ func (t *TrackingMultiStore) GetKVStore(key storetypes.StoreKey) storetypes.KVSt return t.Store.GetKVStore(key) } -func (t *TrackingMultiStore) TracingEnabled() bool { - return t.Store.TracingEnabled() -} - -func (t *TrackingMultiStore) SetTracer(w io.Writer) storetypes.MultiStore { - return t.Store.SetTracer(w) -} - -func (t *TrackingMultiStore) SetTracingContext(context storetypes.TraceContext) storetypes.MultiStore { - return t.Store.SetTracingContext(context) +func (t *TrackingMultiStore) GetObjKVStore(key storetypes.StoreKey) storetypes.ObjKVStore { + return t.Store.GetObjKVStore(key) } func (t *TrackingMultiStore) LatestVersion() int64 { diff --git a/precompiles/types/defaults.go b/precompiles/types/defaults.go index 65b855e3..cd689867 100644 --- a/precompiles/types/defaults.go +++ b/precompiles/types/defaults.go @@ -5,10 +5,11 @@ import ( "github.com/ethereum/go-ethereum/core/vm" evmaddress "github.com/cosmos/evm/encoding/address" + ibcutils "github.com/cosmos/evm/ibc" cmn "github.com/cosmos/evm/precompiles/common" erc20Keeper "github.com/cosmos/evm/x/erc20/keeper" - transferkeeper "github.com/cosmos/evm/x/ibc/transfer/keeper" - channelkeeper "github.com/cosmos/ibc-go/v10/modules/core/04-channel/keeper" + transferkeeper "github.com/cosmos/ibc-go/v11/modules/apps/transfer/keeper" + channelkeeper "github.com/cosmos/ibc-go/v11/modules/core/04-channel/keeper" "cosmossdk.io/core/address" @@ -69,6 +70,7 @@ func DefaultStaticPrecompiles( erc20Keeper *erc20Keeper.Keeper, transferKeeper *transferkeeper.Keeper, channelKeeper *channelkeeper.Keeper, + clientKeeper ibcutils.ClientKeeper, govKeeper govkeeper.Keeper, slashingKeeper slashingkeeper.Keeper, codec codec.Codec, @@ -80,7 +82,8 @@ func DefaultStaticPrecompiles( WithBech32Precompile(). WithStakingPrecompile(stakingKeeper, bankKeeper, opts...). WithDistributionPrecompile(distributionKeeper, stakingKeeper, bankKeeper, opts...). - WithICS20Precompile(bankKeeper, stakingKeeper, transferKeeper, channelKeeper). + WithICS02Precompile(codec, clientKeeper). + WithICS20Precompile(bankKeeper, stakingKeeper, transferKeeper, channelKeeper, erc20Keeper). WithBankPrecompile(bankKeeper, erc20Keeper). WithGovPrecompile(govKeeper, bankKeeper, codec, opts...). WithSlashingPrecompile(slashingKeeper, bankKeeper, opts...) diff --git a/precompiles/types/static_precompiles.go b/precompiles/types/static_precompiles.go index ca49445f..7f19b35c 100644 --- a/precompiles/types/static_precompiles.go +++ b/precompiles/types/static_precompiles.go @@ -7,18 +7,20 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" + ibcutils "github.com/cosmos/evm/ibc" bankprecompile "github.com/cosmos/evm/precompiles/bank" "github.com/cosmos/evm/precompiles/bech32" cmn "github.com/cosmos/evm/precompiles/common" distprecompile "github.com/cosmos/evm/precompiles/distribution" govprecompile "github.com/cosmos/evm/precompiles/gov" + ics02precompile "github.com/cosmos/evm/precompiles/ics02" ics20precompile "github.com/cosmos/evm/precompiles/ics20" "github.com/cosmos/evm/precompiles/p256" slashingprecompile "github.com/cosmos/evm/precompiles/slashing" stakingprecompile "github.com/cosmos/evm/precompiles/staking" erc20Keeper "github.com/cosmos/evm/x/erc20/keeper" - transferkeeper "github.com/cosmos/evm/x/ibc/transfer/keeper" - channelkeeper "github.com/cosmos/ibc-go/v10/modules/core/04-channel/keeper" + transferkeeper "github.com/cosmos/ibc-go/v11/modules/apps/transfer/keeper" + channelkeeper "github.com/cosmos/ibc-go/v11/modules/core/04-channel/keeper" "github.com/cosmos/cosmos-sdk/codec" distributionkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" @@ -99,17 +101,32 @@ func (s StaticPrecompiles) WithDistributionPrecompile( return s } +func (s StaticPrecompiles) WithICS02Precompile( + codec codec.Codec, + clientKeeper ibcutils.ClientKeeper, +) StaticPrecompiles { + ibcClientPrecompile := ics02precompile.NewPrecompile( + codec, + clientKeeper, + ) + + s[ibcClientPrecompile.Address()] = ibcClientPrecompile + return s +} + func (s StaticPrecompiles) WithICS20Precompile( bankKeeper cmn.BankKeeper, stakingKeeper stakingkeeper.Keeper, transferKeeper *transferkeeper.Keeper, channelKeeper *channelkeeper.Keeper, + erc20Keeper *erc20Keeper.Keeper, ) StaticPrecompiles { ibcTransferPrecompile := ics20precompile.NewPrecompile( bankKeeper, stakingKeeper, transferKeeper, channelKeeper, + erc20Keeper, ) s[ibcTransferPrecompile.Address()] = ibcTransferPrecompile diff --git a/precompiles/werc20/abi.json b/precompiles/werc20/abi.json index 3753fd7b..3f97434e 100644 --- a/precompiles/werc20/abi.json +++ b/precompiles/werc20/abi.json @@ -1,299 +1,290 @@ -{ - "_format": "hh-sol-artifact-1", - "contractName": "IWERC20", - "sourceName": "solidity/precompiles/werc20/IWERC20.sol", - "abi": [ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "dst", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "wad", - "type": "uint256" - } - ], - "name": "Deposit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "src", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "wad", - "type": "uint256" - } - ], - "name": "Withdrawal", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "deposit", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "wad", - "type": "uint256" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ], - "bytecode": "0x", - "deployedBytecode": "0x", - "linkReferences": {}, - "deployedLinkReferences": {} -} +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "Withdrawal", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "deposit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/precompiles/werc20/tx.go b/precompiles/werc20/tx.go index 0b69f71d..a4c88504 100644 --- a/precompiles/werc20/tx.go +++ b/precompiles/werc20/tx.go @@ -6,7 +6,6 @@ import ( "github.com/ethereum/go-ethereum/core/vm" - "github.com/cosmos/evm/x/precisebank/types" evmtypes "github.com/cosmos/evm/x/vm/types" "cosmossdk.io/math" @@ -69,7 +68,7 @@ func (p Precompile) Withdraw(ctx sdk.Context, contract *vm.Contract, stateDB vm. caller := contract.Caller() callerAccAddress := sdk.AccAddress(caller.Bytes()) nativeBalance := p.BankKeeper.SpendableCoin(ctx, callerAccAddress, evmtypes.GetEVMCoinDenom()) - if nativeBalance.Amount.Mul(types.ConversionFactor()).LT(amountInt) { + if nativeBalance.Amount.LT(amountInt) { return nil, fmt.Errorf("account balance %v is lower than withdraw balance %v", nativeBalance.Amount, amountInt) } diff --git a/precompiles/werc20/werc20.go b/precompiles/werc20/werc20.go index b9e67623..f7c476f1 100644 --- a/precompiles/werc20/werc20.go +++ b/precompiles/werc20/werc20.go @@ -1,12 +1,14 @@ package werc20 import ( - "embed" + "bytes" "slices" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/core/vm" + _ "embed" + ibcutils "github.com/cosmos/evm/ibc" cmn "github.com/cosmos/evm/precompiles/common" erc20 "github.com/cosmos/evm/precompiles/erc20" @@ -15,20 +17,17 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -// abiPath defines the path to the WERC-20 precompile ABI JSON file. -const abiPath = "abi.json" - var ( // Embed abi json file to the executable binary. Needed when importing as dependency. // //go:embed abi.json - f embed.FS + f []byte ABI abi.ABI ) func init() { var err error - ABI, err = cmn.LoadABI(f, abiPath) + ABI, err = abi.JSON(bytes.NewReader(f)) if err != nil { panic(err) } diff --git a/proto/buf.gen.pulsar.yaml b/proto/buf.gen.pulsar.yaml index 41cfbe2a..fada5e7d 100644 --- a/proto/buf.gen.pulsar.yaml +++ b/proto/buf.gen.pulsar.yaml @@ -15,6 +15,3 @@ plugins: - name: go-grpc out: ../api opt: paths=source_relative - - name: go-cosmos-orm - out: ../api - opt: paths=source_relative diff --git a/proto/cosmos/evm/erc20/v1/erc20.proto b/proto/cosmos/evm/erc20/v1/erc20.proto index d7cd29d2..235fc53b 100644 --- a/proto/cosmos/evm/erc20/v1/erc20.proto +++ b/proto/cosmos/evm/erc20/v1/erc20.proto @@ -17,8 +17,9 @@ enum Owner { OWNER_EXTERNAL = 2; } -// 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. +// 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/query.proto b/proto/cosmos/evm/erc20/v1/query.proto index a23a6832..3358813d 100644 --- a/proto/cosmos/evm/erc20/v1/query.proto +++ b/proto/cosmos/evm/erc20/v1/query.proto @@ -20,7 +20,8 @@ service Query { // 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/precisebank/v1/genesis.proto b/proto/cosmos/evm/precisebank/v1/genesis.proto deleted file mode 100644 index 9d833662..00000000 --- a/proto/cosmos/evm/precisebank/v1/genesis.proto +++ /dev/null @@ -1,42 +0,0 @@ -syntax = "proto3"; -package cosmos.evm.precisebank.v1; - -import "cosmos_proto/cosmos.proto"; -import "gogoproto/gogo.proto"; - -option go_package = "github.com/cosmos/evm/x/precisebank/types"; - -// GenesisState defines the precisebank module's genesis state. -message GenesisState { - // balances is a list of all the balances in the precisebank module. - repeated FractionalBalance balances = 1 [ - (gogoproto.castrepeated) = "FractionalBalances", - (gogoproto.nullable) = false - ]; - - // remainder is an internal value of how much extra fractional digits are - // still backed by the reserve, but not assigned to any account. - string remainder = 2 [ - (cosmos_proto.scalar) = "cosmos.Int", - (gogoproto.customtype) = "cosmossdk.io/math.Int", - (gogoproto.nullable) = false - ]; -} - -// FractionalBalance defines the fractional portion of an account balance -message FractionalBalance { - option (gogoproto.equal) = false; - option (gogoproto.goproto_getters) = false; - - // address is the address of the balance holder. - string address = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; - - // amount indicates amount of only the fractional balance owned by the - // address. FractionalBalance currently only supports tracking 1 single asset, - // e.g. fractional balances of uatom. - string amount = 2 [ - (cosmos_proto.scalar) = "cosmos.Int", - (gogoproto.customtype) = "cosmossdk.io/math.Int", - (gogoproto.nullable) = false - ]; -} diff --git a/proto/cosmos/evm/precisebank/v1/query.proto b/proto/cosmos/evm/precisebank/v1/query.proto deleted file mode 100644 index 8343ad53..00000000 --- a/proto/cosmos/evm/precisebank/v1/query.proto +++ /dev/null @@ -1,51 +0,0 @@ -syntax = "proto3"; -package cosmos.evm.precisebank.v1; - -import "cosmos/base/v1beta1/coin.proto"; -import "gogoproto/gogo.proto"; -import "google/api/annotations.proto"; - -option go_package = "github.com/cosmos/evm/x/precisebank/types"; -option (gogoproto.goproto_getters_all) = false; - -// Query defines the gRPC querier service for precisebank module -service Query { - // Remainder returns the amount backed by the reserve, but not yet owned by - // any account, i.e. not in circulation. - rpc Remainder(QueryRemainderRequest) returns (QueryRemainderResponse) { - option (google.api.http).get = "/cosmos/evm/precisebank/v1/remainder"; - } - - // FractionalBalance returns only the fractional balance of an address. This - // does not include any integer balance. - rpc FractionalBalance(QueryFractionalBalanceRequest) - returns (QueryFractionalBalanceResponse) { - option (google.api.http).get = - "/cosmos/evm/precisebank/v1/fractional_balance/{address}"; - } -} - -// QueryRemainderRequest defines the request type for Query/Remainder method. -message QueryRemainderRequest {} - -// QueryRemainderResponse defines the response type for Query/Remainder method. -message QueryRemainderResponse { - // remainder is the amount backed by the reserve, but not yet owned by any - // account, i.e. not in circulation. - cosmos.base.v1beta1.Coin remainder = 1 [ (gogoproto.nullable) = false ]; -} - -// QueryFractionalBalanceRequest defines the request type for -// Query/FractionalBalance method. -message QueryFractionalBalanceRequest { - // address is the account address to query fractional balance for. - string address = 1; -} - -// QueryFractionalBalanceResponse defines the response type for -// Query/FractionalBalance method. -message QueryFractionalBalanceResponse { - // fractional_balance is the fractional balance of the address. - cosmos.base.v1beta1.Coin fractional_balance = 1 - [ (gogoproto.nullable) = false ]; -} diff --git a/proto/cosmos/evm/vm/v1/evm.proto b/proto/cosmos/evm/vm/v1/evm.proto index ea22da1f..0a87af0c 100644 --- a/proto/cosmos/evm/vm/v1/evm.proto +++ b/proto/cosmos/evm/vm/v1/evm.proto @@ -39,9 +39,7 @@ message Params { ExtendedDenomOptions extended_denom_options = 11; } -message ExtendedDenomOptions { - string extended_denom = 1; -} +message ExtendedDenomOptions { string extended_denom = 1; } // AccessControl defines the permission policy of the EVM // for creating and calling contracts @@ -358,5 +356,7 @@ message EvmCoinInfo { string denom = 1; string extended_denom = 2; string display_denom = 3; - uint32 decimals = 4; -} \ No newline at end of file + // decimals is now deprecated and will be removed in a future release. When it + // is removed we will assume the evm token denom is 18 decimal precision. + uint32 decimals = 4 [ deprecated = true ]; +} diff --git a/proto/cosmos/evm/vm/v1/query.proto b/proto/cosmos/evm/vm/v1/query.proto index 1bc32761..bdaad05a 100644 --- a/proto/cosmos/evm/vm/v1/query.proto +++ b/proto/cosmos/evm/vm/v1/query.proto @@ -355,7 +355,9 @@ message QueryTraceCallRequest { // gas_cap defines the default gas cap to be used uint64 gas_cap = 2; // proposer_address of the requested block in hex format - bytes proposer_address = 3 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.ConsAddress"]; + bytes proposer_address = 3 + [ (gogoproto.casttype) = + "github.com/cosmos/cosmos-sdk/types.ConsAddress" ]; // trace_config holds extra parameters to trace functions. TraceConfig trace_config = 4; // block_number of requested transaction @@ -363,7 +365,8 @@ message QueryTraceCallRequest { // block_hash of requested transaction string block_hash = 6; // block_time of requested transaction - google.protobuf.Timestamp block_time = 7 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + google.protobuf.Timestamp block_time = 7 + [ (gogoproto.nullable) = false, (gogoproto.stdtime) = true ]; // chain_id is the the eip155 chain id parsed from the requested block header int64 chain_id = 8; } diff --git a/proto/cosmos/evm/vm/v1/tx.proto b/proto/cosmos/evm/vm/v1/tx.proto index 7ac870f9..96d195bf 100644 --- a/proto/cosmos/evm/vm/v1/tx.proto +++ b/proto/cosmos/evm/vm/v1/tx.proto @@ -71,7 +71,8 @@ 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 + // 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; diff --git a/rpc/apis.go b/rpc/apis.go index 2ea7100e..442d46cb 100644 --- a/rpc/apis.go +++ b/rpc/apis.go @@ -5,7 +5,6 @@ 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" @@ -16,7 +15,6 @@ import ( "github.com/cosmos/evm/rpc/namespaces/ethereum/txpool" "github.com/cosmos/evm/rpc/namespaces/ethereum/web3" "github.com/cosmos/evm/rpc/stream" - servertypes "github.com/cosmos/evm/server/types" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/server" @@ -46,9 +44,7 @@ type APICreator = func( ctx *server.Context, clientCtx client.Context, stream *stream.RPCStream, - allowUnprotectedTxs bool, - indexer servertypes.EVMTxIndexer, - mempool *evmmempool.ExperimentalEVMMempool, + backend backend.BackendI, ) []rpc.API // apiCreators defines the JSON-RPC API namespaces. @@ -56,30 +52,34 @@ var apiCreators map[string]APICreator func init() { apiCreators = map[string]APICreator{ - EthNamespace: func(ctx *server.Context, + EthNamespace: func( + ctx *server.Context, clientCtx client.Context, stream *stream.RPCStream, - allowUnprotectedTxs bool, - indexer servertypes.EVMTxIndexer, - mempool *evmmempool.ExperimentalEVMMempool, + backend backend.BackendI, ) []rpc.API { - evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, indexer, mempool) + // should not happen, but just in case + filterBackend, ok := backend.(filters.Backend) + if !ok { + panic("backend does not implement filter.Backend") + } + return []rpc.API{ { Namespace: EthNamespace, Version: apiVersion, - Service: eth.NewPublicAPI(ctx.Logger, evmBackend), + Service: eth.NewPublicAPI(ctx.Logger, backend), Public: true, }, { Namespace: EthNamespace, Version: apiVersion, - Service: filters.NewPublicAPI(ctx.Logger, clientCtx, stream, evmBackend), + Service: filters.NewPublicAPI(ctx.Logger, clientCtx, stream, filterBackend), Public: true, }, } }, - Web3Namespace: func(*server.Context, client.Context, *stream.RPCStream, bool, servertypes.EVMTxIndexer, *evmmempool.ExperimentalEVMMempool) []rpc.API { + Web3Namespace: func(*server.Context, client.Context, *stream.RPCStream, backend.BackendI) []rpc.API { return []rpc.API{ { Namespace: Web3Namespace, @@ -89,7 +89,12 @@ func init() { }, } }, - NetNamespace: func(ctx *server.Context, clientCtx client.Context, _ *stream.RPCStream, _ bool, _ servertypes.EVMTxIndexer, _ *evmmempool.ExperimentalEVMMempool) []rpc.API { + NetNamespace: func( + ctx *server.Context, + clientCtx client.Context, + _ *stream.RPCStream, + _ backend.BackendI, + ) []rpc.API { return []rpc.API{ { Namespace: NetNamespace, @@ -99,70 +104,62 @@ func init() { }, } }, - PersonalNamespace: func(ctx *server.Context, - clientCtx client.Context, + PersonalNamespace: func( + ctx *server.Context, + _ client.Context, _ *stream.RPCStream, - allowUnprotectedTxs bool, - indexer servertypes.EVMTxIndexer, - mempool *evmmempool.ExperimentalEVMMempool, + backend backend.BackendI, ) []rpc.API { - evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, indexer, mempool) return []rpc.API{ { Namespace: PersonalNamespace, Version: apiVersion, - Service: personal.NewAPI(ctx.Logger, evmBackend), + Service: personal.NewAPI(ctx.Logger, backend), Public: false, }, } }, - TxPoolNamespace: func(ctx *server.Context, - clientCtx client.Context, + TxPoolNamespace: func( + ctx *server.Context, + _ client.Context, _ *stream.RPCStream, - allowUnprotectedTxs bool, - indexer servertypes.EVMTxIndexer, - mempool *evmmempool.ExperimentalEVMMempool, + backend backend.BackendI, ) []rpc.API { - evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, indexer, mempool) return []rpc.API{ { Namespace: TxPoolNamespace, Version: apiVersion, - Service: txpool.NewPublicAPI(ctx.Logger, evmBackend), + Service: txpool.NewPublicAPI(ctx.Logger, backend), Public: true, }, } }, - DebugNamespace: func(ctx *server.Context, - clientCtx client.Context, + DebugNamespace: func( + ctx *server.Context, + _ client.Context, _ *stream.RPCStream, - allowUnprotectedTxs bool, - indexer servertypes.EVMTxIndexer, - mempool *evmmempool.ExperimentalEVMMempool, + backend backend.BackendI, ) []rpc.API { - evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, indexer, mempool) return []rpc.API{ { Namespace: DebugNamespace, Version: apiVersion, - Service: debug.NewAPI(ctx, evmBackend, evmBackend.GetConfig().JSONRPC.EnableProfiling), + Service: debug.NewAPI(ctx, backend, backend.GetConfig().JSONRPC.EnableProfiling), Public: true, }, } }, - MinerNamespace: func(ctx *server.Context, - clientCtx client.Context, + MinerNamespace: func( + ctx *server.Context, + _ client.Context, _ *stream.RPCStream, - allowUnprotectedTxs bool, - indexer servertypes.EVMTxIndexer, - mempool *evmmempool.ExperimentalEVMMempool, + backend backend.BackendI, ) []rpc.API { - evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, indexer, mempool) return []rpc.API{ { Namespace: MinerNamespace, Version: apiVersion, - Service: miner.NewPrivateAPI(ctx, evmBackend), + Service: miner.NewPrivateAPI(ctx, backend), Public: false, }, } @@ -170,23 +167,26 @@ func init() { } } -// GetRPCAPIs returns the list of all APIs -func GetRPCAPIs(ctx *server.Context, +// BuildRPCs builds the JSON-RPC APIs for the given namespaces. +func BuildRPCs( + selectedAPIs []string, + ctx *server.Context, clientCtx client.Context, stream *stream.RPCStream, - allowUnprotectedTxs bool, - indexer servertypes.EVMTxIndexer, - selectedAPIs []string, - mempool *evmmempool.ExperimentalEVMMempool, + backend backend.BackendI, ) []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, mempool)...) - } else { + creator, ok := apiCreators[ns] + if !ok { ctx.Logger.Error("invalid namespace value", "namespace", ns) + continue } + + api := creator(ctx, clientCtx, stream, backend) + + apis = append(apis, api...) } return apis diff --git a/rpc/backend/account_info.go b/rpc/backend/account_info.go index 9bbaff66..5b5e6713 100644 --- a/rpc/backend/account_info.go +++ b/rpc/backend/account_info.go @@ -1,6 +1,7 @@ package backend import ( + "context" "fmt" "math" "math/big" @@ -8,10 +9,13 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/pkg/errors" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" "github.com/cometbft/cometbft/libs/bytes" rpctypes "github.com/cosmos/evm/rpc/types" + evmtrace "github.com/cosmos/evm/trace" evmtypes "github.com/cosmos/evm/x/vm/types" errorsmod "cosmossdk.io/errors" @@ -23,17 +27,21 @@ import ( ) // GetCode returns the contract code at the given address and block number. -func (b *Backend) GetCode(address common.Address, blockNrOrHash rpctypes.BlockNumberOrHash) (hexutil.Bytes, error) { - blockNum, err := b.BlockNumberFromComet(blockNrOrHash) +func (b *Backend) GetCode(ctx context.Context, address common.Address, blockNrOrHash rpctypes.BlockNumberOrHash) (bz hexutil.Bytes, err error) { + ctx, span := tracer.Start(ctx, "GetCode", trace.WithAttributes(attribute.String("address", address.String()), attribute.String("blockNorHash", unwrapBlockNOrHash(blockNrOrHash)))) + defer func() { evmtrace.EndSpanErr(span, err) }() + + blockNum, err := b.BlockNumberFromComet(ctx, blockNrOrHash) if err != nil { return nil, err } + ctx = rpctypes.ContextWithHeight(ctx, blockNum.Int64()) req := &evmtypes.QueryCodeRequest{ Address: address.String(), } - res, err := b.QueryClient.Code(rpctypes.ContextWithHeight(blockNum.Int64()), req) + res, err := b.QueryClient.Code(ctx, req) if err != nil { return nil, err } @@ -42,15 +50,18 @@ func (b *Backend) GetCode(address common.Address, blockNrOrHash rpctypes.BlockNu } // GetProof returns an account object with proof and any storage proofs -func (b *Backend) GetProof(address common.Address, storageKeys []string, blockNrOrHash rpctypes.BlockNumberOrHash) (*rpctypes.AccountResult, error) { - blockNum, err := b.BlockNumberFromComet(blockNrOrHash) +func (b *Backend) GetProof(ctx context.Context, address common.Address, storageKeys []string, blockNrOrHash rpctypes.BlockNumberOrHash) (result *rpctypes.AccountResult, err error) { + ctx, span := tracer.Start(ctx, "GetProof", trace.WithAttributes(attribute.String("address", address.String()), attribute.StringSlice("storageKeys", storageKeys), attribute.String("blockNorHash", unwrapBlockNOrHash(blockNrOrHash)))) + defer func() { evmtrace.EndSpanErr(span, err) }() + + blockNum, err := b.BlockNumberFromComet(ctx, blockNrOrHash) if err != nil { return nil, err } height := int64(blockNum) - _, err = b.CometHeaderByNumber(blockNum) + _, err = b.CometHeaderByNumber(ctx, blockNum) if err != nil { // the error message imitates geth behavior return nil, errors.New("header not found") @@ -58,7 +69,7 @@ func (b *Backend) GetProof(address common.Address, storageKeys []string, blockNr // if the height is equal to zero, meaning the query condition of the block is either "pending" or "latest" if height == 0 { - bn, err := b.BlockNumber() + bn, err := b.BlockNumber(ctx) if err != nil { return nil, err } @@ -70,8 +81,8 @@ func (b *Backend) GetProof(address common.Address, storageKeys []string, blockNr height = int64(bn) //#nosec G115 -- checked for int overflow already } - ctx := rpctypes.ContextWithHeight(height) - clientCtx := b.ClientCtx.WithHeight(height) + ctx = rpctypes.ContextWithHeight(ctx, height) + clientCtx := b.ClientCtx.WithHeight(height).WithCmdContext(ctx) // query storage proofs storageProofs := make([]rpctypes.StorageResult, len(storageKeys)) @@ -124,18 +135,22 @@ func (b *Backend) GetProof(address common.Address, storageKeys []string, blockNr } // GetStorageAt returns the contract storage at the given address, block number, and key. -func (b *Backend) GetStorageAt(address common.Address, key string, blockNrOrHash rpctypes.BlockNumberOrHash) (hexutil.Bytes, error) { - blockNum, err := b.BlockNumberFromComet(blockNrOrHash) +func (b *Backend) GetStorageAt(ctx context.Context, address common.Address, key string, blockNrOrHash rpctypes.BlockNumberOrHash) (result hexutil.Bytes, err error) { + ctx, span := tracer.Start(ctx, "GetStorageAt", trace.WithAttributes(attribute.String("address", address.String()), attribute.String("key", key), attribute.String("blockNorHash", unwrapBlockNOrHash(blockNrOrHash)))) + defer func() { evmtrace.EndSpanErr(span, err) }() + + blockNum, err := b.BlockNumberFromComet(ctx, blockNrOrHash) if err != nil { return nil, err } + ctx = rpctypes.ContextWithHeight(ctx, blockNum.Int64()) req := &evmtypes.QueryStorageRequest{ Address: address.String(), Key: key, } - res, err := b.QueryClient.Storage(rpctypes.ContextWithHeight(blockNum.Int64()), req) + res, err := b.QueryClient.Storage(ctx, req) if err != nil { return nil, err } @@ -145,22 +160,26 @@ func (b *Backend) GetStorageAt(address common.Address, key string, blockNrOrHash } // GetBalance returns the provided account's *spendable* balance up to the provided block number. -func (b *Backend) GetBalance(address common.Address, blockNrOrHash rpctypes.BlockNumberOrHash) (*hexutil.Big, error) { - blockNum, err := b.BlockNumberFromComet(blockNrOrHash) +func (b *Backend) GetBalance(ctx context.Context, address common.Address, blockNrOrHash rpctypes.BlockNumberOrHash) (result *hexutil.Big, err error) { + ctx, span := tracer.Start(ctx, "GetBalance", trace.WithAttributes(attribute.String("address", address.String()), attribute.String("blockNorHash", unwrapBlockNOrHash(blockNrOrHash)))) + defer func() { evmtrace.EndSpanErr(span, err) }() + + blockNum, err := b.BlockNumberFromComet(ctx, blockNrOrHash) if err != nil { return nil, err } + ctx = rpctypes.ContextWithHeight(ctx, blockNum.Int64()) req := &evmtypes.QueryBalanceRequest{ Address: address.String(), } - _, err = b.CometHeaderByNumber(blockNum) + _, err = b.CometHeaderByNumber(ctx, blockNum) if err != nil { return nil, err } - res, err := b.QueryClient.Balance(rpctypes.ContextWithHeight(blockNum.Int64()), req) + res, err := b.QueryClient.Balance(ctx, req) if err != nil { return nil, err } @@ -179,9 +198,12 @@ func (b *Backend) GetBalance(address common.Address, blockNrOrHash rpctypes.Bloc } // GetTransactionCount returns the number of transactions at the given address up to the given block number. -func (b *Backend) GetTransactionCount(address common.Address, blockNum rpctypes.BlockNumber) (*hexutil.Uint64, error) { +func (b *Backend) GetTransactionCount(ctx context.Context, address common.Address, blockNum rpctypes.BlockNumber) (result *hexutil.Uint64, err error) { + ctx, span := tracer.Start(ctx, "GetTransactionCount", trace.WithAttributes(attribute.String("address", address.String()), attribute.Int64("blockNum", blockNum.Int64()))) + defer func() { evmtrace.EndSpanErr(span, err) }() + n := hexutil.Uint64(0) - bn, err := b.BlockNumber() + bn, err := b.BlockNumber(ctx) if err != nil { return &n, err } @@ -199,14 +221,14 @@ func (b *Backend) GetTransactionCount(address common.Address, blockNum rpctypes. from := sdk.AccAddress(address.Bytes()) accRet := b.ClientCtx.AccountRetriever - err = accRet.EnsureExists(b.ClientCtx, from) + err = accRet.EnsureExists(b.ClientCtx.WithCmdContext(ctx), from) if err != nil { // account doesn't exist yet, return 0 return &n, nil } includePending := blockNum == rpctypes.EthPendingBlockNumber - nonce, err := b.getAccountNonce(address, includePending, blockNum.Int64(), b.Logger) + nonce, err := b.getAccountNonce(ctx, address, includePending, blockNum.Int64(), b.Logger) if err != nil { return nil, err } diff --git a/rpc/backend/backend.go b/rpc/backend/backend.go index e733174c..e39fc9ad 100644 --- a/rpc/backend/backend.go +++ b/rpc/backend/backend.go @@ -14,22 +14,24 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/signer/core/apitypes" + "go.opentelemetry.io/otel" tmrpcclient "github.com/cometbft/cometbft/rpc/client" tmrpctypes "github.com/cometbft/cometbft/rpc/core/types" - evmmempool "github.com/cosmos/evm/mempool" + "github.com/cosmos/evm/mempool/txpool" "github.com/cosmos/evm/rpc/types" "github.com/cosmos/evm/server/config" servertypes "github.com/cosmos/evm/server/types" evmtypes "github.com/cosmos/evm/x/vm/types" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" "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" + sdkmempool "github.com/cosmos/cosmos-sdk/types/mempool" ) // BackendI implements the Cosmos and EVM backend. @@ -45,9 +47,9 @@ type BackendI interface { //nolint: revive type EVMBackend interface { // Node specific queries Accounts() ([]common.Address, error) - Syncing() (interface{}, error) - SetEtherbase(etherbase common.Address) bool - SetGasPrice(gasPrice hexutil.Big) bool + Syncing(ctx context.Context) (interface{}, error) + SetEtherbase(ctx context.Context, etherbase common.Address) bool + SetGasPrice(ctx context.Context, gasPrice hexutil.Big) bool ImportRawKey(privkey, password string) (common.Address, error) ListAccounts() ([]common.Address, error) NewMnemonic(uid string, language keyring.Language, hdPath, bip39Passphrase string, algo keyring.SignatureAlgo) (*keyring.Record, error) @@ -59,85 +61,99 @@ type EVMBackend interface { // Sign Tx Sign(address common.Address, data hexutil.Bytes) (hexutil.Bytes, error) - SendTransaction(args evmtypes.TransactionArgs) (common.Hash, error) + SendTransaction(ctx context.Context, args evmtypes.TransactionArgs) (common.Hash, error) SignTypedData(address common.Address, typedData apitypes.TypedData) (hexutil.Bytes, error) // Blocks Info - BlockNumber() (hexutil.Uint64, error) - GetHeaderByNumber(blockNum types.BlockNumber) (map[string]interface{}, error) - GetHeaderByHash(hash common.Hash) (map[string]interface{}, error) - GetBlockByNumber(blockNum types.BlockNumber, fullTx bool) (map[string]interface{}, error) - GetBlockByHash(hash common.Hash, fullTx bool) (map[string]interface{}, error) - GetBlockTransactionCountByHash(hash common.Hash) *hexutil.Uint - GetBlockTransactionCountByNumber(blockNum types.BlockNumber) *hexutil.Uint - CometBlockByNumber(blockNum types.BlockNumber) (*tmrpctypes.ResultBlock, error) - CometBlockByHash(blockHash common.Hash) (*tmrpctypes.ResultBlock, error) - BlockNumberFromComet(blockNrOrHash types.BlockNumberOrHash) (types.BlockNumber, error) - BlockNumberFromCometByHash(blockHash common.Hash) (*big.Int, error) - EthMsgsFromCometBlock(block *tmrpctypes.ResultBlock, blockRes *tmrpctypes.ResultBlockResults) []*evmtypes.MsgEthereumTx - BlockBloomFromCometBlock(blockRes *tmrpctypes.ResultBlockResults) (ethtypes.Bloom, error) - HeaderByNumber(blockNum types.BlockNumber) (*ethtypes.Header, error) - HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error) - RPCBlockFromCometBlock(resBlock *tmrpctypes.ResultBlock, blockRes *tmrpctypes.ResultBlockResults, fullTx bool) (map[string]interface{}, error) - EthBlockByNumber(blockNum types.BlockNumber) (*ethtypes.Block, error) - EthBlockFromCometBlock(resBlock *tmrpctypes.ResultBlock, blockRes *tmrpctypes.ResultBlockResults) (*ethtypes.Block, error) - GetBlockReceipts(blockNrOrHash types.BlockNumberOrHash) ([]map[string]interface{}, error) + BlockNumber(ctx context.Context) (hexutil.Uint64, error) + GetHeaderByNumber(ctx context.Context, blockNum types.BlockNumber) (map[string]interface{}, error) + GetHeaderByHash(ctx context.Context, hash common.Hash) (map[string]interface{}, error) + GetBlockByNumber(ctx context.Context, blockNum types.BlockNumber, fullTx bool) (map[string]interface{}, error) + GetBlockByHash(ctx context.Context, hash common.Hash, fullTx bool) (map[string]interface{}, error) + GetBlockTransactionCountByHash(ctx context.Context, hash common.Hash) *hexutil.Uint + GetBlockTransactionCountByNumber(ctx context.Context, blockNum types.BlockNumber) *hexutil.Uint + CometBlockByNumber(ctx context.Context, blockNum types.BlockNumber) (*tmrpctypes.ResultBlock, error) + CometBlockByHash(ctx context.Context, blockHash common.Hash) (*tmrpctypes.ResultBlock, error) + BlockNumberFromComet(ctx context.Context, blockNrOrHash types.BlockNumberOrHash) (types.BlockNumber, error) + BlockNumberFromCometByHash(ctx context.Context, blockHash common.Hash) (*big.Int, error) + EthMsgsFromCometBlock(ctx context.Context, block *tmrpctypes.ResultBlock, blockRes *tmrpctypes.ResultBlockResults) []*evmtypes.MsgEthereumTx + BlockBloomFromCometBlock(ctx context.Context, blockRes *tmrpctypes.ResultBlockResults) (ethtypes.Bloom, error) + HeaderByNumber(ctx context.Context, blockNum types.BlockNumber) (*ethtypes.Header, error) + HeaderByHash(ctx context.Context, blockHash common.Hash) (*ethtypes.Header, error) + RPCBlockFromCometBlock(ctx context.Context, resBlock *tmrpctypes.ResultBlock, blockRes *tmrpctypes.ResultBlockResults, fullTx bool) (map[string]interface{}, error) + EthBlockByNumber(ctx context.Context, blockNum types.BlockNumber) (*ethtypes.Block, error) + EthBlockFromCometBlock(ctx context.Context, resBlock *tmrpctypes.ResultBlock, blockRes *tmrpctypes.ResultBlockResults) (*ethtypes.Block, error) + GetBlockReceipts(ctx context.Context, blockNrOrHash types.BlockNumberOrHash) ([]map[string]interface{}, error) // Account Info - GetCode(address common.Address, blockNrOrHash types.BlockNumberOrHash) (hexutil.Bytes, error) - GetBalance(address common.Address, blockNrOrHash types.BlockNumberOrHash) (*hexutil.Big, error) - GetStorageAt(address common.Address, key string, blockNrOrHash types.BlockNumberOrHash) (hexutil.Bytes, error) - GetProof(address common.Address, storageKeys []string, blockNrOrHash types.BlockNumberOrHash) (*types.AccountResult, error) - GetTransactionCount(address common.Address, blockNum types.BlockNumber) (*hexutil.Uint64, error) + GetCode(ctx context.Context, address common.Address, blockNrOrHash types.BlockNumberOrHash) (hexutil.Bytes, error) + GetBalance(ctx context.Context, address common.Address, blockNrOrHash types.BlockNumberOrHash) (*hexutil.Big, error) + GetStorageAt(ctx context.Context, address common.Address, key string, blockNrOrHash types.BlockNumberOrHash) (hexutil.Bytes, error) + GetProof(ctx context.Context, address common.Address, storageKeys []string, blockNrOrHash types.BlockNumberOrHash) (*types.AccountResult, error) + GetTransactionCount(ctx context.Context, address common.Address, blockNum types.BlockNumber) (*hexutil.Uint64, error) // Chain Info - ChainID() (*hexutil.Big, error) + ChainID(ctx context.Context) (*hexutil.Big, error) ChainConfig() *params.ChainConfig - GlobalMinGasPrice() (*big.Int, error) - BaseFee(blockRes *tmrpctypes.ResultBlockResults) (*big.Int, error) - CurrentHeader() (*ethtypes.Header, error) - PendingTransactions() ([]*sdk.Tx, error) - GetCoinbase() (sdk.AccAddress, error) - FeeHistory(blockCount math.HexOrDecimal64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*types.FeeHistoryResult, error) - SuggestGasTipCap(baseFee *big.Int) (*big.Int, error) + GlobalMinGasPrice(ctx context.Context) (*big.Int, error) + BaseFee(ctx context.Context, blockRes *tmrpctypes.ResultBlockResults) (*big.Int, error) + CurrentHeader(ctx context.Context) (*ethtypes.Header, error) + PendingTransactions(ctx context.Context) ([]*sdk.Tx, error) + GetCoinbase(ctx context.Context) (sdk.AccAddress, error) + FeeHistory(ctx context.Context, blockCount math.HexOrDecimal64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*types.FeeHistoryResult, error) + SuggestGasTipCap(ctx context.Context, baseFee *big.Int) (*big.Int, error) // Tx Info - GetTransactionByHash(txHash common.Hash) (*types.RPCTransaction, error) - GetTxByEthHash(txHash common.Hash) (*servertypes.TxResult, error) - GetTxByTxIndex(height int64, txIndex uint) (*servertypes.TxResult, error) - GetTransactionByBlockAndIndex(block *tmrpctypes.ResultBlock, idx hexutil.Uint) (*types.RPCTransaction, error) - GetTransactionReceipt(hash common.Hash) (map[string]interface{}, error) - GetTransactionLogs(hash common.Hash) ([]*ethtypes.Log, error) - GetTransactionByBlockHashAndIndex(hash common.Hash, idx hexutil.Uint) (*types.RPCTransaction, error) - GetTransactionByBlockNumberAndIndex(blockNum types.BlockNumber, idx hexutil.Uint) (*types.RPCTransaction, error) - CreateAccessList(args evmtypes.TransactionArgs, blockNrOrHash types.BlockNumberOrHash, overrides *json.RawMessage) (*types.AccessListResult, error) + GetTransactionByHash(ctx context.Context, txHash common.Hash) (*types.RPCTransaction, error) + GetTxByEthHash(ctx context.Context, txHash common.Hash) (*servertypes.TxResult, error) + GetTxByTxIndex(ctx context.Context, height int64, txIndex uint) (*servertypes.TxResult, error) + GetTransactionByBlockAndIndex(ctx context.Context, block *tmrpctypes.ResultBlock, idx hexutil.Uint) (*types.RPCTransaction, error) + GetTransactionReceipt(ctx context.Context, hash common.Hash) (map[string]interface{}, error) + GetTransactionLogs(ctx context.Context, hash common.Hash) ([]*ethtypes.Log, error) + GetTransactionByBlockHashAndIndex(ctx context.Context, hash common.Hash, idx hexutil.Uint) (*types.RPCTransaction, error) + GetTransactionByBlockNumberAndIndex(ctx context.Context, blockNum types.BlockNumber, idx hexutil.Uint) (*types.RPCTransaction, error) + CreateAccessList(ctx context.Context, args evmtypes.TransactionArgs, blockNrOrHash types.BlockNumberOrHash, overrides *json.RawMessage) (*types.AccessListResult, error) // Send Transaction - Resend(args evmtypes.TransactionArgs, gasPrice *hexutil.Big, gasLimit *hexutil.Uint64) (common.Hash, error) - SendRawTransaction(data hexutil.Bytes) (common.Hash, error) - SetTxDefaults(args evmtypes.TransactionArgs) (evmtypes.TransactionArgs, error) - EstimateGas(args evmtypes.TransactionArgs, blockNrOptional *types.BlockNumber) (hexutil.Uint64, error) - DoCall(args evmtypes.TransactionArgs, blockNr types.BlockNumber, overrides *json.RawMessage) (*evmtypes.MsgEthereumTxResponse, error) - GasPrice() (*hexutil.Big, error) + Resend(ctx context.Context, args evmtypes.TransactionArgs, gasPrice *hexutil.Big, gasLimit *hexutil.Uint64) (common.Hash, error) + SendRawTransaction(ctx context.Context, data hexutil.Bytes) (common.Hash, error) + SetTxDefaults(ctx context.Context, args evmtypes.TransactionArgs) (evmtypes.TransactionArgs, error) + EstimateGas(ctx context.Context, args evmtypes.TransactionArgs, blockNrOrHash *types.BlockNumberOrHash, overrides *json.RawMessage) (hexutil.Uint64, error) + DoCall(ctx context.Context, args evmtypes.TransactionArgs, blockNr types.BlockNumber, overrides *json.RawMessage) (*evmtypes.MsgEthereumTxResponse, error) + GasPrice(ctx context.Context) (*hexutil.Big, error) // Filter API - GetLogs(hash common.Hash) ([][]*ethtypes.Log, error) - GetLogsByHeight(height *int64) ([][]*ethtypes.Log, error) + GetLogs(ctx context.Context, hash common.Hash) ([][]*ethtypes.Log, error) + GetLogsByHeight(ctx context.Context, height *int64) ([][]*ethtypes.Log, error) BloomStatus() (uint64, uint64) // TxPool API - Content() (map[string]map[string]map[string]*types.RPCTransaction, error) - ContentFrom(address common.Address) (map[string]map[string]*types.RPCTransaction, error) - Inspect() (map[string]map[string]map[string]string, error) - Status() (map[string]hexutil.Uint, error) + Content(ctx context.Context) (map[string]map[string]map[string]*types.RPCTransaction, error) + ContentFrom(ctx context.Context, address common.Address) (map[string]map[string]*types.RPCTransaction, error) + Inspect(ctx context.Context) (map[string]map[string]map[string]string, error) + Status(ctx context.Context) (map[string]hexutil.Uint, error) // Tracing - TraceTransaction(hash common.Hash, config *types.TraceConfig) (interface{}, error) - TraceBlock(height types.BlockNumber, config *types.TraceConfig, block *tmrpctypes.ResultBlock) ([]*evmtypes.TxTraceResult, error) - TraceCall(args evmtypes.TransactionArgs, blockNrOrHash types.BlockNumberOrHash, config *types.TraceConfig) (interface{}, error) + TraceTransaction(ctx context.Context, hash common.Hash, config *types.TraceConfig) (interface{}, error) + TraceBlock(ctx context.Context, height types.BlockNumber, config *types.TraceConfig, block *tmrpctypes.ResultBlock) ([]*evmtypes.TxTraceResult, error) + TraceCall(ctx context.Context, args evmtypes.TransactionArgs, blockNrOrHash types.BlockNumberOrHash, config *types.TraceConfig) (interface{}, error) } -var _ BackendI = (*Backend)(nil) +// TrackingMempool is a set of methods that a mempool may implement in order to +// track evm transaction lifecycle events. +type TrackingMempool interface { + // TrackTx is called when a tx should start to be tracked by the + // TrackingMempool. This is called on tx ingestion from the rpc backend. + // This is NOT called when txs are ingested over p2p, i.e local + // transactions only. + TrackTx(hash common.Hash) error +} + +var ( + _ BackendI = (*Backend)(nil) + + tracer = otel.Tracer("evm/rpc/backend") +) // ProcessBlocker is a function type that processes a block and its associated data // for fee history calculation. It takes a Tendermint block, its corresponding @@ -145,6 +161,7 @@ var _ BackendI = (*Backend)(nil) // block results, and a target fee history entry to populate. // // Parameters: +// - ctx: Context for the request // - tendermintBlock: The raw Tendermint block data // - ethBlock: The Ethereum-formatted block representation // - rewardPercentiles: Percentiles used for fee reward calculation @@ -153,6 +170,7 @@ var _ BackendI = (*Backend)(nil) // // Returns an error if block processing fails. type ProcessBlocker func( + ctx context.Context, tendermintBlock *tmrpctypes.ResultBlock, ethBlock *map[string]interface{}, rewardPercentiles []float64, @@ -160,9 +178,16 @@ type ProcessBlocker func( targetOneFeeHistory *types.OneFeeHistory, ) error +// Mempool is a mempool that can be used for the rpc backend. +type Mempool interface { + sdkmempool.Mempool + + // GetTxPool returns the mempools underlying evm txpool. + GetTxPool() *txpool.TxPool +} + // Backend implements the BackendI interface type Backend struct { - Ctx context.Context ClientCtx client.Context RPCClient tmrpcclient.SignClient QueryClient *types.QueryClient // gRPC query client @@ -172,21 +197,29 @@ type Backend struct { AllowUnprotectedTxs bool Indexer servertypes.EVMTxIndexer ProcessBlocker ProcessBlocker - Mempool *evmmempool.ExperimentalEVMMempool + Mempool Mempool } -func (b *Backend) GetConfig() config.Config { - return b.Cfg +// Opt is a function type that configures the backend. +type Opt func(*Backend) + +// WithUnprotectedTxs sets whether to allow unprotected transactions. +func WithUnprotectedTxs(value bool) Opt { + return func(b *Backend) { b.AllowUnprotectedTxs = value } +} + +// WithLogger sets the logger for the backend. +func WithLogger(logger log.Logger) Opt { + return func(b *Backend) { b.Logger = logger.With("module", "backend") } } // NewBackend creates a new Backend instance for cosmos and ethereum namespaces func NewBackend( ctx *server.Context, - logger log.Logger, clientCtx client.Context, - allowUnprotectedTxs bool, indexer servertypes.EVMTxIndexer, - mempool *evmmempool.ExperimentalEVMMempool, + mempool Mempool, + opts ...Opt, ) *Backend { appConf, err := config.GetConfig(ctx.Viper) if err != nil { @@ -199,17 +232,40 @@ func NewBackend( } b := &Backend{ - Ctx: context.Background(), ClientCtx: clientCtx, RPCClient: rpcClient, QueryClient: types.NewQueryClient(clientCtx), - Logger: logger.With("module", "backend"), EvmChainID: big.NewInt(int64(appConf.EVM.EVMChainID)), //nolint:gosec // G115 // won't exceed uint64 Cfg: appConf, - AllowUnprotectedTxs: allowUnprotectedTxs, + AllowUnprotectedTxs: false, Indexer: indexer, Mempool: mempool, + Logger: log.NewNopLogger(), } + b.ProcessBlocker = b.ProcessBlock + + for _, opt := range opts { + opt(b) + } + return b } + +func (b *Backend) GetConfig() config.Config { + return b.Cfg +} + +// TrackTxIfSupported calls TrackTx on the backends mempool if it is a +// supported method. +func (b *Backend) TrackTxIfSupported(txHash common.Hash) { + tm, ok := b.Mempool.(TrackingMempool) + if !ok { + return + } + + // track the tx for tx inclusion timing metrics of local txs + if err := tm.TrackTx(txHash); err != nil { + b.Logger.Error("error tracking inserted inserted into mempool", "hash", txHash, "err", err) + } +} diff --git a/rpc/backend/blocks.go b/rpc/backend/blocks.go index e3b8aa10..91de7d1b 100644 --- a/rpc/backend/blocks.go +++ b/rpc/backend/blocks.go @@ -1,18 +1,22 @@ package backend import ( + "context" "fmt" "strconv" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" ethtypes "github.com/ethereum/go-ethereum/core/types" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" "google.golang.org/grpc" "google.golang.org/grpc/metadata" cmtrpctypes "github.com/cometbft/cometbft/rpc/core/types" "github.com/cosmos/evm/rpc/types" + evmtrace "github.com/cosmos/evm/trace" evmtypes "github.com/cosmos/evm/x/vm/types" grpctypes "github.com/cosmos/cosmos-sdk/types/grpc" @@ -22,10 +26,13 @@ import ( // app state could lag behind from cometbft latest block, it's more stable for // the client to use the latest block number in abci app state than cometbft // rpc. -func (b *Backend) BlockNumber() (hexutil.Uint64, error) { +func (b *Backend) BlockNumber(ctx context.Context) (result hexutil.Uint64, err error) { + ctx, span := tracer.Start(ctx, "GetBlockNumber") + defer func() { evmtrace.EndSpanErr(span, err) }() + // do any grpc query, ignore the response and use the returned block height var header metadata.MD - _, err := b.QueryClient.Params(b.Ctx, &evmtypes.QueryParamsRequest{}, grpc.Header(&header)) + _, err = b.QueryClient.Params(ctx, &evmtypes.QueryParamsRequest{}, grpc.Header(&header)) if err != nil { return hexutil.Uint64(0), err } @@ -46,8 +53,11 @@ func (b *Backend) BlockNumber() (hexutil.Uint64, error) { // GetBlockByNumber returns the JSON-RPC compatible Ethereum block identified by // block number. Depending on fullTx it either returns the full transaction // objects or if false only the hashes of the transactions. -func (b *Backend) GetBlockByNumber(blockNum types.BlockNumber, fullTx bool) (map[string]interface{}, error) { - resBlock, err := b.CometBlockByNumber(blockNum) +func (b *Backend) GetBlockByNumber(ctx context.Context, blockNum types.BlockNumber, fullTx bool) (result map[string]interface{}, err error) { + ctx, span := tracer.Start(ctx, "GetBlockByNumber", trace.WithAttributes(attribute.Int64("blockNum", blockNum.Int64()), attribute.Bool("fullTx", fullTx))) + defer func() { evmtrace.EndSpanErr(span, err) }() + + resBlock, err := b.CometBlockByNumber(ctx, blockNum) if err != nil { return nil, nil } @@ -57,25 +67,28 @@ func (b *Backend) GetBlockByNumber(blockNum types.BlockNumber, fullTx bool) (map return nil, nil } - blockRes, err := b.RPCClient.BlockResults(b.Ctx, &resBlock.Block.Height) + blockRes, err := b.RPCClient.BlockResults(ctx, &resBlock.Block.Height) if err != nil { b.Logger.Debug("failed to fetch block result from CometBFT", "height", blockNum, "error", err.Error()) return nil, nil } - res, err := b.RPCBlockFromCometBlock(resBlock, blockRes, fullTx) + result, err = b.RPCBlockFromCometBlock(ctx, resBlock, blockRes, fullTx) if err != nil { b.Logger.Debug("RPCBlockFromCometBlock failed", "height", blockNum, "error", err.Error()) return nil, err } - return res, nil + return result, nil } // GetBlockByHash returns the JSON-RPC compatible Ethereum block identified by // hash. -func (b *Backend) GetBlockByHash(hash common.Hash, fullTx bool) (map[string]interface{}, error) { - resBlock, err := b.CometBlockByHash(hash) +func (b *Backend) GetBlockByHash(ctx context.Context, hash common.Hash, fullTx bool) (result map[string]interface{}, err error) { + ctx, span := tracer.Start(ctx, "GetBlockByHash", trace.WithAttributes(attribute.String("hash", hash.Hex()), attribute.Bool("fullTx", fullTx))) + defer func() { evmtrace.EndSpanErr(span, err) }() + + resBlock, err := b.CometBlockByHash(ctx, hash) if err != nil { return nil, err } @@ -85,25 +98,27 @@ func (b *Backend) GetBlockByHash(hash common.Hash, fullTx bool) (map[string]inte return nil, nil } - blockRes, err := b.RPCClient.BlockResults(b.Ctx, &resBlock.Block.Height) + blockRes, err := b.RPCClient.BlockResults(ctx, &resBlock.Block.Height) if err != nil { b.Logger.Debug("failed to fetch block result from CometBFT", "block-hash", hash.String(), "error", err.Error()) return nil, nil } - res, err := b.RPCBlockFromCometBlock(resBlock, blockRes, fullTx) + result, err = b.RPCBlockFromCometBlock(ctx, resBlock, blockRes, fullTx) if err != nil { b.Logger.Debug("RPCBlockFromCometBlock failed", "hash", hash, "error", err.Error()) return nil, err } - return res, nil + return result, nil } // GetBlockTransactionCountByHash returns the number of Ethereum transactions in // the block identified by hash. -func (b *Backend) GetBlockTransactionCountByHash(hash common.Hash) *hexutil.Uint { - block, err := b.RPCClient.BlockByHash(b.Ctx, hash.Bytes()) +func (b *Backend) GetBlockTransactionCountByHash(ctx context.Context, hash common.Hash) *hexutil.Uint { + ctx, span := tracer.Start(ctx, "GetBlockTransactionCountByHash", trace.WithAttributes(attribute.String("hash", hash.Hex()))) + defer span.End() + block, err := b.RPCClient.BlockByHash(ctx, hash.Bytes()) if err != nil { b.Logger.Debug("block not found", "hash", hash.Hex(), "error", err.Error()) return nil @@ -114,13 +129,15 @@ func (b *Backend) GetBlockTransactionCountByHash(hash common.Hash) *hexutil.Uint return nil } - return b.getBlockTransactionCount(block) + return b.getBlockTransactionCount(ctx, block) } // GetBlockTransactionCountByNumber returns the number of Ethereum transactions // in the block identified by number. -func (b *Backend) GetBlockTransactionCountByNumber(blockNum types.BlockNumber) *hexutil.Uint { - block, err := b.CometBlockByNumber(blockNum) +func (b *Backend) GetBlockTransactionCountByNumber(ctx context.Context, blockNum types.BlockNumber) *hexutil.Uint { + ctx, span := tracer.Start(ctx, "GetBlockTransactionCountByNumber", trace.WithAttributes(attribute.Int64("blockNum", blockNum.Int64()))) + defer span.End() + block, err := b.CometBlockByNumber(ctx, blockNum) if err != nil { b.Logger.Debug("block not found", "height", blockNum.Int64(), "error", err.Error()) return nil @@ -131,25 +148,30 @@ func (b *Backend) GetBlockTransactionCountByNumber(blockNum types.BlockNumber) * return nil } - return b.getBlockTransactionCount(block) + return b.getBlockTransactionCount(ctx, block) } // getBlockTransactionCount returns the number of Ethereum transactions in a // given block. -func (b *Backend) getBlockTransactionCount(block *cmtrpctypes.ResultBlock) *hexutil.Uint { - blockRes, err := b.RPCClient.BlockResults(b.Ctx, &block.Block.Height) +func (b *Backend) getBlockTransactionCount(ctx context.Context, block *cmtrpctypes.ResultBlock) *hexutil.Uint { + ctx, span := tracer.Start(ctx, "getBlockTransactionCount") + defer span.End() + blockRes, err := b.RPCClient.BlockResults(ctx, &block.Block.Height) if err != nil { return nil } - ethMsgs := b.EthMsgsFromCometBlock(block, blockRes) + ethMsgs := b.EthMsgsFromCometBlock(ctx, block, blockRes) n := hexutil.Uint(len(ethMsgs)) return &n } // EthBlockByNumber returns the Ethereum Block identified by number. -func (b *Backend) EthBlockByNumber(blockNum types.BlockNumber) (*ethtypes.Block, error) { - resBlock, err := b.CometBlockByNumber(blockNum) +func (b *Backend) EthBlockByNumber(ctx context.Context, blockNum types.BlockNumber) (result *ethtypes.Block, err error) { + ctx, span := tracer.Start(ctx, "EthBlockByNumber", trace.WithAttributes(attribute.Int64("blockNum", blockNum.Int64()))) + defer func() { evmtrace.EndSpanErr(span, err) }() + + resBlock, err := b.CometBlockByNumber(ctx, blockNum) if err != nil { return nil, err } @@ -159,29 +181,33 @@ func (b *Backend) EthBlockByNumber(blockNum types.BlockNumber) (*ethtypes.Block, return nil, fmt.Errorf("block not found for height %d", blockNum) } - blockRes, err := b.RPCClient.BlockResults(b.Ctx, &resBlock.Block.Height) + blockRes, err := b.RPCClient.BlockResults(ctx, &resBlock.Block.Height) if err != nil { return nil, fmt.Errorf("block result not found for height %d", resBlock.Block.Height) } - ethBlock, err := b.EthBlockFromCometBlock(resBlock, blockRes) + result, err = b.EthBlockFromCometBlock(ctx, resBlock, blockRes) if err != nil { return nil, fmt.Errorf("failed to get eth block from comet block: %w", err) } - return ethBlock, nil + return result, nil } // GetBlockReceipts returns the receipts for a given block number or hash. func (b *Backend) GetBlockReceipts( + ctx context.Context, blockNrOrHash types.BlockNumberOrHash, -) ([]map[string]interface{}, error) { - blockNum, err := b.BlockNumberFromComet(blockNrOrHash) +) (result []map[string]interface{}, err error) { + ctx, span := tracer.Start(ctx, "GetBlockReceipts", trace.WithAttributes(attribute.String("blockNrOrHash", unwrapBlockNOrHash(blockNrOrHash)))) + defer func() { evmtrace.EndSpanErr(span, err) }() + + blockNum, err := b.BlockNumberFromComet(ctx, blockNrOrHash) if err != nil { return nil, fmt.Errorf("failed to get block number from hash: %w", err) } - resBlock, err := b.CometBlockByNumber(blockNum) + resBlock, err := b.CometBlockByNumber(ctx, blockNum) if err != nil { return nil, fmt.Errorf("failed to get block by number: %w", err) } @@ -190,19 +216,19 @@ func (b *Backend) GetBlockReceipts( return nil, fmt.Errorf("block not found for height %d", *blockNum.CmtHeight()) } - blockRes, err := b.RPCClient.BlockResults(b.Ctx, blockNum.CmtHeight()) + blockRes, err := b.RPCClient.BlockResults(ctx, blockNum.CmtHeight()) if err != nil { return nil, fmt.Errorf("block result not found for height %d", resBlock.Block.Height) } - msgs := b.EthMsgsFromCometBlock(resBlock, blockRes) + msgs := b.EthMsgsFromCometBlock(ctx, resBlock, blockRes) - receipts, err := b.ReceiptsFromCometBlock(resBlock, blockRes, msgs) + receipts, err := b.ReceiptsFromCometBlock(ctx, resBlock, blockRes, msgs) if err != nil { return nil, fmt.Errorf("failed to get receipts from comet block: %w, ", err) } - result := make([]map[string]interface{}, len(msgs)) + result = make([]map[string]interface{}, len(msgs)) for i, msg := range msgs { var signer ethtypes.Signer tx := msg.AsTransaction() diff --git a/rpc/backend/call_tx.go b/rpc/backend/call_tx.go index 217830ff..071ecbc9 100644 --- a/rpc/backend/call_tx.go +++ b/rpc/backend/call_tx.go @@ -6,34 +6,36 @@ import ( "encoding/json" "fmt" "math/big" - "strings" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/pkg/errors" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - "github.com/cosmos/evm/mempool" + "github.com/cosmos/evm/mempool/txpool" rpctypes "github.com/cosmos/evm/rpc/types" + evmtrace "github.com/cosmos/evm/trace" evmtypes "github.com/cosmos/evm/x/vm/types" - errorsmod "cosmossdk.io/errors" - - "github.com/cosmos/cosmos-sdk/client/flags" sdk "github.com/cosmos/cosmos-sdk/types" ) // Resend accepts an existing transaction and a new gas price and limit. It will remove // the given transaction from the pool and reinsert it with the new gas price and limit. -func (b *Backend) Resend(args evmtypes.TransactionArgs, gasPrice *hexutil.Big, gasLimit *hexutil.Uint64) (common.Hash, error) { +func (b *Backend) Resend(ctx context.Context, args evmtypes.TransactionArgs, gasPrice *hexutil.Big, gasLimit *hexutil.Uint64) (result common.Hash, err error) { + ctx, span := tracer.Start(ctx, "Resend", trace.WithAttributes(attribute.String("from", args.GetFrom().Hex()))) + defer func() { evmtrace.EndSpanErr(span, err) }() + if args.Nonce == nil { return common.Hash{}, fmt.Errorf("missing transaction nonce in transaction spec") } - args, err := b.SetTxDefaults(args) + args, err = b.SetTxDefaults(ctx, args) if err != nil { return common.Hash{}, err } @@ -62,15 +64,15 @@ func (b *Backend) Resend(args evmtypes.TransactionArgs, gasPrice *hexutil.Big, g return common.Hash{}, err } - pending, err := b.PendingTransactions() + pending, err := b.PendingTransactions(ctx) if err != nil { return common.Hash{}, err } - for _, tx := range pending { + for _, txItem := range pending { // FIXME does Resend api possible at all? https://github.com/evmos/ethermint/issues/905 - p, err := evmtypes.UnwrapEthereumMsg(tx, common.Hash{}) - if err != nil { + p, unwrapErr := evmtypes.UnwrapEthereumMsg(txItem, common.Hash{}) + if unwrapErr != nil { // not valid ethereum tx continue } @@ -78,8 +80,8 @@ func (b *Backend) Resend(args evmtypes.TransactionArgs, gasPrice *hexutil.Big, g pTx := p.AsTransaction() wantSigHash := signer.Hash(matchTx) - pFrom, err := ethtypes.Sender(signer, pTx) - if err != nil { + pFrom, senderErr := ethtypes.Sender(signer, pTx) + if senderErr != nil { continue } @@ -92,7 +94,7 @@ func (b *Backend) Resend(args evmtypes.TransactionArgs, gasPrice *hexutil.Big, g args.Gas = gasLimit } - return b.SendTransaction(args) // TODO: this calls SetTxDefaults again, refactor to avoid calling it twice + return b.SendTransaction(ctx, args) // TODO: this calls SetTxDefaults again, refactor to avoid calling it twice } } @@ -100,7 +102,10 @@ func (b *Backend) Resend(args evmtypes.TransactionArgs, gasPrice *hexutil.Big, g } // SendRawTransaction send a raw Ethereum transaction. -func (b *Backend) SendRawTransaction(data hexutil.Bytes) (common.Hash, error) { +func (b *Backend) SendRawTransaction(ctx context.Context, data hexutil.Bytes) (result common.Hash, err error) { + ctx, span := tracer.Start(ctx, "SendRawTransaction") + defer func() { evmtrace.EndSpanErr(span, err) }() + // RLP decode raw transaction bytes tx := ðtypes.Transaction{} if err := tx.UnmarshalBinary(data); err != nil { @@ -108,6 +113,8 @@ func (b *Backend) SendRawTransaction(data hexutil.Bytes) (common.Hash, error) { return common.Hash{}, err } + span.SetAttributes(attribute.String("tx_hash", tx.Hash().Hex())) + // check the local node config in case unprotected txs are disabled if !b.UnprotectedAllowed() { if !tx.Protected() { @@ -139,61 +146,43 @@ func (b *Backend) SendRawTransaction(data hexutil.Bytes) (common.Hash, error) { return common.Hash{}, fmt.Errorf("failed to build cosmos tx: %w", err) } - // Encode transaction by default Tx encoder - txBytes, err := b.ClientCtx.TxConfig.TxEncoder()(cosmosTx) - if err != nil { - b.Logger.Error("failed to encode eth tx using default encoder", "error", err.Error()) - return common.Hash{}, fmt.Errorf("failed to encode transaction: %w", err) - } - - txHash := ethereumTx.AsTransaction().Hash() - - syncCtx := b.ClientCtx.WithBroadcastMode(flags.BroadcastSync) - rsp, err := syncCtx.BroadcastTx(txBytes) - if rsp != nil && rsp.Code != 0 { - err = errorsmod.ABCIError(rsp.Codespace, rsp.Code, rsp.RawLog) - } - if err != nil { - // Check if this is a nonce gap error that was successfully queued - 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 - } + txHash := tx.Hash() - // SendRawTransaction does not return error when committed nonce <= tx.Nonce < pending nonce - return txHash, nil + // User-submitted RPC txs should get "already known" instead of a second insert. + if b.Mempool != nil { + if pool := b.Mempool.GetTxPool(); pool != nil && pool.Has(txHash) { + return txHash, txpool.ErrAlreadyKnown } + } - b.Logger.Error("failed to broadcast tx", "error", err.Error()) - return txHash, fmt.Errorf("failed to broadcast transaction: %w", err) + // publish tx directly to app-side mempool, avoiding broadcasting to + // consensus layer. + // we are directly calling into the mempool rather than the ABCI + // handler for InsertTx, since the ABCI handler obfuscates the error's + // returned via codes, and we would like to have the full error to + // return to clients. + if err = b.Mempool.Insert(ctx, cosmosTx); err != nil { + // no need for special error handling like in the broadcast tx case + // since this is coming directly from the evm mempool insert. + return common.Hash{}, err } + b.TrackTxIfSupported(txHash) + return txHash, nil } // SetTxDefaults populates tx message with default values in case they are not // provided on the args -func (b *Backend) SetTxDefaults(args evmtypes.TransactionArgs) (evmtypes.TransactionArgs, error) { +func (b *Backend) SetTxDefaults(ctx context.Context, args evmtypes.TransactionArgs) (result evmtypes.TransactionArgs, err error) { + ctx, span := tracer.Start(ctx, "SetTxDefaults") + defer func() { evmtrace.EndSpanErr(span, err) }() + if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) { return args, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") } - head, _ := b.CurrentHeader() // #nosec G703 -- no need to check error cause we're already checking that head == nil + head, _ := b.CurrentHeader(ctx) // #nosec G703 -- no need to check error cause we're already checking that head == nil if head == nil { return args, errors.New("latest header is nil") } @@ -204,7 +193,7 @@ func (b *Backend) SetTxDefaults(args evmtypes.TransactionArgs) (evmtypes.Transac // In this clause, user left some fields unspecified. if head.BaseFee != nil && args.GasPrice == nil { if args.MaxPriorityFeePerGas == nil { - tip, err := b.SuggestGasTipCap(head.BaseFee) + tip, err := b.SuggestGasTipCap(ctx, head.BaseFee) if err != nil { return args, err } @@ -228,7 +217,7 @@ func (b *Backend) SetTxDefaults(args evmtypes.TransactionArgs) (evmtypes.Transac } if args.GasPrice == nil { - price, err := b.SuggestGasTipCap(head.BaseFee) + price, err := b.SuggestGasTipCap(ctx, head.BaseFee) if err != nil { return args, err } @@ -254,7 +243,7 @@ func (b *Backend) SetTxDefaults(args evmtypes.TransactionArgs) (evmtypes.Transac if args.Nonce == nil { // get the nonce from the account retriever // ignore error in case tge account doesn't exist yet - nonce, _ := b.getAccountNonce(*args.From, true, 0, b.Logger) // #nosec G703s + nonce, _ := b.getAccountNonce(ctx, *args.From, true, 0, b.Logger) // #nosec G703s args.Nonce = (*hexutil.Uint64)(&nonce) } @@ -299,7 +288,8 @@ func (b *Backend) SetTxDefaults(args evmtypes.TransactionArgs) (evmtypes.Transac } blockNr := rpctypes.NewBlockNumber(big.NewInt(0)) - estimated, err := b.EstimateGas(callArgs, &blockNr) + blockNrOrHash := rpctypes.BlockNumberOrHash{BlockNumber: &blockNr} + estimated, err := b.EstimateGas(ctx, callArgs, &blockNrOrHash, nil) if err != nil { return args, err } @@ -316,12 +306,25 @@ func (b *Backend) SetTxDefaults(args evmtypes.TransactionArgs) (evmtypes.Transac // EstimateGas returns an estimate of gas usage for the given smart contract call. func (b *Backend) EstimateGas( + ctx context.Context, args evmtypes.TransactionArgs, - blockNrOptional *rpctypes.BlockNumber, -) (hexutil.Uint64, error) { + blockNrOrHash *rpctypes.BlockNumberOrHash, + overrides *json.RawMessage, +) (result hexutil.Uint64, err error) { + var toAddr string + if args.To != nil { + toAddr = args.To.Hex() + } + ctx, span := tracer.Start(ctx, "EstimateGas", trace.WithAttributes(attribute.String("from", args.GetFrom().Hex()), attribute.String("to", toAddr))) + defer func() { evmtrace.EndSpanErr(span, err) }() + blockNr := rpctypes.EthPendingBlockNumber - if blockNrOptional != nil { - blockNr = *blockNrOptional + if blockNrOrHash != nil { + var err error + blockNr, err = b.BlockNumberFromComet(ctx, *blockNrOrHash) + if err != nil { + return 0, err + } } bz, err := json.Marshal(&args) @@ -329,23 +332,30 @@ func (b *Backend) EstimateGas( return 0, err } - header, err := b.CometHeaderByNumber(blockNr) + header, err := b.CometHeaderByNumber(ctx, blockNr) if err != nil { // the error message imitates geth behavior return 0, errors.New("header not found") } + var bzOverrides []byte + if overrides != nil { + bzOverrides = *overrides + } + req := evmtypes.EthCallRequest{ Args: bz, GasCap: b.RPCGasCap(), ProposerAddress: sdk.ConsAddress(header.Header.ProposerAddress), ChainId: b.EvmChainID.Int64(), + Overrides: bzOverrides, } - // From ContextWithHeight: if the provided height is 0, + // From NewContextWithHeight: if the provided height is 0, // it will return an empty context and the gRPC query will use // the latest block height for querying. - res, err := b.QueryClient.EstimateGas(rpctypes.ContextWithHeight(blockNr.Int64()), &req) + ctx = rpctypes.ContextWithHeight(ctx, blockNr.Int64()) + res, err := b.QueryClient.EstimateGas(ctx, &req) if err != nil { return 0, err } @@ -358,15 +368,23 @@ func (b *Backend) EstimateGas( // DoCall performs a simulated call operation through the evmtypes. It returns the // estimated gas used on the operation or an error if fails. func (b *Backend) DoCall( + ctx context.Context, args evmtypes.TransactionArgs, blockNr rpctypes.BlockNumber, overrides *json.RawMessage, -) (*evmtypes.MsgEthereumTxResponse, error) { +) (result *evmtypes.MsgEthereumTxResponse, err error) { + var toAddr string + if args.To != nil { + toAddr = args.To.Hex() + } + ctx, span := tracer.Start(ctx, "DoCall", trace.WithAttributes(attribute.String("from", args.GetFrom().Hex()), attribute.String("to", toAddr), attribute.Int64("blockNr", blockNr.Int64()))) + defer func() { evmtrace.EndSpanErr(span, err) }() + bz, err := json.Marshal(&args) if err != nil { return nil, err } - header, err := b.CometHeaderByNumber(blockNr) + header, err := b.CometHeaderByNumber(ctx, blockNr) if err != nil { // the error message imitates geth behavior return nil, errors.New("header not found") @@ -385,10 +403,10 @@ func (b *Backend) DoCall( Overrides: bzOverrides, } - // From ContextWithHeight: if the provided height is 0, + // From NewContextWithHeight: if the provided height is 0, // it will return an empty context and the gRPC query will use // the latest block height for querying. - ctx := rpctypes.ContextWithHeight(blockNr.Int64()) + ctx = rpctypes.ContextWithHeight(ctx, blockNr.Int64()) timeout := b.RPCEVMTimeout() // Setup context so it may be canceled the call has completed @@ -417,37 +435,36 @@ func (b *Backend) DoCall( } // GasPrice returns the current gas price based on Cosmos EVM' gas price oracle. -func (b *Backend) GasPrice() (*hexutil.Big, error) { - var ( - result *big.Int - err error - ) +func (b *Backend) GasPrice(ctx context.Context) (result *hexutil.Big, err error) { + ctx, span := tracer.Start(ctx, "GasPrice") + defer func() { evmtrace.EndSpanErr(span, err) }() - head, err := b.CurrentHeader() + head, err := b.CurrentHeader(ctx) if err != nil { return nil, err } + var gasPrice *big.Int if head.BaseFee != nil { - result, err = b.SuggestGasTipCap(head.BaseFee) + gasPrice, err = b.SuggestGasTipCap(ctx, head.BaseFee) if err != nil { return nil, err } - result = result.Add(result, head.BaseFee) + gasPrice = gasPrice.Add(gasPrice, head.BaseFee) } else { - result = b.RPCMinGasPrice() + gasPrice = b.RPCMinGasPrice() } // return at least GlobalMinGasPrice from FeeMarket module - minGasPrice, err := b.GlobalMinGasPrice() + minGasPrice, err := b.GlobalMinGasPrice(ctx) if err != nil { return nil, err } - if result.Cmp(minGasPrice) < 0 { - result = minGasPrice + if gasPrice.Cmp(minGasPrice) < 0 { + gasPrice = minGasPrice } - return (*hexutil.Big)(result), nil + return (*hexutil.Big)(gasPrice), nil } // handleRevertError returns revert related error. diff --git a/rpc/backend/chain_info.go b/rpc/backend/chain_info.go index 3686a325..ad71ad7a 100644 --- a/rpc/backend/chain_info.go +++ b/rpc/backend/chain_info.go @@ -1,6 +1,7 @@ package backend import ( + "context" "fmt" gomath "math" "math/big" @@ -12,11 +13,14 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" "github.com/pkg/errors" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" cmtrpcclient "github.com/cometbft/cometbft/rpc/client" cmtrpctypes "github.com/cometbft/cometbft/rpc/core/types" rpctypes "github.com/cosmos/evm/rpc/types" + evmtrace "github.com/cosmos/evm/trace" feemarkettypes "github.com/cosmos/evm/x/feemarket/types" evmtypes "github.com/cosmos/evm/x/vm/types" @@ -27,9 +31,12 @@ import ( ) // ChainID is the EIP-155 replay-protection chain id for the current ethereum chain config. -func (b *Backend) ChainID() (*hexutil.Big, error) { +func (b *Backend) ChainID(ctx context.Context) (result *hexutil.Big, err error) { + ctx, span := tracer.Start(ctx, "ChainID") + defer func() { evmtrace.EndSpanErr(span, err) }() + // if current block is at or past the EIP-155 replay-protection fork block, return EvmChainID from config - bn, err := b.BlockNumber() + bn, err := b.BlockNumber(ctx) if err != nil { b.Logger.Debug("failed to fetch latest block number", "error", err.Error()) return (*hexutil.Big)(b.EvmChainID), nil @@ -48,8 +55,11 @@ func (b *Backend) ChainConfig() *params.ChainConfig { } // GlobalMinGasPrice returns MinGasPrice param from FeeMarket -func (b *Backend) GlobalMinGasPrice() (*big.Int, error) { - res, err := b.QueryClient.GlobalMinGasPrice(b.Ctx, &evmtypes.QueryGlobalMinGasPriceRequest{}) +func (b *Backend) GlobalMinGasPrice(ctx context.Context) (result *big.Int, err error) { + ctx, span := tracer.Start(ctx, "GlobalMinGasPrice") + defer func() { evmtrace.EndSpanErr(span, err) }() + + res, err := b.QueryClient.GlobalMinGasPrice(ctx, &evmtypes.QueryGlobalMinGasPriceRequest{}) if err != nil { return nil, err } @@ -63,9 +73,13 @@ func (b *Backend) GlobalMinGasPrice() (*big.Int, error) { // If the base fee is not enabled globally, the query returns nil. // If the London hard fork is not activated at the current height, the query will // return nil. -func (b *Backend) BaseFee(blockRes *cmtrpctypes.ResultBlockResults) (*big.Int, error) { +func (b *Backend) BaseFee(ctx context.Context, blockRes *cmtrpctypes.ResultBlockResults) (result *big.Int, err error) { + ctx, span := tracer.Start(ctx, "BaseFee", trace.WithAttributes(attribute.Int64("height", blockRes.Height))) + defer func() { evmtrace.EndSpanErr(span, err) }() + // return BaseFee if London hard fork is activated and feemarket is enabled - res, err := b.QueryClient.BaseFee(rpctypes.ContextWithHeight(blockRes.Height), &evmtypes.QueryBaseFeeRequest{}) + ctx = rpctypes.ContextWithHeight(ctx, blockRes.Height) + res, err := b.QueryClient.BaseFee(ctx, &evmtypes.QueryBaseFeeRequest{}) if err != nil || res.BaseFee == nil { // we can't tell if it's london HF not enabled or the state is pruned, // in either case, we'll fallback to parsing from begin blocker event, @@ -93,28 +107,34 @@ func (b *Backend) BaseFee(blockRes *cmtrpctypes.ResultBlockResults) (*big.Int, e // CurrentHeader returns the latest block header // This will return error as per node configuration // if the ABCI responses are discarded ('discard_abci_responses' config param) -func (b *Backend) CurrentHeader() (*ethtypes.Header, error) { - return b.HeaderByNumber(rpctypes.EthLatestBlockNumber) +func (b *Backend) CurrentHeader(ctx context.Context) (result *ethtypes.Header, err error) { + ctx, span := tracer.Start(ctx, "CurrentHeader") + defer func() { evmtrace.EndSpanErr(span, err) }() + + return b.HeaderByNumber(ctx, rpctypes.EthLatestBlockNumber) } // PendingTransactions returns the transactions that are in the transaction pool // and have a from address that is one of the accounts this node manages. -func (b *Backend) PendingTransactions() ([]*sdk.Tx, error) { +func (b *Backend) PendingTransactions(ctx context.Context) (result []*sdk.Tx, err error) { + ctx, span := tracer.Start(ctx, "PendingTransactions") + defer func() { evmtrace.EndSpanErr(span, err) }() + mc, ok := b.ClientCtx.Client.(cmtrpcclient.MempoolClient) if !ok { return nil, errors.New("invalid rpc client") } - res, err := mc.UnconfirmedTxs(b.Ctx, nil) + res, err := mc.UnconfirmedTxs(ctx, nil) if err != nil { return nil, err } - result := make([]*sdk.Tx, 0, len(res.Txs)) + result = make([]*sdk.Tx, 0, len(res.Txs)) for _, txBz := range res.Txs { - tx, err := b.ClientCtx.TxConfig.TxDecoder()(txBz) - if err != nil { - return nil, err + tx, decodeErr := b.ClientCtx.TxConfig.TxDecoder()(txBz) + if decodeErr != nil { + return nil, decodeErr } result = append(result, &tx) } @@ -123,13 +143,16 @@ func (b *Backend) PendingTransactions() ([]*sdk.Tx, error) { } // GetCoinbase is the address that staking rewards will be send to (alias for Etherbase). -func (b *Backend) GetCoinbase() (sdk.AccAddress, error) { +func (b *Backend) GetCoinbase(ctx context.Context) (result sdk.AccAddress, err error) { + ctx, span := tracer.Start(ctx, "GetCoinbase") + defer func() { evmtrace.EndSpanErr(span, err) }() + node, err := b.ClientCtx.GetNode() if err != nil { return nil, err } - status, err := node.Status(b.Ctx) + status, err := node.Status(ctx) if err != nil { return nil, err } @@ -138,7 +161,7 @@ func (b *Backend) GetCoinbase() (sdk.AccAddress, error) { ConsAddress: sdk.ConsAddress(status.ValidatorInfo.Address).String(), } - res, err := b.QueryClient.ValidatorAccount(b.Ctx, req) + res, err := b.QueryClient.ValidatorAccount(ctx, req) if err != nil { return nil, err } @@ -154,10 +177,14 @@ var ( // FeeHistory returns data relevant for fee estimation based on the specified range of blocks. func (b *Backend) FeeHistory( + ctx context.Context, userBlockCount math.HexOrDecimal64, // number blocks to fetch, maximum is 100 lastBlock rpc.BlockNumber, // the block to start search , to oldest rewardPercentiles []float64, // percentiles to fetch reward -) (*rpctypes.FeeHistoryResult, error) { +) (_ *rpctypes.FeeHistoryResult, err error) { + //nolint:gosec // unlikely + ctx, span := tracer.Start(ctx, "FeeHistory", trace.WithAttributes(attribute.Int64("blockCount", int64(userBlockCount)), attribute.Int64("lastBlock", int64(lastBlock)))) + defer func() { evmtrace.EndSpanErr(span, err) }() for i, p := range rewardPercentiles { if p < 0 || p > 100 { return nil, fmt.Errorf("%w: %f", errInvalidPercentile, p) @@ -166,7 +193,7 @@ func (b *Backend) FeeHistory( return nil, fmt.Errorf("%w: #%d:%f > #%d:%f", errInvalidPercentile, i-1, rewardPercentiles[i-1], i, p) } } - blkNumber, err := b.BlockNumber() + blkNumber, err := b.BlockNumber(ctx) if err != nil { return nil, err } @@ -241,21 +268,21 @@ func (b *Backend) FeeHistory( // fetch block // CometBFT block blockNum := rpctypes.BlockNumber(blockStart + int64(index)) - cometBlock, err := b.CometBlockByNumber(blockNum) + cometBlock, err := b.CometBlockByNumber(ctx, blockNum) if cometBlock == nil { chanErr <- err return } // eth block - ethBlock, err := b.GetBlockByNumber(blockNum, true) + ethBlock, err := b.GetBlockByNumber(ctx, blockNum, true) if ethBlock == nil { chanErr <- err return } // CometBFT block result - cometBlockResult, err := b.CometBlockResultByNumber(&cometBlock.Block.Height) + cometBlockResult, err := b.CometBlockResultByNumber(ctx, &cometBlock.Block.Height) if cometBlockResult == nil { b.Logger.Debug("block result not found", "height", cometBlock.Block.Height, "error", err.Error()) chanErr <- err @@ -263,7 +290,7 @@ func (b *Backend) FeeHistory( } oneFeeHistory := rpctypes.OneFeeHistory{} - err = b.ProcessBlocker(cometBlock, ðBlock, rewardPercentiles, cometBlockResult, &oneFeeHistory) + err = b.ProcessBlocker(ctx, cometBlock, ðBlock, rewardPercentiles, cometBlockResult, &oneFeeHistory) if err != nil { chanErr <- err return @@ -320,13 +347,15 @@ func (b *Backend) FeeHistory( // SuggestGasTipCap returns the suggested tip cap // Although we don't support tx prioritization yet, but we return a positive value to help client to // mitigate the base fee changes. -func (b *Backend) SuggestGasTipCap(baseFee *big.Int) (*big.Int, error) { +func (b *Backend) SuggestGasTipCap(ctx context.Context, baseFee *big.Int) (_ *big.Int, err error) { + ctx, span := tracer.Start(ctx, "SuggestGasTipCap") + defer func() { evmtrace.EndSpanErr(span, err) }() if baseFee == nil { // london hardfork not enabled or feemarket not enabled return big.NewInt(0), nil } - params, err := b.QueryClient.FeeMarket.Params(b.Ctx, &feemarkettypes.QueryParamsRequest{}) + params, err := b.QueryClient.FeeMarket.Params(ctx, &feemarkettypes.QueryParamsRequest{}) if err != nil { return nil, err } diff --git a/rpc/backend/comet.go b/rpc/backend/comet.go index 3b295b08..311250a1 100644 --- a/rpc/backend/comet.go +++ b/rpc/backend/comet.go @@ -1,25 +1,32 @@ package backend import ( + "context" "fmt" "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" cmtrpctypes "github.com/cometbft/cometbft/rpc/core/types" rpctypes "github.com/cosmos/evm/rpc/types" + evmtrace "github.com/cosmos/evm/trace" "github.com/cosmos/evm/utils" ) // CometBlockByNumber returns a CometBFT-formatted block for a given // block number -func (b *Backend) CometBlockByNumber(blockNum rpctypes.BlockNumber) (*cmtrpctypes.ResultBlock, error) { - height, err := b.getHeightByBlockNum(blockNum) +func (b *Backend) CometBlockByNumber(ctx context.Context, blockNum rpctypes.BlockNumber) (result *cmtrpctypes.ResultBlock, err error) { + ctx, span := tracer.Start(ctx, "CometBlockByNumber", trace.WithAttributes(attribute.Int64("blockNum", blockNum.Int64()))) + defer func() { evmtrace.EndSpanErr(span, err) }() + + height, err := b.getHeightByBlockNum(ctx, blockNum) if err != nil { return nil, err } - resBlock, err := b.RPCClient.Block(b.Ctx, &height) + resBlock, err := b.RPCClient.Block(ctx, &height) if err != nil { b.Logger.Debug("cometbft client failed to get block", "height", height, "error", err.Error()) return nil, err @@ -35,31 +42,44 @@ func (b *Backend) CometBlockByNumber(blockNum rpctypes.BlockNumber) (*cmtrpctype // CometHeaderByNumber returns a CometBFT-formatted header for a given // block number -func (b *Backend) CometHeaderByNumber(blockNum rpctypes.BlockNumber) (*cmtrpctypes.ResultHeader, error) { - height, err := b.getHeightByBlockNum(blockNum) +func (b *Backend) CometHeaderByNumber(ctx context.Context, blockNum rpctypes.BlockNumber) (result *cmtrpctypes.ResultHeader, err error) { + ctx, span := tracer.Start(ctx, "CometHeaderByNumber", trace.WithAttributes(attribute.Int64("blockNum", blockNum.Int64()))) + defer func() { evmtrace.EndSpanErr(span, err) }() + + height, err := b.getHeightByBlockNum(ctx, blockNum) if err != nil { return nil, err } - return b.RPCClient.Header(b.Ctx, &height) + return b.RPCClient.Header(ctx, &height) } // CometBlockResultByNumber returns a CometBFT-formatted block result // by block number -func (b *Backend) CometBlockResultByNumber(height *int64) (*cmtrpctypes.ResultBlockResults, error) { +func (b *Backend) CometBlockResultByNumber(ctx context.Context, height *int64) (result *cmtrpctypes.ResultBlockResults, err error) { + var heightAttr int64 + if height != nil { + heightAttr = *height + } + ctx, span := tracer.Start(ctx, "CometBlockResultByNumber", trace.WithAttributes(attribute.Int64("height", heightAttr))) + defer func() { evmtrace.EndSpanErr(span, err) }() + if height != nil && *height == 0 { height = nil } - res, err := b.RPCClient.BlockResults(b.Ctx, height) + res, err := b.RPCClient.BlockResults(ctx, height) if err != nil { - return nil, fmt.Errorf("failed to fetch block result from CometBFT %d: %w", *height, err) + return nil, fmt.Errorf("failed to fetch block result from CometBFT %d: %w", heightAttr, err) } return res, nil } // CometBlockByHash returns a CometBFT-formatted block by block number -func (b *Backend) CometBlockByHash(blockHash common.Hash) (*cmtrpctypes.ResultBlock, error) { - resBlock, err := b.RPCClient.BlockByHash(b.Ctx, blockHash.Bytes()) +func (b *Backend) CometBlockByHash(ctx context.Context, blockHash common.Hash) (result *cmtrpctypes.ResultBlock, err error) { + ctx, span := tracer.Start(ctx, "CometBlockByHash", trace.WithAttributes(attribute.String("blockHash", blockHash.Hex()))) + defer func() { evmtrace.EndSpanErr(span, err) }() + + resBlock, err := b.RPCClient.BlockByHash(ctx, blockHash.Bytes()) if err != nil { b.Logger.Debug("CometBFT client failed to get block", "blockHash", blockHash.Hex(), "error", err.Error()) return nil, err @@ -73,9 +93,12 @@ func (b *Backend) CometBlockByHash(blockHash common.Hash) (*cmtrpctypes.ResultBl return resBlock, nil } -func (b *Backend) getHeightByBlockNum(blockNum rpctypes.BlockNumber) (int64, error) { +func (b *Backend) getHeightByBlockNum(ctx context.Context, blockNum rpctypes.BlockNumber) (height int64, err error) { + ctx, span := tracer.Start(ctx, "getHeightByBlockNum", trace.WithAttributes(attribute.Int64("blockNum", blockNum.Int64()))) + defer func() { evmtrace.EndSpanErr(span, err) }() + if blockNum == rpctypes.EthEarliestBlockNumber { - status, err := b.ClientCtx.Client.Status(b.Ctx) + status, err := b.ClientCtx.Client.Status(ctx) if err != nil { return 0, errors.New("failed to get earliest block height") } @@ -83,7 +106,7 @@ func (b *Backend) getHeightByBlockNum(blockNum rpctypes.BlockNumber) (int64, err return status.SyncInfo.EarliestBlockHeight, nil } - height := blockNum.Int64() + height = blockNum.Int64() if height <= 0 { // In cometBFT, LatestBlockNumber, FinalizedBlockNumber, SafeBlockNumber all map to the latest block height. // Fetch the latest block number from the app state, more accurate than the CometBFT block store state. @@ -91,7 +114,7 @@ func (b *Backend) getHeightByBlockNum(blockNum rpctypes.BlockNumber) (int64, err // For PendingBlockNumber, we alsoe returns the latest block height. // The reason is that CometBFT does not have the concept of pending block, // and the application state is only updated when a block is committed. - n, err := b.BlockNumber() + n, err := b.BlockNumber(ctx) if err != nil { return 0, err } diff --git a/rpc/backend/comet_test.go b/rpc/backend/comet_test.go new file mode 100644 index 00000000..83d8b046 --- /dev/null +++ b/rpc/backend/comet_test.go @@ -0,0 +1,79 @@ +package backend + +import ( + "context" + "errors" + "testing" + + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + tmrpctypes "github.com/cometbft/cometbft/rpc/core/types" + + "github.com/cosmos/evm/rpc/backend/mocks" +) + +func TestCometBlockResultByNumber_NilHeightErrorPath(t *testing.T) { + testCases := []struct { + name string + height *int64 + rpcErr error + expectErr bool + }{ + { + name: "nil height, BlockResults succeeds", + height: nil, + rpcErr: nil, + expectErr: false, + }, + { + name: "non-zero height, BlockResults succeeds", + height: func() *int64 { h := int64(5); return &h }(), + rpcErr: nil, + expectErr: false, + }, + { + name: "zero height remapped to nil, BlockResults errors - must not panic", + height: func() *int64 { h := int64(0); return &h }(), + rpcErr: errors.New("connection timeout"), + expectErr: true, + }, + { + name: "nil height, BlockResults errors", + height: nil, + rpcErr: errors.New("pruned state"), + expectErr: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + backend := setupMockBackend(t) + mockClient := backend.ClientCtx.Client.(*mocks.Client) + + // The function remaps height=0 to nil before calling BlockResults, + // so always mock with nil when input is 0. + var mockHeight *int64 + if tc.height != nil && *tc.height != 0 { + mockHeight = tc.height + } + + if tc.rpcErr != nil { + mockClient.On("BlockResults", mock.Anything, mockHeight). + Return((*tmrpctypes.ResultBlockResults)(nil), tc.rpcErr).Once() + } else { + mockClient.On("BlockResults", mock.Anything, mockHeight). + Return(&tmrpctypes.ResultBlockResults{Height: 1}, nil).Once() + } + + require.NotPanics(t, func() { + _, err := backend.CometBlockResultByNumber(context.Background(), tc.height) + if tc.expectErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + }) + } +} diff --git a/rpc/backend/comet_to_eth.go b/rpc/backend/comet_to_eth.go index 8b484772..d4e90f21 100644 --- a/rpc/backend/comet_to_eth.go +++ b/rpc/backend/comet_to_eth.go @@ -1,6 +1,7 @@ package backend import ( + "context" "fmt" "math/big" @@ -10,10 +11,13 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/trie" "github.com/pkg/errors" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" cmtrpctypes "github.com/cometbft/cometbft/rpc/core/types" rpctypes "github.com/cosmos/evm/rpc/types" + evmtrace "github.com/cosmos/evm/trace" evmtypes "github.com/cosmos/evm/x/vm/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -22,10 +26,14 @@ import ( // RPCBlockFromCometBlock returns a JSON-RPC compatible Ethereum block from a // given CometBFT block and its block result. func (b *Backend) RPCHeaderFromCometBlock( + ctx context.Context, resBlock *cmtrpctypes.ResultBlock, blockRes *cmtrpctypes.ResultBlockResults, -) (map[string]interface{}, error) { - ethBlock, err := b.EthBlockFromCometBlock(resBlock, blockRes) +) (result map[string]interface{}, err error) { + ctx, span := tracer.Start(ctx, "RPCHeaderFromCometBlock") + defer func() { evmtrace.EndSpanErr(span, err) }() + + ethBlock, err := b.EthBlockFromCometBlock(ctx, resBlock, blockRes) if err != nil { return nil, fmt.Errorf("failed to get rpc block from comet block: %w", err) } @@ -36,12 +44,16 @@ func (b *Backend) RPCHeaderFromCometBlock( // RPCBlockFromCometBlock returns a JSON-RPC compatible Ethereum block from a // given CometBFT block and its block result. func (b *Backend) RPCBlockFromCometBlock( + ctx context.Context, resBlock *cmtrpctypes.ResultBlock, blockRes *cmtrpctypes.ResultBlockResults, fullTx bool, -) (map[string]interface{}, error) { - msgs := b.EthMsgsFromCometBlock(resBlock, blockRes) - ethBlock, err := b.EthBlockFromCometBlock(resBlock, blockRes) +) (result map[string]interface{}, err error) { + ctx, span := tracer.Start(ctx, "RPCBlockFromCometBlock") + defer func() { evmtrace.EndSpanErr(span, err) }() + + msgs := b.EthMsgsFromCometBlock(ctx, resBlock, blockRes) + ethBlock, err := b.EthBlockFromCometBlock(ctx, resBlock, blockRes) if err != nil { return nil, fmt.Errorf("failed to get rpc block from comet block: %w", err) } @@ -50,12 +62,15 @@ func (b *Backend) RPCBlockFromCometBlock( } // BlockNumberFromComet returns the BlockNumber from BlockNumberOrHash -func (b *Backend) BlockNumberFromComet(blockNrOrHash rpctypes.BlockNumberOrHash) (rpctypes.BlockNumber, error) { +func (b *Backend) BlockNumberFromComet(ctx context.Context, blockNrOrHash rpctypes.BlockNumberOrHash) (result rpctypes.BlockNumber, err error) { + ctx, span := tracer.Start(ctx, "BlockNumberFromComet", trace.WithAttributes(attribute.String("blockNrOrHash", unwrapBlockNOrHash(blockNrOrHash)))) + defer func() { evmtrace.EndSpanErr(span, err) }() + switch { case blockNrOrHash.BlockHash == nil && blockNrOrHash.BlockNumber == nil: return rpctypes.EthEarliestBlockNumber, fmt.Errorf("types BlockHash and BlockNumber cannot be both nil") case blockNrOrHash.BlockHash != nil: - blockNumber, err := b.BlockNumberFromCometByHash(*blockNrOrHash.BlockHash) + blockNumber, err := b.BlockNumberFromCometByHash(ctx, *blockNrOrHash.BlockHash) if err != nil { return rpctypes.EthEarliestBlockNumber, err } @@ -68,8 +83,11 @@ func (b *Backend) BlockNumberFromComet(blockNrOrHash rpctypes.BlockNumberOrHash) } // BlockNumberFromCometByHash returns the block height of given block hash -func (b *Backend) BlockNumberFromCometByHash(blockHash common.Hash) (*big.Int, error) { - resHeader, err := b.RPCClient.HeaderByHash(b.Ctx, blockHash.Bytes()) +func (b *Backend) BlockNumberFromCometByHash(ctx context.Context, blockHash common.Hash) (result *big.Int, err error) { + ctx, span := tracer.Start(ctx, "BlockNumberFromCometByHash", trace.WithAttributes(attribute.String("blockHash", blockHash.Hex()))) + defer func() { evmtrace.EndSpanErr(span, err) }() + + resHeader, err := b.RPCClient.HeaderByHash(ctx, blockHash.Bytes()) if err != nil { return nil, err } @@ -85,9 +103,12 @@ func (b *Backend) BlockNumberFromCometByHash(blockHash common.Hash) (*big.Int, e // CometBFT block. It also ensures consistency over the correct txs indexes // across RPC endpoints func (b *Backend) EthMsgsFromCometBlock( + ctx context.Context, resBlock *cmtrpctypes.ResultBlock, blockRes *cmtrpctypes.ResultBlockResults, ) []*evmtypes.MsgEthereumTx { + _, span := tracer.Start(ctx, "EthMsgsFromCometBlock") + defer span.End() var result []*evmtypes.MsgEthereumTx block := resBlock.Block @@ -96,9 +117,8 @@ func (b *Backend) EthMsgsFromCometBlock( for i, tx := range block.Txs { // Check if tx exists on EVM by cross checking with blockResults: // - Include unsuccessful tx that exceeds block gas limit - // - Include unsuccessful tx that failed when committing changes to stateDB // - Exclude unsuccessful tx with any other error but ExceedBlockGasLimit - if !rpctypes.TxSucessOrExpectedFailure(txResults[i]) { + if !evmtypes.TxSucessOrExpectedFailure(txResults[i]) { b.Logger.Debug("invalid tx result code", "cosmos-hash", hexutil.Encode(tx.Hash())) continue } @@ -125,26 +145,30 @@ func (b *Backend) EthMsgsFromCometBlock( // RPCBlockFromCometBlock returns a JSON-RPC compatible Ethereum block from a // given CometBFT block and its block result. func (b *Backend) EthBlockFromCometBlock( + ctx context.Context, resBlock *cmtrpctypes.ResultBlock, blockRes *cmtrpctypes.ResultBlockResults, -) (*ethtypes.Block, error) { +) (result *ethtypes.Block, err error) { + ctx, span := tracer.Start(ctx, "EthBlockFromCometBlock") + defer func() { evmtrace.EndSpanErr(span, err) }() + cmtBlock := resBlock.Block // 1. get base fee - baseFee, err := b.BaseFee(blockRes) + baseFee, err := b.BaseFee(ctx, blockRes) if err != nil { // handle the error for pruned node. b.Logger.Error("failed to fetch Base Fee from prunned block. Check node prunning configuration", "height", cmtBlock.Height, "error", err) } // 2. get miner - miner, err := b.MinerFromCometBlock(resBlock) + miner, err := b.MinerFromCometBlock(ctx, resBlock) if err != nil { return nil, fmt.Errorf("failed to get miner(block proposer) address from comet block") } // 3. get block gasLimit - ctx := rpctypes.ContextWithHeight(cmtBlock.Height) + ctx = rpctypes.ContextWithHeight(ctx, cmtBlock.Height) gasLimit, err := rpctypes.BlockMaxGasFromConsensusParams(ctx, b.ClientCtx, cmtBlock.Height) if err != nil { b.Logger.Error("failed to query consensus params", "error", err.Error()) @@ -154,7 +178,7 @@ func (b *Backend) EthBlockFromCometBlock( ethHeader := rpctypes.MakeHeader(cmtBlock.Header, gasLimit, miner, baseFee) // 5. get MsgEthereumTxs - msgs := b.EthMsgsFromCometBlock(resBlock, blockRes) + msgs := b.EthMsgsFromCometBlock(ctx, resBlock, blockRes) txs := make([]*ethtypes.Transaction, len(msgs)) for i, ethMsg := range msgs { txs[i] = ethMsg.AsTransaction() @@ -168,7 +192,7 @@ func (b *Backend) EthBlockFromCometBlock( } // 7. receipts - receipts, err := b.ReceiptsFromCometBlock(resBlock, blockRes, msgs) + receipts, err := b.ReceiptsFromCometBlock(ctx, resBlock, blockRes, msgs) if err != nil { return nil, fmt.Errorf("failed to get receipts from comet block: %w", err) } @@ -191,8 +215,12 @@ func (b *Backend) EthBlockFromCometBlock( } func (b *Backend) MinerFromCometBlock( + ctx context.Context, resBlock *cmtrpctypes.ResultBlock, -) (common.Address, error) { +) (result common.Address, err error) { + ctx, span := tracer.Start(ctx, "MinerFromCometBlock") + defer func() { evmtrace.EndSpanErr(span, err) }() + cmtBlock := resBlock.Block req := &evmtypes.QueryValidatorAccountRequest{ @@ -201,7 +229,7 @@ func (b *Backend) MinerFromCometBlock( var validatorAccAddr sdk.AccAddress - ctx := rpctypes.ContextWithHeight(cmtBlock.Height) + ctx = rpctypes.ContextWithHeight(ctx, cmtBlock.Height) res, err := b.QueryClient.ValidatorAccount(ctx, req) if err != nil { b.Logger.Debug( @@ -223,11 +251,15 @@ func (b *Backend) MinerFromCometBlock( } func (b *Backend) ReceiptsFromCometBlock( + ctx context.Context, resBlock *cmtrpctypes.ResultBlock, blockRes *cmtrpctypes.ResultBlockResults, msgs []*evmtypes.MsgEthereumTx, -) ([]*ethtypes.Receipt, error) { - baseFee, err := b.BaseFee(blockRes) +) (result []*ethtypes.Receipt, err error) { + ctx, span := tracer.Start(ctx, "ReceiptsFromCometBlock") + defer func() { evmtrace.EndSpanErr(span, err) }() + + baseFee, err := b.BaseFee(ctx, blockRes) if err != nil { // handle the error for pruned node. b.Logger.Error("failed to fetch Base Fee from prunned block. Check node prunning configuration", "height", resBlock.Block.Height, "error", err) @@ -237,11 +269,18 @@ func (b *Backend) ReceiptsFromCometBlock( receipts := make([]*ethtypes.Receipt, len(msgs)) cumulatedGasUsed := uint64(0) for i, ethMsg := range msgs { - txResult, err := b.GetTxByEthHash(ethMsg.Hash()) + txResult, err := b.GetTxByEthHash(ctx, ethMsg.Hash()) if err != nil { return nil, fmt.Errorf("tx not found: hash=%s, error=%s", ethMsg.Hash(), err.Error()) } + // Resolve -1 sentinel: indexer hasn't assigned EthTxIndex yet. + // Use the loop index as the correct eth tx position, + // matching the existing fallback in GetTransactionByHash (tx_info.go). + if txResult.EthTxIndex == -1 { + txResult.EthTxIndex = int32(i) //#nosec G115 -- checked for int overflow already + } + cumulatedGasUsed += txResult.GasUsed var effectiveGasPrice *big.Int @@ -273,6 +312,15 @@ func (b *Backend) ReceiptsFromCometBlock( return nil, fmt.Errorf("failed to convert tx result to eth receipt: %w", err) } + if txResult.EthTxIndex == -1 { + var err error + // Fallback to find tx index by iterating all valid eth transactions + txResult.EthTxIndex, err = b.FindEthTxIndexByHash(ctx, ethMsg.Hash(), resBlock, blockRes) + if err != nil { + return nil, err + } + } + bloom := ethtypes.CreateBloom(ðtypes.Receipt{Logs: logs}) receipt := ðtypes.Receipt{ @@ -306,7 +354,10 @@ func (b *Backend) ReceiptsFromCometBlock( } // BlockBloom query block bloom filter from block results -func (b *Backend) BlockBloomFromCometBlock(blockRes *cmtrpctypes.ResultBlockResults) (ethtypes.Bloom, error) { +func (b *Backend) BlockBloomFromCometBlock(ctx context.Context, blockRes *cmtrpctypes.ResultBlockResults) (result ethtypes.Bloom, err error) { + _, span := tracer.Start(ctx, "BlockBloomFromCometBlock") + defer func() { evmtrace.EndSpanErr(span, err) }() + for _, event := range blockRes.FinalizeBlockEvents { if event.Type != evmtypes.EventTypeBlockBloom { continue diff --git a/rpc/backend/filters.go b/rpc/backend/filters.go index fe44ddee..7e079da1 100644 --- a/rpc/backend/filters.go +++ b/rpc/backend/filters.go @@ -1,27 +1,43 @@ package backend import ( + "context" + "github.com/ethereum/go-ethereum/common" ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/pkg/errors" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" + + evmtrace "github.com/cosmos/evm/trace" ) // GetLogs returns all the logs from all the ethereum transactions in a block. -func (b *Backend) GetLogs(hash common.Hash) ([][]*ethtypes.Log, error) { - resBlock, err := b.CometBlockByHash(hash) +func (b *Backend) GetLogs(ctx context.Context, hash common.Hash) (result [][]*ethtypes.Log, err error) { + ctx, span := tracer.Start(ctx, "GetLogs", trace.WithAttributes(attribute.String("hash", hash.Hex()))) + defer func() { evmtrace.EndSpanErr(span, err) }() + + resBlock, err := b.CometBlockByHash(ctx, hash) if err != nil { return nil, err } if resBlock == nil { return nil, errors.Errorf("block not found for hash %s", hash) } - return b.GetLogsByHeight(&resBlock.Block.Height) + return b.GetLogsByHeight(ctx, &resBlock.Block.Height) } // GetLogsByHeight returns all the logs from all the ethereum transactions in a block. -func (b *Backend) GetLogsByHeight(height *int64) ([][]*ethtypes.Log, error) { +func (b *Backend) GetLogsByHeight(ctx context.Context, height *int64) (result [][]*ethtypes.Log, err error) { + var heightAttr int64 + if height != nil { + heightAttr = *height + } + ctx, span := tracer.Start(ctx, "GetLogsByHeight", trace.WithAttributes(attribute.Int64("height", heightAttr))) + defer func() { evmtrace.EndSpanErr(span, err) }() + // NOTE: we query the state in case the tx result logs are not persisted after an upgrade. - blockRes, err := b.RPCClient.BlockResults(b.Ctx, height) + blockRes, err := b.RPCClient.BlockResults(ctx, height) if err != nil { return nil, err } diff --git a/rpc/backend/headers.go b/rpc/backend/headers.go index 14e466f4..ab9841bc 100644 --- a/rpc/backend/headers.go +++ b/rpc/backend/headers.go @@ -1,19 +1,26 @@ package backend import ( + "context" "fmt" "github.com/ethereum/go-ethereum/common" ethtypes "github.com/ethereum/go-ethereum/core/types" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" rpctypes "github.com/cosmos/evm/rpc/types" + evmtrace "github.com/cosmos/evm/trace" ) // GetBlockByNumber returns the JSON-RPC compatible Ethereum block identified by // block number. Depending on fullTx it either returns the full transaction // objects or if false only the hashes of the transactions. -func (b *Backend) GetHeaderByNumber(blockNum rpctypes.BlockNumber) (map[string]interface{}, error) { - resBlock, err := b.CometBlockByNumber(blockNum) +func (b *Backend) GetHeaderByNumber(ctx context.Context, blockNum rpctypes.BlockNumber) (result map[string]interface{}, err error) { + ctx, span := tracer.Start(ctx, "GetHeaderByNumber", trace.WithAttributes(attribute.Int64("blockNum", blockNum.Int64()))) + defer func() { evmtrace.EndSpanErr(span, err) }() + + resBlock, err := b.CometBlockByNumber(ctx, blockNum) if err != nil { return nil, nil } @@ -23,13 +30,13 @@ func (b *Backend) GetHeaderByNumber(blockNum rpctypes.BlockNumber) (map[string]i return nil, nil } - blockRes, err := b.RPCClient.BlockResults(b.Ctx, &resBlock.Block.Height) + blockRes, err := b.RPCClient.BlockResults(ctx, &resBlock.Block.Height) if err != nil { b.Logger.Debug("failed to fetch block result from CometBFT", "height", blockNum, "error", err.Error()) return nil, nil } - res, err := b.RPCHeaderFromCometBlock(resBlock, blockRes) + res, err := b.RPCHeaderFromCometBlock(ctx, resBlock, blockRes) if err != nil { b.Logger.Debug("RPCBlockFromCometBlock failed", "height", blockNum, "error", err.Error()) return nil, err @@ -40,8 +47,11 @@ func (b *Backend) GetHeaderByNumber(blockNum rpctypes.BlockNumber) (map[string]i // GetBlockByHash returns the JSON-RPC compatible Ethereum block identified by // hash. -func (b *Backend) GetHeaderByHash(hash common.Hash) (map[string]interface{}, error) { - resBlock, err := b.CometBlockByHash(hash) +func (b *Backend) GetHeaderByHash(ctx context.Context, hash common.Hash) (result map[string]interface{}, err error) { + ctx, span := tracer.Start(ctx, "GetHeaderByHash", trace.WithAttributes(attribute.String("hash", hash.Hex()))) + defer func() { evmtrace.EndSpanErr(span, err) }() + + resBlock, err := b.CometBlockByHash(ctx, hash) if err != nil { return nil, err } @@ -51,13 +61,13 @@ func (b *Backend) GetHeaderByHash(hash common.Hash) (map[string]interface{}, err return nil, nil } - blockRes, err := b.RPCClient.BlockResults(b.Ctx, &resBlock.Block.Height) + blockRes, err := b.RPCClient.BlockResults(ctx, &resBlock.Block.Height) if err != nil { b.Logger.Debug("failed to fetch block result from CometBFT", "block-hash", hash.String(), "error", err.Error()) return nil, nil } - res, err := b.RPCHeaderFromCometBlock(resBlock, blockRes) + res, err := b.RPCHeaderFromCometBlock(ctx, resBlock, blockRes) if err != nil { b.Logger.Debug("RPCBlockFromCometBlock failed", "hash", hash, "error", err.Error()) return nil, err @@ -67,8 +77,11 @@ func (b *Backend) GetHeaderByHash(hash common.Hash) (map[string]interface{}, err } // HeaderByNumber returns the block header identified by height. -func (b *Backend) HeaderByNumber(blockNum rpctypes.BlockNumber) (*ethtypes.Header, error) { - resBlock, err := b.CometBlockByNumber(blockNum) +func (b *Backend) HeaderByNumber(ctx context.Context, blockNum rpctypes.BlockNumber) (result *ethtypes.Header, err error) { + ctx, span := tracer.Start(ctx, "HeaderByNumber", trace.WithAttributes(attribute.Int64("blockNum", blockNum.Int64()))) + defer func() { evmtrace.EndSpanErr(span, err) }() + + resBlock, err := b.CometBlockByNumber(ctx, blockNum) if err != nil { return nil, err } @@ -78,12 +91,12 @@ func (b *Backend) HeaderByNumber(blockNum rpctypes.BlockNumber) (*ethtypes.Heade return nil, nil } - blockRes, err := b.CometBlockResultByNumber(&resBlock.Block.Height) + blockRes, err := b.CometBlockResultByNumber(ctx, &resBlock.Block.Height) if err != nil { return nil, fmt.Errorf("header result not found for height %d", resBlock.Block.Height) } - ethBlock, err := b.EthBlockFromCometBlock(resBlock, blockRes) + ethBlock, err := b.EthBlockFromCometBlock(ctx, resBlock, blockRes) if err != nil { return nil, fmt.Errorf("failed to get rpc block from comet block: %w", err) } @@ -92,8 +105,11 @@ func (b *Backend) HeaderByNumber(blockNum rpctypes.BlockNumber) (*ethtypes.Heade } // HeaderByHash returns the block header identified by hash. -func (b *Backend) HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error) { - resBlock, err := b.CometBlockByHash(blockHash) +func (b *Backend) HeaderByHash(ctx context.Context, blockHash common.Hash) (result *ethtypes.Header, err error) { + ctx, span := tracer.Start(ctx, "HeaderByHash", trace.WithAttributes(attribute.String("blockHash", blockHash.Hex()))) + defer func() { evmtrace.EndSpanErr(span, err) }() + + resBlock, err := b.CometBlockByHash(ctx, blockHash) if err != nil { return nil, err } @@ -103,13 +119,13 @@ func (b *Backend) HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error) return nil, nil } - blockRes, err := b.RPCClient.BlockResults(b.Ctx, &resBlock.Block.Height) + blockRes, err := b.RPCClient.BlockResults(ctx, &resBlock.Block.Height) if err != nil { b.Logger.Debug("failed to fetch block result from CometBFT", "block-hash", blockHash.String(), "error", err.Error()) return nil, nil } - ethBlock, err := b.EthBlockFromCometBlock(resBlock, blockRes) + ethBlock, err := b.EthBlockFromCometBlock(ctx, resBlock, blockRes) if err != nil { return nil, fmt.Errorf("failed to get rpc block from comet block: %w", err) } diff --git a/rpc/backend/mocks/client.go b/rpc/backend/mocks/client.go index 3b45f960..86cfaa33 100644 --- a/rpc/backend/mocks/client.go +++ b/rpc/backend/mocks/client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks @@ -22,11 +22,27 @@ type Client struct { mock.Mock } +type Client_Expecter struct { + mock *mock.Mock +} + +func (_m *Client) EXPECT() *Client_Expecter { + return &Client_Expecter{mock: &_m.Mock} +} + // ABCIInfo provides a mock function with given fields: _a0 func (_m *Client) ABCIInfo(_a0 context.Context) (*coretypes.ResultABCIInfo, error) { ret := _m.Called(_a0) + if len(ret) == 0 { + panic("no return value specified for ABCIInfo") + } + var r0 *coretypes.ResultABCIInfo + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*coretypes.ResultABCIInfo, error)); ok { + return rf(_a0) + } if rf, ok := ret.Get(0).(func(context.Context) *coretypes.ResultABCIInfo); ok { r0 = rf(_a0) } else { @@ -35,7 +51,6 @@ func (_m *Client) ABCIInfo(_a0 context.Context) (*coretypes.ResultABCIInfo, erro } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context) error); ok { r1 = rf(_a0) } else { @@ -45,11 +60,47 @@ func (_m *Client) ABCIInfo(_a0 context.Context) (*coretypes.ResultABCIInfo, erro return r0, r1 } +// Client_ABCIInfo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ABCIInfo' +type Client_ABCIInfo_Call struct { + *mock.Call +} + +// ABCIInfo is a helper method to define mock.On call +// - _a0 context.Context +func (_e *Client_Expecter) ABCIInfo(_a0 interface{}) *Client_ABCIInfo_Call { + return &Client_ABCIInfo_Call{Call: _e.mock.On("ABCIInfo", _a0)} +} + +func (_c *Client_ABCIInfo_Call) Run(run func(_a0 context.Context)) *Client_ABCIInfo_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *Client_ABCIInfo_Call) Return(_a0 *coretypes.ResultABCIInfo, _a1 error) *Client_ABCIInfo_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_ABCIInfo_Call) RunAndReturn(run func(context.Context) (*coretypes.ResultABCIInfo, error)) *Client_ABCIInfo_Call { + _c.Call.Return(run) + return _c +} + // ABCIQuery provides a mock function with given fields: ctx, path, data func (_m *Client) ABCIQuery(ctx context.Context, path string, data bytes.HexBytes) (*coretypes.ResultABCIQuery, error) { ret := _m.Called(ctx, path, data) + if len(ret) == 0 { + panic("no return value specified for ABCIQuery") + } + var r0 *coretypes.ResultABCIQuery + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, bytes.HexBytes) (*coretypes.ResultABCIQuery, error)); ok { + return rf(ctx, path, data) + } if rf, ok := ret.Get(0).(func(context.Context, string, bytes.HexBytes) *coretypes.ResultABCIQuery); ok { r0 = rf(ctx, path, data) } else { @@ -58,7 +109,6 @@ func (_m *Client) ABCIQuery(ctx context.Context, path string, data bytes.HexByte } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, string, bytes.HexBytes) error); ok { r1 = rf(ctx, path, data) } else { @@ -68,11 +118,49 @@ func (_m *Client) ABCIQuery(ctx context.Context, path string, data bytes.HexByte return r0, r1 } +// Client_ABCIQuery_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ABCIQuery' +type Client_ABCIQuery_Call struct { + *mock.Call +} + +// ABCIQuery is a helper method to define mock.On call +// - ctx context.Context +// - path string +// - data bytes.HexBytes +func (_e *Client_Expecter) ABCIQuery(ctx interface{}, path interface{}, data interface{}) *Client_ABCIQuery_Call { + return &Client_ABCIQuery_Call{Call: _e.mock.On("ABCIQuery", ctx, path, data)} +} + +func (_c *Client_ABCIQuery_Call) Run(run func(ctx context.Context, path string, data bytes.HexBytes)) *Client_ABCIQuery_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string), args[2].(bytes.HexBytes)) + }) + return _c +} + +func (_c *Client_ABCIQuery_Call) Return(_a0 *coretypes.ResultABCIQuery, _a1 error) *Client_ABCIQuery_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_ABCIQuery_Call) RunAndReturn(run func(context.Context, string, bytes.HexBytes) (*coretypes.ResultABCIQuery, error)) *Client_ABCIQuery_Call { + _c.Call.Return(run) + return _c +} + // ABCIQueryWithOptions provides a mock function with given fields: ctx, path, data, opts func (_m *Client) ABCIQueryWithOptions(ctx context.Context, path string, data bytes.HexBytes, opts client.ABCIQueryOptions) (*coretypes.ResultABCIQuery, error) { ret := _m.Called(ctx, path, data, opts) + if len(ret) == 0 { + panic("no return value specified for ABCIQueryWithOptions") + } + var r0 *coretypes.ResultABCIQuery + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, bytes.HexBytes, client.ABCIQueryOptions) (*coretypes.ResultABCIQuery, error)); ok { + return rf(ctx, path, data, opts) + } if rf, ok := ret.Get(0).(func(context.Context, string, bytes.HexBytes, client.ABCIQueryOptions) *coretypes.ResultABCIQuery); ok { r0 = rf(ctx, path, data, opts) } else { @@ -81,7 +169,6 @@ func (_m *Client) ABCIQueryWithOptions(ctx context.Context, path string, data by } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, string, bytes.HexBytes, client.ABCIQueryOptions) error); ok { r1 = rf(ctx, path, data, opts) } else { @@ -91,11 +178,50 @@ func (_m *Client) ABCIQueryWithOptions(ctx context.Context, path string, data by return r0, r1 } +// Client_ABCIQueryWithOptions_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ABCIQueryWithOptions' +type Client_ABCIQueryWithOptions_Call struct { + *mock.Call +} + +// ABCIQueryWithOptions is a helper method to define mock.On call +// - ctx context.Context +// - path string +// - data bytes.HexBytes +// - opts client.ABCIQueryOptions +func (_e *Client_Expecter) ABCIQueryWithOptions(ctx interface{}, path interface{}, data interface{}, opts interface{}) *Client_ABCIQueryWithOptions_Call { + return &Client_ABCIQueryWithOptions_Call{Call: _e.mock.On("ABCIQueryWithOptions", ctx, path, data, opts)} +} + +func (_c *Client_ABCIQueryWithOptions_Call) Run(run func(ctx context.Context, path string, data bytes.HexBytes, opts client.ABCIQueryOptions)) *Client_ABCIQueryWithOptions_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string), args[2].(bytes.HexBytes), args[3].(client.ABCIQueryOptions)) + }) + return _c +} + +func (_c *Client_ABCIQueryWithOptions_Call) Return(_a0 *coretypes.ResultABCIQuery, _a1 error) *Client_ABCIQueryWithOptions_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_ABCIQueryWithOptions_Call) RunAndReturn(run func(context.Context, string, bytes.HexBytes, client.ABCIQueryOptions) (*coretypes.ResultABCIQuery, error)) *Client_ABCIQueryWithOptions_Call { + _c.Call.Return(run) + return _c +} + // Block provides a mock function with given fields: ctx, height func (_m *Client) Block(ctx context.Context, height *int64) (*coretypes.ResultBlock, error) { ret := _m.Called(ctx, height) + if len(ret) == 0 { + panic("no return value specified for Block") + } + var r0 *coretypes.ResultBlock + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *int64) (*coretypes.ResultBlock, error)); ok { + return rf(ctx, height) + } if rf, ok := ret.Get(0).(func(context.Context, *int64) *coretypes.ResultBlock); ok { r0 = rf(ctx, height) } else { @@ -104,7 +230,6 @@ func (_m *Client) Block(ctx context.Context, height *int64) (*coretypes.ResultBl } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, *int64) error); ok { r1 = rf(ctx, height) } else { @@ -114,11 +239,48 @@ func (_m *Client) Block(ctx context.Context, height *int64) (*coretypes.ResultBl return r0, r1 } +// Client_Block_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Block' +type Client_Block_Call struct { + *mock.Call +} + +// Block is a helper method to define mock.On call +// - ctx context.Context +// - height *int64 +func (_e *Client_Expecter) Block(ctx interface{}, height interface{}) *Client_Block_Call { + return &Client_Block_Call{Call: _e.mock.On("Block", ctx, height)} +} + +func (_c *Client_Block_Call) Run(run func(ctx context.Context, height *int64)) *Client_Block_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*int64)) + }) + return _c +} + +func (_c *Client_Block_Call) Return(_a0 *coretypes.ResultBlock, _a1 error) *Client_Block_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_Block_Call) RunAndReturn(run func(context.Context, *int64) (*coretypes.ResultBlock, error)) *Client_Block_Call { + _c.Call.Return(run) + return _c +} + // BlockByHash provides a mock function with given fields: ctx, hash func (_m *Client) BlockByHash(ctx context.Context, hash []byte) (*coretypes.ResultBlock, error) { ret := _m.Called(ctx, hash) + if len(ret) == 0 { + panic("no return value specified for BlockByHash") + } + var r0 *coretypes.ResultBlock + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, []byte) (*coretypes.ResultBlock, error)); ok { + return rf(ctx, hash) + } if rf, ok := ret.Get(0).(func(context.Context, []byte) *coretypes.ResultBlock); ok { r0 = rf(ctx, hash) } else { @@ -127,7 +289,6 @@ func (_m *Client) BlockByHash(ctx context.Context, hash []byte) (*coretypes.Resu } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, []byte) error); ok { r1 = rf(ctx, hash) } else { @@ -137,11 +298,48 @@ func (_m *Client) BlockByHash(ctx context.Context, hash []byte) (*coretypes.Resu return r0, r1 } +// Client_BlockByHash_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BlockByHash' +type Client_BlockByHash_Call struct { + *mock.Call +} + +// BlockByHash is a helper method to define mock.On call +// - ctx context.Context +// - hash []byte +func (_e *Client_Expecter) BlockByHash(ctx interface{}, hash interface{}) *Client_BlockByHash_Call { + return &Client_BlockByHash_Call{Call: _e.mock.On("BlockByHash", ctx, hash)} +} + +func (_c *Client_BlockByHash_Call) Run(run func(ctx context.Context, hash []byte)) *Client_BlockByHash_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].([]byte)) + }) + return _c +} + +func (_c *Client_BlockByHash_Call) Return(_a0 *coretypes.ResultBlock, _a1 error) *Client_BlockByHash_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_BlockByHash_Call) RunAndReturn(run func(context.Context, []byte) (*coretypes.ResultBlock, error)) *Client_BlockByHash_Call { + _c.Call.Return(run) + return _c +} + // BlockResults provides a mock function with given fields: ctx, height func (_m *Client) BlockResults(ctx context.Context, height *int64) (*coretypes.ResultBlockResults, error) { ret := _m.Called(ctx, height) + if len(ret) == 0 { + panic("no return value specified for BlockResults") + } + var r0 *coretypes.ResultBlockResults + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *int64) (*coretypes.ResultBlockResults, error)); ok { + return rf(ctx, height) + } if rf, ok := ret.Get(0).(func(context.Context, *int64) *coretypes.ResultBlockResults); ok { r0 = rf(ctx, height) } else { @@ -150,7 +348,6 @@ func (_m *Client) BlockResults(ctx context.Context, height *int64) (*coretypes.R } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, *int64) error); ok { r1 = rf(ctx, height) } else { @@ -160,11 +357,48 @@ func (_m *Client) BlockResults(ctx context.Context, height *int64) (*coretypes.R return r0, r1 } +// Client_BlockResults_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BlockResults' +type Client_BlockResults_Call struct { + *mock.Call +} + +// BlockResults is a helper method to define mock.On call +// - ctx context.Context +// - height *int64 +func (_e *Client_Expecter) BlockResults(ctx interface{}, height interface{}) *Client_BlockResults_Call { + return &Client_BlockResults_Call{Call: _e.mock.On("BlockResults", ctx, height)} +} + +func (_c *Client_BlockResults_Call) Run(run func(ctx context.Context, height *int64)) *Client_BlockResults_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*int64)) + }) + return _c +} + +func (_c *Client_BlockResults_Call) Return(_a0 *coretypes.ResultBlockResults, _a1 error) *Client_BlockResults_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_BlockResults_Call) RunAndReturn(run func(context.Context, *int64) (*coretypes.ResultBlockResults, error)) *Client_BlockResults_Call { + _c.Call.Return(run) + return _c +} + // BlockSearch provides a mock function with given fields: ctx, query, page, perPage, orderBy func (_m *Client) BlockSearch(ctx context.Context, query string, page *int, perPage *int, orderBy string) (*coretypes.ResultBlockSearch, error) { ret := _m.Called(ctx, query, page, perPage, orderBy) + if len(ret) == 0 { + panic("no return value specified for BlockSearch") + } + var r0 *coretypes.ResultBlockSearch + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, *int, *int, string) (*coretypes.ResultBlockSearch, error)); ok { + return rf(ctx, query, page, perPage, orderBy) + } if rf, ok := ret.Get(0).(func(context.Context, string, *int, *int, string) *coretypes.ResultBlockSearch); ok { r0 = rf(ctx, query, page, perPage, orderBy) } else { @@ -173,7 +407,6 @@ func (_m *Client) BlockSearch(ctx context.Context, query string, page *int, perP } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, string, *int, *int, string) error); ok { r1 = rf(ctx, query, page, perPage, orderBy) } else { @@ -183,11 +416,51 @@ func (_m *Client) BlockSearch(ctx context.Context, query string, page *int, perP return r0, r1 } +// Client_BlockSearch_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BlockSearch' +type Client_BlockSearch_Call struct { + *mock.Call +} + +// BlockSearch is a helper method to define mock.On call +// - ctx context.Context +// - query string +// - page *int +// - perPage *int +// - orderBy string +func (_e *Client_Expecter) BlockSearch(ctx interface{}, query interface{}, page interface{}, perPage interface{}, orderBy interface{}) *Client_BlockSearch_Call { + return &Client_BlockSearch_Call{Call: _e.mock.On("BlockSearch", ctx, query, page, perPage, orderBy)} +} + +func (_c *Client_BlockSearch_Call) Run(run func(ctx context.Context, query string, page *int, perPage *int, orderBy string)) *Client_BlockSearch_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string), args[2].(*int), args[3].(*int), args[4].(string)) + }) + return _c +} + +func (_c *Client_BlockSearch_Call) Return(_a0 *coretypes.ResultBlockSearch, _a1 error) *Client_BlockSearch_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_BlockSearch_Call) RunAndReturn(run func(context.Context, string, *int, *int, string) (*coretypes.ResultBlockSearch, error)) *Client_BlockSearch_Call { + _c.Call.Return(run) + return _c +} + // BlockchainInfo provides a mock function with given fields: ctx, minHeight, maxHeight func (_m *Client) BlockchainInfo(ctx context.Context, minHeight int64, maxHeight int64) (*coretypes.ResultBlockchainInfo, error) { ret := _m.Called(ctx, minHeight, maxHeight) + if len(ret) == 0 { + panic("no return value specified for BlockchainInfo") + } + var r0 *coretypes.ResultBlockchainInfo + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, int64, int64) (*coretypes.ResultBlockchainInfo, error)); ok { + return rf(ctx, minHeight, maxHeight) + } if rf, ok := ret.Get(0).(func(context.Context, int64, int64) *coretypes.ResultBlockchainInfo); ok { r0 = rf(ctx, minHeight, maxHeight) } else { @@ -196,7 +469,6 @@ func (_m *Client) BlockchainInfo(ctx context.Context, minHeight int64, maxHeight } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, int64, int64) error); ok { r1 = rf(ctx, minHeight, maxHeight) } else { @@ -206,11 +478,49 @@ func (_m *Client) BlockchainInfo(ctx context.Context, minHeight int64, maxHeight return r0, r1 } +// Client_BlockchainInfo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BlockchainInfo' +type Client_BlockchainInfo_Call struct { + *mock.Call +} + +// BlockchainInfo is a helper method to define mock.On call +// - ctx context.Context +// - minHeight int64 +// - maxHeight int64 +func (_e *Client_Expecter) BlockchainInfo(ctx interface{}, minHeight interface{}, maxHeight interface{}) *Client_BlockchainInfo_Call { + return &Client_BlockchainInfo_Call{Call: _e.mock.On("BlockchainInfo", ctx, minHeight, maxHeight)} +} + +func (_c *Client_BlockchainInfo_Call) Run(run func(ctx context.Context, minHeight int64, maxHeight int64)) *Client_BlockchainInfo_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(int64), args[2].(int64)) + }) + return _c +} + +func (_c *Client_BlockchainInfo_Call) Return(_a0 *coretypes.ResultBlockchainInfo, _a1 error) *Client_BlockchainInfo_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_BlockchainInfo_Call) RunAndReturn(run func(context.Context, int64, int64) (*coretypes.ResultBlockchainInfo, error)) *Client_BlockchainInfo_Call { + _c.Call.Return(run) + return _c +} + // BroadcastEvidence provides a mock function with given fields: _a0, _a1 func (_m *Client) BroadcastEvidence(_a0 context.Context, _a1 types.Evidence) (*coretypes.ResultBroadcastEvidence, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for BroadcastEvidence") + } + var r0 *coretypes.ResultBroadcastEvidence + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, types.Evidence) (*coretypes.ResultBroadcastEvidence, error)); ok { + return rf(_a0, _a1) + } if rf, ok := ret.Get(0).(func(context.Context, types.Evidence) *coretypes.ResultBroadcastEvidence); ok { r0 = rf(_a0, _a1) } else { @@ -219,7 +529,6 @@ func (_m *Client) BroadcastEvidence(_a0 context.Context, _a1 types.Evidence) (*c } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, types.Evidence) error); ok { r1 = rf(_a0, _a1) } else { @@ -229,11 +538,48 @@ func (_m *Client) BroadcastEvidence(_a0 context.Context, _a1 types.Evidence) (*c return r0, r1 } +// Client_BroadcastEvidence_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BroadcastEvidence' +type Client_BroadcastEvidence_Call struct { + *mock.Call +} + +// BroadcastEvidence is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 types.Evidence +func (_e *Client_Expecter) BroadcastEvidence(_a0 interface{}, _a1 interface{}) *Client_BroadcastEvidence_Call { + return &Client_BroadcastEvidence_Call{Call: _e.mock.On("BroadcastEvidence", _a0, _a1)} +} + +func (_c *Client_BroadcastEvidence_Call) Run(run func(_a0 context.Context, _a1 types.Evidence)) *Client_BroadcastEvidence_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(types.Evidence)) + }) + return _c +} + +func (_c *Client_BroadcastEvidence_Call) Return(_a0 *coretypes.ResultBroadcastEvidence, _a1 error) *Client_BroadcastEvidence_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_BroadcastEvidence_Call) RunAndReturn(run func(context.Context, types.Evidence) (*coretypes.ResultBroadcastEvidence, error)) *Client_BroadcastEvidence_Call { + _c.Call.Return(run) + return _c +} + // BroadcastTxAsync provides a mock function with given fields: _a0, _a1 func (_m *Client) BroadcastTxAsync(_a0 context.Context, _a1 types.Tx) (*coretypes.ResultBroadcastTx, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for BroadcastTxAsync") + } + var r0 *coretypes.ResultBroadcastTx + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, types.Tx) (*coretypes.ResultBroadcastTx, error)); ok { + return rf(_a0, _a1) + } if rf, ok := ret.Get(0).(func(context.Context, types.Tx) *coretypes.ResultBroadcastTx); ok { r0 = rf(_a0, _a1) } else { @@ -242,7 +588,6 @@ func (_m *Client) BroadcastTxAsync(_a0 context.Context, _a1 types.Tx) (*coretype } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, types.Tx) error); ok { r1 = rf(_a0, _a1) } else { @@ -252,11 +597,48 @@ func (_m *Client) BroadcastTxAsync(_a0 context.Context, _a1 types.Tx) (*coretype return r0, r1 } +// Client_BroadcastTxAsync_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BroadcastTxAsync' +type Client_BroadcastTxAsync_Call struct { + *mock.Call +} + +// BroadcastTxAsync is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 types.Tx +func (_e *Client_Expecter) BroadcastTxAsync(_a0 interface{}, _a1 interface{}) *Client_BroadcastTxAsync_Call { + return &Client_BroadcastTxAsync_Call{Call: _e.mock.On("BroadcastTxAsync", _a0, _a1)} +} + +func (_c *Client_BroadcastTxAsync_Call) Run(run func(_a0 context.Context, _a1 types.Tx)) *Client_BroadcastTxAsync_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(types.Tx)) + }) + return _c +} + +func (_c *Client_BroadcastTxAsync_Call) Return(_a0 *coretypes.ResultBroadcastTx, _a1 error) *Client_BroadcastTxAsync_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_BroadcastTxAsync_Call) RunAndReturn(run func(context.Context, types.Tx) (*coretypes.ResultBroadcastTx, error)) *Client_BroadcastTxAsync_Call { + _c.Call.Return(run) + return _c +} + // BroadcastTxCommit provides a mock function with given fields: _a0, _a1 func (_m *Client) BroadcastTxCommit(_a0 context.Context, _a1 types.Tx) (*coretypes.ResultBroadcastTxCommit, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for BroadcastTxCommit") + } + var r0 *coretypes.ResultBroadcastTxCommit + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, types.Tx) (*coretypes.ResultBroadcastTxCommit, error)); ok { + return rf(_a0, _a1) + } if rf, ok := ret.Get(0).(func(context.Context, types.Tx) *coretypes.ResultBroadcastTxCommit); ok { r0 = rf(_a0, _a1) } else { @@ -265,7 +647,6 @@ func (_m *Client) BroadcastTxCommit(_a0 context.Context, _a1 types.Tx) (*coretyp } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, types.Tx) error); ok { r1 = rf(_a0, _a1) } else { @@ -275,11 +656,48 @@ func (_m *Client) BroadcastTxCommit(_a0 context.Context, _a1 types.Tx) (*coretyp return r0, r1 } +// Client_BroadcastTxCommit_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BroadcastTxCommit' +type Client_BroadcastTxCommit_Call struct { + *mock.Call +} + +// BroadcastTxCommit is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 types.Tx +func (_e *Client_Expecter) BroadcastTxCommit(_a0 interface{}, _a1 interface{}) *Client_BroadcastTxCommit_Call { + return &Client_BroadcastTxCommit_Call{Call: _e.mock.On("BroadcastTxCommit", _a0, _a1)} +} + +func (_c *Client_BroadcastTxCommit_Call) Run(run func(_a0 context.Context, _a1 types.Tx)) *Client_BroadcastTxCommit_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(types.Tx)) + }) + return _c +} + +func (_c *Client_BroadcastTxCommit_Call) Return(_a0 *coretypes.ResultBroadcastTxCommit, _a1 error) *Client_BroadcastTxCommit_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_BroadcastTxCommit_Call) RunAndReturn(run func(context.Context, types.Tx) (*coretypes.ResultBroadcastTxCommit, error)) *Client_BroadcastTxCommit_Call { + _c.Call.Return(run) + return _c +} + // BroadcastTxSync provides a mock function with given fields: _a0, _a1 func (_m *Client) BroadcastTxSync(_a0 context.Context, _a1 types.Tx) (*coretypes.ResultBroadcastTx, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for BroadcastTxSync") + } + var r0 *coretypes.ResultBroadcastTx + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, types.Tx) (*coretypes.ResultBroadcastTx, error)); ok { + return rf(_a0, _a1) + } if rf, ok := ret.Get(0).(func(context.Context, types.Tx) *coretypes.ResultBroadcastTx); ok { r0 = rf(_a0, _a1) } else { @@ -288,7 +706,6 @@ func (_m *Client) BroadcastTxSync(_a0 context.Context, _a1 types.Tx) (*coretypes } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, types.Tx) error); ok { r1 = rf(_a0, _a1) } else { @@ -298,11 +715,48 @@ func (_m *Client) BroadcastTxSync(_a0 context.Context, _a1 types.Tx) (*coretypes return r0, r1 } +// Client_BroadcastTxSync_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BroadcastTxSync' +type Client_BroadcastTxSync_Call struct { + *mock.Call +} + +// BroadcastTxSync is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 types.Tx +func (_e *Client_Expecter) BroadcastTxSync(_a0 interface{}, _a1 interface{}) *Client_BroadcastTxSync_Call { + return &Client_BroadcastTxSync_Call{Call: _e.mock.On("BroadcastTxSync", _a0, _a1)} +} + +func (_c *Client_BroadcastTxSync_Call) Run(run func(_a0 context.Context, _a1 types.Tx)) *Client_BroadcastTxSync_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(types.Tx)) + }) + return _c +} + +func (_c *Client_BroadcastTxSync_Call) Return(_a0 *coretypes.ResultBroadcastTx, _a1 error) *Client_BroadcastTxSync_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_BroadcastTxSync_Call) RunAndReturn(run func(context.Context, types.Tx) (*coretypes.ResultBroadcastTx, error)) *Client_BroadcastTxSync_Call { + _c.Call.Return(run) + return _c +} + // CheckTx provides a mock function with given fields: _a0, _a1 func (_m *Client) CheckTx(_a0 context.Context, _a1 types.Tx) (*coretypes.ResultCheckTx, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for CheckTx") + } + var r0 *coretypes.ResultCheckTx + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, types.Tx) (*coretypes.ResultCheckTx, error)); ok { + return rf(_a0, _a1) + } if rf, ok := ret.Get(0).(func(context.Context, types.Tx) *coretypes.ResultCheckTx); ok { r0 = rf(_a0, _a1) } else { @@ -311,7 +765,6 @@ func (_m *Client) CheckTx(_a0 context.Context, _a1 types.Tx) (*coretypes.ResultC } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, types.Tx) error); ok { r1 = rf(_a0, _a1) } else { @@ -321,11 +774,48 @@ func (_m *Client) CheckTx(_a0 context.Context, _a1 types.Tx) (*coretypes.ResultC return r0, r1 } +// Client_CheckTx_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CheckTx' +type Client_CheckTx_Call struct { + *mock.Call +} + +// CheckTx is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 types.Tx +func (_e *Client_Expecter) CheckTx(_a0 interface{}, _a1 interface{}) *Client_CheckTx_Call { + return &Client_CheckTx_Call{Call: _e.mock.On("CheckTx", _a0, _a1)} +} + +func (_c *Client_CheckTx_Call) Run(run func(_a0 context.Context, _a1 types.Tx)) *Client_CheckTx_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(types.Tx)) + }) + return _c +} + +func (_c *Client_CheckTx_Call) Return(_a0 *coretypes.ResultCheckTx, _a1 error) *Client_CheckTx_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_CheckTx_Call) RunAndReturn(run func(context.Context, types.Tx) (*coretypes.ResultCheckTx, error)) *Client_CheckTx_Call { + _c.Call.Return(run) + return _c +} + // Commit provides a mock function with given fields: ctx, height func (_m *Client) Commit(ctx context.Context, height *int64) (*coretypes.ResultCommit, error) { ret := _m.Called(ctx, height) + if len(ret) == 0 { + panic("no return value specified for Commit") + } + var r0 *coretypes.ResultCommit + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *int64) (*coretypes.ResultCommit, error)); ok { + return rf(ctx, height) + } if rf, ok := ret.Get(0).(func(context.Context, *int64) *coretypes.ResultCommit); ok { r0 = rf(ctx, height) } else { @@ -334,7 +824,6 @@ func (_m *Client) Commit(ctx context.Context, height *int64) (*coretypes.ResultC } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, *int64) error); ok { r1 = rf(ctx, height) } else { @@ -344,11 +833,48 @@ func (_m *Client) Commit(ctx context.Context, height *int64) (*coretypes.ResultC return r0, r1 } +// Client_Commit_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Commit' +type Client_Commit_Call struct { + *mock.Call +} + +// Commit is a helper method to define mock.On call +// - ctx context.Context +// - height *int64 +func (_e *Client_Expecter) Commit(ctx interface{}, height interface{}) *Client_Commit_Call { + return &Client_Commit_Call{Call: _e.mock.On("Commit", ctx, height)} +} + +func (_c *Client_Commit_Call) Run(run func(ctx context.Context, height *int64)) *Client_Commit_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*int64)) + }) + return _c +} + +func (_c *Client_Commit_Call) Return(_a0 *coretypes.ResultCommit, _a1 error) *Client_Commit_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_Commit_Call) RunAndReturn(run func(context.Context, *int64) (*coretypes.ResultCommit, error)) *Client_Commit_Call { + _c.Call.Return(run) + return _c +} + // ConsensusParams provides a mock function with given fields: ctx, height func (_m *Client) ConsensusParams(ctx context.Context, height *int64) (*coretypes.ResultConsensusParams, error) { ret := _m.Called(ctx, height) + if len(ret) == 0 { + panic("no return value specified for ConsensusParams") + } + var r0 *coretypes.ResultConsensusParams + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *int64) (*coretypes.ResultConsensusParams, error)); ok { + return rf(ctx, height) + } if rf, ok := ret.Get(0).(func(context.Context, *int64) *coretypes.ResultConsensusParams); ok { r0 = rf(ctx, height) } else { @@ -357,7 +883,6 @@ func (_m *Client) ConsensusParams(ctx context.Context, height *int64) (*coretype } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, *int64) error); ok { r1 = rf(ctx, height) } else { @@ -367,11 +892,48 @@ func (_m *Client) ConsensusParams(ctx context.Context, height *int64) (*coretype return r0, r1 } +// Client_ConsensusParams_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ConsensusParams' +type Client_ConsensusParams_Call struct { + *mock.Call +} + +// ConsensusParams is a helper method to define mock.On call +// - ctx context.Context +// - height *int64 +func (_e *Client_Expecter) ConsensusParams(ctx interface{}, height interface{}) *Client_ConsensusParams_Call { + return &Client_ConsensusParams_Call{Call: _e.mock.On("ConsensusParams", ctx, height)} +} + +func (_c *Client_ConsensusParams_Call) Run(run func(ctx context.Context, height *int64)) *Client_ConsensusParams_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*int64)) + }) + return _c +} + +func (_c *Client_ConsensusParams_Call) Return(_a0 *coretypes.ResultConsensusParams, _a1 error) *Client_ConsensusParams_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_ConsensusParams_Call) RunAndReturn(run func(context.Context, *int64) (*coretypes.ResultConsensusParams, error)) *Client_ConsensusParams_Call { + _c.Call.Return(run) + return _c +} + // ConsensusState provides a mock function with given fields: _a0 func (_m *Client) ConsensusState(_a0 context.Context) (*coretypes.ResultConsensusState, error) { ret := _m.Called(_a0) + if len(ret) == 0 { + panic("no return value specified for ConsensusState") + } + var r0 *coretypes.ResultConsensusState + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*coretypes.ResultConsensusState, error)); ok { + return rf(_a0) + } if rf, ok := ret.Get(0).(func(context.Context) *coretypes.ResultConsensusState); ok { r0 = rf(_a0) } else { @@ -380,7 +942,6 @@ func (_m *Client) ConsensusState(_a0 context.Context) (*coretypes.ResultConsensu } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context) error); ok { r1 = rf(_a0) } else { @@ -390,11 +951,47 @@ func (_m *Client) ConsensusState(_a0 context.Context) (*coretypes.ResultConsensu return r0, r1 } +// Client_ConsensusState_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ConsensusState' +type Client_ConsensusState_Call struct { + *mock.Call +} + +// ConsensusState is a helper method to define mock.On call +// - _a0 context.Context +func (_e *Client_Expecter) ConsensusState(_a0 interface{}) *Client_ConsensusState_Call { + return &Client_ConsensusState_Call{Call: _e.mock.On("ConsensusState", _a0)} +} + +func (_c *Client_ConsensusState_Call) Run(run func(_a0 context.Context)) *Client_ConsensusState_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *Client_ConsensusState_Call) Return(_a0 *coretypes.ResultConsensusState, _a1 error) *Client_ConsensusState_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_ConsensusState_Call) RunAndReturn(run func(context.Context) (*coretypes.ResultConsensusState, error)) *Client_ConsensusState_Call { + _c.Call.Return(run) + return _c +} + // DumpConsensusState provides a mock function with given fields: _a0 func (_m *Client) DumpConsensusState(_a0 context.Context) (*coretypes.ResultDumpConsensusState, error) { ret := _m.Called(_a0) + if len(ret) == 0 { + panic("no return value specified for DumpConsensusState") + } + var r0 *coretypes.ResultDumpConsensusState + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*coretypes.ResultDumpConsensusState, error)); ok { + return rf(_a0) + } if rf, ok := ret.Get(0).(func(context.Context) *coretypes.ResultDumpConsensusState); ok { r0 = rf(_a0) } else { @@ -403,7 +1000,6 @@ func (_m *Client) DumpConsensusState(_a0 context.Context) (*coretypes.ResultDump } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context) error); ok { r1 = rf(_a0) } else { @@ -413,20 +1009,55 @@ func (_m *Client) DumpConsensusState(_a0 context.Context) (*coretypes.ResultDump return r0, r1 } -// Genesis provides a mock function with given fields: _a0 -func (_m *Client) Genesis(_a0 context.Context) (*coretypes.ResultGenesis, error) { - ret := _m.Called(_a0) +// Client_DumpConsensusState_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DumpConsensusState' +type Client_DumpConsensusState_Call struct { + *mock.Call +} - var r0 *coretypes.ResultGenesis - if rf, ok := ret.Get(0).(func(context.Context) *coretypes.ResultGenesis); ok { - r0 = rf(_a0) +// DumpConsensusState is a helper method to define mock.On call +// - _a0 context.Context +func (_e *Client_Expecter) DumpConsensusState(_a0 interface{}) *Client_DumpConsensusState_Call { + return &Client_DumpConsensusState_Call{Call: _e.mock.On("DumpConsensusState", _a0)} +} + +func (_c *Client_DumpConsensusState_Call) Run(run func(_a0 context.Context)) *Client_DumpConsensusState_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *Client_DumpConsensusState_Call) Return(_a0 *coretypes.ResultDumpConsensusState, _a1 error) *Client_DumpConsensusState_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_DumpConsensusState_Call) RunAndReturn(run func(context.Context) (*coretypes.ResultDumpConsensusState, error)) *Client_DumpConsensusState_Call { + _c.Call.Return(run) + return _c +} + +// Genesis provides a mock function with given fields: _a0 +func (_m *Client) Genesis(_a0 context.Context) (*coretypes.ResultGenesis, error) { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for Genesis") + } + + var r0 *coretypes.ResultGenesis + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*coretypes.ResultGenesis, error)); ok { + return rf(_a0) + } + if rf, ok := ret.Get(0).(func(context.Context) *coretypes.ResultGenesis); ok { + r0 = rf(_a0) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*coretypes.ResultGenesis) } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context) error); ok { r1 = rf(_a0) } else { @@ -436,11 +1067,47 @@ func (_m *Client) Genesis(_a0 context.Context) (*coretypes.ResultGenesis, error) return r0, r1 } +// Client_Genesis_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Genesis' +type Client_Genesis_Call struct { + *mock.Call +} + +// Genesis is a helper method to define mock.On call +// - _a0 context.Context +func (_e *Client_Expecter) Genesis(_a0 interface{}) *Client_Genesis_Call { + return &Client_Genesis_Call{Call: _e.mock.On("Genesis", _a0)} +} + +func (_c *Client_Genesis_Call) Run(run func(_a0 context.Context)) *Client_Genesis_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *Client_Genesis_Call) Return(_a0 *coretypes.ResultGenesis, _a1 error) *Client_Genesis_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_Genesis_Call) RunAndReturn(run func(context.Context) (*coretypes.ResultGenesis, error)) *Client_Genesis_Call { + _c.Call.Return(run) + return _c +} + // GenesisChunked provides a mock function with given fields: _a0, _a1 func (_m *Client) GenesisChunked(_a0 context.Context, _a1 uint) (*coretypes.ResultGenesisChunk, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for GenesisChunked") + } + var r0 *coretypes.ResultGenesisChunk + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint) (*coretypes.ResultGenesisChunk, error)); ok { + return rf(_a0, _a1) + } if rf, ok := ret.Get(0).(func(context.Context, uint) *coretypes.ResultGenesisChunk); ok { r0 = rf(_a0, _a1) } else { @@ -449,7 +1116,6 @@ func (_m *Client) GenesisChunked(_a0 context.Context, _a1 uint) (*coretypes.Resu } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, uint) error); ok { r1 = rf(_a0, _a1) } else { @@ -459,11 +1125,48 @@ func (_m *Client) GenesisChunked(_a0 context.Context, _a1 uint) (*coretypes.Resu return r0, r1 } +// Client_GenesisChunked_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GenesisChunked' +type Client_GenesisChunked_Call struct { + *mock.Call +} + +// GenesisChunked is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 uint +func (_e *Client_Expecter) GenesisChunked(_a0 interface{}, _a1 interface{}) *Client_GenesisChunked_Call { + return &Client_GenesisChunked_Call{Call: _e.mock.On("GenesisChunked", _a0, _a1)} +} + +func (_c *Client_GenesisChunked_Call) Run(run func(_a0 context.Context, _a1 uint)) *Client_GenesisChunked_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(uint)) + }) + return _c +} + +func (_c *Client_GenesisChunked_Call) Return(_a0 *coretypes.ResultGenesisChunk, _a1 error) *Client_GenesisChunked_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_GenesisChunked_Call) RunAndReturn(run func(context.Context, uint) (*coretypes.ResultGenesisChunk, error)) *Client_GenesisChunked_Call { + _c.Call.Return(run) + return _c +} + // Header provides a mock function with given fields: ctx, height func (_m *Client) Header(ctx context.Context, height *int64) (*coretypes.ResultHeader, error) { ret := _m.Called(ctx, height) + if len(ret) == 0 { + panic("no return value specified for Header") + } + var r0 *coretypes.ResultHeader + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *int64) (*coretypes.ResultHeader, error)); ok { + return rf(ctx, height) + } if rf, ok := ret.Get(0).(func(context.Context, *int64) *coretypes.ResultHeader); ok { r0 = rf(ctx, height) } else { @@ -472,7 +1175,6 @@ func (_m *Client) Header(ctx context.Context, height *int64) (*coretypes.ResultH } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, *int64) error); ok { r1 = rf(ctx, height) } else { @@ -482,11 +1184,48 @@ func (_m *Client) Header(ctx context.Context, height *int64) (*coretypes.ResultH return r0, r1 } +// Client_Header_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Header' +type Client_Header_Call struct { + *mock.Call +} + +// Header is a helper method to define mock.On call +// - ctx context.Context +// - height *int64 +func (_e *Client_Expecter) Header(ctx interface{}, height interface{}) *Client_Header_Call { + return &Client_Header_Call{Call: _e.mock.On("Header", ctx, height)} +} + +func (_c *Client_Header_Call) Run(run func(ctx context.Context, height *int64)) *Client_Header_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*int64)) + }) + return _c +} + +func (_c *Client_Header_Call) Return(_a0 *coretypes.ResultHeader, _a1 error) *Client_Header_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_Header_Call) RunAndReturn(run func(context.Context, *int64) (*coretypes.ResultHeader, error)) *Client_Header_Call { + _c.Call.Return(run) + return _c +} + // HeaderByHash provides a mock function with given fields: ctx, hash func (_m *Client) HeaderByHash(ctx context.Context, hash bytes.HexBytes) (*coretypes.ResultHeader, error) { ret := _m.Called(ctx, hash) + if len(ret) == 0 { + panic("no return value specified for HeaderByHash") + } + var r0 *coretypes.ResultHeader + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, bytes.HexBytes) (*coretypes.ResultHeader, error)); ok { + return rf(ctx, hash) + } if rf, ok := ret.Get(0).(func(context.Context, bytes.HexBytes) *coretypes.ResultHeader); ok { r0 = rf(ctx, hash) } else { @@ -495,7 +1234,6 @@ func (_m *Client) HeaderByHash(ctx context.Context, hash bytes.HexBytes) (*coret } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, bytes.HexBytes) error); ok { r1 = rf(ctx, hash) } else { @@ -505,11 +1243,48 @@ func (_m *Client) HeaderByHash(ctx context.Context, hash bytes.HexBytes) (*coret return r0, r1 } +// Client_HeaderByHash_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'HeaderByHash' +type Client_HeaderByHash_Call struct { + *mock.Call +} + +// HeaderByHash is a helper method to define mock.On call +// - ctx context.Context +// - hash bytes.HexBytes +func (_e *Client_Expecter) HeaderByHash(ctx interface{}, hash interface{}) *Client_HeaderByHash_Call { + return &Client_HeaderByHash_Call{Call: _e.mock.On("HeaderByHash", ctx, hash)} +} + +func (_c *Client_HeaderByHash_Call) Run(run func(ctx context.Context, hash bytes.HexBytes)) *Client_HeaderByHash_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(bytes.HexBytes)) + }) + return _c +} + +func (_c *Client_HeaderByHash_Call) Return(_a0 *coretypes.ResultHeader, _a1 error) *Client_HeaderByHash_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_HeaderByHash_Call) RunAndReturn(run func(context.Context, bytes.HexBytes) (*coretypes.ResultHeader, error)) *Client_HeaderByHash_Call { + _c.Call.Return(run) + return _c +} + // Health provides a mock function with given fields: _a0 func (_m *Client) Health(_a0 context.Context) (*coretypes.ResultHealth, error) { ret := _m.Called(_a0) + if len(ret) == 0 { + panic("no return value specified for Health") + } + var r0 *coretypes.ResultHealth + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*coretypes.ResultHealth, error)); ok { + return rf(_a0) + } if rf, ok := ret.Get(0).(func(context.Context) *coretypes.ResultHealth); ok { r0 = rf(_a0) } else { @@ -518,7 +1293,6 @@ func (_m *Client) Health(_a0 context.Context) (*coretypes.ResultHealth, error) { } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context) error); ok { r1 = rf(_a0) } else { @@ -528,10 +1302,42 @@ func (_m *Client) Health(_a0 context.Context) (*coretypes.ResultHealth, error) { return r0, r1 } -// IsRunning provides a mock function with given fields: +// Client_Health_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Health' +type Client_Health_Call struct { + *mock.Call +} + +// Health is a helper method to define mock.On call +// - _a0 context.Context +func (_e *Client_Expecter) Health(_a0 interface{}) *Client_Health_Call { + return &Client_Health_Call{Call: _e.mock.On("Health", _a0)} +} + +func (_c *Client_Health_Call) Run(run func(_a0 context.Context)) *Client_Health_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *Client_Health_Call) Return(_a0 *coretypes.ResultHealth, _a1 error) *Client_Health_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_Health_Call) RunAndReturn(run func(context.Context) (*coretypes.ResultHealth, error)) *Client_Health_Call { + _c.Call.Return(run) + return _c +} + +// IsRunning provides a mock function with no fields func (_m *Client) IsRunning() bool { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for IsRunning") + } + var r0 bool if rf, ok := ret.Get(0).(func() bool); ok { r0 = rf() @@ -542,11 +1348,46 @@ func (_m *Client) IsRunning() bool { return r0 } +// Client_IsRunning_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'IsRunning' +type Client_IsRunning_Call struct { + *mock.Call +} + +// IsRunning is a helper method to define mock.On call +func (_e *Client_Expecter) IsRunning() *Client_IsRunning_Call { + return &Client_IsRunning_Call{Call: _e.mock.On("IsRunning")} +} + +func (_c *Client_IsRunning_Call) Run(run func()) *Client_IsRunning_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Client_IsRunning_Call) Return(_a0 bool) *Client_IsRunning_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_IsRunning_Call) RunAndReturn(run func() bool) *Client_IsRunning_Call { + _c.Call.Return(run) + return _c +} + // NetInfo provides a mock function with given fields: _a0 func (_m *Client) NetInfo(_a0 context.Context) (*coretypes.ResultNetInfo, error) { ret := _m.Called(_a0) + if len(ret) == 0 { + panic("no return value specified for NetInfo") + } + var r0 *coretypes.ResultNetInfo + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*coretypes.ResultNetInfo, error)); ok { + return rf(_a0) + } if rf, ok := ret.Get(0).(func(context.Context) *coretypes.ResultNetInfo); ok { r0 = rf(_a0) } else { @@ -555,7 +1396,6 @@ func (_m *Client) NetInfo(_a0 context.Context) (*coretypes.ResultNetInfo, error) } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context) error); ok { r1 = rf(_a0) } else { @@ -565,11 +1405,47 @@ func (_m *Client) NetInfo(_a0 context.Context) (*coretypes.ResultNetInfo, error) return r0, r1 } +// Client_NetInfo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'NetInfo' +type Client_NetInfo_Call struct { + *mock.Call +} + +// NetInfo is a helper method to define mock.On call +// - _a0 context.Context +func (_e *Client_Expecter) NetInfo(_a0 interface{}) *Client_NetInfo_Call { + return &Client_NetInfo_Call{Call: _e.mock.On("NetInfo", _a0)} +} + +func (_c *Client_NetInfo_Call) Run(run func(_a0 context.Context)) *Client_NetInfo_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *Client_NetInfo_Call) Return(_a0 *coretypes.ResultNetInfo, _a1 error) *Client_NetInfo_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_NetInfo_Call) RunAndReturn(run func(context.Context) (*coretypes.ResultNetInfo, error)) *Client_NetInfo_Call { + _c.Call.Return(run) + return _c +} + // NumUnconfirmedTxs provides a mock function with given fields: _a0 func (_m *Client) NumUnconfirmedTxs(_a0 context.Context) (*coretypes.ResultUnconfirmedTxs, error) { ret := _m.Called(_a0) + if len(ret) == 0 { + panic("no return value specified for NumUnconfirmedTxs") + } + var r0 *coretypes.ResultUnconfirmedTxs + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*coretypes.ResultUnconfirmedTxs, error)); ok { + return rf(_a0) + } if rf, ok := ret.Get(0).(func(context.Context) *coretypes.ResultUnconfirmedTxs); ok { r0 = rf(_a0) } else { @@ -578,7 +1454,6 @@ func (_m *Client) NumUnconfirmedTxs(_a0 context.Context) (*coretypes.ResultUncon } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context) error); ok { r1 = rf(_a0) } else { @@ -588,10 +1463,42 @@ func (_m *Client) NumUnconfirmedTxs(_a0 context.Context) (*coretypes.ResultUncon return r0, r1 } -// OnReset provides a mock function with given fields: +// Client_NumUnconfirmedTxs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'NumUnconfirmedTxs' +type Client_NumUnconfirmedTxs_Call struct { + *mock.Call +} + +// NumUnconfirmedTxs is a helper method to define mock.On call +// - _a0 context.Context +func (_e *Client_Expecter) NumUnconfirmedTxs(_a0 interface{}) *Client_NumUnconfirmedTxs_Call { + return &Client_NumUnconfirmedTxs_Call{Call: _e.mock.On("NumUnconfirmedTxs", _a0)} +} + +func (_c *Client_NumUnconfirmedTxs_Call) Run(run func(_a0 context.Context)) *Client_NumUnconfirmedTxs_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *Client_NumUnconfirmedTxs_Call) Return(_a0 *coretypes.ResultUnconfirmedTxs, _a1 error) *Client_NumUnconfirmedTxs_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_NumUnconfirmedTxs_Call) RunAndReturn(run func(context.Context) (*coretypes.ResultUnconfirmedTxs, error)) *Client_NumUnconfirmedTxs_Call { + _c.Call.Return(run) + return _c +} + +// OnReset provides a mock function with no fields func (_m *Client) OnReset() error { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for OnReset") + } + var r0 error if rf, ok := ret.Get(0).(func() error); ok { r0 = rf() @@ -602,10 +1509,41 @@ func (_m *Client) OnReset() error { return r0 } -// OnStart provides a mock function with given fields: +// Client_OnReset_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'OnReset' +type Client_OnReset_Call struct { + *mock.Call +} + +// OnReset is a helper method to define mock.On call +func (_e *Client_Expecter) OnReset() *Client_OnReset_Call { + return &Client_OnReset_Call{Call: _e.mock.On("OnReset")} +} + +func (_c *Client_OnReset_Call) Run(run func()) *Client_OnReset_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Client_OnReset_Call) Return(_a0 error) *Client_OnReset_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_OnReset_Call) RunAndReturn(run func() error) *Client_OnReset_Call { + _c.Call.Return(run) + return _c +} + +// OnStart provides a mock function with no fields func (_m *Client) OnStart() error { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for OnStart") + } + var r0 error if rf, ok := ret.Get(0).(func() error); ok { r0 = rf() @@ -616,15 +1554,73 @@ func (_m *Client) OnStart() error { return r0 } -// OnStop provides a mock function with given fields: +// Client_OnStart_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'OnStart' +type Client_OnStart_Call struct { + *mock.Call +} + +// OnStart is a helper method to define mock.On call +func (_e *Client_Expecter) OnStart() *Client_OnStart_Call { + return &Client_OnStart_Call{Call: _e.mock.On("OnStart")} +} + +func (_c *Client_OnStart_Call) Run(run func()) *Client_OnStart_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Client_OnStart_Call) Return(_a0 error) *Client_OnStart_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_OnStart_Call) RunAndReturn(run func() error) *Client_OnStart_Call { + _c.Call.Return(run) + return _c +} + +// OnStop provides a mock function with no fields func (_m *Client) OnStop() { _m.Called() } -// Quit provides a mock function with given fields: +// Client_OnStop_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'OnStop' +type Client_OnStop_Call struct { + *mock.Call +} + +// OnStop is a helper method to define mock.On call +func (_e *Client_Expecter) OnStop() *Client_OnStop_Call { + return &Client_OnStop_Call{Call: _e.mock.On("OnStop")} +} + +func (_c *Client_OnStop_Call) Run(run func()) *Client_OnStop_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Client_OnStop_Call) Return() *Client_OnStop_Call { + _c.Call.Return() + return _c +} + +func (_c *Client_OnStop_Call) RunAndReturn(run func()) *Client_OnStop_Call { + _c.Run(run) + return _c +} + +// Quit provides a mock function with no fields func (_m *Client) Quit() <-chan struct{} { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for Quit") + } + var r0 <-chan struct{} if rf, ok := ret.Get(0).(func() <-chan struct{}); ok { r0 = rf() @@ -637,10 +1633,41 @@ func (_m *Client) Quit() <-chan struct{} { return r0 } -// Reset provides a mock function with given fields: +// Client_Quit_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Quit' +type Client_Quit_Call struct { + *mock.Call +} + +// Quit is a helper method to define mock.On call +func (_e *Client_Expecter) Quit() *Client_Quit_Call { + return &Client_Quit_Call{Call: _e.mock.On("Quit")} +} + +func (_c *Client_Quit_Call) Run(run func()) *Client_Quit_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Client_Quit_Call) Return(_a0 <-chan struct{}) *Client_Quit_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_Quit_Call) RunAndReturn(run func() <-chan struct{}) *Client_Quit_Call { + _c.Call.Return(run) + return _c +} + +// Reset provides a mock function with no fields func (_m *Client) Reset() error { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for Reset") + } + var r0 error if rf, ok := ret.Get(0).(func() error); ok { r0 = rf() @@ -651,18 +1678,74 @@ func (_m *Client) Reset() error { return r0 } +// Client_Reset_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Reset' +type Client_Reset_Call struct { + *mock.Call +} + +// Reset is a helper method to define mock.On call +func (_e *Client_Expecter) Reset() *Client_Reset_Call { + return &Client_Reset_Call{Call: _e.mock.On("Reset")} +} + +func (_c *Client_Reset_Call) Run(run func()) *Client_Reset_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Client_Reset_Call) Return(_a0 error) *Client_Reset_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_Reset_Call) RunAndReturn(run func() error) *Client_Reset_Call { + _c.Call.Return(run) + return _c +} + // SetLogger provides a mock function with given fields: _a0 -// -// NOTE: here we have to keep the Comet logger, instead of the Cosmos SDK -// one because it has to implement the Client interface. func (_m *Client) SetLogger(_a0 log.Logger) { _m.Called(_a0) } -// Start provides a mock function with given fields: +// Client_SetLogger_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetLogger' +type Client_SetLogger_Call struct { + *mock.Call +} + +// SetLogger is a helper method to define mock.On call +// - _a0 log.Logger +func (_e *Client_Expecter) SetLogger(_a0 interface{}) *Client_SetLogger_Call { + return &Client_SetLogger_Call{Call: _e.mock.On("SetLogger", _a0)} +} + +func (_c *Client_SetLogger_Call) Run(run func(_a0 log.Logger)) *Client_SetLogger_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(log.Logger)) + }) + return _c +} + +func (_c *Client_SetLogger_Call) Return() *Client_SetLogger_Call { + _c.Call.Return() + return _c +} + +func (_c *Client_SetLogger_Call) RunAndReturn(run func(log.Logger)) *Client_SetLogger_Call { + _c.Run(run) + return _c +} + +// Start provides a mock function with no fields func (_m *Client) Start() error { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for Start") + } + var r0 error if rf, ok := ret.Get(0).(func() error); ok { r0 = rf() @@ -673,11 +1756,46 @@ func (_m *Client) Start() error { return r0 } +// Client_Start_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Start' +type Client_Start_Call struct { + *mock.Call +} + +// Start is a helper method to define mock.On call +func (_e *Client_Expecter) Start() *Client_Start_Call { + return &Client_Start_Call{Call: _e.mock.On("Start")} +} + +func (_c *Client_Start_Call) Run(run func()) *Client_Start_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Client_Start_Call) Return(_a0 error) *Client_Start_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_Start_Call) RunAndReturn(run func() error) *Client_Start_Call { + _c.Call.Return(run) + return _c +} + // Status provides a mock function with given fields: _a0 func (_m *Client) Status(_a0 context.Context) (*coretypes.ResultStatus, error) { ret := _m.Called(_a0) + if len(ret) == 0 { + panic("no return value specified for Status") + } + var r0 *coretypes.ResultStatus + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*coretypes.ResultStatus, error)); ok { + return rf(_a0) + } if rf, ok := ret.Get(0).(func(context.Context) *coretypes.ResultStatus); ok { r0 = rf(_a0) } else { @@ -686,7 +1804,6 @@ func (_m *Client) Status(_a0 context.Context) (*coretypes.ResultStatus, error) { } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context) error); ok { r1 = rf(_a0) } else { @@ -696,10 +1813,42 @@ func (_m *Client) Status(_a0 context.Context) (*coretypes.ResultStatus, error) { return r0, r1 } -// Stop provides a mock function with given fields: +// Client_Status_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Status' +type Client_Status_Call struct { + *mock.Call +} + +// Status is a helper method to define mock.On call +// - _a0 context.Context +func (_e *Client_Expecter) Status(_a0 interface{}) *Client_Status_Call { + return &Client_Status_Call{Call: _e.mock.On("Status", _a0)} +} + +func (_c *Client_Status_Call) Run(run func(_a0 context.Context)) *Client_Status_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *Client_Status_Call) Return(_a0 *coretypes.ResultStatus, _a1 error) *Client_Status_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_Status_Call) RunAndReturn(run func(context.Context) (*coretypes.ResultStatus, error)) *Client_Status_Call { + _c.Call.Return(run) + return _c +} + +// Stop provides a mock function with no fields func (_m *Client) Stop() error { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for Stop") + } + var r0 error if rf, ok := ret.Get(0).(func() error); ok { r0 = rf() @@ -710,10 +1859,41 @@ func (_m *Client) Stop() error { return r0 } -// String provides a mock function with given fields: +// Client_Stop_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Stop' +type Client_Stop_Call struct { + *mock.Call +} + +// Stop is a helper method to define mock.On call +func (_e *Client_Expecter) Stop() *Client_Stop_Call { + return &Client_Stop_Call{Call: _e.mock.On("Stop")} +} + +func (_c *Client_Stop_Call) Run(run func()) *Client_Stop_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Client_Stop_Call) Return(_a0 error) *Client_Stop_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_Stop_Call) RunAndReturn(run func() error) *Client_Stop_Call { + _c.Call.Return(run) + return _c +} + +// String provides a mock function with no fields func (_m *Client) String() string { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for String") + } + var r0 string if rf, ok := ret.Get(0).(func() string); ok { r0 = rf() @@ -724,6 +1904,33 @@ func (_m *Client) String() string { return r0 } +// Client_String_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'String' +type Client_String_Call struct { + *mock.Call +} + +// String is a helper method to define mock.On call +func (_e *Client_Expecter) String() *Client_String_Call { + return &Client_String_Call{Call: _e.mock.On("String")} +} + +func (_c *Client_String_Call) Run(run func()) *Client_String_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Client_String_Call) Return(_a0 string) *Client_String_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_String_Call) RunAndReturn(run func() string) *Client_String_Call { + _c.Call.Return(run) + return _c +} + // Subscribe provides a mock function with given fields: ctx, subscriber, query, outCapacity func (_m *Client) Subscribe(ctx context.Context, subscriber string, query string, outCapacity ...int) (<-chan coretypes.ResultEvent, error) { _va := make([]interface{}, len(outCapacity)) @@ -735,7 +1942,15 @@ func (_m *Client) Subscribe(ctx context.Context, subscriber string, query string _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for Subscribe") + } + var r0 <-chan coretypes.ResultEvent + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, string, ...int) (<-chan coretypes.ResultEvent, error)); ok { + return rf(ctx, subscriber, query, outCapacity...) + } if rf, ok := ret.Get(0).(func(context.Context, string, string, ...int) <-chan coretypes.ResultEvent); ok { r0 = rf(ctx, subscriber, query, outCapacity...) } else { @@ -744,7 +1959,6 @@ func (_m *Client) Subscribe(ctx context.Context, subscriber string, query string } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, string, string, ...int) error); ok { r1 = rf(ctx, subscriber, query, outCapacity...) } else { @@ -754,11 +1968,57 @@ func (_m *Client) Subscribe(ctx context.Context, subscriber string, query string return r0, r1 } +// Client_Subscribe_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Subscribe' +type Client_Subscribe_Call struct { + *mock.Call +} + +// Subscribe is a helper method to define mock.On call +// - ctx context.Context +// - subscriber string +// - query string +// - outCapacity ...int +func (_e *Client_Expecter) Subscribe(ctx interface{}, subscriber interface{}, query interface{}, outCapacity ...interface{}) *Client_Subscribe_Call { + return &Client_Subscribe_Call{Call: _e.mock.On("Subscribe", + append([]interface{}{ctx, subscriber, query}, outCapacity...)...)} +} + +func (_c *Client_Subscribe_Call) Run(run func(ctx context.Context, subscriber string, query string, outCapacity ...int)) *Client_Subscribe_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]int, len(args)-3) + for i, a := range args[3:] { + if a != nil { + variadicArgs[i] = a.(int) + } + } + run(args[0].(context.Context), args[1].(string), args[2].(string), variadicArgs...) + }) + return _c +} + +func (_c *Client_Subscribe_Call) Return(out <-chan coretypes.ResultEvent, err error) *Client_Subscribe_Call { + _c.Call.Return(out, err) + return _c +} + +func (_c *Client_Subscribe_Call) RunAndReturn(run func(context.Context, string, string, ...int) (<-chan coretypes.ResultEvent, error)) *Client_Subscribe_Call { + _c.Call.Return(run) + return _c +} + // Tx provides a mock function with given fields: ctx, hash, prove func (_m *Client) Tx(ctx context.Context, hash []byte, prove bool) (*coretypes.ResultTx, error) { ret := _m.Called(ctx, hash, prove) + if len(ret) == 0 { + panic("no return value specified for Tx") + } + var r0 *coretypes.ResultTx + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, []byte, bool) (*coretypes.ResultTx, error)); ok { + return rf(ctx, hash, prove) + } if rf, ok := ret.Get(0).(func(context.Context, []byte, bool) *coretypes.ResultTx); ok { r0 = rf(ctx, hash, prove) } else { @@ -767,7 +2027,6 @@ func (_m *Client) Tx(ctx context.Context, hash []byte, prove bool) (*coretypes.R } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, []byte, bool) error); ok { r1 = rf(ctx, hash, prove) } else { @@ -777,11 +2036,49 @@ func (_m *Client) Tx(ctx context.Context, hash []byte, prove bool) (*coretypes.R return r0, r1 } +// Client_Tx_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Tx' +type Client_Tx_Call struct { + *mock.Call +} + +// Tx is a helper method to define mock.On call +// - ctx context.Context +// - hash []byte +// - prove bool +func (_e *Client_Expecter) Tx(ctx interface{}, hash interface{}, prove interface{}) *Client_Tx_Call { + return &Client_Tx_Call{Call: _e.mock.On("Tx", ctx, hash, prove)} +} + +func (_c *Client_Tx_Call) Run(run func(ctx context.Context, hash []byte, prove bool)) *Client_Tx_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].([]byte), args[2].(bool)) + }) + return _c +} + +func (_c *Client_Tx_Call) Return(_a0 *coretypes.ResultTx, _a1 error) *Client_Tx_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_Tx_Call) RunAndReturn(run func(context.Context, []byte, bool) (*coretypes.ResultTx, error)) *Client_Tx_Call { + _c.Call.Return(run) + return _c +} + // TxSearch provides a mock function with given fields: ctx, query, prove, page, perPage, orderBy func (_m *Client) TxSearch(ctx context.Context, query string, prove bool, page *int, perPage *int, orderBy string) (*coretypes.ResultTxSearch, error) { ret := _m.Called(ctx, query, prove, page, perPage, orderBy) + if len(ret) == 0 { + panic("no return value specified for TxSearch") + } + var r0 *coretypes.ResultTxSearch + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, bool, *int, *int, string) (*coretypes.ResultTxSearch, error)); ok { + return rf(ctx, query, prove, page, perPage, orderBy) + } if rf, ok := ret.Get(0).(func(context.Context, string, bool, *int, *int, string) *coretypes.ResultTxSearch); ok { r0 = rf(ctx, query, prove, page, perPage, orderBy) } else { @@ -790,7 +2087,6 @@ func (_m *Client) TxSearch(ctx context.Context, query string, prove bool, page * } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, string, bool, *int, *int, string) error); ok { r1 = rf(ctx, query, prove, page, perPage, orderBy) } else { @@ -800,11 +2096,52 @@ func (_m *Client) TxSearch(ctx context.Context, query string, prove bool, page * return r0, r1 } +// Client_TxSearch_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TxSearch' +type Client_TxSearch_Call struct { + *mock.Call +} + +// TxSearch is a helper method to define mock.On call +// - ctx context.Context +// - query string +// - prove bool +// - page *int +// - perPage *int +// - orderBy string +func (_e *Client_Expecter) TxSearch(ctx interface{}, query interface{}, prove interface{}, page interface{}, perPage interface{}, orderBy interface{}) *Client_TxSearch_Call { + return &Client_TxSearch_Call{Call: _e.mock.On("TxSearch", ctx, query, prove, page, perPage, orderBy)} +} + +func (_c *Client_TxSearch_Call) Run(run func(ctx context.Context, query string, prove bool, page *int, perPage *int, orderBy string)) *Client_TxSearch_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string), args[2].(bool), args[3].(*int), args[4].(*int), args[5].(string)) + }) + return _c +} + +func (_c *Client_TxSearch_Call) Return(_a0 *coretypes.ResultTxSearch, _a1 error) *Client_TxSearch_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_TxSearch_Call) RunAndReturn(run func(context.Context, string, bool, *int, *int, string) (*coretypes.ResultTxSearch, error)) *Client_TxSearch_Call { + _c.Call.Return(run) + return _c +} + // UnconfirmedTxs provides a mock function with given fields: ctx, limit func (_m *Client) UnconfirmedTxs(ctx context.Context, limit *int) (*coretypes.ResultUnconfirmedTxs, error) { ret := _m.Called(ctx, limit) + if len(ret) == 0 { + panic("no return value specified for UnconfirmedTxs") + } + var r0 *coretypes.ResultUnconfirmedTxs + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *int) (*coretypes.ResultUnconfirmedTxs, error)); ok { + return rf(ctx, limit) + } if rf, ok := ret.Get(0).(func(context.Context, *int) *coretypes.ResultUnconfirmedTxs); ok { r0 = rf(ctx, limit) } else { @@ -813,7 +2150,6 @@ func (_m *Client) UnconfirmedTxs(ctx context.Context, limit *int) (*coretypes.Re } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, *int) error); ok { r1 = rf(ctx, limit) } else { @@ -823,10 +2159,43 @@ func (_m *Client) UnconfirmedTxs(ctx context.Context, limit *int) (*coretypes.Re return r0, r1 } +// Client_UnconfirmedTxs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UnconfirmedTxs' +type Client_UnconfirmedTxs_Call struct { + *mock.Call +} + +// UnconfirmedTxs is a helper method to define mock.On call +// - ctx context.Context +// - limit *int +func (_e *Client_Expecter) UnconfirmedTxs(ctx interface{}, limit interface{}) *Client_UnconfirmedTxs_Call { + return &Client_UnconfirmedTxs_Call{Call: _e.mock.On("UnconfirmedTxs", ctx, limit)} +} + +func (_c *Client_UnconfirmedTxs_Call) Run(run func(ctx context.Context, limit *int)) *Client_UnconfirmedTxs_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*int)) + }) + return _c +} + +func (_c *Client_UnconfirmedTxs_Call) Return(_a0 *coretypes.ResultUnconfirmedTxs, _a1 error) *Client_UnconfirmedTxs_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_UnconfirmedTxs_Call) RunAndReturn(run func(context.Context, *int) (*coretypes.ResultUnconfirmedTxs, error)) *Client_UnconfirmedTxs_Call { + _c.Call.Return(run) + return _c +} + // Unsubscribe provides a mock function with given fields: ctx, subscriber, query func (_m *Client) Unsubscribe(ctx context.Context, subscriber string, query string) error { ret := _m.Called(ctx, subscriber, query) + if len(ret) == 0 { + panic("no return value specified for Unsubscribe") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, string, string) error); ok { r0 = rf(ctx, subscriber, query) @@ -837,10 +2206,44 @@ func (_m *Client) Unsubscribe(ctx context.Context, subscriber string, query stri return r0 } +// Client_Unsubscribe_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Unsubscribe' +type Client_Unsubscribe_Call struct { + *mock.Call +} + +// Unsubscribe is a helper method to define mock.On call +// - ctx context.Context +// - subscriber string +// - query string +func (_e *Client_Expecter) Unsubscribe(ctx interface{}, subscriber interface{}, query interface{}) *Client_Unsubscribe_Call { + return &Client_Unsubscribe_Call{Call: _e.mock.On("Unsubscribe", ctx, subscriber, query)} +} + +func (_c *Client_Unsubscribe_Call) Run(run func(ctx context.Context, subscriber string, query string)) *Client_Unsubscribe_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string), args[2].(string)) + }) + return _c +} + +func (_c *Client_Unsubscribe_Call) Return(_a0 error) *Client_Unsubscribe_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_Unsubscribe_Call) RunAndReturn(run func(context.Context, string, string) error) *Client_Unsubscribe_Call { + _c.Call.Return(run) + return _c +} + // UnsubscribeAll provides a mock function with given fields: ctx, subscriber func (_m *Client) UnsubscribeAll(ctx context.Context, subscriber string) error { ret := _m.Called(ctx, subscriber) + if len(ret) == 0 { + panic("no return value specified for UnsubscribeAll") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, string) error); ok { r0 = rf(ctx, subscriber) @@ -851,11 +2254,48 @@ func (_m *Client) UnsubscribeAll(ctx context.Context, subscriber string) error { return r0 } +// Client_UnsubscribeAll_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UnsubscribeAll' +type Client_UnsubscribeAll_Call struct { + *mock.Call +} + +// UnsubscribeAll is a helper method to define mock.On call +// - ctx context.Context +// - subscriber string +func (_e *Client_Expecter) UnsubscribeAll(ctx interface{}, subscriber interface{}) *Client_UnsubscribeAll_Call { + return &Client_UnsubscribeAll_Call{Call: _e.mock.On("UnsubscribeAll", ctx, subscriber)} +} + +func (_c *Client_UnsubscribeAll_Call) Run(run func(ctx context.Context, subscriber string)) *Client_UnsubscribeAll_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string)) + }) + return _c +} + +func (_c *Client_UnsubscribeAll_Call) Return(_a0 error) *Client_UnsubscribeAll_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_UnsubscribeAll_Call) RunAndReturn(run func(context.Context, string) error) *Client_UnsubscribeAll_Call { + _c.Call.Return(run) + return _c +} + // Validators provides a mock function with given fields: ctx, height, page, perPage func (_m *Client) Validators(ctx context.Context, height *int64, page *int, perPage *int) (*coretypes.ResultValidators, error) { ret := _m.Called(ctx, height, page, perPage) + if len(ret) == 0 { + panic("no return value specified for Validators") + } + var r0 *coretypes.ResultValidators + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *int64, *int, *int) (*coretypes.ResultValidators, error)); ok { + return rf(ctx, height, page, perPage) + } if rf, ok := ret.Get(0).(func(context.Context, *int64, *int, *int) *coretypes.ResultValidators); ok { r0 = rf(ctx, height, page, perPage) } else { @@ -864,7 +2304,6 @@ func (_m *Client) Validators(ctx context.Context, height *int64, page *int, perP } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, *int64, *int, *int) error); ok { r1 = rf(ctx, height, page, perPage) } else { @@ -874,13 +2313,44 @@ func (_m *Client) Validators(ctx context.Context, height *int64, page *int, perP return r0, r1 } -type mockConstructorTestingTNewClient interface { - mock.TestingT - Cleanup(func()) +// Client_Validators_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Validators' +type Client_Validators_Call struct { + *mock.Call +} + +// Validators is a helper method to define mock.On call +// - ctx context.Context +// - height *int64 +// - page *int +// - perPage *int +func (_e *Client_Expecter) Validators(ctx interface{}, height interface{}, page interface{}, perPage interface{}) *Client_Validators_Call { + return &Client_Validators_Call{Call: _e.mock.On("Validators", ctx, height, page, perPage)} +} + +func (_c *Client_Validators_Call) Run(run func(ctx context.Context, height *int64, page *int, perPage *int)) *Client_Validators_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*int64), args[2].(*int), args[3].(*int)) + }) + return _c +} + +func (_c *Client_Validators_Call) Return(_a0 *coretypes.ResultValidators, _a1 error) *Client_Validators_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_Validators_Call) RunAndReturn(run func(context.Context, *int64, *int, *int) (*coretypes.ResultValidators, error)) *Client_Validators_Call { + _c.Call.Return(run) + return _c } // NewClient creates a new instance of Client. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewClient(t mockConstructorTestingTNewClient) *Client { +// The first argument is typically a *testing.T value. +func NewClient(t interface { + mock.TestingT + Cleanup(func()) +}, +) *Client { mock := &Client{} mock.Mock.Test(t) diff --git a/rpc/backend/mocks/evm_query_client.go b/rpc/backend/mocks/evm_query_client.go index f62d963e..7ee7b485 100644 --- a/rpc/backend/mocks/evm_query_client.go +++ b/rpc/backend/mocks/evm_query_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.43.2. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks @@ -12,11 +12,19 @@ import ( types "github.com/cosmos/evm/x/vm/types" ) -// EVMQueryClient is an autogenerated mock type for the EVMQueryClient type +// EVMQueryClient is an autogenerated mock type for the QueryClient type type EVMQueryClient struct { mock.Mock } +type EVMQueryClient_Expecter struct { + mock *mock.Mock +} + +func (_m *EVMQueryClient) EXPECT() *EVMQueryClient_Expecter { + return &EVMQueryClient_Expecter{mock: &_m.Mock} +} + // Account provides a mock function with given fields: ctx, in, opts func (_m *EVMQueryClient) Account(ctx context.Context, in *types.QueryAccountRequest, opts ...grpc.CallOption) (*types.QueryAccountResponse, error) { _va := make([]interface{}, len(opts)) @@ -54,6 +62,43 @@ func (_m *EVMQueryClient) Account(ctx context.Context, in *types.QueryAccountReq return r0, r1 } +// EVMQueryClient_Account_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Account' +type EVMQueryClient_Account_Call struct { + *mock.Call +} + +// Account is a helper method to define mock.On call +// - ctx context.Context +// - in *types.QueryAccountRequest +// - opts ...grpc.CallOption +func (_e *EVMQueryClient_Expecter) Account(ctx interface{}, in interface{}, opts ...interface{}) *EVMQueryClient_Account_Call { + return &EVMQueryClient_Account_Call{Call: _e.mock.On("Account", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *EVMQueryClient_Account_Call) Run(run func(ctx context.Context, in *types.QueryAccountRequest, opts ...grpc.CallOption)) *EVMQueryClient_Account_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*types.QueryAccountRequest), variadicArgs...) + }) + return _c +} + +func (_c *EVMQueryClient_Account_Call) Return(_a0 *types.QueryAccountResponse, _a1 error) *EVMQueryClient_Account_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *EVMQueryClient_Account_Call) RunAndReturn(run func(context.Context, *types.QueryAccountRequest, ...grpc.CallOption) (*types.QueryAccountResponse, error)) *EVMQueryClient_Account_Call { + _c.Call.Return(run) + return _c +} + // Balance provides a mock function with given fields: ctx, in, opts func (_m *EVMQueryClient) Balance(ctx context.Context, in *types.QueryBalanceRequest, opts ...grpc.CallOption) (*types.QueryBalanceResponse, error) { _va := make([]interface{}, len(opts)) @@ -91,6 +136,43 @@ func (_m *EVMQueryClient) Balance(ctx context.Context, in *types.QueryBalanceReq return r0, r1 } +// EVMQueryClient_Balance_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Balance' +type EVMQueryClient_Balance_Call struct { + *mock.Call +} + +// Balance is a helper method to define mock.On call +// - ctx context.Context +// - in *types.QueryBalanceRequest +// - opts ...grpc.CallOption +func (_e *EVMQueryClient_Expecter) Balance(ctx interface{}, in interface{}, opts ...interface{}) *EVMQueryClient_Balance_Call { + return &EVMQueryClient_Balance_Call{Call: _e.mock.On("Balance", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *EVMQueryClient_Balance_Call) Run(run func(ctx context.Context, in *types.QueryBalanceRequest, opts ...grpc.CallOption)) *EVMQueryClient_Balance_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*types.QueryBalanceRequest), variadicArgs...) + }) + return _c +} + +func (_c *EVMQueryClient_Balance_Call) Return(_a0 *types.QueryBalanceResponse, _a1 error) *EVMQueryClient_Balance_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *EVMQueryClient_Balance_Call) RunAndReturn(run func(context.Context, *types.QueryBalanceRequest, ...grpc.CallOption) (*types.QueryBalanceResponse, error)) *EVMQueryClient_Balance_Call { + _c.Call.Return(run) + return _c +} + // BaseFee provides a mock function with given fields: ctx, in, opts func (_m *EVMQueryClient) BaseFee(ctx context.Context, in *types.QueryBaseFeeRequest, opts ...grpc.CallOption) (*types.QueryBaseFeeResponse, error) { _va := make([]interface{}, len(opts)) @@ -128,6 +210,43 @@ func (_m *EVMQueryClient) BaseFee(ctx context.Context, in *types.QueryBaseFeeReq return r0, r1 } +// EVMQueryClient_BaseFee_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BaseFee' +type EVMQueryClient_BaseFee_Call struct { + *mock.Call +} + +// BaseFee is a helper method to define mock.On call +// - ctx context.Context +// - in *types.QueryBaseFeeRequest +// - opts ...grpc.CallOption +func (_e *EVMQueryClient_Expecter) BaseFee(ctx interface{}, in interface{}, opts ...interface{}) *EVMQueryClient_BaseFee_Call { + return &EVMQueryClient_BaseFee_Call{Call: _e.mock.On("BaseFee", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *EVMQueryClient_BaseFee_Call) Run(run func(ctx context.Context, in *types.QueryBaseFeeRequest, opts ...grpc.CallOption)) *EVMQueryClient_BaseFee_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*types.QueryBaseFeeRequest), variadicArgs...) + }) + return _c +} + +func (_c *EVMQueryClient_BaseFee_Call) Return(_a0 *types.QueryBaseFeeResponse, _a1 error) *EVMQueryClient_BaseFee_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *EVMQueryClient_BaseFee_Call) RunAndReturn(run func(context.Context, *types.QueryBaseFeeRequest, ...grpc.CallOption) (*types.QueryBaseFeeResponse, error)) *EVMQueryClient_BaseFee_Call { + _c.Call.Return(run) + return _c +} + // Code provides a mock function with given fields: ctx, in, opts func (_m *EVMQueryClient) Code(ctx context.Context, in *types.QueryCodeRequest, opts ...grpc.CallOption) (*types.QueryCodeResponse, error) { _va := make([]interface{}, len(opts)) @@ -165,8 +284,45 @@ func (_m *EVMQueryClient) Code(ctx context.Context, in *types.QueryCodeRequest, return r0, r1 } -// CosmosAccount provides a mock function with given fields: ctx, in, opts -func (_m *EVMQueryClient) CosmosAccount(ctx context.Context, in *types.QueryCosmosAccountRequest, opts ...grpc.CallOption) (*types.QueryCosmosAccountResponse, error) { +// EVMQueryClient_Code_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Code' +type EVMQueryClient_Code_Call struct { + *mock.Call +} + +// Code is a helper method to define mock.On call +// - ctx context.Context +// - in *types.QueryCodeRequest +// - opts ...grpc.CallOption +func (_e *EVMQueryClient_Expecter) Code(ctx interface{}, in interface{}, opts ...interface{}) *EVMQueryClient_Code_Call { + return &EVMQueryClient_Code_Call{Call: _e.mock.On("Code", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *EVMQueryClient_Code_Call) Run(run func(ctx context.Context, in *types.QueryCodeRequest, opts ...grpc.CallOption)) *EVMQueryClient_Code_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*types.QueryCodeRequest), variadicArgs...) + }) + return _c +} + +func (_c *EVMQueryClient_Code_Call) Return(_a0 *types.QueryCodeResponse, _a1 error) *EVMQueryClient_Code_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *EVMQueryClient_Code_Call) RunAndReturn(run func(context.Context, *types.QueryCodeRequest, ...grpc.CallOption) (*types.QueryCodeResponse, error)) *EVMQueryClient_Code_Call { + _c.Call.Return(run) + return _c +} + +// Config provides a mock function with given fields: ctx, in, opts +func (_m *EVMQueryClient) Config(ctx context.Context, in *types.QueryConfigRequest, opts ...grpc.CallOption) (*types.QueryConfigResponse, error) { _va := make([]interface{}, len(opts)) for _i := range opts { _va[_i] = opts[_i] @@ -177,23 +333,23 @@ func (_m *EVMQueryClient) CosmosAccount(ctx context.Context, in *types.QueryCosm ret := _m.Called(_ca...) if len(ret) == 0 { - panic("no return value specified for CosmosAccount") + panic("no return value specified for Config") } - var r0 *types.QueryCosmosAccountResponse + var r0 *types.QueryConfigResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.QueryCosmosAccountRequest, ...grpc.CallOption) (*types.QueryCosmosAccountResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryConfigRequest, ...grpc.CallOption) (*types.QueryConfigResponse, error)); ok { return rf(ctx, in, opts...) } - if rf, ok := ret.Get(0).(func(context.Context, *types.QueryCosmosAccountRequest, ...grpc.CallOption) *types.QueryCosmosAccountResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryConfigRequest, ...grpc.CallOption) *types.QueryConfigResponse); ok { r0 = rf(ctx, in, opts...) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.QueryCosmosAccountResponse) + r0 = ret.Get(0).(*types.QueryConfigResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.QueryCosmosAccountRequest, ...grpc.CallOption) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryConfigRequest, ...grpc.CallOption) error); ok { r1 = rf(ctx, in, opts...) } else { r1 = ret.Error(1) @@ -202,8 +358,45 @@ func (_m *EVMQueryClient) CosmosAccount(ctx context.Context, in *types.QueryCosm return r0, r1 } -// EstimateGas provides a mock function with given fields: ctx, in, opts -func (_m *EVMQueryClient) EstimateGas(ctx context.Context, in *types.EthCallRequest, opts ...grpc.CallOption) (*types.EstimateGasResponse, error) { +// EVMQueryClient_Config_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Config' +type EVMQueryClient_Config_Call struct { + *mock.Call +} + +// Config is a helper method to define mock.On call +// - ctx context.Context +// - in *types.QueryConfigRequest +// - opts ...grpc.CallOption +func (_e *EVMQueryClient_Expecter) Config(ctx interface{}, in interface{}, opts ...interface{}) *EVMQueryClient_Config_Call { + return &EVMQueryClient_Config_Call{Call: _e.mock.On("Config", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *EVMQueryClient_Config_Call) Run(run func(ctx context.Context, in *types.QueryConfigRequest, opts ...grpc.CallOption)) *EVMQueryClient_Config_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*types.QueryConfigRequest), variadicArgs...) + }) + return _c +} + +func (_c *EVMQueryClient_Config_Call) Return(_a0 *types.QueryConfigResponse, _a1 error) *EVMQueryClient_Config_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *EVMQueryClient_Config_Call) RunAndReturn(run func(context.Context, *types.QueryConfigRequest, ...grpc.CallOption) (*types.QueryConfigResponse, error)) *EVMQueryClient_Config_Call { + _c.Call.Return(run) + return _c +} + +// CosmosAccount provides a mock function with given fields: ctx, in, opts +func (_m *EVMQueryClient) CosmosAccount(ctx context.Context, in *types.QueryCosmosAccountRequest, opts ...grpc.CallOption) (*types.QueryCosmosAccountResponse, error) { _va := make([]interface{}, len(opts)) for _i := range opts { _va[_i] = opts[_i] @@ -214,23 +407,23 @@ func (_m *EVMQueryClient) EstimateGas(ctx context.Context, in *types.EthCallRequ ret := _m.Called(_ca...) if len(ret) == 0 { - panic("no return value specified for EstimateGas") + panic("no return value specified for CosmosAccount") } - var r0 *types.EstimateGasResponse + var r0 *types.QueryCosmosAccountResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.EthCallRequest, ...grpc.CallOption) (*types.EstimateGasResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryCosmosAccountRequest, ...grpc.CallOption) (*types.QueryCosmosAccountResponse, error)); ok { return rf(ctx, in, opts...) } - if rf, ok := ret.Get(0).(func(context.Context, *types.EthCallRequest, ...grpc.CallOption) *types.EstimateGasResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryCosmosAccountRequest, ...grpc.CallOption) *types.QueryCosmosAccountResponse); ok { r0 = rf(ctx, in, opts...) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.EstimateGasResponse) + r0 = ret.Get(0).(*types.QueryCosmosAccountResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.EthCallRequest, ...grpc.CallOption) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryCosmosAccountRequest, ...grpc.CallOption) error); ok { r1 = rf(ctx, in, opts...) } else { r1 = ret.Error(1) @@ -239,8 +432,45 @@ func (_m *EVMQueryClient) EstimateGas(ctx context.Context, in *types.EthCallRequ return r0, r1 } -// GlobalMinGasPrice provides a mock function with given fields: ctx, in, opts -func (_m *EVMQueryClient) GlobalMinGasPrice(ctx context.Context, in *types.QueryGlobalMinGasPriceRequest, opts ...grpc.CallOption) (*types.QueryGlobalMinGasPriceResponse, error) { +// EVMQueryClient_CosmosAccount_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CosmosAccount' +type EVMQueryClient_CosmosAccount_Call struct { + *mock.Call +} + +// CosmosAccount is a helper method to define mock.On call +// - ctx context.Context +// - in *types.QueryCosmosAccountRequest +// - opts ...grpc.CallOption +func (_e *EVMQueryClient_Expecter) CosmosAccount(ctx interface{}, in interface{}, opts ...interface{}) *EVMQueryClient_CosmosAccount_Call { + return &EVMQueryClient_CosmosAccount_Call{Call: _e.mock.On("CosmosAccount", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *EVMQueryClient_CosmosAccount_Call) Run(run func(ctx context.Context, in *types.QueryCosmosAccountRequest, opts ...grpc.CallOption)) *EVMQueryClient_CosmosAccount_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*types.QueryCosmosAccountRequest), variadicArgs...) + }) + return _c +} + +func (_c *EVMQueryClient_CosmosAccount_Call) Return(_a0 *types.QueryCosmosAccountResponse, _a1 error) *EVMQueryClient_CosmosAccount_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *EVMQueryClient_CosmosAccount_Call) RunAndReturn(run func(context.Context, *types.QueryCosmosAccountRequest, ...grpc.CallOption) (*types.QueryCosmosAccountResponse, error)) *EVMQueryClient_CosmosAccount_Call { + _c.Call.Return(run) + return _c +} + +// EstimateGas provides a mock function with given fields: ctx, in, opts +func (_m *EVMQueryClient) EstimateGas(ctx context.Context, in *types.EthCallRequest, opts ...grpc.CallOption) (*types.EstimateGasResponse, error) { _va := make([]interface{}, len(opts)) for _i := range opts { _va[_i] = opts[_i] @@ -250,17 +480,24 @@ func (_m *EVMQueryClient) GlobalMinGasPrice(ctx context.Context, in *types.Query _ca = append(_ca, _va...) ret := _m.Called(_ca...) - var r0 *types.QueryGlobalMinGasPriceResponse - if rf, ok := ret.Get(0).(func(context.Context, *types.QueryGlobalMinGasPriceRequest, ...grpc.CallOption) *types.QueryGlobalMinGasPriceResponse); ok { + if len(ret) == 0 { + panic("no return value specified for EstimateGas") + } + + var r0 *types.EstimateGasResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *types.EthCallRequest, ...grpc.CallOption) (*types.EstimateGasResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *types.EthCallRequest, ...grpc.CallOption) *types.EstimateGasResponse); ok { r0 = rf(ctx, in, opts...) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.QueryGlobalMinGasPriceResponse) + r0 = ret.Get(0).(*types.EstimateGasResponse) } } - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, *types.QueryGlobalMinGasPriceRequest, ...grpc.CallOption) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *types.EthCallRequest, ...grpc.CallOption) error); ok { r1 = rf(ctx, in, opts...) } else { r1 = ret.Error(1) @@ -269,8 +506,45 @@ func (_m *EVMQueryClient) GlobalMinGasPrice(ctx context.Context, in *types.Query return r0, r1 } -// Config provides a mock function with given fields: ctx, in, opts -func (_m *EVMQueryClient) Config(ctx context.Context, in *types.QueryConfigRequest, opts ...grpc.CallOption) (*types.QueryConfigResponse, error) { +// EVMQueryClient_EstimateGas_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EstimateGas' +type EVMQueryClient_EstimateGas_Call struct { + *mock.Call +} + +// EstimateGas is a helper method to define mock.On call +// - ctx context.Context +// - in *types.EthCallRequest +// - opts ...grpc.CallOption +func (_e *EVMQueryClient_Expecter) EstimateGas(ctx interface{}, in interface{}, opts ...interface{}) *EVMQueryClient_EstimateGas_Call { + return &EVMQueryClient_EstimateGas_Call{Call: _e.mock.On("EstimateGas", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *EVMQueryClient_EstimateGas_Call) Run(run func(ctx context.Context, in *types.EthCallRequest, opts ...grpc.CallOption)) *EVMQueryClient_EstimateGas_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*types.EthCallRequest), variadicArgs...) + }) + return _c +} + +func (_c *EVMQueryClient_EstimateGas_Call) Return(_a0 *types.EstimateGasResponse, _a1 error) *EVMQueryClient_EstimateGas_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *EVMQueryClient_EstimateGas_Call) RunAndReturn(run func(context.Context, *types.EthCallRequest, ...grpc.CallOption) (*types.EstimateGasResponse, error)) *EVMQueryClient_EstimateGas_Call { + _c.Call.Return(run) + return _c +} + +// EthCall provides a mock function with given fields: ctx, in, opts +func (_m *EVMQueryClient) EthCall(ctx context.Context, in *types.EthCallRequest, opts ...grpc.CallOption) (*types.MsgEthereumTxResponse, error) { _va := make([]interface{}, len(opts)) for _i := range opts { _va[_i] = opts[_i] @@ -281,23 +555,23 @@ func (_m *EVMQueryClient) Config(ctx context.Context, in *types.QueryConfigReque ret := _m.Called(_ca...) if len(ret) == 0 { - panic("no return value specified for Config") + panic("no return value specified for EthCall") } - var r0 *types.QueryConfigResponse + var r0 *types.MsgEthereumTxResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.QueryConfigRequest, ...grpc.CallOption) (*types.QueryConfigResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *types.EthCallRequest, ...grpc.CallOption) (*types.MsgEthereumTxResponse, error)); ok { return rf(ctx, in, opts...) } - if rf, ok := ret.Get(0).(func(context.Context, *types.QueryConfigRequest, ...grpc.CallOption) *types.QueryConfigResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, *types.EthCallRequest, ...grpc.CallOption) *types.MsgEthereumTxResponse); ok { r0 = rf(ctx, in, opts...) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.QueryConfigResponse) + r0 = ret.Get(0).(*types.MsgEthereumTxResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.QueryConfigRequest, ...grpc.CallOption) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *types.EthCallRequest, ...grpc.CallOption) error); ok { r1 = rf(ctx, in, opts...) } else { r1 = ret.Error(1) @@ -306,8 +580,45 @@ func (_m *EVMQueryClient) Config(ctx context.Context, in *types.QueryConfigReque return r0, r1 } -// EthCall provides a mock function with given fields: ctx, in, opts -func (_m *EVMQueryClient) EthCall(ctx context.Context, in *types.EthCallRequest, opts ...grpc.CallOption) (*types.MsgEthereumTxResponse, error) { +// EVMQueryClient_EthCall_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EthCall' +type EVMQueryClient_EthCall_Call struct { + *mock.Call +} + +// EthCall is a helper method to define mock.On call +// - ctx context.Context +// - in *types.EthCallRequest +// - opts ...grpc.CallOption +func (_e *EVMQueryClient_Expecter) EthCall(ctx interface{}, in interface{}, opts ...interface{}) *EVMQueryClient_EthCall_Call { + return &EVMQueryClient_EthCall_Call{Call: _e.mock.On("EthCall", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *EVMQueryClient_EthCall_Call) Run(run func(ctx context.Context, in *types.EthCallRequest, opts ...grpc.CallOption)) *EVMQueryClient_EthCall_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*types.EthCallRequest), variadicArgs...) + }) + return _c +} + +func (_c *EVMQueryClient_EthCall_Call) Return(_a0 *types.MsgEthereumTxResponse, _a1 error) *EVMQueryClient_EthCall_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *EVMQueryClient_EthCall_Call) RunAndReturn(run func(context.Context, *types.EthCallRequest, ...grpc.CallOption) (*types.MsgEthereumTxResponse, error)) *EVMQueryClient_EthCall_Call { + _c.Call.Return(run) + return _c +} + +// GlobalMinGasPrice provides a mock function with given fields: ctx, in, opts +func (_m *EVMQueryClient) GlobalMinGasPrice(ctx context.Context, in *types.QueryGlobalMinGasPriceRequest, opts ...grpc.CallOption) (*types.QueryGlobalMinGasPriceResponse, error) { _va := make([]interface{}, len(opts)) for _i := range opts { _va[_i] = opts[_i] @@ -318,23 +629,23 @@ func (_m *EVMQueryClient) EthCall(ctx context.Context, in *types.EthCallRequest, ret := _m.Called(_ca...) if len(ret) == 0 { - panic("no return value specified for EthCall") + panic("no return value specified for GlobalMinGasPrice") } - var r0 *types.MsgEthereumTxResponse + var r0 *types.QueryGlobalMinGasPriceResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.EthCallRequest, ...grpc.CallOption) (*types.MsgEthereumTxResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryGlobalMinGasPriceRequest, ...grpc.CallOption) (*types.QueryGlobalMinGasPriceResponse, error)); ok { return rf(ctx, in, opts...) } - if rf, ok := ret.Get(0).(func(context.Context, *types.EthCallRequest, ...grpc.CallOption) *types.MsgEthereumTxResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryGlobalMinGasPriceRequest, ...grpc.CallOption) *types.QueryGlobalMinGasPriceResponse); ok { r0 = rf(ctx, in, opts...) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.MsgEthereumTxResponse) + r0 = ret.Get(0).(*types.QueryGlobalMinGasPriceResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.EthCallRequest, ...grpc.CallOption) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryGlobalMinGasPriceRequest, ...grpc.CallOption) error); ok { r1 = rf(ctx, in, opts...) } else { r1 = ret.Error(1) @@ -343,6 +654,43 @@ func (_m *EVMQueryClient) EthCall(ctx context.Context, in *types.EthCallRequest, return r0, r1 } +// EVMQueryClient_GlobalMinGasPrice_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GlobalMinGasPrice' +type EVMQueryClient_GlobalMinGasPrice_Call struct { + *mock.Call +} + +// GlobalMinGasPrice is a helper method to define mock.On call +// - ctx context.Context +// - in *types.QueryGlobalMinGasPriceRequest +// - opts ...grpc.CallOption +func (_e *EVMQueryClient_Expecter) GlobalMinGasPrice(ctx interface{}, in interface{}, opts ...interface{}) *EVMQueryClient_GlobalMinGasPrice_Call { + return &EVMQueryClient_GlobalMinGasPrice_Call{Call: _e.mock.On("GlobalMinGasPrice", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *EVMQueryClient_GlobalMinGasPrice_Call) Run(run func(ctx context.Context, in *types.QueryGlobalMinGasPriceRequest, opts ...grpc.CallOption)) *EVMQueryClient_GlobalMinGasPrice_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*types.QueryGlobalMinGasPriceRequest), variadicArgs...) + }) + return _c +} + +func (_c *EVMQueryClient_GlobalMinGasPrice_Call) Return(_a0 *types.QueryGlobalMinGasPriceResponse, _a1 error) *EVMQueryClient_GlobalMinGasPrice_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *EVMQueryClient_GlobalMinGasPrice_Call) RunAndReturn(run func(context.Context, *types.QueryGlobalMinGasPriceRequest, ...grpc.CallOption) (*types.QueryGlobalMinGasPriceResponse, error)) *EVMQueryClient_GlobalMinGasPrice_Call { + _c.Call.Return(run) + return _c +} + // Params provides a mock function with given fields: ctx, in, opts func (_m *EVMQueryClient) Params(ctx context.Context, in *types.QueryParamsRequest, opts ...grpc.CallOption) (*types.QueryParamsResponse, error) { _va := make([]interface{}, len(opts)) @@ -380,6 +728,43 @@ func (_m *EVMQueryClient) Params(ctx context.Context, in *types.QueryParamsReque return r0, r1 } +// EVMQueryClient_Params_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Params' +type EVMQueryClient_Params_Call struct { + *mock.Call +} + +// Params is a helper method to define mock.On call +// - ctx context.Context +// - in *types.QueryParamsRequest +// - opts ...grpc.CallOption +func (_e *EVMQueryClient_Expecter) Params(ctx interface{}, in interface{}, opts ...interface{}) *EVMQueryClient_Params_Call { + return &EVMQueryClient_Params_Call{Call: _e.mock.On("Params", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *EVMQueryClient_Params_Call) Run(run func(ctx context.Context, in *types.QueryParamsRequest, opts ...grpc.CallOption)) *EVMQueryClient_Params_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*types.QueryParamsRequest), variadicArgs...) + }) + return _c +} + +func (_c *EVMQueryClient_Params_Call) Return(_a0 *types.QueryParamsResponse, _a1 error) *EVMQueryClient_Params_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *EVMQueryClient_Params_Call) RunAndReturn(run func(context.Context, *types.QueryParamsRequest, ...grpc.CallOption) (*types.QueryParamsResponse, error)) *EVMQueryClient_Params_Call { + _c.Call.Return(run) + return _c +} + // Storage provides a mock function with given fields: ctx, in, opts func (_m *EVMQueryClient) Storage(ctx context.Context, in *types.QueryStorageRequest, opts ...grpc.CallOption) (*types.QueryStorageResponse, error) { _va := make([]interface{}, len(opts)) @@ -417,6 +802,43 @@ func (_m *EVMQueryClient) Storage(ctx context.Context, in *types.QueryStorageReq return r0, r1 } +// EVMQueryClient_Storage_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Storage' +type EVMQueryClient_Storage_Call struct { + *mock.Call +} + +// Storage is a helper method to define mock.On call +// - ctx context.Context +// - in *types.QueryStorageRequest +// - opts ...grpc.CallOption +func (_e *EVMQueryClient_Expecter) Storage(ctx interface{}, in interface{}, opts ...interface{}) *EVMQueryClient_Storage_Call { + return &EVMQueryClient_Storage_Call{Call: _e.mock.On("Storage", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *EVMQueryClient_Storage_Call) Run(run func(ctx context.Context, in *types.QueryStorageRequest, opts ...grpc.CallOption)) *EVMQueryClient_Storage_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*types.QueryStorageRequest), variadicArgs...) + }) + return _c +} + +func (_c *EVMQueryClient_Storage_Call) Return(_a0 *types.QueryStorageResponse, _a1 error) *EVMQueryClient_Storage_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *EVMQueryClient_Storage_Call) RunAndReturn(run func(context.Context, *types.QueryStorageRequest, ...grpc.CallOption) (*types.QueryStorageResponse, error)) *EVMQueryClient_Storage_Call { + _c.Call.Return(run) + return _c +} + // TraceBlock provides a mock function with given fields: ctx, in, opts func (_m *EVMQueryClient) TraceBlock(ctx context.Context, in *types.QueryTraceBlockRequest, opts ...grpc.CallOption) (*types.QueryTraceBlockResponse, error) { _va := make([]interface{}, len(opts)) @@ -454,6 +876,43 @@ func (_m *EVMQueryClient) TraceBlock(ctx context.Context, in *types.QueryTraceBl return r0, r1 } +// EVMQueryClient_TraceBlock_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TraceBlock' +type EVMQueryClient_TraceBlock_Call struct { + *mock.Call +} + +// TraceBlock is a helper method to define mock.On call +// - ctx context.Context +// - in *types.QueryTraceBlockRequest +// - opts ...grpc.CallOption +func (_e *EVMQueryClient_Expecter) TraceBlock(ctx interface{}, in interface{}, opts ...interface{}) *EVMQueryClient_TraceBlock_Call { + return &EVMQueryClient_TraceBlock_Call{Call: _e.mock.On("TraceBlock", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *EVMQueryClient_TraceBlock_Call) Run(run func(ctx context.Context, in *types.QueryTraceBlockRequest, opts ...grpc.CallOption)) *EVMQueryClient_TraceBlock_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*types.QueryTraceBlockRequest), variadicArgs...) + }) + return _c +} + +func (_c *EVMQueryClient_TraceBlock_Call) Return(_a0 *types.QueryTraceBlockResponse, _a1 error) *EVMQueryClient_TraceBlock_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *EVMQueryClient_TraceBlock_Call) RunAndReturn(run func(context.Context, *types.QueryTraceBlockRequest, ...grpc.CallOption) (*types.QueryTraceBlockResponse, error)) *EVMQueryClient_TraceBlock_Call { + _c.Call.Return(run) + return _c +} + // TraceCall provides a mock function with given fields: ctx, in, opts func (_m *EVMQueryClient) TraceCall(ctx context.Context, in *types.QueryTraceCallRequest, opts ...grpc.CallOption) (*types.QueryTraceCallResponse, error) { _va := make([]interface{}, len(opts)) @@ -491,6 +950,43 @@ func (_m *EVMQueryClient) TraceCall(ctx context.Context, in *types.QueryTraceCal return r0, r1 } +// EVMQueryClient_TraceCall_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TraceCall' +type EVMQueryClient_TraceCall_Call struct { + *mock.Call +} + +// TraceCall is a helper method to define mock.On call +// - ctx context.Context +// - in *types.QueryTraceCallRequest +// - opts ...grpc.CallOption +func (_e *EVMQueryClient_Expecter) TraceCall(ctx interface{}, in interface{}, opts ...interface{}) *EVMQueryClient_TraceCall_Call { + return &EVMQueryClient_TraceCall_Call{Call: _e.mock.On("TraceCall", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *EVMQueryClient_TraceCall_Call) Run(run func(ctx context.Context, in *types.QueryTraceCallRequest, opts ...grpc.CallOption)) *EVMQueryClient_TraceCall_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*types.QueryTraceCallRequest), variadicArgs...) + }) + return _c +} + +func (_c *EVMQueryClient_TraceCall_Call) Return(_a0 *types.QueryTraceCallResponse, _a1 error) *EVMQueryClient_TraceCall_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *EVMQueryClient_TraceCall_Call) RunAndReturn(run func(context.Context, *types.QueryTraceCallRequest, ...grpc.CallOption) (*types.QueryTraceCallResponse, error)) *EVMQueryClient_TraceCall_Call { + _c.Call.Return(run) + return _c +} + // TraceTx provides a mock function with given fields: ctx, in, opts func (_m *EVMQueryClient) TraceTx(ctx context.Context, in *types.QueryTraceTxRequest, opts ...grpc.CallOption) (*types.QueryTraceTxResponse, error) { _va := make([]interface{}, len(opts)) @@ -528,6 +1024,43 @@ func (_m *EVMQueryClient) TraceTx(ctx context.Context, in *types.QueryTraceTxReq return r0, r1 } +// EVMQueryClient_TraceTx_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TraceTx' +type EVMQueryClient_TraceTx_Call struct { + *mock.Call +} + +// TraceTx is a helper method to define mock.On call +// - ctx context.Context +// - in *types.QueryTraceTxRequest +// - opts ...grpc.CallOption +func (_e *EVMQueryClient_Expecter) TraceTx(ctx interface{}, in interface{}, opts ...interface{}) *EVMQueryClient_TraceTx_Call { + return &EVMQueryClient_TraceTx_Call{Call: _e.mock.On("TraceTx", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *EVMQueryClient_TraceTx_Call) Run(run func(ctx context.Context, in *types.QueryTraceTxRequest, opts ...grpc.CallOption)) *EVMQueryClient_TraceTx_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*types.QueryTraceTxRequest), variadicArgs...) + }) + return _c +} + +func (_c *EVMQueryClient_TraceTx_Call) Return(_a0 *types.QueryTraceTxResponse, _a1 error) *EVMQueryClient_TraceTx_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *EVMQueryClient_TraceTx_Call) RunAndReturn(run func(context.Context, *types.QueryTraceTxRequest, ...grpc.CallOption) (*types.QueryTraceTxResponse, error)) *EVMQueryClient_TraceTx_Call { + _c.Call.Return(run) + return _c +} + // ValidatorAccount provides a mock function with given fields: ctx, in, opts func (_m *EVMQueryClient) ValidatorAccount(ctx context.Context, in *types.QueryValidatorAccountRequest, opts ...grpc.CallOption) (*types.QueryValidatorAccountResponse, error) { _va := make([]interface{}, len(opts)) @@ -565,6 +1098,43 @@ func (_m *EVMQueryClient) ValidatorAccount(ctx context.Context, in *types.QueryV return r0, r1 } +// EVMQueryClient_ValidatorAccount_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ValidatorAccount' +type EVMQueryClient_ValidatorAccount_Call struct { + *mock.Call +} + +// ValidatorAccount is a helper method to define mock.On call +// - ctx context.Context +// - in *types.QueryValidatorAccountRequest +// - opts ...grpc.CallOption +func (_e *EVMQueryClient_Expecter) ValidatorAccount(ctx interface{}, in interface{}, opts ...interface{}) *EVMQueryClient_ValidatorAccount_Call { + return &EVMQueryClient_ValidatorAccount_Call{Call: _e.mock.On("ValidatorAccount", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *EVMQueryClient_ValidatorAccount_Call) Run(run func(ctx context.Context, in *types.QueryValidatorAccountRequest, opts ...grpc.CallOption)) *EVMQueryClient_ValidatorAccount_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*types.QueryValidatorAccountRequest), variadicArgs...) + }) + return _c +} + +func (_c *EVMQueryClient_ValidatorAccount_Call) Return(_a0 *types.QueryValidatorAccountResponse, _a1 error) *EVMQueryClient_ValidatorAccount_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *EVMQueryClient_ValidatorAccount_Call) RunAndReturn(run func(context.Context, *types.QueryValidatorAccountRequest, ...grpc.CallOption) (*types.QueryValidatorAccountResponse, error)) *EVMQueryClient_ValidatorAccount_Call { + _c.Call.Return(run) + return _c +} + // NewEVMQueryClient creates a new instance of EVMQueryClient. 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 NewEVMQueryClient(t interface { diff --git a/rpc/backend/mocks/feemarket_query_client.go b/rpc/backend/mocks/feemarket_query_client.go index 42f0a853..9027e8f1 100644 --- a/rpc/backend/mocks/feemarket_query_client.go +++ b/rpc/backend/mocks/feemarket_query_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.14.1. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks @@ -17,6 +17,14 @@ type FeeMarketQueryClient struct { mock.Mock } +type FeeMarketQueryClient_Expecter struct { + mock *mock.Mock +} + +func (_m *FeeMarketQueryClient) EXPECT() *FeeMarketQueryClient_Expecter { + return &FeeMarketQueryClient_Expecter{mock: &_m.Mock} +} + // BaseFee provides a mock function with given fields: ctx, in, opts func (_m *FeeMarketQueryClient) BaseFee(ctx context.Context, in *types.QueryBaseFeeRequest, opts ...grpc.CallOption) (*types.QueryBaseFeeResponse, error) { _va := make([]interface{}, len(opts)) @@ -28,7 +36,15 @@ func (_m *FeeMarketQueryClient) BaseFee(ctx context.Context, in *types.QueryBase _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for BaseFee") + } + var r0 *types.QueryBaseFeeResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryBaseFeeRequest, ...grpc.CallOption) (*types.QueryBaseFeeResponse, error)); ok { + return rf(ctx, in, opts...) + } if rf, ok := ret.Get(0).(func(context.Context, *types.QueryBaseFeeRequest, ...grpc.CallOption) *types.QueryBaseFeeResponse); ok { r0 = rf(ctx, in, opts...) } else { @@ -37,7 +53,6 @@ func (_m *FeeMarketQueryClient) BaseFee(ctx context.Context, in *types.QueryBase } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, *types.QueryBaseFeeRequest, ...grpc.CallOption) error); ok { r1 = rf(ctx, in, opts...) } else { @@ -47,6 +62,43 @@ func (_m *FeeMarketQueryClient) BaseFee(ctx context.Context, in *types.QueryBase return r0, r1 } +// FeeMarketQueryClient_BaseFee_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BaseFee' +type FeeMarketQueryClient_BaseFee_Call struct { + *mock.Call +} + +// BaseFee is a helper method to define mock.On call +// - ctx context.Context +// - in *types.QueryBaseFeeRequest +// - opts ...grpc.CallOption +func (_e *FeeMarketQueryClient_Expecter) BaseFee(ctx interface{}, in interface{}, opts ...interface{}) *FeeMarketQueryClient_BaseFee_Call { + return &FeeMarketQueryClient_BaseFee_Call{Call: _e.mock.On("BaseFee", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *FeeMarketQueryClient_BaseFee_Call) Run(run func(ctx context.Context, in *types.QueryBaseFeeRequest, opts ...grpc.CallOption)) *FeeMarketQueryClient_BaseFee_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*types.QueryBaseFeeRequest), variadicArgs...) + }) + return _c +} + +func (_c *FeeMarketQueryClient_BaseFee_Call) Return(_a0 *types.QueryBaseFeeResponse, _a1 error) *FeeMarketQueryClient_BaseFee_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeMarketQueryClient_BaseFee_Call) RunAndReturn(run func(context.Context, *types.QueryBaseFeeRequest, ...grpc.CallOption) (*types.QueryBaseFeeResponse, error)) *FeeMarketQueryClient_BaseFee_Call { + _c.Call.Return(run) + return _c +} + // BlockGas provides a mock function with given fields: ctx, in, opts func (_m *FeeMarketQueryClient) BlockGas(ctx context.Context, in *types.QueryBlockGasRequest, opts ...grpc.CallOption) (*types.QueryBlockGasResponse, error) { _va := make([]interface{}, len(opts)) @@ -58,7 +110,15 @@ func (_m *FeeMarketQueryClient) BlockGas(ctx context.Context, in *types.QueryBlo _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for BlockGas") + } + var r0 *types.QueryBlockGasResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryBlockGasRequest, ...grpc.CallOption) (*types.QueryBlockGasResponse, error)); ok { + return rf(ctx, in, opts...) + } if rf, ok := ret.Get(0).(func(context.Context, *types.QueryBlockGasRequest, ...grpc.CallOption) *types.QueryBlockGasResponse); ok { r0 = rf(ctx, in, opts...) } else { @@ -67,7 +127,6 @@ func (_m *FeeMarketQueryClient) BlockGas(ctx context.Context, in *types.QueryBlo } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, *types.QueryBlockGasRequest, ...grpc.CallOption) error); ok { r1 = rf(ctx, in, opts...) } else { @@ -77,6 +136,43 @@ func (_m *FeeMarketQueryClient) BlockGas(ctx context.Context, in *types.QueryBlo return r0, r1 } +// FeeMarketQueryClient_BlockGas_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BlockGas' +type FeeMarketQueryClient_BlockGas_Call struct { + *mock.Call +} + +// BlockGas is a helper method to define mock.On call +// - ctx context.Context +// - in *types.QueryBlockGasRequest +// - opts ...grpc.CallOption +func (_e *FeeMarketQueryClient_Expecter) BlockGas(ctx interface{}, in interface{}, opts ...interface{}) *FeeMarketQueryClient_BlockGas_Call { + return &FeeMarketQueryClient_BlockGas_Call{Call: _e.mock.On("BlockGas", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *FeeMarketQueryClient_BlockGas_Call) Run(run func(ctx context.Context, in *types.QueryBlockGasRequest, opts ...grpc.CallOption)) *FeeMarketQueryClient_BlockGas_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*types.QueryBlockGasRequest), variadicArgs...) + }) + return _c +} + +func (_c *FeeMarketQueryClient_BlockGas_Call) Return(_a0 *types.QueryBlockGasResponse, _a1 error) *FeeMarketQueryClient_BlockGas_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeMarketQueryClient_BlockGas_Call) RunAndReturn(run func(context.Context, *types.QueryBlockGasRequest, ...grpc.CallOption) (*types.QueryBlockGasResponse, error)) *FeeMarketQueryClient_BlockGas_Call { + _c.Call.Return(run) + return _c +} + // Params provides a mock function with given fields: ctx, in, opts func (_m *FeeMarketQueryClient) Params(ctx context.Context, in *types.QueryParamsRequest, opts ...grpc.CallOption) (*types.QueryParamsResponse, error) { _va := make([]interface{}, len(opts)) @@ -88,7 +184,15 @@ func (_m *FeeMarketQueryClient) Params(ctx context.Context, in *types.QueryParam _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for Params") + } + var r0 *types.QueryParamsResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryParamsRequest, ...grpc.CallOption) (*types.QueryParamsResponse, error)); ok { + return rf(ctx, in, opts...) + } if rf, ok := ret.Get(0).(func(context.Context, *types.QueryParamsRequest, ...grpc.CallOption) *types.QueryParamsResponse); ok { r0 = rf(ctx, in, opts...) } else { @@ -97,7 +201,6 @@ func (_m *FeeMarketQueryClient) Params(ctx context.Context, in *types.QueryParam } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, *types.QueryParamsRequest, ...grpc.CallOption) error); ok { r1 = rf(ctx, in, opts...) } else { @@ -107,13 +210,50 @@ func (_m *FeeMarketQueryClient) Params(ctx context.Context, in *types.QueryParam return r0, r1 } -type mockConstructorTestingTNewQueryClient interface { - mock.TestingT - Cleanup(func()) +// FeeMarketQueryClient_Params_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Params' +type FeeMarketQueryClient_Params_Call struct { + *mock.Call +} + +// Params is a helper method to define mock.On call +// - ctx context.Context +// - in *types.QueryParamsRequest +// - opts ...grpc.CallOption +func (_e *FeeMarketQueryClient_Expecter) Params(ctx interface{}, in interface{}, opts ...interface{}) *FeeMarketQueryClient_Params_Call { + return &FeeMarketQueryClient_Params_Call{Call: _e.mock.On("Params", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *FeeMarketQueryClient_Params_Call) Run(run func(ctx context.Context, in *types.QueryParamsRequest, opts ...grpc.CallOption)) *FeeMarketQueryClient_Params_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*types.QueryParamsRequest), variadicArgs...) + }) + return _c } -// NewQueryClient creates a new instance of QueryClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewFeeMarketQueryClient(t mockConstructorTestingTNewQueryClient) *FeeMarketQueryClient { +func (_c *FeeMarketQueryClient_Params_Call) Return(_a0 *types.QueryParamsResponse, _a1 error) *FeeMarketQueryClient_Params_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeMarketQueryClient_Params_Call) RunAndReturn(run func(context.Context, *types.QueryParamsRequest, ...grpc.CallOption) (*types.QueryParamsResponse, error)) *FeeMarketQueryClient_Params_Call { + _c.Call.Return(run) + return _c +} + +// NewFeeMarketQueryClient creates a new instance of FeeMarketQueryClient. 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 NewFeeMarketQueryClient(t interface { + mock.TestingT + Cleanup(func()) +}, +) *FeeMarketQueryClient { mock := &FeeMarketQueryClient{} mock.Mock.Test(t) diff --git a/rpc/backend/mocks/mempool.go b/rpc/backend/mocks/mempool.go new file mode 100644 index 00000000..2920edd9 --- /dev/null +++ b/rpc/backend/mocks/mempool.go @@ -0,0 +1,276 @@ +// Code generated by mockery v2.53.6. DO NOT EDIT. + +package mocks + +import ( + context "context" + + mempool "github.com/cosmos/cosmos-sdk/types/mempool" + mock "github.com/stretchr/testify/mock" + + txpool "github.com/cosmos/evm/mempool/txpool" + + types "github.com/cosmos/cosmos-sdk/types" +) + +// Mempool is an autogenerated mock type for the Mempool type +type Mempool struct { + mock.Mock +} + +type Mempool_Expecter struct { + mock *mock.Mock +} + +func (_m *Mempool) EXPECT() *Mempool_Expecter { + return &Mempool_Expecter{mock: &_m.Mock} +} + +// CountTx provides a mock function with no fields +func (_m *Mempool) CountTx() int { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for CountTx") + } + + var r0 int + if rf, ok := ret.Get(0).(func() int); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(int) + } + + return r0 +} + +// Mempool_CountTx_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CountTx' +type Mempool_CountTx_Call struct { + *mock.Call +} + +// CountTx is a helper method to define mock.On call +func (_e *Mempool_Expecter) CountTx() *Mempool_CountTx_Call { + return &Mempool_CountTx_Call{Call: _e.mock.On("CountTx")} +} + +func (_c *Mempool_CountTx_Call) Run(run func()) *Mempool_CountTx_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Mempool_CountTx_Call) Return(_a0 int) *Mempool_CountTx_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Mempool_CountTx_Call) RunAndReturn(run func() int) *Mempool_CountTx_Call { + _c.Call.Return(run) + return _c +} + +// GetTxPool provides a mock function with no fields +func (_m *Mempool) GetTxPool() *txpool.TxPool { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for GetTxPool") + } + + var r0 *txpool.TxPool + if rf, ok := ret.Get(0).(func() *txpool.TxPool); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*txpool.TxPool) + } + } + + return r0 +} + +// Mempool_GetTxPool_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTxPool' +type Mempool_GetTxPool_Call struct { + *mock.Call +} + +// GetTxPool is a helper method to define mock.On call +func (_e *Mempool_Expecter) GetTxPool() *Mempool_GetTxPool_Call { + return &Mempool_GetTxPool_Call{Call: _e.mock.On("GetTxPool")} +} + +func (_c *Mempool_GetTxPool_Call) Run(run func()) *Mempool_GetTxPool_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Mempool_GetTxPool_Call) Return(_a0 *txpool.TxPool) *Mempool_GetTxPool_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Mempool_GetTxPool_Call) RunAndReturn(run func() *txpool.TxPool) *Mempool_GetTxPool_Call { + _c.Call.Return(run) + return _c +} + +// Insert provides a mock function with given fields: _a0, _a1 +func (_m *Mempool) Insert(_a0 context.Context, _a1 types.Tx) error { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for Insert") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, types.Tx) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Mempool_Insert_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Insert' +type Mempool_Insert_Call struct { + *mock.Call +} + +// Insert is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 types.Tx +func (_e *Mempool_Expecter) Insert(_a0 interface{}, _a1 interface{}) *Mempool_Insert_Call { + return &Mempool_Insert_Call{Call: _e.mock.On("Insert", _a0, _a1)} +} + +func (_c *Mempool_Insert_Call) Run(run func(_a0 context.Context, _a1 types.Tx)) *Mempool_Insert_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(types.Tx)) + }) + return _c +} + +func (_c *Mempool_Insert_Call) Return(_a0 error) *Mempool_Insert_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Mempool_Insert_Call) RunAndReturn(run func(context.Context, types.Tx) error) *Mempool_Insert_Call { + _c.Call.Return(run) + return _c +} + +// Remove provides a mock function with given fields: _a0 +func (_m *Mempool) Remove(_a0 types.Tx) error { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for Remove") + } + + var r0 error + if rf, ok := ret.Get(0).(func(types.Tx) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Mempool_Remove_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Remove' +type Mempool_Remove_Call struct { + *mock.Call +} + +// Remove is a helper method to define mock.On call +// - _a0 types.Tx +func (_e *Mempool_Expecter) Remove(_a0 interface{}) *Mempool_Remove_Call { + return &Mempool_Remove_Call{Call: _e.mock.On("Remove", _a0)} +} + +func (_c *Mempool_Remove_Call) Run(run func(_a0 types.Tx)) *Mempool_Remove_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Tx)) + }) + return _c +} + +func (_c *Mempool_Remove_Call) Return(_a0 error) *Mempool_Remove_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Mempool_Remove_Call) RunAndReturn(run func(types.Tx) error) *Mempool_Remove_Call { + _c.Call.Return(run) + return _c +} + +// Select provides a mock function with given fields: _a0, _a1 +func (_m *Mempool) Select(_a0 context.Context, _a1 [][]byte) mempool.Iterator { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for Select") + } + + var r0 mempool.Iterator + if rf, ok := ret.Get(0).(func(context.Context, [][]byte) mempool.Iterator); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(mempool.Iterator) + } + } + + return r0 +} + +// Mempool_Select_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Select' +type Mempool_Select_Call struct { + *mock.Call +} + +// Select is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 [][]byte +func (_e *Mempool_Expecter) Select(_a0 interface{}, _a1 interface{}) *Mempool_Select_Call { + return &Mempool_Select_Call{Call: _e.mock.On("Select", _a0, _a1)} +} + +func (_c *Mempool_Select_Call) Run(run func(_a0 context.Context, _a1 [][]byte)) *Mempool_Select_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].([][]byte)) + }) + return _c +} + +func (_c *Mempool_Select_Call) Return(_a0 mempool.Iterator) *Mempool_Select_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Mempool_Select_Call) RunAndReturn(run func(context.Context, [][]byte) mempool.Iterator) *Mempool_Select_Call { + _c.Call.Return(run) + return _c +} + +// NewMempool creates a new instance of Mempool. 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 NewMempool(t interface { + mock.TestingT + Cleanup(func()) +}, +) *Mempool { + mock := &Mempool{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/rpc/backend/node_info.go b/rpc/backend/node_info.go index dcdf28a6..f5d308e3 100644 --- a/rpc/backend/node_info.go +++ b/rpc/backend/node_info.go @@ -1,6 +1,7 @@ package backend import ( + "context" "fmt" "math/big" "time" @@ -15,6 +16,7 @@ import ( rpctypes "github.com/cosmos/evm/rpc/types" "github.com/cosmos/evm/server/config" "github.com/cosmos/evm/testutil/constants" + evmtrace "github.com/cosmos/evm/trace" evmtypes "github.com/cosmos/evm/x/vm/types" errorsmod "cosmossdk.io/errors" @@ -63,8 +65,11 @@ func (b *Backend) Accounts() ([]common.Address, error) { // - highestBlock: block number of the highest block header this node has received from peers // - pulledStates: number of state entries processed until now // - knownStates: number of known state entries that still need to be pulled -func (b *Backend) Syncing() (interface{}, error) { - status, err := b.ClientCtx.Client.Status(b.Ctx) +func (b *Backend) Syncing(ctx context.Context) (result interface{}, err error) { + ctx, span := tracer.Start(ctx, "Syncing") + defer func() { evmtrace.EndSpanErr(span, err) }() + + status, err := b.ClientCtx.Client.Status(ctx) if err != nil { return false, err } @@ -83,13 +88,15 @@ func (b *Backend) Syncing() (interface{}, error) { } // SetEtherbase sets the etherbase of the miner -func (b *Backend) SetEtherbase(etherbase common.Address) bool { +func (b *Backend) SetEtherbase(ctx context.Context, etherbase common.Address) bool { + ctx, span := tracer.Start(ctx, "SetEtherbase") + defer span.End() if !b.Cfg.JSONRPC.AllowInsecureUnlock { b.Logger.Debug("account unlock with HTTP access is forbidden") return false } - delAddr, err := b.GetCoinbase() + delAddr, err := b.GetCoinbase(ctx) if err != nil { b.Logger.Debug("failed to get coinbase address", "error", err.Error()) return false @@ -121,7 +128,7 @@ func (b *Backend) SetEtherbase(etherbase common.Address) bool { denom := minGasPrices[0].Denom delCommonAddr := common.BytesToAddress(delAddr.Bytes()) - nonce, err := b.GetTransactionCount(delCommonAddr, rpctypes.EthPendingBlockNumber) + nonce, err := b.GetTransactionCount(ctx, delCommonAddr, rpctypes.EthPendingBlockNumber) if err != nil { b.Logger.Debug("failed to get nonce", "error", err.Error()) return false @@ -154,7 +161,7 @@ func (b *Backend) SetEtherbase(etherbase common.Address) bool { return false } - if err := tx.Sign(b.ClientCtx.CmdContext, txFactory, keyInfo.Name, builder, false); err != nil { + if err := tx.Sign(ctx, txFactory, keyInfo.Name, builder, false); err != nil { b.Logger.Debug("failed to sign tx", "error", err.Error()) return false } @@ -263,7 +270,7 @@ func (b *Backend) NewMnemonic(uid string, // SetGasPrice sets the minimum accepted gas price for the miner. // NOTE: this function accepts only integers to have the same interface than go-eth // to use float values, the gas prices must be configured using the configuration file -func (b *Backend) SetGasPrice(gasPrice hexutil.Big) bool { +func (b *Backend) SetGasPrice(ctx context.Context, gasPrice hexutil.Big) bool { appConf, err := config.GetConfig(b.ClientCtx.Viper) if err != nil { b.Logger.Debug("could not get the server config", "error", err.Error()) @@ -317,11 +324,6 @@ func (b *Backend) RPCTxFeeCap() float64 { return b.Cfg.JSONRPC.TxFeeCap } -// RPCFilterCap is the limit for total number of filters that can be created -func (b *Backend) RPCFilterCap() int32 { - return b.Cfg.JSONRPC.FilterCap -} - // RPCFeeHistoryCap is the limit for total number of blocks that can be fetched func (b *Backend) RPCFeeHistoryCap() int32 { return b.Cfg.JSONRPC.FeeHistoryCap diff --git a/rpc/backend/sign_tx.go b/rpc/backend/sign_tx.go index 859c2c3a..588a720e 100644 --- a/rpc/backend/sign_tx.go +++ b/rpc/backend/sign_tx.go @@ -1,10 +1,10 @@ package backend import ( + "context" "errors" "fmt" "math/big" - "strings" "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" @@ -12,26 +12,32 @@ import ( ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/signer/core/apitypes" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" - "github.com/cosmos/evm/mempool" + evmtrace "github.com/cosmos/evm/trace" evmtypes "github.com/cosmos/evm/x/vm/types" - errorsmod "cosmossdk.io/errors" - - "github.com/cosmos/cosmos-sdk/client/flags" sdk "github.com/cosmos/cosmos-sdk/types" signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" ) // SendTransaction sends transaction based on received args using Node's key to sign it -func (b *Backend) SendTransaction(args evmtypes.TransactionArgs) (common.Hash, error) { +func (b *Backend) SendTransaction(ctx context.Context, args evmtypes.TransactionArgs) (result common.Hash, err error) { + var toAddr string + if args.To != nil { + toAddr = args.To.Hex() + } + ctx, span := tracer.Start(ctx, "SendTransaction", trace.WithAttributes(attribute.String("from", args.GetFrom().Hex()), attribute.String("to", toAddr))) + defer func() { evmtrace.EndSpanErr(span, err) }() + // Look up the wallet containing the requested signer if !b.Cfg.JSONRPC.AllowInsecureUnlock { b.Logger.Debug("account unlock with HTTP access is forbidden") return common.Hash{}, fmt.Errorf("account unlock with HTTP access is forbidden") } - _, err := b.ClientCtx.Keyring.KeyByAddress(sdk.AccAddress(args.GetFrom().Bytes())) + _, err = b.ClientCtx.Keyring.KeyByAddress(sdk.AccAddress(args.GetFrom().Bytes())) if err != nil { b.Logger.Error("failed to find key in keyring", "address", args.GetFrom(), "error", err.Error()) return common.Hash{}, fmt.Errorf("failed to find key in the node's keyring; %s; %s", keystore.ErrNoMatch, err.Error()) @@ -41,18 +47,18 @@ func (b *Backend) SendTransaction(args evmtypes.TransactionArgs) (common.Hash, e return common.Hash{}, fmt.Errorf("chainId does not match node's (have=%v, want=%v)", args.ChainID, (*hexutil.Big)(b.EvmChainID)) } - args, err = b.SetTxDefaults(args) + args, err = b.SetTxDefaults(ctx, args) if err != nil { return common.Hash{}, err } - bn, err := b.BlockNumber() + bn, err := b.BlockNumber(ctx) if err != nil { b.Logger.Debug("failed to fetch latest block number", "error", err.Error()) return common.Hash{}, err } - header, err := b.CurrentHeader() + header, err := b.CurrentHeader(ctx) if err != nil { return common.Hash{}, err } @@ -83,14 +89,6 @@ func (b *Backend) SendTransaction(args evmtypes.TransactionArgs) (common.Hash, e return common.Hash{}, err } - // Encode transaction by default Tx encoder - txEncoder := b.ClientCtx.TxConfig.TxEncoder() - txBytes, err := txEncoder(tx) - if err != nil { - b.Logger.Error("failed to encode eth tx using default encoder", "error", err.Error()) - return common.Hash{}, err - } - ethTx := msg.AsTransaction() // check the local node config in case unprotected txs are disabled @@ -101,25 +99,20 @@ func (b *Backend) SendTransaction(args evmtypes.TransactionArgs) (common.Hash, e txHash := ethTx.Hash() - // Broadcast transaction in sync mode (default) - // NOTE: If error is encountered on the node, the broadcast will not return an error - syncCtx := b.ClientCtx.WithBroadcastMode(flags.BroadcastSync) - rsp, err := syncCtx.BroadcastTx(txBytes) - if rsp != nil && rsp.Code != 0 { - err = errorsmod.ABCIError(rsp.Codespace, rsp.Code, rsp.RawLog) - } - if err != nil { - // Check if this is a nonce gap error that was successfully queued - 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 - } - b.Logger.Error("failed to broadcast tx", "error", err.Error()) - return txHash, err + // publish tx directly to app-side mempool, avoiding broadcasting to + // consensus layer. + // we are directly calling into the mempool rather than the ABCI + // handler for InsertTx, since the ABCI handler obfuscates the error's + // returned via codes, and we would like to have the full error to + // return to clients. + if err = b.Mempool.Insert(ctx, tx); err != nil { + // no need for special error handling like in the broadcast tx case + // since this is coming directly from the evm mempool insert. + return common.Hash{}, err } - // Return transaction hash + b.TrackTxIfSupported(txHash) + return txHash, nil } diff --git a/rpc/backend/tracing.go b/rpc/backend/tracing.go index fa1ee67c..0c476daa 100644 --- a/rpc/backend/tracing.go +++ b/rpc/backend/tracing.go @@ -1,6 +1,7 @@ package backend import ( + "context" "encoding/json" "fmt" "math" @@ -8,11 +9,14 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/pkg/errors" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" tmrpcclient "github.com/cometbft/cometbft/rpc/client" tmrpctypes "github.com/cometbft/cometbft/rpc/core/types" rpctypes "github.com/cosmos/evm/rpc/types" + evmtrace "github.com/cosmos/evm/trace" evmtypes "github.com/cosmos/evm/x/vm/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -20,9 +24,12 @@ import ( // TraceTransaction returns the structured logs created during the execution of EVM // and returns them as a JSON object. -func (b *Backend) TraceTransaction(hash common.Hash, config *rpctypes.TraceConfig) (interface{}, error) { +func (b *Backend) TraceTransaction(ctx context.Context, hash common.Hash, config *rpctypes.TraceConfig) (result interface{}, err error) { + ctx, span := tracer.Start(ctx, "TraceTransaction", trace.WithAttributes(attribute.String("hash", hash.Hex()))) + defer func() { evmtrace.EndSpanErr(span, err) }() + // Get transaction by hash - transaction, err := b.GetTxByEthHash(hash) + transaction, err := b.GetTxByEthHash(ctx, hash) if err != nil { b.Logger.Debug("tx not found", "hash", hash) return nil, err @@ -33,7 +40,7 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *rpctypes.TraceConfi return nil, errors.New("genesis is not traceable") } - blk, err := b.CometBlockByNumber(rpctypes.BlockNumber(transaction.Height)) + blk, err := b.CometBlockByNumber(ctx, rpctypes.BlockNumber(transaction.Height)) if err != nil { b.Logger.Debug("block not found", "height", transaction.Height) return nil, err @@ -93,7 +100,7 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *rpctypes.TraceConfi return nil, errors.New("invalid rpc client") } - cp, err := nc.ConsensusParams(b.Ctx, &blk.Block.Height) + cp, err := nc.ConsensusParams(ctx, &blk.Block.Height) if err != nil { return nil, err } @@ -120,7 +127,7 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *rpctypes.TraceConfi // So here we set the minimum requested height to 1. contextHeight = 1 } - traceResult, err := b.QueryClient.TraceTx(rpctypes.ContextWithHeight(contextHeight), &traceTxRequest) + traceResult, err := b.QueryClient.TraceTx(rpctypes.ContextWithHeight(ctx, contextHeight), &traceTxRequest) if err != nil { return nil, err } @@ -148,10 +155,13 @@ func (b *Backend) convertConfig(config *rpctypes.TraceConfig) *evmtypes.TraceCon // TraceBlock configures a new tracer according to the provided configuration, and // executes all the transactions contained within. The return value will be one item // per transaction, dependent on the requested tracer. -func (b *Backend) TraceBlock(height rpctypes.BlockNumber, +func (b *Backend) TraceBlock(ctx context.Context, height rpctypes.BlockNumber, config *rpctypes.TraceConfig, block *tmrpctypes.ResultBlock, -) ([]*evmtypes.TxTraceResult, error) { +) (result []*evmtypes.TxTraceResult, err error) { + ctx, span := tracer.Start(ctx, "TraceBlock", trace.WithAttributes(attribute.Int64("height", height.Int64()), attribute.String("blockHash", common.BytesToHash(block.BlockID.Hash).Hex()))) + defer func() { evmtrace.EndSpanErr(span, err) }() + txs := block.Block.Txs txsLength := len(txs) @@ -160,7 +170,7 @@ func (b *Backend) TraceBlock(height rpctypes.BlockNumber, return []*evmtypes.TxTraceResult{}, nil } - blockRes, err := b.CometBlockResultByNumber(&block.Block.Height) + blockRes, err := b.CometBlockResultByNumber(ctx, &block.Block.Height) if err != nil { b.Logger.Debug("block result not found", "height", block.Block.Height, "error", err.Error()) return nil, nil @@ -169,7 +179,7 @@ func (b *Backend) TraceBlock(height rpctypes.BlockNumber, var txsMessages []*evmtypes.MsgEthereumTx for i, tx := range txs { - if !rpctypes.TxSucessOrExpectedFailure(blockRes.TxsResults[i]) { + if !evmtypes.TxSucessOrExpectedFailure(blockRes.TxsResults[i]) { b.Logger.Debug("invalid tx result code", "cosmos-hash", hexutil.Encode(tx.Hash())) continue } @@ -192,17 +202,17 @@ func (b *Backend) TraceBlock(height rpctypes.BlockNumber, // minus one to get the context at the beginning of the block contextHeight := height - 1 if contextHeight < 1 { - // 0 is a special value for `ContextWithHeight`. + // 0 is a special value for `NewContextWithHeight`. contextHeight = 1 } - ctxWithHeight := rpctypes.ContextWithHeight(int64(contextHeight)) + ctxWithHeight := rpctypes.ContextWithHeight(ctx, int64(contextHeight)) nc, ok := b.ClientCtx.Client.(tmrpcclient.NetworkClient) if !ok { return nil, errors.New("invalid rpc client") } - cp, err := nc.ConsensusParams(b.Ctx, &block.Block.Height) + cp, err := nc.ConsensusParams(ctx, &block.Block.Height) if err != nil { return nil, err } @@ -234,10 +244,18 @@ func (b *Backend) TraceBlock(height rpctypes.BlockNumber, // TraceCall executes a call with the given arguments and returns the structured logs // created during the execution of EVM. It returns them as a JSON object. func (b *Backend) TraceCall( + ctx context.Context, args evmtypes.TransactionArgs, blockNrOrHash rpctypes.BlockNumberOrHash, config *rpctypes.TraceConfig, -) (interface{}, error) { +) (result interface{}, err error) { + var toAddr string + if args.To != nil { + toAddr = args.To.Hex() + } + ctx, span := tracer.Start(ctx, "TraceCall", trace.WithAttributes(attribute.String("from", args.GetFrom().Hex()), attribute.String("to", toAddr), attribute.String("blockNrOrHash", unwrapBlockNOrHash(blockNrOrHash)))) + defer func() { evmtrace.EndSpanErr(span, err) }() + // Marshal tx args bz, err := json.Marshal(&args) if err != nil { @@ -245,13 +263,13 @@ func (b *Backend) TraceCall( } // Get block number from blockNrOrHash - blockNr, err := b.BlockNumberFromComet(blockNrOrHash) + blockNr, err := b.BlockNumberFromComet(ctx, blockNrOrHash) if err != nil { return nil, err } // Get the block to get necessary context - header, err := b.CometHeaderByNumber(blockNr) + header, err := b.CometHeaderByNumber(ctx, blockNr) if err != nil { b.Logger.Debug("block not found", "number", blockNr) return nil, err @@ -280,7 +298,7 @@ func (b *Backend) TraceCall( } // Use the block height as context for the query - ctxWithHeight := rpctypes.ContextWithHeight(contextHeight) + ctxWithHeight := rpctypes.ContextWithHeight(ctx, contextHeight) traceResult, err := b.QueryClient.TraceCall(ctxWithHeight, &traceCallRequest) if err != nil { return nil, err diff --git a/rpc/backend/tx_info.go b/rpc/backend/tx_info.go index 9c84198f..f4147b9a 100644 --- a/rpc/backend/tx_info.go +++ b/rpc/backend/tx_info.go @@ -1,9 +1,9 @@ package backend import ( + "context" "encoding/json" "fmt" - "math" "math/big" "time" @@ -14,6 +14,8 @@ import ( "github.com/ethereum/go-ethereum/eth/tracers/logger" "github.com/ethereum/go-ethereum/params" "github.com/pkg/errors" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" cmtrpcclient "github.com/cometbft/cometbft/rpc/client" cmtrpctypes "github.com/cometbft/cometbft/rpc/core/types" @@ -21,6 +23,7 @@ import ( "github.com/cosmos/evm/mempool/txpool" rpctypes "github.com/cosmos/evm/rpc/types" servertypes "github.com/cosmos/evm/server/types" + evmtrace "github.com/cosmos/evm/trace" "github.com/cosmos/evm/utils" evmtypes "github.com/cosmos/evm/x/vm/types" @@ -30,13 +33,16 @@ import ( ) // GetTransactionByHash returns the Ethereum format transaction identified by Ethereum transaction hash -func (b *Backend) GetTransactionByHash(txHash common.Hash) (*rpctypes.RPCTransaction, error) { - res, err := b.GetTxByEthHash(txHash) +func (b *Backend) GetTransactionByHash(ctx context.Context, txHash common.Hash) (result *rpctypes.RPCTransaction, err error) { + ctx, span := tracer.Start(ctx, "GetTransactionByHash", trace.WithAttributes(attribute.String("txHash", txHash.Hex()))) + defer func() { evmtrace.EndSpanErr(span, err) }() + + res, err := b.GetTxByEthHash(ctx, txHash) if err != nil { - return b.GetTransactionByHashPending(txHash) + return b.GetTransactionByHashPending(ctx, txHash) } - block, err := b.CometBlockByNumber(rpctypes.BlockNumber(res.Height)) + block, err := b.CometBlockByNumber(ctx, rpctypes.BlockNumber(res.Height)) if err != nil { return nil, err } @@ -52,31 +58,22 @@ func (b *Backend) GetTransactionByHash(txHash common.Hash) (*rpctypes.RPCTransac return nil, errors.New("invalid ethereum tx") } - blockRes, err := b.RPCClient.BlockResults(b.Ctx, &block.Block.Height) + blockRes, err := b.RPCClient.BlockResults(ctx, &block.Block.Height) if err != nil { b.Logger.Debug("block result not found", "height", block.Block.Height, "error", err.Error()) return nil, fmt.Errorf("block result not found: %w", err) } if res.EthTxIndex == -1 { + var err error // Fallback to find tx index by iterating all valid eth transactions - msgs := b.EthMsgsFromCometBlock(block, blockRes) - for i := range msgs { - if msgs[i].Hash() == txHash { - if i > math.MaxInt32 { - return nil, errors.New("tx index overflow") - } - res.EthTxIndex = int32(i) //#nosec G115 -- checked for int overflow already - break - } + res.EthTxIndex, err = b.FindEthTxIndexByHash(ctx, txHash, block, blockRes) + if err != nil { + return nil, err } } - // if we still unable to find the eth tx index, return error, shouldn't happen. - if res.EthTxIndex == -1 { - return nil, errors.New("can't find index of ethereum tx") - } - baseFee, err := b.BaseFee(blockRes) + baseFee, err := b.BaseFee(ctx, blockRes) if err != nil { // handle the error for pruned node. b.Logger.Error("failed to fetch Base Fee from prunned block. Check node prunning configuration", "height", blockRes.Height, "error", err) @@ -97,10 +94,13 @@ func (b *Backend) GetTransactionByHash(txHash common.Hash) (*rpctypes.RPCTransac } // GetTransactionByHashPending find pending tx from mempool -func (b *Backend) GetTransactionByHashPending(txHash common.Hash) (*rpctypes.RPCTransaction, error) { +func (b *Backend) GetTransactionByHashPending(ctx context.Context, txHash common.Hash) (result *rpctypes.RPCTransaction, err error) { + ctx, span := tracer.Start(ctx, "GetTransactionByHashPending", trace.WithAttributes(attribute.String("txHash", txHash.Hex()))) + defer func() { evmtrace.EndSpanErr(span, err) }() + hexTx := txHash.Hex() // try to find tx in mempool - txs, err := b.PendingTransactions() + txs, err := b.PendingTransactions(ctx) if err != nil { b.Logger.Debug("tx not found", "hash", hexTx, "error", err.Error()) return nil, nil @@ -132,12 +132,15 @@ func (b *Backend) GetTransactionByHashPending(txHash common.Hash) (*rpctypes.RPC } // GetGasUsed returns gasUsed from transaction -func (b *Backend) GetGasUsed(res *servertypes.TxResult, price *big.Int, gas uint64) uint64 { +func (b *Backend) GetGasUsed(res *servertypes.TxResult, _ *big.Int, _ uint64) uint64 { return res.GasUsed } // GetTransactionReceipt returns the transaction receipt identified by hash. -func (b *Backend) GetTransactionReceipt(hash common.Hash) (map[string]interface{}, error) { +func (b *Backend) GetTransactionReceipt(ctx context.Context, hash common.Hash) (result map[string]interface{}, err error) { + ctx, span := tracer.Start(ctx, "GetTransactionReceipt", trace.WithAttributes(attribute.String("hash", hash.Hex()))) + defer func() { evmtrace.EndSpanErr(span, err) }() + hexTx := hash.Hex() b.Logger.Debug("eth_getTransactionReceipt", "hash", hexTx) @@ -146,10 +149,9 @@ func (b *Backend) GetTransactionReceipt(hash common.Hash) (map[string]interface{ baseDelay := 50 * time.Millisecond var res *servertypes.TxResult - var err error for attempt := 0; attempt <= maxRetries; attempt++ { - res, err = b.GetTxByEthHash(hash) + res, err = b.GetTxByEthHash(ctx, hash) if err == nil { break // Found the transaction } @@ -174,7 +176,7 @@ func (b *Backend) GetTransactionReceipt(hash common.Hash) (map[string]interface{ return nil, nil } - resBlock, err := b.CometBlockByNumber(rpctypes.BlockNumber(res.Height)) + resBlock, err := b.CometBlockByNumber(ctx, rpctypes.BlockNumber(res.Height)) if err != nil { b.Logger.Debug("block not found", "height", res.Height, "error", err.Error()) return nil, fmt.Errorf("block not found at height %d: %w", res.Height, err) @@ -186,14 +188,14 @@ func (b *Backend) GetTransactionReceipt(hash common.Hash) (map[string]interface{ return nil, fmt.Errorf("failed to decode tx: %w", err) } - blockRes, err := b.RPCClient.BlockResults(b.Ctx, &res.Height) + blockRes, err := b.RPCClient.BlockResults(ctx, &res.Height) if err != nil { b.Logger.Debug("failed to retrieve block results", "height", res.Height, "error", err.Error()) return nil, fmt.Errorf("block result not found at height %d: %w", res.Height, err) } ethMsg := tx.GetMsgs()[res.MsgIndex].(*evmtypes.MsgEthereumTx) - receipts, err := b.ReceiptsFromCometBlock(resBlock, blockRes, []*evmtypes.MsgEthereumTx{ethMsg}) + receipts, err := b.ReceiptsFromCometBlock(ctx, resBlock, blockRes, []*evmtypes.MsgEthereumTx{ethMsg}) if err != nil { return nil, fmt.Errorf("failed to get receipts from comet block") } @@ -214,10 +216,13 @@ func (b *Backend) GetTransactionReceipt(hash common.Hash) (map[string]interface{ } // GetTransactionLogs returns the transaction logs identified by hash. -func (b *Backend) GetTransactionLogs(hash common.Hash) ([]*ethtypes.Log, error) { +func (b *Backend) GetTransactionLogs(ctx context.Context, hash common.Hash) (result []*ethtypes.Log, err error) { + ctx, span := tracer.Start(ctx, "GetTransactionLogs", trace.WithAttributes(attribute.String("hash", hash.Hex()))) + defer func() { evmtrace.EndSpanErr(span, err) }() + hexTx := hash.Hex() - res, err := b.GetTxByEthHash(hash) + res, err := b.GetTxByEthHash(ctx, hash) if err != nil { b.Logger.Debug("tx not found", "hash", hexTx, "error", err.Error()) return nil, nil @@ -228,7 +233,7 @@ func (b *Backend) GetTransactionLogs(hash common.Hash) ([]*ethtypes.Log, error) return nil, nil } - resBlockResult, err := b.RPCClient.BlockResults(b.Ctx, &res.Height) + resBlockResult, err := b.RPCClient.BlockResults(ctx, &res.Height) if err != nil { b.Logger.Debug("block result not found", "number", res.Height, "error", err.Error()) return nil, nil @@ -252,14 +257,18 @@ func (b *Backend) GetTransactionLogs(hash common.Hash) ([]*ethtypes.Log, error) } // GetTransactionByBlockHashAndIndex returns the transaction identified by hash and index. -func (b *Backend) GetTransactionByBlockHashAndIndex(hash common.Hash, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) { +func (b *Backend) GetTransactionByBlockHashAndIndex(ctx context.Context, hash common.Hash, idx hexutil.Uint) (result *rpctypes.RPCTransaction, err error) { + //nolint:gosec // unlikely + ctx, span := tracer.Start(ctx, "GetTransactionByBlockHashAndIndex", trace.WithAttributes(attribute.String("hash", hash.Hex()), attribute.Int64("idx", int64(idx)))) + defer func() { evmtrace.EndSpanErr(span, err) }() + b.Logger.Debug("eth_getTransactionByBlockHashAndIndex", "hash", hash.Hex(), "index", idx) sc, ok := b.ClientCtx.Client.(cmtrpcclient.SignClient) if !ok { return nil, errors.New("invalid rpc client") } - block, err := sc.BlockByHash(b.Ctx, hash.Bytes()) + block, err := sc.BlockByHash(ctx, hash.Bytes()) if err != nil { b.Logger.Debug("block not found", "hash", hash.Hex(), "error", err.Error()) return nil, nil @@ -270,14 +279,18 @@ func (b *Backend) GetTransactionByBlockHashAndIndex(hash common.Hash, idx hexuti return nil, nil } - return b.GetTransactionByBlockAndIndex(block, idx) + return b.GetTransactionByBlockAndIndex(ctx, block, idx) } // GetTransactionByBlockNumberAndIndex returns the transaction identified by number and index. -func (b *Backend) GetTransactionByBlockNumberAndIndex(blockNum rpctypes.BlockNumber, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) { +func (b *Backend) GetTransactionByBlockNumberAndIndex(ctx context.Context, blockNum rpctypes.BlockNumber, idx hexutil.Uint) (result *rpctypes.RPCTransaction, err error) { + //nolint:gosec // unlikely + ctx, span := tracer.Start(ctx, "GetTransactionByBlockNumberAndIndex", trace.WithAttributes(attribute.Int64("blockNum", blockNum.Int64()), attribute.Int64("idx", int64(idx)))) + defer func() { evmtrace.EndSpanErr(span, err) }() + b.Logger.Debug("eth_getTransactionByBlockNumberAndIndex", "number", blockNum, "index", idx) - block, err := b.CometBlockByNumber(blockNum) + block, err := b.CometBlockByNumber(ctx, blockNum) if err != nil { b.Logger.Debug("block not found", "height", blockNum.Int64(), "error", err.Error()) return nil, nil @@ -288,20 +301,23 @@ func (b *Backend) GetTransactionByBlockNumberAndIndex(blockNum rpctypes.BlockNum return nil, nil } - return b.GetTransactionByBlockAndIndex(block, idx) + return b.GetTransactionByBlockAndIndex(ctx, block, idx) } // GetTxByEthHash uses `/tx_query` to find transaction by ethereum tx hash // TODO: Don't need to convert once hashing is fixed on CometBFT // https://github.com/cometbft/cometbft/issues/6539 -func (b *Backend) GetTxByEthHash(hash common.Hash) (*servertypes.TxResult, error) { +func (b *Backend) GetTxByEthHash(ctx context.Context, hash common.Hash) (result *servertypes.TxResult, err error) { + ctx, span := tracer.Start(ctx, "GetTxByEthHash", trace.WithAttributes(attribute.String("hash", hash.Hex()))) + defer func() { evmtrace.EndSpanErr(span, err) }() + if b.Indexer != nil { return b.Indexer.GetByTxHash(hash) } // fallback to CometBFT tx indexer query := fmt.Sprintf("%s.%s='%s'", evmtypes.TypeMsgEthereumTx, evmtypes.AttributeKeyEthereumTxHash, hash.Hex()) - txResult, err := b.QueryCometTxIndexer(query, func(txs *rpctypes.ParsedTxs) *rpctypes.ParsedTx { + txResult, err := b.QueryCometTxIndexer(ctx, query, func(txs *rpctypes.ParsedTxs) *rpctypes.ParsedTx { return txs.GetTxByHash(hash) }) if err != nil { @@ -311,7 +327,11 @@ func (b *Backend) GetTxByEthHash(hash common.Hash) (*servertypes.TxResult, error } // GetTxByTxIndex uses `/tx_query` to find transaction by tx index of valid ethereum txs -func (b *Backend) GetTxByTxIndex(height int64, index uint) (*servertypes.TxResult, error) { +func (b *Backend) GetTxByTxIndex(ctx context.Context, height int64, index uint) (result *servertypes.TxResult, err error) { + //nolint:gosec // unlikely + ctx, span := tracer.Start(ctx, "GetTxByTxIndex", trace.WithAttributes(attribute.Int64("height", height), attribute.Int64("index", int64(index)))) + defer func() { evmtrace.EndSpanErr(span, err) }() + int32Index := int32(index) //#nosec G115 -- checked for int overflow already if b.Indexer != nil { return b.Indexer.GetByBlockAndIndex(height, int32Index) @@ -322,7 +342,7 @@ func (b *Backend) GetTxByTxIndex(height int64, index uint) (*servertypes.TxResul height, evmtypes.TypeMsgEthereumTx, evmtypes.AttributeKeyTxIndex, index, ) - txResult, err := b.QueryCometTxIndexer(query, func(txs *rpctypes.ParsedTxs) *rpctypes.ParsedTx { + txResult, err := b.QueryCometTxIndexer(ctx, query, func(txs *rpctypes.ParsedTxs) *rpctypes.ParsedTx { return txs.GetTxByTxIndex(int(index)) // #nosec G115 -- checked for int overflow already }) if err != nil { @@ -332,8 +352,11 @@ func (b *Backend) GetTxByTxIndex(height int64, index uint) (*servertypes.TxResul } // QueryCometTxIndexer query tx in CometBFT tx indexer -func (b *Backend) QueryCometTxIndexer(query string, txGetter func(*rpctypes.ParsedTxs) *rpctypes.ParsedTx) (*servertypes.TxResult, error) { - resTxs, err := b.ClientCtx.Client.TxSearch(b.Ctx, query, false, nil, nil, "") +func (b *Backend) QueryCometTxIndexer(ctx context.Context, query string, txGetter func(*rpctypes.ParsedTxs) *rpctypes.ParsedTx) (result *servertypes.TxResult, err error) { + ctx, span := tracer.Start(ctx, "QueryCometTxIndexer") + defer func() { evmtrace.EndSpanErr(span, err) }() + + resTxs, err := b.ClientCtx.Client.TxSearch(ctx, query, false, nil, nil, "") if err != nil { return nil, err } @@ -341,7 +364,7 @@ func (b *Backend) QueryCometTxIndexer(query string, txGetter func(*rpctypes.Pars return nil, errors.New("ethereum tx not found") } txResult := resTxs.Txs[0] - if !rpctypes.TxSucessOrExpectedFailure(&txResult.TxResult) { + if !evmtypes.TxSucessOrExpectedFailure(&txResult.TxResult) { return nil, errors.New("invalid ethereum tx") } @@ -358,15 +381,19 @@ func (b *Backend) QueryCometTxIndexer(query string, txGetter func(*rpctypes.Pars } // GetTransactionByBlockAndIndex is the common code shared by `GetTransactionByBlockNumberAndIndex` and `GetTransactionByBlockHashAndIndex`. -func (b *Backend) GetTransactionByBlockAndIndex(block *cmtrpctypes.ResultBlock, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) { - blockRes, err := b.RPCClient.BlockResults(b.Ctx, &block.Block.Height) +func (b *Backend) GetTransactionByBlockAndIndex(ctx context.Context, block *cmtrpctypes.ResultBlock, idx hexutil.Uint) (result *rpctypes.RPCTransaction, err error) { + //nolint:gosec // unlikely + ctx, span := tracer.Start(ctx, "GetTransactionByBlockAndIndex", trace.WithAttributes(attribute.Int64("blockHeight", block.Block.Height), attribute.Int64("idx", int64(idx)))) + defer func() { evmtrace.EndSpanErr(span, err) }() + + blockRes, err := b.RPCClient.BlockResults(ctx, &block.Block.Height) if err != nil { return nil, nil } var msg *evmtypes.MsgEthereumTx // find in tx indexer - res, err := b.GetTxByTxIndex(block.Block.Height, uint(idx)) + res, err := b.GetTxByTxIndex(ctx, block.Block.Height, uint(idx)) if err == nil { tx, err := b.ClientCtx.TxConfig.TxDecoder()(block.Block.Txs[res.TxIndex]) if err != nil { @@ -383,7 +410,7 @@ func (b *Backend) GetTransactionByBlockAndIndex(block *cmtrpctypes.ResultBlock, } } else { i := int(idx) // #nosec G115 - ethMsgs := b.EthMsgsFromCometBlock(block, blockRes) + ethMsgs := b.EthMsgsFromCometBlock(ctx, block, blockRes) if i >= len(ethMsgs) { b.Logger.Debug("block txs index out of bound", "index", i) return nil, nil @@ -392,7 +419,7 @@ func (b *Backend) GetTransactionByBlockAndIndex(block *cmtrpctypes.ResultBlock, msg = ethMsgs[i] } - baseFee, err := b.BaseFee(blockRes) + baseFee, err := b.BaseFee(ctx, blockRes) if err != nil { // handle the error for pruned node. b.Logger.Error("failed to fetch Base Fee from prunned block. Check node prunning configuration", "height", block.Block.Height, "error", err) @@ -415,24 +442,28 @@ func (b *Backend) GetTransactionByBlockAndIndex(block *cmtrpctypes.ResultBlock, // 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 (b *Backend) CreateAccessList( + ctx context.Context, args evmtypes.TransactionArgs, blockNrOrHash rpctypes.BlockNumberOrHash, overrides *json.RawMessage, -) (*rpctypes.AccessListResult, error) { - accessList, gasUsed, vmErr, err := b.createAccessList(args, blockNrOrHash, overrides) +) (result *rpctypes.AccessListResult, err error) { + ctx, span := tracer.Start(ctx, "CreateAccessList", trace.WithAttributes(attribute.String("from", args.GetFrom().Hex()), attribute.String("blockNrOrHash", unwrapBlockNOrHash(blockNrOrHash)))) + defer func() { evmtrace.EndSpanErr(span, err) }() + + accessList, gasUsed, vmErr, err := b.createAccessList(ctx, args, blockNrOrHash, overrides) if err != nil { return nil, err } hexGasUsed := hexutil.Uint64(gasUsed) - result := rpctypes.AccessListResult{ + res := rpctypes.AccessListResult{ AccessList: &accessList, GasUsed: &hexGasUsed, } if vmErr != nil { - result.Error = vmErr.Error() + res.Error = vmErr.Error() } - return &result, nil + return &res, nil } // createAccessList creates the access list for the transaction. @@ -441,29 +472,32 @@ func (b *Backend) CreateAccessList( // If the access list has not converged, an error is returned. // If the transaction itself fails, an vmErr is returned. func (b *Backend) createAccessList( + ctx context.Context, args evmtypes.TransactionArgs, blockNrOrHash rpctypes.BlockNumberOrHash, overrides *json.RawMessage, -) (ethtypes.AccessList, uint64, error, error) { - args, err := b.SetTxDefaults(args) +) (_ ethtypes.AccessList, _ uint64, _ error, sysErr error) { + ctx, span := tracer.Start(ctx, "createAccessList") + defer func() { evmtrace.EndSpanErr(span, sysErr) }() + args, err := b.SetTxDefaults(ctx, args) if err != nil { b.Logger.Error("failed to set tx defaults", "error", err) return nil, 0, nil, err } - blockNum, err := b.BlockNumberFromComet(blockNrOrHash) + blockNum, err := b.BlockNumberFromComet(ctx, blockNrOrHash) if err != nil { b.Logger.Error("failed to get block number", "error", err) return nil, 0, nil, err } - addressesToExclude, err := b.getAccessListExcludes(args, blockNum) + addressesToExclude, err := b.getAccessListExcludes(ctx, args, blockNum) if err != nil { b.Logger.Error("failed to get access list excludes", "error", err) return nil, 0, nil, err } - prevTracer, traceArgs, err := b.initAccessListTracer(args, blockNum, addressesToExclude) + prevTracer, traceArgs, err := b.initAccessListTracer(ctx, args, blockNum, addressesToExclude) if err != nil { b.Logger.Error("failed to init access list tracer", "error", err) return nil, 0, nil, err @@ -473,7 +507,7 @@ func (b *Backend) createAccessList( for { accessList := prevTracer.AccessList() traceArgs.AccessList = &accessList - res, err := b.DoCall(*traceArgs, blockNum, overrides) + res, err := b.DoCall(ctx, *traceArgs, blockNum, overrides) if err != nil { b.Logger.Error("failed to apply transaction", "error", err) return nil, 0, nil, fmt.Errorf("failed to apply transaction: %v err: %v", traceArgs.ToTransaction(ethtypes.LegacyTxType).Hash(), err) @@ -497,8 +531,10 @@ func (b *Backend) createAccessList( // getAccessListExcludes returns the addresses to exclude from the access list. // This includes the sender account, the target account (if provided), precompiles, // and any addresses in the authorization list. -func (b *Backend) getAccessListExcludes(args evmtypes.TransactionArgs, blockNum rpctypes.BlockNumber) (map[common.Address]struct{}, error) { - header, err := b.HeaderByNumber(blockNum) +func (b *Backend) getAccessListExcludes(ctx context.Context, args evmtypes.TransactionArgs, blockNum rpctypes.BlockNumber) (_ map[common.Address]struct{}, err error) { + ctx, span := tracer.Start(ctx, "getAccessListExcludes") + defer func() { evmtrace.EndSpanErr(span, err) }() + header, err := b.HeaderByNumber(ctx, blockNum) if err != nil { b.Logger.Error("failed to get header by number", "error", err) return nil, err @@ -544,8 +580,10 @@ func (b *Backend) getAccessListExcludes(args evmtypes.TransactionArgs, blockNum // 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) +func (b *Backend) initAccessListTracer(ctx context.Context, args evmtypes.TransactionArgs, blockNum rpctypes.BlockNumber, addressesToExclude map[common.Address]struct{}) (*logger.AccessListTracer, *evmtypes.TransactionArgs, error) { + ctx, span := tracer.Start(ctx, "initAccessListTracer") + defer span.End() + header, err := b.HeaderByNumber(ctx, blockNum) if err != nil { b.Logger.Error("failed to get header by number", "error", err) return nil, nil, err @@ -553,7 +591,7 @@ func (b *Backend) initAccessListTracer(args evmtypes.TransactionArgs, blockNum r if args.Nonce == nil { pending := blockNum == rpctypes.EthPendingBlockNumber - nonce, err := b.getAccountNonce(args.GetFrom(), pending, blockNum.Int64(), b.Logger) + nonce, err := b.getAccountNonce(ctx, args.GetFrom(), pending, blockNum.Int64(), b.Logger) if err != nil { b.Logger.Error("failed to get account nonce", "error", err) return nil, nil, err diff --git a/rpc/backend/tx_info_test.go b/rpc/backend/tx_info_test.go index 01bc7779..6dd2baa9 100644 --- a/rpc/backend/tx_info_test.go +++ b/rpc/backend/tx_info_test.go @@ -13,6 +13,7 @@ import ( ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + protov2 "google.golang.org/protobuf/proto" abcitypes "github.com/cometbft/cometbft/abci/types" tmrpctypes "github.com/cometbft/cometbft/rpc/core/types" @@ -65,10 +66,9 @@ func setupMockBackend(t *testing.T) *Backend { 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 := NewBackend(ctx, clientCtx, idxer, nil, WithLogger(ctx.Logger)) backend.Cfg.JSONRPC.GasCap = 25000000 backend.Cfg.JSONRPC.EVMTimeout = 0 backend.Cfg.JSONRPC.AllowInsecureUnlock = true @@ -77,7 +77,6 @@ func setupMockBackend(t *testing.T) *Backend { 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{ @@ -376,7 +375,7 @@ func TestCreateAccessList(t *testing.T) { require.NotEqual(t, common.Address{}, args.GetFrom(), "From address should not be zero") } - result, err := backend.CreateAccessList(args, blockNumOrHash, tc.overrides) + result, err := backend.CreateAccessList(rpctypes.NewContextWithHeight(1), args, blockNumOrHash, tc.overrides) if tc.expectError { require.Error(t, err) @@ -408,11 +407,16 @@ func TestCreateAccessList(t *testing.T) { } func buildMsgEthereumTx(t *testing.T) *evmtypes.MsgEthereumTx { + t.Helper() + return buildMsgEthereumTxWithNonce(t, 0) +} + +func buildMsgEthereumTxWithNonce(t *testing.T, nonce uint64) *evmtypes.MsgEthereumTx { t.Helper() from, _ := utiltx.NewAddrKey() ethTxParams := evmtypes.EvmTxArgs{ ChainID: new(big.Int).SetUint64(constants.ExampleChainID.EVMChainID), - Nonce: uint64(0), + Nonce: nonce, To: &common.Address{}, Amount: big.NewInt(0), GasLimit: 100000, @@ -423,6 +427,25 @@ func buildMsgEthereumTx(t *testing.T) *evmtypes.MsgEthereumTx { return msgEthereumTx } +type mockDecodedTx struct { + msgs []sdk.Msg +} + +func (m mockDecodedTx) GetMsgs() []sdk.Msg { return m.msgs } + +func (m mockDecodedTx) GetMsgsV2() ([]protov2.Message, error) { return nil, nil } + +func (m mockDecodedTx) ValidateBasic() error { return nil } + +type txConfigWithDecoder struct { + client.TxConfig + decoder sdk.TxDecoder +} + +func (t txConfigWithDecoder) TxDecoder() sdk.TxDecoder { + return t.decoder +} + type MockIndexer struct { txResults map[common.Hash]*servertypes.TxResult } @@ -466,11 +489,12 @@ func TestReceiptsFromCometBlock(t *testing.T) { TxsResults: []*abcitypes.ExecTxResult{{Code: 0, Data: encodedData}}, } tcs := []struct { - name string - ethTxIndex int32 + name string + ethTxIndex int32 + expectedTxIndex uint }{ - {"tx_with_index_5", 5}, - {"tx_with_index_10", 10}, + {"tx_with_valid_index", 5, 5}, + {"tx_with_sentinel_index", -1, 0}, // -1 sentinel resolved to loop index } for _, tc := range tcs { t.Run(tc.name, func(t *testing.T) { @@ -491,15 +515,128 @@ func TestReceiptsFromCometBlock(t *testing.T) { backend.Indexer = mockIndexer mockEVMQueryClient := backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) mockEVMQueryClient.On("BaseFee", mock.Anything, mock.Anything).Return(&evmtypes.QueryBaseFeeResponse{}, nil) - receipts, err := backend.ReceiptsFromCometBlock(resBlock, blockRes, msgs) + receipts, err := backend.ReceiptsFromCometBlock(rpctypes.NewContextWithHeight(1), resBlock, blockRes, msgs) require.NoError(t, err) require.Len(t, receipts, 1) - actualTxIndex := receipts[0].TransactionIndex - require.NotEqual(t, uint(0), actualTxIndex) - require.Equal(t, uint(tc.ethTxIndex), actualTxIndex) // #nosec G115 + require.Equal(t, tc.expectedTxIndex, receipts[0].TransactionIndex) require.Equal(t, msgs[0].Hash(), receipts[0].TxHash) require.Equal(t, big.NewInt(height), receipts[0].BlockNumber) require.Equal(t, ethtypes.ReceiptStatusSuccessful, receipts[0].Status) }) } } + +// TestReceiptsLogIndexBlockGlobal asserts that after PatchTxResponses runs +// on a block's ExecTxResults, ReceiptsFromCometBlock surfaces block-global +// log.Index and eth-only log.TxIndex per the Ethereum JSON-RPC spec. +func TestReceiptsLogIndexBlockGlobal(t *testing.T) { + backend := setupMockBackend(t) + height := int64(200) + encodingConfig := encoding.MakeConfig(constants.ExampleChainID.EVMChainID) + + addr := common.HexToAddress("0x1234567890abcdef1234567890abcdef12345678") + topic := common.HexToHash("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef") + + // Pre-patch logs: log.TxIndex == cosmos tx index, log.Index per-tx local. + makeTxResponse := func(hash string, cosmosTxIndex uint64) *evmtypes.MsgEthereumTxResponse { + return &evmtypes.MsgEthereumTxResponse{ + Hash: hash, + Logs: []*evmtypes.Log{ + {Address: addr.String(), Topics: []string{topic.String()}, TxIndex: cosmosTxIndex, Index: 0}, + {Address: addr.String(), Topics: []string{topic.String()}, TxIndex: cosmosTxIndex, Index: 1}, + }, + } + } + + // Distinct nonces so the eth tx hashes differ. + msg0 := buildMsgEthereumTxWithNonce(t, 0) + msg1 := buildMsgEthereumTxWithNonce(t, 1) + + encodeTxResult := func(resp *evmtypes.MsgEthereumTxResponse) []byte { + anyData := codectypes.UnsafePackAny(resp) + txMsgData := &sdk.TxMsgData{MsgResponses: []*codectypes.Any{anyData}} + data, err := encodingConfig.Codec.Marshal(txMsgData) + require.NoError(t, err) + return data + } + + tx0Data := encodeTxResult(makeTxResponse(msg0.Hash().Hex(), 0)) + tx1Data := encodeTxResult(makeTxResponse(msg1.Hash().Hex(), 1)) + + resBlock := &tmrpctypes.ResultBlock{ + Block: &tmtypes.Block{Header: tmtypes.Header{Height: height}}, + } + blockRes := &tmrpctypes.ResultBlockResults{ + Height: height, + TxsResults: []*abcitypes.ExecTxResult{ + {Code: 0, Data: tx0Data}, + {Code: 0, Data: tx1Data}, + }, + } + + patched, err := evmtypes.PatchTxResponses(blockRes.TxsResults) + require.NoError(t, err) + blockRes.TxsResults = patched + + mockIndexer := &MockIndexer{ + txResults: map[common.Hash]*servertypes.TxResult{ + msg0.Hash(): {Height: height, TxIndex: 0, EthTxIndex: 0, MsgIndex: 0}, + msg1.Hash(): {Height: height, TxIndex: 1, EthTxIndex: 1, MsgIndex: 0}, + }, + } + backend.Indexer = mockIndexer + + mockEVMQueryClient := backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + mockEVMQueryClient.On("BaseFee", mock.Anything, mock.Anything).Return(&evmtypes.QueryBaseFeeResponse{}, nil) + + msgs := []*evmtypes.MsgEthereumTx{msg0, msg1} + receipts, err := backend.ReceiptsFromCometBlock(rpctypes.NewContextWithHeight(1), resBlock, blockRes, msgs) + require.NoError(t, err) + require.Len(t, receipts, 2) + + require.Len(t, receipts[0].Logs, 2) + require.Equal(t, uint(0), receipts[0].Logs[0].Index) + require.Equal(t, uint(1), receipts[0].Logs[1].Index) + require.Equal(t, uint(0), receipts[0].Logs[0].TxIndex) + require.Equal(t, uint(0), receipts[0].Logs[1].TxIndex) + + require.Len(t, receipts[1].Logs, 2) + require.Equal(t, uint(2), receipts[1].Logs[0].Index) + require.Equal(t, uint(3), receipts[1].Logs[1].Index) + require.Equal(t, uint(1), receipts[1].Logs[0].TxIndex) + require.Equal(t, uint(1), receipts[1].Logs[1].TxIndex) +} + +func TestEthMsgsFromCometBlockSkipStateDBCommitFailure(t *testing.T) { + backend := setupMockBackend(t) + successMsg := buildMsgEthereumTx(t) + decodeCalls := 0 + + backend.ClientCtx = backend.ClientCtx.WithTxConfig(txConfigWithDecoder{ + TxConfig: backend.ClientCtx.TxConfig, + decoder: func(_ []byte) (sdk.Tx, error) { + decodeCalls++ + return mockDecodedTx{msgs: []sdk.Msg{successMsg}}, nil + }, + }) + + resBlock := &tmrpctypes.ResultBlock{ + Block: &tmtypes.Block{ + Header: tmtypes.Header{Height: 100}, + Data: tmtypes.Data{Txs: []tmtypes.Tx{{0x01}, {0x02}}}, + }, + } + + blockRes := &tmrpctypes.ResultBlockResults{ + Height: 100, + TxsResults: []*abcitypes.ExecTxResult{ + {Code: 4, Log: "failed to commit stateDB"}, + {Code: 0}, + }, + } + + msgs := backend.EthMsgsFromCometBlock(rpctypes.NewContextWithHeight(100), resBlock, blockRes) + require.Equal(t, 1, decodeCalls) + require.Len(t, msgs, 1) + require.Same(t, successMsg, msgs[0]) +} diff --git a/rpc/backend/tx_pool.go b/rpc/backend/tx_pool.go index 61b980e3..b76ad1e1 100644 --- a/rpc/backend/tx_pool.go +++ b/rpc/backend/tx_pool.go @@ -1,14 +1,18 @@ package backend import ( + "context" "fmt" "strconv" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" ethtypes "github.com/ethereum/go-ethereum/core/types" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" "github.com/cosmos/evm/rpc/types" + evmtrace "github.com/cosmos/evm/trace" ) const ( @@ -19,14 +23,17 @@ const ( // The code style for this API is based off of the Go-Ethereum implementation: // Content returns the transactions contained within the transaction pool. -func (b *Backend) Content() (map[string]map[string]map[string]*types.RPCTransaction, error) { +func (b *Backend) Content(ctx context.Context) (result map[string]map[string]map[string]*types.RPCTransaction, err error) { + ctx, span := tracer.Start(ctx, "Content") + defer func() { evmtrace.EndSpanErr(span, err) }() + content := map[string]map[string]map[string]*types.RPCTransaction{ StatusPending: make(map[string]map[string]*types.RPCTransaction), StatusQueued: make(map[string]map[string]*types.RPCTransaction), } // Get current block header - curHeader, err := b.CurrentHeader() + curHeader, err := b.CurrentHeader(ctx) if err != nil { return content, fmt.Errorf("failed to get current header: %w", err) } @@ -70,11 +77,14 @@ func (b *Backend) Content() (map[string]map[string]map[string]*types.RPCTransact } // ContentFrom returns the transactions contained within the transaction pool -func (b *Backend) ContentFrom(addr common.Address) (map[string]map[string]*types.RPCTransaction, error) { +func (b *Backend) ContentFrom(ctx context.Context, addr common.Address) (result map[string]map[string]*types.RPCTransaction, err error) { + ctx, span := tracer.Start(ctx, "ContentFrom", trace.WithAttributes(attribute.String("address", addr.Hex()))) + defer func() { evmtrace.EndSpanErr(span, err) }() + content := make(map[string]map[string]*types.RPCTransaction, 2) // Get current block header - curHeader, err := b.CurrentHeader() + curHeader, err := b.CurrentHeader(ctx) if err != nil { return content, fmt.Errorf("failed to get current header: %w", err) } @@ -108,7 +118,7 @@ func (b *Backend) ContentFrom(addr common.Address) (map[string]map[string]*types } // Inspect returns the content of the transaction pool and flattens it into an easily inspectable list. -func (b *Backend) Inspect() (map[string]map[string]map[string]string, error) { +func (b *Backend) Inspect(_ context.Context) (map[string]map[string]map[string]string, error) { inspect := map[string]map[string]map[string]string{ StatusPending: make(map[string]map[string]string), StatusQueued: make(map[string]map[string]string), @@ -155,7 +165,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) { +func (b *Backend) Status(_ context.Context) (map[string]hexutil.Uint, error) { // Get the global mempool instance evmMempool := b.Mempool if evmMempool == nil { diff --git a/rpc/backend/utils.go b/rpc/backend/utils.go index ca46109b..c1f43a44 100644 --- a/rpc/backend/utils.go +++ b/rpc/backend/utils.go @@ -1,6 +1,7 @@ package backend import ( + "context" "fmt" "math" "math/big" @@ -19,11 +20,12 @@ import ( cmtrpctypes "github.com/cometbft/cometbft/rpc/core/types" "github.com/cosmos/evm/rpc/types" + evmtrace "github.com/cosmos/evm/trace" "github.com/cosmos/evm/utils" feemarkettypes "github.com/cosmos/evm/x/feemarket/types" evmtypes "github.com/cosmos/evm/x/vm/types" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -49,10 +51,12 @@ func (s sortGasAndReward) Less(i, j int) bool { // If the pending value is true, it will iterate over the mempool (pending) // txs in order to compute and return the pending tx sequence. // Todo: include the ability to specify a blockNumber -func (b *Backend) getAccountNonce(accAddr common.Address, pending bool, height int64, logger log.Logger) (uint64, error) { +func (b *Backend) getAccountNonce(ctx context.Context, accAddr common.Address, pending bool, height int64, logger log.Logger) (_ uint64, err error) { + ctx, span := tracer.Start(ctx, "getAccountNonce") + defer func() { evmtrace.EndSpanErr(span, err) }() queryClient := authtypes.NewQueryClient(b.ClientCtx) adr := sdk.AccAddress(accAddr.Bytes()).String() - ctx := types.ContextWithHeight(height) + ctx = types.ContextWithHeight(ctx, height) res, err := queryClient.Account(ctx, &authtypes.QueryAccountRequest{Address: adr}) if err != nil { st, ok := status.FromError(err) @@ -81,7 +85,7 @@ func (b *Backend) getAccountNonce(accAddr common.Address, pending bool, height i // the account retriever doesn't include the uncommitted transactions on the nonce so we need to // to manually add them. - pendingTxs, err := b.PendingTransactions() + pendingTxs, err := b.PendingTransactions(ctx) if err != nil { logger.Error("failed to fetch pending transactions", "error", err.Error()) return nonce, nil @@ -122,6 +126,7 @@ func (b *Backend) getAccountNonce(accAddr common.Address, pending bool, height i // - Transaction reward percentiles based on effective gas tip values // // Parameters: +// - ctx: Context for the request // - cometBlock: The raw CometBFT block containing transaction data // - ethBlock: Ethereum-formatted block with gas limit and usage information // - rewardPercentiles: Percentile values (0-100) for reward calculation @@ -130,14 +135,17 @@ func (b *Backend) getAccountNonce(accAddr common.Address, pending bool, height i // // Returns an error if block processing fails due to invalid data types or calculation errors. func (b *Backend) ProcessBlock( + ctx context.Context, cometBlock *cmtrpctypes.ResultBlock, ethBlock *map[string]interface{}, rewardPercentiles []float64, cometBlockResult *cmtrpctypes.ResultBlockResults, targetOneFeeHistory *types.OneFeeHistory, -) error { +) (err error) { + ctx, span := tracer.Start(ctx, "ProcessBlock") + defer func() { evmtrace.EndSpanErr(span, err) }() blockHeight := cometBlock.Block.Height - blockBaseFee, err := b.BaseFee(cometBlockResult) + blockBaseFee, err := b.BaseFee(ctx, cometBlockResult) if err != nil || blockBaseFee == nil { targetOneFeeHistory.BaseFee = big.NewInt(0) } else { @@ -176,7 +184,7 @@ func (b *Backend) ProcessBlock( targetOneFeeHistory.BlobGasUsedRatio = 0 if cfg.IsLondon(big.NewInt(blockHeight + 1)) { - ctx := types.ContextWithHeight(blockHeight) + ctx = types.ContextWithHeight(ctx, blockHeight) params, err := b.QueryClient.FeeMarket.Params(ctx, &feemarkettypes.QueryParamsRequest{}) if err != nil { return err @@ -337,3 +345,29 @@ func GetHexProofs(proof *crypto.ProofOps) []string { } return proofs } + +func unwrapBlockNOrHash(blockNOrHash types.BlockNumberOrHash) string { + if blockNOrHash.BlockHash != nil { + return blockNOrHash.BlockHash.String() + } + if blockNOrHash.BlockNumber != nil { + return fmt.Sprintf("%d", *blockNOrHash.BlockNumber) + } + return "" +} + +// FindEthTxIndexByHash is a fallback that locates an eth tx's index by +// iterating every valid eth tx in the block. Used for legacy blocks whose +// ethereum_tx events lack AttributeKeyTxIndex. +func (b *Backend) FindEthTxIndexByHash(ctx context.Context, txHash common.Hash, block *cmtrpctypes.ResultBlock, blockRes *cmtrpctypes.ResultBlockResults) (int32, error) { + msgs := b.EthMsgsFromCometBlock(ctx, block, blockRes) + for i := range msgs { + if msgs[i].Hash() == txHash { + if i > math.MaxInt32 { + return -1, fmt.Errorf("tx index overflow") + } + return int32(i), nil //#nosec G115 -- checked for int overflow already + } + } + return -1, fmt.Errorf("can't find index of ethereum tx") +} diff --git a/rpc/ethereum/pubsub/pubsub.go b/rpc/ethereum/pubsub/pubsub.go index d76189bb..ce8f519b 100644 --- a/rpc/ethereum/pubsub/pubsub.go +++ b/rpc/ethereum/pubsub/pubsub.go @@ -107,7 +107,7 @@ func (m *memEventBus) Subscribe(name string) (<-chan coretypes.ResultEvent, Unsu m.topicsMux.RUnlock() if !ok { - return nil, nil, errors.Wrapf(ErrTopicNotFound, name) + return nil, nil, errors.Wrap(ErrTopicNotFound, name) } ch := make(chan coretypes.ResultEvent) diff --git a/rpc/namespaces/ethereum/debug/api.go b/rpc/namespaces/ethereum/debug/api.go index 65ff0c5e..4b0de57d 100644 --- a/rpc/namespaces/ethereum/debug/api.go +++ b/rpc/namespaces/ethereum/debug/api.go @@ -2,6 +2,7 @@ package debug import ( "bytes" + "context" "errors" "fmt" "io" @@ -19,16 +20,22 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/rlp" stderrors "github.com/pkg/errors" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" "github.com/cosmos/evm/rpc/backend" rpctypes "github.com/cosmos/evm/rpc/types" + evmtrace "github.com/cosmos/evm/trace" evmtypes "github.com/cosmos/evm/x/vm/types" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" "github.com/cosmos/cosmos-sdk/server" ) +var tracer = otel.Tracer("evm/rpc/namespaces/ethereum/debug") + // HandlerT keeps track of the cpu profiler and trace execution type HandlerT struct { cpuFilename string @@ -66,32 +73,38 @@ func NewAPI( // and returns them as a JSON object. func (a *API) TraceTransaction(hash common.Hash, config *rpctypes.TraceConfig) (interface{}, error) { a.logger.Debug("debug_traceTransaction", "hash", hash) - return a.backend.TraceTransaction(hash, config) + ctx, span := tracer.Start(context.Background(), "eth_traceTransaction", trace.WithAttributes(attribute.String("hash", hash.String()))) + defer span.End() + return a.backend.TraceTransaction(ctx, hash, config) } // TraceBlockByNumber returns the structured logs created during the execution of // EVM and returns them as a JSON object. -func (a *API) TraceBlockByNumber(height rpctypes.BlockNumber, config *rpctypes.TraceConfig) ([]*evmtypes.TxTraceResult, error) { +func (a *API) TraceBlockByNumber(height rpctypes.BlockNumber, config *rpctypes.TraceConfig) (res []*evmtypes.TxTraceResult, err error) { a.logger.Debug("debug_traceBlockByNumber", "height", height) + ctx, span := tracer.Start(context.Background(), "eth_traceBlockByNumber", trace.WithAttributes(attribute.Int64("height", int64(height)))) + defer func() { evmtrace.EndSpanErr(span, err) }() if height == 0 { return nil, errors.New("genesis is not traceable") } // Get CometBFT Block - resBlock, err := a.backend.CometBlockByNumber(height) + resBlock, err := a.backend.CometBlockByNumber(ctx, height) if err != nil { a.logger.Debug("get block failed", "height", height, "error", err.Error()) return nil, err } - return a.backend.TraceBlock(rpctypes.BlockNumber(resBlock.Block.Height), config, resBlock) + return a.backend.TraceBlock(ctx, rpctypes.BlockNumber(resBlock.Block.Height), config, resBlock) } // TraceBlockByHash returns the structured logs created during the execution of // EVM and returns them as a JSON object. func (a *API) TraceBlockByHash(hash common.Hash, config *rpctypes.TraceConfig) ([]*evmtypes.TxTraceResult, error) { a.logger.Debug("debug_traceBlockByHash", "hash", hash) + ctx, span := tracer.Start(context.Background(), "eth_traceBlockByHash") + defer span.End() // Get CometBFT Block - resBlock, err := a.backend.CometBlockByHash(hash) + resBlock, err := a.backend.CometBlockByHash(ctx, hash) if err != nil { a.logger.Debug("get block failed", "hash", hash.Hex(), "error", err.Error()) return nil, err @@ -102,13 +115,15 @@ func (a *API) TraceBlockByHash(hash common.Hash, config *rpctypes.TraceConfig) ( return nil, errors.New("block not found") } - return a.backend.TraceBlock(rpctypes.BlockNumber(resBlock.Block.Height), config, resBlock) + return a.backend.TraceBlock(ctx, rpctypes.BlockNumber(resBlock.Block.Height), config, resBlock) } // TraceBlock returns the structured logs created during the execution of // EVM and returns them as a JSON object. It accepts an RLP-encoded block. -func (a *API) TraceBlock(tblockRlp hexutil.Bytes, config *rpctypes.TraceConfig) ([]*evmtypes.TxTraceResult, error) { +func (a *API) TraceBlock(ctx context.Context, tblockRlp hexutil.Bytes, config *rpctypes.TraceConfig) (_ []*evmtypes.TxTraceResult, err error) { a.logger.Debug("debug_traceBlock", "size", len(tblockRlp)) + ctx, span := tracer.Start(ctx, "eth_traceBlock") + defer func() { evmtrace.EndSpanErr(span, err) }() // Decode RLP-encoded block var block types.Block if err := rlp.DecodeBytes(tblockRlp, &block); err != nil { @@ -125,7 +140,7 @@ func (a *API) TraceBlock(tblockRlp hexutil.Bytes, config *rpctypes.TraceConfig) a.logger.Debug("decoded block", "number", blockNumber, "hash", block.Hash().Hex()) // Get CometBFT block by number (not hash, as Ethereum block hash may differ from CometBFT hash) - resBlock, err := a.backend.CometBlockByNumber(blockNumber) + resBlock, err := a.backend.CometBlockByNumber(ctx, blockNumber) if err != nil { a.logger.Debug("get block failed", "number", blockNumber, "error", err.Error()) return nil, err @@ -136,29 +151,32 @@ func (a *API) TraceBlock(tblockRlp hexutil.Bytes, config *rpctypes.TraceConfig) return nil, errors.New("block not found") } - return a.backend.TraceBlock(blockNumber, config, resBlock) + return a.backend.TraceBlock(ctx, blockNumber, config, resBlock) } // TraceCall lets you trace a given eth_call. It collects the structured logs // created during the execution of EVM if the given transaction was added on // top of the provided block and returns them as a JSON object. -func (a *API) TraceCall(args evmtypes.TransactionArgs, blockNrOrHash rpctypes.BlockNumberOrHash, config *rpctypes.TraceConfig) (interface{}, error) { +func (a *API) TraceCall(ctx context.Context, args evmtypes.TransactionArgs, blockNrOrHash rpctypes.BlockNumberOrHash, config *rpctypes.TraceConfig) (interface{}, error) { a.logger.Debug("debug_traceCall", "args", args, "block number or hash", blockNrOrHash) - return a.backend.TraceCall(args, blockNrOrHash, config) + ctx, span := tracer.Start(ctx, "eth_traceCall") + defer span.End() + return a.backend.TraceCall(ctx, args, blockNrOrHash, config) } // GetRawBlock retrieves the RLP-encoded block by block number or hash. -func (a *API) GetRawBlock(blockNrOrHash rpctypes.BlockNumberOrHash) (hexutil.Bytes, error) { +func (a *API) GetRawBlock(ctx context.Context, blockNrOrHash rpctypes.BlockNumberOrHash) (_ hexutil.Bytes, err error) { a.logger.Debug("debug_getRawBlock", "block number or hash", blockNrOrHash) - + ctx, span := tracer.Start(ctx, "eth_getRawBlock") + defer func() { evmtrace.EndSpanErr(span, err) }() // Get block number from blockNrOrHash - blockNum, err := a.backend.BlockNumberFromComet(blockNrOrHash) + blockNum, err := a.backend.BlockNumberFromComet(ctx, blockNrOrHash) if err != nil { return nil, err } // Get Ethereum block by number - block, err := a.backend.EthBlockByNumber(blockNum) + block, err := a.backend.EthBlockByNumber(ctx, blockNum) if err != nil { return nil, err } @@ -187,7 +205,7 @@ func (a *API) BlockProfile(file string, nsec uint) error { // CpuProfile turns on CPU profiling for nsec seconds and writes // profile data to file. -func (a *API) CpuProfile(file string, nsec uint) error { //nolint: revive +func (a *API) CpuProfile(file string, nsec uint) error { a.logger.Debug("debug_cpuProfile", "file", file, "nsec", nsec) if !a.profilingEnabled { return rpctypes.ErrProfilingDisabled @@ -406,11 +424,13 @@ func (a *API) SetGCPercent(v int) (int, error) { } // GetHeaderRlp retrieves the RLP encoded for of a single header. -func (a *API) GetHeaderRlp(number uint64) (hexutil.Bytes, error) { +func (a *API) GetHeaderRlp(number uint64) (_ hexutil.Bytes, err error) { + ctx, span := tracer.Start(context.Background(), "eth_getHeaderRlp") + defer func() { evmtrace.EndSpanErr(span, err) }() if !a.profilingEnabled { return nil, rpctypes.ErrProfilingDisabled } - header, err := a.backend.HeaderByNumber(rpctypes.BlockNumber(number)) //#nosec G115 -- int overflow is not a concern here -- block number is not likely to exceed int64 max value + header, err := a.backend.HeaderByNumber(ctx, rpctypes.BlockNumber(number)) //#nosec G115 -- int overflow is not a concern here -- block number is not likely to exceed int64 max value if err != nil { return nil, err } @@ -419,11 +439,13 @@ func (a *API) GetHeaderRlp(number uint64) (hexutil.Bytes, error) { } // GetBlockRlp retrieves the RLP encoded for of a single block. -func (a *API) GetBlockRlp(number uint64) (hexutil.Bytes, error) { +func (a *API) GetBlockRlp(number uint64) (_ hexutil.Bytes, err error) { + ctx, span := tracer.Start(context.Background(), "eth_getBlockRlp") + defer func() { evmtrace.EndSpanErr(span, err) }() if !a.profilingEnabled { return nil, rpctypes.ErrProfilingDisabled } - block, err := a.backend.EthBlockByNumber(rpctypes.BlockNumber(number)) //#nosec G115 -- int overflow is not a concern here -- block number is not likely to exceed int64 max value + block, err := a.backend.EthBlockByNumber(ctx, rpctypes.BlockNumber(number)) //#nosec G115 -- int overflow is not a concern here -- block number is not likely to exceed int64 max value if err != nil { return nil, err } @@ -432,11 +454,13 @@ func (a *API) GetBlockRlp(number uint64) (hexutil.Bytes, error) { } // PrintBlock retrieves a block and returns its pretty printed form. -func (a *API) PrintBlock(number uint64) (string, error) { +func (a *API) PrintBlock(number uint64) (_ string, err error) { + ctx, span := tracer.Start(context.Background(), "eth_printBlock") + defer func() { evmtrace.EndSpanErr(span, err) }() if !a.profilingEnabled { return "", rpctypes.ErrProfilingDisabled } - block, err := a.backend.EthBlockByNumber(rpctypes.BlockNumber(number)) //#nosec G115 -- int overflow is not a concern here -- block number is not likely to exceed int64 max value + block, err := a.backend.EthBlockByNumber(ctx, rpctypes.BlockNumber(number)) //#nosec G115 -- int overflow is not a concern here -- block number is not likely to exceed int64 max value if err != nil { return "", err } diff --git a/rpc/namespaces/ethereum/debug/trace_fallback.go b/rpc/namespaces/ethereum/debug/trace_fallback.go index 9100dc46..db3e8b23 100644 --- a/rpc/namespaces/ethereum/debug/trace_fallback.go +++ b/rpc/namespaces/ethereum/debug/trace_fallback.go @@ -15,7 +15,6 @@ // along with the go-ethereum library. If not, see . //go:build !go1.5 -// +build !go1.5 // no-op implementation of tracing methods for Go < 1.5. diff --git a/rpc/namespaces/ethereum/debug/utils.go b/rpc/namespaces/ethereum/debug/utils.go index 8ed0c191..2659db3f 100644 --- a/rpc/namespaces/ethereum/debug/utils.go +++ b/rpc/namespaces/ethereum/debug/utils.go @@ -9,7 +9,7 @@ import ( "github.com/spf13/cast" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" "github.com/cosmos/cosmos-sdk/server" ) diff --git a/rpc/namespaces/ethereum/eth/api.go b/rpc/namespaces/ethereum/eth/api.go index a7af7594..fed086fb 100644 --- a/rpc/namespaces/ethereum/eth/api.go +++ b/rpc/namespaces/ethereum/eth/api.go @@ -10,14 +10,18 @@ import ( ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/signer/core/apitypes" + "go.opentelemetry.io/otel" "github.com/cosmos/evm/rpc/backend" rpctypes "github.com/cosmos/evm/rpc/types" + evmtrace "github.com/cosmos/evm/trace" evmtypes "github.com/cosmos/evm/x/vm/types" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" ) +var tracer = otel.Tracer("evm/rpc/namespaces/ethereum/eth") + // The Ethereum API allows applications to connect to an node of any Cosmos EVM based blockchain. // Developers can interact with on-chain EVM data // and send different types of transactions to the network by utilizing the @@ -74,7 +78,7 @@ type EthereumAPI interface { // Returns information on the Ethereum network and internal settings. ProtocolVersion() hexutil.Uint GasPrice() (*hexutil.Big, error) - EstimateGas(args evmtypes.TransactionArgs, blockNrOptional *rpctypes.BlockNumber) (hexutil.Uint64, error) + EstimateGas(args evmtypes.TransactionArgs, blockNrOrHash *rpctypes.BlockNumberOrHash, overrides *json.RawMessage) (hexutil.Uint64, error) FeeHistory(blockCount math.HexOrDecimal64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*rpctypes.FeeHistoryResult, error) MaxPriorityFeePerGas() (*hexutil.Big, error) ChainId() (*hexutil.Big, error) @@ -133,15 +137,19 @@ func NewPublicAPI(logger log.Logger, backend backend.EVMBackend) *PublicAPI { // - When blockNr is -2 the chain latest header is returned. // - When blockNr is -3 the chain finalized header is returned. // - When blockNr is -4 the chain safe header is returned. -func (e *PublicAPI) GetHeaderByNumber(ethBlockNum rpctypes.BlockNumber) (map[string]interface{}, error) { +func (e *PublicAPI) GetHeaderByNumber(ethBlockNum rpctypes.BlockNumber) (_ map[string]interface{}, err error) { + ctx, span := tracer.Start(context.Background(), "eth_getHeaderByNumber") + defer func() { evmtrace.EndSpanErr(span, err) }() e.logger.Debug("eth_getHeaderByNumber", "number", ethBlockNum) - return e.backend.GetHeaderByNumber(ethBlockNum) + return e.backend.GetHeaderByNumber(ctx, ethBlockNum) } // GetHeaderByHash returns the requested header by hash. -func (e *PublicAPI) GetHeaderByHash(hash common.Hash) (map[string]interface{}, error) { +func (e *PublicAPI) GetHeaderByHash(hash common.Hash) (_ map[string]interface{}, err error) { + ctx, span := tracer.Start(context.Background(), "eth_getHeaderByHash") + defer func() { evmtrace.EndSpanErr(span, err) }() e.logger.Debug("eth_getHeaderByHash", "hash", hash.Hex()) - return e.backend.GetHeaderByHash(hash) + return e.backend.GetHeaderByHash(ctx, hash) } //////////////////////////////////////////////////////////////////////////////////////// @@ -149,27 +157,35 @@ func (e *PublicAPI) GetHeaderByHash(hash common.Hash) (map[string]interface{}, e //////////////////////////////////////////////////////////////////////////////////////// // BlockNumber returns the current block number. -func (e *PublicAPI) BlockNumber() (hexutil.Uint64, error) { +func (e *PublicAPI) BlockNumber() (_ hexutil.Uint64, err error) { + ctx, span := tracer.Start(context.Background(), "eth_blockNumber") + defer func() { evmtrace.EndSpanErr(span, err) }() e.logger.Debug("eth_blockNumber") - return e.backend.BlockNumber() + return e.backend.BlockNumber(ctx) } // GetBlockByNumber returns the block identified by number. -func (e *PublicAPI) GetBlockByNumber(ethBlockNum rpctypes.BlockNumber, fullTx bool) (map[string]interface{}, error) { +func (e *PublicAPI) GetBlockByNumber(ethBlockNum rpctypes.BlockNumber, fullTx bool) (_ map[string]interface{}, err error) { + ctx, span := tracer.Start(context.Background(), "eth_getBlockByNumber") + defer func() { evmtrace.EndSpanErr(span, err) }() e.logger.Debug("eth_getBlockByNumber", "number", ethBlockNum, "full", fullTx) - return e.backend.GetBlockByNumber(ethBlockNum, fullTx) + return e.backend.GetBlockByNumber(ctx, ethBlockNum, fullTx) } // GetBlockByHash returns the block identified by hash. -func (e *PublicAPI) GetBlockByHash(hash common.Hash, fullTx bool) (map[string]interface{}, error) { +func (e *PublicAPI) GetBlockByHash(hash common.Hash, fullTx bool) (_ map[string]interface{}, err error) { + ctx, span := tracer.Start(context.Background(), "eth_getBlockByHash") + defer func() { evmtrace.EndSpanErr(span, err) }() e.logger.Debug("eth_getBlockByHash", "hash", hash.Hex(), "full", fullTx) - return e.backend.GetBlockByHash(hash, fullTx) + return e.backend.GetBlockByHash(ctx, hash, fullTx) } // GetBlockReceipts returns the block receipts for the given block hash or number or tag. -func (e *PublicAPI) GetBlockReceipts(ctx context.Context, blockNrOrHash rpctypes.BlockNumberOrHash) ([]map[string]interface{}, error) { +func (e *PublicAPI) GetBlockReceipts(ctx context.Context, blockNrOrHash rpctypes.BlockNumberOrHash) (_ []map[string]interface{}, err error) { + ctx, span := tracer.Start(ctx, "eth_getBlockReceipts") + defer func() { evmtrace.EndSpanErr(span, err) }() e.logger.Debug("eth_getBlockReceipts", "block number or hash", blockNrOrHash) - return e.backend.GetBlockReceipts(blockNrOrHash) + return e.backend.GetBlockReceipts(ctx, blockNrOrHash) } /////////////////////////////////////////////////////////////////////////////// @@ -177,50 +193,64 @@ func (e *PublicAPI) GetBlockReceipts(ctx context.Context, blockNrOrHash rpctypes /////////////////////////////////////////////////////////////////////////////// // GetTransactionByHash returns the transaction identified by hash. -func (e *PublicAPI) GetTransactionByHash(hash common.Hash) (*rpctypes.RPCTransaction, error) { +func (e *PublicAPI) GetTransactionByHash(hash common.Hash) (_ *rpctypes.RPCTransaction, err error) { + ctx, span := tracer.Start(context.Background(), "eth_getTransactionByHash") + defer func() { evmtrace.EndSpanErr(span, err) }() e.logger.Debug("eth_getTransactionByHash", "hash", hash.Hex()) - return e.backend.GetTransactionByHash(hash) + return e.backend.GetTransactionByHash(ctx, hash) } // GetTransactionCount returns the number of transactions at the given address up to the given block number. -func (e *PublicAPI) GetTransactionCount(address common.Address, blockNrOrHash rpctypes.BlockNumberOrHash) (*hexutil.Uint64, error) { +func (e *PublicAPI) GetTransactionCount(address common.Address, blockNrOrHash rpctypes.BlockNumberOrHash) (_ *hexutil.Uint64, err error) { + ctx, span := tracer.Start(context.Background(), "eth_getTransactionCount") + defer func() { evmtrace.EndSpanErr(span, err) }() e.logger.Debug("eth_getTransactionCount", "address", address.Hex(), "block number or hash", blockNrOrHash) - blockNum, err := e.backend.BlockNumberFromComet(blockNrOrHash) + blockNum, err := e.backend.BlockNumberFromComet(ctx, blockNrOrHash) if err != nil { return nil, err } - return e.backend.GetTransactionCount(address, blockNum) + return e.backend.GetTransactionCount(ctx, address, blockNum) } // GetTransactionReceipt returns the transaction receipt identified by hash. -func (e *PublicAPI) GetTransactionReceipt(hash common.Hash) (map[string]interface{}, error) { +func (e *PublicAPI) GetTransactionReceipt(hash common.Hash) (_ map[string]interface{}, err error) { + ctx, span := tracer.Start(context.Background(), "eth_getTransactionReceipt") + defer func() { evmtrace.EndSpanErr(span, err) }() hexTx := hash.Hex() e.logger.Debug("eth_getTransactionReceipt", "hash", hexTx) - return e.backend.GetTransactionReceipt(hash) + return e.backend.GetTransactionReceipt(ctx, hash) } // GetBlockTransactionCountByHash returns the number of transactions in the block identified by hash. -func (e *PublicAPI) GetBlockTransactionCountByHash(hash common.Hash) *hexutil.Uint { +func (e *PublicAPI) GetBlockTransactionCountByHash(hash common.Hash) (_ *hexutil.Uint) { + ctx, span := tracer.Start(context.Background(), "eth_getBlockTransactionCountByHash") + defer span.End() e.logger.Debug("eth_getBlockTransactionCountByHash", "hash", hash.Hex()) - return e.backend.GetBlockTransactionCountByHash(hash) + return e.backend.GetBlockTransactionCountByHash(ctx, hash) } // GetBlockTransactionCountByNumber returns the number of transactions in the block identified by number. -func (e *PublicAPI) GetBlockTransactionCountByNumber(blockNum rpctypes.BlockNumber) *hexutil.Uint { +func (e *PublicAPI) GetBlockTransactionCountByNumber(blockNum rpctypes.BlockNumber) (_ *hexutil.Uint) { + ctx, span := tracer.Start(context.Background(), "eth_getBlockTransactionCountByNumber") + defer span.End() e.logger.Debug("eth_getBlockTransactionCountByNumber", "height", blockNum.Int64()) - return e.backend.GetBlockTransactionCountByNumber(blockNum) + return e.backend.GetBlockTransactionCountByNumber(ctx, blockNum) } // GetTransactionByBlockHashAndIndex returns the transaction identified by hash and index. -func (e *PublicAPI) GetTransactionByBlockHashAndIndex(hash common.Hash, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) { +func (e *PublicAPI) GetTransactionByBlockHashAndIndex(hash common.Hash, idx hexutil.Uint) (_ *rpctypes.RPCTransaction, err error) { + ctx, span := tracer.Start(context.Background(), "eth_getTransactionByBlockHashAndIndex") + defer func() { evmtrace.EndSpanErr(span, err) }() e.logger.Debug("eth_getTransactionByBlockHashAndIndex", "hash", hash.Hex(), "index", idx) - return e.backend.GetTransactionByBlockHashAndIndex(hash, idx) + return e.backend.GetTransactionByBlockHashAndIndex(ctx, hash, idx) } // GetTransactionByBlockNumberAndIndex returns the transaction identified by number and index. -func (e *PublicAPI) GetTransactionByBlockNumberAndIndex(blockNum rpctypes.BlockNumber, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) { +func (e *PublicAPI) GetTransactionByBlockNumberAndIndex(blockNum rpctypes.BlockNumber, idx hexutil.Uint) (_ *rpctypes.RPCTransaction, err error) { + ctx, span := tracer.Start(context.Background(), "eth_getTransactionByBlockNumberAndIndex") + defer func() { evmtrace.EndSpanErr(span, err) }() e.logger.Debug("eth_getTransactionByBlockNumberAndIndex", "number", blockNum, "index", idx) - return e.backend.GetTransactionByBlockNumberAndIndex(blockNum, idx) + return e.backend.GetTransactionByBlockNumberAndIndex(ctx, blockNum, idx) } /////////////////////////////////////////////////////////////////////////////// @@ -228,15 +258,19 @@ func (e *PublicAPI) GetTransactionByBlockNumberAndIndex(blockNum rpctypes.BlockN /////////////////////////////////////////////////////////////////////////////// // SendRawTransaction send a raw Ethereum transaction. -func (e *PublicAPI) SendRawTransaction(data hexutil.Bytes) (common.Hash, error) { +func (e *PublicAPI) SendRawTransaction(data hexutil.Bytes) (_ common.Hash, err error) { + ctx, span := tracer.Start(context.Background(), "eth_sendRawTransaction") + defer func() { evmtrace.EndSpanErr(span, err) }() e.logger.Debug("eth_sendRawTransaction", "length", len(data)) - return e.backend.SendRawTransaction(data) + return e.backend.SendRawTransaction(ctx, data) } // SendTransaction sends an Ethereum transaction. -func (e *PublicAPI) SendTransaction(args evmtypes.TransactionArgs) (common.Hash, error) { +func (e *PublicAPI) SendTransaction(args evmtypes.TransactionArgs) (_ common.Hash, err error) { + ctx, span := tracer.Start(context.Background(), "eth_sendTransaction") + defer func() { evmtrace.EndSpanErr(span, err) }() e.logger.Debug("eth_sendTransaction", "args", args) - return e.backend.SendTransaction(args) + return e.backend.SendTransaction(ctx, args) } /////////////////////////////////////////////////////////////////////////////// @@ -250,30 +284,38 @@ func (e *PublicAPI) Accounts() ([]common.Address, error) { } // GetBalance returns the provided account's balance up to the provided block number. -func (e *PublicAPI) GetBalance(address common.Address, blockNrOrHash rpctypes.BlockNumberOrHash) (*hexutil.Big, error) { +func (e *PublicAPI) GetBalance(address common.Address, blockNrOrHash rpctypes.BlockNumberOrHash) (_ *hexutil.Big, err error) { + ctx, span := tracer.Start(context.Background(), "eth_getBalance") + defer func() { evmtrace.EndSpanErr(span, err) }() e.logger.Debug("eth_getBalance", "address", address.String(), "block number or hash", blockNrOrHash) - return e.backend.GetBalance(address, blockNrOrHash) + return e.backend.GetBalance(ctx, address, blockNrOrHash) } // GetStorageAt returns the contract storage at the given address, block number, and key. -func (e *PublicAPI) GetStorageAt(address common.Address, key string, blockNrOrHash rpctypes.BlockNumberOrHash) (hexutil.Bytes, error) { +func (e *PublicAPI) GetStorageAt(address common.Address, key string, blockNrOrHash rpctypes.BlockNumberOrHash) (_ hexutil.Bytes, err error) { + ctx, span := tracer.Start(context.Background(), "eth_getStorageAt") + defer func() { evmtrace.EndSpanErr(span, err) }() e.logger.Debug("eth_getStorageAt", "address", address.Hex(), "key", key, "block number or hash", blockNrOrHash) - return e.backend.GetStorageAt(address, key, blockNrOrHash) + return e.backend.GetStorageAt(ctx, address, key, blockNrOrHash) } // GetCode returns the contract code at the given address and block number. -func (e *PublicAPI) GetCode(address common.Address, blockNrOrHash rpctypes.BlockNumberOrHash) (hexutil.Bytes, error) { +func (e *PublicAPI) GetCode(address common.Address, blockNrOrHash rpctypes.BlockNumberOrHash) (_ hexutil.Bytes, err error) { + ctx, span := tracer.Start(context.Background(), "eth_getCode") + defer func() { evmtrace.EndSpanErr(span, err) }() e.logger.Debug("eth_getCode", "address", address.Hex(), "block number or hash", blockNrOrHash) - return e.backend.GetCode(address, blockNrOrHash) + return e.backend.GetCode(ctx, address, blockNrOrHash) } // GetProof returns an account object with proof and any storage proofs func (e *PublicAPI) GetProof(address common.Address, storageKeys []string, blockNrOrHash rpctypes.BlockNumberOrHash, -) (*rpctypes.AccountResult, error) { +) (_ *rpctypes.AccountResult, err error) { + ctx, span := tracer.Start(context.Background(), "eth_getProof") + defer func() { evmtrace.EndSpanErr(span, err) }() e.logger.Debug("eth_getProof", "address", address.Hex(), "keys", storageKeys, "block number or hash", blockNrOrHash) - return e.backend.GetProof(address, storageKeys, blockNrOrHash) + return e.backend.GetProof(ctx, address, storageKeys, blockNrOrHash) } /////////////////////////////////////////////////////////////////////////////// @@ -285,14 +327,16 @@ func (e *PublicAPI) Call( args evmtypes.TransactionArgs, blockNrOrHash rpctypes.BlockNumberOrHash, overrides *json.RawMessage, -) (hexutil.Bytes, error) { +) (_ hexutil.Bytes, err error) { + ctx, span := tracer.Start(context.Background(), "eth_call") + defer func() { evmtrace.EndSpanErr(span, err) }() e.logger.Debug("eth_call", "args", args, "block number or hash", blockNrOrHash) - blockNum, err := e.backend.BlockNumberFromComet(blockNrOrHash) + blockNum, err := e.backend.BlockNumberFromComet(ctx, blockNrOrHash) if err != nil { return nil, err } - data, err := e.backend.DoCall(args, blockNum, overrides) + data, err := e.backend.DoCall(ctx, args, blockNum, overrides) if err != nil { return []byte{}, err } @@ -316,34 +360,42 @@ func (e *PublicAPI) ProtocolVersion() hexutil.Uint { } // GasPrice returns the current gas price based on Cosmos EVM's gas price oracle. -func (e *PublicAPI) GasPrice() (*hexutil.Big, error) { +func (e *PublicAPI) GasPrice() (_ *hexutil.Big, err error) { + ctx, span := tracer.Start(context.Background(), "eth_gasPrice") + defer func() { evmtrace.EndSpanErr(span, err) }() e.logger.Debug("eth_gasPrice") - return e.backend.GasPrice() + return e.backend.GasPrice(ctx) } // EstimateGas returns an estimate of gas usage for the given smart contract call. -func (e *PublicAPI) EstimateGas(args evmtypes.TransactionArgs, blockNrOptional *rpctypes.BlockNumber) (hexutil.Uint64, error) { +func (e *PublicAPI) EstimateGas(args evmtypes.TransactionArgs, blockNrOrHash *rpctypes.BlockNumberOrHash, overrides *json.RawMessage) (_ hexutil.Uint64, err error) { + ctx, span := tracer.Start(context.Background(), "eth_estimateGas") + defer func() { evmtrace.EndSpanErr(span, err) }() e.logger.Debug("eth_estimateGas") - return e.backend.EstimateGas(args, blockNrOptional) + return e.backend.EstimateGas(ctx, args, blockNrOrHash, overrides) } func (e *PublicAPI) FeeHistory( blockCount math.HexOrDecimal64, lastBlock rpc.BlockNumber, rewardPercentiles []float64, -) (*rpctypes.FeeHistoryResult, error) { +) (_ *rpctypes.FeeHistoryResult, err error) { + ctx, span := tracer.Start(context.Background(), "eth_feeHistory") + defer func() { evmtrace.EndSpanErr(span, err) }() e.logger.Debug("eth_feeHistory") - return e.backend.FeeHistory(blockCount, lastBlock, rewardPercentiles) + return e.backend.FeeHistory(ctx, blockCount, lastBlock, rewardPercentiles) } // MaxPriorityFeePerGas returns a suggestion for a gas tip cap for dynamic fee transactions. -func (e *PublicAPI) MaxPriorityFeePerGas() (*hexutil.Big, error) { +func (e *PublicAPI) MaxPriorityFeePerGas() (_ *hexutil.Big, err error) { + ctx, span := tracer.Start(context.Background(), "eth_maxPriorityFeePerGas") + defer func() { evmtrace.EndSpanErr(span, err) }() e.logger.Debug("eth_maxPriorityFeePerGas") - head, err := e.backend.CurrentHeader() + head, err := e.backend.CurrentHeader(ctx) if err != nil { return nil, err } - tipcap, err := e.backend.SuggestGasTipCap(head.BaseFee) + tipcap, err := e.backend.SuggestGasTipCap(ctx, head.BaseFee) if err != nil { return nil, err } @@ -351,9 +403,11 @@ func (e *PublicAPI) MaxPriorityFeePerGas() (*hexutil.Big, error) { } // ChainId is the EIP-155 replay-protection chain id for the current ethereum chain config. -func (e *PublicAPI) ChainId() (*hexutil.Big, error) { //nolint +func (e *PublicAPI) ChainId() (_ *hexutil.Big, err error) { + ctx, span := tracer.Start(context.Background(), "eth_chainId") + defer func() { evmtrace.EndSpanErr(span, err) }() e.logger.Debug("eth_chainId") - return e.backend.ChainID() + return e.backend.ChainID(ctx) } /////////////////////////////////////////////////////////////////////////////// @@ -391,9 +445,11 @@ func (e *PublicAPI) GetUncleCountByBlockNumber(_ rpctypes.BlockNumber) hexutil.U // - highestBlock: block number of the highest block header this node has received from peers // - pulledStates: number of state entries processed until now // - knownStates: number of known state entries that still need to be pulled -func (e *PublicAPI) Syncing() (interface{}, error) { +func (e *PublicAPI) Syncing() (_ interface{}, err error) { + ctx, span := tracer.Start(context.Background(), "eth_syncing") + defer func() { evmtrace.EndSpanErr(span, err) }() e.logger.Debug("eth_syncing") - return e.backend.Syncing() + return e.backend.Syncing(ctx) } // Sign signs the provided data using the private key of address via Geth's signature standard. @@ -403,10 +459,12 @@ func (e *PublicAPI) Sign(address common.Address, data hexutil.Bytes) (hexutil.By } // GetTransactionLogs returns the logs given a transaction hash. -func (e *PublicAPI) GetTransactionLogs(txHash common.Hash) ([]*ethtypes.Log, error) { +func (e *PublicAPI) GetTransactionLogs(txHash common.Hash) (_ []*ethtypes.Log, err error) { + ctx, span := tracer.Start(context.Background(), "eth_getTransactionLogs") + defer func() { evmtrace.EndSpanErr(span, err) }() e.logger.Debug("eth_getTransactionLogs", "hash", txHash) - return e.backend.GetTransactionLogs(txHash) + return e.backend.GetTransactionLogs(ctx, txHash) } // SignTypedData signs EIP-712 conformant typed data @@ -418,9 +476,11 @@ func (e *PublicAPI) SignTypedData(address common.Address, typedData apitypes.Typ // FillTransaction fills the defaults (nonce, gas, gasPrice or 1559 fields) // on a given unsigned transaction, and returns it to the caller for further // processing (signing + broadcast). -func (e *PublicAPI) FillTransaction(args evmtypes.TransactionArgs) (*rpctypes.SignTransactionResult, error) { +func (e *PublicAPI) FillTransaction(args evmtypes.TransactionArgs) (_ *rpctypes.SignTransactionResult, err error) { + ctx, span := tracer.Start(context.Background(), "eth_fillTransaction") + defer func() { evmtrace.EndSpanErr(span, err) }() // Set some sanity defaults and terminate on failure - args, err := e.backend.SetTxDefaults(args) + args, err = e.backend.SetTxDefaults(ctx, args) if err != nil { return nil, err } @@ -428,7 +488,8 @@ func (e *PublicAPI) FillTransaction(args evmtypes.TransactionArgs) (*rpctypes.Si // Assemble the transaction and obtain rlp tx := args.ToTransaction(ethtypes.LegacyTxType) - data, err := tx.MarshalBinary() + var data []byte + data, err = tx.MarshalBinary() if err != nil { return nil, err } @@ -441,13 +502,15 @@ func (e *PublicAPI) FillTransaction(args evmtypes.TransactionArgs) (*rpctypes.Si // Resend accepts an existing transaction and a new gas price and limit. It will remove // the given transaction from the pool and reinsert it with the new gas price and limit. -func (e *PublicAPI) Resend(_ context.Context, +func (e *PublicAPI) Resend(ctx context.Context, args evmtypes.TransactionArgs, gasPrice *hexutil.Big, gasLimit *hexutil.Uint64, -) (common.Hash, error) { +) (_ common.Hash, err error) { + ctx, span := tracer.Start(ctx, "eth_resend") + defer func() { evmtrace.EndSpanErr(span, err) }() e.logger.Debug("eth_resend", "args", args) - return e.backend.Resend(args, gasPrice, gasLimit) + return e.backend.Resend(ctx, args, gasPrice, gasLimit) } // CreateAccessList returns the list of addresses and storage keys used by the transaction (except for the @@ -456,8 +519,10 @@ func (e *PublicAPI) CreateAccessList( args evmtypes.TransactionArgs, blockNrOrHash rpctypes.BlockNumberOrHash, overrides *json.RawMessage, -) (*rpctypes.AccessListResult, error) { - res, err := e.backend.CreateAccessList(args, blockNrOrHash, overrides) +) (_ *rpctypes.AccessListResult, err error) { + ctx, span := tracer.Start(context.Background(), "eth_createAccessList") + defer func() { evmtrace.EndSpanErr(span, err) }() + res, err := e.backend.CreateAccessList(ctx, args, blockNrOrHash, overrides) if err != nil { return nil, err } diff --git a/rpc/namespaces/ethereum/eth/filters/api.go b/rpc/namespaces/ethereum/eth/filters/api.go index 987992e4..2d9fcf61 100644 --- a/rpc/namespaces/ethereum/eth/filters/api.go +++ b/rpc/namespaces/ethereum/eth/filters/api.go @@ -11,13 +11,16 @@ import ( "github.com/ethereum/go-ethereum/eth/filters" "github.com/ethereum/go-ethereum/rpc" "github.com/pkg/errors" + "go.opentelemetry.io/otel" coretypes "github.com/cometbft/cometbft/rpc/core/types" "github.com/cosmos/evm/rpc/stream" "github.com/cosmos/evm/rpc/types" + evmsrvconfig "github.com/cosmos/evm/server/config" + evmtrace "github.com/cosmos/evm/trace" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" "github.com/cosmos/cosmos-sdk/client" ) @@ -25,6 +28,8 @@ import ( var ( errInvalidBlockRange = errors.New("invalid block range params") errPendingLogsUnsupported = errors.New("pending logs are not supported") + + tracer = otel.Tracer("evm/rpc/namespaces/ethereum/eth/filters") ) // FilterAPI gathers @@ -40,18 +45,17 @@ type FilterAPI interface { // Backend defines the methods requided by the PublicFilterAPI backend type Backend interface { - GetBlockByNumber(blockNum types.BlockNumber, fullTx bool) (map[string]interface{}, error) - HeaderByNumber(blockNum types.BlockNumber) (*ethtypes.Header, error) - HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error) - CometBlockByHash(hash common.Hash) (*coretypes.ResultBlock, error) - CometBlockResultByNumber(height *int64) (*coretypes.ResultBlockResults, error) - GetLogs(blockHash common.Hash) ([][]*ethtypes.Log, error) - GetLogsByHeight(*int64) ([][]*ethtypes.Log, error) - BlockBloomFromCometBlock(blockRes *coretypes.ResultBlockResults) (ethtypes.Bloom, error) + GetBlockByNumber(ctx context.Context, blockNum types.BlockNumber, fullTx bool) (map[string]interface{}, error) + HeaderByNumber(ctx context.Context, blockNum types.BlockNumber) (*ethtypes.Header, error) + HeaderByHash(ctx context.Context, blockHash common.Hash) (*ethtypes.Header, error) + CometBlockByHash(ctx context.Context, hash common.Hash) (*coretypes.ResultBlock, error) + CometBlockResultByNumber(ctx context.Context, height *int64) (*coretypes.ResultBlockResults, error) + GetLogs(ctx context.Context, blockHash common.Hash) ([][]*ethtypes.Log, error) + GetLogsByHeight(ctx context.Context, height *int64) ([][]*ethtypes.Log, error) + BlockBloomFromCometBlock(ctx context.Context, blockRes *coretypes.ResultBlockResults) (ethtypes.Bloom, error) BloomStatus() (uint64, uint64) - RPCFilterCap() int32 RPCLogsCap() int32 RPCBlockRangeCap() int32 } @@ -59,6 +63,8 @@ type Backend interface { // consider a filter inactive if it has not been polled for within deadline const defaultDeadline = 5 * time.Minute +const defaultCleanupInterval = 30 * time.Second + // filter is a helper struct that holds meta information over the filter type // and associated subscription in the event system. type filter struct { @@ -78,6 +84,11 @@ type PublicFilterAPI struct { filtersMu sync.Mutex filters map[rpc.ID]*filter deadline time.Duration + + cleanupInterval time.Duration + + stop chan struct{} + stopOnce sync.Once } // NewPublicAPI returns a new PublicFilterAPI instance. @@ -87,8 +98,20 @@ func NewPublicAPI( stream *stream.RPCStream, backend Backend, ) *PublicFilterAPI { - api := NewPublicAPIWithDeadline(logger, clientCtx, stream, backend, defaultDeadline) - return api + deadline := defaultDeadline + cleanupInterval := defaultCleanupInterval + + if cfgBackend, ok := backend.(interface{ GetConfig() evmsrvconfig.Config }); ok { + jsonRPC := cfgBackend.GetConfig().JSONRPC + if jsonRPC.FilterTimeout > 0 { + deadline = jsonRPC.FilterTimeout + } + if jsonRPC.FilterCleanupInterval > 0 { + cleanupInterval = jsonRPC.FilterCleanupInterval + } + } + + return newPublicAPIWithOptions(logger, clientCtx, stream, backend, deadline, cleanupInterval) } // NewPublicAPIWithDeadline returns a new PublicFilterAPI instance with the given deadline. @@ -98,15 +121,28 @@ func NewPublicAPIWithDeadline( stream *stream.RPCStream, backend Backend, deadline time.Duration, +) *PublicFilterAPI { + return newPublicAPIWithOptions(logger, clientCtx, stream, backend, deadline, defaultCleanupInterval) +} + +func newPublicAPIWithOptions( + logger log.Logger, + clientCtx client.Context, + stream *stream.RPCStream, + backend Backend, + deadline time.Duration, + cleanupInterval time.Duration, ) *PublicFilterAPI { logger = logger.With("api", "filter") api := &PublicFilterAPI{ - logger: logger, - clientCtx: clientCtx, - backend: backend, - filters: make(map[rpc.ID]*filter), - events: stream, - deadline: deadline, + logger: logger, + clientCtx: clientCtx, + backend: backend, + filters: make(map[rpc.ID]*filter), + events: stream, + deadline: deadline, + cleanupInterval: cleanupInterval, + stop: make(chan struct{}), } go api.timeoutLoop() @@ -114,20 +150,31 @@ func NewPublicAPIWithDeadline( return api } -// timeoutLoop runs every 5 minutes and deletes filters that have not been recently used. -// Tt is started when the api is created. +// Stop terminates the filter timeout goroutine. Safe to call multiple times. +func (api *PublicFilterAPI) Stop() { + api.stopOnce.Do(func() { + close(api.stop) + }) +} + +// timeoutLoop runs every cleanupInterval and deletes filters that have not been recently used. +// It is started when the api is created. func (api *PublicFilterAPI) timeoutLoop() { - ticker := time.NewTicker(api.deadline) + ticker := time.NewTicker(api.cleanupInterval) defer ticker.Stop() for { - <-ticker.C + select { + case <-api.stop: + return + case <-ticker.C: + } api.filtersMu.Lock() // #nosec G705 for id, f := range api.filters { select { case <-f.deadline.C: - delete(api.filters, id) + api.deleteFilterLocked(id) default: continue } @@ -136,6 +183,36 @@ func (api *PublicFilterAPI) timeoutLoop() { } } +func stopAndDrainTimer(timer *time.Timer) { + if timer == nil { + return + } + if !timer.Stop() { + select { + case <-timer.C: + default: + } + } +} + +func (api *PublicFilterAPI) resetFilterTimer(timer *time.Timer) { + if timer == nil { + return + } + stopAndDrainTimer(timer) + timer.Reset(api.deadline) +} + +func (api *PublicFilterAPI) deleteFilterLocked(id rpc.ID) bool { + f, found := api.filters[id] + if !found { + return false + } + delete(api.filters, id) + stopAndDrainTimer(f.deadline) + return true +} + // NewPendingTransactionFilter creates a filter that fetches pending transaction hashes // as transactions enter the pending state. // @@ -147,10 +224,6 @@ func (api *PublicFilterAPI) NewPendingTransactionFilter() rpc.ID { api.filtersMu.Lock() defer api.filtersMu.Unlock() - if len(api.filters) >= int(api.backend.RPCFilterCap()) { - return rpc.ID("error creating pending tx filter: max limit reached") - } - id := rpc.NewID() _, offset := api.events.PendingTxStream().ReadNonBlocking(-1) api.filters[id] = &filter{ @@ -170,10 +243,6 @@ func (api *PublicFilterAPI) NewBlockFilter() rpc.ID { api.filtersMu.Lock() defer api.filtersMu.Unlock() - if len(api.filters) >= int(api.backend.RPCFilterCap()) { - return rpc.ID("error creating block filter: max limit reached") - } - id := rpc.NewID() _, offset := api.events.HeaderStream().ReadNonBlocking(-1) api.filters[id] = &filter{ @@ -202,10 +271,6 @@ func (api *PublicFilterAPI) NewFilter(criteria filters.FilterCriteria) (rpc.ID, api.filtersMu.Lock() defer api.filtersMu.Unlock() - if len(api.filters) >= int(api.backend.RPCFilterCap()) { - return "", fmt.Errorf("error creating filter: max limit reached") - } - id := rpc.NewID() _, offset := api.events.LogStream().ReadNonBlocking(-1) api.filters[id] = &filter{ @@ -221,7 +286,9 @@ func (api *PublicFilterAPI) NewFilter(criteria filters.FilterCriteria) (rpc.ID, // GetLogs returns logs matching the given argument that are stored within the state. // // https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getlogs -func (api *PublicFilterAPI) GetLogs(ctx context.Context, crit filters.FilterCriteria) ([]*ethtypes.Log, error) { +func (api *PublicFilterAPI) GetLogs(ctx context.Context, crit filters.FilterCriteria) (_ []*ethtypes.Log, err error) { + ctx, span := tracer.Start(ctx, "GetLogs") + defer func() { evmtrace.EndSpanErr(span, err) }() var filter *Filter if crit.BlockHash != nil { // Block filter requested, construct a single-shot filter @@ -259,10 +326,7 @@ func (api *PublicFilterAPI) GetLogs(ctx context.Context, crit filters.FilterCrit // https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_uninstallfilter func (api *PublicFilterAPI) UninstallFilter(id rpc.ID) bool { api.filtersMu.Lock() - _, found := api.filters[id] - if found { - delete(api.filters, id) - } + found := api.deleteFilterLocked(id) api.filtersMu.Unlock() return found @@ -272,7 +336,9 @@ func (api *PublicFilterAPI) UninstallFilter(id rpc.ID) bool { // If the filter could not be found an empty array of logs is returned. // // https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getfilterlogs -func (api *PublicFilterAPI) GetFilterLogs(ctx context.Context, id rpc.ID) ([]*ethtypes.Log, error) { +func (api *PublicFilterAPI) GetFilterLogs(ctx context.Context, id rpc.ID) (_ []*ethtypes.Log, err error) { + ctx, span := tracer.Start(ctx, "GetFilterLogs") + defer func() { evmtrace.EndSpanErr(span, err) }() api.filtersMu.Lock() f, found := api.filters[id] api.filtersMu.Unlock() @@ -326,12 +392,7 @@ func (api *PublicFilterAPI) GetFilterChanges(id rpc.ID) (interface{}, error) { return nil, fmt.Errorf("filter %s not found", id) } - if !f.deadline.Stop() { - // timer expired but filter is not yet removed in timeout loop - // receive timer value and reset timer - <-f.deadline.C - } - f.deadline.Reset(api.deadline) + api.resetFilterTimer(f.deadline) switch f.typ { case filters.PendingTransactionsSubscription: diff --git a/rpc/namespaces/ethereum/eth/filters/api_test.go b/rpc/namespaces/ethereum/eth/filters/api_test.go index be15dc76..ee45c6dd 100644 --- a/rpc/namespaces/ethereum/eth/filters/api_test.go +++ b/rpc/namespaces/ethereum/eth/filters/api_test.go @@ -1,6 +1,7 @@ package filters import ( + "net/http/httptest" "sync" "testing" "time" @@ -8,13 +9,75 @@ import ( "github.com/ethereum/go-ethereum/eth/filters" "github.com/ethereum/go-ethereum/rpc" "github.com/stretchr/testify/require" + + filtermocks "github.com/cosmos/evm/rpc/namespaces/ethereum/eth/filters/mocks" + "github.com/cosmos/evm/rpc/stream" + + "cosmossdk.io/log/v2" + + "github.com/cosmos/cosmos-sdk/client" ) -func TestTimeoutLoop_PanicOnNilCancel(t *testing.T) { +func newFilterAPITestSubject(t *testing.T, backend Backend) *PublicFilterAPI { + t.Helper() + api := NewPublicAPIWithDeadline( + log.NewNopLogger(), + client.Context{}, + stream.NewRPCStreams(nil, log.NewNopLogger(), nil), + backend, + time.Minute, + ) + t.Cleanup(api.Stop) + return api +} + +func newFilterAPITestSubjectWithOptions(t *testing.T, backend Backend, deadline, cleanupInterval time.Duration) *PublicFilterAPI { + t.Helper() + api := newPublicAPIWithOptions( + log.NewNopLogger(), + client.Context{}, + stream.NewRPCStreams(nil, log.NewNopLogger(), nil), + backend, + deadline, + cleanupInterval, + ) + t.Cleanup(api.Stop) + return api +} + +func newHTTPRPCClientForFilterAPI(t *testing.T, api *PublicFilterAPI) *rpc.Client { + t.Helper() + + rpcSrv := rpc.NewServer() + err := rpcSrv.RegisterName("eth", api) + require.NoError(t, err) + t.Cleanup(rpcSrv.Stop) + + ts := httptest.NewServer(rpcSrv) + t.Cleanup(ts.Close) + + rpcClient, err := rpc.Dial(ts.URL) + require.NoError(t, err) + t.Cleanup(rpcClient.Close) + + return rpcClient +} + +func requireNewPendingTxFilterSuccess(t *testing.T, rpcClient *rpc.Client) rpc.ID { + t.Helper() + var id rpc.ID + require.NoError(t, rpcClient.Call(&id, "eth_newPendingTransactionFilter")) + require.NotEmpty(t, id) + return id +} + +func TestTimeoutLoop_StopHalts(t *testing.T) { api := &PublicFilterAPI{ - filters: make(map[rpc.ID]*filter), - filtersMu: sync.Mutex{}, - deadline: 10 * time.Millisecond, + filters: make(map[rpc.ID]*filter), + filtersMu: sync.Mutex{}, + deadline: 10 * time.Millisecond, + cleanupInterval: 10 * time.Millisecond, + stop: make(chan struct{}), } api.filters[rpc.NewID()] = &filter{ typ: filters.BlocksSubscription, @@ -22,19 +85,102 @@ func TestTimeoutLoop_PanicOnNilCancel(t *testing.T) { } done := make(chan struct{}) go func() { - defer func() { - if r := recover(); r == nil { - t.Errorf("cancel panic") - } - close(done) - }() api.timeoutLoop() + close(done) }() - panicked := false + api.Stop() select { case <-done: - panicked = true - case <-time.After(100 * time.Millisecond): + case <-time.After(200 * time.Millisecond): + t.Fatalf("timeoutLoop did not exit after Stop") + } +} + +func TestNewPendingTransactionFilter_HTTPContext(t *testing.T) { + backend := filtermocks.NewBackend(t) + + api := newFilterAPITestSubject(t, backend) + rpcClient := newHTTPRPCClientForFilterAPI(t, api) + id := requireNewPendingTxFilterSuccess(t, rpcClient) + require.NotEmpty(t, id) +} + +func TestNewPendingTransactionFilter_NoCapExhaustion(t *testing.T) { + backend := filtermocks.NewBackend(t) + + api := newFilterAPITestSubject(t, backend) + rpcClient := newHTTPRPCClientForFilterAPI(t, api) + + // Create more filters than the old default cap (200) to confirm the + // node no longer refuses filter creation — matches upstream geth, + // which relies on the idle-deadline sweep rather than a fixed cap. + for i := 0; i < 300; i++ { + requireNewPendingTxFilterSuccess(t, rpcClient) + } + require.Equal(t, 300, func() int { + api.filtersMu.Lock() + defer api.filtersMu.Unlock() + return len(api.filters) + }()) +} + +func TestFilter_ExpiresAfterDeadline(t *testing.T) { + backend := filtermocks.NewBackend(t) + + api := newFilterAPITestSubjectWithOptions(t, backend, 20*time.Millisecond, 5*time.Millisecond) + rpcClient := newHTTPRPCClientForFilterAPI(t, api) + requireNewPendingTxFilterSuccess(t, rpcClient) + + require.Eventually(t, func() bool { + api.filtersMu.Lock() + defer api.filtersMu.Unlock() + return len(api.filters) == 0 + }, 400*time.Millisecond, 10*time.Millisecond) +} + +func TestFilter_PollingResetsDeadline(t *testing.T) { + backend := filtermocks.NewBackend(t) + + deadline := 500 * time.Millisecond + cleanup := 25 * time.Millisecond + api := newFilterAPITestSubjectWithOptions(t, backend, deadline, cleanup) + rpcClient := newHTTPRPCClientForFilterAPI(t, api) + id := requireNewPendingTxFilterSuccess(t, rpcClient) + + filterPresent := func() bool { + api.filtersMu.Lock() + defer api.filtersMu.Unlock() + _, ok := api.filters[id] + return ok } - require.False(t, panicked) + + // Poll faster than deadline, each call must reset the timer + const pollInterval = 50 * time.Millisecond + pollEnd := time.Now().Add(3 * deadline) + for time.Now().Before(pollEnd) { + var hashes []string + require.NoError(t, rpcClient.Call(&hashes, "eth_getFilterChanges", id)) + require.True(t, filterPresent(), "filter reaped while still being polled") + time.Sleep(pollInterval) + } + + // After polling stops, filter is reaped within deadline+cleanup + require.Eventually(t, func() bool { + return !filterPresent() + }, deadline+cleanup+2*time.Second, 25*time.Millisecond) +} + +func TestDeleteFilterLocked_RemovesAndReportsMissing(t *testing.T) { + api := &PublicFilterAPI{ + filters: make(map[rpc.ID]*filter), + } + + id := rpc.NewID() + api.filters[id] = &filter{deadline: time.NewTimer(time.Minute)} + + require.True(t, api.deleteFilterLocked(id)) + _, exists := api.filters[id] + require.False(t, exists) + + require.False(t, api.deleteFilterLocked(rpc.NewID())) } diff --git a/rpc/namespaces/ethereum/eth/filters/filters.go b/rpc/namespaces/ethereum/eth/filters/filters.go index 05066f08..6290087b 100644 --- a/rpc/namespaces/ethereum/eth/filters/filters.go +++ b/rpc/namespaces/ethereum/eth/filters/filters.go @@ -17,8 +17,9 @@ import ( "github.com/cosmos/evm/rpc/backend" "github.com/cosmos/evm/rpc/types" + evmtrace "github.com/cosmos/evm/trace" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" ) // BloomIV represents the bit indexes and value inside the bloom filter that belong @@ -90,25 +91,27 @@ func newFilter(logger log.Logger, backend Backend, criteria filters.FilterCriter // Logs searches the blockchain for matching log entries, returning all from the // first block that contains matches, updating the start of the filter accordingly. -func (f *Filter) Logs(_ context.Context, logLimit int, blockLimit int64) (logs []*ethtypes.Log, err error) { +func (f *Filter) Logs(ctx context.Context, logLimit int, blockLimit int64) (logs []*ethtypes.Log, err error) { + ctx, span := tracer.Start(ctx, "Filter.Logs") + defer func() { evmtrace.EndSpanErr(span, err) }() if blockLimit == 0 { return nil, nil } // If we're doing singleton block filtering, execute and return if f.criteria.BlockHash != nil && *f.criteria.BlockHash != (common.Hash{}) { - resBlock, err := f.backend.CometBlockByHash(*f.criteria.BlockHash) + resBlock, err := f.backend.CometBlockByHash(ctx, *f.criteria.BlockHash) if err != nil { return nil, fmt.Errorf("failed to fetch header by hash %s: %w", f.criteria.BlockHash, err) } - blockRes, err := f.backend.CometBlockResultByNumber(&resBlock.Block.Height) + blockRes, err := f.backend.CometBlockResultByNumber(ctx, &resBlock.Block.Height) if err != nil { f.logger.Debug("failed to fetch block result from CometBFT", "height", resBlock.Block.Height, "error", err.Error()) return nil, err } - bloom, err := f.backend.BlockBloomFromCometBlock(blockRes) + bloom, err := f.backend.BlockBloomFromCometBlock(ctx, blockRes) if err != nil { return nil, err } @@ -122,7 +125,7 @@ func (f *Filter) Logs(_ context.Context, logLimit int, blockLimit int64) (logs [ } // Figure out the limits of the filter range - header, err := f.backend.HeaderByNumber(types.EthLatestBlockNumber) + header, err := f.backend.HeaderByNumber(ctx, types.EthLatestBlockNumber) if err != nil { return nil, fmt.Errorf("failed to fetch header by number (latest): %w", err) } @@ -171,13 +174,13 @@ func (f *Filter) Logs(_ context.Context, logLimit int, blockLimit int64) (logs [ for height := from; height <= to; height++ { h := int64(height) //#nosec G115 - blockRes, err := f.backend.CometBlockResultByNumber(&h) + blockRes, err := f.backend.CometBlockResultByNumber(ctx, &h) if err != nil { f.logger.Debug("failed to fetch block result from CometBFT", "height", height, "error", err.Error()) return nil, fmt.Errorf("failed to fetch block result from CometBFT: %w", err) } - bloom, err := f.backend.BlockBloomFromCometBlock(blockRes) + bloom, err := f.backend.BlockBloomFromCometBlock(ctx, blockRes) if err != nil { return nil, fmt.Errorf("failed to query block bloom filter from block results: %w", err) } diff --git a/rpc/namespaces/ethereum/eth/filters/filters_test.go b/rpc/namespaces/ethereum/eth/filters/filters_test.go index f92c020e..bb08655c 100644 --- a/rpc/namespaces/ethereum/eth/filters/filters_test.go +++ b/rpc/namespaces/ethereum/eth/filters/filters_test.go @@ -18,65 +18,9 @@ import ( filtermocks "github.com/cosmos/evm/rpc/namespaces/ethereum/eth/filters/mocks" rpctypes "github.com/cosmos/evm/rpc/types" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" ) -type MockBackend struct { - mock.Mock -} - -func (m *MockBackend) GetBlockByNumber(blockNum rpctypes.BlockNumber, fullTx bool) (map[string]interface{}, error) { - panic("implement me") -} - -func (m *MockBackend) HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error) { - panic("implement me") -} - -func (m *MockBackend) GetLogs(blockHash common.Hash) ([][]*ethtypes.Log, error) { - panic("implement me") -} - -func (m *MockBackend) GetLogsByHeight(i *int64) ([][]*ethtypes.Log, error) { - panic("implement me") -} - -func (m *MockBackend) BloomStatus() (uint64, uint64) { - panic("implement me") -} - -func (m *MockBackend) RPCFilterCap() int32 { - panic("implement me") -} - -func (m *MockBackend) RPCLogsCap() int32 { - panic("implement me") -} - -func (m *MockBackend) RPCBlockRangeCap() int32 { - panic("implement me") -} - -func (m *MockBackend) CometBlockByHash(hash common.Hash) (*cmtrpctypes.ResultBlock, error) { - args := m.Called(hash) - return args.Get(0).(*cmtrpctypes.ResultBlock), args.Error(1) -} - -func (m *MockBackend) CometBlockResultByNumber(height *int64) (*cmtrpctypes.ResultBlockResults, error) { - args := m.Called(height) - return args.Get(0).(*cmtrpctypes.ResultBlockResults), args.Error(1) -} - -func (m *MockBackend) BlockBloomFromCometBlock(blockRes *cmtrpctypes.ResultBlockResults) (ethtypes.Bloom, error) { - args := m.Called(blockRes) - return args.Get(0).(ethtypes.Bloom), args.Error(1) -} - -func (m *MockBackend) HeaderByNumber(blockNum rpctypes.BlockNumber) (*ethtypes.Header, error) { - args := m.Called(blockNum) - return args.Get(0).(*ethtypes.Header), args.Error(1) -} - func TestLogs(t *testing.T) { blockHeight := int64(100) fakeHeader := ðtypes.Header{Number: big.NewInt(blockHeight)} @@ -88,7 +32,7 @@ func TestLogs(t *testing.T) { tests := []struct { name string errorStep string - prepare func() *MockBackend + prepare func() *filtermocks.Backend criteria filters.FilterCriteria expectErr bool expectMsg string @@ -96,9 +40,9 @@ func TestLogs(t *testing.T) { { name: "HeaderByNumber returns error", errorStep: "HeaderByNumber", - prepare: func() *MockBackend { - backend := &MockBackend{} - backend.On("HeaderByNumber", mock.Anything).Return((*ethtypes.Header)(nil), errors.New("header error")) + prepare: func() *filtermocks.Backend { + backend := &filtermocks.Backend{} + backend.EXPECT().HeaderByNumber(mock.Anything, mock.Anything).Return((*ethtypes.Header)(nil), errors.New("header error")) return backend }, criteria: filters.FilterCriteria{ @@ -111,10 +55,10 @@ func TestLogs(t *testing.T) { { name: "CometBlockResultByNumber returns error", errorStep: "CometBlockResultByNumber", - prepare: func() *MockBackend { - backend := &MockBackend{} - backend.On("HeaderByNumber", mock.Anything).Return(fakeHeader, nil) - backend.On("CometBlockResultByNumber", &blockHeight).Return((*cmtrpctypes.ResultBlockResults)(nil), errors.New("block result error")) + prepare: func() *filtermocks.Backend { + backend := &filtermocks.Backend{} + backend.EXPECT().HeaderByNumber(mock.Anything, mock.Anything).Return(fakeHeader, nil) + backend.EXPECT().CometBlockResultByNumber(mock.Anything, &blockHeight).Return((*cmtrpctypes.ResultBlockResults)(nil), errors.New("block result error")) return backend }, criteria: filters.FilterCriteria{ @@ -127,11 +71,11 @@ func TestLogs(t *testing.T) { { name: "BlockBloom returns error", errorStep: "BlockBloom", - prepare: func() *MockBackend { - backend := &MockBackend{} - backend.On("HeaderByNumber", mock.Anything).Return(fakeHeader, nil) - backend.On("CometBlockResultByNumber", &blockHeight).Return(fakeBlockRes, nil) - backend.On("BlockBloomFromCometBlock", fakeBlockRes).Return(ethtypes.Bloom{}, errors.New("bloom error")) + prepare: func() *filtermocks.Backend { + backend := &filtermocks.Backend{} + backend.EXPECT().HeaderByNumber(mock.Anything, mock.Anything).Return(fakeHeader, nil) + backend.EXPECT().CometBlockResultByNumber(mock.Anything, &blockHeight).Return(fakeBlockRes, nil) + backend.EXPECT().BlockBloomFromCometBlock(mock.Anything, fakeBlockRes).Return(ethtypes.Bloom{}, errors.New("bloom error")) return backend }, criteria: filters.FilterCriteria{ @@ -144,11 +88,11 @@ func TestLogs(t *testing.T) { { name: "Single block by BlockHash", errorStep: "none", - prepare: func() *MockBackend { - backend := &MockBackend{} - backend.On("CometBlockByHash", blockHash).Return(fakeBlock, nil) - backend.On("CometBlockResultByNumber", &blockHeight).Return(fakeBlockRes, nil) - backend.On("BlockBloomFromCometBlock", fakeBlockRes).Return(fakeBloom, nil) + prepare: func() *filtermocks.Backend { + backend := &filtermocks.Backend{} + backend.EXPECT().CometBlockByHash(mock.Anything, blockHash).Return(fakeBlock, nil) + backend.EXPECT().CometBlockResultByNumber(mock.Anything, &blockHeight).Return(fakeBlockRes, nil) + backend.EXPECT().BlockBloomFromCometBlock(mock.Anything, fakeBlockRes).Return(fakeBloom, nil) return backend }, criteria: filters.FilterCriteria{ @@ -198,7 +142,7 @@ func TestFilter(t *testing.T) { name: "invalid block range returns error", filter: filters.FilterCriteria{FromBlock: big.NewInt(100), ToBlock: big.NewInt(110)}, expectations: func(b *filtermocks.Backend) { - b.EXPECT().HeaderByNumber(rpctypes.EthLatestBlockNumber).Return(ðtypes.Header{Number: big.NewInt(5)}, nil) + b.EXPECT().HeaderByNumber(mock.Anything, rpctypes.EthLatestBlockNumber).Return(ðtypes.Header{Number: big.NewInt(5)}, nil) }, expErr: "invalid block range params", }, diff --git a/rpc/namespaces/ethereum/eth/filters/mocks/Backend.go b/rpc/namespaces/ethereum/eth/filters/mocks/Backend.go index e7e47350..4d3018bd 100644 --- a/rpc/namespaces/ethereum/eth/filters/mocks/Backend.go +++ b/rpc/namespaces/ethereum/eth/filters/mocks/Backend.go @@ -3,9 +3,12 @@ package mocks import ( - coretypes "github.com/cometbft/cometbft/rpc/core/types" + context "context" + common "github.com/ethereum/go-ethereum/common" + coretypes "github.com/cometbft/cometbft/rpc/core/types" + mock "github.com/stretchr/testify/mock" rpctypes "github.com/cosmos/evm/rpc/types" @@ -26,9 +29,9 @@ func (_m *Backend) EXPECT() *Backend_Expecter { return &Backend_Expecter{mock: &_m.Mock} } -// BlockBloomFromCometBlock provides a mock function with given fields: blockRes -func (_m *Backend) BlockBloomFromCometBlock(blockRes *coretypes.ResultBlockResults) (types.Bloom, error) { - ret := _m.Called(blockRes) +// BlockBloomFromCometBlock provides a mock function with given fields: ctx, blockRes +func (_m *Backend) BlockBloomFromCometBlock(ctx context.Context, blockRes *coretypes.ResultBlockResults) (types.Bloom, error) { + ret := _m.Called(ctx, blockRes) if len(ret) == 0 { panic("no return value specified for BlockBloomFromCometBlock") @@ -36,19 +39,19 @@ func (_m *Backend) BlockBloomFromCometBlock(blockRes *coretypes.ResultBlockResul var r0 types.Bloom var r1 error - if rf, ok := ret.Get(0).(func(*coretypes.ResultBlockResults) (types.Bloom, error)); ok { - return rf(blockRes) + if rf, ok := ret.Get(0).(func(context.Context, *coretypes.ResultBlockResults) (types.Bloom, error)); ok { + return rf(ctx, blockRes) } - if rf, ok := ret.Get(0).(func(*coretypes.ResultBlockResults) types.Bloom); ok { - r0 = rf(blockRes) + if rf, ok := ret.Get(0).(func(context.Context, *coretypes.ResultBlockResults) types.Bloom); ok { + r0 = rf(ctx, blockRes) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(types.Bloom) } } - if rf, ok := ret.Get(1).(func(*coretypes.ResultBlockResults) error); ok { - r1 = rf(blockRes) + if rf, ok := ret.Get(1).(func(context.Context, *coretypes.ResultBlockResults) error); ok { + r1 = rf(ctx, blockRes) } else { r1 = ret.Error(1) } @@ -62,14 +65,15 @@ type Backend_BlockBloomFromCometBlock_Call struct { } // BlockBloomFromCometBlock is a helper method to define mock.On call +// - ctx context.Context // - blockRes *coretypes.ResultBlockResults -func (_e *Backend_Expecter) BlockBloomFromCometBlock(blockRes interface{}) *Backend_BlockBloomFromCometBlock_Call { - return &Backend_BlockBloomFromCometBlock_Call{Call: _e.mock.On("BlockBloomFromCometBlock", blockRes)} +func (_e *Backend_Expecter) BlockBloomFromCometBlock(ctx interface{}, blockRes interface{}) *Backend_BlockBloomFromCometBlock_Call { + return &Backend_BlockBloomFromCometBlock_Call{Call: _e.mock.On("BlockBloomFromCometBlock", ctx, blockRes)} } -func (_c *Backend_BlockBloomFromCometBlock_Call) Run(run func(blockRes *coretypes.ResultBlockResults)) *Backend_BlockBloomFromCometBlock_Call { +func (_c *Backend_BlockBloomFromCometBlock_Call) Run(run func(ctx context.Context, blockRes *coretypes.ResultBlockResults)) *Backend_BlockBloomFromCometBlock_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*coretypes.ResultBlockResults)) + run(args[0].(context.Context), args[1].(*coretypes.ResultBlockResults)) }) return _c } @@ -79,7 +83,7 @@ func (_c *Backend_BlockBloomFromCometBlock_Call) Return(_a0 types.Bloom, _a1 err return _c } -func (_c *Backend_BlockBloomFromCometBlock_Call) RunAndReturn(run func(*coretypes.ResultBlockResults) (types.Bloom, error)) *Backend_BlockBloomFromCometBlock_Call { +func (_c *Backend_BlockBloomFromCometBlock_Call) RunAndReturn(run func(context.Context, *coretypes.ResultBlockResults) (types.Bloom, error)) *Backend_BlockBloomFromCometBlock_Call { _c.Call.Return(run) return _c } @@ -139,9 +143,9 @@ func (_c *Backend_BloomStatus_Call) RunAndReturn(run func() (uint64, uint64)) *B return _c } -// CometBlockByHash provides a mock function with given fields: hash -func (_m *Backend) CometBlockByHash(hash common.Hash) (*coretypes.ResultBlock, error) { - ret := _m.Called(hash) +// CometBlockByHash provides a mock function with given fields: ctx, hash +func (_m *Backend) CometBlockByHash(ctx context.Context, hash common.Hash) (*coretypes.ResultBlock, error) { + ret := _m.Called(ctx, hash) if len(ret) == 0 { panic("no return value specified for CometBlockByHash") @@ -149,19 +153,19 @@ func (_m *Backend) CometBlockByHash(hash common.Hash) (*coretypes.ResultBlock, e var r0 *coretypes.ResultBlock var r1 error - if rf, ok := ret.Get(0).(func(common.Hash) (*coretypes.ResultBlock, error)); ok { - return rf(hash) + if rf, ok := ret.Get(0).(func(context.Context, common.Hash) (*coretypes.ResultBlock, error)); ok { + return rf(ctx, hash) } - if rf, ok := ret.Get(0).(func(common.Hash) *coretypes.ResultBlock); ok { - r0 = rf(hash) + if rf, ok := ret.Get(0).(func(context.Context, common.Hash) *coretypes.ResultBlock); ok { + r0 = rf(ctx, hash) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*coretypes.ResultBlock) } } - if rf, ok := ret.Get(1).(func(common.Hash) error); ok { - r1 = rf(hash) + if rf, ok := ret.Get(1).(func(context.Context, common.Hash) error); ok { + r1 = rf(ctx, hash) } else { r1 = ret.Error(1) } @@ -175,14 +179,15 @@ type Backend_CometBlockByHash_Call struct { } // CometBlockByHash is a helper method to define mock.On call +// - ctx context.Context // - hash common.Hash -func (_e *Backend_Expecter) CometBlockByHash(hash interface{}) *Backend_CometBlockByHash_Call { - return &Backend_CometBlockByHash_Call{Call: _e.mock.On("CometBlockByHash", hash)} +func (_e *Backend_Expecter) CometBlockByHash(ctx interface{}, hash interface{}) *Backend_CometBlockByHash_Call { + return &Backend_CometBlockByHash_Call{Call: _e.mock.On("CometBlockByHash", ctx, hash)} } -func (_c *Backend_CometBlockByHash_Call) Run(run func(hash common.Hash)) *Backend_CometBlockByHash_Call { +func (_c *Backend_CometBlockByHash_Call) Run(run func(ctx context.Context, hash common.Hash)) *Backend_CometBlockByHash_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(common.Hash)) + run(args[0].(context.Context), args[1].(common.Hash)) }) return _c } @@ -192,14 +197,14 @@ func (_c *Backend_CometBlockByHash_Call) Return(_a0 *coretypes.ResultBlock, _a1 return _c } -func (_c *Backend_CometBlockByHash_Call) RunAndReturn(run func(common.Hash) (*coretypes.ResultBlock, error)) *Backend_CometBlockByHash_Call { +func (_c *Backend_CometBlockByHash_Call) RunAndReturn(run func(context.Context, common.Hash) (*coretypes.ResultBlock, error)) *Backend_CometBlockByHash_Call { _c.Call.Return(run) return _c } -// CometBlockResultByNumber provides a mock function with given fields: height -func (_m *Backend) CometBlockResultByNumber(height *int64) (*coretypes.ResultBlockResults, error) { - ret := _m.Called(height) +// CometBlockResultByNumber provides a mock function with given fields: ctx, height +func (_m *Backend) CometBlockResultByNumber(ctx context.Context, height *int64) (*coretypes.ResultBlockResults, error) { + ret := _m.Called(ctx, height) if len(ret) == 0 { panic("no return value specified for CometBlockResultByNumber") @@ -207,19 +212,19 @@ func (_m *Backend) CometBlockResultByNumber(height *int64) (*coretypes.ResultBlo var r0 *coretypes.ResultBlockResults var r1 error - if rf, ok := ret.Get(0).(func(*int64) (*coretypes.ResultBlockResults, error)); ok { - return rf(height) + if rf, ok := ret.Get(0).(func(context.Context, *int64) (*coretypes.ResultBlockResults, error)); ok { + return rf(ctx, height) } - if rf, ok := ret.Get(0).(func(*int64) *coretypes.ResultBlockResults); ok { - r0 = rf(height) + if rf, ok := ret.Get(0).(func(context.Context, *int64) *coretypes.ResultBlockResults); ok { + r0 = rf(ctx, height) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*coretypes.ResultBlockResults) } } - if rf, ok := ret.Get(1).(func(*int64) error); ok { - r1 = rf(height) + if rf, ok := ret.Get(1).(func(context.Context, *int64) error); ok { + r1 = rf(ctx, height) } else { r1 = ret.Error(1) } @@ -233,14 +238,15 @@ type Backend_CometBlockResultByNumber_Call struct { } // CometBlockResultByNumber is a helper method to define mock.On call +// - ctx context.Context // - height *int64 -func (_e *Backend_Expecter) CometBlockResultByNumber(height interface{}) *Backend_CometBlockResultByNumber_Call { - return &Backend_CometBlockResultByNumber_Call{Call: _e.mock.On("CometBlockResultByNumber", height)} +func (_e *Backend_Expecter) CometBlockResultByNumber(ctx interface{}, height interface{}) *Backend_CometBlockResultByNumber_Call { + return &Backend_CometBlockResultByNumber_Call{Call: _e.mock.On("CometBlockResultByNumber", ctx, height)} } -func (_c *Backend_CometBlockResultByNumber_Call) Run(run func(height *int64)) *Backend_CometBlockResultByNumber_Call { +func (_c *Backend_CometBlockResultByNumber_Call) Run(run func(ctx context.Context, height *int64)) *Backend_CometBlockResultByNumber_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*int64)) + run(args[0].(context.Context), args[1].(*int64)) }) return _c } @@ -250,14 +256,14 @@ func (_c *Backend_CometBlockResultByNumber_Call) Return(_a0 *coretypes.ResultBlo return _c } -func (_c *Backend_CometBlockResultByNumber_Call) RunAndReturn(run func(*int64) (*coretypes.ResultBlockResults, error)) *Backend_CometBlockResultByNumber_Call { +func (_c *Backend_CometBlockResultByNumber_Call) RunAndReturn(run func(context.Context, *int64) (*coretypes.ResultBlockResults, error)) *Backend_CometBlockResultByNumber_Call { _c.Call.Return(run) return _c } -// GetBlockByNumber provides a mock function with given fields: blockNum, fullTx -func (_m *Backend) GetBlockByNumber(blockNum rpctypes.BlockNumber, fullTx bool) (map[string]interface{}, error) { - ret := _m.Called(blockNum, fullTx) +// GetBlockByNumber provides a mock function with given fields: ctx, blockNum, fullTx +func (_m *Backend) GetBlockByNumber(ctx context.Context, blockNum rpctypes.BlockNumber, fullTx bool) (map[string]interface{}, error) { + ret := _m.Called(ctx, blockNum, fullTx) if len(ret) == 0 { panic("no return value specified for GetBlockByNumber") @@ -265,19 +271,19 @@ func (_m *Backend) GetBlockByNumber(blockNum rpctypes.BlockNumber, fullTx bool) var r0 map[string]interface{} var r1 error - if rf, ok := ret.Get(0).(func(rpctypes.BlockNumber, bool) (map[string]interface{}, error)); ok { - return rf(blockNum, fullTx) + if rf, ok := ret.Get(0).(func(context.Context, rpctypes.BlockNumber, bool) (map[string]interface{}, error)); ok { + return rf(ctx, blockNum, fullTx) } - if rf, ok := ret.Get(0).(func(rpctypes.BlockNumber, bool) map[string]interface{}); ok { - r0 = rf(blockNum, fullTx) + if rf, ok := ret.Get(0).(func(context.Context, rpctypes.BlockNumber, bool) map[string]interface{}); ok { + r0 = rf(ctx, blockNum, fullTx) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(map[string]interface{}) } } - if rf, ok := ret.Get(1).(func(rpctypes.BlockNumber, bool) error); ok { - r1 = rf(blockNum, fullTx) + if rf, ok := ret.Get(1).(func(context.Context, rpctypes.BlockNumber, bool) error); ok { + r1 = rf(ctx, blockNum, fullTx) } else { r1 = ret.Error(1) } @@ -291,15 +297,16 @@ type Backend_GetBlockByNumber_Call struct { } // GetBlockByNumber is a helper method to define mock.On call +// - ctx context.Context // - blockNum rpctypes.BlockNumber // - fullTx bool -func (_e *Backend_Expecter) GetBlockByNumber(blockNum interface{}, fullTx interface{}) *Backend_GetBlockByNumber_Call { - return &Backend_GetBlockByNumber_Call{Call: _e.mock.On("GetBlockByNumber", blockNum, fullTx)} +func (_e *Backend_Expecter) GetBlockByNumber(ctx interface{}, blockNum interface{}, fullTx interface{}) *Backend_GetBlockByNumber_Call { + return &Backend_GetBlockByNumber_Call{Call: _e.mock.On("GetBlockByNumber", ctx, blockNum, fullTx)} } -func (_c *Backend_GetBlockByNumber_Call) Run(run func(blockNum rpctypes.BlockNumber, fullTx bool)) *Backend_GetBlockByNumber_Call { +func (_c *Backend_GetBlockByNumber_Call) Run(run func(ctx context.Context, blockNum rpctypes.BlockNumber, fullTx bool)) *Backend_GetBlockByNumber_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(rpctypes.BlockNumber), args[1].(bool)) + run(args[0].(context.Context), args[1].(rpctypes.BlockNumber), args[2].(bool)) }) return _c } @@ -309,14 +316,14 @@ func (_c *Backend_GetBlockByNumber_Call) Return(_a0 map[string]interface{}, _a1 return _c } -func (_c *Backend_GetBlockByNumber_Call) RunAndReturn(run func(rpctypes.BlockNumber, bool) (map[string]interface{}, error)) *Backend_GetBlockByNumber_Call { +func (_c *Backend_GetBlockByNumber_Call) RunAndReturn(run func(context.Context, rpctypes.BlockNumber, bool) (map[string]interface{}, error)) *Backend_GetBlockByNumber_Call { _c.Call.Return(run) return _c } -// GetLogs provides a mock function with given fields: blockHash -func (_m *Backend) GetLogs(blockHash common.Hash) ([][]*types.Log, error) { - ret := _m.Called(blockHash) +// GetLogs provides a mock function with given fields: ctx, blockHash +func (_m *Backend) GetLogs(ctx context.Context, blockHash common.Hash) ([][]*types.Log, error) { + ret := _m.Called(ctx, blockHash) if len(ret) == 0 { panic("no return value specified for GetLogs") @@ -324,19 +331,19 @@ func (_m *Backend) GetLogs(blockHash common.Hash) ([][]*types.Log, error) { var r0 [][]*types.Log var r1 error - if rf, ok := ret.Get(0).(func(common.Hash) ([][]*types.Log, error)); ok { - return rf(blockHash) + if rf, ok := ret.Get(0).(func(context.Context, common.Hash) ([][]*types.Log, error)); ok { + return rf(ctx, blockHash) } - if rf, ok := ret.Get(0).(func(common.Hash) [][]*types.Log); ok { - r0 = rf(blockHash) + if rf, ok := ret.Get(0).(func(context.Context, common.Hash) [][]*types.Log); ok { + r0 = rf(ctx, blockHash) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([][]*types.Log) } } - if rf, ok := ret.Get(1).(func(common.Hash) error); ok { - r1 = rf(blockHash) + if rf, ok := ret.Get(1).(func(context.Context, common.Hash) error); ok { + r1 = rf(ctx, blockHash) } else { r1 = ret.Error(1) } @@ -350,14 +357,15 @@ type Backend_GetLogs_Call struct { } // GetLogs is a helper method to define mock.On call +// - ctx context.Context // - blockHash common.Hash -func (_e *Backend_Expecter) GetLogs(blockHash interface{}) *Backend_GetLogs_Call { - return &Backend_GetLogs_Call{Call: _e.mock.On("GetLogs", blockHash)} +func (_e *Backend_Expecter) GetLogs(ctx interface{}, blockHash interface{}) *Backend_GetLogs_Call { + return &Backend_GetLogs_Call{Call: _e.mock.On("GetLogs", ctx, blockHash)} } -func (_c *Backend_GetLogs_Call) Run(run func(blockHash common.Hash)) *Backend_GetLogs_Call { +func (_c *Backend_GetLogs_Call) Run(run func(ctx context.Context, blockHash common.Hash)) *Backend_GetLogs_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(common.Hash)) + run(args[0].(context.Context), args[1].(common.Hash)) }) return _c } @@ -367,14 +375,14 @@ func (_c *Backend_GetLogs_Call) Return(_a0 [][]*types.Log, _a1 error) *Backend_G return _c } -func (_c *Backend_GetLogs_Call) RunAndReturn(run func(common.Hash) ([][]*types.Log, error)) *Backend_GetLogs_Call { +func (_c *Backend_GetLogs_Call) RunAndReturn(run func(context.Context, common.Hash) ([][]*types.Log, error)) *Backend_GetLogs_Call { _c.Call.Return(run) return _c } -// GetLogsByHeight provides a mock function with given fields: _a0 -func (_m *Backend) GetLogsByHeight(_a0 *int64) ([][]*types.Log, error) { - ret := _m.Called(_a0) +// GetLogsByHeight provides a mock function with given fields: ctx, height +func (_m *Backend) GetLogsByHeight(ctx context.Context, height *int64) ([][]*types.Log, error) { + ret := _m.Called(ctx, height) if len(ret) == 0 { panic("no return value specified for GetLogsByHeight") @@ -382,19 +390,19 @@ func (_m *Backend) GetLogsByHeight(_a0 *int64) ([][]*types.Log, error) { var r0 [][]*types.Log var r1 error - if rf, ok := ret.Get(0).(func(*int64) ([][]*types.Log, error)); ok { - return rf(_a0) + if rf, ok := ret.Get(0).(func(context.Context, *int64) ([][]*types.Log, error)); ok { + return rf(ctx, height) } - if rf, ok := ret.Get(0).(func(*int64) [][]*types.Log); ok { - r0 = rf(_a0) + if rf, ok := ret.Get(0).(func(context.Context, *int64) [][]*types.Log); ok { + r0 = rf(ctx, height) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([][]*types.Log) } } - if rf, ok := ret.Get(1).(func(*int64) error); ok { - r1 = rf(_a0) + if rf, ok := ret.Get(1).(func(context.Context, *int64) error); ok { + r1 = rf(ctx, height) } else { r1 = ret.Error(1) } @@ -408,14 +416,15 @@ type Backend_GetLogsByHeight_Call struct { } // GetLogsByHeight is a helper method to define mock.On call -// - _a0 *int64 -func (_e *Backend_Expecter) GetLogsByHeight(_a0 interface{}) *Backend_GetLogsByHeight_Call { - return &Backend_GetLogsByHeight_Call{Call: _e.mock.On("GetLogsByHeight", _a0)} +// - ctx context.Context +// - height *int64 +func (_e *Backend_Expecter) GetLogsByHeight(ctx interface{}, height interface{}) *Backend_GetLogsByHeight_Call { + return &Backend_GetLogsByHeight_Call{Call: _e.mock.On("GetLogsByHeight", ctx, height)} } -func (_c *Backend_GetLogsByHeight_Call) Run(run func(_a0 *int64)) *Backend_GetLogsByHeight_Call { +func (_c *Backend_GetLogsByHeight_Call) Run(run func(ctx context.Context, height *int64)) *Backend_GetLogsByHeight_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*int64)) + run(args[0].(context.Context), args[1].(*int64)) }) return _c } @@ -425,14 +434,14 @@ func (_c *Backend_GetLogsByHeight_Call) Return(_a0 [][]*types.Log, _a1 error) *B return _c } -func (_c *Backend_GetLogsByHeight_Call) RunAndReturn(run func(*int64) ([][]*types.Log, error)) *Backend_GetLogsByHeight_Call { +func (_c *Backend_GetLogsByHeight_Call) RunAndReturn(run func(context.Context, *int64) ([][]*types.Log, error)) *Backend_GetLogsByHeight_Call { _c.Call.Return(run) return _c } -// HeaderByHash provides a mock function with given fields: blockHash -func (_m *Backend) HeaderByHash(blockHash common.Hash) (*types.Header, error) { - ret := _m.Called(blockHash) +// HeaderByHash provides a mock function with given fields: ctx, blockHash +func (_m *Backend) HeaderByHash(ctx context.Context, blockHash common.Hash) (*types.Header, error) { + ret := _m.Called(ctx, blockHash) if len(ret) == 0 { panic("no return value specified for HeaderByHash") @@ -440,19 +449,19 @@ func (_m *Backend) HeaderByHash(blockHash common.Hash) (*types.Header, error) { var r0 *types.Header var r1 error - if rf, ok := ret.Get(0).(func(common.Hash) (*types.Header, error)); ok { - return rf(blockHash) + if rf, ok := ret.Get(0).(func(context.Context, common.Hash) (*types.Header, error)); ok { + return rf(ctx, blockHash) } - if rf, ok := ret.Get(0).(func(common.Hash) *types.Header); ok { - r0 = rf(blockHash) + if rf, ok := ret.Get(0).(func(context.Context, common.Hash) *types.Header); ok { + r0 = rf(ctx, blockHash) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*types.Header) } } - if rf, ok := ret.Get(1).(func(common.Hash) error); ok { - r1 = rf(blockHash) + if rf, ok := ret.Get(1).(func(context.Context, common.Hash) error); ok { + r1 = rf(ctx, blockHash) } else { r1 = ret.Error(1) } @@ -466,14 +475,15 @@ type Backend_HeaderByHash_Call struct { } // HeaderByHash is a helper method to define mock.On call +// - ctx context.Context // - blockHash common.Hash -func (_e *Backend_Expecter) HeaderByHash(blockHash interface{}) *Backend_HeaderByHash_Call { - return &Backend_HeaderByHash_Call{Call: _e.mock.On("HeaderByHash", blockHash)} +func (_e *Backend_Expecter) HeaderByHash(ctx interface{}, blockHash interface{}) *Backend_HeaderByHash_Call { + return &Backend_HeaderByHash_Call{Call: _e.mock.On("HeaderByHash", ctx, blockHash)} } -func (_c *Backend_HeaderByHash_Call) Run(run func(blockHash common.Hash)) *Backend_HeaderByHash_Call { +func (_c *Backend_HeaderByHash_Call) Run(run func(ctx context.Context, blockHash common.Hash)) *Backend_HeaderByHash_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(common.Hash)) + run(args[0].(context.Context), args[1].(common.Hash)) }) return _c } @@ -483,14 +493,14 @@ func (_c *Backend_HeaderByHash_Call) Return(_a0 *types.Header, _a1 error) *Backe return _c } -func (_c *Backend_HeaderByHash_Call) RunAndReturn(run func(common.Hash) (*types.Header, error)) *Backend_HeaderByHash_Call { +func (_c *Backend_HeaderByHash_Call) RunAndReturn(run func(context.Context, common.Hash) (*types.Header, error)) *Backend_HeaderByHash_Call { _c.Call.Return(run) return _c } -// HeaderByNumber provides a mock function with given fields: blockNum -func (_m *Backend) HeaderByNumber(blockNum rpctypes.BlockNumber) (*types.Header, error) { - ret := _m.Called(blockNum) +// HeaderByNumber provides a mock function with given fields: ctx, blockNum +func (_m *Backend) HeaderByNumber(ctx context.Context, blockNum rpctypes.BlockNumber) (*types.Header, error) { + ret := _m.Called(ctx, blockNum) if len(ret) == 0 { panic("no return value specified for HeaderByNumber") @@ -498,19 +508,19 @@ func (_m *Backend) HeaderByNumber(blockNum rpctypes.BlockNumber) (*types.Header, var r0 *types.Header var r1 error - if rf, ok := ret.Get(0).(func(rpctypes.BlockNumber) (*types.Header, error)); ok { - return rf(blockNum) + if rf, ok := ret.Get(0).(func(context.Context, rpctypes.BlockNumber) (*types.Header, error)); ok { + return rf(ctx, blockNum) } - if rf, ok := ret.Get(0).(func(rpctypes.BlockNumber) *types.Header); ok { - r0 = rf(blockNum) + if rf, ok := ret.Get(0).(func(context.Context, rpctypes.BlockNumber) *types.Header); ok { + r0 = rf(ctx, blockNum) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*types.Header) } } - if rf, ok := ret.Get(1).(func(rpctypes.BlockNumber) error); ok { - r1 = rf(blockNum) + if rf, ok := ret.Get(1).(func(context.Context, rpctypes.BlockNumber) error); ok { + r1 = rf(ctx, blockNum) } else { r1 = ret.Error(1) } @@ -524,14 +534,15 @@ type Backend_HeaderByNumber_Call struct { } // HeaderByNumber is a helper method to define mock.On call +// - ctx context.Context // - blockNum rpctypes.BlockNumber -func (_e *Backend_Expecter) HeaderByNumber(blockNum interface{}) *Backend_HeaderByNumber_Call { - return &Backend_HeaderByNumber_Call{Call: _e.mock.On("HeaderByNumber", blockNum)} +func (_e *Backend_Expecter) HeaderByNumber(ctx interface{}, blockNum interface{}) *Backend_HeaderByNumber_Call { + return &Backend_HeaderByNumber_Call{Call: _e.mock.On("HeaderByNumber", ctx, blockNum)} } -func (_c *Backend_HeaderByNumber_Call) Run(run func(blockNum rpctypes.BlockNumber)) *Backend_HeaderByNumber_Call { +func (_c *Backend_HeaderByNumber_Call) Run(run func(ctx context.Context, blockNum rpctypes.BlockNumber)) *Backend_HeaderByNumber_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(rpctypes.BlockNumber)) + run(args[0].(context.Context), args[1].(rpctypes.BlockNumber)) }) return _c } @@ -541,7 +552,7 @@ func (_c *Backend_HeaderByNumber_Call) Return(_a0 *types.Header, _a1 error) *Bac return _c } -func (_c *Backend_HeaderByNumber_Call) RunAndReturn(run func(rpctypes.BlockNumber) (*types.Header, error)) *Backend_HeaderByNumber_Call { +func (_c *Backend_HeaderByNumber_Call) RunAndReturn(run func(context.Context, rpctypes.BlockNumber) (*types.Header, error)) *Backend_HeaderByNumber_Call { _c.Call.Return(run) return _c } @@ -591,51 +602,6 @@ func (_c *Backend_RPCBlockRangeCap_Call) RunAndReturn(run func() int32) *Backend return _c } -// RPCFilterCap provides a mock function with no fields -func (_m *Backend) RPCFilterCap() int32 { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for RPCFilterCap") - } - - var r0 int32 - if rf, ok := ret.Get(0).(func() int32); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(int32) - } - - return r0 -} - -// Backend_RPCFilterCap_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RPCFilterCap' -type Backend_RPCFilterCap_Call struct { - *mock.Call -} - -// RPCFilterCap is a helper method to define mock.On call -func (_e *Backend_Expecter) RPCFilterCap() *Backend_RPCFilterCap_Call { - return &Backend_RPCFilterCap_Call{Call: _e.mock.On("RPCFilterCap")} -} - -func (_c *Backend_RPCFilterCap_Call) Run(run func()) *Backend_RPCFilterCap_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *Backend_RPCFilterCap_Call) Return(_a0 int32) *Backend_RPCFilterCap_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *Backend_RPCFilterCap_Call) RunAndReturn(run func() int32) *Backend_RPCFilterCap_Call { - _c.Call.Return(run) - return _c -} - // RPCLogsCap provides a mock function with no fields func (_m *Backend) RPCLogsCap() int32 { ret := _m.Called() @@ -686,7 +652,8 @@ func (_c *Backend_RPCLogsCap_Call) RunAndReturn(run func() int32) *Backend_RPCLo func NewBackend(t interface { mock.TestingT Cleanup(func()) -}) *Backend { +}, +) *Backend { mock := &Backend{} mock.Mock.Test(t) diff --git a/rpc/namespaces/ethereum/miner/api.go b/rpc/namespaces/ethereum/miner/api.go index b8e60d3d..0ecf00da 100644 --- a/rpc/namespaces/ethereum/miner/api.go +++ b/rpc/namespaces/ethereum/miner/api.go @@ -1,16 +1,21 @@ package miner import ( + "context" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "go.opentelemetry.io/otel" "github.com/cosmos/evm/rpc/backend" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" "github.com/cosmos/cosmos-sdk/server" ) +var tracer = otel.Tracer("evm/rpc/namespaces/ethereum/miner") + // API is the private miner prefixed set of APIs in the Miner JSON-RPC spec. type API struct { ctx *server.Context @@ -33,11 +38,15 @@ func NewPrivateAPI( // SetEtherbase sets the etherbase of the miner func (api *API) SetEtherbase(etherbase common.Address) bool { api.logger.Debug("miner_setEtherbase") - return api.backend.SetEtherbase(etherbase) + ctx, span := tracer.Start(context.Background(), "miner_setEtherbase") + defer span.End() + return api.backend.SetEtherbase(ctx, etherbase) } // SetGasPrice sets the minimum accepted gas price for the miner. func (api *API) SetGasPrice(gasPrice hexutil.Big) bool { api.logger.Info(api.ctx.Viper.ConfigFileUsed()) - return api.backend.SetGasPrice(gasPrice) + ctx, span := tracer.Start(context.Background(), "miner_setGasPrice") + defer span.End() + return api.backend.SetGasPrice(ctx, gasPrice) } diff --git a/rpc/namespaces/ethereum/net/api.go b/rpc/namespaces/ethereum/net/api.go index d1c8f39f..226c0c79 100644 --- a/rpc/namespaces/ethereum/net/api.go +++ b/rpc/namespaces/ethereum/net/api.go @@ -4,6 +4,8 @@ import ( "context" "fmt" + "go.opentelemetry.io/otel" + rpcclient "github.com/cometbft/cometbft/rpc/client" "github.com/cosmos/evm/server/config" @@ -12,6 +14,8 @@ import ( "github.com/cosmos/cosmos-sdk/server" ) +var tracer = otel.Tracer("evm/rpc/namespaces/ethereum/net") + // PublicAPI is the eth_ prefixed set of APIs in the Web3 JSON-RPC spec. type PublicAPI struct { networkVersion uint64 @@ -37,7 +41,8 @@ func (s *PublicAPI) Version() string { // Listening returns if client is actively listening for network connections. func (s *PublicAPI) Listening() bool { - ctx := context.Background() + ctx, span := tracer.Start(context.Background(), "Listening") + defer span.End() netInfo, err := s.tmClient.NetInfo(ctx) if err != nil { return false @@ -47,7 +52,8 @@ func (s *PublicAPI) Listening() bool { // PeerCount returns the number of peers currently connected to the client. func (s *PublicAPI) PeerCount() int { - ctx := context.Background() + ctx, span := tracer.Start(context.Background(), "PeerCount") + defer span.End() netInfo, err := s.tmClient.NetInfo(ctx) if err != nil { return 0 diff --git a/rpc/namespaces/ethereum/personal/api.go b/rpc/namespaces/ethereum/personal/api.go index 51a5b73c..93bd689c 100644 --- a/rpc/namespaces/ethereum/personal/api.go +++ b/rpc/namespaces/ethereum/personal/api.go @@ -10,17 +10,21 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" + "go.opentelemetry.io/otel" "github.com/cosmos/evm/crypto/hd" "github.com/cosmos/evm/rpc/backend" + evmtrace "github.com/cosmos/evm/trace" evmtypes "github.com/cosmos/evm/x/vm/types" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" "github.com/cosmos/cosmos-sdk/crypto/keyring" sdk "github.com/cosmos/cosmos-sdk/types" ) +var tracer = otel.Tracer("evm/rpc/namespaces/ethereum/personal") + // PrivateAccountAPI is the personal_ prefixed set of APIs in the Web3 JSON-RPC spec. type PrivateAccountAPI struct { backend backend.EVMBackend @@ -110,9 +114,11 @@ func (api *PrivateAccountAPI) UnlockAccount(_ context.Context, addr common.Addre // SendTransaction will create a transaction from the given arguments and // tries to sign it with the key associated with args.To. If the given password isn't // able to decrypt the key it fails. -func (api *PrivateAccountAPI) SendTransaction(_ context.Context, args evmtypes.TransactionArgs, _ string) (common.Hash, error) { +func (api *PrivateAccountAPI) SendTransaction(ctx context.Context, args evmtypes.TransactionArgs, _ string) (_ common.Hash, err error) { api.logger.Debug("personal_sendTransaction", "address", args.To.String()) - return api.backend.SendTransaction(args) + ctx, span := tracer.Start(ctx, "SendTransaction") + defer func() { evmtrace.EndSpanErr(span, err) }() + return api.backend.SendTransaction(ctx, args) } // Sign calculates an Ethereum ECDSA signature for: @@ -124,7 +130,7 @@ func (api *PrivateAccountAPI) SendTransaction(_ context.Context, args evmtypes.T // The key used to calculate the signature is decrypted with the given password. // // https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_sign -func (api *PrivateAccountAPI) Sign(_ context.Context, data hexutil.Bytes, addr common.Address, _ string) (hexutil.Bytes, error) { +func (api *PrivateAccountAPI) Sign(ctx context.Context, data hexutil.Bytes, addr common.Address, _ string) (hexutil.Bytes, error) { api.logger.Debug("personal_sign", "data", data, "address", addr.String()) return api.backend.Sign(addr, data) } @@ -139,8 +145,10 @@ func (api *PrivateAccountAPI) Sign(_ context.Context, data hexutil.Bytes, addr c // the V value must be 27 or 28 for legacy reasons. // // https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_ecRecove -func (api *PrivateAccountAPI) EcRecover(_ context.Context, data, sig hexutil.Bytes) (common.Address, error) { +func (api *PrivateAccountAPI) EcRecover(ctx context.Context, data, sig hexutil.Bytes) (_ common.Address, err error) { api.logger.Debug("personal_ecRecover", "data", data, "sig", sig) + _, span := tracer.Start(ctx, "EcRecover") + defer func() { evmtrace.EndSpanErr(span, err) }() if len(sig) != crypto.SignatureLength { return common.Address{}, fmt.Errorf("signature must be %d bytes long", crypto.SignatureLength) diff --git a/rpc/namespaces/ethereum/txpool/api.go b/rpc/namespaces/ethereum/txpool/api.go index ec041865..398a0b46 100644 --- a/rpc/namespaces/ethereum/txpool/api.go +++ b/rpc/namespaces/ethereum/txpool/api.go @@ -1,15 +1,23 @@ package txpool import ( + "context" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" "github.com/cosmos/evm/rpc/backend" "github.com/cosmos/evm/rpc/types" + evmtrace "github.com/cosmos/evm/trace" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" ) +var tracer = otel.Tracer("evm/rpc/namespaces/ethereum/txpool") + // PublicAPI offers and API for the transaction pool. It only operates on data that is non-confidential. // NOTE: For more info about the current status of this endpoints see https://github.com/evmos/ethermint/issues/124 type PublicAPI struct { @@ -26,25 +34,33 @@ func NewPublicAPI(logger log.Logger, backend backend.EVMBackend) *PublicAPI { } // Content returns the transactions contained within the transaction pool -func (api *PublicAPI) Content() (map[string]map[string]map[string]*types.RPCTransaction, error) { +func (api *PublicAPI) Content() (_ map[string]map[string]map[string]*types.RPCTransaction, err error) { api.logger.Debug("txpool_content") - return api.backend.Content() + ctx, span := tracer.Start(context.Background(), "Content") + defer func() { evmtrace.EndSpanErr(span, err) }() + return api.backend.Content(ctx) } // ContentFrom returns the transactions contained within the transaction pool -func (api *PublicAPI) ContentFrom(address common.Address) (map[string]map[string]*types.RPCTransaction, error) { +func (api *PublicAPI) ContentFrom(address common.Address) (_ map[string]map[string]*types.RPCTransaction, err error) { api.logger.Debug("txpool_contentFrom") - return api.backend.ContentFrom(address) + ctx, span := tracer.Start(context.Background(), "ContentFrom", trace.WithAttributes(attribute.String("address", address.Hex()))) + defer func() { evmtrace.EndSpanErr(span, err) }() + return api.backend.ContentFrom(ctx, address) } // Inspect returns the content of the transaction pool and flattens it into an easily inspectable list -func (api *PublicAPI) Inspect() (map[string]map[string]map[string]string, error) { +func (api *PublicAPI) Inspect() (_ map[string]map[string]map[string]string, err error) { api.logger.Debug("txpool_inspect") - return api.backend.Inspect() + ctx, span := tracer.Start(context.Background(), "Inspect") + defer func() { evmtrace.EndSpanErr(span, err) }() + return api.backend.Inspect(ctx) } // Status returns the number of pending and queued transaction in the pool -func (api *PublicAPI) Status() (map[string]hexutil.Uint, error) { +func (api *PublicAPI) Status() (_ map[string]hexutil.Uint, err error) { api.logger.Debug("txpool_status") - return api.backend.Status() + ctx, span := tracer.Start(context.Background(), "Status") + defer func() { evmtrace.EndSpanErr(span, err) }() + return api.backend.Status(ctx) } diff --git a/rpc/stream/rpc.go b/rpc/stream/rpc.go index 684f0946..305c0c82 100644 --- a/rpc/stream/rpc.go +++ b/rpc/stream/rpc.go @@ -17,7 +17,7 @@ import ( "github.com/cosmos/evm/utils" evmtypes "github.com/cosmos/evm/x/vm/types" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" sdk "github.com/cosmos/cosmos-sdk/types" ) diff --git a/rpc/types/block.go b/rpc/types/block.go index 3f34bf39..b57e80a9 100644 --- a/rpc/types/block.go +++ b/rpc/types/block.go @@ -48,15 +48,23 @@ func NewBlockNumber(n *big.Int) BlockNumber { return BlockNumber(n.Int64()) } -// ContextWithHeight wraps a context with the a gRPC block height header. If the provided height is -// 0, it will return an empty context and the gRPC query will use the latest block height for querying. -// Note that all metadata is processed and removed by the CometBFT layer, so it won't be accessible at gRPC server level. -func ContextWithHeight(height int64) context.Context { +// ContextWithHeight wraps a context with the GRPCBlockHeightHeader set. +// If height == 0, the original context is returned unmodified. +func ContextWithHeight(ctx context.Context, height int64) context.Context { if height == 0 { - return context.Background() + return ctx } + return metadata.AppendToOutgoingContext(ctx, grpctypes.GRPCBlockHeightHeader, fmt.Sprintf("%d", height)) +} - return metadata.AppendToOutgoingContext(context.Background(), grpctypes.GRPCBlockHeightHeader, fmt.Sprintf("%d", height)) +// NewContextWithHeight wraps a new background context with the gRPC block height header. If the provided height is +// 0, it will return an empty context and the gRPC query will use the latest block height for querying. +func NewContextWithHeight(height int64) context.Context { + ctx := context.Background() + if height == 0 { + return ctx + } + return metadata.AppendToOutgoingContext(ctx, grpctypes.GRPCBlockHeightHeader, fmt.Sprintf("%d", height)) } // UnmarshalJSON parses the given JSON fragment into a BlockNumber. It supports: diff --git a/rpc/types/events.go b/rpc/types/events.go index 34761d81..70ee1020 100644 --- a/rpc/types/events.go +++ b/rpc/types/events.go @@ -188,6 +188,9 @@ func (p *ParsedTxs) updateTx(eventIndex int, attrs []abci.EventAttribute) error // if hash is different, index the new one too p.TxHashes[tx.Hash] = eventIndex } + if tx.EthTxIndex == -1 { + tx.EthTxIndex = p.Txs[eventIndex].EthTxIndex + } // override the tx because the second event is more trustworthy p.Txs[eventIndex] = tx return nil diff --git a/rpc/types/events_test.go b/rpc/types/events_test.go index e20cc11d..13020e82 100644 --- a/rpc/types/events_test.go +++ b/rpc/types/events_test.go @@ -165,6 +165,34 @@ func TestParseTxResult(t *testing.T) { }, nil, }, + { + "format 2, second event missing txIndex (msg_server)", + abci.ExecTxResult{ + GasUsed: 21000, + Events: []abci.Event{ + {Type: evmtypes.EventTypeEthereumTx, Attributes: []abci.EventAttribute{ + {Key: "ethereumTxHash", Value: txHash.Hex()}, + {Key: "txIndex", Value: "7"}, + }}, + {Type: evmtypes.EventTypeEthereumTx, Attributes: []abci.EventAttribute{ + {Key: "amount", Value: "1000"}, + {Key: "ethereumTxHash", Value: txHash.Hex()}, + {Key: "txGasUsed", Value: "21000"}, + {Key: "txHash", Value: "14A84ED06282645EFBF080E0B7ED80D8D8D6A36337668A12B5F229F81CDD3F57"}, + {Key: "recipient", Value: "0x775b87ef5D82ca211811C1a02CE0fE0CA3a455d7"}, + }}, + }, + }, + []*ParsedTx{ + { + MsgIndex: 0, + Hash: txHash, + EthTxIndex: 7, + GasUsed: 21000, + Failed: false, + }, + }, + }, } for _, tc := range testCases { diff --git a/rpc/types/types.go b/rpc/types/types.go index 471a9f0a..adaed22b 100644 --- a/rpc/types/types.go +++ b/rpc/types/types.go @@ -110,7 +110,7 @@ func (diff *StateOverride) Apply(db *statedb.StateDB, precompiles vm.Precompiled } // Override account(contract) code. if account.Code != nil { - db.SetCode(addr, *account.Code) + db.SetCode(addr, *account.Code, tracing.CodeChangeUnspecified) } // Override account balance. if account.Balance != nil && *account.Balance != nil { diff --git a/rpc/types/types_test.go b/rpc/types/types_test.go index 33360236..744d6b76 100644 --- a/rpc/types/types_test.go +++ b/rpc/types/types_test.go @@ -17,6 +17,8 @@ import ( type precompileContract struct{} +func (p *precompileContract) Name() string { return "" } + func (p *precompileContract) Address() common.Address { return common.Address{} } func (p *precompileContract) RequiredGas(input []byte) uint64 { return 0 } @@ -27,7 +29,7 @@ func (p *precompileContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bo func TestApply(t *testing.T) { emptyTxConfig := statedb.NewEmptyTxConfig() - db := statedb.New(sdk.Context{}, mocks.NewEVMKeeper(), emptyTxConfig) + db := statedb.New(sdk.Context{}.WithEventManager(sdk.NewEventManager()), mocks.NewEVMKeeper(), emptyTxConfig) precompiles := map[common.Address]vm.PrecompiledContract{ common.BytesToAddress([]byte{0x1}): &precompileContract{}, common.BytesToAddress([]byte{0x2}): &precompileContract{}, diff --git a/rpc/types/utils.go b/rpc/types/utils.go index d2554f7b..37845e42 100644 --- a/rpc/types/utils.go +++ b/rpc/types/utils.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "math/big" - "strings" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -12,12 +11,14 @@ import ( ethtypes "github.com/ethereum/go-ethereum/core/types" ethparams "github.com/ethereum/go-ethereum/params" "github.com/pkg/errors" + "go.opentelemetry.io/otel" abci "github.com/cometbft/cometbft/abci/types" cmtrpcclient "github.com/cometbft/cometbft/rpc/client" cmtrpccore "github.com/cometbft/cometbft/rpc/core/types" cmttypes "github.com/cometbft/cometbft/types" + evmtrace "github.com/cosmos/evm/trace" feemarkettypes "github.com/cosmos/evm/x/feemarket/types" evmtypes "github.com/cosmos/evm/x/vm/types" @@ -28,15 +29,6 @@ import ( errortypes "github.com/cosmos/cosmos-sdk/types/errors" ) -// ExceedBlockGasLimitError defines the error message when tx execution exceeds the block gas limit. -// The tx fee is deducted in ante handler, so it shouldn't be ignored in JSON-RPC API. -const ExceedBlockGasLimitError = "out of gas in location: block gas meter; gasWanted:" - -// StateDBCommitError defines the error message when commit after executing EVM transaction, for example -// transfer native token to a distribution module account 0x93354845030274cD4bf1686Abd60AB28EC52e1a7 using an evm type transaction -// note: the transfer amount cannot be set to 0, otherwise this problem will not be triggered -const StateDBCommitError = "failed to commit stateDB" - // RawTxToEthTx returns a evm MsgEthereum transaction from raw tx bytes. func RawTxToEthTx(clientCtx client.Context, txBz cmttypes.Tx) ([]*evmtypes.MsgEthereumTx, error) { tx, err := clientCtx.TxConfig.TxDecoder()(txBz) @@ -97,8 +89,13 @@ func EthHeaderFromComet(header cmttypes.Header, bloom ethtypes.Bloom, baseFee *b } } +var tracer = otel.Tracer("evm/rpc/types") + // BlockMaxGasFromConsensusParams returns the gas limit for the current block from the chain consensus params. -func BlockMaxGasFromConsensusParams(goCtx context.Context, clientCtx client.Context, blockHeight int64) (int64, error) { +func BlockMaxGasFromConsensusParams(goCtx context.Context, clientCtx client.Context, blockHeight int64) (_ int64, err error) { + goCtx, span := tracer.Start(goCtx, "BlockMaxGasFromConsensusParams") + defer func() { evmtrace.EndSpanErr(span, err) }() + cmtrpcclient, ok := clientCtx.Client.(cmtrpcclient.Client) if !ok { panic("incorrect tm rpc client") @@ -343,22 +340,6 @@ func CheckTxFee(gasPrice *big.Int, gas uint64, minCap float64) error { return nil } -// TxExceedBlockGasLimit returns true if the tx exceeds block gas limit. -func TxExceedBlockGasLimit(res *abci.ExecTxResult) bool { - return strings.Contains(res.Log, ExceedBlockGasLimitError) -} - -// TxStateDBCommitError returns true if the evm tx commit error. -func TxStateDBCommitError(res *abci.ExecTxResult) bool { - return strings.Contains(res.Log, StateDBCommitError) -} - -// TxSucessOrExpectedFailure returns true if the transaction was successful -// or if it failed with an ExceedBlockGasLimit error or TxStateDBCommitError error -func TxSucessOrExpectedFailure(res *abci.ExecTxResult) bool { - return res.Code == 0 || TxExceedBlockGasLimit(res) || TxStateDBCommitError(res) -} - // CalcBaseFee calculates the basefee of the header. func CalcBaseFee(config *ethparams.ChainConfig, parent *ethtypes.Header, p feemarkettypes.Params) (*big.Int, error) { // If the current block is the first EIP-1559 block, return the InitialBaseFee. diff --git a/rpc/websockets.go b/rpc/websockets.go index d1e84df5..5d9d7a94 100644 --- a/rpc/websockets.go +++ b/rpc/websockets.go @@ -27,7 +27,7 @@ import ( "github.com/cosmos/evm/rpc/stream" "github.com/cosmos/evm/server/config" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" "github.com/cosmos/cosmos-sdk/client" ) @@ -41,9 +41,9 @@ type WebsocketsServer interface { } type SubscriptionResponseJSON struct { - Jsonrpc string `json:"jsonrpc"` - Result interface{} `json:"result"` - ID float64 `json:"id"` + Jsonrpc string `json:"jsonrpc"` + Result any `json:"result"` + ID float64 `json:"id"` } type SubscriptionNotification struct { @@ -53,8 +53,8 @@ type SubscriptionNotification struct { } type SubscriptionResult struct { - Subscription rpc.ID `json:"subscription"` - Result interface{} `json:"result"` + Subscription rpc.ID `json:"subscription"` + Result any `json:"result"` } type ErrorResponseJSON struct { @@ -219,7 +219,7 @@ type wsConn struct { mux *sync.Mutex } -func (w *wsConn) WriteJSON(v interface{}) error { +func (w *wsConn) WriteJSON(v any) error { w.mux.Lock() defer w.mux.Unlock() @@ -266,7 +266,7 @@ readLoop: continue } - var msg map[string]interface{} + var msg map[string]any if err = json.Unmarshal(mb, &msg); err != nil { s.sendErrResponse(wsConn, err.Error()) continue @@ -364,8 +364,8 @@ readLoop: } // tcpGetAndSendResponse sends error response to client if params is invalid -func (s *websocketsServer) getParamsAndCheckValid(msg map[string]interface{}, wsConn *wsConn) ([]interface{}, bool) { - params, ok := msg["params"].([]interface{}) +func (s *websocketsServer) getParamsAndCheckValid(msg map[string]any, wsConn *wsConn) ([]any, bool) { + params, ok := msg["params"].([]any) if !ok { s.sendErrResponse(wsConn, "invalid parameters") return nil, false @@ -389,6 +389,7 @@ func (s *websocketsServer) tcpGetAndSendResponse(wsConn *wsConn, mb []byte) erro req.Header.Set("Content-Type", "application/json") client := &http.Client{} + // #nosec G704 -- URL is node's own rpcAddr from config, not user-controlled resp, err := client.Do(req) if err != nil { return errors.Wrap(err, "Could not perform request") @@ -401,7 +402,7 @@ func (s *websocketsServer) tcpGetAndSendResponse(wsConn *wsConn, mb []byte) erro return errors.Wrap(err, "could not read body from response") } - var wsSend interface{} + var wsSend any err = json.Unmarshal(body, &wsSend) if err != nil { return errors.Wrap(err, "failed to unmarshal rest-server response") @@ -427,7 +428,7 @@ func newPubSubAPI(clientCtx client.Context, logger log.Logger, stream *stream.RP } } -func (api *pubSubAPI) subscribe(wsConn *wsConn, subID rpc.ID, params []interface{}) (context.CancelFunc, error) { +func (api *pubSubAPI) subscribe(wsConn *wsConn, subID rpc.ID, params []any) (context.CancelFunc, error) { method, ok := params[0].(string) if !ok { return nil, errors.New("invalid parameters") @@ -500,11 +501,11 @@ func try(fn func(), l log.Logger, desc string) { fn() } -func (api *pubSubAPI) subscribeLogs(wsConn *wsConn, subID rpc.ID, extra interface{}) (context.CancelFunc, error) { +func (api *pubSubAPI) subscribeLogs(wsConn *wsConn, subID rpc.ID, extra any) (context.CancelFunc, error) { crit := filters.FilterCriteria{} if extra != nil { - params, ok := extra.(map[string]interface{}) + params, ok := extra.(map[string]any) if !ok { err := errors.New("invalid criteria") api.logger.Debug("invalid criteria", "type", fmt.Sprintf("%T", extra)) @@ -530,7 +531,7 @@ func (api *pubSubAPI) subscribeLogs(wsConn *wsConn, subID rpc.ID, extra interfac } if params["topics"] != nil { - topics, ok := params["topics"].([]interface{}) + topics, ok := params["topics"].([]any) if !ok { err := errors.Errorf("invalid topics: %s", topics) api.logger.Error("invalid topics", "type", fmt.Sprintf("%T", topics)) @@ -539,7 +540,7 @@ func (api *pubSubAPI) subscribeLogs(wsConn *wsConn, subID rpc.ID, extra interfac crit.Topics = make([][]common.Hash, len(topics)) - addCritTopic := func(topicIdx int, topic interface{}) error { + addCritTopic := func(topicIdx int, topic any) error { tstr, ok := topic.(string) if !ok { err := errors.Errorf("invalid topic: %s", topic) @@ -566,7 +567,7 @@ func (api *pubSubAPI) subscribeLogs(wsConn *wsConn, subID rpc.ID, extra interfac } // in case we actually have a list of subtopics - subtopicsList, ok := subtopics.([]interface{}) + subtopicsList, ok := subtopics.([]any) if !ok { err := errors.New("invalid subtopics") api.logger.Error("invalid subtopic", "type", fmt.Sprintf("%T", subtopics)) diff --git a/rpc/websockets_test.go b/rpc/websockets_test.go index dd49dd43..ffa3904d 100644 --- a/rpc/websockets_test.go +++ b/rpc/websockets_test.go @@ -13,7 +13,7 @@ import ( "github.com/cosmos/evm/rpc/stream" "github.com/cosmos/evm/server/config" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" "github.com/cosmos/cosmos-sdk/client" ) diff --git a/scripts/compile_smart_contracts/compile_smart_contracts.py b/scripts/compile_smart_contracts/compile_smart_contracts.py index df47af41..eacc1d37 100644 --- a/scripts/compile_smart_contracts/compile_smart_contracts.py +++ b/scripts/compile_smart_contracts/compile_smart_contracts.py @@ -154,17 +154,17 @@ def is_ignored_file(file_path: Path, repo_path: Path) -> bool: """ relative_path = file_path.relative_to(repo_path) file_name = file_path.name - + for ignored_pattern in IGNORED_FILES: # Check if it's a regex pattern (contains regex metacharacters) - if any(char in ignored_pattern for char in r'.*+?^${}[]|()\\'): + if any(char in ignored_pattern for char in r".*+?^${}[]|()\\"): if re.search(ignored_pattern, str(relative_path)): return True else: # Simple filename match if file_name == ignored_pattern: return True - + return False diff --git a/scripts/go-mod-tidy-all.sh b/scripts/go-mod-tidy-all.sh new file mode 100755 index 00000000..c129f734 --- /dev/null +++ b/scripts/go-mod-tidy-all.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +set -euo pipefail + +for modfile in $(find . -name go.mod); do + echo "Updating $modfile" + DIR=$(dirname $modfile) + (cd $DIR; go mod tidy) +done diff --git a/scripts/go-update-dep-all.sh b/scripts/go-update-dep-all.sh new file mode 100755 index 00000000..a11d8e95 --- /dev/null +++ b/scripts/go-update-dep-all.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +set -euo pipefail + +if [ -z ${1+x} ]; then + echo "USAGE: + ./scripts/go-update-dep-all.sh + This command updates a dependency in all of the go.mod files which import it. + It should be called with a single argument which is the go module path of the dependency, + with an optional version specified by @." + exit +fi + +dependency=$1 +# in case the user explicitly specified a dependency version with @, we separate +# the dependency module name into dependency_mod +IFS='@' read -ra dependency_mod <<< "$dependency" +dependency_mod=${dependency_mod[0]} + +for modfile in $(find . -name go.mod); do + if grep $dependency_mod $modfile &> /dev/null; then + echo "Updating $modfile" + DIR=$(dirname $modfile) + # we want to skip the go.mod of the package we're updating + if [[ "$dependency_mod" == *"$(basename $DIR)" ]]; then + echo "Skipping $DIR" + continue + fi + (cd $DIR; go get -u $dependency) + fi +done diff --git a/server/config/config.go b/server/config/config.go index ddec8669..b1c9ae81 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -9,6 +9,7 @@ import ( "github.com/spf13/viper" + cmtconfig "github.com/cometbft/cometbft/config" "github.com/cometbft/cometbft/libs/strings" errorsmod "cosmossdk.io/errors" @@ -76,8 +77,11 @@ const ( // DefaultJSONRPCAllowInsecureUnlock is true DefaultJSONRPCAllowInsecureUnlock bool = true - // DefaultFilterCap is the default cap for total number of filters that can be created - DefaultFilterCap int32 = 200 + // DefaultFilterTimeout defines when an idle filter expires. + DefaultFilterTimeout = 5 * time.Minute + + // DefaultFilterCleanupInterval defines how often expired filters are cleaned up. + DefaultFilterCleanupInterval = 30 * time.Second // DefaultFeeHistoryCap is the default cap for total number of blocks that can be fetched DefaultFeeHistoryCap int32 = 100 @@ -100,6 +104,9 @@ const ( // DefaultHTTPIdleTimeout is the default idle timeout of the http json-rpc server DefaultHTTPIdleTimeout = 120 * time.Second + // DefaultHTTPBodyLimit is the default maximum request body size of the http json-rpc server. + DefaultHTTPBodyLimit = 5 * 1024 * 1024 + // DefaultAllowUnprotectedTxs value is false DefaultAllowUnprotectedTxs = false @@ -171,18 +178,37 @@ type MempoolConfig struct { GlobalQueue uint64 `mapstructure:"global-queue"` // Lifetime is the maximum amount of time non-executable transaction are queued Lifetime time.Duration `mapstructure:"lifetime"` + // IncludedNonceCacheSize is the maximum amount of nonces to store in the + // included cache + IncludedNonceCacheSize int `mapstructure:"included-nonce-cache-size"` + // PendingTxProposalTimeout is the amount of time to spend waiting for + // rechecking of the mempool to complete when creating a proposal + PendingTxProposalTimeout time.Duration `mapstructure:"pending-tx-proposal-timeout"` + // CheckTxTimeout timeout for CheckTx handler. + CheckTxTimeout time.Duration `mapstructure:"check-tx-timeout"` + // InsertQueueSize is the maximum number of transactions that can be in the + // insert queue at once (0 means unbounded) + InsertQueueSize int `mapstructure:"insert-queue-size"` + // EnableTxTracker enables per-tx lifecycle telemetry from the mempool + // (queued/pending/included latencies). Disabled by default. + EnableTxTracker bool `mapstructure:"enable-tx-tracker"` } // DefaultMempoolConfig returns the default mempool configuration func DefaultMempoolConfig() MempoolConfig { return MempoolConfig{ - PriceLimit: 1, // Minimum gas price of 1 wei - PriceBump: 10, // 10% price bump to replace transaction - AccountSlots: 16, // 16 executable transaction slots per account - GlobalSlots: 5120, // 4096 + 1024 = 5120 global executable slots - AccountQueue: 64, // 64 non-executable transaction slots per account - GlobalQueue: 1024, // 1024 global non-executable slots - Lifetime: 3 * time.Hour, // 3 hour lifetime for queued transactions + PriceLimit: 1, // Minimum gas price of 1 wei + PriceBump: 10, // 10% price bump to replace transaction + AccountSlots: 16, // 16 executable transaction slots per account + GlobalSlots: 5120, // 4096 + 1024 = 5120 global executable slots + AccountQueue: 64, // 64 non-executable transaction slots per account + GlobalQueue: 1024, // 1024 global non-executable slots + Lifetime: 3 * time.Hour, // 3 hour lifetime for queued transactions + IncludedNonceCacheSize: 4096, // Maximum 4096 nonces in LRU by default + PendingTxProposalTimeout: 250 * time.Millisecond, // 250 milliseconds to wait for rechecks + CheckTxTimeout: 5 * time.Second, // 5 seconds timeout for CheckTx handler. + InsertQueueSize: 5_000, // 5000 txs maximum in the insert queue + EnableTxTracker: false, // tx lifecycle telemetry off by default } } @@ -209,6 +235,15 @@ func (c MempoolConfig) Validate() error { if c.Lifetime < 1 { return fmt.Errorf("lifetime must be at least 1 nanosecond, got %s", c.Lifetime) } + if c.IncludedNonceCacheSize < 1 { + return fmt.Errorf("included nonce cache size should be at least 1, got %d", c.IncludedNonceCacheSize) + } + if c.CheckTxTimeout <= 0 { + return fmt.Errorf("check tx timeout must be greater than 0, got %s", c.CheckTxTimeout) + } + if c.InsertQueueSize < 1 { + return fmt.Errorf("insert queue size must be at least 1, got %d", c.InsertQueueSize) + } return nil } @@ -228,8 +263,10 @@ type JSONRPCConfig struct { EVMTimeout time.Duration `mapstructure:"evm-timeout"` // TxFeeCap is the global tx-fee cap for send transaction TxFeeCap float64 `mapstructure:"txfee-cap"` - // FilterCap is the global cap for total number of filters that can be created. - FilterCap int32 `mapstructure:"filter-cap"` + // FilterTimeout defines when an idle filter expires. + FilterTimeout time.Duration `mapstructure:"filter-timeout"` + // FilterCleanupInterval defines how often expired filters are cleaned up. + FilterCleanupInterval time.Duration `mapstructure:"filter-cleanup-interval"` // FeeHistoryCap is the global cap for total number of blocks that can be fetched FeeHistoryCap int32 `mapstructure:"feehistory-cap"` // Enable defines if the EVM RPC server should be enabled. @@ -242,6 +279,8 @@ type JSONRPCConfig struct { HTTPTimeout time.Duration `mapstructure:"http-timeout"` // HTTPIdleTimeout is the idle timeout of http json-rpc server. HTTPIdleTimeout time.Duration `mapstructure:"http-idle-timeout"` + // HTTPBodyLimit is the maximum allowed size, in bytes, of a JSON-RPC HTTP request body. + HTTPBodyLimit int `mapstructure:"http-body-limit"` // AllowUnprotectedTxs restricts unprotected (non EIP155 signed) transactions to be submitted via // the node's RPC when global parameter is disabled. AllowUnprotectedTxs bool `mapstructure:"allow-unprotected-txs"` @@ -318,28 +357,30 @@ 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, - WSOrigins: GetDefaultWSOrigins(), - EnableProfiling: DefaultEnableProfiling, + Enable: false, + API: GetDefaultAPINamespaces(), + Address: DefaultJSONRPCAddress, + WsAddress: DefaultJSONRPCWsAddress, + GasCap: DefaultGasCap, + AllowInsecureUnlock: DefaultJSONRPCAllowInsecureUnlock, + EVMTimeout: DefaultEVMTimeout, + TxFeeCap: DefaultTxFeeCap, + FilterTimeout: DefaultFilterTimeout, + FilterCleanupInterval: DefaultFilterCleanupInterval, + FeeHistoryCap: DefaultFeeHistoryCap, + BlockRangeCap: DefaultBlockRangeCap, + LogsCap: DefaultLogsCap, + HTTPTimeout: DefaultHTTPTimeout, + HTTPIdleTimeout: DefaultHTTPIdleTimeout, + HTTPBodyLimit: DefaultHTTPBodyLimit, + AllowUnprotectedTxs: DefaultAllowUnprotectedTxs, + BatchRequestLimit: DefaultBatchRequestLimit, + BatchResponseMaxSize: DefaultBatchResponseMaxSize, + MaxOpenConnections: DefaultMaxOpenConnections, + EnableIndexer: false, + MetricsAddress: DefaultJSONRPCMetricsAddress, + WSOrigins: GetDefaultWSOrigins(), + EnableProfiling: DefaultEnableProfiling, } } @@ -349,8 +390,12 @@ func (c JSONRPCConfig) Validate() error { return errors.New("cannot enable JSON-RPC without defining any API namespace") } - if c.FilterCap < 0 { - return errors.New("JSON-RPC filter-cap cannot be negative") + if c.FilterTimeout < 0 { + return errors.New("JSON-RPC filter-timeout cannot be negative") + } + + if c.FilterCleanupInterval < 0 { + return errors.New("JSON-RPC filter-cleanup-interval cannot be negative") } if c.FeeHistoryCap <= 0 { @@ -381,6 +426,10 @@ func (c JSONRPCConfig) Validate() error { return errors.New("JSON-RPC HTTP idle timeout duration cannot be negative") } + if c.HTTPBodyLimit <= 0 { + return errors.New("JSON-RPC HTTP body limit must be greater than 0") + } + if c.BatchRequestLimit < 0 { return errors.New("JSON-RPC batch request limit cannot be negative") } @@ -449,6 +498,11 @@ func GetConfig(v *viper.Viper) (Config, error) { if err := v.Unmarshal(conf); err != nil { return Config{}, fmt.Errorf("error extracting app config: %w", err) } + sdkConf, err := config.GetConfig(v) + if err != nil { + return Config{}, err + } + conf.GRPC.HistoricalGRPCAddressBlockRange = sdkConf.GRPC.HistoricalGRPCAddressBlockRange return *conf, nil } @@ -468,3 +522,43 @@ func (c Config) ValidateBasic() error { return c.Config.ValidateBasic() } + +// ValidateCrossConfig ensures compatibility between comet-bft (config.toml) and evm (app.toml) configs +func ValidateCrossConfig(cometBFT *cmtconfig.Config, app *Config) error { + errWrap := func(msg string, args ...any) error { + return errortypes.ErrAppConfig.Wrapf(msg, args...) + } + + if cometBFT == nil || app == nil { + return errWrap("comet and app configs are required") + } + + const ( + consensusMempoolApp = "app" + evmMempoolMaxTxsDisabled = -1 + ) + + var ( + cometAppMempoolEnabled = cometBFT.Mempool.Type == consensusMempoolApp + evmMempoolEnabled = app.Mempool.MaxTxs > evmMempoolMaxTxsDisabled + ) + + switch { + case cometAppMempoolEnabled == evmMempoolEnabled: + // all good (both enabled or both disabled) + return nil + case evmMempoolEnabled && !cometAppMempoolEnabled: + return errWrap( + "EVM mempool enabled, but comet-bft has invalid config.toml:mempool.type (want '%s', got '%s')", + consensusMempoolApp, + cometBFT.Mempool.Type, + ) + case cometAppMempoolEnabled && !evmMempoolEnabled: + return errWrap( + "CometBFT app-side mempool enabled, but EVM mempool is disabled (app.toml:mempool.max-txs=%d)", + app.Mempool.MaxTxs, + ) + } + + return nil +} diff --git a/server/config/config_test.go b/server/config/config_test.go index e5920a98..9f3bd1cf 100644 --- a/server/config/config_test.go +++ b/server/config/config_test.go @@ -4,10 +4,13 @@ import ( "fmt" "reflect" "testing" + "time" "github.com/spf13/viper" "github.com/stretchr/testify/require" + cmtcfg "github.com/cometbft/cometbft/config" + serverconfig "github.com/cosmos/evm/server/config" "github.com/cosmos/evm/testutil/constants" ) @@ -17,6 +20,44 @@ func TestDefaultConfig(t *testing.T) { require.False(t, cfg.JSONRPC.Enable) require.Equal(t, cfg.JSONRPC.Address, serverconfig.DefaultJSONRPCAddress) require.Equal(t, cfg.JSONRPC.WsAddress, serverconfig.DefaultJSONRPCWsAddress) + require.Equal(t, serverconfig.DefaultFilterTimeout, cfg.JSONRPC.FilterTimeout) + require.Equal(t, serverconfig.DefaultFilterCleanupInterval, cfg.JSONRPC.FilterCleanupInterval) + require.Equal(t, cfg.EVM.Mempool.CheckTxTimeout, 5*time.Second) + require.Equal(t, cfg.JSONRPC.HTTPBodyLimit, serverconfig.DefaultHTTPBodyLimit) +} + +func TestJSONRPCConfigValidate_FilterProtectionFields(t *testing.T) { + tests := []struct { + name string + mutate func(c *serverconfig.JSONRPCConfig) + errText string + }{ + { + name: "negative filter-timeout", + mutate: func(c *serverconfig.JSONRPCConfig) { + c.FilterTimeout = -1 + }, + errText: "filter-timeout cannot be negative", + }, + { + name: "negative cleanup interval", + mutate: func(c *serverconfig.JSONRPCConfig) { + c.FilterCleanupInterval = -1 + }, + errText: "filter-cleanup-interval cannot be negative", + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + cfg := *serverconfig.DefaultJSONRPCConfig() + tc.mutate(&cfg) + + err := cfg.Validate() + require.Error(t, err) + require.Contains(t, err.Error(), tc.errText) + }) + } } func TestGetConfig(t *testing.T) { @@ -69,3 +110,68 @@ func TestGetConfig(t *testing.T) { }) } } + +func TestValidateCrossConfig(t *testing.T) { + for _, tt := range []struct { + name string + cometType string + mempoolMaxTx int + nilCometCfg bool + errContains string + }{ + { + // both enabled + name: "comet-app:evm-on", + cometType: "app", + mempoolMaxTx: 0, + }, + { + name: "comet-flood:evm-off", + cometType: "flood", + mempoolMaxTx: 0, + errContains: "invalid config.toml:mempool.type", + }, + { + name: "comet-app:evm-off", + cometType: "app", + mempoolMaxTx: -1, + errContains: "EVM mempool is disabled", + }, + { + // both disabled + name: "comet-flood:evm-on", + mempoolMaxTx: -1, + cometType: "flood", + }, + // nil check + { + name: "nil comet config", + mempoolMaxTx: 0, + nilCometCfg: true, + errContains: "comet and app configs are required", + }, + } { + t.Run(tt.name, func(t *testing.T) { + // ARRANGE + appCfg := serverconfig.DefaultConfig() + appCfg.Mempool.MaxTxs = tt.mempoolMaxTx + + cometCfg := cmtcfg.DefaultConfig() + cometCfg.Mempool.Type = tt.cometType + + if tt.nilCometCfg { + cometCfg = nil + } + + // ACT + err := serverconfig.ValidateCrossConfig(cometCfg, appCfg) + + // ASSERT + if tt.errContains != "" { + require.ErrorContains(t, err, tt.errContains) + return + } + require.NoError(t, err) + }) + } +} diff --git a/server/config/migration/v0.50-app.toml b/server/config/migration/v0.50-app.toml index 0bebf82c..bfccc212 100644 --- a/server/config/migration/v0.50-app.toml +++ b/server/config/migration/v0.50-app.toml @@ -298,6 +298,9 @@ http-timeout = "30s" # HTTPIdleTimeout is the idle timeout of http json-rpc server. http-idle-timeout = "2m0s" +# HTTPBodyLimit is the maximum request body size in bytes for json-rpc http server. +http-body-limit = 5242880 + # AllowUnprotectedTxs restricts unprotected (non EIP155 signed) transactions to be submitted via # the node's RPC when the global parameter is disabled. allow-unprotected-txs = false diff --git a/server/config/opendb.go b/server/config/opendb.go index af6de8dc..1d0d99be 100644 --- a/server/config/opendb.go +++ b/server/config/opendb.go @@ -1,5 +1,4 @@ //go:build !rocksdb -// +build !rocksdb package config diff --git a/server/config/opendb_rocksdb.go b/server/config/opendb_rocksdb.go index f81aa027..be3903f5 100644 --- a/server/config/opendb_rocksdb.go +++ b/server/config/opendb_rocksdb.go @@ -1,5 +1,4 @@ //go:build rocksdb -// +build rocksdb package config diff --git a/server/config/toml.go b/server/config/toml.go index 60bd3402..80bb6589 100644 --- a/server/config/toml.go +++ b/server/config/toml.go @@ -52,6 +52,24 @@ global-queue = {{ .EVM.Mempool.GlobalQueue }} # Lifetime is the maximum amount of time non-executable transaction are queued lifetime = "{{ .EVM.Mempool.Lifetime }}" +# IncludedNonceCacheSize is the maximum amount of evm txs that can be tracked for +# removal via nonce invalidation. This should be >= the number of txs that can +# be included in a block. +included-nonce-cache-size = {{ .EVM.Mempool.IncludedNonceCacheSize }} + +# PendingTxProposalTimeout is the amount of time to spend waiting for rechecking of the mempool to complete when creating a proposal +pending-tx-proposal-timeout = "{{ .EVM.Mempool.PendingTxProposalTimeout }}" + +# CheckTxTimeout is the timeout for async CheckTx handler. +check-tx-timeout = "{{ .EVM.Mempool.CheckTxTimeout }}" + +# InsertQueueSize is the maximum number of transactions that can be in the insert queue at once (0 means unbounded) +insert-queue-size = "{{ .EVM.Mempool.InsertQueueSize }}" + +# EnableTxTracker enables per-tx lifecycle telemetry from the mempool +# (queued/pending/included latencies). Disabled by default. +enable-tx-tracker = {{ .EVM.Mempool.EnableTxTracker }} + ############################################################################### ### JSON RPC Configuration ### ############################################################################### @@ -87,8 +105,13 @@ evm-timeout = "{{ .JSONRPC.EVMTimeout }}" # TxFeeCap is the global tx-fee cap for send transaction. Default: 1eth. txfee-cap = {{ .JSONRPC.TxFeeCap }} -# FilterCap sets the global cap for total number of filters that can be created -filter-cap = {{ .JSONRPC.FilterCap }} +# FilterTimeout defines when an idle filter expires. +# Filters are reclaimed via this idle sweep (matching upstream go-ethereum); +# front the JSON-RPC server with a reverse proxy if you need rate limiting. +filter-timeout = "{{ .JSONRPC.FilterTimeout }}" + +# FilterCleanupInterval defines how often expired filters are cleaned up. +filter-cleanup-interval = "{{ .JSONRPC.FilterCleanupInterval }}" # FeeHistoryCap sets the global cap for total number of blocks that can be fetched feehistory-cap = {{ .JSONRPC.FeeHistoryCap }} @@ -105,6 +128,9 @@ http-timeout = "{{ .JSONRPC.HTTPTimeout }}" # HTTPIdleTimeout is the idle timeout of http json-rpc server. http-idle-timeout = "{{ .JSONRPC.HTTPIdleTimeout }}" +# HTTPBodyLimit is the maximum request body size in bytes for json-rpc http server. +http-body-limit = {{ .JSONRPC.HTTPBodyLimit }} + # AllowUnprotectedTxs restricts unprotected (non EIP155 signed) transactions to be submitted via # the node's RPC when the global parameter is disabled. allow-unprotected-txs = {{ .JSONRPC.AllowUnprotectedTxs }} diff --git a/server/flags/flags.go b/server/flags/flags.go index 9550a774..1ec9d84a 100644 --- a/server/flags/flags.go +++ b/server/flags/flags.go @@ -46,11 +46,11 @@ const ( JSONRPCAllowInsecureUnlock = "json-rpc.allow-insecure-unlock" JSONRPCEVMTimeout = "json-rpc.evm-timeout" JSONRPCTxFeeCap = "json-rpc.txfee-cap" - JSONRPCFilterCap = "json-rpc.filter-cap" JSONRPCLogsCap = "json-rpc.logs-cap" JSONRPCBlockRangeCap = "json-rpc.block-range-cap" JSONRPCHTTPTimeout = "json-rpc.http-timeout" JSONRPCHTTPIdleTimeout = "json-rpc.http-idle-timeout" + JSONRPCHTTPBodyLimit = "json-rpc.http-body-limit" JSONRPCAllowUnprotectedTxs = "json-rpc.allow-unprotected-txs" JSONRPCMaxOpenConnections = "json-rpc.max-open-connections" JSONRPCEnableIndexer = "json-rpc.enable-indexer" @@ -72,13 +72,18 @@ const ( EVMMinTip = "evm.min-tip" EvmGethMetricsAddress = "evm.geth-metrics-address" - EVMMempoolPriceLimit = "evm.mempool.price-limit" - EVMMempoolPriceBump = "evm.mempool.price-bump" - EVMMempoolAccountSlots = "evm.mempool.account-slots" - EVMMempoolGlobalSlots = "evm.mempool.global-slots" - EVMMempoolAccountQueue = "evm.mempool.account-queue" - EVMMempoolGlobalQueue = "evm.mempool.global-queue" - EVMMempoolLifetime = "evm.mempool.lifetime" + EVMMempoolPriceLimit = "evm.mempool.price-limit" + EVMMempoolPriceBump = "evm.mempool.price-bump" + EVMMempoolAccountSlots = "evm.mempool.account-slots" + EVMMempoolGlobalSlots = "evm.mempool.global-slots" + EVMMempoolAccountQueue = "evm.mempool.account-queue" + EVMMempoolGlobalQueue = "evm.mempool.global-queue" + EVMMempoolLifetime = "evm.mempool.lifetime" + EVMMempoolIncludedNonceCacheSize = "evm.mempool.included-nonce-cache-size" + EVMMempoolPendingTxProposalTimeout = "evm.mempool.pending-tx-proposal-timeout" + EVMMempoolCheckTxTimeout = "evm.mempool.check-tx-timeout" + EVMMempoolInsertQueueSize = "evm.mempool.insert-queue-size" + EVMMempoolEnableTxTracker = "evm.mempool.enable-tx-tracker" ) // TLS flags diff --git a/server/json_rpc.go b/server/json_rpc.go index c490d342..c5da5390 100644 --- a/server/json_rpc.go +++ b/server/json_rpc.go @@ -3,7 +3,6 @@ package server import ( "context" "fmt" - "log/slog" "net/http" "time" @@ -15,8 +14,8 @@ import ( rpcclient "github.com/cometbft/cometbft/rpc/client" - evmmempool "github.com/cosmos/evm/mempool" "github.com/cosmos/evm/rpc" + "github.com/cosmos/evm/rpc/backend" "github.com/cosmos/evm/rpc/stream" serverconfig "github.com/cosmos/evm/server/config" "github.com/cosmos/evm/server/types" @@ -40,7 +39,7 @@ func StartJSONRPC( config *serverconfig.Config, indexer types.EVMTxIndexer, app AppWithPendingTxStream, - mempool *evmmempool.ExperimentalEVMMempool, + mempool backend.Mempool, ) (*http.Server, error) { logger := srvCtx.Logger.With("module", "geth") @@ -52,17 +51,20 @@ func StartJSONRPC( stream := stream.NewRPCStreams(evtClient, logger, clientCtx.TxConfig.TxDecoder()) app.RegisterPendingTxListener(stream.ListenPendingTx) - // Set Geth's global logger to use this handler - handler := &CustomSlogHandler{logger: logger} - slog.SetDefault(slog.New(handler)) + evmBackend := backend.NewBackend( + srvCtx, + clientCtx, + indexer, + mempool, + backend.WithUnprotectedTxs(config.JSONRPC.AllowUnprotectedTxs), + backend.WithLogger(srvCtx.Logger), + ) - rpcServer := ethrpc.NewServer() + apis := rpc.BuildRPCs(config.JSONRPC.API, srvCtx, clientCtx, stream, evmBackend) + rpcServer := ethrpc.NewServer() rpcServer.SetBatchLimits(config.JSONRPC.BatchRequestLimit, config.JSONRPC.BatchResponseMaxSize) - allowUnprotectedTxs := config.JSONRPC.AllowUnprotectedTxs - rpcAPIArr := config.JSONRPC.API - - apis := rpc.GetRPCAPIs(srvCtx, clientCtx, stream, allowUnprotectedTxs, indexer, rpcAPIArr, mempool) + rpcServer.SetHTTPBodyLimit(config.JSONRPC.HTTPBodyLimit) for _, api := range apis { if err := rpcServer.RegisterName(api.Namespace, api.Service); err != nil { diff --git a/server/log_handler.go b/server/log_handler.go index b4077282..8695b3d8 100644 --- a/server/log_handler.go +++ b/server/log_handler.go @@ -4,17 +4,44 @@ import ( "context" "log/slog" - "cosmossdk.io/log" + evm "github.com/ethereum/go-ethereum/log" + + sdk "cosmossdk.io/log/v2" ) -// CustomSlogHandler bridges Geth's slog logs to the existing Cosmos SDK logger. -type CustomSlogHandler struct { - logger log.Logger +// slogAdapter bridges Geth's slog logs to the existing Cosmos SDK logger. +type slogAdapter struct { + logger sdk.Logger + level slog.Level +} + +// SetEVMLogger sets the default evm logger and the default slog logger +func SetEVMLogger(logger *slog.Logger, level slog.Level) { + // slog defaults + slog.SetDefault(logger) + slog.SetLogLoggerLevel(level) + + // evm logger defaults + evmLogger := evm.NewLogger(slog.Default().Handler()) + evm.SetDefault(evmLogger) +} + +// NewSlogFromCosmosLogger wraps cosmos sdk logger to slog +func NewSlogFromCosmosLogger(logger sdk.Logger, levelStr string) (*slog.Logger, slog.Level) { + a := &slogAdapter{ + logger: logger, + level: slog.LevelInfo, + } + + // try to parse or leave as info + _ = a.level.UnmarshalText([]byte(levelStr)) + + return slog.New(a), a.level } // Handle processes slog records and forwards them to your Cosmos SDK logger. -func (h *CustomSlogHandler) Handle(_ context.Context, r slog.Record) error { - attrs := []interface{}{} +func (a *slogAdapter) Handle(_ context.Context, r slog.Record) error { + attrs := []any{} r.Attrs(func(attr slog.Attr) bool { attrs = append(attrs, attr.Key, attr.Value.Any()) return true @@ -23,31 +50,42 @@ func (h *CustomSlogHandler) Handle(_ context.Context, r slog.Record) error { // Map slog levels to Cosmos SDK logger switch r.Level { case slog.LevelDebug: - h.logger.Debug(r.Message, attrs...) + a.logger.Debug(r.Message, attrs...) case slog.LevelInfo: - h.logger.Info(r.Message, attrs...) + a.logger.Info(r.Message, attrs...) case slog.LevelWarn: - h.logger.Warn(r.Message, attrs...) + a.logger.Warn(r.Message, attrs...) case slog.LevelError: - h.logger.Error(r.Message, attrs...) + a.logger.Error(r.Message, attrs...) default: - h.logger.Info(r.Message, attrs...) + a.logger.Info(r.Message, attrs...) } return nil } // Enabled determines if the handler should log a given level. -func (h *CustomSlogHandler) Enabled(_ context.Context, _ slog.Level) bool { - return true +func (a *slogAdapter) Enabled(_ context.Context, lvl slog.Level) bool { + return lvl >= a.level } // WithAttrs allows adding additional attributes. -func (h *CustomSlogHandler) WithAttrs(_ []slog.Attr) slog.Handler { - return h +func (a *slogAdapter) WithAttrs(attrs []slog.Attr) slog.Handler { + flatten := make([]any, 0, len(attrs)*2) + for _, attr := range attrs { + flatten = append(flatten, attr.Key, attr.Value.Any()) + } + + return &slogAdapter{ + logger: a.logger.With(flatten...), + level: a.level, + } } -// WithGroup is required to implement slog.Handler (not used). -func (h *CustomSlogHandler) WithGroup(_ string) slog.Handler { - return h +// WithGroup is required to implement slog.Handler +func (a *slogAdapter) WithGroup(group string) slog.Handler { + return &slogAdapter{ + logger: a.logger.With("group", group), + level: a.level, + } } diff --git a/config/server_app_options.go b/server/server_app_options.go similarity index 50% rename from config/server_app_options.go rename to server/server_app_options.go index c98f1bf2..59157518 100644 --- a/config/server_app_options.go +++ b/server/server_app_options.go @@ -1,36 +1,98 @@ -package config +package server import ( + "fmt" "math" "path/filepath" + "time" "github.com/holiman/uint256" "github.com/spf13/cast" + cmtcfg "github.com/cometbft/cometbft/config" + + evmmempool "github.com/cosmos/evm/mempool" "github.com/cosmos/evm/mempool/txpool/legacypool" srvflags "github.com/cosmos/evm/server/flags" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" "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" + sdkmempool "github.com/cosmos/cosmos-sdk/types/mempool" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" ) +const ( + cmtMempoolMaxTxBytesKey = "mempool.max_tx_bytes" + cmtMempoolReapMaxBytesKey = "mempool.reap_max_bytes" + cmtMempoolReapMaxGasKey = "mempool.reap_max_gas" +) + +// ValidateReapBounds errors when an admission cap exceeds the matching reap +// cap. A tx admitted via CheckTx that's larger than reap_max_bytes (or whose +// gas exceeds reap_max_gas) would wedge the head of the reap list. A zero reap +// cap means "no limit" on Comet's side — skip. +func ValidateReapBounds(appOpts servertypes.AppOptions, blockGasLimit uint64) error { + if appOpts == nil { + return nil + } + + // Fall back to Comet's default when max_tx_bytes is missing or 0 — viper + // returns nil for an absent key, cast.ToUint64(nil) is 0, and a 0 cap + // would silently bypass the comparison even though Comet's effective + // admission limit is 1 MiB. + maxTxBytes := cast.ToUint64(appOpts.Get(cmtMempoolMaxTxBytesKey)) + if maxTxBytes == 0 { + maxTxBytes = uint64(cmtcfg.DefaultMempoolConfig().MaxTxBytes) // #nosec G115 -- comet default is positive (1 MiB) + } + reapMaxBytes := cast.ToUint64(appOpts.Get(cmtMempoolReapMaxBytesKey)) + reapMaxGas := cast.ToUint64(appOpts.Get(cmtMempoolReapMaxGasKey)) + + if reapMaxBytes > 0 && maxTxBytes > reapMaxBytes { + return fmt.Errorf( + "mempool.max_tx_bytes (%d) must be <= mempool.reap_max_bytes (%d): "+ + "a tx admitted via CheckTx that exceeds reap_max_bytes would wedge the reap list", + maxTxBytes, reapMaxBytes, + ) + } + if reapMaxGas > 0 && blockGasLimit > reapMaxGas { + return fmt.Errorf( + "genesis consensus block.max_gas (%d) must be <= mempool.reap_max_gas (%d): "+ + "a tx admitted with gas up to block.max_gas that exceeds reap_max_gas would wedge the reap list", + blockGasLimit, reapMaxGas, + ) + } + return nil +} + +// ResolveMempoolConfig resolves the mempool configuration from the app options. +func ResolveMempoolConfig(anteHandler sdk.AnteHandler, appOpts servertypes.AppOptions, logger log.Logger) *evmmempool.Config { + return &evmmempool.Config{ + AnteHandler: anteHandler, + LegacyPoolConfig: GetLegacyPoolConfig(appOpts, logger), + BlockGasLimit: GetBlockGasLimit(appOpts, logger), + MinTip: GetMinTip(appOpts, logger), + PendingTxProposalTimeout: GetPendingTxProposalTimeout(appOpts, logger), + InsertQueueSize: GetMempoolInsertQueueSize(appOpts, logger), + EnableTxTracker: GetMempoolEnableTxTracker(appOpts), + } +} + // 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 { if appOpts == nil { - logger.Error("app options is nil, using zero block gas limit") - return math.MaxUint64 + logger.Error("app options is nil, using max int64 block gas limit") + return math.MaxInt64 } 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 + logger.Error("home directory not found in app options, using max int64 block gas limit") + return math.MaxInt64 } genesisPath := filepath.Join(homeDir, "config", "genesis.json") @@ -52,8 +114,8 @@ func GetBlockGasLimit(appOpts servertypes.AppOptions, logger log.Logger) uint64 maxGas := genDoc.ConsensusParams.Block.MaxGas if maxGas == -1 { - logger.Warn("genesis max_gas is unlimited (-1), using max uint64") - return math.MaxUint64 + logger.Warn("genesis max_gas is unlimited (-1), using max int64 block gas limit") + return math.MaxInt64 } if maxGas < -1 { logger.Error("invalid max_gas value in genesis, using zero block gas limit") @@ -136,6 +198,9 @@ func GetLegacyPoolConfig(appOpts servertypes.AppOptions, logger log.Logger) *leg if globalQueue := cast.ToUint64(appOpts.Get(srvflags.EVMMempoolGlobalQueue)); globalQueue != 0 { legacyConfig.GlobalQueue = globalQueue } + if includedNonceCacheSize := cast.ToInt(appOpts.Get(srvflags.EVMMempoolIncludedNonceCacheSize)); includedNonceCacheSize != 0 { + legacyConfig.IncludedNonceCacheSize = includedNonceCacheSize + } if lifetime := cast.ToDuration(appOpts.Get(srvflags.EVMMempoolLifetime)); lifetime != 0 { legacyConfig.Lifetime = lifetime } @@ -143,11 +208,55 @@ func GetLegacyPoolConfig(appOpts servertypes.AppOptions, logger log.Logger) *leg return &legacyConfig } -func GetCosmosPoolMaxTx(appOpts servertypes.AppOptions, logger log.Logger) int { +func GetPendingTxProposalTimeout(appOpts servertypes.AppOptions, logger log.Logger) time.Duration { if appOpts == nil { - logger.Error("app options is nil, using default cosmos pool max tx of -1 (no-op)") + logger.Error("app options is nil, using pending tx proposal timeout of 0 (unlimited)") return 0 } + return cast.ToDuration(appOpts.Get(srvflags.EVMMempoolPendingTxProposalTimeout)) +} + +func GetMempoolInsertQueueSize(appOpts servertypes.AppOptions, logger log.Logger) int { + if appOpts == nil { + logger.Error("app options is nil, using insert queue size of 5000") + return 5000 + } + + return cast.ToInt(appOpts.Get(srvflags.EVMMempoolInsertQueueSize)) +} + +// GetMempoolEnableTxTracker reads whether per-tx lifecycle telemetry should be +// recorded by the mempool. Defaults to false when not set or appOpts is nil. +func GetMempoolEnableTxTracker(appOpts servertypes.AppOptions) bool { + if appOpts == nil { + return false + } + return cast.ToBool(appOpts.Get(srvflags.EVMMempoolEnableTxTracker)) +} + +func GetMempoolCheckTxTimeout(appOpts servertypes.AppOptions, logger log.Logger) time.Duration { + if appOpts == nil { + logger.Error("app options is nil, using check tx timeout of 5 seconds") + return 5 * time.Second + } + + dur := cast.ToDuration(appOpts.Get(srvflags.EVMMempoolCheckTxTimeout)) + if dur <= 0 { + logger.Error("check tx timeout must be greater than 0, using 5 seconds") + return 5 * time.Second + } + + return dur +} + +func GetCosmosPoolMaxTx(appOpts servertypes.AppOptions, logger log.Logger) int { + if appOpts == nil { + // we don't want to return 0 here, as then appOpts.Get() will return nil and that will be + // "accidentally" cast to the correct evm max tx default of 0, thereby hiding the error + logger.Error("app options is nil, using sdk max tx default of -1 (no-op)") + return sdkmempool.DefaultMaxTx + } + return cast.ToInt(appOpts.Get(sdkserver.FlagMempoolMaxTxs)) } diff --git a/config/server_app_options_test.go b/server/server_app_options_test.go similarity index 75% rename from config/server_app_options_test.go rename to server/server_app_options_test.go index ee4ed2ff..09dd1e2f 100644 --- a/config/server_app_options_test.go +++ b/server/server_app_options_test.go @@ -1,4 +1,4 @@ -package config +package server import ( "encoding/json" @@ -10,7 +10,9 @@ import ( "github.com/stretchr/testify/require" - "cosmossdk.io/log" + cmtcfg "github.com/cometbft/cometbft/config" + + "cosmossdk.io/log/v2" sdkmath "cosmossdk.io/math" "github.com/cosmos/cosmos-sdk/client/flags" @@ -46,12 +48,12 @@ func TestGetBlockGasLimit(t *testing.T) { expected uint64 }{ { - name: "empty home directory returns max uint64", + name: "empty home directory returns max int64", setupFn: func() servertypes.AppOptions { opts := newMockAppOptions() return opts }, - expected: math.MaxUint64, + expected: math.MaxInt64, }, { name: "genesis file not found returns 0", @@ -63,14 +65,14 @@ func TestGetBlockGasLimit(t *testing.T) { expected: 0, }, { - name: "valid genesis with max_gas = -1 returns max uint64", + name: "valid genesis with max_gas = -1 returns max int64", setupFn: func() servertypes.AppOptions { homeDir := createGenesisWithMaxGas(t, -1) opts := newMockAppOptions() opts.Set(flags.FlagHome, homeDir) return opts }, - expected: math.MaxUint64, + expected: math.MaxInt64, }, { name: "valid genesis with max_gas < -1 returns 0", @@ -330,3 +332,89 @@ func createInvalidGenesis(t *testing.T) string { return tempDir } + +func TestValidateReapBounds(t *testing.T) { + t.Parallel() + + cometDefaultMaxTxBytes := uint64(cmtcfg.DefaultMempoolConfig().MaxTxBytes) // #nosec G115 -- comet default is positive (1 MiB) + + tests := []struct { + name string + omitMaxTxBytes bool + maxTxBytes uint64 + reapMaxBytes uint64 + reapMaxGas uint64 + blockGasLimit uint64 + nilOpts bool + wantErr string + }{ + { + name: "nil app options is a no-op", + nilOpts: true, + }, + { + name: "default reap caps (zero) accept any admission caps", + maxTxBytes: 1 << 20, + blockGasLimit: 100_000_000, + }, + { + name: "max_tx_bytes equal to reap_max_bytes is allowed", + maxTxBytes: 500_000, + reapMaxBytes: 500_000, + blockGasLimit: 100_000, + reapMaxGas: 100_000, + }, + { + name: "max_tx_bytes above reap_max_bytes is rejected", + maxTxBytes: 1 << 20, + reapMaxBytes: 500_000, + wantErr: "mempool.max_tx_bytes (1048576) must be <= mempool.reap_max_bytes (500000)", + }, + { + name: "block_gas_limit above reap_max_gas is rejected", + blockGasLimit: 100_000_000, + reapMaxGas: 50_000_000, + wantErr: "genesis consensus block.max_gas (100000000) must be <= mempool.reap_max_gas (50000000)", + }, + { + name: "bytes-axis fires before gas-axis when both are misconfigured", + maxTxBytes: 1 << 20, + reapMaxBytes: 500_000, + blockGasLimit: 100_000_000, + reapMaxGas: 50_000_000, + wantErr: "mempool.max_tx_bytes", + }, + { + // Greptile P1: viper read returning 0 must not silently bypass the check. + name: "missing max_tx_bytes falls back to comet default and is rejected against a smaller reap cap", + omitMaxTxBytes: true, + reapMaxBytes: cometDefaultMaxTxBytes - 1, + wantErr: fmt.Sprintf("mempool.max_tx_bytes (%d) must be", cometDefaultMaxTxBytes), + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + var opts servertypes.AppOptions + if !tc.nilOpts { + m := newMockAppOptions() + if !tc.omitMaxTxBytes { + m.Set(cmtMempoolMaxTxBytesKey, tc.maxTxBytes) + } + m.Set(cmtMempoolReapMaxBytesKey, tc.reapMaxBytes) + m.Set(cmtMempoolReapMaxGasKey, tc.reapMaxGas) + opts = m + } + + err := ValidateReapBounds(opts, tc.blockGasLimit) + if tc.wantErr == "" { + require.NoError(t, err) + return + } + require.Error(t, err) + require.Contains(t, err.Error(), tc.wantErr) + }) + } +} diff --git a/server/start.go b/server/start.go index 72577885..90538920 100644 --- a/server/start.go +++ b/server/start.go @@ -3,17 +3,15 @@ package server import ( "context" "fmt" - "io" - "net" "os" "path/filepath" "runtime/pprof" ethmetricsexp "github.com/ethereum/go-ethereum/metrics/exp" "github.com/spf13/cobra" + "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" "golang.org/x/sync/errgroup" "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" abciserver "github.com/cometbft/cometbft/abci/server" tcmd "github.com/cometbft/cometbft/cmd/cometbft/commands" @@ -30,25 +28,23 @@ import ( "github.com/cosmos/evm/indexer" evmmempool "github.com/cosmos/evm/mempool" evmmetrics "github.com/cosmos/evm/metrics" + "github.com/cosmos/evm/rpc/backend" ethdebug "github.com/cosmos/evm/rpc/namespaces/ethereum/debug" cosmosevmserverconfig "github.com/cosmos/evm/server/config" srvflags "github.com/cosmos/evm/server/flags" servertypes "github.com/cosmos/evm/server/types" - errorsmod "cosmossdk.io/errors" - "cosmossdk.io/log" - pruningtypes "cosmossdk.io/store/pruning/types" + "cosmossdk.io/log/v2" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/server" "github.com/cosmos/cosmos-sdk/server/api" serverconfig "github.com/cosmos/cosmos-sdk/server/config" - servergrpc "github.com/cosmos/cosmos-sdk/server/grpc" servercmtlog "github.com/cosmos/cosmos-sdk/server/log" "github.com/cosmos/cosmos-sdk/server/types" + pruningtypes "github.com/cosmos/cosmos-sdk/store/v2/pruning/types" "github.com/cosmos/cosmos-sdk/telemetry" sdkmempool "github.com/cosmos/cosmos-sdk/types/mempool" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" @@ -61,11 +57,10 @@ type Application interface { types.Application AppWithPendingTxStream GetMempool() sdkmempool.ExtMempool - SetClientCtx(clientCtx client.Context) } // AppCreator is a function that allows us to lazily initialize an application implementing with AppWithPendingTxStream. -type AppCreator func(log.Logger, dbm.DB, io.Writer, types.AppOptions) Application +type AppCreator func(log.Logger, dbm.DB, types.AppOptions) Application // StartOptions defines options that can be customized in `StartCmd` type StartOptions struct { @@ -77,8 +72,8 @@ type StartOptions struct { // NewDefaultStartOptions use the default db opener provided in tm-db. func NewDefaultStartOptions(appCreator AppCreator, defaultNodeHome string) StartOptions { return StartOptions{ - AppCreator: func(l log.Logger, d dbm.DB, w io.Writer, ao types.AppOptions) types.Application { - return appCreator(l, d, w, ao) + AppCreator: func(l log.Logger, d dbm.DB, ao types.AppOptions) types.Application { + return appCreator(l, d, ao) }, DefaultNodeHome: defaultNodeHome, DBOpener: cosmosevmserverconfig.OpenDB, @@ -133,11 +128,16 @@ which accepts a path for the resulting pprof file. return err } + otelFile := filepath.Join(clientCtx.HomeDir, "config", telemetry.OtelFileName) + if err := telemetry.InitializeOpenTelemetry(otelFile); err != nil { + return fmt.Errorf("failed to initialize OpenTelemetry: %w", err) + } + 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) + return startStandAlone(serverCtx, opts) }) } @@ -184,7 +184,12 @@ which accepts a path for the resulting pprof file. cmd.Flags().Uint(server.FlagInvCheckPeriod, 0, "Assert registered invariants every N blocks") cmd.Flags().Uint64(server.FlagMinRetainBlocks, 0, "Minimum block height offset during ABCI commit to prune CometBFT blocks") cmd.Flags().String(srvflags.AppDBBackend, "", "The type of database for application and snapshots databases") - cmd.Flags().Int32(server.FlagMempoolMaxTxs, 0, "The maximum number of transactions in the mempool") + + cmd.Flags().Int(server.FlagMempoolMaxTxs, 0, "The maximum number of transactions in the mempool") + // explicitly override the app.toml default value, as normally config file takes precedence over flag defaults + if err := cmd.Flags().Set(server.FlagMempoolMaxTxs, "0"); err != nil { + panic(err) + } cmd.Flags().Bool(srvflags.GRPCOnly, false, "Start the node in gRPC query only mode without CometBFT process") cmd.Flags().Bool(srvflags.GRPCEnable, cosmosevmserverconfig.DefaultGRPCEnable, "Define if the gRPC server should be enabled") @@ -203,10 +208,10 @@ which accepts a path for the resulting pprof file. cmd.Flags().Uint64(srvflags.JSONRPCGasCap, cosmosevmserverconfig.DefaultGasCap, "Sets a cap on gas that can be used in eth_call/estimateGas unit is aatom (0=infinite)") //nolint:lll cmd.Flags().Bool(srvflags.JSONRPCAllowInsecureUnlock, cosmosevmserverconfig.DefaultJSONRPCAllowInsecureUnlock, "Allow insecure account unlocking when account-related RPCs are exposed by http") //nolint:lll cmd.Flags().Float64(srvflags.JSONRPCTxFeeCap, cosmosevmserverconfig.DefaultTxFeeCap, "Sets a cap on transaction fee that can be sent via the RPC APIs (1 = default 1 evmos)") //nolint:lll - cmd.Flags().Int32(srvflags.JSONRPCFilterCap, cosmosevmserverconfig.DefaultFilterCap, "Sets the global cap for total number of filters that can be created") cmd.Flags().Duration(srvflags.JSONRPCEVMTimeout, cosmosevmserverconfig.DefaultEVMTimeout, "Sets a timeout used for eth_call (0=infinite)") cmd.Flags().Duration(srvflags.JSONRPCHTTPTimeout, cosmosevmserverconfig.DefaultHTTPTimeout, "Sets a read/write timeout for json-rpc http server (0=infinite)") cmd.Flags().Duration(srvflags.JSONRPCHTTPIdleTimeout, cosmosevmserverconfig.DefaultHTTPIdleTimeout, "Sets a idle timeout for json-rpc http server (0=infinite)") + cmd.Flags().Int(srvflags.JSONRPCHTTPBodyLimit, cosmosevmserverconfig.DefaultHTTPBodyLimit, "Sets max request body size in bytes for json-rpc http server") cmd.Flags().Bool(srvflags.JSONRPCAllowUnprotectedTxs, cosmosevmserverconfig.DefaultAllowUnprotectedTxs, "Allow for unprotected (non EIP155 signed) transactions to be submitted via the node's RPC when the global parameter is disabled") //nolint:lll cmd.Flags().Int(srvflags.JSONRPCBatchRequestLimit, cosmosevmserverconfig.DefaultBatchRequestLimit, "Maximum number of requests in a batch") cmd.Flags().Int(srvflags.JSONRPCBatchResponseMaxSize, cosmosevmserverconfig.DefaultBatchResponseMaxSize, "Maximum size of server response") @@ -224,13 +229,20 @@ which accepts a path for the resulting pprof file. 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().Uint64(srvflags.EVMMempoolPriceLimit, cosmosevmserverconfig.DefaultMempoolConfig().PriceLimit, "the minimum gas price to enforce for acceptance into the pool (in wei)") - cmd.Flags().Uint64(srvflags.EVMMempoolPriceBump, cosmosevmserverconfig.DefaultMempoolConfig().PriceBump, "the minimum price bump percentage to replace an already existing transaction (nonce)") - cmd.Flags().Uint64(srvflags.EVMMempoolAccountSlots, cosmosevmserverconfig.DefaultMempoolConfig().AccountSlots, "the number of executable transaction slots guaranteed per account") - cmd.Flags().Uint64(srvflags.EVMMempoolGlobalSlots, cosmosevmserverconfig.DefaultMempoolConfig().GlobalSlots, "the maximum number of executable transaction slots for all accounts") - cmd.Flags().Uint64(srvflags.EVMMempoolAccountQueue, cosmosevmserverconfig.DefaultMempoolConfig().AccountQueue, "the maximum number of non-executable transaction slots permitted per account") - cmd.Flags().Uint64(srvflags.EVMMempoolGlobalQueue, cosmosevmserverconfig.DefaultMempoolConfig().GlobalQueue, "the maximum number of non-executable transaction slots for all accounts") - cmd.Flags().Duration(srvflags.EVMMempoolLifetime, cosmosevmserverconfig.DefaultMempoolConfig().Lifetime, "the maximum amount of time non-executable transaction are queued") + mpDefaults := cosmosevmserverconfig.DefaultMempoolConfig() + + cmd.Flags().Uint64(srvflags.EVMMempoolPriceLimit, mpDefaults.PriceLimit, "the minimum gas price to enforce for acceptance into the pool (in wei)") + cmd.Flags().Uint64(srvflags.EVMMempoolPriceBump, mpDefaults.PriceBump, "the minimum price bump percentage to replace an already existing transaction (nonce)") + cmd.Flags().Uint64(srvflags.EVMMempoolAccountSlots, mpDefaults.AccountSlots, "the number of executable transaction slots guaranteed per account") + cmd.Flags().Uint64(srvflags.EVMMempoolGlobalSlots, mpDefaults.GlobalSlots, "the maximum number of executable transaction slots for all accounts") + cmd.Flags().Uint64(srvflags.EVMMempoolAccountQueue, mpDefaults.AccountQueue, "the maximum number of non-executable transaction slots permitted per account") + cmd.Flags().Uint64(srvflags.EVMMempoolGlobalQueue, mpDefaults.GlobalQueue, "the maximum number of non-executable transaction slots for all accounts") + cmd.Flags().Duration(srvflags.EVMMempoolLifetime, mpDefaults.Lifetime, "the maximum amount of time non-executable transaction are queued") + cmd.Flags().Int(srvflags.EVMMempoolIncludedNonceCacheSize, mpDefaults.IncludedNonceCacheSize, "the maximum amount of nonces in the included cache") + cmd.Flags().Duration(srvflags.EVMMempoolPendingTxProposalTimeout, mpDefaults.PendingTxProposalTimeout, "the maximum amount of time to spend waiting for rechecking of the mempool to complete when creating a proposal") + cmd.Flags().Duration(srvflags.EVMMempoolCheckTxTimeout, mpDefaults.CheckTxTimeout, "timeout for async CheckTx handler") + cmd.Flags().Int(srvflags.EVMMempoolInsertQueueSize, mpDefaults.InsertQueueSize, "the maximum number of transactions that can be in the insert queue at once") + cmd.Flags().Bool(srvflags.EVMMempoolEnableTxTracker, mpDefaults.EnableTxTracker, "enable per-tx lifecycle telemetry from the mempool (queued/pending/included latencies)") 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") @@ -247,7 +259,7 @@ which accepts a path for the resulting pprof file. // Parameters: // - svrCtx: The context object that holds server configurations, logger, and other stateful information. // - opts: Options for starting the server, including functions for creating the application and opening the database. -func startStandAlone(svrCtx *server.Context, clientCtx client.Context, opts StartOptions) error { +func startStandAlone(svrCtx *server.Context, opts StartOptions) error { addr := svrCtx.Viper.GetString(srvflags.Address) transport := svrCtx.Viper.GetString(srvflags.Transport) home := svrCtx.Viper.GetString(flags.FlagHome) @@ -266,23 +278,19 @@ func startStandAlone(svrCtx *server.Context, clientCtx client.Context, opts Star } }() - traceWriterFile := svrCtx.Viper.GetString(srvflags.TraceStore) - traceWriter, err := openTraceWriter(traceWriterFile) - if err != nil { - return err - } + SetEVMLogger( + NewSlogFromCosmosLogger( + svrCtx.Logger.With("module", "evm"), + svrCtx.Config.LogLevel, + ), + ) - app = opts.AppCreator(svrCtx.Logger, db, traceWriter, svrCtx.Viper) + app = opts.AppCreator(svrCtx.Logger, db, svrCtx.Viper) defer func() { if err := app.Close(); err != nil { svrCtx.Logger.Error("close application failed", "error", err.Error()) } }() - evmApp, ok := app.(Application) - if !ok { - svrCtx.Logger.Error("failed to get server config", "error", err.Error()) - } - evmApp.SetClientCtx(clientCtx) config, err := cosmosevmserverconfig.GetConfig(svrCtx.Viper) if err != nil { @@ -295,6 +303,11 @@ func startStandAlone(svrCtx *server.Context, clientCtx client.Context, opts Star return err } + if err := cosmosevmserverconfig.ValidateCrossConfig(svrCtx.Config, &config); err != nil { + svrCtx.Logger.Error("configs mismatch", "error", err.Error()) + return err + } + _, err = startTelemetry(config) if err != nil { return err @@ -373,13 +386,6 @@ func startInProcess(svrCtx *server.Context, clientCtx client.Context, opts Start } }() - traceWriterFile := svrCtx.Viper.GetString(srvflags.TraceStore) - traceWriter, err := openTraceWriter(traceWriterFile) - if err != nil { - logger.Error("failed to open trace writer", "error", err.Error()) - return err - } - config, err := cosmosevmserverconfig.GetConfig(svrCtx.Viper) if err != nil { logger.Error("failed to get server config", "error", err.Error()) @@ -391,7 +397,19 @@ func startInProcess(svrCtx *server.Context, clientCtx client.Context, opts Start return err } - app = opts.AppCreator(svrCtx.Logger, db, traceWriter, svrCtx.Viper) + if err := cosmosevmserverconfig.ValidateCrossConfig(svrCtx.Config, &config); err != nil { + logger.Error("configs mismatch", "error", err.Error()) + return err + } + + SetEVMLogger( + NewSlogFromCosmosLogger( + svrCtx.Logger.With("module", "evm"), + svrCtx.Config.LogLevel, + ), + ) + + app = opts.AppCreator(svrCtx.Logger, db, svrCtx.Viper) defer func() { if err := app.Close(); err != nil { logger.Error("close application failed", "error", err.Error()) @@ -401,7 +419,6 @@ func startInProcess(svrCtx *server.Context, clientCtx client.Context, opts Start if !ok { svrCtx.Logger.Error("failed to get server config", "error", err.Error()) } - evmApp.SetClientCtx(clientCtx) nodeKey, err := p2p.LoadOrGenNodeKey(cfg.NodeKeyFile()) if err != nil { @@ -444,7 +461,10 @@ func startInProcess(svrCtx *server.Context, clientCtx client.Context, opts Start return err } - if m, ok := evmApp.GetMempool().(*evmmempool.ExperimentalEVMMempool); ok && m != nil { + type EventBusser interface { + SetEventBus(eventBus *cmttypes.EventBus) + } + if m, ok := evmApp.GetMempool().(EventBusser); ok && m != nil { m.SetEventBus(bftNode.EventBus()) } defer func() { @@ -463,6 +483,11 @@ func startInProcess(svrCtx *server.Context, clientCtx client.Context, opts Start app.RegisterTxService(clientCtx) app.RegisterTendermintService(clientCtx) app.RegisterNodeService(clientCtx, config.Config) + + // Set the clientCtx into the mempool + if m, ok := evmApp.GetMempool().(*evmmempool.Mempool); ok && m != nil { + m.SetClientCtx(clientCtx) + } } metrics, err := startTelemetry(config) @@ -524,13 +549,12 @@ func startInProcess(svrCtx *server.Context, clientCtx client.Context, opts Start WithChainID(genDoc.ChainID) } - grpcSrv, clientCtx, err := startGrpcServer(ctx, svrCtx, clientCtx, g, config.GRPC, app) + grpcSrv, clientCtx, err := server.StartGrpcServer(ctx, g, config.GRPC, clientCtx, svrCtx, app, + grpc.WithStatsHandler(otelgrpc.NewClientHandler()), + ) if err != nil { return err } - if grpcSrv != nil { - defer grpcSrv.GracefulStop() - } startAPIServer(ctx, svrCtx, clientCtx, g, config.Config, app, grpcSrv, metrics, config.EVM.GethMetricsAddress) @@ -539,9 +563,15 @@ func startInProcess(svrCtx *server.Context, clientCtx client.Context, opts Start if !ok { return fmt.Errorf("json-rpc server requires AppWithPendingTxStream") } - _, err = StartJSONRPC(ctx, svrCtx, clientCtx, g, &config, idxer, txApp, evmApp.GetMempool().(*evmmempool.ExperimentalEVMMempool)) + + mp, ok := evmApp.GetMempool().(backend.Mempool) + if !ok { + return fmt.Errorf("json-rpc server requires backend.Mempool") + } + + _, err = StartJSONRPC(ctx, svrCtx, clientCtx, g, &config, idxer, txApp, mp) if err != nil { - return err + return fmt.Errorf("failed to start json-rpc server: %w", err) } } @@ -564,22 +594,6 @@ func OpenIndexerDB(rootDir string, backendType dbm.BackendType) (dbm.DB, error) return dbm.NewDB("evmindexer", backendType, dataDir) } -// openTraceWriter opens a trace writer if a trace store file is specified. -// Parameters: -// - traceWriterFile: The path to the trace store file. If this is an empty string, no file will be opened. -func openTraceWriter(traceWriterFile string) (w io.Writer, err error) { - if traceWriterFile == "" { - return - } - - filePath := filepath.Clean(traceWriterFile) - return os.OpenFile( - filePath, - os.O_WRONLY|os.O_APPEND|os.O_CREATE, - 0o600, - ) -} - func startTelemetry(cfg cosmosevmserverconfig.Config) (*telemetry.Metrics, error) { if !cfg.Telemetry.Enabled { return nil, nil @@ -625,65 +639,6 @@ func getCtx(svrCtx *server.Context, block bool) (*errgroup.Group, context.Contex return g, ctx } -// startGrpcServer starts a gRPC server based on the provided configuration. -func startGrpcServer( - ctx context.Context, - svrCtx *server.Context, - clientCtx client.Context, - g *errgroup.Group, - config serverconfig.GRPCConfig, - app types.Application, -) (*grpc.Server, client.Context, error) { - if !config.Enable { - // return grpcServer as nil if gRPC is disabled - return nil, clientCtx, nil - } - _, _, err := net.SplitHostPort(config.Address) - if err != nil { - return nil, clientCtx, errorsmod.Wrapf(err, "invalid grpc address %s", config.Address) - } - - maxSendMsgSize := config.MaxSendMsgSize - if maxSendMsgSize == 0 { - maxSendMsgSize = serverconfig.DefaultGRPCMaxSendMsgSize - } - - maxRecvMsgSize := config.MaxRecvMsgSize - if maxRecvMsgSize == 0 { - maxRecvMsgSize = serverconfig.DefaultGRPCMaxRecvMsgSize - } - - // if gRPC is enabled, configure gRPC client for gRPC gateway and json-rpc - grpcClient, err := grpc.NewClient( - config.Address, - grpc.WithTransportCredentials(insecure.NewCredentials()), - grpc.WithDefaultCallOptions( - grpc.ForceCodec(codec.NewProtoCodec(clientCtx.InterfaceRegistry).GRPCCodec()), - grpc.MaxCallRecvMsgSize(maxRecvMsgSize), - grpc.MaxCallSendMsgSize(maxSendMsgSize), - ), - ) - if err != nil { - return nil, clientCtx, err - } - // Set `GRPCClient` to `clientCtx` to enjoy concurrent grpc query. - // only use it if gRPC server is enabled. - clientCtx = clientCtx.WithGRPCClient(grpcClient) - svrCtx.Logger.Debug("gRPC client assigned to client context", "address", config.Address) - - grpcSrv, err := servergrpc.NewGRPCServer(clientCtx, app, config) - if err != nil { - return nil, clientCtx, err - } - - // Start the gRPC server in a goroutine. Note, the provided ctx will ensure - // that the server is gracefully shut down. - g.Go(func() error { - return servergrpc.StartGRPCServer(ctx, svrCtx.Logger.With("module", "grpc-server"), config, grpcSrv) - }) - return grpcSrv, clientCtx, nil -} - // startAPIServer starts an API server based on the provided configuration and application context. // Parameters: // - ctx: The context used for managing the server's lifecycle, allowing for graceful shutdown. diff --git a/server/util.go b/server/util.go index c5d47328..940a457d 100644 --- a/server/util.go +++ b/server/util.go @@ -13,7 +13,7 @@ import ( "github.com/cosmos/evm/server/config" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" sdkserver "github.com/cosmos/cosmos-sdk/server" "github.com/cosmos/cosmos-sdk/server/types" diff --git a/tests/evm-tools-compatibility/hardhat/package-lock.json b/tests/evm-tools-compatibility/hardhat/package-lock.json index e7c043e9..e7e9faaa 100644 --- a/tests/evm-tools-compatibility/hardhat/package-lock.json +++ b/tests/evm-tools-compatibility/hardhat/package-lock.json @@ -6,7 +6,7 @@ "": { "name": "hardhat-project", "dependencies": { - "@openzeppelin/contracts": "^5.3.0" + "@openzeppelin/contracts": "^5.4.0" }, "devDependencies": { "@nomicfoundation/hardhat-chai-matchers": "^2.0.9", @@ -1374,9 +1374,9 @@ } }, "node_modules/@openzeppelin/contracts": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.3.0.tgz", - "integrity": "sha512-zj/KGoW7zxWUE8qOI++rUM18v+VeLTTzKs/DJFkSzHpQFPD/jKKF0TrMxBfGLl3kpdELCNccvB3zmofSzm4nlA==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.4.0.tgz", + "integrity": "sha512-eCYgWnLg6WO+X52I16TZt8uEjbtdkgLC0SUX/xnAksjjrQI4Xfn4iBRoI5j55dmlOhDv1Y7BoR3cU7e3WWhC6A==", "license": "MIT" }, "node_modules/@scure/base": { @@ -2121,6 +2121,22 @@ "node": ">= 4.0.0" } }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/axios": { "version": "1.8.4", "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz", @@ -2221,9 +2237,9 @@ } }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", "dev": true, "license": "MIT", "dependencies": { @@ -2318,6 +2334,25 @@ "node": ">= 0.8" } }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", @@ -2478,14 +2513,15 @@ "license": "MIT" }, "node_modules/cipher-base": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.6.tgz", - "integrity": "sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.7.tgz", + "integrity": "sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==", "dev": true, "license": "MIT", "dependencies": { "inherits": "^2.0.4", - "safe-buffer": "^5.2.1" + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.2" }, "engines": { "node": ">= 0.10" @@ -2906,9 +2942,9 @@ "dev": true }, "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -2966,6 +3002,24 @@ "dev": true, "license": "MIT" }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -2987,9 +3041,9 @@ } }, "node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.2.tgz", + "integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -3663,16 +3717,33 @@ } } }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/form-data": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", - "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { @@ -3984,9 +4055,9 @@ } }, "node_modules/globby/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", "dev": true, "license": "MIT", "dependencies": { @@ -4050,9 +4121,9 @@ "license": "ISC" }, "node_modules/handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "version": "4.7.9", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz", + "integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4429,6 +4500,19 @@ "node": ">=8" } }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", @@ -4459,20 +4543,61 @@ } }, "node_modules/hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.2.tgz", + "integrity": "sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==", "dev": true, "license": "MIT", "dependencies": { "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.1" }, "engines": { - "node": ">=4" + "node": ">= 0.8" + } + }, + "node_modules/hash-base/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hash-base/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/hash-base/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" } }, + "node_modules/hash-base/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, "node_modules/hash.js": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", @@ -4626,9 +4751,9 @@ } }, "node_modules/immutable": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz", - "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==", + "version": "4.3.8", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.8.tgz", + "integrity": "sha512-d/Ld9aLbKpNwyl0KiM2CT1WYvkitQ1TSvmRtkcV8FKStiDoA7Slzgjmb/1G2yhKM1p0XeNOieaTbFZmU1d3Xuw==", "dev": true, "license": "MIT" }, @@ -4711,6 +4836,19 @@ "node": ">=8" } }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -4775,6 +4913,22 @@ "node": ">=8" } }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", @@ -4810,9 +4964,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "license": "MIT", "dependencies": { @@ -5639,20 +5793,21 @@ } }, "node_modules/pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.5.tgz", + "integrity": "sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ==", "dev": true, "license": "MIT", "dependencies": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "ripemd160": "^2.0.3", + "safe-buffer": "^5.2.1", + "sha.js": "^2.4.12", + "to-buffer": "^1.2.1" }, "engines": { - "node": ">=0.12" + "node": ">= 0.10" } }, "node_modules/picocolors": { @@ -5663,9 +5818,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", "engines": { @@ -5685,6 +5840,16 @@ "node": ">=6" } }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -5750,9 +5915,9 @@ "license": "MIT" }, "node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", + "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -5867,9 +6032,9 @@ } }, "node_modules/recursive-readdir/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", "dev": true, "license": "MIT", "dependencies": { @@ -5981,14 +6146,17 @@ } }, "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.3.tgz", + "integrity": "sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==", "dev": true, "license": "MIT", "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" + "hash-base": "^3.1.2", + "inherits": "^2.0.4" + }, + "engines": { + "node": ">= 0.8" } }, "node_modules/rlp": { @@ -6093,9 +6261,9 @@ } }, "node_modules/sc-istanbul/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", "dev": true, "license": "MIT", "dependencies": { @@ -6132,9 +6300,9 @@ } }, "node_modules/sc-istanbul/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "dev": true, "license": "MIT", "dependencies": { @@ -6242,6 +6410,24 @@ "randombytes": "^2.1.0" } }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", @@ -6257,17 +6443,24 @@ "license": "ISC" }, "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz", + "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==", "dev": true, "license": "(MIT AND BSD-3-Clause)", "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.0" }, "bin": { "sha.js": "bin.js" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/sha1": { @@ -6303,9 +6496,9 @@ } }, "node_modules/shelljs/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", "dev": true, "license": "MIT", "dependencies": { @@ -6938,15 +7131,16 @@ "license": "MIT" }, "node_modules/then-request/node_modules/form-data": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.3.tgz", - "integrity": "sha512-XHIrMD0NpDrNM/Ckf7XJiBbLl57KEhT3+i3yY+eWm+cqYZJQTZrKo8Y8AWKnuV5GT4scfuUGt9LzNoIx3dU1nQ==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.5.tgz", + "integrity": "sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A==", "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.35", "safe-buffer": "^5.2.1" }, @@ -6998,9 +7192,9 @@ } }, "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -7023,6 +7217,28 @@ "node": ">=0.6.0" } }, + "node_modules/to-buffer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz", + "integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "isarray": "^2.0.5", + "safe-buffer": "^5.2.1", + "typed-array-buffer": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/to-buffer/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -7117,9 +7333,9 @@ } }, "node_modules/ts-node/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -7203,9 +7419,9 @@ } }, "node_modules/typechain/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", "dev": true, "license": "MIT", "dependencies": { @@ -7296,6 +7512,21 @@ "node": ">= 4.0.0" } }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -7512,6 +7743,28 @@ "which": "bin/which" } }, + "node_modules/which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/widest-line": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", diff --git a/tests/evm-tools-compatibility/hardhat/package.json b/tests/evm-tools-compatibility/hardhat/package.json index 889de6fa..5e799641 100644 --- a/tests/evm-tools-compatibility/hardhat/package.json +++ b/tests/evm-tools-compatibility/hardhat/package.json @@ -21,6 +21,6 @@ "typescript": "^5.8.3" }, "dependencies": { - "@openzeppelin/contracts": "^5.3.0" + "@openzeppelin/contracts": "^5.4.0" } } diff --git a/tests/evm-tools-compatibility/viem/package-lock.json b/tests/evm-tools-compatibility/viem/package-lock.json index 6a14d299..740a53fb 100644 --- a/tests/evm-tools-compatibility/viem/package-lock.json +++ b/tests/evm-tools-compatibility/viem/package-lock.json @@ -309,9 +309,9 @@ } }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", "dev": true, "license": "MIT", "dependencies": { @@ -467,9 +467,9 @@ } }, "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -668,9 +668,9 @@ } }, "node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "dev": true, "license": "ISC", "dependencies": { @@ -855,9 +855,9 @@ } }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "license": "MIT", "dependencies": { @@ -1163,9 +1163,9 @@ } }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", "engines": { diff --git a/tests/evm-tools-compatibility/web3.js/package-lock.json b/tests/evm-tools-compatibility/web3.js/package-lock.json index c5925ad8..d00eeedf 100644 --- a/tests/evm-tools-compatibility/web3.js/package-lock.json +++ b/tests/evm-tools-compatibility/web3.js/package-lock.json @@ -15,23 +15,49 @@ } }, "node_modules/@ethereumjs/common": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.5.0.tgz", - "integrity": "sha512-DEHjW6e38o+JmB/NO3GZBpW4lpaiBpkFgXF6jLcJ6gETBYpEyaA5nTimsWBUJR3Vmtm/didUEbNjajskugZORg==", + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", + "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", "license": "MIT", "dependencies": { "crc-32": "^1.2.0", - "ethereumjs-util": "^7.1.1" + "ethereumjs-util": "^7.1.5" + } + }, + "node_modules/@ethereumjs/rlp": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-4.0.1.tgz", + "integrity": "sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==", + "license": "MPL-2.0", + "bin": { + "rlp": "bin/rlp" + }, + "engines": { + "node": ">=14" } }, "node_modules/@ethereumjs/tx": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.3.2.tgz", - "integrity": "sha512-6AaJhwg4ucmwTvw/1qLaZUX5miWrwZ4nLOUsKyb/HtzS3BMw/CasKhdi1ims9mBKeK9sOJCH4qGKOBGyJCeeog==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.5.2.tgz", + "integrity": "sha512-gQDNJWKrSDGu2w7w0PzVXVBNMzb7wwdDOmOqczmhNjqFxFuIbhVJDwiGEnxFNC2/b8ifcZzY7MLcluizohRzNw==", + "license": "MPL-2.0", + "dependencies": { + "@ethereumjs/common": "^2.6.4", + "ethereumjs-util": "^7.1.5" + } + }, + "node_modules/@ethereumjs/util": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/util/-/util-8.1.0.tgz", + "integrity": "sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==", "license": "MPL-2.0", "dependencies": { - "@ethereumjs/common": "^2.5.0", - "ethereumjs-util": "^7.1.2" + "@ethereumjs/rlp": "^4.0.1", + "ethereum-cryptography": "^2.0.0", + "micro-ftch": "^0.3.1" + }, + "engines": { + "node": ">=14" } }, "node_modules/@ethersproject/abi": { @@ -173,9 +199,9 @@ } }, "node_modules/@ethersproject/bignumber/node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.2.tgz", + "integrity": "sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==", "license": "MIT" }, "node_modules/@ethersproject/bytes": { @@ -362,9 +388,9 @@ } }, "node_modules/@ethersproject/signing-key/node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.2.tgz", + "integrity": "sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==", "license": "MIT" }, "node_modules/@ethersproject/strings": { @@ -438,13 +464,61 @@ "@ethersproject/strings": "^5.8.0" } }, + "node_modules/@noble/curves": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.4.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@noble/hashes": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", - "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", "license": "MIT", "engines": { - "node": "^14.21.3 || >=16" + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/base": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", + "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", + "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.4.0", + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", + "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" }, "funding": { "url": "https://paulmillr.com/funding/" @@ -475,9 +549,9 @@ } }, "node_modules/@types/bn.js": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.6.tgz", - "integrity": "sha512-Xh8vSwUeMKeYYrj3cX4lGQgFSF/N03r+tv4AiLl1SucqV+uTQpxRcnM8AkXKHwYP9ZPXOYXRr2KPXpVlIvqh9w==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-DLbJ1BPqxvQhIGbeu8VbUC1DiAiahHtAYvA0ZEAa4P31F7IaArc8z3C3BRQdWX4mtLQuABG4yzp76ZrS02Ui1Q==", "license": "MIT", "dependencies": { "@types/node": "*" @@ -535,9 +609,9 @@ } }, "node_modules/@types/secp256k1": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.6.tgz", - "integrity": "sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.7.tgz", + "integrity": "sha512-Rcvjl6vARGAKRO6jHeKMatGrvOMGrR/AR11N1x2LqintPCyDZ7NBhrh238Z2VZc7aM7KIwnFpFQ7fnfK4H/9Qw==", "license": "MIT", "dependencies": { "@types/node": "*" @@ -563,9 +637,9 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -749,9 +823,9 @@ } }, "node_modules/bignumber.js": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.0.tgz", - "integrity": "sha512-EM7aMFTXbptt/wZdMlBv2t8IViwQL+h6SLHosp8Yf0dqJMTnY6iL32opnAB6kAdL0SZPuvcAzFr31o0c/R3/RA==", + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", + "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", "license": "MIT", "engines": { "node": "*" @@ -782,9 +856,9 @@ "license": "MIT" }, "node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", "license": "MIT" }, "node_modules/body-parser": { @@ -812,9 +886,9 @@ } }, "node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" @@ -1168,13 +1242,14 @@ } }, "node_modules/cipher-base": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.6.tgz", - "integrity": "sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.7.tgz", + "integrity": "sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==", "license": "MIT", "dependencies": { "inherits": "^2.0.4", - "safe-buffer": "^5.2.1" + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.2" }, "engines": { "node": ">= 0.10" @@ -1345,9 +1420,9 @@ } }, "node_modules/cross-fetch": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", - "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.1.0.tgz", + "integrity": "sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw==", "license": "MIT", "dependencies": { "node-fetch": "^2.7.0" @@ -1501,9 +1576,9 @@ } }, "node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.2.tgz", + "integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==", "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" @@ -1575,9 +1650,9 @@ } }, "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", "license": "MIT", "dependencies": { "once": "^1.4.0" @@ -1750,26 +1825,15 @@ } }, "node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", + "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", "license": "MIT", "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" + "@noble/curves": "1.4.2", + "@noble/hashes": "1.4.0", + "@scure/bip32": "1.4.0", + "@scure/bip39": "1.3.0" } }, "node_modules/ethereumjs-util": { @@ -1789,11 +1853,34 @@ } }, "node_modules/ethereumjs-util/node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.2.tgz", + "integrity": "sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==", "license": "MIT" }, + "node_modules/ethereumjs-util/node_modules/ethereum-cryptography": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", + "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "license": "MIT", + "dependencies": { + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "browserify-aes": "^1.2.0", + "bs58check": "^2.1.2", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "hash.js": "^1.1.7", + "keccak": "^3.0.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, "node_modules/ethjs-unit": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", @@ -1841,39 +1928,39 @@ } }, "node_modules/express": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", - "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", + "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", + "body-parser": "~1.20.3", + "content-disposition": "~0.5.4", "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", "debug": "2.6.9", "depd": "2.0.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", "merge-descriptors": "1.0.3", "methods": "~1.1.2", - "on-finished": "2.4.1", + "on-finished": "~2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.12", + "path-to-regexp": "~0.1.12", "proxy-addr": "~2.0.7", - "qs": "6.13.0", + "qs": "~6.14.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", + "send": "~0.19.0", + "serve-static": "~1.16.2", "setprototypeof": "1.2.0", - "statuses": "2.0.1", + "statuses": "~2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" @@ -1886,6 +1973,21 @@ "url": "https://opencollective.com/express" } }, + "node_modules/express/node_modules/qs": { + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", + "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/ext": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", @@ -2088,6 +2190,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -2322,17 +2433,18 @@ } }, "node_modules/hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.2.tgz", + "integrity": "sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==", "license": "MIT", "dependencies": { "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.1" }, "engines": { - "node": ">=4" + "node": ">= 0.8" } }, "node_modules/hash.js": { @@ -2378,9 +2490,9 @@ } }, "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", "license": "BSD-2-Clause" }, "node_modules/http-errors": { @@ -2577,13 +2689,14 @@ "license": "MIT" }, "node_modules/is-generator-function": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", - "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "get-proto": "^1.0.0", + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" }, @@ -2685,6 +2798,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, "node_modules/isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -2698,9 +2817,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -2778,6 +2897,20 @@ "node": ">=10.0.0" } }, + "node_modules/keccak/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -2885,6 +3018,12 @@ "node": ">= 0.6" } }, + "node_modules/micro-ftch": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/micro-ftch/-/micro-ftch-0.3.1.tgz", + "integrity": "sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg==", + "license": "MIT" + }, "node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -2928,9 +3067,10 @@ } }, "node_modules/min-document": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", - "integrity": "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==", + "version": "2.19.2", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.2.tgz", + "integrity": "sha512-8S5I8db/uZN8r9HSLFVWPdJCvYOejMcEC82VIzNUc6Zkklf/d1gg2psfE79/vyhWOj4+J8MtwmoOz3TmvaGu5A==", + "license": "MIT", "dependencies": { "dom-walk": "^0.1.0" } @@ -2948,9 +3088,9 @@ "license": "MIT" }, "node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" @@ -3365,19 +3505,20 @@ } }, "node_modules/pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.5.tgz", + "integrity": "sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ==", "license": "MIT", "dependencies": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "ripemd160": "^2.0.3", + "safe-buffer": "^5.2.1", + "sha.js": "^2.4.12", + "to-buffer": "^1.2.1" }, "engines": { - "node": ">=0.12" + "node": ">= 0.10" } }, "node_modules/performance-now": { @@ -3387,9 +3528,9 @@ "license": "MIT" }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "license": "MIT", "engines": { "node": ">=8.6" @@ -3416,6 +3557,12 @@ "node": ">= 0.6.0" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -3442,9 +3589,9 @@ } }, "node_modules/pump": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", - "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", @@ -3535,19 +3682,26 @@ } }, "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "license": "MIT", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -3638,13 +3792,16 @@ } }, "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.3.tgz", + "integrity": "sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==", "license": "MIT", "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" + "hash-base": "^3.1.2", + "inherits": "^2.0.4" + }, + "engines": { + "node": ">= 0.8" } }, "node_modules/rlp": { @@ -3660,9 +3817,9 @@ } }, "node_modules/rlp/node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.2.tgz", + "integrity": "sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==", "license": "MIT" }, "node_modules/safe-buffer": { @@ -3844,16 +4001,23 @@ "license": "ISC" }, "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz", + "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==", "license": "(MIT AND BSD-3-Clause)", "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.0" }, "bin": { "sha.js": "bin.js" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/side-channel": { @@ -4015,14 +4179,20 @@ } }, "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "license": "MIT", "dependencies": { - "safe-buffer": "~5.2.0" + "safe-buffer": "~5.1.0" } }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -4224,6 +4394,26 @@ "node": ">=0.10.0" } }, + "node_modules/to-buffer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz", + "integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==", + "license": "MIT", + "dependencies": { + "isarray": "^2.0.5", + "safe-buffer": "^5.2.1", + "typed-array-buffer": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/to-buffer/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "license": "MIT" + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -4309,6 +4499,20 @@ "node": ">= 0.6" } }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -4444,28 +4648,28 @@ } }, "node_modules/web3": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/web3/-/web3-1.10.0.tgz", - "integrity": "sha512-YfKY9wSkGcM8seO+daR89oVTcbu18NsVfvOngzqMYGUU0pPSQmE57qQDvQzUeoIOHAnXEBNzrhjQJmm8ER0rng==", + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3/-/web3-1.10.4.tgz", + "integrity": "sha512-kgJvQZjkmjOEKimx/tJQsqWfRDPTTcBfYPa9XletxuHLpHcXdx67w8EFn5AW3eVxCutE9dTVHgGa9VYe8vgsEA==", "hasInstallScript": true, "license": "LGPL-3.0", "dependencies": { - "web3-bzz": "1.10.0", - "web3-core": "1.10.0", - "web3-eth": "1.10.0", - "web3-eth-personal": "1.10.0", - "web3-net": "1.10.0", - "web3-shh": "1.10.0", - "web3-utils": "1.10.0" + "web3-bzz": "1.10.4", + "web3-core": "1.10.4", + "web3-eth": "1.10.4", + "web3-eth-personal": "1.10.4", + "web3-net": "1.10.4", + "web3-shh": "1.10.4", + "web3-utils": "1.10.4" }, "engines": { "node": ">=8.0.0" } }, "node_modules/web3-bzz": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.10.0.tgz", - "integrity": "sha512-o9IR59io3pDUsXTsps5pO5hW1D5zBmg46iNc2t4j2DkaYHNdDLwk2IP9ukoM2wg47QILfPEJYzhTfkS/CcX0KA==", + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.10.4.tgz", + "integrity": "sha512-ZZ/X4sJ0Uh2teU9lAGNS8EjveEppoHNQiKlOXAjedsrdWuaMErBPdLQjXfcrYvN6WM6Su9PMsAxf3FXXZ+HwQw==", "hasInstallScript": true, "license": "LGPL-3.0", "dependencies": { @@ -4478,56 +4682,56 @@ } }, "node_modules/web3-core": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.10.0.tgz", - "integrity": "sha512-fWySwqy2hn3TL89w5TM8wXF1Z2Q6frQTKHWmP0ppRQorEK8NcHJRfeMiv/mQlSKoTS1F6n/nv2uyZsixFycjYQ==", + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.10.4.tgz", + "integrity": "sha512-B6elffYm81MYZDTrat7aEhnhdtVE3lDBUZft16Z8awYMZYJDbnykEbJVS+l3mnA7AQTnSDr/1MjWofGDLBJPww==", "license": "LGPL-3.0", "dependencies": { "@types/bn.js": "^5.1.1", "@types/node": "^12.12.6", "bignumber.js": "^9.0.0", - "web3-core-helpers": "1.10.0", - "web3-core-method": "1.10.0", - "web3-core-requestmanager": "1.10.0", - "web3-utils": "1.10.0" + "web3-core-helpers": "1.10.4", + "web3-core-method": "1.10.4", + "web3-core-requestmanager": "1.10.4", + "web3-utils": "1.10.4" }, "engines": { "node": ">=8.0.0" } }, "node_modules/web3-core-helpers": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.10.0.tgz", - "integrity": "sha512-pIxAzFDS5vnbXvfvLSpaA1tfRykAe9adw43YCKsEYQwH0gCLL0kMLkaCX3q+Q8EVmAh+e1jWL/nl9U0de1+++g==", + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.10.4.tgz", + "integrity": "sha512-r+L5ylA17JlD1vwS8rjhWr0qg7zVoVMDvWhajWA5r5+USdh91jRUYosp19Kd1m2vE034v7Dfqe1xYRoH2zvG0g==", "license": "LGPL-3.0", "dependencies": { - "web3-eth-iban": "1.10.0", - "web3-utils": "1.10.0" + "web3-eth-iban": "1.10.4", + "web3-utils": "1.10.4" }, "engines": { "node": ">=8.0.0" } }, "node_modules/web3-core-method": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.10.0.tgz", - "integrity": "sha512-4R700jTLAMKDMhQ+nsVfIXvH6IGJlJzGisIfMKWAIswH31h5AZz7uDUW2YctI+HrYd+5uOAlS4OJeeT9bIpvkA==", + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.10.4.tgz", + "integrity": "sha512-uZTb7flr+Xl6LaDsyTeE2L1TylokCJwTDrIVfIfnrGmnwLc6bmTWCCrm71sSrQ0hqs6vp/MKbQYIYqUN0J8WyA==", "license": "LGPL-3.0", "dependencies": { "@ethersproject/transactions": "^5.6.2", - "web3-core-helpers": "1.10.0", - "web3-core-promievent": "1.10.0", - "web3-core-subscriptions": "1.10.0", - "web3-utils": "1.10.0" + "web3-core-helpers": "1.10.4", + "web3-core-promievent": "1.10.4", + "web3-core-subscriptions": "1.10.4", + "web3-utils": "1.10.4" }, "engines": { "node": ">=8.0.0" } }, "node_modules/web3-core-promievent": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.10.0.tgz", - "integrity": "sha512-68N7k5LWL5R38xRaKFrTFT2pm2jBNFaM4GioS00YjAKXRQ3KjmhijOMG3TICz6Aa5+6GDWYelDNx21YAeZ4YTg==", + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.10.4.tgz", + "integrity": "sha512-2de5WnJQ72YcIhYwV/jHLc4/cWJnznuoGTJGD29ncFQHAfwW/MItHFSVKPPA5v8AhJe+r6y4Y12EKvZKjQVBvQ==", "license": "LGPL-3.0", "dependencies": { "eventemitter3": "4.0.4" @@ -4537,86 +4741,86 @@ } }, "node_modules/web3-core-requestmanager": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.10.0.tgz", - "integrity": "sha512-3z/JKE++Os62APml4dvBM+GAuId4h3L9ckUrj7ebEtS2AR0ixyQPbrBodgL91Sv7j7cQ3Y+hllaluqjguxvSaQ==", + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.10.4.tgz", + "integrity": "sha512-vqP6pKH8RrhT/2MoaU+DY/OsYK9h7HmEBNCdoMj+4ZwujQtw/Mq2JifjwsJ7gits7Q+HWJwx8q6WmQoVZAWugg==", "license": "LGPL-3.0", "dependencies": { "util": "^0.12.5", - "web3-core-helpers": "1.10.0", - "web3-providers-http": "1.10.0", - "web3-providers-ipc": "1.10.0", - "web3-providers-ws": "1.10.0" + "web3-core-helpers": "1.10.4", + "web3-providers-http": "1.10.4", + "web3-providers-ipc": "1.10.4", + "web3-providers-ws": "1.10.4" }, "engines": { "node": ">=8.0.0" } }, "node_modules/web3-core-subscriptions": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.10.0.tgz", - "integrity": "sha512-HGm1PbDqsxejI075gxBc5OSkwymilRWZufIy9zEpnWKNmfbuv5FfHgW1/chtJP6aP3Uq2vHkvTDl3smQBb8l+g==", + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.10.4.tgz", + "integrity": "sha512-o0lSQo/N/f7/L76C0HV63+S54loXiE9fUPfHFcTtpJRQNDBVsSDdWRdePbWwR206XlsBqD5VHApck1//jEafTw==", "license": "LGPL-3.0", "dependencies": { "eventemitter3": "4.0.4", - "web3-core-helpers": "1.10.0" + "web3-core-helpers": "1.10.4" }, "engines": { "node": ">=8.0.0" } }, "node_modules/web3-eth": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.10.0.tgz", - "integrity": "sha512-Z5vT6slNMLPKuwRyKGbqeGYC87OAy8bOblaqRTgg94CXcn/mmqU7iPIlG4506YdcdK3x6cfEDG7B6w+jRxypKA==", + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.10.4.tgz", + "integrity": "sha512-Sql2kYKmgt+T/cgvg7b9ce24uLS7xbFrxE4kuuor1zSCGrjhTJ5rRNG8gTJUkAJGKJc7KgnWmgW+cOfMBPUDSA==", "license": "LGPL-3.0", "dependencies": { - "web3-core": "1.10.0", - "web3-core-helpers": "1.10.0", - "web3-core-method": "1.10.0", - "web3-core-subscriptions": "1.10.0", - "web3-eth-abi": "1.10.0", - "web3-eth-accounts": "1.10.0", - "web3-eth-contract": "1.10.0", - "web3-eth-ens": "1.10.0", - "web3-eth-iban": "1.10.0", - "web3-eth-personal": "1.10.0", - "web3-net": "1.10.0", - "web3-utils": "1.10.0" + "web3-core": "1.10.4", + "web3-core-helpers": "1.10.4", + "web3-core-method": "1.10.4", + "web3-core-subscriptions": "1.10.4", + "web3-eth-abi": "1.10.4", + "web3-eth-accounts": "1.10.4", + "web3-eth-contract": "1.10.4", + "web3-eth-ens": "1.10.4", + "web3-eth-iban": "1.10.4", + "web3-eth-personal": "1.10.4", + "web3-net": "1.10.4", + "web3-utils": "1.10.4" }, "engines": { "node": ">=8.0.0" } }, "node_modules/web3-eth-abi": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.10.0.tgz", - "integrity": "sha512-cwS+qRBWpJ43aI9L3JS88QYPfFcSJJ3XapxOQ4j40v6mk7ATpA8CVK1vGTzpihNlOfMVRBkR95oAj7oL6aiDOg==", + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.10.4.tgz", + "integrity": "sha512-cZ0q65eJIkd/jyOlQPDjr8X4fU6CRL1eWgdLwbWEpo++MPU/2P4PFk5ZLAdye9T5Sdp+MomePPJ/gHjLMj2VfQ==", "license": "LGPL-3.0", "dependencies": { "@ethersproject/abi": "^5.6.3", - "web3-utils": "1.10.0" + "web3-utils": "1.10.4" }, "engines": { "node": ">=8.0.0" } }, "node_modules/web3-eth-accounts": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.10.0.tgz", - "integrity": "sha512-wiq39Uc3mOI8rw24wE2n15hboLE0E9BsQLdlmsL4Zua9diDS6B5abXG0XhFcoNsXIGMWXVZz4TOq3u4EdpXF/Q==", + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.10.4.tgz", + "integrity": "sha512-ysy5sVTg9snYS7tJjxVoQAH6DTOTkRGR8emEVCWNGLGiB9txj+qDvSeT0izjurS/g7D5xlMAgrEHLK1Vi6I3yg==", "license": "LGPL-3.0", "dependencies": { - "@ethereumjs/common": "2.5.0", - "@ethereumjs/tx": "3.3.2", + "@ethereumjs/common": "2.6.5", + "@ethereumjs/tx": "3.5.2", + "@ethereumjs/util": "^8.1.0", "eth-lib": "0.2.8", - "ethereumjs-util": "^7.1.5", "scrypt-js": "^3.0.1", "uuid": "^9.0.0", - "web3-core": "1.10.0", - "web3-core-helpers": "1.10.0", - "web3-core-method": "1.10.0", - "web3-utils": "1.10.0" + "web3-core": "1.10.4", + "web3-core-helpers": "1.10.4", + "web3-core-method": "1.10.4", + "web3-utils": "1.10.4" }, "engines": { "node": ">=8.0.0" @@ -4647,129 +4851,129 @@ } }, "node_modules/web3-eth-contract": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.10.0.tgz", - "integrity": "sha512-MIC5FOzP/+2evDksQQ/dpcXhSqa/2hFNytdl/x61IeWxhh6vlFeSjq0YVTAyIzdjwnL7nEmZpjfI6y6/Ufhy7w==", + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.10.4.tgz", + "integrity": "sha512-Q8PfolOJ4eV9TvnTj1TGdZ4RarpSLmHnUnzVxZ/6/NiTfe4maJz99R0ISgwZkntLhLRtw0C7LRJuklzGYCNN3A==", "license": "LGPL-3.0", "dependencies": { "@types/bn.js": "^5.1.1", - "web3-core": "1.10.0", - "web3-core-helpers": "1.10.0", - "web3-core-method": "1.10.0", - "web3-core-promievent": "1.10.0", - "web3-core-subscriptions": "1.10.0", - "web3-eth-abi": "1.10.0", - "web3-utils": "1.10.0" + "web3-core": "1.10.4", + "web3-core-helpers": "1.10.4", + "web3-core-method": "1.10.4", + "web3-core-promievent": "1.10.4", + "web3-core-subscriptions": "1.10.4", + "web3-eth-abi": "1.10.4", + "web3-utils": "1.10.4" }, "engines": { "node": ">=8.0.0" } }, "node_modules/web3-eth-ens": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.10.0.tgz", - "integrity": "sha512-3hpGgzX3qjgxNAmqdrC2YUQMTfnZbs4GeLEmy8aCWziVwogbuqQZ+Gzdfrym45eOZodk+lmXyLuAdqkNlvkc1g==", + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.10.4.tgz", + "integrity": "sha512-LLrvxuFeVooRVZ9e5T6OWKVflHPFgrVjJ/jtisRWcmI7KN/b64+D/wJzXqgmp6CNsMQcE7rpmf4CQmJCrTdsgg==", "license": "LGPL-3.0", "dependencies": { "content-hash": "^2.5.2", "eth-ens-namehash": "2.0.8", - "web3-core": "1.10.0", - "web3-core-helpers": "1.10.0", - "web3-core-promievent": "1.10.0", - "web3-eth-abi": "1.10.0", - "web3-eth-contract": "1.10.0", - "web3-utils": "1.10.0" + "web3-core": "1.10.4", + "web3-core-helpers": "1.10.4", + "web3-core-promievent": "1.10.4", + "web3-eth-abi": "1.10.4", + "web3-eth-contract": "1.10.4", + "web3-utils": "1.10.4" }, "engines": { "node": ">=8.0.0" } }, "node_modules/web3-eth-iban": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.10.0.tgz", - "integrity": "sha512-0l+SP3IGhInw7Q20LY3IVafYEuufo4Dn75jAHT7c2aDJsIolvf2Lc6ugHkBajlwUneGfbRQs/ccYPQ9JeMUbrg==", + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.10.4.tgz", + "integrity": "sha512-0gE5iNmOkmtBmbKH2aTodeompnNE8jEyvwFJ6s/AF6jkw9ky9Op9cqfzS56AYAbrqEFuClsqB/AoRves7LDELw==", "license": "LGPL-3.0", "dependencies": { "bn.js": "^5.2.1", - "web3-utils": "1.10.0" + "web3-utils": "1.10.4" }, "engines": { "node": ">=8.0.0" } }, "node_modules/web3-eth-iban/node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.2.tgz", + "integrity": "sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==", "license": "MIT" }, "node_modules/web3-eth-personal": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.10.0.tgz", - "integrity": "sha512-anseKn98w/d703eWq52uNuZi7GhQeVjTC5/svrBWEKob0WZ5kPdo+EZoFN0sp5a5ubbrk/E0xSl1/M5yORMtpg==", + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.10.4.tgz", + "integrity": "sha512-BRa/hs6jU1hKHz+AC/YkM71RP3f0Yci1dPk4paOic53R4ZZG4MgwKRkJhgt3/GPuPliwS46f/i5A7fEGBT4F9w==", "license": "LGPL-3.0", "dependencies": { "@types/node": "^12.12.6", - "web3-core": "1.10.0", - "web3-core-helpers": "1.10.0", - "web3-core-method": "1.10.0", - "web3-net": "1.10.0", - "web3-utils": "1.10.0" + "web3-core": "1.10.4", + "web3-core-helpers": "1.10.4", + "web3-core-method": "1.10.4", + "web3-net": "1.10.4", + "web3-utils": "1.10.4" }, "engines": { "node": ">=8.0.0" } }, "node_modules/web3-net": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.10.0.tgz", - "integrity": "sha512-NLH/N3IshYWASpxk4/18Ge6n60GEvWBVeM8inx2dmZJVmRI6SJIlUxbL8jySgiTn3MMZlhbdvrGo8fpUW7a1GA==", + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.10.4.tgz", + "integrity": "sha512-mKINnhOOnZ4koA+yV2OT5s5ztVjIx7IY9a03w6s+yao/BUn+Luuty0/keNemZxTr1E8Ehvtn28vbOtW7Ids+Ow==", "license": "LGPL-3.0", "dependencies": { - "web3-core": "1.10.0", - "web3-core-method": "1.10.0", - "web3-utils": "1.10.0" + "web3-core": "1.10.4", + "web3-core-method": "1.10.4", + "web3-utils": "1.10.4" }, "engines": { "node": ">=8.0.0" } }, "node_modules/web3-providers-http": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.10.0.tgz", - "integrity": "sha512-eNr965YB8a9mLiNrkjAWNAPXgmQWfpBfkkn7tpEFlghfww0u3I0tktMZiaToJVcL2+Xq+81cxbkpeWJ5XQDwOA==", + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.10.4.tgz", + "integrity": "sha512-m2P5Idc8hdiO0l60O6DSCPw0kw64Zgi0pMjbEFRmxKIck2Py57RQMu4bxvkxJwkF06SlGaEQF8rFZBmuX7aagQ==", "license": "LGPL-3.0", "dependencies": { - "abortcontroller-polyfill": "^1.7.3", - "cross-fetch": "^3.1.4", + "abortcontroller-polyfill": "^1.7.5", + "cross-fetch": "^4.0.0", "es6-promise": "^4.2.8", - "web3-core-helpers": "1.10.0" + "web3-core-helpers": "1.10.4" }, "engines": { "node": ">=8.0.0" } }, "node_modules/web3-providers-ipc": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.10.0.tgz", - "integrity": "sha512-OfXG1aWN8L1OUqppshzq8YISkWrYHaATW9H8eh0p89TlWMc1KZOL9vttBuaBEi96D/n0eYDn2trzt22bqHWfXA==", + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.10.4.tgz", + "integrity": "sha512-YRF/bpQk9z3WwjT+A6FI/GmWRCASgd+gC0si7f9zbBWLXjwzYAKG73bQBaFRAHex1hl4CVcM5WUMaQXf3Opeuw==", "license": "LGPL-3.0", "dependencies": { "oboe": "2.1.5", - "web3-core-helpers": "1.10.0" + "web3-core-helpers": "1.10.4" }, "engines": { "node": ">=8.0.0" } }, "node_modules/web3-providers-ws": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.10.0.tgz", - "integrity": "sha512-sK0fNcglW36yD5xjnjtSGBnEtf59cbw4vZzJ+CmOWIKGIR96mP5l684g0WD0Eo+f4NQc2anWWXG74lRc9OVMCQ==", + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.10.4.tgz", + "integrity": "sha512-j3FBMifyuFFmUIPVQR4pj+t5ILhAexAui0opgcpu9R5LxQrLRUZxHSnU+YO25UycSOa/NAX8A+qkqZNpcFAlxA==", "license": "LGPL-3.0", "dependencies": { "eventemitter3": "4.0.4", - "web3-core-helpers": "1.10.0", + "web3-core-helpers": "1.10.4", "websocket": "^1.0.32" }, "engines": { @@ -4777,30 +4981,31 @@ } }, "node_modules/web3-shh": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.10.0.tgz", - "integrity": "sha512-uNUUuNsO2AjX41GJARV9zJibs11eq6HtOe6Wr0FtRUcj8SN6nHeYIzwstAvJ4fXA53gRqFMTxdntHEt9aXVjpg==", + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.10.4.tgz", + "integrity": "sha512-cOH6iFFM71lCNwSQrC3niqDXagMqrdfFW85hC9PFUrAr3PUrIem8TNstTc3xna2bwZeWG6OBy99xSIhBvyIACw==", "hasInstallScript": true, "license": "LGPL-3.0", "dependencies": { - "web3-core": "1.10.0", - "web3-core-method": "1.10.0", - "web3-core-subscriptions": "1.10.0", - "web3-net": "1.10.0" + "web3-core": "1.10.4", + "web3-core-method": "1.10.4", + "web3-core-subscriptions": "1.10.4", + "web3-net": "1.10.4" }, "engines": { "node": ">=8.0.0" } }, "node_modules/web3-utils": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.10.0.tgz", - "integrity": "sha512-kSaCM0uMcZTNUSmn5vMEhlo02RObGNRRCkdX0V9UTAU0+lrvn0HSaudyCo6CQzuXUsnuY2ERJGCGPfeWmv19Rg==", + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.10.4.tgz", + "integrity": "sha512-tsu8FiKJLk2PzhDl9fXbGUWTkkVXYhtTA+SmEFkKft+9BgwLxfCRpU96sWv7ICC8zixBNd3JURVoiR3dUXgP8A==", "license": "LGPL-3.0", "dependencies": { + "@ethereumjs/util": "^8.1.0", "bn.js": "^5.2.1", "ethereum-bloom-filters": "^1.0.6", - "ethereumjs-util": "^7.1.0", + "ethereum-cryptography": "^2.1.2", "ethjs-unit": "0.1.6", "number-to-bn": "1.7.0", "randombytes": "^2.1.0", @@ -4811,9 +5016,9 @@ } }, "node_modules/web3-utils/node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.2.tgz", + "integrity": "sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==", "license": "MIT" }, "node_modules/webidl-conversions": { diff --git a/tests/integration/README.md b/tests/integration/README.md index a1d0bab6..03e98318 100644 --- a/tests/integration/README.md +++ b/tests/integration/README.md @@ -26,7 +26,9 @@ All tests defined here can be used by any client application that implements the You can find usage examples under `evmd/tests/integration`. For instance, if you want to test your own application with the Bank Precompile Integration Test Suite, -implement your own `CreateApp` function and pass it in as shown below: + +1. Refer to interfaces.go file and implement `EvmApp` interface in your own app. +2. Refer to the `evmd/tests/integration/create_app.go` file and implement your own `CreateApp` function and pass it in as shown below: ```go package integration @@ -35,15 +37,20 @@ import ( "testing" "github.com/stretchr/testify/suite" + "github.com/cosmos/cosmos-sdk/baseapp" + evm "github.com/cosmos/evm" + testapp "github.com/cosmos/evm/testutil/app" "github.com/cosmos/evm/tests/integration/precompiles/bank" ) func TestBankPrecompileTestSuite(t *testing.T) { - s := bank.NewPrecompileTestSuite(CreateEvmd) + create := testapp.ToEvmAppCreator[evm.BankPrecompileApp](CreateEvmd, "evm.BankPrecompileApp") + s := bank.NewPrecompileTestSuite(create) suite.Run(t, s) } func TestBankPrecompileIntegrationTestSuite(t *testing.T) { - bank.TestIntegrationSuite(t, CreateEvmd) + create := testapp.ToEvmAppCreator[evm.BankPrecompileApp](CreateEvmd, "evm.BankPrecompileApp") + bank.TestIntegrationSuite(t, create) } ``` diff --git a/tests/integration/ante/evm_ante_test_suite.go b/tests/integration/ante/evm_ante_test_suite.go index 36107144..476e02dd 100644 --- a/tests/integration/ante/evm_ante_test_suite.go +++ b/tests/integration/ante/evm_ante_test_suite.go @@ -18,13 +18,10 @@ import ( "github.com/cosmos/evm/testutil/integration/evm/network" utiltx "github.com/cosmos/evm/testutil/tx" evmtypes "github.com/cosmos/evm/x/vm/types" - ibctypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - ibcclienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" + ibctypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + ibcclienttypes "github.com/cosmos/ibc-go/v11/modules/core/02-client/types" sdkmath "cosmossdk.io/math" - storetypes "cosmossdk.io/store/types" - evtypes "cosmossdk.io/x/evidence/types" - "cosmossdk.io/x/feegrant" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" @@ -33,6 +30,7 @@ import ( kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" "github.com/cosmos/cosmos-sdk/crypto/types/multisig" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/tx/signing" sdkante "github.com/cosmos/cosmos-sdk/x/auth/ante" @@ -41,6 +39,8 @@ import ( authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" "github.com/cosmos/cosmos-sdk/x/authz" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + evtypes "github.com/cosmos/cosmos-sdk/x/evidence/types" + "github.com/cosmos/cosmos-sdk/x/feegrant" govtypesv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" teststaking "github.com/cosmos/cosmos-sdk/x/staking/testutil" diff --git a/tests/integration/ante/test_bench_evm_ante.go b/tests/integration/ante/test_bench_evm_ante.go index fc7919d6..b8bdcd07 100644 --- a/tests/integration/ante/test_bench_evm_ante.go +++ b/tests/integration/ante/test_bench_evm_ante.go @@ -15,8 +15,8 @@ import ( evmtypes "github.com/cosmos/evm/x/vm/types" sdkmath "cosmossdk.io/math" - storetypes "cosmossdk.io/store/types" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" ) diff --git a/tests/integration/ante/test_evm_01_setup_ctx.go b/tests/integration/ante/test_evm_01_setup_ctx.go index 259e601f..03022530 100644 --- a/tests/integration/ante/test_evm_01_setup_ctx.go +++ b/tests/integration/ante/test_evm_01_setup_ctx.go @@ -8,13 +8,12 @@ import ( testutiltx "github.com/cosmos/evm/testutil/tx" evmtypes "github.com/cosmos/evm/x/vm/types" - storetypes "cosmossdk.io/store/types" - + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" ) func (s *EvmAnteTestSuite) TestEthSetupContextDecorator() { - dec := evmante.NewEthSetUpContextDecorator(s.GetNetwork().App.GetEVMKeeper()) + dec := evmante.EthSetupContextDecorator{} ethContractCreationTxParams := &evmtypes.EvmTxArgs{ ChainID: evmtypes.GetEthChainConfig().ChainID, Nonce: 1, diff --git a/tests/integration/ante/test_evm_antehandler_benchmark.go b/tests/integration/ante/test_evm_antehandler_benchmark.go index e46e5cff..639c1585 100644 --- a/tests/integration/ante/test_evm_antehandler_benchmark.go +++ b/tests/integration/ante/test_evm_antehandler_benchmark.go @@ -5,6 +5,7 @@ import ( "math/big" "testing" + evm "github.com/cosmos/evm" "github.com/cosmos/evm/ante" antetypes "github.com/cosmos/evm/ante/types" basefactory "github.com/cosmos/evm/testutil/integration/base/factory" @@ -141,6 +142,7 @@ func (s *benchmarkSuite) generateTxType(txType string) (sdktypes.Tx, error) { func (s *benchmarkSuite) generateHandlerOptions() ante.HandlerOptions { encCfg := s.network.GetEncodingConfig() + ibcKeeper := s.network.App.(evm.IBCKeeperProvider).GetIBCKeeper() return ante.HandlerOptions{ Cdc: s.network.App.AppCodec(), AccountKeeper: s.network.App.GetAccountKeeper(), @@ -148,7 +150,7 @@ func (s *benchmarkSuite) generateHandlerOptions() ante.HandlerOptions { ExtensionOptionChecker: antetypes.HasDynamicFeeExtensionOption, EvmKeeper: s.network.App.GetEVMKeeper(), FeegrantKeeper: s.network.App.GetFeeGrantKeeper(), - IBCKeeper: s.network.App.GetIBCKeeper(), + IBCKeeper: ibcKeeper, FeeMarketKeeper: s.network.App.GetFeeMarketKeeper(), SignModeHandler: encCfg.TxConfig.SignModeHandler(), SigGasConsumer: ante.SigVerificationGasConsumer, diff --git a/tests/integration/ante/test_evm_fee_market.go b/tests/integration/ante/test_evm_fee_market.go deleted file mode 100644 index 13053b16..00000000 --- a/tests/integration/ante/test_evm_fee_market.go +++ /dev/null @@ -1,150 +0,0 @@ -package ante - -import ( - "math/big" - - ethtypes "github.com/ethereum/go-ethereum/core/types" - - "github.com/cosmos/evm/ante/evm" - "github.com/cosmos/evm/ante/types" - "github.com/cosmos/evm/server/config" - "github.com/cosmos/evm/testutil" - testconstants "github.com/cosmos/evm/testutil/constants" - utiltx "github.com/cosmos/evm/testutil/tx" - 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" -) - -func (s *EvmAnteTestSuite) TestGasWantedDecorator() { - s.WithFeemarketEnabled(true) - s.SetupTest() - ctx := s.GetNetwork().GetContext() - feeMarketKeeper := s.GetNetwork().App.GetFeeMarketKeeper() - params := feeMarketKeeper.GetParams(ctx) - dec := evm.NewGasWantedDecorator(s.GetNetwork().App.GetEVMKeeper(), feeMarketKeeper, ¶ms) - from, fromPrivKey := utiltx.NewAddrKey() - to := utiltx.GenerateAddress() - denom := evmtypes.GetEVMCoinDenom() - - testCases := []struct { - name string - expectedGasWanted uint64 - malleate func() sdk.Tx - expPass bool - }{ - { - "Cosmos Tx", - TestGasLimit, - func() sdk.Tx { - testMsg := banktypes.MsgSend{ - FromAddress: "cosmos1x8fhpj9nmhqk8z9kpgjt95ck2xwyue0ptzkucp", - ToAddress: "cosmos1dx67l23hz9l0k9hcher8xz04uj7wf3yu26l2yn", - Amount: sdk.Coins{sdk.Coin{Amount: sdkmath.NewInt(10), Denom: denom}}, - } - txBuilder := s.CreateTestCosmosTxBuilder(sdkmath.NewInt(10), denom, &testMsg) - return txBuilder.GetTx() - }, - true, - }, - { - "Ethereum Legacy Tx", - TestGasLimit, - func() sdk.Tx { - txArgs := evmtypes.EvmTxArgs{ - To: &to, - GasPrice: big.NewInt(0), - GasLimit: TestGasLimit, - } - return s.CreateTxBuilder(fromPrivKey, txArgs).GetTx() - }, - true, - }, - { - "Ethereum Access List Tx", - TestGasLimit, - func() sdk.Tx { - emptyAccessList := ethtypes.AccessList{} - txArgs := evmtypes.EvmTxArgs{ - To: &to, - GasPrice: big.NewInt(0), - GasLimit: TestGasLimit, - Accesses: &emptyAccessList, - } - return s.CreateTxBuilder(fromPrivKey, txArgs).GetTx() - }, - true, - }, - { - "Ethereum Dynamic Fee Tx (EIP1559)", - TestGasLimit, - func() sdk.Tx { - emptyAccessList := ethtypes.AccessList{} - txArgs := evmtypes.EvmTxArgs{ - To: &to, - GasPrice: big.NewInt(0), - GasFeeCap: big.NewInt(100), - GasLimit: TestGasLimit, - GasTipCap: big.NewInt(50), - Accesses: &emptyAccessList, - } - return s.CreateTxBuilder(fromPrivKey, txArgs).GetTx() - }, - true, - }, - { - "EIP712 message", - 200000, - func() sdk.Tx { - amount := sdk.NewCoins(sdk.NewCoin(testconstants.ExampleAttoDenom, sdkmath.NewInt(20))) - gas := uint64(200000) - acc := s.GetNetwork().App.GetAccountKeeper().NewAccountWithAddress(ctx, from.Bytes()) - s.Require().NoError(acc.SetSequence(1)) - s.GetNetwork().App.GetAccountKeeper().SetAccount(ctx, acc) - builder, err := s.CreateTestEIP712TxBuilderMsgSend(acc.GetAddress(), fromPrivKey, ctx.ChainID(), config.DefaultEVMChainID, gas, amount) - s.Require().NoError(err) - return builder.GetTx() - }, - true, - }, - { - "Cosmos Tx - gasWanted > max block gas", - TestGasLimit, - func() sdk.Tx { - denom := testconstants.ExampleAttoDenom - testMsg := banktypes.MsgSend{ - FromAddress: "cosmos1x8fhpj9nmhqk8z9kpgjt95ck2xwyue0ptzkucp", - ToAddress: "cosmos1dx67l23hz9l0k9hcher8xz04uj7wf3yu26l2yn", - Amount: sdk.Coins{sdk.Coin{Amount: sdkmath.NewInt(10), Denom: denom}}, - } - txBuilder := s.CreateTestCosmosTxBuilder(sdkmath.NewInt(10), testconstants.ExampleAttoDenom, &testMsg) - limit := types.BlockGasLimit(ctx) - txBuilder.SetGasLimit(limit + 5) - return txBuilder.GetTx() - }, - false, - }, - } - - // cumulative gas wanted from all test transactions in the same block - var expectedGasWanted uint64 - - for _, tc := range testCases { - s.Run(tc.name, func() { - _, err := dec.AnteHandle(ctx, tc.malleate(), false, testutil.NoOpNextFn) - if tc.expPass { - s.Require().NoError(err) - - gasWanted := s.GetNetwork().App.GetFeeMarketKeeper().GetTransientGasWanted(ctx) - expectedGasWanted += tc.expectedGasWanted - s.Require().Equal(expectedGasWanted, gasWanted) - } else { - // TODO: check for specific error message - s.Require().Error(err) - } - }) - } -} diff --git a/tests/integration/ante/test_evm_unit_04_validate.go b/tests/integration/ante/test_evm_unit_04_validate.go index 8e87308c..1d035065 100644 --- a/tests/integration/ante/test_evm_unit_04_validate.go +++ b/tests/integration/ante/test_evm_unit_04_validate.go @@ -6,6 +6,7 @@ import ( "github.com/ethereum/go-ethereum/common" ethtypes "github.com/ethereum/go-ethereum/core/types" + protov2 "google.golang.org/protobuf/proto" "github.com/cosmos/evm/ante/evm" testconstants "github.com/cosmos/evm/testutil/constants" @@ -14,6 +15,7 @@ import ( "cosmossdk.io/math" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdktypes "github.com/cosmos/cosmos-sdk/types" errortypes "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/types/tx" @@ -273,3 +275,285 @@ func (s *EvmUnitAnteTestSuite) TestCheckTxFee() { } } } + +// mockTx is a mock transaction that implements sdktypes.Tx and ProtoTxProvider +type mockTx struct { + protoTx *tx.Tx +} + +func (m *mockTx) GetMsgs() []sdktypes.Msg { + return nil +} + +func (m *mockTx) GetMsgsV2() ([]protov2.Message, error) { + return nil, nil +} + +func (m *mockTx) ValidateBasic() error { + return nil +} + +func (m *mockTx) GetProtoTx() *tx.Tx { + return m.protoTx +} + +func (s *EvmUnitAnteTestSuite) TestValidateTx() { + keyring := testkeyring.New(2) + to := keyring.GetAddr(1) + + // Create a valid MsgEthereumTx + validTxArgs := evmtypes.EvmTxArgs{ + To: &to, + Amount: big.NewInt(100), + } + msgEthTx := evmtypes.NewTx(&validTxArgs) + msgEthTx.From = keyring.GetAddr(0).Bytes() + + // Create a valid proto transaction structure + createValidProtoTx := func() *tx.Tx { + option, err := codectypes.NewAnyWithValue(&evmtypes.ExtensionOptionsEthereumTx{}) + s.Require().NoError(err) + + evmExtendedDenom := evmtypes.GetEVMCoinExtendedDenom() + feeAmount := sdktypes.NewCoins(sdktypes.NewCoin(evmExtendedDenom, math.NewInt(1000))) + + return &tx.Tx{ + Body: &tx.TxBody{ + Messages: []*codectypes.Any{}, + Memo: "", + TimeoutHeight: 0, + ExtensionOptions: []*codectypes.Any{option}, + NonCriticalExtensionOptions: []*codectypes.Any{}, + }, + AuthInfo: &tx.AuthInfo{ + SignerInfos: []*tx.SignerInfo{}, + Fee: &tx.Fee{ + Amount: feeAmount, + GasLimit: 100000, + Payer: "", + Granter: "", + }, + Tip: nil, + }, + Signatures: [][]byte{}, + } + } + + testCases := []struct { + name string + createTx func() sdktypes.Tx + expectedErr error + errContains string + }{ + { + name: "success: valid transaction", + createTx: func() sdktypes.Tx { + protoTx := createValidProtoTx() + // Set the message + msgAny, err := codectypes.NewAnyWithValue(msgEthTx) + s.Require().NoError(err) + protoTx.Body.Messages = []*codectypes.Any{msgAny} + return &mockTx{protoTx: protoTx} + }, + expectedErr: nil, + }, + { + name: "fail: transaction does not implement ProtoTxProvider", + createTx: func() sdktypes.Tx { + // Create a transaction that doesn't implement ProtoTxProvider + return &mockTxWithoutProto{} + }, + expectedErr: errortypes.ErrUnknownRequest, + errContains: "didn't implement interface ProtoTxProvider", + }, + { + name: "fail: body Memo is not empty", + createTx: func() sdktypes.Tx { + protoTx := createValidProtoTx() + protoTx.Body.Memo = "test memo" + msgAny, err := codectypes.NewAnyWithValue(msgEthTx) + s.Require().NoError(err) + protoTx.Body.Messages = []*codectypes.Any{msgAny} + return &mockTx{protoTx: protoTx} + }, + expectedErr: errortypes.ErrInvalidRequest, + errContains: "Memo", + }, + { + name: "fail: body TimeoutHeight is not zero", + createTx: func() sdktypes.Tx { + protoTx := createValidProtoTx() + protoTx.Body.TimeoutHeight = 100 + msgAny, err := codectypes.NewAnyWithValue(msgEthTx) + s.Require().NoError(err) + protoTx.Body.Messages = []*codectypes.Any{msgAny} + return &mockTx{protoTx: protoTx} + }, + expectedErr: errortypes.ErrInvalidRequest, + errContains: "TimeoutHeight", + }, + { + name: "fail: body NonCriticalExtensionOptions is not empty", + createTx: func() sdktypes.Tx { + protoTx := createValidProtoTx() + option, err := codectypes.NewAnyWithValue(&evmtypes.ExtensionOptionsEthereumTx{}) + s.Require().NoError(err) + protoTx.Body.NonCriticalExtensionOptions = []*codectypes.Any{option} + msgAny, err := codectypes.NewAnyWithValue(msgEthTx) + s.Require().NoError(err) + protoTx.Body.Messages = []*codectypes.Any{msgAny} + return &mockTx{protoTx: protoTx} + }, + expectedErr: errortypes.ErrInvalidRequest, + errContains: "NonCriticalExtensionOptions", + }, + { + name: "fail: body ExtensionOptions length is not 1", + createTx: func() sdktypes.Tx { + protoTx := createValidProtoTx() + protoTx.Body.ExtensionOptions = []*codectypes.Any{} // empty + msgAny, err := codectypes.NewAnyWithValue(msgEthTx) + s.Require().NoError(err) + protoTx.Body.Messages = []*codectypes.Any{msgAny} + return &mockTx{protoTx: protoTx} + }, + expectedErr: errortypes.ErrInvalidRequest, + errContains: "ExtensionOptions should be 1", + }, + { + name: "fail: body ExtensionOptions length is greater than 1", + createTx: func() sdktypes.Tx { + protoTx := createValidProtoTx() + option1, err := codectypes.NewAnyWithValue(&evmtypes.ExtensionOptionsEthereumTx{}) + s.Require().NoError(err) + option2, err := codectypes.NewAnyWithValue(&evmtypes.ExtensionOptionsEthereumTx{}) + s.Require().NoError(err) + protoTx.Body.ExtensionOptions = []*codectypes.Any{option1, option2} + msgAny, err := codectypes.NewAnyWithValue(msgEthTx) + s.Require().NoError(err) + protoTx.Body.Messages = []*codectypes.Any{msgAny} + return &mockTx{protoTx: protoTx} + }, + expectedErr: errortypes.ErrInvalidRequest, + errContains: "ExtensionOptions should be 1", + }, + { + name: "fail: AuthInfo SignerInfos is not empty", + createTx: func() sdktypes.Tx { + protoTx := createValidProtoTx() + protoTx.AuthInfo.SignerInfos = []*tx.SignerInfo{ + {}, + } + msgAny, err := codectypes.NewAnyWithValue(msgEthTx) + s.Require().NoError(err) + protoTx.Body.Messages = []*codectypes.Any{msgAny} + return &mockTx{protoTx: protoTx} + }, + expectedErr: errortypes.ErrInvalidRequest, + errContains: "SignerInfos should be empty", + }, + { + name: "fail: AuthInfo Fee is nil", + createTx: func() sdktypes.Tx { + protoTx := createValidProtoTx() + protoTx.AuthInfo.Fee = nil + msgAny, err := codectypes.NewAnyWithValue(msgEthTx) + s.Require().NoError(err) + protoTx.Body.Messages = []*codectypes.Any{msgAny} + return &mockTx{protoTx: protoTx} + }, + expectedErr: errortypes.ErrInvalidRequest, + errContains: "authInfo.Fee should not be nil", + }, + { + name: "fail: AuthInfo Fee Payer is not empty", + createTx: func() sdktypes.Tx { + protoTx := createValidProtoTx() + protoTx.AuthInfo.Fee.Payer = "cosmos1test" + msgAny, err := codectypes.NewAnyWithValue(msgEthTx) + s.Require().NoError(err) + protoTx.Body.Messages = []*codectypes.Any{msgAny} + return &mockTx{protoTx: protoTx} + }, + expectedErr: errortypes.ErrInvalidRequest, + errContains: "payer and granter should be empty", + }, + { + name: "fail: AuthInfo Fee Granter is not empty", + createTx: func() sdktypes.Tx { + protoTx := createValidProtoTx() + protoTx.AuthInfo.Fee.Granter = "cosmos1test" + msgAny, err := codectypes.NewAnyWithValue(msgEthTx) + s.Require().NoError(err) + protoTx.Body.Messages = []*codectypes.Any{msgAny} + return &mockTx{protoTx: protoTx} + }, + expectedErr: errortypes.ErrInvalidRequest, + errContains: "payer and granter should be empty", + }, + { + name: "fail: AuthInfo Tip is not nil", + createTx: func() sdktypes.Tx { + protoTx := createValidProtoTx() + protoTx.AuthInfo.Tip = &tx.Tip{ + Amount: sdktypes.NewCoins(), + } + msgAny, err := codectypes.NewAnyWithValue(msgEthTx) + s.Require().NoError(err) + protoTx.Body.Messages = []*codectypes.Any{msgAny} + return &mockTx{protoTx: protoTx} + }, + expectedErr: errortypes.ErrInvalidRequest, + errContains: "authInfo.Tip must be nil", + }, + { + name: "fail: Signatures is not empty", + createTx: func() sdktypes.Tx { + protoTx := createValidProtoTx() + protoTx.Signatures = [][]byte{[]byte("signature")} + msgAny, err := codectypes.NewAnyWithValue(msgEthTx) + s.Require().NoError(err) + protoTx.Body.Messages = []*codectypes.Any{msgAny} + return &mockTx{protoTx: protoTx} + }, + expectedErr: errortypes.ErrInvalidRequest, + errContains: "Signatures should be empty", + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + testTx := tc.createTx() + + // Function under test + fee, err := evm.ValidateTx(testTx) + + if tc.expectedErr != nil { + s.Require().Error(err) + s.Contains(err.Error(), tc.expectedErr.Error()) + if tc.errContains != "" { + s.Contains(err.Error(), tc.errContains) + } + s.Nil(fee) + } else { + s.Require().NoError(err) + s.NotNil(fee) + } + }) + } +} + +// mockTxWithoutProto is a mock transaction that doesn't implement ProtoTxProvider +type mockTxWithoutProto struct{} + +func (m *mockTxWithoutProto) GetMsgs() []sdktypes.Msg { + return nil +} + +func (m *mockTxWithoutProto) GetMsgsV2() ([]protov2.Message, error) { + return nil, nil +} + +func (m *mockTxWithoutProto) ValidateBasic() error { + return nil +} diff --git a/tests/integration/ante/test_evm_unit_06_account_verification.go b/tests/integration/ante/test_evm_unit_06_account_verification.go index b9e248af..58e1d428 100644 --- a/tests/integration/ante/test_evm_unit_06_account_verification.go +++ b/tests/integration/ante/test_evm_unit_06_account_verification.go @@ -12,7 +12,6 @@ import ( "github.com/cosmos/evm/testutil/integration/evm/grpc" "github.com/cosmos/evm/testutil/integration/evm/network" testkeyring "github.com/cosmos/evm/testutil/keyring" - "github.com/cosmos/evm/x/precisebank/types" "github.com/cosmos/evm/x/vm/statedb" evmtypes "github.com/cosmos/evm/x/vm/types" @@ -108,7 +107,6 @@ func (s *EvmUnitAnteTestSuite) TestVerifyAccountBalance() { balance, ok := math.NewIntFromString(balanceResp.Balance) s.Require().True(ok) - balance = balance.Quo(types.ConversionFactor()) // replace with vesting account ctx := unitNetwork.GetContext() @@ -131,7 +129,7 @@ func (s *EvmUnitAnteTestSuite) TestVerifyAccountBalance() { s.Require().Equal(totalBalance.Amount, balance) statedbAccount := getDefaultStateDBAccount(unitNetwork, senderKey.Addr) - s.Require().Equal(spendable.String(), math.NewIntFromBigInt(statedbAccount.Balance.ToBig()).Quo(types.ConversionFactor()).String()) + s.Require().Equal(spendable.String(), math.NewIntFromBigInt(statedbAccount.Balance.ToBig()).String()) return statedbAccount, txArgs }, }, @@ -148,7 +146,6 @@ func (s *EvmUnitAnteTestSuite) TestVerifyAccountBalance() { balance, ok := math.NewIntFromString(balanceResp.Balance) s.Require().True(ok) - balance = balance.Quo(types.ConversionFactor()) // replace with vesting account ctx := unitNetwork.GetContext() @@ -189,7 +186,7 @@ func (s *EvmUnitAnteTestSuite) TestVerifyAccountBalance() { s.Require().Equal(totalBalance.Amount, balance.Mul(math.NewInt(2))) statedbAccount := getDefaultStateDBAccount(unitNetwork, senderKey.Addr) - s.Require().Equal(spendable.String(), math.NewIntFromBigInt(statedbAccount.Balance.ToBig()).Quo(types.ConversionFactor()).String()) + s.Require().Equal(spendable.String(), math.NewIntFromBigInt(statedbAccount.Balance.ToBig()).String()) return statedbAccount, txArgs }, }, diff --git a/tests/integration/ante/test_evm_unit_07_can_transfer.go b/tests/integration/ante/test_evm_unit_07_can_transfer.go index 18a9b6fd..c4fc90c4 100644 --- a/tests/integration/ante/test_evm_unit_07_can_transfer.go +++ b/tests/integration/ante/test_evm_unit_07_can_transfer.go @@ -9,7 +9,6 @@ import ( "github.com/cosmos/evm/testutil/integration/evm/grpc" "github.com/cosmos/evm/testutil/integration/evm/network" testkeyring "github.com/cosmos/evm/testutil/keyring" - "github.com/cosmos/evm/x/precisebank/types" evmtypes "github.com/cosmos/evm/x/vm/types" "cosmossdk.io/math" @@ -76,7 +75,6 @@ func (s *EvmUnitAnteTestSuite) TestCanTransfer() { balance, ok := math.NewIntFromString(balanceResp.Balance) s.Require().True(ok) - balance = balance.Quo(types.ConversionFactor()) // replace with vesting account ctx := unitNetwork.GetContext() @@ -110,7 +108,6 @@ func (s *EvmUnitAnteTestSuite) TestCanTransfer() { balance, ok := math.NewIntFromString(balanceResp.Balance) s.Require().True(ok) - balance = balance.Quo(types.ConversionFactor()) // replace with vesting account ctx := unitNetwork.GetContext() diff --git a/tests/integration/ante/test_evm_unit_10_gas_wanted.go b/tests/integration/ante/test_evm_unit_10_gas_wanted.go deleted file mode 100644 index c0f4fb18..00000000 --- a/tests/integration/ante/test_evm_unit_10_gas_wanted.go +++ /dev/null @@ -1,138 +0,0 @@ -package ante - -import ( - "fmt" - - "github.com/cosmos/evm/ante/evm" - testconstants "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/testutil/integration/evm/factory" - "github.com/cosmos/evm/testutil/integration/evm/grpc" - "github.com/cosmos/evm/testutil/integration/evm/network" - "github.com/cosmos/evm/testutil/integration/evm/utils" - testkeyring "github.com/cosmos/evm/testutil/keyring" - evmtypes "github.com/cosmos/evm/x/vm/types" - - storetypes "cosmossdk.io/store/types" - - sdktypes "github.com/cosmos/cosmos-sdk/types" - errortypes "github.com/cosmos/cosmos-sdk/types/errors" -) - -func (s *EvmUnitAnteTestSuite) TestCheckGasWanted() { - keyring := testkeyring.New(1) - unitNetwork := network.NewUnitTestNetwork( - s.create, - network.WithChainID(testconstants.ChainID{ - ChainID: s.ChainID, - EVMChainID: s.EvmChainID, - }), - network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), - ) - grpcHandler := grpc.NewIntegrationHandler(unitNetwork) - txFactory := factory.New(unitNetwork, grpcHandler) - commonGasLimit := uint64(100_000) - - testCases := []struct { - name string - expectedError error - getCtx func() sdktypes.Context - isLondon bool - expectedTransientGasWanted uint64 - }{ - { - name: "success: if isLondon false it should not error", - expectedError: nil, - getCtx: func() sdktypes.Context { - // Even if the gasWanted is more than the blockGasLimit, it should not error - blockMeter := storetypes.NewGasMeter(commonGasLimit - 10000) - return unitNetwork.GetContext().WithBlockGasMeter(blockMeter) - }, - isLondon: false, - expectedTransientGasWanted: 0, - }, - { - name: "success: gasWanted is less than blockGasLimit", - expectedError: nil, - getCtx: func() sdktypes.Context { - blockMeter := storetypes.NewGasMeter(commonGasLimit + 10000) - return unitNetwork.GetContext().WithBlockGasMeter(blockMeter) - }, - isLondon: true, - expectedTransientGasWanted: commonGasLimit, - }, - { - name: "fail: gasWanted is more than blockGasLimit", - expectedError: errortypes.ErrOutOfGas, - getCtx: func() sdktypes.Context { - blockMeter := storetypes.NewGasMeter(commonGasLimit - 10000) - return unitNetwork.GetContext().WithBlockGasMeter(blockMeter) - }, - isLondon: true, - expectedTransientGasWanted: 0, - }, - { - name: "success: gasWanted is less than blockGasLimit and basefee param is disabled", - expectedError: nil, - getCtx: func() sdktypes.Context { - // Set basefee param to false - feeMarketParams, err := grpcHandler.GetFeeMarketParams() - s.Require().NoError(err) - - feeMarketParams.Params.NoBaseFee = true - err = utils.UpdateFeeMarketParams(utils.UpdateParamsInput{ - Tf: txFactory, - Network: unitNetwork, - Pk: keyring.GetPrivKey(0), - Params: feeMarketParams.Params, - }) - s.Require().NoError(err, "expected no error when updating fee market params") - - blockMeter := storetypes.NewGasMeter(commonGasLimit + 10_000) - return unitNetwork.GetContext().WithBlockGasMeter(blockMeter) - }, - isLondon: true, - expectedTransientGasWanted: 0, - }, - } - - for _, tc := range testCases { - s.Run(fmt.Sprintf("%v_%v_%v", evmtypes.GetTxTypeName(s.EthTxType), s.ChainID, tc.name), func() { - sender := keyring.GetKey(0) - txArgs, err := txFactory.GenerateDefaultTxTypeArgs( - sender.Addr, - s.EthTxType, - ) - s.Require().NoError(err) - txArgs.GasLimit = commonGasLimit - tx, err := txFactory.GenerateSignedEthTx(sender.Priv, txArgs) - s.Require().NoError(err) - - ctx := tc.getCtx() - feemarketkeeper := unitNetwork.App.GetFeeMarketKeeper() - feemarketParam := feemarketkeeper.GetParams(ctx) - // Function under test - err = evm.CheckGasWanted( - ctx, - feemarketkeeper, - tx, - tc.isLondon, - &feemarketParam, - ) - - if tc.expectedError != nil { - s.Require().Error(err) - s.Contains(err.Error(), tc.expectedError.Error()) - } else { - s.Require().NoError(err) - transientGasWanted := feemarketkeeper.GetTransientGasWanted( - unitNetwork.GetContext(), - ) - s.Require().Equal(tc.expectedTransientGasWanted, transientGasWanted) - } - - // Start from a fresh block and ctx - err = unitNetwork.NextBlock() - s.Require().NoError(err) - }) - } -} diff --git a/tests/integration/ante/test_validate_handler_options.go b/tests/integration/ante/test_validate_handler_options.go index ccd2c1ee..dad97ae7 100644 --- a/tests/integration/ante/test_validate_handler_options.go +++ b/tests/integration/ante/test_validate_handler_options.go @@ -6,6 +6,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" + evm "github.com/cosmos/evm" "github.com/cosmos/evm/ante" antetypes "github.com/cosmos/evm/ante/types" "github.com/cosmos/evm/testutil/integration/evm/network" @@ -14,6 +15,7 @@ import ( //nolint:thelper // RunValidateHandlerOptionsTest is not a helper function; it's an externally called benchmark entry point func RunValidateHandlerOptionsTest(t *testing.T, create network.CreateEvmApp, options ...network.ConfigOption) { nw := network.NewUnitTestNetwork(create, options...) + ibcKeeper := nw.App.(evm.IBCKeeperProvider).GetIBCKeeper() cases := []struct { name string options ante.HandlerOptions @@ -57,7 +59,7 @@ func RunValidateHandlerOptionsTest(t *testing.T, create network.CreateEvmApp, op Cdc: nw.App.AppCodec(), AccountKeeper: nw.App.GetAccountKeeper(), BankKeeper: nw.App.GetBankKeeper(), - IBCKeeper: nw.App.GetIBCKeeper(), + IBCKeeper: ibcKeeper, FeeMarketKeeper: nil, }, false, @@ -68,7 +70,7 @@ func RunValidateHandlerOptionsTest(t *testing.T, create network.CreateEvmApp, op Cdc: nw.App.AppCodec(), AccountKeeper: nw.App.GetAccountKeeper(), BankKeeper: nw.App.GetBankKeeper(), - IBCKeeper: nw.App.GetIBCKeeper(), + IBCKeeper: ibcKeeper, FeeMarketKeeper: nw.App.GetFeeMarketKeeper(), EvmKeeper: nil, }, @@ -80,7 +82,7 @@ func RunValidateHandlerOptionsTest(t *testing.T, create network.CreateEvmApp, op Cdc: nw.App.AppCodec(), AccountKeeper: nw.App.GetAccountKeeper(), BankKeeper: nw.App.GetBankKeeper(), - IBCKeeper: nw.App.GetIBCKeeper(), + IBCKeeper: ibcKeeper, FeeMarketKeeper: nw.App.GetFeeMarketKeeper(), EvmKeeper: nw.App.GetEVMKeeper(), SigGasConsumer: nil, @@ -93,7 +95,7 @@ func RunValidateHandlerOptionsTest(t *testing.T, create network.CreateEvmApp, op Cdc: nw.App.AppCodec(), AccountKeeper: nw.App.GetAccountKeeper(), BankKeeper: nw.App.GetBankKeeper(), - IBCKeeper: nw.App.GetIBCKeeper(), + IBCKeeper: ibcKeeper, FeeMarketKeeper: nw.App.GetFeeMarketKeeper(), EvmKeeper: nw.App.GetEVMKeeper(), SigGasConsumer: ante.SigVerificationGasConsumer, @@ -107,7 +109,7 @@ func RunValidateHandlerOptionsTest(t *testing.T, create network.CreateEvmApp, op Cdc: nw.App.AppCodec(), AccountKeeper: nw.App.GetAccountKeeper(), BankKeeper: nw.App.GetBankKeeper(), - IBCKeeper: nw.App.GetIBCKeeper(), + IBCKeeper: ibcKeeper, FeeMarketKeeper: nw.App.GetFeeMarketKeeper(), EvmKeeper: nw.App.GetEVMKeeper(), SigGasConsumer: ante.SigVerificationGasConsumer, @@ -124,7 +126,7 @@ func RunValidateHandlerOptionsTest(t *testing.T, create network.CreateEvmApp, op ExtensionOptionChecker: antetypes.HasDynamicFeeExtensionOption, EvmKeeper: nw.App.GetEVMKeeper(), FeegrantKeeper: nw.App.GetFeeGrantKeeper(), - IBCKeeper: nw.App.GetIBCKeeper(), + IBCKeeper: ibcKeeper, FeeMarketKeeper: nw.App.GetFeeMarketKeeper(), SignModeHandler: nw.GetEncodingConfig().TxConfig.SignModeHandler(), SigGasConsumer: ante.SigVerificationGasConsumer, @@ -143,7 +145,7 @@ func RunValidateHandlerOptionsTest(t *testing.T, create network.CreateEvmApp, op ExtensionOptionChecker: antetypes.HasDynamicFeeExtensionOption, EvmKeeper: nw.App.GetEVMKeeper(), FeegrantKeeper: nw.App.GetFeeGrantKeeper(), - IBCKeeper: nw.App.GetIBCKeeper(), + IBCKeeper: ibcKeeper, FeeMarketKeeper: nw.App.GetFeeMarketKeeper(), SignModeHandler: nw.GetEncodingConfig().TxConfig.SignModeHandler(), SigGasConsumer: ante.SigVerificationGasConsumer, diff --git a/tests/integration/eip712/test_eip712.go b/tests/integration/eip712/test_eip712.go index cd7d19a2..32480077 100644 --- a/tests/integration/eip712/test_eip712.go +++ b/tests/integration/eip712/test_eip712.go @@ -10,7 +10,6 @@ import ( "github.com/tidwall/gjson" "github.com/tidwall/sjson" - "github.com/cosmos/evm/config" "github.com/cosmos/evm/crypto/ethsecp256k1" "github.com/cosmos/evm/ethereum/eip712" "github.com/cosmos/evm/testutil/constants" @@ -72,8 +71,6 @@ func (s *TestSuite) SetupTest() { s.config = nw.GetEncodingConfig() s.clientCtx = client.Context{}.WithTxConfig(s.config.TxConfig) s.denom = evmtypes.GetEVMCoinDenom() - - sdk.GetConfig().SetBech32PrefixForAccount(config.Bech32Prefix, "") } // createTestAddress creates random test addresses for messages diff --git a/tests/integration/eip712/test_eip712_fuzzer.go b/tests/integration/eip712/test_eip712_fuzzer.go index 36d3e4e7..cfcea9a7 100644 --- a/tests/integration/eip712/test_eip712_fuzzer.go +++ b/tests/integration/eip712/test_eip712_fuzzer.go @@ -174,6 +174,7 @@ func (s *TestSuite) createRandomString() string { bz := make([]byte, bzLen) for i := 0; i < bzLen; i++ { + // #nosec G115 -- ascii range constrains to 0-255 bz[i] = byte(s.createRandomIntInRange(asciiRangeStart, asciiRangeEnd)) } diff --git a/tests/integration/eip7702/test_integration.go b/tests/integration/eip7702/test_integration.go index f80886b7..783379f8 100644 --- a/tests/integration/eip7702/test_integration.go +++ b/tests/integration/eip7702/test_integration.go @@ -122,7 +122,7 @@ func TestEIP7702IntegrationTestSuite(t *testing.T, create network.CreateEvmApp, stateDB := s.network.GetStateDB() sdAddr := utiltx.GenerateAddress() stateDB.CreateAccount(sdAddr) - stateDB.SetCode(sdAddr, []byte{0x60, 0x00}) + stateDB.SetCode(sdAddr, []byte{0x60, 0x00}, 0x0) stateDB.SelfDestruct(sdAddr) Expect(stateDB.Commit()).To(BeNil()) Expect(s.network.NextBlock()).To(BeNil()) diff --git a/tests/integration/indexer/test_kv_indexer.go b/tests/integration/indexer/test_kv_indexer.go index 93a62d8d..70762acf 100644 --- a/tests/integration/indexer/test_kv_indexer.go +++ b/tests/integration/indexer/test_kv_indexer.go @@ -19,7 +19,7 @@ import ( utiltx "github.com/cosmos/evm/testutil/tx" "github.com/cosmos/evm/x/vm/types" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" "github.com/cosmos/cosmos-sdk/client" ) diff --git a/tests/integration/mempool/test_helpers.go b/tests/integration/mempool/test_helpers.go index 1c87c058..8019e5f9 100644 --- a/tests/integration/mempool/test_helpers.go +++ b/tests/integration/mempool/test_helpers.go @@ -4,34 +4,38 @@ 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" + "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) // Constants const ( - TxGas = 100_000 + TxGas = 100_000 + feeDenom = "aatom" ) -// createCosmosSendTransactionWithKey creates a simple bank send transaction with the specified key +// createCosmosSendTransactionWithKey creates a simple bank send transaction +// with the specified key, sending 1000aatom func (s *IntegrationTestSuite) createCosmosSendTx(key keyring.Key, gasPrice *big.Int) sdk.Tx { - feeDenom := "aatom" + return s.createCosmosSendTxWithAmount(key, big.NewInt(1000), gasPrice) +} +// createCosmosSendTransactionWithKey creates a simple bank send transaction +// with the specified key and amount +func (s *IntegrationTestSuite) createCosmosSendTxWithAmount(key keyring.Key, amt *big.Int, gasPrice *big.Int) sdk.Tx { fromAddr := key.AccAddr toAddr := s.keyring.GetKey(1).AccAddr - amount := sdk.NewCoins(sdk.NewInt64Coin(feeDenom, 1000)) + amount := sdk.NewCoins(sdk.NewCoin(feeDenom, sdkmath.NewIntFromBigInt(amt))) bankMsg := banktypes.NewMsgSend(fromAddr, toAddr, amount) @@ -47,8 +51,74 @@ func (s *IntegrationTestSuite) createCosmosSendTx(key keyring.Key, gasPrice *big return tx } -// createEVMTransaction creates an EVM transaction using the provided key +// createCosmosSendTransactionWithKey creates a simple bank send transaction +// with the specified key and amount. Uses a custom nonce for the sender that +// may not match what is currently the next nonce on chain for this sender. +// Requires a custom gasLimit to be set to prevent simulation of the tx in +// order to fetch the gas limit (since this will fail due to a nonce mismatch). +func (s *IntegrationTestSuite) createCosmosSendTxWithNonceAndGas(key keyring.Key, nonce uint64, amt *big.Int, gasLimit uint64, gasPrice *big.Int) sdk.Tx { + fromAddr := key.AccAddr + toAddr := s.keyring.GetKey(1).AccAddr + amount := sdk.NewCoins(sdk.NewCoin(feeDenom, sdkmath.NewIntFromBigInt(amt))) + + bankMsg := banktypes.NewMsgSend(fromAddr, toAddr, amount) + + gasPriceConverted := sdkmath.NewIntFromBigInt(gasPrice) + + txArgs := factory.CosmosTxArgs{ + Msgs: []sdk.Msg{bankMsg}, + GasPrice: &gasPriceConverted, + Nonce: &nonce, + Gas: &gasLimit, + } + tx, err := s.factory.BuildCosmosTx(key.Priv, txArgs) + s.Require().NoError(err) + + return tx +} + +func (s *IntegrationTestSuite) createMultiSignerCosmosSendTx(gasPrice *big.Int, keys ...keyring.Key) sdk.Tx { + return s.createMultiSignerCosmosSendTxWithAmount(big.NewInt(1000), gasPrice, keys...) +} + +func (s *IntegrationTestSuite) createMultiSignerCosmosSendTxWithAmount(amt *big.Int, gasPrice *big.Int, keys ...keyring.Key) sdk.Tx { + if len(keys) == 0 { + panic("no keys provided") + } + + toAddr := s.keyring.GetKey(9).AccAddr + amount := sdk.NewCoins(sdk.NewCoin(feeDenom, sdkmath.NewIntFromBigInt(amt))) + + // one MsgSend per signer so the tx's aggregated GetSigners() returns one + // entry per provided key + msgs := make([]sdk.Msg, len(keys)) + privs := make([]types.PrivKey, len(keys)) + for i, key := range keys { + msgs[i] = banktypes.NewMsgSend(key.AccAddr, toAddr, amount) + privs[i] = key.Priv + } + + gasPriceConverted := sdkmath.NewIntFromBigInt(gasPrice) + + txArgs := factory.CosmosTxArgs{ + Msgs: msgs, + GasPrice: &gasPriceConverted, + } + tx, err := s.factory.BuildMultiSignerCosmosTx(txArgs, privs...) + s.Require().NoError(err) + + return tx +} + +// createEVMTransaction creates an EVM transaction using the provided key, +// nonce, and gas price. Defaults to sending 1000 of the native gas token func (s *IntegrationTestSuite) createEVMValueTransferTx(key keyring.Key, nonce int, gasPrice *big.Int) sdk.Tx { + return s.createEVMValueTransferTxWithValue(key, nonce, big.NewInt(1000), gasPrice) +} + +// createEVMTransaction creates an EVM transaction using the provided key, +// nonce, value, and gas price +func (s *IntegrationTestSuite) createEVMValueTransferTxWithValue(key keyring.Key, nonce int, value *big.Int, gasPrice *big.Int) sdk.Tx { to := s.keyring.GetKey(1).Addr if nonce < 0 { @@ -56,9 +126,10 @@ func (s *IntegrationTestSuite) createEVMValueTransferTx(key keyring.Key, nonce i } ethTxArgs := evmtypes.EvmTxArgs{ + // #nosec G115 -- nonce checked >= 0 above Nonce: uint64(nonce), To: &to, - Amount: big.NewInt(1000), + Amount: value, GasLimit: TxGas, GasPrice: gasPrice, Input: nil, @@ -78,6 +149,7 @@ func (s *IntegrationTestSuite) createEVMValueTransferDynamicFeeTx(key keyring.Ke } ethTxArgs := evmtypes.EvmTxArgs{ + // #nosec G115 -- nonce checked >= 0 above Nonce: uint64(nonce), To: &to, Amount: big.NewInt(1000), @@ -108,51 +180,19 @@ func (s *IntegrationTestSuite) createEVMContractDeployTx(key keyring.Key, gasPri 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 +// insertTxs call mempool Insert for multiple transactions +func (s *IntegrationTestSuite) insertTxs(txs []sdk.Tx) error { + for idx, tx := range txs { + if err := s.insertTx(tx); err != nil { + return fmt.Errorf("failed to insert for tx at idx %d %s: %w", idx, s.getTxHash(tx), 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 +// insertTx call mempool Insert for a transaction +func (s *IntegrationTestSuite) insertTx(tx sdk.Tx) error { + return s.network.App.GetMempool().Insert(s.network.GetContext(), tx) } // getTxHashes returns transaction hashes for multiple transactions @@ -194,28 +234,3 @@ func (s *IntegrationTestSuite) calculateCosmosEffectiveTip(feeAmount int64, gasL 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 32e24a4a..19f0ff9f 100644 --- a/tests/integration/mempool/test_mempool_integration.go +++ b/tests/integration/mempool/test_mempool_integration.go @@ -8,6 +8,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/require" + evmmempool "github.com/cosmos/evm/mempool" "github.com/cosmos/evm/testutil/integration/evm/network" "github.com/cosmos/evm/testutil/keyring" evmtypes "github.com/cosmos/evm/x/vm/types" @@ -28,7 +29,7 @@ func (s *IntegrationTestSuite) TestMempoolInsert() { { name: "cosmos transaction success", setupTx: func() sdk.Tx { - return s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(1000)) + return s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(1000000000)) }, wantError: false, verifyFunc: func() { @@ -36,6 +37,32 @@ func (s *IntegrationTestSuite) TestMempoolInsert() { s.Require().Equal(1, mpool.CountTx()) }, }, + { + name: "failed cosmos insert does not propagate state", + setupTx: func() sdk.Tx { + // create a tx that will use the entire balance of the sender + balance := network.PrefundedAccountInitialBalance.BigInt() + gasPrice := new(big.Int).Quo(balance, new(big.Int).SetUint64(TxGas/2)) + return s.createCosmosSendTx(s.keyring.GetKey(0), gasPrice) + }, + wantError: true, // want the above tx to fail to insert + verifyFunc: func() { + balance := network.PrefundedAccountInitialBalance.BigInt() + // spend half the balance, ensure that the above tx spending + // our entire balance does not persist that state across + // inserts + gasPrice := new(big.Int).Quo(balance, new(big.Int).SetUint64(TxGas*2)) + + mpool := s.network.App.GetMempool() + + // try to insert a valid tx for the sender, ensure this succeeds + tx := s.createCosmosSendTx(s.keyring.GetKey(0), gasPrice) + s.Require().NoError(mpool.Insert(s.network.GetContext(), tx)) + + // ensure it made it into the pool + s.Require().Equal(1, mpool.CountTx()) + }, + }, { name: "EVM transaction success", setupTx: func() sdk.Tx { @@ -68,8 +95,7 @@ func (s *IntegrationTestSuite) TestMempoolInsert() { txBuilder := s.network.App.GetTxConfig().NewTxBuilder() return txBuilder.GetTx() }, - wantError: true, - errorContains: "tx must have at least one signer", + wantError: true, verifyFunc: func() { }, }, @@ -126,7 +152,7 @@ func (s *IntegrationTestSuite) TestMempoolInsert() { return txBuilder.GetTx() }, wantError: true, - errorContains: "tx must have at least one signer", // assumes that this is a cosmos message because multiple evm messages fail + errorContains: "multiple messages with an EVM msg", verifyFunc: func() { }, }, @@ -134,6 +160,8 @@ func (s *IntegrationTestSuite) TestMempoolInsert() { for _, tc := range testCases { s.Run(tc.name, func() { + // Clean up previous test's resources before resetting + s.TearDownTest() // Reset test setup to ensure clean state s.SetupTest() @@ -166,18 +194,6 @@ func (s *IntegrationTestSuite) TestMempoolRemove() { errorContains string verifyFunc func() }{ - { - name: "remove cosmos transaction success", - setupTx: func() sdk.Tx { - return s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(1000)) - }, - insertFirst: true, - wantError: false, - verifyFunc: func() { - mpool := s.network.App.GetMempool() - s.Require().Equal(0, mpool.CountTx()) - }, - }, { name: "remove EVM transaction fail", setupTx: func() sdk.Tx { @@ -203,36 +219,30 @@ func (s *IntegrationTestSuite) TestMempoolRemove() { verifyFunc: func() { }, }, - { - name: "remove non-existent transaction", - setupTx: func() sdk.Tx { - return s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(1000)) - }, - insertFirst: false, - wantError: true, // Remove should error for non-existent transactions - errorContains: "tx not found in mempool", - verifyFunc: func() { - mpool := s.network.App.GetMempool() - s.Require().Equal(0, mpool.CountTx()) - }, - }, } for _, tc := range testCases { s.Run(tc.name, func() { + // Clean up previous test's resources before resetting + s.TearDownTest() // Reset test setup to ensure clean state s.SetupTest() tx := tc.setupTx() - mpool := s.network.App.GetMempool() + mp := s.network.App.GetMempool() if tc.insertFirst { - err := mpool.Insert(s.network.GetContext(), tx) + err := mp.Insert(s.network.GetContext(), tx) require.NoError(s.T(), err) - require.Equal(s.T(), 1, mpool.CountTx()) + require.Equal(s.T(), 1, mp.CountTx()) } - err := mpool.Remove(tx) + reason := mempool.RemoveReason{ + Caller: "test_mempool_remove", + Error: nil, + } + + err := mempool.RemoveWithReason(s.network.GetContext(), mp, tx, reason) if tc.wantError { require.Error(s.T(), err) @@ -266,7 +276,7 @@ func (s *IntegrationTestSuite) TestMempoolSelect() { { name: "single cosmos transaction", setupTxs: func() { - cosmosTx := s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(2000)) + cosmosTx := s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(2000000000)) mpool := s.network.App.GetMempool() err := mpool.Insert(s.network.GetContext(), cosmosTx) s.Require().NoError(err) @@ -304,13 +314,24 @@ func (s *IntegrationTestSuite) TestMempoolSelect() { for _, tc := range testCases { s.Run(tc.name, func() { + // Clean up previous test's resources before resetting + s.TearDownTest() // Reset test setup to ensure clean state s.SetupTest() tc.setupTxs() + // Refresh the cached latestCtx and trigger cosmos recheck so + // cosmos txs are available via Select (mirrors production flow + // where recheck happens after a new block notification). mpool := s.network.App.GetMempool() - iterator := mpool.Select(s.network.GetContext(), nil) + ctx := s.network.GetContext() + if kMp, ok := mpool.(*evmmempool.Mempool); ok { + head := kMp.GetBlockchain().CurrentBlock() + kMp.RecheckEVMTxs(head) + kMp.RecheckCosmosTxs(head) + } + iterator := mpool.Select(ctx.WithBlockHeight(ctx.BlockHeight()+1), nil) tc.verifyFunc(iterator) }) } @@ -334,7 +355,7 @@ func (s *IntegrationTestSuite) TestMempoolIterator() { { name: "single cosmos transaction iteration", setupTxs: func() { - cosmosTx := s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(2000)) + cosmosTx := s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(2000000000)) mpool := s.network.App.GetMempool() err := mpool.Insert(s.network.GetContext(), cosmosTx) s.Require().NoError(err) @@ -370,11 +391,11 @@ func (s *IntegrationTestSuite) TestMempoolIterator() { setupTxs: func() { mpool := s.network.App.GetMempool() - cosmosTx1 := s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(1000)) + cosmosTx1 := s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(1000000000)) err := mpool.Insert(s.network.GetContext(), cosmosTx1) s.Require().NoError(err) - cosmosTx2 := s.createCosmosSendTx(s.keyring.GetKey(1), big.NewInt(2000)) + cosmosTx2 := s.createCosmosSendTx(s.keyring.GetKey(1), big.NewInt(2000000000)) err = mpool.Insert(s.network.GetContext(), cosmosTx2) s.Require().NoError(err) }, @@ -394,14 +415,14 @@ func (s *IntegrationTestSuite) TestMempoolIterator() { setupTxs: func() { mpool := s.network.App.GetMempool() - // Add EVM transaction - evmTx := s.createEVMValueTransferTx(s.keyring.GetKey(0), 0, big.NewInt(2000)) + // Add EVM transaction (use key 0) + evmTx := s.createEVMValueTransferTx(s.keyring.GetKey(0), 0, big.NewInt(2000000000)) err := mpool.Insert(s.network.GetContext(), evmTx) s.Require().NoError(err) - // Add Cosmos transaction - cosmosTx := s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(2000)) + // Add Cosmos transaction (use key 2 to avoid address reservation conflict) + cosmosTx := s.createCosmosSendTx(s.keyring.GetKey(2), big.NewInt(2000000000)) err = mpool.Insert(s.network.GetContext(), cosmosTx) s.Require().NoError(err) }, @@ -419,13 +440,24 @@ func (s *IntegrationTestSuite) TestMempoolIterator() { for _, tc := range testCases { s.Run(tc.name, func() { + // Clean up previous test's resources before resetting + s.TearDownTest() // Reset test setup to ensure clean state s.SetupTest() tc.setupTxs() + // Refresh the cached latestCtx and trigger cosmos recheck so + // cosmos txs are available via Select (mirrors production flow + // where recheck happens after a new block notification). mpool := s.network.App.GetMempool() - iterator := mpool.Select(s.network.GetContext(), nil) + ctx := s.network.GetContext() + if kMp, ok := mpool.(*evmmempool.Mempool); ok { + head := kMp.GetBlockchain().CurrentBlock() + kMp.RecheckEVMTxs(head) + kMp.RecheckCosmosTxs(head) + } + iterator := mpool.Select(ctx.WithBlockHeight(ctx.BlockHeight()+1), nil) tc.verifyFunc(iterator) }) } @@ -551,11 +583,13 @@ func (s *IntegrationTestSuite) TestTransactionOrdering() { }, }, { - name: "cosmos-only transaction replacement", + name: "cosmos-only transaction ordering", setupTxs: func() { - 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 + // Cosmos txs from the same sender require incrementing sequences + // (no same-nonce replacement like EVM), so use different keys. + highFeeTx := s.createCosmosSendTx(s.keyring.GetKey(5), big.NewInt(5000000000)) // 5 gaatom + lowFeeTx := s.createCosmosSendTx(s.keyring.GetKey(6), big.NewInt(1000000000)) // 1 gaatom + mediumFeeTx := s.createCosmosSendTx(s.keyring.GetKey(7), big.NewInt(3000000000)) // 3 gaatom mpool := s.network.App.GetMempool() @@ -568,14 +602,22 @@ func (s *IntegrationTestSuite) TestTransactionOrdering() { s.Require().NoError(err) }, verifyFunc: func(iterator mempool.Iterator) { - // Should get first transaction from cosmos pool + // Should get transactions ordered by fee: high, medium, low tx1 := iterator.Tx() s.Require().NotNil(tx1) - // Calculate gas price: fee_amount / gas_limit = 5000000000 / 200000 = 25000 - expectedGasPrice := big.NewInt(5000000000) - feeTx := tx1.(sdk.FeeTx) - actualGasPrice := s.calculateCosmosGasPrice(feeTx.GetFee().AmountOf("aatom").Int64(), feeTx.GetGas()) - s.Require().Equal(expectedGasPrice, actualGasPrice, "Expected gas price should match fee_amount/gas_limit") + feeTx1 := tx1.(sdk.FeeTx) + s.Require().Equal(big.NewInt(5000000000), s.calculateCosmosGasPrice(feeTx1.GetFee().AmountOf("aatom").Int64(), feeTx1.GetGas())) + + iterator = iterator.Next() + s.Require().NotNil(iterator) + feeTx2 := iterator.Tx().(sdk.FeeTx) + s.Require().Equal(big.NewInt(3000000000), s.calculateCosmosGasPrice(feeTx2.GetFee().AmountOf("aatom").Int64(), feeTx2.GetGas())) + + iterator = iterator.Next() + s.Require().NotNil(iterator) + feeTx3 := iterator.Tx().(sdk.FeeTx) + s.Require().Equal(big.NewInt(1000000000), s.calculateCosmosGasPrice(feeTx3.GetFee().AmountOf("aatom").Int64(), feeTx3.GetGas())) + iterator = iterator.Next() s.Require().Nil(iterator) }, @@ -587,8 +629,8 @@ func (s *IntegrationTestSuite) TestTransactionOrdering() { // EVM: 1000 aatom/gas effective tip 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.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(1000000000)) // 1 gaatom/gas effective tip + // Cosmos with same effective tip (use different key to avoid address reservation conflict) + cosmosTx := s.createCosmosSendTx(s.keyring.GetKey(3), big.NewInt(1000000000)) // 1 gaatom/gas effective tip mpool := s.network.App.GetMempool() @@ -629,8 +671,8 @@ func (s *IntegrationTestSuite) TestTransactionOrdering() { // Create EVM transaction with higher gas price evmTx := s.createEVMValueTransferTx(s.keyring.GetKey(0), 0, big.NewInt(5000000000)) // 5 gaatom/gas - // Create Cosmos transaction with lower gas price - cosmosTx := s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(2000000000)) // 2 gaatom/gas + // Create Cosmos transaction with lower gas price (use different key to avoid address reservation conflict) + cosmosTx := s.createCosmosSendTx(s.keyring.GetKey(3), big.NewInt(2000000000)) // 2 gaatom/gas mpool := s.network.App.GetMempool() @@ -668,8 +710,8 @@ func (s *IntegrationTestSuite) TestTransactionOrdering() { // 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 + // Create Cosmos transaction with higher gas price (use different key to avoid address reservation conflict) + cosmosTx := s.createCosmosSendTx(s.keyring.GetKey(3), big.NewInt(5000000000)) // 5000 aatom/gas mpool := s.network.App.GetMempool() @@ -805,13 +847,24 @@ func (s *IntegrationTestSuite) TestTransactionOrdering() { for _, tc := range testCases { s.Run(tc.name, func() { + // Clean up previous test's resources before resetting + s.TearDownTest() // Reset test setup to ensure clean state s.SetupTest() tc.setupTxs() + // Refresh the cached latestCtx and trigger cosmos recheck so + // cosmos txs are available via Select (mirrors production flow + // where recheck happens after a new block notification). mpool := s.network.App.GetMempool() - iterator := mpool.Select(s.network.GetContext(), nil) + ctx := s.network.GetContext() + if kMp, ok := mpool.(*evmmempool.Mempool); ok { + head := kMp.GetBlockchain().CurrentBlock() + kMp.RecheckEVMTxs(head) + kMp.RecheckCosmosTxs(head) + } + iterator := mpool.Select(ctx.WithBlockHeight(ctx.BlockHeight()+1), nil) tc.verifyFunc(iterator) }) } @@ -838,7 +891,7 @@ func (s *IntegrationTestSuite) TestSelectBy() { { name: "single cosmos transaction - terminates properly", setupTxs: func() { - cosmosTx := s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(2000)) + cosmosTx := s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(2000000000)) mpool := s.network.App.GetMempool() err := mpool.Insert(s.network.GetContext(), cosmosTx) s.Require().NoError(err) @@ -866,19 +919,19 @@ func (s *IntegrationTestSuite) TestSelectBy() { setupTxs: func() { mpool := s.network.App.GetMempool() - // Add transactions with different fees + // Add transactions with different fees (gas prices above base fee) for i := 1; i < 6; i++ { // Use different keys for different transactions - cosmosTx := s.createCosmosSendTx(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)*1000000000)) err := mpool.Insert(s.network.GetContext(), cosmosTx) s.Require().NoError(err) } }, filterFunc: func(tx sdk.Tx) bool { - // Accept transactions with fees >= 3000, reject lower + // Accept transactions with fees >= 3 gwei * TxGas, reject lower if feeTx, ok := tx.(sdk.FeeTx); ok { fees := feeTx.GetFee() if len(fees) > 0 { - return fees[0].Amount.Int64() >= 3000*TxGas + return fees[0].Amount.Int64() >= 3000000000*TxGas } } return false @@ -923,6 +976,16 @@ func (s *IntegrationTestSuite) TestSelectBy() { tc.setupTxs() + // Refresh the cached latestCtx and trigger cosmos recheck so + // cosmos txs are available via SelectBy (mirrors production flow + // where recheck happens after a new block notification). + ctx := s.network.GetContext() + if kMp, ok := mpool.(*evmmempool.Mempool); ok { + head := kMp.GetBlockchain().CurrentBlock() + kMp.RecheckEVMTxs(head) + kMp.RecheckCosmosTxs(head) + } + // Track filter function calls to ensure we don't have infinite loops callCount := 0 wrappedFilter := func(tx sdk.Tx) bool { @@ -935,7 +998,7 @@ func (s *IntegrationTestSuite) TestSelectBy() { } // Test SelectBy directly - mpool.SelectBy(s.network.GetContext(), nil, wrappedFilter) + mpool.SelectBy(ctx.WithBlockHeight(ctx.BlockHeight()+1), nil, wrappedFilter) // Assert that SelectBy completed without hanging if tc.expectedCalls > 0 { @@ -967,7 +1030,7 @@ func (s *IntegrationTestSuite) TestMempoolHeightRequirement() { s.Require().Equal(int64(2), nw.GetContext().BlockHeight()) mpool := nw.App.GetMempool() - tx := s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(1000)) + tx := s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(1000000000)) // Should fail because mempool requires block height >= 2 err = mpool.Insert(nw.GetContext(), tx) @@ -1001,10 +1064,11 @@ func (s *IntegrationTestSuite) TestEVMTransactionComprehensive() { setupTx: func() sdk.Tx { return s.createEVMValueTransferTx(s.keyring.GetKey(0), 0, big.NewInt(100000000)) // 0.1 gaatom }, - wantError: false, + wantError: true, + errorContains: "insufficient fee", verifyFunc: func() { mpool := s.network.App.GetMempool() - s.Require().Equal(1, mpool.CountTx()) + s.Require().Equal(0, mpool.CountTx()) }, }, { diff --git a/tests/integration/mempool/test_mempool_integration_abci.go b/tests/integration/mempool/test_mempool_integration_abci.go index cd064846..ef535458 100644 --- a/tests/integration/mempool/test_mempool_integration_abci.go +++ b/tests/integration/mempool/test_mempool_integration_abci.go @@ -4,11 +4,15 @@ import ( "encoding/hex" "math/big" - "github.com/ethereum/go-ethereum/core" - abci "github.com/cometbft/cometbft/abci/types" "github.com/cometbft/cometbft/crypto/tmhash" + evmmempool "github.com/cosmos/evm/mempool" + "github.com/cosmos/evm/mempool/reserver" + "github.com/cosmos/evm/mempool/txpool/legacypool" + "github.com/cosmos/evm/testutil/integration/evm/network" + "github.com/cosmos/evm/testutil/keyring" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/mempool" ) @@ -82,8 +86,8 @@ func (s *IntegrationTestSuite) TestTransactionOrderingWithABCIMethodCalls() { { 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 + // Cosmos with same effective tip (use different key to avoid address reservation conflict) + cosmosTx := s.createCosmosSendTx(s.keyring.GetKey(9), big.NewInt(1000000000)) // 1 gaatom/gas effective tip // Create transactions with equal effective tips (assuming base fee = 0) // EVM: 1000 aatom/gas effective tip @@ -93,7 +97,7 @@ func (s *IntegrationTestSuite) TestTransactionOrderingWithABCIMethodCalls() { inputTxs := []sdk.Tx{cosmosTx, evmTx} // Expected txs in order - expectedTxs := []sdk.Tx{evmTx} + expectedTxs := []sdk.Tx{evmTx, cosmosTx} expTxHashes := s.getTxHashes(expectedTxs) return inputTxs, expTxHashes @@ -102,8 +106,8 @@ func (s *IntegrationTestSuite) TestTransactionOrderingWithABCIMethodCalls() { { 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 Cosmos transaction with lower gas price (use different key to avoid address reservation conflict) + cosmosTx := s.createCosmosSendTx(s.keyring.GetKey(9), 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 @@ -112,7 +116,7 @@ func (s *IntegrationTestSuite) TestTransactionOrderingWithABCIMethodCalls() { inputTxs := []sdk.Tx{cosmosTx, evmTx} // Expected txs in order - expectedTxs := []sdk.Tx{evmTx} + expectedTxs := []sdk.Tx{evmTx, cosmosTx} expTxHashes := s.getTxHashes(expectedTxs) return inputTxs, expTxHashes @@ -124,14 +128,14 @@ func (s *IntegrationTestSuite) TestTransactionOrderingWithABCIMethodCalls() { // 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 + // Create Cosmos transaction with higher gas price (use different key to avoid address reservation conflict) + cosmosTx := s.createCosmosSendTx(s.keyring.GetKey(9), big.NewInt(5000000000)) // 5000 aatom/gas // Input txs in order inputTxs := []sdk.Tx{evmTx, cosmosTx} // Expected txs in order - expectedTxs := []sdk.Tx{evmTx} + expectedTxs := []sdk.Tx{cosmosTx, evmTx} expTxHashes := s.getTxHashes(expectedTxs) return inputTxs, expTxHashes @@ -166,29 +170,46 @@ func (s *IntegrationTestSuite) TestTransactionOrderingWithABCIMethodCalls() { for _, tc := range testCases { s.Run(tc.name, func() { + // Clean up previous test's resources before resetting + s.TearDownTest() // Reset test setup to ensure clean state s.SetupTest() txs, expTxHashes := tc.setupTxs() - // Call CheckTx for transactions - err := s.checkTxs(txs) + // insert txs given by setup + err := s.insertTxs(txs) s.Require().NoError(err) + // Refresh the cached latestCtx and trigger cosmos recheck so + // cosmos txs are available via Select/PrepareProposal. + mpool := s.network.App.GetMempool() + if kMp, ok := mpool.(*evmmempool.Mempool); ok { + head := kMp.GetBlockchain().CurrentBlock() + kMp.RecheckEVMTxs(head) + kMp.RecheckCosmosTxs(head) + } + // 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 + // Call PrepareProposal for the next block (H+1) after recheck at height H. + // This mirrors production where PrepareProposal is for the next block. prepareProposalRes, err := s.network.App.PrepareProposal(&abci.RequestPrepareProposal{ MaxTxBytes: 1_000_000, - Height: 1, + Height: s.network.GetContext().BlockHeight() + 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) + ctx := s.network.GetContext() + if kMp, ok := mpool.(*evmmempool.Mempool); ok { + head := kMp.GetBlockchain().CurrentBlock() + kMp.RecheckEVMTxs(head) + kMp.RecheckCosmosTxs(head) + } + iterator := mpool.Select(ctx.WithBlockHeight(ctx.BlockHeight()+1), nil) for _, txHash := range expTxHashes { actualTxHash := s.getTxHash(iterator.Tx()) s.Require().Equal(txHash, actualTxHash) @@ -196,7 +217,7 @@ func (s *IntegrationTestSuite) TestTransactionOrderingWithABCIMethodCalls() { iterator = iterator.Next() } - // Check whether expected transactions are selcted by PrepareProposal + // Check whether expected transactions are selected by PrepareProposal txHashes := make([]string, 0) for _, txBytes := range prepareProposalRes.Txs { txHash := hex.EncodeToString(tmhash.Sum(txBytes)) @@ -368,31 +389,120 @@ func (s *IntegrationTestSuite) TestNonceGappedEVMTransactionsWithABCIMethodCalls s.Require().Equal(2, count, "After replacement, both transactions should be pending") }, }, + { + // NOTE: this test is implicitly relying on the fact that ante + // handlers will ensure balances before they check and increment + // nonces, if this ordering changes, this will need to be modified + name: "test queue txs do not propagate state changes after failed recheck", + setupTxs: func() ([]sdk.Tx, []string) { + key := s.keyring.GetKey(0) + var txs []sdk.Tx + + balance := network.PrefundedAccountInitialBalance.BigInt() + gasPrice := new(big.Int).Quo(balance, new(big.Int).SetUint64(2*TxGas)) + + // nonce gapped tx that will spend over half of the sender + // balance + txs = append(txs, s.createEVMValueTransferTx(key, 1, gasPrice)) + + // nonce gapped tx that will spend over half of the sender + // balance + txs = append(txs, s.createEVMValueTransferTx(key, 2, gasPrice)) + + return txs, s.getTxHashes(nil) + }, + verifyFunc: func(mpool mempool.Mempool) { + evmMp := mpool.(*evmmempool.Mempool) + legacyPool := evmMp.GetTxPool().Subpools[0].(*legacypool.LegacyPool) + pending, queued := legacyPool.Stats() + s.Require().Equal(0, pending, "expected no txs to be pending") + + // ensure that we do evict either of the txs, they are both + // nonce gapped which means that they should simply sit in + // queued until the nonce gap is filled and they are ready to + // be validated. if we incorrectly propagate the ante writes from + // rechecking tx1 to tx2, then tx2 will fail recheck with a non + // tolerated error (using > signers balance) and it will be + // improperly evicted. + s.Require().Equal(2, queued, "expected both txs to be queued") + }, + }, + { + // NOTE: this test is implicitly relying on the fact that ante + // handlers will ensure balances before they check and increment + // nonces, if this ordering changes, this will need to be modified + name: "test queued rechecks happen on pending state", + setupTxs: func() ([]sdk.Tx, []string) { + key := s.keyring.GetKey(0) + balance := network.PrefundedAccountInitialBalance.BigInt() + + var txs []sdk.Tx + + // these txs will go to queued + txs = append(txs, s.createEVMValueTransferTx(key, 10, big.NewInt(1000000000))) + txs = append(txs, s.createEVMValueTransferTx(key, 11, big.NewInt(1000000000))) + txs = append(txs, s.createEVMValueTransferTx(key, 12, big.NewInt(1000000000))) + + // this tx will use the senders entire balance + gasPrice := new(big.Int).Quo(balance, new(big.Int).SetUint64(TxGas)) + txs = append(txs, s.createEVMValueTransferTxWithValue(key, 0, big.NewInt(0), gasPrice)) + + return txs, s.getTxHashes(txs[len(txs)-1:]) + }, + verifyFunc: func(mpool mempool.Mempool) { + evmMp := mpool.(*evmmempool.Mempool) + legacyPool := evmMp.GetTxPool().Subpools[0].(*legacypool.LegacyPool) + pending, queued := legacyPool.Stats() + s.Require().Equal(1, pending, "expected 1 pending tx") + + // not expecting any txs to be in queued since the queued txs + // are validated on top of pending state. if we take pending + // state into account, the sender should have no balance when + // it tries to validate the queued tx, thus it is evicted. + s.Require().Equal(0, queued, "expected no queued txs") + }, + }, } for _, tc := range testCases { s.Run(tc.name, func() { + // Clean up previous test's resources before resetting + s.TearDownTest() s.SetupTest() txs, expTxHashes := tc.setupTxs() - // Call CheckTx for transactions - err := s.checkTxs(txs) + // insert txs given by setup + err := s.insertTxs(txs) s.Require().NoError(err) + // Refresh the cached latestCtx and trigger cosmos recheck so + // HeightSync is at the correct height for Select/PrepareProposal. + mpool := s.network.App.GetMempool() + if kMp, ok := mpool.(*evmmempool.Mempool); ok { + head := kMp.GetBlockchain().CurrentBlock() + kMp.RecheckEVMTxs(head) + kMp.RecheckCosmosTxs(head) + } + // 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 + // Call PrepareProposal for the next block (H+1) after recheck at height H. prepareProposalRes, err := s.network.App.PrepareProposal(&abci.RequestPrepareProposal{ MaxTxBytes: 1_000_000, - Height: 1, + Height: s.network.GetContext().BlockHeight() + 1, }) s.Require().NoError(err) - mpool := s.network.App.GetMempool() - iterator := mpool.Select(s.network.GetContext(), nil) + ctx := s.network.GetContext() + if kMp, ok := mpool.(*evmmempool.Mempool); ok { + head := kMp.GetBlockchain().CurrentBlock() + kMp.RecheckEVMTxs(head) + kMp.RecheckCosmosTxs(head) + } + iterator := mpool.Select(ctx.WithBlockHeight(ctx.BlockHeight()+1), nil) // Check whether expected transactions are included and returned as pending state in mempool for _, txHash := range expTxHashes { @@ -403,7 +513,7 @@ func (s *IntegrationTestSuite) TestNonceGappedEVMTransactionsWithABCIMethodCalls } tc.verifyFunc(mpool) - // Check whether expected transactions are selcted by PrepareProposal + // Check whether expected transactions are selected by PrepareProposal txHashes := make([]string, 0) for _, txBytes := range prepareProposalRes.Txs { txHash := hex.EncodeToString(tmhash.Sum(txBytes)) @@ -414,93 +524,575 @@ func (s *IntegrationTestSuite) TestNonceGappedEVMTransactionsWithABCIMethodCalls } } -// 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() { +func (s *IntegrationTestSuite) TestRechecking() { testCases := []struct { name string - setupTxs func() []sdk.Tx - verifyFunc func() + setupTxs func() ([]sdk.Tx, []string) + networkTxs func() []sdk.Tx + verifyFunc func(mpool mempool.Mempool) }{ { - name: "EVM transactions: committed txs removed from mempool and lower nonce txs fail", - setupTxs: func() []sdk.Tx { + name: "recheck drops evm tx after attempted spend is no longer valid", + setupTxs: func() ([]sdk.Tx, []string) { + key := s.keyring.GetKey(0) + var txs []sdk.Tx + + // create two txs that will each spend half our balance + balance := network.PrefundedAccountInitialBalance.BigInt() + gasPrice := big.NewInt(1000000000) + gasCost := new(big.Int).Mul(big.NewInt(TxGas), gasPrice) + value := new(big.Int).Sub(new(big.Int).Quo(balance, big.NewInt(2)), gasCost) + txs = append(txs, s.createEVMValueTransferTxWithValue(key, 0, value, gasPrice)) + txs = append(txs, s.createEVMValueTransferTxWithValue(key, 1, value, gasPrice)) + + return txs, s.getTxHashes(nil) + }, + networkTxs: func() []sdk.Tx { + // create a new network tx spending just over half balance + balance := network.PrefundedAccountInitialBalance.BigInt() + value := new(big.Int).Quo(balance, big.NewInt(2)) + return []sdk.Tx{ + s.createEVMValueTransferTxWithValue(s.keyring.GetKey(0), 0, value, big.NewInt(1000000000)), + } + }, + verifyFunc: func(mpool mempool.Mempool) { + mp := mpool.(*evmmempool.Mempool) + legacyPool := mp.GetTxPool().Subpools[0].(*legacypool.LegacyPool) + pending, queued := legacyPool.Stats() + + // expecting our tx to have been dropped + s.Require().Equal(0, pending, "expected no pending txs") + s.Require().Equal(0, queued, "expected no queued txs") + }, + }, + { + name: "recheck drops cosmos tx after attempted spend is no longer valid", + setupTxs: func() ([]sdk.Tx, []string) { + key := s.keyring.GetKey(0) + + // cosmos tx that spends ~half the balance; becomes invalid + // once the network tx below also spends half the balance. + balance := network.PrefundedAccountInitialBalance.BigInt() + gasPrice := big.NewInt(1000000000) + gasCost := new(big.Int).Mul(big.NewInt(TxGas), gasPrice) + value := new(big.Int).Sub(new(big.Int).Quo(balance, big.NewInt(2)), gasCost) + + return []sdk.Tx{s.createCosmosSendTxWithAmount(key, value, gasPrice)}, s.getTxHashes(nil) + }, + networkTxs: func() []sdk.Tx { + // create a new network tx spending just over half balance + balance := network.PrefundedAccountInitialBalance.BigInt() + value := new(big.Int).Quo(balance, big.NewInt(2)) + return []sdk.Tx{ + s.createEVMValueTransferTxWithValue(s.keyring.GetKey(0), 0, value, big.NewInt(1000000000)), + } + }, + verifyFunc: func(mpool mempool.Mempool) { + mp := mpool.(*evmmempool.Mempool) + + s.Require().Equal(0, mp.CountTx(), "expected no txs in any pool") + + legacyPool := mp.GetTxPool().Subpools[0].(*legacypool.LegacyPool) + _, queued := legacyPool.Stats() + + // mp.CountTx does not include queued txs, so we explicitly + // ensure that no queued txs are present either + s.Require().Equal(0, queued, "expected no queued txs") + }, + }, + { + name: "recheck demotes future evm txs to queued after predecessor failure", + setupTxs: func() ([]sdk.Tx, []string) { key := s.keyring.GetKey(0) + var txs []sdk.Tx + + gasPrice := big.NewInt(1000000000) + // this is a placeholder tx that will be removed and its + // changes not included in state since another tx0 will be + // included in state + txs = append(txs, s.createEVMValueTransferTx(key, 0, gasPrice)) + + // create a tx that will fail recheck due to balance spend when + // the network tx is included + balance := network.PrefundedAccountInitialBalance.BigInt() + gasCost := new(big.Int).Mul(big.NewInt(TxGas), gasPrice) + value := new(big.Int).Sub(new(big.Int).Quo(balance, big.NewInt(2)), gasCost) + txs = append(txs, s.createEVMValueTransferTxWithValue(key, 1, value, gasPrice)) + + // create a final tx that will spend a minimal amount. this is + // a valid tx even after the inclusion of the network tx. + txs = append(txs, s.createEVMValueTransferTx(key, 2, gasPrice)) - // 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. + return txs, s.getTxHashes(nil) + }, + networkTxs: func() []sdk.Tx { + // create a new network tx spending just over half balance + balance := network.PrefundedAccountInitialBalance.BigInt() + value := new(big.Int).Quo(balance, big.NewInt(2)) + return []sdk.Tx{ + s.createEVMValueTransferTxWithValue(s.keyring.GetKey(0), 0, value, big.NewInt(1000000000)), + } + }, + verifyFunc: func(mpool mempool.Mempool) { + mp := mpool.(*evmmempool.Mempool) + legacyPool := mp.GetTxPool().Subpools[0].(*legacypool.LegacyPool) + pending, queued := legacyPool.Stats() + + // expecting txs 0 and 1 to have been dropped (tx0 is too old, + // tx1 spends too much). However tx2 should be demoted to + // queued, since its parent tx was dropped from pending and its + // now nonce gapped. + s.Require().Equal(0, pending, "expected no pending txs") + s.Require().Equal(1, queued, "expected pending tx to be demoted to queued") + }, + }, + { + name: "invalid queue tx stays queue while gapped and dropped once filled", + setupTxs: func() ([]sdk.Tx, []string) { key := s.keyring.GetKey(0) + var txs []sdk.Tx - // 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") + gasPrice := big.NewInt(1000000000) + + // queued tx that will be promoted once the nonce gap is filled + txs = append(txs, s.createEVMValueTransferTx(key, 1, gasPrice)) + + // queued tx that is invalid when taking into account the above + // tx, and will be dropped only once the above tx is promoted + balance := network.PrefundedAccountInitialBalance.BigInt() + gasCost := new(big.Int).Mul(big.NewInt(TxGas), gasPrice) + value := new(big.Int).Sub(new(big.Int).Quo(balance, big.NewInt(2)), gasCost) + txs = append(txs, s.createEVMValueTransferTxWithValue(key, 2, value, gasPrice)) + + // this tx is valid if we have removed the above tx, this + // should not be promoted (it will be gapped again once its + // parent is dropped), but it should stay in queued + txs = append(txs, s.createEVMValueTransferTx(key, 3, gasPrice)) + + return txs, s.getTxHashes([]sdk.Tx{txs[0]}) + }, + networkTxs: func() []sdk.Tx { + // create a new network tx spending just over half balance + balance := network.PrefundedAccountInitialBalance.BigInt() + value := new(big.Int).Quo(balance, big.NewInt(2)) + return []sdk.Tx{ + s.createEVMValueTransferTxWithValue(s.keyring.GetKey(0), 0, value, big.NewInt(1000000000)), + } + }, + verifyFunc: func(mpool mempool.Mempool) { + mp := mpool.(*evmmempool.Mempool) + legacyPool := mp.GetTxPool().Subpools[0].(*legacypool.LegacyPool) + + pending, queued := legacyPool.ContentFrom(s.keyring.GetKey(0).Addr) + s.Require().Len(pending, 1, "expected only 1 tx to have been promoted to pending") + s.Require().Len(queued, 1, "expected only 1 tx to have stayed in queued") + + s.Require().Equal(uint64(0x1), pending[0].Nonce(), "expected nonce 1 tx to be in pending") + s.Require().Equal(uint64(0x3), queued[0].Nonce(), "expected nonce 3 tx to be in queued") + }, + }, + { + name: "cosmos recheck does not leak failed txs partial writes", + setupTxs: func() ([]sdk.Tx, []string) { + keyA := s.keyring.GetKey(2) + keyB := s.keyring.GetKey(3) + + // create a tx for keyA nonce0. we will include a tx from the + // network that will also arrive with this nonce, causing this + // tx to fail recheck. + failingTxA := s.createCosmosSendTx(keyA, big.NewInt(2_000_000_000)) + + // create a tx from a new sender keyB nonce0. this will + // successfully pass recheck AFTER keyA since the gas price is + // less. this test is ensuring that having a successful recheck + // write state after a previous failure does not incorrectly + // persist the failure txs writes. + flushingTxB := s.createCosmosSendTx(keyB, big.NewInt(1_000_000_000)) + + return []sdk.Tx{failingTxA, flushingTxB}, s.getTxHashes([]sdk.Tx{flushingTxB}) + }, + networkTxs: func() []sdk.Tx { + keyA := s.keyring.GetKey(2) + balance := network.PrefundedAccountInitialBalance.BigInt() + // drain keyA's balance with a tx not in our mempool (but not + // enough to make failingTxA fail due to out of balance, it + // must write its balance change into its context to exercise + // this). NOTE: we are relying on the fact that nonce checks + // happen after balance checks in the ante handler sequence. + drainValue := new(big.Int).Sub(balance, big.NewInt(400_000_000_000_000)) + return []sdk.Tx{ + s.createEVMValueTransferTxWithValue(keyA, 0, drainValue, big.NewInt(1_000_000_000)), + } + }, + verifyFunc: func(mpool mempool.Mempool) { + keyA := s.keyring.GetKey(2) + + // try and insert a new tx. if failingTxA's balance writes were + // improperly persisted to the rechecker's context, then + // inserting this will fail with out of balance. if we have + // correctly discarded its writes, the insert will succeed. + tx := s.createCosmosSendTx(keyA, big.NewInt(1_000_000_000)) + err := mpool.Insert(s.network.GetContext(), tx) + s.Require().NoError(err, "tx should have been successfully inserted after recheck") }, }, } - for _, tc := range testCases { s.Run(tc.name, func() { - // Reset test setup to ensure clean state + // clean up previous test's resources before resetting + s.TearDownTest() s.SetupTest() - txs := tc.setupTxs() + txs, expTxHashes := tc.setupTxs() + s.T().Logf("inserting %d txs into local mempool", len(txs)) - // Call CheckTx for transactions - err := s.checkTxs(txs) + // insert txs given by setup + err := s.insertTxs(txs) s.Require().NoError(err) - // Finalize block with txs and Commit state - txBytes, err := s.getTxBytes(txs) + // commit a block with network txs + networkTxs := tc.networkTxs() + s.T().Logf("including %d txs from the network", len(networkTxs)) + + var toFinalize [][]byte + for _, tx := range networkTxs { + encoded, err := s.factory.EncodeTx(tx) + s.Require().NoError(err) + toFinalize = append(toFinalize, encoded) + } + res, err := s.network.NextBlockWithTxs(toFinalize...) s.Require().NoError(err) + for _, result := range res.GetTxResults() { + s.Require().Equal(uint32(0x0), result.GetCode()) + } - _, err = s.network.NextBlockWithTxs(txBytes...) + // call PrepareProposal for the next block (H+1) after recheck at height H. + prepareProposalRes, err := s.network.App.PrepareProposal(&abci.RequestPrepareProposal{ + MaxTxBytes: 1_000_000, + Height: s.network.GetContext().BlockHeight() + 1, + }) 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 custom verify func + tc.verifyFunc(s.network.App.GetMempool()) + + // check whether expected transactions are selected 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) + }) + } +} + +func (s *IntegrationTestSuite) TestMultiPoolInteractions() { + type insertWithResults struct { + tx sdk.Tx + err error + } + testCases := []struct { + name string + setupTxs func() ([]insertWithResults, []string) + networkTxs func() []sdk.Tx + verifyFunc func(mpool mempool.Mempool) + }{ + { + name: "same signer rejected from multi pool insert", + setupTxs: func() ([]insertWithResults, []string) { + key := s.keyring.GetKey(0) + var results []insertWithResults + + // cosmos tx automatically created with nonce 0 + results = append(results, insertWithResults{s.createCosmosSendTx(key, big.NewInt(5000000000)), nil}) + + // create two evm txs from the same key, both not allowed to be + // inserted according to reserver rules + + // evm tx from same key at nonce 0, this is invalid if we take + // into account cosmos pending state, but valid if not + results = append(results, insertWithResults{s.createEVMValueTransferTx(key, 0, big.NewInt(1000000000)), reserver.ErrAlreadyReserved}) + + // evm tx from same key at nonce 1, this is valid if we take + // into account cosmos pending state, but invalid if not + results = append(results, insertWithResults{s.createEVMValueTransferTx(key, 1, big.NewInt(1000000000)), reserver.ErrAlreadyReserved}) + + return results, s.getTxHashes([]sdk.Tx{results[0].tx}) + }, + networkTxs: func() []sdk.Tx { return nil }, + verifyFunc: func(mpool mempool.Mempool) { + mp := mpool.(*evmmempool.Mempool) + s.Require().Equal(1, mp.CountTx(), "expected only a single tx in the mempool") + + legacyPool := mp.GetTxPool().Subpools[0].(*legacypool.LegacyPool) + pending, queued := legacyPool.Stats() + + // no evm txs should be allowed since they were all from the + // same sender that has a cosmos tx in the pool already + s.Require().Equal(0, pending, "expected no pending txs") + s.Require().Equal(0, queued, "expected no queued txs") + }, + }, + { + name: "multi signer cosmos tx reserves all signers", + setupTxs: func() ([]insertWithResults, []string) { + var results []insertWithResults + + // create multi signer cosmos tx to reserve keys 0,1,2 for the + // cosmos pool + signers := []keyring.Key{s.keyring.GetKey(0), s.keyring.GetKey(1), s.keyring.GetKey(2)} + results = append(results, insertWithResults{s.createMultiSignerCosmosSendTx(big.NewInt(5000000000), signers...), nil}) + + // all should fail since each signer is being held by the + // cosmos pool + results = append(results, insertWithResults{s.createEVMValueTransferTx(s.keyring.GetKey(0), 0, big.NewInt(1000000000)), reserver.ErrAlreadyReserved}) + results = append(results, insertWithResults{s.createEVMValueTransferTx(s.keyring.GetKey(1), 0, big.NewInt(1000000000)), reserver.ErrAlreadyReserved}) + results = append(results, insertWithResults{s.createEVMValueTransferTx(s.keyring.GetKey(2), 0, big.NewInt(1000000000)), reserver.ErrAlreadyReserved}) + + return results, s.getTxHashes([]sdk.Tx{results[0].tx}) + }, + networkTxs: func() []sdk.Tx { return nil }, + verifyFunc: func(mpool mempool.Mempool) { + mp := mpool.(*evmmempool.Mempool) + s.Require().Equal(1, mp.CountTx(), "expected only a single tx in the mempool") + + legacyPool := mp.GetTxPool().Subpools[0].(*legacypool.LegacyPool) + pending, queued := legacyPool.Stats() + + // no evm txs should be allowed since they were all from a + // sender that already a cosmos tx in the pool already + s.Require().Equal(0, pending, "expected no pending txs") + s.Require().Equal(0, queued, "expected no queued txs") + }, + }, + { + name: "multi signer cosmos tx atomically fails reservations", + setupTxs: func() ([]insertWithResults, []string) { + var results []insertWithResults + + // insert evm tx with key 0 + results = append(results, insertWithResults{s.createEVMValueTransferTx(s.keyring.GetKey(0), 0, big.NewInt(1000000000)), nil}) - // Run verification function - tc.verifyFunc() + // create multi signer cosmos tx to reserve keys 0,1,2 for the + // cosmos pool + signers := []keyring.Key{s.keyring.GetKey(0), s.keyring.GetKey(1), s.keyring.GetKey(2)} + results = append(results, insertWithResults{s.createMultiSignerCosmosSendTx(big.NewInt(5000000000), signers...), reserver.ErrAlreadyReserved}) + + // expecting the above tx to fail insert, make sure that after + // the failure it does not create any new reservations + results = append(results, insertWithResults{s.createEVMValueTransferTx(s.keyring.GetKey(0), 1, big.NewInt(1000000000)), nil}) + results = append(results, insertWithResults{s.createEVMValueTransferTx(s.keyring.GetKey(1), 0, big.NewInt(1000000000)), nil}) + results = append(results, insertWithResults{s.createEVMValueTransferTx(s.keyring.GetKey(2), 0, big.NewInt(1000000000)), nil}) + + return results, s.getTxHashes([]sdk.Tx{results[0].tx, results[2].tx, results[3].tx, results[4].tx}) + }, + networkTxs: func() []sdk.Tx { return nil }, + verifyFunc: func(mpool mempool.Mempool) { + mp := mpool.(*evmmempool.Mempool) + s.Require().Equal(4, mp.CountTx(), "expected 4 txs in the mempool") + + legacyPool := mp.GetTxPool().Subpools[0].(*legacypool.LegacyPool) + pending, queued := legacyPool.Stats() + + // all txs should be in the evm tx pending pool + s.Require().Equal(4, pending, "expected 4 pending txs") + s.Require().Equal(0, queued, "expected no queued txs") + }, + }, + { + name: "same network tx properly releases reservations", + setupTxs: func() ([]insertWithResults, []string) { + var results []insertWithResults + + signers := []keyring.Key{s.keyring.GetKey(0), s.keyring.GetKey(1), s.keyring.GetKey(2)} + results = append(results, insertWithResults{s.createMultiSignerCosmosSendTx(big.NewInt(5000000000), signers...), nil}) + + return results, s.getTxHashes(nil) + }, + networkTxs: func() []sdk.Tx { + // same tx that is in our cosmos pool is included in a block + signers := []keyring.Key{s.keyring.GetKey(0), s.keyring.GetKey(1), s.keyring.GetKey(2)} + tx := s.createMultiSignerCosmosSendTx(big.NewInt(5000000000), signers...) + return []sdk.Tx{tx} + }, + verifyFunc: func(mpool mempool.Mempool) { + mp := mpool.(*evmmempool.Mempool) + + // expect a completely empty mempool + s.Require().Equal(0, mp.CountTx(), "expected no txs in the mempool") + legacyPool := mp.GetTxPool().Subpools[0].(*legacypool.LegacyPool) + pending, queued := legacyPool.Stats() + s.Require().Equal(0, pending, "expected no pending txs") + s.Require().Equal(0, queued, "expected no queued txs") + + // ensure that we can insert txs for the signers that were + // evicted from the cosmos pool into the evm pool + var txs []sdk.Tx + txs = append(txs, s.createEVMValueTransferTx(s.keyring.GetKey(0), 0, big.NewInt(1000000000))) + txs = append(txs, s.createEVMValueTransferTx(s.keyring.GetKey(1), 0, big.NewInt(1000000000))) + txs = append(txs, s.createEVMValueTransferTx(s.keyring.GetKey(2), 0, big.NewInt(1000000000))) + s.Require().NoError(s.insertTxs(txs)) + + s.Require().Equal(3, mp.CountTx(), "expected 3 txs in the mempool") + pending, queued = legacyPool.Stats() + s.Require().Equal(3, pending, "expected 3 pending txs") + s.Require().Equal(0, queued, "expected no queued txs") + }, + }, + { + name: "cosmos multi signer recheck failure properly releases all reservations", + setupTxs: func() ([]insertWithResults, []string) { + var results []insertWithResults + + signers := []keyring.Key{s.keyring.GetKey(0), s.keyring.GetKey(1), s.keyring.GetKey(2)} + results = append(results, insertWithResults{s.createMultiSignerCosmosSendTx(big.NewInt(5000000000), signers...), nil}) + + return results, s.getTxHashes(nil) + }, + networkTxs: func() []sdk.Tx { + // include a tx from the network that will cause the tx in our + // cosmos pool to fail recheck (bumping key 0's nonce) + + // NOTE: we are also testing an interesting property of how + // removals work for cosmos txs. the cosmos pool is built on + // top of the priority nonce mempool and that only looks at the + // first signer of mutli signer txs. so the tx below and the + // one already in the mempool look identical to it. so when + // including this tx from the network, it will remove the one + // in the mempool if we process the removal during finalize + // block. however, this gives us no way to determine that our + // original tx had multiple signers and we need to release all + // of those address reservations. so, we must not remove during + // finalize block, and process the removal during recheck where + // the tx will be dropped due to a nonce too low error on + // signer 0. during recheck we know exactly which tx we are + // removing and why, and can properly unreserve the signers + // reservations. + tx := s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(5000000000)) + return []sdk.Tx{tx} + }, + verifyFunc: func(mpool mempool.Mempool) { + mp := mpool.(*evmmempool.Mempool) + + // expect a completely empty mempool + s.Require().Equal(0, mp.CountTx(), "expected no txs in the mempool") + legacyPool := mp.GetTxPool().Subpools[0].(*legacypool.LegacyPool) + pending, queued := legacyPool.Stats() + s.Require().Equal(0, pending, "expected no pending txs") + s.Require().Equal(0, queued, "expected no queued txs") + + // ensure that we can insert txs for the signers that were + // evicted from the cosmos pool into the evm pool + var txs []sdk.Tx + txs = append(txs, s.createEVMValueTransferTx(s.keyring.GetKey(0), 0, big.NewInt(1000000000))) + txs = append(txs, s.createEVMValueTransferTx(s.keyring.GetKey(1), 0, big.NewInt(1000000000))) + txs = append(txs, s.createEVMValueTransferTx(s.keyring.GetKey(2), 0, big.NewInt(1000000000))) + s.Require().NoError(s.insertTxs(txs)) + + s.Require().Equal(3, mp.CountTx(), "expected 3 txs in the mempool") + pending, queued = legacyPool.Stats() + s.Require().Equal(3, pending, "expected 3 pending txs") + s.Require().Equal(0, queued, "expected no queued txs") + }, + }, + { + name: "cosmos signer reserved twice is not unreserved on first removal", + setupTxs: func() ([]insertWithResults, []string) { + var results []insertWithResults + + // create a multi signer tx that will be dropped + signers := []keyring.Key{s.keyring.GetKey(0), s.keyring.GetKey(1), s.keyring.GetKey(2)} + results = append(results, insertWithResults{s.createMultiSignerCosmosSendTx(big.NewInt(5000000000), signers...), nil}) + + // reserve signer 0 a second time with a new tx at its next + // nonce (given the above tx) + var nextNonce uint64 = 1 + var gasLimit uint64 = 100000000 + results = append(results, insertWithResults{ + s.createCosmosSendTxWithNonceAndGas(s.keyring.GetKey(0), nextNonce, big.NewInt(1000), gasLimit, big.NewInt(5000000000)), + nil, + }) + + return results, s.getTxHashes([]sdk.Tx{results[1].tx}) + }, + networkTxs: func() []sdk.Tx { + // bump signer 0's nonce on chain so that the multi signer tx + // will be dropped, the single signer tx at nonce 1 will remain + tx := s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(5000000000)) + return []sdk.Tx{tx} + }, + verifyFunc: func(mpool mempool.Mempool) { + mp := mpool.(*evmmempool.Mempool) + + // expect a single tx in the mempool + s.Require().Equal(1, mp.CountTx(), "expected a single tx in the mempool") + legacyPool := mp.GetTxPool().Subpools[0].(*legacypool.LegacyPool) + pending, queued := legacyPool.Stats() + s.Require().Equal(0, pending, "expected no pending txs") + s.Require().Equal(0, queued, "expected no queued txs") + + // ensure signers 1 and 2 were unreserved + var txs []sdk.Tx + txs = append(txs, s.createEVMValueTransferTx(s.keyring.GetKey(1), 0, big.NewInt(1000000000))) + txs = append(txs, s.createEVMValueTransferTx(s.keyring.GetKey(2), 0, big.NewInt(1000000000))) + s.Require().NoError(s.insertTxs(txs)) + + // ensure signer 0 remains reserved since it has another cosmos + // tx still in the pool + err := s.insertTx(s.createEVMValueTransferTx(s.keyring.GetKey(0), 0, big.NewInt(1000000000))) + s.Require().ErrorIs(err, reserver.ErrAlreadyReserved) + }, + }, + } + for _, tc := range testCases { + s.Run(tc.name, func() { + // clean up previous test's resources before resetting + s.TearDownTest() + s.SetupTest() + + insertResults, expTxHashes := tc.setupTxs() + s.T().Logf("inserting %d txs into local mempool", len(insertResults)) + + // insert txs given by setup + for _, result := range insertResults { + err := s.insertTx(result.tx) + s.Require().ErrorIs(err, result.err) + } + + // commit a block with network txs + networkTxs := tc.networkTxs() + s.T().Logf("including %d txs from the network", len(networkTxs)) + + var toFinalize [][]byte + for _, tx := range networkTxs { + encoded, err := s.factory.EncodeTx(tx) + s.Require().NoError(err) + toFinalize = append(toFinalize, encoded) + } + res, err := s.network.NextBlockWithTxs(toFinalize...) + s.Require().NoError(err) + for _, result := range res.GetTxResults() { + s.Require().Equal(uint32(0x0), result.GetCode()) + } + + // call PrepareProposal for the next block (H+1) after recheck at height H. + prepareProposalRes, err := s.network.App.PrepareProposal(&abci.RequestPrepareProposal{ + MaxTxBytes: 1_000_000, + Height: s.network.GetContext().BlockHeight() + 1, + }) + s.Require().NoError(err) + + // run custom verify func + tc.verifyFunc(s.network.App.GetMempool()) + + // check whether expected transactions are selected 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) }) } } diff --git a/tests/integration/mempool/test_setup.go b/tests/integration/mempool/test_setup.go index ae80aaee..29f5b8e1 100644 --- a/tests/integration/mempool/test_setup.go +++ b/tests/integration/mempool/test_setup.go @@ -5,6 +5,7 @@ import ( "github.com/stretchr/testify/suite" + evmmempool "github.com/cosmos/evm/mempool" testconstants "github.com/cosmos/evm/testutil/constants" "github.com/cosmos/evm/testutil/integration/evm/factory" "github.com/cosmos/evm/testutil/integration/evm/grpc" @@ -42,6 +43,33 @@ func (s *IntegrationTestSuite) SetupTest() { s.SetupTestWithChainID(testconstants.ExampleChainID) } +// TearDownTest cleans up resources after each test. +func (s *IntegrationTestSuite) TearDownTest() { + if s.network != nil && s.network.App != nil { + // Close the mempool to stop background goroutines before the next test + // This prevents race conditions when global test state is reset in SetupTest + if mp := s.network.App.GetMempool(); mp != nil { + if closer, ok := mp.(interface{ Close() error }); ok { + if err := closer.Close(); err != nil { + s.T().Logf("Warning: failed to close mempool: %v", err) + } + + // Wait for goroutines to fully exit before next test starts + // The mempool spawns background goroutines that may still be accessing + // global config (like EVMCoinInfo) even after Close() returns. + // We need to ensure these goroutines have completely finished before + // the next test's SetupTest() resets the global config. + // A longer wait time reduces the chance of race conditions where: + // - Old test's goroutine is still reading global config + // - New test's SetupTest() is resetting global config + // Under race detector and high system load (full test suite), goroutines + // may take longer to fully exit. 2 seconds provides adequate buffer. + time.Sleep(2 * time.Second) + } + } + } +} + // SetupTestWithChainID initializes the test environment with a specific chain ID. func (s *IntegrationTestSuite) SetupTestWithChainID(chainID testconstants.ChainID) { s.keyring = keyring.New(20) @@ -53,8 +81,11 @@ func (s *IntegrationTestSuite) SetupTestWithChainID(chainID testconstants.ChainI options = append(options, s.options...) nw := network.NewUnitTestNetwork(s.create, options...) + s.network = nw + gh := grpc.NewIntegrationHandler(nw) tf := factory.New(nw, gh) + s.factory = tf // Advance to block 2+ where mempool is designed to operate // This ensures proper headers, StateDB, and fee market initialization @@ -63,11 +94,11 @@ func (s *IntegrationTestSuite) SetupTestWithChainID(chainID testconstants.ChainI err = nw.NextBlock() s.Require().NoError(err) - // Wait for mempool async reset goroutines to complete - // NextBlock() triggers chain head events that start async goroutines to reset - // the mempool state. Without this wait, tests can start before the reset completes, - // causing race conditions with stale mempool state. - time.Sleep(100 * time.Millisecond) + // Synchronize mempool state with the blockchain after block progression + // Directly call Reset on subpools to ensure synchronous completion + // This prevents race conditions by waiting for the reset to complete + // before continuing with test setup + s.TrySetupMempool() // Ensure mempool is in ready state by verifying block height s.Require().Equal(int64(3), nw.GetContext().BlockHeight()) @@ -80,8 +111,28 @@ func (s *IntegrationTestSuite) SetupTestWithChainID(chainID testconstants.ChainI initialCount := mempool.CountTx() s.Require().Equal(0, initialCount, "mempool should be empty initially") - s.network = nw - s.factory = tf + // Enforces deterministic mempool state for tests + evmmempool.AllowUnsafeSyncInsert = true +} + +// TrySetupMempool sets up the Mempool, if it is the configured mempool on the suite. +func (s *IntegrationTestSuite) TrySetupMempool() { + mp, ok := s.network.App.GetMempool().(*evmmempool.Mempool) + if !ok { + return + } + + blockchain := mp.GetBlockchain() + txPool := mp.GetTxPool() + + oldHead := blockchain.CurrentBlock() + blockchain.NotifyNewBlock() + newHead := blockchain.CurrentBlock() + + mp.RecheckCosmosTxs(newHead) + for _, subpool := range txPool.Subpools { + subpool.Reset(oldHead, newHead) + } } // FundAccount funds an account with a specific amount of a given denomination. diff --git a/tests/integration/precompiles/bank/test_integration.go b/tests/integration/precompiles/bank/test_integration.go index 258d9669..060b9db9 100644 --- a/tests/integration/precompiles/bank/test_integration.go +++ b/tests/integration/precompiles/bank/test_integration.go @@ -1,6 +1,7 @@ package bank import ( + "fmt" "math/big" "testing" @@ -26,6 +27,7 @@ import ( "cosmossdk.io/math" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" ) @@ -119,8 +121,8 @@ func TestIntegrationSuite(t *testing.T, create network.CreateEvmApp, options ... contractData ContractData passCheck testutil.LogCheckArgs - cosmosEVMTotalSupply, _ = new(big.Int).SetString("200003000000000000000000", 10) - xmplTotalSupply, _ = new(big.Int).SetString("200000000000000000000000", 10) + cosmosEVMTotalSupply *big.Int + xmplTotalSupply *big.Int ) BeforeEach(func() { @@ -155,6 +157,13 @@ func TestIntegrationSuite(t *testing.T, create network.CreateEvmApp, options ... err = is.network.NextBlock() Expect(err).ToNot(HaveOccurred(), "failed to advance block") + + // Get total supply from bank keeper + cosmosSupply := is.network.App.GetBankKeeper().GetSupply(is.network.GetContext(), is.bondDenom) + cosmosEVMTotalSupply = new(big.Int).Set(cosmosSupply.Amount.BigInt()) + + xmplSupply := is.network.App.GetBankKeeper().GetSupply(is.network.GetContext(), is.tokenDenom) + xmplTotalSupply = new(big.Int).Set(xmplSupply.Amount.BigInt()) }) Context("Direct precompile queries", func() { @@ -248,6 +257,67 @@ func TestIntegrationSuite(t *testing.T, create network.CreateEvmApp, options ... Expect(balances[0].Amount.String()).To(Equal(cosmosEVMTotalSupply.String())) Expect(balances[1].Amount.String()).To(Equal(xmplTotalSupply.String())) }) + + It("should properly handle OOG in precompile and consume all gas", func() { + numDenoms := 5000 + // Mint denoms to make TotalSupply expensive enough to OOG. + ctx := is.network.GetContext() + for i := 0; i < numDenoms; i++ { + denom := fmt.Sprintf("token%d", i) + err = is.network.App.GetBankKeeper().MintCoins( + ctx, minttypes.ModuleName, + sdk.Coins{{Denom: denom, Amount: math.NewInt(1e18)}}, + ) + Expect(err).ToNot(HaveOccurred(), "failed to mint coin %s", denom) + } + // Commit keeper changes directly to state. + store := is.network.GetContext().MultiStore() + cms, ok := store.(storetypes.CacheMultiStore) + Expect(ok).To(BeTrue()) + cms.Write() + + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "failed to advance block") + + // Use callTotalSupplyWithGas to measure inner call gas consumption. + // Forward enough gas for the precompile to OOG iterating 5000+ denoms. + gasForward := big.NewInt(9_000_000) + + txArgs := evmtypes.EvmTxArgs{ + To: &bankCallerContractAddr, + GasLimit: 20_000_000, + } + callArgs := testutiltypes.CallArgs{ + ContractABI: bankCallerContract.ABI, + MethodName: "callTotalSupplyWithGas", + Args: []interface{}{gasForward}, + } + + res, execErr := is.factory.ExecuteContractCall(sender.Priv, txArgs, callArgs) + Expect(execErr).ToNot(HaveOccurred(), "failed to execute callTotalSupplyWithGas") + + ethRes, decErr := evmtypes.DecodeTxResponse(res.Data) + Expect(decErr).ToNot(HaveOccurred(), "failed to decode eth tx response") + Expect(ethRes.VmError).To(BeEmpty(), "outer call should not revert") + + // Unpack: (bool success, uint256 innerGasUsed) + out, unpackErr := bankCallerContract.ABI.Unpack("callTotalSupplyWithGas", ethRes.Ret) + Expect(unpackErr).ToNot(HaveOccurred(), "failed to unpack result") + + innerSuccess := out[0].(bool) + innerGasUsed := out[1].(*big.Int) + + fmt.Printf("\nInner call: success=%v, innerGasUsed=%s, gasForwarded=%s, txGasUsed=%d\n", + innerSuccess, innerGasUsed.String(), gasForward.String(), ethRes.GasUsed) + + // The inner call should have failed (OOG with 5000 denoms). + Expect(innerSuccess).To(BeFalse(), "inner call should OOG with insufficient gas for 5000 denoms") + + // The inner call should have consumed all (or nearly all) forwarded gas. + // With correct gas accounting, innerGasUsed ≈ gasForward. + // With the bug, innerGasUsed would be ~3k (only EVM overhead, no precompile charge). + Expect(innerGasUsed.Uint64()).To(BeNumerically(">=", gasForward.Uint64()*90/100), + "inner OOG call should consume all forwarded gas, got %s out of %s", innerGasUsed.String(), gasForward.String()) + }) }) Context("supplyOf query", func() { diff --git a/tests/integration/precompiles/bech32/test_bech32.go b/tests/integration/precompiles/bech32/test_bech32.go index bca4a45a..b03d1182 100644 --- a/tests/integration/precompiles/bech32/test_bech32.go +++ b/tests/integration/precompiles/bech32/test_bech32.go @@ -5,7 +5,6 @@ import ( "github.com/ethereum/go-ethereum/core/vm" "github.com/holiman/uint256" - "github.com/cosmos/evm/config" "github.com/cosmos/evm/precompiles/bech32" sdk "github.com/cosmos/cosmos-sdk/types" @@ -111,7 +110,7 @@ func (s *PrecompileTestSuite) TestRun() { input, err := s.precompile.Pack( bech32.HexToBech32Method, s.keyring.GetAddr(0), - config.Bech32Prefix, + sdk.GetConfig().GetBech32AccountAddrPrefix(), ) s.Require().NoError(err, "failed to pack input") contract.Input = input @@ -137,7 +136,7 @@ func (s *PrecompileTestSuite) TestRun() { input, err := s.precompile.Pack( bech32.HexToBech32Method, common.BytesToAddress(valAddrBz), - config.Bech32PrefixValAddr, + sdk.GetConfig().GetBech32ValidatorAddrPrefix(), ) s.Require().NoError(err, "failed to pack input") contract.Input = input @@ -160,7 +159,7 @@ func (s *PrecompileTestSuite) TestRun() { input, err := s.precompile.Pack( bech32.HexToBech32Method, s.keyring.GetAddr(0), - config.Bech32PrefixConsAddr, + sdk.GetConfig().GetBech32ConsensusAddrPrefix(), ) s.Require().NoError(err, "failed to pack input") contract.Input = input diff --git a/tests/integration/precompiles/bech32/test_methods.go b/tests/integration/precompiles/bech32/test_methods.go index 30acdf60..4b0cef4b 100644 --- a/tests/integration/precompiles/bech32/test_methods.go +++ b/tests/integration/precompiles/bech32/test_methods.go @@ -5,7 +5,6 @@ import ( "github.com/ethereum/go-ethereum/common" - "github.com/cosmos/evm/config" "github.com/cosmos/evm/precompiles/bech32" cmn "github.com/cosmos/evm/precompiles/common" @@ -63,7 +62,7 @@ func (s *PrecompileTestSuite) TestHexToBech32() { func() []interface{} { return []interface{}{ s.keyring.GetAddr(0), - config.Bech32Prefix, + sdk.GetConfig().GetBech32AccountAddrPrefix(), } }, func(data []byte) { @@ -109,7 +108,7 @@ func (s *PrecompileTestSuite) TestBech32ToHex() { malleate func() []interface{} postCheck func(data []byte) expError bool - errContains string + errContains func() string }{ { "fail - invalid args length", @@ -118,7 +117,9 @@ func (s *PrecompileTestSuite) TestBech32ToHex() { }, func([]byte) {}, true, - fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 1, 0), + func() string { + return fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 1, 0) + }, }, { "fail - empty bech32 address", @@ -129,29 +130,35 @@ func (s *PrecompileTestSuite) TestBech32ToHex() { }, func([]byte) {}, true, - "invalid bech32 address", + func() string { + return "invalid bech32 address" + }, }, { "fail - invalid bech32 address", func() []interface{} { return []interface{}{ - config.Bech32Prefix, + "cosmos", } }, func([]byte) {}, true, - fmt.Sprintf("invalid bech32 address: %s", config.Bech32Prefix), + func() string { + return fmt.Sprintf("invalid bech32 address: %s", "cosmos") + }, }, { "fail - decoding bech32 failed", func() []interface{} { return []interface{}{ - config.Bech32Prefix + "1", + "cosmos" + "1", } }, func([]byte) {}, true, - "decoding bech32 failed", + func() string { + return "decoding bech32 failed" + }, }, { "fail - invalid address format", @@ -162,7 +169,13 @@ func (s *PrecompileTestSuite) TestBech32ToHex() { }, func([]byte) {}, true, - "address max length is 255", + func() string { + if addrVerifier := sdk.GetConfig().GetAddressVerifier(); addrVerifier != nil { + err := addrVerifier(sdk.AccAddress(make([]byte, 256))) + return err.Error() + } + return "address max length is 255" + }, }, { "success - valid bech32 address", @@ -180,7 +193,9 @@ func (s *PrecompileTestSuite) TestBech32ToHex() { s.Require().Equal(s.keyring.GetAddr(0), addr) }, false, - "", + func() string { + return "" + }, }, } @@ -192,7 +207,7 @@ func (s *PrecompileTestSuite) TestBech32ToHex() { if tc.expError { s.Require().Error(err) - s.Require().ErrorContains(err, tc.errContains) + s.Require().ErrorContains(err, tc.errContains()) s.Require().Empty(bz) } else { s.Require().NoError(err) diff --git a/tests/integration/precompiles/common/test_static_call.go b/tests/integration/precompiles/common/test_static_call.go new file mode 100644 index 00000000..4983cded --- /dev/null +++ b/tests/integration/precompiles/common/test_static_call.go @@ -0,0 +1,364 @@ +package common + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/contracts" + "github.com/cosmos/evm/precompiles/werc20" + testconstants "github.com/cosmos/evm/testutil/constants" + "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" + testutiltypes "github.com/cosmos/evm/testutil/types" + evmtypes "github.com/cosmos/evm/x/vm/types" +) + +type StaticCallTestSuite struct { + suite.Suite + + create network.CreateEvmApp + network *network.UnitTestNetwork + factory factory.TxFactory + grpcHandler grpc.Handler + keyring testkeyring.Keyring + contractAddr common.Address + werc20Addr common.Address +} + +func NewStaticCallTestSuite(create network.CreateEvmApp) *StaticCallTestSuite { + return &StaticCallTestSuite{ + create: create, + } +} + +func (s *StaticCallTestSuite) SetupTest() { + keyring := testkeyring.New(2) + nw := network.NewUnitTestNetwork( + s.create, + network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), + ) + grpcHandler := grpc.NewIntegrationHandler(nw) + txFactory := factory.New(nw, grpcHandler) + + s.network = nw + s.factory = txFactory + s.grpcHandler = grpcHandler + s.keyring = keyring + + werc20Hex := network.GetWEVMOSContractHex(testconstants.ExampleChainID) + s.werc20Addr = common.HexToAddress(werc20Hex) + + // Deploy StaticCallTester contract + contractAddr, err := s.factory.DeployContract( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{}, + testutiltypes.ContractDeploymentData{ + Contract: contracts.StaticCallTesterContract, + ConstructorArgs: []interface{}{s.werc20Addr}, + }, + ) + s.Require().NoError(err, "failed to deploy StaticCallTester") + s.Require().NoError(s.network.NextBlock()) + s.contractAddr = contractAddr + + // Fund the contract with WERC20 tokens. + // Step 1: Deposit native tokens into WERC20 for keyring[0]. + depositAmount := big.NewInt(1e18) + _, err = s.factory.ExecuteContractCall( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{ + To: &s.werc20Addr, + Amount: depositAmount, + }, + testutiltypes.CallArgs{ + ContractABI: werc20.ABI, + MethodName: "deposit", + }, + ) + s.Require().NoError(err, "failed to deposit into WERC20") + s.Require().NoError(s.network.NextBlock()) + + // Step 2: Transfer WERC20 tokens from keyring[0] to the deployed contract. + _, err = s.factory.ExecuteContractCall( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{To: &s.werc20Addr}, + testutiltypes.CallArgs{ + ContractABI: werc20.ABI, + MethodName: "transfer", + Args: []interface{}{s.contractAddr, depositAmount}, + }, + ) + s.Require().NoError(err, "failed to transfer WERC20 to contract") + s.Require().NoError(s.network.NextBlock()) +} + +func (s *StaticCallTestSuite) TestNonStaticPrecompileCall() { + transferAmount := big.NewInt(1e17) + + res, err := s.factory.ExecuteContractCall( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{To: &s.contractAddr}, + testutiltypes.CallArgs{ + ContractABI: contracts.StaticCallTesterContract.ABI, + MethodName: "nonStaticPrecompileTransfer", + Args: []interface{}{s.keyring.GetAddr(1), transferAmount}, + }, + ) + s.Require().NoError(err, "non-static precompile transfer should succeed") + + ethRes, err := evmtypes.DecodeTxResponse(res.Data) + s.Require().NoError(err) + s.Require().False(ethRes.Failed(), "tx should not have VM error") + + // Decode return value — should be false (staticcall blocked by write protection) + out, err := contracts.StaticCallTesterContract.ABI.Unpack("nonStaticPrecompileTransfer", ethRes.Ret) + s.Require().NoError(err) + s.Require().Len(out, 1) + success, ok := out[0].(bool) + s.Require().True(ok) + s.Require().True(success, "call to precompile transfer should return true") +} + +func (s *StaticCallTestSuite) TestStaticPrecompileCall() { + transferAmount := big.NewInt(1e17) + + res, err := s.factory.ExecuteContractCall( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{To: &s.contractAddr}, + testutiltypes.CallArgs{ + ContractABI: contracts.StaticCallTesterContract.ABI, + MethodName: "staticPrecompileTransfer", + Args: []interface{}{s.keyring.GetAddr(1), transferAmount}, + }, + ) + s.Require().NoError(err, "outer tx should succeed") + + ethRes, err := evmtypes.DecodeTxResponse(res.Data) + s.Require().NoError(err) + s.Require().False(ethRes.Failed()) + + // Decode return value — should be false (staticcall blocked by write protection) + out, err := contracts.StaticCallTesterContract.ABI.Unpack("staticPrecompileTransfer", ethRes.Ret) + s.Require().NoError(err) + s.Require().Len(out, 1) + success, ok := out[0].(bool) + s.Require().True(ok) + s.Require().False(success, "staticcall to precompile transfer should return false") +} + +func (s *StaticCallTestSuite) TestNonStaticContractCall() { + res, err := s.factory.ExecuteContractCall( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{To: &s.contractAddr}, + testutiltypes.CallArgs{ + ContractABI: contracts.StaticCallTesterContract.ABI, + MethodName: "nonStaticIncrement", + }, + ) + s.Require().NoError(err, "non-static increment should succeed") + + ethRes, err := evmtypes.DecodeTxResponse(res.Data) + s.Require().NoError(err) + s.Require().False(ethRes.Failed()) + s.Require().NoError(s.network.NextBlock()) + + // Query counter — should be 1 + queryRes, err := s.factory.QueryContract( + evmtypes.EvmTxArgs{To: &s.contractAddr}, + testutiltypes.CallArgs{ + ContractABI: contracts.StaticCallTesterContract.ABI, + MethodName: "getCounter", + }, + 0, + ) + s.Require().NoError(err) + + out, err := contracts.StaticCallTesterContract.ABI.Unpack("getCounter", queryRes.Ret) + s.Require().NoError(err) + s.Require().Len(out, 1) + counter, ok := out[0].(*big.Int) + s.Require().True(ok) + s.Require().Equal(int64(1), counter.Int64(), "counter should be 1 after increment") +} + +func (s *StaticCallTestSuite) TestStaticContractCall() { + res, err := s.factory.ExecuteContractCall( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{To: &s.contractAddr}, + testutiltypes.CallArgs{ + ContractABI: contracts.StaticCallTesterContract.ABI, + MethodName: "staticIncrement", + }, + ) + s.Require().NoError(err, "outer tx should succeed") + + ethRes, err := evmtypes.DecodeTxResponse(res.Data) + s.Require().NoError(err) + s.Require().False(ethRes.Failed()) + + // Decode return value — should be false (staticcall blocked by SSTORE protection) + out, err := contracts.StaticCallTesterContract.ABI.Unpack("staticIncrement", ethRes.Ret) + s.Require().NoError(err) + s.Require().Len(out, 1) + success, ok := out[0].(bool) + s.Require().True(ok) + s.Require().False(success, "staticcall to increment should return false") + s.Require().NoError(s.network.NextBlock()) + + // Query counter — should still be 0 + queryRes, err := s.factory.QueryContract( + evmtypes.EvmTxArgs{To: &s.contractAddr}, + testutiltypes.CallArgs{ + ContractABI: contracts.StaticCallTesterContract.ABI, + MethodName: "getCounter", + }, + 0, + ) + s.Require().NoError(err) + + out, err = contracts.StaticCallTesterContract.ABI.Unpack("getCounter", queryRes.Ret) + s.Require().NoError(err) + s.Require().Len(out, 1) + counter, ok := out[0].(*big.Int) + s.Require().True(ok) + s.Require().Equal(int64(0), counter.Int64(), "counter should be unchanged after static increment") +} + +// TestCrossContractViewCallWriteProtection tests that precompile state changes +// are blocked when called through a cross-contract STATICCALL chain: +// 1. ViewCaller invokes StaticCallbackTarget.callback() via ICallback interface (STATICCALL) +// 2. Inside callback(), StaticCallbackTarget attempts werc20.transfer() via regular CALL +// 3. The transfer should fail because the static context propagates through the call chain +func (s *StaticCallTestSuite) TestCrossContractViewCallWriteProtection() { + // Deploy StaticCallbackTarget contract + targetAddr, err := s.factory.DeployContract( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{}, + testutiltypes.ContractDeploymentData{ + Contract: contracts.StaticCallbackTargetContract, + ConstructorArgs: []interface{}{s.werc20Addr}, + }, + ) + s.Require().NoError(err, "failed to deploy StaticCallbackTarget") + s.Require().NoError(s.network.NextBlock()) + + // Deploy ViewCaller contract + callerAddr, err := s.factory.DeployContract( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{}, + testutiltypes.ContractDeploymentData{ + Contract: contracts.ViewCallerContract, + }, + ) + s.Require().NoError(err, "failed to deploy ViewCaller") + s.Require().NoError(s.network.NextBlock()) + + // Fund the target contract with WERC20 tokens + fundAmount := big.NewInt(1e18) + + // Deposit native tokens into WERC20 + _, err = s.factory.ExecuteContractCall( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{ + To: &s.werc20Addr, + Amount: fundAmount, + }, + testutiltypes.CallArgs{ + ContractABI: werc20.ABI, + MethodName: "deposit", + }, + ) + s.Require().NoError(err, "failed to deposit into WERC20") + s.Require().NoError(s.network.NextBlock()) + + // Transfer WERC20 tokens to target contract + _, err = s.factory.ExecuteContractCall( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{To: &s.werc20Addr}, + testutiltypes.CallArgs{ + ContractABI: werc20.ABI, + MethodName: "transfer", + Args: []interface{}{targetAddr, fundAmount}, + }, + ) + s.Require().NoError(err, "failed to transfer WERC20 to target") + s.Require().NoError(s.network.NextBlock()) + + // Set up transfer parameters + transferAmount := big.NewInt(1e17) + _, err = s.factory.ExecuteContractCall( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{To: &targetAddr}, + testutiltypes.CallArgs{ + ContractABI: contracts.StaticCallbackTargetContract.ABI, + MethodName: "setTransferParams", + Args: []interface{}{s.keyring.GetAddr(1), transferAmount}, + }, + ) + s.Require().NoError(err, "failed to set transfer params") + s.Require().NoError(s.network.NextBlock()) + + // Check target's initial WERC20 balance + initialBalanceRes, err := s.factory.QueryContract( + evmtypes.EvmTxArgs{To: &s.werc20Addr}, + testutiltypes.CallArgs{ + ContractABI: werc20.ABI, + MethodName: "balanceOf", + Args: []interface{}{targetAddr}, + }, + 0, + ) + s.Require().NoError(err) + initialBalanceOut, err := werc20.ABI.Unpack("balanceOf", initialBalanceRes.Ret) + s.Require().NoError(err) + initialBalance := initialBalanceOut[0].(*big.Int) + + // Execute: ViewCaller calls StaticCallbackTarget.callback() via ICallback (STATICCALL) + // Inside callback(), target attempts werc20.transfer() + res, err := s.factory.ExecuteContractCall( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{To: &callerAddr}, + testutiltypes.CallArgs{ + ContractABI: contracts.ViewCallerContract.ABI, + MethodName: "callViewAndReturn", + Args: []interface{}{targetAddr}, + }, + ) + s.Require().NoError(err, "outer tx should succeed") + + ethRes, err := evmtypes.DecodeTxResponse(res.Data) + s.Require().NoError(err) + s.Require().False(ethRes.Failed(), "tx should not have top-level VM error") + s.Require().NoError(s.network.NextBlock()) + + // Decode the return value - should be "TRANSFER_FAILED" + out, err := contracts.ViewCallerContract.ABI.Unpack("callViewAndReturn", ethRes.Ret) + s.Require().NoError(err) + s.Require().Len(out, 1) + result, ok := out[0].(string) + s.Require().True(ok) + s.Require().Equal("TRANSFER_FAILED", result, + "transfer inside STATICCALL context should fail; got %q", result) + + // Verify the balance didn't change (transfer was blocked) + finalBalanceRes, err := s.factory.QueryContract( + evmtypes.EvmTxArgs{To: &s.werc20Addr}, + testutiltypes.CallArgs{ + ContractABI: werc20.ABI, + MethodName: "balanceOf", + Args: []interface{}{targetAddr}, + }, + 0, + ) + s.Require().NoError(err) + finalBalanceOut, err := werc20.ABI.Unpack("balanceOf", finalBalanceRes.Ret) + s.Require().NoError(err) + finalBalance := finalBalanceOut[0].(*big.Int) + + s.Require().Equal(initialBalance.String(), finalBalance.String(), + "target balance should be unchanged") +} diff --git a/tests/integration/precompiles/distribution/test_distribution.go b/tests/integration/precompiles/distribution/test_distribution.go index c749828b..62f82724 100644 --- a/tests/integration/precompiles/distribution/test_distribution.go +++ b/tests/integration/precompiles/distribution/test_distribution.go @@ -13,12 +13,13 @@ import ( "github.com/cosmos/evm/precompiles/distribution" "github.com/cosmos/evm/precompiles/testutil" chainutil "github.com/cosmos/evm/testutil" - "github.com/cosmos/evm/testutil/constants" + testconstants "github.com/cosmos/evm/testutil/constants" evmtypes "github.com/cosmos/evm/x/vm/types" "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/distribution/types" ) @@ -86,7 +87,7 @@ func (s *PrecompileTestSuite) TestRun() { valAddr, err := sdk.ValAddressFromBech32(s.network.GetValidators()[0].OperatorAddress) s.Require().NoError(err) val, _ := s.network.App.GetStakingKeeper().GetValidator(ctx, valAddr) - coins := sdk.NewCoins(sdk.NewCoin(constants.ExampleAttoDenom, math.NewInt(1e18))) + coins := sdk.NewCoins(sdk.NewCoin(testconstants.ExampleAttoDenom, math.NewInt(1e18))) s.Require().NoError(s.network.App.GetDistrKeeper().AllocateTokensToValidator(ctx, val, sdk.NewDecCoinsFromCoins(coins...))) input, err := s.precompile.Pack( @@ -109,7 +110,7 @@ func (s *PrecompileTestSuite) TestRun() { caller := common.BytesToAddress(valAddr) commAmt := math.LegacyNewDecWithPrec(1000000000000000000, 1) - valCommission := sdk.DecCoins{sdk.NewDecCoinFromDec(constants.ExampleAttoDenom, commAmt)} + valCommission := sdk.DecCoins{sdk.NewDecCoinFromDec(testconstants.ExampleAttoDenom, commAmt)} // set outstanding rewards s.Require().NoError(s.network.App.GetDistrKeeper().SetValidatorOutstandingRewards(ctx, valAddr, types.ValidatorOutstandingRewards{Rewards: valCommission})) // set commission @@ -189,7 +190,7 @@ func (s *PrecompileTestSuite) TestRun() { s.keyring.GetAddr(0), []cmn.Coin{ { - Denom: constants.ExampleAttoDenom, + Denom: testconstants.ExampleAttoDenom, Amount: big.NewInt(1e18), }, }, @@ -209,7 +210,7 @@ func (s *PrecompileTestSuite) TestRun() { s.keyring.GetAddr(0), []cmn.Coin{ { - Denom: constants.ExampleAttoDenom, + Denom: testconstants.ExampleAttoDenom, Amount: big.NewInt(1e18), }, { @@ -312,7 +313,7 @@ func (s *PrecompileTestSuite) TestCMS() { valAddr, err := sdk.ValAddressFromBech32(s.network.GetValidators()[0].OperatorAddress) s.Require().NoError(err) val, _ := s.network.App.GetStakingKeeper().GetValidator(ctx, valAddr) - coins := sdk.NewCoins(sdk.NewCoin(constants.ExampleAttoDenom, math.NewInt(1e18))) + coins := sdk.NewCoins(sdk.NewCoin(testconstants.ExampleAttoDenom, math.NewInt(1e18))) s.Require().NoError(s.network.App.GetDistrKeeper().AllocateTokensToValidator(ctx, val, sdk.NewDecCoinsFromCoins(coins...))) input, err := s.precompile.Pack( @@ -334,7 +335,7 @@ func (s *PrecompileTestSuite) TestCMS() { caller := common.BytesToAddress(valAddr) commAmt := math.LegacyNewDecWithPrec(1000000000000000000, 1) - valCommission := sdk.DecCoins{sdk.NewDecCoinFromDec(constants.ExampleAttoDenom, commAmt)} + valCommission := sdk.DecCoins{sdk.NewDecCoinFromDec(testconstants.ExampleAttoDenom, commAmt)} // set outstanding rewards s.Require().NoError(s.network.App.GetDistrKeeper().SetValidatorOutstandingRewards(ctx, valAddr, types.ValidatorOutstandingRewards{Rewards: valCommission})) // set commission @@ -411,7 +412,7 @@ func (s *PrecompileTestSuite) TestCMS() { s.keyring.GetAddr(0), []cmn.Coin{ { - Denom: constants.ExampleAttoDenom, + Denom: testconstants.ExampleAttoDenom, Amount: big.NewInt(1e18), }, }, @@ -430,7 +431,7 @@ func (s *PrecompileTestSuite) TestCMS() { s.keyring.GetAddr(0), []cmn.Coin{ { - Denom: constants.ExampleAttoDenom, + Denom: testconstants.ExampleAttoDenom, Amount: big.NewInt(1e18), }, { @@ -462,6 +463,16 @@ func (s *PrecompileTestSuite) TestCMS() { HistoricalStores: nil, } ctx = ctx.WithMultiStore(cms) + + // With virtual fee collection enabled, RefundGas uses virtual balance. + // Move the fee collector's real coins into its virtual balance. + feeCollectorAddr := authtypes.NewModuleAddress(authtypes.FeeCollectorName) + feeCoins := sdk.NewCoins(sdk.NewCoin(testconstants.ExampleAttoDenom, math.NewInt(1e18))) + err := s.network.App.GetBankKeeper().SendCoinsFromAccountToModuleVirtual( + ctx, feeCollectorAddr, authtypes.FeeCollectorName, feeCoins, + ) + s.Require().NoError(err, "failed to fund fee collector virtual balance") + baseFee := s.network.App.GetEVMKeeper().GetBaseFee(ctx) // malleate testcase diff --git a/tests/integration/precompiles/distribution/test_event.go b/tests/integration/precompiles/distribution/test_event.go index c646edb6..82be7f0d 100644 --- a/tests/integration/precompiles/distribution/test_event.go +++ b/tests/integration/precompiles/distribution/test_event.go @@ -8,7 +8,6 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/holiman/uint256" - "github.com/cosmos/evm/config" cmn "github.com/cosmos/evm/precompiles/common" "github.com/cosmos/evm/precompiles/distribution" "github.com/cosmos/evm/precompiles/testutil" @@ -16,8 +15,8 @@ import ( "github.com/cosmos/evm/x/vm/statedb" "cosmossdk.io/math" - storetypes "cosmossdk.io/store/types" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/distribution/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -59,7 +58,8 @@ func (s *PrecompileTestSuite) TestSetWithdrawAddressEvent() { err := cmn.UnpackLog(s.precompile.ABI, &setWithdrawerAddrEvent, distribution.EventTypeSetWithdrawAddress, *log) s.Require().NoError(err) s.Require().Equal(s.keyring.GetAddr(0), setWithdrawerAddrEvent.Caller) - s.Require().Equal(sdk.MustBech32ifyAddressBytes(config.Bech32Prefix, s.keyring.GetAddr(0).Bytes()), setWithdrawerAddrEvent.WithdrawerAddress) + bech32AddrPrefix := sdk.GetConfig().GetBech32AccountAddrPrefix() + s.Require().Equal(sdk.MustBech32ifyAddressBytes(bech32AddrPrefix, s.keyring.GetAddr(0).Bytes()), setWithdrawerAddrEvent.WithdrawerAddress) }, 20000, false, diff --git a/tests/integration/precompiles/distribution/test_tx.go b/tests/integration/precompiles/distribution/test_tx.go index c4b86810..7de33619 100644 --- a/tests/integration/precompiles/distribution/test_tx.go +++ b/tests/integration/precompiles/distribution/test_tx.go @@ -7,7 +7,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" - evmaddress "github.com/cosmos/evm/encoding/address" cmn "github.com/cosmos/evm/precompiles/common" "github.com/cosmos/evm/precompiles/distribution" "github.com/cosmos/evm/precompiles/testutil" @@ -677,7 +676,7 @@ func (s *PrecompileTestSuite) TestDepositValidatorRewardsPoolMethod() { s.Require().True(success, "expected true, got false") val := s.network.GetValidators()[0] - valCodec := evmaddress.NewEvmCodec("cosmosvaloper") + valCodec := s.network.App.GetStakingKeeper().ValidatorAddressCodec() valBz, err := valCodec.StringToBytes(val.GetOperator()) s.Require().NoError(err) diff --git a/tests/integration/precompiles/erc20/test_query.go b/tests/integration/precompiles/erc20/test_query.go index f462bc2c..864b66fd 100644 --- a/tests/integration/precompiles/erc20/test_query.go +++ b/tests/integration/precompiles/erc20/test_query.go @@ -9,8 +9,8 @@ import ( "github.com/cosmos/evm/precompiles/erc20" "github.com/cosmos/evm/testutil" - transferkeeper "github.com/cosmos/evm/x/ibc/transfer/keeper" - "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" + transferkeeper "github.com/cosmos/ibc-go/v11/modules/apps/transfer/keeper" + "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" sdkmath "cosmossdk.io/math" @@ -112,7 +112,7 @@ func (s *PrecompileTestSuite) TestNameSymbol() { testcases := []struct { name string denom string - malleate func(sdk.Context, bankkeeper.Keeper, transferkeeper.Keeper) + malleate func(sdk.Context, bankkeeper.Keeper, *transferkeeper.Keeper) expPass bool errContains string expName string @@ -131,7 +131,7 @@ func (s *PrecompileTestSuite) TestNameSymbol() { { name: "fail - invalid denom (too short < 3 chars)", denom: tooShort.IBCDenom(), - malleate: func(ctx sdk.Context, _ bankkeeper.Keeper, keeper transferkeeper.Keeper) { + malleate: func(ctx sdk.Context, _ bankkeeper.Keeper, keeper *transferkeeper.Keeper) { keeper.SetDenom(ctx, tooShort) }, errContains: vm.ErrExecutionReverted.Error(), @@ -144,7 +144,7 @@ func (s *PrecompileTestSuite) TestNameSymbol() { { name: "pass - valid ibc denom without metadata and neither atto nor micro prefix", denom: validDenomNoMicroAtto.IBCDenom(), - malleate: func(ctx sdk.Context, _ bankkeeper.Keeper, keeper transferkeeper.Keeper) { + malleate: func(ctx sdk.Context, _ bankkeeper.Keeper, keeper *transferkeeper.Keeper) { keeper.SetDenom(ctx, validDenomNoMicroAtto) }, expPass: true, @@ -154,7 +154,7 @@ func (s *PrecompileTestSuite) TestNameSymbol() { { name: "pass - valid denom with metadata", denom: validMetadataDenom, - malleate: func(ctx sdk.Context, keeper bankkeeper.Keeper, _ transferkeeper.Keeper) { + malleate: func(ctx sdk.Context, keeper bankkeeper.Keeper, _ *transferkeeper.Keeper) { // NOTE: we mint some coins to the inflation module address to be able to set denom metadata err := keeper.MintCoins(ctx, minttypes.ModuleName, sdk.Coins{sdk.NewInt64Coin(validMetadata.Base, 1)}) s.Require().NoError(err) @@ -169,7 +169,7 @@ func (s *PrecompileTestSuite) TestNameSymbol() { { name: "pass - valid ibc denom without metadata", denom: validDenom.IBCDenom(), - malleate: func(ctx sdk.Context, _ bankkeeper.Keeper, keeper transferkeeper.Keeper) { + malleate: func(ctx sdk.Context, _ bankkeeper.Keeper, keeper *transferkeeper.Keeper) { keeper.SetDenom(ctx, validDenom) }, expPass: true, @@ -190,7 +190,7 @@ func (s *PrecompileTestSuite) TestNameSymbol() { s.Require().NoError(err) s.Run("name", func() { - bz, err := precompile.Name( + bz, err := precompile.TokenName( s.network.GetContext(), nil, nil, @@ -224,7 +224,7 @@ func (s *PrecompileTestSuite) TestDecimals() { testcases := []struct { name string denom string - malleate func(sdk.Context, bankkeeper.Keeper, transferkeeper.Keeper) + malleate func(sdk.Context, bankkeeper.Keeper, *transferkeeper.Keeper) expPass bool errContains string expDecimals uint8 @@ -247,7 +247,7 @@ func (s *PrecompileTestSuite) TestDecimals() { { name: "fail - valid ibc denom without metadata and neither atto nor micro prefix", denom: validDenomNoMicroAtto.IBCDenom(), - malleate: func(ctx sdk.Context, _ bankkeeper.Keeper, keeper transferkeeper.Keeper) { + malleate: func(ctx sdk.Context, _ bankkeeper.Keeper, keeper *transferkeeper.Keeper) { keeper.SetDenom(ctx, validDenomNoMicroAtto) }, errContains: vm.ErrExecutionReverted.Error(), @@ -255,7 +255,7 @@ func (s *PrecompileTestSuite) TestDecimals() { { name: "pass - invalid denom (too short < 3 chars)", denom: tooShort.IBCDenom(), - malleate: func(ctx sdk.Context, _ bankkeeper.Keeper, keeper transferkeeper.Keeper) { + malleate: func(ctx sdk.Context, _ bankkeeper.Keeper, keeper *transferkeeper.Keeper) { keeper.SetDenom(ctx, tooShort) }, expPass: true, // TODO: do we want to check in decimals query for the above error? @@ -264,7 +264,7 @@ func (s *PrecompileTestSuite) TestDecimals() { { name: "pass - valid denom with metadata", denom: validMetadataDenom, - malleate: func(ctx sdk.Context, keeper bankkeeper.Keeper, _ transferkeeper.Keeper) { + malleate: func(ctx sdk.Context, keeper bankkeeper.Keeper, _ *transferkeeper.Keeper) { // NOTE: we mint some coins to the inflation module address to be able to set denom metadata err := keeper.MintCoins(ctx, minttypes.ModuleName, sdk.Coins{sdk.NewInt64Coin(validMetadata.Base, 1)}) s.Require().NoError(err) @@ -278,7 +278,7 @@ func (s *PrecompileTestSuite) TestDecimals() { { name: "pass - valid ibc denom without metadata", denom: validDenom.IBCDenom(), - malleate: func(ctx sdk.Context, _ bankkeeper.Keeper, keeper transferkeeper.Keeper) { + malleate: func(ctx sdk.Context, _ bankkeeper.Keeper, keeper *transferkeeper.Keeper) { keeper.SetDenom(ctx, validDenom) }, expPass: true, @@ -287,7 +287,7 @@ func (s *PrecompileTestSuite) TestDecimals() { { name: "pass - valid ibc denom without metadata and 18 decimals", denom: validAttoDenom.IBCDenom(), - malleate: func(ctx sdk.Context, _ bankkeeper.Keeper, keeper transferkeeper.Keeper) { + malleate: func(ctx sdk.Context, _ bankkeeper.Keeper, keeper *transferkeeper.Keeper) { keeper.SetDenom(ctx, validAttoDenom) }, expPass: true, @@ -296,7 +296,7 @@ func (s *PrecompileTestSuite) TestDecimals() { { name: "pass - valid denom with metadata but decimals overflow", denom: validMetadataDenom, - malleate: func(ctx sdk.Context, keeper bankkeeper.Keeper, _ transferkeeper.Keeper) { + malleate: func(ctx sdk.Context, keeper bankkeeper.Keeper, _ *transferkeeper.Keeper) { // NOTE: we mint some coins to the inflation module address to be able to set denom metadata err := keeper.MintCoins(ctx, minttypes.ModuleName, sdk.Coins{sdk.NewInt64Coin(validMetadata.Base, 1)}) s.Require().NoError(err) @@ -309,7 +309,7 @@ func (s *PrecompileTestSuite) TestDecimals() { { name: "pass - valid ibc denom with metadata but no display denom", denom: validMetadataDenom, - malleate: func(ctx sdk.Context, keeper bankkeeper.Keeper, _ transferkeeper.Keeper) { + malleate: func(ctx sdk.Context, keeper bankkeeper.Keeper, _ *transferkeeper.Keeper) { // NOTE: we mint some coins to the inflation module address to be able to set denom metadata err := keeper.MintCoins(ctx, minttypes.ModuleName, sdk.Coins{sdk.NewInt64Coin(validMetadata.Base, 1)}) s.Require().NoError(err) @@ -322,7 +322,7 @@ func (s *PrecompileTestSuite) TestDecimals() { { name: "pass - valid IBC denom with metadata using display path", denom: "ibc/B89BE1E96B3DBC0ABB05F858F08561BA12B9C5E420CA2F5E83C475CCB47A834E", - malleate: func(ctx sdk.Context, keeper bankkeeper.Keeper, _ transferkeeper.Keeper) { + malleate: func(ctx sdk.Context, keeper bankkeeper.Keeper, _ *transferkeeper.Keeper) { keeper.SetDenomMetaData(ctx, banktypes.Metadata{ Base: "ibc/B89BE1E96B3DBC0ABB05F858F08561BA12B9C5E420CA2F5E83C475CCB47A834E", DenomUnits: []*banktypes.DenomUnit{ @@ -346,7 +346,7 @@ func (s *PrecompileTestSuite) TestDecimals() { { name: "fail - IBC denom with metadata but no matching display unit", denom: "ibc/C1D2E3F4567890123456789012345678901234567890123456789012345678901234", - malleate: func(ctx sdk.Context, keeper bankkeeper.Keeper, _ transferkeeper.Keeper) { + malleate: func(ctx sdk.Context, keeper bankkeeper.Keeper, _ *transferkeeper.Keeper) { keeper.SetDenomMetaData(ctx, banktypes.Metadata{ Base: "ibc/C1D2E3F4567890123456789012345678901234567890123456789012345678901234", DenomUnits: []*banktypes.DenomUnit{ diff --git a/tests/integration/precompiles/erc20/test_tx.go b/tests/integration/precompiles/erc20/test_tx.go index e50f3425..d6665679 100644 --- a/tests/integration/precompiles/erc20/test_tx.go +++ b/tests/integration/precompiles/erc20/test_tx.go @@ -333,13 +333,6 @@ func (s *PrecompileTestSuite) TestSend() { }, expFail: false, }, - { - name: "send with PreciseBankKeeper", - malleate: func() cmn.BankKeeper { - return s.network.App.GetPreciseBankKeeper() - }, - expFail: false, - }, { name: "send with MockBankKeeper", malleate: func() cmn.BankKeeper { diff --git a/tests/integration/precompiles/erc20/test_utils.go b/tests/integration/precompiles/erc20/test_utils.go index e68530fa..fe9c3d21 100644 --- a/tests/integration/precompiles/erc20/test_utils.go +++ b/tests/integration/precompiles/erc20/test_utils.go @@ -24,9 +24,9 @@ import ( errorsmod "cosmossdk.io/errors" "cosmossdk.io/math" - storetypes "cosmossdk.io/store/types" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" ) diff --git a/tests/integration/precompiles/gov/test_events.go b/tests/integration/precompiles/gov/test_events.go index 6efc7bf3..7156d08c 100644 --- a/tests/integration/precompiles/gov/test_events.go +++ b/tests/integration/precompiles/gov/test_events.go @@ -10,8 +10,7 @@ import ( "github.com/cosmos/evm/precompiles/gov" "github.com/cosmos/evm/x/vm/statedb" - storetypes "cosmossdk.io/store/types" - + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" ) diff --git a/tests/integration/precompiles/gov/test_integration.go b/tests/integration/precompiles/gov/test_integration.go index 06f11181..33f8a05e 100644 --- a/tests/integration/precompiles/gov/test_integration.go +++ b/tests/integration/precompiles/gov/test_integration.go @@ -264,9 +264,8 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp It("cancels a proposal and see cancellation fee charged", func() { // Fix the gas limit and gas price for predictable gas usage. // This is for calculating expected cancellation fee. - baseFee := s.network.App.GetFeeMarketKeeper().GetBaseFee(s.network.GetContext()) - baseFeeInt := baseFee.TruncateInt64() - txArgs.GasPrice = new(big.Int).SetInt64(baseFeeInt) + baseFee := s.network.App.GetEVMKeeper().GetBaseFee(s.network.GetContext()) + txArgs.GasPrice = baseFee txArgs.GasLimit = 500_000 // Get the prposal for cancellation @@ -1248,9 +1247,8 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp func(tc testCase) { // Fix the gas limit and gas price for predictable gas usage. // This is for calculating expected cancellation fee. - baseFee := s.network.App.GetFeeMarketKeeper().GetBaseFee(s.network.GetContext()) - baseFeeInt := baseFee.TruncateInt64() - txArgs.GasPrice = new(big.Int).SetInt64(baseFeeInt) + baseFee := s.network.App.GetEVMKeeper().GetBaseFee(s.network.GetContext()) + txArgs.GasPrice = baseFee txArgs.GasLimit = 500_000 // Prepare the proposal @@ -1406,9 +1404,8 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp func(tc testCase) { // Fix the gas limit and gas price for predictable gas usage. // This is for calculating expected cancellation fee. - baseFee := s.network.App.GetFeeMarketKeeper().GetBaseFee(s.network.GetContext()) - baseFeeInt := baseFee.TruncateInt64() - txArgs.GasPrice = new(big.Int).SetInt64(baseFeeInt) + baseFee := s.network.App.GetEVMKeeper().GetBaseFee(s.network.GetContext()) + txArgs.GasPrice = baseFee txArgs.GasLimit = 500_000 // Prepare the proposal @@ -1502,9 +1499,8 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp func(tc testCase) { // Fix the gas limit and gas price for predictable gas usage. // This is for calculating expected cancellation fee. - baseFee := s.network.App.GetFeeMarketKeeper().GetBaseFee(s.network.GetContext()) - baseFeeInt := baseFee.TruncateInt64() - txArgs.GasPrice = new(big.Int).SetInt64(baseFeeInt) + baseFee := s.network.App.GetEVMKeeper().GetBaseFee(s.network.GetContext()) + txArgs.GasPrice = baseFee txArgs.GasLimit = 500_000 txArgs.Amount = big.NewInt(300) @@ -1692,9 +1688,8 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp func(tc testCase) { // Fix the gas limit and gas ice for predictable gas usage. // This is for calculating expected cancellation fee. - baseFee := s.network.App.GetFeeMarketKeeper().GetBaseFee(s.network.GetContext()) - baseFeeInt := baseFee.TruncateInt64() - txArgs.GasPrice = new(big.Int).SetInt64(baseFeeInt) + baseFee := s.network.App.GetEVMKeeper().GetBaseFee(s.network.GetContext()) + txArgs.GasPrice = baseFee txArgs.GasLimit = 500_000 txArgs.Amount = big.NewInt(100) @@ -1925,9 +1920,8 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp func(tc testCase) { // Fix the gas limit and gas ice for predictable gas usage. // This is for calculating expected cancellation fee. - baseFee := s.network.App.GetFeeMarketKeeper().GetBaseFee(s.network.GetContext()) - baseFeeInt := baseFee.TruncateInt64() - txArgs.GasPrice = new(big.Int).SetInt64(baseFeeInt) + baseFee := s.network.App.GetEVMKeeper().GetBaseFee(s.network.GetContext()) + txArgs.GasPrice = baseFee txArgs.GasLimit = 500_000 txArgs.Amount = big.NewInt(100) @@ -2076,9 +2070,8 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp func(tc testCase) { // Fix the gas limit and gas price for predictable gas usage. // This is for calculating expected cancellation fee. - baseFee := s.network.App.GetFeeMarketKeeper().GetBaseFee(s.network.GetContext()) - baseFeeInt := baseFee.TruncateInt64() - txArgs.GasPrice = new(big.Int).SetInt64(baseFeeInt) + baseFee := s.network.App.GetEVMKeeper().GetBaseFee(s.network.GetContext()) + txArgs.GasPrice = baseFee txArgs.GasLimit = 500_000 txArgs.Amount = big.NewInt(100) randomAddr := testutiltx.GenerateAddress() diff --git a/tests/integration/precompiles/ics20/test_integration.go b/tests/integration/precompiles/ics20/test_integration.go index ca5f18cb..705b0134 100644 --- a/tests/integration/precompiles/ics20/test_integration.go +++ b/tests/integration/precompiles/ics20/test_integration.go @@ -21,8 +21,8 @@ import ( "github.com/cosmos/evm/testutil/tx" testutiltypes "github.com/cosmos/evm/testutil/types" evmtypes "github.com/cosmos/evm/x/vm/types" - "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - ibctesting "github.com/cosmos/ibc-go/v10/testing" + "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + ibctesting "github.com/cosmos/ibc-go/v11/testing" "cosmossdk.io/math" @@ -311,7 +311,6 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, evmAppCreator ibctesting.A // send some tokens to the contract address fundAmt := math.NewInt(100) - fundAmtConverted := fundAmt.Mul(math.NewInt(1e12)) err = evmAppA.GetBankKeeper().SendCoins( s.chainA.GetContext(), s.chainA.SenderAccount.GetAddress(), @@ -324,10 +323,9 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, evmAppCreator ibctesting.A s.chainA.GetContext(), ics20CallerAddr, ) - Expect(contractBalance.ToBig()).To(Equal(fundAmtConverted.BigInt()), "Contract balance should be equal to the fund amount") + Expect(contractBalance.ToBig()).To(Equal(fundAmt.BigInt()), "Contract balance should be equal to the fund amount") sendAmt := math.NewInt(1) - sendAmtConverted := sendAmt.Mul(math.NewInt(1e12)) callArgs := testutiltypes.CallArgs{ ContractABI: ics20CallerContract.ABI, MethodName: "testIbcTransferWithTransfer", @@ -356,7 +354,7 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, evmAppCreator ibctesting.A 0, ) Expect(err).To(BeNil(), "Failed to testTransfer") - expectedContractBalance := fundAmtConverted.Sub(sendAmtConverted) + expectedContractBalance := fundAmt.Sub(sendAmt) if tc.before { expectedContractBalance = expectedContractBalance.Sub(math.NewInt(15)) } @@ -407,7 +405,6 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, evmAppCreator ibctesting.A // send some tokens to the contract address fundAmt := math.NewInt(100) - fundAmtConverted := fundAmt.Mul(math.NewInt(1e12)) err = evmAppA.GetBankKeeper().SendCoins( s.chainA.GetContext(), s.chainA.SenderAccount.GetAddress(), @@ -420,7 +417,7 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, evmAppCreator ibctesting.A common.BytesToAddress(ics20CallerAddr.Bytes()), ) // check contract balance - Expect(contractBalance.ToBig()).To(Equal(fundAmtConverted.BigInt()), "Contract balance should be equal to the fund amount") + Expect(contractBalance.ToBig()).To(Equal(fundAmt.BigInt()), "Contract balance should be equal to the fund amount") sendAmt := math.NewInt(1) callArgs := testutiltypes.CallArgs{ diff --git a/tests/integration/precompiles/ics20/test_query.go b/tests/integration/precompiles/ics20/test_query.go index 0e46238c..62bcfc30 100644 --- a/tests/integration/precompiles/ics20/test_query.go +++ b/tests/integration/precompiles/ics20/test_query.go @@ -9,7 +9,7 @@ import ( cmn "github.com/cosmos/evm/precompiles/common" "github.com/cosmos/evm/precompiles/ics20" precompiletestutil "github.com/cosmos/evm/precompiles/testutil" - transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" + transfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" @@ -47,7 +47,8 @@ func (s *PrecompileTestSuite) TestDenoms() { args: []interface{}{query.PageRequest{Limit: 10, CountTotal: true}}, malleate: func(ctx sdk.Context) { evmApp := s.chainA.App.(evm.EvmApp) - evmApp.GetTransferKeeper().SetDenom(ctx, denom) + keeper := evmApp.GetTransferKeeper() + keeper.SetDenom(ctx, denom) }, expDenom: denom, }, @@ -108,7 +109,8 @@ func (s *PrecompileTestSuite) TestDenom() { arg: denom.Hash().String(), malleate: func(ctx sdk.Context) { evmApp := s.chainA.App.(evm.EvmApp) - evmApp.GetTransferKeeper().SetDenom(ctx, denom) + keeper := evmApp.GetTransferKeeper() + keeper.SetDenom(ctx, denom) }, expDenom: denom, }, @@ -189,7 +191,8 @@ func (s *PrecompileTestSuite) TestDenomHash() { arg: denom.Path(), malleate: func(ctx sdk.Context) { evmApp := s.chainA.App.(evm.EvmApp) - evmApp.GetTransferKeeper().SetDenom(ctx, denom) + keeper := evmApp.GetTransferKeeper() + keeper.SetDenom(ctx, denom) }, expHash: denom.Hash().String(), }, diff --git a/tests/integration/precompiles/ics20/test_setup.go b/tests/integration/precompiles/ics20/test_setup.go index cd90158c..e9b285e5 100644 --- a/tests/integration/precompiles/ics20/test_setup.go +++ b/tests/integration/precompiles/ics20/test_setup.go @@ -8,7 +8,7 @@ import ( "github.com/cosmos/evm" "github.com/cosmos/evm/precompiles/ics20" evmibctesting "github.com/cosmos/evm/testutil/ibc" - ibctesting "github.com/cosmos/ibc-go/v10/testing" + ibctesting "github.com/cosmos/ibc-go/v11/testing" ) type PrecompileTestSuite struct { @@ -42,20 +42,22 @@ func (s *PrecompileTestSuite) SetupTest() { s.chainA = s.coordinator.GetChain(evmibctesting.GetEvmChainID(1)) s.chainB = s.coordinator.GetChain(evmibctesting.GetEvmChainID(2)) - evmAppA := s.chainA.App.(evm.EvmApp) + evmAppA := s.chainA.App.(evm.IBCApp) s.chainAPrecompile = ics20.NewPrecompile( evmAppA.GetBankKeeper(), *evmAppA.GetStakingKeeper(), evmAppA.GetTransferKeeper(), evmAppA.GetIBCKeeper().ChannelKeeper, + evmAppA.GetErc20Keeper(), ) s.chainABondDenom, _ = evmAppA.GetStakingKeeper().BondDenom(s.chainA.GetContext()) - evmAppB := s.chainB.App.(evm.EvmApp) + evmAppB := s.chainB.App.(evm.IBCApp) s.chainBPrecompile = ics20.NewPrecompile( evmAppB.GetBankKeeper(), *evmAppB.GetStakingKeeper(), evmAppB.GetTransferKeeper(), evmAppB.GetIBCKeeper().ChannelKeeper, + evmAppB.GetErc20Keeper(), ) s.chainBBondDenom, _ = evmAppB.GetStakingKeeper().BondDenom(s.chainB.GetContext()) } diff --git a/tests/integration/precompiles/ics20/test_tx.go b/tests/integration/precompiles/ics20/test_tx.go index cbd34287..49447460 100644 --- a/tests/integration/precompiles/ics20/test_tx.go +++ b/tests/integration/precompiles/ics20/test_tx.go @@ -10,8 +10,8 @@ import ( evmibctesting "github.com/cosmos/evm/testutil/ibc" "github.com/cosmos/evm/testutil/tx" evmtypes "github.com/cosmos/evm/x/vm/types" - transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" + transfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/v11/modules/core/02-client/types" sdkmath "cosmossdk.io/math" diff --git a/tests/integration/precompiles/p256/test_integration.go b/tests/integration/precompiles/p256/test_integration.go index 88a0bf2e..8ad73846 100644 --- a/tests/integration/precompiles/p256/test_integration.go +++ b/tests/integration/precompiles/p256/test_integration.go @@ -16,6 +16,7 @@ import ( "github.com/cometbft/cometbft/crypto" "github.com/cosmos/evm/precompiles/p256" + "github.com/cosmos/evm/testutil/constants" "github.com/cosmos/evm/testutil/integration/evm/factory" "github.com/cosmos/evm/testutil/integration/evm/grpc" "github.com/cosmos/evm/testutil/integration/evm/network" @@ -123,6 +124,7 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp When("the precompile is not enabled in the EVM params", func() { BeforeAll(func() { customGenesis := evmtypes.DefaultGenesisState() + customGenesis.Params.EvmDenom = constants.ChainsCoinInfo[constants.EighteenDecimalsChainID].Denom customGenesis.Params.ActiveStaticPrecompiles = evmtypes.AvailableStaticPrecompiles params := customGenesis.Params addr := s.precompileAddress.String() diff --git a/tests/integration/precompiles/slashing/test_events.go b/tests/integration/precompiles/slashing/test_events.go index c0a68440..2052f136 100644 --- a/tests/integration/precompiles/slashing/test_events.go +++ b/tests/integration/precompiles/slashing/test_events.go @@ -10,8 +10,7 @@ import ( "github.com/cosmos/evm/precompiles/slashing" "github.com/cosmos/evm/x/vm/statedb" - storetypes "cosmossdk.io/store/types" - + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" ) diff --git a/tests/integration/precompiles/staking/test_integration.go b/tests/integration/precompiles/staking/test_integration.go index 059483b3..9759590a 100644 --- a/tests/integration/precompiles/staking/test_integration.go +++ b/tests/integration/precompiles/staking/test_integration.go @@ -22,6 +22,7 @@ import ( "github.com/cosmos/evm/precompiles/testutil" "github.com/cosmos/evm/precompiles/testutil/contracts" cosmosevmutil "github.com/cosmos/evm/testutil/constants" + basefactory "github.com/cosmos/evm/testutil/integration/base/factory" "github.com/cosmos/evm/testutil/integration/evm/network" "github.com/cosmos/evm/testutil/integration/evm/utils" testutiltx "github.com/cosmos/evm/testutil/tx" @@ -35,6 +36,8 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/types/query" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) @@ -428,6 +431,90 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp }) }) + Context("from a vesting account", func() { + var ( + vestAddr sdk.AccAddress + vestPriv *ethsecp256k1.PrivKey + amtLocked math.Int + amtSpendable math.Int + preBal math.Int + preSupply math.Int + ) + + BeforeEach(func() { + // setup vesting account to delegate from + vestAddr, vestPriv = testutiltx.NewAccAddressAndKey() + amtLocked = math.NewInt(2e18) + amtSpendable = math.NewInt(2e18) + + funder := s.keyring.GetKey(0) + startTime := s.network.GetContext().BlockTime().Unix() + createMsg := &vestingtypes.MsgCreateVestingAccount{ + FromAddress: funder.AccAddr.String(), + ToAddress: vestAddr.String(), + Amount: sdk.NewCoins(sdk.NewCoin(s.bondDenom, amtLocked)), + EndTime: startTime + 365*24*3600, + Delayed: false, + } + sendMsg := banktypes.NewMsgSend( + funder.AccAddr, vestAddr, + sdk.NewCoins(sdk.NewCoin(s.bondDenom, amtSpendable)), + ) + _, err := s.factory.CommitCosmosTx(funder.Priv, basefactory.CosmosTxArgs{ + Msgs: []sdk.Msg{createMsg, sendMsg}, + }) + Expect(err).To(BeNil(), "error while submitting vesting setup tx") + + ctx := s.network.GetContext() + _, ok := s.network.App.GetAccountKeeper().GetAccount(ctx, vestAddr).(*vestingtypes.ContinuousVestingAccount) + Expect(ok).To(BeTrue(), "expected vesting account to persist after tx commit") + spendable := s.network.App.GetBankKeeper().SpendableCoin(ctx, vestAddr, s.bondDenom).Amount + Expect(spendable).To(Equal(amtSpendable), "unexpected spendable balance after vesting setup") + + preBalRes, err := s.grpcHandler.GetBalanceFromBank(vestAddr, s.bondDenom) + Expect(err).To(BeNil(), "error while getting pre balance") + preBal = preBalRes.Balance.Amount + Expect(preBal).To(Equal(amtLocked.Add(amtSpendable)), "expected vester pre bank balance to equal OV + extra") + + preSupplyRes, err := s.grpcHandler.GetTotalSupply() + Expect(err).To(BeNil(), "error while getting pre supply") + preSupply = preSupplyRes.Supply.AmountOf(s.bondDenom) + }) + + It("should preserve bank balance and total supply when delegating within spendable", func() { + // delegating less than spendable balance and less than + // locked balance + delAmt := big.NewInt(1e18) + gasPrice := big.NewInt(1e9) + + callArgs.Args = []interface{}{ + common.BytesToAddress(vestAddr), valAddr.String(), delAmt, + } + delTxArgs := txArgs + delTxArgs.GasPrice = gasPrice + + logCheckArgs := passCheck.WithExpEvents(staking.EventTypeDelegate) + res, _, err := s.factory.CallContractAndCheckLogs( + vestPriv, delTxArgs, callArgs, logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + postBalRes, err := s.grpcHandler.GetBalanceFromBank(vestAddr, s.bondDenom) + Expect(err).To(BeNil(), "error while getting post balance") + postSupplyRes, err := s.grpcHandler.GetTotalSupply() + Expect(err).To(BeNil(), "error while getting post supply") + postBal := postBalRes.Balance.Amount + postSupply := postSupplyRes.Supply.AmountOf(s.bondDenom) + + gasCost := new(big.Int).Mul(gasPrice, big.NewInt(res.GasUsed)) + expBalDrop := new(big.Int).Add(delAmt, gasCost) + actualBalDrop := preBal.Sub(postBal).BigInt() + Expect(actualBalDrop).To(Equal(expBalDrop), "vesting bank balance dropped by more than delegation amount + gas") + Expect(postSupply).To(Equal(preSupply), "unexpected total supply after delegating from vesting account") + }) + }) + Context("on behalf of another account", func() { It("should not delegate if delegator address is not the msg.sender", func() { delegator := s.keyring.GetKey(0) @@ -694,9 +781,11 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp logCheckArgs := passCheck. WithExpEvents(staking.EventTypeCancelUnbondingDelegation) + cancelTxArgs := txArgs + cancelTxArgs.GasLimit = 200_000 _, _, err = s.factory.CallContractAndCheckLogs( delegator.Priv, - txArgs, + cancelTxArgs, callArgs, logCheckArgs, ) @@ -2151,6 +2240,59 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp bondedTokensPoolFinalBalance := balRes.Balance Expect(bondedTokensPoolFinalBalance.Amount).To(Equal(bondedTokensPoolInitialBalance.Amount)) }) + + DescribeTable("should not delegate and update balances accordingly across orderings - internal transfer to tokens pool", + func(tc struct { + before bool + after bool + msgAmt *big.Int + }, + ) { + args.MethodName = "testDelegateWithTransfer" + args.Args = []interface{}{ + common.BytesToAddress(bondedTokensPoolAccAddr), + s.keyring.GetAddr(0), valAddr.String(), tc.before, tc.after, + } + + txArgs.To = &contractTwoAddr + if tc.msgAmt != nil { + txArgs.Amount = tc.msgAmt + } + + reverReasonCheck := execRevertedCheck.WithErrContains( + errorsmod.Wrapf( + sdkerrors.ErrUnauthorized, "%s is not allowed to receive funds", bondedTokensPoolAccAddr.String(), + ).Error(), + ) + + _, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + args, + reverReasonCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + balRes, err := s.grpcHandler.GetBalanceFromBank(contractTwoAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + Expect(balRes.Balance.Amount).To(Equal(contractInitialBalance.Amount)) + + balRes, err = s.grpcHandler.GetBalanceFromBank(bondedTokensPoolAccAddr, s.bondDenom) + Expect(err).To(BeNil()) + Expect(balRes.Balance.Amount).To(Equal(bondedTokensPoolInitialBalance.Amount)) + }, + Entry("internal transfer after precompile call", struct { + before bool + after bool + msgAmt *big.Int + }{before: false, after: true, msgAmt: nil}), + Entry("internal transfer after precompile call with matching amounts", struct { + before bool + after bool + msgAmt *big.Int + }{before: false, after: true, msgAmt: big.NewInt(15)}), + ) }) It("should not delegate when validator does not exist", func() { @@ -3374,7 +3516,21 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp Expect(s.network.NextBlock()).To(BeNil()) // Check that the StakingCaller contract has the correct balance - erc20Balance := s.network.App.GetErc20Keeper().BalanceOf(s.network.GetContext(), erc20Contract.ABI, erc20ContractAddr, contractAddr) + ethRes, err := s.factory.QueryContract( + evmtypes.EvmTxArgs{ + To: &erc20ContractAddr, + }, + testutiltypes.CallArgs{ + ContractABI: erc20Contract.ABI, + MethodName: "balanceOf", + Args: []interface{}{contractAddr}, + }, + 0, + ) + Expect(err).To(BeNil(), "error while querying the ERC20 balance of the StakingCaller contract") + var erc20Balance *big.Int + err = erc20Contract.ABI.UnpackIntoInterface(&erc20Balance, "balanceOf", ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the ERC20 balance result") Expect(erc20Balance).To(Equal(mintAmount), "expected different ERC20 balance for the StakingCaller contract") // populate default call args @@ -3457,9 +3613,23 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp Expect(res.DelegationResponse).NotTo(BeNil()) delegationPost := res.DelegationResponse.Delegation sharesPost := delegationPost.GetShares() - erc20BalancePost := s.network.App.GetErc20Keeper().BalanceOf(s.network.GetContext(), erc20Contract.ABI, erc20ContractAddr, delegator.Addr) - Expect(sharesPost).To(Equal(sharesPre), "expected shares to be equal when reverting state") + + var erc20BalancePost *big.Int + ethRes, err := s.factory.QueryContract( + evmtypes.EvmTxArgs{ + To: &erc20ContractAddr, + }, + testutiltypes.CallArgs{ + ContractABI: erc20Contract.ABI, + MethodName: "balanceOf", + Args: []interface{}{delegator.Addr}, + }, + 0, + ) + Expect(err).To(BeNil(), "error while querying the ERC20 balance of delegator") + err = erc20Contract.ABI.UnpackIntoInterface(&erc20BalancePost, "balanceOf", ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the ERC20 balance result") Expect(erc20BalancePost.Int64()).To(BeZero(), "expected erc20 balance of target address to be zero when reverting state") }) @@ -3490,9 +3660,23 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp Expect(res.DelegationResponse).NotTo(BeNil()) delegationPost := res.DelegationResponse.Delegation sharesPost := delegationPost.GetShares() - erc20BalancePost := s.network.App.GetErc20Keeper().BalanceOf(s.network.GetContext(), erc20Contract.ABI, erc20ContractAddr, delegator.Addr) - Expect(sharesPost).To(Equal(sharesPre), "expected shares to be equal when reverting state") + + ethRes, err := s.factory.QueryContract( + evmtypes.EvmTxArgs{ + To: &erc20ContractAddr, + }, + testutiltypes.CallArgs{ + ContractABI: erc20Contract.ABI, + MethodName: "balanceOf", + Args: []interface{}{delegator.Addr}, + }, + 0, + ) + Expect(err).To(BeNil(), "error while querying the ERC20 balance of delegator") + var erc20BalancePost *big.Int + err = erc20Contract.ABI.UnpackIntoInterface(&erc20BalancePost, "balanceOf", ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the ERC20 balance result") Expect(erc20BalancePost.Int64()).To(BeZero(), "expected erc20 balance of target address to be zero when reverting state") }) @@ -3538,9 +3722,23 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp ) delegationPost := res.DelegationResponse.Delegation sharesPost := delegationPost.GetShares() - erc20BalancePost := s.network.App.GetErc20Keeper().BalanceOf(s.network.GetContext(), erc20Contract.ABI, erc20ContractAddr, delegator.Addr) - Expect(sharesPost.GT(sharesPre)).To(BeTrue(), "expected shares to be more than before") + + ethRes, err := s.factory.QueryContract( + evmtypes.EvmTxArgs{ + To: &erc20ContractAddr, + }, + testutiltypes.CallArgs{ + ContractABI: erc20Contract.ABI, + MethodName: "balanceOf", + Args: []interface{}{delegator.Addr}, + }, + 0, + ) + Expect(err).To(BeNil(), "error while querying the ERC20 balance of delegator") + var erc20BalancePost *big.Int + err = erc20Contract.ABI.UnpackIntoInterface(&erc20BalancePost, "balanceOf", ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the ERC20 balance result") Expect(erc20BalancePost).To(Equal(transferredAmount), "expected different erc20 balance of target address") }) }) diff --git a/tests/integration/precompiles/staking/test_query.go b/tests/integration/precompiles/staking/test_query.go index b5165cfd..46f94212 100644 --- a/tests/integration/precompiles/staking/test_query.go +++ b/tests/integration/precompiles/staking/test_query.go @@ -504,7 +504,8 @@ func (s *PrecompileTestSuite) TestRedelegation() { { name: "success - no redelegation found", malleate: func(srcOperatorAddr, _ string) []interface{} { - nonExistentOperator := sdk.ValAddress([]byte("non-existent-operator")) + nonExistentAddr, _ := testutiltx.NewAccAddressAndKey() + nonExistentOperator := sdk.ValAddress(nonExistentAddr) return []interface{}{ s.keyring.GetAddr(0), srcOperatorAddr, diff --git a/tests/integration/precompiles/staking/test_staking.go b/tests/integration/precompiles/staking/test_staking.go index 9bc4c715..aa4a0a37 100644 --- a/tests/integration/precompiles/staking/test_staking.go +++ b/tests/integration/precompiles/staking/test_staking.go @@ -21,6 +21,7 @@ import ( "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) @@ -132,6 +133,7 @@ func (s *PrecompileTestSuite) TestRun() { gas uint64 readOnly bool expPass bool + expRevert bool // true if error returns ABI-encoded revert reason bytes (not OOG) errContains string }{ { @@ -149,6 +151,7 @@ func (s *PrecompileTestSuite) TestRun() { 8000, false, false, + false, "out of gas", }, { @@ -166,6 +169,7 @@ func (s *PrecompileTestSuite) TestRun() { 1000000, false, true, + false, "", }, { @@ -183,6 +187,7 @@ func (s *PrecompileTestSuite) TestRun() { 1000000, false, true, + false, "", }, { @@ -201,6 +206,7 @@ func (s *PrecompileTestSuite) TestRun() { 1000000, false, true, + false, "failed to redelegate tokens", }, { @@ -241,6 +247,7 @@ func (s *PrecompileTestSuite) TestRun() { 1000000, false, true, + false, "", }, { @@ -257,6 +264,7 @@ func (s *PrecompileTestSuite) TestRun() { 1000000, false, true, + false, "", }, { @@ -275,6 +283,7 @@ func (s *PrecompileTestSuite) TestRun() { 1000000, false, true, + false, "", }, { @@ -313,6 +322,7 @@ func (s *PrecompileTestSuite) TestRun() { 1000000, false, true, + false, "", }, { @@ -329,6 +339,7 @@ func (s *PrecompileTestSuite) TestRun() { 1000000, true, true, + false, "", }, { @@ -367,6 +378,7 @@ func (s *PrecompileTestSuite) TestRun() { 1000000, true, true, + false, "", }, { @@ -381,9 +393,10 @@ func (s *PrecompileTestSuite) TestRun() { s.Require().NoError(err, "failed to pack input") return input }, - 21295, // use enough gas to avoid out of gas error + 25000, // use enough gas to avoid out of gas error true, false, + true, "write protection", }, { @@ -391,9 +404,10 @@ func (s *PrecompileTestSuite) TestRun() { func(_ keyring.Key) []byte { return []byte("invalid") }, - 21295, // use enough gas to avoid out of gas error + 25000, // use enough gas to avoid out of gas error false, false, + true, "no method with id", }, } @@ -454,17 +468,20 @@ func (s *PrecompileTestSuite) TestRun() { bz, err := s.precompile.Run(evm, contract, tc.readOnly) // Check results - if tc.expPass { + switch { + case tc.expPass: s.Require().NoError(err, "expected no error when running the precompile") s.Require().NotNil(bz, "expected returned bytes not to be nil") - } else { - s.Require().Error(err, "expected error to be returned when running the precompile") - s.Require().NotNil(bz, "expected returned bytes to be nil") - execRevertErr := evmtypes.NewExecErrorWithReason(bz) - s.Require().ErrorContains(execRevertErr, tc.errContains) + case tc.expRevert: + s.Require().ErrorIs(err, vm.ErrExecutionReverted) + s.Require().NotNil(bz, "expected revert reason bytes") + revertErr := evmtypes.NewExecErrorWithReason(bz) + s.Require().ErrorContains(revertErr, tc.errContains) + default: + s.Require().ErrorIs(err, vm.ErrOutOfGas) + s.Require().Nil(bz, "expected nil bytes on out of gas") consumed := ctx.GasMeter().GasConsumed() - // LessThanOrEqual because the gas is consumed before the error is returned - s.Require().LessOrEqual(tc.gas, consumed, "expected gas consumed to be equal to gas limit") + s.Require().LessOrEqual(tc.gas, consumed, "expected all gas to be consumed on OOG") } }) } @@ -741,6 +758,16 @@ func (s *PrecompileTestSuite) TestCMS() { HistoricalStores: nil, } ctx = ctx.WithMultiStore(cms) + + // With virtual fee collection enabled, RefundGas uses virtual balance. + // Move the fee collector's real coins into its virtual balance. + feeCollectorAddr := authtypes.NewModuleAddress(authtypes.FeeCollectorName) + feeCoins := sdk.NewCoins(sdk.NewCoin(testconstants.ExampleAttoDenom, math.NewInt(InitialTestBalance))) + err := s.network.App.GetBankKeeper().SendCoinsFromAccountToModuleVirtual( + ctx, feeCollectorAddr, authtypes.FeeCollectorName, feeCoins, + ) + s.Require().NoError(err, "failed to fund fee collector virtual balance") + baseFee := s.network.App.GetEVMKeeper().GetBaseFee(ctx) delegator := s.keyring.GetKey(0) diff --git a/tests/integration/precompiles/staking/test_tx.go b/tests/integration/precompiles/staking/test_tx.go index 0e48f224..214d3d75 100644 --- a/tests/integration/precompiles/staking/test_tx.go +++ b/tests/integration/precompiles/staking/test_tx.go @@ -248,7 +248,7 @@ func (s *PrecompileTestSuite) TestCreateValidator() { { "fail - cannot be called from account with code (if it is not EIP-7702 delegated account)", func() []interface{} { - stDB.SetCode(validatorAddress, []byte{0x60, 0x00}) + stDB.SetCode(validatorAddress, []byte{0x60, 0x00}, 0x0) return []interface{}{ description, commission, @@ -562,7 +562,7 @@ func (s *PrecompileTestSuite) TestEditValidator() { { "fail - cannot be called from smart contract", func() []interface{} { - stDB.SetCode(validatorAddress, []byte{0x60, 0x00}) + stDB.SetCode(validatorAddress, []byte{0x60, 0x00}, 0x0) return []interface{}{ description, validatorAddress, diff --git a/tests/integration/precompiles/werc20/test_integration.go b/tests/integration/precompiles/werc20/test_integration.go index ea5e1a0e..ae442f3d 100644 --- a/tests/integration/precompiles/werc20/test_integration.go +++ b/tests/integration/precompiles/werc20/test_integration.go @@ -24,7 +24,6 @@ import ( testutiltypes "github.com/cosmos/evm/testutil/types" erc20types "github.com/cosmos/evm/x/erc20/types" feemarkettypes "github.com/cosmos/evm/x/feemarket/types" - precisebanktypes "github.com/cosmos/evm/x/precisebank/types" evmtypes "github.com/cosmos/evm/x/vm/types" "cosmossdk.io/math" @@ -63,28 +62,11 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp revertContractAddr common.Address // Account balance tracking - accountBalances []*AccountBalanceInfo - precisebankRemainder *big.Int + accountBalances []*AccountBalanceInfo ) - // Configure deposit amounts with integer and fractional components to test - // precise balance handling across different decimal configurations - var conversionFactor *big.Int - switch chainId { - case testconstants.SixDecimalsChainID: - conversionFactor = big.NewInt(1e12) // For 6-decimal chains - case testconstants.TwelveDecimalsChainID: - conversionFactor = big.NewInt(1e6) // For 12-decimal chains - default: - conversionFactor = big.NewInt(1) // For 18-decimal chains - } - - // Create deposit with 1000 integer units + fractional part + // Create deposit with 1000 integer units depositAmount := big.NewInt(1000) - depositAmount = depositAmount.Mul(depositAmount, conversionFactor) // 1000 integer units - depositFractional := new(big.Int).Div(new(big.Int).Mul(conversionFactor, big.NewInt(3)), big.NewInt(10)) // 0.3 * conversion factor as fractional - depositAmount = depositAmount.Add(depositAmount, depositFractional) - withdrawAmount := depositAmount transferAmount := big.NewInt(10) // Start with 10 integer units @@ -216,7 +198,6 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp // Reset expected balance change of accounts ResetExpectedDeltas(accountBalances) - precisebankRemainder = big.NewInt(0) }) // JustBeforeEach takes snapshots after individual test setup @@ -226,7 +207,7 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp // AfterEach verifies balance changes AfterEach(func() { - VerifyBalanceChanges(accountBalances, is.grpcHandler, precisebankRemainder) + VerifyBalanceChanges(accountBalances, is.grpcHandler) }) Context("calling a specific wrapped coin method", func() { @@ -323,7 +304,7 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp newUserAcc, newUserPriv := utiltx.NewAccAddressAndKey() newUserBalance := sdk.Coins{sdk.Coin{ Denom: evmtypes.GetEVMCoinDenom(), - Amount: math.NewIntFromBigInt(withdrawAmount).Quo(precisebanktypes.ConversionFactor()).SubRaw(1), + Amount: math.NewIntFromBigInt(withdrawAmount).SubRaw(1), }} err := is.network.App.GetBankKeeper().SendCoins(is.network.GetContext(), user.AccAddr, newUserAcc, newUserBalance) Expect(err).ToNot(HaveOccurred(), "expected no error sending tokens") @@ -422,17 +403,10 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp When("to call the deposit", func() { It("it should return funds to the last sender and emit the event", func() { borrow := big.NewInt(0) - if conversionFactor.Cmp(big.NewInt(1)) != 0 { // 18-decimal chain (conversionFactor = 1) - borrow = big.NewInt(1) - } - - balanceOf(Sender).IntegerDelta = new(big.Int).Sub(new(big.Int).Neg((new(big.Int).Quo(depositAmount, conversionFactor))), borrow) - balanceOf(Sender).FractionalDelta = new(big.Int).Mod(new(big.Int).Sub(conversionFactor, depositFractional), conversionFactor) - balanceOf(Contract).IntegerDelta = new(big.Int).Quo(depositAmount, conversionFactor) - balanceOf(Contract).FractionalDelta = depositFractional + balanceOf(Sender).IntegerDelta = new(big.Int).Sub(new(big.Int).Neg((new(big.Int).Set(depositAmount))), borrow) - balanceOf(PrecisebankModule).IntegerDelta = borrow + balanceOf(Contract).IntegerDelta = new(big.Int).Set(depositAmount) txArgs, callArgs := callsData.getTxAndCallArgs(contractCall, "depositWithRevert", false, false) txArgs.Amount = depositAmount @@ -552,11 +526,8 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp err = is.precompile.UnpackIntoInterface(&decimals, erc20.DecimalsMethod, ethRes.Ret) Expect(err).ToNot(HaveOccurred(), "failed to unpack result") - coinInfo := testconstants.ExampleChainCoinInfo[testconstants.ChainID{ - ChainID: is.network.GetChainID(), - EVMChainID: is.network.GetEIP155ChainID().Uint64(), - }] - Expect(decimals).To(Equal(uint8(coinInfo.Decimals)), "expected different decimals") //nolint:gosec // G115 + // Without precisebank, all chains operate natively with 18 decimals + Expect(decimals).To(Equal(uint8(evmtypes.EighteenDecimals)), "expected 18 decimals") }, ) }) diff --git a/tests/integration/precompiles/werc20/test_utils.go b/tests/integration/precompiles/werc20/test_utils.go index a82bd824..4b0053cf 100644 --- a/tests/integration/precompiles/werc20/test_utils.go +++ b/tests/integration/precompiles/werc20/test_utils.go @@ -13,11 +13,9 @@ import ( "github.com/cosmos/evm/testutil/integration/evm/grpc" "github.com/cosmos/evm/testutil/keyring" testutiltypes "github.com/cosmos/evm/testutil/types" - precisebanktypes "github.com/cosmos/evm/x/precisebank/types" evmtypes "github.com/cosmos/evm/x/vm/types" sdk "github.com/cosmos/cosmos-sdk/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" ) // callType constants to differentiate between @@ -87,7 +85,6 @@ const ( Receiver Precompile Contract - PrecisebankModule ) // String returns the string representation of AccountType @@ -101,8 +98,6 @@ func (at AccountType) String() string { return "precompile" case Contract: return "contract" - case PrecisebankModule: - return "precisebank module" default: return "unknown" } @@ -110,8 +105,7 @@ func (at AccountType) String() string { // BalanceSnapshot represents a snapshot of account balances for testing type BalanceSnapshot struct { - IntegerBalance *big.Int - FractionalBalance *big.Int + IntegerBalance *big.Int } // AccountBalanceInfo holds balance tracking information for a test account @@ -128,13 +122,11 @@ func InitializeAccountBalances( senderAddr, receiverAddr sdk.AccAddress, precompileAddr, contractAddr common.Address, ) []*AccountBalanceInfo { - precisebankModuleAddr := authtypes.NewModuleAddress(precisebanktypes.ModuleName) return []*AccountBalanceInfo{ {AccountType: Sender, Address: senderAddr}, {AccountType: Receiver, Address: receiverAddr}, {AccountType: Precompile, Address: precompileAddr.Bytes()}, {AccountType: Contract, Address: contractAddr.Bytes()}, - {AccountType: PrecisebankModule, Address: precisebankModuleAddr}, } } @@ -159,17 +151,11 @@ func TakeBalanceSnapshots(accounts []*AccountBalanceInfo, grpcHandler grpc.Handl func VerifyBalanceChanges( accounts []*AccountBalanceInfo, grpcHandler grpc.Handler, - expectedRemainder *big.Int, ) { for _, account := range accounts { ExpectBalanceChange(account.Address, account.BeforeSnapshot, account.IntegerDelta, account.FractionalDelta, account.AccountType.String(), grpcHandler) } - - res, err := grpcHandler.Remainder() - Expect(err).ToNot(HaveOccurred(), "failed to get precisebank module remainder") - actualRemainder := res.Remainder.Amount.BigInt() - Expect(actualRemainder).To(Equal(expectedRemainder)) } // GetAccountBalance returns the AccountBalanceInfo for a given account type @@ -190,15 +176,8 @@ func GetBalanceSnapshot(addr sdk.AccAddress, grpcHandler grpc.Handler) (*Balance return nil, fmt.Errorf("failed to get integer balance: %w", err) } - // Get fractional balance using the new grpcHandler method - fracRes, err := grpcHandler.FractionalBalance(addr) - if err != nil { - return nil, fmt.Errorf("failed to get fractional balance: %w", err) - } - return &BalanceSnapshot{ - IntegerBalance: intRes.Balance.Amount.BigInt(), - FractionalBalance: fracRes.FractionalBalance.Amount.BigInt(), + IntegerBalance: intRes.Balance.Amount.BigInt(), }, nil } @@ -215,13 +194,8 @@ func ExpectBalanceChange( Expect(err).ToNot(HaveOccurred(), "failed to get balance snapshot for %s", description) actualIntegerDelta := new(big.Int).Sub(afterSnapshot.IntegerBalance, beforeSnapshot.IntegerBalance) - actualFractionalDelta := new(big.Int).Sub(afterSnapshot.FractionalBalance, beforeSnapshot.FractionalBalance) Expect(actualIntegerDelta.Cmp(expectedIntegerDelta)).To(Equal(0), "integer balance delta mismatch for %s: expected %s, got %s", description, expectedIntegerDelta.String(), actualIntegerDelta.String()) - - Expect(actualFractionalDelta.Cmp(expectedFractionalDelta)).To(Equal(0), - "fractional balance delta mismatch for %s: expected %s, got %s", - description, expectedFractionalDelta.String(), actualFractionalDelta.String()) } diff --git a/tests/integration/rpc/backend/test_account_info.go b/tests/integration/rpc/backend/test_account_info.go index 8afaf045..0a4868e3 100644 --- a/tests/integration/rpc/backend/test_account_info.go +++ b/tests/integration/rpc/backend/test_account_info.go @@ -67,7 +67,7 @@ func (s *TestSuite) TestGetCode() { s.SetupTest() // reset tc.registerMock(tc.addr) - code, err := s.backend.GetCode(tc.addr, tc.blockNrOrHash) + code, err := s.backend.GetCode(s.Ctx(), tc.addr, tc.blockNrOrHash) if tc.expPass { s.Require().NoError(err) s.Require().Equal(tc.expCode, code) @@ -128,7 +128,7 @@ func (s *TestSuite) TestGetProof() { rpctypes.BlockNumberOrHash{BlockNumber: &blockNr}, func(bn rpctypes.BlockNumber, addr common.Address) { height := bn.Int64() - s.backend.Ctx = rpctypes.ContextWithHeight(height) + // Context is now passed to methods directly, not stored in backend client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterHeader(client, &height, nil) QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) @@ -175,7 +175,7 @@ func (s *TestSuite) TestGetProof() { rpctypes.BlockNumberOrHash{BlockNumber: &blockNrZero}, func(bn rpctypes.BlockNumber, addr common.Address) { height := int64(4) - s.backend.Ctx = rpctypes.ContextWithHeight(height) + // Context is now passed to methods directly, not stored in backend client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterHeader(client, &height, nil) queryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) @@ -223,7 +223,7 @@ func (s *TestSuite) TestGetProof() { s.SetupTest() tc.registerMock(*tc.blockNrOrHash.BlockNumber, tc.addr) - accRes, err := s.backend.GetProof(tc.addr, tc.storageKeys, tc.blockNrOrHash) + accRes, err := s.backend.GetProof(s.Ctx(), tc.addr, tc.storageKeys, tc.blockNrOrHash) if tc.expPass { s.Require().NoError(err) @@ -286,7 +286,7 @@ func (s *TestSuite) TestGetStorageAt() { s.SetupTest() tc.registerMock(tc.addr, tc.key, tc.expStorage.String()) - storage, err := s.backend.GetStorageAt(tc.addr, tc.key, tc.blockNrOrHash) + storage, err := s.backend.GetStorageAt(s.Ctx(), tc.addr, tc.key, tc.blockNrOrHash) if tc.expPass { s.Require().NoError(err) s.Require().Equal(tc.expStorage, storage) @@ -395,7 +395,7 @@ func (s *TestSuite) TestGetBalance() { tc.registerMock(*tc.blockNrOrHash.BlockNumber, tc.addr) } - balance, err := s.backend.GetBalance(tc.addr, tc.blockNrOrHash) + balance, err := s.backend.GetBalance(s.Ctx(), tc.addr, tc.blockNrOrHash) if tc.expPass { s.Require().NoError(err) s.Require().Equal(tc.expBalance, balance) @@ -472,7 +472,7 @@ func (s *TestSuite) TestGetTransactionCount() { tc.registerMock(addr, tc.blockNum) - txCount, err := s.backend.GetTransactionCount(addr, tc.blockNum) + txCount, err := s.backend.GetTransactionCount(s.Ctx(), addr, tc.blockNum) if tc.expPass { s.Require().NoError(err) s.Require().Equal(tc.expTxCount, *txCount) diff --git a/tests/integration/rpc/backend/test_backend_suite.go b/tests/integration/rpc/backend/test_backend_suite.go index c056d6d6..2badb689 100644 --- a/tests/integration/rpc/backend/test_backend_suite.go +++ b/tests/integration/rpc/backend/test_backend_suite.go @@ -2,6 +2,7 @@ package backend import ( "bufio" + "context" "math/big" "os" "path/filepath" @@ -83,7 +84,8 @@ func (s *TestSuite) SetupTest() { nw := network.New(s.create, s.options...) encodingConfig := nw.GetEncodingConfig() - clientCtx := client.Context{}.WithChainID(ChainID.ChainID). + clientCtx := client.Context{}. + WithChainID(ChainID.ChainID). WithHeight(1). WithTxConfig(encodingConfig.TxConfig). WithCodec(encodingConfig.Codec). @@ -92,22 +94,31 @@ func (s *TestSuite) SetupTest() { WithAccountRetriever(client.TestAccountRetriever{Accounts: accounts}). WithClient(mocks.NewClient(s.T())) - allowUnprotectedTxs := false idxer := indexer.NewKVIndexer(dbm.NewMemDB(), ctx.Logger, clientCtx) - s.backend = rpcbackend.NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, idxer, nil) + mempool := NewEvmMempoolMock(s.T()) + + s.backend = rpcbackend.NewBackend(ctx, clientCtx, idxer, mempool, rpcbackend.WithLogger(ctx.Logger)) s.backend.Cfg.JSONRPC.GasCap = 0 s.backend.Cfg.JSONRPC.EVMTimeout = 0 s.backend.Cfg.JSONRPC.AllowInsecureUnlock = true s.backend.Cfg.EVM.EVMChainID = ChainID.EVMChainID s.backend.QueryClient.QueryClient = mocks.NewEVMQueryClient(s.T()) s.backend.QueryClient.FeeMarket = mocks.NewFeeMarketQueryClient(s.T()) - s.backend.Ctx = rpctypes.ContextWithHeight(1) // Add codec s.backend.ClientCtx.Codec = encodingConfig.Codec } +// Ctx returns a context with height set for testing +func (s *TestSuite) Ctx() context.Context { + return rpctypes.NewContextWithHeight(1) +} + +func (s *TestSuite) Mempool() *mocks.Mempool { + return s.backend.Mempool.(*mocks.Mempool) +} + // buildEthereumTx returns an example legacy Ethereum transaction func (s *TestSuite) buildEthereumTx() (*evmtypes.MsgEthereumTx, []byte) { ethTxParams := evmtypes.EvmTxArgs{ @@ -193,7 +204,7 @@ func (s *TestSuite) buildEthBlock( // 1) Gas limit from consensus params // if failed to query consensus params, default gasLimit is applied. - gasLimit, _ := rpctypes.BlockMaxGasFromConsensusParams(rpctypes.ContextWithHeight(cmtHeader.Height), s.backend.ClientCtx, cmtHeader.Height) + gasLimit, _ := rpctypes.BlockMaxGasFromConsensusParams(rpctypes.NewContextWithHeight(cmtHeader.Height), s.backend.ClientCtx, cmtHeader.Height) // 2) Miner from provided validator miner := common.BytesToAddress(validator.Bytes()) @@ -208,7 +219,7 @@ func (s *TestSuite) buildEthBlock( } // 5) Build receipts - receipts, err := s.backend.ReceiptsFromCometBlock(resBlock, blockRes, msgs) + receipts, err := s.backend.ReceiptsFromCometBlock(s.Ctx(), resBlock, blockRes, msgs) s.Require().NoError(err) // 6) Gas used @@ -222,6 +233,7 @@ func (s *TestSuite) buildEthBlock( s.T().Errorf("negative gas used value: %d", gas) continue } + // #nosec G115 -- gas checked >= 0 above gasUsed += uint64(gas) } ethHeader.GasUsed = gasUsed diff --git a/tests/integration/rpc/backend/test_blocks.go b/tests/integration/rpc/backend/test_blocks.go index e8fb30c5..34e1125f 100644 --- a/tests/integration/rpc/backend/test_blocks.go +++ b/tests/integration/rpc/backend/test_blocks.go @@ -72,7 +72,7 @@ func (s *TestSuite) TestBlockNumber() { s.SetupTest() // reset test and queries tc.registerMock() - blockNumber, err := s.backend.BlockNumber() + blockNumber, err := s.backend.BlockNumber(s.Ctx()) if tc.expPass { s.Require().NoError(err) @@ -217,7 +217,7 @@ func (s *TestSuite) TestGetBlockByNumber() { s.SetupTest() // reset test and queries tc.registerMock(tc.blockNumber, math.NewIntFromBigInt(tc.baseFee), tc.validator, tc.txBz) - block, err := s.backend.GetBlockByNumber(tc.blockNumber, tc.fullTx) + block, err := s.backend.GetBlockByNumber(s.Ctx(), tc.blockNumber, tc.fullTx) if tc.expPass { s.Require().NoError(err) @@ -381,7 +381,7 @@ func (s *TestSuite) TestGetBlockByHash() { s.SetupTest() // reset test and queries tc.registerMock(tc.hash, math.NewIntFromBigInt(tc.baseFee), tc.validator, tc.txBz) - block, err := s.backend.GetBlockByHash(tc.hash, tc.fullTx) + block, err := s.backend.GetBlockByHash(s.Ctx(), tc.hash, tc.fullTx) if tc.expPass { if tc.expNoop { @@ -471,7 +471,7 @@ func (s *TestSuite) TestGetBlockTransactionCountByHash() { s.SetupTest() // reset test and queries tc.registerMock(tc.hash) - count := s.backend.GetBlockTransactionCountByHash(tc.hash) + count := s.backend.GetBlockTransactionCountByHash(s.Ctx(), tc.hash) if tc.expPass { s.Require().Equal(tc.expCount, *count) } else { @@ -547,7 +547,7 @@ func (s *TestSuite) TestGetBlockTransactionCountByNumber() { s.SetupTest() // reset test and queries tc.registerMock(tc.blockNum) - count := s.backend.GetBlockTransactionCountByNumber(tc.blockNum) + count := s.backend.GetBlockTransactionCountByNumber(s.Ctx(), tc.blockNum) if tc.expPass { s.Require().Equal(tc.expCount, *count) } else { @@ -645,7 +645,7 @@ func (s *TestSuite) TestCometBlockByNumber() { s.SetupTest() // reset test and queries tc.registerMock(tc.blockNumber) - resultBlock, err := s.backend.CometBlockByNumber(tc.blockNumber) + resultBlock, err := s.backend.CometBlockByNumber(s.Ctx(), tc.blockNumber) if tc.expPass { s.Require().NoError(err) @@ -701,7 +701,7 @@ func (s *TestSuite) TestCometBlockResultByNumber() { tc.registerMock(tc.blockNumber) client := s.backend.ClientCtx.Client.(*mocks.Client) - blockRes, err := client.BlockResults(s.backend.Ctx, &tc.blockNumber) //#nosec G601 -- fine for tests + blockRes, err := client.BlockResults(s.Ctx(), &tc.blockNumber) //#nosec G601 -- fine for tests if tc.expPass { s.Require().NoError(err) @@ -773,7 +773,7 @@ func (s *TestSuite) TestBlockNumberFromComet() { } tc.registerMock(tc.hash) - blockNum, err := s.backend.BlockNumberFromComet(blockNrOrHash) + blockNum, err := s.backend.BlockNumberFromComet(s.Ctx(), blockNrOrHash) if tc.expPass { s.Require().NoError(err) @@ -836,7 +836,7 @@ func (s *TestSuite) TestBlockNumberFromCometByHash() { s.SetupTest() // reset test and queries tc.registerMock(tc.hash) - blockNum, err := s.backend.BlockNumberFromCometByHash(tc.hash) + blockNum, err := s.backend.BlockNumberFromCometByHash(s.Ctx(), tc.hash) if tc.expPass { expHeight := big.NewInt(resHeader.Header.Height) s.Require().NoError(err) @@ -902,7 +902,7 @@ func (s *TestSuite) TestBlockBloomFromCometBlock() { } for _, tc := range testCases { s.Run(fmt.Sprintf("Case %s", tc.name), func() { - blockBloom, err := s.backend.BlockBloomFromCometBlock(tc.blockRes) + blockBloom, err := s.backend.BlockBloomFromCometBlock(s.Ctx(), tc.blockRes) if tc.expPass { s.Require().NoError(err) @@ -1124,7 +1124,7 @@ func (s *TestSuite) TestGetEthBlockFromComet() { err := s.backend.Indexer.IndexBlock(tc.resBlock.Block, tc.blockRes.TxsResults) s.Require().NoError(err) } - block, err := s.backend.RPCBlockFromCometBlock(tc.resBlock, tc.blockRes, tc.fullTx) + block, err := s.backend.RPCBlockFromCometBlock(s.Ctx(), tc.resBlock, tc.blockRes, tc.fullTx) var tx *evmtypes.MsgEthereumTx if tc.expTxs { @@ -1174,7 +1174,7 @@ func (s *TestSuite) TestEthMsgsFromCometBlock() { TxsResults: []*types.ExecTxResult{ { Code: 1, - Log: ethrpc.ExceedBlockGasLimitError, + Log: evmtypes.ExceedBlockGasLimitError, }, }, }, @@ -1189,7 +1189,7 @@ func (s *TestSuite) TestEthMsgsFromCometBlock() { TxsResults: []*types.ExecTxResult{ { Code: 0, - Log: ethrpc.ExceedBlockGasLimitError, + Log: evmtypes.ExceedBlockGasLimitError, }, }, }, @@ -1200,7 +1200,7 @@ func (s *TestSuite) TestEthMsgsFromCometBlock() { s.Run(fmt.Sprintf("Case %s", tc.name), func() { s.SetupTest() // reset test and queries - msgs := s.backend.EthMsgsFromCometBlock(tc.resBlock, tc.blockRes) + msgs := s.backend.EthMsgsFromCometBlock(s.Ctx(), tc.resBlock, tc.blockRes) for i, expMsg := range tc.expMsgs { expBytes, err := json.Marshal(expMsg) s.Require().Nil(err) @@ -1345,10 +1345,10 @@ func (s *TestSuite) TestHeaderByNumber() { s.SetupTest() // reset test and queries tc.registerMock(tc.blockNumber, math.NewIntFromBigInt(tc.baseFee)) - header, err := s.backend.HeaderByNumber(tc.blockNumber) + header, err := s.backend.HeaderByNumber(s.Ctx(), tc.blockNumber) if tc.expPass { - msgs := s.backend.EthMsgsFromCometBlock(resBlock, blockRes) + msgs := s.backend.EthMsgsFromCometBlock(s.Ctx(), resBlock, blockRes) expHeader := s.buildEthBlock(blockRes, resBlock, msgs, validator, tc.baseFee).Header() s.Require().NoError(err) @@ -1467,10 +1467,10 @@ func (s *TestSuite) TestHeaderByHash() { s.SetupTest() // reset test and queries tc.registerMock(tc.hash, math.NewIntFromBigInt(tc.baseFee)) - header, err := s.backend.HeaderByHash(tc.hash) + header, err := s.backend.HeaderByHash(s.Ctx(), tc.hash) if tc.expPass { - msgs := s.backend.EthMsgsFromCometBlock(resBlock, blockRes) + msgs := s.backend.EthMsgsFromCometBlock(s.Ctx(), resBlock, blockRes) expHeader := s.buildEthBlock(blockRes, resBlock, msgs, validator, tc.baseFee).Header() s.Require().NoError(err) @@ -1567,12 +1567,12 @@ func (s *TestSuite) TestEthBlockByNumber() { s.SetupTest() // reset test and queries tc.registerMock(tc.blockNumber) - ethBlock, err := s.backend.EthBlockByNumber(tc.blockNumber) + ethBlock, err := s.backend.EthBlockByNumber(s.Ctx(), tc.blockNumber) if tc.expPass { s.Require().NoError(err) - msgs := s.backend.EthMsgsFromCometBlock(resBlock, blockRes) + msgs := s.backend.EthMsgsFromCometBlock(s.Ctx(), resBlock, blockRes) txs := make([]*ethtypes.Transaction, len(msgs)) for i, m := range msgs { txs[i] = m.AsTransaction() @@ -1681,12 +1681,12 @@ func (s *TestSuite) TestEthBlockFromCometBlock() { s.Require().NoError(s.backend.Indexer.IndexBlock(tc.resBlock.Block, tc.blockRes.TxsResults)) } - ethBlock, err := s.backend.EthBlockFromCometBlock(tc.resBlock, tc.blockRes) + ethBlock, err := s.backend.EthBlockFromCometBlock(s.Ctx(), tc.resBlock, tc.blockRes) if tc.expPass { s.Require().NoError(err) - msgs := s.backend.EthMsgsFromCometBlock(tc.resBlock, tc.blockRes) + msgs := s.backend.EthMsgsFromCometBlock(s.Ctx(), tc.resBlock, tc.blockRes) txs := make([]*ethtypes.Transaction, len(msgs)) for i, m := range msgs { txs[i] = m.AsTransaction() diff --git a/tests/integration/rpc/backend/test_call_tx.go b/tests/integration/rpc/backend/test_call_tx.go index d52cb412..b346749c 100644 --- a/tests/integration/rpc/backend/test_call_tx.go +++ b/tests/integration/rpc/backend/test_call_tx.go @@ -21,7 +21,6 @@ import ( "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" - errortypes "github.com/cosmos/cosmos-sdk/types/errors" ) func (s *TestSuite) TestResend() { @@ -281,7 +280,7 @@ func (s *TestSuite) TestResend() { s.SetupTest() // reset test and queries tc.registerMock() - hash, err := s.backend.Resend(tc.args, tc.gasPrice, tc.gasLimit) + hash, err := s.backend.Resend(s.Ctx(), tc.args, tc.gasPrice, tc.gasLimit) if tc.expPass { s.Require().Equal(tc.expHash, hash) @@ -293,7 +292,7 @@ func (s *TestSuite) TestResend() { } func (s *TestSuite) TestSendRawTransaction() { - ethTx, bz := s.buildEthereumTx() + ethTx, _ := s.buildEthereumTx() emptyEvmChainIDTx := s.buildEthereumTxWithChainID(nil) invalidChainID := big.NewInt(1) @@ -315,27 +314,18 @@ func (s *TestSuite) TestSendRawTransaction() { expPass bool }{ { - "fail - empty bytes", - func() {}, - func() []byte { return []byte{} }, - common.Hash{}, - "", - false, - }, - { - "fail - no RLP encoded bytes", - func() {}, - func() []byte { return bz }, - common.Hash{}, - "", - false, + name: "fail - empty bytes", + registerMock: func() {}, + rawTx: func() []byte { return []byte{} }, + expHash: common.Hash{}, + expError: "", }, { - "fail - invalid chain-id", - func() { + name: "fail - invalid chain-id", + registerMock: func() { s.backend.AllowUnprotectedTxs = false }, - func() []byte { + rawTx: func() []byte { from, priv := utiltx.NewAddrKey() signer := utiltx.NewSigner(priv) invalidEvmChainIDTx := s.buildEthereumTxWithChainID(invalidChainID) @@ -345,55 +335,47 @@ func (s *TestSuite) TestSendRawTransaction() { bytes, _ := rlp.EncodeToBytes(invalidEvmChainIDTx.AsTransaction()) return bytes }, - common.Hash{}, - fmt.Errorf("incorrect chain-id; expected %d, got %d", constants.ExampleChainID.EVMChainID, invalidChainID).Error(), - false, + expHash: common.Hash{}, + expError: fmt.Errorf("incorrect chain-id; expected %d, got %d", constants.ExampleChainID.EVMChainID, invalidChainID).Error(), }, { - "fail - unprotected tx", - func() { + name: "fail - unprotected tx", + registerMock: func() { s.backend.AllowUnprotectedTxs = false }, - func() []byte { + rawTx: func() []byte { bytes, _ := rlp.EncodeToBytes(emptyEvmChainIDTx.AsTransaction()) return bytes }, - common.Hash{}, - errors.New("only replay-protected (EIP-155) transactions allowed over RPC").Error(), - false, + expHash: common.Hash{}, + expError: errors.New("only replay-protected (EIP-155) transactions allowed over RPC").Error(), }, { - "fail - failed to broadcast transaction", - func() { + name: "fail - queue is full", + registerMock: func() { cosmosTx, _ := ethTx.BuildTx(s.backend.ClientCtx.TxConfig.NewTxBuilder(), evmDenom) - txBytes, _ := s.backend.ClientCtx.TxConfig.TxEncoder()(cosmosTx) - client := s.backend.ClientCtx.Client.(*mocks.Client) s.backend.AllowUnprotectedTxs = true - RegisterBroadcastTxError(client, txBytes) + RegisterMempoolInsert(s.T(), s.Mempool(), cosmosTx, errors.New("queue is full")) }, - func() []byte { + rawTx: func() []byte { bytes, _ := rlp.EncodeToBytes(ethTx.AsTransaction()) return bytes }, - ethTx.Hash(), - errortypes.ErrInvalidRequest.Error(), - false, + expHash: ethTx.Hash(), + expError: "queue is full", }, { - "pass - Gets the correct transaction hash of the eth transaction", - func() { + name: "pass - Gets the correct transaction hash of the eth transaction", + registerMock: func() { cosmosTx, _ := ethTx.BuildTx(s.backend.ClientCtx.TxConfig.NewTxBuilder(), evmDenom) - txBytes, _ := s.backend.ClientCtx.TxConfig.TxEncoder()(cosmosTx) - - client := s.backend.ClientCtx.Client.(*mocks.Client) s.backend.AllowUnprotectedTxs = true - RegisterBroadcastTx(client, txBytes) + + RegisterMempoolInsert(s.T(), s.Mempool(), cosmosTx, nil) }, - func() []byte { return rlpEncodedBz }, - ethTx.Hash(), - "", - true, + rawTx: func() []byte { return rlpEncodedBz }, + expHash: ethTx.Hash(), + expPass: true, }, } @@ -402,13 +384,12 @@ func (s *TestSuite) TestSendRawTransaction() { s.SetupTest() // reset test and queries tc.registerMock() - hash, err := s.backend.SendRawTransaction(tc.rawTx()) + hash, err := s.backend.SendRawTransaction(s.Ctx(), tc.rawTx()) if tc.expPass { s.Require().Equal(tc.expHash, hash) } else { - s.Require().Error(err) - s.Require().Contains(err.Error(), tc.expError) + s.Require().ErrorContains(err, tc.expError) } }) } @@ -553,7 +534,7 @@ func (s *TestSuite) TestDoCall() { s.SetupTest() // reset test and queries tc.registerMock() - msgEthTx, err := s.backend.DoCall(tc.callArgs, tc.blockNum, tc.overrides) + msgEthTx, err := s.backend.DoCall(s.Ctx(), tc.callArgs, tc.blockNum, tc.overrides) if tc.expPass { s.Require().NoError(err) @@ -618,7 +599,7 @@ func (s *TestSuite) TestGasPrice() { s.SetupTest() // reset test and queries tc.registerMock() - gasPrice, err := s.backend.GasPrice() + gasPrice, err := s.backend.GasPrice(s.Ctx()) if tc.expPass { s.Require().Equal(tc.expGas, gasPrice) } else { @@ -627,3 +608,150 @@ func (s *TestSuite) TestGasPrice() { }) } } + +func (s *TestSuite) TestEstimateGas() { + gasPrice := (*hexutil.Big)(big.NewInt(1)) + toAddr := utiltx.GenerateAddress() + evmChainID := (*hexutil.Big)(s.backend.EvmChainID) + callArgs := evmtypes.TransactionArgs{ + From: nil, + To: &toAddr, + Gas: nil, + GasPrice: nil, + MaxFeePerGas: gasPrice, + MaxPriorityFeePerGas: gasPrice, + Value: gasPrice, + Input: nil, + Data: nil, + AccessList: nil, + ChainID: evmChainID, + } + argsBz, err := json.Marshal(callArgs) + s.Require().NoError(err) + + overrides := json.RawMessage(`{ + "` + toAddr.Hex() + `": { + "balance": "0x0" + } + }`) + invalidOverrides := json.RawMessage(`{"invalid": json}`) + emptyOverrides := json.RawMessage(`{}`) + + testCases := []struct { + name string + registerMock func() + callArgs evmtypes.TransactionArgs + overrides *json.RawMessage + expGas hexutil.Uint64 + expPass bool + }{ + { + "fail - Invalid request", + func() { + _, bz := s.buildEthereumTx() + client := s.backend.ClientCtx.Client.(*mocks.Client) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + height := int64(1) + RegisterHeader(client, &height, bz) + RegisterEstimateGasError(QueryClient, &evmtypes.EthCallRequest{Args: argsBz, ChainId: s.backend.EvmChainID.Int64()}) + }, + callArgs, + nil, + 0, + false, + }, + { + "pass - Returned gas estimate", + func() { + _, bz := s.buildEthereumTx() + client := s.backend.ClientCtx.Client.(*mocks.Client) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + height := int64(1) + RegisterHeader(client, &height, bz) + RegisterEstimateGas(QueryClient, callArgs) + }, + callArgs, + nil, + 21000, + true, + }, + { + "pass - With state overrides", + func() { + _, bz := s.buildEthereumTx() + client := s.backend.ClientCtx.Client.(*mocks.Client) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + height := int64(1) + RegisterHeader(client, &height, bz) + expected := &evmtypes.EthCallRequest{ + Args: argsBz, + ChainId: s.backend.EvmChainID.Int64(), + Overrides: overrides, + } + RegisterEstimateGasWithOverrides(QueryClient, expected) + }, + callArgs, + &overrides, + 21000, + true, + }, + { + "fail - Invalid state overrides JSON", + func() { + _, bz := s.buildEthereumTx() + client := s.backend.ClientCtx.Client.(*mocks.Client) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + height := int64(1) + RegisterHeader(client, &height, bz) + expected := &evmtypes.EthCallRequest{ + Args: argsBz, + ChainId: s.backend.EvmChainID.Int64(), + Overrides: invalidOverrides, + } + RegisterEstimateGasError(QueryClient, expected) + }, + callArgs, + &invalidOverrides, + 0, + false, + }, + { + "pass - Empty state overrides", + func() { + _, bz := s.buildEthereumTx() + client := s.backend.ClientCtx.Client.(*mocks.Client) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + height := int64(1) + RegisterHeader(client, &height, bz) + expected := &evmtypes.EthCallRequest{ + Args: argsBz, + ChainId: s.backend.EvmChainID.Int64(), + Overrides: emptyOverrides, + } + RegisterEstimateGasWithOverrides(QueryClient, expected) + }, + callArgs, + &emptyOverrides, + 21000, + true, + }, + } + + for _, tc := range testCases { + s.Run(fmt.Sprintf("case %s", tc.name), func() { + s.SetupTest() // reset test and queries + tc.registerMock() + + blockNum := rpctypes.BlockNumber(1) + blockNrOrHash := rpctypes.BlockNumberOrHash{BlockNumber: &blockNum} + gas, err := s.backend.EstimateGas(s.Ctx(), tc.callArgs, &blockNrOrHash, tc.overrides) + + if tc.expPass { + s.Require().NoError(err) + s.Require().Equal(tc.expGas, gas) + } else { + s.Require().Error(err) + } + }) + } +} diff --git a/tests/integration/rpc/backend/test_chain_info.go b/tests/integration/rpc/backend/test_chain_info.go index 631aedd4..05d3028b 100644 --- a/tests/integration/rpc/backend/test_chain_info.go +++ b/tests/integration/rpc/backend/test_chain_info.go @@ -1,6 +1,7 @@ package backend import ( + "context" "fmt" "math/big" @@ -143,7 +144,7 @@ func (s *TestSuite) TestBaseFee() { s.SetupTest() // reset test and queries tc.registerMock() - baseFee, err := s.backend.BaseFee(tc.blockRes) + baseFee, err := s.backend.BaseFee(s.Ctx(), tc.blockRes) if tc.expPass { s.Require().NoError(err) @@ -180,7 +181,7 @@ func (s *TestSuite) TestChainID() { s.SetupTest() // reset test and queries tc.registerMock() - chainID, err := s.backend.ChainID() + chainID, err := s.backend.ChainID(s.Ctx()) if tc.expPass { s.Require().NoError(err) s.Require().Equal(tc.expChainID, chainID) @@ -237,7 +238,7 @@ func (s *TestSuite) TestGetCoinbase() { s.SetupTest() // reset test and queries tc.registerMock() - accAddr, err := s.backend.GetCoinbase() + accAddr, err := s.backend.GetCoinbase(s.Ctx()) if tc.expPass { s.Require().Equal(tc.accAddr, accAddr) @@ -277,7 +278,7 @@ func (s *TestSuite) TestSuggestGasTipCap() { s.SetupTest() // reset test and queries tc.registerMock() - maxDelta, err := s.backend.SuggestGasTipCap(tc.baseFee) + maxDelta, err := s.backend.SuggestGasTipCap(s.Ctx(), tc.baseFee) if tc.expPass { s.Require().Equal(tc.expGasTipCap, maxDelta) @@ -311,7 +312,7 @@ func (s *TestSuite) TestGlobalMinGasPrice() { s.SetupTest() // reset test and queries tc.registerMock() - globalMinGasPrice, err := s.backend.GlobalMinGasPrice() + globalMinGasPrice, err := s.backend.GlobalMinGasPrice(s.Ctx()) if tc.expPass { s.Require().Equal(tc.expMinGasPrice, globalMinGasPrice) @@ -577,13 +578,14 @@ func (s *TestSuite) TestFeeHistory() { called := 0 if len(tc.targetNewBaseFees) > 0 { s.backend.ProcessBlocker = func( + ctx context.Context, cometBlock *cmtrpctypes.ResultBlock, ethBlock *map[string]interface{}, rewardPercentiles []float64, cometBlockResult *cmtrpctypes.ResultBlockResults, targetOneFeeHistory *rpc.OneFeeHistory, ) error { - err := s.backend.ProcessBlock(cometBlock, ethBlock, rewardPercentiles, cometBlockResult, targetOneFeeHistory) + err := s.backend.ProcessBlock(ctx, cometBlock, ethBlock, rewardPercentiles, cometBlockResult, targetOneFeeHistory) s.Require().NoError(err) targetOneFeeHistory.NextBaseFee = tc.targetNewBaseFees[called] called++ @@ -591,7 +593,7 @@ func (s *TestSuite) TestFeeHistory() { } } - feeHistory, err := s.backend.FeeHistory(tc.userBlockCount, tc.latestBlock, []float64{25, 50, 75, 100}) + feeHistory, err := s.backend.FeeHistory(s.Ctx(), tc.userBlockCount, tc.latestBlock, []float64{25, 50, 75, 100}) if tc.expPass { s.Require().NoError(err) s.Require().Equal(feeHistory, tc.expFeeHistory) diff --git a/tests/integration/rpc/backend/test_client.go b/tests/integration/rpc/backend/test_client.go index f9af73be..c2f1ed8c 100644 --- a/tests/integration/rpc/backend/test_client.go +++ b/tests/integration/rpc/backend/test_client.go @@ -40,60 +40,60 @@ var _ cmtrpcclient.Client = &mocks.Client{} func RegisterTxSearch(client *mocks.Client, query string, txBz []byte) { resulTxs := []*cmtrpctypes.ResultTx{{Tx: txBz}} - client.On("TxSearch", rpc.ContextWithHeight(1), query, false, (*int)(nil), (*int)(nil), ""). + client.EXPECT().TxSearch(mock.Anything, query, false, (*int)(nil), (*int)(nil), ""). Return(&cmtrpctypes.ResultTxSearch{Txs: resulTxs, TotalCount: 1}, nil) } func RegisterTxSearchEmpty(client *mocks.Client, query string) { - client.On("TxSearch", rpc.ContextWithHeight(1), query, false, (*int)(nil), (*int)(nil), ""). + client.EXPECT().TxSearch(mock.Anything, query, false, (*int)(nil), (*int)(nil), ""). Return(&cmtrpctypes.ResultTxSearch{}, nil) } func RegisterTxSearchError(client *mocks.Client, query string) { - client.On("TxSearch", rpc.ContextWithHeight(1), query, false, (*int)(nil), (*int)(nil), ""). + client.EXPECT().TxSearch(mock.Anything, query, false, (*int)(nil), (*int)(nil), ""). Return(nil, errortypes.ErrInvalidRequest) } // Broadcast Tx func RegisterBroadcastTx(client *mocks.Client, tx types.Tx) { - client.On("BroadcastTxSync", context.Background(), tx). + client.EXPECT().BroadcastTxSync(mock.Anything, tx). Return(&cmtrpctypes.ResultBroadcastTx{}, nil) } func RegisterBroadcastTxError(client *mocks.Client, tx types.Tx) { - client.On("BroadcastTxSync", context.Background(), tx). + client.EXPECT().BroadcastTxSync(mock.Anything, tx). Return(nil, errortypes.ErrInvalidRequest) } // Unconfirmed Transactions func RegisterUnconfirmedTxs(client *mocks.Client, limit *int, txs []types.Tx) { - client.On("UnconfirmedTxs", rpc.ContextWithHeight(1), limit). + client.EXPECT().UnconfirmedTxs(mock.Anything, limit). Return(&cmtrpctypes.ResultUnconfirmedTxs{Txs: txs}, nil) } func RegisterUnconfirmedTxsEmpty(client *mocks.Client, limit *int) { - client.On("UnconfirmedTxs", rpc.ContextWithHeight(1), limit). + client.EXPECT().UnconfirmedTxs(mock.Anything, limit). Return(&cmtrpctypes.ResultUnconfirmedTxs{ Txs: make([]types.Tx, 2), }, nil) } func RegisterUnconfirmedTxsError(client *mocks.Client, limit *int) { - client.On("UnconfirmedTxs", rpc.ContextWithHeight(1), limit). + client.EXPECT().UnconfirmedTxs(mock.Anything, limit). Return(nil, errortypes.ErrInvalidRequest) } // Status func RegisterStatus(client *mocks.Client) { - client.On("Status", rpc.ContextWithHeight(1)). + client.EXPECT().Status(mock.Anything). Return(&cmtrpctypes.ResultStatus{}, nil) } func RegisterStatusError(client *mocks.Client) { - client.On("Status", rpc.ContextWithHeight(1)). + client.EXPECT().Status(mock.Anything). Return(nil, errortypes.ErrInvalidRequest) } @@ -107,7 +107,7 @@ func RegisterBlockMultipleTxs( block := types.MakeBlock(height, txs, nil, nil) block.ChainID = ChainID.ChainID resBlock := &cmtrpctypes.ResultBlock{Block: block} - client.On("Block", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).Return(resBlock, nil) + client.EXPECT().Block(mock.Anything, mock.AnythingOfType("*int64")).Return(resBlock, nil) return resBlock } @@ -121,7 +121,7 @@ func RegisterBlock( emptyBlock := types.MakeBlock(height, []types.Tx{}, nil, nil) emptyBlock.ChainID = ChainID.ChainID resBlock := &cmtrpctypes.ResultBlock{Block: emptyBlock} - client.On("Block", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).Return(resBlock, nil) + client.EXPECT().Block(mock.Anything, mock.AnythingOfType("*int64")).Return(resBlock, nil) return resBlock } @@ -129,14 +129,14 @@ func RegisterBlock( block := types.MakeBlock(height, []types.Tx{tx}, nil, nil) block.ChainID = ChainID.ChainID resBlock := &cmtrpctypes.ResultBlock{Block: block} - client.On("Block", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).Return(resBlock, nil) + client.EXPECT().Block(mock.Anything, mock.AnythingOfType("*int64")).Return(resBlock, nil) return resBlock } // Block returns error func RegisterBlockError(client *mocks.Client, height int64) { - client.On("Block", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")). + client.EXPECT().Block(mock.Anything, mock.AnythingOfType("*int64")). Return(nil, errortypes.ErrInvalidRequest) } @@ -146,7 +146,7 @@ func RegisterBlockNotFound( client *mocks.Client, height int64, ) *cmtrpctypes.ResultBlock { - client.On("Block", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")). + client.EXPECT().Block(mock.Anything, mock.AnythingOfType("*int64")). Return(&cmtrpctypes.ResultBlock{Block: nil}, nil) return &cmtrpctypes.ResultBlock{Block: nil} @@ -155,10 +155,10 @@ func RegisterBlockNotFound( // Block panic func RegisterBlockPanic(client *mocks.Client, height int64) { - client.On("Block", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")). - Return(func(context.Context, *int64) *cmtrpctypes.ResultBlock { + client.EXPECT().Block(mock.Anything, mock.AnythingOfType("*int64")). + RunAndReturn(func(context.Context, *int64) (*cmtrpctypes.ResultBlock, error) { panic("Block call panic") - }, nil) + }) } func TestRegisterBlock(t *testing.T) { @@ -166,7 +166,7 @@ func TestRegisterBlock(t *testing.T) { height := rpc.BlockNumber(1).Int64() RegisterBlock(client, height, nil) - res, err := client.Block(rpc.ContextWithHeight(height), &height) + res, err := client.Block(rpc.NewContextWithHeight(height), &height) emptyBlock := types.MakeBlock(height, []types.Tx{}, nil, nil) emptyBlock.ChainID = ChainID.ChainID @@ -179,12 +179,12 @@ func TestRegisterBlock(t *testing.T) { func RegisterConsensusParams(client *mocks.Client, height int64) { consensusParams := types.DefaultConsensusParams() - client.On("ConsensusParams", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")). + client.EXPECT().ConsensusParams(mock.Anything, mock.AnythingOfType("*int64")). Return(&cmtrpctypes.ResultConsensusParams{ConsensusParams: *consensusParams}, nil) } func RegisterConsensusParamsError(client *mocks.Client, height int64) { - client.On("ConsensusParams", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")). + client.EXPECT().ConsensusParams(mock.Anything, mock.AnythingOfType("*int64")). Return(nil, errortypes.ErrInvalidRequest) } @@ -193,7 +193,7 @@ func TestRegisterConsensusParams(t *testing.T) { height := int64(1) RegisterConsensusParams(client, height) - res, err := client.ConsensusParams(rpc.ContextWithHeight(height), &height) + res, err := client.ConsensusParams(rpc.NewContextWithHeight(height), &height) consensusParams := types.DefaultConsensusParams() require.Equal(t, &cmtrpctypes.ResultConsensusParams{ConsensusParams: *consensusParams}, res) require.NoError(t, err) @@ -219,7 +219,7 @@ func RegisterBlockResultsWithEventLog(client *mocks.Client, height int64) (*cmtr {Code: 0, GasUsed: 0, Data: data}, }, } - client.On("BlockResults", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")). + client.EXPECT().BlockResults(mock.Anything, mock.AnythingOfType("*int64")). Return(res, nil) return res, nil } @@ -240,13 +240,13 @@ func RegisterBlockResultsWithTxs( Height: height, TxsResults: txsResults, } - client.On("BlockResults", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")). + client.EXPECT().BlockResults(mock.Anything, mock.AnythingOfType("*int64")). Return(res, nil) return res } func RegisterBlockResultsError(client *mocks.Client, height int64) { - client.On("BlockResults", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")). + client.EXPECT().BlockResults(mock.Anything, mock.AnythingOfType("*int64")). Return(nil, errortypes.ErrInvalidRequest) } @@ -255,7 +255,7 @@ func TestRegisterBlockResults(t *testing.T) { height := int64(1) RegisterBlockResults(client, height) - res, err := client.BlockResults(rpc.ContextWithHeight(height), &height) + res, err := client.BlockResults(rpc.NewContextWithHeight(height), &height) expRes := &cmtrpctypes.ResultBlockResults{ Height: height, TxsResults: []*abci.ExecTxResult{{Code: 0, GasUsed: 0}}, @@ -274,18 +274,18 @@ func RegisterBlockByHash( block := types.MakeBlock(1, []types.Tx{tx}, nil, nil) resBlock := &cmtrpctypes.ResultBlock{Block: block} - client.On("BlockByHash", rpc.ContextWithHeight(1), []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}). + client.EXPECT().BlockByHash(mock.Anything, []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}). Return(resBlock, nil) return resBlock } func RegisterBlockByHashError(client *mocks.Client, _ common.Hash, _ []byte) { - client.On("BlockByHash", rpc.ContextWithHeight(1), []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}). + client.EXPECT().BlockByHash(mock.Anything, []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}). Return(nil, errortypes.ErrInvalidRequest) } func RegisterBlockByHashNotFound(client *mocks.Client, _ common.Hash, _ []byte) { - client.On("BlockByHash", rpc.ContextWithHeight(1), []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}). + client.EXPECT().BlockByHash(mock.Anything, []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}). Return(nil, nil) } @@ -304,18 +304,18 @@ func RegisterHeaderByHash( Header: header, } - client.On("HeaderByHash", rpc.ContextWithHeight(1), bytes.HexBytes{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}). + client.EXPECT().HeaderByHash(mock.Anything, bytes.HexBytes{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}). Return(resHeader, nil) return resHeader } func RegisterHeaderByHashError(client *mocks.Client, _ common.Hash, _ []byte) { - client.On("HeaderByHash", rpc.ContextWithHeight(1), bytes.HexBytes{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}). + client.EXPECT().HeaderByHash(mock.Anything, bytes.HexBytes{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}). Return(nil, errortypes.ErrInvalidRequest) } func RegisterHeaderByHashNotFound(client *mocks.Client, hash common.Hash, tx []byte) { - client.On("HeaderByHash", rpc.ContextWithHeight(1), bytes.HexBytes(hash.Bytes())). + client.EXPECT().HeaderByHash(mock.Anything, bytes.HexBytes(hash.Bytes())). Return(&coretypes.ResultHeader{Header: nil}, nil) } @@ -324,24 +324,24 @@ func RegisterHeaderByHashNotFound(client *mocks.Client, hash common.Hash, tx []b func RegisterHeader(client *mocks.Client, height *int64, tx []byte) *coretypes.ResultHeader { block := types.MakeBlock(*height, []types.Tx{tx}, nil, nil) resHeader := &coretypes.ResultHeader{Header: &block.Header} - client.On("Header", rpc.ContextWithHeight(*height), mock.AnythingOfType("*int64")).Return(resHeader, nil) + client.EXPECT().Header(mock.Anything, mock.AnythingOfType("*int64")).Return(resHeader, nil) return resHeader } func RegisterHeaderError(client *mocks.Client, height *int64) { - client.On("Header", rpc.ContextWithHeight(*height), height).Return(nil, errortypes.ErrInvalidRequest) + client.EXPECT().Header(mock.Anything, height).Return(nil, errortypes.ErrInvalidRequest) } // Header not found func RegisterHeaderNotFound(client *mocks.Client, height int64) { - client.On("Header", rpc.ContextWithHeight(height), mock.MatchedBy(func(arg *int64) bool { + client.EXPECT().Header(mock.Anything, mock.MatchedBy(func(arg *int64) bool { return arg != nil && height == *arg })).Return(&coretypes.ResultHeader{Header: nil}, nil) } func RegisterABCIQueryWithOptions(client *mocks.Client, height int64, path string, data bytes.HexBytes, opts cmtrpcclient.ABCIQueryOptions) { - client.On("ABCIQueryWithOptions", context.Background(), path, data, opts). + client.EXPECT().ABCIQueryWithOptions(mock.Anything, path, data, opts). Return(&cmtrpctypes.ResultABCIQuery{ Response: abci.ResponseQuery{ Value: []byte{2}, // TODO replace with data.Bytes(), @@ -351,7 +351,7 @@ func RegisterABCIQueryWithOptions(client *mocks.Client, height int64, path strin } func RegisterABCIQueryWithOptionsError(clients *mocks.Client, path string, data bytes.HexBytes, opts cmtrpcclient.ABCIQueryOptions) { - clients.On("ABCIQueryWithOptions", context.Background(), path, data, opts). + clients.EXPECT().ABCIQueryWithOptions(mock.Anything, path, data, opts). Return(nil, errortypes.ErrInvalidRequest) } @@ -360,7 +360,7 @@ func RegisterABCIQueryAccount(clients *mocks.Client, data bytes.HexBytes, opts c accAny, _ := codectypes.NewAnyWithValue(baseAccount) accResponse := authtypes.QueryAccountResponse{Account: accAny} respBz, _ := accResponse.Marshal() - clients.On("ABCIQueryWithOptions", context.Background(), "/cosmos.auth.v1beta1.Query/Account", data, opts). + clients.EXPECT().ABCIQueryWithOptions(mock.Anything, "/cosmos.auth.v1beta1.Query/Account", data, opts). Return(&cmtrpctypes.ResultABCIQuery{ Response: abci.ResponseQuery{ Value: respBz, diff --git a/tests/integration/rpc/backend/test_evm_query_client.go b/tests/integration/rpc/backend/test_evm_query_client.go index efcacaf6..7225c2e7 100644 --- a/tests/integration/rpc/backend/test_evm_query_client.go +++ b/tests/integration/rpc/backend/test_evm_query_client.go @@ -55,103 +55,115 @@ var _ evmtypes.QueryClient = &mocks.EVMQueryClient{} // TraceTransaction func RegisterTraceTransactionWithPredecessors(queryClient *mocks.EVMQueryClient, msgEthTx *evmtypes.MsgEthereumTx, predecessors []*evmtypes.MsgEthereumTx) { data := []byte{0x7b, 0x22, 0x74, 0x65, 0x73, 0x74, 0x22, 0x3a, 0x20, 0x22, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x22, 0x7d} - queryClient.On("TraceTx", rpc.ContextWithHeight(1), + queryClient.EXPECT().TraceTx(mock.Anything, MatchByProto(&evmtypes.QueryTraceTxRequest{Msg: msgEthTx, BlockNumber: 1, Predecessors: predecessors, ChainId: int64(constants.ExampleChainID.EVMChainID), BlockMaxGas: -1})). //nolint:gosec // G115 Return(&evmtypes.QueryTraceTxResponse{Data: data}, nil) } func RegisterTraceTransaction(queryClient *mocks.EVMQueryClient, msgEthTx *evmtypes.MsgEthereumTx) { data := []byte{0x7b, 0x22, 0x74, 0x65, 0x73, 0x74, 0x22, 0x3a, 0x20, 0x22, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x22, 0x7d} - queryClient.On("TraceTx", rpc.ContextWithHeight(1), MatchByProto(&evmtypes.QueryTraceTxRequest{Msg: msgEthTx, BlockNumber: 1, ChainId: int64(constants.ExampleChainID.EVMChainID), BlockMaxGas: -1})). //nolint:gosec // G115 - Return(&evmtypes.QueryTraceTxResponse{Data: data}, nil) + queryClient.EXPECT().TraceTx(mock.Anything, MatchByProto(&evmtypes.QueryTraceTxRequest{Msg: msgEthTx, BlockNumber: 1, ChainId: int64(constants.ExampleChainID.EVMChainID), BlockMaxGas: -1})). //nolint:gosec // G115 + Return(&evmtypes.QueryTraceTxResponse{Data: data}, nil) } func RegisterTraceTransactionError(queryClient *mocks.EVMQueryClient, msgEthTx *evmtypes.MsgEthereumTx) { - queryClient.On("TraceTx", rpc.ContextWithHeight(1), MatchByProto(&evmtypes.QueryTraceTxRequest{Msg: msgEthTx, BlockNumber: 1, ChainId: int64(constants.ExampleChainID.EVMChainID)})). //nolint:gosec // G115 - Return(nil, errortypes.ErrInvalidRequest) + queryClient.EXPECT().TraceTx(mock.Anything, MatchByProto(&evmtypes.QueryTraceTxRequest{Msg: msgEthTx, BlockNumber: 1, ChainId: int64(constants.ExampleChainID.EVMChainID)})). //nolint:gosec // G115 + Return(nil, errortypes.ErrInvalidRequest) } // TraceBlock func RegisterTraceBlock(queryClient *mocks.EVMQueryClient, txs []*evmtypes.MsgEthereumTx) { data := []byte{0x7b, 0x22, 0x74, 0x65, 0x73, 0x74, 0x22, 0x3a, 0x20, 0x22, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x22, 0x7d} - queryClient.On("TraceBlock", rpc.ContextWithHeight(1), + queryClient.EXPECT().TraceBlock(mock.Anything, MatchByProto(&evmtypes.QueryTraceBlockRequest{Txs: txs, BlockNumber: 1, TraceConfig: &evmtypes.TraceConfig{}, ChainId: int64(constants.ExampleChainID.EVMChainID), BlockMaxGas: -1})). //nolint:gosec // G115 Return(&evmtypes.QueryTraceBlockResponse{Data: data}, nil) } func RegisterTraceBlockError(queryClient *mocks.EVMQueryClient) { - queryClient.On("TraceBlock", rpc.ContextWithHeight(1), &evmtypes.QueryTraceBlockRequest{}). + queryClient.EXPECT().TraceBlock(mock.Anything, &evmtypes.QueryTraceBlockRequest{}). Return(nil, errortypes.ErrInvalidRequest) } // TraceCall func RegisterTraceCall(queryClient *mocks.EVMQueryClient, msgEthTx *evmtypes.MsgEthereumTx) { data := []byte{0x7b, 0x22, 0x74, 0x65, 0x73, 0x74, 0x22, 0x3a, 0x20, 0x22, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x22, 0x7d} // {"test": "trace_call"} - queryClient.On("TraceCall", rpc.ContextWithHeight(1), mock.AnythingOfType("*types.QueryTraceCallRequest")). + queryClient.EXPECT().TraceCall(mock.Anything, mock.AnythingOfType("*types.QueryTraceCallRequest")). Return(&evmtypes.QueryTraceCallResponse{Data: data}, nil) } func RegisterTraceCallWithTracer(queryClient *mocks.EVMQueryClient, msgEthTx *evmtypes.MsgEthereumTx, tracer string) { data := []byte{0x7b, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x20, 0x22, 0x43, 0x41, 0x4c, 0x4c, 0x22, 0x7d} // {"type": "CALL"} - queryClient.On("TraceCall", rpc.ContextWithHeight(1), mock.MatchedBy(func(req *evmtypes.QueryTraceCallRequest) bool { + queryClient.EXPECT().TraceCall(mock.Anything, mock.MatchedBy(func(req *evmtypes.QueryTraceCallRequest) bool { return req.TraceConfig != nil && req.TraceConfig.Tracer == tracer })).Return(&evmtypes.QueryTraceCallResponse{Data: data}, nil) } func RegisterTraceCallError(queryClient *mocks.EVMQueryClient) { - queryClient.On("TraceCall", rpc.ContextWithHeight(1), mock.AnythingOfType("*types.QueryTraceCallRequest")). + queryClient.EXPECT().TraceCall(mock.Anything, mock.AnythingOfType("*types.QueryTraceCallRequest")). Return(nil, errortypes.ErrInvalidRequest) } // Params func RegisterParams(queryClient *mocks.EVMQueryClient, header *metadata.MD, height int64) { - queryClient.On("Params", rpc.ContextWithHeight(height), &evmtypes.QueryParamsRequest{}, grpc.Header(header)). + queryClient.EXPECT().Params(mock.Anything, &evmtypes.QueryParamsRequest{}, grpc.Header(header)). Return(&evmtypes.QueryParamsResponse{}, nil). - Run(func(args mock.Arguments) { + Run(func(_ context.Context, _ *evmtypes.QueryParamsRequest, opts ...grpc.CallOption) { // If Params call is successful, also update the header height - arg := args.Get(2).(grpc.HeaderCallOption) - h := metadata.MD{} - h.Set(grpctypes.GRPCBlockHeightHeader, fmt.Sprint(height)) - *arg.HeaderAddr = h + for _, opt := range opts { + if h, ok := opt.(grpc.HeaderCallOption); ok { + md := metadata.MD{} + md.Set(grpctypes.GRPCBlockHeightHeader, fmt.Sprint(height)) + *h.HeaderAddr = md + break + } + } }) } func RegisterParamsWithoutHeader(queryClient *mocks.EVMQueryClient, height int64) { - queryClient.On("Params", rpc.ContextWithHeight(height), &evmtypes.QueryParamsRequest{}). + queryClient.EXPECT().Params(mock.Anything, &evmtypes.QueryParamsRequest{}). Return(&evmtypes.QueryParamsResponse{Params: evmtypes.DefaultParams()}, nil) } func RegisterParamsInvalidHeader(queryClient *mocks.EVMQueryClient, header *metadata.MD, height int64) { - queryClient.On("Params", rpc.ContextWithHeight(height), &evmtypes.QueryParamsRequest{}, grpc.Header(header)). + queryClient.EXPECT().Params(mock.Anything, &evmtypes.QueryParamsRequest{}, grpc.Header(header)). Return(&evmtypes.QueryParamsResponse{}, nil). - Run(func(args mock.Arguments) { + Run(func(_ context.Context, _ *evmtypes.QueryParamsRequest, opts ...grpc.CallOption) { // If Params call is successful, also update the header height - arg := args.Get(2).(grpc.HeaderCallOption) - h := metadata.MD{} - *arg.HeaderAddr = h + for _, opt := range opts { + if h, ok := opt.(grpc.HeaderCallOption); ok { + md := metadata.MD{} + *h.HeaderAddr = md + break + } + } }) } func RegisterParamsInvalidHeight(queryClient *mocks.EVMQueryClient, header *metadata.MD, height int64) { - queryClient.On("Params", rpc.ContextWithHeight(height), &evmtypes.QueryParamsRequest{}, grpc.Header(header)). + queryClient.EXPECT().Params(mock.Anything, &evmtypes.QueryParamsRequest{}, grpc.Header(header)). Return(&evmtypes.QueryParamsResponse{}, nil). - Run(func(args mock.Arguments) { + Run(func(_ context.Context, _ *evmtypes.QueryParamsRequest, opts ...grpc.CallOption) { // If Params call is successful, also update the header height - arg := args.Get(2).(grpc.HeaderCallOption) - h := metadata.MD{} - h.Set(grpctypes.GRPCBlockHeightHeader, "invalid") - *arg.HeaderAddr = h + for _, opt := range opts { + if h, ok := opt.(grpc.HeaderCallOption); ok { + md := metadata.MD{} + md.Set(grpctypes.GRPCBlockHeightHeader, "invalid") + *h.HeaderAddr = md + break + } + } }) } func RegisterParamsWithoutHeaderError(queryClient *mocks.EVMQueryClient, height int64) { - queryClient.On("Params", rpc.ContextWithHeight(height), &evmtypes.QueryParamsRequest{}). + queryClient.EXPECT().Params(mock.Anything, &evmtypes.QueryParamsRequest{}). Return(nil, errortypes.ErrInvalidRequest) } // Params returns error func RegisterParamsError(queryClient *mocks.EVMQueryClient, header *metadata.MD, height int64) { - queryClient.On("Params", rpc.ContextWithHeight(height), &evmtypes.QueryParamsRequest{}, grpc.Header(header)). + queryClient.EXPECT().Params(mock.Anything, &evmtypes.QueryParamsRequest{}, grpc.Header(header)). Return(nil, errortypes.ErrInvalidRequest) } @@ -162,7 +174,7 @@ func TestRegisterParams(t *testing.T) { height := int64(1) RegisterParams(queryClient, &header, height) - _, err := queryClient.Params(rpc.ContextWithHeight(height), &evmtypes.QueryParamsRequest{}, grpc.Header(&header)) + _, err := queryClient.Params(rpc.NewContextWithHeight(height), &evmtypes.QueryParamsRequest{}, grpc.Header(&header)) require.NoError(t, err) blockHeightHeader := header.Get(grpctypes.GRPCBlockHeightHeader) headerHeight, err := strconv.ParseInt(blockHeightHeader[0], 10, 64) @@ -173,45 +185,53 @@ func TestRegisterParams(t *testing.T) { func TestRegisterParamsError(t *testing.T) { queryClient := mocks.NewEVMQueryClient(t) RegisterBaseFeeError(queryClient) - _, err := queryClient.BaseFee(rpc.ContextWithHeight(1), &evmtypes.QueryBaseFeeRequest{}) + _, err := queryClient.BaseFee(rpc.NewContextWithHeight(1), &evmtypes.QueryBaseFeeRequest{}) require.Error(t, err) } // ETH Call func RegisterEthCall(queryClient *mocks.EVMQueryClient, request *evmtypes.EthCallRequest) { - ctx, _ := context.WithCancel(rpc.ContextWithHeight(1)) //nolint - queryClient.On("EthCall", ctx, request). + queryClient.EXPECT().EthCall(mock.Anything, request). Return(&evmtypes.MsgEthereumTxResponse{}, nil) } func RegisterEthCallError(queryClient *mocks.EVMQueryClient, request *evmtypes.EthCallRequest) { - ctx, _ := context.WithCancel(rpc.ContextWithHeight(1)) //nolint - queryClient.On("EthCall", ctx, request). + queryClient.EXPECT().EthCall(mock.Anything, request). Return(nil, errortypes.ErrInvalidRequest) } // Estimate Gas func RegisterEstimateGas(queryClient *mocks.EVMQueryClient, args evmtypes.TransactionArgs) { bz, _ := json.Marshal(args) - queryClient.On("EstimateGas", rpc.ContextWithHeight(1), &evmtypes.EthCallRequest{Args: bz, ChainId: args.ChainID.ToInt().Int64()}). - Return(&evmtypes.EstimateGasResponse{}, nil) + queryClient.EXPECT().EstimateGas(mock.Anything, &evmtypes.EthCallRequest{Args: bz, ChainId: args.ChainID.ToInt().Int64()}). + Return(&evmtypes.EstimateGasResponse{Gas: 21000}, nil) +} + +func RegisterEstimateGasError(queryClient *mocks.EVMQueryClient, req *evmtypes.EthCallRequest) { + queryClient.EXPECT().EstimateGas(mock.Anything, req). + Return(nil, errortypes.ErrInvalidRequest) +} + +func RegisterEstimateGasWithOverrides(queryClient *mocks.EVMQueryClient, req *evmtypes.EthCallRequest) { + queryClient.EXPECT().EstimateGas(mock.Anything, req). + Return(&evmtypes.EstimateGasResponse{Gas: 21000}, nil) } // BaseFee func RegisterBaseFee(queryClient *mocks.EVMQueryClient, baseFee math.Int) { - queryClient.On("BaseFee", rpc.ContextWithHeight(1), &evmtypes.QueryBaseFeeRequest{}). + queryClient.EXPECT().BaseFee(mock.Anything, &evmtypes.QueryBaseFeeRequest{}). Return(&evmtypes.QueryBaseFeeResponse{BaseFee: &baseFee}, nil) } // Base fee returns error func RegisterBaseFeeError(queryClient *mocks.EVMQueryClient) { - queryClient.On("BaseFee", rpc.ContextWithHeight(1), &evmtypes.QueryBaseFeeRequest{}). + queryClient.EXPECT().BaseFee(mock.Anything, &evmtypes.QueryBaseFeeRequest{}). Return(&evmtypes.QueryBaseFeeResponse{}, evmtypes.ErrInvalidBaseFee) } // Base fee not enabled func RegisterBaseFeeDisabled(queryClient *mocks.EVMQueryClient) { - queryClient.On("BaseFee", rpc.ContextWithHeight(1), &evmtypes.QueryBaseFeeRequest{}). + queryClient.EXPECT().BaseFee(mock.Anything, &evmtypes.QueryBaseFeeRequest{}). Return(&evmtypes.QueryBaseFeeResponse{}, nil) } @@ -219,7 +239,7 @@ func TestRegisterBaseFee(t *testing.T) { baseFee := math.NewInt(1) queryClient := mocks.NewEVMQueryClient(t) RegisterBaseFee(queryClient, baseFee) - res, err := queryClient.BaseFee(rpc.ContextWithHeight(1), &evmtypes.QueryBaseFeeRequest{}) + res, err := queryClient.BaseFee(rpc.NewContextWithHeight(1), &evmtypes.QueryBaseFeeRequest{}) require.Equal(t, &evmtypes.QueryBaseFeeResponse{BaseFee: &baseFee}, res) require.NoError(t, err) } @@ -227,7 +247,7 @@ func TestRegisterBaseFee(t *testing.T) { func TestRegisterBaseFeeError(t *testing.T) { queryClient := mocks.NewEVMQueryClient(t) RegisterBaseFeeError(queryClient) - res, err := queryClient.BaseFee(rpc.ContextWithHeight(1), &evmtypes.QueryBaseFeeRequest{}) + res, err := queryClient.BaseFee(rpc.NewContextWithHeight(1), &evmtypes.QueryBaseFeeRequest{}) require.Equal(t, &evmtypes.QueryBaseFeeResponse{}, res) require.Error(t, err) } @@ -235,19 +255,19 @@ func TestRegisterBaseFeeError(t *testing.T) { func TestRegisterBaseFeeDisabled(t *testing.T) { queryClient := mocks.NewEVMQueryClient(t) RegisterBaseFeeDisabled(queryClient) - res, err := queryClient.BaseFee(rpc.ContextWithHeight(1), &evmtypes.QueryBaseFeeRequest{}) + res, err := queryClient.BaseFee(rpc.NewContextWithHeight(1), &evmtypes.QueryBaseFeeRequest{}) require.Equal(t, &evmtypes.QueryBaseFeeResponse{}, res) require.NoError(t, err) } // ValidatorAccount func RegisterValidatorAccount(queryClient *mocks.EVMQueryClient, validator sdk.AccAddress) { - queryClient.On("ValidatorAccount", rpc.ContextWithHeight(1), &evmtypes.QueryValidatorAccountRequest{}). + queryClient.EXPECT().ValidatorAccount(mock.Anything, &evmtypes.QueryValidatorAccountRequest{}). Return(&evmtypes.QueryValidatorAccountResponse{AccountAddress: validator.String()}, nil) } func RegisterValidatorAccountError(queryClient *mocks.EVMQueryClient) { - queryClient.On("ValidatorAccount", rpc.ContextWithHeight(1), &evmtypes.QueryValidatorAccountRequest{}). + queryClient.EXPECT().ValidatorAccount(mock.Anything, &evmtypes.QueryValidatorAccountRequest{}). Return(nil, status.Error(codes.InvalidArgument, "empty request")) } @@ -256,35 +276,35 @@ func TestRegisterValidatorAccount(t *testing.T) { validator := sdk.AccAddress(utiltx.GenerateAddress().Bytes()) RegisterValidatorAccount(queryClient, validator) - res, err := queryClient.ValidatorAccount(rpc.ContextWithHeight(1), &evmtypes.QueryValidatorAccountRequest{}) + res, err := queryClient.ValidatorAccount(rpc.NewContextWithHeight(1), &evmtypes.QueryValidatorAccountRequest{}) require.Equal(t, &evmtypes.QueryValidatorAccountResponse{AccountAddress: validator.String()}, res) require.NoError(t, err) } // Code func RegisterCode(queryClient *mocks.EVMQueryClient, addr common.Address, code []byte) { - queryClient.On("Code", rpc.ContextWithHeight(1), &evmtypes.QueryCodeRequest{Address: addr.String()}). + queryClient.EXPECT().Code(mock.Anything, &evmtypes.QueryCodeRequest{Address: addr.String()}). Return(&evmtypes.QueryCodeResponse{Code: code}, nil) } func RegisterCodeError(queryClient *mocks.EVMQueryClient, addr common.Address) { - queryClient.On("Code", rpc.ContextWithHeight(1), &evmtypes.QueryCodeRequest{Address: addr.String()}). + queryClient.EXPECT().Code(mock.Anything, &evmtypes.QueryCodeRequest{Address: addr.String()}). Return(nil, errortypes.ErrInvalidRequest) } // Storage func RegisterStorageAt(queryClient *mocks.EVMQueryClient, addr common.Address, key string, storage string) { - queryClient.On("Storage", rpc.ContextWithHeight(1), &evmtypes.QueryStorageRequest{Address: addr.String(), Key: key}). + queryClient.EXPECT().Storage(mock.Anything, &evmtypes.QueryStorageRequest{Address: addr.String(), Key: key}). Return(&evmtypes.QueryStorageResponse{Value: storage}, nil) } func RegisterStorageAtError(queryClient *mocks.EVMQueryClient, addr common.Address, key string) { - queryClient.On("Storage", rpc.ContextWithHeight(1), &evmtypes.QueryStorageRequest{Address: addr.String(), Key: key}). + queryClient.EXPECT().Storage(mock.Anything, &evmtypes.QueryStorageRequest{Address: addr.String(), Key: key}). Return(nil, errortypes.ErrInvalidRequest) } func RegisterAccount(queryClient *mocks.EVMQueryClient, addr common.Address, height int64) { - queryClient.On("Account", rpc.ContextWithHeight(height), &evmtypes.QueryAccountRequest{Address: addr.String()}). + queryClient.EXPECT().Account(mock.Anything, &evmtypes.QueryAccountRequest{Address: addr.String()}). Return(&evmtypes.QueryAccountResponse{ Balance: "0", CodeHash: "", @@ -296,27 +316,27 @@ func RegisterAccount(queryClient *mocks.EVMQueryClient, addr common.Address, hei // Balance func RegisterBalance(queryClient *mocks.EVMQueryClient, addr common.Address, height int64) { - queryClient.On("Balance", rpc.ContextWithHeight(height), &evmtypes.QueryBalanceRequest{Address: addr.String()}). + queryClient.EXPECT().Balance(mock.Anything, &evmtypes.QueryBalanceRequest{Address: addr.String()}). Return(&evmtypes.QueryBalanceResponse{Balance: "1"}, nil) } func RegisterBalanceInvalid(queryClient *mocks.EVMQueryClient, addr common.Address, height int64) { - queryClient.On("Balance", rpc.ContextWithHeight(height), &evmtypes.QueryBalanceRequest{Address: addr.String()}). + queryClient.EXPECT().Balance(mock.Anything, &evmtypes.QueryBalanceRequest{Address: addr.String()}). Return(&evmtypes.QueryBalanceResponse{Balance: "invalid"}, nil) } func RegisterBalanceNegative(queryClient *mocks.EVMQueryClient, addr common.Address, height int64) { - queryClient.On("Balance", rpc.ContextWithHeight(height), &evmtypes.QueryBalanceRequest{Address: addr.String()}). + queryClient.EXPECT().Balance(mock.Anything, &evmtypes.QueryBalanceRequest{Address: addr.String()}). Return(&evmtypes.QueryBalanceResponse{Balance: "-1"}, nil) } func RegisterBalanceError(queryClient *mocks.EVMQueryClient, addr common.Address, height int64) { - queryClient.On("Balance", rpc.ContextWithHeight(height), &evmtypes.QueryBalanceRequest{Address: addr.String()}). + queryClient.EXPECT().Balance(mock.Anything, &evmtypes.QueryBalanceRequest{Address: addr.String()}). Return(nil, errortypes.ErrInvalidRequest) } // GlobalMinGasPrice func RegisterGlobalMinGasPrice(queryClient *mocks.EVMQueryClient, height int64) { - queryClient.On("GlobalMinGasPrice", rpc.ContextWithHeight(height), &evmtypes.QueryGlobalMinGasPriceRequest{}). + queryClient.EXPECT().GlobalMinGasPrice(mock.Anything, &evmtypes.QueryGlobalMinGasPriceRequest{}). Return(&evmtypes.QueryGlobalMinGasPriceResponse{MinGasPrice: math.OneInt()}, nil) } diff --git a/tests/integration/rpc/backend/test_feemarket_query_client.go b/tests/integration/rpc/backend/test_feemarket_query_client.go index 47e961ac..ccf6c791 100644 --- a/tests/integration/rpc/backend/test_feemarket_query_client.go +++ b/tests/integration/rpc/backend/test_feemarket_query_client.go @@ -1,8 +1,9 @@ package backend import ( + "github.com/stretchr/testify/mock" + "github.com/cosmos/evm/rpc/backend/mocks" - rpc "github.com/cosmos/evm/rpc/types" feemarkettypes "github.com/cosmos/evm/x/feemarket/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" @@ -12,11 +13,11 @@ var _ feemarkettypes.QueryClient = &mocks.FeeMarketQueryClient{} // Params func RegisterFeeMarketParams(feeMarketClient *mocks.FeeMarketQueryClient, height int64) { - feeMarketClient.On("Params", rpc.ContextWithHeight(height), &feemarkettypes.QueryParamsRequest{}). + feeMarketClient.EXPECT().Params(mock.Anything, &feemarkettypes.QueryParamsRequest{}). Return(&feemarkettypes.QueryParamsResponse{Params: feemarkettypes.DefaultParams()}, nil) } func RegisterFeeMarketParamsError(feeMarketClient *mocks.FeeMarketQueryClient, height int64) { - feeMarketClient.On("Params", rpc.ContextWithHeight(height), &feemarkettypes.QueryParamsRequest{}). + feeMarketClient.EXPECT().Params(mock.Anything, &feemarkettypes.QueryParamsRequest{}). Return(nil, sdkerrors.ErrInvalidRequest) } diff --git a/tests/integration/rpc/backend/test_filters.go b/tests/integration/rpc/backend/test_filters.go index 50311699..b1a6ef4a 100644 --- a/tests/integration/rpc/backend/test_filters.go +++ b/tests/integration/rpc/backend/test_filters.go @@ -78,7 +78,7 @@ func (s *TestSuite) TestGetLogs() { s.SetupTest() tc.registerMock(tc.blockHash) - logs, err := s.backend.GetLogs(tc.blockHash) + logs, err := s.backend.GetLogs(s.Ctx(), tc.blockHash) if tc.expPass { s.Require().NoError(err) diff --git a/tests/integration/rpc/backend/test_mempool.go b/tests/integration/rpc/backend/test_mempool.go new file mode 100644 index 00000000..eb60eb76 --- /dev/null +++ b/tests/integration/rpc/backend/test_mempool.go @@ -0,0 +1,73 @@ +package backend + +import ( + "context" + "math/big" + "testing" + + gethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/params" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/cosmos/evm/mempool/txpool" + txpoolmocks "github.com/cosmos/evm/mempool/txpool/mocks" + "github.com/cosmos/evm/rpc/backend/mocks" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func NewEvmMempoolMock(t *testing.T) *mocks.Mempool { + t.Helper() + + blockchain := txpoolmocks.NewBlockChain(t) + blockchain.On("CurrentBlock").Return(&gethtypes.Header{Number: big.NewInt(1)}).Maybe() + blockchain.On("StateAt", mock.Anything).Return(nil, nil).Maybe() + blockchain.On("SubscribeChainHeadEvent", mock.Anything).Return(&mockMempoolSubscription{}).Maybe() + blockchain.On("Config").Return(¶ms.ChainConfig{ChainID: big.NewInt(1)}).Maybe() + + // pool.Status() will return TxStatusUnknown + pool, err := txpool.New(0, blockchain, nil, nil) + require.NoError(t, err) + t.Cleanup(func() { pool.Close() }) + + mempool := mocks.NewMempool(t) + mempool.On("GetTxPool").Return(pool).Maybe() + + return mempool +} + +func RegisterMempoolInsert(t *testing.T, mempool *mocks.Mempool, expect sdk.Tx, err error) { + t.Helper() + + doReturn := func(_ context.Context, actual sdk.Tx) error { + if err == nil { + requireTxEqual(t, expect, actual) + } + + return err + } + + mempool.On("Insert", mock.Anything, mock.Anything).Return(doReturn) +} + +func requireTxEqual(t *testing.T, expected, actual sdk.Tx) { + t.Helper() + + require.NotNil(t, actual, "tx mempool.Insert(ctx, tx) is nil") + require.NotNil(t, expected, "expected tx is nil") + + require.Equal(t, len(expected.GetMsgs()), len(actual.GetMsgs()), "txs have different msgs") + + for i := range len(expected.GetMsgs()) { + leftStr := expected.GetMsgs()[i].String() + rightStr := actual.GetMsgs()[i].String() + + require.True(t, leftStr == rightStr, "tx.message %d is different", i) + } +} + +type mockMempoolSubscription struct{} + +func (ms *mockMempoolSubscription) Err() <-chan error { return make(chan error) } +func (ms *mockMempoolSubscription) Unsubscribe() {} diff --git a/tests/integration/rpc/backend/test_node_info.go b/tests/integration/rpc/backend/test_node_info.go index 270a3c8a..04ff5068 100644 --- a/tests/integration/rpc/backend/test_node_info.go +++ b/tests/integration/rpc/backend/test_node_info.go @@ -196,7 +196,7 @@ func (s *TestSuite) TestSyncing() { func() { client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterStatus(client) - status, _ := client.Status(s.backend.Ctx) + status, _ := client.Status(s.Ctx()) status.SyncInfo.CatchingUp = true }, map[string]interface{}{ @@ -212,7 +212,7 @@ func (s *TestSuite) TestSyncing() { s.SetupTest() // reset test and queries tc.registerMock() - output, err := s.backend.Syncing() + output, err := s.backend.Syncing(s.Ctx()) if tc.expPass { s.Require().NoError(err) @@ -262,7 +262,7 @@ func (s *TestSuite) TestSetEtherbase() { RegisterParams(QueryClient, &header, 1) c := sdk.NewDecCoin(constants.ExampleAttoDenom, math.NewIntFromBigInt(big.NewInt(1))) s.backend.Cfg.SetMinGasPrices(sdk.DecCoins{c}) - delAddr, _ := s.backend.GetCoinbase() + delAddr, _ := s.backend.GetCoinbase(s.Ctx()) // account, _ := s.backend.ClientCtx.AccountRetriever.GetAccount(s.backend.ClientCtx, delAddr) delCommonAddr := common.BytesToAddress(delAddr.Bytes()) request := &authtypes.QueryAccountRequest{Address: sdk.AccAddress(delCommonAddr.Bytes()).String()} @@ -309,7 +309,7 @@ func (s *TestSuite) TestSetEtherbase() { s.SetupTest() // reset test and queries tc.registerMock() - output := s.backend.SetEtherbase(tc.etherbase) + output := s.backend.SetEtherbase(s.Ctx(), tc.etherbase) s.Require().Equal(tc.expResult, output) }) diff --git a/tests/integration/rpc/backend/test_sign_tx.go b/tests/integration/rpc/backend/test_sign_tx.go index a0f2d3f1..67784c5a 100644 --- a/tests/integration/rpc/backend/test_sign_tx.go +++ b/tests/integration/rpc/backend/test_sign_tx.go @@ -1,6 +1,7 @@ package backend import ( + "errors" "fmt" "github.com/ethereum/go-ethereum/common" @@ -20,6 +21,7 @@ import ( "github.com/cosmos/cosmos-sdk/crypto" sdk "github.com/cosmos/cosmos-sdk/types" signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" + "github.com/cosmos/cosmos-sdk/x/auth/signing" ) const MinIntrinsicGas = 21000 @@ -102,8 +104,8 @@ func (s *TestSuite) TestSendTransaction() { { "fail - Cannot broadcast transaction", func() { - client, txBytes := broadcastTx(s, priv, baseFee, callArgsDefault) - RegisterBroadcastTxError(client, txBytes) + _, _ = buildBroadcastTx(s, priv, baseFee, callArgsDefault) + RegisterMempoolInsert(s.T(), s.Mempool(), nil, errors.New("queue is full")) }, callArgsDefault, common.Hash{}, @@ -112,8 +114,8 @@ func (s *TestSuite) TestSendTransaction() { { "pass - Return the transaction hash", func() { - client, txBytes := broadcastTx(s, priv, baseFee, callArgsDefault) - RegisterBroadcastTx(client, txBytes) + _, tx := buildBroadcastTx(s, priv, baseFee, callArgsDefault) + RegisterMempoolInsert(s.T(), s.Mempool(), tx, nil) }, callArgsDefault, hash, @@ -135,11 +137,12 @@ func (s *TestSuite) TestSendTransaction() { s.Require().NoError(err) tc.expHash = msg.AsTransaction().Hash() } - responseHash, err := s.backend.SendTransaction(tc.args) + responseHash, err := s.backend.SendTransaction(s.Ctx(), tc.args) if tc.expPass { s.Require().NoError(err) s.Require().Equal(tc.expHash, responseHash) } else { + s.T().Logf("error: %v", err) s.Require().Error(err) } }) @@ -243,26 +246,33 @@ func (s *TestSuite) TestSignTypedData() { } } -func broadcastTx(suite *TestSuite, priv *ethsecp256k1.PrivKey, baseFee math.Int, callArgsDefault evmtypes.TransactionArgs) (client *mocks.Client, txBytes []byte) { +//nolint:unparam +func buildBroadcastTx(suite *TestSuite, priv *ethsecp256k1.PrivKey, baseFee math.Int, callArgsDefault evmtypes.TransactionArgs) (*mocks.Client, signing.Tx) { var header metadata.MD - QueryClient := suite.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) - client = suite.backend.ClientCtx.Client.(*mocks.Client) + + evmQueryClient := suite.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + client := suite.backend.ClientCtx.Client.(*mocks.Client) armor := crypto.EncryptArmorPrivKey(priv, "", "eth_secp256k1") _ = suite.backend.ClientCtx.Keyring.ImportPrivKey("test_key", armor, "") height := int64(1) - RegisterParams(QueryClient, &header, height) + + RegisterParams(evmQueryClient, &header, height) RegisterBlock(client, height, nil) RegisterBlockResults(client, height) - RegisterBaseFee(QueryClient, baseFee) - RegisterValidatorAccount(QueryClient, sdk.AccAddress(utiltx.GenerateAddress().Bytes())) + RegisterBaseFee(evmQueryClient, baseFee) + RegisterValidatorAccount(evmQueryClient, sdk.AccAddress(utiltx.GenerateAddress().Bytes())) RegisterConsensusParams(client, height) + ethSigner := ethtypes.LatestSigner(suite.backend.ChainConfig()) msg := evmtypes.NewTxFromArgs(&callArgsDefault) + err := msg.Sign(ethSigner, suite.backend.ClientCtx.Keyring) suite.Require().NoError(err) - baseDenom := evmtypes.GetEVMCoinDenom() - tx, _ := msg.BuildTx(suite.backend.ClientCtx.TxConfig.NewTxBuilder(), baseDenom) - txEncoder := suite.backend.ClientCtx.TxConfig.TxEncoder() - txBytes, _ = txEncoder(tx) - return client, txBytes + + tx, _ := msg.BuildTx( + suite.backend.ClientCtx.TxConfig.NewTxBuilder(), + evmtypes.GetEVMCoinDenom(), + ) + + return client, tx } diff --git a/tests/integration/rpc/backend/test_tracing.go b/tests/integration/rpc/backend/test_tracing.go index eefbaf81..8a5193c2 100644 --- a/tests/integration/rpc/backend/test_tracing.go +++ b/tests/integration/rpc/backend/test_tracing.go @@ -18,7 +18,7 @@ import ( rpctypes "github.com/cosmos/evm/rpc/types" evmtypes "github.com/cosmos/evm/x/vm/types" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" "github.com/cosmos/cosmos-sdk/crypto" ) @@ -196,7 +196,7 @@ func (s *TestSuite) TestTraceTransaction() { err := s.backend.Indexer.IndexBlock(tc.block, tc.responseBlock) s.Require().NoError(err) - txResult, err := s.backend.TraceTransaction(txHash, nil) + txResult, err := s.backend.TraceTransaction(s.Ctx(), txHash, nil) if tc.expPass { s.Require().NoError(err) @@ -369,7 +369,7 @@ func (s *TestSuite) TestTraceCall() { s.SetupTest() // reset test and queries tc.registerMock() - result, err := s.backend.TraceCall(tc.args, tc.blockNrOrHash, tc.config) + result, err := s.backend.TraceCall(s.Ctx(), tc.args, tc.blockNrOrHash, tc.config) if tc.expPass { s.Require().NoError(err) @@ -441,7 +441,7 @@ func (s *TestSuite) TestTraceBlock() { Data: []byte(`[{"result": "trace1"}, {"result": "trace2"}]`), } queryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) - queryClient.On("TraceBlock", mock.Anything, mock.AnythingOfType("*types.QueryTraceBlockRequest")). + queryClient.EXPECT().TraceBlock(mock.Anything, mock.AnythingOfType("*types.QueryTraceBlockRequest")). Return(traceResult, nil). Once() }, @@ -457,7 +457,7 @@ func (s *TestSuite) TestTraceBlock() { s.SetupTest() // reset test and queries tc.registerMock() - traceResults, err := s.backend.TraceBlock(1, tc.config, tc.resBlock) + traceResults, err := s.backend.TraceBlock(s.Ctx(), 1, tc.config, tc.resBlock) if tc.expPass { s.Require().NoError(err) diff --git a/tests/integration/rpc/backend/test_tx_info.go b/tests/integration/rpc/backend/test_tx_info.go index 0d6efea5..718ddcbe 100644 --- a/tests/integration/rpc/backend/test_tx_info.go +++ b/tests/integration/rpc/backend/test_tx_info.go @@ -20,7 +20,7 @@ import ( cosmosevmtypes "github.com/cosmos/evm/server/types" evmtypes "github.com/cosmos/evm/x/vm/types" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" "cosmossdk.io/math" ) @@ -115,7 +115,7 @@ func (s *TestSuite) TestGetTransactionByHash() { err := s.backend.Indexer.IndexBlock(block, responseDeliver) s.Require().NoError(err) - rpcTx, err := s.backend.GetTransactionByHash(tc.tx.Hash()) + rpcTx, err := s.backend.GetTransactionByHash(s.Ctx(), tc.tx.Hash()) if tc.expPass { s.Require().NoError(err) @@ -175,7 +175,7 @@ func (s *TestSuite) TestGetTransactionsByHashPending() { s.SetupTest() // reset tc.registerMock() - rpcTx, err := s.backend.GetTransactionByHashPending(tc.tx.Hash()) + rpcTx, err := s.backend.GetTransactionByHashPending(s.Ctx(), tc.tx.Hash()) if tc.expPass { s.Require().NoError(err) @@ -217,7 +217,7 @@ func (s *TestSuite) TestGetTxByEthHash() { s.SetupTest() // reset tc.registerMock() - rpcTx, err := s.backend.GetTxByEthHash(tc.tx.Hash()) + rpcTx, err := s.backend.GetTxByEthHash(s.Ctx(), tc.tx.Hash()) if tc.expPass { s.Require().NoError(err) @@ -267,7 +267,7 @@ func (s *TestSuite) TestGetTransactionByBlockHashAndIndex() { s.SetupTest() // reset tc.registerMock() - rpcTx, err := s.backend.GetTransactionByBlockHashAndIndex(tc.blockHash, 1) + rpcTx, err := s.backend.GetTransactionByBlockHashAndIndex(s.Ctx(), tc.blockHash, 1) if tc.expPass { s.Require().NoError(err) @@ -380,7 +380,7 @@ func (s *TestSuite) TestGetTransactionByBlockAndIndex() { s.SetupTest() // reset tc.registerMock() - rpcTx, err := s.backend.GetTransactionByBlockAndIndex(tc.block, tc.idx) + rpcTx, err := s.backend.GetTransactionByBlockAndIndex(s.Ctx(), tc.block, tc.idx) if tc.expPass { s.Require().NoError(err) @@ -445,7 +445,7 @@ func (s *TestSuite) TestGetTransactionByBlockNumberAndIndex() { s.SetupTest() // reset tc.registerMock() - rpcTx, err := s.backend.GetTransactionByBlockNumberAndIndex(tc.blockNum, tc.idx) + rpcTx, err := s.backend.GetTransactionByBlockNumberAndIndex(s.Ctx(), tc.blockNum, tc.idx) if tc.expPass { s.Require().NoError(err) s.Require().Equal(rpcTx, tc.expRPCTx) @@ -486,7 +486,7 @@ func (s *TestSuite) TestGetTransactionByTxIndex() { s.SetupTest() // reset tc.registerMock() - txResults, err := s.backend.GetTxByTxIndex(tc.height, tc.index) + txResults, err := s.backend.GetTxByTxIndex(s.Ctx(), tc.height, tc.index) if tc.expPass { s.Require().NoError(err) @@ -527,7 +527,7 @@ func (s *TestSuite) TestQueryCometTxIndexer() { s.SetupTest() // reset tc.registerMock() - txResults, err := s.backend.QueryCometTxIndexer(tc.query, tc.txGetter) + txResults, err := s.backend.QueryCometTxIndexer(s.Ctx(), tc.query, tc.txGetter) if tc.expPass { s.Require().NoError(err) @@ -685,7 +685,7 @@ func (s *TestSuite) TestGetTransactionReceipt() { err := s.backend.Indexer.IndexBlock(tc.block, tc.blockResult) s.Require().NoError(err) - res, err := s.backend.GetTransactionReceipt(tc.tx.Hash()) + res, err := s.backend.GetTransactionReceipt(s.Ctx(), tc.tx.Hash()) if tc.expPass { s.Require().Equal(res["transactionHash"], tc.tx.Hash()) s.Require().Equal(res["blockNumber"], hexutil.Uint64(tc.block.Height)) //nolint: gosec // G115 diff --git a/tests/integration/rpc/backend/test_utils.go b/tests/integration/rpc/backend/test_utils.go index 8b3aae1d..994ddfbb 100644 --- a/tests/integration/rpc/backend/test_utils.go +++ b/tests/integration/rpc/backend/test_utils.go @@ -1,11 +1,18 @@ package backend import ( + "context" "fmt" + "github.com/ethereum/go-ethereum/common" + + abci "github.com/cometbft/cometbft/abci/types" "github.com/cometbft/cometbft/proto/tendermint/crypto" + cmtrpctypes "github.com/cometbft/cometbft/rpc/core/types" + "github.com/cometbft/cometbft/types" backend2 "github.com/cosmos/evm/rpc/backend" + evmtypes "github.com/cosmos/evm/x/vm/types" ) func mookProofs(num int, withData bool) *crypto.ProofOps { @@ -52,3 +59,194 @@ func (s *TestSuite) TestGetHexProofs() { }) } } + +func (s *TestSuite) TestFindEthTxIndexByHash() { + txHash := common.HexToHash("0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef") + tx := evmtypes.NewTx(&evmtypes.EvmTxArgs{ + ChainID: s.backend.EvmChainID, + Nonce: 0, + GasLimit: 100000, + }) + tx.From = s.from.Bytes() + txEncoder := s.backend.ClientCtx.TxConfig.TxEncoder() + builder := s.backend.ClientCtx.TxConfig.NewTxBuilder() + err := builder.SetMsgs(tx) + s.Require().NoError(err) + txBz, err := txEncoder(builder.GetTx()) + s.Require().NoError(err) + + testCases := []struct { + name string + setupMock func() (*cmtrpctypes.ResultBlock, *cmtrpctypes.ResultBlockResults) + txHash common.Hash + expectError bool + errorMsg string + expectedIdx int32 + }{ + { + name: "tx found at index 0", + setupMock: func() (*cmtrpctypes.ResultBlock, *cmtrpctypes.ResultBlockResults) { + block := &cmtrpctypes.ResultBlock{ + Block: &types.Block{ + Header: types.Header{Height: 1}, + Data: types.Data{ + Txs: []types.Tx{txBz}, + }, + }, + } + blockRes := &cmtrpctypes.ResultBlockResults{ + TxsResults: []*abci.ExecTxResult{ + {Code: 0, GasUsed: 21000}, + }, + } + return block, blockRes + }, + txHash: tx.Hash(), + expectError: false, + expectedIdx: 0, + }, + { + name: "tx not found", + setupMock: func() (*cmtrpctypes.ResultBlock, *cmtrpctypes.ResultBlockResults) { + otherTx := evmtypes.NewTx(&evmtypes.EvmTxArgs{ + ChainID: s.backend.EvmChainID, + Nonce: 1, + GasLimit: 100000, + }) + otherTx.From = s.from.Bytes() + + builder := s.backend.ClientCtx.TxConfig.NewTxBuilder() + _ = builder.SetMsgs(otherTx) + otherTxBz, _ := txEncoder(builder.GetTx()) + + block := &cmtrpctypes.ResultBlock{ + Block: &types.Block{ + Header: types.Header{Height: 1}, + Data: types.Data{ + Txs: []types.Tx{otherTxBz}, + }, + }, + } + blockRes := &cmtrpctypes.ResultBlockResults{ + TxsResults: []*abci.ExecTxResult{ + {Code: 0, GasUsed: 21000}, + }, + } + return block, blockRes + }, + txHash: txHash, // Different hash + expectError: true, + errorMsg: "can't find index of ethereum tx", + }, + { + name: "empty block", + setupMock: func() (*cmtrpctypes.ResultBlock, *cmtrpctypes.ResultBlockResults) { + block := &cmtrpctypes.ResultBlock{ + Block: &types.Block{ + Header: types.Header{Height: 1}, + Data: types.Data{Txs: []types.Tx{}}, + }, + } + blockRes := &cmtrpctypes.ResultBlockResults{ + TxsResults: []*abci.ExecTxResult{}, + } + return block, blockRes + }, + txHash: txHash, + expectError: true, + errorMsg: "can't find index of ethereum tx", + }, + { + name: "tx with failed result code", + setupMock: func() (*cmtrpctypes.ResultBlock, *cmtrpctypes.ResultBlockResults) { + block := &cmtrpctypes.ResultBlock{ + Block: &types.Block{ + Header: types.Header{Height: 1}, + Data: types.Data{ + Txs: []types.Tx{txBz}, + }, + }, + } + blockRes := &cmtrpctypes.ResultBlockResults{ + TxsResults: []*abci.ExecTxResult{ + {Code: 1, GasUsed: 21000, Log: "execution reverted"}, // Failed tx + }, + } + return block, blockRes + }, + txHash: tx.Hash(), + expectError: true, + errorMsg: "can't find index of ethereum tx", // Will be filtered out by EthMsgsFromCometBlock + }, + { + name: "multiple txs, target at index 1", + setupMock: func() (*cmtrpctypes.ResultBlock, *cmtrpctypes.ResultBlockResults) { + tx1 := evmtypes.NewTx(&evmtypes.EvmTxArgs{ + ChainID: s.backend.EvmChainID, + Nonce: 0, + GasLimit: 100000, + }) + tx1.From = s.from.Bytes() + + builder1 := s.backend.ClientCtx.TxConfig.NewTxBuilder() + _ = builder1.SetMsgs(tx1) + tx1Bz, _ := txEncoder(builder1.GetTx()) + + tx2 := evmtypes.NewTx(&evmtypes.EvmTxArgs{ + ChainID: s.backend.EvmChainID, + Nonce: 1, + GasLimit: 100000, + }) + tx2.From = s.from.Bytes() + + builder2 := s.backend.ClientCtx.TxConfig.NewTxBuilder() + _ = builder2.SetMsgs(tx2) + tx2Bz, _ := txEncoder(builder2.GetTx()) + + block := &cmtrpctypes.ResultBlock{ + Block: &types.Block{ + Header: types.Header{Height: 1}, + Data: types.Data{ + Txs: []types.Tx{tx1Bz, tx2Bz}, + }, + }, + } + blockRes := &cmtrpctypes.ResultBlockResults{ + TxsResults: []*abci.ExecTxResult{ + {Code: 0, GasUsed: 21000}, + {Code: 0, GasUsed: 21000}, + }, + } + return block, blockRes + }, + txHash: func() common.Hash { + tx2 := evmtypes.NewTx(&evmtypes.EvmTxArgs{ + ChainID: s.backend.EvmChainID, + Nonce: 1, + GasLimit: 100000, + }) + tx2.From = s.from.Bytes() + return tx2.Hash() + }(), + expectError: false, + expectedIdx: 1, + }, + } + + for _, tc := range testCases { + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + block, blockRes := tc.setupMock() + + idx, err := s.backend.FindEthTxIndexByHash(context.Background(), tc.txHash, block, blockRes) + + if tc.expectError { + s.Require().Error(err) + s.Require().Contains(err.Error(), tc.errorMsg) + s.Require().Equal(int32(-1), idx) + } else { + s.Require().NoError(err) + s.Require().Equal(tc.expectedIdx, idx) + } + }) + } +} diff --git a/tests/integration/x/erc20/test_convert.go b/tests/integration/x/erc20/test_convert.go new file mode 100644 index 00000000..5d10d0c1 --- /dev/null +++ b/tests/integration/x/erc20/test_convert.go @@ -0,0 +1,383 @@ +package erc20 + +import ( + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/holiman/uint256" + "github.com/stretchr/testify/mock" + "go.uber.org/mock/gomock" + + "github.com/cosmos/evm/testutil/integration/evm/utils" + "github.com/cosmos/evm/x/erc20/keeper" + "github.com/cosmos/evm/x/erc20/types" + erc20mocks "github.com/cosmos/evm/x/erc20/types/mocks" + "github.com/cosmos/evm/x/vm/statedb" + evmtypes "github.com/cosmos/evm/x/vm/types" + + "cosmossdk.io/math" + + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" +) + +// TestConvertERC20IntoCoinsForNativeToken tests the core conversion logic +func (s *KeeperTestSuite) TestConvertERC20IntoCoinsForNativeToken() { + var ( + contractAddr common.Address + coinName string + ) + testCases := []struct { + name string + mint int64 + transfer int64 + malleate func(common.Address) + extra func() + contractType int + expPass bool + selfdestructed bool + }{ + { + "ok - sufficient funds", + 100, + 10, + func(common.Address) {}, + func() {}, + contractMinterBurner, + true, + false, + }, + { + "ok - equal funds", + 10, + 10, + func(common.Address) {}, + func() {}, + contractMinterBurner, + true, + false, + }, + { + "fail - insufficient funds - callEVM", + 0, + 10, + func(common.Address) {}, + func() {}, + contractMinterBurner, + false, + false, + }, + { + "fail - minting disabled", + 100, + 10, + func(contractAddr common.Address) { + params := types.DefaultParams() + params.EnableErc20 = false + err := utils.UpdateERC20Params( + utils.UpdateParamsInput{ + Tf: s.factory, + Network: s.network, + Pk: s.keyring.GetPrivKey(0), + Params: params, + }, + ) + s.Require().NoError(err) + }, + func() {}, + contractMinterBurner, + false, + false, + }, + { + "fail - direct balance manipulation contract", + 100, + 10, + func(common.Address) {}, + func() {}, + contractDirectBalanceManipulation, + false, + false, + }, + { + "pass - delayed malicious contract", + 10, + 10, + func(common.Address) {}, + func() {}, + contractMaliciousDelayed, + true, + false, + }, + { + "fail - negative transfer amount", + 10, + -10, + func(common.Address) {}, + func() {}, + contractMinterBurner, + false, + false, + }, + { + "fail - force evm fail", + 100, + 10, + func(common.Address) {}, + func() { + mockEVMKeeper := &erc20mocks.EVMKeeper{} + transferKeeper := s.network.App.GetTransferKeeper() + erc20Keeper := keeper.NewKeeper( + s.network.App.GetKey("erc20"), s.network.App.AppCodec(), + authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), + s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), + transferKeeper, + ) + s.network.App.SetErc20Keeper(erc20Keeper) + + existingAcc := &statedb.Account{Nonce: uint64(1), Balance: uint256.NewInt(1)} + balance := make([]uint8, 32) + mockEVMKeeper.On("EstimateGasInternal", mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.EstimateGasResponse{Gas: uint64(200)}, nil) + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, + mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: balance}, nil).Once() + mockEVMKeeper.On("CallEVMWithData", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, + mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("forced ApplyMessage error")) + mockEVMKeeper.On("GetAccountWithoutBalance", mock.Anything, mock.Anything).Return(existingAcc, nil) + mockEVMKeeper.On("IsContract", mock.Anything, mock.Anything).Return(true) + }, + contractMinterBurner, + false, + false, + }, + { + "fail - force get balance fail", + 100, + 10, + func(common.Address) {}, + func() { + mockEVMKeeper := &erc20mocks.EVMKeeper{} + transferKeeper := s.network.App.GetTransferKeeper() + erc20Keeper := keeper.NewKeeper( + s.network.App.GetKey("erc20"), s.network.App.AppCodec(), + authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), + s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), + transferKeeper, + ) + s.network.App.SetErc20Keeper(erc20Keeper) + + existingAcc := &statedb.Account{Nonce: uint64(1), Balance: uint256.NewInt(1)} + balance := make([]uint8, 32) + balance[31] = uint8(1) + mockEVMKeeper.On("EstimateGasInternal", mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.EstimateGasResponse{Gas: uint64(200)}, nil) + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: balance}, nil).Twice() + mockEVMKeeper.On("CallEVMWithData", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("forced balance error")) + mockEVMKeeper.On("GetAccountWithoutBalance", mock.Anything, mock.Anything).Return(existingAcc, nil) + mockEVMKeeper.On("IsContract", mock.Anything, mock.Anything).Return(true) + }, + contractMinterBurner, + false, + false, + }, + { + "fail - force transfer unpack fail", + 100, + 10, + func(common.Address) {}, + func() { + mockEVMKeeper := &erc20mocks.EVMKeeper{} + transferKeeper := s.network.App.GetTransferKeeper() + erc20Keeper := keeper.NewKeeper( + s.network.App.GetKey("erc20"), s.network.App.AppCodec(), + authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), + s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), + transferKeeper, + ) + s.network.App.SetErc20Keeper(erc20Keeper) + + existingAcc := &statedb.Account{Nonce: uint64(1), Balance: uint256.NewInt(1)} + balance := make([]uint8, 32) + mockEVMKeeper.On("EstimateGasInternal", mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.EstimateGasResponse{Gas: uint64(200)}, nil) + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, + mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: balance}, nil).Once() + mockEVMKeeper.On("CallEVMWithData", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{}, nil) + mockEVMKeeper.On("GetAccountWithoutBalance", mock.Anything, mock.Anything).Return(existingAcc, nil) + mockEVMKeeper.On("IsContract", mock.Anything, mock.Anything).Return(true) + }, + contractMinterBurner, + false, + false, + }, + { + "fail - force invalid transfer fail", + 100, + 10, + func(common.Address) {}, + func() { + mockEVMKeeper := &erc20mocks.EVMKeeper{} + transferKeeper := s.network.App.GetTransferKeeper() + erc20Keeper := keeper.NewKeeper( + s.network.App.GetKey("erc20"), s.network.App.AppCodec(), + authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), + s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), + transferKeeper, + ) + s.network.App.SetErc20Keeper(erc20Keeper) + + existingAcc := &statedb.Account{Nonce: uint64(1), Balance: uint256.NewInt(1)} + balance := make([]uint8, 32) + mockEVMKeeper.On("EstimateGasInternal", mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.EstimateGasResponse{Gas: uint64(200)}, nil) + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, + mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: balance}, nil).Once() + mockEVMKeeper.On("CallEVMWithData", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, + mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: balance}, nil) + mockEVMKeeper.On("GetAccountWithoutBalance", mock.Anything, mock.Anything).Return(existingAcc, nil) + mockEVMKeeper.On("IsContract", mock.Anything, mock.Anything).Return(true) + }, + contractMinterBurner, + false, + false, + }, + { + "fail - force mint fail", + 100, + 10, + func(common.Address) {}, + func() { + ctrl := gomock.NewController(s.T()) + mockBankKeeper := erc20mocks.NewMockBankKeeper(ctrl) + transferKeeper := s.network.App.GetTransferKeeper() + erc20Keeper := keeper.NewKeeper( + s.network.App.GetKey("erc20"), s.network.App.AppCodec(), + authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), + mockBankKeeper, s.network.App.GetEVMKeeper(), s.network.App.GetStakingKeeper(), + transferKeeper, + ) + s.network.App.SetErc20Keeper(erc20Keeper) + + mockBankKeeper.EXPECT().MintCoins(gomock.Any(), gomock.Any(), gomock.Any()).Return(fmt.Errorf("failed to mint")).AnyTimes() + mockBankKeeper.EXPECT().SendCoinsFromModuleToAccount(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(fmt.Errorf("failed to unescrow")).AnyTimes() + mockBankKeeper.EXPECT().BlockedAddr(gomock.Any()).Return(false).AnyTimes() + mockBankKeeper.EXPECT().GetBalance(gomock.Any(), gomock.Any(), gomock.Any()).Return(sdk.Coin{Denom: "coin", Amount: math.OneInt()}).AnyTimes() + mockBankKeeper.EXPECT().IsSendEnabledCoin(gomock.Any(), gomock.Any()).Return(true).AnyTimes() + }, + contractMinterBurner, + false, + false, + }, + { + "fail - force send minted fail", + 100, + 10, + func(common.Address) {}, + func() { + ctrl := gomock.NewController(s.T()) + mockBankKeeper := erc20mocks.NewMockBankKeeper(ctrl) + transferKeeper := s.network.App.GetTransferKeeper() + erc20Keeper := keeper.NewKeeper( + s.network.App.GetKey("erc20"), s.network.App.AppCodec(), + authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), + mockBankKeeper, s.network.App.GetEVMKeeper(), s.network.App.GetStakingKeeper(), + transferKeeper, + ) + s.network.App.SetErc20Keeper(erc20Keeper) + + mockBankKeeper.EXPECT().MintCoins(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) + mockBankKeeper.EXPECT().SendCoinsFromModuleToAccount(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(fmt.Errorf("failed to unescrow")) + mockBankKeeper.EXPECT().BlockedAddr(gomock.Any()).Return(false) + mockBankKeeper.EXPECT().GetBalance(gomock.Any(), gomock.Any(), gomock.Any()).Return(sdk.Coin{Denom: "coin", Amount: math.OneInt()}) + mockBankKeeper.EXPECT().IsSendEnabledCoin(gomock.Any(), gomock.Any()).Return(true).AnyTimes() + }, + contractMinterBurner, + false, + false, + }, + { + "fail - force bank balance fail", + 100, + 10, + func(common.Address) {}, + func() { + ctrl := gomock.NewController(s.T()) + mockBankKeeper := erc20mocks.NewMockBankKeeper(ctrl) + transferKeeper := s.network.App.GetTransferKeeper() + erc20Keeper := keeper.NewKeeper( + s.network.App.GetKey("erc20"), s.network.App.AppCodec(), + authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), + mockBankKeeper, s.network.App.GetEVMKeeper(), s.network.App.GetStakingKeeper(), + transferKeeper, + ) + s.network.App.SetErc20Keeper(erc20Keeper) + + mockBankKeeper.EXPECT().MintCoins(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) + mockBankKeeper.EXPECT().SendCoinsFromModuleToAccount(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) + mockBankKeeper.EXPECT().BlockedAddr(gomock.Any()).Return(false) + mockBankKeeper.EXPECT().GetBalance(gomock.Any(), gomock.Any(), gomock.Any()).Return(sdk.Coin{Denom: coinName, Amount: math.OneInt()}).AnyTimes() + mockBankKeeper.EXPECT().IsSendEnabledCoin(gomock.Any(), gomock.Any()).Return(true).AnyTimes() + }, + contractMinterBurner, + false, + false, + }, + } + for _, tc := range testCases { + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + var err error + s.mintFeeCollector = true + defer func() { + s.mintFeeCollector = false + }() + + s.SetupTest() + + contractAddr, err = s.setupRegisterERC20Pair(tc.contractType) + s.Require().NoError(err) + + tc.malleate(contractAddr) + s.Require().NotNil(contractAddr) + + coinName = types.CreateDenom(contractAddr.String()) + sender := s.keyring.GetAccAddr(0) + senderHex := s.keyring.GetAddr(0) + + _, err = s.MintERC20Token(contractAddr, senderHex, big.NewInt(tc.mint)) + s.Require().NoError(err) + + tc.extra() + + // Get context AFTER state modifications so changes are visible + ctx := s.network.GetContext() + stateDB := statedb.New(ctx, s.network.App.GetEVMKeeper(), statedb.NewEmptyTxConfig()) + + if tc.expPass { + // Call the conversion function directly + _, err = s.network.App.GetErc20Keeper().ConvertERC20IntoCoinsForNativeToken(ctx, stateDB, contractAddr, math.NewInt(tc.transfer), sender, senderHex, true, false) + s.Require().NoError(err, tc.name) + + cosmosBalance := s.network.App.GetBankKeeper().GetBalance(ctx, sender, coinName) + + acc := s.network.App.GetEVMKeeper().GetAccountWithoutBalance(ctx, contractAddr) + if tc.selfdestructed { + s.Require().Nil(acc, "expected contract to be destroyed") + } else { + s.Require().NotNil(acc) + } + + isContract := s.network.App.GetEVMKeeper().IsContract(ctx, contractAddr) + if tc.selfdestructed || !isContract { + id := s.network.App.GetErc20Keeper().GetTokenPairID(ctx, contractAddr.String()) + _, found := s.network.App.GetErc20Keeper().GetTokenPair(ctx, id) + s.Require().False(found) + } else { + s.Require().Equal(cosmosBalance.Amount, math.NewInt(tc.transfer)) + } + } else { + // Call the conversion function directly + _, err = s.network.App.GetErc20Keeper().ConvertERC20IntoCoinsForNativeToken(ctx, stateDB, contractAddr, math.NewInt(tc.transfer), sender, senderHex, true, false) + s.Require().Error(err, tc.name) + } + }) + } + s.mintFeeCollector = false +} diff --git a/tests/integration/x/erc20/test_dynamic_precompiles.go b/tests/integration/x/erc20/test_dynamic_precompiles.go index 9ca28906..3f2c9d8c 100644 --- a/tests/integration/x/erc20/test_dynamic_precompiles.go +++ b/tests/integration/x/erc20/test_dynamic_precompiles.go @@ -111,7 +111,7 @@ func (s *KeeperTestSuite) TestRegisterERC20CodeHash() { s.Require().Equal(nonce, acc.Nonce) if tc.vesting { totalBalance = s.network.App.GetBankKeeper().GetBalance(ctx, account.Bytes(), s.network.GetBaseDenom()).Amount - s.Require().Equal(totalBalance.BigInt(), common.U2560.Add(balance, balance).ToBig()) + s.Require().Equal(totalBalance.BigInt(), uint256.NewInt(0).Add(balance, balance).ToBig()) } } else { s.Require().Equal(common.U2560, acc.Balance) @@ -128,7 +128,7 @@ func (s *KeeperTestSuite) TestRegisterERC20CodeHash() { s.Require().Equal(nonce, acc.Nonce) if tc.vesting { totalBalance = s.network.App.GetBankKeeper().GetBalance(ctx, account.Bytes(), s.network.GetBaseDenom()).Amount - s.Require().Equal(totalBalance.BigInt(), common.U2560.Add(balance, balance).ToBig()) + s.Require().Equal(totalBalance.BigInt(), uint256.NewInt(0).Add(balance, balance).ToBig()) } } else { s.Require().Equal(common.U2560, acc.Balance) diff --git a/tests/integration/x/erc20/test_evm.go b/tests/integration/x/erc20/test_evm.go index 4e197741..25bf2317 100644 --- a/tests/integration/x/erc20/test_evm.go +++ b/tests/integration/x/erc20/test_evm.go @@ -84,8 +84,8 @@ func (s *KeeperTestSuite) TestBalanceOf() { { "Failed to call Evm", func() { - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, - mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("forced ApplyMessage error")) + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, + mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("forced ApplyMessage error")) }, int64(0), false, @@ -93,8 +93,8 @@ func (s *KeeperTestSuite) TestBalanceOf() { { "Incorrect res", func() { - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, - mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: []uint8{0, 0}}, nil).Once() + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, + mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: []uint8{0, 0}}, nil).Once() }, int64(0), false, @@ -104,8 +104,8 @@ func (s *KeeperTestSuite) TestBalanceOf() { func() { balance := make([]uint8, 32) balance[31] = uint8(10) - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, - mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: balance}, nil).Once() + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, + mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: balance}, nil).Once() }, int64(10), true, @@ -120,7 +120,7 @@ func (s *KeeperTestSuite) TestBalanceOf() { authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), - &transferKeeper, + transferKeeper, ) s.network.App.SetErc20Keeper(erc20Keeper) @@ -147,16 +147,16 @@ func (s *KeeperTestSuite) TestQueryERC20ForceFail() { { "Failed to call Evm", func() { - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, - mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("forced ApplyMessage error")) + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, + mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("forced ApplyMessage error")) }, false, }, { "Incorrect res", func() { - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, - mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: []uint8{0, 0}}, nil).Once() + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, + mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: []uint8{0, 0}}, nil).Once() }, false, }, @@ -165,8 +165,8 @@ func (s *KeeperTestSuite) TestQueryERC20ForceFail() { func() { ret := []uint8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 67, 111, 105, 110, 32, 84, 111, 107, 101, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} mockEVMKeeper.On("ApplyMessage", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: ret}, nil).Once() - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, - mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{VmError: "Error"}, nil).Once() + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, + mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{VmError: "Error"}, nil).Once() }, false, }, @@ -174,10 +174,10 @@ func (s *KeeperTestSuite) TestQueryERC20ForceFail() { "incorrect symbol res", func() { ret := []uint8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 67, 111, 105, 110, 32, 84, 111, 107, 101, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, - mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: ret}, nil).Once() - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, - mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: []uint8{0, 0}}, nil).Once() + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, + mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: ret}, nil).Once() + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, + mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: []uint8{0, 0}}, nil).Once() }, false, }, @@ -186,11 +186,11 @@ func (s *KeeperTestSuite) TestQueryERC20ForceFail() { func() { ret := []uint8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 67, 111, 105, 110, 32, 84, 111, 107, 101, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} retSymbol := []uint8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 67, 84, 75, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: ret}, nil).Once() - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: retSymbol}, nil).Once() - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{VmError: "Error"}, nil).Once() }, false, @@ -200,12 +200,12 @@ func (s *KeeperTestSuite) TestQueryERC20ForceFail() { func() { ret := []uint8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 67, 111, 105, 110, 32, 84, 111, 107, 101, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} retSymbol := []uint8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 67, 84, 75, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, - mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: ret}, nil).Once() - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, - mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: retSymbol}, nil).Once() - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, - mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: []uint8{0, 0}}, nil).Once() + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, + mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: ret}, nil).Once() + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, + mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: retSymbol}, nil).Once() + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, + mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: []uint8{0, 0}}, nil).Once() }, false, }, @@ -221,7 +221,7 @@ func (s *KeeperTestSuite) TestQueryERC20ForceFail() { authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), - &transferKeeper, + transferKeeper, ) s.network.App.SetErc20Keeper(erc20Keeper) @@ -265,6 +265,7 @@ func (s *KeeperTestSuite) TestQueryERC20Bytes32Fallback() { data[31] = 32 // Length (32 bytes) + // #nosec G115 -- textLen bounded by paddedLen data[63] = byte(textLen) // String data (padded to 32-byte boundary) @@ -286,11 +287,11 @@ func (s *KeeperTestSuite) TestQueryERC20Bytes32Fallback() { symbolData := createStringData("MKR") decimalsData := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18} - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "name"). + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "name"). Return(&evmtypes.MsgEthereumTxResponse{Ret: nameData}, nil).Once() - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "symbol"). + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "symbol"). Return(&evmtypes.MsgEthereumTxResponse{Ret: symbolData}, nil).Once() - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "decimals"). + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "decimals"). Return(&evmtypes.MsgEthereumTxResponse{Ret: decimalsData}, nil).Once() }, types.ERC20Data{Name: "Maker", Symbol: "MKR", Decimals: 18}, @@ -304,11 +305,11 @@ func (s *KeeperTestSuite) TestQueryERC20Bytes32Fallback() { decimalsData := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18} // First call tries string unpacking (will fail), then tries bytes32 (will succeed) - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "name"). + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "name"). Return(&evmtypes.MsgEthereumTxResponse{Ret: nameData}, nil).Once() - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "symbol"). + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "symbol"). Return(&evmtypes.MsgEthereumTxResponse{Ret: symbolData}, nil).Once() - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "decimals"). + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "decimals"). Return(&evmtypes.MsgEthereumTxResponse{Ret: decimalsData}, nil).Once() }, types.ERC20Data{Name: "Maker", Symbol: "MKR", Decimals: 18}, @@ -321,11 +322,11 @@ func (s *KeeperTestSuite) TestQueryERC20Bytes32Fallback() { symbolData := createBytes32Data("MKR") decimalsData := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18} - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "name"). + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "name"). Return(&evmtypes.MsgEthereumTxResponse{Ret: nameData}, nil).Once() - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "symbol"). + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "symbol"). Return(&evmtypes.MsgEthereumTxResponse{Ret: symbolData}, nil).Once() - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "decimals"). + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "decimals"). Return(&evmtypes.MsgEthereumTxResponse{Ret: decimalsData}, nil).Once() }, types.ERC20Data{Name: "Maker", Symbol: "MKR", Decimals: 18}, @@ -345,11 +346,11 @@ func (s *KeeperTestSuite) TestQueryERC20Bytes32Fallback() { decimalsData := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18} - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "name"). + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "name"). Return(&evmtypes.MsgEthereumTxResponse{Ret: nameData}, nil).Once() - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "symbol"). + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "symbol"). Return(&evmtypes.MsgEthereumTxResponse{Ret: symbolData}, nil).Once() - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "decimals"). + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "decimals"). Return(&evmtypes.MsgEthereumTxResponse{Ret: decimalsData}, nil).Once() }, types.ERC20Data{Name: "Maker", Symbol: "MKR", Decimals: 18}, @@ -358,7 +359,7 @@ func (s *KeeperTestSuite) TestQueryERC20Bytes32Fallback() { { "EVM call fails for name", func() { - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "name"). + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "name"). Return(nil, fmt.Errorf("EVM call failed")).Once() }, types.ERC20Data{}, @@ -369,7 +370,7 @@ func (s *KeeperTestSuite) TestQueryERC20Bytes32Fallback() { func() { invalidData := []byte{0xFF, 0xFF} // Invalid data that will fail both unpacking methods - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "name"). + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "name"). Return(&evmtypes.MsgEthereumTxResponse{Ret: invalidData}, nil).Once() }, types.ERC20Data{}, @@ -380,9 +381,9 @@ func (s *KeeperTestSuite) TestQueryERC20Bytes32Fallback() { func() { nameData := createStringData("Maker") - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "name"). + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "name"). Return(&evmtypes.MsgEthereumTxResponse{Ret: nameData}, nil).Once() - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "symbol"). + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, "symbol"). Return(nil, fmt.Errorf("EVM call failed")).Once() }, types.ERC20Data{}, @@ -401,7 +402,7 @@ func (s *KeeperTestSuite) TestQueryERC20Bytes32Fallback() { authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), - &transferKeeper, + transferKeeper, )) tc.malleate() diff --git a/tests/integration/x/erc20/test_genesis.go b/tests/integration/x/erc20/test_genesis.go index 3c5b5e02..c1a95274 100644 --- a/tests/integration/x/erc20/test_genesis.go +++ b/tests/integration/x/erc20/test_genesis.go @@ -7,7 +7,7 @@ import ( utiltx "github.com/cosmos/evm/testutil/tx" "github.com/cosmos/evm/x/erc20" "github.com/cosmos/evm/x/erc20/types" - transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" + transfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" "cosmossdk.io/math" ) diff --git a/tests/integration/x/erc20/test_ibc_callback.go b/tests/integration/x/erc20/test_ibc_callback.go index d404b79a..88c28164 100644 --- a/tests/integration/x/erc20/test_ibc_callback.go +++ b/tests/integration/x/erc20/test_ibc_callback.go @@ -6,24 +6,28 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/mock" + evm "github.com/cosmos/evm" "github.com/cosmos/evm/contracts" "github.com/cosmos/evm/crypto/ethsecp256k1" "github.com/cosmos/evm/testutil" "github.com/cosmos/evm/utils" "github.com/cosmos/evm/x/erc20/keeper" "github.com/cosmos/evm/x/erc20/types" + erc20mocks "github.com/cosmos/evm/x/erc20/types/mocks" "github.com/cosmos/evm/x/vm/statedb" evmtypes "github.com/cosmos/evm/x/vm/types" - transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" - channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types" - ibcgotesting "github.com/cosmos/ibc-go/v10/testing" - ibcmock "github.com/cosmos/ibc-go/v10/testing/mock" + transfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/v11/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/v11/modules/core/04-channel/types" + ibcgotesting "github.com/cosmos/ibc-go/v11/testing" + ibcmock "github.com/cosmos/ibc-go/v11/testing/mock" "cosmossdk.io/math" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" @@ -102,28 +106,28 @@ func (s *KeeperTestSuite) TestOnRecvPacketRegistered() { expCoins: coins, }, { - name: "error - invalid sender (no '1')", + name: "success - invalid sender (no '1')", malleate: func() { transfer := transfertypes.NewFungibleTokenPacketData(registeredDenom, "100", "evmos", ethsecpAddrCosmos, "") bz := transfertypes.ModuleCdc.MustMarshalJSON(&transfer) packet = channeltypes.NewPacket(bz, 100, transfertypes.PortID, sourceChannel, transfertypes.PortID, cosmosEVMChannel, timeoutHeight, 0) }, receiver: secpAddr, - ackSuccess: false, - checkBalances: false, + ackSuccess: true, + checkBalances: true, expErc20s: big.NewInt(0), expCoins: coins, }, { - name: "error - invalid sender (bad address)", + name: "success - invalid sender (bad address)", malleate: func() { transfer := transfertypes.NewFungibleTokenPacketData(registeredDenom, "100", "badba1sv9m0g7ycejwr3s369km58h5qe7xj77hvcxrms", ethsecpAddrCosmos, "") bz := transfertypes.ModuleCdc.MustMarshalJSON(&transfer) packet = channeltypes.NewPacket(bz, 100, transfertypes.PortID, sourceChannel, transfertypes.PortID, cosmosEVMChannel, timeoutHeight, 0) }, receiver: secpAddr, - ackSuccess: false, - checkBalances: false, + ackSuccess: true, + checkBalances: true, expErc20s: big.NewInt(0), expCoins: coins, }, @@ -281,6 +285,8 @@ func (s *KeeperTestSuite) TestOnRecvPacketRegistered() { denom := transfertypes.NewDenom(registeredDenom, hop) s.network.App.GetTransferKeeper().SetDenom(ctx, denom) + ibcKeeper := s.network.App.(evm.IBCKeeperProvider).GetIBCKeeper() + // Set Cosmos Channel channel := channeltypes.Channel{ State: channeltypes.INIT, @@ -288,10 +294,10 @@ func (s *KeeperTestSuite) TestOnRecvPacketRegistered() { Counterparty: channeltypes.NewCounterparty(transfertypes.PortID, sourceChannel), ConnectionHops: []string{sourceChannel}, } - s.network.App.GetIBCKeeper().ChannelKeeper.SetChannel(ctx, transfertypes.PortID, cosmosEVMChannel, channel) + ibcKeeper.ChannelKeeper.SetChannel(ctx, transfertypes.PortID, cosmosEVMChannel, channel) // Set Next Sequence Send - s.network.App.GetIBCKeeper().ChannelKeeper.SetNextSequenceSend(ctx, transfertypes.PortID, cosmosEVMChannel, 1) + ibcKeeper.ChannelKeeper.SetNextSequenceSend(ctx, transfertypes.PortID, cosmosEVMChannel, 1) tranasferKeeper := s.network.App.GetTransferKeeper() erc20Keeper := keeper.NewKeeper( @@ -302,7 +308,7 @@ func (s *KeeperTestSuite) TestOnRecvPacketRegistered() { s.network.App.GetBankKeeper(), s.network.App.GetEVMKeeper(), s.network.App.GetStakingKeeper(), - &tranasferKeeper, + tranasferKeeper, ) s.network.App.SetErc20Keeper(erc20Keeper) @@ -426,8 +432,8 @@ func (s *KeeperTestSuite) TestConvertCoinToERC20FromPacket() { ), ) s.Require().NoError(err) - - _, err = s.network.App.GetEVMKeeper().CallEVM(ctx, contracts.ERC20MinterBurnerDecimalsContract.ABI, s.keyring.GetAddr(0), contractAddr, true, nil, "mint", types.ModuleAddress, big.NewInt(10)) + stateDB := statedb.New(ctx, s.network.App.GetEVMKeeper(), statedb.NewEmptyTxConfig()) + _, err = s.network.App.GetEVMKeeper().CallEVM(ctx, stateDB, contracts.ERC20MinterBurnerDecimalsContract.ABI, s.keyring.GetAddr(0), contractAddr, true, false, nil, "mint", types.ModuleAddress, big.NewInt(10)) s.Require().NoError(err) return transfertypes.NewFungibleTokenPacketData(pair.Denom, "10", senderAddr, "", "") @@ -455,6 +461,56 @@ func (s *KeeperTestSuite) TestConvertCoinToERC20FromPacket() { } } +func (s *KeeperTestSuite) TestConvertCoinToERC20FromPacket_GasConfigPreserved() { + s.mintFeeCollector = true + defer func() { s.mintFeeCollector = false }() + s.SetupTest() + + contractAddr, err := s.setupRegisterERC20Pair(contractMinterBurner) + s.Require().NoError(err) + + ctx := s.network.GetContext() + id := s.network.App.GetErc20Keeper().GetTokenPairID(ctx, contractAddr.String()) + pair, found := s.network.App.GetErc20Keeper().GetTokenPair(ctx, id) + s.Require().True(found) + + // Replace EVMKeeper with a mock so we can capture the ctx forwarded to the EVM. + evmMock := new(erc20mocks.EVMKeeper) + customKeeper := keeper.NewKeeper( + s.network.App.GetKey(types.StoreKey), + s.network.App.AppCodec(), + authtypes.NewModuleAddress(govtypes.ModuleName), + s.network.App.GetAccountKeeper(), + s.network.App.GetBankKeeper(), + evmMock, + s.network.App.GetStakingKeeper(), + s.network.App.GetTransferKeeper(), + ) + + kvGas := storetypes.KVGasConfig() + transientGas := storetypes.TransientGasConfig() + ctx = ctx.WithKVGasConfig(kvGas).WithTransientKVGasConfig(transientGas) + + var capturedCtx sdk.Context + evmMock.On("CallEVM", + mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, + mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, + ).Run(func(args mock.Arguments) { + capturedCtx = args.Get(0).(sdk.Context) + }).Return((*evmtypes.MsgEthereumTxResponse)(nil), errors.New("mock evm error")) + evmMock.On("KVStoreKeys").Return(map[string]storetypes.StoreKey{}).Maybe() + + sender := sdk.AccAddress(s.keyring.GetAddr(0).Bytes()) + data := transfertypes.NewFungibleTokenPacketData(pair.Denom, "10", sender.String(), sender.String(), "") + + s.Require().NoError(customKeeper.ConvertCoinToERC20FromPacket(ctx, data)) + + // capturedCtx is only set if CallEVM was reached. A zeroed GasConfig would not + // equal kvGas, so these assertions also verify that CallEVM was called. + s.Require().Equal(kvGas, capturedCtx.KVGasConfig(), "KV gas config must not be zeroed before EVM call") + s.Require().Equal(transientGas, capturedCtx.TransientKVGasConfig(), "transient KV gas config must not be zeroed before EVM call") +} + func (s *KeeperTestSuite) TestOnAcknowledgementPacket() { var ( ctx sdk.Context @@ -563,7 +619,8 @@ func (s *KeeperTestSuite) TestOnAcknowledgementPacket() { ) s.Require().NoError(err) - _, err = s.network.App.GetEVMKeeper().CallEVM(ctx, contracts.ERC20MinterBurnerDecimalsContract.ABI, s.keyring.GetAddr(0), contractAddr, true, nil, "mint", types.ModuleAddress, big.NewInt(100)) + stateDB := statedb.New(ctx, s.network.App.GetEVMKeeper(), statedb.NewEmptyTxConfig()) + _, err = s.network.App.GetEVMKeeper().CallEVM(ctx, stateDB, contracts.ERC20MinterBurnerDecimalsContract.ABI, s.keyring.GetAddr(0), contractAddr, true, false, nil, "mint", types.ModuleAddress, big.NewInt(100)) s.Require().NoError(err) ack = channeltypes.NewErrorAcknowledgement(errors.New("error")) @@ -669,7 +726,8 @@ func (s *KeeperTestSuite) TestOnTimeoutPacket() { pair, _ = s.network.App.GetErc20Keeper().GetTokenPair(ctx, id) s.Require().NotNil(pair) - _, err = s.network.App.GetEVMKeeper().CallEVM(ctx, contracts.ERC20MinterBurnerDecimalsContract.ABI, s.keyring.GetAddr(0), contractAddr, true, nil, "mint", types.ModuleAddress, big.NewInt(100)) + stateDB := statedb.New(ctx, s.network.App.GetEVMKeeper(), statedb.NewEmptyTxConfig()) + _, err = s.network.App.GetEVMKeeper().CallEVM(ctx, stateDB, contracts.ERC20MinterBurnerDecimalsContract.ABI, s.keyring.GetAddr(0), contractAddr, true, false, nil, "mint", types.ModuleAddress, big.NewInt(100)) s.Require().NoError(err) // Fund module account with ATOM, ERC20 coins and IBC vouchers diff --git a/tests/integration/x/erc20/test_mint.go b/tests/integration/x/erc20/test_mint.go index 9a9a151c..209c418e 100644 --- a/tests/integration/x/erc20/test_mint.go +++ b/tests/integration/x/erc20/test_mint.go @@ -11,7 +11,6 @@ import ( func (s *KeeperTestSuite) TestMintingEnabled() { var ctx sdk.Context - sender := sdk.AccAddress(utiltx.GenerateAddress().Bytes()) receiver := sdk.AccAddress(utiltx.GenerateAddress().Bytes()) expPair := types.NewTokenPair(utiltx.GenerateAddress(), "coin", types.OWNER_MODULE) id := expPair.GetID() @@ -97,7 +96,7 @@ func (s *KeeperTestSuite) TestMintingEnabled() { tc.malleate() - pair, err := s.network.App.GetErc20Keeper().MintingEnabled(ctx, sender, receiver, expPair.Erc20Address) + pair, err := s.network.App.GetErc20Keeper().MintingEnabled(ctx, receiver, expPair.Erc20Address) if tc.expPass { s.Require().NoError(err) s.Require().Equal(expPair, pair) diff --git a/tests/integration/x/erc20/test_msg_server.go b/tests/integration/x/erc20/test_msg_server.go index 1d09f1dd..884f2401 100644 --- a/tests/integration/x/erc20/test_msg_server.go +++ b/tests/integration/x/erc20/test_msg_server.go @@ -9,8 +9,9 @@ import ( "github.com/stretchr/testify/mock" "go.uber.org/mock/gomock" + cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + "github.com/cosmos/evm/testutil/integration/base/factory" - "github.com/cosmos/evm/testutil/integration/evm/utils" "github.com/cosmos/evm/x/erc20/keeper" "github.com/cosmos/evm/x/erc20/types" erc20mocks "github.com/cosmos/evm/x/erc20/types/mocks" @@ -24,363 +25,121 @@ import ( govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ) -func (s *KeeperTestSuite) TestConvertERC20NativeERC20() { - var ( - contractAddr common.Address - coinName string - ) +// TestConvertERC20 tests the ConvertERC20 msg server method, +// focusing on message validation and address parsing +func (s *KeeperTestSuite) TestConvertERC20() { testCases := []struct { - name string - mint int64 - transfer int64 - malleate func(common.Address) - extra func() - contractType int - expPass bool - selfdestructed bool + name string + setup func() *types.MsgConvertERC20 + expPass bool }{ { - "ok - sufficient funds", - 100, - 10, - func(common.Address) {}, - func() {}, - contractMinterBurner, - true, - false, - }, - { - "ok - equal funds", - 10, - 10, - func(common.Address) {}, - func() {}, - contractMinterBurner, - true, - false, - }, - { - "fail - insufficient funds - callEVM", - 0, - 10, - func(common.Address) {}, - func() {}, - contractMinterBurner, - false, - false, - }, - { - "fail - minting disabled", - 100, - 10, - func(common.Address) { - params := types.DefaultParams() - params.EnableErc20 = false - err := utils.UpdateERC20Params( - utils.UpdateParamsInput{ - Tf: s.factory, - Network: s.network, - Pk: s.keyring.GetPrivKey(0), - Params: params, - }, - ) + "pass - valid message with proper addresses", + func() *types.MsgConvertERC20 { + contractAddr, err := s.setupRegisterERC20Pair(contractMinterBurner) s.Require().NoError(err) - }, - func() {}, - contractMinterBurner, - false, - false, - }, - { - "fail - direct balance manipulation contract", - 100, - 10, - func(common.Address) {}, - func() {}, - contractDirectBalanceManipulation, - false, - false, - }, - { - "pass - delayed malicious contract", - 10, - 10, - func(common.Address) {}, - func() {}, - contractMaliciousDelayed, - true, - false, - }, - { - "fail - negative transfer contract", - 10, - -10, - func(common.Address) {}, - func() {}, - contractMinterBurner, - false, - false, - }, - { - "fail - force evm fail", - 100, - 10, - func(common.Address) {}, - func() { - mockEVMKeeper := &erc20mocks.EVMKeeper{} - transferKeeper := s.network.App.GetTransferKeeper() - erc20Keeper := keeper.NewKeeper( - s.network.App.GetKey("erc20"), s.network.App.AppCodec(), - authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), - s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), - &transferKeeper, - ) - s.network.App.SetErc20Keeper(erc20Keeper) - existingAcc := &statedb.Account{Nonce: uint64(1), Balance: uint256.NewInt(1)} - balance := make([]uint8, 32) - mockEVMKeeper.On("EstimateGasInternal", mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.EstimateGasResponse{Gas: uint64(200)}, nil) - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, - mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: balance}, nil).Once() - mockEVMKeeper.On("CallEVMWithData", mock.Anything, mock.Anything, mock.Anything, mock.Anything, - mock.Anything, mock.Anything).Return(nil, fmt.Errorf("forced ApplyMessage error")) - mockEVMKeeper.On("GetAccountWithoutBalance", mock.Anything, mock.Anything).Return(existingAcc, nil) - mockEVMKeeper.On("IsContract", mock.Anything, mock.Anything).Return(true) - }, - contractMinterBurner, - false, - false, - }, - { - "fail - force get balance fail", - 100, - 10, - func(common.Address) {}, - func() { - mockEVMKeeper := &erc20mocks.EVMKeeper{} - transferKeeper := s.network.App.GetTransferKeeper() - erc20Keeper := keeper.NewKeeper( - s.network.App.GetKey("erc20"), s.network.App.AppCodec(), - authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), - s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), - &transferKeeper, - ) - s.network.App.SetErc20Keeper(erc20Keeper) + sender := s.keyring.GetAccAddr(0) + senderHex := s.keyring.GetAddr(0) - existingAcc := &statedb.Account{Nonce: uint64(1), Balance: uint256.NewInt(1)} - balance := make([]uint8, 32) - balance[31] = uint8(1) - mockEVMKeeper.On("EstimateGasInternal", mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.EstimateGasResponse{Gas: uint64(200)}, nil) - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: balance}, nil).Twice() - mockEVMKeeper.On("CallEVMWithData", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("forced balance error")) - mockEVMKeeper.On("GetAccountWithoutBalance", mock.Anything, mock.Anything).Return(existingAcc, nil) - mockEVMKeeper.On("IsContract", mock.Anything, mock.Anything).Return(true) + _, err = s.MintERC20Token(contractAddr, senderHex, big.NewInt(100)) + s.Require().NoError(err) + + return types.NewMsgConvertERC20( + math.NewInt(10), + sender, + contractAddr, + senderHex, + ) }, - contractMinterBurner, - false, - false, + true, }, { - "fail - force transfer unpack fail", - 100, - 10, - func(common.Address) {}, - func() { - mockEVMKeeper := &erc20mocks.EVMKeeper{} - transferKeeper := s.network.App.GetTransferKeeper() - erc20Keeper := keeper.NewKeeper( - s.network.App.GetKey("erc20"), s.network.App.AppCodec(), - authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), - s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), - &transferKeeper, - ) - s.network.App.SetErc20Keeper(erc20Keeper) + "fail - invalid receiver bech32 address format", + func() *types.MsgConvertERC20 { + contractAddr, err := s.setupRegisterERC20Pair(contractMinterBurner) + s.Require().NoError(err) - existingAcc := &statedb.Account{Nonce: uint64(1), Balance: uint256.NewInt(1)} - balance := make([]uint8, 32) - mockEVMKeeper.On("EstimateGasInternal", mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.EstimateGasResponse{Gas: uint64(200)}, nil) - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, - mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: balance}, nil).Once() - mockEVMKeeper.On("CallEVMWithData", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{}, nil) - mockEVMKeeper.On("GetAccountWithoutBalance", mock.Anything, mock.Anything).Return(existingAcc, nil) - mockEVMKeeper.On("IsContract", mock.Anything, mock.Anything).Return(true) - }, - contractMinterBurner, - false, - false, - }, + sender := s.keyring.GetAccAddr(0) + senderHex := s.keyring.GetAddr(0) - { - "fail - force invalid transfer fail", - 100, - 10, - func(common.Address) {}, - func() { - mockEVMKeeper := &erc20mocks.EVMKeeper{} - transferKeeper := s.network.App.GetTransferKeeper() - erc20Keeper := keeper.NewKeeper( - s.network.App.GetKey("erc20"), s.network.App.AppCodec(), - authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), - s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), - &transferKeeper, - ) - s.network.App.SetErc20Keeper(erc20Keeper) + _, err = s.MintERC20Token(contractAddr, senderHex, big.NewInt(100)) + s.Require().NoError(err) - existingAcc := &statedb.Account{Nonce: uint64(1), Balance: uint256.NewInt(1)} - balance := make([]uint8, 32) - mockEVMKeeper.On("EstimateGasInternal", mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.EstimateGasResponse{Gas: uint64(200)}, nil) - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, - mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: balance}, nil).Once() - mockEVMKeeper.On("CallEVMWithData", mock.Anything, mock.Anything, mock.Anything, mock.Anything, - mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: balance}, nil) - mockEVMKeeper.On("GetAccountWithoutBalance", mock.Anything, mock.Anything).Return(existingAcc, nil) - mockEVMKeeper.On("IsContract", mock.Anything, mock.Anything).Return(true) - }, - contractMinterBurner, - false, - false, - }, - { - "fail - force mint fail", - 100, - 10, - func(common.Address) {}, - func() { - ctrl := gomock.NewController(s.T()) - mockBankKeeper := erc20mocks.NewMockBankKeeper(ctrl) - transferKeeper := s.network.App.GetTransferKeeper() - erc20Keeper := keeper.NewKeeper( - s.network.App.GetKey("erc20"), s.network.App.AppCodec(), - authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), - mockBankKeeper, s.network.App.GetEVMKeeper(), s.network.App.GetStakingKeeper(), - &transferKeeper, + msg := types.NewMsgConvertERC20( + math.NewInt(10), + sender, + contractAddr, + senderHex, ) - s.network.App.SetErc20Keeper(erc20Keeper) - - mockBankKeeper.EXPECT().MintCoins(gomock.Any(), gomock.Any(), gomock.Any()).Return(fmt.Errorf("failed to mint")).AnyTimes() - mockBankKeeper.EXPECT().SendCoinsFromModuleToAccount(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(fmt.Errorf("failed to unescrow")).AnyTimes() - mockBankKeeper.EXPECT().BlockedAddr(gomock.Any()).Return(false).AnyTimes() - mockBankKeeper.EXPECT().GetBalance(gomock.Any(), gomock.Any(), gomock.Any()).Return(sdk.Coin{Denom: "coin", Amount: math.OneInt()}).AnyTimes() + // Create invalid bech32 address with valid length but invalid format + // Using wrong prefix or invalid checksum + msg.Receiver = "cosmos100000000000000000000000000000000" + return msg }, - contractMinterBurner, - false, false, }, { - "fail - force send minted fail", - 100, - 10, - func(common.Address) {}, - func() { - ctrl := gomock.NewController(s.T()) - mockBankKeeper := erc20mocks.NewMockBankKeeper(ctrl) - transferKeeper := s.network.App.GetTransferKeeper() - erc20Keeper := keeper.NewKeeper( - s.network.App.GetKey("erc20"), s.network.App.AppCodec(), - authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), - mockBankKeeper, s.network.App.GetEVMKeeper(), s.network.App.GetStakingKeeper(), - &transferKeeper, - ) - s.network.App.SetErc20Keeper(erc20Keeper) + "fail - invalid sender hex address format", + func() *types.MsgConvertERC20 { + contractAddr, err := s.setupRegisterERC20Pair(contractMinterBurner) + s.Require().NoError(err) - mockBankKeeper.EXPECT().MintCoins(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) - mockBankKeeper.EXPECT().SendCoinsFromModuleToAccount(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(fmt.Errorf("failed to unescrow")) - mockBankKeeper.EXPECT().BlockedAddr(gomock.Any()).Return(false) - mockBankKeeper.EXPECT().GetBalance(gomock.Any(), gomock.Any(), gomock.Any()).Return(sdk.Coin{Denom: "coin", Amount: math.OneInt()}) + sender := s.keyring.GetAccAddr(0) + senderHex := s.keyring.GetAddr(0) + + _, err = s.MintERC20Token(contractAddr, senderHex, big.NewInt(100)) + s.Require().NoError(err) + + msg := types.NewMsgConvertERC20( + math.NewInt(10), + sender, + contractAddr, + senderHex, + ) + // Create invalid hex address - not a valid hex string + msg.Sender = "0xZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + return msg }, - contractMinterBurner, - false, false, }, { - "fail - force bank balance fail", - 100, - 10, - func(common.Address) {}, - func() { - ctrl := gomock.NewController(s.T()) - mockBankKeeper := erc20mocks.NewMockBankKeeper(ctrl) - transferKeeper := s.network.App.GetTransferKeeper() - erc20Keeper := keeper.NewKeeper( - s.network.App.GetKey("erc20"), s.network.App.AppCodec(), - authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), - mockBankKeeper, s.network.App.GetEVMKeeper(), s.network.App.GetStakingKeeper(), - &transferKeeper, + "fail - invalid contract hex address format", + func() *types.MsgConvertERC20 { + sender := s.keyring.GetAccAddr(0) + senderHex := s.keyring.GetAddr(0) + + msg := types.NewMsgConvertERC20( + math.NewInt(10), + sender, + common.HexToAddress("0x0"), + senderHex, ) - s.network.App.SetErc20Keeper(erc20Keeper) - - mockBankKeeper.EXPECT().MintCoins(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) - mockBankKeeper.EXPECT().SendCoinsFromModuleToAccount(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) - mockBankKeeper.EXPECT().BlockedAddr(gomock.Any()).Return(false) - mockBankKeeper.EXPECT().GetBalance(gomock.Any(), gomock.Any(), gomock.Any()).Return(sdk.Coin{Denom: coinName, Amount: math.OneInt()}).AnyTimes() + // Create invalid hex address - not a valid hex string + msg.ContractAddress = "0xGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG" + return msg }, - contractMinterBurner, - false, false, }, } + for _, tc := range testCases { - s.Run(fmt.Sprintf("Case %s", tc.name), func() { - var err error + s.Run(tc.name, func() { s.mintFeeCollector = true - defer func() { - s.mintFeeCollector = false - }() + defer func() { s.mintFeeCollector = false }() s.SetupTest() - - contractAddr, err = s.setupRegisterERC20Pair(tc.contractType) - s.Require().NoError(err) - - tc.malleate(contractAddr) - s.Require().NotNil(contractAddr) - - coinName = types.CreateDenom(contractAddr.String()) - sender := s.keyring.GetAccAddr(0) - - _, err = s.MintERC20Token(contractAddr, s.keyring.GetAddr(0), big.NewInt(tc.mint)) - s.Require().NoError(err) - // update context with latest committed changes - - tc.extra() - - convertERC20Msg := types.NewMsgConvertERC20( - math.NewInt(tc.transfer), - sender, - contractAddr, - s.keyring.GetAddr(0), - ) - - ctx := s.network.GetContext() + msg := tc.setup() if tc.expPass { - _, err = s.factory.CommitCosmosTx(s.keyring.GetPrivKey(0), factory.CosmosTxArgs{Msgs: []sdk.Msg{convertERC20Msg}}) + _, err := s.network.App.GetErc20Keeper().ConvertERC20(s.network.GetContext(), msg) s.Require().NoError(err, tc.name) - - cosmosBalance := s.network.App.GetBankKeeper().GetBalance(ctx, sender, coinName) - - acc := s.network.App.GetEVMKeeper().GetAccountWithoutBalance(ctx, contractAddr) - if tc.selfdestructed { - s.Require().Nil(acc, "expected contract to be destroyed") - } else { - s.Require().NotNil(acc) - } - - isContract := s.network.App.GetEVMKeeper().IsContract(s.network.GetContext(), contractAddr) - if tc.selfdestructed || !isContract { - id := s.network.App.GetErc20Keeper().GetTokenPairID(ctx, contractAddr.String()) - _, found := s.network.App.GetErc20Keeper().GetTokenPair(ctx, id) - s.Require().False(found) - } else { - s.Require().Equal(cosmosBalance.Amount, math.NewInt(tc.transfer)) - } } else { - _, err = s.network.App.GetErc20Keeper().ConvertERC20(ctx, convertERC20Msg) + _, err := s.network.App.GetErc20Keeper().ConvertERC20(s.network.GetContext(), msg) s.Require().Error(err, tc.name) } }) } - s.mintFeeCollector = false } func (s *KeeperTestSuite) TestConvertNativeERC20ToEVMERC20() { @@ -440,17 +199,17 @@ func (s *KeeperTestSuite) TestConvertNativeERC20ToEVMERC20() { s.network.App.GetKey("erc20"), s.network.App.AppCodec(), authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), - &transferKeeper, + transferKeeper, ) s.network.App.SetErc20Keeper(erc20Keeper) existingAcc := &statedb.Account{Nonce: uint64(1), Balance: uint256.NewInt(1)} balance := make([]uint8, 32) mockEVMKeeper.On("EstimateGasInternal", mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.EstimateGasResponse{Gas: uint64(200)}, nil) - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, - mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: balance}, fmt.Errorf("forced ApplyMessage error")).Once() - mockEVMKeeper.On("CallEVMWithData", mock.Anything, mock.Anything, mock.Anything, mock.Anything, - mock.Anything, mock.Anything).Return(nil, fmt.Errorf("forced ApplyMessage error")) + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, + mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: balance}, fmt.Errorf("forced ApplyMessage error")).Once() + mockEVMKeeper.On("CallEVMWithData", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, + mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("forced ApplyMessage error")) mockEVMKeeper.On("GetAccountWithoutBalance", mock.Anything, mock.Anything).Return(existingAcc, nil) mockEVMKeeper.On("IsContract", mock.Anything, mock.Anything).Return(true) }, @@ -470,7 +229,7 @@ func (s *KeeperTestSuite) TestConvertNativeERC20ToEVMERC20() { s.network.App.GetKey("erc20"), s.network.App.AppCodec(), authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), - &transferKeeper, + transferKeeper, ) s.network.App.SetErc20Keeper(erc20Keeper) @@ -478,8 +237,11 @@ func (s *KeeperTestSuite) TestConvertNativeERC20ToEVMERC20() { balance := make([]uint8, 32) balance[31] = uint8(1) mockEVMKeeper.On("EstimateGasInternal", mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.EstimateGasResponse{Gas: uint64(200)}, nil) - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: balance}, nil).Times(3) - mockEVMKeeper.On("CallEVMWithData", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("forced balance error")) + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, + mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: balance}, nil).Times(3) + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, + mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: balance}, nil).Maybe() + mockEVMKeeper.On("CallEVMWithData", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("forced balance error")) mockEVMKeeper.On("GetAccountWithoutBalance", mock.Anything, mock.Anything).Return(existingAcc, nil) mockEVMKeeper.On("IsContract", mock.Anything, mock.Anything).Return(true) }, @@ -499,16 +261,16 @@ func (s *KeeperTestSuite) TestConvertNativeERC20ToEVMERC20() { s.network.App.GetKey("erc20"), s.network.App.AppCodec(), authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), - &transferKeeper, + transferKeeper, ) s.network.App.SetErc20Keeper(erc20Keeper) existingAcc := &statedb.Account{Nonce: uint64(1), Balance: uint256.NewInt(1)} balance := make([]uint8, 32) mockEVMKeeper.On("EstimateGasInternal", mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.EstimateGasResponse{Gas: uint64(200)}, nil) - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, - mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: balance}, nil).Twice() - mockEVMKeeper.On("CallEVMWithData", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{}, nil) + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, + mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: balance}, nil).Twice() + mockEVMKeeper.On("CallEVMWithData", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{}, nil) mockEVMKeeper.On("GetAccountWithoutBalance", mock.Anything, mock.Anything).Return(existingAcc, nil) mockEVMKeeper.On("IsContract", mock.Anything, mock.Anything).Return(true) }, @@ -529,16 +291,16 @@ func (s *KeeperTestSuite) TestConvertNativeERC20ToEVMERC20() { s.network.App.GetKey("erc20"), s.network.App.AppCodec(), authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), - &transferKeeper, + transferKeeper, ) s.network.App.SetErc20Keeper(erc20Keeper) existingAcc := &statedb.Account{Nonce: uint64(1), Balance: uint256.NewInt(1)} balance := make([]uint8, 32) mockEVMKeeper.On("EstimateGasInternal", mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.EstimateGasResponse{Gas: uint64(200)}, nil) - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: balance}, nil).Twice() - mockEVMKeeper.On("CallEVMWithData", mock.Anything, mock.Anything, mock.Anything, mock.Anything, + mockEVMKeeper.On("CallEVMWithData", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: balance}, nil) mockEVMKeeper.On("GetAccountWithoutBalance", mock.Anything, mock.Anything).Return(existingAcc, nil) mockEVMKeeper.On("IsContract", mock.Anything, mock.Anything).Return(true) @@ -560,7 +322,7 @@ func (s *KeeperTestSuite) TestConvertNativeERC20ToEVMERC20() { s.network.App.GetKey("erc20"), s.network.App.AppCodec(), authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), mockBankKeeper, s.network.App.GetEVMKeeper(), s.network.App.GetStakingKeeper(), - &transferKeeper, + transferKeeper, ) s.network.App.SetErc20Keeper(erc20Keeper) @@ -568,6 +330,7 @@ func (s *KeeperTestSuite) TestConvertNativeERC20ToEVMERC20() { mockBankKeeper.EXPECT().SendCoinsFromAccountToModule(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(fmt.Errorf("failed to unescrow")).AnyTimes() mockBankKeeper.EXPECT().BlockedAddr(gomock.Any()).Return(false).AnyTimes() mockBankKeeper.EXPECT().GetBalance(gomock.Any(), gomock.Any(), gomock.Any()).Return(sdk.Coin{Denom: "coin", Amount: math.OneInt()}).AnyTimes() + mockBankKeeper.EXPECT().IsSendEnabledCoin(gomock.Any(), gomock.Any()).Return(true).AnyTimes() }, contractMinterBurner, false, @@ -586,13 +349,14 @@ func (s *KeeperTestSuite) TestConvertNativeERC20ToEVMERC20() { s.network.App.GetKey("erc20"), s.network.App.AppCodec(), authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), mockBankKeeper, s.network.App.GetEVMKeeper(), s.network.App.GetStakingKeeper(), - &transferKeeper, + transferKeeper, ) s.network.App.SetErc20Keeper(erc20Keeper) mockBankKeeper.EXPECT().SendCoinsFromAccountToModule(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) mockBankKeeper.EXPECT().BurnCoins(gomock.Any(), gomock.Any(), gomock.Any()).Return(fmt.Errorf("failed to burn")).AnyTimes() mockBankKeeper.EXPECT().BlockedAddr(gomock.Any()).Return(false) + mockBankKeeper.EXPECT().IsSendEnabledCoin(gomock.Any(), gomock.Any()).Return(true).AnyTimes() }, contractMinterBurner, false, @@ -707,3 +471,103 @@ func (s *KeeperTestSuite) TestUpdateParams() { }) } } + +// TestUpdateParamsAuthority verifies that the erc20 keeper resolves the +// authority through the consensus AuthorityParams when set, and otherwise +// falls back to the keeper's authority. Covers UpdateParams, RegisterERC20 +// (when permissionless registration is disabled) and ToggleConversion, all +// of which share the same validateAuthority helper. +func (s *KeeperTestSuite) TestUpdateParamsAuthority() { + s.SetupTest() + + keeperAuthority := authtypes.NewModuleAddress(govtypes.ModuleName).String() + overrideAuthority := sdk.AccAddress("override_authority___").String() + s.Require().NotEqual(keeperAuthority, overrideAuthority) + + s.Run("UpdateParams: fallback to keeper authority when consensus authority is unset", func() { + ctx := s.network.GetContext() + + _, err := s.network.App.GetErc20Keeper().UpdateParams(ctx, &types.MsgUpdateParams{ + Authority: keeperAuthority, + Params: types.DefaultParams(), + }) + s.Require().NoError(err) + + _, err = s.network.App.GetErc20Keeper().UpdateParams(ctx, &types.MsgUpdateParams{ + Authority: overrideAuthority, + Params: types.DefaultParams(), + }) + s.Require().Error(err) + s.Require().Contains(err.Error(), "invalid authority") + }) + + s.Run("UpdateParams: consensus authority takes precedence over keeper authority", func() { + ctx := s.network.GetContext().WithConsensusParams(cmtproto.ConsensusParams{ + Authority: &cmtproto.AuthorityParams{Authority: overrideAuthority}, + }) + + _, err := s.network.App.GetErc20Keeper().UpdateParams(ctx, &types.MsgUpdateParams{ + Authority: overrideAuthority, + Params: types.DefaultParams(), + }) + s.Require().NoError(err) + + _, err = s.network.App.GetErc20Keeper().UpdateParams(ctx, &types.MsgUpdateParams{ + Authority: keeperAuthority, + Params: types.DefaultParams(), + }) + s.Require().Error(err) + s.Require().Contains(err.Error(), "invalid authority") + }) + + s.Run("RegisterERC20: consensus authority takes precedence when permissionless registration is disabled", func() { + s.SetupTest() + baseCtx := s.network.GetContext() + s.network.App.GetErc20Keeper().SetPermissionlessRegistration(baseCtx, false) + + ctx := s.network.GetContext().WithConsensusParams(cmtproto.ConsensusParams{ + Authority: &cmtproto.AuthorityParams{Authority: overrideAuthority}, + }) + + // keeper authority is rejected once consensus authority is set + _, err := s.network.App.GetErc20Keeper().RegisterERC20(ctx, &types.MsgRegisterERC20{ + Signer: keeperAuthority, + Erc20Addresses: []string{}, + }) + s.Require().Error(err) + s.Require().Contains(err.Error(), "invalid authority") + + // consensus authority is accepted (validation passes; an empty + // erc20 address list short-circuits with no further error). + _, err = s.network.App.GetErc20Keeper().RegisterERC20(ctx, &types.MsgRegisterERC20{ + Signer: overrideAuthority, + Erc20Addresses: []string{}, + }) + s.Require().NoError(err) + }) + + s.Run("ToggleConversion: consensus authority takes precedence over keeper authority", func() { + s.SetupTest() + ctx := s.network.GetContext().WithConsensusParams(cmtproto.ConsensusParams{ + Authority: &cmtproto.AuthorityParams{Authority: overrideAuthority}, + }) + + // keeper authority is rejected by validateAuthority once consensus + // authority is set + _, err := s.network.App.GetErc20Keeper().ToggleConversion(ctx, &types.MsgToggleConversion{ + Authority: keeperAuthority, + Token: "missing", + }) + s.Require().Error(err) + s.Require().Contains(err.Error(), "invalid authority") + + // consensus authority is accepted; token-pair lookup fails afterwards, + // proving authority validation succeeded. + _, err = s.network.App.GetErc20Keeper().ToggleConversion(ctx, &types.MsgToggleConversion{ + Authority: overrideAuthority, + Token: "missing", + }) + s.Require().Error(err) + s.Require().NotContains(err.Error(), "invalid authority") + }) +} diff --git a/tests/integration/x/erc20/test_proposals.go b/tests/integration/x/erc20/test_proposals.go index 997bd9d8..2ce7cd5f 100644 --- a/tests/integration/x/erc20/test_proposals.go +++ b/tests/integration/x/erc20/test_proposals.go @@ -163,12 +163,12 @@ func (s *KeeperTestSuite) TestRegisterERC20() { s.network.App.GetKey("erc20"), s.network.App.AppCodec(), authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), - &transferKeeper, + transferKeeper, ) s.network.App.SetErc20Keeper(erc20Keeper) mockEVMKeeper.On("EstimateGasInternal", mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.EstimateGasResponse{Gas: uint64(200)}, nil) - mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("forced CallEVM error")) + mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("forced CallEVM error")) mockEVMKeeper.On("ApplyMessage", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("forced ApplyMessage error")) }, s.keyring.GetAccAddr(0).String(), diff --git a/tests/integration/x/feemarket/test_abci.go b/tests/integration/x/feemarket/test_abci.go index df7a0f5e..04282efe 100644 --- a/tests/integration/x/feemarket/test_abci.go +++ b/tests/integration/x/feemarket/test_abci.go @@ -3,8 +3,7 @@ package feemarket import ( "github.com/cosmos/evm/testutil/integration/evm/network" - storetypes "cosmossdk.io/store/types" - + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -31,8 +30,7 @@ func (s *KeeperTestSuite) TestEndBlock() { false, func() { meter := storetypes.NewGasMeter(uint64(1000000000)) - ctx = ctx.WithBlockGasMeter(meter) - nw.App.GetFeeMarketKeeper().SetTransientBlockGasWanted(ctx, 5000000) + ctx = ctx.WithBlockGasMeter(meter).WithBlockGasWanted(5000000) }, uint64(2500000), }, diff --git a/tests/integration/x/feemarket/test_msg_server.go b/tests/integration/x/feemarket/test_msg_server.go index b5b42850..80b36ed6 100644 --- a/tests/integration/x/feemarket/test_msg_server.go +++ b/tests/integration/x/feemarket/test_msg_server.go @@ -1,6 +1,8 @@ package feemarket import ( + cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + "github.com/cosmos/evm/testutil/integration/evm/network" "github.com/cosmos/evm/x/feemarket/types" @@ -50,3 +52,50 @@ func (s *KeeperTestSuite) TestUpdateParams() { }) } } + +// TestUpdateParamsAuthority verifies that the feemarket keeper resolves the +// authority through the consensus AuthorityParams when set, and otherwise +// falls back to the keeper's authority. +func (s *KeeperTestSuite) TestUpdateParamsAuthority() { + nw := network.NewUnitTestNetwork(s.create, s.options...) + + keeperAuthority := authtypes.NewModuleAddress(govtypes.ModuleName).String() + overrideAuthority := sdk.AccAddress("override_authority___").String() + s.Require().NotEqual(keeperAuthority, overrideAuthority) + + s.Run("fallback to keeper authority when consensus authority is unset", func() { + ctx := nw.GetContext() + + _, err := nw.App.GetFeeMarketKeeper().UpdateParams(ctx, &types.MsgUpdateParams{ + Authority: keeperAuthority, + Params: types.DefaultParams(), + }) + s.Require().NoError(err) + + _, err = nw.App.GetFeeMarketKeeper().UpdateParams(ctx, &types.MsgUpdateParams{ + Authority: overrideAuthority, + Params: types.DefaultParams(), + }) + s.Require().Error(err) + s.Require().Contains(err.Error(), "invalid authority") + }) + + s.Run("consensus authority takes precedence over keeper authority", func() { + ctx := nw.GetContext().WithConsensusParams(cmtproto.ConsensusParams{ + Authority: &cmtproto.AuthorityParams{Authority: overrideAuthority}, + }) + + _, err := nw.App.GetFeeMarketKeeper().UpdateParams(ctx, &types.MsgUpdateParams{ + Authority: overrideAuthority, + Params: types.DefaultParams(), + }) + s.Require().NoError(err) + + _, err = nw.App.GetFeeMarketKeeper().UpdateParams(ctx, &types.MsgUpdateParams{ + Authority: keeperAuthority, + Params: types.DefaultParams(), + }) + s.Require().Error(err) + s.Require().Contains(err.Error(), "invalid authority") + }) +} diff --git a/tests/integration/x/ibc/callbacks/test_keeper.go b/tests/integration/x/ibc/callbacks/test_keeper.go index ec3c91f2..dc143dc7 100644 --- a/tests/integration/x/ibc/callbacks/test_keeper.go +++ b/tests/integration/x/ibc/callbacks/test_keeper.go @@ -7,11 +7,11 @@ import ( "github.com/cosmos/evm/testutil/keyring" "github.com/cosmos/evm/x/ibc/callbacks/types" - cbtypes "github.com/cosmos/ibc-go/v10/modules/apps/callbacks/types" - transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" - channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types" - ibcerrors "github.com/cosmos/ibc-go/v10/modules/core/errors" + cbtypes "github.com/cosmos/ibc-go/v11/modules/apps/callbacks/types" + transfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/v11/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/v11/modules/core/04-channel/types" + ibcerrors "github.com/cosmos/ibc-go/v11/modules/core/errors" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -27,37 +27,54 @@ func (s *KeeperTestSuite) TestOnRecvPacket() { ) testCases := []struct { name string - malleate func() + malleate func() uint64 expErr error }{ + { + "packet data is transfer with receiver account already existing", + func() uint64 { + receiverAcc, err := sdk.AccAddressFromBech32(receiver) + s.Require().NoError(err) + + // Create and set the account + acc := s.network.App.GetAccountKeeper().NewAccountWithAddress(ctx, receiverAcc) + s.network.App.GetAccountKeeper().SetAccount(ctx, acc) + s.Require().True(s.network.App.GetAccountKeeper().HasAccount(ctx, receiverAcc)) + return acc.GetAccountNumber() + }, + types.ErrContractHasNoCode, + }, { "contract code does not exist", - func() {}, + func() uint64 { return 0 }, types.ErrContractHasNoCode, }, { "packet data is not transfer", - func() { + func() uint64 { packet.Data = []byte("not a transfer packet") + return 0 }, - ibcerrors.ErrInvalidType, + ibcerrors.ErrInvalidType, // This will be wrapped by the transfer module }, { "packet data is transfer but receiver is not isolated address", - func() { + func() uint64 { receiver = senderKey.AccAddr.String() // not an isolated address transferData.Receiver = receiver transferDataBz := transferData.GetBytes() packet.Data = transferDataBz + return 0 }, types.ErrInvalidReceiverAddress, }, { "packet data is transfer but callback data is not valid", - func() { + func() uint64 { transferData.Memo = fmt.Sprintf(`{"dest_callback": {"address": 10, "calldata": "%x"}}`, []byte("calldata")) transferDataBz := transferData.GetBytes() packet.Data = transferDataBz + return 0 }, cbtypes.ErrInvalidCallbackData, }, @@ -93,9 +110,13 @@ func (s *KeeperTestSuite) TestOnRecvPacket() { ) ack := channeltypes.NewResultAcknowledgement([]byte{1}) - tc.malleate() - + originalAccNumber := tc.malleate() err := s.network.App.GetCallbackKeeper().IBCReceivePacketCallback(ctx, packet, ack, contract.Hex(), transfertypes.V1) + if originalAccNumber != 0 { + acc := s.network.App.GetAccountKeeper().GetAccount(ctx, sdk.MustAccAddressFromBech32(receiver)) + s.Require().NotNil(acc) + s.Require().Equal(originalAccNumber, acc.GetAccountNumber(), "account number should not be modified") + } if tc.expErr != nil { s.Require().Contains(err.Error(), tc.expErr.Error(), "expected error: %s, got: %s", tc.expErr.Error(), err.Error()) } else { diff --git a/tests/integration/x/ibc/test_keeper.go b/tests/integration/x/ibc/test_keeper.go index 71a21f68..7a41181c 100644 --- a/tests/integration/x/ibc/test_keeper.go +++ b/tests/integration/x/ibc/test_keeper.go @@ -18,11 +18,11 @@ import ( testutiltypes "github.com/cosmos/evm/testutil/types" erc20types "github.com/cosmos/evm/x/erc20/types" evmtypes "github.com/cosmos/evm/x/vm/types" - transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" - channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types" - porttypes "github.com/cosmos/ibc-go/v10/modules/core/05-port/types" - "github.com/cosmos/ibc-go/v10/modules/core/exported" + transfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/v11/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/v11/modules/core/04-channel/types" + porttypes "github.com/cosmos/ibc-go/v11/modules/core/05-port/types" + "github.com/cosmos/ibc-go/v11/modules/core/exported" "cosmossdk.io/math" @@ -42,8 +42,6 @@ type KeeperTestSuite struct { otherDenom string } -var timeoutHeight = clienttypes.NewHeight(1000, 1000) - func NewKeeperTestSuite(create network.CreateEvmApp, options ...network.ConfigOption) *KeeperTestSuite { return &KeeperTestSuite{ create: create, @@ -76,6 +74,8 @@ type MockChannelKeeper struct { mock.Mock } +func (b *MockChannelKeeper) SetICS4Wrapper(_ porttypes.ICS4Wrapper) {} + func (b *MockChannelKeeper) GetChannel(ctx sdk.Context, srcPort, srcChan string) (channel channeltypes.Channel, found bool) { args := b.Called(mock.Anything, mock.Anything, mock.Anything) return args.Get(0).(channeltypes.Channel), true @@ -95,6 +95,26 @@ func (b *MockChannelKeeper) GetAllChannelsWithPortPrefix(ctx sdk.Context, portPr return []channeltypes.IdentifiedChannel{} } +func (b *MockChannelKeeper) WriteAcknowledgement(_ sdk.Context, _ exported.PacketI, _ exported.Acknowledgement) error { + return nil +} + +func (b *MockChannelKeeper) GetAppVersion(ctx sdk.Context, portID string, channelID string) (string, bool) { + return "", false +} + +func (b *MockChannelKeeper) SendPacket( + ctx sdk.Context, + sourcePort string, + sourceChannel string, + timeoutHeight clienttypes.Height, + timeoutTimestamp uint64, + data []byte, +) (sequence uint64, err error) { + // _ = b.Called(mock.Anything, mock.Anything, mock.Anything) + return 0, nil +} + var _ porttypes.ICS4Wrapper = &MockICS4Wrapper{} type MockICS4Wrapper struct { diff --git a/tests/integration/x/ibc/test_msg_server.go b/tests/integration/x/ibc/test_msg_server.go deleted file mode 100644 index 56a9599c..00000000 --- a/tests/integration/x/ibc/test_msg_server.go +++ /dev/null @@ -1,517 +0,0 @@ -package ibc - -import ( - "fmt" - "strings" - - "github.com/stretchr/testify/mock" - - "github.com/cosmos/evm/testutil/integration/evm/utils" - testutils "github.com/cosmos/evm/testutil/integration/evm/utils" - "github.com/cosmos/evm/testutil/keyring" - erc20types "github.com/cosmos/evm/x/erc20/types" - transferkeeper "github.com/cosmos/evm/x/ibc/transfer/keeper" - evmtypes "github.com/cosmos/evm/x/vm/types" - "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types" - - "cosmossdk.io/math" - - "github.com/cosmos/cosmos-sdk/runtime" - 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" - govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" -) - -func (suite *KeeperTestSuite) TestTransfer() { - var ( - ctx sdk.Context - sender keyring.Key - ) - mockChannelKeeper := &MockChannelKeeper{} - mockICS4Wrapper := &MockICS4Wrapper{} - mockChannelKeeper.On("GetNextSequenceSend", mock.Anything, mock.Anything, mock.Anything).Return(1, true) - mockChannelKeeper.On("GetChannel", mock.Anything, mock.Anything, mock.Anything).Return(channeltypes.Channel{Counterparty: channeltypes.NewCounterparty("transfer", "channel-1")}, true) - mockICS4Wrapper.On("SendPacket", mock.Anything, mock.Anything, mock.Anything).Return(nil) - authAddr := authtypes.NewModuleAddress(govtypes.ModuleName).String() - receiver := sdk.AccAddress([]byte("receiver")) - chan0 := "channel-0" - - testCases := []struct { - name string - malleate func() *types.MsgTransfer - expPass bool - }{ - { - "pass - no token pair", - func() *types.MsgTransfer { - transferMsg := types.NewMsgTransfer(types.PortID, chan0, sdk.NewCoin(evmtypes.GetEVMCoinDenom(), math.NewInt(10)), sender.AccAddr.String(), receiver.String(), timeoutHeight, 0, "") - return transferMsg - }, - true, - }, - { - "error - invalid sender", - func() *types.MsgTransfer { - addr := "" - contractAddr, err := suite.DeployContract("coin", "token", uint8(6)) - suite.Require().NoError(err) - - transferMsg := types.NewMsgTransfer(types.PortID, chan0, sdk.NewCoin(erc20types.CreateDenom(contractAddr.String()), math.NewInt(10)), addr, receiver.String(), timeoutHeight, 0, "") - return transferMsg - }, - false, - }, - { - "no-op - disabled erc20 by params - sufficient sdk.Coins balance", - func() *types.MsgTransfer { - contractAddr, err := suite.DeployContract("coin", "token", uint8(6)) - suite.Require().NoError(err) - - pair, err := utils.RegisterERC20(suite.factory, suite.network, utils.ERC20RegistrationData{ - Addresses: []string{contractAddr.Hex()}, - ProposerPriv: sender.Priv, - }) - suite.Require().NoError(err) - suite.Require().True(len(pair) == 1) - - amt := math.NewInt(10) - _, err = suite.MintERC20Token(contractAddr, sender.Addr, amt.BigInt()) - suite.Require().NoError(err) - - // convert all ERC20 to IBC coin - err = suite.ConvertERC20(sender, contractAddr, amt) - suite.Require().NoError(err) - - params := suite.network.App.GetErc20Keeper().GetParams(ctx) - params.EnableErc20 = false - - err = utils.UpdateERC20Params(utils.UpdateParamsInput{ - Tf: suite.factory, - Network: suite.network, - Pk: sender.Priv, - Params: params, - }) - suite.Require().NoError(err) - - coin := sdk.NewCoin(pair[0].Denom, amt) - transferMsg := types.NewMsgTransfer(types.PortID, chan0, coin, sender.AccAddr.String(), receiver.String(), timeoutHeight, 0, "") - - return transferMsg - }, - true, - }, - { - "error - disabled erc20 by params - insufficient sdk.Coins balance", - func() *types.MsgTransfer { - contractAddr, err := suite.DeployContract("coin", "token", uint8(6)) - suite.Require().NoError(err) - - pair, err := utils.RegisterERC20(suite.factory, suite.network, utils.ERC20RegistrationData{ - Addresses: []string{contractAddr.Hex()}, - ProposerPriv: sender.Priv, - }) - suite.Require().NoError(err) - suite.Require().True(len(pair) == 1) - - amt := math.NewInt(10) - _, err = suite.MintERC20Token(contractAddr, sender.Addr, amt.BigInt()) - suite.Require().NoError(err) - - // No conversion to IBC coin, so the balance is insufficient - suite.Require().EqualValues(suite.network.App.GetBankKeeper().GetBalance( - ctx, sender.AccAddr, pair[0].Denom).Amount, math.ZeroInt()) - - params := suite.network.App.GetErc20Keeper().GetParams(ctx) - params.EnableErc20 = false - err = utils.UpdateERC20Params(utils.UpdateParamsInput{ - Tf: suite.factory, - Network: suite.network, - Pk: sender.Priv, - Params: params, - }) - suite.Require().NoError(err) - - coin := sdk.NewCoin(pair[0].Denom, amt) - transferMsg := types.NewMsgTransfer(types.PortID, chan0, coin, sender.AccAddr.String(), receiver.String(), timeoutHeight, 0, "") - - return transferMsg - }, - false, - }, - { - "no-op - pair not registered", - func() *types.MsgTransfer { - coin := sdk.NewCoin(suite.otherDenom, math.NewInt(10)) - transferMsg := types.NewMsgTransfer(types.PortID, chan0, coin, sender.AccAddr.String(), receiver.String(), timeoutHeight, 0, "") - return transferMsg - }, - true, - }, - { - "no-op - pair is disabled", - func() *types.MsgTransfer { - contractAddr, err := suite.DeployContract("coin", "token", uint8(6)) - suite.Require().NoError(err) - - pair, err := utils.RegisterERC20(suite.factory, suite.network, utils.ERC20RegistrationData{ - Addresses: []string{contractAddr.Hex()}, - ProposerPriv: sender.Priv, - }) - suite.Require().NoError(err) - suite.Require().True(len(pair) == 1) - - amt := math.NewInt(10) - _, err = suite.MintERC20Token(contractAddr, sender.Addr, amt.BigInt()) - suite.Require().NoError(err) - - // convert all erc20 to coins to perform regular transfer without conversion - err = suite.ConvertERC20(sender, contractAddr, amt) - suite.Require().NoError(err) - - // disable token conversion - err = utils.ToggleTokenConversion(suite.factory, suite.network, sender.Priv, pair[0].Denom) - suite.Require().NoError(err) - - coin := sdk.NewCoin(pair[0].Denom, math.NewInt(10)) - transferMsg := types.NewMsgTransfer(types.PortID, chan0, coin, sender.AccAddr.String(), receiver.String(), timeoutHeight, 0, "") - - return transferMsg - }, - true, - }, - { - "pass - has enough balance in erc20 - need to convert", - func() *types.MsgTransfer { - contractAddr, err := suite.DeployContract("coin", "token", uint8(6)) - suite.Require().NoError(err) - - res, err := utils.RegisterERC20(suite.factory, suite.network, utils.ERC20RegistrationData{ - Addresses: []string{contractAddr.Hex()}, - ProposerPriv: sender.Priv, - }) - suite.Require().NoError(err) - suite.Require().True(len(res) == 1) - pair := res[0] - suite.Require().Equal(erc20types.CreateDenom(pair.Erc20Address), pair.Denom) - - amt := math.NewInt(10) - _, err = suite.MintERC20Token(contractAddr, sender.Addr, amt.BigInt()) - suite.Require().NoError(err) - - transferMsg := types.NewMsgTransfer(types.PortID, chan0, sdk.NewCoin(pair.Denom, amt), sender.AccAddr.String(), receiver.String(), timeoutHeight, 0, "") - - return transferMsg - }, - true, - }, - { - "pass - has enough balance in coins", - func() *types.MsgTransfer { - contractAddr, err := suite.DeployContract("coin", "token", uint8(6)) - suite.Require().NoError(err) - - pair, err := utils.RegisterERC20(suite.factory, suite.network, utils.ERC20RegistrationData{ - Addresses: []string{contractAddr.Hex()}, - ProposerPriv: sender.Priv, - }) - suite.Require().NoError(err) - suite.Require().True(len(pair) == 1) - - // mint some erc20 tokens - amt := math.NewInt(10) - _, err = suite.MintERC20Token(contractAddr, suite.keyring.GetAddr(0), amt.BigInt()) - suite.Require().NoError(err) - - // convert all to IBC coins - err = suite.ConvertERC20(sender, contractAddr, amt) - suite.Require().NoError(err) - - transferMsg := types.NewMsgTransfer(types.PortID, chan0, sdk.NewCoin(pair[0].Denom, amt), sender.AccAddr.String(), receiver.String(), timeoutHeight, 0, "") - - return transferMsg - }, - true, - }, - { - "error - fail conversion - no balance in erc20", - func() *types.MsgTransfer { - contractAddr, err := suite.DeployContract("coin", "token", uint8(6)) - suite.Require().NoError(err) - - pair, err := utils.RegisterERC20(suite.factory, suite.network, utils.ERC20RegistrationData{ - Addresses: []string{contractAddr.Hex()}, - ProposerPriv: sender.Priv, - }) - suite.Require().NoError(err) - suite.Require().True(len(pair) == 1) - - transferMsg := types.NewMsgTransfer(types.PortID, chan0, sdk.NewCoin(pair[0].Denom, math.NewInt(10)), sender.AccAddr.String(), receiver.String(), timeoutHeight, 0, "") - return transferMsg - }, - false, - }, - { - "pass - verify correct prefix trimming for ERC20 native tokens", - func() *types.MsgTransfer { - contractAddr, err := suite.DeployContract("coin", "token", uint8(6)) - suite.Require().NoError(err) - - pair, err := testutils.RegisterERC20(suite.factory, suite.network, testutils.ERC20RegistrationData{ - Addresses: []string{contractAddr.Hex()}, - ProposerPriv: sender.Priv, - }) - suite.Require().NoError(err) - suite.Require().True(len(pair) == 1) - - // Mint ERC20 tokens - amt := math.NewInt(10) - _, err = suite.MintERC20Token(contractAddr, sender.Addr, amt.BigInt()) - suite.Require().NoError(err) - - // Create a denom with erc20: prefix - erc20Denom := erc20types.CreateDenom(contractAddr.String()) - suite.Require().Equal(erc20types.Erc20NativeCoinDenomPrefix+contractAddr.String(), erc20Denom) - - // Verify that GetTokenPairID works correctly with the contract address (hex string) - pairIDFromAddress := suite.network.App.GetErc20Keeper().GetTokenPairID(ctx, contractAddr.String()) - suite.Require().NotEmpty(pairIDFromAddress) - - // Verify that GetTokenPairID works correctly with the full denom - pairIDFromDenom := suite.network.App.GetErc20Keeper().GetTokenPairID(ctx, erc20Denom) - suite.Require().NotEmpty(pairIDFromDenom) - - // Both should return the same pair ID - suite.Require().Equal(pairIDFromAddress, pairIDFromDenom) - - transferMsg := types.NewMsgTransfer(types.PortID, chan0, sdk.NewCoin(erc20Denom, amt), sender.AccAddr.String(), receiver.String(), timeoutHeight, 0, "") - - return transferMsg - }, - true, - }, - - // STRV2 - // native coin - perform normal ibc transfer - { - "no-op - fail transfer", - func() *types.MsgTransfer { - senderAcc := suite.keyring.GetAccAddr(0) - - denom := "ibc/DF63978F803A2E27CA5CC9B7631654CCF0BBC788B3B7F0A10200508E37C70992" - coinMetadata := banktypes.Metadata{ - Name: "Generic IBC name", - Symbol: "IBC", - Description: "Generic IBC token description", - DenomUnits: []*banktypes.DenomUnit{ - { - Denom: denom, - Exponent: 0, - Aliases: []string{denom}, - }, - { - Denom: denom, - Exponent: 18, - }, - }, - Display: denom, - Base: denom, - } - - coin := sdk.NewCoin(denom, math.NewInt(10)) - - pair, err := suite.network.App.GetErc20Keeper().RegisterERC20Extension(suite.network.GetContext(), coinMetadata.Base) - suite.Require().Equal(pair.Denom, denom) - suite.Require().NoError(err) - - transferMsg := types.NewMsgTransfer(types.PortID, chan0, coin, senderAcc.String(), receiver.String(), timeoutHeight, 0, "") - - return transferMsg - }, - false, - }, - } - for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() - sender = suite.keyring.GetKey(0) - ctx = suite.network.GetContext() - - suite.network.App.SetTransferKeeper(transferkeeper.NewKeeper( - suite.network.App.AppCodec(), - runtime.NewKVStoreService(suite.network.App.GetKey(types.StoreKey)), - &MockICS4Wrapper{}, // ICS4 Wrapper - mockChannelKeeper, - suite.network.App.MsgServiceRouter(), - suite.network.App.GetAccountKeeper(), - suite.network.App.GetBankKeeper(), - suite.network.App.GetErc20Keeper(), // Add ERC20 Keeper for ERC20 transfers - authAddr, - )) - msg := tc.malleate() - - // get updated context with the latest changes - ctx = suite.network.GetContext() - - _, err := suite.network.App.GetTransferKeeper().Transfer(ctx, msg) - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -// TestPrefixTrimming tests that the Transfer method correctly trims the erc20: prefix -// This test specifically catches the bug where "erc20/" was being trimmed instead of "erc20:" -func (suite *KeeperTestSuite) TestPrefixTrimming() { - var ( - ctx sdk.Context - sender keyring.Key - ) - mockChannelKeeper := &MockChannelKeeper{} - mockICS4Wrapper := &MockICS4Wrapper{} - mockChannelKeeper.On("GetNextSequenceSend", mock.Anything, mock.Anything, mock.Anything).Return(1, true) - mockChannelKeeper.On("GetChannel", mock.Anything, mock.Anything, mock.Anything).Return(channeltypes.Channel{Counterparty: channeltypes.NewCounterparty("transfer", "channel-1")}, true) - mockICS4Wrapper.On("SendPacket", mock.Anything, mock.Anything, mock.Anything).Return(nil) - authAddr := authtypes.NewModuleAddress(govtypes.ModuleName).String() - receiver := sdk.AccAddress([]byte("receiver")) - chan0 := "channel-0" - - testCases := []struct { - name string - malleate func() *types.MsgTransfer - expPass bool - description string - }{ - { - name: "pass - correct prefix trimming erc20:", - malleate: func() *types.MsgTransfer { - contractAddr, err := suite.DeployContract("coin", "token", uint8(6)) - suite.Require().NoError(err) - - pair, err := testutils.RegisterERC20(suite.factory, suite.network, testutils.ERC20RegistrationData{ - Addresses: []string{contractAddr.Hex()}, - ProposerPriv: sender.Priv, - }) - suite.Require().NoError(err) - suite.Require().True(len(pair) == 1) - - // Mint ERC20 tokens - amt := math.NewInt(10) - _, err = suite.MintERC20Token(contractAddr, sender.Addr, amt.BigInt()) - suite.Require().NoError(err) - - // Create a denom with erc20: prefix - erc20Denom := erc20types.CreateDenom(contractAddr.String()) - suite.Require().Equal(erc20types.Erc20NativeCoinDenomPrefix+contractAddr.String(), erc20Denom) - - // TEST: Verify that the prefix trimming works correctly - // The Transfer method should trim "erc20:" prefix to get the hex address - expectedTrimmed := strings.TrimPrefix(erc20Denom, erc20types.Erc20NativeCoinDenomPrefix) - suite.Require().Equal(contractAddr.String(), expectedTrimmed) - - // Verify that GetTokenPairID works correctly with the contract address (hex string) - pairIDFromAddress := suite.network.App.GetErc20Keeper().GetTokenPairID(ctx, contractAddr.String()) - suite.Require().NotEmpty(pairIDFromAddress) - - // Verify that GetTokenPairID works correctly with the full denom - pairIDFromDenom := suite.network.App.GetErc20Keeper().GetTokenPairID(ctx, erc20Denom) - suite.Require().NotEmpty(pairIDFromDenom) - - // Both should return the same pair ID - suite.Require().Equal(pairIDFromAddress, pairIDFromDenom) - - // TEST: Verify that incorrect prefix trimming would fail - // If we incorrectly trim "erc20/" instead of "erc20:", we'd get the wrong string - incorrectTrimmed := strings.TrimPrefix(erc20Denom, erc20types.ModuleName+"/") - suite.Require().NotEqual(contractAddr.String(), incorrectTrimmed) - suite.Require().Equal(erc20Denom, incorrectTrimmed) // Since "erc20/" is not in the string, it returns unchanged - - transferMsg := types.NewMsgTransfer(types.PortID, chan0, sdk.NewCoin(erc20Denom, amt), sender.AccAddr.String(), receiver.String(), timeoutHeight, 0, "") - - return transferMsg - }, - expPass: true, - description: "Test that verifies correct prefix trimming for ERC20 native tokens", - }, - { - name: "pass - demonstrate bug impact", - malleate: func() *types.MsgTransfer { - contractAddr, err := suite.DeployContract("coin2", "token2", uint8(6)) - suite.Require().NoError(err) - - pair, err := testutils.RegisterERC20(suite.factory, suite.network, testutils.ERC20RegistrationData{ - Addresses: []string{contractAddr.Hex()}, - ProposerPriv: sender.Priv, - }) - suite.Require().NoError(err) - suite.Require().True(len(pair) == 1) - - // Mint ERC20 tokens - amt := math.NewInt(10) - _, err = suite.MintERC20Token(contractAddr, sender.Addr, amt.BigInt()) - suite.Require().NoError(err) - - // Create a denom with erc20: prefix - erc20Denom := erc20types.CreateDenom(contractAddr.String()) - - // TEST: Demonstrate the bug's impact - // With correct prefix trimming ("erc20:"), we get the hex address - correctTrimmed := strings.TrimPrefix(erc20Denom, erc20types.Erc20NativeCoinDenomPrefix) - suite.Require().Equal(contractAddr.String(), correctTrimmed) - - // With incorrect prefix trimming ("erc20/"), we get the full denom (no change) - incorrectTrimmed := strings.TrimPrefix(erc20Denom, erc20types.ModuleName+"/") - suite.Require().Equal(erc20Denom, incorrectTrimmed) - - // Both lookups should work due to dual mapping, but use different code paths - pairIDFromCorrect := suite.network.App.GetErc20Keeper().GetTokenPairID(ctx, correctTrimmed) - pairIDFromIncorrect := suite.network.App.GetErc20Keeper().GetTokenPairID(ctx, incorrectTrimmed) - - suite.Require().NotEmpty(pairIDFromCorrect) - suite.Require().NotEmpty(pairIDFromIncorrect) - suite.Require().Equal(pairIDFromCorrect, pairIDFromIncorrect) - - transferMsg := types.NewMsgTransfer(types.PortID, chan0, sdk.NewCoin(erc20Denom, amt), sender.AccAddr.String(), receiver.String(), timeoutHeight, 0, "") - - return transferMsg - }, - expPass: true, - description: "Test that demonstrates why the bug wasn't caught - both lookups work", - }, - } - - for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() - sender = suite.keyring.GetKey(0) - ctx = suite.network.GetContext() - - suite.network.App.SetTransferKeeper(transferkeeper.NewKeeper( - suite.network.App.AppCodec(), - runtime.NewKVStoreService(suite.network.App.GetKey(types.StoreKey)), - &MockICS4Wrapper{}, // ICS4 Wrapper - mockChannelKeeper, - suite.network.App.MsgServiceRouter(), - suite.network.App.GetAccountKeeper(), - suite.network.App.GetBankKeeper(), - suite.network.App.GetErc20Keeper(), // Add ERC20 Keeper for ERC20 transfers - authAddr, - )) - msg := tc.malleate() - - // get updated context with the latest changes - ctx = suite.network.GetContext() - - _, err := suite.network.App.GetTransferKeeper().Transfer(ctx, msg) - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} diff --git a/tests/integration/x/precisebank/test_burn_integration.go b/tests/integration/x/precisebank/test_burn_integration.go deleted file mode 100644 index 65b57f5d..00000000 --- a/tests/integration/x/precisebank/test_burn_integration.go +++ /dev/null @@ -1,559 +0,0 @@ -package precisebank - -import ( - "fmt" - "math/big" - "math/rand" - "testing" - - "github.com/stretchr/testify/require" - - testconstants "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/x/precisebank/types" - evmtypes "github.com/cosmos/evm/x/vm/types" - - sdkmath "cosmossdk.io/math" - - sdk "github.com/cosmos/cosmos-sdk/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" -) - -func (s *KeeperIntegrationTestSuite) TestBurnCoinsMatchingErrors() { - // x/precisebank BurnCoins should be identical to x/bank BurnCoins to - // consumers. This test ensures that the panics & errors returned by - // x/precisebank are identical to x/bank. - - tests := []struct { - name string - recipientModule string - setupFn func() - burnAmount sdk.Coins - wantErr string - wantPanic string - }{ - { - "invalid module", - "notamodule", - func() {}, - cs(c(types.IntegerCoinDenom(), 1000)), - "", - "module account notamodule does not exist: unknown address", - }, - { - "no burn permissions", - // Check app.go to ensure this module has no burn permissions - authtypes.FeeCollectorName, - func() {}, - cs(c(types.IntegerCoinDenom(), 1000)), - "", - "module account fee_collector does not have permissions to burn tokens: unauthorized", - }, - { - "invalid amount", - // Has burn permissions so it goes to the amt check - evmtypes.ModuleName, - func() {}, - sdk.Coins{sdk.Coin{Denom: types.IntegerCoinDenom(), Amount: sdkmath.NewInt(-100)}}, - fmt.Sprintf("-100%s: invalid coins", types.IntegerCoinDenom()), - "", - }, - { - "insufficient balance - empty", - evmtypes.ModuleName, - func() {}, - cs(c(types.IntegerCoinDenom(), 1000)), - fmt.Sprintf("spendable balance 0%s is smaller than 1000%s: insufficient funds", types.IntegerCoinDenom(), types.IntegerCoinDenom()), - "", - }, - } - - for _, tt := range tests { - s.Run(tt.name, func() { - // Reset - s.SetupTest() - - if tt.wantErr == "" && tt.wantPanic == "" { - s.Fail("test must specify either wantErr or wantPanic") - } - - if tt.wantErr != "" { - // Check x/bank BurnCoins for identical error - bankErr := s.network.App.GetBankKeeper().BurnCoins(s.network.GetContext(), tt.recipientModule, tt.burnAmount) - s.Require().Error(bankErr) - s.Require().EqualError(bankErr, tt.wantErr, "expected error should match x/bank BurnCoins error") - - pbankErr := s.network.App.GetPreciseBankKeeper().BurnCoins(s.network.GetContext(), tt.recipientModule, tt.burnAmount) - s.Require().Error(pbankErr) - // Compare strings instead of errors, as error stack is still different - s.Require().Equal( - bankErr.Error(), - pbankErr.Error(), - "x/precisebank error should match x/bank BurnCoins error", - ) - } - - if tt.wantPanic != "" { - // First check the wantPanic string is correct. - // Actually specify the panic string in the test since it makes - // it more clear we are testing specific and different cases. - s.Require().PanicsWithError(tt.wantPanic, func() { - _ = s.network.App.GetBankKeeper().BurnCoins(s.network.GetContext(), tt.recipientModule, tt.burnAmount) - }, "expected panic error should match x/bank BurnCoins") - - s.Require().PanicsWithError(tt.wantPanic, func() { - _ = s.network.App.GetPreciseBankKeeper().BurnCoins(s.network.GetContext(), tt.recipientModule, tt.burnAmount) - }, "x/precisebank panic should match x/bank BurnCoins") - } - }) - } -} - -func (s *KeeperIntegrationTestSuite) TestBurnCoins() { - tests := []struct { - name string - startBalance sdk.Coins - burnCoins sdk.Coins - wantBalance sdk.Coins - wantErr string - }{ - { - "passthrough - unrelated", - cs(c("meow", 1000)), - cs(c("meow", 1000)), - cs(), - "", - }, - { - "passthrough - integer denom", - cs(c(types.IntegerCoinDenom(), 2000)), - cs(c(types.IntegerCoinDenom(), 1000)), - cs(c(types.ExtendedCoinDenom(), 1000000000000000)), - "", - }, - { - "fractional only - no borrow", - cs(c(types.ExtendedCoinDenom(), 1000)), - cs(c(types.ExtendedCoinDenom(), 500)), - cs(c(types.ExtendedCoinDenom(), 500)), - "", - }, - { - "fractional burn - borrows", - cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().AddRaw(100))), - cs(c(types.ExtendedCoinDenom(), 500)), - cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().SubRaw(400))), - "", - }, - { - "error - insufficient integer balance", - cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor())), - cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().MulRaw(2))), - cs(), - // Returns correct error with aatom balance (rewrites Bank BurnCoins err) - fmt.Sprintf("spendable balance 1000000000000%s is smaller than 2000000000000%s: insufficient funds", - types.ExtendedCoinDenom(), types.ExtendedCoinDenom()), - }, - { - "error - insufficient fractional, borrow", - cs(c(types.ExtendedCoinDenom(), 1000)), - cs(c(types.ExtendedCoinDenom(), 2000)), - cs(), - // Error from SendCoins to reserve - fmt.Sprintf("spendable balance 1000%s is smaller than 2000%s: insufficient funds", - types.ExtendedCoinDenom(), types.ExtendedCoinDenom()), - }, - } - - for _, tt := range tests { - s.Run(tt.name, func() { - // Reset - s.SetupTest() - - moduleName := evmtypes.ModuleName - recipientAddr := s.network.App.GetAccountKeeper().GetModuleAddress(moduleName) - - // Start balance - err := s.network.App.GetPreciseBankKeeper().MintCoins(s.network.GetContext(), moduleName, tt.startBalance) - s.Require().NoError(err) - - // Get fractional balance before burn - fracBalBefore := s.network.App.GetPreciseBankKeeper().GetFractionalBalance(s.network.GetContext(), recipientAddr) - - // Burn - err = s.network.App.GetPreciseBankKeeper().BurnCoins(s.network.GetContext(), moduleName, tt.burnCoins) - if tt.wantErr != "" { - s.Require().Error(err) - s.Require().EqualError(err, tt.wantErr) - return - } - - s.Require().NoError(err) - - // Get fractional balance after burn - fracBalAfter := s.network.App.GetPreciseBankKeeper().GetFractionalBalance(s.network.GetContext(), recipientAddr) - - // ------------------------------------------------------------- - // Check FULL balances - // x/bank balances + x/precisebank balance - // Exclude "uatom" as x/precisebank balance will include it - afterBalance := s.GetAllBalances(recipientAddr) - - s.Require().Equal( - tt.wantBalance.String(), - afterBalance.String(), - "unexpected balance after minting %s to %s", - ) - - // Check fractinoal balance change event - if !fracBalAfter.Sub(fracBalBefore).Equal(sdkmath.ZeroInt()) { - expEvent := types.NewEventFractionalBalanceChange(recipientAddr, fracBalBefore, fracBalAfter) - events := s.network.GetContext().EventManager().Events() - s.Require().Contains(events, expEvent) - } - }) - } -} - -func (s *KeeperIntegrationTestSuite) TestBurnCoinsRemainder() { - // This tests a series of small burns to ensure the remainder is both - // updated correctly and reserve is correctly updated. This only burns from - // 1 single account. - - reserveAddr := s.network.App.GetAccountKeeper().GetModuleAddress(types.ModuleName) - - moduleName := evmtypes.ModuleName - moduleAddr := s.network.App.GetAccountKeeper().GetModuleAddress(moduleName) - - startCoins := cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().MulRaw(5))) - - // Start balance - err := s.network.App.GetPreciseBankKeeper().MintCoins( - s.network.GetContext(), - moduleName, - startCoins, - ) - s.Require().NoError(err) - - burnAmt := types.ConversionFactor().QuoRaw(10) - burnCoins := cs(ci(types.ExtendedCoinDenom(), burnAmt)) - - // Burn 0.1 until balance is 0 - for { - reserveBalBefore := s.network.App.GetBankKeeper().GetBalance( - s.network.GetContext(), - reserveAddr, - types.IntegerCoinDenom(), - ) - - balBefore := s.network.App.GetPreciseBankKeeper().GetBalance( - s.network.GetContext(), - moduleAddr, - types.ExtendedCoinDenom(), - ) - remainderBefore := s.network.App.GetPreciseBankKeeper().GetRemainderAmount(s.network.GetContext()) - - // ---------------------------------------- - // Burn - err := s.network.App.GetPreciseBankKeeper().BurnCoins( - s.network.GetContext(), - moduleName, - burnCoins, - ) - s.Require().NoError(err) - - // ---------------------------------------- - // Checks - remainderAfter := s.network.App.GetPreciseBankKeeper().GetRemainderAmount(s.network.GetContext()) - balAfter := s.network.App.GetPreciseBankKeeper().GetBalance( - s.network.GetContext(), - moduleAddr, - types.ExtendedCoinDenom(), - ) - reserveBalAfter := s.network.App.GetBankKeeper().GetBalance( - s.network.GetContext(), - reserveAddr, - types.IntegerCoinDenom(), - ) - - s.Require().Equal( - balBefore.Amount.Sub(burnAmt).String(), - balAfter.Amount.String(), - "balance should decrease by burn amount", - ) - - // Remainder should be updated correctly - s.Require().Equal( - remainderBefore.Add(burnAmt).Mod(types.ConversionFactor()), - remainderAfter, - ) - - // If remainder has exceeded (then rolled over), reserve should be updated - if remainderAfter.LT(remainderBefore) { - s.Require().Equal( - reserveBalBefore.Amount.SubRaw(1).String(), - reserveBalAfter.Amount.String(), - "reserve should decrease by 1 if remainder exceeds ConversionFactor", - ) - } - - // No more to burn - if balAfter.Amount.IsZero() { - break - } - } -} - -func (s *KeeperIntegrationTestSuite) TestBurnCoinsSpreadRemainder() { - // This tests a series of small burns to ensure the remainder is both - // updated correctly and reserve is correctly updated. This burns from - // a series of multiple accounts, to test when the remainder is modified - // by multiple accounts. - - reserveAddr := s.network.App.GetAccountKeeper().GetModuleAddress(types.ModuleName) - burnerModuleName := evmtypes.ModuleName - burnerAddr := s.network.App.GetAccountKeeper().GetModuleAddress(burnerModuleName) - - accCount := 20 - startCoins := cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().MulRaw(5))) - - addrs := []sdk.AccAddress{} - - for i := 0; i < accCount; i++ { - addr := sdk.AccAddress(fmt.Sprintf("addr%d", i)) - s.MintToAccount(addr, startCoins) - - addrs = append(addrs, addr) - } - - burnAmt := types.ConversionFactor().QuoRaw(10) - burnCoins := cs(ci(types.ExtendedCoinDenom(), burnAmt)) - - // Burn 0.1 from each account - for _, addr := range addrs { - reserveBalBefore := s.network.App.GetBankKeeper().GetBalance( - s.network.GetContext(), - reserveAddr, - types.IntegerCoinDenom(), - ) - - balBefore := s.network.App.GetPreciseBankKeeper().GetBalance( - s.network.GetContext(), - addr, - types.ExtendedCoinDenom(), - ) - remainderBefore := s.network.App.GetPreciseBankKeeper().GetRemainderAmount(s.network.GetContext()) - - // ---------------------------------------- - // Send & Burn - err := s.network.App.GetPreciseBankKeeper().SendCoins( - s.network.GetContext(), - addr, - burnerAddr, - burnCoins, - ) - s.Require().NoError(err) - - err = s.network.App.GetPreciseBankKeeper().BurnCoins( - s.network.GetContext(), - burnerModuleName, - burnCoins, - ) - s.Require().NoError(err) - - // ---------------------------------------- - // Checks - remainderAfter := s.network.App.GetPreciseBankKeeper().GetRemainderAmount(s.network.GetContext()) - balAfter := s.network.App.GetPreciseBankKeeper().GetBalance( - s.network.GetContext(), - addr, - types.ExtendedCoinDenom(), - ) - reserveBalAfter := s.network.App.GetBankKeeper().GetBalance( - s.network.GetContext(), - reserveAddr, - types.IntegerCoinDenom(), - ) - - s.Require().Equal( - balBefore.Amount.Sub(burnAmt).String(), - balAfter.Amount.String(), - "balance should decrease by burn amount", - ) - - // Remainder should be updated correctly - s.Require().Equal( - remainderBefore.Add(burnAmt).Mod(types.ConversionFactor()), - remainderAfter, - ) - - s.T().Logf("acc: %s", string(addr.Bytes())) - s.T().Logf("acc bal: %s -> %s", balBefore, balAfter) - s.T().Logf("remainder: %s -> %s", remainderBefore, remainderAfter) - s.T().Logf("reserve: %v -> %v", reserveBalBefore, reserveBalAfter) - - // Reserve will change when: - // 1. Account needs to borrow from integer (transfers to reserve) - // 2. Remainder meets or exceeds conversion factor (burn 1 from reserve) - reserveIncrease := sdkmath.ZeroInt() - - // Does account need to borrow from integer? - if balBefore.Amount.Mod(types.ConversionFactor()).LT(burnAmt) { - reserveIncrease = reserveIncrease.AddRaw(1) - } - - // If remainder has exceeded (then rolled over), burn additional 1 - if remainderBefore.Add(burnAmt).GTE(types.ConversionFactor()) { - reserveIncrease = reserveIncrease.SubRaw(1) - } - - s.Require().Equal( - reserveBalBefore.Amount.Add(reserveIncrease).String(), - reserveBalAfter.Amount.String(), - "reserve should be updated by remainder and borrowing", - ) - } -} - -func (s *KeeperIntegrationTestSuite) TestBurnCoinsRandomValueMultiDecimals() { - tests := []struct { - name string - chainID testconstants.ChainID - }{ - { - name: "6 decimals", - chainID: testconstants.SixDecimalsChainID, - }, - { - name: "12 decimals", - chainID: testconstants.TwelveDecimalsChainID, - }, - { - name: "2 decimals", - chainID: testconstants.TwoDecimalsChainID, - }, - } - - for _, tt := range tests { - s.Run(tt.name, func() { - s.SetupTestWithChainID(tt.chainID) - - // Has burn permissions - burnerModuleName := evmtypes.ModuleName - burner := sdk.AccAddress([]byte{1}) - - // Initial balance large enough to cover many small burns - initialBalance := types.ConversionFactor().MulRaw(100) - initialCoin := cs(ci(types.ExtendedCoinDenom(), initialBalance)) - err := s.network.App.GetPreciseBankKeeper().MintCoins(s.network.GetContext(), burnerModuleName, initialCoin) - s.Require().NoError(err) - err = s.network.App.GetPreciseBankKeeper().SendCoinsFromModuleToAccount(s.network.GetContext(), burnerModuleName, burner, initialCoin) - s.Require().NoError(err) - - // Setup test parameters - maxBurnUnit := types.ConversionFactor().MulRaw(2).SubRaw(1) - r := rand.New(rand.NewSource(SEED)) - - totalBurned := sdkmath.ZeroInt() - burnCount := 0 - - // Continue burns as long as burner has balance remaining - for { - // Check current burner balance - burnerAmount := s.GetAllBalances(burner).AmountOf(types.ExtendedCoinDenom()) - if burnerAmount.IsZero() { - break - } - - // Generate random amount within the range of max possible burn amount - maxPossibleBurn := maxBurnUnit - if maxPossibleBurn.GT(burnerAmount) { - maxPossibleBurn = burnerAmount - } - randAmount := sdkmath.NewIntFromBigInt(new(big.Int).Rand(r, maxPossibleBurn.BigInt())).AddRaw(1) - - // 1. send to burner module - burnCoins := cs(ci(types.ExtendedCoinDenom(), randAmount)) - err := s.network.App.GetPreciseBankKeeper().SendCoinsFromAccountToModule(s.network.GetContext(), burner, burnerModuleName, burnCoins) - s.Require().NoError(err) - - // 2. burn from burner module - err = s.network.App.GetPreciseBankKeeper().BurnCoins(s.network.GetContext(), burnerModuleName, burnCoins) - s.Require().NoError(err) - - totalBurned = totalBurned.Add(randAmount) - burnCount++ - } - - s.T().Logf("Completed %d random burns, total burned: %s", burnCount, totalBurned) - - // Check burner balance - burnerBal := s.GetAllBalances(burner).AmountOf(types.ExtendedCoinDenom()) - s.Equal(burnerBal.BigInt().Cmp(big.NewInt(0)), 0, "burner balance mismatch (expected: %s, actual: %s)", big.NewInt(0), burnerBal) - - // Check remainder - remainder := s.network.App.GetPreciseBankKeeper().GetRemainderAmount(s.network.GetContext()) - s.Equal(remainder.BigInt().Cmp(big.NewInt(0)), 0, "remainder should be zero (expected: %s, actual: %s)", big.NewInt(0), remainder) - }) - } -} - -func FuzzBurnCoins(f *testing.F) { - configurator := evmtypes.NewEVMConfigurator() - configurator.ResetTestConfig() - configurator.WithEVMCoinInfo(testconstants.ExampleChainCoinInfo[testconstants.SixDecimalsChainID]) - err := configurator.Configure() - require.NoError(f, err) - - f.Add(int64(0)) - f.Add(int64(100)) - f.Add(types.ConversionFactor().Int64()) - f.Add(types.ConversionFactor().MulRaw(5).Int64()) - f.Add(types.ConversionFactor().MulRaw(2).AddRaw(123948723).Int64()) - - f.Fuzz(func(t *testing.T, amount int64) { - // No negative amounts - if amount < 0 { - amount = -amount - } - - // Manually setup test suite since no direct Fuzz support in test suites - suite := new(KeeperIntegrationTestSuite) - suite.SetT(t) - suite.SetS(suite) - suite.SetupTest() - - burnCount := int64(10) - - // Has both mint & burn permissions - moduleName := evmtypes.ModuleName - moduleAddr := suite.network.App.GetAccountKeeper().GetModuleAddress(moduleName) - - // Start balance - err := suite.network.App.GetPreciseBankKeeper().MintCoins( - suite.network.GetContext(), - moduleName, - cs(ci(types.ExtendedCoinDenom(), sdkmath.NewInt(amount).MulRaw(burnCount))), - ) - suite.Require().NoError(err) - - // Burn multiple times to ensure different balance scenarios - for i := int64(0); i < burnCount; i++ { - err := suite.network.App.GetPreciseBankKeeper().BurnCoins( - suite.network.GetContext(), - moduleName, - cs(c(types.ExtendedCoinDenom(), amount)), - ) - suite.Require().NoError(err) - } - - // Check full balances - balAfter := suite.network.App.GetPreciseBankKeeper().GetBalance(suite.network.GetContext(), moduleAddr, types.ExtendedCoinDenom()) - - suite.Require().Equalf( - int64(0), - balAfter.Amount.Int64(), - "all coins should be burned, got %d", - balAfter.Amount.Int64(), - ) - }) -} diff --git a/tests/integration/x/precisebank/test_genesis.go b/tests/integration/x/precisebank/test_genesis.go deleted file mode 100644 index 02f01e13..00000000 --- a/tests/integration/x/precisebank/test_genesis.go +++ /dev/null @@ -1,317 +0,0 @@ -package precisebank - -import ( - "fmt" - - "github.com/stretchr/testify/suite" - - testconstants "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/testutil/integration/evm/network" - "github.com/cosmos/evm/x/precisebank" - "github.com/cosmos/evm/x/precisebank/types" - - sdkmath "cosmossdk.io/math" - - sdk "github.com/cosmos/cosmos-sdk/types" -) - -type GenesisTestSuite struct { - suite.Suite - - network *network.UnitTestNetwork - create network.CreateEvmApp - options []network.ConfigOption -} - -func NewGenesisTestSuite(create network.CreateEvmApp, options ...network.ConfigOption) *GenesisTestSuite { - return &GenesisTestSuite{ - create: create, - options: options, - } -} - -func (s *GenesisTestSuite) SetupTest() { - s.SetupTestWithChainID(testconstants.SixDecimalsChainID) -} - -func (s *GenesisTestSuite) SetupTestWithChainID(chainID testconstants.ChainID) { - options := []network.ConfigOption{ - network.WithChainID(chainID), - } - options = append(options, s.options...) - s.network = network.NewUnitTestNetwork(s.create, options...) - - // Clear all fractional balances to ensure no leftover balances persist between tests - s.network.App.GetPreciseBankKeeper().IterateFractionalBalances(s.network.GetContext(), func(addr sdk.AccAddress, bal sdkmath.Int) bool { - s.network.App.GetPreciseBankKeeper().DeleteFractionalBalance(s.network.GetContext(), addr) - return false - }) -} - -func (s *GenesisTestSuite) TestInitGenesis() { - tests := []struct { - name string - setupFn func() - genesisState *types.GenesisState - panicMsg string - }{ - { - "valid - default genesisState", - func() {}, - types.DefaultGenesisState(), - "", - }, - { - "valid - empty genesisState", - func() {}, - &types.GenesisState{}, - "failed to validate precisebank genesis state: nil remainder amount", - }, - { - "valid - module balance matches non-zero amount", - func() { - // The network setup creates an initial balance of 1, so we need to mint 1 more - // to get to the expected amount of 2 for this test case - err := s.network.App.GetBankKeeper().MintCoins( - s.network.GetContext(), - types.ModuleName, - sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom(), sdkmath.NewInt(1))), - ) - s.Require().NoError(err) - }, - types.NewGenesisState( - types.FractionalBalances{ - types.NewFractionalBalance(sdk.AccAddress{1}.String(), types.ConversionFactor().SubRaw(1)), - types.NewFractionalBalance(sdk.AccAddress{2}.String(), types.ConversionFactor().SubRaw(1)), - }, - // 2 leftover from 0.999... + 0.999... - sdkmath.NewInt(2), - ), - "", - }, - { - // Other GenesisState.Validate() tests are in types/genesis_test.go - "invalid genesisState - GenesisState.Validate() is called", - func() {}, - types.NewGenesisState( - types.FractionalBalances{ - types.NewFractionalBalance(sdk.AccAddress{1}.String(), sdkmath.NewInt(1)), - types.NewFractionalBalance(sdk.AccAddress{1}.String(), sdkmath.NewInt(1)), - }, - sdkmath.ZeroInt(), - ), - "failed to validate precisebank genesis state: invalid balances: duplicate address cosmos1qyfkm2y3", - }, - { - "invalid - module balance insufficient", - func() { - // The network setup creates an initial balance of 1, so we need to burn that - // to get to 0 balance for this test case - err := s.network.App.GetBankKeeper().BurnCoins( - s.network.GetContext(), - types.ModuleName, - sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom(), sdkmath.NewInt(1))), - ) - s.Require().NoError(err) - }, - types.NewGenesisState( - types.FractionalBalances{ - types.NewFractionalBalance(sdk.AccAddress{1}.String(), types.ConversionFactor().SubRaw(1)), - types.NewFractionalBalance(sdk.AccAddress{2}.String(), types.ConversionFactor().SubRaw(1)), - }, - // 2 leftover from 0.999... + 0.999... - sdkmath.NewInt(2), - ), - fmt.Sprintf("module account balance does not match sum of fractional balances and remainder, balance is 0%s but expected 2000000000000%s (2%s)", - types.IntegerCoinDenom(), types.ExtendedCoinDenom(), types.IntegerCoinDenom()), - }, - { - "invalid - module balance excessive", - func() { - // The network setup creates an initial balance of 1, so we need to mint 99 more - // to get to 100 total balance for this test case - err := s.network.App.GetBankKeeper().MintCoins( - s.network.GetContext(), - types.ModuleName, - sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom(), sdkmath.NewInt(99))), - ) - s.Require().NoError(err) - }, - types.NewGenesisState( - types.FractionalBalances{ - types.NewFractionalBalance(sdk.AccAddress{1}.String(), types.ConversionFactor().SubRaw(1)), - types.NewFractionalBalance(sdk.AccAddress{2}.String(), types.ConversionFactor().SubRaw(1)), - }, - sdkmath.NewInt(2), - ), - fmt.Sprintf("module account balance does not match sum of fractional balances and remainder, balance is 100%s but expected 2000000000000%s (2%s)", - types.IntegerCoinDenom(), types.ExtendedCoinDenom(), types.IntegerCoinDenom()), - }, - { - "sets module account", - func() { - // Delete the module account first to ensure it's created here - moduleAcc := s.network.App.GetAccountKeeper().GetModuleAccount(s.network.GetContext(), types.ModuleName) - s.network.App.GetAccountKeeper().RemoveAccount(s.network.GetContext(), moduleAcc) - - // Ensure module account is deleted in state. - // GetModuleAccount() will always return non-nil and does not - // necessarily equate to the account being stored in the account store. - s.Require().Nil(s.network.App.GetAccountKeeper().GetAccount(s.network.GetContext(), moduleAcc.GetAddress())) - }, - types.DefaultGenesisState(), - "", - }, - } - - for _, tc := range tests { - s.Run(tc.name, func() { - s.SetupTest() - tc.setupFn() - - if tc.panicMsg != "" { - s.Require().PanicsWithValue( - tc.panicMsg, - func() { - precisebank.InitGenesis( - s.network.GetContext(), - *s.network.App.GetPreciseBankKeeper(), - s.network.App.GetAccountKeeper(), - s.network.App.GetBankKeeper(), - tc.genesisState, - ) - }, - ) - - return - } - - s.Require().NotPanics(func() { - precisebank.InitGenesis( - s.network.GetContext(), - *s.network.App.GetPreciseBankKeeper(), - s.network.App.GetAccountKeeper(), - s.network.App.GetBankKeeper(), - tc.genesisState, - ) - }) - - // Ensure module account is created - moduleAcc := s.network.App.GetAccountKeeper().GetModuleAccount(s.network.GetContext(), types.ModuleName) - s.NotNil(moduleAcc) - s.NotNil( - s.network.App.GetAccountKeeper().GetAccount(s.network.GetContext(), moduleAcc.GetAddress()), - "module account should be created & stored in account store", - ) - - // Verify balances are set in state, get full list of balances in - // state to ensure they are set AND no extra balances are set - var bals []types.FractionalBalance - s.network.App.GetPreciseBankKeeper().IterateFractionalBalances(s.network.GetContext(), func(addr sdk.AccAddress, bal sdkmath.Int) bool { - bals = append(bals, types.NewFractionalBalance(addr.String(), bal)) - return false - }) - s.Require().ElementsMatch(tc.genesisState.Balances, bals, "balances should be set in state") - - remainder := s.network.App.GetPreciseBankKeeper().GetRemainderAmount(s.network.GetContext()) - s.Require().Equal(tc.genesisState.Remainder, remainder, "remainder should be set in state") - }) - } -} - -func (s *GenesisTestSuite) TestExportGenesis() { - // ExportGenesis(InitGenesis(genesisState)) == genesisState - // Must also be valid. - - tests := []struct { - name string - initGenesisState func() *types.GenesisState - }{ - { - "InitGenesis(DefaultGenesisState)", - types.DefaultGenesisState, - }, - { - "balances, no remainder", - func() *types.GenesisState { - // Burn the initial balance created by network setup, then mint the expected amount - err := s.network.App.GetBankKeeper().BurnCoins( - s.network.GetContext(), - types.ModuleName, - sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom(), sdkmath.NewInt(1))), - ) - s.Require().NoError(err) - - err = s.network.App.GetBankKeeper().MintCoins( - s.network.GetContext(), - types.ModuleName, - sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom(), sdkmath.NewInt(1))), - ) - s.Require().NoError(err) - - return types.NewGenesisState( - types.FractionalBalances{ - types.NewFractionalBalance(sdk.AccAddress{1}.String(), types.ConversionFactor().QuoRaw(2)), - types.NewFractionalBalance(sdk.AccAddress{2}.String(), types.ConversionFactor().QuoRaw(2)), - }, - sdkmath.ZeroInt(), - ) - }, - }, - { - "balances, remainder", - func() *types.GenesisState { - // Burn the initial balance created by network setup, then mint the expected amount - err := s.network.App.GetBankKeeper().BurnCoins( - s.network.GetContext(), - types.ModuleName, - sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom(), sdkmath.NewInt(1))), - ) - s.Require().NoError(err) - - err = s.network.App.GetBankKeeper().MintCoins( - s.network.GetContext(), - types.ModuleName, - sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom(), sdkmath.NewInt(1))), - ) - s.Require().NoError(err) - - return types.NewGenesisState( - types.FractionalBalances{ - types.NewFractionalBalance(sdk.AccAddress{1}.String(), types.ConversionFactor().QuoRaw(2)), - types.NewFractionalBalance(sdk.AccAddress{2}.String(), types.ConversionFactor().QuoRaw(2).SubRaw(1)), - }, - sdkmath.OneInt(), - ) - }, - }, - } - - for _, tc := range tests { - s.Run(tc.name, func() { - // Reset state - s.SetupTest() - - initGs := tc.initGenesisState() - - s.Require().NotPanics(func() { - precisebank.InitGenesis( - s.network.GetContext(), - *s.network.App.GetPreciseBankKeeper(), - s.network.App.GetAccountKeeper(), - s.network.App.GetBankKeeper(), - initGs, - ) - }) - - genesisState := precisebank.ExportGenesis(s.network.GetContext(), *s.network.App.GetPreciseBankKeeper()) - s.Require().NoError(genesisState.Validate(), "exported genesis state should be valid") - - s.Require().Equal( - initGs, - genesisState, - "exported genesis state should equal initial genesis state", - ) - }) - } -} diff --git a/tests/integration/x/precisebank/test_grpc_query.go b/tests/integration/x/precisebank/test_grpc_query.go deleted file mode 100644 index 317c21ad..00000000 --- a/tests/integration/x/precisebank/test_grpc_query.go +++ /dev/null @@ -1,96 +0,0 @@ -package precisebank - -import ( - "context" - - "github.com/cosmos/evm/x/precisebank/types" - - sdkmath "cosmossdk.io/math" - - sdk "github.com/cosmos/cosmos-sdk/types" - minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" -) - -func (s *KeeperIntegrationTestSuite) TestQueryRemainder() { - res, err := s.network.GetPreciseBankClient().Remainder( - context.Background(), - &types.QueryRemainderRequest{}, - ) - s.Require().NoError(err) - - expRemainder := sdk.NewCoin(types.ExtendedCoinDenom(), sdkmath.ZeroInt()) - s.Require().Equal(expRemainder, res.Remainder) - - // Mint fractional coins to create non-zero remainder - - pbk := s.network.App.GetPreciseBankKeeper() - - coin := sdk.NewCoin(types.ExtendedCoinDenom(), sdkmath.OneInt()) - err = pbk.MintCoins( - s.network.GetContext(), - minttypes.ModuleName, - sdk.NewCoins(coin), - ) - s.Require().NoError(err) - - res, err = s.network.GetPreciseBankClient().Remainder( - context.Background(), - &types.QueryRemainderRequest{}, - ) - s.Require().NoError(err) - - expRemainder.Amount = types.ConversionFactor().Sub(coin.Amount) - s.Require().Equal(expRemainder, res.Remainder) -} - -func (s *KeeperIntegrationTestSuite) TestQueryFractionalBalance() { - testCases := []struct { - name string - giveBalance sdkmath.Int - }{ - { - "zero", - sdkmath.ZeroInt(), - }, - { - "min amount", - sdkmath.OneInt(), - }, - { - "max amount", - types.ConversionFactor().SubRaw(1), - }, - { - "multiple integer amounts, 0 fractional", - types.ConversionFactor().MulRaw(5), - }, - { - "multiple integer amounts, non-zero fractional", - types.ConversionFactor().MulRaw(5).Add(types.ConversionFactor().QuoRaw(2)), - }, - } - - for _, tc := range testCases { - s.Run(tc.name, func() { - s.SetupTest() - - addr := sdk.AccAddress([]byte("test")) - - coin := sdk.NewCoin(types.ExtendedCoinDenom(), tc.giveBalance) - s.MintToAccount(addr, sdk.NewCoins(coin)) - - res, err := s.network.GetPreciseBankClient().FractionalBalance( - context.Background(), - &types.QueryFractionalBalanceRequest{ - Address: addr.String(), - }, - ) - s.Require().NoError(err) - - // Only fractional amount, even if minted more than conversion factor - expAmount := tc.giveBalance.Mod(types.ConversionFactor()) - expFractionalBalance := sdk.NewCoin(types.ExtendedCoinDenom(), expAmount) - s.Require().Equal(expFractionalBalance, res.FractionalBalance) - }) - } -} diff --git a/tests/integration/x/precisebank/test_integration.go b/tests/integration/x/precisebank/test_integration.go deleted file mode 100644 index 9b568d2a..00000000 --- a/tests/integration/x/precisebank/test_integration.go +++ /dev/null @@ -1,343 +0,0 @@ -package precisebank - -import ( - "math/big" - "math/rand" - - "github.com/ethereum/go-ethereum/common" - - "github.com/cosmos/evm/contracts" - testconstants "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/testutil/integration/evm/utils" - testutiltypes "github.com/cosmos/evm/testutil/types" - "github.com/cosmos/evm/x/precisebank/types" - evmtypes "github.com/cosmos/evm/x/vm/types" - - sdkmath "cosmossdk.io/math" - - sdk "github.com/cosmos/cosmos-sdk/types" -) - -func (s *KeeperIntegrationTestSuite) TestMintBurnSendCoinsRandomValueMultiDecimals() { - tests := []struct { - name string - chainID testconstants.ChainID - }{ - { - name: "6 decimals", - chainID: testconstants.SixDecimalsChainID, - }, - { - name: "2 decimals", - chainID: testconstants.TwoDecimalsChainID, - }, - { - name: "12 decimals", - chainID: testconstants.TwelveDecimalsChainID, - }, - } - - for _, tt := range tests { - s.Run(tt.name, func() { - s.SetupTestWithChainID(tt.chainID) - - moduleName := evmtypes.ModuleName - sender := sdk.AccAddress([]byte{1}) - recipient := sdk.AccAddress([]byte{2}) - - // Mint initial balance to sender - initialBalance := types.ConversionFactor().MulRaw(100) - initialCoins := cs(ci(types.ExtendedCoinDenom(), initialBalance)) - s.Require().NoError(s.network.App.GetPreciseBankKeeper().MintCoins(s.network.GetContext(), moduleName, initialCoins)) - s.Require().NoError(s.network.App.GetPreciseBankKeeper().SendCoinsFromModuleToAccount(s.network.GetContext(), moduleName, sender, initialCoins)) - - maxUnit := types.ConversionFactor().MulRaw(2).SubRaw(1) - r := rand.New(rand.NewSource(SEED)) - - // Expected balances tracking - expectedSenderBal := initialBalance - expectedRecipientBal := sdkmath.ZeroInt() - - mintCount, burnCount, sendCount := 0, 0, 0 - - mintAmount := sdkmath.NewInt(0) - burnAmount := sdkmath.NewInt(0) - - iterations := 1000 - for range iterations { - op := r.Intn(3) - switch op { - case 0: // Mint to sender via module - randAmount := sdkmath.NewIntFromBigInt(new(big.Int).Rand(r, maxUnit.BigInt())).AddRaw(1) - mintCoins := cs(ci(types.ExtendedCoinDenom(), randAmount)) - if err := s.network.App.GetPreciseBankKeeper().MintCoins(s.network.GetContext(), moduleName, mintCoins); err != nil { - continue - } - if err := s.network.App.GetPreciseBankKeeper().SendCoinsFromModuleToAccount(s.network.GetContext(), moduleName, sender, mintCoins); err != nil { - continue - } - expectedSenderBal = expectedSenderBal.Add(randAmount) - mintAmount = mintAmount.Add(randAmount) - mintCount++ - - case 1: // Burn from sender via module - senderBal := s.GetAllBalances(sender).AmountOf(types.ExtendedCoinDenom()) - if senderBal.IsZero() { - continue - } - burnable := sdkmath.MinInt(senderBal, maxUnit) - randAmount := sdkmath.NewIntFromBigInt(new(big.Int).Rand(r, burnable.BigInt())).AddRaw(1) - burnCoins := cs(ci(types.ExtendedCoinDenom(), randAmount)) - if err := s.network.App.GetPreciseBankKeeper().SendCoinsFromAccountToModule(s.network.GetContext(), sender, moduleName, burnCoins); err != nil { - continue - } - if err := s.network.App.GetPreciseBankKeeper().BurnCoins(s.network.GetContext(), moduleName, burnCoins); err != nil { - continue - } - expectedSenderBal = expectedSenderBal.Sub(randAmount) - burnAmount = burnAmount.Add(randAmount) - burnCount++ - - case 2: // Send from sender to recipient - senderBal := s.GetAllBalances(sender).AmountOf(types.ExtendedCoinDenom()) - if senderBal.IsZero() { - continue - } - sendable := sdkmath.MinInt(senderBal, maxUnit) - randAmount := sdkmath.NewIntFromBigInt(new(big.Int).Rand(r, sendable.BigInt())).AddRaw(1) - sendCoins := cs(ci(types.ExtendedCoinDenom(), randAmount)) - if err := s.network.App.GetPreciseBankKeeper().SendCoins(s.network.GetContext(), sender, recipient, sendCoins); err != nil { - continue - } - expectedSenderBal = expectedSenderBal.Sub(randAmount) - expectedRecipientBal = expectedRecipientBal.Add(randAmount) - sendCount++ - } - } - - s.T().Logf("Executed operations: %d mints, %d burns, %d sends", mintCount, burnCount, sendCount) - - // Check balances - actualSenderBal := s.GetAllBalances(sender).AmountOf(types.ExtendedCoinDenom()) - actualRecipientBal := s.GetAllBalances(recipient).AmountOf(types.ExtendedCoinDenom()) - s.Require().Equal(expectedSenderBal.BigInt().Cmp(actualSenderBal.BigInt()), 0, "Sender balance mismatch (expected: %s, actual: %s)", expectedSenderBal, actualSenderBal) - s.Require().Equal(expectedRecipientBal.BigInt().Cmp(actualRecipientBal.BigInt()), 0, "Recipient balance mismatch (expected: %s, actual: %s)", expectedRecipientBal, actualRecipientBal) - - // Check remainder - expectedRemainder := burnAmount.Sub(mintAmount).Mod(types.ConversionFactor()) - actualRemainder := s.network.App.GetPreciseBankKeeper().GetRemainderAmount(s.network.GetContext()) - s.Require().Equal(expectedRemainder.BigInt().Cmp(actualRemainder.BigInt()), 0, "Remainder mismatch (expected: %s, actual: %s)", expectedRemainder, actualRemainder) - }) - } -} - -func (s *KeeperIntegrationTestSuite) TestSendEvmTxRandomValueMultiDecimals() { - maxGasLimit := int64(500000) - defaultEVMCoinTransferGasLimit := int64(21000) - - tests := []struct { - name string - chainID testconstants.ChainID - }{ - { - name: "6 decimals", - chainID: testconstants.SixDecimalsChainID, - }, - { - name: "12 decimals", - chainID: testconstants.TwelveDecimalsChainID, - }, - { - name: "2 decimals", - chainID: testconstants.TwoDecimalsChainID, - }, - } - - for _, tt := range tests { - s.Run(tt.name, func() { - s.SetupTestWithChainID(tt.chainID) - - sender := s.keyring.GetKey(0) - recipient := s.keyring.GetKey(1) - burnerAddr := common.HexToAddress("0x0000000000000000000000000000000000000000") - - baseFeeResp, err := s.network.GetEvmClient().BaseFee(s.network.GetContext(), &evmtypes.QueryBaseFeeRequest{}) - s.Require().NoError(err) - gasPrice := sdkmath.NewIntFromBigInt(baseFeeResp.BaseFee.BigInt()) - gasFee := gasPrice.Mul(sdkmath.NewInt(defaultEVMCoinTransferGasLimit)) - - // Burn balance from sender except for initial balance - initialBalance := types.ConversionFactor().MulRaw(100) - senderBal := s.GetAllBalances(sender.AccAddr).AmountOf(types.ExtendedCoinDenom()).Sub(gasFee).Sub(initialBalance) - _, err = s.factory.ExecuteEthTx(sender.Priv, evmtypes.EvmTxArgs{ - To: &burnerAddr, - Amount: senderBal.BigInt(), - GasLimit: uint64(defaultEVMCoinTransferGasLimit), //nolint:gosec // G115 - GasPrice: gasPrice.BigInt(), - }) - s.Require().NoError(err) - - // Burn balance from recipient - recipientBal := s.GetAllBalances(recipient.AccAddr).AmountOf(types.ExtendedCoinDenom()).Sub(gasFee) - _, err = s.factory.ExecuteEthTx(recipient.Priv, evmtypes.EvmTxArgs{ - To: &burnerAddr, - Amount: recipientBal.BigInt(), - GasLimit: uint64(defaultEVMCoinTransferGasLimit), //nolint:gosec // G115 - GasPrice: gasPrice.BigInt(), - }) - s.Require().NoError(err) - - err = s.network.NextBlock() - s.Require().NoError(err) - - maxSendUnit := types.ConversionFactor().MulRaw(2).SubRaw(1) - r := rand.New(rand.NewSource(SEED)) - - expectedSenderBal := initialBalance - expectedRecipientBal := sdkmath.ZeroInt() - - sentCount := 0 - for { - gasLimit := r.Int63n(maxGasLimit-defaultEVMCoinTransferGasLimit) + defaultEVMCoinTransferGasLimit - baseFeeResp, err = s.network.GetEvmClient().BaseFee(s.network.GetContext(), &evmtypes.QueryBaseFeeRequest{}) - s.Require().NoError(err) - gasPrice = sdkmath.NewIntFromBigInt(baseFeeResp.BaseFee.BigInt()) - - // Generate random value to send - randAmount := sdkmath.NewIntFromBigInt(new(big.Int).Rand(r, maxSendUnit.BigInt())).AddRaw(1) - - // Execute EVM coin transfer - txRes, _ := s.factory.ExecuteEthTx(sender.Priv, evmtypes.EvmTxArgs{ - To: &recipient.Addr, - Amount: randAmount.BigInt(), - GasLimit: uint64(gasLimit), //nolint:gosec // G115 - GasPrice: gasPrice.BigInt(), - }) - err = s.network.NextBlock() - s.Require().NoError(err) - - // Calculate gas fee used - gasUsed := txRes.GasUsed - gasFeeUsed := gasPrice.Mul(sdkmath.NewInt(gasUsed)) - expectedSenderBal = expectedSenderBal.Sub(gasFeeUsed) - - // break, if EVM coin transfer tx is failed - sentCount++ - if txRes.IsErr() { - break - } - - // Update expected balances - expectedSenderBal = expectedSenderBal.Sub(randAmount) - expectedRecipientBal = expectedRecipientBal.Add(randAmount) - } - - s.T().Logf("Completed %d random evm sends", sentCount) - - // Check sender balance - actualSenderBal := s.GetAllBalances(sender.AccAddr).AmountOf(types.ExtendedCoinDenom()) - s.Require().Equal(expectedSenderBal.BigInt().Cmp(actualSenderBal.BigInt()), 0, - "Sender balance mismatch (expected: %s, actual: %s)", expectedSenderBal, actualSenderBal) - - // Check recipient balance - actualRecipientBal := s.GetAllBalances(recipient.AccAddr).AmountOf(types.ExtendedCoinDenom()) - s.Require().Equal(expectedRecipientBal.BigInt().Cmp(actualRecipientBal.BigInt()), 0, - "Recipient balance mismatch (expected: %s, actual: %s)", expectedRecipientBal, actualRecipientBal) - }) - } -} - -func (s *KeeperIntegrationTestSuite) TestWATOMWrapUnwrapMultiDecimal() { - tests := []struct { - name string - chainID testconstants.ChainID - }{ - { - name: "6 decimals", - chainID: testconstants.SixDecimalsChainID, - }, - { - name: "12 decimals", - chainID: testconstants.TwelveDecimalsChainID, - }, - { - name: "2 decimals", - chainID: testconstants.TwoDecimalsChainID, - }, - } - - for _, tt := range tests { - s.Run(tt.name, func() { - s.SetupTestWithChainID(tt.chainID) - - sender := s.keyring.GetKey(0) - amount := big.NewInt(1) - - // Deploy WATOM contract - watomAddr, err := s.factory.DeployContract( - sender.Priv, - evmtypes.EvmTxArgs{}, - testutiltypes.ContractDeploymentData{ - Contract: contracts.WATOMContract, - }, - ) - s.Require().NoError(err) - - err = s.network.NextBlock() - s.Require().NoError(err) - - baseFeeRes, err := s.network.GetEvmClient().BaseFee(s.network.GetContext(), &evmtypes.QueryBaseFeeRequest{}) - s.Require().NoError(err) - - // Call deposit() with msg.value = wrapAmount - _, err = s.factory.ExecuteContractCall( - sender.Priv, - evmtypes.EvmTxArgs{ - To: &watomAddr, - Amount: amount, - GasLimit: 100_000, - GasFeeCap: baseFeeRes.BaseFee.BigInt(), - GasTipCap: big.NewInt(1), - }, - testutiltypes.CallArgs{ - ContractABI: contracts.WATOMContract.ABI, - MethodName: "deposit", - }, - ) - s.Require().NoError(err) - err = s.network.NextBlock() - s.Require().NoError(err) - - // Check WATOM balance == wrapAmount - bal, err := utils.GetERC20Balance(s.network, watomAddr, sender.Addr) - s.Require().NoError(err) - s.Require().Equal(amount.Cmp(bal), 0, "WATOM balance should match deposited amount (expected: %s, actual: %s)", amount, bal) - - baseFeeRes, err = s.network.GetEvmClient().BaseFee(s.network.GetContext(), &evmtypes.QueryBaseFeeRequest{}) - s.Require().NoError(err) - - // Call withdraw(wrapAmount) - _, err = s.factory.ExecuteContractCall( - sender.Priv, - evmtypes.EvmTxArgs{ - To: &watomAddr, - GasLimit: 100_000, - GasFeeCap: baseFeeRes.BaseFee.BigInt(), - GasTipCap: big.NewInt(1), - }, - testutiltypes.CallArgs{ - ContractABI: contracts.WATOMContract.ABI, - MethodName: "withdraw", - Args: []interface{}{amount}, - }, - ) - s.Require().NoError(err) - s.Require().NoError(s.network.NextBlock()) - - // Final WATOM balance should be 0 - bal, err = utils.GetERC20Balance(s.network, watomAddr, sender.Addr) - s.Require().NoError(err) - s.Require().Equal("0", bal.String(), "WATOM balance should be zero after withdraw") - }) - } -} diff --git a/tests/integration/x/precisebank/test_mint_integration.go b/tests/integration/x/precisebank/test_mint_integration.go deleted file mode 100644 index 0458f129..00000000 --- a/tests/integration/x/precisebank/test_mint_integration.go +++ /dev/null @@ -1,469 +0,0 @@ -package precisebank - -import ( - "fmt" - "math/big" - "math/rand" - "testing" - - "github.com/stretchr/testify/require" - - testconstants "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/x/precisebank/types" - evmtypes "github.com/cosmos/evm/x/vm/types" - - sdkmath "cosmossdk.io/math" - - sdk "github.com/cosmos/cosmos-sdk/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" -) - -func (s *KeeperIntegrationTestSuite) TestBlockedRecipient() { - // Tests that sending funds to x/precisebank is disallowed. - // x/precisebank balance is used as the reserve funds and should not be - // directly interacted with by external modules or users. - msgServer := bankkeeper.NewMsgServerImpl(s.network.App.GetBankKeeper()) - - fromAddr := sdk.AccAddress{1} - - // To x/precisebank - toAddr := s.network.App.GetAccountKeeper().GetModuleAddress(types.ModuleName) - amount := cs(c(types.IntegerCoinDenom(), 1000)) - - msg := banktypes.NewMsgSend(fromAddr, toAddr, amount) - - _, err := msgServer.Send(s.network.GetContext(), msg) - s.Require().Error(err) - - s.Require().EqualError( - err, - fmt.Sprintf("%s is not allowed to receive funds: unauthorized", toAddr.String()), - ) -} - -func (s *KeeperIntegrationTestSuite) TestMintCoinsMatchingErrors() { - // x/precisebank MintCoins should be identical to x/bank MintCoins to - // consumers. This test ensures that the panics & errors returned by - // x/precisebank are identical to x/bank. - - tests := []struct { - name string - recipientModule string - mintAmount sdk.Coins - wantErr string - wantPanic string - }{ - { - "invalid module", - "notamodule", - cs(c(types.IntegerCoinDenom(), 1000)), - "", - "module account notamodule does not exist: unknown address", - }, - { - "no mint permissions", - // Check app.go to ensure this module has no mint permissions - authtypes.FeeCollectorName, - cs(c(types.IntegerCoinDenom(), 1000)), - "", - "module account fee_collector does not have permissions to mint tokens: unauthorized", - }, - { - "invalid amount", - evmtypes.ModuleName, - sdk.Coins{sdk.Coin{Denom: types.IntegerCoinDenom(), Amount: sdkmath.NewInt(-100)}}, - fmt.Sprintf("-100%s: invalid coins", types.IntegerCoinDenom()), - "", - }, - } - - for _, tt := range tests { - s.Run(tt.name, func() { - // Reset - s.SetupTest() - - if tt.wantErr == "" && tt.wantPanic == "" { - s.Fail("test must specify either wantErr or wantPanic") - } - - if tt.wantErr != "" { - // Check x/bank MintCoins for identical error - bankErr := s.network.App.GetBankKeeper().MintCoins(s.network.GetContext(), tt.recipientModule, tt.mintAmount) - s.Require().Error(bankErr) - s.Require().EqualError(bankErr, tt.wantErr, "expected error should match x/bank MintCoins error") - - pbankErr := s.network.App.GetPreciseBankKeeper().MintCoins(s.network.GetContext(), tt.recipientModule, tt.mintAmount) - s.Require().Error(pbankErr) - // Compare strings instead of errors, as error stack is still different - s.Require().Equal( - bankErr.Error(), - pbankErr.Error(), - "x/precisebank error should match x/bank MintCoins error", - ) - } - - if tt.wantPanic != "" { - // First check the wantPanic string is correct. - // Actually specify the panic string in the test since it makes - // it more clear we are testing specific and different cases. - s.Require().PanicsWithError(tt.wantPanic, func() { - _ = s.network.App.GetBankKeeper().MintCoins(s.network.GetContext(), tt.recipientModule, tt.mintAmount) - }, "expected panic error should match x/bank MintCoins") - - s.Require().PanicsWithError(tt.wantPanic, func() { - _ = s.network.App.GetPreciseBankKeeper().MintCoins(s.network.GetContext(), tt.recipientModule, tt.mintAmount) - }, "x/precisebank panic should match x/bank MintCoins") - } - }) - } -} - -func (s *KeeperIntegrationTestSuite) TestMintCoins() { - type mintTest struct { - mintAmount sdk.Coins - // Expected **full** balances after MintCoins(mintAmount) - wantBalance sdk.Coins - } - - tests := []struct { - name string - recipientModule string - // Instead of having a start balance, we just have a list of mints to - // both test & get into desired non-default states. - mints []mintTest - }{ - { - "passthrough - unrelated", - evmtypes.ModuleName, - []mintTest{ - { - mintAmount: cs(c("busd", 1000)), - wantBalance: cs(c("busd", 1000)), - }, - }, - }, - { - "passthrough - integer denom", - evmtypes.ModuleName, - []mintTest{ - { - mintAmount: cs(c(types.IntegerCoinDenom(), 1000)), - wantBalance: cs(c(types.ExtendedCoinDenom(), 1000000000000000)), - }, - }, - }, - { - "fractional only", - evmtypes.ModuleName, - []mintTest{ - { - mintAmount: cs(c(types.ExtendedCoinDenom(), 1000)), - wantBalance: cs(c(types.ExtendedCoinDenom(), 1000)), - }, - { - mintAmount: cs(c(types.ExtendedCoinDenom(), 1000)), - wantBalance: cs(c(types.ExtendedCoinDenom(), 2000)), - }, - }, - }, - { - "fractional only with carry", - evmtypes.ModuleName, - []mintTest{ - { - // Start with (1/4 * 3) = 0.75 - mintAmount: cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().QuoRaw(4).MulRaw(3))), - wantBalance: cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().QuoRaw(4).MulRaw(3))), - }, - { - // Add another 0.50 to incur carry to test reserve on carry - mintAmount: cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().QuoRaw(2))), - wantBalance: cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().QuoRaw(4).MulRaw(5))), - }, - }, - }, - { - "fractional only, resulting in exact carry and 0 remainder", - evmtypes.ModuleName, - []mintTest{ - // mint 0.5, acc = 0.5, reserve = 1 - { - mintAmount: cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().QuoRaw(2))), - wantBalance: cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().QuoRaw(2))), - }, - // mint another 0.5, acc = 1, reserve = 0 - // Reserve actually goes down by 1 for integer carry - { - mintAmount: cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().QuoRaw(2))), - wantBalance: cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor())), - }, - }, - }, - { - "exact carry", - evmtypes.ModuleName, - []mintTest{ - { - mintAmount: cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor())), - wantBalance: cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor())), - }, - // Carry again - exact amount - { - mintAmount: cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor())), - wantBalance: cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().MulRaw(2))), - }, - }, - }, - { - "carry with extra", - evmtypes.ModuleName, - []mintTest{ - // MintCoins(C + 100) - { - mintAmount: cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().AddRaw(100))), - wantBalance: cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().AddRaw(100))), - }, - // MintCoins(C + 5), total = 2C + 105 - { - mintAmount: cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().AddRaw(5))), - wantBalance: cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().MulRaw(2).AddRaw(105))), - }, - }, - }, - { - "integer with fractional", - evmtypes.ModuleName, - []mintTest{ - { - mintAmount: cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().MulRaw(5).AddRaw(100))), - wantBalance: cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().MulRaw(5).AddRaw(100))), - }, - { - mintAmount: cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().MulRaw(2).AddRaw(5))), - wantBalance: cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().MulRaw(7).AddRaw(105))), - }, - }, - }, - { - "with passthrough", - evmtypes.ModuleName, - []mintTest{ - { - mintAmount: cs( - ci(types.ExtendedCoinDenom(), types.ConversionFactor().MulRaw(5).AddRaw(100)), - c("busd", 1000), - ), - wantBalance: cs( - ci(types.ExtendedCoinDenom(), types.ConversionFactor().MulRaw(5).AddRaw(100)), - c("busd", 1000), - ), - }, - { - mintAmount: cs( - ci(types.ExtendedCoinDenom(), types.ConversionFactor().MulRaw(2).AddRaw(5)), - c("meow", 40), - ), - wantBalance: cs( - ci(types.ExtendedCoinDenom(), types.ConversionFactor().MulRaw(7).AddRaw(105)), - c("busd", 1000), - c("meow", 40), - ), - }, - }, - }, - } - - for _, tt := range tests { - s.Run(tt.name, func() { - // Reset - s.SetupTest() - - recipientAddr := s.network.App.GetAccountKeeper().GetModuleAddress(tt.recipientModule) - - for _, mt := range tt.mints { - // Get fractional balance before mint - fracBalBefore := s.network.App.GetPreciseBankKeeper().GetFractionalBalance(s.network.GetContext(), recipientAddr) - - err := s.network.App.GetPreciseBankKeeper().MintCoins(s.network.GetContext(), tt.recipientModule, mt.mintAmount) - s.Require().NoError(err) - - // ------------------------------------------------------------- - // Check FULL balances - // x/bank balances + x/precisebank balance - // Exclude "uatom" as x/precisebank balance will include it - bankCoins := s.network.App.GetBankKeeper().GetAllBalances(s.network.GetContext(), recipientAddr) - - // Get fractional balance after mint - fracBalAfter := s.network.App.GetPreciseBankKeeper().GetFractionalBalance(s.network.GetContext(), recipientAddr) - - // Only use x/bank balances for non-uatom denoms - var denoms []string - for _, coin := range bankCoins { - // Ignore integer coins, query the extended denom instead - if coin.Denom == types.IntegerCoinDenom() { - continue - } - - denoms = append(denoms, coin.Denom) - } - - // Add the extended denom to the list of denoms to balance check - // Will be included in balance check even if x/bank doesn't have - // uatom. - denoms = append(denoms, types.ExtendedCoinDenom()) - - // All balance queries through x/precisebank - afterBalance := sdk.NewCoins() - for _, denom := range denoms { - coin := s.network.App.GetPreciseBankKeeper().GetBalance(s.network.GetContext(), recipientAddr, denom) - afterBalance = afterBalance.Add(coin) - } - - s.Require().Equal( - mt.wantBalance.String(), - afterBalance.String(), - "unexpected balance after minting %s to %s", - ) - - // Check fractinoal balance change event - if !fracBalAfter.Sub(fracBalBefore).Equal(sdkmath.ZeroInt()) { - expEvent := types.NewEventFractionalBalanceChange(recipientAddr, fracBalBefore, fracBalAfter) - events := s.network.GetContext().EventManager().Events() - s.Require().Contains(events, expEvent) - } - } - }) - } -} - -func (s *KeeperIntegrationTestSuite) TestMintCoinsRandomValueMultiDecimals() { - tests := []struct { - name string - chainID testconstants.ChainID - }{ - { - name: "6 decimals", - chainID: testconstants.SixDecimalsChainID, - }, - { - name: "12 decimals", - chainID: testconstants.TwelveDecimalsChainID, - }, - { - name: "2 decimals", - chainID: testconstants.TwoDecimalsChainID, - }, - } - - for _, tt := range tests { - s.Run(tt.name, func() { - s.SetupTestWithChainID(tt.chainID) - - // Has mint permissions - minterModuleName := evmtypes.ModuleName - minter := sdk.AccAddress([]byte{1}) - - // Target balance - targetBalance := types.ConversionFactor().MulRaw(100) - - // Setup test parameters - maxMintUnit := types.ConversionFactor().MulRaw(2).SubRaw(1) - r := rand.New(rand.NewSource(SEED)) - - totalMinted := sdkmath.ZeroInt() - mintCount := 0 - - // Continue mints as long as target balance is not reached - for { - // Check current minter balance - minterBal := s.GetAllBalances(minter).AmountOf(types.ExtendedCoinDenom()) - if minterBal.GTE(targetBalance) { - break - } - - // Generate random amount within the range of max possible mint amount - remaining := targetBalance.Sub(minterBal) - maxPossible := sdkmath.MinInt(maxMintUnit, remaining) - randAmount := sdkmath.NewIntFromBigInt(new(big.Int).Rand(r, maxPossible.BigInt())).AddRaw(1) - - // 1. mint to evm module - mintCoins := cs(ci(types.ExtendedCoinDenom(), randAmount)) - err := s.network.App.GetPreciseBankKeeper().MintCoins(s.network.GetContext(), minterModuleName, mintCoins) - s.Require().NoError(err) - - // 2. send to account - err = s.network.App.GetPreciseBankKeeper().SendCoinsFromModuleToAccount(s.network.GetContext(), minterModuleName, minter, mintCoins) - s.Require().NoError(err) - - totalMinted = totalMinted.Add(randAmount) - mintCount++ - } - - s.T().Logf("Completed %d random mints, total minted: %s", mintCount, totalMinted) - - // Check minter balance - minterBal := s.GetAllBalances(minter).AmountOf(types.ExtendedCoinDenom()) - s.Equal(minterBal.BigInt().Cmp(targetBalance.BigInt()), 0, "minter balance mismatch (expected: %s, actual: %s)", targetBalance, minterBal) - - // Check remainder - remainder := s.network.App.GetPreciseBankKeeper().GetRemainderAmount(s.network.GetContext()) - s.Equal(remainder.BigInt().Cmp(big.NewInt(0)), 0, "remainder should be zero (expected: %s, actual: %s)", big.NewInt(0), remainder) - }) - } -} - -func FuzzMintCoins(f *testing.F) { - configurator := evmtypes.NewEVMConfigurator() - configurator.ResetTestConfig() - configurator.WithEVMCoinInfo(testconstants.ExampleChainCoinInfo[testconstants.SixDecimalsChainID]) - err := configurator.Configure() - require.NoError(f, err) - - f.Add(int64(0)) - f.Add(int64(100)) - f.Add(types.ConversionFactor().Int64()) - f.Add(types.ConversionFactor().QuoRaw(2).Int64()) - f.Add(types.ConversionFactor().MulRaw(5).Int64()) - f.Add(types.ConversionFactor().MulRaw(2).AddRaw(123948723).Int64()) - - f.Fuzz(func(t *testing.T, amount int64) { - // No negative amounts - if amount < 0 { - amount = -amount - } - - // Manually setup test suite since no direct Fuzz support in test suites - suite := new(KeeperIntegrationTestSuite) - suite.SetT(t) - suite.SetS(suite) - suite.SetupTest() - - mintCount := int64(10) - - suite.T().Logf("minting %d %d times", amount, mintCount) - - // Mint 10 times to include mints from non-zero balances - for i := int64(0); i < mintCount; i++ { - err := suite.network.App.GetPreciseBankKeeper().MintCoins( - suite.network.GetContext(), - evmtypes.ModuleName, - cs(c(types.ExtendedCoinDenom(), amount)), - ) - suite.Require().NoError(err) - } - - // Check full balances - recipientAddr := suite.network.App.GetAccountKeeper().GetModuleAddress(evmtypes.ModuleName) - bal := suite.network.App.GetPreciseBankKeeper().GetBalance(suite.network.GetContext(), recipientAddr, types.ExtendedCoinDenom()) - - suite.Require().Equalf( - amount*mintCount, - bal.Amount.Int64(), - "unexpected balance after minting %d %d times", - amount, - mintCount, - ) - }) -} diff --git a/tests/integration/x/precisebank/test_send_integration.go b/tests/integration/x/precisebank/test_send_integration.go deleted file mode 100644 index d819bf65..00000000 --- a/tests/integration/x/precisebank/test_send_integration.go +++ /dev/null @@ -1,988 +0,0 @@ -package precisebank - -import ( - "fmt" - "maps" - "math/big" - "math/rand" - "sort" - "testing" - - corevm "github.com/ethereum/go-ethereum/core/vm" - "github.com/stretchr/testify/require" - - testconstants "github.com/cosmos/evm/testutil/constants" - cosmosevmutils "github.com/cosmos/evm/utils" - erc20types "github.com/cosmos/evm/x/erc20/types" - feemarkettypes "github.com/cosmos/evm/x/feemarket/types" - "github.com/cosmos/evm/x/precisebank/types" - precisebanktypes "github.com/cosmos/evm/x/precisebank/types" - evmtypes "github.com/cosmos/evm/x/vm/types" - ibctransfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - - sdkmath "cosmossdk.io/math" - - 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" - 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" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" -) - -func (s *KeeperIntegrationTestSuite) TestSendCoinsFromAccountToModuleMatchingErrors() { - // No specific errors for SendCoinsFromAccountToModule, only 1 panic if - // the module account does not exist - - tests := []struct { - name string - sender sdk.AccAddress - recipientModule string - sendAmount sdk.Coins - wantPanic string - }{ - // SendCoinsFromAccountToModule specific errors/panics - { - "missing module account - passthrough", - sdk.AccAddress([]byte{2}), - "cat", - cs(c("usdc", 1000)), - "module account cat does not exist: unknown address", - }, - { - "missing module account - extended", - sdk.AccAddress([]byte{2}), - "cat", - cs(c(types.ExtendedCoinDenom(), 1000)), - "module account cat does not exist: unknown address", - }, - } - - for _, tt := range tests { - s.Run(tt.name, func() { - // Reset - s.SetupTest() - - s.Require().NotEmpty(tt.wantPanic, "test case must have a wantPanic") - - s.Require().PanicsWithError(tt.wantPanic, func() { - err := s.network.App.GetBankKeeper().SendCoinsFromAccountToModule(s.network.GetContext(), tt.sender, tt.recipientModule, tt.sendAmount) - s.Require().Error(err) - }, "wantPanic should match x/bank SendCoinsFromAccountToModule panic") - - s.Require().PanicsWithError(tt.wantPanic, func() { - err := s.network.App.GetPreciseBankKeeper().SendCoinsFromAccountToModule(s.network.GetContext(), tt.sender, tt.recipientModule, tt.sendAmount) - s.Require().Error(err) - }, "x/precisebank panic should match x/bank SendCoinsFromAccountToModule panic") - }) - } -} - -func (s *KeeperIntegrationTestSuite) TestSendCoinsFromModuleToAccountMatchingErrors() { - // Ensure errors match x/bank errors AND panics. This needs to be well - // tested before SendCoins as all send tests rely on this to initialize - // account balances. - // No unit test with mock x/bank for SendCoinsFromModuleToAccount since - // we only are testing the errors/panics specific to the method and - // remaining logic is the same as SendCoins. - - blockedMacAddrs := blockedAddresses() - precisebankAddr := s.network.App.GetAccountKeeper().GetModuleAddress(types.ModuleName) - - var blockedAddr sdk.AccAddress - // Get the first blocked address - for addr, isBlocked := range blockedMacAddrs { - // Skip x/precisebank module account - if addr == precisebankAddr.String() { - continue - } - - if isBlocked { - blockedAddr = sdk.MustAccAddressFromBech32(addr) - break - } - } - - // We need a ModuleName of another module account to send funds from. - // x/precisebank is blocked from use with SendCoinsFromModuleToAccount as we - // don't want external modules to modify x/precisebank balances. - var senderModuleName string - macPerms := getMaccPerms() - for moduleName := range macPerms { - if moduleName != types.ModuleName && moduleName != stakingtypes.BondedPoolName { - senderModuleName = moduleName - } - } - - s.Require().NotEmpty(blockedAddr, "no blocked addresses found") - s.Require().NotEmpty(senderModuleName, "no sender module name found") - - tests := []struct { - name string - senderModule string - recipient sdk.AccAddress - sendAmount sdk.Coins - wantErr string - wantPanic string - }{ - // SendCoinsFromModuleToAccount specific errors/panics - { - "missing module account - passthrough", - "cat", - sdk.AccAddress([]byte{2}), - cs(c("usdc", 1000)), - "", - "module account cat does not exist: unknown address", - }, - { - "missing module account - extended", - "cat", - sdk.AccAddress([]byte{2}), - cs(c(types.ExtendedCoinDenom(), 1000)), - "", - "module account cat does not exist: unknown address", - }, - { - "blocked recipient address - passthrough", - senderModuleName, - blockedAddr, - cs(c("usdc", 1000)), - fmt.Sprintf("%s is not allowed to receive funds: unauthorized", blockedAddr.String()), - "", - }, - { - "blocked recipient address - extended", - senderModuleName, - blockedAddr, - cs(c(types.ExtendedCoinDenom(), 1000)), - fmt.Sprintf("%s is not allowed to receive funds: unauthorized", blockedAddr.String()), - "", - }, - // SendCoins specific errors/panics - { - "invalid coins", - senderModuleName, - sdk.AccAddress([]byte{2}), - sdk.Coins{sdk.Coin{Denom: types.IntegerCoinDenom(), Amount: sdkmath.NewInt(-1)}}, - fmt.Sprintf("-1%s: invalid coins", types.IntegerCoinDenom()), - "", - }, - { - "insufficient balance - passthrough", - senderModuleName, - sdk.AccAddress([]byte{2}), - cs(c(types.IntegerCoinDenom(), 1000)), - fmt.Sprintf("spendable balance 0%s is smaller than 1000%s: insufficient funds", - types.IntegerCoinDenom(), types.IntegerCoinDenom()), - "", - }, - { - "insufficient balance - extended", - senderModuleName, - sdk.AccAddress([]byte{2}), - // We can still test insufficient bal errors with "aatom" since - // we also expect it to not exist in x/bank - cs(c(types.ExtendedCoinDenom(), 1000)), - fmt.Sprintf("spendable balance 0%s is smaller than 1000%s: insufficient funds", - types.ExtendedCoinDenom(), types.ExtendedCoinDenom()), - "", - }, - } - - for _, tt := range tests { - s.Run(tt.name, func() { - // Reset - s.SetupTest() - - if tt.wantPanic == "" && tt.wantErr == "" { - s.FailNow("test case must have a wantErr or wantPanic") - } - - if tt.wantPanic != "" { - s.Require().Empty(tt.wantErr, "test case must not have a wantErr if wantPanic is set") - - s.Require().PanicsWithError(tt.wantPanic, func() { - err := s.network.App.GetBankKeeper().SendCoinsFromModuleToAccount(s.network.GetContext(), tt.senderModule, tt.recipient, tt.sendAmount) - s.Require().Error(err) - }, "wantPanic should match x/bank SendCoinsFromModuleToAccount panic") - - s.Require().PanicsWithError(tt.wantPanic, func() { - err := s.network.App.GetPreciseBankKeeper().SendCoinsFromModuleToAccount(s.network.GetContext(), tt.senderModule, tt.recipient, tt.sendAmount) - s.Require().Error(err) - }, "x/precisebank panic should match x/bank SendCoinsFromModuleToAccount panic") - } - - if tt.wantErr != "" { - bankErr := s.network.App.GetBankKeeper().SendCoinsFromModuleToAccount(s.network.GetContext(), tt.senderModule, tt.recipient, tt.sendAmount) - s.Require().Error(bankErr) - s.Require().EqualError(bankErr, tt.wantErr, "expected error should match x/bank SendCoins error") - - pbankErr := s.network.App.GetPreciseBankKeeper().SendCoinsFromModuleToAccount(s.network.GetContext(), tt.senderModule, tt.recipient, tt.sendAmount) - s.Require().Error(pbankErr) - // Compare strings instead of errors, as error stack is still different - s.Require().Equal( - bankErr.Error(), - pbankErr.Error(), - "x/precisebank error should match x/bank SendCoins error", - ) - } - }) - } -} - -func (s *KeeperIntegrationTestSuite) TestSendCoinsMatchingErrors() { - // Ensure errors match x/bank errors - - tests := []struct { - name string - initialAmount sdk.Coins - sendAmount sdk.Coins - wantErr string - }{ - { - "invalid coins", - cs(), - sdk.Coins{sdk.Coin{Denom: types.IntegerCoinDenom(), Amount: sdkmath.NewInt(-1)}}, - fmt.Sprintf("-1%s: invalid coins", - types.IntegerCoinDenom()), - }, - { - "insufficient empty balance - passthrough", - cs(), - cs(c(types.IntegerCoinDenom(), 1000)), - fmt.Sprintf("spendable balance 0%s is smaller than 1000%s: insufficient funds", - types.IntegerCoinDenom(), types.IntegerCoinDenom()), - }, - { - "insufficient empty balance - extended", - cs(), - // We can still test insufficient bal errors with "aatom" since - // we also expect it to not exist in x/bank - cs(c(types.ExtendedCoinDenom(), 1000)), - fmt.Sprintf("spendable balance 0%s is smaller than 1000%s: insufficient funds", - types.ExtendedCoinDenom(), types.ExtendedCoinDenom()), - }, - { - "insufficient non-empty balance - passthrough", - cs(c(types.IntegerCoinDenom(), 100), c("usdc", 1000)), - cs(c(types.IntegerCoinDenom(), 1000)), - fmt.Sprintf("spendable balance 100%s is smaller than 1000%s: insufficient funds", - types.IntegerCoinDenom(), types.IntegerCoinDenom()), - }, - // non-empty aatom transfer error is tested in SendCoins, not here since - // x/bank doesn't hold aatom - } - - for _, tt := range tests { - s.Run(tt.name, func() { - // Reset - s.SetupTest() - sender := sdk.AccAddress([]byte{1}) - recipient := sdk.AccAddress([]byte{2}) - - s.Require().NotEmpty(tt.wantErr, "test case must have a wantErr") - - s.MintToAccount(sender, tt.initialAmount) - - bankErr := s.network.App.GetBankKeeper().SendCoins(s.network.GetContext(), sender, recipient, tt.sendAmount) - s.Require().Error(bankErr) - s.Require().EqualError(bankErr, tt.wantErr, "expected error should match x/bank SendCoins error") - - pbankErr := s.network.App.GetPreciseBankKeeper().SendCoins(s.network.GetContext(), sender, recipient, tt.sendAmount) - s.Require().Error(pbankErr) - // Compare strings instead of errors, as error stack is still different - s.Require().Equal( - bankErr.Error(), - pbankErr.Error(), - "x/precisebank error should match x/bank SendCoins error", - ) - }) - } -} - -func (s *KeeperIntegrationTestSuite) TestSendCoins() { - // SendCoins is tested mostly in this integration test, as a unit test with - // mocked BankKeeper overcomplicates expected keepers and makes initializing - // balances very complex. - - tests := []struct { - name string - giveStartBalSender sdk.Coins - giveStartBalRecipient sdk.Coins - giveAmt sdk.Coins - wantErr string - }{ - { - "insufficient balance error denom matches", - cs(c(types.ExtendedCoinDenom(), 10), c("usdc", 1000)), - cs(), - cs(c(types.ExtendedCoinDenom(), 1000)), - fmt.Sprintf("spendable balance 10%s is smaller than 1000%s: insufficient funds", - types.ExtendedCoinDenom(), types.ExtendedCoinDenom()), - }, - { - "passthrough - unrelated", - cs(c("cats", 1000)), - cs(), - cs(c("cats", 1000)), - "", - }, - { - "passthrough - integer denom", - cs(c(types.IntegerCoinDenom(), 1000)), - cs(), - cs(c(types.IntegerCoinDenom(), 1000)), - "", - }, - { - "passthrough & extended", - cs(c(types.IntegerCoinDenom(), 1000)), - cs(), - cs(c(types.IntegerCoinDenom(), 10), c(types.ExtendedCoinDenom(), 1)), - "", - }, - { - "aatom send - 1aatom to 0 balance", - // Starting balances - cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().MulRaw(5))), - cs(), - // Send amount - cs(c(types.ExtendedCoinDenom(), 1)), // aatom - "", - }, - { - "sender borrow from integer", - // 1uatom, 0 fractional - cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor())), - cs(), - // Send 1 with 0 fractional balance - cs(c(types.ExtendedCoinDenom(), 1)), - "", - }, - { - "sender borrow from integer - max fractional amount", - // 1uatom, 0 fractional - cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor())), - cs(), - // Max fractional amount - cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().SubRaw(1))), - "", - }, - { - "receiver carry", - cs(c(types.ExtendedCoinDenom(), 1000)), - // max fractional amount, carries over to integer - cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().SubRaw(1))), - cs(c(types.ExtendedCoinDenom(), 1)), - "", - }, - { - "receiver carry - max fractional amount", - cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().MulRaw(5))), - // max fractional amount, carries over to integer - cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().SubRaw(1))), - cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().SubRaw(1))), - "", - }, - } - - for _, tt := range tests { - s.Run(tt.name, func() { - s.SetupTest() - - sender := sdk.AccAddress([]byte{1}) - recipient := sdk.AccAddress([]byte{2}) - - // Initialize balances - s.MintToAccount(sender, tt.giveStartBalSender) - s.MintToAccount(recipient, tt.giveStartBalRecipient) - - senderBalBefore := s.GetAllBalances(sender) - recipientBalBefore := s.GetAllBalances(recipient) - - senderFracBalBefore := s.network.App.GetPreciseBankKeeper().GetFractionalBalance(s.network.GetContext(), sender) - recipientFracBalBefore := s.network.App.GetPreciseBankKeeper().GetFractionalBalance(s.network.GetContext(), recipient) - - err := s.network.App.GetPreciseBankKeeper().SendCoins(s.network.GetContext(), sender, recipient, tt.giveAmt) - if tt.wantErr != "" { - s.Require().Error(err) - s.Require().EqualError(err, tt.wantErr) - return - } - - s.Require().NoError(err) - - // Check balances - senderBalAfter := s.GetAllBalances(sender) - recipientBalAfter := s.GetAllBalances(recipient) - - senderFracBalAfter := s.network.App.GetPreciseBankKeeper().GetFractionalBalance(s.network.GetContext(), sender) - recipientFracBalAfter := s.network.App.GetPreciseBankKeeper().GetFractionalBalance(s.network.GetContext(), recipient) - - // Convert send amount coins to extended coins. i.e. if send coins - // includes uatom, convert it so that its the equivalent aatom - // amount so its easier to compare. Compare extended coins only. - sendAmountFullExtended := tt.giveAmt - sendAmountInteger := tt.giveAmt.AmountOf(types.IntegerCoinDenom()) - if !sendAmountInteger.IsZero() { - integerCoin := sdk.NewCoin(types.IntegerCoinDenom(), sendAmountInteger) - sendAmountFullExtended = sendAmountFullExtended.Sub(integerCoin) - - // Add equivalent extended coin - extendedCoinAmount := sendAmountInteger.Mul(types.ConversionFactor()) - extendedCoin := sdk.NewCoin(types.ExtendedCoinDenom(), extendedCoinAmount) - sendAmountFullExtended = sendAmountFullExtended.Add(extendedCoin) - } - - s.Require().Equal( - senderBalBefore.Sub(sendAmountFullExtended...), - senderBalAfter, - ) - - s.Require().Equal( - recipientBalBefore.Add(sendAmountFullExtended...), - recipientBalAfter, - ) - - // Check events - events := s.network.GetContext().EventManager().Events() - targetEvents := []sdk.Event{} - for _, event := range events { - if event.Type == types.EventTypeFractionalBalanceChange { - targetEvents = append(targetEvents, event) - } - } - - if !senderFracBalAfter.Sub(senderFracBalBefore).Equal(sdkmath.ZeroInt()) { - expSenderFracBalChangeEvent := types.NewEventFractionalBalanceChange( - sender, senderFracBalBefore, senderFracBalAfter, - ) - s.Require().Contains(targetEvents, expSenderFracBalChangeEvent) - } - - if !recipientFracBalAfter.Sub(recipientFracBalBefore).Equal(sdkmath.ZeroInt()) { - expRecipientFracBalChangeEvent := types.NewEventFractionalBalanceChange( - recipient, recipientFracBalBefore, recipientFracBalAfter, - ) - s.Require().Contains(targetEvents, expRecipientFracBalChangeEvent) - } - }) - } -} - -func (s *KeeperIntegrationTestSuite) TestSendCoinsMatrix() { - // SendCoins is tested mostly in this integration test, as a unit test with - // mocked BankKeeper overcomplicates expected keepers and makes initializing - // balances very complex. - - type startBalance struct { - name string - bal sdk.Coins - } - - // Run through each combination of start sender/recipient balance & send amt - // Test matrix fields: - startBalances := []startBalance{ - {"empty", cs()}, - {"integer only", cs(c(types.IntegerCoinDenom(), 1000))}, - {"extended only", cs(c(types.ExtendedCoinDenom(), 1000))}, - {"integer & extended", cs(c(types.IntegerCoinDenom(), 1000), c(types.ExtendedCoinDenom(), 1000))}, - {"integer & extended - max fractional", cs(c(types.IntegerCoinDenom(), 1000), ci(types.ExtendedCoinDenom(), types.ConversionFactor().SubRaw(1)))}, - {"integer & extended - min fractional", cs(c(types.IntegerCoinDenom(), 1000), c(types.ExtendedCoinDenom(), 1))}, - } - - sendAmts := []struct { - name string - amt sdk.Coins - }{ - { - "empty", - cs(), - }, - { - "integer only", - cs(c(types.IntegerCoinDenom(), 10)), - }, - { - "extended only", - cs(c(types.ExtendedCoinDenom(), 10)), - }, - { - "integer & extended", - cs(c(types.IntegerCoinDenom(), 10), c(types.ExtendedCoinDenom(), 1000)), - }, - { - "integer & extended - max fractional", - cs(c(types.IntegerCoinDenom(), 10), ci(types.ExtendedCoinDenom(), types.ConversionFactor().SubRaw(1))), - }, - { - "integer & extended - min fractional", - cs(c(types.IntegerCoinDenom(), 10), c(types.ExtendedCoinDenom(), 1)), - }, - } - - for _, senderStartBal := range startBalances { - for _, recipientStartBal := range startBalances { - for _, sendAmt := range sendAmts { - testName := fmt.Sprintf( - "%s -> %s (%s -> %s), send %s (%s)", - senderStartBal.name, senderStartBal.bal, - recipientStartBal.name, recipientStartBal.bal, - sendAmt.name, sendAmt.amt, - ) - - s.Run(testName, func() { - s.SetupTest() - - sender := sdk.AccAddress([]byte{1}) - recipient := sdk.AccAddress([]byte{2}) - - // Initialize balances - s.MintToAccount(sender, senderStartBal.bal) - s.MintToAccount(recipient, recipientStartBal.bal) - - // balances & send amount will only contain total equivalent - // extended coins and no integer coins so its easier to compare - senderBalBefore := s.GetAllBalances(sender) - recipientBalBefore := s.GetAllBalances(recipient) - - sendAmtNormalized := ConvertCoinsToExtendedCoinDenom(sendAmt.amt) - - err := s.network.App.GetPreciseBankKeeper().SendCoins(s.network.GetContext(), sender, recipient, sendAmt.amt) - - hasSufficientBal := senderBalBefore.IsAllGTE(sendAmtNormalized) - - if hasSufficientBal { - s.Require().NoError(err) - } else { - s.Require().Error(err, "expected insufficient funds error") - // No balance checks if insufficient funds - return - } - - // Check balances - senderBalAfter := s.GetAllBalances(sender) - recipientBalAfter := s.GetAllBalances(recipient) - - // Convert send amount coins to extended coins. i.e. if send coins - // includes uatom, convert it so that its the equivalent aatom - // amount so its easier to compare. Compare extended coins only. - - s.Require().Equal( - senderBalBefore.Sub(sendAmtNormalized...), - senderBalAfter, - ) - - s.Require().Equal( - recipientBalBefore.Add(sendAmtNormalized...), - recipientBalAfter, - ) - }) - } - } - } -} - -func (s *KeeperIntegrationTestSuite) TestSendCoinsFromAccountToModule() { - // Ensure recipient correctly matches the specified module account. Specific - // send amount and cases are handled by SendCoins() tests, so we are only - // checking SendCoinsFromAccountToModule specific behavior here. - - sender := sdk.AccAddress([]byte{1}) - recipientModule := minttypes.ModuleName - recipientAddr := s.network.App.GetAccountKeeper().GetModuleAddress(recipientModule) - - sendAmt := cs(c(types.ExtendedCoinDenom(), 1000)) - - s.MintToAccount(sender, sendAmt) - - err := s.network.App.GetPreciseBankKeeper().SendCoinsFromAccountToModule( - s.network.GetContext(), - sender, - recipientModule, - sendAmt, - ) - s.Require().NoError(err) - - // Check balances - senderBalAfter := s.GetAllBalances(sender) - recipientBalAfter := s.GetAllBalances(recipientAddr) - - s.Require().Equal( - cs(), - senderBalAfter, - ) - - s.Require().Equal( - sendAmt, - recipientBalAfter, - ) -} - -func (s *KeeperIntegrationTestSuite) TestSendCoinsFromAccountToModuleBlockedRecipientCarry() { - // Carrying to module account balance. This tests that SendCoinsFromAccountToModule - // does not fail when sending to a blocked module account. - - sender := sdk.AccAddress([]byte{1}) - - sendAmt := cs(c(types.ExtendedCoinDenom(), 1000)) - sendAmt2 := cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().SubRaw(10))) - - s.MintToAccount(sender, sendAmt.Add(sendAmt2...)) - - err := s.network.App.GetPreciseBankKeeper().SendCoinsFromAccountToModule( - s.network.GetContext(), - sender, - authtypes.FeeCollectorName, - sendAmt, - ) - s.Require().NoError(err) - - // Trigger carry for fee_collector module account - err = s.network.App.GetPreciseBankKeeper().SendCoinsFromAccountToModule( - s.network.GetContext(), - sender, - authtypes.FeeCollectorName, - sendAmt2, - ) - s.Require().NoError(err) -} - -func (s *KeeperIntegrationTestSuite) TestSendCoinsBlockedRecipientCarry() { - // Same test as TestSendCoinsFromModuleToAccount_Blocked, but with SendCoins - // which also should not fail when sending to a blocked module account. - sender := sdk.AccAddress([]byte{1}) - - sendAmt := cs(c(types.ExtendedCoinDenom(), 1000)) - sendAmt2 := cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().SubRaw(10))) - - s.MintToAccount(sender, sendAmt.Add(sendAmt2...)) - - recipient := s.network.App.GetAccountKeeper().GetModuleAddress(authtypes.FeeCollectorName) - - err := s.network.App.GetPreciseBankKeeper().SendCoins( - s.network.GetContext(), - sender, - recipient, - sendAmt, - ) - s.Require().NoError(err) - - // Trigger carry for fee_collector module account - err = s.network.App.GetPreciseBankKeeper().SendCoins( - s.network.GetContext(), - sender, - recipient, - sendAmt2, - ) - s.Require().NoError(err) -} - -func (s *KeeperIntegrationTestSuite) TestSendCoinsFromModuleToAccount() { - // Ensure sender correctly matches the specified module account. Opposite - // of SendCoinsFromAccountToModule, so we are only checking the correct - // addresses are being used. - - senderModule := evmtypes.ModuleName - senderAddr := s.network.App.GetAccountKeeper().GetModuleAddress(senderModule) - - recipient := sdk.AccAddress([]byte{1}) - - sendAmt := cs(c(types.ExtendedCoinDenom(), 1000)) - - s.MintToModuleAccount(senderModule, sendAmt) - - err := s.network.App.GetPreciseBankKeeper().SendCoinsFromModuleToAccount( - s.network.GetContext(), - senderModule, - recipient, - sendAmt, - ) - s.Require().NoError(err) - - // Check balances - senderBalAfter := s.GetAllBalances(senderAddr) - recipientBalAfter := s.GetAllBalances(recipient) - - s.Require().Equal( - cs(), - senderBalAfter, - ) - - s.Require().Equal( - sendAmt, - recipientBalAfter, - ) -} - -func (s *KeeperIntegrationTestSuite) TestSendCoinsRandomValueMultiDecimals() { - tests := []struct { - name string - chainID testconstants.ChainID - }{ - { - name: "6 decimals", - chainID: testconstants.SixDecimalsChainID, - }, - { - name: "12 decimals", - chainID: testconstants.TwelveDecimalsChainID, - }, - { - name: "2 decimals", - chainID: testconstants.TwoDecimalsChainID, - }, - } - - for _, tt := range tests { - s.Run(tt.name, func() { - s.SetupTestWithChainID(tt.chainID) - - sender := sdk.AccAddress([]byte{1}) - recipient := sdk.AccAddress([]byte{2}) - - // Initial balance large enough to cover many small sends - initialBalance := types.ConversionFactor().MulRaw(100) - s.MintToAccount(sender, cs(ci(types.ExtendedCoinDenom(), initialBalance))) - - // Setup test parameters - maxSendUnit := types.ConversionFactor().MulRaw(2).SubRaw(1) - r := rand.New(rand.NewSource(SEED)) - - totalSent := sdkmath.ZeroInt() - sentCount := 0 - - // Continue transfers as long as sender has balance remaining - for { - // Check current sender balance - senderAmount := s.GetAllBalances(sender).AmountOf(types.ExtendedCoinDenom()) - if senderAmount.IsZero() { - break - } - - // Generate random amount within the range of max possible send amount - maxPossibleSend := maxSendUnit - if maxPossibleSend.GT(senderAmount) { - maxPossibleSend = senderAmount - } - randAmount := sdkmath.NewIntFromBigInt(new(big.Int).Rand(r, maxPossibleSend.BigInt())).AddRaw(1) - - sendAmount := cs(ci(types.ExtendedCoinDenom(), randAmount)) - err := s.network.App.GetPreciseBankKeeper().SendCoins(s.network.GetContext(), sender, recipient, sendAmount) - s.NoError(err) - totalSent = totalSent.Add(randAmount) - sentCount++ - } - - s.T().Logf("Completed %d random sends, total sent: %s", sentCount, totalSent.String()) - - // Check sender balance - senderAmount := s.GetAllBalances(sender).AmountOf(types.ExtendedCoinDenom()) - s.Equal(senderAmount.BigInt().Cmp(big.NewInt(0)), 0, "sender balance should be zero") - - // Check recipient balance - recipientBal := s.GetAllBalances(recipient) - intReceived := recipientBal.AmountOf(types.ExtendedCoinDenom()).Quo(types.ConversionFactor()) - fracReceived := s.network.App.GetPreciseBankKeeper().GetFractionalBalance(s.network.GetContext(), recipient) - - expectedInt := totalSent.Quo(types.ConversionFactor()) - expectedFrac := totalSent.Mod(types.ConversionFactor()) - - s.Equal(expectedInt.BigInt().Cmp(intReceived.BigInt()), 0, "integer carry mismatch (expected: %s, received: %s)", expectedInt, intReceived) - s.Equal(expectedFrac.BigInt().Cmp(fracReceived.BigInt()), 0, "fractional balance mismatch (expected: %s, received: %s)", expectedFrac, fracReceived) - }) - } -} - -func FuzzSendCoins(f *testing.F) { - configurator := evmtypes.NewEVMConfigurator() - configurator.ResetTestConfig() - configurator.WithEVMCoinInfo(testconstants.ExampleChainCoinInfo[testconstants.SixDecimalsChainID]) - err := configurator.Configure() - require.NoError(f, err) - - f.Add(uint64(100), uint64(0), uint64(2)) - f.Add(uint64(100), uint64(100), uint64(5)) - f.Add(types.ConversionFactor().Uint64(), uint64(0), uint64(500)) - f.Add( - types.ConversionFactor().MulRaw(2).AddRaw(123948723).Uint64(), - types.ConversionFactor().MulRaw(2).Uint64(), - types.ConversionFactor().Uint64(), - ) - - f.Fuzz(func( - t *testing.T, - startBalSender uint64, - startBalReceiver uint64, - sendAmount uint64, - ) { - // Manually setup test suite since no direct Fuzz support in test suites - suite := new(KeeperIntegrationTestSuite) - suite.SetT(t) - suite.SetS(suite) - suite.SetupTest() - - sender := sdk.AccAddress([]byte{1}) - recipient := sdk.AccAddress([]byte{2}) - - // Initial balances - suite.MintToAccount(sender, cs(c(types.ExtendedCoinDenom(), int64(startBalSender)))) //nolint:gosec // G115 - suite.MintToAccount(recipient, cs(c(types.ExtendedCoinDenom(), int64(startBalReceiver)))) //nolint:gosec // G115 - - // Send amount - sendCoins := cs(c(types.ExtendedCoinDenom(), int64(sendAmount))) //nolint:gosec // G115 - err := suite.network.App.GetPreciseBankKeeper().SendCoins(suite.network.GetContext(), sender, recipient, sendCoins) - if startBalSender < sendAmount { - suite.Require().Error(err, "expected insufficient funds error") - return - } - - suite.Require().NoError(err) - - // Check full balances - balSender := suite.GetAllBalances(sender) - balReceiver := suite.GetAllBalances(recipient) - - suite.Require().Equal( - startBalSender-sendAmount, - balSender.AmountOf(types.ExtendedCoinDenom()).Uint64(), - ) - suite.Require().Equal( - startBalReceiver+sendAmount, - balReceiver.AmountOf(types.ExtendedCoinDenom()).Uint64(), - ) - }) -} - -func (s *KeeperIntegrationTestSuite) TestSendMsg_RandomValueMultiDecimals() { //nolint:revive // false positive due to file name - tests := []struct { - name string - chainID testconstants.ChainID - }{ - { - name: "6 decimals", - chainID: testconstants.SixDecimalsChainID, - }, - { - name: "12 decimals", - chainID: testconstants.TwelveDecimalsChainID, - }, - { - name: "2 decimals", - chainID: testconstants.TwoDecimalsChainID, - }, - } - - for _, tt := range tests { - s.Run(tt.name, func() { - s.SetupTestWithChainID(tt.chainID) - - sender := sdk.AccAddress([]byte{1}) - recipient := sdk.AccAddress([]byte{2}) - - // Initial balance large enough to cover many small sends - initialBalance := types.ConversionFactor().MulRaw(100) - s.MintToAccount(sender, cs(ci(types.ExtendedCoinDenom(), initialBalance))) - - // Setup test parameters - maxSendUnit := types.ConversionFactor().MulRaw(2).SubRaw(1) - r := rand.New(rand.NewSource(SEED)) - - totalSent := sdkmath.ZeroInt() - sentCount := 0 - - // Continue transfers as long as sender has balance remaining - for { - // Check current sender balance - senderAmount := s.GetAllBalances(sender).AmountOf(types.ExtendedCoinDenom()) - if senderAmount.IsZero() { - break - } - - // Generate random amount within the range of max possible send amount - maxPossibleSend := maxSendUnit - if maxPossibleSend.GT(senderAmount) { - maxPossibleSend = senderAmount - } - randAmount := sdkmath.NewIntFromBigInt(new(big.Int).Rand(r, maxPossibleSend.BigInt())).AddRaw(1) - - sendAmount := cs(ci(types.ExtendedCoinDenom(), randAmount)) - msgSend := banktypes.MsgSend{ - FromAddress: sender.String(), - ToAddress: recipient.String(), - Amount: sendAmount, - } - _, err := s.network.App.GetPreciseBankKeeper().Send(s.network.GetContext(), &msgSend) - s.NoError(err) - totalSent = totalSent.Add(randAmount) - sentCount++ - } - - s.T().Logf("Completed %d random sends, total sent: %s", sentCount, totalSent.String()) - - // Check sender balance - senderAmount := s.GetAllBalances(sender).AmountOf(types.ExtendedCoinDenom()) - s.Equal(senderAmount.BigInt().Cmp(big.NewInt(0)), 0, "sender balance should be zero") - - // Check recipient balance - recipientBal := s.GetAllBalances(recipient) - intReceived := recipientBal.AmountOf(types.ExtendedCoinDenom()).Quo(types.ConversionFactor()) - fracReceived := s.network.App.GetPreciseBankKeeper().GetFractionalBalance(s.network.GetContext(), recipient) - - expectedInt := totalSent.Quo(types.ConversionFactor()) - expectedFrac := totalSent.Mod(types.ConversionFactor()) - - s.Equal(expectedInt.BigInt().Cmp(intReceived.BigInt()), 0, "integer carry mismatch (expected: %s, received: %s)", expectedInt, intReceived) - s.Equal(expectedFrac.BigInt().Cmp(fracReceived.BigInt()), 0, "fractional balance mismatch (expected: %s, received: %s)", expectedFrac, fracReceived) - }) - } -} - -func blockedAddresses() map[string]bool { - blockedAddrs := make(map[string]bool) - - maccPerms := getMaccPerms() - accs := make([]string, 0, len(maccPerms)) - for acc := range maccPerms { - accs = append(accs, acc) - } - sort.Strings(accs) - - for _, acc := range accs { - blockedAddrs[authtypes.NewModuleAddress(acc).String()] = true - } - - blockedPrecompilesHex := evmtypes.AvailableStaticPrecompiles - for _, addr := range corevm.PrecompiledAddressesPrague { - blockedPrecompilesHex = append(blockedPrecompilesHex, addr.Hex()) - } - - for _, precompile := range blockedPrecompilesHex { - blockedAddrs[cosmosevmutils.Bech32StringFromHexAddress(precompile)] = true - } - - return blockedAddrs -} - -// module account permissions -var maccPerms = map[string][]string{ - authtypes.FeeCollectorName: nil, - distrtypes.ModuleName: nil, - ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner}, - minttypes.ModuleName: {authtypes.Minter}, - stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking}, - stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, - govtypes.ModuleName: {authtypes.Burner}, - - // Cosmos EVM modules - evmtypes.ModuleName: {authtypes.Minter, authtypes.Burner}, - feemarkettypes.ModuleName: nil, - erc20types.ModuleName: {authtypes.Minter, authtypes.Burner}, - precisebanktypes.ModuleName: {authtypes.Minter, authtypes.Burner}, -} - -// getMaccPerms returns a copy of the module account permissions -func getMaccPerms() map[string][]string { - return maps.Clone(maccPerms) -} diff --git a/tests/integration/x/precisebank/test_setup.go b/tests/integration/x/precisebank/test_setup.go deleted file mode 100644 index bab55b5f..00000000 --- a/tests/integration/x/precisebank/test_setup.go +++ /dev/null @@ -1,60 +0,0 @@ -package precisebank - -import ( - "github.com/stretchr/testify/suite" - - testconstants "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/testutil/integration/evm/factory" - "github.com/cosmos/evm/testutil/integration/evm/grpc" - "github.com/cosmos/evm/testutil/integration/evm/network" - "github.com/cosmos/evm/testutil/keyring" - - sdkmath "cosmossdk.io/math" - - sdk "github.com/cosmos/cosmos-sdk/types" -) - -const SEED = int64(42) - -type KeeperIntegrationTestSuite struct { - suite.Suite - - create network.CreateEvmApp - options []network.ConfigOption - network *network.UnitTestNetwork - factory factory.TxFactory - keyring keyring.Keyring -} - -func NewKeeperIntegrationTestSuite(create network.CreateEvmApp, options ...network.ConfigOption) *KeeperIntegrationTestSuite { - return &KeeperIntegrationTestSuite{ - create: create, - options: options, - } -} - -func (s *KeeperIntegrationTestSuite) SetupTest() { - s.SetupTestWithChainID(testconstants.SixDecimalsChainID) -} - -func (s *KeeperIntegrationTestSuite) SetupTestWithChainID(chainID testconstants.ChainID) { - s.keyring = keyring.New(2) - - options := []network.ConfigOption{ - network.WithChainID(chainID), - network.WithPreFundedAccounts(s.keyring.GetAllAccAddrs()...), - } - options = append(options, s.options...) - nw := network.NewUnitTestNetwork(s.create, options...) - gh := grpc.NewIntegrationHandler(nw) - tf := factory.New(nw, gh) - - s.network = nw - s.factory = tf - - // Clear all fractional balances to ensure no leftover balances persist between tests - s.network.App.GetPreciseBankKeeper().IterateFractionalBalances(s.network.GetContext(), func(addr sdk.AccAddress, bal sdkmath.Int) bool { - s.network.App.GetPreciseBankKeeper().DeleteFractionalBalance(s.network.GetContext(), addr) - return false - }) -} diff --git a/tests/integration/x/precisebank/test_utils.go b/tests/integration/x/precisebank/test_utils.go deleted file mode 100644 index 2ac668c8..00000000 --- a/tests/integration/x/precisebank/test_utils.go +++ /dev/null @@ -1,96 +0,0 @@ -package precisebank - -import ( - "github.com/cosmos/evm/x/precisebank/types" - - sdkmath "cosmossdk.io/math" - - sdk "github.com/cosmos/cosmos-sdk/types" - minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" -) - -// MintToAccount mints coins to an account with the x/precisebank methods. This -// must be used when minting extended coins, ie. aatom coins. This depends on -// the methods to be properly tested to be implemented correctly. -func (s *KeeperIntegrationTestSuite) MintToAccount(addr sdk.AccAddress, amt sdk.Coins) { - accBalancesBefore := s.GetAllBalances(addr) - - err := s.network.App.GetPreciseBankKeeper().MintCoins(s.network.GetContext(), minttypes.ModuleName, amt) - s.Require().NoError(err) - - err = s.network.App.GetPreciseBankKeeper().SendCoinsFromModuleToAccount(s.network.GetContext(), minttypes.ModuleName, addr, amt) - s.Require().NoError(err) - - // Double check balances are correctly minted and sent to account - accBalancesAfter := s.GetAllBalances(addr) - - netIncrease := accBalancesAfter.Sub(accBalancesBefore...) - s.Require().Equal(ConvertCoinsToExtendedCoinDenom(amt), netIncrease) - - s.T().Logf("minted %s to %s", amt, addr) -} - -// MintToModuleAccount mints coins to an account with the x/precisebank methods. This -// must be used when minting extended coins, ie. aatom coins. This depends on -// the methods to be properly tested to be implemented correctly. -func (s *KeeperIntegrationTestSuite) MintToModuleAccount(moduleName string, amt sdk.Coins) { - moduleAddr := s.network.App.GetAccountKeeper().GetModuleAddress(moduleName) - accBalancesBefore := s.GetAllBalances(moduleAddr) - - err := s.network.App.GetPreciseBankKeeper().MintCoins(s.network.GetContext(), minttypes.ModuleName, amt) - s.Require().NoError(err) - - err = s.network.App.GetPreciseBankKeeper().SendCoinsFromModuleToModule(s.network.GetContext(), minttypes.ModuleName, moduleName, amt) - s.Require().NoError(err) - - // Double check balances are correctly minted and sent to account - accBalancesAfter := s.GetAllBalances(moduleAddr) - - netIncrease := accBalancesAfter.Sub(accBalancesBefore...) - s.Require().Equal(ConvertCoinsToExtendedCoinDenom(amt), netIncrease) - - s.T().Logf("minted %s to %s", amt, moduleName) -} - -// GetAllBalances returns all the account balances for the given account address. -// This returns the extended coin balance if the account has a non-zero balance, -// WITHOUT the integer coin balance. -func (s *KeeperIntegrationTestSuite) GetAllBalances(addr sdk.AccAddress) sdk.Coins { - // Get all balances for an account - bankBalances := s.network.App.GetBankKeeper().GetAllBalances(s.network.GetContext(), addr) - - // Remove integer coins from the balance - for _, coin := range bankBalances { - if coin.Denom == types.IntegerCoinDenom() { - bankBalances = bankBalances.Sub(coin) - } - } - - // Replace the integer coin with the extended coin, from x/precisebank - extendedBal := s.network.App.GetPreciseBankKeeper().GetBalance(s.network.GetContext(), addr, types.ExtendedCoinDenom()) - - return bankBalances.Add(extendedBal) -} - -// ConvertCoinsToExtendedCoinDenom converts sdk.Coins that includes Integer denoms -// to sdk.Coins that includes Extended denoms of the same amount. This is useful -// for testing to make sure only extended amounts are compared instead of double -// counting balances. -func ConvertCoinsToExtendedCoinDenom(coins sdk.Coins) sdk.Coins { - integerCoinAmt := coins.AmountOf(types.IntegerCoinDenom()) - if integerCoinAmt.IsZero() { - return coins - } - - // Remove the integer coin from the coins - integerCoin := sdk.NewCoin(types.IntegerCoinDenom(), integerCoinAmt) - - // Add the equivalent extended coin to the coins - extendedCoin := sdk.NewCoin(types.ExtendedCoinDenom(), integerCoinAmt.Mul(types.ConversionFactor())) - - return coins.Sub(integerCoin).Add(extendedCoin) -} - -func c(denom string, amount int64) sdk.Coin { return sdk.NewInt64Coin(denom, amount) } -func ci(denom string, amount sdkmath.Int) sdk.Coin { return sdk.NewCoin(denom, amount) } -func cs(coins ...sdk.Coin) sdk.Coins { return sdk.NewCoins(coins...) } diff --git a/tests/integration/x/precisebank/test_view_integration.go b/tests/integration/x/precisebank/test_view_integration.go deleted file mode 100644 index 48c877ef..00000000 --- a/tests/integration/x/precisebank/test_view_integration.go +++ /dev/null @@ -1,188 +0,0 @@ -package precisebank - -import ( - "github.com/cosmos/evm/x/precisebank/types" - - sdkmath "cosmossdk.io/math" - - sdk "github.com/cosmos/cosmos-sdk/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" -) - -func (s *KeeperIntegrationTestSuite) TestKeeperSpendableCoin() { - tests := []struct { - name string - giveDenom string // queried denom for balance - - giveBankBal sdk.Coins // full balance - giveFractionalBal sdkmath.Int // stored fractional balance for giveAddr - giveLockedCoins sdk.Coins // locked coins - - wantSpendableBal sdk.Coin - }{ - { - "extended denom, no fractional - locked coins", - types.ExtendedCoinDenom(), - // queried bank balance in uatom when querying for aatom - sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom(), sdkmath.NewInt(1000))), - sdkmath.ZeroInt(), - sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom(), sdkmath.NewInt(10))), - // (integer + fractional) - locked - sdk.NewCoin( - types.ExtendedCoinDenom(), - types.ConversionFactor().MulRaw(1000-10), - ), - }, - { - "extended denom, with fractional - locked coins", - types.ExtendedCoinDenom(), - // queried bank balance in uatom when querying for aatom - sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom(), sdkmath.NewInt(1000))), - sdkmath.NewInt(5000), - sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom(), sdkmath.NewInt(10))), - sdk.NewCoin( - types.ExtendedCoinDenom(), - // (integer - locked) + fractional - types.ConversionFactor().MulRaw(1000-10).AddRaw(5000), - ), - }, - { - "non-extended denom - uatom returns uatom", - types.IntegerCoinDenom(), - sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom(), sdkmath.NewInt(1000))), - sdkmath.ZeroInt(), - sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom(), sdkmath.NewInt(10))), - sdk.NewCoin(types.IntegerCoinDenom(), sdkmath.NewInt(990)), - }, - { - "non-extended denom, with fractional - uatom returns uatom", - types.IntegerCoinDenom(), - sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom(), sdkmath.NewInt(1000))), - // does not affect balance - sdkmath.NewInt(100), - sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom(), sdkmath.NewInt(10))), - sdk.NewCoin(types.IntegerCoinDenom(), sdkmath.NewInt(990)), - }, - } - - for _, tt := range tests { - s.Run(tt.name, func() { - s.SetupTest() - - addr := sdk.AccAddress([]byte("test-address")) - - s.MintToAccount(addr, tt.giveBankBal) - - // Set fractional balance in store before query - s.network.App.GetPreciseBankKeeper().SetFractionalBalance(s.network.GetContext(), addr, tt.giveFractionalBal) - - // Add some locked coins - acc := s.network.App.GetAccountKeeper().GetAccount(s.network.GetContext(), addr) - if acc == nil { - acc = authtypes.NewBaseAccount(addr, nil, 0, 0) - } - - vestingAcc, err := vestingtypes.NewPeriodicVestingAccount( - acc.(*authtypes.BaseAccount), - tt.giveLockedCoins, - s.network.GetContext().BlockTime().Unix(), - vestingtypes.Periods{ - vestingtypes.Period{ - Length: 100, - Amount: tt.giveLockedCoins, - }, - }, - ) - s.Require().NoError(err) - s.network.App.GetAccountKeeper().SetAccount(s.network.GetContext(), vestingAcc) - - fetchedLockedCoins := vestingAcc.LockedCoins(s.network.GetContext().BlockTime()) - s.Require().Equal( - tt.giveLockedCoins, - fetchedLockedCoins, - "locked coins should be matching at current block time", - ) - - spendableCoinsWithLocked := s.network.App.GetPreciseBankKeeper().SpendableCoin(s.network.GetContext(), addr, tt.giveDenom) - - s.Require().Equalf( - tt.wantSpendableBal, - spendableCoinsWithLocked, - "expected spendable coins of denom %s", - tt.giveDenom, - ) - }) - } -} - -func (s *KeeperIntegrationTestSuite) TestKeeperHiddenReserve() { - // Reserve balances should not be shown to consumers of x/precisebank, as it - // represents the fractional balances of accounts. - - moduleAddr := authtypes.NewModuleAddress(types.ModuleName) - addr1 := sdk.AccAddress{1} - - // Make the reserve hold a non-zero balance - // Mint fractional coins to an account, which should cause a mint of 1 - // integer coin to the reserve to back it. - extCoin := sdk.NewCoin(types.ExtendedCoinDenom(), types.ConversionFactor().AddRaw(1000)) - unrelatedCoin := sdk.NewCoin("unrelated", sdkmath.NewInt(1000)) - s.MintToAccount( - addr1, - sdk.NewCoins( - extCoin, - unrelatedCoin, - ), - ) - - // Check underlying x/bank balance for reserve - reserveIntCoin := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), moduleAddr, types.IntegerCoinDenom()) - s.Require().Equal( - sdkmath.NewInt(2), // Network setup creates 1, test mints 1 more = 2 total - reserveIntCoin.Amount, - "reserve should hold 2 integer coins (1 from network setup + 1 from test mint)", - ) - - tests := []struct { - name string - giveAddr sdk.AccAddress - giveDenom string - wantAmount sdkmath.Int - }{ - { - "reserve account - hidden extended denom", - moduleAddr, - types.ExtendedCoinDenom(), - sdkmath.ZeroInt(), - }, - { - "reserve account - visible integer denom", - moduleAddr, - types.IntegerCoinDenom(), - sdkmath.NewInt(2), // Network setup creates 1, test mints 1 more = 2 total - }, - { - "user account - visible extended denom", - addr1, - types.ExtendedCoinDenom(), - extCoin.Amount, - }, - { - "user account - visible integer denom", - addr1, - types.IntegerCoinDenom(), - extCoin.Amount.Quo(types.ConversionFactor()), - }, - } - - for _, tt := range tests { - s.Run(tt.name, func() { - coin := s.network.App.GetPreciseBankKeeper().GetBalance(s.network.GetContext(), tt.giveAddr, tt.giveDenom) - s.Require().Equal(tt.wantAmount.Int64(), coin.Amount.Int64()) - - spendableCoin := s.network.App.GetPreciseBankKeeper().SpendableCoin(s.network.GetContext(), tt.giveAddr, tt.giveDenom) - s.Require().Equal(tt.wantAmount.Int64(), spendableCoin.Amount.Int64()) - }) - } -} diff --git a/tests/integration/x/vm/benchmark_statedb.go b/tests/integration/x/vm/benchmark_statedb.go index 9006a643..1d2282cb 100644 --- a/tests/integration/x/vm/benchmark_statedb.go +++ b/tests/integration/x/vm/benchmark_statedb.go @@ -68,7 +68,7 @@ func BenchmarkSetCode(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { - vmdb.SetCode(suite.Keyring.GetAddr(0), hash) + vmdb.SetCode(suite.Keyring.GetAddr(0), hash, 0x0) } } @@ -83,7 +83,7 @@ func BenchmarkSetState(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { - vmdb.SetCode(suite.Keyring.GetAddr(0), hash) + vmdb.SetCode(suite.Keyring.GetAddr(0), hash, 0x0) } } diff --git a/tests/integration/x/vm/state_transition_benchmark.go b/tests/integration/x/vm/state_transition_benchmark.go index e3e0a2c9..f8c5913d 100644 --- a/tests/integration/x/vm/state_transition_benchmark.go +++ b/tests/integration/x/vm/state_transition_benchmark.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" utiltx "github.com/cosmos/evm/testutil/tx" + "github.com/cosmos/evm/x/vm/statedb" evmtypes "github.com/cosmos/evm/x/vm/types" "github.com/cosmos/cosmos-sdk/crypto/keyring" @@ -128,11 +129,11 @@ func newEthMsgTx( templateDynamicFeeTx.Nonce = nonce if data != nil { - templateAccessListTx.Data = data + templateDynamicFeeTx.Data = data } else { - templateAccessListTx.Data = []byte{} + templateDynamicFeeTx.Data = []byte{} } - templateAccessListTx.AccessList = accessList + templateDynamicFeeTx.AccessList = accessList ethTx = ethtypes.NewTx(templateDynamicFeeTx) baseFee = big.NewInt(3) case ethtypes.SetCodeTxType: @@ -165,7 +166,7 @@ func newNativeMessage( txType byte, data []byte, accessList ethtypes.AccessList, - authorizationList []ethtypes.SetCodeAuthorization, //nolint:unparam + authorizationList []ethtypes.SetCodeAuthorization, ) (*core.Message, error) { msg, baseFee, err := newEthMsgTx(nonce, address, krSigner, ethSigner, txType, data, accessList, authorizationList) if err != nil { @@ -287,8 +288,10 @@ func BenchmarkApplyMessage(b *testing.B) { ) require.NoError(b, err) + stateDB := statedb.New(suite.Network.GetContext(), suite.Network.App.GetEVMKeeper(), statedb.NewEmptyTxConfig()) + b.StartTimer() - resp, err := suite.Network.App.GetEVMKeeper().ApplyMessage(suite.Network.GetContext(), *m, nil, true, false) + resp, err := suite.Network.App.GetEVMKeeper().ApplyMessage(suite.Network.GetContext(), stateDB, *m, nil, true, false, false) b.StopTimer() require.NoError(b, err) @@ -314,15 +317,17 @@ func BenchmarkApplyMessageWithLegacyTx(b *testing.B) { addr, krSigner, signer, - ethtypes.AccessListTxType, + ethtypes.LegacyTxType, nil, nil, nil, ) require.NoError(b, err) + stateDB := statedb.New(suite.Network.GetContext(), suite.Network.App.GetEVMKeeper(), statedb.NewEmptyTxConfig()) + b.StartTimer() - resp, err := suite.Network.App.GetEVMKeeper().ApplyMessage(suite.Network.GetContext(), *m, nil, true, false) + resp, err := suite.Network.App.GetEVMKeeper().ApplyMessage(suite.Network.GetContext(), stateDB, *m, nil, true, false, false) b.StopTimer() require.NoError(b, err) @@ -355,8 +360,10 @@ func BenchmarkApplyMessageWithDynamicFeeTx(b *testing.B) { ) require.NoError(b, err) + stateDB := statedb.New(suite.Network.GetContext(), suite.Network.App.GetEVMKeeper(), statedb.NewEmptyTxConfig()) + b.StartTimer() - resp, err := suite.Network.App.GetEVMKeeper().ApplyMessage(suite.Network.GetContext(), *m, nil, true, false) + resp, err := suite.Network.App.GetEVMKeeper().ApplyMessage(suite.Network.GetContext(), stateDB, *m, nil, true, false, false) b.StopTimer() require.NoError(b, err) diff --git a/tests/integration/x/vm/test_benchmark.go b/tests/integration/x/vm/test_benchmark.go index 77847f07..454eeba1 100644 --- a/tests/integration/x/vm/test_benchmark.go +++ b/tests/integration/x/vm/test_benchmark.go @@ -10,13 +10,13 @@ import ( testconstants "github.com/cosmos/evm/testutil/constants" utiltx "github.com/cosmos/evm/testutil/tx" + vmkeeper "github.com/cosmos/evm/x/vm/keeper" "github.com/cosmos/evm/x/vm/keeper/testdata" "github.com/cosmos/evm/x/vm/types" sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" - authante "github.com/cosmos/cosmos-sdk/x/auth/ante" ) func SetupContract(b *testing.B) (*KeeperTestSuite, common.Address) { @@ -73,7 +73,7 @@ func DoBenchmark(b *testing.B, txBuilder TxBuilder) { ctx, _ := suite.Network.GetContext().CacheContext() fees := sdk.Coins{sdk.NewCoin(suite.EvmDenom(), sdkmath.NewIntFromBigInt(msg.GetFee()))} - err = authante.DeductFees(suite.Network.App.GetBankKeeper(), suite.Network.GetContext(), suite.Network.App.GetAccountKeeper().GetAccount(ctx, msg.GetFrom()), fees) + err = vmkeeper.DeductFees(suite.Network.App.GetBankKeeper(), suite.Network.App.GetEVMKeeper(), suite.Network.GetContext(), suite.Network.App.GetAccountKeeper().GetAccount(ctx, msg.GetFrom()), fees) require.NoError(b, err) rsp, err := suite.Network.App.GetEVMKeeper().EthereumTx(ctx, msg) @@ -198,7 +198,7 @@ func BenchmarkMessageCall(b *testing.B) { ctx, _ := suite.Network.GetContext().CacheContext() fees := sdk.Coins{sdk.NewCoin(suite.EvmDenom(), sdkmath.NewIntFromBigInt(msg.GetFee()))} - err = authante.DeductFees(suite.Network.App.GetBankKeeper(), suite.Network.GetContext(), suite.Network.App.GetAccountKeeper().GetAccount(ctx, msg.GetFrom()), fees) + err = vmkeeper.DeductFees(suite.Network.App.GetBankKeeper(), suite.Network.App.GetEVMKeeper(), suite.Network.GetContext(), suite.Network.App.GetAccountKeeper().GetAccount(ctx, msg.GetFrom()), fees) require.NoError(b, err) rsp, err := suite.Network.App.GetEVMKeeper().EthereumTx(ctx, msg) diff --git a/tests/integration/x/vm/test_call_evm.go b/tests/integration/x/vm/test_call_evm.go index 013b200f..359d8d0d 100644 --- a/tests/integration/x/vm/test_call_evm.go +++ b/tests/integration/x/vm/test_call_evm.go @@ -9,25 +9,41 @@ import ( testconstants "github.com/cosmos/evm/testutil/constants" utiltx "github.com/cosmos/evm/testutil/tx" "github.com/cosmos/evm/x/erc20/types" + "github.com/cosmos/evm/x/vm/statedb" evmtypes "github.com/cosmos/evm/x/vm/types" + + sdk "github.com/cosmos/cosmos-sdk/types" ) func (s *KeeperTestSuite) TestCallEVM() { wcosmosEVMContract := common.HexToAddress(testconstants.WEVMOSContractMainnet) testCases := []struct { - name string - method string - expPass bool + name string + method string + stateDB *statedb.StateDB + expPass bool + expError string }{ { "unknown method", "", + nil, false, + "", }, { "pass", "balanceOf", + nil, true, + "", + }, + { + "fail with nil statedb", + "balanceOf", + nil, + false, + "stateDB cannot be nil", }, } for _, tc := range testCases { @@ -35,12 +51,23 @@ func (s *KeeperTestSuite) TestCallEVM() { erc20 := contracts.ERC20MinterBurnerDecimalsContract.ABI account := utiltx.GenerateAddress() - res, err := s.Network.App.GetEVMKeeper().CallEVM(s.Network.GetContext(), erc20, types.ModuleAddress, wcosmosEVMContract, false, nil, tc.method, account) + + var stateDB *statedb.StateDB + if tc.stateDB == nil && tc.name != "fail with nil statedb" { + stateDB = statedb.New(s.Network.GetContext(), s.Network.App.GetEVMKeeper(), statedb.NewEmptyTxConfig()) + } else { + stateDB = tc.stateDB + } + + res, err := s.Network.App.GetEVMKeeper().CallEVM(s.Network.GetContext(), stateDB, erc20, types.ModuleAddress, wcosmosEVMContract, false, false, nil, tc.method, account) if tc.expPass { s.Require().IsTypef(&evmtypes.MsgEthereumTxResponse{}, res, tc.name) s.Require().NoError(err) } else { s.Require().Error(err) + if tc.expError != "" { + s.Require().Contains(err.Error(), tc.expError) + } } } } @@ -48,69 +75,111 @@ func (s *KeeperTestSuite) TestCallEVM() { func (s *KeeperTestSuite) TestCallEVMWithData() { erc20 := contracts.ERC20MinterBurnerDecimalsContract.ABI wcosmosEVMContract := common.HexToAddress(testconstants.WEVMOSContractMainnet) + + // Deployments run from a dedicated EOA rather than a module account. + // It also fails in practice: contract creation bumps the sender's nonce, + // SetAccount writes nonce and balance together, and the EVM commit path may + // not write a module account's balance. + deployer := common.BytesToAddress([]byte("vm-test-deployer")) + // The sender's sequence is read before the message runs, so the account has to exist. + ensureDeployer := func() { + ctx := s.Network.GetContext() + ak := s.Network.App.GetAccountKeeper() + accAddr := sdk.AccAddress(deployer.Bytes()) + if ak.GetAccount(ctx, accAddr) == nil { + ak.SetAccount(ctx, ak.NewAccountWithAddress(ctx, accAddr)) + } + } + testCases := []struct { name string from common.Address malleate func() []byte deploy bool + useNilDB bool expPass bool + expError string }{ { - "pass with unknown method", - types.ModuleAddress, - func() []byte { + name: "pass with unknown method", + from: types.ModuleAddress, + malleate: func() []byte { account := utiltx.GenerateAddress() data, _ := erc20.Pack("", account) return data }, - false, - true, + deploy: false, + useNilDB: false, + expPass: true, + expError: "", }, { - "pass", - types.ModuleAddress, - func() []byte { + name: "pass", + from: types.ModuleAddress, + malleate: func() []byte { account := utiltx.GenerateAddress() data, _ := erc20.Pack("balanceOf", account) return data }, - false, - true, + deploy: false, + useNilDB: false, + expPass: true, + expError: "", }, { - "pass with empty data", - types.ModuleAddress, - func() []byte { + name: "pass with empty data", + from: types.ModuleAddress, + malleate: func() []byte { return []byte{} }, - false, - true, + deploy: false, + useNilDB: false, + expPass: true, + expError: "", }, - { - "fail empty sender", - common.Address{}, - func() []byte { + name: "fail empty sender", + from: common.Address{}, + malleate: func() []byte { return []byte{} }, - false, - false, + deploy: false, + useNilDB: false, + expPass: false, + expError: "", + }, + { + name: "fail with nil statedb", + from: types.ModuleAddress, + malleate: func() []byte { + account := utiltx.GenerateAddress() + data, _ := erc20.Pack("balanceOf", account) + return data + }, + deploy: false, + useNilDB: true, + expPass: false, + expError: "stateDB cannot be nil", }, { - "deploy", - types.ModuleAddress, - func() []byte { + name: "deploy", + from: deployer, + malleate: func() []byte { + ensureDeployer() ctorArgs, _ := contracts.ERC20MinterBurnerDecimalsContract.ABI.Pack("", "test", "test", uint8(18)) data := append(contracts.ERC20MinterBurnerDecimalsContract.Bin, ctorArgs...) //nolint:gocritic return data }, - true, - true, + deploy: true, + useNilDB: false, + expPass: true, + expError: "", }, { - "fail deploy", - types.ModuleAddress, - func() []byte { + name: "fail deploy", + from: deployer, + malleate: func() []byte { + ensureDeployer() params := s.Network.App.GetEVMKeeper().GetParams(s.Network.GetContext()) params.AccessControl.Create = evmtypes.AccessControlType{ AccessType: evmtypes.AccessTypeRestricted, @@ -120,8 +189,24 @@ func (s *KeeperTestSuite) TestCallEVMWithData() { data := append(contracts.ERC20MinterBurnerDecimalsContract.Bin, ctorArgs...) //nolint:gocritic return data }, - true, - false, + deploy: true, + useNilDB: false, + expPass: false, + expError: "does not have permission to deploy contracts", + }, + { + name: "fail deploy with nil statedb", + from: deployer, + malleate: func() []byte { + ensureDeployer() + ctorArgs, _ := contracts.ERC20MinterBurnerDecimalsContract.ABI.Pack("", "test", "test", uint8(18)) + data := append(contracts.ERC20MinterBurnerDecimalsContract.Bin, ctorArgs...) //nolint:gocritic + return data + }, + deploy: true, + useNilDB: true, + expPass: false, + expError: "stateDB cannot be nil", }, } @@ -133,10 +218,15 @@ func (s *KeeperTestSuite) TestCallEVMWithData() { var res *evmtypes.MsgEthereumTxResponse var err error + var stateDB *statedb.StateDB + if !tc.useNilDB { + stateDB = statedb.New(s.Network.GetContext(), s.Network.App.GetEVMKeeper(), statedb.NewEmptyTxConfig()) + } + if tc.deploy { - res, err = s.Network.App.GetEVMKeeper().CallEVMWithData(s.Network.GetContext(), tc.from, nil, data, true, nil) + res, err = s.Network.App.GetEVMKeeper().CallEVMWithData(s.Network.GetContext(), stateDB, tc.from, nil, data, true, false, nil) } else { - res, err = s.Network.App.GetEVMKeeper().CallEVMWithData(s.Network.GetContext(), tc.from, &wcosmosEVMContract, data, false, nil) + res, err = s.Network.App.GetEVMKeeper().CallEVMWithData(s.Network.GetContext(), stateDB, tc.from, &wcosmosEVMContract, data, false, false, nil) } if tc.expPass { @@ -144,6 +234,9 @@ func (s *KeeperTestSuite) TestCallEVMWithData() { s.Require().NoError(err) } else { s.Require().Error(err) + if tc.expError != "" { + s.Require().Contains(err.Error(), tc.expError) + } } }) } diff --git a/tests/integration/x/vm/test_commit_idempotency.go b/tests/integration/x/vm/test_commit_idempotency.go new file mode 100644 index 00000000..3a3797d2 --- /dev/null +++ b/tests/integration/x/vm/test_commit_idempotency.go @@ -0,0 +1,235 @@ +package vm + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/holiman/uint256" + + vmkeeper "github.com/cosmos/evm/x/vm/keeper" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// TestCommitIdempotency verifies that calling FlushToCacheCtx multiple times +// without any state changes produces identical results across all branches in commitWithCtx: +// - DeleteAccount (self-destructed) +// - SetCode/DeleteCode (code operations) +// - SetAccount (account updates) +// - SetState/DeleteState (storage operations) +func (s *KeeperTestSuite) TestCommitIdempotency() { + s.SetupTest() + evmKeeper := s.Network.App.GetEVMKeeper() + + // Setup test accounts + addr1 := common.BytesToAddress([]byte("addr1")) + addr2 := common.BytesToAddress([]byte("addr2")) + addr3 := common.BytesToAddress([]byte("addr3")) + addr4 := common.BytesToAddress([]byte("addr4")) + + // Test data + code := []byte{0x60, 0x80, 0x60, 0x40, 0x52} // sample bytecode + emptyCodeHash := crypto.Keccak256Hash(nil) + storageKey1 := common.HexToHash("0x1") + storageKey2 := common.HexToHash("0x2") + + // Setup state to cover all branches + db := s.StateDB() + cacheCtx, err := db.GetCacheContext() + s.Require().NoError(err) + + // addr1: Account with code and storage (tests SetCode + SetState) + db.CreateAccount(addr1) + code1 := []byte{0x60, 0x42} + db.SetCode(addr1, code1, 0x0) + db.SetState(addr1, storageKey1, common.HexToHash("0x456")) + db.AddBalance(addr1, uint256ToInt(big.NewInt(1000)), 0) + + // addr2: Account with empty/deleted code (tests DeleteCode) + db.CreateAccount(addr2) + db.SetCode(addr2, nil, 0x0) + db.AddBalance(addr2, uint256ToInt(big.NewInt(2000)), 0) + + // addr3: Self-destructed account (tests DeleteAccount) + db.CreateAccount(addr3) + db.SetCode(addr3, code, 0x0) + db.SelfDestruct(addr3) + + // addr4: Account with storage deleted (tests DeleteState) + db.CreateAccount(addr4) + db.SetState(addr4, storageKey1, common.Hash{}) // deleted storage + db.SetState(addr4, storageKey2, common.HexToHash("0x789")) + db.AddBalance(addr4, uint256ToInt(big.NewInt(4000)), 0) + + // Commit once to persist state + err = db.FlushToCacheCtx() + s.Require().NoError(err) + + // Capture state after first commit + snapshot1 := captureState(cacheCtx, evmKeeper, []common.Address{addr1, addr2, addr3, addr4}) + + err = db.FlushToCacheCtx() + s.Require().NoError(err) + + snapshot2 := captureState(cacheCtx, evmKeeper, []common.Address{addr1, addr2, addr3, addr4}) + + err = db.FlushToCacheCtx() + s.Require().NoError(err) + + snapshot3 := captureState(cacheCtx, evmKeeper, []common.Address{addr1, addr2, addr3, addr4}) + + // All snapshots should be identical + s.Require().Equal(snapshot1, snapshot2, "First and second commit should produce identical state") + s.Require().Equal(snapshot2, snapshot3, "Second and third commit should produce identical state") + + // Verify specific invariants + s.Require().Equal(code1, evmKeeper.GetCode(cacheCtx, crypto.Keccak256Hash(code1))) + s.Require().Empty(evmKeeper.GetCode(cacheCtx, emptyCodeHash)) + s.Require().Nil(evmKeeper.GetAccount(cacheCtx, addr3)) + s.Require().Equal(common.Hash{}, evmKeeper.GetState(cacheCtx, addr4, storageKey1)) +} + +// TestCommitIdempotencyWithStorage tests idempotency of storage operations +func (s *KeeperTestSuite) TestCommitIdempotencyWithStorage() { + s.SetupTest() + evmKeeper := s.Network.App.GetEVMKeeper() + + addr := common.BytesToAddress([]byte("testaddr")) + storageKey := common.HexToHash("0x1") + targetValue := common.HexToHash("0x222") + + // Setup: Create account and set storage + db := s.StateDB() + cacheCtx, err := db.GetCacheContext() + s.Require().NoError(err) + db.CreateAccount(addr) + db.SetState(addr, storageKey, targetValue) + err = db.FlushToCacheCtx() + s.Require().NoError(err) + + snapshot1 := evmKeeper.GetState(cacheCtx, addr, storageKey) + + // Multiple commits without changes should be idempotent + err = db.FlushToCacheCtx() + s.Require().NoError(err) + snapshot2 := evmKeeper.GetState(cacheCtx, addr, storageKey) + + err = db.FlushToCacheCtx() + s.Require().NoError(err) + snapshot3 := evmKeeper.GetState(cacheCtx, addr, storageKey) + + s.Require().Equal(snapshot1, snapshot2) + s.Require().Equal(snapshot2, snapshot3) + s.Require().Equal(targetValue, snapshot3) +} + +// TestCommitIdempotencyWithCodeDeletion tests idempotency of code deletion +func (s *KeeperTestSuite) TestCommitIdempotencyWithCodeDeletion() { + s.SetupTest() + evmKeeper := s.Network.App.GetEVMKeeper() + + addr := common.BytesToAddress([]byte("testaddr")) + + // Setup: Create account and delete code + db := s.StateDB() + cacheCtx, err := db.GetCacheContext() + s.Require().NoError(err) + db.CreateAccount(addr) + db.SetCode(addr, nil, 0x0) + err = db.FlushToCacheCtx() + s.Require().NoError(err) + + codeHash1 := evmKeeper.GetCodeHash(cacheCtx, addr) + + // Multiple commits without changes should be idempotent + err = db.FlushToCacheCtx() + s.Require().NoError(err) + codeHash2 := evmKeeper.GetCodeHash(cacheCtx, addr) + + err = db.FlushToCacheCtx() + s.Require().NoError(err) + codeHash3 := evmKeeper.GetCodeHash(cacheCtx, addr) + + s.Require().Equal(codeHash1, codeHash2) + s.Require().Equal(codeHash2, codeHash3) +} + +// TestCommitIdempotencyWithSelfDestruct tests idempotency of account deletion +func (s *KeeperTestSuite) TestCommitIdempotencyWithSelfDestruct() { + s.SetupTest() + evmKeeper := s.Network.App.GetEVMKeeper() + + addr := common.BytesToAddress([]byte("testaddr")) + + // Setup: Create account and self-destruct + db := s.StateDB() + cacheCtx, err := db.GetCacheContext() + s.Require().NoError(err) + db.CreateAccount(addr) + db.SelfDestruct(addr) + err = db.FlushToCacheCtx() + s.Require().NoError(err) + + account1 := evmKeeper.GetAccount(cacheCtx, addr) + + // Multiple commits without changes should be idempotent + err = db.FlushToCacheCtx() + s.Require().NoError(err) + account2 := evmKeeper.GetAccount(cacheCtx, addr) + + err = db.FlushToCacheCtx() + s.Require().NoError(err) + account3 := evmKeeper.GetAccount(cacheCtx, addr) + + s.Require().Nil(account1) + s.Require().Nil(account2) + s.Require().Nil(account3) +} + +// accountState captures relevant account state for comparison +type accountState struct { + Exists bool + Balance *big.Int + Nonce uint64 + CodeHash common.Hash + StorageState map[common.Hash]common.Hash +} + +// stateSnapshot captures the state of multiple accounts +type stateSnapshot map[common.Address]accountState + +// captureState reads and captures the current state of given addresses +func captureState(ctx sdk.Context, evmKeeper *vmkeeper.Keeper, addrs []common.Address) stateSnapshot { + snapshot := make(stateSnapshot) + + for _, addr := range addrs { + account := evmKeeper.GetAccount(ctx, addr) + if account == nil { + snapshot[addr] = accountState{Exists: false} + continue + } + + storage := make(map[common.Hash]common.Hash) + // Capture all storage keys for this address + evmKeeper.ForEachStorage(ctx, addr, func(key, value common.Hash) bool { + storage[key] = value + return true + }) + + snapshot[addr] = accountState{ + Exists: true, + Balance: account.Balance.ToBig(), + Nonce: account.Nonce, + CodeHash: common.BytesToHash(account.CodeHash), + StorageState: storage, + } + } + + return snapshot +} + +func uint256ToInt(i *big.Int) *uint256.Int { + u, _ := uint256.FromBig(i) + return u +} diff --git a/tests/integration/x/vm/test_ctx.go b/tests/integration/x/vm/test_ctx.go index 6603fb9c..2aa0f4be 100644 --- a/tests/integration/x/vm/test_ctx.go +++ b/tests/integration/x/vm/test_ctx.go @@ -4,7 +4,7 @@ import ( "github.com/cosmos/evm/testutil/integration/evm/network" evmante "github.com/cosmos/evm/x/vm/ante" - storetypes "cosmossdk.io/store/types" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" ) func (s *EvmAnteTestSuite) TestBuildEvmExecutionCtx() { diff --git a/tests/integration/x/vm/test_eip7702_nonce.go b/tests/integration/x/vm/test_eip7702_nonce.go new file mode 100644 index 00000000..ad48d496 --- /dev/null +++ b/tests/integration/x/vm/test_eip7702_nonce.go @@ -0,0 +1,129 @@ +package vm + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/holiman/uint256" + + testKeyring "github.com/cosmos/evm/testutil/keyring" + testutiltypes "github.com/cosmos/evm/testutil/types" + "github.com/cosmos/evm/x/vm/keeper/testdata" + evmtypes "github.com/cosmos/evm/x/vm/types" +) + +// TestEIP7702NonceIncrement tests that when a user with EIP-7702 delegation +// deploys a contract whose constructor calls back to the user (via the delegation) +// and deploys more contracts, the user's nonce is correctly incremented. +// +// This test reproduces a bug where the nonce was unconditionally reset to msg.Nonce+1 +// after evm.Create(), ignoring any nonce increments that occurred during execution. +// +// Bug scenario: +// 1. User (with EIP-7702 delegation) sends contract creation tx with nonce N +// 2. evm.Create() increments User's nonce to N+1 +// 3. Constructor calls back to User via delegation, deploying more contracts +// 4. Each nested CREATE increments User's nonce (N+2, N+3, ...) +// 5. BUG: After evm.Create() returns, nonce is reset to N+1, losing all increments +func (s *KeeperTestSuite) TestEIP7702NonceIncrement() { + s.SetupTest() + + delegationTarget, err := testdata.LoadDelegationTargetContract() + s.Require().NoError(err) + + maliciousDeployer, err := testdata.LoadMaliciousDeployerContract() + s.Require().NoError(err) + + chainIDUint256 := uint256.NewInt(evmtypes.GetChainConfig().GetChainId()) + + // Use key 0 as BOTH the delegated EOA AND the deployer + // This is critical - the bug only manifests when the tx sender + // is the same address that gets called back via EIP-7702 + user := s.Keyring.GetKey(0) + // Use key 1 just to deploy the DelegationTarget contract initially + helper := s.Keyring.GetKey(1) + + // Deploy DelegationTarget contract (using helper account) + delegationTargetAddr, err := s.Factory.DeployContract( + helper.Priv, + evmtypes.EvmTxArgs{GasLimit: 5_000_000}, + testutiltypes.ContractDeploymentData{ + Contract: delegationTarget, + }, + ) + s.Require().NoError(err) + s.Require().NoError(s.Network.NextBlock()) + + // Set up EIP-7702 delegation for user -> DelegationTarget + // User delegates their account to DelegationTarget code + s.setupDelegationSameAccount(user, delegationTargetAddr, chainIDUint256) + s.Require().NoError(s.Network.NextBlock()) + + // Verify delegation was set + code := s.Network.App.GetEVMKeeper().GetCode( + s.Network.GetContext(), + s.Network.App.GetEVMKeeper().GetCodeHash(s.Network.GetContext(), user.Addr), + ) + delegationAddr, ok := ethtypes.ParseDelegation(code) + s.Require().True(ok, "delegation should be set") + s.Require().Equal(delegationTargetAddr, delegationAddr) + + // Get initial nonce of user (should be 2: one for setcode tx auth increment) + initialNonce := s.Network.App.GetEVMKeeper().GetNonce(s.Network.GetContext(), user.Addr) + + // User deploys MaliciousDeployer + // The constructor will call back to user.Addr (which has DelegationTarget code) + // and deploy numContracts contracts through it + numContracts := uint64(30) + + _, err = s.Factory.DeployContract( + user.Priv, + evmtypes.EvmTxArgs{GasLimit: 10_000_000}, + testutiltypes.ContractDeploymentData{ + Contract: maliciousDeployer, + ConstructorArgs: []interface{}{user.Addr, big.NewInt(int64(numContracts)), big.NewInt(int64(1))}, + }, + ) + s.Require().NoError(err) + s.Require().NoError(s.Network.NextBlock()) + + // Verify the nonce + finalNonce := s.Network.App.GetEVMKeeper().GetNonce(s.Network.GetContext(), user.Addr) + + // Expected: initialNonce + 1 (for MaliciousDeployer creation) + numContracts (nested CREATEs) + // The +1 comes from go-ethereum incrementing nonce at the start of evm.Create() + // The +numContracts comes from the nested CREATE calls through the delegation + expectedNonce := initialNonce + 1 + numContracts + s.Require().Equal(expectedNonce, finalNonce, + "user nonce should be %d (initial %d + 1 for deployment + %d nested creates), but got %d", + expectedNonce, initialNonce, numContracts, finalNonce) +} + +// setupDelegationSameAccount sets up EIP-7702 delegation where the user +// sends the SetCode tx for themselves. In this case, the authorization nonce +// must be currentNonce + 1 because the tx increments the nonce before +// the authorization is applied. +func (s *KeeperTestSuite) setupDelegationSameAccount(user testKeyring.Key, targetAddr common.Address, chainID *uint256.Int) { + accResp, err := s.Handler.GetEvmAccount(user.Addr) + s.Require().NoError(err) + + // When sender == authority, authorization nonce must be currentNonce + 1 + auth := ethtypes.SetCodeAuthorization{ + ChainID: *chainID, + Address: targetAddr, + Nonce: accResp.GetNonce() + 1, + } + + signedAuth := s.SignSetCodeAuthorization(user, auth) + + zeroAddr := common.Address{} + txArgs := evmtypes.EvmTxArgs{ + To: &zeroAddr, + GasLimit: 100_000, + AuthorizationList: []ethtypes.SetCodeAuthorization{signedAuth}, + } + + _, err = s.Factory.ExecuteEthTx(user.Priv, txArgs) + s.Require().NoError(err) +} diff --git a/tests/integration/x/vm/test_fees.go b/tests/integration/x/vm/test_fees.go index f3cf852a..40b13dfc 100644 --- a/tests/integration/x/vm/test_fees.go +++ b/tests/integration/x/vm/test_fees.go @@ -511,11 +511,11 @@ func (s *KeeperTestSuite) TestVerifyFeeAndDeductTxCostsFromUserBalance() { if tc.expectPassVerify { s.Require().NoError(err, "valid test %d failed - '%s'", i, tc.name) if tc.EnableFeemarket { - baseFee := s.Network.App.GetFeeMarketKeeper().GetBaseFee(s.Network.GetContext()) + baseFee := s.Network.App.GetEVMKeeper().GetBaseFee(s.Network.GetContext()) s.Require().Equal( fees, sdk.NewCoins( - sdk.NewCoin(baseDenom, sdkmath.NewIntFromBigInt(tx.GetEffectiveFee(baseFee.TruncateInt().BigInt()))), + sdk.NewCoin(baseDenom, sdkmath.NewIntFromBigInt(tx.GetEffectiveFee(baseFee))), ), "valid test %d failed, fee value is wrong - '%s'", i, tc.name, ) diff --git a/tests/integration/x/vm/test_grpc_query.go b/tests/integration/x/vm/test_grpc_query.go index 52f73539..7867bd31 100644 --- a/tests/integration/x/vm/test_grpc_query.go +++ b/tests/integration/x/vm/test_grpc_query.go @@ -1,10 +1,12 @@ package vm import ( + "encoding/hex" "encoding/json" "fmt" "math" "math/big" + "strings" "testing" "github.com/ethereum/go-ethereum/common" @@ -24,7 +26,6 @@ import ( "github.com/cosmos/evm/testutil/tx" testutiltypes "github.com/cosmos/evm/testutil/types" feemarkettypes "github.com/cosmos/evm/x/feemarket/types" - types2 "github.com/cosmos/evm/x/precisebank/types" "github.com/cosmos/evm/x/vm/keeper/testdata" "github.com/cosmos/evm/x/vm/statedb" "github.com/cosmos/evm/x/vm/types" @@ -349,7 +350,7 @@ func (s *KeeperTestSuite) TestQueryCode() { expCode = []byte("code") stateDB := s.Network.GetStateDB() - stateDB.SetCode(addr, expCode) + stateDB.SetCode(addr, expCode, 0x0) s.Require().NoError(stateDB.Commit()) req = &types.QueryCodeRequest{ @@ -385,7 +386,7 @@ func (s *KeeperTestSuite) TestQueryTxLogs() { expLogs := []*types.Log{} txHash := common.BytesToHash([]byte("tx_hash")) txIndex := uint(1) - logIndex := uint(1) + logIndex := uint(0) testCases := []struct { msg string @@ -427,7 +428,6 @@ func (s *KeeperTestSuite) TestQueryTxLogs() { txCfg := statedb.NewTxConfig( txHash, txIndex, - logIndex, ) vmdb := statedb.New( s.Network.GetContext(), @@ -449,6 +449,8 @@ func (s *KeeperTestSuite) TestQueryParams() { expParams := types.DefaultParams() expParams.ActiveStaticPrecompiles = types.AvailableStaticPrecompiles expParams.ExtraEIPs = nil + expParams.EvmDenom = testconstants.ExampleAttoDenom + expParams.ExtendedDenomOptions = &types.ExtendedDenomOptions{ExtendedDenom: testconstants.ExampleAttoDenom} res, err := s.Network.GetEvmClient().Params(ctx, &types.QueryParamsRequest{}) s.Require().NoError(err) @@ -929,7 +931,7 @@ func (s *KeeperTestSuite) TestEstimateGas() { // Update feemarket params per test evmParams := feemarkettypes.DefaultParams() if !tc.EnableFeemarket { - evmParams := s.Network.App.GetFeeMarketKeeper().GetParams( + evmParams = s.Network.App.GetFeeMarketKeeper().GetParams( s.Network.GetContext(), ) evmParams.NoBaseFee = true @@ -967,6 +969,183 @@ func (s *KeeperTestSuite) TestEstimateGas() { } } +func (s *KeeperTestSuite) TestEstimateGasWithStateOverrides() { + // Hardcode recipient address to avoid non determinism in tests + hardcodedRecipient := common.HexToAddress("0xC6Fe5D33615a1C52c08018c47E8Bc53646A0E101") + + erc20Contract, err := testdata.LoadERC20Contract() + s.Require().NoError(err) + + testCases := []struct { + msg string + getArgs func() types.TransactionArgs + getOverrides func() string + expPass bool + expGas uint64 + EnableFeemarket bool + gasCap uint64 + }{ + { + "success - native transfer with balance override", + func() types.TransactionArgs { + addr := s.Keyring.GetAddr(0) + recipient := common.HexToAddress("0x963EBDf2e1f8DB8707D05FC75bfeFFBa1B5BaC17") + return types.TransactionArgs{ + From: &addr, + To: &recipient, + Value: (*hexutil.Big)(big.NewInt(10000000000000000)), // 0.01 ether + } + }, + func() string { + // Override recipient's balance to 0 + return `{ + "0x963EBDf2e1f8DB8707D05FC75bfeFFBa1B5BaC17": { + "balance": "0x0" + } + }` + }, + true, + ethparams.TxGas, + false, + config.DefaultGasCap, + }, + { + "success - erc20 transfer with code and storage override", + func() types.TransactionArgs { + addr := s.Keyring.GetAddr(0) + contractAddr := common.HexToAddress("0x5555555555555555555555555555555555555555") + + // Prepare transfer(address,uint256) call data + // 100 TOKEN with 18 decimals + amount := new(big.Int) + amount.SetString("100000000000000000000", 10) + transferData, err := erc20Contract.ABI.Pack( + "transfer", + hardcodedRecipient, + amount, + ) + s.Require().NoError(err) + + return types.TransactionArgs{ + From: &addr, + To: &contractAddr, + Input: (*hexutil.Bytes)(&transferData), + } + }, + func() string { + // Override contract code and sender's balance in ERC20 contract + // Storage slot for balances[sender] - simplified for testing + erc20Contract, err := testdata.LoadERC20Contract() + s.Require().NoError(err) + + sender := s.Keyring.GetAddr(0) + slot := crypto.Keccak256Hash( + common.LeftPadBytes(sender.Bytes(), common.HashLength), + make([]byte, common.HashLength), + ) + + amount := new(big.Int) + amount.SetString("100000000000000000000", 10) + + contractHex := hex.EncodeToString(erc20Contract.Bin) + runtimeIdx := strings.Index(contractHex, "f3fe") + s.Require().Greater(runtimeIdx, -1) + runtimeHex := contractHex[runtimeIdx+4:] + + overrides := map[string]map[string]interface{}{ + "0x5555555555555555555555555555555555555555": { + "code": "0x" + runtimeHex, + "stateDiff": map[string]string{ + slot.Hex(): fmt.Sprintf("0x%064x", amount), + }, + }, + } + + bz, err := json.Marshal(overrides) + s.Require().NoError(err) + + return string(bz) + }, + true, + 49140, + false, + config.DefaultGasCap, + }, + { + "success - override account nonce", + func() types.TransactionArgs { + addr := s.Keyring.GetAddr(0) + return types.TransactionArgs{ + From: &addr, + To: &common.Address{}, + Value: (*hexutil.Big)(big.NewInt(100)), + } + }, + func() string { + addr := s.Keyring.GetAddr(0) + return fmt.Sprintf(`{ + "%s": { + "nonce": "0x10" + } + }`, addr.Hex()) + }, + true, + ethparams.TxGas, + false, + config.DefaultGasCap, + }, + } + + for _, tc := range testCases { + s.Run(fmt.Sprintf("Case %s", tc.msg), func() { + // Start from a clean state + s.Require().NoError(s.Network.NextBlock()) + + // Update feemarket params per test + evmParams := feemarkettypes.DefaultParams() + if !tc.EnableFeemarket { + evmParams = s.Network.App.GetFeeMarketKeeper().GetParams( + s.Network.GetContext(), + ) + evmParams.NoBaseFee = true + } + + err := s.Network.App.GetFeeMarketKeeper().SetParams( + s.Network.GetContext(), + evmParams, + ) + s.Require().NoError(err) + + // Get call args + args := tc.getArgs() + marshalArgs, err := json.Marshal(args) + s.Require().NoError(err) + + // Get overrides + overrides := json.RawMessage(tc.getOverrides()) + + req := types.EthCallRequest{ + Args: marshalArgs, + GasCap: tc.gasCap, + ProposerAddress: s.Network.GetContext().BlockHeader().ProposerAddress, + Overrides: overrides, + } + + // Function under test + rsp, err := s.Network.GetEvmClient().EstimateGas( + s.Network.GetContext(), + &req, + ) + if tc.expPass { + s.Require().NoError(err) + s.Require().Equal(int64(tc.expGas), int64(rsp.Gas)) //#nosec G115 + } else { + s.Require().Error(err) + } + }) + } +} + func getDefaultTraceTxRequest(unitNetwork network.Network) *types.QueryTraceTxRequest { ctx := unitNetwork.GetContext() chainID := unitNetwork.GetEIP155ChainID().Int64() @@ -2054,7 +2233,6 @@ func (s *KeeperTestSuite) TestBalance() { balance, ok := sdkmath.NewIntFromString(balanceResp.Balance) s.Require().True(ok) - balance = balance.Quo(types2.ConversionFactor()) s.Require().NotEqual(balance.String(), "0") // replace with vesting account @@ -2101,7 +2279,6 @@ func (s *KeeperTestSuite) TestBalance() { balance, ok := sdkmath.NewIntFromString(balanceResp.Balance) s.Require().True(ok) - balance = balance.Quo(types2.ConversionFactor()) s.Require().NotEqual(balance.String(), "0") // replace with vesting account diff --git a/tests/integration/x/vm/test_hooks.go b/tests/integration/x/vm/test_hooks.go index 23aef41a..b834396d 100644 --- a/tests/integration/x/vm/test_hooks.go +++ b/tests/integration/x/vm/test_hooks.go @@ -72,7 +72,6 @@ func (s *KeeperTestSuite) TestEvmHooks() { vmdb := statedb.New(ctx, k, statedb.NewTxConfig( txHash, 0, - 0, )) vmdb.AddLog(ðtypes.Log{ @@ -110,10 +109,6 @@ func (s *KeeperTestSuite) TestPostTxProcessingFailureLogReversion() { err = s.Network.App.GetBankKeeper().SendCoinsFromModuleToAccount(ctx, "mint", sender.AccAddr, coins) s.Require().NoError(err) - // Store original transient state - originalBloom := k.GetBlockBloomTransient(ctx) - originalLogSize := k.GetLogSizeTransient(ctx) - // Create a simple transfer transaction transferArgs := types.EvmTxArgs{ To: &recipient, @@ -136,13 +131,4 @@ func (s *KeeperTestSuite) TestPostTxProcessingFailureLogReversion() { // Critical test: Verify logs are completely cleared s.Require().Nil(res.Logs, "res.Logs should be nil after PostTxProcessing failure") - - // Critical test: Verify transient state was not updated when PostTx failed - finalBloom := k.GetBlockBloomTransient(ctx) - finalLogSize := k.GetLogSizeTransient(ctx) - - s.Require().Equal(originalBloom.String(), finalBloom.String(), - "BlockBloomTransient should not be updated when PostTxProcessing fails") - s.Require().Equal(originalLogSize, finalLogSize, - "LogSizeTransient should not be updated when PostTxProcessing fails") } diff --git a/tests/integration/x/vm/test_msg_server.go b/tests/integration/x/vm/test_msg_server.go index 8f776f9c..4659d77d 100644 --- a/tests/integration/x/vm/test_msg_server.go +++ b/tests/integration/x/vm/test_msg_server.go @@ -6,12 +6,15 @@ import ( ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/holiman/uint256" + cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + "github.com/cosmos/evm/testutil/integration/evm/utils" "github.com/cosmos/evm/x/vm/types" sdkmath "cosmossdk.io/math" sdktypes "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ) @@ -121,12 +124,15 @@ func (s *KeeperTestSuite) TestEthereumTx() { for _, tc := range testCases { s.Run(tc.name, func() { - // Fund fee collector account + // Fund fee collector account's virtual balance. + // With virtual fee collection enabled, RefundGas uses SendCoinsFromModuleToAccountVirtual + // which checks the virtual (object store) balance, not the real balance. ctx := s.Network.GetContext() coins := sdktypes.NewCoins(sdktypes.NewCoin(types.GetEVMCoinDenom(), sdkmath.NewInt(1e18))) err := s.Network.App.GetBankKeeper().MintCoins(ctx, "mint", coins) s.Require().NoError(err) - err = s.Network.App.GetBankKeeper().SendCoinsFromModuleToModule(ctx, "mint", "fee_collector", coins) + mintAddr := authtypes.NewModuleAddress("mint") + err = s.Network.App.GetBankKeeper().SendCoinsFromAccountToModuleVirtual(ctx, mintAddr, authtypes.FeeCollectorName, coins) s.Require().NoError(err) // Get EthereumTx msg @@ -173,7 +179,7 @@ func (s *KeeperTestSuite) TestUpdateParams() { getMsg: func() *types.MsgUpdateParams { return &types.MsgUpdateParams{Authority: "foobar"} }, - expectedErr: govtypes.ErrInvalidSigner, + expectedErr: sdkerrors.ErrUnauthorized, }, { name: "pass - valid Update msg", @@ -216,7 +222,7 @@ func (s *KeeperTestSuite) TestRegisterPreinstalls() { getMsg: func() *types.MsgRegisterPreinstalls { return &types.MsgRegisterPreinstalls{Authority: "foobar"} }, - expectedErr: govtypes.ErrInvalidSigner, + expectedErr: sdkerrors.ErrUnauthorized, }, { name: "pass - valid Update msg", @@ -260,3 +266,77 @@ func (s *KeeperTestSuite) TestRegisterPreinstalls() { s.Require().NoError(err) } } + +// TestUpdateParamsAuthority verifies that the EVM keeper resolves the +// authority through the consensus AuthorityParams when set, and otherwise +// falls back to the keeper's authority. +func (s *KeeperTestSuite) TestUpdateParamsAuthority() { + s.SetupTest() + + keeperAuthority := s.Network.App.GetEVMKeeper().GetAuthority().String() + overrideAuthority := sdktypes.AccAddress("override_authority___").String() + s.Require().NotEqual(keeperAuthority, overrideAuthority) + + s.Run("fallback to keeper authority when consensus authority is unset", func() { + ctx := s.Network.GetContext() + + _, err := s.Network.App.GetEVMKeeper().UpdateParams(ctx, &types.MsgUpdateParams{ + Authority: keeperAuthority, + Params: types.DefaultParams(), + }) + s.Require().NoError(err) + + _, err = s.Network.App.GetEVMKeeper().UpdateParams(ctx, &types.MsgUpdateParams{ + Authority: overrideAuthority, + Params: types.DefaultParams(), + }) + s.Require().Error(err) + s.Require().Contains(err.Error(), "invalid authority") + }) + + s.Run("consensus authority takes precedence over keeper authority", func() { + ctx := s.Network.GetContext().WithConsensusParams(cmtproto.ConsensusParams{ + Authority: &cmtproto.AuthorityParams{Authority: overrideAuthority}, + }) + + _, err := s.Network.App.GetEVMKeeper().UpdateParams(ctx, &types.MsgUpdateParams{ + Authority: overrideAuthority, + Params: types.DefaultParams(), + }) + s.Require().NoError(err) + + _, err = s.Network.App.GetEVMKeeper().UpdateParams(ctx, &types.MsgUpdateParams{ + Authority: keeperAuthority, + Params: types.DefaultParams(), + }) + s.Require().Error(err) + s.Require().Contains(err.Error(), "invalid authority") + }) + + s.Run("RegisterPreinstalls honors consensus authority override", func() { + ctx := s.Network.GetContext().WithConsensusParams(cmtproto.ConsensusParams{ + Authority: &cmtproto.AuthorityParams{Authority: overrideAuthority}, + }) + + _, err := s.Network.App.GetEVMKeeper().RegisterPreinstalls(ctx, &types.MsgRegisterPreinstalls{ + Authority: keeperAuthority, + Preinstalls: []types.Preinstall{{ + Name: "AuthOverride1", + Address: "0xb364E75b1189DcbBF7f0C856456c1ba8e4d6481b", + Code: "0x000000000", + }}, + }) + s.Require().Error(err) + s.Require().Contains(err.Error(), "invalid authority") + + _, err = s.Network.App.GetEVMKeeper().RegisterPreinstalls(ctx, &types.MsgRegisterPreinstalls{ + Authority: overrideAuthority, + Preinstalls: []types.Preinstall{{ + Name: "AuthOverride2", + Address: "0xc364E75b1189DcbBF7f0C856456c1ba8e4d6481b", + Code: "0x000000000", + }}, + }) + s.Require().NoError(err) + }) +} diff --git a/tests/integration/x/vm/test_state_transition.go b/tests/integration/x/vm/test_state_transition.go index f44f5d5e..9b9f2bf6 100644 --- a/tests/integration/x/vm/test_state_transition.go +++ b/tests/integration/x/vm/test_state_transition.go @@ -26,11 +26,12 @@ import ( utiltx "github.com/cosmos/evm/testutil/tx" feemarkettypes "github.com/cosmos/evm/x/feemarket/types" "github.com/cosmos/evm/x/vm/keeper" + "github.com/cosmos/evm/x/vm/statedb" "github.com/cosmos/evm/x/vm/types" sdkmath "cosmossdk.io/math" - storetypes "cosmossdk.io/store/types" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" 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" @@ -38,6 +39,8 @@ import ( govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ) +const TestPostProcessingEventType = "test_post_processing_event" + func (s *KeeperTestSuite) TestContextSetConsensusParams() { // set new value of max gas in consensus params maxGas := int64(123456789) @@ -69,7 +72,7 @@ func (s *KeeperTestSuite) TestContextSetConsensusParams() { // evm should query the max gas from consensus keeper, yielding the number set above. vm := s.Network.App.GetEVMKeeper().NewEVM(queryContext, *msg, cfg, nil, s.Network.GetStateDB()) - //nolint:gosec + s.Require().Equal(vm.Context.GasLimit, uint64(maxGas)) // if we explicitly set the consensus params in context, like when Cosmos builds a transaction context, @@ -156,15 +159,27 @@ func (s *KeeperTestSuite) TestGetCoinbaseAddress() { msg string malleate func() sdk.Context expPass bool + expEmpty bool }{ + { + "empty proposer address - should return empty address without error", + func() sdk.Context { + header := s.Network.GetContext().BlockHeader() + header.ProposerAddress = sdk.ConsAddress{} + return s.Network.GetContext().WithBlockHeader(header) + }, + true, + true, + }, { "validator not found", func() sdk.Context { header := s.Network.GetContext().BlockHeader() - header.ProposerAddress = []byte{} + header.ProposerAddress = []byte{1, 2, 3} return s.Network.GetContext().WithBlockHeader(header) }, false, + false, }, { "success", @@ -172,23 +187,33 @@ func (s *KeeperTestSuite) TestGetCoinbaseAddress() { return s.Network.GetContext() }, true, + false, }, } for _, tc := range testCases { s.Run(fmt.Sprintf("Case %s", tc.msg), func() { ctx := tc.malleate() - proposerAddress := ctx.BlockHeader().ProposerAddress + var proposerAddress sdk.ConsAddress + if tc.expEmpty { + proposerAddress = sdk.ConsAddress{} + } else { + proposerAddress = ctx.BlockHeader().ProposerAddress + } // Function being tested coinbase, err := s.Network.App.GetEVMKeeper().GetCoinbaseAddress( ctx, - sdk.ConsAddress(proposerAddress), + proposerAddress, ) if tc.expPass { s.Require().NoError(err) - s.Require().Equal(proposerAddressHex, coinbase) + if tc.expEmpty { + s.Require().Equal(common.Address{}, coinbase) + } else { + s.Require().Equal(proposerAddressHex, coinbase) + } } else { s.Require().Error(err) } @@ -411,6 +436,14 @@ func (s *KeeperTestSuite) TestRefundGas() { grpcHandler := grpc.NewIntegrationHandler(unitNetwork) txFactory := factory.New(unitNetwork, grpcHandler) + // With virtual fee collection enabled, RefundGas uses virtual balance. + // Move the fee collector's real coins into its virtual balance. + feeCollectorAddr := authtypes.NewModuleAddress(authtypes.FeeCollectorName) + err := unitNetwork.App.GetBankKeeper().SendCoinsFromAccountToModuleVirtual( + unitNetwork.GetContext(), feeCollectorAddr, authtypes.FeeCollectorName, coins, + ) + s.Require().NoError(err) + sender := Keyring.GetKey(0) recipient := Keyring.GetAddr(1) @@ -488,6 +521,7 @@ func (s *KeeperTestSuite) TestRefundGas() { unitNetwork.GetContext(), *coreMsg, refund, + gasUsed, unitNetwork.GetBaseDenom(), ) @@ -592,6 +626,13 @@ func (s *KeeperTestSuite) TestApplyTransaction() { 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) + // With virtual fee collection enabled, RefundGas uses virtual balance. + // Move the fee collector's real coins into its virtual balance. + feeCollectorAddr := authtypes.NewModuleAddress(authtypes.FeeCollectorName) + err = s.Network.App.GetBankKeeper().SendCoinsFromAccountToModuleVirtual( + ctx, feeCollectorAddr, authtypes.FeeCollectorName, sdk.NewCoins(sdk.NewCoin("aatom", sdkmath.NewInt(3e18))), + ) + s.Require().NoError(err) testCases := []struct { name string gasLimit uint64 @@ -653,6 +694,7 @@ func (s *KeeperTestSuite) TestApplyTransactionWithTxPostProcessing() { keeper.NewMultiEvmHooks( &testHooks{ postProcessing: func(ctx sdk.Context, sender common.Address, msg core.Message, receipt *gethtypes.Receipt) error { + ctx.EventManager().EmitEvent(sdk.NewEvent(TestPostProcessingEventType)) return nil }, }, @@ -684,7 +726,17 @@ func (s *KeeperTestSuite) TestApplyTransactionWithTxPostProcessing() { s.Require().Equal(senderBefore.Sub(sdkmath.NewIntFromBigInt(transferAmt)), senderAfter) s.Require().Equal(recipientBefore.Add(sdkmath.NewIntFromBigInt(transferAmt)), recipientAfter) }, - func(s *KeeperTestSuite) {}, + func(s *KeeperTestSuite) { + // check if the event emitted exactly once + events := s.Network.GetContext().EventManager().Events() + var postProcessingEvents []sdk.Event + for _, event := range events { + if event.Type == TestPostProcessingEventType { + postProcessingEvents = append(postProcessingEvents, event) + } + } + s.Require().Len(postProcessingEvents, 1) + }, }, { "pass - evm tx succeeds, post processing is called but fails, the balance is unchanged", @@ -800,31 +852,68 @@ func (s *KeeperTestSuite) TestApplyMessage() { defer func() { s.EnableFeemarket = false }() s.SetupTest() - // Generate a transfer tx message - sender := s.Keyring.GetKey(0) - recipient := s.Keyring.GetAddr(1) - transferArgs := types.EvmTxArgs{ - To: &recipient, - Amount: big.NewInt(100), + testCases := []struct { + name string + useNilDB bool + expPass bool + expError string + }{ + { + name: "success", + useNilDB: false, + expPass: true, + expError: "", + }, + { + name: "fail with nil statedb", + useNilDB: true, + expPass: false, + expError: "stateDB cannot be nil", + }, } - coreMsg, err := s.Factory.GenerateGethCoreMsg( - sender.Priv, - transferArgs, - ) - s.Require().NoError(err) - tracer := s.Network.App.GetEVMKeeper().Tracer( - s.Network.GetContext(), - *coreMsg, - types.GetEthChainConfig(), - ) - res, err := s.Network.App.GetEVMKeeper().ApplyMessage(s.Network.GetContext(), *coreMsg, tracer, true, false) - s.Require().NoError(err) - s.Require().False(res.Failed()) + for _, tc := range testCases { + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + // Generate a transfer tx message + sender := s.Keyring.GetKey(0) + recipient := s.Keyring.GetAddr(1) + transferArgs := types.EvmTxArgs{ + To: &recipient, + Amount: big.NewInt(100), + } + coreMsg, err := s.Factory.GenerateGethCoreMsg( + sender.Priv, + transferArgs, + ) + s.Require().NoError(err) + + tracer := s.Network.App.GetEVMKeeper().Tracer( + s.Network.GetContext(), + *coreMsg, + types.GetEthChainConfig(), + ) + + var stateDB *statedb.StateDB + if !tc.useNilDB { + stateDB = statedb.New(s.Network.GetContext(), s.Network.App.GetEVMKeeper(), statedb.NewEmptyTxConfig()) + } + + res, err := s.Network.App.GetEVMKeeper().ApplyMessage(s.Network.GetContext(), stateDB, *coreMsg, tracer, true, false, false) - // Compare gas to a transfer tx gas - expectedGasUsed := params.TxGas - s.Require().Equal(expectedGasUsed, res.GasUsed) + if tc.expPass { + s.Require().NoError(err) + s.Require().False(res.Failed()) + // Compare gas to a transfer tx gas + expectedGasUsed := params.TxGas + s.Require().Equal(expectedGasUsed, res.GasUsed) + } else { + s.Require().Error(err) + if tc.expError != "" { + s.Require().Contains(err.Error(), tc.expError) + } + } + }) + } } func (s *KeeperTestSuite) TestApplyMessageWithConfig() { @@ -835,6 +924,7 @@ func (s *KeeperTestSuite) TestApplyMessageWithConfig() { testAddr := utiltx.GenerateAddress() balance := (*hexutil.Big)(big.NewInt(1000000000000000000)) nonce := hexutil.Uint64(0) + movedStaticPrecompileAddr := utiltx.GenerateAddress() overrides := rpctypes.StateOverride{ testAddr: rpctypes.OverrideAccount{ @@ -843,12 +933,19 @@ func (s *KeeperTestSuite) TestApplyMessageWithConfig() { }, } + staticPrecompileMoveOverrides := rpctypes.StateOverride{ + common.HexToAddress(types.DistributionPrecompileAddress): rpctypes.OverrideAccount{ + MovePrecompileTo: &movedStaticPrecompileAddr, + }, + } + testCases := []struct { name string getMessage func() core.Message getEVMParams func() types.Params getFeeMarketParams func() feemarkettypes.Params overrides *rpctypes.StateOverride + useNilDB bool expErr bool expVMErr bool expectedGasUsed uint64 @@ -869,6 +966,7 @@ func (s *KeeperTestSuite) TestApplyMessageWithConfig() { getEVMParams: types.DefaultParams, getFeeMarketParams: feemarkettypes.DefaultParams, overrides: nil, + useNilDB: false, expErr: false, expVMErr: false, expectedGasUsed: params.TxGas, @@ -1014,6 +1112,29 @@ func (s *KeeperTestSuite) TestApplyMessageWithConfig() { expVMErr: false, expectedGasUsed: params.TxGas, }, + { + name: "success - move cosmos static precompile with state overrides", + getMessage: func() core.Message { + sender := s.Keyring.GetKey(0) + recipient := s.Keyring.GetAddr(1) + msg, err := s.Factory.GenerateGethCoreMsg(sender.Priv, types.EvmTxArgs{ + To: &recipient, + Amount: big.NewInt(100), + }) + s.Require().NoError(err) + return *msg + }, + getEVMParams: func() types.Params { + params := types.DefaultParams() + params.ActiveStaticPrecompiles = append([]string(nil), types.AvailableStaticPrecompiles...) + return params + }, + getFeeMarketParams: feemarkettypes.DefaultParams, + overrides: &staticPrecompileMoveOverrides, + expErr: false, + expVMErr: false, + expectedGasUsed: params.TxGas, + }, { name: "call contract tx with config param EnableCall = false", getMessage: func() core.Message { @@ -1091,11 +1212,33 @@ func (s *KeeperTestSuite) TestApplyMessageWithConfig() { return params }, overrides: nil, + useNilDB: false, expErr: true, expVMErr: false, expectedGasUsed: 0, postCheck: nil, }, + { + name: "fail with nil statedb", + getMessage: func() core.Message { + sender := s.Keyring.GetKey(0) + recipient := s.Keyring.GetAddr(1) + msg, err := s.Factory.GenerateGethCoreMsg(sender.Priv, types.EvmTxArgs{ + To: &recipient, + Amount: big.NewInt(100), + }) + s.Require().NoError(err) + return *msg + }, + getEVMParams: types.DefaultParams, + getFeeMarketParams: feemarkettypes.DefaultParams, + overrides: nil, + useNilDB: true, + expErr: true, + expVMErr: false, + expectedGasUsed: 0, + postCheck: nil, + }, } for _, tc := range testCases { @@ -1125,16 +1268,12 @@ func (s *KeeperTestSuite) TestApplyMessageWithConfig() { ) s.Require().NoError(err) - res, err := s.Network.App.GetEVMKeeper().ApplyMessageWithConfig( - s.Network.GetContext(), - msg, - nil, - true, - config, - txConfig, - false, - tc.overrides, - ) + var stateDB *statedb.StateDB + if !tc.useNilDB { + stateDB = statedb.New(s.Network.GetContext(), s.Network.App.GetEVMKeeper(), statedb.NewEmptyTxConfig()) + } + + res, err := s.Network.App.GetEVMKeeper().ApplyMessageWithConfig(s.Network.GetContext(), stateDB, msg, nil, true, false, config, txConfig, false, tc.overrides) if tc.expErr { s.Require().Error(err) @@ -1150,6 +1289,7 @@ func (s *KeeperTestSuite) TestApplyMessageWithConfig() { err = s.Network.NextBlock() if tc.expVMErr { + s.Require().NoError(err) s.Require().NotEmpty(res.VmError) return } @@ -1222,13 +1362,9 @@ func (s *KeeperTestSuite) TestApplyMessageWithNegativeAmount() { ctx := s.Network.GetContext() balance0Before := s.Network.App.GetBankKeeper().GetBalance(ctx, s.Keyring.GetAccAddr(0), "aatom") balance1Before := s.Network.App.GetBankKeeper().GetBalance(ctx, s.Keyring.GetAccAddr(1), "aatom") - res, err := s.Network.App.GetEVMKeeper().ApplyMessage( - s.Network.GetContext(), - *coreMsg, - tracer, - true, - false, - ) + stateDB := statedb.New(s.Network.GetContext(), s.Network.App.GetEVMKeeper(), statedb.NewEmptyTxConfig()) + + res, err := s.Network.App.GetEVMKeeper().ApplyMessage(s.Network.GetContext(), stateDB, *coreMsg, tracer, true, false, false) s.Require().Nil(res) s.Require().Error(err) diff --git a/tests/integration/x/vm/test_statedb.go b/tests/integration/x/vm/test_statedb.go index 0aedd5b8..9bc1bc4b 100644 --- a/tests/integration/x/vm/test_statedb.go +++ b/tests/integration/x/vm/test_statedb.go @@ -20,16 +20,17 @@ import ( "github.com/cosmos/evm/x/vm/types" "cosmossdk.io/math" - "cosmossdk.io/store/prefix" "github.com/cosmos/cosmos-sdk/client" codectypes "github.com/cosmos/cosmos-sdk/codec/types" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/store/v2/prefix" sdk "github.com/cosmos/cosmos-sdk/types" authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) func (s *KeeperTestSuite) TestCreateAccount() { @@ -39,17 +40,6 @@ func (s *KeeperTestSuite) TestCreateAccount() { malleate func(vm.StateDB, common.Address) callback func(vm.StateDB, common.Address) }{ - { - "reset account (keep balance)", - utiltx.GenerateAddress(), - func(vmdb vm.StateDB, addr common.Address) { - vmdb.AddBalance(addr, uint256.NewInt(100), tracing.BalanceChangeUnspecified) - s.Require().NotZero(vmdb.GetBalance(addr).Uint64()) - }, - func(vmdb vm.StateDB, addr common.Address) { - s.Require().Equal(vmdb.GetBalance(addr).Uint64(), uint64(100)) - }, - }, { "create account", utiltx.GenerateAddress(), @@ -247,7 +237,7 @@ func (s *KeeperTestSuite) TestGetCodeHash() { s.Keyring.GetAddr(0), crypto.Keccak256Hash([]byte("codeHash")), func(vmdb vm.StateDB) { - vmdb.SetCode(s.Keyring.GetAddr(0), []byte("codeHash")) + vmdb.SetCode(s.Keyring.GetAddr(0), []byte("codeHash"), 0x0) }, }, } @@ -305,7 +295,7 @@ func (s *KeeperTestSuite) TestSetCode() { s.Run(tc.name, func() { vmdb := s.StateDB() prev := vmdb.GetCode(tc.address) - vmdb.SetCode(tc.address, tc.code) + vmdb.SetCode(tc.address, tc.code, 0x0) post := vmdb.GetCode(tc.address) if tc.isNoOp { @@ -467,7 +457,7 @@ func (s *KeeperTestSuite) TestSuicide() { code := []byte("code") db := s.Network.GetStateDB() // Add code to account - db.SetCode(firstAddress, code) + db.SetCode(firstAddress, code, 0x0) s.Require().Equal(code, db.GetCode(firstAddress)) // Add state to account for i := 0; i < 5; i++ { @@ -481,7 +471,7 @@ func (s *KeeperTestSuite) TestSuicide() { db = s.Network.GetStateDB() // Add code and state to account 2 - db.SetCode(secondAddress, code) + db.SetCode(secondAddress, code, 0x0) s.Require().Equal(code, db.GetCode(secondAddress)) for i := 0; i < 5; i++ { db.SetState( @@ -685,7 +675,7 @@ func (s *KeeperTestSuite) TestAddLog() { msg2.From = addr.Bytes() ethTx3Params := &types.EvmTxArgs{ - ChainID: big.NewInt(testconstants.ExampleEIP155ChainID), + ChainID: big.NewInt(testconstants.EighteenDecimalsChainID), Nonce: 0, To: &toAddr, Amount: common.Big1, @@ -753,7 +743,7 @@ func (s *KeeperTestSuite) TestAddLog() { s.SetupTest() vmdb := statedb.New(s.Network.GetContext(), s.Network.App.GetEVMKeeper(), statedb.NewTxConfig( tc.hash, - 0, 0, + 0, )) tc.malleate(vmdb) @@ -774,7 +764,6 @@ func (s *KeeperTestSuite) TestPrepareAccessList() { } rules := ethparams.Rules{ - ChainID: s.Network.GetEVMChainConfig().ChainID, IsHomestead: true, IsEIP150: true, IsEIP155: true, @@ -923,6 +912,68 @@ func (s *KeeperTestSuite) TestAddSlotToAccessList() { // } // } +// TestGetAccountLocked verifies Keeper.GetAccount snapshots LockedCoins for +// the EVM denom into the Account at load time. The snapshot powers the commit +// path's bank-balance reconstruction without re-reading LockedCoins after a +// precompile may have mutated DelegatedVesting on a vesting account. +func (s *KeeperTestSuite) TestGetAccountLocked() { + addr := utiltx.GenerateAddress() + bondDenom := s.Network.GetBaseDenom() + + testCases := []struct { + name string + malleate func() + expLocked *big.Int + }{ + { + "non-existent account returns nil", + func() {}, + nil, // GetAccount returns nil entirely; checked separately + }, + { + "base account has zero Locked snapshot", + func() { + ctx := s.Network.GetContext() + err := s.Network.App.GetBankKeeper().SendCoins(ctx, s.Keyring.GetAccAddr(0), addr.Bytes(), sdk.NewCoins(sdk.NewCoin(bondDenom, math.NewInt(100)))) + s.Require().NoError(err) + }, + big.NewInt(0), + }, + { + "vesting account snapshots OriginalVesting at start time", + func() { + ctx := s.Network.GetContext() + accAddr := sdk.AccAddress(addr.Bytes()) + err := s.Network.App.GetBankKeeper().SendCoins(ctx, s.Keyring.GetAccAddr(0), accAddr, sdk.NewCoins(sdk.NewCoin(bondDenom, math.NewInt(100)))) + s.Require().NoError(err) + + baseAccount := s.Network.App.GetAccountKeeper().GetAccount(ctx, accAddr).(*authtypes.BaseAccount) + currTime := ctx.BlockTime().Unix() + acc, err := vestingtypes.NewContinuousVestingAccount(baseAccount, sdk.NewCoins(sdk.NewCoin(bondDenom, math.NewInt(100))), currTime, currTime+100) + s.Require().NoError(err) + s.Network.App.GetAccountKeeper().SetAccount(ctx, acc) + }, + big.NewInt(100), + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + s.SetupTest() + tc.malleate() + acc := s.Network.App.GetEVMKeeper().GetAccount(s.Network.GetContext(), addr) + if tc.expLocked == nil { + s.Require().Nil(acc, "expected nil account") + return + } + s.Require().NotNil(acc, "expected non-nil account") + locked := acc.LockedBalanceSnapshot() + s.Require().NotNil(locked, "expected Locked snapshot to be populated") + s.Require().Zero(tc.expLocked.Cmp(locked), "Locked snapshot mismatch: want %s got %s", tc.expLocked, locked) + }) + } +} + func (s *KeeperTestSuite) TestSetBalance() { amount := common.U2560 totalBalance := common.U2560 @@ -984,7 +1035,7 @@ func (s *KeeperTestSuite) TestSetBalance() { }, false, func() *uint256.Int { - return common.U2560.Add(totalBalance, amount) + return uint256.NewInt(0).Add(totalBalance, amount) }, }, { @@ -1060,6 +1111,180 @@ func (s *KeeperTestSuite) TestSetBalance() { } } +func (s *KeeperTestSuite) TestSetBalanceRejectsModuleAccounts() { + type setup struct { + addr common.Address + current *uint256.Int + } + + cases := []struct { + name string + prepare func() setup + amountFn func(current *uint256.Int) *uint256.Int + }{ + { + name: "mocked module account (isModule arm)", + prepare: func() setup { + ctx := s.Network.GetContext() + ak := s.Network.App.GetAccountKeeper() + acc := authtypes.NewEmptyModuleAccount("test-blocked-stale-overwrite", authtypes.Minter) + ak.NewAccount(ctx, acc) + ak.SetAccount(ctx, acc) + modEth := common.BytesToAddress(acc.GetAddress().Bytes()) + return setup{ + addr: modEth, + current: s.Network.App.GetEVMKeeper().GetBalance(ctx, modEth), + } + }, + amountFn: func(_ *uint256.Int) *uint256.Int { return uint256.NewInt(12345) }, + }, + { + name: "bonded_tokens_pool, decrease (isBlockedChange arm)", + prepare: func() setup { + modEth := common.BytesToAddress(authtypes.NewModuleAddress(stakingtypes.BondedPoolName).Bytes()) + return setup{ + addr: modEth, + current: s.Network.App.GetEVMKeeper().GetBalance(s.Network.GetContext(), modEth), + } + }, + amountFn: func(cur *uint256.Int) *uint256.Int { + if cur.IsZero() { + return uint256.NewInt(0) + } + return new(uint256.Int).Sub(cur, uint256.NewInt(1)) + }, + }, + { + name: "bonded_tokens_pool, equal (isModule arm, isBlockedChange skipped)", + prepare: func() setup { + modEth := common.BytesToAddress(authtypes.NewModuleAddress(stakingtypes.BondedPoolName).Bytes()) + return setup{ + addr: modEth, + current: s.Network.App.GetEVMKeeper().GetBalance(s.Network.GetContext(), modEth), + } + }, + amountFn: func(cur *uint256.Int) *uint256.Int { return new(uint256.Int).Set(cur) }, + }, + } + + for _, tc := range cases { + s.Run(tc.name, func() { + s.SetupTest() + st := tc.prepare() + amount := tc.amountFn(st.current) + + err := s.Network.App.GetEVMKeeper().SetBalance(s.Network.GetContext(), st.addr, amount) + s.Require().Error(err) + s.Require().Contains(err.Error(), "is not allowed to receive funds") + + after := s.Network.App.GetEVMKeeper().GetBalance(s.Network.GetContext(), st.addr) + s.Require().Equal(st.current, after) + }) + } +} + +func (s *KeeperTestSuite) TestSetBalanceAllowsEOA() { + s.SetupTest() + addr := utiltx.GenerateAddress() + amount := uint256.NewInt(12345) + + err := s.Network.App.GetEVMKeeper().SetBalance(s.Network.GetContext(), addr, amount) + s.Require().NoError(err) + + got := s.Network.App.GetEVMKeeper().GetBalance(s.Network.GetContext(), addr) + s.Require().Equal(amount, got) +} + +func (s *KeeperTestSuite) TestSetBalanceWithLocked() { + amount := common.U2560 + var locked *big.Int + addr := utiltx.GenerateAddress() + + testCases := []struct { + name string + addr common.Address + malleate func() + expErr bool + expTotalAmount func() *uint256.Int + expSpendable func() *uint256.Int + }{ + { + "non vesting account: locked overrides reread", + addr, + func() { + amount = uint256.NewInt(100) + locked = big.NewInt(50) + }, + false, + func() *uint256.Int { + return uint256.NewInt(150) + }, + func() *uint256.Int { + // All funds are spendable on a non base account, the snapshot + // only inflates the bank balance reconstruction. + return uint256.NewInt(150) + }, + }, + { + "vesting account: locked snapshot beats current LockedCoins re-read", + addr, + func() { + ctx := s.Network.GetContext() + accAddr := sdk.AccAddress(addr.Bytes()) + err := s.Network.App.GetBankKeeper().SendCoins(ctx, s.Keyring.GetAccAddr(0), accAddr, sdk.NewCoins(sdk.NewCoin(s.Network.GetBaseDenom(), math.NewInt(100)))) + s.Require().NoError(err) + + baseAccount := s.Network.App.GetAccountKeeper().GetAccount(ctx, accAddr).(*authtypes.BaseAccount) + baseDenom := s.Network.GetBaseDenom() + currTime := s.Network.GetContext().BlockTime().Unix() + + // setup vesting account with 40 locked to simulate a spend + acc, err := vestingtypes.NewContinuousVestingAccount( + baseAccount, + sdk.NewCoins(sdk.NewCoin(baseDenom, math.NewInt(40))), + currTime, currTime+100, + ) + s.Require().NoError(err) + s.Network.App.GetAccountKeeper().SetAccount(ctx, acc) + + amount = uint256.NewInt(100) + + // override locked to 100 + locked = big.NewInt(100) + }, + false, + func() *uint256.Int { + // ensure we used the override of 100 + return uint256.NewInt(200) + }, + func() *uint256.Int { + // spendable = bank balance − current LockedCoins = 200 − 40 = 160. + return uint256.NewInt(160) + }, + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + s.SetupTest() + + tc.malleate() + err := s.Network.App.GetEVMKeeper().SetBalanceWithLocked(s.Network.GetContext(), tc.addr, amount, locked) + if tc.expErr { + s.Require().Error(err) + return + } + + balance := s.Network.App.GetEVMKeeper().GetBalance(s.Network.GetContext(), tc.addr) + s.Require().NoError(err) + s.Require().Equal(tc.expTotalAmount(), balance) + + spendable := s.Network.App.GetEVMKeeper().SpendableCoin(s.Network.GetContext(), tc.addr) + s.Require().Equal(tc.expSpendable(), spendable) + }) + } +} + func (s *KeeperTestSuite) TestDeleteAccount() { var ( ctx sdk.Context diff --git a/tests/jsonrpc/scripts/evmd/container-start-evmd.sh b/tests/jsonrpc/scripts/evmd/container-start-evmd.sh index 83c201eb..05548e62 100755 --- a/tests/jsonrpc/scripts/evmd/container-start-evmd.sh +++ b/tests/jsonrpc/scripts/evmd/container-start-evmd.sh @@ -91,4 +91,4 @@ exec evmd start \ --json-rpc.ws-address 0.0.0.0:8546 \ --json-rpc.enable-profiling \ --keyring-backend test \ - --chain-id "$CHAIN_ID" \ No newline at end of file + --chain-id "$CHAIN_ID" diff --git a/tests/jsonrpc/scripts/evmd/start-evmd.sh b/tests/jsonrpc/scripts/evmd/start-evmd.sh index c32ae7f7..4d7f5286 100755 --- a/tests/jsonrpc/scripts/evmd/start-evmd.sh +++ b/tests/jsonrpc/scripts/evmd/start-evmd.sh @@ -262,4 +262,4 @@ echo -e " Tendermint RPC: http://localhost:26657" echo -e " gRPC: localhost:9090" echo echo -e "${YELLOW}To view logs: docker logs -f $CONTAINER_NAME${NC}" -echo -e "${YELLOW}To stop: $SCRIPT_DIR/stop-evmd.sh${NC}" \ No newline at end of file +echo -e "${YELLOW}To stop: $SCRIPT_DIR/stop-evmd.sh${NC}" diff --git a/tests/jsonrpc/simulator/go.mod b/tests/jsonrpc/simulator/go.mod index d07be9db..23014b3c 100644 --- a/tests/jsonrpc/simulator/go.mod +++ b/tests/jsonrpc/simulator/go.mod @@ -1,9 +1,9 @@ module github.com/cosmos/evm/tests/jsonrpc/simulator -go 1.23.8 +go 1.25.0 require ( - github.com/ethereum/go-ethereum v1.16.3 + github.com/ethereum/go-ethereum v1.17.0 github.com/fatih/color v1.16.0 github.com/gorilla/websocket v1.4.2 github.com/status-im/keycard-go v0.2.0 @@ -12,15 +12,17 @@ require ( require ( github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6 // indirect github.com/StackExchange/wmi v1.2.1 // indirect github.com/bits-and-blooms/bitset v1.20.0 // indirect - github.com/consensys/gnark-crypto v0.18.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/cespare/xxhash/v2 v2.3.0 // indirect + github.com/consensys/gnark-crypto v0.18.1 // indirect + github.com/crate-crypto/go-eth-kzg v1.4.0 // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect - github.com/ethereum/c-kzg-4844/v2 v2.1.0 // indirect - github.com/ethereum/go-verkle v0.2.2 // indirect + github.com/ethereum/c-kzg-4844/v2 v2.1.5 // 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/holiman/uint256 v1.3.2 // indirect github.com/mattn/go-colorable v0.1.13 // indirect @@ -29,15 +31,19 @@ require ( github.com/richardlehane/mscfb v1.0.4 // indirect github.com/richardlehane/msoleps v1.0.3 // indirect github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect - github.com/supranational/blst v0.3.14 // indirect + github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53 // indirect github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05 // indirect - golang.org/x/crypto v0.36.0 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/otel v1.41.0 // indirect + go.opentelemetry.io/otel/metric v1.41.0 // indirect + go.opentelemetry.io/otel/trace v1.41.0 // indirect + golang.org/x/crypto v0.45.0 // indirect golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect - golang.org/x/net v0.38.0 // indirect - golang.org/x/sync v0.12.0 // indirect - golang.org/x/sys v0.31.0 // indirect - golang.org/x/text v0.23.0 // indirect + golang.org/x/net v0.47.0 // indirect + golang.org/x/sync v0.18.0 // indirect + golang.org/x/sys v0.39.0 // indirect + golang.org/x/text v0.31.0 // indirect ) diff --git a/tests/jsonrpc/simulator/go.sum b/tests/jsonrpc/simulator/go.sum index 5682f1fc..a4f65676 100644 --- a/tests/jsonrpc/simulator/go.sum +++ b/tests/jsonrpc/simulator/go.sum @@ -2,10 +2,12 @@ github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6 h1:1zYrtlhrZ6/b6SAjLSfKzWtdgqK0U+HtH/VcBWh1BaU= +github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI= github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= -github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI= -github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI= +github.com/VictoriaMetrics/fastcache v1.13.0 h1:AW4mheMR5Vd9FkAPUv+NH6Nhw+fmbTMGMsNAoA/+4G0= +github.com/VictoriaMetrics/fastcache v1.13.0/go.mod h1:hHXhl4DA2fTL2HTZDJFXWgW0LNjo6B+4aj2Wmng3TjU= 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/bits-and-blooms/bitset v1.20.0 h1:2F+rfL86jE2d/bmw7OhqUg2Sj/1rURkBn3MdfoPyRVU= @@ -24,14 +26,12 @@ github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwP github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= -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/consensys/gnark-crypto v0.18.1 h1:RyLV6UhPRoYYzaFnPQA4qK3DyuDgkTgskDdoGqFt3fI= +github.com/consensys/gnark-crypto v0.18.1/go.mod h1:L3mXGFTe1ZN+RSJ+CLjUt9x7PNdx8ubaYfDROyp2Z8c= github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc= github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -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-eth-kzg v1.4.0 h1:WzDGjHk4gFg6YzV0rJOAsTK4z3Qkz5jd4RE3DAvPFkg= +github.com/crate-crypto/go-eth-kzg v1.4.0/go.mod h1:J9/u5sWfznSObptgfa92Jq8rTswn6ahQWEuiLHOjCUI= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dchest/siphash v1.2.3 h1:QXwFc8cFOR2dSa/gE6o/HokBMWtLUaNDVd+22aKHeEA= @@ -44,18 +44,23 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/emicklei/dot v1.6.2 h1:08GN+DD79cy/tzN6uLCT84+2Wk9u+wvqP+Hkx/dIR8A= github.com/emicklei/dot v1.6.2/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= -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.16.3 h1:nDoBSrmsrPbrDIVLTkDQCy1U9KdHN+F2PzvMbDoS42Q= -github.com/ethereum/go-ethereum v1.16.3/go.mod h1:Lrsc6bt9Gm9RyvhfFK53vboCia8kpF9nv+2Ukntnl+8= -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/ethereum/c-kzg-4844/v2 v2.1.5 h1:aVtoLK5xwJ6c5RiqO8g8ptJ5KU+2Hdquf6G3aXiHh5s= +github.com/ethereum/c-kzg-4844/v2 v2.1.5/go.mod h1:u59hRTTah4Co6i9fDWtiCjTrblJv0UwsqZKCc0GfgUs= +github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab h1:rvv6MJhy07IMfEKuARQ9TKojGqLVNxQajaXEp/BoqSk= +github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab/go.mod h1:IuLm4IsPipXKF7CW5Lzf68PIbZ5yl7FFd74l/E0o9A8= +github.com/ethereum/go-ethereum v1.17.0 h1:2D+1Fe23CwZ5tQoAS5DfwKFNI1HGcTwi65/kRlAVxes= +github.com/ethereum/go-ethereum v1.17.0/go.mod h1:2W3msvdosS/MCWytpqTcqgFiRYbTH59FxDJzqah120o= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/ferranbt/fastssz v0.1.4 h1:OCDB+dYDEQDvAgtAGnTSidK1Pe2tW3nFV40XyMkTeDY= github.com/ferranbt/fastssz v0.1.4/go.mod h1:Ea3+oeoRGGLGm5shYAeDgu6PGUlcvQhE2fILyD9+tGg= github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +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= @@ -67,16 +72,24 @@ github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXe github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= 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/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs= +github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +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 v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +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/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grafana/pyroscope-go v1.2.7 h1:VWBBlqxjyR0Cwk2W6UrE8CdcdD80GOFNutj0Kb1T8ac= +github.com/grafana/pyroscope-go v1.2.7/go.mod h1:o/bpSLiJYYP6HQtvcoVKiE9s5RiNgjYTj1DhiddP2Pc= +github.com/grafana/pyroscope-go/godeltaprof v0.1.9 h1:c1Us8i6eSmkW+Ez05d3co8kasnuOY813tbMN8i/a3Og= +github.com/grafana/pyroscope-go/godeltaprof v0.1.9/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU= 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/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/billy v0.0.0-20250707135307-f2f9b9aae7db h1:IZUYC/xb3giYwBLMnr8d0TGTzPKFGNTCGgGLoyeX330= +github.com/holiman/billy v0.0.0-20250707135307-f2f9b9aae7db/go.mod h1:xTEYN9KCHxuYHs+NmrmzFcnvHMzLLNiGFafCb1n3Mfg= 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= @@ -85,8 +98,8 @@ github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= 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/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= -github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= +github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -102,8 +115,6 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 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.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= -github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= @@ -114,8 +125,6 @@ github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjU github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= 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= @@ -143,10 +152,8 @@ github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7 github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg= github.com/richardlehane/msoleps v1.0.3 h1:aznSZzrwYRl3rLKRT3gUk9am7T/mLNSnJINvN0AQoVM= github.com/richardlehane/msoleps v1.0.3/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg= -github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -155,10 +162,10 @@ github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1 github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/supranational/blst v0.3.14 h1:xNMoHRJOTwMn63ip6qoWJ2Ymgvj7E2b9jY2FAwY+qRo= -github.com/supranational/blst v0.3.14/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe h1:nbdqkIGOGfUAD54q1s2YBcBz/WcsxCO9HUQ4aGV5hUw= +github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= @@ -175,30 +182,40 @@ github.com/xuri/excelize/v2 v2.8.1 h1:pZLMEwK8ep+CLIUWpWmvW8IWE/yxqG0I1xcN6cVMGu github.com/xuri/excelize/v2 v2.8.1/go.mod h1:oli1E4C3Pa5RXg1TBXn4ENCXDV5JUMlBluUhG7c+CEE= github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05 h1:qhbILQo1K3mphbwKh1vNm4oGezE1eF9fQWmNiIpSfI4= github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ= -golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= -golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/otel v1.41.0 h1:YlEwVsGAlCvczDILpUXpIpPSL/VPugt7zHThEMLce1c= +go.opentelemetry.io/otel v1.41.0/go.mod h1:Yt4UwgEKeT05QbLwbyHXEwhnjxNO6D8L5PQP51/46dE= +go.opentelemetry.io/otel/metric v1.41.0 h1:rFnDcs4gRzBcsO9tS8LCpgR0dxg4aaxWlJxCno7JlTQ= +go.opentelemetry.io/otel/metric v1.41.0/go.mod h1:xPvCwd9pU0VN8tPZYzDZV/BMj9CM9vs00GuBjeKhJps= +go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18= +go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE= +go.opentelemetry.io/otel/trace v1.41.0 h1:Vbk2co6bhj8L59ZJ6/xFTskY+tGAbOnCtQGVVa9TIN0= +go.opentelemetry.io/otel/trace v1.41.0/go.mod h1:U1NU4ULCoxeDKc09yCWdWe+3QoyweJcISEVa1RBzOis= +golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= +golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= golang.org/x/image v0.14.0 h1:tNgSxAFe3jC4uYqvZdTr84SZoM1KfwdC9SKIFrLjFn4= golang.org/x/image v0.14.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE= -golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= -golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= -golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= -golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= +golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= +golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= +golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= +golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= 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= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= 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 4a04cf9e..9f8841ba 100644 --- a/tests/jsonrpc/simulator/namespaces/debug.go +++ b/tests/jsonrpc/simulator/namespaces/debug.go @@ -1,4 +1,5 @@ package namespaces + import ( "context" "fmt" @@ -79,7 +80,6 @@ const ( // Debug API implementations func DebugTraceTransaction(rCtx *types.RPCContext) (*types.RpcResult, error) { - txHash := rCtx.Evmd.ProcessedTransactions[0] // Test with callTracer configuration to get structured result @@ -176,7 +176,6 @@ func DebugTraceTransaction(rCtx *types.RPCContext) (*types.RpcResult, error) { } func DebugPrintBlock(rCtx *types.RPCContext) (*types.RpcResult, error) { - // Get current block number blockNumber, err := rCtx.Evmd.BlockNumber(context.Background()) if err != nil { @@ -209,7 +208,6 @@ func DebugPrintBlock(rCtx *types.RPCContext) (*types.RpcResult, error) { } func DebugSetBlockProfileRate(rCtx *types.RPCContext) (*types.RpcResult, error) { - // Set a test profile rate (1 for enabled, 0 for disabled) rate := 1 @@ -233,7 +231,6 @@ func DebugSetBlockProfileRate(rCtx *types.RPCContext) (*types.RpcResult, error) } func DebugSetMutexProfileFraction(rCtx *types.RPCContext) (*types.RpcResult, error) { - // Set a test mutex profile fraction (1 for enabled, 0 for disabled) fraction := 1 @@ -257,7 +254,6 @@ func DebugSetMutexProfileFraction(rCtx *types.RPCContext) (*types.RpcResult, err } func DebugSetGCPercent(rCtx *types.RPCContext) (*types.RpcResult, error) { - // Set a test GC percentage (100 is default) percent := 100 @@ -282,7 +278,6 @@ func DebugSetGCPercent(rCtx *types.RPCContext) (*types.RpcResult, error) { } func DebugIntermediateRoots(rCtx *types.RPCContext) (*types.RpcResult, error) { - receipt, err := rCtx.Evmd.TransactionReceipt(context.Background(), rCtx.Evmd.ProcessedTransactions[0]) if err != nil { return &types.RpcResult{ @@ -314,7 +309,6 @@ func DebugIntermediateRoots(rCtx *types.RPCContext) (*types.RpcResult, error) { } func DebugTraceCall(rCtx *types.RPCContext) (*types.RpcResult, error) { - // Prepare transaction args for the trace call fromAddr := rCtx.Evmd.Acc.Address toAddr := rCtx.Evmd.Acc.Address // simple transfer to self @@ -356,7 +350,6 @@ func DebugTraceCall(rCtx *types.RPCContext) (*types.RpcResult, error) { } func DebugGetRawBlock(rCtx *types.RPCContext) (*types.RpcResult, error) { - // Get a block number from a processed transaction receipt, err := rCtx.Evmd.TransactionReceipt(context.Background(), rCtx.Evmd.ProcessedTransactions[0]) if err != nil { @@ -403,7 +396,6 @@ func DebugGetRawBlock(rCtx *types.RPCContext) (*types.RpcResult, error) { } func DebugTraceBlockByHash(rCtx *types.RPCContext) (*types.RpcResult, error) { - receipt, err := rCtx.Evmd.TransactionReceipt(context.Background(), rCtx.Evmd.ProcessedTransactions[0]) if err != nil { return &types.RpcResult{ @@ -450,7 +442,6 @@ func DebugTraceBlockByHash(rCtx *types.RPCContext) (*types.RpcResult, error) { } func DebugTraceBlock(rCtx *types.RPCContext) (*types.RpcResult, error) { - // Get a block to trace - use the receipt's block from a processed transaction receipt, err := rCtx.Evmd.TransactionReceipt(context.Background(), rCtx.Evmd.ProcessedTransactions[0]) if err != nil { @@ -526,7 +517,6 @@ func DebugTraceBlock(rCtx *types.RPCContext) (*types.RpcResult, error) { } func DebugTraceBlockByNumber(rCtx *types.RPCContext) (*types.RpcResult, error) { - // Get current block number blockNumber, err := rCtx.Evmd.BlockNumber(context.Background()) if err != nil { @@ -566,7 +556,6 @@ func DebugTraceBlockByNumber(rCtx *types.RPCContext) (*types.RpcResult, error) { } func DebugGcStats(rCtx *types.RPCContext) (*types.RpcResult, error) { - var gcStats interface{} err := rCtx.Evmd.RPCClient().CallContext(context.Background(), &gcStats, string(MethodNameDebugGcStats)) if err != nil { @@ -588,7 +577,6 @@ func DebugGcStats(rCtx *types.RPCContext) (*types.RpcResult, error) { } func DebugFreeOSMemory(rCtx *types.RPCContext) (*types.RpcResult, error) { - err := rCtx.Evmd.RPCClient().CallContext(context.Background(), nil, string(MethodNameDebugFreeOSMemory)) if err != nil { return &types.RpcResult{ @@ -609,7 +597,6 @@ func DebugFreeOSMemory(rCtx *types.RPCContext) (*types.RpcResult, error) { } func DebugStacks(rCtx *types.RPCContext) (*types.RpcResult, error) { - var stacks string err := rCtx.Evmd.RPCClient().CallContext(context.Background(), &stacks, string(MethodNameDebugStacks)) if err != nil { @@ -631,7 +618,6 @@ func DebugStacks(rCtx *types.RPCContext) (*types.RpcResult, error) { } func DebugMutexProfile(rCtx *types.RPCContext) (*types.RpcResult, error) { - // Call debug_mutexProfile with test parameters filename := "/tmp/mutex_profile.out" duration := 1 // 1 second duration for testing @@ -656,7 +642,6 @@ func DebugMutexProfile(rCtx *types.RPCContext) (*types.RpcResult, error) { } func DebugCPUProfile(rCtx *types.RPCContext) (*types.RpcResult, error) { - // Call debug_cpuProfile with test parameters filename := "/tmp/cpu_profile.out" duration := 1 // 1 second duration for testing @@ -681,7 +666,6 @@ func DebugCPUProfile(rCtx *types.RPCContext) (*types.RpcResult, error) { } func DebugGoTrace(rCtx *types.RPCContext) (*types.RpcResult, error) { - // Call debug_goTrace with test parameters filename := "/tmp/go_trace.out" duration := 1 // 1 second duration for testing @@ -706,7 +690,6 @@ func DebugGoTrace(rCtx *types.RPCContext) (*types.RpcResult, error) { } func DebugBlockProfile(rCtx *types.RPCContext) (*types.RpcResult, error) { - // Call debug_blockProfile with test parameters filename := "/tmp/block_profile.out" duration := 1 // 1 second duration for testing @@ -1097,7 +1080,6 @@ func DebugVerbosity(rCtx *types.RPCContext) (*types.RpcResult, error) { // DebugStartGoTrace starts Go execution tracing func DebugStartGoTrace(rCtx *types.RPCContext) (*types.RpcResult, error) { - // Call debug_startGoTrace with test parameters filename := "/tmp/go_trace_start.out" @@ -1135,7 +1117,6 @@ func DebugStartGoTrace(rCtx *types.RPCContext) (*types.RpcResult, error) { // DebugStopGoTrace stops Go execution tracing func DebugStopGoTrace(rCtx *types.RPCContext) (*types.RpcResult, error) { - var result any err := rCtx.Evmd.RPCClient().Call(&result, string(MethodNameDebugStopGoTrace)) if err != nil { diff --git a/tests/jsonrpc/simulator/namespaces/eth.go b/tests/jsonrpc/simulator/namespaces/eth.go index 97ce5f64..bc86db93 100644 --- a/tests/jsonrpc/simulator/namespaces/eth.go +++ b/tests/jsonrpc/simulator/namespaces/eth.go @@ -1,4 +1,5 @@ package namespaces + import ( "context" "encoding/hex" @@ -132,7 +133,6 @@ func EthCoinbase(rCtx *types.RPCContext) (*types.RpcResult, error) { } func EthBlockNumber(rCtx *types.RPCContext) (*types.RpcResult, error) { - blockNumber, err := rCtx.Evmd.BlockNumber(context.Background()) if err != nil { return nil, err @@ -155,7 +155,6 @@ func EthBlockNumber(rCtx *types.RPCContext) (*types.RpcResult, error) { } func EthGasPrice(rCtx *types.RPCContext) (*types.RpcResult, error) { - gasPrice, err := rCtx.Evmd.SuggestGasPrice(context.Background()) if err != nil { return nil, err @@ -182,7 +181,6 @@ func EthGasPrice(rCtx *types.RPCContext) (*types.RpcResult, error) { } func EthMaxPriorityFeePerGas(rCtx *types.RPCContext) (*types.RpcResult, error) { - maxPriorityFeePerGas, err := rCtx.Evmd.SuggestGasTipCap(context.Background()) if err != nil { return nil, err @@ -202,7 +200,6 @@ func EthMaxPriorityFeePerGas(rCtx *types.RPCContext) (*types.RpcResult, error) { } func EthChainID(rCtx *types.RPCContext) (*types.RpcResult, error) { - chainID, err := rCtx.Evmd.ChainID(context.Background()) if err != nil { return nil, err @@ -227,7 +224,6 @@ func EthChainID(rCtx *types.RPCContext) (*types.RpcResult, error) { } func EthGetBalance(rCtx *types.RPCContext) (*types.RpcResult, error) { - balance, err := rCtx.Evmd.BalanceAt(context.Background(), rCtx.Evmd.Acc.Address, nil) if err != nil { return nil, err @@ -247,7 +243,6 @@ func EthGetBalance(rCtx *types.RPCContext) (*types.RpcResult, error) { } func EthGetTransactionCount(rCtx *types.RPCContext) (*types.RpcResult, error) { - nonce, err := rCtx.Evmd.PendingNonceAt(context.Background(), rCtx.Evmd.Acc.Address) if err != nil { return nil, err @@ -265,7 +260,6 @@ func EthGetTransactionCount(rCtx *types.RPCContext) (*types.RpcResult, error) { } func EthGetBlockByHash(rCtx *types.RPCContext) (*types.RpcResult, error) { - // Get a receipt from one of our processed transactions to get a real block hash receipt, err := rCtx.Evmd.TransactionReceipt(context.Background(), rCtx.Evmd.ProcessedTransactions[0]) if err != nil { @@ -299,7 +293,6 @@ func EthGetBlockByHash(rCtx *types.RPCContext) (*types.RpcResult, error) { } func EthGetBlockByNumber(rCtx *types.RPCContext) (*types.RpcResult, error) { - // Get a receipt from one of our processed transactions to get a real block hash receipt, err := rCtx.Evmd.TransactionReceipt(context.Background(), rCtx.Evmd.ProcessedTransactions[0]) if err != nil { @@ -662,7 +655,6 @@ func EthSendRawTransactionTransferERC20(rCtx *types.RPCContext) (*types.RpcResul } func EthGetBlockReceipts(rCtx *types.RPCContext) (*types.RpcResult, error) { - // TODO: Random pick // pick a block with transactions blkNum := rCtx.Evmd.BlockNumsIncludingTx[0] @@ -695,7 +687,6 @@ func EthGetBlockReceipts(rCtx *types.RPCContext) (*types.RpcResult, error) { } func EthGetTransactionByHash(rCtx *types.RPCContext) (*types.RpcResult, error) { - // TODO: Random pick txHash := rCtx.Evmd.ProcessedTransactions[0] @@ -722,7 +713,6 @@ func EthGetTransactionByHash(rCtx *types.RPCContext) (*types.RpcResult, error) { } func EthGetTransactionByBlockHashAndIndex(rCtx *types.RPCContext) (*types.RpcResult, error) { - // Get a receipt from one of our processed transactions to get a real block hash receipt, err := rCtx.Evmd.TransactionReceipt(context.Background(), rCtx.Evmd.ProcessedTransactions[0]) if err != nil { @@ -761,7 +751,6 @@ func EthGetTransactionByBlockHashAndIndex(rCtx *types.RPCContext) (*types.RpcRes } func EthGetTransactionByBlockNumberAndIndex(rCtx *types.RPCContext) (*types.RpcResult, error) { - // TODO: Random pick blkNum := rCtx.Evmd.BlockNumsIncludingTx[0] var tx gethtypes.Transaction @@ -790,7 +779,6 @@ func EthGetTransactionByBlockNumberAndIndex(rCtx *types.RPCContext) (*types.RpcR } func EthGetBlockTransactionCountByNumber(rCtx *types.RPCContext) (*types.RpcResult, error) { - // Get a receipt from one of our processed transactions to get a real block hash receipt, err := rCtx.Evmd.TransactionReceipt(context.Background(), rCtx.Evmd.ProcessedTransactions[0]) if err != nil { @@ -825,7 +813,6 @@ func EthGetBlockTransactionCountByNumber(rCtx *types.RPCContext) (*types.RpcResu // Uncle methods - these should always return 0 or nil in Cosmos EVM (no uncles in PoS) func EthGetUncleCountByBlockHash(rCtx *types.RPCContext) (*types.RpcResult, error) { - // Get a block hash - try from processed transactions first, fallback to latest block var blockHash common.Hash if len(rCtx.Evmd.ProcessedTransactions) > 0 { @@ -871,7 +858,6 @@ func EthGetUncleCountByBlockHash(rCtx *types.RPCContext) (*types.RpcResult, erro } func EthGetUncleCountByBlockNumber(rCtx *types.RPCContext) (*types.RpcResult, error) { - var uncleCount string err := rCtx.Evmd.RPCClient().CallContext(context.Background(), &uncleCount, string(MethodNameEthGetUncleCountByBlockNumber), "latest") if err != nil { @@ -893,7 +879,6 @@ func EthGetUncleCountByBlockNumber(rCtx *types.RPCContext) (*types.RpcResult, er } func EthGetUncleByBlockHashAndIndex(rCtx *types.RPCContext) (*types.RpcResult, error) { - // Get a block hash - try from processed transactions first, fallback to latest block var blockHash common.Hash if len(rCtx.Evmd.ProcessedTransactions) > 0 { @@ -932,7 +917,6 @@ func EthGetUncleByBlockHashAndIndex(rCtx *types.RPCContext) (*types.RpcResult, e } func EthGetUncleByBlockNumberAndIndex(rCtx *types.RPCContext) (*types.RpcResult, error) { - var uncle interface{} // Get current block number and format as hex blockNumber, err := rCtx.Evmd.BlockNumber(context.Background()) @@ -961,7 +945,6 @@ func EthGetUncleByBlockNumberAndIndex(rCtx *types.RPCContext) (*types.RpcResult, } func EthGetTransactionCountByHash(rCtx *types.RPCContext) (*types.RpcResult, error) { - // get block blkNum := rCtx.Evmd.BlockNumsIncludingTx[0] blk, err := rCtx.Evmd.BlockByNumber(context.Background(), new(big.Int).SetUint64(blkNum)) @@ -987,7 +970,6 @@ func EthGetTransactionCountByHash(rCtx *types.RPCContext) (*types.RpcResult, err } func EthGetTransactionReceipt(rCtx *types.RPCContext) (*types.RpcResult, error) { - if len(rCtx.Evmd.ProcessedTransactions) == 0 { return nil, errors.New("no transactions") } @@ -1017,7 +999,6 @@ func EthGetTransactionReceipt(rCtx *types.RPCContext) (*types.RpcResult, error) } func EthGetBlockTransactionCountByHash(rCtx *types.RPCContext) (*types.RpcResult, error) { - if len(rCtx.Evmd.ProcessedTransactions) == 0 { return nil, errors.New("no processed transactions available - run transaction generation first") } @@ -1053,7 +1034,6 @@ func EthGetBlockTransactionCountByHash(rCtx *types.RPCContext) (*types.RpcResult } func EthGetCode(rCtx *types.RPCContext) (*types.RpcResult, error) { - if rCtx.Evmd.ERC20Addr == (common.Address{}) { return nil, errors.New("no contract address, must be deployed first") } @@ -1081,7 +1061,6 @@ func EthGetCode(rCtx *types.RPCContext) (*types.RpcResult, error) { } func EthGetStorageAt(rCtx *types.RPCContext) (*types.RpcResult, error) { - if rCtx.Evmd.ERC20Addr == (common.Address{}) { return nil, errors.New("no contract address, must be deployed first") } @@ -1112,7 +1091,6 @@ func EthGetStorageAt(rCtx *types.RPCContext) (*types.RpcResult, error) { } func EthNewFilter(rCtx *types.RPCContext) (*types.RpcResult, error) { - fErc20Transfer := ethereum.FilterQuery{ FromBlock: new(big.Int).SetUint64(rCtx.Evmd.BlockNumsIncludingTx[0] - 1), Addresses: []common.Address{rCtx.Evmd.ERC20Addr}, @@ -1167,7 +1145,6 @@ func EthNewFilter(rCtx *types.RPCContext) (*types.RpcResult, error) { } func EthGetFilterLogs(rCtx *types.RPCContext) (*types.RpcResult, error) { - if rCtx.Evmd.FilterID == "" { return nil, errors.New("no filter id, must create a filter first") } @@ -1215,7 +1192,6 @@ func EthGetFilterLogs(rCtx *types.RPCContext) (*types.RpcResult, error) { } func EthNewBlockFilter(rCtx *types.RPCContext) (*types.RpcResult, error) { - var filterID string if err := rCtx.Evmd.Client.Client().CallContext(context.Background(), &filterID, string(MethodNameEthNewBlockFilter)); err != nil { return nil, err @@ -1235,7 +1211,6 @@ func EthNewBlockFilter(rCtx *types.RPCContext) (*types.RpcResult, error) { } func EthGetFilterChanges(rCtx *types.RPCContext) (*types.RpcResult, error) { - var changes []interface{} if err := rCtx.Evmd.RPCClient().CallContext(context.Background(), &changes, string(MethodNameEthGetFilterChanges), rCtx.Evmd.BlockFilterID); err != nil { return nil, err @@ -1279,7 +1254,6 @@ func EthGetFilterChanges(rCtx *types.RPCContext) (*types.RpcResult, error) { } func EthUninstallFilter(rCtx *types.RPCContext) (*types.RpcResult, error) { - _, filterID, err := utils.NewERC20FilterLogs(rCtx, false) if err != nil { return nil, fmt.Errorf("failed to create filter logs: %w", err) @@ -1313,7 +1287,6 @@ func EthUninstallFilter(rCtx *types.RPCContext) (*types.RpcResult, error) { } func EthGetLogs(rCtx *types.RPCContext) (*types.RpcResult, error) { - if _, err := EthNewFilter(rCtx); err != nil { return nil, errors.New("failed to create a filter") } @@ -1515,35 +1488,180 @@ func EthCall(rCtx *types.RPCContext) (*types.RpcResult, error) { }, nil } -func EthEstimateGas(rCtx *types.RPCContext) (*types.RpcResult, error) { - // Perform dual API comparison if enabled - rCtx.PerformComparison(MethodNameEthEstimateGas, map[string]interface{}{ - "from": rCtx.Evmd.Acc.Address.Hex(), - "to": rCtx.Evmd.Acc.Address.Hex(), - "value": "0x0", - }) - - // Simple gas estimation test +// estimateNativeTransferGas exercises the simplest path – sending native ETH +// from the pre-funded dev0 account to a second dev account – so we can compare +// Cosmos EVM and go-ethereum behaviour for plain value transfers. +func estimateNativeTransferGas(rCtx *types.RPCContext) (string, error) { + recipient := utils.StandardDevAccounts["dev2"] callMsg := ethereum.CallMsg{ From: rCtx.Evmd.Acc.Address, - To: &rCtx.Evmd.Acc.Address, - Value: big.NewInt(0), + To: &recipient, + Value: big.NewInt(1e15), } gasLimit, err := rCtx.Evmd.EstimateGas(context.Background(), callMsg) if err != nil { + return "", err + } + + return fmt.Sprintf("0x%x", gasLimit), nil +} + +// estimateERC20TransferGas measures gas usage for a token transfer against the +// ERC20 instance that Setup() deploys and mints to the standard dev accounts. +// This mirrors the real execution path (contract code lives on-chain already). +func estimateERC20TransferGas(rCtx *types.RPCContext) (string, bool, error) { + if rCtx.Evmd.ERC20Abi == nil || rCtx.Evmd.ERC20Addr == (common.Address{}) { + return "", true, nil + } + + sender := utils.StandardDevAccounts["dev1"] + recipient := utils.StandardDevAccounts["dev2"] + amount := new(big.Int).Mul(big.NewInt(10), big.NewInt(1e18)) + + data, err := rCtx.Evmd.ERC20Abi.Pack("transfer", recipient, amount) + if err != nil { + return "", false, err + } + + erc20Call := ethereum.CallMsg{From: sender, To: &rCtx.Evmd.ERC20Addr, Data: data} + + if rCtx.EnableComparison { + rCtx.PerformComparison(MethodNameEthEstimateGas, map[string]interface{}{ + "from": sender.Hex(), + "to": rCtx.Evmd.ERC20Addr.Hex(), + "data": "0x" + hex.EncodeToString(data), + }) + } + + gas, err := rCtx.Evmd.EstimateGas(context.Background(), erc20Call) + if err != nil { + return "", false, err + } + + return fmt.Sprintf("0x%x", gas), false, nil +} + +// estimateERC20OverrideGas simulates the "deploy via state override" RPC usage: +// - inject runtime bytecode at a synthetic contract address +// - seed balances[dev1] so the transfer can succeed +// - provide enough native balance for dev1 to cover gas +// +// This ensures our override behaviour matches geth for contract calls without +// first deploying on-chain. +func estimateERC20OverrideGas(rCtx *types.RPCContext) (string, bool, error) { + const overrideContractHex = "0x5555555555555555555555555555555555555555" + + if rCtx.Evmd.ERC20Abi == nil || len(rCtx.Evmd.ERC20ByteCode) == 0 { + return "", true, nil + } + + runtimeHex, err := utils.ExtractRuntimeBytecodeHex(rCtx.Evmd.ERC20ByteCode) + if err != nil { + return "", true, nil + } + + overrideSender := utils.StandardDevAccounts["dev1"] + overrideRecipient := utils.StandardDevAccounts["dev2"] + overrideAmount := new(big.Int).Mul(big.NewInt(5), big.NewInt(1e18)) + + data, err := rCtx.Evmd.ERC20Abi.Pack("transfer", overrideRecipient, overrideAmount) + if err != nil { + return "", false, err + } + + // balanceOf is stored at slot 4 in the deployed ERC20 layout. + // (name, symbol, decimals, totalSupply precede the mapping.) + const balanceMappingSlot = 4 + slotKey := utils.MustCalculateSlotKey(overrideSender, balanceMappingSlot) + tokenBalance := fmt.Sprintf("0x%064x", overrideAmount) + fromBalance := fmt.Sprintf("0x%x", new(big.Int).Mul(big.NewInt(100), big.NewInt(1e18))) + + overrideParams := map[string]interface{}{ + "from": overrideSender.Hex(), + "to": overrideContractHex, + "data": "0x" + hex.EncodeToString(data), + } + overrideState := map[string]interface{}{ + overrideContractHex: map[string]interface{}{ + "code": runtimeHex, + "stateDiff": map[string]string{ + slotKey.Hex(): tokenBalance, + }, + }, + overrideSender.Hex(): map[string]string{ + "balance": fromBalance, + }, + } + + if rCtx.EnableComparison { + rCtx.PerformComparison(MethodNameEthEstimateGas, overrideParams, "latest", overrideState) + } + + var overrideGas hexutil.Uint64 + if err := rCtx.Evmd.RPCClient().Call(&overrideGas, string(MethodNameEthEstimateGas), overrideParams, "latest", overrideState); err != nil { + return "", false, err + } + + return fmt.Sprintf("0x%x", uint64(overrideGas)), false, nil +} + +// EthEstimateGas aggregates native ETH, deployed ERC20, and override ERC20 +// scenarios so we continuously exercise the major gas-estimation paths. +func EthEstimateGas(rCtx *types.RPCContext) (*types.RpcResult, error) { + if rCtx.EnableComparison { + rCtx.PerformComparison(MethodNameEthEstimateGas, map[string]interface{}{ + "from": rCtx.Evmd.Acc.Address.Hex(), + "to": rCtx.Evmd.Acc.Address.Hex(), + "value": "0x0", + }) + } + + // Collect individual scenario results keyed by a descriptive name. + results := map[string]string{} + + single, err := estimateNativeTransferGas(rCtx) + if err != nil { + return &types.RpcResult{ + Method: MethodNameEthEstimateGas, + Status: types.Error, + ErrMsg: err.Error(), + Category: NamespaceEth, + }, nil + } + singleKey := "nativeTransfer" + results[singleKey] = single + + if erc20Gas, skipped, err := estimateERC20TransferGas(rCtx); err != nil { return &types.RpcResult{ Method: MethodNameEthEstimateGas, Status: types.Error, ErrMsg: err.Error(), Category: NamespaceEth, }, nil + } else if skipped { + results["erc20Transfer"] = "skipped" + } else { + results["erc20Transfer"] = erc20Gas + } + + if overrideGas, skipped, err := estimateERC20OverrideGas(rCtx); err != nil { + return &types.RpcResult{ + Method: MethodNameEthEstimateGas, + Status: types.Error, + ErrMsg: err.Error(), + Category: NamespaceEth, + }, nil + } else if skipped { + results["erc20Override"] = "skipped" + } else { + results["erc20Override"] = overrideGas } return &types.RpcResult{ Method: MethodNameEthEstimateGas, Status: types.Ok, - Value: fmt.Sprintf("0x%x", gasLimit), + Value: results, Category: NamespaceEth, }, nil } @@ -1551,7 +1669,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 { @@ -1636,7 +1753,6 @@ func EthGetProof(rCtx *types.RPCContext) (*types.RpcResult, error) { // EthSendTransaction sends a transaction using eth_sendTransaction // This requires the account to be unlocked or managed by the node func EthSendTransaction(rCtx *types.RPCContext) (*types.RpcResult, error) { - // Create a simple transaction object for testing tx := map[string]interface{}{ "from": rCtx.Evmd.Acc.Address.Hex(), @@ -1692,7 +1808,6 @@ func EthSendTransaction(rCtx *types.RPCContext) (*types.RpcResult, error) { // EthSign signs data using eth_sign // This requires the account to be unlocked or managed by the node func EthSign(rCtx *types.RPCContext) (*types.RpcResult, error) { - // Test data to sign (32-byte hash) testData := "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef" @@ -1782,7 +1897,6 @@ func EthCreateAccessList(rCtx *types.RPCContext) (*types.RpcResult, error) { } func EthGetHeaderByHash(rCtx *types.RPCContext) (*types.RpcResult, error) { - // Get a block hash from processed transactions receipt, err := rCtx.Evmd.TransactionReceipt(context.Background(), rCtx.Evmd.ProcessedTransactions[0]) if err != nil { @@ -1796,7 +1910,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") { @@ -1851,7 +1964,6 @@ func EthGetHeaderByHash(rCtx *types.RPCContext) (*types.RpcResult, error) { } func EthGetHeaderByNumber(rCtx *types.RPCContext) (*types.RpcResult, error) { - // Get current block number blockNumber, err := rCtx.Evmd.BlockNumber(context.Background()) if err != nil { @@ -1867,7 +1979,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") { @@ -1922,7 +2033,6 @@ func EthGetHeaderByNumber(rCtx *types.RPCContext) (*types.RpcResult, error) { } func EthSimulateV1(rCtx *types.RPCContext) (*types.RpcResult, error) { - // Create a simulation request with test parameters simulationReq := map[string]any{ "blockStateCalls": []map[string]any{ @@ -1947,7 +2057,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") || @@ -2004,10 +2113,8 @@ func EthSimulateV1(rCtx *types.RPCContext) (*types.RpcResult, error) { } 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 d1f668bc..20b664b2 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/types/context.go b/tests/jsonrpc/simulator/types/context.go index dadd52df..21e3e944 100644 --- a/tests/jsonrpc/simulator/types/context.go +++ b/tests/jsonrpc/simulator/types/context.go @@ -74,7 +74,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) { diff --git a/tests/jsonrpc/simulator/utils/test_helpers.go b/tests/jsonrpc/simulator/utils/test_helpers.go index d584b116..ea0bda5d 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/jsonrpc/simulator/utils/utils.go b/tests/jsonrpc/simulator/utils/utils.go index b61522a4..9f377dfb 100644 --- a/tests/jsonrpc/simulator/utils/utils.go +++ b/tests/jsonrpc/simulator/utils/utils.go @@ -1,6 +1,7 @@ package utils import ( + "bytes" "crypto/ecdsa" "encoding/json" "errors" @@ -87,6 +88,17 @@ func MustBeautifyTransaction(tx *gethtypes.Transaction) string { return string(indentedTxJSON) } +// ExtractRuntimeBytecodeHex strips the init code suffix (F3FE...) and returns the runtime bytecode as hex string with 0x prefix. +func ExtractRuntimeBytecodeHex(creation []byte) (string, error) { + marker := []byte{0xf3, 0xfe} + idx := bytes.Index(creation, marker) + if idx == -1 { + return "", fmt.Errorf("runtime marker not found in creation bytecode") + } + runtime := creation[idx+len(marker):] + return hexutil.Encode(runtime), nil +} + func MustCalculateSlotKey(addr common.Address, slotIndex uint64) common.Hash { addressTy, err := abi.NewType("address", "", nil) if err != nil { diff --git a/tests/solidity/package.json b/tests/solidity/package.json index 6203c4e6..e08316d0 100644 --- a/tests/solidity/package.json +++ b/tests/solidity/package.json @@ -13,9 +13,9 @@ ] }, "dependencies": { - "truffle": "5.5.8", - "yargs": "^17.0.1", - "patch-package": "^6.4.7" + "truffle": "5.11.5", + "yargs": "^18.0.0", + "patch-package": "^8.0.0" }, "scripts": { "test": "node test-helper.js", diff --git a/tests/solidity/suites/precompiles/package.json b/tests/solidity/suites/precompiles/package.json index 15bee378..ab7990b3 100644 --- a/tests/solidity/suites/precompiles/package.json +++ b/tests/solidity/suites/precompiles/package.json @@ -16,7 +16,7 @@ "@nomicfoundation/hardhat-toolbox": "^3.0.0", "@nomicfoundation/hardhat-verify": "^1.1.1", "@openzeppelin/hardhat-upgrades": "^2.0.2", - "@openzeppelin/contracts": "^4.9.6", + "@openzeppelin/contracts": "^5.4.0", "@typechain/ethers-v6": "^0.4.3", "@typechain/hardhat": "^8.0.3", "@types/chai": "^4.3.5", diff --git a/tests/solidity/suites/revert_cases/package.json b/tests/solidity/suites/revert_cases/package.json index 7788ed08..94aa5498 100644 --- a/tests/solidity/suites/revert_cases/package.json +++ b/tests/solidity/suites/revert_cases/package.json @@ -16,7 +16,7 @@ "@nomicfoundation/hardhat-toolbox": "^3.0.0", "@nomicfoundation/hardhat-verify": "^1.1.1", "@openzeppelin/hardhat-upgrades": "^2.0.2", - "@openzeppelin/contracts": "^4.9.6", + "@openzeppelin/contracts": "^5.4.0", "@typechain/ethers-v6": "^0.4.3", "@typechain/hardhat": "^8.0.3", "@types/chai": "^4.3.5", diff --git a/tests/solidity/yarn.lock b/tests/solidity/yarn.lock index d6016fcd..e02d0513 100644 --- a/tests/solidity/yarn.lock +++ b/tests/solidity/yarn.lock @@ -4,7 +4,7 @@ "@adraffy/ens-normalize@1.9.2": version "1.9.2" - resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.9.2.tgz#60111a5d9db45b2e5cbb6231b0bb8d97e8659316" + resolved "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.9.2.tgz" integrity sha512-0h+FrQDqe2Wn+IIGFkTCd4aAwTJ+7834Ek1COohCyV26AXhwQ7WQaz+4F/nLOeVl/3BtWHOHLPsq46V8YB46Eg== "@apollo/protobufjs@1.2.6": @@ -117,7 +117,7 @@ "@aws-crypto/sha256-js@1.2.2": version "1.2.2" - resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-js/-/sha256-js-1.2.2.tgz#02acd1a1fda92896fc5a28ec7c6e164644ea32fc" + resolved "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-1.2.2.tgz" integrity sha512-Nr1QJIbW/afYYGzYvrF70LtaHrIRtd4TNAglX8BvlfxJLZ45SAmueIKYl5tWoNBPzp65ymXGFK0Bb1vZUpuc9g== dependencies: "@aws-crypto/util" "^1.2.2" @@ -126,7 +126,7 @@ "@aws-crypto/util@^1.2.2": version "1.2.2" - resolved "https://registry.yarnpkg.com/@aws-crypto/util/-/util-1.2.2.tgz#b28f7897730eb6538b21c18bd4de22d0ea09003c" + resolved "https://registry.npmjs.org/@aws-crypto/util/-/util-1.2.2.tgz" integrity sha512-H8PjG5WJ4wz0UXAFXeJjWCW1vkvIJ3qUUD+rGRwJ2/hj+xT58Qle2MTql/2MGzkU+1JLAFuR6aJpLAjHwhmwwg== dependencies: "@aws-sdk/types" "^3.1.0" @@ -135,7 +135,7 @@ "@aws-sdk/types@^3.1.0": version "3.387.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.387.0.tgz#15a968344956b2587dbab1224718d72329e050f4" + resolved "https://registry.npmjs.org/@aws-sdk/types/-/types-3.387.0.tgz" integrity sha512-YTjFabNwjTF+6yl88f0/tWff018qmmgMmjlw45s6sdVKueWxdxV68U7gepNLF2nhaQPZa6FDOBoA51NaviVs0Q== dependencies: "@smithy/types" "^2.1.0" @@ -143,30 +143,50 @@ "@aws-sdk/util-utf8-browser@^3.0.0": version "3.259.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz#3275a6f5eb334f96ca76635b961d3c50259fd9ff" + resolved "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz" integrity sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw== dependencies: tslib "^2.3.1" -"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.22.9": - version "7.22.9" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.9.tgz#71cdb00a1ce3a329ce4cbec3a44f9fef35669730" - integrity sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ== +"@babel/code-frame@^7.27.1": + version "7.27.1" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz" + integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg== + dependencies: + "@babel/helper-validator-identifier" "^7.27.1" + js-tokens "^4.0.0" + picocolors "^1.1.1" + +"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.27.2": + version "7.28.5" + resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz" + integrity sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA== + +"@babel/generator@^7.28.5": + version "7.28.5" + resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz" + integrity sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ== + dependencies: + "@babel/parser" "^7.28.5" + "@babel/types" "^7.28.5" + "@jridgewell/gen-mapping" "^0.3.12" + "@jridgewell/trace-mapping" "^0.3.28" + jsesc "^3.0.2" "@babel/helper-compilation-targets@^7.22.6": - version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.10.tgz#01d648bbc25dd88f513d862ee0df27b7d4e67024" - integrity sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q== + version "7.27.2" + resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz" + integrity sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ== dependencies: - "@babel/compat-data" "^7.22.9" - "@babel/helper-validator-option" "^7.22.5" - browserslist "^4.21.9" + "@babel/compat-data" "^7.27.2" + "@babel/helper-validator-option" "^7.27.1" + browserslist "^4.24.0" lru-cache "^5.1.1" semver "^6.3.1" "@babel/helper-define-polyfill-provider@^0.4.2": version "0.4.2" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.2.tgz#82c825cadeeeee7aad237618ebbe8fa1710015d7" + resolved "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.2.tgz" integrity sha512-k0qnnOqHn5dK9pZpfD5XXZ9SojAITdCKRn2Lp6rnDGzIbaP0rHyMPk/4wsSxVBVz4RfN0q6VpXWP2pDGIoQ7hw== dependencies: "@babel/helper-compilation-targets" "^7.22.6" @@ -175,36 +195,49 @@ lodash.debounce "^4.0.8" resolve "^1.14.2" +"@babel/helper-globals@^7.28.0": + version "7.28.0" + resolved "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz" + integrity sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw== + "@babel/helper-module-imports@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz#1a8f4c9f4027d23f520bd76b364d44434a72660c" - integrity sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg== + version "7.27.1" + resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz" + integrity sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w== dependencies: - "@babel/types" "^7.22.5" + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" "@babel/helper-plugin-utils@^7.22.5": version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" + resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz" integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== -"@babel/helper-string-parser@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" - integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== +"@babel/helper-string-parser@^7.27.1": + version "7.27.1" + resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz" + integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== -"@babel/helper-validator-identifier@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193" - integrity sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ== +"@babel/helper-validator-identifier@^7.27.1", "@babel/helper-validator-identifier@^7.28.5": + version "7.28.5" + resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz" + integrity sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q== -"@babel/helper-validator-option@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz#de52000a15a177413c8234fa3a8af4ee8102d0ac" - integrity sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw== +"@babel/helper-validator-option@^7.27.1": + version "7.27.1" + resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz" + integrity sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg== + +"@babel/parser@^7.27.2", "@babel/parser@^7.28.5": + version "7.28.5" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz" + integrity sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ== + dependencies: + "@babel/types" "^7.28.5" "@babel/plugin-transform-runtime@^7.5.5": version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.22.10.tgz#89eda6daf1d3af6f36fb368766553054c8d7cd46" + resolved "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.22.10.tgz" integrity sha512-RchI7HePu1eu0CYNKHHHQdfenZcM4nz8rew5B1VWqeRKdcwW5aQ5HeG9eTUbWiAS1UrmHVLmoxTWHt3iLD/NhA== dependencies: "@babel/helper-module-imports" "^7.22.5" @@ -215,24 +248,43 @@ semver "^6.3.1" "@babel/runtime@^7.12.1", "@babel/runtime@^7.17.2", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.9.2": - version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.10.tgz#ae3e9631fd947cb7e3610d3e9d8fef5f76696682" - integrity sha512-21t/fkKLMZI4pqP2wlmsQAWnYW1PDyKyyUV4vCi+B25ydmdaYTKXPwCj0BzSUnZf4seIiYvSA3jcZ3gdsMFkLQ== - dependencies: - regenerator-runtime "^0.14.0" + version "7.28.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.28.4.tgz#a70226016fabe25c5783b2f22d3e1c9bc5ca3326" + integrity sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ== + +"@babel/template@^7.27.2": + version "7.27.2" + resolved "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz" + integrity sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw== + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/parser" "^7.27.2" + "@babel/types" "^7.27.1" + +"@babel/traverse@^7.27.1": + version "7.28.5" + resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz" + integrity sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ== + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/generator" "^7.28.5" + "@babel/helper-globals" "^7.28.0" + "@babel/parser" "^7.28.5" + "@babel/template" "^7.27.2" + "@babel/types" "^7.28.5" + debug "^4.3.1" -"@babel/types@^7.22.5": - version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.10.tgz#4a9e76446048f2c66982d1a989dd12b8a2d2dc03" - integrity sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg== +"@babel/types@^7.27.1", "@babel/types@^7.28.5": + version "7.28.5" + resolved "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz" + integrity sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA== dependencies: - "@babel/helper-string-parser" "^7.22.5" - "@babel/helper-validator-identifier" "^7.22.5" - to-fast-properties "^2.0.0" + "@babel/helper-string-parser" "^7.27.1" + "@babel/helper-validator-identifier" "^7.28.5" "@consento/sync-randombytes@^1.0.4", "@consento/sync-randombytes@^1.0.5": version "1.0.5" - resolved "https://registry.yarnpkg.com/@consento/sync-randombytes/-/sync-randombytes-1.0.5.tgz#5be6bc58c6a6fa6e09f04cc684d037e29e6c28d5" + resolved "https://registry.npmjs.org/@consento/sync-randombytes/-/sync-randombytes-1.0.5.tgz" integrity sha512-mPJ2XvrTLQGEdhleDuSIkWtVWnvmhREOC1FjorV1nlK49t/52Z9X1d618gTj6nlQghRLiYvcd8oL4vZ2YZuDIQ== dependencies: buffer "^5.4.3" @@ -240,7 +292,7 @@ "@cspotcode/source-map-support@^0.8.0": version "0.8.1" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + resolved "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz" integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== dependencies: "@jridgewell/trace-mapping" "0.3.9" @@ -298,12 +350,17 @@ "@ethereumjs/common@^2.4.0", "@ethereumjs/common@^2.5.0", "@ethereumjs/common@^2.6.4": version "2.6.5" - resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.6.5.tgz#0a75a22a046272579d91919cb12d84f2756e8d30" + resolved "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz" integrity sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA== dependencies: crc-32 "^1.2.0" ethereumjs-util "^7.1.5" +"@ethereumjs/rlp@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@ethereumjs/rlp/-/rlp-4.0.1.tgz#626fabfd9081baab3d0a3074b0c7ecaf674aaa41" + integrity sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw== + "@ethereumjs/tx@3.3.2": version "3.3.2" resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.3.2.tgz#348d4624bf248aaab6c44fec2ae67265efe3db00" @@ -314,15 +371,39 @@ "@ethereumjs/tx@^3.3.0", "@ethereumjs/tx@^3.3.2": version "3.5.2" - resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.5.2.tgz#197b9b6299582ad84f9527ca961466fce2296c1c" + resolved "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.5.2.tgz" integrity sha512-gQDNJWKrSDGu2w7w0PzVXVBNMzb7wwdDOmOqczmhNjqFxFuIbhVJDwiGEnxFNC2/b8ifcZzY7MLcluizohRzNw== dependencies: "@ethereumjs/common" "^2.6.4" ethereumjs-util "^7.1.5" -"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.0.0-beta.146", "@ethersproject/abi@^5.0.9", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.6.3", "@ethersproject/abi@^5.7.0": +"@ethereumjs/util@^8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/util/-/util-8.1.0.tgz#299df97fb6b034e0577ce9f94c7d9d1004409ed4" + integrity sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA== + dependencies: + "@ethereumjs/rlp" "^4.0.1" + ethereum-cryptography "^2.0.0" + micro-ftch "^0.3.1" + +"@ethersproject/abi@5.8.0", "@ethersproject/abi@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.8.0.tgz#e79bb51940ac35fe6f3262d7fe2cdb25ad5f07d9" + integrity sha512-b9YS/43ObplgyV6SlyQsG53/vkSal0MNA1fskSC4mbnCMi8R+NkcH8K9FPYNESf6jUefBUniE4SOKms0E/KK1Q== + dependencies: + "@ethersproject/address" "^5.8.0" + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/constants" "^5.8.0" + "@ethersproject/hash" "^5.8.0" + "@ethersproject/keccak256" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/strings" "^5.8.0" + +"@ethersproject/abi@^5.0.0-beta.146", "@ethersproject/abi@^5.0.9", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.6.3": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" + resolved "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz" integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== dependencies: "@ethersproject/address" "^5.7.0" @@ -335,9 +416,22 @@ "@ethersproject/properties" "^5.7.0" "@ethersproject/strings" "^5.7.0" -"@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.7.0": +"@ethersproject/abstract-provider@5.8.0", "@ethersproject/abstract-provider@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.8.0.tgz#7581f9be601afa1d02b95d26b9d9840926a35b0c" + integrity sha512-wC9SFcmh4UK0oKuLJQItoQdzS/qZ51EJegK6EmAWlh+OptpQ/npECOR3QqECd8iGHC0RJb4WKbVdSfif4ammrg== + dependencies: + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/networks" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/transactions" "^5.8.0" + "@ethersproject/web" "^5.8.0" + +"@ethersproject/abstract-provider@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef" + resolved "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz" integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== dependencies: "@ethersproject/bignumber" "^5.7.0" @@ -348,9 +442,20 @@ "@ethersproject/transactions" "^5.7.0" "@ethersproject/web" "^5.7.0" -"@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.7.0": +"@ethersproject/abstract-signer@5.8.0", "@ethersproject/abstract-signer@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.8.0.tgz#8d7417e95e4094c1797a9762e6789c7356db0754" + integrity sha512-N0XhZTswXcmIZQdYtUnd79VJzvEwXQw6PK0dTl9VoYrEBxxCPXqS0Eod7q5TNKRxe1/5WUMuR0u0nqTF/avdCA== + dependencies: + "@ethersproject/abstract-provider" "^5.8.0" + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + +"@ethersproject/abstract-signer@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2" + resolved "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz" integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== dependencies: "@ethersproject/abstract-provider" "^5.7.0" @@ -359,9 +464,20 @@ "@ethersproject/logger" "^5.7.0" "@ethersproject/properties" "^5.7.0" -"@ethersproject/address@5.7.0", "@ethersproject/address@^5.0.2", "@ethersproject/address@^5.7.0": +"@ethersproject/address@5.8.0", "@ethersproject/address@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.8.0.tgz#3007a2c352eee566ad745dca1dbbebdb50a6a983" + integrity sha512-GhH/abcC46LJwshoN+uBNoKVFPxUuZm6dA257z0vZkKmU1+t8xTn8oK7B9qrj8W2rFRMch4gbJl6PmVxjxBEBA== + dependencies: + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/keccak256" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/rlp" "^5.8.0" + +"@ethersproject/address@^5.0.2", "@ethersproject/address@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" + resolved "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz" integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== dependencies: "@ethersproject/bignumber" "^5.7.0" @@ -370,63 +486,108 @@ "@ethersproject/logger" "^5.7.0" "@ethersproject/rlp" "^5.7.0" -"@ethersproject/base64@5.7.0", "@ethersproject/base64@^5.7.0": +"@ethersproject/base64@5.8.0", "@ethersproject/base64@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.8.0.tgz#61c669c648f6e6aad002c228465d52ac93ee83eb" + integrity sha512-lN0oIwfkYj9LbPx4xEkie6rAMJtySbpOAFXSDVQaBnAzYfB4X2Qr+FXJGxMoc3Bxp2Sm8OwvzMrywxyw0gLjIQ== + dependencies: + "@ethersproject/bytes" "^5.8.0" + +"@ethersproject/base64@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c" + resolved "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz" integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== dependencies: "@ethersproject/bytes" "^5.7.0" -"@ethersproject/basex@5.7.0", "@ethersproject/basex@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.7.0.tgz#97034dc7e8938a8ca943ab20f8a5e492ece4020b" - integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw== +"@ethersproject/basex@5.8.0", "@ethersproject/basex@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.8.0.tgz#1d279a90c4be84d1c1139114a1f844869e57d03a" + integrity sha512-PIgTszMlDRmNwW9nhS6iqtVfdTAKosA7llYXNmGPw4YAI1PUyMv28988wAb41/gHF/WqGdoLv0erHaRcHRKW2Q== dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/properties" "^5.7.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/properties" "^5.8.0" -"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.7.0": +"@ethersproject/bignumber@5.8.0", "@ethersproject/bignumber@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.8.0.tgz#c381d178f9eeb370923d389284efa19f69efa5d7" + integrity sha512-ZyaT24bHaSeJon2tGPKIiHszWjD/54Sz8t57Toch475lCLljC6MgPmxk7Gtzz+ddNN5LuHea9qhAe0x3D+uYPA== + dependencies: + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + bn.js "^5.2.1" + +"@ethersproject/bignumber@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" + resolved "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz" integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== dependencies: "@ethersproject/bytes" "^5.7.0" "@ethersproject/logger" "^5.7.0" bn.js "^5.2.1" -"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.7.0": +"@ethersproject/bytes@5.8.0", "@ethersproject/bytes@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.8.0.tgz#9074820e1cac7507a34372cadeb035461463be34" + integrity sha512-vTkeohgJVCPVHu5c25XWaWQOZ4v+DkGoC42/TS2ond+PARCxTJvgTFUNDZovyQ/uAQ4EcpqqowKydcdmRKjg7A== + dependencies: + "@ethersproject/logger" "^5.8.0" + +"@ethersproject/bytes@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" + resolved "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz" integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== dependencies: "@ethersproject/logger" "^5.7.0" -"@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" - integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== +"@ethersproject/constants@5.8.0", "@ethersproject/constants@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.8.0.tgz#12f31c2f4317b113a4c19de94e50933648c90704" + integrity sha512-wigX4lrf5Vu+axVTIvNsuL6YrV4O5AXl5ubcURKMEME5TnWBouUh0CDTWxZ2GpnRn1kcCgE7l8O5+VbV9QTTcg== dependencies: - "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bignumber" "^5.8.0" -"@ethersproject/contracts@5.7.0": +"@ethersproject/constants@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e" - integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== + resolved "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz" + integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== dependencies: - "@ethersproject/abi" "^5.7.0" - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" -"@ethersproject/hash@5.7.0", "@ethersproject/hash@^5.7.0": +"@ethersproject/contracts@5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.8.0.tgz#243a38a2e4aa3e757215ea64e276f8a8c9d8ed73" + integrity sha512-0eFjGz9GtuAi6MZwhb4uvUM216F38xiuR0yYCjKJpNfSEy4HUM8hvqqBj9Jmm0IUz8l0xKEhWwLIhPgxNY0yvQ== + dependencies: + "@ethersproject/abi" "^5.8.0" + "@ethersproject/abstract-provider" "^5.8.0" + "@ethersproject/abstract-signer" "^5.8.0" + "@ethersproject/address" "^5.8.0" + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/constants" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/transactions" "^5.8.0" + +"@ethersproject/hash@5.8.0", "@ethersproject/hash@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.8.0.tgz#b8893d4629b7f8462a90102572f8cd65a0192b4c" + integrity sha512-ac/lBcTbEWW/VGJij0CNSw/wPcw9bSRgCB0AIBz8CvED/jfvDoV9hsIIiWfvWmFEi8RcXtlNwp2jv6ozWOsooA== + dependencies: + "@ethersproject/abstract-signer" "^5.8.0" + "@ethersproject/address" "^5.8.0" + "@ethersproject/base64" "^5.8.0" + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/keccak256" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/strings" "^5.8.0" + +"@ethersproject/hash@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" + resolved "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz" integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== dependencies: "@ethersproject/abstract-signer" "^5.7.0" @@ -439,132 +600,179 @@ "@ethersproject/properties" "^5.7.0" "@ethersproject/strings" "^5.7.0" -"@ethersproject/hdnode@5.7.0", "@ethersproject/hdnode@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.7.0.tgz#e627ddc6b466bc77aebf1a6b9e47405ca5aef9cf" - integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg== - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/basex" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/pbkdf2" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/signing-key" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/wordlists" "^5.7.0" - -"@ethersproject/json-wallets@5.7.0", "@ethersproject/json-wallets@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz#5e3355287b548c32b368d91014919ebebddd5360" - integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g== - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/hdnode" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/pbkdf2" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" +"@ethersproject/hdnode@5.8.0", "@ethersproject/hdnode@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.8.0.tgz#a51ae2a50bcd48ef6fd108c64cbae5e6ff34a761" + integrity sha512-4bK1VF6E83/3/Im0ERnnUeWOY3P1BZml4ZD3wcH8Ys0/d1h1xaFt6Zc+Dh9zXf9TapGro0T4wvO71UTCp3/uoA== + dependencies: + "@ethersproject/abstract-signer" "^5.8.0" + "@ethersproject/basex" "^5.8.0" + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/pbkdf2" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/sha2" "^5.8.0" + "@ethersproject/signing-key" "^5.8.0" + "@ethersproject/strings" "^5.8.0" + "@ethersproject/transactions" "^5.8.0" + "@ethersproject/wordlists" "^5.8.0" + +"@ethersproject/json-wallets@5.8.0", "@ethersproject/json-wallets@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.8.0.tgz#d18de0a4cf0f185f232eb3c17d5e0744d97eb8c9" + integrity sha512-HxblNck8FVUtNxS3VTEYJAcwiKYsBIF77W15HufqlBF9gGfhmYOJtYZp8fSDZtn9y5EaXTE87zDwzxRoTFk11w== + dependencies: + "@ethersproject/abstract-signer" "^5.8.0" + "@ethersproject/address" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/hdnode" "^5.8.0" + "@ethersproject/keccak256" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/pbkdf2" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/random" "^5.8.0" + "@ethersproject/strings" "^5.8.0" + "@ethersproject/transactions" "^5.8.0" aes-js "3.0.0" scrypt-js "3.0.1" -"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.7.0": +"@ethersproject/keccak256@5.8.0", "@ethersproject/keccak256@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.8.0.tgz#d2123a379567faf2d75d2aaea074ffd4df349e6a" + integrity sha512-A1pkKLZSz8pDaQ1ftutZoaN46I6+jvuqugx5KYNeQOPqq+JZ0Txm7dlWesCHB5cndJSu5vP2VKptKf7cksERng== + dependencies: + "@ethersproject/bytes" "^5.8.0" + js-sha3 "0.8.0" + +"@ethersproject/keccak256@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" + resolved "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz" integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== dependencies: "@ethersproject/bytes" "^5.7.0" js-sha3 "0.8.0" -"@ethersproject/logger@5.7.0", "@ethersproject/logger@^5.7.0": +"@ethersproject/logger@5.8.0", "@ethersproject/logger@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.8.0.tgz#f0232968a4f87d29623a0481690a2732662713d6" + integrity sha512-Qe6knGmY+zPPWTC+wQrpitodgBfH7XoceCGL5bJVejmH+yCS3R8jJm8iiWuvWbG76RUmyEG53oqv6GMVWqunjA== + +"@ethersproject/logger@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" + resolved "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz" integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== -"@ethersproject/networks@5.7.1", "@ethersproject/networks@^5.7.0": +"@ethersproject/networks@5.8.0", "@ethersproject/networks@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.8.0.tgz#8b4517a3139380cba9fb00b63ffad0a979671fde" + integrity sha512-egPJh3aPVAzbHwq8DD7Po53J4OUSsA1MjQp8Vf/OZPav5rlmWUaFLiq8cvQiGK0Z5K6LYzm29+VA/p4RL1FzNg== + dependencies: + "@ethersproject/logger" "^5.8.0" + +"@ethersproject/networks@^5.7.0": version "5.7.1" - resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6" + resolved "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz" integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== dependencies: "@ethersproject/logger" "^5.7.0" -"@ethersproject/pbkdf2@5.7.0", "@ethersproject/pbkdf2@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz#d2267d0a1f6e123f3771007338c47cccd83d3102" - integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw== +"@ethersproject/pbkdf2@5.8.0", "@ethersproject/pbkdf2@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.8.0.tgz#cd2621130e5dd51f6a0172e63a6e4a0c0a0ec37e" + integrity sha512-wuHiv97BrzCmfEaPbUFpMjlVg/IDkZThp9Ri88BpjRleg4iePJaj2SW8AIyE8cXn5V1tuAaMj6lzvsGJkGWskg== dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/sha2" "^5.8.0" + +"@ethersproject/properties@5.8.0", "@ethersproject/properties@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.8.0.tgz#405a8affb6311a49a91dabd96aeeae24f477020e" + integrity sha512-PYuiEoQ+FMaZZNGrStmN7+lWjlsoufGIHdww7454FIaGdbe/p5rnaCXTr5MtBYl3NkeoVhHZuyzChPeGeKIpQw== + dependencies: + "@ethersproject/logger" "^5.8.0" -"@ethersproject/properties@5.7.0", "@ethersproject/properties@^5.7.0": +"@ethersproject/properties@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" + resolved "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz" integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== dependencies: "@ethersproject/logger" "^5.7.0" -"@ethersproject/providers@5.7.2": - version "5.7.2" - resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" - integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/base64" "^5.7.0" - "@ethersproject/basex" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/networks" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/web" "^5.7.0" +"@ethersproject/providers@5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.8.0.tgz#6c2ae354f7f96ee150439f7de06236928bc04cb4" + integrity sha512-3Il3oTzEx3o6kzcg9ZzbE+oCZYyY+3Zh83sKkn4s1DZfTUjIegHnN2Cm0kbn9YFy45FDVcuCLLONhU7ny0SsCw== + dependencies: + "@ethersproject/abstract-provider" "^5.8.0" + "@ethersproject/abstract-signer" "^5.8.0" + "@ethersproject/address" "^5.8.0" + "@ethersproject/base64" "^5.8.0" + "@ethersproject/basex" "^5.8.0" + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/constants" "^5.8.0" + "@ethersproject/hash" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/networks" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/random" "^5.8.0" + "@ethersproject/rlp" "^5.8.0" + "@ethersproject/sha2" "^5.8.0" + "@ethersproject/strings" "^5.8.0" + "@ethersproject/transactions" "^5.8.0" + "@ethersproject/web" "^5.8.0" bech32 "1.1.4" - ws "7.4.6" + ws "8.18.0" -"@ethersproject/random@5.7.0", "@ethersproject/random@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.7.0.tgz#af19dcbc2484aae078bb03656ec05df66253280c" - integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ== +"@ethersproject/random@5.8.0", "@ethersproject/random@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.8.0.tgz#1bced04d49449f37c6437c701735a1a022f0057a" + integrity sha512-E4I5TDl7SVqyg4/kkA/qTfuLWAQGXmSOgYyO01So8hLfwgKvYK5snIlzxJMk72IFdG/7oh8yuSqY2KX7MMwg+A== dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/logger" "^5.8.0" -"@ethersproject/rlp@5.7.0", "@ethersproject/rlp@^5.7.0": +"@ethersproject/rlp@5.8.0", "@ethersproject/rlp@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.8.0.tgz#5a0d49f61bc53e051532a5179472779141451de5" + integrity sha512-LqZgAznqDbiEunaUvykH2JAoXTT9NV0Atqk8rQN9nx9SEgThA/WMx5DnW8a9FOufo//6FZOCHZ+XiClzgbqV9Q== + dependencies: + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + +"@ethersproject/rlp@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304" + resolved "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz" integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== dependencies: "@ethersproject/bytes" "^5.7.0" "@ethersproject/logger" "^5.7.0" -"@ethersproject/sha2@5.7.0", "@ethersproject/sha2@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.7.0.tgz#9a5f7a7824ef784f7f7680984e593a800480c9fb" - integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw== +"@ethersproject/sha2@5.8.0", "@ethersproject/sha2@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.8.0.tgz#8954a613bb78dac9b46829c0a95de561ef74e5e1" + integrity sha512-dDOUrXr9wF/YFltgTBYS0tKslPEKr6AekjqDW2dbn1L1xmjGR+9GiKu4ajxovnrDbwxAKdHjW8jNcwfz8PAz4A== dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/logger" "^5.8.0" hash.js "1.1.7" -"@ethersproject/signing-key@5.7.0", "@ethersproject/signing-key@^5.7.0": +"@ethersproject/signing-key@5.8.0", "@ethersproject/signing-key@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.8.0.tgz#9797e02c717b68239c6349394ea85febf8893119" + integrity sha512-LrPW2ZxoigFi6U6aVkFN/fa9Yx/+4AtIUe4/HACTvKJdhm0eeb107EVCIQcrLZkxaSIgc/eCrX8Q1GtbH+9n3w== + dependencies: + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + bn.js "^5.2.1" + elliptic "6.6.1" + hash.js "1.1.7" + +"@ethersproject/signing-key@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3" + resolved "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz" integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== dependencies: "@ethersproject/bytes" "^5.7.0" @@ -574,30 +782,54 @@ elliptic "6.5.4" hash.js "1.1.7" -"@ethersproject/solidity@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8" - integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== +"@ethersproject/solidity@5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.8.0.tgz#429bb9fcf5521307a9448d7358c26b93695379b9" + integrity sha512-4CxFeCgmIWamOHwYN9d+QWGxye9qQLilpgTU0XhYs1OahkclF+ewO+3V1U0mvpiuQxm5EHHmv8f7ClVII8EHsA== dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/strings" "^5.7.0" + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/keccak256" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/sha2" "^5.8.0" + "@ethersproject/strings" "^5.8.0" -"@ethersproject/strings@5.7.0", "@ethersproject/strings@^5.7.0": +"@ethersproject/strings@5.8.0", "@ethersproject/strings@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.8.0.tgz#ad79fafbf0bd272d9765603215ac74fd7953908f" + integrity sha512-qWEAk0MAvl0LszjdfnZ2uC8xbR2wdv4cDabyHiBh3Cldq/T8dPH3V4BbBsAYJUeonwD+8afVXld274Ls+Y1xXg== + dependencies: + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/constants" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + +"@ethersproject/strings@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" + resolved "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz" integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== dependencies: "@ethersproject/bytes" "^5.7.0" "@ethersproject/constants" "^5.7.0" "@ethersproject/logger" "^5.7.0" -"@ethersproject/transactions@5.7.0", "@ethersproject/transactions@^5.6.2", "@ethersproject/transactions@^5.7.0": +"@ethersproject/transactions@5.8.0", "@ethersproject/transactions@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.8.0.tgz#1e518822403abc99def5a043d1c6f6fe0007e46b" + integrity sha512-UglxSDjByHG0TuU17bDfCemZ3AnKO2vYrL5/2n2oXvKzvb7Cz+W9gOWXKARjp2URVwcWlQlPOEQyAviKwT4AHg== + dependencies: + "@ethersproject/address" "^5.8.0" + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/constants" "^5.8.0" + "@ethersproject/keccak256" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/rlp" "^5.8.0" + "@ethersproject/signing-key" "^5.8.0" + +"@ethersproject/transactions@^5.6.2", "@ethersproject/transactions@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b" + resolved "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz" integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== dependencies: "@ethersproject/address" "^5.7.0" @@ -610,39 +842,50 @@ "@ethersproject/rlp" "^5.7.0" "@ethersproject/signing-key" "^5.7.0" -"@ethersproject/units@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1" - integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/wallet@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d" - integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/hdnode" "^5.7.0" - "@ethersproject/json-wallets" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/signing-key" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/wordlists" "^5.7.0" - -"@ethersproject/web@5.7.1", "@ethersproject/web@^5.7.0": +"@ethersproject/units@5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.8.0.tgz#c12f34ba7c3a2de0e9fa0ed0ee32f3e46c5c2c6a" + integrity sha512-lxq0CAnc5kMGIiWW4Mr041VT8IhNM+Pn5T3haO74XZWFulk7wH1Gv64HqE96hT4a7iiNMdOCFEBgaxWuk8ETKQ== + dependencies: + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/constants" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + +"@ethersproject/wallet@5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.8.0.tgz#49c300d10872e6986d953e8310dc33d440da8127" + integrity sha512-G+jnzmgg6UxurVKRKvw27h0kvG75YKXZKdlLYmAHeF32TGUzHkOFd7Zn6QHOTYRFWnfjtSSFjBowKo7vfrXzPA== + dependencies: + "@ethersproject/abstract-provider" "^5.8.0" + "@ethersproject/abstract-signer" "^5.8.0" + "@ethersproject/address" "^5.8.0" + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/hash" "^5.8.0" + "@ethersproject/hdnode" "^5.8.0" + "@ethersproject/json-wallets" "^5.8.0" + "@ethersproject/keccak256" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/random" "^5.8.0" + "@ethersproject/signing-key" "^5.8.0" + "@ethersproject/transactions" "^5.8.0" + "@ethersproject/wordlists" "^5.8.0" + +"@ethersproject/web@5.8.0", "@ethersproject/web@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.8.0.tgz#3e54badc0013b7a801463a7008a87988efce8a37" + integrity sha512-j7+Ksi/9KfGviws6Qtf9Q7KCqRhpwrYKQPs+JBA/rKVFF/yaWLHJEH3zfVP2plVu+eys0d2DlFmhoQJayFewcw== + dependencies: + "@ethersproject/base64" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/strings" "^5.8.0" + +"@ethersproject/web@^5.7.0": version "5.7.1" - resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae" + resolved "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz" integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== dependencies: "@ethersproject/base64" "^5.7.0" @@ -651,20 +894,20 @@ "@ethersproject/properties" "^5.7.0" "@ethersproject/strings" "^5.7.0" -"@ethersproject/wordlists@5.7.0", "@ethersproject/wordlists@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.7.0.tgz#8fb2c07185d68c3e09eb3bfd6e779ba2774627f5" - integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA== +"@ethersproject/wordlists@5.8.0", "@ethersproject/wordlists@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.8.0.tgz#7a5654ee8d1bb1f4dbe43f91d217356d650ad821" + integrity sha512-2df9bbXicZws2Sb5S6ET493uJ0Z84Fjr3pC4tu/qlnZERibZCeUVuqdtt+7Tv9xxhUxHoIekIA7avrKUWHrezg== dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/hash" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/strings" "^5.8.0" "@fastify/busboy@^2.0.0": version "2.0.0" - resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.0.0.tgz#f22824caff3ae506b18207bad4126dbc6ccdb6b8" + resolved "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.0.0.tgz" integrity sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ== "@graphql-tools/batch-execute@8.5.1": @@ -757,21 +1000,21 @@ "@improbable-eng/grpc-web@^0.12.0": version "0.12.0" - resolved "https://registry.yarnpkg.com/@improbable-eng/grpc-web/-/grpc-web-0.12.0.tgz#9b10a7edf2a1d7672f8997e34a60e7b70e49738f" + resolved "https://registry.npmjs.org/@improbable-eng/grpc-web/-/grpc-web-0.12.0.tgz" integrity sha512-uJjgMPngreRTYPBuo6gswMj1gK39Wbqre/RgE0XnSDXJRg6ST7ZhuS53dFE6Vc2CX4jxgl+cO+0B3op8LA4Q0Q== dependencies: browser-headers "^0.4.0" "@improbable-eng/grpc-web@^0.13.0": version "0.13.0" - resolved "https://registry.yarnpkg.com/@improbable-eng/grpc-web/-/grpc-web-0.13.0.tgz#289e6fc4dafc00b1af8e2b93b970e6892299014d" + resolved "https://registry.npmjs.org/@improbable-eng/grpc-web/-/grpc-web-0.13.0.tgz" integrity sha512-vaxxT+Qwb7GPqDQrBV4vAAfH0HywgOLw6xGIKXd9Q8hcV63CQhmS3p4+pZ9/wVvt4Ph3ZDK9fdC983b9aGMUFg== dependencies: browser-headers "^0.4.0" "@improbable-eng/grpc-web@^0.14.0", "@improbable-eng/grpc-web@^0.14.1": version "0.14.1" - resolved "https://registry.yarnpkg.com/@improbable-eng/grpc-web/-/grpc-web-0.14.1.tgz#f4662f64dc89c0f956a94bb8a3b576556c74589c" + resolved "https://registry.npmjs.org/@improbable-eng/grpc-web/-/grpc-web-0.14.1.tgz" integrity sha512-XaIYuunepPxoiGVLLHmlnVminUGzBTnXr8Wv7khzmLWbNw4TCwJKX09GSMJlKhu/TRk6gms0ySFxewaETSBqgw== dependencies: browser-headers "^0.4.1" @@ -781,27 +1024,43 @@ resolved "https://registry.yarnpkg.com/@josephg/resolvable/-/resolvable-1.0.1.tgz#69bc4db754d79e1a2f17a650d3466e038d94a5eb" integrity sha512-CtzORUwWTTOTqfVtHaKRJ0I1kNQd1bpn3sUh8I3nJDVY+5/M/Oe1DnEWzPQvqq/xPIIkzzzIP7mfCoAjFRvDhg== -"@jridgewell/resolve-uri@^3.0.3": +"@jridgewell/gen-mapping@^0.3.12": + version "0.3.13" + resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz" + integrity sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": version "3.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" + resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz" integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== -"@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0": + version "1.5.5" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz" + integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== "@jridgewell/trace-mapping@0.3.9": version "0.3.9" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz" integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== dependencies: "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" +"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.28": + version "0.3.31" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz" + integrity sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + "@ledgerhq/devices@^5.51.1": version "5.51.1" - resolved "https://registry.yarnpkg.com/@ledgerhq/devices/-/devices-5.51.1.tgz#d741a4a5d8f17c2f9d282fd27147e6fe1999edb7" + resolved "https://registry.npmjs.org/@ledgerhq/devices/-/devices-5.51.1.tgz" integrity sha512-4w+P0VkbjzEXC7kv8T1GJ/9AVaP9I6uasMZ/JcdwZBS3qwvKo5A5z9uGhP5c7TvItzcmPb44b5Mw2kT+WjUuAA== dependencies: "@ledgerhq/errors" "^5.50.0" @@ -811,12 +1070,12 @@ "@ledgerhq/errors@^5.50.0": version "5.50.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/errors/-/errors-5.50.0.tgz#e3a6834cb8c19346efca214c1af84ed28e69dad9" + resolved "https://registry.npmjs.org/@ledgerhq/errors/-/errors-5.50.0.tgz" integrity sha512-gu6aJ/BHuRlpU7kgVpy2vcYk6atjB4iauP2ymF7Gk0ez0Y/6VSMVSJvubeEQN+IV60+OBK0JgeIZG7OiHaw8ow== "@ledgerhq/hw-transport-webusb@^5.22.0": version "5.53.1" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-webusb/-/hw-transport-webusb-5.53.1.tgz#3df8c401417571e3bcacc378d8aca587214b05ae" + resolved "https://registry.npmjs.org/@ledgerhq/hw-transport-webusb/-/hw-transport-webusb-5.53.1.tgz" integrity sha512-A/f+xcrkIAZiJrvPpDvsrjxQX4cI2kbdiunQkwsYmOG3Bp4z89ZnsBiC7YBst4n2/g+QgTg0/KPVtODU5djooQ== dependencies: "@ledgerhq/devices" "^5.51.1" @@ -826,7 +1085,7 @@ "@ledgerhq/hw-transport@^5.51.1": version "5.51.1" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-5.51.1.tgz#8dd14a8e58cbee4df0c29eaeef983a79f5f22578" + resolved "https://registry.npmjs.org/@ledgerhq/hw-transport/-/hw-transport-5.51.1.tgz" integrity sha512-6wDYdbWrw9VwHIcoDnqWBaDFyviyjZWv6H9vz9Vyhe4Qd7TIFmbTl/eWs6hZvtZBza9K8y7zD8ChHwRI4s9tSw== dependencies: "@ledgerhq/devices" "^5.51.1" @@ -835,12 +1094,12 @@ "@ledgerhq/logs@^5.50.0": version "5.50.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/logs/-/logs-5.50.0.tgz#29c6419e8379d496ab6d0426eadf3c4d100cd186" + resolved "https://registry.npmjs.org/@ledgerhq/logs/-/logs-5.50.0.tgz" integrity sha512-swKHYCOZUGyVt4ge0u8a7AwNcA//h4nx5wIi0sruGye1IJ5Cva0GyK9L2/WdX+kWVTKp92ZiEo1df31lrWGPgA== "@metamask/eth-sig-util@^4.0.0": version "4.0.1" - resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz#3ad61f6ea9ad73ba5b19db780d40d9aae5157088" + resolved "https://registry.npmjs.org/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz" integrity sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ== dependencies: ethereumjs-abi "^0.6.8" @@ -851,42 +1110,54 @@ "@multiformats/base-x@^4.0.1": version "4.0.1" - resolved "https://registry.yarnpkg.com/@multiformats/base-x/-/base-x-4.0.1.tgz#95ff0fa58711789d53aefb2590a8b7a4e715d121" + resolved "https://registry.npmjs.org/@multiformats/base-x/-/base-x-4.0.1.tgz" integrity sha512-eMk0b9ReBbV23xXU693TAIrLyeO5iTgBZGSJfpqriG8UkYvr/hC9u9pyMlAakDNHWmbhMZCDs6KQO0jzKD8OTw== +"@noble/curves@1.4.2", "@noble/curves@~1.4.0": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.2.tgz#40309198c76ed71bc6dbf7ba24e81ceb4d0d1fe9" + integrity sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw== + dependencies: + "@noble/hashes" "1.4.0" + "@noble/hashes@1.1.2": version "1.1.2" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.2.tgz#e9e035b9b166ca0af657a7848eb2718f0f22f183" + resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.2.tgz" integrity sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA== "@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": version "1.2.0" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" + resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz" integrity sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ== +"@noble/hashes@1.4.0", "@noble/hashes@~1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" + integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== + "@noble/hashes@^1.2.0": version "1.3.1" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.1.tgz#8831ef002114670c603c458ab8b11328406953a9" + resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz" integrity sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA== "@noble/secp256k1@1.7.1", "@noble/secp256k1@~1.7.0": version "1.7.1" - resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c" + resolved "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz" integrity sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw== "@nodefactory/filsnap-adapter@^0.2.1": version "0.2.2" - resolved "https://registry.yarnpkg.com/@nodefactory/filsnap-adapter/-/filsnap-adapter-0.2.2.tgz#0e182150ce3825b6c26b8512ab9355ab7759b498" + resolved "https://registry.npmjs.org/@nodefactory/filsnap-adapter/-/filsnap-adapter-0.2.2.tgz" integrity sha512-nbaYMwVopOXN2bWOdDY3il6gGL9qMuCmMN4WPuoxzJjSnAMJNqEeSe6MNNJ/fYBLipZcJfAtirNXRrFLFN+Tvw== "@nodefactory/filsnap-types@^0.2.1": version "0.2.2" - resolved "https://registry.yarnpkg.com/@nodefactory/filsnap-types/-/filsnap-types-0.2.2.tgz#f95cbf93ce5815d8d151c60663940086b015cb8f" + resolved "https://registry.npmjs.org/@nodefactory/filsnap-types/-/filsnap-types-0.2.2.tgz" integrity sha512-XT1tE2vrYF2D0tSNNekgjqKRpqPQn4W72eKul9dDCul/8ykouhqnVTyjFHYvBhlBWE0PK3nmG7i83QvhgGSiMw== "@nodelib/fs.scandir@2.1.5": version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== dependencies: "@nodelib/fs.stat" "2.0.5" @@ -894,12 +1165,12 @@ "@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== "@nodelib/fs.walk@^1.2.3": version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== dependencies: "@nodelib/fs.scandir" "2.1.5" @@ -907,7 +1178,7 @@ "@nomicfoundation/ethereumjs-block@5.0.4": version "5.0.4" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-5.0.4.tgz#ff2acb98a86b9290e35e315a6abfb9aebb9cf39e" + resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-5.0.4.tgz" integrity sha512-AcyacJ9eX/uPEvqsPiB+WO1ymE+kyH48qGGiGV+YTojdtas8itUTW5dehDSOXEEItWGbbzEJ4PRqnQZlWaPvDw== dependencies: "@nomicfoundation/ethereumjs-common" "4.0.4" @@ -919,7 +1190,7 @@ "@nomicfoundation/ethereumjs-blockchain@7.0.4": version "7.0.4" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-7.0.4.tgz#b77511b389290b186c8d999e70f4b15c27ef44ea" + resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-7.0.4.tgz" integrity sha512-jYsd/kwzbmpnxx86tXsYV8wZ5xGvFL+7/P0c6OlzpClHsbFzeF41KrYA9scON8Rg6bZu3ZTv6JOAgj3t7USUfg== dependencies: "@nomicfoundation/ethereumjs-block" "5.0.4" @@ -935,14 +1206,14 @@ "@nomicfoundation/ethereumjs-common@4.0.4": version "4.0.4" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.4.tgz#9901f513af2d4802da87c66d6f255b510bef5acb" + resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.4.tgz" integrity sha512-9Rgb658lcWsjiicr5GzNCjI1llow/7r0k50dLL95OJ+6iZJcVbi15r3Y0xh2cIO+zgX0WIHcbzIu6FeQf9KPrg== dependencies: "@nomicfoundation/ethereumjs-util" "9.0.4" "@nomicfoundation/ethereumjs-ethash@3.0.4": version "3.0.4" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-3.0.4.tgz#06cb2502b3012fb6c11cffd44af08aecf71310da" + resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-3.0.4.tgz" integrity sha512-xvIrwIMl9sSaiYKRem68+O7vYdj7Q2XWv5P7JXiIkn83918QzWHvqbswTRsH7+r6X1UEvdsURRnZbvZszEjAaQ== dependencies: "@nomicfoundation/ethereumjs-block" "5.0.4" @@ -953,7 +1224,7 @@ "@nomicfoundation/ethereumjs-evm@2.0.4": version "2.0.4" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-2.0.4.tgz#c9c761767283ac53946185474362230b169f8f63" + resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-2.0.4.tgz" integrity sha512-lTyZZi1KpeMHzaO6cSVisR2tjiTTedjo7PcmhI/+GNFo9BmyY6QYzGeSti0sFttmjbEMioHgXxl5yrLNRg6+1w== dependencies: "@nomicfoundation/ethereumjs-common" "4.0.4" @@ -967,12 +1238,12 @@ "@nomicfoundation/ethereumjs-rlp@5.0.4": version "5.0.4" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.4.tgz#66c95256fc3c909f6fb18f6a586475fc9762fa30" + resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.4.tgz" integrity sha512-8H1S3s8F6QueOc/X92SdrA4RDenpiAEqMg5vJH99kcQaCy/a3Q6fgseo75mgWlbanGJXSlAPtnCeG9jvfTYXlw== "@nomicfoundation/ethereumjs-statemanager@2.0.4": version "2.0.4" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-2.0.4.tgz#bf14415e1f31b5ea8b98a0c027c547d0555059b6" + resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-2.0.4.tgz" integrity sha512-HPDjeFrxw6llEi+BzqXkZ+KkvFnTOPczuHBtk21hRlDiuKuZz32dPzlhpRsDBGV1b5JTmRDUVqCS1lp3Gghw4Q== dependencies: "@nomicfoundation/ethereumjs-common" "4.0.4" @@ -986,7 +1257,7 @@ "@nomicfoundation/ethereumjs-trie@6.0.4": version "6.0.4" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-6.0.4.tgz#688a3f76646c209365ee6d959c3d7330ede5e609" + resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-6.0.4.tgz" integrity sha512-3nSwQiFMvr2VFe/aZUyinuohYvtytUqZCUCvIWcPJ/BwJH6oQdZRB42aNFBJ/8nAh2s3OcroWpBLskzW01mFKA== dependencies: "@nomicfoundation/ethereumjs-rlp" "5.0.4" @@ -998,7 +1269,7 @@ "@nomicfoundation/ethereumjs-tx@5.0.4": version "5.0.4" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.4.tgz#b0ceb58c98cc34367d40a30d255d6315b2f456da" + resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.4.tgz" integrity sha512-Xjv8wAKJGMrP1f0n2PeyfFCCojHd7iS3s/Ab7qzF1S64kxZ8Z22LCMynArYsVqiFx6rzYy548HNVEyI+AYN/kw== dependencies: "@nomicfoundation/ethereumjs-common" "4.0.4" @@ -1008,7 +1279,7 @@ "@nomicfoundation/ethereumjs-util@9.0.4": version "9.0.4" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.4.tgz#84c5274e82018b154244c877b76bc049a4ed7b38" + resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.4.tgz" integrity sha512-sLOzjnSrlx9Bb9EFNtHzK/FJFsfg2re6bsGqinFinH1gCqVfz9YYlXiMWwDM4C/L4ywuHFCYwfKTVr/QHQcU0Q== dependencies: "@nomicfoundation/ethereumjs-rlp" "5.0.4" @@ -1016,7 +1287,7 @@ "@nomicfoundation/ethereumjs-verkle@0.0.2": version "0.0.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-verkle/-/ethereumjs-verkle-0.0.2.tgz#7686689edec775b2efea5a71548f417c18f7dea4" + resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-verkle/-/ethereumjs-verkle-0.0.2.tgz" integrity sha512-bjnfZElpYGK/XuuVRmLS3yDvr+cDs85D9oonZ0YUa5A3lgFgokWMp76zXrxX2jVQ0BfHaw12y860n1+iOi6yFQ== dependencies: "@nomicfoundation/ethereumjs-rlp" "5.0.4" @@ -1026,7 +1297,7 @@ "@nomicfoundation/ethereumjs-vm@7.0.4": version "7.0.4" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-7.0.4.tgz#e5a6eec4877dc62dda93003c6d7afd1fe4b9625b" + resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-7.0.4.tgz" integrity sha512-gsA4IhmtWHI4BofKy3kio9W+dqZQs5Ji5mLjLYxHCkat+JQBUt5szjRKra2F9nGDJ2XcI/wWb0YWUFNgln4zRQ== dependencies: "@nomicfoundation/ethereumjs-block" "5.0.4" @@ -1043,7 +1314,7 @@ "@nomicfoundation/hardhat-chai-matchers@^2.0.2": version "2.0.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-chai-matchers/-/hardhat-chai-matchers-2.0.2.tgz#a0e5dbca43ba9560c096da162c0e3245303479d1" + resolved "https://registry.npmjs.org/@nomicfoundation/hardhat-chai-matchers/-/hardhat-chai-matchers-2.0.2.tgz" integrity sha512-9Wu9mRtkj0U9ohgXYFbB/RQDa+PcEdyBm2suyEtsJf3PqzZEEjLUZgWnMjlFhATMk/fp3BjmnYVPrwl+gr8oEw== dependencies: "@types/chai-as-promised" "^7.1.3" @@ -1053,7 +1324,7 @@ "@nomicfoundation/hardhat-ethers@^3.0.4": version "3.0.4" - resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-ethers/-/hardhat-ethers-3.0.4.tgz#6f0df2424e687e26d6574610de7a36bd69485cc1" + resolved "https://registry.npmjs.org/@nomicfoundation/hardhat-ethers/-/hardhat-ethers-3.0.4.tgz" integrity sha512-k9qbLoY7qn6C6Y1LI0gk2kyHXil2Tauj4kGzQ8pgxYXIGw8lWn8tuuL72E11CrlKaXRUvOgF0EXrv/msPI2SbA== dependencies: debug "^4.1.1" @@ -1061,19 +1332,19 @@ "@nomicfoundation/hardhat-network-helpers@^1.0.8": version "1.0.8" - resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-network-helpers/-/hardhat-network-helpers-1.0.8.tgz#e4fe1be93e8a65508c46d73c41fa26c7e9f84931" + resolved "https://registry.npmjs.org/@nomicfoundation/hardhat-network-helpers/-/hardhat-network-helpers-1.0.8.tgz" integrity sha512-MNqQbzUJZnCMIYvlniC3U+kcavz/PhhQSsY90tbEtUyMj/IQqsLwIRZa4ctjABh3Bz0KCh9OXUZ7Yk/d9hr45Q== dependencies: ethereumjs-util "^7.1.4" "@nomicfoundation/hardhat-toolbox@^3.0.0": version "3.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-toolbox/-/hardhat-toolbox-3.0.0.tgz#83e2c28a745aa4eb1236072166367b0de68b4c76" + resolved "https://registry.npmjs.org/@nomicfoundation/hardhat-toolbox/-/hardhat-toolbox-3.0.0.tgz" integrity sha512-MsteDXd0UagMksqm9KvcFG6gNKYNa3GGNCy73iQ6bEasEgg2v8Qjl6XA5hjs8o5UD5A3153B6W2BIVJ8SxYUtA== "@nomicfoundation/hardhat-verify@^1.1.1": version "1.1.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-verify/-/hardhat-verify-1.1.1.tgz#6a433d777ce0172d1f0edf7f2d3e1df14b3ecfc1" + resolved "https://registry.npmjs.org/@nomicfoundation/hardhat-verify/-/hardhat-verify-1.1.1.tgz" integrity sha512-9QsTYD7pcZaQFEA3tBb/D/oCStYDiEVDN7Dxeo/4SCyHRSm86APypxxdOMEPlGmXsAvd+p1j/dTODcpxb8aztA== dependencies: "@ethersproject/abi" "^5.1.2" @@ -1088,7 +1359,7 @@ "@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.1": version "0.1.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.1.tgz#4c858096b1c17fe58a474fe81b46815f93645c15" + resolved "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.1.tgz" integrity sha512-KcTodaQw8ivDZyF+D76FokN/HdpgGpfjc/gFCImdLUyqB6eSWVaZPazMbeAjmfhx3R0zm/NYVzxwAokFKgrc0w== "@nomicfoundation/solidity-analyzer-darwin-x64@0.1.1": @@ -1138,7 +1409,7 @@ "@nomicfoundation/solidity-analyzer@^0.1.0": version "0.1.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.1.tgz#f5f4d36d3f66752f59a57e7208cd856f3ddf6f2d" + resolved "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.1.tgz" integrity sha512-1LMtXj1puAxyFusBgUIy5pZk3073cNXYnXUpuNKFghHbIit/xZgbk0AokpUADbNm3gyD6bFWl3LRFh3dhVdREg== optionalDependencies: "@nomicfoundation/solidity-analyzer-darwin-arm64" "0.1.1" @@ -1152,14 +1423,14 @@ "@nomicfoundation/solidity-analyzer-win32-ia32-msvc" "0.1.1" "@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.1" -"@openzeppelin/contracts@^4.9.6": - version "4.9.6" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.9.6.tgz#2a880a24eb19b4f8b25adc2a5095f2aa27f39677" - integrity sha512-xSmezSupL+y9VkHZJGDoCBpmnB2ogM13ccaYDWqJTfS3dbuHkgjuwDFUmaFauBCboQMGB/S5UqUl2y54X99BmA== +"@openzeppelin/contracts@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-5.4.0.tgz#177594bdb2d86c71f5d1052fe40cb4edb95fb20f" + integrity sha512-eCYgWnLg6WO+X52I16TZt8uEjbtdkgLC0SUX/xnAksjjrQI4Xfn4iBRoI5j55dmlOhDv1Y7BoR3cU7e3WWhC6A== "@openzeppelin/defender-base-client@^1.47.0": version "1.48.0" - resolved "https://registry.yarnpkg.com/@openzeppelin/defender-base-client/-/defender-base-client-1.48.0.tgz#9103b1b036db0451b52d7899a277bf24db4c4b06" + resolved "https://registry.npmjs.org/@openzeppelin/defender-base-client/-/defender-base-client-1.48.0.tgz" integrity sha512-HFO87s010hRrMjyh2xYOCEAkLe21BfIbho7n5/kikA6A1ZgXi7MsEiqnQv1zP4bxMJgxGZ5b3t4tt6fWrakbag== dependencies: amazon-cognito-identity-js "^6.0.1" @@ -1170,7 +1441,7 @@ "@openzeppelin/hardhat-upgrades@^2.0.2": version "2.1.1" - resolved "https://registry.yarnpkg.com/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-2.1.1.tgz#43d89eda502007f8c5e92d9d4a443823843499c2" + resolved "https://registry.npmjs.org/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-2.1.1.tgz" integrity sha512-t+tFpgQq3BOeatMzn4XddDMHX4R0hGbj/5FuKF2DkFscbpqEFVARMkrL0a1hX2zIZNz25bVuzB4rlmUA0RWV5w== dependencies: "@openzeppelin/defender-base-client" "^1.47.0" @@ -1183,7 +1454,7 @@ "@openzeppelin/platform-deploy-client@^0.9.0": version "0.9.0" - resolved "https://registry.yarnpkg.com/@openzeppelin/platform-deploy-client/-/platform-deploy-client-0.9.0.tgz#6d7092066d1c5cf4c25ba6f9d8164e8d1c425b61" + resolved "https://registry.npmjs.org/@openzeppelin/platform-deploy-client/-/platform-deploy-client-0.9.0.tgz" integrity sha512-VepsNJu5B5xhrKMg//hROFljlxlNhlkcgLSKl8rqapKiRFN/dxXtSVmmpNmySrCFnbbV/6twfhuhYGAZiG7oAw== dependencies: "@ethersproject/abi" "^5.6.3" @@ -1194,7 +1465,7 @@ "@openzeppelin/upgrades-core@^1.27.0": version "1.28.0" - resolved "https://registry.yarnpkg.com/@openzeppelin/upgrades-core/-/upgrades-core-1.28.0.tgz#19405f272dc09e766c756d9d149cbd680168aef7" + resolved "https://registry.npmjs.org/@openzeppelin/upgrades-core/-/upgrades-core-1.28.0.tgz" integrity sha512-8RKlyg98Adv+46GxDaR0awL3R8bVCcQ27DcSEwrgWOp6siHh8sZg4a2l+2dhPl1510S6uBfhHSydMH5VX2BV5g== dependencies: cbor "^9.0.0" @@ -1208,27 +1479,27 @@ "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2" - resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" + resolved "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz" integrity sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ== "@protobufjs/base64@^1.1.2": version "1.1.2" - resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735" + resolved "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz" integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg== "@protobufjs/codegen@^2.0.4": version "2.0.4" - resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb" + resolved "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz" integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg== "@protobufjs/eventemitter@^1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70" + resolved "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz" integrity sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q== "@protobufjs/fetch@^1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45" + resolved "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz" integrity sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ== dependencies: "@protobufjs/aspromise" "^1.1.1" @@ -1236,32 +1507,32 @@ "@protobufjs/float@^1.0.2": version "1.0.2" - resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1" + resolved "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz" integrity sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ== "@protobufjs/inquire@^1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089" + resolved "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz" integrity sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q== "@protobufjs/path@^1.1.2": version "1.1.2" - resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d" + resolved "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz" integrity sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA== "@protobufjs/pool@^1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54" + resolved "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz" integrity sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw== "@protobufjs/utf8@^1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" + resolved "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz" integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw== "@redux-saga/core@^1.0.0": version "1.2.3" - resolved "https://registry.yarnpkg.com/@redux-saga/core/-/core-1.2.3.tgz#882ed9ac58b5f42c6abb23349542315b871de305" + resolved "https://registry.npmjs.org/@redux-saga/core/-/core-1.2.3.tgz" integrity sha512-U1JO6ncFBAklFTwoQ3mjAeQZ6QGutsJzwNBjgVLSWDpZTRhobUzuVDS1qH3SKGJD8fvqoaYOjp6XJ3gCmeZWgA== dependencies: "@babel/runtime" "^7.6.3" @@ -1275,19 +1546,19 @@ "@redux-saga/deferred@^1.2.1": version "1.2.1" - resolved "https://registry.yarnpkg.com/@redux-saga/deferred/-/deferred-1.2.1.tgz#aca373a08ccafd6f3481037f2f7ee97f2c87c3ec" + resolved "https://registry.npmjs.org/@redux-saga/deferred/-/deferred-1.2.1.tgz" integrity sha512-cmin3IuuzMdfQjA0lG4B+jX+9HdTgHZZ+6u3jRAOwGUxy77GSlTi4Qp2d6PM1PUoTmQUR5aijlA39scWWPF31g== "@redux-saga/delay-p@^1.2.1": version "1.2.1" - resolved "https://registry.yarnpkg.com/@redux-saga/delay-p/-/delay-p-1.2.1.tgz#e72ac4731c5080a21f75b61bedc31cb639d9e446" + resolved "https://registry.npmjs.org/@redux-saga/delay-p/-/delay-p-1.2.1.tgz" integrity sha512-MdiDxZdvb1m+Y0s4/hgdcAXntpUytr9g0hpcOO1XFVyyzkrDu3SKPgBFOtHn7lhu7n24ZKIAT1qtKyQjHqRd+w== dependencies: "@redux-saga/symbols" "^1.1.3" "@redux-saga/is@^1.1.3": version "1.1.3" - resolved "https://registry.yarnpkg.com/@redux-saga/is/-/is-1.1.3.tgz#b333f31967e87e32b4e6b02c75b78d609dd4ad73" + resolved "https://registry.npmjs.org/@redux-saga/is/-/is-1.1.3.tgz" integrity sha512-naXrkETG1jLRfVfhOx/ZdLj0EyAzHYbgJWkXbB3qFliPcHKiWbv/ULQryOAEKyjrhiclmr6AMdgsXFyx7/yE6Q== dependencies: "@redux-saga/symbols" "^1.1.3" @@ -1295,49 +1566,66 @@ "@redux-saga/symbols@^1.1.3": version "1.1.3" - resolved "https://registry.yarnpkg.com/@redux-saga/symbols/-/symbols-1.1.3.tgz#b731d56201719e96dc887dc3ae9016e761654367" + resolved "https://registry.npmjs.org/@redux-saga/symbols/-/symbols-1.1.3.tgz" integrity sha512-hCx6ZvU4QAEUojETnX8EVg4ubNLBFl1Lps4j2tX7o45x/2qg37m3c6v+kSp8xjDJY+2tJw4QB3j8o8dsl1FDXg== "@redux-saga/types@^1.2.1": version "1.2.1" - resolved "https://registry.yarnpkg.com/@redux-saga/types/-/types-1.2.1.tgz#9403f51c17cae37edf870c6bc0c81c1ece5ccef8" + resolved "https://registry.npmjs.org/@redux-saga/types/-/types-1.2.1.tgz" integrity sha512-1dgmkh+3so0+LlBWRhGA33ua4MYr7tUOj+a9Si28vUi0IUFNbff1T3sgpeDJI/LaC75bBYnQ0A3wXjn0OrRNBA== "@repeaterjs/repeater@^3.0.4": version "3.0.4" - resolved "https://registry.yarnpkg.com/@repeaterjs/repeater/-/repeater-3.0.4.tgz#a04d63f4d1bf5540a41b01a921c9a7fddc3bd1ca" + resolved "https://registry.npmjs.org/@repeaterjs/repeater/-/repeater-3.0.4.tgz" integrity sha512-AW8PKd6iX3vAZ0vA43nOUOnbq/X5ihgU+mSXXqunMkeQADGiqw/PY0JNeYtD5sr0PAy51YPgAPbDoeapv9r8WA== -"@scure/base@^1.1.1": +"@scure/base@^1.1.1", "@scure/base@~1.1.0": version "1.1.5" - resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.5.tgz#1d85d17269fe97694b9c592552dd9e5e33552157" + resolved "https://registry.npmjs.org/@scure/base/-/base-1.1.5.tgz" integrity sha512-Brj9FiG2W1MRQSTB212YVPRrcbjkv48FoZi/u4l/zds/ieRrqsh7aUf6CLwkAq61oKXr/ZlTzlY66gLIj3TFTQ== -"@scure/base@~1.1.0": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938" - integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA== +"@scure/base@~1.1.6": + version "1.1.9" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.9.tgz#e5e142fbbfe251091f9c5f1dd4c834ac04c3dbd1" + integrity sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg== "@scure/bip32@1.1.5": version "1.1.5" - resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.1.5.tgz#d2ccae16dcc2e75bc1d75f5ef3c66a338d1ba300" + resolved "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.5.tgz" integrity sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw== dependencies: "@noble/hashes" "~1.2.0" "@noble/secp256k1" "~1.7.0" "@scure/base" "~1.1.0" +"@scure/bip32@1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.4.0.tgz#4e1f1e196abedcef395b33b9674a042524e20d67" + integrity sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg== + dependencies: + "@noble/curves" "~1.4.0" + "@noble/hashes" "~1.4.0" + "@scure/base" "~1.1.6" + "@scure/bip39@1.1.1": version "1.1.1" - resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.1.tgz#b54557b2e86214319405db819c4b6a370cf340c5" + resolved "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.1.tgz" integrity sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg== dependencies: "@noble/hashes" "~1.2.0" "@scure/base" "~1.1.0" +"@scure/bip39@1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.3.0.tgz#0f258c16823ddd00739461ac31398b4e7d6a18c3" + integrity sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ== + dependencies: + "@noble/hashes" "~1.4.0" + "@scure/base" "~1.1.6" + "@sentry/core@5.30.0": version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" + resolved "https://registry.npmjs.org/@sentry/core/-/core-5.30.0.tgz" integrity sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg== dependencies: "@sentry/hub" "5.30.0" @@ -1348,7 +1636,7 @@ "@sentry/hub@5.30.0": version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.30.0.tgz#2453be9b9cb903404366e198bd30c7ca74cdc100" + resolved "https://registry.npmjs.org/@sentry/hub/-/hub-5.30.0.tgz" integrity sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ== dependencies: "@sentry/types" "5.30.0" @@ -1357,7 +1645,7 @@ "@sentry/minimal@5.30.0": version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.30.0.tgz#ce3d3a6a273428e0084adcb800bc12e72d34637b" + resolved "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.30.0.tgz" integrity sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw== dependencies: "@sentry/hub" "5.30.0" @@ -1366,7 +1654,7 @@ "@sentry/node@^5.18.1": version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.30.0.tgz#4ca479e799b1021285d7fe12ac0858951c11cd48" + resolved "https://registry.npmjs.org/@sentry/node/-/node-5.30.0.tgz" integrity sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg== dependencies: "@sentry/core" "5.30.0" @@ -1381,7 +1669,7 @@ "@sentry/tracing@5.30.0": version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-5.30.0.tgz#501d21f00c3f3be7f7635d8710da70d9419d4e1f" + resolved "https://registry.npmjs.org/@sentry/tracing/-/tracing-5.30.0.tgz" integrity sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw== dependencies: "@sentry/hub" "5.30.0" @@ -1392,12 +1680,12 @@ "@sentry/types@5.30.0": version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.30.0.tgz#19709bbe12a1a0115bc790b8942917da5636f402" + resolved "https://registry.npmjs.org/@sentry/types/-/types-5.30.0.tgz" integrity sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw== "@sentry/utils@5.30.0": version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.30.0.tgz#9a5bd7ccff85ccfe7856d493bffa64cabc41e980" + resolved "https://registry.npmjs.org/@sentry/utils/-/utils-5.30.0.tgz" integrity sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww== dependencies: "@sentry/types" "5.30.0" @@ -1405,45 +1693,45 @@ "@sindresorhus/is@^0.14.0": version "0.14.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" + resolved "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz" integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== "@sindresorhus/is@^4.0.0", "@sindresorhus/is@^4.6.0": version "4.6.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" + resolved "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz" integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw== "@smithy/types@^2.1.0": version "2.2.0" - resolved "https://registry.yarnpkg.com/@smithy/types/-/types-2.2.0.tgz#52fa236967729f5a4e2c6c334f1a03930fa86f67" + resolved "https://registry.npmjs.org/@smithy/types/-/types-2.2.0.tgz" integrity sha512-Ahpt9KvD0mWeWiyaGo5EBE7KOByLl3jl4CD9Ps/r8qySgzVzo/4qsa+vvstOU3ZEriALmrPqUKIhqHt0Rn+m6g== dependencies: tslib "^2.5.0" "@solidity-parser/parser@^0.14.0": version "0.14.5" - resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.14.5.tgz#87bc3cc7b068e08195c219c91cd8ddff5ef1a804" + resolved "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.14.5.tgz" integrity sha512-6dKnHZn7fg/iQATVEzqyUOyEidbn05q7YA2mQ9hC0MMXhhV3/JrsxmFSYZAcr7j1yUP700LLhTruvJ3MiQmjJg== dependencies: antlr4ts "^0.5.0-alpha.4" "@solidity-parser/parser@^0.16.0": version "0.16.1" - resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.16.1.tgz#f7c8a686974e1536da0105466c4db6727311253c" + resolved "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.16.1.tgz" integrity sha512-PdhRFNhbTtu3x8Axm0uYpqOy/lODYQK+MlYSgqIsq2L8SFYEHJPHNUiOTAJbDGzNjjr1/n9AcIayxafR/fWmYw== dependencies: antlr4ts "^0.5.0-alpha.4" "@szmarczak/http-timer@^1.1.2": version "1.1.2" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" + resolved "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz" integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== dependencies: defer-to-connect "^1.0.1" "@szmarczak/http-timer@^4.0.5": version "4.0.6" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807" + resolved "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz" integrity sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w== dependencies: defer-to-connect "^2.0.0" @@ -1457,7 +1745,7 @@ "@textile/buckets-grpc@2.6.18": version "2.6.18" - resolved "https://registry.yarnpkg.com/@textile/buckets-grpc/-/buckets-grpc-2.6.18.tgz#d5c6a1e277a412734a15e38a33936bda4ef3d13d" + resolved "https://registry.npmjs.org/@textile/buckets-grpc/-/buckets-grpc-2.6.18.tgz" integrity sha512-oc1J5M9q+UPPWnf/RoMfaeITOjsgP1FzDg1iO+oZb8Mjol4VpChB+C/yePKISImjYupMgmFdlzf37chKBjZVQw== dependencies: "@improbable-eng/grpc-web" "^0.14.1" @@ -1466,7 +1754,7 @@ "@textile/buckets@^6.2.4": version "6.2.4" - resolved "https://registry.yarnpkg.com/@textile/buckets/-/buckets-6.2.4.tgz#7763186257f7f38d4b8d9e23b0ef026b39de679f" + resolved "https://registry.npmjs.org/@textile/buckets/-/buckets-6.2.4.tgz" integrity sha512-wyu2PMXUUs4YvDM/dEJiy8+CVM+3dTuqCVm1fBvwyYLTdjislegJjFxpHZMpZQMWK/aQfCdeZ4i3x/UJ8fCq5g== dependencies: "@improbable-eng/grpc-web" "^0.13.0" @@ -1490,7 +1778,7 @@ "@textile/context@^0.12.2": version "0.12.2" - resolved "https://registry.yarnpkg.com/@textile/context/-/context-0.12.2.tgz#30c4b85e68ba2c838e63fcb95706ad9d7f688dc5" + resolved "https://registry.npmjs.org/@textile/context/-/context-0.12.2.tgz" integrity sha512-io5rjca4rjCvy39LHTHUXEdPhrhxtDhov05eqi4xftqm/ID4DbLmIsDJJpJqgk8T8/n9mU4cHSFfKbn1dhxHQw== dependencies: "@improbable-eng/grpc-web" "^0.13.0" @@ -1498,7 +1786,7 @@ "@textile/crypto@^4.2.1": version "4.2.1" - resolved "https://registry.yarnpkg.com/@textile/crypto/-/crypto-4.2.1.tgz#96f03daab9e9a1b97967e490e2ca3f9b2fd66f89" + resolved "https://registry.npmjs.org/@textile/crypto/-/crypto-4.2.1.tgz" integrity sha512-7qxFLrXiSq5Tf3Wh3Oh6JKJMitF/6N3/AJyma6UAA8iQnAZBF98ShWz9tR59a3dvmGTc9MlyplOm16edbccscg== dependencies: "@types/ed2curve" "^0.2.2" @@ -1509,7 +1797,7 @@ "@textile/grpc-authentication@^3.4.5": version "3.4.5" - resolved "https://registry.yarnpkg.com/@textile/grpc-authentication/-/grpc-authentication-3.4.5.tgz#eee0624ff4d1d3582aadd55d2d1843055b3bad41" + resolved "https://registry.npmjs.org/@textile/grpc-authentication/-/grpc-authentication-3.4.5.tgz" integrity sha512-6K2SIJxhFUuNeq11pfRKPP70FXHuG6qBdx2jJgKqi0QPnKbyzQQrpS0cVGSPqHf66lq3dmqTTeefmlBGw9l6+w== dependencies: "@textile/context" "^0.12.2" @@ -1520,7 +1808,7 @@ "@textile/grpc-connection@^2.5.4": version "2.5.4" - resolved "https://registry.yarnpkg.com/@textile/grpc-connection/-/grpc-connection-2.5.4.tgz#796110e92b9b276ece3fa65365e92a913ad66b1b" + resolved "https://registry.npmjs.org/@textile/grpc-connection/-/grpc-connection-2.5.4.tgz" integrity sha512-EIIJkO1PA7nRBw3b4NSFp2JV+FcHvvk2uyRs50hE1GVcIZ1GrXS8iEqw3uuJH3le7RoKvh3hsURhNqUd+81vNg== dependencies: "@improbable-eng/grpc-web" "^0.12.0" @@ -1529,7 +1817,7 @@ "@textile/grpc-powergate-client@^2.6.2": version "2.6.2" - resolved "https://registry.yarnpkg.com/@textile/grpc-powergate-client/-/grpc-powergate-client-2.6.2.tgz#c267cc3e3dd1e68673c234d5465ff70bed843df6" + resolved "https://registry.npmjs.org/@textile/grpc-powergate-client/-/grpc-powergate-client-2.6.2.tgz" integrity sha512-ODe22lveqPiSkBsxnhLIRKQzZVwvyqDVx6WBPQJZI4yxrja5SDOq6/yH2Dtmqyfxg8BOobFvn+tid3wexRZjnQ== dependencies: "@improbable-eng/grpc-web" "^0.14.0" @@ -1538,7 +1826,7 @@ "@textile/grpc-transport@^0.5.2": version "0.5.2" - resolved "https://registry.yarnpkg.com/@textile/grpc-transport/-/grpc-transport-0.5.2.tgz#79b63e0618d25479fb06f6b9be256d6a80e9fac4" + resolved "https://registry.npmjs.org/@textile/grpc-transport/-/grpc-transport-0.5.2.tgz" integrity sha512-XEC+Ubs7/pibZU2AHDJLeCEAVNtgEWmEXBXYJubpp4SVviuGUyd4h+zvqLw4FiIBGtlxx1u//cmzANhL0Ew7Rw== dependencies: "@improbable-eng/grpc-web" "^0.13.0" @@ -1549,7 +1837,7 @@ "@textile/hub-filecoin@^2.2.4": version "2.2.4" - resolved "https://registry.yarnpkg.com/@textile/hub-filecoin/-/hub-filecoin-2.2.4.tgz#1b6044046ce6f11cac513dbd863d04d6891844d1" + resolved "https://registry.npmjs.org/@textile/hub-filecoin/-/hub-filecoin-2.2.4.tgz" integrity sha512-h3N6jcRkqJemAO5Bcl9c6gTFN9q2vNOdrc/256pTOM6BsPGMMVn8QU97rZ7YSP7XusyxiRu1+NLDzbPxmP2xdA== dependencies: "@improbable-eng/grpc-web" "^0.12.0" @@ -1565,7 +1853,7 @@ "@textile/hub-grpc@2.6.18": version "2.6.18" - resolved "https://registry.yarnpkg.com/@textile/hub-grpc/-/hub-grpc-2.6.18.tgz#5c15146682586b136949e454d2f567588f4169c6" + resolved "https://registry.npmjs.org/@textile/hub-grpc/-/hub-grpc-2.6.18.tgz" integrity sha512-Gne0CpqBywfOeTd3OW0OQUxnJfxK/K1NYQqwl8vMEPncp4uk68YnKNHsvWK2077Ar2VfGsWJayFtyBKbQ6cOcQ== dependencies: "@improbable-eng/grpc-web" "^0.14.1" @@ -1574,7 +1862,7 @@ "@textile/hub-threads-client@^5.5.4": version "5.5.4" - resolved "https://registry.yarnpkg.com/@textile/hub-threads-client/-/hub-threads-client-5.5.4.tgz#9424f404c0456a62b42d2ebca3b59d9d30f54849" + resolved "https://registry.npmjs.org/@textile/hub-threads-client/-/hub-threads-client-5.5.4.tgz" integrity sha512-dHgRd4Wsu1ywId2Q88FZWtkbG4iuZms6co0X7/Lld7eDL0YlrVmb8/lHEhhJqCmJq3vTUxVwviHM8kLrEHwvIw== dependencies: "@improbable-eng/grpc-web" "^0.13.0" @@ -1588,7 +1876,7 @@ "@textile/hub@^6.0.2": version "6.3.4" - resolved "https://registry.yarnpkg.com/@textile/hub/-/hub-6.3.4.tgz#3c1b7e56ba2e48f2c73358a3eeea0d63460f54f0" + resolved "https://registry.npmjs.org/@textile/hub/-/hub-6.3.4.tgz" integrity sha512-/F+rfE+zPg3cLwX7/KuHAZrm9Tt0S++wgc1jiipb7NViGeZhRz1p6JHcEy3+g+MDvyMTSITO6phKmtUMHKItKg== dependencies: "@textile/buckets" "^6.2.4" @@ -1605,7 +1893,7 @@ "@textile/multiaddr@^0.6.1": version "0.6.1" - resolved "https://registry.yarnpkg.com/@textile/multiaddr/-/multiaddr-0.6.1.tgz#c3dc666866d7616ab7a31bceb390ffad4f5932fb" + resolved "https://registry.npmjs.org/@textile/multiaddr/-/multiaddr-0.6.1.tgz" integrity sha512-OQK/kXYhtUA8yN41xltCxCiCO98Pkk8yMgUdhPDAhogvptvX4k9g6Rg0Yob18uBwN58AYUg075V//SWSK1kUCQ== dependencies: "@textile/threads-id" "^0.6.1" @@ -1614,7 +1902,7 @@ "@textile/security@^0.9.1": version "0.9.1" - resolved "https://registry.yarnpkg.com/@textile/security/-/security-0.9.1.tgz#fe40cad3b27caf097252236b843b4fa71e81ffaf" + resolved "https://registry.npmjs.org/@textile/security/-/security-0.9.1.tgz" integrity sha512-pmiSOUezV/udTMoQsvyEZwZFfN0tMo6dOAof4VBqyFdDZZV6doeI5zTDpqSJZTg69n0swfWxsHw96ZWQIoWvsw== dependencies: "@consento/sync-randombytes" "^1.0.5" @@ -1624,7 +1912,7 @@ "@textile/threads-client-grpc@^1.1.5": version "1.1.5" - resolved "https://registry.yarnpkg.com/@textile/threads-client-grpc/-/threads-client-grpc-1.1.5.tgz#566efb645d9d46d97a0dfcfdd5319113e6df8aac" + resolved "https://registry.npmjs.org/@textile/threads-client-grpc/-/threads-client-grpc-1.1.5.tgz" integrity sha512-gJw3Eso9hdwAB+LbCDAWnzp3/uS6ahs9a+gYmA+xBxeYL4PfTP/3X01G6dJz8oZ9/pHcw1cxodH16dXn4INT5g== dependencies: "@improbable-eng/grpc-web" "^0.14.1" @@ -1633,7 +1921,7 @@ "@textile/threads-client@^2.3.4": version "2.3.4" - resolved "https://registry.yarnpkg.com/@textile/threads-client/-/threads-client-2.3.4.tgz#094da8e929cbc9dd4b6afec9b34cbdaf6dbcf1f9" + resolved "https://registry.npmjs.org/@textile/threads-client/-/threads-client-2.3.4.tgz" integrity sha512-y89bpIuGDzkPqNpwGBu9Ky20g/IAEj0H62RDx7k4q66FsKJ2aSV+Jp7a4l0J+nxnqOpwUwennndlynmKzmTnnw== dependencies: "@improbable-eng/grpc-web" "^0.13.0" @@ -1650,7 +1938,7 @@ "@textile/threads-id@^0.6.1": version "0.6.1" - resolved "https://registry.yarnpkg.com/@textile/threads-id/-/threads-id-0.6.1.tgz#ac6b5c93c9bd669f6c8f75ab2044b47a0f09627c" + resolved "https://registry.npmjs.org/@textile/threads-id/-/threads-id-0.6.1.tgz" integrity sha512-KwhbLjZ/eEquPorGgHFotw4g0bkKLTsqQmnsIxFeo+6C1mz40PQu4IOvJwohHr5GL6wedjlobry4Jj+uI3N+0w== dependencies: "@consento/sync-randombytes" "^1.0.4" @@ -1659,7 +1947,7 @@ "@textile/users-grpc@2.6.18": version "2.6.18" - resolved "https://registry.yarnpkg.com/@textile/users-grpc/-/users-grpc-2.6.18.tgz#3fa14c749ab74a1ce1e23ea27ed1d7ace33717ea" + resolved "https://registry.npmjs.org/@textile/users-grpc/-/users-grpc-2.6.18.tgz" integrity sha512-n/0Vki1RzJZvJ66M6HwAaw/giygoenPH/gElGcZeqPePtnRWC4ZrhOcGo+Nx3LjjejTu8TjvjW9cwA0/0P8IQw== dependencies: "@improbable-eng/grpc-web" "^0.14.1" @@ -1668,7 +1956,7 @@ "@textile/users@^6.2.4": version "6.2.4" - resolved "https://registry.yarnpkg.com/@textile/users/-/users-6.2.4.tgz#52401645e85e350c3d1c6f792e01acb0b9f6edfd" + resolved "https://registry.npmjs.org/@textile/users/-/users-6.2.4.tgz" integrity sha512-NnCoRgVlQV14JatsSWe1k3ffPzLWSzkSwGJQjKwYJy8Cs1WRkwGDMddYJmg2B1P5rrZj/Zbu4krlEGVvFELncg== dependencies: "@improbable-eng/grpc-web" "^0.13.0" @@ -1688,7 +1976,7 @@ "@truffle/abi-utils@^0.2.14", "@truffle/abi-utils@^0.2.15": version "0.2.17" - resolved "https://registry.yarnpkg.com/@truffle/abi-utils/-/abi-utils-0.2.17.tgz#a234ff38a12e80a1342ea3d7193e9c3caaf5cc03" + resolved "https://registry.npmjs.org/@truffle/abi-utils/-/abi-utils-0.2.17.tgz" integrity sha512-Lz8bDjEYInaesdpP3ENVnDkfSkEmrV2z9BNcIEQPQnqdB5x/H+rIrWGny7LV6rX3Kz3kAerF8eGBFh7Z/dEhZw== dependencies: change-case "3.0.2" @@ -1706,23 +1994,39 @@ "@truffle/abi-utils@^1.0.2": version "1.0.2" - resolved "https://registry.yarnpkg.com/@truffle/abi-utils/-/abi-utils-1.0.2.tgz#41210b234912051433960382af009f339f8a9642" + resolved "https://registry.npmjs.org/@truffle/abi-utils/-/abi-utils-1.0.2.tgz" integrity sha512-MefEcxsBlprKIpfW7eh2I5zJqlWM18xk3duL7SW4VhIs6kNEec//hCpEDoE6P0m7GjqY3vk8X4vnf4aLlZkRcA== dependencies: change-case "3.0.2" fast-check "3.1.1" web3-utils "1.10.0" -"@truffle/code-utils@^3.0.0", "@truffle/code-utils@^3.0.3": +"@truffle/abi-utils@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@truffle/abi-utils/-/abi-utils-1.0.3.tgz#9f0df7a8aaf5e815bee47e0ad26bd4c91e4045f2" + integrity sha512-AWhs01HCShaVKjml7Z4AbVREr/u4oiWxCcoR7Cktm0mEvtT04pvnxW5xB/cI4znRkrbPdFQlFt67kgrAjesYkw== + dependencies: + change-case "3.0.2" + fast-check "3.1.1" + web3-utils "1.10.0" + +"@truffle/code-utils@^3.0.0", "@truffle/code-utils@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@truffle/code-utils/-/code-utils-3.0.4.tgz#5a3ab050847522f17ee318a86869f6d586a264bd" + integrity sha512-MWK3TMisIFaBpSjK7tt1GoQan7DQDBqT2iSsdQOGD74C7r9NMwsIdnL2EYoB/DPcEJ7B8yP4grlG2fQTrPF96g== + dependencies: + cbor "^5.2.0" + +"@truffle/code-utils@^3.0.3": version "3.0.3" - resolved "https://registry.yarnpkg.com/@truffle/code-utils/-/code-utils-3.0.3.tgz#17fa90a0b1a01298824a383e7008f1aa478fda58" + resolved "https://registry.npmjs.org/@truffle/code-utils/-/code-utils-3.0.3.tgz" integrity sha512-VMQMXvt/nXxWvHo5K1t697se1NU7VNh3zmiFw41qaSE1DjFZ2FMsZuW1ZoLhO4NKc14uB8k8pX3NN7XoF3uP4w== dependencies: cbor "^5.2.0" "@truffle/codec@^0.13.2": version "0.13.3" - resolved "https://registry.yarnpkg.com/@truffle/codec/-/codec-0.13.3.tgz#cec94f10f73d13cf856f7ca63d300220502f55c0" + resolved "https://registry.npmjs.org/@truffle/codec/-/codec-0.13.3.tgz" integrity sha512-RkbjTE2RuoShxalMqmOUEhxSTZcxeM4m8yLzMaQKvmEga+0b9Gpjn3wu9+3smnNRWC6T3q0AGsaBKt9FSiVGmg== dependencies: "@truffle/abi-utils" "^0.2.15" @@ -1738,7 +2042,7 @@ "@truffle/codec@^0.17.2": version "0.17.2" - resolved "https://registry.yarnpkg.com/@truffle/codec/-/codec-0.17.2.tgz#52a3604f73b89964373eec945f20d5cd0f4244d4" + resolved "https://registry.npmjs.org/@truffle/codec/-/codec-0.17.2.tgz" integrity sha512-n9HX8R5a5+/j6Y0+lqSzIyU1cUxTRYn/xEWp0Qc1b0Vtltad7wvVh+KLGvbm/KQEX3o1RK1xRIUN2E0QlDeQnA== dependencies: "@truffle/abi-utils" "^1.0.2" @@ -1752,9 +2056,25 @@ utf8 "^3.0.0" web3-utils "1.10.0" +"@truffle/codec@^0.17.3": + version "0.17.3" + resolved "https://registry.yarnpkg.com/@truffle/codec/-/codec-0.17.3.tgz#94057e56e1a947594b35eba498d96915df3861d2" + integrity sha512-Ko/+dsnntNyrJa57jUD9u4qx9nQby+H4GsUO6yjiCPSX0TQnEHK08XWqBSg0WdmCH2+h0y1nr2CXSx8gbZapxg== + dependencies: + "@truffle/abi-utils" "^1.0.3" + "@truffle/compile-common" "^0.9.8" + big.js "^6.0.3" + bn.js "^5.1.3" + cbor "^5.2.0" + debug "^4.3.1" + lodash "^4.17.21" + semver "^7.5.4" + utf8 "^3.0.0" + web3-utils "1.10.0" + "@truffle/compile-common@^0.7.32": version "0.7.34" - resolved "https://registry.yarnpkg.com/@truffle/compile-common/-/compile-common-0.7.34.tgz#c5b3e31cc716af91330f6a66f4dde1dbc491a58b" + resolved "https://registry.npmjs.org/@truffle/compile-common/-/compile-common-0.7.34.tgz" integrity sha512-NA8HuTCw6pgTpCyMd7M70Ii8AVD921R95UnXB3dwVWwEyV1OksaAsTKfdLxeLnFR4ISkK6o2NqpFb/lM3+V+9w== dependencies: "@truffle/error" "^0.1.1" @@ -1762,34 +2082,42 @@ "@truffle/compile-common@^0.9.7": version "0.9.7" - resolved "https://registry.yarnpkg.com/@truffle/compile-common/-/compile-common-0.9.7.tgz#e8ba6cd49c4d4e7ae4684ba453fb9b2dcd09b347" + resolved "https://registry.npmjs.org/@truffle/compile-common/-/compile-common-0.9.7.tgz" integrity sha512-TXuVLc5yJ/A0bSWw5OWIdXmcyaPpj3TJQ60ki7w9cIuW65Bazw7P4FRPaVNjR9YGe1FLYJ36GSdd9V3egPbzCg== dependencies: "@truffle/error" "^0.2.1" colors "1.4.0" -"@truffle/config@^1.3.38", "@truffle/config@^1.3.59": - version "1.3.59" - resolved "https://registry.yarnpkg.com/@truffle/config/-/config-1.3.59.tgz#d2fbd0befe2580644befb90e480937d52ec1ae84" - integrity sha512-mZbxmBRZs1Mn2Sx0cSi5mhug02FkBEEFaNFZ3FYr1HKWuiSCqlSQygeRTzezRjK+zqGUoon/2H+bpUXLxBavJg== +"@truffle/compile-common@^0.9.8": + version "0.9.8" + resolved "https://registry.yarnpkg.com/@truffle/compile-common/-/compile-common-0.9.8.tgz#f91507c895852289a17bf401eefebc293c4c69f0" + integrity sha512-DTpiyo32t/YhLI1spn84D3MHYHrnoVqO+Gp7ZHrYNwDs86mAxtNiH5lsVzSb8cPgiqlvNsRCU9nm9R0YmKMTBQ== dependencies: - "@truffle/error" "^0.2.1" - "@truffle/events" "^0.1.24" - "@truffle/provider" "^0.3.11" + "@truffle/error" "^0.2.2" + colors "1.4.0" + +"@truffle/config@^1.3.38", "@truffle/config@^1.3.61": + version "1.3.61" + resolved "https://registry.yarnpkg.com/@truffle/config/-/config-1.3.61.tgz#912d11eb03720b6b8cb79979aa56b85215075aec" + integrity sha512-L4uyG47V+k0NrSoVJ9D+hp2jcMstihW1QlNuXiu5g3mU24BjrozlJT34DFkczh/TtRceLjdrQJKA8WJCMICutw== + dependencies: + "@truffle/error" "^0.2.2" + "@truffle/events" "^0.1.25" + "@truffle/provider" "^0.3.13" conf "^10.1.2" debug "^4.3.1" find-up "^2.1.0" lodash "^4.17.21" original-require "^1.0.1" -"@truffle/dashboard-message-bus-client@^0.1.11": - version "0.1.11" - resolved "https://registry.yarnpkg.com/@truffle/dashboard-message-bus-client/-/dashboard-message-bus-client-0.1.11.tgz#62870fb5bf08f2887f3dc94ad3d3283314ce7ad4" - integrity sha512-ABoKtaogh5KjOw0UM5/6wYuhg4T5cMPVSSNF1rv4j3s2XGzExx3vUObvXqNO6I8gZ8xuvzClw4RmcEk8JkM8yA== +"@truffle/dashboard-message-bus-client@^0.1.12": + version "0.1.12" + resolved "https://registry.yarnpkg.com/@truffle/dashboard-message-bus-client/-/dashboard-message-bus-client-0.1.12.tgz#160bf0ae888efee8a45425232d296630f83fe6af" + integrity sha512-pI9G0La9tTstb2J2wxUZIMx6H+ZF0XBlsGN3HBkffr4edT0oT12WMCK9GxmKE22Q5VnpXl7wGjatRSEx0C9qDQ== dependencies: - "@truffle/dashboard-message-bus-common" "^0.1.6" - "@truffle/promise-tracker" "^0.1.6" - axios "1.2.4" + "@truffle/dashboard-message-bus-common" "^0.1.7" + "@truffle/promise-tracker" "^0.1.7" + axios "1.5.0" debug "^4.3.1" delay "^5.0.0" isomorphic-ws "^4.0.1" @@ -1797,24 +2125,24 @@ tiny-typed-emitter "^2.1.0" ws "^7.2.0" -"@truffle/dashboard-message-bus-common@^0.1.6": - version "0.1.6" - resolved "https://registry.yarnpkg.com/@truffle/dashboard-message-bus-common/-/dashboard-message-bus-common-0.1.6.tgz#53bd095d84b5913753cab7c6c78d3870b8ec2207" - integrity sha512-93HNXILKeKgmW1YaWPdsQ55MJ0MaLzOA8kRXPnM5jF2H3KRlRxOeEg77R4YWtGH+cVZP4VYGXdpvUap/lOAnvw== +"@truffle/dashboard-message-bus-common@^0.1.7": + version "0.1.7" + resolved "https://registry.yarnpkg.com/@truffle/dashboard-message-bus-common/-/dashboard-message-bus-common-0.1.7.tgz#dc7b76e18845788429929a97a416c1e6e37580dc" + integrity sha512-jN7q8LBmwQRldSzT/YJE33mnDLrp3EFFDuZyLwtQGInlfcRTXcr5yPY42jxr3Ln19dQe2Chx3I6dWtDByeKLIQ== "@truffle/db-loader@^0.1.10": version "0.1.33" - resolved "https://registry.yarnpkg.com/@truffle/db-loader/-/db-loader-0.1.33.tgz#46f8b2da6d61fffb470af48fb540fd433716ecc4" + resolved "https://registry.npmjs.org/@truffle/db-loader/-/db-loader-0.1.33.tgz" integrity sha512-OHt9Lu2xI+DVCC8WdEtNJrZFbGq9yFEBPjPJZVTDQI4SMd7I6tQmRmusXTKCSCDEHE0xAp02stmKjSHC+pxJpA== optionalDependencies: "@truffle/db" "^1.0.23" -"@truffle/db-loader@^0.2.33": - version "0.2.33" - resolved "https://registry.yarnpkg.com/@truffle/db-loader/-/db-loader-0.2.33.tgz#3600d750c9569cd2cf2cb10e78e518d92f06d77f" - integrity sha512-VAsT2YxzVmugzIWYpf+tlPRW7l68rC5hM99D/jldN4cnvn2Ki74diOI8svTZ9R2o5iY1Uk26swHceAm106+wdQ== +"@truffle/db-loader@^0.2.36": + version "0.2.36" + resolved "https://registry.yarnpkg.com/@truffle/db-loader/-/db-loader-0.2.36.tgz#7f9f06191d7e8945949e5408c2bed7aaefc8daec" + integrity sha512-Cm8uVc2eoihquMOSZm8UOuGGUvBo+/GHkxRoPAZ5pftOpSlRAug0okVOp6ETj1BujgLJ02izU/qdrwSGWwGR9A== optionalDependencies: - "@truffle/db" "^2.0.33" + "@truffle/db" "^2.0.36" "@truffle/db@^1.0.0", "@truffle/db@^1.0.23": version "1.0.23" @@ -1842,16 +2170,16 @@ pouchdb-find "^7.0.0" web3-utils "1.7.4" -"@truffle/db@^2.0.33": - version "2.0.33" - resolved "https://registry.yarnpkg.com/@truffle/db/-/db-2.0.33.tgz#ce6d22ebf716b832130afe19786c2a28d296eca6" - integrity sha512-6AQfZLeKo72zvBisTIAnuG3Ho28cji2OkWLK6HFVHiGT/+7+AbB45IHVBeRqhqlIk57IFaDuSsxtyY4FeEZBSg== +"@truffle/db@^2.0.36": + version "2.0.36" + resolved "https://registry.yarnpkg.com/@truffle/db/-/db-2.0.36.tgz#f502f8307a70ad17acaded48d69bcb680c3848b3" + integrity sha512-PpUjOXZgf9Gy8RlP8bJhl5pjJRkghZUcCiGOsS0YbCCI//PGDDoKmS+3QUjXWhiMwTeld3gfUV2ip4p2hMbyVA== dependencies: "@graphql-tools/delegate" "^8.4.3" "@graphql-tools/schema" "^8.3.1" - "@truffle/abi-utils" "^1.0.2" - "@truffle/code-utils" "^3.0.3" - "@truffle/config" "^1.3.59" + "@truffle/abi-utils" "^1.0.3" + "@truffle/code-utils" "^3.0.4" + "@truffle/config" "^1.3.61" abstract-leveldown "^7.2.0" apollo-server "^3.11.0" debug "^4.3.1" @@ -1869,7 +2197,7 @@ "@truffle/debugger@^10.0.4": version "10.0.17" - resolved "https://registry.yarnpkg.com/@truffle/debugger/-/debugger-10.0.17.tgz#4b7c4773635be8d0a99a2e2184989883f0ac6030" + resolved "https://registry.npmjs.org/@truffle/debugger/-/debugger-10.0.17.tgz" integrity sha512-z119CdSa2pjfchxU7KUeR8yxuTSfayeo6MGrMo9pCTsoIb2/SjPgIz3kiObLgumi36Pi+gfjXaHmvnCtaYwBNA== dependencies: "@truffle/abi-utils" "^0.2.14" @@ -1887,15 +2215,15 @@ web3 "1.7.4" web3-eth-abi "1.7.4" -"@truffle/debugger@^12.1.2": - version "12.1.2" - resolved "https://registry.yarnpkg.com/@truffle/debugger/-/debugger-12.1.2.tgz#a53f11b796a0a9b02f9c66824fc505b943fdf9a1" - integrity sha512-h+CcxTZWxjcsldT6+GdGYE2R122EQ4wh4Q41nZ66SwbpM7qPN4VparGqoU18k1jJx5piYm+aJ7FPOdaaEVYPLQ== +"@truffle/debugger@^12.1.5": + version "12.1.5" + resolved "https://registry.yarnpkg.com/@truffle/debugger/-/debugger-12.1.5.tgz#39be29471f8e0ed31e9a3f5434266058bde74708" + integrity sha512-m6FQoddmptcXZkO+OABcz4Ka7YDLAPW9/GhnTSqYonlaOeV7g5dMzybhHq6whaQet34rhNteomep7JpskKW9Mw== dependencies: "@ensdomains/ensjs" "^2.1.0" - "@truffle/abi-utils" "^1.0.2" - "@truffle/codec" "^0.17.2" - "@truffle/source-map-utils" "^1.3.118" + "@truffle/abi-utils" "^1.0.3" + "@truffle/codec" "^0.17.3" + "@truffle/source-map-utils" "^1.3.119" bn.js "^5.1.3" debug "^4.3.1" json-pointer "^0.6.1" @@ -1904,34 +2232,39 @@ redux "^3.7.2" redux-saga "1.0.0" reselect-tree "^1.3.7" - semver "7.5.2" + semver "^7.5.4" web3 "1.10.0" web3-eth-abi "1.10.0" "@truffle/error@^0.1.1": version "0.1.1" - resolved "https://registry.yarnpkg.com/@truffle/error/-/error-0.1.1.tgz#e52026ac8ca7180d83443dca73c03e07ace2a301" + resolved "https://registry.npmjs.org/@truffle/error/-/error-0.1.1.tgz" integrity sha512-sE7c9IHIGdbK4YayH4BC8i8qMjoAOeg6nUXUDZZp8wlU21/EMpaG+CLx+KqcIPyR+GSWIW3Dm0PXkr2nlggFDA== "@truffle/error@^0.2.1": version "0.2.1" - resolved "https://registry.yarnpkg.com/@truffle/error/-/error-0.2.1.tgz#71bb8e777a832e0cfe09a8638a70a5177aad8628" + resolved "https://registry.npmjs.org/@truffle/error/-/error-0.2.1.tgz" integrity sha512-5Qy+z9dg9hP37WNdLnXH4b9MzemWrjTufRq7/DTKqimjyxCP/1zlL8gQEMdiSx1BBtAZz0xypkID/jb7AF/Osg== -"@truffle/events@^0.1.24": - version "0.1.24" - resolved "https://registry.yarnpkg.com/@truffle/events/-/events-0.1.24.tgz#e7f5b4e6b7f76058cdc25bd935ceb3e8b6182aaa" - integrity sha512-rS+jKDjmdM0g+14H/H8MzhohaTKsSS6plNNzO95MIcUs0Ytinu1DXfSkUovDpgv5h2NcRoU0BMTKCR21Y3JiNw== +"@truffle/error@^0.2.2": + version "0.2.2" + resolved "https://registry.yarnpkg.com/@truffle/error/-/error-0.2.2.tgz#1b4c4237c14dda792f20bd4f19ff4e4585b47796" + integrity sha512-TqbzJ0O8DHh34cu8gDujnYl4dUl6o2DE4PR6iokbybvnIm/L2xl6+Gv1VC+YJS45xfH83Yo3/Zyg/9Oq8/xZWg== + +"@truffle/events@^0.1.25": + version "0.1.25" + resolved "https://registry.yarnpkg.com/@truffle/events/-/events-0.1.25.tgz#52d4ae968273c267edfcb5c8e2d3b90c7f1f6b89" + integrity sha512-5elJxNXPVuXDMOoIcCVox0sz95ovRhRbte/H9ht18vyOvtualb4bTjwYyRoWw6Y7j0pom0tPI3OLZWqCdKQNdA== dependencies: - "@truffle/dashboard-message-bus-client" "^0.1.11" - "@truffle/spinners" "^0.2.4" + "@truffle/dashboard-message-bus-client" "^0.1.12" + "@truffle/spinners" "^0.2.5" debug "^4.3.1" emittery "^0.4.1" web3-utils "1.10.0" "@truffle/hdwallet-provider@^1.6.0": version "1.7.0" - resolved "https://registry.yarnpkg.com/@truffle/hdwallet-provider/-/hdwallet-provider-1.7.0.tgz#5cfa8bc67c2a30b3943d3dab78f74c6a191cde02" + resolved "https://registry.npmjs.org/@truffle/hdwallet-provider/-/hdwallet-provider-1.7.0.tgz" integrity sha512-nT7BPJJ2jPCLJc5uZdVtRnRMny5he5d3kO9Hi80ZSqe5xlnK905grBptM/+CwOfbeqHKQirI1btwm6r3wIBM8A== dependencies: "@ethereumjs/common" "^2.4.0" @@ -1943,10 +2276,10 @@ ethereumjs-util "^6.1.0" ethereumjs-wallet "^1.0.1" -"@truffle/interface-adapter@^0.5.35": - version "0.5.35" - resolved "https://registry.yarnpkg.com/@truffle/interface-adapter/-/interface-adapter-0.5.35.tgz#f0eb1c4a2803190ca249143f545029a8b641fe96" - integrity sha512-B5gtJnvsum5j2do393n0UfCT8MklrlAZxuqvEFBeMM9UKnreYct0/D368FVMlZwWo1N50HgGeZ0hlpSJqR/nvg== +"@truffle/interface-adapter@^0.5.37": + version "0.5.37" + resolved "https://registry.yarnpkg.com/@truffle/interface-adapter/-/interface-adapter-0.5.37.tgz#95d249c1912d2baaa63c54e8a138d3f476a1181a" + integrity sha512-lPH9MDgU+7sNDlJSClwyOwPCfuOimqsCx0HfGkznL3mcFRymc1pukAR1k17zn7ErHqBwJjiKAZ6Ri72KkS+IWw== dependencies: bn.js "^5.1.3" ethers "^4.0.32" @@ -1954,14 +2287,14 @@ "@truffle/preserve-fs@^0.2.7": version "0.2.8" - resolved "https://registry.yarnpkg.com/@truffle/preserve-fs/-/preserve-fs-0.2.8.tgz#1dab46b1431f7dcf9dbff73a8736f9799627ce58" + resolved "https://registry.npmjs.org/@truffle/preserve-fs/-/preserve-fs-0.2.8.tgz" integrity sha512-AYuhWHqE3KRB90h9gR3tHVBRMA7dqghI9boZiW7S8czwSwq7sC5koITJyJEU+nWVo0dMucjYdyXElHOXZhD3ew== dependencies: "@truffle/preserve" "^0.2.8" "@truffle/preserve-to-buckets@^0.2.8": version "0.2.9" - resolved "https://registry.yarnpkg.com/@truffle/preserve-to-buckets/-/preserve-to-buckets-0.2.9.tgz#032a813b5722f7af9db3a42f302ad83d256463f7" + resolved "https://registry.npmjs.org/@truffle/preserve-to-buckets/-/preserve-to-buckets-0.2.9.tgz" integrity sha512-j9kibjpUrNtN+n2qHhV76PtTCGgmlUnvYKtx+WcRFz3OoiLg3Q88OpK4pS7TkBwYhsa62R4SqeLX+2vtsD5FJw== dependencies: "@textile/hub" "^6.0.2" @@ -1974,7 +2307,7 @@ "@truffle/preserve-to-filecoin@^0.2.8": version "0.2.10" - resolved "https://registry.yarnpkg.com/@truffle/preserve-to-filecoin/-/preserve-to-filecoin-0.2.10.tgz#429975a87d3fe11a16afcedb7bdf8bdc6e05f84c" + resolved "https://registry.npmjs.org/@truffle/preserve-to-filecoin/-/preserve-to-filecoin-0.2.10.tgz" integrity sha512-8sw9i07USderPIlM/Q5Kd0OsNx0GiprzM82MOoDK9T3IZWHXxWFjyknA4Y42dagiMWuINsUFOvdTuhN9fC8djA== dependencies: "@truffle/preserve" "^0.2.8" @@ -1984,7 +2317,7 @@ "@truffle/preserve-to-ipfs@^0.2.8": version "0.2.9" - resolved "https://registry.yarnpkg.com/@truffle/preserve-to-ipfs/-/preserve-to-ipfs-0.2.9.tgz#f71d21247183230b52ee731edd147222c3f819e6" + resolved "https://registry.npmjs.org/@truffle/preserve-to-ipfs/-/preserve-to-ipfs-0.2.9.tgz" integrity sha512-5zOA6A/pWNXLpeAE5o7x8SRqem1cpur+Ct1+jkgJYiIa0ZmkOz8lKVzRG5NAiJFG7QLEUu+ERmDkDTEd4+0oxA== dependencies: "@truffle/preserve" "^0.2.8" @@ -1993,31 +2326,43 @@ "@truffle/preserve@^0.2.8": version "0.2.16" - resolved "https://registry.yarnpkg.com/@truffle/preserve/-/preserve-0.2.16.tgz#63a9513b0880d12f7db67e0558841529da7a883e" + resolved "https://registry.npmjs.org/@truffle/preserve/-/preserve-0.2.16.tgz" integrity sha512-zAiZ+izyfBjc/rkFOfHOisuDhKZhESJDE07sI5jCRZoY0AdAkJq6ikXecDi1VRsnUivtPgcoN3It9gdO89D8Jg== dependencies: "@truffle/error" "^0.2.1" "@truffle/spinners" "^0.2.4" chalk "^2.4.2" -"@truffle/promise-tracker@^0.1.6": - version "0.1.6" - resolved "https://registry.yarnpkg.com/@truffle/promise-tracker/-/promise-tracker-0.1.6.tgz#daecee974e8271387031f32765a414f76e727a79" - integrity sha512-oUZ4Mc6Yt/qTvFZ/yD4nnUIN8pXhrBN0h4/SZ4e8W1TcHNvQkV6gUkkYkn8fZRvFwTMYjvWot+eAHHNRsSl/eA== +"@truffle/promise-tracker@^0.1.7": + version "0.1.7" + resolved "https://registry.yarnpkg.com/@truffle/promise-tracker/-/promise-tracker-0.1.7.tgz#edc5e5940656439db7b1956bd4838d12dd4b9ecf" + integrity sha512-NiPXNJvdei8MRZRUjEZoL0Y7TPDR1TaeCfGUgB3md6Q7TBiqSKo2p5OT36JO106B2j57SLmXOiDn8fLb+u2sjA== -"@truffle/provider@^0.3.11": - version "0.3.11" - resolved "https://registry.yarnpkg.com/@truffle/provider/-/provider-0.3.11.tgz#ece46441d43db71449e1407d7b00535603213af4" - integrity sha512-8W7w2rcDLS/CAomTEZXzmHDgh5wQvnD0ZmTQ8Q5DktaD0z+83W8XmrSPLY3gJT7deb43ySJxEoCIj+e6+nySAw== +"@truffle/provider@^0.3.13": + version "0.3.13" + resolved "https://registry.yarnpkg.com/@truffle/provider/-/provider-0.3.13.tgz#795b6172c5db20f30a026f2f733b9a3417847a9f" + integrity sha512-W9yZO0ZUwA0LhFvf7+NNNXVSCOd4x5pTbFiXUVURjyqp7f4YooLAqnlLPSpV+6qwIwThc+86CeLlOiFslYdDIA== dependencies: - "@truffle/error" "^0.2.1" - "@truffle/interface-adapter" "^0.5.35" + "@truffle/error" "^0.2.2" + "@truffle/interface-adapter" "^0.5.37" debug "^4.3.1" web3 "1.10.0" -"@truffle/source-map-utils@^1.3.118", "@truffle/source-map-utils@^1.3.88": +"@truffle/source-map-utils@^1.3.119": + version "1.3.119" + resolved "https://registry.yarnpkg.com/@truffle/source-map-utils/-/source-map-utils-1.3.119.tgz#d02b5859183d61a605fa8aafa2ad56b39f145f9a" + integrity sha512-TFYi3XvanY8WZBOfBwDHQe9HfZUXJ2ejnmFNjsq1//sbM4fUNWjeNshGqkWGxfKPh3OAzXgD4iTnPG3YeXM8YQ== + dependencies: + "@truffle/code-utils" "^3.0.4" + "@truffle/codec" "^0.17.3" + debug "^4.3.1" + json-pointer "^0.6.1" + node-interval-tree "^1.3.3" + web3-utils "1.10.0" + +"@truffle/source-map-utils@^1.3.88": version "1.3.118" - resolved "https://registry.yarnpkg.com/@truffle/source-map-utils/-/source-map-utils-1.3.118.tgz#5f477ed44e190d29e476cf8dc64c6cb1e46b3a69" + resolved "https://registry.npmjs.org/@truffle/source-map-utils/-/source-map-utils-1.3.118.tgz" integrity sha512-SGOW6moch7MqsjSoUf7e/y6xuCZi5M6kEtSG1aaZQJrxrj/ZuooYpShXxISyiOAB89QZ5txCRVsN2EnNYgjjkA== dependencies: "@truffle/code-utils" "^3.0.3" @@ -2029,21 +2374,28 @@ "@truffle/spinners@^0.2.4": version "0.2.4" - resolved "https://registry.yarnpkg.com/@truffle/spinners/-/spinners-0.2.4.tgz#23a226e0b4e2ecb5e574a0de85ea9eb058149bec" + resolved "https://registry.npmjs.org/@truffle/spinners/-/spinners-0.2.4.tgz" integrity sha512-8GsIX9GzO6wBDGoNF4yAmQEe95TiIuAJq9p+2szCKGArYbAD3kbn+mG3TMS3Gr/zAS5p7fTJxnCm60E2HghsUQ== dependencies: "@trufflesuite/spinnies" "^0.1.1" +"@truffle/spinners@^0.2.5": + version "0.2.5" + resolved "https://registry.yarnpkg.com/@truffle/spinners/-/spinners-0.2.5.tgz#fe3bb3451768f5353085551b8fe6285d354705ef" + integrity sha512-emYyLEuoY62MQV/RNjyVIuTPEjMyIA0WiYMG2N3yfh8OSjD/TC0HRc2oyDWtVkNNox/5D2tH2m5fFB8HOt80FQ== + dependencies: + "@trufflesuite/spinnies" "^0.1.1" + "@trufflesuite/bigint-buffer@1.1.10": version "1.1.10" - resolved "https://registry.yarnpkg.com/@trufflesuite/bigint-buffer/-/bigint-buffer-1.1.10.tgz#a1d9ca22d3cad1a138b78baaf15543637a3e1692" + resolved "https://registry.npmjs.org/@trufflesuite/bigint-buffer/-/bigint-buffer-1.1.10.tgz" integrity sha512-pYIQC5EcMmID74t26GCC67946mgTJFiLXOT/BYozgrd4UEY2JHEGLhWi9cMiQCt5BSqFEvKkCHNnoj82SRjiEw== dependencies: node-gyp-build "4.4.0" "@trufflesuite/eth-json-rpc-filters@^4.1.2-1": version "4.1.2-1" - resolved "https://registry.yarnpkg.com/@trufflesuite/eth-json-rpc-filters/-/eth-json-rpc-filters-4.1.2-1.tgz#61ab78c52e98a883e5cf086925b34a30297b1824" + resolved "https://registry.npmjs.org/@trufflesuite/eth-json-rpc-filters/-/eth-json-rpc-filters-4.1.2-1.tgz" integrity sha512-/MChvC5dw2ck9NU1cZmdovCz2VKbOeIyR4tcxDvA5sT+NaL0rA2/R5U0yI7zsbo1zD+pgqav77rQHTzpUdDNJQ== dependencies: "@trufflesuite/eth-json-rpc-middleware" "^4.4.2-0" @@ -2055,7 +2407,7 @@ "@trufflesuite/eth-json-rpc-infura@^4.0.3-0": version "4.0.3-0" - resolved "https://registry.yarnpkg.com/@trufflesuite/eth-json-rpc-infura/-/eth-json-rpc-infura-4.0.3-0.tgz#6d22122937cf60ec9d21a02351c101fdc608c4fe" + resolved "https://registry.npmjs.org/@trufflesuite/eth-json-rpc-infura/-/eth-json-rpc-infura-4.0.3-0.tgz" integrity sha512-xaUanOmo0YLqRsL0SfXpFienhdw5bpQ1WEXxMTRi57az4lwpZBv4tFUDvcerdwJrxX9wQqNmgUgd1BrR01dumw== dependencies: "@trufflesuite/eth-json-rpc-middleware" "^4.4.2-1" @@ -2065,7 +2417,7 @@ "@trufflesuite/eth-json-rpc-middleware@^4.4.2-0", "@trufflesuite/eth-json-rpc-middleware@^4.4.2-1": version "4.4.2-1" - resolved "https://registry.yarnpkg.com/@trufflesuite/eth-json-rpc-middleware/-/eth-json-rpc-middleware-4.4.2-1.tgz#8c3638ed8a7ed89a1e5e71407de068a65bef0df2" + resolved "https://registry.npmjs.org/@trufflesuite/eth-json-rpc-middleware/-/eth-json-rpc-middleware-4.4.2-1.tgz" integrity sha512-iEy9H8ja7/8aYES5HfrepGBKU9n/Y4OabBJEklVd/zIBlhCCBAWBqkIZgXt11nBXO/rYAeKwYuE3puH3ByYnLA== dependencies: "@trufflesuite/eth-sig-util" "^1.4.2" @@ -2085,7 +2437,7 @@ "@trufflesuite/eth-sig-util@^1.4.2": version "1.4.2" - resolved "https://registry.yarnpkg.com/@trufflesuite/eth-sig-util/-/eth-sig-util-1.4.2.tgz#b529e2f38ac08e652116f48981132a26242a4f08" + resolved "https://registry.npmjs.org/@trufflesuite/eth-sig-util/-/eth-sig-util-1.4.2.tgz" integrity sha512-+GyfN6b0LNW77hbQlH3ufZ/1eCON7mMrGym6tdYf7xiNw9Vv3jBO72bmmos1EId2NgBvPMhmYYm6DSLQFTmzrA== dependencies: ethereumjs-abi "^0.6.8" @@ -2093,7 +2445,7 @@ "@trufflesuite/filecoin.js@^0.0.4": version "0.0.4" - resolved "https://registry.yarnpkg.com/@trufflesuite/filecoin.js/-/filecoin.js-0.0.4.tgz#acf3a29379e456ff0c0f4f0c90b4336b99647248" + resolved "https://registry.npmjs.org/@trufflesuite/filecoin.js/-/filecoin.js-0.0.4.tgz" integrity sha512-LYk6Pc2uujLrPgtXSqL6kh/dZsfw8Q4/h5EHfGczj9BuxLyDezAmPFs1lMq4DdA18OgYVXDbqSOCwDww7oGHsw== dependencies: "@ledgerhq/hw-transport-webusb" "^5.22.0" @@ -2116,7 +2468,7 @@ "@trufflesuite/spinnies@^0.1.1": version "0.1.1" - resolved "https://registry.yarnpkg.com/@trufflesuite/spinnies/-/spinnies-0.1.1.tgz#719230993f55ab39f936ed8778979e7661af188d" + resolved "https://registry.npmjs.org/@trufflesuite/spinnies/-/spinnies-0.1.1.tgz" integrity sha512-jltEtmFJj6xmQqr85gP8OqBHCEiId+zw+uAsb3DyLLRD17O6sySW6Afa2Z/jpzSafj+32ssDfLJ+c0of1NLqcA== dependencies: chalk "^4.1.2" @@ -2125,7 +2477,7 @@ "@trufflesuite/uws-js-unofficial@20.10.0-unofficial.2": version "20.10.0-unofficial.2" - resolved "https://registry.yarnpkg.com/@trufflesuite/uws-js-unofficial/-/uws-js-unofficial-20.10.0-unofficial.2.tgz#7ed613ce3260cd5d1773a4d5787a2a106acd1a91" + resolved "https://registry.npmjs.org/@trufflesuite/uws-js-unofficial/-/uws-js-unofficial-20.10.0-unofficial.2.tgz" integrity sha512-oQQlnS3oNeGsgS4K3KCSSavJgSb0W9D5ktZs4FacX9VbM7b+NlhjH96d6/G4fMrz+bc5MXRyco419on0X0dvRA== dependencies: ws "8.2.3" @@ -2133,9 +2485,19 @@ bufferutil "4.0.5" utf-8-validate "5.0.7" +"@trufflesuite/uws-js-unofficial@20.30.0-unofficial.0": + version "20.30.0-unofficial.0" + resolved "https://registry.yarnpkg.com/@trufflesuite/uws-js-unofficial/-/uws-js-unofficial-20.30.0-unofficial.0.tgz#2fbc2f8ef7e82fbeea6abaf7e8a9d42a02b479d3" + integrity sha512-r5X0aOQcuT6pLwTRLD+mPnAM/nlKtvIK4Z+My++A8tTOR0qTjNRx8UB8jzRj3D+p9PMAp5LnpCUUGmz7/TppwA== + dependencies: + ws "8.13.0" + optionalDependencies: + bufferutil "4.0.7" + utf-8-validate "6.0.3" + "@trufflesuite/web3-provider-engine@15.0.14": version "15.0.14" - resolved "https://registry.yarnpkg.com/@trufflesuite/web3-provider-engine/-/web3-provider-engine-15.0.14.tgz#8f9696f434585cc0ab2e57c312090c1f138bc471" + resolved "https://registry.npmjs.org/@trufflesuite/web3-provider-engine/-/web3-provider-engine-15.0.14.tgz" integrity sha512-6/LoWvNMxYf0oaYzJldK2a9AdnkAdIeJhHW4nuUBAeO29eK9xezEaEYQ0ph1QRTaICxGxvn+1Azp4u8bQ8NEZw== dependencies: "@ethereumjs/tx" "^3.3.0" @@ -2163,27 +2525,27 @@ "@tsconfig/node10@^1.0.7": version "1.0.9" - resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" + resolved "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz" integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== "@tsconfig/node12@^1.0.7": version "1.0.11" - resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + resolved "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz" integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== "@tsconfig/node14@^1.0.0": version "1.0.3" - resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + resolved "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz" integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== "@tsconfig/node16@^1.0.2": version "1.0.4" - resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz" integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== "@typechain/ethers-v6@^0.4.3": version "0.4.3" - resolved "https://registry.yarnpkg.com/@typechain/ethers-v6/-/ethers-v6-0.4.3.tgz#badd99f88d5a1f1a2f42590f298e20cc62618e59" + resolved "https://registry.npmjs.org/@typechain/ethers-v6/-/ethers-v6-0.4.3.tgz" integrity sha512-TrxBsyb4ryhaY9keP6RzhFCviWYApcLCIRMPyWaKp2cZZrfaM3QBoxXTnw/eO4+DAY3l+8O0brNW0WgeQeOiDA== dependencies: lodash "^4.17.15" @@ -2191,33 +2553,48 @@ "@typechain/hardhat@^8.0.3": version "8.0.3" - resolved "https://registry.yarnpkg.com/@typechain/hardhat/-/hardhat-8.0.3.tgz#a114825f130405bbb8e535314003733b7ce3f91c" + resolved "https://registry.npmjs.org/@typechain/hardhat/-/hardhat-8.0.3.tgz" integrity sha512-MytSmJJn+gs7Mqrpt/gWkTCOpOQ6ZDfRrRT2gtZL0rfGe4QrU4x9ZdW15fFbVM/XTa+5EsKiOMYXhRABibNeng== dependencies: fs-extra "^9.1.0" "@types/accepts@^1.3.5": - version "1.3.5" - resolved "https://registry.yarnpkg.com/@types/accepts/-/accepts-1.3.5.tgz#c34bec115cfc746e04fe5a059df4ce7e7b391575" - integrity sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ== + version "1.3.7" + resolved "https://registry.yarnpkg.com/@types/accepts/-/accepts-1.3.7.tgz#3b98b1889d2b2386604c2bbbe62e4fb51e95b265" + integrity sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ== dependencies: "@types/node" "*" "@types/bn.js@^4.11.3": version "4.11.6" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" + resolved "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz" integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== dependencies: "@types/node" "*" -"@types/bn.js@^5.1.0", "@types/bn.js@^5.1.1": +"@types/bn.js@^5.1.0": version "5.1.1" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682" + resolved "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.1.tgz" integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g== dependencies: "@types/node" "*" -"@types/body-parser@*", "@types/body-parser@1.19.2": +"@types/bn.js@^5.1.1": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.2.0.tgz#4349b9710e98f9ab3cdc50f1c5e4dcbd8ef29c80" + integrity sha512-DLbJ1BPqxvQhIGbeu8VbUC1DiAiahHtAYvA0ZEAa4P31F7IaArc8z3C3BRQdWX4mtLQuABG4yzp76ZrS02Ui1Q== + dependencies: + "@types/node" "*" + +"@types/body-parser@*": + version "1.19.6" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.6.tgz#1859bebb8fd7dac9918a45d54c1971ab8b5af474" + integrity sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g== + dependencies: + "@types/connect" "*" + "@types/node" "*" + +"@types/body-parser@1.19.2": version "1.19.2" resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== @@ -2227,7 +2604,7 @@ "@types/cacheable-request@^6.0.1", "@types/cacheable-request@^6.0.2": version "6.0.3" - resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.3.tgz#a430b3260466ca7b5ca5bfd735693b36e7a9d183" + resolved "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz" integrity sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw== dependencies: "@types/http-cache-semantics" "*" @@ -2237,27 +2614,27 @@ "@types/chai-as-promised@^7.1.3": version "7.1.5" - resolved "https://registry.yarnpkg.com/@types/chai-as-promised/-/chai-as-promised-7.1.5.tgz#6e016811f6c7a64f2eed823191c3a6955094e255" + resolved "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.5.tgz" integrity sha512-jStwss93SITGBwt/niYrkf2C+/1KTeZCZl1LaeezTlqppAKeoQC7jxyqYuP72sxBGKCIbw7oHgbYssIRzT5FCQ== dependencies: "@types/chai" "*" "@types/chai@*", "@types/chai@^4.3.5": version "4.3.5" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.5.tgz#ae69bcbb1bebb68c4ac0b11e9d8ed04526b3562b" + resolved "https://registry.npmjs.org/@types/chai/-/chai-4.3.5.tgz" integrity sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng== "@types/concat-stream@^1.6.0": version "1.6.1" - resolved "https://registry.yarnpkg.com/@types/concat-stream/-/concat-stream-1.6.1.tgz#24bcfc101ecf68e886aaedce60dfd74b632a1b74" + resolved "https://registry.npmjs.org/@types/concat-stream/-/concat-stream-1.6.1.tgz" integrity sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA== dependencies: "@types/node" "*" "@types/connect@*": - version "3.4.35" - resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" - integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== + version "3.4.38" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858" + integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug== dependencies: "@types/node" "*" @@ -2268,14 +2645,14 @@ "@types/debug@^4.1.9": version "4.1.12" - resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.12.tgz#a155f21690871953410df4b6b6f53187f0500917" + resolved "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz" integrity sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ== dependencies: "@types/ms" "*" "@types/ed2curve@^0.2.2": version "0.2.2" - resolved "https://registry.yarnpkg.com/@types/ed2curve/-/ed2curve-0.2.2.tgz#8f8bc7e2c9a5895a941c63a4f7acd7a6a62a5b15" + resolved "https://registry.npmjs.org/@types/ed2curve/-/ed2curve-0.2.2.tgz" integrity sha512-G1sTX5xo91ydevQPINbL2nfgVAj/s1ZiqZxC8OCWduwu+edoNGUm5JXtTkg9F3LsBZbRI46/0HES4CPUE2wc9g== dependencies: tweetnacl "^1.0.0" @@ -2290,9 +2667,9 @@ "@types/range-parser" "*" "@types/express-serve-static-core@^4.17.18": - version "4.17.35" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz#c95dd4424f0d32e525d23812aa8ab8e4d3906c4f" - integrity sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg== + version "4.19.7" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.19.7.tgz#f1d306dcc03b1aafbfb6b4fe684cce8a31cffc10" + integrity sha512-FvPtiIf1LfhzsaIXhv/PHan/2FeQBbtBDtfX2QfvPxdUelMDEckK08SM6nqo1MIZY3RUlfA+HV8+hFUSio78qg== dependencies: "@types/node" "*" "@types/qs" "*" @@ -2311,14 +2688,14 @@ "@types/form-data@0.0.33": version "0.0.33" - resolved "https://registry.yarnpkg.com/@types/form-data/-/form-data-0.0.33.tgz#c9ac85b2a5fd18435b8c85d9ecb50e6d6c893ff8" + resolved "https://registry.npmjs.org/@types/form-data/-/form-data-0.0.33.tgz" integrity sha512-8BSvG1kGm83cyJITQMZSulnl6QV8jqAGreJsc5tPu1Jq0vTSOiY/k24Wx82JRpWwZSqrala6sd5rWi6aNXvqcw== dependencies: "@types/node" "*" "@types/glob@^7.1.1": version "7.2.0" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb" + resolved "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz" integrity sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA== dependencies: "@types/minimatch" "*" @@ -2326,79 +2703,69 @@ "@types/google-protobuf@^3.15.2", "@types/google-protobuf@^3.15.5": version "3.15.6" - resolved "https://registry.yarnpkg.com/@types/google-protobuf/-/google-protobuf-3.15.6.tgz#674a69493ef2c849b95eafe69167ea59079eb504" + resolved "https://registry.npmjs.org/@types/google-protobuf/-/google-protobuf-3.15.6.tgz" integrity sha512-pYVNNJ+winC4aek+lZp93sIKxnXt5qMkuKmaqS3WGuTq0Bw1ZDYNBgzG5kkdtwcv+GmYJGo3yEg6z2cKKAiEdw== "@types/http-cache-semantics@*": version "4.0.1" - resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz#0ea7b61496902b95890dc4c3a116b60cb8dae812" + resolved "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz" integrity sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ== "@types/http-errors@*": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.1.tgz#20172f9578b225f6c7da63446f56d4ce108d5a65" - integrity sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ== + version "2.0.5" + resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.5.tgz#5b749ab2b16ba113423feb1a64a95dcd30398472" + integrity sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg== "@types/json-schema@*": version "7.0.12" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb" + resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz" integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA== "@types/keyv@^3.1.4": version "3.1.4" - resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.4.tgz#3ccdb1c6751b0c7e52300bcdacd5bcbf8faa75b6" + resolved "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz" integrity sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg== dependencies: "@types/node" "*" "@types/long@^4.0.0", "@types/long@^4.0.1": version "4.0.2" - resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a" + resolved "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz" integrity sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA== "@types/lru-cache@5.1.1", "@types/lru-cache@^5.1.0": version "5.1.1" - resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef" + resolved "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.1.tgz" integrity sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw== -"@types/mime@*": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10" - integrity sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA== - -"@types/mime@^1": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" - integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== - "@types/minimatch@*": version "5.1.2" - resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" + resolved "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz" integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== "@types/mocha@^10.0.1": version "10.0.1" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.1.tgz#2f4f65bb08bc368ac39c96da7b2f09140b26851b" + resolved "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.1.tgz" integrity sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q== "@types/ms@*": version "0.7.34" - resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.34.tgz#10964ba0dee6ac4cd462e2795b6bebd407303433" + resolved "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz" integrity sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g== "@types/node@*", "@types/node@>=13.7.0": version "20.4.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.4.9.tgz#c7164e0f8d3f12dfae336af0b1f7fdec8c6b204f" + resolved "https://registry.npmjs.org/@types/node/-/node-20.4.9.tgz" integrity sha512-8e2HYcg7ohnTUbHk8focoklEQYvemQmu9M/f43DZVx43kHn0tE3BY/6gSDxS7k0SprtS0NHvj+L80cGLnoOUcQ== "@types/node@10.12.18": version "10.12.18" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.18.tgz#1d3ca764718915584fcd9f6344621b7672665c67" + resolved "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz" integrity sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ== "@types/node@18.15.13": version "18.15.13" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.13.tgz#f64277c341150c979e42b00e4ac289290c9df469" + resolved "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz" integrity sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q== "@types/node@^10.0.3", "@types/node@^10.1.0": @@ -2408,39 +2775,44 @@ "@types/node@^12.12.6": version "12.20.55" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" + resolved "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz" integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== "@types/node@^8.0.0": version "8.10.66" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.66.tgz#dd035d409df322acc83dff62a602f12a5783bbb3" + resolved "https://registry.npmjs.org/@types/node/-/node-8.10.66.tgz" integrity sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw== "@types/pbkdf2@^3.0.0": version "3.1.0" - resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.0.tgz#039a0e9b67da0cdc4ee5dab865caa6b267bb66b1" + resolved "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.0.tgz" integrity sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ== dependencies: "@types/node" "*" "@types/prettier@^2.1.1": version "2.7.3" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.3.tgz#3e51a17e291d01d17d3fc61422015a933af7a08f" + resolved "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz" integrity sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA== -"@types/qs@*", "@types/qs@^6.2.31": +"@types/qs@*": + version "6.14.0" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.14.0.tgz#d8b60cecf62f2db0fb68e5e006077b9178b85de5" + integrity sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ== + +"@types/qs@^6.2.31": version "6.9.7" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" + resolved "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz" integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== "@types/range-parser@*": - version "1.2.4" - resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" - integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== + version "1.2.7" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb" + integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ== "@types/readable-stream@^2.3.13": version "2.3.15" - resolved "https://registry.yarnpkg.com/@types/readable-stream/-/readable-stream-2.3.15.tgz#3d79c9ceb1b6a57d5f6e6976f489b9b5384321ae" + resolved "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-2.3.15.tgz" integrity sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ== dependencies: "@types/node" "*" @@ -2448,67 +2820,66 @@ "@types/responselike@^1.0.0": version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29" + resolved "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz" integrity sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA== dependencies: "@types/node" "*" "@types/secp256k1@^4.0.1": version "4.0.3" - resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.3.tgz#1b8e55d8e00f08ee7220b4d59a6abe89c37a901c" + resolved "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.3.tgz" integrity sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w== dependencies: "@types/node" "*" "@types/seedrandom@3.0.1": version "3.0.1" - resolved "https://registry.yarnpkg.com/@types/seedrandom/-/seedrandom-3.0.1.tgz#1254750a4fec4aff2ebec088ccd0bb02e91fedb4" + resolved "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-3.0.1.tgz" integrity sha512-giB9gzDeiCeloIXDgzFBCgjj1k4WxcDrZtGl6h1IqmUPlxF+Nx8Ve+96QCyDZ/HseB/uvDsKbpib9hU5cU53pw== "@types/send@*": - version "0.17.1" - resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.1.tgz#ed4932b8a2a805f1fe362a70f4e62d0ac994e301" - integrity sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q== + version "1.2.1" + resolved "https://registry.yarnpkg.com/@types/send/-/send-1.2.1.tgz#6a784e45543c18c774c049bff6d3dbaf045c9c74" + integrity sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ== dependencies: - "@types/mime" "^1" "@types/node" "*" "@types/serve-static@*": - version "1.15.2" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.2.tgz#3e5419ecd1e40e7405d34093f10befb43f63381a" - integrity sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw== + version "2.2.0" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-2.2.0.tgz#d4a447503ead0d1671132d1ab6bd58b805d8de6a" + integrity sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ== dependencies: "@types/http-errors" "*" - "@types/mime" "*" "@types/node" "*" "@types/to-json-schema@^0.2.0": version "0.2.1" - resolved "https://registry.yarnpkg.com/@types/to-json-schema/-/to-json-schema-0.2.1.tgz#223346df86bc0c183d53c939ad5eb1ddfb0e9bf5" + resolved "https://registry.npmjs.org/@types/to-json-schema/-/to-json-schema-0.2.1.tgz" integrity sha512-DlvjodmdSrih054SrUqgS3bIZ93allrfbzjFUFmUhAtC60O+B/doLfgB8stafkEFyrU/zXWtPlX/V1H94iKv/A== dependencies: "@types/json-schema" "*" "@types/ws@^7.2.6": version "7.4.7" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.7.tgz#f7c390a36f7a0679aa69de2d501319f4f8d9b702" + resolved "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz" integrity sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww== dependencies: "@types/node" "*" "@ungap/promise-all-settled@1.1.2": version "1.1.2" - resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" + resolved "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz" integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== "@yarnpkg/lockfile@^1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" + resolved "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz" integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== "@zondax/filecoin-signing-tools@github:trufflesuite/filecoin-signing-tools-js": version "0.2.0" resolved "https://codeload.github.com/trufflesuite/filecoin-signing-tools-js/tar.gz/2786fdb8a2b71bd1c7789c0701da41bb644a098f" + integrity sha512-/EEqUgpe4dQm2FC9Oj79OWC1K6Uy5QJ6YgyozQzUF4Bnu7mPsyBWFl1Y83sYbKX6olEWYauOyqjYV8uxTY7cGA== dependencies: axios "0.26.1" base32-decode "^1.0.0" @@ -2523,34 +2894,29 @@ "@zxing/text-encoding@0.9.0": version "0.9.0" - resolved "https://registry.yarnpkg.com/@zxing/text-encoding/-/text-encoding-0.9.0.tgz#fb50ffabc6c7c66a0c96b4c03e3d9be74864b70b" + resolved "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz" integrity sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA== -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== - -abbrev@1.0.x: +abbrev@1, abbrev@1.0.x: version "1.0.9" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" + resolved "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz" integrity sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q== abort-controller@3.0.0, abort-controller@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + resolved "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz" integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== dependencies: event-target-shim "^5.0.0" abortcontroller-polyfill@^1.7.3: - version "1.7.5" - resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz#6738495f4e901fbb57b6c0611d0c75f76c485bed" - integrity sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ== + version "1.7.8" + resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.8.tgz#fe8d4370403f02e2aa37e3d2b0b178bae9d83f49" + integrity sha512-9f1iZ2uWh92VcrU9Y8x+LdM4DLj75VE0MJB8zuF1iUnroEptStw+DQ8EQPMUdfe5k+PkB1uUfDQfWbhstH8LrQ== abstract-level@1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/abstract-level/-/abstract-level-1.0.3.tgz#78a67d3d84da55ee15201486ab44c09560070741" + resolved "https://registry.npmjs.org/abstract-level/-/abstract-level-1.0.3.tgz" integrity sha512-t6jv+xHy+VYwc4xqZMn2Pa9DjcdzvzZmQGRjTFc8spIbRGHgBrEKbPq+rYXc7CCo0lxgYvSgKVg9qZAhpVQSjA== dependencies: buffer "^6.0.3" @@ -2563,7 +2929,7 @@ abstract-level@1.0.3: abstract-leveldown@7.2.0, abstract-leveldown@^7.2.0: version "7.2.0" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-7.2.0.tgz#08d19d4e26fb5be426f7a57004851b39e1795a2e" + resolved "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-7.2.0.tgz" integrity sha512-DnhQwcFEaYsvYDnACLZhMmCWd3rkOeEvglpa4q5i/5Jlm3UIsWaxVzuXvDLFCSCWRO3yy2/+V/G7FusFgejnfQ== dependencies: buffer "^6.0.3" @@ -2586,14 +2952,14 @@ abstract-leveldown@^6.2.1: abstract-leveldown@~2.6.0: version "2.6.3" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz#1c5e8c6a5ef965ae8c35dfb3a8770c476b82c4b8" + resolved "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz" integrity sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA== dependencies: xtend "~4.0.0" abstract-leveldown@~2.7.1: version "2.7.2" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz#87a44d7ebebc341d59665204834c8b7e0932cc93" + resolved "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz" integrity sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w== dependencies: xtend "~4.0.0" @@ -2611,7 +2977,7 @@ abstract-leveldown@~6.2.1, abstract-leveldown@~6.2.3: accepts@^1.3.5, accepts@~1.3.8: version "1.3.8" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + resolved "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz" integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== dependencies: mime-types "~2.1.34" @@ -2619,49 +2985,49 @@ accepts@^1.3.5, accepts@~1.3.8: acorn-walk@^8.1.1: version "8.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz" integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== acorn@^8.4.1: version "8.10.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz" integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== address@^1.0.1: version "1.2.2" - resolved "https://registry.yarnpkg.com/address/-/address-1.2.2.tgz#2b5248dac5485a6390532c6a517fda2e3faac89e" + resolved "https://registry.npmjs.org/address/-/address-1.2.2.tgz" integrity sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA== adm-zip@^0.4.16: version "0.4.16" - resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.16.tgz#cf4c508fdffab02c269cbc7f471a875f05570365" + resolved "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz" integrity sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg== aes-js@3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + resolved "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz" integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== aes-js@4.0.0-beta.5: version "4.0.0-beta.5" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-4.0.0-beta.5.tgz#8d2452c52adedebc3a3e28465d858c11ca315873" + resolved "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz" integrity sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q== aes-js@^3.1.2: version "3.1.2" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" + resolved "https://registry.npmjs.org/aes-js/-/aes-js-3.1.2.tgz" integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== agent-base@6: version "6.0.2" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + resolved "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz" integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== dependencies: debug "4" aggregate-error@^3.0.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + resolved "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz" integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== dependencies: clean-stack "^2.0.0" @@ -2675,9 +3041,9 @@ ajv-formats@^2.1.1: ajv "^8.0.0" ajv@^6.12.3: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + version "6.14.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.14.0.tgz#fd067713e228210636ebb08c60bd3765d6dbe73a" + integrity sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw== dependencies: fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" @@ -2685,18 +3051,18 @@ ajv@^6.12.3: uri-js "^4.2.2" ajv@^8.0.0, ajv@^8.0.1, ajv@^8.6.3: - version "8.12.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" - integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== + version "8.18.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.18.0.tgz#8864186b6738d003eb3a933172bb3833e10cefbc" + integrity sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A== dependencies: - fast-deep-equal "^3.1.1" + fast-deep-equal "^3.1.3" + fast-uri "^3.0.1" json-schema-traverse "^1.0.0" require-from-string "^2.0.2" - uri-js "^4.2.2" amazon-cognito-identity-js@^6.0.1: version "6.3.2" - resolved "https://registry.yarnpkg.com/amazon-cognito-identity-js/-/amazon-cognito-identity-js-6.3.2.tgz#48a216d3e151dda40f97d1765446bcba7fcc820f" + resolved "https://registry.npmjs.org/amazon-cognito-identity-js/-/amazon-cognito-identity-js-6.3.2.tgz" integrity sha512-g1MqdAuvIsUtzI4b9gqusk/J5hH93XVlTV4/pjWb2cKnsWJfyMo/52EKWJL5dI2cp37dZhXt/xS1l9me42ENDg== dependencies: "@aws-crypto/sha256-js" "1.2.2" @@ -2707,34 +3073,34 @@ amazon-cognito-identity-js@^6.0.1: amdefine@>=0.0.4: version "1.0.1" - resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + resolved "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz" integrity sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg== ansi-align@^3.0.0: version "3.0.1" - resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" + resolved "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz" integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== dependencies: string-width "^4.1.0" ansi-colors@3.2.3: version "3.2.3" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" + resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz" integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== ansi-colors@4.1.1: version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz" integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== ansi-colors@^4.1.1: version "4.1.3" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" + resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz" integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== ansi-escapes@^4.3.0: version "4.3.2" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz" integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== dependencies: type-fest "^0.21.3" @@ -2746,41 +3112,51 @@ ansi-regex@^2.0.0: ansi-regex@^3.0.0: version "3.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz" integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== ansi-regex@^4.1.0: version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz" integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== ansi-regex@^5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +ansi-regex@^6.0.1: + version "6.2.2" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.2.2.tgz#60216eea464d864597ce2832000738a0589650c1" + integrity sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg== + ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: color-convert "^2.0.1" +ansi-styles@^6.2.1: + version "6.2.3" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.3.tgz#c044d5dcc521a076413472597a1acb1f103c4041" + integrity sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg== + antlr4ts@^0.5.0-alpha.4: version "0.5.0-alpha.4" - resolved "https://registry.yarnpkg.com/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz#71702865a87478ed0b40c0709f422cf14d51652a" + resolved "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz" integrity sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ== any-signal@^2.0.0, any-signal@^2.1.0: version "2.1.2" - resolved "https://registry.yarnpkg.com/any-signal/-/any-signal-2.1.2.tgz#8d48270de0605f8b218cf9abe8e9c6a0e7418102" + resolved "https://registry.npmjs.org/any-signal/-/any-signal-2.1.2.tgz" integrity sha512-B+rDnWasMi/eWcajPcCWSlYc7muXOrcYrqgyzcdKisl2H/WTlQ0gip1KyQfr0ZlxJdsuWCj/LWwQm7fhyhRfIQ== dependencies: abort-controller "^3.0.0" @@ -2788,7 +3164,7 @@ any-signal@^2.0.0, any-signal@^2.1.0: anymatch@~3.1.1, anymatch@~3.1.2: version "3.1.3" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz" integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== dependencies: normalize-path "^3.0.0" @@ -2809,10 +3185,10 @@ apollo-reporting-protobuf@^3.4.0: dependencies: "@apollo/protobufjs" "1.2.6" -apollo-server-core@^3.12.0: - version "3.12.1" - resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-3.12.1.tgz#ba255c37345db29c48a2e0c064c519a8d62eb5af" - integrity sha512-9SF5WAkkV0FZQ2HVUWI9Jada1U0jg7e8NCN9EklbtvaCeUlOLyXyM+KCWuZ7+dqHxjshbtcwylPHutt3uzoNkw== +apollo-server-core@^3.13.0: + version "3.13.0" + resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-3.13.0.tgz#ad6601fbb34cc97eedca27a9fb0b5738d11cd27d" + integrity sha512-v/g6DR6KuHn9DYSdtQijz8dLOkP78I5JSVJzPkARhDbhpH74QNwrQ2PP2URAPPEDJ2EeZNQDX8PvbYkAKqg+kg== dependencies: "@apollo/utils.keyvaluecache" "^1.0.1" "@apollo/utils.logger" "^1.0.0" @@ -2850,10 +3226,10 @@ apollo-server-errors@^3.3.1: resolved "https://registry.yarnpkg.com/apollo-server-errors/-/apollo-server-errors-3.3.1.tgz#ba5c00cdaa33d4cbd09779f8cb6f47475d1cd655" integrity sha512-xnZJ5QWs6FixHICXHxUfm+ZWqqxrNuPlQ+kj5m6RtEgIpekOPssH/SD9gf2B4HuWV0QozorrygwZnux8POvyPA== -apollo-server-express@^3.12.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-3.12.0.tgz#a6e392bb0427544b8c7e5d841ef07f7691b0c105" - integrity sha512-m8FaGPUfDOEGSm7QRWRmUUGjG/vqvpQoorkId9/FXkC57fz/A59kEdrzkMt9538Xgsa5AV+X4MEWLJhTvlW3LQ== +apollo-server-express@^3.13.0: + version "3.13.0" + resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-3.13.0.tgz#0d8d9bbba3b8b8264912d215f63fd44e74d5f42a" + integrity sha512-iSxICNbDUyebOuM8EKb3xOrpIwOQgKxGbR2diSr4HP3IW8T3njKFOoMce50vr+moOCe1ev8BnLcw9SNbuUtf7g== dependencies: "@types/accepts" "^1.3.5" "@types/body-parser" "1.19.2" @@ -2861,7 +3237,7 @@ apollo-server-express@^3.12.0: "@types/express" "4.17.14" "@types/express-serve-static-core" "4.17.31" accepts "^1.3.5" - apollo-server-core "^3.12.0" + apollo-server-core "^3.13.0" apollo-server-types "^3.8.0" body-parser "^1.19.0" cors "^2.8.5" @@ -2885,18 +3261,18 @@ apollo-server-types@^3.8.0: apollo-server-env "^4.2.1" apollo-server@^3.11.0, apollo-server@^3.6.3: - version "3.12.0" - resolved "https://registry.yarnpkg.com/apollo-server/-/apollo-server-3.12.0.tgz#bd43d6dadb8cb16ed34edfc6ad97a81b1fab748a" - integrity sha512-wZHLgBoIdGxr/YpPTG5RwNnS+B2y70T/nCegCnU6Yl+H3PXB92OIguLMhdJIZVjukIOhiQT12dNIehqLQ+1hMQ== + version "3.13.0" + resolved "https://registry.yarnpkg.com/apollo-server/-/apollo-server-3.13.0.tgz#38d355756717c0cb519e7ab95bce6dcc8ce35677" + integrity sha512-hgT/MswNB5G1r+oBhggVX4Fjw53CFLqG15yB5sN+OrYkCVWF5YwPbJWHfSWa7699JMEXJGaoVfFzcvLZK0UlDg== dependencies: "@types/express" "4.17.14" - apollo-server-core "^3.12.0" - apollo-server-express "^3.12.0" + apollo-server-core "^3.13.0" + apollo-server-express "^3.13.0" express "^4.17.1" app-module-path@^2.2.0: version "2.2.0" - resolved "https://registry.yarnpkg.com/app-module-path/-/app-module-path-2.2.0.tgz#641aa55dfb7d6a6f0a8141c4b9c0aa50b6c24dd5" + resolved "https://registry.npmjs.org/app-module-path/-/app-module-path-2.2.0.tgz" integrity sha512-gkco+qxENJV+8vFcDiiFhuoSvRXb2a/QPqpSoWhVz829VNJfOTnELbBmPmNKFxf3xdNnw4DWCkzkDaavcX/1YQ== aproba@^1.0.3: @@ -2914,19 +3290,19 @@ are-we-there-yet@~1.1.2: arg@^4.1.0: version "4.1.3" - resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + resolved "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz" integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== argparse@^1.0.7: version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz" integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== dependencies: sprintf-js "~1.0.2" argparse@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== argsarray@0.0.1, argsarray@^0.0.1: @@ -2936,17 +3312,17 @@ argsarray@0.0.1, argsarray@^0.0.1: array-back@^3.0.1, array-back@^3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0" + resolved "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz" integrity sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q== array-back@^4.0.1, array-back@^4.0.2: version "4.0.2" - resolved "https://registry.yarnpkg.com/array-back/-/array-back-4.0.2.tgz#8004e999a6274586beeb27342168652fdb89fa1e" + resolved "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz" integrity sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg== array-buffer-byte-length@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead" + resolved "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz" integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A== dependencies: call-bind "^1.0.2" @@ -2954,22 +3330,22 @@ array-buffer-byte-length@^1.0.0: array-flatten@1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + resolved "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== array-union@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== array-uniq@1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + resolved "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz" integrity sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q== array.prototype.reduce@^1.0.5: version "1.0.5" - resolved "https://registry.yarnpkg.com/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz#6b20b0daa9d9734dd6bc7ea66b5bbce395471eac" + resolved "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz" integrity sha512-kDdugMl7id9COE8R7MHF5jWk7Dqt/fs4Pv+JXoICnYwqpjjjbUurz6w5fT5IG6brLdJhv6/VoHB0H7oyIBXd+Q== dependencies: call-bind "^1.0.2" @@ -2980,7 +3356,7 @@ array.prototype.reduce@^1.0.5: arraybuffer.prototype.slice@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz#9b5ea3868a6eebc30273da577eb888381c0044bb" + resolved "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz" integrity sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw== dependencies: array-buffer-byte-length "^1.0.0" @@ -2992,12 +3368,12 @@ arraybuffer.prototype.slice@^1.0.1: asap@~2.0.6: version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + resolved "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz" integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== asn1.js@^5.0.1, asn1.js@^5.2.0: version "5.4.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" + resolved "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz" integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== dependencies: bn.js "^4.0.0" @@ -3007,36 +3383,36 @@ asn1.js@^5.0.1, asn1.js@^5.2.0: asn1@~0.2.3: version "0.2.6" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" + resolved "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz" integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== dependencies: safer-buffer "~2.1.0" assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + resolved "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== assertion-error@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + resolved "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz" integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== astral-regex@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + resolved "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== async-eventemitter@0.2.4, async-eventemitter@^0.2.2: version "0.2.4" - resolved "https://registry.yarnpkg.com/async-eventemitter/-/async-eventemitter-0.2.4.tgz#f5e7c8ca7d3e46aab9ec40a292baf686a0bafaca" + resolved "https://registry.npmjs.org/async-eventemitter/-/async-eventemitter-0.2.4.tgz" integrity sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw== dependencies: async "^2.4.0" async-limiter@~1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" + resolved "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz" integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== async-retry@^1.2.1, async-retry@^1.3.3: @@ -3048,24 +3424,24 @@ async-retry@^1.2.1, async-retry@^1.3.3: async@1.x, async@^1.4.2: version "1.5.2" - resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + resolved "https://registry.npmjs.org/async/-/async-1.5.2.tgz" integrity sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w== async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.5.0: version "2.6.4" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" + resolved "https://registry.npmjs.org/async/-/async-2.6.4.tgz" integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== dependencies: lodash "^4.17.14" asynckit@^0.4.0: version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== at-least-node@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + resolved "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz" integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== atomically@^1.7.0: @@ -3075,35 +3451,42 @@ atomically@^1.7.0: available-typed-arrays@^1.0.5: version "1.0.5" - resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" + resolved "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz" integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== +available-typed-arrays@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" + integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== + dependencies: + possible-typed-array-names "^1.0.0" + await-semaphore@^0.1.3: version "0.1.3" - resolved "https://registry.yarnpkg.com/await-semaphore/-/await-semaphore-0.1.3.tgz#2b88018cc8c28e06167ae1cdff02504f1f9688d3" + resolved "https://registry.npmjs.org/await-semaphore/-/await-semaphore-0.1.3.tgz" integrity sha512-d1W2aNSYcz/sxYO4pMGX9vq65qOTu0P800epMud+6cYYX0QcT7zyqcxec3VWzpgvdXo57UWmVbZpLMjX2m1I7Q== aws-sign2@~0.7.0: version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + resolved "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz" integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== aws4@^1.8.0: version "1.12.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3" + resolved "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz" integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg== axios@0.26.1: version "0.26.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.26.1.tgz#1ede41c51fcf51bbbd6fd43669caaa4f0495aaa9" + resolved "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz" integrity sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA== dependencies: follow-redirects "^1.14.8" -axios@1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.2.4.tgz#6555dd955d2efa9b8f4cb4cb0b3371b7b243537a" - integrity sha512-lIQuCfBJvZB/Bv7+RWUqEJqNShGOVpk9v7P0ZWx5Ip0qY6u7JBAU6dzQPMLasU9vHL2uD8av/1FDJXj7n6c39w== +axios@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.5.0.tgz#f02e4af823e2e46a9768cfc74691fdd0517ea267" + integrity sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ== dependencies: follow-redirects "^1.15.0" form-data "^4.0.0" @@ -3111,7 +3494,7 @@ axios@1.2.4: axios@^1.4.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.4.0.tgz#38a7bf1224cd308de271146038b551d725f0be1f" + resolved "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz" integrity sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA== dependencies: follow-redirects "^1.15.0" @@ -3120,7 +3503,7 @@ axios@^1.4.0: babel-plugin-polyfill-corejs2@^0.4.5: version "0.4.5" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.5.tgz#8097b4cb4af5b64a1d11332b6fb72ef5e64a054c" + resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.5.tgz" integrity sha512-19hwUH5FKl49JEsvyTcoHakh6BE0wgXLLptIyKZ3PijHc/Ci521wygORCUCCred+E/twuqRyAkE02BAWPmsHOg== dependencies: "@babel/compat-data" "^7.22.6" @@ -3129,7 +3512,7 @@ babel-plugin-polyfill-corejs2@^0.4.5: babel-plugin-polyfill-corejs3@^0.8.3: version "0.8.3" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.3.tgz#b4f719d0ad9bb8e0c23e3e630c0c8ec6dd7a1c52" + resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.3.tgz" integrity sha512-z41XaniZL26WLrvjy7soabMXrfPWARN25PZoriDEiLMxAp50AUW3t35BGQUMg5xK3UrpVTtagIDklxYa+MhiNA== dependencies: "@babel/helper-define-polyfill-provider" "^0.4.2" @@ -3137,50 +3520,55 @@ babel-plugin-polyfill-corejs3@^0.8.3: babel-plugin-polyfill-regenerator@^0.5.2: version "0.5.2" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.2.tgz#80d0f3e1098c080c8b5a65f41e9427af692dc326" + resolved "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.2.tgz" integrity sha512-tAlOptU0Xj34V1Y2PNTL4Y0FOJMDB6bZmoW39FeCQIhigGLkqu3Fj6uiXpxIf6Ij274ENdYx64y6Au+ZKlb1IA== dependencies: "@babel/helper-define-polyfill-provider" "^0.4.2" backoff@^2.5.0: version "2.5.0" - resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f" + resolved "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz" integrity sha512-wC5ihrnUXmR2douXmXLCe5O3zg3GKIyvRi/hi58a/XyRxVI+3/yM0PYueQOZXPXQ9pxBislYkw+sF9b7C/RuMA== dependencies: precond "0.2" balanced-match@^1.0.0: version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== base-x@^3.0.2, base-x@^3.0.8: - version "3.0.9" - resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.9.tgz#6349aaabb58526332de9f60995e548a53fe21320" - integrity sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ== + version "3.0.11" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.11.tgz#40d80e2a1aeacba29792ccc6c5354806421287ff" + integrity sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA== dependencies: safe-buffer "^5.0.1" base32-decode@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/base32-decode/-/base32-decode-1.0.0.tgz#2a821d6a664890c872f20aa9aca95a4b4b80e2a7" + resolved "https://registry.npmjs.org/base32-decode/-/base32-decode-1.0.0.tgz" integrity sha512-KNWUX/R7wKenwE/G/qFMzGScOgVntOmbE27vvc6GrniDGYb6a5+qWcuoXl8WIOQL7q0TpK7nZDm1Y04Yi3Yn5g== base32-encode@^1.1.1: version "1.2.0" - resolved "https://registry.yarnpkg.com/base32-encode/-/base32-encode-1.2.0.tgz#e150573a5e431af0a998e32bdfde7045725ca453" + resolved "https://registry.npmjs.org/base32-encode/-/base32-encode-1.2.0.tgz" integrity sha512-cHFU8XeRyx0GgmoWi5qHMCVRiqU6J3MHWxVgun7jggCBUpVzm1Ir7M9dYr2whjSNc3tFeXfQ/oZjQu/4u55h9A== dependencies: to-data-view "^1.1.0" base64-js@^1.0.2, base64-js@^1.3.1: version "1.5.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== +baseline-browser-mapping@^2.8.25: + version "2.8.30" + resolved "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.30.tgz" + integrity sha512-aTUKW4ptQhS64+v2d6IkPzymEzzhw+G0bA1g3uBRV3+ntkH+svttKseW5IOR4Ed6NUVKqnY7qT3dKvzQ7io4AA== + bcrypt-pbkdf@^1.0.0: version "1.0.2" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + resolved "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz" integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== dependencies: tweetnacl "^0.14.3" @@ -3192,7 +3580,7 @@ bech32@1.1.4, bech32@^1.1.3: bech32@=2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/bech32/-/bech32-2.0.0.tgz#078d3686535075c8c79709f054b1b226a133b355" + resolved "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz" integrity sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg== big-integer@1.6.36: @@ -3202,39 +3590,39 @@ big-integer@1.6.36: big.js@^6.0.3: version "6.2.1" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-6.2.1.tgz#7205ce763efb17c2e41f26f121c420c6a7c2744f" + resolved "https://registry.npmjs.org/big.js/-/big.js-6.2.1.tgz" integrity sha512-bCtHMwL9LeDIozFn+oNhhFoq+yQ3BNdnsLSASUxLciOb1vgvpHsIO1dsENiGMgbb4SkP5TrzWzRiLddn8ahVOQ== bigi@^1.1.0, bigi@^1.4.2: version "1.4.2" - resolved "https://registry.yarnpkg.com/bigi/-/bigi-1.4.2.tgz#9c665a95f88b8b08fc05cfd731f561859d725825" + resolved "https://registry.npmjs.org/bigi/-/bigi-1.4.2.tgz" integrity sha512-ddkU+dFIuEIW8lE7ZwdIAf2UPoM90eaprg5m3YXAVVTmKlqV/9BX4A2M8BOK2yOq6/VgZFVhK6QAxJebhlbhzw== bigint-crypto-utils@^3.2.2: version "3.3.0" - resolved "https://registry.yarnpkg.com/bigint-crypto-utils/-/bigint-crypto-utils-3.3.0.tgz#72ad00ae91062cf07f2b1def9594006c279c1d77" + resolved "https://registry.npmjs.org/bigint-crypto-utils/-/bigint-crypto-utils-3.3.0.tgz" integrity sha512-jOTSb+drvEDxEq6OuUybOAv/xxoh3cuYRUIPyu8sSHQNKM303UQ2R1DAo45o1AkcIXw6fzbaFI1+xGGdaXs2lg== bignumber.js@^9.0.0, bignumber.js@^9.0.1: version "9.1.1" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.1.tgz#c4df7dc496bd849d4c9464344c1aa74228b4dac6" + resolved "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.1.tgz" integrity sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig== binary-extensions@^2.0.0: version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== bindings@^1.3.0, bindings@^1.5.0: version "1.5.0" - resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + resolved "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz" integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== dependencies: file-uri-to-path "1.0.0" bip-schnorr@=0.6.4: version "0.6.4" - resolved "https://registry.yarnpkg.com/bip-schnorr/-/bip-schnorr-0.6.4.tgz#6fde7f301fe6b207dbd05f8ec2caf08fa5a51d0d" + resolved "https://registry.npmjs.org/bip-schnorr/-/bip-schnorr-0.6.4.tgz" integrity sha512-dNKw7Lea8B0wMIN4OjEmOk/Z5qUGqoPDY0P2QttLqGk1hmDPytLWW8PR5Pb6Vxy6CprcdEgfJpOjUu+ONQveyg== dependencies: bigi "^1.4.2" @@ -3245,7 +3633,7 @@ bip-schnorr@=0.6.4: bip32@^2.0.5: version "2.0.6" - resolved "https://registry.yarnpkg.com/bip32/-/bip32-2.0.6.tgz#6a81d9f98c4cd57d05150c60d8f9e75121635134" + resolved "https://registry.npmjs.org/bip32/-/bip32-2.0.6.tgz" integrity sha512-HpV5OMLLGTjSVblmrtYRfFFKuQB+GArM0+XP8HGWfJ5vxYBqo+DesvJwOdC2WJ3bCkZShGf0QIfoIpeomVzVdA== dependencies: "@types/node" "10.12.18" @@ -3258,14 +3646,14 @@ bip32@^2.0.5: bip39@^3.0.2: version "3.1.0" - resolved "https://registry.yarnpkg.com/bip39/-/bip39-3.1.0.tgz#c55a418deaf48826a6ceb34ac55b3ee1577e18a3" + resolved "https://registry.npmjs.org/bip39/-/bip39-3.1.0.tgz" integrity sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A== dependencies: "@noble/hashes" "^1.2.0" bitcore-lib@^8.22.2, bitcore-lib@^8.25.47: version "8.25.47" - resolved "https://registry.yarnpkg.com/bitcore-lib/-/bitcore-lib-8.25.47.tgz#a2382fdfbf55922aff2f77c8f2d754239bc2854a" + resolved "https://registry.npmjs.org/bitcore-lib/-/bitcore-lib-8.25.47.tgz" integrity sha512-qDZr42HuP4P02I8kMGZUx/vvwuDsz8X3rQxXLfM0BtKzlQBcbSM7ycDkDN99Xc5jzpd4fxNQyyFXOmc6owUsrQ== dependencies: bech32 "=2.0.0" @@ -3279,7 +3667,7 @@ bitcore-lib@^8.22.2, bitcore-lib@^8.25.47: bitcore-mnemonic@^8.22.2: version "8.25.47" - resolved "https://registry.yarnpkg.com/bitcore-mnemonic/-/bitcore-mnemonic-8.25.47.tgz#d15b12bb7a76930aa78f3fce2393715064aa66d4" + resolved "https://registry.npmjs.org/bitcore-mnemonic/-/bitcore-mnemonic-8.25.47.tgz" integrity sha512-wTa0imZZpFTqwlpyokvU8CNl+YdaIvQIrWKp/0AEL9gPX2vuzBnE+U8Ok6D5lHCnbG6dvmoesmtyf6R3aYI86A== dependencies: bitcore-lib "^8.25.47" @@ -3287,7 +3675,7 @@ bitcore-mnemonic@^8.22.2: bl@^4.0.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + resolved "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz" integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== dependencies: buffer "^5.5.0" @@ -3296,45 +3684,45 @@ bl@^4.0.0: blakejs@^1.1.0: version "1.2.1" - resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814" + resolved "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz" integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ== blob-to-it@^1.0.1: version "1.0.4" - resolved "https://registry.yarnpkg.com/blob-to-it/-/blob-to-it-1.0.4.tgz#f6caf7a4e90b7bb9215fa6a318ed6bd8ad9898cb" + resolved "https://registry.npmjs.org/blob-to-it/-/blob-to-it-1.0.4.tgz" integrity sha512-iCmk0W4NdbrWgRRuxOriU8aM5ijeVLI61Zulsmg/lUHNr7pYjoj+U77opLefNagevtrrbMt3JQ5Qip7ar178kA== dependencies: browser-readablestream-to-it "^1.0.3" bluebird@^3.5.0, bluebird@^3.5.2: version "3.7.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + resolved "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== bn.js@4.11.6: version "4.11.6" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" + resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz" integrity sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA== bn.js@=4.11.8: version "4.11.8" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" + resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz" integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.0, bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^4.11.9: version "4.12.0" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== bn.js@^5.0.0, bn.js@^5.1.2, bn.js@^5.1.3, bn.js@^5.2.0, bn.js@^5.2.1: version "5.2.1" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + resolved "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz" integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== -body-parser@1.20.2, body-parser@^1.16.0, body-parser@^1.19.0: - version "1.20.2" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" - integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== +body-parser@1.20.3: + version "1.20.3" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.3.tgz#1953431221c6fb5cd63c4b36d53fab0928e548c6" + integrity sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g== dependencies: bytes "3.1.2" content-type "~1.0.5" @@ -3344,14 +3732,32 @@ body-parser@1.20.2, body-parser@^1.16.0, body-parser@^1.19.0: http-errors "2.0.0" iconv-lite "0.4.24" on-finished "2.4.1" - qs "6.11.0" + qs "6.13.0" raw-body "2.5.2" type-is "~1.6.18" unpipe "1.0.0" +body-parser@^1.16.0, body-parser@^1.19.0: + version "1.20.4" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.4.tgz#f8e20f4d06ca8a50a71ed329c15dccad1cdc547f" + integrity sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA== + dependencies: + bytes "~3.1.2" + content-type "~1.0.5" + debug "2.6.9" + depd "2.0.0" + destroy "~1.2.0" + http-errors "~2.0.1" + iconv-lite "~0.4.24" + on-finished "~2.4.1" + qs "~6.14.0" + raw-body "~2.5.3" + type-is "~1.6.18" + unpipe "~1.0.0" + borc@^2.1.2: version "2.1.2" - resolved "https://registry.yarnpkg.com/borc/-/borc-2.1.2.tgz#6ce75e7da5ce711b963755117dd1b187f6f8cf19" + resolved "https://registry.npmjs.org/borc/-/borc-2.1.2.tgz" integrity sha512-Sy9eoUi4OiKzq7VovMn246iTo17kzuyHJKomCfpWMlI6RpfN1gk95w7d7gH264nApVLg0HZfcpz62/g4VH1Y4w== dependencies: bignumber.js "^9.0.0" @@ -3364,7 +3770,7 @@ borc@^2.1.2: boxen@^5.1.2: version "5.1.2" - resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" + resolved "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz" integrity sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ== dependencies: ansi-align "^3.0.0" @@ -3377,50 +3783,50 @@ boxen@^5.1.2: wrap-ansi "^7.0.0" brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + version "1.1.12" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" + integrity sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + version "2.0.2" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" + integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== dependencies: balanced-match "^1.0.0" -braces@^3.0.2, braces@~3.0.2: +braces@^3.0.3, braces@~3.0.2: version "3.0.3" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + resolved "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz" integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== dependencies: fill-range "^7.1.1" brorand@^1.0.1, brorand@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + resolved "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz" integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== browser-headers@^0.4.0, browser-headers@^0.4.1: version "0.4.1" - resolved "https://registry.yarnpkg.com/browser-headers/-/browser-headers-0.4.1.tgz#4308a7ad3b240f4203dbb45acedb38dc2d65dd02" + resolved "https://registry.npmjs.org/browser-headers/-/browser-headers-0.4.1.tgz" integrity sha512-CA9hsySZVo9371qEHjHZtYxV2cFtVj5Wj/ZHi8ooEsrtm4vOnl9Y9HmyYWk9q+05d7K3rdoAE0j3MVEFVvtQtg== browser-readablestream-to-it@^1.0.1, browser-readablestream-to-it@^1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/browser-readablestream-to-it/-/browser-readablestream-to-it-1.0.3.tgz#ac3e406c7ee6cdf0a502dd55db33bab97f7fba76" + resolved "https://registry.npmjs.org/browser-readablestream-to-it/-/browser-readablestream-to-it-1.0.3.tgz" integrity sha512-+12sHB+Br8HIh6VAMVEG5r3UXCyESIgDW7kzk3BjIXa43DVqVwL7GC5TW3jeh+72dtcH99pPVpw0X8i0jt+/kw== browser-stdout@1.3.1: version "1.3.1" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + resolved "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz" integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.2.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + resolved "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz" integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== dependencies: buffer-xor "^1.0.3" @@ -3432,7 +3838,7 @@ browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.2.0: browserify-cipher@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + resolved "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz" integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== dependencies: browserify-aes "^1.0.4" @@ -3441,7 +3847,7 @@ browserify-cipher@^1.0.0: browserify-des@^1.0.0: version "1.0.2" - resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + resolved "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz" integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== dependencies: cipher-base "^1.0.1" @@ -3451,7 +3857,7 @@ browserify-des@^1.0.0: browserify-rsa@^4.0.0, browserify-rsa@^4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" + resolved "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz" integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== dependencies: bn.js "^5.0.0" @@ -3459,7 +3865,7 @@ browserify-rsa@^4.0.0, browserify-rsa@^4.1.0: browserify-sign@^4.0.0: version "4.2.2" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.2.tgz#e78d4b69816d6e3dd1c747e64e9947f9ad79bc7e" + resolved "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.2.tgz" integrity sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg== dependencies: bn.js "^5.2.1" @@ -3472,26 +3878,27 @@ browserify-sign@^4.0.0: readable-stream "^3.6.2" safe-buffer "^5.2.1" -browserslist@^4.21.9: - version "4.21.10" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.10.tgz#dbbac576628c13d3b2231332cb2ec5a46e015bb0" - integrity sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ== +browserslist@^4.21.9, browserslist@^4.24.0: + version "4.28.0" + resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.28.0.tgz" + integrity sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ== dependencies: - caniuse-lite "^1.0.30001517" - electron-to-chromium "^1.4.477" - node-releases "^2.0.13" - update-browserslist-db "^1.0.11" + baseline-browser-mapping "^2.8.25" + caniuse-lite "^1.0.30001754" + electron-to-chromium "^1.5.249" + node-releases "^2.0.27" + update-browserslist-db "^1.1.4" bs58@^4.0.0, bs58@^4.0.1: version "4.0.1" - resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" + resolved "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz" integrity sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw== dependencies: base-x "^3.0.2" bs58check@<3.0.0, bs58check@^2.1.1, bs58check@^2.1.2: version "2.1.2" - resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" + resolved "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz" integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== dependencies: bs58 "^4.0.0" @@ -3500,17 +3907,17 @@ bs58check@<3.0.0, bs58check@^2.1.1, bs58check@^2.1.2: btoa-lite@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/btoa-lite/-/btoa-lite-1.0.0.tgz#337766da15801210fdd956c22e9c6891ab9d0337" + resolved "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz" integrity sha512-gvW7InbIyF8AicrqWoptdW08pUxuhq8BEgowNajy9RhiE86fmGAGl+bLKo6oB8QP0CkqHLowfN0oJdKC/J6LbA== btoa@^1.2.1: version "1.2.1" - resolved "https://registry.yarnpkg.com/btoa/-/btoa-1.2.1.tgz#01a9909f8b2c93f6bf680ba26131eb30f7fa3d73" + resolved "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz" integrity sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g== buffer-compare@=1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-compare/-/buffer-compare-1.1.1.tgz#5be7be853af89198d1f4ddc090d1d66a48aef596" + resolved "https://registry.npmjs.org/buffer-compare/-/buffer-compare-1.1.1.tgz" integrity sha512-O6NvNiHZMd3mlIeMDjP6t/gPG75OqGPeiRZXoMQZJ6iy9GofCls4Ijs5YkPZZwoysizLiedhticmdyx/GyHghA== buffer-from@1.1.0: @@ -3525,24 +3932,24 @@ buffer-from@1.1.2, buffer-from@^1.0.0: buffer-pipe@0.0.3: version "0.0.3" - resolved "https://registry.yarnpkg.com/buffer-pipe/-/buffer-pipe-0.0.3.tgz#242197681d4591e7feda213336af6c07a5ce2409" + resolved "https://registry.npmjs.org/buffer-pipe/-/buffer-pipe-0.0.3.tgz" integrity sha512-GlxfuD/NrKvCNs0Ut+7b1IHjylfdegMBxQIlZHj7bObKVQBxB5S84gtm2yu1mQ8/sSggceWBDPY0cPXgvX2MuA== dependencies: safe-buffer "^5.1.2" buffer-to-arraybuffer@^0.0.5: version "0.0.5" - resolved "https://registry.yarnpkg.com/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz#6064a40fa76eb43c723aba9ef8f6e1216d10511a" + resolved "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz" integrity sha512-3dthu5CYiVB1DEJp61FtApNnNndTckcqe4pFcLdvHtrpG+kcyekCJKg4MRiDcFW7A6AODnXB9U4dwQiCW5kzJQ== buffer-xor@^1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + resolved "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz" integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== buffer@4.9.2: version "4.9.2" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" + resolved "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz" integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== dependencies: base64-js "^1.0.2" @@ -3551,7 +3958,7 @@ buffer@4.9.2: buffer@6.0.3, buffer@^6.0.1, buffer@^6.0.3: version "6.0.3" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + resolved "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz" integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== dependencies: base64-js "^1.3.1" @@ -3559,7 +3966,7 @@ buffer@6.0.3, buffer@^6.0.1, buffer@^6.0.3: buffer@^5.0.5, buffer@^5.4.3, buffer@^5.5.0, buffer@^5.6.0: version "5.7.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== dependencies: base64-js "^1.3.1" @@ -3567,26 +3974,26 @@ buffer@^5.0.5, buffer@^5.4.3, buffer@^5.5.0, buffer@^5.6.0: bufferutil@4.0.5: version "4.0.5" - resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.5.tgz#da9ea8166911cc276bf677b8aed2d02d31f59028" + resolved "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.5.tgz" integrity sha512-HTm14iMQKK2FjFLRTM5lAVcyaUzOnqbPtesFIvREgXpJHdQm8bWS+GkQgIkfaBYRHuCnea7w8UVNfwiAQhlr9A== dependencies: node-gyp-build "^4.3.0" -bufferutil@^4.0.1: +bufferutil@4.0.7, bufferutil@^4.0.1: version "4.0.7" - resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.7.tgz#60c0d19ba2c992dd8273d3f73772ffc894c153ad" + resolved "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.7.tgz" integrity sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw== dependencies: node-gyp-build "^4.3.0" -bytes@3.1.2: +bytes@3.1.2, bytes@~3.1.2: version "3.1.2" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== cacheable-lookup@^5.0.3: version "5.0.4" - resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005" + resolved "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz" integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA== cacheable-lookup@^6.0.4: @@ -3596,7 +4003,7 @@ cacheable-lookup@^6.0.4: cacheable-request@^6.0.0: version "6.1.0" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" + resolved "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz" integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== dependencies: clone-response "^1.0.2" @@ -3609,7 +4016,7 @@ cacheable-request@^6.0.0: cacheable-request@^7.0.2: version "7.0.4" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.4.tgz#7a33ebf08613178b403635be7b899d3e69bbe817" + resolved "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz" integrity sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg== dependencies: clone-response "^1.0.2" @@ -3620,17 +4027,43 @@ cacheable-request@^7.0.2: normalize-url "^6.0.1" responselike "^2.0.0" +call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" + integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz" integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== dependencies: function-bind "^1.1.1" get-intrinsic "^1.0.2" +call-bind@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.8.tgz#0736a9660f537e3388826f440d5ec45f744eaa4c" + integrity sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww== + dependencies: + call-bind-apply-helpers "^1.0.0" + es-define-property "^1.0.0" + get-intrinsic "^1.2.4" + set-function-length "^1.2.2" + +call-bound@^1.0.2, call-bound@^1.0.3, call-bound@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.4.tgz#238de935d2a2a692928c538c7ccfa91067fd062a" + integrity sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg== + dependencies: + call-bind-apply-helpers "^1.0.2" + get-intrinsic "^1.3.0" + camel-case@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73" + resolved "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz" integrity sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w== dependencies: no-case "^2.2.0" @@ -3643,32 +4076,34 @@ camelcase@^3.0.0: camelcase@^5.0.0: version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== camelcase@^6.0.0, camelcase@^6.2.0: version "6.3.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001517: - version "1.0.30001519" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001519.tgz#3e7b8b8a7077e78b0eb054d69e6edf5c7df35601" - integrity sha512-0QHgqR+Jv4bxHMp8kZ1Kn8CH55OikjKJ6JmKkZYP1F3D7w+lnFXF70nG5eNfsZS89jadi5Ywy5UCSKLAglIRkg== +caniuse-lite@^1.0.30001754: + version "1.0.30001756" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001756.tgz" + integrity sha512-4HnCNKbMLkLdhJz3TToeVWHSnfJvPaq6vu/eRP0Ahub/07n484XHhBF5AJoSGHdVrS8tKFauUQz8Bp9P7LVx7A== caseless@^0.12.0, caseless@~0.12.0: version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + resolved "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz" integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== catering@^2.0.0, catering@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/catering/-/catering-2.1.1.tgz#66acba06ed5ee28d5286133982a927de9a04b510" - integrity sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w== + version "2.1.0" + resolved "https://registry.npmjs.org/catering/-/catering-2.1.0.tgz" + integrity sha512-M5imwzQn6y+ODBfgi+cfgZv2hIUI6oYU/0f35Mdb1ujGeqeoI5tOnl9Q13DTH7LW+7er+NYq8stNOKZD/Z3U/A== + dependencies: + queue-tick "^1.0.0" cbor@^5.1.0, cbor@^5.2.0: version "5.2.0" - resolved "https://registry.yarnpkg.com/cbor/-/cbor-5.2.0.tgz#4cca67783ccd6de7b50ab4ed62636712f287a67c" + resolved "https://registry.npmjs.org/cbor/-/cbor-5.2.0.tgz" integrity sha512-5IMhi9e1QU76ppa5/ajP1BmMWZ2FHkhAhjeVKQ/EFCgYSEaeVaoGtL7cxJskf9oCCk+XjzaIdc3IuU/dbA/o2A== dependencies: bignumber.js "^9.0.1" @@ -3676,28 +4111,28 @@ cbor@^5.1.0, cbor@^5.2.0: cbor@^8.1.0: version "8.1.0" - resolved "https://registry.yarnpkg.com/cbor/-/cbor-8.1.0.tgz#cfc56437e770b73417a2ecbfc9caf6b771af60d5" + resolved "https://registry.npmjs.org/cbor/-/cbor-8.1.0.tgz" integrity sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg== dependencies: nofilter "^3.1.0" cbor@^9.0.0: version "9.0.1" - resolved "https://registry.yarnpkg.com/cbor/-/cbor-9.0.1.tgz#b16e393d4948d44758cd54ac6151379d443b37ae" + resolved "https://registry.npmjs.org/cbor/-/cbor-9.0.1.tgz" integrity sha512-/TQOWyamDxvVIv+DY9cOLNuABkoyz8K/F3QE56539pGVYohx0+MEA1f4lChFTX79dBTBS7R1PF6ovH7G+VtBfQ== dependencies: nofilter "^3.1.0" chai-as-promised@^7.1.1: version "7.1.1" - resolved "https://registry.yarnpkg.com/chai-as-promised/-/chai-as-promised-7.1.1.tgz#08645d825deb8696ee61725dbf590c012eb00ca0" + resolved "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz" integrity sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA== dependencies: check-error "^1.0.2" chai@^4.3.7: version "4.3.7" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51" + resolved "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz" integrity sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A== dependencies: assertion-error "^1.1.0" @@ -3710,7 +4145,7 @@ chai@^4.3.7: chalk@^2.4.2: version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies: ansi-styles "^3.2.1" @@ -3719,7 +4154,7 @@ chalk@^2.4.2: chalk@^4.1.0, chalk@^4.1.2: version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== dependencies: ansi-styles "^4.1.0" @@ -3727,7 +4162,7 @@ chalk@^4.1.0, chalk@^4.1.2: change-case@3.0.2: version "3.0.2" - resolved "https://registry.yarnpkg.com/change-case/-/change-case-3.0.2.tgz#fd48746cce02f03f0a672577d1d3a8dc2eceb037" + resolved "https://registry.npmjs.org/change-case/-/change-case-3.0.2.tgz" integrity sha512-Mww+SLF6MZ0U6kdg11algyKd5BARbyM4TbFBepwowYSR5ClfQGCGtxNXgykpN0uF/bstWeaGDT4JWaDh8zWAHA== dependencies: camel-case "^3.0.0" @@ -3751,24 +4186,24 @@ change-case@3.0.2: "charenc@>= 0.0.1": version "0.0.2" - resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" + resolved "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz" integrity sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA== check-error@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" + resolved "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz" integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA== checkpoint-store@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/checkpoint-store/-/checkpoint-store-1.1.0.tgz#04e4cb516b91433893581e6d4601a78e9552ea06" + resolved "https://registry.npmjs.org/checkpoint-store/-/checkpoint-store-1.1.0.tgz" integrity sha512-J/NdY2WvIx654cc6LWSq/IYFFCUf75fFTgwzFnmbqyORH4MwgiQCgswLLKBGzmsyTI5V7i5bp/So6sMbDWhedg== dependencies: functional-red-black-tree "^1.0.1" chokidar@3.3.0: version "3.3.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.0.tgz#12c0714668c55800f659e262d4962a97faf554a6" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz" integrity sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A== dependencies: anymatch "~3.1.1" @@ -3783,7 +4218,7 @@ chokidar@3.3.0: chokidar@3.5.3, chokidar@^3.4.0: version "3.5.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz" integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== dependencies: anymatch "~3.1.2" @@ -3798,17 +4233,22 @@ chokidar@3.5.3, chokidar@^3.4.0: chownr@^1.1.4: version "1.1.4" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + resolved "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== ci-info@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + resolved "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== +ci-info@^3.7.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" + integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== + cids@^0.7.1: version "0.7.5" - resolved "https://registry.yarnpkg.com/cids/-/cids-0.7.5.tgz#60a08138a99bfb69b6be4ceb63bfef7a396b28b2" + resolved "https://registry.npmjs.org/cids/-/cids-0.7.5.tgz" integrity sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA== dependencies: buffer "^5.5.0" @@ -3819,7 +4259,7 @@ cids@^0.7.1: cids@^1.0.0, cids@^1.1.4, cids@^1.1.5: version "1.1.9" - resolved "https://registry.yarnpkg.com/cids/-/cids-1.1.9.tgz#402c26db5c07059377bcd6fb82f2a24e7f2f4a4f" + resolved "https://registry.npmjs.org/cids/-/cids-1.1.9.tgz" integrity sha512-l11hWRfugIcbGuTZwAM5PwpjPPjyb6UZOGwlHSnOBV5o07XhQ4gNpBN67FbODvpjyHtd+0Xs6KNvUcGBiDRsdg== dependencies: multibase "^4.0.1" @@ -3828,38 +4268,39 @@ cids@^1.0.0, cids@^1.1.4, cids@^1.1.5: uint8arrays "^3.0.0" cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + version "1.0.7" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.7.tgz#bd094bfef42634ccfd9e13b9fc73274997111e39" + integrity sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA== dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" + inherits "^2.0.4" + safe-buffer "^5.2.1" + to-buffer "^1.2.2" class-is@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/class-is/-/class-is-1.1.0.tgz#9d3c0fba0440d211d843cec3dedfa48055005825" + resolved "https://registry.npmjs.org/class-is/-/class-is-1.1.0.tgz" integrity sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw== clean-stack@^2.0.0: version "2.2.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + resolved "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== cli-boxes@^2.2.1: version "2.2.1" - resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" + resolved "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz" integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== cli-cursor@^3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz" integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== dependencies: restore-cursor "^3.1.0" cli-table3@^0.5.0: version "0.5.1" - resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202" + resolved "https://registry.npmjs.org/cli-table3/-/cli-table3-0.5.1.tgz" integrity sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw== dependencies: object-assign "^4.1.0" @@ -3878,7 +4319,7 @@ cliui@^3.2.0: cliui@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + resolved "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz" integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== dependencies: string-width "^3.1.0" @@ -3887,21 +4328,21 @@ cliui@^5.0.0: cliui@^7.0.2: version "7.0.4" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + resolved "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz" integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== dependencies: string-width "^4.2.0" strip-ansi "^6.0.0" wrap-ansi "^7.0.0" -cliui@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" - integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== +cliui@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-9.0.1.tgz#6f7890f386f6f1f79953adc1f78dec46fcc2d291" + integrity sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w== dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.1" - wrap-ansi "^7.0.0" + string-width "^7.2.0" + strip-ansi "^7.1.0" + wrap-ansi "^9.0.0" clone-buffer@1.0.0: version "1.0.0" @@ -3910,14 +4351,14 @@ clone-buffer@1.0.0: clone-response@^1.0.2: version "1.0.3" - resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.3.tgz#af2032aa47816399cf5f0a1d0db902f517abb8c3" + resolved "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz" integrity sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA== dependencies: mimic-response "^1.0.0" clone@^2.0.0, clone@^2.1.1: version "2.1.2" - resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + resolved "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz" integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w== code-point-at@^1.0.0: @@ -3927,48 +4368,48 @@ code-point-at@^1.0.0: color-convert@^1.9.0: version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" color-convert@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== dependencies: color-name "~1.1.4" color-name@1.1.3: version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== color-name@~1.1.4: version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== colors@1.4.0, colors@^1.1.2: version "1.4.0" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" + resolved "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== dependencies: delayed-stream "~1.0.0" command-exists@^1.2.8: version "1.2.9" - resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" + resolved "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz" integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== command-line-args@^5.1.1: version "5.2.1" - resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.2.1.tgz#c44c32e437a57d7c51157696893c5909e9cec42e" + resolved "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz" integrity sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg== dependencies: array-back "^3.1.0" @@ -3978,7 +4419,7 @@ command-line-args@^5.1.1: command-line-usage@^6.1.0: version "6.1.3" - resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-6.1.3.tgz#428fa5acde6a838779dfa30e44686f4b6761d957" + resolved "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.3.tgz" integrity sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw== dependencies: array-back "^4.0.2" @@ -3988,27 +4429,27 @@ command-line-usage@^6.1.0: commander@3.0.2: version "3.0.2" - resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" + resolved "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz" integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== commander@^2.15.0, commander@^2.20.3: version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== compare-versions@^6.0.0: version "6.1.0" - resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-6.1.0.tgz#3f2131e3ae93577df111dba133e6db876ffe127a" + resolved "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.0.tgz" integrity sha512-LNZQXhqUvqUTotpZ00qLSaify3b4VFD588aRr8MKFw4CMUr98ytzCW5wDH5qx/DEY5kCDXcbcRuCqL0szEf2tg== concat-map@0.0.1: version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== concat-stream@^1.6.0, concat-stream@^1.6.2: version "1.6.2" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + resolved "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz" integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== dependencies: buffer-from "^1.0.0" @@ -4039,7 +4480,7 @@ console-control-strings@^1.0.0, console-control-strings@~1.1.0: constant-case@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/constant-case/-/constant-case-2.0.0.tgz#4175764d389d3fa9c8ecd29186ed6005243b6a46" + resolved "https://registry.npmjs.org/constant-case/-/constant-case-2.0.0.tgz" integrity sha512-eS0N9WwmjTqrOmR3o83F5vW8Z+9R1HnVz3xmzT2PMFug9ly+Au/fxRWlEBSb6LcZwspSsEn9Xs1uw9YgzAg1EQ== dependencies: snake-case "^2.1.0" @@ -4047,14 +4488,14 @@ constant-case@^2.0.0: content-disposition@0.5.4: version "0.5.4" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz" integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== dependencies: safe-buffer "5.2.1" content-hash@^2.5.2: version "2.5.2" - resolved "https://registry.yarnpkg.com/content-hash/-/content-hash-2.5.2.tgz#bbc2655e7c21f14fd3bfc7b7d4bfe6e454c9e211" + resolved "https://registry.npmjs.org/content-hash/-/content-hash-2.5.2.tgz" integrity sha512-FvIQKy0S1JaWV10sMsA7TRx8bpU+pqPkhbsfvOJAdjRXvYxEckAwQWGwtRjiaJfh+E0DvcWUGqcdjwMGFjsSdw== dependencies: cids "^0.7.1" @@ -4063,49 +4504,44 @@ content-hash@^2.5.2: content-type@~1.0.4, content-type@~1.0.5: version "1.0.5" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + resolved "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz" integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== cookie-signature@1.0.6: version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + resolved "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== -cookie@0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" - integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== +cookie@0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.1.tgz#2f73c42142d5d5cf71310a74fc4ae61670e5dbc9" + integrity sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w== cookie@^0.4.1: version "0.4.2" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz" integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== cookiejar@^2.1.1: version "2.1.4" - resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.4.tgz#ee669c1fea2cf42dc31585469d193fef0d65771b" + resolved "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz" integrity sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw== core-js-compat@^3.31.0: version "3.32.0" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.32.0.tgz#f41574b6893ab15ddb0ac1693681bd56c8550a90" + resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.32.0.tgz" integrity sha512-7a9a3D1k4UCVKnLhrgALyFcP7YCsLOQIxPd0dKjf/6GuPcgyiGP70ewWdCGrSK7evyhymi0qO4EqCmSJofDeYw== dependencies: browserslist "^4.21.9" -core-util-is@1.0.2: +core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== -core-util-is@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" - integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== - cors@^2.8.1, cors@^2.8.5: version "2.8.5" - resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" + resolved "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz" integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== dependencies: object-assign "^4" @@ -4113,12 +4549,12 @@ cors@^2.8.1, cors@^2.8.5: crc-32@^1.2.0: version "1.2.2" - resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" + resolved "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz" integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== create-ecdh@^4.0.0: version "4.0.4" - resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" + resolved "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz" integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== dependencies: bn.js "^4.1.0" @@ -4126,7 +4562,7 @@ create-ecdh@^4.0.0: create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + resolved "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz" integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== dependencies: cipher-base "^1.0.1" @@ -4135,9 +4571,9 @@ create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: ripemd160 "^2.0.1" sha.js "^2.4.0" -create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: +create-hmac@^1.1.0, create-hmac@^1.1.7: version "1.1.7" - resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + resolved "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz" integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== dependencies: cipher-base "^1.0.3" @@ -4149,44 +4585,42 @@ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: create-require@^1.1.0: version "1.1.1" - resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== cross-fetch@^2.1.0, cross-fetch@^2.1.1: version "2.2.6" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-2.2.6.tgz#2ef0bb39a24ac034787965c457368a28730e220a" + resolved "https://registry.npmjs.org/cross-fetch/-/cross-fetch-2.2.6.tgz" integrity sha512-9JZz+vXCmfKUZ68zAptS7k4Nu8e2qcibe7WVZYps7sAgk5R8GYTc+T1WR0v1rlP9HxgARmOX1UTIJZFytajpNA== dependencies: node-fetch "^2.6.7" whatwg-fetch "^2.0.4" cross-fetch@^3.1.4: - version "3.1.8" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82" - integrity sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg== + version "3.2.0" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.2.0.tgz#34e9192f53bc757d6614304d9e5e6fb4edb782e3" + integrity sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q== dependencies: - node-fetch "^2.6.12" + node-fetch "^2.7.0" -cross-spawn@^6.0.5: - version "6.0.6" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.6.tgz#30d0efa0712ddb7eb5a76e1e8721bffafa6b5d57" - integrity sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw== +cross-spawn@^7.0.3: + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" "crypt@>= 0.0.1": version "0.0.2" - resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" + resolved "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz" integrity sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow== crypto-addr-codec@^0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/crypto-addr-codec/-/crypto-addr-codec-0.1.7.tgz#e16cea892730178fe25a38f6d15b680cab3124ae" - integrity sha512-X4hzfBzNhy4mAc3UpiXEC/L0jo5E8wAa9unsnA8nNXYzXjCcGk83hfC5avJWCSGT8V91xMnAS9AKMHmjw5+XCg== + version "0.1.8" + resolved "https://registry.yarnpkg.com/crypto-addr-codec/-/crypto-addr-codec-0.1.8.tgz#45c4b24e2ebce8e24a54536ee0ca25b65787b016" + integrity sha512-GqAK90iLLgP3FvhNmHbpT3wR6dEdaM8hZyZtLX29SPardh3OA13RFLHDR6sntGCgRWOfiHqW6sIyohpNqOtV/g== dependencies: base-x "^3.0.8" big-integer "1.6.36" @@ -4198,7 +4632,7 @@ crypto-addr-codec@^0.1.7: crypto-browserify@3.12.0: version "3.12.0" - resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + resolved "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz" integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== dependencies: browserify-cipher "^1.0.0" @@ -4220,7 +4654,7 @@ cssfilter@0.0.10: d@1, d@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" + resolved "https://registry.npmjs.org/d/-/d-1.0.1.tgz" integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== dependencies: es5-ext "^0.10.50" @@ -4228,7 +4662,7 @@ d@1, d@^1.0.1: dashdash@^1.12.0: version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + resolved "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz" integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== dependencies: assert-plus "^1.0.0" @@ -4240,7 +4674,7 @@ dataloader@2.1.0: death@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/death/-/death-1.1.0.tgz#01aa9c401edd92750514470b8266390c66c67318" + resolved "https://registry.npmjs.org/death/-/death-1.1.0.tgz" integrity sha512-vsV6S4KVHvTGxbEcij7hkWRv0It+sGGWVOM67dQde/o5Xjnr+KmLjxWJii2uEObIrt1CcM9w0Yaovx+iOlIL+w== debounce-fn@^4.0.0: @@ -4252,7 +4686,7 @@ debounce-fn@^4.0.0: debug@2.6.9, debug@^2.2.0: version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" @@ -4266,28 +4700,28 @@ debug@3.1.0: debug@3.2.6: version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + resolved "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz" integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== dependencies: ms "^2.1.1" debug@4, debug@4.3.4, debug@^4.1.1, debug@^4.3.1, debug@^4.3.3: version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" debug@4.3.3: version "4.3.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz" integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== dependencies: ms "2.1.2" debug@^3.1.0, debug@^3.2.6: version "3.2.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + resolved "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== dependencies: ms "^2.1.1" @@ -4299,31 +4733,31 @@ decamelize@^1.1.1, decamelize@^1.2.0: decamelize@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + resolved "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz" integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== decode-uri-component@^0.2.0: version "0.2.2" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" + resolved "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz" integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== decompress-response@^3.3.0: version "3.3.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + resolved "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz" integrity sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA== dependencies: mimic-response "^1.0.0" decompress-response@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" + resolved "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz" integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== dependencies: mimic-response "^3.1.0" deep-eql@^4.0.1, deep-eql@^4.1.2: version "4.1.3" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" + resolved "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz" integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== dependencies: type-detect "^4.0.0" @@ -4335,22 +4769,22 @@ deep-extend@^0.6.0, deep-extend@~0.6.0: deep-is@~0.1.3: version "0.1.4" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== defer-to-connect@^1.0.1: version "1.1.3" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" + resolved "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz" integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== defer-to-connect@^2.0.0, defer-to-connect@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" + resolved "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz" integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== deferred-leveldown@~1.2.1: version "1.2.2" - resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz#3acd2e0b75d1669924bc0a4b642851131173e1eb" + resolved "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz" integrity sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA== dependencies: abstract-leveldown "~2.6.0" @@ -4363,9 +4797,18 @@ deferred-leveldown@~5.3.0: abstract-leveldown "~6.2.1" inherits "^2.0.3" +define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + define-properties@^1.1.2, define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5" + resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz" integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA== dependencies: has-property-descriptors "^1.0.0" @@ -4373,12 +4816,12 @@ define-properties@^1.1.2, define-properties@^1.1.3, define-properties@^1.1.4, de delay@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/delay/-/delay-5.0.0.tgz#137045ef1b96e5071060dd5be60bf9334436bd1d" + resolved "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz" integrity sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw== delayed-stream@~1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== delegates@^1.0.0: @@ -4388,25 +4831,25 @@ delegates@^1.0.0: delimit-stream@0.1.0: version "0.1.0" - resolved "https://registry.yarnpkg.com/delimit-stream/-/delimit-stream-0.1.0.tgz#9b8319477c0e5f8aeb3ce357ae305fc25ea1cd2b" + resolved "https://registry.npmjs.org/delimit-stream/-/delimit-stream-0.1.0.tgz" integrity sha512-a02fiQ7poS5CnjiJBAsjGLPp5EwVoGHNeu9sziBd9huppRfsAFIpv5zNLv0V1gbop53ilngAf5Kf331AwcoRBQ== -depd@2.0.0: +depd@2.0.0, depd@~2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + resolved "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== des.js@^1.0.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.1.0.tgz#1d37f5766f3bbff4ee9638e871a8768c173b81da" + resolved "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz" integrity sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg== dependencies: inherits "^2.0.1" minimalistic-assert "^1.0.0" -destroy@1.2.0: +destroy@1.2.0, destroy@~1.2.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + resolved "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz" integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== detect-libc@^1.0.2: @@ -4416,7 +4859,7 @@ detect-libc@^1.0.2: detect-port@^1.3.0: version "1.5.1" - resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.5.1.tgz#451ca9b6eaf20451acb0799b8ab40dff7718727b" + resolved "https://registry.npmjs.org/detect-port/-/detect-port-1.5.1.tgz" integrity sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ== dependencies: address "^1.0.1" @@ -4424,22 +4867,22 @@ detect-port@^1.3.0: diff@3.5.0: version "3.5.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + resolved "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz" integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== diff@5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" + resolved "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz" integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== diff@^4.0.1: version "4.0.2" - resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== diffie-hellman@^5.0.0: version "5.0.3" - resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + resolved "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz" integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== dependencies: bn.js "^4.1.0" @@ -4448,21 +4891,21 @@ diffie-hellman@^5.0.0: difflib@^0.2.4: version "0.2.4" - resolved "https://registry.yarnpkg.com/difflib/-/difflib-0.2.4.tgz#b5e30361a6db023176d562892db85940a718f47e" + resolved "https://registry.npmjs.org/difflib/-/difflib-0.2.4.tgz" integrity sha512-9YVwmMb0wQHQNr5J9m6BSj6fk4pfGITGQOOs+D9Fl+INODWFOfvhIU1hNv6GgR1RBoC/9NJcwu77zShxV0kT7w== dependencies: heap ">= 0.2.0" dir-glob@^3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz" integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== dependencies: path-type "^4.0.0" dns-over-http-resolver@^1.0.0: version "1.2.3" - resolved "https://registry.yarnpkg.com/dns-over-http-resolver/-/dns-over-http-resolver-1.2.3.tgz#194d5e140a42153f55bb79ac5a64dd2768c36af9" + resolved "https://registry.npmjs.org/dns-over-http-resolver/-/dns-over-http-resolver-1.2.3.tgz" integrity sha512-miDiVSI6KSNbi4SVifzO/reD8rMnxgrlnkrlkugOLQpWQTe2qMdHsZp5DmfKjxNE+/T3VAAYLQUZMv9SMr6+AA== dependencies: debug "^4.3.1" @@ -4471,12 +4914,12 @@ dns-over-http-resolver@^1.0.0: dom-walk@^0.1.0: version "0.1.2" - resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84" + resolved "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz" integrity sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w== dot-case@^2.1.0: version "2.1.1" - resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-2.1.1.tgz#34dcf37f50a8e93c2b3bca8bb7fb9155c7da3bee" + resolved "https://registry.npmjs.org/dot-case/-/dot-case-2.1.1.tgz" integrity sha512-HnM6ZlFqcajLsyudHq7LeeLDr2rFAVYtDv/hV5qchQEidSck8j9OPUsXY9KwJv/lHMtYlX4DjRQqwFYa+0r8Ug== dependencies: no-case "^2.2.0" @@ -4493,14 +4936,23 @@ double-ended-queue@2.1.0-0: resolved "https://registry.yarnpkg.com/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz#103d3527fd31528f40188130c841efdd78264e5c" integrity sha512-+BNfZ+deCo8hMNpDqDnvT+c0XpJ5cUa6mqYq89bho2Ifze4URTqRkcwR399hWoTrTkbZ/XJYDgP6rc7pRgffEQ== +dunder-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" + integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-errors "^1.3.0" + gopd "^1.2.0" + duplexer3@^0.1.4: version "0.1.5" - resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.5.tgz#0b5e4d7bad5de8901ea4440624c8e1d20099217e" + resolved "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz" integrity sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA== ecc-jsbn@~0.1.1: version "0.1.2" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + resolved "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz" integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw== dependencies: jsbn "~0.1.0" @@ -4508,7 +4960,7 @@ ecc-jsbn@~0.1.1: ecurve@^1.0.6: version "1.0.6" - resolved "https://registry.yarnpkg.com/ecurve/-/ecurve-1.0.6.tgz#dfdabbb7149f8d8b78816be5a7d5b83fcf6de797" + resolved "https://registry.npmjs.org/ecurve/-/ecurve-1.0.6.tgz" integrity sha512-/BzEjNfiSuB7jIWKcS/z8FK9jNjmEWvUV2YZ4RLSmcDtP7Lq0m6FvDuSnJpBlDpGRpfRQeTLGLBI8H+kEv0r+w== dependencies: bigi "^1.1.0" @@ -4516,31 +4968,31 @@ ecurve@^1.0.6: ed2curve@^0.3.0: version "0.3.0" - resolved "https://registry.yarnpkg.com/ed2curve/-/ed2curve-0.3.0.tgz#322b575152a45305429d546b071823a93129a05d" + resolved "https://registry.npmjs.org/ed2curve/-/ed2curve-0.3.0.tgz" integrity sha512-8w2fmmq3hv9rCrcI7g9hms2pMunQr1JINfcjwR9tAyZqhtyaMN991lF/ZfHfr5tzZQ8c7y7aBgZbjfbd0fjFwQ== dependencies: tweetnacl "1.x.x" ee-first@1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== electron-fetch@^1.7.2: version "1.9.1" - resolved "https://registry.yarnpkg.com/electron-fetch/-/electron-fetch-1.9.1.tgz#e28bfe78d467de3f2dec884b1d72b8b05322f30f" + resolved "https://registry.npmjs.org/electron-fetch/-/electron-fetch-1.9.1.tgz" integrity sha512-M9qw6oUILGVrcENMSRRefE1MbHPIz0h79EKIeJWK9v563aT9Qkh8aEHPO1H5vi970wPirNY+jO9OpFoLiMsMGA== dependencies: encoding "^0.1.13" -electron-to-chromium@^1.4.477: - version "1.4.490" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.490.tgz#d99286f6e915667fa18ea4554def1aa60eb4d5f1" - integrity sha512-6s7NVJz+sATdYnIwhdshx/N/9O6rvMxmhVoDSDFdj6iA45gHR8EQje70+RYsF4GeB+k0IeNSBnP7yG9ZXJFr7A== +electron-to-chromium@^1.5.249: + version "1.5.259" + resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.259.tgz" + integrity sha512-I+oLXgpEJzD6Cwuwt1gYjxsDmu/S/Kd41mmLA3O+/uH2pFRO/DvOjUyGozL8j3KeLV6WyZ7ssPwELMsXCcsJAQ== elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3, elliptic@^6.5.4: version "6.5.4" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + resolved "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz" integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== dependencies: bn.js "^4.11.9" @@ -4551,9 +5003,22 @@ elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3, elliptic@^6.5 minimalistic-assert "^1.0.1" minimalistic-crypto-utils "^1.0.1" +elliptic@6.6.1: + version "6.6.1" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.1.tgz#3b8ffb02670bf69e382c7f65bf524c97c5405c06" + integrity sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + emittery@0.10.0: version "0.10.0" - resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.10.0.tgz#bb373c660a9d421bb44706ec4967ed50c02a8026" + resolved "https://registry.npmjs.org/emittery/-/emittery-0.10.0.tgz" integrity sha512-AGvFfs+d0JKCJQ4o01ASQLGPmSCxgfU9RFXvzPvZdjKK8oscynksuJhWrSTSw7j7Ep/sZct5b5ZhYCi8S/t0HQ== emittery@^0.4.1: @@ -4561,21 +5026,31 @@ emittery@^0.4.1: resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.4.1.tgz#abe9d3297389ba424ac87e53d1c701962ce7433d" integrity sha512-r4eRSeStEGf6M5SKdrQhhLK5bOwOBxQhIE3YSTnZE3GpKiLfnnhE+tPtrJE79+eDJgm39BM6LSoI8SCx4HbwlQ== +emoji-regex@^10.3.0: + version "10.6.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.6.0.tgz#bf3d6e8f7f8fd22a65d9703475bc0147357a6b0d" + integrity sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A== + emoji-regex@^7.0.1: version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz" integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== emoji-regex@^8.0.0: version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== encodeurl@~1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz" integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== +encodeurl@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" + integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== + encoding-down@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/encoding-down/-/encoding-down-6.3.0.tgz#b1c4eb0e1728c146ecaef8e32963c549e76d082b" @@ -4588,14 +5063,14 @@ encoding-down@^6.3.0: encoding@^0.1.11, encoding@^0.1.13: version "0.1.13" - resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" + resolved "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz" integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== dependencies: iconv-lite "^0.6.2" end-of-stream@^1.1.0: version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== dependencies: once "^1.4.0" @@ -4609,7 +5084,7 @@ end-stream@~0.1.0: enquirer@^2.3.0: version "2.4.1" - resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.4.1.tgz#93334b3fbd74fc7097b224ab4a8fb7e40bf4ae56" + resolved "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz" integrity sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ== dependencies: ansi-colors "^4.1.1" @@ -4622,31 +5097,31 @@ env-paths@^2.2.0, env-paths@^2.2.1: err-code@^2.0.0, err-code@^2.0.3: version "2.0.3" - resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" + resolved "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz" integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA== err-code@^3.0.0, err-code@^3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/err-code/-/err-code-3.0.1.tgz#a444c7b992705f2b120ee320b09972eef331c920" + resolved "https://registry.npmjs.org/err-code/-/err-code-3.0.1.tgz" integrity sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA== errno@~0.1.1: version "0.1.8" - resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" + resolved "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz" integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== dependencies: prr "~1.0.1" error-ex@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + version "1.3.4" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.4.tgz#b3a8d8bb6f92eecc1629e3e27d3c8607a8a32414" + integrity sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ== dependencies: is-arrayish "^0.2.1" es-abstract@^1.19.0, es-abstract@^1.20.4, es-abstract@^1.21.2: version "1.22.1" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.1.tgz#8b4e5fc5cefd7f1660f0f8e1a52900dfbc9d9ccc" + resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz" integrity sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw== dependencies: array-buffer-byte-length "^1.0.0" @@ -4691,12 +5166,29 @@ es-abstract@^1.19.0, es-abstract@^1.20.4, es-abstract@^1.21.2: es-array-method-boxes-properly@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" + resolved "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz" integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== +es-define-property@^1.0.0, es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" + integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== + dependencies: + es-errors "^1.3.0" + es-set-tostringtag@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" + resolved "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz" integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== dependencies: get-intrinsic "^1.1.3" @@ -4705,7 +5197,7 @@ es-set-tostringtag@^2.0.1: es-to-primitive@^1.2.1: version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + resolved "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz" integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== dependencies: is-callable "^1.1.4" @@ -4714,7 +5206,7 @@ es-to-primitive@^1.2.1: es5-ext@^0.10.35, es5-ext@^0.10.50, es5-ext@^0.10.62, es5-ext@~0.10.14: version "0.10.63" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.63.tgz#9c222a63b6a332ac80b1e373b426af723b895bd6" + resolved "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.63.tgz" integrity sha512-hUCZd2Byj/mNKjfP9jXrdVZ62B8KuA/VoK7X8nUh5qT+AxDmcbvZz041oDVZdbIN1qW6XY9VDNwzkvKnZvK2TQ== dependencies: es6-iterator "^2.0.3" @@ -4724,7 +5216,7 @@ es5-ext@^0.10.35, es5-ext@^0.10.50, es5-ext@^0.10.62, es5-ext@~0.10.14: es6-iterator@^2.0.3: version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + resolved "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz" integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g== dependencies: d "1" @@ -4738,35 +5230,35 @@ es6-promise@^4.2.8: es6-symbol@^3.1.1, es6-symbol@^3.1.3: version "3.1.3" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" + resolved "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz" integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== dependencies: d "^1.0.1" ext "^1.1.2" -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== +escalade@^3.1.1, escalade@^3.2.0: + version "3.2.0" + resolved "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== escape-html@~1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== escape-string-regexp@4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== escodegen@1.8.x: version "1.8.1" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" + resolved "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz" integrity sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A== dependencies: esprima "^2.7.1" @@ -4778,7 +5270,7 @@ escodegen@1.8.x: esniff@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/esniff/-/esniff-2.0.1.tgz#a4d4b43a5c71c7ec51c51098c1d8a29081f9b308" + resolved "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz" integrity sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg== dependencies: d "^1.0.1" @@ -4788,32 +5280,32 @@ esniff@^2.0.1: esprima@2.7.x, esprima@^2.7.1: version "2.7.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" + resolved "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz" integrity sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A== esprima@^4.0.0: version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== estraverse@^1.9.1: version "1.9.3" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz" integrity sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA== esutils@^2.0.2: version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== etag@~1.8.1: version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== eth-block-tracker@^4.4.2: version "4.4.3" - resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-4.4.3.tgz#766a0a0eb4a52c867a28328e9ae21353812cf626" + resolved "https://registry.npmjs.org/eth-block-tracker/-/eth-block-tracker-4.4.3.tgz" integrity sha512-A8tG4Z4iNg4mw5tP1Vung9N9IjgMNqpiMoJ/FouSFwNCGHv2X0mmOYwtQOJzki6XN7r7Tyo01S29p7b224I4jw== dependencies: "@babel/plugin-transform-runtime" "^7.5.5" @@ -4825,7 +5317,7 @@ eth-block-tracker@^4.4.2: eth-ens-namehash@2.0.8, eth-ens-namehash@^2.0.8: version "2.0.8" - resolved "https://registry.yarnpkg.com/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz#229ac46eca86d52e0c991e7cb2aef83ff0f68bcf" + resolved "https://registry.npmjs.org/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz" integrity sha512-VWEI1+KJfz4Km//dadyvBBoBeSQ0MHTXPvr8UIXiLW6IanxvAV+DmlZAijZwAyggqGUfwQBeHf7tc9wzc1piSw== dependencies: idna-uts46-hx "^2.3.1" @@ -4833,7 +5325,7 @@ eth-ens-namehash@2.0.8, eth-ens-namehash@^2.0.8: eth-gas-reporter@^0.2.25: version "0.2.25" - resolved "https://registry.yarnpkg.com/eth-gas-reporter/-/eth-gas-reporter-0.2.25.tgz#546dfa946c1acee93cb1a94c2a1162292d6ff566" + resolved "https://registry.npmjs.org/eth-gas-reporter/-/eth-gas-reporter-0.2.25.tgz" integrity sha512-1fRgyE4xUB8SoqLgN3eDfpDfwEfRxh2Sz1b7wzFbyQA+9TekMmvSjjoRu9SKcSVyK+vLkLIsVbJDsTWjw195OQ== dependencies: "@ethersproject/abi" "^5.0.0-beta.146" @@ -4854,21 +5346,21 @@ eth-gas-reporter@^0.2.25: eth-json-rpc-errors@^1.0.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/eth-json-rpc-errors/-/eth-json-rpc-errors-1.1.1.tgz#148377ef55155585981c21ff574a8937f9d6991f" + resolved "https://registry.npmjs.org/eth-json-rpc-errors/-/eth-json-rpc-errors-1.1.1.tgz" integrity sha512-WT5shJ5KfNqHi9jOZD+ID8I1kuYWNrigtZat7GOQkvwo99f8SzAVaEcWhJUv656WiZOAg3P1RiJQANtUmDmbIg== dependencies: fast-safe-stringify "^2.0.6" eth-json-rpc-errors@^2.0.2: version "2.0.2" - resolved "https://registry.yarnpkg.com/eth-json-rpc-errors/-/eth-json-rpc-errors-2.0.2.tgz#c1965de0301fe941c058e928bebaba2e1285e3c4" + resolved "https://registry.npmjs.org/eth-json-rpc-errors/-/eth-json-rpc-errors-2.0.2.tgz" integrity sha512-uBCRM2w2ewusRHGxN8JhcuOb2RN3ueAOYH/0BhqdFmQkZx5lj5+fLKTz0mIVOzd4FG5/kUksCzCD7eTEim6gaA== dependencies: fast-safe-stringify "^2.0.6" eth-lib@0.2.8: version "0.2.8" - resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.8.tgz#b194058bef4b220ad12ea497431d6cb6aa0623c8" + resolved "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz" integrity sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw== dependencies: bn.js "^4.11.6" @@ -4877,7 +5369,7 @@ eth-lib@0.2.8: eth-lib@^0.1.26: version "0.1.29" - resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.1.29.tgz#0c11f5060d42da9f931eab6199084734f4dbd1d9" + resolved "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.29.tgz" integrity sha512-bfttrr3/7gG4E02HoWTDUcDDslN003OlOoBxk9virpAZQ1ja/jDgwkWB8QfJF7ojuEowrqy+lzp9VcJG7/k5bQ== dependencies: bn.js "^4.11.6" @@ -4889,7 +5381,7 @@ eth-lib@^0.1.26: eth-query@^2.1.0, eth-query@^2.1.2: version "2.1.2" - resolved "https://registry.yarnpkg.com/eth-query/-/eth-query-2.1.2.tgz#d6741d9000106b51510c72db92d6365456a6da5e" + resolved "https://registry.npmjs.org/eth-query/-/eth-query-2.1.2.tgz" integrity sha512-srES0ZcvwkR/wd5OQBRA1bIJMww1skfGS0s8wlwK3/oNP4+wnds60krvu5R1QbpRQjMmpG5OMIWro5s7gvDPsA== dependencies: json-rpc-random-id "^1.0.0" @@ -4897,14 +5389,14 @@ eth-query@^2.1.0, eth-query@^2.1.2: eth-rpc-errors@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/eth-rpc-errors/-/eth-rpc-errors-3.0.0.tgz#d7b22653c70dbf9defd4ef490fd08fe70608ca10" + resolved "https://registry.npmjs.org/eth-rpc-errors/-/eth-rpc-errors-3.0.0.tgz" integrity sha512-iPPNHPrLwUlR9xCSYm7HHQjWBasor3+KZfRvwEWxMz3ca0yqnlBeJrnyphkGIXZ4J7AMAaOLmwy4AWhnxOiLxg== dependencies: fast-safe-stringify "^2.0.6" eth-sig-util@^3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-3.0.1.tgz#8753297c83a3f58346bd13547b59c4b2cd110c96" + resolved "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-3.0.1.tgz" integrity sha512-0Us50HiGGvZgjtWTyAI/+qTzYPMLy5Q451D0Xy68bxq1QMWdoOddDwGvsqcFT27uohKgalM9z/yxplyt+mY2iQ== dependencies: ethereumjs-abi "^0.6.8" @@ -4914,24 +5406,24 @@ eth-sig-util@^3.0.1: ethereum-bloom-filters@^1.0.6: version "1.0.10" - resolved "https://registry.yarnpkg.com/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz#3ca07f4aed698e75bd134584850260246a5fed8a" + resolved "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz" integrity sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA== dependencies: js-sha3 "^0.8.0" ethereum-common@0.2.0: version "0.2.0" - resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.2.0.tgz#13bf966131cce1eeade62a1b434249bb4cb120ca" + resolved "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz" integrity sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA== ethereum-common@^0.0.18: version "0.0.18" - resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" + resolved "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz" integrity sha512-EoltVQTRNg2Uy4o84qpa2aXymXDJhxm7eos/ACOg0DG4baAbMjhbdAEsx9GeE8sC3XCxnYvrrzZDH8D8MtA2iQ== ethereum-cryptography@0.1.3, ethereum-cryptography@^0.1.3: version "0.1.3" - resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191" + resolved "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz" integrity sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ== dependencies: "@types/pbkdf2" "^3.0.0" @@ -4952,7 +5444,7 @@ ethereum-cryptography@0.1.3, ethereum-cryptography@^0.1.3: ethereum-cryptography@^1.0.3: version "1.2.0" - resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz#5ccfa183e85fdaf9f9b299a79430c044268c9b3a" + resolved "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz" integrity sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw== dependencies: "@noble/hashes" "1.2.0" @@ -4960,14 +5452,24 @@ ethereum-cryptography@^1.0.3: "@scure/bip32" "1.1.5" "@scure/bip39" "1.1.1" +ethereum-cryptography@^2.0.0, ethereum-cryptography@^2.1.2: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz#58f2810f8e020aecb97de8c8c76147600b0b8ccf" + integrity sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg== + dependencies: + "@noble/curves" "1.4.2" + "@noble/hashes" "1.4.0" + "@scure/bip32" "1.4.0" + "@scure/bip39" "1.3.0" + ethereum-protocol@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/ethereum-protocol/-/ethereum-protocol-1.0.1.tgz#b7d68142f4105e0ae7b5e178cf42f8d4dc4b93cf" + resolved "https://registry.npmjs.org/ethereum-protocol/-/ethereum-protocol-1.0.1.tgz" integrity sha512-3KLX1mHuEsBW0dKG+c6EOJS1NBNqdCICvZW9sInmZTt5aY0oxmHVggYRE0lJu1tcnMD1K+AKHdLi6U43Awm1Vg== ethereumjs-abi@^0.6.8: version "0.6.8" - resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz#71bc152db099f70e62f108b7cdfca1b362c6fcae" + resolved "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz" integrity sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA== dependencies: bn.js "^4.11.8" @@ -4975,7 +5477,7 @@ ethereumjs-abi@^0.6.8: ethereumjs-account@^2.0.3: version "2.0.5" - resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz#eeafc62de544cb07b0ee44b10f572c9c49e00a84" + resolved "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz" integrity sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA== dependencies: ethereumjs-util "^5.0.0" @@ -4984,7 +5486,7 @@ ethereumjs-account@^2.0.3: ethereumjs-block@^1.2.2, ethereumjs-block@^1.6.0: version "1.7.1" - resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz#78b88e6cc56de29a6b4884ee75379b6860333c3f" + resolved "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz" integrity sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg== dependencies: async "^2.0.1" @@ -4995,7 +5497,7 @@ ethereumjs-block@^1.2.2, ethereumjs-block@^1.6.0: ethereumjs-block@~2.2.0: version "2.2.2" - resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz#c7654be7e22df489fda206139ecd63e2e9c04965" + resolved "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz" integrity sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg== dependencies: async "^2.0.1" @@ -5006,12 +5508,12 @@ ethereumjs-block@~2.2.0: ethereumjs-common@^1.1.0, ethereumjs-common@^1.5.0: version "1.5.2" - resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.5.2.tgz#2065dbe9214e850f2e955a80e650cb6999066979" + resolved "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-1.5.2.tgz" integrity sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA== ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.7: version "1.3.7" - resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz#88323a2d875b10549b8347e09f4862b546f3d89a" + resolved "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz" integrity sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA== dependencies: ethereum-common "^0.0.18" @@ -5019,7 +5521,7 @@ ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.7: ethereumjs-tx@^2.1.1: version "2.1.2" - resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz#5dfe7688bf177b45c9a23f86cf9104d47ea35fed" + resolved "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz" integrity sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw== dependencies: ethereumjs-common "^1.5.0" @@ -5027,7 +5529,7 @@ ethereumjs-tx@^2.1.1: ethereumjs-util@^5.0.0, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.2, ethereumjs-util@^5.1.5: version "5.2.1" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz#a833f0e5fca7e5b361384dc76301a721f537bf65" + resolved "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz" integrity sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ== dependencies: bn.js "^4.11.0" @@ -5040,7 +5542,7 @@ ethereumjs-util@^5.0.0, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.2, ethereum ethereumjs-util@^6.0.0, ethereumjs-util@^6.1.0, ethereumjs-util@^6.2.1: version "6.2.1" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz#fcb4e4dd5ceacb9d2305426ab1a5cd93e3163b69" + resolved "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz" integrity sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw== dependencies: "@types/bn.js" "^4.11.3" @@ -5053,7 +5555,7 @@ ethereumjs-util@^6.0.0, ethereumjs-util@^6.1.0, ethereumjs-util@^6.2.1: ethereumjs-util@^7.0.10, ethereumjs-util@^7.0.3, ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.1, ethereumjs-util@^7.1.2, ethereumjs-util@^7.1.4, ethereumjs-util@^7.1.5: version "7.1.5" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" + resolved "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz" integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== dependencies: "@types/bn.js" "^5.1.0" @@ -5064,7 +5566,7 @@ ethereumjs-util@^7.0.10, ethereumjs-util@^7.0.3, ethereumjs-util@^7.1.0, ethereu ethereumjs-vm@^2.3.4, ethereumjs-vm@^2.6.0: version "2.6.0" - resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.6.0.tgz#76243ed8de031b408793ac33907fb3407fe400c6" + resolved "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-2.6.0.tgz" integrity sha512-r/XIUik/ynGbxS3y+mvGnbOKnuLo40V5Mj1J25+HEO63aWYREIqvWeRO/hnROlMBE5WoniQmPmhiaN0ctiHaXw== dependencies: async "^2.1.2" @@ -5081,7 +5583,7 @@ ethereumjs-vm@^2.3.4, ethereumjs-vm@^2.6.0: ethereumjs-wallet@^1.0.1: version "1.0.2" - resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-1.0.2.tgz#2c000504b4c71e8f3782dabe1113d192522e99b6" + resolved "https://registry.npmjs.org/ethereumjs-wallet/-/ethereumjs-wallet-1.0.2.tgz" integrity sha512-CCWV4RESJgRdHIvFciVQFnCHfqyhXWchTPlkfp28Qc53ufs+doi5I/cV2+xeK9+qEo25XCWfP9MiL+WEPAZfdA== dependencies: aes-js "^3.1.2" @@ -5109,44 +5611,44 @@ ethers@^4.0.32, ethers@^4.0.40: xmlhttprequest "1.8.0" ethers@^5.0.13: - version "5.7.2" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" - integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== - dependencies: - "@ethersproject/abi" "5.7.0" - "@ethersproject/abstract-provider" "5.7.0" - "@ethersproject/abstract-signer" "5.7.0" - "@ethersproject/address" "5.7.0" - "@ethersproject/base64" "5.7.0" - "@ethersproject/basex" "5.7.0" - "@ethersproject/bignumber" "5.7.0" - "@ethersproject/bytes" "5.7.0" - "@ethersproject/constants" "5.7.0" - "@ethersproject/contracts" "5.7.0" - "@ethersproject/hash" "5.7.0" - "@ethersproject/hdnode" "5.7.0" - "@ethersproject/json-wallets" "5.7.0" - "@ethersproject/keccak256" "5.7.0" - "@ethersproject/logger" "5.7.0" - "@ethersproject/networks" "5.7.1" - "@ethersproject/pbkdf2" "5.7.0" - "@ethersproject/properties" "5.7.0" - "@ethersproject/providers" "5.7.2" - "@ethersproject/random" "5.7.0" - "@ethersproject/rlp" "5.7.0" - "@ethersproject/sha2" "5.7.0" - "@ethersproject/signing-key" "5.7.0" - "@ethersproject/solidity" "5.7.0" - "@ethersproject/strings" "5.7.0" - "@ethersproject/transactions" "5.7.0" - "@ethersproject/units" "5.7.0" - "@ethersproject/wallet" "5.7.0" - "@ethersproject/web" "5.7.1" - "@ethersproject/wordlists" "5.7.0" + version "5.8.0" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.8.0.tgz#97858dc4d4c74afce83ea7562fe9493cedb4d377" + integrity sha512-DUq+7fHrCg1aPDFCHx6UIPb3nmt2XMpM7Y/g2gLhsl3lIBqeAfOJIl1qEvRf2uq3BiKxmh6Fh5pfp2ieyek7Kg== + dependencies: + "@ethersproject/abi" "5.8.0" + "@ethersproject/abstract-provider" "5.8.0" + "@ethersproject/abstract-signer" "5.8.0" + "@ethersproject/address" "5.8.0" + "@ethersproject/base64" "5.8.0" + "@ethersproject/basex" "5.8.0" + "@ethersproject/bignumber" "5.8.0" + "@ethersproject/bytes" "5.8.0" + "@ethersproject/constants" "5.8.0" + "@ethersproject/contracts" "5.8.0" + "@ethersproject/hash" "5.8.0" + "@ethersproject/hdnode" "5.8.0" + "@ethersproject/json-wallets" "5.8.0" + "@ethersproject/keccak256" "5.8.0" + "@ethersproject/logger" "5.8.0" + "@ethersproject/networks" "5.8.0" + "@ethersproject/pbkdf2" "5.8.0" + "@ethersproject/properties" "5.8.0" + "@ethersproject/providers" "5.8.0" + "@ethersproject/random" "5.8.0" + "@ethersproject/rlp" "5.8.0" + "@ethersproject/sha2" "5.8.0" + "@ethersproject/signing-key" "5.8.0" + "@ethersproject/solidity" "5.8.0" + "@ethersproject/strings" "5.8.0" + "@ethersproject/transactions" "5.8.0" + "@ethersproject/units" "5.8.0" + "@ethersproject/wallet" "5.8.0" + "@ethersproject/web" "5.8.0" + "@ethersproject/wordlists" "5.8.0" ethers@^6.7.0: version "6.7.0" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.7.0.tgz#0f772c31a9450de28aa518b181c8cb269bbe7fd1" + resolved "https://registry.npmjs.org/ethers/-/ethers-6.7.0.tgz" integrity sha512-pxt5hK82RNwcTX2gOZP81t6qVPVspnkpeivwEgQuK9XUvbNtghBnT8GNIb/gPh+WnVSfi8cXC9XlfT8sqc6D6w== dependencies: "@adraffy/ens-normalize" "1.9.2" @@ -5159,7 +5661,7 @@ ethers@^6.7.0: ethjs-unit@0.1.6: version "0.1.6" - resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" + resolved "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz" integrity sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw== dependencies: bn.js "4.11.6" @@ -5167,7 +5669,7 @@ ethjs-unit@0.1.6: ethjs-util@0.1.6, ethjs-util@^0.1.3, ethjs-util@^0.1.6: version "0.1.6" - resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" + resolved "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz" integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== dependencies: is-hex-prefixed "1.0.0" @@ -5175,7 +5677,7 @@ ethjs-util@0.1.6, ethjs-util@^0.1.3, ethjs-util@^0.1.6: event-emitter@^0.3.5: version "0.3.5" - resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + resolved "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz" integrity sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA== dependencies: d "1" @@ -5183,73 +5685,73 @@ event-emitter@^0.3.5: event-iterator@^1.0.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/event-iterator/-/event-iterator-1.2.0.tgz#2e71dc6ca56f1cf8ebcb2b9be7fdfd10acabbb76" + resolved "https://registry.npmjs.org/event-iterator/-/event-iterator-1.2.0.tgz" integrity sha512-Daq7YUl0Mv1i4QEgzGQlz0jrx7hUFNyLGbiF+Ap7NCMCjDLCCnolyj6s0TAc6HmrBziO5rNVHsPwGMp7KdRPvw== event-iterator@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/event-iterator/-/event-iterator-2.0.0.tgz#10f06740cc1e9fd6bc575f334c2bc1ae9d2dbf62" + resolved "https://registry.npmjs.org/event-iterator/-/event-iterator-2.0.0.tgz" integrity sha512-KGft0ldl31BZVV//jj+IAIGCxkvvUkkON+ScH6zfoX+l+omX6001ggyRSpI0Io2Hlro0ThXotswCtfzS8UkIiQ== event-target-shim@^5.0.0: version "5.0.1" - resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + resolved "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz" integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== eventemitter3@4.0.4: version "4.0.4" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" + resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz" integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== eventemitter3@^4.0.7: version "4.0.7" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== events@^3.0.0, events@^3.2.0, events@^3.3.0: version "3.3.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + resolved "https://registry.npmjs.org/events/-/events-3.3.0.tgz" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + resolved "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz" integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== dependencies: md5.js "^1.3.4" safe-buffer "^5.1.1" express@^4.14.0, express@^4.17.1: - version "4.19.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465" - integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q== + version "4.21.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.21.2.tgz#cf250e48362174ead6cea4a566abef0162c1ec32" + integrity sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA== dependencies: accepts "~1.3.8" array-flatten "1.1.1" - body-parser "1.20.2" + body-parser "1.20.3" content-disposition "0.5.4" content-type "~1.0.4" - cookie "0.6.0" + cookie "0.7.1" cookie-signature "1.0.6" debug "2.6.9" depd "2.0.0" - encodeurl "~1.0.2" + encodeurl "~2.0.0" escape-html "~1.0.3" etag "~1.8.1" - finalhandler "1.2.0" + finalhandler "1.3.1" fresh "0.5.2" http-errors "2.0.0" - merge-descriptors "1.0.1" + merge-descriptors "1.0.3" methods "~1.1.2" on-finished "2.4.1" parseurl "~1.3.3" - path-to-regexp "0.1.7" + path-to-regexp "0.1.12" proxy-addr "~2.0.7" - qs "6.11.0" + qs "6.13.0" range-parser "~1.2.1" safe-buffer "5.2.1" - send "0.18.0" - serve-static "1.15.0" + send "0.19.0" + serve-static "1.16.2" setprototypeof "1.2.0" statuses "2.0.1" type-is "~1.6.18" @@ -5258,63 +5760,58 @@ express@^4.14.0, express@^4.17.1: ext@^1.1.2: version "1.7.0" - resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" + resolved "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz" integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw== dependencies: type "^2.7.2" extend@~3.0.2: version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + resolved "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== -extsprintf@1.3.0: +extsprintf@1.3.0, extsprintf@^1.2.0: version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz" integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== -extsprintf@^1.2.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" - integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== - fake-merkle-patricia-tree@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz#4b8c3acfb520afadf9860b1f14cd8ce3402cddd3" + resolved "https://registry.npmjs.org/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz" integrity sha512-Tgq37lkc9pUIgIKw5uitNUKcgcYL3R6JvXtKQbOf/ZSavXbidsksgp/pAY6p//uhw0I4yoMsvTSovvVIsk/qxA== dependencies: checkpoint-store "^1.1.0" faker@5.5.3: version "5.5.3" - resolved "https://registry.yarnpkg.com/faker/-/faker-5.5.3.tgz#c57974ee484431b25205c2c8dc09fda861e51e0e" + resolved "https://registry.npmjs.org/faker/-/faker-5.5.3.tgz" integrity sha512-wLTv2a28wjUyWkbnX7u/ABZBkUkIF2fCd73V6P2oFqEGEktDfzWx4UxrSqtPRw0xPRAcjeAOIiJWqZm3pP4u3g== fast-base64-decode@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/fast-base64-decode/-/fast-base64-decode-1.0.0.tgz#b434a0dd7d92b12b43f26819300d2dafb83ee418" + resolved "https://registry.npmjs.org/fast-base64-decode/-/fast-base64-decode-1.0.0.tgz" integrity sha512-qwaScUgUGBYeDNRnbc/KyllVU88Jk1pRHPStuF/lO7B0/RTRLj7U0lkdTAutlBblY08rwZDff6tNU9cjv6j//Q== fast-check@3.1.1: version "3.1.1" - resolved "https://registry.yarnpkg.com/fast-check/-/fast-check-3.1.1.tgz#72c5ae7022a4e86504762e773adfb8a5b0b01252" + resolved "https://registry.npmjs.org/fast-check/-/fast-check-3.1.1.tgz" integrity sha512-3vtXinVyuUKCKFKYcwXhGE6NtGWkqF8Yh3rvMZNzmwz8EPrgoc/v4pDdLHyLnCyCI5MZpZZkDEwFyXyEONOxpA== dependencies: pure-rand "^5.0.1" -fast-deep-equal@^3.1.1: +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== fast-fifo@^1.0.0: version "1.3.0" - resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.0.tgz#03e381bcbfb29932d7c3afde6e15e83e05ab4d8b" + resolved "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.0.tgz" integrity sha512-IgfweLvEpwyA4WgiQe9Nx6VV2QkML2NkvZnk1oKnIzXgXdWxuhF7zw4DvLTPZJn6PIUneiAXPF24QmoEqHTjyw== fast-glob@^3.0.3: version "3.3.1" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" + resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz" integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== dependencies: "@nodelib/fs.stat" "^2.0.2" @@ -5325,32 +5822,37 @@ fast-glob@^3.0.3: fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== fast-levenshtein@~2.0.6: version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== fast-safe-stringify@^2.0.6: version "2.1.1" - resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" + resolved "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz" integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== fast-sha256@^1.3.0: version "1.3.0" - resolved "https://registry.yarnpkg.com/fast-sha256/-/fast-sha256-1.3.0.tgz#7916ba2054eeb255982608cccd0f6660c79b7ae6" + resolved "https://registry.npmjs.org/fast-sha256/-/fast-sha256-1.3.0.tgz" integrity sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ== +fast-uri@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.0.tgz#66eecff6c764c0df9b762e62ca7edcfb53b4edfa" + integrity sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA== + fastestsmallesttextencoderdecoder@^1.0.22: version "1.0.22" - resolved "https://registry.yarnpkg.com/fastestsmallesttextencoderdecoder/-/fastestsmallesttextencoderdecoder-1.0.22.tgz#59b47e7b965f45258629cc6c127bf783281c5e93" + resolved "https://registry.npmjs.org/fastestsmallesttextencoderdecoder/-/fastestsmallesttextencoderdecoder-1.0.22.tgz" integrity sha512-Pb8d48e+oIuY4MaM64Cd7OW1gt4nxCHs7/ddPPZ/Ic3sg8yVGM7O9wDvZ7us6ScaUupzM+pfBolwtYhN1IxBIw== fastq@^1.6.0: version "1.15.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" + resolved "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz" integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== dependencies: reusify "^1.0.4" @@ -5364,30 +5866,30 @@ fetch-cookie@0.11.0: fetch-ponyfill@^4.0.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz#ae3ce5f732c645eab87e4ae8793414709b239893" + resolved "https://registry.npmjs.org/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz" integrity sha512-knK9sGskIg2T7OnYLdZ2hZXn0CtDrAIBxYQLpmEf0BqfdWnwmM1weccUl5+4EdA44tzNSFAuxITPbXtPehUB3g== dependencies: node-fetch "~1.7.1" file-uri-to-path@1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + resolved "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz" integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== fill-range@^7.1.1: version "7.1.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz" integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== dependencies: to-regex-range "^5.0.1" -finalhandler@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" - integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== +finalhandler@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.3.1.tgz#0c575f1d1d324ddd1da35ad7ece3df7d19088019" + integrity sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ== dependencies: debug "2.6.9" - encodeurl "~1.0.2" + encodeurl "~2.0.0" escape-html "~1.0.3" on-finished "2.4.1" parseurl "~1.3.3" @@ -5396,21 +5898,21 @@ finalhandler@1.2.0: find-replace@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38" + resolved "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz" integrity sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ== dependencies: array-back "^3.0.1" find-up@3.0.0, find-up@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + resolved "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz" integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== dependencies: locate-path "^3.0.0" find-up@5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== dependencies: locate-path "^6.0.0" @@ -5426,50 +5928,57 @@ find-up@^1.0.0: find-up@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + resolved "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz" integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== dependencies: locate-path "^2.0.0" find-yarn-workspace-root@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd" + resolved "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz" integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ== dependencies: micromatch "^4.0.2" flat@^4.1.0: version "4.1.1" - resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.1.tgz#a392059cc382881ff98642f5da4dde0a959f309b" + resolved "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz" integrity sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA== dependencies: is-buffer "~2.0.3" flat@^5.0.2: version "5.0.2" - resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + resolved "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== follow-redirects@^1.12.1, follow-redirects@^1.14.8, follow-redirects@^1.15.0: version "1.15.6" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" + resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz" integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== for-each@^0.3.3: version "0.3.3" - resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + resolved "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz" integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== dependencies: is-callable "^1.1.3" +for-each@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.5.tgz#d650688027826920feeb0af747ee7b9421a41d47" + integrity sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg== + dependencies: + is-callable "^1.2.7" + foreach@^2.0.4: version "2.0.6" - resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.6.tgz#87bcc8a1a0e74000ff2bf9802110708cfb02eb6e" + resolved "https://registry.npmjs.org/foreach/-/foreach-2.0.6.tgz" integrity sha512-k6GAGDyqLe9JaebCsFCoudPPWfihKu8pylYXRlqP1J7ms39iPoTtk2fviNglIeQEwdh0bQeKJ01ZPyuyQvKzwg== forever-agent@~0.6.1: version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + resolved "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz" integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== form-data-encoder@1.7.1: @@ -5479,7 +5988,7 @@ form-data-encoder@1.7.1: form-data@^2.2.0: version "2.5.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" + resolved "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz" integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== dependencies: asynckit "^0.4.0" @@ -5488,7 +5997,7 @@ form-data@^2.2.0: form-data@^3.0.0: version "3.0.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + resolved "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz" integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== dependencies: asynckit "^0.4.0" @@ -5497,7 +6006,7 @@ form-data@^3.0.0: form-data@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + resolved "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz" integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== dependencies: asynckit "^0.4.0" @@ -5506,7 +6015,7 @@ form-data@^4.0.0: form-data@~2.3.2: version "2.3.3" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + resolved "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz" integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== dependencies: asynckit "^0.4.0" @@ -5515,27 +6024,22 @@ form-data@~2.3.2: forwarded@0.2.0: version "0.2.0" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + resolved "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz" integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== -fp-ts@1.19.3: +fp-ts@1.19.3, fp-ts@^1.0.0: version "1.19.3" - resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.3.tgz#261a60d1088fbff01f91256f91d21d0caaaaa96f" + resolved "https://registry.npmjs.org/fp-ts/-/fp-ts-1.19.3.tgz" integrity sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg== -fp-ts@^1.0.0: - version "1.19.5" - resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.5.tgz#3da865e585dfa1fdfd51785417357ac50afc520a" - integrity sha512-wDNqTimnzs8QqpldiId9OavWK2NptormjXnRJTQecNjzwfyp6P/8s/zG8e4h3ja3oqkKaY72UlTjQYt/1yXf9A== - fresh@0.5.2: version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + resolved "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz" integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== fs-extra@^0.30.0: version "0.30.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz" integrity sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA== dependencies: graceful-fs "^4.1.2" @@ -5544,9 +6048,18 @@ fs-extra@^0.30.0: path-is-absolute "^1.0.0" rimraf "^2.2.8" +fs-extra@^10.0.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs-extra@^4.0.2: version "4.0.3" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz" integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== dependencies: graceful-fs "^4.1.2" @@ -5555,7 +6068,7 @@ fs-extra@^4.0.2: fs-extra@^7.0.0, fs-extra@^7.0.1: version "7.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz" integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== dependencies: graceful-fs "^4.1.2" @@ -5564,16 +6077,16 @@ fs-extra@^7.0.0, fs-extra@^7.0.1: fs-extra@^8.1.0: version "8.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz" integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== dependencies: graceful-fs "^4.2.0" jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^9.0.0, fs-extra@^9.0.1, fs-extra@^9.1.0: +fs-extra@^9.0.1, fs-extra@^9.1.0: version "9.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz" integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== dependencies: at-least-node "^1.0.0" @@ -5583,19 +6096,19 @@ fs-extra@^9.0.0, fs-extra@^9.0.1, fs-extra@^9.1.0: fs-minipass@^1.2.7: version "1.2.7" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" + resolved "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz" integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== dependencies: minipass "^2.6.0" fs-readdir-recursive@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" + resolved "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz" integrity sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA== fs.realpath@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@~2.1.1: @@ -5604,18 +6117,23 @@ fsevents@~2.1.1: integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== function-bind@^1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + function.prototype.name@^1.1.5: version "1.1.5" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" + resolved "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz" integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== dependencies: call-bind "^1.0.2" @@ -5625,17 +6143,38 @@ function.prototype.name@^1.1.5: functional-red-black-tree@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + resolved "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz" integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== functions-have-names@^1.2.2, functions-have-names@^1.2.3: version "1.2.3" - resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + resolved "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== -ganache@7.9.0, ganache@^7.0.3: +ganache@7.9.1: + version "7.9.1" + resolved "https://registry.yarnpkg.com/ganache/-/ganache-7.9.1.tgz#94f8518215c7989ff5fd542db80bd47d7c7da786" + integrity sha512-Tqhd4J3cpiLeYTD6ek/zlchSB107IVPMIm4ypyg+xz1sdkeALUnYYZnmY4Bdjqj3i6QwtlZPCu7U4qKy7HlWTA== + dependencies: + "@trufflesuite/bigint-buffer" "1.1.10" + "@trufflesuite/uws-js-unofficial" "20.30.0-unofficial.0" + "@types/bn.js" "^5.1.0" + "@types/lru-cache" "5.1.1" + "@types/seedrandom" "3.0.1" + abstract-level "1.0.3" + abstract-leveldown "7.2.0" + async-eventemitter "0.2.4" + emittery "0.10.0" + keccak "3.0.2" + leveldown "6.1.0" + secp256k1 "4.0.3" + optionalDependencies: + bufferutil "4.0.5" + utf-8-validate "5.0.7" + +ganache@^7.0.3: version "7.9.0" - resolved "https://registry.yarnpkg.com/ganache/-/ganache-7.9.0.tgz#561deceb376b1c4e8998ac8e5a842574507d3295" + resolved "https://registry.npmjs.org/ganache/-/ganache-7.9.0.tgz" integrity sha512-KdsTZaAKqDXTNDMKnLzg0ngX8wnZKyVGm7HD03GIyUMVRuXI83s0CUEaGIDWRUWTQP7BE8sDh7QtbW+NoX4zrQ== dependencies: "@trufflesuite/bigint-buffer" "1.1.10" @@ -5675,17 +6214,22 @@ get-caller-file@^1.0.1: get-caller-file@^2.0.1, get-caller-file@^2.0.5: version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== +get-east-asian-width@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz#9bc4caa131702b4b61729cb7e42735bc550c9ee6" + integrity sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q== + get-func-name@^2.0.0: version "2.0.2" - resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" + resolved "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz" integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0, get-intrinsic@^1.2.1: version "1.2.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82" + resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz" integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== dependencies: function-bind "^1.1.1" @@ -5693,26 +6237,50 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@ has-proto "^1.0.1" has-symbols "^1.0.3" +get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" + integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== + dependencies: + call-bind-apply-helpers "^1.0.2" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.1.1" + function-bind "^1.1.2" + get-proto "^1.0.1" + gopd "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + math-intrinsics "^1.1.0" + get-iterator@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/get-iterator/-/get-iterator-1.0.2.tgz#cd747c02b4c084461fac14f48f6b45a80ed25c82" + resolved "https://registry.npmjs.org/get-iterator/-/get-iterator-1.0.2.tgz" integrity sha512-v+dm9bNVfOYsY1OrhaCrmyOcYoSeVvbt+hHZ0Au+T+p1y+0Uyj9aMaGIeUTT6xdpRbWzDeYKvfOslPhggQMcsg== get-port@^3.1.0: version "3.2.0" - resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc" + resolved "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz" integrity sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg== +get-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" + integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== + dependencies: + dunder-proto "^1.0.1" + es-object-atoms "^1.0.0" + get-stream@^4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + resolved "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz" integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== dependencies: pump "^3.0.0" get-stream@^5.1.0: version "5.2.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + resolved "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz" integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== dependencies: pump "^3.0.0" @@ -5724,7 +6292,7 @@ get-stream@^6.0.1: get-symbol-description@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" + resolved "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz" integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== dependencies: call-bind "^1.0.2" @@ -5732,14 +6300,14 @@ get-symbol-description@^1.0.0: getpass@^0.1.1: version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + resolved "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz" integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng== dependencies: assert-plus "^1.0.0" ghost-testrpc@^0.0.2: version "0.0.2" - resolved "https://registry.yarnpkg.com/ghost-testrpc/-/ghost-testrpc-0.0.2.tgz#c4de9557b1d1ae7b2d20bbe474a91378ca90ce92" + resolved "https://registry.npmjs.org/ghost-testrpc/-/ghost-testrpc-0.0.2.tgz" integrity sha512-i08dAEgJ2g8z5buJIrCTduwPIhih3DP+hOCTyyryikfV8T0bNvHnGXO67i0DD1H4GBDETTclPy9njZbfluQYrQ== dependencies: chalk "^2.4.2" @@ -5747,14 +6315,14 @@ ghost-testrpc@^0.0.2: glob-parent@^5.1.2, glob-parent@~5.1.0, glob-parent@~5.1.2: version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: is-glob "^4.0.1" glob@7.1.3: version "7.1.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + resolved "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz" integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== dependencies: fs.realpath "^1.0.0" @@ -5766,7 +6334,7 @@ glob@7.1.3: glob@7.1.7: version "7.1.7" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" + resolved "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz" integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== dependencies: fs.realpath "^1.0.0" @@ -5778,7 +6346,7 @@ glob@7.1.7: glob@7.2.0: version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + resolved "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz" integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== dependencies: fs.realpath "^1.0.0" @@ -5790,7 +6358,7 @@ glob@7.2.0: glob@^5.0.15: version "5.0.15" - resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" + resolved "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz" integrity sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA== dependencies: inflight "^1.0.4" @@ -5801,7 +6369,7 @@ glob@^5.0.15: glob@^7.0.0, glob@^7.1.3: version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== dependencies: fs.realpath "^1.0.0" @@ -5813,14 +6381,14 @@ glob@^7.0.0, glob@^7.1.3: global-modules@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" + resolved "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz" integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== dependencies: global-prefix "^3.0.0" global-prefix@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" + resolved "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz" integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== dependencies: ini "^1.3.5" @@ -5829,7 +6397,7 @@ global-prefix@^3.0.0: global@~4.4.0: version "4.4.0" - resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406" + resolved "https://registry.npmjs.org/global/-/global-4.4.0.tgz" integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w== dependencies: min-document "^2.19.0" @@ -5837,14 +6405,14 @@ global@~4.4.0: globalthis@^1.0.1, globalthis@^1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" + resolved "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz" integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== dependencies: define-properties "^1.1.3" globby@^10.0.1: version "10.0.2" - resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.2.tgz#277593e745acaa4646c3ab411289ec47a0392543" + resolved "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz" integrity sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg== dependencies: "@types/glob" "^7.1.1" @@ -5857,17 +6425,22 @@ globby@^10.0.1: slash "^3.0.0" google-protobuf@^3.17.3, google-protobuf@^3.19.4: - version "3.21.2" - resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.21.2.tgz#4580a2bea8bbb291ee579d1fefb14d6fa3070ea4" - integrity sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA== + version "3.21.4" + resolved "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.4.tgz" + integrity sha512-MnG7N936zcKTco4Jd2PX2U96Kf9PxygAPKBug+74LHzmHXmceN16MmRcdgZv+DGef/S9YvQAfRsNCn4cjf9yyQ== gopd@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + resolved "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz" integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== dependencies: get-intrinsic "^1.1.3" +gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== + got@12.1.0: version "12.1.0" resolved "https://registry.yarnpkg.com/got/-/got-12.1.0.tgz#099f3815305c682be4fd6b0ee0726d8e4c6b0af4" @@ -5889,7 +6462,7 @@ got@12.1.0: got@9.6.0: version "9.6.0" - resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" + resolved "https://registry.npmjs.org/got/-/got-9.6.0.tgz" integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== dependencies: "@sindresorhus/is" "^0.14.0" @@ -5906,7 +6479,7 @@ got@9.6.0: got@^11.8.5: version "11.8.6" - resolved "https://registry.yarnpkg.com/got/-/got-11.8.6.tgz#276e827ead8772eddbcfc97170590b841823233a" + resolved "https://registry.npmjs.org/got/-/got-11.8.6.tgz" integrity sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g== dependencies: "@sindresorhus/is" "^4.0.0" @@ -5923,7 +6496,7 @@ got@^11.8.5: graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.4: version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== graphql-tag@^2.11.0, graphql-tag@^2.12.6: @@ -5934,19 +6507,19 @@ graphql-tag@^2.11.0, graphql-tag@^2.12.6: tslib "^2.1.0" graphql@^15.3.0: - version "15.8.0" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.8.0.tgz#33410e96b012fa3bdb1091cc99a94769db212b38" - integrity sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw== + version "15.10.1" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.10.1.tgz#e9ff3bb928749275477f748b14aa5c30dcad6f2f" + integrity sha512-BL/Xd/T9baO6NFzoMpiMD7YUZ62R6viR5tp/MULVEnbYJXZA//kRNW7J0j1w/wXArgL0sCxhDfK5dczSKn3+cg== growl@1.10.5: version "1.10.5" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + resolved "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz" integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== handlebars@^4.0.1: - version "4.7.8" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.8.tgz#41c42c18b1be2365439188c77c6afae71c0cd9e9" - integrity sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ== + version "4.7.9" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.9.tgz#6f139082ab58dc4e5a0e51efe7db5ae890d56a0f" + integrity sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ== dependencies: minimist "^1.2.5" neo-async "^2.6.2" @@ -5957,12 +6530,12 @@ handlebars@^4.0.1: har-schema@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + resolved "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz" integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q== har-validator@~5.1.3: version "5.1.5" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + resolved "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz" integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== dependencies: ajv "^6.12.3" @@ -5970,7 +6543,7 @@ har-validator@~5.1.3: hardhat-gas-reporter@^1.0.9: version "1.0.9" - resolved "https://registry.yarnpkg.com/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.9.tgz#9a2afb354bc3b6346aab55b1c02ca556d0e16450" + resolved "https://registry.npmjs.org/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.9.tgz" integrity sha512-INN26G3EW43adGKBNzYWOlI3+rlLnasXTwW79YNnUhXPDa+yHESgt639dJEs37gCjhkbNKcRRJnomXEuMFBXJg== dependencies: array-uniq "1.0.3" @@ -5979,7 +6552,7 @@ hardhat-gas-reporter@^1.0.9: hardhat@^2.20.0: version "2.20.1" - resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.20.1.tgz#3ad8f2b003a96c9ce80a55fec3575580ff2ddcd4" + resolved "https://registry.npmjs.org/hardhat/-/hardhat-2.20.1.tgz" integrity sha512-q75xDQiQtCZcTMBwjTovrXEU5ECr49baxr4/OBkIu/ULTPzlB20yk1dRWNmD2IFbAeAeXggaWvQAdpiScaHtPw== dependencies: "@ethersproject/abi" "^5.1.2" @@ -6035,48 +6608,67 @@ hardhat@^2.20.0: has-bigints@^1.0.1, has-bigints@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + resolved "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz" integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== has-flag@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz" integrity sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA== has-flag@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== has-flag@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== has-property-descriptors@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + resolved "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz" integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== dependencies: get-intrinsic "^1.1.1" +has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + dependencies: + es-define-property "^1.0.0" + has-proto@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + resolved "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz" integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== has-symbols@^1.0.0, has-symbols@^1.0.2, has-symbols@^1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== +has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== + has-tostringtag@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz" integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== dependencies: has-symbols "^1.0.2" +has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + dependencies: + has-symbols "^1.0.3" + has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" @@ -6084,23 +6676,33 @@ has-unicode@^2.0.0: has@^1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz" integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== dependencies: function-bind "^1.1.1" hash-base@^3.0.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + resolved "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz" integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== dependencies: inherits "^2.0.4" readable-stream "^3.6.0" safe-buffer "^5.2.0" +hash-base@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.2.tgz#79d72def7611c3f6e3c3b5730652638001b10a74" + integrity sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg== + dependencies: + inherits "^2.0.4" + readable-stream "^2.3.8" + safe-buffer "^5.2.1" + to-buffer "^1.2.1" + hash.js@1.1.3: version "1.1.3" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846" + resolved "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz" integrity sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA== dependencies: inherits "^2.0.3" @@ -6108,20 +6710,27 @@ hash.js@1.1.3: hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: version "1.1.7" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + resolved "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz" integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== dependencies: inherits "^2.0.3" minimalistic-assert "^1.0.1" +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + he@1.2.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + resolved "https://registry.npmjs.org/he/-/he-1.2.0.tgz" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== header-case@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/header-case/-/header-case-1.0.1.tgz#9535973197c144b09613cd65d317ef19963bd02d" + resolved "https://registry.npmjs.org/header-case/-/header-case-1.0.1.tgz" integrity sha512-i0q9mkOeSuhXw6bGgiQCCBgY/jlZuV/7dZXyZ9c6LcBrqwvT8eT719E9uxE5LiZftdl+z81Ugbg/VvXV4OJOeQ== dependencies: no-case "^2.2.0" @@ -6129,12 +6738,12 @@ header-case@^1.0.0: "heap@>= 0.2.0": version "0.2.7" - resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.7.tgz#1e6adf711d3f27ce35a81fe3b7bd576c2260a8fc" + resolved "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz" integrity sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg== hmac-drbg@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + resolved "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz" integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== dependencies: hash.js "^1.0.3" @@ -6148,7 +6757,7 @@ hosted-git-info@^2.1.4: http-basic@^8.1.1: version "8.1.3" - resolved "https://registry.yarnpkg.com/http-basic/-/http-basic-8.1.3.tgz#a7cabee7526869b9b710136970805b1004261bbf" + resolved "https://registry.npmjs.org/http-basic/-/http-basic-8.1.3.tgz" integrity sha512-/EcDMwJZh3mABI2NhGfHOGOeOZITqfkEO4p/xK+l3NpyncIHUQBoMvCSF/b5GqvKtySC2srL/GGG3+EtlqlmCw== dependencies: caseless "^0.12.0" @@ -6158,12 +6767,12 @@ http-basic@^8.1.1: http-cache-semantics@^4.0.0: version "4.1.1" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" + resolved "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz" integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== http-errors@2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + resolved "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz" integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== dependencies: depd "2.0.0" @@ -6172,21 +6781,32 @@ http-errors@2.0.0: statuses "2.0.1" toidentifier "1.0.1" +http-errors@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.1.tgz#36d2f65bc909c8790018dd36fb4d93da6caae06b" + integrity sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ== + dependencies: + depd "~2.0.0" + inherits "~2.0.4" + setprototypeof "~1.2.0" + statuses "~2.0.2" + toidentifier "~1.0.1" + http-https@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b" + resolved "https://registry.npmjs.org/http-https/-/http-https-1.0.0.tgz" integrity sha512-o0PWwVCSp3O0wS6FvNr6xfBCHgt0m1tvPLFOCc2iFDKTRAXhB7m8klDf7ErowFH8POa6dVdGatKU5I1YYwzUyg== http-response-object@^3.0.1: version "3.0.2" - resolved "https://registry.yarnpkg.com/http-response-object/-/http-response-object-3.0.2.tgz#7f435bb210454e4360d074ef1f989d5ea8aa9810" + resolved "https://registry.npmjs.org/http-response-object/-/http-response-object-3.0.2.tgz" integrity sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA== dependencies: "@types/node" "^10.0.3" http-signature@~1.2.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + resolved "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz" integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== dependencies: assert-plus "^1.0.0" @@ -6195,52 +6815,52 @@ http-signature@~1.2.0: http2-wrapper@^1.0.0-beta.5.2: version "1.0.3" - resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d" + resolved "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz" integrity sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg== dependencies: quick-lru "^5.1.1" resolve-alpn "^1.0.0" http2-wrapper@^2.1.10: - version "2.2.0" - resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-2.2.0.tgz#b80ad199d216b7d3680195077bd7b9060fa9d7f3" - integrity sha512-kZB0wxMo0sh1PehyjJUWRFEd99KC5TLjZ2cULC4f9iqJBAmKQQXEICjxl5iPJRwP40dpeHFqqhm7tYCvODpqpQ== + version "2.2.1" + resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-2.2.1.tgz#310968153dcdedb160d8b72114363ef5fce1f64a" + integrity sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ== dependencies: quick-lru "^5.1.1" resolve-alpn "^1.2.0" https-proxy-agent@^5.0.0: version "5.0.1" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz" integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== dependencies: agent-base "6" debug "4" -iconv-lite@0.4.24, iconv-lite@^0.4.4: +iconv-lite@0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.24: version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== dependencies: safer-buffer ">= 2.1.2 < 3" iconv-lite@^0.6.2: version "0.6.3" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz" integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== dependencies: safer-buffer ">= 2.1.2 < 3.0.0" idna-uts46-hx@^2.3.1: version "2.3.1" - resolved "https://registry.yarnpkg.com/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz#a1dc5c4df37eee522bf66d969cc980e00e8711f9" + resolved "https://registry.npmjs.org/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz" integrity sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA== dependencies: punycode "2.1.0" ieee754@^1.1.13, ieee754@^1.1.4, ieee754@^1.2.1: version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== ignore-walk@^3.0.1: @@ -6252,7 +6872,7 @@ ignore-walk@^3.0.1: ignore@^5.1.1: version "5.2.4" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" + resolved "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz" integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== immediate@3.0.6: @@ -6266,26 +6886,26 @@ immediate@3.3.0, immediate@^3.2.2, immediate@^3.2.3: integrity sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q== immutable@^4.0.0-rc.12: - version "4.3.2" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.2.tgz#f89d910f8dfb6e15c03b2cae2faaf8c1f66455fe" - integrity sha512-oGXzbEDem9OOpDWZu88jGiYCvIsLHMvGw+8OXlpsvTFvIQplQbjg1B1cvKg8f7Hoch6+NGjpPsH1Fr+Mc2D1aA== + version "4.3.8" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.8.tgz#02d183c7727fb2bb1d5d0380da0d779dce9296a7" + integrity sha512-d/Ld9aLbKpNwyl0KiM2CT1WYvkitQ1TSvmRtkcV8FKStiDoA7Slzgjmb/1G2yhKM1p0XeNOieaTbFZmU1d3Xuw== indent-string@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + resolved "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== inflight@^1.0.4: version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== dependencies: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4: version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== inherits@2.0.3: @@ -6295,7 +6915,7 @@ inherits@2.0.3: inherits@=2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" integrity sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA== ini@^1.3.5, ini@~1.3.0: @@ -6305,7 +6925,7 @@ ini@^1.3.5, ini@~1.3.0: internal-slot@^1.0.5: version "1.0.5" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" + resolved "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz" integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== dependencies: get-intrinsic "^1.2.0" @@ -6314,7 +6934,7 @@ internal-slot@^1.0.5: interpret@^1.0.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" + resolved "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz" integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== invert-kv@^1.0.0: @@ -6324,24 +6944,24 @@ invert-kv@^1.0.0: io-ts@1.10.4: version "1.10.4" - resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-1.10.4.tgz#cd5401b138de88e4f920adbcb7026e2d1967e6e2" + resolved "https://registry.npmjs.org/io-ts/-/io-ts-1.10.4.tgz" integrity sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g== dependencies: fp-ts "^1.0.0" ip-regex@^4.0.0: version "4.3.0" - resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-4.3.0.tgz#687275ab0f57fa76978ff8f4dddc8a23d5990db5" + resolved "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz" integrity sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q== ipaddr.js@1.9.1: version "1.9.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== ipfs-core-types@^0.2.1: version "0.2.1" - resolved "https://registry.yarnpkg.com/ipfs-core-types/-/ipfs-core-types-0.2.1.tgz#460bf2116477ce621995468c962c685dbdc4ac6f" + resolved "https://registry.npmjs.org/ipfs-core-types/-/ipfs-core-types-0.2.1.tgz" integrity sha512-q93+93qSybku6woZaajE9mCrHeVoMzNtZ7S5m/zx0+xHRhnoLlg8QNnGGsb5/+uFQt/RiBArsIw/Q61K9Jwkzw== dependencies: cids "^1.1.5" @@ -6350,7 +6970,7 @@ ipfs-core-types@^0.2.1: ipfs-core-utils@^0.6.1: version "0.6.1" - resolved "https://registry.yarnpkg.com/ipfs-core-utils/-/ipfs-core-utils-0.6.1.tgz#59d1ca9ff4a33bbf6497c4abe024573c3fd7d784" + resolved "https://registry.npmjs.org/ipfs-core-utils/-/ipfs-core-utils-0.6.1.tgz" integrity sha512-UFIklwE3CFcsNIhYFDuz0qB7E2QtdFauRfc76kskgiqhGWcjqqiDeND5zBCrAy0u8UMaDqAbFl02f/mIq1yKXw== dependencies: any-signal "^2.0.0" @@ -6371,7 +6991,7 @@ ipfs-core-utils@^0.6.1: ipfs-http-client@^48.2.2: version "48.2.2" - resolved "https://registry.yarnpkg.com/ipfs-http-client/-/ipfs-http-client-48.2.2.tgz#b570fb99866f94df1c394a6101a2eb750ff46599" + resolved "https://registry.npmjs.org/ipfs-http-client/-/ipfs-http-client-48.2.2.tgz" integrity sha512-f3ppfWe913SJLvunm0UgqdA1dxVZSGQJPaEVJtqgjxPa5x0fPDiBDdo60g2MgkW1W6bhF9RGlxvHHIE9sv/tdg== dependencies: any-signal "^2.0.0" @@ -6403,7 +7023,7 @@ ipfs-http-client@^48.2.2: ipfs-utils@^5.0.0: version "5.0.1" - resolved "https://registry.yarnpkg.com/ipfs-utils/-/ipfs-utils-5.0.1.tgz#7c0053d5e77686f45577257a73905d4523e6b4f7" + resolved "https://registry.npmjs.org/ipfs-utils/-/ipfs-utils-5.0.1.tgz" integrity sha512-28KZPgO4Uf5duT2ORLAYfboUp98iUshDD7yRAfbNxNAR8Dtidfn6o20rZfoXnkri2zKBVIPlJkuCPmPJB+6erg== dependencies: abort-controller "^3.0.0" @@ -6425,14 +7045,14 @@ ipfs-utils@^5.0.0: ipld-block@^0.11.0: version "0.11.1" - resolved "https://registry.yarnpkg.com/ipld-block/-/ipld-block-0.11.1.tgz#c3a7b41aee3244187bd87a73f980e3565d299b6e" + resolved "https://registry.npmjs.org/ipld-block/-/ipld-block-0.11.1.tgz" integrity sha512-sDqqLqD5qh4QzGq6ssxLHUCnH4emCf/8F8IwjQM2cjEEIEHMUj57XhNYgmGbemdYPznUhffxFGEHsruh5+HQRw== dependencies: cids "^1.0.0" ipld-dag-cbor@^0.17.0: version "0.17.1" - resolved "https://registry.yarnpkg.com/ipld-dag-cbor/-/ipld-dag-cbor-0.17.1.tgz#842e6c250603e5791049168831a425ec03471fb1" + resolved "https://registry.npmjs.org/ipld-dag-cbor/-/ipld-dag-cbor-0.17.1.tgz" integrity sha512-Bakj/cnxQBdscORyf4LRHxQJQfoaY8KWc7PWROQgX+aw5FCzBt8ga0VM/59K+ABOznsqNvyLR/wz/oYImOpXJw== dependencies: borc "^2.1.2" @@ -6444,7 +7064,7 @@ ipld-dag-cbor@^0.17.0: ipld-dag-pb@^0.20.0: version "0.20.0" - resolved "https://registry.yarnpkg.com/ipld-dag-pb/-/ipld-dag-pb-0.20.0.tgz#025c0343aafe6cb9db395dd1dc93c8c60a669360" + resolved "https://registry.npmjs.org/ipld-dag-pb/-/ipld-dag-pb-0.20.0.tgz" integrity sha512-zfM0EdaolqNjAxIrtpuGKvXxWk5YtH9jKinBuQGTcngOsWFQhyybGCTJHGNGGtRjHNJi2hz5Udy/8pzv4kcKyg== dependencies: cids "^1.0.0" @@ -6459,7 +7079,7 @@ ipld-dag-pb@^0.20.0: ipld-raw@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/ipld-raw/-/ipld-raw-6.0.0.tgz#74d947fcd2ce4e0e1d5bb650c1b5754ed8ea6da0" + resolved "https://registry.npmjs.org/ipld-raw/-/ipld-raw-6.0.0.tgz" integrity sha512-UK7fjncAzs59iu/o2kwYtb8jgTtW6B+cNWIiNpAJkfRwqoMk1xD/6i25ktzwe4qO8gQgoR9RxA5ibC23nq8BLg== dependencies: cids "^1.0.0" @@ -6468,7 +7088,7 @@ ipld-raw@^6.0.0: is-arguments@^1.0.4: version "1.1.1" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" + resolved "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz" integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== dependencies: call-bind "^1.0.2" @@ -6476,7 +7096,7 @@ is-arguments@^1.0.4: is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: version "3.0.2" - resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" + resolved "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz" integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== dependencies: call-bind "^1.0.2" @@ -6490,21 +7110,21 @@ is-arrayish@^0.2.1: is-bigint@^1.0.1: version "1.0.4" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" + resolved "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz" integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== dependencies: has-bigints "^1.0.1" is-binary-path@~2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== dependencies: binary-extensions "^2.0.0" is-boolean-object@^1.1.0: version "1.1.2" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + resolved "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz" integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== dependencies: call-bind "^1.0.2" @@ -6512,58 +7132,51 @@ is-boolean-object@^1.1.0: is-buffer@^2.0.5, is-buffer@~2.0.3: version "2.0.5" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" + resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz" integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: version "1.2.7" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== -is-ci@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" - integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== - dependencies: - ci-info "^2.0.0" - is-circular@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/is-circular/-/is-circular-1.0.2.tgz#2e0ab4e9835f4c6b0ea2b9855a84acd501b8366c" + resolved "https://registry.npmjs.org/is-circular/-/is-circular-1.0.2.tgz" integrity sha512-YttjnrswnUYRVJvxCvu8z+PGMUSzC2JttP0OEXezlAEdp3EXzhf7IZ3j0gRAybJBQupedIZFhY61Tga6E0qASA== -is-core-module@^2.13.0: - version "2.13.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" - integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== +is-core-module@^2.16.1: + version "2.16.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" + integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== dependencies: - has "^1.0.3" + hasown "^2.0.2" is-date-object@^1.0.1: version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" + resolved "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz" integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== dependencies: has-tostringtag "^1.0.0" is-docker@^2.0.0: version "2.2.1" - resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + resolved "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz" integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== is-electron@^2.2.0: version "2.2.2" - resolved "https://registry.yarnpkg.com/is-electron/-/is-electron-2.2.2.tgz#3778902a2044d76de98036f5dc58089ac4d80bb9" + resolved "https://registry.npmjs.org/is-electron/-/is-electron-2.2.2.tgz" integrity sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg== is-extglob@^2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== is-fn@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fn/-/is-fn-1.0.0.tgz#9543d5de7bcf5b08a22ec8a20bae6e286d510d8c" + resolved "https://registry.npmjs.org/is-fn/-/is-fn-1.0.0.tgz" integrity sha512-XoFPJQmsAShb3jEQRfzf2rqXavq7fIqF/jOekp308JlThqrODnMpweVSGilKTCXELfLhltGP2AGgbQGVP8F1dg== is-fullwidth-code-point@^1.0.0: @@ -6575,67 +7188,67 @@ is-fullwidth-code-point@^1.0.0: is-fullwidth-code-point@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz" integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== is-fullwidth-code-point@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== is-function@^1.0.1: version "1.0.2" - resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.2.tgz#4f097f30abf6efadac9833b17ca5dc03f8144e08" + resolved "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz" integrity sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ== is-generator-function@^1.0.7: version "1.0.10" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" + resolved "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz" integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== dependencies: has-tostringtag "^1.0.0" is-glob@^4.0.1, is-glob@~4.0.1: version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== dependencies: is-extglob "^2.1.1" is-hex-prefixed@1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" + resolved "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz" integrity sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA== is-ip@^3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/is-ip/-/is-ip-3.1.0.tgz#2ae5ddfafaf05cb8008a62093cf29734f657c5d8" + resolved "https://registry.npmjs.org/is-ip/-/is-ip-3.1.0.tgz" integrity sha512-35vd5necO7IitFPjd/YBeqwWnyDWbuLH9ZXQdMfDA8TEo7pv5X8yfrvVO3xbJbLUlERCMvf6X0hTUamQxCYJ9Q== dependencies: ip-regex "^4.0.0" is-lower-case@^1.1.0: version "1.1.3" - resolved "https://registry.yarnpkg.com/is-lower-case/-/is-lower-case-1.1.3.tgz#7e147be4768dc466db3bfb21cc60b31e6ad69393" + resolved "https://registry.npmjs.org/is-lower-case/-/is-lower-case-1.1.3.tgz" integrity sha512-+5A1e/WJpLLXZEDlgz4G//WYSHyQBD32qa4Jd3Lw06qQlv3fJHnp3YIHjTQSGzHMgzmVKz2ZP3rBxTHkPw/lxA== dependencies: lower-case "^1.1.0" is-negative-zero@^2.0.2: version "2.0.2" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" + resolved "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz" integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== is-number-object@^1.0.4: version "1.0.7" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" + resolved "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz" integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== dependencies: has-tostringtag "^1.0.0" is-number@^7.0.0: version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== is-obj@^2.0.0: @@ -6645,12 +7258,12 @@ is-obj@^2.0.0: is-plain-obj@^2.0.0, is-plain-obj@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz" integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== is-regex@^1.1.4: version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + resolved "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz" integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== dependencies: call-bind "^1.0.2" @@ -6658,50 +7271,57 @@ is-regex@^1.1.4: is-shared-array-buffer@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" + resolved "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz" integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== dependencies: call-bind "^1.0.2" is-stream@^1.0.1: version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + resolved "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz" integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ== is-string@^1.0.5, is-string@^1.0.7: version "1.0.7" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + resolved "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz" integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== dependencies: has-tostringtag "^1.0.0" is-symbol@^1.0.2, is-symbol@^1.0.3: version "1.0.4" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + resolved "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz" integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== dependencies: has-symbols "^1.0.2" is-typed-array@^1.1.10, is-typed-array@^1.1.3, is-typed-array@^1.1.9: version "1.1.12" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.12.tgz#d0bab5686ef4a76f7a73097b95470ab199c57d4a" + resolved "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz" integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg== dependencies: which-typed-array "^1.1.11" +is-typed-array@^1.1.14: + version "1.1.15" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.15.tgz#4bfb4a45b61cee83a5a46fba778e4e8d59c0ce0b" + integrity sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ== + dependencies: + which-typed-array "^1.1.16" + is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + resolved "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz" integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== is-unicode-supported@^0.1.0: version "0.1.0" - resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz" integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== is-upper-case@^1.1.0: version "1.1.2" - resolved "https://registry.yarnpkg.com/is-upper-case/-/is-upper-case-1.1.2.tgz#8d0b1fa7e7933a1e58483600ec7d9661cbaf756f" + resolved "https://registry.npmjs.org/is-upper-case/-/is-upper-case-1.1.2.tgz" integrity sha512-GQYSJMgfeAmVwh9ixyk888l7OIhNAGKtY6QA+IrWlu9MDTCaXmeozOZ2S9Knj7bQwBO/H6J2kb+pbyTUiMNbsw== dependencies: upper-case "^1.1.0" @@ -6713,46 +7333,46 @@ is-utf8@^0.2.0: is-weakref@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + resolved "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz" integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== dependencies: call-bind "^1.0.2" is-wsl@^2.1.1: version "2.2.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + resolved "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz" integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== dependencies: is-docker "^2.0.0" isarray@0.0.1: version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + resolved "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== isarray@^2.0.5: version "2.0.5" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + resolved "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz" integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== isexe@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== iso-constants@^0.1.2: version "0.1.2" - resolved "https://registry.yarnpkg.com/iso-constants/-/iso-constants-0.1.2.tgz#3d2456ed5aeaa55d18564f285ba02a47a0d885b4" + resolved "https://registry.npmjs.org/iso-constants/-/iso-constants-0.1.2.tgz" integrity sha512-OTCM5ZCQsHBCI4Wdu4tSxvDIkmDHd5EwJDps5mKqnQnWJSKlnwMs3EDZ4n3Fh1tmkWkDlyd2vCDbEYuPbyrUNQ== iso-random-stream@^2.0.0: version "2.0.2" - resolved "https://registry.yarnpkg.com/iso-random-stream/-/iso-random-stream-2.0.2.tgz#a24f77c34cfdad9d398707d522a6a0cc640ff27d" + resolved "https://registry.npmjs.org/iso-random-stream/-/iso-random-stream-2.0.2.tgz" integrity sha512-yJvs+Nnelic1L2vH2JzWvvPQFA4r7kSTnpST/+LkAQjSz0hos2oqLD+qIVi9Qk38Hoe7mNDt3j0S27R58MVjLQ== dependencies: events "^3.3.0" @@ -6760,17 +7380,17 @@ iso-random-stream@^2.0.0: iso-url@^1.0.0: version "1.2.1" - resolved "https://registry.yarnpkg.com/iso-url/-/iso-url-1.2.1.tgz#db96a49d8d9a64a1c889fc07cc525d093afb1811" + resolved "https://registry.npmjs.org/iso-url/-/iso-url-1.2.1.tgz" integrity sha512-9JPDgCN4B7QPkLtYAAOrEuAWvP9rWvR5offAr0/SeF046wIkglqH3VXgYYP6NcsKslH80UIVgmPqNe3j7tG2ng== iso-url@~0.4.7: version "0.4.7" - resolved "https://registry.yarnpkg.com/iso-url/-/iso-url-0.4.7.tgz#de7e48120dae46921079fe78f325ac9e9217a385" + resolved "https://registry.npmjs.org/iso-url/-/iso-url-0.4.7.tgz" integrity sha512-27fFRDnPAMnHGLq36bWTpKET+eiXct3ENlCcdcMdk+mjXrb2kw3mhBUg1B7ewAC0kVzlOPhADzQgz1SE6Tglog== isomorphic-unfetch@^3.0.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/isomorphic-unfetch/-/isomorphic-unfetch-3.1.0.tgz#87341d5f4f7b63843d468438128cb087b7c3e98f" + resolved "https://registry.npmjs.org/isomorphic-unfetch/-/isomorphic-unfetch-3.1.0.tgz" integrity sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q== dependencies: node-fetch "^2.6.1" @@ -6778,34 +7398,34 @@ isomorphic-unfetch@^3.0.0: isomorphic-ws@^4.0.1: version "4.0.1" - resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#55fd4cd6c5e6491e76dc125938dd863f5cd4f2dc" + resolved "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz" integrity sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w== isstream@~0.1.2: version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + resolved "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz" integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== it-all@^1.0.4: version "1.0.6" - resolved "https://registry.yarnpkg.com/it-all/-/it-all-1.0.6.tgz#852557355367606295c4c3b7eff0136f07749335" + resolved "https://registry.npmjs.org/it-all/-/it-all-1.0.6.tgz" integrity sha512-3cmCc6Heqe3uWi3CVM/k51fa/XbMFpQVzFoDsV0IZNHSQDyAXl3c4MjHkFX5kF3922OGj7Myv1nSEUgRtcuM1A== it-concat@^1.0.0: version "1.0.3" - resolved "https://registry.yarnpkg.com/it-concat/-/it-concat-1.0.3.tgz#84db9376e4c77bf7bc1fd933bb90f184e7cef32b" + resolved "https://registry.npmjs.org/it-concat/-/it-concat-1.0.3.tgz" integrity sha512-sjeZQ1BWQ9U/W2oI09kZgUyvSWzQahTkOkLIsnEPgyqZFaF9ME5gV6An4nMjlyhXKWQMKEakQU8oRHs2SdmeyA== dependencies: bl "^4.0.0" it-drain@^1.0.3: version "1.0.5" - resolved "https://registry.yarnpkg.com/it-drain/-/it-drain-1.0.5.tgz#0466d4e286b37bcd32599d4e99b37a87cb8cfdf6" + resolved "https://registry.npmjs.org/it-drain/-/it-drain-1.0.5.tgz" integrity sha512-r/GjkiW1bZswC04TNmUnLxa6uovme7KKwPhc+cb1hHU65E3AByypHH6Pm91WHuvqfFsm+9ws0kPtDBV3/8vmIg== it-glob@0.0.10: version "0.0.10" - resolved "https://registry.yarnpkg.com/it-glob/-/it-glob-0.0.10.tgz#4defd9286f693847c3ff483d2ff65f22e1359ad8" + resolved "https://registry.npmjs.org/it-glob/-/it-glob-0.0.10.tgz" integrity sha512-p1PR15djgPV7pxdLOW9j4WcJdla8+91rJdUU2hU2Jm68vkxpIEXK55VHBeH8Lvqh2vqLtM83t8q4BuJxue6niA== dependencies: fs-extra "^9.0.1" @@ -6813,29 +7433,29 @@ it-glob@0.0.10: it-last@^1.0.4: version "1.0.6" - resolved "https://registry.yarnpkg.com/it-last/-/it-last-1.0.6.tgz#4106232e5905ec11e16de15a0e9f7037eaecfc45" + resolved "https://registry.npmjs.org/it-last/-/it-last-1.0.6.tgz" integrity sha512-aFGeibeiX/lM4bX3JY0OkVCFkAw8+n9lkukkLNivbJRvNz8lI3YXv5xcqhFUV2lDJiraEK3OXRDbGuevnnR67Q== it-map@^1.0.4: version "1.0.6" - resolved "https://registry.yarnpkg.com/it-map/-/it-map-1.0.6.tgz#6aa547e363eedcf8d4f69d8484b450bc13c9882c" + resolved "https://registry.npmjs.org/it-map/-/it-map-1.0.6.tgz" integrity sha512-XT4/RM6UHIFG9IobGlQPFQUrlEKkU4eBUFG3qhWhfAdh1JfF2x11ShCrKCdmZ0OiZppPfoLuzcfA4cey6q3UAQ== it-peekable@^1.0.1: version "1.0.3" - resolved "https://registry.yarnpkg.com/it-peekable/-/it-peekable-1.0.3.tgz#8ebe933767d9c5aa0ae4ef8e9cb3a47389bced8c" + resolved "https://registry.npmjs.org/it-peekable/-/it-peekable-1.0.3.tgz" integrity sha512-5+8zemFS+wSfIkSZyf0Zh5kNN+iGyccN02914BY4w/Dj+uoFEoPSvj5vaWn8pNZJNSxzjW0zHRxC3LUb2KWJTQ== it-reader@^2.0.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/it-reader/-/it-reader-2.1.0.tgz#b1164be343f8538d8775e10fb0339f61ccf71b0f" + resolved "https://registry.npmjs.org/it-reader/-/it-reader-2.1.0.tgz" integrity sha512-hSysqWTO9Tlwc5EGjVf8JYZzw0D2FsxD/g+eNNWrez9zODxWt6QlN6JAMmycK72Mv4jHEKEXoyzUN4FYGmJaZw== dependencies: bl "^4.0.0" it-tar@^1.2.2: version "1.2.2" - resolved "https://registry.yarnpkg.com/it-tar/-/it-tar-1.2.2.tgz#8d79863dad27726c781a4bcc491f53c20f2866cf" + resolved "https://registry.npmjs.org/it-tar/-/it-tar-1.2.2.tgz" integrity sha512-M8V4a9I+x/vwXTjqvixcEZbQZHjwDIb8iUQ+D4M2QbhAdNs3WKVSl+45u5/F2XFx6jYMFOGzMVlKNK/uONgNIA== dependencies: bl "^4.0.0" @@ -6847,7 +7467,7 @@ it-tar@^1.2.2: it-to-stream@^0.1.2: version "0.1.2" - resolved "https://registry.yarnpkg.com/it-to-stream/-/it-to-stream-0.1.2.tgz#7163151f75b60445e86b8ab1a968666acaacfe7b" + resolved "https://registry.npmjs.org/it-to-stream/-/it-to-stream-0.1.2.tgz" integrity sha512-DTB5TJRZG3untmZehcaFN0kGWl2bNv7tnJRgQHAO9QEt8jfvVRrebZtnD5NZd4SCj4WVPjl0LSrugNWE/UaZRQ== dependencies: buffer "^5.6.0" @@ -6859,44 +7479,44 @@ it-to-stream@^0.1.2: iter-tools@^7.0.2: version "7.5.3" - resolved "https://registry.yarnpkg.com/iter-tools/-/iter-tools-7.5.3.tgz#79c1d40b39bd805120cd6d6c907d1f97e912ab30" + resolved "https://registry.npmjs.org/iter-tools/-/iter-tools-7.5.3.tgz" integrity sha512-iEcHpgM9cn6tsI5MewqxyEega9KPbIDytQTEnu6c0MtlQQhQFofssYuRqxCarZgUdzliepRZPwwwflE4wAIjaA== dependencies: "@babel/runtime" "^7.12.1" js-cookie@^2.2.1: version "2.2.1" - resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-2.2.1.tgz#69e106dc5d5806894562902aa5baec3744e9b2b8" + resolved "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz" integrity sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ== js-sdsl@^4.1.4: version "4.4.2" - resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.4.2.tgz#2e3c031b1f47d3aca8b775532e3ebb0818e7f847" + resolved "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.2.tgz" integrity sha512-dwXFwByc/ajSV6m5bcKAPwe4yDDF6D614pxmIi5odytzxRlwqF6nwoiCek80Ixc7Cvma5awClxrzFtxCQvcM8w== js-sha256@^0.9.0: version "0.9.0" - resolved "https://registry.yarnpkg.com/js-sha256/-/js-sha256-0.9.0.tgz#0b89ac166583e91ef9123644bd3c5334ce9d0966" + resolved "https://registry.npmjs.org/js-sha256/-/js-sha256-0.9.0.tgz" integrity sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA== js-sha3@0.5.7, js-sha3@^0.5.7: version "0.5.7" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" + resolved "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz" integrity sha512-GII20kjaPX0zJ8wzkTbNDYMY7msuZcTWk8S5UOh6806Jq/wz1J8/bnr8uGU0DAUmYDjj2Mr4X1cW8v/GLYnR+g== js-sha3@0.8.0, js-sha3@^0.8.0: version "0.8.0" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + resolved "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz" integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== -"js-tokens@^3.0.0 || ^4.0.0": +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-yaml@3.13.1: version "3.13.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz" integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== dependencies: argparse "^1.0.7" @@ -6904,7 +7524,7 @@ js-yaml@3.13.1: js-yaml@3.x: version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== dependencies: argparse "^1.0.7" @@ -6912,36 +7532,41 @@ js-yaml@3.x: js-yaml@4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== dependencies: argparse "^2.0.1" jsbn@~0.1.0: version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + resolved "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz" integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== +jsesc@^3.0.2: + version "3.1.0" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz" + integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== + json-buffer@3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" + resolved "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz" integrity sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ== json-buffer@3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + resolved "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz" integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== json-pointer@^0.6.1: version "0.6.2" - resolved "https://registry.yarnpkg.com/json-pointer/-/json-pointer-0.6.2.tgz#f97bd7550be5e9ea901f8c9264c9d436a22a93cd" + resolved "https://registry.npmjs.org/json-pointer/-/json-pointer-0.6.2.tgz" integrity sha512-vLWcKbOaXlO+jvRy4qNd+TI1QUPZzfJj1tpJ3vAXDych5XJf93ftpUKe5pKCrzyIIwgBJcOcCVRUfqQP25afBw== dependencies: foreach "^2.0.4" json-rpc-engine@^5.1.3: version "5.4.0" - resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-5.4.0.tgz#75758609d849e1dba1e09021ae473f3ab63161e5" + resolved "https://registry.npmjs.org/json-rpc-engine/-/json-rpc-engine-5.4.0.tgz" integrity sha512-rAffKbPoNDjuRnXkecTjnsE3xLLrb00rEkdgalINhaYVYIxDwWtvYBr9UFbhTvPB1B2qUOLoFd/cV6f4Q7mh7g== dependencies: eth-rpc-errors "^3.0.0" @@ -6949,17 +7574,17 @@ json-rpc-engine@^5.1.3: json-rpc-random-id@^1.0.0, json-rpc-random-id@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz#ba49d96aded1444dbb8da3d203748acbbcdec8c8" + resolved "https://registry.npmjs.org/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz" integrity sha512-RJ9YYNCkhVDBuP4zN5BBtYAzEl03yq/jIIsyif0JY9qyJuQQZNeDK7anAPKKlyEtLSj2s8h6hNh2F8zO5q7ScA== json-schema-traverse@^0.4.1: version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== json-schema-traverse@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== json-schema-typed@^7.0.3: @@ -6969,45 +7594,56 @@ json-schema-typed@^7.0.3: json-schema@0.4.0: version "0.4.0" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" + resolved "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz" integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== json-stable-stringify@^1.0.1: version "1.0.2" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz#e06f23128e0bbe342dc996ed5a19e28b57b580e0" + resolved "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz" integrity sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g== dependencies: jsonify "^0.0.1" +json-stable-stringify@^1.0.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.3.0.tgz#8903cfac42ea1a0f97f35d63a4ce0518f0cc6a70" + integrity sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.4" + isarray "^2.0.5" + jsonify "^0.0.1" + object-keys "^1.1.1" + json-stringify-safe@~5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + resolved "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== json-text-sequence@~0.1.0: version "0.1.1" - resolved "https://registry.yarnpkg.com/json-text-sequence/-/json-text-sequence-0.1.1.tgz#a72f217dc4afc4629fff5feb304dc1bd51a2f3d2" + resolved "https://registry.npmjs.org/json-text-sequence/-/json-text-sequence-0.1.1.tgz" integrity sha512-L3mEegEWHRekSHjc7+sc8eJhba9Clq1PZ8kMkzf8OxElhXc8O4TS5MwcVlj9aEbm5dr81N90WHC5nAz3UO971w== dependencies: delimit-stream "0.1.0" jsonfile@^2.1.0: version "2.4.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" + resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz" integrity sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw== optionalDependencies: graceful-fs "^4.1.6" jsonfile@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz" integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== optionalDependencies: graceful-fs "^4.1.6" jsonfile@^6.0.1: version "6.1.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz" integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== dependencies: universalify "^2.0.0" @@ -7016,17 +7652,17 @@ jsonfile@^6.0.1: jsonify@^0.0.1: version "0.0.1" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978" + resolved "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz" integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg== jsonschema@^1.2.4: version "1.4.1" - resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.4.1.tgz#cc4c3f0077fb4542982973d8a083b6b34f482dab" + resolved "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.1.tgz" integrity sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ== jsprim@^1.2.2: version "1.4.2" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" + resolved "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz" integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== dependencies: assert-plus "1.0.0" @@ -7036,7 +7672,7 @@ jsprim@^1.2.2: keccak@3.0.2: version "3.0.2" - resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.2.tgz#4c2c6e8c54e04f2670ee49fa734eb9da152206e0" + resolved "https://registry.npmjs.org/keccak/-/keccak-3.0.2.tgz" integrity sha512-PyKKjkH53wDMLGrvmRGSNWgmSxZOUqbnXwKL9tmgbFYA1iAYqW21kfR7mZXV0MlESiefxQQE9X9fTa3X+2MPDQ== dependencies: node-addon-api "^2.0.0" @@ -7045,7 +7681,7 @@ keccak@3.0.2: keccak@^3.0.0, keccak@^3.0.2: version "3.0.3" - resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.3.tgz#4bc35ad917be1ef54ff246f904c2bbbf9ac61276" + resolved "https://registry.npmjs.org/keccak/-/keccak-3.0.3.tgz" integrity sha512-JZrLIAJWuZxKbCilMpNz5Vj7Vtb4scDG3dMXLOsbzBmQGyjwE61BbW7bJkfKKCShXiQZt3T6sBgALRtmd+nZaQ== dependencies: node-addon-api "^2.0.0" @@ -7054,38 +7690,38 @@ keccak@^3.0.0, keccak@^3.0.2: keypair@^1.0.1: version "1.0.4" - resolved "https://registry.yarnpkg.com/keypair/-/keypair-1.0.4.tgz#a749a45f388593f3950f18b3757d32a93bd8ce83" + resolved "https://registry.npmjs.org/keypair/-/keypair-1.0.4.tgz" integrity sha512-zwhgOhhniaL7oxMgUMKKw5219PWWABMO+dgMnzJOQ2/5L3XJtTJGhW2PEXlxXj9zaccdReZJZ83+4NPhVfNVDg== keyv@^3.0.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" + resolved "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz" integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== dependencies: json-buffer "3.0.0" keyv@^4.0.0: version "4.5.3" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.3.tgz#00873d2b046df737963157bd04f294ca818c9c25" + resolved "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz" integrity sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug== dependencies: json-buffer "3.0.1" kind-of@^6.0.2: version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== klaw-sync@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/klaw-sync/-/klaw-sync-6.0.0.tgz#1fd2cfd56ebb6250181114f0a581167099c2b28c" + resolved "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz" integrity sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ== dependencies: graceful-fs "^4.1.11" klaw@^1.0.0: version "1.3.1" - resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" + resolved "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz" integrity sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw== optionalDependencies: graceful-fs "^4.1.9" @@ -7099,7 +7735,7 @@ lcid@^1.0.0: leb128@0.0.5: version "0.0.5" - resolved "https://registry.yarnpkg.com/leb128/-/leb128-0.0.5.tgz#84524a86ef7799fb3933ce41345f6490e27ac948" + resolved "https://registry.npmjs.org/leb128/-/leb128-0.0.5.tgz" integrity sha512-elbNtfmu3GndZbesVF6+iQAfVjOXW9bM/aax9WwMlABZW+oK9sbAZEXoewaPHmL34sxa8kVwWsru8cNE/yn2gg== dependencies: bn.js "^5.0.0" @@ -7114,12 +7750,12 @@ level-codec@9.0.2, level-codec@^9.0.0: level-codec@~7.0.0: version "7.0.1" - resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-7.0.1.tgz#341f22f907ce0f16763f24bddd681e395a0fb8a7" + resolved "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz" integrity sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ== level-concat-iterator@^3.0.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/level-concat-iterator/-/level-concat-iterator-3.1.0.tgz#5235b1f744bc34847ed65a50548aa88d22e881cf" + resolved "https://registry.npmjs.org/level-concat-iterator/-/level-concat-iterator-3.1.0.tgz" integrity sha512-BWRCMHBxbIqPxJ8vHOvKUsaO0v1sLYZtjN3K2iZJsRBYtp+ONsY6Jfi6hy9K3+zolgQRryhIn2NRZjZnWJ9NmQ== dependencies: catering "^2.1.0" @@ -7129,10 +7765,10 @@ level-concat-iterator@~2.0.0: resolved "https://registry.yarnpkg.com/level-concat-iterator/-/level-concat-iterator-2.0.1.tgz#1d1009cf108340252cb38c51f9727311193e6263" integrity sha512-OTKKOqeav2QWcERMJR7IS9CUo1sHnke2C0gkSmcR7QuEtFNLLzHQAvnMw8ykvEcv0Qtkg0p7FOwP1v9e5Smdcw== -level-errors@^1.0.3: - version "1.1.2" - resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.1.2.tgz#4399c2f3d3ab87d0625f7e3676e2d807deff404d" - integrity sha512-Sw/IJwWbPKF5Ai4Wz60B52yj0zYeqzObLh8k1Tk88jVmD51cJSKWSYpRyhVIvFzZdvsPqlH5wfhp/yxdsaQH4w== +level-errors@^1.0.3, level-errors@~1.0.3: + version "1.0.5" + resolved "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz" + integrity sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig== dependencies: errno "~0.1.1" @@ -7143,16 +7779,9 @@ level-errors@^2.0.0, level-errors@~2.0.0: dependencies: errno "~0.1.1" -level-errors@~1.0.3: - version "1.0.5" - resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.0.5.tgz#83dbfb12f0b8a2516bdc9a31c4876038e227b859" - integrity sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig== - dependencies: - errno "~0.1.1" - level-iterator-stream@~1.3.0: version "1.3.1" - resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz#e43b78b1a8143e6fa97a4f485eb8ea530352f2ed" + resolved "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz" integrity sha512-1qua0RHNtr4nrZBgYlpV0qHHeHpcRRWTxEZJ8xsemoHAXNL5tbooh4tPEEqIqsbWCAJBmUmkwYK/sW5OrFjWWw== dependencies: inherits "^2.0.1" @@ -7189,12 +7818,12 @@ level-packager@^5.1.0: level-supports@^2.0.1: version "2.1.0" - resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-2.1.0.tgz#9af908d853597ecd592293b2fad124375be79c5f" + resolved "https://registry.npmjs.org/level-supports/-/level-supports-2.1.0.tgz" integrity sha512-E486g1NCjW5cF78KGPrMDRBYzPuueMZ6VBXHT6gC7A8UYWGiM14fGgp+s/L1oFfDWSPV/+SFkYCmZ0SiESkRKA== level-supports@^4.0.0: version "4.0.1" - resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-4.0.1.tgz#431546f9d81f10ff0fea0e74533a0e875c08c66a" + resolved "https://registry.npmjs.org/level-supports/-/level-supports-4.0.1.tgz" integrity sha512-PbXpve8rKeNcZ9C1mUicC9auIYFyGpkV9/i6g76tLgANwWhtG2v7I4xNBUlkn3lE2/dZF3Pi0ygYGtLc4RXXdA== level-supports@~1.0.0: @@ -7206,7 +7835,7 @@ level-supports@~1.0.0: level-transcoder@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/level-transcoder/-/level-transcoder-1.0.1.tgz#f8cef5990c4f1283d4c86d949e73631b0bc8ba9c" + resolved "https://registry.npmjs.org/level-transcoder/-/level-transcoder-1.0.1.tgz" integrity sha512-t7bFwFtsQeD8cl8NIoQ2iwxA0CL/9IFw7/9gAjOonH0PWTTiRfY7Hq+Ejbsxh86tXobDQ6IOiddjNYIfOBs06w== dependencies: buffer "^6.0.3" @@ -7221,7 +7850,7 @@ level-write-stream@1.0.0: level-ws@0.0.0: version "0.0.0" - resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-0.0.0.tgz#372e512177924a00424b0b43aef2bb42496d228b" + resolved "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz" integrity sha512-XUTaO/+Db51Uiyp/t7fCMGVFOTdtLS/NIACxE/GHsij15mKzxksZifKVjlXDF41JMUP/oM1Oc4YNGdKnc3dVLw== dependencies: readable-stream "~1.0.15" @@ -7247,7 +7876,7 @@ leveldown@5.6.0, leveldown@^5.4.0: leveldown@6.1.0: version "6.1.0" - resolved "https://registry.yarnpkg.com/leveldown/-/leveldown-6.1.0.tgz#7ab1297706f70c657d1a72b31b40323aa612b9ee" + resolved "https://registry.npmjs.org/leveldown/-/leveldown-6.1.0.tgz" integrity sha512-8C7oJDT44JXxh04aSSsfcMI8YiaGRhOFI9/pMEL7nWJLVsWajDPTRxsSHTM2WcTVY5nXM+SuRHzPPi0GbnDX+w== dependencies: abstract-leveldown "^7.2.0" @@ -7267,7 +7896,7 @@ levelup@4.4.0, levelup@^4.3.2: levelup@^1.2.1: version "1.3.9" - resolved "https://registry.yarnpkg.com/levelup/-/levelup-1.3.9.tgz#2dbcae845b2bb2b6bea84df334c475533bbd82ab" + resolved "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz" integrity sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ== dependencies: deferred-leveldown "~1.2.1" @@ -7280,7 +7909,7 @@ levelup@^1.2.1: levn@~0.3.0: version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + resolved "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz" integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== dependencies: prelude-ls "~1.1.2" @@ -7288,7 +7917,7 @@ levn@~0.3.0: libp2p-crypto@^0.19.0: version "0.19.7" - resolved "https://registry.yarnpkg.com/libp2p-crypto/-/libp2p-crypto-0.19.7.tgz#e96a95bd430e672a695209fe0fbd2bcbd348bc35" + resolved "https://registry.npmjs.org/libp2p-crypto/-/libp2p-crypto-0.19.7.tgz" integrity sha512-Qb5o/3WFKF2j6mYSt4UBPyi2kbKl3jYV0podBJoJCw70DlpM5Xc+oh3fFY9ToSunu8aSQQ5GY8nutjXgX/uGRA== dependencies: err-code "^3.0.1" @@ -7316,7 +7945,7 @@ load-json-file@^1.0.0: locate-path@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz" integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA== dependencies: p-locate "^2.0.0" @@ -7324,7 +7953,7 @@ locate-path@^2.0.0: locate-path@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz" integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== dependencies: p-locate "^3.0.0" @@ -7332,15 +7961,15 @@ locate-path@^3.0.0: locate-path@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== dependencies: p-locate "^5.0.0" lodash-es@^4.2.1: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" - integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== + version "4.18.1" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.18.1.tgz#b962eeb80d9d983a900bf342961fb7418ca10b1d" + integrity sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A== lodash.assign@^4.0.3, lodash.assign@^4.0.6: version "4.2.0" @@ -7349,42 +7978,42 @@ lodash.assign@^4.0.3, lodash.assign@^4.0.6: lodash.camelcase@^4.3.0: version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + resolved "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz" integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== lodash.clonedeep@^4.5.0: version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + resolved "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz" integrity sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ== lodash.debounce@^4.0.8: version "4.0.8" - resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz" integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== lodash.flatmap@^4.5.0: version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.flatmap/-/lodash.flatmap-4.5.0.tgz#ef8cbf408f6e48268663345305c6acc0b778702e" + resolved "https://registry.npmjs.org/lodash.flatmap/-/lodash.flatmap-4.5.0.tgz" integrity sha512-/OcpcAGWlrZyoHGeHh3cAoa6nGdX6QYtmzNP84Jqol6UEQQ2gIaU3H+0eICcjcKGl0/XF8LWOujNn9lffsnaOg== lodash.isequal@^4.5.0: version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + resolved "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz" integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== lodash.keys@^4.2.0: version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-4.2.0.tgz#a08602ac12e4fb83f91fc1fb7a360a4d9ba35205" + resolved "https://registry.npmjs.org/lodash.keys/-/lodash.keys-4.2.0.tgz" integrity sha512-J79MkJcp7Df5mizHiVNpjoHXLi4HLjh9VLS/M7lQSGoQ+0oQ+lWEigREkqKyizPB1IawvQLLKY8mzEcm1tkyxQ== lodash.merge@^4.6.2: version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== lodash.omit@^4.5.0: version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.omit/-/lodash.omit-4.5.0.tgz#6eb19ae5a1ee1dd9df0b969e66ce0b7fa30b5e60" + resolved "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz" integrity sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg== lodash.sortby@^4.7.0: @@ -7394,34 +8023,34 @@ lodash.sortby@^4.7.0: lodash.truncate@^4.4.2: version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" + resolved "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz" integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== lodash.without@^4.4.0: version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.without/-/lodash.without-4.4.0.tgz#3cd4574a00b67bae373a94b748772640507b7aac" + resolved "https://registry.npmjs.org/lodash.without/-/lodash.without-4.4.0.tgz" integrity sha512-M3MefBwfDhgKgINVuBJCO1YR3+gf6s9HNJsIiZ/Ru77Ws6uTb9eBuvrkpzO+9iLoAaRodGuq7tyrPCx+74QYGQ== lodash.xor@^4.5.0: version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.xor/-/lodash.xor-4.5.0.tgz#4d48ed7e98095b0632582ba714d3ff8ae8fb1db6" + resolved "https://registry.npmjs.org/lodash.xor/-/lodash.xor-4.5.0.tgz" integrity sha512-sVN2zimthq7aZ5sPGXnSz32rZPuqcparVW50chJQe+mzTYV+IsxSsl/2gnkWWE2Of7K3myBQBqtLKOUEHJKRsQ== lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.2.1: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + version "4.17.23" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.23.tgz#f113b0378386103be4f6893388c73d0bde7f2c5a" + integrity sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w== log-symbols@3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" + resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz" integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ== dependencies: chalk "^2.4.2" log-symbols@4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz" integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== dependencies: chalk "^4.1.0" @@ -7429,48 +8058,48 @@ log-symbols@4.1.0: loglevel@^1.6.6, loglevel@^1.6.8, loglevel@^1.7.0: version "1.8.1" - resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.8.1.tgz#5c621f83d5b48c54ae93b6156353f555963377b4" + resolved "https://registry.npmjs.org/loglevel/-/loglevel-1.8.1.tgz" integrity sha512-tCRIJM51SHjAayKwC+QAg8hT8vg6z7GSgLJKGvzuPb1Wc+hLzqtuVLxp6/HzSPOozuK+8ErAhy7U/sVzw8Dgfg== long@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" + resolved "https://registry.npmjs.org/long/-/long-4.0.0.tgz" integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== loose-envify@^1.1.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== dependencies: js-tokens "^3.0.0 || ^4.0.0" loupe@^2.3.1: version "2.3.6" - resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.6.tgz#76e4af498103c532d1ecc9be102036a21f787b53" + resolved "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz" integrity sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA== dependencies: get-func-name "^2.0.0" lower-case-first@^1.0.0: version "1.0.2" - resolved "https://registry.yarnpkg.com/lower-case-first/-/lower-case-first-1.0.2.tgz#e5da7c26f29a7073be02d52bac9980e5922adfa1" + resolved "https://registry.npmjs.org/lower-case-first/-/lower-case-first-1.0.2.tgz" integrity sha512-UuxaYakO7XeONbKrZf5FEgkantPf5DUqDayzP5VXZrtRPdH86s4kN47I8B3TW10S4QKiE3ziHNf3kRN//okHjA== dependencies: lower-case "^1.1.2" lower-case@^1.1.0, lower-case@^1.1.1, lower-case@^1.1.2: version "1.1.4" - resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" + resolved "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz" integrity sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA== lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + resolved "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz" integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== lowercase-keys@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + resolved "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz" integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== lowercase-keys@^3.0.0: @@ -7485,26 +8114,26 @@ lowercase-keys@^3.0.0: lru-cache@^10.0.0: version "10.2.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz" integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q== lru-cache@^5.1.1: version "5.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz" integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== dependencies: yallist "^3.0.2" lru-cache@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== dependencies: yallist "^4.0.0" lru_map@^0.3.3: version "0.3.3" - resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" + resolved "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz" integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== ltgt@2.2.1, ltgt@^2.1.2, ltgt@~2.2.0: @@ -7514,17 +8143,22 @@ ltgt@2.2.1, ltgt@^2.1.2, ltgt@~2.2.0: make-error@^1.1.1: version "1.3.6" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== markdown-table@^1.1.3: version "1.1.3" - resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.3.tgz#9fcb69bcfdb8717bfd0398c6ec2d93036ef8de60" + resolved "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.3.tgz" integrity sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q== +math-intrinsics@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" + integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== + md5.js@^1.3.4: version "1.3.5" - resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + resolved "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz" integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== dependencies: hash-base "^3.0.0" @@ -7533,7 +8167,7 @@ md5.js@^1.3.4: media-typer@0.3.0: version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + resolved "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== memdown@1.4.1, memdown@^1.0.0: @@ -7550,29 +8184,29 @@ memdown@1.4.1, memdown@^1.0.0: memorystream@^0.3.1: version "0.3.1" - resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" + resolved "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz" integrity sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw== -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== +merge-descriptors@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz#d80319a65f3c7935351e5cfdac8f9318504dbed5" + integrity sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ== merge-options@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-options/-/merge-options-2.0.0.tgz#36ca5038badfc3974dbde5e58ba89d3df80882c3" + resolved "https://registry.npmjs.org/merge-options/-/merge-options-2.0.0.tgz" integrity sha512-S7xYIeWHl2ZUKF7SDeBhGg6rfv5bKxVBdk95s/I7wVF8d+hjLSztJ/B271cnUiF6CAFduEQ5Zn3HYwAjT16DlQ== dependencies: is-plain-obj "^2.0.0" merge2@^1.2.3, merge2@^1.3.0: version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== merkle-patricia-tree@^2.1.2, merkle-patricia-tree@^2.3.2: version "2.3.2" - resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz#982ca1b5a0fde00eed2f6aeed1f9152860b8208a" + resolved "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz" integrity sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g== dependencies: async "^1.4.2" @@ -7586,20 +8220,25 @@ merkle-patricia-tree@^2.1.2, merkle-patricia-tree@^2.3.2: methods@~1.1.2: version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + resolved "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== +micro-ftch@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/micro-ftch/-/micro-ftch-0.3.1.tgz#6cb83388de4c1f279a034fb0cf96dfc050853c5f" + integrity sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg== + micromatch@^4.0.2, micromatch@^4.0.4: - version "4.0.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== dependencies: - braces "^3.0.2" + braces "^3.0.3" picomatch "^2.3.1" miller-rabin@^4.0.0: version "4.0.1" - resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + resolved "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz" integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== dependencies: bn.js "^4.0.0" @@ -7607,24 +8246,24 @@ miller-rabin@^4.0.0: mime-db@1.52.0: version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: mime-db "1.52.0" mime@1.6.0: version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== mimic-fn@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== mimic-fn@^3.0.0: @@ -7634,74 +8273,67 @@ mimic-fn@^3.0.0: mimic-response@^1.0.0, mimic-response@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + resolved "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz" integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== mimic-response@^3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" + resolved "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz" integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== min-document@^2.19.0: - version "2.19.0" - resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" - integrity sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ== + version "2.19.2" + resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.2.tgz#f95db44639eaae3ac8ea85ae6809ae85ff7e3b81" + integrity sha512-8S5I8db/uZN8r9HSLFVWPdJCvYOejMcEC82VIzNUc6Zkklf/d1gg2psfE79/vyhWOj4+J8MtwmoOz3TmvaGu5A== dependencies: dom-walk "^0.1.0" minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + resolved "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== minimalistic-crypto-utils@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + resolved "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz" integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== -minimatch@*: - version "9.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" - integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== - dependencies: - brace-expansion "^2.0.1" - -"minimatch@2 || 3", minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1: +minimatch@*, "minimatch@2 || 3", minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1: version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" minimatch@3.0.4: version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" minimatch@4.2.1: version "4.2.1" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-4.2.1.tgz#40d9d511a46bdc4e563c22c3080cde9c0d8299b4" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz" integrity sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g== dependencies: brace-expansion "^1.1.7" minimatch@5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz" integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== dependencies: brace-expansion "^2.0.1" minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6, minimist@^1.2.7: version "1.2.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== minipass@^2.6.0, minipass@^2.9.0: version "2.9.0" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" + resolved "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz" integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== dependencies: safe-buffer "^5.1.2" @@ -7709,45 +8341,40 @@ minipass@^2.6.0, minipass@^2.9.0: minizlib@^1.3.3: version "1.3.3" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" + resolved "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz" integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== dependencies: minipass "^2.9.0" mkdirp-promise@^5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" + resolved "https://registry.npmjs.org/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz" integrity sha512-Hepn5kb1lJPtVW84RFT40YG1OddBNTOVUZR2bzQUHc+Z03en8/3uX0+060JDhcEzyO08HmipsN9DcnFMxhIL9w== dependencies: mkdirp "*" -mkdirp@*: - version "3.0.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50" - integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg== +mkdirp@*, mkdirp@0.5.x, mkdirp@^0.5.1, mkdirp@^0.5.5: + version "0.5.6" + resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" mkdirp@0.5.5: version "0.5.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" + resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== dependencies: minimist "^1.2.5" -mkdirp@0.5.x, mkdirp@^0.5.1, mkdirp@^0.5.5: - version "0.5.6" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" - integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== - dependencies: - minimist "^1.2.6" - mkdirp@^1.0.4: version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== mnemonist@^0.38.0: version "0.38.5" - resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.38.5.tgz#4adc7f4200491237fe0fa689ac0b86539685cade" + resolved "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.5.tgz" integrity sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg== dependencies: obliterator "^2.0.0" @@ -7781,7 +8408,7 @@ mocha@10.1.0: mocha@7.1.2: version "7.1.2" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-7.1.2.tgz#8e40d198acf91a52ace122cd7599c9ab857b29e6" + resolved "https://registry.npmjs.org/mocha/-/mocha-7.1.2.tgz" integrity sha512-o96kdRKMKI3E8U0bjnfqW4QMk12MwZ4mhdBTf+B5a1q9+aq2HRnj+3ZdJu0B/ZhJeK78MgYuv6L8d/rA5AeBJA== dependencies: ansi-colors "3.2.3" @@ -7811,7 +8438,7 @@ mocha@7.1.2: mocha@9.2.2: version "9.2.2" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-9.2.2.tgz#d70db46bdb93ca57402c809333e5a84977a88fb9" + resolved "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz" integrity sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g== dependencies: "@ungap/promise-all-settled" "1.1.2" @@ -7841,7 +8468,7 @@ mocha@9.2.2: mocha@^10.0.0: version "10.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.2.0.tgz#1fd4a7c32ba5ac372e03a17eef435bd00e5c68b8" + resolved "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz" integrity sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg== dependencies: ansi-colors "4.1.1" @@ -7868,7 +8495,7 @@ mocha@^10.0.0: mocha@^7.1.1: version "7.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-7.2.0.tgz#01cc227b00d875ab1eed03a75106689cfed5a604" + resolved "https://registry.npmjs.org/mocha/-/mocha-7.2.0.tgz" integrity sha512-O9CIypScywTVpNaRrCAgoUnJgozpIofjKUYmJhiCIJMiuYnLI6otcb1/kpW9/n/tJODHGZ7i8aLQoDVsMtOKQQ== dependencies: ansi-colors "3.2.3" @@ -7898,44 +8525,44 @@ mocha@^7.1.1: mock-fs@^4.1.0: version "4.14.0" - resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.14.0.tgz#ce5124d2c601421255985e6e94da80a7357b1b18" + resolved "https://registry.npmjs.org/mock-fs/-/mock-fs-4.14.0.tgz" integrity sha512-qYvlv/exQ4+svI3UOvPUpLDF0OMX5euvUH0Ny4N5QyRyhNdgAgUrVH3iUINSzEPLvx0kbo/Bp28GJKIqvE7URw== module-error@^1.0.1: version "1.0.2" - resolved "https://registry.yarnpkg.com/module-error/-/module-error-1.0.2.tgz#8d1a48897ca883f47a45816d4fb3e3c6ba404d86" + resolved "https://registry.npmjs.org/module-error/-/module-error-1.0.2.tgz" integrity sha512-0yuvsqSCv8LbaOKhnsQ/T5JhyFlCYLPXK3U2sgV10zoKQwzs/MyfuQUOZQ1V/6OCOJsK/TRgNVrPuPDqtdMFtA== ms@2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== ms@2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz" integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== -ms@2.1.2: +ms@2.1.2, ms@^2.1.1: version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@2.1.3, ms@^2.1.1: +ms@2.1.3: version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== multiaddr-to-uri@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/multiaddr-to-uri/-/multiaddr-to-uri-6.0.0.tgz#8f08a75c6eeb2370d5d24b77b8413e3f0fa9bcc0" + resolved "https://registry.npmjs.org/multiaddr-to-uri/-/multiaddr-to-uri-6.0.0.tgz" integrity sha512-OjpkVHOXEmIKMO8WChzzQ7aZQcSQX8squxmvtDbRpy7/QNmJ3Z7jv6qyD74C28QtaeNie8O8ngW2AkeiMmKP7A== dependencies: multiaddr "^8.0.0" multiaddr@^8.0.0, multiaddr@^8.1.2: version "8.1.2" - resolved "https://registry.yarnpkg.com/multiaddr/-/multiaddr-8.1.2.tgz#74060ff8636ba1c01b2cf0ffd53950b852fa9b1f" + resolved "https://registry.npmjs.org/multiaddr/-/multiaddr-8.1.2.tgz" integrity sha512-r13IzW8+Sv9zab9Gt8RPMIN2WkptIPq99EpAzg4IbJ/zTELhiEwXWr9bAmEatSCI4j/LSA6ESJzvz95JZ+ZYXQ== dependencies: cids "^1.0.0" @@ -7949,7 +8576,7 @@ multiaddr@^8.0.0, multiaddr@^8.1.2: multibase@^0.7.0: version "0.7.0" - resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.7.0.tgz#1adfc1c50abe05eefeb5091ac0c2728d6b84581b" + resolved "https://registry.npmjs.org/multibase/-/multibase-0.7.0.tgz" integrity sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg== dependencies: base-x "^3.0.8" @@ -7957,7 +8584,7 @@ multibase@^0.7.0: multibase@^3.0.0, multibase@^3.1.0: version "3.1.2" - resolved "https://registry.yarnpkg.com/multibase/-/multibase-3.1.2.tgz#59314e1e2c35d018db38e4c20bb79026827f0f2f" + resolved "https://registry.npmjs.org/multibase/-/multibase-3.1.2.tgz" integrity sha512-bpklWHs70LO3smJUHOjcnzGceJJvn9ui0Vau6Za0B/GBepaXswmW8Ufea0uD9pROf/qCQ4N4lZ3sf3U+SNf0tw== dependencies: "@multiformats/base-x" "^4.0.1" @@ -7965,14 +8592,14 @@ multibase@^3.0.0, multibase@^3.1.0: multibase@^4.0.1: version "4.0.6" - resolved "https://registry.yarnpkg.com/multibase/-/multibase-4.0.6.tgz#6e624341483d6123ca1ede956208cb821b440559" + resolved "https://registry.npmjs.org/multibase/-/multibase-4.0.6.tgz" integrity sha512-x23pDe5+svdLz/k5JPGCVdfn7Q5mZVMBETiC+ORfO+sor9Sgs0smJzAjfTbM5tckeCqnaUuMYoz+k3RXMmJClQ== dependencies: "@multiformats/base-x" "^4.0.1" multibase@~0.6.0: version "0.6.1" - resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.6.1.tgz#b76df6298536cc17b9f6a6db53ec88f85f8cc12b" + resolved "https://registry.npmjs.org/multibase/-/multibase-0.6.1.tgz" integrity sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw== dependencies: base-x "^3.0.8" @@ -7980,14 +8607,14 @@ multibase@~0.6.0: multicodec@^0.5.5: version "0.5.7" - resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-0.5.7.tgz#1fb3f9dd866a10a55d226e194abba2dcc1ee9ffd" + resolved "https://registry.npmjs.org/multicodec/-/multicodec-0.5.7.tgz" integrity sha512-PscoRxm3f+88fAtELwUnZxGDkduE2HD9Q6GHUOywQLjOGT/HAdhjLDYNZ1e7VR0s0TP0EwZ16LNUTFpoBGivOA== dependencies: varint "^5.0.0" multicodec@^1.0.0: version "1.0.4" - resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-1.0.4.tgz#46ac064657c40380c28367c90304d8ed175a714f" + resolved "https://registry.npmjs.org/multicodec/-/multicodec-1.0.4.tgz" integrity sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg== dependencies: buffer "^5.6.0" @@ -7995,7 +8622,7 @@ multicodec@^1.0.0: multicodec@^2.0.0, multicodec@^2.0.1: version "2.1.3" - resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-2.1.3.tgz#b9850635ad4e2a285a933151b55b4a2294152a5d" + resolved "https://registry.npmjs.org/multicodec/-/multicodec-2.1.3.tgz" integrity sha512-0tOH2Gtio39uO41o+2xl9UhRkCWxU5ZmZSbFCh/OjGzkWJI8e6lkN/s4Mj1YfyWoBod+2+S3W+6wO6nhkwN8pA== dependencies: uint8arrays "1.1.0" @@ -8003,7 +8630,7 @@ multicodec@^2.0.0, multicodec@^2.0.1: multicodec@^3.0.1: version "3.2.1" - resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-3.2.1.tgz#82de3254a0fb163a107c1aab324f2a91ef51efb2" + resolved "https://registry.npmjs.org/multicodec/-/multicodec-3.2.1.tgz" integrity sha512-+expTPftro8VAW8kfvcuNNNBgb9gPeNYV9dn+z1kJRWF2vih+/S79f2RVeIwmrJBUJ6NT9IUPWnZDQvegEh5pw== dependencies: uint8arrays "^3.0.0" @@ -8011,12 +8638,12 @@ multicodec@^3.0.1: multiformats@^9.4.2, multiformats@^9.4.5: version "9.9.0" - resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-9.9.0.tgz#c68354e7d21037a8f1f8833c8ccd68618e8f1d37" + resolved "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz" integrity sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg== multihashes@3.1.2, multihashes@^3.0.1: version "3.1.2" - resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-3.1.2.tgz#ffa5e50497aceb7911f7b4a3b6cada9b9730edfc" + resolved "https://registry.npmjs.org/multihashes/-/multihashes-3.1.2.tgz" integrity sha512-AP4IoV/YzkNrfbQKZE3OMPibrmy350OmCd6cJkwyM8oExaXIlOY4UnOOVSQtAEuq/LR01XfXKCESidzZvSwHCQ== dependencies: multibase "^3.1.0" @@ -8025,7 +8652,7 @@ multihashes@3.1.2, multihashes@^3.0.1: multihashes@^0.4.15, multihashes@~0.4.15: version "0.4.21" - resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-0.4.21.tgz#dc02d525579f334a7909ade8a122dabb58ccfcb5" + resolved "https://registry.npmjs.org/multihashes/-/multihashes-0.4.21.tgz" integrity sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw== dependencies: buffer "^5.5.0" @@ -8034,7 +8661,7 @@ multihashes@^0.4.15, multihashes@~0.4.15: multihashes@^4.0.1, multihashes@^4.0.2: version "4.0.3" - resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-4.0.3.tgz#426610539cd2551edbf533adeac4c06b3b90fb05" + resolved "https://registry.npmjs.org/multihashes/-/multihashes-4.0.3.tgz" integrity sha512-0AhMH7Iu95XjDLxIeuCOOE4t9+vQZsACyKZ9Fxw2pcsRmlX4iCn1mby0hS0bb+nQOVpdQYWPpnyusw4da5RPhA== dependencies: multibase "^4.0.1" @@ -8043,7 +8670,7 @@ multihashes@^4.0.1, multihashes@^4.0.2: multihashing-async@^2.0.0: version "2.1.4" - resolved "https://registry.yarnpkg.com/multihashing-async/-/multihashing-async-2.1.4.tgz#26dce2ec7a40f0e7f9e732fc23ca5f564d693843" + resolved "https://registry.npmjs.org/multihashing-async/-/multihashing-async-2.1.4.tgz" integrity sha512-sB1MiQXPSBTNRVSJc2zM157PXgDtud2nMFUEIvBrsq5Wv96sUclMRK/ecjoP1T/W61UJBqt4tCTwMkUpt2Gbzg== dependencies: blakejs "^1.1.0" @@ -8055,12 +8682,17 @@ multihashing-async@^2.0.0: murmurhash3js-revisited@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/murmurhash3js-revisited/-/murmurhash3js-revisited-3.0.0.tgz#6bd36e25de8f73394222adc6e41fa3fac08a5869" + resolved "https://registry.npmjs.org/murmurhash3js-revisited/-/murmurhash3js-revisited-3.0.0.tgz" integrity sha512-/sF3ee6zvScXMb1XFJ8gDsSnY+X8PbOyjIuBhtgis10W2Jx4ZjIhikUCIF9c4gpJxVnQIsPAFrSwTCuAjicP6g== -nan@^2.12.1, nan@^2.13.2, nan@^2.14.2: +nan@^2.12.1: + version "2.23.1" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.23.1.tgz#6f86a31dd87e3d1eb77512bf4b9e14c8aded3975" + integrity sha512-r7bBUGKzlqk8oPBDYxt6Z0aEdF1G1rwlMcLk8LCOMbOzf0mG+JUfUzG4fIMWwHWP0iyaLWEQZJmtB7nOHEm/qw== + +nan@^2.13.2, nan@^2.14.2: version "2.17.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb" + resolved "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz" integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== nano-base32@^1.0.1: @@ -8070,51 +8702,51 @@ nano-base32@^1.0.1: nano-json-stream-parser@^0.1.2: version "0.1.2" - resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" + resolved "https://registry.npmjs.org/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz" integrity sha512-9MqxMH/BSJC7dnLsEMPyfN5Dvoo49IsPFYMcHw3Bcfc2kN0lpHRBSzlMSVx4HGyJ7s9B31CyBTVehWJoQ8Ctew== nanoid@3.3.1: version "3.3.1" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" + resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz" integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== nanoid@3.3.3: version "3.3.3" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" + resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz" integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== nanoid@^3.1.12, nanoid@^3.1.3: version "3.3.6" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" + resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz" integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== napi-macros@~2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/napi-macros/-/napi-macros-2.0.0.tgz#2b6bae421e7b96eb687aa6c77a7858640670001b" + resolved "https://registry.npmjs.org/napi-macros/-/napi-macros-2.0.0.tgz" integrity sha512-A0xLykHtARfueITVDernsAWdtIMbOJgKgcluwENp3AlsKN/PloyO10HtmoqnFAQAcxPkgZN7wdfPfEd0zNGxbg== native-abort-controller@0.0.3, native-abort-controller@~0.0.3: version "0.0.3" - resolved "https://registry.yarnpkg.com/native-abort-controller/-/native-abort-controller-0.0.3.tgz#4c528a6c9c7d3eafefdc2c196ac9deb1a5edf2f8" + resolved "https://registry.npmjs.org/native-abort-controller/-/native-abort-controller-0.0.3.tgz" integrity sha512-YIxU5nWqSHG1Xbu3eOu3pdFRD882ivQpIcu6AiPVe2oSVoRbfYW63DVkZm3g1gHiMtZSvZzF6THSzTGEBYl8YA== dependencies: globalthis "^1.0.1" native-abort-controller@^1.0.3: version "1.0.4" - resolved "https://registry.yarnpkg.com/native-abort-controller/-/native-abort-controller-1.0.4.tgz#39920155cc0c18209ff93af5bc90be856143f251" + resolved "https://registry.npmjs.org/native-abort-controller/-/native-abort-controller-1.0.4.tgz" integrity sha512-zp8yev7nxczDJMoP6pDxyD20IU0T22eX8VwN2ztDccKvSZhRaV33yP1BGwKSZfXuqWUzsXopVFjBdau9OOAwMQ== native-fetch@^2.0.0: version "2.0.1" - resolved "https://registry.yarnpkg.com/native-fetch/-/native-fetch-2.0.1.tgz#319d53741a7040def92d5dc8ea5fe9416b1fad89" + resolved "https://registry.npmjs.org/native-fetch/-/native-fetch-2.0.1.tgz" integrity sha512-gv4Bea+ga9QdXINurpkEqun3ap3vnB+WYoe4c8ddqUYEH7B2h6iD39RF8uVN7OwmSfMY3RDxkvBnoI4e2/vLXQ== dependencies: globalthis "^1.0.1" native-fetch@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/native-fetch/-/native-fetch-3.0.0.tgz#06ccdd70e79e171c365c75117959cf4fe14a09bb" + resolved "https://registry.npmjs.org/native-fetch/-/native-fetch-3.0.0.tgz" integrity sha512-G3Z7vx0IFb/FQ4JxvtqGABsOTIqRWvgQz6e+erkB+JJD6LrszQtMozEHI4EkmgZQvnGHrpLVzUWk7t4sJCIkVw== needle@^2.2.1: @@ -8128,27 +8760,22 @@ needle@^2.2.1: negotiator@0.6.3: version "0.6.3" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== neo-async@^2.6.2: version "2.6.2" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== next-tick@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" + resolved "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz" integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== - no-case@^2.2.0, no-case@^2.3.2: version "2.3.2" - resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac" + resolved "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz" integrity sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ== dependencies: lower-case "^1.1.1" @@ -8160,19 +8787,19 @@ node-abort-controller@^3.0.1: node-addon-api@^2.0.0: version "2.0.2" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" + resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz" integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== node-emoji@^1.10.0: version "1.11.0" - resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.11.0.tgz#69a0150e6946e2f115e9d7ea4df7971e2628301c" + resolved "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz" integrity sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A== dependencies: lodash "^4.17.21" node-environment-flags@1.0.6: version "1.0.6" - resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.6.tgz#a30ac13621f6f7d674260a54dede048c3982c088" + resolved "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz" integrity sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw== dependencies: object.getownpropertydescriptors "^2.0.3" @@ -8185,16 +8812,23 @@ node-fetch@2.6.7: dependencies: whatwg-url "^5.0.0" -node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.12, node-fetch@^2.6.7: +node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7: version "2.6.12" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.12.tgz#02eb8e22074018e3d5a83016649d04df0e348fba" + resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz" integrity sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g== dependencies: whatwg-url "^5.0.0" +node-fetch@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + node-fetch@~1.7.1: version "1.7.3" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" + resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz" integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== dependencies: encoding "^0.1.11" @@ -8202,17 +8836,17 @@ node-fetch@~1.7.1: node-forge@^0.10.0: version "0.10.0" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" + resolved "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz" integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA== node-gyp-build@4.4.0: version "4.4.0" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.4.0.tgz#42e99687ce87ddeaf3a10b99dc06abc11021f3f4" + resolved "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.4.0.tgz" integrity sha512-amJnQCcgtRVw9SvoebO3BKGESClrfXGCUTX9hSn1OuGQTQBOZmVd0Z0OlecpuRksKvbsUqALE8jls/ErClAPuQ== node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: version "4.6.0" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055" + resolved "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.0.tgz" integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ== node-gyp-build@~4.1.0: @@ -8222,7 +8856,7 @@ node-gyp-build@~4.1.0: node-interval-tree@^1.3.3: version "1.3.3" - resolved "https://registry.yarnpkg.com/node-interval-tree/-/node-interval-tree-1.3.3.tgz#15ffb904cde08270214acace8dc7653e89ae32b7" + resolved "https://registry.npmjs.org/node-interval-tree/-/node-interval-tree-1.3.3.tgz" integrity sha512-K9vk96HdTK5fEipJwxSvIIqwTqr4e3HRJeJrNxBSeVMNSC/JWARRaX7etOLOuTmrRMeOI/K5TCJu3aWIwZiNTw== dependencies: shallowequal "^1.0.2" @@ -8243,19 +8877,19 @@ node-pre-gyp@^0.11.0: semver "^5.3.0" tar "^4" -node-releases@^2.0.13: - version "2.0.13" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.13.tgz#d5ed1627c23e3461e819b02e57b75e4899b1c81d" - integrity sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ== +node-releases@^2.0.27: + version "2.0.27" + resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz" + integrity sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA== nofilter@^1.0.4: version "1.0.4" - resolved "https://registry.yarnpkg.com/nofilter/-/nofilter-1.0.4.tgz#78d6f4b6a613e7ced8b015cec534625f7667006e" + resolved "https://registry.npmjs.org/nofilter/-/nofilter-1.0.4.tgz" integrity sha512-N8lidFp+fCz+TD51+haYdbDGrcBWwuHX40F5+z0qkUjMJ5Tp+rdSuAkMJ9N9eoolDlEVTf6u5icM+cNKkKW2mA== nofilter@^3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/nofilter/-/nofilter-3.1.0.tgz#c757ba68801d41ff930ba2ec55bab52ca184aa66" + resolved "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz" integrity sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g== noop-fn@^1.0.0: @@ -8265,7 +8899,7 @@ noop-fn@^1.0.0: nopt@3.x: version "3.0.6" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + resolved "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz" integrity sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg== dependencies: abbrev "1" @@ -8290,17 +8924,17 @@ normalize-package-data@^2.3.2: normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== normalize-url@^4.1.0: version "4.5.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" + resolved "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz" integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== normalize-url@^6.0.1: version "6.1.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" + resolved "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz" integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== npm-bundled@^1.0.1: @@ -8341,7 +8975,7 @@ number-is-nan@^1.0.0: number-to-bn@1.7.0: version "1.7.0" - resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" + resolved "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz" integrity sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig== dependencies: bn.js "4.11.6" @@ -8349,32 +8983,37 @@ number-to-bn@1.7.0: oauth-sign@~0.9.0: version "0.9.0" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + resolved "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== object-assign@^4, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== object-inspect@^1.12.3, object-inspect@^1.9.0: version "1.12.3" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" + resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz" integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== +object-inspect@^1.13.3: + version "1.13.4" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213" + integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew== + object-keys@^1.0.11, object-keys@^1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== object-keys@~0.4.0: version "0.4.0" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" + resolved "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz" integrity sha512-ncrLw+X55z7bkl5PnUvHwFK9FcGuFYo9gtjws2XtSzL+aZ8tm830P60WJ0dSmFVaSalWieW5MD7kEdnXda9yJw== object.assign@4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz" integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== dependencies: define-properties "^1.1.2" @@ -8384,7 +9023,7 @@ object.assign@4.1.0: object.assign@^4.1.4: version "4.1.4" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" + resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz" integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== dependencies: call-bind "^1.0.2" @@ -8394,7 +9033,7 @@ object.assign@^4.1.4: object.getownpropertydescriptors@^2.0.3: version "2.1.6" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.6.tgz#5e5c384dd209fa4efffead39e3a0512770ccc312" + resolved "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.6.tgz" integrity sha512-lq+61g26E/BgHv0ZTFgRvi7NMEPuAxLkFU7rukXjc/AlwH4Am5xXVnIXy3un1bg/JPbXHrixRkK1itUzzPiIjQ== dependencies: array.prototype.reduce "^1.0.5" @@ -8405,40 +9044,40 @@ object.getownpropertydescriptors@^2.0.3: obliterator@^2.0.0: version "2.0.4" - resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.4.tgz#fa650e019b2d075d745e44f1effeb13a2adbe816" + resolved "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz" integrity sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ== oboe@2.1.5: version "2.1.5" - resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.5.tgz#5554284c543a2266d7a38f17e073821fbde393cd" + resolved "https://registry.npmjs.org/oboe/-/oboe-2.1.5.tgz" integrity sha512-zRFWiF+FoicxEs3jNI/WYUrVEgA7DeET/InK0XQuudGHRg8iIob3cNPrJTKaz4004uaA9Pbe+Dwa8iluhjLZWA== dependencies: http-https "^1.0.0" -on-finished@2.4.1: +on-finished@2.4.1, on-finished@~2.4.1: version "2.4.1" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz" integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== dependencies: ee-first "1.1.1" once@1.x, once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" onetime@^5.1.0, onetime@^5.1.2: version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + resolved "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== dependencies: mimic-fn "^2.1.0" open@^7.4.2: version "7.4.2" - resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" + resolved "https://registry.npmjs.org/open/-/open-7.4.2.tgz" integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== dependencies: is-docker "^2.0.0" @@ -8446,7 +9085,7 @@ open@^7.4.2: optionator@^0.8.1: version "0.8.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + resolved "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz" integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== dependencies: deep-is "~0.1.3" @@ -8458,12 +9097,12 @@ optionator@^0.8.1: ordinal@^1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/ordinal/-/ordinal-1.0.3.tgz#1a3c7726a61728112f50944ad7c35c06ae3a0d4d" + resolved "https://registry.npmjs.org/ordinal/-/ordinal-1.0.3.tgz" integrity sha512-cMddMgb2QElm8G7vdaa02jhUNbTSrhsgAGUz1OokD83uJTwSUn+nKoNoKVVaRa08yF6sgfO7Maou1+bgLd9rdQ== original-require@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/original-require/-/original-require-1.0.1.tgz#0f130471584cd33511c5ec38c8d59213f9ac5e20" + resolved "https://registry.npmjs.org/original-require/-/original-require-1.0.1.tgz" integrity sha512-5vdKMbE58WaE61uVD+PKyh8xdM398UnjPBLotW2sjG5MzHARwta/+NtMBCBA0t2WQblGYBvq5vsiZpWokwno+A== os-homedir@^1.0.0: @@ -8493,12 +9132,12 @@ osenv@^0.1.4: p-cancelable@^1.0.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" + resolved "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz" integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== p-cancelable@^2.0.0: version "2.1.1" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf" + resolved "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz" integrity sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg== p-cancelable@^3.0.0: @@ -8508,12 +9147,12 @@ p-cancelable@^3.0.0: p-defer@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-3.0.0.tgz#d1dceb4ee9b2b604b1d94ffec83760175d4e6f83" + resolved "https://registry.npmjs.org/p-defer/-/p-defer-3.0.0.tgz" integrity sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw== p-fifo@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/p-fifo/-/p-fifo-1.0.0.tgz#e29d5cf17c239ba87f51dde98c1d26a9cfe20a63" + resolved "https://registry.npmjs.org/p-fifo/-/p-fifo-1.0.0.tgz" integrity sha512-IjoCxXW48tqdtDFz6fqo5q1UfFVjjVZe8TC1QRflvNUJtNfCUhxOUw6MOVZhDPjqhSzc26xKdugsO17gmzd5+A== dependencies: fast-fifo "^1.0.0" @@ -8521,80 +9160,80 @@ p-fifo@^1.0.0: p-limit@^1.1.0: version "1.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz" integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== dependencies: p-try "^1.0.0" p-limit@^2.0.0: version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== dependencies: p-try "^2.0.0" p-limit@^3.0.2: version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== dependencies: yocto-queue "^0.1.0" p-locate@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz" integrity sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg== dependencies: p-limit "^1.1.0" p-locate@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz" integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== dependencies: p-limit "^2.0.0" p-locate@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz" integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== dependencies: p-limit "^3.0.2" p-map@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + resolved "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz" integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== dependencies: aggregate-error "^3.0.0" p-try@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + resolved "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz" integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww== p-try@^2.0.0: version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== param-case@^2.1.0: version "2.1.1" - resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247" + resolved "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz" integrity sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w== dependencies: no-case "^2.2.0" paramap-it@^0.1.1: version "0.1.1" - resolved "https://registry.yarnpkg.com/paramap-it/-/paramap-it-0.1.1.tgz#dad5963c003315c0993b84402a9c08f8c36e80d9" + resolved "https://registry.npmjs.org/paramap-it/-/paramap-it-0.1.1.tgz" integrity sha512-3uZmCAN3xCw7Am/4ikGzjjR59aNMJVXGSU7CjG2Z6DfOAdhnLdCOd0S0m1sTkN4ov9QhlE3/jkzyu953hq0uwQ== dependencies: event-iterator "^1.0.0" parse-asn1@^5.0.0, parse-asn1@^5.1.6: version "5.1.6" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" + resolved "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz" integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== dependencies: asn1.js "^5.2.0" @@ -8605,17 +9244,17 @@ parse-asn1@^5.0.0, parse-asn1@^5.1.6: parse-cache-control@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/parse-cache-control/-/parse-cache-control-1.0.1.tgz#8eeab3e54fa56920fe16ba38f77fa21aacc2d74e" + resolved "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz" integrity sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg== parse-duration@^0.4.4: version "0.4.4" - resolved "https://registry.yarnpkg.com/parse-duration/-/parse-duration-0.4.4.tgz#11c0f51a689e97d06c57bd772f7fda7dc013243c" + resolved "https://registry.npmjs.org/parse-duration/-/parse-duration-0.4.4.tgz" integrity sha512-KbAJuYGUhZkB9gotDiKLnZ7Z3VTacK3fgwmDdB6ZVDtJbMBT6MfLga0WJaYpPDu0mzqT0NgHtHDt5PY4l0nidg== parse-headers@^2.0.0: version "2.0.5" - resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.5.tgz#069793f9356a54008571eb7f9761153e6c770da9" + resolved "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.5.tgz" integrity sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA== parse-json@^2.2.0: @@ -8627,40 +9266,40 @@ parse-json@^2.2.0: parseurl@^1.3.3, parseurl@~1.3.3: version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + resolved "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== pascal-case@^2.0.0, pascal-case@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-2.0.1.tgz#2d578d3455f660da65eca18ef95b4e0de912761e" + resolved "https://registry.npmjs.org/pascal-case/-/pascal-case-2.0.1.tgz" integrity sha512-qjS4s8rBOJa2Xm0jmxXiyh1+OFf6ekCWOvUaRgAQSktzlTbMotS0nmG9gyYAybCWBcuP4fsBeRCKNwGBnMe2OQ== dependencies: camel-case "^3.0.0" upper-case-first "^1.1.0" -patch-package@^6.4.7: - version "6.5.1" - resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.5.1.tgz#3e5d00c16997e6160291fee06a521c42ac99b621" - integrity sha512-I/4Zsalfhc6bphmJTlrLoOcAF87jcxko4q0qsv4bGcurbr8IskEOtdnt9iCmsQVGL1B+iUhSQqweyTLJfCF9rA== +patch-package@^8.0.0: + version "8.0.1" + resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-8.0.1.tgz#79d02f953f711e06d1f8949c8a13e5d3d7ba1a60" + integrity sha512-VsKRIA8f5uqHQ7NGhwIna6Bx6D9s/1iXlA1hthBVBEbkq+t4kXD0HHt+rJhf/Z+Ci0F/HCB2hvn0qLdLG+Qxlw== dependencies: "@yarnpkg/lockfile" "^1.1.0" chalk "^4.1.2" - cross-spawn "^6.0.5" + ci-info "^3.7.0" + cross-spawn "^7.0.3" find-yarn-workspace-root "^2.0.0" - fs-extra "^9.0.0" - is-ci "^2.0.0" + fs-extra "^10.0.0" + json-stable-stringify "^1.0.2" klaw-sync "^6.0.0" minimist "^1.2.6" open "^7.4.2" - rimraf "^2.6.3" - semver "^5.6.0" + semver "^7.5.3" slash "^2.0.0" - tmp "^0.0.33" - yaml "^1.10.2" + tmp "^0.2.4" + yaml "^2.2.2" path-case@^2.1.0: version "2.1.1" - resolved "https://registry.yarnpkg.com/path-case/-/path-case-2.1.1.tgz#94b8037c372d3fe2906e465bb45e25d226e8eea5" + resolved "https://registry.npmjs.org/path-case/-/path-case-2.1.1.tgz" integrity sha512-Ou0N05MioItesaLr9q8TtHVWmJ6fxWdqKB2RohFmNWVyJ+2zeKIeDNWAN6B/Pe7wpzWChhZX6nONYmOnMeJQ/Q== dependencies: no-case "^2.2.0" @@ -8674,33 +9313,33 @@ path-exists@^2.0.0: path-exists@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz" integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== path-exists@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== path-is-absolute@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== -path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== path-parse@^1.0.6, path-parse@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== +path-to-regexp@0.1.12: + version "0.1.12" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.12.tgz#d5e1a12e478a976d432ef3c58d534b9923164bb7" + integrity sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ== path-type@^1.0.0: version "1.1.0" @@ -8713,28 +9352,29 @@ path-type@^1.0.0: path-type@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== pathval@^1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" + resolved "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz" integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== pbkdf2@^3.0.17, pbkdf2@^3.0.3: - version "3.1.2" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" - integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== + version "3.1.5" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.5.tgz#444a59d7a259a95536c56e80c89de31cc01ed366" + integrity sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ== dependencies: - create-hash "^1.1.2" - create-hmac "^1.1.4" - ripemd160 "^2.0.1" - safe-buffer "^5.0.1" - sha.js "^2.4.8" + create-hash "^1.2.0" + create-hmac "^1.1.7" + ripemd160 "^2.0.3" + safe-buffer "^5.2.1" + sha.js "^2.4.12" + to-buffer "^1.2.1" peer-id@^0.14.1: version "0.14.8" - resolved "https://registry.yarnpkg.com/peer-id/-/peer-id-0.14.8.tgz#667c6bedc8ab313c81376f6aca0baa2140266fab" + resolved "https://registry.npmjs.org/peer-id/-/peer-id-0.14.8.tgz" integrity sha512-GpuLpob/9FrEFvyZrKKsISEkaBYsON2u0WtiawLHj1ii6ewkoeRiSDFLyIefYhw0jGvQoeoZS05jaT52X7Bvig== dependencies: cids "^1.1.5" @@ -8747,25 +9387,25 @@ peer-id@^0.14.1: pem-jwk@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/pem-jwk/-/pem-jwk-2.0.0.tgz#1c5bb264612fc391340907f5c1de60c06d22f085" + resolved "https://registry.npmjs.org/pem-jwk/-/pem-jwk-2.0.0.tgz" integrity sha512-rFxu7rVoHgQ5H9YsP50dDWf0rHjreVA2z0yPiWr5WdH/UHb29hKtF7h6l8vNd1cbYR1t0QL+JKhW55a2ZV4KtA== dependencies: asn1.js "^5.0.1" performance-now@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + resolved "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz" integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== +picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + version "2.3.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.2.tgz#5a942915e26b372dc0f0e6753149a16e6b1c5601" + integrity sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA== pify@^2.0.0: version "2.3.0" @@ -8774,12 +9414,12 @@ pify@^2.0.0: pify@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + resolved "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz" integrity sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg== pify@^4.0.1: version "4.0.1" - resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + resolved "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz" integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== pinkie-promise@^2.0.0: @@ -8806,6 +9446,11 @@ pluralize@^8.0.0: resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== +possible-typed-array-names@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz#93e3582bc0e5426586d9d07b79ee40fc841de4ae" + integrity sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg== + pouchdb-abstract-mapreduce@7.3.1: version "7.3.1" resolved "https://registry.yarnpkg.com/pouchdb-abstract-mapreduce/-/pouchdb-abstract-mapreduce-7.3.1.tgz#96ff4a0f41cbe273f3f52fde003b719005a2093c" @@ -9081,37 +9726,37 @@ pouchdb@7.3.0: precond@0.2: version "0.2.3" - resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac" + resolved "https://registry.npmjs.org/precond/-/precond-0.2.3.tgz" integrity sha512-QCYG84SgGyGzqJ/vlMsxeXd/pgL/I94ixdNFyh1PusWmTCyVfPJjZ1K1jvHtsbfnXQs2TSkEP2fR7QiMZAnKFQ== prelude-ls@~1.1.2: version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz" integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== prepend-http@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" + resolved "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz" integrity sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA== prettier@^2.3.1: version "2.8.8" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" + resolved "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz" integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== process-nextick-args@~2.0.0: version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== process@^0.11.10: version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + resolved "https://registry.npmjs.org/process/-/process-0.11.10.tgz" integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== promise-to-callback@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/promise-to-callback/-/promise-to-callback-1.0.0.tgz#5d2a749010bfb67d963598fcd3960746a68feef7" + resolved "https://registry.npmjs.org/promise-to-callback/-/promise-to-callback-1.0.0.tgz" integrity sha512-uhMIZmKM5ZteDMfLgJnoSq9GCwsNKrYau73Awf1jIy6/eUcuuZ3P+CD9zUv0kJsIUbU+x6uLNIhXhLHDs1pNPA== dependencies: is-fn "^1.0.0" @@ -9119,14 +9764,14 @@ promise-to-callback@^1.0.0: promise@^8.0.0: version "8.3.0" - resolved "https://registry.yarnpkg.com/promise/-/promise-8.3.0.tgz#8cb333d1edeb61ef23869fbb8a4ea0279ab60e0a" + resolved "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz" integrity sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg== dependencies: asap "~2.0.6" proper-lockfile@^4.1.1: version "4.1.2" - resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-4.1.2.tgz#c8b9de2af6b2f1601067f98e01ac66baa223141f" + resolved "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz" integrity sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA== dependencies: graceful-fs "^4.2.4" @@ -9135,7 +9780,7 @@ proper-lockfile@^4.1.1: protobufjs@^6.10.2, protobufjs@^6.11.2: version "6.11.4" - resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.4.tgz#29a412c38bf70d89e537b6d02d904a6f448173aa" + resolved "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz" integrity sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw== dependencies: "@protobufjs/aspromise" "^1.1.2" @@ -9154,12 +9799,12 @@ protobufjs@^6.10.2, protobufjs@^6.11.2: protocol-buffers-schema@^3.3.1: version "3.6.0" - resolved "https://registry.yarnpkg.com/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz#77bc75a48b2ff142c1ad5b5b90c94cd0fa2efd03" + resolved "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz" integrity sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw== protons@^2.0.0: version "2.0.3" - resolved "https://registry.yarnpkg.com/protons/-/protons-2.0.3.tgz#94f45484d04b66dfedc43ad3abff1e8907994bb2" + resolved "https://registry.npmjs.org/protons/-/protons-2.0.3.tgz" integrity sha512-j6JikP/H7gNybNinZhAHMN07Vjr1i4lVupg598l4I9gSTjJqOvKnwjzYX2PzvBTSVf2eZ2nWv4vG+mtW8L6tpA== dependencies: protocol-buffers-schema "^3.3.1" @@ -9169,7 +9814,7 @@ protons@^2.0.0: proxy-addr@~2.0.7: version "2.0.7" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + resolved "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz" integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== dependencies: forwarded "0.2.0" @@ -9177,22 +9822,29 @@ proxy-addr@~2.0.7: proxy-from-env@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + resolved "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== prr@~1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + resolved "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz" integrity sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw== -psl@^1.1.28, psl@^1.1.33: +psl@^1.1.28: version "1.9.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + resolved "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz" integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== +psl@^1.1.33: + version "1.15.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.15.0.tgz#bdace31896f1d97cec6a79e8224898ce93d974c6" + integrity sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w== + dependencies: + punycode "^2.3.1" + public-encrypt@^4.0.0: version "4.0.3" - resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" + resolved "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz" integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== dependencies: bn.js "^4.1.0" @@ -9204,7 +9856,7 @@ public-encrypt@^4.0.0: pump@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + resolved "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz" integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== dependencies: end-of-stream "^1.1.0" @@ -9212,25 +9864,30 @@ pump@^3.0.0: punycode@2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d" + resolved "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz" integrity sha512-Yxz2kRwT90aPiWEMHVYnEf4+rhwF1tBmmZ4KepCP+Wkium9JxtWnUm1nqGwpiAHr/tnTSeHqr3wb++jgSkXjhA== punycode@^2.1.0, punycode@^2.1.1: version "2.3.0" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz" integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== +punycode@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + pure-rand@^5.0.1: version "5.0.5" - resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-5.0.5.tgz#bda2a7f6a1fc0f284d78d78ca5902f26f2ad35cf" + resolved "https://registry.npmjs.org/pure-rand/-/pure-rand-5.0.5.tgz" integrity sha512-BwQpbqxSCBJVpamI6ydzcKqyFmnd5msMWUGvzXLm1aXvusbbgkbOto/EUPM00hjveJEaJtdbhUjKSzWRhQVkaw== -qs@6.11.0: - version "6.11.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" - integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== +qs@6.13.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906" + integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg== dependencies: - side-channel "^1.0.4" + side-channel "^1.0.6" qs@^6.4.0: version "6.11.2" @@ -9239,14 +9896,21 @@ qs@^6.4.0: dependencies: side-channel "^1.0.4" +qs@~6.14.0: + version "6.14.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.14.0.tgz#c63fa40680d2c5c941412a0e899c89af60c0a930" + integrity sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w== + dependencies: + side-channel "^1.1.0" + qs@~6.5.2: version "6.5.3" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" + resolved "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz" integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== query-string@^5.0.1: version "5.1.1" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" + resolved "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz" integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== dependencies: decode-uri-component "^0.2.0" @@ -9260,24 +9924,29 @@ querystringify@^2.1.1: queue-microtask@^1.2.2, queue-microtask@^1.2.3: version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +queue-tick@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.0.tgz" + integrity sha512-ULWhjjE8BmiICGn3G8+1L9wFpERNxkf8ysxkAer4+TFdRefDaXOCV5m92aMB9FtBVmn/8sETXLXY6BfW7hyaWQ== + quick-lru@^5.1.1: version "5.1.1" - resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" + resolved "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz" integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== dependencies: safe-buffer "^5.1.0" randomfill@^1.0.3: version "1.0.4" - resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + resolved "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz" integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== dependencies: randombytes "^2.0.5" @@ -9285,12 +9954,12 @@ randomfill@^1.0.3: range-parser@~1.2.1: version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== raw-body@2.5.2, raw-body@^2.4.1: version "2.5.2" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" + resolved "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz" integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== dependencies: bytes "3.1.2" @@ -9298,6 +9967,16 @@ raw-body@2.5.2, raw-body@^2.4.1: iconv-lite "0.4.24" unpipe "1.0.0" +raw-body@~2.5.3: + version "2.5.3" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.3.tgz#11c6650ee770a7de1b494f197927de0c923822e2" + integrity sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA== + dependencies: + bytes "~3.1.2" + http-errors "~2.0.1" + iconv-lite "~0.4.24" + unpipe "~1.0.0" + rc@^1.2.7: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" @@ -9337,14 +10016,14 @@ readable-stream@1.1.14, readable-stream@^1.0.33: "readable-stream@2 || 3", readable-stream@^3.4.0, readable-stream@^3.6.0, readable-stream@^3.6.2: version "3.6.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== dependencies: inherits "^2.0.3" string_decoder "^1.1.1" util-deprecate "^1.0.1" -readable-stream@^2.0.0, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.2.9: +readable-stream@^2.0.0, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.2.9, readable-stream@^2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== @@ -9364,7 +10043,7 @@ readable-stream@~0.0.2: readable-stream@~1.0.15: version "1.0.34" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz" integrity sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg== dependencies: core-util-is "~1.0.0" @@ -9374,54 +10053,54 @@ readable-stream@~1.0.15: readdirp@~3.2.0: version "3.2.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.2.0.tgz#c30c33352b12c96dfb4b895421a49fd5a9593839" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz" integrity sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ== dependencies: picomatch "^2.0.4" readdirp@~3.6.0: version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== dependencies: picomatch "^2.2.1" receptacle@^1.3.2: version "1.3.2" - resolved "https://registry.yarnpkg.com/receptacle/-/receptacle-1.3.2.tgz#a7994c7efafc7a01d0e2041839dab6c4951360d2" + resolved "https://registry.npmjs.org/receptacle/-/receptacle-1.3.2.tgz" integrity sha512-HrsFvqZZheusncQRiEE7GatOAETrARKV/lnfYicIm8lbvp/JQOdADOfhjBd2DajvoszEyxSM6RlAAIZgEoeu/A== dependencies: ms "^2.1.1" rechoir@^0.6.2: version "0.6.2" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + resolved "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz" integrity sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw== dependencies: resolve "^1.1.6" recursive-readdir@^2.2.2: version "2.2.3" - resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.3.tgz#e726f328c0d69153bcabd5c322d3195252379372" + resolved "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz" integrity sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA== dependencies: minimatch "^3.0.5" reduce-flatten@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27" + resolved "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz" integrity sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w== redux-saga@1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/redux-saga/-/redux-saga-1.0.0.tgz#acb8b3ed9180fecbe75f342011d75af3ac11045b" + resolved "https://registry.npmjs.org/redux-saga/-/redux-saga-1.0.0.tgz" integrity sha512-GvJWs/SzMvEQgeaw6sRMXnS2FghlvEGsHiEtTLpJqc/FHF3I5EE/B+Hq5lyHZ8LSoT2r/X/46uWvkdCnK9WgHA== dependencies: "@redux-saga/core" "^1.0.0" redux@^3.7.2: version "3.7.2" - resolved "https://registry.yarnpkg.com/redux/-/redux-3.7.2.tgz#06b73123215901d25d065be342eb026bc1c8537b" + resolved "https://registry.npmjs.org/redux/-/redux-3.7.2.tgz" integrity sha512-pNqnf9q1hI5HHZRBkj3bAngGZW/JMCmexDlOxw4XagXY2o1327nHH54LoTjiPJ0gizoqPDRqWyX/00g0hD6w+A== dependencies: lodash "^4.2.1" @@ -9431,19 +10110,14 @@ redux@^3.7.2: redux@^4.0.4: version "4.2.1" - resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.1.tgz#c08f4306826c49b5e9dc901dee0452ea8fce6197" + resolved "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz" integrity sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w== dependencies: "@babel/runtime" "^7.9.2" -regenerator-runtime@^0.14.0: - version "0.14.0" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz#5e19d68eb12d486f797e15a3c6a918f7cec5eb45" - integrity sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA== - regexp.prototype.flags@^1.5.0: version "1.5.0" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz#fe7ce25e7e4cca8db37b6634c8a2c7009199b9cb" + resolved "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz" integrity sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA== dependencies: call-bind "^1.0.2" @@ -9452,28 +10126,28 @@ regexp.prototype.flags@^1.5.0: req-cwd@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/req-cwd/-/req-cwd-2.0.0.tgz#d4082b4d44598036640fb73ddea01ed53db49ebc" + resolved "https://registry.npmjs.org/req-cwd/-/req-cwd-2.0.0.tgz" integrity sha512-ueoIoLo1OfB6b05COxAA9UpeoscNpYyM+BqYlA7H6LVF4hKGPXQQSSaD2YmvDVJMkk4UDpAHIeU1zG53IqjvlQ== dependencies: req-from "^2.0.0" req-from@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/req-from/-/req-from-2.0.0.tgz#d74188e47f93796f4aa71df6ee35ae689f3e0e70" + resolved "https://registry.npmjs.org/req-from/-/req-from-2.0.0.tgz" integrity sha512-LzTfEVDVQHBRfjOUMgNBA+V6DWsSnoeKzf42J7l0xa/B4jyPOuuF5MlNSmomLNGemWTnV2TIdjSSLnEn95fOQA== dependencies: resolve-from "^3.0.0" request-promise-core@1.1.4: version "1.1.4" - resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f" + resolved "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz" integrity sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw== dependencies: lodash "^4.17.19" request-promise-native@^1.0.5: version "1.0.9" - resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.9.tgz#e407120526a5efdc9a39b28a5679bf47b9d9dc28" + resolved "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz" integrity sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g== dependencies: request-promise-core "1.1.4" @@ -9482,7 +10156,7 @@ request-promise-native@^1.0.5: request@^2.79.0, request@^2.85.0, request@^2.88.0: version "2.88.2" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + resolved "https://registry.npmjs.org/request/-/request-2.88.2.tgz" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== dependencies: aws-sign2 "~0.7.0" @@ -9508,7 +10182,7 @@ request@^2.79.0, request@^2.85.0, request@^2.88.0: require-directory@^2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== require-from-string@^1.1.0: @@ -9518,7 +10192,7 @@ require-from-string@^1.1.0: require-from-string@^2.0.0, require-from-string@^2.0.2: version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + resolved "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== require-main-filename@^1.0.1: @@ -9528,7 +10202,7 @@ require-main-filename@^1.0.1: require-main-filename@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + resolved "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz" integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== requires-port@^1.0.0: @@ -9538,7 +10212,7 @@ requires-port@^1.0.0: reselect-tree@^1.3.7: version "1.3.7" - resolved "https://registry.yarnpkg.com/reselect-tree/-/reselect-tree-1.3.7.tgz#c3eca58765d9df96bae0017f6ff3504c304cdea0" + resolved "https://registry.npmjs.org/reselect-tree/-/reselect-tree-1.3.7.tgz" integrity sha512-kZN+C1cVJ6fFN2smSb0l4UvYZlRzttgnu183svH4NrU22cBY++ikgr2QT75Uuk4MYpv5gXSVijw4c5U6cx6GKg== dependencies: debug "^3.1.0" @@ -9547,62 +10221,62 @@ reselect-tree@^1.3.7: reselect@^4.0.0: version "4.1.8" - resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.1.8.tgz#3f5dc671ea168dccdeb3e141236f69f02eaec524" + resolved "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz" integrity sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ== reset@^0.1.0: version "0.1.0" - resolved "https://registry.yarnpkg.com/reset/-/reset-0.1.0.tgz#9fc7314171995ae6cb0b7e58b06ce7522af4bafb" + resolved "https://registry.npmjs.org/reset/-/reset-0.1.0.tgz" integrity sha512-RF7bp2P2ODreUPA71FZ4DSK52gNLJJ8dSwA1nhOCoC0mI4KZ4D/W6zhd2nfBqX/JlR+QZ/iUqAYPjq1UQU8l0Q== resolve-alpn@^1.0.0, resolve-alpn@^1.2.0: version "1.2.1" - resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" + resolved "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz" integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g== resolve-from@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz" integrity sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw== resolve@1.1.x: version "1.1.7" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" + resolved "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz" integrity sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg== -resolve@1.17.0: +resolve@1.17.0, resolve@^1.1.6, resolve@^1.14.2: version "1.17.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + resolved "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz" integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== dependencies: path-parse "^1.0.6" -resolve@^1.1.6, resolve@^1.10.0, resolve@^1.14.2: - version "1.22.4" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.4.tgz#1dc40df46554cdaf8948a486a10f6ba1e2026c34" - integrity sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg== +resolve@^1.10.0: + version "1.22.11" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.11.tgz#aad857ce1ffb8bfa9b0b1ac29f1156383f68c262" + integrity sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ== dependencies: - is-core-module "^2.13.0" + is-core-module "^2.16.1" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" responselike@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" + resolved "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz" integrity sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ== dependencies: lowercase-keys "^1.0.0" responselike@^2.0.0: version "2.0.1" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.1.tgz#9a0bc8fdc252f3fb1cca68b016591059ba1422bc" + resolved "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz" integrity sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw== dependencies: lowercase-keys "^2.0.0" restore-cursor@^3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz" integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== dependencies: onetime "^5.1.0" @@ -9610,25 +10284,25 @@ restore-cursor@^3.1.0: retimer@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/retimer/-/retimer-2.0.0.tgz#e8bd68c5e5a8ec2f49ccb5c636db84c04063bbca" + resolved "https://registry.npmjs.org/retimer/-/retimer-2.0.0.tgz" integrity sha512-KLXY85WkEq2V2bKex/LOO1ViXVn2KGYe4PYysAdYdjmraYIUsVkXu8O4am+8+5UbaaGl1qho4aqAAPHNQ4GSbg== retry@0.13.1: version "0.13.1" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" + resolved "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz" integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== retry@^0.12.0: version "0.12.0" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + resolved "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz" integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== reusify@^1.0.4: version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rimraf@^2.2.8, rimraf@^2.6.1, rimraf@^2.6.3: +rimraf@^2.2.8, rimraf@^2.6.1: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -9640,24 +10314,32 @@ ripemd160-min@0.0.6: resolved "https://registry.yarnpkg.com/ripemd160-min/-/ripemd160-min-0.0.6.tgz#a904b77658114474d02503e819dcc55853b67e62" integrity sha512-+GcJgQivhs6S9qvLogusiTcS9kQUfgR75whKuy5jIhuiOfQuJ8fjqxV6EGD5duH1Y/FawFUMtMhyeq3Fbnib8A== -ripemd160@^2.0.0, ripemd160@^2.0.1, ripemd160@^2.0.2: +ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" - resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + resolved "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz" integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== dependencies: hash-base "^3.0.0" inherits "^2.0.1" +ripemd160@^2.0.2, ripemd160@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.3.tgz#9be54e4ba5e3559c8eee06a25cd7648bbccdf5a8" + integrity sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA== + dependencies: + hash-base "^3.1.2" + inherits "^2.0.4" + rlp@^2.0.0, rlp@^2.2.3, rlp@^2.2.4: version "2.2.7" - resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" + resolved "https://registry.npmjs.org/rlp/-/rlp-2.2.7.tgz" integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== dependencies: bn.js "^5.2.0" rpc-websockets@^7.4.17: version "7.5.1" - resolved "https://registry.yarnpkg.com/rpc-websockets/-/rpc-websockets-7.5.1.tgz#e0a05d525a97e7efc31a0617f093a13a2e10c401" + resolved "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-7.5.1.tgz" integrity sha512-kGFkeTsmd37pHPMaHIgN1LVKXMi0JD782v4Ds9ZKtLlwdTKjn+CxM9A9/gLT2LaOuEcEFGL98h1QWQtlOIdW0w== dependencies: "@babel/runtime" "^7.17.2" @@ -9670,45 +10352,45 @@ rpc-websockets@^7.4.17: run-parallel@^1.1.9: version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== dependencies: queue-microtask "^1.2.2" run@^1.4.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/run/-/run-1.4.0.tgz#e17d9e9043ab2fe17776cb299e1237f38f0b4ffa" + resolved "https://registry.npmjs.org/run/-/run-1.4.0.tgz" integrity sha512-962oBW07IjQ9SizyMHdoteVbDKt/e2nEsnTRZ0WjK/zs+jfQQICqH0qj0D5lqZNuy0JkbzfA6IOqw0Sk7C3DlQ== dependencies: minimatch "*" rust-verkle-wasm@^0.0.1: version "0.0.1" - resolved "https://registry.yarnpkg.com/rust-verkle-wasm/-/rust-verkle-wasm-0.0.1.tgz#fd8396a7060d8ee8ea10da50ab6e862948095a74" + resolved "https://registry.npmjs.org/rust-verkle-wasm/-/rust-verkle-wasm-0.0.1.tgz" integrity sha512-BN6fiTsxcd2dCECz/cHtGTt9cdLJR925nh7iAuRcj8ymKw7OOaPmCneQZ7JePOJ/ia27TjEL91VdOi88Yf+mcA== rustbn-wasm@^0.2.0: version "0.2.0" - resolved "https://registry.yarnpkg.com/rustbn-wasm/-/rustbn-wasm-0.2.0.tgz#0407521fb55ae69eeb4968d01885d63efd1c4ff9" + resolved "https://registry.npmjs.org/rustbn-wasm/-/rustbn-wasm-0.2.0.tgz" integrity sha512-FThvYFNTqrEKGqXuseeg0zR7yROh/6U1617mCHF68OVqrN1tNKRN7Tdwy4WayPVsCmmK+eMxtIZX1qL6JxTkMg== dependencies: "@scure/base" "^1.1.1" rustbn.js@~0.2.0: version "0.2.0" - resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" + resolved "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.2.0.tgz" integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== rxjs@6: version "6.6.7" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" + resolved "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz" integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== dependencies: tslib "^1.9.0" safe-array-concat@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.0.tgz#2064223cba3c08d2ee05148eedbc563cd6d84060" + resolved "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz" integrity sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ== dependencies: call-bind "^1.0.2" @@ -9718,24 +10400,24 @@ safe-array-concat@^1.0.0: safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== safe-event-emitter@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/safe-event-emitter/-/safe-event-emitter-1.0.1.tgz#5b692ef22329ed8f69fdce607e50ca734f6f20af" + resolved "https://registry.npmjs.org/safe-event-emitter/-/safe-event-emitter-1.0.1.tgz" integrity sha512-e1wFe99A91XYYxoQbcq2ZJUWurxEyP8vfz7A7vuUe1s95q8r5ebraVaA1BukYJcpM6V16ugWoD9vngi8Ccu5fg== dependencies: events "^3.0.0" safe-regex-test@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" + resolved "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz" integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== dependencies: call-bind "^1.0.2" @@ -9744,17 +10426,17 @@ safe-regex-test@^1.0.0: "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== sax@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + version "1.4.3" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.3.tgz#fcebae3b756cdc8428321805f4b70f16ec0ab5db" + integrity sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ== sc-istanbul@^0.4.5: version "0.4.6" - resolved "https://registry.yarnpkg.com/sc-istanbul/-/sc-istanbul-0.4.6.tgz#cf6784355ff2076f92d70d59047d71c13703e839" + resolved "https://registry.npmjs.org/sc-istanbul/-/sc-istanbul-0.4.6.tgz" integrity sha512-qJFF/8tW/zJsbyfh/iT/ZM5QNHE3CXxtLJbZsL+CzdJLBsPD7SedJZoUA4d8iAcN2IoMp/Dx80shOOd2x96X/g== dependencies: abbrev "1.0.x" @@ -9774,22 +10456,22 @@ sc-istanbul@^0.4.5: scrypt-async@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/scrypt-async/-/scrypt-async-2.0.1.tgz#4318dae48a8b7cc3b8fe05f75f4164a7d973d25d" + resolved "https://registry.npmjs.org/scrypt-async/-/scrypt-async-2.0.1.tgz" integrity sha512-wHR032jldwZNy7Tzrfu7RccOgGf8r5hyDMSP2uV6DpLiBUsR8JsDcx/in73o2UGVVrH5ivRFdNsFPcjtl3LErQ== scrypt-js@2.0.4: version "2.0.4" - resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.4.tgz#32f8c5149f0797672e551c07e230f834b6af5f16" + resolved "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.4.tgz" integrity sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw== scrypt-js@3.0.1, scrypt-js@^3.0.0, scrypt-js@^3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" + resolved "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz" integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== secp256k1@4.0.3, secp256k1@^4.0.0, secp256k1@^4.0.1: version "4.0.3" - resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" + resolved "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.3.tgz" integrity sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA== dependencies: elliptic "^6.5.4" @@ -9798,54 +10480,59 @@ secp256k1@4.0.3, secp256k1@^4.0.0, secp256k1@^4.0.1: seedrandom@^3.0.5: version "3.0.5" - resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.5.tgz#54edc85c95222525b0c7a6f6b3543d8e0b3aa0a7" + resolved "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz" integrity sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg== semaphore@>=1.0.1, semaphore@^1.0.3: version "1.1.0" - resolved "https://registry.yarnpkg.com/semaphore/-/semaphore-1.1.0.tgz#aaad8b86b20fe8e9b32b16dc2ee682a8cd26a8aa" + resolved "https://registry.npmjs.org/semaphore/-/semaphore-1.1.0.tgz" integrity sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA== -"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0, semver@^5.6.0, semver@^5.7.0: +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0, semver@^5.7.0: version "5.7.2" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== semver@7.3.7: version "7.3.7" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" + resolved "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz" integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== dependencies: lru-cache "^6.0.0" semver@7.5.2: version "7.5.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.2.tgz#5b851e66d1be07c1cdaf37dfc856f543325a2beb" + resolved "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz" integrity sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ== dependencies: lru-cache "^6.0.0" semver@^6.3.0, semver@^6.3.1: version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== semver@^7.3.4, semver@^7.3.5: version "7.5.4" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + resolved "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz" integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== dependencies: lru-cache "^6.0.0" +semver@^7.5.3, semver@^7.5.4: + version "7.7.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.3.tgz#4b5f4143d007633a8dc671cd0a6ef9147b8bb946" + integrity sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q== + semver@~5.4.1: version "5.4.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" + resolved "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz" integrity sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg== -send@0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" - integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== +send@0.19.0: + version "0.19.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8" + integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw== dependencies: debug "2.6.9" depd "2.0.0" @@ -9863,7 +10550,7 @@ send@0.18.0: sentence-case@^2.1.0: version "2.1.1" - resolved "https://registry.yarnpkg.com/sentence-case/-/sentence-case-2.1.1.tgz#1f6e2dda39c168bf92d13f86d4a918933f667ed4" + resolved "https://registry.npmjs.org/sentence-case/-/sentence-case-2.1.1.tgz" integrity sha512-ENl7cYHaK/Ktwk5OTD+aDbQ3uC8IByu/6Bkg+HDv8Mm+XnBnppVNalcfJTNsp1ibstKh030/JKQQWglDvtKwEQ== dependencies: no-case "^2.2.0" @@ -9871,24 +10558,24 @@ sentence-case@^2.1.0: serialize-javascript@6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz" integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== dependencies: randombytes "^2.1.0" -serve-static@1.15.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" - integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== +serve-static@1.16.2: + version "1.16.2" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.2.tgz#b6a5343da47f6bdd2673848bf45754941e803296" + integrity sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw== dependencies: - encodeurl "~1.0.2" + encodeurl "~2.0.0" escape-html "~1.0.3" parseurl "~1.3.3" - send "0.18.0" + send "0.19.0" servify@^0.1.12: version "0.1.12" - resolved "https://registry.yarnpkg.com/servify/-/servify-0.1.12.tgz#142ab7bee1f1d033b66d0707086085b17c06db95" + resolved "https://registry.npmjs.org/servify/-/servify-0.1.12.tgz" integrity sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw== dependencies: body-parser "^1.16.0" @@ -9902,37 +10589,50 @@ set-blocking@^2.0.0, set-blocking@~2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== +set-function-length@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + set-immediate-shim@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" + resolved "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz" integrity sha512-Li5AOqrZWCVA2n5kryzEmqai6bKSIvpz5oUJHPVj6+dsbD3X1ixtsY5tEnsaNpH3pFAHmG8eIHUrtEtohrg+UQ== setimmediate@1.0.4: version "1.0.4" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.4.tgz#20e81de622d4a02588ce0c8da8973cbcf1d3138f" + resolved "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz" integrity sha512-/TjEmXQVEzdod/FFskf3o7oOAsGhHf2j1dZqRFbDzq4F3mvvxflIIi4Hd3bLQE9y/CpwqfSQam5JakI/mi3Pog== setimmediate@^1.0.5: version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + resolved "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz" integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== -setprototypeof@1.2.0: +setprototypeof@1.2.0, setprototypeof@~1.2.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz" integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== -sha.js@^2.4.0, sha.js@^2.4.11, sha.js@^2.4.8: - version "2.4.11" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== +sha.js@^2.4.0, sha.js@^2.4.11, sha.js@^2.4.12, sha.js@^2.4.8: + version "2.4.12" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.12.tgz#eb8b568bf383dfd1867a32c3f2b74eb52bdbf23f" + integrity sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w== dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" + inherits "^2.0.4" + safe-buffer "^5.2.1" + to-buffer "^1.2.0" sha1@^1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/sha1/-/sha1-1.1.1.tgz#addaa7a93168f393f19eb2b15091618e2700f848" + resolved "https://registry.npmjs.org/sha1/-/sha1-1.1.1.tgz" integrity sha512-dZBS6OrMjtgVkopB1Gmo4RQCDKiZsqcpAQpkV/aaj+FCrCg8r4I4qMkDPQjBgLIxlmu9k4nUbWq6ohXahOneYA== dependencies: charenc ">= 0.0.1" @@ -9947,59 +10647,99 @@ sha3@^2.1.1: shallowequal@^1.0.2: version "1.1.0" - resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" + resolved "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz" integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ== -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== dependencies: - shebang-regex "^1.0.0" + shebang-regex "^3.0.0" -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== shelljs@^0.8.3: version "0.8.5" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c" + resolved "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz" integrity sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow== dependencies: glob "^7.0.0" interpret "^1.0.0" rechoir "^0.6.2" +side-channel-list@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad" + integrity sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + +side-channel-map@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/side-channel-map/-/side-channel-map-1.0.1.tgz#d6bb6b37902c6fef5174e5f533fab4c732a26f42" + integrity sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + +side-channel-weakmap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz#11dda19d5368e40ce9ec2bdc1fb0ecbc0790ecea" + integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + side-channel-map "^1.0.1" + side-channel@^1.0.4: version "1.0.4" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz" integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== dependencies: call-bind "^1.0.0" get-intrinsic "^1.0.2" object-inspect "^1.9.0" +side-channel@^1.0.6, side-channel@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" + integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + side-channel-list "^1.0.0" + side-channel-map "^1.0.1" + side-channel-weakmap "^1.0.2" + signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== signed-varint@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/signed-varint/-/signed-varint-2.0.1.tgz#50a9989da7c98c2c61dad119bc97470ef8528129" + resolved "https://registry.npmjs.org/signed-varint/-/signed-varint-2.0.1.tgz" integrity sha512-abgDPg1106vuZZOvw7cFwdCABddfJRz5akcCcchzTbhyhYnsG31y4AlZEgp315T7W3nQq5P4xeOm186ZiPVFzw== dependencies: varint "~5.0.0" simple-concat@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" + resolved "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz" integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== simple-get@^2.7.0: version "2.8.2" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.2.tgz#5708fb0919d440657326cd5fe7d2599d07705019" + resolved "https://registry.npmjs.org/simple-get/-/simple-get-2.8.2.tgz" integrity sha512-Ijd/rV5o+mSBBs4F/x9oDPtTx9Zb6X9brmnXvMW4J7IR15ngi9q5xxqWBKU744jTZiaXtxaPL7uHG6vtN8kUkw== dependencies: decompress-response "^3.3.0" @@ -10008,17 +10748,17 @@ simple-get@^2.7.0: slash@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" + resolved "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz" integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== slash@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== slice-ansi@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz" integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== dependencies: ansi-styles "^4.0.0" @@ -10027,14 +10767,14 @@ slice-ansi@^4.0.0: snake-case@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-2.1.0.tgz#41bdb1b73f30ec66a04d4e2cad1b76387d4d6d9f" + resolved "https://registry.npmjs.org/snake-case/-/snake-case-2.1.0.tgz" integrity sha512-FMR5YoPFwOLuh4rRz92dywJjyKYZNLpMn1R5ujVpIYkbA9p01fq8RMg0FkO4M+Yobt4MjHeLTJVm5xFFBHSV2Q== dependencies: no-case "^2.2.0" solc@0.7.3: version "0.7.3" - resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a" + resolved "https://registry.npmjs.org/solc/-/solc-0.7.3.tgz" integrity sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA== dependencies: command-exists "^1.2.8" @@ -10060,12 +10800,12 @@ solc@^0.4.20: solidity-ast@^0.4.26: version "0.4.49" - resolved "https://registry.yarnpkg.com/solidity-ast/-/solidity-ast-0.4.49.tgz#ecba89d10c0067845b7848c3a3e8cc61a4fc5b82" + resolved "https://registry.npmjs.org/solidity-ast/-/solidity-ast-0.4.49.tgz" integrity sha512-Pr5sCAj1SFqzwFZw1HPKSq0PehlQNdM8GwKyAVYh2DOn7/cCK8LUKD1HeHnKtTgBW7hi9h4nnnan7hpAg5RhWQ== solidity-coverage@^0.8.4: version "0.8.4" - resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.8.4.tgz#c57a21979f5e86859c5198de9fbae2d3bc6324a5" + resolved "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.8.4.tgz" integrity sha512-xeHOfBOjdMF6hWTbt42iH4x+7j1Atmrf5OldDPMxI+i/COdExUxszOswD9qqvcBTaLGiOrrpnh9UZjSpt4rBsg== dependencies: "@ethersproject/abi" "^5.0.9" @@ -10091,7 +10831,7 @@ solidity-coverage@^0.8.4: source-map-support@^0.5.13: version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz" integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== dependencies: buffer-from "^1.0.0" @@ -10099,12 +10839,12 @@ source-map-support@^0.5.13: source-map@^0.6.0, source-map@^0.6.1: version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== source-map@~0.2.0: version "0.2.0" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz" integrity sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA== dependencies: amdefine ">=0.0.4" @@ -10128,9 +10868,9 @@ spdx-correct@^3.0.0: spdx-license-ids "^3.0.0" spdx-exceptions@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" - integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + version "2.5.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz#5d607d27fc806f66d7b64a766650fa890f04ed66" + integrity sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w== spdx-expression-parse@^3.0.0: version "3.0.1" @@ -10141,13 +10881,13 @@ spdx-expression-parse@^3.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.13" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz#7189a474c46f8d47c7b0da4b987bb45e908bd2d5" - integrity sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w== + version "3.0.22" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz#abf5a08a6f5d7279559b669f47f0a43e8f3464ef" + integrity sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ== sprintf-js@~1.0.2: version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== sqlite3@^4.0.0: @@ -10160,7 +10900,7 @@ sqlite3@^4.0.0: sshpk@^1.7.0: version "1.17.0" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" + resolved "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz" integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== dependencies: asn1 "~0.2.3" @@ -10175,41 +10915,46 @@ sshpk@^1.7.0: stable@^0.1.8: version "0.1.8" - resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" + resolved "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz" integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== stacktrace-parser@^0.1.10: version "0.1.10" - resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" + resolved "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz" integrity sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg== dependencies: type-fest "^0.7.1" statuses@2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== +statuses@~2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.2.tgz#8f75eecef765b5e1cfcdc080da59409ed424e382" + integrity sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw== + stealthy-require@^1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" + resolved "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz" integrity sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g== stream-to-it@^0.2.0, stream-to-it@^0.2.2: version "0.2.4" - resolved "https://registry.yarnpkg.com/stream-to-it/-/stream-to-it-0.2.4.tgz#d2fd7bfbd4a899b4c0d6a7e6a533723af5749bd0" + resolved "https://registry.npmjs.org/stream-to-it/-/stream-to-it-0.2.4.tgz" integrity sha512-4vEbkSs83OahpmBybNJXlJd7d6/RxzkkSdT3I0mnGt79Xd2Kk+e1JqbvAvsQfCeKj3aKb0QIWkyK3/n0j506vQ== dependencies: get-iterator "^1.0.2" strict-uri-encode@^1.0.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" + resolved "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz" integrity sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ== string-format@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/string-format/-/string-format-2.0.0.tgz#f2df2e7097440d3b65de31b6d40d54c96eaffb9b" + resolved "https://registry.npmjs.org/string-format/-/string-format-2.0.0.tgz" integrity sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA== string-width@^1.0.1: @@ -10223,7 +10968,7 @@ string-width@^1.0.1: "string-width@^1.0.2 || 2", string-width@^2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + resolved "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== dependencies: is-fullwidth-code-point "^2.0.0" @@ -10231,7 +10976,7 @@ string-width@^1.0.1: "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== dependencies: emoji-regex "^8.0.0" @@ -10240,16 +10985,25 @@ string-width@^1.0.1: string-width@^3.0.0, string-width@^3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + resolved "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz" integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== dependencies: emoji-regex "^7.0.1" is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" +string-width@^7.0.0, string-width@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-7.2.0.tgz#b5bb8e2165ce275d4d43476dd2700ad9091db6dc" + integrity sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ== + dependencies: + emoji-regex "^10.3.0" + get-east-asian-width "^1.0.0" + strip-ansi "^7.1.0" + string.prototype.trim@^1.2.7: version "1.2.7" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533" + resolved "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz" integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg== dependencies: call-bind "^1.0.2" @@ -10258,7 +11012,7 @@ string.prototype.trim@^1.2.7: string.prototype.trimend@^1.0.6: version "1.0.6" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" + resolved "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz" integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ== dependencies: call-bind "^1.0.2" @@ -10267,7 +11021,7 @@ string.prototype.trimend@^1.0.6: string.prototype.trimstart@^1.0.6: version "1.0.6" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4" + resolved "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz" integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA== dependencies: call-bind "^1.0.2" @@ -10276,19 +11030,19 @@ string.prototype.trimstart@^1.0.6: string_decoder@^1.1.1: version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== dependencies: safe-buffer "~5.2.0" string_decoder@~0.10.x: version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== string_decoder@~1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== dependencies: safe-buffer "~5.1.0" @@ -10302,25 +11056,32 @@ strip-ansi@^3.0.0, strip-ansi@^3.0.1: strip-ansi@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz" integrity sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow== dependencies: ansi-regex "^3.0.0" strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz" integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== dependencies: ansi-regex "^4.1.0" strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: ansi-regex "^5.0.1" +strip-ansi@^7.1.0: + version "7.1.2" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.2.tgz#132875abde678c7ea8d691533f2e7e22bb744dba" + integrity sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA== + dependencies: + ansi-regex "^6.0.1" + strip-bom@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" @@ -10330,7 +11091,7 @@ strip-bom@^2.0.0: strip-hex-prefix@1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" + resolved "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz" integrity sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A== dependencies: is-hex-prefixed "1.0.0" @@ -10342,7 +11103,7 @@ strip-json-comments@2.0.1, strip-json-comments@~2.0.1: strip-json-comments@3.1.1: version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== sublevel-pouchdb@7.3.1: @@ -10357,35 +11118,35 @@ sublevel-pouchdb@7.3.1: supports-color@6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz" integrity sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg== dependencies: has-flag "^3.0.0" supports-color@8.1.1: version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== dependencies: has-flag "^4.0.0" supports-color@^3.1.0: version "3.2.3" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz" integrity sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A== dependencies: has-flag "^1.0.0" supports-color@^5.3.0: version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" supports-color@^7.1.0: version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: has-flag "^4.0.0" @@ -10397,7 +11158,7 @@ supports-preserve-symlinks-flag@^1.0.0: swap-case@^1.1.0: version "1.1.2" - resolved "https://registry.yarnpkg.com/swap-case/-/swap-case-1.1.2.tgz#c39203a4587385fad3c850a0bd1bcafa081974e3" + resolved "https://registry.npmjs.org/swap-case/-/swap-case-1.1.2.tgz" integrity sha512-BAmWG6/bx8syfc6qXPprof3Mn5vQgf5dwdUNJhsNqU9WdPt5P+ES/wQ5bxfijy8zwZgZZHslC3iAsxsuQMCzJQ== dependencies: lower-case "^1.1.1" @@ -10405,7 +11166,7 @@ swap-case@^1.1.0: swarm-js@^0.1.40: version "0.1.42" - resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.42.tgz#497995c62df6696f6e22372f457120e43e727979" + resolved "https://registry.npmjs.org/swarm-js/-/swarm-js-0.1.42.tgz" integrity sha512-BV7c/dVlA3R6ya1lMlSSNPLYrntt0LUq4YMgy3iwpCIc6rZnS5W2wUoctarZ5pXlpKtxDDf9hNziEkcfrxdhqQ== dependencies: bluebird "^3.5.0" @@ -10422,12 +11183,12 @@ swarm-js@^0.1.40: symbol-observable@^1.0.3: version "1.2.0" - resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" + resolved "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz" integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== sync-request@^6.0.0: version "6.1.0" - resolved "https://registry.yarnpkg.com/sync-request/-/sync-request-6.1.0.tgz#e96217565b5e50bbffe179868ba75532fb597e68" + resolved "https://registry.npmjs.org/sync-request/-/sync-request-6.1.0.tgz" integrity sha512-8fjNkrNlNCrVc/av+Jn+xxqfCjYaBoHqCsDz6mt030UMxJGr+GSfCV1dQt2gRtlL63+VPidwDVLr7V2OcTSdRw== dependencies: http-response-object "^3.0.1" @@ -10436,14 +11197,14 @@ sync-request@^6.0.0: sync-rpc@^1.2.1: version "1.3.6" - resolved "https://registry.yarnpkg.com/sync-rpc/-/sync-rpc-1.3.6.tgz#b2e8b2550a12ccbc71df8644810529deb68665a7" + resolved "https://registry.npmjs.org/sync-rpc/-/sync-rpc-1.3.6.tgz" integrity sha512-J8jTXuZzRlvU7HemDgHi3pGnh/rkoqR/OZSjhTyyZrEkkYQbk7Z33AXp37mkPfPpfdOuj7Ex3H/TJM1z48uPQw== dependencies: get-port "^3.1.0" table-layout@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-1.0.2.tgz#c4038a1853b0136d63365a734b6931cf4fad4a04" + resolved "https://registry.npmjs.org/table-layout/-/table-layout-1.0.2.tgz" integrity sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A== dependencies: array-back "^4.0.1" @@ -10453,7 +11214,7 @@ table-layout@^1.0.2: table@^6.8.0: version "6.8.1" - resolved "https://registry.yarnpkg.com/table/-/table-6.8.1.tgz#ea2b71359fe03b017a5fbc296204471158080bdf" + resolved "https://registry.npmjs.org/table/-/table-6.8.1.tgz" integrity sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA== dependencies: ajv "^8.0.1" @@ -10464,7 +11225,7 @@ table@^6.8.0: tar@^4, tar@^4.0.2: version "4.4.19" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3" + resolved "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz" integrity sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA== dependencies: chownr "^1.1.4" @@ -10482,7 +11243,7 @@ testrpc@0.0.1: then-request@^6.0.0: version "6.0.2" - resolved "https://registry.yarnpkg.com/then-request/-/then-request-6.0.2.tgz#ec18dd8b5ca43aaee5cb92f7e4c1630e950d4f0c" + resolved "https://registry.npmjs.org/then-request/-/then-request-6.0.2.tgz" integrity sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA== dependencies: "@types/concat-stream" "^1.6.0" @@ -10507,12 +11268,12 @@ through2@3.0.2: timed-out@^4.0.1: version "4.0.1" - resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" + resolved "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz" integrity sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA== timeout-abort-controller@^1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/timeout-abort-controller/-/timeout-abort-controller-1.1.1.tgz#2c3c3c66f13c783237987673c276cbd7a9762f29" + resolved "https://registry.npmjs.org/timeout-abort-controller/-/timeout-abort-controller-1.1.1.tgz" integrity sha512-BsF9i3NAJag6T0ZEjki9j654zoafI2X6ayuNd6Tp8+Ul6Tr5s4jo973qFeiWrRSweqvskC+AHDKUmIW4b7pdhQ== dependencies: abort-controller "^3.0.0" @@ -10525,7 +11286,7 @@ tiny-queue@^0.2.1: tiny-secp256k1@^1.1.3: version "1.1.7" - resolved "https://registry.yarnpkg.com/tiny-secp256k1/-/tiny-secp256k1-1.1.7.tgz#0c1b6b9d2d93404f9093dc7e287b0aa834480573" + resolved "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-1.1.7.tgz" integrity sha512-eb+F6NabSnjbLwNoC+2o5ItbmP1kg7HliWue71JgLegQt6A5mTN8YbvTLCazdlg6e5SV6A+r8OGvZYskdlmhqQ== dependencies: bindings "^1.3.0" @@ -10541,32 +11302,41 @@ tiny-typed-emitter@^2.1.0: title-case@^2.1.0: version "2.1.1" - resolved "https://registry.yarnpkg.com/title-case/-/title-case-2.1.1.tgz#3e127216da58d2bc5becf137ab91dae3a7cd8faa" + resolved "https://registry.npmjs.org/title-case/-/title-case-2.1.1.tgz" integrity sha512-EkJoZ2O3zdCz3zJsYCsxyq2OC5hrxR9mfdd5I+w8h/tmFfeOxJ+vvkxsKxdmN0WtS9zLdHEgfgVOiMVgv+Po4Q== dependencies: no-case "^2.2.0" upper-case "^1.0.3" -tmp@0.0.33, tmp@^0.0.33: +tmp@0.0.33: version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + resolved "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz" integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== dependencies: os-tmpdir "~1.0.2" +tmp@^0.2.4: + version "0.2.5" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.5.tgz#b06bcd23f0f3c8357b426891726d16015abfd8f8" + integrity sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow== + +to-buffer@^1.2.0, to-buffer@^1.2.1, to-buffer@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.2.2.tgz#ffe59ef7522ada0a2d1cb5dfe03bb8abc3cdc133" + integrity sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw== + dependencies: + isarray "^2.0.5" + safe-buffer "^5.2.1" + typed-array-buffer "^1.0.3" + to-data-view@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/to-data-view/-/to-data-view-1.1.0.tgz#08d6492b0b8deb9b29bdf1f61c23eadfa8994d00" + resolved "https://registry.npmjs.org/to-data-view/-/to-data-view-1.1.0.tgz" integrity sha512-1eAdufMg6mwgmlojAx3QeMnzB/BTVp7Tbndi3U7ftcT2zCZadjxkkmLmd97zmaxWi+sgGcgWrokmpEoy0Dn0vQ== -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== - to-json-schema@^0.2.5: version "0.2.5" - resolved "https://registry.yarnpkg.com/to-json-schema/-/to-json-schema-0.2.5.tgz#ef3c3f11ad64460dcfbdbafd0fd525d69d62a98f" + resolved "https://registry.npmjs.org/to-json-schema/-/to-json-schema-0.2.5.tgz" integrity sha512-jP1ievOee8pec3tV9ncxLSS48Bnw7DIybgy112rhMCEhf3K4uyVNZZHr03iQQBzbV5v5Hos+dlZRRyk6YSMNDw== dependencies: lodash.isequal "^4.5.0" @@ -10578,33 +11348,33 @@ to-json-schema@^0.2.5: to-readable-stream@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" + resolved "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz" integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== to-regex-range@^5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== dependencies: is-number "^7.0.0" -toidentifier@1.0.1: +toidentifier@1.0.1, toidentifier@~1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== tough-cookie@^2.3.3, tough-cookie@~2.5.0: version "2.5.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz" integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== dependencies: psl "^1.1.28" punycode "^2.1.1" "tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0": - version "4.1.3" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf" - integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw== + version "4.1.4" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.4.tgz#945f1461b45b5a8c76821c33ea49c3ac192c1b36" + integrity sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag== dependencies: psl "^1.1.33" punycode "^2.1.1" @@ -10613,20 +11383,34 @@ tough-cookie@^2.3.3, tough-cookie@~2.5.0: tr46@~0.0.3: version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + resolved "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== truffle-assertions@^0.9.2: version "0.9.2" - resolved "https://registry.yarnpkg.com/truffle-assertions/-/truffle-assertions-0.9.2.tgz#0f8360f53ad92b6d8fdb8ceb5dce54c1fc392e23" + resolved "https://registry.npmjs.org/truffle-assertions/-/truffle-assertions-0.9.2.tgz" integrity sha512-9g2RhaxU2F8DeWhqoGQvL/bV8QVoSnQ6PY+ZPvYRP5eF7+/8LExb4mjLx/FeliLTjc3Tv1SABG05Gu5qQ/ErmA== dependencies: assertion-error "^1.1.0" lodash.isequal "^4.5.0" -truffle@5.5.8: +truffle@5.11.5: + version "5.11.5" + resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.11.5.tgz#b0a3a9308c417dbe0290307d7698316d3e8eabe8" + integrity sha512-yCa2uWs5DmL0spuJUuIMtnVayRQrVuWLtcRXHMB0NLrtWDcRo7VM9RViveV4+oi9LdZ8VpFmmqHGm43LbzUxOA== + dependencies: + "@truffle/db-loader" "^0.2.36" + "@truffle/debugger" "^12.1.5" + app-module-path "^2.2.0" + ganache "7.9.1" + mocha "10.1.0" + original-require "^1.0.1" + optionalDependencies: + "@truffle/db" "^2.0.36" + +truffle@^5.4.14: version "5.5.8" - resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.5.8.tgz#79346b8478d87de1962b57c44dcd057658253716" + resolved "https://registry.npmjs.org/truffle/-/truffle-5.5.8.tgz" integrity sha512-zH7MHKzeeNyafTba2LENKM99ldob7VW8n4vzFUdiyWjzMA2HLiWv0oIrr2IxuXWROCOGaO+iI0rhAOS8ojodbA== dependencies: "@truffle/db-loader" "^0.1.10" @@ -10642,23 +11426,9 @@ truffle@5.5.8: "@truffle/preserve-to-filecoin" "^0.2.8" "@truffle/preserve-to-ipfs" "^0.2.8" -truffle@^5.4.14: - version "5.11.2" - resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.11.2.tgz#2ca31a202ad2c43705936b1f74b571cec88adc6f" - integrity sha512-wQzdSkd1HKl0RFDltDVBL35SPqiibrPDlkZ2LJx8OcBheWrenXwFgdjW616w0ImyCySXsbnNw0tO63K+LxlwGw== - dependencies: - "@truffle/db-loader" "^0.2.33" - "@truffle/debugger" "^12.1.2" - app-module-path "^2.2.0" - ganache "7.9.0" - mocha "10.1.0" - original-require "^1.0.1" - optionalDependencies: - "@truffle/db" "^2.0.33" - ts-command-line-args@^2.2.0: version "2.5.1" - resolved "https://registry.yarnpkg.com/ts-command-line-args/-/ts-command-line-args-2.5.1.tgz#e64456b580d1d4f6d948824c274cf6fa5f45f7f0" + resolved "https://registry.npmjs.org/ts-command-line-args/-/ts-command-line-args-2.5.1.tgz" integrity sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw== dependencies: chalk "^4.1.0" @@ -10668,12 +11438,12 @@ ts-command-line-args@^2.2.0: ts-essentials@^7.0.1: version "7.0.3" - resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-7.0.3.tgz#686fd155a02133eedcc5362dc8b5056cde3e5a38" + resolved "https://registry.npmjs.org/ts-essentials/-/ts-essentials-7.0.3.tgz" integrity sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ== ts-node@^10.9.1: version "10.9.1" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" + resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz" integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== dependencies: "@cspotcode/source-map-support" "^0.8.0" @@ -10692,81 +11462,86 @@ ts-node@^10.9.1: tslib@2.4.0: version "2.4.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" + resolved "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz" integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== tslib@^1.11.1, tslib@^1.9.0, tslib@^1.9.3: version "1.14.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.1.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.5.0: - version "2.6.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.1.tgz#fd8c9a0ff42590b25703c0acb3de3d3f4ede0410" - integrity sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig== +tslib@^2.1.0, tslib@^2.4.0: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== -tslib@~2.4.0: +tslib@^2.3.1, tslib@~2.4.0: version "2.4.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e" integrity sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA== +tslib@^2.5.0: + version "2.6.1" + resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz" + integrity sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig== + tsort@0.0.1: version "0.0.1" - resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786" + resolved "https://registry.npmjs.org/tsort/-/tsort-0.0.1.tgz" integrity sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw== tunnel-agent@^0.6.0: version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + resolved "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz" integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== dependencies: safe-buffer "^5.0.1" tweetnacl-util@^0.15.0, tweetnacl-util@^0.15.1: version "0.15.1" - resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b" + resolved "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz" integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw== tweetnacl@1.x.x, tweetnacl@^1.0.0, tweetnacl@^1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" + resolved "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz" integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + resolved "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz" integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== type-check@~0.3.2: version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + resolved "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz" integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== dependencies: prelude-ls "~1.1.2" type-detect@^4.0.0, type-detect@^4.0.5: version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== type-fest@^0.20.2: version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== type-fest@^0.21.3: version "0.21.3" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== type-fest@^0.7.1: version "0.7.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz" integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== type-is@~1.6.18: version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + resolved "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz" integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== dependencies: media-typer "0.3.0" @@ -10774,17 +11549,17 @@ type-is@~1.6.18: type@^1.0.1: version "1.2.0" - resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" + resolved "https://registry.npmjs.org/type/-/type-1.2.0.tgz" integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== type@^2.7.2: version "2.7.2" - resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0" + resolved "https://registry.npmjs.org/type/-/type-2.7.2.tgz" integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw== typechain@^8.3.1: version "8.3.1" - resolved "https://registry.yarnpkg.com/typechain/-/typechain-8.3.1.tgz#dccbc839b94877997536c356380eff7325395cfb" + resolved "https://registry.npmjs.org/typechain/-/typechain-8.3.1.tgz" integrity sha512-fA7clol2IP/56yq6vkMTR+4URF1nGjV82Wx6Rf09EsqD4tkzMAvEaqYxVFCavJm/1xaRga/oD55K+4FtuXwQOQ== dependencies: "@types/prettier" "^2.1.1" @@ -10800,16 +11575,25 @@ typechain@^8.3.1: typed-array-buffer@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz#18de3e7ed7974b0a729d3feecb94338d1472cd60" + resolved "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz" integrity sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw== dependencies: call-bind "^1.0.2" get-intrinsic "^1.2.1" is-typed-array "^1.1.10" +typed-array-buffer@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz#a72395450a4869ec033fd549371b47af3a2ee536" + integrity sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw== + dependencies: + call-bound "^1.0.3" + es-errors "^1.3.0" + is-typed-array "^1.1.14" + typed-array-byte-length@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz#d787a24a995711611fb2b87a4052799517b230d0" + resolved "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz" integrity sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA== dependencies: call-bind "^1.0.2" @@ -10819,7 +11603,7 @@ typed-array-byte-length@^1.0.0: typed-array-byte-offset@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz#cbbe89b51fdef9cd6aaf07ad4707340abbc4ea0b" + resolved "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz" integrity sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg== dependencies: available-typed-arrays "^1.0.5" @@ -10830,7 +11614,7 @@ typed-array-byte-offset@^1.0.0: typed-array-length@^1.0.4: version "1.0.4" - resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" + resolved "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz" integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== dependencies: call-bind "^1.0.2" @@ -10839,63 +11623,63 @@ typed-array-length@^1.0.4: typedarray-to-buffer@^3.1.5: version "3.1.5" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + resolved "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz" integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== dependencies: is-typedarray "^1.0.0" typedarray@^0.0.6: version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz" integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== typeforce@^1.11.5: version "1.18.0" - resolved "https://registry.yarnpkg.com/typeforce/-/typeforce-1.18.0.tgz#d7416a2c5845e085034d70fcc5b6cc4a90edbfdc" + resolved "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz" integrity sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g== typescript-compare@^0.0.2: version "0.0.2" - resolved "https://registry.yarnpkg.com/typescript-compare/-/typescript-compare-0.0.2.tgz#7ee40a400a406c2ea0a7e551efd3309021d5f425" + resolved "https://registry.npmjs.org/typescript-compare/-/typescript-compare-0.0.2.tgz" integrity sha512-8ja4j7pMHkfLJQO2/8tut7ub+J3Lw2S3061eJLFQcvs3tsmJKp8KG5NtpLn7KcY2w08edF74BSVN7qJS0U6oHA== dependencies: typescript-logic "^0.0.0" typescript-logic@^0.0.0: version "0.0.0" - resolved "https://registry.yarnpkg.com/typescript-logic/-/typescript-logic-0.0.0.tgz#66ebd82a2548f2b444a43667bec120b496890196" + resolved "https://registry.npmjs.org/typescript-logic/-/typescript-logic-0.0.0.tgz" integrity sha512-zXFars5LUkI3zP492ls0VskH3TtdeHCqu0i7/duGt60i5IGPIpAHE/DWo5FqJ6EjQ15YKXrt+AETjv60Dat34Q== typescript-tuple@^2.2.1: version "2.2.1" - resolved "https://registry.yarnpkg.com/typescript-tuple/-/typescript-tuple-2.2.1.tgz#7d9813fb4b355f69ac55032e0363e8bb0f04dad2" + resolved "https://registry.npmjs.org/typescript-tuple/-/typescript-tuple-2.2.1.tgz" integrity sha512-Zcr0lbt8z5ZdEzERHAMAniTiIKerFCMgd7yjq1fPnDJ43et/k9twIFQMUYff9k5oXcsQ0WpvFcgzK2ZKASoW6Q== dependencies: typescript-compare "^0.0.2" typescript@^5.1.6: version "5.1.6" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.6.tgz#02f8ac202b6dad2c0dd5e0913745b47a37998274" + resolved "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz" integrity sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA== typical@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" + resolved "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz" integrity sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw== typical@^5.2.0: version "5.2.0" - resolved "https://registry.yarnpkg.com/typical/-/typical-5.2.0.tgz#4daaac4f2b5315460804f0acf6cb69c52bb93066" + resolved "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz" integrity sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg== uglify-js@^3.1.4: version "3.17.4" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.4.tgz#61678cf5fa3f5b7eb789bb345df29afb8257c22c" + resolved "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz" integrity sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g== uint8arrays@1.1.0, uint8arrays@^1.0.0, uint8arrays@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-1.1.0.tgz#d034aa65399a9fd213a1579e323f0b29f67d0ed2" + resolved "https://registry.npmjs.org/uint8arrays/-/uint8arrays-1.1.0.tgz" integrity sha512-cLdlZ6jnFczsKf5IH1gPHTtcHtPGho5r4CvctohmQjw8K7Q3gFdfIGHxSTdTaCKrL4w09SsPRJTqRS0drYeszA== dependencies: multibase "^3.0.0" @@ -10903,26 +11687,26 @@ uint8arrays@1.1.0, uint8arrays@^1.0.0, uint8arrays@^1.1.0: uint8arrays@^2.0.5, uint8arrays@^2.1.3: version "2.1.10" - resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-2.1.10.tgz#34d023c843a327c676e48576295ca373c56e286a" + resolved "https://registry.npmjs.org/uint8arrays/-/uint8arrays-2.1.10.tgz" integrity sha512-Q9/hhJa2836nQfEJSZTmr+pg9+cDJS9XEAp7N2Vg5MzL3bK/mkMVfjscRGYruP9jNda6MAdf4QD/y78gSzkp6A== dependencies: multiformats "^9.4.2" uint8arrays@^3.0.0: version "3.1.1" - resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-3.1.1.tgz#2d8762acce159ccd9936057572dade9459f65ae0" + resolved "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.1.1.tgz" integrity sha512-+QJa8QRnbdXVpHYjLoTpJIdCTiw9Ir62nocClWuXIq2JIh4Uta0cQsTSpFL678p2CN8B+XSApwcU+pQEqVpKWg== dependencies: multiformats "^9.4.2" ultron@~1.1.0: version "1.1.1" - resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" + resolved "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz" integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== unbox-primitive@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + resolved "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz" integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== dependencies: call-bind "^1.0.2" @@ -10931,20 +11715,20 @@ unbox-primitive@^1.0.2: which-boxed-primitive "^1.0.2" undici@^5.14.0: - version "5.28.4" - resolved "https://registry.yarnpkg.com/undici/-/undici-5.28.4.tgz#6b280408edb6a1a604a9b20340f45b422e373068" - integrity sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g== + version "5.29.0" + resolved "https://registry.yarnpkg.com/undici/-/undici-5.29.0.tgz#419595449ae3f2cdcba3580a2e8903399bd1f5a3" + integrity sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg== dependencies: "@fastify/busboy" "^2.0.0" unfetch@^4.2.0: version "4.2.0" - resolved "https://registry.yarnpkg.com/unfetch/-/unfetch-4.2.0.tgz#7e21b0ef7d363d8d9af0fb929a5555f6ef97a3be" + resolved "https://registry.npmjs.org/unfetch/-/unfetch-4.2.0.tgz" integrity sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA== universalify@^0.1.0: version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + resolved "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== universalify@^0.2.0: @@ -10954,49 +11738,49 @@ universalify@^0.2.0: universalify@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" + resolved "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz" integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== unorm@^1.4.1: version "1.6.0" - resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.6.0.tgz#029b289661fba714f1a9af439eb51d9b16c205af" + resolved "https://registry.npmjs.org/unorm/-/unorm-1.6.0.tgz" integrity sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA== unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + resolved "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== -update-browserslist-db@^1.0.11: - version "1.0.11" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz#9a2a641ad2907ae7b3616506f4b977851db5b940" - integrity sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA== +update-browserslist-db@^1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz" + integrity sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A== dependencies: - escalade "^3.1.1" - picocolors "^1.0.0" + escalade "^3.2.0" + picocolors "^1.1.1" upper-case-first@^1.1.0, upper-case-first@^1.1.2: version "1.1.2" - resolved "https://registry.yarnpkg.com/upper-case-first/-/upper-case-first-1.1.2.tgz#5d79bedcff14419518fd2edb0a0507c9b6859115" + resolved "https://registry.npmjs.org/upper-case-first/-/upper-case-first-1.1.2.tgz" integrity sha512-wINKYvI3Db8dtjikdAqoBbZoP6Q+PZUyfMR7pmwHzjC2quzSkUq5DmPrTtPEqHaz8AGtmsB4TqwapMTM1QAQOQ== dependencies: upper-case "^1.1.1" upper-case@^1.0.3, upper-case@^1.1.0, upper-case@^1.1.1, upper-case@^1.1.3: version "1.1.3" - resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" + resolved "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz" integrity sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA== uri-js@^4.2.2: version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== dependencies: punycode "^2.1.0" url-parse-lax@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" + resolved "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz" integrity sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ== dependencies: prepend-http "^2.0.0" @@ -11011,12 +11795,12 @@ url-parse@^1.5.3: url-set-query@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/url-set-query/-/url-set-query-1.0.0.tgz#016e8cfd7c20ee05cafe7795e892bd0702faa339" + resolved "https://registry.npmjs.org/url-set-query/-/url-set-query-1.0.0.tgz" integrity sha512-3AChu4NiXquPfeckE5R5cGdiHCMWJx1dwCWOmWIL4KHAziJNOFIYJlpGFeKDvwLPHovZRCxK3cYlwzqI9Vp+Gg== ursa-optional@^0.10.1: version "0.10.2" - resolved "https://registry.yarnpkg.com/ursa-optional/-/ursa-optional-0.10.2.tgz#bd74e7d60289c22ac2a69a3c8dea5eb2817f9681" + resolved "https://registry.npmjs.org/ursa-optional/-/ursa-optional-0.10.2.tgz" integrity sha512-TKdwuLboBn7M34RcvVTuQyhvrA8gYKapuVdm0nBP0mnBc7oECOfUQZrY91cefL3/nm64ZyrejSRrhTVdX7NG/A== dependencies: bindings "^1.5.0" @@ -11024,31 +11808,38 @@ ursa-optional@^0.10.1: utf-8-validate@5.0.7: version "5.0.7" - resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.7.tgz#c15a19a6af1f7ad9ec7ddc425747ca28c3644922" + resolved "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.7.tgz" integrity sha512-vLt1O5Pp+flcArHGIyKEQq883nBt8nN8tVBcoL0qUXj2XT1n7p70yGIq2VK98I5FdZ1YHc0wk/koOnHjnXWk1Q== dependencies: node-gyp-build "^4.3.0" +utf-8-validate@6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-6.0.3.tgz#7d8c936d854e86b24d1d655f138ee27d2636d777" + integrity sha512-uIuGf9TWQ/y+0Lp+KGZCMuJWc3N9BHA+l/UmHd/oUHwJJDeysyTRxNQVkbzsIWfGFbRe3OcgML/i0mvVRPOyDA== + dependencies: + node-gyp-build "^4.3.0" + utf-8-validate@^5.0.2: version "5.0.10" - resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz#d7d10ea39318171ca982718b6b96a8d2442571a2" + resolved "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz" integrity sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ== dependencies: node-gyp-build "^4.3.0" utf8@3.0.0, utf8@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" + resolved "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz" integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== util@^0.12.0, util@^0.12.3, util@^0.12.5: version "0.12.5" - resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" + resolved "https://registry.npmjs.org/util/-/util-0.12.5.tgz" integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== dependencies: inherits "^2.0.3" @@ -11059,12 +11850,12 @@ util@^0.12.0, util@^0.12.3, util@^0.12.5: utils-merge@1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz" integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== uuid@2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.1.tgz#c2a30dedb3e535d72ccf82e343941a50ba8533ac" + resolved "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz" integrity sha512-nWg9+Oa3qD2CQzHIP4qKUqwNfzKn8P0LtFhotaCTFchsV7ZfDhAybeip/HZVeMIpZi9JgY1E3nUlwaCmZT1sEg== uuid@3.2.1: @@ -11074,27 +11865,27 @@ uuid@3.2.1: uuid@3.3.2: version "3.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" + resolved "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz" integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== uuid@8.3.2, uuid@^8.3.2: version "8.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== uuid@^3.3.2: version "3.4.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + resolved "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== uuid@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5" - integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg== + version "9.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" + integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== v8-compile-cache-lib@^3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + resolved "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz" integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== validate-npm-package-license@^3.0.1: @@ -11117,22 +11908,22 @@ value-or-promise@^1.0.12: varint@^5.0.0, varint@^5.0.2, varint@~5.0.0: version "5.0.2" - resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.2.tgz#5b47f8a947eb668b848e034dcfa87d0ff8a7f7a4" + resolved "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz" integrity sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow== varint@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/varint/-/varint-6.0.0.tgz#9881eb0ce8feaea6512439d19ddf84bf551661d0" + resolved "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz" integrity sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg== vary@^1, vary@~1.1.2: version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== verror@1.10.0: version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + resolved "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz" integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== dependencies: assert-plus "^1.0.0" @@ -11146,7 +11937,7 @@ vuvuzela@1.0.3: web-encoding@^1.0.2, web-encoding@^1.0.6: version "1.1.5" - resolved "https://registry.yarnpkg.com/web-encoding/-/web-encoding-1.1.5.tgz#fc810cf7667364a6335c939913f5051d3e0c4864" + resolved "https://registry.npmjs.org/web-encoding/-/web-encoding-1.1.5.tgz" integrity sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA== dependencies: util "^0.12.3" @@ -11164,7 +11955,7 @@ web3-bzz@1.10.0: web3-bzz@1.7.4: version "1.7.4" - resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.7.4.tgz#9419e606e38a9777443d4ce40506ebd796e06075" + resolved "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.7.4.tgz" integrity sha512-w9zRhyEqTK/yi0LGRHjZMcPCfP24LBjYXI/9YxFw9VqsIZ9/G0CRCnUt12lUx0A56LRAMpF7iQ8eA73aBcO29Q== dependencies: "@types/node" "^12.12.6" @@ -11181,7 +11972,7 @@ web3-core-helpers@1.10.0: web3-core-helpers@1.7.4: version "1.7.4" - resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.7.4.tgz#f8f808928560d3e64e0c8d7bdd163aa4766bcf40" + resolved "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.7.4.tgz" integrity sha512-F8PH11qIkE/LpK4/h1fF/lGYgt4B6doeMi8rukeV/s4ivseZHHslv1L6aaijLX/g/j4PsFmR42byynBI/MIzFg== dependencies: web3-eth-iban "1.7.4" @@ -11200,7 +11991,7 @@ web3-core-method@1.10.0: web3-core-method@1.7.4: version "1.7.4" - resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.7.4.tgz#3873c6405e1a0a8a1efc1d7b28de8b7550b00c15" + resolved "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.7.4.tgz" integrity sha512-56K7pq+8lZRkxJyzf5MHQPI9/VL3IJLoy4L/+q8HRdZJ3CkB1DkXYaXGU2PeylG1GosGiSzgIfu1ljqS7CP9xQ== dependencies: "@ethersproject/transactions" "^5.6.2" @@ -11218,7 +12009,7 @@ web3-core-promievent@1.10.0: web3-core-promievent@1.7.4: version "1.7.4" - resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.7.4.tgz#80a75633fdfe21fbaae2f1e38950edb2f134868c" + resolved "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.7.4.tgz" integrity sha512-o4uxwXKDldN7ER7VUvDfWsqTx9nQSP1aDssi1XYXeYC2xJbVo0n+z6ryKtmcoWoRdRj7uSpVzal3nEmlr480mA== dependencies: eventemitter3 "4.0.4" @@ -11236,7 +12027,7 @@ web3-core-requestmanager@1.10.0: web3-core-requestmanager@1.7.4: version "1.7.4" - resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.7.4.tgz#2dc8a526dab8183dca3fef54658621801b1d0469" + resolved "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.7.4.tgz" integrity sha512-IuXdAm65BQtPL4aI6LZJJOrKAs0SM5IK2Cqo2/lMNvVMT9Kssq6qOk68Uf7EBDH0rPuINi+ReLP+uH+0g3AnPA== dependencies: util "^0.12.0" @@ -11255,7 +12046,7 @@ web3-core-subscriptions@1.10.0: web3-core-subscriptions@1.7.4: version "1.7.4" - resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.7.4.tgz#cfbd3fa71081a8c8c6f1a64577a1a80c5bd9826f" + resolved "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.7.4.tgz" integrity sha512-VJvKWaXRyxk2nFWumOR94ut9xvjzMrRtS38c4qj8WBIRSsugrZr5lqUwgndtj0qx4F+50JhnU++QEqUEAtKm3g== dependencies: eventemitter3 "4.0.4" @@ -11276,7 +12067,7 @@ web3-core@1.10.0: web3-core@1.7.4: version "1.7.4" - resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.7.4.tgz#943fff99134baedafa7c65b4a0bbd424748429ff" + resolved "https://registry.npmjs.org/web3-core/-/web3-core-1.7.4.tgz" integrity sha512-L0DCPlIh9bgIED37tYbe7bsWrddoXYc897ANGvTJ6MFkSNGiMwDkTLWSgYd9Mf8qu8b4iuPqXZHMwIo4atoh7Q== dependencies: "@types/bn.js" "^5.1.0" @@ -11297,7 +12088,7 @@ web3-eth-abi@1.10.0: web3-eth-abi@1.7.4: version "1.7.4" - resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.7.4.tgz#3fee967bafd67f06b99ceaddc47ab0970f2a614a" + resolved "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.7.4.tgz" integrity sha512-eMZr8zgTbqyL9MCTCAvb67RbVyN5ZX7DvA0jbLOqRWCiw+KlJKTGnymKO6jPE8n5yjk4w01e165Qb11hTDwHgg== dependencies: "@ethersproject/abi" "^5.6.3" @@ -11321,7 +12112,7 @@ web3-eth-accounts@1.10.0: web3-eth-accounts@1.7.4: version "1.7.4" - resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.7.4.tgz#7a24a4dfe947f7e9d1bae678529e591aa146167a" + resolved "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.7.4.tgz" integrity sha512-Y9vYLRKP7VU7Cgq6wG1jFaG2k3/eIuiTKAG8RAuQnb6Cd9k5BRqTm5uPIiSo0AP/u11jDomZ8j7+WEgkU9+Btw== dependencies: "@ethereumjs/common" "^2.5.0" @@ -11352,7 +12143,7 @@ web3-eth-contract@1.10.0: web3-eth-contract@1.7.4: version "1.7.4" - resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.7.4.tgz#e5761cfb43d453f57be4777b2e5e7e1082078ff7" + resolved "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.7.4.tgz" integrity sha512-ZgSZMDVI1pE9uMQpK0T0HDT2oewHcfTCv0osEqf5qyn5KrcQDg1GT96/+S0dfqZ4HKj4lzS5O0rFyQiLPQ8LzQ== dependencies: "@types/bn.js" "^5.1.0" @@ -11380,7 +12171,7 @@ web3-eth-ens@1.10.0: web3-eth-ens@1.7.4: version "1.7.4" - resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.7.4.tgz#346720305379c0a539e226141a9602f1da7bc0c8" + resolved "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.7.4.tgz" integrity sha512-Gw5CVU1+bFXP5RVXTCqJOmHn71X2ghNk9VcEH+9PchLr0PrKbHTA3hySpsPco1WJAyK4t8SNQVlNr3+bJ6/WZA== dependencies: content-hash "^2.5.2" @@ -11402,7 +12193,7 @@ web3-eth-iban@1.10.0: web3-eth-iban@1.7.4: version "1.7.4" - resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.7.4.tgz#711fb2547fdf0f988060027331b2b6c430505753" + resolved "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.7.4.tgz" integrity sha512-XyrsgWlZQMv5gRcjXMsNvAoCRvV5wN7YCfFV5+tHUCqN8g9T/o4XUS20vDWD0k4HNiAcWGFqT1nrls02MGZ08w== dependencies: bn.js "^5.2.1" @@ -11422,7 +12213,7 @@ web3-eth-personal@1.10.0: web3-eth-personal@1.7.4: version "1.7.4" - resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.7.4.tgz#22c399794cb828a75703df8bb4b3c1331b471546" + resolved "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.7.4.tgz" integrity sha512-O10C1Hln5wvLQsDhlhmV58RhXo+GPZ5+W76frSsyIrkJWLtYQTCr5WxHtRC9sMD1idXLqODKKgI2DL+7xeZ0/g== dependencies: "@types/node" "^12.12.6" @@ -11452,7 +12243,7 @@ web3-eth@1.10.0: web3-eth@1.7.4: version "1.7.4" - resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.7.4.tgz#a7c1d3ccdbba4de4a82df7e3c4db716e4a944bf2" + resolved "https://registry.npmjs.org/web3-eth/-/web3-eth-1.7.4.tgz" integrity sha512-JG0tTMv0Ijj039emXNHi07jLb0OiWSA9O24MRSk5vToTQyDNXihdF2oyq85LfHuF690lXZaAXrjhtLNlYqb7Ug== dependencies: web3-core "1.7.4" @@ -11479,7 +12270,7 @@ web3-net@1.10.0: web3-net@1.7.4: version "1.7.4" - resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.7.4.tgz#3153dfd3423262dd6fbec7aae5467202c4cad431" + resolved "https://registry.npmjs.org/web3-net/-/web3-net-1.7.4.tgz" integrity sha512-d2Gj+DIARHvwIdmxFQ4PwAAXZVxYCR2lET0cxz4KXbE5Og3DNjJi+MoPkX+WqoUXqimu/EOd4Cd+7gefqVAFDg== dependencies: web3-core "1.7.4" @@ -11498,7 +12289,7 @@ web3-providers-http@1.10.0: web3-providers-http@1.7.4: version "1.7.4" - resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.7.4.tgz#8209cdcb115db5ccae1f550d1c4e3005e7538d02" + resolved "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.7.4.tgz" integrity sha512-AU+/S+49rcogUER99TlhW+UBMk0N2DxvN54CJ2pK7alc2TQ7+cprNPLHJu4KREe8ndV0fT6JtWUfOMyTvl+FRA== dependencies: web3-core-helpers "1.7.4" @@ -11514,7 +12305,7 @@ web3-providers-ipc@1.10.0: web3-providers-ipc@1.7.4: version "1.7.4" - resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.7.4.tgz#02e85e99e48f432c9d34cee7d786c3685ec9fcfa" + resolved "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.7.4.tgz" integrity sha512-jhArOZ235dZy8fS8090t60nTxbd1ap92ibQw5xIrAQ9m7LcZKNfmLAQUVsD+3dTFvadRMi6z1vCO7zRi84gWHw== dependencies: oboe "2.1.5" @@ -11531,7 +12322,7 @@ web3-providers-ws@1.10.0: web3-providers-ws@1.7.4: version "1.7.4" - resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.7.4.tgz#6e60bcefb456f569a3e766e386d7807a96f90595" + resolved "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.7.4.tgz" integrity sha512-g72X77nrcHMFU8hRzQJzfgi/072n8dHwRCoTw+WQrGp+XCQ71fsk2qIu3Tp+nlp5BPn8bRudQbPblVm2uT4myQ== dependencies: eventemitter3 "4.0.4" @@ -11550,7 +12341,7 @@ web3-shh@1.10.0: web3-shh@1.7.4: version "1.7.4" - resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.7.4.tgz#bee91cce2737c529fd347274010b548b6ea060f1" + resolved "https://registry.npmjs.org/web3-shh/-/web3-shh-1.7.4.tgz" integrity sha512-mlSZxSYcMkuMCxqhTYnZkUdahZ11h+bBv/8TlkXp/IHpEe4/Gg+KAbmfudakq3EzG/04z70XQmPgWcUPrsEJ+A== dependencies: web3-core "1.7.4" @@ -11558,9 +12349,9 @@ web3-shh@1.7.4: web3-core-subscriptions "1.7.4" web3-net "1.7.4" -web3-utils@1.10.0, web3-utils@^1.0.0-beta.31, web3-utils@^1.3.6: +web3-utils@1.10.0: version "1.10.0" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.10.0.tgz#ca4c1b431a765c14ac7f773e92e0fd9377ccf578" + resolved "https://registry.npmjs.org/web3-utils/-/web3-utils-1.10.0.tgz" integrity sha512-kSaCM0uMcZTNUSmn5vMEhlo02RObGNRRCkdX0V9UTAU0+lrvn0HSaudyCo6CQzuXUsnuY2ERJGCGPfeWmv19Rg== dependencies: bn.js "^5.2.1" @@ -11571,9 +12362,9 @@ web3-utils@1.10.0, web3-utils@^1.0.0-beta.31, web3-utils@^1.3.6: randombytes "^2.1.0" utf8 "3.0.0" -web3-utils@1.7.4: +web3-utils@1.7.4, web3-utils@^1.3.6: version "1.7.4" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.7.4.tgz#eb6fa3706b058602747228234453811bbee017f5" + resolved "https://registry.npmjs.org/web3-utils/-/web3-utils-1.7.4.tgz" integrity sha512-acBdm6Evd0TEZRnChM/MCvGsMwYKmSh7OaUfNf5OKG0CIeGWD/6gqLOWIwmwSnre/2WrA1nKGId5uW2e5EfluA== dependencies: bn.js "^5.2.1" @@ -11584,6 +12375,20 @@ web3-utils@1.7.4: randombytes "^2.1.0" utf8 "3.0.0" +web3-utils@^1.0.0-beta.31: + version "1.10.4" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.10.4.tgz#0daee7d6841641655d8b3726baf33b08eda1cbec" + integrity sha512-tsu8FiKJLk2PzhDl9fXbGUWTkkVXYhtTA+SmEFkKft+9BgwLxfCRpU96sWv7ICC8zixBNd3JURVoiR3dUXgP8A== + dependencies: + "@ethereumjs/util" "^8.1.0" + bn.js "^5.2.1" + ethereum-bloom-filters "^1.0.6" + ethereum-cryptography "^2.1.2" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randombytes "^2.1.0" + utf8 "3.0.0" + web3@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3/-/web3-1.10.0.tgz#2fde0009f59aa756c93e07ea2a7f3ab971091274" @@ -11599,7 +12404,7 @@ web3@1.10.0: web3@1.7.4: version "1.7.4" - resolved "https://registry.yarnpkg.com/web3/-/web3-1.7.4.tgz#00c9aef8e13ade92fd773d845fff250535828e93" + resolved "https://registry.npmjs.org/web3/-/web3-1.7.4.tgz" integrity sha512-iFGK5jO32vnXM/ASaJBaI0+gVR6uHozvYdxkdhaeOCD6HIQ4iIXadbO2atVpE9oc/H8l2MovJ4LtPhG7lIBN8A== dependencies: web3-bzz "1.7.4" @@ -11612,12 +12417,12 @@ web3@1.7.4: webidl-conversions@^3.0.0: version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz" integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== websocket@^1.0.31, websocket@^1.0.32: version "1.0.34" - resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.34.tgz#2bdc2602c08bf2c82253b730655c0ef7dcab3111" + resolved "https://registry.npmjs.org/websocket/-/websocket-1.0.34.tgz" integrity sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ== dependencies: bufferutil "^4.0.1" @@ -11640,7 +12445,7 @@ websql@1.0.0: whatwg-fetch@^2.0.4: version "2.0.4" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" + resolved "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz" integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng== whatwg-mimetype@^3.0.0: @@ -11650,7 +12455,7 @@ whatwg-mimetype@^3.0.0: whatwg-url@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz" integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== dependencies: tr46 "~0.0.3" @@ -11658,7 +12463,7 @@ whatwg-url@^5.0.0: which-boxed-primitive@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + resolved "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz" integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== dependencies: is-bigint "^1.0.1" @@ -11674,12 +12479,12 @@ which-module@^1.0.0: which-module@^2.0.0: version "2.0.1" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" + resolved "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz" integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== which-typed-array@^1.1.10, which-typed-array@^1.1.11, which-typed-array@^1.1.2: version "1.1.11" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.11.tgz#99d691f23c72aab6768680805a271b69761ed61a" + resolved "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz" integrity sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew== dependencies: available-typed-arrays "^1.0.5" @@ -11688,14 +12493,27 @@ which-typed-array@^1.1.10, which-typed-array@^1.1.11, which-typed-array@^1.1.2: gopd "^1.0.1" has-tostringtag "^1.0.0" -which@1.3.1, which@^1.1.1, which@^1.2.9, which@^1.3.1: +which-typed-array@^1.1.16: + version "1.1.19" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.19.tgz#df03842e870b6b88e117524a4b364b6fc689f956" + integrity sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.4" + for-each "^0.3.5" + get-proto "^1.0.1" + gopd "^1.2.0" + has-tostringtag "^1.0.2" + +which@1.3.1, which@^1.1.1, which@^1.3.1: version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + resolved "https://registry.npmjs.org/which/-/which-1.3.1.tgz" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== dependencies: isexe "^2.0.0" -which@2.0.2: +which@2.0.2, which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== @@ -11704,7 +12522,7 @@ which@2.0.2: wide-align@1.1.3: version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + resolved "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz" integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== dependencies: string-width "^1.0.2 || 2" @@ -11718,14 +12536,14 @@ wide-align@^1.1.0: widest-line@^3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" + resolved "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz" integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== dependencies: string-width "^4.0.0" wif@^2.0.6: version "2.0.6" - resolved "https://registry.yarnpkg.com/wif/-/wif-2.0.6.tgz#08d3f52056c66679299726fade0d432ae74b4704" + resolved "https://registry.npmjs.org/wif/-/wif-2.0.6.tgz" integrity sha512-HIanZn1zmduSF+BQhkE+YXIbEiH0xPr1012QbFEGB0xsKqJii0/SqJjyn8dFv6y36kOznMgMB+LGcbZTJ1xACQ== dependencies: bs58check "<3.0.0" @@ -11737,17 +12555,17 @@ window-size@^0.2.0: word-wrap@~1.2.3: version "1.2.5" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz" integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== wordwrap@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + resolved "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz" integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== wordwrapjs@^4.0.0: version "4.0.1" - resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-4.0.1.tgz#d9790bccfb110a0fc7836b5ebce0937b37a8b98f" + resolved "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.1.tgz" integrity sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA== dependencies: reduce-flatten "^2.0.0" @@ -11755,12 +12573,12 @@ wordwrapjs@^4.0.0: workerpool@6.2.0: version "6.2.0" - resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.0.tgz#827d93c9ba23ee2019c3ffaff5c27fccea289e8b" + resolved "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz" integrity sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A== workerpool@6.2.1: version "6.2.1" - resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" + resolved "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== wrap-ansi@^2.0.0: @@ -11773,7 +12591,7 @@ wrap-ansi@^2.0.0: wrap-ansi@^5.1.0: version "5.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz" integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== dependencies: ansi-styles "^3.2.0" @@ -11782,16 +12600,25 @@ wrap-ansi@^5.1.0: wrap-ansi@^7.0.0: version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== dependencies: ansi-styles "^4.0.0" string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^9.0.0: + version "9.0.2" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-9.0.2.tgz#956832dea9494306e6d209eb871643bb873d7c98" + integrity sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww== + dependencies: + ansi-styles "^6.2.1" + string-width "^7.0.0" + strip-ansi "^7.1.0" + wrappy@1: version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== write-stream@~0.4.3: @@ -11801,24 +12628,29 @@ write-stream@~0.4.3: dependencies: readable-stream "~0.0.2" -ws@7.4.6: - version "7.4.6" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" - integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== +ws@8.13.0, ws@^8.5.0: + version "8.13.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" + integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== + +ws@8.18.0: + version "8.18.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" + integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== ws@8.2.3: version "8.2.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.3.tgz#63a56456db1b04367d0b721a0b80cae6d8becbba" + resolved "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz" integrity sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA== ws@8.5.0: version "8.5.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" + resolved "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz" integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== ws@^3.0.0: version "3.3.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" + resolved "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz" integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA== dependencies: async-limiter "~1.0.0" @@ -11827,31 +12659,26 @@ ws@^3.0.0: ws@^5.1.1: version "5.2.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.3.tgz#05541053414921bc29c63bee14b8b0dd50b07b3d" + resolved "https://registry.npmjs.org/ws/-/ws-5.2.3.tgz" integrity sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA== dependencies: async-limiter "~1.0.0" ws@^7.2.0, ws@^7.2.1, ws@^7.3.1, ws@^7.4.6: version "7.5.9" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" + resolved "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz" integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== -ws@^8.5.0: - version "8.13.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" - integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== - xhr-request-promise@^0.1.2: version "0.1.3" - resolved "https://registry.yarnpkg.com/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz#2d5f4b16d8c6c893be97f1a62b0ed4cf3ca5f96c" + resolved "https://registry.npmjs.org/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz" integrity sha512-YUBytBsuwgitWtdRzXDDkWAXzhdGB8bYm0sSzMPZT7Z2MBjMSTHFsyCT1yCRATY+XC69DUrQraRAEgcoCRaIPg== dependencies: xhr-request "^1.1.0" xhr-request@^1.0.1, xhr-request@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/xhr-request/-/xhr-request-1.1.0.tgz#f4a7c1868b9f198723444d82dcae317643f2e2ed" + resolved "https://registry.npmjs.org/xhr-request/-/xhr-request-1.1.0.tgz" integrity sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA== dependencies: buffer-to-arraybuffer "^0.0.5" @@ -11864,14 +12691,14 @@ xhr-request@^1.0.1, xhr-request@^1.1.0: xhr2-cookies@1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz#7d77449d0999197f155cb73b23df72505ed89d48" + resolved "https://registry.npmjs.org/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz" integrity sha512-hjXUA6q+jl/bd8ADHcVfFsSPIf+tyLIjuO9TwJC9WI6JP2zKcS7C+p56I9kCLLsaCiNT035iYvEUUzdEFj/8+g== dependencies: cookiejar "^2.1.1" xhr@^2.0.4, xhr@^2.2.0, xhr@^2.3.3: version "2.6.0" - resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.6.0.tgz#b69d4395e792b4173d6b7df077f0fc5e4e2b249d" + resolved "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz" integrity sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA== dependencies: global "~4.4.0" @@ -11881,25 +12708,25 @@ xhr@^2.0.4, xhr@^2.2.0, xhr@^2.3.3: xmlhttprequest@1.8.0: version "1.8.0" - resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" + resolved "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz" integrity sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA== xss@^1.0.8: - version "1.0.14" - resolved "https://registry.yarnpkg.com/xss/-/xss-1.0.14.tgz#4f3efbde75ad0d82e9921cc3c95e6590dd336694" - integrity sha512-og7TEJhXvn1a7kzZGQ7ETjdQVS2UfZyTlsEdDOqvQF7GoxNfY+0YLCzBy1kPdsDDx4QuNAonQPddpsn6Xl/7sw== + version "1.0.15" + resolved "https://registry.yarnpkg.com/xss/-/xss-1.0.15.tgz#96a0e13886f0661063028b410ed1b18670f4e59a" + integrity sha512-FVdlVVC67WOIPvfOwhoMETV72f6GbW7aOabBC3WxN/oUdoEMDyLz4OgRv5/gck2ZeNqEQu+Tb0kloovXOfpYVg== dependencies: commander "^2.20.3" cssfilter "0.0.10" xtend@^4.0.0, xtend@^4.0.1, xtend@^4.0.2, xtend@~4.0.0: version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== xtend@~2.1.1: version "2.1.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" + resolved "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz" integrity sha512-vMNKzr2rHP9Dp/e1NQFnLQlwlhp9L/LfvnsVdHxN1f+uggyVI3i08uD14GPvCToPkdsRfyPqIyYGmIk58V98ZQ== dependencies: object-keys "~0.4.0" @@ -11911,45 +12738,45 @@ y18n@^3.2.1: y18n@^4.0.0: version "4.0.3" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + resolved "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz" integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== y18n@^5.0.5: version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== yaeti@^0.0.6: version "0.0.6" - resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" + resolved "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz" integrity sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug== yallist@^3.0.0, yallist@^3.0.2, yallist@^3.1.1: version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== yallist@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yaml@^1.10.2: - version "1.10.2" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" - integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== +yaml@^2.2.2: + version "2.8.3" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.8.3.tgz#a0d6bd2efb3dd03c59370223701834e60409bd7d" + integrity sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg== yargs-parser@13.1.2, yargs-parser@^13.1.2: version "13.1.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz" integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== dependencies: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@20.2.4: +yargs-parser@20.2.4, yargs-parser@^20.2.2: version "20.2.4" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz" integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== yargs-parser@^2.4.1: @@ -11960,19 +12787,14 @@ yargs-parser@^2.4.1: camelcase "^3.0.0" lodash.assign "^4.0.6" -yargs-parser@^20.2.2: - version "20.2.9" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" - integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== - -yargs-parser@^21.1.1: - version "21.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" - integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== +yargs-parser@^22.0.0: + version "22.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-22.0.0.tgz#87b82094051b0567717346ecd00fd14804b357c8" + integrity sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw== yargs-unparser@1.6.0: version "1.6.0" - resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" + resolved "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz" integrity sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw== dependencies: flat "^4.1.0" @@ -11981,7 +12803,7 @@ yargs-unparser@1.6.0: yargs-unparser@2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + resolved "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz" integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== dependencies: camelcase "^6.0.0" @@ -11991,7 +12813,7 @@ yargs-unparser@2.0.0: yargs@13.3.2, yargs@^13.3.0: version "13.3.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" + resolved "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz" integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== dependencies: cliui "^5.0.0" @@ -12007,7 +12829,7 @@ yargs@13.3.2, yargs@^13.3.0: yargs@16.2.0: version "16.2.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + resolved "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz" integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== dependencies: cliui "^7.0.2" @@ -12018,18 +12840,17 @@ yargs@16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" -yargs@^17.0.1: - version "17.7.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" - integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== +yargs@^18.0.0: + version "18.0.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-18.0.0.tgz#6c84259806273a746b09f579087b68a3c2d25bd1" + integrity sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg== dependencies: - cliui "^8.0.1" + cliui "^9.0.1" escalade "^3.1.1" get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.3" + string-width "^7.2.0" y18n "^5.0.5" - yargs-parser "^21.1.1" + yargs-parser "^22.0.0" yargs@^4.7.1: version "4.8.1" @@ -12053,10 +12874,10 @@ yargs@^4.7.1: yn@3.1.1: version "3.1.1" - resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz" integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== yocto-queue@^0.1.0: version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/tests/speedtest/README.md b/tests/speedtest/README.md new file mode 100644 index 00000000..efeccdca --- /dev/null +++ b/tests/speedtest/README.md @@ -0,0 +1,23 @@ +# Speedtest + +Speedtest tests the TPS of your application's execution. + +# Build + +cd tests/speedtest +go build . + +# Run + +The default configuration runs with 10k accounts, 4k txs per block, for 100 blocks. + +./speedtest + +To change parameters run: + +./speedtest --acounts 60000 --txs 5000 --blocks 150 + +IMPORTANT: It is important to ensure your configuration is not exceeding the block max gas/bytes. These are by default +set to the maximum possible values. However, should you exceed this, the program will report a false TPS value. Use +--verify-txs to verify that your configuration is sound. Once the configuration is confirmed (i.e. you've run with +--verify-txs and it didn't error), run again without the --verify-txs flag to get true a TPS value. \ No newline at end of file diff --git a/tests/speedtest/go.mod b/tests/speedtest/go.mod new file mode 100644 index 00000000..f222e853 --- /dev/null +++ b/tests/speedtest/go.mod @@ -0,0 +1,370 @@ +module github.com/cosmos/evm/tests/speedtest + +go 1.25.9 + +replace ( + github.com/cosmos/evm => ../../ + github.com/cosmos/evm/evmd => ../../evmd + // use Cosmos geth fork + // branch: release/1.16 + github.com/ethereum/go-ethereum => github.com/cosmos/go-ethereum v1.16.2-cosmos-1 +) + +require ( + cosmossdk.io/log/v2 v2.1.0 + github.com/cosmos/cosmos-db v1.1.3 + github.com/cosmos/cosmos-sdk v0.54.3 + github.com/cosmos/evm v0.2.0 + github.com/cosmos/evm/evmd v0.0.0-20251112193856-d450ea1d6bd0 + github.com/ethereum/go-ethereum v1.16.8 + github.com/spf13/cobra v1.10.2 +) + +require ( + cel.dev/expr v0.25.1 // indirect + cloud.google.com/go v0.123.0 // indirect + cloud.google.com/go/auth v0.20.0 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect + cloud.google.com/go/compute/metadata v0.9.0 // indirect + cloud.google.com/go/iam v1.9.0 // indirect + cloud.google.com/go/monitoring v1.27.0 // indirect + cloud.google.com/go/storage v1.62.1 // indirect + cosmossdk.io/api v1.0.0 // indirect + cosmossdk.io/client/v2 v2.0.0-beta.10.0.20260227212600-39d4711b8970 // indirect + cosmossdk.io/collections v1.4.0 // indirect + cosmossdk.io/core v1.1.0 // indirect + cosmossdk.io/depinject v1.2.1 // indirect + cosmossdk.io/errors v1.1.0 // indirect + cosmossdk.io/math v1.5.3 // indirect + cosmossdk.io/schema v1.1.0 // indirect + filippo.io/edwards25519 v1.2.0 // indirect + github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // 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/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.32.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.56.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.56.0 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/RoaringBitmap/roaring/v2 v2.18.0 // indirect + github.com/VictoriaMetrics/fastcache v1.13.0 // indirect + github.com/aws/aws-sdk-go-v2 v1.41.6 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.9 // indirect + github.com/aws/aws-sdk-go-v2/config v1.32.14 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.19.14 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.22 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.22 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.23 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.8 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.14 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.22 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.22 // indirect + github.com/aws/aws-sdk-go-v2/service/s3 v1.100.0 // indirect + github.com/aws/aws-sdk-go-v2/service/signin v1.0.9 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.30.15 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.19 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.41.10 // indirect + github.com/aws/smithy-go v1.25.0 // indirect + github.com/benbjohnson/clock v1.3.5 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect + github.com/bgentry/speakeasy v0.2.0 // indirect + github.com/bits-and-blooms/bitset v1.24.4 // indirect + github.com/btcsuite/btcd v0.24.2 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.5 // indirect + github.com/btcsuite/btcd/btcutil v1.1.6 // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect + github.com/bytedance/gopkg v0.1.4 // indirect + github.com/bytedance/sonic v1.15.0 // indirect + github.com/bytedance/sonic/loader v0.5.1 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cenkalti/backoff/v5 v5.0.3 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/chzyer/readline v1.5.1 // indirect + github.com/cloudwego/base64x v0.1.6 // indirect + github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 // indirect + github.com/cockroachdb/errors v1.13.0 // indirect + github.com/cockroachdb/fifo v0.0.0-20240816210425-c5d0cb0b6fc0 // 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.8 // indirect + github.com/cockroachdb/tokenbucket v0.0.0-20250429170803-42689b6311bb // indirect + github.com/cometbft/cometbft v0.39.3 // indirect + github.com/cometbft/cometbft-db v1.0.4 // indirect + github.com/consensys/gnark-crypto v0.18.1 // indirect + github.com/cosmos/btcutil v1.0.5 // indirect + github.com/cosmos/btree v1.0.0 // indirect + github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect + github.com/cosmos/cosmos-sdk/store/v2 v2.0.0 // indirect + github.com/cosmos/go-bip39 v1.0.0 // indirect + github.com/cosmos/gogogateway v1.2.0 // indirect + github.com/cosmos/gogoproto v1.7.2 // indirect + github.com/cosmos/iavl v1.2.8 // indirect + github.com/cosmos/ibc-go/v11 v11.0.0 // indirect + github.com/cosmos/ics23/go v0.11.0 // indirect + github.com/cosmos/ledger-cosmos-go v1.0.0 // indirect + github.com/crate-crypto/go-eth-kzg v1.5.0 // indirect + github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect + github.com/danieljoos/wincred v1.2.3 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect + github.com/deckarep/golang-set/v2 v2.6.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.1 // indirect + github.com/desertbit/timer v1.0.1 // indirect + github.com/dgraph-io/badger/v4 v4.9.1 // indirect + github.com/dgraph-io/ristretto/v2 v2.4.0 // indirect + github.com/dlclark/regexp2 v1.7.0 // indirect + github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 // indirect + github.com/dunglas/httpsfv v1.1.0 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/dvsekhvalnov/jose2go v1.8.0 // indirect + github.com/ebitengine/purego v0.10.0 // indirect + github.com/emicklei/dot v1.11.0 // indirect + github.com/envoyproxy/go-control-plane/envoy v1.37.0 // indirect + github.com/envoyproxy/protoc-gen-validate v1.3.3 // indirect + github.com/ethereum/c-kzg-4844/v2 v2.1.6 // 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/ferranbt/fastssz v0.1.4 // indirect + github.com/flynn/noise v1.1.0 // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect + github.com/gammazero/deque v1.2.0 // indirect + github.com/getsentry/sentry-go v0.46.0 // indirect + github.com/go-jose/go-jose/v4 v4.1.4 // indirect + github.com/go-kit/kit v0.13.0 // indirect + github.com/go-kit/log v0.2.1 // indirect + github.com/go-logfmt/logfmt v0.6.1 // 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-sourcemap/sourcemap v2.1.3+incompatible // indirect + github.com/go-viper/mapstructure/v2 v2.5.0 // indirect + 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/protobuf v1.5.4 // indirect + github.com/golang/snappy v1.0.0 // indirect + github.com/google/btree v1.1.3 // indirect + github.com/google/flatbuffers v25.2.10+incompatible // indirect + github.com/google/go-cmp v0.7.0 // indirect + github.com/google/orderedcode v0.0.1 // indirect + github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect + github.com/google/s2a-go v0.1.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.14 // indirect + github.com/googleapis/gax-go/v2 v2.22.0 // indirect + github.com/gorilla/handlers v1.5.2 // indirect + github.com/gorilla/mux v1.8.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect + github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 // indirect + github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect + github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.72 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-getter v1.8.6 // indirect + github.com/hashicorp/go-hclog v1.6.3 // indirect + github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/go-metrics v0.5.4 // indirect + github.com/hashicorp/go-plugin v1.7.0 // indirect + github.com/hashicorp/go-version v1.9.0 // indirect + github.com/hashicorp/golang-lru v1.0.2 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect + github.com/hashicorp/yamux v0.1.2 // indirect + github.com/hdevalence/ed25519consensus v0.2.0 // indirect + github.com/holiman/bloomfilter/v2 v2.0.3 // indirect + 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/strcase v0.3.0 // indirect + github.com/improbable-eng/grpc-web v0.15.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/ipfs/go-cid v0.5.0 // indirect + github.com/jackpal/go-nat-pmp v1.0.2 // indirect + github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect + github.com/jmhodges/levigo v1.0.0 // indirect + github.com/klauspost/compress v1.18.5 // indirect + github.com/klauspost/cpuid/v2 v2.3.0 // indirect + github.com/koron/go-ssdp v0.0.6 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/lib/pq v1.12.3 // indirect + github.com/libp2p/go-buffer-pool v0.1.0 // indirect + github.com/libp2p/go-flow-metrics v0.2.0 // indirect + github.com/libp2p/go-libp2p v0.47.0 // indirect + github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect + github.com/libp2p/go-msgio v0.3.0 // indirect + github.com/libp2p/go-netroute v0.3.0 // indirect + github.com/libp2p/go-reuseport v0.4.0 // indirect + github.com/libp2p/go-yamux/v5 v5.0.1 // indirect + github.com/linxGnu/grocksdb v1.10.7 // indirect + github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e // indirect + github.com/manifoldco/promptui v0.9.0 // indirect + github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect + github.com/mattn/go-colorable v0.1.14 // indirect + github.com/mattn/go-isatty v0.0.22 // indirect + github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/miekg/dns v1.1.66 // indirect + github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect + github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect + github.com/minio/highwayhash v1.0.4 // indirect + github.com/minio/sha256-simd v1.0.1 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/mr-tron/base58 v1.3.0 // indirect + github.com/mschoch/smat v0.2.0 // indirect + github.com/mtibben/percent v0.2.1 // indirect + github.com/multiformats/go-base32 v0.1.0 // indirect + github.com/multiformats/go-base36 v0.2.0 // indirect + github.com/multiformats/go-multiaddr v0.16.1 // indirect + github.com/multiformats/go-multiaddr-dns v0.4.1 // indirect + github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect + github.com/multiformats/go-multibase v0.2.0 // indirect + github.com/multiformats/go-multicodec v0.9.1 // indirect + github.com/multiformats/go-multihash v0.2.3 // indirect + github.com/multiformats/go-multistream v0.6.1 // indirect + github.com/multiformats/go-varint v0.0.7 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/oasisprotocol/curve25519-voi v0.0.0-20251114093237-2ab5a27a1729 // indirect + github.com/oklog/run v1.2.0 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect + github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/petermattis/goid v0.0.0-20260113132338-7c7de50cc741 // indirect + github.com/pion/datachannel v1.5.10 // indirect + github.com/pion/dtls/v2 v2.2.12 // indirect + github.com/pion/dtls/v3 v3.1.2 // indirect + github.com/pion/ice/v4 v4.0.10 // indirect + github.com/pion/interceptor v0.1.40 // indirect + github.com/pion/logging v0.2.4 // indirect + github.com/pion/mdns/v2 v2.0.7 // indirect + github.com/pion/randutil v0.1.0 // indirect + github.com/pion/rtcp v1.2.15 // indirect + github.com/pion/rtp v1.8.19 // indirect + github.com/pion/sctp v1.8.39 // indirect + github.com/pion/sdp/v3 v3.0.13 // indirect + github.com/pion/srtp/v3 v3.0.6 // indirect + github.com/pion/stun v0.6.1 // indirect + github.com/pion/stun/v2 v2.0.0 // indirect + github.com/pion/stun/v3 v3.0.0 // indirect + github.com/pion/transport/v2 v2.2.10 // indirect + github.com/pion/transport/v3 v3.0.7 // indirect + github.com/pion/transport/v4 v4.0.1 // indirect + github.com/pion/turn/v4 v4.0.2 // indirect + github.com/pion/webrtc/v4 v4.1.2 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect + github.com/prometheus/client_golang v1.23.2 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/common v0.67.5 // indirect + github.com/prometheus/procfs v0.20.1 // indirect + github.com/quic-go/qpack v0.6.0 // indirect + github.com/quic-go/quic-go v0.59.0 // indirect + github.com/quic-go/webtransport-go v0.10.0 // indirect + github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/rogpeppe/go-internal v1.14.1 // indirect + github.com/rs/cors v1.11.1 // indirect + github.com/rs/zerolog v1.35.0 // indirect + github.com/sagikazarmark/locafero v0.12.0 // indirect + github.com/sasha-s/go-deadlock v0.3.9 // indirect + github.com/shirou/gopsutil v3.21.11+incompatible // indirect + github.com/shirou/gopsutil/v4 v4.26.4 // indirect + github.com/spaolacci/murmur3 v1.1.0 // indirect + github.com/spf13/afero v1.15.0 // indirect + github.com/spf13/cast v1.10.0 // indirect + github.com/spf13/pflag v1.0.10 // indirect + github.com/spf13/viper v1.21.0 // indirect + github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect + github.com/stretchr/testify v1.11.1 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + github.com/supranational/blst v0.3.16 // 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.8.1 // indirect + github.com/tidwall/gjson v1.18.0 // indirect + github.com/tidwall/match v1.2.0 // indirect + github.com/tidwall/pretty v1.2.1 // indirect + github.com/tidwall/sjson v1.2.5 // indirect + github.com/tklauser/go-sysconf v0.3.16 // indirect + github.com/tklauser/numcpus v0.11.0 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/ulikunitz/xz v0.5.15 // indirect + github.com/wlynxg/anet v0.0.5 // indirect + github.com/yusufpapurcu/wmi v1.2.4 // indirect + github.com/zondax/golem v0.27.0 // indirect + github.com/zondax/hid v0.9.2 // indirect + github.com/zondax/ledger-go v1.0.1 // indirect + go.etcd.io/bbolt v1.4.3 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/contrib/bridges/otelslog v0.18.0 // indirect + go.opentelemetry.io/contrib/detectors/gcp v1.43.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 // indirect + go.opentelemetry.io/contrib/instrumentation/host v0.68.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 // indirect + go.opentelemetry.io/contrib/instrumentation/runtime v0.68.0 // indirect + go.opentelemetry.io/contrib/otelconf v0.23.0 // indirect + go.opentelemetry.io/contrib/propagators/autoprop v0.68.0 // indirect + go.opentelemetry.io/contrib/propagators/aws v1.43.0 // indirect + go.opentelemetry.io/contrib/propagators/b3 v1.43.0 // indirect + go.opentelemetry.io/contrib/propagators/jaeger v1.43.0 // indirect + go.opentelemetry.io/contrib/propagators/ot v1.43.0 // indirect + go.opentelemetry.io/otel v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.19.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.19.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.43.0 // indirect + go.opentelemetry.io/otel/log v0.19.0 // indirect + go.opentelemetry.io/otel/metric v1.43.0 // indirect + go.opentelemetry.io/otel/sdk v1.43.0 // indirect + go.opentelemetry.io/otel/sdk/log v0.19.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.43.0 // indirect + go.opentelemetry.io/otel/trace v1.43.0 // indirect + go.opentelemetry.io/proto/otlp v1.10.0 // indirect + go.uber.org/dig v1.19.0 // indirect + go.uber.org/fx v1.24.0 // indirect + go.uber.org/mock v0.6.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.27.1 // indirect + go.yaml.in/yaml/v2 v2.4.4 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect + golang.org/x/arch v0.26.0 // indirect + golang.org/x/crypto v0.50.0 // indirect + golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90 // indirect + golang.org/x/mod v0.34.0 // indirect + golang.org/x/net v0.53.0 // indirect + golang.org/x/oauth2 v0.36.0 // indirect + golang.org/x/sync v0.20.0 // indirect + golang.org/x/sys v0.43.0 // indirect + golang.org/x/telemetry v0.0.0-20260311193753-579e4da9a98c // indirect + golang.org/x/term v0.42.0 // indirect + golang.org/x/text v0.36.0 // indirect + golang.org/x/time v0.15.0 // indirect + golang.org/x/tools v0.43.0 // indirect + google.golang.org/api v0.276.0 // indirect + google.golang.org/genproto v0.0.0-20260414002931-afd174a4e478 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 // indirect + google.golang.org/grpc v1.80.0 // indirect + google.golang.org/protobuf v1.36.11 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + gotest.tools/v3 v3.5.2 // indirect + lukechampine.com/blake3 v1.4.1 // indirect + nhooyr.io/websocket v1.8.17 // indirect + pgregory.net/rapid v1.3.0 // indirect + sigs.k8s.io/yaml v1.6.0 // indirect +) diff --git a/tests/speedtest/go.sum b/tests/speedtest/go.sum new file mode 100644 index 00000000..a990d109 --- /dev/null +++ b/tests/speedtest/go.sum @@ -0,0 +1,1557 @@ +cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4= +cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= +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.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE= +cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= +cloud.google.com/go/auth v0.20.0 h1:kXTssoVb4azsVDoUiF8KvxAqrsQcQtB53DcSgta74CA= +cloud.google.com/go/auth v0.20.0/go.mod h1:942/yi/itH1SsmpyrbnTMDgGfdy2BUqIKyd0cyYLc5Q= +cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= +cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= +cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= +cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= +cloud.google.com/go/iam v1.9.0 h1:89wyjxT6DL4b5rk/Nk8eBC9DHqf+JiMstrn5IEYxFw4= +cloud.google.com/go/iam v1.9.0/go.mod h1:KP+nKGugNJW4LcLx1uEZcq1ok5sQHFaQehQNl4QDgV4= +cloud.google.com/go/logging v1.15.0 h1:6ooUEBNT6jdWh2b36+iuPn6b/R9qN/tHCbvGS5255gg= +cloud.google.com/go/logging v1.15.0/go.mod h1:ZGKnpBaURITh+g/uom2VhbiFoFWvejcrHPDhxFtU/gI= +cloud.google.com/go/longrunning v0.10.0 h1:4OWvp1BjCvoeSZTog3sRFDu6j4IrI9TI4/Y9N+8h25g= +cloud.google.com/go/longrunning v0.10.0/go.mod h1:8nqFBPOO1U/XkhWl0I19AMZEphrHi73VNABIpKYaTwM= +cloud.google.com/go/monitoring v1.27.0 h1:BhYwMqao+e5Nn7JtWMM9m6zRtKtVUK6kJWMizXChkLU= +cloud.google.com/go/monitoring v1.27.0/go.mod h1:72NOVjJXHY/HBfoLT0+qlCZBT059+9VXLeAnL2PeeVM= +cloud.google.com/go/storage v1.62.1 h1:Os0G3XbUbjZumkpDUf2Y0rLoXJTCF1kU2kWUujKYXD8= +cloud.google.com/go/storage v1.62.1/go.mod h1:cpYz/kRVZ+UQAF1uHeea10/9ewcRbxGoGNKsS9daSXA= +cloud.google.com/go/trace v1.13.0 h1:RfqsqPOiSCG8ql50UZt5F65KrVa1zbY9mJrO7xvZfbE= +cloud.google.com/go/trace v1.13.0/go.mod h1:r+bdAn16dKLSV1G2D5v3e58IlQlizfxWrUfjx7kM7X0= +cosmossdk.io/api v1.0.0 h1:qTV8OPVEwcBPwp2b9p4Qy4noZyihJ+sOMaWL/VT+RCc= +cosmossdk.io/api v1.0.0/go.mod h1:fKRljeYk+04p4T8Shdyv+uH2fSVyzHoWrvDAs/7OxfI= +cosmossdk.io/client/v2 v2.0.0-beta.10.0.20260227212600-39d4711b8970 h1:hRL2KLqyVnbOfb2UzNQUZ0IXdL8TsHSGeYyF3tbcfcM= +cosmossdk.io/client/v2 v2.0.0-beta.10.0.20260227212600-39d4711b8970/go.mod h1:cgdrvgMJ23AzeYIXQtcIyw283R9heNuGXHoHYJ5KvdM= +cosmossdk.io/collections v1.4.0 h1:b373bkxCxKiRbapxZ42TRmcKJEnBVBebdQVk9I5IkkE= +cosmossdk.io/collections v1.4.0/go.mod h1:gxbieVY3tjbvWlkm3yOXf7sGyDrVi12haZH+sek6whw= +cosmossdk.io/core v1.1.0 h1:iJ7j2DjNsFzg4/z4ImNQYzy2D4LfMCsaQ8Lrz1KCmxk= +cosmossdk.io/core v1.1.0/go.mod h1:qGmJxBFHobvG1k4bROQnueslotBU5MIKZLC57xVBYYI= +cosmossdk.io/depinject v1.2.1 h1:eD6FxkIjlVaNZT+dXTQuwQTKZrFZ4UrfCq1RKgzyhMw= +cosmossdk.io/depinject v1.2.1/go.mod h1:lqQEycz0H2JXqvOgVwTsjEdMI0plswI7p6KX+MVqFOM= +cosmossdk.io/errors v1.1.0 h1:X2DSt9JYgH7cuiaDr318aUqIl2z5Lfo/PdGzAtmczUU= +cosmossdk.io/errors v1.1.0/go.mod h1:lnjBmx7etZpMTLnxdspZupH0d9HGRWZhiezDZX2ayyI= +cosmossdk.io/log/v2 v2.1.0 h1:oWLWqZ1UObWu5hIS3dvTW7QyjtvlmSzC3LOy04U/hVI= +cosmossdk.io/log/v2 v2.1.0/go.mod h1:zDNpuRD2sWw4zuw1lZYg/jxKftVG+VizgcWAWkIorwY= +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= +cosmossdk.io/schema v1.1.0/go.mod h1:Gb7pqO+tpR+jLW5qDcNOSv0KtppYs7881kfzakguhhI= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo= +filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc= +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.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-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= +github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/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/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.32.0 h1:rIkQfkCOVKc1OiRCNcSDD8ml5RJlZbH/Xsq7lbpynwc= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.32.0/go.mod h1:RD2SsorTmYhF6HkTmDw7KmPYQk8OBYwTkuasChwv7R4= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.56.0 h1:O2sXMyJh8b7devAGdE+163xtRurt0RVpB6DIzX5vGfg= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.56.0/go.mod h1:hEpiGU18xf70qb3jbTcIggWAiEfX/cOIVc2OTe4OegA= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.56.0 h1:ZIT85vKP7LBS84XJ0WdJ3dPOX3iz4j3c0+lpajGQMyo= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.56.0/go.mod h1:rqP9UEhOXv9WhQ7Gjz+G5y/pf8+BJZW5/Ts0AhE0PwE= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.56.0 h1:0YP0+/ixwu+Uqeu/FGiBZNQ19huiUxxiPXIc9WsLKuQ= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.56.0/go.mod h1:6ZZMQhZKDvUvkJw2rc+oDP90tMMzuU/J+5HG1ZmPOmE= +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= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= +github.com/RoaringBitmap/roaring/v2 v2.18.0 h1:h7sS0VqCkfBMGgcHaudJFB4FE6Td71H6svRB2poRnGY= +github.com/RoaringBitmap/roaring/v2 v2.18.0/go.mod h1:eq4wdNXxtJIS/oikeCzdX1rBzek7ANzbth041hrU8Q4= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/VictoriaMetrics/fastcache v1.13.0 h1:AW4mheMR5Vd9FkAPUv+NH6Nhw+fmbTMGMsNAoA/+4G0= +github.com/VictoriaMetrics/fastcache v1.13.0/go.mod h1:hHXhl4DA2fTL2HTZDJFXWgW0LNjo6B+4aj2Wmng3TjU= +github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/adlio/schema v1.4.0 h1:dekxG6P0my/bPvlyWzMULelR2Xej8RGErlnJcoY5ddw= +github.com/adlio/schema v1.4.0/go.mod h1:3/ojUldWBCWp4e+6VN9ets6unG5WdqbjF7vyzM0zTVQ= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +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-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= +github.com/aws/aws-sdk-go-v2 v1.41.6 h1:1AX0AthnBQzMx1vbmir3Y4WsnJgiydmnJjiLu+LvXOg= +github.com/aws/aws-sdk-go-v2 v1.41.6/go.mod h1:dy0UzBIfwSeot4grGvY1AqFWN5zgziMmWGzysDnHFcQ= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.9 h1:adBsCIIpLbLmYnkQU+nAChU5yhVTvu5PerROm+/Kq2A= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.9/go.mod h1:uOYhgfgThm/ZyAuJGNQ5YgNyOlYfqnGpTHXvk3cpykg= +github.com/aws/aws-sdk-go-v2/config v1.32.14 h1:opVIRo/ZbbI8OIqSOKmpFaY7IwfFUOCCXBsUpJOwDdI= +github.com/aws/aws-sdk-go-v2/config v1.32.14/go.mod h1:U4/V0uKxh0Tl5sxmCBZ3AecYny4UNlVmObYjKuuaiOo= +github.com/aws/aws-sdk-go-v2/credentials v1.19.14 h1:n+UcGWAIZHkXzYt87uMFBv/l8THYELoX6gVcUvgl6fI= +github.com/aws/aws-sdk-go-v2/credentials v1.19.14/go.mod h1:cJKuyWB59Mqi0jM3nFYQRmnHVQIcgoxjEMAbLkpr62w= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21 h1:NUS3K4BTDArQqNu2ih7yeDLaS3bmHD0YndtA6UP884g= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21/go.mod h1:YWNWJQNjKigKY1RHVJCuupeWDrrHjRqHm0N9rdrWzYI= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.22 h1:GmLa5Kw1ESqtFpXsx5MmC84QWa/ZrLZvlJGa2y+4kcQ= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.22/go.mod h1:6sW9iWm9DK9YRpRGga/qzrzNLgKpT2cIxb7Vo2eNOp0= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.22 h1:dY4kWZiSaXIzxnKlj17nHnBcXXBfac6UlsAx2qL6XrU= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.22/go.mod h1:KIpEUx0JuRZLO7U6cbV204cWAEco2iC3l061IxlwLtI= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 h1:qYQ4pzQ2Oz6WpQ8T3HvGHnZydA72MnLuFK9tJwmrbHw= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6/go.mod h1:O3h0IK87yXci+kg6flUKzJnWeziQUKciKrLjcatSNcY= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.23 h1:FPXsW9+gMuIeKmz7j6ENWcWtBGTe1kH8r9thNt5Uxx4= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.23/go.mod h1:7J8iGMdRKk6lw2C+cMIphgAnT8uTwBwNOsGkyOCm80U= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.8 h1:HtOTYcbVcGABLOVuPYaIihj6IlkqubBwFj10K5fxRek= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.8/go.mod h1:VsK9abqQeGlzPgUr+isNWzPlK2vKe9INMLWnY65f5Xs= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.14 h1:xnvDEnw+pnj5mctWiYuFbigrEzSm35x7k4KS/ZkCANg= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.14/go.mod h1:yS5rNogD8e0Wu9+l3MUwr6eENBzEeGejvINpN5PAYfY= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.22 h1:PUmZeJU6Y1Lbvt9WFuJ0ugUK2xn6hIWUBBbKuOWF30s= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.22/go.mod h1:nO6egFBoAaoXze24a2C0NjQCvdpk8OueRoYimvEB9jo= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.22 h1:SE+aQ4DEqG53RRCAIHlCf//B2ycxGH7jFkpnAh/kKPM= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.22/go.mod h1:ES3ynECd7fYeJIL6+oax+uIEljmfps0S70BaQzbMd/o= +github.com/aws/aws-sdk-go-v2/service/s3 v1.100.0 h1:7G26Sae6PMKn4kMcU5JzNfrm1YrKwyOhowXPYR2WiWY= +github.com/aws/aws-sdk-go-v2/service/s3 v1.100.0/go.mod h1:Fw9aqhJicIVee1VytBBjH+l+5ov6/PhbtIK/u3rt/ls= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.9 h1:QKZH0S178gCmFEgst8hN0mCX1KxLgHBKKY/CLqwP8lg= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.9/go.mod h1:7yuQJoT+OoH8aqIxw9vwF+8KpvLZ8AWmvmUWHsGQZvI= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.15 h1:lFd1+ZSEYJZYvv9d6kXzhkZu07si3f+GQ1AaYwa2LUM= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.15/go.mod h1:WSvS1NLr7JaPunCXqpJnWk1Bjo7IxzZXrZi1QQCkuqM= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.19 h1:dzztQ1YmfPrxdrOiuZRMF6fuOwWlWpD2StNLTceKpys= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.19/go.mod h1:YO8TrYtFdl5w/4vmjL8zaBSsiNp3w0L1FfKVKenZT7w= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.10 h1:p8ogvvLugcR/zLBXTXrTkj0RYBUdErbMnAFFp12Lm/U= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.10/go.mod h1:60dv0eZJfeVXfbT1tFJinbHrDfSJ2GZl4Q//OSSNAVw= +github.com/aws/smithy-go v1.25.0 h1:Sz/XJ64rwuiKtB6j98nDIPyYrV1nVNJ4YU74gttcl5U= +github.com/aws/smithy-go v1.25.0/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= +github.com/benbjohnson/clock v1.3.5/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.24.4 h1:95H15Og1clikBrKr/DuzMXkQzECs1M6hhoGXLwLQOZE= +github.com/bits-and-blooms/bitset v1.24.4/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= +github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= +github.com/btcsuite/btcd v0.24.2 h1:aLmxPguqxza+4ag8R1I2nnJjSu2iFn/kqtHTIImswcY= +github.com/btcsuite/btcd v0.24.2/go.mod h1:5C8ChTkl5ejr3WHj8tkQSCmydiMEPB0ZhQhehpq7Dgg= +github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= +github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/btcec/v2 v2.3.5 h1:dpAlnAwmT1yIBm3exhT1/8iUSD98RDJM5vqJVQDQLiU= +github.com/btcsuite/btcd/btcec/v2 v2.3.5/go.mod h1:m22FrOAiuxl/tht9wIqAoGHcbnCCaPWyauO8y2LGGtQ= +github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= +github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= +github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= +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/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/bytedance/gopkg v0.1.4 h1:oZnQwnX82KAIWb7033bEwtxvTqXcYMxDBaQxo5JJHWM= +github.com/bytedance/gopkg v0.1.4/go.mod h1:v1zWfPm21Fb+OsyXN2VAHdL6TBb2L88anLQgdyje6R4= +github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE= +github.com/bytedance/sonic v1.15.0/go.mod h1:tFkWrPz0/CUCLEF4ri4UkHekCIcdnkqXw9VduqpJh0k= +github.com/bytedance/sonic/loader v0.5.1 h1:Ygpfa9zwRCCKSlrp5bBP/b/Xzc3VxsAW+5NIYXrOOpI= +github.com/bytedance/sonic/loader v0.5.1/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= +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= +github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= +github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= +github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= +github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= +github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= +github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI= +github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= +github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M= +github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +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-20260202195803-dba9d589def2 h1:aBangftG7EVZoUb69Os8IaYg++6uMOdKK83QtkkvJik= +github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2/go.mod h1:qwXFYgsP6T7XnJtbKlf1HP8AjxZZyzxMmc+Lq5GjlU4= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= +github.com/cockroachdb/errors v1.13.0 h1:BoCcJeiP9hpBJDETkX19qi8Tb8So37srSsp3stTaDMQ= +github.com/cockroachdb/errors v1.13.0/go.mod h1:bjxt/4E5+OyuAnacpTIU9rn2mzPu1VlthvHP+xpROq0= +github.com/cockroachdb/fifo v0.0.0-20240816210425-c5d0cb0b6fc0 h1:pU88SPhIFid6/k0egdR5V6eALQYq2qbSmukrkgIh/0A= +github.com/cockroachdb/fifo v0.0.0-20240816210425-c5d0cb0b6fc0/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 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.8 h1:8eVLLj6juKxiKrAEw2b8cJvNqWq++U8WOfQFuL7KTaA= +github.com/cockroachdb/redact v1.1.8/go.mod h1:GceHHpJ0rMDpYARL5In88Alq/xMBUtVlz7Qxix6ZVkw= +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.39.3 h1:UegHXskZNomsijmm29nL5NkeXtnzkme6fg+q1hPQnEI= +github.com/cometbft/cometbft v0.39.3/go.mod h1:PmNfvtw256BC41ad0FABts236CSZnvZ0kjPOciBwTdM= +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/consensys/gnark-crypto v0.18.1 h1:RyLV6UhPRoYYzaFnPQA4qK3DyuDgkTgskDdoGqFt3fI= +github.com/consensys/gnark-crypto v0.18.1/go.mod h1:L3mXGFTe1ZN+RSJ+CLjUt9x7PNdx8ubaYfDROyp2Z8c= +github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4= +github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= +github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= +github.com/cosmos/btree v1.0.0 h1:V3OdIzTQw2yE7f6pD6FfA9j2/YLj1UpB9MdY0zU3v3k= +github.com/cosmos/btree v1.0.0/go.mod h1:BZML+flLn4d3MOa4POmzDWf5HQ7EGh0y1OLlfhh7A0k= +github.com/cosmos/cosmos-db v1.1.3 h1:7QNT77+vkefostcKkhrzDK9uoIEryzFrU9eoMeaQOPY= +github.com/cosmos/cosmos-db v1.1.3/go.mod h1:kN+wGsnwUJZYn8Sy5Q2O0vCYA99MJllkKASbs6Unb9U= +github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= +github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= +github.com/cosmos/cosmos-sdk v0.54.3 h1:oUxbIACmHZV13IZXl59y+mIEOCFlUAjXV9p1rqrYcEg= +github.com/cosmos/cosmos-sdk v0.54.3/go.mod h1:Unt21RO+q1EebU6gcUPKYVzpAQSr4KIHjaOmjpz2twA= +github.com/cosmos/cosmos-sdk/store/v2 v2.0.0 h1:5CFXBU5cHIvxMpz5QBrTwR5DL/W3uZL2BYYMoDp4siY= +github.com/cosmos/cosmos-sdk/store/v2 v2.0.0/go.mod h1:XyRyi5fGjIcokBqS1cyA8/QVbVNy4ui8hmpk1gezuHo= +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 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= +github.com/cosmos/gogoproto v1.7.2 h1:5G25McIraOC0mRFv9TVO139Uh3OklV2hczr13KKVHCA= +github.com/cosmos/gogoproto v1.7.2/go.mod h1:8S7w53P1Y1cHwND64o0BnArT6RmdgIvsBuco6uTllsk= +github.com/cosmos/iavl v1.2.8 h1:55F96BGUJ7KT7h+Ky/cEqS+pEvhFqsU4O8Th3F0N1js= +github.com/cosmos/iavl v1.2.8/go.mod h1:FRHN4tO+6crf0p2zsqye+nAbsMgiwdkxpWm18DyP6+Y= +github.com/cosmos/ibc-go/v11 v11.0.0 h1:9EIehi88hNP1cCU83NC+J8UXNn+05YZt9eqmnzCQLSg= +github.com/cosmos/ibc-go/v11 v11.0.0/go.mod h1:iWlzLuCu+ctVbQwoVf5z51HE5e/NE8/pwnLVVDmP++4= +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 v1.0.0 h1:jNKW89nPf0vR0EkjHG8Zz16h6p3zqwYEOxlHArwgYtw= +github.com/cosmos/ledger-cosmos-go v1.0.0/go.mod h1:mGaw2wDOf+Z6SfRJsMGxU9DIrBa4du0MAiPlpPhLAOE= +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.5.0 h1:FYRiJMJG2iv+2Dy3fi14SVGjcPteZ5HAAUe4YWlJygc= +github.com/crate-crypto/go-eth-kzg v1.5.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/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.2.3 h1:v7dZC2x32Ut3nEfRH+vhoZGvN72+dQ/snVXo/vMFLdQ= +github.com/danieljoos/wincred v1.2.3/go.mod h1:6qqX0WNrS4RzPZ1tnroDzq9kY3fu1KwE7MRLQK4X0bs= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +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/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= +github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= +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.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +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.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.1 h1:5RVFMOWjMyRy8cARdy79nAmgYw3hK/4HUq48LQ6Wwqo= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.1/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/deepmap/oapi-codegen v1.6.0 h1:w/d1ntwh91XI0b/8ja7+u5SvA4IFfM0UNNLmiDR1gg0= +github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M= +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.9.1 h1:DocZXZkg5JJHJPtUErA0ibyHxOVUDVoXLSCV6t8NC8w= +github.com/dgraph-io/badger/v4 v4.9.1/go.mod h1:5/MEx97uzdPUHR4KtkNt8asfI2T4JiEiQlV7kWUo8c0= +github.com/dgraph-io/ristretto/v2 v2.4.0 h1:I/w09yLjhdcVD2QV192UJcq8dPBaAJb9pOuMyNy0XlU= +github.com/dgraph-io/ristretto/v2 v2.4.0/go.mod h1:0KsrXtXvnv0EqnzyowllbVJB8yBonswa2lTCK2gGo9E= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da h1:aIftn67I1fkbMa512G+w+Pxci9hJPB8oMnkcP3iZF38= +github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= +github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94= +github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE= +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/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= +github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjUQYeC8R4ILzVcIe8+5edAJJnE= +github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= +github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= +github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= +github.com/dunglas/httpsfv v1.1.0 h1:Jw76nAyKWKZKFrpMMcL76y35tOpYHqQPzHQiwDvpe54= +github.com/dunglas/httpsfv v1.1.0/go.mod h1:zID2mqw9mFsnt7YC3vYQ9/cjq30q41W+1AnDwH8TiMg= +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.8.0 h1:LqkkVKAlHFfH9LOEl5fe4p/zL02OhWE7pCufMBG2jLA= +github.com/dvsekhvalnov/jose2go v1.8.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= +github.com/ebitengine/purego v0.10.0 h1:QIw4xfpWT6GWTzaW5XEKy3HXoqrJGx1ijYHzTF0/ISU= +github.com/ebitengine/purego v0.10.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/emicklei/dot v1.11.0 h1:zsrhCuFHAJge/aZIC4N4LdHy5tqYu4tWEaUzIwdYj4Y= +github.com/emicklei/dot v1.11.0/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +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.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA= +github.com/envoyproxy/go-control-plane v0.14.0/go.mod h1:NcS5X47pLl/hfqxU70yPwL9ZMkUlwlKxtAohpi2wBEU= +github.com/envoyproxy/go-control-plane/envoy v1.37.0 h1:u3riX6BoYRfF4Dr7dwSOroNfdSbEPe9Yyl09/B6wBrQ= +github.com/envoyproxy/go-control-plane/envoy v1.37.0/go.mod h1:DReE9MMrmecPy+YvQOAOHNYMALuowAnbjjEMkkWOi6A= +github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 h1:/G9QYbddjL25KvtKTv3an9lx6VBE2cnb8wp1vEGNYGI= +github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v1.3.3 h1:MVQghNeW+LZcmXe7SY1V36Z+WFMDjpqGAGacLe2T0ds= +github.com/envoyproxy/protoc-gen-validate v1.3.3/go.mod h1:TsndJ/ngyIdQRhMcVVGDDHINPLWB7C82oDArY51KfB0= +github.com/ethereum/c-kzg-4844/v2 v2.1.6 h1:xQymkKCT5E2Jiaoqf3v4wsNgjZLY0lRSkZn27fRjSls= +github.com/ethereum/c-kzg-4844/v2 v2.1.6/go.mod h1:8HMkUZ5JRv4hpw/XUrYWSQNAUzhHMg2UDb/U+5m+XNw= +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= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/ferranbt/fastssz v0.1.4 h1:OCDB+dYDEQDvAgtAGnTSidK1Pe2tW3nFV40XyMkTeDY= +github.com/ferranbt/fastssz v0.1.4/go.mod h1:Ea3+oeoRGGLGm5shYAeDgu6PGUlcvQhE2fILyD9+tGg= +github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg= +github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= +github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/gammazero/deque v1.2.0 h1:scEFO8Uidhw6KDU5qg1HA5fYwM0+us2qdeJqm43bitU= +github.com/gammazero/deque v1.2.0/go.mod h1:JVrR+Bj1NMQbPnYclvDlvSX0nVGReLrQZ0aUMuWLctg= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/getsentry/sentry-go v0.46.0 h1:mbdDaarbUdOt9X+dx6kDdntkShLEX3/+KyOsVDTPDj0= +github.com/getsentry/sentry-go v0.46.0/go.mod h1:evVbw2qotNUdYG8KxXbAdjOQWWvWIwKxpjdZZIvcIPw= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +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.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= +github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= +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.1 h1:4hvbpePJKnIzH1B+8OR/JPbTx37NktoI9LE2QZBBkvE= +github.com/go-logfmt/logfmt v0.6.1/go.mod h1:EV2pOAQoZaT1ZXZbqDl5hrymndi4SY9ED9/z6CO0XAk= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +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.6/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/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +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.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro= +github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= +github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +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/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= +github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +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/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= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +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.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs= +github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= +github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/flatbuffers v25.2.10+incompatible h1:F3vclr7C3HpB1k9mxCGRMXq6FdUalZ6H/pNX4FP1v0Q= +github.com/google/flatbuffers v25.2.10+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.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= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +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/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc= +github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= +github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= +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/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= +github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8= +github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +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.14 h1:yh8ncqsbUY4shRD5dA6RlzjJaT4hi3kII+zYw8wmLb8= +github.com/googleapis/enterprise-certificate-proxy v0.3.14/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg= +github.com/googleapis/gax-go/v2 v2.22.0 h1:PjIWBpgGIVKGoCXuiCoP64altEJCj3/Ei+kSU5vlZD4= +github.com/googleapis/gax-go/v2 v2.22.0/go.mod h1:irWBbALSr0Sk3qlqb9SyJ1h68WjgeFuiOzI4Rqw5+aY= +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= +github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0= +github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c= +github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= +github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= +github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.72 h1:vTCWu1wbdYo7PEZFem/rlr01+Un+wwVmI7wiegFdRLk= +github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.72/go.mod h1:Vn+BBgKQHVQYdVQ4NZDICE1Brb+JfaONyDHr3q07oQc= +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.8.6 h1:9sQboWULaydVphxc4S64oAI4YqpuCk7nPmvbk131ebY= +github.com/hashicorp/go-getter v1.8.6/go.mod h1:nVH12eOV2P58dIiL3rsU6Fh3wLeJEKBOJzhMmzlSWoo= +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= +github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-metrics v0.5.4 h1:8mmPiIJkTPPEbAiV97IxdAGNdRdaWwVap1BU6elejKY= +github.com/hashicorp/go-metrics v0.5.4/go.mod h1:CG5yz4NZ/AI/aQt9Ucm/vdBnbh7fvmv4lxZ350i+QQI= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-plugin v1.7.0 h1:YghfQH/0QmPNc/AZMTFE3ac8fipZyZECHdDPshfk+mA= +github.com/hashicorp/go-plugin v1.7.0/go.mod h1:BExt6KEaIYx804z8k4gRzRLEvxKVb+kn0NMcihqOqb8= +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-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= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +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.9.0 h1:CeOIz6k+LoN3qX9Z0tyQrPtiB1DFYRPfCIBtaXPSCnA= +github.com/hashicorp/go-version v1.9.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= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +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= +github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= +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/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= +github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= +github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ= +github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPtwNr0l57L4f878wP8= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +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/influxdb-client-go/v2 v2.4.0 h1:HGBfZYStlx3Kqvsv1h2pJixbCl/jhnFtxpKFAv9Tu5k= +github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c h1:qSHzRbhzK8RdXOsAdfDgO49TtqC1oZ+acxPrkfTxcCs= +github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 h1:W9WBk7wlPfJLvMCdtV4zPulc4uCPrlywQOmbFOhgQNU= +github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= +github.com/ipfs/go-cid v0.5.0 h1:goEKKhaGm0ul11IHA7I6p1GmKz8kEYniqFopaB5Otwg= +github.com/ipfs/go-cid v0.5.0/go.mod h1:0L7vmeNXpQpUS9vt+yEARkJ8rOg43DF3iPgn4GIN0mk= +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/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= +github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jhump/protoreflect v1.18.0 h1:TOz0MSR/0JOZ5kECB/0ufGnC2jdsgZ123Rd/k4Z5/2w= +github.com/jhump/protoreflect v1.18.0/go.mod h1:ezWcltJIVF4zYdIFM+D/sHV4Oh5LNU08ORzCGfwvTz8= +github.com/jhump/protoreflect/v2 v2.0.0-beta.1 h1:Dw1rslK/VotaUGYsv53XVWITr+5RCPXfvvlGrM/+B6w= +github.com/jhump/protoreflect/v2 v2.0.0-beta.1/go.mod h1:D9LBEowZyv8/iSu97FU2zmXG3JxVTmNw21mu63niFzU= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +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= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +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/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= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE= +github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= +github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/koron/go-ssdp v0.0.6 h1:Jb0h04599eq/CY7rB5YEqPS83HmRfHP2azkxMN2rFtU= +github.com/koron/go-ssdp v0.0.6/go.mod h1:0R9LfRJGek1zWTjN3JUNlm5INCDYGpRDfAptnct63fI= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +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/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/lib/pq v1.12.3 h1:tTWxr2YLKwIvK90ZXEw8GP7UFHtcbTtty8zsI+YjrfQ= +github.com/lib/pq v1.12.3/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA= +github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= +github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= +github.com/libp2p/go-flow-metrics v0.2.0 h1:EIZzjmeOE6c8Dav0sNv35vhZxATIXWZg6j/C08XmmDw= +github.com/libp2p/go-flow-metrics v0.2.0/go.mod h1:st3qqfu8+pMfh+9Mzqb2GTiwrAGjIPszEjZmtksN8Jc= +github.com/libp2p/go-libp2p v0.47.0 h1:qQpBjSCWNQFF0hjBbKirMXE9RHLtSuzTDkTfr1rw0yc= +github.com/libp2p/go-libp2p v0.47.0/go.mod h1:s8HPh7mMV933OtXzONaGFseCg/BE//m1V34p3x4EUOY= +github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94= +github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8= +github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= +github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg= +github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= +github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM= +github.com/libp2p/go-netroute v0.3.0 h1:nqPCXHmeNmgTJnktosJ/sIef9hvwYCrsLxXmfNks/oc= +github.com/libp2p/go-netroute v0.3.0/go.mod h1:Nkd5ShYgSMS5MUKy/MU2T57xFoOKvvLR92Lic48LEyA= +github.com/libp2p/go-reuseport v0.4.0 h1:nR5KU7hD0WxXCJbmw7r2rhRYruNRl2koHw8fQscQm2s= +github.com/libp2p/go-reuseport v0.4.0/go.mod h1:ZtI03j/wO5hZVDFo2jKywN6bYKWLOy8Se6DrI2E1cLU= +github.com/libp2p/go-yamux/v5 v5.0.1 h1:f0WoX/bEF2E8SbE4c/k1Mo+/9z0O4oC/hWEA+nfYRSg= +github.com/libp2p/go-yamux/v5 v5.0.1/go.mod h1:en+3cdX51U0ZslwRdRLrvQsdayFt3TSUKvBGErzpWbU= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/linxGnu/grocksdb v1.10.7 h1:fCi4qvZWo04VgFwGWmO8HQJgUVounJBy+C2TMVPU/ho= +github.com/linxGnu/grocksdb v1.10.7/go.mod h1:OLQKZwiKwaJiAVCsOzWKvwiLwfZ5Vz8Md5TYR7t7pM8= +github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e h1:Q6MvJtQK/iRcRtzAscm/zF23XxJlbECiGPyRicsX+Ak= +github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= +github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= +github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= +github.com/marcopolo/simnet v0.0.4 h1:50Kx4hS9kFGSRIbrt9xUS3NJX33EyPqHVmpXvaKLqrY= +github.com/marcopolo/simnet v0.0.4/go.mod h1:tfQF1u2DmaB6WHODMtQaLtClEf3a296CKQLq5gAsIS0= +github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= +github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4= +github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +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/miekg/dns v1.1.66 h1:FeZXOS3VCVsKnEAd+wBkjMC3D2K+ww66Cq3VnCINuJE= +github.com/miekg/dns v1.1.66/go.mod h1:jGFzBsSNbJw6z1HYut1RKBKHA9PBdxeHrZG8J+gC2WE= +github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= +github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms= +github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= +github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b/go.mod h1:lxPUiZwKoFL8DUUmalo2yJJUCxbPKtm8OKfqr2/FTNU= +github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdnNMiD9ZejrlswWrCpBEZgWOiTrc= +github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s= +github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= +github.com/minio/highwayhash v1.0.4 h1:asJizugGgchQod2ja9NJlGOWq4s7KsAWr5XUc9Clgl4= +github.com/minio/highwayhash v1.0.4/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= +github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= +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/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/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/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs= +github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +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/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mr-tron/base58 v1.3.0 h1:K6Y13R2h+dku0wOqKtecgRnBUBPrZzLZy5aIj8lCcJI= +github.com/mr-tron/base58 v1.3.0/go.mod h1:2BuubE67DCSWwVfx37JWNG8emOC0sHEU4/HpcYgCLX8= +github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM= +github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw= +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/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= +github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= +github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= +github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= +github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= +github.com/multiformats/go-multiaddr v0.16.1 h1:fgJ0Pitow+wWXzN9do+1b8Pyjmo8m5WhGfzpL82MpCw= +github.com/multiformats/go-multiaddr v0.16.1/go.mod h1:JSVUmXDjsVFiW7RjIFMP7+Ev+h1DTbiJgVeTV/tcmP0= +github.com/multiformats/go-multiaddr-dns v0.4.1 h1:whi/uCLbDS3mSEUMb1MsoT4uzUeZB0N32yzufqS0i5M= +github.com/multiformats/go-multiaddr-dns v0.4.1/go.mod h1:7hfthtB4E4pQwirrz+J0CcDUfbWzTqEzVyYKKIKpgkc= +github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= +github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= +github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= +github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk= +github.com/multiformats/go-multicodec v0.9.1 h1:x/Fuxr7ZuR4jJV4Os5g444F7xC4XmyUaT/FWtE+9Zjo= +github.com/multiformats/go-multicodec v0.9.1/go.mod h1:LLWNMtyV5ithSBUo3vFIMaeDy+h3EbkMTek1m+Fybbo= +github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= +github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U= +github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= +github.com/multiformats/go-multistream v0.6.1 h1:4aoX5v6T+yWmc2raBHsTvzmFhOI8WVOer28DeBBEYdQ= +github.com/multiformats/go-multistream v0.6.1/go.mod h1:ksQf6kqHAb6zIsyw7Zm+gAuVo57Qbq84E27YlYqavqw= +github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= +github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/grpc-proxy v0.0.0-20181017164139-0f1106ef9c76/go.mod h1:x5OoJHDHqxHS801UIuhqGl6QdSAEJvtausosHSdazIo= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oasisprotocol/curve25519-voi v0.0.0-20251114093237-2ab5a27a1729 h1:yfQ2sO9WJXUAIUR+g7NUkxJSKCAFJcR5sUDu+ZmjTZI= +github.com/oasisprotocol/curve25519-voi v0.0.0-20251114093237-2ab5a27a1729/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/oklog/run v1.2.0 h1:O8x3yXwah4A73hJdlrwo/2X6J62gE5qTMusH0dvz60E= +github.com/oklog/run v1.2.0/go.mod h1:mgDbKRSwPhJfesJ4PntqFUbKQRZ50NgmZTSPlFA0YFk= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +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= +github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= +github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= +github.com/opencontainers/runc v1.2.8 h1:RnEICeDReapbZ5lZEgHvj7E9Q3Eex9toYmaGBsbvU5Q= +github.com/opencontainers/runc v1.2.8/go.mod h1:cC0YkmZcuvr+rtBZ6T7NBoVbMGNAdLa/21vIElJDOzI= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= +github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= +github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 h1:oYW+YCJ1pachXTQmzR3rNLYGGz4g/UgFcjb28p/viDM= +github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= +github.com/petermattis/goid v0.0.0-20250813065127-a731cc31b4fe/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/petermattis/goid v0.0.0-20260113132338-7c7de50cc741 h1:KPpdlQLZcHfTMQRi6bFQ7ogNO0ltFT4PmtwTLW4W+14= +github.com/petermattis/goid v0.0.0-20260113132338-7c7de50cc741/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +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/datachannel v1.5.10 h1:ly0Q26K1i6ZkGf42W7D4hQYR90pZwzFOjTq5AuCKk4o= +github.com/pion/datachannel v1.5.10/go.mod h1:p/jJfC9arb29W7WrxyKbepTU20CFgyx5oLo8Rs4Py/M= +github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s= +github.com/pion/dtls/v2 v2.2.12 h1:KP7H5/c1EiVAAKUmXyCzPiQe5+bCJrpOeKg/L05dunk= +github.com/pion/dtls/v2 v2.2.12/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE= +github.com/pion/dtls/v3 v3.1.2 h1:gqEdOUXLtCGW+afsBLO0LtDD8GnuBBjEy6HRtyofZTc= +github.com/pion/dtls/v3 v3.1.2/go.mod h1:Hw/igcX4pdY69z1Hgv5x7wJFrUkdgHwAn/Q/uo7YHRo= +github.com/pion/ice/v4 v4.0.10 h1:P59w1iauC/wPk9PdY8Vjl4fOFL5B+USq1+xbDcN6gT4= +github.com/pion/ice/v4 v4.0.10/go.mod h1:y3M18aPhIxLlcO/4dn9X8LzLLSma84cx6emMSu14FGw= +github.com/pion/interceptor v0.1.40 h1:e0BjnPcGpr2CFQgKhrQisBU7V3GXK6wrfYrGYaU6Jq4= +github.com/pion/interceptor v0.1.40/go.mod h1:Z6kqH7M/FYirg3frjGJ21VLSRJGBXB/KqaTIrdqnOic= +github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= +github.com/pion/logging v0.2.4 h1:tTew+7cmQ+Mc1pTBLKH2puKsOvhm32dROumOZ655zB8= +github.com/pion/logging v0.2.4/go.mod h1:DffhXTKYdNZU+KtJ5pyQDjvOAh/GsNSyv1lbkFbe3so= +github.com/pion/mdns/v2 v2.0.7 h1:c9kM8ewCgjslaAmicYMFQIde2H9/lrZpjBkN8VwoVtM= +github.com/pion/mdns/v2 v2.0.7/go.mod h1:vAdSYNAT0Jy3Ru0zl2YiW3Rm/fJCwIeM0nToenfOJKA= +github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= +github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= +github.com/pion/rtcp v1.2.15 h1:LZQi2JbdipLOj4eBjK4wlVoQWfrZbh3Q6eHtWtJBZBo= +github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0= +github.com/pion/rtp v1.8.19 h1:jhdO/3XhL/aKm/wARFVmvTfq0lC/CvN1xwYKmduly3c= +github.com/pion/rtp v1.8.19/go.mod h1:bAu2UFKScgzyFqvUKmbvzSdPr+NGbZtv6UB2hesqXBk= +github.com/pion/sctp v1.8.39 h1:PJma40vRHa3UTO3C4MyeJDQ+KIobVYRZQZ0Nt7SjQnE= +github.com/pion/sctp v1.8.39/go.mod h1:cNiLdchXra8fHQwmIoqw0MbLLMs+f7uQ+dGMG2gWebE= +github.com/pion/sdp/v3 v3.0.13 h1:uN3SS2b+QDZnWXgdr69SM8KB4EbcnPnPf2Laxhty/l4= +github.com/pion/sdp/v3 v3.0.13/go.mod h1:88GMahN5xnScv1hIMTqLdu/cOcUkj6a9ytbncwMCq2E= +github.com/pion/srtp/v3 v3.0.6 h1:E2gyj1f5X10sB/qILUGIkL4C2CqK269Xq167PbGCc/4= +github.com/pion/srtp/v3 v3.0.6/go.mod h1:BxvziG3v/armJHAaJ87euvkhHqWe9I7iiOy50K2QkhY= +github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4= +github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8= +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/stun/v3 v3.0.0 h1:4h1gwhWLWuZWOJIJR9s2ferRO+W3zA/b6ijOI6mKzUw= +github.com/pion/stun/v3 v3.0.0/go.mod h1:HvCN8txt8mwi4FBvS3EmDghW6aQJ24T+y+1TKjB5jyU= +github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g= +github.com/pion/transport/v2 v2.2.4/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0= +github.com/pion/transport/v2 v2.2.10 h1:ucLBLE8nuxiHfvkFKnkDQRYWYfp8ejf4YBOPfaQpw6Q= +github.com/pion/transport/v2 v2.2.10/go.mod h1:sq1kSLWs+cHW9E+2fJP95QudkzbK7wscs8yYgQToO5E= +github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0= +github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0= +github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo= +github.com/pion/transport/v4 v4.0.1 h1:sdROELU6BZ63Ab7FrOLn13M6YdJLY20wldXW2Cu2k8o= +github.com/pion/transport/v4 v4.0.1/go.mod h1:nEuEA4AD5lPdcIegQDpVLgNoDGreqM/YqmEx3ovP4jM= +github.com/pion/turn/v4 v4.0.2 h1:ZqgQ3+MjP32ug30xAbD6Mn+/K4Sxi3SdNOTFf+7mpps= +github.com/pion/turn/v4 v4.0.2/go.mod h1:pMMKP/ieNAG/fN5cZiN4SDuyKsXtNTr0ccN7IToA1zs= +github.com/pion/webrtc/v4 v4.1.2 h1:mpuUo/EJ1zMNKGE79fAdYNFZBX790KE7kQQpLMjjR54= +github.com/pion/webrtc/v4 v4.1.2/go.mod h1:xsCXiNAmMEjIdFxAYU0MbB3RwRieJsegSB2JZsGN+8U= +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= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= +github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= +github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc= +github.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo= +github.com/prysmaticlabs/gohashtree v0.0.4-beta h1:H/EbCuXPeTV3lpKeXGPpEV9gsUpkqOOVnWapUyeWro4= +github.com/prysmaticlabs/gohashtree v0.0.4-beta/go.mod h1:BFdtALS+Ffhg3lGQIHv9HDWuHS8cTvHZzrHWxwOtGOs= +github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8= +github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII= +github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw= +github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU= +github.com/quic-go/webtransport-go v0.10.0 h1:LqXXPOXuETY5Xe8ITdGisBzTYmUOy5eSj+9n4hLTjHI= +github.com/quic-go/webtransport-go v0.10.0/go.mod h1:LeGIXr5BQKE3UsynwVBeQrU1TPrbh73MGoC6jd+V7ow= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 h1:bsUq1dX0N8AOIL7EB/X911+m4EHsnWEHeJ0c+3TTBrg= +github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= +github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/zerolog v1.35.0 h1:VD0ykx7HMiMJytqINBsKcbLS+BJ4WYjz+05us+LRTdI= +github.com/rs/zerolog v1.35.0/go.mod h1:EjML9kdfa/RMA7h/6z6pYmq1ykOuA8/mjWaEvGI+jcw= +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.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88eegjfxfHb4= +github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9tLLBmM4eneO6WwsI= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/sasha-s/go-deadlock v0.3.9 h1:fiaT9rB7g5sr5ddNZvlwheclN9IP86eFW9WgqlEQV+w= +github.com/sasha-s/go-deadlock v0.3.9/go.mod h1:KuZj51ZFmx42q/mPaYbRk0P1xcwe697zsJKE03vD4/Y= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= +github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil/v4 v4.26.4 h1:B4SXVbcwTyrocPHEmWBC4uCYr4Xcu3MK1TXqbprAOWY= +github.com/shirou/gopsutil/v4 v4.26.4/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= +github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= +github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= +github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= +github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= +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.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= +github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= +github.com/spiffe/go-spiffe/v2 v2.6.0 h1:l+DolpxNWYgruGQVV0xsfeya3CsC7m8iBzDnMpsbLuo= +github.com/spiffe/go-spiffe/v2 v2.6.0/go.mod h1:gm2SeUoMZEtpnzPNs2Csc0D/gX33k1xIx7lEzqblHEs= +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= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4= +github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/supranational/blst v0.3.16 h1:bTDadT+3fK497EvLdWRQEjiGnUtzJ7jjIUMF0jqwYhE= +github.com/supranational/blst v0.3.16/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= +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.8.1 h1:27ehoXvm5AG/g+1VxLS1SD3vRhp/H7LuEfwNvddEdmA= +github.com/tidwall/btree v1.8.1/go.mod h1:jBbTdUWhSZClZWoDg54VnvV7/54modSOzDN7VXftj1A= +github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= +github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/match v1.2.0 h1:0pt8FlkOwjN2fPt4bIl4BoNxb98gGHN2ObFEDkrfZnM= +github.com/tidwall/match v1.2.0/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= +github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= +github.com/tklauser/go-sysconf v0.3.16 h1:frioLaCQSsF5Cy1jgRBrzr6t502KIIwQ0MArYICU0nA= +github.com/tklauser/go-sysconf v0.3.16/go.mod h1:/qNL9xxDhc7tx3HSRsLWNnuzbVfh3e7gh/BmM179nYI= +github.com/tklauser/numcpus v0.11.0 h1:nSTwhKH5e1dMNsCdVBukSZrURJRoHbSEQjdEbY+9RXw= +github.com/tklauser/numcpus v0.11.0/go.mod h1:z+LwcLq54uWZTX0u/bGobaV34u6V7KNlTZejzM6/3MQ= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +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/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY= +github.com/ulikunitz/xz v0.5.15/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/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= +github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU= +github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= +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/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +github.com/zondax/golem v0.27.0 h1:IbBjGIXF3SoGOZHsILJvIM/F/ylwJzMcHAcggiqniPw= +github.com/zondax/golem v0.27.0/go.mod h1:AmorCgJPt00L8xN1VrMBe13PSifoZksnQ1Ge906bu4A= +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 v1.0.1 h1:Ks/2tz/dOF+dbRynfZ0dEhcdL1lqw43Sa0zMXHpQ3aQ= +github.com/zondax/ledger-go v1.0.1/go.mod h1:j7IgMY39f30apthJYMd1YsHZRqdyu4KbVmUp0nU78X0= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo= +go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +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.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/contrib/bridges/otelslog v0.18.0 h1:hhPGP3zvvy1xWT9RTy970wlniSxFttBIsAK1gvMguJM= +go.opentelemetry.io/contrib/bridges/otelslog v0.18.0/go.mod h1:twJF7inoMza6kxMcF8JOdL3mPmtOZu7GEr34CUNE6Dg= +go.opentelemetry.io/contrib/detectors/gcp v1.43.0 h1:62yY3dT7/ShwOxzA0RsKRgshBmfElKI4d/Myu2OxDFU= +go.opentelemetry.io/contrib/detectors/gcp v1.43.0/go.mod h1:RyaZMFY7yi1kAs45S6mbFGz8O8rqB0dTY14uzvG4LCs= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 h1:0Qx7VGBacMm9ZENQ7TnNObTYI4ShC+lHI16seduaxZo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0/go.mod h1:Sje3i3MjSPKTSPvVWCaL8ugBzJwik3u4smCjUeuupqg= +go.opentelemetry.io/contrib/instrumentation/host v0.68.0 h1:0BfTRAHtFpIlIY7cw1qg9nODUwblutIqx7Cn6NPD+2s= +go.opentelemetry.io/contrib/instrumentation/host v0.68.0/go.mod h1:SmgEeGNt1+gp8bmzB5LLyUlCObWcWrRbYMIiDii3NH8= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 h1:CqXxU8VOmDefoh0+ztfGaymYbhdB/tT3zs79QaZTNGY= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0/go.mod h1:BuhAPThV8PBHBvg8ZzZ/Ok3idOdhWIodywz2xEcRbJo= +go.opentelemetry.io/contrib/instrumentation/runtime v0.68.0 h1:jhVIQEprwUTV+KfzzliLidclhoTOoHTgdz96kAyR8mU= +go.opentelemetry.io/contrib/instrumentation/runtime v0.68.0/go.mod h1:4HsdbLUbernaTnA8CNaNE+1g026SciXb3juRYe3l8EY= +go.opentelemetry.io/contrib/otelconf v0.23.0 h1:s3C7KdMYiutf4rC8hKFA0WOIDG+gIru8ajjQKS59ir8= +go.opentelemetry.io/contrib/otelconf v0.23.0/go.mod h1:0kN2tcccZS82e7IZlo045gkcL8/8dup1k25sf9ypGxM= +go.opentelemetry.io/contrib/propagators/autoprop v0.68.0 h1:wLGFvNBPqQhzBn0QRBZjrriH8lZ9gqtTz8ufHEjLg7k= +go.opentelemetry.io/contrib/propagators/autoprop v0.68.0/go.mod h1:evWK9nCqCzH8nhclTlpkdUzmxrmJQ2mrWCdKIvyOYec= +go.opentelemetry.io/contrib/propagators/aws v1.43.0 h1:EwnsB3cXRLAh7/Nr/9rMuGw73nfb3z6uAvVDjRrbeUg= +go.opentelemetry.io/contrib/propagators/aws v1.43.0/go.mod h1:CJjTym6F87tEdm61Qvnz5xrV8vKlH4C92djiqcn62k8= +go.opentelemetry.io/contrib/propagators/b3 v1.43.0 h1:CETqV3QLLPTy5yNrqyMr41VnAOOD4lsRved7n4QG00A= +go.opentelemetry.io/contrib/propagators/b3 v1.43.0/go.mod h1:Q4mCiCdziYzpNR0g+6UqVotAlCDZdzz6L8jwY4knOrw= +go.opentelemetry.io/contrib/propagators/jaeger v1.43.0 h1:peiLMz1+aqJE+3L4mOVtR9wlmv+yh/JVYXCBjqmzJJE= +go.opentelemetry.io/contrib/propagators/jaeger v1.43.0/go.mod h1:Agvif+4A8p/3UtZzJ0MCcDEuQwgtrzM71DueU41DCs8= +go.opentelemetry.io/contrib/propagators/ot v1.43.0 h1:Hh1HahlGc81AOE7siqi1tVOlbanY/UxMMWedpb0d5oQ= +go.opentelemetry.io/contrib/propagators/ot v1.43.0/go.mod h1:58MlyS7lghzYvAm5LN9gGmZpCMQEMB5vpZp9SRgOyE4= +go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= +go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.19.0 h1:Dn8rkudDzY6KV9dr/D/bTUuWgqDf9xe0rr4G2elrn0Y= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.19.0/go.mod h1:gMk9F0xDgyN9M/3Ed5Y1wKcx/9mlU91NXY2SNq7RQuU= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0 h1:HIBTQ3VO5aupLKjC90JgMqpezVXwFuq6Ryjn0/izoag= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0/go.mod h1:ji9vId85hMxqfvICA0Jt8JqEdrXaAkcpkI9HPXya0ro= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.43.0 h1:8UQVDcZxOJLtX6gxtDt3vY2WTgvZqMQRzjsqiIHQdkc= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.43.0/go.mod h1:2lmweYCiHYpEjQ/lSJBYhj9jP1zvCvQW4BqL9dnT7FQ= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0 h1:w1K+pCJoPpQifuVpsKamUdn9U0zM3xUziVOqsGksUrY= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0/go.mod h1:HBy4BjzgVE8139ieRI75oXm3EcDN+6GhD88JT1Kjvxg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 h1:88Y4s2C8oTui1LGM6bTWkw0ICGcOLCAI5l6zsD1j20k= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0/go.mod h1:Vl1/iaggsuRlrHf/hfPJPvVag77kKyvrLeD10kpMl+A= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 h1:RAE+JPfvEmvy+0LzyUA25/SGawPwIUbZ6u0Wug54sLc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0/go.mod h1:AGmbycVGEsRx9mXMZ75CsOyhSP6MFIcj/6dnG+vhVjk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 h1:3iZJKlCZufyRzPzlQhUIWVmfltrXuGyfjREgGP3UUjc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0/go.mod h1:/G+nUPfhq2e+qiXMGxMwumDrP5jtzU+mWN7/sjT2rak= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.19.0 h1:GJkybS+crDMdExT/BUNCEgfrmfboztcS6PhvSo88HKM= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.19.0/go.mod h1:NuAyxRYIG2lKX3YQkB+83StTxM7s52PUUkRRiC0wnYI= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.43.0 h1:TC+BewnDpeiAmcscXbGMfxkO+mwYUwE/VySwvw88PfA= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.43.0/go.mod h1:J/ZyF4vfPwsSr9xJSPyQ4LqtcTPULFR64KwTikGLe+A= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.43.0 h1:mS47AX77OtFfKG4vtp+84kuGSFZHTyxtXIN269vChY0= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.43.0/go.mod h1:PJnsC41lAGncJlPUniSwM81gc80GkgWJWr3cu2nKEtU= +go.opentelemetry.io/otel/log v0.19.0 h1:KUZs/GOsw79TBBMfDWsXS+KZ4g2Ckzksd1ymzsIEbo4= +go.opentelemetry.io/otel/log v0.19.0/go.mod h1:5DQYeGmxVIr4n0/BcJvF4upsraHjg6vudJJpnkL6Ipk= +go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= +go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= +go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= +go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= +go.opentelemetry.io/otel/sdk/log v0.19.0 h1:scYVLqT22D2gqXItnWiocLUKGH9yvkkeql5dBDiXyko= +go.opentelemetry.io/otel/sdk/log v0.19.0/go.mod h1:vFBowwXGLlW9AvpuF7bMgnNI95LiW10szrOdvzBHlAg= +go.opentelemetry.io/otel/sdk/log/logtest v0.19.0 h1:BEbF7ZBB6qQloV/Ub1+3NQoOUnVtcGkU3XX4Ws3GQfk= +go.opentelemetry.io/otel/sdk/log/logtest v0.19.0/go.mod h1:Lua81/3yM0wOmoHTokLj9y9ADeA02v1naRrVrkAZuKk= +go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= +go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= +go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= +go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g= +go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk= +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= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/dig v1.19.0 h1:BACLhebsYdpQ7IROQ1AGPjrXcP5dF80U3gKoFzbaq/4= +go.uber.org/dig v1.19.0/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE= +go.uber.org/fx v1.24.0 h1:wE8mruvpg2kiiL1Vqd0CC+tr0/24XIB10Iwp2lLWzkg= +go.uber.org/fx v1.24.0/go.mod h1:AmDeGyS+ZARGKM4tlH4FY2Jr63VjbEDJHtqXTGP5hbo= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= +go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +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.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= +go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= +go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +golang.org/x/arch v0.26.0 h1:jZ6dpec5haP/fUv1kLCbuJy6dnRrfX6iVK08lZBFpk4= +golang.org/x/arch v0.26.0/go.mod h1:0X+GdSIP+kL5wPmpK7sdkEVTt2XoYP0cSjQSbZBwOi8= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +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.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= +golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= +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= +golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90 h1:jiDhWWeC7jfWqR9c/uplMOqJ0sbNlNWv0UkzE0vX1MA= +golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90/go.mod h1:xE1HEv6b+1SCZ5/uscMRjUBKtIxworgEcEi+/n9NQDQ= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI= +golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY= +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= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +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.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= +golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= +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.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= +golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= +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= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +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.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +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= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +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= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +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-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= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-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-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.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.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= +golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/telemetry v0.0.0-20260311193753-579e4da9a98c h1:6a8FdnNk6bTXBjR4AGKFgUKuo+7GnR3FX5L7CbveeZc= +golang.org/x/telemetry v0.0.0-20260311193753-579e4da9a98c/go.mod h1:TpUTTEp9frx7rTdLpC9gFG9kdI7zVLFTFFlqaH2Cncw= +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.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= +golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY= +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.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= +golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= +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.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= +golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= +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= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s= +golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +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= +gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= +gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +google.golang.org/api v0.276.0 h1:nVArUtfLEihtW+b0DdcqRGK1xoEm2+ltAihyztq7MKY= +google.golang.org/api v0.276.0/go.mod h1:Fnag/EWUPIcJXuIkP1pjoTgS5vdxlk3eeemL7Do6bvw= +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= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20260414002931-afd174a4e478 h1:aLsVTW0lZ8+IY5u/ERjZSCvAmhuR7slKzyha3YikDNA= +google.golang.org/genproto v0.0.0-20260414002931-afd174a4e478/go.mod h1:YJAzKjfHIUHb9T+bfu8L7mthAp7VVXQBUs1PLdBWS7M= +google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 h1:yQugLulqltosq0B/f8l4w9VryjV+N/5gcW0jQ3N8Qec= +google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478/go.mod h1:C6ADNqOxbgdUUeRTU+LCHDPB9ttAMCTff6auwCVa4uc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 h1:RmoJA1ujG+/lRGNfUnOMfhCy5EipVMyvUE+KNbPbTlw= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +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.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= +google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= +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= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +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= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/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/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +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= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= +gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +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= +lukechampine.com/blake3 v1.4.1 h1:I3Smz7gso8w4/TunLKec6K2fn+kyKtDxr/xcQEN84Wg= +lukechampine.com/blake3 v1.4.1/go.mod h1:QFosUxmjB8mnrWFSNwKmvxHpfY72bmD2tQ0kBMM3kwo= +nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= +nhooyr.io/websocket v1.8.17 h1:KEVeLJkUywCKVsnLIDlD/5gtayKp8VoCkksHCGGfT9Y= +nhooyr.io/websocket v1.8.17/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c= +pgregory.net/rapid v1.3.0 h1:vBvO0VSqti75J1jjYqpgPNBLKMd1+gxa9fYo7vk/Exc= +pgregory.net/rapid v1.3.0/go.mod h1:dPlE4OBBxgXPqkP79flB6sJL1dx5azpI7HQ9MY9Z7uk= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +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/speedtest/main.go b/tests/speedtest/main.go new file mode 100644 index 00000000..33be6374 --- /dev/null +++ b/tests/speedtest/main.go @@ -0,0 +1,7 @@ +package main + +func main() { + if err := NewSpeedTestCommand().Execute(); err != nil { + panic(err) + } +} diff --git a/tests/speedtest/speedtest.go b/tests/speedtest/speedtest.go new file mode 100644 index 00000000..16809b05 --- /dev/null +++ b/tests/speedtest/speedtest.go @@ -0,0 +1,240 @@ +package main + +import ( + "context" + "crypto/ecdsa" + "encoding/json" + "math/big" + "math/rand" + "os" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + types2 "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/spf13/cobra" + + dbm "github.com/cosmos/cosmos-db" + "github.com/cosmos/evm/crypto/ethsecp256k1" + "github.com/cosmos/evm/evmd" + erc20types "github.com/cosmos/evm/x/erc20/types" + feemarkettypes "github.com/cosmos/evm/x/feemarket/types" + evmtypes "github.com/cosmos/evm/x/vm/types" + + "cosmossdk.io/log/v2" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/codec" + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" + "github.com/cosmos/cosmos-sdk/tools/speedtest" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +var ( + r = rand.New(rand.NewSource(time.Now().UnixNano())) + ERC20PrecompileAddr = common.HexToAddress("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE") +) + +func NewSpeedTestCommand() *cobra.Command { + cmd := &cobra.Command{ + RunE: func(cmd *cobra.Command, args []string) error { + dir, err := os.MkdirTemp("", "speedtest-*") + if err != nil { + panic(err) + } + defer os.RemoveAll(dir) + logger := log.NewNopLogger() + db, err := dbm.NewDB("app", dbm.PebbleDBBackend, dir) + if err != nil { + panic(err) + } + + chainID := "9001" + baseAppOpts := make([]func(*baseapp.BaseApp), 0) + baseAppOpts = append(baseAppOpts, baseapp.SetChainID(chainID)) + evmApp := evmd.NewExampleApp(logger, db, true, simtestutil.NewAppOptionsWithFlagHome(dir), baseAppOpts...) + gen := generator{ + app: evmApp, + accounts: make([]accountInfo, 0), + } + speedTestCmd := speedtest.NewCmd( + gen.createAccount, + gen.generateTx, + evmApp, + evmApp.AppCodec(), + evmApp.DefaultGenesis(), + chainID, + DisableFeeMarket, + SetERC20Precompile(ERC20PrecompileAddr.String(), sdk.DefaultBondDenom), + BankMetadataSetter(sdk.DefaultBondDenom, 18), + ) + speedTestCmd.SetArgs(args) + return speedTestCmd.Execute() + }, + } + cmd.DisableFlagParsing = true + + return cmd +} + +type generator struct { + app *evmd.EVMD + accounts []accountInfo +} + +type accountInfo struct { + ecdsaKey *ecdsa.PrivateKey + address sdk.AccAddress + seqNum uint64 +} + +func (gen *generator) createAccount() (*types.BaseAccount, sdk.Coins) { + privKey, err := ethsecp256k1.GenerateKey() + if err != nil { + panic(err) + } + ecsdaKey, err := crypto.ToECDSA(privKey.Key) + if err != nil { + panic(err) + } + addr := sdk.AccAddress(privKey.PubKey().Address()) + accountNum := uint64(len(gen.accounts)) + baseAcc := types.NewBaseAccount(addr, privKey.PubKey(), accountNum+1, 0) + + gen.accounts = append(gen.accounts, accountInfo{ + ecdsaKey: ecsdaKey, + address: addr, + seqNum: 0, + }) + fundingAmount := sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 1_000_000_000_000_000_000)) + return baseAcc, fundingAmount +} + +func (gen *generator) generateTx() []byte { + // Select sender and recipient (ensure they're different) + senderIdx := r.Intn(len(gen.accounts)) + recipientIdx := (senderIdx + 1 + r.Intn(len(gen.accounts)-1)) % len(gen.accounts) + + sender := gen.accounts[senderIdx] + recipient := gen.accounts[recipientIdx] + + // Create MsgSend + ethTx := createMsgNativeERC20Transfer( + 10_000, + ERC20PrecompileAddr, + common.Address(sender.address.Bytes()), + common.Address(recipient.address.Bytes()), + sender.seqNum, + func(address common.Address, transaction *types2.Transaction) (*types2.Transaction, error) { + signer := types2.NewLondonSigner(big.NewInt(int64(evmtypes.DefaultEVMChainID))) + return types2.SignTx(transaction, signer, sender.ecdsaKey) + }) + msg := &evmtypes.MsgEthereumTx{} + msg.FromEthereumTx(ethTx) + msg.From = sender.address.Bytes() + builder := gen.app.TxConfig().NewTxBuilder() + tx, err := msg.BuildTx(builder, sdk.DefaultBondDenom) + if err != nil { + panic(err) + } + txEncoder := gen.app.TxConfig().TxEncoder() + + // Encode transaction + txBytes, err := txEncoder(tx) + if err != nil { + panic(err) + } + + gen.accounts[senderIdx].seqNum++ + + return txBytes +} + +func createMsgNativeERC20Transfer(sendAmt int64, precompileAddress common.Address, fromAddr common.Address, recipientAddr common.Address, nonce uint64, signerFn bind.SignerFn) *types2.Transaction { + // random amount. weth calls amounts wad for some reason. we continue that trend here. + wad := big.NewInt(int64(rand.Intn(int(sendAmt)))) + + // we use the weth transactor even though were interacting with the native precompile since they share the same interface, + // and the call data constructed here will be the same. + wethInstance, err := NewWethTransactor(precompileAddress, nil) + if err != nil { + panic(err) + } + txOpts := &bind.TransactOpts{ + From: fromAddr, + Signer: signerFn, + Nonce: big.NewInt(int64(nonce)), //nolint:gosec // G115: overflow unlikely in practice + GasTipCap: big.NewInt(25_000), + GasFeeCap: big.NewInt(25_000), + Context: context.Background(), + GasLimit: 250_000, + NoSend: true, + } + tx, err := wethInstance.Transfer(txOpts, recipientAddr, wad) + if err != nil { + panic(err) + } + return tx +} + +var ( + BankMetadataSetter = func(denom string, exp uint32) func(cdc codec.Codec, genesisState map[string]json.RawMessage) { + return func(cdc codec.Codec, genesisState map[string]json.RawMessage) { + bankGenesis := genesisState[banktypes.ModuleName] + var bankGen banktypes.GenesisState + if err := cdc.UnmarshalJSON(bankGenesis, &bankGen); err != nil { + panic(err) + } + bankGen.DenomMetadata = append(bankGen.DenomMetadata, banktypes.Metadata{ + Description: "some stuff", + DenomUnits: []*banktypes.DenomUnit{ + { + Denom: denom, + Exponent: exp, + Aliases: nil, + }, + }, + Base: denom, + Display: denom, + Name: denom, + Symbol: denom, + }) + bz := cdc.MustMarshalJSON(&bankGen) + genesisState[banktypes.ModuleName] = bz + } + } + + SetERC20Precompile = func(addr, denom string) func(cdc codec.Codec, genesisState map[string]json.RawMessage) { + return func(cdc codec.Codec, genesisState map[string]json.RawMessage) { + erc20Genesis := genesisState[erc20types.ModuleName] + var erc20Gen erc20types.GenesisState + if err := erc20Genesis.UnmarshalJSON(erc20Genesis); err != nil { + panic(err) + } + erc20Gen.NativePrecompiles = append(erc20Gen.NativePrecompiles, addr) + erc20Gen.TokenPairs = append(erc20Gen.TokenPairs, erc20types.TokenPair{ + Erc20Address: addr, + Denom: denom, + Enabled: true, + ContractOwner: 1, + }) + erc20Bz := cdc.MustMarshalJSON(&erc20Gen) + + genesisState[erc20types.ModuleName] = erc20Bz + } + } + + DisableFeeMarket = func(cdc codec.Codec, genesisState map[string]json.RawMessage) { + feeMarketGenesis := genesisState[feemarkettypes.ModuleName] + var feeMarketGen feemarkettypes.GenesisState + if err := feeMarketGenesis.UnmarshalJSON(feeMarketGenesis); err != nil { + panic(err) + } + feeMarketGen.Params.NoBaseFee = true + bz := cdc.MustMarshalJSON(&feeMarketGen) + genesisState[feemarkettypes.ModuleName] = bz + } +) diff --git a/tests/speedtest/weth.go b/tests/speedtest/weth.go new file mode 100644 index 00000000..ba16adb6 --- /dev/null +++ b/tests/speedtest/weth.go @@ -0,0 +1,1093 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package main + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// WethMetaData contains all meta data concerning the Weth contract. +var WethMetaData = &bind.MetaData{ + ABI: "[{\"type\":\"fallback\",\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"allowance\",\"inputs\":[{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"approve\",\"inputs\":[{\"name\":\"guy\",\"type\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"balanceOf\",\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"decimals\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"deposit\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"name\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"symbol\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"totalSupply\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transfer\",\"inputs\":[{\"name\":\"dst\",\"type\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferFrom\",\"inputs\":[{\"name\":\"src\",\"type\":\"address\"},{\"name\":\"dst\",\"type\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"withdraw\",\"inputs\":[{\"name\":\"wad\",\"type\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"Approval\",\"inputs\":[{\"name\":\"src\",\"type\":\"address\",\"indexed\":true},{\"name\":\"guy\",\"type\":\"address\",\"indexed\":true},{\"name\":\"wad\",\"type\":\"uint256\",\"indexed\":false}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Deposit\",\"inputs\":[{\"name\":\"dst\",\"type\":\"address\",\"indexed\":true},{\"name\":\"wad\",\"type\":\"uint256\",\"indexed\":false}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Transfer\",\"inputs\":[{\"name\":\"src\",\"type\":\"address\",\"indexed\":true},{\"name\":\"dst\",\"type\":\"address\",\"indexed\":true},{\"name\":\"wad\",\"type\":\"uint256\",\"indexed\":false}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Withdrawal\",\"inputs\":[{\"name\":\"src\",\"type\":\"address\",\"indexed\":true},{\"name\":\"wad\",\"type\":\"uint256\",\"indexed\":false}],\"anonymous\":false}]", + Bin: "0x60806040526040805190810160405280600d81526020017f57726170706564204574686572000000000000000000000000000000000000008152506000908051906020019061004f9291906100ca565b506040805190810160405280600481526020017f57455448000000000000000000000000000000000000000000000000000000008152506001908051906020019061009b9291906100ca565b506012600260006101000a81548160ff021916908360ff1602179055503480156100c457600080fd5b5061016f565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061010b57805160ff1916838001178555610139565b82800160010185558215610139579182015b8281111561013857825182559160200191906001019061011d565b5b509050610146919061014a565b5090565b61016c91905b80821115610168576000816000905550600101610150565b5090565b90565b610c5d8061017e6000396000f3006080604052600436106100925760003560e01c63ffffffff16806306fdde031461009c578063095ea7b31461012c57806318160ddd1461019157806323b872dd146101bc5780632e1a7d4d14610241578063313ce5671461026e57806370a082311461029f57806395d89b41146102f6578063a9059cbb14610386578063d0e30db0146103eb578063dd62ed3e146103f5575b61009a61046c565b005b3480156100a857600080fd5b506100b1610509565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f15780820151818401526020810190506100d6565b50505050905090810190601f16801561011e5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561013857600080fd5b50610177600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105a7565b604051808215151515815260200191505060405180910390f35b34801561019d57600080fd5b506101a6610699565b6040518082815260200191505060405180910390f35b3480156101c857600080fd5b50610227600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506106b8565b604051808215151515815260200191505060405180910390f35b34801561024d57600080fd5b5061026c600480360381019080803590602001909291905050506109fb565b005b34801561027a57600080fd5b50610283610b2e565b604051808260ff1660ff16815260200191505060405180910390f35b3480156102ab57600080fd5b506102e0600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b41565b6040518082815260200191505060405180910390f35b34801561030257600080fd5b5061030b610b59565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561034b578082015181840152602081019050610330565b50505050905090810190601f1680156103785780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561039257600080fd5b506103d1600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610bf7565b604051808215151515815260200191505060405180910390f35b6103f361046c565b005b34801561040157600080fd5b50610456600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610c0c565b6040518082815260200191505060405180910390f35b34600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055503373ffffffffffffffffffffffffffffffffffffffff167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c346040518082815260200191505060405180910390a2565b60008054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561059f5780601f106105745761010080835404028352916020019161059f565b820191906000526020600020905b81548152906001019060200180831161058257829003601f168201915b505050505081565b600081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60003073ffffffffffffffffffffffffffffffffffffffff1631905090565b600080600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490503373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16141580156107d557507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600460008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414155b156108f05782600460008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561086557600080fd5b82600460008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055505b82600360008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555082600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a360019150509392505050565b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610a4957600080fd5b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015610adc573d6000803e3d6000fd5b503373ffffffffffffffffffffffffffffffffffffffff167f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65826040518082815260200191505060405180910390a250565b600260009054906101000a900460ff1681565b60036020528060005260406000206000915090505481565b60018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610bef5780601f10610bc457610100808354040283529160200191610bef565b820191906000526020600020905b815481529060010190602001808311610bd257829003601f168201915b505050505081565b6000610c043384846106b8565b905092915050565b60046020528160005260406000206020528060005260406000206000915091505054815600a165627a7a723058205b4bac16cc6daa1eeaceb9dd59da953cda10289ef215459bfd5bdc611d01b0630029", +} + +// WethABI is the input ABI used to generate the binding from. +// Deprecated: Use WethMetaData.ABI instead. +var WethABI = WethMetaData.ABI + +// WethBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use WethMetaData.Bin instead. +var WethBin = WethMetaData.Bin + +// DeployWeth deploys a new Ethereum contract, binding an instance of Weth to it. +func DeployWeth(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Weth, error) { + parsed, err := WethMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(WethBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Weth{WethCaller: WethCaller{contract: contract}, WethTransactor: WethTransactor{contract: contract}, WethFilterer: WethFilterer{contract: contract}}, nil +} + +// Weth is an auto generated Go binding around an Ethereum contract. +type Weth struct { + WethCaller // Read-only binding to the contract + WethTransactor // Write-only binding to the contract + WethFilterer // Log filterer for contract events +} + +// WethCaller is an auto generated read-only Go binding around an Ethereum contract. +type WethCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// WethTransactor is an auto generated write-only Go binding around an Ethereum contract. +type WethTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// WethFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type WethFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// WethSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type WethSession struct { + Contract *Weth // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// WethCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type WethCallerSession struct { + Contract *WethCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// WethTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type WethTransactorSession struct { + Contract *WethTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// WethRaw is an auto generated low-level Go binding around an Ethereum contract. +type WethRaw struct { + Contract *Weth // Generic contract binding to access the raw methods on +} + +// WethCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type WethCallerRaw struct { + Contract *WethCaller // Generic read-only contract binding to access the raw methods on +} + +// WethTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type WethTransactorRaw struct { + Contract *WethTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewWeth creates a new instance of Weth, bound to a specific deployed contract. +func NewWeth(address common.Address, backend bind.ContractBackend) (*Weth, error) { + contract, err := bindWeth(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Weth{WethCaller: WethCaller{contract: contract}, WethTransactor: WethTransactor{contract: contract}, WethFilterer: WethFilterer{contract: contract}}, nil +} + +// NewWethCaller creates a new read-only instance of Weth, bound to a specific deployed contract. +func NewWethCaller(address common.Address, caller bind.ContractCaller) (*WethCaller, error) { + contract, err := bindWeth(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &WethCaller{contract: contract}, nil +} + +// NewWethTransactor creates a new write-only instance of Weth, bound to a specific deployed contract. +func NewWethTransactor(address common.Address, transactor bind.ContractTransactor) (*WethTransactor, error) { + contract, err := bindWeth(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &WethTransactor{contract: contract}, nil +} + +// NewWethFilterer creates a new log filterer instance of Weth, bound to a specific deployed contract. +func NewWethFilterer(address common.Address, filterer bind.ContractFilterer) (*WethFilterer, error) { + contract, err := bindWeth(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &WethFilterer{contract: contract}, nil +} + +// bindWeth binds a generic wrapper to an already deployed contract. +func bindWeth(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := WethMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Weth *WethRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Weth.Contract.WethCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Weth *WethRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Weth.Contract.WethTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Weth *WethRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Weth.Contract.WethTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Weth *WethCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Weth.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Weth *WethTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Weth.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Weth *WethTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Weth.Contract.contract.Transact(opts, method, params...) +} + +// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e. +// +// Solidity: function allowance(address , address ) view returns(uint256) +func (_Weth *WethCaller) Allowance(opts *bind.CallOpts, arg0 common.Address, arg1 common.Address) (*big.Int, error) { + var out []interface{} + err := _Weth.contract.Call(opts, &out, "allowance", arg0, arg1) + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err +} + +// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e. +// +// Solidity: function allowance(address , address ) view returns(uint256) +func (_Weth *WethSession) Allowance(arg0 common.Address, arg1 common.Address) (*big.Int, error) { + return _Weth.Contract.Allowance(&_Weth.CallOpts, arg0, arg1) +} + +// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e. +// +// Solidity: function allowance(address , address ) view returns(uint256) +func (_Weth *WethCallerSession) Allowance(arg0 common.Address, arg1 common.Address) (*big.Int, error) { + return _Weth.Contract.Allowance(&_Weth.CallOpts, arg0, arg1) +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address ) view returns(uint256) +func (_Weth *WethCaller) BalanceOf(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error) { + var out []interface{} + err := _Weth.contract.Call(opts, &out, "balanceOf", arg0) + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address ) view returns(uint256) +func (_Weth *WethSession) BalanceOf(arg0 common.Address) (*big.Int, error) { + return _Weth.Contract.BalanceOf(&_Weth.CallOpts, arg0) +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address ) view returns(uint256) +func (_Weth *WethCallerSession) BalanceOf(arg0 common.Address) (*big.Int, error) { + return _Weth.Contract.BalanceOf(&_Weth.CallOpts, arg0) +} + +// Decimals is a free data retrieval call binding the contract method 0x313ce567. +// +// Solidity: function decimals() view returns(uint8) +func (_Weth *WethCaller) Decimals(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _Weth.contract.Call(opts, &out, "decimals") + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err +} + +// Decimals is a free data retrieval call binding the contract method 0x313ce567. +// +// Solidity: function decimals() view returns(uint8) +func (_Weth *WethSession) Decimals() (uint8, error) { + return _Weth.Contract.Decimals(&_Weth.CallOpts) +} + +// Decimals is a free data retrieval call binding the contract method 0x313ce567. +// +// Solidity: function decimals() view returns(uint8) +func (_Weth *WethCallerSession) Decimals() (uint8, error) { + return _Weth.Contract.Decimals(&_Weth.CallOpts) +} + +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_Weth *WethCaller) Name(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _Weth.contract.Call(opts, &out, "name") + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err +} + +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_Weth *WethSession) Name() (string, error) { + return _Weth.Contract.Name(&_Weth.CallOpts) +} + +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_Weth *WethCallerSession) Name() (string, error) { + return _Weth.Contract.Name(&_Weth.CallOpts) +} + +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_Weth *WethCaller) Symbol(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _Weth.contract.Call(opts, &out, "symbol") + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err +} + +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_Weth *WethSession) Symbol() (string, error) { + return _Weth.Contract.Symbol(&_Weth.CallOpts) +} + +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_Weth *WethCallerSession) Symbol() (string, error) { + return _Weth.Contract.Symbol(&_Weth.CallOpts) +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_Weth *WethCaller) TotalSupply(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Weth.contract.Call(opts, &out, "totalSupply") + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_Weth *WethSession) TotalSupply() (*big.Int, error) { + return _Weth.Contract.TotalSupply(&_Weth.CallOpts) +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_Weth *WethCallerSession) TotalSupply() (*big.Int, error) { + return _Weth.Contract.TotalSupply(&_Weth.CallOpts) +} + +// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. +// +// Solidity: function approve(address guy, uint256 wad) returns(bool) +func (_Weth *WethTransactor) Approve(opts *bind.TransactOpts, guy common.Address, wad *big.Int) (*types.Transaction, error) { + return _Weth.contract.Transact(opts, "approve", guy, wad) +} + +// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. +// +// Solidity: function approve(address guy, uint256 wad) returns(bool) +func (_Weth *WethSession) Approve(guy common.Address, wad *big.Int) (*types.Transaction, error) { + return _Weth.Contract.Approve(&_Weth.TransactOpts, guy, wad) +} + +// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. +// +// Solidity: function approve(address guy, uint256 wad) returns(bool) +func (_Weth *WethTransactorSession) Approve(guy common.Address, wad *big.Int) (*types.Transaction, error) { + return _Weth.Contract.Approve(&_Weth.TransactOpts, guy, wad) +} + +// Deposit is a paid mutator transaction binding the contract method 0xd0e30db0. +// +// Solidity: function deposit() payable returns() +func (_Weth *WethTransactor) Deposit(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Weth.contract.Transact(opts, "deposit") +} + +// Deposit is a paid mutator transaction binding the contract method 0xd0e30db0. +// +// Solidity: function deposit() payable returns() +func (_Weth *WethSession) Deposit() (*types.Transaction, error) { + return _Weth.Contract.Deposit(&_Weth.TransactOpts) +} + +// Deposit is a paid mutator transaction binding the contract method 0xd0e30db0. +// +// Solidity: function deposit() payable returns() +func (_Weth *WethTransactorSession) Deposit() (*types.Transaction, error) { + return _Weth.Contract.Deposit(&_Weth.TransactOpts) +} + +// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb. +// +// Solidity: function transfer(address dst, uint256 wad) returns(bool) +func (_Weth *WethTransactor) Transfer(opts *bind.TransactOpts, dst common.Address, wad *big.Int) (*types.Transaction, error) { + return _Weth.contract.Transact(opts, "transfer", dst, wad) +} + +// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb. +// +// Solidity: function transfer(address dst, uint256 wad) returns(bool) +func (_Weth *WethSession) Transfer(dst common.Address, wad *big.Int) (*types.Transaction, error) { + return _Weth.Contract.Transfer(&_Weth.TransactOpts, dst, wad) +} + +// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb. +// +// Solidity: function transfer(address dst, uint256 wad) returns(bool) +func (_Weth *WethTransactorSession) Transfer(dst common.Address, wad *big.Int) (*types.Transaction, error) { + return _Weth.Contract.Transfer(&_Weth.TransactOpts, dst, wad) +} + +// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. +// +// Solidity: function transferFrom(address src, address dst, uint256 wad) returns(bool) +func (_Weth *WethTransactor) TransferFrom(opts *bind.TransactOpts, src common.Address, dst common.Address, wad *big.Int) (*types.Transaction, error) { + return _Weth.contract.Transact(opts, "transferFrom", src, dst, wad) +} + +// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. +// +// Solidity: function transferFrom(address src, address dst, uint256 wad) returns(bool) +func (_Weth *WethSession) TransferFrom(src common.Address, dst common.Address, wad *big.Int) (*types.Transaction, error) { + return _Weth.Contract.TransferFrom(&_Weth.TransactOpts, src, dst, wad) +} + +// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. +// +// Solidity: function transferFrom(address src, address dst, uint256 wad) returns(bool) +func (_Weth *WethTransactorSession) TransferFrom(src common.Address, dst common.Address, wad *big.Int) (*types.Transaction, error) { + return _Weth.Contract.TransferFrom(&_Weth.TransactOpts, src, dst, wad) +} + +// Withdraw is a paid mutator transaction binding the contract method 0x2e1a7d4d. +// +// Solidity: function withdraw(uint256 wad) returns() +func (_Weth *WethTransactor) Withdraw(opts *bind.TransactOpts, wad *big.Int) (*types.Transaction, error) { + return _Weth.contract.Transact(opts, "withdraw", wad) +} + +// Withdraw is a paid mutator transaction binding the contract method 0x2e1a7d4d. +// +// Solidity: function withdraw(uint256 wad) returns() +func (_Weth *WethSession) Withdraw(wad *big.Int) (*types.Transaction, error) { + return _Weth.Contract.Withdraw(&_Weth.TransactOpts, wad) +} + +// Withdraw is a paid mutator transaction binding the contract method 0x2e1a7d4d. +// +// Solidity: function withdraw(uint256 wad) returns() +func (_Weth *WethTransactorSession) Withdraw(wad *big.Int) (*types.Transaction, error) { + return _Weth.Contract.Withdraw(&_Weth.TransactOpts, wad) +} + +// Fallback is a paid mutator transaction binding the contract fallback function. +// +// Solidity: fallback() payable returns() +func (_Weth *WethTransactor) Fallback(opts *bind.TransactOpts, calldata []byte) (*types.Transaction, error) { + return _Weth.contract.RawTransact(opts, calldata) +} + +// Fallback is a paid mutator transaction binding the contract fallback function. +// +// Solidity: fallback() payable returns() +func (_Weth *WethSession) Fallback(calldata []byte) (*types.Transaction, error) { + return _Weth.Contract.Fallback(&_Weth.TransactOpts, calldata) +} + +// Fallback is a paid mutator transaction binding the contract fallback function. +// +// Solidity: fallback() payable returns() +func (_Weth *WethTransactorSession) Fallback(calldata []byte) (*types.Transaction, error) { + return _Weth.Contract.Fallback(&_Weth.TransactOpts, calldata) +} + +// WethApprovalIterator is returned from FilterApproval and is used to iterate over the raw logs and unpacked data for Approval events raised by the Weth contract. +type WethApprovalIterator struct { + Event *WethApproval // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *WethApprovalIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(WethApproval) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(WethApproval) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *WethApprovalIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *WethApprovalIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// WethApproval represents a Approval event raised by the Weth contract. +type WethApproval struct { + Src common.Address + Guy common.Address + Wad *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterApproval is a free log retrieval operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. +// +// Solidity: event Approval(address indexed src, address indexed guy, uint256 wad) +func (_Weth *WethFilterer) FilterApproval(opts *bind.FilterOpts, src []common.Address, guy []common.Address) (*WethApprovalIterator, error) { + var srcRule []interface{} + for _, srcItem := range src { + srcRule = append(srcRule, srcItem) + } + var guyRule []interface{} + for _, guyItem := range guy { + guyRule = append(guyRule, guyItem) + } + + logs, sub, err := _Weth.contract.FilterLogs(opts, "Approval", srcRule, guyRule) + if err != nil { + return nil, err + } + return &WethApprovalIterator{contract: _Weth.contract, event: "Approval", logs: logs, sub: sub}, nil +} + +// WatchApproval is a free log subscription operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. +// +// Solidity: event Approval(address indexed src, address indexed guy, uint256 wad) +func (_Weth *WethFilterer) WatchApproval(opts *bind.WatchOpts, sink chan<- *WethApproval, src []common.Address, guy []common.Address) (event.Subscription, error) { + var srcRule []interface{} + for _, srcItem := range src { + srcRule = append(srcRule, srcItem) + } + var guyRule []interface{} + for _, guyItem := range guy { + guyRule = append(guyRule, guyItem) + } + + logs, sub, err := _Weth.contract.WatchLogs(opts, "Approval", srcRule, guyRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(WethApproval) + if err := _Weth.contract.UnpackLog(event, "Approval", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseApproval is a log parse operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. +// +// Solidity: event Approval(address indexed src, address indexed guy, uint256 wad) +func (_Weth *WethFilterer) ParseApproval(log types.Log) (*WethApproval, error) { + event := new(WethApproval) + if err := _Weth.contract.UnpackLog(event, "Approval", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// WethDepositIterator is returned from FilterDeposit and is used to iterate over the raw logs and unpacked data for Deposit events raised by the Weth contract. +type WethDepositIterator struct { + Event *WethDeposit // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *WethDepositIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(WethDeposit) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(WethDeposit) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *WethDepositIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *WethDepositIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// WethDeposit represents a Deposit event raised by the Weth contract. +type WethDeposit struct { + Dst common.Address + Wad *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterDeposit is a free log retrieval operation binding the contract event 0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c. +// +// Solidity: event Deposit(address indexed dst, uint256 wad) +func (_Weth *WethFilterer) FilterDeposit(opts *bind.FilterOpts, dst []common.Address) (*WethDepositIterator, error) { + var dstRule []interface{} + for _, dstItem := range dst { + dstRule = append(dstRule, dstItem) + } + + logs, sub, err := _Weth.contract.FilterLogs(opts, "Deposit", dstRule) + if err != nil { + return nil, err + } + return &WethDepositIterator{contract: _Weth.contract, event: "Deposit", logs: logs, sub: sub}, nil +} + +// WatchDeposit is a free log subscription operation binding the contract event 0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c. +// +// Solidity: event Deposit(address indexed dst, uint256 wad) +func (_Weth *WethFilterer) WatchDeposit(opts *bind.WatchOpts, sink chan<- *WethDeposit, dst []common.Address) (event.Subscription, error) { + var dstRule []interface{} + for _, dstItem := range dst { + dstRule = append(dstRule, dstItem) + } + + logs, sub, err := _Weth.contract.WatchLogs(opts, "Deposit", dstRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(WethDeposit) + if err := _Weth.contract.UnpackLog(event, "Deposit", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseDeposit is a log parse operation binding the contract event 0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c. +// +// Solidity: event Deposit(address indexed dst, uint256 wad) +func (_Weth *WethFilterer) ParseDeposit(log types.Log) (*WethDeposit, error) { + event := new(WethDeposit) + if err := _Weth.contract.UnpackLog(event, "Deposit", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// WethTransferIterator is returned from FilterTransfer and is used to iterate over the raw logs and unpacked data for Transfer events raised by the Weth contract. +type WethTransferIterator struct { + Event *WethTransfer // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *WethTransferIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(WethTransfer) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(WethTransfer) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *WethTransferIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *WethTransferIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// WethTransfer represents a Transfer event raised by the Weth contract. +type WethTransfer struct { + Src common.Address + Dst common.Address + Wad *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterTransfer is a free log retrieval operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. +// +// Solidity: event Transfer(address indexed src, address indexed dst, uint256 wad) +func (_Weth *WethFilterer) FilterTransfer(opts *bind.FilterOpts, src []common.Address, dst []common.Address) (*WethTransferIterator, error) { + var srcRule []interface{} + for _, srcItem := range src { + srcRule = append(srcRule, srcItem) + } + var dstRule []interface{} + for _, dstItem := range dst { + dstRule = append(dstRule, dstItem) + } + + logs, sub, err := _Weth.contract.FilterLogs(opts, "Transfer", srcRule, dstRule) + if err != nil { + return nil, err + } + return &WethTransferIterator{contract: _Weth.contract, event: "Transfer", logs: logs, sub: sub}, nil +} + +// WatchTransfer is a free log subscription operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. +// +// Solidity: event Transfer(address indexed src, address indexed dst, uint256 wad) +func (_Weth *WethFilterer) WatchTransfer(opts *bind.WatchOpts, sink chan<- *WethTransfer, src []common.Address, dst []common.Address) (event.Subscription, error) { + var srcRule []interface{} + for _, srcItem := range src { + srcRule = append(srcRule, srcItem) + } + var dstRule []interface{} + for _, dstItem := range dst { + dstRule = append(dstRule, dstItem) + } + + logs, sub, err := _Weth.contract.WatchLogs(opts, "Transfer", srcRule, dstRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(WethTransfer) + if err := _Weth.contract.UnpackLog(event, "Transfer", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseTransfer is a log parse operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. +// +// Solidity: event Transfer(address indexed src, address indexed dst, uint256 wad) +func (_Weth *WethFilterer) ParseTransfer(log types.Log) (*WethTransfer, error) { + event := new(WethTransfer) + if err := _Weth.contract.UnpackLog(event, "Transfer", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// WethWithdrawalIterator is returned from FilterWithdrawal and is used to iterate over the raw logs and unpacked data for Withdrawal events raised by the Weth contract. +type WethWithdrawalIterator struct { + Event *WethWithdrawal // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *WethWithdrawalIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(WethWithdrawal) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(WethWithdrawal) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *WethWithdrawalIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *WethWithdrawalIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// WethWithdrawal represents a Withdrawal event raised by the Weth contract. +type WethWithdrawal struct { + Src common.Address + Wad *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterWithdrawal is a free log retrieval operation binding the contract event 0x7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65. +// +// Solidity: event Withdrawal(address indexed src, uint256 wad) +func (_Weth *WethFilterer) FilterWithdrawal(opts *bind.FilterOpts, src []common.Address) (*WethWithdrawalIterator, error) { + var srcRule []interface{} + for _, srcItem := range src { + srcRule = append(srcRule, srcItem) + } + + logs, sub, err := _Weth.contract.FilterLogs(opts, "Withdrawal", srcRule) + if err != nil { + return nil, err + } + return &WethWithdrawalIterator{contract: _Weth.contract, event: "Withdrawal", logs: logs, sub: sub}, nil +} + +// WatchWithdrawal is a free log subscription operation binding the contract event 0x7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65. +// +// Solidity: event Withdrawal(address indexed src, uint256 wad) +func (_Weth *WethFilterer) WatchWithdrawal(opts *bind.WatchOpts, sink chan<- *WethWithdrawal, src []common.Address) (event.Subscription, error) { + var srcRule []interface{} + for _, srcItem := range src { + srcRule = append(srcRule, srcItem) + } + + logs, sub, err := _Weth.contract.WatchLogs(opts, "Withdrawal", srcRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(WethWithdrawal) + if err := _Weth.contract.UnpackLog(event, "Withdrawal", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseWithdrawal is a log parse operation binding the contract event 0x7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65. +// +// Solidity: event Withdrawal(address indexed src, uint256 wad) +func (_Weth *WethFilterer) ParseWithdrawal(log types.Log) (*WethWithdrawal, error) { + event := new(WethWithdrawal) + if err := _Weth.contract.UnpackLog(event, "Withdrawal", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/tests/systemtests/Makefile b/tests/systemtests/Makefile index 05b3d2e4..167fae5e 100644 --- a/tests/systemtests/Makefile +++ b/tests/systemtests/Makefile @@ -3,10 +3,4 @@ WAIT_TIME ?= 20s test: - go test -failfast -timeout=30m -p=1 -mod=readonly -tags='system_test' -v ./... -run TestCosmosTxCompat --wait-time=$(WAIT_TIME) --block-time=9.5s --binary evmd --chain-id local-4221 - go test -failfast -timeout=30m -p=1 -mod=readonly -tags='system_test' -v ./... -run TestTxsReplacement --wait-time=$(WAIT_TIME) --block-time=9.5s --binary evmd --chain-id local-4221 - go test -failfast -timeout=30m -p=1 -mod=readonly -tags='system_test' -v ./... -run TestTxsOrdering --wait-time=$(WAIT_TIME) --block-time=3s --binary evmd --chain-id local-4221 - go test -failfast -timeout=30m -p=1 -mod=readonly -tags='system_test' -v ./... -run TestExceptions --wait-time=$(WAIT_TIME) --block-time=8s --binary evmd --chain-id local-4221 - go test -failfast -timeout=30m -p=1 -mod=readonly -tags='system_test' -v ./... -run TestEIP7702 --wait-time=$(WAIT_TIME) --block-time=5s --binary evmd --chain-id local-4221 - go test -failfast -timeout=30m -p=1 -mod=readonly -tags='system_test' -v ./... -run TestEIP712 --wait-time=$(WAIT_TIME) --block-time=5s --binary evmd --chain-id local-4221 - go test -failfast -timeout=30m -p=1 -mod=readonly -tags='system_test' -v ./... -run 'TestUpgrade|TestEth' --wait-time=$(WAIT_TIME) --block-time=5s --binary evmd --chain-id local-4221 + go test -failfast -timeout=30m -mod=readonly -tags='system_test' -v ./... --wait-time=$(WAIT_TIME) --binary evmd --chain-id local-4221 diff --git a/tests/systemtests/README.md b/tests/systemtests/README.md index 9e99b09e..cc44bb20 100644 --- a/tests/systemtests/README.md +++ b/tests/systemtests/README.md @@ -23,33 +23,46 @@ cp ./build/evmd ./tests/systemtests/binaries/v0.4 ## Run Individual test -### Run test cases for txs ordering +Each scenario now has its own `Test…` wrapper in `main_test.go`, so you can target a specific flow directly. For example, to exercise the mempool ordering suite: ```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 +cd tests/systemtests +go test -failfast -mod=readonly -tags=system_test ./... -run TestMempoolTxsOrdering \ + --verbose --binary evmd --block-time 3s --chain-id local-4221 ``` -### Run test cases for txs replacement +Mempool scenarios: -```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 -``` +| Test name | Description | +|-----------|-------------| +| `TestMempoolTxsOrdering` | Ordering of pending transactions across nodes | +| `TestMempoolTxsReplacement` | Replacement behaviour for EVM transactions | +| `TestMempoolTxsReplacementWithCosmosTx` | Replacement when Cosmos transactions are present | +| `TestMempoolMixedTxsReplacementEVMAndCosmos` | Mixed Cosmos/EVM replacement coverage | +| `TestMempoolTxRebroadcasting` | Rebroadcasting and nonce-gap handling | +| `TestMempoolCosmosTxsCompatibility` | Cosmos-only transactions interacting with the mempool | -### Run test exceptions +EIP-712 scenarios: -```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 -``` +| Test name | Description | +|-----------|-------------| +| `TestEIP712BankSend` | Single transfer signed via EIP-712 | +| `TestEIP712BankSendWithBalanceCheck` | Transfer plus balance assertions | +| `TestEIP712MultipleBankSends` | Sequential transfers with nonce management | -### Run EIP-7702 test +Account abstraction: -```shell -go test -p 1 -mod=readonly -tags='system_test' -v ./... \ ---run TestEIP7702 --verbose --binary evmd --block-time 3s --chain-id local-4221 -``` +| Test name | Description | +|-----------|-------------| +| `TestAccountAbstractionEIP7702` | Account abstraction (EIP-7702) flow | + +Chain lifecycle: + +| Test name | Description | +|-----------|-------------| +| `TestChainUpgrade` | End-to-end upgrade handling | + +> ℹ️ The shared system test suite keeps a single chain alive across multiple tests when the node arguments are identical. Running several tests back-to-back therefore re-uses the same process unless a scenario explicitly changes the node configuration. ## Run all tests diff --git a/tests/systemtests/accountabstraction/interface.go b/tests/systemtests/accountabstraction/interface.go deleted file mode 100644 index 5314215c..00000000 --- a/tests/systemtests/accountabstraction/interface.go +++ /dev/null @@ -1,31 +0,0 @@ -package accountabstraction - -import ( - "crypto/ecdsa" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - ethtypes "github.com/ethereum/go-ethereum/core/types" -) - -type AccountAbstractionTestSuite interface { - // Lifecycle - SetupTest(t *testing.T) - WaitForCommit(txHash common.Hash) - - // Query helpers - GetChainID() uint64 - GetNonce(accID string) uint64 - GetPrivKey(accID string) *ecdsa.PrivateKey - GetAddr(accID string) common.Address - GetCounterAddr() common.Address - - // Transactions - SendSetCodeTx(accID string, signedAuth ...ethtypes.SetCodeAuthorization) (common.Hash, error) - InvokeCounter(accID string, method string, args ...interface{}) (common.Hash, error) - - // Verification - CheckSetCode(authorityAccID string, delegate common.Address, expectDelegation bool) - QueryCounterNumber(accID string) (*big.Int, error) -} diff --git a/tests/systemtests/accountabstraction/test_eip7702.go b/tests/systemtests/accountabstraction/test_eip7702.go index 5b39d7a6..fb3c1e1b 100644 --- a/tests/systemtests/accountabstraction/test_eip7702.go +++ b/tests/systemtests/accountabstraction/test_eip7702.go @@ -1,3 +1,5 @@ +//go:build system_test + package accountabstraction import ( @@ -10,23 +12,29 @@ import ( . "github.com/onsi/ginkgo/v2" //nolint:revive // dot imports are fine for Ginkgo . "github.com/onsi/gomega" -) -func TestEIP7702(t *testing.T) { - const ( - user0 = "acc0" - user1 = "acc1" - ) + suite "github.com/cosmos/evm/tests/systemtests/suite" +) +func RunEIP7702(t *testing.T, base *suite.BaseTestSuite) { Describe("test EIP-7702 scenorios", Ordered, func() { var ( - s AccountAbstractionTestSuite + s *TestSuite + user0Acc *suite.TestAccount + user1Acc *suite.TestAccount + user0 string + user1 string ) // We intentionally use BeforeAll instead of BeforeAll because, // The test takes too much time if we restart network for each test case. BeforeAll(func() { - s = NewTestSuite(t) + s = NewTestSuite(base) + user0Acc = s.BaseTestSuite.Acc(0) + user1Acc = s.BaseTestSuite.Acc(1) + user0 = user0Acc.ID + user1 = user1Acc.ID + s.SetPrimaryAccount(user0Acc) s.SetupTest(t) }) @@ -59,20 +67,20 @@ func TestEIP7702(t *testing.T) { authChainID func() uint64 authNonce func() uint64 authAddress func() common.Address - authSigner string - txSender string + authSigner func() string + txSender func() string expDelegation bool } DescribeTable("SetCode authorization scenarios", func(tc testCase) { authorization := createSetCodeAuthorization(tc.authChainID(), tc.authNonce(), tc.authAddress()) - signedAuthorization, err := signSetCodeAuthorization(s.GetPrivKey(tc.authSigner), authorization) + signedAuthorization, err := signSetCodeAuthorization(s.GetPrivKey(tc.authSigner()), authorization) Expect(err).To(BeNil()) - txHash, err := s.SendSetCodeTx(tc.txSender, signedAuthorization) + txHash, err := s.SendSetCodeTx(tc.txSender(), signedAuthorization) Expect(err).To(BeNil(), "error while sending SetCode tx") s.WaitForCommit(txHash) - s.CheckSetCode(tc.authSigner, tc.authAddress(), tc.expDelegation) + s.CheckSetCode(tc.authSigner(), tc.authAddress(), tc.expDelegation) }, Entry("setCode with invalid chainID should fail", testCase{ authChainID: func() uint64 { return s.GetChainID() + 1 }, @@ -82,8 +90,8 @@ func TestEIP7702(t *testing.T) { authAddress: func() common.Address { return s.GetCounterAddr() }, - authSigner: user0, - txSender: user0, + authSigner: func() string { return user0 }, + txSender: func() string { return user0 }, expDelegation: false, }), Entry("setCode with empty address should reset delegation", testCase{ @@ -94,8 +102,8 @@ func TestEIP7702(t *testing.T) { authAddress: func() common.Address { return common.HexToAddress("0x0") }, - authSigner: user0, - txSender: user0, + authSigner: func() string { return user0 }, + txSender: func() string { return user0 }, expDelegation: false, }), Entry("setCode with invalid address should fail", testCase{ @@ -106,8 +114,8 @@ func TestEIP7702(t *testing.T) { authAddress: func() common.Address { return common.BytesToAddress([]byte("invalid")) }, - authSigner: user0, - txSender: user0, + authSigner: func() string { return user0 }, + txSender: func() string { return user0 }, expDelegation: true, }), Entry("setCode with EoA address should fail", testCase{ @@ -118,8 +126,8 @@ func TestEIP7702(t *testing.T) { authAddress: func() common.Address { return s.GetAddr(user1) }, - authSigner: user0, - txSender: user0, + authSigner: func() string { return user0 }, + txSender: func() string { return user0 }, expDelegation: true, }), Entry("same signer/sender with matching nonce should fail", testCase{ @@ -130,8 +138,8 @@ func TestEIP7702(t *testing.T) { authAddress: func() common.Address { return s.GetCounterAddr() }, - authSigner: user0, - txSender: user0, + authSigner: func() string { return user0 }, + txSender: func() string { return user0 }, expDelegation: false, }), Entry("same signer/sender with future nonce sholud succeed", testCase{ @@ -142,8 +150,8 @@ func TestEIP7702(t *testing.T) { authAddress: func() common.Address { return s.GetCounterAddr() }, - authSigner: user0, - txSender: user0, + authSigner: func() string { return user0 }, + txSender: func() string { return user0 }, expDelegation: true, }), Entry("different signer/sender with current nonce should succeed", testCase{ @@ -154,8 +162,8 @@ func TestEIP7702(t *testing.T) { authAddress: func() common.Address { return s.GetCounterAddr() }, - authSigner: user1, - txSender: user0, + authSigner: func() string { return user1 }, + txSender: func() string { return user0 }, expDelegation: true, }), Entry("different signer/sender with future nonce should fail", testCase{ @@ -166,8 +174,8 @@ func TestEIP7702(t *testing.T) { authAddress: func() common.Address { return s.GetCounterAddr() }, - authSigner: user1, - txSender: user0, + authSigner: func() string { return user1 }, + txSender: func() string { return user0 }, expDelegation: false, }), ) diff --git a/tests/systemtests/accountabstraction/test_eip7702_same_block.go b/tests/systemtests/accountabstraction/test_eip7702_same_block.go new file mode 100644 index 00000000..541c6c35 --- /dev/null +++ b/tests/systemtests/accountabstraction/test_eip7702_same_block.go @@ -0,0 +1,209 @@ +//go:build system_test + +package accountabstraction + +import ( + "context" + "math/big" + "strings" + "testing" + "time" + + sdkmath "cosmossdk.io/math" + + "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/holiman/uint256" + + "github.com/onsi/gomega" + "github.com/stretchr/testify/require" + + suite "github.com/cosmos/evm/tests/systemtests/suite" +) + +// RunEIP7702SameBlock tests an EIP-7702 SetCode tx (relayer-sent, user as +// authority at nonce N) and a user-signed Cosmos bank send at sequence N +// landing in the same block. Both block-internal orderings are exercised: +// +// - SetCode-first: delegation installed; bank included-as-failed. +// - Bank-first: bank commits; SetCode's auth silently skipped; no delegation. +func RunEIP7702SameBlock(t *testing.T, base *suite.BaseTestSuite) { + gomega.RegisterTestingT(t) + + s := NewTestSuite(base) + s.SetupTestWithTimeoutCommit(t, 8*time.Second) + + relayer := s.BaseTestSuite.Acc(0) + user := s.BaseTestSuite.Acc(1) + s.SetPrimaryAccount(relayer) + relayerID := relayer.ID + userID := user.ID + + fee, err := s.GetLatestBaseFee("node0") + require.NoError(t, err) + s.SetBaseFee(fee) + + cleanupDelegation := func(t *testing.T) { + ctx := context.Background() + code, err := s.EthClient.Clients["node0"].CodeAt(ctx, s.GetAddr(userID), nil) + require.NoError(t, err) + if len(code) == 0 { + return + } + auth := createSetCodeAuthorization(s.GetChainID(), s.GetNonce(userID)+1, common.Address{}) + signed, err := signSetCodeAuthorization(s.GetPrivKey(userID), auth) + require.NoError(t, err) + txHash, err := s.SendSetCodeTx(userID, signed) + require.NoError(t, err, "cleanup SetCode failed") + s.WaitForCommit(txHash) + } + + // SetCode-first: bias the SetCode tx's tip so the proposer iterator + // emits it before the bank tx inside the same block. + t.Run("SetCode-first execution: delegation installed, bank included-as-failed", func(t *testing.T) { + t.Cleanup(func() { cleanupDelegation(t) }) + + counterAddr := s.GetCounterAddr() + baseFee := s.GasPriceMultiplier(1) + setCodeTip := uint256.MustFromBig(new(big.Int).Mul(baseFee, big.NewInt(100))) + setCodeFeeCap := new(uint256.Int).Mul(setCodeTip, uint256.NewInt(2)) + bankPrice := new(big.Int).Mul(baseFee, big.NewInt(2)) + + receipt, bankRes := submitSameBlock(t, s, relayerID, userID, counterAddr, setCodeTip, setCodeFeeCap, bankPrice) + + require.Equal(t, uint64(1), receipt.Status, "outer SetCode tx must be accepted") + + ctx := context.Background() + code, err := s.EthClient.Clients["node0"].CodeAt(ctx, s.GetAddr(userID), nil) + require.NoError(t, err) + require.Equal(t, 23, len(code), "delegation must be installed; got code length %d", len(code)) + resolved, ok := ethtypes.ParseDelegation(code) + require.True(t, ok) + require.Equal(t, counterAddr, resolved) + + require.NotZero(t, bankRes.code, + "bank must be included-as-failed; got code=%d log=%q", bankRes.code, bankRes.log) + require.True(t, + strings.Contains(strings.ToLower(bankRes.log), "sequence") || + strings.Contains(strings.ToLower(bankRes.log), "nonce"), + "expected sequence/nonce error in bank log, got: %s", bankRes.log) + + t.Logf("SetCode-first: block=%d delegation=installed bankCode=%d log=%q", + receipt.BlockNumber.Uint64(), bankRes.code, bankRes.log) + }) + + // Bank-first: bias the bank tx's tip so the proposer iterator emits + // it before the SetCode tx inside the same block. + t.Run("Bank-first execution: bank commits, auth silently skipped, no delegation", func(t *testing.T) { + t.Cleanup(func() { cleanupDelegation(t) }) + + counterAddr := s.GetCounterAddr() + baseFee := s.GasPriceMultiplier(1) + setCodeTip := uint256.MustFromBig(new(big.Int).Mul(baseFee, big.NewInt(1))) + // 10× base fee absorbs any drift between GetLatestBaseFee and inclusion + // so the SetCode tx still passes its fee cap check when the iterator + // emits it after the bank tx. + setCodeFeeCap := uint256.MustFromBig(new(big.Int).Mul(baseFee, big.NewInt(10))) + bankPrice := new(big.Int).Mul(baseFee, big.NewInt(100)) + + receipt, bankRes := submitSameBlock(t, s, relayerID, userID, counterAddr, setCodeTip, setCodeFeeCap, bankPrice) + + require.Equal(t, uint64(1), receipt.Status, "outer SetCode tx must be accepted") + + ctx := context.Background() + code, err := s.EthClient.Clients["node0"].CodeAt(ctx, s.GetAddr(userID), nil) + require.NoError(t, err) + require.Equal(t, 0, len(code), "no delegation should be installed when auth was silently skipped") + + require.Zero(t, bankRes.code, + "bank must commit normally; got code=%d log=%q", bankRes.code, bankRes.log) + + t.Logf("Bank-first: block=%d delegation=absent bankCode=%d", receipt.BlockNumber.Uint64(), bankRes.code) + }) +} + +type bankCommitResult struct { + height int64 + code uint32 + log string +} + +// submitSameBlock submits a relayer-sent SetCode tx (user as authority at the +// user's current nonce N), waits for it to reach every validator's legacypool +// pending list, then submits a user-signed bank tx at the same sequence N. +// Asserts both land in the same block. +func submitSameBlock( + t *testing.T, + s *TestSuite, + relayerID, userID string, + counterAddr common.Address, + setCodeTip, setCodeFeeCap *uint256.Int, + bankPrice *big.Int, +) (*ethtypes.Receipt, bankCommitResult) { + t.Helper() + + contested := s.GetNonce(userID) + + auth := createSetCodeAuthorization(s.GetChainID(), contested, counterAddr) + signedAuth, err := signSetCodeAuthorization(s.GetPrivKey(userID), auth) + require.NoError(t, err) + + s.AwaitNBlocks(t, 1) + + setCodeHash, err := s.SendSetCodeTxWithFees(relayerID, setCodeTip, setCodeFeeCap, signedAuth) + require.NoError(t, err, "failed to broadcast SetCode tx") + + // Wait for SetCode to be in pending on every validator before submitting bank. + require.Eventually(t, func() bool { + for i := 0; i < 4; i++ { + pending, _, err := s.TxPoolContent(s.Node(i), suite.TxTypeEVM, 5*time.Second) + if err != nil { + return false + } + found := false + for _, h := range pending { + if h == setCodeHash.Hex() { + found = true + break + } + } + if !found { + return false + } + } + return true + }, 30*time.Second, 500*time.Millisecond, + "SetCode tx failed to gossip into every validator's legacypool pending") + + // Bank at the same sequence as the auth. + userCosmosAcc := s.CosmosAccount(userID) + toAcc := s.CosmosAccount(s.AccID(2)) + bankResp, err := s.CosmosClient.BankSend( + "node0", + userCosmosAcc, + userCosmosAcc.AccAddress, + toAcc.AccAddress, + sdkmath.NewInt(1000), + contested, + bankPrice, + ) + require.NoError(t, err, "BankSend RPC call should not error") + require.NotNil(t, bankResp) + require.Zero(t, bankResp.Code, + "bank CheckTx must accept; got code=%d raw_log=%q", bankResp.Code, bankResp.RawLog) + + receipt, err := s.EthClient.WaitForCommit("node0", setCodeHash.Hex(), 60*time.Second) + require.NoError(t, err, "SetCode never committed") + bankRes, err := s.CosmosClient.WaitForCommit("node0", bankResp.TxHash, 60*time.Second) + require.NoError(t, err, "bank never committed") + + require.Equal(t, int64(receipt.BlockNumber.Uint64()), bankRes.Height, + "SetCode and bank must land in the same block; got SetCode=%d bank=%d", + receipt.BlockNumber.Uint64(), bankRes.Height) + + return receipt, bankCommitResult{ + height: bankRes.Height, + code: bankRes.TxResult.Code, + log: bankRes.TxResult.Log, + } +} diff --git a/tests/systemtests/accountabstraction/test_suite.go b/tests/systemtests/accountabstraction/test_suite.go index 18523124..0e39c9e4 100644 --- a/tests/systemtests/accountabstraction/test_suite.go +++ b/tests/systemtests/accountabstraction/test_suite.go @@ -1,3 +1,5 @@ +//go:build system_test + package accountabstraction import ( @@ -18,32 +20,56 @@ import ( //nolint:revive // dot imports are fine for Ginkgo . "github.com/onsi/gomega" - basesuite "github.com/cosmos/evm/tests/systemtests/suite" + suite "github.com/cosmos/evm/tests/systemtests/suite" "github.com/stretchr/testify/require" ) type TestSuite struct { - *basesuite.SystemTestSuite + *suite.BaseTestSuite - counterAddress common.Address - counterABI abi.ABI + counterAddress common.Address + counterABI abi.ABI + primaryAccountID string } -func NewTestSuite(t *testing.T) *TestSuite { +func NewTestSuite(base *suite.BaseTestSuite) *TestSuite { return &TestSuite{ - SystemTestSuite: basesuite.NewSystemTestSuite(t), + BaseTestSuite: base, } } +// SetPrimaryAccount configures the account that will be used for contract deployment/setup. +func (s *TestSuite) SetPrimaryAccount(acc *suite.TestAccount) { + if acc == nil { + return + } + s.primaryAccountID = acc.ID +} + // SetupTest setup test suite and deploy test contracts func (s *TestSuite) SetupTest(t *testing.T) { - s.SystemTestSuite.SetupTest(t) + s.setupWithOpts(t) +} + +// SetupTestWithTimeoutCommit is like SetupTest but configures the chain with the +// supplied timeout_commit so the caller can widen the window for racing two txs +// into the same block. +func (s *TestSuite) SetupTestWithTimeoutCommit(t *testing.T, tc time.Duration) { + s.setupWithOpts(t, suite.WithTimeoutCommit(tc)) +} + +func (s *TestSuite) setupWithOpts(t *testing.T, opts ...suite.TestSetupConfigOption) { + s.BaseTestSuite.SetupTest(t, opts...) + + if s.primaryAccountID == "" { + s.primaryAccountID = s.AccID(0) + } counterPath := filepath.Join("..", "Counter", "out", "Counter.sol", "Counter.json") bytecode, err := loadContractCreationBytecode(counterPath) Expect(err).To(BeNil(), "failed to load counter creation bytecode") - addr, err := deployContract(s.EthClient, bytecode) + addr, err := deployContract(s.EthClient, s.EthAccount(s.primaryAccountID), bytecode) require.NoError(t, err, "failed to deploy counter contract") s.counterAddress = addr @@ -72,7 +98,7 @@ func (s *TestSuite) GetNonce(accID string) uint64 { // GetSequence returns the Cosmos account sequence for the given account ID. func (s *TestSuite) GetSequence(accID string) uint64 { - cosmosAcc := s.CosmosClient.Accs[accID] + cosmosAcc := s.CosmosAccount(accID) ctx := s.CosmosClient.ClientCtx.WithClient(s.CosmosClient.RpcClients["node0"]) account, err := ctx.AccountRetriever.GetAccount(ctx, cosmosAcc.AccAddress) Expect(err).To(BeNil(), "unable to retrieve cosmos account for %s", accID) @@ -81,12 +107,12 @@ func (s *TestSuite) GetSequence(accID string) uint64 { // GetPrivKey returns ecdsa private key of account func (s *TestSuite) GetPrivKey(accID string) *ecdsa.PrivateKey { - return s.EthClient.Accs[accID].PrivKey + return s.EthAccount(accID).PrivKey } // GetAddr returns ethereum address of account func (s *TestSuite) GetAddr(accID string) common.Address { - return s.EthClient.Accs[accID].Address + return s.EthAccount(accID).Address } // GetCounterAddr returns the deployed counter contract address. @@ -94,11 +120,17 @@ func (s *TestSuite) GetCounterAddr() common.Address { return s.counterAddress } -// SendSetCodeTx sends SetCodeTx +// SendSetCodeTx sends SetCodeTx with default fees. func (s *TestSuite) SendSetCodeTx(accID string, signedAuths ...ethtypes.SetCodeAuthorization) (common.Hash, error) { + return s.SendSetCodeTxWithFees(accID, uint256.NewInt(1_000_000), uint256.NewInt(1_000_000_000), signedAuths...) +} + +// SendSetCodeTxWithFees sends a SetCodeTx with explicit fee caps so callers can +// bias proposer ordering against competing txs. +func (s *TestSuite) SendSetCodeTxWithFees(accID string, gasTipCap, gasFeeCap *uint256.Int, signedAuths ...ethtypes.SetCodeAuthorization) (common.Hash, error) { ctx := context.Background() ethCli := s.EthClient.Clients["node0"] - acc := s.EthClient.Accs[accID] + acc := s.EthAccount(accID) if acc == nil { return common.Hash{}, fmt.Errorf("account %s not found", accID) } @@ -118,8 +150,8 @@ func (s *TestSuite) SendSetCodeTx(accID string, signedAuths ...ethtypes.SetCodeA txdata := ðtypes.SetCodeTx{ ChainID: uint256.MustFromBig(chainID), Nonce: nonce, - GasTipCap: uint256.NewInt(1_000_000), - GasFeeCap: uint256.NewInt(1_000_000_000), + GasTipCap: gasTipCap, + GasFeeCap: gasFeeCap, Gas: 100_000, To: common.Address{}, Value: uint256.NewInt(0), @@ -140,7 +172,7 @@ func (s *TestSuite) SendSetCodeTx(accID string, signedAuths ...ethtypes.SetCodeA // CheckSetCode checks the account is EIP-7702 SetCode authorized. func (s *TestSuite) CheckSetCode(authorityAccID string, delegate common.Address, expectDelegation bool) { - account := s.EthClient.Accs[authorityAccID] + account := s.EthAccount(authorityAccID) Expect(account).ToNot(BeNil(), "account %s not found", authorityAccID) ctx := context.Background() @@ -163,7 +195,7 @@ func (s *TestSuite) CheckSetCode(authorityAccID string, delegate common.Address, // InvokeCounter sends a transaction from the delegated account to execute a counter method. func (s *TestSuite) InvokeCounter(accID string, method string, args ...interface{}) (common.Hash, error) { - account := s.EthClient.Accs[accID] + account := s.EthAccount(accID) if account == nil { return common.Hash{}, fmt.Errorf("account %s not found", accID) } @@ -224,7 +256,7 @@ func (s *TestSuite) InvokeCounter(accID string, method string, args ...interface // QueryCounterNumber queries the delegated counter contract via the account code. func (s *TestSuite) QueryCounterNumber(accID string) (*big.Int, error) { - account := s.EthClient.Accs[accID] + account := s.EthAccount(accID) if account == nil { return nil, fmt.Errorf("account %s not found", accID) } diff --git a/tests/systemtests/accountabstraction/test_utils.go b/tests/systemtests/accountabstraction/test_utils.go index da1f007d..fca8f2ac 100644 --- a/tests/systemtests/accountabstraction/test_utils.go +++ b/tests/systemtests/accountabstraction/test_utils.go @@ -1,3 +1,5 @@ +//go:build system_test + package accountabstraction import ( @@ -96,12 +98,11 @@ func loadContractABI(filePath string) (abi.ABI, error) { return parsedABI, nil } -func deployContract(ethClient *clients.EthClient, creationBytecode []byte) (common.Address, error) { +func deployContract(ethClient *clients.EthClient, deployer *clients.EthAccount, creationBytecode []byte) (common.Address, error) { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() ethCli := ethClient.Clients["node0"] - deployer := ethClient.Accs["acc0"] chainID, err := ethCli.ChainID(ctx) if err != nil { diff --git a/tests/systemtests/accountabstraction/types.go b/tests/systemtests/accountabstraction/types.go index d80e9886..be19e50e 100644 --- a/tests/systemtests/accountabstraction/types.go +++ b/tests/systemtests/accountabstraction/types.go @@ -1,10 +1,13 @@ +//go:build system_test + package accountabstraction import ( "fmt" - "github.com/cosmos/evm/tests/systemtests/clients" "math/big" + "github.com/cosmos/evm/tests/systemtests/clients" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" diff --git a/tests/systemtests/chainupgrade/v6_v7.go b/tests/systemtests/chainupgrade/v6_v7.go new file mode 100644 index 00000000..80b10363 --- /dev/null +++ b/tests/systemtests/chainupgrade/v6_v7.go @@ -0,0 +1,205 @@ +//go:build system_test + +package chainupgrade + +import ( + "context" + "fmt" + "math/big" + "sync" + "testing" + "time" + + "github.com/stretchr/testify/require" + "github.com/tidwall/gjson" + + "github.com/cosmos/evm/tests/systemtests/suite" + + systest "github.com/cosmos/cosmos-sdk/tools/systemtests" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" +) + +const ( + upgradeHeight int64 = 22 + upgradeName = "v0.6.0-to-v0.7.0" // must match UpgradeName in evmd/upgrades.go + + // Contended-account workload — multiple senders, single recipient. + // SendEthLegacyTx hard-codes the recipient to acc3 and the value to 1000 wei, + // so any change to that helper means changing these constants too. + contendedSenders = 3 // acc0, acc1, acc2 + contendedTxsPerEOA = 4 + contendedRecipient = "acc3" + contendedTxValue = int64(1000) +) + +// RunChainUpgrade exercises an on-chain software upgrade using the injected shared suite. +func RunChainUpgrade(t *testing.T, base *suite.BaseTestSuite) { + t.Helper() + + base.SetupTest(t) + sut := base.SystemUnderTest + + // Scenario: + // start a legacy chain with some state + // when a chain upgrade proposal is executed + // then the chain upgrades successfully + sut.StopChain() + + currentBranchBinary := sut.ExecBinary() + currentInitializer := sut.TestnetInitializer() + + legacyBinary := systest.WorkDir + "/binaries/v0.6/evmd" + systest.Sut.SetExecBinary(legacyBinary) + systest.Sut.SetTestnetInitializer(systest.InitializerWithBinary(legacyBinary, systest.Sut)) + systest.Sut.SetupChain() + + votingPeriod := 5 * time.Second // enough time to vote + sut.ModifyGenesisJSON(t, systest.SetGovVotingPeriod(t, votingPeriod)) + + sut.StartChain(t, fmt.Sprintf("--halt-height=%d", upgradeHeight+1), "--chain-id=local-4221", "--minimum-gas-prices=0.00atest") + + cli := systest.NewCLIWrapper(t, 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 sut.NodesCount() { + go func(i int) { // do parallel + 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) + } + + sut.AwaitBlockHeight(t, upgradeHeight-1, 60*time.Second) + t.Logf("current_height: %d\n", 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") + sut.AwaitUpgradeInfo(t) + sut.StopChain() + + t.Log("Upgrade height was reached. Upgrading chain") + sut.SetExecBinary(currentBranchBinary) + sut.SetTestnetInitializer(currentInitializer) + // Keep Comet and app mempool settings in sync for the upgraded binary startup. + base.ModifyCometMempool(t, "app") + // Use the shared default args (pins EVM chain ID to 4221 so the eth client + // can sign valid txs — v0.7's default EVM chain ID differs from v0.6 — and + // enables the JSON-RPC namespaces the contended-account workload needs). + sut.StartChain(t, suite.DefaultNodeArgs()...) + + require.Equal(t, upgradeHeight+1, sut.CurrentHeight()) + + // smoke test to make sure the chain still functions. + cli = systest.NewCLIWrapper(t, 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) + + runContendedAccountWorkload(t, base) +} + +// runContendedAccountWorkload exercises BlockSTM's conflict detection across +// the upgrade boundary. Multiple senders fire EVM txs concurrently to a single +// recipient so every tx in a block writes to the same balance slot — the +// classic contended-account scenario. A missed scheduler conflict would +// manifest as a lost write (final balance below the expected delta). +func runContendedAccountWorkload(t *testing.T, base *suite.BaseTestSuite) { + t.Helper() + + sut := base.SystemUnderTest + nodeID := base.Node(0) + + baseFee, err := base.GetLatestBaseFee(nodeID) + require.NoError(t, err, "fetch base fee") + base.SetBaseFee(baseFee) + gasPrice := base.GasPriceMultiplier(10) + + recipient := base.EthAccount(contendedRecipient) + balCtx, cancelBal := context.WithTimeout(context.Background(), 10*time.Second) + defer cancelBal() + startBal, err := base.EthClient.Clients[nodeID].BalanceAt(balCtx, recipient.Address, nil) + require.NoError(t, err, "fetch starting recipient balance") + + type sendResult struct { + hash string + err error + } + resultsCh := make(chan sendResult, contendedSenders*contendedTxsPerEOA) + + var wg sync.WaitGroup + for i := 0; i < contendedSenders; i++ { + wg.Add(1) + go func(senderIdx int) { + defer wg.Done() + signerID := base.AccID(senderIdx) + // Fire txsPerEOA txs back-to-back from this EOA. Each call reads the + // chain nonce and adds nonceIdx; while the txs sit in the mempool + // the chain nonce hasn't advanced, so this produces a contiguous + // nonce sequence per sender. + for n := uint64(0); n < contendedTxsPerEOA; n++ { + info, err := base.SendEthLegacyTx(t, nodeID, signerID, n, gasPrice) + if err != nil { + resultsCh <- sendResult{err: fmt.Errorf("sender %s nonce %d: %w", signerID, n, err)} + return + } + resultsCh <- sendResult{hash: info.TxHash} + } + }(i) + } + wg.Wait() + close(resultsCh) + + var hashes []string + for r := range resultsCh { + require.NoError(t, r.err) + hashes = append(hashes, r.hash) + } + require.Len(t, hashes, contendedSenders*contendedTxsPerEOA) + + for _, h := range hashes { + _, err := base.EthClient.WaitForCommit(nodeID, h, 60*time.Second) + require.NoErrorf(t, err, "tx %s did not commit", h) + } + + endCtx, cancelEnd := context.WithTimeout(context.Background(), 10*time.Second) + defer cancelEnd() + endBal, err := base.EthClient.Clients[nodeID].BalanceAt(endCtx, recipient.Address, nil) + require.NoError(t, err, "fetch ending recipient balance") + + expectedDelta := big.NewInt(int64(contendedSenders*contendedTxsPerEOA) * contendedTxValue) + expected := new(big.Int).Add(startBal, expectedDelta) + require.Equalf(t, expected.String(), endBal.String(), + "contended-account balance mismatch: start=%s end=%s expected=%s — possible BlockSTM lost write", + startBal, endBal, expected) + + // Chain liveness: if any node forked, the chain would have halted by now. + sut.AwaitNBlocks(t, 2) +} diff --git a/tests/systemtests/clients/config.go b/tests/systemtests/clients/config.go index 44566790..581646d0 100644 --- a/tests/systemtests/clients/config.go +++ b/tests/systemtests/clients/config.go @@ -49,9 +49,13 @@ type Config struct { // NewConfig creates a new Config instance. func NewConfig() (*Config, error) { - // private keys of test accounts - privKeys := []string{Acc0PrivKey, Acc1PrivKey, Acc2PrivKey, Acc3PrivKey} + privKeys := []string{ + Acc0PrivKey, + Acc1PrivKey, + Acc2PrivKey, + Acc3PrivKey, + } // jsonrpc urls of testnet nodes jsonRPCUrls := []string{JsonRPCUrl0, JsonRPCUrl1, JsonRPCUrl2, JsonRPCUrl3} diff --git a/tests/systemtests/clients/cosmosclient.go b/tests/systemtests/clients/cosmosclient.go index 398f0f75..a768313a 100644 --- a/tests/systemtests/clients/cosmosclient.go +++ b/tests/systemtests/clients/cosmosclient.go @@ -35,26 +35,27 @@ 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) { +const defaultGenesisAccountCount = 4 + +// NewCosmosClient creates a new CosmosClient instance and returns it together with the loaded accounts. +func NewCosmosClient() (*CosmosClient, map[string]*CosmosAccount, error) { config, err := NewConfig() if err != nil { - return nil, fmt.Errorf("failed to load config") + return nil, 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) + return nil, 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) + return nil, nil, fmt.Errorf("failed to connect rpc server: %v", err) } rpcClients[fmt.Sprintf("node%v", i)] = rpcClient @@ -68,11 +69,19 @@ func NewCosmosClient() (*CosmosClient, error) { addr := sdk.AccAddress(privKey.PubKey().Address().Bytes()) if err != nil { - return nil, err + return nil, nil, err + } + // Only the default genesis accounts have deterministic account numbers. + // Additional test accounts are created on demand by the suite; they start + // with an account number of zero and will query the chain for their actual + // value once they exist on-chain. + accountNumber := uint64(0) + if i < defaultGenesisAccountCount { + accountNumber = uint64(i + 1) } acc := &CosmosAccount{ AccAddress: addr, - AccountNumber: uint64(i + 1), + AccountNumber: accountNumber, PrivKey: privKey, } accs[fmt.Sprintf("acc%v", i)] = acc @@ -82,16 +91,15 @@ func NewCosmosClient() (*CosmosClient, error) { ChainID: config.ChainID, ClientCtx: *clientCtx, RpcClients: rpcClients, - Accs: accs, - }, nil + }, 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) { +func (c *CosmosClient) BankSend(nodeID string, account *CosmosAccount, 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 + privKey := account.PrivKey + accountNumber := account.AccountNumber msg := banktypes.NewMsgSend(from, to, sdk.NewCoins(sdk.NewCoin("atest", amount))) @@ -162,26 +170,24 @@ func (c *CosmosClient) CheckTxsPending( 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, string(tx.Hash())) - } - - if ok := slices.Contains(pendingTxHashes, txHash); ok { - return nil + result, err := c.UnconfirmedTxs(ctx, nodeID) + if err == nil { + pendingTxHashes := make([]string, 0, len(result.Txs)) + for _, tx := range result.Txs { + pendingTxHashes = append(pendingTxHashes, string(tx.Hash())) + } + + if slices.Contains(pendingTxHashes, txHash) { + 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) +func (c *CosmosClient) UnconfirmedTxs(ctx context.Context, nodeID string) (*coretypes.ResultUnconfirmedTxs, error) { + return c.RpcClients[nodeID].UnconfirmedTxs(ctx, nil) } // GetBalance retrieves the balance of a given address for a specific denomination. diff --git a/tests/systemtests/clients/ethclient.go b/tests/systemtests/clients/ethclient.go index a4644fa6..a2e4137f 100644 --- a/tests/systemtests/clients/ethclient.go +++ b/tests/systemtests/clients/ethclient.go @@ -18,21 +18,20 @@ import ( 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) { +// NewEthClient creates a new EthClient instance and returns it together with the loaded accounts. +func NewEthClient() (*EthClient, map[string]*EthAccount, error) { config, err := NewConfig() if err != nil { - return nil, fmt.Errorf("failed to load config") + return nil, 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) + return nil, nil, fmt.Errorf("failed to connecting node url: %s", jsonrpcUrl) } clients[fmt.Sprintf("node%v", i)] = ethcli } @@ -41,7 +40,7 @@ func NewEthClient() (*EthClient, error) { for i, privKey := range config.PrivKeys { ecdsaPrivKey, err := crypto.HexToECDSA(privKey) if err != nil { - return nil, err + return nil, nil, err } address := crypto.PubkeyToAddress(ecdsaPrivKey.PublicKey) acc := &EthAccount{ @@ -54,23 +53,22 @@ func NewEthClient() (*EthClient, error) { return &EthClient{ ChainID: config.EVMChainID, Clients: clients, - Accs: accs, - }, nil + }, 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 +// Setup prepares the context, client, and address for the given node and account. +func (ec *EthClient) Setup(nodeID string, account *EthAccount) (context.Context, *ethclient.Client, common.Address) { + return context.Background(), ec.Clients[nodeID], account.Address } // SendRawTransaction sends a raw Ethereum transaction to the specified node. func (ec *EthClient) SendRawTransaction( nodeID string, - accID string, + account *EthAccount, tx *ethtypes.Transaction, ) (common.Hash, error) { ethCli := ec.Clients[nodeID] - privKey := ec.Accs[accID].PrivKey + privKey := account.PrivKey signer := ethtypes.NewLondonSigner(ec.ChainID) signedTx, err := ethtypes.SignTx(tx, signer, privKey) @@ -131,7 +129,7 @@ func (ec *EthClient) CheckTxsPending( case <-ctx.Done(): return fmt.Errorf("timeout waiting for transaction %s", txHash) case <-ticker.C: - pendingTxs, _, err := ec.TxPoolContent(nodeID) + pendingTxs, _, err := ec.TxPoolContent(ctx, nodeID) if err != nil { fmt.Printf("DEBUG: failed to get txpool content: %v", err) continue // Retry on error @@ -147,11 +145,11 @@ func (ec *EthClient) CheckTxsPending( } // 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) { +func (ec *EthClient) TxPoolContent(ctx context.Context, 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") + err := ethCli.Client().CallContext(ctx, &result, "txpool_content") if err != nil { return nil, nil, fmt.Errorf("failed to call txpool_content eth api: %v", err) } @@ -184,12 +182,7 @@ func extractTxHashesSorted(txMap map[string]map[string]*EthRPCTransaction) []str return result } -func (ec *EthClient) CodeAt(nodeID, accID string) ([]byte, error) { - acc := ec.Accs[accID] - if acc == nil { - return nil, fmt.Errorf("account %s not found", accID) - } - +func (ec *EthClient) CodeAt(nodeID string, account *EthAccount) ([]byte, error) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() @@ -198,9 +191,9 @@ func (ec *EthClient) CodeAt(nodeID, accID string) ([]byte, error) { return nil, fmt.Errorf("failed to query block number: %w", err) } - code, err := ec.Clients[nodeID].CodeAt(ctx, acc.Address, big.NewInt(int64(blockNumber))) + code, err := ec.Clients[nodeID].CodeAt(ctx, account.Address, big.NewInt(int64(blockNumber))) if err != nil { - return nil, fmt.Errorf("failed to query code for %s: %w", accID, err) + return nil, fmt.Errorf("failed to query code for %s: %w", account.Address.Hex(), err) } return code, nil diff --git a/tests/systemtests/eip712/eip712_utils.go b/tests/systemtests/eip712/eip712_utils.go index 49dbbe07..4cc7412a 100644 --- a/tests/systemtests/eip712/eip712_utils.go +++ b/tests/systemtests/eip712/eip712_utils.go @@ -22,7 +22,8 @@ import ( // BankSendWithEIP712 sends a bank send transaction using EIP-712 signing. func BankSendWithEIP712( cosmosClient *clients.CosmosClient, - nodeID, accID string, + account *clients.CosmosAccount, + nodeID string, from, to sdk.AccAddress, amount sdkmath.Int, nonce uint64, @@ -30,14 +31,14 @@ func BankSendWithEIP712( ) (*sdk.TxResponse, error) { cosmosClient.ClientCtx = cosmosClient.ClientCtx.WithClient(cosmosClient.RpcClients[nodeID]) - privKey := cosmosClient.Accs[accID].PrivKey + privKey := account.PrivKey // Query account number from chain - account, err := cosmosClient.ClientCtx.AccountRetriever.GetAccount(cosmosClient.ClientCtx, from) + accountInfo, err := cosmosClient.ClientCtx.AccountRetriever.GetAccount(cosmosClient.ClientCtx, from) if err != nil { return nil, fmt.Errorf("failed to get account: %v", err) } - accountNumber := account.GetAccountNumber() + accountNumber := accountInfo.GetAccountNumber() msg := banktypes.NewMsgSend(from, to, sdk.NewCoins(sdk.NewCoin("atest", amount))) diff --git a/tests/systemtests/eip712/interface.go b/tests/systemtests/eip712/interface.go deleted file mode 100644 index e322e7bd..00000000 --- a/tests/systemtests/eip712/interface.go +++ /dev/null @@ -1,28 +0,0 @@ -package eip712 - -import ( - "math/big" - "testing" - - sdk "github.com/cosmos/cosmos-sdk/types" -) - -type TestSuite interface { - // Test Lifecycle - BeforeEachCase(t *testing.T) - AfterEachCase(t *testing.T) - - // Tx - EIP-712 signing - SendBankSendWithEIP712(t *testing.T, nodeID string, accID string, to sdk.AccAddress, amount *big.Int, nonce uint64, gasPrice *big.Int) (string, error) - - // Query - GetBalance(t *testing.T, nodeID string, address sdk.AccAddress, denom string) (*big.Int, error) - WaitForCommit(nodeID string, txHash string, timeout ...int) error - - // Config - Node(idx int) string - Acc(idx int) string - - // Test Utils - AwaitNBlocks(t *testing.T, n int64) -} diff --git a/tests/systemtests/eip712/test_eip712.go b/tests/systemtests/eip712/test_eip712.go index f1908af8..febe65e0 100644 --- a/tests/systemtests/eip712/test_eip712.go +++ b/tests/systemtests/eip712/test_eip712.go @@ -6,40 +6,40 @@ import ( "math/big" "testing" + "github.com/cosmos/evm/tests/systemtests/suite" "github.com/stretchr/testify/require" ) -// TestEIP712BankSend tests that a bank send transaction can be signed and broadcast using EIP-712. -func TestEIP712BankSend(t *testing.T) { - sut := NewSystemTestSuite(t) - sut.SetupTest(t) +// RunEIP712BankSend tests that a bank send transaction can be signed and broadcast using EIP-712. +func RunEIP712BankSend(t *testing.T, base *suite.BaseTestSuite) { + s := NewTestSuite(base) + s.SetupTest(t) // Get initial nonce for acc0 + acc0 := s.Acc(0) + gasPrice := big.NewInt(1000000000000) // Send a bank send transaction from acc0 to acc1 using EIP-712 signing - from := sut.CosmosClient.Accs[sut.Acc(0)].AccAddress - cosmosAcc := sut.CosmosClient.Accs[sut.Acc(0)] - ctx := sut.CosmosClient.ClientCtx.WithClient(sut.CosmosClient.RpcClients["node0"]) - account, err := ctx.AccountRetriever.GetAccount(ctx, cosmosAcc.AccAddress) - require.Nil(t, err) - to := sut.CosmosClient.Accs[sut.Acc(1)].AccAddress + from := acc0.Cosmos.AccAddress + to := s.Acc(1).Cosmos.AccAddress amount := big.NewInt(1000000) + curNonceIdx := uint64(0) - txHash, err := sut.SendBankSendWithEIP712( + txHash, err := s.SendBankSendWithEIP712( t, - sut.Node(0), - sut.Acc(0), + s.Node(0), + acc0.ID, to, amount, - account.GetSequence(), + curNonceIdx, gasPrice, ) require.NoError(t, err, "Failed to send bank send with EIP-712") require.NotEmpty(t, txHash, "Transaction hash should not be empty") // Wait for the transaction to be committed - err = sut.WaitForCommit(sut.Node(0), txHash) + err = s.WaitForCommit(s.Node(0), txHash) require.NoError(t, err, "Transaction should be committed successfully") t.Logf("Successfully sent bank send transaction with EIP-712 signing: %s", txHash) @@ -48,57 +48,59 @@ func TestEIP712BankSend(t *testing.T) { t.Logf("Amount: %s", amount.String()) } -// TestEIP712BankSendWithBalanceCheck tests that a bank send transaction using EIP-712 +// RunEIP712BankSendWithBalanceCheck tests that a bank send transaction using EIP-712 // correctly updates the balances of the sender and receiver. -func TestEIP712BankSendWithBalanceCheck(t *testing.T) { - sut := NewSystemTestSuite(t) - sut.SetupTest(t) +func RunEIP712BankSendWithBalanceCheck(t *testing.T, base *suite.BaseTestSuite) { + s := NewTestSuite(base) + s.SetupTest(t) + + signer := s.Acc(0) denom := "atest" // Get accounts - fromAddr := sut.CosmosClient.Accs[sut.Acc(0)].AccAddress - toAddr := sut.CosmosClient.Accs[sut.Acc(1)].AccAddress + fromAddr := signer.Cosmos.AccAddress + toAddr := s.Acc(1).Cosmos.AccAddress // Get initial balances - initialFromBalance, err := sut.GetBalance(t, sut.Node(0), fromAddr, denom) + initialFromBalance, err := s.GetBalance(t, s.Node(0), fromAddr, denom) require.NoError(t, err, "Failed to get initial balance for sender") t.Logf("Initial sender balance: %s", initialFromBalance.String()) - initialToBalance, err := sut.GetBalance(t, sut.Node(0), toAddr, denom) + initialToBalance, err := s.GetBalance(t, s.Node(0), toAddr, denom) require.NoError(t, err, "Failed to get initial balance for receiver") t.Logf("Initial receiver balance: %s", initialToBalance.String()) // Send a bank send transaction using EIP-712 - nonce := uint64(0) + curNonceIdx := uint64(0) gasPrice := big.NewInt(1000000000000) amount := big.NewInt(5000000) - txHash, err := sut.SendBankSendWithEIP712( + txHash, err := s.SendBankSendWithEIP712( t, - sut.Node(0), - sut.Acc(0), + s.Node(0), + signer.ID, toAddr, amount, - nonce, + curNonceIdx, gasPrice, ) require.NoError(t, err, "Failed to send bank send with EIP-712") require.NotEmpty(t, txHash, "Transaction hash should not be empty") // Wait for the transaction to be committed - err = sut.WaitForCommit(sut.Node(0), txHash) + err = s.WaitForCommit(s.Node(0), txHash) require.NoError(t, err, "Transaction should be committed successfully") // Wait for one more block to ensure balance updates are finalized - sut.AwaitNBlocks(t, 1) + s.AwaitNBlocks(t, 1) // Get final balances - finalFromBalance, err := sut.GetBalance(t, sut.Node(0), fromAddr, denom) + finalFromBalance, err := s.GetBalance(t, s.Node(0), fromAddr, denom) require.NoError(t, err, "Failed to get final balance for sender") t.Logf("Final sender balance: %s", finalFromBalance.String()) - finalToBalance, err := sut.GetBalance(t, sut.Node(0), toAddr, denom) + finalToBalance, err := s.GetBalance(t, s.Node(0), toAddr, denom) require.NoError(t, err, "Failed to get final balance for receiver") t.Logf("Final receiver balance: %s", finalToBalance.String()) @@ -119,20 +121,23 @@ func TestEIP712BankSendWithBalanceCheck(t *testing.T) { t.Logf("Receiver balance change: %s", new(big.Int).Sub(finalToBalance, initialToBalance).String()) } -// TestEIP712MultipleBankSends tests that multiple bank send transactions can be sent +// RunEIP712MultipleBankSends tests that multiple bank send transactions can be sent // sequentially using EIP-712 signing with correct nonce management. -func TestEIP712MultipleBankSends(t *testing.T) { - sut := NewSystemTestSuite(t) - sut.SetupTest(t) +func RunEIP712MultipleBankSends(t *testing.T, base *suite.BaseTestSuite) { + s := NewTestSuite(base) + s.SetupTest(t) + + signer := s.Acc(0) denom := "atest" - toAddr := sut.CosmosClient.Accs[sut.Acc(1)].AccAddress + toAddr := s.Acc(1).Cosmos.AccAddress // Get initial balance - initialBalance, err := sut.GetBalance(t, sut.Node(0), toAddr, denom) + initialBalance, err := s.GetBalance(t, s.Node(0), toAddr, denom) require.NoError(t, err, "Failed to get initial balance") t.Logf("Initial receiver balance: %s", initialBalance.String()) + curNonceIdx := uint64(0) gasPrice := big.NewInt(1000000000000) amount := big.NewInt(1000000) numTxs := 3 @@ -141,13 +146,13 @@ func TestEIP712MultipleBankSends(t *testing.T) { // Send multiple transactions with sequential nonces for i := 0; i < numTxs; i++ { - txHash, err := sut.SendBankSendWithEIP712( + txHash, err := s.SendBankSendWithEIP712( t, - sut.Node(0), - sut.Acc(0), + s.Node(0), + signer.ID, toAddr, amount, - uint64(i), + curNonceIdx, gasPrice, ) require.NoError(t, err, "Failed to send transaction %d", i) @@ -156,15 +161,15 @@ func TestEIP712MultipleBankSends(t *testing.T) { t.Logf("Sent transaction %d with hash: %s", i, txHash) // Wait for the transaction to be committed - err = sut.WaitForCommit(sut.Node(0), txHash) + err = s.WaitForCommit(s.Node(0), txHash) require.NoError(t, err, "Transaction %d should be committed successfully", i) } // Wait for one more block to ensure all balance updates are finalized - sut.AwaitNBlocks(t, 1) + s.AwaitNBlocks(t, 1) // Get final balance - finalBalance, err := sut.GetBalance(t, sut.Node(0), toAddr, denom) + finalBalance, err := s.GetBalance(t, s.Node(0), toAddr, denom) require.NoError(t, err, "Failed to get final balance") t.Logf("Final receiver balance: %s", finalBalance.String()) diff --git a/tests/systemtests/eip712/test_suite.go b/tests/systemtests/eip712/test_suite.go index 50be1da8..4fe4c400 100644 --- a/tests/systemtests/eip712/test_suite.go +++ b/tests/systemtests/eip712/test_suite.go @@ -9,76 +9,46 @@ import ( "time" sdkmath "cosmossdk.io/math" - "cosmossdk.io/systemtests" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/evm/tests/systemtests/clients" - "github.com/stretchr/testify/require" + basesuite "github.com/cosmos/evm/tests/systemtests/suite" ) -// SystemTestSuite implements the TestSuite interface for EIP-712 system tests. -type SystemTestSuite struct { - *systemtests.SystemUnderTest - CosmosClient *clients.CosmosClient - EthClient *clients.EthClient +type TestSuite struct { + *basesuite.BaseTestSuite } -// NewSystemTestSuite creates a new SystemTestSuite instance. -func NewSystemTestSuite(t *testing.T) *SystemTestSuite { - cosmosClient, err := clients.NewCosmosClient() - require.NoError(t, err) - - ethClient, err := clients.NewEthClient() - require.NoError(t, err) - - return &SystemTestSuite{ - SystemUnderTest: systemtests.Sut, - CosmosClient: cosmosClient, - EthClient: ethClient, - } -} - -// SetupTest initializes the test suite by resetting and starting the chain. -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) +func NewTestSuite(base *basesuite.BaseTestSuite) *TestSuite { + return &TestSuite{BaseTestSuite: base} } -// BeforeEachCase runs before each test case. -func (s *SystemTestSuite) BeforeEachCase(t *testing.T) { - // Setup before each test case if needed -} - -// AfterEachCase runs after each test case. -func (s *SystemTestSuite) AfterEachCase(t *testing.T) { - // Wait for a block to ensure transactions are processed - s.AwaitNBlocks(t, 1) -} - -// SendBankSendWithEIP712 sends a bank send transaction using EIP-712 signing. -func (s *SystemTestSuite) SendBankSendWithEIP712( +func (s *TestSuite) SendBankSendWithEIP712( t *testing.T, nodeID string, accID string, to sdk.AccAddress, amount *big.Int, - nonce uint64, + nonceIdx uint64, gasPrice *big.Int, ) (string, error) { - from := s.CosmosClient.Accs[accID].AccAddress + cosmosAccount := s.CosmosAccount(accID) + + ctx := s.CosmosClient.ClientCtx.WithClient(s.CosmosClient.RpcClients[nodeID]) + account, err := ctx.AccountRetriever.GetAccount(ctx, cosmosAccount.AccAddress) + if err != nil { + return "", fmt.Errorf("failed to query account for nonce: %w", err) + } + + cosmosAccount.AccountNumber = account.GetAccountNumber() + actualNonce := account.GetSequence() + nonceIdx resp, err := BankSendWithEIP712( s.CosmosClient, + cosmosAccount, nodeID, - accID, - from, + cosmosAccount.AccAddress, to, sdkmath.NewIntFromBigInt(amount), - nonce, + actualNonce, gasPrice, ) if err != nil { @@ -88,8 +58,7 @@ func (s *SystemTestSuite) SendBankSendWithEIP712( return resp.TxHash, nil } -// GetBalance retrieves the balance of a given address for a specific denomination. -func (s *SystemTestSuite) GetBalance( +func (s *TestSuite) GetBalance( t *testing.T, nodeID string, address sdk.AccAddress, @@ -97,54 +66,16 @@ func (s *SystemTestSuite) GetBalance( ) (*big.Int, error) { balance, err := s.CosmosClient.GetBalance(nodeID, address, denom) if err != nil { - return nil, fmt.Errorf("failed to get balance: %v", err) + return nil, fmt.Errorf("failed to get balance: %w", err) } return balance, nil } -// WaitForCommit waits for a transaction to be committed. -func (s *SystemTestSuite) WaitForCommit(nodeID string, txHash string, timeout ...int) error { - timeoutDuration := 15 * time.Second +func (s *TestSuite) WaitForCommit(nodeID string, txHash string, timeout ...int) error { + duration := 15 * time.Second if len(timeout) > 0 && timeout[0] > 0 { - timeoutDuration = time.Duration(timeout[0]) * time.Second + duration = time.Duration(timeout[0]) * time.Second } - - result, err := s.CosmosClient.WaitForCommit(nodeID, txHash, timeoutDuration) - if err != nil { - return fmt.Errorf("failed to wait for commit: %v", err) - } - - if result.TxResult.Code != 0 { - return fmt.Errorf("transaction failed with code %d: %s", result.TxResult.Code, result.TxResult.Log) - } - - return nil -} - -// 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) -} - -// AwaitNBlocks waits for N blocks to be produced. -func (s *SystemTestSuite) AwaitNBlocks(t *testing.T, n int64) { - s.SystemUnderTest.AwaitNBlocks(t, n) -} - -// DefaultNodeArgs returns the default node startup arguments. -func DefaultNodeArgs() []string { - chainID := "--chain-id=local-4221" - evmChainID := "--evm.evm-chain-id=4221" - apiEnable := "--api.enable=true" - jsonrpcApi := "--json-rpc.api=eth,txpool,personal,net,debug,web3" - jsonrpcAllowUnprotectedTxs := "--json-rpc.allow-unprotected-txs=true" - maxTxs := "--mempool.max-txs=0" - - return []string{jsonrpcApi, chainID, evmChainID, apiEnable, jsonrpcAllowUnprotectedTxs, maxTxs} + return s.BaseTestSuite.WaitForCommit(nodeID, txHash, basesuite.TxTypeCosmos, duration) } diff --git a/tests/systemtests/eth_test.go b/tests/systemtests/eth_test.go deleted file mode 100644 index 52efb5b0..00000000 --- a/tests/systemtests/eth_test.go +++ /dev/null @@ -1,358 +0,0 @@ -package systemtests - -import ( - "context" - "encoding/hex" - "fmt" - "math/big" - "os" - "os/exec" - "path/filepath" - "regexp" - "runtime" - "strconv" - "strings" - "sync" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/stretchr/testify/require" - - "cosmossdk.io/systemtests" -) - -const ( - // this PK is derived from the accounts created in testnet.go - pk = "0x88cbead91aee890d27bf06e003ade3d4e952427e88f88d31d61d3ef5e5d54305" -) - -func StartChain(t *testing.T, sut *systemtests.SystemUnderTest) { - chainID := "--chain-id=local-4221" - evmChainID := "--evm.evm-chain-id=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, evmChainID, apiEnable, jsonrpcAllowUnprotectedTxs} - - sut.StartChain(t, args...) -} - -// cosmos and eth tx with same nonce. -// tx pool with nonce gapped txs - submit cosmos tx for the gapped txs and first in queue. overlapped txs inbetween pools. - -// todo: 2 very fast txs make sure its replaced across everything.. -// what happens if 2nd tx is not relayed to the proposer fast enough? -// set 2 vals, one with lots of stake, other v little - -func TestPriorityReplacement(t *testing.T) { - sut := systemtests.Sut - sut.ResetChain(t) - StartChain(t, sut) - - sut.AwaitNBlocks(t, 10) - - // get the directory of the counter project to run commands from - _, filename, _, _ := runtime.Caller(0) - testDir := filepath.Dir(filename) - counterDir := filepath.Join(testDir, "Counter") - - // deploy the contract - cmd := exec.Command( - "forge", - "create", "src/Counter.sol:Counter", - "--rpc-url", "http://127.0.0.1:8545", - "--broadcast", - "--private-key", pk, - ) - cmd.Dir = counterDir - res, err := cmd.CombinedOutput() - require.NoError(t, err) - require.NotEmpty(t, string(res)) - - // get contract address - contractAddr := parseContractAddress(string(res)) - require.NotEmpty(t, contractAddr) - - wg := sync.WaitGroup{} - - var highPrioRes []byte - wg.Add(1) - go func() { - defer wg.Done() - var prioErr error - highPrioRes, 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", - "--nonce", "2", - ).CombinedOutput() - require.NoError(t, prioErr) - }() - - wg.Add(1) - var lowPrioRes []byte - go func() { - defer wg.Done() - var prioErr error - lowPrioRes, prioErr = exec.Command( - "cast", "send", - contractAddr, - "increment()", - "--rpc-url", "http://127.0.0.1:8545", - "--private-key", pk, - "--gas-price", "99900000000000", - "--nonce", "2", - ).CombinedOutput() - require.Error(t, prioErr) - }() - - // wait a bit to make sure the tx is submitted and waiting in the txpool. - time.Sleep(2 * time.Second) - - res, err = exec.Command( - "cast", "send", - contractAddr, - "increment()", - "--rpc-url", "http://127.0.0.1:8545", - "--private-key", pk, - "--nonce", "1", - ).CombinedOutput() - require.NoError(t, err) - - 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. - require.Equal(t, highPrioReceipt.Status, uint64(1)) - require.Equal(t, lowPrioReceipt.Status, uint64(0)) -} - -// todo: check that the other nodes dont have this tx. check ethtxpool. -func TestNonceGappedTxsPass(t *testing.T) { - sut := systemtests.Sut - sut.ResetChain(t) - StartChain(t, sut) - - sut.AwaitNBlocks(t, 10) - - // get the directory of the counter project to run commands from - _, filename, _, _ := runtime.Caller(0) - testDir := filepath.Dir(filename) - counterDir := filepath.Join(testDir, "Counter") - - // deploy the contract - cmd := exec.Command( - "forge", - "create", "src/Counter.sol:Counter", - "--rpc-url", "http://127.0.0.1:8545", - "--broadcast", - "--private-key", pk, - ) - cmd.Dir = counterDir - res, err := cmd.CombinedOutput() - require.NoError(t, err) - require.NotEmpty(t, string(res)) - - // get contract address - contractAddr := parseContractAddress(string(res)) - require.NotEmpty(t, contractAddr) - - wg := sync.WaitGroup{} - - outOfOrderNonces := []uint64{4, 2, 5, 3} - responses := make([][]byte, len(outOfOrderNonces)) - - for i, nonce := range outOfOrderNonces { - wg.Add(1) - go func() { - defer wg.Done() - res1, err1 := exec.Command( - "cast", "send", - contractAddr, - "increment()", - "--rpc-url", "http://127.0.0.1:8545", - "--private-key", pk, - "--nonce", fmt.Sprintf("%d", nonce), - ).CombinedOutput() - require.NoError(t, err1, "response: %s", string(res1)) - responses[i] = res1 - }() - } - - // wait a bit to make sure the tx is submitted and waiting in the txpool. - time.Sleep(2 * time.Second) - - res, err = exec.Command( - "cast", "send", - contractAddr, - "increment()", - "--rpc-url", "http://127.0.0.1:8545", - "--private-key", pk, - "--nonce", "1", - ).CombinedOutput() - require.NoError(t, err, "response: %s", string(res)) - - wg.Wait() - - receipt, err := parseReceipt(string(res)) - require.NoError(t, err) - require.Equal(t, receipt.Status, uint64(1)) - - for _, bz := range responses { - receipt, err := parseReceipt(string(bz)) - require.NoError(t, err) - require.Equal(t, receipt.Status, uint64(1)) - } -} - -func TestSimpleSendsScript(t *testing.T) { - sut := systemtests.Sut - sut.ResetChain(t) - StartChain(t, sut) - sut.AwaitNBlocks(t, 10) - // this PK is derived from the accounts created in testnet.go - pk := "0x88cbead91aee890d27bf06e003ade3d4e952427e88f88d31d61d3ef5e5d54305" - - // get the directory of the counter project to run commands from - _, filename, _, _ := runtime.Caller(0) - testDir := filepath.Dir(filename) - counterDir := filepath.Join(testDir, "Counter") - - // Wait for the RPC endpoint to be fully ready - time.Sleep(3 * time.Second) - - // First, let's test if forge is available and the script compiles - compileCmd := exec.Command( - "forge", - "build", - ) - compileCmd.Dir = counterDir - compileRes, err := compileCmd.CombinedOutput() - require.NoError(t, err, "Forge build failed: %s", string(compileRes)) - - // Set the private key as an environment variable for the script - cmd := exec.Command( - "forge", - "script", - "script/SimpleSends.s.sol:SimpleSendsScript", - "--rpc-url", "http://127.0.0.1:8545", - "--broadcast", - "--private-key", pk, - "--gas-limit", "5000000", // Reduced gas limit - "--timeout", "60", // Add timeout - ) - cmd.Dir = counterDir - cmd.Env = append(cmd.Env, "PRIVATE_KEY="+pk) - // Set a timeout for the command execution - - ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second) - defer cancel() - cmd = exec.CommandContext(ctx, cmd.Path, cmd.Args[1:]...) - cmd.Dir = counterDir - cmd.Env = append(os.Environ(), "PRIVATE_KEY="+pk) - - res, err := cmd.CombinedOutput() - require.NoError(t, err, "Script execution failed: %s", string(res)) - require.NotEmpty(t, string(res)) - - // Verify the script output contains expected logs - output := string(res) - require.Contains(t, output, "Script ran successfully.") - - // Wait for a few blocks to ensure transactions are processed - sut.AwaitNBlocks(t, 5) - - // Verify that the script executed without errors - require.NotContains(t, output, "Error:") - require.NotContains(t, output, "Failed:") -} - -func parseContractAddress(output string) string { - re := regexp.MustCompile(`Deployed to: (0x[a-fA-F0-9]{40})`) - matches := re.FindStringSubmatch(output) - if len(matches) >= 2 { - return matches[1] - } - return "" -} - -func parseReceipt(output string) (*types.Receipt, error) { - receipt := &types.Receipt{} - - lines := strings.Split(output, "\n") - for _, line := range lines { - line = strings.TrimSpace(line) - if line == "" { - continue - } - - parts := strings.SplitN(line, " ", 2) - if len(parts) != 2 { - continue - } - - key := strings.TrimSpace(parts[0]) - value := strings.TrimSpace(parts[1]) - - switch key { - case "blockHash": - receipt.BlockHash = common.HexToHash(value) - case "blockNumber": - if blockNum, err := strconv.ParseUint(value, 10, 64); err == nil { - receipt.BlockNumber = big.NewInt(int64(blockNum)) - } - case "transactionHash": - receipt.TxHash = common.HexToHash(value) - case "transactionIndex": - if txIndex, err := strconv.ParseUint(value, 10, 64); err == nil { - receipt.TransactionIndex = uint(txIndex) - } - case "contractAddress": - if value != "" { - receipt.ContractAddress = common.HexToAddress(value) - } - case "gasUsed": - if gasUsed, err := strconv.ParseUint(value, 10, 64); err == nil { - receipt.GasUsed = gasUsed - } - case "cumulativeGasUsed": - if cumulativeGas, err := strconv.ParseUint(value, 10, 64); err == nil { - receipt.CumulativeGasUsed = cumulativeGas - } - case "status": - if strings.Contains(value, "1") || strings.Contains(value, "success") { - receipt.Status = types.ReceiptStatusSuccessful - } else { - receipt.Status = types.ReceiptStatusFailed - } - case "type": - if txType, err := strconv.ParseUint(value, 10, 8); err == nil { - receipt.Type = uint8(txType) - } - case "logsBloom": - if bloomHex := strings.TrimPrefix(value, "0x"); bloomHex != "" { - if bloomBytes, err := hex.DecodeString(bloomHex); err == nil && len(bloomBytes) == 256 { - copy(receipt.Bloom[:], bloomBytes) - } - } - } - } - - return receipt, nil -} diff --git a/tests/systemtests/go.mod b/tests/systemtests/go.mod index 12e57bc4..48a02374 100644 --- a/tests/systemtests/go.mod +++ b/tests/systemtests/go.mod @@ -1,14 +1,15 @@ module github.com/cosmos/evm/tests/systemtests -go 1.24.4 +go 1.25.9 require ( cosmossdk.io/math v1.5.3 - cosmossdk.io/systemtests v1.4.0 - github.com/cometbft/cometbft v0.38.19 - github.com/cosmos/cosmos-sdk v0.53.4 + github.com/cometbft/cometbft v0.39.3 + github.com/cosmos/cosmos-sdk v0.54.3 + github.com/cosmos/cosmos-sdk/tools/systemtests v0.0.0-20260505173942-e77c24c3eda7 github.com/cosmos/evm v0.5.0-rc.0 - github.com/ethereum/go-ethereum v1.15.11 + github.com/creachadair/tomledit v0.0.29 + github.com/ethereum/go-ethereum v1.16.8 github.com/holiman/uint256 v1.3.2 github.com/onsi/ginkgo/v2 v2.23.4 github.com/onsi/gomega v1.38.0 @@ -18,77 +19,83 @@ require ( ) require ( - cosmossdk.io/api v1.0.0-rc.1 // indirect - cosmossdk.io/collections v1.3.1 // indirect - cosmossdk.io/core v1.1.0-rc.1 // indirect + cosmossdk.io/api v1.0.0 // indirect + cosmossdk.io/collections v1.4.0 // indirect + cosmossdk.io/core v1.1.0 // indirect cosmossdk.io/depinject v1.2.1 // indirect - cosmossdk.io/errors v1.0.2 // indirect - cosmossdk.io/log v1.6.1 // indirect + cosmossdk.io/errors v1.1.0 // indirect + cosmossdk.io/log/v2 v2.1.0 // 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 - cosmossdk.io/x/upgrade v0.2.0 // indirect - filippo.io/edwards25519 v1.1.0 // indirect + filippo.io/edwards25519 v1.2.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // 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/VictoriaMetrics/fastcache v1.12.2 // indirect + github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260116142910-60249400e523 // indirect + github.com/RoaringBitmap/roaring/v2 v2.18.0 // indirect + github.com/VictoriaMetrics/fastcache v1.13.0 // indirect + github.com/benbjohnson/clock v1.3.5 // 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.14.0 // indirect - github.com/bytedance/sonic/loader v0.3.0 // indirect + github.com/bits-and-blooms/bitset v1.24.4 // indirect + github.com/bytedance/gopkg v0.1.4 // indirect + github.com/bytedance/sonic v1.15.0 // indirect + github.com/bytedance/sonic/loader v0.5.1 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cenkalti/backoff/v5 v5.0.3 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/cloudwego/base64x v0.1.5 // indirect - github.com/cockroachdb/errors v1.12.0 // indirect + github.com/cloudwego/base64x v0.1.6 // indirect + github.com/cockroachdb/errors v1.13.0 // indirect github.com/cockroachdb/fifo v0.0.0-20240816210425-c5d0cb0b6fc0 // 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 + github.com/cockroachdb/redact v1.1.8 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20250429170803-42689b6311bb // indirect github.com/cometbft/cometbft-db v1.0.4 // indirect - github.com/consensys/gnark-crypto v0.18.0 // indirect + github.com/consensys/gnark-crypto v0.18.1 // indirect github.com/cosmos/btcutil v1.0.5 // indirect + github.com/cosmos/btree v1.0.0 // 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/store/v2 v2.0.0 // 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/ibc-go/v10 v10.3.1-0.20250909102629-ed3b125c7b6f // indirect + github.com/cosmos/gogoproto v1.7.2 // indirect + github.com/cosmos/iavl v1.2.8 // indirect + github.com/cosmos/ibc-go/v11 v11.0.0 // indirect github.com/cosmos/ics23/go v0.11.0 // indirect - github.com/cosmos/ledger-cosmos-go v0.16.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/creachadair/tomledit v0.0.29 // indirect - github.com/danieljoos/wincred v1.2.2 // indirect + github.com/cosmos/ledger-cosmos-go v1.0.0 // indirect + github.com/crate-crypto/go-eth-kzg v1.5.0 // indirect + github.com/danieljoos/wincred v1.2.3 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.1 // 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/dgraph-io/badger/v4 v4.9.1 // indirect + github.com/dgraph-io/ristretto/v2 v2.4.0 // indirect + github.com/dunglas/httpsfv v1.1.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect - github.com/dvsekhvalnov/jose2go v1.7.0 // indirect - github.com/emicklei/dot v1.8.0 // indirect - github.com/ethereum/c-kzg-4844/v2 v2.1.0 // indirect - github.com/ethereum/go-verkle v0.2.2 // indirect + github.com/dvsekhvalnov/jose2go v1.8.0 // indirect + github.com/ebitengine/purego v0.10.0 // indirect + github.com/emicklei/dot v1.11.0 // indirect + github.com/ethereum/c-kzg-4844/v2 v2.1.6 // indirect + github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab // indirect github.com/fatih/color v1.18.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/ferranbt/fastssz v0.1.4 // indirect + github.com/flynn/noise v1.1.0 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect - github.com/getsentry/sentry-go v0.35.0 // indirect + github.com/getsentry/sentry-go v0.46.0 // indirect github.com/go-kit/kit v0.13.0 // indirect github.com/go-kit/log v0.2.1 // indirect - github.com/go-logfmt/logfmt v0.6.0 // indirect + github.com/go-logfmt/logfmt v0.6.1 // 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-task/slim-sprig/v3 v3.0.0 // indirect - github.com/go-viper/mapstructure/v2 v2.4.0 // indirect + github.com/go-viper/mapstructure/v2 v2.5.0 // indirect 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 @@ -100,11 +107,13 @@ require ( github.com/google/go-cmp v0.7.0 // indirect github.com/google/orderedcode v0.0.1 // indirect github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/gorilla/handlers v1.5.2 // indirect github.com/gorilla/mux v1.8.1 // indirect github.com/gorilla/websocket v1.5.3 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect @@ -116,99 +125,184 @@ 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/huin/goupnp v1.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 + github.com/ipfs/go-cid v0.5.0 // indirect + github.com/jackpal/go-nat-pmp v1.0.2 // indirect + github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect - github.com/klauspost/compress v1.18.0 // indirect - github.com/klauspost/cpuid/v2 v2.2.10 // indirect + github.com/klauspost/compress v1.18.5 // indirect + github.com/klauspost/cpuid/v2 v2.3.0 // indirect + github.com/koron/go-ssdp v0.0.6 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect - github.com/lib/pq v1.10.9 // indirect - github.com/linxGnu/grocksdb v1.10.1 // indirect + github.com/lib/pq v1.12.3 // indirect + github.com/libp2p/go-buffer-pool v0.1.0 // indirect + github.com/libp2p/go-flow-metrics v0.2.0 // indirect + github.com/libp2p/go-libp2p v0.47.0 // indirect + github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect + github.com/libp2p/go-msgio v0.3.0 // indirect + github.com/libp2p/go-netroute v0.3.0 // indirect + github.com/libp2p/go-reuseport v0.4.0 // indirect + github.com/libp2p/go-yamux/v5 v5.0.1 // indirect + github.com/linxGnu/grocksdb v1.10.7 // indirect + github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e // indirect + github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect github.com/mattn/go-colorable v0.1.14 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.15 // indirect - github.com/minio/highwayhash v1.0.3 // indirect - github.com/minio/sha256-simd v1.0.0 // indirect + github.com/mattn/go-isatty v0.0.22 // indirect + github.com/miekg/dns v1.1.66 // indirect + github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect + github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect + github.com/minio/highwayhash v1.0.4 // indirect + github.com/minio/sha256-simd v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/mr-tron/base58 v1.3.0 // indirect + github.com/mschoch/smat v0.2.0 // indirect github.com/mtibben/percent v0.2.1 // indirect + github.com/multiformats/go-base32 v0.1.0 // indirect + github.com/multiformats/go-base36 v0.2.0 // indirect + github.com/multiformats/go-multiaddr v0.16.1 // indirect + github.com/multiformats/go-multiaddr-dns v0.4.1 // indirect + github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect + github.com/multiformats/go-multibase v0.2.0 // indirect + github.com/multiformats/go-multicodec v0.9.1 // indirect + github.com/multiformats/go-multihash v0.2.3 // indirect + github.com/multiformats/go-multistream v0.6.1 // indirect + github.com/multiformats/go-varint v0.0.7 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a // indirect - github.com/oklog/run v1.1.0 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/nxadm/tail v1.4.11 // indirect + github.com/oasisprotocol/curve25519-voi v0.0.0-20251114093237-2ab5a27a1729 // indirect + github.com/oklog/run v1.2.0 // indirect + github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect - github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect + github.com/petermattis/goid v0.0.0-20260113132338-7c7de50cc741 // indirect + github.com/pion/datachannel v1.5.10 // indirect + github.com/pion/dtls/v2 v2.2.12 // indirect + github.com/pion/dtls/v3 v3.1.2 // indirect + github.com/pion/ice/v4 v4.0.10 // indirect + github.com/pion/interceptor v0.1.40 // indirect + github.com/pion/logging v0.2.4 // indirect + github.com/pion/mdns/v2 v2.0.7 // indirect + github.com/pion/randutil v0.1.0 // indirect + github.com/pion/rtcp v1.2.15 // indirect + github.com/pion/rtp v1.8.19 // indirect + github.com/pion/sctp v1.8.39 // indirect + github.com/pion/sdp/v3 v3.0.13 // indirect + github.com/pion/srtp/v3 v3.0.6 // indirect + github.com/pion/stun v0.6.1 // indirect + github.com/pion/stun/v3 v3.0.0 // indirect + github.com/pion/transport/v2 v2.2.10 // indirect + github.com/pion/transport/v3 v3.0.7 // indirect + github.com/pion/transport/v4 v4.0.1 // indirect + github.com/pion/turn/v4 v4.0.2 // indirect + github.com/pion/webrtc/v4 v4.1.2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect github.com/prometheus/client_golang v1.23.2 // indirect github.com/prometheus/client_model v0.6.2 // indirect - github.com/prometheus/common v0.66.1 // indirect - github.com/prometheus/procfs v0.16.1 // indirect - github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect - github.com/rivo/uniseg v0.2.0 // indirect + github.com/prometheus/common v0.67.5 // indirect + github.com/prometheus/procfs v0.20.1 // indirect + github.com/quic-go/qpack v0.6.0 // indirect + github.com/quic-go/quic-go v0.59.0 // indirect + github.com/quic-go/webtransport-go v0.10.0 // indirect + github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/rs/cors v1.11.1 // indirect - github.com/rs/zerolog v1.34.0 // indirect - github.com/sagikazarmark/locafero v0.11.0 // indirect - github.com/sasha-s/go-deadlock v0.3.5 // indirect + github.com/rs/zerolog v1.35.0 // indirect + github.com/sagikazarmark/locafero v0.12.0 // indirect + github.com/sasha-s/go-deadlock v0.3.9 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect - github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect + github.com/shirou/gopsutil/v4 v4.26.4 // indirect + github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spf13/afero v1.15.0 // indirect github.com/spf13/cast v1.10.0 // indirect - github.com/spf13/cobra v1.10.1 // indirect + github.com/spf13/cobra v1.10.2 // indirect github.com/spf13/pflag v1.0.10 // indirect github.com/spf13/viper v1.21.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect - github.com/supranational/blst v0.3.14 // indirect + github.com/supranational/blst v0.3.16 // 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/match v1.1.1 // indirect - github.com/tidwall/pretty v1.2.0 // indirect + github.com/tidwall/btree v1.8.1 // indirect + github.com/tidwall/match v1.2.0 // indirect + github.com/tidwall/pretty v1.2.1 // indirect github.com/tidwall/sjson v1.2.5 // indirect - github.com/tklauser/go-sysconf v0.3.15 // indirect - github.com/tklauser/numcpus v0.10.0 // indirect + github.com/tklauser/go-sysconf v0.3.16 // indirect + github.com/tklauser/numcpus v0.11.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/wlynxg/anet v0.0.5 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect github.com/zondax/golem v0.27.0 // indirect github.com/zondax/hid v0.9.2 // indirect github.com/zondax/ledger-go v1.0.1 // indirect - go.etcd.io/bbolt v1.4.0 // indirect - go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/otel v1.37.0 // indirect - go.opentelemetry.io/otel/metric v1.37.0 // indirect - go.opentelemetry.io/otel/trace v1.37.0 // indirect + go.etcd.io/bbolt v1.4.3 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/contrib/bridges/otelslog v0.18.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 // indirect + go.opentelemetry.io/contrib/instrumentation/host v0.68.0 // indirect + go.opentelemetry.io/contrib/instrumentation/runtime v0.68.0 // indirect + go.opentelemetry.io/contrib/otelconf v0.23.0 // indirect + go.opentelemetry.io/contrib/propagators/autoprop v0.68.0 // indirect + go.opentelemetry.io/contrib/propagators/aws v1.43.0 // indirect + go.opentelemetry.io/contrib/propagators/b3 v1.43.0 // indirect + go.opentelemetry.io/contrib/propagators/jaeger v1.43.0 // indirect + go.opentelemetry.io/contrib/propagators/ot v1.43.0 // indirect + go.opentelemetry.io/otel v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.19.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.19.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.43.0 // indirect + go.opentelemetry.io/otel/log v0.19.0 // indirect + go.opentelemetry.io/otel/metric v1.43.0 // indirect + go.opentelemetry.io/otel/sdk v1.43.0 // indirect + go.opentelemetry.io/otel/sdk/log v0.19.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.43.0 // indirect + go.opentelemetry.io/otel/trace v1.43.0 // indirect + go.opentelemetry.io/proto/otlp v1.10.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect + go.uber.org/dig v1.19.0 // indirect + go.uber.org/fx v1.24.0 // indirect + go.uber.org/mock v0.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.27.0 // indirect - go.yaml.in/yaml/v2 v2.4.2 // indirect + go.uber.org/zap v1.27.1 // indirect + go.yaml.in/yaml/v2 v2.4.4 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/arch v0.21.0 // indirect - golang.org/x/crypto v0.42.0 // indirect - golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 // indirect - golang.org/x/net v0.44.0 // indirect - golang.org/x/sync v0.17.0 // indirect - golang.org/x/sys v0.36.0 // indirect - golang.org/x/term v0.35.0 // indirect - golang.org/x/text v0.29.0 // indirect - golang.org/x/tools v0.36.0 // indirect - google.golang.org/genproto v0.0.0-20250603155806-513f23925822 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250804133106-a7a43d27e69b // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c // indirect - google.golang.org/grpc v1.76.0 // indirect - google.golang.org/protobuf v1.36.10 // indirect + golang.org/x/arch v0.26.0 // indirect + golang.org/x/crypto v0.50.0 // indirect + golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90 // indirect + golang.org/x/mod v0.34.0 // indirect + golang.org/x/net v0.53.0 // indirect + golang.org/x/sync v0.20.0 // indirect + golang.org/x/sys v0.43.0 // indirect + golang.org/x/telemetry v0.0.0-20260311193753-579e4da9a98c // indirect + golang.org/x/term v0.42.0 // indirect + golang.org/x/text v0.36.0 // indirect + golang.org/x/time v0.15.0 // indirect + golang.org/x/tools v0.43.0 // indirect + google.golang.org/genproto v0.0.0-20260414002931-afd174a4e478 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 // indirect + google.golang.org/grpc v1.80.0 // indirect + google.golang.org/protobuf v1.36.11 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.2 // indirect + lukechampine.com/blake3 v1.4.1 // indirect nhooyr.io/websocket v1.8.17 // indirect - pgregory.net/rapid v1.2.0 // indirect + pgregory.net/rapid v1.3.0 // indirect sigs.k8s.io/yaml v1.6.0 // indirect ) replace ( github.com/cosmos/evm => ../.. - github.com/ethereum/go-ethereum => github.com/cosmos/go-ethereum v1.16.2-cosmos-1 + github.com/ethereum/go-ethereum => github.com/cosmos/go-ethereum v1.17.2-cosmos-0 ) - -replace cosmossdk.io/store => cosmossdk.io/store v1.1.2 diff --git a/tests/systemtests/go.sum b/tests/systemtests/go.sum index 2bcf64d9..c41bd4b6 100644 --- a/tests/systemtests/go.sum +++ b/tests/systemtests/go.sum @@ -1,59 +1,47 @@ -cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY= -cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw= +cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4= +cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= 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.16.4 h1:fXOAIQmkApVvcIn7Pc2+5J8QTMVbUGLscnSVNl11su8= -cloud.google.com/go/auth v0.16.4/go.mod h1:j10ncYwjX/g3cdX7GpEzsdM+d+ZNsXAbb6qXA7p1Y5M= +cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE= +cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= +cloud.google.com/go/auth v0.20.0 h1:kXTssoVb4azsVDoUiF8KvxAqrsQcQtB53DcSgta74CA= +cloud.google.com/go/auth v0.20.0/go.mod h1:942/yi/itH1SsmpyrbnTMDgGfdy2BUqIKyd0cyYLc5Q= cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= -cloud.google.com/go/compute v1.38.0 h1:MilCLYQW2m7Dku8hRIIKo4r0oKastlD74sSu16riYKs= -cloud.google.com/go/compute/metadata v0.8.0 h1:HxMRIbao8w17ZX6wBnjhcDkW6lTFpgcaobyVfZWqRLA= -cloud.google.com/go/compute/metadata v0.8.0/go.mod h1:sYOGTp851OV9bOFJ9CH7elVvyzopvWQFNNghtDQ/Biw= -cloud.google.com/go/iam v1.5.2 h1:qgFRAGEmd8z6dJ/qyEchAuL9jpswyODjA2lS+w234g8= -cloud.google.com/go/iam v1.5.2/go.mod h1:SE1vg0N81zQqLzQEwxL2WI6yhetBdbNQuTvIKCSkUHE= -cloud.google.com/go/monitoring v1.24.2 h1:5OTsoJ1dXYIiMiuL+sYscLc9BumrL3CarVLL7dd7lHM= -cloud.google.com/go/monitoring v1.24.2/go.mod h1:x7yzPWcgDRnPEv3sI+jJGBkwl5qINf+6qY4eq0I9B4U= -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= -cosmossdk.io/collections v1.3.1/go.mod h1:ynvkP0r5ruAjbmedE+vQ07MT6OtJ0ZIDKrtJHK7Q/4c= -cosmossdk.io/core v1.1.0-rc.1 h1:VhF5xd4uJZt/lQzbl8qT1W3Pcrklp4RSnugcWQZyf5M= -cosmossdk.io/core v1.1.0-rc.1/go.mod h1:fKHIWVYfPCC4tto9eoYFZC/yAWFlWw2mz8YgSYvjnUs= +cloud.google.com/go/compute v1.58.0 h1:WQamD8d9Vxu+m5IJBxgUzqsbHxXwx/T7Ol4V5GyVCZE= +cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= +cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= +cloud.google.com/go/iam v1.9.0 h1:89wyjxT6DL4b5rk/Nk8eBC9DHqf+JiMstrn5IEYxFw4= +cloud.google.com/go/iam v1.9.0/go.mod h1:KP+nKGugNJW4LcLx1uEZcq1ok5sQHFaQehQNl4QDgV4= +cloud.google.com/go/monitoring v1.27.0 h1:BhYwMqao+e5Nn7JtWMM9m6zRtKtVUK6kJWMizXChkLU= +cloud.google.com/go/monitoring v1.27.0/go.mod h1:72NOVjJXHY/HBfoLT0+qlCZBT059+9VXLeAnL2PeeVM= +cloud.google.com/go/storage v1.62.1 h1:Os0G3XbUbjZumkpDUf2Y0rLoXJTCF1kU2kWUujKYXD8= +cloud.google.com/go/storage v1.62.1/go.mod h1:cpYz/kRVZ+UQAF1uHeea10/9ewcRbxGoGNKsS9daSXA= +cosmossdk.io/api v1.0.0 h1:qTV8OPVEwcBPwp2b9p4Qy4noZyihJ+sOMaWL/VT+RCc= +cosmossdk.io/api v1.0.0/go.mod h1:fKRljeYk+04p4T8Shdyv+uH2fSVyzHoWrvDAs/7OxfI= +cosmossdk.io/collections v1.4.0 h1:b373bkxCxKiRbapxZ42TRmcKJEnBVBebdQVk9I5IkkE= +cosmossdk.io/collections v1.4.0/go.mod h1:gxbieVY3tjbvWlkm3yOXf7sGyDrVi12haZH+sek6whw= +cosmossdk.io/core v1.1.0 h1:iJ7j2DjNsFzg4/z4ImNQYzy2D4LfMCsaQ8Lrz1KCmxk= +cosmossdk.io/core v1.1.0/go.mod h1:qGmJxBFHobvG1k4bROQnueslotBU5MIKZLC57xVBYYI= 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.1 h1:YXNwAgbDwMEKwDlCdH8vPcoggma48MgZrTQXCfmMBeI= -cosmossdk.io/log v1.6.1/go.mod h1:gMwsWyyDBjpdG9u2avCFdysXqxq28WJapJvu+vF1y+E= +cosmossdk.io/errors v1.1.0 h1:X2DSt9JYgH7cuiaDr318aUqIl2z5Lfo/PdGzAtmczUU= +cosmossdk.io/errors v1.1.0/go.mod h1:lnjBmx7etZpMTLnxdspZupH0d9HGRWZhiezDZX2ayyI= +cosmossdk.io/log/v2 v2.1.0 h1:oWLWqZ1UObWu5hIS3dvTW7QyjtvlmSzC3LOy04U/hVI= +cosmossdk.io/log/v2 v2.1.0/go.mod h1:zDNpuRD2sWw4zuw1lZYg/jxKftVG+VizgcWAWkIorwY= 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= cosmossdk.io/schema v1.1.0/go.mod h1:Gb7pqO+tpR+jLW5qDcNOSv0KtppYs7881kfzakguhhI= -cosmossdk.io/store v1.1.2 h1:3HOZG8+CuThREKv6cn3WSohAc6yccxO3hLzwK6rBC7o= -cosmossdk.io/store v1.1.2/go.mod h1:60rAGzTHevGm592kFhiUVkNC9w7gooSEn5iUBPzHQ6A= -cosmossdk.io/systemtests v1.4.0 h1:ix+q2BCiqJ6DNluxSayAfUNja43aQ4ZaJUj0fAAw9ko= -cosmossdk.io/systemtests v1.4.0/go.mod h1:rMD8LWYo/rOuX1n7e6ncHcGEgwf68IEW/o2k37/IBXs= -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= +filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo= +filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc= 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.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/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= +github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/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/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= @@ -61,25 +49,29 @@ github.com/DataDog/datadog-go v4.8.3+incompatible h1:fNGaYSuObuQb5nzeTQqowRAd9bp 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.29.0 h1:UQUsRi8WTzhZntp5313l+CHIAT95ojUI2lpP/ExlZa4= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0/go.mod h1:Cz6ft6Dkn3Et6l2v2a9/RpN7epQ1GtDlO6lj8bEcOvw= -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/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.32.0 h1:rIkQfkCOVKc1OiRCNcSDD8ml5RJlZbH/Xsq7lbpynwc= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.32.0/go.mod h1:RD2SsorTmYhF6HkTmDw7KmPYQk8OBYwTkuasChwv7R4= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.56.0 h1:O2sXMyJh8b7devAGdE+163xtRurt0RVpB6DIzX5vGfg= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.56.0/go.mod h1:hEpiGU18xf70qb3jbTcIggWAiEfX/cOIVc2OTe4OegA= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.56.0 h1:0YP0+/ixwu+Uqeu/FGiBZNQ19huiUxxiPXIc9WsLKuQ= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.56.0/go.mod h1:6ZZMQhZKDvUvkJw2rc+oDP90tMMzuU/J+5HG1ZmPOmE= 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= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= +github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260116142910-60249400e523 h1:pQUezn45oyv/8VcOQvPCg2851EIIusY0YKkJhAXsy2I= +github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260116142910-60249400e523/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI= +github.com/RoaringBitmap/roaring/v2 v2.18.0 h1:h7sS0VqCkfBMGgcHaudJFB4FE6Td71H6svRB2poRnGY= +github.com/RoaringBitmap/roaring/v2 v2.18.0/go.mod h1:eq4wdNXxtJIS/oikeCzdX1rBzek7ANzbth041hrU8Q4= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI= -github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI= +github.com/VictoriaMetrics/fastcache v1.13.0 h1:AW4mheMR5Vd9FkAPUv+NH6Nhw+fmbTMGMsNAoA/+4G0= +github.com/VictoriaMetrics/fastcache v1.13.0/go.mod h1:hHXhl4DA2fTL2HTZDJFXWgW0LNjo6B+4aj2Wmng3TjU= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= -github.com/adlio/schema v1.3.6 h1:k1/zc2jNfeiZBA5aFTRy37jlBIuCkXCm0XmvpzCKI9I= -github.com/adlio/schema v1.3.6/go.mod h1:qkxwLgPBd1FgLRHYVCmQT/rrBr3JH38J9LjmVzWNudg= +github.com/adlio/schema v1.4.0 h1:dekxG6P0my/bPvlyWzMULelR2Xej8RGErlnJcoY5ddw= +github.com/adlio/schema v1.4.0/go.mod h1:3/ojUldWBCWp4e+6VN9ets6unG5WdqbjF7vyzM0zTVQ= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -98,10 +90,48 @@ 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/aws/aws-sdk-go-v2 v1.41.6 h1:1AX0AthnBQzMx1vbmir3Y4WsnJgiydmnJjiLu+LvXOg= +github.com/aws/aws-sdk-go-v2 v1.41.6/go.mod h1:dy0UzBIfwSeot4grGvY1AqFWN5zgziMmWGzysDnHFcQ= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.9 h1:adBsCIIpLbLmYnkQU+nAChU5yhVTvu5PerROm+/Kq2A= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.9/go.mod h1:uOYhgfgThm/ZyAuJGNQ5YgNyOlYfqnGpTHXvk3cpykg= +github.com/aws/aws-sdk-go-v2/config v1.32.14 h1:opVIRo/ZbbI8OIqSOKmpFaY7IwfFUOCCXBsUpJOwDdI= +github.com/aws/aws-sdk-go-v2/config v1.32.14/go.mod h1:U4/V0uKxh0Tl5sxmCBZ3AecYny4UNlVmObYjKuuaiOo= +github.com/aws/aws-sdk-go-v2/credentials v1.19.14 h1:n+UcGWAIZHkXzYt87uMFBv/l8THYELoX6gVcUvgl6fI= +github.com/aws/aws-sdk-go-v2/credentials v1.19.14/go.mod h1:cJKuyWB59Mqi0jM3nFYQRmnHVQIcgoxjEMAbLkpr62w= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21 h1:NUS3K4BTDArQqNu2ih7yeDLaS3bmHD0YndtA6UP884g= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21/go.mod h1:YWNWJQNjKigKY1RHVJCuupeWDrrHjRqHm0N9rdrWzYI= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.22 h1:GmLa5Kw1ESqtFpXsx5MmC84QWa/ZrLZvlJGa2y+4kcQ= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.22/go.mod h1:6sW9iWm9DK9YRpRGga/qzrzNLgKpT2cIxb7Vo2eNOp0= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.22 h1:dY4kWZiSaXIzxnKlj17nHnBcXXBfac6UlsAx2qL6XrU= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.22/go.mod h1:KIpEUx0JuRZLO7U6cbV204cWAEco2iC3l061IxlwLtI= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 h1:qYQ4pzQ2Oz6WpQ8T3HvGHnZydA72MnLuFK9tJwmrbHw= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6/go.mod h1:O3h0IK87yXci+kg6flUKzJnWeziQUKciKrLjcatSNcY= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.23 h1:FPXsW9+gMuIeKmz7j6ENWcWtBGTe1kH8r9thNt5Uxx4= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.23/go.mod h1:7J8iGMdRKk6lw2C+cMIphgAnT8uTwBwNOsGkyOCm80U= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.8 h1:HtOTYcbVcGABLOVuPYaIihj6IlkqubBwFj10K5fxRek= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.8/go.mod h1:VsK9abqQeGlzPgUr+isNWzPlK2vKe9INMLWnY65f5Xs= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.14 h1:xnvDEnw+pnj5mctWiYuFbigrEzSm35x7k4KS/ZkCANg= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.14/go.mod h1:yS5rNogD8e0Wu9+l3MUwr6eENBzEeGejvINpN5PAYfY= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.22 h1:PUmZeJU6Y1Lbvt9WFuJ0ugUK2xn6hIWUBBbKuOWF30s= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.22/go.mod h1:nO6egFBoAaoXze24a2C0NjQCvdpk8OueRoYimvEB9jo= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.22 h1:SE+aQ4DEqG53RRCAIHlCf//B2ycxGH7jFkpnAh/kKPM= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.22/go.mod h1:ES3ynECd7fYeJIL6+oax+uIEljmfps0S70BaQzbMd/o= +github.com/aws/aws-sdk-go-v2/service/s3 v1.100.0 h1:7G26Sae6PMKn4kMcU5JzNfrm1YrKwyOhowXPYR2WiWY= +github.com/aws/aws-sdk-go-v2/service/s3 v1.100.0/go.mod h1:Fw9aqhJicIVee1VytBBjH+l+5ov6/PhbtIK/u3rt/ls= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.9 h1:QKZH0S178gCmFEgst8hN0mCX1KxLgHBKKY/CLqwP8lg= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.9/go.mod h1:7yuQJoT+OoH8aqIxw9vwF+8KpvLZ8AWmvmUWHsGQZvI= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.15 h1:lFd1+ZSEYJZYvv9d6kXzhkZu07si3f+GQ1AaYwa2LUM= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.15/go.mod h1:WSvS1NLr7JaPunCXqpJnWk1Bjo7IxzZXrZi1QQCkuqM= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.19 h1:dzztQ1YmfPrxdrOiuZRMF6fuOwWlWpD2StNLTceKpys= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.19/go.mod h1:YO8TrYtFdl5w/4vmjL8zaBSsiNp3w0L1FfKVKenZT7w= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.10 h1:p8ogvvLugcR/zLBXTXrTkj0RYBUdErbMnAFFp12Lm/U= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.10/go.mod h1:60dv0eZJfeVXfbT1tFJinbHrDfSJ2GZl4Q//OSSNAVw= +github.com/aws/smithy-go v1.25.0 h1:Sz/XJ64rwuiKtB6j98nDIPyYrV1nVNJ4YU74gttcl5U= +github.com/aws/smithy-go v1.25.0/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= +github.com/benbjohnson/clock v1.3.5/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= @@ -111,8 +141,8 @@ github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ 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/bits-and-blooms/bitset v1.24.4 h1:95H15Og1clikBrKr/DuzMXkQzECs1M6hhoGXLwLQOZE= +github.com/bits-and-blooms/bitset v1.24.4/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/btcsuite/btcd v0.24.2 h1:aLmxPguqxza+4ag8R1I2nnJjSu2iFn/kqtHTIImswcY= github.com/btcsuite/btcd v0.24.2/go.mod h1:5C8ChTkl5ejr3WHj8tkQSCmydiMEPB0ZhQhehpq7Dgg= github.com/btcsuite/btcd/btcec/v2 v2.3.5 h1:dpAlnAwmT1yIBm3exhT1/8iUSD98RDJM5vqJVQDQLiU= @@ -121,22 +151,22 @@ github.com/btcsuite/btcd/btcutil v1.1.6 h1:zFL2+c3Lb9gEgqKNzowKUPQNb8jV7v5Oaodi/ github.com/btcsuite/btcd/btcutil v1.1.6/go.mod h1:9dFymx8HpuLqBnsPELrImQeTQfKBQqzqGbbV3jK55aE= github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -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.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.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA= -github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= +github.com/bytedance/gopkg v0.1.4 h1:oZnQwnX82KAIWb7033bEwtxvTqXcYMxDBaQxo5JJHWM= +github.com/bytedance/gopkg v0.1.4/go.mod h1:v1zWfPm21Fb+OsyXN2VAHdL6TBb2L88anLQgdyje6R4= +github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE= +github.com/bytedance/sonic v1.15.0/go.mod h1:tFkWrPz0/CUCLEF4ri4UkHekCIcdnkqXw9VduqpJh0k= +github.com/bytedance/sonic/loader v0.5.1 h1:Ygpfa9zwRCCKSlrp5bBP/b/Xzc3VxsAW+5NIYXrOOpI= +github.com/bytedance/sonic/loader v0.5.1/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= 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= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= +github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -148,9 +178,8 @@ github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6D github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4= -github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= -github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= +github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M= +github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= @@ -158,111 +187,120 @@ 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/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 h1:aBangftG7EVZoUb69Os8IaYg++6uMOdKK83QtkkvJik= +github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2/go.mod h1:qwXFYgsP6T7XnJtbKlf1HP8AjxZZyzxMmc+Lq5GjlU4= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= 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/errors v1.13.0 h1:BoCcJeiP9hpBJDETkX19qi8Tb8So37srSsp3stTaDMQ= +github.com/cockroachdb/errors v1.13.0/go.mod h1:bjxt/4E5+OyuAnacpTIU9rn2mzPu1VlthvHP+xpROq0= github.com/cockroachdb/fifo v0.0.0-20240816210425-c5d0cb0b6fc0 h1:pU88SPhIFid6/k0egdR5V6eALQYq2qbSmukrkgIh/0A= github.com/cockroachdb/fifo v0.0.0-20240816210425-c5d0cb0b6fc0/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 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/redact v1.1.8 h1:8eVLLj6juKxiKrAEw2b8cJvNqWq++U8WOfQFuL7KTaA= +github.com/cockroachdb/redact v1.1.8/go.mod h1:GceHHpJ0rMDpYARL5In88Alq/xMBUtVlz7Qxix6ZVkw= 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.19 h1:vNdtCkvhuwUlrcLPAyigV7lQpmmo+tAq8CsB8gZjEYw= -github.com/cometbft/cometbft v0.38.19/go.mod h1:UCu8dlHqvkAsmAFmWDRWNZJPlu6ya2fTWZlDrWsivwo= +github.com/cometbft/cometbft v0.39.3 h1:UegHXskZNomsijmm29nL5NkeXtnzkme6fg+q1hPQnEI= +github.com/cometbft/cometbft v0.39.3/go.mod h1:PmNfvtw256BC41ad0FABts236CSZnvZ0kjPOciBwTdM= 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/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/consensys/gnark-crypto v0.18.1 h1:RyLV6UhPRoYYzaFnPQA4qK3DyuDgkTgskDdoGqFt3fI= +github.com/consensys/gnark-crypto v0.18.1/go.mod h1:L3mXGFTe1ZN+RSJ+CLjUt9x7PNdx8ubaYfDROyp2Z8c= +github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4= +github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= +github.com/cosmos/btree v1.0.0 h1:V3OdIzTQw2yE7f6pD6FfA9j2/YLj1UpB9MdY0zU3v3k= +github.com/cosmos/btree v1.0.0/go.mod h1:BZML+flLn4d3MOa4POmzDWf5HQ7EGh0y1OLlfhh7A0k= github.com/cosmos/cosmos-db v1.1.3 h1:7QNT77+vkefostcKkhrzDK9uoIEryzFrU9eoMeaQOPY= github.com/cosmos/cosmos-db v1.1.3/go.mod h1:kN+wGsnwUJZYn8Sy5Q2O0vCYA99MJllkKASbs6Unb9U= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= -github.com/cosmos/cosmos-sdk v0.53.4 h1:kPF6vY68+/xi1/VebSZGpoxQqA52qkhUzqkrgeBn3Mg= -github.com/cosmos/cosmos-sdk v0.53.4/go.mod h1:7U3+WHZtI44dEOnU46+lDzBb2tFh1QlMvi8Z5JugopI= +github.com/cosmos/cosmos-sdk v0.54.3 h1:oUxbIACmHZV13IZXl59y+mIEOCFlUAjXV9p1rqrYcEg= +github.com/cosmos/cosmos-sdk v0.54.3/go.mod h1:Unt21RO+q1EebU6gcUPKYVzpAQSr4KIHjaOmjpz2twA= +github.com/cosmos/cosmos-sdk/store/v2 v2.0.0 h1:5CFXBU5cHIvxMpz5QBrTwR5DL/W3uZL2BYYMoDp4siY= +github.com/cosmos/cosmos-sdk/store/v2 v2.0.0/go.mod h1:XyRyi5fGjIcokBqS1cyA8/QVbVNy4ui8hmpk1gezuHo= +github.com/cosmos/cosmos-sdk/tools/systemtests v0.0.0-20260505173942-e77c24c3eda7 h1:ohumeEjaD6E0R8lGMz3KdXNKbmb098Zm/Qst+7foKHU= +github.com/cosmos/cosmos-sdk/tools/systemtests v0.0.0-20260505173942-e77c24c3eda7/go.mod h1:KODZKT+GdXHy/pZZ3u0OgQAykofeFRhL0F0Ks5fOqxE= 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 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/go-ethereum v1.17.2-cosmos-0 h1:V1vadF7/miUwwbNh3iiqNM51aHAG/5mzRCeIdcdostw= +github.com/cosmos/go-ethereum v1.17.2-cosmos-0/go.mod h1:KHcRXfGOUfUmKg51IhQ0IowiqZ6PqZf08CMtk0g5K1o= 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= -github.com/cosmos/gogoproto v1.7.0 h1:79USr0oyXAbxg3rspGh/m4SWNyoz/GLaAh0QlCe2fro= -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.1-0.20250909102629-ed3b125c7b6f h1:I5t5Tuewh6E9icYCtS4aSwyzIEvr2iBods08Hq+GBME= -github.com/cosmos/ibc-go/v10 v10.3.1-0.20250909102629-ed3b125c7b6f/go.mod h1:a74pAPUSJ7NewvmvELU74hUClJhwnmm5MGbEaiTw/kE= +github.com/cosmos/gogoproto v1.7.2 h1:5G25McIraOC0mRFv9TVO139Uh3OklV2hczr13KKVHCA= +github.com/cosmos/gogoproto v1.7.2/go.mod h1:8S7w53P1Y1cHwND64o0BnArT6RmdgIvsBuco6uTllsk= +github.com/cosmos/iavl v1.2.8 h1:55F96BGUJ7KT7h+Ky/cEqS+pEvhFqsU4O8Th3F0N1js= +github.com/cosmos/iavl v1.2.8/go.mod h1:FRHN4tO+6crf0p2zsqye+nAbsMgiwdkxpWm18DyP6+Y= +github.com/cosmos/ibc-go/v11 v11.0.0 h1:9EIehi88hNP1cCU83NC+J8UXNn+05YZt9eqmnzCQLSg= +github.com/cosmos/ibc-go/v11 v11.0.0/go.mod h1:iWlzLuCu+ctVbQwoVf5z51HE5e/NE8/pwnLVVDmP++4= 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.16.0 h1:YKlWPG9NnGZIEUb2bEfZ6zhON1CHlNTg0QKRRGcNEd0= -github.com/cosmos/ledger-cosmos-go v0.16.0/go.mod h1:WrM2xEa8koYoH2DgeIuZXNarF7FGuZl3mrIOnp3Dp0o= +github.com/cosmos/ledger-cosmos-go v1.0.0 h1:jNKW89nPf0vR0EkjHG8Zz16h6p3zqwYEOxlHArwgYtw= +github.com/cosmos/ledger-cosmos-go v1.0.0/go.mod h1:mGaw2wDOf+Z6SfRJsMGxU9DIrBa4du0MAiPlpPhLAOE= 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-eth-kzg v1.5.0 h1:FYRiJMJG2iv+2Dy3fi14SVGjcPteZ5HAAUe4YWlJygc= +github.com/crate-crypto/go-eth-kzg v1.5.0/go.mod h1:J9/u5sWfznSObptgfa92Jq8rTswn6ahQWEuiLHOjCUI= github.com/creachadair/tomledit v0.0.29 h1:dB5CbdwJMpn/fmfAPTAAleXF/KJwY0Ggc1eL/zvZRgk= github.com/creachadair/tomledit v0.0.29/go.mod h1:4SoTXxzHgvzHRMIJPw+o6zK/yXii4VjLrb6/3gCQnyA= 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.2.2 h1:774zMFJrqaeYCK2W57BgAem/MLi6mtSE47MB6BOJ0i0= -github.com/danieljoos/wincred v1.2.2/go.mod h1:w7w4Utbrz8lqeMbDAK0lkNJUv5sAOkFi7nd/ogr0Uh8= +github.com/danieljoos/wincred v1.2.3 h1:v7dZC2x32Ut3nEfRH+vhoZGvN72+dQ/snVXo/vMFLdQ= +github.com/danieljoos/wincred v1.2.3/go.mod h1:6qqX0WNrS4RzPZ1tnroDzq9kY3fu1KwE7MRLQK4X0bs= 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/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= +github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= +github.com/dchest/siphash v1.2.3 h1:QXwFc8cFOR2dSa/gE6o/HokBMWtLUaNDVd+22aKHeEA= +github.com/dchest/siphash v1.2.3/go.mod h1:0NvQU092bT0ipiFN++/rXm69QG9tVxLAlQHIXMPAkHc= 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/decred/dcrd/dcrec/secp256k1/v4 v4.4.1 h1:5RVFMOWjMyRy8cARdy79nAmgYw3hK/4HUq48LQ6Wwqo= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.1/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40= 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= -github.com/dgraph-io/ristretto/v2 v2.1.0/go.mod h1:uejeqfYXpUomfse0+lO+13ATz4TypQYLJZzBSAemuB4= +github.com/dgraph-io/badger/v4 v4.9.1 h1:DocZXZkg5JJHJPtUErA0ibyHxOVUDVoXLSCV6t8NC8w= +github.com/dgraph-io/badger/v4 v4.9.1/go.mod h1:5/MEx97uzdPUHR4KtkNt8asfI2T4JiEiQlV7kWUo8c0= +github.com/dgraph-io/ristretto/v2 v2.4.0 h1:I/w09yLjhdcVD2QV192UJcq8dPBaAJb9pOuMyNy0XlU= +github.com/dgraph-io/ristretto/v2 v2.4.0/go.mod h1:0KsrXtXvnv0EqnzyowllbVJB8yBonswa2lTCK2gGo9E= 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.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= -github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= +github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da h1:aIftn67I1fkbMa512G+w+Pxci9hJPB8oMnkcP3iZF38= +github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94= +github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE= 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/dunglas/httpsfv v1.1.0 h1:Jw76nAyKWKZKFrpMMcL76y35tOpYHqQPzHQiwDvpe54= +github.com/dunglas/httpsfv v1.1.0/go.mod h1:zID2mqw9mFsnt7YC3vYQ9/cjq30q41W+1AnDwH8TiMg= 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.7.0 h1:bnQc8+GMnidJZA8zc6lLEAb4xNrIqHwO+9TzqvtQZPo= -github.com/dvsekhvalnov/jose2go v1.7.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= +github.com/dvsekhvalnov/jose2go v1.8.0 h1:LqkkVKAlHFfH9LOEl5fe4p/zL02OhWE7pCufMBG2jLA= +github.com/dvsekhvalnov/jose2go v1.8.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= +github.com/ebitengine/purego v0.10.0 h1:QIw4xfpWT6GWTzaW5XEKy3HXoqrJGx1ijYHzTF0/ISU= +github.com/ebitengine/purego v0.10.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= -github.com/emicklei/dot v1.8.0 h1:HnD60yAKFAevNeT+TPYr9pb8VB9bqdeSo0nzwIW6IOI= -github.com/emicklei/dot v1.8.0/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= +github.com/emicklei/dot v1.11.0 h1:zsrhCuFHAJge/aZIC4N4LdHy5tqYu4tWEaUzIwdYj4Y= +github.com/emicklei/dot v1.11.0/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -270,16 +308,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/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA= +github.com/envoyproxy/go-control-plane/envoy v1.37.0 h1:u3riX6BoYRfF4Dr7dwSOroNfdSbEPe9Yyl09/B6wBrQ= +github.com/envoyproxy/go-control-plane/envoy v1.37.0/go.mod h1:DReE9MMrmecPy+YvQOAOHNYMALuowAnbjjEMkkWOi6A= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -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-verkle v0.2.2 h1:I2W0WjnrFUIzzVPwm8ykY+7pL2d4VhlsePn4j7cnFk8= -github.com/ethereum/go-verkle v0.2.2/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk= +github.com/envoyproxy/protoc-gen-validate v1.3.3 h1:MVQghNeW+LZcmXe7SY1V36Z+WFMDjpqGAGacLe2T0ds= +github.com/envoyproxy/protoc-gen-validate v1.3.3/go.mod h1:TsndJ/ngyIdQRhMcVVGDDHINPLWB7C82oDArY51KfB0= +github.com/ethereum/c-kzg-4844/v2 v2.1.6 h1:xQymkKCT5E2Jiaoqf3v4wsNgjZLY0lRSkZn27fRjSls= +github.com/ethereum/c-kzg-4844/v2 v2.1.6/go.mod h1:8HMkUZ5JRv4hpw/XUrYWSQNAUzhHMg2UDb/U+5m+XNw= +github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab h1:rvv6MJhy07IMfEKuARQ9TKojGqLVNxQajaXEp/BoqSk= +github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab/go.mod h1:IuLm4IsPipXKF7CW5Lzf68PIbZ5yl7FFd74l/E0o9A8= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= @@ -288,6 +326,8 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/ferranbt/fastssz v0.1.4 h1:OCDB+dYDEQDvAgtAGnTSidK1Pe2tW3nFV40XyMkTeDY= github.com/ferranbt/fastssz v0.1.4/go.mod h1:Ea3+oeoRGGLGm5shYAeDgu6PGUlcvQhE2fILyD9+tGg= +github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg= +github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= @@ -297,18 +337,19 @@ github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7z github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= -github.com/getsentry/sentry-go v0.35.0 h1:+FJNlnjJsZMG3g0/rmmP7GiKjQoUF5EXfEtBwtPtkzY= -github.com/getsentry/sentry-go v0.35.0/go.mod h1:C55omcY9ChRQIUcVcGcs+Zdy4ZpQGvNJ7JYHIoSWOtE= +github.com/getsentry/sentry-go v0.46.0 h1:mbdDaarbUdOt9X+dx6kDdntkShLEX3/+KyOsVDTPDj0= +github.com/getsentry/sentry-go v0.46.0/go.mod h1:evVbw2qotNUdYG8KxXbAdjOQWWvWIwKxpjdZZIvcIPw= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= 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.1.2 h1:TK/7NqRQZfgAh+Td8AlsrvtPoUyiHh0LqVvokh+1vHI= -github.com/go-jose/go-jose/v4 v4.1.2/go.mod h1:22cg9HWM1pOlnRiY+9cQYJ9XHmya1bYW8OeDM6Ku6Oo= +github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= +github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= 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= @@ -320,8 +361,8 @@ github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBj 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-logfmt/logfmt v0.6.1 h1:4hvbpePJKnIzH1B+8OR/JPbTx37NktoI9LE2QZBBkvE= +github.com/go-logfmt/logfmt v0.6.1/go.mod h1:EV2pOAQoZaT1ZXZbqDl5hrymndi4SY9ED9/z6CO0XAk= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -339,14 +380,13 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= -github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro= +github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= 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.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= @@ -359,13 +399,11 @@ 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-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI= +github.com/golang-jwt/jwt/v4 v4.5.2/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= @@ -423,10 +461,10 @@ github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ 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.15.0 h1:SyjDc1mGgZU5LncH8gimWo9lW1DtIfPibOG81vgd/bo= -github.com/googleapis/gax-go/v2 v2.15.0/go.mod h1:zVVkkxAQHa1RQpg9z2AUCMnKhi0Qld9rcmyfL1OZhoc= +github.com/googleapis/enterprise-certificate-proxy v0.3.14 h1:yh8ncqsbUY4shRD5dA6RlzjJaT4hi3kII+zYw8wmLb8= +github.com/googleapis/enterprise-certificate-proxy v0.3.14/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg= +github.com/googleapis/gax-go/v2 v2.22.0 h1:PjIWBpgGIVKGoCXuiCoP64altEJCj3/Ei+kSU5vlZD4= +github.com/googleapis/gax-go/v2 v2.22.0/go.mod h1:irWBbALSr0Sk3qlqb9SyJ1h68WjgeFuiOzI4Rqw5+aY= 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= @@ -439,6 +477,10 @@ github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grafana/pyroscope-go v1.2.7 h1:VWBBlqxjyR0Cwk2W6UrE8CdcdD80GOFNutj0Kb1T8ac= +github.com/grafana/pyroscope-go v1.2.7/go.mod h1:o/bpSLiJYYP6HQtvcoVKiE9s5RiNgjYTj1DhiddP2Pc= +github.com/grafana/pyroscope-go/godeltaprof v0.1.9 h1:c1Us8i6eSmkW+Ez05d3co8kasnuOY813tbMN8i/a3Og= +github.com/grafana/pyroscope-go/godeltaprof v0.1.9/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= @@ -447,8 +489,12 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= +github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.72 h1:vTCWu1wbdYo7PEZFem/rlr01+Un+wwVmI7wiegFdRLk= +github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.72/go.mod h1:Vn+BBgKQHVQYdVQ4NZDICE1Brb+JfaONyDHr3q07oQc= 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= @@ -458,8 +504,8 @@ github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng 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-getter v1.8.6 h1:9sQboWULaydVphxc4S64oAI4YqpuCk7nPmvbk131ebY= +github.com/hashicorp/go-getter v1.8.6/go.mod h1:nVH12eOV2P58dIiL3rsU6Fh3wLeJEKBOJzhMmzlSWoo= 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= @@ -473,17 +519,14 @@ github.com/hashicorp/go-plugin v1.7.0 h1:YghfQH/0QmPNc/AZMTFE3ac8fipZyZECHdDPshf github.com/hashicorp/go-plugin v1.7.0/go.mod h1:BExt6KEaIYx804z8k4gRzRLEvxKVb+kn0NMcihqOqb8= 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= +github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -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-version v1.9.0 h1:CeOIz6k+LoN3qX9Z0tyQrPtiB1DFYRPfCIBtaXPSCnA= +github.com/hashicorp/go-version v1.9.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= @@ -499,8 +542,8 @@ 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/billy v0.0.0-20250707135307-f2f9b9aae7db h1:IZUYC/xb3giYwBLMnr8d0TGTzPKFGNTCGgGLoyeX330= +github.com/holiman/billy v0.0.0-20250707135307-f2f9b9aae7db/go.mod h1:xTEYN9KCHxuYHs+NmrmzFcnvHMzLLNiGFafCb1n3Mfg= 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= @@ -522,13 +565,17 @@ 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/ipfs/go-cid v0.5.0 h1:goEKKhaGm0ul11IHA7I6p1GmKz8kEYniqFopaB5Otwg= +github.com/ipfs/go-cid v0.5.0/go.mod h1:0L7vmeNXpQpUS9vt+yEARkJ8rOg43DF3iPgn4GIN0mk= 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/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= +github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= +github.com/jhump/protoreflect v1.18.0 h1:TOz0MSR/0JOZ5kECB/0ufGnC2jdsgZ123Rd/k4Z5/2w= +github.com/jhump/protoreflect v1.18.0/go.mod h1:ezWcltJIVF4zYdIFM+D/sHV4Oh5LNU08ORzCGfwvTz8= +github.com/jhump/protoreflect/v2 v2.0.0-beta.1 h1:Dw1rslK/VotaUGYsv53XVWITr+5RCPXfvvlGrM/+B6w= +github.com/jhump/protoreflect/v2 v2.0.0-beta.1/go.mod h1:D9LBEowZyv8/iSu97FU2zmXG3JxVTmNw21mu63niFzU= 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= @@ -548,17 +595,17 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= -github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= -github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= -github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= -github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE= +github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= +github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/koron/go-ssdp v0.0.6 h1:Jb0h04599eq/CY7rB5YEqPS83HmRfHP2azkxMN2rFtU= +github.com/koron/go-ssdp v0.0.6/go.mod h1:0R9LfRJGek1zWTjN3JUNlm5INCDYGpRDfAptnct63fI= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -570,48 +617,74 @@ github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+ 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/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= +github.com/lib/pq v1.12.3 h1:tTWxr2YLKwIvK90ZXEw8GP7UFHtcbTtty8zsI+YjrfQ= +github.com/lib/pq v1.12.3/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA= +github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= +github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= +github.com/libp2p/go-flow-metrics v0.2.0 h1:EIZzjmeOE6c8Dav0sNv35vhZxATIXWZg6j/C08XmmDw= +github.com/libp2p/go-flow-metrics v0.2.0/go.mod h1:st3qqfu8+pMfh+9Mzqb2GTiwrAGjIPszEjZmtksN8Jc= +github.com/libp2p/go-libp2p v0.47.0 h1:qQpBjSCWNQFF0hjBbKirMXE9RHLtSuzTDkTfr1rw0yc= +github.com/libp2p/go-libp2p v0.47.0/go.mod h1:s8HPh7mMV933OtXzONaGFseCg/BE//m1V34p3x4EUOY= +github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94= +github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8= +github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= +github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg= +github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= +github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM= +github.com/libp2p/go-netroute v0.3.0 h1:nqPCXHmeNmgTJnktosJ/sIef9hvwYCrsLxXmfNks/oc= +github.com/libp2p/go-netroute v0.3.0/go.mod h1:Nkd5ShYgSMS5MUKy/MU2T57xFoOKvvLR92Lic48LEyA= +github.com/libp2p/go-reuseport v0.4.0 h1:nR5KU7hD0WxXCJbmw7r2rhRYruNRl2koHw8fQscQm2s= +github.com/libp2p/go-reuseport v0.4.0/go.mod h1:ZtI03j/wO5hZVDFo2jKywN6bYKWLOy8Se6DrI2E1cLU= +github.com/libp2p/go-yamux/v5 v5.0.1 h1:f0WoX/bEF2E8SbE4c/k1Mo+/9z0O4oC/hWEA+nfYRSg= +github.com/libp2p/go-yamux/v5 v5.0.1/go.mod h1:en+3cdX51U0ZslwRdRLrvQsdayFt3TSUKvBGErzpWbU= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= -github.com/linxGnu/grocksdb v1.10.1 h1:YX6gUcKvSC3d0s9DaqgbU+CRkZHzlELgHu1Z/kmtslg= -github.com/linxGnu/grocksdb v1.10.1/go.mod h1:C3CNe9UYc9hlEM2pC82AqiGS3LRW537u9LFV4wIZuHk= +github.com/linxGnu/grocksdb v1.10.7 h1:fCi4qvZWo04VgFwGWmO8HQJgUVounJBy+C2TMVPU/ho= +github.com/linxGnu/grocksdb v1.10.7/go.mod h1:OLQKZwiKwaJiAVCsOzWKvwiLwfZ5Vz8Md5TYR7t7pM8= +github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e h1:Q6MvJtQK/iRcRtzAscm/zF23XxJlbECiGPyRicsX+Ak= +github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= +github.com/marcopolo/simnet v0.0.4 h1:50Kx4hS9kFGSRIbrt9xUS3NJX33EyPqHVmpXvaKLqrY= +github.com/marcopolo/simnet v0.0.4/go.mod h1:tfQF1u2DmaB6WHODMtQaLtClEf3a296CKQLq5gAsIS0= +github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= +github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -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-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4= +github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -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/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= -github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= +github.com/miekg/dns v1.1.66 h1:FeZXOS3VCVsKnEAd+wBkjMC3D2K+ww66Cq3VnCINuJE= +github.com/miekg/dns v1.1.66/go.mod h1:jGFzBsSNbJw6z1HYut1RKBKHA9PBdxeHrZG8J+gC2WE= +github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= +github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms= +github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= +github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b/go.mod h1:lxPUiZwKoFL8DUUmalo2yJJUCxbPKtm8OKfqr2/FTNU= +github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdnNMiD9ZejrlswWrCpBEZgWOiTrc= +github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s= +github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= +github.com/minio/highwayhash v1.0.4 h1:asJizugGgchQod2ja9NJlGOWq4s7KsAWr5XUc9Clgl4= +github.com/minio/highwayhash v1.0.4/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= +github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= 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= @@ -620,12 +693,41 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua 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/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs= +github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 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/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mr-tron/base58 v1.3.0 h1:K6Y13R2h+dku0wOqKtecgRnBUBPrZzLZy5aIj8lCcJI= +github.com/mr-tron/base58 v1.3.0/go.mod h1:2BuubE67DCSWwVfx37JWNG8emOC0sHEU4/HpcYgCLX8= +github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM= +github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw= 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/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= +github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= +github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= +github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= +github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= +github.com/multiformats/go-multiaddr v0.16.1 h1:fgJ0Pitow+wWXzN9do+1b8Pyjmo8m5WhGfzpL82MpCw= +github.com/multiformats/go-multiaddr v0.16.1/go.mod h1:JSVUmXDjsVFiW7RjIFMP7+Ev+h1DTbiJgVeTV/tcmP0= +github.com/multiformats/go-multiaddr-dns v0.4.1 h1:whi/uCLbDS3mSEUMb1MsoT4uzUeZB0N32yzufqS0i5M= +github.com/multiformats/go-multiaddr-dns v0.4.1/go.mod h1:7hfthtB4E4pQwirrz+J0CcDUfbWzTqEzVyYKKIKpgkc= +github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= +github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= +github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= +github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk= +github.com/multiformats/go-multicodec v0.9.1 h1:x/Fuxr7ZuR4jJV4Os5g444F7xC4XmyUaT/FWtE+9Zjo= +github.com/multiformats/go-multicodec v0.9.1/go.mod h1:LLWNMtyV5ithSBUo3vFIMaeDy+h3EbkMTek1m+Fybbo= +github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= +github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U= +github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= +github.com/multiformats/go-multistream v0.6.1 h1:4aoX5v6T+yWmc2raBHsTvzmFhOI8WVOer28DeBBEYdQ= +github.com/multiformats/go-multistream v0.6.1/go.mod h1:ksQf6kqHAb6zIsyw7Zm+gAuVo57Qbq84E27YlYqavqw= +github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= +github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -644,15 +746,13 @@ github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= -github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a h1:dlRvE5fWabOchtH7znfiFCcOvmIYgOeAS5ifBXBlh9Q= -github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= +github.com/oasisprotocol/curve25519-voi v0.0.0-20251114093237-2ab5a27a1729 h1:yfQ2sO9WJXUAIUR+g7NUkxJSKCAFJcR5sUDu+ZmjTZI= +github.com/oasisprotocol/curve25519-voi v0.0.0-20251114093237-2ab5a27a1729/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= -github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= +github.com/oklog/run v1.2.0 h1:O8x3yXwah4A73hJdlrwo/2X6J62gE5qTMusH0dvz60E= +github.com/oklog/run v1.2.0/go.mod h1:mgDbKRSwPhJfesJ4PntqFUbKQRZ50NgmZTSPlFA0YFk= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= @@ -672,10 +772,10 @@ github.com/onsi/gomega v1.38.0/go.mod h1:OcXcwId0b9QsE7Y49u+BTrL4IdKOBOKnD6VQNTJ 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= -github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= -github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= -github.com/opencontainers/runc v1.1.12 h1:BOIssBaW1La0/qbNZHXOOa71dZfZEQOzW7dqQf3phss= -github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma/O44Ekby9FK8= +github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= +github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= +github.com/opencontainers/runc v1.2.8 h1:RnEICeDReapbZ5lZEgHvj7E9Q3Eex9toYmaGBsbvU5Q= +github.com/opencontainers/runc v1.2.8/go.mod h1:cC0YkmZcuvr+rtBZ6T7NBoVbMGNAdLa/21vIElJDOzI= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= @@ -690,26 +790,65 @@ github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIw github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= -github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 h1:Dx7Ovyv/SFnMFw3fD4oEoeorXc6saIiQ23LrGLth0Gw= -github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/petermattis/goid v0.0.0-20250813065127-a731cc31b4fe/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/petermattis/goid v0.0.0-20260113132338-7c7de50cc741 h1:KPpdlQLZcHfTMQRi6bFQ7ogNO0ltFT4PmtwTLW4W+14= +github.com/petermattis/goid v0.0.0-20260113132338-7c7de50cc741/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= 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/datachannel v1.5.10 h1:ly0Q26K1i6ZkGf42W7D4hQYR90pZwzFOjTq5AuCKk4o= +github.com/pion/datachannel v1.5.10/go.mod h1:p/jJfC9arb29W7WrxyKbepTU20CFgyx5oLo8Rs4Py/M= 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/dtls/v2 v2.2.12 h1:KP7H5/c1EiVAAKUmXyCzPiQe5+bCJrpOeKg/L05dunk= +github.com/pion/dtls/v2 v2.2.12/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE= +github.com/pion/dtls/v3 v3.1.2 h1:gqEdOUXLtCGW+afsBLO0LtDD8GnuBBjEy6HRtyofZTc= +github.com/pion/dtls/v3 v3.1.2/go.mod h1:Hw/igcX4pdY69z1Hgv5x7wJFrUkdgHwAn/Q/uo7YHRo= +github.com/pion/ice/v4 v4.0.10 h1:P59w1iauC/wPk9PdY8Vjl4fOFL5B+USq1+xbDcN6gT4= +github.com/pion/ice/v4 v4.0.10/go.mod h1:y3M18aPhIxLlcO/4dn9X8LzLLSma84cx6emMSu14FGw= +github.com/pion/interceptor v0.1.40 h1:e0BjnPcGpr2CFQgKhrQisBU7V3GXK6wrfYrGYaU6Jq4= +github.com/pion/interceptor v0.1.40/go.mod h1:Z6kqH7M/FYirg3frjGJ21VLSRJGBXB/KqaTIrdqnOic= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= +github.com/pion/logging v0.2.4 h1:tTew+7cmQ+Mc1pTBLKH2puKsOvhm32dROumOZ655zB8= +github.com/pion/logging v0.2.4/go.mod h1:DffhXTKYdNZU+KtJ5pyQDjvOAh/GsNSyv1lbkFbe3so= +github.com/pion/mdns/v2 v2.0.7 h1:c9kM8ewCgjslaAmicYMFQIde2H9/lrZpjBkN8VwoVtM= +github.com/pion/mdns/v2 v2.0.7/go.mod h1:vAdSYNAT0Jy3Ru0zl2YiW3Rm/fJCwIeM0nToenfOJKA= +github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= +github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= +github.com/pion/rtcp v1.2.15 h1:LZQi2JbdipLOj4eBjK4wlVoQWfrZbh3Q6eHtWtJBZBo= +github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0= +github.com/pion/rtp v1.8.19 h1:jhdO/3XhL/aKm/wARFVmvTfq0lC/CvN1xwYKmduly3c= +github.com/pion/rtp v1.8.19/go.mod h1:bAu2UFKScgzyFqvUKmbvzSdPr+NGbZtv6UB2hesqXBk= +github.com/pion/sctp v1.8.39 h1:PJma40vRHa3UTO3C4MyeJDQ+KIobVYRZQZ0Nt7SjQnE= +github.com/pion/sctp v1.8.39/go.mod h1:cNiLdchXra8fHQwmIoqw0MbLLMs+f7uQ+dGMG2gWebE= +github.com/pion/sdp/v3 v3.0.13 h1:uN3SS2b+QDZnWXgdr69SM8KB4EbcnPnPf2Laxhty/l4= +github.com/pion/sdp/v3 v3.0.13/go.mod h1:88GMahN5xnScv1hIMTqLdu/cOcUkj6a9ytbncwMCq2E= +github.com/pion/srtp/v3 v3.0.6 h1:E2gyj1f5X10sB/qILUGIkL4C2CqK269Xq167PbGCc/4= +github.com/pion/srtp/v3 v3.0.6/go.mod h1:BxvziG3v/armJHAaJ87euvkhHqWe9I7iiOy50K2QkhY= +github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4= +github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8= 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/stun/v3 v3.0.0 h1:4h1gwhWLWuZWOJIJR9s2ferRO+W3zA/b6ijOI6mKzUw= +github.com/pion/stun/v3 v3.0.0/go.mod h1:HvCN8txt8mwi4FBvS3EmDghW6aQJ24T+y+1TKjB5jyU= 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/pion/transport/v2 v2.2.4/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0= +github.com/pion/transport/v2 v2.2.10 h1:ucLBLE8nuxiHfvkFKnkDQRYWYfp8ejf4YBOPfaQpw6Q= +github.com/pion/transport/v2 v2.2.10/go.mod h1:sq1kSLWs+cHW9E+2fJP95QudkzbK7wscs8yYgQToO5E= +github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0= +github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo= +github.com/pion/transport/v4 v4.0.1 h1:sdROELU6BZ63Ab7FrOLn13M6YdJLY20wldXW2Cu2k8o= +github.com/pion/transport/v4 v4.0.1/go.mod h1:nEuEA4AD5lPdcIegQDpVLgNoDGreqM/YqmEx3ovP4jM= +github.com/pion/turn/v4 v4.0.2 h1:ZqgQ3+MjP32ug30xAbD6Mn+/K4Sxi3SdNOTFf+7mpps= +github.com/pion/turn/v4 v4.0.2/go.mod h1:pMMKP/ieNAG/fN5cZiN4SDuyKsXtNTr0ccN7IToA1zs= +github.com/pion/webrtc/v4 v4.1.2 h1:mpuUo/EJ1zMNKGE79fAdYNFZBX790KE7kQQpLMjjR54= +github.com/pion/webrtc/v4 v4.1.2/go.mod h1:xsCXiNAmMEjIdFxAYU0MbB3RwRieJsegSB2JZsGN+8U= 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= @@ -722,6 +861,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN 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= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -748,8 +889,8 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs= -github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA= +github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= +github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -757,15 +898,19 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= -github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= +github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc= +github.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo= github.com/prysmaticlabs/gohashtree v0.0.4-beta h1:H/EbCuXPeTV3lpKeXGPpEV9gsUpkqOOVnWapUyeWro4= github.com/prysmaticlabs/gohashtree v0.0.4-beta/go.mod h1:BFdtALS+Ffhg3lGQIHv9HDWuHS8cTvHZzrHWxwOtGOs= +github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8= +github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII= +github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw= +github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU= +github.com/quic-go/webtransport-go v0.10.0 h1:LqXXPOXuETY5Xe8ITdGisBzTYmUOy5eSj+9n4hLTjHI= +github.com/quic-go/webtransport-go v0.10.0/go.mod h1:LeGIXr5BQKE3UsynwVBeQrU1TPrbh73MGoC6jd+V7ow= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= -github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 h1:bsUq1dX0N8AOIL7EB/X911+m4EHsnWEHeJ0c+3TTBrg= +github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -775,21 +920,22 @@ github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7 github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= -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/rs/zerolog v1.35.0 h1:VD0ykx7HMiMJytqINBsKcbLS+BJ4WYjz+05us+LRTdI= +github.com/rs/zerolog v1.35.0/go.mod h1:EjML9kdfa/RMA7h/6z6pYmq1ykOuA8/mjWaEvGI+jcw= 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.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc= -github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik= +github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88eegjfxfHb4= +github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9tLLBmM4eneO6WwsI= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= -github.com/sasha-s/go-deadlock v0.3.5 h1:tNCOEEDG6tBqrNDOX35j/7hL5FcFViG6awUGROb2NsU= -github.com/sasha-s/go-deadlock v0.3.5/go.mod h1:bugP6EGbdGYObIlx7pUZtWqlvo8k9H6vCBBsiChJQ5U= +github.com/sasha-s/go-deadlock v0.3.9 h1:fiaT9rB7g5sr5ddNZvlwheclN9IP86eFW9WgqlEQV+w= +github.com/sasha-s/go-deadlock v0.3.9/go.mod h1:KuZj51ZFmx42q/mPaYbRk0P1xcwe697zsJKE03vD4/Y= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil/v4 v4.26.4 h1:B4SXVbcwTyrocPHEmWBC4uCYr4Xcu3MK1TXqbprAOWY= +github.com/shirou/gopsutil/v4 v4.26.4/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -801,15 +947,15 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1 github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= -github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw= -github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U= +github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s= -github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0= +github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= +github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= 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.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= @@ -817,8 +963,8 @@ github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= -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/spiffe/go-spiffe/v2 v2.6.0 h1:l+DolpxNWYgruGQVV0xsfeya3CsC7m8iBzDnMpsbLuo= +github.com/spiffe/go-spiffe/v2 v2.6.0/go.mod h1:gm2SeUoMZEtpnzPNs2Csc0D/gX33k1xIx7lEzqblHEs= 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= @@ -826,8 +972,9 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4= +github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -837,34 +984,38 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= -github.com/supranational/blst v0.3.14 h1:xNMoHRJOTwMn63ip6qoWJ2Ymgvj7E2b9jY2FAwY+qRo= -github.com/supranational/blst v0.3.14/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/supranational/blst v0.3.16 h1:bTDadT+3fK497EvLdWRQEjiGnUtzJ7jjIUMF0jqwYhE= +github.com/supranational/blst v0.3.16/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= 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/btree v1.8.1 h1:27ehoXvm5AG/g+1VxLS1SD3vRhp/H7LuEfwNvddEdmA= +github.com/tidwall/btree v1.8.1/go.mod h1:jBbTdUWhSZClZWoDg54VnvV7/54modSOzDN7VXftj1A= github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= -github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= -github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= +github.com/tidwall/match v1.2.0 h1:0pt8FlkOwjN2fPt4bIl4BoNxb98gGHN2ObFEDkrfZnM= +github.com/tidwall/match v1.2.0/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= -github.com/tklauser/go-sysconf v0.3.15 h1:VE89k0criAymJ/Os65CSn1IXaol+1wrsFHEB8Ol49K4= -github.com/tklauser/go-sysconf v0.3.15/go.mod h1:Dmjwr6tYFIseJw7a3dRLJfsHAMXZ3nEnL/aZY+0IuI4= -github.com/tklauser/numcpus v0.10.0 h1:18njr6LDBk1zuna922MgdjQuJFjrdppsZG60sHGfjso= -github.com/tklauser/numcpus v0.10.0/go.mod h1:BiTKazU708GQTYF4mB+cmlpT2Is1gLk7XVuEeem8LsQ= +github.com/tklauser/go-sysconf v0.3.16 h1:frioLaCQSsF5Cy1jgRBrzr6t502KIIwQ0MArYICU0nA= +github.com/tklauser/go-sysconf v0.3.16/go.mod h1:/qNL9xxDhc7tx3HSRsLWNnuzbVfh3e7gh/BmM179nYI= +github.com/tklauser/numcpus v0.11.0 h1:nSTwhKH5e1dMNsCdVBukSZrURJRoHbSEQjdEbY+9RXw= +github.com/tklauser/numcpus v0.11.0/go.mod h1:z+LwcLq54uWZTX0u/bGobaV34u6V7KNlTZejzM6/3MQ= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= 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= @@ -873,22 +1024,24 @@ github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2n github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= 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/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY= +github.com/ulikunitz/xz v0.5.15/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/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= +github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU= +github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= 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/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -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/golem v0.27.0 h1:IbBjGIXF3SoGOZHsILJvIM/F/ylwJzMcHAcggiqniPw= github.com/zondax/golem v0.27.0/go.mod h1:AmorCgJPt00L8xN1VrMBe13PSifoZksnQ1Ge906bu4A= github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= @@ -896,44 +1049,92 @@ github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWp github.com/zondax/ledger-go v1.0.1 h1:Ks/2tz/dOF+dbRynfZ0dEhcdL1lqw43Sa0zMXHpQ3aQ= github.com/zondax/ledger-go v1.0.1/go.mod h1:j7IgMY39f30apthJYMd1YsHZRqdyu4KbVmUp0nU78X0= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.4.0 h1:TU77id3TnN/zKr7CO/uk+fBCwF2jGcMuw2B/FMAzYIk= -go.etcd.io/bbolt v1.4.0/go.mod h1:AsD+OCi/qPN1giOX1aiLAha3o1U8rAz65bvN4j0sRuk= +go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo= +go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= 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/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.61.0 h1:q4XOmH/0opmeuJtPsbFNivyl7bCt7yRBbeEm2sC/XtQ= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0/go.mod h1:snMWehoOh2wsEwnvvwtDyFCxVeDAODenXHtn5vzrKjo= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 h1:Hf9xI/XLML9ElpiHVDNwvqI0hIFlzV8dgIr35kV1kRU= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0/go.mod h1:NfchwuyNoMcZ5MLHwPrODwUF1HWCXWrL31s8gSAdIKY= -go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= -go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= -go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= -go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= -go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= -go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= -go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= -go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= -go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= -go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/contrib/bridges/otelslog v0.18.0 h1:hhPGP3zvvy1xWT9RTy970wlniSxFttBIsAK1gvMguJM= +go.opentelemetry.io/contrib/bridges/otelslog v0.18.0/go.mod h1:twJF7inoMza6kxMcF8JOdL3mPmtOZu7GEr34CUNE6Dg= +go.opentelemetry.io/contrib/detectors/gcp v1.43.0 h1:62yY3dT7/ShwOxzA0RsKRgshBmfElKI4d/Myu2OxDFU= +go.opentelemetry.io/contrib/detectors/gcp v1.43.0/go.mod h1:RyaZMFY7yi1kAs45S6mbFGz8O8rqB0dTY14uzvG4LCs= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 h1:0Qx7VGBacMm9ZENQ7TnNObTYI4ShC+lHI16seduaxZo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0/go.mod h1:Sje3i3MjSPKTSPvVWCaL8ugBzJwik3u4smCjUeuupqg= +go.opentelemetry.io/contrib/instrumentation/host v0.68.0 h1:0BfTRAHtFpIlIY7cw1qg9nODUwblutIqx7Cn6NPD+2s= +go.opentelemetry.io/contrib/instrumentation/host v0.68.0/go.mod h1:SmgEeGNt1+gp8bmzB5LLyUlCObWcWrRbYMIiDii3NH8= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 h1:CqXxU8VOmDefoh0+ztfGaymYbhdB/tT3zs79QaZTNGY= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0/go.mod h1:BuhAPThV8PBHBvg8ZzZ/Ok3idOdhWIodywz2xEcRbJo= +go.opentelemetry.io/contrib/instrumentation/runtime v0.68.0 h1:jhVIQEprwUTV+KfzzliLidclhoTOoHTgdz96kAyR8mU= +go.opentelemetry.io/contrib/instrumentation/runtime v0.68.0/go.mod h1:4HsdbLUbernaTnA8CNaNE+1g026SciXb3juRYe3l8EY= +go.opentelemetry.io/contrib/otelconf v0.23.0 h1:s3C7KdMYiutf4rC8hKFA0WOIDG+gIru8ajjQKS59ir8= +go.opentelemetry.io/contrib/otelconf v0.23.0/go.mod h1:0kN2tcccZS82e7IZlo045gkcL8/8dup1k25sf9ypGxM= +go.opentelemetry.io/contrib/propagators/autoprop v0.68.0 h1:wLGFvNBPqQhzBn0QRBZjrriH8lZ9gqtTz8ufHEjLg7k= +go.opentelemetry.io/contrib/propagators/autoprop v0.68.0/go.mod h1:evWK9nCqCzH8nhclTlpkdUzmxrmJQ2mrWCdKIvyOYec= +go.opentelemetry.io/contrib/propagators/aws v1.43.0 h1:EwnsB3cXRLAh7/Nr/9rMuGw73nfb3z6uAvVDjRrbeUg= +go.opentelemetry.io/contrib/propagators/aws v1.43.0/go.mod h1:CJjTym6F87tEdm61Qvnz5xrV8vKlH4C92djiqcn62k8= +go.opentelemetry.io/contrib/propagators/b3 v1.43.0 h1:CETqV3QLLPTy5yNrqyMr41VnAOOD4lsRved7n4QG00A= +go.opentelemetry.io/contrib/propagators/b3 v1.43.0/go.mod h1:Q4mCiCdziYzpNR0g+6UqVotAlCDZdzz6L8jwY4knOrw= +go.opentelemetry.io/contrib/propagators/jaeger v1.43.0 h1:peiLMz1+aqJE+3L4mOVtR9wlmv+yh/JVYXCBjqmzJJE= +go.opentelemetry.io/contrib/propagators/jaeger v1.43.0/go.mod h1:Agvif+4A8p/3UtZzJ0MCcDEuQwgtrzM71DueU41DCs8= +go.opentelemetry.io/contrib/propagators/ot v1.43.0 h1:Hh1HahlGc81AOE7siqi1tVOlbanY/UxMMWedpb0d5oQ= +go.opentelemetry.io/contrib/propagators/ot v1.43.0/go.mod h1:58MlyS7lghzYvAm5LN9gGmZpCMQEMB5vpZp9SRgOyE4= +go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= +go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.19.0 h1:Dn8rkudDzY6KV9dr/D/bTUuWgqDf9xe0rr4G2elrn0Y= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.19.0/go.mod h1:gMk9F0xDgyN9M/3Ed5Y1wKcx/9mlU91NXY2SNq7RQuU= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0 h1:HIBTQ3VO5aupLKjC90JgMqpezVXwFuq6Ryjn0/izoag= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0/go.mod h1:ji9vId85hMxqfvICA0Jt8JqEdrXaAkcpkI9HPXya0ro= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.43.0 h1:8UQVDcZxOJLtX6gxtDt3vY2WTgvZqMQRzjsqiIHQdkc= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.43.0/go.mod h1:2lmweYCiHYpEjQ/lSJBYhj9jP1zvCvQW4BqL9dnT7FQ= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0 h1:w1K+pCJoPpQifuVpsKamUdn9U0zM3xUziVOqsGksUrY= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0/go.mod h1:HBy4BjzgVE8139ieRI75oXm3EcDN+6GhD88JT1Kjvxg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 h1:88Y4s2C8oTui1LGM6bTWkw0ICGcOLCAI5l6zsD1j20k= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0/go.mod h1:Vl1/iaggsuRlrHf/hfPJPvVag77kKyvrLeD10kpMl+A= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 h1:RAE+JPfvEmvy+0LzyUA25/SGawPwIUbZ6u0Wug54sLc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0/go.mod h1:AGmbycVGEsRx9mXMZ75CsOyhSP6MFIcj/6dnG+vhVjk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 h1:3iZJKlCZufyRzPzlQhUIWVmfltrXuGyfjREgGP3UUjc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0/go.mod h1:/G+nUPfhq2e+qiXMGxMwumDrP5jtzU+mWN7/sjT2rak= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.19.0 h1:GJkybS+crDMdExT/BUNCEgfrmfboztcS6PhvSo88HKM= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.19.0/go.mod h1:NuAyxRYIG2lKX3YQkB+83StTxM7s52PUUkRRiC0wnYI= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.43.0 h1:TC+BewnDpeiAmcscXbGMfxkO+mwYUwE/VySwvw88PfA= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.43.0/go.mod h1:J/ZyF4vfPwsSr9xJSPyQ4LqtcTPULFR64KwTikGLe+A= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.43.0 h1:mS47AX77OtFfKG4vtp+84kuGSFZHTyxtXIN269vChY0= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.43.0/go.mod h1:PJnsC41lAGncJlPUniSwM81gc80GkgWJWr3cu2nKEtU= +go.opentelemetry.io/otel/log v0.19.0 h1:KUZs/GOsw79TBBMfDWsXS+KZ4g2Ckzksd1ymzsIEbo4= +go.opentelemetry.io/otel/log v0.19.0/go.mod h1:5DQYeGmxVIr4n0/BcJvF4upsraHjg6vudJJpnkL6Ipk= +go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= +go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= +go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= +go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= +go.opentelemetry.io/otel/sdk/log v0.19.0 h1:scYVLqT22D2gqXItnWiocLUKGH9yvkkeql5dBDiXyko= +go.opentelemetry.io/otel/sdk/log v0.19.0/go.mod h1:vFBowwXGLlW9AvpuF7bMgnNI95LiW10szrOdvzBHlAg= +go.opentelemetry.io/otel/sdk/log/logtest v0.19.0 h1:BEbF7ZBB6qQloV/Ub1+3NQoOUnVtcGkU3XX4Ws3GQfk= +go.opentelemetry.io/otel/sdk/log/logtest v0.19.0/go.mod h1:Lua81/3yM0wOmoHTokLj9y9ADeA02v1naRrVrkAZuKk= +go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= +go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= +go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= +go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g= +go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk= 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= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= +go.uber.org/dig v1.19.0 h1:BACLhebsYdpQ7IROQ1AGPjrXcP5dF80U3gKoFzbaq/4= +go.uber.org/dig v1.19.0/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE= +go.uber.org/fx v1.24.0 h1:wE8mruvpg2kiiL1Vqd0CC+tr0/24XIB10Iwp2lLWzkg= +go.uber.org/fx v1.24.0/go.mod h1:AmDeGyS+ZARGKM4tlH4FY2Jr63VjbEDJHtqXTGP5hbo= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko= -go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o= +go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= +go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= @@ -943,29 +1144,36 @@ 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.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= -go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -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.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= +go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= +go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= -golang.org/x/arch v0.21.0 h1:iTC9o7+wP6cPWpDWkivCvQFGAHDQ59SrSxsLPcnkArw= -golang.org/x/arch v0.21.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A= +golang.org/x/arch v0.26.0 h1:jZ6dpec5haP/fUv1kLCbuJy6dnRrfX6iVK08lZBFpk4= +golang.org/x/arch v0.26.0/go.mod h1:0X+GdSIP+kL5wPmpK7sdkEVTt2XoYP0cSjQSbZBwOi8= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 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.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI= -golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= +golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= 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= -golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 h1:y5zboxd6LQAqYIhHnB48p0ByQ/GnQx2BE33L8BOHQkI= -golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ= +golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90 h1:jiDhWWeC7jfWqR9c/uplMOqJ0sbNlNWv0UkzE0vX1MA= +golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90/go.mod h1:xE1HEv6b+1SCZ5/uscMRjUBKtIxworgEcEi+/n9NQDQ= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -979,6 +1187,10 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI= +golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1001,18 +1213,26 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= 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.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= -golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= +golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= 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/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= +golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= 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= @@ -1021,8 +1241,11 @@ 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.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= -golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= 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= @@ -1052,10 +1275,12 @@ golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1073,30 +1298,44 @@ golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/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.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.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.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= -golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= +golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/telemetry v0.0.0-20260311193753-579e4da9a98c h1:6a8FdnNk6bTXBjR4AGKFgUKuo+7GnR3FX5L7CbveeZc= +golang.org/x/telemetry v0.0.0-20260311193753-579e4da9a98c/go.mod h1:TpUTTEp9frx7rTdLpC9gFG9kdI7zVLFTFFlqaH2Cncw= 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.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= -golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= +golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY= 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.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= -golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= +golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= 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.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= -golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= +golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= 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= @@ -1117,18 +1356,20 @@ golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= -golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s= +golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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= -gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= -gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= +gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= -google.golang.org/api v0.247.0 h1:tSd/e0QrUlLsrwMKmkbQhYVa109qIintOls2Wh6bngc= -google.golang.org/api v0.247.0/go.mod h1:r1qZOPmxXffXg6xS5uhx16Fa/UFY8QU/K4bfKrnvovM= +google.golang.org/api v0.276.0 h1:nVArUtfLEihtW+b0DdcqRGK1xoEm2+ltAihyztq7MKY= +google.golang.org/api v0.276.0/go.mod h1:Fnag/EWUPIcJXuIkP1pjoTgS5vdxlk3eeemL7Do6bvw= 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= @@ -1143,12 +1384,12 @@ google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= -google.golang.org/genproto v0.0.0-20250603155806-513f23925822 h1:rHWScKit0gvAPuOnu87KpaYtjK5zBMLcULh7gxkCXu4= -google.golang.org/genproto v0.0.0-20250603155806-513f23925822/go.mod h1:HubltRL7rMh0LfnQPkMH4NPDFEWp0jw3vixw7jEM53s= -google.golang.org/genproto/googleapis/api v0.0.0-20250804133106-a7a43d27e69b h1:ULiyYQ0FdsJhwwZUwbaXpZF5yUE3h+RA+gxvBu37ucc= -google.golang.org/genproto/googleapis/api v0.0.0-20250804133106-a7a43d27e69b/go.mod h1:oDOGiMSXHL4sDTJvFvIB9nRQCGdLP1o/iVaqQK8zB+M= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c h1:qXWI/sQtv5UKboZ/zUk7h+mrf/lXORyI+n9DKDAusdg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c/go.mod h1:gw1tLEfykwDz2ET4a12jcXt4couGAm7IwsVaTy0Sflo= +google.golang.org/genproto v0.0.0-20260414002931-afd174a4e478 h1:aLsVTW0lZ8+IY5u/ERjZSCvAmhuR7slKzyha3YikDNA= +google.golang.org/genproto v0.0.0-20260414002931-afd174a4e478/go.mod h1:YJAzKjfHIUHb9T+bfu8L7mthAp7VVXQBUs1PLdBWS7M= +google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 h1:yQugLulqltosq0B/f8l4w9VryjV+N/5gcW0jQ3N8Qec= +google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478/go.mod h1:C6ADNqOxbgdUUeRTU+LCHDPB9ttAMCTff6auwCVa4uc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 h1:RmoJA1ujG+/lRGNfUnOMfhCy5EipVMyvUE+KNbPbTlw= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= @@ -1166,8 +1407,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.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A= -google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= +google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= +google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= 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= @@ -1182,8 +1423,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.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= -google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= 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= @@ -1221,12 +1462,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= +lukechampine.com/blake3 v1.4.1 h1:I3Smz7gso8w4/TunLKec6K2fn+kyKtDxr/xcQEN84Wg= +lukechampine.com/blake3 v1.4.1/go.mod h1:QFosUxmjB8mnrWFSNwKmvxHpfY72bmD2tQ0kBMM3kwo= nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= nhooyr.io/websocket v1.8.17 h1:KEVeLJkUywCKVsnLIDlD/5gtayKp8VoCkksHCGGfT9Y= nhooyr.io/websocket v1.8.17/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= +pgregory.net/rapid v1.3.0 h1:vBvO0VSqti75J1jjYqpgPNBLKMd1+gxa9fYo7vk/Exc= +pgregory.net/rapid v1.3.0/go.mod h1:dPlE4OBBxgXPqkP79flB6sJL1dx5azpI7HQ9MY9Z7uk= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= diff --git a/tests/systemtests/main_test.go b/tests/systemtests/main_test.go index caabc9e3..5c431fdd 100644 --- a/tests/systemtests/main_test.go +++ b/tests/systemtests/main_test.go @@ -6,51 +6,83 @@ import ( "testing" "github.com/cosmos/evm/tests/systemtests/accountabstraction" - "github.com/cosmos/evm/tests/systemtests/mempool" - + "github.com/cosmos/evm/tests/systemtests/chainupgrade" "github.com/cosmos/evm/tests/systemtests/eip712" - "cosmossdk.io/systemtests" + "github.com/cosmos/evm/tests/systemtests/mempool" + "github.com/cosmos/evm/tests/systemtests/suite" + + "github.com/cosmos/cosmos-sdk/tools/systemtests" ) func TestMain(m *testing.M) { systemtests.RunTests(m) } -func TestCosmosTxCompat(t *testing.T) { - mempool.TestCosmosTxsCompatibility(t) +/* + * Mempool Tests + */ +func TestMempoolTxsOrdering(t *testing.T) { + suite.RunWithSharedSuite(t, mempool.RunTxsOrdering, suite.MempoolArgs()...) +} + +func TestMempoolTxsReplacement(t *testing.T) { + suite.RunWithSharedSuite(t, mempool.RunTxsReplacement, suite.MempoolArgs()...) +} + +func TestMempoolTxsReplacementWithCosmosTx(t *testing.T) { + suite.RunWithSharedSuite(t, mempool.RunTxsReplacementWithCosmosTx, suite.MempoolArgs()...) } -// Mempool Tests -func TestTxsOrdering(t *testing.T) { - mempool.TestTxsOrdering(t) +func TestMempoolMixedTxsReplacementLegacyAndDynamicFee(t *testing.T) { + suite.RunWithSharedSuite(t, mempool.RunMixedTxsReplacementLegacyAndDynamicFee, suite.MempoolMinGasPriceZeroArgs()...) } -func TestTxsReplacement(t *testing.T) { - mempool.TestTxsReplacement(t) - mempool.TestTxsReplacementWithCosmosTx(t) - mempool.TestMixedTxsReplacementLegacyAndDynamicFee(t) +func TestMempoolTxBroadcasting(t *testing.T) { + suite.RunWithSharedSuite(t, mempool.RunTxBroadcasting, suite.MempoolArgs()...) } -func TestExceptions(t *testing.T) { - mempool.TestTxRebroadcasting(t) - mempool.TestMinimumGasPricesZero(t) +func TestMempoolMinimumGasPricesZero(t *testing.T) { + suite.RunWithSharedSuite(t, mempool.RunMinimumGasPricesZero, suite.MempoolArgs()...) } -// Account Abstraction Tests -func TestEIP7702(t *testing.T) { - accountabstraction.TestEIP7702(t) +func TestMempoolCosmosTxsCompatibility(t *testing.T) { + suite.RunWithSharedSuite(t, mempool.RunCosmosTxsCompatibility, suite.MempoolArgs()...) } -// EIP-712 Tests +func TestMempoolSetCode7702QueuedTxPromotion(t *testing.T) { + suite.RunWithSharedSuite(t, mempool.RunSetCode7702QueuedTxPromotion, suite.MempoolArgs()...) +} + +// /* +// * EIP-712 Tests +// */ func TestEIP712BankSend(t *testing.T) { - eip712.TestEIP712BankSend(t) + suite.RunWithSharedSuite(t, eip712.RunEIP712BankSend) } func TestEIP712BankSendWithBalanceCheck(t *testing.T) { - eip712.TestEIP712BankSendWithBalanceCheck(t) + suite.RunWithSharedSuite(t, eip712.RunEIP712BankSendWithBalanceCheck) } func TestEIP712MultipleBankSends(t *testing.T) { - eip712.TestEIP712MultipleBankSends(t) + suite.RunWithSharedSuite(t, eip712.RunEIP712MultipleBankSends) +} + +/* +* Account Abstraction Tests + */ +func TestAccountAbstractionEIP7702(t *testing.T) { + suite.RunWithSharedSuite(t, accountabstraction.RunEIP7702) +} + +func TestAccountAbstractionEIP7702SameBlock(t *testing.T) { + suite.RunWithSharedSuite(t, accountabstraction.RunEIP7702SameBlock) +} + +/* +* Chain Upgrade Tests + */ +func TestChainUpgrade(t *testing.T) { + suite.RunWithSharedSuite(t, chainupgrade.RunChainUpgrade) } diff --git a/tests/systemtests/mempool/interface.go b/tests/systemtests/mempool/interface.go deleted file mode 100644 index a13491e7..00000000 --- a/tests/systemtests/mempool/interface.go +++ /dev/null @@ -1,46 +0,0 @@ -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) - GetTxGasPrice(baseFee *big.Int) *big.Int -} diff --git a/tests/systemtests/mempool/test_broadcast.go b/tests/systemtests/mempool/test_broadcast.go new file mode 100644 index 00000000..fa0c3701 --- /dev/null +++ b/tests/systemtests/mempool/test_broadcast.go @@ -0,0 +1,415 @@ +//go:build system_test + +package mempool + +import ( + "context" + "fmt" + "slices" + "testing" + "time" + + "github.com/test-go/testify/require" + + "github.com/cosmos/evm/tests/systemtests/suite" +) + +// RunTxBroadcasting tests transaction broadcasting and duplicate handling in a multi-node network. +// +// This test verifies two critical aspects of transaction propagation: +// +// 1. Mempool Broadcasting: Transactions submitted to one node are gossiped to all other nodes +// via the mempool gossip protocol BEFORE blocks are produced. +// +// 2. Duplicate Detection: The RPC layer properly rejects duplicate transactions submitted +// by users via JSON-RPC (returning txpool.ErrAlreadyKnown), while internal gossip remains silent. +// +// The test uses a 5-second consensus timeout to create a larger window for verifying that +// transactions appear in other nodes' mempools before blocks are committed. +func RunTxBroadcasting(t *testing.T, base *suite.BaseTestSuite) { + testCases := []struct { + name string + actions []func(*testing.T, *TestSuite, *TestContext) + }{ + { + // Scenario 1: Basic Broadcasting and Transaction Promotion + // + // This scenario verifies that: + // 1. Transactions are gossiped to all nodes BEFORE blocks are committed + // 2. Queued transactions (with nonce gaps) are NOT gossiped + // 3. When gaps are filled, queued txs are promoted and then gossiped + // + // Broadcasting Flow: + // User -> JSON-RPC -> Mempool (pending) -> Gossip to peers + // When nonce gap filled: Queued -> Promoted to pending -> Gossiped + name: "tx broadcast to other nodes %s", + actions: []func(*testing.T, *TestSuite, *TestContext){ + func(t *testing.T, s *TestSuite, ctx *TestContext) { + // Step 1: Send tx with nonce 0 to node0 + // Expected: tx is added to node0's pending pool (nonce is correct) + signer := s.Acc(0) + + // Send transaction to node0 + tx1, err := s.SendTx(t, s.Node(0), signer.ID, 0, s.GasPriceMultiplier(10), nil) + require.NoError(t, err, "failed to send tx to node0") + + // Step 2: Verify tx appears in nodes 1, 2, 3 mempools before the next block + // Expected: tx is gossiped to all nodes BEFORE any block is committed + // This proves mempool gossip works, not just block propagation + maxWaitTime := 5 * time.Second + checkInterval := 100 * time.Millisecond + + for _, nodeIdx := range []int{1, 2, 3} { + func(nodeIdx int) { + nodeID := s.Node(nodeIdx) + found := false + + timeoutCtx, cancel := context.WithTimeout(context.Background(), maxWaitTime) + defer cancel() + + ticker := time.NewTicker(checkInterval) + defer ticker.Stop() + + for !found { + select { + case <-timeoutCtx.Done(): + require.FailNow(t, fmt.Sprintf( + "transaction %s was not broadcast to %s within %s - mempool gossip may not be working", + tx1.TxHash, nodeID, maxWaitTime, + )) + case <-ticker.C: + pendingTxs, _, err := s.TxPoolContent(nodeID, suite.TxTypeEVM, 5*time.Second) + if err != nil { + // Retry on error + t.Logf("Error querying txpool content: %s", err) + continue + } + + if slices.Contains(pendingTxs, tx1.TxHash) { + t.Logf("Transaction %s successfully broadcast to %s", tx1.TxHash, nodeID) + found = true + } + } + } + }(nodeIdx) + } + + // Now set expected state and let the transaction commit normally + ctx.SetExpPendingTxs(tx1) + }, + func(t *testing.T, s *TestSuite, ctx *TestContext) { + // Step 3: Send tx with nonce 2 to node1 (creating a nonce gap) + // Current nonce is 1 (after previous tx), so nonce 2 creates a gap + // Expected: tx is added to node1's QUEUED pool (not pending due to gap) + signer := s.Acc(0) + + // Send tx with nonce +2 to node1 (creating a gap since current nonce is 1) + tx3, err := s.SendTx(t, s.Node(1), signer.ID, 2, s.GasPriceMultiplier(10), nil) + require.NoError(t, err, "failed to send tx with nonce 2") + + // Step 4: Verify tx is in node1's QUEUED pool (not pending) + // Queued txs cannot execute until the nonce gap is filled + maxWaitTime := 2 * time.Second + checkInterval := 100 * time.Millisecond + + timeoutCtx, cancel := context.WithTimeout(context.Background(), maxWaitTime) + defer cancel() + + ticker := time.NewTicker(checkInterval) + defer ticker.Stop() + + queuedOnNode1 := false + for !queuedOnNode1 { + select { + case <-timeoutCtx.Done(): + require.FailNow(t, fmt.Sprintf( + "transaction %s was not queued on node1 within %s", + tx3.TxHash, maxWaitTime, + )) + case <-ticker.C: + _, queuedTxs, err := s.TxPoolContent(s.Node(1), suite.TxTypeEVM, 5*time.Second) + if err != nil { + continue + } + + if slices.Contains(queuedTxs, tx3.TxHash) { + t.Logf("Transaction %s is queued on node1 (as expected due to nonce gap)", tx3.TxHash) + queuedOnNode1 = true + } + } + } + + // Step 5: Verify queued tx is NOT gossiped to other nodes + // Queued txs should stay local until they become pending (executable) + // This prevents network spam from non-executable transactions + time.Sleep(1 * time.Second) // Give some time for any potential gossip + + for _, nodeIdx := range []int{0, 2, 3} { + nodeID := s.Node(nodeIdx) + pendingTxs, queuedTxs, err := s.TxPoolContent(nodeID, suite.TxTypeEVM, 5*time.Second) + require.NoError(t, err, "failed to get txpool content from %s", nodeID) + + require.NotContains(t, pendingTxs, tx3.TxHash, + "queued transaction should not be in pending pool of %s", nodeID) + require.NotContains(t, queuedTxs, tx3.TxHash, + "queued transaction should not be broadcast to %s", nodeID) + } + + // Step 6: Send tx with nonce +1 to node2 (filling the gap) + // Expected: tx is added to node2's pending pool and gossiped + tx2, err := s.SendTx(t, s.Node(2), signer.ID, 1, s.GasPriceMultiplier(10), nil) + require.NoError(t, err, "failed to send tx with nonce 1") + + // Step 7: Verify BOTH txs appear in all nodes' pending pools + // - tx2 (nonce=1) should be gossiped immediately (it's pending) + // - tx3 (nonce=2) should be promoted from queued to pending on node1 + // - Promoted tx3 should then be gossiped to all other nodes + // This proves queued txs get rebroadcast when promoted + maxWaitTime = 5 * time.Second + ticker2 := time.NewTicker(checkInterval) + defer ticker2.Stop() + + for _, nodeIdx := range []int{0, 1, 3} { + func(nodeIdx int) { + nodeID := s.Node(nodeIdx) + foundTx2 := false + foundTx3 := false + + timeoutCtx2, cancel2 := context.WithTimeout(context.Background(), maxWaitTime) + defer cancel2() + + for !foundTx2 || !foundTx3 { + select { + case <-timeoutCtx2.Done(): + if !foundTx2 { + require.FailNow(t, fmt.Sprintf( + "transaction %s was not broadcast to %s within %s", + tx2.TxHash, nodeID, maxWaitTime, + )) + } + if !foundTx3 { + require.FailNow(t, fmt.Sprintf( + "transaction %s (promoted from queued) was not broadcast to %s within %s", + tx3.TxHash, nodeID, maxWaitTime, + )) + } + case <-ticker2.C: + pendingTxs, _, err := s.TxPoolContent(nodeID, suite.TxTypeEVM, 5*time.Second) + if err != nil { + continue + } + + if !foundTx2 && slices.Contains(pendingTxs, tx2.TxHash) { + t.Logf("Transaction %s broadcast to %s", tx2.TxHash, nodeID) + foundTx2 = true + } + + if !foundTx3 && slices.Contains(pendingTxs, tx3.TxHash) { + t.Logf("Transaction %s (promoted) broadcast to %s", tx3.TxHash, nodeID) + foundTx3 = true + } + } + } + }(nodeIdx) + } + + ctx.SetExpPendingTxs(tx2, tx3) + }, + }, + }, + { + // Scenario 2: Duplicate Detection on Same Node + // + // This scenario verifies that when a user submits the same transaction twice + // to the same node via JSON-RPC, the second submission returns an error. + // + // Error Handling: + // RPC Layer: Checks mempool.Has(txHash) -> returns txpool.ErrAlreadyKnown + // Users get immediate error feedback (not silent failure) + name: "duplicate tx rejected on same node %s", + actions: []func(*testing.T, *TestSuite, *TestContext){ + func(t *testing.T, s *TestSuite, ctx *TestContext) { + // Step 1: Send tx with the current nonce to node0 + // Expected: tx is accepted and added to pending pool + signer := s.Acc(0) + + // Send transaction to node0 + tx1, err := s.SendTx(t, s.Node(0), signer.ID, 0, s.GasPriceMultiplier(10), nil) + require.NoError(t, err, "failed to send tx to node0") + + // Step 2: Verify tx is in node0's pending pool + // Poll for the transaction to appear (it should be fast, but we need to wait for async processing) + maxWaitTime := 3 * time.Second + checkInterval := 100 * time.Millisecond + + timeoutCtx, cancel := context.WithTimeout(context.Background(), maxWaitTime) + defer cancel() + + ticker := time.NewTicker(checkInterval) + defer ticker.Stop() + + found := false + for !found { + select { + case <-timeoutCtx.Done(): + require.FailNow(t, fmt.Sprintf( + "transaction %s was not found in node0's pending pool within %s", + tx1.TxHash, maxWaitTime, + )) + case <-ticker.C: + pendingTxs, _, err := s.TxPoolContent(s.Node(0), suite.TxTypeEVM, 5*time.Second) + if err != nil { + continue + } + if slices.Contains(pendingTxs, tx1.TxHash) { + found = true + } + } + } + + // Step 3: Send the SAME transaction again to node0 via JSON-RPC + // Expected: Error returned (txpool.ErrAlreadyKnown) + // Users must receive error feedback for duplicate submissions + _, err = s.SendTx(t, s.Node(0), signer.ID, 0, s.GasPriceMultiplier(10), nil) + require.Error(t, err, "duplicate tx via JSON-RPC must return error") + require.Contains(t, err.Error(), "already", "error should indicate transaction is already known") + + t.Logf("Duplicate transaction correctly rejected with 'already known' error") + + ctx.SetExpPendingTxs(tx1) + }, + }, + }, + { + // Scenario 3: Duplicate Detection After Gossip + // + // This scenario verifies that even when a node receives a transaction via + // internal gossip (not user submission), attempting to submit that same + // transaction again via JSON-RPC returns an error. + // + // Flow: + // 1. User submits tx to node0 -> added to mempool -> gossiped to node1 + // 2. User tries to submit same tx to node1 via JSON-RPC + // 3. RPC layer detects duplicate (mempool.Has) and returns error + // + // This ensures duplicate detection works regardless of how the node + // originally received the transaction (user submission vs gossip). + name: "duplicate tx rejected after gossip %s", + actions: []func(*testing.T, *TestSuite, *TestContext){ + func(t *testing.T, s *TestSuite, ctx *TestContext) { + // Step 1: Send tx with the current nonce to node0 + // Expected: tx is accepted, added to pending, and gossiped + signer := s.Acc(0) + + // Send transaction to node0 + tx1, err := s.SendTx(t, s.Node(0), signer.ID, 0, s.GasPriceMultiplier(10), nil) + require.NoError(t, err, "failed to send tx to node0") + + // Step 2: Wait for tx to be gossiped to node1 + // Expected: tx appears in node1's pending pool before the next block + maxWaitTime := 3 * time.Second + checkInterval := 100 * time.Millisecond + + timeoutCtx, cancel := context.WithTimeout(context.Background(), maxWaitTime) + defer cancel() + + ticker := time.NewTicker(checkInterval) + defer ticker.Stop() + + found := false + for !found { + select { + case <-timeoutCtx.Done(): + require.FailNow(t, fmt.Sprintf( + "transaction %s was not broadcast to node1 within %s", + tx1.TxHash, maxWaitTime, + )) + case <-ticker.C: + pendingTxs, _, err := s.TxPoolContent(s.Node(1), suite.TxTypeEVM, 5*time.Second) + if err != nil { + continue + } + if slices.Contains(pendingTxs, tx1.TxHash) { + t.Logf("Transaction %s broadcast to node1 via gossip", tx1.TxHash) + found = true + } + } + } + + // Step 3: Try to send the SAME transaction to node1 via JSON-RPC + // Expected: Error returned (txpool.ErrAlreadyKnown) + // Even though node1 received it via gossip (not user submission), + // the RPC layer should still detect and reject the duplicate + _, err = s.SendTx(t, s.Node(1), signer.ID, 0, s.GasPriceMultiplier(10), nil) + require.Error(t, err, "duplicate tx via JSON-RPC should return error even after gossip") + require.Contains(t, err.Error(), "already", "error should indicate transaction is already known") + + t.Logf("JSON-RPC correctly rejects duplicate that node already has from gossip") + + ctx.SetExpPendingTxs(tx1) + }, + }, + }, + } + + testOptions := []*suite.TestOptions{ + { + Description: "EVM LegacyTx", + TxType: suite.TxTypeEVM, + IsDynamicFeeTx: false, + }, + { + Description: "EVM DynamicFeeTx", + TxType: suite.TxTypeEVM, + IsDynamicFeeTx: true, + }, + } + + s := NewTestSuite(base) + + // First, setup the chain with default configuration + // + // Slow down block production to give time to verify gossip before blocks + // commit. + s.SetupTestWithTimeoutCommit(t, 5*time.Second) + + 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) { + // Await a block before starting the test case (ensures clean state) + s.AwaitNBlocks(t, 1) + + ctx := NewTestContext() + s.BeforeEachCase(t, ctx) + + // Capture the initial block height - no blocks should be produced during the test case + initialHeight := s.GetCurrentBlockHeight(t, "node0") + t.Logf("Test case starting at block height %d", initialHeight) + + // Execute all test actions (broadcasting, mempool checks, etc.) + for _, action := range tc.actions { + action(t, s, ctx) + // NOTE: We don't call AfterEachAction here because we're manually + // checking the mempool state in the action functions + } + + // Verify no blocks were produced during the test case + // All broadcasting and mempool checks should happen within a single block period + currentHeight := s.GetCurrentBlockHeight(t, "node0") + require.Equal(t, initialHeight, currentHeight, + "No blocks should be produced during test case execution - expected height %d but got %d", + initialHeight, currentHeight) + t.Logf("✓ Test case completed at same block height %d (no blocks produced)", currentHeight) + + // Now await a block to allow transactions to commit + s.AwaitNBlocks(t, 1) + t.Logf("Awaited block for transaction commits") + + // Verify transactions committed successfully + s.AfterEachCase(t, ctx) + }) + } + } +} diff --git a/tests/systemtests/mempool/test_cosmos_tx.go b/tests/systemtests/mempool/test_cosmos_tx.go index 48f62576..a1d7bca6 100644 --- a/tests/systemtests/mempool/test_cosmos_tx.go +++ b/tests/systemtests/mempool/test_cosmos_tx.go @@ -1,3 +1,5 @@ +//go:build system_test + package mempool import ( @@ -5,39 +7,39 @@ import ( "testing" "github.com/cosmos/evm/tests/systemtests/suite" - "github.com/test-go/testify/require" + "github.com/stretchr/testify/require" ) -// TestCosmosTxsCompatibility tests that cosmos txs are still functional and interacting with the mempool properly. -func TestCosmosTxsCompatibility(t *testing.T) { +// RunCosmosTxsCompatibility tests that cosmos txs are still functional and interacting with the mempool properly. +func RunCosmosTxsCompatibility(t *testing.T, base *suite.BaseTestSuite) { testCases := []struct { name string - actions []func(s TestSuite) + actions []func(*TestSuite, *TestContext) }{ { name: "single pending tx submitted to same nodes %s", - actions: []func(s TestSuite){ - func(s TestSuite) { - tx1, err := s.SendTx(t, s.Node(0), "acc0", 0, s.GetTxGasPrice(s.BaseFee()), nil) + actions: []func(*TestSuite, *TestContext){ + func(s *TestSuite, ctx *TestContext) { + tx1, err := s.SendTx(t, s.Node(0), "acc0", 0, s.GasPriceMultiplier(10), nil) require.NoError(t, err, "failed to send tx") - s.SetExpPendingTxs(tx1) + ctx.SetExpPendingTxs(tx1) }, }, }, { name: "multiple pending txs submitted to same nodes %s", - actions: []func(s TestSuite){ - func(s TestSuite) { - tx1, err := s.SendTx(t, s.Node(0), "acc0", 0, s.GetTxGasPrice(s.BaseFee()), nil) + actions: []func(*TestSuite, *TestContext){ + func(s *TestSuite, ctx *TestContext) { + tx1, err := s.SendTx(t, s.Node(0), "acc0", 0, s.GasPriceMultiplier(10), nil) require.NoError(t, err, "failed to send tx") - tx2, err := s.SendTx(t, s.Node(0), "acc0", 1, s.GetTxGasPrice(s.BaseFee()), nil) + tx2, err := s.SendTx(t, s.Node(0), "acc0", 1, s.GasPriceMultiplier(10), nil) require.NoError(t, err, "failed to send tx") - tx3, err := s.SendTx(t, s.Node(0), "acc0", 2, s.GetTxGasPrice(s.BaseFee()), nil) + tx3, err := s.SendTx(t, s.Node(0), "acc0", 2, s.GasPriceMultiplier(10), nil) require.NoError(t, err, "failed to send tx") - s.SetExpPendingTxs(tx1, tx2, tx3) + ctx.SetExpPendingTxs(tx1, tx2, tx3) }, }, }, @@ -50,7 +52,7 @@ func TestCosmosTxsCompatibility(t *testing.T) { }, } - s := suite.NewSystemTestSuite(t) + s := NewTestSuite(base) s.SetupTest(t) for _, to := range testOptions { @@ -58,11 +60,13 @@ func TestCosmosTxsCompatibility(t *testing.T) { for _, tc := range testCases { testName := fmt.Sprintf(tc.name, to.Description) t.Run(testName, func(t *testing.T) { - s.BeforeEachCase(t) + ctx := NewTestContext() + + s.BeforeEachCase(t, ctx) for _, action := range tc.actions { - action(s) + action(s, ctx) } - s.AfterEachCase(t) + s.AfterEachCase(t, ctx) }) } } diff --git a/tests/systemtests/mempool/test_exceptions.go b/tests/systemtests/mempool/test_exceptions.go index 3f38bba6..1198cff4 100644 --- a/tests/systemtests/mempool/test_exceptions.go +++ b/tests/systemtests/mempool/test_exceptions.go @@ -1,3 +1,5 @@ +//go:build system_test + package mempool import ( @@ -5,107 +7,30 @@ import ( "testing" "github.com/cosmos/evm/tests/systemtests/suite" - "github.com/test-go/testify/require" + "github.com/stretchr/testify/require" ) -func TestTxRebroadcasting(t *testing.T) { - testCases := []struct { - name string - actions []func(s TestSuite) - }{ - { - name: "ordering of pending txs %s", - actions: []func(s TestSuite){ - func(s TestSuite) { - tx1, err := s.SendTx(t, s.Node(0), "acc0", 0, s.GetTxGasPrice(s.BaseFee()), nil) - require.NoError(t, err, "failed to send tx") - - tx2, err := s.SendTx(t, s.Node(1), "acc0", 1, s.GetTxGasPrice(s.BaseFee()), nil) - require.NoError(t, err, "failed to send tx") - - tx3, err := s.SendTx(t, s.Node(2), "acc0", 2, s.GetTxGasPrice(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.GetTxGasPrice(s.BaseFee()), nil) - require.NoError(t, err, "failed to send tx") - - tx6, err := s.SendTx(t, s.Node(0), "acc0", 5, s.GetTxGasPrice(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.GetTxGasPrice(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) { - s.BeforeEachCase(t) - for _, action := range tc.actions { - action(s) - s.AfterEachAction(t) - } - s.AfterEachCase(t) - }) - } - } -} - -func TestMinimumGasPricesZero(t *testing.T) { +func RunMinimumGasPricesZero(t *testing.T, base *suite.BaseTestSuite) { testCases := []struct { name string - actions []func(s TestSuite) + actions []func(*TestSuite, *TestContext) }{ { name: "sequencial pending txs %s", - actions: []func(s TestSuite){ - func(s TestSuite) { - tx1, err := s.SendTx(t, s.Node(0), "acc0", 0, s.GetTxGasPrice(s.BaseFee()), nil) + actions: []func(*TestSuite, *TestContext){ + func(s *TestSuite, ctx *TestContext) { + signer := s.Acc(0) + + tx1, err := s.SendTx(t, s.Node(0), signer.ID, 0, s.GasPriceMultiplier(10), nil) require.NoError(t, err, "failed to send tx") - tx2, err := s.SendTx(t, s.Node(1), "acc0", 1, s.GetTxGasPrice(s.BaseFee()), nil) + tx2, err := s.SendTx(t, s.Node(1), signer.ID, 1, s.GasPriceMultiplier(10), nil) require.NoError(t, err, "failed to send tx") - tx3, err := s.SendTx(t, s.Node(2), "acc0", 2, s.GetTxGasPrice(s.BaseFee()), nil) + tx3, err := s.SendTx(t, s.Node(2), signer.ID, 2, s.GasPriceMultiplier(10), nil) require.NoError(t, err, "failed to send tx") - s.SetExpPendingTxs(tx1, tx2, tx3) + ctx.SetExpPendingTxs(tx1, tx2, tx3) }, }, }, @@ -124,20 +49,21 @@ func TestMinimumGasPricesZero(t *testing.T) { }, } - s := suite.NewSystemTestSuite(t) - s.SetupTest(t, suite.MinimumGasPriceZeroArgs()...) + s := NewTestSuite(base) + 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) { - s.BeforeEachCase(t) + ctx := NewTestContext() + s.BeforeEachCase(t, ctx) for _, action := range tc.actions { - action(s) - s.AfterEachAction(t) + action(s, ctx) + s.AfterEachAction(t, ctx) } - s.AfterEachCase(t) + s.AfterEachCase(t, ctx) }) } } diff --git a/tests/systemtests/mempool/test_ordering.go b/tests/systemtests/mempool/test_ordering.go index e428c5b2..844686f2 100644 --- a/tests/systemtests/mempool/test_ordering.go +++ b/tests/systemtests/mempool/test_ordering.go @@ -1,23 +1,33 @@ +//go:build system_test + package mempool import ( + "context" "fmt" "math/big" "testing" + "time" + + "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/holiman/uint256" + "github.com/stretchr/testify/require" "github.com/cosmos/evm/tests/systemtests/suite" - "github.com/test-go/testify/require" ) -func TestTxsOrdering(t *testing.T) { +func RunTxsOrdering(t *testing.T, base *suite.BaseTestSuite) { testCases := []struct { name string - actions []func(s TestSuite) + actions []func(*TestSuite, *TestContext) }{ { name: "ordering of pending txs %s", - actions: []func(s TestSuite){ - func(s TestSuite) { + actions: []func(*TestSuite, *TestContext){ + func(s *TestSuite, ctx *TestContext) { + signer := s.Acc(0) + expPendingTxs := make([]*suite.TxInfo, 5) for i := 0; i < 5; i++ { // nonce order of submitted txs: 3,4,0,1,2 @@ -31,14 +41,17 @@ func TestTxsOrdering(t *testing.T) { nodeId = s.Node(i % 4) } - txInfo, err := s.SendTx(t, nodeId, "acc0", nonceIdx, s.GetTxGasPrice(s.BaseFee()), big.NewInt(1)) - require.NoError(t, err, "failed to send tx") + txInfo, err := s.SendTx(t, nodeId, signer.ID, nonceIdx, s.GasPriceMultiplier(10), big.NewInt(1)) + require.NoError(t, err, "failed to send tx to node %s, nonce %d", nodeId, nonceIdx) // nonce order of committed txs: 0,1,2,3,4 expPendingTxs[nonceIdx] = txInfo } - s.SetExpPendingTxs(expPendingTxs...) + // Because txs are sent to different nodes, we need to wait for some blocks + // so that all nonce-gapped txs are gossiped to all nodes and committed sequentially. + s.AwaitNBlocks(t, 4) + ctx.SetExpPendingTxs(expPendingTxs...) }, }, }, @@ -57,7 +70,7 @@ func TestTxsOrdering(t *testing.T) { }, } - s := suite.NewSystemTestSuite(t) + s := NewTestSuite(base) s.SetupTest(t) for _, to := range testOptions { @@ -65,13 +78,169 @@ func TestTxsOrdering(t *testing.T) { for _, tc := range testCases { testName := fmt.Sprintf(tc.name, to.Description) t.Run(testName, func(t *testing.T) { - s.BeforeEachCase(t) + ctx := NewTestContext() + s.BeforeEachCase(t, ctx) for _, action := range tc.actions { - action(s) - s.AfterEachAction(t) + action(s, ctx) + // NOTE: In this test, we don't need to check mempool state after each action + // because we check the final state after all actions are done. + // s.AfterEachAction(t, ctx) --- IGNORE --- } - s.AfterEachCase(t) + s.AfterEachCase(t, ctx) }) } } } + +// RunSetCode7702QueuedTxPromotion proves that a queued tx whose nonce gap +// is closed by a self-sponsored 7702 actually promotes and lands. Submits +// tx5 (5 nonces ahead of chain head), then a self-sponsored 7702 with 4 +// self-auths to bump the sender's chain nonce by 5. Asserts both land. +func RunSetCode7702QueuedTxPromotion(t *testing.T, base *suite.BaseTestSuite) { + s := NewTestSuite(base) + s.SetupTest(t) + s.SetOptions(&suite.TestOptions{ + Description: "EVM SetCodeTx promotion lag", + TxType: suite.TxTypeEVM, + }) + + t.Run("queued tx promotes after self-sponsored 7702 closes the gap", func(t *testing.T) { + ctx := NewTestContext() + s.BeforeEachCase(t, ctx) + + signer := s.Acc(0) + nodeID := "node0" + + startNonce, err := s.NonceAt(nodeID, signer.ID) + require.NoError(t, err) + + // Queued tx 5 nonces ahead of chain head. + queuedTxInfo, err := s.SendTx(t, nodeID, signer.ID, 5, s.GasPriceMultiplier(10), big.NewInt(1)) + require.NoError(t, err, "failed to send queued tx") + require.NoError(t, s.CheckTxsQueuedAsync([]*suite.TxInfo{queuedTxInfo})) + + // Self-sponsored 7702 with 4 self-auths at startNonce+1..+4. + // Sender bump (+1) plus 4 auth bumps -> chain nonce += 5. + sevenSeven02Hash := sendSelfSponsored7702BulkAuths(t, s, nodeID, signer.ID, startNonce, 4) + + require.NoError(t, s.WaitForCommit(nodeID, sevenSeven02Hash.Hex(), suite.TxTypeEVM, 60*time.Second)) + require.NoError(t, s.WaitForCommit(nodeID, queuedTxInfo.TxHash, suite.TxTypeEVM, 60*time.Second)) + + // Chain nonce must reflect 7702 (+5) and queued tx (+1). + finalNonce, err := s.NonceAt(nodeID, signer.ID) + require.NoError(t, err) + require.GreaterOrEqual(t, finalNonce, startNonce+6) + + // Clear delegation so subsequent shared-suite cases see acc0 clean. + clearDelegation(t, s, nodeID, signer.ID, finalNonce) + }) +} + +// sendSelfSponsored7702BulkAuths constructs and sends a SetCodeTx where +// the sender is also the authority for `numAuths` consecutive auth slots +// starting at startNonce+1. Returns the tx hash. +func sendSelfSponsored7702BulkAuths( + t *testing.T, + s *TestSuite, + nodeID string, + accID string, + startNonce uint64, + numAuths uint64, +) common.Hash { + t.Helper() + + ctx := context.Background() + ethCli := s.EthClient.Clients[nodeID] + acc := s.EthAccount(accID) + require.NotNil(t, acc, "account %s not found", accID) + + chainID, err := ethCli.ChainID(ctx) + require.NoError(t, err) + + // Each auth points at a non-zero placeholder so the delegation + // actually applies (zero target is the "clear delegation" sentinel + // and would still bump the nonce, but using a real target keeps the + // test honest about a delegation actually being installed). + target := common.Address{0x42} + + auths := make([]ethtypes.SetCodeAuthorization, numAuths) + for i := uint64(0); i < numAuths; i++ { + raw := ethtypes.SetCodeAuthorization{ + ChainID: *uint256.MustFromBig(chainID), + Address: target, + Nonce: startNonce + 1 + i, + } + signed, signErr := ethtypes.SignSetCode(acc.PrivKey, raw) + require.NoError(t, signErr, "failed to sign auth %d", i) + auths[i] = signed + } + + txdata := ðtypes.SetCodeTx{ + ChainID: uint256.MustFromBig(chainID), + Nonce: startNonce, + GasTipCap: uint256.NewInt(1_000_000), + GasFeeCap: uint256.NewInt(1_000_000_000), + Gas: 200_000, + To: common.Address{}, + Value: uint256.NewInt(0), + Data: []byte{}, + AccessList: ethtypes.AccessList{}, + AuthList: auths, + } + + txSigner := ethtypes.LatestSignerForChainID(chainID) + signedTx := ethtypes.MustSignNewTx(acc.PrivKey, txSigner, txdata) + + require.NoError(t, ethCli.SendTransaction(ctx, signedTx), + fmt.Sprintf("failed to broadcast 7702 tx (nonce=%d, %d auths)", startNonce, numAuths)) + + return signedTx.Hash() +} + +// clearDelegation sends a self-sponsored 7702 with a single zero-address +// auth to remove any code delegation on the sender. +func clearDelegation( + t *testing.T, + s *TestSuite, + nodeID string, + accID string, + currentNonce uint64, +) { + t.Helper() + + ctx := context.Background() + ethCli := s.EthClient.Clients[nodeID] + acc := s.EthAccount(accID) + require.NotNil(t, acc) + + chainID, err := ethCli.ChainID(ctx) + require.NoError(t, err) + + clearAuth := ethtypes.SetCodeAuthorization{ + ChainID: *uint256.MustFromBig(chainID), + Address: common.Address{}, + Nonce: currentNonce + 1, + } + signedClear, err := ethtypes.SignSetCode(acc.PrivKey, clearAuth) + require.NoError(t, err) + + txdata := ðtypes.SetCodeTx{ + ChainID: uint256.MustFromBig(chainID), + Nonce: currentNonce, + GasTipCap: uint256.NewInt(1_000_000), + GasFeeCap: uint256.NewInt(1_000_000_000), + Gas: 100_000, + To: common.Address{}, + Value: uint256.NewInt(0), + Data: []byte{}, + AccessList: ethtypes.AccessList{}, + AuthList: []ethtypes.SetCodeAuthorization{signedClear}, + } + + txSigner := ethtypes.LatestSignerForChainID(chainID) + signedTx := ethtypes.MustSignNewTx(acc.PrivKey, txSigner, txdata) + + require.NoError(t, ethCli.SendTransaction(ctx, signedTx), + "failed to broadcast delegation-clear 7702") + require.NoError(t, s.WaitForCommit(nodeID, signedTx.Hash().Hex(), suite.TxTypeEVM, 60*time.Second)) +} diff --git a/tests/systemtests/mempool/test_replacement.go b/tests/systemtests/mempool/test_replacement.go index ebb2d67c..635ac118 100644 --- a/tests/systemtests/mempool/test_replacement.go +++ b/tests/systemtests/mempool/test_replacement.go @@ -1,3 +1,5 @@ +//go:build system_test + package mempool import ( @@ -6,97 +8,106 @@ import ( "testing" "github.com/cosmos/evm/tests/systemtests/suite" - "github.com/test-go/testify/require" + "github.com/stretchr/testify/require" ) -func TestTxsReplacement(t *testing.T) { +func RunTxsReplacement(t *testing.T, base *suite.BaseTestSuite) { testCases := []struct { name string - actions []func(s TestSuite) + actions []func(*TestSuite, *TestContext) }{ - { - 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.GetTxGasPrice(s.BaseFee()), nil) - require.NoError(t, err, "failed to send tx") - tx2, err := s.SendTx(t, s.Node(1), "acc0", 0, s.GetTxGasPrice(s.BaseFeeX2()), big.NewInt(1)) - require.NoError(t, err, "failed to send tx") - - s.SetExpPendingTxs(tx2) - }, - }, - }, - { - 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.GetTxGasPrice(s.BaseFee()), nil) - require.NoError(t, err, "failed to send tx") - tx2, err := s.SendTx(t, s.Node(1), "acc0", 0, s.GetTxGasPrice(s.BaseFeeX2()), big.NewInt(1)) - require.NoError(t, err, "failed to send tx") - - _, err = s.SendTx(t, s.Node(0), "acc0", 1, s.GetTxGasPrice(s.BaseFee()), nil) - require.NoError(t, err, "failed to send tx") - tx4, err := s.SendTx(t, s.Node(1), "acc0", 1, s.GetTxGasPrice(s.BaseFeeX2()), big.NewInt(1)) - require.NoError(t, err, "failed to send tx") - - _, err = s.SendTx(t, s.Node(0), "acc0", 2, s.GetTxGasPrice(s.BaseFee()), nil) - require.NoError(t, err, "failed to send tx") - tx6, err := s.SendTx(t, s.Node(1), "acc0", 2, s.GetTxGasPrice(s.BaseFeeX2()), big.NewInt(1)) - require.NoError(t, err, "failed to send tx") - - s.SetExpPendingTxs(tx2, tx4, tx6) - }, - }, - }, + // Note: These test cases are unstable in the GitHub CI environment. + // When running it locally, please uncomment it and run the test. + // + // { + // name: "single pending tx submitted to same nodes %s", + // actions: []func(*TestSuite, *TestContext){ + // func(s *TestSuite, ctx *TestContext) { + // signer := s.Acc(0) + // _, err := s.SendTx(t, s.Node(0), signer.ID, 0, s.GasPriceMultiplier(10), nil) + // require.NoError(t, err, "failed to send tx") + // tx2, err := s.SendTx(t, s.Node(1), signer.ID, 0, s.GasPriceMultiplier(20), big.NewInt(1)) + // require.NoError(t, err, "failed to send tx") + + // ctx.SetExpPendingTxs(tx2) + // }, + // }, + // }, + // { + // name: "multiple pending txs submitted to same nodes %s", + // actions: []func(*TestSuite, *TestContext){ + // func(s *TestSuite, ctx *TestContext) { + // signer := s.Acc(0) + // _, err := s.SendTx(t, s.Node(0), signer.ID, 0, s.GasPriceMultiplier(10), nil) + // require.NoError(t, err, "failed to send tx") + // tx2, err := s.SendTx(t, s.Node(1), signer.ID, 0, s.GasPriceMultiplier(20), big.NewInt(1)) + // require.NoError(t, err, "failed to send tx") + + // _, err = s.SendTx(t, s.Node(0), signer.ID, 1, s.GasPriceMultiplier(10), nil) + // require.NoError(t, err, "failed to send tx") + // tx4, err := s.SendTx(t, s.Node(1), signer.ID, 1, s.GasPriceMultiplier(20), big.NewInt(1)) + // require.NoError(t, err, "failed to send tx") + + // _, err = s.SendTx(t, s.Node(0), signer.ID, 2, s.GasPriceMultiplier(10), nil) + // require.NoError(t, err, "failed to send tx") + // tx6, err := s.SendTx(t, s.Node(1), signer.ID, 2, s.GasPriceMultiplier(20), big.NewInt(1)) + // require.NoError(t, err, "failed to send tx") + + // ctx.SetExpPendingTxs(tx2, tx4, tx6) + // }, + // }, + // }, { name: "single queued tx %s", - actions: []func(s TestSuite){ - func(s TestSuite) { - _, err := s.SendTx(t, s.Node(0), "acc0", 1, s.GetTxGasPrice(s.BaseFee()), nil) + actions: []func(*TestSuite, *TestContext){ + func(s *TestSuite, ctx *TestContext) { + signer := s.Acc(0) + _, err := s.SendTx(t, s.Node(0), signer.ID, 1, s.GasPriceMultiplier(10), nil) require.NoError(t, err, "failed to send tx") - tx2, err := s.SendTx(t, s.Node(0), "acc0", 1, s.GetTxGasPrice(s.BaseFeeX2()), big.NewInt(1)) + tx2, err := s.SendTx(t, s.Node(0), signer.ID, 1, s.GasPriceMultiplier(20), big.NewInt(1)) require.NoError(t, err, "failed to send tx") - s.SetExpQueuedTxs(tx2) + ctx.SetExpQueuedTxs(tx2) }, - func(s TestSuite) { - txHash, err := s.SendTx(t, s.Node(1), "acc0", 0, s.GetTxGasPrice(s.BaseFee()), nil) + func(s *TestSuite, ctx *TestContext) { + signer := s.Acc(0) + txHash, err := s.SendTx(t, s.Node(1), signer.ID, 0, s.GasPriceMultiplier(10), nil) require.NoError(t, err, "failed to send tx") - s.SetExpPendingTxs(txHash) - s.PromoteExpTxs(1) + ctx.SetExpPendingTxs(txHash) + ctx.PromoteExpTxs(1) }, }, }, { name: "multiple queued txs %s", - actions: []func(s TestSuite){ - func(s TestSuite) { - _, err := s.SendTx(t, s.Node(0), "acc0", 1, s.GetTxGasPrice(s.BaseFee()), nil) + actions: []func(*TestSuite, *TestContext){ + func(s *TestSuite, ctx *TestContext) { + signer := s.Acc(0) + _, err := s.SendTx(t, s.Node(0), signer.ID, 1, s.GasPriceMultiplier(10), nil) require.NoError(t, err, "failed to send tx") - tx2, err := s.SendTx(t, s.Node(0), "acc0", 1, s.GetTxGasPrice(s.BaseFeeX2()), big.NewInt(1)) + tx2, err := s.SendTx(t, s.Node(0), signer.ID, 1, s.GasPriceMultiplier(20), big.NewInt(1)) require.NoError(t, err, "failed to send tx") - _, err = s.SendTx(t, s.Node(1), "acc0", 2, s.GetTxGasPrice(s.BaseFee()), nil) + _, err = s.SendTx(t, s.Node(1), signer.ID, 2, s.GasPriceMultiplier(10), nil) require.NoError(t, err, "failed to send tx") - tx4, err := s.SendTx(t, s.Node(1), "acc0", 2, s.GetTxGasPrice(s.BaseFeeX2()), big.NewInt(1)) + tx4, err := s.SendTx(t, s.Node(1), signer.ID, 2, s.GasPriceMultiplier(20), big.NewInt(1)) require.NoError(t, err, "failed to send tx") - _, err = s.SendTx(t, s.Node(2), "acc0", 3, s.GetTxGasPrice(s.BaseFee()), nil) + _, err = s.SendTx(t, s.Node(2), signer.ID, 3, s.GasPriceMultiplier(10), nil) require.NoError(t, err, "failed to send tx") - tx6, err := s.SendTx(t, s.Node(2), "acc0", 3, s.GetTxGasPrice(s.BaseFeeX2()), big.NewInt(1)) + tx6, err := s.SendTx(t, s.Node(2), signer.ID, 3, s.GasPriceMultiplier(20), big.NewInt(1)) require.NoError(t, err, "failed to send tx") - s.SetExpQueuedTxs(tx2, tx4, tx6) + ctx.SetExpQueuedTxs(tx2, tx4, tx6) }, - func(s TestSuite) { - tx, err := s.SendTx(t, s.Node(3), "acc0", 0, s.GetTxGasPrice(s.BaseFee()), nil) + func(s *TestSuite, ctx *TestContext) { + signer := s.Acc(0) + tx, err := s.SendTx(t, s.Node(3), signer.ID, 0, s.GasPriceMultiplier(10), nil) require.NoError(t, err, "failed to send tx") - s.SetExpPendingTxs(tx) - s.PromoteExpTxs(3) + ctx.SetExpPendingTxs(tx) + ctx.PromoteExpTxs(3) }, }, }, @@ -115,7 +126,7 @@ func TestTxsReplacement(t *testing.T) { }, } - s := suite.NewSystemTestSuite(t) + s := NewTestSuite(base) s.SetupTest(t) for _, to := range testOptions { @@ -123,64 +134,68 @@ func TestTxsReplacement(t *testing.T) { for _, tc := range testCases { testName := fmt.Sprintf(tc.name, to.Description) t.Run(testName, func(t *testing.T) { - s.BeforeEachCase(t) + ctx := NewTestContext() + s.BeforeEachCase(t, ctx) for _, action := range tc.actions { - action(s) - s.AfterEachAction(t) + action(s, ctx) + s.AfterEachAction(t, ctx) } - s.AfterEachCase(t) + s.AfterEachCase(t, ctx) }) } } } -func TestTxsReplacementWithCosmosTx(t *testing.T) { +func RunTxsReplacementWithCosmosTx(t *testing.T, base *suite.BaseTestSuite) { t.Skip("This test does not work.") + testCases := []struct { name string - actions []func(s TestSuite) + actions []func(*TestSuite, *TestContext) }{ { name: "single pending tx submitted to same nodes %s", - actions: []func(s TestSuite){ - func(s TestSuite) { + actions: []func(*TestSuite, *TestContext){ + func(s *TestSuite, ctx *TestContext) { // NOTE: Currently EVMD cannot handle tx reordering correctly when cosmos tx is used. // It is because of CheckTxHandler cannot handle errors from SigVerificationDecorator properly. // After modifying CheckTxHandler, we can also modify this test case // : high prio cosmos tx should replace low prio evm tx. - tx1, err := s.SendTx(t, s.Node(0), "acc0", 0, s.GetTxGasPrice(s.BaseFee()), nil) + signer := s.Acc(0) + tx1, err := s.SendTx(t, s.Node(0), signer.ID, 0, s.GasPriceMultiplier(10), nil) + require.NoError(t, err, "failed to send tx") + _, err = s.SendTx(t, s.Node(1), signer.ID, 0, s.GasPriceMultiplier(20), big.NewInt(1)) require.NoError(t, err, "failed to send tx") - //_, err = s.SendTx(t, s.Node(1), "acc0", 0, s.GetTxGasPrice(s.BaseFeeX2()), big.NewInt(1)) - //require.NoError(t, err, "failed to send tx") - s.SetExpPendingTxs(tx1) + ctx.SetExpPendingTxs(tx1) }, }, }, { name: "multiple pending txs submitted to same nodes %s", - actions: []func(s TestSuite){ - func(s TestSuite) { + actions: []func(*TestSuite, *TestContext){ + func(s *TestSuite, ctx *TestContext) { // NOTE: Currently EVMD cannot handle tx reordering correctly when cosmos tx is used. // It is because of CheckTxHandler cannot handle errors from SigVerificationDecorator properly. // After modifying CheckTxHandler, we can also modify this test case // : high prio cosmos tx should replace low prio evm tx. - tx1, err := s.SendTx(t, s.Node(0), "acc0", 0, s.GetTxGasPrice(s.BaseFee()), nil) + signer := s.Acc(0) + tx1, err := s.SendTx(t, s.Node(0), signer.ID, 0, s.GasPriceMultiplier(10), nil) + require.NoError(t, err, "failed to send tx") + _, err = s.SendTx(t, s.Node(1), signer.ID, 0, s.GasPriceMultiplier(20), big.NewInt(1)) require.NoError(t, err, "failed to send tx") - //_, err = s.SendTx(t, s.Node(1), "acc0", 0, s.GetTxGasPrice(s.BaseFeeX2()), big.NewInt(1)) - //require.NoError(t, err, "failed to send tx") - tx3, err := s.SendTx(t, s.Node(0), "acc0", 1, s.GetTxGasPrice(s.BaseFee()), nil) + tx3, err := s.SendTx(t, s.Node(0), signer.ID, 1, s.GasPriceMultiplier(10), nil) + require.NoError(t, err, "failed to send tx") + _, err = s.SendTx(t, s.Node(1), signer.ID, 1, s.GasPriceMultiplier(20), big.NewInt(1)) require.NoError(t, err, "failed to send tx") - //_, err = s.SendTx(t, s.Node(1), "acc0", 1, s.GetTxGasPrice(s.BaseFeeX2()), big.NewInt(1)) - //require.NoError(t, err, "failed to send tx") - tx5, err := s.SendTx(t, s.Node(0), "acc0", 2, s.GetTxGasPrice(s.BaseFee()), nil) + tx5, err := s.SendTx(t, s.Node(0), signer.ID, 2, s.GasPriceMultiplier(10), nil) + require.NoError(t, err, "failed to send tx") + _, err = s.SendTx(t, s.Node(1), signer.ID, 2, s.GasPriceMultiplier(20), big.NewInt(1)) require.NoError(t, err, "failed to send tx") - //_, err = s.SendTx(t, s.Node(1), "acc0", 2, s.GetTxGasPrice(s.BaseFeeX2()), big.NewInt(1)) - //require.NoError(t, err, "failed to send tx") - s.SetExpPendingTxs(tx1, tx3, tx5) + ctx.SetExpPendingTxs(tx1, tx3, tx5) }, }, }, @@ -193,7 +208,7 @@ func TestTxsReplacementWithCosmosTx(t *testing.T) { }, } - s := suite.NewSystemTestSuite(t) + s := NewTestSuite(base) s.SetupTest(t) for _, to := range testOptions { @@ -201,105 +216,113 @@ func TestTxsReplacementWithCosmosTx(t *testing.T) { for _, tc := range testCases { testName := fmt.Sprintf(tc.name, to.Description) t.Run(testName, func(t *testing.T) { - s.BeforeEachCase(t) + ctx := NewTestContext() + s.BeforeEachCase(t, ctx) for _, action := range tc.actions { - action(s) - s.AfterEachAction(t) + action(s, ctx) + s.AfterEachAction(t, ctx) } - s.AfterEachCase(t) + s.AfterEachCase(t, ctx) }) } } } -func TestMixedTxsReplacementLegacyAndDynamicFee(t *testing.T) { +func RunMixedTxsReplacementLegacyAndDynamicFee(t *testing.T, base *suite.BaseTestSuite) { testCases := []struct { name string - actions []func(s TestSuite) + actions []func(*TestSuite, *TestContext) }{ { 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.GetTxGasPrice(s.BaseFee())) + actions: []func(*TestSuite, *TestContext){ + func(s *TestSuite, ctx *TestContext) { + signer := s.Acc(0) + tx1, err := s.SendEthLegacyTx(t, s.Node(0), signer.ID, 1, s.GasPriceMultiplier(10)) require.NoError(t, err, "failed to send eth legacy tx") - _, err = s.SendEthDynamicFeeTx(t, s.Node(0), s.Acc(0), 1, s.GetTxGasPrice(s.BaseFeeX2()), big.NewInt(1)) + _, err = s.SendEthDynamicFeeTx(t, s.Node(0), signer.ID, 1, s.GasPriceMultiplier(20), big.NewInt(1)) require.Error(t, err) require.Contains(t, err.Error(), "replacement transaction underpriced") - s.SetExpQueuedTxs(tx1) + ctx.SetExpQueuedTxs(tx1) }, - func(s TestSuite) { - txHash, err := s.SendEthLegacyTx(t, s.Node(0), s.Acc(0), 0, s.GetTxGasPrice(s.BaseFee())) + func(s *TestSuite, ctx *TestContext) { + signer := s.Acc(0) + txHash, err := s.SendEthLegacyTx(t, s.Node(0), signer.ID, 0, s.GasPriceMultiplier(10)) require.NoError(t, err, "failed to send tx") - s.SetExpPendingTxs(txHash) - s.PromoteExpTxs(1) + ctx.SetExpPendingTxs(txHash) + ctx.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.GetTxGasPrice(s.BaseFee())) + actions: []func(*TestSuite, *TestContext){ + func(s *TestSuite, ctx *TestContext) { + signer := s.Acc(0) + _, err := s.SendEthLegacyTx(t, s.Node(0), signer.ID, 1, s.GasPriceMultiplier(10)) require.NoError(t, err, "failed to send eth legacy tx") - tx2, err := s.SendEthDynamicFeeTx(t, s.Node(0), s.Acc(0), 1, - s.GetTxGasPrice(s.BaseFeeX2()), - s.GetTxGasPrice(s.BaseFeeX2()), + tx2, err := s.SendEthDynamicFeeTx(t, s.Node(0), signer.ID, 1, + s.GasPriceMultiplier(20), + s.GasPriceMultiplier(20), ) require.NoError(t, err) - s.SetExpQueuedTxs(tx2) + ctx.SetExpQueuedTxs(tx2) }, - func(s TestSuite) { - txHash, err := s.SendEthLegacyTx(t, s.Node(0), s.Acc(0), 0, s.GetTxGasPrice(s.BaseFee())) + func(s *TestSuite, ctx *TestContext) { + signer := s.Acc(0) + txHash, err := s.SendEthLegacyTx(t, s.Node(0), signer.ID, 0, s.GasPriceMultiplier(10)) require.NoError(t, err, "failed to send tx") - s.SetExpPendingTxs(txHash) - s.PromoteExpTxs(1) + ctx.SetExpPendingTxs(txHash) + ctx.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.GetTxGasPrice(s.BaseFeeX2()), - new(big.Int).Sub(s.GetTxGasPrice(s.BaseFee()), big.NewInt(1))) + actions: []func(*TestSuite, *TestContext){ + func(s *TestSuite, ctx *TestContext) { + signer := s.Acc(0) + tx1, err := s.SendEthDynamicFeeTx(t, s.Node(0), signer.ID, 1, s.GasPriceMultiplier(20), + new(big.Int).Sub(s.GasPriceMultiplier(10), big.NewInt(1))) require.NoError(t, err) - _, err = s.SendEthLegacyTx(t, s.Node(0), s.Acc(0), 1, s.GetTxGasPrice(s.BaseFee())) + _, err = s.SendEthLegacyTx(t, s.Node(0), signer.ID, 1, s.GasPriceMultiplier(10)) 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) + ctx.SetExpQueuedTxs(tx1) }, - func(s TestSuite) { - txHash, err := s.SendEthLegacyTx(t, s.Node(0), s.Acc(0), 0, s.GetTxGasPrice(s.BaseFee())) + func(s *TestSuite, ctx *TestContext) { + signer := s.Acc(0) + txHash, err := s.SendEthLegacyTx(t, s.Node(0), signer.ID, 0, s.GasPriceMultiplier(10)) require.NoError(t, err, "failed to send tx") - s.SetExpPendingTxs(txHash) - s.PromoteExpTxs(1) + ctx.SetExpPendingTxs(txHash) + ctx.PromoteExpTxs(1) }, }, }, } - s := suite.NewSystemTestSuite(t) + s := NewTestSuite(base) s.SetupTest(t) for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - s.BeforeEachCase(t) + ctx := NewTestContext() + s.BeforeEachCase(t, ctx) for _, action := range tc.actions { - action(s) - s.AfterEachAction(t) + action(s, ctx) + s.AfterEachAction(t, ctx) } - s.AfterEachCase(t) + s.AfterEachCase(t, ctx) }) } } diff --git a/tests/systemtests/mempool/test_suite.go b/tests/systemtests/mempool/test_suite.go new file mode 100644 index 00000000..fd58840a --- /dev/null +++ b/tests/systemtests/mempool/test_suite.go @@ -0,0 +1,107 @@ +//go:build system_test + +package mempool + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/evm/tests/systemtests/suite" +) + +const txPoolContentTimeout = 120 * time.Second + +// Suite wraps the shared BaseTestSuite with mempool-specific helpers. +type TestSuite struct { + *suite.BaseTestSuite +} + +func NewTestSuite(base *suite.BaseTestSuite) *TestSuite { + return &TestSuite{BaseTestSuite: base} +} + +func (s *TestSuite) SetupTest(t *testing.T) { + s.BaseTestSuite.SetupTest(t) +} + +func (s *TestSuite) SetupTestWithTimeoutCommit(t *testing.T, tc time.Duration) { + s.BaseTestSuite.SetupTest(t, suite.WithTimeoutCommit(tc)) +} + +// GetCurrentBlockHeight returns the current block height from the specified node +func (s *TestSuite) GetCurrentBlockHeight(t *testing.T, nodeID string) uint64 { + t.Helper() + account := s.EthAccount("acc0") + ctx, cli, _ := s.EthClient.Setup(nodeID, account) + blockNumber, err := cli.BlockNumber(ctx) + require.NoError(t, err, "failed to get block number from %s", nodeID) + return blockNumber +} + +// BeforeEach resets the expected mempool state and retrieves the current base fee before each test case +func (s *TestSuite) BeforeEachCase(t *testing.T, ctx *TestContext) { + ctx.Reset() + + // Get current base fee + currentBaseFee, err := s.GetLatestBaseFee("node0") + require.NoError(t, err) + + s.SetBaseFee(currentBaseFee) +} + +func (s *TestSuite) AfterEachAction(t *testing.T, ctx *TestContext) { + require.NoError(t, s.CheckTxsPendingAsync(ctx.ExpPending)) + require.NoError(t, s.CheckTxsQueuedAsync(ctx.ExpQueued)) + + currentBaseFee, err := s.GetLatestBaseFee("node0") + if err != nil { + // If we fail to get the latest base fee, we just keep the previous one + currentBaseFee = s.BaseFee() + } + s.SetBaseFee(currentBaseFee) +} + +func (s *TestSuite) AfterEachCase(t *testing.T, ctx *TestContext) { + for _, txInfo := range ctx.ExpPending { + err := s.WaitForCommit(txInfo.DstNodeID, txInfo.TxHash, txInfo.TxType, txPoolContentTimeout) + require.NoError(t, err) + } +} + +type TestContext struct { + ExpPending []*suite.TxInfo + ExpQueued []*suite.TxInfo +} + +func NewTestContext() *TestContext { + return &TestContext{} +} + +func (c *TestContext) Reset() { + c.ExpPending = nil + c.ExpQueued = nil +} + +func (c *TestContext) SetExpPendingTxs(txs ...*suite.TxInfo) { + c.ExpPending = append(c.ExpPending[:0], txs...) +} + +func (c *TestContext) SetExpQueuedTxs(txs ...*suite.TxInfo) { + c.ExpQueued = append(c.ExpQueued[:0], txs...) +} + +func (c *TestContext) PromoteExpTxs(count int) { + if count <= 0 || len(c.ExpQueued) == 0 { + return + } + + if count > len(c.ExpQueued) { + count = len(c.ExpQueued) + } + + promoted := c.ExpQueued[:count] + c.ExpPending = append(c.ExpPending, promoted...) + c.ExpQueued = c.ExpQueued[count:] +} diff --git a/tests/systemtests/suite/query.go b/tests/systemtests/suite/query.go index 76ac64c4..ab227adb 100644 --- a/tests/systemtests/suite/query.go +++ b/tests/systemtests/suite/query.go @@ -1,6 +1,7 @@ package suite import ( + "context" "fmt" "maps" "math/big" @@ -11,8 +12,9 @@ import ( ) // 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) +func (s *BaseTestSuite) NonceAt(nodeID string, accID string) (uint64, error) { + account := s.EthAccount(accID) + ctx, cli, addr := s.EthClient.Setup(nodeID, account) 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) @@ -24,8 +26,9 @@ func (s *SystemTestSuite) NonceAt(nodeID string, accID string) (uint64, error) { } // 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") +func (s *BaseTestSuite) GetLatestBaseFee(nodeID string) (*big.Int, error) { + account := s.EthAccount("acc0") + ctx, cli, _ := s.EthClient.Setup(nodeID, account) blockNumber, err := cli.BlockNumber(ctx) if err != nil { return nil, fmt.Errorf("failed to get block number from %s: %v", nodeID, err) @@ -47,7 +50,7 @@ func (s *SystemTestSuite) GetLatestBaseFee(nodeID string) (*big.Int, error) { } // BaseFee returns the base fee of the latest block -func (s *SystemTestSuite) WaitForCommit( +func (s *BaseTestSuite) WaitForCommit( nodeID string, txHash string, txType string, @@ -64,7 +67,7 @@ func (s *SystemTestSuite) WaitForCommit( } // waitForEthCommmit waits for the given eth tx to be committed within the timeout duration -func (s *SystemTestSuite) waitForEthCommmit( +func (s *BaseTestSuite) waitForEthCommmit( nodeID string, txHash string, timeout time.Duration, @@ -82,7 +85,7 @@ func (s *SystemTestSuite) waitForEthCommmit( } // waitForCosmosCommmit waits for the given cosmos tx to be committed within the timeout duration -func (s *SystemTestSuite) waitForCosmosCommmit( +func (s *BaseTestSuite) waitForCosmosCommmit( nodeID string, txHash string, timeout time.Duration, @@ -99,8 +102,8 @@ func (s *SystemTestSuite) waitForCosmosCommmit( return nil } -// CheckTxsPending checks if the given tx is either pending or committed within the timeout duration -func (s *SystemTestSuite) CheckTxPending( +// CheckTxPending checks if the given tx is pending within the timeout duration +func (s *BaseTestSuite) CheckTxPending( nodeID string, txHash string, txType string, @@ -110,27 +113,45 @@ func (s *SystemTestSuite) CheckTxPending( case TxTypeEVM: return s.EthClient.CheckTxsPending(nodeID, txHash, timeout) case TxTypeCosmos: - return s.CosmosClient.CheckTxsPending(nodeID, txHash, timeout) + // Note: Cosmos transactions vanish from the mempool right after they get included in a block. + // CosmosClient.CheckTxsPending therefore treats “pending or already committed” as success, + // whereas the EVM client keeps transactions in the EVM pool until nonce progression occurs. + err := s.CosmosClient.CheckTxsPending(nodeID, txHash, timeout) + if err != nil { + _, err = s.CosmosClient.WaitForCommit(nodeID, txHash, timeout) + return err + } + return nil + default: return fmt.Errorf("invalid tx type") } } +const defaultTxPoolContentTimeout = 60 * time.Second + // 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) { +func (s *BaseTestSuite) TxPoolContent(nodeID string, txType string, timeout time.Duration) (pendingTxs, queuedTxs []string, err error) { + if timeout <= 0 { + timeout = defaultTxPoolContentTimeout + } + switch txType { case TxTypeEVM: - return s.ethTxPoolContent(nodeID) + return s.ethTxPoolContent(nodeID, timeout) case TxTypeCosmos: - return s.cosmosTxPoolContent(nodeID) + return s.cosmosTxPoolContent(nodeID, timeout) 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) +func (s *BaseTestSuite) ethTxPoolContent(nodeID string, timeout time.Duration) (pendingTxHashes, queuedTxHashes []string, err error) { + ctx, cancel := context.WithTimeout(context.Background(), timeout) + defer cancel() + + pendingTxs, queuedTxs, err := s.EthClient.TxPoolContent(ctx, nodeID) if err != nil { return nil, nil, fmt.Errorf("failed to get txpool content from eth client: %v", err) } @@ -139,8 +160,11 @@ func (s *SystemTestSuite) ethTxPoolContent(nodeID string) (pendingTxHashes, queu } // 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) +func (s *BaseTestSuite) cosmosTxPoolContent(nodeID string, timeout time.Duration) (pendingTxHashes, queuedTxHashes []string, err error) { + ctx, cancel := context.WithTimeout(context.Background(), timeout) + defer cancel() + + result, err := s.CosmosClient.UnconfirmedTxs(ctx, nodeID) if err != nil { return nil, nil, fmt.Errorf("failed to call unconfired transactions from cosmos client: %v", err) } @@ -154,7 +178,7 @@ func (s *SystemTestSuite) cosmosTxPoolContent(nodeID string) (pendingTxHashes, q } // 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 { +func (s *BaseTestSuite) extractTxHashesSorted(txMap map[string]map[string]*clients.EthRPCTransaction) []string { var result []string // Get addresses and sort them for deterministic iteration diff --git a/tests/systemtests/suite/test_helpers.go b/tests/systemtests/suite/test_helpers.go index 06403475..ff6e1479 100644 --- a/tests/systemtests/suite/test_helpers.go +++ b/tests/systemtests/suite/test_helpers.go @@ -1,74 +1,84 @@ package suite import ( + "context" "fmt" "math/big" "slices" "sync" "time" + + "github.com/cosmos/evm/tests/systemtests/clients" ) // BaseFee returns the most recently retrieved and stored baseFee. -func (s *SystemTestSuite) BaseFee() *big.Int { +func (s *BaseTestSuite) 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)) -} +// BaseFeeMultiplier returns the cached base fee scaled by the provided multiplier. +func (s *BaseTestSuite) BaseFeeMultiplier(multiplier int64) *big.Int { + if multiplier <= 0 { + panic("base fee multiplier must be positive") + } -func (s *SystemTestSuite) GetTxGasPrice(baseFee *big.Int) *big.Int { - return new(big.Int).Mul(baseFee, big.NewInt(10)) -} + if s.baseFee == nil { + panic("base fee is not initialized") + } -// GetExpPendingTxs returns the expected pending transactions -func (s *SystemTestSuite) GetExpPendingTxs() []*TxInfo { - return s.expPendingTxs + return new(big.Int).Mul(s.baseFee, big.NewInt(multiplier)) } -// SetExpPendingTxs sets the expected pending transactions -func (s *SystemTestSuite) SetExpPendingTxs(txs ...*TxInfo) { - s.expPendingTxs = txs +// SetBaseFee overrides the cached base fee. +func (s *BaseTestSuite) SetBaseFee(fee *big.Int) { + if fee == nil { + s.baseFee = nil + return + } + s.baseFee = new(big.Int).Set(fee) } -// GetExpQueuedTxs returns the expected queued transactions -func (s *SystemTestSuite) GetExpQueuedTxs() []*TxInfo { - return s.expQueuedTxs +const DefaultGasPriceMultiplier int64 = 10 + +// GasPrice returns the gas price computed from the cached base fee using the default multiplier. +func (s *BaseTestSuite) GasPrice() *big.Int { + return s.GasPriceMultiplier(DefaultGasPriceMultiplier) } -// 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) +// GasPriceMultiplier returns the gas price computed from the cached base fee scaled by the provided multiplier. +func (s *BaseTestSuite) GasPriceMultiplier(multiplier int64) *big.Int { + if multiplier <= 0 { + panic("gas price multiplier must be positive") } - 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 + if s.baseFee == nil { + panic("base fee is not initialized") } - // Ensure we don't try to promote more than available - actualCount := count - if actualCount > len(s.expQueuedTxs) { - actualCount = len(s.expQueuedTxs) + return new(big.Int).Mul(s.baseFee, big.NewInt(multiplier)) +} + +// Account returns the shared test account matching the identifier. +func (s *BaseTestSuite) Account(id string) *TestAccount { + acc, ok := s.accountsByID[id] + if !ok { + panic(fmt.Sprintf("account %s not found", id)) } + return acc +} - // Pop from expQueuedTxs and push to expPendingTxs - txs := s.expQueuedTxs[:actualCount] - s.expPendingTxs = append(s.expPendingTxs, txs...) - s.expQueuedTxs = s.expQueuedTxs[actualCount:] +// EthAccount returns the Ethereum account associated with the given identifier. +func (s *BaseTestSuite) EthAccount(id string) *clients.EthAccount { + return s.Account(id).Eth +} + +// CosmosAccount returns the Cosmos account associated with the given identifier. +func (s *BaseTestSuite) CosmosAccount(id string) *clients.CosmosAccount { + return s.Account(id).Cosmos } // Nodes returns the node IDs in the system under test -func (s *SystemTestSuite) Nodes() []string { +func (s *BaseTestSuite) Nodes() []string { nodes := make([]string, 4) for i := 0; i < 4; i++ { nodes[i] = fmt.Sprintf("node%d", i) @@ -77,46 +87,55 @@ func (s *SystemTestSuite) Nodes() []string { } // Node returns the node ID for the given index -func (s *SystemTestSuite) Node(idx int) string { +func (s *BaseTestSuite) 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) +// Acc returns the test account for the given index +func (s *BaseTestSuite) Acc(idx int) *TestAccount { + if idx < 0 || idx >= len(s.accounts) { + panic(fmt.Sprintf("account index out of range: %d", idx)) + } + return s.accounts[idx] +} + +// AccID returns the identifier of the test account for the given index. +func (s *BaseTestSuite) AccID(idx int) string { + return s.Acc(idx).ID } // GetOptions returns the current test options -func (s *SystemTestSuite) GetOptions() *TestOptions { +func (s *BaseTestSuite) GetOptions() *TestOptions { return s.options } // SetOptions sets the current test options -func (s *SystemTestSuite) SetOptions(options *TestOptions) { +func (s *BaseTestSuite) 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 { +func (s *BaseTestSuite) 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 + var ( + wg sync.WaitGroup + mu sync.Mutex + errors []error + ) 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*120) + err := s.CheckTxPending(tx.DstNodeID, tx.TxHash, tx.TxType, defaultTxPoolContentTimeout) if err != nil { mu.Lock() - errors = append(errors, fmt.Errorf("tx %s is not pending or committed: %v", tx.TxHash, err)) + errors = append(errors, fmt.Errorf("tx %s is not pending: %v", tx.TxHash, err)) mu.Unlock() } }(txInfo) @@ -132,29 +151,81 @@ func (s *SystemTestSuite) CheckTxsPendingAsync(expPendingTxs []*TxInfo) error { 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: %w", err) - } - queuedHashes[i] = queued - pendingHashes[i] = pending +// CheckTxsQueuedAsync verifies asynchronously that the expected queued transactions are actually queued +// (and not pending) in the mempool. It mirrors CheckTxsPendingAsync in style to better surface API +// failures when querying txpool content. +func (s *BaseTestSuite) CheckTxsQueuedAsync(expQueuedTxs []*TxInfo) error { + if len(expQueuedTxs) == 0 { + return nil + } + + type nodeContent struct { + nodeID string + pendingHashes []string + queuedHashes []string + } + + nodes := s.Nodes() + contents := make([]nodeContent, len(nodes)) + + var ( + wg sync.WaitGroup + mu sync.Mutex + errors []error + ) + + for idx, nodeID := range nodes { + wg.Add(1) + go func(i int, nID string) { //nolint:gosec // Concurrency is intentional for parallel tx checking + defer wg.Done() + + ctx, cancel := context.WithTimeout(context.Background(), defaultTxPoolContentTimeout) + defer cancel() + + ticker := time.NewTicker(100 * time.Millisecond) + defer ticker.Stop() + + var lastErr error + for { + pending, queued, err := s.TxPoolContent(nID, TxTypeEVM, defaultTxPoolContentTimeout) + if err == nil { + contents[i] = nodeContent{ + nodeID: nID, + pendingHashes: pending, + queuedHashes: queued, + } + return + } + lastErr = err + + select { + case <-ctx.Done(): + mu.Lock() + errors = append(errors, fmt.Errorf("failed to call txpool_content api on %s: %w", nID, lastErr)) + mu.Unlock() + return + case <-ticker.C: + } + } + }(idx, nodeID) + } + + wg.Wait() + + if len(errors) > 0 { + return fmt.Errorf("failed to check queued transactions: %w", errors[0]) } - for _, txInfo := range s.GetExpQueuedTxs() { + for _, txInfo := range expQueuedTxs { if txInfo.TxType != TxTypeEVM { panic("queued txs should be only EVM txs") } - for i := range s.Nodes() { - pendingTxHashes := pendingHashes[i] - queuedTxHashes := queuedHashes[i] + for _, content := range contents { + pendingTxHashes := content.pendingHashes + queuedTxHashes := content.queuedHashes - if s.Node(i) == txInfo.DstNodeID { + if content.nodeID == 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) } diff --git a/tests/systemtests/suite/test_suite.go b/tests/systemtests/suite/test_suite.go index 345c8522..6867f864 100644 --- a/tests/systemtests/suite/test_suite.go +++ b/tests/systemtests/suite/test_suite.go @@ -1,21 +1,33 @@ package suite import ( + "crypto/ecdsa" + "fmt" "math/big" + "os" + "path/filepath" + "slices" + "sync" "testing" "time" - "github.com/cosmos/evm/tests/systemtests/clients" + "github.com/creachadair/tomledit" + "github.com/creachadair/tomledit/parser" + "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" - "cosmossdk.io/systemtests" + "github.com/cosmos/evm/crypto/ethsecp256k1" + "github.com/cosmos/evm/tests/systemtests/clients" + + "github.com/cosmos/cosmos-sdk/tools/systemtests" + sdk "github.com/cosmos/cosmos-sdk/types" ) -// SystemTestSuite implements the TestSuite interface and +// BaseTestSuite implements the TestSuite interface and // provides methods for managing test lifecycle, // sending transactions, querying state, // and managing expected mempool state. -type SystemTestSuite struct { +type BaseTestSuite struct { *systemtests.SystemUnderTest options *TestOptions @@ -23,96 +35,240 @@ type SystemTestSuite struct { EthClient *clients.EthClient CosmosClient *clients.CosmosClient + // Accounts shared across clients + accounts []*TestAccount + accountsByID map[string]*TestAccount + + // Chain management + chainMu sync.Mutex + currentNodeArgs []string + currentNodeConfig TestSetupConfig + // Most recently retrieved base fee baseFee *big.Int - // Expected transaction hashes - expPendingTxs []*TxInfo - expQueuedTxs []*TxInfo + // Extra node start args on top of default + nodeStartArgs []string } -func NewSystemTestSuite(t *testing.T) *SystemTestSuite { - ethClient, err := clients.NewEthClient() +func NewBaseTestSuite(t *testing.T) *BaseTestSuite { + ethClient, ethAccounts, err := clients.NewEthClient() require.NoError(t, err) - cosmosClient, err := clients.NewCosmosClient() + cosmosClient, cosmosAccounts, err := clients.NewCosmosClient() require.NoError(t, err) - return &SystemTestSuite{ + accountCount := len(ethAccounts) + require.Equal(t, accountCount, len(cosmosAccounts), "ethereum/cosmos account mismatch") + accounts := make([]*TestAccount, accountCount) + accountsByID := make(map[string]*TestAccount, accountCount) + for i := 0; i < accountCount; i++ { + id := fmt.Sprintf("acc%d", i) + ethAcc, ok := ethAccounts[id] + require.Truef(t, ok, "ethereum account %s not found", id) + cosmosAcc, ok := cosmosAccounts[id] + require.Truef(t, ok, "cosmos account %s not found", id) + acc := &TestAccount{ + ID: id, + Address: ethAcc.Address, + AccAddress: cosmosAcc.AccAddress, + AccNumber: cosmosAcc.AccountNumber, + ECDSAPrivKey: ethAcc.PrivKey, + PrivKey: cosmosAcc.PrivKey, + Eth: ethAcc, + Cosmos: cosmosAcc, + } + accounts[i] = acc + accountsByID[id] = acc + } + + suite := &BaseTestSuite{ SystemUnderTest: systemtests.Sut, EthClient: ethClient, CosmosClient: cosmosClient, + accounts: accounts, + accountsByID: accountsByID, + } + return suite +} + +var ( + sharedSuiteOnce sync.Once + sharedSuite *BaseTestSuite +) + +func GetSharedSuite(t *testing.T) *BaseTestSuite { + t.Helper() + + sharedSuiteOnce.Do(func() { + sharedSuite = NewBaseTestSuite(t) + }) + + return sharedSuite +} + +// RunWithSharedSuite retrieves the shared suite instance and executes the provided test function. +func RunWithSharedSuite(t *testing.T, fn func(*testing.T, *BaseTestSuite), nodeStartArgs ...string) { + t.Helper() + suite := GetSharedSuite(t) + suite.SetNodeStartArgs(nodeStartArgs...) + fn(t, suite) +} + +func (suite *BaseTestSuite) SetNodeStartArgs(nodeStartArgs ...string) { + suite.nodeStartArgs = nodeStartArgs +} + +// TestAccount aggregates account metadata usable across both Ethereum and Cosmos flows. +type TestAccount struct { + ID string + Address common.Address + AccAddress sdk.AccAddress + AccNumber uint64 + + ECDSAPrivKey *ecdsa.PrivateKey + PrivKey *ethsecp256k1.PrivKey + + Eth *clients.EthAccount + Cosmos *clients.CosmosAccount +} + +type TestSetupConfig struct { + timeoutCommit time.Duration +} + +func (tc TestSetupConfig) Equals(other TestSetupConfig) bool { + return tc.timeoutCommit == other.timeoutCommit +} + +type TestSetupConfigOption func(*TestSetupConfig) + +func WithTimeoutCommit(tc time.Duration) TestSetupConfigOption { + return func(tsc *TestSetupConfig) { + tsc.timeoutCommit = tc } } // 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() +func (s *BaseTestSuite) SetupTest(t *testing.T, opts ...TestSetupConfigOption) { + t.Helper() + + var cfg TestSetupConfig + for _, opt := range opts { + opt(&cfg) } - s.ResetChain(t) - s.StartChain(t, nodeStartArgs...) - s.AwaitNBlocks(t, 2) -} + if len(s.nodeStartArgs) == 0 { + s.nodeStartArgs = DefaultNodeArgs() + } -// 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.expPendingTxs = []*TxInfo{} - s.expQueuedTxs = []*TxInfo{} + s.LockChain() + defer s.UnlockChain() - // Get current base fee - currentBaseFee, err := s.GetLatestBaseFee("node0") - require.NoError(t, err) + if !s.ChainStarted { + s.currentNodeArgs = nil + s.currentNodeConfig = TestSetupConfig{} + } + + if s.ChainStarted && slices.Equal(s.nodeStartArgs, s.currentNodeArgs) && s.currentNodeConfig == cfg { + // Chain already running with desired configuration; nothing to do. + return + } - s.baseFee = currentBaseFee + if s.ChainStarted { + s.ResetChain(t) + } + + s.ModifyCometMempool(t, "app") + + if cfg.timeoutCommit > time.Duration(0) { + s.ModifyConsensusTimeout(t, cfg.timeoutCommit.String()) + } else { + // if not set, default to 2s + s.ModifyConsensusTimeout(t, time.Duration(2*time.Second).String()) + } + + s.StartChain(t, s.nodeStartArgs...) + s.currentNodeConfig = cfg + s.AwaitNBlocks(t, 2) } -// 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) +// LockChain acquires exclusive control over the underlying chain lifecycle. +func (s *BaseTestSuite) LockChain() { + s.chainMu.Lock() +} - // Check queued txs only exist in local mempool (queued txs should be only EVM txs) - err = s.CheckTxsQueuedSync(s.GetExpQueuedTxs()) - require.NoError(t, err) +// UnlockChain releases the chain lifecycle lock. +func (s *BaseTestSuite) UnlockChain() { + s.chainMu.Unlock() +} - // Wait for block commit - s.AwaitNBlocks(t, 1) +// ModifyCometMempool modifies the mempool type in the config.toml +func (s *BaseTestSuite) ModifyCometMempool(t *testing.T, mempoolType string) { + t.Helper() - // Get current base fee and set it to suite.baseFee - currentBaseFee, err := s.GetLatestBaseFee("node0") - require.NoError(t, err) + // Modify config.toml for each node + for i := 0; i < s.NodesCount(); i++ { + nodeDir := s.NodeDir(i) + configPath := filepath.Join(nodeDir, "config", "config.toml") - s.baseFee = currentBaseFee + err := editToml(configPath, func(doc *tomledit.Document) { + setValue(doc, mempoolType, "mempool", "type") + }) + require.NoError(t, err, "failed to modify config.toml for node %d", i) + } } -// 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*60) - require.NoError(t, err) +// ModifyConsensusTimeout modifies the consensus timeout_commit in the config.toml +// for all nodes and restarts the chain with the new configuration. +func (s *BaseTestSuite) ModifyConsensusTimeout(t *testing.T, timeout string) { + t.Helper() + + // Modify config.toml for each node + for i := 0; i < s.NodesCount(); i++ { + nodeDir := s.NodeDir(i) + configPath := filepath.Join(nodeDir, "config", "config.toml") + + err := editToml(configPath, func(doc *tomledit.Document) { + setValue(doc, timeout, "consensus", "timeout_commit") + }) + require.NoError(t, err, "failed to modify config.toml for node %d", i) } +} - // 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) +// editToml is a helper to edit TOML files +func editToml(filename string, f func(doc *tomledit.Document)) error { + tomlFile, err := os.OpenFile(filename, os.O_RDWR, 0o600) + if err != nil { + return fmt.Errorf("failed to open file: %w", err) + } + defer tomlFile.Close() - require.Len(t, pending, 0, "pending txs are not cleared in mempool") + doc, err := tomledit.Parse(tomlFile) + if err != nil { + return fmt.Errorf("failed to parse toml: %w", err) } - // 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) + f(doc) - require.Len(t, pending, 0, "pending txs are not cleared in mempool") + if _, err := tomlFile.Seek(0, 0); err != nil { + return fmt.Errorf("failed to seek: %w", err) + } + if err := tomlFile.Truncate(0); err != nil { + return fmt.Errorf("failed to truncate: %w", err) + } + if err := tomledit.Format(tomlFile, doc); err != nil { + return fmt.Errorf("failed to format: %w", err) } - // Wait for block commit - s.AwaitNBlocks(t, 1) + return nil +} + +// setValue sets a value in a TOML document +func setValue(doc *tomledit.Document, newVal string, xpath ...string) { + e := doc.First(xpath...) + if e == nil { + panic(fmt.Sprintf("not found: %v", xpath)) + } + e.Value = parser.MustValue(fmt.Sprintf("%q", newVal)) } diff --git a/tests/systemtests/suite/tx.go b/tests/systemtests/suite/tx.go index 78a90f13..c2e47a47 100644 --- a/tests/systemtests/suite/tx.go +++ b/tests/systemtests/suite/tx.go @@ -10,7 +10,7 @@ import ( ) // GetOptions retrieves the current test options. -func (s *SystemTestSuite) SendTx( +func (s *BaseTestSuite) SendTx( t *testing.T, nodeID string, accID string, @@ -26,7 +26,7 @@ func (s *SystemTestSuite) SendTx( } // SendEthTx sends an Ethereum transaction (either Legacy or Dynamic Fee based on options). -func (s *SystemTestSuite) SendEthTx( +func (s *BaseTestSuite) SendEthTx( t *testing.T, nodeID string, accID string, @@ -42,7 +42,7 @@ func (s *SystemTestSuite) SendEthTx( } // SendEthLegacyTx sends an Ethereum legacy transaction. -func (s *SystemTestSuite) SendEthLegacyTx( +func (s *BaseTestSuite) SendEthLegacyTx( t *testing.T, nodeID string, accID string, @@ -54,12 +54,13 @@ func (s *SystemTestSuite) SendEthLegacyTx( return nil, fmt.Errorf("failed to get current nonce: %v", err) } gappedNonce := nonce + nonceIdx - to := s.EthClient.Accs["acc3"].Address + to := s.EthAccount("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) + account := s.EthAccount(accID) + txHash, err := s.EthClient.SendRawTransaction(nodeID, account, tx) if err != nil { return nil, fmt.Errorf("failed to send eth legacy tx: %v", err) } @@ -68,7 +69,7 @@ func (s *SystemTestSuite) SendEthLegacyTx( } // SendEthDynamicFeeTx sends an Ethereum dynamic fee transaction. -func (s *SystemTestSuite) SendEthDynamicFeeTx( +func (s *BaseTestSuite) SendEthDynamicFeeTx( t *testing.T, nodeID string, accID string, @@ -81,18 +82,20 @@ func (s *SystemTestSuite) SendEthDynamicFeeTx( return nil, fmt.Errorf("failed to get current nonce: %v", err) } gappedNonce := nonce + nonceIdx + toAddr := s.EthAccount("acc3").Address + account := s.EthAccount(accID) tx := ethtypes.NewTx(ðtypes.DynamicFeeTx{ ChainID: s.EthClient.ChainID, Nonce: gappedNonce, - To: &(s.EthClient.Accs["acc3"].Address), + To: &toAddr, Value: big.NewInt(1000), Gas: uint64(50_000), GasFeeCap: gasFeeCap, GasTipCap: gasTipCap, }) - txHash, err := s.EthClient.SendRawTransaction(nodeID, accID, tx) + txHash, err := s.EthClient.SendRawTransaction(nodeID, account, tx) if err != nil { return nil, fmt.Errorf("failed to send eth dynamic fee tx: %v", err) } @@ -101,7 +104,7 @@ func (s *SystemTestSuite) SendEthDynamicFeeTx( } // SendCosmosTx sends a Cosmos transaction. -func (s *SystemTestSuite) SendCosmosTx( +func (s *BaseTestSuite) SendCosmosTx( t *testing.T, nodeID string, accID string, @@ -109,8 +112,9 @@ func (s *SystemTestSuite) SendCosmosTx( gasPrice *big.Int, gasTipCap *big.Int, ) (*TxInfo, error) { - from := s.CosmosClient.Accs[accID].AccAddress - to := s.CosmosClient.Accs["acc3"].AccAddress + cosmosAccount := s.CosmosAccount(accID) + from := cosmosAccount.AccAddress + to := s.CosmosAccount("acc3").AccAddress amount := sdkmath.NewInt(1000) nonce, err := s.NonceAt(nodeID, accID) @@ -119,7 +123,7 @@ func (s *SystemTestSuite) SendCosmosTx( } gappedNonce := nonce + nonceIdx - resp, err := s.CosmosClient.BankSend(nodeID, accID, from, to, amount, gappedNonce, gasPrice) + resp, err := s.CosmosClient.BankSend(nodeID, cosmosAccount, from, to, amount, gappedNonce, gasPrice) if err != nil { return nil, fmt.Errorf("failed to send cosmos bank send tx: %v", err) } diff --git a/tests/systemtests/suite/types.go b/tests/systemtests/suite/types.go index 6ddcbabf..f5f82a37 100644 --- a/tests/systemtests/suite/types.go +++ b/tests/systemtests/suite/types.go @@ -11,6 +11,9 @@ const ( NodeArgsJsonrpcAllowUnprotectedTxs = "--json-rpc.allow-unprotected-txs=true" NodeArgsMinimumGasPrice = "--minimum-gas-prices=0.000001atest" NodeArgsMaxTxs = "--mempool.max-txs=0" + + NodeArgPendingTxProposalTimeout = "--evm.mempool.pending-tx-proposal-timeout=200ms" + NodeArgInsertQueueSize = "--evm.mempool.insert-queue-size=1000" ) // TestOptions defines the options for a test case. @@ -55,10 +58,27 @@ func MinimumGasPriceZeroArgs() []string { // Remove the default minimum gas price argument var args []string for _, arg := range defaultArgs { - if arg != NodeArgsMinimumGasPrice { - args = append(args, arg) + if arg == NodeArgsMinimumGasPrice { + continue } + + args = append(args, arg) } + // Add the zero minimum gas price argument - return append(DefaultNodeArgs(), "--minimum-gas-prices=0atest") + return append(args, "--minimum-gas-prices=0atest") +} + +// MempoolArgs returns the node arguments to run with the mempool. +func MempoolArgs() []string { + return append( + DefaultNodeArgs(), + NodeArgInsertQueueSize, + NodeArgPendingTxProposalTimeout, + ) +} + +// MempoolMinGasPriceZeroArgs returns the node arguments to run with the mempool with no min gas price. +func MempoolMinGasPriceZeroArgs() []string { + return append(MempoolArgs(), "--minimum-gas-prices=0atest") } diff --git a/tests/systemtests/upgrade_test.go b/tests/systemtests/upgrade_test.go deleted file mode 100644 index 9ae700e8..00000000 --- a/tests/systemtests/upgrade_test.go +++ /dev/null @@ -1,102 +0,0 @@ -//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/app/adapter.go b/testutil/app/adapter.go new file mode 100644 index 00000000..64156660 --- /dev/null +++ b/testutil/app/adapter.go @@ -0,0 +1,229 @@ +package testapp + +import ( + "encoding/json" + "fmt" + + evm "github.com/cosmos/evm" + erc20keeper "github.com/cosmos/evm/x/erc20/keeper" + feemarketkeeper "github.com/cosmos/evm/x/feemarket/keeper" + "github.com/cosmos/evm/x/ibc/callbacks/keeper" + evmkeeper "github.com/cosmos/evm/x/vm/keeper" + transferkeeper "github.com/cosmos/ibc-go/v11/modules/apps/transfer/keeper" + ibckeeper "github.com/cosmos/ibc-go/v11/modules/core/keeper" + ibctesting "github.com/cosmos/ibc-go/v11/testing" + + "github.com/cosmos/cosmos-sdk/baseapp" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + consensusparamkeeper "github.com/cosmos/cosmos-sdk/x/consensus/keeper" + distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" + evidencekeeper "github.com/cosmos/cosmos-sdk/x/evidence/keeper" + feegrantkeeper "github.com/cosmos/cosmos-sdk/x/feegrant/keeper" + govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" + mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper" + slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" +) + +// NewEvmAppAdapter wraps a specialized TestApp (one that implements the keeper +// provider interfaces) into a full evm.EvmApp so shared testing helpers can +// keep using the broader interface. +func NewEvmAppAdapter(app evm.TestApp) *EvmAppAdapter { + return &EvmAppAdapter{TestApp: app} +} + +// ToEvmAppCreator validates that the provided factory returns an app +// implementing the desired interface T and then wraps it behind the keeper +// adapter so downstream helpers can keep using evm.EvmApp. +func ToEvmAppCreator[T any](create func(string, uint64, ...func(*baseapp.BaseApp)) evm.EvmApp, ifaceName string) func(string, uint64, ...func(*baseapp.BaseApp)) evm.EvmApp { + return func(chainID string, evmChainID uint64, customBaseAppOptions ...func(*baseapp.BaseApp)) evm.EvmApp { + app := create(chainID, evmChainID, customBaseAppOptions...) + if _, ok := app.(T); !ok { + panic(fmt.Sprintf("CreateEvmApp must implement %s", ifaceName)) + } + return NewEvmAppAdapter(app) + } +} + +// ToIBCAppCreator adapts an ibctesting.AppCreator into one that +// guarantees the returned app implements the desired interface T and exposes +// the evm.EvmApp API via the testing adapter. +func ToIBCAppCreator[T any](creator ibctesting.AppCreator, ifaceName string) ibctesting.AppCreator { + return func() (ibctesting.TestingApp, map[string]json.RawMessage) { + app, genesis := creator() + typedApp, ok := app.(evm.TestApp) + if !ok { + panic("AppCreator must return an app implementing evm.TestApp") + } + if _, ok := app.(T); !ok { + panic(fmt.Sprintf("AppCreator must implement %s", ifaceName)) + } + if _, ok := app.(evm.IBCTestApp); !ok { + panic("AppCreator must return an app implementing evm.IBCTestApp") + } + return NewEvmAppAdapter(typedApp), genesis + } +} + +type EvmAppAdapter struct { + evm.TestApp +} + +var _ evm.EvmApp = (*EvmAppAdapter)(nil) + +func (a *EvmAppAdapter) GetEVMKeeper() *evmkeeper.Keeper { + if provider, ok := a.TestApp.(evm.VMKeeperProvider); ok { + return provider.GetEVMKeeper() + } + panicMissingProvider("EVMKeeperProvider") + return nil +} + +func (a *EvmAppAdapter) GetErc20Keeper() *erc20keeper.Keeper { + if provider, ok := a.TestApp.(evm.Erc20KeeperProvider); ok { + return provider.GetErc20Keeper() + } + panicMissingProvider("Erc20KeeperProvider") + return nil +} + +func (a *EvmAppAdapter) SetErc20Keeper(k erc20keeper.Keeper) { + if setter, ok := a.TestApp.(evm.Erc20KeeperSetter); ok { + setter.SetErc20Keeper(k) + return + } + panicMissingProvider("Erc20KeeperSetter") +} + +func (a *EvmAppAdapter) GetGovKeeper() govkeeper.Keeper { + if provider, ok := a.TestApp.(evm.GovKeeperProvider); ok { + return provider.GetGovKeeper() + } + panicMissingProvider("GovKeeperProvider") + return govkeeper.Keeper{} +} + +func (a *EvmAppAdapter) GetSlashingKeeper() slashingkeeper.Keeper { + if provider, ok := a.TestApp.(evm.SlashingKeeperProvider); ok { + return provider.GetSlashingKeeper() + } + panicMissingProvider("SlashingKeeperProvider") + return slashingkeeper.Keeper{} +} + +func (a *EvmAppAdapter) GetIBCKeeper() *ibckeeper.Keeper { + if provider, ok := a.TestApp.(evm.IBCKeeperProvider); ok { + return provider.GetIBCKeeper() + } + panicMissingProvider("IBCKeeperProvider") + return nil +} + +func (a *EvmAppAdapter) GetEvidenceKeeper() *evidencekeeper.Keeper { + if provider, ok := a.TestApp.(evm.EvidenceKeeperProvider); ok { + return provider.GetEvidenceKeeper() + } + panicMissingProvider("EvidenceKeeperProvider") + return nil +} + +func (a *EvmAppAdapter) GetBankKeeper() bankkeeper.Keeper { + if provider, ok := a.TestApp.(evm.BankKeeperProvider); ok { + return provider.GetBankKeeper() + } + panicMissingProvider("BankKeeperProvider") + return bankkeeper.BaseKeeper{} +} + +func (a *EvmAppAdapter) GetFeeMarketKeeper() *feemarketkeeper.Keeper { + if provider, ok := a.TestApp.(evm.FeeMarketKeeperProvider); ok { + return provider.GetFeeMarketKeeper() + } + panicMissingProvider("FeeMarketKeeperProvider") + return nil +} + +func (a *EvmAppAdapter) GetAccountKeeper() authkeeper.AccountKeeper { + if provider, ok := a.TestApp.(evm.AccountKeeperProvider); ok { + return provider.GetAccountKeeper() + } + panicMissingProvider("AccountKeeperProvider") + return authkeeper.AccountKeeper{} +} + +func (a *EvmAppAdapter) GetDistrKeeper() distrkeeper.Keeper { + if provider, ok := a.TestApp.(evm.DistrKeeperProvider); ok { + return provider.GetDistrKeeper() + } + panicMissingProvider("DistrKeeperProvider") + return distrkeeper.Keeper{} +} + +func (a *EvmAppAdapter) GetStakingKeeper() *stakingkeeper.Keeper { + if provider, ok := a.TestApp.(evm.StakingKeeperProvider); ok { + return provider.GetStakingKeeper() + } + panicMissingProvider("StakingKeeperProvider") + return nil +} + +func (a *EvmAppAdapter) GetMintKeeper() mintkeeper.Keeper { + if provider, ok := a.TestApp.(evm.MintKeeperProvider); ok { + return provider.GetMintKeeper() + } + panicMissingProvider("MintKeeperProvider") + return mintkeeper.Keeper{} +} + +func (a *EvmAppAdapter) GetFeeGrantKeeper() feegrantkeeper.Keeper { + if provider, ok := a.TestApp.(evm.FeeGrantKeeperProvider); ok { + return provider.GetFeeGrantKeeper() + } + panicMissingProvider("FeeGrantKeeperProvider") + return feegrantkeeper.Keeper{} +} + +func (a *EvmAppAdapter) GetConsensusParamsKeeper() consensusparamkeeper.Keeper { + if provider, ok := a.TestApp.(evm.ConsensusParamsKeeperProvider); ok { + return provider.GetConsensusParamsKeeper() + } + panicMissingProvider("ConsensusParamsKeeperProvider") + return consensusparamkeeper.Keeper{} +} + +func (a *EvmAppAdapter) GetCallbackKeeper() keeper.ContractKeeper { + if provider, ok := a.TestApp.(evm.CallbackKeeperProvider); ok { + return provider.GetCallbackKeeper() + } + panicMissingProvider("CallbackKeeperProvider") + return keeper.ContractKeeper{} +} + +func (a *EvmAppAdapter) GetTransferKeeper() *transferkeeper.Keeper { + if provider, ok := a.TestApp.(evm.TransferKeeperProvider); ok { + return provider.GetTransferKeeper() + } + panicMissingProvider("TransferKeeperProvider") + return &transferkeeper.Keeper{} +} + +func (a *EvmAppAdapter) SetTransferKeeper(k *transferkeeper.Keeper) { + if setter, ok := a.TestApp.(evm.TransferKeeperSetter); ok { + setter.SetTransferKeeper(k) + return + } + panicMissingProvider("TransferKeeperSetter") +} + +func (a *EvmAppAdapter) GetKey(storeKey string) *storetypes.KVStoreKey { + if provider, ok := a.TestApp.(evm.KeyProvider); ok { + return provider.GetKey(storeKey) + } + return a.TestApp.GetKey(storeKey) +} + +func panicMissingProvider(name string) { + panic(fmt.Sprintf("keeper adapter: app does not implement %s", name)) +} diff --git a/testutil/config/genesis.go b/testutil/config/genesis.go index 41e5736a..fa528f9f 100644 --- a/testutil/config/genesis.go +++ b/testutil/config/genesis.go @@ -3,13 +3,9 @@ package config import ( "encoding/json" - "github.com/cosmos/evm/config" testconstants "github.com/cosmos/evm/testutil/constants" erc20types "github.com/cosmos/evm/x/erc20/types" - feemarkettypes "github.com/cosmos/evm/x/feemarket/types" evmtypes "github.com/cosmos/evm/x/vm/types" - - minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" ) // GenesisState of the blockchain is represented here as a map of raw json @@ -28,6 +24,9 @@ type GenesisState map[string]json.RawMessage func NewEVMGenesisState() *evmtypes.GenesisState { evmGenState := evmtypes.DefaultGenesisState() evmGenState.Params.ActiveStaticPrecompiles = evmtypes.AvailableStaticPrecompiles + evmGenState.Params.EvmDenom = testconstants.ExampleAttoDenom + evmGenState.Params.ExtendedDenomOptions = &evmtypes.ExtendedDenomOptions{ExtendedDenom: testconstants. + ExampleAttoDenom} return evmGenState } @@ -43,23 +42,3 @@ func NewErc20GenesisState() *erc20types.GenesisState { return erc20GenState } - -// NewMintGenesisState returns the default genesis state for the mint module. -// -// NOTE: for the example chain implementation we are also adding a default minter. -func NewMintGenesisState() *minttypes.GenesisState { - mintGenState := minttypes.DefaultGenesisState() - mintGenState.Params.MintDenom = config.ExampleChainDenom - - return mintGenState -} - -// NewFeeMarketGenesisState returns the default genesis state for the feemarket module. -// -// NOTE: for the example chain implementation we are disabling the base fee. -func NewFeeMarketGenesisState() *feemarkettypes.GenesisState { - feeMarketGenState := feemarkettypes.DefaultGenesisState() - feeMarketGenState.Params.NoBaseFee = true - - return feeMarketGenState -} diff --git a/testutil/constants/constants.go b/testutil/constants/constants.go index 317171f3..764ae4db 100644 --- a/testutil/constants/constants.go +++ b/testutil/constants/constants.go @@ -1,6 +1,7 @@ package constants import ( + "github.com/cosmos/evm/server/config" erc20types "github.com/cosmos/evm/x/erc20/types" evmtypes "github.com/cosmos/evm/x/vm/types" @@ -23,8 +24,8 @@ const ( // ExampleBech32Prefix provides an example Bech32 prefix for use in tests ExampleBech32Prefix = "cosmos" - // ExampleEIP155ChainID provides an example EIP-155 chain ID for use in tests - ExampleEIP155ChainID = 9001 + // EighteenDecimalsChainID provides an example EIP-155 chain ID for use in tests + EighteenDecimalsChainID = 9001 // WEVMOSContractMainnet is the WEVMOS contract address for mainnet WEVMOSContractMainnet = "0xD4949664cD82660AaE99bEdc034a0deA8A0bd517" @@ -36,6 +37,44 @@ const ( ExampleEvmAddressBob = "0x0AFc8e15F0A74E98d0AEC6C67389D2231384D4B2" ) +// ChainsCoinInfo is a map of the chain id and its corresponding EvmCoinInfo +// that allows initializing the app with different coin info based on the +// chain id +var ChainsCoinInfo = map[uint64]evmtypes.EvmCoinInfo{ // TODO:VLAD - deduplicate this for tests + EighteenDecimalsChainID: { + Denom: ExampleAttoDenom, + ExtendedDenom: ExampleAttoDenom, + DisplayDenom: ExampleDisplayDenom, + Decimals: evmtypes.EighteenDecimals.Uint32(), + }, + // SixDecimalsChainID provides a chain ID which is being set up with 6 decimals + SixDecimalsChainID.EVMChainID: { + Denom: "utest", + ExtendedDenom: "atest", + DisplayDenom: "test", + Decimals: evmtypes.SixDecimals.Uint32(), + }, + // EVMChainID provides a chain ID used for internal testing + config.DefaultEVMChainID: { + Denom: "atest", + ExtendedDenom: "atest", + DisplayDenom: "test", + Decimals: evmtypes.EighteenDecimals.Uint32(), + }, + TwelveDecimalsChainID.EVMChainID: { + Denom: "ptest2", + ExtendedDenom: "atest2", + DisplayDenom: "test2", + Decimals: evmtypes.TwelveDecimals.Uint32(), + }, + TwoDecimalsChainID.EVMChainID: { + Denom: "ctest3", + ExtendedDenom: "atest3", + DisplayDenom: "test3", + Decimals: evmtypes.TwoDecimals.Uint32(), + }, +} + type ChainID struct { ChainID string `json:"chain_id"` EVMChainID uint64 `json:"evm_chain_id"` diff --git a/testutil/constants/constants_test.go b/testutil/constants/constants_test.go deleted file mode 100644 index 1c739e83..00000000 --- a/testutil/constants/constants_test.go +++ /dev/null @@ -1,34 +0,0 @@ -package constants_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/evm/config" - "github.com/cosmos/evm/testutil/constants" -) - -func TestRequireSameTestDenom(t *testing.T) { - require.Equal(t, - constants.ExampleAttoDenom, - config.ExampleChainDenom, - "test denoms should be the same across the repo", - ) -} - -func TestRequireSameTestBech32Prefix(t *testing.T) { - require.Equal(t, - constants.ExampleBech32Prefix, - config.Bech32Prefix, - "bech32 prefixes should be the same across the repo", - ) -} - -func TestRequireSameWEVMOSMainnet(t *testing.T) { - require.Equal(t, - constants.WEVMOSContractMainnet, - config.WEVMOSContractMainnet, - "wevmos contract addresses should be the same across the repo", - ) -} diff --git a/testutil/ibc.go b/testutil/ibc.go index dc563613..30b0ee15 100644 --- a/testutil/ibc.go +++ b/testutil/ibc.go @@ -1,7 +1,7 @@ package testutil import ( - transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" + transfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" ) func GetVoucherDenomFromPacketData( diff --git a/testutil/ibc/README.md b/testutil/ibc/README.md index 95d32faa..d32c0789 100644 --- a/testutil/ibc/README.md +++ b/testutil/ibc/README.md @@ -271,8 +271,8 @@ import ( "github.com/cometbft/cometbft/libs/log" dbm "github.com/cometbft/cometbft-db" - "github.com/cosmos/ibc-go/v10/modules/apps/transfer/simapp" - ibctesting "github.com/cosmos/ibc-go/v10/testing" + "github.com/cosmos/ibc-go/v11/modules/apps/transfer/simapp" + ibctesting "github.com/cosmos/ibc-go/v11/testing" ) func SetupTransferTestingApp() (ibctesting.TestingApp, map[string]json.RawMessage) { diff --git a/testutil/ibc/chain.go b/testutil/ibc/chain.go index 1f8d2916..1d75a8dc 100644 --- a/testutil/ibc/chain.go +++ b/testutil/ibc/chain.go @@ -22,14 +22,14 @@ import ( "github.com/cosmos/evm/crypto/ethsecp256k1" "github.com/cosmos/evm/testutil/tx" "github.com/cosmos/evm/x/vm/types" - clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" - channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types" - commitmenttypes "github.com/cosmos/ibc-go/v10/modules/core/23-commitment/types" - host "github.com/cosmos/ibc-go/v10/modules/core/24-host" - "github.com/cosmos/ibc-go/v10/modules/core/exported" - ibctm "github.com/cosmos/ibc-go/v10/modules/light-clients/07-tendermint" - ibctesting "github.com/cosmos/ibc-go/v10/testing" - "github.com/cosmos/ibc-go/v10/testing/simapp" + clienttypes "github.com/cosmos/ibc-go/v11/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/v11/modules/core/04-channel/types" + commitmenttypes "github.com/cosmos/ibc-go/v11/modules/core/23-commitment/types" + host "github.com/cosmos/ibc-go/v11/modules/core/24-host" + "github.com/cosmos/ibc-go/v11/modules/core/exported" + ibctm "github.com/cosmos/ibc-go/v11/modules/light-clients/07-tendermint" + ibctesting "github.com/cosmos/ibc-go/v11/testing" + "github.com/cosmos/ibc-go/v11/testing/simapp" errorsmod "cosmossdk.io/errors" sdkmath "cosmossdk.io/math" @@ -95,6 +95,13 @@ type TestChain struct { // Short-term solution to override the logic of the standard SendMsgs function. // See issue https://github.com/cosmos/ibc-go/issues/3123 for more information. SendMsgsOverride func(msgs ...sdk.Msg) (*abci.ExecTxResult, error) + + // nextBlockContextInitialized tracks whether NewNextBlockContext has been + // called for the current block. Calling it again would reset the finalize + // state and discard any writes made since the last call. GetContext uses + // this to initialize lazily and then return NewContextLegacy on subsequent + // calls so direct keeper writes accumulate across a single test body. + nextBlockContextInitialized bool } // NewTestChainWithValSet initializes a new TestChain instance with the given validator set @@ -162,7 +169,7 @@ func NewTestChainWithValSet(tb testing.TB, isEVM bool, coord *Coordinator, chain }, { Denom: types.DefaultEVMDisplayDenom, - Exponent: 6, + Exponent: 18, Aliases: nil, }, }, @@ -235,8 +242,32 @@ func NewTestChain(t *testing.T, isEVM bool, coord *Coordinator, chainID string) } // GetContext returns the current context for the application. +// If called between blocks (after Commit, before FinalizeBlock), it lazily +// initializes the finalize state via NewNextBlockContext so that direct keeper +// writes target the state that will be committed in the next block. +// If called during FinalizeBlock (e.g. inside a contract callback), it returns +// the already-active finalize state without replacing it. func (chain *TestChain) GetContext() sdk.Context { - return chain.App.GetBaseApp().NewUncachedContext(false, chain.ProposedHeader) + if !chain.nextBlockContextInitialized { + // Try to get the existing finalize state first. If FinalizeBlock is + // in progress, the state already exists and we must not replace it + // with NewNextBlockContext. + if ctx, ok := chain.tryGetContextLegacy(); ok { + return ctx + } + chain.App.GetBaseApp().NewNextBlockContext(chain.ProposedHeader) + chain.nextBlockContextInitialized = true + } + + return chain.App.GetBaseApp().NewContextLegacy(false, chain.ProposedHeader) +} + +// tryGetContextLegacy attempts to get a context from the finalize state. +// Returns false if the finalize state is not initialized (e.g. between blocks). +func (chain *TestChain) tryGetContextLegacy() (sdk.Context, bool) { + defer func() { recover() }() //nolint:errcheck // catch nil pointer panic + ctx := chain.App.GetBaseApp().NewContextLegacy(false, chain.ProposedHeader) + return ctx, true } // GetSimApp returns the SimApp to allow usage ofnon-interface fields. @@ -347,6 +378,7 @@ func (chain *TestChain) NextBlock() { func (chain *TestChain) commitBlock(res *abci.ResponseFinalizeBlock) { _, err := chain.App.Commit() require.NoError(chain.TB, err) + chain.nextBlockContextInitialized = false // set the last header to the current header // use nil trusted fields diff --git a/testutil/ibc/config.go b/testutil/ibc/config.go index 879d61d0..f6eae75f 100644 --- a/testutil/ibc/config.go +++ b/testutil/ibc/config.go @@ -3,11 +3,11 @@ package ibctesting import ( "time" - connectiontypes "github.com/cosmos/ibc-go/v10/modules/core/03-connection/types" - channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types" - "github.com/cosmos/ibc-go/v10/modules/core/exported" - ibctm "github.com/cosmos/ibc-go/v10/modules/light-clients/07-tendermint" - "github.com/cosmos/ibc-go/v10/testing/mock" + connectiontypes "github.com/cosmos/ibc-go/v11/modules/core/03-connection/types" + channeltypes "github.com/cosmos/ibc-go/v11/modules/core/04-channel/types" + "github.com/cosmos/ibc-go/v11/modules/core/exported" + ibctm "github.com/cosmos/ibc-go/v11/modules/light-clients/07-tendermint" + "github.com/cosmos/ibc-go/v11/testing/mock" ) type ClientConfig interface { diff --git a/testutil/ibc/coordinator.go b/testutil/ibc/coordinator.go index 0d235d32..b5bbeeef 100644 --- a/testutil/ibc/coordinator.go +++ b/testutil/ibc/coordinator.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/require" "github.com/cosmos/evm/x/vm/types" - ibctesting "github.com/cosmos/ibc-go/v10/testing" + ibctesting "github.com/cosmos/ibc-go/v11/testing" ) var ( @@ -89,6 +89,7 @@ func (coord *Coordinator) UpdateTimeForChain(chain *TestChain) { // Setup constructs a TM client, connection, and channel on both chains provided. It will // fail if any error occurs. +// // Deprecated: please use path.Setup(), this function will be removed in v10 func (*Coordinator) Setup(path *Path) { path.Setup() @@ -96,6 +97,7 @@ func (*Coordinator) Setup(path *Path) { // SetupClients is a helper function to create clients on both chains. It assumes the // caller does not anticipate any errors. +// // Deprecated: please use path.SetupClients(), this function will be removed in v10 func (*Coordinator) SetupClients(path *Path) { path.SetupClients() @@ -104,6 +106,7 @@ func (*Coordinator) SetupClients(path *Path) { // SetupConnections is a helper function to create clients and the appropriate // connections on both the source and counterparty chain. It assumes the caller does not // anticipate any errors. +// // Deprecated: please use path.SetupConnections(), this function will be removed in v10 func (*Coordinator) SetupConnections(path *Path) { path.SetupConnections() @@ -113,6 +116,7 @@ func (*Coordinator) SetupConnections(path *Path) { // OPEN channels on chainA and chainB. The connection information of for chainA and chainB // are returned within a TestConnection struct. The function expects the connections to be // successfully opened otherwise testing will fail. +// // Deprecated: please use path.CreateConnections(), this function will be removed in v10 func (*Coordinator) CreateConnections(path *Path) { path.CreateConnections() @@ -142,6 +146,7 @@ func (*Coordinator) CreateTransferChannels(path *Path) { // CreateChannels constructs and executes channel handshake messages in order to create // OPEN channels on chainA and chainB. The function expects the channels to be successfully // opened otherwise testing will fail. +// // Deprecated: please use path.CreateChannels(), this function will be removed in v10 func (*Coordinator) CreateChannels(path *Path) { path.CreateChannels() diff --git a/testutil/ibc/endpoint.go b/testutil/ibc/endpoint.go index 37fb3e82..9e62027a 100644 --- a/testutil/ibc/endpoint.go +++ b/testutil/ibc/endpoint.go @@ -10,14 +10,14 @@ import ( abci "github.com/cometbft/cometbft/abci/types" - clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/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" - commitmenttypes "github.com/cosmos/ibc-go/v10/modules/core/23-commitment/types" - commitmenttypesv2 "github.com/cosmos/ibc-go/v10/modules/core/23-commitment/types/v2" - host "github.com/cosmos/ibc-go/v10/modules/core/24-host" - "github.com/cosmos/ibc-go/v10/modules/core/exported" - ibctm "github.com/cosmos/ibc-go/v10/modules/light-clients/07-tendermint" + clienttypes "github.com/cosmos/ibc-go/v11/modules/core/02-client/types" + connectiontypes "github.com/cosmos/ibc-go/v11/modules/core/03-connection/types" + channeltypes "github.com/cosmos/ibc-go/v11/modules/core/04-channel/types" + commitmenttypes "github.com/cosmos/ibc-go/v11/modules/core/23-commitment/types" + commitmenttypesv2 "github.com/cosmos/ibc-go/v11/modules/core/23-commitment/types/v2" + host "github.com/cosmos/ibc-go/v11/modules/core/24-host" + "github.com/cosmos/ibc-go/v11/modules/core/exported" + ibctm "github.com/cosmos/ibc-go/v11/modules/light-clients/07-tendermint" "github.com/cosmos/cosmos-sdk/baseapp" ) diff --git a/testutil/ibc/endpoint_v2.go b/testutil/ibc/endpoint_v2.go index 7c0e35fe..93f1ba39 100644 --- a/testutil/ibc/endpoint_v2.go +++ b/testutil/ibc/endpoint_v2.go @@ -8,9 +8,9 @@ import ( abci "github.com/cometbft/cometbft/abci/types" "github.com/cosmos/gogoproto/proto" - clientv2types "github.com/cosmos/ibc-go/v10/modules/core/02-client/v2/types" - channeltypesv2 "github.com/cosmos/ibc-go/v10/modules/core/04-channel/v2/types" - hostv2 "github.com/cosmos/ibc-go/v10/modules/core/24-host/v2" + clientv2types "github.com/cosmos/ibc-go/v11/modules/core/02-client/v2/types" + channeltypesv2 "github.com/cosmos/ibc-go/v11/modules/core/04-channel/v2/types" + hostv2 "github.com/cosmos/ibc-go/v11/modules/core/24-host/v2" sdk "github.com/cosmos/cosmos-sdk/types" ) diff --git a/testutil/ibc/events.go b/testutil/ibc/events.go index 5a89e9ce..e90ea8c4 100644 --- a/testutil/ibc/events.go +++ b/testutil/ibc/events.go @@ -11,10 +11,10 @@ import ( abci "github.com/cometbft/cometbft/abci/types" - clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/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" - channeltypesv2 "github.com/cosmos/ibc-go/v10/modules/core/04-channel/v2/types" + clienttypes "github.com/cosmos/ibc-go/v11/modules/core/02-client/types" + connectiontypes "github.com/cosmos/ibc-go/v11/modules/core/03-connection/types" + channeltypes "github.com/cosmos/ibc-go/v11/modules/core/04-channel/types" + channeltypesv2 "github.com/cosmos/ibc-go/v11/modules/core/04-channel/v2/types" ) // ParseClientIDFromEvents parses events emitted from a MsgCreateClient and returns the diff --git a/testutil/ibc/path.go b/testutil/ibc/path.go index d66f388f..cec9a169 100644 --- a/testutil/ibc/path.go +++ b/testutil/ibc/path.go @@ -7,9 +7,9 @@ import ( abci "github.com/cometbft/cometbft/abci/types" "github.com/cosmos/gogoproto/proto" - transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types" - channeltypesv2 "github.com/cosmos/ibc-go/v10/modules/core/04-channel/v2/types" + transfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + channeltypes "github.com/cosmos/ibc-go/v11/modules/core/04-channel/types" + channeltypesv2 "github.com/cosmos/ibc-go/v11/modules/core/04-channel/v2/types" ) // Path contains two endpoints representing two chains connected over IBC diff --git a/testutil/ibc/testing_app.go b/testutil/ibc/testing_app.go index 5988c7b3..c84a5ae9 100644 --- a/testutil/ibc/testing_app.go +++ b/testutil/ibc/testing_app.go @@ -12,13 +12,12 @@ import ( dbm "github.com/cosmos/cosmos-db" evmtypes "github.com/cosmos/evm/x/vm/types" - "github.com/cosmos/ibc-go/v10/modules/core/keeper" - ibctesting "github.com/cosmos/ibc-go/v10/testing" - "github.com/cosmos/ibc-go/v10/testing/simapp" + "github.com/cosmos/ibc-go/v11/modules/core/keeper" + ibctesting "github.com/cosmos/ibc-go/v11/testing" + "github.com/cosmos/ibc-go/v11/testing/simapp" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" sdkmath "cosmossdk.io/math" - storetypes "cosmossdk.io/store/types" "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/client" @@ -26,6 +25,7 @@ import ( codectypes "github.com/cosmos/cosmos-sdk/codec/types" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" servertypes "github.com/cosmos/cosmos-sdk/server/types" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" diff --git a/testutil/ibc/values.go b/testutil/ibc/values.go index bff8ebd3..55aaa884 100644 --- a/testutil/ibc/values.go +++ b/testutil/ibc/values.go @@ -9,11 +9,11 @@ import ( "github.com/cometbft/cometbft/crypto/tmhash" - ibctransfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - connectiontypes "github.com/cosmos/ibc-go/v10/modules/core/03-connection/types" - commitmenttypes "github.com/cosmos/ibc-go/v10/modules/core/23-commitment/types" - ibctm "github.com/cosmos/ibc-go/v10/modules/light-clients/07-tendermint" - "github.com/cosmos/ibc-go/v10/testing/mock" + ibctransfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + connectiontypes "github.com/cosmos/ibc-go/v11/modules/core/03-connection/types" + commitmenttypes "github.com/cosmos/ibc-go/v11/modules/core/23-commitment/types" + ibctm "github.com/cosmos/ibc-go/v11/modules/light-clients/07-tendermint" + "github.com/cosmos/ibc-go/v11/testing/mock" sdkmath "cosmossdk.io/math" ) diff --git a/testutil/integration/base/factory/base.go b/testutil/integration/base/factory/base.go index fe74f0ed..e6e3a1cb 100644 --- a/testutil/integration/base/factory/base.go +++ b/testutil/integration/base/factory/base.go @@ -22,6 +22,9 @@ import ( type BaseTxFactory interface { // BuildCosmosTx builds a Cosmos tx with the provided private key and txArgs BuildCosmosTx(privKey cryptotypes.PrivKey, txArgs CosmosTxArgs) (authsigning.Tx, error) + // BuildMultiSignerCosmosTx builds a Cosmos tx signed by multiple private + // keys. The first key is used as the fee payer. + BuildMultiSignerCosmosTx(txArgs CosmosTxArgs, privKeys ...cryptotypes.PrivKey) (authsigning.Tx, error) // SignCosmosTx signs a Cosmos transaction with the provided // private key and tx builder SignCosmosTx(privKey cryptotypes.PrivKey, txBuilder client.TxBuilder) error @@ -63,6 +66,21 @@ func (tf *baseTxFactory) BuildCosmosTx(privKey cryptotypes.PrivKey, txArgs Cosmo return txBuilder.GetTx(), nil } +// BuildMultiSignerCosmosTx builds and signs a Cosmos tx with multiple signers. +// The first private key is the fee payer. Each signer signs independently over +// its own SignerData; the resulting tx carries one SignatureV2 per signer so +// the default SDK signer extractor returns one entry per key. +func (tf *baseTxFactory) BuildMultiSignerCosmosTx(txArgs CosmosTxArgs, privKeys ...cryptotypes.PrivKey) (authsigning.Tx, error) { + if len(privKeys) == 0 { + return nil, fmt.Errorf("at least one private key is required") + } + txBuilder, err := tf.buildMultiSignerTx(txArgs, privKeys) + if err != nil { + return nil, errorsmod.Wrap(err, "failed to build multi-signer tx") + } + return txBuilder.GetTx(), nil +} + // ExecuteCosmosTx creates, signs and broadcasts a Cosmos transaction func (tf *baseTxFactory) ExecuteCosmosTx(privKey cryptotypes.PrivKey, txArgs CosmosTxArgs) (abcitypes.ExecTxResult, error) { signedTx, err := tf.BuildCosmosTx(privKey, txArgs) @@ -110,7 +128,7 @@ func (tf *baseTxFactory) SignCosmosTx(privKey cryptotypes.PrivKey, txBuilder cli if err != nil { return errorsmod.Wrap(err, "invalid sign mode") } - signerData, err := tf.setSignatures(privKey, txBuilder, signMode) + signerData, err := tf.setSignatures(privKey, nil, txBuilder, signMode) if err != nil { return errorsmod.Wrap(err, "failed to set tx signatures") } diff --git a/testutil/integration/base/factory/helper.go b/testutil/integration/base/factory/helper.go index d716dd83..b0a4e55c 100644 --- a/testutil/integration/base/factory/helper.go +++ b/testutil/integration/base/factory/helper.go @@ -36,7 +36,6 @@ func (tf *baseTxFactory) buildTx(privKey cryptotypes.PrivKey, txArgs CosmosTxArg } senderAddress := sdktypes.AccAddress(privKey.PubKey().Address().Bytes()) - if txArgs.FeeGranter != nil { txBuilder.SetFeeGranter(txArgs.FeeGranter) } @@ -48,7 +47,7 @@ func (tf *baseTxFactory) buildTx(privKey cryptotypes.PrivKey, txArgs CosmosTxArg if err != nil { return nil, errorsmod.Wrap(err, "invalid sign mode") } - signerData, err := tf.setSignatures(privKey, txBuilder, signMode) + signerData, err := tf.setSignatures(privKey, txArgs.Nonce, txBuilder, signMode) if err != nil { return nil, errorsmod.Wrap(err, "failed to set tx signatures") } @@ -75,6 +74,60 @@ func (tf *baseTxFactory) buildTx(privKey cryptotypes.PrivKey, txArgs CosmosTxArg return txBuilder, nil } +// buildMultiSignerTx builds a tx signed by multiple private keys. The first +// key in privKeys is set as the fee payer. +func (tf *baseTxFactory) buildMultiSignerTx(txArgs CosmosTxArgs, privKeys []cryptotypes.PrivKey) (client.TxBuilder, error) { + txConfig := tf.ec.TxConfig + txBuilder := txConfig.NewTxBuilder() + + if err := txBuilder.SetMsgs(txArgs.Msgs...); err != nil { + return nil, errorsmod.Wrap(err, "failed to set tx msgs") + } + + if txArgs.FeeGranter != nil { + txBuilder.SetFeeGranter(txArgs.FeeGranter) + } + + feePayer := sdktypes.AccAddress(privKeys[0].PubKey().Address().Bytes()) + txBuilder.SetFeePayer(feePayer) + + signMode, err := authsigning.APISignModeToInternal(txConfig.SignModeHandler().DefaultMode()) + if err != nil { + return nil, errorsmod.Wrap(err, "invalid sign mode") + } + + signerDatas, err := tf.setMultiSignerSignatures(privKeys, txBuilder, signMode) + if err != nil { + return nil, errorsmod.Wrap(err, "failed to set tx signatures") + } + + var gasLimit uint64 + if txArgs.Gas == nil { + gasLimit, err = tf.estimateGas(txArgs, txBuilder) + if err != nil { + return nil, errorsmod.Wrap(err, "failed to estimate gas") + } + } else { + gasLimit = *txArgs.Gas + } + txBuilder.SetGasLimit(gasLimit) + + fees := txArgs.Fees + if fees.IsZero() { + fees, err = tf.calculateFees(txArgs.GasPrice, gasLimit) + if err != nil { + return nil, errorsmod.Wrap(err, "failed to calculate fees") + } + } + txBuilder.SetFeeAmount(fees) + + if err := tf.signMultiSignerWithPrivKeys(privKeys, txBuilder, signerDatas, signMode); err != nil { + return nil, errorsmod.Wrap(err, "failed to sign Cosmos Tx") + } + + return txBuilder, nil +} + // calculateFees calculates the fees for the transaction. func (tf *baseTxFactory) calculateFees(gasPrice *sdkmath.Int, gasLimit uint64) (sdktypes.Coins, error) { denom := tf.network.GetBaseDenom() diff --git a/testutil/integration/base/factory/sign.go b/testutil/integration/base/factory/sign.go index 88265979..92a0bb5b 100644 --- a/testutil/integration/base/factory/sign.go +++ b/testutil/integration/base/factory/sign.go @@ -16,13 +16,17 @@ import ( // setSignatures is a helper function that sets the signature for // the transaction in the tx builder. It returns the signerData to be used // when signing the transaction (e.g. when calling signWithPrivKey) -func (tf *baseTxFactory) setSignatures(privKey cryptotypes.PrivKey, txBuilder client.TxBuilder, signMode signing.SignMode) (signerData authsigning.SignerData, err error) { +func (tf *baseTxFactory) setSignatures(privKey cryptotypes.PrivKey, nonce *uint64, txBuilder client.TxBuilder, signMode signing.SignMode) (signerData authsigning.SignerData, err error) { senderAddress := sdktypes.AccAddress(privKey.PubKey().Address().Bytes()) account, err := tf.grpcHandler.GetAccount(senderAddress.String()) if err != nil { return signerData, err } sequence := account.GetSequence() + if nonce != nil { + sequence = *nonce + } + signerData = authsigning.SignerData{ ChainID: tf.network.GetChainID(), AccountNumber: account.GetAccountNumber(), @@ -43,6 +47,56 @@ func (tf *baseTxFactory) setSignatures(privKey cryptotypes.PrivKey, txBuilder cl return signerData, txBuilder.SetSignatures(sigsV2) } +// setMultiSignerSignatures sets nil signatures for each provided signer in +// order so the tx can be simulated, returning the per-signer SignerData used +// during the actual signing pass. +func (tf *baseTxFactory) setMultiSignerSignatures(privKeys []cryptotypes.PrivKey, txBuilder client.TxBuilder, signMode signing.SignMode) ([]authsigning.SignerData, error) { + signerDatas := make([]authsigning.SignerData, len(privKeys)) + sigsV2 := make([]signing.SignatureV2, len(privKeys)) + for i, privKey := range privKeys { + addr := sdktypes.AccAddress(privKey.PubKey().Address().Bytes()) + account, err := tf.grpcHandler.GetAccount(addr.String()) + if err != nil { + return nil, err + } + seq := account.GetSequence() + signerDatas[i] = authsigning.SignerData{ + ChainID: tf.network.GetChainID(), + AccountNumber: account.GetAccountNumber(), + Sequence: seq, + Address: addr.String(), + PubKey: privKey.PubKey(), + } + sigsV2[i] = signing.SignatureV2{ + PubKey: privKey.PubKey(), + Data: &signing.SingleSignatureData{ + SignMode: signMode, + Signature: nil, + }, + Sequence: seq, + } + } + if err := txBuilder.SetSignatures(sigsV2...); err != nil { + return nil, err + } + return signerDatas, nil +} + +// signMultiSignerWithPrivKeys produces a signature per signer and sets them +// all on the tx builder in the same order as privKeys. +func (tf *baseTxFactory) signMultiSignerWithPrivKeys(privKeys []cryptotypes.PrivKey, txBuilder client.TxBuilder, signerDatas []authsigning.SignerData, signMode signing.SignMode) error { + txConfig := tf.ec.TxConfig + sigs := make([]signing.SignatureV2, len(privKeys)) + for i, privKey := range privKeys { + sig, err := cosmostx.SignWithPrivKey(context.TODO(), signMode, signerDatas[i], txBuilder, privKey, txConfig, signerDatas[i].Sequence) + if err != nil { + return errorsmod.Wrap(err, "failed to sign tx") + } + sigs[i] = sig + } + return txBuilder.SetSignatures(sigs...) +} + // signWithPrivKey is a helper function that signs a transaction // with the provided private key func (tf *baseTxFactory) signWithPrivKey(privKey cryptotypes.PrivKey, txBuilder client.TxBuilder, signerData authsigning.SignerData, signMode signing.SignMode) error { diff --git a/testutil/integration/base/factory/types.go b/testutil/integration/base/factory/types.go index f8987ae0..c4f615ca 100644 --- a/testutil/integration/base/factory/types.go +++ b/testutil/integration/base/factory/types.go @@ -16,6 +16,8 @@ type CosmosTxArgs struct { GasPrice *sdkmath.Int // Fees is the fee to be used on the tx (amount and denom) Fees sdktypes.Coins + // Nonce is an optional custom nonce to use for the fee payer + Nonce *uint64 // FeeGranter is the account address of the fee granter FeeGranter sdktypes.AccAddress // Msgs slice of messages to include on the tx diff --git a/testutil/integration/base/grpc/authz.go b/testutil/integration/base/grpc/authz.go deleted file mode 100644 index b80d6b24..00000000 --- a/testutil/integration/base/grpc/authz.go +++ /dev/null @@ -1,114 +0,0 @@ -package grpc - -import ( - "context" - - "github.com/cosmos/cosmos-sdk/x/authz" -) - -// GetGrants returns the grants for the given grantee and granter combination. -// -// NOTE: To extract the concrete authorizations, use the GetAuthorizations method. -func (gqh *IntegrationHandler) GetGrants(grantee, granter string) ([]*authz.Grant, error) { - authzClient := gqh.network.GetAuthzClient() - res, err := authzClient.Grants(context.Background(), &authz.QueryGrantsRequest{ - Grantee: grantee, - Granter: granter, - }) - if err != nil { - return nil, err - } - - return res.Grants, nil -} - -// GetGrantsByGrantee returns the grants for the given grantee. -// -// NOTE: To extract the concrete authorizations, use the GetAuthorizationsByGrantee method. -func (gqh *IntegrationHandler) GetGrantsByGrantee(grantee string) ([]*authz.GrantAuthorization, error) { - authzClient := gqh.network.GetAuthzClient() - res, err := authzClient.GranteeGrants(context.Background(), &authz.QueryGranteeGrantsRequest{ - Grantee: grantee, - }) - if err != nil { - return nil, err - } - - return res.Grants, nil -} - -// GetGrantsByGranter returns the grants for the given granter. -// -// NOTE: To extract the concrete authorizations, use the GetAuthorizationsByGranter method. -func (gqh *IntegrationHandler) GetGrantsByGranter(granter string) ([]*authz.GrantAuthorization, error) { - authzClient := gqh.network.GetAuthzClient() - res, err := authzClient.GranterGrants(context.Background(), &authz.QueryGranterGrantsRequest{ - Granter: granter, - }) - if err != nil { - return nil, err - } - - return res.Grants, nil -} - -// GetAuthorizations returns the concrete authorizations for the given grantee and granter combination. -func (gqh *IntegrationHandler) GetAuthorizations(grantee, granter string) ([]authz.Authorization, error) { - encodingCfg := gqh.network.GetEncodingConfig() - - grants, err := gqh.GetGrants(grantee, granter) - if err != nil { - return nil, err - } - - auths := make([]authz.Authorization, 0, len(grants)) - for _, grant := range grants { - var auth authz.Authorization - err := encodingCfg.InterfaceRegistry.UnpackAny(grant.Authorization, &auth) - if err != nil { - return nil, err - } - - auths = append(auths, auth) - } - - return auths, nil -} - -// GetAuthorizationsByGrantee returns the concrete authorizations for the given grantee. -func (gqh *IntegrationHandler) GetAuthorizationsByGrantee(grantee string) ([]authz.Authorization, error) { - grants, err := gqh.GetGrantsByGrantee(grantee) - if err != nil { - return nil, err - } - - return gqh.unpackGrantAuthzs(grants) -} - -// GetAuthorizationsByGranter returns the concrete authorizations for the given granter. -func (gqh *IntegrationHandler) GetAuthorizationsByGranter(granter string) ([]authz.Authorization, error) { - grants, err := gqh.GetGrantsByGranter(granter) - if err != nil { - return nil, err - } - - return gqh.unpackGrantAuthzs(grants) -} - -// unpackGrantAuthzs unpacks the given grant authorization. -func (gqh *IntegrationHandler) unpackGrantAuthzs(grantAuthzs []*authz.GrantAuthorization) ([]authz.Authorization, error) { - encodingCfg := gqh.network.GetEncodingConfig() - - auths := make([]authz.Authorization, 0, len(grantAuthzs)) - for _, grantAuthz := range grantAuthzs { - var auth authz.Authorization - err := encodingCfg.InterfaceRegistry.UnpackAny(grantAuthz.Authorization, &auth) - if err != nil { - return nil, err - } - - auths = append(auths, auth) - } - - return auths, nil -} diff --git a/testutil/integration/base/grpc/grpc.go b/testutil/integration/base/grpc/grpc.go index 539a94a0..b70a790f 100644 --- a/testutil/integration/base/grpc/grpc.go +++ b/testutil/integration/base/grpc/grpc.go @@ -2,10 +2,8 @@ package grpc import ( "github.com/cosmos/evm/testutil/integration/base/network" - precisebanktypes "github.com/cosmos/evm/x/precisebank/types" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/authz" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -17,24 +15,12 @@ type Handler interface { // Account methods GetAccount(address string) (sdk.AccountI, error) - // Authz methods - GetAuthorizations(grantee, granter string) ([]authz.Authorization, error) - GetAuthorizationsByGrantee(grantee string) ([]authz.Authorization, error) - GetAuthorizationsByGranter(granter string) ([]authz.Authorization, error) - GetGrants(grantee, granter string) ([]*authz.Grant, error) - GetGrantsByGrantee(grantee string) ([]*authz.GrantAuthorization, error) - GetGrantsByGranter(granter string) ([]*authz.GrantAuthorization, error) - // Bank methods GetBalanceFromBank(address sdk.AccAddress, denom string) (*banktypes.QueryBalanceResponse, error) GetSpendableBalance(address sdk.AccAddress, denom string) (*banktypes.QuerySpendableBalanceByDenomResponse, error) GetAllBalances(address sdk.AccAddress) (*banktypes.QueryAllBalancesResponse, error) GetTotalSupply() (*banktypes.QueryTotalSupplyResponse, error) - // PreciseBank methods - Remainder() (*precisebanktypes.QueryRemainderResponse, error) - FractionalBalance(address sdk.AccAddress) (*precisebanktypes.QueryFractionalBalanceResponse, error) - // Staking methods GetDelegation(delegatorAddress string, validatorAddress string) (*stakingtypes.QueryDelegationResponse, error) GetDelegatorDelegations(delegatorAddress string) (*stakingtypes.QueryDelegatorDelegationsResponse, error) diff --git a/testutil/integration/base/grpc/precisebank.go b/testutil/integration/base/grpc/precisebank.go deleted file mode 100644 index ca3ad4e2..00000000 --- a/testutil/integration/base/grpc/precisebank.go +++ /dev/null @@ -1,21 +0,0 @@ -package grpc - -import ( - "context" - - precisebanktypes "github.com/cosmos/evm/x/precisebank/types" - - sdktypes "github.com/cosmos/cosmos-sdk/types" -) - -func (gqh *IntegrationHandler) Remainder() (*precisebanktypes.QueryRemainderResponse, error) { - preciseBankClient := gqh.network.GetPreciseBankClient() - return preciseBankClient.Remainder(context.Background(), &precisebanktypes.QueryRemainderRequest{}) -} - -func (gqh *IntegrationHandler) FractionalBalance(address sdktypes.AccAddress) (*precisebanktypes.QueryFractionalBalanceResponse, error) { - preciseBankClient := gqh.network.GetPreciseBankClient() - return preciseBankClient.FractionalBalance(context.Background(), &precisebanktypes.QueryFractionalBalanceRequest{ - Address: address.String(), - }) -} diff --git a/testutil/integration/base/network/network.go b/testutil/integration/base/network/network.go index 37d11b74..99f379ac 100644 --- a/testutil/integration/base/network/network.go +++ b/testutil/integration/base/network/network.go @@ -6,14 +6,12 @@ import ( abcitypes "github.com/cometbft/cometbft/abci/types" - precisebanktypes "github.com/cosmos/evm/x/precisebank/types" - ibctesting "github.com/cosmos/ibc-go/v10/testing" + ibctesting "github.com/cosmos/ibc-go/v11/testing" sdktypes "github.com/cosmos/cosmos-sdk/types" sdktestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" txtypes "github.com/cosmos/cosmos-sdk/types/tx" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - "github.com/cosmos/cosmos-sdk/x/authz" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -36,9 +34,7 @@ type Network interface { // Clients GetAuthClient() authtypes.QueryClient - GetAuthzClient() authz.QueryClient GetBankClient() banktypes.QueryClient - GetPreciseBankClient() precisebanktypes.QueryClient GetStakingClient() stakingtypes.QueryClient GetDistrClient() distrtypes.QueryClient diff --git a/testutil/integration/evm/network/abci.go b/testutil/integration/evm/network/abci.go index a1bdb7fa..07e2d434 100644 --- a/testutil/integration/evm/network/abci.go +++ b/testutil/integration/evm/network/abci.go @@ -7,7 +7,9 @@ import ( cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" cmttypes "github.com/cometbft/cometbft/types" - storetypes "cosmossdk.io/store/types" + evmmempool "github.com/cosmos/evm/mempool" + + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" ) // NextBlock is a private helper function that runs the EndBlocker logic, commits the changes, @@ -84,7 +86,16 @@ func (n *IntegrationNetwork) finalizeBlockAndCommit(duration time.Duration, txBy newCtx = newCtx.WithHeaderHash(header.AppHash) n.ctx = newCtx - // commit changes + // Acquire commit lock to prevent mempool background readers from accessing + // IAVL concurrently during commit in tests, then commit changes. + if mp := n.app.GetMempool(); mp != nil { + if evmMp, ok := mp.(*evmmempool.Mempool); ok { + if bc := evmMp.GetBlockchain(); bc != nil { + bc.BeginCommit() + defer bc.EndCommit() + } + } + } _, err = n.app.Commit() return res, err diff --git a/testutil/integration/evm/network/chain_id_modifiers.go b/testutil/integration/evm/network/chain_id_modifiers.go index 4bf9f67d..953794f2 100644 --- a/testutil/integration/evm/network/chain_id_modifiers.go +++ b/testutil/integration/evm/network/chain_id_modifiers.go @@ -5,7 +5,6 @@ package network import ( - "github.com/cosmos/evm/config" testconstants "github.com/cosmos/evm/testutil/constants" erc20types "github.com/cosmos/evm/x/erc20/types" evmtypes "github.com/cosmos/evm/x/vm/types" @@ -24,13 +23,11 @@ func updateBankGenesisStateForChainID(bankGenesisState banktypes.GenesisState, e // GenerateBankGenesisMetadata generates the metadata entries // for both extended and native EVM denominations depending on the chain. func GenerateBankGenesisMetadata(evmChainID uint64) []banktypes.Metadata { - denomConfig := config.ChainsCoinInfo[evmChainID] + denomConfig := testconstants.ChainsCoinInfo[evmChainID] // Basic denom settings displayDenom := denomConfig.DisplayDenom // e.g., "atom" evmDenom := denomConfig.Denom // e.g., "uatom" - extDenom := denomConfig.ExtendedDenom // always 18-decimals base denom - evmDecimals := denomConfig.Decimals // native decimal precision, e.g., 6, 12, ..., or 18 // Standard metadata fields name := "Cosmos EVM" @@ -38,36 +35,18 @@ func GenerateBankGenesisMetadata(evmChainID uint64) []banktypes.Metadata { var metas []banktypes.Metadata - if evmDenom != extDenom { - // This means we are initializing a chain with non-18 decimals - // - // Note: extDenom is always 18-decimals and handled by the precisebank module's states, - // So we don't need to add it to the bank module's metadata. - metas = append(metas, banktypes.Metadata{ - Description: "Native EVM denom metadata", - Base: evmDenom, - DenomUnits: []*banktypes.DenomUnit{ - {Denom: evmDenom, Exponent: 0}, - {Denom: displayDenom, Exponent: evmDecimals}, - }, - Name: name, - Symbol: symbol, - Display: displayDenom, - }) - } else { - // EVM native chain: single metadata with 18-decimals - metas = append(metas, banktypes.Metadata{ - Description: "Native 18-decimal denom metadata for Cosmos EVM chain", - Base: evmDenom, - DenomUnits: []*banktypes.DenomUnit{ - {Denom: evmDenom, Exponent: 0}, - {Denom: displayDenom, Exponent: uint32(evmtypes.EighteenDecimals)}, - }, - Name: name, - Symbol: symbol, - Display: displayDenom, - }) - } + // EVM native chain: single metadata with 18-decimals + metas = append(metas, banktypes.Metadata{ + Description: "Native 18-decimal denom metadata for Cosmos EVM chain", + Base: evmDenom, + DenomUnits: []*banktypes.DenomUnit{ + {Denom: evmDenom, Exponent: 0}, + {Denom: displayDenom, Exponent: uint32(evmtypes.EighteenDecimals)}, + }, + Name: name, + Symbol: symbol, + Display: displayDenom, + }) return metas } @@ -83,8 +62,8 @@ func updateErc20GenesisStateForChainID(chainID testconstants.ChainID, erc20Genes // updateErc20GenesisStateForChainID modify the default genesis state for the // erc20 module on the testing suite depending on the chainID. func updateVMGenesisStateForChainID(chainID testconstants.ChainID, vmGenesisState evmtypes.GenesisState) evmtypes.GenesisState { - vmGenesisState.Params.EvmDenom = config.ChainsCoinInfo[chainID.EVMChainID].Denom - vmGenesisState.Params.ExtendedDenomOptions = &evmtypes.ExtendedDenomOptions{ExtendedDenom: config.ChainsCoinInfo[chainID.EVMChainID].ExtendedDenom} + vmGenesisState.Params.EvmDenom = testconstants.ChainsCoinInfo[chainID.EVMChainID].Denom + vmGenesisState.Params.ExtendedDenomOptions = &evmtypes.ExtendedDenomOptions{ExtendedDenom: testconstants.ChainsCoinInfo[chainID.EVMChainID].ExtendedDenom} return vmGenesisState } diff --git a/testutil/integration/evm/network/clients.go b/testutil/integration/evm/network/clients.go index 965ade62..cd730f7c 100644 --- a/testutil/integration/evm/network/clients.go +++ b/testutil/integration/evm/network/clients.go @@ -3,8 +3,6 @@ package network import ( erc20types "github.com/cosmos/evm/x/erc20/types" feemarkettypes "github.com/cosmos/evm/x/feemarket/types" - precisebankkeeper "github.com/cosmos/evm/x/precisebank/keeper" - precisebanktypes "github.com/cosmos/evm/x/precisebank/types" evmtypes "github.com/cosmos/evm/x/vm/types" "github.com/cosmos/cosmos-sdk/baseapp" @@ -12,7 +10,6 @@ import ( "github.com/cosmos/cosmos-sdk/types/module/testutil" authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - "github.com/cosmos/cosmos-sdk/x/authz" 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" @@ -69,12 +66,6 @@ func (n *IntegrationNetwork) GetAuthClient() authtypes.QueryClient { return authtypes.NewQueryClient(queryHelper) } -func (n *IntegrationNetwork) GetAuthzClient() authz.QueryClient { - queryHelper := getQueryHelper(n.GetContext(), n.GetEncodingConfig()) - authz.RegisterQueryServer(queryHelper, n.app.GetAuthzKeeper()) - return authz.NewQueryClient(queryHelper) -} - func (n *IntegrationNetwork) GetStakingClient() stakingtypes.QueryClient { queryHelper := getQueryHelper(n.GetContext(), n.GetEncodingConfig()) stakingtypes.RegisterQueryServer(queryHelper, stakingkeeper.Querier{Keeper: n.app.GetStakingKeeper()}) @@ -92,9 +83,3 @@ func (n *IntegrationNetwork) GetMintClient() minttypes.QueryClient { minttypes.RegisterQueryServer(queryHelper, mintkeeper.NewQueryServerImpl(n.app.GetMintKeeper())) return minttypes.NewQueryClient(queryHelper) } - -func (n *IntegrationNetwork) GetPreciseBankClient() precisebanktypes.QueryClient { - queryHelper := getQueryHelper(n.GetContext(), n.GetEncodingConfig()) - precisebanktypes.RegisterQueryServer(queryHelper, precisebankkeeper.NewQueryServerImpl(*n.app.GetPreciseBankKeeper())) - return precisebanktypes.NewQueryClient(queryHelper) -} diff --git a/testutil/integration/evm/network/config.go b/testutil/integration/evm/network/config.go index e83758eb..c49cee12 100644 --- a/testutil/integration/evm/network/config.go +++ b/testutil/integration/evm/network/config.go @@ -55,7 +55,7 @@ func DefaultConfig() Config { return Config{ chainID: testconstants.ExampleChainID.ChainID, - eip155ChainID: big.NewInt(testconstants.ExampleEIP155ChainID), + eip155ChainID: big.NewInt(testconstants.EighteenDecimalsChainID), chainCoins: DefaultChainCoins(), initialAmounts: DefaultInitialAmounts(), initialBondedAmount: DefaultInitialBondedAmount(), @@ -107,7 +107,7 @@ func getGenAccountsAndBalances(cfg Config, validators []stakingtypes.Validator) } genAccounts = append(genAccounts, createGenesisAccounts(valAccs)...) - return + return genAccounts, balances } // ConfigOption defines a function that can modify the NetworkConfig. diff --git a/testutil/integration/evm/network/ibc.go b/testutil/integration/evm/network/ibc.go index 90d9a651..13cdfaf6 100644 --- a/testutil/integration/evm/network/ibc.go +++ b/testutil/integration/evm/network/ibc.go @@ -3,7 +3,7 @@ package network import ( "testing" - ibctesting "github.com/cosmos/ibc-go/v10/testing" + ibctesting "github.com/cosmos/ibc-go/v11/testing" ) // GetIBCChain returns a TestChain instance for the given network. @@ -11,13 +11,17 @@ import ( // The keyring should be used instead. func (n *IntegrationNetwork) GetIBCChain(t *testing.T, coord *ibctesting.Coordinator) *ibctesting.TestChain { t.Helper() + app, ok := n.app.(ibctesting.TestingApp) + if !ok { + panic("network app does not implement ibctesting.TestingApp") + } return &ibctesting.TestChain{ TB: t, Coordinator: coord, ChainID: n.GetChainID(), - App: n.app, - TxConfig: n.app.GetTxConfig(), - Codec: n.app.AppCodec(), + App: app, + TxConfig: app.GetTxConfig(), + Codec: app.AppCodec(), Vals: n.valSet, NextVals: n.valSet, Signers: n.valSigners, diff --git a/testutil/integration/evm/network/network.go b/testutil/integration/evm/network/network.go index 907af989..b4e557b6 100644 --- a/testutil/integration/evm/network/network.go +++ b/testutil/integration/evm/network/network.go @@ -23,9 +23,9 @@ import ( evmtypes "github.com/cosmos/evm/x/vm/types" sdkmath "cosmossdk.io/math" - storetypes "cosmossdk.io/store/types" "github.com/cosmos/cosmos-sdk/baseapp" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdktypes "github.com/cosmos/cosmos-sdk/types" sdktestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" txtypes "github.com/cosmos/cosmos-sdk/types/tx" diff --git a/testutil/integration/evm/utils/genesis.go b/testutil/integration/evm/utils/genesis.go index 76c340fe..ba1e481f 100644 --- a/testutil/integration/evm/utils/genesis.go +++ b/testutil/integration/evm/utils/genesis.go @@ -34,7 +34,7 @@ func CreateGenesisWithTokenPairs(keyring testkeyring.Keyring, denoms ...string) genesisAccounts[i] = &authtypes.BaseAccount{ Address: addr.String(), PubKey: nil, - AccountNumber: uint64(i + 1), //nolint:gosec // G115 + AccountNumber: uint64(i + 1), Sequence: 1, } } diff --git a/testutil/integration/evm/utils/types.go b/testutil/integration/evm/utils/types.go index 00b5c8b2..572fcd18 100644 --- a/testutil/integration/evm/utils/types.go +++ b/testutil/integration/evm/utils/types.go @@ -7,6 +7,9 @@ import ( ) func ValidatorConsAddressToHex(valAddress string) common.Address { - coinbaseAddressBytes := sdk.ConsAddress(valAddress).Bytes() - return common.BytesToAddress(coinbaseAddressBytes) + valAddr, err := sdk.ValAddressFromBech32(valAddress) + if err != nil { + return common.Address{} + } + return common.BytesToAddress(valAddr) } diff --git a/testutil/integration/evm/utils/unit.go b/testutil/integration/evm/utils/unit.go index 24780d0b..7d2abb7f 100644 --- a/testutil/integration/evm/utils/unit.go +++ b/testutil/integration/evm/utils/unit.go @@ -9,7 +9,7 @@ import ( "github.com/cosmos/evm/testutil/integration/evm/network" erc20types "github.com/cosmos/evm/x/erc20/types" - transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" + transfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" "cosmossdk.io/math" @@ -85,7 +85,8 @@ func RegisterIBCERC20Coins( denom transfertypes.Denom, ) (erc20types.TokenPair, error) { ibcDenom := denom.IBCDenom() - network.App.GetTransferKeeper().SetDenom(network.GetContext(), denom) + keeper := network.App.GetTransferKeeper() + keeper.SetDenom(network.GetContext(), denom) ibcMetadata := banktypes.Metadata{ Name: "Generic IBC name", Symbol: "IBC", diff --git a/testutil/tx/eip712.go b/testutil/tx/eip712.go index 89b4a57a..3482bbc1 100644 --- a/testutil/tx/eip712.go +++ b/testutil/tx/eip712.go @@ -73,11 +73,10 @@ func PrepareEIP712CosmosTx( return nil, err } - // using nolint:all because the staticcheck nolint is not working as expected - fee := legacytx.NewStdFee(txArgs.Gas, txArgs.Fees) //nolint:all + fee := legacytx.NewStdFee(txArgs.Gas, txArgs.Fees) //nolint:staticcheck // check against deprecated type msgs := txArgs.Msgs - data := legacytx.StdSignBytes(ctx.ChainID(), accNumber, nonce, 0, fee, msgs, "") + data := legacytx.StdSignBytes(ctx.ChainID(), accNumber, nonce, 0, fee, msgs, "") //nolint:staticcheck // TODO: fix typedDataArgs := typedDataArgs{ chainID: args.EVMChainID, diff --git a/trace/span.go b/trace/span.go new file mode 100644 index 00000000..996d99fe --- /dev/null +++ b/trace/span.go @@ -0,0 +1,25 @@ +package trace + +import ( + "go.opentelemetry.io/otel/codes" + "go.opentelemetry.io/otel/trace" +) + +// EndSpanErr records the error to the span if not nil, and then ends the span. +// NOTE: This should be called like so: +// +// defer func() { EndSpanErr(span, err) } +// +// and not like this: +// +// defer EndSpanErr(span, err) +// +// This is due to the fact that the latter captures the error value at the point in time of the defer line, +// whilst the former will capture the final error value at the very end of the function. +func EndSpanErr(span trace.Span, err error) { + if err != nil { + span.RecordError(err) + span.SetStatus(codes.Error, err.Error()) + } + span.End() +} diff --git a/utils/int.go b/utils/int.go index b9ad3d1c..4a4c29f5 100644 --- a/utils/int.go +++ b/utils/int.go @@ -51,5 +51,5 @@ func SafeHexToInt64(value hexutil.Uint64) (int64, error) { return 0, fmt.Errorf("hexutil.Uint64 value %v cannot exceed %v", value, math.MaxInt64) } - return int64(value), nil //nolint:gosec // checked + return int64(value), nil } diff --git a/utils/utils.go b/utils/utils.go index b7db88bf..cb8be152 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -4,17 +4,20 @@ import ( "cmp" "fmt" "math/big" + "path/filepath" "sort" "strings" "github.com/ethereum/go-ethereum/common" "github.com/holiman/uint256" + "github.com/spf13/viper" "github.com/cosmos/evm/crypto/ethsecp256k1" - ibctransfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" + ibctransfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" errorsmod "cosmossdk.io/errors" + "github.com/cosmos/cosmos-sdk/client/config" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" "github.com/cosmos/cosmos-sdk/crypto/types/multisig" @@ -219,3 +222,23 @@ func Bytes32ToString(data [32]byte) string { } return string(data[:i]) } + +// GetChainIDFromHome returns the chain ID from the client configuration +// in the given home directory. +func GetChainIDFromHome(home string) (string, error) { + v := viper.New() + v.AddConfigPath(filepath.Join(home, "config")) + v.SetConfigName("client") + v.SetConfigType("toml") + + if err := v.ReadInConfig(); err != nil { + return "", err + } + conf := new(config.ClientConfig) + + if err := v.Unmarshal(conf); err != nil { + return "", err + } + + return conf.ChainID, nil +} diff --git a/wallets/usbwallet/hub.go b/wallets/usbwallet/hub.go index 897ab9f4..116aaffe 100644 --- a/wallets/usbwallet/hub.go +++ b/wallets/usbwallet/hub.go @@ -55,7 +55,7 @@ type Hub struct { func NewLedgerHub() (*Hub, error) { return newHub(LedgerScheme, 0x2c97, []uint16{ // Device definitions taken from - // https://github.com/LedgerHQ/ledger-live/blob/38012bc8899e0f07149ea9cfe7e64b2c146bc92b/libs/ledgerjs/packages/devices/src/index.ts + // https://github.com/LedgerHQ/ledger-live/blob/595cb73b7e6622dbbcfc11867082ddc886f1bf01/libs/ledgerjs/packages/devices/src/index.ts // Original product IDs 0x0000, /* Ledger Blue */ @@ -63,18 +63,16 @@ func NewLedgerHub() (*Hub, error) { 0x0004, /* Ledger Nano X */ 0x0005, /* Ledger Nano S Plus */ 0x0006, /* Ledger Nano FTS */ - - 0x0015, /* HID + U2F + WebUSB Ledger Blue */ - 0x1015, /* HID + U2F + WebUSB Ledger Nano S */ - 0x4015, /* HID + U2F + WebUSB Ledger Nano X */ - 0x5015, /* HID + U2F + WebUSB Ledger Nano S Plus */ - 0x6015, /* HID + U2F + WebUSB Ledger Nano FTS */ - - 0x0011, /* HID + WebUSB Ledger Blue */ - 0x1011, /* HID + WebUSB Ledger Nano S */ - 0x4011, /* HID + WebUSB Ledger Nano X */ - 0x5011, /* HID + WebUSB Ledger Nano S Plus */ - 0x6011, /* HID + WebUSB Ledger Nano FTS */ + 0x0007, /* Ledger Flex */ + 0x0008, /* Ledger Nano Gen5 */ + + 0x0000, /* WebUSB Ledger Blue */ + 0x1000, /* WebUSB Ledger Nano S */ + 0x4000, /* WebUSB Ledger Nano X */ + 0x5000, /* WebUSB Ledger Nano S Plus */ + 0x6000, /* WebUSB Ledger Nano FTS */ + 0x7000, /* WebUSB Ledger Flex */ + 0x8000, /* WebUSB Ledger Nano Gen5 */ }, 0xffa0, 0, newLedgerDriver) } @@ -156,7 +154,11 @@ func (hub *Hub) refreshWallets() { for _, info := range infos { for _, id := range hub.productIDs { // Windows and macOS use UsageID matching, Linux uses Interface matching - if info.ProductID == id && (info.UsagePage == hub.usageID || info.Interface == hub.endpointID) { + // Ledger product IDs use MMII format where MM is device model and II is interface flags. + // Match either exact legacy IDs (0x0001, 0x0004, etc.) or device model prefix for + // WebUSB/app-specific IDs (e.g., 0x4011 matches 0x4000 prefix for Nano X with Ethereum app). + modelMatch := id >= 0x1000 && (info.ProductID>>8 == id>>8) + if (info.ProductID == id || modelMatch) && (info.UsagePage == hub.usageID || info.Interface == hub.endpointID) { devices = append(devices, info) break } diff --git a/wallets/usbwallet/ledger.go b/wallets/usbwallet/ledger.go index 650ddee5..2cc3a464 100644 --- a/wallets/usbwallet/ledger.go +++ b/wallets/usbwallet/ledger.go @@ -208,6 +208,7 @@ func (w *ledgerDriver) ledgerVersion() ([3]byte, error) { func (w *ledgerDriver) ledgerDerive(derivationPath gethaccounts.DerivationPath) (common.Address, *ecdsa.PublicKey, error) { // Flatten the derivation path into the Ledger request path := make([]byte, 1+4*len(derivationPath)) + // #nosec G115 -- derivation path length is small path[0] = byte(len(derivationPath)) for i, component := range derivationPath { binary.BigEndian.PutUint32(path[1+4*i:], component) @@ -294,6 +295,7 @@ func (w *ledgerDriver) ledgerDerive(derivationPath gethaccounts.DerivationPath) func (w *ledgerDriver) ledgerSignTypedMessage(derivationPath gethaccounts.DerivationPath, domainHash, messageHash []byte) ([]byte, error) { // Flatten the derivation path into the Ledger request path := make([]byte, 1+4*len(derivationPath)) + // #nosec G115 -- derivation path length is small path[0] = byte(len(derivationPath)) for i, component := range derivationPath { binary.BigEndian.PutUint32(path[1+4*i:], component) @@ -368,6 +370,7 @@ func (w *ledgerDriver) ledgerExchange(opcode ledgerOpcode, p1 ledgerParam1, p2 l //#nosec G115 -- gosec will raise a warning on this integer conversion for potential overflow binary.BigEndian.PutUint16(apdu, uint16(5+len(data))) + // #nosec G115 -- APDU length is bounded apdu = append(apdu, []byte{0xe0, byte(opcode), byte(p1), byte(p2), byte(len(data))}...) apdu = append(apdu, data...) diff --git a/x/erc20/ibc_middleware.go b/x/erc20/ibc_middleware.go index 1b653233..f4e82567 100644 --- a/x/erc20/ibc_middleware.go +++ b/x/erc20/ibc_middleware.go @@ -1,14 +1,15 @@ package erc20 import ( + "bytes" "errors" "github.com/cosmos/evm/ibc" erc20types "github.com/cosmos/evm/x/erc20/types" - transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types" - porttypes "github.com/cosmos/ibc-go/v10/modules/core/05-port/types" - "github.com/cosmos/ibc-go/v10/modules/core/exported" + transfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + channeltypes "github.com/cosmos/ibc-go/v11/modules/core/04-channel/types" + porttypes "github.com/cosmos/ibc-go/v11/modules/core/05-port/types" + "github.com/cosmos/ibc-go/v11/modules/core/exported" errorsmod "cosmossdk.io/errors" @@ -81,6 +82,11 @@ func (im IBCMiddleware) OnAcknowledgementPacket( return errorsmod.Wrapf(errortypes.ErrUnknownRequest, "cannot unmarshal ICS-20 transfer packet acknowledgement: %v", err) } + bz := transfertypes.ModuleCdc.MustMarshalJSON(&ack) + if !bytes.Equal(bz, acknowledgement) { + return errorsmod.Wrapf(errortypes.ErrInvalidType, "acknowledgement did not marshal to expected bytes: %X ≠ %X", bz, acknowledgement) + } + var data transfertypes.FungibleTokenPacketData if err := transfertypes.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err != nil { return errorsmod.Wrapf(errortypes.ErrUnknownRequest, "cannot unmarshal ICS-20 transfer packet data: %s", err.Error()) diff --git a/x/erc20/keeper/allowance.go b/x/erc20/keeper/allowance.go index 643b25bb..cab8f4de 100644 --- a/x/erc20/keeper/allowance.go +++ b/x/erc20/keeper/allowance.go @@ -8,9 +8,9 @@ import ( "github.com/cosmos/evm/x/erc20/types" errorsmod "cosmossdk.io/errors" - "cosmossdk.io/store/prefix" - storetypes "cosmossdk.io/store/types" + "github.com/cosmos/cosmos-sdk/store/v2/prefix" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" errortypes "github.com/cosmos/cosmos-sdk/types/errors" ) diff --git a/x/erc20/keeper/convert.go b/x/erc20/keeper/convert.go new file mode 100644 index 00000000..aa06cf9e --- /dev/null +++ b/x/erc20/keeper/convert.go @@ -0,0 +1,167 @@ +package keeper + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/hashicorp/go-metrics" + + "github.com/cosmos/evm/contracts" + "github.com/cosmos/evm/x/erc20/types" + "github.com/cosmos/evm/x/vm/statedb" + + "cosmossdk.io/errors" + "cosmossdk.io/math" + + "github.com/cosmos/cosmos-sdk/telemetry" + sdk "github.com/cosmos/cosmos-sdk/types" + errortypes "github.com/cosmos/cosmos-sdk/types/errors" +) + +// ConvertERC20IntoCoinsForNativeToken handles the erc20 conversion for a native erc20 token pair. +// This function is used by both the msg server and precompiles (like ICS20). +// It performs the following operations: +// - validates the token pair and checks if conversion is enabled +// - removes the token pair if the contract is suicided +// - escrows tokens on module account +// - mints coins on bank module +// - sends minted coins to the receiver +// - checks if coin balance increased by amount +// - checks if token balance decreased by amount +// - checks for unexpected `Approval` event in logs +func (k Keeper) ConvertERC20IntoCoinsForNativeToken(ctx sdk.Context, stateDB *statedb.StateDB, contract common.Address, amount math.Int, receiver sdk.AccAddress, sender common.Address, commit bool, callFromPrecompile bool) (*types.MsgConvertERC20Response, error) { + // Validate and get token pair + pair, err := k.MintingEnabled(ctx, receiver, contract.Hex()) + if err != nil { + return nil, err + } + + // Check that this is a native ERC20 token + if !pair.IsNativeERC20() { + if pair.IsNativeCoin() { + return nil, types.ErrNativeConversionDisabled + } + return nil, types.ErrUndefinedOwner + } + + // Remove token pair if contract is suicided + acc := k.evmKeeper.GetAccountWithoutBalance(ctx, pair.GetERC20Contract()) + if acc == nil || !acc.HasCodeHash() { + k.DeleteTokenPair(ctx, pair) + k.Logger(ctx).Debug( + "deleting selfdestructed token pair from state", + "contract", pair.Erc20Address, + ) + // NOTE: return nil error to persist the changes from the deletion + return nil, nil + } + erc20 := contracts.ERC20MinterBurnerDecimalsContract.ABI + erc20Contract := pair.GetERC20Contract() + balanceCoin := k.bankKeeper.GetBalance(ctx, receiver, pair.Denom) + balanceToken := k.BalanceOf(ctx, erc20, erc20Contract, types.ModuleAddress) + if balanceToken == nil { + return nil, errors.Wrap(types.ErrEVMCall, "failed to retrieve balance") + } + + // Escrow tokens on module account + transferData, err := erc20.Pack("transfer", types.ModuleAddress, amount.BigInt()) + if err != nil { + return nil, err + } + + res, err := k.evmKeeper.CallEVMWithData(ctx, stateDB, sender, &erc20Contract, transferData, commit, callFromPrecompile, nil) + if err != nil { + return nil, err + } + + // Check evm call response + var unpackedRet types.ERC20BoolResponse + if len(res.Ret) == 0 { + // if the token does not return a value, check for the transfer event in logs + if err := validateTransferEventExists(res.Logs, erc20Contract); err != nil { + return nil, err + } + } else { + if err := erc20.UnpackIntoInterface(&unpackedRet, "transfer", res.Ret); err != nil { + return nil, err + } + if !unpackedRet.Value { + return nil, errors.Wrap(errortypes.ErrLogic, "failed to execute transfer") + } + } + + // Check expected escrow balance after transfer execution + coins := sdk.Coins{sdk.Coin{Denom: pair.Denom, Amount: amount}} + tokens := coins[0].Amount.BigInt() + balanceTokenAfter := k.BalanceOf(ctx, erc20, erc20Contract, types.ModuleAddress) + if balanceTokenAfter == nil { + return nil, errors.Wrap(types.ErrEVMCall, "failed to retrieve balance") + } + + expToken := big.NewInt(0).Add(balanceToken, tokens) + + if r := balanceTokenAfter.Cmp(expToken); r != 0 { + return nil, errors.Wrapf( + types.ErrBalanceInvariance, + "invalid token balance - expected: %v, actual: %v", + expToken, balanceTokenAfter, + ) + } + + // Mint coins + if err := k.bankKeeper.MintCoins(ctx, types.ModuleName, coins); err != nil { + return nil, err + } + + // Send minted coins to the receiver + if err := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, receiver, coins); err != nil { + return nil, err + } + + // Check expected receiver balance after transfer + balanceCoinAfter := k.bankKeeper.GetBalance(ctx, receiver, pair.Denom) + expCoin := balanceCoin.Add(coins[0]) + + if ok := balanceCoinAfter.Equal(expCoin); !ok { + return nil, errors.Wrapf( + types.ErrBalanceInvariance, + "invalid coin balance - expected: %v, actual: %v", + expCoin, balanceCoinAfter, + ) + } + + defer func() { + telemetry.IncrCounterWithLabels( + []string{"tx", "msg", "convert", "erc20", "total"}, + 1, + []metrics.Label{ + telemetry.NewLabel("coin", pair.Denom), + }, + ) + + if amount.IsInt64() { + telemetry.IncrCounterWithLabels( + []string{"tx", "msg", "convert", "erc20", "amount", "total"}, + float32(amount.Int64()), + []metrics.Label{ + telemetry.NewLabel("denom", pair.Denom), + }, + ) + } + }() + + ctx.EventManager().EmitEvents( + sdk.Events{ + sdk.NewEvent( + types.EventTypeConvertERC20, + sdk.NewAttribute(sdk.AttributeKeySender, sender.Hex()), + sdk.NewAttribute(types.AttributeKeyReceiver, receiver.String()), + sdk.NewAttribute(sdk.AttributeKeyAmount, amount.String()), + sdk.NewAttribute(types.AttributeKeyCosmosCoin, pair.Denom), + sdk.NewAttribute(types.AttributeKeyERC20Token, contract.Hex()), + ), + }, + ) + + return &types.MsgConvertERC20Response{}, nil +} diff --git a/x/erc20/keeper/dynamic_precompiles.go b/x/erc20/keeper/dynamic_precompiles.go index 7eb0e569..5dad4d73 100644 --- a/x/erc20/keeper/dynamic_precompiles.go +++ b/x/erc20/keeper/dynamic_precompiles.go @@ -45,21 +45,14 @@ func (k Keeper) RegisterERC20CodeHash(ctx sdk.Context, erc20Addr common.Address) k.evmKeeper.SetCode(ctx, codeHash, bytecode) } - var ( - nonce uint64 - balance = common.U2560 - ) - // keep balance and nonce if account exists - if acc := k.evmKeeper.GetAccount(ctx, erc20Addr); acc != nil { - nonce = acc.Nonce - balance = acc.Balance + // reuse account with modified code hash if it already exists + acc := k.evmKeeper.GetAccount(ctx, erc20Addr) + if acc == nil { + acc = statedb.NewEmptyAccount() } + acc.CodeHash = codeHash - return k.evmKeeper.SetAccount(ctx, erc20Addr, statedb.Account{ - CodeHash: codeHash, - Nonce: nonce, - Balance: balance, - }) + return k.evmKeeper.SetAccount(ctx, erc20Addr, *acc) } // UnRegisterERC20CodeHash sets the codehash for the account to an empty one diff --git a/x/erc20/keeper/evm.go b/x/erc20/keeper/evm.go index 05fdafb3..1e14d275 100644 --- a/x/erc20/keeper/evm.go +++ b/x/erc20/keeper/evm.go @@ -10,11 +10,11 @@ import ( "github.com/cosmos/evm/contracts" "github.com/cosmos/evm/utils" "github.com/cosmos/evm/x/erc20/types" + "github.com/cosmos/evm/x/vm/statedb" errorsmod "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) var ( @@ -25,45 +25,6 @@ var ( logApprovalSigHash = crypto.Keccak256Hash(logApprovalSig) ) -// DeployERC20Contract creates and deploys an ERC20 contract on the EVM with the -// erc20 module account as owner. -func (k Keeper) DeployERC20Contract( - ctx sdk.Context, - coinMetadata banktypes.Metadata, -) (common.Address, error) { - decimals := uint8(0) - if len(coinMetadata.DenomUnits) > 0 { - decimalsIdx := len(coinMetadata.DenomUnits) - 1 - decimals = uint8(coinMetadata.DenomUnits[decimalsIdx].Exponent) //#nosec G115 // exponent will not exceed uint8 - } - ctorArgs, err := contracts.ERC20MinterBurnerDecimalsContract.ABI.Pack( - "", - coinMetadata.Name, - coinMetadata.Symbol, - decimals, - ) - if err != nil { - return common.Address{}, errorsmod.Wrapf(types.ErrABIPack, "coin metadata is invalid %s: %s", coinMetadata.Name, err.Error()) - } - - data := make([]byte, len(contracts.ERC20MinterBurnerDecimalsContract.Bin)+len(ctorArgs)) - copy(data[:len(contracts.ERC20MinterBurnerDecimalsContract.Bin)], contracts.ERC20MinterBurnerDecimalsContract.Bin) - copy(data[len(contracts.ERC20MinterBurnerDecimalsContract.Bin):], ctorArgs) - - nonce, err := k.accountKeeper.GetSequence(ctx, types.ModuleAddress.Bytes()) - if err != nil { - return common.Address{}, err - } - - contractAddr := crypto.CreateAddress(types.ModuleAddress, nonce) - _, err = k.evmKeeper.CallEVMWithData(ctx, types.ModuleAddress, nil, data, true, nil) - if err != nil { - return common.Address{}, errorsmod.Wrapf(err, "failed to deploy contract for %s", coinMetadata.Name) - } - - return contractAddr, nil -} - // QueryERC20 returns the data of a deployed ERC20 contract func (k Keeper) QueryERC20( ctx sdk.Context, @@ -84,7 +45,9 @@ func (k Keeper) QueryERC20( } // Decimals - standard uint8, no fallback needed - res, err := k.evmKeeper.CallEVM(ctx, erc20, types.ModuleAddress, contract, false, nil, "decimals") + stateDB := statedb.New(ctx, k.evmKeeper, statedb.NewEmptyTxConfig()) + // Okay to assume we're not calling from a precompile, as queries will just revert state changes. + res, err := k.evmKeeper.CallEVM(ctx, stateDB, erc20, types.ModuleAddress, contract, false, false, nil, "decimals") if err != nil { return types.ERC20Data{}, err } @@ -107,7 +70,9 @@ func (k Keeper) queryERC20String( method string, ) (string, error) { // 1) Call into the EVM - res, err := k.evmKeeper.CallEVM(ctx, erc20, types.ModuleAddress, contract, false, nil, method) + stateDB := statedb.New(ctx, k.evmKeeper, statedb.NewEmptyTxConfig()) + // Okay to assume we're not calling from a precompile, as queries will just revert state changes. + res, err := k.evmKeeper.CallEVM(ctx, stateDB, erc20, types.ModuleAddress, contract, false, false, nil, method) if err != nil { return "", err } @@ -140,7 +105,9 @@ func (k Keeper) BalanceOf( abi abi.ABI, contract, account common.Address, ) *big.Int { - res, err := k.evmKeeper.CallEVM(ctx, abi, types.ModuleAddress, contract, false, nil, "balanceOf", account) + stateDB := statedb.New(ctx, k.evmKeeper, statedb.NewEmptyTxConfig()) + // Okay to assume we're not calling from a precompile, as queries will just revert state changes. + res, err := k.evmKeeper.CallEVM(ctx, stateDB, abi, types.ModuleAddress, contract, false, false, nil, "balanceOf", account) if err != nil { return nil } diff --git a/x/erc20/keeper/grpc_query.go b/x/erc20/keeper/grpc_query.go index 8ca7191d..c48613d4 100644 --- a/x/erc20/keeper/grpc_query.go +++ b/x/erc20/keeper/grpc_query.go @@ -9,8 +9,7 @@ import ( "github.com/cosmos/evm/utils" "github.com/cosmos/evm/x/erc20/types" - "cosmossdk.io/store/prefix" - + "github.com/cosmos/cosmos-sdk/store/v2/prefix" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" ) diff --git a/x/erc20/keeper/ibc_callbacks.go b/x/erc20/keeper/ibc_callbacks.go index 657eefbd..b4a7bccf 100644 --- a/x/erc20/keeper/ibc_callbacks.go +++ b/x/erc20/keeper/ibc_callbacks.go @@ -8,12 +8,11 @@ import ( "github.com/cosmos/evm/ibc" "github.com/cosmos/evm/x/erc20/types" - transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types" - "github.com/cosmos/ibc-go/v10/modules/core/exported" + transfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + channeltypes "github.com/cosmos/ibc-go/v11/modules/core/04-channel/types" + "github.com/cosmos/ibc-go/v11/modules/core/exported" errorsmod "cosmossdk.io/errors" - storetypes "cosmossdk.io/store/types" "github.com/cosmos/cosmos-sdk/telemetry" sdk "github.com/cosmos/cosmos-sdk/types" @@ -50,32 +49,8 @@ func (k Keeper) OnRecvPacket( return channeltypes.NewErrorAcknowledgement(err) } - // use a zero gas config to avoid extra costs for the relayers - ctx = ctx. - WithKVGasConfig(storetypes.GasConfig{}). - WithTransientKVGasConfig(storetypes.GasConfig{}) - - // recipient (local chain address): accept hex or local bech32 - recipientBz, err := k.addrCodec.StringToBytes(data.Receiver) - if err != nil { - return channeltypes.NewErrorAcknowledgement(errorsmod.Wrap(err, "invalid recipient")) - } - recipient := sdk.AccAddress(recipientBz) - - senderBz, err := k.addrCodec.StringToBytes(data.Sender) - if err != nil { - return channeltypes.NewErrorAcknowledgement(errorsmod.Wrap(err, "invalid sender")) - } - sender := sdk.AccAddress(senderBz) - - receiverAcc := k.accountKeeper.GetAccount(ctx, recipient) - - // return acknowledgement without conversion if receiver is a module account - if types.IsModuleAccount(receiverAcc) { - return ack - } - - // parse the transferred denom + // Parse the transferred denom early to check for early exit conditions + // before attempting to parse potentially foreign sender addresses (e.g. Penumbra) token := transfertypes.Token{ Denom: transfertypes.ExtractDenomFromPath(data.Denom), Amount: data.Amount, @@ -98,6 +73,20 @@ func (k Keeper) OnRecvPacket( return ack } + // recipient (local chain address): accept hex or local bech32 + recipientBz, err := k.addrCodec.StringToBytes(data.Receiver) + if err != nil { + return channeltypes.NewErrorAcknowledgement(errorsmod.Wrap(err, "invalid recipient")) + } + recipient := sdk.AccAddress(recipientBz) + + receiverAcc := k.accountKeeper.GetAccount(ctx, recipient) + + // return acknowledgement without conversion if receiver is a module account + if types.IsModuleAccount(receiverAcc) { + return ack + } + pairID := k.GetTokenPairID(ctx, coin.Denom) pair, found := k.GetTokenPair(ctx, pairID) switch { @@ -128,7 +117,7 @@ func (k Keeper) OnRecvPacket( return ack } - pair, err := k.MintingEnabled(ctx, sender, recipient, coin.Denom) + pair, err := k.MintingEnabled(ctx, recipient, coin.Denom) if err != nil { ctx.EventManager().EmitEvent( sdk.NewEvent("erc20_callback_failure", @@ -140,7 +129,7 @@ func (k Keeper) OnRecvPacket( return channeltypes.NewErrorAcknowledgement(err) } - if err := k.ConvertCoinNativeERC20(ctx, pair, coin.Amount, common.BytesToAddress(recipient.Bytes()), recipient); err != nil { + if err := k.ConvertCoinNativeERC20(ctx, pair, coin.Amount, common.BytesToAddress(recipient.Bytes()), recipient, false); err != nil { return channeltypes.NewErrorAcknowledgement(err) } @@ -221,11 +210,6 @@ func (k Keeper) ConvertCoinToERC20FromPacket(ctx sdk.Context, data transfertypes // Case 2. if pair is native ERC20 -> unescrow case pair.IsNativeERC20(): - // use a zero gas config to avoid extra costs for the relayers - ctx = ctx. - WithKVGasConfig(storetypes.GasConfig{}). - WithTransientKVGasConfig(storetypes.GasConfig{}) - params := k.GetParams(ctx) if !params.EnableErc20 || !k.IsDenomRegistered(ctx, coin.Denom) { // no-op, ERC20s are disabled or the denom is not registered @@ -240,7 +224,7 @@ func (k Keeper) ConvertCoinToERC20FromPacket(ctx sdk.Context, data transfertypes } // Convert from Coin to ERC20 - if err := k.ConvertCoinNativeERC20(ctx, pair, coin.Amount, common.BytesToAddress(sender), sender); err != nil { + if err := k.ConvertCoinNativeERC20(ctx, pair, coin.Amount, common.BytesToAddress(sender), sender, false); err != nil { // We want to record only the failed attempt to reconvert the coins during IBC. defer func() { telemetry.IncrCounter(1, types.ModuleName, "ibc", "error", "total") diff --git a/x/erc20/keeper/keeper.go b/x/erc20/keeper/keeper.go index 981a2de1..a3d674b0 100644 --- a/x/erc20/keeper/keeper.go +++ b/x/erc20/keeper/keeper.go @@ -4,13 +4,13 @@ import ( "fmt" "github.com/cosmos/evm/x/erc20/types" - transferkeeper "github.com/cosmos/evm/x/ibc/transfer/keeper" + transferkeeper "github.com/cosmos/ibc-go/v11/modules/apps/transfer/keeper" "cosmossdk.io/core/address" - "cosmossdk.io/log" - storetypes "cosmossdk.io/store/types" + "cosmossdk.io/log/v2" "github.com/cosmos/cosmos-sdk/codec" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" ) diff --git a/x/erc20/keeper/mint.go b/x/erc20/keeper/mint.go index dba3792f..be8fb44f 100644 --- a/x/erc20/keeper/mint.go +++ b/x/erc20/keeper/mint.go @@ -17,7 +17,7 @@ import ( // - bank module transfers are enabled for the Cosmos coin func (k Keeper) MintingEnabled( ctx sdk.Context, - sender, receiver sdk.AccAddress, + receiver sdk.AccAddress, token string, ) (types.TokenPair, error) { if !k.IsERC20Enabled(ctx) { @@ -57,7 +57,7 @@ func (k Keeper) MintingEnabled( // check if minting to a recipient address other than the sender is enabled // for for the given coin denom - if !sender.Equals(receiver) && !k.bankKeeper.IsSendEnabledCoin(ctx, coin) { + if !k.bankKeeper.IsSendEnabledCoin(ctx, coin) { return types.TokenPair{}, errorsmod.Wrapf( banktypes.ErrSendDisabled, "minting '%s' coins to an external address is currently disabled", token, ) diff --git a/x/erc20/keeper/msg_server.go b/x/erc20/keeper/msg_server.go index dc7a3c72..8213cb20 100644 --- a/x/erc20/keeper/msg_server.go +++ b/x/erc20/keeper/msg_server.go @@ -5,18 +5,16 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" - "github.com/hashicorp/go-metrics" "github.com/cosmos/evm/contracts" "github.com/cosmos/evm/x/erc20/types" + "github.com/cosmos/evm/x/vm/statedb" sdkerrors "cosmossdk.io/errors" "cosmossdk.io/math" - "github.com/cosmos/cosmos-sdk/telemetry" sdk "github.com/cosmos/cosmos-sdk/types" errortypes "github.com/cosmos/cosmos-sdk/types/errors" - govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ) var _ types.MsgServer = &Keeper{} @@ -29,162 +27,18 @@ func (k Keeper) ConvertERC20( ) (*types.MsgConvertERC20Response, error) { ctx := sdk.UnwrapSDKContext(goCtx) - // Error checked during msg validation - receiver := sdk.MustAccAddressFromBech32(msg.Receiver) - sender := common.HexToAddress(msg.Sender) - - pair, err := k.MintingEnabled(ctx, sender.Bytes(), receiver, msg.ContractAddress) - if err != nil { - return nil, err - } - - // Check ownership and execute conversion - if pair.IsNativeERC20() { - // Remove token pair if contract is suicided - acc := k.evmKeeper.GetAccountWithoutBalance(ctx, pair.GetERC20Contract()) - if acc == nil || !acc.HasCodeHash() { - k.DeleteTokenPair(ctx, pair) - k.Logger(ctx).Debug( - "deleting selfdestructed token pair from state", - "contract", pair.Erc20Address, - ) - // NOTE: return nil error to persist the changes from the deletion - return nil, nil - } - - return k.convertERC20IntoCoinsForNativeToken(ctx, pair, msg, receiver, sender) // case 2.1 - } else if pair.IsNativeCoin() { - return nil, types.ErrNativeConversionDisabled - } - - return nil, types.ErrUndefinedOwner -} - -// convertERC20IntoCoinsForNativeToken handles the erc20 conversion for a native erc20 token -// pair: -// - escrow tokens on module account -// - mint coins on bank module -// - send minted coins to the receiver -// - check if coin balance increased by amount -// - check if token balance decreased by amount -// - check for unexpected `Approval` event in logs -func (k Keeper) convertERC20IntoCoinsForNativeToken( - ctx sdk.Context, - pair types.TokenPair, - msg *types.MsgConvertERC20, - receiver sdk.AccAddress, - sender common.Address, -) (*types.MsgConvertERC20Response, error) { - erc20 := contracts.ERC20MinterBurnerDecimalsContract.ABI - contract := pair.GetERC20Contract() - balanceCoin := k.bankKeeper.GetBalance(ctx, receiver, pair.Denom) - balanceToken := k.BalanceOf(ctx, erc20, contract, types.ModuleAddress) - if balanceToken == nil { - return nil, sdkerrors.Wrap(types.ErrEVMCall, "failed to retrieve balance") - } - - // Escrow tokens on module account - transferData, err := erc20.Pack("transfer", types.ModuleAddress, msg.Amount.BigInt()) - if err != nil { - return nil, err - } - - res, err := k.evmKeeper.CallEVMWithData(ctx, sender, &contract, transferData, true, nil) + // Parse message + receiver, err := sdk.AccAddressFromBech32(msg.Receiver) if err != nil { return nil, err } + sender := common.HexToAddress(msg.Sender) + contract := common.HexToAddress(msg.ContractAddress) - // Check evm call response - var unpackedRet types.ERC20BoolResponse - if len(res.Ret) == 0 { - // if the token does not return a value, check for the transfer event in logs - if err := validateTransferEventExists(res.Logs, contract); err != nil { - return nil, err - } - } else { - if err := erc20.UnpackIntoInterface(&unpackedRet, "transfer", res.Ret); err != nil { - return nil, err - } - if !unpackedRet.Value { - return nil, sdkerrors.Wrap(errortypes.ErrLogic, "failed to execute transfer") - } - } - - // Check expected escrow balance after transfer execution - // NOTE: coin fields already validated in the ValidateBasic() of the message - coins := sdk.Coins{sdk.Coin{Denom: pair.Denom, Amount: msg.Amount}} - tokens := coins[0].Amount.BigInt() - balanceTokenAfter := k.BalanceOf(ctx, erc20, contract, types.ModuleAddress) - if balanceTokenAfter == nil { - return nil, sdkerrors.Wrap(types.ErrEVMCall, "failed to retrieve balance") - } - - expToken := big.NewInt(0).Add(balanceToken, tokens) - - if r := balanceTokenAfter.Cmp(expToken); r != 0 { - return nil, sdkerrors.Wrapf( - types.ErrBalanceInvariance, - "invalid token balance - expected: %v, actual: %v", - expToken, balanceTokenAfter, - ) - } - - // Mint coins - if err := k.bankKeeper.MintCoins(ctx, types.ModuleName, coins); err != nil { - return nil, err - } - - // Send minted coins to the receiver - if err := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, receiver, coins); err != nil { - return nil, err - } - - // Check expected receiver balance after transfer - balanceCoinAfter := k.bankKeeper.GetBalance(ctx, receiver, pair.Denom) - expCoin := balanceCoin.Add(coins[0]) - - if ok := balanceCoinAfter.Equal(expCoin); !ok { - return nil, sdkerrors.Wrapf( - types.ErrBalanceInvariance, - "invalid coin balance - expected: %v, actual: %v", - expCoin, balanceCoinAfter, - ) - } - - defer func() { - telemetry.IncrCounterWithLabels( - []string{"tx", "msg", "convert", "erc20", "total"}, - 1, - []metrics.Label{ - telemetry.NewLabel("coin", pair.Denom), - }, - ) - - if msg.Amount.IsInt64() { - telemetry.IncrCounterWithLabels( - []string{"tx", "msg", "convert", "erc20", "amount", "total"}, - float32(msg.Amount.Int64()), - []metrics.Label{ - telemetry.NewLabel("denom", pair.Denom), - }, - ) - } - }() - - ctx.EventManager().EmitEvents( - sdk.Events{ - sdk.NewEvent( - types.EventTypeConvertERC20, - sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender), - sdk.NewAttribute(types.AttributeKeyReceiver, msg.Receiver), - sdk.NewAttribute(sdk.AttributeKeyAmount, msg.Amount.String()), - sdk.NewAttribute(types.AttributeKeyCosmosCoin, pair.Denom), - sdk.NewAttribute(types.AttributeKeyERC20Token, msg.ContractAddress), - ), - }, - ) + // Create stateDB for this transaction + stateDB := statedb.New(ctx, k.evmKeeper, statedb.NewEmptyTxConfig()) - return &types.MsgConvertERC20Response{}, nil + return k.ConvertERC20IntoCoinsForNativeToken(ctx, stateDB, contract, msg.Amount, receiver, sender, true, false) } // ConvertCoin converts native Cosmos coins into ERC20 tokens for both @@ -199,7 +53,7 @@ func (k Keeper) ConvertCoin( sender := sdk.MustAccAddressFromBech32(msg.Sender) receiver := common.HexToAddress(msg.Receiver) - pair, err := k.MintingEnabled(ctx, sender, receiver.Bytes(), msg.Coin.Denom) + pair, err := k.MintingEnabled(ctx, receiver.Bytes(), msg.Coin.Denom) if err != nil { return nil, err } @@ -219,7 +73,7 @@ func (k Keeper) ConvertCoin( return nil, nil } - return nil, k.ConvertCoinNativeERC20(ctx, pair, msg.Coin.Amount, receiver, sender) + return nil, k.ConvertCoinNativeERC20(ctx, pair, msg.Coin.Amount, receiver, sender, false) case pair.IsNativeCoin(): return nil, types.ErrNativeConversionDisabled } @@ -234,13 +88,7 @@ func (k Keeper) ConvertCoin( // - burn escrowed Coins // - check if token balance increased by amount // - check for unexpected `Approval` event in logs -func (k Keeper) ConvertCoinNativeERC20( - ctx sdk.Context, - pair types.TokenPair, - amount math.Int, - receiver common.Address, - sender sdk.AccAddress, -) error { +func (k Keeper) ConvertCoinNativeERC20(ctx sdk.Context, pair types.TokenPair, amount math.Int, receiver common.Address, sender sdk.AccAddress, callFromPrecompile bool) error { if !amount.IsPositive() { return sdkerrors.Wrap(types.ErrNegativeToken, "converted coin amount must be positive") } @@ -260,7 +108,8 @@ func (k Keeper) ConvertCoinNativeERC20( } // Unescrow Tokens and send to receiver - res, err := k.evmKeeper.CallEVM(ctx, erc20, types.ModuleAddress, contract, true, nil, "transfer", receiver, amount.BigInt()) + stateDB := statedb.New(ctx, k.evmKeeper, statedb.NewEmptyTxConfig()) + res, err := k.evmKeeper.CallEVM(ctx, stateDB, erc20, types.ModuleAddress, contract, true, callFromPrecompile, nil, "transfer", receiver, amount.BigInt()) if err != nil { return err } @@ -307,13 +156,15 @@ func (k Keeper) ConvertCoinNativeERC20( // UpdateParams implements the gRPC MsgServer interface. After a successful governance vote // it updates the parameters in the keeper only if the requested authority -// is the Cosmos SDK governance module account +// is the Cosmos SDK governance module account, unless an authority address is +// configured via the consensus AuthorityParams, in which case that takes +// precedence. func (k *Keeper) UpdateParams(goCtx context.Context, req *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) { - if k.authority.String() != req.Authority { - return nil, sdkerrors.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", k.authority, req.Authority) + ctx := sdk.UnwrapSDKContext(goCtx) + if err := k.validateAuthority(ctx, req.Authority); err != nil { + return nil, err } - ctx := sdk.UnwrapSDKContext(goCtx) if err := k.SetParams(ctx, req.Params); err != nil { return nil, err } @@ -329,7 +180,7 @@ func (k *Keeper) RegisterERC20(goCtx context.Context, req *types.MsgRegisterERC2 params := k.GetParams(ctx) if !params.PermissionlessRegistration { - if err := k.validateAuthority(req.Signer); err != nil { + if err := k.validateAuthority(ctx, req.Signer); err != nil { return nil, err } } @@ -372,7 +223,7 @@ func (k *Keeper) ToggleConversion(goCtx context.Context, req *types.MsgToggleCon return nil, types.ErrERC20Disabled.Wrap("toggle conversion is currently disabled by governance") } - if err := k.validateAuthority(req.Authority); err != nil { + if err := k.validateAuthority(ctx, req.Authority); err != nil { return nil, err } @@ -393,14 +244,12 @@ func (k *Keeper) ToggleConversion(goCtx context.Context, req *types.MsgToggleCon } // validateAuthority is a helper function to validate that the provided authority -// is the keeper's authority address -func (k *Keeper) validateAuthority(authority string) error { +// matches the effective authority. It first checks the consensus AuthorityParams +// and falls back to the keeper's authority address if none is configured. +func (k *Keeper) validateAuthority(ctx sdk.Context, authority string) error { if _, err := k.addrCodec.StringToBytes(authority); err != nil { return errortypes.ErrInvalidAddress.Wrapf("invalid authority address: %s", err) } - if k.authority.String() != authority { - return sdkerrors.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", k.authority, authority) - } - return nil + return sdk.ValidateAuthority(ctx, k.authority.String(), authority) } diff --git a/x/erc20/keeper/precompiles.go b/x/erc20/keeper/precompiles.go index 95e40d8f..c0cdb06e 100644 --- a/x/erc20/keeper/precompiles.go +++ b/x/erc20/keeper/precompiles.go @@ -12,9 +12,9 @@ import ( "github.com/cosmos/evm/x/erc20/types" errorsmod "cosmossdk.io/errors" - "cosmossdk.io/store/prefix" - storetypes "cosmossdk.io/store/types" + "github.com/cosmos/cosmos-sdk/store/v2/prefix" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -62,10 +62,10 @@ func (k Keeper) InstantiateERC20Precompile(ctx sdk.Context, contractAddr common. } if hasWrappedMethods { - return werc20.NewPrecompile(pair, k.bankKeeper, k, *k.transferKeeper), nil + return werc20.NewPrecompile(pair, k.bankKeeper, k, k.transferKeeper), nil } - return erc20.NewPrecompile(pair, k.bankKeeper, k, *k.transferKeeper), nil + return erc20.NewPrecompile(pair, k.bankKeeper, k, k.transferKeeper), nil } // RegisterCodeHash checks if a new precompile already exists and registers the code hash it is not diff --git a/x/erc20/keeper/token_pairs.go b/x/erc20/keeper/token_pairs.go index 6957ab35..ccaecab5 100644 --- a/x/erc20/keeper/token_pairs.go +++ b/x/erc20/keeper/token_pairs.go @@ -7,9 +7,9 @@ import ( "github.com/cosmos/evm/x/erc20/types" errorsmod "cosmossdk.io/errors" - "cosmossdk.io/store/prefix" - storetypes "cosmossdk.io/store/types" + "github.com/cosmos/cosmos-sdk/store/v2/prefix" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" ) diff --git a/x/erc20/module.go b/x/erc20/module.go index 332509f1..6422a2cd 100644 --- a/x/erc20/module.go +++ b/x/erc20/module.go @@ -31,7 +31,7 @@ const consensusVersion = 1 // type check to ensure the interface is properly implemented var ( - _ module.AppModule = AppModule{} + _ module.AppModule = AppModule{} //nolint:staticcheck // keep for legacy purposes _ module.AppModuleBasic = AppModuleBasic{} _ module.AppModuleSimulation = AppModule{} diff --git a/x/erc20/types/erc20.pb.go b/x/erc20/types/erc20.pb.go index 9370f63d..09650ef8 100644 --- a/x/erc20/types/erc20.pb.go +++ b/x/erc20/types/erc20.pb.go @@ -57,8 +57,9 @@ func (Owner) EnumDescriptor() ([]byte, []int) { return fileDescriptor_1164958b5b106e92, []int{0} } -// 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. +// 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/interfaces.go b/x/erc20/types/interfaces.go index 32705733..2daba1dc 100644 --- a/x/erc20/types/interfaces.go +++ b/x/erc20/types/interfaces.go @@ -11,13 +11,14 @@ import ( "github.com/cosmos/evm/x/vm/statedb" evmtypes "github.com/cosmos/evm/x/vm/types" - transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types" - "github.com/cosmos/ibc-go/v10/modules/core/exported" + transfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + channeltypes "github.com/cosmos/ibc-go/v11/modules/core/04-channel/types" + "github.com/cosmos/ibc-go/v11/modules/core/exported" "cosmossdk.io/core/address" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -41,16 +42,24 @@ type EVMKeeper interface { GetParams(ctx sdk.Context) evmtypes.Params GetAccountWithoutBalance(ctx sdk.Context, addr common.Address) *statedb.Account EstimateGasInternal(c context.Context, req *evmtypes.EthCallRequest, fromType evmtypes.CallType) (*evmtypes.EstimateGasResponse, error) - ApplyMessage(ctx sdk.Context, msg core.Message, tracer *tracing.Hooks, commit, internal bool) (*evmtypes.MsgEthereumTxResponse, error) + ApplyMessage(ctx sdk.Context, stateDB *statedb.StateDB, msg core.Message, tracer *tracing.Hooks, commit, callFromPrecompile, internal bool) (*evmtypes.MsgEthereumTxResponse, error) DeleteAccount(ctx sdk.Context, addr common.Address) error IsAvailableStaticPrecompile(params *evmtypes.Params, address common.Address) bool - CallEVM(ctx sdk.Context, abi abi.ABI, from, contract common.Address, commit bool, gasCap *big.Int, method string, args ...interface{}) (*evmtypes.MsgEthereumTxResponse, error) - CallEVMWithData(ctx sdk.Context, from common.Address, contract *common.Address, data []byte, commit bool, gasCap *big.Int) (*evmtypes.MsgEthereumTxResponse, error) + CallEVM(ctx sdk.Context, stateDB *statedb.StateDB, abi abi.ABI, from, contract common.Address, commit, callFromPrecompile bool, gasCap *big.Int, method string, args ...interface{}) (*evmtypes.MsgEthereumTxResponse, error) + CallEVMWithData(ctx sdk.Context, stateDB *statedb.StateDB, from common.Address, contract *common.Address, data []byte, commit bool, callFromPrecompile bool, gasCap *big.Int) (*evmtypes.MsgEthereumTxResponse, error) GetCode(ctx sdk.Context, hash common.Hash) []byte SetCode(ctx sdk.Context, hash []byte, bytecode []byte) SetAccount(ctx sdk.Context, address common.Address, account statedb.Account) error GetAccount(ctx sdk.Context, address common.Address) *statedb.Account + IsBaseAccountOrEmpty(ctx sdk.Context, address common.Address) bool IsContract(ctx sdk.Context, address common.Address) bool + GetState(ctx sdk.Context, addr common.Address, key common.Hash) common.Hash + GetCodeHash(ctx sdk.Context, addr common.Address) common.Hash + ForEachStorage(ctx sdk.Context, addr common.Address, cb func(key, value common.Hash) bool) + DeleteState(ctx sdk.Context, addr common.Address, key common.Hash) + SetState(ctx sdk.Context, addr common.Address, key common.Hash, value []byte) + DeleteCode(ctx sdk.Context, codeHash []byte) + KVStoreKeys() map[string]storetypes.StoreKey } type Erc20Keeper interface { diff --git a/x/erc20/types/mocks/EVMKeeper.go b/x/erc20/types/mocks/EVMKeeper.go index eacc172d..ff97d3a5 100644 --- a/x/erc20/types/mocks/EVMKeeper.go +++ b/x/erc20/types/mocks/EVMKeeper.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.0. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks @@ -17,6 +17,8 @@ import ( statedb "github.com/cosmos/evm/x/vm/statedb" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" + tracing "github.com/ethereum/go-ethereum/core/tracing" types "github.com/cosmos/cosmos-sdk/types" @@ -29,9 +31,9 @@ type EVMKeeper struct { mock.Mock } -// ApplyMessage provides a mock function with given fields: ctx, msg, tracer, commit -func (_m *EVMKeeper) ApplyMessage(ctx types.Context, msg core.Message, tracer *tracing.Hooks, commit bool, internal bool) (*vmtypes.MsgEthereumTxResponse, error) { - ret := _m.Called(ctx, msg, tracer, commit) +// ApplyMessage provides a mock function with given fields: ctx, stateDB, msg, tracer, commit, callFromPrecompile, internal +func (_m *EVMKeeper) ApplyMessage(ctx types.Context, stateDB *statedb.StateDB, msg core.Message, tracer *tracing.Hooks, commit bool, callFromPrecompile bool, internal bool) (*vmtypes.MsgEthereumTxResponse, error) { + ret := _m.Called(ctx, stateDB, msg, tracer, commit, callFromPrecompile, internal) if len(ret) == 0 { panic("no return value specified for ApplyMessage") @@ -39,19 +41,19 @@ func (_m *EVMKeeper) ApplyMessage(ctx types.Context, msg core.Message, tracer *t var r0 *vmtypes.MsgEthereumTxResponse var r1 error - if rf, ok := ret.Get(0).(func(types.Context, core.Message, *tracing.Hooks, bool) (*vmtypes.MsgEthereumTxResponse, error)); ok { - return rf(ctx, msg, tracer, commit) + if rf, ok := ret.Get(0).(func(types.Context, *statedb.StateDB, core.Message, *tracing.Hooks, bool, bool, bool) (*vmtypes.MsgEthereumTxResponse, error)); ok { + return rf(ctx, stateDB, msg, tracer, commit, callFromPrecompile, internal) } - if rf, ok := ret.Get(0).(func(types.Context, core.Message, *tracing.Hooks, bool) *vmtypes.MsgEthereumTxResponse); ok { - r0 = rf(ctx, msg, tracer, commit) + if rf, ok := ret.Get(0).(func(types.Context, *statedb.StateDB, core.Message, *tracing.Hooks, bool, bool, bool) *vmtypes.MsgEthereumTxResponse); ok { + r0 = rf(ctx, stateDB, msg, tracer, commit, callFromPrecompile, internal) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*vmtypes.MsgEthereumTxResponse) } } - if rf, ok := ret.Get(1).(func(types.Context, core.Message, *tracing.Hooks, bool) error); ok { - r1 = rf(ctx, msg, tracer, commit) + if rf, ok := ret.Get(1).(func(types.Context, *statedb.StateDB, core.Message, *tracing.Hooks, bool, bool, bool) error); ok { + r1 = rf(ctx, stateDB, msg, tracer, commit, callFromPrecompile, internal) } else { r1 = ret.Error(1) } @@ -59,10 +61,10 @@ func (_m *EVMKeeper) ApplyMessage(ctx types.Context, msg core.Message, tracer *t return r0, r1 } -// CallEVM provides a mock function with given fields: ctx, _a1, from, contract, commit, gasCap, method, args -func (_m *EVMKeeper) CallEVM(ctx types.Context, _a1 abi.ABI, from common.Address, contract common.Address, commit bool, gasCap *big.Int, method string, args ...interface{}) (*vmtypes.MsgEthereumTxResponse, error) { +// CallEVM provides a mock function with given fields: ctx, stateDB, _a2, from, contract, commit, callFromPrecompile, gasCap, method, args +func (_m *EVMKeeper) CallEVM(ctx types.Context, stateDB *statedb.StateDB, _a2 abi.ABI, from common.Address, contract common.Address, commit bool, callFromPrecompile bool, gasCap *big.Int, method string, args ...interface{}) (*vmtypes.MsgEthereumTxResponse, error) { var _ca []interface{} - _ca = append(_ca, ctx, _a1, from, contract, commit, gasCap, method) + _ca = append(_ca, ctx, stateDB, _a2, from, contract, commit, callFromPrecompile, gasCap, method) _ca = append(_ca, args...) ret := _m.Called(_ca...) @@ -72,19 +74,19 @@ func (_m *EVMKeeper) CallEVM(ctx types.Context, _a1 abi.ABI, from common.Address var r0 *vmtypes.MsgEthereumTxResponse var r1 error - if rf, ok := ret.Get(0).(func(types.Context, abi.ABI, common.Address, common.Address, bool, *big.Int, string, ...interface{}) (*vmtypes.MsgEthereumTxResponse, error)); ok { - return rf(ctx, _a1, from, contract, commit, gasCap, method, args...) + if rf, ok := ret.Get(0).(func(types.Context, *statedb.StateDB, abi.ABI, common.Address, common.Address, bool, bool, *big.Int, string, ...interface{}) (*vmtypes.MsgEthereumTxResponse, error)); ok { + return rf(ctx, stateDB, _a2, from, contract, commit, callFromPrecompile, gasCap, method, args...) } - if rf, ok := ret.Get(0).(func(types.Context, abi.ABI, common.Address, common.Address, bool, *big.Int, string, ...interface{}) *vmtypes.MsgEthereumTxResponse); ok { - r0 = rf(ctx, _a1, from, contract, commit, gasCap, method, args...) + if rf, ok := ret.Get(0).(func(types.Context, *statedb.StateDB, abi.ABI, common.Address, common.Address, bool, bool, *big.Int, string, ...interface{}) *vmtypes.MsgEthereumTxResponse); ok { + r0 = rf(ctx, stateDB, _a2, from, contract, commit, callFromPrecompile, gasCap, method, args...) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*vmtypes.MsgEthereumTxResponse) } } - if rf, ok := ret.Get(1).(func(types.Context, abi.ABI, common.Address, common.Address, bool, *big.Int, string, ...interface{}) error); ok { - r1 = rf(ctx, _a1, from, contract, commit, gasCap, method, args...) + if rf, ok := ret.Get(1).(func(types.Context, *statedb.StateDB, abi.ABI, common.Address, common.Address, bool, bool, *big.Int, string, ...interface{}) error); ok { + r1 = rf(ctx, stateDB, _a2, from, contract, commit, callFromPrecompile, gasCap, method, args...) } else { r1 = ret.Error(1) } @@ -92,9 +94,9 @@ func (_m *EVMKeeper) CallEVM(ctx types.Context, _a1 abi.ABI, from common.Address return r0, r1 } -// CallEVMWithData provides a mock function with given fields: ctx, from, contract, data, commit, gasCap -func (_m *EVMKeeper) CallEVMWithData(ctx types.Context, from common.Address, contract *common.Address, data []byte, commit bool, gasCap *big.Int) (*vmtypes.MsgEthereumTxResponse, error) { - ret := _m.Called(ctx, from, contract, data, commit, gasCap) +// CallEVMWithData provides a mock function with given fields: ctx, stateDB, from, contract, data, commit, callFromPrecompile, gasCap +func (_m *EVMKeeper) CallEVMWithData(ctx types.Context, stateDB *statedb.StateDB, from common.Address, contract *common.Address, data []byte, commit bool, callFromPrecompile bool, gasCap *big.Int) (*vmtypes.MsgEthereumTxResponse, error) { + ret := _m.Called(ctx, stateDB, from, contract, data, commit, callFromPrecompile, gasCap) if len(ret) == 0 { panic("no return value specified for CallEVMWithData") @@ -102,19 +104,19 @@ func (_m *EVMKeeper) CallEVMWithData(ctx types.Context, from common.Address, con var r0 *vmtypes.MsgEthereumTxResponse var r1 error - if rf, ok := ret.Get(0).(func(types.Context, common.Address, *common.Address, []byte, bool, *big.Int) (*vmtypes.MsgEthereumTxResponse, error)); ok { - return rf(ctx, from, contract, data, commit, gasCap) + if rf, ok := ret.Get(0).(func(types.Context, *statedb.StateDB, common.Address, *common.Address, []byte, bool, bool, *big.Int) (*vmtypes.MsgEthereumTxResponse, error)); ok { + return rf(ctx, stateDB, from, contract, data, commit, callFromPrecompile, gasCap) } - if rf, ok := ret.Get(0).(func(types.Context, common.Address, *common.Address, []byte, bool, *big.Int) *vmtypes.MsgEthereumTxResponse); ok { - r0 = rf(ctx, from, contract, data, commit, gasCap) + if rf, ok := ret.Get(0).(func(types.Context, *statedb.StateDB, common.Address, *common.Address, []byte, bool, bool, *big.Int) *vmtypes.MsgEthereumTxResponse); ok { + r0 = rf(ctx, stateDB, from, contract, data, commit, callFromPrecompile, gasCap) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*vmtypes.MsgEthereumTxResponse) } } - if rf, ok := ret.Get(1).(func(types.Context, common.Address, *common.Address, []byte, bool, *big.Int) error); ok { - r1 = rf(ctx, from, contract, data, commit, gasCap) + if rf, ok := ret.Get(1).(func(types.Context, *statedb.StateDB, common.Address, *common.Address, []byte, bool, bool, *big.Int) error); ok { + r1 = rf(ctx, stateDB, from, contract, data, commit, callFromPrecompile, gasCap) } else { r1 = ret.Error(1) } @@ -140,6 +142,16 @@ func (_m *EVMKeeper) DeleteAccount(ctx types.Context, addr common.Address) error return r0 } +// DeleteCode provides a mock function with given fields: ctx, codeHash +func (_m *EVMKeeper) DeleteCode(ctx types.Context, codeHash []byte) { + _m.Called(ctx, codeHash) +} + +// DeleteState provides a mock function with given fields: ctx, addr, key +func (_m *EVMKeeper) DeleteState(ctx types.Context, addr common.Address, key common.Hash) { + _m.Called(ctx, addr, key) +} + // EstimateGasInternal provides a mock function with given fields: c, req, fromType func (_m *EVMKeeper) EstimateGasInternal(c context.Context, req *vmtypes.EthCallRequest, fromType vmtypes.CallType) (*vmtypes.EstimateGasResponse, error) { ret := _m.Called(c, req, fromType) @@ -170,6 +182,11 @@ func (_m *EVMKeeper) EstimateGasInternal(c context.Context, req *vmtypes.EthCall return r0, r1 } +// ForEachStorage provides a mock function with given fields: ctx, addr, cb +func (_m *EVMKeeper) ForEachStorage(ctx types.Context, addr common.Address, cb func(common.Hash, common.Hash) bool) { + _m.Called(ctx, addr, cb) +} + // GetAccount provides a mock function with given fields: ctx, address func (_m *EVMKeeper) GetAccount(ctx types.Context, address common.Address) *statedb.Account { ret := _m.Called(ctx, address) @@ -190,6 +207,24 @@ func (_m *EVMKeeper) GetAccount(ctx types.Context, address common.Address) *stat return r0 } +// IsBaseAccountOrEmpty provides a mock function with given fields: ctx, address +func (_m *EVMKeeper) IsBaseAccountOrEmpty(ctx types.Context, address common.Address) bool { + ret := _m.Called(ctx, address) + + if len(ret) == 0 { + panic("no return value specified for IsBaseAccountOrEmpty") + } + + var r0 bool + if rf, ok := ret.Get(0).(func(types.Context, common.Address) bool); ok { + r0 = rf(ctx, address) + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + // GetAccountWithoutBalance provides a mock function with given fields: ctx, addr func (_m *EVMKeeper) GetAccountWithoutBalance(ctx types.Context, addr common.Address) *statedb.Account { ret := _m.Called(ctx, addr) @@ -230,6 +265,26 @@ func (_m *EVMKeeper) GetCode(ctx types.Context, hash common.Hash) []byte { return r0 } +// GetCodeHash provides a mock function with given fields: ctx, addr +func (_m *EVMKeeper) GetCodeHash(ctx types.Context, addr common.Address) common.Hash { + ret := _m.Called(ctx, addr) + + if len(ret) == 0 { + panic("no return value specified for GetCodeHash") + } + + var r0 common.Hash + if rf, ok := ret.Get(0).(func(types.Context, common.Address) common.Hash); ok { + r0 = rf(ctx, addr) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(common.Hash) + } + } + + return r0 +} + // GetParams provides a mock function with given fields: ctx func (_m *EVMKeeper) GetParams(ctx types.Context) vmtypes.Params { ret := _m.Called(ctx) @@ -248,6 +303,26 @@ func (_m *EVMKeeper) GetParams(ctx types.Context) vmtypes.Params { return r0 } +// GetState provides a mock function with given fields: ctx, addr, key +func (_m *EVMKeeper) GetState(ctx types.Context, addr common.Address, key common.Hash) common.Hash { + ret := _m.Called(ctx, addr, key) + + if len(ret) == 0 { + panic("no return value specified for GetState") + } + + var r0 common.Hash + if rf, ok := ret.Get(0).(func(types.Context, common.Address, common.Hash) common.Hash); ok { + r0 = rf(ctx, addr, key) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(common.Hash) + } + } + + return r0 +} + // IsAvailableStaticPrecompile provides a mock function with given fields: params, address func (_m *EVMKeeper) IsAvailableStaticPrecompile(params *vmtypes.Params, address common.Address) bool { ret := _m.Called(params, address) @@ -284,6 +359,26 @@ func (_m *EVMKeeper) IsContract(ctx types.Context, address common.Address) bool return r0 } +// KVStoreKeys provides a mock function with no fields +func (_m *EVMKeeper) KVStoreKeys() map[string]storetypes.StoreKey { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for KVStoreKeys") + } + + var r0 map[string]storetypes.StoreKey + if rf, ok := ret.Get(0).(func() map[string]storetypes.StoreKey); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(map[string]storetypes.StoreKey) + } + } + + return r0 +} + // SetAccount provides a mock function with given fields: ctx, address, account func (_m *EVMKeeper) SetAccount(ctx types.Context, address common.Address, account statedb.Account) error { ret := _m.Called(ctx, address, account) @@ -307,6 +402,11 @@ func (_m *EVMKeeper) SetCode(ctx types.Context, hash []byte, bytecode []byte) { _m.Called(ctx, hash, bytecode) } +// SetState provides a mock function with given fields: ctx, addr, key, value +func (_m *EVMKeeper) SetState(ctx types.Context, addr common.Address, key common.Hash, value []byte) { + _m.Called(ctx, addr, key, value) +} + // NewEVMKeeper creates a new instance of EVMKeeper. 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 NewEVMKeeper(t interface { diff --git a/x/erc20/types/msg.go b/x/erc20/types/msg.go index 8c4213b1..1f0c4c2b 100644 --- a/x/erc20/types/msg.go +++ b/x/erc20/types/msg.go @@ -8,10 +8,10 @@ import ( errorsmod "cosmossdk.io/errors" "cosmossdk.io/math" - txsigning "cosmossdk.io/x/tx/signing" sdk "github.com/cosmos/cosmos-sdk/types" errortypes "github.com/cosmos/cosmos-sdk/types/errors" + txsigning "github.com/cosmos/cosmos-sdk/x/tx/signing" ) var ( @@ -81,7 +81,7 @@ func (msg MsgConvertERC20) ValidateBasic() error { // GetSignBytes encodes the message for signing func (msg MsgConvertERC20) GetSignBytes() []byte { - return sdk.MustSortJSON(AminoCdc.MustMarshalJSON(&msg)) + return AminoCdc.MustMarshalJSON(&msg) } // ValidateBasic does a sanity check of the provided data @@ -94,7 +94,7 @@ func (m *MsgUpdateParams) ValidateBasic() error { // GetSignBytes implements the LegacyMsg interface. func (m MsgUpdateParams) GetSignBytes() []byte { - return sdk.MustSortJSON(AminoCdc.MustMarshalJSON(&m)) + return AminoCdc.MustMarshalJSON(&m) } // ValidateBasic does a sanity check of the provided data @@ -147,5 +147,5 @@ func (msg MsgConvertCoin) ValidateBasic() error { // GetSignBytes encodes the message for signing func (msg MsgConvertCoin) GetSignBytes() []byte { - return sdk.MustSortJSON(AminoCdc.MustMarshalJSON(&msg)) + return AminoCdc.MustMarshalJSON(&msg) } diff --git a/x/erc20/types/msg_test.go b/x/erc20/types/msg_test.go index 28b9c4ad..b71a4ad3 100644 --- a/x/erc20/types/msg_test.go +++ b/x/erc20/types/msg_test.go @@ -25,16 +25,14 @@ func TestMsgsTestSuite(t *testing.T) { } func (suite *MsgsTestSuite) TestMsgConvertERC20Getters() { - msgInvalid := types.MsgConvertERC20{} msg := types.NewMsgConvertERC20( math.NewInt(100), - sdk.AccAddress(utiltx.GenerateAddress().Bytes()), + utiltx.GenerateAddress().Bytes(), utiltx.GenerateAddress(), utiltx.GenerateAddress(), ) suite.Require().Equal(types.RouterKey, msg.Route()) suite.Require().Equal(types.TypeMsgConvertERC20, msg.Type()) - suite.Require().NotNil(msgInvalid.GetSignBytes()) } func (suite *MsgsTestSuite) TestMsgConvertERC20New() { @@ -132,18 +130,16 @@ func (suite *MsgsTestSuite) TestMsgConvertERC20() { } func (suite *MsgsTestSuite) TestMsgConvertCoinGetters() { - msgInvalid := types.MsgConvertCoin{} msg := types.NewMsgConvertCoin( sdk.NewCoin( "atest", math.NewInt(100), ), utiltx.GenerateAddress(), - sdk.AccAddress(utiltx.GenerateAddress().Bytes()), + utiltx.GenerateAddress().Bytes(), ) suite.Require().Equal(types.RouterKey, msg.Route()) suite.Require().Equal(types.TypeMsgConvertCoin, msg.Type()) - suite.Require().NotNil(msgInvalid.GetSignBytes()) } func (suite *MsgsTestSuite) TestNewMsgConvertCoin() { diff --git a/x/erc20/types/proposal_test.go b/x/erc20/types/proposal_test.go index 63137695..d6acd89f 100644 --- a/x/erc20/types/proposal_test.go +++ b/x/erc20/types/proposal_test.go @@ -178,7 +178,7 @@ func (suite *ProposalTestSuite) TestToggleTokenConversionProposal() { expectPass bool }{ {msg: "Enable token conversion proposal - valid denom", title: "test", description: "test desc", token: "test", expectPass: true}, - {msg: "Enable token conversion proposal - valid address", title: "test", description: "test desc", token: "0x5dCA2483280D9727c80b5518faC4556617fb194F", expectPass: true}, //gitleaks:allow + {msg: "Enable token conversion proposal - valid address", title: "test", description: "test desc", token: "0x5dCA2483280D9727c80b5518faC4556617fb194F", expectPass: true}, //nolint:gosec // test contract {msg: "Enable token conversion proposal - invalid address", title: "test", description: "test desc", token: "0x123", expectPass: false}, // Invalid missing params diff --git a/x/erc20/types/query.pb.go b/x/erc20/types/query.pb.go index ac5fe18e..f3baac3d 100644 --- a/x/erc20/types/query.pb.go +++ b/x/erc20/types/query.pb.go @@ -498,6 +498,7 @@ func _Query_Params_Handler(srv interface{}, ctx context.Context, dec func(interf return interceptor(ctx, in, info, handler) } +var Query_serviceDesc = _Query_serviceDesc var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "cosmos.evm.erc20.v1.Query", HandlerType: (*QueryServer)(nil), diff --git a/x/erc20/types/tx.pb.go b/x/erc20/types/tx.pb.go index 5e68426e..4a978cf2 100644 --- a/x/erc20/types/tx.pb.go +++ b/x/erc20/types/tx.pb.go @@ -817,6 +817,7 @@ func _Msg_ToggleConversion_Handler(srv interface{}, ctx context.Context, dec fun return interceptor(ctx, in, info, handler) } +var Msg_serviceDesc = _Msg_serviceDesc var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "cosmos.evm.erc20.v1.Msg", HandlerType: (*MsgServer)(nil), diff --git a/x/erc20/v2/ibc_middleware.go b/x/erc20/v2/ibc_middleware.go index e3a0f35f..5c9f1cce 100644 --- a/x/erc20/v2/ibc_middleware.go +++ b/x/erc20/v2/ibc_middleware.go @@ -7,11 +7,14 @@ import ( "fmt" erc20types "github.com/cosmos/evm/x/erc20/types" - transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" - channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types" - channeltypesv2 "github.com/cosmos/ibc-go/v10/modules/core/04-channel/v2/types" - ibcapi "github.com/cosmos/ibc-go/v10/modules/core/api" + transfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/v11/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/v11/modules/core/04-channel/types" + channeltypesv2 "github.com/cosmos/ibc-go/v11/modules/core/04-channel/v2/types" + ibcapi "github.com/cosmos/ibc-go/v11/modules/core/api" + ibcerrors "github.com/cosmos/ibc-go/v11/modules/core/errors" + + errorsmod "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -86,8 +89,14 @@ func (im IBCMiddleware) OnRecvPacket( Status: channeltypesv2.PacketStatus_Failure, } } - im.keeper.OnRecvPacket(ctx, packet, ack) - return recvResult + modifiedAck := im.keeper.OnRecvPacket(ctx, packet, ack) + if !modifiedAck.Success() { + return channeltypesv2.RecvPacketResult{Status: channeltypesv2.PacketStatus_Failure} + } else if !bytes.Equal(modifiedAck.Acknowledgement(), ack.Acknowledgement()) { + ctx.Logger().Error("erc20 ibcv2 middleware keeper modified the application ack, original: %s modified: %s", ack.Acknowledgement(), modifiedAck.Acknowledgement()) + return channeltypesv2.RecvPacketResult{Status: recvResult.Status, Acknowledgement: modifiedAck.Acknowledgement()} + } + return channeltypesv2.RecvPacketResult{Status: recvResult.Status, Acknowledgement: modifiedAck.Acknowledgement()} } // OnAcknowledgementPacket implements the IBCModule interface. @@ -102,6 +111,26 @@ func (im IBCMiddleware) OnAcknowledgementPacket( payload channeltypesv2.Payload, relayer sdk.AccAddress, ) error { + var ack channeltypes.Acknowledgement + if bytes.Equal(acknowledgement, channeltypesv2.ErrorAcknowledgement[:]) { + // construct an error acknowledgement from the sentinel so we can reuse the shared transfer logic + ack = channeltypes.NewErrorAcknowledgement(transfertypes.ErrReceiveFailed) + } else { + if err := transfertypes.ModuleCdc.UnmarshalJSON(acknowledgement, &ack); err != nil { + im.keeper.Logger(ctx).Error(fmt.Sprintf("erc20 middleware OnAckPacket failed to unmarshal acknowledgement: %s", err.Error())) + return errorsmod.Wrapf(ibcerrors.ErrUnknownRequest, "cannot unmarshal ICS-20 transfer packet acknowledgement: %v", err) + } + + bz := transfertypes.ModuleCdc.MustMarshalJSON(&ack) + if !bytes.Equal(bz, acknowledgement) { + return errorsmod.Wrapf(ibcerrors.ErrInvalidType, "acknowledgement did not marshal to expected bytes: %X ≠ %X", bz, acknowledgement) + } + + if !ack.Success() { + return errorsmod.Wrapf(ibcerrors.ErrInvalidRequest, "cannot pass in a custom error acknowledgement with IBC v2") + } + } + if err := im.app.OnAcknowledgementPacket(ctx, sourceClient, destinationClient, sequence, acknowledgement, payload, relayer); err != nil { im.keeper.Logger(ctx).Error(fmt.Sprintf("erc20 middleware OnAckPacket failed to call underlying app: %s", err.Error())) return err @@ -112,20 +141,13 @@ func (im IBCMiddleware) OnAcknowledgementPacket( im.keeper.Logger(ctx).Error(fmt.Sprintf("erc20 middleware OnAckPacketfailed failed to convert v2 packet to v1 packet: %s", err.Error())) return err } + var data transfertypes.FungibleTokenPacketData - if err = transfertypes.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err != nil { + if err := transfertypes.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err != nil { im.keeper.Logger(ctx).Error(fmt.Sprintf("erc20 middleware OnAckPacket failed to unmarshal packet data: %s", err.Error())) return err } - var ack channeltypes.Acknowledgement - if bytes.Equal(acknowledgement, channeltypesv2.ErrorAcknowledgement[:]) { - ack = channeltypes.NewErrorAcknowledgement(transfertypes.ErrReceiveFailed) - } else { - if err = transfertypes.ModuleCdc.UnmarshalJSON(acknowledgement, &ack); err != nil { - im.keeper.Logger(ctx).Error(fmt.Sprintf("erc20 middleware OnAckPacket failed to unmarshal acknowledgement: %s", err.Error())) - return err - } - } + return im.keeper.OnAcknowledgementPacket(ctx, packet, data, ack) } diff --git a/x/feemarket/keeper/abci.go b/x/feemarket/keeper/abci.go index ec807fa7..94062f55 100644 --- a/x/feemarket/keeper/abci.go +++ b/x/feemarket/keeper/abci.go @@ -3,6 +3,7 @@ package keeper import ( "errors" "fmt" + gomath "math" "github.com/cosmos/evm/x/feemarket/types" @@ -54,19 +55,17 @@ func (k *Keeper) EndBlock(ctx sdk.Context) error { return err } - gasWanted := math.NewIntFromUint64(k.GetTransientGasWanted(ctx)) - gasUsed := math.NewIntFromUint64(ctx.BlockGasMeter().GasConsumedToLimit()) + gasWanted := ctx.BlockGasWanted() + gasUsed := ctx.BlockGasUsed() - if !gasWanted.IsInt64() { - err := fmt.Errorf("integer overflow by integer type conversion. Gas wanted > MaxInt64. Gas wanted: %s", gasWanted) - k.Logger(ctx).Error(err.Error()) - return err + if gasWanted > gomath.MaxInt64 { + k.Logger(ctx).Error("gas wanted exceeds MaxInt64, clamping", "gas_wanted", gasWanted) + gasWanted = gomath.MaxInt64 } - if !gasUsed.IsInt64() { - err := fmt.Errorf("integer overflow by integer type conversion. Gas used > MaxInt64. Gas used: %s", gasUsed) - k.Logger(ctx).Error(err.Error()) - return err + if gasUsed > gomath.MaxInt64 { + k.Logger(ctx).Error("gas used exceeds MaxInt64, clamping", "gas_used", gasUsed) + gasUsed = gomath.MaxInt64 } // to prevent BaseFee manipulation we limit the gasWanted so that @@ -74,8 +73,8 @@ func (k *Keeper) EndBlock(ctx sdk.Context) error { // this will be keep BaseFee protected from un-penalized manipulation // more info here https://github.com/evmos/ethermint/pull/1105#discussion_r888798925 minGasMultiplier := k.GetParams(ctx).MinGasMultiplier - limitedGasWanted := math.LegacyNewDec(gasWanted.Int64()).Mul(minGasMultiplier) - updatedGasWanted := math.LegacyMaxDec(limitedGasWanted, math.LegacyNewDec(gasUsed.Int64())).TruncateInt().Uint64() + limitedGasWanted := math.LegacyNewDec(int64(gasWanted)).Mul(minGasMultiplier) + updatedGasWanted := math.LegacyMaxDec(limitedGasWanted, math.LegacyNewDec(int64(gasUsed))).TruncateInt().Uint64() k.SetBlockGasWanted(ctx, updatedGasWanted) defer func() { diff --git a/x/feemarket/keeper/keeper.go b/x/feemarket/keeper/keeper.go index b43b21c1..12005716 100644 --- a/x/feemarket/keeper/keeper.go +++ b/x/feemarket/keeper/keeper.go @@ -3,10 +3,10 @@ package keeper import ( "github.com/cosmos/evm/x/feemarket/types" - "cosmossdk.io/log" - storetypes "cosmossdk.io/store/types" + "cosmossdk.io/log/v2" "github.com/cosmos/cosmos-sdk/codec" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -15,15 +15,14 @@ type Keeper struct { // Protobuf codec cdc codec.BinaryCodec // Store key required for the Fee Market Prefix KVStore. - storeKey storetypes.StoreKey - transientKey storetypes.StoreKey + storeKey storetypes.StoreKey // the address capable of executing a MsgUpdateParams message. Typically, this should be the x/gov module account. authority sdk.AccAddress } // NewKeeper generates new fee market module keeper func NewKeeper( - cdc codec.BinaryCodec, authority sdk.AccAddress, storeKey, transientKey storetypes.StoreKey, + cdc codec.BinaryCodec, authority sdk.AccAddress, storeKey storetypes.StoreKey, ) Keeper { // ensure authority account is correctly formatted if err := sdk.VerifyAddressFormat(authority); err != nil { @@ -31,10 +30,9 @@ func NewKeeper( } return Keeper{ - cdc: cdc, - storeKey: storeKey, - authority: authority, - transientKey: transientKey, + cdc: cdc, + storeKey: storeKey, + authority: authority, } } @@ -61,23 +59,3 @@ func (k Keeper) GetBlockGasWanted(ctx sdk.Context) uint64 { store := ctx.KVStore(k.storeKey) return sdk.BigEndianToUint64(store.Get(types.KeyPrefixBlockGasWanted)) } - -// GetTransientGasWanted returns the gas wanted in the current block from transient store. -func (k Keeper) GetTransientGasWanted(ctx sdk.Context) uint64 { - store := ctx.TransientStore(k.transientKey) - return sdk.BigEndianToUint64(store.Get(types.KeyPrefixTransientBlockGasWanted)) -} - -// SetTransientBlockGasWanted sets the block gas wanted to the transient store. -func (k Keeper) SetTransientBlockGasWanted(ctx sdk.Context, gasWanted uint64) { - store := ctx.TransientStore(k.transientKey) - gasBz := sdk.Uint64ToBigEndian(gasWanted) - store.Set(types.KeyPrefixTransientBlockGasWanted, gasBz) -} - -// AddTransientGasWanted adds the cumulative gas wanted in the transient store -func (k Keeper) AddTransientGasWanted(ctx sdk.Context, gasWanted uint64) (uint64, error) { - result := k.GetTransientGasWanted(ctx) + gasWanted - k.SetTransientBlockGasWanted(ctx, result) - return result, nil -} diff --git a/x/feemarket/keeper/msg_server.go b/x/feemarket/keeper/msg_server.go index 11c85dc6..450c6eda 100644 --- a/x/feemarket/keeper/msg_server.go +++ b/x/feemarket/keeper/msg_server.go @@ -5,22 +5,20 @@ import ( "github.com/cosmos/evm/x/feemarket/types" - errorsmod "cosmossdk.io/errors" - sdk "github.com/cosmos/cosmos-sdk/types" - govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ) // UpdateParams implements the gRPC MsgServer interface. When an UpdateParams // proposal passes, it updates the module parameters. The update can only be // performed if the requested authority is the Cosmos SDK governance module -// account. +// account, unless an authority address is configured via the consensus +// AuthorityParams, in which case that takes precedence. func (k *Keeper) UpdateParams(goCtx context.Context, req *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) { - if k.authority.String() != req.Authority { - return nil, errorsmod.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", k.authority.String(), req.Authority) + ctx := sdk.UnwrapSDKContext(goCtx) + if err := sdk.ValidateAuthority(ctx, k.authority.String(), req.Authority); err != nil { + return nil, err } - ctx := sdk.UnwrapSDKContext(goCtx) if err := k.SetParams(ctx, req.Params); err != nil { return nil, err } diff --git a/x/feemarket/module.go b/x/feemarket/module.go index 67557898..e81911f6 100644 --- a/x/feemarket/module.go +++ b/x/feemarket/module.go @@ -29,7 +29,7 @@ import ( const consensusVersion = 1 var ( - _ module.AppModule = AppModule{} + _ module.AppModule = AppModule{} //nolint:staticcheck // keep for legacy purposes _ module.AppModuleBasic = AppModuleBasic{} _ appmodule.HasEndBlocker = AppModule{} diff --git a/x/feemarket/types/keys.go b/x/feemarket/types/keys.go index 055fc513..d2e0c402 100644 --- a/x/feemarket/types/keys.go +++ b/x/feemarket/types/keys.go @@ -10,10 +10,6 @@ const ( // RouterKey uses module name for routing RouterKey = ModuleName - - // TransientKey is the key to access the FeeMarket transient store, that is reset - // during the Commit phase. - TransientKey = "transient_" + ModuleName ) // prefix bytes for the feemarket persistent store diff --git a/x/feemarket/types/msg.go b/x/feemarket/types/msg.go index 31b23e59..86e5e0c7 100644 --- a/x/feemarket/types/msg.go +++ b/x/feemarket/types/msg.go @@ -19,5 +19,5 @@ func (m *MsgUpdateParams) ValidateBasic() error { // GetSignBytes implements the LegacyMsg interface. func (m MsgUpdateParams) GetSignBytes() []byte { - return sdk.MustSortJSON(AminoCdc.MustMarshalJSON(&m)) + return AminoCdc.MustMarshalJSON(&m) } diff --git a/x/feemarket/types/query.pb.go b/x/feemarket/types/query.pb.go index 24a1e80c..bcf3e42c 100644 --- a/x/feemarket/types/query.pb.go +++ b/x/feemarket/types/query.pb.go @@ -458,6 +458,7 @@ func _Query_BlockGas_Handler(srv interface{}, ctx context.Context, dec func(inte return interceptor(ctx, in, info, handler) } +var Query_serviceDesc = _Query_serviceDesc var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "cosmos.evm.feemarket.v1.Query", HandlerType: (*QueryServer)(nil), diff --git a/x/feemarket/types/tx.pb.go b/x/feemarket/types/tx.pb.go index ae2b238f..edafdd46 100644 --- a/x/feemarket/types/tx.pb.go +++ b/x/feemarket/types/tx.pb.go @@ -231,6 +231,7 @@ func _Msg_UpdateParams_Handler(srv interface{}, ctx context.Context, dec func(in return interceptor(ctx, in, info, handler) } +var Msg_serviceDesc = _Msg_serviceDesc var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "cosmos.evm.feemarket.v1.Msg", HandlerType: (*MsgServer)(nil), diff --git a/x/ibc/callbacks/keeper/keeper.go b/x/ibc/callbacks/keeper/keeper.go index d12603e2..ae78acd9 100644 --- a/x/ibc/callbacks/keeper/keeper.go +++ b/x/ibc/callbacks/keeper/keeper.go @@ -12,13 +12,14 @@ import ( erc20types "github.com/cosmos/evm/x/erc20/types" "github.com/cosmos/evm/x/ibc/callbacks/types" evmante "github.com/cosmos/evm/x/vm/ante" + "github.com/cosmos/evm/x/vm/statedb" evmtypes "github.com/cosmos/evm/x/vm/types" - callbacktypes "github.com/cosmos/ibc-go/v10/modules/apps/callbacks/types" - transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" - channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types" - porttypes "github.com/cosmos/ibc-go/v10/modules/core/05-port/types" - ibcexported "github.com/cosmos/ibc-go/v10/modules/core/exported" + callbacktypes "github.com/cosmos/ibc-go/v11/modules/apps/callbacks/types" + transfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/v11/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/v11/modules/core/04-channel/types" + porttypes "github.com/cosmos/ibc-go/v11/modules/core/05-port/types" + ibcexported "github.com/cosmos/ibc-go/v11/modules/core/exported" errorsmod "cosmossdk.io/errors" "cosmossdk.io/math" @@ -129,6 +130,7 @@ func (k ContractKeeper) IBCReceivePacketCallback( cachedCtx, writeFn := ctx.CacheContext() cachedCtx = evmante.BuildEvmExecutionCtx(cachedCtx). WithGasMeter(evmtypes.NewInfiniteGasMeterWithLimit(cbData.CommitGasLimit)) + stateDB := statedb.New(cachedCtx, k.evmKeeper, statedb.NewEmptyTxConfig()) // receiver := sdk.MustAccAddressFromBech32(data.Receiver) receiver, err := sdk.AccAddressFromBech32(data.Receiver) @@ -146,8 +148,10 @@ func (k ContractKeeper) IBCReceivePacketCallback( isolatedAddr := types.GenerateIsolatedAddress(packet.GetDestChannel(), data.Sender) isolatedAddrHex := common.BytesToAddress(isolatedAddr.Bytes()) - acc := k.authKeeper.NewAccountWithAddress(ctx, receiver) - k.authKeeper.SetAccount(ctx, acc) + if !k.authKeeper.HasAccount(ctx, receiver) { + acc := k.authKeeper.NewAccountWithAddress(ctx, receiver) + k.authKeeper.SetAccount(ctx, acc) + } // Ensure receiver address is equal to the isolated address. if receiverHex.Cmp(isolatedAddrHex) != 0 { @@ -189,7 +193,7 @@ func (k ContractKeeper) IBCReceivePacketCallback( // Call the EVM with the remaining gas as the maximum gas limit. // Up to now, the remaining gas is equal to the callback gas limit set by the user. // NOTE: use the cached ctx for the EVM calls. - res, err := k.evmKeeper.CallEVM(cachedCtx, erc20.ABI, receiverHex, tokenPair.GetERC20Contract(), true, remainingGas, "approve", contractAddr, amountInt.BigInt()) + res, err := k.evmKeeper.CallEVM(cachedCtx, stateDB, erc20.ABI, receiverHex, tokenPair.GetERC20Contract(), true, false, remainingGas, "approve", contractAddr, amountInt.BigInt()) if err != nil { return errorsmod.Wrapf(types.ErrAllowanceFailed, "failed to set allowance: %v", err) } @@ -212,7 +216,7 @@ func (k ContractKeeper) IBCReceivePacketCallback( } // NOTE: use the cached ctx for the EVM calls. - res, err = k.evmKeeper.CallEVMWithData(cachedCtx, receiverHex, &contractAddr, cbData.Calldata, true, remainingGas) + res, err = k.evmKeeper.CallEVMWithData(cachedCtx, stateDB, receiverHex, &contractAddr, cbData.Calldata, true, false, remainingGas) if err != nil { return errorsmod.Wrapf(types.ErrEVMCallFailed, "EVM returned error: %s", err.Error()) } @@ -297,6 +301,8 @@ func (k ContractKeeper) IBCOnAcknowledgementPacketCallback( cachedCtx, writeFn := ctx.CacheContext() cachedCtx = evmante.BuildEvmExecutionCtx(cachedCtx). WithGasMeter(evmtypes.NewInfiniteGasMeterWithLimit(cbData.CommitGasLimit)) + cachedCtx = types.WithSourceCallbackExecution(cachedCtx) + stateDB := statedb.New(cachedCtx, k.evmKeeper, statedb.NewEmptyTxConfig()) if len(cbData.Calldata) != 0 { return errorsmod.Wrap(types.ErrInvalidCalldata, "acknowledgement callback data should not contain calldata") @@ -309,6 +315,11 @@ func (k ContractKeeper) IBCOnAcknowledgementPacketCallback( contractAddr := common.HexToAddress(contractAddress) + // Only allow src_callback to target the packet sender. + if contractAddr != sender { + return errorsmod.Wrapf(types.ErrCallbackFailed, "source callback contract must match packet sender: sender=%s contract=%s", sender.Hex(), contractAddr.Hex()) + } + // Check if the contract address contains code. // This check is required because if there is no code, the call will still pass on the EVM side, // but it will ignore the calldata and funds may get stuck. @@ -316,14 +327,9 @@ func (k ContractKeeper) IBCOnAcknowledgementPacketCallback( return errorsmod.Wrapf(types.ErrCallbackFailed, "provided contract address is not a contract: %s", contractAddr) } - abi, err := callbacksabi.LoadABI() - if err != nil { - return err - } - // Call the onPacketAcknowledgement function in the contract // NOTE: use the cached ctx for the EVM calls. - res, err := k.evmKeeper.CallEVM(cachedCtx, *abi, sender, contractAddr, true, math.NewIntFromUint64(cachedCtx.GasMeter().GasRemaining()).BigInt(), "onPacketAcknowledgement", + res, err := k.evmKeeper.CallEVM(cachedCtx, stateDB, callbacksabi.ABI, sender, contractAddr, true, false, math.NewIntFromUint64(cachedCtx.GasMeter().GasRemaining()).BigInt(), "onPacketAcknowledgement", packet.GetSourceChannel(), packet.GetSourcePort(), packet.GetSequence(), packet.GetData(), acknowledgement) if err != nil { return errorsmod.Wrapf(types.ErrCallbackFailed, "EVM returned error: %s", err.Error()) @@ -389,15 +395,6 @@ func (k ContractKeeper) IBCOnTimeoutPacketCallback( return nil } - // `ProcessCallback` in IBC-Go overrides the infinite gas meter with a basic gas meter, - // so we need to generate a new infinite gas meter to run the EVM executions on. - // Skipping this causes the EVM gas estimation function to deplete all Cosmos gas. - // We re-add the actual EVM call gas used to the original context after the call is complete - // with the gas retrieved from the EVM message result. - cachedCtx, writeFn := ctx.CacheContext() - cachedCtx = evmante.BuildEvmExecutionCtx(cachedCtx). - WithGasMeter(evmtypes.NewInfiniteGasMeterWithLimit(cbData.CommitGasLimit)) - if len(cbData.Calldata) != 0 { return errorsmod.Wrap(types.ErrInvalidCalldata, "timeout callback data should not contain calldata") } @@ -409,6 +406,11 @@ func (k ContractKeeper) IBCOnTimeoutPacketCallback( sender := common.BytesToAddress(senderAccount.Bytes()) contractAddr := common.HexToAddress(contractAddress) + // Only allow src_callback to target the packet sender. + if contractAddr != sender { + return errorsmod.Wrapf(types.ErrCallbackFailed, "source callback contract must match packet sender: sender=%s contract=%s", sender.Hex(), contractAddr.Hex()) + } + // Check if the contract address contains code. // This check is required because if there is no code, the call will still pass on the EVM side, // but it will ignore the calldata and funds may get stuck. @@ -416,19 +418,25 @@ func (k ContractKeeper) IBCOnTimeoutPacketCallback( return errorsmod.Wrapf(types.ErrCallbackFailed, "provided contract address is not a contract: %s", contractAddr) } - abi, err := callbacksabi.LoadABI() - if err != nil { - return err - } + // `ProcessCallback` in IBC-Go overrides the infinite gas meter with a basic gas meter, + // so we need to generate a new infinite gas meter to run the EVM executions on. + // Skipping this causes the EVM gas estimation function to deplete all Cosmos gas. + // We re-add the actual EVM call gas used to the original context after the call is complete + // with the gas retrieved from the EVM message result. + cachedCtx, writeFn := ctx.CacheContext() + cachedCtx = evmante.BuildEvmExecutionCtx(cachedCtx). + WithGasMeter(evmtypes.NewInfiniteGasMeterWithLimit(cbData.CommitGasLimit)) + cachedCtx = types.WithSourceCallbackExecution(cachedCtx) + stateDB := statedb.New(cachedCtx, k.evmKeeper, statedb.NewEmptyTxConfig()) - res, err := k.evmKeeper.CallEVM(ctx, *abi, sender, contractAddr, true, math.NewIntFromUint64(cachedCtx.GasMeter().GasRemaining()).BigInt(), "onPacketTimeout", + res, err := k.evmKeeper.CallEVM(cachedCtx, stateDB, callbacksabi.ABI, sender, contractAddr, true, false, math.NewIntFromUint64(cachedCtx.GasMeter().GasRemaining()).BigInt(), "onPacketTimeout", packet.GetSourceChannel(), packet.GetSourcePort(), packet.GetSequence(), packet.GetData()) if err != nil { return errorsmod.Wrapf(types.ErrCallbackFailed, "EVM returned error: %s", err.Error()) } // Consume the actual gas used on the original callback context. - ctx.GasMeter().ConsumeGas(res.GasUsed, "callback onPacketAcknowledgement") + ctx.GasMeter().ConsumeGas(res.GasUsed, "callback onTimeoutPacket") if ctx.GasMeter().IsOutOfGas() { return errorsmod.Wrapf(types.ErrCallbackFailed, "out of gas") } diff --git a/x/ibc/callbacks/keeper/keeper_test.go b/x/ibc/callbacks/keeper/keeper_test.go new file mode 100644 index 00000000..30fc4096 --- /dev/null +++ b/x/ibc/callbacks/keeper/keeper_test.go @@ -0,0 +1,121 @@ +package keeper + +import ( + "encoding/json" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + + "github.com/cosmos/evm/x/ibc/callbacks/types" + callbacktypes "github.com/cosmos/ibc-go/v11/modules/apps/callbacks/types" + transfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/v11/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/v11/modules/core/04-channel/types" + + "cosmossdk.io/log/v2" + + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" + sdktestutil "github.com/cosmos/cosmos-sdk/testutil" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func ensureBech32Config(t *testing.T) { + t.Helper() + cfg := sdk.GetConfig() + if cfg.GetBech32AccountAddrPrefix() != "" { + return + } + cfg.SetBech32PrefixForAccount("cosmos", "cosmospub") + cfg.SetBech32PrefixForValidator("cosmosvaloper", "cosmosvaloperpub") + cfg.SetBech32PrefixForConsensusNode("cosmosvalcons", "cosmosvalconspub") + cfg.Seal() +} + +func assertRejectsMismatchedContractSender( + t *testing.T, + senderEth common.Address, + contractEth common.Address, + seq uint64, + invoke func(ctx sdk.Context, packet channeltypes.Packet, contractHex string, senderBech32 string) error, +) { + t.Helper() + ensureBech32Config(t) + storeKey := storetypes.NewKVStoreKey("test") + tKey := storetypes.NewTransientStoreKey("test_t") + ctx := sdktestutil.DefaultContext(storeKey, tKey) + ctx = ctx.WithLogger(log.NewNopLogger()) + ctx = ctx.WithGasMeter(storetypes.NewGasMeter(10_000_000)) + port := "transfer" + srcChan := "channel-0" + destChan := "channel-1" + gasLimit := "1000000" + timeoutNs := uint64(0) + senderBech32 := sdk.AccAddress(senderEth.Bytes()).String() + memoBz, err := json.Marshal(map[string]any{ + callbacktypes.SourceCallbackKey: map[string]string{ + "address": contractEth.Hex(), + "gas_limit": gasLimit, + }, + }) + require.NoError(t, err) + memo := string(memoBz) + packetData := transfertypes.NewFungibleTokenPacketData( + "stake", + "1", + senderBech32, + senderBech32, + memo, + ) + packetDataBz, err := transfertypes.MarshalPacketData(packetData, transfertypes.V1, transfertypes.EncodingJSON) + require.NoError(t, err) + + packet := channeltypes.NewPacket( + packetDataBz, + seq, + port, + srcChan, + port, + destChan, + clienttypes.NewHeight(0, 100), + timeoutNs, + ) + + err = invoke(ctx, packet, contractEth.Hex(), senderBech32) + require.Error(t, err) + require.ErrorIs(t, err, types.ErrCallbackFailed) + require.ErrorContains(t, err, "source callback contract must match packet sender") +} + +func TestIBCOnAcknowledgementPacketCallback_RejectsMismatchedContractSender(t *testing.T) { + senderEth := common.HexToAddress("0x2222222222222222222222222222222222222222") + contractEth := common.HexToAddress("0x1111111111111111111111111111111111111111") + assertRejectsMismatchedContractSender(t, senderEth, contractEth, 1, func(ctx sdk.Context, packet channeltypes.Packet, contractHex string, senderBech32 string) error { + k := ContractKeeper{} + return k.IBCOnAcknowledgementPacketCallback( + ctx, + packet, + []byte("ack"), + sdk.AccAddress{}, + contractHex, + senderBech32, + transfertypes.V1, + ) + }) +} + +func TestIBCOnTimeoutPacketCallback_RejectsMismatchedContractSender(t *testing.T) { + senderEth := common.HexToAddress("0x3333333333333333333333333333333333333333") + contractEth := common.HexToAddress("0x4444444444444444444444444444444444444444") + assertRejectsMismatchedContractSender(t, senderEth, contractEth, 7, func(ctx sdk.Context, packet channeltypes.Packet, contractHex string, senderBech32 string) error { + k := ContractKeeper{} + return k.IBCOnTimeoutPacketCallback( + ctx, + packet, + sdk.AccAddress{}, + contractHex, + senderBech32, + transfertypes.V1, + ) + }) +} diff --git a/x/ibc/callbacks/types/context.go b/x/ibc/callbacks/types/context.go new file mode 100644 index 00000000..5403700e --- /dev/null +++ b/x/ibc/callbacks/types/context.go @@ -0,0 +1,19 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type sourceCallbackCtxKey struct{} + +// WithSourceCallbackExecution marks a context as executing a source callback. +func WithSourceCallbackExecution(ctx sdk.Context) sdk.Context { + return ctx.WithValue(sourceCallbackCtxKey{}, true) +} + +// IsSourceCallbackExecution returns true when executing inside a source callback. +func IsSourceCallbackExecution(ctx sdk.Context) bool { + v := ctx.Value(sourceCallbackCtxKey{}) + b, ok := v.(bool) + return ok && b +} diff --git a/x/ibc/callbacks/types/context_test.go b/x/ibc/callbacks/types/context_test.go new file mode 100644 index 00000000..3f5bc157 --- /dev/null +++ b/x/ibc/callbacks/types/context_test.go @@ -0,0 +1,20 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/require" + + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" + sdktestutil "github.com/cosmos/cosmos-sdk/testutil" +) + +func TestSourceCallbackExecutionContextMarker(t *testing.T) { + storeKey := storetypes.NewKVStoreKey("test") + tKey := storetypes.NewTransientStoreKey("test_t") + ctx := sdktestutil.DefaultContext(storeKey, tKey) + require.False(t, IsSourceCallbackExecution(ctx)) + callbackCtx := WithSourceCallbackExecution(ctx) + require.True(t, IsSourceCallbackExecution(callbackCtx)) + require.False(t, IsSourceCallbackExecution(ctx)) +} diff --git a/x/ibc/callbacks/types/errors.go b/x/ibc/callbacks/types/errors.go index 1d3d643f..d8a24589 100644 --- a/x/ibc/callbacks/types/errors.go +++ b/x/ibc/callbacks/types/errors.go @@ -6,13 +6,14 @@ import ( // EVM sentinel callback errors var ( - ErrInvalidReceiverAddress = errorsmod.Register(ModuleName, 1, "invalid receiver address") - ErrCallbackFailed = errorsmod.Register(ModuleName, 2, "callback failed") - ErrInvalidCalldata = errorsmod.Register(ModuleName, 3, "invalid calldata in callback data") - ErrContractHasNoCode = errorsmod.Register(ModuleName, 4, "contract has no code") - ErrTokenPairNotFound = errorsmod.Register(ModuleName, 5, "token not registered") - ErrNumberOverflow = errorsmod.Register(ModuleName, 6, "number overflow") - ErrAllowanceFailed = errorsmod.Register(ModuleName, 7, "allowance failed") - ErrEVMCallFailed = errorsmod.Register(ModuleName, 8, "evm call failed") - ErrOutOfGas = errorsmod.Register(ModuleName, 9, "out of gas") + ErrInvalidReceiverAddress = errorsmod.Register(ModuleName, 1, "invalid receiver address") + ErrCallbackFailed = errorsmod.Register(ModuleName, 2, "callback failed") + ErrInvalidCalldata = errorsmod.Register(ModuleName, 3, "invalid calldata in callback data") + ErrContractHasNoCode = errorsmod.Register(ModuleName, 4, "contract has no code") + ErrTokenPairNotFound = errorsmod.Register(ModuleName, 5, "token not registered") + ErrNumberOverflow = errorsmod.Register(ModuleName, 6, "number overflow") + ErrAllowanceFailed = errorsmod.Register(ModuleName, 7, "allowance failed") + ErrEVMCallFailed = errorsmod.Register(ModuleName, 8, "evm call failed") + ErrOutOfGas = errorsmod.Register(ModuleName, 9, "out of gas") + ErrNestedSourceCallbackTransfer = errorsmod.Register(ModuleName, 10, "ics20 transfer is not allowed during source callback execution") ) diff --git a/x/ibc/callbacks/types/expected_keepers.go b/x/ibc/callbacks/types/expected_keepers.go index bafdf9c3..4692c96d 100644 --- a/x/ibc/callbacks/types/expected_keepers.go +++ b/x/ibc/callbacks/types/expected_keepers.go @@ -11,6 +11,7 @@ import ( "github.com/cosmos/evm/x/vm/statedb" evmtypes "github.com/cosmos/evm/x/vm/types" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -18,15 +19,28 @@ import ( type AccountKeeper interface { NewAccountWithAddress(ctx context.Context, addr sdk.AccAddress) sdk.AccountI SetAccount(ctx context.Context, acc sdk.AccountI) + HasAccount(ctx context.Context, addr sdk.AccAddress) bool } // EVMKeeper defines the expected EVM keeper interface used on erc20 type EVMKeeper interface { - CallEVM(ctx sdk.Context, abi abi.ABI, from, contract common.Address, commit bool, gasCap *big.Int, method string, args ...interface{}) (*evmtypes.MsgEthereumTxResponse, error) - CallEVMWithData(ctx sdk.Context, from common.Address, contract *common.Address, data []byte, commit bool, gasCap *big.Int) (*evmtypes.MsgEthereumTxResponse, error) + CallEVM(ctx sdk.Context, stateDB *statedb.StateDB, abi abi.ABI, from, contract common.Address, commit bool, callFromPrecompile bool, gasCap *big.Int, method string, args ...interface{}) (*evmtypes.MsgEthereumTxResponse, error) + CallEVMWithData(ctx sdk.Context, stateDB *statedb.StateDB, from common.Address, contract *common.Address, data []byte, commit bool, callFromPrecompile bool, gasCap *big.Int) (*evmtypes.MsgEthereumTxResponse, error) GetAccountOrEmpty(ctx sdk.Context, addr common.Address) statedb.Account GetAccount(ctx sdk.Context, addr common.Address) *statedb.Account + IsBaseAccountOrEmpty(ctx sdk.Context, addr common.Address) bool IsContract(ctx sdk.Context, addr common.Address) bool + GetState(ctx sdk.Context, addr common.Address, key common.Hash) common.Hash + GetCode(ctx sdk.Context, codeHash common.Hash) []byte + GetCodeHash(ctx sdk.Context, addr common.Address) common.Hash + ForEachStorage(ctx sdk.Context, addr common.Address, cb func(key common.Hash, value common.Hash) bool) + SetAccount(ctx sdk.Context, addr common.Address, account statedb.Account) error + DeleteState(ctx sdk.Context, addr common.Address, key common.Hash) + SetState(ctx sdk.Context, addr common.Address, key common.Hash, value []byte) + DeleteCode(ctx sdk.Context, codeHash []byte) + SetCode(ctx sdk.Context, codeHash []byte, code []byte) + DeleteAccount(ctx sdk.Context, addr common.Address) error + KVStoreKeys() map[string]storetypes.StoreKey } type ERC20Keeper interface { diff --git a/x/ibc/callbacks/types/marshal.go b/x/ibc/callbacks/types/marshal.go index fc91f492..edd5c553 100644 --- a/x/ibc/callbacks/types/marshal.go +++ b/x/ibc/callbacks/types/marshal.go @@ -1,8 +1,8 @@ package types import ( - transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - porttypes "github.com/cosmos/ibc-go/v10/modules/core/05-port/types" + transfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + porttypes "github.com/cosmos/ibc-go/v11/modules/core/05-port/types" sdk "github.com/cosmos/cosmos-sdk/types" ) diff --git a/x/ibc/transfer/ibc_module.go b/x/ibc/transfer/ibc_module.go deleted file mode 100644 index 1d5a4a6c..00000000 --- a/x/ibc/transfer/ibc_module.go +++ /dev/null @@ -1,22 +0,0 @@ -package transfer - -import ( - "github.com/cosmos/evm/x/ibc/transfer/keeper" - ibctransfer "github.com/cosmos/ibc-go/v10/modules/apps/transfer" - porttypes "github.com/cosmos/ibc-go/v10/modules/core/05-port/types" -) - -var _ porttypes.IBCModule = IBCModule{} - -// IBCModule implements the ICS26 interface for transfer given the transfer keeper. -type IBCModule struct { - *ibctransfer.IBCModule -} - -// NewIBCModule creates a new IBCModule given the keeper -func NewIBCModule(k keeper.Keeper) IBCModule { - transferModule := ibctransfer.NewIBCModule(*k.Keeper) - return IBCModule{ - IBCModule: &transferModule, - } -} diff --git a/x/ibc/transfer/keeper/keeper.go b/x/ibc/transfer/keeper/keeper.go deleted file mode 100644 index 48b15080..00000000 --- a/x/ibc/transfer/keeper/keeper.go +++ /dev/null @@ -1,50 +0,0 @@ -package keeper - -import ( - "github.com/cosmos/evm/x/ibc/transfer/types" - "github.com/cosmos/ibc-go/v10/modules/apps/transfer/keeper" - transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - porttypes "github.com/cosmos/ibc-go/v10/modules/core/05-port/types" - - corestore "cosmossdk.io/core/store" - - "github.com/cosmos/cosmos-sdk/codec" -) - -// Keeper defines the modified IBC transfer keeper that embeds the original one. -// It also contains the bank keeper and the erc20 keeper to support ERC20 tokens -// to be sent via IBC. -type Keeper struct { - *keeper.Keeper - bankKeeper types.BankKeeper - erc20Keeper types.ERC20Keeper - accountKeeper types.AccountKeeper -} - -// NewKeeper creates a new IBC transfer Keeper instance -func NewKeeper( - cdc codec.BinaryCodec, - storeService corestore.KVStoreService, - - ics4Wrapper porttypes.ICS4Wrapper, - channelKeeper transfertypes.ChannelKeeper, - msgRouter transfertypes.MessageRouter, - authKeeper types.AccountKeeper, - bankKeeper types.BankKeeper, - erc20Keeper types.ERC20Keeper, - authority string, -) Keeper { - // create the original IBC transfer keeper for embedding - transferKeeper := keeper.NewKeeper( - cdc, storeService, nil, - ics4Wrapper, channelKeeper, msgRouter, - authKeeper, bankKeeper, authority, - ) - - return Keeper{ - Keeper: &transferKeeper, - bankKeeper: bankKeeper, - erc20Keeper: erc20Keeper, - accountKeeper: authKeeper, - } -} diff --git a/x/ibc/transfer/keeper/msg_server.go b/x/ibc/transfer/keeper/msg_server.go deleted file mode 100644 index 33715839..00000000 --- a/x/ibc/transfer/keeper/msg_server.go +++ /dev/null @@ -1,117 +0,0 @@ -package keeper - -import ( - "context" - "strings" - - "github.com/ethereum/go-ethereum/common" - "github.com/hashicorp/go-metrics" - - erc20types "github.com/cosmos/evm/x/erc20/types" - "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - - storetypes "cosmossdk.io/store/types" - - "github.com/cosmos/cosmos-sdk/telemetry" - sdk "github.com/cosmos/cosmos-sdk/types" -) - -var _ types.MsgServer = Keeper{} - -// Transfer defines a gRPC msg server method for the MsgTransfer message. -// This implementation overrides the default ICS20 transfer by converting -// the ERC20 tokens to their Cosmos representation if the token pair has been -// registered through governance. -// If user doesn't have enough balance of coin, it will attempt to convert -// ERC20 tokens to the coin denomination, and continue with a regular transfer. -func (k Keeper) Transfer(goCtx context.Context, msg *types.MsgTransfer) (*types.MsgTransferResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - // Temporarily save the KV and transient KV gas config. To avoid extra costs for relayers - // these two gas config are replaced with empty one and should be restored before exiting this function. - kvGasCfg := ctx.KVGasConfig() - transientKVGasCfg := ctx.TransientKVGasConfig() - ctx = ctx. - WithKVGasConfig(storetypes.GasConfig{}). - WithTransientKVGasConfig(storetypes.GasConfig{}) - - defer func() { - // Return the KV gas config to initial values - ctx = ctx. - WithKVGasConfig(kvGasCfg). - WithTransientKVGasConfig(transientKVGasCfg) - }() - - // use native denom or contract address - denom := strings.TrimPrefix(msg.Token.Denom, erc20types.Erc20NativeCoinDenomPrefix) - - pairID := k.erc20Keeper.GetTokenPairID(ctx, denom) - if len(pairID) == 0 { - // no-op: token is not registered so we can proceed with regular transfer - return k.Keeper.Transfer(ctx, msg) - } - - pair, _ := k.erc20Keeper.GetTokenPair(ctx, pairID) - if !pair.Enabled { - // no-op: pair is not enabled so we can proceed with regular transfer - return k.Keeper.Transfer(ctx, msg) - } - - sender := sdk.MustAccAddressFromBech32(msg.Sender) - - if !k.erc20Keeper.IsERC20Enabled(ctx) { - // no-op: continue with regular transfer - return k.Keeper.Transfer(ctx, msg) - } - - // update the msg denom to the token pair denom - msg.Token.Denom = pair.Denom - - if !pair.IsNativeERC20() { - return k.Keeper.Transfer(ctx, msg) - } - // if the user has enough balance of the Cosmos representation, then we don't need to Convert - balance := k.bankKeeper.SpendableCoin(ctx, sender, pair.Denom) - if balance.Amount.GTE(msg.Token.Amount) { - - defer func() { - telemetry.IncrCounterWithLabels( - []string{"erc20", "ibc", "transfer", "total"}, - 1, - []metrics.Label{ - telemetry.NewLabel("denom", pair.Denom), - }, - ) - }() - - return k.Keeper.Transfer(ctx, msg) - } - - // Only convert if the pair is a native ERC20 - // only convert the remaining difference - difference := msg.Token.Amount.Sub(balance.Amount) - - msgConvertERC20 := erc20types.NewMsgConvertERC20( - difference, - sender, - pair.GetERC20Contract(), - common.BytesToAddress(sender.Bytes()), - ) - - // Use MsgConvertERC20 to convert the ERC20 to a Cosmos IBC Coin - if _, err := k.erc20Keeper.ConvertERC20(ctx, msgConvertERC20); err != nil { - return nil, err - } - - defer func() { - telemetry.IncrCounterWithLabels( - []string{"erc20", "ibc", "transfer", "total"}, - 1, - []metrics.Label{ - telemetry.NewLabel("denom", pair.Denom), - }, - ) - }() - - return k.Keeper.Transfer(ctx, msg) -} diff --git a/x/ibc/transfer/module.go b/x/ibc/transfer/module.go deleted file mode 100644 index bda640f0..00000000 --- a/x/ibc/transfer/module.go +++ /dev/null @@ -1,62 +0,0 @@ -package transfer - -import ( - "fmt" - - "github.com/cosmos/evm/x/ibc/transfer/keeper" - ibctransfer "github.com/cosmos/ibc-go/v10/modules/apps/transfer" - ibctransferkeeper "github.com/cosmos/ibc-go/v10/modules/apps/transfer/keeper" - "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - - "github.com/cosmos/cosmos-sdk/types/module" -) - -var ( - _ module.AppModule = AppModule{} - _ module.AppModuleBasic = AppModuleBasic{} -) - -// AppModuleBasic embeds the IBC Transfer AppModuleBasic -type AppModuleBasic struct { - *ibctransfer.AppModuleBasic -} - -// AppModule represents the AppModule for this module -type AppModule struct { - *ibctransfer.AppModule - keeper keeper.Keeper -} - -// NewAppModule creates a new 20-transfer module -func NewAppModule(k keeper.Keeper) AppModule { - am := ibctransfer.NewAppModule(*k.Keeper) - return AppModule{ - AppModule: &am, - keeper: k, - } -} - -// RegisterServices registers module services. -func (am AppModule) RegisterServices(cfg module.Configurator) { - // Override Transfer Msg Server - types.RegisterMsgServer(cfg.MsgServer(), am.keeper) - types.RegisterQueryServer(cfg.QueryServer(), am.keeper) - - m := ibctransferkeeper.NewMigrator(*am.keeper.Keeper) - - if err := cfg.RegisterMigration(types.ModuleName, 2, m.MigrateTotalEscrowForDenom); err != nil { - panic(fmt.Sprintf("failed to migrate transfer app from version 2 to 3: %v", err)) - } - - if err := cfg.RegisterMigration(types.ModuleName, 3, m.MigrateParams); err != nil { - panic(fmt.Errorf("failed to migrate transfer app version 3 to 4 (self-managed params migration): %v", err)) - } - - if err := cfg.RegisterMigration(types.ModuleName, 4, m.MigrateDenomMetadata); err != nil { - panic(fmt.Errorf("failed to migrate transfer app from version 4 to 5 (set denom metadata migration): %v", err)) - } - - if err := cfg.RegisterMigration(types.ModuleName, 5, m.MigrateDenomTraceToDenom); err != nil { - panic(fmt.Errorf("failed to migrate transfer app from version 5 to 6 (migrate DenomTrace to Denom): %v", err)) - } -} diff --git a/x/ibc/transfer/types/channels.go b/x/ibc/transfer/types/channels.go deleted file mode 100644 index 1316b848..00000000 --- a/x/ibc/transfer/types/channels.go +++ /dev/null @@ -1,13 +0,0 @@ -package types - -// Osmosis channels -const ( - OsmosisTestnetChannelID = "channel-215" - OsmosisMainnetChannelID = "channel-0" -) - -// Stride channels -const ( - StrideTestnetChannelID = "channel-25" - StrideMainnetChannelID = "channel-25" -) diff --git a/x/ibc/transfer/types/interfaces.go b/x/ibc/transfer/types/interfaces.go deleted file mode 100644 index fa5d349f..00000000 --- a/x/ibc/transfer/types/interfaces.go +++ /dev/null @@ -1,31 +0,0 @@ -package types - -import ( - "context" - - erc20types "github.com/cosmos/evm/x/erc20/types" - transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - - sdk "github.com/cosmos/cosmos-sdk/types" -) - -// AccountKeeper defines the expected interface needed to retrieve account info. -type AccountKeeper interface { - transfertypes.AccountKeeper - GetAccount(context.Context, sdk.AccAddress) sdk.AccountI -} - -// BankKeeper defines the expected interface needed to check balances and send coins. -type BankKeeper interface { - transfertypes.BankKeeper - GetBalance(ctx context.Context, addr sdk.AccAddress, denom string) sdk.Coin -} - -// ERC20Keeper defines the expected ERC20 keeper interface for supporting -// ERC20 token transfers via IBC. -type ERC20Keeper interface { - IsERC20Enabled(ctx sdk.Context) bool - GetTokenPairID(ctx sdk.Context, token string) []byte - GetTokenPair(ctx sdk.Context, id []byte) (erc20types.TokenPair, bool) - ConvertERC20(ctx context.Context, msg *erc20types.MsgConvertERC20) (*erc20types.MsgConvertERC20Response, error) -} diff --git a/x/ibc/transfer/v2/ibc_module.go b/x/ibc/transfer/v2/ibc_module.go deleted file mode 100644 index 06996dd9..00000000 --- a/x/ibc/transfer/v2/ibc_module.go +++ /dev/null @@ -1,22 +0,0 @@ -package v2 - -import ( - "github.com/cosmos/evm/x/ibc/transfer/keeper" - v2 "github.com/cosmos/ibc-go/v10/modules/apps/transfer/v2" - ibcapi "github.com/cosmos/ibc-go/v10/modules/core/api" -) - -var _ ibcapi.IBCModule = IBCModule{} - -// IBCModule implements the ICS26 interface for transfer given the transfer keeper. -type IBCModule struct { - *v2.IBCModule -} - -// NewIBCModule creates a new IBCModule given the keeper -func NewIBCModule(k keeper.Keeper) IBCModule { - transferModule := v2.NewIBCModule(*k.Keeper) - return IBCModule{ - IBCModule: transferModule, - } -} diff --git a/x/vm/ante/ctx.go b/x/vm/ante/ctx.go index f73d3999..ed5aac4f 100644 --- a/x/vm/ante/ctx.go +++ b/x/vm/ante/ctx.go @@ -1,8 +1,7 @@ package ante import ( - storetypes "cosmossdk.io/store/types" - + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdktypes "github.com/cosmos/cosmos-sdk/types" ) diff --git a/x/vm/client/cli/query.go b/x/vm/client/cli/query.go index e3ecc752..8395e444 100644 --- a/x/vm/client/cli/query.go +++ b/x/vm/client/cli/query.go @@ -70,7 +70,7 @@ func GetStorageCmd() *cobra.Command { Key: key, } - res, err := queryClient.Storage(rpctypes.ContextWithHeight(clientCtx.Height), req) + res, err := queryClient.Storage(rpctypes.NewContextWithHeight(clientCtx.Height), req) if err != nil { return err } @@ -107,7 +107,7 @@ func GetCodeCmd() *cobra.Command { Address: address, } - res, err := queryClient.Code(rpctypes.ContextWithHeight(clientCtx.Height), req) + res, err := queryClient.Code(rpctypes.NewContextWithHeight(clientCtx.Height), req) if err != nil { return err } @@ -144,7 +144,7 @@ func GetAccountCmd() *cobra.Command { Address: address, } - res, err := queryClient.Account(rpctypes.ContextWithHeight(clientCtx.Height), req) + res, err := queryClient.Account(rpctypes.NewContextWithHeight(clientCtx.Height), req) if err != nil { return err } diff --git a/x/vm/keeper/abci.go b/x/vm/keeper/abci.go index 558c230b..1f241fa0 100644 --- a/x/vm/keeper/abci.go +++ b/x/vm/keeper/abci.go @@ -1,17 +1,19 @@ package keeper import ( - ethtypes "github.com/ethereum/go-ethereum/core/types" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" + evmtrace "github.com/cosmos/evm/trace" evmtypes "github.com/cosmos/evm/x/vm/types" - storetypes "cosmossdk.io/store/types" - sdk "github.com/cosmos/cosmos-sdk/types" ) // BeginBlock emits a base fee event which will be adjusted to the evm decimals -func (k *Keeper) BeginBlock(ctx sdk.Context) error { +func (k *Keeper) BeginBlock(ctx sdk.Context) (err error) { + ctx, span := ctx.StartSpan(tracer, "BeginBlock", trace.WithAttributes(attribute.Int64("block_num", ctx.BlockHeight()))) + defer func() { evmtrace.EndSpanErr(span, err) }() logger := ctx.Logger().With("begin_block", "evm") // Base fee is already set on FeeMarket BeginBlock @@ -39,16 +41,11 @@ func (k *Keeper) BeginBlock(ctx sdk.Context) error { // EndBlock also retrieves the bloom filter value from the transient store and commits it to the // KVStore. The EVM end block logic doesn't update the validator set, thus it returns // an empty slice. -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 && !k.evmMempool.HasEventBus() { - k.evmMempool.GetBlockchain().NotifyNewBlock() - } +func (k *Keeper) EndBlock(ctx sdk.Context) (err error) { + ctx, span := ctx.StartSpan(tracer, "EndBlock", trace.WithAttributes(attribute.Int64("block_num", ctx.BlockHeight()))) + defer func() { evmtrace.EndSpanErr(span, err) }() - bloom := ethtypes.BytesToBloom(k.GetBlockBloomTransient(infCtx).Bytes()) - k.EmitBlockBloomEvent(infCtx, bloom) + k.CollectTxBloom(ctx) return nil } diff --git a/x/vm/keeper/block_proposer.go b/x/vm/keeper/block_proposer.go index 59588ac6..75c98cbd 100644 --- a/x/vm/keeper/block_proposer.go +++ b/x/vm/keeper/block_proposer.go @@ -2,6 +2,10 @@ package keeper import ( "github.com/ethereum/go-ethereum/common" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" + + evmtrace "github.com/cosmos/evm/trace" errorsmod "cosmossdk.io/errors" @@ -9,9 +13,19 @@ import ( stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) -// GetCoinbaseAddress returns the block proposer's validator operator address. -func (k Keeper) GetCoinbaseAddress(ctx sdk.Context, proposerAddress sdk.ConsAddress) (common.Address, error) { - validator, err := k.stakingKeeper.GetValidatorByConsAddr(ctx, GetProposerAddress(ctx, proposerAddress)) +// GetCoinbaseAddress converts the block proposer's validator operator address to an Ethereum address +// for use as block.coinbase in the EVM. +func (k Keeper) GetCoinbaseAddress(ctx sdk.Context, proposerAddress sdk.ConsAddress) (_ common.Address, err error) { + ctx, span := ctx.StartSpan(tracer, "GetCoinbaseAddress", trace.WithAttributes( + attribute.String("proposer_address", proposerAddress.String()), + )) + defer func() { evmtrace.EndSpanErr(span, err) }() + proposerAddress = GetProposerAddress(ctx, proposerAddress) + if len(proposerAddress) == 0 { + // it's ok that proposer address don't exsits in some contexts like CheckTx. + return common.Address{}, nil + } + validator, err := k.stakingKeeper.GetValidatorByConsAddr(ctx, proposerAddress) if err != nil { return common.Address{}, errorsmod.Wrapf( stakingtypes.ErrNoValidatorFound, @@ -21,8 +35,15 @@ func (k Keeper) GetCoinbaseAddress(ctx sdk.Context, proposerAddress sdk.ConsAddr ) } - coinbase := common.BytesToAddress([]byte(validator.GetOperator())) - return coinbase, nil + bz, err := sdk.ValAddressFromBech32(validator.GetOperator()) + if err != nil { + return common.Address{}, errorsmod.Wrapf( + err, + "failed to convert validator operator address %s to bytes", + validator.GetOperator(), + ) + } + return common.BytesToAddress(bz), nil } // GetProposerAddress returns current block proposer's address when provided proposer address is empty. diff --git a/x/vm/keeper/block_proposer_test.go b/x/vm/keeper/block_proposer_test.go new file mode 100644 index 00000000..45a4e9fd --- /dev/null +++ b/x/vm/keeper/block_proposer_test.go @@ -0,0 +1,67 @@ +package keeper_test + +import ( + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/mock" + + sdk "github.com/cosmos/cosmos-sdk/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" +) + +func (suite *KeeperTestSuite) TestGetCoinbaseAddress() { + proposerConsAddr := sdk.ConsAddress([]byte("proposer")) + valAddr := sdk.ValAddress([]byte("test_validator_addr")) + validatorOperator := valAddr.String() + + testCases := []struct { + name string + proposerAddr sdk.ConsAddress + malleate func() + expectedAddr common.Address + expectedErr bool + }{ + { + name: "success - validator found", + proposerAddr: proposerConsAddr, + malleate: func() { + validator := stakingtypes.Validator{ + OperatorAddress: validatorOperator, + } + suite.stakingKeeper.On("GetValidatorByConsAddr", mock.Anything, proposerConsAddr). + Return(validator, nil).Once() + }, + expectedAddr: common.BytesToAddress(valAddr.Bytes()), + expectedErr: false, + }, + { + name: "validator not found returns error", + proposerAddr: proposerConsAddr, + malleate: func() { + suite.stakingKeeper.On("GetValidatorByConsAddr", mock.Anything, proposerConsAddr). + Return(stakingtypes.Validator{}, stakingtypes.ErrNoValidatorFound).Once() + }, + expectedAddr: common.Address{}, + expectedErr: true, + }, + { + name: "empty proposer address returns empty address", + proposerAddr: sdk.ConsAddress{}, + malleate: func() {}, + expectedAddr: common.Address{}, + expectedErr: false, + }, + } + + for _, tc := range testCases { + suite.Run(tc.name, func() { + tc.malleate() + addr, err := suite.vmKeeper.GetCoinbaseAddress(suite.ctx, tc.proposerAddr) + if tc.expectedErr { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + suite.Require().Equal(tc.expectedAddr, addr) + } + }) + } +} diff --git a/x/vm/keeper/call_evm.go b/x/vm/keeper/call_evm.go index 3f5b36c7..82d4dfcc 100644 --- a/x/vm/keeper/call_evm.go +++ b/x/vm/keeper/call_evm.go @@ -7,8 +7,12 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" ethtypes "github.com/ethereum/go-ethereum/core/types" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" "github.com/cosmos/evm/server/config" + evmtrace "github.com/cosmos/evm/trace" + "github.com/cosmos/evm/x/vm/statedb" "github.com/cosmos/evm/x/vm/types" errorsmod "cosmossdk.io/errors" @@ -17,15 +21,16 @@ import ( ) // CallEVM performs a smart contract method call using given args. -func (k Keeper) CallEVM( - ctx sdk.Context, - abi abi.ABI, - from, contract common.Address, - commit bool, - gasCap *big.Int, - method string, - args ...interface{}, -) (*types.MsgEthereumTxResponse, error) { +// Note: if you call this from a precompile context, ensure that +// you use the existing stateDB. +func (k Keeper) CallEVM(ctx sdk.Context, stateDB *statedb.StateDB, abi abi.ABI, from, contract common.Address, commit, callFromPrecompile bool, gasCap *big.Int, method string, args ...interface{}) (_ *types.MsgEthereumTxResponse, err error) { + ctx, span := ctx.StartSpan(tracer, "CallEVM", trace.WithAttributes( + attribute.String("from", from.Hex()), + attribute.String("contract", contract.Hex()), + attribute.String("method", method), + attribute.Bool("commit", commit), + )) + defer func() { evmtrace.EndSpanErr(span, err) }() data, err := abi.Pack(method, args...) if err != nil { return nil, errorsmod.Wrap( @@ -34,7 +39,7 @@ func (k Keeper) CallEVM( ) } - resp, err := k.CallEVMWithData(ctx, from, &contract, data, commit, gasCap) + resp, err := k.CallEVMWithData(ctx, stateDB, from, &contract, data, commit, callFromPrecompile, gasCap) if err != nil { return resp, errorsmod.Wrapf(err, "contract call failed: method '%s', contract '%s'", method, contract) } @@ -42,25 +47,41 @@ func (k Keeper) CallEVM( } // CallEVMWithData performs a smart contract method call using contract data. -func (k Keeper) CallEVMWithData( - ctx sdk.Context, - from common.Address, - contract *common.Address, - data []byte, - commit bool, - gasCap *big.Int, -) (*types.MsgEthereumTxResponse, error) { +// Note: if you call this from a precompile context, ensure that +// you use the existing stateDB. +func (k Keeper) CallEVMWithData(ctx sdk.Context, stateDB *statedb.StateDB, from common.Address, contract *common.Address, data []byte, commit bool, callFromPrecompile bool, gasCap *big.Int) (_ *types.MsgEthereumTxResponse, err error) { + contractAddr := "" + if contract != nil { + contractAddr = contract.Hex() + } + ctx, span := ctx.StartSpan(tracer, "CallEVMWithData", trace.WithAttributes( + attribute.String("from", from.Hex()), + attribute.String("contract", contractAddr), + attribute.Bool("commit", commit), + attribute.Int("data_size", len(data)), + )) + defer func() { evmtrace.EndSpanErr(span, err) }() nonce, err := k.accountKeeper.GetSequence(ctx, from.Bytes()) if err != nil { return nil, err } + gasLimit := config.DefaultGasCap + if gasCap != nil && gasCap.Sign() > 0 { + if gasCap.BitLen() <= 64 { + provided := gasCap.Uint64() + if provided < gasLimit { + gasLimit = provided + } + } + } + msg := core.Message{ From: from, To: contract, Nonce: nonce, Value: big.NewInt(0), - GasLimit: config.DefaultGasCap, + GasLimit: gasLimit, GasPrice: big.NewInt(0), GasTipCap: big.NewInt(0), GasFeeCap: big.NewInt(0), @@ -68,7 +89,7 @@ func (k Keeper) CallEVMWithData( AccessList: ethtypes.AccessList{}, } - res, err := k.ApplyMessage(ctx, msg, nil, commit, true) + res, err := k.ApplyMessage(ctx, stateDB, msg, nil, commit, callFromPrecompile, true) if err != nil { return nil, err } diff --git a/x/vm/keeper/coin_info.go b/x/vm/keeper/coin_info.go index 78399afa..765de247 100644 --- a/x/vm/keeper/coin_info.go +++ b/x/vm/keeper/coin_info.go @@ -3,16 +3,23 @@ package keeper import ( "fmt" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" + + evmtrace "github.com/cosmos/evm/trace" "github.com/cosmos/evm/x/vm/types" sdk "github.com/cosmos/cosmos-sdk/types" ) // LoadEvmCoinInfo load EvmCoinInfo from bank denom metadata -func (k Keeper) LoadEvmCoinInfo(ctx sdk.Context) (types.EvmCoinInfo, error) { - var decimals types.Decimals - +func (k Keeper) LoadEvmCoinInfo(ctx sdk.Context) (_ types.EvmCoinInfo, err error) { params := k.GetParams(ctx) + ctx, span := ctx.StartSpan(tracer, "LoadEvmCoinInfo", trace.WithAttributes( + attribute.String("evm_denom", params.EvmDenom), + )) + defer func() { evmtrace.EndSpanErr(span, err) }() + var decimals types.Decimals evmDenomMetadata, found := k.bankWrapper.GetDenomMetaData(ctx, params.EvmDenom) if !found { return types.EvmCoinInfo{}, fmt.Errorf("denom metadata %s could not be found", params.EvmDenom) @@ -43,7 +50,9 @@ func (k Keeper) LoadEvmCoinInfo(ctx sdk.Context) (types.EvmCoinInfo, error) { } // InitEvmCoinInfo load EvmCoinInfo from bank denom metadata and store it in the module -func (k Keeper) InitEvmCoinInfo(ctx sdk.Context) error { +func (k Keeper) InitEvmCoinInfo(ctx sdk.Context) (err error) { + ctx, span := ctx.StartSpan(tracer, "InitEvmCoinInfo") + defer func() { evmtrace.EndSpanErr(span, err) }() coinInfo, err := k.LoadEvmCoinInfo(ctx) if err != nil { return err @@ -52,18 +61,31 @@ func (k Keeper) InitEvmCoinInfo(ctx sdk.Context) error { } // GetEvmCoinInfo returns the EVM Coin Info stored in the module -func (k Keeper) GetEvmCoinInfo(ctx sdk.Context) (coinInfo types.EvmCoinInfo) { - store := ctx.KVStore(k.storeKey) - bz := store.Get(types.KeyPrefixEvmCoinInfo) +// Make sure to call this method ONLY after genesis block. +func (k Keeper) GetEvmCoinInfo(ctx sdk.Context) types.EvmCoinInfo { + ctx, span := ctx.StartSpan(tracer, "GetEvmCoinInfo") + defer span.End() + + bz := ctx.KVStore(k.storeKey).Get(types.KeyPrefixEvmCoinInfo) if bz == nil { - return coinInfo + // fallback a global variable in case if + // ctx height doesn't contain evmCoinInfo. + return types.GetCoinInfo() } + + var coinInfo types.EvmCoinInfo k.cdc.MustUnmarshal(bz, &coinInfo) - return + + return coinInfo } // SetEvmCoinInfo sets the EVM Coin Info stored in the module -func (k Keeper) SetEvmCoinInfo(ctx sdk.Context, coinInfo types.EvmCoinInfo) error { +func (k Keeper) SetEvmCoinInfo(ctx sdk.Context, coinInfo types.EvmCoinInfo) (err error) { + ctx, span := ctx.StartSpan(tracer, "SetEvmCoinInfo", trace.WithAttributes( + attribute.String("denom", coinInfo.Denom), + attribute.Int64("decimals", int64(coinInfo.Decimals)), + )) + defer func() { evmtrace.EndSpanErr(span, err) }() store := ctx.KVStore(k.storeKey) bz, err := k.cdc.Marshal(&coinInfo) if err != nil { diff --git a/x/vm/keeper/config.go b/x/vm/keeper/config.go index 53005086..81bb24fb 100644 --- a/x/vm/keeper/config.go +++ b/x/vm/keeper/config.go @@ -5,7 +5,10 @@ import ( "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/tracing" "github.com/ethereum/go-ethereum/core/vm" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" + evmtrace "github.com/cosmos/evm/trace" "github.com/cosmos/evm/x/vm/statedb" "github.com/cosmos/evm/x/vm/types" @@ -15,7 +18,9 @@ import ( ) // EVMConfig creates the EVMConfig based on current state -func (k *Keeper) EVMConfig(ctx sdk.Context, proposerAddress sdk.ConsAddress) (*statedb.EVMConfig, error) { +func (k *Keeper) EVMConfig(ctx sdk.Context, proposerAddress sdk.ConsAddress) (_ *statedb.EVMConfig, err error) { + ctx, span := ctx.StartSpan(tracer, "EVMConfig", trace.WithAttributes(attribute.String("proposer", proposerAddress.String()))) + defer func() { evmtrace.EndSpanErr(span, err) }() params := k.GetParams(ctx) feemarketParams := k.feeMarketWrapper.GetParams(ctx) @@ -35,18 +40,22 @@ func (k *Keeper) EVMConfig(ctx sdk.Context, proposerAddress sdk.ConsAddress) (*s }, nil } -// TxConfig loads `TxConfig` from current transient storage +// TxConfig loads `TxConfig` from current transient storage. func (k *Keeper) TxConfig(ctx sdk.Context, txHash common.Hash) statedb.TxConfig { return statedb.NewTxConfig( - txHash, // TxHash - uint(k.GetTxIndexTransient(ctx)), // TxIndex - uint(k.GetLogSizeTransient(ctx)), // LogIndex + txHash, + uint(ctx.TxIndex()), //#nosec G115 ) } // VMConfig creates an EVM configuration from the debug setting and the extra EIPs enabled on the // module parameters. The config generated uses the default JumpTable from the EVM. -func (k Keeper) VMConfig(ctx sdk.Context, _ core.Message, cfg *statedb.EVMConfig, tracer *tracing.Hooks) vm.Config { +func (k Keeper) VMConfig(ctx sdk.Context, _ core.Message, cfg *statedb.EVMConfig, tracingHooks *tracing.Hooks) vm.Config { + ctx, span := ctx.StartSpan(tracer, "VMConfig", trace.WithAttributes( + attribute.Bool("enable_preimage_recording", cfg.EnablePreimageRecording), + attribute.Int("extra_eips_count", len(cfg.Params.ExtraEIPs)), + )) + defer span.End() noBaseFee := true if types.IsLondon(types.GetEthChainConfig(), ctx.BlockHeight()) { noBaseFee = cfg.FeeMarketParams.NoBaseFee @@ -54,7 +63,7 @@ func (k Keeper) VMConfig(ctx sdk.Context, _ core.Message, cfg *statedb.EVMConfig return vm.Config{ EnablePreimageRecording: cfg.EnablePreimageRecording, - Tracer: tracer, + Tracer: tracingHooks, NoBaseFee: noBaseFee, ExtraEips: cfg.Params.EIPs(), } diff --git a/x/vm/keeper/fees.go b/x/vm/keeper/fees.go index a5569fa1..9c40e166 100644 --- a/x/vm/keeper/fees.go +++ b/x/vm/keeper/fees.go @@ -1,11 +1,17 @@ package keeper import ( + "fmt" "math/big" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" ethtypes "github.com/ethereum/go-ethereum/core/types" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" + + evmtrace "github.com/cosmos/evm/trace" + "github.com/cosmos/evm/x/vm/types" errorsmod "cosmossdk.io/errors" sdkmath "cosmossdk.io/math" @@ -13,6 +19,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" errortypes "github.com/cosmos/cosmos-sdk/types/errors" authante "github.com/cosmos/cosmos-sdk/x/auth/ante" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" ) // CheckSenderBalance validates that the tx cost value is positive and that the @@ -44,7 +51,12 @@ func (k *Keeper) DeductTxCostsFromUserBalance( ctx sdk.Context, fees sdk.Coins, from common.Address, -) error { +) (err error) { + ctx, span := ctx.StartSpan(tracer, "DeductTxCostsFromUserBalance", trace.WithAttributes( + attribute.String("from", from.Hex()), + attribute.String("fees", fees.String()), + )) + defer func() { evmtrace.EndSpanErr(span, err) }() // fetch sender account signerAcc, err := authante.GetSignerAcc(ctx, k.accountKeeper, from.Bytes()) if err != nil { @@ -54,7 +66,12 @@ func (k *Keeper) DeductTxCostsFromUserBalance( // Deduct fees from the user balance. Notice that it is used // the bankWrapper to properly convert fees from the 18 decimals // representation to the original one before calling into the bank keeper. - if err := authante.DeductFees(k.bankWrapper, ctx, signerAcc, fees); err != nil { + if k.virtualFeeCollection { + err = DeductFees(k.bankWrapper, k, ctx, signerAcc, fees) + } else { + err = authante.DeductFees(k.bankWrapper, ctx, signerAcc, fees) + } + if err != nil { return errorsmod.Wrapf(err, "failed to deduct full gas cost %s from the user %s balance", fees, from) } @@ -116,3 +133,38 @@ func VerifyFee( return sdk.Coins{{Denom: denom, Amount: sdkmath.NewIntFromBigInt(feeAmt)}}, nil } + +// DeductFees deducts fees from the given account. +func DeductFees(bankKeeper types.BankKeeper, vmKeeper types.VMKeeper, ctx sdk.Context, acc sdk.AccountI, fees sdk.Coins) (err error) { + ctx, span := ctx.StartSpan(tracer, "DeductFees", trace.WithAttributes( + attribute.String("account", acc.GetAddress().String()), + attribute.String("fees", fees.String()), + )) + defer func() { evmtrace.EndSpanErr(span, err) }() + if !fees.IsValid() { + return errorsmod.Wrapf(errortypes.ErrInsufficientFee, "invalid fee amount: %s", fees) + } + evmCoinInfo := vmKeeper.GetEvmCoinInfo(ctx) + for _, coin := range fees { + md, found := bankKeeper.GetDenomMetaData(ctx, coin.Denom) + if !found { + // DenomMetadata being set for the evm coin is enforced in genesis + continue + } + for _, du := range md.DenomUnits { + if du.Denom == evmCoinInfo.DisplayDenom && du.Exponent != types.EighteenDecimals.Uint32() { + panic( + fmt.Sprintf( + "Cannot use virtual fee collection for denom %s, which has a display denom that has %d exponent", + du.Denom, du.Exponent)) + } + } + } + + err = bankKeeper.SendCoinsFromAccountToModuleVirtual(ctx, acc.GetAddress(), authtypes.FeeCollectorName, fees) + if err != nil { + return errorsmod.Wrap(errortypes.ErrInsufficientFunds, err.Error()) + } + + return nil +} diff --git a/x/vm/keeper/fees_test.go b/x/vm/keeper/fees_test.go new file mode 100644 index 00000000..57253794 --- /dev/null +++ b/x/vm/keeper/fees_test.go @@ -0,0 +1,94 @@ +package keeper_test + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/cosmos/evm/x/vm/keeper" + vmtypes "github.com/cosmos/evm/x/vm/types" + "github.com/cosmos/evm/x/vm/types/mocks" + + sdkmath "cosmossdk.io/math" + + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" + "github.com/cosmos/cosmos-sdk/testutil" + 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" +) + +func TestDeductFees(t *testing.T) { + testCases := []struct { + name string + feeCoin sdk.Coin + sdkDenom banktypes.DenomUnit + evmCoinInfo vmtypes.EvmCoinInfo + expectedPanic bool + expectedErr error + }{ + { + name: "happy path coins", + feeCoin: sdk.NewCoin("feecoin", sdkmath.NewInt(100)), + sdkDenom: banktypes.DenomUnit{Denom: "feecoin", Exponent: 18}, + evmCoinInfo: vmtypes.EvmCoinInfo{DisplayDenom: "feecoin"}, + expectedPanic: false, + expectedErr: nil, + }, + { + name: "panic on exponent mismatch", + feeCoin: sdk.NewCoin("feecoin", sdkmath.NewInt(100)), + sdkDenom: banktypes.DenomUnit{Denom: "feecoin", Exponent: 6}, + evmCoinInfo: vmtypes.EvmCoinInfo{DisplayDenom: "feecoin"}, + expectedPanic: true, + expectedErr: nil, + }, + { + name: "error on bank call failure", + feeCoin: sdk.NewCoin("feecoin", sdkmath.NewInt(100)), + sdkDenom: banktypes.DenomUnit{Denom: "feecoin", Exponent: 18}, + evmCoinInfo: vmtypes.EvmCoinInfo{DisplayDenom: "feecoin"}, + expectedPanic: false, + expectedErr: errors.New("foo"), + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + // Setup + vmKeeper := mocks.NewVMKeeper(t) + bankKeeper := mocks.NewBankKeeper(t) + + key1 := storetypes.NewKVStoreKey(vmtypes.StoreKey) + key2 := storetypes.NewTransientStoreKey("foobar") + + ctx := testutil.DefaultContext(key1, key2) + feeCoins := sdk.NewCoins(tc.feeCoin) + acc := authtypes.BaseAccount{Address: "foobar"} + + vmKeeper.On("GetEvmCoinInfo", mock.Anything).Return(tc.evmCoinInfo) + bankKeeper.On("GetDenomMetaData", mock.Anything, mock.Anything).Return( + banktypes.Metadata{DenomUnits: []*banktypes.DenomUnit{&tc.sdkDenom}}, true) + if !tc.expectedPanic { + bankKeeper.On("SendCoinsFromAccountToModuleVirtual", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.expectedErr) + } + + // Run DeductFees + var err error + if tc.expectedPanic { + require.Panics(t, func() { err = keeper.DeductFees(bankKeeper, vmKeeper, ctx, &acc, feeCoins) }) + } else { + err = keeper.DeductFees(bankKeeper, vmKeeper, ctx, &acc, feeCoins) + } + + // Validate Results + if tc.expectedErr != nil { + require.ErrorContains(t, err, tc.expectedErr.Error()) + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/x/vm/keeper/gas.go b/x/vm/keeper/gas.go index ab5dcf08..c6b8820e 100644 --- a/x/vm/keeper/gas.go +++ b/x/vm/keeper/gas.go @@ -5,7 +5,10 @@ import ( "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/params" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" + evmtrace "github.com/cosmos/evm/trace" "github.com/cosmos/evm/x/vm/types" errorsmod "cosmossdk.io/errors" @@ -16,10 +19,19 @@ import ( authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" ) +// ContextPaidFeesKey stores the coins actually charged for an EVM tx. +// Fee abstraction sets this so the refund uses that denom, capped by the amount paid. +type ContextPaidFeesKey struct{} + // GetEthIntrinsicGas returns the intrinsic gas cost for the transaction func (k *Keeper) GetEthIntrinsicGas(ctx sdk.Context, msg core.Message, cfg *params.ChainConfig, isContractCreation bool, -) (uint64, error) { +) (_ uint64, err error) { + ctx, span := ctx.StartSpan(tracer, "GetEthIntrinsicGas", trace.WithAttributes( + attribute.Bool("is_contract_creation", isContractCreation), + attribute.Int("data_size", len(msg.Data)), + )) + defer func() { evmtrace.EndSpanErr(span, err) }() height := big.NewInt(ctx.BlockHeight()) homestead := cfg.IsHomestead(height) istanbul := cfg.IsIstanbul(height) @@ -32,7 +44,15 @@ func (k *Keeper) GetEthIntrinsicGas(ctx sdk.Context, msg core.Message, cfg *para // consumed in the transaction. Additionally, the function sets the total gas consumed to the value // returned by the EVM execution, thus ignoring the previous intrinsic gas consumed during in the // AnteHandler. -func (k *Keeper) RefundGas(ctx sdk.Context, msg core.Message, leftoverGas uint64, denom string) error { +func (k *Keeper) RefundGas(ctx sdk.Context, msg core.Message, leftoverGas, gasUsed uint64, denom string) (err error) { + ctx, span := ctx.StartSpan(tracer, "RefundGas", trace.WithAttributes(attribute.Int64("leftover_gas", int64(leftoverGas)))) //nolint:gosec // G115 + defer func() { evmtrace.EndSpanErr(span, err) }() + + // No gas was consumed, so there is nothing to refund against. + if gasUsed == 0 { + return nil + } + // Return EVM tokens for remaining gas, exchanged at the original rate. remaining := new(big.Int).Mul(new(big.Int).SetUint64(leftoverGas), msg.GasPrice) @@ -41,11 +61,37 @@ func (k *Keeper) RefundGas(ctx sdk.Context, msg core.Message, leftoverGas uint64 // negative refund errors return errorsmod.Wrapf(types.ErrInvalidRefund, "refunded amount value cannot be negative %d", remaining.Int64()) case 1: + // Fee abstraction records the coin that was actually charged. + // Refund that coin, scaled by leftover gas over the tx gas limit, + // so the sender never receives more than was paid. + if val := ctx.Value(ContextPaidFeesKey{}); val != nil { + if paidCoins, ok := val.(sdk.Coins); ok && !paidCoins.IsZero() { + if len(paidCoins) != 1 { + return errorsmod.Wrapf(types.ErrInvalidRefund, "expected a single coin for EVM refunds, got %d", len(paidCoins)) + } + paidCoin := paidCoins[0] + denom = paidCoin.Denom + remaining = new(big.Int).Div( + new(big.Int).Mul(paidCoin.Amount.BigInt(), new(big.Int).SetUint64(leftoverGas)), + new(big.Int).SetUint64(msg.GasLimit), + ) + } + } + + if remaining.Sign() <= 0 { + return nil + } + // positive amount refund refundedCoins := sdk.Coins{sdk.NewCoin(denom, sdkmath.NewIntFromBigInt(remaining))} // refund to sender from the fee collector module account, which is the escrow account in charge of collecting tx fees - err := k.bankWrapper.SendCoinsFromModuleToAccount(ctx, authtypes.FeeCollectorName, msg.From.Bytes(), refundedCoins) + var err error + if k.virtualFeeCollection { + err = k.bankWrapper.SendCoinsFromModuleToAccountVirtual(ctx, authtypes.FeeCollectorName, msg.From.Bytes(), refundedCoins) + } else { + err = k.bankWrapper.SendCoinsFromModuleToAccount(ctx, authtypes.FeeCollectorName, msg.From.Bytes(), refundedCoins) + } if err != nil { err = errorsmod.Wrapf(errortypes.ErrInsufficientFunds, "fee collector account failed to refund fees: %s", err.Error()) return errorsmod.Wrapf(err, "failed to refund %d leftover gas (%s)", leftoverGas, refundedCoins.String()) @@ -61,6 +107,10 @@ func (k *Keeper) RefundGas(ctx sdk.Context, msg core.Message, leftoverGas uint64 // 'gasUsed' func (k *Keeper) ResetGasMeterAndConsumeGas(ctx sdk.Context, gasUsed uint64) { // reset the gas count + ctx, span := ctx.StartSpan(tracer, "ResetGasMeterAndConsumeGas", trace.WithAttributes( + attribute.Int64("gas_used", int64(gasUsed)), //nolint:gosec // G115 + )) + defer span.End() ctx.GasMeter().RefundGas(ctx.GasMeter().GasConsumed(), "reset the gas count") ctx.GasMeter().ConsumeGas(gasUsed, "apply evm transaction") } diff --git a/x/vm/keeper/grpc_query.go b/x/vm/keeper/grpc_query.go index 0e69e5ce..d8464d47 100644 --- a/x/vm/keeper/grpc_query.go +++ b/x/vm/keeper/grpc_query.go @@ -16,20 +16,23 @@ import ( "github.com/ethereum/go-ethereum/eth/tracers" "github.com/ethereum/go-ethereum/eth/tracers/logger" ethparams "github.com/ethereum/go-ethereum/params" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" tmproto "github.com/cometbft/cometbft/proto/tendermint/types" rpctypes "github.com/cosmos/evm/rpc/types" + evmtrace "github.com/cosmos/evm/trace" "github.com/cosmos/evm/utils" evmante "github.com/cosmos/evm/x/vm/ante" "github.com/cosmos/evm/x/vm/statedb" "github.com/cosmos/evm/x/vm/types" sdkmath "cosmossdk.io/math" - storetypes "cosmossdk.io/store/types" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -46,11 +49,15 @@ const ( // Account implements the Query/Account gRPC method. The method returns the // *spendable* balance of the account in 18 decimals representation. -func (k Keeper) Account(c context.Context, req *types.QueryAccountRequest) (*types.QueryAccountResponse, error) { +func (k Keeper) Account(c context.Context, req *types.QueryAccountRequest) (_ *types.QueryAccountResponse, err error) { if req == nil { return nil, status.Error(codes.InvalidArgument, "empty request") } + ctx := sdk.UnwrapSDKContext(c) + ctx, span := ctx.StartSpan(tracer, "Account", trace.WithAttributes(attribute.String("address", req.Address))) + defer func() { evmtrace.EndSpanErr(span, err) }() + if err := utils.ValidateAddress(req.Address); err != nil { return nil, status.Error( codes.InvalidArgument, err.Error(), @@ -59,7 +66,6 @@ func (k Keeper) Account(c context.Context, req *types.QueryAccountRequest) (*typ addr := common.HexToAddress(req.Address) - ctx := sdk.UnwrapSDKContext(c) acct := k.GetAccountOrEmpty(ctx, addr) return &types.QueryAccountResponse{ @@ -69,19 +75,21 @@ func (k Keeper) Account(c context.Context, req *types.QueryAccountRequest) (*typ }, nil } -func (k Keeper) CosmosAccount(c context.Context, req *types.QueryCosmosAccountRequest) (*types.QueryCosmosAccountResponse, error) { +func (k Keeper) CosmosAccount(c context.Context, req *types.QueryCosmosAccountRequest) (_ *types.QueryCosmosAccountResponse, err error) { if req == nil { return nil, status.Error(codes.InvalidArgument, "empty request") } + ctx := sdk.UnwrapSDKContext(c) + ctx, span := ctx.StartSpan(tracer, "CosmosAccount", trace.WithAttributes(attribute.String("address", req.Address))) + defer func() { evmtrace.EndSpanErr(span, err) }() + if err := utils.ValidateAddress(req.Address); err != nil { return nil, status.Error( codes.InvalidArgument, err.Error(), ) } - ctx := sdk.UnwrapSDKContext(c) - ethAddr := common.HexToAddress(req.Address) cosmosAddr := sdk.AccAddress(ethAddr.Bytes()) @@ -99,11 +107,15 @@ func (k Keeper) CosmosAccount(c context.Context, req *types.QueryCosmosAccountRe } // ValidatorAccount implements the Query/Balance gRPC method -func (k Keeper) ValidatorAccount(c context.Context, req *types.QueryValidatorAccountRequest) (*types.QueryValidatorAccountResponse, error) { +func (k Keeper) ValidatorAccount(c context.Context, req *types.QueryValidatorAccountRequest) (_ *types.QueryValidatorAccountResponse, err error) { if req == nil { return nil, status.Error(codes.InvalidArgument, "empty request") } + ctx := sdk.UnwrapSDKContext(c) + ctx, span := ctx.StartSpan(tracer, "ValidatorAccount", trace.WithAttributes(attribute.String("address", req.ConsAddress))) + defer func() { evmtrace.EndSpanErr(span, err) }() + consAddr, err := sdk.ConsAddressFromBech32(req.ConsAddress) if err != nil { return nil, status.Error( @@ -111,8 +123,6 @@ func (k Keeper) ValidatorAccount(c context.Context, req *types.QueryValidatorAcc ) } - ctx := sdk.UnwrapSDKContext(c) - validator, err := k.stakingKeeper.GetValidatorByConsAddr(ctx, consAddr) if err != nil { return nil, fmt.Errorf("error while getting validator %s. %w", consAddr.String(), err) @@ -139,11 +149,15 @@ func (k Keeper) ValidatorAccount(c context.Context, req *types.QueryValidatorAcc // Balance implements the Query/Balance gRPC method. The method returns the 18 // decimal representation of the account's *spendable* balance. -func (k Keeper) Balance(c context.Context, req *types.QueryBalanceRequest) (*types.QueryBalanceResponse, error) { +func (k Keeper) Balance(c context.Context, req *types.QueryBalanceRequest) (_ *types.QueryBalanceResponse, err error) { if req == nil { return nil, status.Error(codes.InvalidArgument, "empty request") } + ctx := sdk.UnwrapSDKContext(c) + ctx, span := ctx.StartSpan(tracer, "Balance", trace.WithAttributes(attribute.String("address", req.Address))) + defer func() { evmtrace.EndSpanErr(span, err) }() + if err := utils.ValidateAddress(req.Address); err != nil { return nil, status.Error( codes.InvalidArgument, @@ -151,21 +165,28 @@ func (k Keeper) Balance(c context.Context, req *types.QueryBalanceRequest) (*typ ) } - ctx := sdk.UnwrapSDKContext(c) - balanceInt := k.SpendableCoin(ctx, common.HexToAddress(req.Address)) + span.AddEvent("balance", trace.WithAttributes(attribute.String("balance", balanceInt.String()))) + return &types.QueryBalanceResponse{ Balance: balanceInt.String(), }, nil } // Storage implements the Query/Storage gRPC method -func (k Keeper) Storage(c context.Context, req *types.QueryStorageRequest) (*types.QueryStorageResponse, error) { +func (k Keeper) Storage(c context.Context, req *types.QueryStorageRequest) (_ *types.QueryStorageResponse, err error) { if req == nil { return nil, status.Error(codes.InvalidArgument, "empty request") } + ctx := sdk.UnwrapSDKContext(c) + ctx, span := ctx.StartSpan(tracer, "Storage", trace.WithAttributes( + attribute.String("address", req.Address), + attribute.String("key", req.Key), + )) + defer func() { evmtrace.EndSpanErr(span, err) }() + if err := utils.ValidateAddress(req.Address); err != nil { return nil, status.Error( codes.InvalidArgument, @@ -173,8 +194,6 @@ func (k Keeper) Storage(c context.Context, req *types.QueryStorageRequest) (*typ ) } - ctx := sdk.UnwrapSDKContext(c) - address := common.HexToAddress(req.Address) key := common.HexToHash(req.Key) @@ -187,11 +206,17 @@ func (k Keeper) Storage(c context.Context, req *types.QueryStorageRequest) (*typ } // Code implements the Query/Code gRPC method -func (k Keeper) Code(c context.Context, req *types.QueryCodeRequest) (*types.QueryCodeResponse, error) { +func (k Keeper) Code(c context.Context, req *types.QueryCodeRequest) (_ *types.QueryCodeResponse, err error) { if req == nil { return nil, status.Error(codes.InvalidArgument, "empty request") } + ctx := sdk.UnwrapSDKContext(c) + ctx, span := ctx.StartSpan(tracer, "Code", trace.WithAttributes( + attribute.String("address", req.Address), + )) + defer func() { evmtrace.EndSpanErr(span, err) }() + if err := utils.ValidateAddress(req.Address); err != nil { return nil, status.Error( codes.InvalidArgument, @@ -199,8 +224,6 @@ func (k Keeper) Code(c context.Context, req *types.QueryCodeRequest) (*types.Que ) } - ctx := sdk.UnwrapSDKContext(c) - address := common.HexToAddress(req.Address) acct := k.GetAccountWithoutBalance(ctx, address) @@ -215,8 +238,11 @@ func (k Keeper) Code(c context.Context, req *types.QueryCodeRequest) (*types.Que } // Params implements the Query/Params gRPC method -func (k Keeper) Params(c context.Context, _ *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { +func (k Keeper) Params(c context.Context, _ *types.QueryParamsRequest) (_ *types.QueryParamsResponse, err error) { ctx := sdk.UnwrapSDKContext(c) + ctx, span := ctx.StartSpan(tracer, "Params", trace.WithAttributes()) + defer func() { evmtrace.EndSpanErr(span, err) }() + params := k.GetParams(ctx) return &types.QueryParamsResponse{ @@ -225,11 +251,15 @@ func (k Keeper) Params(c context.Context, _ *types.QueryParamsRequest) (*types.Q } // EthCall implements eth_call rpc api. -func (k Keeper) EthCall(c context.Context, req *types.EthCallRequest) (*types.MsgEthereumTxResponse, error) { +func (k Keeper) EthCall(c context.Context, req *types.EthCallRequest) (_ *types.MsgEthereumTxResponse, err error) { if req == nil { return nil, status.Error(codes.InvalidArgument, "empty request") } + ctx := sdk.UnwrapSDKContext(c) + ctx, span := ctx.StartSpan(tracer, "EthCall", trace.WithAttributes(attribute.String("proposer", req.ProposerAddress.String()))) + defer func() { evmtrace.EndSpanErr(span, err) }() + var overrides *rpctypes.StateOverride if len(req.Overrides) > 0 { overrides = new(rpctypes.StateOverride) @@ -238,10 +268,8 @@ func (k Keeper) EthCall(c context.Context, req *types.EthCallRequest) (*types.Ms } } - ctx := sdk.UnwrapSDKContext(c) - var args types.TransactionArgs - err := json.Unmarshal(req.Args, &args) + err = json.Unmarshal(req.Args, &args) if err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) } @@ -263,7 +291,8 @@ func (k Keeper) EthCall(c context.Context, req *types.EthCallRequest) (*types.Ms txConfig := statedb.NewEmptyTxConfig() // pass false to not commit StateDB - res, err := k.ApplyMessageWithConfig(ctx, *msg, nil, false, cfg, txConfig, false, overrides) + stateDB := statedb.New(ctx, &k, txConfig) + res, err := k.ApplyMessageWithConfig(ctx, stateDB, *msg, nil, false, false, cfg, txConfig, false, overrides) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } @@ -272,7 +301,7 @@ func (k Keeper) EthCall(c context.Context, req *types.EthCallRequest) (*types.Ms } // EstimateGas implements eth_estimateGas rpc api. -func (k Keeper) EstimateGas(c context.Context, req *types.EthCallRequest) (*types.EstimateGasResponse, error) { +func (k Keeper) EstimateGas(c context.Context, req *types.EthCallRequest) (_ *types.EstimateGasResponse, err error) { return k.EstimateGasInternal(c, req, types.RPC) } @@ -281,19 +310,29 @@ func (k Keeper) EstimateGas(c context.Context, req *types.EthCallRequest) (*type // When called from the RPC client, we need to reset the gas meter before // simulating the transaction to have // an accurate gas estimation for EVM extensions transactions. -func (k Keeper) EstimateGasInternal(c context.Context, req *types.EthCallRequest, fromType types.CallType) (*types.EstimateGasResponse, error) { +func (k Keeper) EstimateGasInternal(c context.Context, req *types.EthCallRequest, fromType types.CallType) (_ *types.EstimateGasResponse, err error) { if req == nil { return nil, status.Error(codes.InvalidArgument, "empty request") } ctx := sdk.UnwrapSDKContext(c) + ctx, span := ctx.StartSpan(tracer, "EstimateGasInternal", trace.WithAttributes(attribute.String("proposer", req.ProposerAddress.String()))) + defer func() { evmtrace.EndSpanErr(span, err) }() + + var overrides *rpctypes.StateOverride + if len(req.Overrides) > 0 { + overrides = new(rpctypes.StateOverride) + if err := json.Unmarshal(req.Overrides, overrides); err != nil { + return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("invalid state overrides format: %s", err.Error())) + } + } if req.GasCap < ethparams.TxGas { return nil, status.Errorf(codes.InvalidArgument, "gas cap cannot be lower than %d", ethparams.TxGas) } var args types.TransactionArgs - err := json.Unmarshal(req.Args, &args) + err = json.Unmarshal(req.Args, &args) if err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) } @@ -312,7 +351,7 @@ func (k Keeper) EstimateGasInternal(c context.Context, req *types.EthCallRequest // Query block gas limit params := ctx.ConsensusParams() if params.Block != nil && params.Block.MaxGas > 0 { - hi = uint64(params.Block.MaxGas) //nolint:gosec // G115 // won't exceed uint64 + hi = uint64(params.Block.MaxGas) } else { hi = req.GasCap } @@ -403,7 +442,8 @@ func (k Keeper) EstimateGasInternal(c context.Context, req *types.EthCallRequest tmpCtx = buildTraceCtx(tmpCtx, msg.GasLimit) } // pass false to not commit StateDB - rsp, err = k.ApplyMessageWithConfig(tmpCtx, *msg, nil, false, cfg, txConfig, false, nil) + stateDB := statedb.New(tmpCtx, &k, txConfig) + rsp, err = k.ApplyMessageWithConfig(tmpCtx, stateDB, *msg, nil, false, false, cfg, txConfig, false, overrides) if err != nil { if errors.Is(err, core.ErrIntrinsicGas) || errors.Is(err, core.ErrFloorDataGas) { return true, nil, nil // Special case, raise gas limit @@ -482,11 +522,19 @@ func (k Keeper) EstimateGasInternal(c context.Context, req *types.EthCallRequest // TraceTx configures a new tracer according to the provided configuration, and // executes the given message in the provided environment. The return value will // be tracer-dependent. -func (k Keeper) TraceTx(c context.Context, req *types.QueryTraceTxRequest) (*types.QueryTraceTxResponse, error) { +func (k Keeper) TraceTx(c context.Context, req *types.QueryTraceTxRequest) (_ *types.QueryTraceTxResponse, err error) { if req == nil || req.Msg == nil { return nil, status.Error(codes.InvalidArgument, "empty request") } + ctx := sdk.UnwrapSDKContext(c) + ctx, span := ctx.StartSpan(tracer, "TraceTx", trace.WithAttributes( + attribute.Int64("block_number", req.BlockNumber), + attribute.String("block_hash", req.BlockHash), + attribute.Int("predecessor_count", len(req.Predecessors)), + )) + defer func() { evmtrace.EndSpanErr(span, err) }() + if req.TraceConfig != nil && req.TraceConfig.Limit < 0 { return nil, status.Errorf(codes.InvalidArgument, "output limit cannot be negative, got %d", req.TraceConfig.Limit) } @@ -503,7 +551,6 @@ func (k Keeper) TraceTx(c context.Context, req *types.QueryTraceTxRequest) (*typ requestedHeight = 1 } - ctx := sdk.UnwrapSDKContext(c) // the caller sets the `ctx.BlockHeight()` to be `requestedHeight - 1`, so we can get the context of block beginning if requestedHeight > ctx.BlockHeight()+1 { return nil, status.Errorf(codes.FailedPrecondition, "requested height [%d] must be less than or equal to current height [%d]", requestedHeight, ctx.BlockHeight()) @@ -550,15 +597,15 @@ func (k Keeper) TraceTx(c context.Context, req *types.QueryTraceTxRequest) (*typ } msg.GasLimit = min(msg.GasLimit, maxPredecessorGas) txConfig.TxHash = ethTx.Hash() - txConfig.TxIndex = uint(i) //nolint:gosec // G115 // won't exceed uint64 + txConfig.TxIndex = uint(i) ctx = buildTraceCtx(ctx, msg.GasLimit) // we ignore the error here. this endpoint, ideally, is called internally from the ETH backend, which will call this query // using all previous txs in the trace transaction's block. some of those _could_ be invalid transactions. - rsp, _ := k.ApplyMessageWithConfig(ctx, *msg, nil, true, cfg, txConfig, false, nil) + stateDB := statedb.New(ctx, &k, txConfig) + rsp, _ := k.ApplyMessageWithConfig(ctx, stateDB, *msg, nil, true, false, cfg, txConfig, false, nil) if rsp != nil { ctx.GasMeter().ConsumeGas(rsp.GasUsed, "evm predecessor tx") - txConfig.LogIndex += uint(len(rsp.Logs)) } } @@ -568,7 +615,7 @@ func (k Keeper) TraceTx(c context.Context, req *types.QueryTraceTxRequest) (*typ txConfig.TxIndex++ } - result, _, err := k.traceTx(ctx, cfg, txConfig, signer, tx, req.TraceConfig, false) + result, err := k.traceTx(ctx, cfg, txConfig, signer, tx, req.TraceConfig, false) if err != nil { // error will be returned with detail status from traceTx return nil, err @@ -587,11 +634,19 @@ func (k Keeper) TraceTx(c context.Context, req *types.QueryTraceTxRequest) (*typ // TraceBlock configures a new tracer according to the provided configuration, and // executes the given message in the provided environment for all the transactions in the queried block. // The return value will be tracer dependent. -func (k Keeper) TraceBlock(c context.Context, req *types.QueryTraceBlockRequest) (*types.QueryTraceBlockResponse, error) { +func (k Keeper) TraceBlock(c context.Context, req *types.QueryTraceBlockRequest) (_ *types.QueryTraceBlockResponse, err error) { if req == nil { return nil, status.Error(codes.InvalidArgument, "empty request") } + ctx := sdk.UnwrapSDKContext(c) + ctx, span := ctx.StartSpan(tracer, "TraceBlock", trace.WithAttributes( + attribute.Int64("block_number", req.BlockNumber), + attribute.String("block_hash", req.BlockHash), + attribute.Int("tx_count", len(req.Txs)), + )) + defer func() { evmtrace.EndSpanErr(span, err) }() + if req.TraceConfig != nil && req.TraceConfig.Limit < 0 { return nil, status.Errorf(codes.InvalidArgument, "output limit cannot be negative, got %d", req.TraceConfig.Limit) } @@ -604,7 +659,6 @@ func (k Keeper) TraceBlock(c context.Context, req *types.QueryTraceBlockRequest) contextHeight = 1 } - ctx := sdk.UnwrapSDKContext(c) ctx = ctx.WithBlockHeight(contextHeight) ctx = ctx.WithBlockTime(req.BlockTime) ctx = ctx.WithHeaderHash(common.Hex2Bytes(req.BlockHash)) @@ -635,12 +689,11 @@ func (k Keeper) TraceBlock(c context.Context, req *types.QueryTraceBlockRequest) result := types.TxTraceResult{} ethTx := tx.AsTransaction() txConfig.TxHash = ethTx.Hash() - txConfig.TxIndex = uint(i) //nolint:gosec // G115 // won't exceed uint64 - traceResult, logIndex, err := k.traceTx(ctx, cfg, txConfig, signer, ethTx, req.TraceConfig, true) + txConfig.TxIndex = uint(i) + traceResult, err := k.traceTx(ctx, cfg, txConfig, signer, ethTx, req.TraceConfig, true) if err != nil { result.Error = err.Error() } else { - txConfig.LogIndex = logIndex result.Result = traceResult } results = append(results, &result) @@ -659,11 +712,18 @@ func (k Keeper) TraceBlock(c context.Context, req *types.QueryTraceBlockRequest) // TraceCall configures a new tracer according to the provided configuration, and // executes the given call in the provided environment. The return value will // be tracer dependent. -func (k Keeper) TraceCall(c context.Context, req *types.QueryTraceCallRequest) (*types.QueryTraceCallResponse, error) { +func (k Keeper) TraceCall(c context.Context, req *types.QueryTraceCallRequest) (_ *types.QueryTraceCallResponse, err error) { if req == nil || req.Args == nil { return nil, status.Error(codes.InvalidArgument, "empty request") } + ctx := sdk.UnwrapSDKContext(c) + ctx, span := ctx.StartSpan(tracer, "TraceCall", trace.WithAttributes( + attribute.Int64("block_number", req.BlockNumber), + attribute.String("block_hash", req.BlockHash), + )) + defer func() { evmtrace.EndSpanErr(span, err) }() + if req.TraceConfig != nil && req.TraceConfig.Limit < 0 { return nil, status.Errorf(codes.InvalidArgument, "output limit cannot be negative, got %d", req.TraceConfig.Limit) } @@ -676,7 +736,6 @@ func (k Keeper) TraceCall(c context.Context, req *types.QueryTraceCallRequest) ( requestedHeight = 1 } - ctx := sdk.UnwrapSDKContext(c) // the caller sets the `ctx.BlockHeight()` to be `requestedHeight - 1`, so we can get the context of block beginning if requestedHeight > ctx.BlockHeight()+1 { return nil, status.Errorf(codes.FailedPrecondition, "requested height [%d] must be less than or equal to current height [%d]", requestedHeight, ctx.BlockHeight()) @@ -715,7 +774,7 @@ func (k Keeper) TraceCall(c context.Context, req *types.QueryTraceCallRequest) ( msg := args.ToMessage(baseFee, true, true) // trace call - result, _, err := k.traceTxWithMsg(ctx, cfg, txConfig, msg, req.GetTraceConfig(), false) + result, err := k.traceTxWithMsg(ctx, cfg, txConfig, msg, req.GetTraceConfig(), false) if err != nil { // error will be returned with detail status from traceTx return nil, err @@ -731,7 +790,7 @@ func (k Keeper) TraceCall(c context.Context, req *types.QueryTraceCallRequest) ( }, nil } -// traceTx do trace on one transaction, it returns a tuple: (traceResult, nextLogIndex, error). +// traceTx do trace on one transaction, it returns a tuple: (traceResult, error). func (k *Keeper) traceTx( ctx sdk.Context, cfg *statedb.EVMConfig, @@ -740,16 +799,20 @@ func (k *Keeper) traceTx( tx *ethtypes.Transaction, traceConfig *types.TraceConfig, commitMessage bool, -) (*any, uint, error) { +) (_ *any, err error) { + ctx, span := ctx.StartSpan(tracer, "traceTx", trace.WithAttributes( + attribute.String("tx_hash", tx.Hash().Hex()), + )) + defer func() { evmtrace.EndSpanErr(span, err) }() msg, err := core.TransactionToMessage(tx, signer, cfg.BaseFee) if err != nil { - return nil, 0, status.Error(codes.Internal, err.Error()) + return nil, status.Error(codes.Internal, err.Error()) } return k.traceTxWithMsg(ctx, cfg, txConfig, msg, traceConfig, commitMessage) } -// traceTxWithMsg do trace on one Ethereum message, it returns a tuple: (traceResult, nextLogIndex, error). +// traceTxWithMsg do trace on one Ethereum message, it returns a tuple: (traceResult, error). func (k *Keeper) traceTxWithMsg( ctx sdk.Context, cfg *statedb.EVMConfig, @@ -757,13 +820,18 @@ func (k *Keeper) traceTxWithMsg( msg *core.Message, traceConfig *types.TraceConfig, commitMessage bool, -) (*interface{}, uint, error) { +) (_ *any, err error) { + ctx, span := ctx.StartSpan(tracer, "traceTxWithMsg", trace.WithAttributes( + attribute.String("tx_hash", txConfig.TxHash.Hex()), + attribute.Int("tx_index", int(txConfig.TxIndex)), //nolint:gosec // G115 + attribute.String("from", msg.From.Hex()), + )) + defer func() { evmtrace.EndSpanErr(span, err) }() // Assemble the structured logger or the JavaScript tracer var ( tracer *tracers.Tracer overrides *ethparams.ChainConfig jsonTracerConfig json.RawMessage - err error timeout = defaultTraceTimeout ) @@ -809,14 +877,14 @@ func (k *Keeper) traceTxWithMsg( } if tracer, err = tracers.DefaultDirectory.New(traceConfig.Tracer, tCtx, cfg, types.GetEthChainConfig()); err != nil { - return nil, 0, status.Error(codes.Internal, err.Error()) + return nil, status.Error(codes.Internal, err.Error()) } } // Define a meaningful timeout of a single transaction trace if traceConfig.Timeout != "" { if timeout, err = time.ParseDuration(traceConfig.Timeout); err != nil { - return nil, 0, status.Errorf(codes.InvalidArgument, "timeout value: %s", err.Error()) + return nil, status.Errorf(codes.InvalidArgument, "timeout value: %s", err.Error()) } } @@ -833,23 +901,26 @@ func (k *Keeper) traceTxWithMsg( // Build EVM execution context ctx = buildTraceCtx(ctx, msg.GasLimit) - res, err := k.ApplyMessageWithConfig(ctx, *msg, tracer.Hooks, commitMessage, cfg, txConfig, false, nil) + stateDB := statedb.New(ctx, k, txConfig) + _, err = k.ApplyMessageWithConfig(ctx, stateDB, *msg, tracer.Hooks, commitMessage, false, cfg, txConfig, false, nil) if err != nil { - return nil, 0, status.Error(codes.Internal, err.Error()) + return nil, status.Error(codes.Internal, err.Error()) } var result interface{} result, err = tracer.GetResult() if err != nil { - return nil, 0, status.Error(codes.Internal, err.Error()) + return nil, status.Error(codes.Internal, err.Error()) } - return &result, txConfig.LogIndex + uint(len(res.Logs)), nil + return &result, nil } // BaseFee implements the Query/BaseFee gRPC method func (k Keeper) BaseFee(c context.Context, _ *types.QueryBaseFeeRequest) (*types.QueryBaseFeeResponse, error) { ctx := sdk.UnwrapSDKContext(c) + ctx, span := ctx.StartSpan(tracer, "BaseFee") + defer span.End() baseFee := k.GetBaseFee(ctx) @@ -865,12 +936,16 @@ func (k Keeper) BaseFee(c context.Context, _ *types.QueryBaseFeeRequest) (*types // GlobalMinGasPrice implements the Query/GlobalMinGasPrice gRPC method func (k Keeper) GlobalMinGasPrice(c context.Context, _ *types.QueryGlobalMinGasPriceRequest) (*types.QueryGlobalMinGasPriceResponse, error) { ctx := sdk.UnwrapSDKContext(c) + ctx, span := ctx.StartSpan(tracer, "GlobalMinGasPrice") + defer span.End() minGasPrice := k.GetMinGasPrice(ctx).TruncateInt() return &types.QueryGlobalMinGasPriceResponse{MinGasPrice: minGasPrice}, nil } // Config implements the Query/Config gRPC method -func (k Keeper) Config(_ context.Context, _ *types.QueryConfigRequest) (*types.QueryConfigResponse, error) { +func (k Keeper) Config(ctx context.Context, _ *types.QueryConfigRequest) (*types.QueryConfigResponse, error) { + _, span := tracer.Start(ctx, "Config") + defer span.End() config := types.GetChainConfig() config.Denom = types.GetEVMCoinDenom() config.Decimals = uint64(types.GetEVMCoinDecimals()) diff --git a/x/vm/keeper/hooks.go b/x/vm/keeper/hooks.go index 12be8907..a1dccb28 100644 --- a/x/vm/keeper/hooks.go +++ b/x/vm/keeper/hooks.go @@ -4,7 +4,10 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" ethtypes "github.com/ethereum/go-ethereum/core/types" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" + evmtrace "github.com/cosmos/evm/trace" "github.com/cosmos/evm/x/vm/types" errorsmod "cosmossdk.io/errors" @@ -26,7 +29,13 @@ func NewMultiEvmHooks(hooks ...types.EvmHooks) MultiEvmHooks { } // PostTxProcessing delegate the call to underlying hooks -func (mh MultiEvmHooks) PostTxProcessing(ctx sdk.Context, sender common.Address, msg core.Message, receipt *ethtypes.Receipt) error { +func (mh MultiEvmHooks) PostTxProcessing(ctx sdk.Context, sender common.Address, msg core.Message, receipt *ethtypes.Receipt) (err error) { + ctx, span := ctx.StartSpan(tracer, "MultiEVMHooks.PostTxProcessing", trace.WithAttributes( + attribute.String("sender", sender.Hex()), + attribute.String("tx_hash", receipt.TxHash.Hex()), + attribute.Int("hooks_count", len(mh)), + )) + defer func() { evmtrace.EndSpanErr(span, err) }() for i := range mh { if err := mh[i].PostTxProcessing(ctx, sender, msg, receipt); err != nil { return errorsmod.Wrapf(err, "EVM hook %T failed", mh[i]) diff --git a/x/vm/keeper/keeper.go b/x/vm/keeper/keeper.go index 4a75eab9..6b7b9564 100644 --- a/x/vm/keeper/keeper.go +++ b/x/vm/keeper/keeper.go @@ -11,23 +11,28 @@ import ( "github.com/ethereum/go-ethereum/core/vm" ethparams "github.com/ethereum/go-ethereum/params" "github.com/holiman/uint256" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" - evmmempool "github.com/cosmos/evm/mempool" + evmtrace "github.com/cosmos/evm/trace" "github.com/cosmos/evm/utils" "github.com/cosmos/evm/x/vm/statedb" "github.com/cosmos/evm/x/vm/types" "github.com/cosmos/evm/x/vm/wrappers" errorsmod "cosmossdk.io/errors" - "cosmossdk.io/log" + "cosmossdk.io/log/v2" "cosmossdk.io/math" - "cosmossdk.io/store/prefix" - storetypes "cosmossdk.io/store/types" "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store/v2/prefix" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" ) +var tracer = otel.Tracer("evm/x/vm/keeper") + // Keeper grants access to the EVM module state and implements the go-ethereum StateDB interface. type Keeper struct { // Protobuf codec @@ -39,11 +44,11 @@ type Keeper struct { // - storing Bloom filters by block height. Needed for the Web3 API. storeKey storetypes.StoreKey - // key to access the transient store, which is reset on every block during Commit - transientKey storetypes.StoreKey + // key to access the object store, which is reset on every block during Commit + objectKey storetypes.StoreKey - // KVStore Keys for modules wired to app - storeKeys map[string]*storetypes.KVStoreKey + // Store Keys for modules wired to app + storeKeys map[string]storetypes.StoreKey // the address capable of executing a MsgUpdateParams message. Typically, this should be the x/gov module account. authority sdk.AccAddress @@ -78,16 +83,16 @@ type Keeper struct { // parameters. precompiles map[common.Address]vm.PrecompiledContract - // evmMempool is the custom EVM appside mempool - // if it is nil, the default comet mempool will be used - evmMempool *evmmempool.ExperimentalEVMMempool + // virtualFeeCollection enabling will use "Virtual" methods from the bank module to accumulate + // fees to the fee collector module in the endBlocker instead of using regular sends during tx execution. + virtualFeeCollection bool } // NewKeeper generates new evm module keeper func NewKeeper( cdc codec.BinaryCodec, - storeKey, transientKey storetypes.StoreKey, - keys map[string]*storetypes.KVStoreKey, + storeKey, objectKey storetypes.StoreKey, + keys []storetypes.StoreKey, authority sdk.AccAddress, ak types.AccountKeeper, bankKeeper types.BankKeeper, @@ -110,6 +115,10 @@ func NewKeeper( bankWrapper := wrappers.NewBankWrapper(bankKeeper) feeMarketWrapper := wrappers.NewFeeMarketWrapper(fmk) + storeKeys := make(map[string]storetypes.StoreKey) + for _, k := range keys { + storeKeys[k.Name()] = k + } // set global chain config ethCfg := types.DefaultChainConfig(evmChainID) @@ -126,14 +135,21 @@ func NewKeeper( stakingKeeper: sk, feeMarketWrapper: feeMarketWrapper, storeKey: storeKey, - transientKey: transientKey, + objectKey: objectKey, tracer: tracer, consensusKeeper: consensusKeeper, erc20Keeper: erc20Keeper, - storeKeys: keys, + storeKeys: storeKeys, } } +// EnableVirtualFeeCollection switches fee deduction for evm transactions to use the virtual fee collection of the +// bank keeper via the object store. +// Note: Do NOT use this if your chain does not have an 18 decimal point precision gas token. +func (k *Keeper) EnableVirtualFeeCollection() { + k.virtualFeeCollection = true +} + // Logger returns a module-specific logger. func (k Keeper) Logger(ctx sdk.Context) log.Logger { return ctx.Logger().With("module", types.ModuleName) @@ -145,11 +161,11 @@ func (k Keeper) Logger(ctx sdk.Context) log.Logger { // ---------------------------------------------------------------------------- // EmitBlockBloomEvent emit block bloom events -func (k Keeper) EmitBlockBloomEvent(ctx sdk.Context, bloom ethtypes.Bloom) { +func (k Keeper) EmitBlockBloomEvent(ctx sdk.Context, bloom []byte) { ctx.EventManager().EmitEvent( sdk.NewEvent( types.EventTypeBlockBloom, - sdk.NewAttribute(types.AttributeKeyEthereumBloom, string(bloom.Bytes())), + sdk.NewAttribute(types.AttributeKeyEthereumBloom, string(bloom)), ), ) } @@ -159,40 +175,35 @@ func (k Keeper) GetAuthority() sdk.AccAddress { return k.authority } -// GetBlockBloomTransient returns bloom bytes for the current block height -func (k Keeper) GetBlockBloomTransient(ctx sdk.Context) *big.Int { - store := prefix.NewStore(ctx.TransientStore(k.transientKey), types.KeyPrefixTransientBloom) - heightBz := sdk.Uint64ToBigEndian(uint64(ctx.BlockHeight())) //nolint:gosec // G115 // won't exceed uint64 - bz := store.Get(heightBz) - if len(bz) == 0 { - return big.NewInt(0) +// CollectTxBloom collects all tx blooms and emit a single block bloom event +func (k Keeper) CollectTxBloom(ctx sdk.Context) { + ctx, span := ctx.StartSpan(tracer, "CollectTxBloom", trace.WithAttributes( + attribute.Int64("block_height", ctx.BlockHeight()), + )) + defer span.End() + store := prefix.NewObjStore(ctx.ObjectStore(k.objectKey), types.KeyPrefixObjectBloom) + it := store.Iterator(nil, nil) + defer it.Close() + + bloom := new(big.Int) + for ; it.Valid(); it.Next() { + bloom.Or(bloom, it.Value().(*big.Int)) + store.Delete(it.Key()) } - return new(big.Int).SetBytes(bz) + k.EmitBlockBloomEvent(ctx, bloom.Bytes()) } -// SetBlockBloomTransient sets the given bloom bytes to the transient store. This value is reset on +// SetTxBloom sets the given bloom bytes to the object store. This value is reset on // every block. -func (k Keeper) SetBlockBloomTransient(ctx sdk.Context, bloom *big.Int) { - store := prefix.NewStore(ctx.TransientStore(k.transientKey), types.KeyPrefixTransientBloom) - heightBz := sdk.Uint64ToBigEndian(uint64(ctx.BlockHeight())) //nolint:gosec // G115 // won't exceed uint64 - store.Set(heightBz, bloom.Bytes()) -} - -// ---------------------------------------------------------------------------- -// Tx -// ---------------------------------------------------------------------------- - -// SetTxIndexTransient set the index of processing transaction -func (k Keeper) SetTxIndexTransient(ctx sdk.Context, index uint64) { - store := ctx.TransientStore(k.transientKey) - store.Set(types.KeyPrefixTransientTxIndex, sdk.Uint64ToBigEndian(index)) -} - -// GetTxIndexTransient returns EVM transaction index on the current block. -func (k Keeper) GetTxIndexTransient(ctx sdk.Context) uint64 { - store := ctx.TransientStore(k.transientKey) - return sdk.BigEndianToUint64(store.Get(types.KeyPrefixTransientTxIndex)) +func (k Keeper) SetTxBloom(ctx sdk.Context, bloom *big.Int) { + ctx, span := ctx.StartSpan(tracer, "SetTxBloom", trace.WithAttributes( + attribute.Int("tx_index", ctx.TxIndex()), + attribute.Int("msg_index", ctx.MsgIndex()), + )) + defer span.End() + store := ctx.ObjectStore(k.objectKey) + store.Set(types.ObjectBloomKey(ctx.TxIndex(), ctx.MsgIndex()), bloom) } // ---------------------------------------------------------------------------- @@ -217,7 +228,12 @@ func (k *Keeper) PostTxProcessing( sender common.Address, msg core.Message, receipt *ethtypes.Receipt, -) error { +) (err error) { + ctx, span := ctx.StartSpan(tracer, "PostTxProcessing", trace.WithAttributes( + attribute.String("sender", sender.Hex()), + attribute.String("tx_hash", receipt.TxHash.Hex()), + )) + defer func() { evmtrace.EndSpanErr(span, err) }() if k.hooks == nil { return nil } @@ -229,29 +245,14 @@ func (k *Keeper) HasHooks() bool { return k.hooks != nil } -// ---------------------------------------------------------------------------- -// Log -// ---------------------------------------------------------------------------- - -// GetLogSizeTransient returns EVM log index on the current block. -func (k Keeper) GetLogSizeTransient(ctx sdk.Context) uint64 { - store := ctx.TransientStore(k.transientKey) - return sdk.BigEndianToUint64(store.Get(types.KeyPrefixTransientLogSize)) -} - -// SetLogSizeTransient fetches the current EVM log index from the transient store, increases its -// value by one and then sets the new index back to the transient store. -func (k Keeper) SetLogSizeTransient(ctx sdk.Context, logSize uint64) { - store := ctx.TransientStore(k.transientKey) - store.Set(types.KeyPrefixTransientLogSize, sdk.Uint64ToBigEndian(logSize)) -} - // ---------------------------------------------------------------------------- // Storage // ---------------------------------------------------------------------------- // GetAccountStorage return state storage associated with an account func (k Keeper) GetAccountStorage(ctx sdk.Context, address common.Address) types.Storage { + ctx, span := ctx.StartSpan(tracer, "GetAccountStorage", trace.WithAttributes(attribute.String("address", address.Hex()))) + defer span.End() storage := types.Storage{} k.ForEachStorage(ctx, address, func(key, value common.Hash) bool { @@ -274,6 +275,8 @@ func (k Keeper) Tracer(ctx sdk.Context, msg core.Message, ethCfg *ethparams.Chai // GetAccountWithoutBalance load nonce and codehash without balance, // more efficient in cases where balance is not needed. func (k *Keeper) GetAccountWithoutBalance(ctx sdk.Context, addr common.Address) *statedb.Account { + ctx, span := ctx.StartSpan(tracer, "GetAccountWithoutBalance", trace.WithAttributes(attribute.String("address", addr.Hex()))) + defer span.End() cosmosAddr := sdk.AccAddress(addr.Bytes()) acct := k.accountKeeper.GetAccount(ctx, cosmosAddr) if acct == nil { @@ -290,6 +293,8 @@ func (k *Keeper) GetAccountWithoutBalance(ctx sdk.Context, addr common.Address) // GetAccountOrEmpty returns empty account if not exist. func (k *Keeper) GetAccountOrEmpty(ctx sdk.Context, addr common.Address) statedb.Account { + ctx, span := ctx.StartSpan(tracer, "GetAccountOrEmpty", trace.WithAttributes(attribute.String("address", addr.Hex()))) + defer span.End() acct := k.GetAccount(ctx, addr) if acct != nil { return *acct @@ -304,6 +309,8 @@ func (k *Keeper) GetAccountOrEmpty(ctx sdk.Context, addr common.Address) statedb // GetNonce returns the sequence number of an account, returns 0 if not exists. func (k *Keeper) GetNonce(ctx sdk.Context, addr common.Address) uint64 { + ctx, span := ctx.StartSpan(tracer, "GetNonce", trace.WithAttributes(attribute.String("address", addr.Hex()))) + defer span.End() cosmosAddr := sdk.AccAddress(addr.Bytes()) acct := k.accountKeeper.GetAccount(ctx, cosmosAddr) if acct == nil { @@ -315,6 +322,8 @@ func (k *Keeper) GetNonce(ctx sdk.Context, addr common.Address) uint64 { // SpendableCoin load account's balance of gas token. func (k *Keeper) SpendableCoin(ctx sdk.Context, addr common.Address) *uint256.Int { + ctx, span := ctx.StartSpan(tracer, "SpendableCoin", trace.WithAttributes(attribute.String("address", addr.Hex()))) + defer span.End() cosmosAddr := sdk.AccAddress(addr.Bytes()) // Get the balance via bank wrapper to convert it to 18 decimals if needed. @@ -328,8 +337,22 @@ func (k *Keeper) SpendableCoin(ctx sdk.Context, addr common.Address) *uint256.In return result } +// lockedCoin loads account's locked balance of the gas token. +func (k *Keeper) lockedCoin(ctx sdk.Context, addr common.Address) *big.Int { + ctx, span := ctx.StartSpan(tracer, "LockedCoin", trace.WithAttributes(attribute.String("address", addr.Hex()))) + defer span.End() + cosmosAddr := sdk.AccAddress(addr.Bytes()) + + lockedCoins := k.bankWrapper.LockedCoins(ctx, cosmosAddr) + lockedGasCoin := lockedCoins.AmountOf(types.GetEVMCoinDenom()) + + return lockedGasCoin.BigInt() +} + // GetBalance load account's balance of gas token. func (k *Keeper) GetBalance(ctx sdk.Context, addr common.Address) *uint256.Int { + ctx, span := ctx.StartSpan(tracer, "GetBalance", trace.WithAttributes(attribute.String("address", addr.Hex()))) + defer span.End() cosmosAddr := sdk.AccAddress(addr.Bytes()) // Get the balance via bank wrapper to convert it to 18 decimals if needed. @@ -348,6 +371,8 @@ func (k *Keeper) GetBalance(ctx sdk.Context, addr common.Address) *uint256.Int { // - `0`: london hardfork enabled but feemarket is not enabled. // - `n`: both london hardfork and feemarket are enabled. func (k Keeper) GetBaseFee(ctx sdk.Context) *big.Int { + ctx, span := ctx.StartSpan(tracer, "GetBaseFee", trace.WithAttributes(attribute.Int64("block_height", ctx.BlockHeight()))) + defer span.End() ethCfg := types.GetEthChainConfig() if !types.IsLondon(ethCfg, ctx.BlockHeight()) { return nil @@ -367,23 +392,20 @@ func (k Keeper) GetMinGasPrice(ctx sdk.Context) math.LegacyDec { return k.feeMarketWrapper.GetParams(ctx).MinGasPrice } -// ResetTransientGasUsed reset gas used to prepare for execution of current cosmos tx, called in ante handler. -func (k Keeper) ResetTransientGasUsed(ctx sdk.Context) { - store := ctx.TransientStore(k.transientKey) - store.Delete(types.KeyPrefixTransientGasUsed) -} - // GetTransientGasUsed returns the gas used by current cosmos tx. func (k Keeper) GetTransientGasUsed(ctx sdk.Context) uint64 { - store := ctx.TransientStore(k.transientKey) - return sdk.BigEndianToUint64(store.Get(types.KeyPrefixTransientGasUsed)) + store := ctx.ObjectStore(k.objectKey) + v := store.Get(types.ObjectGasUsedKey(ctx.TxIndex())) + if v == nil { + return 0 + } + return v.(uint64) } // SetTransientGasUsed sets the gas used by current cosmos tx. func (k Keeper) SetTransientGasUsed(ctx sdk.Context, gasUsed uint64) { - store := ctx.TransientStore(k.transientKey) - bz := sdk.Uint64ToBigEndian(gasUsed) - store.Set(types.KeyPrefixTransientGasUsed, bz) + store := ctx.ObjectStore(k.objectKey) + store.Set(types.ObjectGasUsedKey(ctx.TxIndex()), gasUsed) } // AddTransientGasUsed accumulate gas used by each eth msgs included in current cosmos tx. @@ -397,22 +419,16 @@ func (k Keeper) AddTransientGasUsed(ctx sdk.Context, gasUsed uint64) (uint64, er } // KVStoreKeys returns KVStore keys injected to keeper -func (k Keeper) KVStoreKeys() map[string]*storetypes.KVStoreKey { +func (k Keeper) KVStoreKeys() map[string]storetypes.StoreKey { return k.storeKeys } -// SetEvmMempool sets the evm mempool -func (k *Keeper) SetEvmMempool(evmMempool *evmmempool.ExperimentalEVMMempool) { - k.evmMempool = evmMempool -} - -// GetEvmMempool returns the evm mempool -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) { + ctx, span := ctx.StartSpan(tracer, "SetHeaderHash", trace.WithAttributes( + attribute.Int64("block_height", ctx.BlockHeight()), + )) + defer span.End() window := uint64(types.DefaultHistoryServeWindow) params := k.GetParams(ctx) if params.HistoryServeWindow > 0 { @@ -431,6 +447,10 @@ func (k Keeper) SetHeaderHash(ctx sdk.Context) { // GetHeaderHash sets block hash into EIP-2935 compatible storage contract. func (k Keeper) GetHeaderHash(ctx sdk.Context, height uint64) common.Hash { + ctx, span := ctx.StartSpan(tracer, "GetHeaderHash", trace.WithAttributes( + attribute.Int64("height", int64(height)), //nolint:gosec // G115 + )) + defer span.End() window := uint64(types.DefaultHistoryServeWindow) params := k.GetParams(ctx) if params.HistoryServeWindow > 0 { diff --git a/x/vm/keeper/keeper_test.go b/x/vm/keeper/keeper_test.go index a2117754..c2ec9060 100644 --- a/x/vm/keeper/keeper_test.go +++ b/x/vm/keeper/keeper_test.go @@ -9,33 +9,16 @@ import ( cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" cmttime "github.com/cometbft/cometbft/types/time" - "github.com/cosmos/evm/config" - erc20types "github.com/cosmos/evm/x/erc20/types" - feemarkettypes "github.com/cosmos/evm/x/feemarket/types" - precisebanktypes "github.com/cosmos/evm/x/precisebank/types" + "github.com/cosmos/evm/testutil/constants" vmkeeper "github.com/cosmos/evm/x/vm/keeper" vmtypes "github.com/cosmos/evm/x/vm/types" "github.com/cosmos/evm/x/vm/types/mocks" - ibctransfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - ibcexported "github.com/cosmos/ibc-go/v10/modules/core/exported" - - storetypes "cosmossdk.io/store/types" - evidencetypes "cosmossdk.io/x/evidence/types" - "cosmossdk.io/x/feegrant" - upgradetypes "cosmossdk.io/x/upgrade/types" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" "github.com/cosmos/cosmos-sdk/testutil" sdk "github.com/cosmos/cosmos-sdk/types" moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - consensusparamtypes "github.com/cosmos/cosmos-sdk/x/consensus/types" - 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" - slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) type KeeperTestSuite struct { @@ -56,19 +39,11 @@ func TestKeeperTestSuite(t *testing.T) { } func (suite *KeeperTestSuite) SetupTest() { - keys := storetypes.NewKVStoreKeys( - authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, - minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey, - govtypes.StoreKey, consensusparamtypes.StoreKey, - upgradetypes.StoreKey, feegrant.StoreKey, evidencetypes.StoreKey, authzkeeper.StoreKey, - // ibc keys - ibcexported.StoreKey, ibctransfertypes.StoreKey, - // Cosmos EVM store keys - vmtypes.StoreKey, feemarkettypes.StoreKey, erc20types.StoreKey, precisebanktypes.StoreKey, - ) key := storetypes.NewKVStoreKey(vmtypes.StoreKey) - transientKey := storetypes.NewTransientStoreKey(vmtypes.TransientKey) - testCtx := testutil.DefaultContextWithDB(suite.T(), key, storetypes.NewTransientStoreKey("transient_test")) + oKey := storetypes.NewObjectStoreKey(vmtypes.ObjectKey) + allKeys := []storetypes.StoreKey{key, oKey} + testCtx := testutil.DefaultContextWithObjectStore(suite.T(), key, + storetypes.NewTransientStoreKey("store_test"), oKey) ctx := testCtx.Ctx.WithBlockHeader(cmtproto.Header{Time: cmttime.Now()}) encCfg := moduletestutil.MakeTestEncodingConfig() @@ -87,8 +62,8 @@ func (suite *KeeperTestSuite) SetupTest() { suite.vmKeeper = vmkeeper.NewKeeper( encCfg.Codec, key, - transientKey, - keys, + oKey, + allKeys, authority, suite.accKeeper, suite.bankKeeper, @@ -96,7 +71,7 @@ func (suite *KeeperTestSuite) SetupTest() { suite.fmKeeper, suite.consensusKeeper, suite.erc20Keeper, - config.EighteenDecimalsChainID, + constants.EighteenDecimalsChainID, "", ) } diff --git a/x/vm/keeper/msg_server.go b/x/vm/keeper/msg_server.go index 27cebf57..f1aad23a 100644 --- a/x/vm/keeper/msg_server.go +++ b/x/vm/keeper/msg_server.go @@ -7,9 +7,12 @@ import ( "strconv" "github.com/hashicorp/go-metrics" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" cmttypes "github.com/cometbft/cometbft/types" + evmtrace "github.com/cosmos/evm/trace" "github.com/cosmos/evm/x/vm/types" errorsmod "cosmossdk.io/errors" @@ -17,7 +20,6 @@ import ( "github.com/cosmos/cosmos-sdk/telemetry" sdk "github.com/cosmos/cosmos-sdk/types" - govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ) var _ types.MsgServer = &Keeper{} @@ -26,11 +28,14 @@ var _ types.MsgServer = &Keeper{} // executed (i.e applied) against the go-ethereum EVM. The provided SDK Context is set to the Keeper // so that it can implements and call the StateDB methods without receiving it as a function // parameter. -func (k *Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*types.MsgEthereumTxResponse, error) { +func (k *Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (_ *types.MsgEthereumTxResponse, err error) { + goCtx, span := tracer.Start(goCtx, "EthereumTx", trace.WithAttributes( + attribute.String("tx_hash", msg.Hash().Hex()), + )) + defer func() { evmtrace.EndSpanErr(span, err) }() ctx := sdk.UnwrapSDKContext(goCtx) tx := msg.AsTransaction() - txIndex := k.GetTxIndexTransient(ctx) labels := []metrics.Label{ telemetry.NewLabel("tx_type", fmt.Sprintf("%d", tx.Type())), @@ -78,8 +83,6 @@ func (k *Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*t sdk.NewAttribute(sdk.AttributeKeyAmount, tx.Value().String()), // add event for ethereum transaction hash format sdk.NewAttribute(types.AttributeKeyEthereumTxHash, response.Hash), - // add event for index of valid ethereum tx - sdk.NewAttribute(types.AttributeKeyTxIndex, strconv.FormatUint(txIndex, 10)), // add event for eth tx gas used, we can't get it from cosmos tx result when it contains multiple eth tx msgs. sdk.NewAttribute(types.AttributeKeyTxGasUsed, strconv.FormatUint(response.GasUsed, 10)), } @@ -119,12 +122,18 @@ func (k *Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*t // proposal passes, it updates the module parameters. The update can only be // performed if the requested authority is the Cosmos SDK governance module // account. -func (k *Keeper) UpdateParams(goCtx context.Context, req *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) { - if k.authority.String() != req.Authority { - return nil, errorsmod.Wrapf(govtypes.ErrInvalidSigner, "invalid authority, expected %s, got %s", k.authority.String(), req.Authority) +func (k *Keeper) UpdateParams(goCtx context.Context, req *types.MsgUpdateParams) (_ *types.MsgUpdateParamsResponse, err error) { + ctx := sdk.UnwrapSDKContext(goCtx) + ctx, span := ctx.StartSpan(tracer, "UpdateParams", trace.WithAttributes( + attribute.String("authority", req.Authority), + attribute.String("params", req.Params.String()), + )) + defer func() { evmtrace.EndSpanErr(span, err) }() + + if err := sdk.ValidateAuthority(ctx, k.authority.String(), req.Authority); err != nil { + return nil, err } - ctx := sdk.UnwrapSDKContext(goCtx) if err := k.SetParams(ctx, req.Params); err != nil { return nil, err } @@ -136,14 +145,18 @@ func (k *Keeper) UpdateParams(goCtx context.Context, req *types.MsgUpdateParams) // proposal passes, it creates the preinstalls. The registration can only be // performed if the requested authority is the Cosmos SDK governance module // account. -func (k *Keeper) RegisterPreinstalls(goCtx context.Context, req *types.MsgRegisterPreinstalls) (*types. - MsgRegisterPreinstallsResponse, error, +func (k *Keeper) RegisterPreinstalls(goCtx context.Context, req *types.MsgRegisterPreinstalls) ( + _ *types.MsgRegisterPreinstallsResponse, err error, ) { - if k.authority.String() != req.Authority { - return nil, errorsmod.Wrapf(govtypes.ErrInvalidSigner, "invalid authority, expected %s, got %s", k.authority.String(), req.Authority) + ctx := sdk.UnwrapSDKContext(goCtx) + ctx, span := ctx.StartSpan(tracer, "RegisterPreinstalls", trace.WithAttributes( + attribute.String("authority", req.Authority), + )) + defer func() { evmtrace.EndSpanErr(span, err) }() + if err := sdk.ValidateAuthority(ctx, k.authority.String(), req.Authority); err != nil { + return nil, err } - ctx := sdk.UnwrapSDKContext(goCtx) if err := k.AddPreinstalls(ctx, req.Preinstalls); err != nil { return nil, err } diff --git a/x/vm/keeper/params.go b/x/vm/keeper/params.go index b5892ad4..833553d4 100644 --- a/x/vm/keeper/params.go +++ b/x/vm/keeper/params.go @@ -6,7 +6,10 @@ import ( "sort" "github.com/ethereum/go-ethereum/common" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" + evmtrace "github.com/cosmos/evm/trace" "github.com/cosmos/evm/utils" "github.com/cosmos/evm/x/vm/types" @@ -15,17 +18,25 @@ import ( // GetParams returns the total set of evm parameters. func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) { + ctx, span := ctx.StartSpan(tracer, "GetParams") + defer span.End() store := ctx.KVStore(k.storeKey) bz := store.Get(types.KeyPrefixParams) if bz == nil { return params } k.cdc.MustUnmarshal(bz, ¶ms) - return + return params } // SetParams sets the EVM params each in their individual key for better get performance -func (k Keeper) SetParams(ctx sdk.Context, params types.Params) error { +func (k Keeper) SetParams(ctx sdk.Context, params types.Params) (err error) { + ctx, span := ctx.StartSpan(tracer, "SetParams", trace.WithAttributes( + attribute.String("evm_denom", params.EvmDenom), + attribute.Int("active_precompiles_count", len(params.ActiveStaticPrecompiles)), + attribute.Int("extra_eips_count", len(params.ExtraEIPs)), + )) + defer func() { evmtrace.EndSpanErr(span, err) }() // NOTE: We need to sort the precompiles in order to enable searching with binary search // in params.IsActivePrecompile. slices.Sort(params.ActiveStaticPrecompiles) @@ -46,7 +57,11 @@ func (k Keeper) SetParams(ctx sdk.Context, params types.Params) error { // EnableStaticPrecompiles appends the addresses of the given Precompiles to the list // of active static precompiles. -func (k Keeper) EnableStaticPrecompiles(ctx sdk.Context, addresses ...common.Address) error { +func (k Keeper) EnableStaticPrecompiles(ctx sdk.Context, addresses ...common.Address) (err error) { + ctx, span := ctx.StartSpan(tracer, "EnableStaticPrecompiles", trace.WithAttributes( + attribute.Int("addresses_count", len(addresses)), + )) + defer func() { evmtrace.EndSpanErr(span, err) }() params := k.GetParams(ctx) activePrecompiles := params.ActiveStaticPrecompiles @@ -81,7 +96,11 @@ func appendPrecompiles(existingPrecompiles []string, addresses ...common.Address } // EnableEIPs enables the given EIPs in the EVM parameters. -func (k Keeper) EnableEIPs(ctx sdk.Context, eips ...int64) error { +func (k Keeper) EnableEIPs(ctx sdk.Context, eips ...int64) (err error) { + ctx, span := ctx.StartSpan(tracer, "EnableEIPs", trace.WithAttributes( + attribute.Int("eips_count", len(eips)), + )) + defer func() { evmtrace.EndSpanErr(span, err) }() evmParams := k.GetParams(ctx) evmParams.ExtraEIPs = append(evmParams.ExtraEIPs, eips...) diff --git a/x/vm/keeper/precompiles.go b/x/vm/keeper/precompiles.go index 2813afed..ee26a8e0 100644 --- a/x/vm/keeper/precompiles.go +++ b/x/vm/keeper/precompiles.go @@ -3,7 +3,10 @@ package keeper import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" + evmtrace "github.com/cosmos/evm/trace" "github.com/cosmos/evm/x/vm/types" sdktypes "github.com/cosmos/cosmos-sdk/types" @@ -19,7 +22,11 @@ type Precompiles struct { func (k *Keeper) GetPrecompileInstance( ctx sdktypes.Context, address common.Address, -) (*Precompiles, bool, error) { +) (_ *Precompiles, _ bool, err error) { + ctx, span := ctx.StartSpan(tracer, "GetPrecompileInstance", trace.WithAttributes( + attribute.String("address", address.Hex()), + )) + defer func() { evmtrace.EndSpanErr(span, err) }() params := k.GetParams(ctx) // Get the precompile from the static precompiles if precompile, found, err := k.GetStaticPrecompileInstance(¶ms, address); err != nil { @@ -54,7 +61,11 @@ func (k *Keeper) GetPrecompileInstance( // GetPrecompilesCallHook returns a closure that can be used to instantiate the EVM with a specific // precompile instance. func (k *Keeper) GetPrecompilesCallHook(ctx sdktypes.Context) types.CallHook { - return func(evm *vm.EVM, _ common.Address, recipient common.Address) error { + return func(evm *vm.EVM, _ common.Address, recipient common.Address) (err error) { + ctx, span := ctx.StartSpan(tracer, "PrecompileCallHook", trace.WithAttributes( + attribute.String("recipient", recipient.Hex()), + )) + defer func() { evmtrace.EndSpanErr(span, err) }() // Check if the recipient is a precompile contract and if so, load the precompile instance precompiles, found, err := k.GetPrecompileInstance(ctx, recipient) if err != nil { @@ -72,22 +83,30 @@ func (k *Keeper) GetPrecompilesCallHook(ctx sdktypes.Context) types.CallHook { } } -// GetPrecompileRecipientCallHook returns a closure that can be used to instantiate the EVM with a specific -// recipient from precompiles. +// GetPrecompileRecipientCallHook returns a call hook for use with state overrides. +// It checks active precompiles first, then only dynamic precompiles (not static ones +// which may have been moved/disabled by state overrides). func (k *Keeper) GetPrecompileRecipientCallHook(ctx sdktypes.Context) types.CallHook { - return func(evm *vm.EVM, _ common.Address, recipient common.Address) error { - // Check if the recipient is a precompile contract and if so, load the precompile instance - _, found, err := k.GetPrecompileInstance(ctx, recipient) - if err != nil { - return err - } - - // If the precompile instance is created, we have to update the EVM with - // only the recipient precompile and add it's address to the access list. - if found { + return func(evm *vm.EVM, _ common.Address, recipient common.Address) (err error) { + ctx, span := ctx.StartSpan(tracer, "PrecompileRecipientCallHook", trace.WithAttributes( + attribute.String("recipient", recipient.Hex()), + )) + defer func() { evmtrace.EndSpanErr(span, err) }() + if _, ok := evm.Precompile(recipient); ok { evm.StateDB.AddAddressToAccessList(recipient) + return nil } - + if k.erc20Keeper == nil { + return nil + } + precompile, found, err := k.erc20Keeper.GetERC20PrecompileInstance(ctx, recipient) + if err != nil || !found { + return err + } + addressMap := make(map[common.Address]vm.PrecompiledContract) + addressMap[recipient] = precompile + evm.WithPrecompiles(addressMap) + evm.StateDB.AddAddressToAccessList(recipient) return nil } } diff --git a/x/vm/keeper/precompiles_test.go b/x/vm/keeper/precompiles_test.go new file mode 100644 index 00000000..e585760d --- /dev/null +++ b/x/vm/keeper/precompiles_test.go @@ -0,0 +1,116 @@ +package keeper_test + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/params" + "github.com/stretchr/testify/mock" + + statedbmocks "github.com/cosmos/evm/x/vm/statedb/mocks" +) + +func (suite *KeeperTestSuite) TestGetPrecompileRecipientCallHook() { + staticPrecompileAddr := common.HexToAddress("0x0000000000000000000000000000000000000001") + dynamicPrecompileAddr := common.HexToAddress("0x0000000000000000000000000000000000001234") + nonPrecompileAddr := common.HexToAddress("0x0000000000000000000000000000000000009999") + caller := common.HexToAddress("0x1111111111111111111111111111111111111111") + + // recipient in active precompiles + suite.Run("recipient in active precompiles", func() { + mockStateDB := statedbmocks.NewStateDB(suite.T()) + precompileMap := map[common.Address]vm.PrecompiledContract{ + staticPrecompileAddr: &mockPrecompiledContract{address: staticPrecompileAddr}, + } + + evm := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1), Time: 1}, mockStateDB, params.TestChainConfig, vm.Config{}) + evm.WithPrecompiles(precompileMap) + + mockStateDB.On("AddAddressToAccessList", staticPrecompileAddr).Return().Once() + + hook := suite.vmKeeper.GetPrecompileRecipientCallHook(suite.ctx) + err := hook(evm, caller, staticPrecompileAddr) + suite.Require().NoError(err) + mockStateDB.AssertExpectations(suite.T()) + }) + + // recipient not in active precompiles but is a dynamic precompile + suite.Run("dynamic precompile found", func() { + mockStateDB := statedbmocks.NewStateDB(suite.T()) + precompileMap := map[common.Address]vm.PrecompiledContract{ + staticPrecompileAddr: &mockPrecompiledContract{address: staticPrecompileAddr}, + } + + evm := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1), Time: 1}, mockStateDB, params.TestChainConfig, vm.Config{}) + evm.WithPrecompiles(precompileMap) + + mockPrecompile := &mockPrecompiledContract{address: dynamicPrecompileAddr} + suite.erc20Keeper.On("GetERC20PrecompileInstance", mock.Anything, dynamicPrecompileAddr). + Return(mockPrecompile, true, nil).Once() + mockStateDB.On("AddAddressToAccessList", dynamicPrecompileAddr).Return().Once() + + hook := suite.vmKeeper.GetPrecompileRecipientCallHook(suite.ctx) + err := hook(evm, caller, dynamicPrecompileAddr) + suite.Require().NoError(err) + mockStateDB.AssertExpectations(suite.T()) + }) + + // recipient is neither static nor dynamic precompile + suite.Run("non-precompile address", func() { + mockStateDB := statedbmocks.NewStateDB(suite.T()) + precompileMap := map[common.Address]vm.PrecompiledContract{ + staticPrecompileAddr: &mockPrecompiledContract{address: staticPrecompileAddr}, + } + + evm := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1), Time: 1}, mockStateDB, params.TestChainConfig, vm.Config{}) + evm.WithPrecompiles(precompileMap) + + suite.erc20Keeper.On("GetERC20PrecompileInstance", mock.Anything, nonPrecompileAddr). + Return(nil, false, nil).Once() + + hook := suite.vmKeeper.GetPrecompileRecipientCallHook(suite.ctx) + err := hook(evm, caller, nonPrecompileAddr) + suite.Require().NoError(err) + mockStateDB.AssertExpectations(suite.T()) + }) + + // empty active precompiles but dynamic precompile exists + suite.Run("empty active precompiles with dynamic precompile", func() { + mockStateDB := statedbmocks.NewStateDB(suite.T()) + precompileMap := map[common.Address]vm.PrecompiledContract{} + + evm := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1), Time: 1}, mockStateDB, params.TestChainConfig, vm.Config{}) + evm.WithPrecompiles(precompileMap) + + mockPrecompile := &mockPrecompiledContract{address: dynamicPrecompileAddr} + suite.erc20Keeper.On("GetERC20PrecompileInstance", mock.Anything, dynamicPrecompileAddr). + Return(mockPrecompile, true, nil).Once() + mockStateDB.On("AddAddressToAccessList", dynamicPrecompileAddr).Return().Once() + + hook := suite.vmKeeper.GetPrecompileRecipientCallHook(suite.ctx) + err := hook(evm, caller, dynamicPrecompileAddr) + suite.Require().NoError(err) + mockStateDB.AssertExpectations(suite.T()) + }) +} + +type mockPrecompiledContract struct { + address common.Address +} + +func (m *mockPrecompiledContract) Name() string { + return "" +} + +func (m *mockPrecompiledContract) Address() common.Address { + return m.address +} + +func (m *mockPrecompiledContract) RequiredGas(input []byte) uint64 { + return 0 +} + +func (m *mockPrecompiledContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool) ([]byte, error) { + return nil, nil +} diff --git a/x/vm/keeper/preinstalls.go b/x/vm/keeper/preinstalls.go index 14c8cc0c..7be13774 100644 --- a/x/vm/keeper/preinstalls.go +++ b/x/vm/keeper/preinstalls.go @@ -5,7 +5,10 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" + evmtrace "github.com/cosmos/evm/trace" "github.com/cosmos/evm/x/vm/types" errorsmod "cosmossdk.io/errors" @@ -13,7 +16,11 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -func (k *Keeper) AddPreinstalls(ctx sdk.Context, preinstalls []types.Preinstall) error { +func (k *Keeper) AddPreinstalls(ctx sdk.Context, preinstalls []types.Preinstall) (err error) { + ctx, span := ctx.StartSpan(tracer, "AddPreinstalls", trace.WithAttributes( + attribute.Int("count", len(preinstalls)), + )) + defer func() { evmtrace.EndSpanErr(span, err) }() for _, preinstall := range preinstalls { address := common.HexToAddress(preinstall.Address) accAddress := sdk.AccAddress(address.Bytes()) diff --git a/x/vm/keeper/state_transition.go b/x/vm/keeper/state_transition.go index eb8975cf..dab023b2 100644 --- a/x/vm/keeper/state_transition.go +++ b/x/vm/keeper/state_transition.go @@ -11,19 +11,22 @@ import ( "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" cmttypes "github.com/cometbft/cometbft/types" antetypes "github.com/cosmos/evm/ante/types" rpctypes "github.com/cosmos/evm/rpc/types" + evmtrace "github.com/cosmos/evm/trace" "github.com/cosmos/evm/utils" "github.com/cosmos/evm/x/vm/statedb" "github.com/cosmos/evm/x/vm/types" errorsmod "cosmossdk.io/errors" "cosmossdk.io/math" - storetypes "cosmossdk.io/store/types" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" consensustypes "github.com/cosmos/cosmos-sdk/x/consensus/types" ) @@ -37,10 +40,15 @@ func (k *Keeper) NewEVMWithOverridePrecompiles( ctx sdk.Context, msg core.Message, cfg *statedb.EVMConfig, - tracer *tracing.Hooks, + tracingHooks *tracing.Hooks, stateDB vm.StateDB, overridePrecompiles bool, ) *vm.EVM { + ctx, span := ctx.StartSpan(tracer, "NewEVMWithOverridePrecompiles", trace.WithAttributes( + attribute.Bool("override_precompiles", overridePrecompiles), + attribute.String("from", msg.From.Hex()), + )) + defer span.End() ctx = k.SetConsensusParamsInCtx(ctx) blockCtx := vm.BlockContext{ CanTransfer: core.CanTransfer, @@ -57,10 +65,10 @@ func (k *Keeper) NewEVMWithOverridePrecompiles( ethCfg := types.GetEthChainConfig() txCtx := core.NewEVMTxContext(&msg) - if tracer == nil { - tracer = k.Tracer(ctx, msg, ethCfg) + if tracingHooks == nil { + tracingHooks = k.Tracer(ctx, msg, ethCfg) } - vmConfig := k.VMConfig(ctx, msg, cfg, tracer) + vmConfig := k.VMConfig(ctx, msg, cfg, tracingHooks) signer := msg.From accessControl := types.NewRestrictedPermissionPolicy(&cfg.Params.AccessControl, signer) @@ -97,14 +105,16 @@ func (k *Keeper) NewEVM( ctx sdk.Context, msg core.Message, cfg *statedb.EVMConfig, - tracer *tracing.Hooks, + tracingHooks *tracing.Hooks, stateDB vm.StateDB, ) *vm.EVM { + ctx, span := ctx.StartSpan(tracer, "NewEVM") + defer span.End() return k.NewEVMWithOverridePrecompiles( ctx, msg, cfg, - tracer, + tracingHooks, stateDB, true, ) @@ -122,6 +132,9 @@ func (k Keeper) GetHashFn(ctx sdk.Context) vm.GetHashFunc { return common.Hash{} } + ctx, span := ctx.StartSpan(tracer, "GetHashFnInner", trace.WithAttributes(attribute.Int64("height", h))) + defer span.End() + switch { case ctx.BlockHeight() == h: // Case 1: The requested height matches the one from the context so we can retrieve the header @@ -154,15 +167,16 @@ func (k Keeper) GetHashFn(ctx sdk.Context) vm.GetHashFunc { } } -func (k *Keeper) initializeBloomFromLogs(ctx sdk.Context, ethLogs []*ethtypes.Log) (bloom *big.Int, bloomReceipt ethtypes.Bloom) { - // Compute block bloom filter - if len(ethLogs) > 0 { - bloom = k.GetBlockBloomTransient(ctx) - bloom.Or(bloom, big.NewInt(0).SetBytes(ethtypes.CreateBloom(ðtypes.Receipt{Logs: ethLogs}).Bytes())) - bloomReceipt = ethtypes.BytesToBloom(bloom.Bytes()) +// logsBloom returns the bloom bytes for the given logs +func logsBloom(logs []*ethtypes.Log) []byte { + var bin ethtypes.Bloom + for _, log := range logs { + bin.Add(log.Address.Bytes()) + for _, b := range log.Topics { + bin.Add(b[:]) + } } - - return + return bin[:] } func calculateCumulativeGasFromEthResponse(meter storetypes.GasMeter, res *types.MsgEthereumTxResponse) uint64 { @@ -194,7 +208,11 @@ func calculateCumulativeGasFromEthResponse(meter storetypes.GasMeter, res *types // returning. // // For relevant discussion see: https://github.com/cosmos/cosmos-sdk/discussions/9072 -func (k *Keeper) ApplyTransaction(ctx sdk.Context, tx *ethtypes.Transaction) (*types.MsgEthereumTxResponse, error) { +func (k *Keeper) ApplyTransaction(ctx sdk.Context, tx *ethtypes.Transaction) (_ *types.MsgEthereumTxResponse, err error) { + ctx, span := ctx.StartSpan(tracer, "ApplyTransaction", trace.WithAttributes( + attribute.String("hash", tx.Hash().String()), + )) + defer func() { evmtrace.EndSpanErr(span, err) }() cfg, err := k.EVMConfig(ctx, ctx.BlockHeader().ProposerAddress) if err != nil { return nil, errorsmod.Wrap(err, "failed to load evm config") @@ -214,7 +232,8 @@ func (k *Keeper) ApplyTransaction(ctx sdk.Context, tx *ethtypes.Transaction) (*t tmpCtx, commitFn := ctx.CacheContext() // pass true to commit the StateDB - res, err := k.ApplyMessageWithConfig(tmpCtx, *msg, nil, true, cfg, txConfig, false, nil) + stateDB := statedb.New(tmpCtx, k, txConfig) + res, err := k.ApplyMessageWithConfig(tmpCtx, stateDB, *msg, nil, true, false, cfg, txConfig, false, nil) if err != nil { // when a transaction contains multiple msg, as long as one of the msg fails // all gas will be deducted. so is not msg.Gas() @@ -223,7 +242,10 @@ func (k *Keeper) ApplyTransaction(ctx sdk.Context, tx *ethtypes.Transaction) (*t } ethLogs := types.LogsToEthereum(res.Logs) - _, bloomReceipt := k.initializeBloomFromLogs(ctx, ethLogs) + // Compute block bloom filter + if len(ethLogs) > 0 { + k.SetTxBloom(tmpCtx, new(big.Int).SetBytes(logsBloom(ethLogs))) + } var contractAddr common.Address if msg.To == nil { @@ -234,14 +256,13 @@ func (k *Keeper) ApplyTransaction(ctx sdk.Context, tx *ethtypes.Transaction) (*t 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, + TransactionIndex: uint(ctx.TxIndex()), //#nosec G115 } if res.Failed() { @@ -259,8 +280,6 @@ func (k *Keeper) ApplyTransaction(ctx sdk.Context, tx *ethtypes.Transaction) (*t 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 @@ -294,35 +313,18 @@ func (k *Keeper) ApplyTransaction(ctx sdk.Context, tx *ethtypes.Transaction) (*t } else { res.Logs = types.NewLogsFromEth(receipt.Logs) } - - events := tmpCtx.EventManager().Events() - if len(events) > eventsLen { - ctx.EventManager().EmitEvents(events[eventsLen:]) - } } } - // update logs and bloom for full view if post processing updated them - ethLogs = types.LogsToEthereum(res.Logs) - bloom, _ := k.initializeBloomFromLogs(ctx, ethLogs) - // refund gas to match the Ethereum gas consumption instead of the default SDK one. remainingGas := uint64(0) if msg.GasLimit > res.GasUsed { remainingGas = msg.GasLimit - res.GasUsed } - if err = k.RefundGas(ctx, *msg, remainingGas, types.GetEVMCoinDenom()); err != nil { - return nil, errorsmod.Wrapf(err, "failed to refund gas leftover gas to sender %s", msg.From) - } - - if len(ethLogs) > 0 { - // Update transient block bloom filter - k.SetBlockBloomTransient(ctx, bloom) - k.SetLogSizeTransient(ctx, uint64(txConfig.LogIndex)+uint64(len(ethLogs))) + if err = k.RefundGas(ctx, *msg, remainingGas, res.GasUsed, types.GetEVMCoinDenom()); err != nil { + return nil, errorsmod.Wrapf(err, "failed to refund leftover gas to sender %s", msg.From) } - k.SetTxIndexTransient(ctx, uint64(txConfig.TxIndex)+1) - totalGasUsed, err := k.AddTransientGasUsed(ctx, res.GasUsed) if err != nil { return nil, errorsmod.Wrap(err, "failed to add transient gas used") @@ -334,14 +336,22 @@ func (k *Keeper) ApplyTransaction(ctx sdk.Context, tx *ethtypes.Transaction) (*t } // ApplyMessage calls ApplyMessageWithConfig with an empty TxConfig. -func (k *Keeper) ApplyMessage(ctx sdk.Context, msg core.Message, tracer *tracing.Hooks, commit bool, internal bool) (*types.MsgEthereumTxResponse, error) { +// Note: if you call this from a precompile context, ensure that +// you use the existing stateDB. +func (k *Keeper) ApplyMessage(ctx sdk.Context, stateDB *statedb.StateDB, msg core.Message, tracingHooks *tracing.Hooks, commit, callFromPrecompile, internal bool) (*types.MsgEthereumTxResponse, error) { + ctx, span := ctx.StartSpan(tracer, "ApplyMessage", trace.WithAttributes( + attribute.Bool("commit", commit), + attribute.Bool("internal", internal), + attribute.String("from", msg.From.Hex()), + )) + defer span.End() cfg, err := k.EVMConfig(ctx, ctx.BlockHeader().ProposerAddress) if err != nil { return nil, errorsmod.Wrap(err, "failed to load evm config") } txConfig := statedb.NewEmptyTxConfig() - return k.ApplyMessageWithConfig(ctx, msg, tracer, commit, cfg, txConfig, internal, nil) + return k.ApplyMessageWithConfig(ctx, stateDB, msg, tracingHooks, commit, callFromPrecompile, cfg, txConfig, internal, nil) } // ApplyMessageWithConfig computes the new state by applying the given message against the existing state. @@ -381,29 +391,37 @@ func (k *Keeper) ApplyMessage(ctx sdk.Context, msg core.Message, tracer *tracing // // # Commit parameter // -// If commit is true, the `StateDB` will be committed, otherwise discarded. -func (k *Keeper) ApplyMessageWithConfig( - ctx sdk.Context, - msg core.Message, - tracer *tracing.Hooks, - commit bool, - cfg *statedb.EVMConfig, - txConfig statedb.TxConfig, - internal bool, - overrides *rpctypes.StateOverride, -) (*types.MsgEthereumTxResponse, error) { +// If commit is true, the `StateDB` will be committed or flushed (if called from within a precompile), otherwise discarded. +func (k *Keeper) ApplyMessageWithConfig(ctx sdk.Context, stateDB *statedb.StateDB, msg core.Message, tracingHooks *tracing.Hooks, commit bool, callFromPrecompile bool, cfg *statedb.EVMConfig, txConfig statedb.TxConfig, internal bool, overrides *rpctypes.StateOverride) (_ *types.MsgEthereumTxResponse, err error) { var ( ret []byte // return bytes from evm execution vmErr error // vm errors do not effect consensus and are therefore not assigned to err ) - stateDB := statedb.New(ctx, k, txConfig) + ctx, span := ctx.StartSpan(tracer, "ApplyMessageWithConfig", trace.WithAttributes( + attribute.String("hash", txConfig.TxHash.String()), + attribute.Int("tx_index", int(txConfig.TxIndex)), //nolint:gosec // G115 + attribute.Bool("commit", commit), + attribute.Bool("internal", internal), + )) + defer func() { evmtrace.EndSpanErr(span, err) }() + + if stateDB == nil { + return nil, types.ErrNilStateDB + } ethCfg := types.GetEthChainConfig() - evm := k.NewEVMWithOverridePrecompiles(ctx, msg, cfg, tracer, stateDB, overrides == nil) + evm := k.NewEVMWithOverridePrecompiles(ctx, msg, cfg, tracingHooks, stateDB, overrides == nil) // Gas limit suffices for the floor data cost (EIP-7623) rules := ethCfg.Rules(evm.Context.BlockNumber, true, evm.Context.Time) if overrides != nil { precompiles := vm.ActivePrecompiledContracts(rules) + params := k.GetParams(ctx) + for _, precompileAddr := range params.ActiveStaticPrecompiles { + address := common.HexToAddress(precompileAddr) + if precompile, found := k.precompiles[address]; found { + precompiles[address] = precompile + } + } if err := overrides.Apply(stateDB, precompiles); err != nil { return nil, errorsmod.Wrap(err, "failed to apply state override") } @@ -415,11 +433,13 @@ func (k *Keeper) ApplyMessageWithConfig( // Allow the tracer captures the tx level events, mainly the gas consumption. vmCfg := evm.Config if vmCfg.Tracer != nil { - vmCfg.Tracer.OnTxStart( - evm.GetVMContext(), - ethtypes.NewTx(ðtypes.LegacyTx{To: msg.To, Data: msg.Data, Value: msg.Value, Gas: msg.GasLimit}), - msg.From, - ) + if vmCfg.Tracer.OnTxStart != nil { + vmCfg.Tracer.OnTxStart( + evm.GetVMContext(), + ethtypes.NewTx(ðtypes.LegacyTx{To: msg.To, Data: msg.Data, Value: msg.Value, Gas: msg.GasLimit}), + msg.From, + ) + } defer func() { if vmCfg.Tracer.OnTxEnd != nil { vmCfg.Tracer.OnTxEnd(ðtypes.Receipt{GasUsed: msg.GasLimit - leftoverGas}, vmErr) @@ -455,7 +475,10 @@ func (k *Keeper) ApplyMessageWithConfig( // access list preparation is moved from ante handler to here, because it's needed when `ApplyMessage` is called // under contexts where ante handlers are not run, for example `eth_call` and `eth_estimateGas`. - stateDB.Prepare(rules, msg.From, common.Address{}, msg.To, evm.ActivePrecompiles(), msg.AccessList) + // If we're in a nested precompile scenario, then we don't want to prepare the stateDB a second time. + if !callFromPrecompile { + stateDB.Prepare(rules, msg.From, common.Address{}, msg.To, evm.ActivePrecompiles(), msg.AccessList) + } convertedValue, err := utils.Uint256FromBigInt(msg.Value) if err != nil { @@ -467,14 +490,22 @@ func (k *Keeper) ApplyMessageWithConfig( // - reset sender's nonce to msg.Nonce() before calling evm. // - increase sender's nonce by one no matter the result. stateDB.SetNonce(sender.Address(), msg.Nonce, tracing.NonceChangeEoACall) - ret, _, leftoverGas, vmErr = evm.Create(sender.Address(), msg.Data, leftoverGas, convertedValue) - stateDB.SetNonce(sender.Address(), msg.Nonce+1, tracing.NonceChangeContractCreator) + var contractAddr common.Address + ret, contractAddr, leftoverGas, vmErr = evm.Create(sender.Address(), msg.Data, leftoverGas, convertedValue) + // Only increment nonce if it wasn't already incremented during evm.Create() + // (e.g., by nested contract creations through EIP-7702 delegation) + if stateDB.GetNonce(sender.Address()) == msg.Nonce { + stateDB.SetNonce(sender.Address(), msg.Nonce+1, tracing.NonceChangeContractCreator) + } + if vmErr == nil { + span.AddEvent("contract_creation", trace.WithAttributes(attribute.String("contract_address", contractAddr.String()))) + } } else { // Apply EIP-7702 authorizations. if msg.SetCodeAuthorizations != nil { for _, auth := range msg.SetCodeAuthorizations { // Note errors are ignored, we simply skip invalid authorizations here. - if err := k.applyAuthorization(&auth, stateDB, ethCfg.ChainID); err != nil { + if err := k.applyAuthorization(ctx, &auth, stateDB, ethCfg.ChainID); err != nil { k.Logger(ctx).Debug("failed to apply authorization", "error", err, "authorization", auth) } } @@ -518,15 +549,27 @@ func (k *Keeper) ApplyMessageWithConfig( var vmError string if vmErr != nil { vmError = vmErr.Error() + span.AddEvent("vm_error", trace.WithAttributes(attribute.String("vm_err", vmError))) } + isAmsterdam := ethCfg.IsAmsterdam(evm.Context.BlockNumber, evm.Context.Time) + if isAmsterdam { + stateDB.EmitLogsForBurnAccounts() + } // The dirty states in `StateDB` is either committed or discarded after return if commit { - if err := stateDB.Commit(); err != nil { - return nil, errorsmod.Wrap(err, "failed to commit stateDB") + // In a precompile context, we never want to commit, as that will collapse the cache stack. + // Instead, we want to flush to the cacheCtx. + if callFromPrecompile { + if err := stateDB.FlushToCacheCtx(); err != nil { + return nil, errorsmod.Wrap(err, "failed to flush stateDB to cacheCtx") + } + } else { + if err := stateDB.Commit(); err != nil { + return nil, errorsmod.Wrap(err, "failed to commit stateDB") + } } } - // calculate a minimum amount of gas to be charged to sender if GasLimit // is considerably higher than GasUsed to stay more aligned with CometBFT gas mechanics // for more info https://github.com/evmos/ethermint/issues/1085 @@ -550,12 +593,12 @@ func (k *Keeper) ApplyMessageWithConfig( if !internal { gasUsed = math.LegacyMaxDec(gasUsed, minimumGasUsed) } - // reset leftoverGas, to be used by the tracer + // reset leftoverGas, to be used by the tracingHooks leftoverGas = msg.GasLimit - gasUsed.TruncateInt().Uint64() // if the execution reverted, we return the revert reason as the return data if vmError == vm.ErrExecutionReverted.Error() { - ret = evm.Interpreter().ReturnData() + ret = evm.ReturnData() } return &types.MsgEthereumTxResponse{ GasUsed: gasUsed.TruncateInt().Uint64(), @@ -585,8 +628,13 @@ func (k *Keeper) SetConsensusParamsInCtx(ctx sdk.Context) sdk.Context { } // applyAuthorization applies an EIP-7702 code delegation to the state. -func (k *Keeper) applyAuthorization(auth *ethtypes.SetCodeAuthorization, state vm.StateDB, chainID *big.Int) error { - authority, err := k.validateAuthorization(auth, state, chainID) +func (k *Keeper) applyAuthorization(ctx sdk.Context, auth *ethtypes.SetCodeAuthorization, state vm.StateDB, chainID *big.Int) (err error) { + ctx, span := ctx.StartSpan(tracer, "applyAuthorization", trace.WithAttributes( + attribute.String("delegate_address", auth.Address.Hex()), + attribute.Int64("nonce", int64(auth.Nonce)), //nolint:gosec // G115 + )) + defer func() { evmtrace.EndSpanErr(span, err) }() + authority, err := k.validateAuthorization(ctx, auth, state, chainID) if err != nil { return err } @@ -601,18 +649,23 @@ func (k *Keeper) applyAuthorization(auth *ethtypes.SetCodeAuthorization, state v state.SetNonce(authority, auth.Nonce+1, tracing.NonceChangeAuthorization) if auth.Address == (common.Address{}) { // Delegation to zero address means clear. - state.SetCode(authority, nil) + state.SetCode(authority, nil, tracing.CodeChangeAuthorizationClear) return nil } // Otherwise install delegation to auth.Address. - state.SetCode(authority, ethtypes.AddressToDelegation(auth.Address)) + state.SetCode(authority, ethtypes.AddressToDelegation(auth.Address), tracing.CodeChangeAuthorization) return nil } // validateAuthorization validates an EIP-7702 authorization against the state. -func (k *Keeper) validateAuthorization(auth *ethtypes.SetCodeAuthorization, state vm.StateDB, chainID *big.Int) (authority common.Address, err error) { +func (k *Keeper) validateAuthorization(ctx sdk.Context, auth *ethtypes.SetCodeAuthorization, state vm.StateDB, chainID *big.Int) (authority common.Address, err error) { + _, span := ctx.StartSpan(tracer, "validateAuthorization", trace.WithAttributes( + attribute.String("delegate_address", auth.Address.Hex()), + attribute.Int64("nonce", int64(auth.Nonce)), //nolint:gosec // G115 + )) + defer func() { evmtrace.EndSpanErr(span, err) }() // Verify chain ID is null or equal to current chain ID. if !auth.ChainID.IsZero() && auth.ChainID.CmpBig(chainID) != 0 { return authority, core.ErrAuthorizationWrongChainID diff --git a/x/vm/keeper/statedb.go b/x/vm/keeper/statedb.go index 828e0da6..e6dce21d 100644 --- a/x/vm/keeper/statedb.go +++ b/x/vm/keeper/statedb.go @@ -6,14 +6,19 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/holiman/uint256" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" + evmtrace "github.com/cosmos/evm/trace" "github.com/cosmos/evm/x/vm/statedb" "github.com/cosmos/evm/x/vm/types" - "cosmossdk.io/store/prefix" - storetypes "cosmossdk.io/store/types" + errorsmod "cosmossdk.io/errors" + "github.com/cosmos/cosmos-sdk/store/v2/prefix" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/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" ) @@ -25,17 +30,42 @@ var _ statedb.Keeper = &Keeper{} // GetAccount returns nil if account is not exist func (k *Keeper) GetAccount(ctx sdk.Context, addr common.Address) *statedb.Account { - acct := k.GetAccountWithoutBalance(ctx, addr) + ctx, span := ctx.StartSpan(tracer, "GetAccount", trace.WithAttributes(attribute.String("address", addr.Hex()))) + defer span.End() + + cosmosAddr := sdk.AccAddress(addr.Bytes()) + acct := k.accountKeeper.GetAccount(ctx, cosmosAddr) if acct == nil { return nil } - acct.Balance = k.SpendableCoin(ctx, addr) - return acct + return statedb.NewAccount( + acct.GetSequence(), + k.SpendableCoin(ctx, addr), + k.lockedCoin(ctx, addr), + k.GetCodeHash(ctx, addr).Bytes(), + ) +} + +// IsBaseAccountOrEmpty reports whether addr has no Cosmos account yet, or +// carries exactly the plain BaseAccount type. CreateAccount uses it to reject +// EVM contract deployment onto vesting, module, or other non-base accounts. +func (k *Keeper) IsBaseAccountOrEmpty(ctx sdk.Context, addr common.Address) bool { + acct := k.accountKeeper.GetAccount(ctx, addr.Bytes()) + if acct == nil { + return true + } + _, ok := acct.(*authtypes.BaseAccount) + return ok } // GetState loads contract state from database. func (k *Keeper) GetState(ctx sdk.Context, addr common.Address, key common.Hash) common.Hash { + ctx, span := ctx.StartSpan(tracer, "GetState", trace.WithAttributes( + attribute.String("address", addr.Hex()), + attribute.String("key", key.Hex()), + )) + defer span.End() store := prefix.NewStore(ctx.KVStore(k.storeKey), types.AddressStoragePrefix(addr)) value := store.Get(key.Bytes()) @@ -48,6 +78,11 @@ func (k *Keeper) GetState(ctx sdk.Context, addr common.Address, key common.Hash) // GetFastState loads contract state from database. func (k *Keeper) GetFastState(ctx sdk.Context, addr common.Address, key common.Hash) []byte { + ctx, span := ctx.StartSpan(tracer, "GetFastState", trace.WithAttributes( + attribute.String("address", addr.Hex()), + attribute.String("key", key.Hex()), + )) + defer span.End() store := prefix.NewStore(ctx.KVStore(k.storeKey), types.AddressStoragePrefix(addr)) return store.Get(key.Bytes()) @@ -55,6 +90,8 @@ func (k *Keeper) GetFastState(ctx sdk.Context, addr common.Address, key common.H // GetCodeHash loads the code hash from the database for the given contract address. func (k *Keeper) GetCodeHash(ctx sdk.Context, addr common.Address) common.Hash { + ctx, span := ctx.StartSpan(tracer, "GetCodeHash", trace.WithAttributes(attribute.String("address", addr.Hex()))) + defer span.End() store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixCodeHash) bz := store.Get(addr.Bytes()) if len(bz) == 0 { @@ -69,6 +106,8 @@ func (k *Keeper) GetCodeHash(ctx sdk.Context, addr common.Address) common.Hash { // // The iteration is stopped when the callback function returns true. func (k Keeper) IterateContracts(ctx sdk.Context, cb func(addr common.Address, codeHash common.Hash) (stop bool)) { + ctx, span := ctx.StartSpan(tracer, "IterateContracts") + defer span.End() store := ctx.KVStore(k.storeKey) iterator := storetypes.KVStorePrefixIterator(store, types.KeyPrefixCodeHash) @@ -85,12 +124,18 @@ func (k Keeper) IterateContracts(ctx sdk.Context, cb func(addr common.Address, c // GetCode loads contract code from database, implements `statedb.Keeper` interface. func (k *Keeper) GetCode(ctx sdk.Context, codeHash common.Hash) []byte { + ctx, span := ctx.StartSpan(tracer, "GetCode", trace.WithAttributes( + attribute.String("code_hash", codeHash.Hex()), + )) + defer span.End() store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixCode) return store.Get(codeHash.Bytes()) } // ForEachStorage iterate contract storage, callback return false to break early func (k *Keeper) ForEachStorage(ctx sdk.Context, addr common.Address, cb func(key, value common.Hash) bool) { + ctx, span := ctx.StartSpan(tracer, "ForEachStorage", trace.WithAttributes(attribute.String("address", addr.Hex()))) + defer span.End() store := ctx.KVStore(k.storeKey) prefix := types.AddressStoragePrefix(addr) @@ -108,35 +153,64 @@ func (k *Keeper) ForEachStorage(ctx sdk.Context, addr common.Address, cb func(ke } } -// SetBalance update account's balance, compare with current balance first, then decide to mint or burn. -func (k *Keeper) SetBalance(ctx sdk.Context, addr common.Address, amount *uint256.Int) error { +// SetAccountBalance update account's balance, compare with current balance first, +// then decide to mint or burn. +// +// If account has a Locked balance specified within it, that value is used in +// order to compute the final balance. If Locked is nil, account's locked +// balance is fetched from state first in order to compute the final balance. +func (k *Keeper) SetAccountBalance(ctx sdk.Context, addr common.Address, account statedb.Account) error { + locked := account.LockedBalanceSnapshot() + if locked == nil { + return k.SetBalance(ctx, addr, account.Balance) + } + return k.SetBalanceWithLocked(ctx, addr, account.Balance, locked) +} + +// SetBalance updates an account's balance, compare with current balance first, +// then decide to mint or burn. +func (k *Keeper) SetBalance(ctx sdk.Context, addr common.Address, amount *uint256.Int) (err error) { + cosmosAddr := sdk.AccAddress(addr.Bytes()) + lockedCoin := k.bankWrapper.LockedCoins(ctx, cosmosAddr).AmountOf(types.GetEVMCoinDenom()) + return k.SetBalanceWithLocked(ctx, addr, amount, lockedCoin.BigInt()) +} + +// SetBalanceWithLocked updates an account's balance, compare with current +// balance first, then decide to mint or burn. +// +// Locked must be non nil and is used to compute the final balance instead of +// looking it up from state at set time. If you do not know the locked balance +// already, use SetBalance in order to look it up from state at set time. +func (k *Keeper) SetBalanceWithLocked(ctx sdk.Context, addr common.Address, amount *uint256.Int, locked *big.Int) (err error) { if amount == nil { return nil } + + ctx, span := ctx.StartSpan(tracer, "SetBalanceWithLocked", trace.WithAttributes(attribute.String("address", addr.Hex()), attribute.String("amount", amount.String()))) + defer func() { evmtrace.EndSpanErr(span, err) }() cosmosAddr := sdk.AccAddress(addr.Bytes()) - coin := k.bankWrapper.SpendableCoin(ctx, cosmosAddr, types.GetEVMCoinDenom()) - balance := coin.Amount.BigInt() - delta := new(big.Int).Sub(amount.ToBig(), balance) - switch delta.Sign() { - case 1: - // mint - if err := k.bankWrapper.MintAmountToAccount(ctx, cosmosAddr, delta); err != nil { - return err - } - case -1: - // burn - if err := k.bankWrapper.BurnAmountFromAccount(ctx, cosmosAddr, new(big.Int).Neg(delta)); err != nil { - return err - } - default: - // not changed + isModule := false + if acct := k.accountKeeper.GetAccount(ctx, cosmosAddr); acct != nil { + _, isModule = acct.(sdk.ModuleAccountI) } - return nil + coin := k.bankWrapper.SpendableCoin(ctx, cosmosAddr, types.GetEVMCoinDenom()) + isBlockedChange := k.bankWrapper.BlockedAddr(cosmosAddr) && amount.ToBig().Cmp(coin.Amount.BigInt()) != 0 + if isModule || isBlockedChange { + return errorsmod.Wrapf(errortypes.ErrUnauthorized, "%s is not allowed to receive funds", cosmosAddr) + } + + newBalance := new(big.Int).Add(amount.ToBig(), locked) + return k.bankWrapper.SetBalance(ctx, cosmosAddr, newBalance) } // SetAccount updates nonce/balance/codeHash together. -func (k *Keeper) SetAccount(ctx sdk.Context, addr common.Address, account statedb.Account) error { +func (k *Keeper) SetAccount(ctx sdk.Context, addr common.Address, account statedb.Account) (err error) { + ctx, span := ctx.StartSpan(tracer, "SetAccount", trace.WithAttributes( + attribute.String("address", addr.Hex()), + attribute.Int64("nonce", int64(account.Nonce)), //nolint:gosec // G115 + )) + defer func() { evmtrace.EndSpanErr(span, err) }() // update account acct := k.accountKeeper.GetAccount(ctx, addr.Bytes()) if acct == nil { @@ -154,7 +228,7 @@ func (k *Keeper) SetAccount(ctx sdk.Context, addr common.Address, account stated } k.accountKeeper.SetAccount(ctx, acct) - if err := k.SetBalance(ctx, addr, account.Balance); err != nil { + if err := k.SetAccountBalance(ctx, addr, account); err != nil { return err } @@ -164,12 +238,18 @@ func (k *Keeper) SetAccount(ctx sdk.Context, addr common.Address, account stated "nonce", account.Nonce, "codeHash", common.BytesToHash(account.CodeHash).Hex(), "balance", account.Balance, + "locked-balance", account.LockedBalanceSnapshot(), ) return nil } // SetState update contract storage. func (k *Keeper) SetState(ctx sdk.Context, addr common.Address, key common.Hash, value []byte) { + ctx, span := ctx.StartSpan(tracer, "SetState", trace.WithAttributes( + attribute.String("address", addr.Hex()), + attribute.String("key", key.Hex()), + )) + defer span.End() store := prefix.NewStore(ctx.KVStore(k.storeKey), types.AddressStoragePrefix(addr)) store.Set(key.Bytes(), value) @@ -183,6 +263,11 @@ func (k *Keeper) SetState(ctx sdk.Context, addr common.Address, key common.Hash, // DeleteState deletes the entry for the given key in the contract storage // at the defined contract address. func (k *Keeper) DeleteState(ctx sdk.Context, addr common.Address, key common.Hash) { + ctx, span := ctx.StartSpan(tracer, "DeleteState", trace.WithAttributes( + attribute.String("address", addr.Hex()), + attribute.String("key", key.Hex()), + )) + defer span.End() store := prefix.NewStore(ctx.KVStore(k.storeKey), types.AddressStoragePrefix(addr)) store.Delete(key.Bytes()) @@ -195,6 +280,11 @@ func (k *Keeper) DeleteState(ctx sdk.Context, addr common.Address, key common.Ha // SetCodeHash sets the code hash for the given contract address. func (k *Keeper) SetCodeHash(ctx sdk.Context, addrBytes, hashBytes []byte) { + ctx, span := ctx.StartSpan(tracer, "SetCodeHash", trace.WithAttributes( + attribute.String("address", common.BytesToAddress(addrBytes).Hex()), + attribute.String("code_hash", common.BytesToHash(hashBytes).Hex()), + )) + defer span.End() store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixCodeHash) store.Set(addrBytes, hashBytes) @@ -207,6 +297,8 @@ func (k *Keeper) SetCodeHash(ctx sdk.Context, addrBytes, hashBytes []byte) { // DeleteCodeHash deletes the code hash for the given contract address from the store. func (k *Keeper) DeleteCodeHash(ctx sdk.Context, addr common.Address) { + ctx, span := ctx.StartSpan(tracer, "DeleteCodeHash", trace.WithAttributes(attribute.String("address", addr.Hex()))) + defer span.End() store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixCodeHash) store.Delete(addr.Bytes()) @@ -219,6 +311,11 @@ func (k *Keeper) DeleteCodeHash(ctx sdk.Context, addr common.Address) { // SetCode sets the given contract code bytes for the corresponding code hash bytes key // in the code store. func (k *Keeper) SetCode(ctx sdk.Context, codeHash, code []byte) { + ctx, span := ctx.StartSpan(tracer, "SetCode", trace.WithAttributes( + attribute.String("code_hash", common.BytesToHash(codeHash).Hex()), + attribute.Int("code_size", len(code)), + )) + defer span.End() store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixCode) store.Set(codeHash, code) @@ -231,6 +328,8 @@ func (k *Keeper) SetCode(ctx sdk.Context, codeHash, code []byte) { // DeleteCode deletes the contract code for the given code hash bytes in // the corresponding store. func (k *Keeper) DeleteCode(ctx sdk.Context, codeHash []byte) { + ctx, span := ctx.StartSpan(tracer, "DeleteCode", trace.WithAttributes(attribute.String("code_hash", common.BytesToHash(codeHash).Hex()))) + defer span.End() store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixCode) store.Delete(codeHash) @@ -247,6 +346,8 @@ func (k *Keeper) DeleteCode(ctx sdk.Context, codeHash []byte) { // - remove the code hash // - remove auth account func (k *Keeper) DeleteAccount(ctx sdk.Context, addr common.Address) error { + ctx, span := ctx.StartSpan(tracer, "DeleteAccount", trace.WithAttributes(attribute.String("address", addr.Hex()))) + defer span.End() cosmosAddr := sdk.AccAddress(addr.Bytes()) acct := k.accountKeeper.GetAccount(ctx, cosmosAddr) if acct == nil { @@ -262,8 +363,7 @@ func (k *Keeper) DeleteAccount(ctx sdk.Context, addr common.Address) error { baseAccount := k.accountKeeper.GetAccount(ctx, cosmosAddr) k.accountKeeper.SetAccount(ctx, authtypes.NewBaseAccount(cosmosAddr, baseAccount.GetPubKey(), baseAccount.GetAccountNumber(), baseAccount.GetSequence())) - // clear balance - if err := k.SetBalance(ctx, addr, new(uint256.Int)); err != nil { + if err := k.SetBalanceWithLocked(ctx, addr, new(uint256.Int), new(big.Int)); err != nil { return err } diff --git a/x/vm/keeper/testdata/DelegationTarget.json b/x/vm/keeper/testdata/DelegationTarget.json new file mode 100644 index 00000000..9ed1bbaf --- /dev/null +++ b/x/vm/keeper/testdata/DelegationTarget.json @@ -0,0 +1,4 @@ +{ + "abi": "[{\"type\": \"receive\", \"stateMutability\": \"payable\"}, {\"type\": \"function\", \"name\": \"deploy\", \"inputs\": [{\"name\": \"bytecode\", \"type\": \"bytes\", \"internalType\": \"bytes\"}], \"outputs\": [{\"name\": \"deployed\", \"type\": \"address\", \"internalType\": \"address\"}], \"stateMutability\": \"nonpayable\"}, {\"type\": \"function\", \"name\": \"emitAllCodeHashes\", \"inputs\": [], \"outputs\": [], \"stateMutability\": \"nonpayable\"}, {\"type\": \"function\", \"name\": \"execute\", \"inputs\": [{\"name\": \"target\", \"type\": \"address\", \"internalType\": \"address\"}, {\"name\": \"data\", \"type\": \"bytes\", \"internalType\": \"bytes\"}], \"outputs\": [{\"name\": \"success\", \"type\": \"bool\", \"internalType\": \"bool\"}, {\"name\": \"result\", \"type\": \"bytes\", \"internalType\": \"bytes\"}], \"stateMutability\": \"payable\"}, {\"type\": \"function\", \"name\": \"getDeployedAt\", \"inputs\": [{\"name\": \"index\", \"type\": \"uint256\", \"internalType\": \"uint256\"}], \"outputs\": [{\"name\": \"addr\", \"type\": \"address\", \"internalType\": \"address\"}], \"stateMutability\": \"view\"}, {\"type\": \"function\", \"name\": \"getDeploymentCount\", \"inputs\": [], \"outputs\": [{\"name\": \"count\", \"type\": \"uint256\", \"internalType\": \"uint256\"}], \"stateMutability\": \"view\"}, {\"type\": \"function\", \"name\": \"selfdestructAll\", \"inputs\": [], \"outputs\": [], \"stateMutability\": \"nonpayable\"}, {\"type\": \"event\", \"name\": \"CodeHash\", \"inputs\": [{\"name\": \"deployed\", \"type\": \"address\", \"indexed\": true, \"internalType\": \"address\"}, {\"name\": \"codeHash\", \"type\": \"bytes32\", \"indexed\": false, \"internalType\": \"bytes32\"}], \"anonymous\": false}, {\"type\": \"event\", \"name\": \"ContractDeployed\", \"inputs\": [{\"name\": \"deployed\", \"type\": \"address\", \"indexed\": true, \"internalType\": \"address\"}, {\"name\": \"salt\", \"type\": \"bytes32\", \"indexed\": false, \"internalType\": \"bytes32\"}], \"anonymous\": false}, {\"type\": \"event\", \"name\": \"ContractDestroyed\", \"inputs\": [{\"name\": \"destroyed\", \"type\": \"address\", \"indexed\": true, \"internalType\": \"address\"}, {\"name\": \"index\", \"type\": \"uint256\", \"indexed\": false, \"internalType\": \"uint256\"}, {\"name\": \"success\", \"type\": \"bool\", \"indexed\": false, \"internalType\": \"bool\"}], \"anonymous\": false}]", + "bin": "6080604052348015600e575f5ffd5b50610ac18061001c5f395ff3fe608060405260043610610057575f3560e01c8062774360146100625780631cff79cd1461009e5780633ea4903b146100cf5780638118a1511461010b578063b3eedf1214610121578063d0f97d991461014b5761005e565b3661005e57005b5f5ffd5b34801561006d575f5ffd5b506100886004803603810190610083919061067e565b610161565b6040516100959190610704565b60405180910390f35b6100b860048036038101906100b391906107a4565b61027b565b6040516100c692919061087b565b60405180910390f35b3480156100da575f5ffd5b506100f560048036038101906100f091906108dc565b6102f6565b6040516101029190610704565b60405180910390f35b348015610116575f5ffd5b5061011f610300565b005b34801561012c575f5ffd5b5061013561046c565b6040516101429190610916565b60405180910390f35b348015610156575f5ffd5b5061015f610494565b005b5f8151602083015ff090507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff54818155600181017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff55505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610226576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161021d90610989565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167fb085ff794f342ed78acc7791d067e28a931e614b52476c0305795e1ff0a154bc5f5f1b60405161026e91906109bf565b60405180910390a2919050565b5f60608473ffffffffffffffffffffffffffffffffffffffff163485856040516102a6929190610a06565b5f6040518083038185875af1925050503d805f81146102e0576040519150601f19603f3d011682016040523d82523d5f602084013e6102e5565b606091505b508092508193505050935093915050565b5f81549050919050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5490505f5f90505b81811015610468575f815490505f8173ffffffffffffffffffffffffffffffffffffffff16639cb8a26a60e01b604051602401604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516103c79190610a4e565b5f604051808303815f865af19150503d805f8114610400576040519150601f19603f3d011682016040523d82523d5f602084013e610405565b606091505b505090508173ffffffffffffffffffffffffffffffffffffffff167fa06b1f3a43650cf222ac05b32cc9ac448734acda4a913477d2c12e21a0302fba8483604051610451929190610a64565b60405180910390a25050808060010191505061032a565b5050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff54905090565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5490505f5f90505b8181101561052d575f815490505f813f90508173ffffffffffffffffffffffffffffffffffffffff167fa81105b49ce4f9802c1888a827171628bb0a7cb5b6c3295b657f9071bad492388260405161051691906109bf565b60405180910390a2505080806001019150506104be565b5050565b5f604051905090565b5f5ffd5b5f5ffd5b5f5ffd5b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6105908261054a565b810181811067ffffffffffffffff821117156105af576105ae61055a565b5b80604052505050565b5f6105c1610531565b90506105cd8282610587565b919050565b5f67ffffffffffffffff8211156105ec576105eb61055a565b5b6105f58261054a565b9050602081019050919050565b828183375f83830152505050565b5f61062261061d846105d2565b6105b8565b90508281526020810184848401111561063e5761063d610546565b5b610649848285610602565b509392505050565b5f82601f83011261066557610664610542565b5b8135610675848260208601610610565b91505092915050565b5f602082840312156106935761069261053a565b5b5f82013567ffffffffffffffff8111156106b0576106af61053e565b5b6106bc84828501610651565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6106ee826106c5565b9050919050565b6106fe816106e4565b82525050565b5f6020820190506107175f8301846106f5565b92915050565b610726816106e4565b8114610730575f5ffd5b50565b5f813590506107418161071d565b92915050565b5f5ffd5b5f5ffd5b5f5f83601f84011261076457610763610542565b5b8235905067ffffffffffffffff81111561078157610780610747565b5b60208301915083600182028301111561079d5761079c61074b565b5b9250929050565b5f5f5f604084860312156107bb576107ba61053a565b5b5f6107c886828701610733565b935050602084013567ffffffffffffffff8111156107e9576107e861053e565b5b6107f58682870161074f565b92509250509250925092565b5f8115159050919050565b61081581610801565b82525050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f61084d8261081b565b6108578185610825565b9350610867818560208601610835565b6108708161054a565b840191505092915050565b5f60408201905061088e5f83018561080c565b81810360208301526108a08184610843565b90509392505050565b5f819050919050565b6108bb816108a9565b81146108c5575f5ffd5b50565b5f813590506108d6816108b2565b92915050565b5f602082840312156108f1576108f061053a565b5b5f6108fe848285016108c8565b91505092915050565b610910816108a9565b82525050565b5f6020820190506109295f830184610907565b92915050565b5f82825260208201905092915050565b7f4465706c6f796d656e74206661696c65640000000000000000000000000000005f82015250565b5f61097360118361092f565b915061097e8261093f565b602082019050919050565b5f6020820190508181035f8301526109a081610967565b9050919050565b5f819050919050565b6109b9816109a7565b82525050565b5f6020820190506109d25f8301846109b0565b92915050565b5f81905092915050565b5f6109ed83856109d8565b93506109fa838584610602565b82840190509392505050565b5f610a128284866109e2565b91508190509392505050565b5f610a288261081b565b610a3281856109d8565b9350610a42818560208601610835565b80840191505092915050565b5f610a598284610a1e565b915081905092915050565b5f604082019050610a775f830185610907565b610a84602083018461080c565b939250505056fea26469706673582212209fc5cdc35c5653b10dabe5e5a8b58736f0a116cad597db3d6f8b09b9915de12964736f6c634300081e0033" +} \ No newline at end of file diff --git a/x/vm/keeper/testdata/MaliciousDeployer.json b/x/vm/keeper/testdata/MaliciousDeployer.json new file mode 100644 index 00000000..e3e36993 --- /dev/null +++ b/x/vm/keeper/testdata/MaliciousDeployer.json @@ -0,0 +1,4 @@ +{ + "abi": "[{\"type\": \"constructor\", \"inputs\": [{\"name\": \"delegatedEOA\", \"type\": \"address\", \"internalType\": \"address\"}, {\"name\": \"numContracts\", \"type\": \"uint256\", \"internalType\": \"uint256\"}, {\"name\": \"step\", \"type\": \"uint256\", \"internalType\": \"uint256\"}], \"stateMutability\": \"nonpayable\"}, {\"type\": \"function\", \"name\": \"deployedContracts\", \"inputs\": [{\"name\": \"\", \"type\": \"uint256\", \"internalType\": \"uint256\"}], \"outputs\": [{\"name\": \"\", \"type\": \"address\", \"internalType\": \"address\"}], \"stateMutability\": \"view\"}, {\"type\": \"function\", \"name\": \"deployer\", \"inputs\": [], \"outputs\": [{\"name\": \"\", \"type\": \"address\", \"internalType\": \"address\"}], \"stateMutability\": \"view\"}, {\"type\": \"function\", \"name\": \"getDeployedContracts\", \"inputs\": [], \"outputs\": [{\"name\": \"\", \"type\": \"address[]\", \"internalType\": \"address[]\"}], \"stateMutability\": \"view\"}, {\"type\": \"function\", \"name\": \"getDeployedCount\", \"inputs\": [], \"outputs\": [{\"name\": \"\", \"type\": \"uint256\", \"internalType\": \"uint256\"}], \"stateMutability\": \"view\"}, {\"type\": \"event\", \"name\": \"CallbackExecuted\", \"inputs\": [{\"name\": \"delegatedEOA\", \"type\": \"address\", \"indexed\": true, \"internalType\": \"address\"}, {\"name\": \"success\", \"type\": \"bool\", \"indexed\": false, \"internalType\": \"bool\"}], \"anonymous\": false}, {\"type\": \"event\", \"name\": \"ContractDeployedViaCallback\", \"inputs\": [{\"name\": \"deployed\", \"type\": \"address\", \"indexed\": true, \"internalType\": \"address\"}], \"anonymous\": false}]", + "bin": "60a060405234801561000f575f5ffd5b50604051610fcd380380610fcd833981810160405281019061003191906104f3565b3373ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250505f5f90505b82811015610296576060600183036100a7576040518060200161008c90610448565b6020820181038252601f19601f8201166040525090506100ce565b604051806020016100b790610455565b6020820181038252601f19601f8201166040525090505b5f5f8673ffffffffffffffffffffffffffffffffffffffff166277436060e01b846040516024016100ff91906105b3565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610169919061060d565b5f604051808303815f865af19150503d805f81146101a2576040519150601f19603f3d011682016040523d82523d5f602084013e6101a7565b606091505b50915091508673ffffffffffffffffffffffffffffffffffffffff167fe52b6c495c617798fed9610421afb7309762a6925ea97edd107a2f424957044e836040516101f2919061063d565b60405180910390a25f82801561020a57506020825110155b1561028557818060200190518101906102239190610691565b90505f81908060018154018082558091505060019003905f5260205f20015f9091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50505050808060010191505061006a565b508273ffffffffffffffffffffffffffffffffffffffff1663d0f97d9960e01b604051602401604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610326919061060d565b5f604051808303815f865af19150503d805f811461035f576040519150601f19603f3d011682016040523d82523d5f602084013e610364565b606091505b50505060018103610440578273ffffffffffffffffffffffffffffffffffffffff16638118a15160e01b604051602401604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516103fe919061060d565b5f604051808303815f865af19150503d805f8114610437576040519150601f19603f3d011682016040523d82523d5f602084013e61043c565b606091505b5050505b5050506106bc565b61029380610a8e83390190565b6102ac80610d2183390190565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61048f82610466565b9050919050565b61049f81610485565b81146104a9575f5ffd5b50565b5f815190506104ba81610496565b92915050565b5f819050919050565b6104d2816104c0565b81146104dc575f5ffd5b50565b5f815190506104ed816104c9565b92915050565b5f5f5f6060848603121561050a57610509610462565b5b5f610517868287016104ac565b9350506020610528868287016104df565b9250506040610539868287016104df565b9150509250925092565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61058582610543565b61058f818561054d565b935061059f81856020860161055d565b6105a88161056b565b840191505092915050565b5f6020820190508181035f8301526105cb818461057b565b905092915050565b5f81905092915050565b5f6105e782610543565b6105f181856105d3565b935061060181856020860161055d565b80840191505092915050565b5f61061882846105dd565b915081905092915050565b5f8115159050919050565b61063781610623565b82525050565b5f6020820190506106505f83018461062e565b92915050565b5f61066082610466565b9050919050565b61067081610656565b811461067a575f5ffd5b50565b5f8151905061068b81610667565b92915050565b5f602082840312156106a6576106a5610462565b5b5f6106b38482850161067d565b91505092915050565b6080516103ba6106d45f395f6101a901526103ba5ff3fe608060405234801561000f575f5ffd5b506004361061004a575f3560e01c80630ff654141461004e5780639ad1ee101461006c578063aa9a068f1461009c578063d5f39488146100ba575b5f5ffd5b6100566100d8565b60405161006391906101e3565b60405180910390f35b6100866004803603810190610081919061022a565b6100e3565b6040516100939190610294565b60405180910390f35b6100a461011d565b6040516100b19190610364565b60405180910390f35b6100c26101a7565b6040516100cf9190610294565b60405180910390f35b5f5f80549050905090565b5f81815481106100f1575f80fd5b905f5260205f20015f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60605f80548060200260200160405190810160405280929190818152602001828054801561019d57602002820191905f5260205f20905b815f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610154575b5050505050905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b5f819050919050565b6101dd816101cb565b82525050565b5f6020820190506101f65f8301846101d4565b92915050565b5f5ffd5b610209816101cb565b8114610213575f5ffd5b50565b5f8135905061022481610200565b92915050565b5f6020828403121561023f5761023e6101fc565b5b5f61024c84828501610216565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61027e82610255565b9050919050565b61028e81610274565b82525050565b5f6020820190506102a75f830184610285565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b6102df81610274565b82525050565b5f6102f083836102d6565b60208301905092915050565b5f602082019050919050565b5f610312826102ad565b61031c81856102b7565b9350610327836102c7565b805f5b8381101561035757815161033e88826102e5565b9750610349836102fc565b92505060018101905061032a565b5085935050505092915050565b5f6020820190508181035f83015261037c8184610308565b90509291505056fea26469706673582212209fbc76075ede0f5b7fedb33456302dacc566b247bfe95b68589a12a4ccd1915764736f6c634300081e003360a0604052348015600e575f5ffd5b503373ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250506080516102336100605f395f818160b2015260e401526102335ff3fe608060405234801561000f575f5ffd5b506004361061004a575f3560e01c806302d05d3f1461004e5780633fa4f2451461006c578063552410771461008a5780639cb8a26a146100a6575b5f5ffd5b6100566100b0565b604051610063919061015a565b60405180910390f35b6100746100d4565b604051610081919061018b565b60405180910390f35b6100a4600480360381019061009f91906101d2565b6100d9565b005b6100ae6100e2565b005b7f000000000000000000000000000000000000000000000000000000000000000081565b5f5481565b805f8190555050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16ff5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6101448261011b565b9050919050565b6101548161013a565b82525050565b5f60208201905061016d5f83018461014b565b92915050565b5f819050919050565b61018581610173565b82525050565b5f60208201905061019e5f83018461017c565b92915050565b5f5ffd5b6101b181610173565b81146101bb575f5ffd5b50565b5f813590506101cc816101a8565b92915050565b5f602082840312156101e7576101e66101a4565b5b5f6101f4848285016101be565b9150509291505056fea264697066735822122041920cba5afa273ee01b9c4ae578a6d4cd575fd1499dff5db5ece09231598faa64736f6c634300081e003360a0604052348015600e575f5ffd5b503373ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff168152505060805161025261005a5f395f609f01526102525ff3fe608060405234801561000f575f5ffd5b506004361061003f575f3560e01c806302d05d3f14610043578063057ece53146100615780633fa4f2451461007f575b5f5ffd5b61004b61009d565b6040516100589190610142565b60405180910390f35b6100696100c1565b60405161007691906101cb565b60405180910390f35b6100876100fe565b6040516100949190610203565b60405180910390f35b7f000000000000000000000000000000000000000000000000000000000000000081565b60606040518060400160405280601881526020017f4920616d207468652066696e616c20636f6e7472616374210000000000000000815250905090565b5f5481565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61012c82610103565b9050919050565b61013c81610122565b82525050565b5f6020820190506101555f830184610133565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61019d8261015b565b6101a78185610165565b93506101b7818560208601610175565b6101c081610183565b840191505092915050565b5f6020820190508181035f8301526101e38184610193565b905092915050565b5f819050919050565b6101fd816101eb565b82525050565b5f6020820190506102165f8301846101f4565b9291505056fea2646970667358221220972c3dac982ebcfc8e74b849f78cfe04b580e9b76aad531f727c25b21494491564736f6c634300081e0033" +} \ No newline at end of file diff --git a/x/vm/keeper/testdata/contracts.go b/x/vm/keeper/testdata/contracts.go index d17bb849..1347fcc9 100644 --- a/x/vm/keeper/testdata/contracts.go +++ b/x/vm/keeper/testdata/contracts.go @@ -12,3 +12,11 @@ func LoadERC20Contract() (evmtypes.CompiledContract, error) { func LoadMessageCallContract() (evmtypes.CompiledContract, error) { return contractutils.LegacyLoadContractFromJSONFile("MessageCallContract.json") } + +func LoadDelegationTargetContract() (evmtypes.CompiledContract, error) { + return contractutils.LegacyLoadContractFromJSONFile("DelegationTarget.json") +} + +func LoadMaliciousDeployerContract() (evmtypes.CompiledContract, error) { + return contractutils.LegacyLoadContractFromJSONFile("MaliciousDeployer.json") +} diff --git a/x/vm/keeper/utils.go b/x/vm/keeper/utils.go index 7a8728c6..be843cf8 100644 --- a/x/vm/keeper/utils.go +++ b/x/vm/keeper/utils.go @@ -3,6 +3,8 @@ package keeper import ( "github.com/ethereum/go-ethereum/common" ethtypes "github.com/ethereum/go-ethereum/core/types" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -11,6 +13,10 @@ import ( // It checks if the account has associated code and ensures that // the code is not a delegated contract (EIP-7702). func (k *Keeper) IsContract(ctx sdk.Context, addr common.Address) bool { + ctx, span := ctx.StartSpan(tracer, "IsContract", trace.WithAttributes( + attribute.String("address", addr.Hex()), + )) + defer span.End() codeHash := k.GetCodeHash(ctx, addr) code := k.GetCode(ctx, codeHash) diff --git a/x/vm/module.go b/x/vm/module.go index ac01dae4..27106cf3 100644 --- a/x/vm/module.go +++ b/x/vm/module.go @@ -136,12 +136,18 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterQueryServer(cfg.QueryServer(), am.keeper) } +// HydrateGlobals restores global EVM variables from KV store after a node restart (post-genesis). +func (am AppModule) HydrateGlobals(goCtx context.Context) { + ctx := sdk.UnwrapSDKContext(goCtx) + if ctx.BlockHeight() > 1 { + am.hydrateGlobals(ctx, "HydrateGlobals") + } +} + func (am AppModule) PreBlock(goCtx context.Context) (appmodule.ResponsePreBlock, error) { ctx := sdk.UnwrapSDKContext(goCtx) - coinInfo := am.keeper.GetEvmCoinInfo(ctx) - am.initializer.Do(func() { - SetGlobalConfigVariables(coinInfo) - }) + am.hydrateGlobals(ctx, "PreBlock") + return &sdk.ResponsePreBlock{ConsensusParamsChanged: false}, nil } @@ -193,6 +199,14 @@ func (am AppModule) IsAppModule() {} // IsOnePerModuleType implements the depinject.OnePerModuleType interface. func (am AppModule) IsOnePerModuleType() {} +func (am AppModule) hydrateGlobals(ctx sdk.Context, origin string) { + coinInfo := am.keeper.GetEvmCoinInfo(ctx) + am.initializer.Do(func() { + SetGlobalConfigVariables(coinInfo) + ctx.Logger().With("module", "vm", "origin", origin).Info("Restored global evm variables from store") + }) +} + // setBaseDenom registers the display denom and base denom and sets the // base denom for the chain. The function registered different values based on // the EvmCoinInfo to allow different configurations in mainnet and testnet. @@ -219,9 +233,11 @@ func SetGlobalConfigVariables(coinInfo types.EvmCoinInfo) { } configurator := types.NewEVMConfigurator() + + // we're using the 18 decimals default for the example chain + // note that .Configure() sets global evmCoinInfo err := configurator. WithExtendedEips(types.DefaultCosmosEVMActivators). - // NOTE: we're using the 18 decimals default for the example chain WithEVMCoinInfo(coinInfo). Configure() if err != nil { diff --git a/x/vm/runner/runner.go b/x/vm/runner/runner.go new file mode 100644 index 00000000..c0e40610 --- /dev/null +++ b/x/vm/runner/runner.go @@ -0,0 +1,46 @@ +// Package runner installs a baseapp TxRunner wrapped with the EVM module's +// post-execution log-index fix-up (evmtypes.PatchTxResponses). +package runner + +import ( + "context" + + abci "github.com/cometbft/cometbft/abci/types" + + evmtypes "github.com/cosmos/evm/x/vm/types" + + "github.com/cosmos/cosmos-sdk/baseapp" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// SetRunner installs inner as bApp's block tx runner, wrapped so +// PatchTxResponses runs once per block. Works for sequential and BlockSTM +// runners alike; the SDK's SetBlockSTMTxRunner name is the same setter for +// both. +func SetRunner(bApp *baseapp.BaseApp, inner sdk.TxRunner) { + bApp.SetBlockSTMTxRunner(Wrap(inner)) +} + +// Wrap returns a TxRunner that delegates to inner and then applies +// PatchTxResponses to the block results. +func Wrap(inner sdk.TxRunner) sdk.TxRunner { + return &patchingRunner{inner: inner} +} + +type patchingRunner struct { + inner sdk.TxRunner +} + +func (r *patchingRunner) Run( + ctx context.Context, + ms storetypes.MultiStore, + txs [][]byte, + deliverTx sdk.DeliverTxFunc, +) ([]*abci.ExecTxResult, error) { + results, err := r.inner.Run(ctx, ms, txs, deliverTx) + if err != nil { + return nil, err + } + return evmtypes.PatchTxResponses(results) +} diff --git a/x/vm/runner/runner_test.go b/x/vm/runner/runner_test.go new file mode 100644 index 00000000..64c71c3e --- /dev/null +++ b/x/vm/runner/runner_test.go @@ -0,0 +1,120 @@ +package runner_test + +import ( + "context" + "errors" + "testing" + + "github.com/stretchr/testify/require" + + abci "github.com/cometbft/cometbft/abci/types" + + "github.com/cosmos/evm/x/vm/runner" + evmtypes "github.com/cosmos/evm/x/vm/types" + "github.com/cosmos/gogoproto/proto" + + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type fakeRunner struct { + results []*abci.ExecTxResult + err error + calls int +} + +func (r *fakeRunner) Run( + _ context.Context, + _ storetypes.MultiStore, + _ [][]byte, + _ sdk.DeliverTxFunc, +) ([]*abci.ExecTxResult, error) { + r.calls++ + if r.err != nil { + return nil, r.err + } + return r.results, nil +} + +func encodeEthResponse(t *testing.T, hash string, logs []*evmtypes.Log) []byte { + t.Helper() + resp := &evmtypes.MsgEthereumTxResponse{Hash: hash, Logs: logs} + anyResp, err := codectypes.NewAnyWithValue(resp) + require.NoError(t, err) + txMsgData := &sdk.TxMsgData{MsgResponses: []*codectypes.Any{anyResp}} + data, err := proto.Marshal(txMsgData) + require.NoError(t, err) + return data +} + +func TestWrap_PatchesLogIndices(t *testing.T) { + inner := &fakeRunner{ + results: []*abci.ExecTxResult{ + { + Code: 0, + Data: encodeEthResponse(t, "0xaa", []*evmtypes.Log{ + {TxIndex: 0, Index: 0}, + {TxIndex: 0, Index: 1}, + }), + }, + { + Code: 0, + Data: encodeEthResponse(t, "0xbb", []*evmtypes.Log{ + {TxIndex: 1, Index: 0}, + }), + }, + }, + } + + wrapped := runner.Wrap(inner) + out, err := wrapped.Run(context.Background(), nil, nil, nil) + require.NoError(t, err) + require.Equal(t, 1, inner.calls) + require.Len(t, out, 2) + + gotLogs := func(data []byte) []*evmtypes.Log { + var txMsgData sdk.TxMsgData + require.NoError(t, proto.Unmarshal(data, &txMsgData)) + require.Len(t, txMsgData.MsgResponses, 1) + var resp evmtypes.MsgEthereumTxResponse + require.NoError(t, proto.Unmarshal(txMsgData.MsgResponses[0].Value, &resp)) + return resp.Logs + } + + logs0 := gotLogs(out[0].Data) + require.Len(t, logs0, 2) + require.Equal(t, uint64(0), logs0[0].TxIndex) + require.Equal(t, uint64(0), logs0[0].Index) + require.Equal(t, uint64(0), logs0[1].TxIndex) + require.Equal(t, uint64(1), logs0[1].Index) + + logs1 := gotLogs(out[1].Data) + require.Len(t, logs1, 1) + require.Equal(t, uint64(1), logs1[0].TxIndex) + require.Equal(t, uint64(2), logs1[0].Index) +} + +func TestWrap_PropagatesInnerError(t *testing.T) { + want := errors.New("inner boom") + wrapped := runner.Wrap(&fakeRunner{err: want}) + out, err := wrapped.Run(context.Background(), nil, nil, nil) + require.ErrorIs(t, err, want) + require.Nil(t, out) +} + +func TestWrap_NoEthResponses(t *testing.T) { + raw := []byte{0x01, 0x02, 0x03} + inner := &fakeRunner{ + results: []*abci.ExecTxResult{ + {Code: 0, Data: nil}, + {Code: 1, Data: raw}, + }, + } + wrapped := runner.Wrap(inner) + out, err := wrapped.Run(context.Background(), nil, nil, nil) + require.NoError(t, err) + require.Len(t, out, 2) + require.Nil(t, out[0].Data) + require.Equal(t, raw, out[1].Data) +} diff --git a/x/vm/runner/tx_index_contract_test.go b/x/vm/runner/tx_index_contract_test.go new file mode 100644 index 00000000..8a51c5fb --- /dev/null +++ b/x/vm/runner/tx_index_contract_test.go @@ -0,0 +1,103 @@ +package runner_test + +import ( + "context" + "sync" + "testing" + + "github.com/stretchr/testify/require" + + abci "github.com/cometbft/cometbft/abci/types" + + dbm "github.com/cosmos/cosmos-db" + + "cosmossdk.io/log/v2" + + "github.com/cosmos/cosmos-sdk/baseapp/txnrunner" + "github.com/cosmos/cosmos-sdk/store/v2" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// Guards the SDK TxRunner contract x/vm relies on: deliverTx's txIndex must +// match the tx's slice position (BaseApp forwards it to ctx.TxIndex()). + +func newTestMultiStore(t *testing.T, key storetypes.StoreKey) storetypes.MultiStore { + t.Helper() + db := dbm.NewMemDB() + cms := store.NewCommitMultiStore(db, log.NewNopLogger()) + cms.MountStoreWithDB(key, storetypes.StoreTypeIAVL, db) + require.NoError(t, cms.LoadLatestVersion()) + return cms +} + +func noopTxDecoder(_ []byte) (sdk.Tx, error) { return nil, nil } + +// DefaultRunner: txIndex == slice position, exactly once per tx. +func TestDefaultRunner_PreservesBlockOrderIndex(t *testing.T) { + r := txnrunner.NewDefaultRunner(noopTxDecoder) + + const n = 16 + txs := make([][]byte, n) + for i := range txs { + txs[i] = []byte{byte(i)} + } + + seen := make([]int, n) + deliverTx := func(tx []byte, _ sdk.Tx, _ storetypes.MultiStore, txIndex int, _ map[string]any) *abci.ExecTxResult { + require.Equalf(t, int(tx[0]), txIndex, + "DefaultRunner must pass original block-order index; tx payload %d got txIndex %d", tx[0], txIndex) + seen[txIndex]++ + return &abci.ExecTxResult{Code: 0} + } + + results, err := r.Run(context.Background(), nil, txs, deliverTx) + require.NoError(t, err) + require.Len(t, results, n) + for i, c := range seen { + require.Equalf(t, 1, c, "tx %d executed %d times, want exactly 1", i, c) + } +} + +// STMRunner: txIndex == slice position under parallel execution and +// incarnation retries. +func TestSTMRunner_PreservesBlockOrderIndex(t *testing.T) { + key := storetypes.NewKVStoreKey("test") + ms := newTestMultiStore(t, key) + + coinDenom := func(_ storetypes.MultiStore) string { return "stake" } + r := txnrunner.NewSTMRunner( + noopTxDecoder, + []storetypes.StoreKey{key}, + 4, + false, + coinDenom, + ) + + const n = 32 + txs := make([][]byte, n) + for i := range txs { + txs[i] = []byte{byte(i)} + } + + var ( + mu sync.Mutex + runs = make(map[int]int, n) + ) + deliverTx := func(tx []byte, _ sdk.Tx, _ storetypes.MultiStore, txIndex int, _ map[string]any) *abci.ExecTxResult { + require.Equalf(t, int(tx[0]), txIndex, + "STMRunner must pass original block-order index; tx payload %d got txIndex %d", tx[0], txIndex) + mu.Lock() + runs[txIndex]++ + mu.Unlock() + return &abci.ExecTxResult{Code: 0} + } + + results, err := r.Run(context.Background(), ms, txs, deliverTx) + require.NoError(t, err) + require.Len(t, results, n) + + for i := 0; i < n; i++ { + require.GreaterOrEqualf(t, runs[i], 1, "tx %d never executed under STM", i) + } +} diff --git a/x/vm/statedb/balance_events_test.go b/x/vm/statedb/balance_events_test.go new file mode 100644 index 00000000..a50dbf20 --- /dev/null +++ b/x/vm/statedb/balance_events_test.go @@ -0,0 +1,113 @@ +package statedb + +import ( + "testing" + + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// mockSnapshotter is a simple mock implementation of the Snapshotter interface for testing. +type mockSnapshotter struct { + snapshots []int + current int +} + +func newMockSnapshotter() *mockSnapshotter { + return &mockSnapshotter{ + snapshots: []int{}, + current: 0, + } +} + +func (m *mockSnapshotter) Snapshot() int { + id := m.current + m.snapshots = append(m.snapshots, id) + m.current++ + return id +} + +func (m *mockSnapshotter) RevertToSnapshot(snapshot int) { + // Find the snapshot index + for i, s := range m.snapshots { + if s == snapshot { + m.snapshots = m.snapshots[:i+1] + m.current = snapshot + 1 + return + } + } +} + +// TestRevertToSnapshot_ProcessedEventsInvariant verifies the invariant: +// "After any revert, processedEventsCount <= current event count" +// This tests cacheCtx event manager behavior during EVM execution with precompile calls and reverts. +func TestRevertToSnapshot_ProcessedEventsInvariant(t *testing.T) { + // Test each revert scenario independently since reverting invalidates future snapshots + testCases := []struct { + name string + numPrecompiles int + revertToIndex int + expectedEvents int + }{ + {"revert to 5 precompile calls", 10, 5, 5}, + {"revert to 2 precompile calls", 10, 2, 2}, + {"revert to 0 precompile calls", 10, 0, 0}, + {"revert to 8 precompile calls", 10, 8, 8}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + mockSnap := newMockSnapshotter() + stateDB := &StateDB{ + validRevisions: []revision{}, + nextRevisionID: 0, + journal: newJournal(), + snapshotter: mockSnap, + } + + ctx := sdk.Context{}.WithEventManager(sdk.NewEventManager()) + cacheCtx := sdk.Context{}.WithEventManager(sdk.NewEventManager()) + stateDB.ctx = ctx + stateDB.cacheCtx = cacheCtx + stateDB.writeCache = func() {} // Simulate cache exists (after first precompile call) + + // Snapshot with 0 events (before any precompile calls) + snapshots := []int{stateDB.Snapshot()} + + // Simulate precompile calls - each emits an event + for i := 0; i < tc.numPrecompiles; i++ { + // Create multi-store snapshot for precompile journal entry + multiStoreSnapshot := mockSnap.Snapshot() + + // Add precompile journal entry (captures events before precompile) + err := stateDB.AddPrecompileFn(multiStoreSnapshot) + require.NoError(t, err) + + // Emit event during "precompile execution" + cacheCtx.EventManager().EmitEvent(sdk.NewEvent("test", sdk.NewAttribute("count", string(rune(i))))) + + // Update processed events count (simulates FlushToCacheCtx) + stateDB.processedEventsCount = len(cacheCtx.EventManager().Events()) + + // Take snapshot after precompile + snap := stateDB.Snapshot() + snapshots = append(snapshots, snap) + } + + // Revert to the target snapshot + stateDB.RevertToSnapshot(snapshots[tc.revertToIndex]) + + currentEventCount := len(cacheCtx.EventManager().Events()) + require.Equal(t, tc.expectedEvents, currentEventCount, "event count mismatch after revert") + + // Verify invariant: processedEventsCount <= current event count + require.LessOrEqual(t, stateDB.processedEventsCount, currentEventCount, + "processedEventsCount %d exceeds current event count %d", + stateDB.processedEventsCount, currentEventCount) + + require.Equal(t, tc.expectedEvents, stateDB.processedEventsCount, + "processedEventsCount should match expected event count") + }) + } +} diff --git a/x/vm/statedb/commit_atomicity_test.go b/x/vm/statedb/commit_atomicity_test.go new file mode 100644 index 00000000..2f8d122b --- /dev/null +++ b/x/vm/statedb/commit_atomicity_test.go @@ -0,0 +1,142 @@ +package statedb_test + +import ( + "errors" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/tracing" + "github.com/holiman/uint256" + "github.com/stretchr/testify/require" + + "github.com/cosmos/evm/x/vm/statedb" + + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" + "github.com/cosmos/cosmos-sdk/testutil" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// atomicTestKeeper routes writes through ctx's real KVStore, unlike the +// in-memory-map mocks elsewhere in this package, so a write discarded via +// CacheContext is actually observable as absent. +type atomicTestKeeper struct { + key *storetypes.KVStoreKey + errAddr common.Address +} + +var _ statedb.Keeper = &atomicTestKeeper{} + +func (k *atomicTestKeeper) store(ctx sdk.Context) storetypes.KVStore { return ctx.KVStore(k.key) } + +func (k *atomicTestKeeper) IsBaseAccountOrEmpty(_ sdk.Context, _ common.Address) bool { + return true +} + +func (k *atomicTestKeeper) GetAccount(ctx sdk.Context, addr common.Address) *statedb.Account { + bz := k.store(ctx).Get(addr.Bytes()) + if bz == nil { + return nil + } + return &statedb.Account{Balance: new(uint256.Int).SetBytes(bz)} +} + +func (k *atomicTestKeeper) SetAccount(ctx sdk.Context, addr common.Address, acc statedb.Account) error { + if addr == k.errAddr { + return errors.New("blocked") + } + k.store(ctx).Set(addr.Bytes(), acc.Balance.Bytes()) + return nil +} + +func (k *atomicTestKeeper) DeleteAccount(ctx sdk.Context, addr common.Address) error { + if addr == k.errAddr { + return errors.New("blocked") + } + k.store(ctx).Delete(addr.Bytes()) + return nil +} + +func (k *atomicTestKeeper) GetState(sdk.Context, common.Address, common.Hash) common.Hash { + return common.Hash{} +} +func (k *atomicTestKeeper) GetCode(sdk.Context, common.Hash) []byte { return nil } +func (k *atomicTestKeeper) GetCodeHash(sdk.Context, common.Address) common.Hash { return common.Hash{} } +func (k *atomicTestKeeper) ForEachStorage(sdk.Context, common.Address, func(common.Hash, common.Hash) bool) { +} +func (k *atomicTestKeeper) DeleteState(sdk.Context, common.Address, common.Hash) {} +func (k *atomicTestKeeper) SetState(sdk.Context, common.Address, common.Hash, []byte) {} +func (k *atomicTestKeeper) DeleteCode(sdk.Context, []byte) {} +func (k *atomicTestKeeper) SetCode(sdk.Context, []byte, []byte) {} + +func (k *atomicTestKeeper) KVStoreKeys() map[string]storetypes.StoreKey { + return map[string]storetypes.StoreKey{k.key.Name(): k.key} +} + +// TestCommitAtomicity commits a dirty set sorted [credit, blocked, debit]. A +// late failure on blocked must discard the whole commit, including credit, +// which a non-atomic commit would already have written. +func TestCommitAtomicity(t *testing.T) { + credit := common.BigToAddress(big.NewInt(10)) + blocked := common.BigToAddress(big.NewInt(50)) + debit := common.BigToAddress(big.NewInt(90)) + precompileAddr := common.BigToAddress(big.NewInt(1)) // written via cacheCtx, bypassing the journal + + setup := func(name string, errAddr common.Address) *statedb.StateDB { + key := storetypes.NewKVStoreKey(name) + tkey := storetypes.NewTransientStoreKey(name + "_t") + ctx := testutil.DefaultContext(key, tkey).WithEventManager(sdk.NewEventManager()) + return statedb.New(ctx, &atomicTestKeeper{key: key, errAddr: errAddr}, emptyTxConfig) + } + seed := func(db *statedb.StateDB) { + db.AddBalance(credit, uint256.NewInt(1_000_000), tracing.BalanceChangeUnspecified) + db.AddBalance(blocked, uint256.NewInt(1), tracing.BalanceChangeUnspecified) + db.AddBalance(debit, uint256.NewInt(1), tracing.BalanceChangeUnspecified) + } + // persisted reads through db's own keeper/ctx, bypassing db's in-memory + // cache, to check what actually reached the real store. + persisted := func(db *statedb.StateDB, addr common.Address) *statedb.Account { + return db.Keeper().GetAccount(db.GetContext(), addr) + } + // stageViaPrecompile writes directly through the cache context the way a + // real precompile does, bypassing the journal entirely. + stageViaPrecompile := func(t *testing.T, db *statedb.StateDB) { + t.Helper() + cacheCtx, err := db.GetCacheContext() + require.NoError(t, err) + require.NoError(t, db.Keeper().SetAccount(cacheCtx, precompileAddr, statedb.Account{Balance: uint256.NewInt(7)})) + } + + t.Run("late failure discards the whole commit", func(t *testing.T) { + db := setup("fail", blocked) + seed(db) + require.Error(t, db.Commit()) + require.Nil(t, persisted(db, credit)) + }) + + t.Run("late failure discards precompile-staged writes too", func(t *testing.T) { + db := setup("fail_precompile", blocked) + stageViaPrecompile(t, db) + seed(db) + require.Error(t, db.Commit()) + require.Nil(t, persisted(db, credit)) + require.Nil(t, persisted(db, precompileAddr)) + }) + + t.Run("success still persists everything", func(t *testing.T) { + db := setup("ok", common.Address{}) + seed(db) + require.NoError(t, db.Commit()) + require.Equal(t, uint256.NewInt(1_000_000), persisted(db, credit).Balance) + require.Equal(t, uint256.NewInt(1), persisted(db, debit).Balance) + }) + + t.Run("success persists precompile-staged writes too", func(t *testing.T) { + db := setup("ok_precompile", common.Address{}) + stageViaPrecompile(t, db) + seed(db) + require.NoError(t, db.Commit()) + require.Equal(t, uint256.NewInt(1_000_000), persisted(db, credit).Balance) + require.Equal(t, uint256.NewInt(7), persisted(db, precompileAddr).Balance) + }) +} diff --git a/x/vm/statedb/config.go b/x/vm/statedb/config.go index 58970878..949060e1 100644 --- a/x/vm/statedb/config.go +++ b/x/vm/statedb/config.go @@ -11,17 +11,15 @@ import ( // TxConfig encapulates the readonly information of current tx for `StateDB`. type TxConfig struct { - 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 } // NewTxConfig returns a TxConfig -func NewTxConfig(thash common.Hash, txIndex, logIndex uint) TxConfig { +func NewTxConfig(thash common.Hash, txIndex uint) TxConfig { return TxConfig{ - TxHash: thash, - TxIndex: txIndex, - LogIndex: logIndex, + TxHash: thash, + TxIndex: txIndex, } } @@ -29,9 +27,8 @@ func NewTxConfig(thash common.Hash, txIndex, logIndex uint) TxConfig { // used in context where there's no transaction, e.g. `eth_call`/`eth_estimateGas`. func NewEmptyTxConfig() TxConfig { return TxConfig{ - TxHash: common.Hash{}, - TxIndex: 0, - LogIndex: 0, + TxHash: common.Hash{}, + TxIndex: 0, } } diff --git a/x/vm/statedb/interfaces.go b/x/vm/statedb/interfaces.go index b5591690..d5aca0f4 100644 --- a/x/vm/statedb/interfaces.go +++ b/x/vm/statedb/interfaces.go @@ -4,8 +4,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" - storetypes "cosmossdk.io/store/types" - + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -23,6 +22,10 @@ type ExtStateDB interface { type Keeper interface { // Read methods GetAccount(ctx sdk.Context, addr common.Address) *Account + // IsBaseAccountOrEmpty reports whether addr has no Cosmos account yet, or + // carries exactly the plain BaseAccount type. EVM contract code may only + // attach to such an address. + IsBaseAccountOrEmpty(ctx sdk.Context, addr common.Address) bool GetState(ctx sdk.Context, addr common.Address, key common.Hash) common.Hash GetCode(ctx sdk.Context, codeHash common.Hash) []byte GetCodeHash(ctx sdk.Context, addr common.Address) common.Hash @@ -37,7 +40,7 @@ type Keeper interface { SetCode(ctx sdk.Context, codeHash []byte, code []byte) DeleteAccount(ctx sdk.Context, addr common.Address) error - // Getter for injected KVStore keys + // Getter for injected Store keys // It is used for StateDB.snapshotter creation - KVStoreKeys() map[string]*storetypes.KVStoreKey + KVStoreKeys() map[string]storetypes.StoreKey } diff --git a/x/vm/statedb/journal.go b/x/vm/statedb/journal.go index 3ae0817d..75fb0a5b 100644 --- a/x/vm/statedb/journal.go +++ b/x/vm/statedb/journal.go @@ -98,13 +98,8 @@ type ( createObjectChange struct { account *common.Address } - resetObjectChange struct { - prev *stateObject - } selfDestructChange struct { - account *common.Address - prev bool // whether account had already self-destructed - prevbalance *uint256.Int + account *common.Address } // Changes to individual accounts. @@ -144,8 +139,9 @@ type ( slot *common.Hash } precompileCallChange struct { - snapshot int - events sdk.Events + snapshot int + prevEvents sdk.Events + prevProcessedEventCount int } createContractChange struct { account *common.Address @@ -155,7 +151,6 @@ type ( var ( _ JournalEntry = createContractChange{} _ JournalEntry = createObjectChange{} - _ JournalEntry = resetObjectChange{} _ JournalEntry = selfDestructChange{} _ JournalEntry = balanceChange{} _ JournalEntry = nonceChange{} @@ -180,7 +175,13 @@ func (ch createContractChange) Dirtied() *common.Address { func (pc precompileCallChange) Revert(s *StateDB) { // rollback multi store from cache ctx to the previous // state stored in the snapshot - s.RevertMultiStore(pc.snapshot, pc.events) + s.RevertMultiStore(pc.snapshot) + + // Restore events to the state before this precompile call + s.cacheCtx.EventManager().OverrideEvents(pc.prevEvents) + + // Restore processed events counter + s.processedEventsCount = pc.prevProcessedEventCount } func (pc precompileCallChange) Dirtied() *common.Address { @@ -195,19 +196,10 @@ func (ch createObjectChange) Dirtied() *common.Address { return ch.account } -func (ch resetObjectChange) Revert(s *StateDB) { - s.setStateObject(ch.prev) -} - -func (ch resetObjectChange) Dirtied() *common.Address { - return nil -} - func (ch selfDestructChange) Revert(s *StateDB) { obj := s.getStateObject(*ch.account) if obj != nil { - obj.selfDestructed = ch.prev - obj.setBalance(ch.prevbalance) + obj.selfDestructed = false } } diff --git a/x/vm/statedb/mock_test.go b/x/vm/statedb/mock_test.go index 198ccfc9..6bf6ea73 100644 --- a/x/vm/statedb/mock_test.go +++ b/x/vm/statedb/mock_test.go @@ -10,8 +10,7 @@ import ( "github.com/cosmos/evm/x/vm/statedb" "github.com/cosmos/evm/x/vm/types" - storetypes "cosmossdk.io/store/types" - + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -30,6 +29,10 @@ type MockKeeper struct { codes map[common.Hash][]byte } +func (k MockKeeper) IsBaseAccountOrEmpty(_ sdk.Context, _ common.Address) bool { + return true +} + func (k MockKeeper) GetCodeHash(_ sdk.Context, addr common.Address) common.Hash { return common.HexToHash(addr.Hex()) } @@ -120,6 +123,6 @@ func (k MockKeeper) Clone() *MockKeeper { return &MockKeeper{accounts, codes} } -func (k MockKeeper) KVStoreKeys() map[string]*storetypes.KVStoreKey { - return make(map[string]*storetypes.KVStoreKey) +func (k MockKeeper) KVStoreKeys() map[string]storetypes.StoreKey { + return make(map[string]storetypes.StoreKey) } diff --git a/x/vm/statedb/mocks/statedb.go b/x/vm/statedb/mocks/statedb.go index cc437ade..b73c7447 100644 --- a/x/vm/statedb/mocks/statedb.go +++ b/x/vm/statedb/mocks/statedb.go @@ -17,8 +17,6 @@ import ( types "github.com/ethereum/go-ethereum/core/types" uint256 "github.com/holiman/uint256" - - utils "github.com/ethereum/go-ethereum/trie/utils" ) // StateDB is an autogenerated mock type for the StateDB type @@ -119,6 +117,11 @@ func (_m *StateDB) CreateContract(_a0 common.Address) { _m.Called(_a0) } +// EmitLogsForBurnAccounts provides a mock function with no fields +func (_m *StateDB) EmitLogsForBurnAccounts() { + _m.Called() +} + // Empty provides a mock function with given fields: _a0 func (_m *StateDB) Empty(_a0 common.Address) bool { ret := _m.Called(_a0) @@ -384,12 +387,12 @@ func (_m *StateDB) HasSelfDestructed(_a0 common.Address) bool { return r0 } -// IsStorageEmpty provides a mock function with given fields: addr -func (_m *StateDB) IsStorageEmpty(addr common.Address) bool { +// IsNewContract provides a mock function with given fields: addr +func (_m *StateDB) IsNewContract(addr common.Address) bool { ret := _m.Called(addr) if len(ret) == 0 { - panic("no return value specified for IsStorageEmpty") + panic("no return value specified for IsNewContract") } var r0 bool @@ -402,21 +405,19 @@ func (_m *StateDB) IsStorageEmpty(addr common.Address) bool { return r0 } -// PointCache provides a mock function with no fields -func (_m *StateDB) PointCache() *utils.PointCache { - ret := _m.Called() +// IsStorageEmpty provides a mock function with given fields: addr +func (_m *StateDB) IsStorageEmpty(addr common.Address) bool { + ret := _m.Called(addr) if len(ret) == 0 { - panic("no return value specified for PointCache") + panic("no return value specified for IsStorageEmpty") } - var r0 *utils.PointCache - if rf, ok := ret.Get(0).(func() *utils.PointCache); ok { - r0 = rf() + var r0 bool + if rf, ok := ret.Get(0).(func(common.Address) bool); ok { + r0 = rf(addr) } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*utils.PointCache) - } + r0 = ret.Get(0).(bool) } return r0 @@ -433,66 +434,21 @@ func (_m *StateDB) RevertToSnapshot(_a0 int) { } // SelfDestruct provides a mock function with given fields: _a0 -func (_m *StateDB) SelfDestruct(_a0 common.Address) uint256.Int { - ret := _m.Called(_a0) - - if len(ret) == 0 { - panic("no return value specified for SelfDestruct") - } - - var r0 uint256.Int - if rf, ok := ret.Get(0).(func(common.Address) uint256.Int); ok { - r0 = rf(_a0) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(uint256.Int) - } - } - - return r0 -} - -// SelfDestruct6780 provides a mock function with given fields: _a0 -func (_m *StateDB) SelfDestruct6780(_a0 common.Address) (uint256.Int, bool) { - ret := _m.Called(_a0) - - if len(ret) == 0 { - panic("no return value specified for SelfDestruct6780") - } - - var r0 uint256.Int - var r1 bool - if rf, ok := ret.Get(0).(func(common.Address) (uint256.Int, bool)); ok { - return rf(_a0) - } - if rf, ok := ret.Get(0).(func(common.Address) uint256.Int); ok { - r0 = rf(_a0) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(uint256.Int) - } - } - - if rf, ok := ret.Get(1).(func(common.Address) bool); ok { - r1 = rf(_a0) - } else { - r1 = ret.Get(1).(bool) - } - - return r0, r1 +func (_m *StateDB) SelfDestruct(_a0 common.Address) { + _m.Called(_a0) } -// SetCode provides a mock function with given fields: _a0, _a1 -func (_m *StateDB) SetCode(_a0 common.Address, _a1 []byte) []byte { - ret := _m.Called(_a0, _a1) +// SetCode provides a mock function with given fields: _a0, _a1, _a2 +func (_m *StateDB) SetCode(_a0 common.Address, _a1 []byte, _a2 tracing.CodeChangeReason) []byte { + ret := _m.Called(_a0, _a1, _a2) if len(ret) == 0 { panic("no return value specified for SetCode") } var r0 []byte - if rf, ok := ret.Get(0).(func(common.Address, []byte) []byte); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(common.Address, []byte, tracing.CodeChangeReason) []byte); ok { + r0 = rf(_a0, _a1, _a2) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]byte) diff --git a/x/vm/statedb/state_object.go b/x/vm/statedb/state_object.go index db52e60c..42bbb6e2 100644 --- a/x/vm/statedb/state_object.go +++ b/x/vm/statedb/state_object.go @@ -2,6 +2,8 @@ package statedb import ( "bytes" + "fmt" + "math/big" "sort" "github.com/ethereum/go-ethereum/common" @@ -16,6 +18,11 @@ type Account struct { Nonce uint64 Balance *uint256.Int CodeHash []byte + + // lockedBalance is a snapshot of Account's LockedCoins at load time. Note + // that this is simply a constant offset to recover the full bank balance + // from spendable Balance at commit, not a live updating value. + lockedBalance *big.Int } // NewEmptyAccount returns an empty account. @@ -26,11 +33,30 @@ func NewEmptyAccount() *Account { } } +// NewAccount returns a new account instance. +func NewAccount(nonce uint64, balance *uint256.Int, lockedBalance *big.Int, codeHash []byte) *Account { + return &Account{ + Nonce: nonce, + Balance: balance, + CodeHash: codeHash, + lockedBalance: lockedBalance, + } +} + // IsContract returns if the account contains contract code. func (acct Account) HasCodeHash() bool { return !types.IsEmptyCodeHash(acct.CodeHash) } +// LockedBalanceSnapshot returns a copy of the LockedCoins value observed when +// the account was loaded, or nil if no snapshot was recorded. +func (acct Account) LockedBalanceSnapshot() *big.Int { + if acct.lockedBalance == nil { + return nil + } + return new(big.Int).Set(acct.lockedBalance) +} + // Storage represents in-memory cache/buffer of contract storage. type Storage map[common.Hash]common.Hash @@ -112,7 +138,17 @@ func (s *stateObject) AddBalance(amount *uint256.Int) uint256.Int { if amount.IsZero() { return *(s.Balance()) } - return s.SetBalance(new(uint256.Int).Add(s.Balance(), amount)) + + newBalance, overflowed := new(uint256.Int).AddOverflow(s.Balance(), amount) + if overflowed { + panic(fmt.Sprintf( + "state balance overflow for %s: have=%s add=%s", + s.address.Hex(), + s.Balance().String(), + amount.String(), + )) + } + return s.SetBalance(newBalance) } // SubBalance removes amount from s's balance. @@ -122,7 +158,16 @@ func (s *stateObject) SubBalance(amount *uint256.Int) uint256.Int { if amount.IsZero() { return *(s.Balance()) } - return s.SetBalance(new(uint256.Int).Sub(s.Balance(), amount)) + balance := s.Balance() + if balance.Lt(amount) { + panic(fmt.Sprintf( + "state balance underflow for %s: have=%s sub=%s", + s.address.Hex(), + balance.String(), + amount.String(), + )) + } + return s.SetBalance(new(uint256.Int).Sub(balance, amount)) } // SetBalance updates account balance. diff --git a/x/vm/statedb/statedb.go b/x/vm/statedb/statedb.go index 98185b60..0ac0e935 100644 --- a/x/vm/statedb/statedb.go +++ b/x/vm/statedb/statedb.go @@ -15,7 +15,6 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/trie" - "github.com/ethereum/go-ethereum/trie/utils" "github.com/holiman/uint256" "github.com/cosmos/evm/x/vm/store/snapshotmulti" @@ -23,8 +22,8 @@ import ( "github.com/cosmos/evm/x/vm/types" errorsmod "cosmossdk.io/errors" - storetypes "cosmossdk.io/store/types" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -34,7 +33,6 @@ import ( type revision struct { id int journalIndex int - events sdk.Events } var _ vm.StateDB = &StateDB{} @@ -80,6 +78,12 @@ type StateDB struct { // The count of calls to precompiles precompileCallsCounter uint8 + + // processedEventsCount tracks how many events have been + // processed by BalanceHandler. Events are processed sequentially starting + // from index 0. Event counter tracks events to avoid having them reprocessed. + // On revert, this counter is rewound to the snapshot's event count. + processedEventsCount int } func (s *StateDB) CreateContract(address common.Address) { @@ -92,6 +96,16 @@ func (s *StateDB) CreateContract(address common.Address) { } } +// IsNewContract reports whether the contract at the given address was deployed +// during the current transaction. +func (s *StateDB) IsNewContract(addr common.Address) bool { + obj := s.getStateObject(addr) + if obj == nil { + return false + } + return obj.newContract +} + // GetStorageRoot calculates the hash of the trie root by iterating through all storage objects for a given account func (s *StateDB) GetStorageRoot(addr common.Address) common.Hash { sr := trie.NewStackTrie(nil) @@ -114,15 +128,6 @@ func (s *StateDB) IsStorageEmpty(addr common.Address) bool { return empty } -/* - PointCache, Witness, and AccessEvents are all utilized for verkle trees. - For now, we just return nil and verkle trees are not supported. -*/ - -func (s *StateDB) PointCache() *utils.PointCache { - return nil -} - func (s *StateDB) Witness() *stateless.Witness { // TODO support verkle tries? return nil @@ -132,6 +137,41 @@ func (s *StateDB) AccessEvents() *state.AccessEvents { return nil } +type removedAccountWithBalance struct { + address common.Address + balance *uint256.Int +} + +// EmitLogsForBurnAccounts emits the eth burn logs for accounts scheduled for +// removal which still have positive balance. The purpose of this function is +// to handle a corner case of EIP-7708 where a self-destructed account might +// still receive funds between sending/burning its previous balance and actual +// removal. In this case the burning of these remaining balances still need to +// be logged. +// Specification EIP-7708: https://eips.ethereum.org/EIPS/eip-7708 +// +// This function should only be invoked at the transaction boundary, specifically +// before the Finalise. +func (s *StateDB) EmitLogsForBurnAccounts() { + var list []removedAccountWithBalance + for addr := range s.journal.dirties { + if obj, exist := s.stateObjects[addr]; exist && obj.selfDestructed && !obj.Balance().IsZero() { + list = append(list, removedAccountWithBalance{ + address: obj.address, + balance: obj.Balance(), + }) + } + } + if list != nil { + sort.Slice(list, func(i, j int) bool { + return list[i].address.Cmp(list[j].address) < 0 + }) + } + for _, acct := range list { + s.AddLog(ethtypes.EthBurnLog(acct.address, acct.balance)) + } +} + func (s *StateDB) Finalise(deleteEmptyObjects bool) { for addr := range s.journal.dirties { obj, exist := s.stateObjects[addr] @@ -147,13 +187,14 @@ func (s *StateDB) Finalise(deleteEmptyObjects bool) { // New creates a new state from a given trie. func New(ctx sdk.Context, keeper Keeper, txConfig TxConfig) *StateDB { return &StateDB{ - keeper: keeper, - ctx: ctx, - stateObjects: make(map[common.Address]*stateObject), - journal: newJournal(), - accessList: newAccessList(), - transientStorage: newTransientStorage(), - txConfig: txConfig, + keeper: keeper, + ctx: ctx, + stateObjects: make(map[common.Address]*stateObject), + journal: newJournal(), + accessList: newAccessList(), + transientStorage: newTransientStorage(), + txConfig: txConfig, + processedEventsCount: len(ctx.EventManager().Events()), } } @@ -184,12 +225,8 @@ func (s *StateDB) MultiStoreSnapshot() int { return s.snapshotter.Snapshot() } -func (s *StateDB) RevertMultiStore(snapshot int, events sdk.Events) { +func (s *StateDB) RevertMultiStore(snapshot int) { s.snapshotter.RevertToSnapshot(snapshot) - s.writeCache = func() { - s.ctx.EventManager().EmitEvents(events) - s.cacheCtx.MultiStore().(storetypes.CacheMultiStore).Write() - } } // cache creates the stateDB cache context @@ -200,7 +237,7 @@ func (s *StateDB) cache() error { s.cacheCtx, _ = s.ctx.CacheContext() // Get KVStores for modules wired to app - cms := s.cacheCtx.MultiStore().(storetypes.CacheMultiStore) + cms := s.cacheCtx.MultiStore() storeKeys := s.keeper.KVStoreKeys() // Create and set snapshot store to stateDB @@ -208,7 +245,8 @@ func (s *StateDB) cache() error { s.snapshotter = snapshotStore s.cacheCtx = s.cacheCtx.WithMultiStore(snapshotStore) s.writeCache = func() { - s.ctx.EventManager().EmitEvents(s.cacheCtx.EventManager().Events()) + eventsToEmit := s.cacheCtx.EventManager().Events() + s.ctx.EventManager().EmitEvents(eventsToEmit) s.cacheCtx.MultiStore().(storetypes.CacheMultiStore).Write() } @@ -220,7 +258,7 @@ func (s *StateDB) AddLog(log *ethtypes.Log) { s.journal.append(addLogChange{}) log.TxIndex = s.txConfig.TxIndex - log.Index = s.txConfig.LogIndex + uint(len(s.logs)) + log.Index = uint(len(s.logs)) s.logs = append(s.logs, log) } @@ -364,44 +402,34 @@ func (s *StateDB) getStateObject(addr common.Address) *stateObject { func (s *StateDB) getOrNewStateObject(addr common.Address) *stateObject { stateObject := s.getStateObject(addr) if stateObject == nil { - stateObject, _ = s.createObject(addr) + stateObject = s.createObject(addr) } return stateObject } -// createObject creates a new state object. If there is an existing account with -// the given address, it is overwritten and returned as the second return value. -func (s *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) { - prev = s.getStateObject(addr) - - newobj = newObject(s, addr, Account{}) - if prev == nil { - s.journal.append(createObjectChange{account: &addr}) - } else { - s.journal.append(resetObjectChange{prev: prev}) - } - s.setStateObject(newobj) - if prev != nil { - return newobj, prev - } - return newobj, nil +// createObject creates a new state object. The assumption is held there is no +// existing account with the given address, otherwise it will be silently overwritten. +func (s *StateDB) createObject(addr common.Address) *stateObject { + obj := newObject(s, addr, Account{}) + s.journal.append(createObjectChange{account: &addr}) + s.setStateObject(obj) + return obj } -// CreateAccount explicitly creates a state object. If a state object with the address -// already exists the balance is carried over to the new account. +// CreateAccount explicitly creates a new state object, assuming that the +// account did not previously exist in the state. If the account already +// exists, this function will silently overwrite it which might lead to a +// consensus bug eventually. // -// CreateAccount is called during the EVM CREATE operation. The situation might arise that -// a contract does the following: -// -// 1. sends funds to sha(account ++ (nonce + 1)) -// 2. tx_create(sha(account ++ nonce)) (note that this gets the address of 1) -// -// Carrying over the balance ensures that Ether doesn't disappear. +// The EVM only calls CreateAccount when Exist(addr) is false, immediately +// followed by CreateContract to set the EIP-6780 newContract flag, so the +// pre-funded-then-deployed flow is preserved without any balance carry-over +// here. See go-ethereum PR #29520. func (s *StateDB) CreateAccount(addr common.Address) { - newObj, prev := s.createObject(addr) - if prev != nil { - newObj.setBalance(prev.account.Balance) + if !s.keeper.IsBaseAccountOrEmpty(s.ctx, addr) { + panic(fmt.Sprintf("cannot deploy EVM contract on top of non-base account %s", addr.Hex())) } + s.createObject(addr) } // ForEachStorage iterate the contract storage, the iteration order is not defined. @@ -433,10 +461,14 @@ 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(snapshot int, events sdk.Events) error { +func (s *StateDB) AddPrecompileFn(snapshot int) error { + // Capture events before the precompile call + prevEvents := s.cacheCtx.EventManager().Events() + s.journal.append(precompileCallChange{ - snapshot: snapshot, - events: events, + snapshot: snapshot, + prevEvents: prevEvents, + prevProcessedEventCount: s.processedEventsCount, }) s.precompileCallsCounter++ if s.precompileCallsCounter > types.MaxPrecompileCalls { @@ -445,6 +477,23 @@ func (s *StateDB) AddPrecompileFn(snapshot int, events sdk.Events) error { return nil } +// MarkEventProcessed records that the event at the given index +// has been seen by BalanceHandler. Events must be marked sequentially. +func (s *StateDB) MarkEventProcessed(idx int) { + // Events must be processed sequentially - idx should equal current count + if idx != s.processedEventsCount { + panic(fmt.Sprintf("balance events must be processed sequentially: expected %d, got %d", + s.processedEventsCount, idx)) + } + s.processedEventsCount++ +} + +// IsEventProcessed reports whether the event at idx has already been +// seen by a previous AfterBalanceChange invocation. +func (s *StateDB) IsEventProcessed(idx int) bool { + return idx < s.processedEventsCount +} + // AddBalance adds amount to the account associated with addr. func (s *StateDB) AddBalance(addr common.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) uint256.Int { stateObject := s.getOrNewStateObject(addr) @@ -475,7 +524,7 @@ func (s *StateDB) SetNonce(addr common.Address, nonce uint64, reason tracing.Non } // SetCode sets the code of account. -func (s *StateDB) SetCode(addr common.Address, code []byte) []byte { +func (s *StateDB) SetCode(addr common.Address, code []byte, reason tracing.CodeChangeReason) []byte { stateObject := s.getOrNewStateObject(addr) var prev []byte if stateObject != nil { @@ -510,37 +559,18 @@ func (s *StateDB) SetStorage(addr common.Address, storage Storage) { } // SelfDestruct marks the given account as self-destructed. -// This clears the account balance. // // The account's state object is still available until the state is committed, // getStateObject will return a non-nil account after SelfDestruct. -func (s *StateDB) SelfDestruct(addr common.Address) uint256.Int { +func (s *StateDB) SelfDestruct(addr common.Address) { stateObject := s.getStateObject(addr) - var prevBalance uint256.Int if stateObject == nil { - return prevBalance + return } - prevBalance = *(stateObject.Balance()) s.journal.append(selfDestructChange{ - account: &addr, - prev: stateObject.selfDestructed, - prevbalance: new(uint256.Int).Set(stateObject.Balance()), + account: &addr, }) stateObject.markSelfDestructed() - stateObject.account.Balance = new(uint256.Int) - return prevBalance -} - -func (s *StateDB) SelfDestruct6780(addr common.Address) (uint256.Int, bool) { - stateObject := s.getStateObject(addr) - if stateObject == nil { - return uint256.Int{}, false - } - - if stateObject.newContract { - return s.SelfDestruct(addr), true - } - return *(stateObject.Balance()), false } // HasSelfDestructed returns if the contract is self-destructed in current transaction. @@ -664,7 +694,7 @@ func (s *StateDB) SlotInAccessList(addr common.Address, slot common.Hash) (addre func (s *StateDB) Snapshot() int { id := s.nextRevisionID s.nextRevisionID++ - s.validRevisions = append(s.validRevisions, revision{id, s.journal.length(), s.ctx.EventManager().Events()}) + s.validRevisions = append(s.validRevisions, revision{id, s.journal.length()}) return id } @@ -679,32 +709,49 @@ func (s *StateDB) RevertToSnapshot(revid int) { } snapshot := s.validRevisions[idx].journalIndex - // revert back to snapshotted events - eventManager := sdk.NewEventManager() - eventManager.EmitEvents(s.validRevisions[idx].events) - s.ctx = s.ctx.WithEventManager(eventManager) - // Replay the journal to undo changes and remove invalidated snapshots + // Event restoration is handled by precompileCallChange.Revert() s.journal.Revert(s, snapshot) s.validRevisions = s.validRevisions[:idx] } -// Commit writes the dirty states to keeper -// the StateDB object should be discarded after committed. +// Commit writes the dirty states to keeper. +// The StateDB object should be discarded after being committed. func (s *StateDB) Commit() error { // writeCache func will exist only when there's a call to a precompile. // It applies all the store updates preformed by precompile calls. if s.writeCache != nil { + // fold the remaining dirty set into the precompile cache so the + // state changes are atomic. + if err := s.commitWithCtx(s.cacheCtx); err != nil { + return err + } s.writeCache() + return nil + } + + // stage writes here so a late failure leaves s.ctx untouched. + cacheCtx, writeCache := s.ctx.CacheContext() + if err := s.commitWithCtx(cacheCtx); err != nil { + return err } - return s.commitWithCtx(s.ctx) + writeCache() + return nil } -// CommitWithCacheCtx writes the dirty states to keeper using the cacheCtx. +// FlushToCacheCtx writes the dirty states to keeper using the cacheCtx. // This function is used before any precompile call to make sure the cacheCtx // is updated with the latest changes within the tx (StateDB's journal entries). -func (s *StateDB) CommitWithCacheCtx() error { - return s.commitWithCtx(s.cacheCtx) +func (s *StateDB) FlushToCacheCtx() error { + if err := s.commitWithCtx(s.cacheCtx); err != nil { + return err + } + + // Set counter to event count - all flushed events (from mint/burn during commit) are now accounted for. + // This prevents the balance handler from re-adding already flushed events. + s.processedEventsCount = len(s.cacheCtx.EventManager().Events()) + + return nil } // commitWithCtx writes the dirty states to keeper @@ -713,6 +760,14 @@ func (s *StateDB) commitWithCtx(ctx sdk.Context) error { for _, addr := range s.journal.sortedDirties() { obj := s.stateObjects[addr] if obj.selfDestructed { + // For EIP-6780 same-tx self-destruct: persist code+account first so DeleteAccount's + // IsContract check can verify it, then immediately delete everything + if obj.code != nil && obj.dirtyCode && len(obj.code) > 0 { + s.keeper.SetCode(ctx, obj.CodeHash(), obj.code) + if err := s.keeper.SetAccount(ctx, obj.Address(), obj.account); err != nil { + return errorsmod.Wrap(err, "failed to set account before delete") + } + } if err := s.keeper.DeleteAccount(ctx, obj.Address()); err != nil { return errorsmod.Wrapf(err, "failed to delete account %s", obj.Address()) } diff --git a/x/vm/statedb/statedb_test.go b/x/vm/statedb/statedb_test.go index 69bbddc2..61c90c2a 100644 --- a/x/vm/statedb/statedb_test.go +++ b/x/vm/statedb/statedb_test.go @@ -12,14 +12,23 @@ import ( "github.com/ethereum/go-ethereum/crypto" ethparams "github.com/ethereum/go-ethereum/params" "github.com/holiman/uint256" + "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" "github.com/cosmos/evm/x/vm/statedb" "github.com/cosmos/evm/x/vm/types/mocks" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" + "github.com/cosmos/cosmos-sdk/testutil" sdk "github.com/cosmos/cosmos-sdk/types" ) +func newTestCtx() sdk.Context { + key := storetypes.NewKVStoreKey("statedb_test") + tkey := storetypes.NewTransientStoreKey("statedb_test_transient") + return testutil.DefaultContext(key, tkey).WithEventManager(sdk.NewEventManager()) +} + var ( address common.Address = common.BigToAddress(big.NewInt(101)) address2 common.Address = common.BigToAddress(big.NewInt(102)) @@ -58,7 +67,7 @@ func (suite *StateDBTestSuite) TestAccount() { suite.Require().Empty(acct.Balance) suite.Require().False(acct.HasCodeHash()) - db = statedb.New(sdk.Context{}, keeper, emptyTxConfig) + db = statedb.New(newTestCtx(), keeper, emptyTxConfig) suite.Require().Equal(true, db.Exist(address)) suite.Require().Equal(true, db.Empty(address)) suite.Require().Equal(common.U2560, db.GetBalance(address)) @@ -73,7 +82,7 @@ func (suite *StateDBTestSuite) TestAccount() { // create a contract account db.CreateAccount(address) - db.SetCode(address, []byte("hello world")) + db.SetCode(address, []byte("hello world"), 0x0) db.AddBalance(address, uint256.NewInt(100), tracing.BalanceChangeUnspecified) db.CreateContract(address) db.SetState(address, key1, value1) @@ -81,14 +90,12 @@ func (suite *StateDBTestSuite) TestAccount() { suite.Require().NoError(db.Commit()) // SelfDestruct - db = statedb.New(sdk.Context{}, db.Keeper(), emptyTxConfig) + db = statedb.New(newTestCtx(), db.Keeper(), emptyTxConfig) suite.Require().False(db.HasSelfDestructed(address)) db.SelfDestruct(address) // check dirty state suite.Require().True(db.HasSelfDestructed(address)) - // balance is cleared - suite.Require().Equal(common.U2560, db.GetBalance(address)) // but code and state are still accessible in dirty state suite.Require().Equal(value1, db.GetState(address, key1)) suite.Require().Equal([]byte("hello world"), db.GetCode(address)) @@ -96,7 +103,7 @@ func (suite *StateDBTestSuite) TestAccount() { suite.Require().NoError(db.Commit()) // not accessible from StateDB anymore - db = statedb.New(sdk.Context{}, db.Keeper(), emptyTxConfig) + db = statedb.New(newTestCtx(), db.Keeper(), emptyTxConfig) suite.Require().False(db.Exist(address)) // and cleared in keeper too @@ -106,118 +113,17 @@ func (suite *StateDBTestSuite) TestAccount() { return true }) }}, - {"self-destruct-6780 same tx", func(ctx sdk.Context, db *statedb.StateDB) { - // non-exist account. - db.SelfDestruct(address) - suite.Require().False(db.HasSelfDestructed(address)) - - // create a contract account - db.CreateAccount(address) - db.SetCode(address, []byte("hello world")) - db.AddBalance(address, uint256.NewInt(100), tracing.BalanceChangeUnspecified) - db.CreateContract(address) - db.SetState(address, key1, value1) - db.SetState(address, key2, value2) - - // SelfDestruct - suite.Require().False(db.HasSelfDestructed(address)) - _, _ = db.SelfDestruct6780(address) - - // check dirty state - suite.Require().True(db.HasSelfDestructed(address)) - // balance is cleared - suite.Require().Equal(common.U2560, db.GetBalance(address)) - // but code and state are still accessible in dirty state - suite.Require().Equal(value1, db.GetState(address, key1)) - suite.Require().Equal([]byte("hello world"), db.GetCode(address)) - - suite.Require().NoError(db.Commit()) - - // not accessible from StateDB anymore - db = statedb.New(sdk.Context{}, db.Keeper(), emptyTxConfig) - suite.Require().False(db.Exist(address)) - - // and cleared in keeper too - keeper := db.Keeper().(*mocks.EVMKeeper) - keeper.ForEachStorage(ctx, address, func(key, value common.Hash) bool { - suite.Require().Equal(0, len(value.Bytes())) - return true - }) - }}, - {"self-destruct-6780 different tx", func(ctx sdk.Context, db *statedb.StateDB) { - // non-exist account. - db.SelfDestruct(address) - suite.Require().False(db.HasSelfDestructed(address)) - - // create a contract account - db.CreateAccount(address) - db.SetCode(address, []byte("hello world")) - db.AddBalance(address, uint256.NewInt(100), tracing.BalanceChangeUnspecified) - db.CreateContract(address) - db.SetState(address, key1, value1) - db.SetState(address, key2, value2) - suite.Require().NoError(db.Commit()) - - // SelfDestruct - db = statedb.New(sdk.Context{}, db.Keeper(), emptyTxConfig) - suite.Require().False(db.HasSelfDestructed(address)) - _, _ = db.SelfDestruct6780(address) - - // Same-tx is not marked as self-destructed - suite.Require().False(db.HasSelfDestructed(address)) - // code and state are still accessible in dirty state - suite.Require().Equal(value1, db.GetState(address, key1)) - suite.Require().Equal([]byte("hello world"), db.GetCode(address)) - - suite.Require().NoError(db.Commit()) - - // Same-tx maintains state - db = statedb.New(sdk.Context{}, db.Keeper(), emptyTxConfig) - suite.Require().True(db.Exist(address)) - suite.Require().False(db.HasSelfDestructed(address)) - // but code and state are still accessible in dirty state - suite.Require().Equal(value1, db.GetState(address, key1)) - suite.Require().Equal([]byte("hello world"), db.GetCode(address)) - - // and not cleared in keeper too - keeper := db.Keeper().(*mocks.EVMKeeper) - acc := keeper.GetAccount(ctx, address) - suite.Require().NotNil(acc) - keeper.ForEachStorage(ctx, address, func(key, value common.Hash) bool { - suite.Require().Greater(len(value.Bytes()), 0) - return len(value) == 0 - }) - }}, } for _, tc := range testCases { suite.Run(tc.name, func() { - ctx := sdk.Context{}.WithEventManager(sdk.NewEventManager()) + ctx := newTestCtx() keeper := mocks.NewEVMKeeper() - db := statedb.New(sdk.Context{}, keeper, emptyTxConfig) + db := statedb.New(newTestCtx(), keeper, emptyTxConfig) tc.malleate(ctx, db) }) } } -func (suite *StateDBTestSuite) TestAccountOverride() { - keeper := mocks.NewEVMKeeper() - db := statedb.New(sdk.Context{}, keeper, emptyTxConfig) - // test balance carry over when overwritten - amount := uint256.NewInt(1) - - // init an EOA account, account overridden only happens on EOA account. - db.AddBalance(address, amount, tracing.BalanceChangeUnspecified) - db.SetNonce(address, 1, tracing.NonceChangeUnspecified) - - // override - db.CreateAccount(address) - - // check balance is not lost - suite.Require().Equal(amount, db.GetBalance(address)) - // but nonce is reset - suite.Require().Equal(uint64(0), db.GetNonce(address)) -} - func (suite *StateDBTestSuite) TestDBError() { testCases := []struct { name string @@ -233,14 +139,15 @@ func (suite *StateDBTestSuite) TestDBError() { }}, } for _, tc := range testCases { - db := statedb.New(sdk.Context{}, mocks.NewEVMKeeper(), emptyTxConfig) - tc.malleate(db) - suite.Require().Error(db.Commit()) + suite.Run(tc.name, func() { + db := statedb.New(newTestCtx(), mocks.NewEVMKeeper(), emptyTxConfig) + tc.malleate(db) + suite.Require().Error(db.Commit()) + }) } } func (suite *StateDBTestSuite) TestBalance() { - // NOTE: no need to test overflow/underflow, that is guaranteed by evm implementation. testCases := []struct { name string malleate func(*statedb.StateDB) @@ -265,9 +172,9 @@ func (suite *StateDBTestSuite) TestBalance() { for _, tc := range testCases { suite.Run(tc.name, func() { - ctx := sdk.Context{}.WithEventManager(sdk.NewEventManager()) + ctx := newTestCtx() keeper := mocks.NewEVMKeeper() - db := statedb.New(sdk.Context{}, keeper, emptyTxConfig) + db := statedb.New(newTestCtx(), keeper, emptyTxConfig) tc.malleate(db) // check dirty state @@ -279,6 +186,56 @@ func (suite *StateDBTestSuite) TestBalance() { } } +func (suite *StateDBTestSuite) TestSubBalanceUnderflowPanics() { + db := statedb.New(sdk.Context{}.WithEventManager(sdk.NewEventManager()), mocks.NewEVMKeeper(), emptyTxConfig) + db.AddBalance(address, uint256.NewInt(1), tracing.BalanceChangeUnspecified) + + expectedPanic := fmt.Sprintf("state balance underflow for %s: have=%s sub=%s", address.Hex(), "1", "2") + suite.Require().PanicsWithValue(expectedPanic, func() { + db.SubBalance(address, uint256.NewInt(2), tracing.BalanceChangeUnspecified) + }) +} + +func (suite *StateDBTestSuite) TestCreateAccountBlocksNonBaseAccountTypes() { + testCases := []struct { + name string + malleate func(*mocks.EVMKeeper, common.Address) + expectPanic bool + }{ + {"no account", func(*mocks.EVMKeeper, common.Address) {}, false}, + {"empty BaseAccount", func(k *mocks.EVMKeeper, addr common.Address) { + err := k.SetAccount(sdk.Context{}, addr, statedb.Account{Balance: uint256.NewInt(0), CodeHash: mocks.EmptyCodeHash}) + suite.Require().NoError(err) + }, false}, + {"funded BaseAccount", func(k *mocks.EVMKeeper, addr common.Address) { + err := k.SetAccount(sdk.Context{}, addr, statedb.Account{Balance: uint256.NewInt(100), CodeHash: mocks.EmptyCodeHash}) + suite.Require().NoError(err) + }, false}, + {"non-BaseAccount type present", func(k *mocks.EVMKeeper, addr common.Address) { + err := k.SetAccount(sdk.Context{}, addr, statedb.Account{Balance: uint256.NewInt(2), CodeHash: mocks.EmptyCodeHash}) + suite.Require().NoError(err) + k.SetBlockedAccountType(addr, true) + }, true}, + } + + for _, tc := range testCases { + suite.Run(tc.name, func() { + keeper := mocks.NewEVMKeeper() + addr := common.BigToAddress(big.NewInt(200)) + tc.malleate(keeper, addr) + + db := statedb.New(newTestCtx(), keeper, emptyTxConfig) + createAccount := func() { db.CreateAccount(addr) } + + if tc.expectPanic { + suite.Require().Panics(createAccount) + } else { + suite.Require().NotPanics(createAccount) + } + }) + } +} + func (suite *StateDBTestSuite) TestState() { key1 := common.BigToHash(big.NewInt(1)) value1 := common.BigToHash(big.NewInt(1)) @@ -320,9 +277,9 @@ func (suite *StateDBTestSuite) TestState() { for _, tc := range testCases { suite.Run(tc.name, func() { - ctx := sdk.Context{}.WithEventManager(sdk.NewEventManager()) + ctx := newTestCtx() keeper := mocks.NewEVMKeeper() - db := statedb.New(sdk.Context{}, keeper, emptyTxConfig) + db := statedb.New(newTestCtx(), keeper, emptyTxConfig) tc.malleate(db) suite.Require().NoError(db.Commit()) @@ -332,7 +289,7 @@ func (suite *StateDBTestSuite) TestState() { } // check ForEachStorage - db = statedb.New(sdk.Context{}, keeper, emptyTxConfig) + db = statedb.New(newTestCtx(), keeper, emptyTxConfig) collected := CollectContractStorage(db) if len(tc.expStates) > 0 { suite.Require().Equal(tc.expStates, collected) @@ -358,14 +315,14 @@ func (suite *StateDBTestSuite) TestCode() { db.CreateAccount(address) }, nil, common.BytesToHash(mocks.EmptyCodeHash)}, {"set code", func(db vm.StateDB) { - db.SetCode(address, code) + db.SetCode(address, code, 0x0) }, code, codeHash}, } for _, tc := range testCases { suite.Run(tc.name, func() { keeper := mocks.NewEVMKeeper() - db := statedb.New(sdk.Context{}, keeper, emptyTxConfig) + db := statedb.New(newTestCtx(), keeper, emptyTxConfig) tc.malleate(db) // check dirty state @@ -376,7 +333,7 @@ func (suite *StateDBTestSuite) TestCode() { suite.Require().NoError(db.Commit()) // check again - db = statedb.New(sdk.Context{}, keeper, emptyTxConfig) + db = statedb.New(newTestCtx(), keeper, emptyTxConfig) suite.Require().Equal(tc.expCode, db.GetCode(address)) suite.Require().Equal(len(tc.expCode), db.GetCodeSize(address)) suite.Require().Equal(tc.expCodeHash, db.GetCodeHash(address)) @@ -406,11 +363,11 @@ func (suite *StateDBTestSuite) TestRevertSnapshot() { db.CreateAccount(address) }}, {"set code", func(db vm.StateDB) { - db.SetCode(address, []byte("hello world")) + db.SetCode(address, []byte("hello world"), 0x0) }}, {"suicide", func(db vm.StateDB) { db.SetState(address, v1, v2) - db.SetCode(address, []byte("hello world")) + db.SetCode(address, []byte("hello world"), 0x0) db.SelfDestruct(address) suite.Require().True(db.HasSelfDestructed(address)) }}, @@ -430,7 +387,7 @@ func (suite *StateDBTestSuite) TestRevertSnapshot() { } for _, tc := range testCases { suite.Run(tc.name, func() { - ctx := sdk.Context{}.WithEventManager(sdk.NewEventManager()) + ctx := newTestCtx() keeper := mocks.NewEVMKeeper() { @@ -438,7 +395,7 @@ func (suite *StateDBTestSuite) TestRevertSnapshot() { db := statedb.New(ctx, keeper, emptyTxConfig) db.SetNonce(address, 1, tracing.NonceChangeUnspecified) db.AddBalance(address, uint256.NewInt(100), tracing.BalanceChangeUnspecified) - db.SetCode(address, []byte("hello world")) + db.SetCode(address, []byte("hello world"), 0x0) db.SetState(address, v1, v2) db.SetNonce(address2, 1, tracing.NonceChangeUnspecified) suite.Require().NoError(db.Commit()) @@ -469,7 +426,7 @@ func (suite *StateDBTestSuite) TestNestedSnapshot() { value1 := common.BigToHash(big.NewInt(1)) value2 := common.BigToHash(big.NewInt(2)) - db := statedb.New(sdk.Context{}.WithEventManager(sdk.NewEventManager()), mocks.NewEVMKeeper(), emptyTxConfig) + db := statedb.New(newTestCtx(), mocks.NewEVMKeeper(), emptyTxConfig) rev1 := db.Snapshot() db.SetState(address, key, value1) @@ -486,7 +443,7 @@ func (suite *StateDBTestSuite) TestNestedSnapshot() { } func (suite *StateDBTestSuite) TestInvalidSnapshotId() { - db := statedb.New(sdk.Context{}, mocks.NewEVMKeeper(), emptyTxConfig) + db := statedb.New(newTestCtx(), mocks.NewEVMKeeper(), emptyTxConfig) suite.Require().Panics(func() { db.RevertToSnapshot(1) }) @@ -541,7 +498,6 @@ func (suite *StateDBTestSuite) TestAccessList() { }} rules := ethparams.Rules{ - ChainID: big.NewInt(1000), IsHomestead: true, IsEIP150: true, IsEIP155: true, @@ -577,7 +533,7 @@ func (suite *StateDBTestSuite) TestAccessList() { } for _, tc := range testCases { - db := statedb.New(sdk.Context{}, mocks.NewEVMKeeper(), emptyTxConfig) + db := statedb.New(newTestCtx(), mocks.NewEVMKeeper(), emptyTxConfig) tc.malleate(db) } } @@ -587,9 +543,9 @@ func (suite *StateDBTestSuite) TestLog() { // use a non-default tx config txConfig := statedb.NewTxConfig( txHash, - 1, 1, + 1, ) - db := statedb.New(sdk.Context{}, mocks.NewEVMKeeper(), txConfig) + db := statedb.New(newTestCtx(), mocks.NewEVMKeeper(), txConfig) data := []byte("hello world") db.AddLog(ðtypes.Log{ Address: address, @@ -604,7 +560,7 @@ func (suite *StateDBTestSuite) TestLog() { Data: data, BlockNumber: 1, TxIndex: 1, - Index: 1, + Index: 0, } suite.Require().Equal(expecedLog, db.Logs()[0]) @@ -639,7 +595,7 @@ func (suite *StateDBTestSuite) TestRefund() { }, 0, true}, } for _, tc := range testCases { - db := statedb.New(sdk.Context{}, mocks.NewEVMKeeper(), emptyTxConfig) + db := statedb.New(newTestCtx(), mocks.NewEVMKeeper(), emptyTxConfig) if !tc.expPanic { tc.malleate(db) suite.Require().Equal(tc.expRefund, db.GetRefund()) @@ -652,7 +608,7 @@ func (suite *StateDBTestSuite) TestRefund() { } func (suite *StateDBTestSuite) TestIterateStorage() { - ctx := sdk.Context{}.WithEventManager(sdk.NewEventManager()) + ctx := newTestCtx() key1 := common.BigToHash(big.NewInt(1)) value1 := common.BigToHash(big.NewInt(2)) @@ -660,7 +616,7 @@ func (suite *StateDBTestSuite) TestIterateStorage() { value2 := common.BigToHash(big.NewInt(4)) keeper := mocks.NewEVMKeeper() - db := statedb.New(sdk.Context{}, keeper, emptyTxConfig) + db := statedb.New(newTestCtx(), keeper, emptyTxConfig) db.SetState(address, key1, value1) db.SetState(address, key2, value2) @@ -716,7 +672,7 @@ func (suite *StateDBTestSuite) TestSetStorage() { for _, tc := range testCases { suite.Run(tc.name, func() { keeper := mocks.NewEVMKeeper() - db := statedb.New(sdk.Context{}, keeper, emptyTxConfig) + db := statedb.New(newTestCtx(), keeper, emptyTxConfig) for k, v := range tc.prestate { db.SetState(contract, k, v) } @@ -745,3 +701,18 @@ func CollectContractStorage(db vm.StateDB) statedb.Storage { func TestStateDBTestSuite(t *testing.T) { suite.Run(t, &StateDBTestSuite{}) } + +func TestAddBalanceOverflow(t *testing.T) { + // Overflowing uint256 must panic, not silently wrap around. + db := statedb.New(newTestCtx(), mocks.NewEVMKeeper(), emptyTxConfig) + db.AddBalance(address, new(uint256.Int).SetAllOne(), tracing.BalanceChangeUnspecified) + require.Panics(t, func() { + db.AddBalance(address, uint256.NewInt(1), tracing.BalanceChangeUnspecified) + }) + + // A non-overflowing add still updates the balance normally. + db = statedb.New(newTestCtx(), mocks.NewEVMKeeper(), emptyTxConfig) + db.AddBalance(address, uint256.NewInt(100), tracing.BalanceChangeUnspecified) + db.AddBalance(address, uint256.NewInt(23), tracing.BalanceChangeUnspecified) + require.Equal(t, uint256.NewInt(123), db.GetBalance(address)) +} diff --git a/x/vm/store/snapshotkv/store.go b/x/vm/store/snapshotkv/store.go index 6f9e002f..9375f15a 100644 --- a/x/vm/store/snapshotkv/store.go +++ b/x/vm/store/snapshotkv/store.go @@ -5,24 +5,23 @@ import ( "github.com/cosmos/evm/x/vm/store/types" - "cosmossdk.io/store/cachekv" - storetypes "cosmossdk.io/store/types" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" ) // Store manages a stack of nested cache store to // support the evm `StateDB`'s `Snapshot` and `RevertToSnapshot` methods. type Store struct { // Store of the initial state before transaction execution - initialStore storetypes.CacheKVStore + initialStore storetypes.CacheWrap // Stack of cached store - cacheStores []storetypes.CacheKVStore + cacheStores []storetypes.CacheWrap } var _ types.SnapshotKVStore = (*Store)(nil) // NewStore creates a new Store object -func NewStore(store storetypes.CacheKVStore) *Store { +func NewStore(store storetypes.CacheWrap) *Store { return &Store{ initialStore: store, cacheStores: nil, @@ -31,7 +30,7 @@ func NewStore(store storetypes.CacheKVStore) *Store { // CurrentStore returns the top of cached store stack. // If the stack is empty, returns the initial store. -func (cs *Store) CurrentStore() storetypes.CacheKVStore { +func (cs *Store) CurrentStore() storetypes.CacheWrap { l := len(cs.cacheStores) if l == 0 { return cs.initialStore @@ -53,7 +52,7 @@ func (cs *Store) Commit() { // Snapshot pushes a new cached store to the stack, // and returns the index of it. func (cs *Store) Snapshot() int { - cs.cacheStores = append(cs.cacheStores, cachekv.NewStore(cs.CurrentStore())) + cs.cacheStores = append(cs.cacheStores, cs.CurrentStore().CacheWrap()) return len(cs.cacheStores) - 1 } diff --git a/x/vm/store/snapshotkv/store_test.go b/x/vm/store/snapshotkv/store_test.go index 0939611d..c85b3cda 100644 --- a/x/vm/store/snapshotkv/store_test.go +++ b/x/vm/store/snapshotkv/store_test.go @@ -9,8 +9,9 @@ import ( dbm "github.com/cosmos/cosmos-db" "github.com/cosmos/evm/x/vm/store/snapshotkv" - "cosmossdk.io/store/cachekv" - "cosmossdk.io/store/dbadapter" + "github.com/cosmos/cosmos-sdk/store/v2/cachekv" + "github.com/cosmos/cosmos-sdk/store/v2/dbadapter" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" ) func newSnapshotKV() *snapshotkv.Store { @@ -35,28 +36,28 @@ func TestSnapshotRevertAndCommit(t *testing.T) { store := newSnapshotKV() // set in base store - base := store.CurrentStore() + base := store.CurrentStore().(storetypes.KVStore) base.Set([]byte("a"), []byte("1")) idx0 := store.Snapshot() - store.CurrentStore().Set([]byte("b"), []byte("2")) + store.CurrentStore().(storetypes.KVStore).Set([]byte("b"), []byte("2")) idx1 := store.Snapshot() - store.CurrentStore().Set([]byte("c"), []byte("3")) + store.CurrentStore().(storetypes.KVStore).Set([]byte("c"), []byte("3")) // revert latest snapshot (idx1) store.RevertToSnapshot(idx1) - require.Nil(t, store.CurrentStore().Get([]byte("c"))) - require.Equal(t, []byte("2"), store.CurrentStore().Get([]byte("b"))) + require.Nil(t, store.CurrentStore().(storetypes.KVStore).Get([]byte("c"))) + require.Equal(t, []byte("2"), store.CurrentStore().(storetypes.KVStore).Get([]byte("b"))) // revert the first snapshot store.RevertToSnapshot(idx0) - require.Nil(t, store.CurrentStore().Get([]byte("b"))) - require.Equal(t, []byte("1"), store.CurrentStore().Get([]byte("a"))) + require.Nil(t, store.CurrentStore().(storetypes.KVStore).Get([]byte("b"))) + require.Equal(t, []byte("1"), store.CurrentStore().(storetypes.KVStore).Get([]byte("a"))) // take new snapshot and commit store.Snapshot() - store.CurrentStore().Set([]byte("d"), []byte("4")) + store.CurrentStore().(storetypes.KVStore).Set([]byte("d"), []byte("4")) store.Commit() require.Equal(t, []byte("4"), base.Get([]byte("d"))) @@ -72,31 +73,31 @@ func TestSnapshotKVRevertOverwriteSameKey(t *testing.T) { base := store.CurrentStore() // Initial write under key "a" - store.CurrentStore().Set([]byte("a"), []byte("1")) + store.CurrentStore().(storetypes.KVStore).Set([]byte("a"), []byte("1")) // Overwrite "a" with "2" idx0 := store.Snapshot() - store.CurrentStore().Set([]byte("a"), []byte("2")) + store.CurrentStore().(storetypes.KVStore).Set([]byte("a"), []byte("2")) // Overwrite "a" with "3" idx1 := store.Snapshot() - store.CurrentStore().Set([]byte("a"), []byte("3")) + store.CurrentStore().(storetypes.KVStore).Set([]byte("a"), []byte("3")) // Revert to idx1: expect value "2" store.RevertToSnapshot(idx1) - require.Equal(t, []byte("2"), store.CurrentStore().Get([]byte("a"))) + require.Equal(t, []byte("2"), store.CurrentStore().(storetypes.KVStore).Get([]byte("a"))) // Revert to idx0: expect value "1" store.RevertToSnapshot(idx0) - require.Equal(t, []byte("1"), store.CurrentStore().Get([]byte("a"))) + require.Equal(t, []byte("1"), store.CurrentStore().(storetypes.KVStore).Get([]byte("a"))) // Take a new snapshot, overwrite "a" with "4", then commit idx2 := store.Snapshot() - store.CurrentStore().Set([]byte("a"), []byte("4")) + store.CurrentStore().(storetypes.KVStore).Set([]byte("a"), []byte("4")) store.Commit() // After commit, the base store should have "4" - require.Equal(t, []byte("4"), base.Get([]byte("a"))) + require.Equal(t, []byte("4"), base.(storetypes.KVStore).Get([]byte("a"))) // Commit clears the snapshot stack, so reverting to idx2 should panic expectedErr := fmt.Sprintf("snapshot index %d out of bound [%d..%d)", idx2, 0, 0) diff --git a/x/vm/store/snapshotmulti/store.go b/x/vm/store/snapshotmulti/store.go index 259f866b..47ddc523 100644 --- a/x/vm/store/snapshotmulti/store.go +++ b/x/vm/store/snapshotmulti/store.go @@ -2,26 +2,25 @@ package snapshotmulti import ( "fmt" - "io" "sort" "github.com/cosmos/evm/x/vm/store/snapshotkv" "github.com/cosmos/evm/x/vm/store/types" vmtypes "github.com/cosmos/evm/x/vm/types" - storetypes "cosmossdk.io/store/types" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" ) type Store struct { stores map[storetypes.StoreKey]types.SnapshotKVStore - storeKeys []*storetypes.KVStoreKey // ordered keys + storeKeys []storetypes.StoreKey // ordered keys head int } var _ types.SnapshotMultiStore = (*Store)(nil) // NewStore creates a new Store objectwith CacheMultiStore and KVStoreKeys -func NewStore(cms storetypes.CacheMultiStore, keys map[string]*storetypes.KVStoreKey) *Store { +func NewStore(cms storetypes.MultiStore, keys map[string]storetypes.StoreKey) *Store { s := &Store{ stores: make(map[storetypes.StoreKey]types.SnapshotKVStore), storeKeys: vmtypes.SortedKVStoreKeys(keys), @@ -29,8 +28,13 @@ func NewStore(cms storetypes.CacheMultiStore, keys map[string]*storetypes.KVStor } for _, key := range s.storeKeys { - store := cms.GetKVStore(key).(storetypes.CacheKVStore) - s.stores[key] = snapshotkv.NewStore(store) + if _, ok := key.(*storetypes.KVStoreKey); ok { + store := cms.GetKVStore(key) + s.stores[key] = snapshotkv.NewStore(store.(storetypes.CacheWrap)) + } else { + store := cms.GetObjKVStore(key) + s.stores[key] = snapshotkv.NewStore(store.(storetypes.CacheWrap)) + } } return s @@ -88,16 +92,6 @@ func (s *Store) CacheWrap() storetypes.CacheWrap { return s.CacheMultiStore().(storetypes.CacheWrap) } -// CacheWrapWithTrace implements the CacheWrapper interface. -// -// NOTE: CacheWrapWithTrace is a method that enables a Store to satisfy the CacheWrapper interface. -// Although it accepts an io.Writer and tracingContext as inputs, these are not used in the implementation. -// Instead, it simply adds an additional cache layer on top of the existing KVStores. -// As a result, while the return value differs, the behavior is effectively the same as the Snapshot() method. -func (s *Store) CacheWrapWithTrace(_ io.Writer, _ storetypes.TraceContext) storetypes.CacheWrap { - return s.CacheWrap() -} - // CacheMultiStore snapshots store and return current store. func (s *Store) CacheMultiStore() storetypes.CacheMultiStore { s.Snapshot() @@ -117,7 +111,7 @@ func (s *Store) GetStore(key storetypes.StoreKey) storetypes.Store { if key == nil || store == nil { panic(fmt.Sprintf("kv store with key %v has not been registered in stores", key)) } - return store.CurrentStore() + return store.CurrentStore().(storetypes.KVStore) } // GetKVStore returns an underlying KVStore by key. @@ -126,30 +120,19 @@ func (s *Store) GetKVStore(key storetypes.StoreKey) storetypes.KVStore { if key == nil || store == nil { panic(fmt.Sprintf("kv store with key %v has not been registered in stores", key)) } - return store.CurrentStore() -} - -// TracingEnabled returns if tracing is enabled for the MultiStore. -func (s *Store) TracingEnabled() bool { - return false -} - -// SetTracer sets the tracer for the MultiStore that the underlying -// stores will utilize to trace operations. A MultiStore is returned. -// -// NOTE: SetTracer no-op function. -func (s *Store) SetTracer(_ io.Writer) storetypes.MultiStore { - return s + return store.CurrentStore().(storetypes.KVStore) } -// SetTracingContext updates the tracing context for the MultiStore by merging -// the given context with the existing context by key. Any existing keys will -// be overwritten. It is implied that the caller should update the context when -// necessary between tracing operations. It returns a modified MultiStore. -// -// NOTE: SetTracingContext no-op function -func (s *Store) SetTracingContext(_ storetypes.TraceContext) storetypes.MultiStore { - return s +func (s *Store) GetObjKVStore(key storetypes.StoreKey) storetypes.ObjKVStore { + store := s.stores[key] + if key == nil || store == nil { + panic(fmt.Sprintf("kv store with key %v has not been registered in stores", key)) + } + objStore, ok := store.CurrentStore().(storetypes.ObjKVStore) + if !ok { + panic(fmt.Sprintf("store with key %v is not ObjKVStore", key)) + } + return objStore } // LatestVersion returns the branch version of the store diff --git a/x/vm/store/snapshotmulti/store_bench_test.go b/x/vm/store/snapshotmulti/store_bench_test.go index ed8a0f2d..445c2023 100644 --- a/x/vm/store/snapshotmulti/store_bench_test.go +++ b/x/vm/store/snapshotmulti/store_bench_test.go @@ -8,13 +8,13 @@ import ( dbm "github.com/cosmos/cosmos-db" - "cosmossdk.io/store/cachekv" - "cosmossdk.io/store/dbadapter" - "cosmossdk.io/store/types" + "github.com/cosmos/cosmos-sdk/store/v2/cachekv" + "github.com/cosmos/cosmos-sdk/store/v2/dbadapter" + "github.com/cosmos/cosmos-sdk/store/v2/types" ) var ( - benchSink interface{} + benchSink any benchTxCount = flag.Int("bench.numtx", 256, "number of transactions per benchmark run") ) diff --git a/x/vm/store/snapshotmulti/store_test.go b/x/vm/store/snapshotmulti/store_test.go index ebba81e5..83cc6955 100644 --- a/x/vm/store/snapshotmulti/store_test.go +++ b/x/vm/store/snapshotmulti/store_test.go @@ -9,9 +9,9 @@ import ( dbm "github.com/cosmos/cosmos-db" "github.com/cosmos/evm/x/vm/store/snapshotmulti" - "cosmossdk.io/store/cachekv" - "cosmossdk.io/store/dbadapter" - storetypes "cosmossdk.io/store/types" + "github.com/cosmos/cosmos-sdk/store/v2/cachekv" + "github.com/cosmos/cosmos-sdk/store/v2/dbadapter" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" ) func setupStore() (*snapshotmulti.Store, *storetypes.KVStoreKey) { @@ -136,18 +136,6 @@ func TestSnapshotMultiCacheWrap(t *testing.T) { require.Equal(t, 1, idx) } -func TestSnapshotMultiCacheWrapWithTrace(t *testing.T) { - snapshotStore, _ := setupStore() - - // NOTES: CacheWrapWithTrace of snapshotmulti.Store is same with regualr CacheWrap, - // and arguments are not actually used. - wrap := snapshotStore.CacheWrapWithTrace(nil, nil) - require.Equal(t, snapshotStore, wrap) - - idx := snapshotStore.Snapshot() - require.Equal(t, 1, idx) -} - func TestSnapshotMultiCacheMultiStore(t *testing.T) { snapshotStore, _ := setupStore() @@ -165,15 +153,6 @@ func TestSnapshotMultiCacheMultiStoreWithVersion(t *testing.T) { require.Equal(t, snapshotStore, m) } -func TestSnapshotMultiMetadata(t *testing.T) { - snapshotStore, _ := setupStore() - - require.Equal(t, storetypes.StoreTypeMulti, snapshotStore.GetStoreType()) - require.False(t, snapshotStore.TracingEnabled()) - require.Equal(t, snapshotStore, snapshotStore.SetTracer(nil)) - require.Equal(t, snapshotStore, snapshotStore.SetTracingContext(nil)) -} - func TestSnapshotMultiLatestVersion(t *testing.T) { snapshotStore, _ := setupStore() diff --git a/x/vm/store/types/store.go b/x/vm/store/types/store.go index 0521f219..b42361f0 100644 --- a/x/vm/store/types/store.go +++ b/x/vm/store/types/store.go @@ -1,7 +1,7 @@ package types import ( - storetypes "cosmossdk.io/store/types" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" ) const InitialHead = 0 @@ -26,7 +26,7 @@ type SnapshotKVStore interface { // CurrentStore returns the underlying CacheKVStore that is currently // active (i.e., where reads and writes will be applied). - CurrentStore() storetypes.CacheKVStore + CurrentStore() storetypes.CacheWrap // Commit flushes all pending changes in the current store layer // down to its parent, making them permanent. diff --git a/x/vm/types/chain_config.go b/x/vm/types/chain_config.go index 930ffdcf..84d12b77 100644 --- a/x/vm/types/chain_config.go +++ b/x/vm/types/chain_config.go @@ -13,6 +13,8 @@ import ( // opcodes are active based on Ethereum upgrades. var chainConfig *ChainConfig +var gethChainConfig *gethparams.ChainConfig + // EthereumConfig returns an Ethereum ChainConfig for EVM state transitions. // All the negative or nil values are converted to nil func (cc ChainConfig) EthereumConfig(chainID *big.Int) *gethparams.ChainConfig { @@ -20,6 +22,11 @@ func (cc ChainConfig) EthereumConfig(chainID *big.Int) *gethparams.ChainConfig { if chainID != nil { cID = chainID } + + if gethChainConfig != nil { + return gethChainConfig + } + return &gethparams.ChainConfig{ ChainID: cID, HomesteadBlock: getBlockValue(cc.HomesteadBlock), diff --git a/x/vm/types/config.go b/x/vm/types/config.go index 4fc952a7..232dbe97 100644 --- a/x/vm/types/config.go +++ b/x/vm/types/config.go @@ -3,7 +3,6 @@ // Its primary purpose is to be used during application initialization. //go:build !test -// +build !test package types @@ -23,7 +22,7 @@ func (ec *EVMConfigurator) Configure() error { return fmt.Errorf("error configuring EVMConfigurator: already sealed and cannot be modified") } - if err := setEVMCoinInfo(ec.evmCoinInfo); err != nil { + if err := setCoinInfo(ec.evmCoinInfo); err != nil { return err } @@ -48,7 +47,7 @@ func (ec *EVMConfigurator) ResetTestConfig() { // GetEthChainConfig returns the `chainConfig` used in the EVM (geth type). func GetEthChainConfig() *geth.ChainConfig { - return chainConfig.EthereumConfig(nil) + return gethChainConfig } // GetChainConfig returns the `chainConfig`. @@ -70,7 +69,11 @@ func SetChainConfig(cc *ChainConfig) error { if err := config.Validate(); err != nil { return err } + chainConfig = config + gethChainConfig = nil + gethChainConfig = config.EthereumConfig(nil) + return nil } diff --git a/x/vm/types/config_testing.go b/x/vm/types/config_testing.go index fe16fab1..b47d8f6e 100644 --- a/x/vm/types/config_testing.go +++ b/x/vm/types/config_testing.go @@ -3,13 +3,14 @@ // Its primary purpose is to be used during application initialization. //go:build test -// +build test package types import ( "errors" "fmt" + "sync" + "github.com/ethereum/go-ethereum/core/vm" geth "github.com/ethereum/go-ethereum/params" ) @@ -18,6 +19,9 @@ import ( // opcodes are active based on Ethereum upgrades. var testChainConfig *ChainConfig +// testChainConfigMu protects concurrent access to testChainConfig +var testChainConfigMu sync.RWMutex + // Configure applies the changes to the virtual machine configuration. func (ec *EVMConfigurator) Configure() error { // If Configure method has been already used in the object, return @@ -48,10 +52,15 @@ func (ec *EVMConfigurator) Configure() error { func (ec *EVMConfigurator) ResetTestConfig() { vm.ResetActivators() resetEVMCoinInfo() + testChainConfigMu.Lock() testChainConfig = nil + testChainConfigMu.Unlock() } func setTestChainConfig(cc *ChainConfig) error { + testChainConfigMu.Lock() + defer testChainConfigMu.Unlock() + if testChainConfig != nil { return errors.New("chainConfig already set. Cannot set again the chainConfig. Call the configurators ResetTestConfig method before configuring a new chain.") } @@ -70,6 +79,9 @@ func setTestChainConfig(cc *ChainConfig) error { // default values. The method is private because it should only be called once // in the EVMConfigurator. func SetChainConfig(cc *ChainConfig) error { + testChainConfigMu.Lock() + defer testChainConfigMu.Unlock() + if chainConfig != nil && chainConfig.ChainId != DefaultEVMChainID { return errors.New("chainConfig already set. Cannot set again the chainConfig") } @@ -87,10 +99,14 @@ func SetChainConfig(cc *ChainConfig) error { // GetEthChainConfig returns the `chainConfig` used in the EVM (geth type). func GetEthChainConfig() *geth.ChainConfig { + testChainConfigMu.RLock() + defer testChainConfigMu.RUnlock() return testChainConfig.EthereumConfig(nil) } // GetChainConfig returns the `chainConfig`. func GetChainConfig() *ChainConfig { + testChainConfigMu.RLock() + defer testChainConfigMu.RUnlock() return testChainConfig } diff --git a/x/vm/types/denom_config.go b/x/vm/types/denom_config.go index ca731fc3..6ebd4345 100644 --- a/x/vm/types/denom_config.go +++ b/x/vm/types/denom_config.go @@ -3,101 +3,84 @@ // Its primary purpose is to be used during application initialization. //go:build !test -// +build !test package types import ( - "errors" "fmt" + "sync/atomic" sdk "github.com/cosmos/cosmos-sdk/types" ) // evmCoinInfo hold the information of the coin used in the EVM as gas token. It // can only be set via `EVMConfigurator` before starting the app. -var evmCoinInfo *EvmCoinInfo +var evmCoinInfo atomic.Pointer[EvmCoinInfo] -// setEVMCoinDecimals allows to define the decimals used in the representation -// of the EVM coin. -func setEVMCoinDecimals(d Decimals) error { - if err := d.Validate(); err != nil { - return fmt.Errorf("setting EVM coin decimals: %w", err) - } - - evmCoinInfo.Decimals = d.Uint32() - return nil +// GetCoinInfo returns EvmCoinInfo if set, otherwise panics. +func GetCoinInfo() EvmCoinInfo { + return *getCoinInfo() } -// setEVMCoinDenom allows to define the denom of the coin used in the EVM. -func setEVMCoinDenom(denom string) error { - if err := sdk.ValidateDenom(denom); err != nil { - return fmt.Errorf("setting EVM coin denom: %w", err) - } - evmCoinInfo.Denom = denom - return nil -} - -// setEVMCoinExtendedDenom allows to define the extended denom of the coin used in the EVM. -func setEVMCoinExtendedDenom(extendedDenom string) error { - if err := sdk.ValidateDenom(extendedDenom); err != nil { - return err - } - evmCoinInfo.ExtendedDenom = extendedDenom - return nil -} - -func setDisplayDenom(displayDenom string) error { - if err := sdk.ValidateDenom(displayDenom); err != nil { - return fmt.Errorf("setting EVM coin display denom: %w", err) - } - evmCoinInfo.DisplayDenom = displayDenom - return nil -} - -// GetEVMCoinDecimals returns the decimals used in the representation of the EVM -// coin. +// GetEVMCoinDecimals returns the decimals used in the representation of the EVM coin. func GetEVMCoinDecimals() Decimals { - return Decimals(evmCoinInfo.Decimals) + return Decimals(getCoinInfo().Decimals) } // GetEVMCoinDenom returns the denom used for the EVM coin. func GetEVMCoinDenom() string { - return evmCoinInfo.Denom + return getCoinInfo().Denom } // GetEVMCoinExtendedDenom returns the extended denom used for the EVM coin. func GetEVMCoinExtendedDenom() string { - return evmCoinInfo.ExtendedDenom + return getCoinInfo().ExtendedDenom } // GetEVMCoinDisplayDenom returns the display denom used for the EVM coin. func GetEVMCoinDisplayDenom() string { - return evmCoinInfo.DisplayDenom + return getCoinInfo().DisplayDenom } -// setEVMCoinInfo allows to define denom and decimals of the coin used in the EVM. -func setEVMCoinInfo(eci EvmCoinInfo) error { - if evmCoinInfo != nil { - return errors.New("EVM coin info already set") +// getCoinInfo return evmCoinInfo or panics if not present! +func getCoinInfo() *EvmCoinInfo { + if info := evmCoinInfo.Load(); info != nil { + return info } - if Decimals(eci.Decimals) == EighteenDecimals { - if eci.Denom != eci.ExtendedDenom { - return errors.New("EVM coin denom and extended denom must be the same for 18 decimals") - } + panic("global evmCoinInfo is not set yet!") +} + +func setCoinInfo(info EvmCoinInfo) error { + if err := validateCoinInfo(&info); err != nil { + return err } - evmCoinInfo = new(EvmCoinInfo) + evmCoinInfo.Store(&info) - if err := setEVMCoinDenom(eci.Denom); err != nil { - return err + return nil +} + +func validateCoinInfo(info *EvmCoinInfo) error { + if err := sdk.ValidateDenom(info.Denom); err != nil { + return fmt.Errorf("invalid EVM denom: %w", err) } - if err := setEVMCoinExtendedDenom(eci.ExtendedDenom); err != nil { - return err + + if err := sdk.ValidateDenom(info.ExtendedDenom); err != nil { + return fmt.Errorf("invalid EVM extended denom: %w", err) } - if err := setDisplayDenom(eci.DisplayDenom); err != nil { - return err + + if err := sdk.ValidateDenom(info.DisplayDenom); err != nil { + return fmt.Errorf("invalid EVM display denom: %w", err) + } + + if err := Decimals(info.Decimals).Validate(); err != nil { + return fmt.Errorf("invalid EVM decimals: %w", err) } - return setEVMCoinDecimals(Decimals(eci.Decimals)) + + if Decimals(info.Decimals) == EighteenDecimals && info.Denom != info.ExtendedDenom { + return fmt.Errorf("EVM denom and extended denom must be the same for 18 decimals") + } + + return nil } diff --git a/x/vm/types/denom_config_testing.go b/x/vm/types/denom_config_testing.go index fede6ffd..9fb3f60f 100644 --- a/x/vm/types/denom_config_testing.go +++ b/x/vm/types/denom_config_testing.go @@ -3,13 +3,13 @@ // Its primary purpose is to be used during application initialization. //go:build test -// +build test package types import ( "errors" "fmt" + "sync" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -18,6 +18,17 @@ import ( // can only be set via `EVMConfigurator` before starting the app. var testingEvmCoinInfo *EvmCoinInfo +// testingEvmCoinInfoMu protects concurrent access to testingEvmCoinInfo +var testingEvmCoinInfoMu sync.RWMutex + +// SetDefaultEvmCoinInfo sets the default EVM coin info to be used as fallback. +// This should be called during keeper initialization. +func SetDefaultEvmCoinInfo(coinInfo EvmCoinInfo) { + testingEvmCoinInfoMu.Lock() + defer testingEvmCoinInfoMu.Unlock() + testingEvmCoinInfo = &coinInfo +} + // setEVMCoinDecimals allows to define the decimals used in the representation // of the EVM coin. func setEVMCoinDecimals(d Decimals) error { @@ -55,29 +66,50 @@ func setDisplayDenom(displayDenom string) error { return nil } +// GetCoinInfo returns EvmCoinInfo if set, otherwise panics. +func GetCoinInfo() EvmCoinInfo { + testingEvmCoinInfoMu.RLock() + defer testingEvmCoinInfoMu.RUnlock() + if testingEvmCoinInfo == nil { + panic("global testingEvmCoinInfo is not set yet!") + } + return *testingEvmCoinInfo +} + // GetEVMCoinDecimals returns the decimals used in the representation of the EVM // coin. func GetEVMCoinDecimals() Decimals { + testingEvmCoinInfoMu.RLock() + defer testingEvmCoinInfoMu.RUnlock() return Decimals(testingEvmCoinInfo.Decimals) } // GetEVMCoinDenom returns the denom used for the EVM coin. func GetEVMCoinDenom() string { + testingEvmCoinInfoMu.RLock() + defer testingEvmCoinInfoMu.RUnlock() return testingEvmCoinInfo.Denom } // GetEVMCoinExtendedDenom returns the extended denom used for the EVM coin. func GetEVMCoinExtendedDenom() string { + testingEvmCoinInfoMu.RLock() + defer testingEvmCoinInfoMu.RUnlock() return testingEvmCoinInfo.ExtendedDenom } // GetEVMCoinDisplayDenom returns the display denom used for the EVM coin. func GetEVMCoinDisplayDenom() string { + testingEvmCoinInfoMu.RLock() + defer testingEvmCoinInfoMu.RUnlock() return testingEvmCoinInfo.DisplayDenom } // setTestingEVMCoinInfo allows to define denom and decimals of the coin used in the EVM. func setTestingEVMCoinInfo(eci EvmCoinInfo) error { + testingEvmCoinInfoMu.Lock() + defer testingEvmCoinInfoMu.Unlock() + if testingEvmCoinInfo != nil { return errors.New("testing EVM coin info already set. Make sure you run the configurator's ResetTestConfig before trying to set a new evm coin info") } @@ -104,5 +136,7 @@ func setTestingEVMCoinInfo(eci EvmCoinInfo) error { // resetEVMCoinInfo resets to nil the testingEVMCoinInfo func resetEVMCoinInfo() { + testingEvmCoinInfoMu.Lock() + defer testingEvmCoinInfoMu.Unlock() testingEvmCoinInfo = nil } diff --git a/x/vm/types/errors.go b/x/vm/types/errors.go index aba44843..007fa054 100644 --- a/x/vm/types/errors.go +++ b/x/vm/types/errors.go @@ -32,6 +32,7 @@ const ( codeErrABIPack codeErrABIUnpack codeErrInvalidPreinstall + codeErrNilStateDB ) var ( @@ -94,6 +95,9 @@ var ( // RevertSelector is selector of ErrExecutionReverted RevertSelector = crypto.Keccak256([]byte("Error(string)"))[:4] + + // ErrNilStateDB + ErrNilStateDB = errorsmod.Register(ModuleName, codeErrNilStateDB, "stateDB cannot be nil") ) // RevertReasonBytes converts a message to ABI-encoded revert bytes. @@ -141,6 +145,6 @@ func (e *RevertError) ErrorCode() int { } // ErrorData returns the hex encoded revert reason. -func (e *RevertError) ErrorData() interface{} { +func (e *RevertError) ErrorData() any { return e.reason } diff --git a/x/vm/types/evm.pb.go b/x/vm/types/evm.pb.go index 28450b4f..912f47df 100644 --- a/x/vm/types/evm.pb.go +++ b/x/vm/types/evm.pb.go @@ -987,7 +987,9 @@ type EvmCoinInfo struct { Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"` ExtendedDenom string `protobuf:"bytes,2,opt,name=extended_denom,json=extendedDenom,proto3" json:"extended_denom,omitempty"` DisplayDenom string `protobuf:"bytes,3,opt,name=display_denom,json=displayDenom,proto3" json:"display_denom,omitempty"` - Decimals uint32 `protobuf:"varint,4,opt,name=decimals,proto3" json:"decimals,omitempty"` + // decimals is now deprecated and will be removed in a future release. When it is removed we will assume + // the evm token denom is 18 decimal precision. + Decimals uint32 `protobuf:"varint,4,opt,name=decimals,proto3" json:"decimals,omitempty"` // Deprecated: Do not use. } func (m *EvmCoinInfo) Reset() { *m = EvmCoinInfo{} } @@ -1044,6 +1046,7 @@ func (m *EvmCoinInfo) GetDisplayDenom() string { return "" } +// Deprecated: Do not use. func (m *EvmCoinInfo) GetDecimals() uint32 { if m != nil { return m.Decimals @@ -1071,139 +1074,140 @@ func init() { func init() { proto.RegisterFile("cosmos/evm/vm/v1/evm.proto", fileDescriptor_d1129b8db63d55c7) } var fileDescriptor_d1129b8db63d55c7 = []byte{ - // 2111 bytes of a gzipped FileDescriptorProto + // 2116 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, 0xd4, 0x7a, 0x44, 0xcb, 0x34, 0xed, 0x68, 0xd5, 0x4d, - 0x5b, 0xa8, 0x46, 0x2a, 0x59, 0x72, 0xd4, 0x1a, 0x4e, 0xd3, 0x42, 0x94, 0x98, 0x56, 0xaa, 0x6c, - 0x0b, 0x43, 0x35, 0x46, 0x8a, 0x14, 0x8b, 0xe1, 0xee, 0x78, 0xb9, 0xd1, 0xee, 0x0e, 0xb1, 0xb3, - 0xa4, 0xc5, 0xfe, 0x81, 0x06, 0xee, 0x25, 0xed, 0xdd, 0x40, 0x80, 0x5e, 0x72, 0xcc, 0x4f, 0xe8, - 0x31, 0xc7, 0x1c, 0x8b, 0x02, 0x5d, 0x14, 0xf4, 0x21, 0x80, 0x8e, 0xfa, 0x05, 0xc5, 0x7c, 0xf0, - 0x5b, 0x61, 0x15, 0x40, 0xb0, 0xe7, 0x79, 0x3f, 0x9e, 0x67, 0x3e, 0xde, 0xdd, 0x79, 0x97, 0xa0, - 0xe2, 0x50, 0x16, 0x52, 0xb6, 0x4d, 0x3a, 0xe1, 0x36, 0xff, 0xdb, 0xe1, 0xa3, 0xad, 0x56, 0x4c, - 0x13, 0x0a, 0x0d, 0xe9, 0xdb, 0xe2, 0x16, 0xfe, 0xb7, 0x53, 0xb9, 0x85, 0x43, 0x3f, 0xa2, 0xdb, - 0xe2, 0x5f, 0x19, 0x54, 0x29, 0x79, 0xd4, 0xa3, 0x62, 0xb8, 0xcd, 0x47, 0xd2, 0x6a, 0xfd, 0x5d, - 0x03, 0x8b, 0xa7, 0x38, 0xc6, 0x21, 0x83, 0x3b, 0x20, 0x47, 0x3a, 0xa1, 0xed, 0x92, 0x88, 0x86, - 0xe5, 0xcc, 0x46, 0x66, 0x33, 0x57, 0x2d, 0x5d, 0xa5, 0xa6, 0xd1, 0xc5, 0x61, 0xf0, 0xc4, 0x1a, - 0xb8, 0x2c, 0xa4, 0x93, 0x4e, 0x78, 0xc8, 0x87, 0x70, 0x1f, 0x00, 0x72, 0x91, 0xc4, 0xd8, 0x26, - 0x7e, 0x8b, 0x95, 0xb5, 0x8d, 0xec, 0x66, 0xb6, 0x6a, 0xf5, 0x52, 0x33, 0x57, 0xe3, 0xd6, 0xda, - 0xd1, 0x29, 0xbb, 0x4a, 0xcd, 0x5b, 0x8a, 0x60, 0x10, 0x68, 0xa1, 0x9c, 0x00, 0x35, 0xbf, 0xc5, - 0xe0, 0x2e, 0x28, 0x70, 0x6a, 0xa7, 0x89, 0xa3, 0x88, 0x04, 0xac, 0xbc, 0xb4, 0x91, 0xdd, 0xcc, - 0x55, 0x57, 0x7a, 0xa9, 0x99, 0xaf, 0x7d, 0xfc, 0xf4, 0x40, 0x99, 0x51, 0x9e, 0x74, 0xc2, 0x3e, - 0x80, 0x7f, 0x02, 0x45, 0xec, 0x38, 0x84, 0x31, 0xdb, 0xa1, 0x51, 0x12, 0xd3, 0xa0, 0xac, 0x6f, - 0x64, 0x36, 0xf3, 0xbb, 0xe6, 0xd6, 0xe4, 0x46, 0x6c, 0xed, 0x8b, 0xb8, 0x03, 0x19, 0x56, 0xbd, - 0xfd, 0x4d, 0x6a, 0xce, 0xf5, 0x52, 0x73, 0x79, 0xcc, 0x8c, 0x96, 0xf1, 0x28, 0x84, 0x4f, 0xc0, - 0x5d, 0xec, 0x24, 0x7e, 0x87, 0xd8, 0x2c, 0xc1, 0x89, 0xef, 0xd8, 0xad, 0x98, 0x38, 0x34, 0x6c, - 0xf9, 0x01, 0x61, 0xe5, 0x1c, 0x9f, 0x1f, 0xba, 0x23, 0x03, 0xea, 0xc2, 0x7f, 0x3a, 0x74, 0xc3, - 0x87, 0xa0, 0xd4, 0xf4, 0x59, 0x42, 0xe3, 0xae, 0xcd, 0x48, 0xdc, 0x21, 0xf6, 0x2b, 0x3f, 0x72, - 0xe9, 0xab, 0x32, 0xd8, 0xc8, 0x6c, 0x6a, 0x08, 0x2a, 0x5f, 0x9d, 0xbb, 0x5e, 0x08, 0x0f, 0xfc, - 0x14, 0xac, 0x91, 0x8b, 0x84, 0x44, 0x2e, 0x71, 0xe5, 0x06, 0xdb, 0xb4, 0x95, 0xf8, 0x34, 0x62, - 0xe5, 0xbc, 0x58, 0xd4, 0x4f, 0xa7, 0x17, 0x55, 0x53, 0xf1, 0xe2, 0x10, 0x9e, 0xcb, 0x68, 0x54, - 0x22, 0xd7, 0x58, 0x9f, 0xdc, 0x7b, 0xfd, 0xdd, 0xd7, 0x0f, 0xd6, 0x46, 0x6a, 0xe7, 0x82, 0x57, - 0x8f, 0x3c, 0xf1, 0x63, 0x4d, 0x9f, 0x37, 0xb2, 0xc7, 0x9a, 0x9e, 0x35, 0xb4, 0x63, 0x4d, 0x5f, - 0x30, 0x16, 0x8f, 0x35, 0x7d, 0xd1, 0x58, 0xb2, 0x3e, 0x04, 0xa5, 0xeb, 0x24, 0xe0, 0x4f, 0x40, - 0x71, 0x7c, 0xaa, 0xb2, 0x4c, 0xd0, 0xf2, 0x98, 0xb4, 0xf5, 0xb7, 0x0c, 0x18, 0xdf, 0x60, 0xb8, - 0x0f, 0x16, 0x9d, 0x98, 0xe0, 0x84, 0x88, 0x84, 0xfc, 0xee, 0xbb, 0xff, 0xe7, 0xa0, 0xce, 0xba, - 0x2d, 0x52, 0xd5, 0xf8, 0x61, 0x21, 0x95, 0x08, 0x3f, 0x04, 0x9a, 0x83, 0x83, 0xa0, 0x3c, 0xff, - 0x43, 0x09, 0x44, 0x9a, 0xf5, 0x9f, 0x0c, 0xb8, 0x35, 0x15, 0x01, 0x1d, 0x90, 0x57, 0x85, 0x94, - 0x74, 0x5b, 0x72, 0x72, 0xc5, 0xdd, 0xfb, 0xdf, 0xc7, 0x2d, 0x48, 0x7f, 0xdc, 0x4b, 0x4d, 0x30, - 0xc4, 0x57, 0xa9, 0x09, 0x65, 0x7d, 0x8f, 0x10, 0x59, 0x08, 0xe0, 0x41, 0x04, 0x74, 0xc0, 0xea, - 0x78, 0xb5, 0xda, 0x81, 0xcf, 0x92, 0xf2, 0xbc, 0x28, 0xf4, 0x47, 0xbd, 0xd4, 0x1c, 0x9f, 0xd8, - 0x89, 0xcf, 0x92, 0xab, 0xd4, 0xac, 0x8c, 0xb1, 0x8e, 0x66, 0x5a, 0xe8, 0x16, 0x9e, 0x4c, 0xb0, - 0xbe, 0x32, 0x40, 0xfe, 0xa0, 0x89, 0xfd, 0xe8, 0x80, 0x46, 0x2f, 0x7d, 0x0f, 0x7e, 0x0a, 0x56, - 0x9a, 0x34, 0x24, 0x2c, 0x21, 0xd8, 0xb5, 0x1b, 0x01, 0x75, 0xce, 0xd5, 0x23, 0xfd, 0xe8, 0xdf, - 0xa9, 0x79, 0x5b, 0x2e, 0x90, 0xb9, 0xe7, 0x5b, 0x3e, 0xdd, 0x0e, 0x71, 0xd2, 0xdc, 0x3a, 0x8a, - 0xb8, 0xe8, 0x9a, 0x14, 0x9d, 0xc8, 0xb4, 0x50, 0x71, 0x60, 0xa9, 0x72, 0x03, 0x6c, 0x82, 0xa2, - 0x8b, 0xa9, 0xfd, 0x92, 0xc6, 0xe7, 0x8a, 0x7c, 0x5e, 0x90, 0x57, 0xbf, 0x97, 0xbc, 0x97, 0x9a, - 0x85, 0xc3, 0xfd, 0xe7, 0x1f, 0xd1, 0xf8, 0x5c, 0x50, 0x5c, 0xa5, 0xe6, 0x6d, 0x29, 0x36, 0x4e, - 0x64, 0xa1, 0x82, 0x8b, 0xe9, 0x20, 0x0c, 0xbe, 0x00, 0xc6, 0x20, 0x80, 0xb5, 0x5b, 0x2d, 0x1a, - 0x27, 0xe5, 0xec, 0x46, 0x66, 0x53, 0xaf, 0xfe, 0xbc, 0x97, 0x9a, 0x45, 0x45, 0x59, 0x97, 0x9e, - 0xab, 0xd4, 0xbc, 0x33, 0x41, 0xaa, 0x72, 0x2c, 0x54, 0x54, 0xb4, 0x2a, 0x14, 0x36, 0x40, 0x81, - 0xf8, 0xad, 0x9d, 0xbd, 0x87, 0x6a, 0x01, 0x9a, 0x58, 0xc0, 0x6f, 0x66, 0x2d, 0x20, 0x5f, 0x3b, - 0x3a, 0xdd, 0xd9, 0x7b, 0xd8, 0x9f, 0xff, 0xaa, 0x7a, 0xaf, 0x8d, 0xb0, 0x58, 0x28, 0x2f, 0xa1, - 0x9c, 0x7c, 0x5f, 0x63, 0x4f, 0x69, 0x2c, 0xde, 0x54, 0x63, 0xef, 0x3a, 0x8d, 0xbd, 0x71, 0x8d, - 0xbd, 0x71, 0x8d, 0xc7, 0x4a, 0x63, 0xe9, 0xa6, 0x1a, 0x8f, 0xaf, 0xd3, 0x78, 0x3c, 0xae, 0x21, - 0x63, 0x78, 0x31, 0x35, 0xba, 0x7f, 0xc6, 0x51, 0xe2, 0xb7, 0x43, 0x25, 0xa3, 0xdf, 0xb8, 0x98, - 0x26, 0x32, 0x2d, 0x54, 0x1c, 0x58, 0x24, 0xfb, 0x39, 0x28, 0x39, 0x34, 0x62, 0x09, 0xb7, 0x45, - 0xb4, 0x15, 0x10, 0x25, 0x91, 0x13, 0x12, 0x8f, 0x67, 0x49, 0xdc, 0x93, 0x12, 0xd7, 0xa5, 0x5b, - 0x68, 0x75, 0xdc, 0x2c, 0xc5, 0x6c, 0x60, 0xb4, 0x48, 0x42, 0x62, 0xd6, 0x68, 0xc7, 0x9e, 0x12, - 0x02, 0x42, 0xe8, 0xfd, 0x59, 0x42, 0xaa, 0xac, 0x26, 0x53, 0x2d, 0xb4, 0x32, 0x34, 0x49, 0x81, - 0x4f, 0x40, 0xd1, 0xe7, 0xaa, 0x8d, 0x76, 0xa0, 0xe8, 0xf3, 0x82, 0x7e, 0x77, 0x16, 0xbd, 0x7a, - 0x14, 0xc6, 0x13, 0x2d, 0xb4, 0xdc, 0x37, 0x48, 0x6a, 0x17, 0xc0, 0xb0, 0xed, 0xc7, 0xb6, 0x17, - 0x60, 0xc7, 0x27, 0xb1, 0xa2, 0x2f, 0x08, 0xfa, 0x5f, 0xcc, 0xa2, 0xbf, 0x2b, 0xe9, 0xa7, 0x93, - 0x2d, 0x64, 0x70, 0xe3, 0x6f, 0xa5, 0x4d, 0xaa, 0xd4, 0x41, 0xa1, 0x41, 0xe2, 0xc0, 0x8f, 0x14, - 0xff, 0xb2, 0xe0, 0x7f, 0x38, 0x8b, 0x5f, 0x55, 0xd0, 0x68, 0x9a, 0x85, 0xf2, 0x12, 0x0e, 0x48, - 0x03, 0x1a, 0xb9, 0xb4, 0x4f, 0x7a, 0xeb, 0xc6, 0xa4, 0xa3, 0x69, 0x16, 0xca, 0x4b, 0x28, 0x49, - 0x3d, 0xb0, 0x8a, 0xe3, 0x98, 0xbe, 0x9a, 0xd8, 0x10, 0x28, 0xb8, 0x7f, 0x39, 0x8b, 0xbb, 0xff, - 0x72, 0x9d, 0xce, 0xe6, 0x2f, 0x57, 0x6e, 0x1d, 0xdb, 0x12, 0x17, 0x40, 0x2f, 0xc6, 0xdd, 0x09, - 0x9d, 0xd2, 0x8d, 0x37, 0x7e, 0x3a, 0xd9, 0x42, 0x06, 0x37, 0x8e, 0xa9, 0x7c, 0x06, 0x4a, 0x21, - 0x89, 0x3d, 0x62, 0x47, 0x24, 0x61, 0xad, 0xc0, 0x4f, 0x94, 0xce, 0xed, 0x1b, 0x3f, 0x07, 0xd7, - 0xa5, 0x5b, 0x08, 0x0a, 0xf3, 0x33, 0x65, 0x95, 0x5a, 0x77, 0x81, 0xee, 0xf0, 0xdb, 0xc2, 0xf6, - 0xdd, 0x72, 0x59, 0xb4, 0x26, 0x4b, 0x02, 0x1f, 0xb9, 0xb0, 0x04, 0x16, 0xe4, 0xdd, 0x7e, 0x57, - 0xdc, 0xed, 0x12, 0xc0, 0x0a, 0xd0, 0x5d, 0xe2, 0xf8, 0x21, 0x0e, 0x58, 0xb9, 0x22, 0x12, 0x06, - 0x18, 0x7e, 0x0c, 0x96, 0x59, 0x13, 0x47, 0x5e, 0x13, 0xfb, 0x76, 0xe2, 0x87, 0xa4, 0x7c, 0x4f, - 0xcc, 0x78, 0x67, 0xd6, 0x8c, 0x4b, 0x72, 0xc6, 0x63, 0x79, 0x16, 0x2a, 0xf4, 0xf1, 0x99, 0x1f, - 0x12, 0x78, 0x0a, 0xf2, 0x0e, 0x8e, 0x9c, 0x76, 0x24, 0x59, 0xef, 0x0b, 0xd6, 0xed, 0x59, 0xac, - 0xea, 0x2a, 0x1e, 0xc9, 0xb2, 0x10, 0x90, 0xa8, 0xcf, 0xd8, 0x8a, 0xb1, 0xd7, 0x26, 0x92, 0xf1, - 0x9d, 0x1b, 0x33, 0x8e, 0x64, 0x59, 0x08, 0x48, 0xd4, 0x67, 0xec, 0x90, 0xf8, 0x3c, 0x50, 0x8c, - 0xeb, 0x37, 0x66, 0x1c, 0xc9, 0xb2, 0x10, 0x90, 0x48, 0x30, 0x3e, 0x05, 0x80, 0x32, 0x7c, 0x8e, - 0x25, 0xa1, 0x29, 0x08, 0xb7, 0x66, 0x11, 0xaa, 0xfe, 0x7a, 0x98, 0x64, 0xa1, 0x9c, 0x00, 0x9c, - 0x6e, 0xd0, 0xd7, 0xad, 0x19, 0x77, 0x8e, 0x35, 0xfd, 0x8e, 0x51, 0xb6, 0xb6, 0xc1, 0x02, 0xef, - 0x5b, 0x09, 0x34, 0x40, 0xf6, 0x9c, 0x74, 0x55, 0x0f, 0xc7, 0x87, 0xfc, 0xec, 0x3b, 0x38, 0x68, - 0x13, 0x79, 0x9d, 0x23, 0x09, 0xac, 0x53, 0xb0, 0x72, 0x16, 0xe3, 0x88, 0xf1, 0x9e, 0x97, 0x46, - 0x27, 0xd4, 0x63, 0x10, 0x02, 0xad, 0x89, 0x59, 0x53, 0xe5, 0x8a, 0x31, 0xfc, 0x19, 0xd0, 0x02, - 0xea, 0x31, 0xd1, 0xd8, 0xe4, 0x77, 0x6f, 0x4f, 0x77, 0x51, 0x27, 0xd4, 0x43, 0x22, 0xc4, 0xfa, - 0x4b, 0x16, 0x64, 0x4f, 0xa8, 0x07, 0xcb, 0x60, 0x09, 0xbb, 0x6e, 0x4c, 0x18, 0x53, 0x4c, 0x7d, - 0x08, 0xd7, 0xc0, 0x62, 0x42, 0x5b, 0xbe, 0x23, 0xe9, 0x72, 0x48, 0x21, 0x2e, 0xec, 0xe2, 0x04, - 0x8b, 0x1e, 0xa0, 0x80, 0xc4, 0x98, 0x7f, 0x42, 0x88, 0x52, 0xb7, 0xa3, 0x76, 0xd8, 0x20, 0xb1, - 0xb8, 0xca, 0xb5, 0xea, 0xca, 0x65, 0x6a, 0xe6, 0x85, 0xfd, 0x99, 0x30, 0xa3, 0x51, 0x00, 0xdf, - 0x03, 0x4b, 0xc9, 0x85, 0x2d, 0xd6, 0xb0, 0x20, 0xb6, 0x78, 0xf5, 0x32, 0x35, 0x57, 0x92, 0xe1, - 0x32, 0x7f, 0x87, 0x59, 0x13, 0x2d, 0x26, 0x17, 0xfc, 0x7f, 0xb8, 0x0d, 0xf4, 0xe4, 0xc2, 0xf6, - 0x23, 0x97, 0x5c, 0x88, 0x4b, 0x5c, 0xab, 0x96, 0x2e, 0x53, 0xd3, 0x18, 0x09, 0x3f, 0xe2, 0x3e, - 0xb4, 0x94, 0x5c, 0x88, 0x01, 0x7c, 0x0f, 0x00, 0x39, 0x25, 0xa1, 0x20, 0xef, 0xe4, 0xe5, 0xcb, - 0xd4, 0xcc, 0x09, 0xab, 0xe0, 0x1e, 0x0e, 0xa1, 0x05, 0x16, 0x24, 0xb7, 0x2e, 0xb8, 0x0b, 0x97, - 0xa9, 0xa9, 0x07, 0xd4, 0x93, 0x9c, 0xd2, 0xc5, 0xb7, 0x2a, 0x26, 0x21, 0xed, 0x10, 0x57, 0x5c, - 0x8c, 0x3a, 0xea, 0x43, 0xf8, 0x01, 0x58, 0x91, 0x5a, 0xfc, 0xec, 0x59, 0x82, 0xc3, 0x96, 0xfc, - 0xda, 0xa8, 0xc2, 0xcb, 0xd4, 0x2c, 0x0a, 0xd7, 0x59, 0xdf, 0x83, 0x26, 0xb0, 0xf5, 0xc5, 0x3c, - 0xd0, 0xcf, 0x2e, 0x10, 0x61, 0xed, 0x20, 0x81, 0x1f, 0x01, 0x43, 0x34, 0x9a, 0xd8, 0x49, 0xec, - 0xb1, 0x73, 0xa9, 0xde, 0x1b, 0xde, 0x81, 0x93, 0x11, 0x16, 0x5a, 0xe9, 0x9b, 0xf6, 0xd5, 0xe1, - 0x95, 0xc0, 0x42, 0x23, 0xa0, 0x34, 0x14, 0x65, 0x54, 0x40, 0x12, 0xc0, 0x17, 0x62, 0xcb, 0x45, - 0x89, 0x64, 0x45, 0x13, 0xff, 0xa3, 0xe9, 0x12, 0x99, 0xa8, 0xb3, 0xea, 0x3d, 0xde, 0xc2, 0x5f, - 0xa5, 0x66, 0x51, 0x6a, 0xab, 0x7c, 0xeb, 0xab, 0xef, 0xbe, 0x7e, 0x90, 0xe1, 0xa7, 0x23, 0x8a, - 0xd1, 0x00, 0xd9, 0x98, 0x24, 0xe2, 0xd8, 0x0b, 0x88, 0x0f, 0xf9, 0xdb, 0x2a, 0x26, 0x1d, 0x12, - 0x27, 0xc4, 0x15, 0xc7, 0xab, 0xa3, 0x01, 0xe6, 0xaf, 0x3e, 0x0f, 0x33, 0xbb, 0xcd, 0x88, 0x2b, - 0xcf, 0x12, 0x2d, 0x79, 0x98, 0xfd, 0x81, 0x11, 0xf7, 0x89, 0xf6, 0xf9, 0x97, 0xe6, 0x9c, 0x85, - 0x41, 0x5e, 0xf5, 0xf7, 0xed, 0x56, 0x40, 0x66, 0xd4, 0xe8, 0x2e, 0x28, 0xf0, 0xaf, 0x39, 0xec, - 0x11, 0xfb, 0x9c, 0x74, 0x55, 0xa5, 0xca, 0xba, 0x53, 0xf6, 0xdf, 0x93, 0x2e, 0x43, 0xa3, 0x40, - 0x49, 0x7c, 0xa9, 0x81, 0xfc, 0x59, 0x8c, 0x1d, 0xa2, 0xba, 0x75, 0x5e, 0xed, 0x1c, 0xc6, 0x4a, - 0x42, 0x21, 0xae, 0xcd, 0x0f, 0x95, 0xb6, 0x13, 0xf5, 0x44, 0xf6, 0x21, 0xcf, 0x88, 0x09, 0xb9, - 0x20, 0x8e, 0xd8, 0x4b, 0x0d, 0x29, 0x04, 0xf7, 0xc0, 0xb2, 0xeb, 0x33, 0xdc, 0x08, 0xc4, 0xc7, - 0xab, 0x73, 0x2e, 0x97, 0x5f, 0x35, 0x2e, 0x53, 0xb3, 0xa0, 0x1c, 0x75, 0x6e, 0x47, 0x63, 0x88, - 0xd7, 0xd0, 0x30, 0x4d, 0xcc, 0x56, 0xec, 0x8d, 0x2e, 0x6b, 0x68, 0x10, 0x2a, 0x3c, 0x68, 0x02, - 0xcb, 0x1b, 0xa3, 0xd1, 0xf6, 0x44, 0xf9, 0xea, 0x48, 0x02, 0x6e, 0x0d, 0xfc, 0xd0, 0x4f, 0x44, - 0xb9, 0x2e, 0x20, 0x09, 0xe0, 0x07, 0x20, 0x47, 0x3b, 0x24, 0x8e, 0x7d, 0x97, 0x30, 0x51, 0xa6, - 0xf9, 0xdd, 0x77, 0xa6, 0xcb, 0x60, 0xe4, 0x4b, 0x06, 0x0d, 0xe3, 0xf9, 0xe2, 0x48, 0x24, 0x26, - 0x19, 0x92, 0x90, 0xc6, 0x5d, 0xd1, 0x5a, 0xa9, 0xc5, 0x49, 0xc7, 0x53, 0x61, 0x47, 0x63, 0x08, - 0x56, 0x01, 0x54, 0x69, 0x31, 0x49, 0xda, 0x71, 0x64, 0x8b, 0x37, 0x48, 0x41, 0xe4, 0x8a, 0xe7, - 0x58, 0x7a, 0x91, 0x70, 0x1e, 0xe2, 0x04, 0xa3, 0x29, 0x0b, 0xfc, 0x35, 0x80, 0xf2, 0x4c, 0xec, - 0xcf, 0x18, 0x8d, 0xf8, 0xf7, 0xd8, 0x4b, 0xdf, 0x53, 0xbd, 0x91, 0xd0, 0x97, 0x5e, 0x35, 0x67, - 0x43, 0xa2, 0x63, 0x46, 0xd5, 0x2a, 0x8e, 0x35, 0x5d, 0x33, 0x16, 0x8e, 0x35, 0x7d, 0xc9, 0xd0, - 0x07, 0xfb, 0xa7, 0x56, 0x81, 0x56, 0xfb, 0x78, 0x64, 0x7a, 0xd6, 0x33, 0x00, 0x4e, 0x63, 0xe2, - 0xf3, 0x0e, 0x36, 0x08, 0xf8, 0x6b, 0x2f, 0xc2, 0x21, 0xe9, 0xbf, 0x6f, 0xf9, 0x78, 0xb4, 0x30, - 0xe7, 0xc7, 0x0b, 0x13, 0x02, 0xcd, 0xa1, 0x2e, 0x11, 0xa5, 0x91, 0x43, 0x62, 0x6c, 0xfd, 0x35, - 0x03, 0xf2, 0xb5, 0x4e, 0x78, 0x40, 0xfd, 0xe8, 0x28, 0x7a, 0x49, 0x87, 0xd7, 0x7c, 0x66, 0xf4, - 0x9a, 0x9f, 0xfe, 0xc2, 0x9f, 0xbf, 0xe6, 0x0b, 0x1f, 0xbe, 0x2b, 0xaa, 0xac, 0x15, 0xe0, 0xae, - 0x8a, 0x92, 0x4a, 0x05, 0x65, 0x3c, 0x9c, 0x6a, 0x19, 0xf8, 0xb3, 0xb9, 0x3c, 0x6c, 0x19, 0x1e, - 0xfc, 0x33, 0x03, 0x46, 0x3e, 0xa2, 0xe1, 0xaf, 0x40, 0x65, 0xff, 0xe0, 0xa0, 0x56, 0xaf, 0xdb, - 0x67, 0x9f, 0x9c, 0xd6, 0xec, 0xd3, 0x1a, 0x7a, 0x7a, 0x54, 0xaf, 0x1f, 0x3d, 0x7f, 0x76, 0x52, - 0xab, 0xd7, 0x8d, 0xb9, 0xca, 0xfd, 0xd7, 0x6f, 0x36, 0xca, 0xc3, 0xf8, 0x53, 0x12, 0x87, 0x3e, - 0x63, 0x3e, 0x8d, 0x02, 0xbe, 0xdc, 0xf7, 0xc1, 0xda, 0x68, 0x36, 0xaa, 0xd5, 0xcf, 0xd0, 0xd1, - 0xc1, 0x59, 0xed, 0xd0, 0xc8, 0x54, 0xca, 0xaf, 0xdf, 0x6c, 0x94, 0x86, 0x99, 0x88, 0xb0, 0x24, - 0xf6, 0x1d, 0xfe, 0x1e, 0x78, 0x0c, 0xca, 0xd7, 0x6b, 0xd6, 0x0e, 0x8d, 0xf9, 0x4a, 0xe5, 0xf5, - 0x9b, 0x8d, 0xb5, 0xeb, 0x14, 0x89, 0x5b, 0xd1, 0x3e, 0xff, 0xc7, 0xfa, 0x5c, 0xf5, 0xc9, 0x37, - 0xbd, 0xf5, 0xcc, 0xb7, 0xbd, 0xf5, 0xcc, 0x7f, 0x7b, 0xeb, 0x99, 0x2f, 0xde, 0xae, 0xcf, 0x7d, - 0xfb, 0x76, 0x7d, 0xee, 0x5f, 0x6f, 0xd7, 0xe7, 0xfe, 0xb8, 0xe1, 0xf9, 0x49, 0xb3, 0xdd, 0xd8, - 0x72, 0x68, 0xb8, 0x3d, 0xf9, 0xcb, 0x4b, 0xd2, 0x6d, 0x11, 0xd6, 0x58, 0x14, 0x3f, 0xbe, 0x3d, - 0xfa, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x48, 0x59, 0x0f, 0x70, 0xd5, 0x13, 0x00, 0x00, + 0x19, 0x16, 0xa5, 0x95, 0xb4, 0x1c, 0x52, 0xd4, 0x7a, 0x44, 0xcb, 0x34, 0xed, 0x68, 0xd5, 0x4d, + 0x5b, 0xa8, 0x46, 0x2a, 0x59, 0x72, 0xd4, 0x1a, 0x4e, 0xd3, 0x42, 0x94, 0x99, 0x56, 0xaa, 0x3f, + 0x84, 0xa1, 0x1a, 0x23, 0x45, 0x8a, 0xc5, 0x70, 0x77, 0xbc, 0xdc, 0x68, 0x77, 0x87, 0xd8, 0x19, + 0xd2, 0x62, 0xff, 0x40, 0x03, 0x5f, 0x9a, 0xf6, 0x6e, 0x20, 0x40, 0x2f, 0x39, 0xe6, 0x27, 0xf4, + 0x98, 0x63, 0x8e, 0x45, 0x81, 0x2e, 0x0a, 0xf9, 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, 0x59, 0x4c, 0xd9, 0x16, 0xe9, 0xc6, 0x5b, 0xe2, 0x6f, 0x5b, 0x8c, 0x36, 0xdb, 0x29, + 0xe5, 0x14, 0x5a, 0xca, 0xb7, 0x29, 0x2c, 0xe2, 0x6f, 0xbb, 0x7a, 0x03, 0xc7, 0x61, 0x42, 0xb7, + 0xe4, 0xbf, 0x2a, 0xa8, 0x5a, 0x0e, 0x68, 0x40, 0xe5, 0x70, 0x4b, 0x8c, 0x94, 0xd5, 0xf9, 0xbb, + 0x01, 0x16, 0x8e, 0x70, 0x8a, 0x63, 0x06, 0xb7, 0x41, 0x9e, 0x74, 0x63, 0xd7, 0x27, 0x09, 0x8d, + 0x2b, 0xb9, 0xf5, 0xdc, 0x46, 0xbe, 0x56, 0xbe, 0xc8, 0x6c, 0xab, 0x87, 0xe3, 0xe8, 0x91, 0x33, + 0x70, 0x39, 0xc8, 0x24, 0xdd, 0xf8, 0xb1, 0x18, 0xc2, 0x3d, 0x00, 0xc8, 0x29, 0x4f, 0xb1, 0x4b, + 0xc2, 0x36, 0xab, 0x18, 0xeb, 0x73, 0x1b, 0x73, 0x35, 0xe7, 0x2c, 0xb3, 0xf3, 0x75, 0x61, 0xad, + 0x1f, 0x1c, 0xb1, 0x8b, 0xcc, 0xbe, 0xa1, 0x09, 0x06, 0x81, 0x0e, 0xca, 0x4b, 0x50, 0x0f, 0xdb, + 0x0c, 0xee, 0x80, 0xa2, 0xa0, 0xf6, 0x5a, 0x38, 0x49, 0x48, 0xc4, 0x2a, 0x8b, 0xeb, 0x73, 0x1b, + 0xf9, 0xda, 0xf2, 0x59, 0x66, 0x17, 0xea, 0x1f, 0x3f, 0xdd, 0xd7, 0x66, 0x54, 0x20, 0xdd, 0xb8, + 0x0f, 0xe0, 0x9f, 0x40, 0x09, 0x7b, 0x1e, 0x61, 0xcc, 0xf5, 0x68, 0xc2, 0x53, 0x1a, 0x55, 0xcc, + 0xf5, 0xdc, 0x46, 0x61, 0xc7, 0xde, 0x9c, 0xdc, 0x88, 0xcd, 0x3d, 0x19, 0xb7, 0xaf, 0xc2, 0x6a, + 0x37, 0xbf, 0xc9, 0xec, 0x99, 0xb3, 0xcc, 0x5e, 0x1a, 0x33, 0xa3, 0x25, 0x3c, 0x0a, 0xe1, 0x23, + 0x70, 0x1b, 0x7b, 0x3c, 0xec, 0x12, 0x97, 0x71, 0xcc, 0x43, 0xcf, 0x6d, 0xa7, 0xc4, 0xa3, 0x71, + 0x3b, 0x8c, 0x08, 0xab, 0xe4, 0xc5, 0xfc, 0xd0, 0x2d, 0x15, 0xd0, 0x90, 0xfe, 0xa3, 0xa1, 0x1b, + 0xde, 0x07, 0xe5, 0x56, 0xc8, 0x38, 0x4d, 0x7b, 0x2e, 0x23, 0x69, 0x97, 0xb8, 0xaf, 0xc2, 0xc4, + 0xa7, 0xaf, 0x2a, 0x60, 0x3d, 0xb7, 0x61, 0x20, 0xa8, 0x7d, 0x0d, 0xe1, 0x7a, 0x21, 0x3d, 0xf0, + 0x53, 0xb0, 0x4a, 0x4e, 0x39, 0x49, 0x7c, 0xe2, 0xab, 0x0d, 0x76, 0x69, 0x9b, 0x87, 0x34, 0x61, + 0x95, 0x82, 0x5c, 0xd4, 0x4f, 0x2f, 0x2f, 0xaa, 0xae, 0xe3, 0xe5, 0x21, 0x3c, 0x57, 0xd1, 0xa8, + 0x4c, 0xae, 0xb0, 0x3e, 0xba, 0xf3, 0xfa, 0xbb, 0xaf, 0xef, 0xad, 0x8e, 0xd4, 0xce, 0xa9, 0xa8, + 0x1e, 0x75, 0xe2, 0x87, 0x86, 0x39, 0x6b, 0xcd, 0x1d, 0x1a, 0xe6, 0x9c, 0x65, 0x1c, 0x1a, 0xe6, + 0xbc, 0xb5, 0x70, 0x68, 0x98, 0x0b, 0xd6, 0xa2, 0xf3, 0x21, 0x28, 0x5f, 0x25, 0x01, 0x7f, 0x02, + 0x4a, 0xe3, 0x53, 0x55, 0x65, 0x82, 0x96, 0xc6, 0xa4, 0x9d, 0xbf, 0xe5, 0xc0, 0xf8, 0x06, 0xc3, + 0x3d, 0xb0, 0xe0, 0xa5, 0x04, 0x73, 0x22, 0x13, 0x0a, 0x3b, 0xef, 0xfe, 0x9f, 0x83, 0x3a, 0xee, + 0xb5, 0x49, 0xcd, 0x10, 0x87, 0x85, 0x74, 0x22, 0xfc, 0x10, 0x18, 0x1e, 0x8e, 0xa2, 0xca, 0xec, + 0x0f, 0x25, 0x90, 0x69, 0xce, 0x7f, 0x72, 0xe0, 0xc6, 0xa5, 0x08, 0xe8, 0x81, 0x82, 0x2e, 0x24, + 0xde, 0x6b, 0xab, 0xc9, 0x95, 0x76, 0xee, 0x7e, 0x1f, 0xb7, 0x24, 0xfd, 0xf1, 0x59, 0x66, 0x83, + 0x21, 0xbe, 0xc8, 0x6c, 0xa8, 0xea, 0x7b, 0x84, 0xc8, 0x41, 0x00, 0x0f, 0x22, 0xa0, 0x07, 0x56, + 0xc6, 0xab, 0xd5, 0x8d, 0x42, 0xc6, 0x2b, 0xb3, 0xb2, 0xd0, 0x1f, 0x9c, 0x65, 0xf6, 0xf8, 0xc4, + 0x9e, 0x84, 0x8c, 0x5f, 0x64, 0x76, 0x75, 0x8c, 0x75, 0x34, 0xd3, 0x41, 0x37, 0xf0, 0x64, 0x82, + 0xf3, 0x95, 0x05, 0x0a, 0xfb, 0x2d, 0x1c, 0x26, 0xfb, 0x34, 0x79, 0x19, 0x06, 0xf0, 0x53, 0xb0, + 0xdc, 0xa2, 0x31, 0x61, 0x9c, 0x60, 0xdf, 0x6d, 0x46, 0xd4, 0x3b, 0xd1, 0x8f, 0xf4, 0x83, 0x7f, + 0x67, 0xf6, 0x4d, 0xb5, 0x40, 0xe6, 0x9f, 0x6c, 0x86, 0x74, 0x2b, 0xc6, 0xbc, 0xb5, 0x79, 0x90, + 0x08, 0xd1, 0x55, 0x25, 0x3a, 0x91, 0xe9, 0xa0, 0xd2, 0xc0, 0x52, 0x13, 0x06, 0xd8, 0x02, 0x25, + 0x1f, 0x53, 0xf7, 0x25, 0x4d, 0x4f, 0x34, 0xf9, 0xac, 0x24, 0xaf, 0x7d, 0x2f, 0xf9, 0x59, 0x66, + 0x17, 0x1f, 0xef, 0x3d, 0xff, 0x88, 0xa6, 0x27, 0x92, 0xe2, 0x22, 0xb3, 0x6f, 0x2a, 0xb1, 0x71, + 0x22, 0x07, 0x15, 0x7d, 0x4c, 0x07, 0x61, 0xf0, 0x05, 0xb0, 0x06, 0x01, 0xac, 0xd3, 0x6e, 0xd3, + 0x94, 0x57, 0xe6, 0xd6, 0x73, 0x1b, 0x66, 0xed, 0xe7, 0x67, 0x99, 0x5d, 0xd2, 0x94, 0x0d, 0xe5, + 0xb9, 0xc8, 0xec, 0x5b, 0x13, 0xa4, 0x3a, 0xc7, 0x41, 0x25, 0x4d, 0xab, 0x43, 0x61, 0x13, 0x14, + 0x49, 0xd8, 0xde, 0xde, 0xbd, 0xaf, 0x17, 0x60, 0xc8, 0x05, 0xfc, 0x66, 0xda, 0x02, 0x0a, 0xf5, + 0x83, 0xa3, 0xed, 0xdd, 0xfb, 0xfd, 0xf9, 0xaf, 0xe8, 0xf7, 0xda, 0x08, 0x8b, 0x83, 0x0a, 0x0a, + 0xaa, 0xc9, 0xf7, 0x35, 0x76, 0xb5, 0xc6, 0xc2, 0x75, 0x35, 0x76, 0xaf, 0xd2, 0xd8, 0x1d, 0xd7, + 0xd8, 0x1d, 0xd7, 0x78, 0xa8, 0x35, 0x16, 0xaf, 0xab, 0xf1, 0xf0, 0x2a, 0x8d, 0x87, 0xe3, 0x1a, + 0x2a, 0x46, 0x14, 0x53, 0xb3, 0xf7, 0x67, 0x9c, 0xf0, 0xb0, 0x13, 0x6b, 0x19, 0xf3, 0xda, 0xc5, + 0x34, 0x91, 0xe9, 0xa0, 0xd2, 0xc0, 0xa2, 0xd8, 0x4f, 0x40, 0xd9, 0xa3, 0x09, 0xe3, 0xc2, 0x96, + 0xd0, 0x76, 0x44, 0xb4, 0x44, 0x5e, 0x4a, 0x3c, 0x9c, 0x26, 0x71, 0x47, 0x49, 0x5c, 0x95, 0xee, + 0xa0, 0x95, 0x71, 0xb3, 0x12, 0x73, 0x81, 0xd5, 0x26, 0x9c, 0xa4, 0xac, 0xd9, 0x49, 0x03, 0x2d, + 0x04, 0xa4, 0xd0, 0xfb, 0xd3, 0x84, 0x74, 0x59, 0x4d, 0xa6, 0x3a, 0x68, 0x79, 0x68, 0x52, 0x02, + 0x9f, 0x80, 0x52, 0x28, 0x54, 0x9b, 0x9d, 0x48, 0xd3, 0x17, 0x24, 0xfd, 0xce, 0x34, 0x7a, 0xfd, + 0x28, 0x8c, 0x27, 0x3a, 0x68, 0xa9, 0x6f, 0x50, 0xd4, 0x3e, 0x80, 0x71, 0x27, 0x4c, 0xdd, 0x20, + 0xc2, 0x5e, 0x48, 0x52, 0x4d, 0x5f, 0x94, 0xf4, 0xbf, 0x98, 0x46, 0x7f, 0x5b, 0xd1, 0x5f, 0x4e, + 0x76, 0x90, 0x25, 0x8c, 0xbf, 0x55, 0x36, 0xa5, 0xd2, 0x00, 0xc5, 0x26, 0x49, 0xa3, 0x30, 0xd1, + 0xfc, 0x4b, 0x92, 0xff, 0xfe, 0x34, 0x7e, 0x5d, 0x41, 0xa3, 0x69, 0x0e, 0x2a, 0x28, 0x38, 0x20, + 0x8d, 0x68, 0xe2, 0xd3, 0x3e, 0xe9, 0x8d, 0x6b, 0x93, 0x8e, 0xa6, 0x39, 0xa8, 0xa0, 0xa0, 0x22, + 0x0d, 0xc0, 0x0a, 0x4e, 0x53, 0xfa, 0x6a, 0x62, 0x43, 0xa0, 0xe4, 0xfe, 0xe5, 0x34, 0xee, 0xfe, + 0xcb, 0xf5, 0x72, 0xb6, 0x78, 0xb9, 0x0a, 0xeb, 0xd8, 0x96, 0xf8, 0x00, 0x06, 0x29, 0xee, 0x4d, + 0xe8, 0x94, 0xaf, 0xbd, 0xf1, 0x97, 0x93, 0x1d, 0x64, 0x09, 0xe3, 0x98, 0xca, 0x67, 0xa0, 0x1c, + 0x93, 0x34, 0x20, 0x6e, 0x42, 0x38, 0x6b, 0x47, 0x21, 0xd7, 0x3a, 0x37, 0xaf, 0xfd, 0x1c, 0x5c, + 0x95, 0xee, 0x20, 0x28, 0xcd, 0xcf, 0xb4, 0x55, 0x69, 0xdd, 0x06, 0xa6, 0x27, 0x6e, 0x0b, 0x37, + 0xf4, 0x2b, 0x15, 0xd9, 0x9a, 0x2c, 0x4a, 0x7c, 0xe0, 0xc3, 0x32, 0x98, 0x57, 0x77, 0xfb, 0x6d, + 0x79, 0xb7, 0x2b, 0x00, 0xab, 0xc0, 0xf4, 0x89, 0x17, 0xc6, 0x38, 0x62, 0x95, 0xaa, 0x4c, 0x18, + 0x60, 0xf8, 0x31, 0x58, 0x62, 0x2d, 0x9c, 0x04, 0x2d, 0x1c, 0xba, 0x3c, 0x8c, 0x49, 0xe5, 0x8e, + 0x9c, 0xf1, 0xf6, 0xb4, 0x19, 0x97, 0xd5, 0x8c, 0xc7, 0xf2, 0x1c, 0x54, 0xec, 0xe3, 0xe3, 0x30, + 0x26, 0xf0, 0x08, 0x14, 0x3c, 0x9c, 0x78, 0x9d, 0x44, 0xb1, 0xde, 0x95, 0xac, 0x5b, 0xd3, 0x58, + 0xf5, 0x55, 0x3c, 0x92, 0xe5, 0x20, 0xa0, 0x50, 0x9f, 0xb1, 0x9d, 0xe2, 0xa0, 0x43, 0x14, 0xe3, + 0x3b, 0xd7, 0x66, 0x1c, 0xc9, 0x72, 0x10, 0x50, 0xa8, 0xcf, 0xd8, 0x25, 0xe9, 0x49, 0xa4, 0x19, + 0xd7, 0xae, 0xcd, 0x38, 0x92, 0xe5, 0x20, 0xa0, 0x90, 0x64, 0x7c, 0x0a, 0x00, 0x65, 0xf8, 0x04, + 0x2b, 0x42, 0x5b, 0x12, 0x6e, 0x4e, 0x23, 0xd4, 0xfd, 0xf5, 0x30, 0xc9, 0x41, 0x79, 0x09, 0x04, + 0xdd, 0xa0, 0xaf, 0x5b, 0xb5, 0x6e, 0x1d, 0x1a, 0xe6, 0x2d, 0xab, 0xe2, 0x6c, 0x81, 0x79, 0xd1, + 0xb7, 0x12, 0x68, 0x81, 0xb9, 0x13, 0xd2, 0xd3, 0x3d, 0x9c, 0x18, 0x8a, 0xb3, 0xef, 0xe2, 0xa8, + 0x43, 0xd4, 0x75, 0x8e, 0x14, 0x70, 0x8e, 0xc0, 0xf2, 0x71, 0x8a, 0x13, 0x26, 0x7a, 0x5e, 0x9a, + 0x3c, 0xa1, 0x01, 0x83, 0x10, 0x18, 0x2d, 0xcc, 0x5a, 0x3a, 0x57, 0x8e, 0xe1, 0xcf, 0x80, 0x11, + 0xd1, 0x80, 0xc9, 0xc6, 0xa6, 0xb0, 0x73, 0xf3, 0x72, 0x17, 0xf5, 0x84, 0x06, 0x48, 0x86, 0x38, + 0x7f, 0x99, 0x03, 0x73, 0x4f, 0x68, 0x00, 0x2b, 0x60, 0x11, 0xfb, 0x7e, 0x4a, 0x18, 0xd3, 0x4c, + 0x7d, 0x08, 0x57, 0xc1, 0x02, 0xa7, 0xed, 0xd0, 0x53, 0x74, 0x79, 0xa4, 0x91, 0x10, 0xf6, 0x31, + 0xc7, 0xb2, 0x07, 0x28, 0x22, 0x39, 0x16, 0x9f, 0x10, 0xb2, 0xd4, 0xdd, 0xa4, 0x13, 0x37, 0x49, + 0x2a, 0xaf, 0x72, 0xa3, 0xb6, 0x7c, 0x9e, 0xd9, 0x05, 0x69, 0x7f, 0x26, 0xcd, 0x68, 0x14, 0xc0, + 0xf7, 0xc0, 0x22, 0x3f, 0x75, 0xe5, 0x1a, 0xe6, 0xe5, 0x16, 0xaf, 0x9c, 0x67, 0xf6, 0x32, 0x1f, + 0x2e, 0xf3, 0x77, 0x98, 0xb5, 0xd0, 0x02, 0x3f, 0x15, 0xff, 0xc3, 0x2d, 0x60, 0xf2, 0x53, 0x37, + 0x4c, 0x7c, 0x72, 0x2a, 0x2f, 0x71, 0xa3, 0x56, 0x3e, 0xcf, 0x6c, 0x6b, 0x24, 0xfc, 0x40, 0xf8, + 0xd0, 0x22, 0x3f, 0x95, 0x03, 0xf8, 0x1e, 0x00, 0x6a, 0x4a, 0x52, 0x41, 0xdd, 0xc9, 0x4b, 0xe7, + 0x99, 0x9d, 0x97, 0x56, 0xc9, 0x3d, 0x1c, 0x42, 0x07, 0xcc, 0x2b, 0x6e, 0x53, 0x72, 0x17, 0xcf, + 0x33, 0xdb, 0x8c, 0x68, 0xa0, 0x38, 0x95, 0x4b, 0x6c, 0x55, 0x4a, 0x62, 0xda, 0x25, 0xbe, 0xbc, + 0x18, 0x4d, 0xd4, 0x87, 0xf0, 0x03, 0xb0, 0xac, 0xb4, 0xc4, 0xd9, 0x33, 0x8e, 0xe3, 0xb6, 0xfa, + 0xda, 0xa8, 0xc1, 0xf3, 0xcc, 0x2e, 0x49, 0xd7, 0x71, 0xdf, 0x83, 0x26, 0xb0, 0xf3, 0xc5, 0x2c, + 0x30, 0x8f, 0x4f, 0x11, 0x61, 0x9d, 0x88, 0xc3, 0x8f, 0x80, 0x25, 0x1b, 0x4d, 0xec, 0x71, 0x77, + 0xec, 0x5c, 0x6a, 0x77, 0x86, 0x77, 0xe0, 0x64, 0x84, 0x83, 0x96, 0xfb, 0xa6, 0x3d, 0x7d, 0x78, + 0x65, 0x30, 0xdf, 0x8c, 0x28, 0x8d, 0x65, 0x19, 0x15, 0x91, 0x02, 0xf0, 0x85, 0xdc, 0x72, 0x59, + 0x22, 0x73, 0xb2, 0x89, 0xff, 0xd1, 0xe5, 0x12, 0x99, 0xa8, 0xb3, 0xda, 0x1d, 0xd1, 0xc2, 0x5f, + 0x64, 0x76, 0x49, 0x69, 0xeb, 0x7c, 0xe7, 0xab, 0xef, 0xbe, 0xbe, 0x97, 0x13, 0xa7, 0x23, 0x8b, + 0xd1, 0x02, 0x73, 0x29, 0xe1, 0xf2, 0xd8, 0x8b, 0x48, 0x0c, 0xc5, 0xdb, 0x2a, 0x25, 0x5d, 0x92, + 0x72, 0xe2, 0xcb, 0xe3, 0x35, 0xd1, 0x00, 0x8b, 0x57, 0x5f, 0x80, 0x99, 0xdb, 0x61, 0xc4, 0x57, + 0x67, 0x89, 0x16, 0x03, 0xcc, 0xfe, 0xc0, 0x88, 0xff, 0xc8, 0xf8, 0xfc, 0x4b, 0x7b, 0xc6, 0xc1, + 0xa0, 0xa0, 0xfb, 0xfb, 0x4e, 0x3b, 0x22, 0x53, 0x6a, 0x74, 0x07, 0x14, 0xc5, 0xd7, 0x1c, 0x0e, + 0x88, 0x7b, 0x42, 0x7a, 0xba, 0x52, 0x55, 0xdd, 0x69, 0xfb, 0xef, 0x49, 0x8f, 0xa1, 0x51, 0xa0, + 0x25, 0xbe, 0x34, 0x40, 0xe1, 0x38, 0xc5, 0x1e, 0xd1, 0xdd, 0xba, 0xa8, 0x76, 0x01, 0x53, 0x2d, + 0xa1, 0x91, 0xd0, 0x16, 0x87, 0x4a, 0x3b, 0x5c, 0x3f, 0x91, 0x7d, 0x28, 0x32, 0x52, 0x42, 0x4e, + 0x89, 0x27, 0xf7, 0xd2, 0x40, 0x1a, 0xc1, 0x5d, 0xb0, 0xe4, 0x87, 0x0c, 0x37, 0x23, 0xf9, 0xf1, + 0xea, 0x9d, 0xa8, 0xe5, 0xd7, 0xac, 0xf3, 0xcc, 0x2e, 0x6a, 0x47, 0x43, 0xd8, 0xd1, 0x18, 0x12, + 0x35, 0x34, 0x4c, 0x93, 0xb3, 0x95, 0x7b, 0x63, 0xaa, 0x1a, 0x1a, 0x84, 0x4a, 0x0f, 0x9a, 0xc0, + 0xea, 0xc6, 0x68, 0x76, 0x02, 0x59, 0xbe, 0x26, 0x52, 0x40, 0x58, 0xa3, 0x30, 0x0e, 0xb9, 0x2c, + 0xd7, 0x79, 0xa4, 0x00, 0xfc, 0x00, 0xe4, 0x69, 0x97, 0xa4, 0x69, 0xe8, 0x13, 0x26, 0xcb, 0xb4, + 0xb0, 0xf3, 0xce, 0xe5, 0x32, 0x18, 0xf9, 0x92, 0x41, 0xc3, 0x78, 0xb1, 0x38, 0x92, 0xc8, 0x49, + 0xc6, 0x24, 0xa6, 0x69, 0x4f, 0xb6, 0x56, 0x7a, 0x71, 0xca, 0xf1, 0x54, 0xda, 0xd1, 0x18, 0x82, + 0x35, 0x00, 0x75, 0x5a, 0x4a, 0x78, 0x27, 0x4d, 0x5c, 0xf9, 0x06, 0x29, 0xca, 0x5c, 0xf9, 0x1c, + 0x2b, 0x2f, 0x92, 0xce, 0xc7, 0x98, 0x63, 0x74, 0xc9, 0x02, 0x7f, 0x0d, 0xa0, 0x3a, 0x13, 0xf7, + 0x33, 0x46, 0x13, 0xf1, 0x3d, 0xf6, 0x32, 0x0c, 0x74, 0x6f, 0x24, 0xf5, 0x95, 0x57, 0xcf, 0xd9, + 0x52, 0xe8, 0x90, 0x51, 0xbd, 0x8a, 0x43, 0xc3, 0x34, 0xac, 0xf9, 0x43, 0xc3, 0x5c, 0xb4, 0xcc, + 0xc1, 0xfe, 0xe9, 0x55, 0xa0, 0x95, 0x3e, 0x1e, 0x99, 0x9e, 0xf3, 0x0c, 0x80, 0xa3, 0x94, 0x84, + 0xa2, 0x83, 0x8d, 0x22, 0xf1, 0xda, 0x4b, 0x70, 0x4c, 0xfa, 0xef, 0x5b, 0x31, 0x1e, 0x2d, 0xcc, + 0xd9, 0xf1, 0xc2, 0x84, 0xc0, 0xf0, 0xa8, 0x4f, 0x64, 0x69, 0xe4, 0x91, 0x1c, 0x3b, 0x7f, 0xcd, + 0x81, 0x42, 0xbd, 0x1b, 0xef, 0xd3, 0x30, 0x39, 0x48, 0x5e, 0xd2, 0xe1, 0x35, 0x9f, 0x1b, 0xbd, + 0xe6, 0x2f, 0x7f, 0xe1, 0xcf, 0x5e, 0xf1, 0x85, 0x0f, 0xdf, 0x95, 0x55, 0xd6, 0x8e, 0x70, 0x4f, + 0x47, 0x29, 0xa5, 0xa2, 0x36, 0xaa, 0xa0, 0xb5, 0x91, 0x96, 0x41, 0x3c, 0x9b, 0x4b, 0xb5, 0xd9, + 0x4a, 0x6e, 0xd8, 0x36, 0xdc, 0xfb, 0x67, 0x0e, 0x8c, 0x7c, 0x48, 0xc3, 0x5f, 0x81, 0xea, 0xde, + 0xfe, 0x7e, 0xbd, 0xd1, 0x70, 0x8f, 0x3f, 0x39, 0xaa, 0xbb, 0x47, 0x75, 0xf4, 0xf4, 0xa0, 0xd1, + 0x38, 0x78, 0xfe, 0xec, 0x49, 0xbd, 0xd1, 0xb0, 0x66, 0xaa, 0x77, 0x5f, 0xbf, 0x59, 0xaf, 0x0c, + 0xe3, 0x8f, 0x48, 0x1a, 0x87, 0x8c, 0x85, 0x34, 0x89, 0xc4, 0x92, 0xdf, 0x07, 0xab, 0xa3, 0xd9, + 0xa8, 0xde, 0x38, 0x46, 0x07, 0xfb, 0xc7, 0xf5, 0xc7, 0x56, 0xae, 0x5a, 0x79, 0xfd, 0x66, 0xbd, + 0x3c, 0xcc, 0x44, 0x84, 0xf1, 0x34, 0xf4, 0xc4, 0xbb, 0xe0, 0x21, 0xa8, 0x5c, 0xad, 0x59, 0x7f, + 0x6c, 0xcd, 0x56, 0xab, 0xaf, 0xdf, 0xac, 0xaf, 0x5e, 0xa5, 0x48, 0xfc, 0xaa, 0xf1, 0xf9, 0x3f, + 0xd6, 0x66, 0x6a, 0x8f, 0xbe, 0x39, 0x5b, 0xcb, 0x7d, 0x7b, 0xb6, 0x96, 0xfb, 0xef, 0xd9, 0x5a, + 0xee, 0x8b, 0xb7, 0x6b, 0x33, 0xdf, 0xbe, 0x5d, 0x9b, 0xf9, 0xd7, 0xdb, 0xb5, 0x99, 0x3f, 0xae, + 0x07, 0x21, 0x6f, 0x75, 0x9a, 0x9b, 0x1e, 0x8d, 0xb7, 0x26, 0x7f, 0x7d, 0xe1, 0xbd, 0x36, 0x61, + 0xcd, 0x05, 0xf9, 0x03, 0xdc, 0x83, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0x21, 0xae, 0x2c, 0x6d, + 0xd9, 0x13, 0x00, 0x00, } func (m *Params) Marshal() (dAtA []byte, err error) { diff --git a/x/vm/types/gasmeter.go b/x/vm/types/gasmeter.go index a7dde1fa..e1e77110 100644 --- a/x/vm/types/gasmeter.go +++ b/x/vm/types/gasmeter.go @@ -4,7 +4,7 @@ import ( fmt "fmt" math "math" - storetypes "cosmossdk.io/store/types" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" ) // ErrorNegativeGasConsumed defines an error thrown when the amount of gas refunded results in a diff --git a/x/vm/types/interfaces.go b/x/vm/types/interfaces.go index 75d35867..1b69bed0 100644 --- a/x/vm/types/interfaces.go +++ b/x/vm/types/interfaces.go @@ -51,6 +51,11 @@ type BankKeeper interface { GetSupply(ctx context.Context, denom string) sdk.Coin GetDenomMetaData(ctx context.Context, denom string) (banktypes.Metadata, bool) SetDenomMetaData(ctx context.Context, denomMetaData banktypes.Metadata) + SendCoinsFromModuleToAccountVirtual(ctx context.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error + SendCoinsFromAccountToModuleVirtual(ctx context.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error + UncheckedSetBalance(ctx context.Context, addr sdk.AccAddress, amt sdk.Coin) error + LockedCoins(ctx context.Context, addr sdk.AccAddress) sdk.Coins + BlockedAddr(addr sdk.AccAddress) bool } // StakingKeeper returns the historical headers kept in store. @@ -85,11 +90,15 @@ type EvmHooks interface { type BankWrapper interface { BankKeeper - MintAmountToAccount(ctx context.Context, recipientAddr sdk.AccAddress, amt *big.Int) error - BurnAmountFromAccount(ctx context.Context, account sdk.AccAddress, amt *big.Int) error + SetBalance(ctx context.Context, account sdk.AccAddress, amt *big.Int) error } // ConsensusParamsKeeper defines the expected consensus params keeper. type ConsensusParamsKeeper interface { Params(context.Context, *types.QueryParamsRequest) (*types.QueryParamsResponse, error) } + +// VMKeeper defines the expected interface needed for the VMKeeper when passed to functions. +type VMKeeper interface { + GetEvmCoinInfo(ctx sdk.Context) (coinInfo EvmCoinInfo) +} diff --git a/x/vm/types/key.go b/x/vm/types/key.go index 45226c8d..d1caf8d2 100644 --- a/x/vm/types/key.go +++ b/x/vm/types/key.go @@ -1,6 +1,8 @@ package types import ( + "encoding/binary" + "github.com/ethereum/go-ethereum/common" ) @@ -13,9 +15,9 @@ const ( // The EVM module should use a prefix store. StoreKey = ModuleName - // TransientKey is the key to access the EVM transient store, that is reset + // ObjectKey is the key to access the EVM object store, that is reset // during the Commit phase. - TransientKey = "transient_" + ModuleName + ObjectKey = "object:" + ModuleName // RouterKey uses module name for routing RouterKey = ModuleName @@ -30,12 +32,10 @@ const ( prefixEvmCoinInfo ) -// prefix bytes for the EVM transient store +// prefix bytes for the EVM object store const ( - prefixTransientBloom = iota + 1 - prefixTransientTxIndex - prefixTransientLogSize - prefixTransientGasUsed + prefixObjectBloom = iota + 1 + prefixObjectGasUsed ) // KVStore key prefixes @@ -47,12 +47,10 @@ var ( KeyPrefixEvmCoinInfo = []byte{prefixEvmCoinInfo} ) -// Transient Store key prefixes +// Object Store key prefixes var ( - KeyPrefixTransientBloom = []byte{prefixTransientBloom} - KeyPrefixTransientTxIndex = []byte{prefixTransientTxIndex} - KeyPrefixTransientLogSize = []byte{prefixTransientLogSize} - KeyPrefixTransientGasUsed = []byte{prefixTransientGasUsed} + KeyPrefixObjectBloom = []byte{prefixObjectBloom} + KeyPrefixObjectGasUsed = []byte{prefixObjectGasUsed} ) // AddressStoragePrefix returns a prefix to iterate over a given account storage. @@ -64,3 +62,18 @@ func AddressStoragePrefix(address common.Address) []byte { func StateKey(address common.Address, key []byte) []byte { return append(AddressStoragePrefix(address), key...) } + +func ObjectGasUsedKey(txIndex int) []byte { + var key [1 + 8]byte + key[0] = prefixObjectGasUsed + binary.BigEndian.PutUint64(key[1:], uint64(txIndex)) //nolint:gosec + return key[:] +} + +func ObjectBloomKey(txIndex, msgIndex int) []byte { + var key [1 + 8 + 8]byte + key[0] = prefixObjectBloom + binary.BigEndian.PutUint64(key[1:], uint64(txIndex)) //nolint:gosec + binary.BigEndian.PutUint64(key[9:], uint64(msgIndex)) //nolint:gosec + return key[:] +} diff --git a/x/vm/types/mocks/BankKeeper.go b/x/vm/types/mocks/BankKeeper.go index 31c4ba98..ff04e733 100644 --- a/x/vm/types/mocks/BankKeeper.go +++ b/x/vm/types/mocks/BankKeeper.go @@ -17,6 +17,24 @@ type BankKeeper struct { mock.Mock } +// 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 +} + // BurnCoins provides a mock function with given fields: ctx, moduleName, amt func (_m *BankKeeper) BurnCoins(ctx context.Context, moduleName string, amt types.Coins) error { ret := _m.Called(ctx, moduleName, amt) @@ -134,6 +152,26 @@ func (_m *BankKeeper) IterateTotalSupply(ctx context.Context, cb func(types.Coin _m.Called(ctx, cb) } +// LockedCoins provides a mock function with given fields: ctx, addr +func (_m *BankKeeper) LockedCoins(ctx context.Context, addr types.AccAddress) types.Coins { + ret := _m.Called(ctx, addr) + + if len(ret) == 0 { + panic("no return value specified for LockedCoins") + } + + var r0 types.Coins + if rf, ok := ret.Get(0).(func(context.Context, types.AccAddress) types.Coins); ok { + r0 = rf(ctx, addr) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(types.Coins) + } + } + + 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) @@ -188,6 +226,24 @@ func (_m *BankKeeper) SendCoinsFromAccountToModule(ctx context.Context, senderAd return r0 } +// SendCoinsFromAccountToModuleVirtual provides a mock function with given fields: ctx, senderAddr, recipientModule, amt +func (_m *BankKeeper) SendCoinsFromAccountToModuleVirtual(ctx context.Context, senderAddr types.AccAddress, recipientModule string, amt types.Coins) error { + ret := _m.Called(ctx, senderAddr, recipientModule, amt) + + if len(ret) == 0 { + panic("no return value specified for SendCoinsFromAccountToModuleVirtual") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, types.AccAddress, string, types.Coins) error); ok { + r0 = rf(ctx, senderAddr, recipientModule, 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) @@ -206,6 +262,24 @@ func (_m *BankKeeper) SendCoinsFromModuleToAccount(ctx context.Context, senderMo return r0 } +// SendCoinsFromModuleToAccountVirtual provides a mock function with given fields: ctx, senderModule, recipientAddr, amt +func (_m *BankKeeper) SendCoinsFromModuleToAccountVirtual(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 SendCoinsFromModuleToAccountVirtual") + } + + 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 +} + // SetDenomMetaData provides a mock function with given fields: ctx, denomMetaData func (_m *BankKeeper) SetDenomMetaData(ctx context.Context, denomMetaData banktypes.Metadata) { _m.Called(ctx, denomMetaData) @@ -229,12 +303,31 @@ func (_m *BankKeeper) SpendableCoin(ctx context.Context, addr types.AccAddress, return r0 } +// UncheckedSetBalance provides a mock function with given fields: ctx, addr, amt +func (_m *BankKeeper) UncheckedSetBalance(ctx context.Context, addr types.AccAddress, amt types.Coin) error { + ret := _m.Called(ctx, addr, amt) + + if len(ret) == 0 { + panic("no return value specified for UncheckedSetBalance") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, types.AccAddress, types.Coin) error); ok { + r0 = rf(ctx, addr, 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/x/vm/types/mocks/EVMKeeper.go b/x/vm/types/mocks/EVMKeeper.go index 4aa50b93..50196169 100644 --- a/x/vm/types/mocks/EVMKeeper.go +++ b/x/vm/types/mocks/EVMKeeper.go @@ -11,8 +11,7 @@ import ( "github.com/cosmos/evm/x/vm/statedb" "github.com/cosmos/evm/x/vm/types" - storetypes "cosmossdk.io/store/types" - + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -23,8 +22,9 @@ var ( ) type Account struct { - account statedb.Account - states statedb.Storage + account statedb.Account + states statedb.Storage + blockedAccountType bool } type EVMKeeper struct { @@ -49,6 +49,25 @@ func (k EVMKeeper) GetAccount(_ sdk.Context, addr common.Address) *statedb.Accou return &acct.account } +// IsBaseAccountOrEmpty reports true unless the address was marked with SetBlockedAccountType. +func (k EVMKeeper) IsBaseAccountOrEmpty(_ sdk.Context, addr common.Address) bool { + acct, ok := k.accounts[addr] + if !ok { + return true + } + return !acct.blockedAccountType +} + +// SetBlockedAccountType marks addr as a non-base Cosmos account for CreateAccount tests. +func (k EVMKeeper) SetBlockedAccountType(addr common.Address, blocked bool) { + acct, exists := k.accounts[addr] + if !exists { + acct = Account{states: make(statedb.Storage)} + } + acct.blockedAccountType = blocked + k.accounts[addr] = acct +} + func (k EVMKeeper) GetState(_ sdk.Context, addr common.Address, key common.Hash) common.Hash { return k.accounts[addr].states[key] } @@ -107,6 +126,12 @@ func (k EVMKeeper) DeleteAccount(_ sdk.Context, addr common.Address) error { return errors.New("mock db error") } old := k.accounts[addr] + if !types.IsEmptyCodeHash(old.account.CodeHash) { + code := k.codes[common.BytesToHash(old.account.CodeHash)] + if len(code) == 0 { + return errors.New("only smart contracts can be self-destructed") + } + } delete(k.accounts, addr) if !types.IsEmptyCodeHash(old.account.CodeHash) { delete(k.codes, common.BytesToHash(old.account.CodeHash)) @@ -121,8 +146,12 @@ func (k EVMKeeper) Clone() *EVMKeeper { return &EVMKeeper{accounts, codes, storeKeys} } -func (k EVMKeeper) KVStoreKeys() map[string]*storetypes.KVStoreKey { - return k.storeKeys +func (k EVMKeeper) KVStoreKeys() map[string]storetypes.StoreKey { + result := make(map[string]storetypes.StoreKey, len(k.storeKeys)) + for k, v := range k.storeKeys { + result[k] = v + } + return result } func (k EVMKeeper) GetCodeHash(_ sdk.Context, _ common.Address) common.Hash { diff --git a/x/vm/types/mocks/VMKeeper.go b/x/vm/types/mocks/VMKeeper.go new file mode 100644 index 00000000..673a309d --- /dev/null +++ b/x/vm/types/mocks/VMKeeper.go @@ -0,0 +1,48 @@ +// Code generated by mockery v2.53.5. DO NOT EDIT. + +package mocks + +import ( + types "github.com/cosmos/cosmos-sdk/types" + mock "github.com/stretchr/testify/mock" + + vmtypes "github.com/cosmos/evm/x/vm/types" +) + +// VMKeeper is an autogenerated mock type for the VMKeeper type +type VMKeeper struct { + mock.Mock +} + +// GetEvmCoinInfo provides a mock function with given fields: ctx +func (_m *VMKeeper) GetEvmCoinInfo(ctx types.Context) vmtypes.EvmCoinInfo { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for GetEvmCoinInfo") + } + + var r0 vmtypes.EvmCoinInfo + if rf, ok := ret.Get(0).(func(types.Context) vmtypes.EvmCoinInfo); ok { + r0 = rf(ctx) + } else { + r0 = ret.Get(0).(vmtypes.EvmCoinInfo) + } + + return r0 +} + +// NewVMKeeper creates a new instance of VMKeeper. 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 NewVMKeeper(t interface { + mock.TestingT + Cleanup(func()) +}, +) *VMKeeper { + mock := &VMKeeper{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/x/vm/types/msg.go b/x/vm/types/msg.go index 19bda468..1619a7f5 100644 --- a/x/vm/types/msg.go +++ b/x/vm/types/msg.go @@ -16,7 +16,6 @@ import ( errorsmod "cosmossdk.io/errors" sdkmath "cosmossdk.io/math" - txsigning "cosmossdk.io/x/tx/signing" "github.com/cosmos/cosmos-sdk/client" codectypes "github.com/cosmos/cosmos-sdk/codec/types" @@ -27,6 +26,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth/ante" "github.com/cosmos/cosmos-sdk/x/auth/signing" authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" + txsigning "github.com/cosmos/cosmos-sdk/x/tx/signing" ) var ( @@ -68,26 +68,29 @@ func (msg *MsgEthereumTx) FromEthereumTx(tx *ethtypes.Transaction) { // FromSignedEthereumTx populates the message fields from the given signed ethereum transaction, and set From field. func (msg *MsgEthereumTx) FromSignedEthereumTx(tx *ethtypes.Transaction, signer ethtypes.Signer) error { - msg.Raw.Transaction = tx - from, err := ethtypes.Sender(signer, tx) if err != nil { return err } + // trigger cache tx size + _ = tx.Size() + + msg.Raw.Transaction = tx msg.From = from.Bytes() + return nil } // Route returns the route value of an MsgEthereumTx. -func (msg MsgEthereumTx) Route() string { return RouterKey } +func (msg *MsgEthereumTx) Route() string { return RouterKey } // Type returns the type value of an MsgEthereumTx. -func (msg MsgEthereumTx) Type() string { return TypeMsgEthereumTx } +func (msg *MsgEthereumTx) Type() string { return TypeMsgEthereumTx } // ValidateBasic implements the sdk.Msg interface. It performs basic validation // checks of a Transaction. If returns an error if validation fails. -func (msg MsgEthereumTx) ValidateBasic() error { +func (msg *MsgEthereumTx) ValidateBasic() error { if msg.Raw.Transaction == nil { return errorsmod.Wrapf(errortypes.ErrInvalidRequest, "raw transaction is required") } @@ -182,7 +185,7 @@ func (msg *MsgEthereumTx) recoverSender(signer ethtypes.Signer) (common.Address, // // NOTE: This method cannot be used as a chain ID is needed to create valid bytes // to sign over. Use 'RLPSignBytes' instead. -func (msg MsgEthereumTx) GetSignBytes() []byte { +func (msg *MsgEthereumTx) GetSignBytes() []byte { panic("must use 'RLPSignBytes' with a chain ID to get the valid bytes to sign") } @@ -216,18 +219,18 @@ func (msg *MsgEthereumTx) Sign(ethSigner ethtypes.Signer, keyringSigner keyring. } // GetGas implements the GasTx interface. It returns the GasLimit of the transaction. -func (msg MsgEthereumTx) GetGas() uint64 { +func (msg *MsgEthereumTx) GetGas() uint64 { return msg.Raw.Gas() } // GetFee returns the fee for non dynamic fee tx -func (msg MsgEthereumTx) GetFee() *big.Int { +func (msg *MsgEthereumTx) GetFee() *big.Int { i := new(big.Int).SetUint64(msg.Raw.Gas()) return i.Mul(i, msg.Raw.GasPrice()) } // GetEffectiveFee returns the fee for dynamic fee tx -func (msg MsgEthereumTx) GetEffectiveFee(baseFee *big.Int) *big.Int { +func (msg *MsgEthereumTx) GetEffectiveFee(baseFee *big.Int) *big.Int { i := new(big.Int).SetUint64(msg.Raw.Gas()) gasTip, _ := msg.Raw.EffectiveGasTip(baseFee) effectiveGasPrice := new(big.Int).Add(gasTip, baseFee) @@ -241,13 +244,13 @@ func (msg *MsgEthereumTx) GetFrom() sdk.AccAddress { } // AsTransaction creates an Ethereum Transaction type from the msg fields -func (msg MsgEthereumTx) AsTransaction() *ethtypes.Transaction { +func (msg *MsgEthereumTx) AsTransaction() *ethtypes.Transaction { return msg.Raw.Transaction } // AsMessage vendors the core.TransactionToMessage function to avoid sender recovery, // assume the From field is set correctly in the MsgEthereumTx. -func (msg MsgEthereumTx) AsMessage(baseFee *big.Int) *core.Message { +func (msg *MsgEthereumTx) AsMessage(baseFee *big.Int) *core.Message { tx := msg.AsTransaction() ethMsg := &core.Message{ Nonce: tx.Nonce(), @@ -261,7 +264,7 @@ func (msg MsgEthereumTx) AsMessage(baseFee *big.Int) *core.Message { AccessList: tx.AccessList(), SetCodeAuthorizations: tx.SetCodeAuthorizations(), SkipNonceChecks: false, - SkipFromEOACheck: false, + SkipTransactionChecks: false, BlobHashes: tx.BlobHashes(), BlobGasFeeCap: tx.BlobGasFeeCap(), } @@ -357,5 +360,5 @@ func (m *MsgUpdateParams) ValidateBasic() error { // GetSignBytes implements the LegacyMsg interface. func (m MsgUpdateParams) GetSignBytes() []byte { - return sdk.MustSortJSON(AminoCdc.MustMarshalJSON(&m)) + return AminoCdc.MustMarshalJSON(&m) } diff --git a/x/vm/types/msg_test.go b/x/vm/types/msg_test.go index 0e2ca649..f2e38ec1 100644 --- a/x/vm/types/msg_test.go +++ b/x/vm/types/msg_test.go @@ -146,7 +146,7 @@ func (suite *MsgsTestSuite) TestMsgEthereumTx_ValidateBasic() { validChainID = big.NewInt(9000) zeroInt = big.NewInt(0) minusOneInt = big.NewInt(-1) - //nolint:all + exp_2_255 = new(big.Int).Exp(big.NewInt(2), big.NewInt(255), nil) ) testCases := []struct { diff --git a/x/vm/types/params.go b/x/vm/types/params.go index b861ea0c..0a9fd86b 100644 --- a/x/vm/types/params.go +++ b/x/vm/types/params.go @@ -5,15 +5,16 @@ import ( "math/big" "slices" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/params" "github.com/cosmos/evm/utils" - channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types" - host "github.com/cosmos/ibc-go/v10/modules/core/24-host" + channeltypes "github.com/cosmos/ibc-go/v11/modules/core/04-channel/types" + host "github.com/cosmos/ibc-go/v11/modules/core/24-host" errorsmod "cosmossdk.io/errors" + + sdk "github.com/cosmos/cosmos-sdk/types" ) var ( @@ -67,23 +68,18 @@ func NewParams( // DefaultParams returns default evm parameters func DefaultParams() Params { return Params{ - EvmDenom: DefaultEVMExtendedDenom, + EvmDenom: sdk.DefaultBondDenom, ExtraEIPs: DefaultExtraEIPs, ActiveStaticPrecompiles: DefaultStaticPrecompiles, EVMChannels: DefaultEVMChannels, AccessControl: DefaultAccessControl, HistoryServeWindow: DefaultHistoryServeWindow, - ExtendedDenomOptions: &ExtendedDenomOptions{ExtendedDenom: DefaultEVMExtendedDenom}, + ExtendedDenomOptions: &ExtendedDenomOptions{ExtendedDenom: sdk.DefaultBondDenom}, } } // validateChannels checks if channels ids are valid -func validateChannels(i interface{}) error { - channels, ok := i.([]string) - if !ok { - return fmt.Errorf("invalid parameter type: %T", i) - } - +func validateChannels(channels []string) error { for _, channel := range channels { if err := host.ChannelIdentifierValidator(channel); err != nil { return errorsmod.Wrap( @@ -121,16 +117,6 @@ func (p Params) EIPs() []int { return eips } -// GetActiveStaticPrecompilesAddrs is a util function that the Active Precompiles -// as a slice of addresses. -func (p Params) GetActiveStaticPrecompilesAddrs() []common.Address { - precompiles := make([]common.Address, len(p.ActiveStaticPrecompiles)) - for i, precompile := range p.ActiveStaticPrecompiles { - precompiles[i] = common.HexToAddress(precompile) - } - return precompiles -} - // IsEVMChannel returns true if the channel provided is in the list of // EVM channels func (p Params) IsEVMChannel(channel string) bool { @@ -151,12 +137,7 @@ func (act AccessControlType) Validate() error { return validateAllowlistAddresses(act.AccessControlList) } -func validateAccessType(i interface{}) error { - accessType, ok := i.(AccessType) - if !ok { - return fmt.Errorf("invalid access type type: %T", i) - } - +func validateAccessType(accessType AccessType) error { switch accessType { case AccessTypePermissionless, AccessTypeRestricted, AccessTypePermissioned: return nil @@ -165,12 +146,7 @@ func validateAccessType(i interface{}) error { } } -func validateAllowlistAddresses(i interface{}) error { - addresses, ok := i.([]string) - if !ok { - return fmt.Errorf("invalid whitelist addresses type: %T", i) - } - +func validateAllowlistAddresses(addresses []string) error { for _, address := range addresses { if err := utils.ValidateAddress(address); err != nil { return fmt.Errorf("invalid whitelist address: %s", address) @@ -179,12 +155,7 @@ func validateAllowlistAddresses(i interface{}) error { return nil } -func validateEIPs(i interface{}) error { - eips, ok := i.([]int64) - if !ok { - return fmt.Errorf("invalid EIP slice type: %T", i) - } - +func validateEIPs(eips []int64) error { uniqueEIPs := make(map[int64]struct{}) for _, eip := range eips { @@ -203,12 +174,7 @@ func validateEIPs(i interface{}) error { } // ValidatePrecompiles checks if the precompile addresses are valid and unique. -func ValidatePrecompiles(i interface{}) error { - precompiles, ok := i.([]string) - if !ok { - return fmt.Errorf("invalid precompile slice type: %T", i) - } - +func ValidatePrecompiles(precompiles []string) error { seenPrecompiles := make(map[string]struct{}) for _, precompile := range precompiles { if _, ok := seenPrecompiles[precompile]; ok { diff --git a/x/vm/types/params_test.go b/x/vm/types/params_test.go index 23e8dc00..2395952f 100644 --- a/x/vm/types/params_test.go +++ b/x/vm/types/params_test.go @@ -1,6 +1,7 @@ package types import ( + "strings" "testing" ethparams "github.com/ethereum/go-ethereum/params" @@ -49,6 +50,22 @@ func TestParamsValidate(t *testing.T) { }, errContains: "precompiles need to be sorted", }, + { + name: "lowercase access control entries", + params: Params{ + AccessControl: AccessControl{ + Create: AccessControlType{ + AccessType: AccessTypePermissionless, + AccessControlList: []string{strings.ToLower("0x8FA78CEB7F04118Ec6d06AaC37Ca854691d8e963")}, + }, + Call: AccessControlType{ + AccessType: AccessTypePermissioned, + AccessControlList: []string{strings.ToLower("0x8FA78CEB7F04118Ec6d06AaC37Ca854691d8e963")}, + }, + }, + }, + expPass: true, + }, } for _, tc := range testCases { @@ -84,13 +101,10 @@ func TestParamsEIPs(t *testing.T) { } func TestParamsValidatePriv(t *testing.T) { - require.Error(t, validateEIPs("")) require.NoError(t, validateEIPs([]int64{1884})) require.ErrorContains(t, validateEIPs([]int64{1884, 1884, 1885}), "duplicate EIP: 1884") require.NoError(t, validateChannels([]string{"channel-0"})) - require.Error(t, validateChannels(false)) - require.Error(t, validateChannels(int64(123))) - require.Error(t, validateChannels("")) + require.Error(t, validateChannels([]string{"invalid"})) } func TestIsLondon(t *testing.T) { diff --git a/x/vm/types/permissions.go b/x/vm/types/permissions.go index e5bdcc76..e6f6f62b 100644 --- a/x/vm/types/permissions.go +++ b/x/vm/types/permissions.go @@ -2,7 +2,6 @@ package types import ( "fmt" - "slices" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" @@ -95,7 +94,24 @@ func getCanCreateFn(accessControl *AccessControl, signer common.Address) callerF return func(_ common.Address) bool { return false } } -// CanCreate implements the PermissionPolicy interface. +// addressSet is used for quickly checking inclusion of an address in both permissionedCheckFn and permissionlessCheckFn. +// Previous iterations of cosmos/evm used string equality checks, which made the checks case-sensitive. +type addressSet map[common.Address]struct{} + +func newAddressSet(addresses []string) addressSet { + set := make(addressSet, len(addresses)) + for _, address := range addresses { + set[common.HexToAddress(address)] = struct{}{} + } + return set +} + +func (s addressSet) contains(address common.Address) bool { + _, ok := s[address] + return ok +} + +// CanCall implements the PermissionPolicy interface. // It allows calls if access type is set to everybody. // Otherwise, it checks if: // - The signer is allowed to do so. @@ -121,21 +137,19 @@ func getCanCallFn(accessControl *AccessControl, signer common.Address) callerFn // permissionlessCheckFn returns a callerFn that returns true unless the signer or the caller is // within the addresses slice. func permissionlessCheckFn(addresses []string, signer common.Address) callerFn { - strSigner := signer.String() - isSignerBlocked := !slices.Contains(addresses, strSigner) + blockedAddresses := newAddressSet(addresses) + isSignerAllowed := !blockedAddresses.contains(signer) return func(caller common.Address) bool { - strCaller := caller.String() - return isSignerBlocked && !slices.Contains(addresses, strCaller) + return isSignerAllowed && !blockedAddresses.contains(caller) } } // permissionedCheckFn returns a callerFn that returns true if the signer or caller // is within the addresses slice. func permissionedCheckFn(addresses []string, signer common.Address) callerFn { - strSigner := signer.String() - isSignerAllowed := slices.Contains(addresses, strSigner) + allowedAddresses := newAddressSet(addresses) + isSignerAllowed := allowedAddresses.contains(signer) return func(caller common.Address) bool { - strCaller := caller.String() - return isSignerAllowed || slices.Contains(addresses, strCaller) + return isSignerAllowed || allowedAddresses.contains(caller) } } diff --git a/x/vm/types/permissions_test.go b/x/vm/types/permissions_test.go index be8683e6..58d088f2 100644 --- a/x/vm/types/permissions_test.go +++ b/x/vm/types/permissions_test.go @@ -1,6 +1,7 @@ package types_test import ( + "strings" "testing" "github.com/ethereum/go-ethereum/common" @@ -211,11 +212,44 @@ func (suite *UnitTestSuite) TestAccessControl() { caller: keyring.GetAddr(0), recipient: keyring.GetAddr(0), }, + { + name: "should block lowercase access control list entries with permissionless policy", + getAccessControl: func() types.AccessControl { + p := types.DefaultParams().AccessControl + p.Create.AccessType = types.AccessTypePermissionless + p.Create.AccessControlList = []string{strings.ToLower(keyring.GetAddr(0).String())} + p.Call.AccessType = types.AccessTypePermissionless + p.Call.AccessControlList = []string{strings.ToLower(keyring.GetAddr(0).String())} + return p + }, + canCall: false, + canCreate: false, + signer: keyring.GetAddr(0), + caller: keyring.GetAddr(0), + recipient: keyring.GetAddr(0), + }, + { + name: "should allow lowercase access control list entries with permissioned policy", + getAccessControl: func() types.AccessControl { + p := types.DefaultParams().AccessControl + p.Create.AccessType = types.AccessTypePermissioned + p.Create.AccessControlList = []string{strings.ToLower(keyring.GetAddr(0).String())} + p.Call.AccessType = types.AccessTypePermissioned + p.Call.AccessControlList = []string{strings.ToLower(keyring.GetAddr(0).String())} + return p + }, + canCall: true, + canCreate: true, + signer: keyring.GetAddr(0), + caller: keyring.GetAddr(0), + recipient: keyring.GetAddr(0), + }, } for _, tc := range testCases { suite.Run(tc.name, func() { accessControl := tc.getAccessControl() + suite.Require().NoError(accessControl.Validate()) permissionPolicy := types.NewRestrictedPermissionPolicy( &accessControl, tc.signer, diff --git a/x/vm/types/precompiles.go b/x/vm/types/precompiles.go index aa0c484e..a7e058ac 100644 --- a/x/vm/types/precompiles.go +++ b/x/vm/types/precompiles.go @@ -13,6 +13,7 @@ const ( BankPrecompileAddress = "0x0000000000000000000000000000000000000804" GovPrecompileAddress = "0x0000000000000000000000000000000000000805" SlashingPrecompileAddress = "0x0000000000000000000000000000000000000806" + ICS02PrecompileAddress = "0x0000000000000000000000000000000000000807" ) // AvailableStaticPrecompiles defines the full list of all available EVM extension addresses. @@ -29,4 +30,5 @@ var AvailableStaticPrecompiles = []string{ BankPrecompileAddress, GovPrecompileAddress, SlashingPrecompileAddress, + ICS02PrecompileAddress, } diff --git a/x/vm/types/query.pb.go b/x/vm/types/query.pb.go index c007de0a..ecb82c79 100644 --- a/x/vm/types/query.pb.go +++ b/x/vm/types/query.pb.go @@ -2355,6 +2355,7 @@ func _Query_GlobalMinGasPrice_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } +var Query_serviceDesc = _Query_serviceDesc var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "cosmos.evm.vm.v1.Query", HandlerType: (*QueryServer)(nil), diff --git a/x/vm/types/response.go b/x/vm/types/response.go new file mode 100644 index 00000000..80cc7409 --- /dev/null +++ b/x/vm/types/response.go @@ -0,0 +1,108 @@ +package types + +import ( + "strconv" + + abci "github.com/cometbft/cometbft/abci/types" + + "github.com/cosmos/gogoproto/proto" + + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// PatchTxResponses rewrites block-cumulative / eth-only indices that cannot +// be computed per-tx under BlockSTM: +// +// - log.Index (cumulative across the block) and log.TxIndex (eth-only tx +// counter) inside MsgEthereumTxResponse payloads. +// - AttributeKeyTxIndex on ante-emitted ethereum_tx events, rewritten from +// ctx.TxIndex() (cosmos-level position) to the eth-only counter so the +// indexer's stored EthTxIndex — which becomes receipt.TransactionIndex +// in RPC receipts — stays aligned with log.TxIndex in mixed-tx blocks. +// +// Must be invoked once per block on the full ExecTxResult slice produced by +// the TxRunner. Gated on TxSucessOrExpectedFailure to match the indexer's and +// RPC backend's eth-rank inclusion rule — unexpected failures don't consume +// an eth-tx rank. +func PatchTxResponses(input []*abci.ExecTxResult) ([]*abci.ExecTxResult, error) { + var ( + ethTxIndex uint64 + logIndex uint64 + ) + for _, res := range input { + if !TxSucessOrExpectedFailure(res) { + continue + } + + rewritten := rewriteEthTxEventIndex(res.Events, ethTxIndex) + + if res.Code != 0 { + ethTxIndex += uint64(rewritten) //#nosec G115 -- int overflow is not a concern here + continue + } + + var txMsgData sdk.TxMsgData + if err := proto.Unmarshal(res.Data, &txMsgData); err != nil { + ethTxIndex += uint64(rewritten) //#nosec G115 -- int overflow is not a concern here + continue + } + + dataDirty := false + for i, rsp := range txMsgData.MsgResponses { + var response MsgEthereumTxResponse + if rsp.TypeUrl != "/"+proto.MessageName(&response) { + continue + } + if err := proto.Unmarshal(rsp.Value, &response); err != nil { + return nil, err + } + + if len(response.Logs) > 0 { + for _, log := range response.Logs { + log.TxIndex = ethTxIndex + log.Index = logIndex + logIndex++ + } + + anyRsp, err := codectypes.NewAnyWithValue(&response) + if err != nil { + return nil, err + } + txMsgData.MsgResponses[i] = anyRsp + dataDirty = true + } + + ethTxIndex++ + } + + if dataDirty { + data, err := proto.Marshal(&txMsgData) + if err != nil { + return nil, err + } + res.Data = data + } + } + return input, nil +} + +// rewriteEthTxEventIndex rewrites AttributeKeyTxIndex on every ethereum_tx +// event in events to start, start+1, ... and returns the number of events +// rewritten. +func rewriteEthTxEventIndex(events []abci.Event, start uint64) int { + n := 0 + for eIdx := range events { + if events[eIdx].Type != EventTypeEthereumTx { + continue + } + for aIdx := range events[eIdx].Attributes { + if events[eIdx].Attributes[aIdx].Key == AttributeKeyTxIndex { + events[eIdx].Attributes[aIdx].Value = strconv.FormatUint(start+uint64(n), 10) //#nosec G115 -- int overflow is not a concern here + n++ + break + } + } + } + return n +} diff --git a/x/vm/types/response_test.go b/x/vm/types/response_test.go new file mode 100644 index 00000000..45a1bd68 --- /dev/null +++ b/x/vm/types/response_test.go @@ -0,0 +1,382 @@ +package types_test + +import ( + "strconv" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + + abci "github.com/cometbft/cometbft/abci/types" + + evmtypes "github.com/cosmos/evm/x/vm/types" + "github.com/cosmos/gogoproto/proto" + + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func createEthTxResult(t *testing.T, hash string, numLogs int, code uint32) *abci.ExecTxResult { + t.Helper() + logs := make([]*evmtypes.Log, numLogs) + for i := 0; i < numLogs; i++ { + logs[i] = &evmtypes.Log{Data: []byte{byte(i)}} + } + response := &evmtypes.MsgEthereumTxResponse{ + Hash: common.BytesToHash([]byte(hash)).String(), + Logs: logs, + } + anyRsp, _ := codectypes.NewAnyWithValue(response) + txMsgData := &sdk.TxMsgData{ + MsgResponses: []*codectypes.Any{anyRsp}, + } + data, _ := proto.Marshal(txMsgData) + return &abci.ExecTxResult{ + Code: code, + Data: data, + } +} + +func unmarshalTxResponse(t *testing.T, result *abci.ExecTxResult) *evmtypes.MsgEthereumTxResponse { + t.Helper() + var txMsgData sdk.TxMsgData + err := proto.Unmarshal(result.Data, &txMsgData) + require.NoError(t, err) + var response evmtypes.MsgEthereumTxResponse + err = proto.Unmarshal(txMsgData.MsgResponses[0].Value, &response) + require.NoError(t, err) + return &response +} + +func TestPatchTxResponses(t *testing.T) { + testCases := []struct { + name string + input []*abci.ExecTxResult + validate func(t *testing.T, result []*abci.ExecTxResult) + }{ + { + name: "empty input", + input: []*abci.ExecTxResult{}, + validate: func(t *testing.T, result []*abci.ExecTxResult) { + t.Helper() + require.Empty(t, result) + }, + }, + { + name: "single tx with no logs is a no-op", + input: []*abci.ExecTxResult{createEthTxResult(t, "hash1", 0, 0)}, + validate: func(t *testing.T, result []*abci.ExecTxResult) { + t.Helper() + require.Len(t, result, 1) + require.Empty(t, result[0].Events) + }, + }, + { + name: "single tx with logs: log.Index + log.TxIndex rewritten", + input: []*abci.ExecTxResult{createEthTxResult(t, "hash1", 2, 0)}, + validate: func(t *testing.T, result []*abci.ExecTxResult) { + t.Helper() + require.Len(t, result, 1) + response := unmarshalTxResponse(t, result[0]) + require.Len(t, response.Logs, 2) + require.Equal(t, uint64(0), response.Logs[0].TxIndex) + require.Equal(t, uint64(0), response.Logs[0].Index) + require.Equal(t, uint64(0), response.Logs[1].TxIndex) + require.Equal(t, uint64(1), response.Logs[1].Index) + }, + }, + { + name: "multiple txs with logs: indices monotonic across block", + input: []*abci.ExecTxResult{ + createEthTxResult(t, "hash1", 2, 0), + createEthTxResult(t, "hash2", 3, 0), + }, + validate: func(t *testing.T, result []*abci.ExecTxResult) { + t.Helper() + require.Len(t, result, 2) + response1 := unmarshalTxResponse(t, result[0]) + require.Len(t, response1.Logs, 2) + require.Equal(t, uint64(0), response1.Logs[0].TxIndex) + require.Equal(t, uint64(0), response1.Logs[0].Index) + require.Equal(t, uint64(0), response1.Logs[1].TxIndex) + require.Equal(t, uint64(1), response1.Logs[1].Index) + + response2 := unmarshalTxResponse(t, result[1]) + require.Len(t, response2.Logs, 3) + require.Equal(t, uint64(1), response2.Logs[0].TxIndex) + require.Equal(t, uint64(2), response2.Logs[0].Index) + require.Equal(t, uint64(1), response2.Logs[1].TxIndex) + require.Equal(t, uint64(3), response2.Logs[1].Index) + require.Equal(t, uint64(1), response2.Logs[2].TxIndex) + require.Equal(t, uint64(4), response2.Logs[2].Index) + }, + }, + { + name: "failed tx is skipped (no index increments)", + input: []*abci.ExecTxResult{createEthTxResult(t, "hash1", 1, 1)}, + validate: func(t *testing.T, result []*abci.ExecTxResult) { + t.Helper() + require.Len(t, result, 1) + require.Empty(t, result[0].Events) + }, + }, + { + name: "mixed success and failed txs: eth tx counter only advances on success", + input: []*abci.ExecTxResult{ + createEthTxResult(t, "hash1", 1, 0), + createEthTxResult(t, "hash2", 1, 1), + createEthTxResult(t, "hash3", 1, 0), + }, + validate: func(t *testing.T, result []*abci.ExecTxResult) { + t.Helper() + require.Len(t, result, 3) + + response1 := unmarshalTxResponse(t, result[0]) + require.Equal(t, uint64(0), response1.Logs[0].TxIndex) + require.Equal(t, uint64(0), response1.Logs[0].Index) + + require.Empty(t, result[1].Events) + + response3 := unmarshalTxResponse(t, result[2]) + require.Equal(t, uint64(1), response3.Logs[0].TxIndex) + require.Equal(t, uint64(1), response3.Logs[0].Index) + }, + }, + { + name: "existing events are preserved", + input: func() []*abci.ExecTxResult { + result := createEthTxResult(t, "hash1", 1, 0) + result.Events = []abci.Event{ + {Type: "existing_event", Attributes: []abci.EventAttribute{{Key: "key", Value: "value"}}}, + } + return []*abci.ExecTxResult{result} + }(), + validate: func(t *testing.T, result []*abci.ExecTxResult) { + t.Helper() + require.Len(t, result, 1) + require.Len(t, result[0].Events, 1) + require.Equal(t, "existing_event", result[0].Events[0].Type) + }, + }, + { + name: "non-ethereum tx msg response is ignored", + input: func() []*abci.ExecTxResult { + anyRsp, _ := codectypes.NewAnyWithValue(&sdk.TxMsgData{}) + txMsgData := &sdk.TxMsgData{MsgResponses: []*codectypes.Any{anyRsp}} + data, _ := proto.Marshal(txMsgData) + return []*abci.ExecTxResult{{Code: 0, Data: data}} + }(), + validate: func(t *testing.T, result []*abci.ExecTxResult) { + t.Helper() + require.Len(t, result, 1) + require.Empty(t, result[0].Events) + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + result, err := evmtypes.PatchTxResponses(tc.input) + require.NoError(t, err) + tc.validate(t, result) + }) + } +} + +// ethTxEvent builds an ante-style ethereum_tx event with the given cosmos +// position as AttributeKeyTxIndex. Used to simulate what EmitTxHashEvent +// produces from the ante handler. +func ethTxEvent(hash string, cosmosTxIndex uint64) abci.Event { + return abci.Event{ + Type: evmtypes.EventTypeEthereumTx, + Attributes: []abci.EventAttribute{ + {Key: evmtypes.AttributeKeyEthereumTxHash, Value: hash}, + {Key: evmtypes.AttributeKeyTxIndex, Value: strconv.FormatUint(cosmosTxIndex, 10)}, + }, + } +} + +func eventTxIndex(t *testing.T, res *abci.ExecTxResult) string { + t.Helper() + for _, ev := range res.Events { + if ev.Type != evmtypes.EventTypeEthereumTx { + continue + } + for _, a := range ev.Attributes { + if a.Key == evmtypes.AttributeKeyTxIndex { + return a.Value + } + } + } + t.Fatalf("no %s event with %s attribute", evmtypes.EventTypeEthereumTx, evmtypes.AttributeKeyTxIndex) + return "" +} + +// TestPatchTxResponses_MixedBlockEventRewrite asserts that in a block where a +// non-EVM cosmos tx sits between EVM txs, the ante-emitted ethereum_tx events +// get their AttributeKeyTxIndex rewritten from cosmos-position to eth-only +// rank so the indexer's EthTxIndex (and downstream receipt.TransactionIndex) +// matches log.TxIndex. +func TestPatchTxResponses_MixedBlockEventRewrite(t *testing.T) { + eth0 := createEthTxResult(t, "hash0", 1, 0) + eth0.Events = []abci.Event{ethTxEvent("0xaa", 0)} + + nonEVM := &abci.ExecTxResult{Code: 0} + + eth2 := createEthTxResult(t, "hash2", 1, 0) + eth2.Events = []abci.Event{ethTxEvent("0xbb", 2)} + + result, err := evmtypes.PatchTxResponses([]*abci.ExecTxResult{eth0, nonEVM, eth2}) + require.NoError(t, err) + require.Len(t, result, 3) + + require.Equal(t, "0", eventTxIndex(t, result[0])) + require.Equal(t, "1", eventTxIndex(t, result[2]), + "second eth tx's event should be rewritten from cosmos-pos 2 to eth-only rank 1") + + resp0 := unmarshalTxResponse(t, result[0]) + require.Equal(t, uint64(0), resp0.Logs[0].TxIndex) + resp2 := unmarshalTxResponse(t, result[2]) + require.Equal(t, uint64(1), resp2.Logs[0].TxIndex, + "log.TxIndex must agree with the event attribute so receipt.TransactionIndex == log.transactionIndex") +} + +// TestPatchTxResponses_NonTxMsgDataDoesNotHaltBlock asserts that a successful +// non-EVM tx carrying a res.Data payload that isn't an sdk.TxMsgData is +// skipped rather than causing the whole block to error out. +func TestPatchTxResponses_NonTxMsgDataDoesNotHaltBlock(t *testing.T) { + nonEVM := &abci.ExecTxResult{Code: 0, Data: []byte{0xff, 0xff, 0xff}} + + eth := createEthTxResult(t, "hash1", 1, 0) + + result, err := evmtypes.PatchTxResponses([]*abci.ExecTxResult{nonEVM, eth}) + require.NoError(t, err) + require.Len(t, result, 2) + + require.Equal(t, []byte{0xff, 0xff, 0xff}, result[0].Data, "non-EVM data must be left untouched") + + resp := unmarshalTxResponse(t, result[1]) + require.Equal(t, uint64(0), resp.Logs[0].TxIndex, + "eth tx counter must start from 0 when preceding non-EVM tx is skipped") +} + +// TestPatchTxResponses_ExceedBlockGasLimitAdvancesCounter asserts that an +// ExceedBlockGasLimit failure — which the indexer still includes in the eth +// rank space — advances the eth-only counter. +func TestPatchTxResponses_ExceedBlockGasLimitAdvancesCounter(t *testing.T) { + failed := &abci.ExecTxResult{ + Code: 1, + Log: evmtypes.ExceedBlockGasLimitError, + Events: []abci.Event{ethTxEvent("0xaa", 0)}, + } + + eth1 := createEthTxResult(t, "hash1", 1, 0) + eth1.Events = []abci.Event{ethTxEvent("0xbb", 1)} + + result, err := evmtypes.PatchTxResponses([]*abci.ExecTxResult{failed, eth1}) + require.NoError(t, err) + + require.Equal(t, "0", eventTxIndex(t, result[0])) + require.Equal(t, "1", eventTxIndex(t, result[1])) + + resp1 := unmarshalTxResponse(t, result[1]) + require.Equal(t, uint64(1), resp1.Logs[0].TxIndex) +} + +// TestPatchTxResponses_UnexpectedFailureIsSkipped asserts that a failure that +// is NOT ExceedBlockGasLimit is skipped entirely — events are not rewritten +// and the eth-only counter is not advanced — matching the indexer's and RPC +// backend's TxSucessOrExpectedFailure gate. +func TestPatchTxResponses_UnexpectedFailureIsSkipped(t *testing.T) { + eth0 := createEthTxResult(t, "hash0", 1, 0) + eth0.Events = []abci.Event{ethTxEvent("0xaa", 0)} + + rejected := &abci.ExecTxResult{ + Code: 1, + Log: "some unrelated ante error", + Events: []abci.Event{ethTxEvent("0xbb", 1)}, + } + + eth2 := createEthTxResult(t, "hash2", 1, 0) + eth2.Events = []abci.Event{ethTxEvent("0xcc", 2)} + + result, err := evmtypes.PatchTxResponses([]*abci.ExecTxResult{eth0, rejected, eth2}) + require.NoError(t, err) + + require.Equal(t, "0", eventTxIndex(t, result[0])) + require.Equal(t, "1", eventTxIndex(t, result[1]), + "rejected tx's event should retain its original cosmos-position value (not rewritten)") + require.Equal(t, "1", eventTxIndex(t, result[2]), + "third eth tx's rank should be 1 (rejected tx did not consume a rank)") + + resp2 := unmarshalTxResponse(t, result[2]) + require.Equal(t, uint64(1), resp2.Logs[0].TxIndex) +} + +func TestPatchTxResponses_LogIndex(t *testing.T) { + input := []*abci.ExecTxResult{ + createEthTxResult(t, "hash1", 2, 0), + createEthTxResult(t, "hash2", 3, 0), + createEthTxResult(t, "hash3", 1, 0), + } + result, err := evmtypes.PatchTxResponses(input) + require.NoError(t, err) + expectedLogIndexes := [][]uint64{ + {0, 1}, + {2, 3, 4}, + {5}, + } + for txIdx, expectedIndexes := range expectedLogIndexes { + response := unmarshalTxResponse(t, result[txIdx]) + require.Len(t, response.Logs, len(expectedIndexes)) + for logIdx, expectedIndex := range expectedIndexes { + require.Equal(t, expectedIndex, response.Logs[logIdx].Index) + require.Equal(t, uint64(txIdx), response.Logs[logIdx].TxIndex) //#nosec G115 + } + } +} + +func TestPatchTxResponses_DualEthereumTxEvents(t *testing.T) { + failed := &abci.ExecTxResult{ + Code: 1, + Log: evmtypes.ExceedBlockGasLimitError, + Events: []abci.Event{ + ethTxEvent("0xaa", 0), + {Type: evmtypes.EventTypeEthereumTx, Attributes: []abci.EventAttribute{ + {Key: evmtypes.AttributeKeyEthereumTxHash, Value: "0xaa"}, + }}, + }, + } + + eth := createEthTxResult(t, "hash1", 1, 0) + eth.Events = []abci.Event{ethTxEvent("0xbb", 1)} + + result, err := evmtypes.PatchTxResponses([]*abci.ExecTxResult{failed, eth}) + require.NoError(t, err) + + require.Equal(t, "0", eventTxIndex(t, result[0])) + require.Equal(t, "1", eventTxIndex(t, result[1])) + + resp := unmarshalTxResponse(t, result[1]) + require.Equal(t, uint64(1), resp.Logs[0].TxIndex) +} + +func TestPatchTxResponses_ZeroLogEthTx(t *testing.T) { + input := []*abci.ExecTxResult{ + createEthTxResult(t, "hash1", 2, 0), + createEthTxResult(t, "hash2", 0, 0), + createEthTxResult(t, "hash3", 1, 0), + } + result, err := evmtypes.PatchTxResponses(input) + require.NoError(t, err) + + resp0 := unmarshalTxResponse(t, result[0]) + require.Len(t, resp0.Logs, 2) + require.Equal(t, uint64(0), resp0.Logs[0].Index) + require.Equal(t, uint64(1), resp0.Logs[1].Index) + + resp2 := unmarshalTxResponse(t, result[2]) + require.Len(t, resp2.Logs, 1) + require.Equal(t, uint64(2), resp2.Logs[0].Index, "zero-log tx must not advance log.Index") + require.Equal(t, uint64(2), resp2.Logs[0].TxIndex, "zero-log tx must still take an eth-tx rank") +} diff --git a/x/vm/types/tracer.go b/x/vm/types/tracer.go index 426835b8..ecf9c6dd 100644 --- a/x/vm/types/tracer.go +++ b/x/vm/types/tracer.go @@ -51,8 +51,8 @@ func NewTracer(tracer string, msg core.Message, cfg *params.ChainConfig, height // TxTraceResult is the result of a single transaction trace during a block trace. type TxTraceResult struct { - Result interface{} `json:"result,omitempty"` // Trace results produced by the tracer - Error string `json:"error,omitempty"` // Trace failure produced by the tracer + Result any `json:"result,omitempty"` // Trace results produced by the tracer + Error string `json:"error,omitempty"` // Trace failure produced by the tracer } // NoOpTracer is an empty implementation of vm.Tracer interface diff --git a/x/vm/types/tx.pb.go b/x/vm/types/tx.pb.go index 09677597..4247dfe4 100644 --- a/x/vm/types/tx.pb.go +++ b/x/vm/types/tx.pb.go @@ -128,7 +128,8 @@ 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 + // 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"` @@ -563,6 +564,7 @@ func _Msg_RegisterPreinstalls_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } +var Msg_serviceDesc = _Msg_serviceDesc var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "cosmos.evm.vm.v1.Msg", HandlerType: (*MsgServer)(nil), diff --git a/x/vm/types/tx_args.go b/x/vm/types/tx_args.go index 9f382e77..74635b68 100644 --- a/x/vm/types/tx_args.go +++ b/x/vm/types/tx_args.go @@ -140,7 +140,7 @@ func (args *TransactionArgs) CallDefaults(globalGasCap uint64, baseFee *big.Int, // core evm. This method is used in calls and traces that do not require a real // live transaction. // Assumes that fields are not nil, i.e. setDefaults or CallDefaults has been called. -func (args *TransactionArgs) ToMessage(baseFee *big.Int, skipNonceCheck, skipEoACheck bool) *core.Message { +func (args *TransactionArgs) ToMessage(baseFee *big.Int, skipNonceCheck, skipTransactionChecks bool) *core.Message { var ( gasPrice *big.Int gasFeeCap *big.Int @@ -188,7 +188,7 @@ func (args *TransactionArgs) ToMessage(baseFee *big.Int, skipNonceCheck, skipEoA BlobHashes: args.BlobHashes, SetCodeAuthorizations: args.AuthorizationList, SkipNonceChecks: skipNonceCheck, - SkipFromEOACheck: skipEoACheck, + SkipTransactionChecks: skipTransactionChecks, } } diff --git a/x/vm/types/tx_result.go b/x/vm/types/tx_result.go new file mode 100644 index 00000000..1a0a505c --- /dev/null +++ b/x/vm/types/tx_result.go @@ -0,0 +1,24 @@ +package types + +import ( + "strings" + + abci "github.com/cometbft/cometbft/abci/types" +) + +// ExceedBlockGasLimitError is the ante-handler error string emitted when the +// block gas meter runs out. The tx fee is already deducted in ante, so the tx +// is still counted toward the eth rank space. +const ExceedBlockGasLimitError = "out of gas in location: block gas meter; gasWanted:" + +// TxExceedBlockGasLimit reports whether res failed due to block gas exhaustion. +func TxExceedBlockGasLimit(res *abci.ExecTxResult) bool { + return strings.Contains(res.Log, ExceedBlockGasLimitError) +} + +// TxSucessOrExpectedFailure reports whether a tx participates in the eth rank +// space — success or an expected ExceedBlockGasLimit failure. The indexer and +// RPC backend gate inclusion on this; PatchTxResponses must agree. +func TxSucessOrExpectedFailure(res *abci.ExecTxResult) bool { + return res.Code == 0 || TxExceedBlockGasLimit(res) +} diff --git a/x/vm/types/utils.go b/x/vm/types/utils.go index 23a01e4f..9aa3d0f9 100644 --- a/x/vm/types/utils.go +++ b/x/vm/types/utils.go @@ -16,8 +16,8 @@ import ( "github.com/cosmos/gogoproto/proto" errorsmod "cosmossdk.io/errors" - storetypes "cosmossdk.io/store/types" + storetypes "github.com/cosmos/cosmos-sdk/store/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" errortypes "github.com/cosmos/cosmos-sdk/types/errors" ) @@ -209,14 +209,14 @@ func HexAddress(a []byte) string { } // SortedKVStoreKeys returns a slice of *KVStoreKey sorted by their map key. -func SortedKVStoreKeys(keys map[string]*storetypes.KVStoreKey) []*storetypes.KVStoreKey { +func SortedKVStoreKeys(keys map[string]storetypes.StoreKey) []storetypes.StoreKey { names := make([]string, 0, len(keys)) for name := range keys { names = append(names, name) } sort.Strings(names) - sorted := make([]*storetypes.KVStoreKey, 0, len(keys)) + sorted := make([]storetypes.StoreKey, 0, len(keys)) for _, name := range names { sorted = append(sorted, keys[name]) } diff --git a/x/vm/wrappers/bank.go b/x/vm/wrappers/bank.go index ac50e308..66943a2b 100644 --- a/x/vm/wrappers/bank.go +++ b/x/vm/wrappers/bank.go @@ -34,40 +34,15 @@ func NewBankWrapper( // Bank wrapper own methods // ------------------------------------------------------------------------------------------ -// MintAmountToAccount converts the given amount into the evm coin scaling -// the amount to the original decimals, then mints that amount to the provided account. -func (w BankWrapper) MintAmountToAccount(ctx context.Context, recipientAddr sdk.AccAddress, amt *big.Int) error { +func (w BankWrapper) SetBalance(ctx context.Context, account sdk.AccAddress, amt *big.Int) error { coin := sdk.Coin{Denom: types.GetEVMCoinDenom(), Amount: sdkmath.NewIntFromBigInt(amt)} convertedCoin, err := types.ConvertEvmCoinDenomToExtendedDenom(coin) if err != nil { - return errors.Wrap(err, "failed to mint coin to account in bank wrapper") + return errors.Wrap(err, "failed to set coins in bank wrapper") } - coinsToMint := sdk.Coins{convertedCoin} - if err := w.MintCoins(ctx, types.ModuleName, coinsToMint); err != nil { - return errors.Wrap(err, "failed to mint coins to account in bank wrapper") - } - - return w.BankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, recipientAddr, coinsToMint) -} - -// BurnAmountFromAccount converts the given amount into the evm coin scaling -// the amount to the original decimals, then burns that quantity from the provided account. -func (w BankWrapper) BurnAmountFromAccount(ctx context.Context, account sdk.AccAddress, amt *big.Int) error { - coin := sdk.Coin{Denom: types.GetEVMCoinDenom(), Amount: sdkmath.NewIntFromBigInt(amt)} - - convertedCoin, err := types.ConvertEvmCoinDenomToExtendedDenom(coin) - if err != nil { - return errors.Wrap(err, "failed to burn coins from account in bank wrapper") - } - - coinsToBurn := sdk.Coins{convertedCoin} - - if err := w.BankKeeper.SendCoinsFromAccountToModule(ctx, account, types.ModuleName, coinsToBurn); err != nil { - return errors.Wrap(err, "failed to burn coins from account in bank wrapper") - } - return w.BurnCoins(ctx, types.ModuleName, coinsToBurn) + return w.UncheckedSetBalance(ctx, account, convertedCoin) } // ------------------------------------------------------------------------------------------ diff --git a/x/vm/wrappers/bank_test.go b/x/vm/wrappers/bank_test.go index 590da990..7bb1ca86 100644 --- a/x/vm/wrappers/bank_test.go +++ b/x/vm/wrappers/bank_test.go @@ -22,112 +22,7 @@ import ( // --------------------------------------TRANSACTIONS----------------------------------------------- -func TestMintAmountToAccount(t *testing.T) { - eighteenDecimalsCoinInfo := testconstants.ExampleChainCoinInfo[testconstants.ExampleChainID] - sixDecimalsCoinInfo := testconstants.ExampleChainCoinInfo[testconstants.SixDecimalsChainID] - - testCases := []struct { - name string - coinInfo evmtypes.EvmCoinInfo - evmDenom string - amount *big.Int - recipient sdk.AccAddress - expectErr string - mockSetup func(*testutil.MockBankWrapper) - }{ - { - name: "success - convert evm coin denom to extended denom", - coinInfo: sixDecimalsCoinInfo, - evmDenom: sixDecimalsCoinInfo.Denom, - amount: big.NewInt(1e18), // 1 token in 18 decimals - recipient: sdk.AccAddress([]byte("test_address")), - expectErr: "", - mockSetup: func(mbk *testutil.MockBankWrapper) { - expectedCoin := sdk.NewCoin(sixDecimalsCoinInfo.ExtendedDenom, sdkmath.NewInt(1e18)) // 1 token in 18 decimals - expectedCoins := sdk.NewCoins(expectedCoin) - - mbk.EXPECT(). - MintCoins(gomock.Any(), evmtypes.ModuleName, expectedCoins). - Return(nil) - - mbk.EXPECT(). - SendCoinsFromModuleToAccount( - gomock.Any(), - evmtypes.ModuleName, - sdk.AccAddress([]byte("test_address")), - expectedCoins, - ).Return(nil) - }, - }, - { - name: "success - 18 decimals amount not modified", - coinInfo: eighteenDecimalsCoinInfo, - evmDenom: eighteenDecimalsCoinInfo.Denom, - amount: big.NewInt(1e18), // 1 token in 18 decimals - recipient: sdk.AccAddress([]byte("test_address")), - expectErr: "", - mockSetup: func(mbk *testutil.MockBankWrapper) { - expectedCoin := sdk.NewCoin(eighteenDecimalsCoinInfo.Denom, sdkmath.NewInt(1e18)) - expectedCoins := sdk.NewCoins(expectedCoin) - - mbk.EXPECT(). - MintCoins(gomock.Any(), evmtypes.ModuleName, expectedCoins). - Return(nil) - - mbk.EXPECT(). - SendCoinsFromModuleToAccount( - gomock.Any(), - evmtypes.ModuleName, - sdk.AccAddress([]byte("test_address")), - expectedCoins, - ).Return(nil) - }, - }, - { - name: "fail - mint coins error", - coinInfo: sixDecimalsCoinInfo, - evmDenom: sixDecimalsCoinInfo.Denom, - amount: big.NewInt(1e18), - recipient: sdk.AccAddress([]byte("test_address")), - expectErr: "failed to mint coins to account in bank wrapper", - mockSetup: func(mbk *testutil.MockBankWrapper) { - expectedCoin := sdk.NewCoin(sixDecimalsCoinInfo.ExtendedDenom, sdkmath.NewInt(1e18)) - expectedCoins := sdk.NewCoins(expectedCoin) - - mbk.EXPECT(). - MintCoins(gomock.Any(), evmtypes.ModuleName, expectedCoins). - Return(errors.New("mint error")) - }, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - // Setup EVM configurator to have access to the EVM coin info. - configurator := evmtypes.NewEVMConfigurator() - configurator.ResetTestConfig() - err := configurator.WithEVMCoinInfo(tc.coinInfo).Configure() - require.NoError(t, err, "failed to configure EVMConfigurator") - - // Setup mock controller - ctrl := gomock.NewController(t) - - mockBankKeeper := testutil.NewMockBankWrapper(ctrl) - tc.mockSetup(mockBankKeeper) - - bankWrapper := wrappers.NewBankWrapper(mockBankKeeper) - err = bankWrapper.MintAmountToAccount(context.Background(), tc.recipient, tc.amount) - - if tc.expectErr != "" { - require.ErrorContains(t, err, tc.expectErr) - } else { - require.NoError(t, err) - } - }) - } -} - -func TestBurnAmountFromAccount(t *testing.T) { +func TestSetBalance(t *testing.T) { eighteenDecimalsCoinInfo := testconstants.ExampleChainCoinInfo[testconstants.ExampleChainID] sixDecimalsCoinInfo := testconstants.ExampleChainCoinInfo[testconstants.SixDecimalsChainID] @@ -147,77 +42,40 @@ func TestBurnAmountFromAccount(t *testing.T) { expectErr: "", mockSetup: func(mbk *testutil.MockBankWrapper) { expectedCoin := sdk.NewCoin(sixDecimalsCoinInfo.ExtendedDenom, sdkmath.NewInt(1e18)) - expectedCoins := sdk.NewCoins(expectedCoin) mbk.EXPECT(). - SendCoinsFromAccountToModule( - gomock.Any(), - account, - evmtypes.ModuleName, - expectedCoins, - ).Return(nil) - - mbk.EXPECT(). - BurnCoins(gomock.Any(), evmtypes.ModuleName, expectedCoins). + UncheckedSetBalance(gomock.Any(), account, expectedCoin). Return(nil) }, }, { name: "success - 18 decimals amount not modified", coinInfo: eighteenDecimalsCoinInfo, - amount: big.NewInt(1e18), + amount: big.NewInt(0), expectErr: "", mockSetup: func(mbk *testutil.MockBankWrapper) { - expectedCoin := sdk.NewCoin(eighteenDecimalsCoinInfo.Denom, sdkmath.NewInt(1e18)) - expectedCoins := sdk.NewCoins(expectedCoin) - - mbk.EXPECT(). - SendCoinsFromAccountToModule( - gomock.Any(), - account, - evmtypes.ModuleName, - expectedCoins, - ).Return(nil) + amt := sdkmath.NewInt(0) + expectedCoin := sdk.NewCoin(eighteenDecimalsCoinInfo.Denom, amt) mbk.EXPECT(). - BurnCoins(gomock.Any(), evmtypes.ModuleName, expectedCoins). + UncheckedSetBalance(gomock.Any(), account, expectedCoin). Return(nil) }, }, { - name: "fail - send coins error", - coinInfo: sixDecimalsCoinInfo, - amount: big.NewInt(1e18), - expectErr: "failed to burn coins from account in bank wrapper", - mockSetup: func(mbk *testutil.MockBankWrapper) { - expectedCoin := sdk.NewCoin(sixDecimalsCoinInfo.ExtendedDenom, sdkmath.NewInt(1e18)) - expectedCoins := sdk.NewCoins(expectedCoin) - - mbk.EXPECT(). - SendCoinsFromAccountToModule( - gomock.Any(), - account, - evmtypes.ModuleName, - expectedCoins, - ).Return(errors.New("send error")) - }, - }, - { - name: "fail - send burn error", + name: "fail - set error", coinInfo: sixDecimalsCoinInfo, amount: big.NewInt(1e18), - expectErr: "burn error", + expectErr: "set error", mockSetup: func(mbk *testutil.MockBankWrapper) { expectedCoin := sdk.NewCoin(sixDecimalsCoinInfo.ExtendedDenom, sdkmath.NewInt(1e18)) - expectedCoins := sdk.NewCoins(expectedCoin) mbk.EXPECT(). - SendCoinsFromAccountToModule( + UncheckedSetBalance( gomock.Any(), account, - evmtypes.ModuleName, - expectedCoins, - ).Return(errors.New("burn error")) + expectedCoin, + ).Return(errors.New("set error")) }, }, } @@ -237,7 +95,7 @@ func TestBurnAmountFromAccount(t *testing.T) { tc.mockSetup(mockBankKeeper) bankWrapper := wrappers.NewBankWrapper(mockBankKeeper) - err = bankWrapper.BurnAmountFromAccount(context.Background(), account, tc.amount) + err = bankWrapper.SetBalance(context.Background(), account, tc.amount) if tc.expectErr != "" { require.ErrorContains(t, err, tc.expectErr) diff --git a/x/vm/wrappers/feemarket.go b/x/vm/wrappers/feemarket.go index f864ec3e..04f9c6a0 100644 --- a/x/vm/wrappers/feemarket.go +++ b/x/vm/wrappers/feemarket.go @@ -32,11 +32,21 @@ func NewFeeMarketWrapper( // GetBaseFee returns the base fee converted to 18 decimals. func (w FeeMarketWrapper) GetBaseFee(ctx sdk.Context, decimals types.Decimals) *big.Int { baseFee := w.FeeMarketKeeper.GetBaseFee(ctx) - if baseFee.IsNil() { - return nil + if baseFee.IsNil() || baseFee.BigInt() == nil { + return big.NewInt(0) } - - return baseFee.MulInt(decimals.ConversionFactor()).TruncateInt().BigInt() + if err := decimals.Validate(); err != nil { + return big.NewInt(0) + } + conv := decimals.ConversionFactor() + if conv.BigInt() == nil { + return big.NewInt(0) + } + converted := baseFee.MulInt(conv).TruncateInt().BigInt() + if converted == nil { + return big.NewInt(0) + } + return converted } // CalculateBaseFee returns the calculated base fee converted to 18 decimals. diff --git a/x/vm/wrappers/feemarket_test.go b/x/vm/wrappers/feemarket_test.go index e23bfb71..df951f7d 100644 --- a/x/vm/wrappers/feemarket_test.go +++ b/x/vm/wrappers/feemarket_test.go @@ -48,7 +48,7 @@ func TestGetBaseFee(t *testing.T) { { name: "success - nil base fee", coinInfo: testconstants.ExampleChainCoinInfo[testconstants.SixDecimalsChainID], - expResult: nil, + expResult: big.NewInt(0), mockSetup: func(mfk *testutil.MockFeeMarketKeeper) { mfk.EXPECT(). GetBaseFee(gomock.Any()). @@ -85,24 +85,58 @@ func TestGetBaseFee(t *testing.T) { Return(sdkmath.LegacyNewDecWithPrec(1, 13)) // multiplied by 1e12 is still less than 1 }, }, + { + name: "defensive - zero decimals returns zero without panic", + coinInfo: evmtypes.EvmCoinInfo{ + Denom: "aevmos", + ExtendedDenom: "aevmos", + DisplayDenom: "evmos", + Decimals: 0, // invalid/uninitialized + }, + expResult: big.NewInt(0), + mockSetup: func(mfk *testutil.MockFeeMarketKeeper) { + mfk.EXPECT(). + GetBaseFee(gomock.Any()). + Return(sdkmath.LegacyNewDec(1e18)) + }, + }, + { + name: "defensive - invalid decimals (19) returns zero without panic", + coinInfo: evmtypes.EvmCoinInfo{ + Denom: "aevmos", + ExtendedDenom: "aevmos", + DisplayDenom: "evmos", + Decimals: 19, // exceeds max supported + }, + expResult: big.NewInt(0), + mockSetup: func(mfk *testutil.MockFeeMarketKeeper) { + mfk.EXPECT(). + GetBaseFee(gomock.Any()). + Return(sdkmath.LegacyNewDec(1e18)) + }, + }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - // Setup EVM configurator to have access to the EVM coin info. - configurator := evmtypes.NewEVMConfigurator() - configurator.ResetTestConfig() - err := configurator.WithEVMCoinInfo(tc.coinInfo).Configure() - require.NoError(t, err, "failed to configure EVMConfigurator") - ctrl := gomock.NewController(t) mockFeeMarketKeeper := testutil.NewMockFeeMarketKeeper(ctrl) tc.mockSetup(mockFeeMarketKeeper) feeMarketWrapper := wrappers.NewFeeMarketWrapper(mockFeeMarketKeeper) - result := feeMarketWrapper.GetBaseFee(sdk.Context{}, evmtypes.Decimals(tc.coinInfo.Decimals)) - - require.Equal(t, tc.expResult, result) + // skip EVMConfigurator for defensive cases + if tc.coinInfo.Decimals == 0 || tc.coinInfo.Decimals > 18 { + result := feeMarketWrapper.GetBaseFee(sdk.Context{}, evmtypes.Decimals(tc.coinInfo.Decimals)) + require.Equal(t, tc.expResult, result) + } else { + // Setup EVM configurator to have access to the EVM coin info. + configurator := evmtypes.NewEVMConfigurator() + configurator.ResetTestConfig() + err := configurator.WithEVMCoinInfo(tc.coinInfo).Configure() + require.NoError(t, err, "failed to configure EVMConfigurator") + result := feeMarketWrapper.GetBaseFee(sdk.Context{}, evmtypes.Decimals(tc.coinInfo.Decimals)) + require.Equal(t, tc.expResult, result) + } }) } } diff --git a/x/vm/wrappers/testutil/mock.go b/x/vm/wrappers/testutil/mock.go index ff3ce949..08ce448f 100644 --- a/x/vm/wrappers/testutil/mock.go +++ b/x/vm/wrappers/testutil/mock.go @@ -22,9 +22,10 @@ import ( types1 "github.com/cosmos/cosmos-sdk/x/bank/types" types2 "github.com/cosmos/cosmos-sdk/x/staking/types" types3 "github.com/cosmos/evm/x/feemarket/types" + types4 "github.com/cosmos/evm/x/vm/types" common "github.com/ethereum/go-ethereum/common" core "github.com/ethereum/go-ethereum/core" - types4 "github.com/ethereum/go-ethereum/core/types" + types5 "github.com/ethereum/go-ethereum/core/types" vm "github.com/ethereum/go-ethereum/core/vm" gomock "go.uber.org/mock/gomock" ) @@ -242,6 +243,20 @@ func (m *MockBankKeeper) EXPECT() *MockBankKeeperMockRecorder { return m.recorder } +// BlockedAddr mocks base method. +func (m *MockBankKeeper) BlockedAddr(addr types.AccAddress) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BlockedAddr", addr) + ret0, _ := ret[0].(bool) + return ret0 +} + +// BlockedAddr indicates an expected call of BlockedAddr. +func (mr *MockBankKeeperMockRecorder) BlockedAddr(addr any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BlockedAddr", reflect.TypeOf((*MockBankKeeper)(nil).BlockedAddr), addr) +} + // BurnCoins mocks base method. func (m *MockBankKeeper) BurnCoins(ctx context.Context, moduleName string, amt types.Coins) error { m.ctrl.T.Helper() @@ -342,6 +357,20 @@ func (mr *MockBankKeeperMockRecorder) IterateTotalSupply(ctx, cb any) *gomock.Ca return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IterateTotalSupply", reflect.TypeOf((*MockBankKeeper)(nil).IterateTotalSupply), ctx, cb) } +// LockedCoins mocks base method. +func (m *MockBankKeeper) 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 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LockedCoins", reflect.TypeOf((*MockBankKeeper)(nil).LockedCoins), ctx, addr) +} + // MintCoins mocks base method. func (m *MockBankKeeper) MintCoins(ctx context.Context, moduleName string, amt types.Coins) error { m.ctrl.T.Helper() @@ -384,6 +413,20 @@ func (mr *MockBankKeeperMockRecorder) SendCoinsFromAccountToModule(ctx, senderAd return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromAccountToModule", reflect.TypeOf((*MockBankKeeper)(nil).SendCoinsFromAccountToModule), ctx, senderAddr, recipientModule, amt) } +// SendCoinsFromAccountToModuleVirtual mocks base method. +func (m *MockBankKeeper) SendCoinsFromAccountToModuleVirtual(ctx context.Context, senderAddr types.AccAddress, recipientModule string, amt types.Coins) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SendCoinsFromAccountToModuleVirtual", ctx, senderAddr, recipientModule, amt) + ret0, _ := ret[0].(error) + return ret0 +} + +// SendCoinsFromAccountToModuleVirtual indicates an expected call of SendCoinsFromAccountToModuleVirtual. +func (mr *MockBankKeeperMockRecorder) SendCoinsFromAccountToModuleVirtual(ctx, senderAddr, recipientModule, amt any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromAccountToModuleVirtual", reflect.TypeOf((*MockBankKeeper)(nil).SendCoinsFromAccountToModuleVirtual), ctx, senderAddr, recipientModule, amt) +} + // SendCoinsFromModuleToAccount mocks base method. func (m *MockBankKeeper) SendCoinsFromModuleToAccount(ctx context.Context, senderModule string, recipientAddr types.AccAddress, amt types.Coins) error { m.ctrl.T.Helper() @@ -398,6 +441,20 @@ func (mr *MockBankKeeperMockRecorder) SendCoinsFromModuleToAccount(ctx, senderMo return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromModuleToAccount", reflect.TypeOf((*MockBankKeeper)(nil).SendCoinsFromModuleToAccount), ctx, senderModule, recipientAddr, amt) } +// SendCoinsFromModuleToAccountVirtual mocks base method. +func (m *MockBankKeeper) SendCoinsFromModuleToAccountVirtual(ctx context.Context, senderModule string, recipientAddr types.AccAddress, amt types.Coins) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SendCoinsFromModuleToAccountVirtual", ctx, senderModule, recipientAddr, amt) + ret0, _ := ret[0].(error) + return ret0 +} + +// SendCoinsFromModuleToAccountVirtual indicates an expected call of SendCoinsFromModuleToAccountVirtual. +func (mr *MockBankKeeperMockRecorder) SendCoinsFromModuleToAccountVirtual(ctx, senderModule, recipientAddr, amt any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromModuleToAccountVirtual", reflect.TypeOf((*MockBankKeeper)(nil).SendCoinsFromModuleToAccountVirtual), ctx, senderModule, recipientAddr, amt) +} + // SetDenomMetaData mocks base method. func (m *MockBankKeeper) SetDenomMetaData(ctx context.Context, denomMetaData types1.Metadata) { m.ctrl.T.Helper() @@ -424,6 +481,20 @@ func (mr *MockBankKeeperMockRecorder) SpendableCoin(ctx, addr, denom any) *gomoc return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SpendableCoin", reflect.TypeOf((*MockBankKeeper)(nil).SpendableCoin), ctx, addr, denom) } +// UncheckedSetBalance mocks base method. +func (m *MockBankKeeper) UncheckedSetBalance(ctx context.Context, addr types.AccAddress, amt types.Coin) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UncheckedSetBalance", ctx, addr, amt) + ret0, _ := ret[0].(error) + return ret0 +} + +// UncheckedSetBalance indicates an expected call of UncheckedSetBalance. +func (mr *MockBankKeeperMockRecorder) UncheckedSetBalance(ctx, addr, amt any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UncheckedSetBalance", reflect.TypeOf((*MockBankKeeper)(nil).UncheckedSetBalance), ctx, addr, amt) +} + // MockStakingKeeper is a mock of StakingKeeper interface. type MockStakingKeeper struct { ctrl *gomock.Controller @@ -448,6 +519,21 @@ func (m *MockStakingKeeper) EXPECT() *MockStakingKeeperMockRecorder { return m.recorder } +// BondDenom mocks base method. +func (m *MockStakingKeeper) BondDenom(ctx context.Context) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BondDenom", ctx) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// BondDenom indicates an expected call of BondDenom. +func (mr *MockStakingKeeperMockRecorder) BondDenom(ctx any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BondDenom", reflect.TypeOf((*MockStakingKeeper)(nil).BondDenom), ctx) +} + // GetHistoricalInfo mocks base method. func (m *MockStakingKeeper) GetHistoricalInfo(ctx context.Context, height int64) (types2.HistoricalInfo, error) { m.ctrl.T.Helper() @@ -623,7 +709,7 @@ func (m *MockEvmHooks) EXPECT() *MockEvmHooksMockRecorder { } // PostTxProcessing mocks base method. -func (m *MockEvmHooks) PostTxProcessing(ctx types.Context, sender common.Address, msg core.Message, receipt *types4.Receipt) error { +func (m *MockEvmHooks) PostTxProcessing(ctx types.Context, sender common.Address, msg core.Message, receipt *types5.Receipt) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "PostTxProcessing", ctx, sender, msg, receipt) ret0, _ := ret[0].(error) @@ -660,18 +746,18 @@ func (m *MockBankWrapper) EXPECT() *MockBankWrapperMockRecorder { return m.recorder } -// BurnAmountFromAccount mocks base method. -func (m *MockBankWrapper) BurnAmountFromAccount(ctx context.Context, account types.AccAddress, amt *big.Int) error { +// BlockedAddr mocks base method. +func (m *MockBankWrapper) BlockedAddr(addr types.AccAddress) bool { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "BurnAmountFromAccount", ctx, account, amt) - ret0, _ := ret[0].(error) + ret := m.ctrl.Call(m, "BlockedAddr", addr) + ret0, _ := ret[0].(bool) return ret0 } -// BurnAmountFromAccount indicates an expected call of BurnAmountFromAccount. -func (mr *MockBankWrapperMockRecorder) BurnAmountFromAccount(ctx, account, amt any) *gomock.Call { +// BlockedAddr indicates an expected call of BlockedAddr. +func (mr *MockBankWrapperMockRecorder) BlockedAddr(addr any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BurnAmountFromAccount", reflect.TypeOf((*MockBankWrapper)(nil).BurnAmountFromAccount), ctx, account, amt) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BlockedAddr", reflect.TypeOf((*MockBankWrapper)(nil).BlockedAddr), addr) } // BurnCoins mocks base method. @@ -774,18 +860,18 @@ func (mr *MockBankWrapperMockRecorder) IterateTotalSupply(ctx, cb any) *gomock.C return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IterateTotalSupply", reflect.TypeOf((*MockBankWrapper)(nil).IterateTotalSupply), ctx, cb) } -// MintAmountToAccount mocks base method. -func (m *MockBankWrapper) MintAmountToAccount(ctx context.Context, recipientAddr types.AccAddress, amt *big.Int) error { +// LockedCoins mocks base method. +func (m *MockBankWrapper) LockedCoins(ctx context.Context, addr types.AccAddress) types.Coins { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "MintAmountToAccount", ctx, recipientAddr, amt) - ret0, _ := ret[0].(error) + ret := m.ctrl.Call(m, "LockedCoins", ctx, addr) + ret0, _ := ret[0].(types.Coins) return ret0 } -// MintAmountToAccount indicates an expected call of MintAmountToAccount. -func (mr *MockBankWrapperMockRecorder) MintAmountToAccount(ctx, recipientAddr, amt any) *gomock.Call { +// LockedCoins indicates an expected call of LockedCoins. +func (mr *MockBankWrapperMockRecorder) LockedCoins(ctx, addr any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MintAmountToAccount", reflect.TypeOf((*MockBankWrapper)(nil).MintAmountToAccount), ctx, recipientAddr, amt) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LockedCoins", reflect.TypeOf((*MockBankWrapper)(nil).LockedCoins), ctx, addr) } // MintCoins mocks base method. @@ -830,6 +916,20 @@ func (mr *MockBankWrapperMockRecorder) SendCoinsFromAccountToModule(ctx, senderA return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromAccountToModule", reflect.TypeOf((*MockBankWrapper)(nil).SendCoinsFromAccountToModule), ctx, senderAddr, recipientModule, amt) } +// SendCoinsFromAccountToModuleVirtual mocks base method. +func (m *MockBankWrapper) SendCoinsFromAccountToModuleVirtual(ctx context.Context, senderAddr types.AccAddress, recipientModule string, amt types.Coins) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SendCoinsFromAccountToModuleVirtual", ctx, senderAddr, recipientModule, amt) + ret0, _ := ret[0].(error) + return ret0 +} + +// SendCoinsFromAccountToModuleVirtual indicates an expected call of SendCoinsFromAccountToModuleVirtual. +func (mr *MockBankWrapperMockRecorder) SendCoinsFromAccountToModuleVirtual(ctx, senderAddr, recipientModule, amt any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromAccountToModuleVirtual", reflect.TypeOf((*MockBankWrapper)(nil).SendCoinsFromAccountToModuleVirtual), ctx, senderAddr, recipientModule, amt) +} + // SendCoinsFromModuleToAccount mocks base method. func (m *MockBankWrapper) SendCoinsFromModuleToAccount(ctx context.Context, senderModule string, recipientAddr types.AccAddress, amt types.Coins) error { m.ctrl.T.Helper() @@ -844,6 +944,34 @@ func (mr *MockBankWrapperMockRecorder) SendCoinsFromModuleToAccount(ctx, senderM return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromModuleToAccount", reflect.TypeOf((*MockBankWrapper)(nil).SendCoinsFromModuleToAccount), ctx, senderModule, recipientAddr, amt) } +// SendCoinsFromModuleToAccountVirtual mocks base method. +func (m *MockBankWrapper) SendCoinsFromModuleToAccountVirtual(ctx context.Context, senderModule string, recipientAddr types.AccAddress, amt types.Coins) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SendCoinsFromModuleToAccountVirtual", ctx, senderModule, recipientAddr, amt) + ret0, _ := ret[0].(error) + return ret0 +} + +// SendCoinsFromModuleToAccountVirtual indicates an expected call of SendCoinsFromModuleToAccountVirtual. +func (mr *MockBankWrapperMockRecorder) SendCoinsFromModuleToAccountVirtual(ctx, senderModule, recipientAddr, amt any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromModuleToAccountVirtual", reflect.TypeOf((*MockBankWrapper)(nil).SendCoinsFromModuleToAccountVirtual), ctx, senderModule, recipientAddr, amt) +} + +// SetBalance mocks base method. +func (m *MockBankWrapper) SetBalance(ctx context.Context, account types.AccAddress, amt *big.Int) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SetBalance", ctx, account, amt) + ret0, _ := ret[0].(error) + return ret0 +} + +// SetBalance indicates an expected call of SetBalance. +func (mr *MockBankWrapperMockRecorder) SetBalance(ctx, account, amt any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetBalance", reflect.TypeOf((*MockBankWrapper)(nil).SetBalance), ctx, account, amt) +} + // SetDenomMetaData mocks base method. func (m *MockBankWrapper) SetDenomMetaData(ctx context.Context, denomMetaData types1.Metadata) { m.ctrl.T.Helper() @@ -869,3 +997,55 @@ func (mr *MockBankWrapperMockRecorder) SpendableCoin(ctx, addr, denom any) *gomo mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SpendableCoin", reflect.TypeOf((*MockBankWrapper)(nil).SpendableCoin), ctx, addr, denom) } + +// UncheckedSetBalance mocks base method. +func (m *MockBankWrapper) UncheckedSetBalance(ctx context.Context, addr types.AccAddress, amt types.Coin) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UncheckedSetBalance", ctx, addr, amt) + ret0, _ := ret[0].(error) + return ret0 +} + +// UncheckedSetBalance indicates an expected call of UncheckedSetBalance. +func (mr *MockBankWrapperMockRecorder) UncheckedSetBalance(ctx, addr, amt any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UncheckedSetBalance", reflect.TypeOf((*MockBankWrapper)(nil).UncheckedSetBalance), ctx, addr, amt) +} + +// MockVMKeeper is a mock of VMKeeper interface. +type MockVMKeeper struct { + ctrl *gomock.Controller + recorder *MockVMKeeperMockRecorder + isgomock struct{} +} + +// MockVMKeeperMockRecorder is the mock recorder for MockVMKeeper. +type MockVMKeeperMockRecorder struct { + mock *MockVMKeeper +} + +// NewMockVMKeeper creates a new mock instance. +func NewMockVMKeeper(ctrl *gomock.Controller) *MockVMKeeper { + mock := &MockVMKeeper{ctrl: ctrl} + mock.recorder = &MockVMKeeperMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockVMKeeper) EXPECT() *MockVMKeeperMockRecorder { + return m.recorder +} + +// GetEvmCoinInfo mocks base method. +func (m *MockVMKeeper) GetEvmCoinInfo(ctx types.Context) types4.EvmCoinInfo { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEvmCoinInfo", ctx) + ret0, _ := ret[0].(types4.EvmCoinInfo) + return ret0 +} + +// GetEvmCoinInfo indicates an expected call of GetEvmCoinInfo. +func (mr *MockVMKeeperMockRecorder) GetEvmCoinInfo(ctx any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEvmCoinInfo", reflect.TypeOf((*MockVMKeeper)(nil).GetEvmCoinInfo), ctx) +}