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
113
.clang-format
113
.clang-format
@ -1,115 +1,6 @@
|
|||||||
---
|
---
|
||||||
Language: Proto
|
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
|
BasedOnStyle: google
|
||||||
ReflowComments: true
|
ColumnLimit: 120
|
||||||
SortIncludes: true
|
IndentWidth: 2
|
||||||
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
|
|
||||||
...
|
...
|
||||||
|
2
.github/workflows/lint.yml
vendored
2
.github/workflows/lint.yml
vendored
@ -25,7 +25,7 @@ jobs:
|
|||||||
**/**.go
|
**/**.go
|
||||||
go.mod
|
go.mod
|
||||||
go.sum
|
go.sum
|
||||||
- uses: golangci/golangci-lint-action@v3.3.0
|
- uses: golangci/golangci-lint-action@v3.3.1
|
||||||
with:
|
with:
|
||||||
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
|
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
|
||||||
version: latest
|
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
|
make test-rpc
|
||||||
if: env.GIT_DIFF
|
if: env.GIT_DIFF
|
||||||
|
|
||||||
test-e2e:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 15
|
|
||||||
steps:
|
|
||||||
- uses: actions/setup-go@v3
|
|
||||||
with:
|
|
||||||
go-version: 1.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:
|
integration_tests:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
@ -148,84 +127,4 @@ jobs:
|
|||||||
name: ethermint
|
name: ethermint
|
||||||
signingKey: "${{ secrets.CACHIX_SIGNING_KEY }}"
|
signingKey: "${{ secrets.CACHIX_SIGNING_KEY }}"
|
||||||
- name: 'instantiate integration test env'
|
- name: 'instantiate integration test env'
|
||||||
run: nix-store -r $(nix-instantiate tests/integration_tests/shell.nix)
|
run: nix-store -r "$(nix-instantiate tests/integration_tests/shell.nix)"
|
||||||
|
|
||||||
test-sim-nondeterminism:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 25
|
|
||||||
steps:
|
|
||||||
- uses: actions/setup-go@v3
|
|
||||||
with:
|
|
||||||
go-version: 1.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
|
|
||||||
|
2766
.gitleaks.toml
Normal file
2766
.gitleaks.toml
Normal file
File diff suppressed because it is too large
Load Diff
@ -15,6 +15,7 @@
|
|||||||
"MD036": false
|
"MD036": false
|
||||||
"MD040": false
|
"MD040": false
|
||||||
"MD041": false
|
"MD041": false
|
||||||
|
"MD051": false
|
||||||
"MD049":
|
"MD049":
|
||||||
"style": "asterisk"
|
"style": "asterisk"
|
||||||
"no-hard-tabs": false
|
"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
|
# Changelog
|
||||||
|
|
||||||
## [v0.20.0-rc2] - 2022-11-02
|
## [v0.20.0-rc3] - 2022-11-30
|
||||||
|
|
||||||
### State Machine Breaking
|
### 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) [#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.
|
* (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.
|
* (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.
|
* (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
|
### API Breaking
|
||||||
|
|
||||||
* (ante) [#1214](https://github.com/evmos/ethermint/pull/1214) Set mempool priority to EVM transactions.
|
* (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
|
### 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
|
* (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
|
* (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.
|
* (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.
|
* (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.
|
* (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
|
* (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) [#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.
|
* (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.
|
* (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
|
* (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.
|
* (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`
|
* (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`
|
* (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.
|
* (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
|
### 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) [#1179](https://github.com/evmos/ethermint/pull/1179) Fix gas used in traceTransaction response.
|
||||||
* (rpc) [#1284](https://github.com/evmos/ethermint/pull/1284) Fix internal trace response upon incomplete `eth_sendTransaction` call.
|
* (rpc) [#1284](https://github.com/evmos/ethermint/pull/1284) Fix internal trace response upon incomplete `eth_sendTransaction` call.
|
||||||
* (rpc) [#1340](https://github.com/evmos/ethermint/pull/1340) Fix error response when `eth_estimateGas` height provided is not found.
|
* (rpc) [#1340](https://github.com/evmos/ethermint/pull/1340) Fix error response when `eth_estimateGas` height provided is not found.
|
||||||
@ -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.
|
* (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.
|
* (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) [#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
|
## [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.
|
* (evm) [tharsis#1088](https://github.com/evmos/ethermint/pull/1088) Fix ability to append log in tx post processing.
|
||||||
* (rpc) [tharsis#1081](https://github.com/evmos/ethermint/pull/1081) fix `debug_getBlockRlp`/`debug_printBlock` don't filter failed transactions.
|
* (rpc) [tharsis#1081](https://github.com/evmos/ethermint/pull/1081) fix `debug_getBlockRlp`/`debug_printBlock` don't filter failed transactions.
|
||||||
* (ante) [tharsis#1111](https://github.com/evmos/ethermint/pull/1111) Move CanTransfer decorator before GasConsume decorator
|
* (ante) [tharsis#1111](https://github.com/evmos/ethermint/pull/1111) Move CanTransfer decorator before GasConsume decorator
|
||||||
* (types) [tharsis#1112](https://github.com/cosmos/ethermint/pull/1112) Add `GetBaseAccount` to avoid invalid account error when create vesting account.
|
* (types) [tharsis#1112](https://github.com/evmos/ethermint/pull/1112) Add `GetBaseAccount` to avoid invalid account error when create vesting account.
|
||||||
|
|
||||||
## [v0.15.0] - 2022-05-09
|
## [v0.15.0] - 2022-05-09
|
||||||
|
|
||||||
@ -647,7 +674,7 @@ the Tracer type used to collect execution traces from the EVM transaction execut
|
|||||||
|
|
||||||
### Improvements
|
### Improvements
|
||||||
|
|
||||||
* (deps) [tharsis#615](https://github.com/cosmos/ethermint/pull/615) Bump Cosmos SDK version to [v0.39.2](https://github.com/cosmos/cosmos-sdk/tag/v0.39.2)
|
* (deps) [tharsis#615](https://github.com/cosmos/ethermint/pull/615) Bump Cosmos SDK version to [v0.39.2](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.39.2)
|
||||||
* (deps) [tharsis#610](https://github.com/cosmos/ethermint/pull/610) Update Go dependency to 1.15+.
|
* (deps) [tharsis#610](https://github.com/cosmos/ethermint/pull/610) Update Go dependency to 1.15+.
|
||||||
* (evm) [tharsis#603](https://github.com/cosmos/ethermint/pull/603) Add state transition params that enable or disable the EVM `Call` and `Create` operations.
|
* (evm) [tharsis#603](https://github.com/cosmos/ethermint/pull/603) Add state transition params that enable or disable the EVM `Call` and `Create` operations.
|
||||||
* (deps) [tharsis#602](https://github.com/cosmos/ethermint/pull/602) Bump tendermint version to [v0.33.9](https://github.com/tendermint/tendermint/releases/tag/v0.33.9)
|
* (deps) [tharsis#602](https://github.com/cosmos/ethermint/pull/602) Bump tendermint version to [v0.33.9](https://github.com/tendermint/tendermint/releases/tag/v0.33.9)
|
||||||
|
@ -17,7 +17,7 @@ COPY . .
|
|||||||
RUN make build
|
RUN make build
|
||||||
|
|
||||||
# Final image
|
# Final image
|
||||||
FROM alpine:3.16.2
|
FROM alpine:3.17.0
|
||||||
|
|
||||||
# Install ca-certificates
|
# Install ca-certificates
|
||||||
RUN apk add --update ca-certificates jq
|
RUN apk add --update ca-certificates jq
|
||||||
|
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
|
HTTPS_GIT := https://github.com/evmos/ethermint.git
|
||||||
PROJECT_NAME = $(shell git remote get-url origin | xargs basename -s .git)
|
PROJECT_NAME = $(shell git remote get-url origin | xargs basename -s .git)
|
||||||
DOCKER := $(shell which docker)
|
DOCKER := $(shell which docker)
|
||||||
DOCKER_BUF := $(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace bufbuild/buf:1.0.0-rc8
|
|
||||||
# RocksDB is a native dependency, so we don't assume the library is installed.
|
# RocksDB is a native dependency, so we don't assume the library is installed.
|
||||||
# Instead, it must be explicitly enabled and we warn when it is not.
|
# Instead, it must be explicitly enabled and we warn when it is not.
|
||||||
ENABLE_ROCKSDB ?= false
|
ENABLE_ROCKSDB ?= false
|
||||||
@ -328,9 +327,6 @@ test-import:
|
|||||||
test-rpc:
|
test-rpc:
|
||||||
./scripts/integration-test-all.sh -t "rpc" -q 1 -z 1 -s 2 -m "rpc" -r "true"
|
./scripts/integration-test-all.sh -t "rpc" -q 1 -z 1 -s 2 -m "rpc" -r "true"
|
||||||
|
|
||||||
test-integration:
|
|
||||||
./scripts/integration-test-all.sh -t "integration" -q 1 -z 1 -s 2 -m "integration" -r "true"
|
|
||||||
|
|
||||||
run-integration-tests:
|
run-integration-tests:
|
||||||
@nix-shell ./tests/integration_tests/shell.nix --run ./scripts/run-integration-tests.sh
|
@nix-shell ./tests/integration_tests/shell.nix --run ./scripts/run-integration-tests.sh
|
||||||
|
|
||||||
@ -347,51 +343,6 @@ test-solidity:
|
|||||||
|
|
||||||
.PHONY: run-tests test test-all test-import test-rpc test-contract test-solidity $(TEST_TARGETS)
|
.PHONY: run-tests test test-all test-import test-rpc test-contract test-solidity $(TEST_TARGETS)
|
||||||
|
|
||||||
test-sim-nondeterminism:
|
|
||||||
@echo "Running non-determinism test..."
|
|
||||||
@go test -mod=readonly $(SIMAPP) -run TestAppStateDeterminism -Enabled=true \
|
|
||||||
-NumBlocks=100 -BlockSize=200 -Commit=true -Period=0 -v -timeout 24h
|
|
||||||
|
|
||||||
test-sim-random-genesis-fast:
|
|
||||||
@echo "Running random genesis simulation..."
|
|
||||||
@go test -mod=readonly $(SIMAPP) -run TestFullAppSimulation \
|
|
||||||
-Enabled=true -NumBlocks=100 -BlockSize=200 -Commit=true -Seed=99 -Period=5 -v -timeout 24h
|
|
||||||
|
|
||||||
test-sim-import-export: runsim
|
|
||||||
@echo "Running application import/export simulation. This may take several minutes..."
|
|
||||||
@$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 50 5 TestAppImportExport
|
|
||||||
|
|
||||||
test-sim-after-import: runsim
|
|
||||||
@echo "Running application simulation-after-import. This may take several minutes..."
|
|
||||||
@$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 50 5 TestAppSimulationAfterImport
|
|
||||||
|
|
||||||
test-sim-random-genesis-multi-seed: runsim
|
|
||||||
@echo "Running multi-seed custom genesis simulation..."
|
|
||||||
@$(BINDIR)/runsim -SimAppPkg=$(SIMAPP) -ExitOnFail 400 5 TestFullAppSimulation
|
|
||||||
|
|
||||||
test-sim-multi-seed-long: runsim
|
|
||||||
@echo "Running long multi-seed application simulation. This may take awhile!"
|
|
||||||
@$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 500 50 TestFullAppSimulation
|
|
||||||
|
|
||||||
test-sim-multi-seed-short: runsim
|
|
||||||
@echo "Running short multi-seed application simulation. This may take awhile!"
|
|
||||||
@$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 50 10 TestFullAppSimulation
|
|
||||||
|
|
||||||
test-sim-benchmark-invariants:
|
|
||||||
@echo "Running simulation invariant benchmarks..."
|
|
||||||
@go test -mod=readonly $(SIMAPP) -benchmem -bench=BenchmarkInvariants -run=^$ \
|
|
||||||
-Enabled=true -NumBlocks=1000 -BlockSize=200 \
|
|
||||||
-Period=1 -Commit=true -Seed=57 -v -timeout 24h
|
|
||||||
|
|
||||||
.PHONY: \
|
|
||||||
test-sim-nondeterminism \
|
|
||||||
test-sim-custom-genesis-fast \
|
|
||||||
test-sim-import-export \
|
|
||||||
test-sim-after-import \
|
|
||||||
test-sim-custom-genesis-multi-seed \
|
|
||||||
test-sim-multi-seed-short \
|
|
||||||
test-sim-multi-seed-long \
|
|
||||||
test-sim-benchmark-invariants
|
|
||||||
|
|
||||||
benchmark:
|
benchmark:
|
||||||
@go test -mod=readonly -bench=. $(PACKAGES_NOSIMULATION)
|
@go test -mod=readonly -bench=. $(PACKAGES_NOSIMULATION)
|
||||||
@ -425,74 +376,62 @@ format-fix:
|
|||||||
### Protobuf ###
|
### Protobuf ###
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
protoVer=v0.2
|
# ------
|
||||||
|
# NOTE: Link to the tendermintdev/sdk-proto-gen docker images:
|
||||||
|
# https://hub.docker.com/r/tendermintdev/sdk-proto-gen/tags
|
||||||
|
#
|
||||||
|
protoVer=v0.7
|
||||||
protoImageName=tendermintdev/sdk-proto-gen:$(protoVer)
|
protoImageName=tendermintdev/sdk-proto-gen:$(protoVer)
|
||||||
containerProtoGen=$(PROJECT_NAME)-proto-gen-$(protoVer)
|
protoImage=$(DOCKER) run --network host --rm -v $(CURDIR):/workspace --workdir /workspace $(protoImageName)
|
||||||
containerProtoGenAny=$(PROJECT_NAME)-proto-gen-any-$(protoVer)
|
# ------
|
||||||
containerProtoGenSwagger=$(PROJECT_NAME)-proto-gen-swagger-$(protoVer)
|
# NOTE: cosmos/proto-builder image is needed because clang-format is not installed
|
||||||
containerProtoFmt=$(PROJECT_NAME)-proto-fmt-$(protoVer)
|
# on the tendermintdev/sdk-proto-gen docker image.
|
||||||
|
# Link to the cosmos/proto-builder docker images:
|
||||||
|
# https://github.com/cosmos/cosmos-sdk/pkgs/container/proto-builder
|
||||||
|
#
|
||||||
|
protoCosmosVer=0.11.2
|
||||||
|
protoCosmosName=ghcr.io/cosmos/proto-builder:$(protoCosmosVer)
|
||||||
|
protoCosmosImage=$(DOCKER) run --network host --rm -v $(CURDIR):/workspace --workdir /workspace $(protoCosmosName)
|
||||||
|
# ------
|
||||||
|
# NOTE: Link to the yoheimuta/protolint docker images:
|
||||||
|
# https://hub.docker.com/r/yoheimuta/protolint/tags
|
||||||
|
#
|
||||||
|
protolintVer=0.42.2
|
||||||
|
protolintName=yoheimuta/protolint:$(protolintVer)
|
||||||
|
protolintImage=$(DOCKER) run --network host --rm -v $(CURDIR):/workspace --workdir /workspace $(protolintName)
|
||||||
|
|
||||||
|
|
||||||
|
# ------
|
||||||
|
# NOTE: If you are experiencing problems running these commands, try deleting
|
||||||
|
# the docker images and execute the desired command again.
|
||||||
|
#
|
||||||
proto-all: proto-format proto-lint proto-gen
|
proto-all: proto-format proto-lint proto-gen
|
||||||
|
|
||||||
proto-gen:
|
proto-gen:
|
||||||
@echo "Generating Protobuf files"
|
@echo "Generating Protobuf files"
|
||||||
@if docker ps -a --format '{{.Names}}' | grep -Eq "^${containerProtoGen}$$"; then docker start -a $(containerProtoGen); else docker run --name $(containerProtoGen) -v $(CURDIR):/workspace --workdir /workspace $(protoImageName) \
|
$(protoImage) sh ./scripts/protocgen.sh
|
||||||
sh ./scripts/protocgen.sh; fi
|
|
||||||
|
|
||||||
proto-swagger-gen:
|
|
||||||
@echo "Generating Protobuf Swagger"
|
# TODO: Rethink API docs generation
|
||||||
@./scripts/proto-tools-installer.sh
|
# proto-swagger-gen:
|
||||||
@./scripts/protoc-swagger-gen.sh
|
# @echo "Generating Protobuf Swagger"
|
||||||
|
# $(protoImage) sh ./scripts/protoc-swagger-gen.sh
|
||||||
|
|
||||||
proto-format:
|
proto-format:
|
||||||
@echo "Formatting Protobuf files"
|
@echo "Formatting Protobuf files"
|
||||||
@if docker ps -a --format '{{.Names}}' | grep -Eq "^${containerProtoFmt}$$"; then docker start -a $(containerProtoFmt); else docker run --name $(containerProtoFmt) -v $(CURDIR):/workspace --workdir /workspace tendermintdev/docker-build-proto \
|
$(protoCosmosImage) find ./ -name *.proto -exec clang-format -i {} \;
|
||||||
find ./ -not -path "./third_party/*" -name "*.proto" -exec clang-format -i {} \; ; fi
|
|
||||||
|
|
||||||
|
# NOTE: The linter configuration lives in .protolint.yaml
|
||||||
proto-lint:
|
proto-lint:
|
||||||
@$(DOCKER_BUF) lint --error-format=json
|
@echo "Linting Protobuf files"
|
||||||
|
$(protolintImage) lint ./proto
|
||||||
|
|
||||||
proto-check-breaking:
|
proto-check-breaking:
|
||||||
@$(DOCKER_BUF) breaking --against $(HTTPS_GIT)#branch=main
|
@echo "Checking Protobuf files for breaking changes"
|
||||||
|
$(protoImage) buf breaking --against $(HTTPS_GIT)#branch=main
|
||||||
|
|
||||||
|
|
||||||
TM_URL = https://raw.githubusercontent.com/tendermint/tendermint/v0.34.12/proto/tendermint
|
.PHONY: proto-all proto-gen proto-gen-any proto-format proto-lint proto-check-breaking
|
||||||
GOGO_PROTO_URL = https://raw.githubusercontent.com/regen-network/protobuf/cosmos
|
|
||||||
COSMOS_SDK_URL = https://raw.githubusercontent.com/cosmos/cosmos-sdk/v0.43.0
|
|
||||||
COSMOS_PROTO_URL = https://raw.githubusercontent.com/regen-network/cosmos-proto/master
|
|
||||||
|
|
||||||
TM_CRYPTO_TYPES = third_party/proto/tendermint/crypto
|
|
||||||
TM_ABCI_TYPES = third_party/proto/tendermint/abci
|
|
||||||
TM_TYPES = third_party/proto/tendermint/types
|
|
||||||
|
|
||||||
GOGO_PROTO_TYPES = third_party/proto/gogoproto
|
|
||||||
|
|
||||||
COSMOS_PROTO_TYPES = third_party/proto/cosmos_proto
|
|
||||||
|
|
||||||
proto-update-deps:
|
|
||||||
@mkdir -p $(GOGO_PROTO_TYPES)
|
|
||||||
@curl -sSL $(GOGO_PROTO_URL)/gogoproto/gogo.proto > $(GOGO_PROTO_TYPES)/gogo.proto
|
|
||||||
|
|
||||||
@mkdir -p $(COSMOS_PROTO_TYPES)
|
|
||||||
@curl -sSL $(COSMOS_PROTO_URL)/cosmos.proto > $(COSMOS_PROTO_TYPES)/cosmos.proto
|
|
||||||
|
|
||||||
## Importing of tendermint protobuf definitions currently requires the
|
|
||||||
## use of `sed` in order to build properly with cosmos-sdk's proto file layout
|
|
||||||
## (which is the standard Buf.build FILE_LAYOUT)
|
|
||||||
## Issue link: https://github.com/tendermint/tendermint/issues/5021
|
|
||||||
@mkdir -p $(TM_ABCI_TYPES)
|
|
||||||
@curl -sSL $(TM_URL)/abci/types.proto > $(TM_ABCI_TYPES)/types.proto
|
|
||||||
|
|
||||||
@mkdir -p $(TM_TYPES)
|
|
||||||
@curl -sSL $(TM_URL)/types/types.proto > $(TM_TYPES)/types.proto
|
|
||||||
|
|
||||||
@mkdir -p $(TM_CRYPTO_TYPES)
|
|
||||||
@curl -sSL $(TM_URL)/crypto/proof.proto > $(TM_CRYPTO_TYPES)/proof.proto
|
|
||||||
@curl -sSL $(TM_URL)/crypto/keys.proto > $(TM_CRYPTO_TYPES)/keys.proto
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.PHONY: proto-all proto-gen proto-gen-any proto-swagger-gen proto-format proto-lint proto-check-breaking proto-update-deps
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
### Localnet ###
|
### Localnet ###
|
||||||
|
@ -6,9 +6,10 @@ import (
|
|||||||
|
|
||||||
tmlog "github.com/tendermint/tendermint/libs/log"
|
tmlog "github.com/tendermint/tendermint/libs/log"
|
||||||
|
|
||||||
|
errorsmod "cosmossdk.io/errors"
|
||||||
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
|
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||||
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||||
@ -51,8 +52,8 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
|
|||||||
// cosmos-sdk tx with dynamic fee extension
|
// cosmos-sdk tx with dynamic fee extension
|
||||||
anteHandler = newCosmosAnteHandler(options)
|
anteHandler = newCosmosAnteHandler(options)
|
||||||
default:
|
default:
|
||||||
return ctx, sdkerrors.Wrapf(
|
return ctx, errorsmod.Wrapf(
|
||||||
sdkerrors.ErrUnknownExtensionOptions,
|
errortypes.ErrUnknownExtensionOptions,
|
||||||
"rejecting tx with unsupported extension option: %s", typeURL,
|
"rejecting tx with unsupported extension option: %s", typeURL,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -66,7 +67,7 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
|
|||||||
case sdk.Tx:
|
case sdk.Tx:
|
||||||
anteHandler = newCosmosAnteHandler(options)
|
anteHandler = newCosmosAnteHandler(options)
|
||||||
default:
|
default:
|
||||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx)
|
return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid transaction type: %T", tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
return anteHandler(ctx, tx, sim)
|
return anteHandler(ctx, tx, sim)
|
||||||
@ -75,7 +76,7 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
|
|||||||
|
|
||||||
func Recover(logger tmlog.Logger, err *error) {
|
func Recover(logger tmlog.Logger, err *error) {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
*err = sdkerrors.Wrapf(sdkerrors.ErrPanic, "%v", r)
|
*err = errorsmod.Wrapf(errortypes.ErrPanic, "%v", r)
|
||||||
|
|
||||||
if e, ok := r.(error); ok {
|
if e, ok := r.(error); ok {
|
||||||
logger.Error(
|
logger.Error(
|
||||||
|
@ -31,6 +31,7 @@ import (
|
|||||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||||
|
|
||||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||||
|
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (suite AnteTestSuite) TestAnteHandler() {
|
func (suite AnteTestSuite) TestAnteHandler() {
|
||||||
@ -348,6 +349,17 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
|||||||
return txBuilder.GetTx()
|
return txBuilder.GetTx()
|
||||||
}, false, false, true,
|
}, false, false, true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"success- DeliverTx EIP712 create validator (with blank fields)",
|
||||||
|
func() sdk.Tx {
|
||||||
|
from := acc.GetAddress()
|
||||||
|
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
|
||||||
|
amount := sdk.NewCoins(coinAmount)
|
||||||
|
gas := uint64(200000)
|
||||||
|
txBuilder := suite.CreateTestEIP712MsgCreateValidator2(from, privKey, "ethermint_9000-1", gas, amount)
|
||||||
|
return txBuilder.GetTx()
|
||||||
|
}, false, false, true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"success- DeliverTx EIP712 MsgSubmitProposal",
|
"success- DeliverTx EIP712 MsgSubmitProposal",
|
||||||
func() sdk.Tx {
|
func() sdk.Tx {
|
||||||
@ -375,7 +387,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
|||||||
from, grantee, &banktypes.SendAuthorization{SpendLimit: gasAmount}, &expiresAt,
|
from, grantee, &banktypes.SendAuthorization{SpendLimit: gasAmount}, &expiresAt,
|
||||||
)
|
)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
return suite.CreateTestEIP712CosmosTxBuilder(from, privKey, "ethermint_9000-1", gas, gasAmount, msg).GetTx()
|
return suite.CreateTestEIP712SingleMessageTxBuilder(from, privKey, "ethermint_9000-1", gas, gasAmount, msg).GetTx()
|
||||||
}, false, false, true,
|
}, false, false, true,
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -408,10 +420,65 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
|||||||
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
|
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
|
||||||
amount := sdk.NewCoins(coinAmount)
|
amount := sdk.NewCoins(coinAmount)
|
||||||
gas := uint64(200000)
|
gas := uint64(200000)
|
||||||
txBuilder := suite.CreateTestEIP712MsgEditValidator(from, privKey, "ethermint_9000-1", gas, amount)
|
txBuilder := suite.CreateTestEIP712MsgSubmitEvidence(from, privKey, "ethermint_9000-1", gas, amount)
|
||||||
return txBuilder.GetTx()
|
return txBuilder.GetTx()
|
||||||
}, false, false, true,
|
}, false, false, true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"success- DeliverTx EIP712 submit proposal v1",
|
||||||
|
func() sdk.Tx {
|
||||||
|
from := acc.GetAddress()
|
||||||
|
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
|
||||||
|
amount := sdk.NewCoins(coinAmount)
|
||||||
|
gas := uint64(200000)
|
||||||
|
txBuilder := suite.CreateTestEIP712SubmitProposalV1(from, privKey, "ethermint_9000-1", gas, amount)
|
||||||
|
return txBuilder.GetTx()
|
||||||
|
}, false, false, true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"success- DeliverTx EIP712 MsgExec",
|
||||||
|
func() sdk.Tx {
|
||||||
|
from := acc.GetAddress()
|
||||||
|
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
|
||||||
|
amount := sdk.NewCoins(coinAmount)
|
||||||
|
gas := uint64(200000)
|
||||||
|
txBuilder := suite.CreateTestEIP712MsgExec(from, privKey, "ethermint_9000-1", gas, amount)
|
||||||
|
return txBuilder.GetTx()
|
||||||
|
}, false, false, true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"success- DeliverTx EIP712 MsgVoteV1",
|
||||||
|
func() sdk.Tx {
|
||||||
|
from := acc.GetAddress()
|
||||||
|
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
|
||||||
|
amount := sdk.NewCoins(coinAmount)
|
||||||
|
gas := uint64(200000)
|
||||||
|
txBuilder := suite.CreateTestEIP712MsgVoteV1(from, privKey, "ethermint_9000-1", gas, amount)
|
||||||
|
return txBuilder.GetTx()
|
||||||
|
}, false, false, true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"success- DeliverTx EIP712 Multiple MsgSend",
|
||||||
|
func() sdk.Tx {
|
||||||
|
from := acc.GetAddress()
|
||||||
|
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
|
||||||
|
amount := sdk.NewCoins(coinAmount)
|
||||||
|
gas := uint64(200000)
|
||||||
|
txBuilder := suite.CreateTestEIP712MultipleMsgSend(from, privKey, "ethermint_9000-1", gas, amount)
|
||||||
|
return txBuilder.GetTx()
|
||||||
|
}, false, false, true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fails - DeliverTx EIP712 Multiple Signers",
|
||||||
|
func() sdk.Tx {
|
||||||
|
from := acc.GetAddress()
|
||||||
|
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
|
||||||
|
amount := sdk.NewCoins(coinAmount)
|
||||||
|
gas := uint64(200000)
|
||||||
|
txBuilder := suite.CreateTestEIP712MultipleSignerMsgs(from, privKey, "ethermint_9000-1", gas, amount)
|
||||||
|
return txBuilder.GetTx()
|
||||||
|
}, false, false, false,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fails - DeliverTx EIP712 signed Cosmos Tx with wrong Chain ID",
|
"fails - DeliverTx EIP712 signed Cosmos Tx with wrong Chain ID",
|
||||||
func() sdk.Tx {
|
func() sdk.Tx {
|
||||||
@ -507,6 +574,301 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
|||||||
return tx
|
return tx
|
||||||
}, true, false, false,
|
}, true, false, false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"passes - Single-signer EIP-712",
|
||||||
|
func() sdk.Tx {
|
||||||
|
msg := banktypes.NewMsgSend(
|
||||||
|
sdk.AccAddress(privKey.PubKey().Address()),
|
||||||
|
addr[:],
|
||||||
|
sdk.NewCoins(
|
||||||
|
sdk.NewCoin(
|
||||||
|
"photon",
|
||||||
|
sdk.NewInt(1),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
txBuilder := suite.CreateTestSingleSignedTx(
|
||||||
|
privKey,
|
||||||
|
signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
|
||||||
|
msg,
|
||||||
|
"ethermint_9000-1",
|
||||||
|
2000000,
|
||||||
|
"EIP-712",
|
||||||
|
)
|
||||||
|
|
||||||
|
return txBuilder.GetTx()
|
||||||
|
}, false, false, true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"passes - EIP-712 multi-key",
|
||||||
|
func() sdk.Tx {
|
||||||
|
numKeys := 5
|
||||||
|
privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys)
|
||||||
|
pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys)
|
||||||
|
|
||||||
|
msg := banktypes.NewMsgSend(
|
||||||
|
sdk.AccAddress(pk.Address()),
|
||||||
|
addr[:],
|
||||||
|
sdk.NewCoins(
|
||||||
|
sdk.NewCoin(
|
||||||
|
"photon",
|
||||||
|
sdk.NewInt(1),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
txBuilder := suite.CreateTestSignedMultisigTx(
|
||||||
|
privKeys,
|
||||||
|
signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
|
||||||
|
msg,
|
||||||
|
"ethermint_9000-1",
|
||||||
|
2000000,
|
||||||
|
"EIP-712",
|
||||||
|
)
|
||||||
|
|
||||||
|
return txBuilder.GetTx()
|
||||||
|
}, false, false, true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"passes - Mixed multi-key",
|
||||||
|
func() sdk.Tx {
|
||||||
|
numKeys := 5
|
||||||
|
privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys)
|
||||||
|
pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys)
|
||||||
|
|
||||||
|
msg := banktypes.NewMsgSend(
|
||||||
|
sdk.AccAddress(pk.Address()),
|
||||||
|
addr[:],
|
||||||
|
sdk.NewCoins(
|
||||||
|
sdk.NewCoin(
|
||||||
|
"photon",
|
||||||
|
sdk.NewInt(1),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
txBuilder := suite.CreateTestSignedMultisigTx(
|
||||||
|
privKeys,
|
||||||
|
signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
|
||||||
|
msg,
|
||||||
|
"ethermint_9000-1",
|
||||||
|
2000000,
|
||||||
|
"mixed", // Combine EIP-712 and standard signatures
|
||||||
|
)
|
||||||
|
|
||||||
|
return txBuilder.GetTx()
|
||||||
|
}, false, false, true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"passes - Mixed multi-key with MsgVote",
|
||||||
|
func() sdk.Tx {
|
||||||
|
numKeys := 5
|
||||||
|
privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys)
|
||||||
|
pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys)
|
||||||
|
|
||||||
|
msg := govtypes.NewMsgVote(
|
||||||
|
sdk.AccAddress(pk.Address()),
|
||||||
|
1,
|
||||||
|
govtypes.OptionYes,
|
||||||
|
)
|
||||||
|
|
||||||
|
txBuilder := suite.CreateTestSignedMultisigTx(
|
||||||
|
privKeys,
|
||||||
|
signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
|
||||||
|
msg,
|
||||||
|
"ethermint_9000-1",
|
||||||
|
2000000,
|
||||||
|
"mixed", // Combine EIP-712 and standard signatures
|
||||||
|
)
|
||||||
|
|
||||||
|
return txBuilder.GetTx()
|
||||||
|
}, false, false, true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Fails - Multi-Key with incorrect Chain ID",
|
||||||
|
func() sdk.Tx {
|
||||||
|
numKeys := 5
|
||||||
|
privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys)
|
||||||
|
pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys)
|
||||||
|
|
||||||
|
msg := banktypes.NewMsgSend(
|
||||||
|
sdk.AccAddress(pk.Address()),
|
||||||
|
addr[:],
|
||||||
|
sdk.NewCoins(
|
||||||
|
sdk.NewCoin(
|
||||||
|
"photon",
|
||||||
|
sdk.NewInt(1),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
txBuilder := suite.CreateTestSignedMultisigTx(
|
||||||
|
privKeys,
|
||||||
|
signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
|
||||||
|
msg,
|
||||||
|
"ethermint_9005-1",
|
||||||
|
2000000,
|
||||||
|
"mixed",
|
||||||
|
)
|
||||||
|
|
||||||
|
return txBuilder.GetTx()
|
||||||
|
}, false, false, false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Fails - Multi-Key with incorrect sign mode",
|
||||||
|
func() sdk.Tx {
|
||||||
|
numKeys := 5
|
||||||
|
privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys)
|
||||||
|
pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys)
|
||||||
|
|
||||||
|
msg := banktypes.NewMsgSend(
|
||||||
|
sdk.AccAddress(pk.Address()),
|
||||||
|
addr[:],
|
||||||
|
sdk.NewCoins(
|
||||||
|
sdk.NewCoin(
|
||||||
|
"photon",
|
||||||
|
sdk.NewInt(1),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
txBuilder := suite.CreateTestSignedMultisigTx(
|
||||||
|
privKeys,
|
||||||
|
signing.SignMode_SIGN_MODE_DIRECT,
|
||||||
|
msg,
|
||||||
|
"ethermint_9000-1",
|
||||||
|
2000000,
|
||||||
|
"mixed",
|
||||||
|
)
|
||||||
|
|
||||||
|
return txBuilder.GetTx()
|
||||||
|
}, false, false, false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Fails - Multi-Key with too little gas",
|
||||||
|
func() sdk.Tx {
|
||||||
|
numKeys := 5
|
||||||
|
privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys)
|
||||||
|
pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys)
|
||||||
|
|
||||||
|
msg := banktypes.NewMsgSend(
|
||||||
|
sdk.AccAddress(pk.Address()),
|
||||||
|
addr[:],
|
||||||
|
sdk.NewCoins(
|
||||||
|
sdk.NewCoin(
|
||||||
|
"photon",
|
||||||
|
sdk.NewInt(1),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
txBuilder := suite.CreateTestSignedMultisigTx(
|
||||||
|
privKeys,
|
||||||
|
signing.SignMode_SIGN_MODE_DIRECT,
|
||||||
|
msg,
|
||||||
|
"ethermint_9000-1",
|
||||||
|
2000,
|
||||||
|
"mixed", // Combine EIP-712 and standard signatures
|
||||||
|
)
|
||||||
|
|
||||||
|
return txBuilder.GetTx()
|
||||||
|
}, false, false, false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Fails - Multi-Key with different payload than one signed",
|
||||||
|
func() sdk.Tx {
|
||||||
|
numKeys := 1
|
||||||
|
privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys)
|
||||||
|
pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys)
|
||||||
|
|
||||||
|
msg := banktypes.NewMsgSend(
|
||||||
|
sdk.AccAddress(pk.Address()),
|
||||||
|
addr[:],
|
||||||
|
sdk.NewCoins(
|
||||||
|
sdk.NewCoin(
|
||||||
|
"photon",
|
||||||
|
sdk.NewInt(1),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
txBuilder := suite.CreateTestSignedMultisigTx(
|
||||||
|
privKeys,
|
||||||
|
signing.SignMode_SIGN_MODE_DIRECT,
|
||||||
|
msg,
|
||||||
|
"ethermint_9000-1",
|
||||||
|
2000,
|
||||||
|
"EIP-712",
|
||||||
|
)
|
||||||
|
|
||||||
|
msg.Amount[0].Amount = sdk.NewInt(5)
|
||||||
|
txBuilder.SetMsgs(msg)
|
||||||
|
|
||||||
|
return txBuilder.GetTx()
|
||||||
|
}, false, false, false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Fails - Multi-Key with messages added after signing",
|
||||||
|
func() sdk.Tx {
|
||||||
|
numKeys := 1
|
||||||
|
privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys)
|
||||||
|
pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys)
|
||||||
|
|
||||||
|
msg := banktypes.NewMsgSend(
|
||||||
|
sdk.AccAddress(pk.Address()),
|
||||||
|
addr[:],
|
||||||
|
sdk.NewCoins(
|
||||||
|
sdk.NewCoin(
|
||||||
|
"photon",
|
||||||
|
sdk.NewInt(1),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
txBuilder := suite.CreateTestSignedMultisigTx(
|
||||||
|
privKeys,
|
||||||
|
signing.SignMode_SIGN_MODE_DIRECT,
|
||||||
|
msg,
|
||||||
|
"ethermint_9000-1",
|
||||||
|
2000,
|
||||||
|
"EIP-712",
|
||||||
|
)
|
||||||
|
|
||||||
|
// Duplicate
|
||||||
|
txBuilder.SetMsgs(msg, msg)
|
||||||
|
|
||||||
|
return txBuilder.GetTx()
|
||||||
|
}, false, false, false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Fails - Single-Signer EIP-712 with messages added after signing",
|
||||||
|
func() sdk.Tx {
|
||||||
|
msg := banktypes.NewMsgSend(
|
||||||
|
sdk.AccAddress(privKey.PubKey().Address()),
|
||||||
|
addr[:],
|
||||||
|
sdk.NewCoins(
|
||||||
|
sdk.NewCoin(
|
||||||
|
"photon",
|
||||||
|
sdk.NewInt(1),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
txBuilder := suite.CreateTestSingleSignedTx(
|
||||||
|
privKey,
|
||||||
|
signing.SignMode_SIGN_MODE_DIRECT,
|
||||||
|
msg,
|
||||||
|
"ethermint_9000-1",
|
||||||
|
2000,
|
||||||
|
"EIP-712",
|
||||||
|
)
|
||||||
|
|
||||||
|
txBuilder.SetMsgs(msg, msg)
|
||||||
|
|
||||||
|
return txBuilder.GetTx()
|
||||||
|
}, false, false, false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
|
@ -3,11 +3,12 @@ package ante
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
errorsmod "cosmossdk.io/errors"
|
||||||
"github.com/cosmos/cosmos-sdk/codec"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||||
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||||
"github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx"
|
"github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx"
|
||||||
@ -15,9 +16,11 @@ import (
|
|||||||
|
|
||||||
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/crypto/secp256k1"
|
"github.com/ethereum/go-ethereum/crypto/secp256k1"
|
||||||
|
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
||||||
"github.com/evmos/ethermint/crypto/ethsecp256k1"
|
"github.com/evmos/ethermint/crypto/ethsecp256k1"
|
||||||
"github.com/evmos/ethermint/ethereum/eip712"
|
"github.com/evmos/ethermint/ethereum/eip712"
|
||||||
ethermint "github.com/evmos/ethermint/types"
|
ethermint "github.com/evmos/ethermint/types"
|
||||||
|
|
||||||
evmtypes "github.com/evmos/ethermint/x/evm/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)
|
sigTx, ok := tx.(authsigning.SigVerifiableTx)
|
||||||
if !ok {
|
if !ok {
|
||||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "tx %T doesn't implement authsigning.SigVerifiableTx", tx)
|
return ctx, errorsmod.Wrapf(errortypes.ErrInvalidType, "tx %T doesn't implement authsigning.SigVerifiableTx", tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
authSignTx, ok := tx.(authsigning.Tx)
|
authSignTx, ok := tx.(authsigning.Tx)
|
||||||
if !ok {
|
if !ok {
|
||||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "tx %T doesn't implement the authsigning.Tx interface", tx)
|
return ctx, errorsmod.Wrapf(errortypes.ErrInvalidType, "tx %T doesn't implement the authsigning.Tx interface", tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// stdSigs contains the sequence number, account number, and signatures.
|
// stdSigs contains the sequence number, account number, and signatures.
|
||||||
@ -80,12 +83,16 @@ func (svd Eip712SigVerificationDecorator) AnteHandle(ctx sdk.Context,
|
|||||||
|
|
||||||
// EIP712 allows just one signature
|
// EIP712 allows just one signature
|
||||||
if len(sigs) != 1 {
|
if len(sigs) != 1 {
|
||||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "invalid number of signers (%d); EIP712 signatures allows just one signature", len(sigs))
|
return ctx, errorsmod.Wrapf(
|
||||||
|
errortypes.ErrTooManySignatures,
|
||||||
|
"invalid number of signers (%d); EIP712 signatures allows just one signature",
|
||||||
|
len(sigs),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that signer length and signature length are the same
|
// check that signer length and signature length are the same
|
||||||
if len(sigs) != len(signerAddrs) {
|
if len(sigs) != len(signerAddrs) {
|
||||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "invalid number of signer; expected: %d, got %d", len(signerAddrs), len(sigs))
|
return ctx, errorsmod.Wrapf(errortypes.ErrorInvalidSigner, "invalid number of signers; expected: %d, got %d", len(signerAddrs), len(sigs))
|
||||||
}
|
}
|
||||||
|
|
||||||
// EIP712 has just one signature, avoid looping here and only read index 0
|
// EIP712 has just one signature, avoid looping here and only read index 0
|
||||||
@ -100,13 +107,13 @@ func (svd Eip712SigVerificationDecorator) AnteHandle(ctx sdk.Context,
|
|||||||
// retrieve pubkey
|
// retrieve pubkey
|
||||||
pubKey := acc.GetPubKey()
|
pubKey := acc.GetPubKey()
|
||||||
if !simulate && pubKey == nil {
|
if !simulate && pubKey == nil {
|
||||||
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidPubKey, "pubkey on account is not set")
|
return ctx, errorsmod.Wrap(errortypes.ErrInvalidPubKey, "pubkey on account is not set")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check account sequence number.
|
// Check account sequence number.
|
||||||
if sig.Sequence != acc.GetSequence() {
|
if sig.Sequence != acc.GetSequence() {
|
||||||
return ctx, sdkerrors.Wrapf(
|
return ctx, errorsmod.Wrapf(
|
||||||
sdkerrors.ErrWrongSequence,
|
errortypes.ErrWrongSequence,
|
||||||
"account sequence mismatch, expected %d, got %d", acc.GetSequence(), sig.Sequence,
|
"account sequence mismatch, expected %d, got %d", acc.GetSequence(), sig.Sequence,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -132,7 +139,7 @@ func (svd Eip712SigVerificationDecorator) AnteHandle(ctx sdk.Context,
|
|||||||
|
|
||||||
if err := VerifySignature(pubKey, signerData, sig.Data, svd.signModeHandler, authSignTx); err != nil {
|
if err := VerifySignature(pubKey, signerData, sig.Data, svd.signModeHandler, authSignTx); err != nil {
|
||||||
errMsg := fmt.Errorf("signature verification failed; please verify account number (%d) and chain-id (%s): %w", accNum, chainID, err)
|
errMsg := fmt.Errorf("signature verification failed; please verify account number (%d) and chain-id (%s): %w", accNum, chainID, err)
|
||||||
return ctx, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, errMsg.Error())
|
return ctx, errorsmod.Wrap(errortypes.ErrUnauthorized, errMsg.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
return next(ctx, tx, simulate)
|
return next(ctx, tx, simulate)
|
||||||
@ -150,12 +157,12 @@ func VerifySignature(
|
|||||||
switch data := sigData.(type) {
|
switch data := sigData.(type) {
|
||||||
case *signing.SingleSignatureData:
|
case *signing.SingleSignatureData:
|
||||||
if data.SignMode != signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON {
|
if data.SignMode != signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON {
|
||||||
return sdkerrors.Wrapf(sdkerrors.ErrNotSupported, "unexpected SignatureData %T: wrong SignMode", sigData)
|
return errorsmod.Wrapf(errortypes.ErrNotSupported, "unexpected SignatureData %T: wrong SignMode", sigData)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: this prevents the user from sending thrash data in the signature field
|
// Note: this prevents the user from sending trash data in the signature field
|
||||||
if len(data.Signature) != 0 {
|
if len(data.Signature) != 0 {
|
||||||
return sdkerrors.Wrap(sdkerrors.ErrTooManySignatures, "invalid signature value; EIP712 must have the cosmos transaction signature empty")
|
return errorsmod.Wrap(errortypes.ErrTooManySignatures, "invalid signature value; EIP712 must have the cosmos transaction signature empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
// @contract: this code is reached only when Msg has Web3Tx extension (so this custom Ante handler flow),
|
// @contract: this code is reached only when Msg has Web3Tx extension (so this custom Ante handler flow),
|
||||||
@ -163,7 +170,7 @@ func VerifySignature(
|
|||||||
|
|
||||||
msgs := tx.GetMsgs()
|
msgs := tx.GetMsgs()
|
||||||
if len(msgs) == 0 {
|
if len(msgs) == 0 {
|
||||||
return sdkerrors.Wrap(sdkerrors.ErrNoSignatures, "tx doesn't contain any msgs to verify signature")
|
return errorsmod.Wrap(errortypes.ErrNoSignatures, "tx doesn't contain any msgs to verify signature")
|
||||||
}
|
}
|
||||||
|
|
||||||
txBytes := legacytx.StdSignBytes(
|
txBytes := legacytx.StdSignBytes(
|
||||||
@ -180,33 +187,33 @@ func VerifySignature(
|
|||||||
|
|
||||||
signerChainID, err := ethermint.ParseChainID(signerData.ChainID)
|
signerChainID, err := ethermint.ParseChainID(signerData.ChainID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return sdkerrors.Wrapf(err, "failed to parse chainID: %s", signerData.ChainID)
|
return errorsmod.Wrapf(err, "failed to parse chain-id: %s", signerData.ChainID)
|
||||||
}
|
}
|
||||||
|
|
||||||
txWithExtensions, ok := tx.(authante.HasExtensionOptionsTx)
|
txWithExtensions, ok := tx.(authante.HasExtensionOptionsTx)
|
||||||
if !ok {
|
if !ok {
|
||||||
return sdkerrors.Wrap(sdkerrors.ErrUnknownExtensionOptions, "tx doesnt contain any extensions")
|
return errorsmod.Wrap(errortypes.ErrUnknownExtensionOptions, "tx doesnt contain any extensions")
|
||||||
}
|
}
|
||||||
opts := txWithExtensions.GetExtensionOptions()
|
opts := txWithExtensions.GetExtensionOptions()
|
||||||
if len(opts) != 1 {
|
if len(opts) != 1 {
|
||||||
return sdkerrors.Wrap(sdkerrors.ErrUnknownExtensionOptions, "tx doesnt contain expected amount of extension options")
|
return errorsmod.Wrap(errortypes.ErrUnknownExtensionOptions, "tx doesnt contain expected amount of extension options")
|
||||||
}
|
}
|
||||||
|
|
||||||
extOpt, ok := opts[0].GetCachedValue().(*ethermint.ExtensionOptionsWeb3Tx)
|
extOpt, ok := opts[0].GetCachedValue().(*ethermint.ExtensionOptionsWeb3Tx)
|
||||||
if !ok {
|
if !ok {
|
||||||
return sdkerrors.Wrap(sdkerrors.ErrInvalidChainID, "unknown extension option")
|
return errorsmod.Wrap(errortypes.ErrUnknownExtensionOptions, "unknown extension option")
|
||||||
}
|
}
|
||||||
|
|
||||||
if extOpt.TypedDataChainID != signerChainID.Uint64() {
|
if extOpt.TypedDataChainID != signerChainID.Uint64() {
|
||||||
return sdkerrors.Wrap(sdkerrors.ErrInvalidChainID, "invalid chainID")
|
return errorsmod.Wrap(errortypes.ErrInvalidChainID, "invalid chain-id")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(extOpt.FeePayer) == 0 {
|
if len(extOpt.FeePayer) == 0 {
|
||||||
return sdkerrors.Wrap(sdkerrors.ErrUnknownExtensionOptions, "no feePayer on ExtensionOptionsWeb3Tx")
|
return errorsmod.Wrap(errortypes.ErrUnknownExtensionOptions, "no feePayer on ExtensionOptionsWeb3Tx")
|
||||||
}
|
}
|
||||||
feePayer, err := sdk.AccAddressFromBech32(extOpt.FeePayer)
|
feePayer, err := sdk.AccAddressFromBech32(extOpt.FeePayer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return sdkerrors.Wrap(err, "failed to parse feePayer from ExtensionOptionsWeb3Tx")
|
return errorsmod.Wrap(err, "failed to parse feePayer from ExtensionOptionsWeb3Tx")
|
||||||
}
|
}
|
||||||
|
|
||||||
feeDelegation := &eip712.FeeDelegationOptions{
|
feeDelegation := &eip712.FeeDelegationOptions{
|
||||||
@ -215,17 +222,17 @@ func VerifySignature(
|
|||||||
|
|
||||||
typedData, err := eip712.WrapTxToTypedData(ethermintCodec, extOpt.TypedDataChainID, msgs[0], txBytes, feeDelegation)
|
typedData, err := eip712.WrapTxToTypedData(ethermintCodec, extOpt.TypedDataChainID, msgs[0], txBytes, feeDelegation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return sdkerrors.Wrap(err, "failed to pack tx data in EIP712 object")
|
return errorsmod.Wrap(err, "failed to create EIP-712 typed data from tx")
|
||||||
}
|
}
|
||||||
|
|
||||||
sigHash, err := eip712.ComputeTypedDataHash(typedData)
|
sigHash, _, err := apitypes.TypedDataAndHash(typedData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
feePayerSig := extOpt.FeePayerSig
|
feePayerSig := extOpt.FeePayerSig
|
||||||
if len(feePayerSig) != ethcrypto.SignatureLength {
|
if len(feePayerSig) != ethcrypto.SignatureLength {
|
||||||
return sdkerrors.Wrap(sdkerrors.ErrorInvalidSigner, "signature length doesn't match typical [R||S||V] signature 65 bytes")
|
return errorsmod.Wrap(errortypes.ErrorInvalidSigner, "signature length doesn't match typical [R||S||V] signature 65 bytes")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the recovery offset if needed (ie. Metamask eip712 signature)
|
// Remove the recovery offset if needed (ie. Metamask eip712 signature)
|
||||||
@ -235,12 +242,12 @@ func VerifySignature(
|
|||||||
|
|
||||||
feePayerPubkey, err := secp256k1.RecoverPubkey(sigHash, feePayerSig)
|
feePayerPubkey, err := secp256k1.RecoverPubkey(sigHash, feePayerSig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return sdkerrors.Wrap(err, "failed to recover delegated fee payer from sig")
|
return errorsmod.Wrap(err, "failed to recover delegated fee payer from sig")
|
||||||
}
|
}
|
||||||
|
|
||||||
ecPubKey, err := ethcrypto.UnmarshalPubkey(feePayerPubkey)
|
ecPubKey, err := ethcrypto.UnmarshalPubkey(feePayerPubkey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return sdkerrors.Wrap(err, "failed to unmarshal recovered fee payer pubkey")
|
return errorsmod.Wrap(err, "failed to unmarshal recovered fee payer pubkey")
|
||||||
}
|
}
|
||||||
|
|
||||||
pk := ðsecp256k1.PubKey{
|
pk := ðsecp256k1.PubKey{
|
||||||
@ -248,23 +255,23 @@ func VerifySignature(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !pubKey.Equals(pk) {
|
if !pubKey.Equals(pk) {
|
||||||
return sdkerrors.Wrapf(sdkerrors.ErrInvalidPubKey, "feePayer pubkey %s is different from transaction pubkey %s", pubKey, pk)
|
return errorsmod.Wrapf(errortypes.ErrInvalidPubKey, "feePayer pubkey %s is different from transaction pubkey %s", pubKey, pk)
|
||||||
}
|
}
|
||||||
|
|
||||||
recoveredFeePayerAcc := sdk.AccAddress(pk.Address().Bytes())
|
recoveredFeePayerAcc := sdk.AccAddress(pk.Address().Bytes())
|
||||||
|
|
||||||
if !recoveredFeePayerAcc.Equals(feePayer) {
|
if !recoveredFeePayerAcc.Equals(feePayer) {
|
||||||
return sdkerrors.Wrapf(sdkerrors.ErrorInvalidSigner, "failed to verify delegated fee payer %s signature", recoveredFeePayerAcc)
|
return errorsmod.Wrapf(errortypes.ErrorInvalidSigner, "failed to verify delegated fee payer %s signature", recoveredFeePayerAcc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// VerifySignature of ethsecp256k1 accepts 64 byte signature [R||S]
|
// VerifySignature of ethsecp256k1 accepts 64 byte signature [R||S]
|
||||||
// WARNING! Under NO CIRCUMSTANCES try to use pubKey.VerifySignature there
|
// WARNING! Under NO CIRCUMSTANCES try to use pubKey.VerifySignature there
|
||||||
if !secp256k1.VerifySignature(pubKey.Bytes(), sigHash, feePayerSig[:len(feePayerSig)-1]) {
|
if !secp256k1.VerifySignature(pubKey.Bytes(), sigHash, feePayerSig[:len(feePayerSig)-1]) {
|
||||||
return sdkerrors.Wrap(sdkerrors.ErrorInvalidSigner, "unable to verify signer signature of EIP712 typed data")
|
return errorsmod.Wrap(errortypes.ErrorInvalidSigner, "unable to verify signer signature of EIP712 typed data")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
default:
|
default:
|
||||||
return sdkerrors.Wrapf(sdkerrors.ErrTooManySignatures, "unexpected SignatureData %T", sigData)
|
return errorsmod.Wrapf(errortypes.ErrTooManySignatures, "unexpected SignatureData %T", sigData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
421
app/ante/eth.go
421
app/ante/eth.go
@ -1,19 +1,17 @@
|
|||||||
package ante
|
package ante
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"math"
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
|
errorsmod "cosmossdk.io/errors"
|
||||||
sdkmath "cosmossdk.io/math"
|
sdkmath "cosmossdk.io/math"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
|
||||||
|
|
||||||
ethermint "github.com/evmos/ethermint/types"
|
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"
|
"github.com/evmos/ethermint/x/evm/statedb"
|
||||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||||
|
|
||||||
@ -21,60 +19,6 @@ import (
|
|||||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// EthSigVerificationDecorator validates an ethereum signatures
|
|
||||||
type EthSigVerificationDecorator struct {
|
|
||||||
evmKeeper EVMKeeper
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewEthSigVerificationDecorator creates a new EthSigVerificationDecorator
|
|
||||||
func NewEthSigVerificationDecorator(ek EVMKeeper) EthSigVerificationDecorator {
|
|
||||||
return EthSigVerificationDecorator{
|
|
||||||
evmKeeper: ek,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AnteHandle validates checks that the registered chain id is the same as the one on the message, and
|
|
||||||
// that the signer address matches the one defined on the message.
|
|
||||||
// It's not skipped for RecheckTx, because it set `From` address which is critical from other ante handler to work.
|
|
||||||
// Failure in RecheckTx will prevent tx to be included into block, especially when CheckTx succeed, in which case user
|
|
||||||
// won't see the error message.
|
|
||||||
func (esvd EthSigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
|
||||||
chainID := esvd.evmKeeper.ChainID()
|
|
||||||
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
|
// EthAccountVerificationDecorator validates an account balance checks
|
||||||
type EthAccountVerificationDecorator struct {
|
type EthAccountVerificationDecorator struct {
|
||||||
ak evmtypes.AccountKeeper
|
ak evmtypes.AccountKeeper
|
||||||
@ -108,18 +52,18 @@ func (avd EthAccountVerificationDecorator) AnteHandle(
|
|||||||
for i, msg := range tx.GetMsgs() {
|
for i, msg := range tx.GetMsgs() {
|
||||||
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||||
if !ok {
|
if !ok {
|
||||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
|
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ctx, sdkerrors.Wrapf(err, "failed to unpack tx data any for tx %d", i)
|
return ctx, errorsmod.Wrapf(err, "failed to unpack tx data any for tx %d", i)
|
||||||
}
|
}
|
||||||
|
|
||||||
// sender address should be in the tx cache from the previous AnteHandle call
|
// sender address should be in the tx cache from the previous AnteHandle call
|
||||||
from := msgEthTx.GetFrom()
|
from := msgEthTx.GetFrom()
|
||||||
if from.Empty() {
|
if from.Empty() {
|
||||||
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "from address cannot be empty")
|
return ctx, errorsmod.Wrap(errortypes.ErrInvalidAddress, "from address cannot be empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
// check whether the sender address is EOA
|
// check whether the sender address is EOA
|
||||||
@ -131,12 +75,12 @@ func (avd EthAccountVerificationDecorator) AnteHandle(
|
|||||||
avd.ak.SetAccount(ctx, acc)
|
avd.ak.SetAccount(ctx, acc)
|
||||||
acct = statedb.NewEmptyAccount()
|
acct = statedb.NewEmptyAccount()
|
||||||
} else if acct.IsContract() {
|
} else if acct.IsContract() {
|
||||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidType,
|
return ctx, errorsmod.Wrapf(errortypes.ErrInvalidType,
|
||||||
"the sender is not EOA: address %s, codeHash <%s>", fromAddr, acct.CodeHash)
|
"the sender is not EOA: address %s, codeHash <%s>", fromAddr, acct.CodeHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := evmkeeper.CheckSenderBalance(sdkmath.NewIntFromBigInt(acct.Balance), txData); err != nil {
|
if err := keeper.CheckSenderBalance(sdkmath.NewIntFromBigInt(acct.Balance), txData); err != nil {
|
||||||
return ctx, sdkerrors.Wrap(err, "failed to check sender balance")
|
return ctx, errorsmod.Wrap(err, "failed to check sender balance")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return next(ctx, tx, simulate)
|
return next(ctx, tx, simulate)
|
||||||
@ -164,7 +108,7 @@ func NewEthGasConsumeDecorator(
|
|||||||
// (during CheckTx only) and that the sender has enough balance to pay for the gas cost.
|
// (during CheckTx only) and that the sender has enough balance to pay for the gas cost.
|
||||||
//
|
//
|
||||||
// Intrinsic gas for a transaction is the amount of gas that the transaction uses before the
|
// Intrinsic gas for a transaction is the amount of gas that the transaction uses before the
|
||||||
// transaction is executed. The gas is a constant value plus any cost inccured by additional bytes
|
// transaction is executed. The gas is a constant value plus any cost incurred by additional bytes
|
||||||
// of data supplied with the transaction.
|
// of data supplied with the transaction.
|
||||||
//
|
//
|
||||||
// This AnteHandler decorator will fail if:
|
// This AnteHandler decorator will fail if:
|
||||||
@ -174,29 +118,36 @@ func NewEthGasConsumeDecorator(
|
|||||||
// - user doesn't have enough balance to deduct the transaction fees (gas_limit * gas_price)
|
// - user doesn't have enough balance to deduct the transaction fees (gas_limit * gas_price)
|
||||||
// - transaction or block gas meter runs out of gas
|
// - transaction or block gas meter runs out of gas
|
||||||
// - sets the gas meter limit
|
// - sets the gas meter limit
|
||||||
|
// - gas limit is greater than the block gas meter limit
|
||||||
func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
|
func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
|
||||||
|
// 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)
|
chainCfg := egcd.evmKeeper.GetChainConfig(ctx)
|
||||||
ethCfg := chainCfg.EthereumConfig(egcd.evmKeeper.ChainID())
|
ethCfg := chainCfg.EthereumConfig(egcd.evmKeeper.ChainID())
|
||||||
|
|
||||||
blockHeight := big.NewInt(ctx.BlockHeight())
|
blockHeight := big.NewInt(ctx.BlockHeight())
|
||||||
homestead := ethCfg.IsHomestead(blockHeight)
|
homestead := ethCfg.IsHomestead(blockHeight)
|
||||||
istanbul := ethCfg.IsIstanbul(blockHeight)
|
istanbul := ethCfg.IsIstanbul(blockHeight)
|
||||||
london := ethCfg.IsLondon(blockHeight)
|
|
||||||
gasWanted := uint64(0)
|
gasWanted := uint64(0)
|
||||||
var events sdk.Events
|
var events sdk.Events
|
||||||
|
|
||||||
// Use the lowest priority of all the messages as the final one.
|
// Use the lowest priority of all the messages as the final one.
|
||||||
minPriority := int64(math.MaxInt64)
|
minPriority := int64(math.MaxInt64)
|
||||||
|
baseFee := egcd.evmKeeper.GetBaseFee(ctx, ethCfg)
|
||||||
|
|
||||||
for _, msg := range tx.GetMsgs() {
|
for _, msg := range tx.GetMsgs() {
|
||||||
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||||
if !ok {
|
if !ok {
|
||||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
|
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ctx, sdkerrors.Wrap(err, "failed to unpack tx data")
|
return ctx, errorsmod.Wrap(err, "failed to unpack tx data")
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.IsCheckTx() && egcd.maxGasWanted != 0 {
|
if ctx.IsCheckTx() && egcd.maxGasWanted != 0 {
|
||||||
@ -211,45 +162,58 @@ func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
|
|||||||
}
|
}
|
||||||
|
|
||||||
evmDenom := egcd.evmKeeper.GetEVMDenom(ctx)
|
evmDenom := egcd.evmKeeper.GetEVMDenom(ctx)
|
||||||
fees, priority, err := egcd.evmKeeper.DeductTxCostsFromUserBalance(
|
|
||||||
ctx,
|
fees, err := keeper.VerifyFee(txData, evmDenom, baseFee, homestead, istanbul, ctx.IsCheckTx())
|
||||||
*msgEthTx,
|
|
||||||
txData,
|
|
||||||
evmDenom,
|
|
||||||
homestead,
|
|
||||||
istanbul,
|
|
||||||
london,
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ctx, sdkerrors.Wrapf(err, "failed to deduct transaction costs from user balance")
|
return ctx, errorsmod.Wrapf(err, "failed to verify the fees")
|
||||||
}
|
}
|
||||||
|
|
||||||
events = append(events, sdk.NewEvent(sdk.EventTypeTx, sdk.NewAttribute(sdk.AttributeKeyFee, fees.String())))
|
err = egcd.evmKeeper.DeductTxCostsFromUserBalance(ctx, fees, common.HexToAddress(msgEthTx.From))
|
||||||
|
if err != nil {
|
||||||
|
return ctx, errorsmod.Wrapf(err, "failed to deduct transaction costs from user balance")
|
||||||
|
}
|
||||||
|
|
||||||
|
events = append(events,
|
||||||
|
sdk.NewEvent(
|
||||||
|
sdk.EventTypeTx,
|
||||||
|
sdk.NewAttribute(sdk.AttributeKeyFee, fees.String()),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
priority := evmtypes.GetTxPriority(txData, baseFee)
|
||||||
|
|
||||||
if priority < minPriority {
|
if priority < minPriority {
|
||||||
minPriority = priority
|
minPriority = priority
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: change to typed events
|
|
||||||
ctx.EventManager().EmitEvents(events)
|
ctx.EventManager().EmitEvents(events)
|
||||||
|
|
||||||
// TODO: deprecate after https://github.com/cosmos/cosmos-sdk/issues/9514 is fixed on SDK
|
|
||||||
blockGasLimit := ethermint.BlockGasLimit(ctx)
|
blockGasLimit := ethermint.BlockGasLimit(ctx)
|
||||||
|
|
||||||
// NOTE: safety check
|
// return error if the tx gas is greater than the block limit (max gas)
|
||||||
if blockGasLimit > 0 {
|
|
||||||
// generate a copy of the gas pool (i.e block gas meter) to see if we've run out of gas for this block
|
// NOTE: it's important here to use the gas wanted instead of the gas consumed
|
||||||
// if current gas consumed is greater than the limit, this funcion panics and the error is recovered on the Baseapp
|
// from the tx gas pool. The later only has the value so far since the
|
||||||
gasPool := sdk.NewGasMeter(blockGasLimit)
|
// EthSetupContextDecorator so it will never exceed the block gas limit.
|
||||||
gasPool.ConsumeGas(ctx.GasMeter().GasConsumedToLimit(), "gas pool check")
|
if gasWanted > blockGasLimit {
|
||||||
|
return ctx, errorsmod.Wrapf(
|
||||||
|
errortypes.ErrOutOfGas,
|
||||||
|
"tx gas (%d) exceeds block gas limit (%d)",
|
||||||
|
gasWanted,
|
||||||
|
blockGasLimit,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set ctx.GasMeter with a limit of GasWanted (gasLimit)
|
// Set tx GasMeter with a limit of GasWanted (i.e gas limit from the Ethereum tx).
|
||||||
gasConsumed := ctx.GasMeter().GasConsumed()
|
// The gas consumed will be then reset to the gas used by the state transition
|
||||||
ctx = ctx.WithGasMeter(ethermint.NewInfiniteGasMeterWithLimit(gasWanted))
|
// in the EVM.
|
||||||
ctx.GasMeter().ConsumeGas(gasConsumed, "copy gas consumed")
|
|
||||||
|
|
||||||
newCtx := ctx.WithPriority(minPriority)
|
// FIXME: use a custom gas configuration that doesn't add any additional gas and only
|
||||||
|
// takes into account the gas consumed at the end of the EVM transaction.
|
||||||
|
newCtx := ctx.
|
||||||
|
WithGasMeter(ethermint.NewInfiniteGasMeterWithLimit(gasWanted)).
|
||||||
|
WithPriority(minPriority)
|
||||||
|
|
||||||
// we know that we have enough gas on the pool to cover the intrinsic gas
|
// we know that we have enough gas on the pool to cover the intrinsic gas
|
||||||
return next(newCtx, tx, simulate)
|
return next(newCtx, tx, simulate)
|
||||||
@ -278,19 +242,35 @@ func (ctd CanTransferDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate
|
|||||||
for _, msg := range tx.GetMsgs() {
|
for _, msg := range tx.GetMsgs() {
|
||||||
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||||
if !ok {
|
if !ok {
|
||||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
baseFee := ctd.evmKeeper.GetBaseFee(ctx, ethCfg)
|
baseFee := ctd.evmKeeper.GetBaseFee(ctx, ethCfg)
|
||||||
|
|
||||||
coreMsg, err := msgEthTx.AsMessage(signer, baseFee)
|
coreMsg, err := msgEthTx.AsMessage(signer, baseFee)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ctx, sdkerrors.Wrapf(
|
return ctx, errorsmod.Wrapf(
|
||||||
err,
|
err,
|
||||||
"failed to create an ethereum core.Message from signer %T", signer,
|
"failed to create an ethereum core.Message from signer %T", signer,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if evmtypes.IsLondon(ethCfg, ctx.BlockHeight()) {
|
||||||
|
if baseFee == nil {
|
||||||
|
return ctx, errorsmod.Wrap(
|
||||||
|
evmtypes.ErrInvalidBaseFee,
|
||||||
|
"base fee is supported but evm block context value is nil",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if coreMsg.GasFeeCap().Cmp(baseFee) < 0 {
|
||||||
|
return ctx, errorsmod.Wrapf(
|
||||||
|
errortypes.ErrInsufficientFee,
|
||||||
|
"max fee per gas less than block base fee (%s < %s)",
|
||||||
|
coreMsg.GasFeeCap(), baseFee,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE: pass in an empty coinbase address and nil tracer as we don't need them for the check below
|
// NOTE: pass in an empty coinbase address and nil tracer as we don't need them for the check below
|
||||||
cfg := &evmtypes.EVMConfig{
|
cfg := &evmtypes.EVMConfig{
|
||||||
ChainConfig: ethCfg,
|
ChainConfig: ethCfg,
|
||||||
@ -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
|
// check that caller has enough balance to cover asset transfer for **topmost** call
|
||||||
// NOTE: here the gas consumed is from the context with the infinite gas meter
|
// NOTE: here the gas consumed is from the context with the infinite gas meter
|
||||||
if coreMsg.Value().Sign() > 0 && !evm.Context().CanTransfer(stateDB, coreMsg.From(), coreMsg.Value()) {
|
if coreMsg.Value().Sign() > 0 && !evm.Context().CanTransfer(stateDB, coreMsg.From(), coreMsg.Value()) {
|
||||||
return ctx, sdkerrors.Wrapf(
|
return ctx, errorsmod.Wrapf(
|
||||||
sdkerrors.ErrInsufficientFunds,
|
errortypes.ErrInsufficientFunds,
|
||||||
"failed to transfer %s from address %s using the EVM block context transfer function",
|
"failed to transfer %s from address %s using the EVM block context transfer function",
|
||||||
coreMsg.Value(),
|
coreMsg.Value(),
|
||||||
coreMsg.From(),
|
coreMsg.From(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if evmtypes.IsLondon(ethCfg, ctx.BlockHeight()) {
|
|
||||||
if baseFee == nil {
|
|
||||||
return ctx, sdkerrors.Wrap(
|
|
||||||
evmtypes.ErrInvalidBaseFee,
|
|
||||||
"base fee is supported but evm block context value is nil",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if coreMsg.GasFeeCap().Cmp(baseFee) < 0 {
|
|
||||||
return ctx, sdkerrors.Wrapf(
|
|
||||||
sdkerrors.ErrInsufficientFee,
|
|
||||||
"max fee per gas less than block base fee (%s < %s)",
|
|
||||||
coreMsg.GasFeeCap(), baseFee,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return next(ctx, tx, simulate)
|
return next(ctx, tx, simulate)
|
||||||
@ -351,19 +315,19 @@ func (issd EthIncrementSenderSequenceDecorator) AnteHandle(ctx sdk.Context, tx s
|
|||||||
for _, msg := range tx.GetMsgs() {
|
for _, msg := range tx.GetMsgs() {
|
||||||
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||||
if !ok {
|
if !ok {
|
||||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
|
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ctx, sdkerrors.Wrap(err, "failed to unpack tx data")
|
return ctx, errorsmod.Wrap(err, "failed to unpack tx data")
|
||||||
}
|
}
|
||||||
|
|
||||||
// increase sequence of sender
|
// increase sequence of sender
|
||||||
acc := issd.ak.GetAccount(ctx, msgEthTx.GetFrom())
|
acc := issd.ak.GetAccount(ctx, msgEthTx.GetFrom())
|
||||||
if acc == nil {
|
if acc == nil {
|
||||||
return ctx, sdkerrors.Wrapf(
|
return ctx, errorsmod.Wrapf(
|
||||||
sdkerrors.ErrUnknownAddress,
|
errortypes.ErrUnknownAddress,
|
||||||
"account %s is nil", common.BytesToAddress(msgEthTx.GetFrom().Bytes()),
|
"account %s is nil", common.BytesToAddress(msgEthTx.GetFrom().Bytes()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -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
|
// we merged the nonce verification to nonce increment, so when tx includes multiple messages
|
||||||
// with same sender, they'll be accepted.
|
// with same sender, they'll be accepted.
|
||||||
if txData.GetNonce() != nonce {
|
if txData.GetNonce() != nonce {
|
||||||
return ctx, sdkerrors.Wrapf(
|
return ctx, errorsmod.Wrapf(
|
||||||
sdkerrors.ErrInvalidSequence,
|
errortypes.ErrInvalidSequence,
|
||||||
"invalid nonce; got %d, expected %d", txData.GetNonce(), nonce,
|
"invalid nonce; got %d, expected %d", txData.GetNonce(), nonce,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := acc.SetSequence(nonce + 1); err != nil {
|
if err := acc.SetSequence(nonce + 1); err != nil {
|
||||||
return ctx, sdkerrors.Wrapf(err, "failed to set sequence to %d", acc.GetSequence()+1)
|
return ctx, errorsmod.Wrapf(err, "failed to set sequence to %d", acc.GetSequence()+1)
|
||||||
}
|
}
|
||||||
|
|
||||||
issd.ak.SetAccount(ctx, acc)
|
issd.ak.SetAccount(ctx, acc)
|
||||||
@ -387,220 +351,3 @@ func (issd EthIncrementSenderSequenceDecorator) AnteHandle(ctx sdk.Context, tx s
|
|||||||
|
|
||||||
return next(ctx, tx, simulate)
|
return next(ctx, tx, simulate)
|
||||||
}
|
}
|
||||||
|
|
||||||
// EthValidateBasicDecorator is adapted from ValidateBasicDecorator from cosmos-sdk, it ignores ErrNoSignatures
|
|
||||||
type EthValidateBasicDecorator struct {
|
|
||||||
evmKeeper EVMKeeper
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewEthValidateBasicDecorator creates a new EthValidateBasicDecorator
|
|
||||||
func NewEthValidateBasicDecorator(ek EVMKeeper) EthValidateBasicDecorator {
|
|
||||||
return EthValidateBasicDecorator{
|
|
||||||
evmKeeper: ek,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AnteHandle handles basic validation of tx
|
|
||||||
func (vbd EthValidateBasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
|
|
||||||
// no need to validate basic on recheck tx, call next antehandler
|
|
||||||
if ctx.IsReCheckTx() {
|
|
||||||
return next(ctx, tx, simulate)
|
|
||||||
}
|
|
||||||
|
|
||||||
err := tx.ValidateBasic()
|
|
||||||
// ErrNoSignatures is fine with eth tx
|
|
||||||
if err != nil && !errors.Is(err, sdkerrors.ErrNoSignatures) {
|
|
||||||
return ctx, sdkerrors.Wrap(err, "tx basic validation failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
// For eth type cosmos tx, some fields should be veified as zero values,
|
|
||||||
// since we will only verify the signature against the hash of the MsgEthereumTx.Data
|
|
||||||
wrapperTx, ok := tx.(protoTxProvider)
|
|
||||||
if !ok {
|
|
||||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid tx type %T, didn't implement interface protoTxProvider", tx)
|
|
||||||
}
|
|
||||||
|
|
||||||
protoTx := wrapperTx.GetProtoTx()
|
|
||||||
body := protoTx.Body
|
|
||||||
if body.Memo != "" || body.TimeoutHeight != uint64(0) || len(body.NonCriticalExtensionOptions) > 0 {
|
|
||||||
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest,
|
|
||||||
"for eth tx body Memo TimeoutHeight NonCriticalExtensionOptions should be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(body.ExtensionOptions) != 1 {
|
|
||||||
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx length of ExtensionOptions should be 1")
|
|
||||||
}
|
|
||||||
|
|
||||||
txFee := sdk.Coins{}
|
|
||||||
txGasLimit := uint64(0)
|
|
||||||
|
|
||||||
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"
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (suite AnteTestSuite) TestEthSigVerificationDecorator() {
|
|
||||||
addr, privKey := tests.NewAddrKey()
|
|
||||||
|
|
||||||
signedTx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
|
|
||||||
signedTx.From = addr.Hex()
|
|
||||||
err := signedTx.Sign(suite.ethSigner, tests.NewSigner(privKey))
|
|
||||||
suite.Require().NoError(err)
|
|
||||||
|
|
||||||
unprotectedTx := evmtypes.NewTxContract(nil, 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
|
|
||||||
unprotectedTx.From = addr.Hex()
|
|
||||||
err = unprotectedTx.Sign(ethtypes.HomesteadSigner{}, tests.NewSigner(privKey))
|
|
||||||
suite.Require().NoError(err)
|
|
||||||
|
|
||||||
testCases := []struct {
|
|
||||||
name string
|
|
||||||
tx sdk.Tx
|
|
||||||
allowUnprotectedTxs bool
|
|
||||||
reCheckTx bool
|
|
||||||
expPass bool
|
|
||||||
}{
|
|
||||||
{"ReCheckTx", &invalidTx{}, false, true, false},
|
|
||||||
{"invalid transaction type", &invalidTx{}, false, false, false},
|
|
||||||
{
|
|
||||||
"invalid sender",
|
|
||||||
evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 1, &addr, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil),
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
{"successful signature verification", signedTx, false, false, true},
|
|
||||||
{"invalid, reject unprotected txs", unprotectedTx, false, false, false},
|
|
||||||
{"successful, allow unprotected txs", unprotectedTx, true, false, true},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range testCases {
|
|
||||||
suite.Run(tc.name, func() {
|
|
||||||
suite.evmParamsOption = func(params *evmtypes.Params) {
|
|
||||||
params.AllowUnprotectedTxs = tc.allowUnprotectedTxs
|
|
||||||
}
|
|
||||||
suite.SetupTest()
|
|
||||||
dec := ante.NewEthSigVerificationDecorator(suite.app.EvmKeeper)
|
|
||||||
_, err := dec.AnteHandle(suite.ctx.WithIsReCheckTx(tc.reCheckTx), tc.tx, false, NextFn)
|
|
||||||
|
|
||||||
if tc.expPass {
|
|
||||||
suite.Require().NoError(err)
|
|
||||||
} else {
|
|
||||||
suite.Require().Error(err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
suite.evmParamsOption = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (suite AnteTestSuite) TestNewEthAccountVerificationDecorator() {
|
func (suite AnteTestSuite) TestNewEthAccountVerificationDecorator() {
|
||||||
dec := ante.NewEthAccountVerificationDecorator(
|
dec := ante.NewEthAccountVerificationDecorator(
|
||||||
suite.app.AccountKeeper, suite.app.EvmKeeper,
|
suite.app.AccountKeeper, suite.app.EvmKeeper,
|
||||||
@ -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"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
|
|
||||||
|
errorsmod "cosmossdk.io/errors"
|
||||||
sdkmath "cosmossdk.io/math"
|
sdkmath "cosmossdk.io/math"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||||
ethermint "github.com/evmos/ethermint/types"
|
ethermint "github.com/evmos/ethermint/types"
|
||||||
"github.com/evmos/ethermint/x/evm/types"
|
"github.com/evmos/ethermint/x/evm/types"
|
||||||
@ -64,7 +65,7 @@ func NewDynamicFeeChecker(k DynamicFeeEVMKeeper) authante.TxFeeChecker {
|
|||||||
baseFeeInt := sdkmath.NewIntFromBigInt(baseFee)
|
baseFeeInt := sdkmath.NewIntFromBigInt(baseFee)
|
||||||
|
|
||||||
if feeCap.LT(baseFeeInt) {
|
if feeCap.LT(baseFeeInt) {
|
||||||
return nil, 0, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "insufficient gas prices; got: %s required: %s", feeCap, baseFeeInt)
|
return nil, 0, errorsmod.Wrapf(errortypes.ErrInsufficientFee, "insufficient gas prices; got: %s required: %s", feeCap, baseFeeInt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate the effective gas price using the EIP-1559 logic.
|
// calculate the effective gas price using the EIP-1559 logic.
|
||||||
@ -112,7 +113,7 @@ func checkTxFeeWithValidatorMinGasPrices(ctx sdk.Context, tx sdk.FeeTx) (sdk.Coi
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !feeCoins.IsAnyGTE(requiredFees) {
|
if !feeCoins.IsAnyGTE(requiredFees) {
|
||||||
return nil, 0, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "insufficient fees; got: %s required: %s", feeCoins, requiredFees)
|
return nil, 0, errorsmod.Wrapf(errortypes.ErrInsufficientFee, "insufficient fees; got: %s required: %s", feeCoins, requiredFees)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,8 +3,8 @@ package ante
|
|||||||
import (
|
import (
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
errorsmod "cosmossdk.io/errors"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// GasWantedDecorator keeps track of the gasWanted amount on the current block in transient store
|
// GasWantedDecorator keeps track of the gasWanted amount on the current block in transient store
|
||||||
@ -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
|
// Add total gasWanted to cumulative in block transientStore in FeeMarket module
|
||||||
if isBaseFeeEnabled {
|
if isBaseFeeEnabled {
|
||||||
if _, err := gwd.feeMarketKeeper.AddTransientGasWanted(ctx, gasWanted); err != nil {
|
if _, err := gwd.feeMarketKeeper.AddTransientGasWanted(ctx, gasWanted); err != nil {
|
||||||
return ctx, sdkerrors.Wrapf(err, "failed to add gas wanted to transient store")
|
return ctx, errorsmod.Wrapf(err, "failed to add gas wanted to transient store")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
110
app/ante/fees.go
110
app/ante/fees.go
@ -3,8 +3,9 @@ package ante
|
|||||||
import (
|
import (
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
errorsmod "cosmossdk.io/errors"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
|
|
||||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||||
@ -20,14 +21,50 @@ type MinGasPriceDecorator struct {
|
|||||||
evmKeeper EVMKeeper
|
evmKeeper EVMKeeper
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EthMinGasPriceDecorator will check if the transaction's fee is at least as large
|
||||||
|
// as the MinGasPrices param. If fee is too low, decorator returns error and tx
|
||||||
|
// is rejected. This applies to both CheckTx and DeliverTx and regardless
|
||||||
|
// if London hard fork or fee market params (EIP-1559) are enabled.
|
||||||
|
// If fee is high enough, then call next AnteHandler
|
||||||
|
type EthMinGasPriceDecorator struct {
|
||||||
|
feesKeeper FeeMarketKeeper
|
||||||
|
evmKeeper EVMKeeper
|
||||||
|
}
|
||||||
|
|
||||||
|
// EthMempoolFeeDecorator will check if the transaction's effective fee is at least as large
|
||||||
|
// as the local validator's minimum gasFee (defined in validator config).
|
||||||
|
// If fee is too low, decorator returns error and tx is rejected from mempool.
|
||||||
|
// Note this only applies when ctx.CheckTx = true
|
||||||
|
// If fee is high enough or not CheckTx, then call next AnteHandler
|
||||||
|
// CONTRACT: Tx must implement FeeTx to use MempoolFeeDecorator
|
||||||
|
type EthMempoolFeeDecorator struct {
|
||||||
|
evmKeeper EVMKeeper
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMinGasPriceDecorator creates a new MinGasPriceDecorator instance used only for
|
||||||
|
// Cosmos transactions.
|
||||||
func NewMinGasPriceDecorator(fk FeeMarketKeeper, ek EVMKeeper) MinGasPriceDecorator {
|
func NewMinGasPriceDecorator(fk FeeMarketKeeper, ek EVMKeeper) MinGasPriceDecorator {
|
||||||
return MinGasPriceDecorator{feesKeeper: fk, evmKeeper: ek}
|
return MinGasPriceDecorator{feesKeeper: fk, evmKeeper: ek}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewEthMinGasPriceDecorator creates a new MinGasPriceDecorator instance used only for
|
||||||
|
// Ethereum transactions.
|
||||||
|
func NewEthMinGasPriceDecorator(fk FeeMarketKeeper, ek EVMKeeper) EthMinGasPriceDecorator {
|
||||||
|
return EthMinGasPriceDecorator{feesKeeper: fk, evmKeeper: ek}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewEthMempoolFeeDecorator creates a new NewEthMempoolFeeDecorator instance used only for
|
||||||
|
// Ethereum transactions.
|
||||||
|
func NewEthMempoolFeeDecorator(ek EVMKeeper) EthMempoolFeeDecorator {
|
||||||
|
return EthMempoolFeeDecorator{
|
||||||
|
evmKeeper: ek,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (mpd MinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
func (mpd MinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||||
feeTx, ok := tx.(sdk.FeeTx)
|
feeTx, ok := tx.(sdk.FeeTx)
|
||||||
if !ok {
|
if !ok {
|
||||||
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx")
|
return ctx, errorsmod.Wrapf(errortypes.ErrInvalidType, "invalid transaction type %T, expected sdk.FeeTx", tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
minGasPrice := mpd.feesKeeper.GetParams(ctx).MinGasPrice
|
minGasPrice := mpd.feesKeeper.GetParams(ctx).MinGasPrice
|
||||||
@ -62,7 +99,7 @@ func (mpd MinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !feeCoins.IsAnyGTE(requiredFees) {
|
if !feeCoins.IsAnyGTE(requiredFees) {
|
||||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee,
|
return ctx, errorsmod.Wrapf(errortypes.ErrInsufficientFee,
|
||||||
"provided fee < minimum global fee (%s < %s). Please increase the gas price.",
|
"provided fee < minimum global fee (%s < %s). Please increase the gas price.",
|
||||||
feeCoins,
|
feeCoins,
|
||||||
requiredFees)
|
requiredFees)
|
||||||
@ -71,20 +108,8 @@ func (mpd MinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate
|
|||||||
return next(ctx, tx, simulate)
|
return next(ctx, tx, simulate)
|
||||||
}
|
}
|
||||||
|
|
||||||
// EthMinGasPriceDecorator will check if the transaction's fee is at least as large
|
// AnteHandle ensures that the that the effective fee from the transaction is greater than the
|
||||||
// as the MinGasPrices param. If fee is too low, decorator returns error and tx
|
// minimum global fee, which is defined by the MinGasPrice (parameter) * GasLimit (tx argument).
|
||||||
// is rejected. This applies to both CheckTx and DeliverTx and regardless
|
|
||||||
// if London hard fork or fee market params (EIP-1559) are enabled.
|
|
||||||
// If fee is high enough, then call next AnteHandler
|
|
||||||
type EthMinGasPriceDecorator struct {
|
|
||||||
feesKeeper FeeMarketKeeper
|
|
||||||
evmKeeper EVMKeeper
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewEthMinGasPriceDecorator(fk FeeMarketKeeper, ek EVMKeeper) EthMinGasPriceDecorator {
|
|
||||||
return EthMinGasPriceDecorator{feesKeeper: fk, evmKeeper: ek}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (empd EthMinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
func (empd EthMinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||||
minGasPrice := empd.feesKeeper.GetParams(ctx).MinGasPrice
|
minGasPrice := empd.feesKeeper.GetParams(ctx).MinGasPrice
|
||||||
|
|
||||||
@ -100,8 +125,8 @@ func (empd EthMinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simul
|
|||||||
for _, msg := range tx.GetMsgs() {
|
for _, msg := range tx.GetMsgs() {
|
||||||
ethMsg, ok := msg.(*evmtypes.MsgEthereumTx)
|
ethMsg, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||||
if !ok {
|
if !ok {
|
||||||
return ctx, sdkerrors.Wrapf(
|
return ctx, errorsmod.Wrapf(
|
||||||
sdkerrors.ErrUnknownRequest,
|
errortypes.ErrUnknownRequest,
|
||||||
"invalid message type %T, expected %T",
|
"invalid message type %T, expected %T",
|
||||||
msg, (*evmtypes.MsgEthereumTx)(nil),
|
msg, (*evmtypes.MsgEthereumTx)(nil),
|
||||||
)
|
)
|
||||||
@ -120,7 +145,7 @@ func (empd EthMinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simul
|
|||||||
|
|
||||||
txData, err := evmtypes.UnpackTxData(ethMsg.Data)
|
txData, err := evmtypes.UnpackTxData(ethMsg.Data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ctx, sdkerrors.Wrapf(err, "failed to unpack tx data %s", ethMsg.Hash)
|
return ctx, errorsmod.Wrapf(err, "failed to unpack tx data %s", ethMsg.Hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
if txData.TxType() != ethtypes.LegacyTxType {
|
if txData.TxType() != ethtypes.LegacyTxType {
|
||||||
@ -133,8 +158,8 @@ func (empd EthMinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simul
|
|||||||
fee := sdk.NewDecFromBigInt(feeAmt)
|
fee := sdk.NewDecFromBigInt(feeAmt)
|
||||||
|
|
||||||
if fee.LT(requiredFee) {
|
if fee.LT(requiredFee) {
|
||||||
return ctx, sdkerrors.Wrapf(
|
return ctx, errorsmod.Wrapf(
|
||||||
sdkerrors.ErrInsufficientFee,
|
errortypes.ErrInsufficientFee,
|
||||||
"provided fee < minimum global fee (%d < %d). Please increase the priority tip (for EIP-1559 txs) or the gas prices (for access list or legacy txs)", //nolint:lll
|
"provided fee < minimum global fee (%d < %d). Please increase the priority tip (for EIP-1559 txs) or the gas prices (for access list or legacy txs)", //nolint:lll
|
||||||
fee.TruncateInt().Int64(), requiredFee.TruncateInt().Int64(),
|
fee.TruncateInt().Int64(), requiredFee.TruncateInt().Int64(),
|
||||||
)
|
)
|
||||||
@ -143,3 +168,44 @@ func (empd EthMinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simul
|
|||||||
|
|
||||||
return next(ctx, tx, simulate)
|
return next(ctx, tx, simulate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AnteHandle ensures that the provided fees meet a minimum threshold for the validator.
|
||||||
|
// This check only for local mempool purposes, and thus it is only run on (Re)CheckTx.
|
||||||
|
// The logic is also skipped if the London hard fork and EIP-1559 are enabled.
|
||||||
|
func (mfd EthMempoolFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||||
|
if !ctx.IsCheckTx() || simulate {
|
||||||
|
return next(ctx, tx, simulate)
|
||||||
|
}
|
||||||
|
chainCfg := mfd.evmKeeper.GetChainConfig(ctx)
|
||||||
|
ethCfg := chainCfg.EthereumConfig(mfd.evmKeeper.ChainID())
|
||||||
|
|
||||||
|
baseFee := mfd.evmKeeper.GetBaseFee(ctx, ethCfg)
|
||||||
|
// skip check as the London hard fork and EIP-1559 are enabled
|
||||||
|
if baseFee != nil {
|
||||||
|
return next(ctx, tx, simulate)
|
||||||
|
}
|
||||||
|
|
||||||
|
evmDenom := mfd.evmKeeper.GetEVMDenom(ctx)
|
||||||
|
minGasPrice := ctx.MinGasPrices().AmountOf(evmDenom)
|
||||||
|
|
||||||
|
for _, msg := range tx.GetMsgs() {
|
||||||
|
ethMsg, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||||
|
if !ok {
|
||||||
|
return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
fee := sdk.NewDecFromBigInt(ethMsg.GetFee())
|
||||||
|
gasLimit := sdk.NewDecFromBigInt(new(big.Int).SetUint64(ethMsg.GetGas()))
|
||||||
|
requiredFee := minGasPrice.Mul(gasLimit)
|
||||||
|
|
||||||
|
if fee.LT(requiredFee) {
|
||||||
|
return ctx, errorsmod.Wrapf(
|
||||||
|
errortypes.ErrInsufficientFee,
|
||||||
|
"insufficient fee; got: %s required: %s",
|
||||||
|
fee, requiredFee,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return next(ctx, tx, simulate)
|
||||||
|
}
|
||||||
|
@ -42,7 +42,7 @@ func (s AnteTestSuite) TestMinGasPriceDecorator() {
|
|||||||
return &invalidTx{}
|
return &invalidTx{}
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
"must be a FeeTx",
|
"invalid transaction type",
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -345,3 +345,7 @@ func (s AnteTestSuite) TestEthMinGasPriceDecorator() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (suite AnteTestSuite) TestEthMempoolFeeDecorator() {
|
||||||
|
// TODO: add test
|
||||||
|
}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
package ante
|
package ante
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
errorsmod "cosmossdk.io/errors"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||||
"github.com/cosmos/cosmos-sdk/x/auth/ante"
|
"github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||||
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||||
@ -32,19 +33,19 @@ type HandlerOptions struct {
|
|||||||
|
|
||||||
func (options HandlerOptions) validate() error {
|
func (options HandlerOptions) validate() error {
|
||||||
if options.AccountKeeper == nil {
|
if options.AccountKeeper == nil {
|
||||||
return sdkerrors.Wrap(sdkerrors.ErrLogic, "account keeper is required for AnteHandler")
|
return errorsmod.Wrap(errortypes.ErrLogic, "account keeper is required for AnteHandler")
|
||||||
}
|
}
|
||||||
if options.BankKeeper == nil {
|
if options.BankKeeper == nil {
|
||||||
return sdkerrors.Wrap(sdkerrors.ErrLogic, "bank keeper is required for AnteHandler")
|
return errorsmod.Wrap(errortypes.ErrLogic, "bank keeper is required for AnteHandler")
|
||||||
}
|
}
|
||||||
if options.SignModeHandler == nil {
|
if options.SignModeHandler == nil {
|
||||||
return sdkerrors.Wrap(sdkerrors.ErrLogic, "sign mode handler is required for ante builder")
|
return errorsmod.Wrap(errortypes.ErrLogic, "sign mode handler is required for ante builder")
|
||||||
}
|
}
|
||||||
if options.FeeMarketKeeper == nil {
|
if options.FeeMarketKeeper == nil {
|
||||||
return sdkerrors.Wrap(sdkerrors.ErrLogic, "fee market keeper is required for AnteHandler")
|
return errorsmod.Wrap(errortypes.ErrLogic, "fee market keeper is required for AnteHandler")
|
||||||
}
|
}
|
||||||
if options.EvmKeeper == nil {
|
if options.EvmKeeper == nil {
|
||||||
return sdkerrors.Wrap(sdkerrors.ErrLogic, "evm keeper is required for AnteHandler")
|
return errorsmod.Wrap(errortypes.ErrLogic, "evm keeper is required for AnteHandler")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -28,9 +28,7 @@ type EVMKeeper interface {
|
|||||||
DynamicFeeEVMKeeper
|
DynamicFeeEVMKeeper
|
||||||
|
|
||||||
NewEVM(ctx sdk.Context, msg core.Message, cfg *evmtypes.EVMConfig, tracer vm.EVMLogger, stateDB vm.StateDB) evm.EVM
|
NewEVM(ctx sdk.Context, msg core.Message, cfg *evmtypes.EVMConfig, tracer vm.EVMLogger, stateDB vm.StateDB) evm.EVM
|
||||||
DeductTxCostsFromUserBalance(
|
DeductTxCostsFromUserBalance(ctx sdk.Context, fees sdk.Coins, from common.Address) error
|
||||||
ctx sdk.Context, msgEthTx evmtypes.MsgEthereumTx, txData evmtypes.TxData, denom string, homestead, istanbul, london bool,
|
|
||||||
) (fees sdk.Coins, priority int64, err error)
|
|
||||||
GetBalance(ctx sdk.Context, addr common.Address) *big.Int
|
GetBalance(ctx sdk.Context, addr common.Address) *big.Int
|
||||||
ResetTransientGasUsed(ctx sdk.Context)
|
ResetTransientGasUsed(ctx sdk.Context)
|
||||||
GetTxIndexTransient(ctx sdk.Context) uint64
|
GetTxIndexTransient(ctx sdk.Context) uint64
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
package ante
|
package ante
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
errorsmod "cosmossdk.io/errors"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
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) {
|
func (rmd RejectMessagesDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||||
for _, msg := range tx.GetMsgs() {
|
for _, msg := range tx.GetMsgs() {
|
||||||
if _, ok := msg.(*evmtypes.MsgEthereumTx); ok {
|
if _, ok := msg.(*evmtypes.MsgEthereumTx); ok {
|
||||||
return ctx, sdkerrors.Wrapf(
|
return ctx, errorsmod.Wrapf(
|
||||||
sdkerrors.ErrInvalidType,
|
errortypes.ErrInvalidType,
|
||||||
"MsgEthereumTx needs to be contained within a tx with 'ExtensionOptionsEthereumTx' option",
|
"MsgEthereumTx needs to be contained within a tx with 'ExtensionOptionsEthereumTx' option",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
189
app/ante/setup.go
Normal file
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/codec"
|
||||||
"github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx"
|
"github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx"
|
||||||
types2 "github.com/cosmos/cosmos-sdk/x/bank/types"
|
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||||
types3 "github.com/cosmos/cosmos-sdk/x/staking/types"
|
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
||||||
"github.com/evmos/ethermint/ethereum/eip712"
|
"github.com/evmos/ethermint/ethereum/eip712"
|
||||||
"github.com/evmos/ethermint/types"
|
"github.com/evmos/ethermint/types"
|
||||||
|
|
||||||
@ -25,21 +26,27 @@ import (
|
|||||||
"github.com/cosmos/cosmos-sdk/client"
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||||
|
kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
|
||||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
|
||||||
"github.com/cosmos/cosmos-sdk/simapp"
|
"github.com/cosmos/cosmos-sdk/simapp"
|
||||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
|
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
|
||||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||||
|
sdkante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||||
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||||
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
|
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
|
||||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||||
|
authz "github.com/cosmos/cosmos-sdk/x/authz"
|
||||||
cryptocodec "github.com/evmos/ethermint/crypto/codec"
|
cryptocodec "github.com/evmos/ethermint/crypto/codec"
|
||||||
|
"github.com/evmos/ethermint/crypto/ethsecp256k1"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
||||||
evtypes "github.com/cosmos/cosmos-sdk/x/evidence/types"
|
evtypes "github.com/cosmos/cosmos-sdk/x/evidence/types"
|
||||||
"github.com/cosmos/cosmos-sdk/x/feegrant"
|
"github.com/cosmos/cosmos-sdk/x/feegrant"
|
||||||
types5 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
|
govtypesv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
|
||||||
|
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
|
||||||
"github.com/evmos/ethermint/app"
|
"github.com/evmos/ethermint/app"
|
||||||
ante "github.com/evmos/ethermint/app/ante"
|
ante "github.com/evmos/ethermint/app/ante"
|
||||||
"github.com/evmos/ethermint/encoding"
|
"github.com/evmos/ethermint/encoding"
|
||||||
@ -92,6 +99,8 @@ func (suite *AnteTestSuite) SetupTest() {
|
|||||||
evmGenesis.Params.ChainConfig.ArrowGlacierBlock = &maxInt
|
evmGenesis.Params.ChainConfig.ArrowGlacierBlock = &maxInt
|
||||||
evmGenesis.Params.ChainConfig.GrayGlacierBlock = &maxInt
|
evmGenesis.Params.ChainConfig.GrayGlacierBlock = &maxInt
|
||||||
evmGenesis.Params.ChainConfig.MergeNetsplitBlock = &maxInt
|
evmGenesis.Params.ChainConfig.MergeNetsplitBlock = &maxInt
|
||||||
|
evmGenesis.Params.ChainConfig.ShanghaiBlock = &maxInt
|
||||||
|
evmGenesis.Params.ChainConfig.CancunBlock = &maxInt
|
||||||
}
|
}
|
||||||
if suite.evmParamsOption != nil {
|
if suite.evmParamsOption != nil {
|
||||||
suite.evmParamsOption(&evmGenesis.Params)
|
suite.evmParamsOption(&evmGenesis.Params)
|
||||||
@ -111,6 +120,7 @@ func (suite *AnteTestSuite) SetupTest() {
|
|||||||
encodingConfig := encoding.MakeConfig(app.ModuleBasics)
|
encodingConfig := encoding.MakeConfig(app.ModuleBasics)
|
||||||
// We're using TestMsg amino encoding in some tests, so register it here.
|
// We're using TestMsg amino encoding in some tests, so register it here.
|
||||||
encodingConfig.Amino.RegisterConcrete(&testdata.TestMsg{}, "testdata.TestMsg", nil)
|
encodingConfig.Amino.RegisterConcrete(&testdata.TestMsg{}, "testdata.TestMsg", nil)
|
||||||
|
eip712.SetEncodingConfig(encodingConfig)
|
||||||
|
|
||||||
suite.clientCtx = client.Context{}.WithTxConfig(encodingConfig.TxConfig)
|
suite.clientCtx = client.Context{}.WithTxConfig(encodingConfig.TxConfig)
|
||||||
|
|
||||||
@ -263,41 +273,57 @@ func (suite *AnteTestSuite) CreateTestCosmosTxBuilder(gasPrice sdkmath.Int, deno
|
|||||||
func (suite *AnteTestSuite) CreateTestEIP712TxBuilderMsgSend(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
func (suite *AnteTestSuite) CreateTestEIP712TxBuilderMsgSend(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||||
// Build MsgSend
|
// Build MsgSend
|
||||||
recipient := sdk.AccAddress(common.Address{}.Bytes())
|
recipient := sdk.AccAddress(common.Address{}.Bytes())
|
||||||
msgSend := types2.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(1))))
|
msgSend := banktypes.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(1))))
|
||||||
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgSend)
|
return suite.CreateTestEIP712SingleMessageTxBuilder(from, priv, chainId, gas, gasAmount, msgSend)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *AnteTestSuite) CreateTestEIP712TxBuilderMsgDelegate(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
func (suite *AnteTestSuite) CreateTestEIP712TxBuilderMsgDelegate(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||||
// Build MsgSend
|
// Build MsgSend
|
||||||
valEthAddr := tests.GenerateAddress()
|
valEthAddr := tests.GenerateAddress()
|
||||||
valAddr := sdk.ValAddress(valEthAddr.Bytes())
|
valAddr := sdk.ValAddress(valEthAddr.Bytes())
|
||||||
msgSend := types3.NewMsgDelegate(from, valAddr, sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(20)))
|
msgSend := stakingtypes.NewMsgDelegate(from, valAddr, sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(20)))
|
||||||
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgSend)
|
return suite.CreateTestEIP712SingleMessageTxBuilder(from, priv, chainId, gas, gasAmount, msgSend)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *AnteTestSuite) CreateTestEIP712MsgCreateValidator(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
func (suite *AnteTestSuite) CreateTestEIP712MsgCreateValidator(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||||
// Build MsgCreateValidator
|
// Build MsgCreateValidator
|
||||||
valAddr := sdk.ValAddress(from.Bytes())
|
valAddr := sdk.ValAddress(from.Bytes())
|
||||||
privEd := ed25519.GenPrivKey()
|
privEd := ed25519.GenPrivKey()
|
||||||
msgCreate, err := types3.NewMsgCreateValidator(
|
msgCreate, err := stakingtypes.NewMsgCreateValidator(
|
||||||
valAddr,
|
valAddr,
|
||||||
privEd.PubKey(),
|
privEd.PubKey(),
|
||||||
sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20)),
|
sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20)),
|
||||||
// TODO: can this values be empty strings?
|
stakingtypes.NewDescription("moniker", "indentity", "website", "security_contract", "details"),
|
||||||
types3.NewDescription("moniker", "indentity", "website", "security_contract", "details"),
|
stakingtypes.NewCommissionRates(sdk.OneDec(), sdk.OneDec(), sdk.OneDec()),
|
||||||
types3.NewCommissionRates(sdk.OneDec(), sdk.OneDec(), sdk.OneDec()),
|
|
||||||
sdk.OneInt(),
|
sdk.OneInt(),
|
||||||
)
|
)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgCreate)
|
return suite.CreateTestEIP712SingleMessageTxBuilder(from, priv, chainId, gas, gasAmount, msgCreate)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *AnteTestSuite) CreateTestEIP712MsgCreateValidator2(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||||
|
// Build MsgCreateValidator
|
||||||
|
valAddr := sdk.ValAddress(from.Bytes())
|
||||||
|
privEd := ed25519.GenPrivKey()
|
||||||
|
msgCreate, err := stakingtypes.NewMsgCreateValidator(
|
||||||
|
valAddr,
|
||||||
|
privEd.PubKey(),
|
||||||
|
sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20)),
|
||||||
|
// Ensure optional fields can be left blank
|
||||||
|
stakingtypes.NewDescription("moniker", "indentity", "", "", ""),
|
||||||
|
stakingtypes.NewCommissionRates(sdk.OneDec(), sdk.OneDec(), sdk.OneDec()),
|
||||||
|
sdk.OneInt(),
|
||||||
|
)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
return suite.CreateTestEIP712SingleMessageTxBuilder(from, priv, chainId, gas, gasAmount, msgCreate)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *AnteTestSuite) CreateTestEIP712SubmitProposal(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins, deposit sdk.Coins) client.TxBuilder {
|
func (suite *AnteTestSuite) CreateTestEIP712SubmitProposal(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins, deposit sdk.Coins) client.TxBuilder {
|
||||||
proposal, ok := types5.ContentFromProposalType("My proposal", "My description", types5.ProposalTypeText)
|
proposal, ok := govtypes.ContentFromProposalType("My proposal", "My description", govtypes.ProposalTypeText)
|
||||||
suite.Require().True(ok)
|
suite.Require().True(ok)
|
||||||
msgSubmit, err := types5.NewMsgSubmitProposal(proposal, deposit, from)
|
msgSubmit, err := govtypes.NewMsgSubmitProposal(proposal, deposit, from)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgSubmit)
|
return suite.CreateTestEIP712SingleMessageTxBuilder(from, priv, chainId, gas, gasAmount, msgSubmit)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *AnteTestSuite) CreateTestEIP712GrantAllowance(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
func (suite *AnteTestSuite) CreateTestEIP712GrantAllowance(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||||
@ -311,18 +337,18 @@ func (suite *AnteTestSuite) CreateTestEIP712GrantAllowance(from sdk.AccAddress,
|
|||||||
grantedAddr := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, granted.Bytes())
|
grantedAddr := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, granted.Bytes())
|
||||||
msgGrant, err := feegrant.NewMsgGrantAllowance(basic, from, grantedAddr.GetAddress())
|
msgGrant, err := feegrant.NewMsgGrantAllowance(basic, from, grantedAddr.GetAddress())
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgGrant)
|
return suite.CreateTestEIP712SingleMessageTxBuilder(from, priv, chainId, gas, gasAmount, msgGrant)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *AnteTestSuite) CreateTestEIP712MsgEditValidator(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
func (suite *AnteTestSuite) CreateTestEIP712MsgEditValidator(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||||
valAddr := sdk.ValAddress(from.Bytes())
|
valAddr := sdk.ValAddress(from.Bytes())
|
||||||
msgEdit := types3.NewMsgEditValidator(
|
msgEdit := stakingtypes.NewMsgEditValidator(
|
||||||
valAddr,
|
valAddr,
|
||||||
types3.NewDescription("moniker", "identity", "website", "security_contract", "details"),
|
stakingtypes.NewDescription("moniker", "identity", "website", "security_contract", "details"),
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
)
|
)
|
||||||
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgEdit)
|
return suite.CreateTestEIP712SingleMessageTxBuilder(from, priv, chainId, gas, gasAmount, msgEdit)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *AnteTestSuite) CreateTestEIP712MsgSubmitEvidence(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
func (suite *AnteTestSuite) CreateTestEIP712MsgSubmitEvidence(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||||
@ -335,7 +361,72 @@ func (suite *AnteTestSuite) CreateTestEIP712MsgSubmitEvidence(from sdk.AccAddres
|
|||||||
})
|
})
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgEvidence)
|
return suite.CreateTestEIP712SingleMessageTxBuilder(from, priv, chainId, gas, gasAmount, msgEvidence)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *AnteTestSuite) CreateTestEIP712MsgVoteV1(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||||
|
msgVote := govtypesv1.NewMsgVote(from, 1, govtypesv1.VoteOption_VOTE_OPTION_YES, "")
|
||||||
|
return suite.CreateTestEIP712SingleMessageTxBuilder(from, priv, chainId, gas, gasAmount, msgVote)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *AnteTestSuite) CreateTestEIP712SubmitProposalV1(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||||
|
// Build V1 proposal messages. Must all be same-type, since EIP-712
|
||||||
|
// does not support arrays of variable type.
|
||||||
|
authAcc := suite.app.GovKeeper.GetGovernanceAccount(suite.ctx)
|
||||||
|
|
||||||
|
proposal1, ok := govtypes.ContentFromProposalType("My proposal 1", "My description 1", govtypes.ProposalTypeText)
|
||||||
|
suite.Require().True(ok)
|
||||||
|
content1, err := govtypesv1.NewLegacyContent(
|
||||||
|
proposal1,
|
||||||
|
sdk.MustBech32ifyAddressBytes(sdk.GetConfig().GetBech32AccountAddrPrefix(), authAcc.GetAddress().Bytes()),
|
||||||
|
)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
proposal2, ok := govtypes.ContentFromProposalType("My proposal 2", "My description 2", govtypes.ProposalTypeText)
|
||||||
|
suite.Require().True(ok)
|
||||||
|
content2, err := govtypesv1.NewLegacyContent(
|
||||||
|
proposal2,
|
||||||
|
sdk.MustBech32ifyAddressBytes(sdk.GetConfig().GetBech32AccountAddrPrefix(), authAcc.GetAddress().Bytes()),
|
||||||
|
)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
proposalMsgs := []sdk.Msg{
|
||||||
|
content1,
|
||||||
|
content2,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build V1 proposal
|
||||||
|
msgProposal, err := govtypesv1.NewMsgSubmitProposal(
|
||||||
|
proposalMsgs,
|
||||||
|
sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(100))),
|
||||||
|
sdk.MustBech32ifyAddressBytes(sdk.GetConfig().GetBech32AccountAddrPrefix(), from.Bytes()),
|
||||||
|
"Metadata",
|
||||||
|
)
|
||||||
|
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
return suite.CreateTestEIP712SingleMessageTxBuilder(from, priv, chainId, gas, gasAmount, msgProposal)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *AnteTestSuite) CreateTestEIP712MsgExec(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||||
|
recipient := sdk.AccAddress(common.Address{}.Bytes())
|
||||||
|
msgSend := banktypes.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(1))))
|
||||||
|
msgExec := authz.NewMsgExec(from, []sdk.Msg{msgSend})
|
||||||
|
return suite.CreateTestEIP712SingleMessageTxBuilder(from, priv, chainId, gas, gasAmount, &msgExec)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *AnteTestSuite) CreateTestEIP712MultipleMsgSend(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||||
|
recipient := sdk.AccAddress(common.Address{}.Bytes())
|
||||||
|
msgSend := banktypes.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(1))))
|
||||||
|
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, []sdk.Msg{msgSend, msgSend, msgSend})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fails
|
||||||
|
func (suite *AnteTestSuite) CreateTestEIP712MultipleSignerMsgs(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||||
|
recipient := sdk.AccAddress(common.Address{}.Bytes())
|
||||||
|
msgSend1 := banktypes.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(1))))
|
||||||
|
msgSend2 := banktypes.NewMsgSend(recipient, from, sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(1))))
|
||||||
|
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, []sdk.Msg{msgSend1, msgSend2})
|
||||||
}
|
}
|
||||||
|
|
||||||
// StdSignBytes returns the bytes to sign for a transaction.
|
// StdSignBytes returns the bytes to sign for a transaction.
|
||||||
@ -376,8 +467,14 @@ func StdSignBytes(cdc *codec.LegacyAmino, chainID string, accnum uint64, sequenc
|
|||||||
return sdk.MustSortJSON(bz)
|
return sdk.MustSortJSON(bz)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *AnteTestSuite) CreateTestEIP712CosmosTxBuilder(
|
func (suite *AnteTestSuite) CreateTestEIP712SingleMessageTxBuilder(
|
||||||
from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins, msg sdk.Msg,
|
from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins, msg sdk.Msg,
|
||||||
|
) client.TxBuilder {
|
||||||
|
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, []sdk.Msg{msg})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *AnteTestSuite) CreateTestEIP712CosmosTxBuilder(
|
||||||
|
from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins, msgs []sdk.Msg,
|
||||||
) client.TxBuilder {
|
) client.TxBuilder {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
@ -398,13 +495,13 @@ func (suite *AnteTestSuite) CreateTestEIP712CosmosTxBuilder(
|
|||||||
fee := legacytx.NewStdFee(gas, gasAmount)
|
fee := legacytx.NewStdFee(gas, gasAmount)
|
||||||
accNumber := suite.app.AccountKeeper.GetAccount(suite.ctx, from).GetAccountNumber()
|
accNumber := suite.app.AccountKeeper.GetAccount(suite.ctx, from).GetAccountNumber()
|
||||||
|
|
||||||
data := legacytx.StdSignBytes(chainId, accNumber, nonce, 0, fee, []sdk.Msg{msg}, "", nil)
|
data := legacytx.StdSignBytes(chainId, accNumber, nonce, 0, fee, msgs, "", nil)
|
||||||
typedData, err := eip712.WrapTxToTypedData(ethermintCodec, ethChainId, msg, data, &eip712.FeeDelegationOptions{
|
typedData, err := eip712.WrapTxToTypedData(ethermintCodec, ethChainId, msgs[0], data, &eip712.FeeDelegationOptions{
|
||||||
FeePayer: from,
|
FeePayer: from,
|
||||||
})
|
})
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
sigHash, err := eip712.ComputeTypedDataHash(typedData)
|
sigHash, _, err := apitypes.TypedDataAndHash(typedData)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
// Sign typedData
|
// Sign typedData
|
||||||
@ -442,12 +539,189 @@ func (suite *AnteTestSuite) CreateTestEIP712CosmosTxBuilder(
|
|||||||
err = builder.SetSignatures(sigsV2)
|
err = builder.SetSignatures(sigsV2)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
err = builder.SetMsgs(msg)
|
err = builder.SetMsgs(msgs...)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
return builder
|
return builder
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate a set of pub/priv keys to be used in creating multi-keys
|
||||||
|
func (suite *AnteTestSuite) GenerateMultipleKeys(n int) ([]cryptotypes.PrivKey, []cryptotypes.PubKey) {
|
||||||
|
privKeys := make([]cryptotypes.PrivKey, n)
|
||||||
|
pubKeys := make([]cryptotypes.PubKey, n)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
privKey, err := ethsecp256k1.GenerateKey()
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
privKeys[i] = privKey
|
||||||
|
pubKeys[i] = privKey.PubKey()
|
||||||
|
}
|
||||||
|
return privKeys, pubKeys
|
||||||
|
}
|
||||||
|
|
||||||
|
// generateSingleSignature signs the given sign doc bytes using the given signType (EIP-712 or Standard)
|
||||||
|
func (suite *AnteTestSuite) generateSingleSignature(signMode signing.SignMode, privKey cryptotypes.PrivKey, signDocBytes []byte, signType string) (signature signing.SignatureV2) {
|
||||||
|
var (
|
||||||
|
msg []byte
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
msg = signDocBytes
|
||||||
|
|
||||||
|
if signType == "EIP-712" {
|
||||||
|
msg, err = eip712.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) {
|
func NextFn(ctx sdk.Context, _ sdk.Tx, _ bool) (sdk.Context, error) {
|
||||||
return ctx, nil
|
return ctx, nil
|
||||||
}
|
}
|
||||||
|
38
app/app.go
38
app/app.go
@ -2,6 +2,7 @@ package app
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
@ -18,6 +19,7 @@ import (
|
|||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||||
"github.com/cosmos/cosmos-sdk/client"
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
|
"github.com/cosmos/cosmos-sdk/client/grpc/node"
|
||||||
"github.com/cosmos/cosmos-sdk/client/grpc/tmservice"
|
"github.com/cosmos/cosmos-sdk/client/grpc/tmservice"
|
||||||
"github.com/cosmos/cosmos-sdk/codec"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||||
@ -26,6 +28,7 @@ import (
|
|||||||
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
||||||
"github.com/cosmos/cosmos-sdk/simapp"
|
"github.com/cosmos/cosmos-sdk/simapp"
|
||||||
simappparams "github.com/cosmos/cosmos-sdk/simapp/params"
|
simappparams "github.com/cosmos/cosmos-sdk/simapp/params"
|
||||||
|
"github.com/cosmos/cosmos-sdk/store/streaming"
|
||||||
storetypes "github.com/cosmos/cosmos-sdk/store/types"
|
storetypes "github.com/cosmos/cosmos-sdk/store/types"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/cosmos/cosmos-sdk/types/module"
|
"github.com/cosmos/cosmos-sdk/types/module"
|
||||||
@ -179,8 +182,6 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ simapp.App = (*EthermintApp)(nil)
|
|
||||||
|
|
||||||
// var _ server.Application (*EthermintApp)(nil)
|
// var _ server.Application (*EthermintApp)(nil)
|
||||||
|
|
||||||
// EthermintApp implements an extended ABCI application. It is an application
|
// EthermintApp implements an extended ABCI application. It is an application
|
||||||
@ -230,9 +231,6 @@ type EthermintApp struct {
|
|||||||
// the module manager
|
// the module manager
|
||||||
mm *module.Manager
|
mm *module.Manager
|
||||||
|
|
||||||
// simulation manager
|
|
||||||
sm *module.SimulationManager
|
|
||||||
|
|
||||||
// the configurator
|
// the configurator
|
||||||
configurator module.Configurator
|
configurator module.Configurator
|
||||||
}
|
}
|
||||||
@ -283,6 +281,12 @@ func NewEthermintApp(
|
|||||||
tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey, evmtypes.TransientKey, feemarkettypes.TransientKey)
|
tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey, evmtypes.TransientKey, feemarkettypes.TransientKey)
|
||||||
memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey)
|
memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey)
|
||||||
|
|
||||||
|
// load state streaming if enabled
|
||||||
|
if _, _, err := streaming.LoadStreamingServices(bApp, appOpts, appCodec, keys); err != nil {
|
||||||
|
fmt.Printf("failed to load state streaming: %s", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
app := &EthermintApp{
|
app := &EthermintApp{
|
||||||
BaseApp: bApp,
|
BaseApp: bApp,
|
||||||
cdc: cdc,
|
cdc: cdc,
|
||||||
@ -591,17 +595,6 @@ func NewEthermintApp(
|
|||||||
// add test gRPC service for testing gRPC queries in isolation
|
// add test gRPC service for testing gRPC queries in isolation
|
||||||
// testdata.RegisterTestServiceServer(app.GRPCQueryRouter(), testdata.TestServiceImpl{})
|
// testdata.RegisterTestServiceServer(app.GRPCQueryRouter(), testdata.TestServiceImpl{})
|
||||||
|
|
||||||
// create the simulation manager and define the order of the modules for deterministic simulations
|
|
||||||
//
|
|
||||||
// NOTE: this is not required apps that don't use the simulator for fuzz testing
|
|
||||||
// transactions
|
|
||||||
overrideModules := map[string]module.AppModuleSimulation{
|
|
||||||
authtypes.ModuleName: auth.NewAppModule(app.appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts),
|
|
||||||
}
|
|
||||||
app.sm = module.NewSimulationManagerFromAppModules(app.mm.Modules, overrideModules)
|
|
||||||
|
|
||||||
app.sm.RegisterStoreDecoders()
|
|
||||||
|
|
||||||
// initialize stores
|
// initialize stores
|
||||||
app.MountKVStores(keys)
|
app.MountKVStores(keys)
|
||||||
app.MountTransientStores(tkeys)
|
app.MountTransientStores(tkeys)
|
||||||
@ -771,11 +764,6 @@ func (app *EthermintApp) GetSubspace(moduleName string) paramstypes.Subspace {
|
|||||||
return subspace
|
return subspace
|
||||||
}
|
}
|
||||||
|
|
||||||
// SimulationManager implements the SimulationApp interface
|
|
||||||
func (app *EthermintApp) SimulationManager() *module.SimulationManager {
|
|
||||||
return app.sm
|
|
||||||
}
|
|
||||||
|
|
||||||
// RegisterAPIRoutes registers all application module routes with the provided
|
// RegisterAPIRoutes registers all application module routes with the provided
|
||||||
// API server.
|
// API server.
|
||||||
func (app *EthermintApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) {
|
func (app *EthermintApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) {
|
||||||
@ -784,6 +772,8 @@ func (app *EthermintApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.
|
|||||||
authtx.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
|
authtx.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
|
||||||
// Register new tendermint queries routes from grpc-gateway.
|
// Register new tendermint queries routes from grpc-gateway.
|
||||||
tmservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
|
tmservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
|
||||||
|
// Register node gRPC service for grpc-gateway.
|
||||||
|
node.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
|
||||||
|
|
||||||
// Register grpc-gateway routes for all modules.
|
// Register grpc-gateway routes for all modules.
|
||||||
ModuleBasics.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
|
ModuleBasics.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
|
||||||
@ -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
|
// RegisterSwaggerAPI registers swagger route with API Server
|
||||||
func RegisterSwaggerAPI(_ client.Context, rtr *mux.Router) {
|
func RegisterSwaggerAPI(_ client.Context, rtr *mux.Router) {
|
||||||
statikFS, err := fs.New()
|
statikFS, err := fs.New()
|
||||||
|
@ -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 (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"math/rand"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/codec"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
@ -11,21 +10,12 @@ import (
|
|||||||
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
||||||
"github.com/cosmos/cosmos-sdk/simapp"
|
"github.com/cosmos/cosmos-sdk/simapp"
|
||||||
"github.com/cosmos/cosmos-sdk/testutil/mock"
|
"github.com/cosmos/cosmos-sdk/testutil/mock"
|
||||||
"github.com/cosmos/cosmos-sdk/types/module"
|
|
||||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||||
|
|
||||||
"github.com/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"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
|
"github.com/evmos/ethermint/encoding"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
|
||||||
"github.com/evmos/ethermint/crypto/ethsecp256k1"
|
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
"github.com/tendermint/tendermint/libs/log"
|
"github.com/tendermint/tendermint/libs/log"
|
||||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||||
@ -94,96 +84,6 @@ func SetupWithDB(isCheckTx bool, patchGenesis func(*EthermintApp, simapp.Genesis
|
|||||||
return app
|
return app
|
||||||
}
|
}
|
||||||
|
|
||||||
// RandomGenesisAccounts is used by the auth module to create random genesis accounts in simulation when a genesis.json is not specified.
|
|
||||||
// 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
|
// NewTestGenesisState generate genesis state with single validator
|
||||||
func NewTestGenesisState(codec codec.Codec) simapp.GenesisState {
|
func NewTestGenesisState(codec codec.Codec) simapp.GenesisState {
|
||||||
privVal := mock.NewPV()
|
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
|
version: v1
|
||||||
directories:
|
directories:
|
||||||
- proto
|
- proto
|
||||||
- third_party/proto
|
|
||||||
|
@ -13,57 +13,6 @@
|
|||||||
"Params": "EvmParams"
|
"Params": "EvmParams"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "./tmp-swagger-gen/cosmos/auth/v1beta1/query.swagger.json",
|
|
||||||
"operationIds": {
|
|
||||||
"rename": {
|
|
||||||
"Account": "AuthAccount",
|
|
||||||
"Params": "AuthParams"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "./tmp-swagger-gen/cosmos/bank/v1beta1/query.swagger.json",
|
|
||||||
"operationIds": {
|
|
||||||
"rename": {
|
|
||||||
"Balance": "BankBalance",
|
|
||||||
"Params": "BankParams"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "./tmp-swagger-gen/cosmos/distribution/v1beta1/query.swagger.json",
|
|
||||||
"operationIds": {
|
|
||||||
"rename": {
|
|
||||||
"Params": "DistributionParams",
|
|
||||||
"DelegatorValidators": "DistDelegatorValidators"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "./tmp-swagger-gen/cosmos/mint/v1beta1/query.swagger.json",
|
|
||||||
"operationIds": {
|
|
||||||
"rename": {
|
|
||||||
"Params": "MintParams"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "./tmp-swagger-gen/cosmos/gov/v1beta1/query.swagger.json",
|
|
||||||
"operationIds": {
|
|
||||||
"rename": {
|
|
||||||
"Params": "GovParams"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "./tmp-swagger-gen/cosmos/staking/v1beta1/query.swagger.json",
|
|
||||||
"operationIds": {
|
|
||||||
"rename": {
|
|
||||||
"Params": "StakingParams"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
5
client/docs/statik/statik.go
vendored
5
client/docs/statik/statik.go
vendored
File diff suppressed because one or more lines are too long
17061
client/docs/swagger-ui/swagger.yaml
vendored
17061
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/client/debug"
|
||||||
"github.com/evmos/ethermint/crypto/hd"
|
"github.com/evmos/ethermint/crypto/hd"
|
||||||
"github.com/evmos/ethermint/encoding"
|
"github.com/evmos/ethermint/encoding"
|
||||||
|
"github.com/evmos/ethermint/ethereum/eip712"
|
||||||
"github.com/evmos/ethermint/server"
|
"github.com/evmos/ethermint/server"
|
||||||
servercfg "github.com/evmos/ethermint/server/config"
|
servercfg "github.com/evmos/ethermint/server/config"
|
||||||
srvflags "github.com/evmos/ethermint/server/flags"
|
srvflags "github.com/evmos/ethermint/server/flags"
|
||||||
@ -61,6 +62,8 @@ func NewRootCmd() (*cobra.Command, params.EncodingConfig) {
|
|||||||
WithKeyringOptions(hd.EthSecp256k1Option()).
|
WithKeyringOptions(hd.EthSecp256k1Option()).
|
||||||
WithViper(EnvPrefix)
|
WithViper(EnvPrefix)
|
||||||
|
|
||||||
|
eip712.SetEncodingConfig(encodingConfig)
|
||||||
|
|
||||||
rootCmd := &cobra.Command{
|
rootCmd := &cobra.Command{
|
||||||
Use: "ethermintd",
|
Use: "ethermintd",
|
||||||
Short: "Ethermint Daemon",
|
Short: "Ethermint Daemon",
|
||||||
@ -179,6 +182,7 @@ func txCommand() *cobra.Command {
|
|||||||
authcmd.GetBroadcastCommand(),
|
authcmd.GetBroadcastCommand(),
|
||||||
authcmd.GetEncodeCommand(),
|
authcmd.GetEncodeCommand(),
|
||||||
authcmd.GetDecodeCommand(),
|
authcmd.GetDecodeCommand(),
|
||||||
|
authcmd.GetAuxToFeeCommand(),
|
||||||
)
|
)
|
||||||
|
|
||||||
app.ModuleBasics.AddTxCommands(cmd)
|
app.ModuleBasics.AddTxCommands(cmd)
|
||||||
|
@ -6,11 +6,12 @@ import (
|
|||||||
"crypto/subtle"
|
"crypto/subtle"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
errorsmod "cosmossdk.io/errors"
|
||||||
"github.com/cosmos/cosmos-sdk/codec"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/evmos/ethermint/ethereum/eip712"
|
||||||
tmcrypto "github.com/tendermint/tendermint/crypto"
|
tmcrypto "github.com/tendermint/tendermint/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -182,7 +183,7 @@ func (pubKey PubKey) MarshalAmino() ([]byte, error) {
|
|||||||
// UnmarshalAmino overrides Amino binary marshaling.
|
// UnmarshalAmino overrides Amino binary marshaling.
|
||||||
func (pubKey *PubKey) UnmarshalAmino(bz []byte) error {
|
func (pubKey *PubKey) UnmarshalAmino(bz []byte) error {
|
||||||
if len(bz) != PubKeySize {
|
if len(bz) != PubKeySize {
|
||||||
return sdkerrors.Wrapf(sdkerrors.ErrInvalidPubKey, "invalid pubkey size, expected %d, got %d", PubKeySize, len(bz))
|
return errorsmod.Wrapf(errortypes.ErrInvalidPubKey, "invalid pubkey size, expected %d, got %d", PubKeySize, len(bz))
|
||||||
}
|
}
|
||||||
pubKey.Key = bz
|
pubKey.Key = bz
|
||||||
|
|
||||||
@ -203,10 +204,28 @@ func (pubKey *PubKey) UnmarshalAminoJSON(bz []byte) error {
|
|||||||
|
|
||||||
// VerifySignature verifies that the ECDSA public key created a given signature over
|
// VerifySignature verifies that the ECDSA public key created a given signature over
|
||||||
// the provided message. It will calculate the Keccak256 hash of the message
|
// the provided message. It will calculate the Keccak256 hash of the message
|
||||||
// prior to verification.
|
// prior to verification and approve verification if the signature can be verified
|
||||||
|
// from either the original message or its EIP-712 representation.
|
||||||
//
|
//
|
||||||
// CONTRACT: The signature should be in [R || S] format.
|
// CONTRACT: The signature should be in [R || S] format.
|
||||||
func (pubKey PubKey) VerifySignature(msg, sig []byte) bool {
|
func (pubKey PubKey) VerifySignature(msg, sig []byte) bool {
|
||||||
|
return pubKey.verifySignatureECDSA(msg, sig) || pubKey.verifySignatureAsEIP712(msg, sig)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verifies the signature as an EIP-712 signature by first converting the message payload
|
||||||
|
// to 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 {
|
if len(sig) == crypto.SignatureLength {
|
||||||
// remove recovery ID (V) if contained in the signature
|
// remove recovery ID (V) if contained in the signature
|
||||||
sig = sig[:len(sig)-1]
|
sig = sig[:len(sig)-1]
|
||||||
|
4
crypto/ethsecp256k1/keys.pb.go
generated
4
crypto/ethsecp256k1/keys.pb.go
generated
@ -5,7 +5,7 @@ package ethsecp256k1
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
fmt "fmt"
|
fmt "fmt"
|
||||||
_ "github.com/gogo/protobuf/gogoproto"
|
_ "github.com/cosmos/gogoproto/gogoproto"
|
||||||
proto "github.com/gogo/protobuf/proto"
|
proto "github.com/gogo/protobuf/proto"
|
||||||
io "io"
|
io "io"
|
||||||
math "math"
|
math "math"
|
||||||
@ -27,6 +27,7 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
|||||||
// Tendermint's PubKey interface. It represents the 33-byte compressed public
|
// Tendermint's PubKey interface. It represents the 33-byte compressed public
|
||||||
// key format.
|
// key format.
|
||||||
type PubKey struct {
|
type PubKey struct {
|
||||||
|
// key is the public key in byte form
|
||||||
Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
|
Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,6 +73,7 @@ func (m *PubKey) GetKey() []byte {
|
|||||||
// PrivKey defines a type alias for an ecdsa.PrivateKey that implements
|
// PrivKey defines a type alias for an ecdsa.PrivateKey that implements
|
||||||
// Tendermint's PrivateKey interface.
|
// Tendermint's PrivateKey interface.
|
||||||
type PrivKey struct {
|
type PrivKey struct {
|
||||||
|
// key is the private key in byte form
|
||||||
Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
|
Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package hd
|
package hd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -10,7 +11,6 @@ import (
|
|||||||
|
|
||||||
hdwallet "github.com/miguelmota/go-ethereum-hdwallet"
|
hdwallet "github.com/miguelmota/go-ethereum-hdwallet"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/codec"
|
|
||||||
amino "github.com/cosmos/cosmos-sdk/codec"
|
amino "github.com/cosmos/cosmos-sdk/codec"
|
||||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||||
@ -20,10 +20,10 @@ import (
|
|||||||
ethermint "github.com/evmos/ethermint/types"
|
ethermint "github.com/evmos/ethermint/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
var TestCodec codec.Codec
|
var TestCodec amino.Codec
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cdc := codec.NewLegacyAmino()
|
cdc := amino.NewLegacyAmino()
|
||||||
cryptocodec.RegisterCrypto(cdc)
|
cryptocodec.RegisterCrypto(cdc)
|
||||||
|
|
||||||
interfaceRegistry := types.NewInterfaceRegistry()
|
interfaceRegistry := types.NewInterfaceRegistry()
|
||||||
@ -31,12 +31,18 @@ func init() {
|
|||||||
enccodec.RegisterInterfaces(interfaceRegistry)
|
enccodec.RegisterInterfaces(interfaceRegistry)
|
||||||
}
|
}
|
||||||
|
|
||||||
const mnemonic = "picnic rent average infant boat squirrel federal assault mercy purity very motor fossil wheel verify upset box fresh horse vivid copy predict square regret"
|
const (
|
||||||
|
mnemonic = "picnic rent average infant boat squirrel federal assault mercy purity very motor fossil wheel verify upset box fresh horse vivid copy predict square regret"
|
||||||
|
|
||||||
|
// hdWalletFixEnv defines whether the standard (correct) bip39
|
||||||
|
// derivation path was used, or if derivation was affected by
|
||||||
|
// https://github.com/btcsuite/btcutil/issues/172
|
||||||
|
hdWalletFixEnv = "GO_ETHEREUM_HDWALLET_FIX_ISSUE_179"
|
||||||
|
)
|
||||||
|
|
||||||
func TestKeyring(t *testing.T) {
|
func TestKeyring(t *testing.T) {
|
||||||
dir := t.TempDir()
|
dir := t.TempDir()
|
||||||
mockIn := strings.NewReader("")
|
mockIn := strings.NewReader("")
|
||||||
|
|
||||||
kr, err := keyring.New("ethermint", keyring.BackendTest, dir, mockIn, TestCodec, EthSecp256k1Option())
|
kr, err := keyring.New("ethermint", keyring.BackendTest, dir, mockIn, TestCodec, EthSecp256k1Option())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
@ -68,7 +74,9 @@ func TestKeyring(t *testing.T) {
|
|||||||
privkey := EthSecp256k1.Generate()(bz)
|
privkey := EthSecp256k1.Generate()(bz)
|
||||||
addr := common.BytesToAddress(privkey.PubKey().Address().Bytes())
|
addr := common.BytesToAddress(privkey.PubKey().Address().Bytes())
|
||||||
|
|
||||||
|
os.Setenv(hdWalletFixEnv, "true")
|
||||||
wallet, err := hdwallet.NewFromMnemonic(mnemonic)
|
wallet, err := hdwallet.NewFromMnemonic(mnemonic)
|
||||||
|
os.Setenv(hdWalletFixEnv, "")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
path := hdwallet.MustParseDerivationPath(hdPath)
|
path := hdwallet.MustParseDerivationPath(hdPath)
|
||||||
|
@ -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 |
|
| `overrides` | [ChainConfig](#ethermint.evm.v1.ChainConfig) | | Chain overrides, can be used to execute a trace using future fork rules |
|
||||||
| `enable_memory` | [bool](#bool) | | enable memory capture |
|
| `enable_memory` | [bool](#bool) | | enable memory capture |
|
||||||
| `enable_return_data` | [bool](#bool) | | enable return data capture |
|
| `enable_return_data` | [bool](#bool) | | enable return data capture |
|
||||||
|
| `tracer_json_config` | [string](#string) | | tracer config |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -563,6 +564,7 @@ EthCallRequest defines EthCall request
|
|||||||
| `args` | [bytes](#bytes) | | same json format as the json rpc api. |
|
| `args` | [bytes](#bytes) | | same json format as the json rpc api. |
|
||||||
| `gas_cap` | [uint64](#uint64) | | the default gas cap to be used |
|
| `gas_cap` | [uint64](#uint64) | | the default gas cap to be used |
|
||||||
| `proposer_address` | [bytes](#bytes) | | the proposer of the requested block |
|
| `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_hash` | [string](#string) | | block hex hash |
|
||||||
| `block_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | block time |
|
| `block_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | block time |
|
||||||
| `proposer_address` | [bytes](#bytes) | | the proposer of the requested block |
|
| `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_hash` | [string](#string) | | block hex hash of requested transaction |
|
||||||
| `block_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | block time of requested transaction |
|
| `block_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | block time of requested transaction |
|
||||||
| `proposer_address` | [bytes](#bytes) | | the proposer of the requested block |
|
| `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/cases"
|
||||||
"golang.org/x/text/language"
|
"golang.org/x/text/language"
|
||||||
|
|
||||||
|
errorsmod "cosmossdk.io/errors"
|
||||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
|
||||||
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ComputeTypedDataHash computes keccak hash of typed data for signing.
|
|
||||||
func ComputeTypedDataHash(typedData apitypes.TypedData) ([]byte, error) {
|
|
||||||
domainSeparator, err := typedData.HashStruct("EIP712Domain", typedData.Domain.Map())
|
|
||||||
if err != nil {
|
|
||||||
err = sdkerrors.Wrap(err, "failed to pack and hash typedData EIP712Domain")
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
typedDataHash, err := typedData.HashStruct(typedData.PrimaryType, typedData.Message)
|
|
||||||
if err != nil {
|
|
||||||
err = sdkerrors.Wrap(err, "failed to pack and hash typedData primary type")
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
rawData := []byte(fmt.Sprintf("\x19\x01%s%s", string(domainSeparator), string(typedDataHash)))
|
|
||||||
return crypto.Keccak256(rawData), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// WrapTxToTypedData is an ultimate method that wraps Amino-encoded Cosmos Tx JSON data
|
// WrapTxToTypedData is an ultimate method that wraps Amino-encoded Cosmos Tx JSON data
|
||||||
// into an EIP712-compatible TypedData request.
|
// into an EIP712-compatible TypedData request.
|
||||||
func WrapTxToTypedData(
|
func WrapTxToTypedData(
|
||||||
@ -54,7 +36,7 @@ func WrapTxToTypedData(
|
|||||||
txData := make(map[string]interface{})
|
txData := make(map[string]interface{})
|
||||||
|
|
||||||
if err := json.Unmarshal(data, &txData); err != nil {
|
if err := json.Unmarshal(data, &txData); err != nil {
|
||||||
return apitypes.TypedData{}, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, "failed to JSON unmarshal data")
|
return apitypes.TypedData{}, errorsmod.Wrap(errortypes.ErrJSONUnmarshal, "failed to JSON unmarshal data")
|
||||||
}
|
}
|
||||||
|
|
||||||
domain := apitypes.TypedDataDomain{
|
domain := apitypes.TypedDataDomain{
|
||||||
@ -73,7 +55,7 @@ func WrapTxToTypedData(
|
|||||||
if feeDelegation != nil {
|
if feeDelegation != nil {
|
||||||
feeInfo, ok := txData["fee"].(map[string]interface{})
|
feeInfo, ok := txData["fee"].(map[string]interface{})
|
||||||
if !ok {
|
if !ok {
|
||||||
return apitypes.TypedData{}, sdkerrors.Wrap(sdkerrors.ErrInvalidType, "cannot parse fee from tx data")
|
return apitypes.TypedData{}, errorsmod.Wrap(errortypes.ErrInvalidType, "cannot parse fee from tx data")
|
||||||
}
|
}
|
||||||
|
|
||||||
feeInfo["feePayer"] = feeDelegation.FeePayer.String()
|
feeInfo["feePayer"] = feeDelegation.FeePayer.String()
|
||||||
@ -206,7 +188,11 @@ func traverseFields(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
var field reflect.Value
|
var (
|
||||||
|
field reflect.Value
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
if v.IsValid() {
|
if v.IsValid() {
|
||||||
field = v.Field(i)
|
field = v.Field(i)
|
||||||
}
|
}
|
||||||
@ -215,27 +201,14 @@ func traverseFields(
|
|||||||
fieldName := jsonNameFromTag(t.Field(i).Tag)
|
fieldName := jsonNameFromTag(t.Field(i).Tag)
|
||||||
|
|
||||||
if fieldType == cosmosAnyType {
|
if fieldType == cosmosAnyType {
|
||||||
any, ok := field.Interface().(*codectypes.Any)
|
// Unpack field, value as Any
|
||||||
if !ok {
|
if fieldType, field, err = unpackAny(cdc, field); err != nil {
|
||||||
return sdkerrors.Wrapf(sdkerrors.ErrPackAny, "%T", field.Interface())
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
anyWrapper := &cosmosAnyWrapper{
|
// If field is an empty value, do not include in types, since it will not be present in the object
|
||||||
Type: any.TypeUrl,
|
if field.IsZero() {
|
||||||
}
|
|
||||||
|
|
||||||
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() {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,6 +246,12 @@ func traverseFields(
|
|||||||
fieldType = fieldType.Elem()
|
fieldType = fieldType.Elem()
|
||||||
field = field.Index(0)
|
field = field.Index(0)
|
||||||
isCollection = true
|
isCollection = true
|
||||||
|
|
||||||
|
if fieldType == cosmosAnyType {
|
||||||
|
if fieldType, field, err = unpackAny(cdc, field); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
@ -363,6 +342,27 @@ func jsonNameFromTag(tag reflect.StructTag) string {
|
|||||||
return parts[0]
|
return parts[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unpack the given Any value with Type/Value deconstruction
|
||||||
|
func unpackAny(cdc codectypes.AnyUnpacker, field reflect.Value) (reflect.Type, reflect.Value, error) {
|
||||||
|
any, ok := field.Interface().(*codectypes.Any)
|
||||||
|
if !ok {
|
||||||
|
return nil, reflect.Value{}, errorsmod.Wrapf(errortypes.ErrPackAny, "%T", field.Interface())
|
||||||
|
}
|
||||||
|
|
||||||
|
anyWrapper := &cosmosAnyWrapper{
|
||||||
|
Type: any.TypeUrl,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := cdc.UnpackAny(any, &anyWrapper.Value); err != nil {
|
||||||
|
return nil, reflect.Value{}, errorsmod.Wrap(err, "failed to unpack Any in msg struct")
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldType := reflect.TypeOf(anyWrapper)
|
||||||
|
field = reflect.ValueOf(anyWrapper)
|
||||||
|
|
||||||
|
return fieldType, field, nil
|
||||||
|
}
|
||||||
|
|
||||||
// _.foo_bar.baz -> TypeFooBarBaz
|
// _.foo_bar.baz -> TypeFooBarBaz
|
||||||
//
|
//
|
||||||
// this is needed for Geth's own signing code which doesn't
|
// this is needed for Geth's own signing code which doesn't
|
||||||
@ -465,7 +465,7 @@ func typToEth(typ reflect.Type) string {
|
|||||||
func doRecover(err *error) {
|
func doRecover(err *error) {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
if e, ok := r.(error); ok {
|
if e, ok := r.(error); ok {
|
||||||
e = sdkerrors.Wrap(e, "panicked with error")
|
e = errorsmod.Wrap(e, "panicked with error")
|
||||||
*err = e
|
*err = e
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
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
|
go 1.19
|
||||||
|
|
||||||
require (
|
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/armon/go-metrics v0.4.1
|
||||||
github.com/btcsuite/btcd v0.22.1
|
github.com/btcsuite/btcd v0.22.1
|
||||||
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce
|
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce
|
||||||
github.com/cosmos/cosmos-sdk v0.46.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/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/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/gogo/protobuf v1.3.3
|
||||||
github.com/golang/protobuf v1.5.2
|
github.com/golang/protobuf v1.5.2
|
||||||
github.com/gorilla/mux v1.8.0
|
github.com/gorilla/mux v1.8.0
|
||||||
@ -20,34 +23,32 @@ require (
|
|||||||
github.com/holiman/uint256 v1.2.1
|
github.com/holiman/uint256 v1.2.1
|
||||||
github.com/improbable-eng/grpc-web v0.15.0
|
github.com/improbable-eng/grpc-web v0.15.0
|
||||||
github.com/miguelmota/go-ethereum-hdwallet v0.1.1
|
github.com/miguelmota/go-ethereum-hdwallet v0.1.1
|
||||||
github.com/onsi/ginkgo/v2 v2.4.0
|
github.com/onsi/ginkgo/v2 v2.5.1
|
||||||
github.com/onsi/gomega v1.23.0
|
github.com/onsi/gomega v1.24.1
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/rakyll/statik v0.1.7
|
github.com/rakyll/statik v0.1.7
|
||||||
github.com/regen-network/cosmos-proto v0.3.1
|
|
||||||
github.com/rs/cors v1.8.2
|
github.com/rs/cors v1.8.2
|
||||||
github.com/spf13/cast v1.5.0
|
github.com/spf13/cast v1.5.0
|
||||||
github.com/spf13/cobra v1.6.1
|
github.com/spf13/cobra v1.6.1
|
||||||
github.com/spf13/viper v1.13.0
|
github.com/spf13/viper v1.14.0
|
||||||
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969
|
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969
|
||||||
github.com/stretchr/testify v1.8.1
|
github.com/stretchr/testify v1.8.1
|
||||||
github.com/tendermint/tendermint v0.34.22
|
github.com/tendermint/tendermint v0.34.23
|
||||||
github.com/tendermint/tm-db v0.6.7
|
github.com/tendermint/tm-db v0.6.7
|
||||||
github.com/tyler-smith/go-bip39 v1.1.0
|
github.com/tyler-smith/go-bip39 v1.1.0
|
||||||
golang.org/x/net v0.1.0
|
golang.org/x/net v0.2.0
|
||||||
golang.org/x/text v0.4.0
|
golang.org/x/text v0.4.0
|
||||||
google.golang.org/genproto v0.0.0-20221018160656-63c7b68cfc55
|
google.golang.org/genproto v0.0.0-20221116193143-41c2ba794472
|
||||||
google.golang.org/grpc v1.50.1
|
google.golang.org/grpc v1.51.0
|
||||||
google.golang.org/protobuf v1.28.1
|
|
||||||
sigs.k8s.io/yaml v1.3.0
|
sigs.k8s.io/yaml v1.3.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go v0.102.1 // indirect
|
cloud.google.com/go v0.105.0 // indirect
|
||||||
cloud.google.com/go/compute v1.7.0 // indirect
|
cloud.google.com/go/compute v1.12.1 // indirect
|
||||||
cloud.google.com/go/iam v0.4.0 // indirect
|
cloud.google.com/go/compute/metadata v0.2.1 // indirect
|
||||||
cloud.google.com/go/storage v1.22.1 // indirect
|
cloud.google.com/go/iam v0.7.0 // indirect
|
||||||
cosmossdk.io/errors v1.0.0-beta.7 // indirect
|
cloud.google.com/go/storage v1.27.0 // indirect
|
||||||
filippo.io/edwards25519 v1.0.0-rc.1 // indirect
|
filippo.io/edwards25519 v1.0.0-rc.1 // indirect
|
||||||
github.com/99designs/keyring v1.2.1 // indirect
|
github.com/99designs/keyring v1.2.1 // indirect
|
||||||
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect
|
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect
|
||||||
@ -68,7 +69,6 @@ require (
|
|||||||
github.com/coinbase/rosetta-sdk-go v0.7.9 // indirect
|
github.com/coinbase/rosetta-sdk-go v0.7.9 // indirect
|
||||||
github.com/confio/ics23/go v0.7.0 // indirect
|
github.com/confio/ics23/go v0.7.0 // indirect
|
||||||
github.com/cosmos/btcutil v1.0.4 // 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/gorocksdb v1.2.0 // indirect
|
||||||
github.com/cosmos/iavl v0.19.4 // indirect
|
github.com/cosmos/iavl v0.19.4 // indirect
|
||||||
github.com/cosmos/ledger-cosmos-go v0.11.1 // indirect
|
github.com/cosmos/ledger-cosmos-go v0.11.1 // indirect
|
||||||
@ -87,7 +87,7 @@ require (
|
|||||||
github.com/dvsekhvalnov/jose2go v1.5.0 // indirect
|
github.com/dvsekhvalnov/jose2go v1.5.0 // indirect
|
||||||
github.com/edsrzf/mmap-go v1.0.0 // indirect
|
github.com/edsrzf/mmap-go v1.0.0 // indirect
|
||||||
github.com/felixge/httpsnoop v1.0.1 // indirect
|
github.com/felixge/httpsnoop v1.0.1 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.5.4 // indirect
|
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||||
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect
|
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect
|
||||||
github.com/go-kit/kit v0.12.0 // indirect
|
github.com/go-kit/kit v0.12.0 // indirect
|
||||||
github.com/go-kit/log v0.2.1 // indirect
|
github.com/go-kit/log v0.2.1 // indirect
|
||||||
@ -105,9 +105,8 @@ require (
|
|||||||
github.com/google/go-cmp v0.5.9 // indirect
|
github.com/google/go-cmp v0.5.9 // indirect
|
||||||
github.com/google/orderedcode v0.0.1 // indirect
|
github.com/google/orderedcode v0.0.1 // indirect
|
||||||
github.com/google/uuid v1.3.0 // indirect
|
github.com/google/uuid v1.3.0 // indirect
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.1.0 // indirect
|
github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect
|
||||||
github.com/googleapis/gax-go/v2 v2.4.0 // indirect
|
github.com/googleapis/gax-go/v2 v2.6.0 // indirect
|
||||||
github.com/googleapis/go-type-adapters v1.0.0 // indirect
|
|
||||||
github.com/gorilla/handlers v1.5.1 // indirect
|
github.com/gorilla/handlers v1.5.1 // indirect
|
||||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
|
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
|
||||||
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // 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/jmespath/go-jmespath v0.4.0 // indirect
|
||||||
github.com/jmhodges/levigo v1.0.0 // indirect
|
github.com/jmhodges/levigo v1.0.0 // indirect
|
||||||
github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d // indirect
|
github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d // indirect
|
||||||
github.com/klauspost/compress v1.15.9 // indirect
|
github.com/klauspost/compress v1.15.11 // indirect
|
||||||
github.com/lib/pq v1.10.6 // indirect
|
github.com/lib/pq v1.10.6 // indirect
|
||||||
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
|
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
|
||||||
github.com/magiconair/properties v1.8.6 // 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_golang v1.12.2 // indirect
|
||||||
github.com/prometheus/client_model v0.2.0 // indirect
|
github.com/prometheus/client_model v0.2.0 // indirect
|
||||||
github.com/prometheus/common v0.34.0 // indirect
|
github.com/prometheus/common v0.34.0 // indirect
|
||||||
github.com/prometheus/procfs v0.7.3 // indirect
|
github.com/prometheus/procfs v0.8.0 // indirect
|
||||||
github.com/prometheus/tsdb v0.7.1 // indirect
|
github.com/prometheus/tsdb v0.7.1 // indirect
|
||||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
|
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
|
||||||
|
github.com/regen-network/cosmos-proto v0.3.1 // indirect
|
||||||
github.com/rjeczalik/notify v0.9.1 // indirect
|
github.com/rjeczalik/notify v0.9.1 // indirect
|
||||||
github.com/rs/zerolog v1.27.0 // indirect
|
github.com/rs/zerolog v1.27.0 // indirect
|
||||||
github.com/sasha-s/go-deadlock v0.3.1 // indirect
|
github.com/sasha-s/go-deadlock v0.3.1 // indirect
|
||||||
@ -173,15 +173,16 @@ require (
|
|||||||
github.com/zondax/hid v0.9.1-0.20220302062450-5552068d2266 // indirect
|
github.com/zondax/hid v0.9.1-0.20220302062450-5552068d2266 // indirect
|
||||||
go.etcd.io/bbolt v1.3.6 // indirect
|
go.etcd.io/bbolt v1.3.6 // indirect
|
||||||
go.opencensus.io v0.23.0 // 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/exp v0.0.0-20220722155223-a9213eeb770e // indirect
|
||||||
golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2 // indirect
|
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect
|
||||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde // indirect
|
golang.org/x/sync v0.1.0 // indirect
|
||||||
golang.org/x/sys v0.1.0 // indirect
|
golang.org/x/sys v0.2.0 // indirect
|
||||||
golang.org/x/term v0.1.0 // indirect
|
golang.org/x/term v0.2.0 // indirect
|
||||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // 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/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/ini.v1 v1.67.0 // indirect
|
||||||
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
|
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // 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.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.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.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
|
||||||
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
|
cloud.google.com/go v0.105.0 h1:DNtEKRBAAzeS4KyIory52wWHuClNaXJ5x1F7xa4q+5Y=
|
||||||
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
|
cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM=
|
||||||
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/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
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.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
cloud.google.com/go/bigquery v1.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.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
cloud.google.com/go/bigquery v1.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/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.12.1 h1:gKVJMEyqV5c/UnpzjjQbo3Rjvvqpr9B1DFSbJC4OXr0=
|
||||||
cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM=
|
cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU=
|
||||||
cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M=
|
cloud.google.com/go/compute/metadata v0.2.1 h1:efOwf5ymceDhK6PKMnnrTHP4pppY5L22mle96M1yP48=
|
||||||
cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s=
|
cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM=
|
||||||
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/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
cloud.google.com/go/datastore v1.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.7.0 h1:k4MuwOsS7zGJJ+QfZ5vBK8SgHBAvYN/23BWsiihJ1vs=
|
||||||
cloud.google.com/go/iam v0.4.0 h1:YBYU00SCDzZJdHqVc4I5d6lsklcYIjQZa1YmEz4jlSE=
|
cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg=
|
||||||
cloud.google.com/go/iam v0.4.0/go.mod h1:cbaZxyScUhxl7ZAkNWiALgihfP75wS/fUsVNaa1r3vA=
|
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.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.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
cloud.google.com/go/pubsub v1.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.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.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.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
|
||||||
cloud.google.com/go/storage v1.22.1 h1:F6IlQJZrZM++apn9V5/VfS3gbTUYg98PS3EMQAzqtfg=
|
cloud.google.com/go/storage v1.27.0 h1:YOO045NZI9RKfCj1c5A/ZtuuENUc8OAW+gHdGnDgyMQ=
|
||||||
cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y=
|
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=
|
collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE=
|
||||||
cosmossdk.io/errors v1.0.0-beta.7 h1:gypHW76pTQGVnHKo6QBkb4yFOJjC+sUGRc5Al3Odj1w=
|
cosmossdk.io/errors v1.0.0-beta.7 h1:gypHW76pTQGVnHKo6QBkb4yFOJjC+sUGRc5Al3Odj1w=
|
||||||
cosmossdk.io/errors v1.0.0-beta.7/go.mod h1:mz6FQMJRku4bY7aqS/Gwfcmr/ue91roMEKAmDUDpBfE=
|
cosmossdk.io/errors v1.0.0-beta.7/go.mod h1:mz6FQMJRku4bY7aqS/Gwfcmr/ue91roMEKAmDUDpBfE=
|
||||||
cosmossdk.io/math v1.0.0-beta.3 h1:TbZxSopz2LqjJ7aXYfn7nJSb8vNaBklW6BLpcei1qwM=
|
cosmossdk.io/math v1.0.0-beta.4 h1:JtKedVLGzA0vv84xjYmZ75RKG35Kf2WwcFu8IjRkIIw=
|
||||||
cosmossdk.io/math v1.0.0-beta.3/go.mod h1:3LYasri3Zna4XpbrTNdKsWmD5fHHkaNAod/mNT9XdE4=
|
cosmossdk.io/math v1.0.0-beta.4/go.mod h1:An0MllWJY6PxibUpnwGk8jOm+a/qIxlKmL5Zyp9NnaM=
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU=
|
filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU=
|
||||||
filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
|
filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
|
||||||
@ -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/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||||
github.com/DataDog/zstd v1.5.0/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
|
github.com/DataDog/zstd v1.5.0/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
|
||||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||||
github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA=
|
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
|
||||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
|
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
|
||||||
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
|
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
|
||||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||||
@ -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-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-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-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 h1:weh8u7Cneje73dDh+2tEVLUvyBc89iwepWCD8b8034E=
|
||||||
github.com/cockroachdb/apd/v2 v2.0.2/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw=
|
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=
|
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/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 h1:n7C2ngKXo7UC9gNyMNLbzqz7Asuf+7Qv4gnX/rOdQ44=
|
||||||
github.com/cosmos/btcutil v1.0.4/go.mod h1:Ffqc8Hn6TJUdDgHBwIZLtrLQC1KdJ9jGJl/TvgUaxbU=
|
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-alpha8 h1:d3pCRuMYYvGA5bM0ZbbjKn+AoQD4A7dyNG2wzwWalUw=
|
||||||
github.com/cosmos/cosmos-proto v1.0.0-alpha7/go.mod h1:dosO4pSAbJF8zWCzCoTWP7nNsjcvSUBQmniFxDg5daw=
|
github.com/cosmos/cosmos-proto v1.0.0-alpha8/go.mod h1:6/p+Bc4O8JKeZqe0VqUGTX31eoYqemTT4C1hLCWsO7I=
|
||||||
github.com/cosmos/cosmos-sdk v0.46.4 h1:I4CPfnz7lAPM7cEvvyTxL1h3M/ugbhTNr5ZRcnW8WsU=
|
github.com/cosmos/cosmos-sdk v0.46.6 h1:K9EZsqOZ2jQX3bIQUpn7Hk/YCoaJWRLU56PzvpX8INk=
|
||||||
github.com/cosmos/cosmos-sdk v0.46.4/go.mod h1:b5usG7aBEEvhaatYCdV6orFbDUsj4BG1V6UtKwNcJeQ=
|
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 h1:iKclrn3YEOwk4jQHT2ulgzuXyxmzmPczUalMwW4XH9k=
|
||||||
github.com/cosmos/cosmos-sdk/ics23/go v0.8.0/go.mod h1:2a4dBq88TUoqoWAU5eu0lGvpFP3wWDPgdHPargtyw30=
|
github.com/cosmos/cosmos-sdk/ics23/go v0.8.0/go.mod h1:2a4dBq88TUoqoWAU5eu0lGvpFP3wWDPgdHPargtyw30=
|
||||||
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y=
|
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y=
|
||||||
github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY=
|
github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY=
|
||||||
github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw=
|
github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw=
|
||||||
|
github.com/cosmos/gogoproto v1.4.3 h1:RP3yyVREh9snv/lsOvmsAPQt8f44LgL281X0IOIhhcI=
|
||||||
|
github.com/cosmos/gogoproto v1.4.3/go.mod h1:0hLIG5TR7IvV1fme1HCFKjfzW9X2x0Mo+RooWXCnOWU=
|
||||||
github.com/cosmos/gorocksdb v1.2.0 h1:d0l3jJG8M4hBouIZq0mDUHZ+zjOx044J3nGRskwTb4Y=
|
github.com/cosmos/gorocksdb v1.2.0 h1:d0l3jJG8M4hBouIZq0mDUHZ+zjOx044J3nGRskwTb4Y=
|
||||||
github.com/cosmos/gorocksdb v1.2.0/go.mod h1:aaKvKItm514hKfNJpUJXnnOWeBnk2GL4+Qw9NHizILw=
|
github.com/cosmos/gorocksdb v1.2.0/go.mod h1:aaKvKItm514hKfNJpUJXnnOWeBnk2GL4+Qw9NHizILw=
|
||||||
github.com/cosmos/iavl v0.19.4 h1:t82sN+Y0WeqxDLJRSpNd8YFX5URIrT+p8n6oJbJ2Dok=
|
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/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.1.0 h1:m1NHXFkwwvNeJegZqtyox1WLinh+PMy4ivU/Cs9KjeA=
|
||||||
github.com/cosmos/ibc-go/v5 v5.0.1/go.mod h1:LX0DHLW3dfi/1e4BJzi8MGLWmQ4DSraPEgVjyo3VzAo=
|
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 h1:DdzS1m6o/pCqeZ8VOAit/gyATedRgjvkVI+UCrLpyuU=
|
||||||
github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76/go.mod h1:0mkLWIoZuQ7uBoospo5Q9zIpqq6rYCPJDSUdeCJvPM8=
|
github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76/go.mod h1:0mkLWIoZuQ7uBoospo5Q9zIpqq6rYCPJDSUdeCJvPM8=
|
||||||
github.com/cosmos/ledger-cosmos-go v0.11.1 h1:9JIYsGnXP613pb2vPjFeMMjBI5lEDsEaF6oYorTy6J4=
|
github.com/cosmos/ledger-cosmos-go v0.11.1 h1:9JIYsGnXP613pb2vPjFeMMjBI5lEDsEaF6oYorTy6J4=
|
||||||
github.com/cosmos/ledger-cosmos-go v0.11.1/go.mod h1:J8//BsAGTo3OC/vDLjMRFLW6q0WAaXvHnVc7ZmE8iUY=
|
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 h1:Nnao/dLwaVTk1Q5U9THldpUMMXU94BOTWPddSmVB6pI=
|
||||||
github.com/cosmos/ledger-go v0.9.2/go.mod h1:oZJ2hHAZROdlHiwTg4t7kP+GKIIkBT+o6c9QWFanOyI=
|
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 v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
github.com/creachadair/taskgroup v0.3.2 h1:zlfutDS+5XG40AOxcHDSThxKzns8Tnr9jnr6VqkYlkM=
|
github.com/creachadair/taskgroup v0.3.2 h1:zlfutDS+5XG40AOxcHDSThxKzns8Tnr9jnr6VqkYlkM=
|
||||||
github.com/creachadair/taskgroup v0.3.2/go.mod h1:wieWwecHVzsidg2CsUnFinW1faVN4+kq+TDlRJQ0Wbk=
|
github.com/creachadair/taskgroup v0.3.2/go.mod h1:wieWwecHVzsidg2CsUnFinW1faVN4+kq+TDlRJQ0Wbk=
|
||||||
@ -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/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
|
||||||
github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||||
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||||
github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA=
|
github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA=
|
||||||
github.com/dop251/goja v0.0.0-20211011172007-d99e4b8cbf48/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk=
|
github.com/dop251/goja v0.0.0-20211011172007-d99e4b8cbf48/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk=
|
||||||
github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf h1:Yt+4K30SdjOkRoRRm3vYNQgR+/ZIy0RmeUDZo7Y8zeQ=
|
github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf h1:Yt+4K30SdjOkRoRRm3vYNQgR+/ZIy0RmeUDZo7Y8zeQ=
|
||||||
@ -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.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.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.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/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg=
|
github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg=
|
||||||
github.com/ethereum/go-ethereum v1.10.17/go.mod h1:Lt5WzjM07XlXc95YzrhosmR4J9Ahd6X2wyEV2SvGhk0=
|
github.com/ethereum/go-ethereum v1.10.17/go.mod h1:Lt5WzjM07XlXc95YzrhosmR4J9Ahd6X2wyEV2SvGhk0=
|
||||||
github.com/ethereum/go-ethereum v1.10.19 h1:EOR5JbL4MD5yeOqv8W2iC1s4NximrTjqFccUz8lyBRA=
|
github.com/ethereum/go-ethereum v1.10.25 h1:5dFrKJDnYf8L6/5o42abCE6a9yJm9cs4EJVRyYMr55s=
|
||||||
github.com/ethereum/go-ethereum v1.10.19/go.mod h1:IJBNMtzKcNHPtllYihy6BL2IgK1u+32JriaTbdt4v+w=
|
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/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0=
|
||||||
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A=
|
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A=
|
||||||
github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk=
|
github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk=
|
||||||
@ -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/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
|
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||||
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
|
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||||
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI=
|
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI=
|
||||||
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
|
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
|
||||||
github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
|
github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
|
||||||
@ -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.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.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.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 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.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.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.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.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
github.com/golang/protobuf v1.4.3/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.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 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
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=
|
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.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.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 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
||||||
@ -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.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.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 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 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us=
|
||||||
github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20=
|
github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20=
|
||||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-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-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-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-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/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.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/google/uuid v1.1.1/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.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 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
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.2.0 h1:y8Yozv7SZtlU//QXbezB6QkpuE6jMD2/gfzk4AftXjs=
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.1.0 h1:zO8WHNx/MYiAKJ3d5spxZXZE6KHmIQGQcAzwUzV7qQw=
|
github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg=
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
|
|
||||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
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.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.6.0 h1:SXk3ABtQYDT/OH8jAyvEOQ58mgawq5C4o/4/89qN2ZU=
|
||||||
github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
|
github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY=
|
||||||
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/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
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/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
github.com/gorilla/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.2/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||||
github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||||
github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||||
github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
|
github.com/klauspost/compress v1.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c=
|
||||||
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
|
||||||
github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||||
github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg=
|
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=
|
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.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||||
github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA=
|
github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA=
|
||||||
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||||
github.com/onsi/ginkgo/v2 v2.4.0 h1:+Ig9nvqgS5OBSACXNk15PLdp0U9XPYROt9CFzVdFGIs=
|
github.com/onsi/ginkgo/v2 v2.5.1 h1:auzK7OI497k6x4OvWq+TKAcpcSAlod0doAH72oIN0Jw=
|
||||||
github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo=
|
github.com/onsi/ginkgo/v2 v2.5.1/go.mod h1:63DOGlLAH8+REH8jUGdL3YpCpu7JODesutUjdENfUAc=
|
||||||
github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||||
github.com/onsi/gomega v1.23.0 h1:/oxKu9c2HVap+F3PfKort2Hw5DEU+HGlW8n+tguWsys=
|
github.com/onsi/gomega v1.24.1 h1:KORJXNNTzJXzu4ScJWssJfJMnJ+2QJqhoQSRwNlze9E=
|
||||||
github.com/onsi/gomega v1.23.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg=
|
github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM=
|
||||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||||
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 h1:rc3tiVYb5z54aKaDfakKn0dDjIyPpTtszkjuMzyt7ec=
|
github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034=
|
||||||
github.com/opencontainers/runc v1.1.3 h1:vIXrkId+0/J2Ymu2m7VjGvbSlAId9XNRPhn2p4b+d8w=
|
github.com/opencontainers/runc v1.1.3 h1:vIXrkId+0/J2Ymu2m7VjGvbSlAId9XNRPhn2p4b+d8w=
|
||||||
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
|
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
|
||||||
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
|
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
|
||||||
@ -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.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||||
github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||||
github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
|
|
||||||
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||||
|
github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
|
||||||
|
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
|
||||||
github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA=
|
github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA=
|
||||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||||
github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ=
|
github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ=
|
||||||
@ -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 v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
|
github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg=
|
||||||
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||||
github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U=
|
github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U=
|
||||||
github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
|
github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
|
||||||
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||||
github.com/rs/zerolog v1.27.0 h1:1T7qCieN22GVc8S4Q2yuexzBb1EqjbgjSH9RohbMjKs=
|
github.com/rs/zerolog v1.27.0 h1:1T7qCieN22GVc8S4Q2yuexzBb1EqjbgjSH9RohbMjKs=
|
||||||
github.com/rs/zerolog v1.27.0/go.mod h1:7frBqO0oezxmnO7GF86FY++uy8I0Tk/If5ni1G9Qc0U=
|
github.com/rs/zerolog v1.27.0/go.mod h1:7frBqO0oezxmnO7GF86FY++uy8I0Tk/If5ni1G9Qc0U=
|
||||||
|
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
|
||||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||||
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
||||||
@ -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 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||||
github.com/spf13/viper v1.13.0 h1:BWSJ/M+f+3nmdz9bxB+bWX28kkALN2ok11D0rSo8EJU=
|
github.com/spf13/viper v1.14.0 h1:Rg7d3Lo706X9tHsJMUjdiwMpHB7W8WnSVOssIY+JElU=
|
||||||
github.com/spf13/viper v1.13.0/go.mod h1:Icm2xNL3/8uyh/wFuB1jI7TiTNKp8632Nwegu+zgdYw=
|
github.com/spf13/viper v1.14.0/go.mod h1:WT//axPky3FdvXHzGw33dNdXXXfFQqmEalje+egj8As=
|
||||||
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
|
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
|
||||||
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969 h1:Oo2KZNP70KE0+IUJSidPj/BFS/RXNHmKIJOdckzml2E=
|
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969 h1:Oo2KZNP70KE0+IUJSidPj/BFS/RXNHmKIJOdckzml2E=
|
||||||
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
|
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
|
||||||
@ -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/crypto v0.0.0-20191022145703-50d29ede1e15/go.mod h1:z4YtwM70uOnk8h0pjJYlj3zdYwi9l03By6iAIF5j/Pk=
|
||||||
github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E=
|
github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E=
|
||||||
github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME=
|
github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME=
|
||||||
github.com/tendermint/tendermint v0.34.22 h1:XMhtC8s8QqJO4l/dn+TkQvevTRSow3Vixjclr41o+2Q=
|
github.com/tendermint/tendermint v0.34.23 h1:JZYsdc59aOiT5efou+BHILJv8x6FlRyvlor84Xq9Tb0=
|
||||||
github.com/tendermint/tendermint v0.34.22/go.mod h1:YpP5vBEAKUT4g6oyfjKgFeZmdB/GjkJAxfF+cgmJg6Y=
|
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 h1:fE00Cbl0jayAoqlExN6oyQJ7fR/ZtoVOmvPJ//+shu8=
|
||||||
github.com/tendermint/tm-db v0.6.7/go.mod h1:byQDzFkZV1syXr/ReXS808NxA2xvyuuVgXOJ/088L6I=
|
github.com/tendermint/tm-db v0.6.7/go.mod h1:byQDzFkZV1syXr/ReXS808NxA2xvyuuVgXOJ/088L6I=
|
||||||
github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||||
@ -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 h1:ERv8V6GKqVi23rgu5cj9pVfVzJbOqAY2Ntl88O6c2nQ=
|
||||||
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||||
|
github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY=
|
||||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||||
|
github.com/urfave/cli/v2 v2.10.2 h1:x3p8awjp/2arX+Nl/G2040AZpOCHS/eMJJ1/a+mye4Y=
|
||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||||
@ -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/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||||
github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
|
github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
|
||||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||||
|
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
|
||||||
github.com/ybbus/jsonrpc v2.1.2+incompatible/go.mod h1:XJrh1eMSzdIYFbM08flv0wp5G35eRniyeGut1z+LSiE=
|
github.com/ybbus/jsonrpc v2.1.2+incompatible/go.mod h1:XJrh1eMSzdIYFbM08flv0wp5G35eRniyeGut1z+LSiE=
|
||||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.27/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.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 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
|
||||||
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
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.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.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
go.uber.org/atomic v1.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-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-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.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
|
golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A=
|
||||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
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-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-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/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-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-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-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-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/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
golang.org/x/mod v0.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.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.4.1/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.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-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
@ -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-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-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-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-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-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-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/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-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-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU=
|
||||||
golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||||
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/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
@ -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-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-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-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-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-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-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk=
|
||||||
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
|
||||||
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/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
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-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-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-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-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-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.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde h1:ejfdSekXMDxDLbRrJMwUk6KnSLZ2McaUCVcIKM+N6jc=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/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-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-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-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-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.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.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.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-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-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.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw=
|
golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM=
|
||||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
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.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.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.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-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs=
|
golang.org/x/time v0.0.0-20220609170525-579cf78fd858 h1:Dpdu/EMxGMFgq0CeYMh4fazTD2vtlZRYE7wyynxJb9U=
|
||||||
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
@ -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-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/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.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
|
||||||
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
|
||||||
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
|
||||||
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
|
||||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.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-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/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 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
|
||||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||||
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
|
gonum.org/v1/gonum v0.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.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
|
||||||
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
|
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.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
|
||||||
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
|
google.golang.org/api v0.102.0 h1:JxJl2qQ85fRMPNvlZY/enexbxpCjLwGhZUtgfGeQ51I=
|
||||||
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
|
google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo=
|
||||||
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/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
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.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.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-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-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-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-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-20221116193143-41c2ba794472 h1:kIfItBRE5gkUKpH4H5lNGciZbka1JrmRli3ArqrKFkA=
|
||||||
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20221116193143-41c2ba794472/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
|
||||||
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/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
@ -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.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.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.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U=
|
||||||
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww=
|
||||||
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/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
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-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
google.golang.org/protobuf 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.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8 h1:KR8+MyP7/qOlV+8Af01LtjL04bu7on42eVsxT4EyBQk=
|
||||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8/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=
|
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
@ -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/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0=
|
|
||||||
gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0=
|
gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0=
|
||||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||||
@ -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=
|
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 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k=
|
||||||
nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
|
nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
|
||||||
pgregory.net/rapid v0.4.7 h1:MTNRktPuv5FNqOO151TM9mDTa+XHcX6ypYeISDVD14g=
|
pgregory.net/rapid v0.5.3 h1:163N50IHFqr1phZens4FQOdPgfJscR7a562mjQqeo4M=
|
||||||
pgregory.net/rapid v0.4.7/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU=
|
|
||||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||||
|
121
gomod2nix.toml
121
gomod2nix.toml
@ -2,23 +2,26 @@ schema = 3
|
|||||||
|
|
||||||
[mod]
|
[mod]
|
||||||
[mod."cloud.google.com/go"]
|
[mod."cloud.google.com/go"]
|
||||||
version = "v0.102.1"
|
version = "v0.105.0"
|
||||||
hash = "sha256-rv3MHFvIrN6AcrmWcWGSQwgaZLbjJMmJFi3bsfHoiO4="
|
hash = "sha256-2nYtHjuN9ghGcM6aPlOxyNNarHebHtj0Xec48sWwdaI="
|
||||||
[mod."cloud.google.com/go/compute"]
|
[mod."cloud.google.com/go/compute"]
|
||||||
version = "v1.7.0"
|
version = "v1.12.1"
|
||||||
hash = "sha256-g+n7L36LC+NP4KaiEu9fCMn6S9fkxjp4PCLOp/oXV38="
|
hash = "sha256-mMsdL+6R1KuFeAFqEJv8oq/cmRc9hSluEisCpGP0GTc="
|
||||||
|
[mod."cloud.google.com/go/compute/metadata"]
|
||||||
|
version = "v0.2.1"
|
||||||
|
hash = "sha256-gqjkb6y5POkTWXGQtCvgygvXqoLkESB+cykKp7Mp3jI="
|
||||||
[mod."cloud.google.com/go/iam"]
|
[mod."cloud.google.com/go/iam"]
|
||||||
version = "v0.4.0"
|
version = "v0.7.0"
|
||||||
hash = "sha256-sPtj6QPPC/QrkDXJW4Y7rMIHk5l1y9XV/DgM47eEtvg="
|
hash = "sha256-2UTJ/BbZ+YMGJhyo3HRPUYVDXW6+B5znFdqiutboYtA="
|
||||||
[mod."cloud.google.com/go/storage"]
|
[mod."cloud.google.com/go/storage"]
|
||||||
version = "v1.22.1"
|
version = "v1.27.0"
|
||||||
hash = "sha256-YZt05wru0kacyi6moTgvocavActKpXx7FlLh+o0HGDs="
|
hash = "sha256-V4B6A1Ms8cemB5Cs6nAtUe1N1ldaI9oqTdzGU2FUhrc="
|
||||||
[mod."cosmossdk.io/errors"]
|
[mod."cosmossdk.io/errors"]
|
||||||
version = "v1.0.0-beta.7"
|
version = "v1.0.0-beta.7"
|
||||||
hash = "sha256-XblGvIx6Wvvq6wggXjp+KbeJGXoe7AZH7hXEdauCezU="
|
hash = "sha256-XblGvIx6Wvvq6wggXjp+KbeJGXoe7AZH7hXEdauCezU="
|
||||||
[mod."cosmossdk.io/math"]
|
[mod."cosmossdk.io/math"]
|
||||||
version = "v1.0.0-beta.3"
|
version = "v1.0.0-beta.4"
|
||||||
hash = "sha256-lTQ27ZlL+kWlc+S//sJmyiOwaf9qS+YLv61I4OXi9XE="
|
hash = "sha256-UYdq/46EubyjxkldGike8FlwJLWGCB576VB7th285ao="
|
||||||
[mod."filippo.io/edwards25519"]
|
[mod."filippo.io/edwards25519"]
|
||||||
version = "v1.0.0-rc.1"
|
version = "v1.0.0-rc.1"
|
||||||
hash = "sha256-3DboBqby2ejRU33FG96Z8JF5AJ8HP2rC/v++VyoQ2LQ="
|
hash = "sha256-3DboBqby2ejRU33FG96Z8JF5AJ8HP2rC/v++VyoQ2LQ="
|
||||||
@ -91,14 +94,17 @@ schema = 3
|
|||||||
version = "v1.0.4"
|
version = "v1.0.4"
|
||||||
hash = "sha256-JvcBXBdjdmnaW/nyf/tw/uaOAGn1b78yxrtl2/Rs3kA="
|
hash = "sha256-JvcBXBdjdmnaW/nyf/tw/uaOAGn1b78yxrtl2/Rs3kA="
|
||||||
[mod."github.com/cosmos/cosmos-proto"]
|
[mod."github.com/cosmos/cosmos-proto"]
|
||||||
version = "v1.0.0-alpha7"
|
version = "v1.0.0-alpha8"
|
||||||
hash = "sha256-2wCH+toTF2A6MfFjOa13muEH5oBCcxAhZEqirNOrBA0="
|
hash = "sha256-iXzXoS5Kfh5DBy+PhdFWraDWXda/3M4j7j4VECjv4CA="
|
||||||
[mod."github.com/cosmos/cosmos-sdk"]
|
[mod."github.com/cosmos/cosmos-sdk"]
|
||||||
version = "v0.46.4"
|
version = "v0.46.6"
|
||||||
hash = "sha256-YjrhZsGKMH7kxCS9Lhbvt7YjJs/B+9aSS+l042oBhAw="
|
hash = "sha256-H1VZxZUWXhpXiY3A9smLp09MEGpXmh+XvX6YUiXPcpQ="
|
||||||
[mod."github.com/cosmos/go-bip39"]
|
[mod."github.com/cosmos/go-bip39"]
|
||||||
version = "v1.0.0"
|
version = "v1.0.0"
|
||||||
hash = "sha256-Qm2aC2vaS8tjtMUbHmlBSagOSqbduEEDwc51qvQaBmA="
|
hash = "sha256-Qm2aC2vaS8tjtMUbHmlBSagOSqbduEEDwc51qvQaBmA="
|
||||||
|
[mod."github.com/cosmos/gogoproto"]
|
||||||
|
version = "v1.4.3"
|
||||||
|
hash = "sha256-Y/NL76ay/oAl8mS3skkK5ula0/xudqbwW1o22lZjKRg="
|
||||||
[mod."github.com/cosmos/gorocksdb"]
|
[mod."github.com/cosmos/gorocksdb"]
|
||||||
version = "v1.2.0"
|
version = "v1.2.0"
|
||||||
hash = "sha256-209TcVuXc5s/TcOvNlaQ1HEJAUDTEK3nxPhs+d8TEcY="
|
hash = "sha256-209TcVuXc5s/TcOvNlaQ1HEJAUDTEK3nxPhs+d8TEcY="
|
||||||
@ -106,8 +112,8 @@ schema = 3
|
|||||||
version = "v0.19.4"
|
version = "v0.19.4"
|
||||||
hash = "sha256-EmpRZ48pjPFq/fIHneut9Vyo5QJATfb3ZO7KzWnqs9g="
|
hash = "sha256-EmpRZ48pjPFq/fIHneut9Vyo5QJATfb3ZO7KzWnqs9g="
|
||||||
[mod."github.com/cosmos/ibc-go/v5"]
|
[mod."github.com/cosmos/ibc-go/v5"]
|
||||||
version = "v5.0.1"
|
version = "v5.1.0"
|
||||||
hash = "sha256-44Vyj9i4gh6U0BGNsEFqRsHAYdxfuJmLGdtPWxcBfWQ="
|
hash = "sha256-9ZwGw6XqYkBtj+vTQ2IodNb7VcGesTFnVsxjd+G1I6Q="
|
||||||
[mod."github.com/cosmos/ledger-cosmos-go"]
|
[mod."github.com/cosmos/ledger-cosmos-go"]
|
||||||
version = "v0.11.1"
|
version = "v0.11.1"
|
||||||
hash = "sha256-yli+VvVtZmHo2LPvCY6lYVUfcCDn3sBLDL+a8KIlqDA="
|
hash = "sha256-yli+VvVtZmHo2LPvCY6lYVUfcCDn3sBLDL+a8KIlqDA="
|
||||||
@ -157,14 +163,14 @@ schema = 3
|
|||||||
version = "v1.0.0"
|
version = "v1.0.0"
|
||||||
hash = "sha256-k1DYvCqO3BKNcGEve/nMW0RxzMkK2tGfXbUbycqcVSo="
|
hash = "sha256-k1DYvCqO3BKNcGEve/nMW0RxzMkK2tGfXbUbycqcVSo="
|
||||||
[mod."github.com/ethereum/go-ethereum"]
|
[mod."github.com/ethereum/go-ethereum"]
|
||||||
version = "v1.10.19"
|
version = "v1.10.25"
|
||||||
hash = "sha256-7FPnTGcCb8Xd1QVR+6PmGTaHdTY1mm/8osFTW1JLuG8="
|
hash = "sha256-tNlI2XyuTXjGuBoe5vlYDcaGN2Sub7yltVtI6TeLLSc="
|
||||||
[mod."github.com/felixge/httpsnoop"]
|
[mod."github.com/felixge/httpsnoop"]
|
||||||
version = "v1.0.1"
|
version = "v1.0.1"
|
||||||
hash = "sha256-TNXnnC/ZGNY9lInAcES1cBGqIdEljKuh5LH/khVFjVk="
|
hash = "sha256-TNXnnC/ZGNY9lInAcES1cBGqIdEljKuh5LH/khVFjVk="
|
||||||
[mod."github.com/fsnotify/fsnotify"]
|
[mod."github.com/fsnotify/fsnotify"]
|
||||||
version = "v1.5.4"
|
version = "v1.6.0"
|
||||||
hash = "sha256-iPuInpDAJvDeSTr6to713J/fTOWdQIWlLXWAuWIs2Bw="
|
hash = "sha256-DQesOCweQPEwmAn6s7DCP/Dwy8IypC+osbpfsvpkdP0="
|
||||||
[mod."github.com/gballet/go-libpcsclite"]
|
[mod."github.com/gballet/go-libpcsclite"]
|
||||||
version = "v0.0.0-20190607065134-2772fd86a8ff"
|
version = "v0.0.0-20190607065134-2772fd86a8ff"
|
||||||
hash = "sha256-Nr5ocU9s1F2Lhx/Zq6/nIo+KkKEqMjDYOEs3yWRC48g="
|
hash = "sha256-Nr5ocU9s1F2Lhx/Zq6/nIo+KkKEqMjDYOEs3yWRC48g="
|
||||||
@ -224,14 +230,11 @@ schema = 3
|
|||||||
version = "v1.3.0"
|
version = "v1.3.0"
|
||||||
hash = "sha256-QoR55eBtA94T2tBszyxfDtO7/pjZZSGb5vm7U0Xhs0Y="
|
hash = "sha256-QoR55eBtA94T2tBszyxfDtO7/pjZZSGb5vm7U0Xhs0Y="
|
||||||
[mod."github.com/googleapis/enterprise-certificate-proxy"]
|
[mod."github.com/googleapis/enterprise-certificate-proxy"]
|
||||||
version = "v0.1.0"
|
version = "v0.2.0"
|
||||||
hash = "sha256-fxaElfiGGh1mLmltkFpVFdiuaagrLZLTW9btVpK13wg="
|
hash = "sha256-5gxsS5kDLqNFBkQ4eK6GS/sNn+aFknm6jjfteO+6jl4="
|
||||||
[mod."github.com/googleapis/gax-go/v2"]
|
[mod."github.com/googleapis/gax-go/v2"]
|
||||||
version = "v2.4.0"
|
version = "v2.6.0"
|
||||||
hash = "sha256-zzat4+3iF2XBTQ6RZAUgsCbfK0HgO0nYhM4utA5dqz0="
|
hash = "sha256-sSsncbJmv0n5jB3G7tHY1Zr2ucCusIeTrXZH4A8QqYI="
|
||||||
[mod."github.com/googleapis/go-type-adapters"]
|
|
||||||
version = "v1.0.0"
|
|
||||||
hash = "sha256-u3ajruRV/EN2E1WKet/zoe3zmRrAy4C5F2Dx8bpQwoc="
|
|
||||||
[mod."github.com/gorilla/handlers"]
|
[mod."github.com/gorilla/handlers"]
|
||||||
version = "v1.5.1"
|
version = "v1.5.1"
|
||||||
hash = "sha256-GnBAARgOx1E+hDMQ63SI17hdhGtLQxb31lZOmn5j/pU="
|
hash = "sha256-GnBAARgOx1E+hDMQ63SI17hdhGtLQxb31lZOmn5j/pU="
|
||||||
@ -308,8 +311,8 @@ schema = 3
|
|||||||
version = "v0.0.0-20190712205309-48d3d31d256d"
|
version = "v0.0.0-20190712205309-48d3d31d256d"
|
||||||
hash = "sha256-bn04wkDnhQ0tb/YzmPf7MNJlApOl+z6+EAbUqH7Ti5Q="
|
hash = "sha256-bn04wkDnhQ0tb/YzmPf7MNJlApOl+z6+EAbUqH7Ti5Q="
|
||||||
[mod."github.com/klauspost/compress"]
|
[mod."github.com/klauspost/compress"]
|
||||||
version = "v1.15.9"
|
version = "v1.15.11"
|
||||||
hash = "sha256-ctPxlVq0c/SoNPVsP66RjxUjTHys3diW2Apxjyc9WdE="
|
hash = "sha256-9MXm0TObg6DyqnYMIw3IChrorHc2ILf5djZYoM0e1J0="
|
||||||
[mod."github.com/lib/pq"]
|
[mod."github.com/lib/pq"]
|
||||||
version = "v1.10.6"
|
version = "v1.10.6"
|
||||||
hash = "sha256-8EhFwY/9YH5L/fd6l2beOnC3VvpegRAmCCsnDVJBqBM="
|
hash = "sha256-8EhFwY/9YH5L/fd6l2beOnC3VvpegRAmCCsnDVJBqBM="
|
||||||
@ -359,11 +362,11 @@ schema = 3
|
|||||||
version = "v0.0.5"
|
version = "v0.0.5"
|
||||||
hash = "sha256-/5i70IkH/qSW5KjGzv8aQNKh9tHoz98tqtL0K2DMFn4="
|
hash = "sha256-/5i70IkH/qSW5KjGzv8aQNKh9tHoz98tqtL0K2DMFn4="
|
||||||
[mod."github.com/onsi/ginkgo/v2"]
|
[mod."github.com/onsi/ginkgo/v2"]
|
||||||
version = "v2.4.0"
|
version = "v2.5.1"
|
||||||
hash = "sha256-Z+bch118Akc5wGkOM7ZePNqw7vW5euXE7ec4Y297HNw="
|
hash = "sha256-VB29+H9k7l6il63oXJvsjamSUhsw/e99iI/BeTCderA="
|
||||||
[mod."github.com/onsi/gomega"]
|
[mod."github.com/onsi/gomega"]
|
||||||
version = "v1.23.0"
|
version = "v1.24.1"
|
||||||
hash = "sha256-g5FaFLUK8ZAR9VgFTTH0ax0t45tZkYbIHbq/gANIOTM="
|
hash = "sha256-REfxQTDRcO23GnmJfOW8/MmPJf9oE2grVvvGiC1eSbo="
|
||||||
[mod."github.com/pelletier/go-toml"]
|
[mod."github.com/pelletier/go-toml"]
|
||||||
version = "v1.9.5"
|
version = "v1.9.5"
|
||||||
hash = "sha256-RJ9K1BTId0Mled7S66iGgxHkZ5JKEIsrrNaEfM8aImc="
|
hash = "sha256-RJ9K1BTId0Mled7S66iGgxHkZ5JKEIsrrNaEfM8aImc="
|
||||||
@ -389,8 +392,8 @@ schema = 3
|
|||||||
version = "v0.34.0"
|
version = "v0.34.0"
|
||||||
hash = "sha256-M+v+7DntUBmiQNzfNmG3aLLufbl0XBQOubtYoNTzJDA="
|
hash = "sha256-M+v+7DntUBmiQNzfNmG3aLLufbl0XBQOubtYoNTzJDA="
|
||||||
[mod."github.com/prometheus/procfs"]
|
[mod."github.com/prometheus/procfs"]
|
||||||
version = "v0.7.3"
|
version = "v0.8.0"
|
||||||
hash = "sha256-ik0WpnpSjMwifPYfQTfu/eb5ilNj+eLJF0d5Dftp8A8="
|
hash = "sha256-hgrilokQsXCOCCvwgOSfuErxoFAQpXM/+zNJKcMVHyM="
|
||||||
[mod."github.com/prometheus/tsdb"]
|
[mod."github.com/prometheus/tsdb"]
|
||||||
version = "v0.7.1"
|
version = "v0.7.1"
|
||||||
hash = "sha256-BPz7YJbfMZgeR+u9YaeWeipVzHIS73EdgXD7VSJSLbA="
|
hash = "sha256-BPz7YJbfMZgeR+u9YaeWeipVzHIS73EdgXD7VSJSLbA="
|
||||||
@ -434,8 +437,8 @@ schema = 3
|
|||||||
version = "v1.0.5"
|
version = "v1.0.5"
|
||||||
hash = "sha256-w9LLYzxxP74WHT4ouBspH/iQZXjuAh2WQCHsuvyEjAw="
|
hash = "sha256-w9LLYzxxP74WHT4ouBspH/iQZXjuAh2WQCHsuvyEjAw="
|
||||||
[mod."github.com/spf13/viper"]
|
[mod."github.com/spf13/viper"]
|
||||||
version = "v1.13.0"
|
version = "v1.14.0"
|
||||||
hash = "sha256-yHviS3lMo1hB6jwyiU3zpyGtxP6v9AsyZUKiLeCVz+k="
|
hash = "sha256-qn3VzD339HZIub5QP4aWVciSufAfVb9llbmQZ8pfDEs="
|
||||||
[mod."github.com/status-im/keycard-go"]
|
[mod."github.com/status-im/keycard-go"]
|
||||||
version = "v0.0.0-20200402102358-957c09536969"
|
version = "v0.0.0-20200402102358-957c09536969"
|
||||||
hash = "sha256-yddXXuu6mEFEO2/K6c1tWymeBKzOcvLQnNsFGRjtfXk="
|
hash = "sha256-yddXXuu6mEFEO2/K6c1tWymeBKzOcvLQnNsFGRjtfXk="
|
||||||
@ -461,8 +464,8 @@ schema = 3
|
|||||||
version = "v0.16.0"
|
version = "v0.16.0"
|
||||||
hash = "sha256-JW4zO/0vMzf1dXLePOqaMtiLUZgNbuIseh9GV+jQlf0="
|
hash = "sha256-JW4zO/0vMzf1dXLePOqaMtiLUZgNbuIseh9GV+jQlf0="
|
||||||
[mod."github.com/tendermint/tendermint"]
|
[mod."github.com/tendermint/tendermint"]
|
||||||
version = "v0.34.22"
|
version = "v0.34.23"
|
||||||
hash = "sha256-4p4cpyCWjBbNQUpYN2gDJvnyj+Pov9hw5uRjHrrO++Y="
|
hash = "sha256-eir0vr8lQOG+FTPo+ZUeDidAIACfyUq2ie3XRE8rIa4="
|
||||||
[mod."github.com/tendermint/tm-db"]
|
[mod."github.com/tendermint/tm-db"]
|
||||||
version = "v0.6.7"
|
version = "v0.6.7"
|
||||||
hash = "sha256-hl/3RrBrpkk2zA6dmrNlIYKs1/GfqegSscDSkA5Pjlo="
|
hash = "sha256-hl/3RrBrpkk2zA6dmrNlIYKs1/GfqegSscDSkA5Pjlo="
|
||||||
@ -488,26 +491,26 @@ schema = 3
|
|||||||
version = "v0.23.0"
|
version = "v0.23.0"
|
||||||
hash = "sha256-R3O9GyNtv6j0ic7s+2xkLLaLzbJEop0Otj1nJDFBjsg="
|
hash = "sha256-R3O9GyNtv6j0ic7s+2xkLLaLzbJEop0Otj1nJDFBjsg="
|
||||||
[mod."golang.org/x/crypto"]
|
[mod."golang.org/x/crypto"]
|
||||||
version = "v0.1.0"
|
version = "v0.3.0"
|
||||||
hash = "sha256-0oZWBSiW5Pd/2a1p2beuoelDe0CpfXZhrg/qPduJlYs="
|
hash = "sha256-Un9wPqz8u/xpV98T4IqE6RMXIPhGCIm2prsNkHP3cjg="
|
||||||
[mod."golang.org/x/exp"]
|
[mod."golang.org/x/exp"]
|
||||||
version = "v0.0.0-20220722155223-a9213eeb770e"
|
version = "v0.0.0-20220722155223-a9213eeb770e"
|
||||||
hash = "sha256-kNgzydWRpjm0sZl4uXEs3LX5L0xjJtJRAFf/CTlYUN4="
|
hash = "sha256-kNgzydWRpjm0sZl4uXEs3LX5L0xjJtJRAFf/CTlYUN4="
|
||||||
[mod."golang.org/x/net"]
|
[mod."golang.org/x/net"]
|
||||||
version = "v0.1.0"
|
version = "v0.2.0"
|
||||||
hash = "sha256-SrThFBg6sqGYpiN1E3d1SilJxbKkQhSZXPmAFoMAA/I="
|
hash = "sha256-0MqnHDdLkkau6k7hlWD9MzIoAFROvxulyT+KzZkSXOs="
|
||||||
[mod."golang.org/x/oauth2"]
|
[mod."golang.org/x/oauth2"]
|
||||||
version = "v0.0.0-20220622183110-fd043fe589d2"
|
version = "v0.0.0-20221014153046-6fdb5e3db783"
|
||||||
hash = "sha256-VLffpTpx3DlUzXB8mKiJfFzm4ZmgnLSUuLB5Ir0WQUg="
|
hash = "sha256-IoygidVNqyAZmN+3macDeIefK8hhJToygpcqlwehdYQ="
|
||||||
[mod."golang.org/x/sync"]
|
[mod."golang.org/x/sync"]
|
||||||
version = "v0.0.0-20220819030929-7fc1605a5dde"
|
version = "v0.1.0"
|
||||||
hash = "sha256-5EOxO8FRdaLW9v/DhwBmWiT2G34A2ofxSCaC7ovvpb0="
|
hash = "sha256-Hygjq9euZ0qz6TvHYQwOZEjNiTbTh1nSLRAWZ6KFGR8="
|
||||||
[mod."golang.org/x/sys"]
|
[mod."golang.org/x/sys"]
|
||||||
version = "v0.1.0"
|
version = "v0.2.0"
|
||||||
hash = "sha256-nZbEJ/2PuWrDLD4ujeVvcFGoIsfVoIH/Lcp4FjD7hpU="
|
hash = "sha256-N6yfQH7R2gfcvyWTQZbxWuSNyVy6hAxiab2WFzgAykI="
|
||||||
[mod."golang.org/x/term"]
|
[mod."golang.org/x/term"]
|
||||||
version = "v0.1.0"
|
version = "v0.2.0"
|
||||||
hash = "sha256-UWnNsJIj5nXsuzlPWQ1NyHQuHStaDacMVkFbJ4pnxXk="
|
hash = "sha256-azcllZ0o/9TurqX9udaJ0o9yxqSoI0/bSJsvQQLYIQc="
|
||||||
[mod."golang.org/x/text"]
|
[mod."golang.org/x/text"]
|
||||||
version = "v0.4.0"
|
version = "v0.4.0"
|
||||||
hash = "sha256-JvyMygdmTvWg7xhbnUB9MMk6WcYXJt8DAj4DYl82Pys="
|
hash = "sha256-JvyMygdmTvWg7xhbnUB9MMk6WcYXJt8DAj4DYl82Pys="
|
||||||
@ -515,20 +518,20 @@ schema = 3
|
|||||||
version = "v0.0.0-20220907171357-04be3eba64a2"
|
version = "v0.0.0-20220907171357-04be3eba64a2"
|
||||||
hash = "sha256-6+zueutgefIYmgXinOflz8qGDDDj0Zhv+2OkGhBTKno="
|
hash = "sha256-6+zueutgefIYmgXinOflz8qGDDDj0Zhv+2OkGhBTKno="
|
||||||
[mod."google.golang.org/api"]
|
[mod."google.golang.org/api"]
|
||||||
version = "v0.93.0"
|
version = "v0.102.0"
|
||||||
hash = "sha256-W17B79osAhObMbrCHlgywEPg9yIPx0ZISDhp9JwFE5A="
|
hash = "sha256-q8t08Wu0qzOQOmhY4GSoUrhqLTW/TeXiKhio+5ONfe4="
|
||||||
[mod."google.golang.org/appengine"]
|
[mod."google.golang.org/appengine"]
|
||||||
version = "v1.6.7"
|
version = "v1.6.7"
|
||||||
hash = "sha256-zIxGRHiq4QBvRqkrhMGMGCaVL4iM4TtlYpAi/hrivS4="
|
hash = "sha256-zIxGRHiq4QBvRqkrhMGMGCaVL4iM4TtlYpAi/hrivS4="
|
||||||
[mod."google.golang.org/genproto"]
|
[mod."google.golang.org/genproto"]
|
||||||
version = "v0.0.0-20221018160656-63c7b68cfc55"
|
version = "v0.0.0-20221116193143-41c2ba794472"
|
||||||
hash = "sha256-Z4ynOw+3NkSkWVOrNaeuQC3G9Q6+joNbTLVoF2HegrU="
|
hash = "sha256-uQuxuOvWRsdMii5M5QresisVd1E+Ss8s2WfR2n7QSXk="
|
||||||
[mod."google.golang.org/grpc"]
|
[mod."google.golang.org/grpc"]
|
||||||
version = "v1.50.1"
|
version = "v1.51.0"
|
||||||
hash = "sha256-38nk4qIme+fE57SsCqNxtCZnc8fyzzi4Sb60uDTT2KE="
|
hash = "sha256-RzH5DU13D/ulxxOouIKpdNt8eHdff7mrEnB+JUupbLU="
|
||||||
[mod."google.golang.org/protobuf"]
|
[mod."google.golang.org/protobuf"]
|
||||||
version = "v1.28.1"
|
version = "v1.28.2-0.20220831092852-f930b1dc76e8"
|
||||||
hash = "sha256-sTJYgvlv5is7vHNxcuigF2lNASp0QonhUgnrguhfHSU="
|
hash = "sha256-li5hXlXwTJ5LIZ8bVki1AZ6UFI2gXHl33JwdX1dOrtM="
|
||||||
[mod."gopkg.in/ini.v1"]
|
[mod."gopkg.in/ini.v1"]
|
||||||
version = "v1.67.0"
|
version = "v1.67.0"
|
||||||
hash = "sha256-V10ahGNGT+NLRdKUyRg1dos5RxLBXBk1xutcnquc/+4="
|
hash = "sha256-V10ahGNGT+NLRdKUyRg1dos5RxLBXBk1xutcnquc/+4="
|
||||||
|
@ -3,10 +3,10 @@ package indexer
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
errorsmod "cosmossdk.io/errors"
|
||||||
"github.com/cosmos/cosmos-sdk/client"
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
"github.com/cosmos/cosmos-sdk/codec"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
|
||||||
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
rpctypes "github.com/evmos/ethermint/rpc/types"
|
rpctypes "github.com/evmos/ethermint/rpc/types"
|
||||||
@ -110,12 +110,12 @@ func (kv *KVIndexer) IndexBlock(block *tmtypes.Block, txResults []*abci.Response
|
|||||||
ethTxIndex++
|
ethTxIndex++
|
||||||
|
|
||||||
if err := saveTxResult(kv.clientCtx.Codec, batch, txHash, &txResult); err != nil {
|
if err := saveTxResult(kv.clientCtx.Codec, batch, txHash, &txResult); err != nil {
|
||||||
return sdkerrors.Wrapf(err, "IndexBlock %d", height)
|
return errorsmod.Wrapf(err, "IndexBlock %d", height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := batch.Write(); err != nil {
|
if err := batch.Write(); err != nil {
|
||||||
return sdkerrors.Wrapf(err, "IndexBlock %d, write batch", block.Height)
|
return errorsmod.Wrapf(err, "IndexBlock %d, write batch", block.Height)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -134,14 +134,14 @@ func (kv *KVIndexer) FirstIndexedBlock() (int64, error) {
|
|||||||
func (kv *KVIndexer) GetByTxHash(hash common.Hash) (*ethermint.TxResult, error) {
|
func (kv *KVIndexer) GetByTxHash(hash common.Hash) (*ethermint.TxResult, error) {
|
||||||
bz, err := kv.db.Get(TxHashKey(hash))
|
bz, err := kv.db.Get(TxHashKey(hash))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, sdkerrors.Wrapf(err, "GetByTxHash %s", hash.Hex())
|
return nil, errorsmod.Wrapf(err, "GetByTxHash %s", hash.Hex())
|
||||||
}
|
}
|
||||||
if len(bz) == 0 {
|
if len(bz) == 0 {
|
||||||
return nil, fmt.Errorf("tx not found, hash: %s", hash.Hex())
|
return nil, fmt.Errorf("tx not found, hash: %s", hash.Hex())
|
||||||
}
|
}
|
||||||
var txKey ethermint.TxResult
|
var txKey ethermint.TxResult
|
||||||
if err := kv.clientCtx.Codec.Unmarshal(bz, &txKey); err != nil {
|
if err := kv.clientCtx.Codec.Unmarshal(bz, &txKey); err != nil {
|
||||||
return nil, sdkerrors.Wrapf(err, "GetByTxHash %s", hash.Hex())
|
return nil, errorsmod.Wrapf(err, "GetByTxHash %s", hash.Hex())
|
||||||
}
|
}
|
||||||
return &txKey, nil
|
return &txKey, nil
|
||||||
}
|
}
|
||||||
@ -150,7 +150,7 @@ func (kv *KVIndexer) GetByTxHash(hash common.Hash) (*ethermint.TxResult, error)
|
|||||||
func (kv *KVIndexer) GetByBlockAndIndex(blockNumber int64, txIndex int32) (*ethermint.TxResult, error) {
|
func (kv *KVIndexer) GetByBlockAndIndex(blockNumber int64, txIndex int32) (*ethermint.TxResult, error) {
|
||||||
bz, err := kv.db.Get(TxIndexKey(blockNumber, txIndex))
|
bz, err := kv.db.Get(TxIndexKey(blockNumber, txIndex))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, sdkerrors.Wrapf(err, "GetByBlockAndIndex %d %d", blockNumber, txIndex)
|
return nil, errorsmod.Wrapf(err, "GetByBlockAndIndex %d %d", blockNumber, txIndex)
|
||||||
}
|
}
|
||||||
if len(bz) == 0 {
|
if len(bz) == 0 {
|
||||||
return nil, fmt.Errorf("tx not found, block: %d, eth-index: %d", blockNumber, txIndex)
|
return nil, fmt.Errorf("tx not found, block: %d, eth-index: %d", blockNumber, txIndex)
|
||||||
@ -174,7 +174,7 @@ func TxIndexKey(blockNumber int64, txIndex int32) []byte {
|
|||||||
func LoadLastBlock(db dbm.DB) (int64, error) {
|
func LoadLastBlock(db dbm.DB) (int64, error) {
|
||||||
it, err := db.ReverseIterator([]byte{KeyPrefixTxIndex}, []byte{KeyPrefixTxIndex + 1})
|
it, err := db.ReverseIterator([]byte{KeyPrefixTxIndex}, []byte{KeyPrefixTxIndex + 1})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, sdkerrors.Wrap(err, "LoadLastBlock")
|
return 0, errorsmod.Wrap(err, "LoadLastBlock")
|
||||||
}
|
}
|
||||||
defer it.Close()
|
defer it.Close()
|
||||||
if !it.Valid() {
|
if !it.Valid() {
|
||||||
@ -187,7 +187,7 @@ func LoadLastBlock(db dbm.DB) (int64, error) {
|
|||||||
func LoadFirstBlock(db dbm.DB) (int64, error) {
|
func LoadFirstBlock(db dbm.DB) (int64, error) {
|
||||||
it, err := db.Iterator([]byte{KeyPrefixTxIndex}, []byte{KeyPrefixTxIndex + 1})
|
it, err := db.Iterator([]byte{KeyPrefixTxIndex}, []byte{KeyPrefixTxIndex + 1})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, sdkerrors.Wrap(err, "LoadFirstBlock")
|
return 0, errorsmod.Wrap(err, "LoadFirstBlock")
|
||||||
}
|
}
|
||||||
defer it.Close()
|
defer it.Close()
|
||||||
if !it.Valid() {
|
if !it.Valid() {
|
||||||
@ -213,10 +213,10 @@ func isEthTx(tx sdk.Tx) bool {
|
|||||||
func saveTxResult(codec codec.Codec, batch dbm.Batch, txHash common.Hash, txResult *ethermint.TxResult) error {
|
func saveTxResult(codec codec.Codec, batch dbm.Batch, txHash common.Hash, txResult *ethermint.TxResult) error {
|
||||||
bz := codec.MustMarshal(txResult)
|
bz := codec.MustMarshal(txResult)
|
||||||
if err := batch.Set(TxHashKey(txHash), bz); err != nil {
|
if err := batch.Set(TxHashKey(txHash), bz); err != nil {
|
||||||
return sdkerrors.Wrap(err, "set tx-hash key")
|
return errorsmod.Wrap(err, "set tx-hash key")
|
||||||
}
|
}
|
||||||
if err := batch.Set(TxIndexKey(txResult.Height, txResult.EthTxIndex), txHash.Bytes()); err != nil {
|
if err := batch.Set(TxIndexKey(txResult.Height, txResult.EthTxIndex), txHash.Bytes()); err != nil {
|
||||||
return sdkerrors.Wrap(err, "set tx-index key")
|
return errorsmod.Wrap(err, "set tx-index key")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
2
init.sh
2
init.sh
@ -6,7 +6,7 @@ MONIKER="localtestnet"
|
|||||||
KEYRING="test"
|
KEYRING="test"
|
||||||
KEYALGO="eth_secp256k1"
|
KEYALGO="eth_secp256k1"
|
||||||
LOGLEVEL="info"
|
LOGLEVEL="info"
|
||||||
# to trace evm
|
# trace evm
|
||||||
TRACE="--trace"
|
TRACE="--trace"
|
||||||
# TRACE=""
|
# TRACE=""
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ import sources.nixpkgs {
|
|||||||
dotenv = builtins.path { name = "dotenv"; path = ../scripts/.env; };
|
dotenv = builtins.path { name = "dotenv"; path = ../scripts/.env; };
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
(_: pkgs: { test-env = import ./testenv.nix { inherit pkgs; }; })
|
(_: pkgs: { test-env = pkgs.callPackage ./testenv.nix { }; })
|
||||||
(_: pkgs: {
|
(_: pkgs: {
|
||||||
cosmovisor = pkgs.buildGo118Module rec {
|
cosmovisor = pkgs.buildGo118Module rec {
|
||||||
name = "cosmovisor";
|
name = "cosmovisor";
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{ lib, stdenv, buildGoModule, fetchFromGitHub, libobjc, IOKit }:
|
{ lib, stdenv, buildGoModule, fetchFromGitHub, libobjc, IOKit, nixosTests }:
|
||||||
|
|
||||||
let
|
let
|
||||||
# A list of binaries to put into separate outputs
|
# A list of binaries to put into separate outputs
|
||||||
@ -7,19 +7,18 @@ let
|
|||||||
"clef"
|
"clef"
|
||||||
];
|
];
|
||||||
|
|
||||||
in
|
in buildGoModule rec {
|
||||||
buildGoModule rec {
|
|
||||||
pname = "go-ethereum";
|
pname = "go-ethereum";
|
||||||
version = "1.10.19";
|
version = "1.10.25";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "ethereum";
|
owner = "ethereum";
|
||||||
repo = pname;
|
repo = pname;
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
sha256 = "0f6n9rg42ph47mvykc9f0lf99yzwqy4jm7mlzyks4l6i6fl1g3q1";
|
sha256 = "sha256-mnf0kMfQEEQMricZJfyF7ZB/2F1dyPBx9iT2v/rGh1U=";
|
||||||
};
|
};
|
||||||
|
|
||||||
vendorSha256 = "1s5yfpk2yn7f3zwjl2fdrh6c63ki2b8rlmnlss27yxibsidaj0yd";
|
vendorSha256 = "sha256-Dj+xN8lr98LJyYr2FwJ7yUIJkUeUrr1fkcbj4hShJI0=";
|
||||||
|
|
||||||
doCheck = false;
|
doCheck = false;
|
||||||
|
|
||||||
@ -47,14 +46,19 @@ buildGoModule rec {
|
|||||||
"cmd/utils"
|
"cmd/utils"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
# Following upstream: https://github.com/ethereum/go-ethereum/blob/v1.10.25/build/ci.go#L218
|
||||||
|
tags = [ "urfave_cli_no_docs" ];
|
||||||
|
|
||||||
# Fix for usb-related segmentation faults on darwin
|
# Fix for usb-related segmentation faults on darwin
|
||||||
propagatedBuildInputs =
|
propagatedBuildInputs =
|
||||||
lib.optionals stdenv.isDarwin [ libobjc IOKit ];
|
lib.optionals stdenv.isDarwin [ libobjc IOKit ];
|
||||||
|
|
||||||
|
passthru.tests = { inherit (nixosTests) geth; };
|
||||||
|
|
||||||
meta = with lib; {
|
meta = with lib; {
|
||||||
homepage = "https://geth.ethereum.org/";
|
homepage = "https://geth.ethereum.org/";
|
||||||
description = "Official golang implementation of the Ethereum protocol";
|
description = "Official golang implementation of the Ethereum protocol";
|
||||||
license = with licenses; [ lgpl3Plus gpl3Plus ];
|
license = with licenses; [ lgpl3Plus gpl3Plus ];
|
||||||
maintainers = with maintainers; [ adisbladis lionello RaghavSood ];
|
maintainers = with maintainers; [ adisbladis RaghavSood ];
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -41,10 +41,10 @@
|
|||||||
"homepage": "",
|
"homepage": "",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "f904e3562aabca382d12f8471ca2330b3f82899a",
|
"rev": "ea2c6a6dda1aa35a80139a512a9dee375b0946e7",
|
||||||
"sha256": "1lsa3sjwp1v3nv2jjpkl5lf9dncplwihmavasalg9fq1217pmzmb",
|
"sha256": "0nd4nn9ryqa80ssw3j2kmr8wa73p2xz1hyxp280cdzqlmdfgw1lm",
|
||||||
"type": "tarball",
|
"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"
|
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,38 @@
|
|||||||
{ pkgs }:
|
{ poetry2nix, lib, python310 }:
|
||||||
pkgs.poetry2nix.mkPoetryEnv {
|
poetry2nix.mkPoetryEnv {
|
||||||
projectDir = ../tests/integration_tests;
|
projectDir = ../tests/integration_tests;
|
||||||
python = pkgs.python39;
|
python = python310;
|
||||||
overrides = pkgs.poetry2nix.overrides.withDefaults (self: super: {
|
overrides = poetry2nix.overrides.withDefaults (lib.composeManyExtensions [
|
||||||
|
(self: super:
|
||||||
|
let
|
||||||
|
buildSystems = {
|
||||||
|
eth-bloom = [ "setuptools" ];
|
||||||
|
pystarport = [ "poetry" ];
|
||||||
|
durations = [ "setuptools" ];
|
||||||
|
multitail2 = [ "setuptools" ];
|
||||||
|
pytest-github-actions-annotate-failures = [ "setuptools" ];
|
||||||
|
flake8-black = [ "setuptools" ];
|
||||||
|
multiaddr = [ "setuptools" ];
|
||||||
|
};
|
||||||
|
in
|
||||||
|
lib.mapAttrs
|
||||||
|
(attr: systems: super.${attr}.overridePythonAttrs
|
||||||
|
(old: {
|
||||||
|
nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ map (a: self.${a}) systems;
|
||||||
|
}))
|
||||||
|
buildSystems
|
||||||
|
)
|
||||||
|
(self: super: {
|
||||||
eth-bloom = super.eth-bloom.overridePythonAttrs {
|
eth-bloom = super.eth-bloom.overridePythonAttrs {
|
||||||
preConfigure = ''
|
preConfigure = ''
|
||||||
substituteInPlace setup.py --replace \'setuptools-markdown\' ""
|
substituteInPlace setup.py --replace \'setuptools-markdown\' ""
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
pyyaml-include = super.pyyaml-include.overridePythonAttrs {
|
||||||
pystarport = super.pystarport.overridePythonAttrs (
|
preConfigure = ''
|
||||||
old: {
|
substituteInPlace setup.py --replace "setup()" "setup(version=\"1.3\")"
|
||||||
nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [ self.poetry ];
|
'';
|
||||||
}
|
};
|
||||||
);
|
})
|
||||||
});
|
]);
|
||||||
}
|
}
|
||||||
|
8
proto/buf.gen.gogo.yaml
Normal file
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
|
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:
|
lint:
|
||||||
use:
|
use:
|
||||||
- DEFAULT
|
- DEFAULT
|
||||||
|
@ -11,11 +11,13 @@ option go_package = "github.com/evmos/ethermint/crypto/ethsecp256k1";
|
|||||||
message PubKey {
|
message PubKey {
|
||||||
option (gogoproto.goproto_stringer) = false;
|
option (gogoproto.goproto_stringer) = false;
|
||||||
|
|
||||||
|
// key is the public key in byte form
|
||||||
bytes key = 1;
|
bytes key = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrivKey defines a type alias for an ecdsa.PrivateKey that implements
|
// PrivKey defines a type alias for an ecdsa.PrivateKey that implements
|
||||||
// Tendermint's PrivateKey interface.
|
// Tendermint's PrivateKey interface.
|
||||||
message PrivKey {
|
message PrivKey {
|
||||||
|
// key is the private key in byte form
|
||||||
bytes key = 1;
|
bytes key = 1;
|
||||||
}
|
}
|
||||||
|
@ -7,18 +7,18 @@ option go_package = "github.com/evmos/ethermint/x/evm/types";
|
|||||||
|
|
||||||
// Params defines the EVM module parameters
|
// Params defines the EVM module parameters
|
||||||
message Params {
|
message Params {
|
||||||
// evm denom represents the token denomination used to run the EVM state
|
// evm_denom represents the token denomination used to run the EVM state
|
||||||
// transitions.
|
// transitions.
|
||||||
string evm_denom = 1 [(gogoproto.moretags) = "yaml:\"evm_denom\""];
|
string evm_denom = 1 [(gogoproto.moretags) = "yaml:\"evm_denom\""];
|
||||||
// enable create toggles state transitions that use the vm.Create function
|
// enable_create toggles state transitions that use the vm.Create function
|
||||||
bool enable_create = 2 [(gogoproto.moretags) = "yaml:\"enable_create\""];
|
bool enable_create = 2 [(gogoproto.moretags) = "yaml:\"enable_create\""];
|
||||||
// enable call toggles state transitions that use the vm.Call function
|
// enable_call toggles state transitions that use the vm.Call function
|
||||||
bool enable_call = 3 [(gogoproto.moretags) = "yaml:\"enable_call\""];
|
bool enable_call = 3 [(gogoproto.moretags) = "yaml:\"enable_call\""];
|
||||||
// extra eips defines the additional EIPs for the vm.Config
|
// extra_eips defines the additional EIPs for the vm.Config
|
||||||
repeated int64 extra_eips = 4 [(gogoproto.customname) = "ExtraEIPs", (gogoproto.moretags) = "yaml:\"extra_eips\""];
|
repeated int64 extra_eips = 4 [(gogoproto.customname) = "ExtraEIPs", (gogoproto.moretags) = "yaml:\"extra_eips\""];
|
||||||
// chain config defines the EVM chain configuration parameters
|
// chain_config defines the EVM chain configuration parameters
|
||||||
ChainConfig chain_config = 5 [(gogoproto.moretags) = "yaml:\"chain_config\"", (gogoproto.nullable) = false];
|
ChainConfig chain_config = 5 [(gogoproto.moretags) = "yaml:\"chain_config\"", (gogoproto.nullable) = false];
|
||||||
// Allow unprotected transactions defines if replay-protected (i.e non EIP155
|
// allow_unprotected_txs defines if replay-protected (i.e non EIP155
|
||||||
// signed) transactions can be executed on the state machine.
|
// signed) transactions can be executed on the state machine.
|
||||||
bool allow_unprotected_txs = 6;
|
bool allow_unprotected_txs = 6;
|
||||||
}
|
}
|
||||||
@ -26,67 +26,67 @@ message Params {
|
|||||||
// ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int values
|
// ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int values
|
||||||
// instead of *big.Int.
|
// instead of *big.Int.
|
||||||
message ChainConfig {
|
message ChainConfig {
|
||||||
// Homestead switch block (nil no fork, 0 = already homestead)
|
// homestead_block switch (nil no fork, 0 = already homestead)
|
||||||
string homestead_block = 1 [
|
string homestead_block = 1 [
|
||||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||||
(gogoproto.moretags) = "yaml:\"homestead_block\""
|
(gogoproto.moretags) = "yaml:\"homestead_block\""
|
||||||
];
|
];
|
||||||
// TheDAO hard-fork switch block (nil no fork)
|
// dao_fork_block corresponds to TheDAO hard-fork switch block (nil no fork)
|
||||||
string dao_fork_block = 2 [
|
string dao_fork_block = 2 [
|
||||||
(gogoproto.customname) = "DAOForkBlock",
|
(gogoproto.customname) = "DAOForkBlock",
|
||||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||||
(gogoproto.moretags) = "yaml:\"dao_fork_block\""
|
(gogoproto.moretags) = "yaml:\"dao_fork_block\""
|
||||||
];
|
];
|
||||||
// Whether the nodes supports or opposes the DAO hard-fork
|
// dao_fork_support defines whether the nodes supports or opposes the DAO hard-fork
|
||||||
bool dao_fork_support = 3
|
bool dao_fork_support = 3
|
||||||
[(gogoproto.customname) = "DAOForkSupport", (gogoproto.moretags) = "yaml:\"dao_fork_support\""];
|
[(gogoproto.customname) = "DAOForkSupport", (gogoproto.moretags) = "yaml:\"dao_fork_support\""];
|
||||||
// EIP150 implements the Gas price changes
|
// eip150_block: EIP150 implements the Gas price changes
|
||||||
// (https://github.com/ethereum/EIPs/issues/150) EIP150 HF block (nil no fork)
|
// (https://github.com/ethereum/EIPs/issues/150) EIP150 HF block (nil no fork)
|
||||||
string eip150_block = 4 [
|
string eip150_block = 4 [
|
||||||
(gogoproto.customname) = "EIP150Block",
|
(gogoproto.customname) = "EIP150Block",
|
||||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||||
(gogoproto.moretags) = "yaml:\"eip150_block\""
|
(gogoproto.moretags) = "yaml:\"eip150_block\""
|
||||||
];
|
];
|
||||||
// EIP150 HF hash (needed for header only clients as only gas pricing changed)
|
// eip150_hash: EIP150 HF hash (needed for header only clients as only gas pricing changed)
|
||||||
string eip150_hash = 5 [(gogoproto.customname) = "EIP150Hash", (gogoproto.moretags) = "yaml:\"byzantium_block\""];
|
string eip150_hash = 5 [(gogoproto.customname) = "EIP150Hash", (gogoproto.moretags) = "yaml:\"byzantium_block\""];
|
||||||
// EIP155Block HF block
|
// eip155_block: EIP155Block HF block
|
||||||
string eip155_block = 6 [
|
string eip155_block = 6 [
|
||||||
(gogoproto.customname) = "EIP155Block",
|
(gogoproto.customname) = "EIP155Block",
|
||||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||||
(gogoproto.moretags) = "yaml:\"eip155_block\""
|
(gogoproto.moretags) = "yaml:\"eip155_block\""
|
||||||
];
|
];
|
||||||
// EIP158 HF block
|
// eip158_block: EIP158 HF block
|
||||||
string eip158_block = 7 [
|
string eip158_block = 7 [
|
||||||
(gogoproto.customname) = "EIP158Block",
|
(gogoproto.customname) = "EIP158Block",
|
||||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||||
(gogoproto.moretags) = "yaml:\"eip158_block\""
|
(gogoproto.moretags) = "yaml:\"eip158_block\""
|
||||||
];
|
];
|
||||||
// Byzantium switch block (nil no fork, 0 = already on byzantium)
|
// byzantium_block: Byzantium switch block (nil no fork, 0 = already on byzantium)
|
||||||
string byzantium_block = 8 [
|
string byzantium_block = 8 [
|
||||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||||
(gogoproto.moretags) = "yaml:\"byzantium_block\""
|
(gogoproto.moretags) = "yaml:\"byzantium_block\""
|
||||||
];
|
];
|
||||||
// Constantinople switch block (nil no fork, 0 = already activated)
|
// constantinople_block: Constantinople switch block (nil no fork, 0 = already activated)
|
||||||
string constantinople_block = 9 [
|
string constantinople_block = 9 [
|
||||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||||
(gogoproto.moretags) = "yaml:\"constantinople_block\""
|
(gogoproto.moretags) = "yaml:\"constantinople_block\""
|
||||||
];
|
];
|
||||||
// Petersburg switch block (nil same as Constantinople)
|
// petersburg_block: Petersburg switch block (nil same as Constantinople)
|
||||||
string petersburg_block = 10 [
|
string petersburg_block = 10 [
|
||||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||||
(gogoproto.moretags) = "yaml:\"petersburg_block\""
|
(gogoproto.moretags) = "yaml:\"petersburg_block\""
|
||||||
];
|
];
|
||||||
// Istanbul switch block (nil no fork, 0 = already on istanbul)
|
// istanbul_block: Istanbul switch block (nil no fork, 0 = already on istanbul)
|
||||||
string istanbul_block = 11 [
|
string istanbul_block = 11 [
|
||||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||||
(gogoproto.moretags) = "yaml:\"istanbul_block\""
|
(gogoproto.moretags) = "yaml:\"istanbul_block\""
|
||||||
];
|
];
|
||||||
// Eip-2384 (bomb delay) switch block (nil no fork, 0 = already activated)
|
// muir_glacier_block: Eip-2384 (bomb delay) switch block (nil no fork, 0 = already activated)
|
||||||
string muir_glacier_block = 12 [
|
string muir_glacier_block = 12 [
|
||||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||||
(gogoproto.moretags) = "yaml:\"muir_glacier_block\""
|
(gogoproto.moretags) = "yaml:\"muir_glacier_block\""
|
||||||
];
|
];
|
||||||
// Berlin switch block (nil = no fork, 0 = already on berlin)
|
// berlin_block: Berlin switch block (nil = no fork, 0 = already on berlin)
|
||||||
string berlin_block = 13 [
|
string berlin_block = 13 [
|
||||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||||
(gogoproto.moretags) = "yaml:\"berlin_block\""
|
(gogoproto.moretags) = "yaml:\"berlin_block\""
|
||||||
@ -94,12 +94,12 @@ message ChainConfig {
|
|||||||
// DEPRECATED: EWASM, YOLOV3 and Catalyst block have been deprecated
|
// DEPRECATED: EWASM, YOLOV3 and Catalyst block have been deprecated
|
||||||
reserved 14, 15, 16;
|
reserved 14, 15, 16;
|
||||||
reserved "yolo_v3_block", "ewasm_block", "catalyst_block";
|
reserved "yolo_v3_block", "ewasm_block", "catalyst_block";
|
||||||
// London switch block (nil = no fork, 0 = already on london)
|
// london_block: London switch block (nil = no fork, 0 = already on london)
|
||||||
string london_block = 17 [
|
string london_block = 17 [
|
||||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||||
(gogoproto.moretags) = "yaml:\"london_block\""
|
(gogoproto.moretags) = "yaml:\"london_block\""
|
||||||
];
|
];
|
||||||
// Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already activated)
|
// arrow_glacier_block: Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already activated)
|
||||||
string arrow_glacier_block = 18 [
|
string arrow_glacier_block = 18 [
|
||||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||||
(gogoproto.moretags) = "yaml:\"arrow_glacier_block\""
|
(gogoproto.moretags) = "yaml:\"arrow_glacier_block\""
|
||||||
@ -107,21 +107,34 @@ message ChainConfig {
|
|||||||
// DEPRECATED: merge fork block was deprecated: https://github.com/ethereum/go-ethereum/pull/24904
|
// DEPRECATED: merge fork block was deprecated: https://github.com/ethereum/go-ethereum/pull/24904
|
||||||
reserved 19;
|
reserved 19;
|
||||||
reserved "merge_fork_block";
|
reserved "merge_fork_block";
|
||||||
// EIP-5133 (bomb delay) switch block (nil = no fork, 0 = already activated)
|
// gray_glacier_block: EIP-5133 (bomb delay) switch block (nil = no fork, 0 = already activated)
|
||||||
string gray_glacier_block = 20 [
|
string gray_glacier_block = 20 [
|
||||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||||
(gogoproto.moretags) = "yaml:\"gray_glacier_block\""
|
(gogoproto.moretags) = "yaml:\"gray_glacier_block\""
|
||||||
];
|
];
|
||||||
// Virtual fork after The Merge to use as a network splitter
|
// merge_netsplit_block: Virtual fork after The Merge to use as a network splitter
|
||||||
string merge_netsplit_block = 21 [
|
string merge_netsplit_block = 21 [
|
||||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||||
(gogoproto.moretags) = "yaml:\"merge_netsplit_block\""
|
(gogoproto.moretags) = "yaml:\"merge_netsplit_block\""
|
||||||
];
|
];
|
||||||
|
// shanghai_block switch block (nil = no fork, 0 = already on shanghai)
|
||||||
|
string shanghai_block = 22 [
|
||||||
|
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||||
|
(gogoproto.moretags) = "yaml:\"shanghai_block\""
|
||||||
|
];
|
||||||
|
// cancun_block switch block (nil = no fork, 0 = already on cancun)
|
||||||
|
string cancun_block = 23 [
|
||||||
|
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||||
|
(gogoproto.moretags) = "yaml:\"cancun_block\""
|
||||||
|
];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// State represents a single Storage key value pair item.
|
// State represents a single Storage key value pair item.
|
||||||
message State {
|
message State {
|
||||||
|
// key is the stored key
|
||||||
string key = 1;
|
string key = 1;
|
||||||
|
// value is the stored value for the given key
|
||||||
string value = 2;
|
string value = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,38 +142,38 @@ message State {
|
|||||||
// with a given hash. It it used for import/export data as transactions are not
|
// with a given hash. It it used for import/export data as transactions are not
|
||||||
// persisted on blockchain state after an upgrade.
|
// persisted on blockchain state after an upgrade.
|
||||||
message TransactionLogs {
|
message TransactionLogs {
|
||||||
|
// hash of the transaction
|
||||||
string hash = 1;
|
string hash = 1;
|
||||||
|
// logs is an array of Logs for the given transaction hash
|
||||||
repeated Log logs = 2;
|
repeated Log logs = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log represents an protobuf compatible Ethereum Log that defines a contract
|
// Log represents an protobuf compatible Ethereum Log that defines a contract
|
||||||
// log event. These events are generated by the LOG opcode and stored/indexed by
|
// log event. These events are generated by the LOG opcode and stored/indexed by
|
||||||
// the node.
|
// the node.
|
||||||
|
//
|
||||||
|
// NOTE: address, topics and data are consensus fields. The rest of the fields
|
||||||
|
// are derived, i.e. filled in by the nodes, but not secured by consensus.
|
||||||
message Log {
|
message Log {
|
||||||
// Consensus fields:
|
|
||||||
|
|
||||||
// address of the contract that generated the event
|
// address of the contract that generated the event
|
||||||
string address = 1;
|
string address = 1;
|
||||||
// list of topics provided by the contract.
|
// topics is a list of topics provided by the contract.
|
||||||
repeated string topics = 2;
|
repeated string topics = 2;
|
||||||
// supplied by the contract, usually ABI-encoded
|
// data which is supplied by the contract, usually ABI-encoded
|
||||||
bytes data = 3;
|
bytes data = 3;
|
||||||
|
|
||||||
// Derived fields. These fields are filled in by the node
|
// block_number of the block in which the transaction was included
|
||||||
// but not secured by consensus.
|
|
||||||
|
|
||||||
// block in which the transaction was included
|
|
||||||
uint64 block_number = 4 [(gogoproto.jsontag) = "blockNumber"];
|
uint64 block_number = 4 [(gogoproto.jsontag) = "blockNumber"];
|
||||||
// hash of the transaction
|
// tx_hash is the transaction hash
|
||||||
string tx_hash = 5 [(gogoproto.jsontag) = "transactionHash"];
|
string tx_hash = 5 [(gogoproto.jsontag) = "transactionHash"];
|
||||||
// index of the transaction in the block
|
// tx_index of the transaction in the block
|
||||||
uint64 tx_index = 6 [(gogoproto.jsontag) = "transactionIndex"];
|
uint64 tx_index = 6 [(gogoproto.jsontag) = "transactionIndex"];
|
||||||
// hash of the block in which the transaction was included
|
// block_hash of the block in which the transaction was included
|
||||||
string block_hash = 7 [(gogoproto.jsontag) = "blockHash"];
|
string block_hash = 7 [(gogoproto.jsontag) = "blockHash"];
|
||||||
// index of the log in the block
|
// index of the log in the block
|
||||||
uint64 index = 8 [(gogoproto.jsontag) = "logIndex"];
|
uint64 index = 8 [(gogoproto.jsontag) = "logIndex"];
|
||||||
|
|
||||||
// The Removed field is true if this log was reverted due to a chain
|
// removed is true if this log was reverted due to a chain
|
||||||
// reorganisation. You must pay attention to this field if you receive logs
|
// reorganisation. You must pay attention to this field if you receive logs
|
||||||
// through a filter query.
|
// through a filter query.
|
||||||
bool removed = 9;
|
bool removed = 9;
|
||||||
@ -191,9 +204,9 @@ message TxResult {
|
|||||||
message AccessTuple {
|
message AccessTuple {
|
||||||
option (gogoproto.goproto_getters) = false;
|
option (gogoproto.goproto_getters) = false;
|
||||||
|
|
||||||
// hex formatted ethereum address
|
// address is a hex formatted ethereum address
|
||||||
string address = 1;
|
string address = 1;
|
||||||
// hex formatted hashes of the storage keys
|
// storage_keys are hex formatted hashes of the storage keys
|
||||||
repeated string storage_keys = 2 [(gogoproto.jsontag) = "storageKeys"];
|
repeated string storage_keys = 2 [(gogoproto.jsontag) = "storageKeys"];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,25 +217,27 @@ message TraceConfig {
|
|||||||
reserved 4, 7;
|
reserved 4, 7;
|
||||||
reserved "disable_memory", "disable_return_data";
|
reserved "disable_memory", "disable_return_data";
|
||||||
|
|
||||||
// custom javascript tracer
|
// tracer is a custom javascript tracer
|
||||||
string tracer = 1;
|
string tracer = 1;
|
||||||
// overrides the default timeout of 5 seconds for JavaScript-based tracing
|
// timeout overrides the default timeout of 5 seconds for JavaScript-based tracing
|
||||||
// calls
|
// calls
|
||||||
string timeout = 2;
|
string timeout = 2;
|
||||||
// number of blocks the tracer is willing to go back
|
// reexec defines the number of blocks the tracer is willing to go back
|
||||||
uint64 reexec = 3;
|
uint64 reexec = 3;
|
||||||
// disable stack capture
|
// disable_stack switches stack capture
|
||||||
bool disable_stack = 5 [(gogoproto.jsontag) = "disableStack"];
|
bool disable_stack = 5 [(gogoproto.jsontag) = "disableStack"];
|
||||||
// disable storage capture
|
// disable_storage switches storage capture
|
||||||
bool disable_storage = 6 [(gogoproto.jsontag) = "disableStorage"];
|
bool disable_storage = 6 [(gogoproto.jsontag) = "disableStorage"];
|
||||||
// print output during capture end
|
// debug can be used to print output during capture end
|
||||||
bool debug = 8;
|
bool debug = 8;
|
||||||
// maximum length of output, but zero means unlimited
|
// limit defines the maximum length of output, but zero means unlimited
|
||||||
int32 limit = 9;
|
int32 limit = 9;
|
||||||
// Chain overrides, can be used to execute a trace using future fork rules
|
// overrides can be used to execute a trace using future fork rules
|
||||||
ChainConfig overrides = 10;
|
ChainConfig overrides = 10;
|
||||||
// enable memory capture
|
// enable_memory switches memory capture
|
||||||
bool enable_memory = 11 [(gogoproto.jsontag) = "enableMemory"];
|
bool enable_memory = 11 [(gogoproto.jsontag) = "enableMemory"];
|
||||||
// enable return data capture
|
// enable_return_data switches the capture of return data
|
||||||
bool enable_return_data = 12 [(gogoproto.jsontag) = "enableReturnData"];
|
bool enable_return_data = 12 [(gogoproto.jsontag) = "enableReturnData"];
|
||||||
|
// tracer_json_config configures the tracer using a JSON string
|
||||||
|
string tracer_json_config = 13 [(gogoproto.jsontag) = "tracerConfig"];
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
package ethermint.evm.v1;
|
package ethermint.evm.v1;
|
||||||
|
|
||||||
import "gogoproto/gogo.proto";
|
|
||||||
import "ethermint/evm/v1/evm.proto";
|
import "ethermint/evm/v1/evm.proto";
|
||||||
|
import "gogoproto/gogo.proto";
|
||||||
|
|
||||||
option go_package = "github.com/evmos/ethermint/x/evm/types";
|
option go_package = "github.com/evmos/ethermint/x/evm/types";
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
package ethermint.evm.v1;
|
package ethermint.evm.v1;
|
||||||
|
|
||||||
import "gogoproto/gogo.proto";
|
|
||||||
import "cosmos/base/query/v1beta1/pagination.proto";
|
import "cosmos/base/query/v1beta1/pagination.proto";
|
||||||
import "google/api/annotations.proto";
|
|
||||||
import "ethermint/evm/v1/evm.proto";
|
import "ethermint/evm/v1/evm.proto";
|
||||||
import "ethermint/evm/v1/tx.proto";
|
import "ethermint/evm/v1/tx.proto";
|
||||||
|
import "gogoproto/gogo.proto";
|
||||||
|
import "google/api/annotations.proto";
|
||||||
import "google/protobuf/timestamp.proto";
|
import "google/protobuf/timestamp.proto";
|
||||||
|
|
||||||
option go_package = "github.com/evmos/ethermint/x/evm/types";
|
option go_package = "github.com/evmos/ethermint/x/evm/types";
|
||||||
@ -89,7 +89,7 @@ message QueryAccountRequest {
|
|||||||
message QueryAccountResponse {
|
message QueryAccountResponse {
|
||||||
// balance is the balance of the EVM denomination.
|
// balance is the balance of the EVM denomination.
|
||||||
string balance = 1;
|
string balance = 1;
|
||||||
// code hash is the hex-formatted code bytes from the EOA.
|
// code_hash is the hex-formatted code bytes from the EOA.
|
||||||
string code_hash = 2;
|
string code_hash = 2;
|
||||||
// nonce is the account's sequence number.
|
// nonce is the account's sequence number.
|
||||||
uint64 nonce = 3;
|
uint64 nonce = 3;
|
||||||
@ -112,7 +112,7 @@ message QueryCosmosAccountResponse {
|
|||||||
string cosmos_address = 1;
|
string cosmos_address = 1;
|
||||||
// sequence is the account's sequence number.
|
// sequence is the account's sequence number.
|
||||||
uint64 sequence = 2;
|
uint64 sequence = 2;
|
||||||
// account_number is the account numbert
|
// account_number is the account number
|
||||||
uint64 account_number = 3;
|
uint64 account_number = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +157,7 @@ message QueryStorageRequest {
|
|||||||
option (gogoproto.equal) = false;
|
option (gogoproto.equal) = false;
|
||||||
option (gogoproto.goproto_getters) = false;
|
option (gogoproto.goproto_getters) = false;
|
||||||
|
|
||||||
/// address is the ethereum hex address to query the storage state for.
|
// address is the ethereum hex address to query the storage state for.
|
||||||
string address = 1;
|
string address = 1;
|
||||||
|
|
||||||
// key defines the key of the storage state
|
// key defines the key of the storage state
|
||||||
@ -167,7 +167,7 @@ message QueryStorageRequest {
|
|||||||
// QueryStorageResponse is the response type for the Query/Storage RPC
|
// QueryStorageResponse is the response type for the Query/Storage RPC
|
||||||
// method.
|
// method.
|
||||||
message QueryStorageResponse {
|
message QueryStorageResponse {
|
||||||
// key defines the storage state value hash associated with the given key.
|
// value defines the storage state value hash associated with the given key.
|
||||||
string value = 1;
|
string value = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,7 +198,7 @@ message QueryTxLogsRequest {
|
|||||||
cosmos.base.query.v1beta1.PageRequest pagination = 2;
|
cosmos.base.query.v1beta1.PageRequest pagination = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryTxLogs is the response type for the Query/TxLogs RPC method.
|
// QueryTxLogsResponse is the response type for the Query/TxLogs RPC method.
|
||||||
message QueryTxLogsResponse {
|
message QueryTxLogsResponse {
|
||||||
// logs represents the ethereum logs generated from the given transaction.
|
// logs represents the ethereum logs generated from the given transaction.
|
||||||
repeated Log logs = 1;
|
repeated Log logs = 1;
|
||||||
@ -217,66 +217,73 @@ message QueryParamsResponse {
|
|||||||
|
|
||||||
// EthCallRequest defines EthCall request
|
// EthCallRequest defines EthCall request
|
||||||
message EthCallRequest {
|
message EthCallRequest {
|
||||||
// same json format as the json rpc api.
|
// args uses the same json format as the json rpc api.
|
||||||
bytes args = 1;
|
bytes args = 1;
|
||||||
// the default gas cap to be used
|
// gas_cap defines the default gas cap to be used
|
||||||
uint64 gas_cap = 2;
|
uint64 gas_cap = 2;
|
||||||
// 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"];
|
bytes proposer_address = 3 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.ConsAddress"];
|
||||||
|
// chain_id is the eip155 chain id parsed from the requested block header
|
||||||
|
int64 chain_id = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
// EstimateGasResponse defines EstimateGas response
|
// EstimateGasResponse defines EstimateGas response
|
||||||
message EstimateGasResponse {
|
message EstimateGasResponse {
|
||||||
// the estimated gas
|
// gas returns the estimated gas
|
||||||
uint64 gas = 1;
|
uint64 gas = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryTraceTxRequest defines TraceTx request
|
// QueryTraceTxRequest defines TraceTx request
|
||||||
message QueryTraceTxRequest {
|
message QueryTraceTxRequest {
|
||||||
// msgEthereumTx for the requested transaction
|
// msg is the MsgEthereumTx for the requested transaction
|
||||||
MsgEthereumTx msg = 1;
|
MsgEthereumTx msg = 1;
|
||||||
// tx_index is not necessary anymore
|
// tx_index is not necessary anymore
|
||||||
reserved 2;
|
reserved 2;
|
||||||
reserved "tx_index";
|
reserved "tx_index";
|
||||||
// TraceConfig holds extra parameters to trace functions.
|
// trace_config holds extra parameters to trace functions.
|
||||||
TraceConfig trace_config = 3;
|
TraceConfig trace_config = 3;
|
||||||
// the predecessor transactions included in the same block
|
// predecessors is an array of transactions included in the same block
|
||||||
// need to be replayed first to get correct context for tracing.
|
// need to be replayed first to get correct context for tracing.
|
||||||
repeated MsgEthereumTx predecessors = 4;
|
repeated MsgEthereumTx predecessors = 4;
|
||||||
// block number of requested transaction
|
// block_number of requested transaction
|
||||||
int64 block_number = 5;
|
int64 block_number = 5;
|
||||||
// block hex hash of requested transaction
|
// block_hash of requested transaction
|
||||||
string block_hash = 6;
|
string block_hash = 6;
|
||||||
// block time of requested transaction
|
// block_time of requested transaction
|
||||||
google.protobuf.Timestamp block_time = 7 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
|
google.protobuf.Timestamp block_time = 7 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
|
||||||
// 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"];
|
bytes proposer_address = 8 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.ConsAddress"];
|
||||||
|
// chain_id is the the eip155 chain id parsed from the requested block header
|
||||||
|
int64 chain_id = 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryTraceTxResponse defines TraceTx response
|
// QueryTraceTxResponse defines TraceTx response
|
||||||
message QueryTraceTxResponse {
|
message QueryTraceTxResponse {
|
||||||
// response serialized in bytes
|
// data is the response serialized in bytes
|
||||||
bytes data = 1;
|
bytes data = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryTraceBlockRequest defines TraceTx request
|
// QueryTraceBlockRequest defines TraceTx request
|
||||||
message QueryTraceBlockRequest {
|
message QueryTraceBlockRequest {
|
||||||
// txs messages in the block
|
// txs is an array of messages in the block
|
||||||
repeated MsgEthereumTx txs = 1;
|
repeated MsgEthereumTx txs = 1;
|
||||||
// TraceConfig holds extra parameters to trace functions.
|
// trace_config holds extra parameters to trace functions.
|
||||||
TraceConfig trace_config = 3;
|
TraceConfig trace_config = 3;
|
||||||
// block number
|
// block_number of the traced block
|
||||||
int64 block_number = 5;
|
int64 block_number = 5;
|
||||||
// block hex hash
|
// block_hash (hex) of the traced block
|
||||||
string block_hash = 6;
|
string block_hash = 6;
|
||||||
// block time
|
// block_time of the traced block
|
||||||
google.protobuf.Timestamp block_time = 7 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
|
google.protobuf.Timestamp block_time = 7 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
|
||||||
// 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"];
|
bytes proposer_address = 8 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.ConsAddress"];
|
||||||
|
// chain_id is the eip155 chain id parsed from the requested block header
|
||||||
|
int64 chain_id = 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryTraceBlockResponse defines TraceBlock response
|
// QueryTraceBlockResponse defines TraceBlock response
|
||||||
message QueryTraceBlockResponse {
|
message QueryTraceBlockResponse {
|
||||||
|
// data is the response serialized in bytes
|
||||||
bytes data = 1;
|
bytes data = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,7 +291,8 @@ message QueryTraceBlockResponse {
|
|||||||
// fee.
|
// fee.
|
||||||
message QueryBaseFeeRequest {}
|
message QueryBaseFeeRequest {}
|
||||||
|
|
||||||
// BaseFeeResponse returns the EIP1559 base fee.
|
// QueryBaseFeeResponse returns the EIP1559 base fee.
|
||||||
message QueryBaseFeeResponse {
|
message QueryBaseFeeResponse {
|
||||||
|
// base_fee is the EIP1559 base fee
|
||||||
string base_fee = 1 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"];
|
string base_fee = 1 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"];
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
package ethermint.evm.v1;
|
package ethermint.evm.v1;
|
||||||
|
|
||||||
|
import "cosmos_proto/cosmos.proto";
|
||||||
|
import "ethermint/evm/v1/evm.proto";
|
||||||
import "gogoproto/gogo.proto";
|
import "gogoproto/gogo.proto";
|
||||||
import "google/api/annotations.proto";
|
import "google/api/annotations.proto";
|
||||||
import "google/protobuf/any.proto";
|
import "google/protobuf/any.proto";
|
||||||
import "cosmos_proto/cosmos.proto";
|
|
||||||
import "ethermint/evm/v1/evm.proto";
|
|
||||||
|
|
||||||
option go_package = "github.com/evmos/ethermint/x/evm/types";
|
option go_package = "github.com/evmos/ethermint/x/evm/types";
|
||||||
|
|
||||||
@ -21,15 +21,14 @@ service Msg {
|
|||||||
message MsgEthereumTx {
|
message MsgEthereumTx {
|
||||||
option (gogoproto.goproto_getters) = false;
|
option (gogoproto.goproto_getters) = false;
|
||||||
|
|
||||||
// inner transaction data
|
// data is inner transaction data of the Ethereum transaction
|
||||||
google.protobuf.Any data = 1;
|
google.protobuf.Any data = 1;
|
||||||
// caches
|
|
||||||
|
|
||||||
// DEPRECATED: encoded storage size of the transaction
|
// size is the encoded storage size of the transaction (DEPRECATED)
|
||||||
double size = 2 [(gogoproto.jsontag) = "-"];
|
double size = 2 [(gogoproto.jsontag) = "-"];
|
||||||
// transaction hash in hex format
|
// hash of the transaction in hex format
|
||||||
string hash = 3 [(gogoproto.moretags) = "rlp:\"-\""];
|
string hash = 3 [(gogoproto.moretags) = "rlp:\"-\""];
|
||||||
// ethereum signer address in hex format. This address value is checked
|
// from is the ethereum signer address in hex format. This address value is checked
|
||||||
// against the address derived from the signature (V, R, S) using the
|
// against the address derived from the signature (V, R, S) using the
|
||||||
// secp256k1 elliptic curve
|
// secp256k1 elliptic curve
|
||||||
string from = 4;
|
string from = 4;
|
||||||
@ -44,16 +43,16 @@ message LegacyTx {
|
|||||||
|
|
||||||
// nonce corresponds to the account nonce (transaction sequence).
|
// nonce corresponds to the account nonce (transaction sequence).
|
||||||
uint64 nonce = 1;
|
uint64 nonce = 1;
|
||||||
// gas price defines the value for each gas unit
|
// gas_price defines the value for each gas unit
|
||||||
string gas_price = 2 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"];
|
string gas_price = 2 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"];
|
||||||
// gas defines the gas limit defined for the transaction.
|
// gas defines the gas limit defined for the transaction.
|
||||||
uint64 gas = 3 [(gogoproto.customname) = "GasLimit"];
|
uint64 gas = 3 [(gogoproto.customname) = "GasLimit"];
|
||||||
// hex formatted address of the recipient
|
// to is the hex formatted address of the recipient
|
||||||
string to = 4;
|
string to = 4;
|
||||||
// value defines the unsigned integer value of the transaction amount.
|
// value defines the unsigned integer value of the transaction amount.
|
||||||
string value = 5
|
string value = 5
|
||||||
[(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customname) = "Amount"];
|
[(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customname) = "Amount"];
|
||||||
// input defines the data payload bytes of the transaction.
|
// data is the data payload bytes of the transaction.
|
||||||
bytes data = 6;
|
bytes data = 6;
|
||||||
// v defines the signature value
|
// v defines the signature value
|
||||||
bytes v = 7;
|
bytes v = 7;
|
||||||
@ -68,7 +67,7 @@ message AccessListTx {
|
|||||||
option (gogoproto.goproto_getters) = false;
|
option (gogoproto.goproto_getters) = false;
|
||||||
option (cosmos_proto.implements_interface) = "TxData";
|
option (cosmos_proto.implements_interface) = "TxData";
|
||||||
|
|
||||||
// destination EVM chain ID
|
// chain_id of the destination EVM chain
|
||||||
string chain_id = 1 [
|
string chain_id = 1 [
|
||||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||||
(gogoproto.customname) = "ChainID",
|
(gogoproto.customname) = "ChainID",
|
||||||
@ -76,17 +75,18 @@ message AccessListTx {
|
|||||||
];
|
];
|
||||||
// nonce corresponds to the account nonce (transaction sequence).
|
// nonce corresponds to the account nonce (transaction sequence).
|
||||||
uint64 nonce = 2;
|
uint64 nonce = 2;
|
||||||
// gas price defines the value for each gas unit
|
// gas_price defines the value for each gas unit
|
||||||
string gas_price = 3 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"];
|
string gas_price = 3 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"];
|
||||||
// gas defines the gas limit defined for the transaction.
|
// gas defines the gas limit defined for the transaction.
|
||||||
uint64 gas = 4 [(gogoproto.customname) = "GasLimit"];
|
uint64 gas = 4 [(gogoproto.customname) = "GasLimit"];
|
||||||
// hex formatted address of the recipient
|
// to is the recipient address in hex format
|
||||||
string to = 5;
|
string to = 5;
|
||||||
// value defines the unsigned integer value of the transaction amount.
|
// value defines the unsigned integer value of the transaction amount.
|
||||||
string value = 6
|
string value = 6
|
||||||
[(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customname) = "Amount"];
|
[(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customname) = "Amount"];
|
||||||
// input defines the data payload bytes of the transaction.
|
// data is the data payload bytes of the transaction.
|
||||||
bytes data = 7;
|
bytes data = 7;
|
||||||
|
// accesses is an array of access tuples
|
||||||
repeated AccessTuple accesses = 8
|
repeated AccessTuple accesses = 8
|
||||||
[(gogoproto.castrepeated) = "AccessList", (gogoproto.jsontag) = "accessList", (gogoproto.nullable) = false];
|
[(gogoproto.castrepeated) = "AccessList", (gogoproto.jsontag) = "accessList", (gogoproto.nullable) = false];
|
||||||
// v defines the signature value
|
// v defines the signature value
|
||||||
@ -102,7 +102,7 @@ message DynamicFeeTx {
|
|||||||
option (gogoproto.goproto_getters) = false;
|
option (gogoproto.goproto_getters) = false;
|
||||||
option (cosmos_proto.implements_interface) = "TxData";
|
option (cosmos_proto.implements_interface) = "TxData";
|
||||||
|
|
||||||
// destination EVM chain ID
|
// chain_id of the destination EVM chain
|
||||||
string chain_id = 1 [
|
string chain_id = 1 [
|
||||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||||
(gogoproto.customname) = "ChainID",
|
(gogoproto.customname) = "ChainID",
|
||||||
@ -110,19 +110,20 @@ message DynamicFeeTx {
|
|||||||
];
|
];
|
||||||
// nonce corresponds to the account nonce (transaction sequence).
|
// nonce corresponds to the account nonce (transaction sequence).
|
||||||
uint64 nonce = 2;
|
uint64 nonce = 2;
|
||||||
// gas tip cap defines the max value for the gas tip
|
// gas_tip_cap defines the max value for the gas tip
|
||||||
string gas_tip_cap = 3 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"];
|
string gas_tip_cap = 3 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"];
|
||||||
// gas fee cap defines the max value for the gas fee
|
// gas_fee_cap defines the max value for the gas fee
|
||||||
string gas_fee_cap = 4 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"];
|
string gas_fee_cap = 4 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"];
|
||||||
// gas defines the gas limit defined for the transaction.
|
// gas defines the gas limit defined for the transaction.
|
||||||
uint64 gas = 5 [(gogoproto.customname) = "GasLimit"];
|
uint64 gas = 5 [(gogoproto.customname) = "GasLimit"];
|
||||||
// hex formatted address of the recipient
|
// to is the hex formatted address of the recipient
|
||||||
string to = 6;
|
string to = 6;
|
||||||
// value defines the the transaction amount.
|
// value defines the the transaction amount.
|
||||||
string value = 7
|
string value = 7
|
||||||
[(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customname) = "Amount"];
|
[(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customname) = "Amount"];
|
||||||
// input defines the data payload bytes of the transaction.
|
// data is the data payload bytes of the transaction.
|
||||||
bytes data = 8;
|
bytes data = 8;
|
||||||
|
// accesses is an array of access tuples
|
||||||
repeated AccessTuple accesses = 9
|
repeated AccessTuple accesses = 9
|
||||||
[(gogoproto.castrepeated) = "AccessList", (gogoproto.jsontag) = "accessList", (gogoproto.nullable) = false];
|
[(gogoproto.castrepeated) = "AccessList", (gogoproto.jsontag) = "accessList", (gogoproto.nullable) = false];
|
||||||
// v defines the signature value
|
// v defines the signature value
|
||||||
@ -133,6 +134,7 @@ message DynamicFeeTx {
|
|||||||
bytes s = 12;
|
bytes s = 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExtensionOptionsEthereumTx is an extension option for ethereum transactions
|
||||||
message ExtensionOptionsEthereumTx {
|
message ExtensionOptionsEthereumTx {
|
||||||
option (gogoproto.goproto_getters) = false;
|
option (gogoproto.goproto_getters) = false;
|
||||||
}
|
}
|
||||||
@ -141,18 +143,18 @@ message ExtensionOptionsEthereumTx {
|
|||||||
message MsgEthereumTxResponse {
|
message MsgEthereumTxResponse {
|
||||||
option (gogoproto.goproto_getters) = false;
|
option (gogoproto.goproto_getters) = false;
|
||||||
|
|
||||||
// ethereum transaction hash in hex format. This hash differs from the
|
// hash of the ethereum transaction in hex format. This hash differs from the
|
||||||
// Tendermint sha256 hash of the transaction bytes. See
|
// Tendermint sha256 hash of the transaction bytes. See
|
||||||
// https://github.com/tendermint/tendermint/issues/6539 for reference
|
// https://github.com/tendermint/tendermint/issues/6539 for reference
|
||||||
string hash = 1;
|
string hash = 1;
|
||||||
// logs contains the transaction hash and the proto-compatible ethereum
|
// logs contains the transaction hash and the proto-compatible ethereum
|
||||||
// logs.
|
// logs.
|
||||||
repeated Log logs = 2;
|
repeated Log logs = 2;
|
||||||
// returned data from evm function (result or data supplied with revert
|
// ret is the returned data from evm function (result or data supplied with revert
|
||||||
// opcode)
|
// opcode)
|
||||||
bytes ret = 3;
|
bytes ret = 3;
|
||||||
// vm error is the error returned by vm execution
|
// vm_error is the error returned by vm execution
|
||||||
string vm_error = 4;
|
string vm_error = 4;
|
||||||
// gas consumed by the transaction
|
// gas_used specifies how much gas was consumed by the transaction
|
||||||
uint64 gas_used = 5;
|
uint64 gas_used = 5;
|
||||||
}
|
}
|
||||||
|
@ -7,26 +7,26 @@ option go_package = "github.com/evmos/ethermint/x/feemarket/types";
|
|||||||
|
|
||||||
// Params defines the EVM module parameters
|
// Params defines the EVM module parameters
|
||||||
message Params {
|
message Params {
|
||||||
// no base fee forces the EIP-1559 base fee to 0 (needed for 0 price calls)
|
// no_base_fee forces the EIP-1559 base fee to 0 (needed for 0 price calls)
|
||||||
bool no_base_fee = 1;
|
bool no_base_fee = 1;
|
||||||
// base fee change denominator bounds the amount the base fee can change
|
// base_fee_change_denominator bounds the amount the base fee can change
|
||||||
// between blocks.
|
// between blocks.
|
||||||
uint32 base_fee_change_denominator = 2;
|
uint32 base_fee_change_denominator = 2;
|
||||||
// elasticity multiplier bounds the maximum gas limit an EIP-1559 block may
|
// elasticity_multiplier bounds the maximum gas limit an EIP-1559 block may
|
||||||
// have.
|
// have.
|
||||||
uint32 elasticity_multiplier = 3;
|
uint32 elasticity_multiplier = 3;
|
||||||
// DEPRECATED: initial base fee for EIP-1559 blocks.
|
// DEPRECATED: initial base fee for EIP-1559 blocks.
|
||||||
reserved 4;
|
reserved 4;
|
||||||
reserved "initial_base_fee";
|
reserved "initial_base_fee";
|
||||||
// height at which the base fee calculation is enabled.
|
// enable_height defines at which block height the base fee calculation is enabled.
|
||||||
int64 enable_height = 5;
|
int64 enable_height = 5;
|
||||||
// base fee for EIP-1559 blocks.
|
// base_fee for EIP-1559 blocks.
|
||||||
string base_fee = 6 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.nullable) = false];
|
string base_fee = 6 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.nullable) = false];
|
||||||
// min_gas_price defines the minimum gas price value for cosmos and eth transactions
|
// min_gas_price defines the minimum gas price value for cosmos and eth transactions
|
||||||
string min_gas_price = 7
|
string min_gas_price = 7
|
||||||
[(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false];
|
[(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false];
|
||||||
// min gas denominator bounds the minimum gasUsed to be charged
|
// min_gas_multiplier bounds the minimum gas used to be charged
|
||||||
// to senders based on GasLimit
|
// to senders based on gas limit
|
||||||
string min_gas_multiplier = 8
|
string min_gas_multiplier = 8
|
||||||
[(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false];
|
[(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false];
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
package ethermint.feemarket.v1;
|
package ethermint.feemarket.v1;
|
||||||
|
|
||||||
import "gogoproto/gogo.proto";
|
|
||||||
import "ethermint/feemarket/v1/feemarket.proto";
|
import "ethermint/feemarket/v1/feemarket.proto";
|
||||||
|
import "gogoproto/gogo.proto";
|
||||||
|
|
||||||
option go_package = "github.com/evmos/ethermint/x/feemarket/types";
|
option go_package = "github.com/evmos/ethermint/x/feemarket/types";
|
||||||
|
|
||||||
// GenesisState defines the feemarket module's genesis state.
|
// GenesisState defines the feemarket module's genesis state.
|
||||||
message GenesisState {
|
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];
|
Params params = 1 [(gogoproto.nullable) = false];
|
||||||
// DEPRECATED: base fee is the exported value from previous software version.
|
// DEPRECATED: base fee is the exported value from previous software version.
|
||||||
// Zero by default.
|
// Zero by default.
|
||||||
reserved 2;
|
reserved 2;
|
||||||
reserved "base_fee";
|
reserved "base_fee";
|
||||||
// block gas is the amount of gas wanted on the last block before the upgrade.
|
// block_gas is the amount of gas wanted on the last block before the upgrade.
|
||||||
// Zero by default.
|
// Zero by default.
|
||||||
uint64 block_gas = 3;
|
uint64 block_gas = 3;
|
||||||
}
|
}
|
@ -3,8 +3,8 @@ package ethermint.feemarket.v1;
|
|||||||
|
|
||||||
import "gogoproto/gogo.proto";
|
import "gogoproto/gogo.proto";
|
||||||
// import "cosmos/base/query/v1beta1/pagination.proto";
|
// import "cosmos/base/query/v1beta1/pagination.proto";
|
||||||
import "google/api/annotations.proto";
|
|
||||||
import "ethermint/feemarket/v1/feemarket.proto";
|
import "ethermint/feemarket/v1/feemarket.proto";
|
||||||
|
import "google/api/annotations.proto";
|
||||||
|
|
||||||
option go_package = "github.com/evmos/ethermint/x/feemarket/types";
|
option go_package = "github.com/evmos/ethermint/x/feemarket/types";
|
||||||
|
|
||||||
@ -39,8 +39,9 @@ message QueryParamsResponse {
|
|||||||
// fee.
|
// fee.
|
||||||
message QueryBaseFeeRequest {}
|
message QueryBaseFeeRequest {}
|
||||||
|
|
||||||
// BaseFeeResponse returns the EIP1559 base fee.
|
// QueryBaseFeeResponse returns the EIP1559 base fee.
|
||||||
message QueryBaseFeeResponse {
|
message QueryBaseFeeResponse {
|
||||||
|
// base_fee is the EIP1559 base fee
|
||||||
string base_fee = 1 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"];
|
string base_fee = 1 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,5 +51,6 @@ message QueryBlockGasRequest {}
|
|||||||
|
|
||||||
// QueryBlockGasResponse returns block gas used for a given height.
|
// QueryBlockGasResponse returns block gas used for a given height.
|
||||||
message QueryBlockGasResponse {
|
message QueryBlockGasResponse {
|
||||||
|
// gas is the returned block gas
|
||||||
int64 gas = 1;
|
int64 gas = 1;
|
||||||
}
|
}
|
@ -16,7 +16,10 @@ message EthAccount {
|
|||||||
|
|
||||||
option (cosmos_proto.implements_interface) = "github.com/cosmos/cosmos-sdk/x/auth/types.AccountI";
|
option (cosmos_proto.implements_interface) = "github.com/cosmos/cosmos-sdk/x/auth/types.AccountI";
|
||||||
|
|
||||||
|
// base_account is an authtypes.BaseAccount
|
||||||
cosmos.auth.v1beta1.BaseAccount base_account = 1
|
cosmos.auth.v1beta1.BaseAccount base_account = 1
|
||||||
[(gogoproto.embed) = true, (gogoproto.moretags) = "yaml:\"base_account\""];
|
[(gogoproto.embed) = true, (gogoproto.moretags) = "yaml:\"base_account\""];
|
||||||
|
|
||||||
|
// code_hash is the hash calculated from the code contents
|
||||||
string code_hash = 2 [(gogoproto.moretags) = "yaml:\"code_hash\""];
|
string code_hash = 2 [(gogoproto.moretags) = "yaml:\"code_hash\""];
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,9 @@ import "gogoproto/gogo.proto";
|
|||||||
|
|
||||||
option go_package = "github.com/evmos/ethermint/types";
|
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 {
|
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
|
string max_priority_price = 1
|
||||||
[(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.nullable) = false];
|
[(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 {
|
message TxResult {
|
||||||
option (gogoproto.goproto_getters) = false;
|
option (gogoproto.goproto_getters) = false;
|
||||||
|
|
||||||
// the block height
|
// height of the blockchain
|
||||||
int64 height = 1;
|
int64 height = 1;
|
||||||
// cosmos tx index
|
// tx_index of the cosmos transaction
|
||||||
uint32 tx_index = 2;
|
uint32 tx_index = 2;
|
||||||
// the msg index in a batch tx
|
// msg_index in a batch transaction
|
||||||
uint32 msg_index = 3;
|
uint32 msg_index = 3;
|
||||||
|
|
||||||
// eth tx index, the index in the list of valid eth tx in the block,
|
// eth_tx_index is the index in the list of valid eth tx in the block,
|
||||||
// aka. the transaction list returned by eth_getBlock api.
|
// aka. the transaction list returned by eth_getBlock api.
|
||||||
int32 eth_tx_index = 4;
|
int32 eth_tx_index = 4;
|
||||||
// if the eth tx is failed
|
// failed is true if the eth transaction did not go succeed
|
||||||
bool failed = 5;
|
bool failed = 5;
|
||||||
// gas used by tx, if exceeds block gas limit,
|
// gas_used by the transaction. If it exceeds the block gas limit,
|
||||||
// it's set to gas limit which is what's actually deducted by ante handler.
|
// it's set to gas limit, which is what's actually deducted by ante handler.
|
||||||
uint64 gas_used = 6;
|
uint64 gas_used = 6;
|
||||||
// the cumulative gas used within current batch tx
|
// cumulative_gas_used specifies the cumulated amount of gas used for all
|
||||||
|
// processed messages within the current batch transaction.
|
||||||
uint64 cumulative_gas_used = 7;
|
uint64 cumulative_gas_used = 7;
|
||||||
}
|
}
|
||||||
|
@ -5,19 +5,21 @@ import "gogoproto/gogo.proto";
|
|||||||
|
|
||||||
option go_package = "github.com/evmos/ethermint/types";
|
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 {
|
message ExtensionOptionsWeb3Tx {
|
||||||
option (gogoproto.goproto_getters) = false;
|
option (gogoproto.goproto_getters) = false;
|
||||||
|
|
||||||
// typed data chain id used only in EIP712 Domain and should match
|
// typed_data_chain_id is used only in EIP712 Domain and should match
|
||||||
// Ethereum network ID in a Web3 provider (e.g. Metamask).
|
// Ethereum network ID in a Web3 provider (e.g. Metamask).
|
||||||
uint64 typed_data_chain_id = 1
|
uint64 typed_data_chain_id = 1
|
||||||
[(gogoproto.jsontag) = "typedDataChainID,omitempty", (gogoproto.customname) = "TypedDataChainID"];
|
[(gogoproto.jsontag) = "typedDataChainID,omitempty", (gogoproto.customname) = "TypedDataChainID"];
|
||||||
|
|
||||||
// fee payer is an account address for the fee payer. It will be validated
|
// fee_payer is an account address for the fee payer. It will be validated
|
||||||
// during EIP712 signature checking.
|
// during EIP712 signature checking.
|
||||||
string fee_payer = 2 [(gogoproto.jsontag) = "feePayer,omitempty"];
|
string fee_payer = 2 [(gogoproto.jsontag) = "feePayer,omitempty"];
|
||||||
|
|
||||||
// fee payer sig is a signature data from the fee paying account,
|
// fee_payer_sig is a signature data from the fee paying account,
|
||||||
// allows to perform fee delegation when using EIP712 Domain.
|
// allows to perform fee delegation when using EIP712 Domain.
|
||||||
bytes fee_payer_sig = 3 [(gogoproto.jsontag) = "feePayerSig,omitempty"];
|
bytes fee_payer_sig = 3 [(gogoproto.jsontag) = "feePayerSig,omitempty"];
|
||||||
}
|
}
|
||||||
|
@ -75,16 +75,10 @@ func (b *Backend) GetProof(address common.Address, storageKeys []string, blockNr
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for proof
|
|
||||||
var proofStr string
|
|
||||||
if proof != nil {
|
|
||||||
proofStr = proof.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
storageProofs[i] = rpctypes.StorageResult{
|
storageProofs[i] = rpctypes.StorageResult{
|
||||||
Key: key,
|
Key: key,
|
||||||
Value: (*hexutil.Big)(new(big.Int).SetBytes(valueBz)),
|
Value: (*hexutil.Big)(new(big.Int).SetBytes(valueBz)),
|
||||||
Proof: []string{proofStr},
|
Proof: GetHexProofs(proof),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,12 +99,6 @@ func (b *Backend) GetProof(address common.Address, storageKeys []string, blockNr
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for proof
|
|
||||||
var accProofStr string
|
|
||||||
if proof != nil {
|
|
||||||
accProofStr = proof.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
balance, ok := sdkmath.NewIntFromString(res.Balance)
|
balance, ok := sdkmath.NewIntFromString(res.Balance)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("invalid balance")
|
return nil, errors.New("invalid balance")
|
||||||
@ -118,7 +106,7 @@ func (b *Backend) GetProof(address common.Address, storageKeys []string, blockNr
|
|||||||
|
|
||||||
return &rpctypes.AccountResult{
|
return &rpctypes.AccountResult{
|
||||||
Address: address,
|
Address: address,
|
||||||
AccountProof: []string{accProofStr},
|
AccountProof: GetHexProofs(proof),
|
||||||
Balance: (*hexutil.Big)(balance.BigInt()),
|
Balance: (*hexutil.Big)(balance.BigInt()),
|
||||||
CodeHash: common.HexToHash(res.CodeHash),
|
CodeHash: common.HexToHash(res.CodeHash),
|
||||||
Nonce: hexutil.Uint64(res.Nonce),
|
Nonce: hexutil.Uint64(res.Nonce),
|
||||||
|
@ -103,6 +103,18 @@ func (suite *BackendTestSuite) TestGetProof() {
|
|||||||
false,
|
false,
|
||||||
&rpctypes.AccountResult{},
|
&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",
|
"pass",
|
||||||
address1,
|
address1,
|
||||||
@ -351,6 +363,27 @@ func (suite *BackendTestSuite) TestGetTransactionCount() {
|
|||||||
true,
|
true,
|
||||||
hexutil.Uint64(0),
|
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 {
|
for _, tc := range testCases {
|
||||||
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
|
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
|
||||||
|
@ -6,7 +6,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/client"
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
|
||||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||||
"github.com/cosmos/cosmos-sdk/server"
|
"github.com/cosmos/cosmos-sdk/server"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
@ -16,12 +15,10 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
||||||
"github.com/evmos/ethermint/crypto/hd"
|
|
||||||
rpctypes "github.com/evmos/ethermint/rpc/types"
|
rpctypes "github.com/evmos/ethermint/rpc/types"
|
||||||
"github.com/evmos/ethermint/server/config"
|
"github.com/evmos/ethermint/server/config"
|
||||||
ethermint "github.com/evmos/ethermint/types"
|
ethermint "github.com/evmos/ethermint/types"
|
||||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||||
"github.com/spf13/viper"
|
|
||||||
"github.com/tendermint/tendermint/libs/log"
|
"github.com/tendermint/tendermint/libs/log"
|
||||||
tmrpctypes "github.com/tendermint/tendermint/rpc/core/types"
|
tmrpctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||||
)
|
)
|
||||||
@ -162,23 +159,6 @@ func NewBackend(
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
algos, _ := clientCtx.Keyring.SupportedAlgorithms()
|
|
||||||
if !algos.Contains(hd.EthSecp256k1) {
|
|
||||||
kr, err := keyring.New(
|
|
||||||
sdk.KeyringServiceName(),
|
|
||||||
viper.GetString(flags.FlagKeyringBackend),
|
|
||||||
clientCtx.KeyringDir,
|
|
||||||
clientCtx.Input,
|
|
||||||
clientCtx.Codec,
|
|
||||||
hd.EthSecp256k1Option(),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
clientCtx = clientCtx.WithKeyring(kr)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &Backend{
|
return &Backend{
|
||||||
ctx: context.Background(),
|
ctx: context.Background(),
|
||||||
clientCtx: clientCtx,
|
clientCtx: clientCtx,
|
||||||
|
@ -2,12 +2,13 @@ package backend
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/evmos/ethermint/crypto/ethsecp256k1"
|
||||||
|
|
||||||
dbm "github.com/tendermint/tm-db"
|
dbm "github.com/tendermint/tm-db"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/client"
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
@ -33,19 +34,22 @@ type BackendTestSuite struct {
|
|||||||
suite.Suite
|
suite.Suite
|
||||||
backend *Backend
|
backend *Backend
|
||||||
acc sdk.AccAddress
|
acc sdk.AccAddress
|
||||||
|
signer keyring.Signer
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBackendTestSuite(t *testing.T) {
|
func TestBackendTestSuite(t *testing.T) {
|
||||||
suite.Run(t, new(BackendTestSuite))
|
suite.Run(t, new(BackendTestSuite))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ChainID = "ethermint_9000-1"
|
||||||
|
|
||||||
// SetupTest is executed before every BackendTestSuite test
|
// SetupTest is executed before every BackendTestSuite test
|
||||||
func (suite *BackendTestSuite) SetupTest() {
|
func (suite *BackendTestSuite) SetupTest() {
|
||||||
ctx := server.NewDefaultContext()
|
ctx := server.NewDefaultContext()
|
||||||
ctx.Viper.Set("telemetry.global-labels", []interface{}{})
|
ctx.Viper.Set("telemetry.global-labels", []interface{}{})
|
||||||
|
|
||||||
baseDir := suite.T().TempDir()
|
baseDir := suite.T().TempDir()
|
||||||
nodeDirName := fmt.Sprintf("node")
|
nodeDirName := "node"
|
||||||
clientDir := filepath.Join(baseDir, nodeDirName, "evmoscli")
|
clientDir := filepath.Join(baseDir, nodeDirName, "evmoscli")
|
||||||
keyRing, err := suite.generateTestKeyring(clientDir)
|
keyRing, err := suite.generateTestKeyring(clientDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -61,8 +65,12 @@ func (suite *BackendTestSuite) SetupTest() {
|
|||||||
Seq: uint64(1),
|
Seq: uint64(1),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
priv, err := ethsecp256k1.GenerateKey()
|
||||||
|
suite.signer = tests.NewSigner(priv)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
encodingConfig := encoding.MakeConfig(app.ModuleBasics)
|
encodingConfig := encoding.MakeConfig(app.ModuleBasics)
|
||||||
clientCtx := client.Context{}.WithChainID("ethermint_9000-1").
|
clientCtx := client.Context{}.WithChainID(ChainID).
|
||||||
WithHeight(1).
|
WithHeight(1).
|
||||||
WithTxConfig(encodingConfig.TxConfig).
|
WithTxConfig(encodingConfig.TxConfig).
|
||||||
WithKeyringDir(clientDir).
|
WithKeyringDir(clientDir).
|
||||||
@ -70,19 +78,24 @@ func (suite *BackendTestSuite) SetupTest() {
|
|||||||
WithAccountRetriever(client.TestAccountRetriever{Accounts: accounts})
|
WithAccountRetriever(client.TestAccountRetriever{Accounts: accounts})
|
||||||
|
|
||||||
allowUnprotectedTxs := false
|
allowUnprotectedTxs := false
|
||||||
|
|
||||||
idxer := indexer.NewKVIndexer(dbm.NewMemDB(), ctx.Logger, clientCtx)
|
idxer := indexer.NewKVIndexer(dbm.NewMemDB(), ctx.Logger, clientCtx)
|
||||||
|
|
||||||
suite.backend = NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, idxer)
|
suite.backend = NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, idxer)
|
||||||
suite.backend.queryClient.QueryClient = mocks.NewEVMQueryClient(suite.T())
|
suite.backend.queryClient.QueryClient = mocks.NewEVMQueryClient(suite.T())
|
||||||
suite.backend.clientCtx.Client = mocks.NewClient(suite.T())
|
suite.backend.clientCtx.Client = mocks.NewClient(suite.T())
|
||||||
|
suite.backend.queryClient.FeeMarket = mocks.NewFeeMarketQueryClient(suite.T())
|
||||||
suite.backend.ctx = rpctypes.ContextWithHeight(1)
|
suite.backend.ctx = rpctypes.ContextWithHeight(1)
|
||||||
|
|
||||||
|
// Add codec
|
||||||
|
encCfg := encoding.MakeConfig(app.ModuleBasics)
|
||||||
|
suite.backend.clientCtx.Codec = encCfg.Codec
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// buildEthereumTx returns an example legacy Ethereum transaction
|
// buildEthereumTx returns an example legacy Ethereum transaction
|
||||||
func (suite *BackendTestSuite) buildEthereumTx() (*evmtypes.MsgEthereumTx, []byte) {
|
func (suite *BackendTestSuite) buildEthereumTx() (*evmtypes.MsgEthereumTx, []byte) {
|
||||||
msgEthereumTx := evmtypes.NewTx(
|
msgEthereumTx := evmtypes.NewTx(
|
||||||
big.NewInt(1),
|
suite.backend.chainID,
|
||||||
uint64(0),
|
uint64(0),
|
||||||
&common.Address{},
|
&common.Address{},
|
||||||
big.NewInt(0),
|
big.NewInt(0),
|
||||||
@ -132,6 +145,7 @@ func (suite *BackendTestSuite) buildFormattedBlock(
|
|||||||
uint64(header.Height),
|
uint64(header.Height),
|
||||||
uint64(0),
|
uint64(0),
|
||||||
baseFee,
|
baseFee,
|
||||||
|
suite.backend.chainID,
|
||||||
)
|
)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
ethRPCTxs = []interface{}{rpcTx}
|
ethRPCTxs = []interface{}{rpcTx}
|
||||||
@ -157,3 +171,25 @@ func (suite *BackendTestSuite) generateTestKeyring(clientDir string) (keyring.Ke
|
|||||||
encCfg := encoding.MakeConfig(app.ModuleBasics)
|
encCfg := encoding.MakeConfig(app.ModuleBasics)
|
||||||
return keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, clientDir, buf, encCfg.Codec, []keyring.Option{hd.EthSecp256k1Option()}...)
|
return keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, clientDir, buf, encCfg.Codec, []keyring.Option{hd.EthSecp256k1Option()}...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (suite *BackendTestSuite) signAndEncodeEthTx(msgEthereumTx *evmtypes.MsgEthereumTx) []byte {
|
||||||
|
from, priv := tests.NewAddrKey()
|
||||||
|
signer := tests.NewSigner(priv)
|
||||||
|
|
||||||
|
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||||
|
RegisterParamsWithoutHeader(queryClient, 1)
|
||||||
|
|
||||||
|
ethSigner := ethtypes.LatestSigner(suite.backend.ChainConfig())
|
||||||
|
msgEthereumTx.From = from.String()
|
||||||
|
err := msgEthereumTx.Sign(ethSigner, signer)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
tx, err := msgEthereumTx.BuildTx(suite.backend.clientCtx.TxConfig.NewTxBuilder(), "aphoton")
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
txEncoder := suite.backend.clientCtx.TxConfig.TxEncoder()
|
||||||
|
txBz, err := txEncoder(tx)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
return txBz
|
||||||
|
}
|
||||||
|
@ -376,6 +376,7 @@ func (b *Backend) RPCBlockFromTendermintBlock(
|
|||||||
uint64(block.Height),
|
uint64(block.Height),
|
||||||
uint64(txIndex),
|
uint64(txIndex),
|
||||||
baseFee,
|
baseFee,
|
||||||
|
b.chainID,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.logger.Debug("NewTransactionFromData for receipt failed", "hash", tx.Hash().Hex(), "error", err.Error())
|
b.logger.Debug("NewTransactionFromData for receipt failed", "hash", tx.Hash().Hex(), "error", err.Error())
|
||||||
|
@ -30,8 +30,8 @@ func (suite *BackendTestSuite) TestBlockNumber() {
|
|||||||
{
|
{
|
||||||
"fail - invalid block header height",
|
"fail - invalid block header height",
|
||||||
func() {
|
func() {
|
||||||
height := int64(1)
|
|
||||||
var header metadata.MD
|
var header metadata.MD
|
||||||
|
height := int64(1)
|
||||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||||
RegisterParamsInvalidHeight(queryClient, &header, int64(height))
|
RegisterParamsInvalidHeight(queryClient, &header, int64(height))
|
||||||
},
|
},
|
||||||
@ -41,8 +41,8 @@ func (suite *BackendTestSuite) TestBlockNumber() {
|
|||||||
{
|
{
|
||||||
"fail - invalid block header",
|
"fail - invalid block header",
|
||||||
func() {
|
func() {
|
||||||
height := int64(1)
|
|
||||||
var header metadata.MD
|
var header metadata.MD
|
||||||
|
height := int64(1)
|
||||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||||
RegisterParamsInvalidHeader(queryClient, &header, int64(height))
|
RegisterParamsInvalidHeader(queryClient, &header, int64(height))
|
||||||
},
|
},
|
||||||
@ -52,8 +52,8 @@ func (suite *BackendTestSuite) TestBlockNumber() {
|
|||||||
{
|
{
|
||||||
"pass - app state header height 1",
|
"pass - app state header height 1",
|
||||||
func() {
|
func() {
|
||||||
height := int64(1)
|
|
||||||
var header metadata.MD
|
var header metadata.MD
|
||||||
|
height := int64(1)
|
||||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||||
RegisterParams(queryClient, &header, int64(height))
|
RegisterParams(queryClient, &header, int64(height))
|
||||||
},
|
},
|
||||||
@ -552,8 +552,8 @@ func (suite *BackendTestSuite) TestTendermintBlockByNumber() {
|
|||||||
"fail - blockNum < 0 with app state height error",
|
"fail - blockNum < 0 with app state height error",
|
||||||
ethrpc.BlockNumber(-1),
|
ethrpc.BlockNumber(-1),
|
||||||
func(_ ethrpc.BlockNumber) {
|
func(_ ethrpc.BlockNumber) {
|
||||||
appHeight := int64(1)
|
|
||||||
var header metadata.MD
|
var header metadata.MD
|
||||||
|
appHeight := int64(1)
|
||||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||||
RegisterParamsError(queryClient, &header, appHeight)
|
RegisterParamsError(queryClient, &header, appHeight)
|
||||||
},
|
},
|
||||||
@ -564,8 +564,8 @@ func (suite *BackendTestSuite) TestTendermintBlockByNumber() {
|
|||||||
"pass - blockNum < 0 with app state height >= 1",
|
"pass - blockNum < 0 with app state height >= 1",
|
||||||
ethrpc.BlockNumber(-1),
|
ethrpc.BlockNumber(-1),
|
||||||
func(blockNum ethrpc.BlockNumber) {
|
func(blockNum ethrpc.BlockNumber) {
|
||||||
appHeight := int64(1)
|
|
||||||
var header metadata.MD
|
var header metadata.MD
|
||||||
|
appHeight := int64(1)
|
||||||
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
|
||||||
RegisterParams(queryClient, &header, appHeight)
|
RegisterParams(queryClient, &header, appHeight)
|
||||||
|
|
||||||
@ -1088,6 +1088,7 @@ func (suite *BackendTestSuite) TestGetEthBlockFromTendermint() {
|
|||||||
uint64(header.Height),
|
uint64(header.Height),
|
||||||
uint64(0),
|
uint64(0),
|
||||||
tc.baseFee,
|
tc.baseFee,
|
||||||
|
suite.backend.chainID,
|
||||||
)
|
)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
ethRPCTxs = []interface{}{rpcTx}
|
ethRPCTxs = []interface{}{rpcTx}
|
||||||
|
@ -7,9 +7,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
errorsmod "cosmossdk.io/errors"
|
||||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
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"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
@ -151,7 +151,7 @@ func (b *Backend) SendRawTransaction(data hexutil.Bytes) (common.Hash, error) {
|
|||||||
syncCtx := b.clientCtx.WithBroadcastMode(flags.BroadcastSync)
|
syncCtx := b.clientCtx.WithBroadcastMode(flags.BroadcastSync)
|
||||||
rsp, err := syncCtx.BroadcastTx(txBytes)
|
rsp, err := syncCtx.BroadcastTx(txBytes)
|
||||||
if rsp != nil && rsp.Code != 0 {
|
if rsp != nil && rsp.Code != 0 {
|
||||||
err = sdkerrors.ABCIError(rsp.Codespace, rsp.Code, rsp.RawLog)
|
err = errorsmod.ABCIError(rsp.Codespace, rsp.Code, rsp.RawLog)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.logger.Error("failed to broadcast tx", "error", err.Error())
|
b.logger.Error("failed to broadcast tx", "error", err.Error())
|
||||||
@ -269,6 +269,8 @@ func (b *Backend) SetTxDefaults(args evmtypes.TransactionArgs) (evmtypes.Transac
|
|||||||
Value: args.Value,
|
Value: args.Value,
|
||||||
Data: input,
|
Data: input,
|
||||||
AccessList: args.AccessList,
|
AccessList: args.AccessList,
|
||||||
|
ChainID: args.ChainID,
|
||||||
|
Nonce: args.Nonce,
|
||||||
}
|
}
|
||||||
|
|
||||||
blockNr := rpctypes.NewBlockNumber(big.NewInt(0))
|
blockNr := rpctypes.NewBlockNumber(big.NewInt(0))
|
||||||
@ -309,6 +311,7 @@ func (b *Backend) EstimateGas(args evmtypes.TransactionArgs, blockNrOptional *rp
|
|||||||
Args: bz,
|
Args: bz,
|
||||||
GasCap: b.RPCGasCap(),
|
GasCap: b.RPCGasCap(),
|
||||||
ProposerAddress: sdk.ConsAddress(header.Block.ProposerAddress),
|
ProposerAddress: sdk.ConsAddress(header.Block.ProposerAddress),
|
||||||
|
ChainId: b.chainID.Int64(),
|
||||||
}
|
}
|
||||||
|
|
||||||
// From ContextWithHeight: if the provided height is 0,
|
// From ContextWithHeight: if the provided height is 0,
|
||||||
@ -335,10 +338,12 @@ func (b *Backend) DoCall(
|
|||||||
// the error message imitates geth behavior
|
// the error message imitates geth behavior
|
||||||
return nil, errors.New("header not found")
|
return nil, errors.New("header not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
req := evmtypes.EthCallRequest{
|
req := evmtypes.EthCallRequest{
|
||||||
Args: bz,
|
Args: bz,
|
||||||
GasCap: b.RPCGasCap(),
|
GasCap: b.RPCGasCap(),
|
||||||
ProposerAddress: sdk.ConsAddress(header.Block.ProposerAddress),
|
ProposerAddress: sdk.ConsAddress(header.Block.ProposerAddress),
|
||||||
|
ChainId: b.chainID.Int64(),
|
||||||
}
|
}
|
||||||
|
|
||||||
// From ContextWithHeight: if the provided height is 0,
|
// From ContextWithHeight: if the provided height is 0,
|
||||||
|
493
rpc/backend/call_tx_test.go
Normal file
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)
|
blockEnd = int64(blockNumber)
|
||||||
}
|
}
|
||||||
|
|
||||||
userBlockCountInt := int64(userBlockCount)
|
userBlockCountInt := int64(userBlockCount)
|
||||||
maxBlockCount := int64(b.cfg.JSONRPC.FeeHistoryCap)
|
maxBlockCount := int64(b.cfg.JSONRPC.FeeHistoryCap)
|
||||||
if userBlockCountInt > maxBlockCount {
|
if userBlockCountInt > maxBlockCount {
|
||||||
return nil, fmt.Errorf("FeeHistory user block count %d higher than %d", userBlockCountInt, maxBlockCount)
|
return nil, fmt.Errorf("FeeHistory user block count %d higher than %d", userBlockCountInt, maxBlockCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
blockStart := blockEnd - userBlockCountInt
|
blockStart := blockEnd - userBlockCountInt
|
||||||
if blockStart < 0 {
|
if blockStart < 0 {
|
||||||
blockStart = 0
|
blockStart = 0
|
||||||
@ -173,6 +175,7 @@ func (b *Backend) FeeHistory(
|
|||||||
for i := 0; i < int(blockCount); i++ {
|
for i := 0; i < int(blockCount); i++ {
|
||||||
reward[i] = make([]*hexutil.Big, rewardCount)
|
reward[i] = make([]*hexutil.Big, rewardCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
thisBaseFee := make([]*hexutil.Big, blockCount)
|
thisBaseFee := make([]*hexutil.Big, blockCount)
|
||||||
thisGasUsedRatio := make([]float64, blockCount)
|
thisGasUsedRatio := make([]float64, blockCount)
|
||||||
|
|
||||||
|
@ -4,6 +4,12 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"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"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/tendermint/tendermint/abci/types"
|
"github.com/tendermint/tendermint/abci/types"
|
||||||
tmrpctypes "github.com/tendermint/tendermint/rpc/core/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 (
|
import (
|
||||||
"context"
|
"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/ethereum/go-ethereum/common"
|
||||||
"github.com/evmos/ethermint/rpc/backend/mocks"
|
"github.com/evmos/ethermint/rpc/backend/mocks"
|
||||||
rpc "github.com/evmos/ethermint/rpc/types"
|
rpc "github.com/evmos/ethermint/rpc/types"
|
||||||
|
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||||
mock "github.com/stretchr/testify/mock"
|
mock "github.com/stretchr/testify/mock"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
@ -15,6 +18,7 @@ import (
|
|||||||
tmrpcclient "github.com/tendermint/tendermint/rpc/client"
|
tmrpcclient "github.com/tendermint/tendermint/rpc/client"
|
||||||
tmrpctypes "github.com/tendermint/tendermint/rpc/core/types"
|
tmrpctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||||
"github.com/tendermint/tendermint/types"
|
"github.com/tendermint/tendermint/types"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Client defines a mocked object that implements the Tendermint JSON-RPC Client
|
// 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.
|
// To use a mock method it has to be registered in a given test.
|
||||||
var _ tmrpcclient.Client = &mocks.Client{}
|
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
|
// 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(
|
func RegisterBlock(
|
||||||
client *mocks.Client,
|
client *mocks.Client,
|
||||||
height int64,
|
height int64,
|
||||||
@ -33,24 +105,24 @@ func RegisterBlock(
|
|||||||
// without tx
|
// without tx
|
||||||
if tx == nil {
|
if tx == nil {
|
||||||
emptyBlock := types.MakeBlock(height, []types.Tx{}, nil, nil)
|
emptyBlock := types.MakeBlock(height, []types.Tx{}, nil, nil)
|
||||||
|
emptyBlock.ChainID = ChainID
|
||||||
resBlock := &tmrpctypes.ResultBlock{Block: emptyBlock}
|
resBlock := &tmrpctypes.ResultBlock{Block: emptyBlock}
|
||||||
client.On("Block", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).
|
client.On("Block", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).Return(resBlock, nil)
|
||||||
Return(resBlock, nil)
|
|
||||||
return resBlock, nil
|
return resBlock, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// with tx
|
// with tx
|
||||||
block := types.MakeBlock(height, []types.Tx{tx}, nil, nil)
|
block := types.MakeBlock(height, []types.Tx{tx}, nil, nil)
|
||||||
|
block.ChainID = ChainID
|
||||||
resBlock := &tmrpctypes.ResultBlock{Block: block}
|
resBlock := &tmrpctypes.ResultBlock{Block: block}
|
||||||
client.On("Block", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).
|
client.On("Block", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).Return(resBlock, nil)
|
||||||
Return(resBlock, nil)
|
|
||||||
return resBlock, nil
|
return resBlock, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Block returns error
|
// Block returns error
|
||||||
func RegisterBlockError(client *mocks.Client, height int64) {
|
func RegisterBlockError(client *mocks.Client, height int64) {
|
||||||
client.On("Block", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).
|
client.On("Block", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).
|
||||||
Return(nil, sdkerrors.ErrInvalidRequest)
|
Return(nil, errortypes.ErrInvalidRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Block not found
|
// Block not found
|
||||||
@ -72,6 +144,7 @@ func TestRegisterBlock(t *testing.T) {
|
|||||||
res, err := client.Block(rpc.ContextWithHeight(height), &height)
|
res, err := client.Block(rpc.ContextWithHeight(height), &height)
|
||||||
|
|
||||||
emptyBlock := types.MakeBlock(height, []types.Tx{}, nil, nil)
|
emptyBlock := types.MakeBlock(height, []types.Tx{}, nil, nil)
|
||||||
|
emptyBlock.ChainID = ChainID
|
||||||
resBlock := &tmrpctypes.ResultBlock{Block: emptyBlock}
|
resBlock := &tmrpctypes.ResultBlock{Block: emptyBlock}
|
||||||
require.Equal(t, resBlock, res)
|
require.Equal(t, resBlock, res)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -86,7 +159,7 @@ func RegisterConsensusParams(client *mocks.Client, height int64) {
|
|||||||
|
|
||||||
func RegisterConsensusParamsError(client *mocks.Client, height int64) {
|
func RegisterConsensusParamsError(client *mocks.Client, height int64) {
|
||||||
client.On("ConsensusParams", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).
|
client.On("ConsensusParams", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).
|
||||||
Return(nil, sdkerrors.ErrInvalidRequest)
|
Return(nil, errortypes.ErrInvalidRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRegisterConsensusParams(t *testing.T) {
|
func TestRegisterConsensusParams(t *testing.T) {
|
||||||
@ -101,6 +174,26 @@ func TestRegisterConsensusParams(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// BlockResults
|
// 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(
|
func RegisterBlockResults(
|
||||||
client *mocks.Client,
|
client *mocks.Client,
|
||||||
height int64,
|
height int64,
|
||||||
@ -117,7 +210,7 @@ func RegisterBlockResults(
|
|||||||
|
|
||||||
func RegisterBlockResultsError(client *mocks.Client, height int64) {
|
func RegisterBlockResultsError(client *mocks.Client, height int64) {
|
||||||
client.On("BlockResults", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).
|
client.On("BlockResults", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).
|
||||||
Return(nil, sdkerrors.ErrInvalidRequest)
|
Return(nil, errortypes.ErrInvalidRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRegisterBlockResults(t *testing.T) {
|
func TestRegisterBlockResults(t *testing.T) {
|
||||||
@ -150,7 +243,7 @@ func RegisterBlockByHash(
|
|||||||
|
|
||||||
func RegisterBlockByHashError(client *mocks.Client, hash common.Hash, tx []byte) {
|
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}).
|
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) {
|
func RegisterBlockByHashNotFound(client *mocks.Client, hash common.Hash, tx []byte) {
|
||||||
@ -167,3 +260,22 @@ func RegisterABCIQueryWithOptions(client *mocks.Client, height int64, path strin
|
|||||||
},
|
},
|
||||||
}, nil)
|
}, 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
|
package backend
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
grpctypes "github.com/cosmos/cosmos-sdk/types/grpc"
|
grpctypes "github.com/cosmos/cosmos-sdk/types/grpc"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/evmos/ethermint/rpc/backend/mocks"
|
"github.com/evmos/ethermint/rpc/backend/mocks"
|
||||||
@ -19,6 +18,8 @@ import (
|
|||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
"google.golang.org/grpc/metadata"
|
"google.golang.org/grpc/metadata"
|
||||||
"google.golang.org/grpc/status"
|
"google.golang.org/grpc/status"
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
// QueryClient defines a mocked object that implements the ethermint GRPC
|
// 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.
|
// To use a mock method it has to be registered in a given test.
|
||||||
var _ evmtypes.QueryClient = &mocks.EVMQueryClient{}
|
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
|
// Params
|
||||||
func RegisterParams(queryClient *mocks.EVMQueryClient, header *metadata.MD, height int64) {
|
func RegisterParams(queryClient *mocks.EVMQueryClient, header *metadata.MD, height int64) {
|
||||||
queryClient.On("Params", rpc.ContextWithHeight(height), &evmtypes.QueryParamsRequest{}, grpc.Header(header)).
|
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) {
|
func RegisterParamsInvalidHeader(queryClient *mocks.EVMQueryClient, header *metadata.MD, height int64) {
|
||||||
queryClient.On("Params", rpc.ContextWithHeight(height), &evmtypes.QueryParamsRequest{}, grpc.Header(header)).
|
queryClient.On("Params", rpc.ContextWithHeight(height), &evmtypes.QueryParamsRequest{}, grpc.Header(header)).
|
||||||
Return(&evmtypes.QueryParamsResponse{}, nil).
|
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
|
// Params returns error
|
||||||
func RegisterParamsError(queryClient *mocks.EVMQueryClient, header *metadata.MD, height int64) {
|
func RegisterParamsError(queryClient *mocks.EVMQueryClient, header *metadata.MD, height int64) {
|
||||||
queryClient.On("Params", rpc.ContextWithHeight(height), &evmtypes.QueryParamsRequest{}, grpc.Header(header)).
|
queryClient.On("Params", rpc.ContextWithHeight(height), &evmtypes.QueryParamsRequest{}, grpc.Header(header)).
|
||||||
Return(nil, sdkerrors.ErrInvalidRequest)
|
Return(nil, errortypes.ErrInvalidRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRegisterParams(t *testing.T) {
|
func TestRegisterParams(t *testing.T) {
|
||||||
queryClient := mocks.NewEVMQueryClient(t)
|
|
||||||
var header metadata.MD
|
var header metadata.MD
|
||||||
|
queryClient := mocks.NewEVMQueryClient(t)
|
||||||
|
|
||||||
height := int64(1)
|
height := int64(1)
|
||||||
RegisterParams(queryClient, &header, height)
|
RegisterParams(queryClient, &header, height)
|
||||||
|
|
||||||
@ -91,6 +135,26 @@ func TestRegisterParamsError(t *testing.T) {
|
|||||||
require.Error(t, err)
|
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
|
// BaseFee
|
||||||
func RegisterBaseFee(queryClient *mocks.EVMQueryClient, baseFee sdk.Int) {
|
func RegisterBaseFee(queryClient *mocks.EVMQueryClient, baseFee sdk.Int) {
|
||||||
queryClient.On("BaseFee", rpc.ContextWithHeight(1), &evmtypes.QueryBaseFeeRequest{}).
|
queryClient.On("BaseFee", rpc.ContextWithHeight(1), &evmtypes.QueryBaseFeeRequest{}).
|
||||||
@ -137,12 +201,7 @@ func TestRegisterBaseFeeDisabled(t *testing.T) {
|
|||||||
// ValidatorAccount
|
// ValidatorAccount
|
||||||
func RegisterValidatorAccount(queryClient *mocks.EVMQueryClient, validator sdk.AccAddress) {
|
func RegisterValidatorAccount(queryClient *mocks.EVMQueryClient, validator sdk.AccAddress) {
|
||||||
queryClient.On("ValidatorAccount", rpc.ContextWithHeight(1), &evmtypes.QueryValidatorAccountRequest{}).
|
queryClient.On("ValidatorAccount", rpc.ContextWithHeight(1), &evmtypes.QueryValidatorAccountRequest{}).
|
||||||
Return(
|
Return(&evmtypes.QueryValidatorAccountResponse{AccountAddress: validator.String()}, nil)
|
||||||
&evmtypes.QueryValidatorAccountResponse{
|
|
||||||
AccountAddress: validator.String(),
|
|
||||||
},
|
|
||||||
nil,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func RegisterValidatorAccountError(queryClient *mocks.EVMQueryClient) {
|
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) {
|
func RegisterCodeError(queryClient *mocks.EVMQueryClient, addr common.Address) {
|
||||||
queryClient.On("Code", rpc.ContextWithHeight(1), &evmtypes.QueryCodeRequest{Address: addr.String()}).
|
queryClient.On("Code", rpc.ContextWithHeight(1), &evmtypes.QueryCodeRequest{Address: addr.String()}).
|
||||||
Return(nil, sdkerrors.ErrInvalidRequest)
|
Return(nil, errortypes.ErrInvalidRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Storage
|
// Storage
|
||||||
@ -179,7 +238,7 @@ func RegisterStorageAt(queryClient *mocks.EVMQueryClient, addr common.Address, k
|
|||||||
|
|
||||||
func RegisterStorageAtError(queryClient *mocks.EVMQueryClient, addr common.Address, key string) {
|
func RegisterStorageAtError(queryClient *mocks.EVMQueryClient, addr common.Address, key string) {
|
||||||
queryClient.On("Storage", rpc.ContextWithHeight(1), &evmtypes.QueryStorageRequest{Address: addr.String(), Key: key}).
|
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) {
|
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) {
|
func RegisterBalanceError(queryClient *mocks.EVMQueryClient, addr common.Address, height int64) {
|
||||||
queryClient.On("Balance", rpc.ContextWithHeight(height), &evmtypes.QueryBalanceRequest{Address: addr.String()}).
|
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 {
|
if resBlock == nil {
|
||||||
return nil, errors.Errorf("block not found for hash %s", hash)
|
return nil, errors.Errorf("block not found for hash %s", hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
return b.GetLogsByHeight(&resBlock.Block.Header.Height)
|
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"
|
"math/big"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
errorsmod "cosmossdk.io/errors"
|
||||||
sdkmath "cosmossdk.io/math"
|
sdkmath "cosmossdk.io/math"
|
||||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||||
@ -12,7 +13,6 @@ import (
|
|||||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||||
sdkconfig "github.com/cosmos/cosmos-sdk/server/config"
|
sdkconfig "github.com/cosmos/cosmos-sdk/server/config"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
|
||||||
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
|
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
|
||||||
distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
|
distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
@ -165,7 +165,7 @@ func (b *Backend) SetEtherbase(etherbase common.Address) bool {
|
|||||||
syncCtx := b.clientCtx.WithBroadcastMode(flags.BroadcastSync)
|
syncCtx := b.clientCtx.WithBroadcastMode(flags.BroadcastSync)
|
||||||
rsp, err := syncCtx.BroadcastTx(txBytes)
|
rsp, err := syncCtx.BroadcastTx(txBytes)
|
||||||
if rsp != nil && rsp.Code != 0 {
|
if rsp != nil && rsp.Code != 0 {
|
||||||
err = sdkerrors.ABCIError(rsp.Codespace, rsp.Code, rsp.RawLog)
|
err = errorsmod.ABCIError(rsp.Codespace, rsp.Code, rsp.RawLog)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.logger.Debug("failed to broadcast tx", "error", err.Error())
|
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
|
package backend
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
errorsmod "cosmossdk.io/errors"
|
||||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
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/accounts/keystore"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
||||||
"github.com/evmos/ethermint/ethereum/eip712"
|
|
||||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
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
|
// 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())
|
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)
|
args, err = b.SetTxDefaults(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.Hash{}, err
|
return common.Hash{}, err
|
||||||
@ -89,7 +93,7 @@ func (b *Backend) SendTransaction(args evmtypes.TransactionArgs) (common.Hash, e
|
|||||||
syncCtx := b.clientCtx.WithBroadcastMode(flags.BroadcastSync)
|
syncCtx := b.clientCtx.WithBroadcastMode(flags.BroadcastSync)
|
||||||
rsp, err := syncCtx.BroadcastTx(txBytes)
|
rsp, err := syncCtx.BroadcastTx(txBytes)
|
||||||
if rsp != nil && rsp.Code != 0 {
|
if rsp != nil && rsp.Code != 0 {
|
||||||
err = sdkerrors.ABCIError(rsp.Codespace, rsp.Code, rsp.RawLog)
|
err = errorsmod.ABCIError(rsp.Codespace, rsp.Code, rsp.RawLog)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.logger.Error("failed to broadcast tx", "error", err.Error())
|
b.logger.Error("failed to broadcast tx", "error", err.Error())
|
||||||
@ -131,7 +135,7 @@ func (b *Backend) SignTypedData(address common.Address, typedData apitypes.Typed
|
|||||||
return nil, fmt.Errorf("%s; %s", keystore.ErrNoMatch, err.Error())
|
return nil, fmt.Errorf("%s; %s", keystore.ErrNoMatch, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
sigHash, err := eip712.ComputeTypedDataHash(typedData)
|
sigHash, _, err := apitypes.TypedDataAndHash(typedData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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,
|
BlockTime: blk.Block.Time,
|
||||||
BlockHash: common.Bytes2Hex(blk.BlockID.Hash),
|
BlockHash: common.Bytes2Hex(blk.BlockID.Hash),
|
||||||
ProposerAddress: sdk.ConsAddress(blk.Block.ProposerAddress),
|
ProposerAddress: sdk.ConsAddress(blk.Block.ProposerAddress),
|
||||||
|
ChainId: b.chainID.Int64(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if config != nil {
|
if config != nil {
|
||||||
@ -112,7 +113,7 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi
|
|||||||
return decodedResult, nil
|
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
|
// executes all the transactions contained within. The return value will be one item
|
||||||
// per transaction, dependent on the requested tracer.
|
// per transaction, dependent on the requested tracer.
|
||||||
func (b *Backend) TraceBlock(height rpctypes.BlockNumber,
|
func (b *Backend) TraceBlock(height rpctypes.BlockNumber,
|
||||||
@ -162,6 +163,7 @@ func (b *Backend) TraceBlock(height rpctypes.BlockNumber,
|
|||||||
BlockTime: block.Block.Time,
|
BlockTime: block.Block.Time,
|
||||||
BlockHash: common.Bytes2Hex(block.BlockID.Hash),
|
BlockHash: common.Bytes2Hex(block.BlockID.Hash),
|
||||||
ProposerAddress: sdk.ConsAddress(block.Block.ProposerAddress),
|
ProposerAddress: sdk.ConsAddress(block.Block.ProposerAddress),
|
||||||
|
ChainId: b.chainID.Int64(),
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := b.queryClient.TraceBlock(ctxWithHeight, traceBlockRequest)
|
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 (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
errorsmod "cosmossdk.io/errors"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
@ -74,6 +74,7 @@ func (b *Backend) GetTransactionByHash(txHash common.Hash) (*rpctypes.RPCTransac
|
|||||||
uint64(res.Height),
|
uint64(res.Height),
|
||||||
uint64(res.EthTxIndex),
|
uint64(res.EthTxIndex),
|
||||||
baseFee,
|
baseFee,
|
||||||
|
b.chainID,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,6 +103,7 @@ func (b *Backend) getTransactionByHashPending(txHash common.Hash) (*rpctypes.RPC
|
|||||||
uint64(0),
|
uint64(0),
|
||||||
uint64(0),
|
uint64(0),
|
||||||
nil,
|
nil,
|
||||||
|
b.chainID,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -214,6 +216,7 @@ func (b *Backend) GetTransactionReceipt(hash common.Hash) (map[string]interface{
|
|||||||
// sender and receiver (contract or EOA) addreses
|
// sender and receiver (contract or EOA) addreses
|
||||||
"from": from,
|
"from": from,
|
||||||
"to": txData.GetTo(),
|
"to": txData.GetTo(),
|
||||||
|
"type": hexutil.Uint(ethMsg.AsTransaction().Type()),
|
||||||
}
|
}
|
||||||
|
|
||||||
if logs == nil {
|
if logs == nil {
|
||||||
@ -288,7 +291,7 @@ func (b *Backend) GetTxByEthHash(hash common.Hash) (*ethermint.TxResult, error)
|
|||||||
return txs.GetTxByHash(hash)
|
return txs.GetTxByHash(hash)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, sdkerrors.Wrapf(err, "GetTxByEthHash %s", hash.Hex())
|
return nil, errorsmod.Wrapf(err, "GetTxByEthHash %s", hash.Hex())
|
||||||
}
|
}
|
||||||
return txResult, nil
|
return txResult, nil
|
||||||
}
|
}
|
||||||
@ -308,7 +311,7 @@ func (b *Backend) GetTxByTxIndex(height int64, index uint) (*ethermint.TxResult,
|
|||||||
return txs.GetTxByTxIndex(int(index))
|
return txs.GetTxByTxIndex(int(index))
|
||||||
})
|
})
|
||||||
if err != nil {
|
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
|
return txResult, nil
|
||||||
}
|
}
|
||||||
@ -339,7 +342,7 @@ func (b *Backend) queryTendermintTxIndexer(query string, txGetter func(*rpctypes
|
|||||||
return rpctypes.ParseTxIndexerResult(txResult, tx, txGetter)
|
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) {
|
func (b *Backend) GetTransactionByBlockAndIndex(block *tmrpctypes.ResultBlock, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) {
|
||||||
blockRes, err := b.TendermintBlockResultByNumber(&block.Block.Height)
|
blockRes, err := b.TendermintBlockResultByNumber(&block.Block.Height)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -386,5 +389,6 @@ func (b *Backend) GetTransactionByBlockAndIndex(block *tmrpctypes.ResultBlock, i
|
|||||||
uint64(block.Block.Height),
|
uint64(block.Block.Height),
|
||||||
uint64(idx),
|
uint64(idx),
|
||||||
baseFee,
|
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"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/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"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
@ -21,6 +23,7 @@ import (
|
|||||||
|
|
||||||
"github.com/evmos/ethermint/rpc/types"
|
"github.com/evmos/ethermint/rpc/types"
|
||||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||||
|
"github.com/tendermint/tendermint/proto/tendermint/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
type txGasAndReward struct {
|
type txGasAndReward struct {
|
||||||
@ -45,8 +48,15 @@ func (s sortGasAndReward) Less(i, j int) bool {
|
|||||||
// Todo: include the ability to specify a blockNumber
|
// Todo: include the ability to specify a blockNumber
|
||||||
func (b *Backend) getAccountNonce(accAddr common.Address, pending bool, height int64, logger log.Logger) (uint64, error) {
|
func (b *Backend) getAccountNonce(accAddr common.Address, pending bool, height int64, logger log.Logger) (uint64, error) {
|
||||||
queryClient := authtypes.NewQueryClient(b.clientCtx)
|
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 {
|
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
|
return 0, err
|
||||||
}
|
}
|
||||||
var acc authtypes.AccountI
|
var acc authtypes.AccountI
|
||||||
@ -260,6 +270,22 @@ func GetLogsFromBlockResults(blockRes *tmrpctypes.ResultBlockResults) ([][]*etht
|
|||||||
|
|
||||||
blockLogs = append(blockLogs, logs...)
|
blockLogs = append(blockLogs, logs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return blockLogs, nil
|
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),
|
||||||
uint64(0),
|
uint64(0),
|
||||||
nil,
|
nil,
|
||||||
|
e.backend.ChainConfig().ChainID,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -292,12 +292,9 @@ func (api *PublicFilterAPI) NewBlockFilter() rpc.ID {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
baseFee := types.BaseFeeFromEvents(data.ResultBeginBlock.Events)
|
|
||||||
|
|
||||||
header := types.EthHeaderFromTendermint(data.Header, ethtypes.Bloom{}, baseFee)
|
|
||||||
api.filtersMu.Lock()
|
api.filtersMu.Lock()
|
||||||
if f, found := api.filters[headerSub.ID()]; found {
|
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()
|
api.filtersMu.Unlock()
|
||||||
case <-errCh:
|
case <-errCh:
|
||||||
|
@ -33,6 +33,7 @@ const (
|
|||||||
BlockParamEarliest = "earliest"
|
BlockParamEarliest = "earliest"
|
||||||
BlockParamLatest = "latest"
|
BlockParamLatest = "latest"
|
||||||
BlockParamFinalized = "finalized"
|
BlockParamFinalized = "finalized"
|
||||||
|
BlockParamSafe = "safe"
|
||||||
BlockParamPending = "pending"
|
BlockParamPending = "pending"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -73,7 +74,7 @@ func (bn *BlockNumber) UnmarshalJSON(data []byte) error {
|
|||||||
case BlockParamEarliest:
|
case BlockParamEarliest:
|
||||||
*bn = EthEarliestBlockNumber
|
*bn = EthEarliestBlockNumber
|
||||||
return nil
|
return nil
|
||||||
case BlockParamLatest, BlockParamFinalized:
|
case BlockParamLatest, BlockParamFinalized, BlockParamSafe:
|
||||||
*bn = EthLatestBlockNumber
|
*bn = EthLatestBlockNumber
|
||||||
return nil
|
return nil
|
||||||
case BlockParamPending:
|
case BlockParamPending:
|
||||||
@ -159,7 +160,7 @@ func (bnh *BlockNumberOrHash) decodeFromString(input string) error {
|
|||||||
case BlockParamEarliest:
|
case BlockParamEarliest:
|
||||||
bn := EthEarliestBlockNumber
|
bn := EthEarliestBlockNumber
|
||||||
bnh.BlockNumber = &bn
|
bnh.BlockNumber = &bn
|
||||||
case BlockParamLatest:
|
case BlockParamLatest, BlockParamFinalized:
|
||||||
bn := EthLatestBlockNumber
|
bn := EthLatestBlockNumber
|
||||||
bnh.BlockNumber = &bn
|
bnh.BlockNumber = &bn
|
||||||
case BlockParamPending:
|
case BlockParamPending:
|
||||||
|
@ -88,7 +88,7 @@ func TestUnmarshalBlockNumberOrHash(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
fmt.Sprintf("Case %s", tc.msg)
|
fmt.Printf("Case %s", tc.msg)
|
||||||
// reset input
|
// reset input
|
||||||
bnh = new(BlockNumberOrHash)
|
bnh = new(BlockNumberOrHash)
|
||||||
err := bnh.UnmarshalJSON(tc.input)
|
err := bnh.UnmarshalJSON(tc.input)
|
||||||
|
@ -10,8 +10,9 @@ import (
|
|||||||
abci "github.com/tendermint/tendermint/abci/types"
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
tmtypes "github.com/tendermint/tendermint/types"
|
tmtypes "github.com/tendermint/tendermint/types"
|
||||||
|
|
||||||
|
errorsmod "cosmossdk.io/errors"
|
||||||
"github.com/cosmos/cosmos-sdk/client"
|
"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"
|
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||||
feemarkettypes "github.com/evmos/ethermint/x/feemarket/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) {
|
func RawTxToEthTx(clientCtx client.Context, txBz tmtypes.Tx) ([]*evmtypes.MsgEthereumTx, error) {
|
||||||
tx, err := clientCtx.TxConfig.TxDecoder()(txBz)
|
tx, err := clientCtx.TxConfig.TxDecoder()(txBz)
|
||||||
if err != nil {
|
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()))
|
ethTxs := make([]*evmtypes.MsgEthereumTx, len(tx.GetMsgs()))
|
||||||
@ -144,15 +145,17 @@ func NewTransactionFromMsg(
|
|||||||
blockHash common.Hash,
|
blockHash common.Hash,
|
||||||
blockNumber, index uint64,
|
blockNumber, index uint64,
|
||||||
baseFee *big.Int,
|
baseFee *big.Int,
|
||||||
|
chainID *big.Int,
|
||||||
) (*RPCTransaction, error) {
|
) (*RPCTransaction, error) {
|
||||||
tx := msg.AsTransaction()
|
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
|
// NewTransactionFromData returns a transaction that will serialize to the RPC
|
||||||
// representation, with the given location metadata set (if available).
|
// representation, with the given location metadata set (if available).
|
||||||
func NewRPCTransaction(
|
func NewRPCTransaction(
|
||||||
tx *ethtypes.Transaction, blockHash common.Hash, blockNumber, index uint64, baseFee *big.Int,
|
tx *ethtypes.Transaction, blockHash common.Hash, blockNumber, index uint64, baseFee *big.Int,
|
||||||
|
chainID *big.Int,
|
||||||
) (*RPCTransaction, error) {
|
) (*RPCTransaction, error) {
|
||||||
// Determine the signer. For replay-protected transactions, use the most permissive
|
// Determine the signer. For replay-protected transactions, use the most permissive
|
||||||
// signer, because we assume that signers are backwards-compatible with old
|
// signer, because we assume that signers are backwards-compatible with old
|
||||||
@ -179,6 +182,7 @@ func NewRPCTransaction(
|
|||||||
V: (*hexutil.Big)(v),
|
V: (*hexutil.Big)(v),
|
||||||
R: (*hexutil.Big)(r),
|
R: (*hexutil.Big)(r),
|
||||||
S: (*hexutil.Big)(s),
|
S: (*hexutil.Big)(s),
|
||||||
|
ChainID: (*hexutil.Big)(chainID),
|
||||||
}
|
}
|
||||||
if blockHash != (common.Hash{}) {
|
if blockHash != (common.Hash{}) {
|
||||||
result.BlockHash = &blockHash
|
result.BlockHash = &blockHash
|
||||||
|
@ -65,12 +65,15 @@ fi
|
|||||||
echo "compiling ethermint"
|
echo "compiling ethermint"
|
||||||
make build
|
make build
|
||||||
|
|
||||||
|
|
||||||
# PID array declaration
|
# PID array declaration
|
||||||
arr=()
|
arr=()
|
||||||
|
|
||||||
init_func() {
|
init_func() {
|
||||||
"$PWD"/build/ethermintd keys add $KEY"$i" --keyring-backend test --home "$DATA_DIR$i" --no-backup --algo "eth_secp256k1"
|
"$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"
|
"$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 add-genesis-account \
|
||||||
"$("$PWD"/build/ethermintd keys show "$KEY$i" --keyring-backend test -a --home "$DATA_DIR$i")" 1000000000000000000aphoton,1000000000000000000stake \
|
"$("$PWD"/build/ethermintd keys show "$KEY$i" --keyring-backend test -a --home "$DATA_DIR$i")" 1000000000000000000aphoton,1000000000000000000stake \
|
||||||
--keyring-backend test --home "$DATA_DIR$i"
|
--keyring-backend test --home "$DATA_DIR$i"
|
||||||
@ -141,17 +144,6 @@ echo "done sleeping"
|
|||||||
|
|
||||||
set +e
|
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
|
if [[ -z $TEST || $TEST == "rpc" || $TEST == "pending" ]]; then
|
||||||
time_out=300s
|
time_out=300s
|
||||||
if [[ $TEST == "pending" ]]; then
|
if [[ $TEST == "pending" ]]; then
|
||||||
@ -186,7 +178,7 @@ for i in "${arr[@]}"; do
|
|||||||
stop_func "$i"
|
stop_func "$i"
|
||||||
done
|
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
|
exit $TEST_FAIL
|
||||||
else
|
else
|
||||||
exit 0
|
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