release: v0.20-rc3 changelog (#1517)
* deps(sdk): bump to v0.46.4 (#1423) * deps(sdk): bump to v0.46.4 * deps(sdk): add IAVLDisableFastNode flag with false default * imp: reduce integration test block time to 2s (#1428) * build(deps): bump github.com/onsi/gomega from 1.23.0 to 1.24.0 (#1429) Bumps [github.com/onsi/gomega](https://github.com/onsi/gomega) from 1.23.0 to 1.24.0. - [Release notes](https://github.com/onsi/gomega/releases) - [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/gomega/compare/v1.23.0...v1.24.0) --- updated-dependencies: - dependency-name: github.com/onsi/gomega dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix(rpc): different result from `eth_getProof` comparing with Ethereum (#1431) * align with eth_getProof for more info, see https://eips.ethereum.org/EIPS/eip-1186 * add GetHexProofs * add change doc * keep default res * fix lint * add e2e test * Apply suggestions from code review * fix lint * nix run -f ./nix gomod2nix * Refactor EIP-712 signature verification (#1397) * [WIP] EIP-712 Signature Refactor * Debug and add ante tests * Add tests for failure cases * Add changelog entry * Code cleanup * Add tests for MsgDelegate and MsgWithdrawDelegationReward * Update ethereum/eip712/encoding.go Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> * Update ethereum/eip712/encoding.go Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> * Update ethereum/eip712/encoding.go Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> * Update ethereum/eip712/encoding.go Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> * Update ethereum/eip712/encoding.go Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> * Update ethereum/eip712/encoding.go Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> * Code cleanup * Update ethereum/eip712/encoding.go Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> * Minor codefix * Update ethereum/eip712/encoding.go * Minor code revision updates * Refactor EIP712 unit tests to use test suite * Address import cycle and implement minor refactors * Fix lint issues * Add EIP712 unit suite test function * Update ethereum/eip712/encoding.go Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> * Update ethereum/eip712/encoding.go Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> * Update ethereum/eip712/encoding.go Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> * Add minor refactors; increase test coverage * Correct ante_test for change in payload * Add single-signer util and tests * Update ethereum/eip712/encoding.go * Update ethereum/eip712/encoding.go * fix build Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> Co-authored-by: Freddy Caceres <facs95@gmail.com> * fix: build test on mac by updating to python3.10 (#1437) * build(deps): bump loader-utils from 1.4.0 to 1.4.1 in /tests/solidity (#1445) Bumps [loader-utils](https://github.com/webpack/loader-utils) from 1.4.0 to 1.4.1. - [Release notes](https://github.com/webpack/loader-utils/releases) - [Changelog](https://github.com/webpack/loader-utils/blob/v1.4.1/CHANGELOG.md) - [Commits](https://github.com/webpack/loader-utils/compare/v1.4.0...v1.4.1) --- updated-dependencies: - dependency-name: loader-utils dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * imp(evm): improve performance of EstimateGas (#1444) * imp(evm): improve performance of EstimateGas * changelog * fix(rpc): decode `finalized` block number (#1442) * fix(rpc): decode 'finalized' block number * changelog Co-authored-by: Freddy Caceres <facs95@gmail.com> * build(deps): bump github.com/onsi/gomega from 1.24.0 to 1.24.1 (#1449) Bumps [github.com/onsi/gomega](https://github.com/onsi/gomega) from 1.24.0 to 1.24.1. - [Release notes](https://github.com/onsi/gomega/releases) - [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/gomega/compare/v1.24.0...v1.24.1) --- updated-dependencies: - dependency-name: github.com/onsi/gomega dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump github.com/spf13/viper from 1.13.0 to 1.14.0 (#1439) Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.13.0 to 1.14.0. - [Release notes](https://github.com/spf13/viper/releases) - [Commits](https://github.com/spf13/viper/compare/v1.13.0...v1.14.0) --- updated-dependencies: - dependency-name: github.com/spf13/viper dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: 4rgon4ut <59182467+4rgon4ut@users.noreply.github.com> Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> * fix: unstable tx_priority test (#1440) * fix unstable tx_priority test * Update tests/integration_tests/test_priority.py Co-authored-by: yihuang <huang@crypto.com> * Update tests/integration_tests/test_priority.py Co-authored-by: yihuang <huang@crypto.com> Co-authored-by: yihuang <huang@crypto.com> Co-authored-by: Adi Saravanan <59209660+adisaran64@users.noreply.github.com> Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> * build(deps): bump github.com/cosmos/ibc-go/v5 from 5.0.1 to 5.1.0 (#1450) Bumps [github.com/cosmos/ibc-go/v5](https://github.com/cosmos/ibc-go) from 5.0.1 to 5.1.0. - [Release notes](https://github.com/cosmos/ibc-go/releases) - [Changelog](https://github.com/cosmos/ibc-go/blob/v5.1.0/CHANGELOG.md) - [Commits](https://github.com/cosmos/ibc-go/compare/v5.0.1...v5.1.0) --- updated-dependencies: - dependency-name: github.com/cosmos/ibc-go/v5 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump golangci/golangci-lint-action from 3.3.0 to 3.3.1 (#1454) Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 3.3.0 to 3.3.1. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/v3.3.0...v3.3.1) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * refactor(all): refactor errors import to use cosmossdk.io (#1456) * refactor (errors) refactor errors import to use cosmossdk.io instead of cosmos-sdk/types/errors * refactor (errors) refactor errors import in ethsecp256k1 file * refactor (errors) add changes to changelog * build(deps): bump alpine from 3.16.2 to 3.16.3 (#1453) Bumps alpine from 3.16.2 to 3.16.3. --- updated-dependencies: - dependency-name: alpine dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Empty KV gas config (#1460) * update sdk version * setup empty gas config * fix lint * fix integration tests * add Ante unit test * update changelog * test: remove unused integration tests (#1462) * fix: remove e2e github action (#1463) * remove unused tests * imp: remove e2e github action * build(deps): bump loader-utils from 1.4.1 to 1.4.2 in /tests/solidity (#1464) Bumps [loader-utils](https://github.com/webpack/loader-utils) from 1.4.1 to 1.4.2. - [Release notes](https://github.com/webpack/loader-utils/releases) - [Changelog](https://github.com/webpack/loader-utils/blob/v1.4.2/CHANGELOG.md) - [Commits](https://github.com/webpack/loader-utils/compare/v1.4.1...v1.4.2) --- updated-dependencies: - dependency-name: loader-utils dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore (deps): Update geth version to v1.10.25 (#1413) * build(deps): bump github.com/ethereum/go-ethereum Bumps [github.com/ethereum/go-ethereum](https://github.com/ethereum/go-ethereum) from 1.10.19 to 1.10.25. - [Release notes](https://github.com/ethereum/go-ethereum/releases) - [Commits](https://github.com/ethereum/go-ethereum/compare/v1.10.19...v1.10.25) --- updated-dependencies: - dependency-name: github.com/ethereum/go-ethereum dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * wip geth update * fix geth init flag order * add chainId to getTransaction. fix types comparison. update expected values on tests * wip add tracer config * tracers test * update tests * update to v1.10.25 * fix linter python * ignore error * fix lint * additional changes from diff * fix issues * solve lint issues * fix tests * fix flake * wrap types comparison in integration tests * fix integration tests * fix flake * update changelog Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> Co-authored-by: Freddy Caceres <facs95@gmail.com> * Add EIP-712 encoding support type for any array (#1430) * Add EIP-712 encoding support type for any array * Refactor implementation + add tests * Refactor unpacking implementation; refactor test case * Fix lint issue * Add MsgExec test case * Update comment for clarity * Add changelog entry * Refactor `sdkerrors` to `errorsmod` Co-authored-by: Freddy Caceres <facs95@gmail.com> * fix: extend geth config on integration tests (#1467) * changing git config and adding tests * removing print statements * remove unneccessary imports * fix flake * remove geth setup test Co-authored-by: Freddy Caceres <facs95@gmail.com> * tests: Add unit tests for rpc client endpoints (#1409) * test: add preliminary unit tests and additional mocks for chain_info, account_info and filters * tests: added additional mocked client calls * tests: bumped coverage of call_tx to 56% and chain_info to 77% * tests: bumped call_tx coverage to 70.2% and added additional mock client calls * tests: tx_info preliminary tests added for debugging. * tests: added test coverage for sign_tx and additional mocks * tests: tx_info test coverage bumped to 60.3% * test: coverage for tracing_tests now at 72% * tests: added fee makert query client mocks and bumped chain_info to 87.6% coverage. * tests: failing Cosmos auth module account query. * tests: added FeeMarket Params mock to call_tx_test * cleanup some unused code * tests: added helper function to test suite for signing a Tx and bumped coverage of tx_info to 71.2% * test: commented GetAccount error case and bumped chain_info to 90.3% coverage * test: cleanup of tests in node_info, sign_tx and account_info * Clean up print Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> * Apply suggestions from code review * fix import issues Co-authored-by: Vladislav Varadinov <vlad@evmos.org> Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> Co-authored-by: Freddy Caceres <facs95@gmail.com> * Refactor to omit empty optionals from EIP-712 type generation (#1459) * Refactor to omit empty values from type creation; add test for v1.vote * Add test for createValidator with optional fields left blank * Add changelog entry * Update changelog entry Co-authored-by: Freddy Caceres <facs95@gmail.com> * fix: protogen scripts were not correctly implemented (#1466) * Delete local copy of third party proto files * Update protocgen script and buf yaml files to mirror cosmos-sdk * Update makefile commands for proto-gen and proto-swagger-gen to correctly use docker * Commit changed .pb.go files after updating the protogen scripts * Adjust grep in proto-tools-installer script to look for correct gogoproto replacement * address reviews - remove unnecessary ignore in buf.yaml and cosmos-sdk download in the protocgen script * remove proto-update-deps from makefile as we don't store local copies of third party protofiles anymore * Add changelog entry * Update protoc-swagger-gen.sh * Remove third party queries from swagger-ui config (for now) * fix integrations tests * fix dead changelog links (markdown-link-check) Co-authored-by: Freddy Caceres <facs95@gmail.com> Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> * added gas consumption test (#1474) * build(deps): bump github.com/cosmos/cosmos-proto (#1475) Bumps [github.com/cosmos/cosmos-proto](https://github.com/cosmos/cosmos-proto) from 1.0.0-alpha7 to 1.0.0-alpha8. - [Release notes](https://github.com/cosmos/cosmos-proto/releases) - [Commits](https://github.com/cosmos/cosmos-proto/compare/v1.0.0-alpha7...v1.0.0-alpha8) --- updated-dependencies: - dependency-name: github.com/cosmos/cosmos-proto dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix: chain-id in grpc query is not initialized without abci event (#1405) * fix: chain-id in grpc query is not initialized without abci event Closes: #1404 Solution: - pass the chain-id from caller. * Update CHANGELOG.md * only override if input is not empty * add comment to chain id * pass chain-id to state transition * Update x/evm/keeper/grpc_query.go * Apply suggestions from code review * fix golang lint * update gomod2nix.toml * fix unit tests * update gomod2nix * api breaking changelog * add unit tests, and fix TraceBlock by the way * Update CHANGELOG.md * test --grpc-only mode in integration tests * remove tmp var * Update tests/integration_tests/test_grpc_only.py * Update x/evm/keeper/grpc_query_test.go Co-authored-by: mmsqe <tqd0800210105@gmail.com> * fix linters * fix nil pointer in tests * fix conflicts * fix conflicts * fixes * fix lint * fix unit test Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> Co-authored-by: mmsqe <tqd0800210105@gmail.com> Co-authored-by: Freddy Caceres <facs95@gmail.com> * fix(evm): Simplify Gas Math (#1452) * fix math * changelog * imp(ante): refactor `AnteHandler` (#1455) * fix(ante): block gas check * refactor * rename * use gas wanted * remove consume gas logic on ante handler * comment * c++ * move min gas price * comment * Update app/ante/eth.go Co-authored-by: Vladislav Varadinov <vladislav.varadinov@gmail.com> * fix build * fix integration test script Co-authored-by: Vladislav Varadinov <vladislav.varadinov@gmail.com> Co-authored-by: Freddy Caceres <facs95@gmail.com> * tests: add additional gas consumption tests (#1477) * split existing gas test * added contract call test * fix flake issues, update gomod2nix * isort imports * add stateful contract calls * chore: update proto make commands (#1471) * Update proto make commands to use cosmos docker image and add notes for possible problems * Apply make proto-all with new docker container * Remove stale DOCKER_BUF variable * Revert to using the tendermintdev/sdk-proto-gen docker image * remove '@' in proto-lint and proto-check-breaking for consistency with other commands * Remove unnecessary go get from protocgen.sh (only works after adding --network host to docker run) * Add --network host to docker run for compatibility on linux * use cosmos/proto-builder docker image for proto-format because clang-format is not installed on tendermintdev/sdk-proto-gen * update swagger docs after recent additions to evm.proto in #1413 Co-authored-by: Tomas Guerra <54514587+GAtom22@users.noreply.github.com> * Remove unbound labels from added custom tendermint metrics (#1434) * Remove unbound labels from added custom tendermint metrics * Add entry to changelog * deps: bump SDK to v0.46.6 (#1486) * deps: bump SDK to v0.46.6 * changelog * Update CHANGELOG.md Co-authored-by: Tomas Guerra <54514587+GAtom22@users.noreply.github.com> Co-authored-by: Tomas Guerra <54514587+GAtom22@users.noreply.github.com> * fear(eip712): Add EIP-712 encoding for multiple messages of the same type (#1483) * Add EIP-712 encoding for multiple messages of the same type * Fix Protobuf encoding bug * Add ante tests * Refactor naming and minor implementation details * Test empty transaction coverage * Address revisions for code clarity * Move aminoMessage type definition * fix: enable `fixIssue172` flag for non-deterministic keyring test (#1447) * enable fixIssue172 flag for test for more info, https://github.com/btcsuite/btcutil/pull/182/files * fix import * Apply suggestions from code review * Apply suggestions from code review Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> Co-authored-by: Adi Saravanan <59209660+adisaran64@users.noreply.github.com> Co-authored-by: Freddy Caceres <facs95@gmail.com> * fix(tests): Delete inconsistent test (#1481) * Delete inconsistent test * delete test * build(deps): bump alpine from 3.16.3 to 3.17.0 (#1492) Bumps alpine from 3.16.3 to 3.17.0. --- updated-dependencies: - dependency-name: alpine dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump google.golang.org/grpc from 1.50.1 to 1.51.0 (#1490) Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.50.1 to 1.51.0. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.50.1...v1.51.0) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump github.com/onsi/ginkgo/v2 from 2.5.0 to 2.5.1 (#1489) Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.5.0 to 2.5.1. - [Release notes](https://github.com/onsi/ginkgo/releases) - [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/ginkgo/compare/v2.5.0...v2.5.1) --- updated-dependencies: - dependency-name: github.com/onsi/ginkgo/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore: refactor imports naming for clarity (#1491) * chore: refactor imports naming for clarity * Merge main and fix conflicts * fix: align empty account result for old blocks as ethereum (#1484) * align result account as ethereum * add test_get_transaction_count * add change doc * sync gomod2nix * Apply suggestions from code review * crosscheck with ws & geth * sync gomod2nix * Update rpc/backend/utils.go * use session provider Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> * imp(ante): refactor AnteHandler (#1479) * imp(ante): refactor AnteHandler * fix test * test * Adjust deprecated sdkerrors import (#1493) * refactor test files * Apply suggestions from code review Co-authored-by: 4rgon4ut <59182467+4rgon4ut@users.noreply.github.com> * lint * prioritization comment * fix test Co-authored-by: MalteHerrmann <42640438+MalteHerrmann@users.noreply.github.com> Co-authored-by: 4rgon4ut <59182467+4rgon4ut@users.noreply.github.com> * chore: Update linter and protogen configuration (#1478) * add protolint yaml * Update .protolint.yml with Evmos settings * Add super-linter.yml for GH action * Copy .markdownlint.yml settings from Evmos * Sort proto imports * address protolint error in all Protobuf files * update Makefile to mirror Proto commands for Evmos * remove unnecessary go get command in protocgen.sh when using cosmos docker image * copy .clang-format from Evmos repo * apply make proto-format * Execute make proto-all after changes to config are complete * address last linter comment * fix(server): telemetry setup (#1497) * fix(server): telemetry setup * more fixes * fix * changelog * update standalone process * chore(evm) - Delete deprecated store migrations (#1498) * (fix): Delete deprecated migrations * Update x/evm/module.go Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> * fix(evm): Added Cancun and Shanghai blocks to ChainConfig (#1499) * (refactor): Added Cancun and Shanghai blocks to ChainConfig * (tests): Added test for invalid Shanghai and Cancun block * (fix): ran proto linter * Applied changes from code review * Added CHANGELOG entry Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> * chore(app): add store listener to Ethermint app (#1501) * add store listener to Ethermint app * add changelog entry * build(deps): bump cosmossdk.io/math from 1.0.0-beta.3 to 1.0.0-beta.4 (#1502) Bumps [cosmossdk.io/math](https://github.com/cosmos/cosmos-sdk) from 1.0.0-beta.3 to 1.0.0-beta.4. - [Release notes](https://github.com/cosmos/cosmos-sdk/releases) - [Changelog](https://github.com/cosmos/cosmos-sdk/blob/main/CHANGELOG.md) - [Commits](https://github.com/cosmos/cosmos-sdk/compare/math/v1.0.0-beta.3...math/v1.0.0-beta.4) --- updated-dependencies: - dependency-name: cosmossdk.io/math dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix(app): register node service (#1505) * fix(app): register node service * changelog * fix(cmd): add missing GetAuxToFeeCommand (#1504) Co-authored-by: MalteHerrmann <42640438+MalteHerrmann@users.noreply.github.com> * chore(feemarket): Delete deprecated migration logic (#1508) * (refactor): Remove old migration code * (fix): Lint and add CHANGELOG entry * Remove simulation checks (#1507) * Add cli rollback command it's useful in app-hash mismatch situation. * Update CHANGELOG.md * (refactor): removed old sim tests logic * (fix): removed tests from CI * (fix): fix test.yml * (fix): format and lint * (fix): fix linter issue * (fix): fix linter issues v2 * (fix): linter * (fix): removed sim-test references * Applied changes from code review Co-authored-by: HuangYi <huang@crypto.com> * chore: verify fees refactor (#1496) * chore: verify fees refactor * adjust call structure in rest of repo after splitting up DeductTxCostsFromUserBalance * adjust test logic after splitting DeductTxCostsFromUserBalance up * remove outdated TODO * address PR comments - remove import name for evm keeper * remove misleading comment * address review comments - only handover boolean instead of context * remove TODO Co-authored-by: MalteHerrmann <malteherrmann.mail@web.de> Co-authored-by: MalteHerrmann <42640438+MalteHerrmann@users.noreply.github.com> * json-rpc(filters) fix block hash on newBlock filter (#1503) * tests(filters) add block hash check on newBlock filter * tests(filters) fix linting errors * fix(filters): fix newBlock filter response * fix(filters): add changes on CHANGELOG file * fix(ci): add gitleaks config (#1513) * fix(ci): add gitleaks config to ignore init.sh * make ci lint init.sh Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> * tests(filters): add/improve integration tests for JSON-RPC methods (#1480) * tests(filters) add block hash check on newBlock filter * tests(filters) add getLogs test cases * tests(filters) add eth_newFilter multiple filters test cases * tests(filters) add eth_newFilter and eth_eth_uninstallFilter test case * tests(filters) fix linting errors * tests(filters) fix linting error on imports * tests(filters) add test case: register filter before contract deploy * tests(filters) refactor logs topics assertion * tests(filters) add topics filter test cases * tests(filters) fix linting errors * tests(filters) remove unnecessary package.json file * tests(filters) update based on PR comments * tests(filters) separate getNewBlocks failing test to a separate PR * tests(filters) add retry on send_tx to avoid Timeout error * tests(filters) add logs by topic and block range test case * update gomod2nix * tests(filters) remove test elapsed time log Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> Co-authored-by: Freddy Caceres <facs95@gmail.com> * add dragonberry update changelog entry again Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Daniel Burckhardt <daniel.m.burckhardt@gmail.com> Co-authored-by: Freddy Caceres <facs95@gmail.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: mmsqe <mavis@crypto.com> Co-authored-by: Austin Chandra <austinchandra@berkeley.edu> Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> Co-authored-by: 4rgon4ut <59182467+4rgon4ut@users.noreply.github.com> Co-authored-by: yihuang <huang@crypto.com> Co-authored-by: Adi Saravanan <59209660+adisaran64@users.noreply.github.com> Co-authored-by: Tomas Guerra <54514587+GAtom22@users.noreply.github.com> Co-authored-by: Ramiro Carlucho <ramirocarlucho@gmail.com> Co-authored-by: Vladislav Varadinov <vladislav.varadinov@gmail.com> Co-authored-by: Vladislav Varadinov <vlad@evmos.org> Co-authored-by: mmsqe <tqd0800210105@gmail.com> Co-authored-by: Devon Bear <itsdevbear@berachain.com> Co-authored-by: v-homsi <110708931+v-homsi@users.noreply.github.com>
This commit is contained in:
parent
4b676b603f
commit
55b292f179
117
.clang-format
117
.clang-format
@ -1,115 +1,6 @@
|
||||
---
|
||||
Language: Proto
|
||||
# BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -2
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: true
|
||||
AlignConsecutiveDeclarations: true
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: true
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: false
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 120
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||
Priority: 2
|
||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||
Priority: 3
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IndentCaseLabels: false
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 2
|
||||
IndentWrappedFunctionNames: false
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Right
|
||||
RawStringFormats:
|
||||
- Delimiters:
|
||||
- pb
|
||||
Language: TextProto
|
||||
BasedOnStyle: google
|
||||
ReflowComments: true
|
||||
SortIncludes: true
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp11
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
Language: Proto
|
||||
BasedOnStyle: google
|
||||
ColumnLimit: 120
|
||||
IndentWidth: 2
|
||||
...
|
||||
|
2
.github/workflows/lint.yml
vendored
2
.github/workflows/lint.yml
vendored
@ -25,7 +25,7 @@ jobs:
|
||||
**/**.go
|
||||
go.mod
|
||||
go.sum
|
||||
- uses: golangci/golangci-lint-action@v3.3.0
|
||||
- uses: golangci/golangci-lint-action@v3.3.1
|
||||
with:
|
||||
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
|
||||
version: latest
|
||||
|
38
.github/workflows/super-linter.yml
vendored
Normal file
38
.github/workflows/super-linter.yml
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
# This workflow executes several linters on changed files based on languages used in your code base whenever
|
||||
# you push a code or open a pull request.
|
||||
#
|
||||
# You can adjust the behavior by modifying this file.
|
||||
# For more information, see:
|
||||
# https://github.com/github/super-linter
|
||||
---
|
||||
name: Lint Code Base
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
pull_request:
|
||||
branches: ["main"]
|
||||
jobs:
|
||||
run-lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
# Full git history is needed to get a proper list of changed files within `super-linter`
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Lint Code Base
|
||||
uses: github/super-linter@v4
|
||||
env:
|
||||
LINTER_RULES_PATH: /
|
||||
YAML_CONFIG_FILE: .yamllint
|
||||
VALIDATE_ALL_CODEBASE: false
|
||||
MARKDOWN_CONFIG_FILE: .markdownlint.yml
|
||||
PROTOBUF_CONFIG_FILE: .protolint.yml
|
||||
VALIDATE_NATURAL_LANGUAGE: false
|
||||
VALIDATE_OPENAPI: false
|
||||
VALIDATE_JSCPD: false
|
||||
VALIDATE_GO: false
|
||||
DEFAULT_BRANCH: "main"
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
103
.github/workflows/test.yml
vendored
103
.github/workflows/test.yml
vendored
@ -82,27 +82,6 @@ jobs:
|
||||
make test-rpc
|
||||
if: env.GIT_DIFF
|
||||
|
||||
test-e2e:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.19
|
||||
check-latest: true
|
||||
- uses: actions/checkout@v3
|
||||
- uses: technote-space/get-diff-action@v6.1.1
|
||||
with:
|
||||
PATTERNS: |
|
||||
**/**.sol
|
||||
**/**.go
|
||||
go.mod
|
||||
go.sum
|
||||
- name: Test e2e
|
||||
run: |
|
||||
make test-integration
|
||||
if: env.GIT_DIFF
|
||||
|
||||
integration_tests:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@ -148,84 +127,4 @@ jobs:
|
||||
name: ethermint
|
||||
signingKey: "${{ secrets.CACHIX_SIGNING_KEY }}"
|
||||
- name: 'instantiate integration test env'
|
||||
run: nix-store -r $(nix-instantiate tests/integration_tests/shell.nix)
|
||||
|
||||
test-sim-nondeterminism:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.19
|
||||
check-latest: true
|
||||
- uses: actions/checkout@v3
|
||||
- uses: technote-space/get-diff-action@v6.1.1
|
||||
with:
|
||||
PATTERNS: |
|
||||
**/**.go
|
||||
go.mod
|
||||
go.sum
|
||||
- name: Test simulation nondeterminism
|
||||
run: |
|
||||
make test-sim-nondeterminism
|
||||
if: env.GIT_DIFF
|
||||
|
||||
test-sim-random-genesis-fast:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.19
|
||||
check-latest: true
|
||||
- uses: actions/checkout@v3
|
||||
- uses: technote-space/get-diff-action@v6.1.1
|
||||
with:
|
||||
PATTERNS: |
|
||||
**/**.go
|
||||
go.mod
|
||||
go.sum
|
||||
- name: Test simulation with random genesis
|
||||
run: |
|
||||
make test-sim-random-genesis-fast
|
||||
if: env.GIT_DIFF
|
||||
|
||||
test-sim-import-export:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.19
|
||||
check-latest: true
|
||||
- uses: actions/checkout@v3
|
||||
- uses: technote-space/get-diff-action@v6.1.1
|
||||
with:
|
||||
PATTERNS: |
|
||||
**/**.go
|
||||
go.mod
|
||||
go.sum
|
||||
- name: Simulation of import and export genesis
|
||||
run: |
|
||||
make test-sim-import-export
|
||||
if: env.GIT_DIFF
|
||||
|
||||
test-sim-after-import:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.19
|
||||
check-latest: true
|
||||
- uses: actions/checkout@v3
|
||||
- uses: technote-space/get-diff-action@v6.1.1
|
||||
with:
|
||||
PATTERNS: |
|
||||
**/**.go
|
||||
go.mod
|
||||
go.sum
|
||||
- name: Test simulation after import
|
||||
run: |
|
||||
make test-sim-after-import
|
||||
if: env.GIT_DIFF
|
||||
run: nix-store -r "$(nix-instantiate tests/integration_tests/shell.nix)"
|
||||
|
2766
.gitleaks.toml
Normal file
2766
.gitleaks.toml
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,13 +1,13 @@
|
||||
"default": true
|
||||
"MD001": false
|
||||
"MD004": false
|
||||
"MD007":
|
||||
"MD007":
|
||||
"indent": 4
|
||||
"MD013": false
|
||||
"MD024":
|
||||
"MD024":
|
||||
"siblings_only": true
|
||||
"MD025": false
|
||||
"MD026":
|
||||
"MD026":
|
||||
"punctuation": ".;:"
|
||||
"MD029": false
|
||||
"MD033": false
|
||||
@ -15,6 +15,7 @@
|
||||
"MD036": false
|
||||
"MD040": false
|
||||
"MD041": false
|
||||
"MD049":
|
||||
"MD051": false
|
||||
"MD049":
|
||||
"style": "asterisk"
|
||||
"no-hard-tabs": false
|
||||
|
174
.protolint.yml
Normal file
174
.protolint.yml
Normal file
@ -0,0 +1,174 @@
|
||||
---
|
||||
# Lint directives.
|
||||
lint:
|
||||
# # Linter files to ignore.
|
||||
# ignores:
|
||||
# - id: MESSAGE_NAMES_UPPER_CAMEL_CASE
|
||||
# files:
|
||||
# # NOTE: UNIX paths will be properly accepted by both UNIX and Windows.
|
||||
# - _example/proto/simple.proto
|
||||
# - id: ENUM_NAMES_UPPER_CAMEL_CASE
|
||||
# files:
|
||||
# - path/to/foo.proto
|
||||
|
||||
# # Linter files to walk.
|
||||
# files:
|
||||
# # The specific files to exclude.
|
||||
# exclude:
|
||||
# # NOTE: UNIX paths will be properly accepted by both UNIX and Windows.
|
||||
# - path/to/file
|
||||
|
||||
# # Linter directories to walk.
|
||||
# directories:
|
||||
# # The specific directories to exclude.
|
||||
# exclude:
|
||||
# # NOTE: UNIX paths will be properly accepted by both UNIX and Windows.
|
||||
# - path/to/dir
|
||||
|
||||
# Linter rules.
|
||||
# Run `protolint list` to see all available rules.
|
||||
rules:
|
||||
# Determines whether or not to include the default set of linters.
|
||||
no_default: true
|
||||
|
||||
# Set the default to all linters. This option works the other way around as no_default does.
|
||||
# If you want to enable this option, delete the comment out below and no_default.
|
||||
# all_default: true
|
||||
|
||||
# The specific linters to add.
|
||||
add:
|
||||
- FIELD_NAMES_LOWER_SNAKE_CASE
|
||||
- MESSAGE_NAMES_UPPER_CAMEL_CASE
|
||||
- MAX_LINE_LENGTH
|
||||
- INDENT
|
||||
# - SERVICE_NAMES_END_WITH
|
||||
- FIELD_NAMES_EXCLUDE_PREPOSITIONS
|
||||
- MESSAGE_NAMES_EXCLUDE_PREPOSITIONS
|
||||
- FILE_NAMES_LOWER_SNAKE_CASE
|
||||
- IMPORTS_SORTED
|
||||
- PACKAGE_NAME_LOWER_CASE
|
||||
- ORDER
|
||||
- MESSAGES_HAVE_COMMENT
|
||||
- SERVICES_HAVE_COMMENT
|
||||
- RPCS_HAVE_COMMENT
|
||||
- FIELDS_HAVE_COMMENT
|
||||
- PROTO3_FIELDS_AVOID_REQUIRED
|
||||
- PROTO3_GROUPS_AVOID
|
||||
# - REPEATED_FIELD_NAMES_PLURALIZED
|
||||
- ENUMS_HAVE_COMMENT
|
||||
- ENUM_FIELDS_HAVE_COMMENT
|
||||
- SYNTAX_CONSISTENT
|
||||
- RPC_NAMES_UPPER_CAMEL_CASE
|
||||
# - FILE_HAS_COMMENT
|
||||
- QUOTE_CONSISTENT
|
||||
|
||||
# # The specific linters to remove.
|
||||
# remove:
|
||||
# - RPC_NAMES_UPPER_CAMEL_CASE
|
||||
|
||||
# Linter rules option.
|
||||
rules_option:
|
||||
# MAX_LINE_LENGTH rule option.
|
||||
max_line_length:
|
||||
# Enforces a maximum line length
|
||||
max_chars: 120
|
||||
# Specifies the character count for tab characters
|
||||
tab_chars: 2
|
||||
|
||||
# INDENT rule option.
|
||||
indent:
|
||||
# Available styles are 4(4-spaces), 2(2-spaces) or tab.
|
||||
style: 2
|
||||
# Specifies if it should stop considering and inserting new lines at the appropriate positions
|
||||
# when the inner elements are on the same line. Default is false.
|
||||
not_insert_newline: true
|
||||
|
||||
# # FILE_NAMES_LOWER_SNAKE_CASE rule option.
|
||||
# file_names_lower_snake_case:
|
||||
# excludes:
|
||||
# - ../proto/invalidFileName.proto
|
||||
|
||||
# QUOTE_CONSISTENT rule option.
|
||||
quote_consistent:
|
||||
# Available quote are "double" or "single".
|
||||
quote: double
|
||||
|
||||
# ENUM_FIELD_NAMES_ZERO_VALUE_END_WITH rule option.
|
||||
enum_field_names_zero_value_end_with:
|
||||
suffix: INVALID
|
||||
|
||||
# # SERVICE_NAMES_END_WITH rule option.
|
||||
# service_names_end_with:
|
||||
# text: Service
|
||||
|
||||
# FIELD_NAMES_EXCLUDE_PREPOSITIONS rule option.
|
||||
field_names_exclude_prepositions:
|
||||
# The specific prepositions to determine if the field name includes.
|
||||
prepositions:
|
||||
- for
|
||||
- at
|
||||
- of
|
||||
# The specific keywords including prepositions to ignore. E.g. end_of_support is a term you would like to use, and skip checking.
|
||||
excludes:
|
||||
- duration_of_decay
|
||||
|
||||
# # REPEATED_FIELD_NAMES_PLURALIZED rule option.
|
||||
# ## The spec for each rules follows the implementation of https://github.com/gertd/go-pluralize.
|
||||
# ## Plus, you can refer to this rule's test code.
|
||||
# repeated_field_names_pluralized:
|
||||
# uncountable_rules:
|
||||
# - paper
|
||||
# irregular_rules:
|
||||
# Irregular: Regular
|
||||
|
||||
# MESSAGE_NAMES_EXCLUDE_PREPOSITIONS rule option.
|
||||
message_names_exclude_prepositions:
|
||||
# The specific prepositions to determine if the message name includes.
|
||||
prepositions:
|
||||
- With
|
||||
- For
|
||||
- Of
|
||||
# # The specific keywords including prepositions to ignore. E.g. EndOfSupport is a term you would like to use, and skip checking.
|
||||
# excludes:
|
||||
# - EndOfSupport
|
||||
|
||||
# # RPC_NAMES_CASE rule option.
|
||||
# rpc_names_case:
|
||||
# # The specific convention the name should conforms to.
|
||||
# ## Available conventions are "lower_camel_case", "upper_snake_case", or "lower_snake_case".
|
||||
# convention: upper_snake_case
|
||||
|
||||
# MESSAGES_HAVE_COMMENT rule option.
|
||||
messages_have_comment:
|
||||
# Comments need to begin with the name of the thing being described. default is false.
|
||||
should_follow_golang_style: true
|
||||
|
||||
# SERVICES_HAVE_COMMENT rule option.
|
||||
services_have_comment:
|
||||
# Comments need to begin with the name of the thing being described. default is false.
|
||||
should_follow_golang_style: true
|
||||
|
||||
# RPCS_HAVE_COMMENT rule option.
|
||||
rpcs_have_comment:
|
||||
# Comments need to begin with the name of the thing being described. default is false.
|
||||
should_follow_golang_style: true
|
||||
|
||||
# FIELDS_HAVE_COMMENT rule option.
|
||||
fields_have_comment:
|
||||
# Comments need to begin with the name of the thing being described. default is false.
|
||||
should_follow_golang_style: true
|
||||
|
||||
# ENUMS_HAVE_COMMENT rule option.
|
||||
enums_have_comment:
|
||||
# Comments need to begin with the name of the thing being described. default is false.
|
||||
should_follow_golang_style: true
|
||||
|
||||
# ENUM_FIELDS_HAVE_COMMENT rule option.
|
||||
enum_fields_have_comment:
|
||||
# Comments need to begin with the name of the thing being described. default is false.
|
||||
should_follow_golang_style: true
|
||||
|
||||
# # SYNTAX_CONSISTENT rule option.
|
||||
# syntax_consistent:
|
||||
# # Default is proto3.
|
||||
# version: proto2
|
39
CHANGELOG.md
39
CHANGELOG.md
@ -36,41 +36,61 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
|
||||
# Changelog
|
||||
|
||||
## [v0.20.0-rc2] - 2022-11-02
|
||||
## [v0.20.0-rc3] - 2022-11-30
|
||||
|
||||
### State Machine Breaking
|
||||
|
||||
* (deps) [#1423](https://github.com/evmos/ethermint/pull/1423) Bump Cosmos SDK to `v0.46.4`
|
||||
* (deps) [#1419](https://github.com/evmos/ethermint/pull/1419) Add ics23 patch for dragonberry and bump iavl to v0.19.4
|
||||
* (deps) [#1361](https://github.com/evmos/ethermint/pull/1361) Bump ibc-go to [`v5.0.0`](https://github.com/cosmos/ibc-go/releases/tag/v5.0.0)
|
||||
* (deps) [#1361](https://github.com/evmos/ethermint/pull/1361) Bump ibc-go to [`v5.1.0`](https://github.com/cosmos/ibc-go/releases/tag/v5.1.0)
|
||||
* (evm) [\#1272](https://github.com/evmos/ethermint/pull/1272) Implement modular interface for the EVM.
|
||||
* (deps) [#1168](https://github.com/evmos/ethermint/pull/1168) Upgrade Cosmos SDK to `v0.46`.
|
||||
* (deps) [#1168](https://github.com/evmos/ethermint/pull/1168) Upgrade Cosmos SDK to [`v0.46.6`](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.6).
|
||||
* (feemarket) [#1194](https://github.com/evmos/ethermint/pull/1194) Apply feemarket to native cosmos tx.
|
||||
* (eth) [#1346](https://github.com/evmos/ethermint/pull/1346) Added support for `sdk.Dec` and `ed25519` type on eip712.
|
||||
* (evm) [#1452](https://github.com/evmos/ethermint/pull/1452) Simplify Gas Math in `ApplyTransaction`.
|
||||
* (eth) [#1430](https://github.com/evmos/ethermint/pull/1430) Added support for array of type `Any` on eip712.
|
||||
* (ante) [1460](https://github.com/evmos/ethermint/pull/1460) Add KV Gas config on ethereum Txs.
|
||||
* (eth) [#1459](https://github.com/evmos/ethermint/pull/1459) Added support for messages with optional types omitted on eip712.
|
||||
* (geth) [#1413](https://github.com/evmos/ethermint/pull/1413) Update go-ethereum version to [`v1.10.26`](https://github.com/ethereum/go-ethereum/releases/tag/v1.10.26).
|
||||
|
||||
### API Breaking
|
||||
|
||||
* (ante) [#1214](https://github.com/evmos/ethermint/pull/1214) Set mempool priority to EVM transactions.
|
||||
* (evm) [#1405](https://github.com/evmos/ethermint/pull/1405) Add parameter `chainID` to evm keeper's `EVMConfig` method, so caller can choose to not use the cached `eip155ChainID`.
|
||||
|
||||
### Features
|
||||
|
||||
- (app) [#1501](https://github.com/evmos/ethermint/pull/1501) Set default File store listener for application from [ADR38](https://docs.cosmos.network/v0.47/architecture/adr-038-state-listening)
|
||||
|
||||
### Improvements
|
||||
|
||||
* (tests) [#1507](https://github.com/evmos/ethermint/pull/1507) Remove legacy sim tests
|
||||
* (feemarket) [#1508](https://github.com/evmos/ethermint/pull/1508) Remove old x/params migration logic
|
||||
* (evm) [#1499](https://github.com/evmos/ethermint/pull/1499) Add Shanghai and Cancun block
|
||||
* (ante) [#1455](https://github.com/evmos/ethermint/pull/1455) Refactor `AnteHandler` logic
|
||||
* (evm) [#1444](https://github.com/evmos/ethermint/pull/1444) Improve performance of `eth_estimateGas`
|
||||
* (ante) [\#1388](https://github.com/evmos/ethermint/pull/1388) Optimize AnteHandler gas consumption
|
||||
* (lint) [#1298](https://github.com/evmos/ethermint/pull/1298) 150 character line length limit, `gofumpt`, and linting
|
||||
* (feemarket) [\#1165](https://github.com/evmos/ethermint/pull/1165) Add hint in specs about different gas terminology in Cosmos and Ethereum.
|
||||
* (cli) [#1226](https://github.com/evmos/ethermint/pull/1226) Add custom app db backend flag.
|
||||
* (ante) [#1289](https://github.com/evmos/ethermint/pull/1289) Change the fallback tx priority mechanism to be based on gas price.
|
||||
* (test) [#1311](https://github.com/evmos/ethermint/pull/1311) Add integration test for the `rollback` cmd
|
||||
* (ledger) [#1277](https://github.com/evmos/ethermint/pull/1277) Add Ledger preprocessing transaction hook for EIP-712-signed Cosmos payloads.
|
||||
* (rpc) [#1296](https://github.com/evmos/ethermint/pull/1296) Add RPC Backend unit tests.
|
||||
* (rpc) [#1352](https://github.com/evmos/ethermint/pull/1352) Make the grpc queries run concurrently, don't block the consensus state machine.
|
||||
* (cli) [#1360](https://github.com/evmos/ethermint/pull/1360) Introduce a new `grpc-only` flag, such that when enabled, will start the node in a query-only mode. Note, gRPC MUST be enabled with this flag.
|
||||
* (rpc) [#1378](https://github.com/evmos/ethermint/pull/1378) Add support for EVM RPC metrics
|
||||
* (ante) [#1390](https://github.com/evmos/ethermint/pull/1390) Added multisig tx support.
|
||||
* (test) [#1396](https://github.com/evmos/ethermint/pull/1396) Increase test coverage for the EVM module `keeper`
|
||||
* (ante) [#1397](https://github.com/evmos/ethermint/pull/1397) Refactor EIP-712 signature verification to support EIP-712 multi-signing.
|
||||
* (deps) [#1416](https://github.com/evmos/ethermint/pull/1416) Bump Go version to `1.19`
|
||||
* (cmd) [\#1417](https://github.com/evmos/ethermint/pull/1417) Apply Google CLI Syntax for required and optional args.
|
||||
* (deps) [#1456](https://github.com/evmos/ethermint/pull/1456) Migrate errors-related functionality from "github.com/cosmos/cosmos-sdk/types/errors" (deprecated) to "cosmossdk.io/errors"
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* (app) [#1505](https://github.com/evmos/ethermint/pull/1505) Setup gRPC node service with the application.
|
||||
* (server) [#1497](https://github.com/evmos/ethermint/pull/1497) Fix telemetry server setup for observability
|
||||
* (rpc) [#1442](https://github.com/evmos/ethermint/pull/1442) Fix decoding of `finalized` block number.
|
||||
* (rpc) [#1179](https://github.com/evmos/ethermint/pull/1179) Fix gas used in traceTransaction response.
|
||||
* (rpc) [#1284](https://github.com/evmos/ethermint/pull/1284) Fix internal trace response upon incomplete `eth_sendTransaction` call.
|
||||
* (rpc) [#1340](https://github.com/evmos/ethermint/pull/1340) Fix error response when `eth_estimateGas` height provided is not found.
|
||||
@ -78,6 +98,13 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
* (cli) [#1362](https://github.com/evmos/ethermint/pull/1362) Fix `index-eth-tx` error when the indexer db is empty.
|
||||
* (state) [#1320](https://github.com/evmos/ethermint/pull/1320) Fix codehash check mismatch when the code has been deleted in the evm state.
|
||||
* (rpc) [#1392](https://github.com/evmos/ethermint/pull/1392) Allow fill the proposer address in json-rpc through tendermint api, and pass explicitly to grpc query handler.
|
||||
* (rpc) [#1431](https://github.com/evmos/ethermint/pull/1431) Align hex-strings proof fields in `eth_getProof` as Ethereum.
|
||||
* (proto) [#1466](https://github.com/evmos/ethermint/pull/1466) Fix proto scripts and upgrade them to mirror current cosmos-sdk scripts
|
||||
* (rpc) [#1405](https://github.com/evmos/ethermint/pull/1405) Fix uninitialized chain ID field in gRPC requests.
|
||||
* (analytics) [#1434](https://github.com/evmos/ethermint/pull/1434) Remove unbound labels from custom tendermint metrics.
|
||||
* (rpc) [#1484](https://github.com/evmos/ethermint/pull/1484) Align empty account result for old blocks as ethereum instead of return account not found error.
|
||||
* (rpc) [#1503](https://github.com/evmos/ethermint/pull/1503) Fix block hashes returned on JSON-RPC filter `eth_newBlockFilter`.
|
||||
|
||||
|
||||
## [v0.19.3] - 2022-10-14
|
||||
|
||||
@ -211,7 +238,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
* (evm) [tharsis#1088](https://github.com/evmos/ethermint/pull/1088) Fix ability to append log in tx post processing.
|
||||
* (rpc) [tharsis#1081](https://github.com/evmos/ethermint/pull/1081) fix `debug_getBlockRlp`/`debug_printBlock` don't filter failed transactions.
|
||||
* (ante) [tharsis#1111](https://github.com/evmos/ethermint/pull/1111) Move CanTransfer decorator before GasConsume decorator
|
||||
* (types) [tharsis#1112](https://github.com/cosmos/ethermint/pull/1112) Add `GetBaseAccount` to avoid invalid account error when create vesting account.
|
||||
* (types) [tharsis#1112](https://github.com/evmos/ethermint/pull/1112) Add `GetBaseAccount` to avoid invalid account error when create vesting account.
|
||||
|
||||
## [v0.15.0] - 2022-05-09
|
||||
|
||||
@ -647,7 +674,7 @@ the Tracer type used to collect execution traces from the EVM transaction execut
|
||||
|
||||
### Improvements
|
||||
|
||||
* (deps) [tharsis#615](https://github.com/cosmos/ethermint/pull/615) Bump Cosmos SDK version to [v0.39.2](https://github.com/cosmos/cosmos-sdk/tag/v0.39.2)
|
||||
* (deps) [tharsis#615](https://github.com/cosmos/ethermint/pull/615) Bump Cosmos SDK version to [v0.39.2](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.39.2)
|
||||
* (deps) [tharsis#610](https://github.com/cosmos/ethermint/pull/610) Update Go dependency to 1.15+.
|
||||
* (evm) [tharsis#603](https://github.com/cosmos/ethermint/pull/603) Add state transition params that enable or disable the EVM `Call` and `Create` operations.
|
||||
* (deps) [tharsis#602](https://github.com/cosmos/ethermint/pull/602) Bump tendermint version to [v0.33.9](https://github.com/tendermint/tendermint/releases/tag/v0.33.9)
|
||||
|
@ -17,7 +17,7 @@ COPY . .
|
||||
RUN make build
|
||||
|
||||
# Final image
|
||||
FROM alpine:3.16.2
|
||||
FROM alpine:3.17.0
|
||||
|
||||
# Install ca-certificates
|
||||
RUN apk add --update ca-certificates jq
|
||||
|
141
Makefile
Executable file → Normal file
141
Makefile
Executable file → Normal file
@ -14,7 +14,6 @@ SIMAPP = ./app
|
||||
HTTPS_GIT := https://github.com/evmos/ethermint.git
|
||||
PROJECT_NAME = $(shell git remote get-url origin | xargs basename -s .git)
|
||||
DOCKER := $(shell which docker)
|
||||
DOCKER_BUF := $(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace bufbuild/buf:1.0.0-rc8
|
||||
# RocksDB is a native dependency, so we don't assume the library is installed.
|
||||
# Instead, it must be explicitly enabled and we warn when it is not.
|
||||
ENABLE_ROCKSDB ?= false
|
||||
@ -328,9 +327,6 @@ test-import:
|
||||
test-rpc:
|
||||
./scripts/integration-test-all.sh -t "rpc" -q 1 -z 1 -s 2 -m "rpc" -r "true"
|
||||
|
||||
test-integration:
|
||||
./scripts/integration-test-all.sh -t "integration" -q 1 -z 1 -s 2 -m "integration" -r "true"
|
||||
|
||||
run-integration-tests:
|
||||
@nix-shell ./tests/integration_tests/shell.nix --run ./scripts/run-integration-tests.sh
|
||||
|
||||
@ -347,51 +343,6 @@ test-solidity:
|
||||
|
||||
.PHONY: run-tests test test-all test-import test-rpc test-contract test-solidity $(TEST_TARGETS)
|
||||
|
||||
test-sim-nondeterminism:
|
||||
@echo "Running non-determinism test..."
|
||||
@go test -mod=readonly $(SIMAPP) -run TestAppStateDeterminism -Enabled=true \
|
||||
-NumBlocks=100 -BlockSize=200 -Commit=true -Period=0 -v -timeout 24h
|
||||
|
||||
test-sim-random-genesis-fast:
|
||||
@echo "Running random genesis simulation..."
|
||||
@go test -mod=readonly $(SIMAPP) -run TestFullAppSimulation \
|
||||
-Enabled=true -NumBlocks=100 -BlockSize=200 -Commit=true -Seed=99 -Period=5 -v -timeout 24h
|
||||
|
||||
test-sim-import-export: runsim
|
||||
@echo "Running application import/export simulation. This may take several minutes..."
|
||||
@$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 50 5 TestAppImportExport
|
||||
|
||||
test-sim-after-import: runsim
|
||||
@echo "Running application simulation-after-import. This may take several minutes..."
|
||||
@$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 50 5 TestAppSimulationAfterImport
|
||||
|
||||
test-sim-random-genesis-multi-seed: runsim
|
||||
@echo "Running multi-seed custom genesis simulation..."
|
||||
@$(BINDIR)/runsim -SimAppPkg=$(SIMAPP) -ExitOnFail 400 5 TestFullAppSimulation
|
||||
|
||||
test-sim-multi-seed-long: runsim
|
||||
@echo "Running long multi-seed application simulation. This may take awhile!"
|
||||
@$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 500 50 TestFullAppSimulation
|
||||
|
||||
test-sim-multi-seed-short: runsim
|
||||
@echo "Running short multi-seed application simulation. This may take awhile!"
|
||||
@$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 50 10 TestFullAppSimulation
|
||||
|
||||
test-sim-benchmark-invariants:
|
||||
@echo "Running simulation invariant benchmarks..."
|
||||
@go test -mod=readonly $(SIMAPP) -benchmem -bench=BenchmarkInvariants -run=^$ \
|
||||
-Enabled=true -NumBlocks=1000 -BlockSize=200 \
|
||||
-Period=1 -Commit=true -Seed=57 -v -timeout 24h
|
||||
|
||||
.PHONY: \
|
||||
test-sim-nondeterminism \
|
||||
test-sim-custom-genesis-fast \
|
||||
test-sim-import-export \
|
||||
test-sim-after-import \
|
||||
test-sim-custom-genesis-multi-seed \
|
||||
test-sim-multi-seed-short \
|
||||
test-sim-multi-seed-long \
|
||||
test-sim-benchmark-invariants
|
||||
|
||||
benchmark:
|
||||
@go test -mod=readonly -bench=. $(PACKAGES_NOSIMULATION)
|
||||
@ -425,74 +376,62 @@ format-fix:
|
||||
### Protobuf ###
|
||||
###############################################################################
|
||||
|
||||
protoVer=v0.2
|
||||
# ------
|
||||
# NOTE: Link to the tendermintdev/sdk-proto-gen docker images:
|
||||
# https://hub.docker.com/r/tendermintdev/sdk-proto-gen/tags
|
||||
#
|
||||
protoVer=v0.7
|
||||
protoImageName=tendermintdev/sdk-proto-gen:$(protoVer)
|
||||
containerProtoGen=$(PROJECT_NAME)-proto-gen-$(protoVer)
|
||||
containerProtoGenAny=$(PROJECT_NAME)-proto-gen-any-$(protoVer)
|
||||
containerProtoGenSwagger=$(PROJECT_NAME)-proto-gen-swagger-$(protoVer)
|
||||
containerProtoFmt=$(PROJECT_NAME)-proto-fmt-$(protoVer)
|
||||
protoImage=$(DOCKER) run --network host --rm -v $(CURDIR):/workspace --workdir /workspace $(protoImageName)
|
||||
# ------
|
||||
# NOTE: cosmos/proto-builder image is needed because clang-format is not installed
|
||||
# on the tendermintdev/sdk-proto-gen docker image.
|
||||
# Link to the cosmos/proto-builder docker images:
|
||||
# https://github.com/cosmos/cosmos-sdk/pkgs/container/proto-builder
|
||||
#
|
||||
protoCosmosVer=0.11.2
|
||||
protoCosmosName=ghcr.io/cosmos/proto-builder:$(protoCosmosVer)
|
||||
protoCosmosImage=$(DOCKER) run --network host --rm -v $(CURDIR):/workspace --workdir /workspace $(protoCosmosName)
|
||||
# ------
|
||||
# NOTE: Link to the yoheimuta/protolint docker images:
|
||||
# https://hub.docker.com/r/yoheimuta/protolint/tags
|
||||
#
|
||||
protolintVer=0.42.2
|
||||
protolintName=yoheimuta/protolint:$(protolintVer)
|
||||
protolintImage=$(DOCKER) run --network host --rm -v $(CURDIR):/workspace --workdir /workspace $(protolintName)
|
||||
|
||||
|
||||
# ------
|
||||
# NOTE: If you are experiencing problems running these commands, try deleting
|
||||
# the docker images and execute the desired command again.
|
||||
#
|
||||
proto-all: proto-format proto-lint proto-gen
|
||||
|
||||
proto-gen:
|
||||
@echo "Generating Protobuf files"
|
||||
@if docker ps -a --format '{{.Names}}' | grep -Eq "^${containerProtoGen}$$"; then docker start -a $(containerProtoGen); else docker run --name $(containerProtoGen) -v $(CURDIR):/workspace --workdir /workspace $(protoImageName) \
|
||||
sh ./scripts/protocgen.sh; fi
|
||||
$(protoImage) sh ./scripts/protocgen.sh
|
||||
|
||||
proto-swagger-gen:
|
||||
@echo "Generating Protobuf Swagger"
|
||||
@./scripts/proto-tools-installer.sh
|
||||
@./scripts/protoc-swagger-gen.sh
|
||||
|
||||
# TODO: Rethink API docs generation
|
||||
# proto-swagger-gen:
|
||||
# @echo "Generating Protobuf Swagger"
|
||||
# $(protoImage) sh ./scripts/protoc-swagger-gen.sh
|
||||
|
||||
proto-format:
|
||||
@echo "Formatting Protobuf files"
|
||||
@if docker ps -a --format '{{.Names}}' | grep -Eq "^${containerProtoFmt}$$"; then docker start -a $(containerProtoFmt); else docker run --name $(containerProtoFmt) -v $(CURDIR):/workspace --workdir /workspace tendermintdev/docker-build-proto \
|
||||
find ./ -not -path "./third_party/*" -name "*.proto" -exec clang-format -i {} \; ; fi
|
||||
$(protoCosmosImage) find ./ -name *.proto -exec clang-format -i {} \;
|
||||
|
||||
# NOTE: The linter configuration lives in .protolint.yaml
|
||||
proto-lint:
|
||||
@$(DOCKER_BUF) lint --error-format=json
|
||||
@echo "Linting Protobuf files"
|
||||
$(protolintImage) lint ./proto
|
||||
|
||||
proto-check-breaking:
|
||||
@$(DOCKER_BUF) breaking --against $(HTTPS_GIT)#branch=main
|
||||
@echo "Checking Protobuf files for breaking changes"
|
||||
$(protoImage) buf breaking --against $(HTTPS_GIT)#branch=main
|
||||
|
||||
|
||||
TM_URL = https://raw.githubusercontent.com/tendermint/tendermint/v0.34.12/proto/tendermint
|
||||
GOGO_PROTO_URL = https://raw.githubusercontent.com/regen-network/protobuf/cosmos
|
||||
COSMOS_SDK_URL = https://raw.githubusercontent.com/cosmos/cosmos-sdk/v0.43.0
|
||||
COSMOS_PROTO_URL = https://raw.githubusercontent.com/regen-network/cosmos-proto/master
|
||||
|
||||
TM_CRYPTO_TYPES = third_party/proto/tendermint/crypto
|
||||
TM_ABCI_TYPES = third_party/proto/tendermint/abci
|
||||
TM_TYPES = third_party/proto/tendermint/types
|
||||
|
||||
GOGO_PROTO_TYPES = third_party/proto/gogoproto
|
||||
|
||||
COSMOS_PROTO_TYPES = third_party/proto/cosmos_proto
|
||||
|
||||
proto-update-deps:
|
||||
@mkdir -p $(GOGO_PROTO_TYPES)
|
||||
@curl -sSL $(GOGO_PROTO_URL)/gogoproto/gogo.proto > $(GOGO_PROTO_TYPES)/gogo.proto
|
||||
|
||||
@mkdir -p $(COSMOS_PROTO_TYPES)
|
||||
@curl -sSL $(COSMOS_PROTO_URL)/cosmos.proto > $(COSMOS_PROTO_TYPES)/cosmos.proto
|
||||
|
||||
## Importing of tendermint protobuf definitions currently requires the
|
||||
## use of `sed` in order to build properly with cosmos-sdk's proto file layout
|
||||
## (which is the standard Buf.build FILE_LAYOUT)
|
||||
## Issue link: https://github.com/tendermint/tendermint/issues/5021
|
||||
@mkdir -p $(TM_ABCI_TYPES)
|
||||
@curl -sSL $(TM_URL)/abci/types.proto > $(TM_ABCI_TYPES)/types.proto
|
||||
|
||||
@mkdir -p $(TM_TYPES)
|
||||
@curl -sSL $(TM_URL)/types/types.proto > $(TM_TYPES)/types.proto
|
||||
|
||||
@mkdir -p $(TM_CRYPTO_TYPES)
|
||||
@curl -sSL $(TM_URL)/crypto/proof.proto > $(TM_CRYPTO_TYPES)/proof.proto
|
||||
@curl -sSL $(TM_URL)/crypto/keys.proto > $(TM_CRYPTO_TYPES)/keys.proto
|
||||
|
||||
|
||||
|
||||
.PHONY: proto-all proto-gen proto-gen-any proto-swagger-gen proto-format proto-lint proto-check-breaking proto-update-deps
|
||||
.PHONY: proto-all proto-gen proto-gen-any proto-format proto-lint proto-check-breaking
|
||||
|
||||
###############################################################################
|
||||
### Localnet ###
|
||||
|
@ -6,9 +6,10 @@ import (
|
||||
|
||||
tmlog "github.com/tendermint/tendermint/libs/log"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
@ -51,8 +52,8 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
|
||||
// cosmos-sdk tx with dynamic fee extension
|
||||
anteHandler = newCosmosAnteHandler(options)
|
||||
default:
|
||||
return ctx, sdkerrors.Wrapf(
|
||||
sdkerrors.ErrUnknownExtensionOptions,
|
||||
return ctx, errorsmod.Wrapf(
|
||||
errortypes.ErrUnknownExtensionOptions,
|
||||
"rejecting tx with unsupported extension option: %s", typeURL,
|
||||
)
|
||||
}
|
||||
@ -66,7 +67,7 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
|
||||
case sdk.Tx:
|
||||
anteHandler = newCosmosAnteHandler(options)
|
||||
default:
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx)
|
||||
return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid transaction type: %T", tx)
|
||||
}
|
||||
|
||||
return anteHandler(ctx, tx, sim)
|
||||
@ -75,7 +76,7 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
|
||||
|
||||
func Recover(logger tmlog.Logger, err *error) {
|
||||
if r := recover(); r != nil {
|
||||
*err = sdkerrors.Wrapf(sdkerrors.ErrPanic, "%v", r)
|
||||
*err = errorsmod.Wrapf(errortypes.ErrPanic, "%v", r)
|
||||
|
||||
if e, ok := r.(error); ok {
|
||||
logger.Error(
|
||||
|
@ -31,6 +31,7 @@ import (
|
||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
|
||||
)
|
||||
|
||||
func (suite AnteTestSuite) TestAnteHandler() {
|
||||
@ -348,6 +349,17 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
||||
return txBuilder.GetTx()
|
||||
}, false, false, true,
|
||||
},
|
||||
{
|
||||
"success- DeliverTx EIP712 create validator (with blank fields)",
|
||||
func() sdk.Tx {
|
||||
from := acc.GetAddress()
|
||||
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
|
||||
amount := sdk.NewCoins(coinAmount)
|
||||
gas := uint64(200000)
|
||||
txBuilder := suite.CreateTestEIP712MsgCreateValidator2(from, privKey, "ethermint_9000-1", gas, amount)
|
||||
return txBuilder.GetTx()
|
||||
}, false, false, true,
|
||||
},
|
||||
{
|
||||
"success- DeliverTx EIP712 MsgSubmitProposal",
|
||||
func() sdk.Tx {
|
||||
@ -375,7 +387,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
||||
from, grantee, &banktypes.SendAuthorization{SpendLimit: gasAmount}, &expiresAt,
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
return suite.CreateTestEIP712CosmosTxBuilder(from, privKey, "ethermint_9000-1", gas, gasAmount, msg).GetTx()
|
||||
return suite.CreateTestEIP712SingleMessageTxBuilder(from, privKey, "ethermint_9000-1", gas, gasAmount, msg).GetTx()
|
||||
}, false, false, true,
|
||||
},
|
||||
|
||||
@ -408,10 +420,65 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
||||
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
|
||||
amount := sdk.NewCoins(coinAmount)
|
||||
gas := uint64(200000)
|
||||
txBuilder := suite.CreateTestEIP712MsgEditValidator(from, privKey, "ethermint_9000-1", gas, amount)
|
||||
txBuilder := suite.CreateTestEIP712MsgSubmitEvidence(from, privKey, "ethermint_9000-1", gas, amount)
|
||||
return txBuilder.GetTx()
|
||||
}, false, false, true,
|
||||
},
|
||||
{
|
||||
"success- DeliverTx EIP712 submit proposal v1",
|
||||
func() sdk.Tx {
|
||||
from := acc.GetAddress()
|
||||
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
|
||||
amount := sdk.NewCoins(coinAmount)
|
||||
gas := uint64(200000)
|
||||
txBuilder := suite.CreateTestEIP712SubmitProposalV1(from, privKey, "ethermint_9000-1", gas, amount)
|
||||
return txBuilder.GetTx()
|
||||
}, false, false, true,
|
||||
},
|
||||
{
|
||||
"success- DeliverTx EIP712 MsgExec",
|
||||
func() sdk.Tx {
|
||||
from := acc.GetAddress()
|
||||
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
|
||||
amount := sdk.NewCoins(coinAmount)
|
||||
gas := uint64(200000)
|
||||
txBuilder := suite.CreateTestEIP712MsgExec(from, privKey, "ethermint_9000-1", gas, amount)
|
||||
return txBuilder.GetTx()
|
||||
}, false, false, true,
|
||||
},
|
||||
{
|
||||
"success- DeliverTx EIP712 MsgVoteV1",
|
||||
func() sdk.Tx {
|
||||
from := acc.GetAddress()
|
||||
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
|
||||
amount := sdk.NewCoins(coinAmount)
|
||||
gas := uint64(200000)
|
||||
txBuilder := suite.CreateTestEIP712MsgVoteV1(from, privKey, "ethermint_9000-1", gas, amount)
|
||||
return txBuilder.GetTx()
|
||||
}, false, false, true,
|
||||
},
|
||||
{
|
||||
"success- DeliverTx EIP712 Multiple MsgSend",
|
||||
func() sdk.Tx {
|
||||
from := acc.GetAddress()
|
||||
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
|
||||
amount := sdk.NewCoins(coinAmount)
|
||||
gas := uint64(200000)
|
||||
txBuilder := suite.CreateTestEIP712MultipleMsgSend(from, privKey, "ethermint_9000-1", gas, amount)
|
||||
return txBuilder.GetTx()
|
||||
}, false, false, true,
|
||||
},
|
||||
{
|
||||
"fails - DeliverTx EIP712 Multiple Signers",
|
||||
func() sdk.Tx {
|
||||
from := acc.GetAddress()
|
||||
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
|
||||
amount := sdk.NewCoins(coinAmount)
|
||||
gas := uint64(200000)
|
||||
txBuilder := suite.CreateTestEIP712MultipleSignerMsgs(from, privKey, "ethermint_9000-1", gas, amount)
|
||||
return txBuilder.GetTx()
|
||||
}, false, false, false,
|
||||
},
|
||||
{
|
||||
"fails - DeliverTx EIP712 signed Cosmos Tx with wrong Chain ID",
|
||||
func() sdk.Tx {
|
||||
@ -507,6 +574,301 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
||||
return tx
|
||||
}, true, false, false,
|
||||
},
|
||||
{
|
||||
"passes - Single-signer EIP-712",
|
||||
func() sdk.Tx {
|
||||
msg := banktypes.NewMsgSend(
|
||||
sdk.AccAddress(privKey.PubKey().Address()),
|
||||
addr[:],
|
||||
sdk.NewCoins(
|
||||
sdk.NewCoin(
|
||||
"photon",
|
||||
sdk.NewInt(1),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
txBuilder := suite.CreateTestSingleSignedTx(
|
||||
privKey,
|
||||
signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
|
||||
msg,
|
||||
"ethermint_9000-1",
|
||||
2000000,
|
||||
"EIP-712",
|
||||
)
|
||||
|
||||
return txBuilder.GetTx()
|
||||
}, false, false, true,
|
||||
},
|
||||
{
|
||||
"passes - EIP-712 multi-key",
|
||||
func() sdk.Tx {
|
||||
numKeys := 5
|
||||
privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys)
|
||||
pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys)
|
||||
|
||||
msg := banktypes.NewMsgSend(
|
||||
sdk.AccAddress(pk.Address()),
|
||||
addr[:],
|
||||
sdk.NewCoins(
|
||||
sdk.NewCoin(
|
||||
"photon",
|
||||
sdk.NewInt(1),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
txBuilder := suite.CreateTestSignedMultisigTx(
|
||||
privKeys,
|
||||
signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
|
||||
msg,
|
||||
"ethermint_9000-1",
|
||||
2000000,
|
||||
"EIP-712",
|
||||
)
|
||||
|
||||
return txBuilder.GetTx()
|
||||
}, false, false, true,
|
||||
},
|
||||
{
|
||||
"passes - Mixed multi-key",
|
||||
func() sdk.Tx {
|
||||
numKeys := 5
|
||||
privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys)
|
||||
pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys)
|
||||
|
||||
msg := banktypes.NewMsgSend(
|
||||
sdk.AccAddress(pk.Address()),
|
||||
addr[:],
|
||||
sdk.NewCoins(
|
||||
sdk.NewCoin(
|
||||
"photon",
|
||||
sdk.NewInt(1),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
txBuilder := suite.CreateTestSignedMultisigTx(
|
||||
privKeys,
|
||||
signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
|
||||
msg,
|
||||
"ethermint_9000-1",
|
||||
2000000,
|
||||
"mixed", // Combine EIP-712 and standard signatures
|
||||
)
|
||||
|
||||
return txBuilder.GetTx()
|
||||
}, false, false, true,
|
||||
},
|
||||
{
|
||||
"passes - Mixed multi-key with MsgVote",
|
||||
func() sdk.Tx {
|
||||
numKeys := 5
|
||||
privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys)
|
||||
pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys)
|
||||
|
||||
msg := govtypes.NewMsgVote(
|
||||
sdk.AccAddress(pk.Address()),
|
||||
1,
|
||||
govtypes.OptionYes,
|
||||
)
|
||||
|
||||
txBuilder := suite.CreateTestSignedMultisigTx(
|
||||
privKeys,
|
||||
signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
|
||||
msg,
|
||||
"ethermint_9000-1",
|
||||
2000000,
|
||||
"mixed", // Combine EIP-712 and standard signatures
|
||||
)
|
||||
|
||||
return txBuilder.GetTx()
|
||||
}, false, false, true,
|
||||
},
|
||||
{
|
||||
"Fails - Multi-Key with incorrect Chain ID",
|
||||
func() sdk.Tx {
|
||||
numKeys := 5
|
||||
privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys)
|
||||
pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys)
|
||||
|
||||
msg := banktypes.NewMsgSend(
|
||||
sdk.AccAddress(pk.Address()),
|
||||
addr[:],
|
||||
sdk.NewCoins(
|
||||
sdk.NewCoin(
|
||||
"photon",
|
||||
sdk.NewInt(1),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
txBuilder := suite.CreateTestSignedMultisigTx(
|
||||
privKeys,
|
||||
signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
|
||||
msg,
|
||||
"ethermint_9005-1",
|
||||
2000000,
|
||||
"mixed",
|
||||
)
|
||||
|
||||
return txBuilder.GetTx()
|
||||
}, false, false, false,
|
||||
},
|
||||
{
|
||||
"Fails - Multi-Key with incorrect sign mode",
|
||||
func() sdk.Tx {
|
||||
numKeys := 5
|
||||
privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys)
|
||||
pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys)
|
||||
|
||||
msg := banktypes.NewMsgSend(
|
||||
sdk.AccAddress(pk.Address()),
|
||||
addr[:],
|
||||
sdk.NewCoins(
|
||||
sdk.NewCoin(
|
||||
"photon",
|
||||
sdk.NewInt(1),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
txBuilder := suite.CreateTestSignedMultisigTx(
|
||||
privKeys,
|
||||
signing.SignMode_SIGN_MODE_DIRECT,
|
||||
msg,
|
||||
"ethermint_9000-1",
|
||||
2000000,
|
||||
"mixed",
|
||||
)
|
||||
|
||||
return txBuilder.GetTx()
|
||||
}, false, false, false,
|
||||
},
|
||||
{
|
||||
"Fails - Multi-Key with too little gas",
|
||||
func() sdk.Tx {
|
||||
numKeys := 5
|
||||
privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys)
|
||||
pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys)
|
||||
|
||||
msg := banktypes.NewMsgSend(
|
||||
sdk.AccAddress(pk.Address()),
|
||||
addr[:],
|
||||
sdk.NewCoins(
|
||||
sdk.NewCoin(
|
||||
"photon",
|
||||
sdk.NewInt(1),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
txBuilder := suite.CreateTestSignedMultisigTx(
|
||||
privKeys,
|
||||
signing.SignMode_SIGN_MODE_DIRECT,
|
||||
msg,
|
||||
"ethermint_9000-1",
|
||||
2000,
|
||||
"mixed", // Combine EIP-712 and standard signatures
|
||||
)
|
||||
|
||||
return txBuilder.GetTx()
|
||||
}, false, false, false,
|
||||
},
|
||||
{
|
||||
"Fails - Multi-Key with different payload than one signed",
|
||||
func() sdk.Tx {
|
||||
numKeys := 1
|
||||
privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys)
|
||||
pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys)
|
||||
|
||||
msg := banktypes.NewMsgSend(
|
||||
sdk.AccAddress(pk.Address()),
|
||||
addr[:],
|
||||
sdk.NewCoins(
|
||||
sdk.NewCoin(
|
||||
"photon",
|
||||
sdk.NewInt(1),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
txBuilder := suite.CreateTestSignedMultisigTx(
|
||||
privKeys,
|
||||
signing.SignMode_SIGN_MODE_DIRECT,
|
||||
msg,
|
||||
"ethermint_9000-1",
|
||||
2000,
|
||||
"EIP-712",
|
||||
)
|
||||
|
||||
msg.Amount[0].Amount = sdk.NewInt(5)
|
||||
txBuilder.SetMsgs(msg)
|
||||
|
||||
return txBuilder.GetTx()
|
||||
}, false, false, false,
|
||||
},
|
||||
{
|
||||
"Fails - Multi-Key with messages added after signing",
|
||||
func() sdk.Tx {
|
||||
numKeys := 1
|
||||
privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys)
|
||||
pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys)
|
||||
|
||||
msg := banktypes.NewMsgSend(
|
||||
sdk.AccAddress(pk.Address()),
|
||||
addr[:],
|
||||
sdk.NewCoins(
|
||||
sdk.NewCoin(
|
||||
"photon",
|
||||
sdk.NewInt(1),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
txBuilder := suite.CreateTestSignedMultisigTx(
|
||||
privKeys,
|
||||
signing.SignMode_SIGN_MODE_DIRECT,
|
||||
msg,
|
||||
"ethermint_9000-1",
|
||||
2000,
|
||||
"EIP-712",
|
||||
)
|
||||
|
||||
// Duplicate
|
||||
txBuilder.SetMsgs(msg, msg)
|
||||
|
||||
return txBuilder.GetTx()
|
||||
}, false, false, false,
|
||||
},
|
||||
{
|
||||
"Fails - Single-Signer EIP-712 with messages added after signing",
|
||||
func() sdk.Tx {
|
||||
msg := banktypes.NewMsgSend(
|
||||
sdk.AccAddress(privKey.PubKey().Address()),
|
||||
addr[:],
|
||||
sdk.NewCoins(
|
||||
sdk.NewCoin(
|
||||
"photon",
|
||||
sdk.NewInt(1),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
txBuilder := suite.CreateTestSingleSignedTx(
|
||||
privKey,
|
||||
signing.SignMode_SIGN_MODE_DIRECT,
|
||||
msg,
|
||||
"ethermint_9000-1",
|
||||
2000,
|
||||
"EIP-712",
|
||||
)
|
||||
|
||||
txBuilder.SetMsgs(msg, msg)
|
||||
|
||||
return txBuilder.GetTx()
|
||||
}, false, false, false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
@ -939,7 +1301,7 @@ func (suite *AnteTestSuite) TestConsumeSignatureVerificationGas() {
|
||||
multisigKey1 := kmultisig.NewLegacyAminoPubKey(2, pkSet1)
|
||||
multisignature1 := multisig.NewMultisig(len(pkSet1))
|
||||
expectedCost1 := expectedGasCostByKeys(pkSet1)
|
||||
|
||||
|
||||
for i := 0; i < len(pkSet1); i++ {
|
||||
stdSig := legacytx.StdSignature{PubKey: pkSet1[i], Signature: sigSet1[i]}
|
||||
sigV2, err := legacytx.StdSignatureToSignatureV2(cdc, stdSig)
|
||||
|
@ -3,11 +3,12 @@ package ante
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx"
|
||||
@ -15,9 +16,11 @@ import (
|
||||
|
||||
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/crypto/secp256k1"
|
||||
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
||||
"github.com/evmos/ethermint/crypto/ethsecp256k1"
|
||||
"github.com/evmos/ethermint/ethereum/eip712"
|
||||
ethermint "github.com/evmos/ethermint/types"
|
||||
|
||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||
)
|
||||
|
||||
@ -61,12 +64,12 @@ func (svd Eip712SigVerificationDecorator) AnteHandle(ctx sdk.Context,
|
||||
|
||||
sigTx, ok := tx.(authsigning.SigVerifiableTx)
|
||||
if !ok {
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "tx %T doesn't implement authsigning.SigVerifiableTx", tx)
|
||||
return ctx, errorsmod.Wrapf(errortypes.ErrInvalidType, "tx %T doesn't implement authsigning.SigVerifiableTx", tx)
|
||||
}
|
||||
|
||||
authSignTx, ok := tx.(authsigning.Tx)
|
||||
if !ok {
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "tx %T doesn't implement the authsigning.Tx interface", tx)
|
||||
return ctx, errorsmod.Wrapf(errortypes.ErrInvalidType, "tx %T doesn't implement the authsigning.Tx interface", tx)
|
||||
}
|
||||
|
||||
// stdSigs contains the sequence number, account number, and signatures.
|
||||
@ -80,12 +83,16 @@ func (svd Eip712SigVerificationDecorator) AnteHandle(ctx sdk.Context,
|
||||
|
||||
// EIP712 allows just one signature
|
||||
if len(sigs) != 1 {
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "invalid number of signers (%d); EIP712 signatures allows just one signature", len(sigs))
|
||||
return ctx, errorsmod.Wrapf(
|
||||
errortypes.ErrTooManySignatures,
|
||||
"invalid number of signers (%d); EIP712 signatures allows just one signature",
|
||||
len(sigs),
|
||||
)
|
||||
}
|
||||
|
||||
// check that signer length and signature length are the same
|
||||
if len(sigs) != len(signerAddrs) {
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "invalid number of signer; expected: %d, got %d", len(signerAddrs), len(sigs))
|
||||
return ctx, errorsmod.Wrapf(errortypes.ErrorInvalidSigner, "invalid number of signers; expected: %d, got %d", len(signerAddrs), len(sigs))
|
||||
}
|
||||
|
||||
// EIP712 has just one signature, avoid looping here and only read index 0
|
||||
@ -100,13 +107,13 @@ func (svd Eip712SigVerificationDecorator) AnteHandle(ctx sdk.Context,
|
||||
// retrieve pubkey
|
||||
pubKey := acc.GetPubKey()
|
||||
if !simulate && pubKey == nil {
|
||||
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidPubKey, "pubkey on account is not set")
|
||||
return ctx, errorsmod.Wrap(errortypes.ErrInvalidPubKey, "pubkey on account is not set")
|
||||
}
|
||||
|
||||
// Check account sequence number.
|
||||
if sig.Sequence != acc.GetSequence() {
|
||||
return ctx, sdkerrors.Wrapf(
|
||||
sdkerrors.ErrWrongSequence,
|
||||
return ctx, errorsmod.Wrapf(
|
||||
errortypes.ErrWrongSequence,
|
||||
"account sequence mismatch, expected %d, got %d", acc.GetSequence(), sig.Sequence,
|
||||
)
|
||||
}
|
||||
@ -132,7 +139,7 @@ func (svd Eip712SigVerificationDecorator) AnteHandle(ctx sdk.Context,
|
||||
|
||||
if err := VerifySignature(pubKey, signerData, sig.Data, svd.signModeHandler, authSignTx); err != nil {
|
||||
errMsg := fmt.Errorf("signature verification failed; please verify account number (%d) and chain-id (%s): %w", accNum, chainID, err)
|
||||
return ctx, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, errMsg.Error())
|
||||
return ctx, errorsmod.Wrap(errortypes.ErrUnauthorized, errMsg.Error())
|
||||
}
|
||||
|
||||
return next(ctx, tx, simulate)
|
||||
@ -150,12 +157,12 @@ func VerifySignature(
|
||||
switch data := sigData.(type) {
|
||||
case *signing.SingleSignatureData:
|
||||
if data.SignMode != signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON {
|
||||
return sdkerrors.Wrapf(sdkerrors.ErrNotSupported, "unexpected SignatureData %T: wrong SignMode", sigData)
|
||||
return errorsmod.Wrapf(errortypes.ErrNotSupported, "unexpected SignatureData %T: wrong SignMode", sigData)
|
||||
}
|
||||
|
||||
// Note: this prevents the user from sending thrash data in the signature field
|
||||
// Note: this prevents the user from sending trash data in the signature field
|
||||
if len(data.Signature) != 0 {
|
||||
return sdkerrors.Wrap(sdkerrors.ErrTooManySignatures, "invalid signature value; EIP712 must have the cosmos transaction signature empty")
|
||||
return errorsmod.Wrap(errortypes.ErrTooManySignatures, "invalid signature value; EIP712 must have the cosmos transaction signature empty")
|
||||
}
|
||||
|
||||
// @contract: this code is reached only when Msg has Web3Tx extension (so this custom Ante handler flow),
|
||||
@ -163,7 +170,7 @@ func VerifySignature(
|
||||
|
||||
msgs := tx.GetMsgs()
|
||||
if len(msgs) == 0 {
|
||||
return sdkerrors.Wrap(sdkerrors.ErrNoSignatures, "tx doesn't contain any msgs to verify signature")
|
||||
return errorsmod.Wrap(errortypes.ErrNoSignatures, "tx doesn't contain any msgs to verify signature")
|
||||
}
|
||||
|
||||
txBytes := legacytx.StdSignBytes(
|
||||
@ -180,33 +187,33 @@ func VerifySignature(
|
||||
|
||||
signerChainID, err := ethermint.ParseChainID(signerData.ChainID)
|
||||
if err != nil {
|
||||
return sdkerrors.Wrapf(err, "failed to parse chainID: %s", signerData.ChainID)
|
||||
return errorsmod.Wrapf(err, "failed to parse chain-id: %s", signerData.ChainID)
|
||||
}
|
||||
|
||||
txWithExtensions, ok := tx.(authante.HasExtensionOptionsTx)
|
||||
if !ok {
|
||||
return sdkerrors.Wrap(sdkerrors.ErrUnknownExtensionOptions, "tx doesnt contain any extensions")
|
||||
return errorsmod.Wrap(errortypes.ErrUnknownExtensionOptions, "tx doesnt contain any extensions")
|
||||
}
|
||||
opts := txWithExtensions.GetExtensionOptions()
|
||||
if len(opts) != 1 {
|
||||
return sdkerrors.Wrap(sdkerrors.ErrUnknownExtensionOptions, "tx doesnt contain expected amount of extension options")
|
||||
return errorsmod.Wrap(errortypes.ErrUnknownExtensionOptions, "tx doesnt contain expected amount of extension options")
|
||||
}
|
||||
|
||||
extOpt, ok := opts[0].GetCachedValue().(*ethermint.ExtensionOptionsWeb3Tx)
|
||||
if !ok {
|
||||
return sdkerrors.Wrap(sdkerrors.ErrInvalidChainID, "unknown extension option")
|
||||
return errorsmod.Wrap(errortypes.ErrUnknownExtensionOptions, "unknown extension option")
|
||||
}
|
||||
|
||||
if extOpt.TypedDataChainID != signerChainID.Uint64() {
|
||||
return sdkerrors.Wrap(sdkerrors.ErrInvalidChainID, "invalid chainID")
|
||||
return errorsmod.Wrap(errortypes.ErrInvalidChainID, "invalid chain-id")
|
||||
}
|
||||
|
||||
if len(extOpt.FeePayer) == 0 {
|
||||
return sdkerrors.Wrap(sdkerrors.ErrUnknownExtensionOptions, "no feePayer on ExtensionOptionsWeb3Tx")
|
||||
return errorsmod.Wrap(errortypes.ErrUnknownExtensionOptions, "no feePayer on ExtensionOptionsWeb3Tx")
|
||||
}
|
||||
feePayer, err := sdk.AccAddressFromBech32(extOpt.FeePayer)
|
||||
if err != nil {
|
||||
return sdkerrors.Wrap(err, "failed to parse feePayer from ExtensionOptionsWeb3Tx")
|
||||
return errorsmod.Wrap(err, "failed to parse feePayer from ExtensionOptionsWeb3Tx")
|
||||
}
|
||||
|
||||
feeDelegation := &eip712.FeeDelegationOptions{
|
||||
@ -215,17 +222,17 @@ func VerifySignature(
|
||||
|
||||
typedData, err := eip712.WrapTxToTypedData(ethermintCodec, extOpt.TypedDataChainID, msgs[0], txBytes, feeDelegation)
|
||||
if err != nil {
|
||||
return sdkerrors.Wrap(err, "failed to pack tx data in EIP712 object")
|
||||
return errorsmod.Wrap(err, "failed to create EIP-712 typed data from tx")
|
||||
}
|
||||
|
||||
sigHash, err := eip712.ComputeTypedDataHash(typedData)
|
||||
sigHash, _, err := apitypes.TypedDataAndHash(typedData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
feePayerSig := extOpt.FeePayerSig
|
||||
if len(feePayerSig) != ethcrypto.SignatureLength {
|
||||
return sdkerrors.Wrap(sdkerrors.ErrorInvalidSigner, "signature length doesn't match typical [R||S||V] signature 65 bytes")
|
||||
return errorsmod.Wrap(errortypes.ErrorInvalidSigner, "signature length doesn't match typical [R||S||V] signature 65 bytes")
|
||||
}
|
||||
|
||||
// Remove the recovery offset if needed (ie. Metamask eip712 signature)
|
||||
@ -235,12 +242,12 @@ func VerifySignature(
|
||||
|
||||
feePayerPubkey, err := secp256k1.RecoverPubkey(sigHash, feePayerSig)
|
||||
if err != nil {
|
||||
return sdkerrors.Wrap(err, "failed to recover delegated fee payer from sig")
|
||||
return errorsmod.Wrap(err, "failed to recover delegated fee payer from sig")
|
||||
}
|
||||
|
||||
ecPubKey, err := ethcrypto.UnmarshalPubkey(feePayerPubkey)
|
||||
if err != nil {
|
||||
return sdkerrors.Wrap(err, "failed to unmarshal recovered fee payer pubkey")
|
||||
return errorsmod.Wrap(err, "failed to unmarshal recovered fee payer pubkey")
|
||||
}
|
||||
|
||||
pk := ðsecp256k1.PubKey{
|
||||
@ -248,23 +255,23 @@ func VerifySignature(
|
||||
}
|
||||
|
||||
if !pubKey.Equals(pk) {
|
||||
return sdkerrors.Wrapf(sdkerrors.ErrInvalidPubKey, "feePayer pubkey %s is different from transaction pubkey %s", pubKey, pk)
|
||||
return errorsmod.Wrapf(errortypes.ErrInvalidPubKey, "feePayer pubkey %s is different from transaction pubkey %s", pubKey, pk)
|
||||
}
|
||||
|
||||
recoveredFeePayerAcc := sdk.AccAddress(pk.Address().Bytes())
|
||||
|
||||
if !recoveredFeePayerAcc.Equals(feePayer) {
|
||||
return sdkerrors.Wrapf(sdkerrors.ErrorInvalidSigner, "failed to verify delegated fee payer %s signature", recoveredFeePayerAcc)
|
||||
return errorsmod.Wrapf(errortypes.ErrorInvalidSigner, "failed to verify delegated fee payer %s signature", recoveredFeePayerAcc)
|
||||
}
|
||||
|
||||
// VerifySignature of ethsecp256k1 accepts 64 byte signature [R||S]
|
||||
// WARNING! Under NO CIRCUMSTANCES try to use pubKey.VerifySignature there
|
||||
if !secp256k1.VerifySignature(pubKey.Bytes(), sigHash, feePayerSig[:len(feePayerSig)-1]) {
|
||||
return sdkerrors.Wrap(sdkerrors.ErrorInvalidSigner, "unable to verify signer signature of EIP712 typed data")
|
||||
return errorsmod.Wrap(errortypes.ErrorInvalidSigner, "unable to verify signer signature of EIP712 typed data")
|
||||
}
|
||||
|
||||
return nil
|
||||
default:
|
||||
return sdkerrors.Wrapf(sdkerrors.ErrTooManySignatures, "unexpected SignatureData %T", sigData)
|
||||
return errorsmod.Wrapf(errortypes.ErrTooManySignatures, "unexpected SignatureData %T", sigData)
|
||||
}
|
||||
}
|
||||
|
421
app/ante/eth.go
421
app/ante/eth.go
@ -1,19 +1,17 @@
|
||||
package ante
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math"
|
||||
"math/big"
|
||||
"strconv"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
sdkmath "cosmossdk.io/math"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
|
||||
ethermint "github.com/evmos/ethermint/types"
|
||||
evmkeeper "github.com/evmos/ethermint/x/evm/keeper"
|
||||
"github.com/evmos/ethermint/x/evm/keeper"
|
||||
"github.com/evmos/ethermint/x/evm/statedb"
|
||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||
|
||||
@ -21,60 +19,6 @@ import (
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
)
|
||||
|
||||
// EthSigVerificationDecorator validates an ethereum signatures
|
||||
type EthSigVerificationDecorator struct {
|
||||
evmKeeper EVMKeeper
|
||||
}
|
||||
|
||||
// NewEthSigVerificationDecorator creates a new EthSigVerificationDecorator
|
||||
func NewEthSigVerificationDecorator(ek EVMKeeper) EthSigVerificationDecorator {
|
||||
return EthSigVerificationDecorator{
|
||||
evmKeeper: ek,
|
||||
}
|
||||
}
|
||||
|
||||
// AnteHandle validates checks that the registered chain id is the same as the one on the message, and
|
||||
// that the signer address matches the one defined on the message.
|
||||
// It's not skipped for RecheckTx, because it set `From` address which is critical from other ante handler to work.
|
||||
// Failure in RecheckTx will prevent tx to be included into block, especially when CheckTx succeed, in which case user
|
||||
// won't see the error message.
|
||||
func (esvd EthSigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||
chainID := esvd.evmKeeper.ChainID()
|
||||
chainCfg := esvd.evmKeeper.GetChainConfig(ctx)
|
||||
ethCfg := chainCfg.EthereumConfig(chainID)
|
||||
blockNum := big.NewInt(ctx.BlockHeight())
|
||||
signer := ethtypes.MakeSigner(ethCfg, blockNum)
|
||||
|
||||
for _, msg := range tx.GetMsgs() {
|
||||
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||
if !ok {
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||
}
|
||||
|
||||
allowUnprotectedTxs := esvd.evmKeeper.GetAllowUnprotectedTxs(ctx)
|
||||
ethTx := msgEthTx.AsTransaction()
|
||||
if !allowUnprotectedTxs && !ethTx.Protected() {
|
||||
return ctx, sdkerrors.Wrapf(
|
||||
sdkerrors.ErrNotSupported,
|
||||
"rejected unprotected Ethereum txs. Please EIP155 sign your transaction to protect it against replay-attacks")
|
||||
}
|
||||
|
||||
sender, err := signer.Sender(ethTx)
|
||||
if err != nil {
|
||||
return ctx, sdkerrors.Wrapf(
|
||||
sdkerrors.ErrorInvalidSigner,
|
||||
"couldn't retrieve sender address from the ethereum transaction: %s",
|
||||
err.Error(),
|
||||
)
|
||||
}
|
||||
|
||||
// set up the sender to the transaction field if not already
|
||||
msgEthTx.From = sender.Hex()
|
||||
}
|
||||
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
// EthAccountVerificationDecorator validates an account balance checks
|
||||
type EthAccountVerificationDecorator struct {
|
||||
ak evmtypes.AccountKeeper
|
||||
@ -108,18 +52,18 @@ func (avd EthAccountVerificationDecorator) AnteHandle(
|
||||
for i, msg := range tx.GetMsgs() {
|
||||
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||
if !ok {
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||
return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||
}
|
||||
|
||||
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
|
||||
if err != nil {
|
||||
return ctx, sdkerrors.Wrapf(err, "failed to unpack tx data any for tx %d", i)
|
||||
return ctx, errorsmod.Wrapf(err, "failed to unpack tx data any for tx %d", i)
|
||||
}
|
||||
|
||||
// sender address should be in the tx cache from the previous AnteHandle call
|
||||
from := msgEthTx.GetFrom()
|
||||
if from.Empty() {
|
||||
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "from address cannot be empty")
|
||||
return ctx, errorsmod.Wrap(errortypes.ErrInvalidAddress, "from address cannot be empty")
|
||||
}
|
||||
|
||||
// check whether the sender address is EOA
|
||||
@ -131,12 +75,12 @@ func (avd EthAccountVerificationDecorator) AnteHandle(
|
||||
avd.ak.SetAccount(ctx, acc)
|
||||
acct = statedb.NewEmptyAccount()
|
||||
} else if acct.IsContract() {
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidType,
|
||||
return ctx, errorsmod.Wrapf(errortypes.ErrInvalidType,
|
||||
"the sender is not EOA: address %s, codeHash <%s>", fromAddr, acct.CodeHash)
|
||||
}
|
||||
|
||||
if err := evmkeeper.CheckSenderBalance(sdkmath.NewIntFromBigInt(acct.Balance), txData); err != nil {
|
||||
return ctx, sdkerrors.Wrap(err, "failed to check sender balance")
|
||||
if err := keeper.CheckSenderBalance(sdkmath.NewIntFromBigInt(acct.Balance), txData); err != nil {
|
||||
return ctx, errorsmod.Wrap(err, "failed to check sender balance")
|
||||
}
|
||||
}
|
||||
return next(ctx, tx, simulate)
|
||||
@ -164,7 +108,7 @@ func NewEthGasConsumeDecorator(
|
||||
// (during CheckTx only) and that the sender has enough balance to pay for the gas cost.
|
||||
//
|
||||
// Intrinsic gas for a transaction is the amount of gas that the transaction uses before the
|
||||
// transaction is executed. The gas is a constant value plus any cost inccured by additional bytes
|
||||
// transaction is executed. The gas is a constant value plus any cost incurred by additional bytes
|
||||
// of data supplied with the transaction.
|
||||
//
|
||||
// This AnteHandler decorator will fail if:
|
||||
@ -174,29 +118,36 @@ func NewEthGasConsumeDecorator(
|
||||
// - user doesn't have enough balance to deduct the transaction fees (gas_limit * gas_price)
|
||||
// - transaction or block gas meter runs out of gas
|
||||
// - sets the gas meter limit
|
||||
// - gas limit is greater than the block gas meter limit
|
||||
func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
|
||||
// gas consumption limit already checked during CheckTx so there's no need to
|
||||
// verify it again during ReCheckTx
|
||||
if ctx.IsReCheckTx() {
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
chainCfg := egcd.evmKeeper.GetChainConfig(ctx)
|
||||
ethCfg := chainCfg.EthereumConfig(egcd.evmKeeper.ChainID())
|
||||
|
||||
blockHeight := big.NewInt(ctx.BlockHeight())
|
||||
homestead := ethCfg.IsHomestead(blockHeight)
|
||||
istanbul := ethCfg.IsIstanbul(blockHeight)
|
||||
london := ethCfg.IsLondon(blockHeight)
|
||||
gasWanted := uint64(0)
|
||||
var events sdk.Events
|
||||
|
||||
// Use the lowest priority of all the messages as the final one.
|
||||
minPriority := int64(math.MaxInt64)
|
||||
baseFee := egcd.evmKeeper.GetBaseFee(ctx, ethCfg)
|
||||
|
||||
for _, msg := range tx.GetMsgs() {
|
||||
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||
if !ok {
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||
return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||
}
|
||||
|
||||
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
|
||||
if err != nil {
|
||||
return ctx, sdkerrors.Wrap(err, "failed to unpack tx data")
|
||||
return ctx, errorsmod.Wrap(err, "failed to unpack tx data")
|
||||
}
|
||||
|
||||
if ctx.IsCheckTx() && egcd.maxGasWanted != 0 {
|
||||
@ -211,45 +162,58 @@ func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
|
||||
}
|
||||
|
||||
evmDenom := egcd.evmKeeper.GetEVMDenom(ctx)
|
||||
fees, priority, err := egcd.evmKeeper.DeductTxCostsFromUserBalance(
|
||||
ctx,
|
||||
*msgEthTx,
|
||||
txData,
|
||||
evmDenom,
|
||||
homestead,
|
||||
istanbul,
|
||||
london,
|
||||
)
|
||||
|
||||
fees, err := keeper.VerifyFee(txData, evmDenom, baseFee, homestead, istanbul, ctx.IsCheckTx())
|
||||
if err != nil {
|
||||
return ctx, sdkerrors.Wrapf(err, "failed to deduct transaction costs from user balance")
|
||||
return ctx, errorsmod.Wrapf(err, "failed to verify the fees")
|
||||
}
|
||||
|
||||
events = append(events, sdk.NewEvent(sdk.EventTypeTx, sdk.NewAttribute(sdk.AttributeKeyFee, fees.String())))
|
||||
err = egcd.evmKeeper.DeductTxCostsFromUserBalance(ctx, fees, common.HexToAddress(msgEthTx.From))
|
||||
if err != nil {
|
||||
return ctx, errorsmod.Wrapf(err, "failed to deduct transaction costs from user balance")
|
||||
}
|
||||
|
||||
events = append(events,
|
||||
sdk.NewEvent(
|
||||
sdk.EventTypeTx,
|
||||
sdk.NewAttribute(sdk.AttributeKeyFee, fees.String()),
|
||||
),
|
||||
)
|
||||
|
||||
priority := evmtypes.GetTxPriority(txData, baseFee)
|
||||
|
||||
if priority < minPriority {
|
||||
minPriority = priority
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: change to typed events
|
||||
ctx.EventManager().EmitEvents(events)
|
||||
|
||||
// TODO: deprecate after https://github.com/cosmos/cosmos-sdk/issues/9514 is fixed on SDK
|
||||
blockGasLimit := ethermint.BlockGasLimit(ctx)
|
||||
|
||||
// NOTE: safety check
|
||||
if blockGasLimit > 0 {
|
||||
// generate a copy of the gas pool (i.e block gas meter) to see if we've run out of gas for this block
|
||||
// if current gas consumed is greater than the limit, this funcion panics and the error is recovered on the Baseapp
|
||||
gasPool := sdk.NewGasMeter(blockGasLimit)
|
||||
gasPool.ConsumeGas(ctx.GasMeter().GasConsumedToLimit(), "gas pool check")
|
||||
// return error if the tx gas is greater than the block limit (max gas)
|
||||
|
||||
// NOTE: it's important here to use the gas wanted instead of the gas consumed
|
||||
// from the tx gas pool. The later only has the value so far since the
|
||||
// EthSetupContextDecorator so it will never exceed the block gas limit.
|
||||
if gasWanted > blockGasLimit {
|
||||
return ctx, errorsmod.Wrapf(
|
||||
errortypes.ErrOutOfGas,
|
||||
"tx gas (%d) exceeds block gas limit (%d)",
|
||||
gasWanted,
|
||||
blockGasLimit,
|
||||
)
|
||||
}
|
||||
|
||||
// Set ctx.GasMeter with a limit of GasWanted (gasLimit)
|
||||
gasConsumed := ctx.GasMeter().GasConsumed()
|
||||
ctx = ctx.WithGasMeter(ethermint.NewInfiniteGasMeterWithLimit(gasWanted))
|
||||
ctx.GasMeter().ConsumeGas(gasConsumed, "copy gas consumed")
|
||||
// Set tx GasMeter with a limit of GasWanted (i.e gas limit from the Ethereum tx).
|
||||
// The gas consumed will be then reset to the gas used by the state transition
|
||||
// in the EVM.
|
||||
|
||||
newCtx := ctx.WithPriority(minPriority)
|
||||
// FIXME: use a custom gas configuration that doesn't add any additional gas and only
|
||||
// takes into account the gas consumed at the end of the EVM transaction.
|
||||
newCtx := ctx.
|
||||
WithGasMeter(ethermint.NewInfiniteGasMeterWithLimit(gasWanted)).
|
||||
WithPriority(minPriority)
|
||||
|
||||
// we know that we have enough gas on the pool to cover the intrinsic gas
|
||||
return next(newCtx, tx, simulate)
|
||||
@ -278,19 +242,35 @@ func (ctd CanTransferDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate
|
||||
for _, msg := range tx.GetMsgs() {
|
||||
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||
if !ok {
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||
return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||
}
|
||||
|
||||
baseFee := ctd.evmKeeper.GetBaseFee(ctx, ethCfg)
|
||||
|
||||
coreMsg, err := msgEthTx.AsMessage(signer, baseFee)
|
||||
if err != nil {
|
||||
return ctx, sdkerrors.Wrapf(
|
||||
return ctx, errorsmod.Wrapf(
|
||||
err,
|
||||
"failed to create an ethereum core.Message from signer %T", signer,
|
||||
)
|
||||
}
|
||||
|
||||
if evmtypes.IsLondon(ethCfg, ctx.BlockHeight()) {
|
||||
if baseFee == nil {
|
||||
return ctx, errorsmod.Wrap(
|
||||
evmtypes.ErrInvalidBaseFee,
|
||||
"base fee is supported but evm block context value is nil",
|
||||
)
|
||||
}
|
||||
if coreMsg.GasFeeCap().Cmp(baseFee) < 0 {
|
||||
return ctx, errorsmod.Wrapf(
|
||||
errortypes.ErrInsufficientFee,
|
||||
"max fee per gas less than block base fee (%s < %s)",
|
||||
coreMsg.GasFeeCap(), baseFee,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: pass in an empty coinbase address and nil tracer as we don't need them for the check below
|
||||
cfg := &evmtypes.EVMConfig{
|
||||
ChainConfig: ethCfg,
|
||||
@ -304,29 +284,13 @@ func (ctd CanTransferDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate
|
||||
// check that caller has enough balance to cover asset transfer for **topmost** call
|
||||
// NOTE: here the gas consumed is from the context with the infinite gas meter
|
||||
if coreMsg.Value().Sign() > 0 && !evm.Context().CanTransfer(stateDB, coreMsg.From(), coreMsg.Value()) {
|
||||
return ctx, sdkerrors.Wrapf(
|
||||
sdkerrors.ErrInsufficientFunds,
|
||||
return ctx, errorsmod.Wrapf(
|
||||
errortypes.ErrInsufficientFunds,
|
||||
"failed to transfer %s from address %s using the EVM block context transfer function",
|
||||
coreMsg.Value(),
|
||||
coreMsg.From(),
|
||||
)
|
||||
}
|
||||
|
||||
if evmtypes.IsLondon(ethCfg, ctx.BlockHeight()) {
|
||||
if baseFee == nil {
|
||||
return ctx, sdkerrors.Wrap(
|
||||
evmtypes.ErrInvalidBaseFee,
|
||||
"base fee is supported but evm block context value is nil",
|
||||
)
|
||||
}
|
||||
if coreMsg.GasFeeCap().Cmp(baseFee) < 0 {
|
||||
return ctx, sdkerrors.Wrapf(
|
||||
sdkerrors.ErrInsufficientFee,
|
||||
"max fee per gas less than block base fee (%s < %s)",
|
||||
coreMsg.GasFeeCap(), baseFee,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return next(ctx, tx, simulate)
|
||||
@ -351,19 +315,19 @@ func (issd EthIncrementSenderSequenceDecorator) AnteHandle(ctx sdk.Context, tx s
|
||||
for _, msg := range tx.GetMsgs() {
|
||||
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||
if !ok {
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||
return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||
}
|
||||
|
||||
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
|
||||
if err != nil {
|
||||
return ctx, sdkerrors.Wrap(err, "failed to unpack tx data")
|
||||
return ctx, errorsmod.Wrap(err, "failed to unpack tx data")
|
||||
}
|
||||
|
||||
// increase sequence of sender
|
||||
acc := issd.ak.GetAccount(ctx, msgEthTx.GetFrom())
|
||||
if acc == nil {
|
||||
return ctx, sdkerrors.Wrapf(
|
||||
sdkerrors.ErrUnknownAddress,
|
||||
return ctx, errorsmod.Wrapf(
|
||||
errortypes.ErrUnknownAddress,
|
||||
"account %s is nil", common.BytesToAddress(msgEthTx.GetFrom().Bytes()),
|
||||
)
|
||||
}
|
||||
@ -372,14 +336,14 @@ func (issd EthIncrementSenderSequenceDecorator) AnteHandle(ctx sdk.Context, tx s
|
||||
// we merged the nonce verification to nonce increment, so when tx includes multiple messages
|
||||
// with same sender, they'll be accepted.
|
||||
if txData.GetNonce() != nonce {
|
||||
return ctx, sdkerrors.Wrapf(
|
||||
sdkerrors.ErrInvalidSequence,
|
||||
return ctx, errorsmod.Wrapf(
|
||||
errortypes.ErrInvalidSequence,
|
||||
"invalid nonce; got %d, expected %d", txData.GetNonce(), nonce,
|
||||
)
|
||||
}
|
||||
|
||||
if err := acc.SetSequence(nonce + 1); err != nil {
|
||||
return ctx, sdkerrors.Wrapf(err, "failed to set sequence to %d", acc.GetSequence()+1)
|
||||
return ctx, errorsmod.Wrapf(err, "failed to set sequence to %d", acc.GetSequence()+1)
|
||||
}
|
||||
|
||||
issd.ak.SetAccount(ctx, acc)
|
||||
@ -387,220 +351,3 @@ func (issd EthIncrementSenderSequenceDecorator) AnteHandle(ctx sdk.Context, tx s
|
||||
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
// EthValidateBasicDecorator is adapted from ValidateBasicDecorator from cosmos-sdk, it ignores ErrNoSignatures
|
||||
type EthValidateBasicDecorator struct {
|
||||
evmKeeper EVMKeeper
|
||||
}
|
||||
|
||||
// NewEthValidateBasicDecorator creates a new EthValidateBasicDecorator
|
||||
func NewEthValidateBasicDecorator(ek EVMKeeper) EthValidateBasicDecorator {
|
||||
return EthValidateBasicDecorator{
|
||||
evmKeeper: ek,
|
||||
}
|
||||
}
|
||||
|
||||
// AnteHandle handles basic validation of tx
|
||||
func (vbd EthValidateBasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
|
||||
// no need to validate basic on recheck tx, call next antehandler
|
||||
if ctx.IsReCheckTx() {
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
err := tx.ValidateBasic()
|
||||
// ErrNoSignatures is fine with eth tx
|
||||
if err != nil && !errors.Is(err, sdkerrors.ErrNoSignatures) {
|
||||
return ctx, sdkerrors.Wrap(err, "tx basic validation failed")
|
||||
}
|
||||
|
||||
// For eth type cosmos tx, some fields should be veified as zero values,
|
||||
// since we will only verify the signature against the hash of the MsgEthereumTx.Data
|
||||
wrapperTx, ok := tx.(protoTxProvider)
|
||||
if !ok {
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid tx type %T, didn't implement interface protoTxProvider", tx)
|
||||
}
|
||||
|
||||
protoTx := wrapperTx.GetProtoTx()
|
||||
body := protoTx.Body
|
||||
if body.Memo != "" || body.TimeoutHeight != uint64(0) || len(body.NonCriticalExtensionOptions) > 0 {
|
||||
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest,
|
||||
"for eth tx body Memo TimeoutHeight NonCriticalExtensionOptions should be empty")
|
||||
}
|
||||
|
||||
if len(body.ExtensionOptions) != 1 {
|
||||
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx length of ExtensionOptions should be 1")
|
||||
}
|
||||
|
||||
txFee := sdk.Coins{}
|
||||
txGasLimit := uint64(0)
|
||||
|
||||
chainCfg := vbd.evmKeeper.GetChainConfig(ctx)
|
||||
chainID := vbd.evmKeeper.ChainID()
|
||||
ethCfg := chainCfg.EthereumConfig(chainID)
|
||||
baseFee := vbd.evmKeeper.GetBaseFee(ctx, ethCfg)
|
||||
enableCreate := vbd.evmKeeper.GetEnableCreate(ctx)
|
||||
enableCall := vbd.evmKeeper.GetEnableCall(ctx)
|
||||
evmDenom := vbd.evmKeeper.GetEVMDenom(ctx)
|
||||
|
||||
for _, msg := range protoTx.GetMsgs() {
|
||||
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||
if !ok {
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||
}
|
||||
|
||||
// Validate `From` field
|
||||
if msgEthTx.From != "" {
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid From %s, expect empty string", msgEthTx.From)
|
||||
}
|
||||
|
||||
txGasLimit += msgEthTx.GetGas()
|
||||
|
||||
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
|
||||
if err != nil {
|
||||
return ctx, sdkerrors.Wrap(err, "failed to unpack MsgEthereumTx Data")
|
||||
}
|
||||
|
||||
// return error if contract creation or call are disabled through governance
|
||||
if !enableCreate && txData.GetTo() == nil {
|
||||
return ctx, sdkerrors.Wrap(evmtypes.ErrCreateDisabled, "failed to create new contract")
|
||||
} else if !enableCall && txData.GetTo() != nil {
|
||||
return ctx, sdkerrors.Wrap(evmtypes.ErrCallDisabled, "failed to call contract")
|
||||
}
|
||||
|
||||
if baseFee == nil && txData.TxType() == ethtypes.DynamicFeeTxType {
|
||||
return ctx, sdkerrors.Wrap(ethtypes.ErrTxTypeNotSupported, "dynamic fee tx not supported")
|
||||
}
|
||||
|
||||
txFee = txFee.Add(sdk.NewCoin(evmDenom, sdkmath.NewIntFromBigInt(txData.Fee())))
|
||||
}
|
||||
|
||||
authInfo := protoTx.AuthInfo
|
||||
if len(authInfo.SignerInfos) > 0 {
|
||||
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx AuthInfo SignerInfos should be empty")
|
||||
}
|
||||
|
||||
if authInfo.Fee.Payer != "" || authInfo.Fee.Granter != "" {
|
||||
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx AuthInfo Fee payer and granter should be empty")
|
||||
}
|
||||
|
||||
if !authInfo.Fee.Amount.IsEqual(txFee) {
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid AuthInfo Fee Amount (%s != %s)", authInfo.Fee.Amount, txFee)
|
||||
}
|
||||
|
||||
if authInfo.Fee.GasLimit != txGasLimit {
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid AuthInfo Fee GasLimit (%d != %d)", authInfo.Fee.GasLimit, txGasLimit)
|
||||
}
|
||||
|
||||
sigs := protoTx.Signatures
|
||||
if len(sigs) > 0 {
|
||||
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx Signatures should be empty")
|
||||
}
|
||||
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
// EthSetupContextDecorator is adapted from SetUpContextDecorator from cosmos-sdk, it ignores gas consumption
|
||||
// by setting the gas meter to infinite
|
||||
type EthSetupContextDecorator struct {
|
||||
evmKeeper EVMKeeper
|
||||
}
|
||||
|
||||
func NewEthSetUpContextDecorator(evmKeeper EVMKeeper) EthSetupContextDecorator {
|
||||
return EthSetupContextDecorator{
|
||||
evmKeeper: evmKeeper,
|
||||
}
|
||||
}
|
||||
|
||||
func (esc EthSetupContextDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||
// all transactions must implement GasTx
|
||||
_, ok := tx.(authante.GasTx)
|
||||
if !ok {
|
||||
return newCtx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be GasTx")
|
||||
}
|
||||
|
||||
newCtx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
|
||||
// Reset transient gas used to prepare the execution of current cosmos tx.
|
||||
// Transient gas-used is necessary to sum the gas-used of cosmos tx, when it contains multiple eth msgs.
|
||||
esc.evmKeeper.ResetTransientGasUsed(ctx)
|
||||
return next(newCtx, tx, simulate)
|
||||
}
|
||||
|
||||
// EthMempoolFeeDecorator will check if the transaction's effective fee is at least as large
|
||||
// as the local validator's minimum gasFee (defined in validator config).
|
||||
// If fee is too low, decorator returns error and tx is rejected from mempool.
|
||||
// Note this only applies when ctx.CheckTx = true
|
||||
// If fee is high enough or not CheckTx, then call next AnteHandler
|
||||
// CONTRACT: Tx must implement FeeTx to use MempoolFeeDecorator
|
||||
type EthMempoolFeeDecorator struct {
|
||||
evmKeeper EVMKeeper
|
||||
}
|
||||
|
||||
func NewEthMempoolFeeDecorator(ek EVMKeeper) EthMempoolFeeDecorator {
|
||||
return EthMempoolFeeDecorator{
|
||||
evmKeeper: ek,
|
||||
}
|
||||
}
|
||||
|
||||
// AnteHandle ensures that the provided fees meet a minimum threshold for the validator,
|
||||
// if this is a CheckTx. This is only for local mempool purposes, and thus
|
||||
// is only ran on check tx.
|
||||
// It only do the check if london hardfork not enabled or feemarket not enabled, because in that case feemarket will take over the task.
|
||||
func (mfd EthMempoolFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||
if ctx.IsCheckTx() && !simulate {
|
||||
chainCfg := mfd.evmKeeper.GetChainConfig(ctx)
|
||||
ethCfg := chainCfg.EthereumConfig(mfd.evmKeeper.ChainID())
|
||||
baseFee := mfd.evmKeeper.GetBaseFee(ctx, ethCfg)
|
||||
evmDenom := mfd.evmKeeper.GetEVMDenom(ctx)
|
||||
|
||||
if baseFee == nil {
|
||||
for _, msg := range tx.GetMsgs() {
|
||||
ethMsg, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||
if !ok {
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||
}
|
||||
|
||||
feeAmt := ethMsg.GetFee()
|
||||
glDec := sdk.NewDec(int64(ethMsg.GetGas()))
|
||||
requiredFee := ctx.MinGasPrices().AmountOf(evmDenom).Mul(glDec)
|
||||
if sdk.NewDecFromBigInt(feeAmt).LT(requiredFee) {
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "insufficient fees; got: %s required: %s", feeAmt, requiredFee)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
// EthEmitEventDecorator emit events in ante handler in case of tx execution failed (out of block gas limit).
|
||||
type EthEmitEventDecorator struct {
|
||||
evmKeeper EVMKeeper
|
||||
}
|
||||
|
||||
// NewEthEmitEventDecorator creates a new EthEmitEventDecorator
|
||||
func NewEthEmitEventDecorator(evmKeeper EVMKeeper) EthEmitEventDecorator {
|
||||
return EthEmitEventDecorator{evmKeeper}
|
||||
}
|
||||
|
||||
// AnteHandle emits some basic events for the eth messages
|
||||
func (eeed EthEmitEventDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||
// After eth tx passed ante handler, the fee is deducted and nonce increased, it shouldn't be ignored by json-rpc,
|
||||
// we need to emit some basic events at the very end of ante handler to be indexed by tendermint.
|
||||
txIndex := eeed.evmKeeper.GetTxIndexTransient(ctx)
|
||||
for i, msg := range tx.GetMsgs() {
|
||||
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||
if !ok {
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||
}
|
||||
|
||||
// emit ethereum tx hash as event, should be indexed by tm tx indexer for query purpose.
|
||||
// it's emitted in ante handler so we can query failed transaction (out of block gas limit).
|
||||
ctx.EventManager().EmitEvent(sdk.NewEvent(
|
||||
evmtypes.EventTypeEthereumTx,
|
||||
sdk.NewAttribute(evmtypes.AttributeKeyEthereumTxHash, msgEthTx.Hash),
|
||||
sdk.NewAttribute(evmtypes.AttributeKeyTxIndex, strconv.FormatUint(txIndex+uint64(i), 10)),
|
||||
))
|
||||
}
|
||||
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
@ -15,59 +15,6 @@ import (
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
)
|
||||
|
||||
func (suite AnteTestSuite) TestEthSigVerificationDecorator() {
|
||||
addr, privKey := tests.NewAddrKey()
|
||||
|
||||
signedTx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
|
||||
signedTx.From = addr.Hex()
|
||||
err := signedTx.Sign(suite.ethSigner, tests.NewSigner(privKey))
|
||||
suite.Require().NoError(err)
|
||||
|
||||
unprotectedTx := evmtypes.NewTxContract(nil, 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
|
||||
unprotectedTx.From = addr.Hex()
|
||||
err = unprotectedTx.Sign(ethtypes.HomesteadSigner{}, tests.NewSigner(privKey))
|
||||
suite.Require().NoError(err)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
tx sdk.Tx
|
||||
allowUnprotectedTxs bool
|
||||
reCheckTx bool
|
||||
expPass bool
|
||||
}{
|
||||
{"ReCheckTx", &invalidTx{}, false, true, false},
|
||||
{"invalid transaction type", &invalidTx{}, false, false, false},
|
||||
{
|
||||
"invalid sender",
|
||||
evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 1, &addr, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil),
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
},
|
||||
{"successful signature verification", signedTx, false, false, true},
|
||||
{"invalid, reject unprotected txs", unprotectedTx, false, false, false},
|
||||
{"successful, allow unprotected txs", unprotectedTx, true, false, true},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.evmParamsOption = func(params *evmtypes.Params) {
|
||||
params.AllowUnprotectedTxs = tc.allowUnprotectedTxs
|
||||
}
|
||||
suite.SetupTest()
|
||||
dec := ante.NewEthSigVerificationDecorator(suite.app.EvmKeeper)
|
||||
_, err := dec.AnteHandle(suite.ctx.WithIsReCheckTx(tc.reCheckTx), tc.tx, false, NextFn)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
suite.evmParamsOption = nil
|
||||
}
|
||||
|
||||
func (suite AnteTestSuite) TestNewEthAccountVerificationDecorator() {
|
||||
dec := ante.NewEthAccountVerificationDecorator(
|
||||
suite.app.AccountKeeper, suite.app.EvmKeeper,
|
||||
@ -521,33 +468,3 @@ func (suite AnteTestSuite) TestEthIncrementSenderSequenceDecorator() {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite AnteTestSuite) TestEthSetupContextDecorator() {
|
||||
dec := ante.NewEthSetUpContextDecorator(suite.app.EvmKeeper)
|
||||
tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
tx sdk.Tx
|
||||
expPass bool
|
||||
}{
|
||||
{"invalid transaction type - does not implement GasTx", &invalidTx{}, false},
|
||||
{
|
||||
"success - transaction implement GasTx",
|
||||
tx,
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
_, err := dec.AnteHandle(suite.ctx, tc.tx, false, NextFn)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -4,10 +4,11 @@ import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
sdkmath "cosmossdk.io/math"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||
ethermint "github.com/evmos/ethermint/types"
|
||||
"github.com/evmos/ethermint/x/evm/types"
|
||||
@ -64,7 +65,7 @@ func NewDynamicFeeChecker(k DynamicFeeEVMKeeper) authante.TxFeeChecker {
|
||||
baseFeeInt := sdkmath.NewIntFromBigInt(baseFee)
|
||||
|
||||
if feeCap.LT(baseFeeInt) {
|
||||
return nil, 0, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "insufficient gas prices; got: %s required: %s", feeCap, baseFeeInt)
|
||||
return nil, 0, errorsmod.Wrapf(errortypes.ErrInsufficientFee, "insufficient gas prices; got: %s required: %s", feeCap, baseFeeInt)
|
||||
}
|
||||
|
||||
// calculate the effective gas price using the EIP-1559 logic.
|
||||
@ -112,7 +113,7 @@ func checkTxFeeWithValidatorMinGasPrices(ctx sdk.Context, tx sdk.FeeTx) (sdk.Coi
|
||||
}
|
||||
|
||||
if !feeCoins.IsAnyGTE(requiredFees) {
|
||||
return nil, 0, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "insufficient fees; got: %s required: %s", feeCoins, requiredFees)
|
||||
return nil, 0, errorsmod.Wrapf(errortypes.ErrInsufficientFee, "insufficient fees; got: %s required: %s", feeCoins, requiredFees)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,8 +3,8 @@ package ante
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
)
|
||||
|
||||
// GasWantedDecorator keeps track of the gasWanted amount on the current block in transient store
|
||||
@ -44,7 +44,7 @@ func (gwd GasWantedDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bo
|
||||
// Add total gasWanted to cumulative in block transientStore in FeeMarket module
|
||||
if isBaseFeeEnabled {
|
||||
if _, err := gwd.feeMarketKeeper.AddTransientGasWanted(ctx, gasWanted); err != nil {
|
||||
return ctx, sdkerrors.Wrapf(err, "failed to add gas wanted to transient store")
|
||||
return ctx, errorsmod.Wrapf(err, "failed to add gas wanted to transient store")
|
||||
}
|
||||
}
|
||||
|
||||
|
110
app/ante/fees.go
110
app/ante/fees.go
@ -3,8 +3,9 @@ package ante
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||
@ -20,14 +21,50 @@ type MinGasPriceDecorator struct {
|
||||
evmKeeper EVMKeeper
|
||||
}
|
||||
|
||||
// EthMinGasPriceDecorator will check if the transaction's fee is at least as large
|
||||
// as the MinGasPrices param. If fee is too low, decorator returns error and tx
|
||||
// is rejected. This applies to both CheckTx and DeliverTx and regardless
|
||||
// if London hard fork or fee market params (EIP-1559) are enabled.
|
||||
// If fee is high enough, then call next AnteHandler
|
||||
type EthMinGasPriceDecorator struct {
|
||||
feesKeeper FeeMarketKeeper
|
||||
evmKeeper EVMKeeper
|
||||
}
|
||||
|
||||
// EthMempoolFeeDecorator will check if the transaction's effective fee is at least as large
|
||||
// as the local validator's minimum gasFee (defined in validator config).
|
||||
// If fee is too low, decorator returns error and tx is rejected from mempool.
|
||||
// Note this only applies when ctx.CheckTx = true
|
||||
// If fee is high enough or not CheckTx, then call next AnteHandler
|
||||
// CONTRACT: Tx must implement FeeTx to use MempoolFeeDecorator
|
||||
type EthMempoolFeeDecorator struct {
|
||||
evmKeeper EVMKeeper
|
||||
}
|
||||
|
||||
// NewMinGasPriceDecorator creates a new MinGasPriceDecorator instance used only for
|
||||
// Cosmos transactions.
|
||||
func NewMinGasPriceDecorator(fk FeeMarketKeeper, ek EVMKeeper) MinGasPriceDecorator {
|
||||
return MinGasPriceDecorator{feesKeeper: fk, evmKeeper: ek}
|
||||
}
|
||||
|
||||
// NewEthMinGasPriceDecorator creates a new MinGasPriceDecorator instance used only for
|
||||
// Ethereum transactions.
|
||||
func NewEthMinGasPriceDecorator(fk FeeMarketKeeper, ek EVMKeeper) EthMinGasPriceDecorator {
|
||||
return EthMinGasPriceDecorator{feesKeeper: fk, evmKeeper: ek}
|
||||
}
|
||||
|
||||
// NewEthMempoolFeeDecorator creates a new NewEthMempoolFeeDecorator instance used only for
|
||||
// Ethereum transactions.
|
||||
func NewEthMempoolFeeDecorator(ek EVMKeeper) EthMempoolFeeDecorator {
|
||||
return EthMempoolFeeDecorator{
|
||||
evmKeeper: ek,
|
||||
}
|
||||
}
|
||||
|
||||
func (mpd MinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||
feeTx, ok := tx.(sdk.FeeTx)
|
||||
if !ok {
|
||||
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx")
|
||||
return ctx, errorsmod.Wrapf(errortypes.ErrInvalidType, "invalid transaction type %T, expected sdk.FeeTx", tx)
|
||||
}
|
||||
|
||||
minGasPrice := mpd.feesKeeper.GetParams(ctx).MinGasPrice
|
||||
@ -62,7 +99,7 @@ func (mpd MinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate
|
||||
}
|
||||
|
||||
if !feeCoins.IsAnyGTE(requiredFees) {
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee,
|
||||
return ctx, errorsmod.Wrapf(errortypes.ErrInsufficientFee,
|
||||
"provided fee < minimum global fee (%s < %s). Please increase the gas price.",
|
||||
feeCoins,
|
||||
requiredFees)
|
||||
@ -71,20 +108,8 @@ func (mpd MinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
// EthMinGasPriceDecorator will check if the transaction's fee is at least as large
|
||||
// as the MinGasPrices param. If fee is too low, decorator returns error and tx
|
||||
// is rejected. This applies to both CheckTx and DeliverTx and regardless
|
||||
// if London hard fork or fee market params (EIP-1559) are enabled.
|
||||
// If fee is high enough, then call next AnteHandler
|
||||
type EthMinGasPriceDecorator struct {
|
||||
feesKeeper FeeMarketKeeper
|
||||
evmKeeper EVMKeeper
|
||||
}
|
||||
|
||||
func NewEthMinGasPriceDecorator(fk FeeMarketKeeper, ek EVMKeeper) EthMinGasPriceDecorator {
|
||||
return EthMinGasPriceDecorator{feesKeeper: fk, evmKeeper: ek}
|
||||
}
|
||||
|
||||
// AnteHandle ensures that the that the effective fee from the transaction is greater than the
|
||||
// minimum global fee, which is defined by the MinGasPrice (parameter) * GasLimit (tx argument).
|
||||
func (empd EthMinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||
minGasPrice := empd.feesKeeper.GetParams(ctx).MinGasPrice
|
||||
|
||||
@ -100,8 +125,8 @@ func (empd EthMinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simul
|
||||
for _, msg := range tx.GetMsgs() {
|
||||
ethMsg, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||
if !ok {
|
||||
return ctx, sdkerrors.Wrapf(
|
||||
sdkerrors.ErrUnknownRequest,
|
||||
return ctx, errorsmod.Wrapf(
|
||||
errortypes.ErrUnknownRequest,
|
||||
"invalid message type %T, expected %T",
|
||||
msg, (*evmtypes.MsgEthereumTx)(nil),
|
||||
)
|
||||
@ -120,7 +145,7 @@ func (empd EthMinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simul
|
||||
|
||||
txData, err := evmtypes.UnpackTxData(ethMsg.Data)
|
||||
if err != nil {
|
||||
return ctx, sdkerrors.Wrapf(err, "failed to unpack tx data %s", ethMsg.Hash)
|
||||
return ctx, errorsmod.Wrapf(err, "failed to unpack tx data %s", ethMsg.Hash)
|
||||
}
|
||||
|
||||
if txData.TxType() != ethtypes.LegacyTxType {
|
||||
@ -133,8 +158,8 @@ func (empd EthMinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simul
|
||||
fee := sdk.NewDecFromBigInt(feeAmt)
|
||||
|
||||
if fee.LT(requiredFee) {
|
||||
return ctx, sdkerrors.Wrapf(
|
||||
sdkerrors.ErrInsufficientFee,
|
||||
return ctx, errorsmod.Wrapf(
|
||||
errortypes.ErrInsufficientFee,
|
||||
"provided fee < minimum global fee (%d < %d). Please increase the priority tip (for EIP-1559 txs) or the gas prices (for access list or legacy txs)", //nolint:lll
|
||||
fee.TruncateInt().Int64(), requiredFee.TruncateInt().Int64(),
|
||||
)
|
||||
@ -143,3 +168,44 @@ func (empd EthMinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simul
|
||||
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
// AnteHandle ensures that the provided fees meet a minimum threshold for the validator.
|
||||
// This check only for local mempool purposes, and thus it is only run on (Re)CheckTx.
|
||||
// The logic is also skipped if the London hard fork and EIP-1559 are enabled.
|
||||
func (mfd EthMempoolFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||
if !ctx.IsCheckTx() || simulate {
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
chainCfg := mfd.evmKeeper.GetChainConfig(ctx)
|
||||
ethCfg := chainCfg.EthereumConfig(mfd.evmKeeper.ChainID())
|
||||
|
||||
baseFee := mfd.evmKeeper.GetBaseFee(ctx, ethCfg)
|
||||
// skip check as the London hard fork and EIP-1559 are enabled
|
||||
if baseFee != nil {
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
evmDenom := mfd.evmKeeper.GetEVMDenom(ctx)
|
||||
minGasPrice := ctx.MinGasPrices().AmountOf(evmDenom)
|
||||
|
||||
for _, msg := range tx.GetMsgs() {
|
||||
ethMsg, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||
if !ok {
|
||||
return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||
}
|
||||
|
||||
fee := sdk.NewDecFromBigInt(ethMsg.GetFee())
|
||||
gasLimit := sdk.NewDecFromBigInt(new(big.Int).SetUint64(ethMsg.GetGas()))
|
||||
requiredFee := minGasPrice.Mul(gasLimit)
|
||||
|
||||
if fee.LT(requiredFee) {
|
||||
return ctx, errorsmod.Wrapf(
|
||||
errortypes.ErrInsufficientFee,
|
||||
"insufficient fee; got: %s required: %s",
|
||||
fee, requiredFee,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ func (s AnteTestSuite) TestMinGasPriceDecorator() {
|
||||
return &invalidTx{}
|
||||
},
|
||||
false,
|
||||
"must be a FeeTx",
|
||||
"invalid transaction type",
|
||||
false,
|
||||
},
|
||||
{
|
||||
@ -345,3 +345,7 @@ func (s AnteTestSuite) TestEthMinGasPriceDecorator() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (suite AnteTestSuite) TestEthMempoolFeeDecorator() {
|
||||
// TODO: add test
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
package ante
|
||||
|
||||
import (
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||
@ -32,19 +33,19 @@ type HandlerOptions struct {
|
||||
|
||||
func (options HandlerOptions) validate() error {
|
||||
if options.AccountKeeper == nil {
|
||||
return sdkerrors.Wrap(sdkerrors.ErrLogic, "account keeper is required for AnteHandler")
|
||||
return errorsmod.Wrap(errortypes.ErrLogic, "account keeper is required for AnteHandler")
|
||||
}
|
||||
if options.BankKeeper == nil {
|
||||
return sdkerrors.Wrap(sdkerrors.ErrLogic, "bank keeper is required for AnteHandler")
|
||||
return errorsmod.Wrap(errortypes.ErrLogic, "bank keeper is required for AnteHandler")
|
||||
}
|
||||
if options.SignModeHandler == nil {
|
||||
return sdkerrors.Wrap(sdkerrors.ErrLogic, "sign mode handler is required for ante builder")
|
||||
return errorsmod.Wrap(errortypes.ErrLogic, "sign mode handler is required for ante builder")
|
||||
}
|
||||
if options.FeeMarketKeeper == nil {
|
||||
return sdkerrors.Wrap(sdkerrors.ErrLogic, "fee market keeper is required for AnteHandler")
|
||||
return errorsmod.Wrap(errortypes.ErrLogic, "fee market keeper is required for AnteHandler")
|
||||
}
|
||||
if options.EvmKeeper == nil {
|
||||
return sdkerrors.Wrap(sdkerrors.ErrLogic, "evm keeper is required for AnteHandler")
|
||||
return errorsmod.Wrap(errortypes.ErrLogic, "evm keeper is required for AnteHandler")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -28,9 +28,7 @@ type EVMKeeper interface {
|
||||
DynamicFeeEVMKeeper
|
||||
|
||||
NewEVM(ctx sdk.Context, msg core.Message, cfg *evmtypes.EVMConfig, tracer vm.EVMLogger, stateDB vm.StateDB) evm.EVM
|
||||
DeductTxCostsFromUserBalance(
|
||||
ctx sdk.Context, msgEthTx evmtypes.MsgEthereumTx, txData evmtypes.TxData, denom string, homestead, istanbul, london bool,
|
||||
) (fees sdk.Coins, priority int64, err error)
|
||||
DeductTxCostsFromUserBalance(ctx sdk.Context, fees sdk.Coins, from common.Address) error
|
||||
GetBalance(ctx sdk.Context, addr common.Address) *big.Int
|
||||
ResetTransientGasUsed(ctx sdk.Context)
|
||||
GetTxIndexTransient(ctx sdk.Context) uint64
|
||||
|
@ -1,8 +1,9 @@
|
||||
package ante
|
||||
|
||||
import (
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||
)
|
||||
|
||||
@ -15,8 +16,8 @@ type RejectMessagesDecorator struct{}
|
||||
func (rmd RejectMessagesDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||
for _, msg := range tx.GetMsgs() {
|
||||
if _, ok := msg.(*evmtypes.MsgEthereumTx); ok {
|
||||
return ctx, sdkerrors.Wrapf(
|
||||
sdkerrors.ErrInvalidType,
|
||||
return ctx, errorsmod.Wrapf(
|
||||
errortypes.ErrInvalidType,
|
||||
"MsgEthereumTx needs to be contained within a tx with 'ExtensionOptionsEthereumTx' option",
|
||||
)
|
||||
}
|
||||
|
189
app/ante/setup.go
Normal file
189
app/ante/setup.go
Normal file
@ -0,0 +1,189 @@
|
||||
package ante
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
sdkmath "cosmossdk.io/math"
|
||||
storetypes "github.com/cosmos/cosmos-sdk/store/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||
)
|
||||
|
||||
// EthSetupContextDecorator is adapted from SetUpContextDecorator from cosmos-sdk, it ignores gas consumption
|
||||
// by setting the gas meter to infinite
|
||||
type EthSetupContextDecorator struct {
|
||||
evmKeeper EVMKeeper
|
||||
}
|
||||
|
||||
func NewEthSetUpContextDecorator(evmKeeper EVMKeeper) EthSetupContextDecorator {
|
||||
return EthSetupContextDecorator{
|
||||
evmKeeper: evmKeeper,
|
||||
}
|
||||
}
|
||||
|
||||
func (esc EthSetupContextDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||
// all transactions must implement GasTx
|
||||
_, ok := tx.(authante.GasTx)
|
||||
if !ok {
|
||||
return ctx, errorsmod.Wrapf(errortypes.ErrInvalidType, "invalid transaction type %T, expected GasTx", tx)
|
||||
}
|
||||
|
||||
// We need to setup an empty gas config so that the gas is consistent with Ethereum.
|
||||
newCtx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter()).
|
||||
WithKVGasConfig(storetypes.GasConfig{}).
|
||||
WithTransientKVGasConfig(storetypes.GasConfig{})
|
||||
|
||||
// Reset transient gas used to prepare the execution of current cosmos tx.
|
||||
// Transient gas-used is necessary to sum the gas-used of cosmos tx, when it contains multiple eth msgs.
|
||||
esc.evmKeeper.ResetTransientGasUsed(ctx)
|
||||
return next(newCtx, tx, simulate)
|
||||
}
|
||||
|
||||
// EthEmitEventDecorator emit events in ante handler in case of tx execution failed (out of block gas limit).
|
||||
type EthEmitEventDecorator struct {
|
||||
evmKeeper EVMKeeper
|
||||
}
|
||||
|
||||
// NewEthEmitEventDecorator creates a new EthEmitEventDecorator
|
||||
func NewEthEmitEventDecorator(evmKeeper EVMKeeper) EthEmitEventDecorator {
|
||||
return EthEmitEventDecorator{evmKeeper}
|
||||
}
|
||||
|
||||
// AnteHandle emits some basic events for the eth messages
|
||||
func (eeed EthEmitEventDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||
// After eth tx passed ante handler, the fee is deducted and nonce increased, it shouldn't be ignored by json-rpc,
|
||||
// we need to emit some basic events at the very end of ante handler to be indexed by tendermint.
|
||||
txIndex := eeed.evmKeeper.GetTxIndexTransient(ctx)
|
||||
for i, msg := range tx.GetMsgs() {
|
||||
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||
if !ok {
|
||||
return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||
}
|
||||
|
||||
// emit ethereum tx hash as an event so that it can be indexed by Tendermint for query purposes
|
||||
// it's emitted in ante handler, so we can query failed transaction (out of block gas limit).
|
||||
ctx.EventManager().EmitEvent(sdk.NewEvent(
|
||||
evmtypes.EventTypeEthereumTx,
|
||||
sdk.NewAttribute(evmtypes.AttributeKeyEthereumTxHash, msgEthTx.Hash),
|
||||
sdk.NewAttribute(evmtypes.AttributeKeyTxIndex, strconv.FormatUint(txIndex+uint64(i), 10)),
|
||||
))
|
||||
}
|
||||
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
// EthValidateBasicDecorator is adapted from ValidateBasicDecorator from cosmos-sdk, it ignores ErrNoSignatures
|
||||
type EthValidateBasicDecorator struct {
|
||||
evmKeeper EVMKeeper
|
||||
}
|
||||
|
||||
// NewEthValidateBasicDecorator creates a new EthValidateBasicDecorator
|
||||
func NewEthValidateBasicDecorator(ek EVMKeeper) EthValidateBasicDecorator {
|
||||
return EthValidateBasicDecorator{
|
||||
evmKeeper: ek,
|
||||
}
|
||||
}
|
||||
|
||||
// AnteHandle handles basic validation of tx
|
||||
func (vbd EthValidateBasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
|
||||
// no need to validate basic on recheck tx, call next antehandler
|
||||
if ctx.IsReCheckTx() {
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
err := tx.ValidateBasic()
|
||||
// ErrNoSignatures is fine with eth tx
|
||||
if err != nil && !errors.Is(err, errortypes.ErrNoSignatures) {
|
||||
return ctx, errorsmod.Wrap(err, "tx basic validation failed")
|
||||
}
|
||||
|
||||
// For eth type cosmos tx, some fields should be verified as zero values,
|
||||
// since we will only verify the signature against the hash of the MsgEthereumTx.Data
|
||||
wrapperTx, ok := tx.(protoTxProvider)
|
||||
if !ok {
|
||||
return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid tx type %T, didn't implement interface protoTxProvider", tx)
|
||||
}
|
||||
|
||||
protoTx := wrapperTx.GetProtoTx()
|
||||
body := protoTx.Body
|
||||
if body.Memo != "" || body.TimeoutHeight != uint64(0) || len(body.NonCriticalExtensionOptions) > 0 {
|
||||
return ctx, errorsmod.Wrap(errortypes.ErrInvalidRequest,
|
||||
"for eth tx body Memo TimeoutHeight NonCriticalExtensionOptions should be empty")
|
||||
}
|
||||
|
||||
if len(body.ExtensionOptions) != 1 {
|
||||
return ctx, errorsmod.Wrap(errortypes.ErrInvalidRequest, "for eth tx length of ExtensionOptions should be 1")
|
||||
}
|
||||
|
||||
authInfo := protoTx.AuthInfo
|
||||
if len(authInfo.SignerInfos) > 0 {
|
||||
return ctx, errorsmod.Wrap(errortypes.ErrInvalidRequest, "for eth tx AuthInfo SignerInfos should be empty")
|
||||
}
|
||||
|
||||
if authInfo.Fee.Payer != "" || authInfo.Fee.Granter != "" {
|
||||
return ctx, errorsmod.Wrap(errortypes.ErrInvalidRequest, "for eth tx AuthInfo Fee payer and granter should be empty")
|
||||
}
|
||||
|
||||
sigs := protoTx.Signatures
|
||||
if len(sigs) > 0 {
|
||||
return ctx, errorsmod.Wrap(errortypes.ErrInvalidRequest, "for eth tx Signatures should be empty")
|
||||
}
|
||||
|
||||
txFee := sdk.Coins{}
|
||||
txGasLimit := uint64(0)
|
||||
|
||||
chainCfg := vbd.evmKeeper.GetChainConfig(ctx)
|
||||
chainID := vbd.evmKeeper.ChainID()
|
||||
ethCfg := chainCfg.EthereumConfig(chainID)
|
||||
baseFee := vbd.evmKeeper.GetBaseFee(ctx, ethCfg)
|
||||
enableCreate := vbd.evmKeeper.GetEnableCreate(ctx)
|
||||
enableCall := vbd.evmKeeper.GetEnableCall(ctx)
|
||||
evmDenom := vbd.evmKeeper.GetEVMDenom(ctx)
|
||||
|
||||
for _, msg := range protoTx.GetMsgs() {
|
||||
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||
if !ok {
|
||||
return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||
}
|
||||
|
||||
// Validate `From` field
|
||||
if msgEthTx.From != "" {
|
||||
return ctx, errorsmod.Wrapf(errortypes.ErrInvalidRequest, "invalid From %s, expect empty string", msgEthTx.From)
|
||||
}
|
||||
|
||||
txGasLimit += msgEthTx.GetGas()
|
||||
|
||||
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
|
||||
if err != nil {
|
||||
return ctx, errorsmod.Wrap(err, "failed to unpack MsgEthereumTx Data")
|
||||
}
|
||||
|
||||
// return error if contract creation or call are disabled through governance
|
||||
if !enableCreate && txData.GetTo() == nil {
|
||||
return ctx, errorsmod.Wrap(evmtypes.ErrCreateDisabled, "failed to create new contract")
|
||||
} else if !enableCall && txData.GetTo() != nil {
|
||||
return ctx, errorsmod.Wrap(evmtypes.ErrCallDisabled, "failed to call contract")
|
||||
}
|
||||
|
||||
if baseFee == nil && txData.TxType() == ethtypes.DynamicFeeTxType {
|
||||
return ctx, errorsmod.Wrap(ethtypes.ErrTxTypeNotSupported, "dynamic fee tx not supported")
|
||||
}
|
||||
|
||||
txFee = txFee.Add(sdk.Coin{Denom: evmDenom, Amount: sdkmath.NewIntFromBigInt(txData.Fee())})
|
||||
}
|
||||
|
||||
if !authInfo.Fee.Amount.IsEqual(txFee) {
|
||||
return ctx, errorsmod.Wrapf(errortypes.ErrInvalidRequest, "invalid AuthInfo Fee Amount (%s != %s)", authInfo.Fee.Amount, txFee)
|
||||
}
|
||||
|
||||
if authInfo.Fee.GasLimit != txGasLimit {
|
||||
return ctx, errorsmod.Wrapf(errortypes.ErrInvalidRequest, "invalid AuthInfo Fee GasLimit (%d != %d)", authInfo.Fee.GasLimit, txGasLimit)
|
||||
}
|
||||
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
42
app/ante/setup_test.go
Normal file
42
app/ante/setup_test.go
Normal file
@ -0,0 +1,42 @@
|
||||
package ante_test
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
storetypes "github.com/cosmos/cosmos-sdk/store/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/evmos/ethermint/app/ante"
|
||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||
)
|
||||
|
||||
func (suite AnteTestSuite) TestEthSetupContextDecorator() {
|
||||
dec := ante.NewEthSetUpContextDecorator(suite.app.EvmKeeper)
|
||||
tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
tx sdk.Tx
|
||||
expPass bool
|
||||
}{
|
||||
{"invalid transaction type - does not implement GasTx", &invalidTx{}, false},
|
||||
{
|
||||
"success - transaction implement GasTx",
|
||||
tx,
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
ctx, err := dec.AnteHandle(suite.ctx, tc.tx, false, NextFn)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
suite.Equal(storetypes.GasConfig{}, ctx.KVGasConfig())
|
||||
suite.Equal(storetypes.GasConfig{}, ctx.TransientKVGasConfig())
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
64
app/ante/signverify_test.go
Normal file
64
app/ante/signverify_test.go
Normal file
@ -0,0 +1,64 @@
|
||||
package ante_test
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/evmos/ethermint/app/ante"
|
||||
"github.com/evmos/ethermint/tests"
|
||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||
)
|
||||
|
||||
func (suite AnteTestSuite) TestEthSigVerificationDecorator() {
|
||||
addr, privKey := tests.NewAddrKey()
|
||||
|
||||
signedTx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
|
||||
signedTx.From = addr.Hex()
|
||||
err := signedTx.Sign(suite.ethSigner, tests.NewSigner(privKey))
|
||||
suite.Require().NoError(err)
|
||||
|
||||
unprotectedTx := evmtypes.NewTxContract(nil, 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
|
||||
unprotectedTx.From = addr.Hex()
|
||||
err = unprotectedTx.Sign(ethtypes.HomesteadSigner{}, tests.NewSigner(privKey))
|
||||
suite.Require().NoError(err)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
tx sdk.Tx
|
||||
allowUnprotectedTxs bool
|
||||
reCheckTx bool
|
||||
expPass bool
|
||||
}{
|
||||
{"ReCheckTx", &invalidTx{}, false, true, false},
|
||||
{"invalid transaction type", &invalidTx{}, false, false, false},
|
||||
{
|
||||
"invalid sender",
|
||||
evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 1, &addr, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil),
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
},
|
||||
{"successful signature verification", signedTx, false, false, true},
|
||||
{"invalid, reject unprotected txs", unprotectedTx, false, false, false},
|
||||
{"successful, allow unprotected txs", unprotectedTx, true, false, true},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.evmParamsOption = func(params *evmtypes.Params) {
|
||||
params.AllowUnprotectedTxs = tc.allowUnprotectedTxs
|
||||
}
|
||||
suite.SetupTest()
|
||||
dec := ante.NewEthSigVerificationDecorator(suite.app.EvmKeeper)
|
||||
_, err := dec.AnteHandle(suite.ctx.WithIsReCheckTx(tc.reCheckTx), tc.tx, false, NextFn)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
suite.evmParamsOption = nil
|
||||
}
|
65
app/ante/sigverify.go
Normal file
65
app/ante/sigverify.go
Normal file
@ -0,0 +1,65 @@
|
||||
package ante
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||
)
|
||||
|
||||
// EthSigVerificationDecorator validates an ethereum signatures
|
||||
type EthSigVerificationDecorator struct {
|
||||
evmKeeper EVMKeeper
|
||||
}
|
||||
|
||||
// NewEthSigVerificationDecorator creates a new EthSigVerificationDecorator
|
||||
func NewEthSigVerificationDecorator(ek EVMKeeper) EthSigVerificationDecorator {
|
||||
return EthSigVerificationDecorator{
|
||||
evmKeeper: ek,
|
||||
}
|
||||
}
|
||||
|
||||
// AnteHandle validates checks that the registered chain id is the same as the one on the message, and
|
||||
// that the signer address matches the one defined on the message.
|
||||
// It's not skipped for RecheckTx, because it set `From` address which is critical from other ante handler to work.
|
||||
// Failure in RecheckTx will prevent tx to be included into block, especially when CheckTx succeed, in which case user
|
||||
// won't see the error message.
|
||||
func (esvd EthSigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||
chainID := esvd.evmKeeper.ChainID()
|
||||
chainCfg := esvd.evmKeeper.GetChainConfig(ctx)
|
||||
ethCfg := chainCfg.EthereumConfig(chainID)
|
||||
blockNum := big.NewInt(ctx.BlockHeight())
|
||||
signer := ethtypes.MakeSigner(ethCfg, blockNum)
|
||||
|
||||
for _, msg := range tx.GetMsgs() {
|
||||
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||
if !ok {
|
||||
return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||
}
|
||||
|
||||
allowUnprotectedTxs := esvd.evmKeeper.GetAllowUnprotectedTxs(ctx)
|
||||
ethTx := msgEthTx.AsTransaction()
|
||||
if !allowUnprotectedTxs && !ethTx.Protected() {
|
||||
return ctx, errorsmod.Wrapf(
|
||||
errortypes.ErrNotSupported,
|
||||
"rejected unprotected Ethereum transaction. Please EIP155 sign your transaction to protect it against replay-attacks")
|
||||
}
|
||||
|
||||
sender, err := signer.Sender(ethTx)
|
||||
if err != nil {
|
||||
return ctx, errorsmod.Wrapf(
|
||||
errortypes.ErrorInvalidSigner,
|
||||
"couldn't retrieve sender address from the ethereum transaction: %s",
|
||||
err.Error(),
|
||||
)
|
||||
}
|
||||
|
||||
// set up the sender to the transaction field if not already
|
||||
msgEthTx.From = sender.Hex()
|
||||
}
|
||||
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
@ -13,9 +13,10 @@ import (
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx"
|
||||
types2 "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
types3 "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
||||
"github.com/evmos/ethermint/ethereum/eip712"
|
||||
"github.com/evmos/ethermint/types"
|
||||
|
||||
@ -25,21 +26,27 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
sdkante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
authz "github.com/cosmos/cosmos-sdk/x/authz"
|
||||
cryptocodec "github.com/evmos/ethermint/crypto/codec"
|
||||
"github.com/evmos/ethermint/crypto/ethsecp256k1"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
||||
evtypes "github.com/cosmos/cosmos-sdk/x/evidence/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/feegrant"
|
||||
types5 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
|
||||
govtypesv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
|
||||
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
|
||||
"github.com/evmos/ethermint/app"
|
||||
ante "github.com/evmos/ethermint/app/ante"
|
||||
"github.com/evmos/ethermint/encoding"
|
||||
@ -92,6 +99,8 @@ func (suite *AnteTestSuite) SetupTest() {
|
||||
evmGenesis.Params.ChainConfig.ArrowGlacierBlock = &maxInt
|
||||
evmGenesis.Params.ChainConfig.GrayGlacierBlock = &maxInt
|
||||
evmGenesis.Params.ChainConfig.MergeNetsplitBlock = &maxInt
|
||||
evmGenesis.Params.ChainConfig.ShanghaiBlock = &maxInt
|
||||
evmGenesis.Params.ChainConfig.CancunBlock = &maxInt
|
||||
}
|
||||
if suite.evmParamsOption != nil {
|
||||
suite.evmParamsOption(&evmGenesis.Params)
|
||||
@ -111,6 +120,7 @@ func (suite *AnteTestSuite) SetupTest() {
|
||||
encodingConfig := encoding.MakeConfig(app.ModuleBasics)
|
||||
// We're using TestMsg amino encoding in some tests, so register it here.
|
||||
encodingConfig.Amino.RegisterConcrete(&testdata.TestMsg{}, "testdata.TestMsg", nil)
|
||||
eip712.SetEncodingConfig(encodingConfig)
|
||||
|
||||
suite.clientCtx = client.Context{}.WithTxConfig(encodingConfig.TxConfig)
|
||||
|
||||
@ -263,41 +273,57 @@ func (suite *AnteTestSuite) CreateTestCosmosTxBuilder(gasPrice sdkmath.Int, deno
|
||||
func (suite *AnteTestSuite) CreateTestEIP712TxBuilderMsgSend(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||
// Build MsgSend
|
||||
recipient := sdk.AccAddress(common.Address{}.Bytes())
|
||||
msgSend := types2.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(1))))
|
||||
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgSend)
|
||||
msgSend := banktypes.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(1))))
|
||||
return suite.CreateTestEIP712SingleMessageTxBuilder(from, priv, chainId, gas, gasAmount, msgSend)
|
||||
}
|
||||
|
||||
func (suite *AnteTestSuite) CreateTestEIP712TxBuilderMsgDelegate(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||
// Build MsgSend
|
||||
valEthAddr := tests.GenerateAddress()
|
||||
valAddr := sdk.ValAddress(valEthAddr.Bytes())
|
||||
msgSend := types3.NewMsgDelegate(from, valAddr, sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(20)))
|
||||
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgSend)
|
||||
msgSend := stakingtypes.NewMsgDelegate(from, valAddr, sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(20)))
|
||||
return suite.CreateTestEIP712SingleMessageTxBuilder(from, priv, chainId, gas, gasAmount, msgSend)
|
||||
}
|
||||
|
||||
func (suite *AnteTestSuite) CreateTestEIP712MsgCreateValidator(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||
// Build MsgCreateValidator
|
||||
valAddr := sdk.ValAddress(from.Bytes())
|
||||
privEd := ed25519.GenPrivKey()
|
||||
msgCreate, err := types3.NewMsgCreateValidator(
|
||||
msgCreate, err := stakingtypes.NewMsgCreateValidator(
|
||||
valAddr,
|
||||
privEd.PubKey(),
|
||||
sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20)),
|
||||
// TODO: can this values be empty strings?
|
||||
types3.NewDescription("moniker", "indentity", "website", "security_contract", "details"),
|
||||
types3.NewCommissionRates(sdk.OneDec(), sdk.OneDec(), sdk.OneDec()),
|
||||
stakingtypes.NewDescription("moniker", "indentity", "website", "security_contract", "details"),
|
||||
stakingtypes.NewCommissionRates(sdk.OneDec(), sdk.OneDec(), sdk.OneDec()),
|
||||
sdk.OneInt(),
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgCreate)
|
||||
return suite.CreateTestEIP712SingleMessageTxBuilder(from, priv, chainId, gas, gasAmount, msgCreate)
|
||||
}
|
||||
|
||||
func (suite *AnteTestSuite) CreateTestEIP712MsgCreateValidator2(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||
// Build MsgCreateValidator
|
||||
valAddr := sdk.ValAddress(from.Bytes())
|
||||
privEd := ed25519.GenPrivKey()
|
||||
msgCreate, err := stakingtypes.NewMsgCreateValidator(
|
||||
valAddr,
|
||||
privEd.PubKey(),
|
||||
sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20)),
|
||||
// Ensure optional fields can be left blank
|
||||
stakingtypes.NewDescription("moniker", "indentity", "", "", ""),
|
||||
stakingtypes.NewCommissionRates(sdk.OneDec(), sdk.OneDec(), sdk.OneDec()),
|
||||
sdk.OneInt(),
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
return suite.CreateTestEIP712SingleMessageTxBuilder(from, priv, chainId, gas, gasAmount, msgCreate)
|
||||
}
|
||||
|
||||
func (suite *AnteTestSuite) CreateTestEIP712SubmitProposal(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins, deposit sdk.Coins) client.TxBuilder {
|
||||
proposal, ok := types5.ContentFromProposalType("My proposal", "My description", types5.ProposalTypeText)
|
||||
proposal, ok := govtypes.ContentFromProposalType("My proposal", "My description", govtypes.ProposalTypeText)
|
||||
suite.Require().True(ok)
|
||||
msgSubmit, err := types5.NewMsgSubmitProposal(proposal, deposit, from)
|
||||
msgSubmit, err := govtypes.NewMsgSubmitProposal(proposal, deposit, from)
|
||||
suite.Require().NoError(err)
|
||||
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgSubmit)
|
||||
return suite.CreateTestEIP712SingleMessageTxBuilder(from, priv, chainId, gas, gasAmount, msgSubmit)
|
||||
}
|
||||
|
||||
func (suite *AnteTestSuite) CreateTestEIP712GrantAllowance(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||
@ -311,18 +337,18 @@ func (suite *AnteTestSuite) CreateTestEIP712GrantAllowance(from sdk.AccAddress,
|
||||
grantedAddr := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, granted.Bytes())
|
||||
msgGrant, err := feegrant.NewMsgGrantAllowance(basic, from, grantedAddr.GetAddress())
|
||||
suite.Require().NoError(err)
|
||||
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgGrant)
|
||||
return suite.CreateTestEIP712SingleMessageTxBuilder(from, priv, chainId, gas, gasAmount, msgGrant)
|
||||
}
|
||||
|
||||
func (suite *AnteTestSuite) CreateTestEIP712MsgEditValidator(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||
valAddr := sdk.ValAddress(from.Bytes())
|
||||
msgEdit := types3.NewMsgEditValidator(
|
||||
msgEdit := stakingtypes.NewMsgEditValidator(
|
||||
valAddr,
|
||||
types3.NewDescription("moniker", "identity", "website", "security_contract", "details"),
|
||||
stakingtypes.NewDescription("moniker", "identity", "website", "security_contract", "details"),
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgEdit)
|
||||
return suite.CreateTestEIP712SingleMessageTxBuilder(from, priv, chainId, gas, gasAmount, msgEdit)
|
||||
}
|
||||
|
||||
func (suite *AnteTestSuite) CreateTestEIP712MsgSubmitEvidence(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||
@ -335,7 +361,72 @@ func (suite *AnteTestSuite) CreateTestEIP712MsgSubmitEvidence(from sdk.AccAddres
|
||||
})
|
||||
suite.Require().NoError(err)
|
||||
|
||||
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgEvidence)
|
||||
return suite.CreateTestEIP712SingleMessageTxBuilder(from, priv, chainId, gas, gasAmount, msgEvidence)
|
||||
}
|
||||
|
||||
func (suite *AnteTestSuite) CreateTestEIP712MsgVoteV1(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||
msgVote := govtypesv1.NewMsgVote(from, 1, govtypesv1.VoteOption_VOTE_OPTION_YES, "")
|
||||
return suite.CreateTestEIP712SingleMessageTxBuilder(from, priv, chainId, gas, gasAmount, msgVote)
|
||||
}
|
||||
|
||||
func (suite *AnteTestSuite) CreateTestEIP712SubmitProposalV1(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||
// Build V1 proposal messages. Must all be same-type, since EIP-712
|
||||
// does not support arrays of variable type.
|
||||
authAcc := suite.app.GovKeeper.GetGovernanceAccount(suite.ctx)
|
||||
|
||||
proposal1, ok := govtypes.ContentFromProposalType("My proposal 1", "My description 1", govtypes.ProposalTypeText)
|
||||
suite.Require().True(ok)
|
||||
content1, err := govtypesv1.NewLegacyContent(
|
||||
proposal1,
|
||||
sdk.MustBech32ifyAddressBytes(sdk.GetConfig().GetBech32AccountAddrPrefix(), authAcc.GetAddress().Bytes()),
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
proposal2, ok := govtypes.ContentFromProposalType("My proposal 2", "My description 2", govtypes.ProposalTypeText)
|
||||
suite.Require().True(ok)
|
||||
content2, err := govtypesv1.NewLegacyContent(
|
||||
proposal2,
|
||||
sdk.MustBech32ifyAddressBytes(sdk.GetConfig().GetBech32AccountAddrPrefix(), authAcc.GetAddress().Bytes()),
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
proposalMsgs := []sdk.Msg{
|
||||
content1,
|
||||
content2,
|
||||
}
|
||||
|
||||
// Build V1 proposal
|
||||
msgProposal, err := govtypesv1.NewMsgSubmitProposal(
|
||||
proposalMsgs,
|
||||
sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(100))),
|
||||
sdk.MustBech32ifyAddressBytes(sdk.GetConfig().GetBech32AccountAddrPrefix(), from.Bytes()),
|
||||
"Metadata",
|
||||
)
|
||||
|
||||
suite.Require().NoError(err)
|
||||
|
||||
return suite.CreateTestEIP712SingleMessageTxBuilder(from, priv, chainId, gas, gasAmount, msgProposal)
|
||||
}
|
||||
|
||||
func (suite *AnteTestSuite) CreateTestEIP712MsgExec(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||
recipient := sdk.AccAddress(common.Address{}.Bytes())
|
||||
msgSend := banktypes.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(1))))
|
||||
msgExec := authz.NewMsgExec(from, []sdk.Msg{msgSend})
|
||||
return suite.CreateTestEIP712SingleMessageTxBuilder(from, priv, chainId, gas, gasAmount, &msgExec)
|
||||
}
|
||||
|
||||
func (suite *AnteTestSuite) CreateTestEIP712MultipleMsgSend(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||
recipient := sdk.AccAddress(common.Address{}.Bytes())
|
||||
msgSend := banktypes.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(1))))
|
||||
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, []sdk.Msg{msgSend, msgSend, msgSend})
|
||||
}
|
||||
|
||||
// Fails
|
||||
func (suite *AnteTestSuite) CreateTestEIP712MultipleSignerMsgs(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||
recipient := sdk.AccAddress(common.Address{}.Bytes())
|
||||
msgSend1 := banktypes.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(1))))
|
||||
msgSend2 := banktypes.NewMsgSend(recipient, from, sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(1))))
|
||||
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, []sdk.Msg{msgSend1, msgSend2})
|
||||
}
|
||||
|
||||
// StdSignBytes returns the bytes to sign for a transaction.
|
||||
@ -376,8 +467,14 @@ func StdSignBytes(cdc *codec.LegacyAmino, chainID string, accnum uint64, sequenc
|
||||
return sdk.MustSortJSON(bz)
|
||||
}
|
||||
|
||||
func (suite *AnteTestSuite) CreateTestEIP712CosmosTxBuilder(
|
||||
func (suite *AnteTestSuite) CreateTestEIP712SingleMessageTxBuilder(
|
||||
from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins, msg sdk.Msg,
|
||||
) client.TxBuilder {
|
||||
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, []sdk.Msg{msg})
|
||||
}
|
||||
|
||||
func (suite *AnteTestSuite) CreateTestEIP712CosmosTxBuilder(
|
||||
from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins, msgs []sdk.Msg,
|
||||
) client.TxBuilder {
|
||||
var err error
|
||||
|
||||
@ -398,13 +495,13 @@ func (suite *AnteTestSuite) CreateTestEIP712CosmosTxBuilder(
|
||||
fee := legacytx.NewStdFee(gas, gasAmount)
|
||||
accNumber := suite.app.AccountKeeper.GetAccount(suite.ctx, from).GetAccountNumber()
|
||||
|
||||
data := legacytx.StdSignBytes(chainId, accNumber, nonce, 0, fee, []sdk.Msg{msg}, "", nil)
|
||||
typedData, err := eip712.WrapTxToTypedData(ethermintCodec, ethChainId, msg, data, &eip712.FeeDelegationOptions{
|
||||
data := legacytx.StdSignBytes(chainId, accNumber, nonce, 0, fee, msgs, "", nil)
|
||||
typedData, err := eip712.WrapTxToTypedData(ethermintCodec, ethChainId, msgs[0], data, &eip712.FeeDelegationOptions{
|
||||
FeePayer: from,
|
||||
})
|
||||
suite.Require().NoError(err)
|
||||
|
||||
sigHash, err := eip712.ComputeTypedDataHash(typedData)
|
||||
sigHash, _, err := apitypes.TypedDataAndHash(typedData)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Sign typedData
|
||||
@ -442,12 +539,189 @@ func (suite *AnteTestSuite) CreateTestEIP712CosmosTxBuilder(
|
||||
err = builder.SetSignatures(sigsV2)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
err = builder.SetMsgs(msg)
|
||||
err = builder.SetMsgs(msgs...)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
return builder
|
||||
}
|
||||
|
||||
// Generate a set of pub/priv keys to be used in creating multi-keys
|
||||
func (suite *AnteTestSuite) GenerateMultipleKeys(n int) ([]cryptotypes.PrivKey, []cryptotypes.PubKey) {
|
||||
privKeys := make([]cryptotypes.PrivKey, n)
|
||||
pubKeys := make([]cryptotypes.PubKey, n)
|
||||
for i := 0; i < n; i++ {
|
||||
privKey, err := ethsecp256k1.GenerateKey()
|
||||
suite.Require().NoError(err)
|
||||
privKeys[i] = privKey
|
||||
pubKeys[i] = privKey.PubKey()
|
||||
}
|
||||
return privKeys, pubKeys
|
||||
}
|
||||
|
||||
// generateSingleSignature signs the given sign doc bytes using the given signType (EIP-712 or Standard)
|
||||
func (suite *AnteTestSuite) generateSingleSignature(signMode signing.SignMode, privKey cryptotypes.PrivKey, signDocBytes []byte, signType string) (signature signing.SignatureV2) {
|
||||
var (
|
||||
msg []byte
|
||||
err error
|
||||
)
|
||||
|
||||
msg = signDocBytes
|
||||
|
||||
if signType == "EIP-712" {
|
||||
msg, err = eip712.GetEIP712HashForMsg(signDocBytes)
|
||||
suite.Require().NoError(err)
|
||||
}
|
||||
|
||||
sigBytes, _ := privKey.Sign(msg)
|
||||
sigData := &signing.SingleSignatureData{
|
||||
SignMode: signMode,
|
||||
Signature: sigBytes,
|
||||
}
|
||||
|
||||
return signing.SignatureV2{
|
||||
PubKey: privKey.PubKey(),
|
||||
Data: sigData,
|
||||
}
|
||||
}
|
||||
|
||||
// generateMultikeySignatures signs a set of messages using each private key within a given multi-key
|
||||
func (suite *AnteTestSuite) generateMultikeySignatures(signMode signing.SignMode, privKeys []cryptotypes.PrivKey, signDocBytes []byte, signType string) (signatures []signing.SignatureV2) {
|
||||
n := len(privKeys)
|
||||
signatures = make([]signing.SignatureV2, n)
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
privKey := privKeys[i]
|
||||
currentType := signType
|
||||
|
||||
// If mixed type, alternate signing type on each iteration
|
||||
if signType == "mixed" {
|
||||
if i%2 == 0 {
|
||||
currentType = "EIP-712"
|
||||
} else {
|
||||
currentType = "Standard"
|
||||
}
|
||||
}
|
||||
|
||||
signatures[i] = suite.generateSingleSignature(
|
||||
signMode,
|
||||
privKey,
|
||||
signDocBytes,
|
||||
currentType,
|
||||
)
|
||||
}
|
||||
|
||||
return signatures
|
||||
}
|
||||
|
||||
// RegisterAccount creates an account with the keeper and populates the initial balance
|
||||
func (suite *AnteTestSuite) RegisterAccount(pubKey cryptotypes.PubKey, balance *big.Int) {
|
||||
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, sdk.AccAddress(pubKey.Address()))
|
||||
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||
|
||||
suite.app.EvmKeeper.SetBalance(suite.ctx, common.BytesToAddress(pubKey.Address()), balance)
|
||||
}
|
||||
|
||||
// createSignerBytes generates sign doc bytes using the given parameters
|
||||
func (suite *AnteTestSuite) createSignerBytes(chainId string, signMode signing.SignMode, pubKey cryptotypes.PubKey, txBuilder client.TxBuilder) []byte {
|
||||
acc, err := sdkante.GetSignerAcc(suite.ctx, suite.app.AccountKeeper, sdk.AccAddress(pubKey.Address()))
|
||||
suite.Require().NoError(err)
|
||||
signerInfo := authsigning.SignerData{
|
||||
Address: sdk.MustBech32ifyAddressBytes(sdk.GetConfig().GetBech32AccountAddrPrefix(), acc.GetAddress().Bytes()),
|
||||
ChainID: chainId,
|
||||
AccountNumber: acc.GetAccountNumber(),
|
||||
Sequence: acc.GetSequence(),
|
||||
PubKey: pubKey,
|
||||
}
|
||||
|
||||
signerBytes, err := suite.clientCtx.TxConfig.SignModeHandler().GetSignBytes(
|
||||
signMode,
|
||||
signerInfo,
|
||||
txBuilder.GetTx(),
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
return signerBytes
|
||||
}
|
||||
|
||||
// createBaseTxBuilder creates a TxBuilder to be used for Single- or Multi-signing
|
||||
func (suite *AnteTestSuite) createBaseTxBuilder(msg sdk.Msg, gas uint64) client.TxBuilder {
|
||||
txBuilder := suite.clientCtx.TxConfig.NewTxBuilder()
|
||||
|
||||
txBuilder.SetGasLimit(gas)
|
||||
txBuilder.SetFeeAmount(sdk.NewCoins(
|
||||
sdk.NewCoin("aphoton", sdk.NewInt(10000)),
|
||||
))
|
||||
|
||||
err := txBuilder.SetMsgs(msg)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
txBuilder.SetMemo("")
|
||||
|
||||
return txBuilder
|
||||
}
|
||||
|
||||
// CreateTestSignedMultisigTx creates and sign a multi-signed tx for the given message. `signType` indicates whether to use standard signing ("Standard"),
|
||||
// EIP-712 signing ("EIP-712"), or a mix of the two ("mixed").
|
||||
func (suite *AnteTestSuite) CreateTestSignedMultisigTx(privKeys []cryptotypes.PrivKey, signMode signing.SignMode, msg sdk.Msg, chainId string, gas uint64, signType string) client.TxBuilder {
|
||||
pubKeys := make([]cryptotypes.PubKey, len(privKeys))
|
||||
for i, privKey := range privKeys {
|
||||
pubKeys[i] = privKey.PubKey()
|
||||
}
|
||||
|
||||
// Re-derive multikey
|
||||
numKeys := len(privKeys)
|
||||
multiKey := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys)
|
||||
|
||||
suite.RegisterAccount(multiKey, big.NewInt(10000000000))
|
||||
|
||||
txBuilder := suite.createBaseTxBuilder(msg, gas)
|
||||
|
||||
// Prepare signature field
|
||||
sig := multisig.NewMultisig(len(pubKeys))
|
||||
txBuilder.SetSignatures(signing.SignatureV2{
|
||||
PubKey: multiKey,
|
||||
Data: sig,
|
||||
})
|
||||
|
||||
signerBytes := suite.createSignerBytes(chainId, signMode, multiKey, txBuilder)
|
||||
|
||||
// Sign for each key and update signature field
|
||||
sigs := suite.generateMultikeySignatures(signMode, privKeys, signerBytes, signType)
|
||||
for _, pkSig := range sigs {
|
||||
err := multisig.AddSignatureV2(sig, pkSig, pubKeys)
|
||||
suite.Require().NoError(err)
|
||||
}
|
||||
|
||||
txBuilder.SetSignatures(signing.SignatureV2{
|
||||
PubKey: multiKey,
|
||||
Data: sig,
|
||||
})
|
||||
|
||||
return txBuilder
|
||||
}
|
||||
|
||||
func (suite *AnteTestSuite) CreateTestSingleSignedTx(privKey cryptotypes.PrivKey, signMode signing.SignMode, msg sdk.Msg, chainId string, gas uint64, signType string) client.TxBuilder {
|
||||
pubKey := privKey.PubKey()
|
||||
|
||||
suite.RegisterAccount(pubKey, big.NewInt(10000000000))
|
||||
|
||||
txBuilder := suite.createBaseTxBuilder(msg, gas)
|
||||
|
||||
// Prepare signature field
|
||||
sig := signing.SingleSignatureData{}
|
||||
txBuilder.SetSignatures(signing.SignatureV2{
|
||||
PubKey: pubKey,
|
||||
Data: &sig,
|
||||
})
|
||||
|
||||
signerBytes := suite.createSignerBytes(chainId, signMode, pubKey, txBuilder)
|
||||
|
||||
sigData := suite.generateSingleSignature(signMode, privKey, signerBytes, signType)
|
||||
txBuilder.SetSignatures(sigData)
|
||||
|
||||
return txBuilder
|
||||
}
|
||||
|
||||
func NextFn(ctx sdk.Context, _ sdk.Tx, _ bool) (sdk.Context, error) {
|
||||
return ctx, nil
|
||||
}
|
||||
|
38
app/app.go
38
app/app.go
@ -2,6 +2,7 @@ package app
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
@ -18,6 +19,7 @@ import (
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/grpc/node"
|
||||
"github.com/cosmos/cosmos-sdk/client/grpc/tmservice"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||
@ -26,6 +28,7 @@ import (
|
||||
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
simappparams "github.com/cosmos/cosmos-sdk/simapp/params"
|
||||
"github.com/cosmos/cosmos-sdk/store/streaming"
|
||||
storetypes "github.com/cosmos/cosmos-sdk/store/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
@ -179,8 +182,6 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
var _ simapp.App = (*EthermintApp)(nil)
|
||||
|
||||
// var _ server.Application (*EthermintApp)(nil)
|
||||
|
||||
// EthermintApp implements an extended ABCI application. It is an application
|
||||
@ -230,9 +231,6 @@ type EthermintApp struct {
|
||||
// the module manager
|
||||
mm *module.Manager
|
||||
|
||||
// simulation manager
|
||||
sm *module.SimulationManager
|
||||
|
||||
// the configurator
|
||||
configurator module.Configurator
|
||||
}
|
||||
@ -283,6 +281,12 @@ func NewEthermintApp(
|
||||
tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey, evmtypes.TransientKey, feemarkettypes.TransientKey)
|
||||
memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey)
|
||||
|
||||
// load state streaming if enabled
|
||||
if _, _, err := streaming.LoadStreamingServices(bApp, appOpts, appCodec, keys); err != nil {
|
||||
fmt.Printf("failed to load state streaming: %s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
app := &EthermintApp{
|
||||
BaseApp: bApp,
|
||||
cdc: cdc,
|
||||
@ -591,17 +595,6 @@ func NewEthermintApp(
|
||||
// add test gRPC service for testing gRPC queries in isolation
|
||||
// testdata.RegisterTestServiceServer(app.GRPCQueryRouter(), testdata.TestServiceImpl{})
|
||||
|
||||
// create the simulation manager and define the order of the modules for deterministic simulations
|
||||
//
|
||||
// NOTE: this is not required apps that don't use the simulator for fuzz testing
|
||||
// transactions
|
||||
overrideModules := map[string]module.AppModuleSimulation{
|
||||
authtypes.ModuleName: auth.NewAppModule(app.appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts),
|
||||
}
|
||||
app.sm = module.NewSimulationManagerFromAppModules(app.mm.Modules, overrideModules)
|
||||
|
||||
app.sm.RegisterStoreDecoders()
|
||||
|
||||
// initialize stores
|
||||
app.MountKVStores(keys)
|
||||
app.MountTransientStores(tkeys)
|
||||
@ -771,11 +764,6 @@ func (app *EthermintApp) GetSubspace(moduleName string) paramstypes.Subspace {
|
||||
return subspace
|
||||
}
|
||||
|
||||
// SimulationManager implements the SimulationApp interface
|
||||
func (app *EthermintApp) SimulationManager() *module.SimulationManager {
|
||||
return app.sm
|
||||
}
|
||||
|
||||
// RegisterAPIRoutes registers all application module routes with the provided
|
||||
// API server.
|
||||
func (app *EthermintApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) {
|
||||
@ -784,6 +772,8 @@ func (app *EthermintApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.
|
||||
authtx.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
|
||||
// Register new tendermint queries routes from grpc-gateway.
|
||||
tmservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
|
||||
// Register node gRPC service for grpc-gateway.
|
||||
node.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
|
||||
|
||||
// Register grpc-gateway routes for all modules.
|
||||
ModuleBasics.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
|
||||
@ -809,6 +799,12 @@ func (app *EthermintApp) RegisterTendermintService(clientCtx client.Context) {
|
||||
)
|
||||
}
|
||||
|
||||
// RegisterNodeService registers the node gRPC service on the provided
|
||||
// application gRPC query router.
|
||||
func (app *EthermintApp) RegisterNodeService(clientCtx client.Context) {
|
||||
node.RegisterNodeService(clientCtx, app.GRPCQueryRouter())
|
||||
}
|
||||
|
||||
// RegisterSwaggerAPI registers swagger route with API Server
|
||||
func RegisterSwaggerAPI(_ client.Context, rtr *mux.Router) {
|
||||
statikFS, err := fs.New()
|
||||
|
@ -1,403 +0,0 @@
|
||||
package app
|
||||
|
||||
// TODO: COsmos SDK fix for the simulator issue for custom keys
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
"github.com/cosmos/cosmos-sdk/simapp/params"
|
||||
"github.com/cosmos/cosmos-sdk/store"
|
||||
storetypes "github.com/cosmos/cosmos-sdk/store/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"
|
||||
distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||
evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types"
|
||||
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
|
||||
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/simulation"
|
||||
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
ibctransfertypes "github.com/cosmos/ibc-go/v5/modules/apps/transfer/types"
|
||||
ibchost "github.com/cosmos/ibc-go/v5/modules/core/24-host"
|
||||
"github.com/evmos/ethermint/app/ante"
|
||||
evmenc "github.com/evmos/ethermint/encoding"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
dbm "github.com/tendermint/tm-db"
|
||||
)
|
||||
|
||||
// MakeEncodingConfig creates the EncodingConfig
|
||||
func MakeEncodingConfig() params.EncodingConfig {
|
||||
return evmenc.MakeConfig(ModuleBasics)
|
||||
}
|
||||
|
||||
func init() {
|
||||
simapp.GetSimulatorFlags()
|
||||
}
|
||||
|
||||
const SimAppChainID = "simulation_777-1"
|
||||
|
||||
type storeKeysPrefixes struct {
|
||||
A storetypes.StoreKey
|
||||
B storetypes.StoreKey
|
||||
Prefixes [][]byte
|
||||
}
|
||||
|
||||
// fauxMerkleModeOpt returns a BaseApp option to use a dbStoreAdapter instead of
|
||||
// an IAVLStore for faster simulation speed.
|
||||
func fauxMerkleModeOpt(bapp *baseapp.BaseApp) {
|
||||
bapp.SetFauxMerkleMode()
|
||||
}
|
||||
|
||||
// NewSimApp disable feemarket on native tx, otherwise the cosmos-sdk simulation tests will fail.
|
||||
func NewSimApp(logger log.Logger, db dbm.DB) (*EthermintApp, error) {
|
||||
encodingConfig := MakeEncodingConfig()
|
||||
app := NewEthermintApp(logger, db, nil, false, map[int64]bool{}, DefaultNodeHome, simapp.FlagPeriodValue, encodingConfig, simapp.EmptyAppOptions{}, fauxMerkleModeOpt)
|
||||
// disable feemarket on native tx
|
||||
anteHandler, err := ante.NewAnteHandler(ante.HandlerOptions{
|
||||
AccountKeeper: app.AccountKeeper,
|
||||
BankKeeper: app.BankKeeper,
|
||||
SignModeHandler: encodingConfig.TxConfig.SignModeHandler(),
|
||||
FeegrantKeeper: app.FeeGrantKeeper,
|
||||
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
|
||||
IBCKeeper: app.IBCKeeper,
|
||||
EvmKeeper: app.EvmKeeper,
|
||||
FeeMarketKeeper: app.FeeMarketKeeper,
|
||||
MaxTxGasWanted: 0,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
app.SetAnteHandler(anteHandler)
|
||||
if err := app.LoadLatestVersion(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return app, nil
|
||||
}
|
||||
|
||||
// interBlockCacheOpt returns a BaseApp option function that sets the persistent
|
||||
// inter-block write-through cache.
|
||||
func interBlockCacheOpt() func(*baseapp.BaseApp) {
|
||||
return baseapp.SetInterBlockCache(store.NewCommitKVStoreCacheManager())
|
||||
}
|
||||
|
||||
func TestFullAppSimulation(t *testing.T) {
|
||||
config, db, dir, logger, skip, err := simapp.SetupSimulation("leveldb-app-sim", "Simulation")
|
||||
if skip {
|
||||
t.Skip("skipping application simulation")
|
||||
}
|
||||
require.NoError(t, err, "simulation setup failed")
|
||||
|
||||
config.ChainID = SimAppChainID
|
||||
|
||||
defer func() {
|
||||
require.NoError(t, db.Close())
|
||||
require.NoError(t, os.RemoveAll(dir))
|
||||
}()
|
||||
|
||||
app, err := NewSimApp(logger, db)
|
||||
require.Equal(t, appName, app.Name())
|
||||
require.NoError(t, err)
|
||||
|
||||
// run randomized simulation
|
||||
_, simParams, simErr := simulation.SimulateFromSeed(
|
||||
t,
|
||||
os.Stdout,
|
||||
app.BaseApp,
|
||||
StateFn(app.AppCodec(), app.SimulationManager()),
|
||||
RandomAccounts, // Replace with own random account function if using keys other than secp256k1
|
||||
simapp.SimulationOperations(app, app.AppCodec(), config),
|
||||
app.ModuleAccountAddrs(),
|
||||
config,
|
||||
app.AppCodec(),
|
||||
)
|
||||
|
||||
// export state and simParams before the simulation error is checked
|
||||
err = simapp.CheckExportSimulation(app, config, simParams)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, simErr)
|
||||
|
||||
if config.Commit {
|
||||
simapp.PrintStats(db)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppImportExport(t *testing.T) {
|
||||
config, db, dir, logger, skip, err := simapp.SetupSimulation("leveldb-app-sim", "Simulation")
|
||||
if skip {
|
||||
t.Skip("skipping application import/export simulation")
|
||||
}
|
||||
require.NoError(t, err, "simulation setup failed")
|
||||
|
||||
config.ChainID = SimAppChainID
|
||||
|
||||
defer func() {
|
||||
require.NoError(t, db.Close())
|
||||
require.NoError(t, os.RemoveAll(dir))
|
||||
}()
|
||||
app, err := NewSimApp(logger, db)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, appName, app.Name())
|
||||
|
||||
// Run randomized simulation
|
||||
_, simParams, simErr := simulation.SimulateFromSeed(
|
||||
t,
|
||||
os.Stdout,
|
||||
app.BaseApp,
|
||||
StateFn(app.AppCodec(), app.SimulationManager()),
|
||||
RandomAccounts, // Replace with own random account function if using keys other than secp256k1
|
||||
simapp.SimulationOperations(app, app.AppCodec(), config),
|
||||
app.ModuleAccountAddrs(),
|
||||
config,
|
||||
app.AppCodec(),
|
||||
)
|
||||
|
||||
// export state and simParams before the simulation error is checked
|
||||
err = simapp.CheckExportSimulation(app, config, simParams)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, simErr)
|
||||
|
||||
if config.Commit {
|
||||
simapp.PrintStats(db)
|
||||
}
|
||||
|
||||
fmt.Printf("exporting genesis...\n")
|
||||
|
||||
exported, err := app.ExportAppStateAndValidators(false, []string{})
|
||||
require.NoError(t, err)
|
||||
|
||||
fmt.Printf("importing genesis...\n")
|
||||
|
||||
//nolint: dogsled
|
||||
_, newDB, newDir, _, _, err := simapp.SetupSimulation("leveldb-app-sim-2", "Simulation-2")
|
||||
require.NoError(t, err, "simulation setup failed")
|
||||
|
||||
defer func() {
|
||||
require.NoError(t, newDB.Close())
|
||||
require.NoError(t, os.RemoveAll(newDir))
|
||||
}()
|
||||
|
||||
newApp, err := NewSimApp(log.NewNopLogger(), newDB)
|
||||
require.Equal(t, appName, newApp.Name())
|
||||
require.NoError(t, err)
|
||||
|
||||
var genesisState simapp.GenesisState
|
||||
err = json.Unmarshal(exported.AppState, &genesisState)
|
||||
require.NoError(t, err)
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err := fmt.Sprintf("%v", r)
|
||||
if !strings.Contains(err, "validator set is empty after InitGenesis") {
|
||||
panic(r)
|
||||
}
|
||||
logger.Info("Skipping simulation as all validators have been unbonded")
|
||||
logger.Info("err", err, "stacktrace", string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
|
||||
ctxA := app.NewContext(true, tmproto.Header{Height: app.LastBlockHeight(), ChainID: SimAppChainID})
|
||||
ctxB := newApp.NewContext(true, tmproto.Header{Height: app.LastBlockHeight(), ChainID: SimAppChainID})
|
||||
newApp.mm.InitGenesis(ctxB, app.AppCodec(), genesisState)
|
||||
newApp.StoreConsensusParams(ctxB, exported.ConsensusParams)
|
||||
|
||||
fmt.Printf("comparing stores...\n")
|
||||
|
||||
storeKeysPrefixes := []storeKeysPrefixes{
|
||||
{app.keys[authtypes.StoreKey], newApp.keys[authtypes.StoreKey], [][]byte{}},
|
||||
{
|
||||
app.keys[stakingtypes.StoreKey], newApp.keys[stakingtypes.StoreKey],
|
||||
[][]byte{
|
||||
stakingtypes.UnbondingQueueKey, stakingtypes.RedelegationQueueKey, stakingtypes.ValidatorQueueKey,
|
||||
stakingtypes.HistoricalInfoKey,
|
||||
},
|
||||
}, // ordering may change but it doesn't matter
|
||||
{app.keys[slashingtypes.StoreKey], newApp.keys[slashingtypes.StoreKey], [][]byte{}},
|
||||
{app.keys[minttypes.StoreKey], newApp.keys[minttypes.StoreKey], [][]byte{}},
|
||||
{app.keys[distrtypes.StoreKey], newApp.keys[distrtypes.StoreKey], [][]byte{}},
|
||||
{app.keys[banktypes.StoreKey], newApp.keys[banktypes.StoreKey], [][]byte{banktypes.BalancesPrefix}},
|
||||
{app.keys[paramtypes.StoreKey], newApp.keys[paramtypes.StoreKey], [][]byte{}},
|
||||
{app.keys[govtypes.StoreKey], newApp.keys[govtypes.StoreKey], [][]byte{}},
|
||||
{app.keys[evidencetypes.StoreKey], newApp.keys[evidencetypes.StoreKey], [][]byte{}},
|
||||
{app.keys[capabilitytypes.StoreKey], newApp.keys[capabilitytypes.StoreKey], [][]byte{}},
|
||||
{app.keys[authzkeeper.StoreKey], newApp.keys[authzkeeper.StoreKey], [][]byte{authzkeeper.GrantKey, authzkeeper.GrantQueuePrefix}},
|
||||
{app.keys[ibchost.StoreKey], newApp.keys[ibchost.StoreKey], [][]byte{}},
|
||||
{app.keys[ibctransfertypes.StoreKey], newApp.keys[ibctransfertypes.StoreKey], [][]byte{}},
|
||||
}
|
||||
|
||||
for _, skp := range storeKeysPrefixes {
|
||||
storeA := ctxA.KVStore(skp.A)
|
||||
storeB := ctxB.KVStore(skp.B)
|
||||
|
||||
failedKVAs, failedKVBs := sdk.DiffKVStores(storeA, storeB, skp.Prefixes)
|
||||
require.Equal(t, len(failedKVAs), len(failedKVBs), "unequal sets of key-values to compare")
|
||||
|
||||
fmt.Printf("compared %d different key/value pairs between %s and %s\n", len(failedKVAs), skp.A, skp.B)
|
||||
require.Equal(t, len(failedKVAs), 0, simapp.GetSimulationLog(skp.A.Name(), app.SimulationManager().StoreDecoders, failedKVAs, failedKVBs))
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppSimulationAfterImport(t *testing.T) {
|
||||
config, db, dir, logger, skip, err := simapp.SetupSimulation("leveldb-app-sim", "Simulation")
|
||||
if skip {
|
||||
t.Skip("skipping application simulation after import")
|
||||
}
|
||||
require.NoError(t, err, "simulation setup failed")
|
||||
|
||||
config.ChainID = SimAppChainID
|
||||
|
||||
defer func() {
|
||||
require.NoError(t, db.Close())
|
||||
require.NoError(t, os.RemoveAll(dir))
|
||||
}()
|
||||
|
||||
app, err := NewSimApp(logger, db)
|
||||
require.Equal(t, appName, app.Name())
|
||||
require.NoError(t, err)
|
||||
|
||||
// Run randomized simulation
|
||||
stopEarly, simParams, simErr := simulation.SimulateFromSeed(
|
||||
t,
|
||||
os.Stdout,
|
||||
app.BaseApp,
|
||||
StateFn(app.AppCodec(), app.SimulationManager()),
|
||||
RandomAccounts, // Replace with own random account function if using keys other than secp256k1
|
||||
simapp.SimulationOperations(app, app.AppCodec(), config),
|
||||
app.ModuleAccountAddrs(),
|
||||
config,
|
||||
app.AppCodec(),
|
||||
)
|
||||
|
||||
// export state and simParams before the simulation error is checked
|
||||
err = simapp.CheckExportSimulation(app, config, simParams)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, simErr)
|
||||
|
||||
if config.Commit {
|
||||
simapp.PrintStats(db)
|
||||
}
|
||||
|
||||
if stopEarly {
|
||||
fmt.Println("can't export or import a zero-validator genesis, exiting test...")
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("exporting genesis...\n")
|
||||
|
||||
exported, err := app.ExportAppStateAndValidators(true, []string{})
|
||||
require.NoError(t, err)
|
||||
|
||||
fmt.Printf("importing genesis...\n")
|
||||
|
||||
_, newDB, newDir, _, _, err := simapp.SetupSimulation("leveldb-app-sim-2", "Simulation-2")
|
||||
require.NoError(t, err, "simulation setup failed")
|
||||
|
||||
defer func() {
|
||||
require.NoError(t, newDB.Close())
|
||||
require.NoError(t, os.RemoveAll(newDir))
|
||||
}()
|
||||
|
||||
newApp, err := NewSimApp(log.NewNopLogger(), newDB)
|
||||
require.Equal(t, appName, newApp.Name())
|
||||
require.NoError(t, err)
|
||||
|
||||
newApp.InitChain(abci.RequestInitChain{
|
||||
ChainId: SimAppChainID,
|
||||
AppStateBytes: exported.AppState,
|
||||
})
|
||||
|
||||
_, _, err = simulation.SimulateFromSeed(
|
||||
t,
|
||||
os.Stdout,
|
||||
newApp.BaseApp,
|
||||
StateFn(app.AppCodec(), app.SimulationManager()),
|
||||
RandomAccounts, // Replace with own random account function if using keys other than secp256k1
|
||||
simapp.SimulationOperations(newApp, newApp.AppCodec(), config),
|
||||
app.ModuleAccountAddrs(),
|
||||
config,
|
||||
app.AppCodec(),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
// TODO: Make another test for the fuzzer itself, which just has noOp txs
|
||||
// and doesn't depend on the application.
|
||||
func TestAppStateDeterminism(t *testing.T) {
|
||||
if !simapp.FlagEnabledValue {
|
||||
t.Skip("skipping application simulation")
|
||||
}
|
||||
|
||||
config := simapp.NewConfigFromFlags()
|
||||
config.InitialBlockHeight = 1
|
||||
config.ExportParamsPath = ""
|
||||
config.OnOperation = false
|
||||
config.AllInvariants = false
|
||||
config.ChainID = SimAppChainID
|
||||
|
||||
numSeeds := 3
|
||||
numTimesToRunPerSeed := 5
|
||||
appHashList := make([]json.RawMessage, numTimesToRunPerSeed)
|
||||
|
||||
for i := 0; i < numSeeds; i++ {
|
||||
config.Seed = rand.Int63()
|
||||
|
||||
for j := 0; j < numTimesToRunPerSeed; j++ {
|
||||
var logger log.Logger
|
||||
if simapp.FlagVerboseValue {
|
||||
logger = log.TestingLogger()
|
||||
} else {
|
||||
logger = log.NewNopLogger()
|
||||
}
|
||||
|
||||
db := dbm.NewMemDB()
|
||||
app, err := NewSimApp(logger, db)
|
||||
require.NoError(t, err)
|
||||
|
||||
fmt.Printf(
|
||||
"running non-determinism simulation; seed %d: %d/%d, attempt: %d/%d\n",
|
||||
config.Seed, i+1, numSeeds, j+1, numTimesToRunPerSeed,
|
||||
)
|
||||
|
||||
_, _, err = simulation.SimulateFromSeed(
|
||||
t,
|
||||
os.Stdout,
|
||||
app.BaseApp,
|
||||
StateFn(app.AppCodec(), app.SimulationManager()),
|
||||
RandomAccounts, // Replace with own random account function if using keys other than secp256k1
|
||||
simapp.SimulationOperations(app, app.AppCodec(), config),
|
||||
app.ModuleAccountAddrs(),
|
||||
config,
|
||||
app.AppCodec(),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
if config.Commit {
|
||||
simapp.PrintStats(db)
|
||||
}
|
||||
|
||||
appHash := app.LastCommitID().Hash
|
||||
appHashList[j] = appHash
|
||||
|
||||
if j != 0 {
|
||||
require.Equal(
|
||||
t, string(appHashList[0]), string(appHashList[j]),
|
||||
"non-determinism in seed %d: %d/%d, attempt: %d/%d\n", config.Seed, i+1, numSeeds, j+1, numTimesToRunPerSeed,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
102
app/utils.go
102
app/utils.go
@ -2,7 +2,6 @@ package app
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
@ -11,21 +10,12 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/mock"
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
|
||||
"github.com/evmos/ethermint/encoding"
|
||||
ethermint "github.com/evmos/ethermint/types"
|
||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/evmos/ethermint/crypto/ethsecp256k1"
|
||||
"github.com/evmos/ethermint/encoding"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
@ -94,96 +84,6 @@ func SetupWithDB(isCheckTx bool, patchGenesis func(*EthermintApp, simapp.Genesis
|
||||
return app
|
||||
}
|
||||
|
||||
// RandomGenesisAccounts is used by the auth module to create random genesis accounts in simulation when a genesis.json is not specified.
|
||||
// In contrast, the default auth module's RandomGenesisAccounts implementation creates only base accounts and vestings accounts.
|
||||
func RandomGenesisAccounts(simState *module.SimulationState) authtypes.GenesisAccounts {
|
||||
emptyCodeHash := crypto.Keccak256(nil)
|
||||
genesisAccs := make(authtypes.GenesisAccounts, len(simState.Accounts))
|
||||
for i, acc := range simState.Accounts {
|
||||
bacc := authtypes.NewBaseAccountWithAddress(acc.Address)
|
||||
|
||||
ethacc := ðermint.EthAccount{
|
||||
BaseAccount: bacc,
|
||||
CodeHash: common.BytesToHash(emptyCodeHash).String(),
|
||||
}
|
||||
genesisAccs[i] = ethacc
|
||||
}
|
||||
|
||||
return genesisAccs
|
||||
}
|
||||
|
||||
// RandomAccounts creates random accounts with an ethsecp256k1 private key
|
||||
// TODO: replace secp256k1.GenPrivKeyFromSecret() with similar function in go-ethereum
|
||||
func RandomAccounts(r *rand.Rand, n int) []simtypes.Account {
|
||||
accs := make([]simtypes.Account, n)
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
// don't need that much entropy for simulation
|
||||
privkeySeed := make([]byte, 15)
|
||||
_, _ = r.Read(privkeySeed)
|
||||
|
||||
prv := secp256k1.GenPrivKeyFromSecret(privkeySeed)
|
||||
ethPrv := ðsecp256k1.PrivKey{}
|
||||
_ = ethPrv.UnmarshalAmino(prv.Bytes()) // UnmarshalAmino simply copies the bytes and assigns them to ethPrv.Key
|
||||
accs[i].PrivKey = ethPrv
|
||||
accs[i].PubKey = accs[i].PrivKey.PubKey()
|
||||
accs[i].Address = sdk.AccAddress(accs[i].PubKey.Address())
|
||||
|
||||
accs[i].ConsKey = ed25519.GenPrivKeyFromSecret(privkeySeed)
|
||||
}
|
||||
|
||||
return accs
|
||||
}
|
||||
|
||||
// StateFn returns the initial application state using a genesis or the simulation parameters.
|
||||
// It is a wrapper of simapp.AppStateFn to replace evm param EvmDenom with staking param BondDenom.
|
||||
func StateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simtypes.AppStateFn {
|
||||
return func(r *rand.Rand, accs []simtypes.Account, config simtypes.Config,
|
||||
) (appState json.RawMessage, simAccs []simtypes.Account, chainID string, genesisTimestamp time.Time) {
|
||||
appStateFn := simapp.AppStateFn(cdc, simManager)
|
||||
appState, simAccs, chainID, genesisTimestamp = appStateFn(r, accs, config)
|
||||
|
||||
rawState := make(map[string]json.RawMessage)
|
||||
err := json.Unmarshal(appState, &rawState)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
stakingStateBz, ok := rawState[stakingtypes.ModuleName]
|
||||
if !ok {
|
||||
panic("staking genesis state is missing")
|
||||
}
|
||||
|
||||
stakingState := new(stakingtypes.GenesisState)
|
||||
cdc.MustUnmarshalJSON(stakingStateBz, stakingState)
|
||||
|
||||
// we should get the BondDenom and make it the evmdenom.
|
||||
// thus simulation accounts could have positive amount of gas token.
|
||||
bondDenom := stakingState.Params.BondDenom
|
||||
|
||||
evmStateBz, ok := rawState[evmtypes.ModuleName]
|
||||
if !ok {
|
||||
panic("evm genesis state is missing")
|
||||
}
|
||||
|
||||
evmState := new(evmtypes.GenesisState)
|
||||
cdc.MustUnmarshalJSON(evmStateBz, evmState)
|
||||
|
||||
// we should replace the EvmDenom with BondDenom
|
||||
evmState.Params.EvmDenom = bondDenom
|
||||
|
||||
// change appState back
|
||||
rawState[evmtypes.ModuleName] = cdc.MustMarshalJSON(evmState)
|
||||
|
||||
// replace appstate
|
||||
appState, err = json.Marshal(rawState)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return appState, simAccs, chainID, genesisTimestamp
|
||||
}
|
||||
}
|
||||
|
||||
// NewTestGenesisState generate genesis state with single validator
|
||||
func NewTestGenesisState(codec codec.Codec) simapp.GenesisState {
|
||||
privVal := mock.NewPV()
|
||||
|
@ -1,113 +0,0 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math/rand"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
paramstypes "github.com/cosmos/cosmos-sdk/x/params/types"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||
|
||||
"github.com/evmos/ethermint/crypto/ethsecp256k1"
|
||||
ethermint "github.com/evmos/ethermint/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
var (
|
||||
maxTestingAccounts = 100
|
||||
seed = int64(233)
|
||||
)
|
||||
|
||||
func TestRandomGenesisAccounts(t *testing.T) {
|
||||
r := rand.New(rand.NewSource(seed))
|
||||
accs := RandomAccounts(r, rand.Intn(maxTestingAccounts))
|
||||
|
||||
encodingConfig := MakeEncodingConfig()
|
||||
appCodec := encodingConfig.Codec
|
||||
cdc := encodingConfig.Amino
|
||||
|
||||
paramsKeeper := initParamsKeeper(appCodec, cdc, sdk.NewKVStoreKey(paramstypes.StoreKey), sdk.NewTransientStoreKey(paramstypes.StoreKey))
|
||||
subSpace, find := paramsKeeper.GetSubspace(authtypes.ModuleName)
|
||||
require.True(t, find)
|
||||
accountKeeper := authkeeper.NewAccountKeeper(
|
||||
appCodec, sdk.NewKVStoreKey(authtypes.StoreKey), subSpace, ethermint.ProtoAccount, maccPerms, sdk.GetConfig().GetBech32AccountAddrPrefix(),
|
||||
)
|
||||
authModule := auth.NewAppModule(appCodec, accountKeeper, RandomGenesisAccounts)
|
||||
|
||||
genesisState := simapp.NewDefaultGenesisState(appCodec)
|
||||
simState := &module.SimulationState{Accounts: accs, Cdc: appCodec, Rand: r, GenState: genesisState}
|
||||
authModule.GenerateGenesisState(simState)
|
||||
|
||||
authStateBz, find := genesisState[authtypes.ModuleName]
|
||||
require.True(t, find)
|
||||
|
||||
authState := new(authtypes.GenesisState)
|
||||
appCodec.MustUnmarshalJSON(authStateBz, authState)
|
||||
accounts, err := authtypes.UnpackAccounts(authState.Accounts)
|
||||
require.NoError(t, err)
|
||||
for _, acc := range accounts {
|
||||
_, ok := acc.(ethermint.EthAccountI)
|
||||
require.True(t, ok)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStateFn(t *testing.T) {
|
||||
config, db, dir, logger, skip, err := simapp.SetupSimulation("leveldb-app-sim", "Simulation")
|
||||
if skip {
|
||||
t.Skip("skipping AppStateFn testing")
|
||||
}
|
||||
require.NoError(t, err, "simulation setup failed")
|
||||
|
||||
config.ChainID = SimAppChainID
|
||||
config.Commit = true
|
||||
|
||||
defer func() {
|
||||
db.Close()
|
||||
require.NoError(t, os.RemoveAll(dir))
|
||||
}()
|
||||
|
||||
app := NewEthermintApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, simapp.FlagPeriodValue, MakeEncodingConfig(), simapp.EmptyAppOptions{}, fauxMerkleModeOpt)
|
||||
require.Equal(t, appName, app.Name())
|
||||
|
||||
appStateFn := StateFn(app.AppCodec(), app.SimulationManager())
|
||||
r := rand.New(rand.NewSource(seed))
|
||||
accounts := RandomAccounts(r, rand.Intn(maxTestingAccounts))
|
||||
appState, _, _, _ := appStateFn(r, accounts, config)
|
||||
|
||||
rawState := make(map[string]json.RawMessage)
|
||||
err = json.Unmarshal(appState, &rawState)
|
||||
require.NoError(t, err)
|
||||
|
||||
stakingStateBz, ok := rawState[stakingtypes.ModuleName]
|
||||
require.True(t, ok)
|
||||
|
||||
stakingState := new(stakingtypes.GenesisState)
|
||||
app.AppCodec().MustUnmarshalJSON(stakingStateBz, stakingState)
|
||||
bondDenom := stakingState.Params.BondDenom
|
||||
|
||||
evmStateBz, ok := rawState[evmtypes.ModuleName]
|
||||
require.True(t, ok)
|
||||
|
||||
evmState := new(evmtypes.GenesisState)
|
||||
app.AppCodec().MustUnmarshalJSON(evmStateBz, evmState)
|
||||
require.Equal(t, bondDenom, evmState.Params.EvmDenom)
|
||||
}
|
||||
|
||||
func TestRandomAccounts(t *testing.T) {
|
||||
r := rand.New(rand.NewSource(seed))
|
||||
accounts := RandomAccounts(r, rand.Intn(maxTestingAccounts))
|
||||
for _, acc := range accounts {
|
||||
_, ok := acc.PrivKey.(*ethsecp256k1.PrivKey)
|
||||
require.True(t, ok)
|
||||
}
|
||||
}
|
@ -1,4 +1,3 @@
|
||||
version: v1
|
||||
directories:
|
||||
- proto
|
||||
- third_party/proto
|
||||
|
@ -13,57 +13,6 @@
|
||||
"Params": "EvmParams"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "./tmp-swagger-gen/cosmos/auth/v1beta1/query.swagger.json",
|
||||
"operationIds": {
|
||||
"rename": {
|
||||
"Account": "AuthAccount",
|
||||
"Params": "AuthParams"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "./tmp-swagger-gen/cosmos/bank/v1beta1/query.swagger.json",
|
||||
"operationIds": {
|
||||
"rename": {
|
||||
"Balance": "BankBalance",
|
||||
"Params": "BankParams"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "./tmp-swagger-gen/cosmos/distribution/v1beta1/query.swagger.json",
|
||||
"operationIds": {
|
||||
"rename": {
|
||||
"Params": "DistributionParams",
|
||||
"DelegatorValidators": "DistDelegatorValidators"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "./tmp-swagger-gen/cosmos/mint/v1beta1/query.swagger.json",
|
||||
"operationIds": {
|
||||
"rename": {
|
||||
"Params": "MintParams"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "./tmp-swagger-gen/cosmos/gov/v1beta1/query.swagger.json",
|
||||
"operationIds": {
|
||||
"rename": {
|
||||
"Params": "GovParams"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "./tmp-swagger-gen/cosmos/staking/v1beta1/query.swagger.json",
|
||||
"operationIds": {
|
||||
"rename": {
|
||||
"Params": "StakingParams"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
7
client/docs/statik/statik.go
vendored
7
client/docs/statik/statik.go
vendored
File diff suppressed because one or more lines are too long
17067
client/docs/swagger-ui/swagger.yaml
vendored
17067
client/docs/swagger-ui/swagger.yaml
vendored
File diff suppressed because it is too large
Load Diff
@ -37,6 +37,7 @@ import (
|
||||
"github.com/evmos/ethermint/client/debug"
|
||||
"github.com/evmos/ethermint/crypto/hd"
|
||||
"github.com/evmos/ethermint/encoding"
|
||||
"github.com/evmos/ethermint/ethereum/eip712"
|
||||
"github.com/evmos/ethermint/server"
|
||||
servercfg "github.com/evmos/ethermint/server/config"
|
||||
srvflags "github.com/evmos/ethermint/server/flags"
|
||||
@ -61,6 +62,8 @@ func NewRootCmd() (*cobra.Command, params.EncodingConfig) {
|
||||
WithKeyringOptions(hd.EthSecp256k1Option()).
|
||||
WithViper(EnvPrefix)
|
||||
|
||||
eip712.SetEncodingConfig(encodingConfig)
|
||||
|
||||
rootCmd := &cobra.Command{
|
||||
Use: "ethermintd",
|
||||
Short: "Ethermint Daemon",
|
||||
@ -179,6 +182,7 @@ func txCommand() *cobra.Command {
|
||||
authcmd.GetBroadcastCommand(),
|
||||
authcmd.GetEncodeCommand(),
|
||||
authcmd.GetDecodeCommand(),
|
||||
authcmd.GetAuxToFeeCommand(),
|
||||
)
|
||||
|
||||
app.ModuleBasics.AddTxCommands(cmd)
|
||||
|
@ -6,11 +6,12 @@ import (
|
||||
"crypto/subtle"
|
||||
"fmt"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
|
||||
"github.com/evmos/ethermint/ethereum/eip712"
|
||||
tmcrypto "github.com/tendermint/tendermint/crypto"
|
||||
)
|
||||
|
||||
@ -182,7 +183,7 @@ func (pubKey PubKey) MarshalAmino() ([]byte, error) {
|
||||
// UnmarshalAmino overrides Amino binary marshaling.
|
||||
func (pubKey *PubKey) UnmarshalAmino(bz []byte) error {
|
||||
if len(bz) != PubKeySize {
|
||||
return sdkerrors.Wrapf(sdkerrors.ErrInvalidPubKey, "invalid pubkey size, expected %d, got %d", PubKeySize, len(bz))
|
||||
return errorsmod.Wrapf(errortypes.ErrInvalidPubKey, "invalid pubkey size, expected %d, got %d", PubKeySize, len(bz))
|
||||
}
|
||||
pubKey.Key = bz
|
||||
|
||||
@ -203,10 +204,28 @@ func (pubKey *PubKey) UnmarshalAminoJSON(bz []byte) error {
|
||||
|
||||
// VerifySignature verifies that the ECDSA public key created a given signature over
|
||||
// the provided message. It will calculate the Keccak256 hash of the message
|
||||
// prior to verification.
|
||||
// prior to verification and approve verification if the signature can be verified
|
||||
// from either the original message or its EIP-712 representation.
|
||||
//
|
||||
// CONTRACT: The signature should be in [R || S] format.
|
||||
func (pubKey PubKey) VerifySignature(msg, sig []byte) bool {
|
||||
return pubKey.verifySignatureECDSA(msg, sig) || pubKey.verifySignatureAsEIP712(msg, sig)
|
||||
}
|
||||
|
||||
// Verifies the signature as an EIP-712 signature by first converting the message payload
|
||||
// to an EIP-712 hashed object, performing ECDSA verification on the hash. This is to support
|
||||
// signing a Cosmos payload using EIP-712.
|
||||
func (pubKey PubKey) verifySignatureAsEIP712(msg, sig []byte) bool {
|
||||
eip712Hash, err := eip712.GetEIP712HashForMsg(msg)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return pubKey.verifySignatureECDSA(eip712Hash, sig)
|
||||
}
|
||||
|
||||
// Perform standard ECDSA signature verification for the given raw bytes and signature.
|
||||
func (pubKey PubKey) verifySignatureECDSA(msg, sig []byte) bool {
|
||||
if len(sig) == crypto.SignatureLength {
|
||||
// remove recovery ID (V) if contained in the signature
|
||||
sig = sig[:len(sig)-1]
|
||||
|
4
crypto/ethsecp256k1/keys.pb.go
generated
4
crypto/ethsecp256k1/keys.pb.go
generated
@ -5,7 +5,7 @@ package ethsecp256k1
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
_ "github.com/cosmos/gogoproto/gogoproto"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
io "io"
|
||||
math "math"
|
||||
@ -27,6 +27,7 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
// Tendermint's PubKey interface. It represents the 33-byte compressed public
|
||||
// key format.
|
||||
type PubKey struct {
|
||||
// key is the public key in byte form
|
||||
Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
|
||||
}
|
||||
|
||||
@ -72,6 +73,7 @@ func (m *PubKey) GetKey() []byte {
|
||||
// PrivKey defines a type alias for an ecdsa.PrivateKey that implements
|
||||
// Tendermint's PrivateKey interface.
|
||||
type PrivKey struct {
|
||||
// key is the private key in byte form
|
||||
Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package hd
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@ -10,7 +11,6 @@ import (
|
||||
|
||||
hdwallet "github.com/miguelmota/go-ethereum-hdwallet"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
amino "github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
@ -20,10 +20,10 @@ import (
|
||||
ethermint "github.com/evmos/ethermint/types"
|
||||
)
|
||||
|
||||
var TestCodec codec.Codec
|
||||
var TestCodec amino.Codec
|
||||
|
||||
func init() {
|
||||
cdc := codec.NewLegacyAmino()
|
||||
cdc := amino.NewLegacyAmino()
|
||||
cryptocodec.RegisterCrypto(cdc)
|
||||
|
||||
interfaceRegistry := types.NewInterfaceRegistry()
|
||||
@ -31,12 +31,18 @@ func init() {
|
||||
enccodec.RegisterInterfaces(interfaceRegistry)
|
||||
}
|
||||
|
||||
const mnemonic = "picnic rent average infant boat squirrel federal assault mercy purity very motor fossil wheel verify upset box fresh horse vivid copy predict square regret"
|
||||
const (
|
||||
mnemonic = "picnic rent average infant boat squirrel federal assault mercy purity very motor fossil wheel verify upset box fresh horse vivid copy predict square regret"
|
||||
|
||||
// hdWalletFixEnv defines whether the standard (correct) bip39
|
||||
// derivation path was used, or if derivation was affected by
|
||||
// https://github.com/btcsuite/btcutil/issues/172
|
||||
hdWalletFixEnv = "GO_ETHEREUM_HDWALLET_FIX_ISSUE_179"
|
||||
)
|
||||
|
||||
func TestKeyring(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
mockIn := strings.NewReader("")
|
||||
|
||||
kr, err := keyring.New("ethermint", keyring.BackendTest, dir, mockIn, TestCodec, EthSecp256k1Option())
|
||||
require.NoError(t, err)
|
||||
|
||||
@ -68,7 +74,9 @@ func TestKeyring(t *testing.T) {
|
||||
privkey := EthSecp256k1.Generate()(bz)
|
||||
addr := common.BytesToAddress(privkey.PubKey().Address().Bytes())
|
||||
|
||||
os.Setenv(hdWalletFixEnv, "true")
|
||||
wallet, err := hdwallet.NewFromMnemonic(mnemonic)
|
||||
os.Setenv(hdWalletFixEnv, "")
|
||||
require.NoError(t, err)
|
||||
|
||||
path := hdwallet.MustParseDerivationPath(hdPath)
|
||||
|
@ -275,6 +275,7 @@ TraceConfig holds extra parameters to trace functions.
|
||||
| `overrides` | [ChainConfig](#ethermint.evm.v1.ChainConfig) | | Chain overrides, can be used to execute a trace using future fork rules |
|
||||
| `enable_memory` | [bool](#bool) | | enable memory capture |
|
||||
| `enable_return_data` | [bool](#bool) | | enable return data capture |
|
||||
| `tracer_json_config` | [string](#string) | | tracer config |
|
||||
|
||||
|
||||
|
||||
@ -563,6 +564,7 @@ EthCallRequest defines EthCall request
|
||||
| `args` | [bytes](#bytes) | | same json format as the json rpc api. |
|
||||
| `gas_cap` | [uint64](#uint64) | | the default gas cap to be used |
|
||||
| `proposer_address` | [bytes](#bytes) | | the proposer of the requested block |
|
||||
| `chain_id` | [int64](#int64) | | the eip155 chain id parsed from the requested block header |
|
||||
|
||||
|
||||
|
||||
@ -793,6 +795,7 @@ QueryTraceBlockRequest defines TraceTx request
|
||||
| `block_hash` | [string](#string) | | block hex hash |
|
||||
| `block_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | block time |
|
||||
| `proposer_address` | [bytes](#bytes) | | the proposer of the requested block |
|
||||
| `chain_id` | [int64](#int64) | | the eip155 chain id parsed from the requested block header |
|
||||
|
||||
|
||||
|
||||
@ -829,6 +832,7 @@ QueryTraceTxRequest defines TraceTx request
|
||||
| `block_hash` | [string](#string) | | block hex hash of requested transaction |
|
||||
| `block_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | block time of requested transaction |
|
||||
| `proposer_address` | [bytes](#bytes) | | the proposer of the requested block |
|
||||
| `chain_id` | [int64](#int64) | | the eip155 chain id parsed from the requested block header |
|
||||
|
||||
|
||||
|
||||
|
@ -14,34 +14,16 @@ import (
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/language"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/math"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
||||
)
|
||||
|
||||
// ComputeTypedDataHash computes keccak hash of typed data for signing.
|
||||
func ComputeTypedDataHash(typedData apitypes.TypedData) ([]byte, error) {
|
||||
domainSeparator, err := typedData.HashStruct("EIP712Domain", typedData.Domain.Map())
|
||||
if err != nil {
|
||||
err = sdkerrors.Wrap(err, "failed to pack and hash typedData EIP712Domain")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
typedDataHash, err := typedData.HashStruct(typedData.PrimaryType, typedData.Message)
|
||||
if err != nil {
|
||||
err = sdkerrors.Wrap(err, "failed to pack and hash typedData primary type")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rawData := []byte(fmt.Sprintf("\x19\x01%s%s", string(domainSeparator), string(typedDataHash)))
|
||||
return crypto.Keccak256(rawData), nil
|
||||
}
|
||||
|
||||
// WrapTxToTypedData is an ultimate method that wraps Amino-encoded Cosmos Tx JSON data
|
||||
// into an EIP712-compatible TypedData request.
|
||||
func WrapTxToTypedData(
|
||||
@ -54,7 +36,7 @@ func WrapTxToTypedData(
|
||||
txData := make(map[string]interface{})
|
||||
|
||||
if err := json.Unmarshal(data, &txData); err != nil {
|
||||
return apitypes.TypedData{}, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, "failed to JSON unmarshal data")
|
||||
return apitypes.TypedData{}, errorsmod.Wrap(errortypes.ErrJSONUnmarshal, "failed to JSON unmarshal data")
|
||||
}
|
||||
|
||||
domain := apitypes.TypedDataDomain{
|
||||
@ -73,7 +55,7 @@ func WrapTxToTypedData(
|
||||
if feeDelegation != nil {
|
||||
feeInfo, ok := txData["fee"].(map[string]interface{})
|
||||
if !ok {
|
||||
return apitypes.TypedData{}, sdkerrors.Wrap(sdkerrors.ErrInvalidType, "cannot parse fee from tx data")
|
||||
return apitypes.TypedData{}, errorsmod.Wrap(errortypes.ErrInvalidType, "cannot parse fee from tx data")
|
||||
}
|
||||
|
||||
feeInfo["feePayer"] = feeDelegation.FeePayer.String()
|
||||
@ -206,7 +188,11 @@ func traverseFields(
|
||||
}
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
var field reflect.Value
|
||||
var (
|
||||
field reflect.Value
|
||||
err error
|
||||
)
|
||||
|
||||
if v.IsValid() {
|
||||
field = v.Field(i)
|
||||
}
|
||||
@ -215,27 +201,14 @@ func traverseFields(
|
||||
fieldName := jsonNameFromTag(t.Field(i).Tag)
|
||||
|
||||
if fieldType == cosmosAnyType {
|
||||
any, ok := field.Interface().(*codectypes.Any)
|
||||
if !ok {
|
||||
return sdkerrors.Wrapf(sdkerrors.ErrPackAny, "%T", field.Interface())
|
||||
// Unpack field, value as Any
|
||||
if fieldType, field, err = unpackAny(cdc, field); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
anyWrapper := &cosmosAnyWrapper{
|
||||
Type: any.TypeUrl,
|
||||
}
|
||||
|
||||
if err := cdc.UnpackAny(any, &anyWrapper.Value); err != nil {
|
||||
return sdkerrors.Wrap(err, "failed to unpack Any in msg struct")
|
||||
}
|
||||
|
||||
fieldType = reflect.TypeOf(anyWrapper)
|
||||
field = reflect.ValueOf(anyWrapper)
|
||||
|
||||
// then continue as normal
|
||||
}
|
||||
|
||||
// If its a nil pointer, do not include in types
|
||||
if fieldType.Kind() == reflect.Ptr && field.IsNil() {
|
||||
// If field is an empty value, do not include in types, since it will not be present in the object
|
||||
if field.IsZero() {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -273,6 +246,12 @@ func traverseFields(
|
||||
fieldType = fieldType.Elem()
|
||||
field = field.Index(0)
|
||||
isCollection = true
|
||||
|
||||
if fieldType == cosmosAnyType {
|
||||
if fieldType, field, err = unpackAny(cdc, field); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for {
|
||||
@ -363,6 +342,27 @@ func jsonNameFromTag(tag reflect.StructTag) string {
|
||||
return parts[0]
|
||||
}
|
||||
|
||||
// Unpack the given Any value with Type/Value deconstruction
|
||||
func unpackAny(cdc codectypes.AnyUnpacker, field reflect.Value) (reflect.Type, reflect.Value, error) {
|
||||
any, ok := field.Interface().(*codectypes.Any)
|
||||
if !ok {
|
||||
return nil, reflect.Value{}, errorsmod.Wrapf(errortypes.ErrPackAny, "%T", field.Interface())
|
||||
}
|
||||
|
||||
anyWrapper := &cosmosAnyWrapper{
|
||||
Type: any.TypeUrl,
|
||||
}
|
||||
|
||||
if err := cdc.UnpackAny(any, &anyWrapper.Value); err != nil {
|
||||
return nil, reflect.Value{}, errorsmod.Wrap(err, "failed to unpack Any in msg struct")
|
||||
}
|
||||
|
||||
fieldType := reflect.TypeOf(anyWrapper)
|
||||
field = reflect.ValueOf(anyWrapper)
|
||||
|
||||
return fieldType, field, nil
|
||||
}
|
||||
|
||||
// _.foo_bar.baz -> TypeFooBarBaz
|
||||
//
|
||||
// this is needed for Geth's own signing code which doesn't
|
||||
@ -465,7 +465,7 @@ func typToEth(typ reflect.Type) string {
|
||||
func doRecover(err *error) {
|
||||
if r := recover(); r != nil {
|
||||
if e, ok := r.(error); ok {
|
||||
e = sdkerrors.Wrap(e, "panicked with error")
|
||||
e = errorsmod.Wrap(e, "panicked with error")
|
||||
*err = e
|
||||
return
|
||||
}
|
||||
|
433
ethereum/eip712/eip712_test.go
Normal file
433
ethereum/eip712/eip712_test.go
Normal file
@ -0,0 +1,433 @@
|
||||
package eip712_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/simapp/params"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/evmos/ethermint/ethereum/eip712"
|
||||
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/evmos/ethermint/crypto/ethsecp256k1"
|
||||
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
"github.com/evmos/ethermint/app"
|
||||
"github.com/evmos/ethermint/encoding"
|
||||
|
||||
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||
|
||||
distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
// Unit tests for single-signer EIP-712 signature verification. Multi-signer verification tests are included
|
||||
// in ante_test.go.
|
||||
|
||||
type EIP712TestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
config params.EncodingConfig
|
||||
clientCtx client.Context
|
||||
}
|
||||
|
||||
func TestEIP712TestSuite(t *testing.T) {
|
||||
suite.Run(t, &EIP712TestSuite{})
|
||||
}
|
||||
|
||||
// Set up test env to replicate prod. environment
|
||||
func (suite *EIP712TestSuite) SetupTest() {
|
||||
suite.config = encoding.MakeConfig(app.ModuleBasics)
|
||||
suite.clientCtx = client.Context{}.WithTxConfig(suite.config.TxConfig)
|
||||
|
||||
sdk.GetConfig().SetBech32PrefixForAccount("ethm", "")
|
||||
eip712.SetEncodingConfig(suite.config)
|
||||
}
|
||||
|
||||
// Helper to create random test addresses for messages
|
||||
func (suite *EIP712TestSuite) createTestAddress() sdk.AccAddress {
|
||||
privkey, _ := ethsecp256k1.GenerateKey()
|
||||
key, err := privkey.ToECDSA()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
addr := crypto.PubkeyToAddress(key.PublicKey)
|
||||
|
||||
return addr.Bytes()
|
||||
}
|
||||
|
||||
// Helper to create random keypair for signing + verification
|
||||
func (suite *EIP712TestSuite) createTestKeyPair() (*ethsecp256k1.PrivKey, *ethsecp256k1.PubKey) {
|
||||
privKey, err := ethsecp256k1.GenerateKey()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
pubKey := ðsecp256k1.PubKey{
|
||||
Key: privKey.PubKey().Bytes(),
|
||||
}
|
||||
suite.Require().Implements((*cryptotypes.PubKey)(nil), pubKey)
|
||||
|
||||
return privKey, pubKey
|
||||
}
|
||||
|
||||
// Helper to create instance of sdk.Coins[] with single coin
|
||||
func (suite *EIP712TestSuite) makeCoins(denom string, amount math.Int) sdk.Coins {
|
||||
return sdk.NewCoins(
|
||||
sdk.NewCoin(
|
||||
denom,
|
||||
amount,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *EIP712TestSuite) TestEIP712SignatureVerification() {
|
||||
suite.SetupTest()
|
||||
|
||||
signModes := []signing.SignMode{
|
||||
signing.SignMode_SIGN_MODE_DIRECT,
|
||||
signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
|
||||
}
|
||||
|
||||
// Fixed test address
|
||||
testAddress := suite.createTestAddress()
|
||||
|
||||
testCases := []struct {
|
||||
title string
|
||||
chainId string
|
||||
fee txtypes.Fee
|
||||
memo string
|
||||
msgs []sdk.Msg
|
||||
accountNumber uint64
|
||||
sequence uint64
|
||||
timeoutHeight uint64
|
||||
expectSuccess bool
|
||||
}{
|
||||
{
|
||||
title: "Succeeds - Standard MsgSend",
|
||||
fee: txtypes.Fee{
|
||||
Amount: suite.makeCoins("aphoton", math.NewInt(2000)),
|
||||
GasLimit: 20000,
|
||||
},
|
||||
memo: "",
|
||||
msgs: []sdk.Msg{
|
||||
banktypes.NewMsgSend(
|
||||
suite.createTestAddress(),
|
||||
suite.createTestAddress(),
|
||||
suite.makeCoins("photon", math.NewInt(1)),
|
||||
),
|
||||
},
|
||||
accountNumber: 8,
|
||||
sequence: 5,
|
||||
expectSuccess: true,
|
||||
},
|
||||
{
|
||||
title: "Succeeds - Standard MsgVote",
|
||||
fee: txtypes.Fee{
|
||||
Amount: suite.makeCoins("aphoton", math.NewInt(2000)),
|
||||
GasLimit: 20000,
|
||||
},
|
||||
memo: "",
|
||||
msgs: []sdk.Msg{
|
||||
govtypes.NewMsgVote(
|
||||
suite.createTestAddress(),
|
||||
5,
|
||||
govtypes.OptionNo,
|
||||
),
|
||||
},
|
||||
accountNumber: 25,
|
||||
sequence: 78,
|
||||
expectSuccess: true,
|
||||
},
|
||||
{
|
||||
title: "Succeeds - Standard MsgDelegate",
|
||||
fee: txtypes.Fee{
|
||||
Amount: suite.makeCoins("aphoton", math.NewInt(2000)),
|
||||
GasLimit: 20000,
|
||||
},
|
||||
memo: "",
|
||||
msgs: []sdk.Msg{
|
||||
stakingtypes.NewMsgDelegate(
|
||||
suite.createTestAddress(),
|
||||
sdk.ValAddress(suite.createTestAddress()),
|
||||
suite.makeCoins("photon", math.NewInt(1))[0],
|
||||
),
|
||||
},
|
||||
accountNumber: 25,
|
||||
sequence: 78,
|
||||
expectSuccess: true,
|
||||
},
|
||||
{
|
||||
title: "Succeeds - Standard MsgWithdrawDelegationReward",
|
||||
fee: txtypes.Fee{
|
||||
Amount: suite.makeCoins("aphoton", math.NewInt(2000)),
|
||||
GasLimit: 20000,
|
||||
},
|
||||
memo: "",
|
||||
msgs: []sdk.Msg{
|
||||
distributiontypes.NewMsgWithdrawDelegatorReward(
|
||||
suite.createTestAddress(),
|
||||
sdk.ValAddress(suite.createTestAddress()),
|
||||
),
|
||||
},
|
||||
accountNumber: 25,
|
||||
sequence: 78,
|
||||
expectSuccess: true,
|
||||
},
|
||||
{
|
||||
title: "Succeeds - Two Single-Signer MsgDelegate",
|
||||
fee: txtypes.Fee{
|
||||
Amount: suite.makeCoins("aphoton", math.NewInt(2000)),
|
||||
GasLimit: 20000,
|
||||
},
|
||||
memo: "",
|
||||
msgs: []sdk.Msg{
|
||||
stakingtypes.NewMsgDelegate(
|
||||
testAddress,
|
||||
sdk.ValAddress(suite.createTestAddress()),
|
||||
suite.makeCoins("photon", math.NewInt(1))[0],
|
||||
),
|
||||
stakingtypes.NewMsgDelegate(
|
||||
testAddress,
|
||||
sdk.ValAddress(suite.createTestAddress()),
|
||||
suite.makeCoins("photon", math.NewInt(5))[0],
|
||||
),
|
||||
},
|
||||
accountNumber: 25,
|
||||
sequence: 78,
|
||||
expectSuccess: true,
|
||||
},
|
||||
{
|
||||
title: "Fails - Two MsgVotes with Different Signers",
|
||||
fee: txtypes.Fee{
|
||||
Amount: suite.makeCoins("aphoton", math.NewInt(2000)),
|
||||
GasLimit: 20000,
|
||||
},
|
||||
memo: "",
|
||||
msgs: []sdk.Msg{
|
||||
govtypes.NewMsgVote(
|
||||
suite.createTestAddress(),
|
||||
5,
|
||||
govtypes.OptionNo,
|
||||
),
|
||||
govtypes.NewMsgVote(
|
||||
suite.createTestAddress(),
|
||||
25,
|
||||
govtypes.OptionAbstain,
|
||||
),
|
||||
},
|
||||
accountNumber: 25,
|
||||
sequence: 78,
|
||||
expectSuccess: false,
|
||||
},
|
||||
{
|
||||
title: "Fails - Empty transaction",
|
||||
fee: txtypes.Fee{
|
||||
Amount: suite.makeCoins("aphoton", math.NewInt(2000)),
|
||||
GasLimit: 20000,
|
||||
},
|
||||
memo: "",
|
||||
msgs: []sdk.Msg{},
|
||||
accountNumber: 25,
|
||||
sequence: 78,
|
||||
expectSuccess: false,
|
||||
},
|
||||
{
|
||||
title: "Fails - Single-Signer MsgSend + MsgVote",
|
||||
fee: txtypes.Fee{
|
||||
Amount: suite.makeCoins("aphoton", math.NewInt(2000)),
|
||||
GasLimit: 20000,
|
||||
},
|
||||
memo: "",
|
||||
msgs: []sdk.Msg{
|
||||
govtypes.NewMsgVote(
|
||||
testAddress,
|
||||
5,
|
||||
govtypes.OptionNo,
|
||||
),
|
||||
banktypes.NewMsgSend(
|
||||
testAddress,
|
||||
suite.createTestAddress(),
|
||||
suite.makeCoins("photon", math.NewInt(50)),
|
||||
),
|
||||
},
|
||||
accountNumber: 25,
|
||||
sequence: 78,
|
||||
expectSuccess: false,
|
||||
},
|
||||
{
|
||||
title: "Fails - Invalid ChainID",
|
||||
chainId: "invalidchainid",
|
||||
fee: txtypes.Fee{
|
||||
Amount: suite.makeCoins("aphoton", math.NewInt(2000)),
|
||||
GasLimit: 20000,
|
||||
},
|
||||
memo: "",
|
||||
msgs: []sdk.Msg{
|
||||
govtypes.NewMsgVote(
|
||||
suite.createTestAddress(),
|
||||
5,
|
||||
govtypes.OptionNo,
|
||||
),
|
||||
},
|
||||
accountNumber: 25,
|
||||
sequence: 78,
|
||||
expectSuccess: false,
|
||||
},
|
||||
{
|
||||
title: "Fails - Includes TimeoutHeight",
|
||||
fee: txtypes.Fee{
|
||||
Amount: suite.makeCoins("aphoton", math.NewInt(2000)),
|
||||
GasLimit: 20000,
|
||||
},
|
||||
memo: "",
|
||||
msgs: []sdk.Msg{
|
||||
govtypes.NewMsgVote(
|
||||
suite.createTestAddress(),
|
||||
5,
|
||||
govtypes.OptionNo,
|
||||
),
|
||||
},
|
||||
accountNumber: 25,
|
||||
sequence: 78,
|
||||
timeoutHeight: 1000,
|
||||
expectSuccess: false,
|
||||
},
|
||||
{
|
||||
title: "Fails - Single Message / Multi-Signer",
|
||||
fee: txtypes.Fee{
|
||||
Amount: suite.makeCoins("aphoton", math.NewInt(2000)),
|
||||
GasLimit: 20000,
|
||||
},
|
||||
memo: "",
|
||||
msgs: []sdk.Msg{
|
||||
banktypes.NewMsgMultiSend(
|
||||
[]banktypes.Input{
|
||||
banktypes.NewInput(
|
||||
suite.createTestAddress(),
|
||||
suite.makeCoins("photon", math.NewInt(50)),
|
||||
),
|
||||
banktypes.NewInput(
|
||||
suite.createTestAddress(),
|
||||
suite.makeCoins("photon", math.NewInt(50)),
|
||||
),
|
||||
},
|
||||
[]banktypes.Output{
|
||||
banktypes.NewOutput(
|
||||
suite.createTestAddress(),
|
||||
suite.makeCoins("photon", math.NewInt(50)),
|
||||
),
|
||||
banktypes.NewOutput(
|
||||
suite.createTestAddress(),
|
||||
suite.makeCoins("photon", math.NewInt(50)),
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
accountNumber: 25,
|
||||
sequence: 78,
|
||||
expectSuccess: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
for _, signMode := range signModes {
|
||||
suite.Run(tc.title, func() {
|
||||
privKey, pubKey := suite.createTestKeyPair()
|
||||
|
||||
// Init tx builder
|
||||
txBuilder := suite.clientCtx.TxConfig.NewTxBuilder()
|
||||
|
||||
// Set gas and fees
|
||||
txBuilder.SetGasLimit(tc.fee.GasLimit)
|
||||
txBuilder.SetFeeAmount(tc.fee.Amount)
|
||||
|
||||
// Set messages
|
||||
err := txBuilder.SetMsgs(tc.msgs...)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Set memo
|
||||
txBuilder.SetMemo(tc.memo)
|
||||
|
||||
// Prepare signature field
|
||||
txSigData := signing.SingleSignatureData{
|
||||
SignMode: signMode,
|
||||
Signature: nil,
|
||||
}
|
||||
txSig := signing.SignatureV2{
|
||||
PubKey: pubKey,
|
||||
Data: &txSigData,
|
||||
Sequence: tc.sequence,
|
||||
}
|
||||
|
||||
err = txBuilder.SetSignatures([]signing.SignatureV2{txSig}...)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
chainId := "ethermint_9000-1"
|
||||
if tc.chainId != "" {
|
||||
chainId = tc.chainId
|
||||
}
|
||||
|
||||
if tc.timeoutHeight != 0 {
|
||||
txBuilder.SetTimeoutHeight(tc.timeoutHeight)
|
||||
}
|
||||
|
||||
// Declare signerData
|
||||
signerData := authsigning.SignerData{
|
||||
ChainID: chainId,
|
||||
AccountNumber: tc.accountNumber,
|
||||
Sequence: tc.sequence,
|
||||
PubKey: pubKey,
|
||||
Address: sdk.MustBech32ifyAddressBytes("ethm", pubKey.Bytes()),
|
||||
}
|
||||
|
||||
bz, err := suite.clientCtx.TxConfig.SignModeHandler().GetSignBytes(
|
||||
signMode,
|
||||
signerData,
|
||||
txBuilder.GetTx(),
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.verifyEIP712SignatureVerification(tc.expectSuccess, *privKey, *pubKey, bz)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Verify that the payload passes signature verification if signed as its EIP-712 representation.
|
||||
func (suite *EIP712TestSuite) verifyEIP712SignatureVerification(expectedSuccess bool, privKey ethsecp256k1.PrivKey, pubKey ethsecp256k1.PubKey, signBytes []byte) {
|
||||
// Convert to EIP712 hash and sign
|
||||
eip712Hash, err := eip712.GetEIP712HashForMsg(signBytes)
|
||||
if !expectedSuccess {
|
||||
// Expect failure generating EIP-712 hash
|
||||
suite.Require().Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
suite.Require().NoError(err)
|
||||
|
||||
sigHash := crypto.Keccak256Hash(eip712Hash)
|
||||
sig, err := privKey.Sign(sigHash.Bytes())
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Verify against original payload bytes. This should pass, even though it is not
|
||||
// the original message that was signed.
|
||||
res := pubKey.VerifySignature(signBytes, sig)
|
||||
suite.Require().True(res)
|
||||
|
||||
// Verify against the signed EIP-712 bytes. This should pass, since it is the message signed.
|
||||
res = pubKey.VerifySignature(eip712Hash, sig)
|
||||
suite.Require().True(res)
|
||||
|
||||
// Verify against random bytes to ensure it does not pass unexpectedly (sanity check).
|
||||
randBytes := make([]byte, len(signBytes))
|
||||
copy(randBytes, signBytes)
|
||||
// Change the first element of signBytes to a different value
|
||||
randBytes[0] = (signBytes[0] + 10) % 128
|
||||
res = pubKey.VerifySignature(randBytes, sig)
|
||||
suite.Require().False(res)
|
||||
}
|
285
ethereum/eip712/encoding.go
Normal file
285
ethereum/eip712/encoding.go
Normal file
@ -0,0 +1,285 @@
|
||||
package eip712
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/simapp/params"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
txTypes "github.com/cosmos/cosmos-sdk/types/tx"
|
||||
|
||||
apitypes "github.com/ethereum/go-ethereum/signer/core/apitypes"
|
||||
ethermint "github.com/evmos/ethermint/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
)
|
||||
|
||||
type aminoMessage struct {
|
||||
Type string `json:"type"`
|
||||
Value interface{} `json:"value"`
|
||||
}
|
||||
|
||||
var (
|
||||
protoCodec codec.ProtoCodecMarshaler
|
||||
aminoCodec *codec.LegacyAmino
|
||||
)
|
||||
|
||||
// SetEncodingConfig set the encoding config to the singleton codecs (Amino and Protobuf).
|
||||
// The process of unmarshaling SignDoc bytes into a SignDoc object requires having a codec
|
||||
// populated with all relevant message types. As a result, we must call this method on app
|
||||
// initialization with the app's encoding config.
|
||||
func SetEncodingConfig(cfg params.EncodingConfig) {
|
||||
aminoCodec = cfg.Amino
|
||||
protoCodec = codec.NewProtoCodec(cfg.InterfaceRegistry)
|
||||
}
|
||||
|
||||
// Get the EIP-712 object hash for the given SignDoc bytes by first decoding the bytes into
|
||||
// an EIP-712 object, then hashing the EIP-712 object to create the bytes to be signed.
|
||||
// See https://eips.ethereum.org/EIPS/eip-712 for more.
|
||||
func GetEIP712HashForMsg(signDocBytes []byte) ([]byte, error) {
|
||||
typedData, err := GetEIP712TypedDataForMsg(signDocBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
domainSeparator, err := typedData.HashStruct("EIP712Domain", typedData.Domain.Map())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not hash EIP-712 domain: %w", err)
|
||||
}
|
||||
|
||||
typedDataHash, err := typedData.HashStruct(typedData.PrimaryType, typedData.Message)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not hash EIP-712 primary type: %w", err)
|
||||
}
|
||||
rawData := []byte(fmt.Sprintf("\x19\x01%s%s", string(domainSeparator), string(typedDataHash)))
|
||||
|
||||
return rawData, nil
|
||||
}
|
||||
|
||||
// GetEIP712TypedDataForMsg returns the EIP-712 TypedData representation for either
|
||||
// Amino or Protobuf encoded signature doc bytes.
|
||||
func GetEIP712TypedDataForMsg(signDocBytes []byte) (apitypes.TypedData, error) {
|
||||
// Attempt to decode as both Amino and Protobuf since the message format is unknown.
|
||||
// If either decode works, we can move forward with the corresponding typed data.
|
||||
typedDataAmino, errAmino := decodeAminoSignDoc(signDocBytes)
|
||||
if errAmino == nil && isValidEIP712Payload(typedDataAmino) {
|
||||
return typedDataAmino, nil
|
||||
}
|
||||
typedDataProtobuf, errProtobuf := decodeProtobufSignDoc(signDocBytes)
|
||||
if errProtobuf == nil && isValidEIP712Payload(typedDataProtobuf) {
|
||||
return typedDataProtobuf, nil
|
||||
}
|
||||
|
||||
return apitypes.TypedData{}, fmt.Errorf("could not decode sign doc as either Amino or Protobuf.\n amino: %v\n protobuf: %v", errAmino, errProtobuf)
|
||||
}
|
||||
|
||||
// isValidEIP712Payload ensures that the given TypedData does not contain empty fields from
|
||||
// an improper initialization.
|
||||
func isValidEIP712Payload(typedData apitypes.TypedData) bool {
|
||||
return len(typedData.Message) != 0 && len(typedData.Types) != 0 && typedData.PrimaryType != "" && typedData.Domain != apitypes.TypedDataDomain{}
|
||||
}
|
||||
|
||||
// decodeAminoSignDoc attempts to decode the provided sign doc (bytes) as an Amino payload
|
||||
// and returns a signable EIP-712 TypedData object.
|
||||
func decodeAminoSignDoc(signDocBytes []byte) (apitypes.TypedData, error) {
|
||||
var aminoDoc legacytx.StdSignDoc
|
||||
if err := aminoCodec.UnmarshalJSON(signDocBytes, &aminoDoc); err != nil {
|
||||
return apitypes.TypedData{}, err
|
||||
}
|
||||
|
||||
var fees legacytx.StdFee
|
||||
if err := aminoCodec.UnmarshalJSON(aminoDoc.Fee, &fees); err != nil {
|
||||
return apitypes.TypedData{}, err
|
||||
}
|
||||
|
||||
// Validate payload messages
|
||||
msgs := make([]sdk.Msg, len(aminoDoc.Msgs))
|
||||
for i, jsonMsg := range aminoDoc.Msgs {
|
||||
var m sdk.Msg
|
||||
if err := aminoCodec.UnmarshalJSON(jsonMsg, &m); err != nil {
|
||||
return apitypes.TypedData{}, fmt.Errorf("failed to unmarshal sign doc message: %w", err)
|
||||
}
|
||||
msgs[i] = m
|
||||
}
|
||||
|
||||
if err := validatePayloadMessages(msgs); err != nil {
|
||||
return apitypes.TypedData{}, err
|
||||
}
|
||||
|
||||
// Use first message for fee payer and type inference
|
||||
msg := msgs[0]
|
||||
|
||||
// By convention, the fee payer is the first address in the list of signers.
|
||||
feePayer := msg.GetSigners()[0]
|
||||
feeDelegation := &FeeDelegationOptions{
|
||||
FeePayer: feePayer,
|
||||
}
|
||||
|
||||
chainID, err := ethermint.ParseChainID(aminoDoc.ChainID)
|
||||
if err != nil {
|
||||
return apitypes.TypedData{}, errors.New("invalid chain ID passed as argument")
|
||||
}
|
||||
|
||||
typedData, err := WrapTxToTypedData(
|
||||
protoCodec,
|
||||
chainID.Uint64(),
|
||||
msg,
|
||||
signDocBytes,
|
||||
feeDelegation,
|
||||
)
|
||||
if err != nil {
|
||||
return apitypes.TypedData{}, fmt.Errorf("could not convert to EIP712 representation: %w", err)
|
||||
}
|
||||
|
||||
return typedData, nil
|
||||
}
|
||||
|
||||
// decodeProtobufSignDoc attempts to decode the provided sign doc (bytes) as a Protobuf payload
|
||||
// and returns a signable EIP-712 TypedData object.
|
||||
func decodeProtobufSignDoc(signDocBytes []byte) (apitypes.TypedData, error) {
|
||||
signDoc := &txTypes.SignDoc{}
|
||||
if err := signDoc.Unmarshal(signDocBytes); err != nil {
|
||||
return apitypes.TypedData{}, err
|
||||
}
|
||||
|
||||
authInfo := &txTypes.AuthInfo{}
|
||||
if err := authInfo.Unmarshal(signDoc.AuthInfoBytes); err != nil {
|
||||
return apitypes.TypedData{}, err
|
||||
}
|
||||
|
||||
body := &txTypes.TxBody{}
|
||||
if err := body.Unmarshal(signDoc.BodyBytes); err != nil {
|
||||
return apitypes.TypedData{}, err
|
||||
}
|
||||
|
||||
// Until support for these fields is added, throw an error at their presence
|
||||
if body.TimeoutHeight != 0 || len(body.ExtensionOptions) != 0 || len(body.NonCriticalExtensionOptions) != 0 {
|
||||
return apitypes.TypedData{}, errors.New("body contains unsupported fields: TimeoutHeight, ExtensionOptions, or NonCriticalExtensionOptions")
|
||||
}
|
||||
|
||||
if len(authInfo.SignerInfos) != 1 {
|
||||
return apitypes.TypedData{}, fmt.Errorf("invalid number of signer infos provided, expected 1 got %v", len(authInfo.SignerInfos))
|
||||
}
|
||||
|
||||
// Validate payload messages
|
||||
msgs := make([]sdk.Msg, len(body.Messages))
|
||||
for i, protoMsg := range body.Messages {
|
||||
var m sdk.Msg
|
||||
if err := protoCodec.UnpackAny(protoMsg, &m); err != nil {
|
||||
return apitypes.TypedData{}, fmt.Errorf("could not unpack message object with error %w", err)
|
||||
}
|
||||
msgs[i] = m
|
||||
}
|
||||
|
||||
if err := validatePayloadMessages(msgs); err != nil {
|
||||
return apitypes.TypedData{}, err
|
||||
}
|
||||
|
||||
// Use first message for fee payer and type inference
|
||||
msg := msgs[0]
|
||||
|
||||
signerInfo := authInfo.SignerInfos[0]
|
||||
|
||||
chainID, err := ethermint.ParseChainID(signDoc.ChainId)
|
||||
if err != nil {
|
||||
return apitypes.TypedData{}, fmt.Errorf("invalid chain ID passed as argument: %w", err)
|
||||
}
|
||||
|
||||
stdFee := &legacytx.StdFee{
|
||||
Amount: authInfo.Fee.Amount,
|
||||
Gas: authInfo.Fee.GasLimit,
|
||||
}
|
||||
|
||||
feePayer := msg.GetSigners()[0]
|
||||
feeDelegation := &FeeDelegationOptions{
|
||||
FeePayer: feePayer,
|
||||
}
|
||||
|
||||
tip := authInfo.Tip
|
||||
|
||||
// WrapTxToTypedData expects the payload as an Amino Sign Doc
|
||||
signBytes := legacytx.StdSignBytes(
|
||||
signDoc.ChainId,
|
||||
signDoc.AccountNumber,
|
||||
signerInfo.Sequence,
|
||||
body.TimeoutHeight,
|
||||
*stdFee,
|
||||
msgs,
|
||||
body.Memo,
|
||||
tip,
|
||||
)
|
||||
|
||||
typedData, err := WrapTxToTypedData(
|
||||
protoCodec,
|
||||
chainID.Uint64(),
|
||||
msg,
|
||||
signBytes,
|
||||
feeDelegation,
|
||||
)
|
||||
if err != nil {
|
||||
return apitypes.TypedData{}, err
|
||||
}
|
||||
|
||||
return typedData, nil
|
||||
}
|
||||
|
||||
// validatePayloadMessages ensures that the transaction messages can be represented in an EIP-712
|
||||
// encoding by checking that messages exist, are of the same type, and share a single signer.
|
||||
func validatePayloadMessages(msgs []sdk.Msg) error {
|
||||
if len(msgs) == 0 {
|
||||
return errors.New("unable to build EIP-712 payload: transaction does contain any messages")
|
||||
}
|
||||
|
||||
var msgType string
|
||||
var msgSigner sdk.AccAddress
|
||||
|
||||
for i, m := range msgs {
|
||||
t, err := getMsgType(m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(m.GetSigners()) != 1 {
|
||||
return errors.New("unable to build EIP-712 payload: expect exactly 1 signer")
|
||||
}
|
||||
|
||||
if i == 0 {
|
||||
msgType = t
|
||||
msgSigner = m.GetSigners()[0]
|
||||
continue
|
||||
}
|
||||
|
||||
if t != msgType {
|
||||
return errors.New("unable to build EIP-712 payload: different types of messages detected")
|
||||
}
|
||||
|
||||
if !msgSigner.Equals(m.GetSigners()[0]) {
|
||||
return errors.New("unable to build EIP-712 payload: multiple signers detected")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getMsgType returns the message type prefix for the given Cosmos SDK Msg
|
||||
func getMsgType(msg sdk.Msg) (string, error) {
|
||||
jsonBytes, err := aminoCodec.MarshalJSON(msg)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var jsonMsg aminoMessage
|
||||
if err := json.Unmarshal(jsonBytes, &jsonMsg); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Verify Type was successfully filled in
|
||||
if jsonMsg.Type == "" {
|
||||
return "", errors.New("could not decode message: type is missing")
|
||||
}
|
||||
|
||||
return jsonMsg.Type, nil
|
||||
}
|
63
go.mod
63
go.mod
@ -3,15 +3,18 @@ module github.com/evmos/ethermint
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
cosmossdk.io/math v1.0.0-beta.3
|
||||
cosmossdk.io/errors v1.0.0-beta.7
|
||||
cosmossdk.io/math v1.0.0-beta.4
|
||||
github.com/armon/go-metrics v0.4.1
|
||||
github.com/btcsuite/btcd v0.22.1
|
||||
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce
|
||||
github.com/cosmos/cosmos-sdk v0.46.4
|
||||
github.com/cosmos/cosmos-proto v1.0.0-alpha8
|
||||
github.com/cosmos/cosmos-sdk v0.46.6
|
||||
github.com/cosmos/go-bip39 v1.0.0
|
||||
github.com/cosmos/ibc-go/v5 v5.0.1
|
||||
github.com/cosmos/gogoproto v1.4.3
|
||||
github.com/cosmos/ibc-go/v5 v5.1.0
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/ethereum/go-ethereum v1.10.19
|
||||
github.com/ethereum/go-ethereum v1.10.25
|
||||
github.com/gogo/protobuf v1.3.3
|
||||
github.com/golang/protobuf v1.5.2
|
||||
github.com/gorilla/mux v1.8.0
|
||||
@ -20,34 +23,32 @@ require (
|
||||
github.com/holiman/uint256 v1.2.1
|
||||
github.com/improbable-eng/grpc-web v0.15.0
|
||||
github.com/miguelmota/go-ethereum-hdwallet v0.1.1
|
||||
github.com/onsi/ginkgo/v2 v2.4.0
|
||||
github.com/onsi/gomega v1.23.0
|
||||
github.com/onsi/ginkgo/v2 v2.5.1
|
||||
github.com/onsi/gomega v1.24.1
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/rakyll/statik v0.1.7
|
||||
github.com/regen-network/cosmos-proto v0.3.1
|
||||
github.com/rs/cors v1.8.2
|
||||
github.com/spf13/cast v1.5.0
|
||||
github.com/spf13/cobra v1.6.1
|
||||
github.com/spf13/viper v1.13.0
|
||||
github.com/spf13/viper v1.14.0
|
||||
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969
|
||||
github.com/stretchr/testify v1.8.1
|
||||
github.com/tendermint/tendermint v0.34.22
|
||||
github.com/tendermint/tendermint v0.34.23
|
||||
github.com/tendermint/tm-db v0.6.7
|
||||
github.com/tyler-smith/go-bip39 v1.1.0
|
||||
golang.org/x/net v0.1.0
|
||||
golang.org/x/net v0.2.0
|
||||
golang.org/x/text v0.4.0
|
||||
google.golang.org/genproto v0.0.0-20221018160656-63c7b68cfc55
|
||||
google.golang.org/grpc v1.50.1
|
||||
google.golang.org/protobuf v1.28.1
|
||||
google.golang.org/genproto v0.0.0-20221116193143-41c2ba794472
|
||||
google.golang.org/grpc v1.51.0
|
||||
sigs.k8s.io/yaml v1.3.0
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.102.1 // indirect
|
||||
cloud.google.com/go/compute v1.7.0 // indirect
|
||||
cloud.google.com/go/iam v0.4.0 // indirect
|
||||
cloud.google.com/go/storage v1.22.1 // indirect
|
||||
cosmossdk.io/errors v1.0.0-beta.7 // indirect
|
||||
cloud.google.com/go v0.105.0 // indirect
|
||||
cloud.google.com/go/compute v1.12.1 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.2.1 // indirect
|
||||
cloud.google.com/go/iam v0.7.0 // indirect
|
||||
cloud.google.com/go/storage v1.27.0 // indirect
|
||||
filippo.io/edwards25519 v1.0.0-rc.1 // indirect
|
||||
github.com/99designs/keyring v1.2.1 // indirect
|
||||
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect
|
||||
@ -68,7 +69,6 @@ require (
|
||||
github.com/coinbase/rosetta-sdk-go v0.7.9 // indirect
|
||||
github.com/confio/ics23/go v0.7.0 // indirect
|
||||
github.com/cosmos/btcutil v1.0.4 // indirect
|
||||
github.com/cosmos/cosmos-proto v1.0.0-alpha7 // indirect
|
||||
github.com/cosmos/gorocksdb v1.2.0 // indirect
|
||||
github.com/cosmos/iavl v0.19.4 // indirect
|
||||
github.com/cosmos/ledger-cosmos-go v0.11.1 // indirect
|
||||
@ -87,7 +87,7 @@ require (
|
||||
github.com/dvsekhvalnov/jose2go v1.5.0 // indirect
|
||||
github.com/edsrzf/mmap-go v1.0.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.1 // indirect
|
||||
github.com/fsnotify/fsnotify v1.5.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect
|
||||
github.com/go-kit/kit v0.12.0 // indirect
|
||||
github.com/go-kit/log v0.2.1 // indirect
|
||||
@ -105,9 +105,8 @@ require (
|
||||
github.com/google/go-cmp v0.5.9 // indirect
|
||||
github.com/google/orderedcode v0.0.1 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.1.0 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.4.0 // indirect
|
||||
github.com/googleapis/go-type-adapters v1.0.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.6.0 // indirect
|
||||
github.com/gorilla/handlers v1.5.1 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
|
||||
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect
|
||||
@ -128,7 +127,7 @@ require (
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/jmhodges/levigo v1.0.0 // indirect
|
||||
github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d // indirect
|
||||
github.com/klauspost/compress v1.15.9 // indirect
|
||||
github.com/klauspost/compress v1.15.11 // indirect
|
||||
github.com/lib/pq v1.10.6 // indirect
|
||||
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
|
||||
github.com/magiconair/properties v1.8.6 // indirect
|
||||
@ -151,9 +150,10 @@ require (
|
||||
github.com/prometheus/client_golang v1.12.2 // indirect
|
||||
github.com/prometheus/client_model v0.2.0 // indirect
|
||||
github.com/prometheus/common v0.34.0 // indirect
|
||||
github.com/prometheus/procfs v0.7.3 // indirect
|
||||
github.com/prometheus/procfs v0.8.0 // indirect
|
||||
github.com/prometheus/tsdb v0.7.1 // indirect
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
|
||||
github.com/regen-network/cosmos-proto v0.3.1 // indirect
|
||||
github.com/rjeczalik/notify v0.9.1 // indirect
|
||||
github.com/rs/zerolog v1.27.0 // indirect
|
||||
github.com/sasha-s/go-deadlock v0.3.1 // indirect
|
||||
@ -173,15 +173,16 @@ require (
|
||||
github.com/zondax/hid v0.9.1-0.20220302062450-5552068d2266 // indirect
|
||||
go.etcd.io/bbolt v1.3.6 // indirect
|
||||
go.opencensus.io v0.23.0 // indirect
|
||||
golang.org/x/crypto v0.1.0 // indirect
|
||||
golang.org/x/crypto v0.3.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2 // indirect
|
||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde // indirect
|
||||
golang.org/x/sys v0.1.0 // indirect
|
||||
golang.org/x/term v0.1.0 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect
|
||||
golang.org/x/sync v0.1.0 // indirect
|
||||
golang.org/x/sys v0.2.0 // indirect
|
||||
golang.org/x/term v0.2.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
google.golang.org/api v0.93.0 // indirect
|
||||
google.golang.org/api v0.102.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
|
317
go.sum
317
go.sum
@ -19,21 +19,8 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb
|
||||
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.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 h1:vpK6iQWv/2uUeFJth4/cBHsQAGjn1iIE6AAlxipRaA0=
|
||||
cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU=
|
||||
cloud.google.com/go v0.105.0 h1:DNtEKRBAAzeS4KyIory52wWHuClNaXJ5x1F7xa4q+5Y=
|
||||
cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM=
|
||||
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=
|
||||
@ -41,18 +28,15 @@ cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUM
|
||||
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/bigtable v1.2.0/go.mod h1:JcVAOl45lrTmQfLj7T6TxyMzIN/3FGGcFm+2xVAli2o=
|
||||
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 h1:v/k9Eueb8aAJ0vZuxKMrgm6kPhCLZU9HxFU+AFDs9Uk=
|
||||
cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U=
|
||||
cloud.google.com/go/compute v1.12.1 h1:gKVJMEyqV5c/UnpzjjQbo3Rjvvqpr9B1DFSbJC4OXr0=
|
||||
cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU=
|
||||
cloud.google.com/go/compute/metadata v0.2.1 h1:efOwf5ymceDhK6PKMnnrTHP4pppY5L22mle96M1yP48=
|
||||
cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM=
|
||||
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/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY=
|
||||
cloud.google.com/go/iam v0.4.0 h1:YBYU00SCDzZJdHqVc4I5d6lsklcYIjQZa1YmEz4jlSE=
|
||||
cloud.google.com/go/iam v0.4.0/go.mod h1:cbaZxyScUhxl7ZAkNWiALgihfP75wS/fUsVNaa1r3vA=
|
||||
cloud.google.com/go/iam v0.7.0 h1:k4MuwOsS7zGJJ+QfZ5vBK8SgHBAvYN/23BWsiihJ1vs=
|
||||
cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg=
|
||||
cloud.google.com/go/longrunning v0.3.0 h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs=
|
||||
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=
|
||||
@ -63,13 +47,13 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
|
||||
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 h1:F6IlQJZrZM++apn9V5/VfS3gbTUYg98PS3EMQAzqtfg=
|
||||
cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y=
|
||||
cloud.google.com/go/storage v1.27.0 h1:YOO045NZI9RKfCj1c5A/ZtuuENUc8OAW+gHdGnDgyMQ=
|
||||
cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s=
|
||||
collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE=
|
||||
cosmossdk.io/errors v1.0.0-beta.7 h1:gypHW76pTQGVnHKo6QBkb4yFOJjC+sUGRc5Al3Odj1w=
|
||||
cosmossdk.io/errors v1.0.0-beta.7/go.mod h1:mz6FQMJRku4bY7aqS/Gwfcmr/ue91roMEKAmDUDpBfE=
|
||||
cosmossdk.io/math v1.0.0-beta.3 h1:TbZxSopz2LqjJ7aXYfn7nJSb8vNaBklW6BLpcei1qwM=
|
||||
cosmossdk.io/math v1.0.0-beta.3/go.mod h1:3LYasri3Zna4XpbrTNdKsWmD5fHHkaNAod/mNT9XdE4=
|
||||
cosmossdk.io/math v1.0.0-beta.4 h1:JtKedVLGzA0vv84xjYmZ75RKG35Kf2WwcFu8IjRkIIw=
|
||||
cosmossdk.io/math v1.0.0-beta.4/go.mod h1:An0MllWJY6PxibUpnwGk8jOm+a/qIxlKmL5Zyp9NnaM=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU=
|
||||
filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
|
||||
@ -100,7 +84,7 @@ github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q
|
||||
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
github.com/DataDog/zstd v1.5.0/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA=
|
||||
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
|
||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
|
||||
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
@ -222,12 +206,6 @@ github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3h
|
||||
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/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/cockroachdb/apd/v2 v2.0.2 h1:weh8u7Cneje73dDh+2tEVLUvyBc89iwepWCD8b8034E=
|
||||
github.com/cockroachdb/apd/v2 v2.0.2/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw=
|
||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||
@ -248,29 +226,33 @@ github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1
|
||||
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cosmos/btcutil v1.0.4 h1:n7C2ngKXo7UC9gNyMNLbzqz7Asuf+7Qv4gnX/rOdQ44=
|
||||
github.com/cosmos/btcutil v1.0.4/go.mod h1:Ffqc8Hn6TJUdDgHBwIZLtrLQC1KdJ9jGJl/TvgUaxbU=
|
||||
github.com/cosmos/cosmos-proto v1.0.0-alpha7 h1:yqYUOHF2jopwZh4dVQp3xgqwftE5/2hkrwIV6vkUbO0=
|
||||
github.com/cosmos/cosmos-proto v1.0.0-alpha7/go.mod h1:dosO4pSAbJF8zWCzCoTWP7nNsjcvSUBQmniFxDg5daw=
|
||||
github.com/cosmos/cosmos-sdk v0.46.4 h1:I4CPfnz7lAPM7cEvvyTxL1h3M/ugbhTNr5ZRcnW8WsU=
|
||||
github.com/cosmos/cosmos-sdk v0.46.4/go.mod h1:b5usG7aBEEvhaatYCdV6orFbDUsj4BG1V6UtKwNcJeQ=
|
||||
github.com/cosmos/cosmos-proto v1.0.0-alpha8 h1:d3pCRuMYYvGA5bM0ZbbjKn+AoQD4A7dyNG2wzwWalUw=
|
||||
github.com/cosmos/cosmos-proto v1.0.0-alpha8/go.mod h1:6/p+Bc4O8JKeZqe0VqUGTX31eoYqemTT4C1hLCWsO7I=
|
||||
github.com/cosmos/cosmos-sdk v0.46.6 h1:K9EZsqOZ2jQX3bIQUpn7Hk/YCoaJWRLU56PzvpX8INk=
|
||||
github.com/cosmos/cosmos-sdk v0.46.6/go.mod h1:JNklMfXo7MhDF1j/jxZCmDyOYyqhVoKB22e8p1ATEqA=
|
||||
github.com/cosmos/cosmos-sdk/ics23/go v0.8.0 h1:iKclrn3YEOwk4jQHT2ulgzuXyxmzmPczUalMwW4XH9k=
|
||||
github.com/cosmos/cosmos-sdk/ics23/go v0.8.0/go.mod h1:2a4dBq88TUoqoWAU5eu0lGvpFP3wWDPgdHPargtyw30=
|
||||
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y=
|
||||
github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY=
|
||||
github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw=
|
||||
github.com/cosmos/gogoproto v1.4.3 h1:RP3yyVREh9snv/lsOvmsAPQt8f44LgL281X0IOIhhcI=
|
||||
github.com/cosmos/gogoproto v1.4.3/go.mod h1:0hLIG5TR7IvV1fme1HCFKjfzW9X2x0Mo+RooWXCnOWU=
|
||||
github.com/cosmos/gorocksdb v1.2.0 h1:d0l3jJG8M4hBouIZq0mDUHZ+zjOx044J3nGRskwTb4Y=
|
||||
github.com/cosmos/gorocksdb v1.2.0/go.mod h1:aaKvKItm514hKfNJpUJXnnOWeBnk2GL4+Qw9NHizILw=
|
||||
github.com/cosmos/iavl v0.19.4 h1:t82sN+Y0WeqxDLJRSpNd8YFX5URIrT+p8n6oJbJ2Dok=
|
||||
github.com/cosmos/iavl v0.19.4/go.mod h1:X9PKD3J0iFxdmgNLa7b2LYWdsGd90ToV5cAONApkEPw=
|
||||
github.com/cosmos/ibc-go/v5 v5.0.1 h1:ZI5xCi6RDOL+hyu6Wx/w6JoAYFlOoK5hijsRTVWo+RA=
|
||||
github.com/cosmos/ibc-go/v5 v5.0.1/go.mod h1:LX0DHLW3dfi/1e4BJzi8MGLWmQ4DSraPEgVjyo3VzAo=
|
||||
github.com/cosmos/ibc-go/v5 v5.1.0 h1:m1NHXFkwwvNeJegZqtyox1WLinh+PMy4ivU/Cs9KjeA=
|
||||
github.com/cosmos/ibc-go/v5 v5.1.0/go.mod h1:H6sV0/CkNRDtvSrhbsIgiog1WnSwhguGfg8x34MOVEk=
|
||||
github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76 h1:DdzS1m6o/pCqeZ8VOAit/gyATedRgjvkVI+UCrLpyuU=
|
||||
github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76/go.mod h1:0mkLWIoZuQ7uBoospo5Q9zIpqq6rYCPJDSUdeCJvPM8=
|
||||
github.com/cosmos/ledger-cosmos-go v0.11.1 h1:9JIYsGnXP613pb2vPjFeMMjBI5lEDsEaF6oYorTy6J4=
|
||||
github.com/cosmos/ledger-cosmos-go v0.11.1/go.mod h1:J8//BsAGTo3OC/vDLjMRFLW6q0WAaXvHnVc7ZmE8iUY=
|
||||
github.com/cosmos/ledger-go v0.9.2 h1:Nnao/dLwaVTk1Q5U9THldpUMMXU94BOTWPddSmVB6pI=
|
||||
github.com/cosmos/ledger-go v0.9.2/go.mod h1:oZJ2hHAZROdlHiwTg4t7kP+GKIIkBT+o6c9QWFanOyI=
|
||||
github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk=
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creachadair/taskgroup v0.3.2 h1:zlfutDS+5XG40AOxcHDSThxKzns8Tnr9jnr6VqkYlkM=
|
||||
github.com/creachadair/taskgroup v0.3.2/go.mod h1:wieWwecHVzsidg2CsUnFinW1faVN4+kq+TDlRJQ0Wbk=
|
||||
@ -316,7 +298,7 @@ github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/
|
||||
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
|
||||
github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA=
|
||||
github.com/dop251/goja v0.0.0-20211011172007-d99e4b8cbf48/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk=
|
||||
github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf h1:Yt+4K30SdjOkRoRRm3vYNQgR+/ZIy0RmeUDZo7Y8zeQ=
|
||||
@ -340,15 +322,11 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m
|
||||
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/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg=
|
||||
github.com/ethereum/go-ethereum v1.10.17/go.mod h1:Lt5WzjM07XlXc95YzrhosmR4J9Ahd6X2wyEV2SvGhk0=
|
||||
github.com/ethereum/go-ethereum v1.10.19 h1:EOR5JbL4MD5yeOqv8W2iC1s4NximrTjqFccUz8lyBRA=
|
||||
github.com/ethereum/go-ethereum v1.10.19/go.mod h1:IJBNMtzKcNHPtllYihy6BL2IgK1u+32JriaTbdt4v+w=
|
||||
github.com/ethereum/go-ethereum v1.10.25 h1:5dFrKJDnYf8L6/5o42abCE6a9yJm9cs4EJVRyYMr55s=
|
||||
github.com/ethereum/go-ethereum v1.10.25/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg=
|
||||
github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0=
|
||||
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A=
|
||||
github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk=
|
||||
@ -365,8 +343,8 @@ github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2
|
||||
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
|
||||
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
|
||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI=
|
||||
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
|
||||
github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
|
||||
@ -450,9 +428,7 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
|
||||
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=
|
||||
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=
|
||||
@ -469,7 +445,6 @@ 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 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
@ -494,9 +469,6 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.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 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
||||
@ -508,7 +480,6 @@ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXi
|
||||
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 h1:d8MncMlErDFTwQGBK1xhv026j9kqhvw1Qv9IbWT1VLQ=
|
||||
github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
|
||||
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=
|
||||
@ -521,11 +492,6 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf
|
||||
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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
@ -534,19 +500,12 @@ github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
|
||||
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.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 h1:zO8WHNx/MYiAKJ3d5spxZXZE6KHmIQGQcAzwUzV7qQw=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.0 h1:y8Yozv7SZtlU//QXbezB6QkpuE6jMD2/gfzk4AftXjs=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg=
|
||||
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 h1:dS9eYAjhrE2RjmzYw2XAPvcXfmcQLtFEQWn0CR82awk=
|
||||
github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c=
|
||||
github.com/googleapis/go-type-adapters v1.0.0 h1:9XdMn+d/G57qq1s8dNc5IesGCXHf6V2HZ2JwRxfA2tA=
|
||||
github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4=
|
||||
github.com/googleapis/gax-go/v2 v2.6.0 h1:SXk3ABtQYDT/OH8jAyvEOQ58mgawq5C4o/4/89qN2ZU=
|
||||
github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY=
|
||||
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
@ -698,8 +657,8 @@ github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs
|
||||
github.com/klauspost/compress v1.11.2/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||
github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
|
||||
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||
github.com/klauspost/compress v1.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c=
|
||||
github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
|
||||
github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg=
|
||||
github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||
@ -830,17 +789,17 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA=
|
||||
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||
github.com/onsi/ginkgo/v2 v2.4.0 h1:+Ig9nvqgS5OBSACXNk15PLdp0U9XPYROt9CFzVdFGIs=
|
||||
github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo=
|
||||
github.com/onsi/ginkgo/v2 v2.5.1 h1:auzK7OI497k6x4OvWq+TKAcpcSAlod0doAH72oIN0Jw=
|
||||
github.com/onsi/ginkgo/v2 v2.5.1/go.mod h1:63DOGlLAH8+REH8jUGdL3YpCpu7JODesutUjdENfUAc=
|
||||
github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.23.0 h1:/oxKu9c2HVap+F3PfKort2Hw5DEU+HGlW8n+tguWsys=
|
||||
github.com/onsi/gomega v1.23.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg=
|
||||
github.com/onsi/gomega v1.24.1 h1:KORJXNNTzJXzu4ScJWssJfJMnJ+2QJqhoQSRwNlze9E=
|
||||
github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM=
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 h1:rc3tiVYb5z54aKaDfakKn0dDjIyPpTtszkjuMzyt7ec=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034=
|
||||
github.com/opencontainers/runc v1.1.3 h1:vIXrkId+0/J2Ymu2m7VjGvbSlAId9XNRPhn2p4b+d8w=
|
||||
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
|
||||
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
|
||||
@ -918,8 +877,9 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx
|
||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
|
||||
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
|
||||
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
|
||||
github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ=
|
||||
@ -937,15 +897,17 @@ github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRr
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
|
||||
github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg=
|
||||
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||
github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U=
|
||||
github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
|
||||
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rs/zerolog v1.27.0 h1:1T7qCieN22GVc8S4Q2yuexzBb1EqjbgjSH9RohbMjKs=
|
||||
github.com/rs/zerolog v1.27.0/go.mod h1:7frBqO0oezxmnO7GF86FY++uy8I0Tk/If5ni1G9Qc0U=
|
||||
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
||||
@ -989,8 +951,8 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||
github.com/spf13/viper v1.13.0 h1:BWSJ/M+f+3nmdz9bxB+bWX28kkALN2ok11D0rSo8EJU=
|
||||
github.com/spf13/viper v1.13.0/go.mod h1:Icm2xNL3/8uyh/wFuB1jI7TiTNKp8632Nwegu+zgdYw=
|
||||
github.com/spf13/viper v1.14.0 h1:Rg7d3Lo706X9tHsJMUjdiwMpHB7W8WnSVOssIY+JElU=
|
||||
github.com/spf13/viper v1.14.0/go.mod h1:WT//axPky3FdvXHzGw33dNdXXXfFQqmEalje+egj8As=
|
||||
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
|
||||
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969 h1:Oo2KZNP70KE0+IUJSidPj/BFS/RXNHmKIJOdckzml2E=
|
||||
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
|
||||
@ -1025,8 +987,8 @@ github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 h1:hqAk8riJvK4RM
|
||||
github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15/go.mod h1:z4YtwM70uOnk8h0pjJYlj3zdYwi9l03By6iAIF5j/Pk=
|
||||
github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E=
|
||||
github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME=
|
||||
github.com/tendermint/tendermint v0.34.22 h1:XMhtC8s8QqJO4l/dn+TkQvevTRSow3Vixjclr41o+2Q=
|
||||
github.com/tendermint/tendermint v0.34.22/go.mod h1:YpP5vBEAKUT4g6oyfjKgFeZmdB/GjkJAxfF+cgmJg6Y=
|
||||
github.com/tendermint/tendermint v0.34.23 h1:JZYsdc59aOiT5efou+BHILJv8x6FlRyvlor84Xq9Tb0=
|
||||
github.com/tendermint/tendermint v0.34.23/go.mod h1:rXVrl4OYzmIa1I91av3iLv2HS0fGSiucyW9J4aMTpKI=
|
||||
github.com/tendermint/tm-db v0.6.7 h1:fE00Cbl0jayAoqlExN6oyQJ7fR/ZtoVOmvPJ//+shu8=
|
||||
github.com/tendermint/tm-db v0.6.7/go.mod h1:byQDzFkZV1syXr/ReXS808NxA2xvyuuVgXOJ/088L6I=
|
||||
github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
@ -1057,8 +1019,10 @@ github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLY
|
||||
github.com/ulikunitz/xz v0.5.8 h1:ERv8V6GKqVi23rgu5cj9pVfVzJbOqAY2Ntl88O6c2nQ=
|
||||
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY=
|
||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||
github.com/urfave/cli/v2 v2.10.2 h1:x3p8awjp/2arX+Nl/G2040AZpOCHS/eMJJ1/a+mye4Y=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
@ -1068,6 +1032,7 @@ github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPyS
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
|
||||
github.com/ybbus/jsonrpc v2.1.2+incompatible/go.mod h1:XJrh1eMSzdIYFbM08flv0wp5G35eRniyeGut1z+LSiE=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
@ -1091,7 +1056,6 @@ 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 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
|
||||
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
@ -1123,8 +1087,8 @@ golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/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.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
|
||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||
golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A=
|
||||
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
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/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
@ -1155,7 +1119,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu
|
||||
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=
|
||||
@ -1167,6 +1130,7 @@ 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.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
|
||||
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@ -1215,9 +1179,7 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/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-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
@ -1225,13 +1187,8 @@ golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||
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-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0=
|
||||
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||
golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
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=
|
||||
@ -1241,19 +1198,10 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ
|
||||
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 h1:+jnHzr9VPj32ykQVai5DNahi9+NSp7yYuCsl5eAQtL0=
|
||||
golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE=
|
||||
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk=
|
||||
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
|
||||
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=
|
||||
@ -1265,9 +1213,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
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-20220819030929-7fc1605a5dde h1:ejfdSekXMDxDLbRrJMwUk6KnSLZ2McaUCVcIKM+N6jc=
|
||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
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=
|
||||
@ -1331,55 +1278,35 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/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-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-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/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-20210819135213-f52c844e1c1c/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-20211019181941-9d821ace8654/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-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-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-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-20220517195934-5e4e11fc645e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/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-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-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.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw=
|
||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
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=
|
||||
@ -1397,7 +1324,7 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxb
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs=
|
||||
golang.org/x/time v0.0.0-20220609170525-579cf78fd858 h1:Dpdu/EMxGMFgq0CeYMh4fazTD2vtlZRYE7wyynxJb9U=
|
||||
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@ -1456,18 +1383,12 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f
|
||||
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.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
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 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
|
||||
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=
|
||||
@ -1496,28 +1417,8 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513
|
||||
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.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.93.0 h1:T2xt9gi0gHdxdnRkVQhT8mIvPaXKNsDNWz+L696M66M=
|
||||
google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw=
|
||||
google.golang.org/api v0.102.0 h1:JxJl2qQ85fRMPNvlZY/enexbxpCjLwGhZUtgfGeQ51I=
|
||||
google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo=
|
||||
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=
|
||||
@ -1570,54 +1471,9 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D
|
||||
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-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
|
||||
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-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-20221018160656-63c7b68cfc55 h1:U1u4KB2kx6KR/aJDjQ97hZ15wQs8ZPvDcGcRynBhkvg=
|
||||
google.golang.org/genproto v0.0.0-20221018160656-63c7b68cfc55/go.mod h1:45EK0dUbEZ2NHjCeAd2LXmyjAgGUGrpGROgjhC3ADck=
|
||||
google.golang.org/genproto v0.0.0-20221116193143-41c2ba794472 h1:kIfItBRE5gkUKpH4H5lNGciZbka1JrmRli3ArqrKFkA=
|
||||
google.golang.org/genproto v0.0.0-20221116193143-41c2ba794472/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
@ -1642,23 +1498,8 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp
|
||||
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.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.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY=
|
||||
google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||
google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U=
|
||||
google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww=
|
||||
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=
|
||||
@ -1671,10 +1512,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8 h1:KR8+MyP7/qOlV+8Af01LtjL04bu7on42eVsxT4EyBQk=
|
||||
google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
@ -1695,7 +1534,6 @@ gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJ
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0=
|
||||
gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
@ -1724,8 +1562,7 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
|
||||
honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
|
||||
nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k=
|
||||
nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
|
||||
pgregory.net/rapid v0.4.7 h1:MTNRktPuv5FNqOO151TM9mDTa+XHcX6ypYeISDVD14g=
|
||||
pgregory.net/rapid v0.4.7/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU=
|
||||
pgregory.net/rapid v0.5.3 h1:163N50IHFqr1phZens4FQOdPgfJscR7a562mjQqeo4M=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
|
121
gomod2nix.toml
121
gomod2nix.toml
@ -2,23 +2,26 @@ schema = 3
|
||||
|
||||
[mod]
|
||||
[mod."cloud.google.com/go"]
|
||||
version = "v0.102.1"
|
||||
hash = "sha256-rv3MHFvIrN6AcrmWcWGSQwgaZLbjJMmJFi3bsfHoiO4="
|
||||
version = "v0.105.0"
|
||||
hash = "sha256-2nYtHjuN9ghGcM6aPlOxyNNarHebHtj0Xec48sWwdaI="
|
||||
[mod."cloud.google.com/go/compute"]
|
||||
version = "v1.7.0"
|
||||
hash = "sha256-g+n7L36LC+NP4KaiEu9fCMn6S9fkxjp4PCLOp/oXV38="
|
||||
version = "v1.12.1"
|
||||
hash = "sha256-mMsdL+6R1KuFeAFqEJv8oq/cmRc9hSluEisCpGP0GTc="
|
||||
[mod."cloud.google.com/go/compute/metadata"]
|
||||
version = "v0.2.1"
|
||||
hash = "sha256-gqjkb6y5POkTWXGQtCvgygvXqoLkESB+cykKp7Mp3jI="
|
||||
[mod."cloud.google.com/go/iam"]
|
||||
version = "v0.4.0"
|
||||
hash = "sha256-sPtj6QPPC/QrkDXJW4Y7rMIHk5l1y9XV/DgM47eEtvg="
|
||||
version = "v0.7.0"
|
||||
hash = "sha256-2UTJ/BbZ+YMGJhyo3HRPUYVDXW6+B5znFdqiutboYtA="
|
||||
[mod."cloud.google.com/go/storage"]
|
||||
version = "v1.22.1"
|
||||
hash = "sha256-YZt05wru0kacyi6moTgvocavActKpXx7FlLh+o0HGDs="
|
||||
version = "v1.27.0"
|
||||
hash = "sha256-V4B6A1Ms8cemB5Cs6nAtUe1N1ldaI9oqTdzGU2FUhrc="
|
||||
[mod."cosmossdk.io/errors"]
|
||||
version = "v1.0.0-beta.7"
|
||||
hash = "sha256-XblGvIx6Wvvq6wggXjp+KbeJGXoe7AZH7hXEdauCezU="
|
||||
[mod."cosmossdk.io/math"]
|
||||
version = "v1.0.0-beta.3"
|
||||
hash = "sha256-lTQ27ZlL+kWlc+S//sJmyiOwaf9qS+YLv61I4OXi9XE="
|
||||
version = "v1.0.0-beta.4"
|
||||
hash = "sha256-UYdq/46EubyjxkldGike8FlwJLWGCB576VB7th285ao="
|
||||
[mod."filippo.io/edwards25519"]
|
||||
version = "v1.0.0-rc.1"
|
||||
hash = "sha256-3DboBqby2ejRU33FG96Z8JF5AJ8HP2rC/v++VyoQ2LQ="
|
||||
@ -91,14 +94,17 @@ schema = 3
|
||||
version = "v1.0.4"
|
||||
hash = "sha256-JvcBXBdjdmnaW/nyf/tw/uaOAGn1b78yxrtl2/Rs3kA="
|
||||
[mod."github.com/cosmos/cosmos-proto"]
|
||||
version = "v1.0.0-alpha7"
|
||||
hash = "sha256-2wCH+toTF2A6MfFjOa13muEH5oBCcxAhZEqirNOrBA0="
|
||||
version = "v1.0.0-alpha8"
|
||||
hash = "sha256-iXzXoS5Kfh5DBy+PhdFWraDWXda/3M4j7j4VECjv4CA="
|
||||
[mod."github.com/cosmos/cosmos-sdk"]
|
||||
version = "v0.46.4"
|
||||
hash = "sha256-YjrhZsGKMH7kxCS9Lhbvt7YjJs/B+9aSS+l042oBhAw="
|
||||
version = "v0.46.6"
|
||||
hash = "sha256-H1VZxZUWXhpXiY3A9smLp09MEGpXmh+XvX6YUiXPcpQ="
|
||||
[mod."github.com/cosmos/go-bip39"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-Qm2aC2vaS8tjtMUbHmlBSagOSqbduEEDwc51qvQaBmA="
|
||||
[mod."github.com/cosmos/gogoproto"]
|
||||
version = "v1.4.3"
|
||||
hash = "sha256-Y/NL76ay/oAl8mS3skkK5ula0/xudqbwW1o22lZjKRg="
|
||||
[mod."github.com/cosmos/gorocksdb"]
|
||||
version = "v1.2.0"
|
||||
hash = "sha256-209TcVuXc5s/TcOvNlaQ1HEJAUDTEK3nxPhs+d8TEcY="
|
||||
@ -106,8 +112,8 @@ schema = 3
|
||||
version = "v0.19.4"
|
||||
hash = "sha256-EmpRZ48pjPFq/fIHneut9Vyo5QJATfb3ZO7KzWnqs9g="
|
||||
[mod."github.com/cosmos/ibc-go/v5"]
|
||||
version = "v5.0.1"
|
||||
hash = "sha256-44Vyj9i4gh6U0BGNsEFqRsHAYdxfuJmLGdtPWxcBfWQ="
|
||||
version = "v5.1.0"
|
||||
hash = "sha256-9ZwGw6XqYkBtj+vTQ2IodNb7VcGesTFnVsxjd+G1I6Q="
|
||||
[mod."github.com/cosmos/ledger-cosmos-go"]
|
||||
version = "v0.11.1"
|
||||
hash = "sha256-yli+VvVtZmHo2LPvCY6lYVUfcCDn3sBLDL+a8KIlqDA="
|
||||
@ -157,14 +163,14 @@ schema = 3
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-k1DYvCqO3BKNcGEve/nMW0RxzMkK2tGfXbUbycqcVSo="
|
||||
[mod."github.com/ethereum/go-ethereum"]
|
||||
version = "v1.10.19"
|
||||
hash = "sha256-7FPnTGcCb8Xd1QVR+6PmGTaHdTY1mm/8osFTW1JLuG8="
|
||||
version = "v1.10.25"
|
||||
hash = "sha256-tNlI2XyuTXjGuBoe5vlYDcaGN2Sub7yltVtI6TeLLSc="
|
||||
[mod."github.com/felixge/httpsnoop"]
|
||||
version = "v1.0.1"
|
||||
hash = "sha256-TNXnnC/ZGNY9lInAcES1cBGqIdEljKuh5LH/khVFjVk="
|
||||
[mod."github.com/fsnotify/fsnotify"]
|
||||
version = "v1.5.4"
|
||||
hash = "sha256-iPuInpDAJvDeSTr6to713J/fTOWdQIWlLXWAuWIs2Bw="
|
||||
version = "v1.6.0"
|
||||
hash = "sha256-DQesOCweQPEwmAn6s7DCP/Dwy8IypC+osbpfsvpkdP0="
|
||||
[mod."github.com/gballet/go-libpcsclite"]
|
||||
version = "v0.0.0-20190607065134-2772fd86a8ff"
|
||||
hash = "sha256-Nr5ocU9s1F2Lhx/Zq6/nIo+KkKEqMjDYOEs3yWRC48g="
|
||||
@ -224,14 +230,11 @@ schema = 3
|
||||
version = "v1.3.0"
|
||||
hash = "sha256-QoR55eBtA94T2tBszyxfDtO7/pjZZSGb5vm7U0Xhs0Y="
|
||||
[mod."github.com/googleapis/enterprise-certificate-proxy"]
|
||||
version = "v0.1.0"
|
||||
hash = "sha256-fxaElfiGGh1mLmltkFpVFdiuaagrLZLTW9btVpK13wg="
|
||||
version = "v0.2.0"
|
||||
hash = "sha256-5gxsS5kDLqNFBkQ4eK6GS/sNn+aFknm6jjfteO+6jl4="
|
||||
[mod."github.com/googleapis/gax-go/v2"]
|
||||
version = "v2.4.0"
|
||||
hash = "sha256-zzat4+3iF2XBTQ6RZAUgsCbfK0HgO0nYhM4utA5dqz0="
|
||||
[mod."github.com/googleapis/go-type-adapters"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-u3ajruRV/EN2E1WKet/zoe3zmRrAy4C5F2Dx8bpQwoc="
|
||||
version = "v2.6.0"
|
||||
hash = "sha256-sSsncbJmv0n5jB3G7tHY1Zr2ucCusIeTrXZH4A8QqYI="
|
||||
[mod."github.com/gorilla/handlers"]
|
||||
version = "v1.5.1"
|
||||
hash = "sha256-GnBAARgOx1E+hDMQ63SI17hdhGtLQxb31lZOmn5j/pU="
|
||||
@ -308,8 +311,8 @@ schema = 3
|
||||
version = "v0.0.0-20190712205309-48d3d31d256d"
|
||||
hash = "sha256-bn04wkDnhQ0tb/YzmPf7MNJlApOl+z6+EAbUqH7Ti5Q="
|
||||
[mod."github.com/klauspost/compress"]
|
||||
version = "v1.15.9"
|
||||
hash = "sha256-ctPxlVq0c/SoNPVsP66RjxUjTHys3diW2Apxjyc9WdE="
|
||||
version = "v1.15.11"
|
||||
hash = "sha256-9MXm0TObg6DyqnYMIw3IChrorHc2ILf5djZYoM0e1J0="
|
||||
[mod."github.com/lib/pq"]
|
||||
version = "v1.10.6"
|
||||
hash = "sha256-8EhFwY/9YH5L/fd6l2beOnC3VvpegRAmCCsnDVJBqBM="
|
||||
@ -359,11 +362,11 @@ schema = 3
|
||||
version = "v0.0.5"
|
||||
hash = "sha256-/5i70IkH/qSW5KjGzv8aQNKh9tHoz98tqtL0K2DMFn4="
|
||||
[mod."github.com/onsi/ginkgo/v2"]
|
||||
version = "v2.4.0"
|
||||
hash = "sha256-Z+bch118Akc5wGkOM7ZePNqw7vW5euXE7ec4Y297HNw="
|
||||
version = "v2.5.1"
|
||||
hash = "sha256-VB29+H9k7l6il63oXJvsjamSUhsw/e99iI/BeTCderA="
|
||||
[mod."github.com/onsi/gomega"]
|
||||
version = "v1.23.0"
|
||||
hash = "sha256-g5FaFLUK8ZAR9VgFTTH0ax0t45tZkYbIHbq/gANIOTM="
|
||||
version = "v1.24.1"
|
||||
hash = "sha256-REfxQTDRcO23GnmJfOW8/MmPJf9oE2grVvvGiC1eSbo="
|
||||
[mod."github.com/pelletier/go-toml"]
|
||||
version = "v1.9.5"
|
||||
hash = "sha256-RJ9K1BTId0Mled7S66iGgxHkZ5JKEIsrrNaEfM8aImc="
|
||||
@ -389,8 +392,8 @@ schema = 3
|
||||
version = "v0.34.0"
|
||||
hash = "sha256-M+v+7DntUBmiQNzfNmG3aLLufbl0XBQOubtYoNTzJDA="
|
||||
[mod."github.com/prometheus/procfs"]
|
||||
version = "v0.7.3"
|
||||
hash = "sha256-ik0WpnpSjMwifPYfQTfu/eb5ilNj+eLJF0d5Dftp8A8="
|
||||
version = "v0.8.0"
|
||||
hash = "sha256-hgrilokQsXCOCCvwgOSfuErxoFAQpXM/+zNJKcMVHyM="
|
||||
[mod."github.com/prometheus/tsdb"]
|
||||
version = "v0.7.1"
|
||||
hash = "sha256-BPz7YJbfMZgeR+u9YaeWeipVzHIS73EdgXD7VSJSLbA="
|
||||
@ -434,8 +437,8 @@ schema = 3
|
||||
version = "v1.0.5"
|
||||
hash = "sha256-w9LLYzxxP74WHT4ouBspH/iQZXjuAh2WQCHsuvyEjAw="
|
||||
[mod."github.com/spf13/viper"]
|
||||
version = "v1.13.0"
|
||||
hash = "sha256-yHviS3lMo1hB6jwyiU3zpyGtxP6v9AsyZUKiLeCVz+k="
|
||||
version = "v1.14.0"
|
||||
hash = "sha256-qn3VzD339HZIub5QP4aWVciSufAfVb9llbmQZ8pfDEs="
|
||||
[mod."github.com/status-im/keycard-go"]
|
||||
version = "v0.0.0-20200402102358-957c09536969"
|
||||
hash = "sha256-yddXXuu6mEFEO2/K6c1tWymeBKzOcvLQnNsFGRjtfXk="
|
||||
@ -461,8 +464,8 @@ schema = 3
|
||||
version = "v0.16.0"
|
||||
hash = "sha256-JW4zO/0vMzf1dXLePOqaMtiLUZgNbuIseh9GV+jQlf0="
|
||||
[mod."github.com/tendermint/tendermint"]
|
||||
version = "v0.34.22"
|
||||
hash = "sha256-4p4cpyCWjBbNQUpYN2gDJvnyj+Pov9hw5uRjHrrO++Y="
|
||||
version = "v0.34.23"
|
||||
hash = "sha256-eir0vr8lQOG+FTPo+ZUeDidAIACfyUq2ie3XRE8rIa4="
|
||||
[mod."github.com/tendermint/tm-db"]
|
||||
version = "v0.6.7"
|
||||
hash = "sha256-hl/3RrBrpkk2zA6dmrNlIYKs1/GfqegSscDSkA5Pjlo="
|
||||
@ -488,26 +491,26 @@ schema = 3
|
||||
version = "v0.23.0"
|
||||
hash = "sha256-R3O9GyNtv6j0ic7s+2xkLLaLzbJEop0Otj1nJDFBjsg="
|
||||
[mod."golang.org/x/crypto"]
|
||||
version = "v0.1.0"
|
||||
hash = "sha256-0oZWBSiW5Pd/2a1p2beuoelDe0CpfXZhrg/qPduJlYs="
|
||||
version = "v0.3.0"
|
||||
hash = "sha256-Un9wPqz8u/xpV98T4IqE6RMXIPhGCIm2prsNkHP3cjg="
|
||||
[mod."golang.org/x/exp"]
|
||||
version = "v0.0.0-20220722155223-a9213eeb770e"
|
||||
hash = "sha256-kNgzydWRpjm0sZl4uXEs3LX5L0xjJtJRAFf/CTlYUN4="
|
||||
[mod."golang.org/x/net"]
|
||||
version = "v0.1.0"
|
||||
hash = "sha256-SrThFBg6sqGYpiN1E3d1SilJxbKkQhSZXPmAFoMAA/I="
|
||||
version = "v0.2.0"
|
||||
hash = "sha256-0MqnHDdLkkau6k7hlWD9MzIoAFROvxulyT+KzZkSXOs="
|
||||
[mod."golang.org/x/oauth2"]
|
||||
version = "v0.0.0-20220622183110-fd043fe589d2"
|
||||
hash = "sha256-VLffpTpx3DlUzXB8mKiJfFzm4ZmgnLSUuLB5Ir0WQUg="
|
||||
version = "v0.0.0-20221014153046-6fdb5e3db783"
|
||||
hash = "sha256-IoygidVNqyAZmN+3macDeIefK8hhJToygpcqlwehdYQ="
|
||||
[mod."golang.org/x/sync"]
|
||||
version = "v0.0.0-20220819030929-7fc1605a5dde"
|
||||
hash = "sha256-5EOxO8FRdaLW9v/DhwBmWiT2G34A2ofxSCaC7ovvpb0="
|
||||
version = "v0.1.0"
|
||||
hash = "sha256-Hygjq9euZ0qz6TvHYQwOZEjNiTbTh1nSLRAWZ6KFGR8="
|
||||
[mod."golang.org/x/sys"]
|
||||
version = "v0.1.0"
|
||||
hash = "sha256-nZbEJ/2PuWrDLD4ujeVvcFGoIsfVoIH/Lcp4FjD7hpU="
|
||||
version = "v0.2.0"
|
||||
hash = "sha256-N6yfQH7R2gfcvyWTQZbxWuSNyVy6hAxiab2WFzgAykI="
|
||||
[mod."golang.org/x/term"]
|
||||
version = "v0.1.0"
|
||||
hash = "sha256-UWnNsJIj5nXsuzlPWQ1NyHQuHStaDacMVkFbJ4pnxXk="
|
||||
version = "v0.2.0"
|
||||
hash = "sha256-azcllZ0o/9TurqX9udaJ0o9yxqSoI0/bSJsvQQLYIQc="
|
||||
[mod."golang.org/x/text"]
|
||||
version = "v0.4.0"
|
||||
hash = "sha256-JvyMygdmTvWg7xhbnUB9MMk6WcYXJt8DAj4DYl82Pys="
|
||||
@ -515,20 +518,20 @@ schema = 3
|
||||
version = "v0.0.0-20220907171357-04be3eba64a2"
|
||||
hash = "sha256-6+zueutgefIYmgXinOflz8qGDDDj0Zhv+2OkGhBTKno="
|
||||
[mod."google.golang.org/api"]
|
||||
version = "v0.93.0"
|
||||
hash = "sha256-W17B79osAhObMbrCHlgywEPg9yIPx0ZISDhp9JwFE5A="
|
||||
version = "v0.102.0"
|
||||
hash = "sha256-q8t08Wu0qzOQOmhY4GSoUrhqLTW/TeXiKhio+5ONfe4="
|
||||
[mod."google.golang.org/appengine"]
|
||||
version = "v1.6.7"
|
||||
hash = "sha256-zIxGRHiq4QBvRqkrhMGMGCaVL4iM4TtlYpAi/hrivS4="
|
||||
[mod."google.golang.org/genproto"]
|
||||
version = "v0.0.0-20221018160656-63c7b68cfc55"
|
||||
hash = "sha256-Z4ynOw+3NkSkWVOrNaeuQC3G9Q6+joNbTLVoF2HegrU="
|
||||
version = "v0.0.0-20221116193143-41c2ba794472"
|
||||
hash = "sha256-uQuxuOvWRsdMii5M5QresisVd1E+Ss8s2WfR2n7QSXk="
|
||||
[mod."google.golang.org/grpc"]
|
||||
version = "v1.50.1"
|
||||
hash = "sha256-38nk4qIme+fE57SsCqNxtCZnc8fyzzi4Sb60uDTT2KE="
|
||||
version = "v1.51.0"
|
||||
hash = "sha256-RzH5DU13D/ulxxOouIKpdNt8eHdff7mrEnB+JUupbLU="
|
||||
[mod."google.golang.org/protobuf"]
|
||||
version = "v1.28.1"
|
||||
hash = "sha256-sTJYgvlv5is7vHNxcuigF2lNASp0QonhUgnrguhfHSU="
|
||||
version = "v1.28.2-0.20220831092852-f930b1dc76e8"
|
||||
hash = "sha256-li5hXlXwTJ5LIZ8bVki1AZ6UFI2gXHl33JwdX1dOrtM="
|
||||
[mod."gopkg.in/ini.v1"]
|
||||
version = "v1.67.0"
|
||||
hash = "sha256-V10ahGNGT+NLRdKUyRg1dos5RxLBXBk1xutcnquc/+4="
|
||||
|
@ -3,10 +3,10 @@ package indexer
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
rpctypes "github.com/evmos/ethermint/rpc/types"
|
||||
@ -110,12 +110,12 @@ func (kv *KVIndexer) IndexBlock(block *tmtypes.Block, txResults []*abci.Response
|
||||
ethTxIndex++
|
||||
|
||||
if err := saveTxResult(kv.clientCtx.Codec, batch, txHash, &txResult); err != nil {
|
||||
return sdkerrors.Wrapf(err, "IndexBlock %d", height)
|
||||
return errorsmod.Wrapf(err, "IndexBlock %d", height)
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := batch.Write(); err != nil {
|
||||
return sdkerrors.Wrapf(err, "IndexBlock %d, write batch", block.Height)
|
||||
return errorsmod.Wrapf(err, "IndexBlock %d, write batch", block.Height)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -134,14 +134,14 @@ func (kv *KVIndexer) FirstIndexedBlock() (int64, error) {
|
||||
func (kv *KVIndexer) GetByTxHash(hash common.Hash) (*ethermint.TxResult, error) {
|
||||
bz, err := kv.db.Get(TxHashKey(hash))
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrapf(err, "GetByTxHash %s", hash.Hex())
|
||||
return nil, errorsmod.Wrapf(err, "GetByTxHash %s", hash.Hex())
|
||||
}
|
||||
if len(bz) == 0 {
|
||||
return nil, fmt.Errorf("tx not found, hash: %s", hash.Hex())
|
||||
}
|
||||
var txKey ethermint.TxResult
|
||||
if err := kv.clientCtx.Codec.Unmarshal(bz, &txKey); err != nil {
|
||||
return nil, sdkerrors.Wrapf(err, "GetByTxHash %s", hash.Hex())
|
||||
return nil, errorsmod.Wrapf(err, "GetByTxHash %s", hash.Hex())
|
||||
}
|
||||
return &txKey, nil
|
||||
}
|
||||
@ -150,7 +150,7 @@ func (kv *KVIndexer) GetByTxHash(hash common.Hash) (*ethermint.TxResult, error)
|
||||
func (kv *KVIndexer) GetByBlockAndIndex(blockNumber int64, txIndex int32) (*ethermint.TxResult, error) {
|
||||
bz, err := kv.db.Get(TxIndexKey(blockNumber, txIndex))
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrapf(err, "GetByBlockAndIndex %d %d", blockNumber, txIndex)
|
||||
return nil, errorsmod.Wrapf(err, "GetByBlockAndIndex %d %d", blockNumber, txIndex)
|
||||
}
|
||||
if len(bz) == 0 {
|
||||
return nil, fmt.Errorf("tx not found, block: %d, eth-index: %d", blockNumber, txIndex)
|
||||
@ -174,7 +174,7 @@ func TxIndexKey(blockNumber int64, txIndex int32) []byte {
|
||||
func LoadLastBlock(db dbm.DB) (int64, error) {
|
||||
it, err := db.ReverseIterator([]byte{KeyPrefixTxIndex}, []byte{KeyPrefixTxIndex + 1})
|
||||
if err != nil {
|
||||
return 0, sdkerrors.Wrap(err, "LoadLastBlock")
|
||||
return 0, errorsmod.Wrap(err, "LoadLastBlock")
|
||||
}
|
||||
defer it.Close()
|
||||
if !it.Valid() {
|
||||
@ -187,7 +187,7 @@ func LoadLastBlock(db dbm.DB) (int64, error) {
|
||||
func LoadFirstBlock(db dbm.DB) (int64, error) {
|
||||
it, err := db.Iterator([]byte{KeyPrefixTxIndex}, []byte{KeyPrefixTxIndex + 1})
|
||||
if err != nil {
|
||||
return 0, sdkerrors.Wrap(err, "LoadFirstBlock")
|
||||
return 0, errorsmod.Wrap(err, "LoadFirstBlock")
|
||||
}
|
||||
defer it.Close()
|
||||
if !it.Valid() {
|
||||
@ -213,10 +213,10 @@ func isEthTx(tx sdk.Tx) bool {
|
||||
func saveTxResult(codec codec.Codec, batch dbm.Batch, txHash common.Hash, txResult *ethermint.TxResult) error {
|
||||
bz := codec.MustMarshal(txResult)
|
||||
if err := batch.Set(TxHashKey(txHash), bz); err != nil {
|
||||
return sdkerrors.Wrap(err, "set tx-hash key")
|
||||
return errorsmod.Wrap(err, "set tx-hash key")
|
||||
}
|
||||
if err := batch.Set(TxIndexKey(txResult.Height, txResult.EthTxIndex), txHash.Bytes()); err != nil {
|
||||
return sdkerrors.Wrap(err, "set tx-index key")
|
||||
return errorsmod.Wrap(err, "set tx-index key")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
2
init.sh
2
init.sh
@ -6,7 +6,7 @@ MONIKER="localtestnet"
|
||||
KEYRING="test"
|
||||
KEYALGO="eth_secp256k1"
|
||||
LOGLEVEL="info"
|
||||
# to trace evm
|
||||
# trace evm
|
||||
TRACE="--trace"
|
||||
# TRACE=""
|
||||
|
||||
|
@ -27,7 +27,7 @@ import sources.nixpkgs {
|
||||
dotenv = builtins.path { name = "dotenv"; path = ../scripts/.env; };
|
||||
};
|
||||
})
|
||||
(_: pkgs: { test-env = import ./testenv.nix { inherit pkgs; }; })
|
||||
(_: pkgs: { test-env = pkgs.callPackage ./testenv.nix { }; })
|
||||
(_: pkgs: {
|
||||
cosmovisor = pkgs.buildGo118Module rec {
|
||||
name = "cosmovisor";
|
||||
|
@ -1,4 +1,4 @@
|
||||
{ lib, stdenv, buildGoModule, fetchFromGitHub, libobjc, IOKit }:
|
||||
{ lib, stdenv, buildGoModule, fetchFromGitHub, libobjc, IOKit, nixosTests }:
|
||||
|
||||
let
|
||||
# A list of binaries to put into separate outputs
|
||||
@ -7,19 +7,18 @@ let
|
||||
"clef"
|
||||
];
|
||||
|
||||
in
|
||||
buildGoModule rec {
|
||||
in buildGoModule rec {
|
||||
pname = "go-ethereum";
|
||||
version = "1.10.19";
|
||||
version = "1.10.25";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "ethereum";
|
||||
repo = pname;
|
||||
rev = "v${version}";
|
||||
sha256 = "0f6n9rg42ph47mvykc9f0lf99yzwqy4jm7mlzyks4l6i6fl1g3q1";
|
||||
sha256 = "sha256-mnf0kMfQEEQMricZJfyF7ZB/2F1dyPBx9iT2v/rGh1U=";
|
||||
};
|
||||
|
||||
vendorSha256 = "1s5yfpk2yn7f3zwjl2fdrh6c63ki2b8rlmnlss27yxibsidaj0yd";
|
||||
vendorSha256 = "sha256-Dj+xN8lr98LJyYr2FwJ7yUIJkUeUrr1fkcbj4hShJI0=";
|
||||
|
||||
doCheck = false;
|
||||
|
||||
@ -47,14 +46,19 @@ buildGoModule rec {
|
||||
"cmd/utils"
|
||||
];
|
||||
|
||||
# Following upstream: https://github.com/ethereum/go-ethereum/blob/v1.10.25/build/ci.go#L218
|
||||
tags = [ "urfave_cli_no_docs" ];
|
||||
|
||||
# Fix for usb-related segmentation faults on darwin
|
||||
propagatedBuildInputs =
|
||||
lib.optionals stdenv.isDarwin [ libobjc IOKit ];
|
||||
|
||||
passthru.tests = { inherit (nixosTests) geth; };
|
||||
|
||||
meta = with lib; {
|
||||
homepage = "https://geth.ethereum.org/";
|
||||
description = "Official golang implementation of the Ethereum protocol";
|
||||
license = with licenses; [ lgpl3Plus gpl3Plus ];
|
||||
maintainers = with maintainers; [ adisbladis lionello RaghavSood ];
|
||||
maintainers = with maintainers; [ adisbladis RaghavSood ];
|
||||
};
|
||||
}
|
||||
}
|
@ -41,10 +41,10 @@
|
||||
"homepage": "",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "f904e3562aabca382d12f8471ca2330b3f82899a",
|
||||
"sha256": "1lsa3sjwp1v3nv2jjpkl5lf9dncplwihmavasalg9fq1217pmzmb",
|
||||
"rev": "ea2c6a6dda1aa35a80139a512a9dee375b0946e7",
|
||||
"sha256": "0nd4nn9ryqa80ssw3j2kmr8wa73p2xz1hyxp280cdzqlmdfgw1lm",
|
||||
"type": "tarball",
|
||||
"url": "https://github.com/NixOS/nixpkgs/archive/f904e3562aabca382d12f8471ca2330b3f82899a.tar.gz",
|
||||
"url": "https://github.com/NixOS/nixpkgs/archive/ea2c6a6dda1aa35a80139a512a9dee375b0946e7.tar.gz",
|
||||
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,38 @@
|
||||
{ pkgs }:
|
||||
pkgs.poetry2nix.mkPoetryEnv {
|
||||
{ poetry2nix, lib, python310 }:
|
||||
poetry2nix.mkPoetryEnv {
|
||||
projectDir = ../tests/integration_tests;
|
||||
python = pkgs.python39;
|
||||
overrides = pkgs.poetry2nix.overrides.withDefaults (self: super: {
|
||||
eth-bloom = super.eth-bloom.overridePythonAttrs {
|
||||
preConfigure = ''
|
||||
substituteInPlace setup.py --replace \'setuptools-markdown\' ""
|
||||
'';
|
||||
};
|
||||
|
||||
pystarport = super.pystarport.overridePythonAttrs (
|
||||
old: {
|
||||
nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [ self.poetry ];
|
||||
}
|
||||
);
|
||||
});
|
||||
python = python310;
|
||||
overrides = poetry2nix.overrides.withDefaults (lib.composeManyExtensions [
|
||||
(self: super:
|
||||
let
|
||||
buildSystems = {
|
||||
eth-bloom = [ "setuptools" ];
|
||||
pystarport = [ "poetry" ];
|
||||
durations = [ "setuptools" ];
|
||||
multitail2 = [ "setuptools" ];
|
||||
pytest-github-actions-annotate-failures = [ "setuptools" ];
|
||||
flake8-black = [ "setuptools" ];
|
||||
multiaddr = [ "setuptools" ];
|
||||
};
|
||||
in
|
||||
lib.mapAttrs
|
||||
(attr: systems: super.${attr}.overridePythonAttrs
|
||||
(old: {
|
||||
nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ map (a: self.${a}) systems;
|
||||
}))
|
||||
buildSystems
|
||||
)
|
||||
(self: super: {
|
||||
eth-bloom = super.eth-bloom.overridePythonAttrs {
|
||||
preConfigure = ''
|
||||
substituteInPlace setup.py --replace \'setuptools-markdown\' ""
|
||||
'';
|
||||
};
|
||||
pyyaml-include = super.pyyaml-include.overridePythonAttrs {
|
||||
preConfigure = ''
|
||||
substituteInPlace setup.py --replace "setup()" "setup(version=\"1.3\")"
|
||||
'';
|
||||
};
|
||||
})
|
||||
]);
|
||||
}
|
||||
|
8
proto/buf.gen.gogo.yaml
Normal file
8
proto/buf.gen.gogo.yaml
Normal file
@ -0,0 +1,8 @@
|
||||
version: v1
|
||||
plugins:
|
||||
- name: gocosmos
|
||||
out: .
|
||||
opt: plugins=grpc,Mgoogle/protobuf/duration.proto=Mgoogle/protobuf/duration.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/struct.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/wrappers.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/any.proto=github.com/cosmos/cosmos-sdk/codec/types,Mcosmos/orm/v1alpha1/orm.proto=github.com/cosmos/cosmos-sdk/api/cosmos/orm/v1alpha1
|
||||
- name: grpc-gateway
|
||||
out: .
|
||||
opt: logtostderr=true,allow_colon_final_segments=true
|
15
proto/buf.gen.swagger.yaml
Normal file
15
proto/buf.gen.swagger.yaml
Normal file
@ -0,0 +1,15 @@
|
||||
version: v1
|
||||
plugins:
|
||||
- name: gocosmos
|
||||
out: .
|
||||
opt: plugins=grpc,Mgoogle/protobuf/duration.proto=Mgoogle/protobuf/duration.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/struct.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/wrappers.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/any.proto=github.com/cosmos/cosmos-sdk/codec/types,Mcosmos/orm/v1alpha1/orm.proto=github.com/cosmos/cosmos-sdk/api/cosmos/orm/v1alpha1
|
||||
- name: grpc-gateway
|
||||
out: .
|
||||
opt: logtostderr=true
|
||||
- name: swagger
|
||||
out: ./tmp-swagger-gen
|
||||
opt:
|
||||
- logtostderr=true
|
||||
- fqn_for_swagger_name=true
|
||||
- simple_operation_ids=true
|
||||
strategy: all
|
19
proto/buf.lock
Normal file
19
proto/buf.lock
Normal file
@ -0,0 +1,19 @@
|
||||
# Generated by buf. DO NOT EDIT.
|
||||
version: v1
|
||||
deps:
|
||||
- remote: buf.build
|
||||
owner: cosmos
|
||||
repository: cosmos-proto
|
||||
commit: 1935555c206d4afb9e94615dfd0fad31
|
||||
- remote: buf.build
|
||||
owner: cosmos
|
||||
repository: cosmos-sdk
|
||||
commit: 508e19f5f37549e3a471a2a59b903c00
|
||||
- remote: buf.build
|
||||
owner: cosmos
|
||||
repository: gogo-proto
|
||||
commit: 34d970b699f84aa382f3c29773a60836
|
||||
- remote: buf.build
|
||||
owner: googleapis
|
||||
repository: googleapis
|
||||
commit: 783e4b5374fa488ab068d08af9658438
|
@ -1,4 +1,10 @@
|
||||
version: v1
|
||||
name: buf.build/evmos/ethermint
|
||||
deps:
|
||||
- buf.build/cosmos/cosmos-sdk
|
||||
- buf.build/cosmos/cosmos-proto
|
||||
- buf.build/cosmos/gogo-proto
|
||||
- buf.build/googleapis/googleapis
|
||||
lint:
|
||||
use:
|
||||
- DEFAULT
|
||||
|
@ -11,11 +11,13 @@ option go_package = "github.com/evmos/ethermint/crypto/ethsecp256k1";
|
||||
message PubKey {
|
||||
option (gogoproto.goproto_stringer) = false;
|
||||
|
||||
// key is the public key in byte form
|
||||
bytes key = 1;
|
||||
}
|
||||
|
||||
// PrivKey defines a type alias for an ecdsa.PrivateKey that implements
|
||||
// Tendermint's PrivateKey interface.
|
||||
message PrivKey {
|
||||
// key is the private key in byte form
|
||||
bytes key = 1;
|
||||
}
|
||||
|
@ -7,18 +7,18 @@ option go_package = "github.com/evmos/ethermint/x/evm/types";
|
||||
|
||||
// Params defines the EVM module parameters
|
||||
message Params {
|
||||
// evm denom represents the token denomination used to run the EVM state
|
||||
// evm_denom represents the token denomination used to run the EVM state
|
||||
// transitions.
|
||||
string evm_denom = 1 [(gogoproto.moretags) = "yaml:\"evm_denom\""];
|
||||
// enable create toggles state transitions that use the vm.Create function
|
||||
// enable_create toggles state transitions that use the vm.Create function
|
||||
bool enable_create = 2 [(gogoproto.moretags) = "yaml:\"enable_create\""];
|
||||
// enable call toggles state transitions that use the vm.Call function
|
||||
// enable_call toggles state transitions that use the vm.Call function
|
||||
bool enable_call = 3 [(gogoproto.moretags) = "yaml:\"enable_call\""];
|
||||
// extra eips defines the additional EIPs for the vm.Config
|
||||
// extra_eips defines the additional EIPs for the vm.Config
|
||||
repeated int64 extra_eips = 4 [(gogoproto.customname) = "ExtraEIPs", (gogoproto.moretags) = "yaml:\"extra_eips\""];
|
||||
// chain config defines the EVM chain configuration parameters
|
||||
// chain_config defines the EVM chain configuration parameters
|
||||
ChainConfig chain_config = 5 [(gogoproto.moretags) = "yaml:\"chain_config\"", (gogoproto.nullable) = false];
|
||||
// Allow unprotected transactions defines if replay-protected (i.e non EIP155
|
||||
// allow_unprotected_txs defines if replay-protected (i.e non EIP155
|
||||
// signed) transactions can be executed on the state machine.
|
||||
bool allow_unprotected_txs = 6;
|
||||
}
|
||||
@ -26,102 +26,115 @@ message Params {
|
||||
// ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int values
|
||||
// instead of *big.Int.
|
||||
message ChainConfig {
|
||||
// Homestead switch block (nil no fork, 0 = already homestead)
|
||||
// homestead_block switch (nil no fork, 0 = already homestead)
|
||||
string homestead_block = 1 [
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(gogoproto.moretags) = "yaml:\"homestead_block\""
|
||||
(gogoproto.moretags) = "yaml:\"homestead_block\""
|
||||
];
|
||||
// TheDAO hard-fork switch block (nil no fork)
|
||||
// dao_fork_block corresponds to TheDAO hard-fork switch block (nil no fork)
|
||||
string dao_fork_block = 2 [
|
||||
(gogoproto.customname) = "DAOForkBlock",
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(gogoproto.moretags) = "yaml:\"dao_fork_block\""
|
||||
(gogoproto.moretags) = "yaml:\"dao_fork_block\""
|
||||
];
|
||||
// Whether the nodes supports or opposes the DAO hard-fork
|
||||
// dao_fork_support defines whether the nodes supports or opposes the DAO hard-fork
|
||||
bool dao_fork_support = 3
|
||||
[(gogoproto.customname) = "DAOForkSupport", (gogoproto.moretags) = "yaml:\"dao_fork_support\""];
|
||||
// EIP150 implements the Gas price changes
|
||||
[(gogoproto.customname) = "DAOForkSupport", (gogoproto.moretags) = "yaml:\"dao_fork_support\""];
|
||||
// eip150_block: EIP150 implements the Gas price changes
|
||||
// (https://github.com/ethereum/EIPs/issues/150) EIP150 HF block (nil no fork)
|
||||
string eip150_block = 4 [
|
||||
(gogoproto.customname) = "EIP150Block",
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(gogoproto.moretags) = "yaml:\"eip150_block\""
|
||||
(gogoproto.moretags) = "yaml:\"eip150_block\""
|
||||
];
|
||||
// EIP150 HF hash (needed for header only clients as only gas pricing changed)
|
||||
// eip150_hash: EIP150 HF hash (needed for header only clients as only gas pricing changed)
|
||||
string eip150_hash = 5 [(gogoproto.customname) = "EIP150Hash", (gogoproto.moretags) = "yaml:\"byzantium_block\""];
|
||||
// EIP155Block HF block
|
||||
// eip155_block: EIP155Block HF block
|
||||
string eip155_block = 6 [
|
||||
(gogoproto.customname) = "EIP155Block",
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(gogoproto.moretags) = "yaml:\"eip155_block\""
|
||||
(gogoproto.moretags) = "yaml:\"eip155_block\""
|
||||
];
|
||||
// EIP158 HF block
|
||||
// eip158_block: EIP158 HF block
|
||||
string eip158_block = 7 [
|
||||
(gogoproto.customname) = "EIP158Block",
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(gogoproto.moretags) = "yaml:\"eip158_block\""
|
||||
(gogoproto.moretags) = "yaml:\"eip158_block\""
|
||||
];
|
||||
// Byzantium switch block (nil no fork, 0 = already on byzantium)
|
||||
// byzantium_block: Byzantium switch block (nil no fork, 0 = already on byzantium)
|
||||
string byzantium_block = 8 [
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(gogoproto.moretags) = "yaml:\"byzantium_block\""
|
||||
(gogoproto.moretags) = "yaml:\"byzantium_block\""
|
||||
];
|
||||
// Constantinople switch block (nil no fork, 0 = already activated)
|
||||
// constantinople_block: Constantinople switch block (nil no fork, 0 = already activated)
|
||||
string constantinople_block = 9 [
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(gogoproto.moretags) = "yaml:\"constantinople_block\""
|
||||
(gogoproto.moretags) = "yaml:\"constantinople_block\""
|
||||
];
|
||||
// Petersburg switch block (nil same as Constantinople)
|
||||
// petersburg_block: Petersburg switch block (nil same as Constantinople)
|
||||
string petersburg_block = 10 [
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(gogoproto.moretags) = "yaml:\"petersburg_block\""
|
||||
(gogoproto.moretags) = "yaml:\"petersburg_block\""
|
||||
];
|
||||
// Istanbul switch block (nil no fork, 0 = already on istanbul)
|
||||
// istanbul_block: Istanbul switch block (nil no fork, 0 = already on istanbul)
|
||||
string istanbul_block = 11 [
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(gogoproto.moretags) = "yaml:\"istanbul_block\""
|
||||
(gogoproto.moretags) = "yaml:\"istanbul_block\""
|
||||
];
|
||||
// Eip-2384 (bomb delay) switch block (nil no fork, 0 = already activated)
|
||||
// muir_glacier_block: Eip-2384 (bomb delay) switch block (nil no fork, 0 = already activated)
|
||||
string muir_glacier_block = 12 [
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(gogoproto.moretags) = "yaml:\"muir_glacier_block\""
|
||||
(gogoproto.moretags) = "yaml:\"muir_glacier_block\""
|
||||
];
|
||||
// Berlin switch block (nil = no fork, 0 = already on berlin)
|
||||
// berlin_block: Berlin switch block (nil = no fork, 0 = already on berlin)
|
||||
string berlin_block = 13 [
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(gogoproto.moretags) = "yaml:\"berlin_block\""
|
||||
(gogoproto.moretags) = "yaml:\"berlin_block\""
|
||||
];
|
||||
// DEPRECATED: EWASM, YOLOV3 and Catalyst block have been deprecated
|
||||
reserved 14, 15, 16;
|
||||
reserved "yolo_v3_block", "ewasm_block", "catalyst_block";
|
||||
// London switch block (nil = no fork, 0 = already on london)
|
||||
// london_block: London switch block (nil = no fork, 0 = already on london)
|
||||
string london_block = 17 [
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(gogoproto.moretags) = "yaml:\"london_block\""
|
||||
(gogoproto.moretags) = "yaml:\"london_block\""
|
||||
];
|
||||
// Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already activated)
|
||||
// arrow_glacier_block: Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already activated)
|
||||
string arrow_glacier_block = 18 [
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(gogoproto.moretags) = "yaml:\"arrow_glacier_block\""
|
||||
(gogoproto.moretags) = "yaml:\"arrow_glacier_block\""
|
||||
];
|
||||
// DEPRECATED: merge fork block was deprecated: https://github.com/ethereum/go-ethereum/pull/24904
|
||||
reserved 19;
|
||||
reserved "merge_fork_block";
|
||||
// EIP-5133 (bomb delay) switch block (nil = no fork, 0 = already activated)
|
||||
// gray_glacier_block: EIP-5133 (bomb delay) switch block (nil = no fork, 0 = already activated)
|
||||
string gray_glacier_block = 20 [
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(gogoproto.moretags) = "yaml:\"gray_glacier_block\""
|
||||
(gogoproto.moretags) = "yaml:\"gray_glacier_block\""
|
||||
];
|
||||
// Virtual fork after The Merge to use as a network splitter
|
||||
// merge_netsplit_block: Virtual fork after The Merge to use as a network splitter
|
||||
string merge_netsplit_block = 21 [
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(gogoproto.moretags) = "yaml:\"merge_netsplit_block\""
|
||||
(gogoproto.moretags) = "yaml:\"merge_netsplit_block\""
|
||||
];
|
||||
// shanghai_block switch block (nil = no fork, 0 = already on shanghai)
|
||||
string shanghai_block = 22 [
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(gogoproto.moretags) = "yaml:\"shanghai_block\""
|
||||
];
|
||||
// cancun_block switch block (nil = no fork, 0 = already on cancun)
|
||||
string cancun_block = 23 [
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(gogoproto.moretags) = "yaml:\"cancun_block\""
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
// State represents a single Storage key value pair item.
|
||||
message State {
|
||||
string key = 1;
|
||||
// key is the stored key
|
||||
string key = 1;
|
||||
// value is the stored value for the given key
|
||||
string value = 2;
|
||||
}
|
||||
|
||||
@ -129,38 +142,38 @@ message State {
|
||||
// with a given hash. It it used for import/export data as transactions are not
|
||||
// persisted on blockchain state after an upgrade.
|
||||
message TransactionLogs {
|
||||
string hash = 1;
|
||||
// hash of the transaction
|
||||
string hash = 1;
|
||||
// logs is an array of Logs for the given transaction hash
|
||||
repeated Log logs = 2;
|
||||
}
|
||||
|
||||
// Log represents an protobuf compatible Ethereum Log that defines a contract
|
||||
// log event. These events are generated by the LOG opcode and stored/indexed by
|
||||
// the node.
|
||||
//
|
||||
// NOTE: address, topics and data are consensus fields. The rest of the fields
|
||||
// are derived, i.e. filled in by the nodes, but not secured by consensus.
|
||||
message Log {
|
||||
// Consensus fields:
|
||||
|
||||
// address of the contract that generated the event
|
||||
string address = 1;
|
||||
// list of topics provided by the contract.
|
||||
// topics is a list of topics provided by the contract.
|
||||
repeated string topics = 2;
|
||||
// supplied by the contract, usually ABI-encoded
|
||||
// data which is supplied by the contract, usually ABI-encoded
|
||||
bytes data = 3;
|
||||
|
||||
// Derived fields. These fields are filled in by the node
|
||||
// but not secured by consensus.
|
||||
|
||||
// block in which the transaction was included
|
||||
// block_number of the block in which the transaction was included
|
||||
uint64 block_number = 4 [(gogoproto.jsontag) = "blockNumber"];
|
||||
// hash of the transaction
|
||||
// tx_hash is the transaction hash
|
||||
string tx_hash = 5 [(gogoproto.jsontag) = "transactionHash"];
|
||||
// index of the transaction in the block
|
||||
// tx_index of the transaction in the block
|
||||
uint64 tx_index = 6 [(gogoproto.jsontag) = "transactionIndex"];
|
||||
// hash of the block in which the transaction was included
|
||||
// block_hash of the block in which the transaction was included
|
||||
string block_hash = 7 [(gogoproto.jsontag) = "blockHash"];
|
||||
// index of the log in the block
|
||||
uint64 index = 8 [(gogoproto.jsontag) = "logIndex"];
|
||||
|
||||
// The Removed field is true if this log was reverted due to a chain
|
||||
// removed is true if this log was reverted due to a chain
|
||||
// reorganisation. You must pay attention to this field if you receive logs
|
||||
// through a filter query.
|
||||
bool removed = 9;
|
||||
@ -191,9 +204,9 @@ message TxResult {
|
||||
message AccessTuple {
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
|
||||
// hex formatted ethereum address
|
||||
// address is a hex formatted ethereum address
|
||||
string address = 1;
|
||||
// hex formatted hashes of the storage keys
|
||||
// storage_keys are hex formatted hashes of the storage keys
|
||||
repeated string storage_keys = 2 [(gogoproto.jsontag) = "storageKeys"];
|
||||
}
|
||||
|
||||
@ -204,25 +217,27 @@ message TraceConfig {
|
||||
reserved 4, 7;
|
||||
reserved "disable_memory", "disable_return_data";
|
||||
|
||||
// custom javascript tracer
|
||||
// tracer is a custom javascript tracer
|
||||
string tracer = 1;
|
||||
// overrides the default timeout of 5 seconds for JavaScript-based tracing
|
||||
// timeout overrides the default timeout of 5 seconds for JavaScript-based tracing
|
||||
// calls
|
||||
string timeout = 2;
|
||||
// number of blocks the tracer is willing to go back
|
||||
// reexec defines the number of blocks the tracer is willing to go back
|
||||
uint64 reexec = 3;
|
||||
// disable stack capture
|
||||
// disable_stack switches stack capture
|
||||
bool disable_stack = 5 [(gogoproto.jsontag) = "disableStack"];
|
||||
// disable storage capture
|
||||
// disable_storage switches storage capture
|
||||
bool disable_storage = 6 [(gogoproto.jsontag) = "disableStorage"];
|
||||
// print output during capture end
|
||||
// debug can be used to print output during capture end
|
||||
bool debug = 8;
|
||||
// maximum length of output, but zero means unlimited
|
||||
// limit defines the maximum length of output, but zero means unlimited
|
||||
int32 limit = 9;
|
||||
// Chain overrides, can be used to execute a trace using future fork rules
|
||||
// overrides can be used to execute a trace using future fork rules
|
||||
ChainConfig overrides = 10;
|
||||
// enable memory capture
|
||||
// enable_memory switches memory capture
|
||||
bool enable_memory = 11 [(gogoproto.jsontag) = "enableMemory"];
|
||||
// enable return data capture
|
||||
// enable_return_data switches the capture of return data
|
||||
bool enable_return_data = 12 [(gogoproto.jsontag) = "enableReturnData"];
|
||||
// tracer_json_config configures the tracer using a JSON string
|
||||
string tracer_json_config = 13 [(gogoproto.jsontag) = "tracerConfig"];
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
syntax = "proto3";
|
||||
package ethermint.evm.v1;
|
||||
|
||||
import "gogoproto/gogo.proto";
|
||||
import "ethermint/evm/v1/evm.proto";
|
||||
import "gogoproto/gogo.proto";
|
||||
|
||||
option go_package = "github.com/evmos/ethermint/x/evm/types";
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
syntax = "proto3";
|
||||
package ethermint.evm.v1;
|
||||
|
||||
import "gogoproto/gogo.proto";
|
||||
import "cosmos/base/query/v1beta1/pagination.proto";
|
||||
import "google/api/annotations.proto";
|
||||
import "ethermint/evm/v1/evm.proto";
|
||||
import "ethermint/evm/v1/tx.proto";
|
||||
import "gogoproto/gogo.proto";
|
||||
import "google/api/annotations.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
option go_package = "github.com/evmos/ethermint/x/evm/types";
|
||||
@ -78,7 +78,7 @@ service Query {
|
||||
|
||||
// QueryAccountRequest is the request type for the Query/Account RPC method.
|
||||
message QueryAccountRequest {
|
||||
option (gogoproto.equal) = false;
|
||||
option (gogoproto.equal) = false;
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
|
||||
// address is the ethereum hex address to query the account for.
|
||||
@ -89,7 +89,7 @@ message QueryAccountRequest {
|
||||
message QueryAccountResponse {
|
||||
// balance is the balance of the EVM denomination.
|
||||
string balance = 1;
|
||||
// code hash is the hex-formatted code bytes from the EOA.
|
||||
// code_hash is the hex-formatted code bytes from the EOA.
|
||||
string code_hash = 2;
|
||||
// nonce is the account's sequence number.
|
||||
uint64 nonce = 3;
|
||||
@ -98,7 +98,7 @@ message QueryAccountResponse {
|
||||
// QueryCosmosAccountRequest is the request type for the Query/CosmosAccount RPC
|
||||
// method.
|
||||
message QueryCosmosAccountRequest {
|
||||
option (gogoproto.equal) = false;
|
||||
option (gogoproto.equal) = false;
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
|
||||
// address is the ethereum hex address to query the account for.
|
||||
@ -112,14 +112,14 @@ message QueryCosmosAccountResponse {
|
||||
string cosmos_address = 1;
|
||||
// sequence is the account's sequence number.
|
||||
uint64 sequence = 2;
|
||||
// account_number is the account numbert
|
||||
// account_number is the account number
|
||||
uint64 account_number = 3;
|
||||
}
|
||||
|
||||
// QueryValidatorAccountRequest is the request type for the
|
||||
// Query/ValidatorAccount RPC method.
|
||||
message QueryValidatorAccountRequest {
|
||||
option (gogoproto.equal) = false;
|
||||
option (gogoproto.equal) = false;
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
|
||||
// cons_address is the validator cons address to query the account for.
|
||||
@ -139,7 +139,7 @@ message QueryValidatorAccountResponse {
|
||||
|
||||
// QueryBalanceRequest is the request type for the Query/Balance RPC method.
|
||||
message QueryBalanceRequest {
|
||||
option (gogoproto.equal) = false;
|
||||
option (gogoproto.equal) = false;
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
|
||||
// address is the ethereum hex address to query the balance for.
|
||||
@ -154,10 +154,10 @@ message QueryBalanceResponse {
|
||||
|
||||
// QueryStorageRequest is the request type for the Query/Storage RPC method.
|
||||
message QueryStorageRequest {
|
||||
option (gogoproto.equal) = false;
|
||||
option (gogoproto.equal) = false;
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
|
||||
/// address is the ethereum hex address to query the storage state for.
|
||||
// address is the ethereum hex address to query the storage state for.
|
||||
string address = 1;
|
||||
|
||||
// key defines the key of the storage state
|
||||
@ -167,13 +167,13 @@ message QueryStorageRequest {
|
||||
// QueryStorageResponse is the response type for the Query/Storage RPC
|
||||
// method.
|
||||
message QueryStorageResponse {
|
||||
// key defines the storage state value hash associated with the given key.
|
||||
// value defines the storage state value hash associated with the given key.
|
||||
string value = 1;
|
||||
}
|
||||
|
||||
// QueryCodeRequest is the request type for the Query/Code RPC method.
|
||||
message QueryCodeRequest {
|
||||
option (gogoproto.equal) = false;
|
||||
option (gogoproto.equal) = false;
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
|
||||
// address is the ethereum hex address to query the code for.
|
||||
@ -189,7 +189,7 @@ message QueryCodeResponse {
|
||||
|
||||
// QueryTxLogsRequest is the request type for the Query/TxLogs RPC method.
|
||||
message QueryTxLogsRequest {
|
||||
option (gogoproto.equal) = false;
|
||||
option (gogoproto.equal) = false;
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
|
||||
// hash is the ethereum transaction hex hash to query the logs for.
|
||||
@ -198,7 +198,7 @@ message QueryTxLogsRequest {
|
||||
cosmos.base.query.v1beta1.PageRequest pagination = 2;
|
||||
}
|
||||
|
||||
// QueryTxLogs is the response type for the Query/TxLogs RPC method.
|
||||
// QueryTxLogsResponse is the response type for the Query/TxLogs RPC method.
|
||||
message QueryTxLogsResponse {
|
||||
// logs represents the ethereum logs generated from the given transaction.
|
||||
repeated Log logs = 1;
|
||||
@ -217,66 +217,73 @@ message QueryParamsResponse {
|
||||
|
||||
// EthCallRequest defines EthCall request
|
||||
message EthCallRequest {
|
||||
// same json format as the json rpc api.
|
||||
// args uses the same json format as the json rpc api.
|
||||
bytes args = 1;
|
||||
// the default gas cap to be used
|
||||
// gas_cap defines the default gas cap to be used
|
||||
uint64 gas_cap = 2;
|
||||
// the proposer of the requested block
|
||||
// proposer_address of the requested block in hex format
|
||||
bytes proposer_address = 3 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.ConsAddress"];
|
||||
// chain_id is the eip155 chain id parsed from the requested block header
|
||||
int64 chain_id = 4;
|
||||
}
|
||||
|
||||
// EstimateGasResponse defines EstimateGas response
|
||||
message EstimateGasResponse {
|
||||
// the estimated gas
|
||||
// gas returns the estimated gas
|
||||
uint64 gas = 1;
|
||||
}
|
||||
|
||||
// QueryTraceTxRequest defines TraceTx request
|
||||
message QueryTraceTxRequest {
|
||||
// msgEthereumTx for the requested transaction
|
||||
// msg is the MsgEthereumTx for the requested transaction
|
||||
MsgEthereumTx msg = 1;
|
||||
// tx_index is not necessary anymore
|
||||
reserved 2;
|
||||
reserved "tx_index";
|
||||
// TraceConfig holds extra parameters to trace functions.
|
||||
// trace_config holds extra parameters to trace functions.
|
||||
TraceConfig trace_config = 3;
|
||||
// the predecessor transactions included in the same block
|
||||
// predecessors is an array of transactions included in the same block
|
||||
// need to be replayed first to get correct context for tracing.
|
||||
repeated MsgEthereumTx predecessors = 4;
|
||||
// block number of requested transaction
|
||||
// block_number of requested transaction
|
||||
int64 block_number = 5;
|
||||
// block hex hash of requested transaction
|
||||
// block_hash of requested transaction
|
||||
string block_hash = 6;
|
||||
// block time of requested transaction
|
||||
// block_time of requested transaction
|
||||
google.protobuf.Timestamp block_time = 7 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
|
||||
// the proposer of the requested block
|
||||
// proposer_address is the proposer of the requested block
|
||||
bytes proposer_address = 8 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.ConsAddress"];
|
||||
// chain_id is the the eip155 chain id parsed from the requested block header
|
||||
int64 chain_id = 9;
|
||||
}
|
||||
|
||||
// QueryTraceTxResponse defines TraceTx response
|
||||
message QueryTraceTxResponse {
|
||||
// response serialized in bytes
|
||||
// data is the response serialized in bytes
|
||||
bytes data = 1;
|
||||
}
|
||||
|
||||
// QueryTraceBlockRequest defines TraceTx request
|
||||
message QueryTraceBlockRequest {
|
||||
// txs messages in the block
|
||||
// txs is an array of messages in the block
|
||||
repeated MsgEthereumTx txs = 1;
|
||||
// TraceConfig holds extra parameters to trace functions.
|
||||
// trace_config holds extra parameters to trace functions.
|
||||
TraceConfig trace_config = 3;
|
||||
// block number
|
||||
// block_number of the traced block
|
||||
int64 block_number = 5;
|
||||
// block hex hash
|
||||
// block_hash (hex) of the traced block
|
||||
string block_hash = 6;
|
||||
// block time
|
||||
// block_time of the traced block
|
||||
google.protobuf.Timestamp block_time = 7 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
|
||||
// the proposer of the requested block
|
||||
// proposer_address is the address of the requested block
|
||||
bytes proposer_address = 8 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.ConsAddress"];
|
||||
// chain_id is the eip155 chain id parsed from the requested block header
|
||||
int64 chain_id = 9;
|
||||
}
|
||||
|
||||
// QueryTraceBlockResponse defines TraceBlock response
|
||||
message QueryTraceBlockResponse {
|
||||
// data is the response serialized in bytes
|
||||
bytes data = 1;
|
||||
}
|
||||
|
||||
@ -284,7 +291,8 @@ message QueryTraceBlockResponse {
|
||||
// fee.
|
||||
message QueryBaseFeeRequest {}
|
||||
|
||||
// BaseFeeResponse returns the EIP1559 base fee.
|
||||
// QueryBaseFeeResponse returns the EIP1559 base fee.
|
||||
message QueryBaseFeeResponse {
|
||||
// base_fee is the EIP1559 base fee
|
||||
string base_fee = 1 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"];
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
syntax = "proto3";
|
||||
package ethermint.evm.v1;
|
||||
|
||||
import "cosmos_proto/cosmos.proto";
|
||||
import "ethermint/evm/v1/evm.proto";
|
||||
import "gogoproto/gogo.proto";
|
||||
import "google/api/annotations.proto";
|
||||
import "google/protobuf/any.proto";
|
||||
import "cosmos_proto/cosmos.proto";
|
||||
import "ethermint/evm/v1/evm.proto";
|
||||
|
||||
option go_package = "github.com/evmos/ethermint/x/evm/types";
|
||||
|
||||
@ -21,15 +21,14 @@ service Msg {
|
||||
message MsgEthereumTx {
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
|
||||
// inner transaction data
|
||||
// data is inner transaction data of the Ethereum transaction
|
||||
google.protobuf.Any data = 1;
|
||||
// caches
|
||||
|
||||
// DEPRECATED: encoded storage size of the transaction
|
||||
// size is the encoded storage size of the transaction (DEPRECATED)
|
||||
double size = 2 [(gogoproto.jsontag) = "-"];
|
||||
// transaction hash in hex format
|
||||
// hash of the transaction in hex format
|
||||
string hash = 3 [(gogoproto.moretags) = "rlp:\"-\""];
|
||||
// ethereum signer address in hex format. This address value is checked
|
||||
// from is the ethereum signer address in hex format. This address value is checked
|
||||
// against the address derived from the signature (V, R, S) using the
|
||||
// secp256k1 elliptic curve
|
||||
string from = 4;
|
||||
@ -39,21 +38,21 @@ message MsgEthereumTx {
|
||||
// NOTE: All non-protected transactions (i.e non EIP155 signed) will fail if the
|
||||
// AllowUnprotectedTxs parameter is disabled.
|
||||
message LegacyTx {
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
option (cosmos_proto.implements_interface) = "TxData";
|
||||
|
||||
// nonce corresponds to the account nonce (transaction sequence).
|
||||
uint64 nonce = 1;
|
||||
// gas price defines the value for each gas unit
|
||||
// gas_price defines the value for each gas unit
|
||||
string gas_price = 2 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"];
|
||||
// gas defines the gas limit defined for the transaction.
|
||||
uint64 gas = 3 [(gogoproto.customname) = "GasLimit"];
|
||||
// hex formatted address of the recipient
|
||||
// to is the hex formatted address of the recipient
|
||||
string to = 4;
|
||||
// value defines the unsigned integer value of the transaction amount.
|
||||
string value = 5
|
||||
[(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customname) = "Amount"];
|
||||
// input defines the data payload bytes of the transaction.
|
||||
// data is the data payload bytes of the transaction.
|
||||
bytes data = 6;
|
||||
// v defines the signature value
|
||||
bytes v = 7;
|
||||
@ -65,28 +64,29 @@ message LegacyTx {
|
||||
|
||||
// AccessListTx is the data of EIP-2930 access list transactions.
|
||||
message AccessListTx {
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
option (cosmos_proto.implements_interface) = "TxData";
|
||||
|
||||
// destination EVM chain ID
|
||||
// chain_id of the destination EVM chain
|
||||
string chain_id = 1 [
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(gogoproto.customname) = "ChainID",
|
||||
(gogoproto.jsontag) = "chainID"
|
||||
(gogoproto.jsontag) = "chainID"
|
||||
];
|
||||
// nonce corresponds to the account nonce (transaction sequence).
|
||||
uint64 nonce = 2;
|
||||
// gas price defines the value for each gas unit
|
||||
// gas_price defines the value for each gas unit
|
||||
string gas_price = 3 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"];
|
||||
// gas defines the gas limit defined for the transaction.
|
||||
uint64 gas = 4 [(gogoproto.customname) = "GasLimit"];
|
||||
// hex formatted address of the recipient
|
||||
// to is the recipient address in hex format
|
||||
string to = 5;
|
||||
// value defines the unsigned integer value of the transaction amount.
|
||||
string value = 6
|
||||
[(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customname) = "Amount"];
|
||||
// input defines the data payload bytes of the transaction.
|
||||
bytes data = 7;
|
||||
// data is the data payload bytes of the transaction.
|
||||
bytes data = 7;
|
||||
// accesses is an array of access tuples
|
||||
repeated AccessTuple accesses = 8
|
||||
[(gogoproto.castrepeated) = "AccessList", (gogoproto.jsontag) = "accessList", (gogoproto.nullable) = false];
|
||||
// v defines the signature value
|
||||
@ -99,30 +99,31 @@ message AccessListTx {
|
||||
|
||||
// DynamicFeeTx is the data of EIP-1559 dinamic fee transactions.
|
||||
message DynamicFeeTx {
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
option (cosmos_proto.implements_interface) = "TxData";
|
||||
|
||||
// destination EVM chain ID
|
||||
// chain_id of the destination EVM chain
|
||||
string chain_id = 1 [
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(gogoproto.customname) = "ChainID",
|
||||
(gogoproto.jsontag) = "chainID"
|
||||
(gogoproto.jsontag) = "chainID"
|
||||
];
|
||||
// nonce corresponds to the account nonce (transaction sequence).
|
||||
uint64 nonce = 2;
|
||||
// gas tip cap defines the max value for the gas tip
|
||||
// gas_tip_cap defines the max value for the gas tip
|
||||
string gas_tip_cap = 3 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"];
|
||||
// gas fee cap defines the max value for the gas fee
|
||||
// gas_fee_cap defines the max value for the gas fee
|
||||
string gas_fee_cap = 4 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"];
|
||||
// gas defines the gas limit defined for the transaction.
|
||||
uint64 gas = 5 [(gogoproto.customname) = "GasLimit"];
|
||||
// hex formatted address of the recipient
|
||||
// to is the hex formatted address of the recipient
|
||||
string to = 6;
|
||||
// value defines the the transaction amount.
|
||||
string value = 7
|
||||
[(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customname) = "Amount"];
|
||||
// input defines the data payload bytes of the transaction.
|
||||
bytes data = 8;
|
||||
// data is the data payload bytes of the transaction.
|
||||
bytes data = 8;
|
||||
// accesses is an array of access tuples
|
||||
repeated AccessTuple accesses = 9
|
||||
[(gogoproto.castrepeated) = "AccessList", (gogoproto.jsontag) = "accessList", (gogoproto.nullable) = false];
|
||||
// v defines the signature value
|
||||
@ -133,6 +134,7 @@ message DynamicFeeTx {
|
||||
bytes s = 12;
|
||||
}
|
||||
|
||||
// ExtensionOptionsEthereumTx is an extension option for ethereum transactions
|
||||
message ExtensionOptionsEthereumTx {
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
}
|
||||
@ -141,18 +143,18 @@ message ExtensionOptionsEthereumTx {
|
||||
message MsgEthereumTxResponse {
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
|
||||
// ethereum transaction hash in hex format. This hash differs from the
|
||||
// hash of the ethereum transaction in hex format. This hash differs from the
|
||||
// Tendermint sha256 hash of the transaction bytes. See
|
||||
// https://github.com/tendermint/tendermint/issues/6539 for reference
|
||||
string hash = 1;
|
||||
// logs contains the transaction hash and the proto-compatible ethereum
|
||||
// logs.
|
||||
repeated Log logs = 2;
|
||||
// returned data from evm function (result or data supplied with revert
|
||||
// ret is the returned data from evm function (result or data supplied with revert
|
||||
// opcode)
|
||||
bytes ret = 3;
|
||||
// vm error is the error returned by vm execution
|
||||
// vm_error is the error returned by vm execution
|
||||
string vm_error = 4;
|
||||
// gas consumed by the transaction
|
||||
// gas_used specifies how much gas was consumed by the transaction
|
||||
uint64 gas_used = 5;
|
||||
}
|
||||
|
@ -7,26 +7,26 @@ option go_package = "github.com/evmos/ethermint/x/feemarket/types";
|
||||
|
||||
// Params defines the EVM module parameters
|
||||
message Params {
|
||||
// no base fee forces the EIP-1559 base fee to 0 (needed for 0 price calls)
|
||||
// no_base_fee forces the EIP-1559 base fee to 0 (needed for 0 price calls)
|
||||
bool no_base_fee = 1;
|
||||
// base fee change denominator bounds the amount the base fee can change
|
||||
// base_fee_change_denominator bounds the amount the base fee can change
|
||||
// between blocks.
|
||||
uint32 base_fee_change_denominator = 2;
|
||||
// elasticity multiplier bounds the maximum gas limit an EIP-1559 block may
|
||||
// elasticity_multiplier bounds the maximum gas limit an EIP-1559 block may
|
||||
// have.
|
||||
uint32 elasticity_multiplier = 3;
|
||||
// DEPRECATED: initial base fee for EIP-1559 blocks.
|
||||
reserved 4;
|
||||
reserved "initial_base_fee";
|
||||
// height at which the base fee calculation is enabled.
|
||||
// enable_height defines at which block height the base fee calculation is enabled.
|
||||
int64 enable_height = 5;
|
||||
// base fee for EIP-1559 blocks.
|
||||
// base_fee for EIP-1559 blocks.
|
||||
string base_fee = 6 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.nullable) = false];
|
||||
// min_gas_price defines the minimum gas price value for cosmos and eth transactions
|
||||
string min_gas_price = 7
|
||||
[(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false];
|
||||
// min gas denominator bounds the minimum gasUsed to be charged
|
||||
// to senders based on GasLimit
|
||||
// min_gas_multiplier bounds the minimum gas used to be charged
|
||||
// to senders based on gas limit
|
||||
string min_gas_multiplier = 8
|
||||
[(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false];
|
||||
}
|
||||
|
@ -1,20 +1,20 @@
|
||||
syntax = "proto3";
|
||||
package ethermint.feemarket.v1;
|
||||
|
||||
import "gogoproto/gogo.proto";
|
||||
import "ethermint/feemarket/v1/feemarket.proto";
|
||||
import "gogoproto/gogo.proto";
|
||||
|
||||
option go_package = "github.com/evmos/ethermint/x/feemarket/types";
|
||||
|
||||
// GenesisState defines the feemarket module's genesis state.
|
||||
message GenesisState {
|
||||
// params defines all the paramaters of the module.
|
||||
// params defines all the parameters of the feemarket module.
|
||||
Params params = 1 [(gogoproto.nullable) = false];
|
||||
// DEPRECATED: base fee is the exported value from previous software version.
|
||||
// Zero by default.
|
||||
reserved 2;
|
||||
reserved "base_fee";
|
||||
// block gas is the amount of gas wanted on the last block before the upgrade.
|
||||
// block_gas is the amount of gas wanted on the last block before the upgrade.
|
||||
// Zero by default.
|
||||
uint64 block_gas = 3;
|
||||
}
|
@ -3,8 +3,8 @@ package ethermint.feemarket.v1;
|
||||
|
||||
import "gogoproto/gogo.proto";
|
||||
// import "cosmos/base/query/v1beta1/pagination.proto";
|
||||
import "google/api/annotations.proto";
|
||||
import "ethermint/feemarket/v1/feemarket.proto";
|
||||
import "google/api/annotations.proto";
|
||||
|
||||
option go_package = "github.com/evmos/ethermint/x/feemarket/types";
|
||||
|
||||
@ -39,8 +39,9 @@ message QueryParamsResponse {
|
||||
// fee.
|
||||
message QueryBaseFeeRequest {}
|
||||
|
||||
// BaseFeeResponse returns the EIP1559 base fee.
|
||||
// QueryBaseFeeResponse returns the EIP1559 base fee.
|
||||
message QueryBaseFeeResponse {
|
||||
// base_fee is the EIP1559 base fee
|
||||
string base_fee = 1 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"];
|
||||
}
|
||||
|
||||
@ -50,5 +51,6 @@ message QueryBlockGasRequest {}
|
||||
|
||||
// QueryBlockGasResponse returns block gas used for a given height.
|
||||
message QueryBlockGasResponse {
|
||||
// gas is the returned block gas
|
||||
int64 gas = 1;
|
||||
}
|
@ -10,13 +10,16 @@ option go_package = "github.com/evmos/ethermint/types";
|
||||
// EthAccount implements the authtypes.AccountI interface and embeds an
|
||||
// authtypes.BaseAccount type. It is compatible with the auth AccountKeeper.
|
||||
message EthAccount {
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
option (gogoproto.goproto_stringer) = false;
|
||||
option (gogoproto.equal) = false;
|
||||
option (gogoproto.equal) = false;
|
||||
|
||||
option (cosmos_proto.implements_interface) = "github.com/cosmos/cosmos-sdk/x/auth/types.AccountI";
|
||||
|
||||
// base_account is an authtypes.BaseAccount
|
||||
cosmos.auth.v1beta1.BaseAccount base_account = 1
|
||||
[(gogoproto.embed) = true, (gogoproto.moretags) = "yaml:\"base_account\""];
|
||||
|
||||
// code_hash is the hash calculated from the code contents
|
||||
string code_hash = 2 [(gogoproto.moretags) = "yaml:\"code_hash\""];
|
||||
}
|
||||
|
@ -5,9 +5,9 @@ import "gogoproto/gogo.proto";
|
||||
|
||||
option go_package = "github.com/evmos/ethermint/types";
|
||||
|
||||
// ExtensionOptionDynamicFeeTx is an extension option that specify the maxPrioPrice for cosmos tx
|
||||
// ExtensionOptionDynamicFeeTx is an extension option that specifies the maxPrioPrice for cosmos tx
|
||||
message ExtensionOptionDynamicFeeTx {
|
||||
// the same as `max_priority_fee_per_gas` in eip-1559 spec
|
||||
// max_priority_price is the same as `max_priority_fee_per_gas` in eip-1559 spec
|
||||
string max_priority_price = 1
|
||||
[(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.nullable) = false];
|
||||
}
|
||||
|
@ -9,21 +9,22 @@ option go_package = "github.com/evmos/ethermint/types";
|
||||
message TxResult {
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
|
||||
// the block height
|
||||
// height of the blockchain
|
||||
int64 height = 1;
|
||||
// cosmos tx index
|
||||
// tx_index of the cosmos transaction
|
||||
uint32 tx_index = 2;
|
||||
// the msg index in a batch tx
|
||||
// msg_index in a batch transaction
|
||||
uint32 msg_index = 3;
|
||||
|
||||
// eth tx index, the index in the list of valid eth tx in the block,
|
||||
// eth_tx_index is the index in the list of valid eth tx in the block,
|
||||
// aka. the transaction list returned by eth_getBlock api.
|
||||
int32 eth_tx_index = 4;
|
||||
// if the eth tx is failed
|
||||
// failed is true if the eth transaction did not go succeed
|
||||
bool failed = 5;
|
||||
// gas used by tx, if exceeds block gas limit,
|
||||
// it's set to gas limit which is what's actually deducted by ante handler.
|
||||
// gas_used by the transaction. If it exceeds the block gas limit,
|
||||
// it's set to gas limit, which is what's actually deducted by ante handler.
|
||||
uint64 gas_used = 6;
|
||||
// the cumulative gas used within current batch tx
|
||||
// cumulative_gas_used specifies the cumulated amount of gas used for all
|
||||
// processed messages within the current batch transaction.
|
||||
uint64 cumulative_gas_used = 7;
|
||||
}
|
||||
|
@ -5,19 +5,21 @@ import "gogoproto/gogo.proto";
|
||||
|
||||
option go_package = "github.com/evmos/ethermint/types";
|
||||
|
||||
// ExtensionOptionsWeb3Tx is an extension option that specifies the typed chain id,
|
||||
// the fee payer as well as its signature data.
|
||||
message ExtensionOptionsWeb3Tx {
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
|
||||
// typed data chain id used only in EIP712 Domain and should match
|
||||
// typed_data_chain_id is used only in EIP712 Domain and should match
|
||||
// Ethereum network ID in a Web3 provider (e.g. Metamask).
|
||||
uint64 typed_data_chain_id = 1
|
||||
[(gogoproto.jsontag) = "typedDataChainID,omitempty", (gogoproto.customname) = "TypedDataChainID"];
|
||||
|
||||
// fee payer is an account address for the fee payer. It will be validated
|
||||
// fee_payer is an account address for the fee payer. It will be validated
|
||||
// during EIP712 signature checking.
|
||||
string fee_payer = 2 [(gogoproto.jsontag) = "feePayer,omitempty"];
|
||||
|
||||
// fee payer sig is a signature data from the fee paying account,
|
||||
// fee_payer_sig is a signature data from the fee paying account,
|
||||
// allows to perform fee delegation when using EIP712 Domain.
|
||||
bytes fee_payer_sig = 3 [(gogoproto.jsontag) = "feePayerSig,omitempty"];
|
||||
}
|
||||
|
@ -75,16 +75,10 @@ func (b *Backend) GetProof(address common.Address, storageKeys []string, blockNr
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// check for proof
|
||||
var proofStr string
|
||||
if proof != nil {
|
||||
proofStr = proof.String()
|
||||
}
|
||||
|
||||
storageProofs[i] = rpctypes.StorageResult{
|
||||
Key: key,
|
||||
Value: (*hexutil.Big)(new(big.Int).SetBytes(valueBz)),
|
||||
Proof: []string{proofStr},
|
||||
Proof: GetHexProofs(proof),
|
||||
}
|
||||
}
|
||||
|
||||
@ -105,12 +99,6 @@ func (b *Backend) GetProof(address common.Address, storageKeys []string, blockNr
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// check for proof
|
||||
var accProofStr string
|
||||
if proof != nil {
|
||||
accProofStr = proof.String()
|
||||
}
|
||||
|
||||
balance, ok := sdkmath.NewIntFromString(res.Balance)
|
||||
if !ok {
|
||||
return nil, errors.New("invalid balance")
|
||||
@ -118,7 +106,7 @@ func (b *Backend) GetProof(address common.Address, storageKeys []string, blockNr
|
||||
|
||||
return &rpctypes.AccountResult{
|
||||
Address: address,
|
||||
AccountProof: []string{accProofStr},
|
||||
AccountProof: GetHexProofs(proof),
|
||||
Balance: (*hexutil.Big)(balance.BigInt()),
|
||||
CodeHash: common.HexToHash(res.CodeHash),
|
||||
Nonce: hexutil.Uint64(res.Nonce),
|
||||
|
@ -103,6 +103,18 @@ func (suite *BackendTestSuite) TestGetProof() {
|
||||
false,
|
||||
&rpctypes.AccountResult{},
|
||||
},
|
||||
{
|
||||
"fail - Block doesn't exist)",
|
||||
address1,
|
||||
[]string{},
|
||||
rpctypes.BlockNumberOrHash{BlockNumber: &blockNrInvalid},
|
||||
func(bn rpctypes.BlockNumber, addr common.Address) {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
RegisterBlockError(client, bn.Int64())
|
||||
},
|
||||
false,
|
||||
&rpctypes.AccountResult{},
|
||||
},
|
||||
{
|
||||
"pass",
|
||||
address1,
|
||||
@ -351,6 +363,27 @@ func (suite *BackendTestSuite) TestGetTransactionCount() {
|
||||
true,
|
||||
hexutil.Uint64(0),
|
||||
},
|
||||
// TODO: Error mocking the GetAccount call - problem with Any type
|
||||
//{
|
||||
// "pass - returns the number of transactions at the given address up to the given block number",
|
||||
// true,
|
||||
// rpctypes.NewBlockNumber(big.NewInt(1)),
|
||||
// func(addr common.Address, bn rpctypes.BlockNumber) {
|
||||
// client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
// account, err := suite.backend.clientCtx.AccountRetriever.GetAccount(suite.backend.clientCtx, suite.acc)
|
||||
// suite.Require().NoError(err)
|
||||
// request := &authtypes.QueryAccountRequest{Address: sdk.AccAddress(suite.acc.Bytes()).String()}
|
||||
// requestMarshal, _ := request.Marshal()
|
||||
// RegisterABCIQueryAccount(
|
||||
// client,
|
||||
// requestMarshal,
|
||||
// tmrpcclient.ABCIQueryOptions{Height: int64(1), Prove: false},
|
||||
// account,
|
||||
// )
|
||||
// },
|
||||
// true,
|
||||
// hexutil.Uint64(0),
|
||||
//},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
|
||||
|
@ -6,7 +6,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
@ -16,12 +15,10 @@ import (
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
||||
"github.com/evmos/ethermint/crypto/hd"
|
||||
rpctypes "github.com/evmos/ethermint/rpc/types"
|
||||
"github.com/evmos/ethermint/server/config"
|
||||
ethermint "github.com/evmos/ethermint/types"
|
||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
tmrpctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||
)
|
||||
@ -162,23 +159,6 @@ func NewBackend(
|
||||
panic(err)
|
||||
}
|
||||
|
||||
algos, _ := clientCtx.Keyring.SupportedAlgorithms()
|
||||
if !algos.Contains(hd.EthSecp256k1) {
|
||||
kr, err := keyring.New(
|
||||
sdk.KeyringServiceName(),
|
||||
viper.GetString(flags.FlagKeyringBackend),
|
||||
clientCtx.KeyringDir,
|
||||
clientCtx.Input,
|
||||
clientCtx.Codec,
|
||||
hd.EthSecp256k1Option(),
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
clientCtx = clientCtx.WithKeyring(kr)
|
||||
}
|
||||
|
||||
return &Backend{
|
||||
ctx: context.Background(),
|
||||
clientCtx: clientCtx,
|
||||
|
@ -2,12 +2,13 @@ package backend
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/evmos/ethermint/crypto/ethsecp256k1"
|
||||
|
||||
dbm "github.com/tendermint/tm-db"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
@ -33,19 +34,22 @@ type BackendTestSuite struct {
|
||||
suite.Suite
|
||||
backend *Backend
|
||||
acc sdk.AccAddress
|
||||
signer keyring.Signer
|
||||
}
|
||||
|
||||
func TestBackendTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(BackendTestSuite))
|
||||
}
|
||||
|
||||
const ChainID = "ethermint_9000-1"
|
||||
|
||||
// SetupTest is executed before every BackendTestSuite test
|
||||
func (suite *BackendTestSuite) SetupTest() {
|
||||
ctx := server.NewDefaultContext()
|
||||
ctx.Viper.Set("telemetry.global-labels", []interface{}{})
|
||||
|
||||
baseDir := suite.T().TempDir()
|
||||
nodeDirName := fmt.Sprintf("node")
|
||||
nodeDirName := "node"
|
||||
clientDir := filepath.Join(baseDir, nodeDirName, "evmoscli")
|
||||
keyRing, err := suite.generateTestKeyring(clientDir)
|
||||
if err != nil {
|
||||
@ -61,8 +65,12 @@ func (suite *BackendTestSuite) SetupTest() {
|
||||
Seq: uint64(1),
|
||||
}
|
||||
|
||||
priv, err := ethsecp256k1.GenerateKey()
|
||||
suite.signer = tests.NewSigner(priv)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
encodingConfig := encoding.MakeConfig(app.ModuleBasics)
|
||||
clientCtx := client.Context{}.WithChainID("ethermint_9000-1").
|
||||
clientCtx := client.Context{}.WithChainID(ChainID).
|
||||
WithHeight(1).
|
||||
WithTxConfig(encodingConfig.TxConfig).
|
||||
WithKeyringDir(clientDir).
|
||||
@ -70,19 +78,24 @@ func (suite *BackendTestSuite) SetupTest() {
|
||||
WithAccountRetriever(client.TestAccountRetriever{Accounts: accounts})
|
||||
|
||||
allowUnprotectedTxs := false
|
||||
|
||||
idxer := indexer.NewKVIndexer(dbm.NewMemDB(), ctx.Logger, clientCtx)
|
||||
|
||||
suite.backend = NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, idxer)
|
||||
suite.backend.queryClient.QueryClient = mocks.NewEVMQueryClient(suite.T())
|
||||
suite.backend.clientCtx.Client = mocks.NewClient(suite.T())
|
||||
suite.backend.queryClient.FeeMarket = mocks.NewFeeMarketQueryClient(suite.T())
|
||||
suite.backend.ctx = rpctypes.ContextWithHeight(1)
|
||||
|
||||
// Add codec
|
||||
encCfg := encoding.MakeConfig(app.ModuleBasics)
|
||||
suite.backend.clientCtx.Codec = encCfg.Codec
|
||||
|
||||
}
|
||||
|
||||
// buildEthereumTx returns an example legacy Ethereum transaction
|
||||
func (suite *BackendTestSuite) buildEthereumTx() (*evmtypes.MsgEthereumTx, []byte) {
|
||||
msgEthereumTx := evmtypes.NewTx(
|
||||
big.NewInt(1),
|
||||
suite.backend.chainID,
|
||||
uint64(0),
|
||||
&common.Address{},
|
||||
big.NewInt(0),
|
||||
@ -132,6 +145,7 @@ func (suite *BackendTestSuite) buildFormattedBlock(
|
||||
uint64(header.Height),
|
||||
uint64(0),
|
||||
baseFee,
|
||||
suite.backend.chainID,
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
ethRPCTxs = []interface{}{rpcTx}
|
||||
@ -157,3 +171,25 @@ func (suite *BackendTestSuite) generateTestKeyring(clientDir string) (keyring.Ke
|
||||
encCfg := encoding.MakeConfig(app.ModuleBasics)
|
||||
return keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, clientDir, buf, encCfg.Codec, []keyring.Option{hd.EthSecp256k1Option()}...)
|
||||
}
|
||||
|
||||
func (suite *BackendTestSuite) signAndEncodeEthTx(msgEthereumTx *evmtypes.MsgEthereumTx) []byte {
|
||||
from, priv := tests.NewAddrKey()
|
||||
signer := tests.NewSigner(priv)
|
||||
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
RegisterParamsWithoutHeader(queryClient, 1)
|
||||
|
||||
ethSigner := ethtypes.LatestSigner(suite.backend.ChainConfig())
|
||||
msgEthereumTx.From = from.String()
|
||||
err := msgEthereumTx.Sign(ethSigner, signer)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
tx, err := msgEthereumTx.BuildTx(suite.backend.clientCtx.TxConfig.NewTxBuilder(), "aphoton")
|
||||
suite.Require().NoError(err)
|
||||
|
||||
txEncoder := suite.backend.clientCtx.TxConfig.TxEncoder()
|
||||
txBz, err := txEncoder(tx)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
return txBz
|
||||
}
|
||||
|
@ -376,6 +376,7 @@ func (b *Backend) RPCBlockFromTendermintBlock(
|
||||
uint64(block.Height),
|
||||
uint64(txIndex),
|
||||
baseFee,
|
||||
b.chainID,
|
||||
)
|
||||
if err != nil {
|
||||
b.logger.Debug("NewTransactionFromData for receipt failed", "hash", tx.Hash().Hex(), "error", err.Error())
|
||||
|
@ -30,8 +30,8 @@ func (suite *BackendTestSuite) TestBlockNumber() {
|
||||
{
|
||||
"fail - invalid block header height",
|
||||
func() {
|
||||
height := int64(1)
|
||||
var header metadata.MD
|
||||
height := int64(1)
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
RegisterParamsInvalidHeight(queryClient, &header, int64(height))
|
||||
},
|
||||
@ -41,8 +41,8 @@ func (suite *BackendTestSuite) TestBlockNumber() {
|
||||
{
|
||||
"fail - invalid block header",
|
||||
func() {
|
||||
height := int64(1)
|
||||
var header metadata.MD
|
||||
height := int64(1)
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
RegisterParamsInvalidHeader(queryClient, &header, int64(height))
|
||||
},
|
||||
@ -52,8 +52,8 @@ func (suite *BackendTestSuite) TestBlockNumber() {
|
||||
{
|
||||
"pass - app state header height 1",
|
||||
func() {
|
||||
height := int64(1)
|
||||
var header metadata.MD
|
||||
height := int64(1)
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
RegisterParams(queryClient, &header, int64(height))
|
||||
},
|
||||
@ -552,8 +552,8 @@ func (suite *BackendTestSuite) TestTendermintBlockByNumber() {
|
||||
"fail - blockNum < 0 with app state height error",
|
||||
ethrpc.BlockNumber(-1),
|
||||
func(_ ethrpc.BlockNumber) {
|
||||
appHeight := int64(1)
|
||||
var header metadata.MD
|
||||
appHeight := int64(1)
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
RegisterParamsError(queryClient, &header, appHeight)
|
||||
},
|
||||
@ -564,8 +564,8 @@ func (suite *BackendTestSuite) TestTendermintBlockByNumber() {
|
||||
"pass - blockNum < 0 with app state height >= 1",
|
||||
ethrpc.BlockNumber(-1),
|
||||
func(blockNum ethrpc.BlockNumber) {
|
||||
appHeight := int64(1)
|
||||
var header metadata.MD
|
||||
appHeight := int64(1)
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
RegisterParams(queryClient, &header, appHeight)
|
||||
|
||||
@ -1088,6 +1088,7 @@ func (suite *BackendTestSuite) TestGetEthBlockFromTendermint() {
|
||||
uint64(header.Height),
|
||||
uint64(0),
|
||||
tc.baseFee,
|
||||
suite.backend.chainID,
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
ethRPCTxs = []interface{}{rpcTx}
|
||||
|
@ -7,9 +7,9 @@ import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
@ -151,7 +151,7 @@ func (b *Backend) SendRawTransaction(data hexutil.Bytes) (common.Hash, error) {
|
||||
syncCtx := b.clientCtx.WithBroadcastMode(flags.BroadcastSync)
|
||||
rsp, err := syncCtx.BroadcastTx(txBytes)
|
||||
if rsp != nil && rsp.Code != 0 {
|
||||
err = sdkerrors.ABCIError(rsp.Codespace, rsp.Code, rsp.RawLog)
|
||||
err = errorsmod.ABCIError(rsp.Codespace, rsp.Code, rsp.RawLog)
|
||||
}
|
||||
if err != nil {
|
||||
b.logger.Error("failed to broadcast tx", "error", err.Error())
|
||||
@ -269,6 +269,8 @@ func (b *Backend) SetTxDefaults(args evmtypes.TransactionArgs) (evmtypes.Transac
|
||||
Value: args.Value,
|
||||
Data: input,
|
||||
AccessList: args.AccessList,
|
||||
ChainID: args.ChainID,
|
||||
Nonce: args.Nonce,
|
||||
}
|
||||
|
||||
blockNr := rpctypes.NewBlockNumber(big.NewInt(0))
|
||||
@ -309,6 +311,7 @@ func (b *Backend) EstimateGas(args evmtypes.TransactionArgs, blockNrOptional *rp
|
||||
Args: bz,
|
||||
GasCap: b.RPCGasCap(),
|
||||
ProposerAddress: sdk.ConsAddress(header.Block.ProposerAddress),
|
||||
ChainId: b.chainID.Int64(),
|
||||
}
|
||||
|
||||
// From ContextWithHeight: if the provided height is 0,
|
||||
@ -335,10 +338,12 @@ func (b *Backend) DoCall(
|
||||
// the error message imitates geth behavior
|
||||
return nil, errors.New("header not found")
|
||||
}
|
||||
|
||||
req := evmtypes.EthCallRequest{
|
||||
Args: bz,
|
||||
GasCap: b.RPCGasCap(),
|
||||
ProposerAddress: sdk.ConsAddress(header.Block.ProposerAddress),
|
||||
ChainId: b.chainID.Int64(),
|
||||
}
|
||||
|
||||
// From ContextWithHeight: if the provided height is 0,
|
||||
|
493
rpc/backend/call_tx_test.go
Normal file
493
rpc/backend/call_tx_test.go
Normal file
@ -0,0 +1,493 @@
|
||||
package backend
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/evmos/ethermint/rpc/backend/mocks"
|
||||
rpctypes "github.com/evmos/ethermint/rpc/types"
|
||||
"github.com/evmos/ethermint/tests"
|
||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
func (suite *BackendTestSuite) TestResend() {
|
||||
txNonce := (hexutil.Uint64)(1)
|
||||
baseFee := sdk.NewInt(1)
|
||||
gasPrice := new(hexutil.Big)
|
||||
toAddr := tests.GenerateAddress()
|
||||
chainID := (*hexutil.Big)(suite.backend.chainID)
|
||||
callArgs := evmtypes.TransactionArgs{
|
||||
From: nil,
|
||||
To: &toAddr,
|
||||
Gas: nil,
|
||||
GasPrice: nil,
|
||||
MaxFeePerGas: gasPrice,
|
||||
MaxPriorityFeePerGas: gasPrice,
|
||||
Value: gasPrice,
|
||||
Nonce: &txNonce,
|
||||
Input: nil,
|
||||
Data: nil,
|
||||
AccessList: nil,
|
||||
ChainID: chainID,
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func()
|
||||
args evmtypes.TransactionArgs
|
||||
gasPrice *hexutil.Big
|
||||
gasLimit *hexutil.Uint64
|
||||
expHash common.Hash
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"fail - Missing transaction nonce ",
|
||||
func() {},
|
||||
evmtypes.TransactionArgs{
|
||||
Nonce: nil,
|
||||
},
|
||||
nil,
|
||||
nil,
|
||||
common.Hash{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"pass - Can't set Tx defaults BaseFee disabled",
|
||||
func() {
|
||||
var header metadata.MD
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
RegisterParams(queryClient, &header, 1)
|
||||
RegisterBlock(client, 1, nil)
|
||||
RegisterBlockResults(client, 1)
|
||||
RegisterBaseFeeDisabled(queryClient)
|
||||
},
|
||||
evmtypes.TransactionArgs{
|
||||
Nonce: &txNonce,
|
||||
ChainID: callArgs.ChainID,
|
||||
},
|
||||
nil,
|
||||
nil,
|
||||
common.Hash{},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"pass - Can't set Tx defaults ",
|
||||
func() {
|
||||
var header metadata.MD
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
feeMarketClient := suite.backend.queryClient.FeeMarket.(*mocks.FeeMarketQueryClient)
|
||||
RegisterParams(queryClient, &header, 1)
|
||||
RegisterFeeMarketParams(feeMarketClient, 1)
|
||||
RegisterBlock(client, 1, nil)
|
||||
RegisterBlockResults(client, 1)
|
||||
RegisterBaseFee(queryClient, baseFee)
|
||||
},
|
||||
evmtypes.TransactionArgs{
|
||||
Nonce: &txNonce,
|
||||
},
|
||||
nil,
|
||||
nil,
|
||||
common.Hash{},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"pass - MaxFeePerGas is nil",
|
||||
func() {
|
||||
var header metadata.MD
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
RegisterParams(queryClient, &header, 1)
|
||||
RegisterBlock(client, 1, nil)
|
||||
RegisterBlockResults(client, 1)
|
||||
RegisterBaseFeeDisabled(queryClient)
|
||||
},
|
||||
evmtypes.TransactionArgs{
|
||||
Nonce: &txNonce,
|
||||
MaxPriorityFeePerGas: nil,
|
||||
GasPrice: nil,
|
||||
MaxFeePerGas: nil,
|
||||
},
|
||||
nil,
|
||||
nil,
|
||||
common.Hash{},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"fail - GasPrice and (MaxFeePerGas or MaxPriorityPerGas specified",
|
||||
func() {},
|
||||
evmtypes.TransactionArgs{
|
||||
Nonce: &txNonce,
|
||||
MaxPriorityFeePerGas: nil,
|
||||
GasPrice: gasPrice,
|
||||
MaxFeePerGas: gasPrice,
|
||||
},
|
||||
nil,
|
||||
nil,
|
||||
common.Hash{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"fail - Block error",
|
||||
func() {
|
||||
var header metadata.MD
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
RegisterParams(queryClient, &header, 1)
|
||||
RegisterBlockError(client, 1)
|
||||
},
|
||||
evmtypes.TransactionArgs{
|
||||
Nonce: &txNonce,
|
||||
},
|
||||
nil,
|
||||
nil,
|
||||
common.Hash{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"pass - MaxFeePerGas is nil",
|
||||
func() {
|
||||
var header metadata.MD
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
RegisterParams(queryClient, &header, 1)
|
||||
RegisterBlock(client, 1, nil)
|
||||
RegisterBlockResults(client, 1)
|
||||
RegisterBaseFee(queryClient, baseFee)
|
||||
},
|
||||
evmtypes.TransactionArgs{
|
||||
Nonce: &txNonce,
|
||||
GasPrice: nil,
|
||||
MaxPriorityFeePerGas: gasPrice,
|
||||
MaxFeePerGas: gasPrice,
|
||||
ChainID: callArgs.ChainID,
|
||||
},
|
||||
nil,
|
||||
nil,
|
||||
common.Hash{},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"pass - Chain Id is nil",
|
||||
func() {
|
||||
var header metadata.MD
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
RegisterParams(queryClient, &header, 1)
|
||||
RegisterBlock(client, 1, nil)
|
||||
RegisterBlockResults(client, 1)
|
||||
RegisterBaseFee(queryClient, baseFee)
|
||||
},
|
||||
evmtypes.TransactionArgs{
|
||||
Nonce: &txNonce,
|
||||
MaxPriorityFeePerGas: gasPrice,
|
||||
ChainID: nil,
|
||||
},
|
||||
nil,
|
||||
nil,
|
||||
common.Hash{},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"fail - Pending transactions error",
|
||||
func() {
|
||||
var header metadata.MD
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
RegisterBlock(client, 1, nil)
|
||||
RegisterBlockResults(client, 1)
|
||||
RegisterBaseFee(queryClient, baseFee)
|
||||
RegisterEstimateGas(queryClient, callArgs)
|
||||
RegisterParams(queryClient, &header, 1)
|
||||
RegisterParamsWithoutHeader(queryClient, 1)
|
||||
RegisterUnconfirmedTxsError(client, nil)
|
||||
},
|
||||
evmtypes.TransactionArgs{
|
||||
Nonce: &txNonce,
|
||||
To: &toAddr,
|
||||
MaxFeePerGas: gasPrice,
|
||||
MaxPriorityFeePerGas: gasPrice,
|
||||
Value: gasPrice,
|
||||
Gas: nil,
|
||||
ChainID: callArgs.ChainID,
|
||||
},
|
||||
gasPrice,
|
||||
nil,
|
||||
common.Hash{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"fail - Not Ethereum txs",
|
||||
func() {
|
||||
var header metadata.MD
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
RegisterBlock(client, 1, nil)
|
||||
RegisterBlockResults(client, 1)
|
||||
RegisterBaseFee(queryClient, baseFee)
|
||||
RegisterEstimateGas(queryClient, callArgs)
|
||||
RegisterParams(queryClient, &header, 1)
|
||||
RegisterParamsWithoutHeader(queryClient, 1)
|
||||
RegisterUnconfirmedTxsEmpty(client, nil)
|
||||
},
|
||||
evmtypes.TransactionArgs{
|
||||
Nonce: &txNonce,
|
||||
To: &toAddr,
|
||||
MaxFeePerGas: gasPrice,
|
||||
MaxPriorityFeePerGas: gasPrice,
|
||||
Value: gasPrice,
|
||||
Gas: nil,
|
||||
ChainID: callArgs.ChainID,
|
||||
},
|
||||
gasPrice,
|
||||
nil,
|
||||
common.Hash{},
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("case %s", tc.name), func() {
|
||||
suite.SetupTest() // reset test and queries
|
||||
tc.registerMock()
|
||||
|
||||
hash, err := suite.backend.Resend(tc.args, tc.gasPrice, tc.gasLimit)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().Equal(tc.expHash, hash)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *BackendTestSuite) TestSendRawTransaction() {
|
||||
ethTx, bz := suite.buildEthereumTx()
|
||||
rlpEncodedBz, _ := rlp.EncodeToBytes(ethTx.AsTransaction())
|
||||
cosmosTx, _ := ethTx.BuildTx(suite.backend.clientCtx.TxConfig.NewTxBuilder(), "aphoton")
|
||||
txBytes, _ := suite.backend.clientCtx.TxConfig.TxEncoder()(cosmosTx)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func()
|
||||
rawTx []byte
|
||||
expHash common.Hash
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"fail - empty bytes",
|
||||
func() {},
|
||||
[]byte{},
|
||||
common.Hash{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"fail - no RLP encoded bytes",
|
||||
func() {},
|
||||
bz,
|
||||
common.Hash{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"fail - unprotected transactions",
|
||||
func() {
|
||||
suite.backend.allowUnprotectedTxs = false
|
||||
},
|
||||
rlpEncodedBz,
|
||||
common.Hash{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"fail - failed to get evm params",
|
||||
func() {
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
suite.backend.allowUnprotectedTxs = true
|
||||
RegisterParamsWithoutHeaderError(queryClient, 1)
|
||||
},
|
||||
rlpEncodedBz,
|
||||
common.Hash{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"fail - failed to broadcast transaction",
|
||||
func() {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
suite.backend.allowUnprotectedTxs = true
|
||||
RegisterParamsWithoutHeader(queryClient, 1)
|
||||
RegisterBroadcastTxError(client, txBytes)
|
||||
},
|
||||
rlpEncodedBz,
|
||||
common.HexToHash(ethTx.Hash),
|
||||
false,
|
||||
},
|
||||
{
|
||||
"pass - Gets the correct transaction hash of the eth transaction",
|
||||
func() {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
suite.backend.allowUnprotectedTxs = true
|
||||
RegisterParamsWithoutHeader(queryClient, 1)
|
||||
RegisterBroadcastTx(client, txBytes)
|
||||
},
|
||||
rlpEncodedBz,
|
||||
common.HexToHash(ethTx.Hash),
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("case %s", tc.name), func() {
|
||||
suite.SetupTest() // reset test and queries
|
||||
tc.registerMock()
|
||||
|
||||
hash, err := suite.backend.SendRawTransaction(tc.rawTx)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().Equal(tc.expHash, hash)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *BackendTestSuite) TestDoCall() {
|
||||
_, bz := suite.buildEthereumTx()
|
||||
gasPrice := (*hexutil.Big)(big.NewInt(1))
|
||||
toAddr := tests.GenerateAddress()
|
||||
chainID := (*hexutil.Big)(suite.backend.chainID)
|
||||
callArgs := evmtypes.TransactionArgs{
|
||||
From: nil,
|
||||
To: &toAddr,
|
||||
Gas: nil,
|
||||
GasPrice: nil,
|
||||
MaxFeePerGas: gasPrice,
|
||||
MaxPriorityFeePerGas: gasPrice,
|
||||
Value: gasPrice,
|
||||
Input: nil,
|
||||
Data: nil,
|
||||
AccessList: nil,
|
||||
ChainID: chainID,
|
||||
}
|
||||
argsBz, err := json.Marshal(callArgs)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func()
|
||||
blockNum rpctypes.BlockNumber
|
||||
callArgs evmtypes.TransactionArgs
|
||||
expEthTx *evmtypes.MsgEthereumTxResponse
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"fail - Invalid request",
|
||||
func() {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
RegisterBlock(client, 1, bz)
|
||||
RegisterEthCallError(queryClient, &evmtypes.EthCallRequest{Args: argsBz, ChainId: suite.backend.chainID.Int64()})
|
||||
},
|
||||
rpctypes.BlockNumber(1),
|
||||
callArgs,
|
||||
&evmtypes.MsgEthereumTxResponse{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"pass - Returned transaction response",
|
||||
func() {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
RegisterBlock(client, 1, bz)
|
||||
RegisterEthCall(queryClient, &evmtypes.EthCallRequest{Args: argsBz, ChainId: suite.backend.chainID.Int64()})
|
||||
},
|
||||
rpctypes.BlockNumber(1),
|
||||
callArgs,
|
||||
&evmtypes.MsgEthereumTxResponse{},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("case %s", tc.name), func() {
|
||||
suite.SetupTest() // reset test and queries
|
||||
tc.registerMock()
|
||||
|
||||
msgEthTx, err := suite.backend.DoCall(tc.callArgs, tc.blockNum)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().Equal(tc.expEthTx, msgEthTx)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *BackendTestSuite) TestGasPrice() {
|
||||
defaultGasPrice := (*hexutil.Big)(big.NewInt(1))
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func()
|
||||
expGas *hexutil.Big
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"pass - get the default gas price",
|
||||
func() {
|
||||
var header metadata.MD
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
feeMarketClient := suite.backend.queryClient.FeeMarket.(*mocks.FeeMarketQueryClient)
|
||||
RegisterFeeMarketParams(feeMarketClient, 1)
|
||||
RegisterParams(queryClient, &header, 1)
|
||||
RegisterBlock(client, 1, nil)
|
||||
RegisterBlockResults(client, 1)
|
||||
RegisterBaseFee(queryClient, sdk.NewInt(1))
|
||||
},
|
||||
defaultGasPrice,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"fail - can't get gasFee, FeeMarketParams error",
|
||||
func() {
|
||||
var header metadata.MD
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
feeMarketClient := suite.backend.queryClient.FeeMarket.(*mocks.FeeMarketQueryClient)
|
||||
RegisterFeeMarketParamsError(feeMarketClient, 1)
|
||||
RegisterParams(queryClient, &header, 1)
|
||||
RegisterBlock(client, 1, nil)
|
||||
RegisterBlockResults(client, 1)
|
||||
RegisterBaseFee(queryClient, sdk.NewInt(1))
|
||||
},
|
||||
defaultGasPrice,
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("case %s", tc.name), func() {
|
||||
suite.SetupTest() // reset test and queries
|
||||
tc.registerMock()
|
||||
|
||||
gasPrice, err := suite.backend.GasPrice()
|
||||
if tc.expPass {
|
||||
suite.Require().Equal(tc.expGas, gasPrice)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
@ -153,11 +153,13 @@ func (b *Backend) FeeHistory(
|
||||
}
|
||||
blockEnd = int64(blockNumber)
|
||||
}
|
||||
|
||||
userBlockCountInt := int64(userBlockCount)
|
||||
maxBlockCount := int64(b.cfg.JSONRPC.FeeHistoryCap)
|
||||
if userBlockCountInt > maxBlockCount {
|
||||
return nil, fmt.Errorf("FeeHistory user block count %d higher than %d", userBlockCountInt, maxBlockCount)
|
||||
}
|
||||
|
||||
blockStart := blockEnd - userBlockCountInt
|
||||
if blockStart < 0 {
|
||||
blockStart = 0
|
||||
@ -173,6 +175,7 @@ func (b *Backend) FeeHistory(
|
||||
for i := 0; i < int(blockCount); i++ {
|
||||
reward[i] = make([]*hexutil.Big, rewardCount)
|
||||
}
|
||||
|
||||
thisBaseFee := make([]*hexutil.Big, blockCount)
|
||||
thisGasUsedRatio := make([]float64, blockCount)
|
||||
|
||||
|
@ -4,6 +4,12 @@ import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
ethrpc "github.com/ethereum/go-ethereum/rpc"
|
||||
rpc "github.com/evmos/ethermint/rpc/types"
|
||||
"github.com/evmos/ethermint/tests"
|
||||
"google.golang.org/grpc/metadata"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/tendermint/tendermint/abci/types"
|
||||
tmrpctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||
@ -144,3 +150,297 @@ func (suite *BackendTestSuite) TestBaseFee() {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *BackendTestSuite) TestChainId() {
|
||||
expChainId := (*hexutil.Big)(big.NewInt(9000))
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func()
|
||||
expChainId *hexutil.Big
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"pass - block is at or past the EIP-155 replay-protection fork block, return chainID from config ",
|
||||
func() {
|
||||
var header metadata.MD
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
RegisterParamsInvalidHeight(queryClient, &header, int64(1))
|
||||
|
||||
},
|
||||
expChainId,
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("case %s", tc.name), func() {
|
||||
suite.SetupTest() // reset test and queries
|
||||
tc.registerMock()
|
||||
|
||||
chainId, err := suite.backend.ChainID()
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().Equal(tc.expChainId, chainId)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *BackendTestSuite) TestGetCoinbase() {
|
||||
validatorAcc := sdk.AccAddress(tests.GenerateAddress().Bytes())
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func()
|
||||
accAddr sdk.AccAddress
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"fail - Can't retrieve status from node",
|
||||
func() {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
RegisterStatusError(client)
|
||||
},
|
||||
validatorAcc,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"fail - Can't query validator account",
|
||||
func() {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
RegisterStatus(client)
|
||||
RegisterValidatorAccountError(queryClient)
|
||||
},
|
||||
validatorAcc,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"pass - Gets coinbase account",
|
||||
func() {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
RegisterStatus(client)
|
||||
RegisterValidatorAccount(queryClient, validatorAcc)
|
||||
},
|
||||
validatorAcc,
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("case %s", tc.name), func() {
|
||||
suite.SetupTest() // reset test and queries
|
||||
tc.registerMock()
|
||||
|
||||
accAddr, err := suite.backend.GetCoinbase()
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().Equal(tc.accAddr, accAddr)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *BackendTestSuite) TestSuggestGasTipCap() {
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func()
|
||||
baseFee *big.Int
|
||||
expGasTipCap *big.Int
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"pass - London hardfork not enabled or feemarket not enabled ",
|
||||
func() {},
|
||||
nil,
|
||||
big.NewInt(0),
|
||||
true,
|
||||
},
|
||||
{
|
||||
"pass - Gets the suggest gas tip cap ",
|
||||
func() {},
|
||||
nil,
|
||||
big.NewInt(0),
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("case %s", tc.name), func() {
|
||||
suite.SetupTest() // reset test and queries
|
||||
tc.registerMock()
|
||||
|
||||
maxDelta, err := suite.backend.SuggestGasTipCap(tc.baseFee)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().Equal(tc.expGasTipCap, maxDelta)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *BackendTestSuite) TestGlobalMinGasPrice() {
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func()
|
||||
expMinGasPrice sdk.Dec
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"fail - Can't get FeeMarket params",
|
||||
func() {
|
||||
feeMarketCleint := suite.backend.queryClient.FeeMarket.(*mocks.FeeMarketQueryClient)
|
||||
RegisterFeeMarketParamsError(feeMarketCleint, int64(1))
|
||||
},
|
||||
sdk.ZeroDec(),
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("case %s", tc.name), func() {
|
||||
suite.SetupTest() // reset test and queries
|
||||
tc.registerMock()
|
||||
|
||||
globalMinGasPrice, err := suite.backend.GlobalMinGasPrice()
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().Equal(tc.expMinGasPrice, globalMinGasPrice)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *BackendTestSuite) TestFeeHistory() {
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func(validator sdk.AccAddress)
|
||||
userBlockCount ethrpc.DecimalOrHex
|
||||
latestBlock ethrpc.BlockNumber
|
||||
expFeeHistory *rpc.FeeHistoryResult
|
||||
validator sdk.AccAddress
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"fail - can't get params ",
|
||||
func(validator sdk.AccAddress) {
|
||||
var header metadata.MD
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
suite.backend.cfg.JSONRPC.FeeHistoryCap = 0
|
||||
RegisterParamsError(queryClient, &header, ethrpc.BlockNumber(1).Int64())
|
||||
},
|
||||
1,
|
||||
0,
|
||||
nil,
|
||||
nil,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"fail - user block count higher than max block count ",
|
||||
func(validator sdk.AccAddress) {
|
||||
var header metadata.MD
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
suite.backend.cfg.JSONRPC.FeeHistoryCap = 0
|
||||
RegisterParams(queryClient, &header, ethrpc.BlockNumber(1).Int64())
|
||||
},
|
||||
1,
|
||||
0,
|
||||
nil,
|
||||
nil,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"fail - Tendermint block fetching error ",
|
||||
func(validator sdk.AccAddress) {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
suite.backend.cfg.JSONRPC.FeeHistoryCap = 2
|
||||
RegisterBlockError(client, ethrpc.BlockNumber(1).Int64())
|
||||
},
|
||||
1,
|
||||
1,
|
||||
nil,
|
||||
nil,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"fail - Eth block fetching error",
|
||||
func(validator sdk.AccAddress) {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
suite.backend.cfg.JSONRPC.FeeHistoryCap = 2
|
||||
RegisterBlock(client, ethrpc.BlockNumber(1).Int64(), nil)
|
||||
RegisterBlockResultsError(client, 1)
|
||||
},
|
||||
1,
|
||||
1,
|
||||
nil,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"fail - Invalid base fee",
|
||||
func(validator sdk.AccAddress) {
|
||||
//baseFee := sdk.NewInt(1)
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
suite.backend.cfg.JSONRPC.FeeHistoryCap = 2
|
||||
RegisterBlock(client, ethrpc.BlockNumber(1).Int64(), nil)
|
||||
RegisterBlockResults(client, 1)
|
||||
RegisterBaseFeeError(queryClient)
|
||||
RegisterValidatorAccount(queryClient, validator)
|
||||
RegisterConsensusParams(client, 1)
|
||||
},
|
||||
1,
|
||||
1,
|
||||
nil,
|
||||
sdk.AccAddress(tests.GenerateAddress().Bytes()),
|
||||
false,
|
||||
},
|
||||
{
|
||||
"pass - Valid FeeHistoryResults object",
|
||||
func(validator sdk.AccAddress) {
|
||||
baseFee := sdk.NewInt(1)
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
suite.backend.cfg.JSONRPC.FeeHistoryCap = 2
|
||||
RegisterBlock(client, ethrpc.BlockNumber(1).Int64(), nil)
|
||||
RegisterBlockResults(client, 1)
|
||||
RegisterBaseFee(queryClient, baseFee)
|
||||
RegisterValidatorAccount(queryClient, validator)
|
||||
RegisterConsensusParams(client, 1)
|
||||
},
|
||||
1,
|
||||
1,
|
||||
&rpc.FeeHistoryResult{
|
||||
OldestBlock: (*hexutil.Big)(big.NewInt(0)),
|
||||
BaseFee: []*hexutil.Big{(*hexutil.Big)(big.NewInt(1))},
|
||||
GasUsedRatio: []float64{0},
|
||||
Reward: [][]*hexutil.Big{{(*hexutil.Big)(big.NewInt(0)), (*hexutil.Big)(big.NewInt(0)), (*hexutil.Big)(big.NewInt(0)), (*hexutil.Big)(big.NewInt(0))}},
|
||||
},
|
||||
sdk.AccAddress(tests.GenerateAddress().Bytes()),
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("case %s", tc.name), func() {
|
||||
suite.SetupTest() // reset test and queries
|
||||
tc.registerMock(tc.validator)
|
||||
|
||||
feeHistory, err := suite.backend.FeeHistory(tc.userBlockCount, tc.latestBlock, []float64{25, 50, 75, 100})
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().Equal(feeHistory, tc.expFeeHistory)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -2,12 +2,15 @@ package backend
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/evmos/ethermint/rpc/backend/mocks"
|
||||
rpc "github.com/evmos/ethermint/rpc/types"
|
||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
@ -15,6 +18,7 @@ import (
|
||||
tmrpcclient "github.com/tendermint/tendermint/rpc/client"
|
||||
tmrpctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Client defines a mocked object that implements the Tendermint JSON-RPC Client
|
||||
@ -24,7 +28,75 @@ import (
|
||||
// To use a mock method it has to be registered in a given test.
|
||||
var _ tmrpcclient.Client = &mocks.Client{}
|
||||
|
||||
// Tx Search
|
||||
func RegisterTxSearch(client *mocks.Client, query string, txBz []byte) {
|
||||
resulTxs := []*tmrpctypes.ResultTx{{Tx: txBz}}
|
||||
client.On("TxSearch", rpc.ContextWithHeight(1), query, false, (*int)(nil), (*int)(nil), "").
|
||||
Return(&tmrpctypes.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), "").
|
||||
Return(&tmrpctypes.ResultTxSearch{}, nil)
|
||||
}
|
||||
|
||||
func RegisterTxSearchError(client *mocks.Client, query string) {
|
||||
client.On("TxSearch", rpc.ContextWithHeight(1), 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).
|
||||
Return(&tmrpctypes.ResultBroadcastTx{}, nil)
|
||||
}
|
||||
|
||||
func RegisterBroadcastTxError(client *mocks.Client, tx types.Tx) {
|
||||
client.On("BroadcastTxSync", context.Background(), tx).
|
||||
Return(nil, errortypes.ErrInvalidRequest)
|
||||
}
|
||||
|
||||
// Unconfirmed Transactions
|
||||
func RegisterUnconfirmedTxs(client *mocks.Client, limit *int, txs []types.Tx) {
|
||||
client.On("UnconfirmedTxs", rpc.ContextWithHeight(1), limit).
|
||||
Return(&tmrpctypes.ResultUnconfirmedTxs{Txs: txs}, nil)
|
||||
}
|
||||
|
||||
func RegisterUnconfirmedTxsEmpty(client *mocks.Client, limit *int) {
|
||||
client.On("UnconfirmedTxs", rpc.ContextWithHeight(1), limit).
|
||||
Return(&tmrpctypes.ResultUnconfirmedTxs{
|
||||
Txs: make([]types.Tx, 2),
|
||||
}, nil)
|
||||
}
|
||||
|
||||
func RegisterUnconfirmedTxsError(client *mocks.Client, limit *int) {
|
||||
client.On("UnconfirmedTxs", rpc.ContextWithHeight(1), limit).
|
||||
Return(nil, errortypes.ErrInvalidRequest)
|
||||
}
|
||||
|
||||
// Status
|
||||
func RegisterStatus(client *mocks.Client) {
|
||||
client.On("Status", rpc.ContextWithHeight(1)).
|
||||
Return(&tmrpctypes.ResultStatus{}, nil)
|
||||
}
|
||||
|
||||
func RegisterStatusError(client *mocks.Client) {
|
||||
client.On("Status", rpc.ContextWithHeight(1)).
|
||||
Return(nil, errortypes.ErrInvalidRequest)
|
||||
}
|
||||
|
||||
// Block
|
||||
func RegisterBlockMultipleTxs(
|
||||
client *mocks.Client,
|
||||
height int64,
|
||||
txs []types.Tx,
|
||||
) (*tmrpctypes.ResultBlock, error) {
|
||||
block := types.MakeBlock(height, txs, nil, nil)
|
||||
block.ChainID = ChainID
|
||||
resBlock := &tmrpctypes.ResultBlock{Block: block}
|
||||
client.On("Block", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).Return(resBlock, nil)
|
||||
return resBlock, nil
|
||||
}
|
||||
func RegisterBlock(
|
||||
client *mocks.Client,
|
||||
height int64,
|
||||
@ -33,24 +105,24 @@ func RegisterBlock(
|
||||
// without tx
|
||||
if tx == nil {
|
||||
emptyBlock := types.MakeBlock(height, []types.Tx{}, nil, nil)
|
||||
emptyBlock.ChainID = ChainID
|
||||
resBlock := &tmrpctypes.ResultBlock{Block: emptyBlock}
|
||||
client.On("Block", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).
|
||||
Return(resBlock, nil)
|
||||
client.On("Block", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).Return(resBlock, nil)
|
||||
return resBlock, nil
|
||||
}
|
||||
|
||||
// with tx
|
||||
block := types.MakeBlock(height, []types.Tx{tx}, nil, nil)
|
||||
block.ChainID = ChainID
|
||||
resBlock := &tmrpctypes.ResultBlock{Block: block}
|
||||
client.On("Block", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).
|
||||
Return(resBlock, nil)
|
||||
client.On("Block", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).Return(resBlock, nil)
|
||||
return resBlock, nil
|
||||
}
|
||||
|
||||
// Block returns error
|
||||
func RegisterBlockError(client *mocks.Client, height int64) {
|
||||
client.On("Block", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).
|
||||
Return(nil, sdkerrors.ErrInvalidRequest)
|
||||
Return(nil, errortypes.ErrInvalidRequest)
|
||||
}
|
||||
|
||||
// Block not found
|
||||
@ -72,6 +144,7 @@ func TestRegisterBlock(t *testing.T) {
|
||||
res, err := client.Block(rpc.ContextWithHeight(height), &height)
|
||||
|
||||
emptyBlock := types.MakeBlock(height, []types.Tx{}, nil, nil)
|
||||
emptyBlock.ChainID = ChainID
|
||||
resBlock := &tmrpctypes.ResultBlock{Block: emptyBlock}
|
||||
require.Equal(t, resBlock, res)
|
||||
require.NoError(t, err)
|
||||
@ -86,7 +159,7 @@ func RegisterConsensusParams(client *mocks.Client, height int64) {
|
||||
|
||||
func RegisterConsensusParamsError(client *mocks.Client, height int64) {
|
||||
client.On("ConsensusParams", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).
|
||||
Return(nil, sdkerrors.ErrInvalidRequest)
|
||||
Return(nil, errortypes.ErrInvalidRequest)
|
||||
}
|
||||
|
||||
func TestRegisterConsensusParams(t *testing.T) {
|
||||
@ -101,6 +174,26 @@ func TestRegisterConsensusParams(t *testing.T) {
|
||||
}
|
||||
|
||||
// BlockResults
|
||||
|
||||
func RegisterBlockResultsWithEventLog(client *mocks.Client, height int64) (*tmrpctypes.ResultBlockResults, error) {
|
||||
res := &tmrpctypes.ResultBlockResults{
|
||||
Height: height,
|
||||
TxsResults: []*abci.ResponseDeliverTx{
|
||||
{Code: 0, GasUsed: 0, Events: []abci.Event{{
|
||||
Type: evmtypes.EventTypeTxLog,
|
||||
Attributes: []abci.EventAttribute{{
|
||||
Key: []byte(evmtypes.AttributeKeyTxLog),
|
||||
Value: []byte{0x7b, 0x22, 0x74, 0x65, 0x73, 0x74, 0x22, 0x3a, 0x20, 0x22, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x22, 0x7d}, // Represents {"test": "hello"}
|
||||
Index: true,
|
||||
}},
|
||||
}}},
|
||||
},
|
||||
}
|
||||
client.On("BlockResults", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).
|
||||
Return(res, nil)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func RegisterBlockResults(
|
||||
client *mocks.Client,
|
||||
height int64,
|
||||
@ -117,7 +210,7 @@ func RegisterBlockResults(
|
||||
|
||||
func RegisterBlockResultsError(client *mocks.Client, height int64) {
|
||||
client.On("BlockResults", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).
|
||||
Return(nil, sdkerrors.ErrInvalidRequest)
|
||||
Return(nil, errortypes.ErrInvalidRequest)
|
||||
}
|
||||
|
||||
func TestRegisterBlockResults(t *testing.T) {
|
||||
@ -150,7 +243,7 @@ func RegisterBlockByHash(
|
||||
|
||||
func RegisterBlockByHashError(client *mocks.Client, hash common.Hash, tx []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}).
|
||||
Return(nil, sdkerrors.ErrInvalidRequest)
|
||||
Return(nil, errortypes.ErrInvalidRequest)
|
||||
}
|
||||
|
||||
func RegisterBlockByHashNotFound(client *mocks.Client, hash common.Hash, tx []byte) {
|
||||
@ -167,3 +260,22 @@ func RegisterABCIQueryWithOptions(client *mocks.Client, height int64, path strin
|
||||
},
|
||||
}, nil)
|
||||
}
|
||||
|
||||
func RegisterABCIQueryWithOptionsError(clients *mocks.Client, path string, data bytes.HexBytes, opts tmrpcclient.ABCIQueryOptions) {
|
||||
clients.On("ABCIQueryWithOptions", context.Background(), path, data, opts).
|
||||
Return(nil, errortypes.ErrInvalidRequest)
|
||||
}
|
||||
|
||||
func RegisterABCIQueryAccount(clients *mocks.Client, data bytes.HexBytes, opts tmrpcclient.ABCIQueryOptions, acc client.Account) {
|
||||
baseAccount := authtypes.NewBaseAccount(acc.GetAddress(), acc.GetPubKey(), acc.GetAccountNumber(), acc.GetSequence())
|
||||
accAny, _ := codectypes.NewAnyWithValue(baseAccount)
|
||||
accResponse := authtypes.QueryAccountResponse{Account: accAny}
|
||||
respBz, _ := accResponse.Marshal()
|
||||
clients.On("ABCIQueryWithOptions", context.Background(), "/cosmos.auth.v1beta1.Query/Account", data, opts).
|
||||
Return(&tmrpctypes.ResultABCIQuery{
|
||||
Response: abci.ResponseQuery{
|
||||
Value: respBz,
|
||||
Height: 1,
|
||||
},
|
||||
}, nil)
|
||||
}
|
||||
|
@ -1,12 +1,11 @@
|
||||
package backend
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
grpctypes "github.com/cosmos/cosmos-sdk/types/grpc"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/evmos/ethermint/rpc/backend/mocks"
|
||||
@ -19,6 +18,8 @@ import (
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/status"
|
||||
"strconv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// QueryClient defines a mocked object that implements the ethermint GRPC
|
||||
@ -28,6 +29,38 @@ import (
|
||||
// To use a mock method it has to be registered in a given test.
|
||||
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),
|
||||
&evmtypes.QueryTraceTxRequest{Msg: msgEthTx, BlockNumber: 1, Predecessors: predecessors, ChainId: 9000}).
|
||||
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), &evmtypes.QueryTraceTxRequest{Msg: msgEthTx, BlockNumber: 1, ChainId: 9000}).
|
||||
Return(&evmtypes.QueryTraceTxResponse{Data: data}, nil)
|
||||
}
|
||||
|
||||
func RegisterTraceTransactionError(queryClient *mocks.EVMQueryClient, msgEthTx *evmtypes.MsgEthereumTx) {
|
||||
queryClient.On("TraceTx", rpc.ContextWithHeight(1), &evmtypes.QueryTraceTxRequest{Msg: msgEthTx, BlockNumber: 1, ChainId: 9000}).
|
||||
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),
|
||||
&evmtypes.QueryTraceBlockRequest{Txs: txs, BlockNumber: 1, TraceConfig: &evmtypes.TraceConfig{}, ChainId: 9000}).
|
||||
Return(&evmtypes.QueryTraceBlockResponse{Data: data}, nil)
|
||||
}
|
||||
|
||||
func RegisterTraceBlockError(queryClient *mocks.EVMQueryClient) {
|
||||
queryClient.On("TraceBlock", rpc.ContextWithHeight(1), &evmtypes.QueryTraceBlockRequest{}).
|
||||
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)).
|
||||
@ -41,6 +74,11 @@ func RegisterParams(queryClient *mocks.EVMQueryClient, header *metadata.MD, heig
|
||||
})
|
||||
}
|
||||
|
||||
func RegisterParamsWithoutHeader(queryClient *mocks.EVMQueryClient, height int64) {
|
||||
queryClient.On("Params", rpc.ContextWithHeight(height), &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)).
|
||||
Return(&evmtypes.QueryParamsResponse{}, nil).
|
||||
@ -64,15 +102,21 @@ func RegisterParamsInvalidHeight(queryClient *mocks.EVMQueryClient, header *meta
|
||||
})
|
||||
}
|
||||
|
||||
func RegisterParamsWithoutHeaderError(queryClient *mocks.EVMQueryClient, height int64) {
|
||||
queryClient.On("Params", rpc.ContextWithHeight(height), &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)).
|
||||
Return(nil, sdkerrors.ErrInvalidRequest)
|
||||
Return(nil, errortypes.ErrInvalidRequest)
|
||||
}
|
||||
|
||||
func TestRegisterParams(t *testing.T) {
|
||||
queryClient := mocks.NewEVMQueryClient(t)
|
||||
var header metadata.MD
|
||||
queryClient := mocks.NewEVMQueryClient(t)
|
||||
|
||||
height := int64(1)
|
||||
RegisterParams(queryClient, &header, height)
|
||||
|
||||
@ -91,6 +135,26 @@ func TestRegisterParamsError(t *testing.T) {
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
// ETH Call
|
||||
func RegisterEthCall(queryClient *mocks.EVMQueryClient, request *evmtypes.EthCallRequest) {
|
||||
ctx, _ := context.WithCancel(rpc.ContextWithHeight(1))
|
||||
queryClient.On("EthCall", ctx, request).
|
||||
Return(&evmtypes.MsgEthereumTxResponse{}, nil)
|
||||
}
|
||||
|
||||
func RegisterEthCallError(queryClient *mocks.EVMQueryClient, request *evmtypes.EthCallRequest) {
|
||||
ctx, _ := context.WithCancel(rpc.ContextWithHeight(1))
|
||||
queryClient.On("EthCall", ctx, 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)
|
||||
}
|
||||
|
||||
// BaseFee
|
||||
func RegisterBaseFee(queryClient *mocks.EVMQueryClient, baseFee sdk.Int) {
|
||||
queryClient.On("BaseFee", rpc.ContextWithHeight(1), &evmtypes.QueryBaseFeeRequest{}).
|
||||
@ -137,12 +201,7 @@ func TestRegisterBaseFeeDisabled(t *testing.T) {
|
||||
// ValidatorAccount
|
||||
func RegisterValidatorAccount(queryClient *mocks.EVMQueryClient, validator sdk.AccAddress) {
|
||||
queryClient.On("ValidatorAccount", rpc.ContextWithHeight(1), &evmtypes.QueryValidatorAccountRequest{}).
|
||||
Return(
|
||||
&evmtypes.QueryValidatorAccountResponse{
|
||||
AccountAddress: validator.String(),
|
||||
},
|
||||
nil,
|
||||
)
|
||||
Return(&evmtypes.QueryValidatorAccountResponse{AccountAddress: validator.String()}, nil)
|
||||
}
|
||||
|
||||
func RegisterValidatorAccountError(queryClient *mocks.EVMQueryClient) {
|
||||
@ -168,7 +227,7 @@ func RegisterCode(queryClient *mocks.EVMQueryClient, addr common.Address, code [
|
||||
|
||||
func RegisterCodeError(queryClient *mocks.EVMQueryClient, addr common.Address) {
|
||||
queryClient.On("Code", rpc.ContextWithHeight(1), &evmtypes.QueryCodeRequest{Address: addr.String()}).
|
||||
Return(nil, sdkerrors.ErrInvalidRequest)
|
||||
Return(nil, errortypes.ErrInvalidRequest)
|
||||
}
|
||||
|
||||
// Storage
|
||||
@ -179,7 +238,7 @@ func RegisterStorageAt(queryClient *mocks.EVMQueryClient, addr common.Address, k
|
||||
|
||||
func RegisterStorageAtError(queryClient *mocks.EVMQueryClient, addr common.Address, key string) {
|
||||
queryClient.On("Storage", rpc.ContextWithHeight(1), &evmtypes.QueryStorageRequest{Address: addr.String(), Key: key}).
|
||||
Return(nil, sdkerrors.ErrInvalidRequest)
|
||||
Return(nil, errortypes.ErrInvalidRequest)
|
||||
}
|
||||
|
||||
func RegisterAccount(queryClient *mocks.EVMQueryClient, addr common.Address, height int64) {
|
||||
@ -211,5 +270,5 @@ func RegisterBalanceNegative(queryClient *mocks.EVMQueryClient, addr common.Addr
|
||||
|
||||
func RegisterBalanceError(queryClient *mocks.EVMQueryClient, addr common.Address, height int64) {
|
||||
queryClient.On("Balance", rpc.ContextWithHeight(height), &evmtypes.QueryBalanceRequest{Address: addr.String()}).
|
||||
Return(nil, sdkerrors.ErrInvalidRequest)
|
||||
Return(nil, errortypes.ErrInvalidRequest)
|
||||
}
|
||||
|
21
rpc/backend/feemarket_query_client_test.go
Normal file
21
rpc/backend/feemarket_query_client_test.go
Normal file
@ -0,0 +1,21 @@
|
||||
package backend
|
||||
|
||||
import (
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/evmos/ethermint/rpc/backend/mocks"
|
||||
rpc "github.com/evmos/ethermint/rpc/types"
|
||||
feemarkettypes "github.com/evmos/ethermint/x/feemarket/types"
|
||||
)
|
||||
|
||||
var _ feemarkettypes.QueryClient = &mocks.FeeMarketQueryClient{}
|
||||
|
||||
// Params
|
||||
func RegisterFeeMarketParams(feeMarketClient *mocks.FeeMarketQueryClient, height int64) {
|
||||
feeMarketClient.On("Params", rpc.ContextWithHeight(height), &feemarkettypes.QueryParamsRequest{}).
|
||||
Return(&feemarkettypes.QueryParamsResponse{Params: feemarkettypes.DefaultParams()}, nil)
|
||||
}
|
||||
|
||||
func RegisterFeeMarketParamsError(feeMarketClient *mocks.FeeMarketQueryClient, height int64) {
|
||||
feeMarketClient.On("Params", rpc.ContextWithHeight(height), &feemarkettypes.QueryParamsRequest{}).
|
||||
Return(nil, sdkerrors.ErrInvalidRequest)
|
||||
}
|
@ -15,7 +15,6 @@ func (b *Backend) GetLogs(hash common.Hash) ([][]*ethtypes.Log, error) {
|
||||
if resBlock == nil {
|
||||
return nil, errors.Errorf("block not found for hash %s", hash)
|
||||
}
|
||||
|
||||
return b.GetLogsByHeight(&resBlock.Block.Header.Height)
|
||||
}
|
||||
|
||||
|
117
rpc/backend/filters_test.go
Normal file
117
rpc/backend/filters_test.go
Normal file
@ -0,0 +1,117 @@
|
||||
package backend
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/evmos/ethermint/rpc/backend/mocks"
|
||||
ethrpc "github.com/evmos/ethermint/rpc/types"
|
||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
func (suite *BackendTestSuite) TestGetLogs() {
|
||||
|
||||
_, bz := suite.buildEthereumTx()
|
||||
block := tmtypes.MakeBlock(1, []tmtypes.Tx{bz}, nil, nil)
|
||||
logs := make([]*evmtypes.Log, 0, 1)
|
||||
var log evmtypes.Log
|
||||
json.Unmarshal([]byte{0x7b, 0x22, 0x74, 0x65, 0x73, 0x74, 0x22, 0x3a, 0x20, 0x22, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x22, 0x7d}, &log)
|
||||
logs = append(logs, &log)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func(hash common.Hash)
|
||||
blockHash common.Hash
|
||||
expLogs [][]*ethtypes.Log
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"fail - no block with that hash",
|
||||
func(hash common.Hash) {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
RegisterBlockByHashNotFound(client, hash, bz)
|
||||
},
|
||||
common.Hash{},
|
||||
nil,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"fail - error fetching block by hash",
|
||||
func(hash common.Hash) {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
RegisterBlockByHashError(client, hash, bz)
|
||||
},
|
||||
common.Hash{},
|
||||
nil,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"fail - error getting block results",
|
||||
func(hash common.Hash) {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
RegisterBlockByHash(client, hash, bz)
|
||||
RegisterBlockResultsError(client, 1)
|
||||
},
|
||||
common.Hash{},
|
||||
nil,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"success - getting logs with block hash",
|
||||
func(hash common.Hash) {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
RegisterBlockByHash(client, hash, bz)
|
||||
RegisterBlockResultsWithEventLog(client, ethrpc.BlockNumber(1).Int64())
|
||||
},
|
||||
common.BytesToHash(block.Hash()),
|
||||
[][]*ethtypes.Log{evmtypes.LogsToEthereum(logs)},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupTest()
|
||||
|
||||
tc.registerMock(tc.blockHash)
|
||||
logs, err := suite.backend.GetLogs(tc.blockHash)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().Equal(tc.expLogs, logs)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *BackendTestSuite) TestBloomStatus() {
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func()
|
||||
expResult uint64
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"pass - returns the BloomBitsBlocks and the number of processed sections maintained",
|
||||
func() {},
|
||||
4096,
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupTest()
|
||||
|
||||
tc.registerMock()
|
||||
bloom, _ := suite.backend.BloomStatus()
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().Equal(tc.expResult, bloom)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
123
rpc/backend/mocks/feemarket_query_client.go
Normal file
123
rpc/backend/mocks/feemarket_query_client.go
Normal file
@ -0,0 +1,123 @@
|
||||
// Code generated by mockery v2.14.1. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
grpc "google.golang.org/grpc"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
types "github.com/evmos/ethermint/x/feemarket/types"
|
||||
)
|
||||
|
||||
// FeeMarketQueryClient is an autogenerated mock type for the QueryClient type
|
||||
type FeeMarketQueryClient struct {
|
||||
mock.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))
|
||||
for _i := range opts {
|
||||
_va[_i] = opts[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx, in)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
var r0 *types.QueryBaseFeeResponse
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *types.QueryBaseFeeRequest, ...grpc.CallOption) *types.QueryBaseFeeResponse); ok {
|
||||
r0 = rf(ctx, in, opts...)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*types.QueryBaseFeeResponse)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *types.QueryBaseFeeRequest, ...grpc.CallOption) error); ok {
|
||||
r1 = rf(ctx, in, opts...)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// 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))
|
||||
for _i := range opts {
|
||||
_va[_i] = opts[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx, in)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
var r0 *types.QueryBlockGasResponse
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *types.QueryBlockGasRequest, ...grpc.CallOption) *types.QueryBlockGasResponse); ok {
|
||||
r0 = rf(ctx, in, opts...)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*types.QueryBlockGasResponse)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *types.QueryBlockGasRequest, ...grpc.CallOption) error); ok {
|
||||
r1 = rf(ctx, in, opts...)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// 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))
|
||||
for _i := range opts {
|
||||
_va[_i] = opts[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx, in)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
var r0 *types.QueryParamsResponse
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *types.QueryParamsRequest, ...grpc.CallOption) *types.QueryParamsResponse); ok {
|
||||
r0 = rf(ctx, in, opts...)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*types.QueryParamsResponse)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *types.QueryParamsRequest, ...grpc.CallOption) error); ok {
|
||||
r1 = rf(ctx, in, opts...)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
type mockConstructorTestingTNewQueryClient interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}
|
||||
|
||||
// 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 {
|
||||
mock := &FeeMarketQueryClient{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
@ -5,6 +5,7 @@ import (
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
sdkmath "cosmossdk.io/math"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
@ -12,7 +13,6 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
sdkconfig "github.com/cosmos/cosmos-sdk/server/config"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
|
||||
distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
@ -165,7 +165,7 @@ func (b *Backend) SetEtherbase(etherbase common.Address) bool {
|
||||
syncCtx := b.clientCtx.WithBroadcastMode(flags.BroadcastSync)
|
||||
rsp, err := syncCtx.BroadcastTx(txBytes)
|
||||
if rsp != nil && rsp.Code != 0 {
|
||||
err = sdkerrors.ABCIError(rsp.Codespace, rsp.Code, rsp.RawLog)
|
||||
err = errorsmod.ABCIError(rsp.Codespace, rsp.Code, rsp.RawLog)
|
||||
}
|
||||
if err != nil {
|
||||
b.logger.Debug("failed to broadcast tx", "error", err.Error())
|
||||
|
355
rpc/backend/node_info_test.go
Normal file
355
rpc/backend/node_info_test.go
Normal file
@ -0,0 +1,355 @@
|
||||
package backend
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/evmos/ethermint/crypto/ethsecp256k1"
|
||||
"github.com/evmos/ethermint/rpc/backend/mocks"
|
||||
ethermint "github.com/evmos/ethermint/types"
|
||||
"github.com/spf13/viper"
|
||||
tmrpcclient "github.com/tendermint/tendermint/rpc/client"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
func (suite *BackendTestSuite) TestRPCMinGasPrice() {
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func()
|
||||
expMinGasPrice int64
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"pass - default gas price",
|
||||
func() {
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
RegisterParamsWithoutHeaderError(queryClient, 1)
|
||||
},
|
||||
ethermint.DefaultGasPrice,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"pass - min gas price is 0",
|
||||
func() {
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
RegisterParamsWithoutHeader(queryClient, 1)
|
||||
},
|
||||
ethermint.DefaultGasPrice,
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("case %s", tc.name), func() {
|
||||
suite.SetupTest() // reset test and queries
|
||||
tc.registerMock()
|
||||
|
||||
minPrice := suite.backend.RPCMinGasPrice()
|
||||
if tc.expPass {
|
||||
suite.Require().Equal(tc.expMinGasPrice, minPrice)
|
||||
} else {
|
||||
suite.Require().NotEqual(tc.expMinGasPrice, minPrice)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *BackendTestSuite) TestSetGasPrice() {
|
||||
defaultGasPrice := (*hexutil.Big)(big.NewInt(1))
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func()
|
||||
gasPrice hexutil.Big
|
||||
expOutput bool
|
||||
}{
|
||||
{
|
||||
"pass - cannot get server config",
|
||||
func() {
|
||||
suite.backend.clientCtx.Viper = viper.New()
|
||||
},
|
||||
*defaultGasPrice,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"pass - cannot find coin denom",
|
||||
func() {
|
||||
suite.backend.clientCtx.Viper = viper.New()
|
||||
suite.backend.clientCtx.Viper.Set("telemetry.global-labels", []interface{}{})
|
||||
},
|
||||
*defaultGasPrice,
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("case %s", tc.name), func() {
|
||||
suite.SetupTest() // reset test and queries
|
||||
tc.registerMock()
|
||||
output := suite.backend.SetGasPrice(tc.gasPrice)
|
||||
suite.Require().Equal(tc.expOutput, output)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Combine these 2 into one test since the code is identical
|
||||
func (suite *BackendTestSuite) TestListAccounts() {
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func()
|
||||
expAddr []common.Address
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"pass - returns empty address",
|
||||
func() {},
|
||||
[]common.Address{},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("case %s", tc.name), func() {
|
||||
suite.SetupTest() // reset test and queries
|
||||
tc.registerMock()
|
||||
|
||||
output, err := suite.backend.ListAccounts()
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().Equal(tc.expAddr, output)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *BackendTestSuite) TestAccounts() {
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func()
|
||||
expAddr []common.Address
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"pass - returns empty address",
|
||||
func() {},
|
||||
[]common.Address{},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("case %s", tc.name), func() {
|
||||
suite.SetupTest() // reset test and queries
|
||||
tc.registerMock()
|
||||
|
||||
output, err := suite.backend.Accounts()
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().Equal(tc.expAddr, output)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *BackendTestSuite) TestSyncing() {
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func()
|
||||
expResponse interface{}
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"fail - Can't get status",
|
||||
func() {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
RegisterStatusError(client)
|
||||
},
|
||||
false,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"pass - Node not catching up",
|
||||
func() {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
RegisterStatus(client)
|
||||
},
|
||||
false,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"pass - Node is catching up",
|
||||
func() {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
RegisterStatus(client)
|
||||
status, _ := client.Status(suite.backend.ctx)
|
||||
status.SyncInfo.CatchingUp = true
|
||||
|
||||
},
|
||||
map[string]interface{}{
|
||||
"startingBlock": hexutil.Uint64(0),
|
||||
"currentBlock": hexutil.Uint64(0),
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("case %s", tc.name), func() {
|
||||
suite.SetupTest() // reset test and queries
|
||||
tc.registerMock()
|
||||
|
||||
output, err := suite.backend.Syncing()
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().Equal(tc.expResponse, output)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *BackendTestSuite) TestSetEtherbase() {
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func()
|
||||
etherbase common.Address
|
||||
expResult bool
|
||||
}{
|
||||
{
|
||||
"pass - Failed to get coinbase address",
|
||||
func() {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
RegisterStatusError(client)
|
||||
},
|
||||
common.Address{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"pass - the minimum fee is not set",
|
||||
func() {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
RegisterStatus(client)
|
||||
RegisterValidatorAccount(queryClient, suite.acc)
|
||||
},
|
||||
common.Address{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"fail - error querying for account ",
|
||||
func() {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
RegisterStatus(client)
|
||||
RegisterValidatorAccount(queryClient, suite.acc)
|
||||
c := sdk.NewDecCoin("aphoton", sdk.NewIntFromBigInt(big.NewInt(1)))
|
||||
suite.backend.cfg.SetMinGasPrices(sdk.DecCoins{c})
|
||||
delAddr, _ := suite.backend.GetCoinbase()
|
||||
//account, _ := suite.backend.clientCtx.AccountRetriever.GetAccount(suite.backend.clientCtx, delAddr)
|
||||
delCommonAddr := common.BytesToAddress(delAddr.Bytes())
|
||||
request := &authtypes.QueryAccountRequest{Address: sdk.AccAddress(delCommonAddr.Bytes()).String()}
|
||||
requestMarshal, _ := request.Marshal()
|
||||
RegisterABCIQueryWithOptionsError(
|
||||
client,
|
||||
"/cosmos.auth.v1beta1.Query/Account",
|
||||
requestMarshal,
|
||||
tmrpcclient.ABCIQueryOptions{Height: int64(1), Prove: false},
|
||||
)
|
||||
},
|
||||
common.Address{},
|
||||
false,
|
||||
},
|
||||
// TODO: Finish this test case once ABCIQuery GetAccount is fixed
|
||||
//{
|
||||
// "pass - set the etherbase for the miner",
|
||||
// func() {
|
||||
// client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
// queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
// RegisterStatus(client)
|
||||
// RegisterValidatorAccount(queryClient, suite.acc)
|
||||
// c := sdk.NewDecCoin("aphoton", sdk.NewIntFromBigInt(big.NewInt(1)))
|
||||
// suite.backend.cfg.SetMinGasPrices(sdk.DecCoins{c})
|
||||
// delAddr, _ := suite.backend.GetCoinbase()
|
||||
// account, _ := suite.backend.clientCtx.AccountRetriever.GetAccount(suite.backend.clientCtx, delAddr)
|
||||
// delCommonAddr := common.BytesToAddress(delAddr.Bytes())
|
||||
// request := &authtypes.QueryAccountRequest{Address: sdk.AccAddress(delCommonAddr.Bytes()).String()}
|
||||
// requestMarshal, _ := request.Marshal()
|
||||
// RegisterABCIQueryAccount(
|
||||
// client,
|
||||
// requestMarshal,
|
||||
// tmrpcclient.ABCIQueryOptions{Height: int64(1), Prove: false},
|
||||
// account,
|
||||
// )
|
||||
// },
|
||||
// common.Address{},
|
||||
// false,
|
||||
//},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("case %s", tc.name), func() {
|
||||
suite.SetupTest() // reset test and queries
|
||||
tc.registerMock()
|
||||
|
||||
output := suite.backend.SetEtherbase(tc.etherbase)
|
||||
|
||||
suite.Require().Equal(tc.expResult, output)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *BackendTestSuite) TestImportRawKey() {
|
||||
priv, _ := ethsecp256k1.GenerateKey()
|
||||
privHex := common.Bytes2Hex(priv.Bytes())
|
||||
pubAddr := common.BytesToAddress(priv.PubKey().Address().Bytes())
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func()
|
||||
privKey string
|
||||
password string
|
||||
expAddr common.Address
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"fail - not a valid private key",
|
||||
func() {},
|
||||
"",
|
||||
"",
|
||||
common.Address{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"pass - returning correct address",
|
||||
func() {},
|
||||
privHex,
|
||||
"",
|
||||
pubAddr,
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("case %s", tc.name), func() {
|
||||
suite.SetupTest() // reset test and queries
|
||||
tc.registerMock()
|
||||
|
||||
output, err := suite.backend.ImportRawKey(tc.privKey, tc.password)
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().Equal(tc.expAddr, output)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -1,21 +1,21 @@
|
||||
package backend
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||
"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/crypto"
|
||||
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
||||
"github.com/evmos/ethermint/ethereum/eip712"
|
||||
|
||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// SendTransaction sends transaction based on received args using Node's key to sign it
|
||||
@ -27,6 +27,10 @@ func (b *Backend) SendTransaction(args evmtypes.TransactionArgs) (common.Hash, e
|
||||
return common.Hash{}, fmt.Errorf("%s; %s", keystore.ErrNoMatch, err.Error())
|
||||
}
|
||||
|
||||
if args.ChainID != nil && (b.chainID).Cmp((*big.Int)(args.ChainID)) != 0 {
|
||||
return common.Hash{}, fmt.Errorf("chainId does not match node's (have=%v, want=%v)", args.ChainID, (*hexutil.Big)(b.chainID))
|
||||
}
|
||||
|
||||
args, err = b.SetTxDefaults(args)
|
||||
if err != nil {
|
||||
return common.Hash{}, err
|
||||
@ -89,7 +93,7 @@ func (b *Backend) SendTransaction(args evmtypes.TransactionArgs) (common.Hash, e
|
||||
syncCtx := b.clientCtx.WithBroadcastMode(flags.BroadcastSync)
|
||||
rsp, err := syncCtx.BroadcastTx(txBytes)
|
||||
if rsp != nil && rsp.Code != 0 {
|
||||
err = sdkerrors.ABCIError(rsp.Codespace, rsp.Code, rsp.RawLog)
|
||||
err = errorsmod.ABCIError(rsp.Codespace, rsp.Code, rsp.RawLog)
|
||||
}
|
||||
if err != nil {
|
||||
b.logger.Error("failed to broadcast tx", "error", err.Error())
|
||||
@ -131,7 +135,7 @@ func (b *Backend) SignTypedData(address common.Address, typedData apitypes.Typed
|
||||
return nil, fmt.Errorf("%s; %s", keystore.ErrNoMatch, err.Error())
|
||||
}
|
||||
|
||||
sigHash, err := eip712.ComputeTypedDataHash(typedData)
|
||||
sigHash, _, err := apitypes.TypedDataAndHash(typedData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
260
rpc/backend/sign_tx_test.go
Normal file
260
rpc/backend/sign_tx_test.go
Normal file
@ -0,0 +1,260 @@
|
||||
package backend
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/cosmos/cosmos-sdk/crypto"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
goethcrypto "github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
||||
"github.com/evmos/ethermint/crypto/ethsecp256k1"
|
||||
"github.com/evmos/ethermint/rpc/backend/mocks"
|
||||
"github.com/evmos/ethermint/tests"
|
||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
func (suite *BackendTestSuite) TestSendTransaction() {
|
||||
gasPrice := new(hexutil.Big)
|
||||
gas := hexutil.Uint64(1)
|
||||
zeroGas := hexutil.Uint64(0)
|
||||
toAddr := tests.GenerateAddress()
|
||||
priv, _ := ethsecp256k1.GenerateKey()
|
||||
from := common.BytesToAddress(priv.PubKey().Address().Bytes())
|
||||
nonce := hexutil.Uint64(1)
|
||||
baseFee := sdk.NewInt(1)
|
||||
callArgsDefault := evmtypes.TransactionArgs{
|
||||
From: &from,
|
||||
To: &toAddr,
|
||||
GasPrice: gasPrice,
|
||||
Gas: &gas,
|
||||
Nonce: &nonce,
|
||||
}
|
||||
|
||||
hash := common.Hash{}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func()
|
||||
args evmtypes.TransactionArgs
|
||||
expHash common.Hash
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"fail - Can't find account in Keyring",
|
||||
func() {},
|
||||
evmtypes.TransactionArgs{},
|
||||
hash,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"fail - Block error can't set Tx defaults",
|
||||
func() {
|
||||
var header metadata.MD
|
||||
queryClient := 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, "")
|
||||
RegisterParams(queryClient, &header, 1)
|
||||
RegisterBlockError(client, 1)
|
||||
},
|
||||
callArgsDefault,
|
||||
hash,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"fail - Cannot validate transaction gas set to 0",
|
||||
func() {
|
||||
var header metadata.MD
|
||||
queryClient := 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, "")
|
||||
RegisterParams(queryClient, &header, 1)
|
||||
RegisterBlock(client, 1, nil)
|
||||
RegisterBlockResults(client, 1)
|
||||
RegisterBaseFee(queryClient, baseFee)
|
||||
},
|
||||
evmtypes.TransactionArgs{
|
||||
From: &from,
|
||||
To: &toAddr,
|
||||
GasPrice: gasPrice,
|
||||
Gas: &zeroGas,
|
||||
Nonce: &nonce,
|
||||
},
|
||||
hash,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"fail - Cannot broadcast transaction",
|
||||
func() {
|
||||
var header metadata.MD
|
||||
queryClient := 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, "")
|
||||
RegisterParams(queryClient, &header, 1)
|
||||
RegisterBlock(client, 1, nil)
|
||||
RegisterBlockResults(client, 1)
|
||||
RegisterBaseFee(queryClient, baseFee)
|
||||
RegisterParamsWithoutHeader(queryClient, 1)
|
||||
ethSigner := ethtypes.LatestSigner(suite.backend.ChainConfig())
|
||||
msg := callArgsDefault.ToTransaction()
|
||||
msg.Sign(ethSigner, suite.backend.clientCtx.Keyring)
|
||||
tx, _ := msg.BuildTx(suite.backend.clientCtx.TxConfig.NewTxBuilder(), "aphoton")
|
||||
txEncoder := suite.backend.clientCtx.TxConfig.TxEncoder()
|
||||
txBytes, _ := txEncoder(tx)
|
||||
RegisterBroadcastTxError(client, txBytes)
|
||||
},
|
||||
callArgsDefault,
|
||||
common.Hash{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"pass - Return the transaction hash",
|
||||
func() {
|
||||
var header metadata.MD
|
||||
queryClient := 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, "")
|
||||
RegisterParams(queryClient, &header, 1)
|
||||
RegisterBlock(client, 1, nil)
|
||||
RegisterBlockResults(client, 1)
|
||||
RegisterBaseFee(queryClient, baseFee)
|
||||
RegisterParamsWithoutHeader(queryClient, 1)
|
||||
ethSigner := ethtypes.LatestSigner(suite.backend.ChainConfig())
|
||||
msg := callArgsDefault.ToTransaction()
|
||||
msg.Sign(ethSigner, suite.backend.clientCtx.Keyring)
|
||||
tx, _ := msg.BuildTx(suite.backend.clientCtx.TxConfig.NewTxBuilder(), "aphoton")
|
||||
txEncoder := suite.backend.clientCtx.TxConfig.TxEncoder()
|
||||
txBytes, _ := txEncoder(tx)
|
||||
RegisterBroadcastTx(client, txBytes)
|
||||
},
|
||||
callArgsDefault,
|
||||
hash,
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("case %s", tc.name), func() {
|
||||
suite.SetupTest() // reset test and queries
|
||||
tc.registerMock()
|
||||
|
||||
if tc.expPass {
|
||||
// Sign the transaction and get the hash
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
RegisterParamsWithoutHeader(queryClient, 1)
|
||||
ethSigner := ethtypes.LatestSigner(suite.backend.ChainConfig())
|
||||
msg := callArgsDefault.ToTransaction()
|
||||
msg.Sign(ethSigner, suite.backend.clientCtx.Keyring)
|
||||
tc.expHash = msg.AsTransaction().Hash()
|
||||
}
|
||||
responseHash, err := suite.backend.SendTransaction(tc.args)
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().Equal(tc.expHash, responseHash)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *BackendTestSuite) TestSign() {
|
||||
from, priv := tests.NewAddrKey()
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func()
|
||||
fromAddr common.Address
|
||||
inputBz hexutil.Bytes
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"fail - can't find key in Keyring",
|
||||
func() {},
|
||||
from,
|
||||
nil,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"pass - sign nil data",
|
||||
func() {
|
||||
armor := crypto.EncryptArmorPrivKey(priv, "", "eth_secp256k1")
|
||||
suite.backend.clientCtx.Keyring.ImportPrivKey("test_key", armor, "")
|
||||
},
|
||||
from,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("case %s", tc.name), func() {
|
||||
suite.SetupTest() // reset test and queries
|
||||
tc.registerMock()
|
||||
|
||||
responseBz, err := suite.backend.Sign(tc.fromAddr, tc.inputBz)
|
||||
if tc.expPass {
|
||||
signature, _, err := suite.backend.clientCtx.Keyring.SignByAddress((sdk.AccAddress)(from.Bytes()), tc.inputBz)
|
||||
signature[goethcrypto.RecoveryIDOffset] += 27
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().Equal((hexutil.Bytes)(signature), responseBz)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *BackendTestSuite) TestSignTypedData() {
|
||||
from, priv := tests.NewAddrKey()
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func()
|
||||
fromAddr common.Address
|
||||
inputTypedData apitypes.TypedData
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"fail - can't find key in Keyring",
|
||||
func() {},
|
||||
from,
|
||||
apitypes.TypedData{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"fail - empty TypeData",
|
||||
func() {
|
||||
armor := crypto.EncryptArmorPrivKey(priv, "", "eth_secp256k1")
|
||||
suite.backend.clientCtx.Keyring.ImportPrivKey("test_key", armor, "")
|
||||
},
|
||||
from,
|
||||
apitypes.TypedData{},
|
||||
false,
|
||||
},
|
||||
// TODO: Generate a TypedData msg
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("case %s", tc.name), func() {
|
||||
suite.SetupTest() // reset test and queries
|
||||
tc.registerMock()
|
||||
|
||||
responseBz, err := suite.backend.SignTypedData(tc.fromAddr, tc.inputTypedData)
|
||||
|
||||
if tc.expPass {
|
||||
sigHash, _, err := apitypes.TypedDataAndHash(tc.inputTypedData)
|
||||
signature, _, err := suite.backend.clientCtx.Keyring.SignByAddress((sdk.AccAddress)(from.Bytes()), sigHash)
|
||||
signature[goethcrypto.RecoveryIDOffset] += 27
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().Equal((hexutil.Bytes)(signature), responseBz)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -84,6 +84,7 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi
|
||||
BlockTime: blk.Block.Time,
|
||||
BlockHash: common.Bytes2Hex(blk.BlockID.Hash),
|
||||
ProposerAddress: sdk.ConsAddress(blk.Block.ProposerAddress),
|
||||
ChainId: b.chainID.Int64(),
|
||||
}
|
||||
|
||||
if config != nil {
|
||||
@ -112,7 +113,7 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi
|
||||
return decodedResult, nil
|
||||
}
|
||||
|
||||
// traceBlock configures a new tracer according to the provided configuration, and
|
||||
// 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,
|
||||
@ -162,6 +163,7 @@ func (b *Backend) TraceBlock(height rpctypes.BlockNumber,
|
||||
BlockTime: block.Block.Time,
|
||||
BlockHash: common.Bytes2Hex(block.BlockID.Hash),
|
||||
ProposerAddress: sdk.ConsAddress(block.Block.ProposerAddress),
|
||||
ChainId: b.chainID.Int64(),
|
||||
}
|
||||
|
||||
res, err := b.queryClient.TraceBlock(ctxWithHeight, traceBlockRequest)
|
||||
|
250
rpc/backend/tracing_test.go
Normal file
250
rpc/backend/tracing_test.go
Normal file
@ -0,0 +1,250 @@
|
||||
package backend
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/cosmos/cosmos-sdk/crypto"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/evmos/ethermint/crypto/ethsecp256k1"
|
||||
"github.com/evmos/ethermint/indexer"
|
||||
"github.com/evmos/ethermint/rpc/backend/mocks"
|
||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
tmlog "github.com/tendermint/tendermint/libs/log"
|
||||
tmrpctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
dbm "github.com/tendermint/tm-db"
|
||||
)
|
||||
|
||||
func (suite *BackendTestSuite) TestTraceTransaction() {
|
||||
msgEthereumTx, _ := suite.buildEthereumTx()
|
||||
msgEthereumTx2, _ := suite.buildEthereumTx()
|
||||
|
||||
txHash := msgEthereumTx.AsTransaction().Hash()
|
||||
txHash2 := msgEthereumTx2.AsTransaction().Hash()
|
||||
|
||||
priv, _ := ethsecp256k1.GenerateKey()
|
||||
from := common.BytesToAddress(priv.PubKey().Address().Bytes())
|
||||
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
RegisterParamsWithoutHeader(queryClient, 1)
|
||||
|
||||
armor := crypto.EncryptArmorPrivKey(priv, "", "eth_secp256k1")
|
||||
suite.backend.clientCtx.Keyring.ImportPrivKey("test_key", armor, "")
|
||||
ethSigner := ethtypes.LatestSigner(suite.backend.ChainConfig())
|
||||
|
||||
txEncoder := suite.backend.clientCtx.TxConfig.TxEncoder()
|
||||
|
||||
msgEthereumTx.From = from.String()
|
||||
msgEthereumTx.Sign(ethSigner, suite.signer)
|
||||
tx, _ := msgEthereumTx.BuildTx(suite.backend.clientCtx.TxConfig.NewTxBuilder(), "aphoton")
|
||||
txBz, _ := txEncoder(tx)
|
||||
|
||||
msgEthereumTx2.From = from.String()
|
||||
msgEthereumTx2.Sign(ethSigner, suite.signer)
|
||||
tx2, _ := msgEthereumTx.BuildTx(suite.backend.clientCtx.TxConfig.NewTxBuilder(), "aphoton")
|
||||
txBz2, _ := txEncoder(tx2)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func()
|
||||
block *types.Block
|
||||
responseBlock []*abci.ResponseDeliverTx
|
||||
expResult interface{}
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"fail - tx not found",
|
||||
func() {},
|
||||
&types.Block{Header: types.Header{Height: 1}, Data: types.Data{Txs: []types.Tx{}}},
|
||||
[]*abci.ResponseDeliverTx{
|
||||
{
|
||||
Code: 0,
|
||||
Events: []abci.Event{
|
||||
{Type: evmtypes.EventTypeEthereumTx, Attributes: []abci.EventAttribute{
|
||||
{Key: []byte("ethereumTxHash"), Value: []byte(txHash.Hex())},
|
||||
{Key: []byte("txIndex"), Value: []byte("0")},
|
||||
{Key: []byte("amount"), Value: []byte("1000")},
|
||||
{Key: []byte("txGasUsed"), Value: []byte("21000")},
|
||||
{Key: []byte("txHash"), Value: []byte("")},
|
||||
{Key: []byte("recipient"), Value: []byte("0x775b87ef5D82ca211811C1a02CE0fE0CA3a455d7")},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
nil,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"fail - block not found",
|
||||
func() {
|
||||
//var header metadata.MD
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
RegisterBlockError(client, 1)
|
||||
},
|
||||
&types.Block{Header: types.Header{Height: 1}, Data: types.Data{Txs: []types.Tx{txBz}}},
|
||||
[]*abci.ResponseDeliverTx{
|
||||
{
|
||||
Code: 0,
|
||||
Events: []abci.Event{
|
||||
{Type: evmtypes.EventTypeEthereumTx, Attributes: []abci.EventAttribute{
|
||||
{Key: []byte("ethereumTxHash"), Value: []byte(txHash.Hex())},
|
||||
{Key: []byte("txIndex"), Value: []byte("0")},
|
||||
{Key: []byte("amount"), Value: []byte("1000")},
|
||||
{Key: []byte("txGasUsed"), Value: []byte("21000")},
|
||||
{Key: []byte("txHash"), Value: []byte("")},
|
||||
{Key: []byte("recipient"), Value: []byte("0x775b87ef5D82ca211811C1a02CE0fE0CA3a455d7")},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
map[string]interface{}{"test": "hello"},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"pass - transaction found in a block with multiple transactions",
|
||||
func() {
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
RegisterBlockMultipleTxs(client, 1, []types.Tx{txBz, txBz2})
|
||||
RegisterTraceTransactionWithPredecessors(queryClient, msgEthereumTx, []*evmtypes.MsgEthereumTx{msgEthereumTx})
|
||||
},
|
||||
&types.Block{Header: types.Header{Height: 1, ChainID: ChainID}, Data: types.Data{Txs: []types.Tx{txBz, txBz2}}},
|
||||
[]*abci.ResponseDeliverTx{
|
||||
{
|
||||
Code: 0,
|
||||
Events: []abci.Event{
|
||||
{Type: evmtypes.EventTypeEthereumTx, Attributes: []abci.EventAttribute{
|
||||
{Key: []byte("ethereumTxHash"), Value: []byte(txHash.Hex())},
|
||||
{Key: []byte("txIndex"), Value: []byte("0")},
|
||||
{Key: []byte("amount"), Value: []byte("1000")},
|
||||
{Key: []byte("txGasUsed"), Value: []byte("21000")},
|
||||
{Key: []byte("txHash"), Value: []byte("")},
|
||||
{Key: []byte("recipient"), Value: []byte("0x775b87ef5D82ca211811C1a02CE0fE0CA3a455d7")},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
Code: 0,
|
||||
Events: []abci.Event{
|
||||
{Type: evmtypes.EventTypeEthereumTx, Attributes: []abci.EventAttribute{
|
||||
{Key: []byte("ethereumTxHash"), Value: []byte(txHash2.Hex())},
|
||||
{Key: []byte("txIndex"), Value: []byte("1")},
|
||||
{Key: []byte("amount"), Value: []byte("1000")},
|
||||
{Key: []byte("txGasUsed"), Value: []byte("21000")},
|
||||
{Key: []byte("txHash"), Value: []byte("")},
|
||||
{Key: []byte("recipient"), Value: []byte("0x775b87ef5D82ca211811C1a02CE0fE0CA3a455d7")},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
map[string]interface{}{"test": "hello"},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"pass - transaction found",
|
||||
func() {
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
RegisterBlock(client, 1, txBz)
|
||||
RegisterTraceTransaction(queryClient, msgEthereumTx)
|
||||
},
|
||||
&types.Block{Header: types.Header{Height: 1}, Data: types.Data{Txs: []types.Tx{txBz}}},
|
||||
[]*abci.ResponseDeliverTx{
|
||||
{
|
||||
Code: 0,
|
||||
Events: []abci.Event{
|
||||
{Type: evmtypes.EventTypeEthereumTx, Attributes: []abci.EventAttribute{
|
||||
{Key: []byte("ethereumTxHash"), Value: []byte(txHash.Hex())},
|
||||
{Key: []byte("txIndex"), Value: []byte("0")},
|
||||
{Key: []byte("amount"), Value: []byte("1000")},
|
||||
{Key: []byte("txGasUsed"), Value: []byte("21000")},
|
||||
{Key: []byte("txHash"), Value: []byte("")},
|
||||
{Key: []byte("recipient"), Value: []byte("0x775b87ef5D82ca211811C1a02CE0fE0CA3a455d7")},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
map[string]interface{}{"test": "hello"},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("case %s", tc.name), func() {
|
||||
suite.SetupTest() // reset test and queries
|
||||
tc.registerMock()
|
||||
|
||||
db := dbm.NewMemDB()
|
||||
suite.backend.indexer = indexer.NewKVIndexer(db, tmlog.NewNopLogger(), suite.backend.clientCtx)
|
||||
|
||||
err := suite.backend.indexer.IndexBlock(tc.block, tc.responseBlock)
|
||||
suite.Require().NoError(err)
|
||||
txResult, err := suite.backend.TraceTransaction(txHash, nil)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().Equal(tc.expResult, txResult)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *BackendTestSuite) TestTraceBlock() {
|
||||
msgEthTx, bz := suite.buildEthereumTx()
|
||||
emptyBlock := tmtypes.MakeBlock(1, []tmtypes.Tx{}, nil, nil)
|
||||
emptyBlock.ChainID = ChainID
|
||||
filledBlock := tmtypes.MakeBlock(1, []tmtypes.Tx{bz}, nil, nil)
|
||||
filledBlock.ChainID = ChainID
|
||||
resBlockEmpty := tmrpctypes.ResultBlock{Block: emptyBlock, BlockID: emptyBlock.LastBlockID}
|
||||
resBlockFilled := tmrpctypes.ResultBlock{Block: filledBlock, BlockID: filledBlock.LastBlockID}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func()
|
||||
expTraceResults []*evmtypes.TxTraceResult
|
||||
resBlock *tmrpctypes.ResultBlock
|
||||
config *evmtypes.TraceConfig
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"pass - no transaction returning empty array",
|
||||
func() {},
|
||||
[]*evmtypes.TxTraceResult{},
|
||||
&resBlockEmpty,
|
||||
&evmtypes.TraceConfig{},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"fail - cannot unmarshal data",
|
||||
func() {
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
RegisterTraceBlock(queryClient, []*evmtypes.MsgEthereumTx{msgEthTx})
|
||||
|
||||
},
|
||||
[]*evmtypes.TxTraceResult{},
|
||||
&resBlockFilled,
|
||||
&evmtypes.TraceConfig{},
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("case %s", tc.name), func() {
|
||||
suite.SetupTest() // reset test and queries
|
||||
tc.registerMock()
|
||||
|
||||
traceResults, err := suite.backend.TraceBlock(1, tc.config, tc.resBlock)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().Equal(tc.expTraceResults, traceResults)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -3,8 +3,8 @@ package backend
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
@ -74,6 +74,7 @@ func (b *Backend) GetTransactionByHash(txHash common.Hash) (*rpctypes.RPCTransac
|
||||
uint64(res.Height),
|
||||
uint64(res.EthTxIndex),
|
||||
baseFee,
|
||||
b.chainID,
|
||||
)
|
||||
}
|
||||
|
||||
@ -102,6 +103,7 @@ func (b *Backend) getTransactionByHashPending(txHash common.Hash) (*rpctypes.RPC
|
||||
uint64(0),
|
||||
uint64(0),
|
||||
nil,
|
||||
b.chainID,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -214,6 +216,7 @@ func (b *Backend) GetTransactionReceipt(hash common.Hash) (map[string]interface{
|
||||
// sender and receiver (contract or EOA) addreses
|
||||
"from": from,
|
||||
"to": txData.GetTo(),
|
||||
"type": hexutil.Uint(ethMsg.AsTransaction().Type()),
|
||||
}
|
||||
|
||||
if logs == nil {
|
||||
@ -288,7 +291,7 @@ func (b *Backend) GetTxByEthHash(hash common.Hash) (*ethermint.TxResult, error)
|
||||
return txs.GetTxByHash(hash)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrapf(err, "GetTxByEthHash %s", hash.Hex())
|
||||
return nil, errorsmod.Wrapf(err, "GetTxByEthHash %s", hash.Hex())
|
||||
}
|
||||
return txResult, nil
|
||||
}
|
||||
@ -308,7 +311,7 @@ func (b *Backend) GetTxByTxIndex(height int64, index uint) (*ethermint.TxResult,
|
||||
return txs.GetTxByTxIndex(int(index))
|
||||
})
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrapf(err, "GetTxByTxIndex %d %d", height, index)
|
||||
return nil, errorsmod.Wrapf(err, "GetTxByTxIndex %d %d", height, index)
|
||||
}
|
||||
return txResult, nil
|
||||
}
|
||||
@ -339,7 +342,7 @@ func (b *Backend) queryTendermintTxIndexer(query string, txGetter func(*rpctypes
|
||||
return rpctypes.ParseTxIndexerResult(txResult, tx, txGetter)
|
||||
}
|
||||
|
||||
// getTransactionByBlockAndIndex is the common code shared by `GetTransactionByBlockNumberAndIndex` and `GetTransactionByBlockHashAndIndex`.
|
||||
// GetTransactionByBlockAndIndex is the common code shared by `GetTransactionByBlockNumberAndIndex` and `GetTransactionByBlockHashAndIndex`.
|
||||
func (b *Backend) GetTransactionByBlockAndIndex(block *tmrpctypes.ResultBlock, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) {
|
||||
blockRes, err := b.TendermintBlockResultByNumber(&block.Block.Height)
|
||||
if err != nil {
|
||||
@ -386,5 +389,6 @@ func (b *Backend) GetTransactionByBlockAndIndex(block *tmrpctypes.ResultBlock, i
|
||||
uint64(block.Block.Height),
|
||||
uint64(idx),
|
||||
baseFee,
|
||||
b.chainID,
|
||||
)
|
||||
}
|
||||
|
600
rpc/backend/tx_info_test.go
Normal file
600
rpc/backend/tx_info_test.go
Normal file
@ -0,0 +1,600 @@
|
||||
package backend
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/evmos/ethermint/indexer"
|
||||
"github.com/evmos/ethermint/rpc/backend/mocks"
|
||||
rpctypes "github.com/evmos/ethermint/rpc/types"
|
||||
ethermint "github.com/evmos/ethermint/types"
|
||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
tmlog "github.com/tendermint/tendermint/libs/log"
|
||||
tmrpctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
dbm "github.com/tendermint/tm-db"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
func (suite *BackendTestSuite) TestGetTransactionByHash() {
|
||||
msgEthereumTx, _ := suite.buildEthereumTx()
|
||||
txHash := msgEthereumTx.AsTransaction().Hash()
|
||||
|
||||
txBz := suite.signAndEncodeEthTx(msgEthereumTx)
|
||||
block := &types.Block{Header: types.Header{Height: 1, ChainID: "test"}, Data: types.Data{Txs: []types.Tx{txBz}}}
|
||||
responseDeliver := []*abci.ResponseDeliverTx{
|
||||
{
|
||||
Code: 0,
|
||||
Events: []abci.Event{
|
||||
{Type: evmtypes.EventTypeEthereumTx, Attributes: []abci.EventAttribute{
|
||||
{Key: []byte("ethereumTxHash"), Value: []byte(txHash.Hex())},
|
||||
{Key: []byte("txIndex"), Value: []byte("0")},
|
||||
{Key: []byte("amount"), Value: []byte("1000")},
|
||||
{Key: []byte("txGasUsed"), Value: []byte("21000")},
|
||||
{Key: []byte("txHash"), Value: []byte("")},
|
||||
{Key: []byte("recipient"), Value: []byte("")},
|
||||
}},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
rpcTransaction, _ := rpctypes.NewRPCTransaction(msgEthereumTx.AsTransaction(), common.Hash{}, 0, 0, big.NewInt(1), suite.backend.chainID)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func()
|
||||
tx *evmtypes.MsgEthereumTx
|
||||
expRPCTx *rpctypes.RPCTransaction
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"fail - Block error",
|
||||
func() {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
RegisterBlockError(client, 1)
|
||||
},
|
||||
msgEthereumTx,
|
||||
rpcTransaction,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"fail - Block Result error",
|
||||
func() {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
RegisterBlock(client, 1, txBz)
|
||||
RegisterBlockResultsError(client, 1)
|
||||
},
|
||||
msgEthereumTx,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"pass - Base fee error",
|
||||
func() {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
RegisterBlock(client, 1, txBz)
|
||||
RegisterBlockResults(client, 1)
|
||||
RegisterBaseFeeError(queryClient)
|
||||
},
|
||||
msgEthereumTx,
|
||||
rpcTransaction,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"pass - Transaction found and returned",
|
||||
func() {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
RegisterBlock(client, 1, txBz)
|
||||
RegisterBlockResults(client, 1)
|
||||
RegisterBaseFee(queryClient, sdk.NewInt(1))
|
||||
},
|
||||
msgEthereumTx,
|
||||
rpcTransaction,
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupTest() // reset
|
||||
tc.registerMock()
|
||||
|
||||
db := dbm.NewMemDB()
|
||||
suite.backend.indexer = indexer.NewKVIndexer(db, tmlog.NewNopLogger(), suite.backend.clientCtx)
|
||||
err := suite.backend.indexer.IndexBlock(block, responseDeliver)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
rpcTx, err := suite.backend.GetTransactionByHash(common.HexToHash(tc.tx.Hash))
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().Equal(rpcTx, tc.expRPCTx)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *BackendTestSuite) TestGetTransactionsByHashPending() {
|
||||
msgEthereumTx, bz := suite.buildEthereumTx()
|
||||
rpcTransaction, _ := rpctypes.NewRPCTransaction(msgEthereumTx.AsTransaction(), common.Hash{}, 0, 0, big.NewInt(1), suite.backend.chainID)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func()
|
||||
tx *evmtypes.MsgEthereumTx
|
||||
expRPCTx *rpctypes.RPCTransaction
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"fail - Pending transactions returns error",
|
||||
func() {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
RegisterUnconfirmedTxsError(client, nil)
|
||||
},
|
||||
msgEthereumTx,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"fail - Tx not found return nil",
|
||||
func() {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
RegisterUnconfirmedTxs(client, nil, nil)
|
||||
},
|
||||
msgEthereumTx,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"pass - Tx found and returned",
|
||||
func() {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
RegisterUnconfirmedTxs(client, nil, types.Txs{bz})
|
||||
},
|
||||
msgEthereumTx,
|
||||
rpcTransaction,
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupTest() // reset
|
||||
tc.registerMock()
|
||||
|
||||
rpcTx, err := suite.backend.getTransactionByHashPending(common.HexToHash(tc.tx.Hash))
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().Equal(rpcTx, tc.expRPCTx)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *BackendTestSuite) TestGetTxByEthHash() {
|
||||
msgEthereumTx, bz := suite.buildEthereumTx()
|
||||
rpcTransaction, _ := rpctypes.NewRPCTransaction(msgEthereumTx.AsTransaction(), common.Hash{}, 0, 0, big.NewInt(1), suite.backend.chainID)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func()
|
||||
tx *evmtypes.MsgEthereumTx
|
||||
expRPCTx *rpctypes.RPCTransaction
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"fail - Indexer disabled can't find transaction",
|
||||
func() {
|
||||
suite.backend.indexer = nil
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
query := fmt.Sprintf("%s.%s='%s'", evmtypes.TypeMsgEthereumTx, evmtypes.AttributeKeyEthereumTxHash, common.HexToHash(msgEthereumTx.Hash).Hex())
|
||||
RegisterTxSearch(client, query, bz)
|
||||
},
|
||||
msgEthereumTx,
|
||||
rpcTransaction,
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupTest() // reset
|
||||
tc.registerMock()
|
||||
|
||||
rpcTx, err := suite.backend.GetTxByEthHash(common.HexToHash(tc.tx.Hash))
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().Equal(rpcTx, tc.expRPCTx)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *BackendTestSuite) TestGetTransactionByBlockHashAndIndex() {
|
||||
_, bz := suite.buildEthereumTx()
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func()
|
||||
blockHash common.Hash
|
||||
expRPCTx *rpctypes.RPCTransaction
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"pass - block not found",
|
||||
func() {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
RegisterBlockByHashError(client, common.Hash{}, bz)
|
||||
},
|
||||
common.Hash{},
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"pass - Block results error",
|
||||
func() {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
RegisterBlockByHash(client, common.Hash{}, bz)
|
||||
RegisterBlockResultsError(client, 1)
|
||||
},
|
||||
common.Hash{},
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupTest() // reset
|
||||
tc.registerMock()
|
||||
|
||||
rpcTx, err := suite.backend.GetTransactionByBlockHashAndIndex(tc.blockHash, 1)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().Equal(rpcTx, tc.expRPCTx)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *BackendTestSuite) TestGetTransactionByBlockAndIndex() {
|
||||
msgEthTx, bz := suite.buildEthereumTx()
|
||||
|
||||
defaultBlock := types.MakeBlock(1, []types.Tx{bz}, nil, nil)
|
||||
defaultResponseDeliverTx := []*abci.ResponseDeliverTx{
|
||||
{
|
||||
Code: 0,
|
||||
Events: []abci.Event{
|
||||
{Type: evmtypes.EventTypeEthereumTx, Attributes: []abci.EventAttribute{
|
||||
{Key: []byte("ethereumTxHash"), Value: []byte(common.HexToHash(msgEthTx.Hash).Hex())},
|
||||
{Key: []byte("txIndex"), Value: []byte("0")},
|
||||
{Key: []byte("amount"), Value: []byte("1000")},
|
||||
{Key: []byte("txGasUsed"), Value: []byte("21000")},
|
||||
{Key: []byte("txHash"), Value: []byte("")},
|
||||
{Key: []byte("recipient"), Value: []byte("")},
|
||||
}},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
txFromMsg, _ := rpctypes.NewTransactionFromMsg(
|
||||
msgEthTx,
|
||||
common.BytesToHash(defaultBlock.Hash().Bytes()),
|
||||
1,
|
||||
0,
|
||||
big.NewInt(1),
|
||||
suite.backend.chainID,
|
||||
)
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func()
|
||||
block *tmrpctypes.ResultBlock
|
||||
idx hexutil.Uint
|
||||
expRPCTx *rpctypes.RPCTransaction
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"pass - block txs index out of bound ",
|
||||
func() {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
RegisterBlockResults(client, 1)
|
||||
},
|
||||
&tmrpctypes.ResultBlock{Block: types.MakeBlock(1, []types.Tx{bz}, nil, nil)},
|
||||
1,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"pass - Can't fetch base fee",
|
||||
func() {
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
RegisterBlockResults(client, 1)
|
||||
RegisterBaseFeeError(queryClient)
|
||||
},
|
||||
&tmrpctypes.ResultBlock{Block: defaultBlock},
|
||||
0,
|
||||
txFromMsg,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"pass - Gets Tx by transaction index",
|
||||
func() {
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
db := dbm.NewMemDB()
|
||||
suite.backend.indexer = indexer.NewKVIndexer(db, tmlog.NewNopLogger(), suite.backend.clientCtx)
|
||||
txBz := suite.signAndEncodeEthTx(msgEthTx)
|
||||
block := &types.Block{Header: types.Header{Height: 1, ChainID: "test"}, Data: types.Data{Txs: []types.Tx{txBz}}}
|
||||
err := suite.backend.indexer.IndexBlock(block, defaultResponseDeliverTx)
|
||||
suite.Require().NoError(err)
|
||||
RegisterBlockResults(client, 1)
|
||||
RegisterBaseFee(queryClient, sdk.NewInt(1))
|
||||
},
|
||||
&tmrpctypes.ResultBlock{Block: defaultBlock},
|
||||
0,
|
||||
txFromMsg,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"pass - returns the Ethereum format transaction by the Ethereum hash",
|
||||
func() {
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
RegisterBlockResults(client, 1)
|
||||
RegisterBaseFee(queryClient, sdk.NewInt(1))
|
||||
},
|
||||
&tmrpctypes.ResultBlock{Block: defaultBlock},
|
||||
0,
|
||||
txFromMsg,
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupTest() // reset
|
||||
tc.registerMock()
|
||||
|
||||
rpcTx, err := suite.backend.GetTransactionByBlockAndIndex(tc.block, tc.idx)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().Equal(rpcTx, tc.expRPCTx)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *BackendTestSuite) TestGetTransactionByBlockNumberAndIndex() {
|
||||
msgEthTx, bz := suite.buildEthereumTx()
|
||||
defaultBlock := types.MakeBlock(1, []types.Tx{bz}, nil, nil)
|
||||
txFromMsg, _ := rpctypes.NewTransactionFromMsg(
|
||||
msgEthTx,
|
||||
common.BytesToHash(defaultBlock.Hash().Bytes()),
|
||||
1,
|
||||
0,
|
||||
big.NewInt(1),
|
||||
suite.backend.chainID,
|
||||
)
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func()
|
||||
blockNum rpctypes.BlockNumber
|
||||
idx hexutil.Uint
|
||||
expRPCTx *rpctypes.RPCTransaction
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"fail - block not found return nil",
|
||||
func() {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
RegisterBlockError(client, 1)
|
||||
},
|
||||
0,
|
||||
0,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"pass - returns the transaction identified by block number and index",
|
||||
func() {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
RegisterBlock(client, 1, bz)
|
||||
RegisterBlockResults(client, 1)
|
||||
RegisterBaseFee(queryClient, sdk.NewInt(1))
|
||||
},
|
||||
0,
|
||||
0,
|
||||
txFromMsg,
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupTest() // reset
|
||||
tc.registerMock()
|
||||
|
||||
rpcTx, err := suite.backend.GetTransactionByBlockNumberAndIndex(tc.blockNum, tc.idx)
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().Equal(rpcTx, tc.expRPCTx)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *BackendTestSuite) TestGetTransactionByTxIndex() {
|
||||
_, bz := suite.buildEthereumTx()
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func()
|
||||
height int64
|
||||
index uint
|
||||
expTxResult *ethermint.TxResult
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"fail - Ethereum tx with query not found",
|
||||
func() {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
suite.backend.indexer = nil
|
||||
RegisterTxSearch(client, "tx.height=0 AND ethereum_tx.txIndex=0", bz)
|
||||
},
|
||||
0,
|
||||
0,
|
||||
ðermint.TxResult{},
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupTest() // reset
|
||||
tc.registerMock()
|
||||
|
||||
txResults, err := suite.backend.GetTxByTxIndex(tc.height, tc.index)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().Equal(txResults, tc.expTxResult)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *BackendTestSuite) TestQueryTendermintTxIndexer() {
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func()
|
||||
txGetter func(*rpctypes.ParsedTxs) *rpctypes.ParsedTx
|
||||
query string
|
||||
expTxResult *ethermint.TxResult
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"fail - Ethereum tx with query not found",
|
||||
func() {
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
RegisterTxSearchEmpty(client, "")
|
||||
},
|
||||
func(txs *rpctypes.ParsedTxs) *rpctypes.ParsedTx {
|
||||
return &rpctypes.ParsedTx{}
|
||||
},
|
||||
"",
|
||||
ðermint.TxResult{},
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupTest() // reset
|
||||
tc.registerMock()
|
||||
|
||||
txResults, err := suite.backend.queryTendermintTxIndexer(tc.query, tc.txGetter)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().Equal(txResults, tc.expTxResult)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *BackendTestSuite) TestGetTransactionReceipt() {
|
||||
msgEthereumTx, _ := suite.buildEthereumTx()
|
||||
txHash := msgEthereumTx.AsTransaction().Hash()
|
||||
|
||||
txBz := suite.signAndEncodeEthTx(msgEthereumTx)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
registerMock func()
|
||||
tx *evmtypes.MsgEthereumTx
|
||||
block *types.Block
|
||||
blockResult []*abci.ResponseDeliverTx
|
||||
expTxReceipt map[string]interface{}
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"fail - Receipts do not match ",
|
||||
func() {
|
||||
var header metadata.MD
|
||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||
RegisterParams(queryClient, &header, 1)
|
||||
RegisterParamsWithoutHeader(queryClient, 1)
|
||||
RegisterBlock(client, 1, txBz)
|
||||
RegisterBlockResults(client, 1)
|
||||
|
||||
},
|
||||
msgEthereumTx,
|
||||
&types.Block{Header: types.Header{Height: 1}, Data: types.Data{Txs: []types.Tx{txBz}}},
|
||||
[]*abci.ResponseDeliverTx{
|
||||
{
|
||||
Code: 0,
|
||||
Events: []abci.Event{
|
||||
{Type: evmtypes.EventTypeEthereumTx, Attributes: []abci.EventAttribute{
|
||||
{Key: []byte("ethereumTxHash"), Value: []byte(txHash.Hex())},
|
||||
{Key: []byte("txIndex"), Value: []byte("0")},
|
||||
{Key: []byte("amount"), Value: []byte("1000")},
|
||||
{Key: []byte("txGasUsed"), Value: []byte("21000")},
|
||||
{Key: []byte("txHash"), Value: []byte("")},
|
||||
{Key: []byte("recipient"), Value: []byte("0x775b87ef5D82ca211811C1a02CE0fE0CA3a455d7")},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
map[string]interface{}(nil),
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupTest() // reset
|
||||
tc.registerMock()
|
||||
|
||||
db := dbm.NewMemDB()
|
||||
suite.backend.indexer = indexer.NewKVIndexer(db, tmlog.NewNopLogger(), suite.backend.clientCtx)
|
||||
err := suite.backend.indexer.IndexBlock(tc.block, tc.blockResult)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
txReceipt, err := suite.backend.GetTransactionReceipt(common.HexToHash(tc.tx.Hash))
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().Equal(txReceipt, tc.expTxReceipt)
|
||||
} else {
|
||||
suite.Require().NotEqual(txReceipt, tc.expTxReceipt)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -10,6 +10,8 @@ import (
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
@ -21,6 +23,7 @@ import (
|
||||
|
||||
"github.com/evmos/ethermint/rpc/types"
|
||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||
"github.com/tendermint/tendermint/proto/tendermint/crypto"
|
||||
)
|
||||
|
||||
type txGasAndReward struct {
|
||||
@ -45,8 +48,15 @@ func (s sortGasAndReward) Less(i, j int) bool {
|
||||
// Todo: include the ability to specify a blockNumber
|
||||
func (b *Backend) getAccountNonce(accAddr common.Address, pending bool, height int64, logger log.Logger) (uint64, error) {
|
||||
queryClient := authtypes.NewQueryClient(b.clientCtx)
|
||||
res, err := queryClient.Account(types.ContextWithHeight(height), &authtypes.QueryAccountRequest{Address: sdk.AccAddress(accAddr.Bytes()).String()})
|
||||
adr := sdk.AccAddress(accAddr.Bytes()).String()
|
||||
ctx := types.ContextWithHeight(height)
|
||||
res, err := queryClient.Account(ctx, &authtypes.QueryAccountRequest{Address: adr})
|
||||
if err != nil {
|
||||
st, ok := status.FromError(err)
|
||||
// treat as account doesn't exist yet
|
||||
if ok && st.Code() == codes.NotFound {
|
||||
return 0, nil
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
var acc authtypes.AccountI
|
||||
@ -260,6 +270,22 @@ func GetLogsFromBlockResults(blockRes *tmrpctypes.ResultBlockResults) ([][]*etht
|
||||
|
||||
blockLogs = append(blockLogs, logs...)
|
||||
}
|
||||
|
||||
return blockLogs, nil
|
||||
}
|
||||
|
||||
// GetHexProofs returns list of hex data of proof op
|
||||
func GetHexProofs(proof *crypto.ProofOps) []string {
|
||||
if proof == nil {
|
||||
return []string{""}
|
||||
}
|
||||
proofs := []string{}
|
||||
// check for proof
|
||||
for _, p := range proof.Ops {
|
||||
proof := ""
|
||||
if len(p.Data) > 0 {
|
||||
proof = hexutil.Encode(p.Data)
|
||||
}
|
||||
proofs = append(proofs, proof)
|
||||
}
|
||||
return proofs
|
||||
}
|
||||
|
52
rpc/backend/utils_test.go
Normal file
52
rpc/backend/utils_test.go
Normal file
@ -0,0 +1,52 @@
|
||||
package backend
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/tendermint/tendermint/proto/tendermint/crypto"
|
||||
)
|
||||
|
||||
func mookProofs(num int, withData bool) *crypto.ProofOps {
|
||||
var proofOps *crypto.ProofOps
|
||||
if num > 0 {
|
||||
proofOps = new(crypto.ProofOps)
|
||||
for i := 0; i < num; i++ {
|
||||
proof := crypto.ProofOp{}
|
||||
if withData {
|
||||
proof.Data = []byte("\n\031\n\003KEY\022\005VALUE\032\013\010\001\030\001 \001*\003\000\002\002")
|
||||
}
|
||||
proofOps.Ops = append(proofOps.Ops, proof)
|
||||
}
|
||||
}
|
||||
return proofOps
|
||||
}
|
||||
|
||||
func (suite *BackendTestSuite) TestGetHexProofs() {
|
||||
defaultRes := []string{""}
|
||||
testCases := []struct {
|
||||
name string
|
||||
proof *crypto.ProofOps
|
||||
exp []string
|
||||
}{
|
||||
{
|
||||
"no proof provided",
|
||||
mookProofs(0, false),
|
||||
defaultRes,
|
||||
},
|
||||
{
|
||||
"no proof data provided",
|
||||
mookProofs(1, false),
|
||||
defaultRes,
|
||||
},
|
||||
{
|
||||
"valid proof provided",
|
||||
mookProofs(1, true),
|
||||
[]string{"0x0a190a034b4559120556414c55451a0b0801180120012a03000202"},
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
|
||||
suite.Require().Equal(tc.exp, GetHexProofs(tc.proof))
|
||||
})
|
||||
}
|
||||
}
|
@ -499,6 +499,7 @@ func (e *PublicAPI) GetPendingTransactions() ([]*rpctypes.RPCTransaction, error)
|
||||
uint64(0),
|
||||
uint64(0),
|
||||
nil,
|
||||
e.backend.ChainConfig().ChainID,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -292,12 +292,9 @@ func (api *PublicFilterAPI) NewBlockFilter() rpc.ID {
|
||||
continue
|
||||
}
|
||||
|
||||
baseFee := types.BaseFeeFromEvents(data.ResultBeginBlock.Events)
|
||||
|
||||
header := types.EthHeaderFromTendermint(data.Header, ethtypes.Bloom{}, baseFee)
|
||||
api.filtersMu.Lock()
|
||||
if f, found := api.filters[headerSub.ID()]; found {
|
||||
f.hashes = append(f.hashes, header.Hash())
|
||||
f.hashes = append(f.hashes, common.BytesToHash(data.Header.Hash()))
|
||||
}
|
||||
api.filtersMu.Unlock()
|
||||
case <-errCh:
|
||||
|
@ -33,6 +33,7 @@ const (
|
||||
BlockParamEarliest = "earliest"
|
||||
BlockParamLatest = "latest"
|
||||
BlockParamFinalized = "finalized"
|
||||
BlockParamSafe = "safe"
|
||||
BlockParamPending = "pending"
|
||||
)
|
||||
|
||||
@ -73,7 +74,7 @@ func (bn *BlockNumber) UnmarshalJSON(data []byte) error {
|
||||
case BlockParamEarliest:
|
||||
*bn = EthEarliestBlockNumber
|
||||
return nil
|
||||
case BlockParamLatest, BlockParamFinalized:
|
||||
case BlockParamLatest, BlockParamFinalized, BlockParamSafe:
|
||||
*bn = EthLatestBlockNumber
|
||||
return nil
|
||||
case BlockParamPending:
|
||||
@ -159,7 +160,7 @@ func (bnh *BlockNumberOrHash) decodeFromString(input string) error {
|
||||
case BlockParamEarliest:
|
||||
bn := EthEarliestBlockNumber
|
||||
bnh.BlockNumber = &bn
|
||||
case BlockParamLatest:
|
||||
case BlockParamLatest, BlockParamFinalized:
|
||||
bn := EthLatestBlockNumber
|
||||
bnh.BlockNumber = &bn
|
||||
case BlockParamPending:
|
||||
|
@ -88,7 +88,7 @@ func TestUnmarshalBlockNumberOrHash(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
fmt.Sprintf("Case %s", tc.msg)
|
||||
fmt.Printf("Case %s", tc.msg)
|
||||
// reset input
|
||||
bnh = new(BlockNumberOrHash)
|
||||
err := bnh.UnmarshalJSON(tc.input)
|
||||
|
@ -10,8 +10,9 @@ import (
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
|
||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||
feemarkettypes "github.com/evmos/ethermint/x/feemarket/types"
|
||||
@ -31,7 +32,7 @@ const ExceedBlockGasLimitError = "out of gas in location: block gas meter; gasWa
|
||||
func RawTxToEthTx(clientCtx client.Context, txBz tmtypes.Tx) ([]*evmtypes.MsgEthereumTx, error) {
|
||||
tx, err := clientCtx.TxConfig.TxDecoder()(txBz)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
|
||||
return nil, errorsmod.Wrap(errortypes.ErrJSONUnmarshal, err.Error())
|
||||
}
|
||||
|
||||
ethTxs := make([]*evmtypes.MsgEthereumTx, len(tx.GetMsgs()))
|
||||
@ -144,15 +145,17 @@ func NewTransactionFromMsg(
|
||||
blockHash common.Hash,
|
||||
blockNumber, index uint64,
|
||||
baseFee *big.Int,
|
||||
chainID *big.Int,
|
||||
) (*RPCTransaction, error) {
|
||||
tx := msg.AsTransaction()
|
||||
return NewRPCTransaction(tx, blockHash, blockNumber, index, baseFee)
|
||||
return NewRPCTransaction(tx, blockHash, blockNumber, index, baseFee, chainID)
|
||||
}
|
||||
|
||||
// NewTransactionFromData returns a transaction that will serialize to the RPC
|
||||
// representation, with the given location metadata set (if available).
|
||||
func NewRPCTransaction(
|
||||
tx *ethtypes.Transaction, blockHash common.Hash, blockNumber, index uint64, baseFee *big.Int,
|
||||
chainID *big.Int,
|
||||
) (*RPCTransaction, error) {
|
||||
// Determine the signer. For replay-protected transactions, use the most permissive
|
||||
// signer, because we assume that signers are backwards-compatible with old
|
||||
@ -179,6 +182,7 @@ func NewRPCTransaction(
|
||||
V: (*hexutil.Big)(v),
|
||||
R: (*hexutil.Big)(r),
|
||||
S: (*hexutil.Big)(s),
|
||||
ChainID: (*hexutil.Big)(chainID),
|
||||
}
|
||||
if blockHash != (common.Hash{}) {
|
||||
result.BlockHash = &blockHash
|
||||
|
@ -65,12 +65,15 @@ fi
|
||||
echo "compiling ethermint"
|
||||
make build
|
||||
|
||||
|
||||
# PID array declaration
|
||||
arr=()
|
||||
|
||||
init_func() {
|
||||
"$PWD"/build/ethermintd keys add $KEY"$i" --keyring-backend test --home "$DATA_DIR$i" --no-backup --algo "eth_secp256k1"
|
||||
"$PWD"/build/ethermintd init $MONIKER --chain-id $CHAINID --home "$DATA_DIR$i"
|
||||
# Set gas limit in genesis
|
||||
cat $DATA_DIR$i/config/genesis.json | jq '.consensus_params["block"]["max_gas"]="10000000"' > $DATA_DIR$i/config/tmp_genesis.json && mv $DATA_DIR$i/config/tmp_genesis.json $DATA_DIR$i/config/genesis.json
|
||||
"$PWD"/build/ethermintd add-genesis-account \
|
||||
"$("$PWD"/build/ethermintd keys show "$KEY$i" --keyring-backend test -a --home "$DATA_DIR$i")" 1000000000000000000aphoton,1000000000000000000stake \
|
||||
--keyring-backend test --home "$DATA_DIR$i"
|
||||
@ -141,17 +144,6 @@ echo "done sleeping"
|
||||
|
||||
set +e
|
||||
|
||||
if [[ -z $TEST || $TEST == "integration" ]] ; then
|
||||
time_out=300s
|
||||
|
||||
for i in $(seq 1 "$TEST_QTD"); do
|
||||
HOST_RPC=http://$IP_ADDR:$RPC_PORT"$i"
|
||||
echo "going to test ethermint node $HOST_RPC ..."
|
||||
MODE=$MODE HOST=$HOST_RPC go test ./tests/e2e/... -timeout=$time_out -v -short
|
||||
TEST_FAIL=$?
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ -z $TEST || $TEST == "rpc" || $TEST == "pending" ]]; then
|
||||
time_out=300s
|
||||
if [[ $TEST == "pending" ]]; then
|
||||
@ -186,7 +178,7 @@ for i in "${arr[@]}"; do
|
||||
stop_func "$i"
|
||||
done
|
||||
|
||||
if [[ (-z $TEST || $TEST == "rpc" || $TEST == "integration" ) && $TEST_FAIL -ne 0 ]]; then
|
||||
if [[ (-z $TEST || $TEST == "rpc") && $TEST_FAIL -ne 0 ]]; then
|
||||
exit $TEST_FAIL
|
||||
else
|
||||
exit 0
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user