diff --git a/.coderabbit.yaml b/.coderabbit.yaml index 381e9d9fc4..a4c78052a8 100644 --- a/.coderabbit.yaml +++ b/.coderabbit.yaml @@ -1,7 +1,7 @@ reviews: path_filters: - - "**/*.pb.go" - - "**/*.pb.gw.go" + - "!**/*.pb.go" + - "!**/*.pb.gw.go" path_instructions: - path: '**/*.go' instructions: >- diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fc58eb6c56..bc075e6447 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -100,77 +100,3 @@ jobs: if: always() shell: bash run: rm -rf * - - e2e-test: - runs-on: ubuntu-20.04 - timeout-minutes: 25 - steps: - - uses: actions/checkout@v4 - - - name: Set CPU Architecture - shell: bash - run: | - if [ "$(uname -m)" == "aarch64" ]; then - echo "CPU_ARCH=arm64" >> $GITHUB_ENV - elif [ "$(uname -m)" == "x86_64" ]; then - echo "CPU_ARCH=amd64" >> $GITHUB_ENV - else - echo "Unsupported architecture" >&2 - exit 1 - fi - - - name: Install Pipeline Dependencies - uses: ./.github/actions/install-dependencies - timeout-minutes: 8 - with: - cpu_architecture: ${{ env.CPU_ARCH }} - skip_python: "false" - skip_aws_cli: "true" - skip_docker_compose: "false" - - - run: | - echo "github.repository: ${{ github.repository }}" - echo "github.event.pull_request.head.repo.full_name: ${{ github.event.pull_request.head.repo.full_name }}" - - - name: Login to Docker Hub - uses: docker/login-action@v2 - if: github.event_name != 'pull_request' || github.repository == github.event.pull_request.head.repo.full_name - with: - username: ${{ secrets.DOCKER_HUB_USERNAME }} - password: ${{ secrets.DOCKER_HUB_READ_ONLY }} - - - name: Start Test - run: make start-e2e-test - - # use docker logs -f rather than docker attach to make sure we get the initial logs - - name: Watch Test - run: | - container_id=$(docker ps --filter "ancestor=orchestrator:latest" --format "{{.ID}}") - docker logs -f "${container_id}" & - exit $(docker wait "${container_id}") - - - name: Full Log Dump On Failure - if: failure() - run: | - make stop-localnet - - - name: Notify Slack on Failure - if: failure() && github.event_name == 'push' && github.ref == 'refs/heads/develop' - uses: 8398a7/action-slack@v3 - with: - status: ${{ job.status }} - fields: repo,message,commit,author,action,eventName,ref,workflow,job,took - env: - SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_CI_ALERTS }} - - - name: Stop Private Network - if: always() - run: | - make stop-localnet - - - name: Clean Up Workspace - if: always() - shell: bash - run: sudo rm -rf * - - diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml new file mode 100644 index 0000000000..a63047890a --- /dev/null +++ b/.github/workflows/e2e.yml @@ -0,0 +1,90 @@ +name: e2e + +on: + push: + branches: + - develop + pull_request: + branches: + - "*" + merge_group: + workflow_dispatch: + schedule: + # run at 6AM UTC Daily + # 6AM UTC -> 11PM PT + - cron: "0 6 * * *" + +concurrency: + group: e2e-${{ github.head_ref || github.sha }} + cancel-in-progress: true + +jobs: + matrix-conditionals: + runs-on: ubuntu-22.04 + env: + GH_TOKEN: ${{ github.token }} + outputs: + UPGRADE_TESTS: ${{ steps.matrix-conditionals.outputs.UPGRADE_TESTS }} + UPGRADE_LIGHT_TESTS: ${{ steps.matrix-conditionals.outputs.UPGRADE_LIGHT_TESTS }} + ADMIN_TESTS: ${{ steps.matrix-conditionals.outputs.ADMIN_TESTS }} + steps: + # use cli rather than event context to avoid race conditions (label added after push) + - id: matrix-conditionals + run: | + if [[ ${{ github.event_name }} == 'pull_request' ]]; then + labels=$(gh pr view -R ${{github.repository}} ${{github.event.pull_request.number}} --json labels -q '.labels[].name') + if [[ "$labels" == *"UPGRADE_TESTS"* ]]; then + echo "UPGRADE_TESTS=true" >> $GITHUB_OUTPUT + fi + + if [[ "$labels" == *"UPGRADE_LIGHT_TESTS"* ]]; then + echo "UPGRADE_LIGHT_TESTS=true" >> $GITHUB_OUTPUT + fi + + if [[ "$labels" == *"ADMIN_TESTS"* ]]; then + echo "ADMIN_TESTS=true" >> $GITHUB_OUTPUT + fi + elif [[ ${{ github.event_name }} == 'schedule' ]]; then + echo "UPGRADE_TESTS=true" >> $GITHUB_OUTPUT + echo "UPGRADE_LIGHT_TESTS=true" >> $GITHUB_OUTPUT + echo "ADMIN_TESTS=true" >> $GITHUB_OUTPUT + fi + + e2e: + needs: matrix-conditionals + strategy: + fail-fast: false + matrix: + include: + - make-target: "start-e2e-test" + runs-on: ubuntu-20.04 + run: true + - make-target: "start-upgrade-test" + runs-on: ubuntu-20.04 + run: ${{ needs.matrix-conditionals.outputs.UPGRADE_TESTS == 'true' }} + - make-target: "start-upgrade-test-light" + runs-on: ubuntu-20.04 + run: ${{ needs.matrix-conditionals.outputs.UPGRADE_LIGHT_TESTS == 'true' }} + - make-target: "start-e2e-admin-test" + runs-on: ubuntu-20.04 + run: ${{ needs.matrix-conditionals.outputs.ADMIN_TESTS == 'true' }} + name: ${{ matrix.make-target }} + uses: ./.github/workflows/reusable-e2e.yml + with: + make-target: ${{ matrix.make-target }} + runs-on: ${{ matrix.runs-on}} + run: ${{ matrix.run }} + secrets: inherit + # this allows you to set a required status check + e2e-ok: + runs-on: ubuntu-22.04 + needs: e2e + if: always() + steps: + - run: | + result="${{ needs.e2e.result }}" + if [[ $result == "success" || $result == "skipped" ]]; then + exit 0 + else + exit 1 + fi diff --git a/.github/workflows/execute_advanced_tests.yaml b/.github/workflows/execute_advanced_tests.yaml index 77d6a2b6bd..e8a4683812 100644 --- a/.github/workflows/execute_advanced_tests.yaml +++ b/.github/workflows/execute_advanced_tests.yaml @@ -3,14 +3,6 @@ name: "TESTING:ADVANCED:E2E" on: workflow_dispatch: inputs: - e2e-admin-tests: - type: boolean - required: false - default: false - e2e-upgrade-test: - type: boolean - required: false - default: false e2e-stateful-upgrade-test: type: boolean required: false @@ -19,10 +11,6 @@ on: type: boolean required: false default: false - e2e-upgrade-test-light: - type: boolean - required: false - default: false e2e-stateful-data-test: type: boolean required: false @@ -37,69 +25,6 @@ on: - cron: "0 6 * * *" jobs: - e2e-admin-tests: - if: ${{ github.event.inputs.e2e-admin-tests == 'true' || github.event_name == 'schedule' }} - runs-on: buildjet-4vcpu-ubuntu-2204 - timeout-minutes: 120 - steps: - - name: "Checkout Code" - uses: actions/checkout@v4 - - - name: Start Test - run: make start-e2e-admin-test - - # use docker logs -f rather than docker attach to make sure we get the initial logs - - name: Watch Test - run: | - container_id=$(docker ps --filter "ancestor=orchestrator:latest" --format "{{.ID}}") - docker logs -f "${container_id}" & - exit $(docker wait "${container_id}") - - - name: Full Log Dump On Failure - if: failure() - run: | - make stop-localnet - - - name: Notify Slack on Failure - if: failure() && github.event_name == 'schedule' - uses: 8398a7/action-slack@v3 - with: - status: ${{ job.status }} - fields: repo,message,commit,author,action,eventName,ref,workflow,job,took - env: - SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_CI_ALERTS }} - - e2e-upgrade-test: - if: ${{ github.event.inputs.e2e-upgrade-test == 'true' || github.event_name == 'schedule' }} - runs-on: buildjet-16vcpu-ubuntu-2204 - timeout-minutes: 120 - steps: - - name: "Checkout Code" - uses: actions/checkout@v4 - - - name: Start Test - run: make start-upgrade-test - - - name: Watch Test - run: | - container_id=$(docker ps --filter "ancestor=orchestrator:latest" --format "{{.ID}}") - docker logs -f "${container_id}" & - exit $(docker wait "${container_id}") - - - name: Full Log Dump On Failure - if: failure() - run: | - make stop-localnet - - - name: Notify Slack on Failure - if: failure() && github.event_name == 'schedule' - uses: 8398a7/action-slack@v3 - with: - status: ${{ job.status }} - fields: repo,message,commit,author,action,eventName,ref,workflow,job,took - env: - SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_CI_ALERTS }} - e2e-stateful-upgrade-test: if: ${{ github.event.inputs.e2e-stateful-upgrade-test == 'true' || github.event_name == 'schedule' }} runs-on: buildjet-16vcpu-ubuntu-2204 @@ -131,37 +56,6 @@ jobs: env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_CI_ALERTS }} - e2e-upgrade-test-light: - if: ${{ github.event.inputs.e2e-upgrade-test-light == 'true' }} - runs-on: buildjet-4vcpu-ubuntu-2204 - timeout-minutes: 120 - steps: - - name: "Checkout Code" - uses: actions/checkout@v4 - - - name: Start Test - run: make start-upgrade-test-light - - - name: Watch Test - run: | - container_id=$(docker ps --filter "ancestor=orchestrator:latest" --format "{{.ID}}") - docker logs -f "${container_id}" & - exit $(docker wait "${container_id}") - - - name: Full Log Dump On Failure - if: failure() - run: | - make stop-localnet - - - name: Notify Slack on Failure - if: failure() && github.event_name == 'schedule' - uses: 8398a7/action-slack@v3 - with: - status: ${{ job.status }} - fields: repo,message,commit,author,action,eventName,ref,workflow,job,took - env: - SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_CI_ALERTS }} - e2e-performance-test: if: ${{ github.event.inputs.e2e-performance-test == 'true' }} runs-on: buildjet-4vcpu-ubuntu-2204 diff --git a/.github/workflows/reusable-e2e.yml b/.github/workflows/reusable-e2e.yml new file mode 100644 index 0000000000..2407598141 --- /dev/null +++ b/.github/workflows/reusable-e2e.yml @@ -0,0 +1,120 @@ +name: Reusable E2E Testing Workflow +on: + workflow_call: + inputs: + make-target: + description: 'Makefile target to execute in the Start Test step' + required: true + type: string + timeout-minutes: + description: 'The maximum number of minutes the job can run' + type: number + default: 25 + run: + description: 'Whether to run the job or not' + required: true + type: boolean + runs-on: + description: 'The runner to use for the job' + required: true + type: string + default: 'ubuntu-20.04' + +jobs: + e2e: + if: ${{ inputs.run }} + runs-on: ${{ inputs.runs-on }} + timeout-minutes: ${{ inputs.timeout-minutes }} + steps: + - uses: actions/checkout@v4 + + # configure docker to use the containerd snapshotter + # so that we can use the buildkit cache + - uses: depot/use-containerd-snapshotter-action@v1 + + - name: Login to Docker Hub registry + uses: docker/login-action@v3 + if: (github.event_name == 'push' && github.repository == 'zeta-chain/node') || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == 'zeta-chain/node') + with: + username: ${{ secrets.DOCKER_HUB_USERNAME }} + password: ${{ secrets.DOCKER_HUB_READ_ONLY }} + + - name: Login to github docker registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Restore go cache + uses: actions/cache@v4 + id: restore-go-cache + with: + path: | + go-cache + key: cache-${{ hashFiles('go.sum') }} + + - name: Inject go cache into docker + uses: reproducible-containers/buildkit-cache-dance@v3.1.2 + with: + cache-map: | + { + "go-cache": "/root/.cache/go-build" + } + skip-extraction: ${{ steps.restore-go-cache.outputs.cache-hit || github.event_name != 'push' }} + + # build zetanode with cache options + - name: Build zetanode for cache + uses: docker/build-push-action@v6 + env: + CACHE_FROM_CONFIG: "type=registry,ref=ghcr.io/${{ github.repository }}:buildcache" + CACHE_TO_CONFIG: "type=registry,ref=ghcr.io/${{ github.repository }}:buildcache,mode=max" + with: + context: . + file: ./Dockerfile-localnet + push: false + tags: zetanode:latest + cache-from: ${{ env.CACHE_FROM_CONFIG }} + cache-to: ${{ github.event_name == 'push' && env.CACHE_TO_CONFIG || '' }} + target: latest-runtime + + - name: Start Test + run: make ${{ inputs.make-target }} + + # use docker logs -f rather than docker attach to make sure we get the initial logs + - name: Watch Test + run: | + container_id=$(docker ps --filter "ancestor=orchestrator:latest" --format "{{.ID}}") + docker logs -f "${container_id}" & + exit $(docker wait "${container_id}") + + - name: Full Log Dump On Failure + if: failure() + run: | + cd contrib/localnet && docker compose --profile all logs --timestamps > /tmp/logs.txt + + - name: Upload Logs On Failure + if: failure() + uses: actions/upload-artifact@v4 + with: + name: ${{ inputs.make-target }}-docker-logs + path: /tmp/logs.txt + + - name: Notify Slack on Failure + if: failure() && (github.event_name == 'push' && github.ref == 'refs/heads/develop') || github.event_name == 'schedule' + uses: 8398a7/action-slack@v3 + with: + status: ${{ job.status }} + fields: repo,message,commit,author,action,eventName,ref,workflow,job,took + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_CI_ALERTS }} + + - name: Stop Private Network + if: always() + run: | + make stop-localnet + + - name: Clean Up Workspace + if: always() + shell: bash + run: sudo rm -rf * diff --git a/Dockerfile-localnet b/Dockerfile-localnet index 1ed82c6b98..f9ff74d48a 100644 --- a/Dockerfile-localnet +++ b/Dockerfile-localnet @@ -28,7 +28,7 @@ RUN go install cosmossdk.io/tools/cosmovisor/cmd/cosmovisor@v1.5.0 FROM golang:1.20.14-bookworm AS base-runtime RUN apt update && \ - apt install -yq jq yq curl tmux python3 openssh-server iputils-ping iproute2 && \ + apt install -yq jq yq curl tmux python3 openssh-server iputils-ping iproute2 bind9-host && \ rm -rf /var/lib/apt/lists/* RUN ssh-keygen -A && \ diff --git a/Makefile b/Makefile index 509cb40fd7..177f064722 100644 --- a/Makefile +++ b/Makefile @@ -28,11 +28,7 @@ export DOCKER_BUILDKIT := 1 # parameters for localnet docker compose files # set defaults to empty to prevent docker warning -export LOCALNET_MODE export E2E_ARGS := $(E2E_ARGS) -export UPGRADE_HEIGHT -export ZETACORED_IMPORT_GENESIS_DATA -export ZETACORED_START_PERIOD := 30s clean: clean-binaries clean-dir clean-test-dir clean-coverage @@ -215,8 +211,9 @@ start-localnet-skip-build: export LOCALNET_MODE=setup-only && \ cd contrib/localnet/ && $(DOCKER) compose -f docker-compose.yml up -d +# stop-localnet should include all profiles so other containers are also removed stop-localnet: - cd contrib/localnet/ && $(DOCKER) compose down --remove-orphans + cd contrib/localnet/ && $(DOCKER) compose --profile all down --remove-orphans ############################################################################### ### E2E tests ### @@ -240,7 +237,7 @@ start-e2e-test: zetanode start-e2e-admin-test: zetanode @echo "--> Starting e2e admin test" export E2E_ARGS="--skip-regular --test-admin" && \ - cd contrib/localnet/ && $(DOCKER) compose -f docker-compose.yml -f docker-compose-additionalevm.yml up -d + cd contrib/localnet/ && $(DOCKER) compose --profile eth2 -f docker-compose.yml up -d start-e2e-performance-test: zetanode @echo "--> Starting e2e performance test" @@ -255,7 +252,7 @@ start-e2e-import-mainnet-test: zetanode start-stress-test: zetanode @echo "--> Starting stress test" - cd contrib/localnet/ && $(DOCKER) compose -f docker-compose.yml -f docker-compose-stress.yml up -d + cd contrib/localnet/ && $(DOCKER) compose --profile stress -f docker-compose.yml up -d ############################################################################### ### Upgrade Tests ### @@ -272,13 +269,13 @@ start-upgrade-test: zetanode-upgrade @echo "--> Starting upgrade test" export LOCALNET_MODE=upgrade && \ export UPGRADE_HEIGHT=225 && \ - cd contrib/localnet/ && $(DOCKER) compose -f docker-compose.yml -f docker-compose-upgrade.yml up -d + cd contrib/localnet/ && $(DOCKER) compose --profile upgrade -f docker-compose.yml -f docker-compose-upgrade.yml up -d start-upgrade-test-light: zetanode-upgrade @echo "--> Starting light upgrade test (no ZetaChain state populating before upgrade)" export LOCALNET_MODE=upgrade && \ export UPGRADE_HEIGHT=90 && \ - cd contrib/localnet/ && $(DOCKER) compose -f docker-compose.yml -f docker-compose-upgrade.yml up -d + cd contrib/localnet/ && $(DOCKER) compose --profile upgrade -f docker-compose.yml -f docker-compose-upgrade.yml up -d start-upgrade-import-mainnet-test: zetanode-upgrade @echo "--> Starting import-data upgrade test" @@ -286,7 +283,8 @@ start-upgrade-import-mainnet-test: zetanode-upgrade export ZETACORED_IMPORT_GENESIS_DATA=true && \ export ZETACORED_START_PERIOD=15m && \ export UPGRADE_HEIGHT=225 && \ - cd contrib/localnet/ && ./scripts/import-data.sh mainnet && $(DOCKER) compose -f docker-compose.yml -f docker-compose-upgrade.yml up -d + cd contrib/localnet/ && ./scripts/import-data.sh mainnet && $(DOCKER) compose --profile upgrade -f docker-compose.yml -f docker-compose-upgrade.yml up -d + ############################################################################### ### Monitoring ### ############################################################################### diff --git a/changelog.md b/changelog.md index 7efe04a213..c45bf10825 100644 --- a/changelog.md +++ b/changelog.md @@ -30,6 +30,7 @@ * [2339](https://github.com/zeta-chain/node/pull/2339) - add binaries related question to syncing issue form * [2366](https://github.com/zeta-chain/node/pull/2366) - add migration script for adding authorizations table * [2372](https://github.com/zeta-chain/node/pull/2372) - add queries for tss fund migration info +* [2416g](https://github.com/zeta-chain/node/pull/2416) - add Solana chain information ### Refactor @@ -55,6 +56,7 @@ * [2357](https://github.com/zeta-chain/node/pull/2357) - integrate base Signer structure into EVM/Bitcoin Signer * [2359](https://github.com/zeta-chain/node/pull/2359) - integrate base Observer structure into EVM/Bitcoin Observer * [2375](https://github.com/zeta-chain/node/pull/2375) - improve & speedup code formatting +* [2380](https://github.com/zeta-chain/node/pull/2380) - use `ChainInfo` in `authority` to allow dynamically support new chains * [2395](https://github.com/zeta-chain/node/pull/2395) - converge AppContext with ZetaCoreContext in zetaclient ### Tests diff --git a/cmd/zetaclientd/debug.go b/cmd/zetaclientd/debug.go index afd56d7904..c6f05d4bf9 100644 --- a/cmd/zetaclientd/debug.go +++ b/cmd/zetaclientd/debug.go @@ -85,20 +85,20 @@ func debugCmd(_ *cobra.Command, args []string) error { if err != nil { return err } - chain := chains.GetChainFromChainID(chainID) - if chain == nil { + chain, found := chains.GetChainFromChainID(chainID, appContext.GetAdditionalChains()) + if !found { return fmt.Errorf("invalid chain id") } // get ballot identifier according to the chain type - if chains.IsEVMChain(chain.ChainId) { + if chains.IsEVMChain(chain.ChainId, appContext.GetAdditionalChains()) { evmObserver := evmobserver.Observer{} evmObserver.WithZetacoreClient(client) var ethRPC *ethrpc.EthRPC var client *ethclient.Client coinType := coin.CoinType_Cmd - for chain, evmConfig := range cfg.GetAllEVMConfigs() { - if chainID == chain { + for chainIDFromConfig, evmConfig := range cfg.GetAllEVMConfigs() { + if chainIDFromConfig == chainID { ethRPC = ethrpc.NewEthRPC(evmConfig.Endpoint) client, err = ethclient.Dial(evmConfig.Endpoint) if err != nil { @@ -106,7 +106,7 @@ func debugCmd(_ *cobra.Command, args []string) error { } evmObserver.WithEvmClient(client) evmObserver.WithEvmJSONRPC(ethRPC) - evmObserver.WithChain(*chains.GetChainFromChainID(chainID)) + evmObserver.WithChain(chain) } } hash := ethcommon.HexToHash(inboundHash) @@ -167,10 +167,10 @@ func debugCmd(_ *cobra.Command, args []string) error { fmt.Println("CoinType not detected") } fmt.Println("CoinType : ", coinType) - } else if chains.IsBitcoinChain(chain.ChainId) { + } else if chains.IsBitcoinChain(chain.ChainId, appContext.GetAdditionalChains()) { btcObserver := btcobserver.Observer{} btcObserver.WithZetacoreClient(client) - btcObserver.WithChain(*chains.GetChainFromChainID(chainID)) + btcObserver.WithChain(chain) connCfg := &rpcclient.ConnConfig{ Host: cfg.BitcoinConfig.RPCHost, User: cfg.BitcoinConfig.RPCUsername, diff --git a/cmd/zetaclientd/keygen_tss.go b/cmd/zetaclientd/keygen_tss.go index 349d5b15e8..ee66920b39 100644 --- a/cmd/zetaclientd/keygen_tss.go +++ b/cmd/zetaclientd/keygen_tss.go @@ -22,8 +22,8 @@ import ( "github.com/zeta-chain/zetacore/zetaclient/zetacore" ) -// GenerateTss waits for the keygen block height to arrive and generates a new TSS -func GenerateTss( +// GenerateTSS waits for the keygen block height to arrive and generates a new TSS +func GenerateTSS( appContext *context.AppContext, logger zerolog.Logger, client *zetacore.Client, diff --git a/cmd/zetaclientd/start.go b/cmd/zetaclientd/start.go index 354d866888..be26719441 100644 --- a/cmd/zetaclientd/start.go +++ b/cmd/zetaclientd/start.go @@ -207,7 +207,7 @@ func start(_ *cobra.Command, _ []string) error { startLogger.Error().Err(err).Msg("GetTssHistory error") } - tss, err := GenerateTss( + tss, err := GenerateTSS( appContext, masterLogger, zetacoreClient, diff --git a/contrib/localnet/docker-compose-additionalevm.yml b/contrib/localnet/docker-compose-additionalevm.yml deleted file mode 100644 index 208a8e30e9..0000000000 --- a/contrib/localnet/docker-compose-additionalevm.yml +++ /dev/null @@ -1,24 +0,0 @@ -# This docker-compose file overrides the orchestrator service to specify the flag to test the admin functions -# and skip the regular tests -# it also adds another local Ethereum network to test EVM chain migration and use the additional-evm flag - -services: - eth2: - build: - context: ./anvil - container_name: eth2 - hostname: eth2 - platform: linux/amd64 - ports: - - "8546:8545" - networks: - mynetwork: - ipv4_address: 172.20.0.102 - - zetaclient0: - environment: - - ADDITIONAL_EVM=true - - zetaclient1: - environment: - - ADDITIONAL_EVM=true diff --git a/contrib/localnet/docker-compose-stress.yml b/contrib/localnet/docker-compose-stress.yml deleted file mode 100644 index fb11f01b5c..0000000000 --- a/contrib/localnet/docker-compose-stress.yml +++ /dev/null @@ -1,73 +0,0 @@ -# This docker-compose redefine the services: -# - ZetaChain with 4 nodes to test performance -# - ZetaChain observer set with 4 clients to test performance - -services: - zetacore0: - environment: - - ZETACORED_REPLICAS=4 - - zetacore1: - environment: - - ZETACORED_REPLICAS=4 - - zetacore2: - image: zetanode:latest - container_name: zetacore2 - hostname: zetacore2 - networks: - mynetwork: - ipv4_address: 172.20.0.13 - entrypoint: [ "/root/start-zetacored.sh", "4" ] - environment: - - HOTKEY_BACKEND=file - - HOTKEY_PASSWORD=password # test purposes only - - ZETACORED_REPLICAS=4 - - zetacore3: - image: zetanode:latest - container_name: zetacore3 - build: - context: ../../. - dockerfile: Dockerfile-localnet - hostname: zetacore3 - networks: - mynetwork: - ipv4_address: 172.20.0.14 - entrypoint: [ "/root/start-zetacored.sh", "4" ] - environment: - - HOTKEY_BACKEND=file - - HOTKEY_PASSWORD=password # test purposes only - - ZETACORED_REPLICAS=4 - - zetaclient2: - image: zetanode:latest - container_name: zetaclient2 - hostname: zetaclient2 - networks: - mynetwork: - ipv4_address: 172.20.0.23 - entrypoint: /root/start-zetaclientd.sh - environment: - - ETHDEV_ENDPOINT=http://eth:8545 - - HOTKEY_BACKEND=file - - HOTKEY_PASSWORD=password # test purposes only - volumes: - - ssh:/root/.ssh - - preparams:/root/preparams - - zetaclient3: - image: zetanode:latest - container_name: zetaclient3 - hostname: zetaclient3 - networks: - mynetwork: - ipv4_address: 172.20.0.24 - entrypoint: /root/start-zetaclientd.sh - environment: - - ETHDEV_ENDPOINT=http://eth:8545 - - HOTKEY_BACKEND=file - - HOTKEY_PASSWORD=password # test purposes only - volumes: - - ssh:/root/.ssh - - preparams:/root/preparams diff --git a/contrib/localnet/docker-compose-upgrade.yml b/contrib/localnet/docker-compose-upgrade.yml index badd7db8e5..7bcfb9a4fa 100644 --- a/contrib/localnet/docker-compose-upgrade.yml +++ b/contrib/localnet/docker-compose-upgrade.yml @@ -1,8 +1,5 @@ version: "3" -# This docker-compose redefine the services: -# - ZetaChain with 2 nodes (zetacore0, zetacore1) using the upgrade option for cosmovisor -# - ZetaChain observer set with 2 clients (zetaclient0, zetaclient1) using the background option -# - Orchestrator with upgrade option +# This docker-compose updates the services to use the old version of the zetanode image services: zetacore0: @@ -11,36 +8,20 @@ services: zetacore1: image: zetanode:old + zetacore2: + image: zetanode:old + + zetacore3: + image: zetanode:old + zetaclient0: image: zetanode:old zetaclient1: image: zetanode:old - upgrade-host: - image: zetanode:latest - container_name: upgrade-host - hostname: upgrade-host - entrypoint: ["/root/start-upgrade-host.sh"] - networks: - mynetwork: - ipv4_address: 172.20.0.250 - volumes: - - ssh:/root/.ssh - - upgrade-orchestrator: - # must run from old node for api compatibility - image: zetanode:old - container_name: upgrade-orchestrator - hostname: upgrade-orchestrator - entrypoint: ["/root/start-upgrade-orchestrator.sh"] - networks: - mynetwork: - ipv4_address: 172.20.0.251 - depends_on: - - zetacore0 - - upgrade-host - environment: - - UPGRADE_HEIGHT=${UPGRADE_HEIGHT} - volumes: - - ssh:/root/.ssh + zetaclient2: + image: zetanode:old + + zetaclient3: + image: zetanode:old diff --git a/contrib/localnet/docker-compose.yml b/contrib/localnet/docker-compose.yml index e73a946c04..880b6de8ad 100644 --- a/contrib/localnet/docker-compose.yml +++ b/contrib/localnet/docker-compose.yml @@ -1,11 +1,14 @@ # This docker-compose file configures the localnet environment # it contains the following services: -# - ZetaChain with 2 nodes (zetacore0, zetacore1) -# - A observer set with 2 clients (zetaclient0, zetaclient1) +# - ZetaChain with 2 nodes (zetacore0, zetacore1). When profile set to stress, 4 nodes will be created. +# - A observer set with 2 clients (zetaclient0, zetaclient1). When profile set to stress, 4 clients will be created. # - An Ethereum node (eth) +# - A secondary optional Ethereum node (eth2) enabled when profile is set to eth2 # - A Bitcoin node (bitcoin) # - A Rosetta API (rosetta) # - An orchestrator to manage interaction with the localnet (orchestrator) +# - An upgrade host to serve binaries for the upgrade tests (upgrade-host). Only enabled when profile is set to upgrade. +# - An upgrade orchestrator to send the upgrade governance proposal (upgrade-orchestrator). Only enabled when profile is set to upgrade. networks: mynetwork: @@ -47,7 +50,7 @@ services: interval: 30s timeout: 10s retries: 3 - start_period: ${ZETACORED_START_PERIOD} + start_period: ${ZETACORED_START_PERIOD-30s} start_interval: 1s networks: mynetwork: @@ -56,8 +59,7 @@ services: environment: - HOTKEY_BACKEND=file - HOTKEY_PASSWORD=password # test purposes only - - ZETACORED_REPLICAS=2 - - ZETACORED_IMPORT_GENESIS_DATA=${ZETACORED_IMPORT_GENESIS_DATA} + - ZETACORED_IMPORT_GENESIS_DATA=${ZETACORED_IMPORT_GENESIS_DATA-} volumes: - ssh:/root/.ssh - ~/.zetacored/genesis_data:/root/genesis_data @@ -73,7 +75,40 @@ services: environment: - HOTKEY_BACKEND=file - HOTKEY_PASSWORD=password # test purposes only - - ZETACORED_REPLICAS=2 + volumes: + - ssh:/root/.ssh + + zetacore2: + image: zetanode:latest + container_name: zetacore2 + hostname: zetacore2 + profiles: + - stress + - all + networks: + mynetwork: + ipv4_address: 172.20.0.13 + entrypoint: [ "/root/start-zetacored.sh", "4" ] + environment: + - HOTKEY_BACKEND=file + - HOTKEY_PASSWORD=password # test purposes only + volumes: + - ssh:/root/.ssh + + zetacore3: + image: zetanode:latest + container_name: zetacore3 + hostname: zetacore3 + profiles: + - stress + - all + networks: + mynetwork: + ipv4_address: 172.20.0.14 + entrypoint: [ "/root/start-zetacored.sh", "4" ] + environment: + - HOTKEY_BACKEND=file + - HOTKEY_PASSWORD=password # test purposes only volumes: - ssh:/root/.ssh @@ -109,6 +144,42 @@ services: - ssh:/root/.ssh - preparams:/root/preparams + zetaclient2: + image: zetanode:latest + container_name: zetaclient2 + hostname: zetaclient2 + profiles: + - stress + - all + networks: + mynetwork: + ipv4_address: 172.20.0.23 + entrypoint: /root/start-zetaclientd.sh + environment: + - HOTKEY_BACKEND=file + - HOTKEY_PASSWORD=password # test purposes only + volumes: + - ssh:/root/.ssh + - preparams:/root/preparams + + zetaclient3: + image: zetanode:latest + container_name: zetaclient3 + hostname: zetaclient3 + profiles: + - stress + - all + networks: + mynetwork: + ipv4_address: 172.20.0.24 + entrypoint: /root/start-zetaclientd.sh + environment: + - HOTKEY_BACKEND=file + - HOTKEY_PASSWORD=password # test purposes only + volumes: + - ssh:/root/.ssh + - preparams:/root/preparams + eth: image: ethereum/client-go:v1.10.26 container_name: eth @@ -120,6 +191,21 @@ services: ipv4_address: 172.20.0.100 entrypoint: ["geth", "--dev", "--http", "--http.addr", "172.20.0.100", "--http.vhosts", "*", "--http.api", "eth,web3,net", "--http.corsdomain", "https://remix.ethereum.org", "--dev.period", "2"] + eth2: + build: + context: ./anvil + container_name: eth2 + hostname: eth2 + profiles: + - eth2 + - all + platform: linux/amd64 + ports: + - "8546:8545" + networks: + mynetwork: + ipv4_address: 172.20.0.102 + bitcoin: image: ruimarinho/bitcoin-core:22 # version 23 is not working with btcd 0.22.0 due to change in createwallet rpc container_name: bitcoin @@ -152,11 +238,45 @@ services: ipv4_address: 172.20.0.2 entrypoint: ["/work/start-zetae2e.sh", "local"] environment: - - LOCALNET_MODE=${LOCALNET_MODE} - - E2E_ARGS=${E2E_ARGS} - - UPGRADE_HEIGHT=${UPGRADE_HEIGHT} + - LOCALNET_MODE=${LOCALNET_MODE-} + - E2E_ARGS=${E2E_ARGS-} + - UPGRADE_HEIGHT=${UPGRADE_HEIGHT-} + volumes: + - ssh:/root/.ssh + + upgrade-host: + image: zetanode:latest + container_name: upgrade-host + hostname: upgrade-host + profiles: + - upgrade + - all + entrypoint: ["/root/start-upgrade-host.sh"] + networks: + mynetwork: + ipv4_address: 172.20.0.250 + volumes: + - ssh:/root/.ssh + + upgrade-orchestrator: + # must run from old node for api compatibility + image: zetanode:old + container_name: upgrade-orchestrator + hostname: upgrade-orchestrator + profiles: + - upgrade + - all + entrypoint: ["/root/start-upgrade-orchestrator.sh"] + networks: + mynetwork: + ipv4_address: 172.20.0.251 + depends_on: + - zetacore0 + - upgrade-host + environment: + - UPGRADE_HEIGHT=${UPGRADE_HEIGHT-} volumes: - ssh:/root/.ssh volumes: ssh: - preparams: \ No newline at end of file + preparams: diff --git a/contrib/localnet/scripts/start-zetaclientd.sh b/contrib/localnet/scripts/start-zetaclientd.sh index a849891275..fea6b69779 100755 --- a/contrib/localnet/scripts/start-zetaclientd.sh +++ b/contrib/localnet/scripts/start-zetaclientd.sh @@ -7,7 +7,6 @@ /usr/sbin/sshd HOSTNAME=$(hostname) -OPTION=$1 export ZETACLIENTD_SUPERVISOR_ENABLE_AUTO_DOWNLOAD=true # sepolia is used in chain migration tests, this functions set the sepolia endpoint in the zetaclient_config.json @@ -28,15 +27,12 @@ while [ ! -f ~/.ssh/authorized_keys ]; do sleep 1 done - - # need to wait for zetacore0 to be up while ! curl -s -o /dev/null zetacore0:26657/status ; do echo "Waiting for zetacore0 rpc" sleep 10 done - # read HOTKEY_BACKEND env var for hotkey keyring backend and set default to test BACKEND="test" if [ "$HOTKEY_BACKEND" == "file" ]; then @@ -60,10 +56,11 @@ then MYIP=$(/sbin/ip -o -4 addr list eth0 | awk '{print $4}' | cut -d/ -f1) zetaclientd init --zetacore-url zetacore0 --chain-id athens_101-1 --operator "$operatorAddress" --log-format=text --public-ip "$MYIP" --keyring-backend "$BACKEND" --pre-params "$PREPARAMS_PATH" - # check if the option is additional-evm + # if eth2 is enabled, set the endpoint in the zetaclient_config.json # in this case, the additional evm is represented with the sepolia chain, we set manually the eth2 endpoint to the sepolia chain (11155111 -> http://eth2:8545) # in /root/.zetacored/config/zetaclient_config.json - if [[ -n $ADDITIONAL_EVM ]]; then + if host eth2 ; then + echo "enabling additional evm (eth2)" set_sepolia_endpoint fi fi diff --git a/contrib/localnet/scripts/start-zetacored.sh b/contrib/localnet/scripts/start-zetacored.sh index aba9538c5e..64779d2a39 100755 --- a/contrib/localnet/scripts/start-zetacored.sh +++ b/contrib/localnet/scripts/start-zetacored.sh @@ -85,16 +85,6 @@ export CLIENT_SKIP_UPGRADE=true export CLIENT_START_PROCESS=false export UNSAFE_SKIP_BACKUP=true -# generate node list -START=1 -# shellcheck disable=SC2100 -END=$((ZETACORED_REPLICAS - 1)) -NODELIST=() -for i in $(eval echo "{$START..$END}") -do - NODELIST+=("zetacore$i") -done - echo "HOSTNAME: $HOSTNAME" # init ssh keys @@ -162,6 +152,21 @@ fi # Skip genesis if it has already been completed (marked by presence of ~/.zetacored/init_complete file) if [[ $HOSTNAME == "zetacore0" && ! -f ~/.zetacored/init_complete ]] then + ZETACORED_REPLICAS=2 + if host zetacore3 ; then + echo "zetacore3 exists, setting ZETACORED_REPLICAS to 4" + ZETACORED_REPLICAS=4 + fi + # generate node list + START=1 + # shellcheck disable=SC2100 + END=$((ZETACORED_REPLICAS - 1)) + NODELIST=() + for i in $(eval echo "{$START..$END}") + do + NODELIST+=("zetacore$i") + done + # Misc : Copying the keyring to the client nodes so that they can sign the transactions ssh zetaclient0 mkdir -p ~/.zetacored/keyring-test/ scp ~/.zetacored/keyring-test/* zetaclient0:~/.zetacored/keyring-test/ diff --git a/docs/openapi/openapi.swagger.yaml b/docs/openapi/openapi.swagger.yaml index 987feb13d4..a6ee4a79f3 100644 --- a/docs/openapi/openapi.swagger.yaml +++ b/docs/openapi/openapi.swagger.yaml @@ -56965,6 +56965,9 @@ definitions: - optimism_sepolia - base_mainnet - base_sepolia + - solana_mainnet + - solana_devnet + - solana_localnet default: empty title: ChainName represents the name of the chain chainsConsensus: @@ -56974,6 +56977,7 @@ definitions: - tendermint - bitcoin - op_stack + - solana_consensus default: ethereum title: |- Consensus represents the consensus algorithm used by the chain @@ -56989,6 +56993,7 @@ definitions: - bsc - optimism - base + - solana default: eth title: |- Network represents the network of the chain @@ -57022,6 +57027,7 @@ definitions: enum: - no_vm - evm + - svm default: no_vm title: |- Vm represents the virtual machine type of the chain to support smart @@ -57832,6 +57838,8 @@ definitions: type: string is_supported: type: boolean + gateway_address: + type: string observerChainParamsList: type: object properties: diff --git a/pkg/chains/chain.go b/pkg/chains/chain.go index 681e13a5ae..46ead5f9f2 100644 --- a/pkg/chains/chain.go +++ b/pkg/chains/chain.go @@ -5,15 +5,9 @@ import ( "strings" "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcutil" ethcommon "github.com/ethereum/go-ethereum/common" ) -type SigninAlgo string - -// Chains represent a slice of Chain -type Chains []Chain - // Validate checks whether the chain is valid // The function check the chain ID is positive and all enum fields have a defined value func (chain Chain) Validate() error { @@ -44,11 +38,6 @@ func (chain Chain) Validate() error { return nil } -// IsEqual compare two chain to see whether they represent the same chain -func (chain Chain) IsEqual(c Chain) bool { - return chain.ChainId == c.ChainId -} - // IsZetaChain returns true if the chain is a ZetaChain chain func (chain Chain) IsZetaChain() bool { return chain.Network == Network_zeta @@ -63,13 +52,13 @@ func (chain Chain) IsExternalChain() bool { // on EVM chain, it is 20Bytes // on Bitcoin chain, it is P2WPKH address, []byte(bech32 encoded string) func (chain Chain) EncodeAddress(b []byte) (string, error) { - if IsEVMChain(chain.ChainId) { + if chain.Consensus == Consensus_ethereum { addr := ethcommon.BytesToAddress(b) if addr == (ethcommon.Address{}) { return "", fmt.Errorf("invalid EVM address") } return addr.Hex(), nil - } else if IsBitcoinChain(chain.ChainId) { + } else if chain.Consensus == Consensus_bitcoin { addrStr := string(b) chainParams, err := GetBTCChainParams(chain.ChainId) if err != nil { @@ -87,61 +76,54 @@ func (chain Chain) EncodeAddress(b []byte) (string, error) { return "", fmt.Errorf("chain (%d) not supported", chain.ChainId) } -func (chain Chain) BTCAddressFromWitnessProgram(witnessProgram []byte) (string, error) { - chainParams, err := GetBTCChainParams(chain.ChainId) - if err != nil { - return "", err - } - address, err := btcutil.NewAddressWitnessPubKeyHash(witnessProgram, chainParams) - if err != nil { - return "", err - } - return address.EncodeAddress(), nil +func (chain Chain) IsEVMChain() bool { + return chain.Consensus == Consensus_ethereum } -// DecodeAddress decode the address string to bytes -func (chain Chain) DecodeAddress(addr string) ([]byte, error) { - return DecodeAddressFromChainID(chain.ChainId, addr) +func (chain Chain) IsBitcoinChain() bool { + return chain.Consensus == Consensus_bitcoin } // DecodeAddressFromChainID decode the address string to bytes -func DecodeAddressFromChainID(chainID int64, addr string) ([]byte, error) { - if IsEVMChain(chainID) { +// additionalChains is a list of additional chains to search from +// in practice, it is used in the protocol to dynamically support new chains without doing an upgrade +func DecodeAddressFromChainID(chainID int64, addr string, additionalChains []Chain) ([]byte, error) { + switch { + case IsEVMChain(chainID, additionalChains): return ethcommon.HexToAddress(addr).Bytes(), nil - } else if IsBitcoinChain(chainID) { + case IsBitcoinChain(chainID, additionalChains): return []byte(addr), nil + default: + return nil, fmt.Errorf("chain (%d) not supported", chainID) } - return nil, fmt.Errorf("chain (%d) not supported", chainID) } // IsEVMChain returns true if the chain is an EVM chain or uses the ethereum consensus mechanism for block finality -func IsEVMChain(chainID int64) bool { - return ChainIDInChainList(chainID, ChainListByConsensus(Consensus_ethereum)) +// additionalChains is a list of additional chains to search from +// in practice, it is used in the protocol to dynamically support new chains without doing an upgrade +func IsEVMChain(chainID int64, additionalChains []Chain) bool { + return ChainIDInChainList(chainID, ChainListByConsensus(Consensus_ethereum, additionalChains)) } // IsBitcoinChain returns true if the chain is a Bitcoin-based chain or uses the bitcoin consensus mechanism for block finality -func IsBitcoinChain(chainID int64) bool { - return ChainIDInChainList(chainID, ChainListByConsensus(Consensus_bitcoin)) +// additionalChains is a list of additional chains to search from +// in practice, it is used in the protocol to dynamically support new chains without doing an upgrade +func IsBitcoinChain(chainID int64, additionalChains []Chain) bool { + return ChainIDInChainList(chainID, ChainListByConsensus(Consensus_bitcoin, additionalChains)) } // IsEthereumChain returns true if the chain is an Ethereum chain -func IsEthereumChain(chainID int64) bool { - return ChainIDInChainList(chainID, ChainListByNetwork(Network_eth)) +// additionalChains is a list of additional chains to search from +// in practice, it is used in the protocol to dynamically support new chains without doing an upgrade +func IsEthereumChain(chainID int64, additionalChains []Chain) bool { + return ChainIDInChainList(chainID, ChainListByNetwork(Network_eth, additionalChains)) } // IsZetaChain returns true if the chain is a Zeta chain -func IsZetaChain(chainID int64) bool { - return ChainIDInChainList(chainID, ChainListByNetwork(Network_zeta)) -} - -// IsHeaderSupportedChain returns true if the chain's consensus supports block header-based verification -func IsHeaderSupportedChain(chainID int64) bool { - return ChainIDInChainList(chainID, ChainListForHeaderSupport()) -} - -// SupportMerkleProof returns true if the chain supports block header-based verification -func (chain Chain) SupportMerkleProof() bool { - return IsEVMChain(chain.ChainId) || IsBitcoinChain(chain.ChainId) +// additionalChains is a list of additional chains to search from +// in practice, it is used in the protocol to dynamically support new chains without doing an upgrade +func IsZetaChain(chainID int64, additionalChains []Chain) bool { + return ChainIDInChainList(chainID, ChainListByNetwork(Network_zeta, additionalChains)) } // IsEmpty is to determinate whether the chain is empty @@ -149,45 +131,20 @@ func (chain Chain) IsEmpty() bool { return strings.TrimSpace(chain.String()) == "" } -// Has check whether chain c is in the list -func (chains Chains) Has(c Chain) bool { - for _, ch := range chains { - if ch.IsEqual(c) { - return true - } - } - return false -} - -// Distinct return a distinct set of chains, no duplicates -func (chains Chains) Distinct() Chains { - var newChains Chains - for _, chain := range chains { - if !newChains.Has(chain) { - newChains = append(newChains, chain) - } - } - return newChains -} - -func (chains Chains) Strings() []string { - str := make([]string, len(chains)) - for i, c := range chains { - str[i] = c.String() - } - return str -} - -func GetChainFromChainID(chainID int64) *Chain { - chains := DefaultChainsList() +// GetChainFromChainID returns the chain from the chain ID +// additionalChains is a list of additional chains to search from +// in practice, it is used in the protocol to dynamically support new chains without doing an upgrade +func GetChainFromChainID(chainID int64, additionalChains []Chain) (Chain, bool) { + chains := CombineDefaultChainsList(additionalChains) for _, chain := range chains { if chainID == chain.ChainId { - return chain + return chain, true } } - return nil + return Chain{}, false } +// GetBTCChainParams returns the bitcoin chain config params from the chain ID func GetBTCChainParams(chainID int64) (*chaincfg.Params, error) { switch chainID { case 18444: @@ -201,6 +158,7 @@ func GetBTCChainParams(chainID int64) (*chaincfg.Params, error) { } } +// GetBTCChainIDFromChainParams returns the bitcoin chain ID from the chain config params func GetBTCChainIDFromChainParams(params *chaincfg.Params) (int64, error) { switch params.Name { case chaincfg.RegressionNetParams.Name: @@ -214,13 +172,8 @@ func GetBTCChainIDFromChainParams(params *chaincfg.Params) (int64, error) { } } -// InChainList checks whether the chain is in the chain list -func (chain Chain) InChainList(chainList []*Chain) bool { - return ChainIDInChainList(chain.ChainId, chainList) -} - // ChainIDInChainList checks whether the chainID is in the chain list -func ChainIDInChainList(chainID int64, chainList []*Chain) bool { +func ChainIDInChainList(chainID int64, chainList []Chain) bool { for _, c := range chainList { if chainID == c.ChainId { return true diff --git a/pkg/chains/chain_test.go b/pkg/chains/chain_test.go index d14fd39a37..e9551d35c7 100644 --- a/pkg/chains/chain_test.go +++ b/pkg/chains/chain_test.go @@ -1,121 +1,120 @@ -package chains +package chains_test import ( - "encoding/hex" + "github.com/zeta-chain/zetacore/testutil/sample" "testing" - "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcutil" ethcommon "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" + "github.com/zeta-chain/zetacore/pkg/chains" ) func TestChain_Validate(t *testing.T) { tests := []struct { name string - chain Chain + chain chains.Chain errStr string }{ { name: "should pass if chain is valid", - chain: Chain{ + chain: chains.Chain{ ChainId: 42, - ChainName: ChainName_empty, - Network: Network_optimism, - NetworkType: NetworkType_testnet, - Vm: Vm_evm, - Consensus: Consensus_op_stack, + ChainName: chains.ChainName_empty, + Network: chains.Network_optimism, + NetworkType: chains.NetworkType_testnet, + Vm: chains.Vm_evm, + Consensus: chains.Consensus_op_stack, IsExternal: true, }, }, { name: "should error if chain ID is zero", - chain: Chain{ + chain: chains.Chain{ ChainId: 0, - ChainName: ChainName_empty, - Network: Network_optimism, - NetworkType: NetworkType_testnet, - Vm: Vm_evm, - Consensus: Consensus_op_stack, + ChainName: chains.ChainName_empty, + Network: chains.Network_optimism, + NetworkType: chains.NetworkType_testnet, + Vm: chains.Vm_evm, + Consensus: chains.Consensus_op_stack, IsExternal: true, }, errStr: "chain ID must be positive", }, { name: "should error if chain ID is negative", - chain: Chain{ + chain: chains.Chain{ ChainId: 0, - ChainName: ChainName_empty, - Network: Network_optimism, - NetworkType: NetworkType_testnet, - Vm: Vm_evm, - Consensus: Consensus_op_stack, + ChainName: chains.ChainName_empty, + Network: chains.Network_optimism, + NetworkType: chains.NetworkType_testnet, + Vm: chains.Vm_evm, + Consensus: chains.Consensus_op_stack, IsExternal: true, }, errStr: "chain ID must be positive", }, { name: "should error if chain name invalid", - chain: Chain{ + chain: chains.Chain{ ChainId: 42, - ChainName: ChainName_base_sepolia + 1, - Network: Network_optimism, - NetworkType: NetworkType_testnet, - Vm: Vm_evm, - Consensus: Consensus_op_stack, + ChainName: chains.ChainName_solana_localnet + 1, + Network: chains.Network_optimism, + NetworkType: chains.NetworkType_testnet, + Vm: chains.Vm_evm, + Consensus: chains.Consensus_op_stack, IsExternal: true, }, errStr: "invalid chain name", }, { name: "should error if network invalid", - chain: Chain{ + chain: chains.Chain{ ChainId: 42, - ChainName: ChainName_empty, - Network: Network_base + 1, - NetworkType: NetworkType_testnet, - Vm: Vm_evm, - Consensus: Consensus_op_stack, + ChainName: chains.ChainName_empty, + Network: chains.Network_solana + 1, + NetworkType: chains.NetworkType_testnet, + Vm: chains.Vm_evm, + Consensus: chains.Consensus_op_stack, IsExternal: true, }, errStr: "invalid network", }, { name: "should error if network type invalid", - chain: Chain{ + chain: chains.Chain{ ChainId: 42, - ChainName: ChainName_empty, - Network: Network_base, - NetworkType: NetworkType_devnet + 1, - Vm: Vm_evm, - Consensus: Consensus_op_stack, + ChainName: chains.ChainName_empty, + Network: chains.Network_base, + NetworkType: chains.NetworkType_devnet + 1, + Vm: chains.Vm_evm, + Consensus: chains.Consensus_op_stack, IsExternal: true, }, errStr: "invalid network type", }, { name: "should error if vm invalid", - chain: Chain{ + chain: chains.Chain{ ChainId: 42, - ChainName: ChainName_empty, - Network: Network_base, - NetworkType: NetworkType_devnet, - Vm: Vm_evm + 1, - Consensus: Consensus_op_stack, + ChainName: chains.ChainName_empty, + Network: chains.Network_base, + NetworkType: chains.NetworkType_devnet, + Vm: chains.Vm_svm + 1, + Consensus: chains.Consensus_op_stack, IsExternal: true, }, errStr: "invalid vm", }, { name: "should error if consensus invalid", - chain: Chain{ + chain: chains.Chain{ ChainId: 42, - ChainName: ChainName_empty, - Network: Network_base, - NetworkType: NetworkType_devnet, - Vm: Vm_evm, - Consensus: Consensus_op_stack + 1, + ChainName: chains.ChainName_empty, + Network: chains.Network_base, + NetworkType: chains.NetworkType_devnet, + Vm: chains.Vm_evm, + Consensus: chains.Consensus_solana_consensus + 1, IsExternal: true, }, errStr: "invalid consensus", @@ -132,7 +131,7 @@ func TestChain_Validate(t *testing.T) { } t.Run("all default chains are valid", func(t *testing.T) { - for _, chain := range DefaultChainsList() { + for _, chain := range chains.DefaultChainsList() { require.NoError(t, chain.Validate()) } }) @@ -141,16 +140,17 @@ func TestChain_Validate(t *testing.T) { func TestChain_EncodeAddress(t *testing.T) { tests := []struct { name string - chain Chain + chain chains.Chain b []byte want string wantErr bool }{ { name: "should error if b is not a valid address on the bitcoin network", - chain: Chain{ - ChainName: ChainName_btc_testnet, + chain: chains.Chain{ + ChainName: chains.ChainName_btc_testnet, ChainId: 18332, + Consensus: chains.Consensus_bitcoin, }, b: []byte("bc1qk0cc73p8m7hswn8y2q080xa4e5pxapnqgp7h9c"), want: "", @@ -158,9 +158,10 @@ func TestChain_EncodeAddress(t *testing.T) { }, { name: "should pass if b is a valid address on the network", - chain: Chain{ - ChainName: ChainName_btc_mainnet, + chain: chains.Chain{ + ChainName: chains.ChainName_btc_mainnet, ChainId: 8332, + Consensus: chains.Consensus_bitcoin, }, b: []byte("bc1qk0cc73p8m7hswn8y2q080xa4e5pxapnqgp7h9c"), want: "bc1qk0cc73p8m7hswn8y2q080xa4e5pxapnqgp7h9c", @@ -168,8 +169,8 @@ func TestChain_EncodeAddress(t *testing.T) { }, { name: "should error if b is not a valid address on the evm network", - chain: Chain{ - ChainName: ChainName_goerli_testnet, + chain: chains.Chain{ + ChainName: chains.ChainName_goerli_testnet, ChainId: 5, }, b: ethcommon.Hex2Bytes("0x321"), @@ -178,8 +179,8 @@ func TestChain_EncodeAddress(t *testing.T) { }, { name: "should pass if b is a valid address on the evm network", - chain: Chain{ - ChainName: ChainName_goerli_testnet, + chain: chains.Chain{ + ChainName: chains.ChainName_goerli_testnet, ChainId: 5, }, b: []byte("0x321"), @@ -188,7 +189,7 @@ func TestChain_EncodeAddress(t *testing.T) { }, { name: "should error if chain not supported", - chain: Chain{ + chain: chains.Chain{ ChainName: 999, ChainId: 999, }, @@ -211,146 +212,125 @@ func TestChain_EncodeAddress(t *testing.T) { } } -func TestChain_DecodeAddress(t *testing.T) { +func TestChain_IsEVMChain(t *testing.T) { tests := []struct { - name string - chain Chain - b string - want []byte - wantErr bool + name string + chain chains.Chain + want bool }{ - { - name: "should decode on btc chain", - chain: Chain{ - ChainName: ChainName_btc_testnet, - ChainId: 18332, - }, - want: []byte("bc1qk0cc73p8m7hswn8y2q080xa4e5pxapnqgp7h9c"), - b: "bc1qk0cc73p8m7hswn8y2q080xa4e5pxapnqgp7h9c", - wantErr: false, - }, - { - name: "should decode on evm chain", - chain: Chain{ - ChainName: ChainName_goerli_testnet, - ChainId: 5, - }, - want: ethcommon.HexToAddress("0x321").Bytes(), - b: "0x321", - wantErr: false, - }, - { - name: "should error if chain not supported", - chain: Chain{ - ChainName: 999, - ChainId: 999, - }, - want: ethcommon.Hex2Bytes("0x321"), - b: "", - wantErr: true, - }, + {"Ethereum Mainnet", chains.Ethereum, true}, + {"Goerli Testnet", chains.Goerli, true}, + {"Sepolia Testnet", chains.Sepolia, true}, + {"Non-EVM", chains.BitcoinMainnet, false}, + {"Zeta Mainnet", chains.ZetaChainMainnet, false}, } - for _, tc := range tests { - tc := tc - t.Run(tc.name, func(t *testing.T) { - s, err := tc.chain.DecodeAddress(tc.b) - if tc.wantErr { - require.Error(t, err) - return - } - require.Equal(t, tc.want, s) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + require.Equal(t, tt.want, tt.chain.IsEVMChain()) }) } } -func TestChain_InChainList(t *testing.T) { - require.True(t, ZetaChainMainnet.InChainList(ChainListByNetwork(Network_zeta))) - require.True(t, ZetaChainDevnet.InChainList(ChainListByNetwork(Network_zeta))) - require.True(t, ZetaChainPrivnet.InChainList(ChainListByNetwork(Network_zeta))) - require.True(t, ZetaChainTestnet.InChainList(ChainListByNetwork(Network_zeta))) - require.False(t, Ethereum.InChainList(ChainListByNetwork(Network_zeta))) -} - -func TestIsZetaChain(t *testing.T) { +func TestChain_IsBitcoinChain(t *testing.T) { tests := []struct { - name string - chainID int64 - want bool + name string + chain chains.Chain + want bool }{ - {"Zeta Mainnet", ZetaChainMainnet.ChainId, true}, - {"Zeta Testnet", ZetaChainTestnet.ChainId, true}, - {"Zeta Mocknet", ZetaChainDevnet.ChainId, true}, - {"Zeta Privnet", ZetaChainPrivnet.ChainId, true}, - {"Non-Zeta", Ethereum.ChainId, false}, + {"Bitcoin Mainnet", chains.BitcoinMainnet, true}, + {"Bitcoin Testnet", chains.BitcoinTestnet, true}, + {"Bitcoin Regtest", chains.BitcoinRegtest, true}, + {"Non-Bitcoin", chains.Ethereum, false}, + {"Zeta Mainnet", chains.ZetaChainMainnet, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - require.Equal(t, tt.want, IsZetaChain(tt.chainID)) + require.Equal(t, tt.want, tt.chain.IsBitcoinChain()) }) } } -func TestIsEVMChain(t *testing.T) { +func TestIsZetaChain(t *testing.T) { tests := []struct { name string chainID int64 want bool }{ - {"Ethereum Mainnet", Ethereum.ChainId, true}, - {"Goerli Testnet", Goerli.ChainId, true}, - {"Sepolia Testnet", Sepolia.ChainId, true}, - {"Non-EVM", BitcoinMainnet.ChainId, false}, - {"Zeta Mainnet", ZetaChainMainnet.ChainId, false}, + {"Zeta Mainnet", chains.ZetaChainMainnet.ChainId, true}, + {"Zeta Testnet", chains.ZetaChainTestnet.ChainId, true}, + {"Zeta Mocknet", chains.ZetaChainDevnet.ChainId, true}, + {"Zeta Privnet", chains.ZetaChainPrivnet.ChainId, true}, + {"Non-Zeta", chains.Ethereum.ChainId, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - require.Equal(t, tt.want, IsEVMChain(tt.chainID)) + require.Equal(t, tt.want, chains.IsZetaChain(tt.chainID, []chains.Chain{})) }) } } -func TestIsHeaderSupportedChain(t *testing.T) { +func TestDecodeAddressFromChainID(t *testing.T) { + ethAddr := sample.EthAddress() + tests := []struct { name string chainID int64 - want bool + addr string + want []byte + wantErr bool }{ - {"Ethereum Mainnet", Ethereum.ChainId, true}, - {"Goerli Testnet", Goerli.ChainId, true}, - {"Goerli Localnet", GoerliLocalnet.ChainId, true}, - {"Sepolia Testnet", Sepolia.ChainId, true}, - {"BSC Testnet", BscTestnet.ChainId, true}, - {"BSC Mainnet", BscMainnet.ChainId, true}, - {"BTC", BitcoinMainnet.ChainId, true}, - {"Zeta Mainnet", ZetaChainMainnet.ChainId, false}, + { + name: "Ethereum", + chainID: chains.Ethereum.ChainId, + addr: ethAddr.Hex(), + want: ethAddr.Bytes(), + }, + { + name: "Bitcoin", + chainID: chains.BitcoinMainnet.ChainId, + addr: "bc1qk0cc73p8m7hswn8y2q080xa4e5pxapnqgp7h9c", + want: []byte("bc1qk0cc73p8m7hswn8y2q080xa4e5pxapnqgp7h9c"), + }, + { + name: "Non-supported chain", + chainID: 9999, + wantErr: true, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - require.Equal(t, tt.want, IsHeaderSupportedChain(tt.chainID)) + got, err := chains.DecodeAddressFromChainID(tt.chainID, tt.addr, []chains.Chain{}) + if tt.wantErr { + require.Error(t, err) + return + } + require.NoError(t, err) + require.Equal(t, tt.want, got) }) + } } -func TestSupportMerkleProof(t *testing.T) { +func TestIsEVMChain(t *testing.T) { tests := []struct { - name string - chain Chain - want bool + name string + chainID int64 + want bool }{ - {"Ethereum Mainnet", Ethereum, true}, - {"BSC Testnet", BscTestnet, true}, - {"BSC Mainnet", BscMainnet, true}, - {"Non-EVM", BitcoinMainnet, true}, - {"Zeta Mainnet", ZetaChainMainnet, false}, + {"Ethereum Mainnet", chains.Ethereum.ChainId, true}, + {"Goerli Testnet", chains.Goerli.ChainId, true}, + {"Sepolia Testnet", chains.Sepolia.ChainId, true}, + {"Non-EVM", chains.BitcoinMainnet.ChainId, false}, + {"Zeta Mainnet", chains.ZetaChainMainnet.ChainId, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - require.Equal(t, tt.want, tt.chain.SupportMerkleProof()) + require.Equal(t, tt.want, chains.IsEVMChain(tt.chainID, []chains.Chain{})) }) } } @@ -361,16 +341,16 @@ func TestIsBitcoinChain(t *testing.T) { chainID int64 want bool }{ - {"Bitcoin Mainnet", BitcoinMainnet.ChainId, true}, - {"Bitcoin Testnet", BitcoinTestnet.ChainId, true}, - {"Bitcoin Regtest", BitcoinRegtest.ChainId, true}, - {"Non-Bitcoin", Ethereum.ChainId, false}, - {"Zeta Mainnet", ZetaChainMainnet.ChainId, false}, + {"Bitcoin Mainnet", chains.BitcoinMainnet.ChainId, true}, + {"Bitcoin Testnet", chains.BitcoinTestnet.ChainId, true}, + {"Bitcoin Regtest", chains.BitcoinRegtest.ChainId, true}, + {"Non-Bitcoin", chains.Ethereum.ChainId, false}, + {"Zeta Mainnet", chains.ZetaChainMainnet.ChainId, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - require.Equal(t, tt.want, IsBitcoinChain(tt.chainID)) + require.Equal(t, tt.want, chains.IsBitcoinChain(tt.chainID, []chains.Chain{})) }) } } @@ -381,128 +361,82 @@ func TestIsEthereumChain(t *testing.T) { chainID int64 want bool }{ - {"Ethereum Mainnet", Ethereum.ChainId, true}, - {"Goerli Testnet", Goerli.ChainId, true}, - {"Sepolia Testnet", Sepolia.ChainId, true}, - {"Non-Ethereum", BitcoinMainnet.ChainId, false}, - {"Zeta Mainnet", ZetaChainMainnet.ChainId, false}, + {"Ethereum Mainnet", chains.Ethereum.ChainId, true}, + {"Goerli Testnet", chains.Goerli.ChainId, true}, + {"Sepolia Testnet", chains.Sepolia.ChainId, true}, + {"Non-Ethereum", chains.BitcoinMainnet.ChainId, false}, + {"Zeta Mainnet", chains.ZetaChainMainnet.ChainId, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - require.Equal(t, tt.want, IsEthereumChain(tt.chainID)) + require.Equal(t, tt.want, chains.IsEthereumChain(tt.chainID, []chains.Chain{})) }) } } func TestChain_IsExternalChain(t *testing.T) { - require.False(t, ZetaChainMainnet.IsExternalChain()) - require.True(t, Ethereum.IsExternalChain()) + require.False(t, chains.ZetaChainMainnet.IsExternalChain()) + require.True(t, chains.Ethereum.IsExternalChain()) } func TestChain_IsZetaChain(t *testing.T) { - require.True(t, ZetaChainMainnet.IsZetaChain()) - require.False(t, Ethereum.IsZetaChain()) + require.True(t, chains.ZetaChainMainnet.IsZetaChain()) + require.False(t, chains.Ethereum.IsZetaChain()) } func TestChain_IsEmpty(t *testing.T) { - require.True(t, Chain{}.IsEmpty()) - require.False(t, ZetaChainMainnet.IsEmpty()) -} - -func TestChain_WitnessProgram(t *testing.T) { - // Ordinarily the private key would come from whatever storage mechanism - // is being used, but for this example just hard code it. - privKeyBytes, err := hex.DecodeString("22a47fa09a223f2aa079edf85a7c2" + - "d4f8720ee63e502ee2869afab7de234b80c") - require.NoError(t, err) - - t.Run("should return btc address", func(t *testing.T) { - _, pubKey := btcec.PrivKeyFromBytes(btcec.S256(), privKeyBytes) - pubKeyHash := btcutil.Hash160(pubKey.SerializeCompressed()) - addr, err := btcutil.NewAddressWitnessPubKeyHash(pubKeyHash, &chaincfg.RegressionNetParams) - require.NoError(t, err) - - chain := BitcoinTestnet - _, err = chain.BTCAddressFromWitnessProgram(addr.WitnessProgram()) - require.NoError(t, err) - }) - - t.Run("should fail for wrong chain id", func(t *testing.T) { - _, pubKey := btcec.PrivKeyFromBytes(btcec.S256(), privKeyBytes) - pubKeyHash := btcutil.Hash160(pubKey.SerializeCompressed()) - addr, err := btcutil.NewAddressWitnessPubKeyHash(pubKeyHash, &chaincfg.RegressionNetParams) - require.NoError(t, err) - - chain := Goerli - _, err = chain.BTCAddressFromWitnessProgram(addr.WitnessProgram()) - require.Error(t, err) - }) - - t.Run("should fail for wrong witness program", func(t *testing.T) { - _, pubKey := btcec.PrivKeyFromBytes(btcec.S256(), privKeyBytes) - pubKeyHash := btcutil.Hash160(pubKey.SerializeCompressed()) - addr, err := btcutil.NewAddressWitnessPubKeyHash(pubKeyHash, &chaincfg.RegressionNetParams) - require.NoError(t, err) - - chain := BitcoinTestnet - _, err = chain.BTCAddressFromWitnessProgram(addr.WitnessProgram()[0:19]) - require.Error(t, err) - }) -} - -func TestChains_Has(t *testing.T) { - chains := Chains{ZetaChainMainnet, ZetaChainTestnet} - require.True(t, chains.Has(ZetaChainMainnet)) - require.False(t, chains.Has(Ethereum)) -} - -func TestChains_Distinct(t *testing.T) { - chains := Chains{ZetaChainMainnet, ZetaChainMainnet, ZetaChainTestnet} - distinctChains := chains.Distinct() - require.Len(t, distinctChains, 2) -} - -func TestChains_Strings(t *testing.T) { - chains := Chains{ZetaChainMainnet, ZetaChainTestnet} - strings := chains.Strings() - expected := []string{chains[0].String(), chains[1].String()} - require.Equal(t, expected, strings) + require.True(t, chains.Chain{}.IsEmpty()) + require.False(t, chains.ZetaChainMainnet.IsEmpty()) } func TestGetChainFromChainID(t *testing.T) { - chain := GetChainFromChainID(ZetaChainMainnet.ChainId) - require.Equal(t, ZetaChainMainnet, *chain) - require.Nil(t, GetChainFromChainID(9999)) + chain, found := chains.GetChainFromChainID(chains.ZetaChainMainnet.ChainId, []chains.Chain{}) + require.EqualValues(t, chains.ZetaChainMainnet, chain) + require.True(t, found) + chain, found = chains.GetChainFromChainID(9999, []chains.Chain{}) + require.False(t, found) } func TestGetBTCChainParams(t *testing.T) { - params, err := GetBTCChainParams(BitcoinMainnet.ChainId) + params, err := chains.GetBTCChainParams(chains.BitcoinMainnet.ChainId) require.NoError(t, err) require.Equal(t, &chaincfg.MainNetParams, params) - _, err = GetBTCChainParams(9999) + _, err = chains.GetBTCChainParams(9999) require.Error(t, err) } func TestGetBTCChainIDFromChainParams(t *testing.T) { - chainID, err := GetBTCChainIDFromChainParams(&chaincfg.MainNetParams) + chainID, err := chains.GetBTCChainIDFromChainParams(&chaincfg.MainNetParams) require.NoError(t, err) require.Equal(t, int64(8332), chainID) - chainID, err = GetBTCChainIDFromChainParams(&chaincfg.RegressionNetParams) + chainID, err = chains.GetBTCChainIDFromChainParams(&chaincfg.RegressionNetParams) require.NoError(t, err) require.Equal(t, int64(18444), chainID) - chainID, err = GetBTCChainIDFromChainParams(&chaincfg.TestNet3Params) + chainID, err = chains.GetBTCChainIDFromChainParams(&chaincfg.TestNet3Params) require.NoError(t, err) require.Equal(t, int64(18332), chainID) - _, err = GetBTCChainIDFromChainParams(&chaincfg.Params{Name: "unknown"}) + _, err = chains.GetBTCChainIDFromChainParams(&chaincfg.Params{Name: "unknown"}) require.Error(t, err) } func TestChainIDInChainList(t *testing.T) { - require.True(t, ChainIDInChainList(ZetaChainMainnet.ChainId, ChainListByNetwork(Network_zeta))) - require.False(t, ChainIDInChainList(Ethereum.ChainId, ChainListByNetwork(Network_zeta))) + require.True( + t, + chains.ChainIDInChainList( + chains.ZetaChainMainnet.ChainId, + chains.ChainListByNetwork(chains.Network_zeta, []chains.Chain{}), + ), + ) + require.False( + t, + chains.ChainIDInChainList( + chains.Ethereum.ChainId, + chains.ChainListByNetwork(chains.Network_zeta, []chains.Chain{}), + ), + ) } diff --git a/pkg/chains/chains.go b/pkg/chains/chains.go index 11c6f952f0..2dcd0377ea 100644 --- a/pkg/chains/chains.go +++ b/pkg/chains/chains.go @@ -91,6 +91,20 @@ var ( CctxGateway: CCTXGateway_observers, } + // SolanaMainnet is Solana mainnet + // TODO: define final chain ID + // https://github.com/zeta-chain/node/issues/2421 + SolanaMainnet = Chain{ + ChainName: ChainName_solana_mainnet, + ChainId: 900, + Network: Network_solana, + NetworkType: NetworkType_mainnet, + Vm: Vm_svm, + Consensus: Consensus_solana_consensus, + IsExternal: true, + CctxGateway: CCTXGateway_observers, + } + /** * Testnet chains */ @@ -179,6 +193,22 @@ var ( CctxGateway: CCTXGateway_observers, } + // SolanaDevnet is Solana devnet + // NOTE: Solana devnet refers to Solana testnet in our terminology + // Solana uses devnet denomitation for network for development + // TODO: define final chain ID + // https://github.com/zeta-chain/node/issues/2421 + SolanaDevnet = Chain{ + ChainName: ChainName_solana_devnet, + ChainId: 901, + Network: Network_solana, + NetworkType: NetworkType_testnet, + Vm: Vm_svm, + Consensus: Consensus_solana_consensus, + IsExternal: true, + CctxGateway: CCTXGateway_observers, + } + /** * Devnet chains */ @@ -236,6 +266,20 @@ var ( CctxGateway: CCTXGateway_observers, } + // SolanaLocalnet is Solana localnet + // TODO: define final chain ID + // https://github.com/zeta-chain/node/issues/2421 + SolanaLocalnet = Chain{ + ChainName: ChainName_solana_localnet, + ChainId: 902, + Network: Network_solana, + NetworkType: NetworkType_privnet, + Vm: Vm_svm, + Consensus: Consensus_solana_consensus, + IsExternal: true, + CctxGateway: CCTXGateway_observers, + } + /** * Deprecated chains */ @@ -265,14 +309,17 @@ var ( } ) +// ErrNotZetaChain is the error for chain not being a ZetaChain chain +var ErrNotZetaChain = fmt.Errorf("chain is not a ZetaChain chain") + // BtcNonceMarkOffset is the offset satoshi amount to calculate the nonce mark output func BtcNonceMarkOffset() int64 { return 2000 } // DefaultChainsList returns a list of default chains -func DefaultChainsList() []*Chain { - return chainListPointers([]Chain{ +func DefaultChainsList() []Chain { + return []Chain{ BitcoinMainnet, BscMainnet, Ethereum, @@ -293,13 +340,16 @@ func DefaultChainsList() []*Chain { OptimismSepolia, BaseMainnet, BaseSepolia, - }) + SolanaMainnet, + SolanaDevnet, + SolanaLocalnet, + } } // ChainListByNetworkType returns a list of chains by network type -func ChainListByNetworkType(networkType NetworkType) []*Chain { - var chainList []*Chain - for _, chain := range DefaultChainsList() { +func ChainListByNetworkType(networkType NetworkType, additionalChains []Chain) []Chain { + var chainList []Chain + for _, chain := range CombineDefaultChainsList(additionalChains) { if chain.NetworkType == networkType { chainList = append(chainList, chain) } @@ -308,9 +358,9 @@ func ChainListByNetworkType(networkType NetworkType) []*Chain { } // ChainListByNetwork returns a list of chains by network -func ChainListByNetwork(network Network) []*Chain { - var chainList []*Chain - for _, chain := range DefaultChainsList() { +func ChainListByNetwork(network Network, additionalChains []Chain) []Chain { + var chainList []Chain + for _, chain := range CombineDefaultChainsList(additionalChains) { if chain.Network == network { chainList = append(chainList, chain) } @@ -319,9 +369,9 @@ func ChainListByNetwork(network Network) []*Chain { } // ExternalChainList returns a list chains that are not Zeta -func ExternalChainList() []*Chain { - var chainList []*Chain - for _, chain := range DefaultChainsList() { +func ExternalChainList(additionalChains []Chain) []Chain { + var chainList []Chain + for _, chain := range CombineDefaultChainsList(additionalChains) { if chain.IsExternal { chainList = append(chainList, chain) } @@ -330,9 +380,9 @@ func ExternalChainList() []*Chain { } // ChainListByConsensus returns a list of chains by consensus -func ChainListByConsensus(consensus Consensus) []*Chain { - var chainList []*Chain - for _, chain := range DefaultChainsList() { +func ChainListByConsensus(consensus Consensus, additionalChains []Chain) []Chain { + var chainList []Chain + for _, chain := range CombineDefaultChainsList(additionalChains) { if chain.Consensus == consensus { chainList = append(chainList, chain) } @@ -341,9 +391,9 @@ func ChainListByConsensus(consensus Consensus) []*Chain { } // ChainListForHeaderSupport returns a list of chains that support headers -func ChainListForHeaderSupport() []*Chain { - var chainList []*Chain - for _, chain := range DefaultChainsList() { +func ChainListForHeaderSupport(additionalChains []Chain) []Chain { + var chainList []Chain + for _, chain := range CombineDefaultChainsList(additionalChains) { if chain.Consensus == Consensus_ethereum || chain.Consensus == Consensus_bitcoin { chainList = append(chainList, chain) } @@ -351,14 +401,19 @@ func ChainListForHeaderSupport() []*Chain { return chainList } -// ZetaChainFromChainID returns a ZetaChain chain object from a Cosmos chain ID -func ZetaChainFromChainID(chainID string) (Chain, error) { +// ZetaChainFromCosmosChainID returns a ZetaChain chain object from a Cosmos chain ID +func ZetaChainFromCosmosChainID(chainID string) (Chain, error) { ethChainID, err := CosmosToEthChainID(chainID) if err != nil { return Chain{}, err } - switch ethChainID { + return ZetaChainFromChainID(ethChainID) +} + +// ZetaChainFromChainID returns a ZetaChain chain object from a chain ID +func ZetaChainFromChainID(chainID int64) (Chain, error) { + switch chainID { case ZetaChainPrivnet.ChainId: return ZetaChainPrivnet, nil case ZetaChainMainnet.ChainId: @@ -368,17 +423,37 @@ func ZetaChainFromChainID(chainID string) (Chain, error) { case ZetaChainDevnet.ChainId: return ZetaChainDevnet, nil default: - return Chain{}, fmt.Errorf("chain %d not found", ethChainID) + return Chain{}, ErrNotZetaChain } } -// TODO : https://github.com/zeta-chain/node/issues/2080 -// remove the usage of this function -// chainListPointers returns a list of chain pointers -func chainListPointers(chains []Chain) []*Chain { - var c []*Chain - for i := 0; i < len(chains); i++ { - c = append(c, &chains[i]) +// CombineDefaultChainsList combines the default chains list with a list of chains +// duplicated chain ID are overwritten by the second list +func CombineDefaultChainsList(chains []Chain) []Chain { + return CombineChainList(DefaultChainsList(), chains) +} + +// CombineChainList combines a list of chains with a list of chains +// duplicated chain ID are overwritten by the second list +func CombineChainList(base []Chain, additional []Chain) []Chain { + combined := make([]Chain, 0, len(base)+len(additional)) + combined = append(combined, base...) + + // map chain ID in combined to index in the list + chainIDIndexMap := make(map[int64]int) + for i, chain := range combined { + chainIDIndexMap[chain.ChainId] = i + } + + // add chains2 to combined + // if chain ID already exists in chains1, overwrite it + for _, chain := range additional { + if index, ok := chainIDIndexMap[chain.ChainId]; ok { + combined[index] = chain + } else { + combined = append(combined, chain) + } } - return c + + return combined } diff --git a/pkg/chains/chains.pb.go b/pkg/chains/chains.pb.go index 848a7e1bc0..b49c3b0c96 100644 --- a/pkg/chains/chains.pb.go +++ b/pkg/chains/chains.pb.go @@ -78,6 +78,9 @@ const ( ChainName_optimism_sepolia ChainName = 18 ChainName_base_mainnet ChainName = 19 ChainName_base_sepolia ChainName = 20 + ChainName_solana_mainnet ChainName = 21 + ChainName_solana_devnet ChainName = 22 + ChainName_solana_localnet ChainName = 23 ) var ChainName_name = map[int32]string{ @@ -100,6 +103,9 @@ var ChainName_name = map[int32]string{ 18: "optimism_sepolia", 19: "base_mainnet", 20: "base_sepolia", + 21: "solana_mainnet", + 22: "solana_devnet", + 23: "solana_localnet", } var ChainName_value = map[string]int32{ @@ -122,6 +128,9 @@ var ChainName_value = map[string]int32{ "optimism_sepolia": 18, "base_mainnet": 19, "base_sepolia": 20, + "solana_mainnet": 21, + "solana_devnet": 22, + "solana_localnet": 23, } func (x ChainName) String() string { @@ -145,6 +154,7 @@ const ( Network_bsc Network = 4 Network_optimism Network = 5 Network_base Network = 6 + Network_solana Network = 7 ) var Network_name = map[int32]string{ @@ -155,6 +165,7 @@ var Network_name = map[int32]string{ 4: "bsc", 5: "optimism", 6: "base", + 7: "solana", } var Network_value = map[string]int32{ @@ -165,6 +176,7 @@ var Network_value = map[string]int32{ "bsc": 4, "optimism": 5, "base": 6, + "solana": 7, } func (x Network) String() string { @@ -215,16 +227,19 @@ type Vm int32 const ( Vm_no_vm Vm = 0 Vm_evm Vm = 1 + Vm_svm Vm = 2 ) var Vm_name = map[int32]string{ 0: "no_vm", 1: "evm", + 2: "svm", } var Vm_value = map[string]int32{ "no_vm": 0, "evm": 1, + "svm": 2, } func (x Vm) String() string { @@ -241,10 +256,11 @@ func (Vm) EnumDescriptor() ([]byte, []int) { type Consensus int32 const ( - Consensus_ethereum Consensus = 0 - Consensus_tendermint Consensus = 1 - Consensus_bitcoin Consensus = 2 - Consensus_op_stack Consensus = 3 + Consensus_ethereum Consensus = 0 + Consensus_tendermint Consensus = 1 + Consensus_bitcoin Consensus = 2 + Consensus_op_stack Consensus = 3 + Consensus_solana_consensus Consensus = 4 ) var Consensus_name = map[int32]string{ @@ -252,13 +268,15 @@ var Consensus_name = map[int32]string{ 1: "tendermint", 2: "bitcoin", 3: "op_stack", + 4: "solana_consensus", } var Consensus_value = map[string]int32{ - "ethereum": 0, - "tendermint": 1, - "bitcoin": 2, - "op_stack": 3, + "ethereum": 0, + "tendermint": 1, + "bitcoin": 2, + "op_stack": 3, + "solana_consensus": 4, } func (x Consensus) String() string { @@ -425,51 +443,54 @@ func init() { } var fileDescriptor_236b85e7bff6130d = []byte{ - // 704 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x54, 0x3d, 0x8f, 0x2b, 0x35, - 0x14, 0xcd, 0x4c, 0xbe, 0xef, 0x64, 0xb3, 0xc6, 0x6f, 0x8b, 0xe1, 0x49, 0x0c, 0x0b, 0x05, 0x0a, - 0x11, 0x24, 0x02, 0x4a, 0x1a, 0x44, 0xc4, 0x7b, 0x02, 0x89, 0x57, 0x0c, 0xab, 0x15, 0xd0, 0x8c, - 0x3c, 0xce, 0x65, 0x62, 0x25, 0x1e, 0x8f, 0xc6, 0x4e, 0x76, 0xc3, 0xaf, 0xe0, 0x47, 0x50, 0xf0, - 0x53, 0x28, 0xb7, 0xa4, 0x44, 0xbb, 0x05, 0x25, 0x7f, 0x01, 0xd9, 0xf3, 0x91, 0xa5, 0x80, 0xdd, - 0x2a, 0xd7, 0x67, 0xce, 0x39, 0xf7, 0xd8, 0xbe, 0x31, 0xcc, 0x7f, 0x46, 0xc3, 0xf8, 0x86, 0x89, - 0x7c, 0xe9, 0x2a, 0x55, 0xe2, 0xb2, 0xd8, 0x66, 0x4b, 0x07, 0xe9, 0xfa, 0x67, 0x51, 0x94, 0xca, - 0x28, 0xfa, 0x4e, 0xcb, 0x5d, 0x34, 0xdc, 0x45, 0xb1, 0xcd, 0x16, 0x15, 0xe9, 0xe5, 0x45, 0xa6, - 0x32, 0xe5, 0x98, 0x4b, 0x5b, 0x55, 0xa2, 0xf7, 0xff, 0xea, 0x42, 0x7f, 0x65, 0x09, 0xf4, 0x6d, - 0x18, 0x39, 0x66, 0x22, 0xd6, 0xa1, 0x7f, 0xe9, 0xcd, 0xba, 0xf1, 0xd0, 0xad, 0xbf, 0x5e, 0xd3, - 0xd7, 0x00, 0xd5, 0xa7, 0x9c, 0x49, 0x0c, 0xbd, 0x4b, 0x6f, 0x36, 0xfd, 0x74, 0xb6, 0xf8, 0xdf, - 0x76, 0x0b, 0x67, 0xfa, 0x86, 0x49, 0x8c, 0xc7, 0xbc, 0x29, 0xe9, 0x17, 0x30, 0xcc, 0xd1, 0xdc, - 0xa8, 0x72, 0x1b, 0x76, 0x9d, 0xcb, 0x07, 0x4f, 0xb8, 0xbc, 0xa9, 0xd8, 0x71, 0x23, 0xa3, 0xdf, - 0xc2, 0xa4, 0x2e, 0x13, 0x73, 0x2c, 0x30, 0xec, 0x39, 0x9b, 0xf9, 0xf3, 0x6c, 0xae, 0x8e, 0x05, - 0xc6, 0x41, 0x7e, 0x5a, 0xd0, 0x4f, 0xc0, 0x3f, 0xc8, 0xb0, 0xef, 0x4c, 0xde, 0x7b, 0xc2, 0xe4, - 0x5a, 0xc6, 0xfe, 0x41, 0xd2, 0x57, 0x30, 0xe6, 0x2a, 0xd7, 0x98, 0xeb, 0xbd, 0x0e, 0x07, 0xcf, - 0x3b, 0x8b, 0x86, 0x1f, 0x9f, 0xa4, 0xf4, 0x5d, 0x08, 0x84, 0x4e, 0xf0, 0xd6, 0x60, 0x99, 0xb3, - 0x5d, 0x38, 0xbc, 0xf4, 0x66, 0xa3, 0x18, 0x84, 0xfe, 0xaa, 0x46, 0xec, 0x56, 0x39, 0x37, 0xb7, - 0x49, 0xc6, 0x0c, 0xde, 0xb0, 0x63, 0x38, 0x7a, 0xd6, 0x56, 0x57, 0xab, 0xab, 0xef, 0x5f, 0x57, - 0x8a, 0x38, 0xb0, 0xfa, 0x7a, 0x31, 0xff, 0x1c, 0xce, 0x62, 0xe4, 0x28, 0x0e, 0xf8, 0x9d, 0x61, - 0x66, 0xaf, 0x69, 0x00, 0x43, 0x5e, 0x22, 0x33, 0xb8, 0x26, 0x1d, 0xbb, 0xd0, 0x7b, 0xce, 0x51, - 0x6b, 0xe2, 0x51, 0x80, 0xc1, 0x4f, 0x4c, 0xec, 0x70, 0x4d, 0xfc, 0x97, 0xbd, 0xdf, 0x7e, 0x8d, - 0xbc, 0xf9, 0xdf, 0x3e, 0x8c, 0xdb, 0x1b, 0xa5, 0x63, 0xe8, 0xa3, 0x2c, 0xcc, 0x91, 0x74, 0xe8, - 0x39, 0x04, 0x68, 0x36, 0x89, 0x64, 0x22, 0xcf, 0xd1, 0x10, 0x8f, 0x12, 0x98, 0xd8, 0x58, 0x2d, - 0xe2, 0x5b, 0x4a, 0x6a, 0x78, 0x0b, 0x74, 0xe9, 0x0b, 0x38, 0x2f, 0xd4, 0xee, 0x98, 0xa9, 0xbc, - 0x05, 0x7b, 0x8e, 0xa5, 0x4f, 0xac, 0x3e, 0xa5, 0x30, 0xcd, 0x14, 0x96, 0x3b, 0x91, 0x18, 0xd4, - 0xc6, 0x62, 0x03, 0x8b, 0xc9, 0xbd, 0x4c, 0xd9, 0x09, 0x1b, 0x36, 0xc2, 0x06, 0x80, 0x36, 0x41, - 0x83, 0x04, 0x4d, 0x82, 0x06, 0x98, 0xd8, 0x04, 0x1a, 0x0b, 0xb5, 0x13, 0x27, 0xd6, 0x99, 0x05, - 0xeb, 0x86, 0x3b, 0xc5, 0xd9, 0xce, 0x82, 0xd3, 0x46, 0x5a, 0x62, 0x66, 0x89, 0xe4, 0xdc, 0xba, - 0x33, 0xa9, 0x8e, 0xad, 0x8e, 0xd0, 0x0b, 0x20, 0xaa, 0x30, 0x42, 0x0a, 0x2d, 0xdb, 0xf8, 0x6f, - 0xfd, 0x0b, 0xad, 0x7b, 0x11, 0x6a, 0xd5, 0x29, 0xd3, 0xd8, 0xf2, 0x5e, 0xb4, 0x48, 0xc3, 0xb9, - 0xa8, 0x4f, 0xfc, 0x07, 0x18, 0xd6, 0x53, 0x4b, 0x87, 0xd0, 0x45, 0xb3, 0x21, 0x1d, 0x3a, 0x82, - 0x9e, 0xdd, 0x19, 0xf1, 0x2c, 0x94, 0x1a, 0x4e, 0x7c, 0x7b, 0x6f, 0xf5, 0x59, 0x92, 0xae, 0x43, - 0x35, 0x27, 0x3d, 0x3a, 0x81, 0x51, 0xd3, 0x9c, 0xf4, 0xad, 0xcc, 0xb6, 0x20, 0x83, 0xda, 0xfa, - 0x15, 0x04, 0x8f, 0xfe, 0x10, 0xd6, 0xa2, 0x89, 0xe3, 0xe6, 0xa0, 0xd9, 0x99, 0xe7, 0xcc, 0x4b, - 0x71, 0xa8, 0xae, 0x11, 0x60, 0xb0, 0x46, 0x57, 0x77, 0x6b, 0x9f, 0x08, 0xfc, 0x6b, 0x69, 0x87, - 0x21, 0x57, 0xc9, 0x41, 0x92, 0x8e, 0x0b, 0x7a, 0x90, 0xc4, 0xab, 0xbf, 0x7f, 0x03, 0xe3, 0x76, - 0xf2, 0x6d, 0x24, 0x34, 0x1b, 0x2c, 0x71, 0x6f, 0x99, 0x53, 0x00, 0x83, 0xf9, 0x1a, 0x4b, 0x29, - 0xf2, 0xba, 0x53, 0x2a, 0x0c, 0x57, 0x22, 0x27, 0x7e, 0x95, 0x3e, 0xd1, 0x86, 0xf1, 0x6d, 0xdb, - 0xeb, 0x23, 0x08, 0x1e, 0x4d, 0x76, 0x75, 0x12, 0xae, 0xe7, 0x19, 0x8c, 0x55, 0xaa, 0xb1, 0x3c, - 0x60, 0xa9, 0x9b, 0xce, 0x5f, 0xae, 0x7e, 0xbf, 0x8f, 0xbc, 0xbb, 0xfb, 0xc8, 0xfb, 0xf3, 0x3e, - 0xf2, 0x7e, 0x79, 0x88, 0x3a, 0x77, 0x0f, 0x51, 0xe7, 0x8f, 0x87, 0xa8, 0xf3, 0xe3, 0x87, 0x99, - 0x30, 0x9b, 0x7d, 0xba, 0xe0, 0x4a, 0xba, 0x17, 0xf5, 0xe3, 0xff, 0x7c, 0x5c, 0xd3, 0x81, 0x7b, - 0x21, 0x3f, 0xfb, 0x27, 0x00, 0x00, 0xff, 0xff, 0x05, 0xa7, 0x7f, 0x40, 0x84, 0x05, 0x00, 0x00, + // 751 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x54, 0x4d, 0x8f, 0xe3, 0x34, + 0x18, 0x6e, 0x9a, 0xb6, 0x69, 0xdf, 0xcc, 0x87, 0xd7, 0x3b, 0x40, 0x58, 0x89, 0x32, 0x70, 0x80, + 0x61, 0x04, 0x1d, 0x01, 0x47, 0x2e, 0x88, 0x11, 0xbb, 0xe2, 0xc0, 0x1e, 0xc2, 0x6a, 0x85, 0xb8, + 0x04, 0xc7, 0x7d, 0x49, 0xad, 0xc6, 0x71, 0x14, 0xbb, 0xd9, 0x2d, 0xbf, 0x82, 0x1f, 0xc1, 0x01, + 0x89, 0x3f, 0xc2, 0x71, 0x8f, 0x1c, 0xd1, 0xcc, 0x81, 0xbf, 0x81, 0xec, 0x38, 0xe9, 0x72, 0x80, + 0x99, 0x53, 0xed, 0xa7, 0xcf, 0xf3, 0xbe, 0xcf, 0xfb, 0xe1, 0xc0, 0xe5, 0xcf, 0x68, 0x18, 0xdf, + 0x30, 0x51, 0x5d, 0xb9, 0x93, 0x6a, 0xf0, 0xaa, 0xde, 0x16, 0x57, 0x0e, 0xd2, 0xfe, 0x67, 0x55, + 0x37, 0xca, 0x28, 0xfa, 0xce, 0xc0, 0x5d, 0xf5, 0xdc, 0x55, 0xbd, 0x2d, 0x56, 0x1d, 0xe9, 0xd1, + 0x59, 0xa1, 0x0a, 0xe5, 0x98, 0x57, 0xf6, 0xd4, 0x89, 0xde, 0xff, 0x3b, 0x84, 0xe9, 0xb5, 0x25, + 0xd0, 0xb7, 0x61, 0xee, 0x98, 0x99, 0x58, 0x27, 0xe3, 0xf3, 0xe0, 0x22, 0x4c, 0x23, 0x77, 0xff, + 0x66, 0x4d, 0x9f, 0x00, 0x74, 0x7f, 0x55, 0x4c, 0x62, 0x12, 0x9c, 0x07, 0x17, 0x27, 0x9f, 0x5d, + 0xac, 0xfe, 0x37, 0xdd, 0xca, 0x05, 0x7d, 0xca, 0x24, 0xa6, 0x0b, 0xde, 0x1f, 0xe9, 0x97, 0x10, + 0x55, 0x68, 0x5e, 0xa8, 0x66, 0x9b, 0x84, 0x2e, 0xca, 0x07, 0x77, 0x44, 0x79, 0xda, 0xb1, 0xd3, + 0x5e, 0x46, 0xbf, 0x85, 0x23, 0x7f, 0xcc, 0xcc, 0xbe, 0xc6, 0x64, 0xe2, 0xc2, 0x5c, 0xde, 0x2f, + 0xcc, 0xb3, 0x7d, 0x8d, 0x69, 0x5c, 0x1d, 0x2e, 0xf4, 0x53, 0x18, 0xb7, 0x32, 0x99, 0xba, 0x20, + 0xef, 0xdd, 0x11, 0xe4, 0xb9, 0x4c, 0xc7, 0xad, 0xa4, 0x8f, 0x61, 0xc1, 0x55, 0xa5, 0xb1, 0xd2, + 0x3b, 0x9d, 0xcc, 0xee, 0xd7, 0x8b, 0x9e, 0x9f, 0x1e, 0xa4, 0xf4, 0x5d, 0x88, 0x85, 0xce, 0xf0, + 0xa5, 0xc1, 0xa6, 0x62, 0x65, 0x12, 0x9d, 0x07, 0x17, 0xf3, 0x14, 0x84, 0xfe, 0xda, 0x23, 0xb6, + 0x54, 0xce, 0xcd, 0xcb, 0xac, 0x60, 0x06, 0x5f, 0xb0, 0x7d, 0x32, 0xbf, 0x57, 0xa9, 0xd7, 0xd7, + 0xcf, 0xbe, 0x7f, 0xd2, 0x29, 0xd2, 0xd8, 0xea, 0xfd, 0xe5, 0xf2, 0x0b, 0x38, 0x4e, 0x91, 0xa3, + 0x68, 0xf1, 0x3b, 0xc3, 0xcc, 0x4e, 0xd3, 0x18, 0x22, 0xde, 0x20, 0x33, 0xb8, 0x26, 0x23, 0x7b, + 0xd1, 0x3b, 0xce, 0x51, 0x6b, 0x12, 0x50, 0x80, 0xd9, 0x4f, 0x4c, 0x94, 0xb8, 0x26, 0xe3, 0x47, + 0x93, 0xdf, 0x7e, 0x5d, 0x06, 0x97, 0xbf, 0x87, 0xb0, 0x18, 0x26, 0x4a, 0x17, 0x30, 0x45, 0x59, + 0x9b, 0x3d, 0x19, 0xd1, 0x53, 0x88, 0xd1, 0x6c, 0x32, 0xc9, 0x44, 0x55, 0xa1, 0x21, 0x01, 0x25, + 0x70, 0x64, 0x6d, 0x0d, 0xc8, 0xd8, 0x52, 0x72, 0xc3, 0x07, 0x20, 0xa4, 0x0f, 0xe1, 0xb4, 0x56, + 0xe5, 0xbe, 0x50, 0xd5, 0x00, 0x4e, 0x1c, 0x4b, 0x1f, 0x58, 0x53, 0x4a, 0xe1, 0xa4, 0x50, 0xd8, + 0x94, 0x22, 0x33, 0xa8, 0x8d, 0xc5, 0x66, 0x16, 0x93, 0x3b, 0x99, 0xb3, 0x03, 0x16, 0xf5, 0xc2, + 0x1e, 0x80, 0xc1, 0x41, 0x8f, 0xc4, 0xbd, 0x83, 0x1e, 0x38, 0xb2, 0x0e, 0x34, 0xd6, 0xaa, 0x14, + 0x07, 0xd6, 0xb1, 0x05, 0x7d, 0xc2, 0x52, 0x71, 0x56, 0x5a, 0xf0, 0xa4, 0x97, 0x36, 0x58, 0x58, + 0x22, 0x39, 0xb5, 0xd1, 0x99, 0x54, 0xfb, 0x41, 0x47, 0xe8, 0x19, 0x10, 0x55, 0x1b, 0x21, 0x85, + 0x96, 0x83, 0xfd, 0x07, 0xff, 0x42, 0x7d, 0x2e, 0x42, 0xad, 0x3a, 0x67, 0x1a, 0x07, 0xde, 0xc3, + 0x01, 0xe9, 0x39, 0x67, 0xb6, 0x48, 0xad, 0x4a, 0x56, 0x1d, 0x7a, 0xf8, 0x06, 0x7d, 0x00, 0xc7, + 0x1e, 0x5b, 0x63, 0x6b, 0xa1, 0x37, 0x5d, 0x0d, 0x1d, 0x34, 0xd8, 0x7d, 0xcb, 0x4f, 0x0b, 0x21, + 0xf2, 0x1b, 0x4f, 0x23, 0x08, 0xd1, 0x6c, 0xc8, 0x88, 0xce, 0x61, 0x62, 0xbb, 0x42, 0x02, 0x0b, + 0xe5, 0x86, 0x93, 0xb1, 0x9d, 0xb9, 0x9f, 0x03, 0x09, 0x1d, 0xaa, 0x39, 0x99, 0xd0, 0x23, 0x98, + 0xf7, 0xc6, 0xc9, 0xd4, 0xca, 0xac, 0x3d, 0x32, 0xb3, 0x4b, 0xd1, 0xe5, 0x23, 0x91, 0x4f, 0xf3, + 0x18, 0xe2, 0xd7, 0x1e, 0x96, 0x0d, 0xd7, 0x1b, 0x76, 0xfb, 0xd4, 0x77, 0x28, 0x70, 0x89, 0x1a, + 0xd1, 0x76, 0xeb, 0x00, 0x30, 0xf3, 0x35, 0x84, 0x3e, 0xce, 0x87, 0x30, 0x7e, 0x2e, 0xed, 0x52, + 0x55, 0x2a, 0x6b, 0x25, 0x19, 0x39, 0xd3, 0xad, 0xec, 0xac, 0xea, 0x56, 0x0e, 0x5b, 0xf8, 0x23, + 0x2c, 0x86, 0xa7, 0x64, 0x7d, 0xa2, 0xd9, 0x60, 0x83, 0x3b, 0x2b, 0x39, 0x01, 0x30, 0x58, 0xad, + 0xb1, 0x91, 0xa2, 0xf2, 0x29, 0x73, 0x61, 0xb8, 0x12, 0x15, 0x19, 0x77, 0x25, 0x65, 0xda, 0x30, + 0xbe, 0x25, 0xa1, 0x9d, 0x8c, 0x6f, 0xdc, 0xf0, 0x18, 0xc9, 0xc4, 0x67, 0xf8, 0x18, 0xe2, 0xd7, + 0x1e, 0x50, 0xd7, 0x34, 0x67, 0xe9, 0x18, 0x16, 0x2a, 0xd7, 0xd8, 0xb4, 0xd8, 0x68, 0x12, 0x74, + 0xec, 0xaf, 0xae, 0xff, 0xb8, 0x59, 0x06, 0xaf, 0x6e, 0x96, 0xc1, 0x5f, 0x37, 0xcb, 0xe0, 0x97, + 0xdb, 0xe5, 0xe8, 0xd5, 0xed, 0x72, 0xf4, 0xe7, 0xed, 0x72, 0xf4, 0xc3, 0x47, 0x85, 0x30, 0x9b, + 0x5d, 0xbe, 0xe2, 0x4a, 0xba, 0x0f, 0xf7, 0x27, 0xff, 0xf9, 0x0d, 0xcf, 0x67, 0xee, 0x43, 0xfc, + 0xf9, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x26, 0xaa, 0x81, 0xba, 0xeb, 0x05, 0x00, 0x00, } func (m *Chain) Marshal() (dAtA []byte, err error) { diff --git a/pkg/chains/chains_test.go b/pkg/chains/chains_test.go index dffb630086..fe947b11be 100644 --- a/pkg/chains/chains_test.go +++ b/pkg/chains/chains_test.go @@ -1,59 +1,64 @@ -package chains +package chains_test import ( "testing" "github.com/stretchr/testify/require" + "github.com/zeta-chain/zetacore/pkg/chains" + "github.com/zeta-chain/zetacore/testutil/sample" ) func TestChainListByNetworkType(t *testing.T) { listTests := []struct { name string - networkType NetworkType - expected []*Chain + networkType chains.NetworkType + expected []chains.Chain }{ { "mainnet chains", - NetworkType_mainnet, - []*Chain{ - &ZetaChainMainnet, - &BitcoinMainnet, - &BscMainnet, - &Ethereum, - &Polygon, - &OptimismMainnet, - &BaseMainnet, + chains.NetworkType_mainnet, + []chains.Chain{ + chains.ZetaChainMainnet, + chains.BitcoinMainnet, + chains.BscMainnet, + chains.Ethereum, + chains.Polygon, + chains.OptimismMainnet, + chains.BaseMainnet, + chains.SolanaMainnet, }, }, { "testnet chains", - NetworkType_testnet, - []*Chain{ - &ZetaChainTestnet, - &BitcoinTestnet, - &Mumbai, - &Amoy, - &BscTestnet, - &Goerli, - &Sepolia, - &OptimismSepolia, - &BaseSepolia, + chains.NetworkType_testnet, + []chains.Chain{ + chains.ZetaChainTestnet, + chains.BitcoinTestnet, + chains.Mumbai, + chains.Amoy, + chains.BscTestnet, + chains.Goerli, + chains.Sepolia, + chains.OptimismSepolia, + chains.BaseSepolia, + chains.SolanaDevnet, }, }, { "privnet chains", - NetworkType_privnet, - []*Chain{ - &ZetaChainPrivnet, - &BitcoinRegtest, - &GoerliLocalnet, + chains.NetworkType_privnet, + []chains.Chain{ + chains.ZetaChainPrivnet, + chains.BitcoinRegtest, + chains.GoerliLocalnet, + chains.SolanaLocalnet, }, }, } for _, lt := range listTests { t.Run(lt.name, func(t *testing.T) { - require.ElementsMatch(t, lt.expected, ChainListByNetworkType(lt.networkType)) + require.ElementsMatch(t, lt.expected, chains.ChainListByNetworkType(lt.networkType, []chains.Chain{})) }) } } @@ -61,167 +66,220 @@ func TestChainListByNetworkType(t *testing.T) { func TestChainListByNetwork(t *testing.T) { listTests := []struct { name string - network Network - expected []*Chain + network chains.Network + expected []chains.Chain }{ { "Zeta", - Network_zeta, - []*Chain{&ZetaChainMainnet, &ZetaChainDevnet, &ZetaChainPrivnet, &ZetaChainTestnet}, + chains.Network_zeta, + []chains.Chain{ + chains.ZetaChainMainnet, + chains.ZetaChainDevnet, + chains.ZetaChainPrivnet, + chains.ZetaChainTestnet, + }, }, { "Btc", - Network_btc, - []*Chain{&BitcoinMainnet, &BitcoinTestnet, &BitcoinRegtest}, + chains.Network_btc, + []chains.Chain{chains.BitcoinMainnet, chains.BitcoinTestnet, chains.BitcoinRegtest}, }, { "Eth", - Network_eth, - []*Chain{&Ethereum, &Goerli, &Sepolia, &GoerliLocalnet}, + chains.Network_eth, + []chains.Chain{chains.Ethereum, chains.Goerli, chains.Sepolia, chains.GoerliLocalnet}, }, { "Bsc", - Network_bsc, - []*Chain{&BscMainnet, &BscTestnet}, + chains.Network_bsc, + []chains.Chain{chains.BscMainnet, chains.BscTestnet}, }, { "Polygon", - Network_polygon, - []*Chain{&Polygon, &Mumbai, &Amoy}, + chains.Network_polygon, + []chains.Chain{chains.Polygon, chains.Mumbai, chains.Amoy}, }, { "Optimism", - Network_optimism, - []*Chain{&OptimismMainnet, &OptimismSepolia}, + chains.Network_optimism, + []chains.Chain{chains.OptimismMainnet, chains.OptimismSepolia}, }, { "Base", - Network_base, - []*Chain{&BaseMainnet, &BaseSepolia}, + chains.Network_base, + []chains.Chain{chains.BaseMainnet, chains.BaseSepolia}, }, - } - - for _, lt := range listTests { - t.Run(lt.name, func(t *testing.T) { - require.ElementsMatch(t, lt.expected, ChainListByNetwork(lt.network)) - }) - } -} -func TestChainListFunctions(t *testing.T) { - listTests := []struct { - name string - function func() []*Chain - expected []*Chain - }{ { - "DefaultChainsList", - DefaultChainsList, - []*Chain{ - &BitcoinMainnet, - &BscMainnet, - &Ethereum, - &BitcoinTestnet, - &Mumbai, - &Amoy, - &BscTestnet, - &Goerli, - &Sepolia, - &BitcoinRegtest, - &GoerliLocalnet, - &ZetaChainMainnet, - &ZetaChainTestnet, - &ZetaChainDevnet, - &ZetaChainPrivnet, - &Polygon, - &OptimismMainnet, - &OptimismSepolia, - &BaseMainnet, - &BaseSepolia, - }, - }, - { - "ExternalChainList", - ExternalChainList, - []*Chain{ - &BitcoinMainnet, - &BscMainnet, - &Ethereum, - &BitcoinTestnet, - &Mumbai, - &Amoy, - &BscTestnet, - &Goerli, - &Sepolia, - &BitcoinRegtest, - &GoerliLocalnet, - &Polygon, - &OptimismMainnet, - &OptimismSepolia, - &BaseMainnet, - &BaseSepolia, - }, + "Solana", + chains.Network_solana, + []chains.Chain{chains.SolanaMainnet, chains.SolanaDevnet, chains.SolanaLocalnet}, }, } for _, lt := range listTests { t.Run(lt.name, func(t *testing.T) { - chains := lt.function() - require.ElementsMatch(t, lt.expected, chains) + require.ElementsMatch(t, lt.expected, chains.ChainListByNetwork(lt.network, []chains.Chain{})) }) } } -func TestZetaChainFromChainID(t *testing.T) { +func TestDefaultChainList(t *testing.T) { + require.ElementsMatch(t, []chains.Chain{ + chains.BitcoinMainnet, + chains.BscMainnet, + chains.Ethereum, + chains.BitcoinTestnet, + chains.Mumbai, + chains.Amoy, + chains.BscTestnet, + chains.Goerli, + chains.Sepolia, + chains.BitcoinRegtest, + chains.GoerliLocalnet, + chains.ZetaChainMainnet, + chains.ZetaChainTestnet, + chains.ZetaChainDevnet, + chains.ZetaChainPrivnet, + chains.Polygon, + chains.OptimismMainnet, + chains.OptimismSepolia, + chains.BaseMainnet, + chains.BaseSepolia, + chains.SolanaMainnet, + chains.SolanaDevnet, + chains.SolanaLocalnet, + }, chains.DefaultChainsList()) +} + +func TestExternalChainList(t *testing.T) { + require.ElementsMatch(t, []chains.Chain{ + chains.BitcoinMainnet, + chains.BscMainnet, + chains.Ethereum, + chains.BitcoinTestnet, + chains.Mumbai, + chains.Amoy, + chains.BscTestnet, + chains.Goerli, + chains.Sepolia, + chains.BitcoinRegtest, + chains.GoerliLocalnet, + chains.Polygon, + chains.OptimismMainnet, + chains.OptimismSepolia, + chains.BaseMainnet, + chains.BaseSepolia, + chains.SolanaMainnet, + chains.SolanaDevnet, + chains.SolanaLocalnet, + }, chains.ExternalChainList([]chains.Chain{})) +} + +func TestZetaChainFromCosmosChainID(t *testing.T) { tests := []struct { name string chainID string - expected Chain + expected chains.Chain wantErr bool }{ { name: "ZetaChainMainnet", chainID: "cosmoshub_7000-1", - expected: ZetaChainMainnet, + expected: chains.ZetaChainMainnet, wantErr: false, }, { name: "ZetaChainTestnet", chainID: "cosmoshub_7001-1", - expected: ZetaChainTestnet, + expected: chains.ZetaChainTestnet, wantErr: false, }, { name: "ZetaChainDevnet", chainID: "cosmoshub_70000-1", - expected: ZetaChainDevnet, + expected: chains.ZetaChainDevnet, wantErr: false, }, { name: "ZetaChainPrivnet", chainID: "cosmoshub_101-1", - expected: ZetaChainPrivnet, + expected: chains.ZetaChainPrivnet, wantErr: false, }, { name: "unknown chain", chainID: "cosmoshub_1234-1", - expected: Chain{}, + expected: chains.Chain{}, wantErr: true, }, { name: "invalid chain id", chainID: "cosmoshub_abc-1", - expected: Chain{}, + expected: chains.Chain{}, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result, err := chains.ZetaChainFromCosmosChainID(tt.chainID) + if tt.wantErr { + require.Error(t, err) + require.Equal(t, chains.Chain{}, result) + } else { + require.NoError(t, err) + require.Equal(t, tt.expected, result) + } + }) + } +} + +func TestZetaChainFromChainID(t *testing.T) { + tests := []struct { + name string + chainID int64 + expected chains.Chain + wantErr bool + }{ + { + name: "ZetaChainMainnet", + chainID: 7000, + expected: chains.ZetaChainMainnet, + wantErr: false, + }, + { + name: "ZetaChainTestnet", + chainID: 7001, + expected: chains.ZetaChainTestnet, + wantErr: false, + }, + { + name: "ZetaChainDevnet", + chainID: 70000, + expected: chains.ZetaChainDevnet, + wantErr: false, + }, + { + name: "ZetaChainPrivnet", + chainID: 101, + expected: chains.ZetaChainPrivnet, + wantErr: false, + }, + { + name: "unknown chain", + chainID: 1234, + expected: chains.Chain{}, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - result, err := ZetaChainFromChainID(tt.chainID) + result, err := chains.ZetaChainFromChainID(tt.chainID) if tt.wantErr { require.Error(t, err) - require.Equal(t, Chain{}, result) + require.ErrorIs(t, err, chains.ErrNotZetaChain) + require.Equal(t, chains.Chain{}, result) } else { require.NoError(t, err) require.Equal(t, tt.expected, result) @@ -229,3 +287,119 @@ func TestZetaChainFromChainID(t *testing.T) { }) } } + +func TestCombineDefaultChainsList(t *testing.T) { + // prepare array containing pre-defined chains + // chain IDs are 11000 - 11009 to not conflict with the default chains + var chainList = make([]chains.Chain, 0, 10) + for i := int64(11000); i < 10; i++ { + chainList = append(chainList, sample.Chain(i)) + } + + bitcoinMainnetChainID := chains.BitcoinMainnet.ChainId + require.Equal( + t, + bitcoinMainnetChainID, + chains.DefaultChainsList()[0].ChainId, + "Bitcoin mainnet be the first in the default chain list for TestCombineDefaultChainsList tests", + ) + alternativeBitcoinMainnet := sample.Chain(bitcoinMainnetChainID) + + tests := []struct { + name string + list []chains.Chain + expected []chains.Chain + }{ + { + name: "empty list", + list: []chains.Chain{}, + expected: chains.DefaultChainsList(), + }, + { + name: "no duplicates", + list: chainList, + expected: append(chains.DefaultChainsList(), chainList...), + }, + { + name: "duplicates", + list: []chains.Chain{alternativeBitcoinMainnet}, + expected: append(chains.DefaultChainsList()[1:], alternativeBitcoinMainnet), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + require.ElementsMatch(t, tt.expected, chains.CombineDefaultChainsList(tt.list)) + }) + } +} + +func TestCombineChainList(t *testing.T) { + // prepare array containing pre-defined chains + var chainList = make([]chains.Chain, 0, 10) + for i := int64(0); i < 10; i++ { + chainList = append(chainList, sample.Chain(i)) + } + + // prepare second array for duplicated chain IDs + var duplicatedChainList = make([]chains.Chain, 0, 10) + for i := int64(0); i < 10; i++ { + duplicatedChainList = append(duplicatedChainList, sample.Chain(i)) + } + + tests := []struct { + name string + list1 []chains.Chain + list2 []chains.Chain + expected []chains.Chain + }{ + { + name: "empty lists", + list1: []chains.Chain{}, + list2: []chains.Chain{}, + expected: []chains.Chain{}, + }, + { + name: "empty list 1", + list1: []chains.Chain{}, + list2: chainList, + expected: chainList, + }, + { + name: "empty list 2", + list1: chainList, + list2: []chains.Chain{}, + expected: chainList, + }, + { + name: "no duplicates", + list1: chainList[:5], + list2: chainList[5:], + expected: chainList, + }, + { + name: "all duplicates", + list1: chainList, + list2: duplicatedChainList, + expected: duplicatedChainList, + }, + { + name: "some duplicates", + list1: chainList[:5], + list2: duplicatedChainList[3:], + expected: append(chainList[:3], duplicatedChainList[3:]...), + }, + { + name: "one duplicate", + list1: chainList[:5], + list2: append(chainList[5:], duplicatedChainList[0]), + expected: append(chainList[1:], duplicatedChainList[0]), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + require.ElementsMatch(t, tt.expected, chains.CombineChainList(tt.list1, tt.list2)) + }) + } +} diff --git a/pkg/chains/conversion.go b/pkg/chains/conversion.go index 200061c3ae..84b3eaf3aa 100644 --- a/pkg/chains/conversion.go +++ b/pkg/chains/conversion.go @@ -8,31 +8,17 @@ import ( ethcommon "github.com/ethereum/go-ethereum/common" ) -// A very special value to mark current nonce in UTXO +// NonceMarkAmount uses special value to mark current nonce in UTXO func NonceMarkAmount(nonce uint64) int64 { // #nosec G701 always in range return int64(nonce) + BtcNonceMarkOffset() } -// HashToString convert hash bytes to string -func HashToString(chainID int64, blockHash []byte) (string, error) { - if IsEVMChain(chainID) { - return hex.EncodeToString(blockHash), nil - } else if IsBitcoinChain(chainID) { - hash, err := chainhash.NewHash(blockHash) - if err != nil { - return "", err - } - return hash.String(), nil - } - return "", fmt.Errorf("cannot convert hash to string for chain %d", chainID) -} - // StringToHash convert string to hash bytes -func StringToHash(chainID int64, hash string) ([]byte, error) { - if IsEVMChain(chainID) { +func StringToHash(chainID int64, hash string, additionalChains []Chain) ([]byte, error) { + if IsEVMChain(chainID, additionalChains) { return ethcommon.HexToHash(hash).Bytes(), nil - } else if IsBitcoinChain(chainID) { + } else if IsBitcoinChain(chainID, additionalChains) { hash, err := chainhash.NewHashFromStr(hash) if err != nil { return nil, err diff --git a/pkg/chains/utils_test.go b/pkg/chains/utils_test.go index cb025e025b..915fa2b8ca 100644 --- a/pkg/chains/utils_test.go +++ b/pkg/chains/utils_test.go @@ -27,41 +27,6 @@ func TestNonceMarkAmount(t *testing.T) { } } -func TestHashToString(t *testing.T) { - evmChainId := int64(5) - btcChainId := int64(8332) - unknownChainId := int64(3) - mockEthBlockHash := []byte("0xc2339489a45f8976d45482ad6fa08751a1eae91f92d60645521ca0aff2422639") - mockBtcBlockHash := []byte("00000000000000000002dcaa3853ac587d4cafdd0aa1fff45942ab5798f29afd") - expectedBtcHash, err := chainhash.NewHashFromStr("00000000000000000002dcaa3853ac587d4cafdd0aa1fff45942ab5798f29afd") - require.NoError(t, err) - - tests := []struct { - name string - chainID int64 - blockHash []byte - expect string - wantErr bool - }{ - {"evm chain", evmChainId, mockEthBlockHash, hex.EncodeToString(mockEthBlockHash), false}, - {"btc chain", btcChainId, expectedBtcHash.CloneBytes(), expectedBtcHash.String(), false}, - {"btc chain invalid hash", btcChainId, mockBtcBlockHash, "", true}, - {"unknown chain", unknownChainId, mockEthBlockHash, "", true}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - result, err := HashToString(tt.chainID, tt.blockHash) - if tt.wantErr { - require.Error(t, err) - } else { - require.NoError(t, err) - require.Equal(t, tt.expect, result) - } - }) - } -} - func TestStringToHash(t *testing.T) { evmChainId := int64(5) btcChainId := int64(8332) @@ -91,7 +56,7 @@ func TestStringToHash(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - result, err := StringToHash(tt.chainID, tt.hash) + result, err := StringToHash(tt.chainID, tt.hash, []Chain{}) if tt.wantErr { require.Error(t, err) } else { diff --git a/pkg/crypto/pubkey.go b/pkg/crypto/pubkey.go index 8c893664b0..545e5367ed 100644 --- a/pkg/crypto/pubkey.go +++ b/pkg/crypto/pubkey.go @@ -71,7 +71,7 @@ func (pubKey PubKey) String() string { // GetAddress will return an address for the given chain func (pubKey PubKey) GetAddress(chain chains.Chain) (chains.Address, error) { - if chains.IsEVMChain(chain.ChainId) { + if chain.IsEVMChain() { return pubKey.GetEVMAddress() } return chains.NoAddress, nil diff --git a/proto/zetachain/zetacore/observer/observer.proto b/proto/zetachain/zetacore/observer/observer.proto index 240f0025f0..7fc6eb5b7b 100644 --- a/proto/zetachain/zetacore/observer/observer.proto +++ b/proto/zetachain/zetacore/observer/observer.proto @@ -2,7 +2,6 @@ syntax = "proto3"; package zetachain.zetacore.observer; import "gogoproto/gogo.proto"; -import "zetachain/zetacore/pkg/chains/chains.proto"; option go_package = "github.com/zeta-chain/zetacore/x/observer/types"; diff --git a/proto/zetachain/zetacore/observer/params.proto b/proto/zetachain/zetacore/observer/params.proto index 1eb096fc0c..c0c732b705 100644 --- a/proto/zetachain/zetacore/observer/params.proto +++ b/proto/zetachain/zetacore/observer/params.proto @@ -3,7 +3,6 @@ package zetachain.zetacore.observer; import "gogoproto/gogo.proto"; import "zetachain/zetacore/observer/observer.proto"; -import "zetachain/zetacore/pkg/chains/chains.proto"; option go_package = "github.com/zeta-chain/zetacore/x/observer/types"; @@ -30,6 +29,7 @@ message ChainParams { (gogoproto.nullable) = false ]; bool is_supported = 16; + string gateway_address = 17; } // Deprecated(v17) diff --git a/proto/zetachain/zetacore/observer/query.proto b/proto/zetachain/zetacore/observer/query.proto index 799bc1efb9..9ad1d71356 100644 --- a/proto/zetachain/zetacore/observer/query.proto +++ b/proto/zetachain/zetacore/observer/query.proto @@ -263,7 +263,9 @@ message QueryObserverSetResponse { repeated string observers = 1; } message QuerySupportedChains {} -message QuerySupportedChainsResponse { repeated pkg.chains.Chain chains = 1; } +message QuerySupportedChainsResponse { + repeated pkg.chains.Chain chains = 1 [ (gogoproto.nullable) = false ]; +} message QueryGetChainParamsForChainRequest { int64 chain_id = 1; } diff --git a/proto/zetachain/zetacore/pkg/chains/chains.proto b/proto/zetachain/zetacore/pkg/chains/chains.proto index 8075822471..137d056713 100644 --- a/proto/zetachain/zetacore/pkg/chains/chains.proto +++ b/proto/zetachain/zetacore/pkg/chains/chains.proto @@ -43,6 +43,10 @@ enum ChainName { optimism_sepolia = 18; base_mainnet = 19; base_sepolia = 20; + + solana_mainnet = 21; + solana_devnet = 22; + solana_localnet = 23; } // Network represents the network of the chain @@ -57,6 +61,7 @@ enum Network { bsc = 4; optimism = 5; base = 6; + solana = 7; } // NetworkType represents the network type of the chain @@ -75,6 +80,7 @@ enum Vm { option (gogoproto.goproto_enum_stringer) = true; no_vm = 0; evm = 1; + svm = 2; } // Consensus represents the consensus algorithm used by the chain @@ -86,6 +92,7 @@ enum Consensus { tendermint = 1; bitcoin = 2; op_stack = 3; + solana_consensus = 4; } // CCTXGateway describes for the chain the gateway used to handle CCTX outbounds diff --git a/testutil/keeper/authority.go b/testutil/keeper/authority.go index 1e61bf9881..169b6df526 100644 --- a/testutil/keeper/authority.go +++ b/testutil/keeper/authority.go @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + "github.com/zeta-chain/zetacore/pkg/chains" "github.com/zeta-chain/zetacore/testutil/sample" "github.com/zeta-chain/zetacore/x/authority/keeper" "github.com/zeta-chain/zetacore/x/authority/types" @@ -79,6 +80,16 @@ func MockCheckAuthorization(m *mock.Mock, msg sdk.Msg, authorizationResult error m.On("CheckAuthorization", mock.Anything, msg).Return(authorizationResult).Once() } +// MockGetChainList mocks the GetAdditionalChainList method of the authority keeper. +func MockGetChainList(m *mock.Mock, chainList []chains.Chain) { + m.On("GetAdditionalChainList", mock.Anything).Return(chainList).Once() +} + +// MockGetChainListEmpty mocks the GetAdditionalChainList method of the authority keeper. +func MockGetChainListEmpty(m *mock.Mock) { + m.On("GetAdditionalChainList", mock.Anything).Return([]chains.Chain{}) +} + func SetAdminPolicies(ctx sdk.Context, ak *keeper.Keeper) string { admin := sample.AccAddress() ak.SetPolicies(ctx, types.Policies{Items: []*types.Policy{ diff --git a/testutil/keeper/crosschain.go b/testutil/keeper/crosschain.go index d2b1bc1d5b..140a9538c5 100644 --- a/testutil/keeper/crosschain.go +++ b/testutil/keeper/crosschain.go @@ -261,24 +261,14 @@ func GetCrosschainFungibleMock(t testing.TB, keeper *keeper.Keeper) *crosschainm return cfk } -func MockGetSupportedChainFromChainID(m *crosschainmocks.CrosschainObserverKeeper, senderChain *chains.Chain) { - if senderChain != nil { - m.On("GetSupportedChainFromChainID", mock.Anything, senderChain.ChainId). - Return(senderChain).Once() - } else { - m.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything). - Return(&chains.Chain{}).Once() - } +func MockGetSupportedChainFromChainID(m *crosschainmocks.CrosschainObserverKeeper, senderChain chains.Chain) { + m.On("GetSupportedChainFromChainID", mock.Anything, senderChain.ChainId). + Return(senderChain, true).Once() } -func MockFailedGetSupportedChainFromChainID(m *crosschainmocks.CrosschainObserverKeeper, senderChain *chains.Chain) { - if senderChain != nil { - m.On("GetSupportedChainFromChainID", mock.Anything, senderChain.ChainId). - Return(nil).Once() - } else { - m.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything). - Return(nil).Once() - } +func MockFailedGetSupportedChainFromChainID(m *crosschainmocks.CrosschainObserverKeeper, senderChain chains.Chain) { + m.On("GetSupportedChainFromChainID", mock.Anything, senderChain.ChainId). + Return(chains.Chain{}, false).Once() } func MockGetRevertGasLimitForERC20( @@ -304,7 +294,7 @@ func MockPayGasAndUpdateCCTX( asset string, ) { m2.On("GetSupportedChainFromChainID", mock.Anything, senderChain.ChainId). - Return(&senderChain).Twice() + Return(senderChain, true).Twice() m.On("GetForeignCoinFromAsset", mock.Anything, asset, senderChain.ChainId). Return(fungibletypes.ForeignCoins{ Zrc20ContractAddress: sample.EthAddress().String(), @@ -340,7 +330,7 @@ func MockUpdateNonce(m *crosschainmocks.CrosschainObserverKeeper, senderChain ch nonce = uint64(1) tss := sample.Tss() m.On("GetSupportedChainFromChainID", mock.Anything, senderChain.ChainId). - Return(senderChain) + Return(senderChain, true).Once() m.On("GetChainNonces", mock.Anything, senderChain.ChainName.String()). Return(observertypes.ChainNonces{Nonce: nonce}, true) m.On("GetTSS", mock.Anything). diff --git a/testutil/keeper/mocks/crosschain/account.go b/testutil/keeper/mocks/crosschain/account.go index fbd7c0377b..e2d05b0425 100644 --- a/testutil/keeper/mocks/crosschain/account.go +++ b/testutil/keeper/mocks/crosschain/account.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.38.0. DO NOT EDIT. +// Code generated by mockery v2.42.2. DO NOT EDIT. package mocks diff --git a/testutil/keeper/mocks/crosschain/authority.go b/testutil/keeper/mocks/crosschain/authority.go index 59edbd6d2d..1f01f4c694 100644 --- a/testutil/keeper/mocks/crosschain/authority.go +++ b/testutil/keeper/mocks/crosschain/authority.go @@ -1,9 +1,10 @@ -// Code generated by mockery v2.38.0. DO NOT EDIT. +// Code generated by mockery v2.42.2. DO NOT EDIT. package mocks import ( mock "github.com/stretchr/testify/mock" + chains "github.com/zeta-chain/zetacore/pkg/chains" types "github.com/cosmos/cosmos-sdk/types" ) @@ -31,6 +32,26 @@ func (_m *CrosschainAuthorityKeeper) CheckAuthorization(ctx types.Context, msg t return r0 } +// GetAdditionalChainList provides a mock function with given fields: ctx +func (_m *CrosschainAuthorityKeeper) GetAdditionalChainList(ctx types.Context) []chains.Chain { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for GetAdditionalChainList") + } + + var r0 []chains.Chain + if rf, ok := ret.Get(0).(func(types.Context) []chains.Chain); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]chains.Chain) + } + } + + return r0 +} + // NewCrosschainAuthorityKeeper creates a new instance of CrosschainAuthorityKeeper. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. func NewCrosschainAuthorityKeeper(t interface { diff --git a/testutil/keeper/mocks/crosschain/bank.go b/testutil/keeper/mocks/crosschain/bank.go index 90f4e17e29..5bba791ed5 100644 --- a/testutil/keeper/mocks/crosschain/bank.go +++ b/testutil/keeper/mocks/crosschain/bank.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.38.0. DO NOT EDIT. +// Code generated by mockery v2.42.2. DO NOT EDIT. package mocks diff --git a/testutil/keeper/mocks/crosschain/fungible.go b/testutil/keeper/mocks/crosschain/fungible.go index 9eab868481..a889b153df 100644 --- a/testutil/keeper/mocks/crosschain/fungible.go +++ b/testutil/keeper/mocks/crosschain/fungible.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.38.0. DO NOT EDIT. +// Code generated by mockery v2.42.2. DO NOT EDIT. package mocks diff --git a/testutil/keeper/mocks/crosschain/ibccrosschain.go b/testutil/keeper/mocks/crosschain/ibccrosschain.go index 177c8ec395..17e407f0c0 100644 --- a/testutil/keeper/mocks/crosschain/ibccrosschain.go +++ b/testutil/keeper/mocks/crosschain/ibccrosschain.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.38.0. DO NOT EDIT. +// Code generated by mockery v2.42.2. DO NOT EDIT. package mocks diff --git a/testutil/keeper/mocks/crosschain/lightclient.go b/testutil/keeper/mocks/crosschain/lightclient.go index d5ee740bc3..14296a330c 100644 --- a/testutil/keeper/mocks/crosschain/lightclient.go +++ b/testutil/keeper/mocks/crosschain/lightclient.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.38.0. DO NOT EDIT. +// Code generated by mockery v2.42.2. DO NOT EDIT. package mocks diff --git a/testutil/keeper/mocks/crosschain/observer.go b/testutil/keeper/mocks/crosschain/observer.go index d504d1a9c8..236e8775fa 100644 --- a/testutil/keeper/mocks/crosschain/observer.go +++ b/testutil/keeper/mocks/crosschain/observer.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.38.0. DO NOT EDIT. +// Code generated by mockery v2.42.2. DO NOT EDIT. package mocks @@ -110,7 +110,7 @@ func (_m *CrosschainObserverKeeper) CheckIfTssPubkeyHasBeenGenerated(ctx types.C } // FindBallot provides a mock function with given fields: ctx, index, chain, observationType -func (_m *CrosschainObserverKeeper) FindBallot(ctx types.Context, index string, chain *chains.Chain, observationType observertypes.ObservationType) (observertypes.Ballot, bool, error) { +func (_m *CrosschainObserverKeeper) FindBallot(ctx types.Context, index string, chain chains.Chain, observationType observertypes.ObservationType) (observertypes.Ballot, bool, error) { ret := _m.Called(ctx, index, chain, observationType) if len(ret) == 0 { @@ -120,22 +120,22 @@ func (_m *CrosschainObserverKeeper) FindBallot(ctx types.Context, index string, var r0 observertypes.Ballot var r1 bool var r2 error - if rf, ok := ret.Get(0).(func(types.Context, string, *chains.Chain, observertypes.ObservationType) (observertypes.Ballot, bool, error)); ok { + if rf, ok := ret.Get(0).(func(types.Context, string, chains.Chain, observertypes.ObservationType) (observertypes.Ballot, bool, error)); ok { return rf(ctx, index, chain, observationType) } - if rf, ok := ret.Get(0).(func(types.Context, string, *chains.Chain, observertypes.ObservationType) observertypes.Ballot); ok { + if rf, ok := ret.Get(0).(func(types.Context, string, chains.Chain, observertypes.ObservationType) observertypes.Ballot); ok { r0 = rf(ctx, index, chain, observationType) } else { r0 = ret.Get(0).(observertypes.Ballot) } - if rf, ok := ret.Get(1).(func(types.Context, string, *chains.Chain, observertypes.ObservationType) bool); ok { + if rf, ok := ret.Get(1).(func(types.Context, string, chains.Chain, observertypes.ObservationType) bool); ok { r1 = rf(ctx, index, chain, observationType) } else { r1 = ret.Get(1).(bool) } - if rf, ok := ret.Get(2).(func(types.Context, string, *chains.Chain, observertypes.ObservationType) error); ok { + if rf, ok := ret.Get(2).(func(types.Context, string, chains.Chain, observertypes.ObservationType) error); ok { r2 = rf(ctx, index, chain, observationType) } else { r2 = ret.Error(2) @@ -557,39 +557,47 @@ func (_m *CrosschainObserverKeeper) GetPendingNonces(ctx types.Context, tss stri } // GetSupportedChainFromChainID provides a mock function with given fields: ctx, chainID -func (_m *CrosschainObserverKeeper) GetSupportedChainFromChainID(ctx types.Context, chainID int64) *chains.Chain { +func (_m *CrosschainObserverKeeper) GetSupportedChainFromChainID(ctx types.Context, chainID int64) (chains.Chain, bool) { ret := _m.Called(ctx, chainID) if len(ret) == 0 { panic("no return value specified for GetSupportedChainFromChainID") } - var r0 *chains.Chain - if rf, ok := ret.Get(0).(func(types.Context, int64) *chains.Chain); ok { + var r0 chains.Chain + var r1 bool + if rf, ok := ret.Get(0).(func(types.Context, int64) (chains.Chain, bool)); ok { + return rf(ctx, chainID) + } + if rf, ok := ret.Get(0).(func(types.Context, int64) chains.Chain); ok { r0 = rf(ctx, chainID) } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*chains.Chain) - } + r0 = ret.Get(0).(chains.Chain) } - return r0 + if rf, ok := ret.Get(1).(func(types.Context, int64) bool); ok { + r1 = rf(ctx, chainID) + } else { + r1 = ret.Get(1).(bool) + } + + return r0, r1 } // GetSupportedChains provides a mock function with given fields: ctx -func (_m *CrosschainObserverKeeper) GetSupportedChains(ctx types.Context) []*chains.Chain { +func (_m *CrosschainObserverKeeper) GetSupportedChains(ctx types.Context) []chains.Chain { ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for GetSupportedChains") } - var r0 []*chains.Chain - if rf, ok := ret.Get(0).(func(types.Context) []*chains.Chain); ok { + var r0 []chains.Chain + if rf, ok := ret.Get(0).(func(types.Context) []chains.Chain); ok { r0 = rf(ctx) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]*chains.Chain) + r0 = ret.Get(0).([]chains.Chain) } } @@ -597,19 +605,19 @@ func (_m *CrosschainObserverKeeper) GetSupportedChains(ctx types.Context) []*cha } // GetSupportedForeignChains provides a mock function with given fields: ctx -func (_m *CrosschainObserverKeeper) GetSupportedForeignChains(ctx types.Context) []*chains.Chain { +func (_m *CrosschainObserverKeeper) GetSupportedForeignChains(ctx types.Context) []chains.Chain { ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for GetSupportedForeignChains") } - var r0 []*chains.Chain - if rf, ok := ret.Get(0).(func(types.Context) []*chains.Chain); ok { + var r0 []chains.Chain + if rf, ok := ret.Get(0).(func(types.Context) []chains.Chain); ok { r0 = rf(ctx) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]*chains.Chain) + r0 = ret.Get(0).([]chains.Chain) } } diff --git a/testutil/keeper/mocks/crosschain/staking.go b/testutil/keeper/mocks/crosschain/staking.go index 5b7d3c501f..f8fcba918b 100644 --- a/testutil/keeper/mocks/crosschain/staking.go +++ b/testutil/keeper/mocks/crosschain/staking.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.38.0. DO NOT EDIT. +// Code generated by mockery v2.42.2. DO NOT EDIT. package mocks diff --git a/testutil/keeper/mocks/emissions/account.go b/testutil/keeper/mocks/emissions/account.go index a660d40e72..3468f329f1 100644 --- a/testutil/keeper/mocks/emissions/account.go +++ b/testutil/keeper/mocks/emissions/account.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.38.0. DO NOT EDIT. +// Code generated by mockery v2.42.2. DO NOT EDIT. package mocks diff --git a/testutil/keeper/mocks/emissions/bank.go b/testutil/keeper/mocks/emissions/bank.go index 8149b5e6af..065aec8fa3 100644 --- a/testutil/keeper/mocks/emissions/bank.go +++ b/testutil/keeper/mocks/emissions/bank.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.38.0. DO NOT EDIT. +// Code generated by mockery v2.42.2. DO NOT EDIT. package mocks diff --git a/testutil/keeper/mocks/emissions/observer.go b/testutil/keeper/mocks/emissions/observer.go index 594f090907..67b185a71a 100644 --- a/testutil/keeper/mocks/emissions/observer.go +++ b/testutil/keeper/mocks/emissions/observer.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.38.0. DO NOT EDIT. +// Code generated by mockery v2.42.2. DO NOT EDIT. package mocks diff --git a/testutil/keeper/mocks/emissions/staking.go b/testutil/keeper/mocks/emissions/staking.go index 69f1b60081..ba70aeffce 100644 --- a/testutil/keeper/mocks/emissions/staking.go +++ b/testutil/keeper/mocks/emissions/staking.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.38.0. DO NOT EDIT. +// Code generated by mockery v2.42.2. DO NOT EDIT. package mocks diff --git a/testutil/keeper/mocks/fungible/account.go b/testutil/keeper/mocks/fungible/account.go index 0522e833b4..8c8bccbfea 100644 --- a/testutil/keeper/mocks/fungible/account.go +++ b/testutil/keeper/mocks/fungible/account.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.38.0. DO NOT EDIT. +// Code generated by mockery v2.42.2. DO NOT EDIT. package mocks diff --git a/testutil/keeper/mocks/fungible/authority.go b/testutil/keeper/mocks/fungible/authority.go index b3ed6cae5a..567c4af2e0 100644 --- a/testutil/keeper/mocks/fungible/authority.go +++ b/testutil/keeper/mocks/fungible/authority.go @@ -1,9 +1,10 @@ -// Code generated by mockery v2.38.0. DO NOT EDIT. +// Code generated by mockery v2.42.2. DO NOT EDIT. package mocks import ( mock "github.com/stretchr/testify/mock" + chains "github.com/zeta-chain/zetacore/pkg/chains" types "github.com/cosmos/cosmos-sdk/types" ) @@ -31,6 +32,26 @@ func (_m *FungibleAuthorityKeeper) CheckAuthorization(ctx types.Context, msg typ return r0 } +// GetAdditionalChainList provides a mock function with given fields: ctx +func (_m *FungibleAuthorityKeeper) GetAdditionalChainList(ctx types.Context) []chains.Chain { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for GetAdditionalChainList") + } + + var r0 []chains.Chain + if rf, ok := ret.Get(0).(func(types.Context) []chains.Chain); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]chains.Chain) + } + } + + return r0 +} + // NewFungibleAuthorityKeeper creates a new instance of FungibleAuthorityKeeper. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. func NewFungibleAuthorityKeeper(t interface { diff --git a/testutil/keeper/mocks/fungible/bank.go b/testutil/keeper/mocks/fungible/bank.go index db14226310..2f7b0f200c 100644 --- a/testutil/keeper/mocks/fungible/bank.go +++ b/testutil/keeper/mocks/fungible/bank.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.38.0. DO NOT EDIT. +// Code generated by mockery v2.42.2. DO NOT EDIT. package mocks diff --git a/testutil/keeper/mocks/fungible/evm.go b/testutil/keeper/mocks/fungible/evm.go index 28fd46e25c..7e72935cb4 100644 --- a/testutil/keeper/mocks/fungible/evm.go +++ b/testutil/keeper/mocks/fungible/evm.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.38.0. DO NOT EDIT. +// Code generated by mockery v2.42.2. DO NOT EDIT. package mocks diff --git a/testutil/keeper/mocks/fungible/observer.go b/testutil/keeper/mocks/fungible/observer.go index bbe76b1afa..a96ff25709 100644 --- a/testutil/keeper/mocks/fungible/observer.go +++ b/testutil/keeper/mocks/fungible/observer.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.38.0. DO NOT EDIT. +// Code generated by mockery v2.42.2. DO NOT EDIT. package mocks @@ -15,19 +15,19 @@ type FungibleObserverKeeper struct { } // GetSupportedChains provides a mock function with given fields: ctx -func (_m *FungibleObserverKeeper) GetSupportedChains(ctx types.Context) []*chains.Chain { +func (_m *FungibleObserverKeeper) GetSupportedChains(ctx types.Context) []chains.Chain { ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for GetSupportedChains") } - var r0 []*chains.Chain - if rf, ok := ret.Get(0).(func(types.Context) []*chains.Chain); ok { + var r0 []chains.Chain + if rf, ok := ret.Get(0).(func(types.Context) []chains.Chain); ok { r0 = rf(ctx) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]*chains.Chain) + r0 = ret.Get(0).([]chains.Chain) } } diff --git a/testutil/keeper/mocks/ibccrosschain/crosschain.go b/testutil/keeper/mocks/ibccrosschain/crosschain.go index e7e665d659..5443ed5dbd 100644 --- a/testutil/keeper/mocks/ibccrosschain/crosschain.go +++ b/testutil/keeper/mocks/ibccrosschain/crosschain.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.38.0. DO NOT EDIT. +// Code generated by mockery v2.42.2. DO NOT EDIT. package mocks diff --git a/testutil/keeper/mocks/ibccrosschain/transfer.go b/testutil/keeper/mocks/ibccrosschain/transfer.go index 7cbab3b6a0..ef94f78cf9 100644 --- a/testutil/keeper/mocks/ibccrosschain/transfer.go +++ b/testutil/keeper/mocks/ibccrosschain/transfer.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.38.0. DO NOT EDIT. +// Code generated by mockery v2.42.2. DO NOT EDIT. package mocks diff --git a/testutil/keeper/mocks/lightclient/authority.go b/testutil/keeper/mocks/lightclient/authority.go index 8592036260..7aa33659d6 100644 --- a/testutil/keeper/mocks/lightclient/authority.go +++ b/testutil/keeper/mocks/lightclient/authority.go @@ -1,9 +1,10 @@ -// Code generated by mockery v2.38.0. DO NOT EDIT. +// Code generated by mockery v2.42.2. DO NOT EDIT. package mocks import ( mock "github.com/stretchr/testify/mock" + chains "github.com/zeta-chain/zetacore/pkg/chains" types "github.com/cosmos/cosmos-sdk/types" ) @@ -31,6 +32,26 @@ func (_m *LightclientAuthorityKeeper) CheckAuthorization(ctx types.Context, msg return r0 } +// GetAdditionalChainList provides a mock function with given fields: ctx +func (_m *LightclientAuthorityKeeper) GetAdditionalChainList(ctx types.Context) []chains.Chain { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for GetAdditionalChainList") + } + + var r0 []chains.Chain + if rf, ok := ret.Get(0).(func(types.Context) []chains.Chain); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]chains.Chain) + } + } + + return r0 +} + // NewLightclientAuthorityKeeper creates a new instance of LightclientAuthorityKeeper. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. func NewLightclientAuthorityKeeper(t interface { diff --git a/testutil/keeper/mocks/observer/authority.go b/testutil/keeper/mocks/observer/authority.go index 30a0d21b6d..531db8662c 100644 --- a/testutil/keeper/mocks/observer/authority.go +++ b/testutil/keeper/mocks/observer/authority.go @@ -1,11 +1,13 @@ -// Code generated by mockery v2.38.0. DO NOT EDIT. +// Code generated by mockery v2.42.2. DO NOT EDIT. package mocks import ( - mock "github.com/stretchr/testify/mock" + chains "github.com/zeta-chain/zetacore/pkg/chains" authoritytypes "github.com/zeta-chain/zetacore/x/authority/types" + mock "github.com/stretchr/testify/mock" + types "github.com/cosmos/cosmos-sdk/types" ) @@ -32,6 +34,26 @@ func (_m *ObserverAuthorityKeeper) CheckAuthorization(ctx types.Context, msg typ return r0 } +// GetAdditionalChainList provides a mock function with given fields: ctx +func (_m *ObserverAuthorityKeeper) GetAdditionalChainList(ctx types.Context) []chains.Chain { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for GetAdditionalChainList") + } + + var r0 []chains.Chain + if rf, ok := ret.Get(0).(func(types.Context) []chains.Chain); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]chains.Chain) + } + } + + return r0 +} + // SetPolicies provides a mock function with given fields: ctx, policies func (_m *ObserverAuthorityKeeper) SetPolicies(ctx types.Context, policies authoritytypes.Policies) { _m.Called(ctx, policies) diff --git a/testutil/keeper/mocks/observer/lightclient.go b/testutil/keeper/mocks/observer/lightclient.go index 442d006a5f..4c4c4e5f9e 100644 --- a/testutil/keeper/mocks/observer/lightclient.go +++ b/testutil/keeper/mocks/observer/lightclient.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.38.0. DO NOT EDIT. +// Code generated by mockery v2.42.2. DO NOT EDIT. package mocks diff --git a/testutil/keeper/mocks/observer/slashing.go b/testutil/keeper/mocks/observer/slashing.go index a7793ef8dc..be79a8f8a8 100644 --- a/testutil/keeper/mocks/observer/slashing.go +++ b/testutil/keeper/mocks/observer/slashing.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.38.0. DO NOT EDIT. +// Code generated by mockery v2.42.2. DO NOT EDIT. package mocks diff --git a/testutil/keeper/mocks/observer/staking.go b/testutil/keeper/mocks/observer/staking.go index 90007b6c35..c59156a7cb 100644 --- a/testutil/keeper/mocks/observer/staking.go +++ b/testutil/keeper/mocks/observer/staking.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.38.0. DO NOT EDIT. +// Code generated by mockery v2.42.2. DO NOT EDIT. package mocks diff --git a/testutil/network/genesis_state.go b/testutil/network/genesis_state.go index 7f0bb2003c..ae6bc247bd 100644 --- a/testutil/network/genesis_state.go +++ b/testutil/network/genesis_state.go @@ -66,7 +66,7 @@ func SetupZetaGenesisState( } if setupChainNonces { - privatenetChains := chains.ChainListByNetworkType(chains.NetworkType_privnet) + privatenetChains := chains.ChainListByNetworkType(chains.NetworkType_privnet, []chains.Chain{}) chainNonceList := make([]observertypes.ChainNonces, len(privatenetChains)) for i, chain := range privatenetChains { chainNonceList[i] = observertypes.ChainNonces{ diff --git a/testutil/sample/authority.go b/testutil/sample/authority.go index be9ca2c555..d777373282 100644 --- a/testutil/sample/authority.go +++ b/testutil/sample/authority.go @@ -29,15 +29,11 @@ func Policies() authoritytypes.Policies { } func ChainInfo(startChainID int64) authoritytypes.ChainInfo { - chain1 := Chain(startChainID) - chain2 := Chain(startChainID + 1) - chain3 := Chain(startChainID + 2) - return authoritytypes.ChainInfo{ Chains: []chains.Chain{ - *chain1, - *chain2, - *chain3, + Chain(startChainID), + Chain(startChainID + 1), + Chain(startChainID + 2), }, } } diff --git a/testutil/sample/crosschain.go b/testutil/sample/crosschain.go index 38d490af62..c4353681bf 100644 --- a/testutil/sample/crosschain.go +++ b/testutil/sample/crosschain.go @@ -280,9 +280,9 @@ func InboundVote(coinType coin.CoinType, from, to int64) types.MsgVoteInbound { return types.MsgVoteInbound{ Creator: "", Sender: EthAddress().String(), - SenderChainId: Chain(from).GetChainId(), + SenderChainId: Chain(from).ChainId, Receiver: EthAddress().String(), - ReceiverChain: Chain(to).GetChainId(), + ReceiverChain: Chain(to).ChainId, Amount: UintInRange(10000000, 1000000000), Message: base64.StdEncoding.EncodeToString(Bytes()), InboundBlockHeight: Uint64InRange(1, 10000), diff --git a/testutil/sample/observer.go b/testutil/sample/observer.go index 3c1a38bc0d..96621ccb26 100644 --- a/testutil/sample/observer.go +++ b/testutil/sample/observer.go @@ -111,7 +111,7 @@ func ChainParamsSupported(chainID int64) *types.ChainParams { } func ChainParamsList() (cpl types.ChainParamsList) { - chainList := chains.ChainListByNetworkType(chains.NetworkType_privnet) + chainList := chains.ChainListByNetworkType(chains.NetworkType_privnet, []chains.Chain{}) for _, chain := range chainList { cpl.ChainParams = append(cpl.ChainParams, ChainParams(chain.ChainId)) diff --git a/testutil/sample/sample.go b/testutil/sample/sample.go index bdd7681ee1..1341be96e4 100644 --- a/testutil/sample/sample.go +++ b/testutil/sample/sample.go @@ -118,7 +118,7 @@ func GenDoc(t *testing.T) *types.GenesisDoc { return genDoc } -func Chain(chainID int64) *chains.Chain { +func Chain(chainID int64) chains.Chain { r := newRandFromSeed(chainID) chainNameLen := len(chains.ChainName_name) @@ -127,7 +127,7 @@ func Chain(chainID int64) *chains.Chain { vmLen := len(chains.Vm_name) consensusLen := len(chains.Consensus_name) - return &chains.Chain{ + return chains.Chain{ ChainId: chainID, ChainName: chains.ChainName(r.Intn(chainNameLen)), Network: chains.Network(r.Intn(networkLen)), diff --git a/typescript/zetachain/zetacore/observer/params_pb.d.ts b/typescript/zetachain/zetacore/observer/params_pb.d.ts index 252793f418..9155826e05 100644 --- a/typescript/zetachain/zetacore/observer/params_pb.d.ts +++ b/typescript/zetachain/zetacore/observer/params_pb.d.ts @@ -104,6 +104,11 @@ export declare class ChainParams extends Message { */ isSupported: boolean; + /** + * @generated from field: string gateway_address = 17; + */ + gatewayAddress: string; + constructor(data?: PartialMessage); static readonly runtime: typeof proto3; diff --git a/typescript/zetachain/zetacore/pkg/chains/chains_pb.d.ts b/typescript/zetachain/zetacore/pkg/chains/chains_pb.d.ts index 782e669d43..ecaf732ec5 100644 --- a/typescript/zetachain/zetacore/pkg/chains/chains_pb.d.ts +++ b/typescript/zetachain/zetacore/pkg/chains/chains_pb.d.ts @@ -132,6 +132,21 @@ export declare enum ChainName { * @generated from enum value: base_sepolia = 20; */ base_sepolia = 20, + + /** + * @generated from enum value: solana_mainnet = 21; + */ + solana_mainnet = 21, + + /** + * @generated from enum value: solana_devnet = 22; + */ + solana_devnet = 22, + + /** + * @generated from enum value: solana_localnet = 23; + */ + solana_localnet = 23, } /** @@ -176,6 +191,11 @@ export declare enum Network { * @generated from enum value: base = 6; */ base = 6, + + /** + * @generated from enum value: solana = 7; + */ + solana = 7, } /** @@ -222,6 +242,11 @@ export declare enum Vm { * @generated from enum value: evm = 1; */ evm = 1, + + /** + * @generated from enum value: svm = 2; + */ + svm = 2, } /** @@ -251,6 +276,11 @@ export declare enum Consensus { * @generated from enum value: op_stack = 3; */ op_stack = 3, + + /** + * @generated from enum value: solana_consensus = 4; + */ + solana_consensus = 4, } /** diff --git a/x/authority/keeper/chain_info.go b/x/authority/keeper/chain_info.go index 5c9056fe0c..557ef7f1c4 100644 --- a/x/authority/keeper/chain_info.go +++ b/x/authority/keeper/chain_info.go @@ -4,6 +4,7 @@ import ( "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/zeta-chain/zetacore/pkg/chains" "github.com/zeta-chain/zetacore/x/authority/types" ) @@ -24,3 +25,15 @@ func (k Keeper) GetChainInfo(ctx sdk.Context) (val types.ChainInfo, found bool) k.cdc.MustUnmarshal(b, &val) return val, true } + +// GetAdditionalChainList returns the list of chains in chain info object +// additional chains are additional static chain information stored on-chain used in addition with the default chain information +// this list allow to add new chain support without doing an upgrade +// returns empty list if no chains are present +func (k Keeper) GetAdditionalChainList(ctx sdk.Context) []chains.Chain { + chainInfo, found := k.GetChainInfo(ctx) + if !found { + return nil + } + return chainInfo.Chains +} diff --git a/x/authority/keeper/chain_info_test.go b/x/authority/keeper/chain_info_test.go index 87424cb4dd..59f1714504 100644 --- a/x/authority/keeper/chain_info_test.go +++ b/x/authority/keeper/chain_info_test.go @@ -31,3 +31,19 @@ func TestKeeper_SetChainInfo(t *testing.T) { require.True(t, found) require.Equal(t, newChainInfo, got) } + +func TestKeeper_GetChainList(t *testing.T) { + k, ctx := keepertest.AuthorityKeeper(t) + + // Empty list + list := k.GetAdditionalChainList(ctx) + require.Empty(t, list) + + // Set chain info + chainInfo := sample.ChainInfo(42) + k.SetChainInfo(ctx, chainInfo) + + // Check list + list = k.GetAdditionalChainList(ctx) + require.Equal(t, chainInfo.Chains, list) +} diff --git a/x/authority/keeper/grpc_query_chain_info.go b/x/authority/keeper/grpc_query_chain_info.go index 695fcee025..f3632d71a6 100644 --- a/x/authority/keeper/grpc_query_chain_info.go +++ b/x/authority/keeper/grpc_query_chain_info.go @@ -7,6 +7,7 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "github.com/zeta-chain/zetacore/pkg/chains" "github.com/zeta-chain/zetacore/x/authority/types" ) @@ -21,9 +22,10 @@ func (k Keeper) ChainInfo( ctx := sdk.UnwrapSDKContext(c) // fetch chain info + // if the object has not been initialized, return an object containing an empty list chainInfo, found := k.GetChainInfo(ctx) if !found { - return nil, status.Error(codes.NotFound, "chain info not found") + chainInfo.Chains = []chains.Chain{} } return &types.QueryGetChainInfoResponse{ChainInfo: chainInfo}, nil diff --git a/x/authority/keeper/grpc_query_chain_info_test.go b/x/authority/keeper/grpc_query_chain_info_test.go index 7529e27437..bd20475a31 100644 --- a/x/authority/keeper/grpc_query_chain_info_test.go +++ b/x/authority/keeper/grpc_query_chain_info_test.go @@ -1,6 +1,7 @@ package keeper_test import ( + "github.com/zeta-chain/zetacore/pkg/chains" "testing" "github.com/stretchr/testify/require" @@ -21,8 +22,13 @@ func TestKeeper_ChainInfo(t *testing.T) { t.Run("chain info not found", func(t *testing.T) { k, ctx := keepertest.AuthorityKeeper(t) - _, err := k.ChainInfo(ctx, &types.QueryGetChainInfoRequest{}) - require.ErrorContains(t, err, "chain info not found") + res, err := k.ChainInfo(ctx, &types.QueryGetChainInfoRequest{}) + require.NoError(t, err) + require.Equal(t, res, &types.QueryGetChainInfoResponse{ + ChainInfo: types.ChainInfo{ + Chains: []chains.Chain{}, + }, + }) }) t.Run("can retrieve chain info", func(t *testing.T) { diff --git a/x/crosschain/keeper/abci.go b/x/crosschain/keeper/abci.go index 4897ae6f66..ee6cfb3aa3 100644 --- a/x/crosschain/keeper/abci.go +++ b/x/crosschain/keeper/abci.go @@ -30,7 +30,7 @@ type CheckAndUpdateCctxGasPriceFunc func( // The function returns the number of cctxs updated and the gas price increase flags used func (k Keeper) IterateAndUpdateCctxGasPrice( ctx sdk.Context, - chains []*zetachains.Chain, + chains []zetachains.Chain, updateFunc CheckAndUpdateCctxGasPriceFunc, ) (int, observertypes.GasPriceIncreaseFlags) { // fetch the gas price increase flags or use default @@ -45,12 +45,14 @@ func (k Keeper) IterateAndUpdateCctxGasPrice( return 0, gasPriceIncreaseFlags } + additionalChains := k.GetAuthorityKeeper().GetAdditionalChainList(ctx) + cctxCount := 0 IterateChains: for _, chain := range chains { // support only external evm chains - if zetachains.IsEVMChain(chain.ChainId) && !zetachains.IsZetaChain(chain.ChainId) { + if zetachains.IsEVMChain(chain.ChainId, additionalChains) && !zetachains.IsZetaChain(chain.ChainId, additionalChains) { res, err := k.ListPendingCctx(sdk.UnwrapSDKContext(ctx), &types.QueryListPendingCctxRequest{ ChainId: chain.ChainId, Limit: gasPriceIncreaseFlags.MaxPendingCctxs, diff --git a/x/crosschain/keeper/abci_test.go b/x/crosschain/keeper/abci_test.go index 36736b254b..817f930079 100644 --- a/x/crosschain/keeper/abci_test.go +++ b/x/crosschain/keeper/abci_test.go @@ -42,7 +42,7 @@ func TestKeeper_IterateAndUpdateCctxGasPrice(t *testing.T) { } // add some evm and non-evm chains - supportedChains := []*chains.Chain{ + supportedChains := []chains.Chain{ {ChainId: chains.Ethereum.ChainId}, {ChainId: chains.BitcoinMainnet.ChainId}, {ChainId: chains.BscMainnet.ChainId}, diff --git a/x/crosschain/keeper/cctx_gateway_observers.go b/x/crosschain/keeper/cctx_gateway_observers.go index 7155e61cd0..18bf31afb8 100644 --- a/x/crosschain/keeper/cctx_gateway_observers.go +++ b/x/crosschain/keeper/cctx_gateway_observers.go @@ -41,7 +41,10 @@ func (c CCTXGatewayObservers) InitiateOutbound( outboundReceiverChainID := config.CCTX.GetCurrentOutboundParam().ReceiverChainId // TODO (https://github.com/zeta-chain/node/issues/1010): workaround for this bug noEthereumTxEvent := false - if chains.IsZetaChain(config.CCTX.InboundParams.SenderChainId) { + if chains.IsZetaChain( + config.CCTX.InboundParams.SenderChainId, + c.crosschainKeeper.GetAuthorityKeeper().GetAdditionalChainList(ctx), + ) { noEthereumTxEvent = true } diff --git a/x/crosschain/keeper/cctx_orchestrator_validate_outbound.go b/x/crosschain/keeper/cctx_orchestrator_validate_outbound.go index 77989b88fe..a1a25e9988 100644 --- a/x/crosschain/keeper/cctx_orchestrator_validate_outbound.go +++ b/x/crosschain/keeper/cctx_orchestrator_validate_outbound.go @@ -121,7 +121,7 @@ func (k Keeper) validateFailedOutboundObservers(ctx sdk.Context, cctx *types.Cro // if the cctx is of coin type cmd or the sender chain is zeta chain, then we do not revert, the cctx is aborted cctx.GetCurrentOutboundParam().TxFinalizationStatus = types.TxFinalizationStatus_Executed cctx.SetAbort("Outbound failed") - } else if chains.IsZetaChain(cctx.InboundParams.SenderChainId) { + } else if chains.IsZetaChain(cctx.InboundParams.SenderChainId, k.GetAuthorityKeeper().GetAdditionalChainList(ctx)) { switch cctx.InboundParams.CoinType { // Try revert if the coin-type is ZETA case coin.CoinType_Zeta: @@ -159,8 +159,7 @@ func (k Keeper) validateFailedOutbound( ) error { switch oldStatus { case types.CctxStatus_PendingOutbound: - senderChain := k.zetaObserverKeeper.GetSupportedChainFromChainID(ctx, cctx.InboundParams.SenderChainId) - if senderChain == nil { + if _, found := k.zetaObserverKeeper.GetSupportedChainFromChainID(ctx, cctx.InboundParams.SenderChainId); !found { return observertypes.ErrSupportedChains } diff --git a/x/crosschain/keeper/cctx_orchestrator_validate_outbound_test.go b/x/crosschain/keeper/cctx_orchestrator_validate_outbound_test.go index fff52e599a..4d97c166f4 100644 --- a/x/crosschain/keeper/cctx_orchestrator_validate_outbound_test.go +++ b/x/crosschain/keeper/cctx_orchestrator_validate_outbound_test.go @@ -248,18 +248,15 @@ func TestKeeper_ValidateFailedOutbound(t *testing.T) { asset := "" // mock successful GetRevertGasLimit for ERC20 - keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain, 100) + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, senderChain, 100) // mock successful PayGasAndUpdateCctx - keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *senderChain, asset) - - // mock successful GetSupportedChainFromChainID - keepertest.MockGetSupportedChainFromChainID(observerMock, senderChain) + keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, senderChain, asset) // mock successful UpdateNonce - _ = keepertest.MockUpdateNonce(observerMock, *senderChain) + _ = keepertest.MockUpdateNonce(observerMock, senderChain) - cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + cctx := GetERC20Cctx(t, receiver, senderChain, asset, amount) cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound err := k.ValidateOutboundObservers( ctx, @@ -288,18 +285,15 @@ func TestKeeper_ValidateFailedOutbound(t *testing.T) { asset := "" // mock successful GetRevertGasLimit for ERC20 - keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain, 0) + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, senderChain, 0) // mock successful PayGasAndUpdateCctx - keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *senderChain, asset) - - // mock successful GetSupportedChainFromChainID - keepertest.MockGetSupportedChainFromChainID(observerMock, senderChain) + keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, senderChain, asset) // mock successful UpdateNonce - _ = keepertest.MockUpdateNonce(observerMock, *senderChain) + _ = keepertest.MockUpdateNonce(observerMock, senderChain) - cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + cctx := GetERC20Cctx(t, receiver, senderChain, asset, amount) cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound err := k.ValidateOutboundObservers( ctx, @@ -328,10 +322,10 @@ func TestKeeper_ValidateFailedOutbound(t *testing.T) { asset := "" // mock successful GetRevertGasLimit for ERC20 - keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain, 100) + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, senderChain, 100) // mock successful PayGasAndUpdateCctx - keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *senderChain, asset) + keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, senderChain, asset) // mock successful GetSupportedChainFromChainID keepertest.MockGetSupportedChainFromChainID(observerMock, senderChain) @@ -340,7 +334,7 @@ func TestKeeper_ValidateFailedOutbound(t *testing.T) { observerMock.On("GetChainNonces", mock.Anything, senderChain.ChainName.String()). Return(observertypes.ChainNonces{}, false) - cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + cctx := GetERC20Cctx(t, receiver, senderChain, asset, amount) cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound err := k.ValidateOutboundObservers( ctx, @@ -367,7 +361,7 @@ func TestKeeper_ValidateFailedOutbound(t *testing.T) { asset := "" // mock successful GetRevertGasLimit for ERC20 - keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain, 100) + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, senderChain, 100) // mock successful GetSupportedChainFromChainID keepertest.MockGetSupportedChainFromChainID(observerMock, senderChain) @@ -375,7 +369,7 @@ func TestKeeper_ValidateFailedOutbound(t *testing.T) { // mock failed failed GetSupportedChainFromChainID to fail PayGasAndUpdateCctx keepertest.MockFailedGetSupportedChainFromChainID(observerMock, senderChain) - cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + cctx := GetERC20Cctx(t, receiver, senderChain, asset, amount) cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound err := k.ValidateOutboundObservers( ctx, @@ -405,7 +399,7 @@ func TestKeeper_ValidateFailedOutbound(t *testing.T) { Zrc20ContractAddress: sample.EthAddress().String(), }, false).Once() - cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + cctx := GetERC20Cctx(t, receiver, senderChain, asset, amount) cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound err := k.ValidateOutboundObservers( ctx, @@ -487,7 +481,7 @@ func TestKeeper_ValidateOutboundObservers(t *testing.T) { senderChain := getValidEthChain() asset := "" - cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + cctx := GetERC20Cctx(t, receiver, senderChain, asset, amount) cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound oldOutboundParamsLen := len(cctx.OutboundParams) // mock failed GetRevertGasLimit for ERC20 @@ -521,7 +515,7 @@ func TestKeeper_ValidateOutboundObservers(t *testing.T) { senderChain := getValidEthChain() asset := "" - cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + cctx := GetERC20Cctx(t, receiver, senderChain, asset, amount) cctx.OutboundParams = append(cctx.OutboundParams, sample.OutboundParams(sample.Rand())) cctx.OutboundParams[1].ReceiverChainId = 5 cctx.OutboundParams[1].BallotIndex = "" @@ -529,7 +523,7 @@ func TestKeeper_ValidateOutboundObservers(t *testing.T) { cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound // mock successful GetRevertGasLimit for ERC20 - keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain, 100) + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, senderChain, 100) err := k.ValidateOutboundObservers( ctx, @@ -554,20 +548,17 @@ func TestKeeper_ValidateOutboundObservers(t *testing.T) { senderChain := getValidEthChain() asset := "" - cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + cctx := GetERC20Cctx(t, receiver, senderChain, asset, amount) cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound oldOutboundParamsLen := len(cctx.OutboundParams) // mock successful GetRevertGasLimit for ERC20 - keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain, 100) + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, senderChain, 100) // mock successful PayGasAndUpdateCctx - keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *senderChain, asset) - - // mock successful GetSupportedChainFromChainID - keepertest.MockGetSupportedChainFromChainID(observerMock, senderChain) + keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, senderChain, asset) // mock successful UpdateNonce - _ = keepertest.MockUpdateNonce(observerMock, *senderChain) + _ = keepertest.MockUpdateNonce(observerMock, senderChain) err := k.ValidateOutboundObservers( ctx, diff --git a/x/crosschain/keeper/cctx_utils.go b/x/crosschain/keeper/cctx_utils.go index 3d3cf31cd5..8996ad0b5a 100644 --- a/x/crosschain/keeper/cctx_utils.go +++ b/x/crosschain/keeper/cctx_utils.go @@ -19,8 +19,8 @@ import ( // SetObserverOutboundInfo sets the CCTX outbound nonce to the next available nonce for the TSS address, and updates the nonce of blockchain state. // It also updates the PendingNonces that is used to track the unfulfilled outbound txs. func (k Keeper) SetObserverOutboundInfo(ctx sdk.Context, receiveChainID int64, cctx *types.CrossChainTx) error { - chain := k.GetObserverKeeper().GetSupportedChainFromChainID(ctx, receiveChainID) - if chain == nil { + chain, found := k.GetObserverKeeper().GetSupportedChainFromChainID(ctx, receiveChainID) + if !found { return zetaObserverTypes.ErrSupportedChains } diff --git a/x/crosschain/keeper/cctx_utils_test.go b/x/crosschain/keeper/cctx_utils_test.go index 798fcdd8c4..dc05117c4e 100644 --- a/x/crosschain/keeper/cctx_utils_test.go +++ b/x/crosschain/keeper/cctx_utils_test.go @@ -234,7 +234,7 @@ func TestKeeper_SetObserverOutboundInfo(t *testing.T) { observerMock := keepertest.GetCrosschainObserverMock(t, k) // mock failed GetSupportedChainFromChainID - keepertest.MockFailedGetSupportedChainFromChainID(observerMock, nil) + keepertest.MockFailedGetSupportedChainFromChainID(observerMock, sample.Chain(5)) err := k.SetObserverOutboundInfo(ctx, 5, nil) require.Error(t, err) @@ -248,7 +248,7 @@ func TestKeeper_SetObserverOutboundInfo(t *testing.T) { observerMock := keepertest.GetCrosschainObserverMock(t, k) // mock successful GetSupportedChainFromChainID - keepertest.MockGetSupportedChainFromChainID(observerMock, &chains.Chain{ + keepertest.MockGetSupportedChainFromChainID(observerMock, chains.Chain{ ChainName: 5, ChainId: 5, }) @@ -274,7 +274,7 @@ func TestKeeper_SetObserverOutboundInfo(t *testing.T) { observerMock := keepertest.GetCrosschainObserverMock(t, k) // mock successful GetSupportedChainFromChainID - keepertest.MockGetSupportedChainFromChainID(observerMock, &chains.Chain{ + keepertest.MockGetSupportedChainFromChainID(observerMock, chains.Chain{ ChainName: 5, ChainId: 5, }) @@ -304,7 +304,7 @@ func TestKeeper_SetObserverOutboundInfo(t *testing.T) { observerMock := keepertest.GetCrosschainObserverMock(t, k) // mock successful GetSupportedChainFromChainID - keepertest.MockGetSupportedChainFromChainID(observerMock, &chains.Chain{ + keepertest.MockGetSupportedChainFromChainID(observerMock, chains.Chain{ ChainName: 5, ChainId: 5, }) @@ -336,7 +336,7 @@ func TestKeeper_SetObserverOutboundInfo(t *testing.T) { observerMock := keepertest.GetCrosschainObserverMock(t, k) // mock successful GetSupportedChainFromChainID - keepertest.MockGetSupportedChainFromChainID(observerMock, &chains.Chain{ + keepertest.MockGetSupportedChainFromChainID(observerMock, chains.Chain{ ChainName: 5, ChainId: 5, }) @@ -370,7 +370,7 @@ func TestKeeper_SetObserverOutboundInfo(t *testing.T) { observerMock := keepertest.GetCrosschainObserverMock(t, k) // mock successful GetSupportedChainFromChainID - keepertest.MockGetSupportedChainFromChainID(observerMock, &chains.Chain{ + keepertest.MockGetSupportedChainFromChainID(observerMock, chains.Chain{ ChainName: 5, ChainId: 5, }) diff --git a/x/crosschain/keeper/events.go b/x/crosschain/keeper/events.go index c503835f14..42b32bc589 100644 --- a/x/crosschain/keeper/events.go +++ b/x/crosschain/keeper/events.go @@ -5,7 +5,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/zeta-chain/zetacore/pkg/chains" "github.com/zeta-chain/zetacore/x/crosschain/types" ) @@ -15,13 +14,11 @@ func EmitEventInboundFinalized(ctx sdk.Context, cctx *types.CrossChainTx) { MsgTypeUrl: sdk.MsgTypeURL(&types.MsgVoteInbound{}), CctxIndex: cctx.Index, Sender: cctx.InboundParams.Sender, - SenderChain: chains.GetChainFromChainID(cctx.InboundParams.SenderChainId).ChainName.String(), TxOrgin: cctx.InboundParams.TxOrigin, Asset: cctx.InboundParams.Asset, InboundHash: cctx.InboundParams.ObservedHash, InboundBlockHeight: strconv.FormatUint(cctx.InboundParams.ObservedExternalHeight, 10), Receiver: currentOutParam.Receiver, - ReceiverChain: chains.GetChainFromChainID(currentOutParam.ReceiverChainId).ChainName.String(), Amount: cctx.InboundParams.Amount.String(), RelayedMessage: cctx.RelayedMessage, NewStatus: cctx.CctxStatus.Status.String(), diff --git a/x/crosschain/keeper/evm_deposit.go b/x/crosschain/keeper/evm_deposit.go index 858c709f18..0b60a3c9e6 100644 --- a/x/crosschain/keeper/evm_deposit.go +++ b/x/crosschain/keeper/evm_deposit.go @@ -78,7 +78,7 @@ func (k Keeper) HandleEVMDeposit(ctx sdk.Context, cctx *types.CrossChainTx) (boo to = parsedAddress } - from, err := chains.DecodeAddressFromChainID(inboundSenderChainID, inboundSender) + from, err := chains.DecodeAddressFromChainID(inboundSenderChainID, inboundSender, k.GetAuthorityKeeper().GetAdditionalChainList(ctx)) if err != nil { return false, fmt.Errorf("HandleEVMDeposit: unable to decode address: %s", err.Error()) } diff --git a/x/crosschain/keeper/evm_hooks.go b/x/crosschain/keeper/evm_hooks.go index 2fc6310800..366dff4ee4 100644 --- a/x/crosschain/keeper/evm_hooks.go +++ b/x/crosschain/keeper/evm_hooks.go @@ -105,7 +105,7 @@ func (k Keeper) ProcessLogs( // If Validation fails, we will not process the event and return and error. This condition means that the event was correct, and emitted from a registered ZRC20 contract // But the information entered by the user is incorrect. In this case we can return an error and roll back the transaction - if err := ValidateZrc20WithdrawEvent(eventZrc20Withdrawal, coin.ForeignChainId); err != nil { + if err := k.ValidateZrc20WithdrawEvent(ctx, eventZrc20Withdrawal, coin.ForeignChainId); err != nil { return err } // If the event is valid, we will process it and create a new CCTX @@ -137,18 +137,21 @@ func (k Keeper) ProcessZRC20WithdrawalEvent( if !found { return fmt.Errorf("cannot find foreign coin with emittingContract address %s", event.Raw.Address.Hex()) } - receiverChain := k.zetaObserverKeeper.GetSupportedChainFromChainID(ctx, foreignCoin.ForeignChainId) - if receiverChain == nil { + + receiverChain, found := k.zetaObserverKeeper.GetSupportedChainFromChainID(ctx, foreignCoin.ForeignChainId) + if !found { return errorsmod.Wrapf( observertypes.ErrSupportedChains, "chain with chainID %d not supported", foreignCoin.ForeignChainId, ) } - senderChain, err := chains.ZetaChainFromChainID(ctx.ChainID()) + + senderChain, err := chains.ZetaChainFromCosmosChainID(ctx.ChainID()) if err != nil { return fmt.Errorf("ProcessZRC20WithdrawalEvent: failed to convert chainID: %s", err.Error()) } + toAddr, err := receiverChain.EncodeAddress(event.To) if err != nil { return fmt.Errorf("cannot encode address %s: %s", event.To, err.Error()) @@ -215,23 +218,27 @@ func (k Keeper) ProcessZetaSentEvent( receiverChainID := event.DestinationChainId - receiverChain := k.zetaObserverKeeper.GetSupportedChainFromChainID(ctx, receiverChainID.Int64()) - if receiverChain == nil { + receiverChain, found := k.zetaObserverKeeper.GetSupportedChainFromChainID(ctx, receiverChainID.Int64()) + if !found { return observertypes.ErrSupportedChains } + // Validation if we want to send ZETA to an external chain, but there is no ZETA token. chainParams, found := k.zetaObserverKeeper.GetChainParamsByChainID(ctx, receiverChain.ChainId) if !found { return observertypes.ErrChainParamsNotFound } + if receiverChain.IsExternalChain() && chainParams.ZetaTokenContractAddress == "" { return types.ErrUnableToSendCoinType } + toAddr := "0x" + hex.EncodeToString(event.DestinationAddress) - senderChain, err := chains.ZetaChainFromChainID(ctx.ChainID()) + senderChain, err := chains.ZetaChainFromCosmosChainID(ctx.ChainID()) if err != nil { return fmt.Errorf("ProcessZetaSentEvent: failed to convert chainID: %s", err.Error()) } + amount := math.NewUintFromBigInt(event.ZetaValueAndGas) messageString := base64.StdEncoding.EncodeToString(event.Message) // Bump gasLimit by event index (which is very unlikely to be larger than 1000) to always have different ZetaSent events msgs. @@ -264,29 +271,12 @@ func (k Keeper) ProcessZetaSentEvent( return nil } -// ParseZRC20WithdrawalEvent tries extracting ZRC20Withdrawal event from the input logs using the zrc20 contract; -// It only returns a not-nil event if the event has been correctly validated as a valid withdrawal event -func ParseZRC20WithdrawalEvent(log ethtypes.Log) (*zrc20.ZRC20Withdrawal, error) { - zrc20ZEVM, err := zrc20.NewZRC20Filterer(log.Address, bind.ContractFilterer(nil)) - if err != nil { - return nil, err - } - if len(log.Topics) == 0 { - return nil, fmt.Errorf("ParseZRC20WithdrawalEvent: invalid log - no topics") - } - event, err := zrc20ZEVM.ParseWithdrawal(log) - if err != nil { - return nil, err - } - return event, nil -} - // ValidateZrc20WithdrawEvent checks if the ZRC20Withdrawal event is valid // It verifies event information for BTC chains and returns an error if the event is invalid -func ValidateZrc20WithdrawEvent(event *zrc20.ZRC20Withdrawal, chainID int64) error { +func (k Keeper) ValidateZrc20WithdrawEvent(ctx sdk.Context, event *zrc20.ZRC20Withdrawal, chainID int64) error { // The event was parsed; that means the user has deposited tokens to the contract. - if chains.IsBitcoinChain(chainID) { + if chains.IsBitcoinChain(chainID, k.GetAuthorityKeeper().GetAdditionalChainList(ctx)) { if event.Value.Cmp(big.NewInt(constant.BTCWithdrawalDustAmount)) < 0 { return errorsmod.Wrapf( types.ErrInvalidWithdrawalAmount, @@ -306,6 +296,23 @@ func ValidateZrc20WithdrawEvent(event *zrc20.ZRC20Withdrawal, chainID int64) err return nil } +// ParseZRC20WithdrawalEvent tries extracting ZRC20Withdrawal event from the input logs using the zrc20 contract; +// It only returns a not-nil event if the event has been correctly validated as a valid withdrawal event +func ParseZRC20WithdrawalEvent(log ethtypes.Log) (*zrc20.ZRC20Withdrawal, error) { + zrc20ZEVM, err := zrc20.NewZRC20Filterer(log.Address, bind.ContractFilterer(nil)) + if err != nil { + return nil, err + } + if len(log.Topics) == 0 { + return nil, fmt.Errorf("ParseZRC20WithdrawalEvent: invalid log - no topics") + } + event, err := zrc20ZEVM.ParseWithdrawal(log) + if err != nil { + return nil, err + } + return event, nil +} + // ParseZetaSentEvent tries extracting ZetaSent event from connectorZEVM contract; // returns error if the log entry is not a ZetaSent event, or is not emitted from connectorZEVM // It only returns a not-nil event if all the error checks pass diff --git a/x/crosschain/keeper/evm_hooks_test.go b/x/crosschain/keeper/evm_hooks_test.go index 20b1c87e47..36b8938a8a 100644 --- a/x/crosschain/keeper/evm_hooks_test.go +++ b/x/crosschain/keeper/evm_hooks_test.go @@ -157,15 +157,17 @@ func TestParseZRC20WithdrawalEvent(t *testing.T) { } func TestValidateZrc20WithdrawEvent(t *testing.T) { t.Run("successfully validate a valid event", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeper(t) btcMainNetWithdrawalEvent, err := crosschainkeeper.ParseZRC20WithdrawalEvent( *sample.GetValidZRC20WithdrawToBTC(t).Logs[3], ) require.NoError(t, err) - err = crosschainkeeper.ValidateZrc20WithdrawEvent(btcMainNetWithdrawalEvent, chains.BitcoinMainnet.ChainId) + err = k.ValidateZrc20WithdrawEvent(ctx, btcMainNetWithdrawalEvent, chains.BitcoinMainnet.ChainId) require.NoError(t, err) }) t.Run("unable to validate a btc withdrawal event with an invalid amount", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeper(t) btcMainNetWithdrawalEvent, err := crosschainkeeper.ParseZRC20WithdrawalEvent( *sample.GetValidZRC20WithdrawToBTC(t).Logs[3], ) @@ -173,32 +175,34 @@ func TestValidateZrc20WithdrawEvent(t *testing.T) { // 1000 satoshis is the minimum amount that can be withdrawn btcMainNetWithdrawalEvent.Value = big.NewInt(constant.BTCWithdrawalDustAmount) - err = crosschainkeeper.ValidateZrc20WithdrawEvent(btcMainNetWithdrawalEvent, chains.BitcoinMainnet.ChainId) + err = k.ValidateZrc20WithdrawEvent(ctx, btcMainNetWithdrawalEvent, chains.BitcoinMainnet.ChainId) require.NoError(t, err) // 999 satoshis cannot be withdrawn btcMainNetWithdrawalEvent.Value = big.NewInt(constant.BTCWithdrawalDustAmount - 1) - err = crosschainkeeper.ValidateZrc20WithdrawEvent(btcMainNetWithdrawalEvent, chains.BitcoinMainnet.ChainId) + err = k.ValidateZrc20WithdrawEvent(ctx, btcMainNetWithdrawalEvent, chains.BitcoinMainnet.ChainId) require.ErrorContains(t, err, "less than minimum amount") }) t.Run("unable to validate a event with an invalid chain ID", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeper(t) btcMainNetWithdrawalEvent, err := crosschainkeeper.ParseZRC20WithdrawalEvent( *sample.GetValidZRC20WithdrawToBTC(t).Logs[3], ) require.NoError(t, err) - err = crosschainkeeper.ValidateZrc20WithdrawEvent(btcMainNetWithdrawalEvent, chains.BitcoinTestnet.ChainId) + err = k.ValidateZrc20WithdrawEvent(ctx, btcMainNetWithdrawalEvent, chains.BitcoinTestnet.ChainId) require.ErrorContains(t, err, "invalid address") }) t.Run("unable to validate an unsupported address type", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeper(t) btcMainNetWithdrawalEvent, err := crosschainkeeper.ParseZRC20WithdrawalEvent( *sample.GetValidZRC20WithdrawToBTC(t).Logs[3], ) require.NoError(t, err) btcMainNetWithdrawalEvent.To = []byte("04b2891ba8cb491828db3ebc8a780d43b169e7b3974114e6e50f9bab6ec" + "63c2f20f6d31b2025377d05c2a704d3bd799d0d56f3a8543d79a01ab6084a1cb204f260") - err = crosschainkeeper.ValidateZrc20WithdrawEvent(btcMainNetWithdrawalEvent, chains.BitcoinMainnet.ChainId) + err = k.ValidateZrc20WithdrawEvent(ctx, btcMainNetWithdrawalEvent, chains.BitcoinMainnet.ChainId) require.ErrorContains(t, err, "unsupported address") }) } @@ -313,7 +317,7 @@ func TestKeeper_ProcessZRC20WithdrawalEvent(t *testing.T) { ctx = ctx.WithChainID("test_21-1") err = k.ProcessZRC20WithdrawalEvent(ctx, event, emittingContract, txOrigin.Hex()) - require.ErrorContains(t, err, "failed to convert chainID: chain 21 not found") + require.ErrorContains(t, err, "failed to convert chainID") require.Empty(t, k.GetAllCrossChainTx(ctx)) }) diff --git a/x/crosschain/keeper/gas_payment.go b/x/crosschain/keeper/gas_payment.go index 58bfe4ffbf..efac718932 100644 --- a/x/crosschain/keeper/gas_payment.go +++ b/x/crosschain/keeper/gas_payment.go @@ -97,7 +97,7 @@ func (k Keeper) PayGasNativeAndUpdateCctx( cctx.InboundParams.CoinType.String(), ) } - if chain := k.zetaObserverKeeper.GetSupportedChainFromChainID(ctx, chainID); chain == nil { + if _, found := k.zetaObserverKeeper.GetSupportedChainFromChainID(ctx, chainID); !found { return observertypes.ErrSupportedChains } @@ -151,7 +151,7 @@ func (k Keeper) PayGasInERC20AndUpdateCctx( ) } - if chain := k.zetaObserverKeeper.GetSupportedChainFromChainID(ctx, chainID); chain == nil { + if _, found := k.zetaObserverKeeper.GetSupportedChainFromChainID(ctx, chainID); !found { return observertypes.ErrSupportedChains } // get gas params @@ -300,7 +300,7 @@ func (k Keeper) PayGasInZetaAndUpdateCctx( ) } - if chain := k.zetaObserverKeeper.GetSupportedChainFromChainID(ctx, chainID); chain == nil { + if _, found := k.zetaObserverKeeper.GetSupportedChainFromChainID(ctx, chainID); !found { return observertypes.ErrSupportedChains } diff --git a/x/crosschain/keeper/grpc_query_cctx_rate_limit.go b/x/crosschain/keeper/grpc_query_cctx_rate_limit.go index 270fb10b87..d2eb8d85ea 100644 --- a/x/crosschain/keeper/grpc_query_cctx_rate_limit.go +++ b/x/crosschain/keeper/grpc_query_cctx_rate_limit.go @@ -64,7 +64,7 @@ func (k Keeper) RateLimiterInput( // if a cctx is an outgoing cctx that orginates from ZetaChain // reverted incoming cctx has an external `SenderChainId` and should not be counted isCCTXOutgoing := func(cctx *types.CrossChainTx) bool { - return chains.IsZetaChain(cctx.InboundParams.SenderChainId) + return chains.IsZetaChain(cctx.InboundParams.SenderChainId, k.GetAuthorityKeeper().GetAdditionalChainList(ctx)) } // it is a past cctx if its nonce < `nonceLow`, @@ -272,7 +272,7 @@ func (k Keeper) ListPendingCctxWithinRateLimit( // if a cctx is outgoing from ZetaChain // reverted incoming cctx has an external `SenderChainId` and should not be counted isCCTXOutgoing := func(cctx *types.CrossChainTx) bool { - return chains.IsZetaChain(cctx.InboundParams.SenderChainId) + return chains.IsZetaChain(cctx.InboundParams.SenderChainId, k.GetAuthorityKeeper().GetAdditionalChainList(ctx)) } // query pending nonces for each foreign chain and get the lowest height of the pending cctxs diff --git a/x/crosschain/keeper/grpc_query_zeta_conversion_rate.go b/x/crosschain/keeper/grpc_query_zeta_conversion_rate.go index 184b398b66..7abf0f5401 100644 --- a/x/crosschain/keeper/grpc_query_zeta_conversion_rate.go +++ b/x/crosschain/keeper/grpc_query_zeta_conversion_rate.go @@ -19,25 +19,29 @@ func (k Keeper) ConvertGasToZeta( request *types.QueryConvertGasToZetaRequest, ) (*types.QueryConvertGasToZetaResponse, error) { ctx := sdk.UnwrapSDKContext(context) - chain := chains.GetChainFromChainID(request.ChainId) - if chain == nil { + chain, found := chains.GetChainFromChainID(request.ChainId, k.GetAuthorityKeeper().GetAdditionalChainList(ctx)) + if !found { return nil, zetaObserverTypes.ErrSupportedChains } + medianGasPrice, isFound := k.GetMedianGasPriceInUint(ctx, chain.ChainId) if !isFound { return nil, status.Error(codes.InvalidArgument, "invalid request: param chain") } + gasLimit := math.NewUintFromString(request.GasLimit) outTxGasFee := medianGasPrice.Mul(gasLimit) zrc20, err := k.fungibleKeeper.QuerySystemContractGasCoinZRC20(ctx, big.NewInt(chain.ChainId)) if err != nil { return nil, status.Error(codes.NotFound, "zrc20 not found") } + outTxGasFeeInZeta, err := k.fungibleKeeper.QueryUniswapV2RouterGetZetaAmountsIn(ctx, outTxGasFee.BigInt(), zrc20) if err != nil { return nil, status.Error(codes.Internal, "zQueryUniswapv2RouterGetAmountsIn failed") } + return &types.QueryConvertGasToZetaResponse{ OutboundGasInZeta: outTxGasFeeInZeta.String(), ProtocolFeeInZeta: types.GetProtocolFee().String(), diff --git a/x/crosschain/keeper/initiate_outbound.go b/x/crosschain/keeper/initiate_outbound.go index 954db18778..7435517f2f 100644 --- a/x/crosschain/keeper/initiate_outbound.go +++ b/x/crosschain/keeper/initiate_outbound.go @@ -24,8 +24,8 @@ type InitiateOutboundConfig struct { // which handles the state changes and error handling. func (k Keeper) InitiateOutbound(ctx sdk.Context, config InitiateOutboundConfig) (types.CctxStatus, error) { receiverChainID := config.CCTX.GetCurrentOutboundParam().ReceiverChainId - chainInfo := chains.GetChainFromChainID(receiverChainID) - if chainInfo == nil { + chainInfo, found := chains.GetChainFromChainID(receiverChainID, k.GetAuthorityKeeper().GetAdditionalChainList(ctx)) + if !found { return config.CCTX.CctxStatus.Status, cosmoserrors.Wrap( types.ErrInitiatitingOutbound, fmt.Sprintf( diff --git a/x/crosschain/keeper/initiate_outbound_test.go b/x/crosschain/keeper/initiate_outbound_test.go index 78175a76a8..212e1dae75 100644 --- a/x/crosschain/keeper/initiate_outbound_test.go +++ b/x/crosschain/keeper/initiate_outbound_test.go @@ -103,7 +103,7 @@ func TestKeeper_InitiateOutboundZEVMDeposit(t *testing.T) { keepertest.MockFailedGetSupportedChainFromChainID(observerMock, senderChain) // call InitiateOutbound - cctx := GetERC20Cctx(t, receiver, *senderChain, "", amount) + cctx := GetERC20Cctx(t, receiver, senderChain, "", amount) cctx.GetCurrentOutboundParam().ReceiverChainId = chains.ZetaChainPrivnet.ChainId newStatus, err := k.InitiateOutbound(ctx, keeper.InitiateOutboundConfig{CCTX: cctx, ShouldPayGas: true}) require.NoError(t, err) @@ -143,7 +143,7 @@ func TestKeeper_InitiateOutboundZEVMDeposit(t *testing.T) { Return(fungibletypes.ForeignCoins{}, false) // call InitiateOutbound - cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + cctx := GetERC20Cctx(t, receiver, senderChain, asset, amount) cctx.GetCurrentOutboundParam().ReceiverChainId = chains.ZetaChainPrivnet.ChainId newStatus, err := k.InitiateOutbound(ctx, keeper.InitiateOutboundConfig{CCTX: cctx, ShouldPayGas: true}) require.NoError(t, err) @@ -180,13 +180,13 @@ func TestKeeper_InitiateOutboundZEVMDeposit(t *testing.T) { keepertest.MockGetSupportedChainFromChainID(observerMock, senderChain) // mock successful GetRevertGasLimit for ERC20 - keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain, 100) + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, senderChain, 100) // mock unsuccessful PayGasInERC20AndUpdateCctx keepertest.MockFailedGetSupportedChainFromChainID(observerMock, senderChain) // call InitiateOutbound - cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + cctx := GetERC20Cctx(t, receiver, senderChain, asset, amount) cctx.GetCurrentOutboundParam().ReceiverChainId = chains.ZetaChainPrivnet.ChainId newStatus, err := k.InitiateOutbound(ctx, keeper.InitiateOutboundConfig{CCTX: cctx, ShouldPayGas: true}) require.NoError(t, err) @@ -225,13 +225,13 @@ func TestKeeper_InitiateOutboundZEVMDeposit(t *testing.T) { keepertest.MockGetSupportedChainFromChainID(observerMock, senderChain) // mock successful GetRevertGasLimit for ERC20 - keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain, 0) + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, senderChain, 0) // mock unsuccessful PayGasInERC20AndUpdateCctx keepertest.MockFailedGetSupportedChainFromChainID(observerMock, senderChain) // call InitiateOutbound - cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + cctx := GetERC20Cctx(t, receiver, senderChain, asset, amount) cctx.GetCurrentOutboundParam().ReceiverChainId = chains.ZetaChainPrivnet.ChainId newStatus, err := k.InitiateOutbound(ctx, keeper.InitiateOutboundConfig{CCTX: cctx, ShouldPayGas: true}) require.NoError(t, err) @@ -268,17 +268,17 @@ func TestKeeper_InitiateOutboundZEVMDeposit(t *testing.T) { keepertest.MockGetSupportedChainFromChainID(observerMock, senderChain) // mock successful GetRevertGasLimit for ERC20 - keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain, 100) + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, senderChain, 100) // mock successful PayGasAndUpdateCctx - keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *senderChain, asset) + keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, senderChain, asset) // Mock unsuccessful UpdateNonce observerMock.On("GetChainNonces", mock.Anything, senderChain.ChainName.String()). Return(observertypes.ChainNonces{}, false) // call InitiateOutbound - cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + cctx := GetERC20Cctx(t, receiver, senderChain, asset, amount) cctx.GetCurrentOutboundParam().ReceiverChainId = chains.ZetaChainPrivnet.ChainId newStatus, err := k.InitiateOutbound(ctx, keeper.InitiateOutboundConfig{CCTX: cctx, ShouldPayGas: true}) require.NoError(t, err) @@ -306,19 +306,16 @@ func TestKeeper_InitiateOutboundZEVMDeposit(t *testing.T) { // mock unsuccessful HandleEVMDeposit which reverts , i.e returns err and isContractReverted = true keepertest.MockRevertForHandleEVMDeposit(fungibleMock, receiver, amount, senderChain.ChainId, errDeposit) - // Mock successful GetSupportedChainFromChainID - keepertest.MockGetSupportedChainFromChainID(observerMock, senderChain) - // mock successful GetRevertGasLimit for ERC20 - keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain, 100) + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, senderChain, 100) // mock successful PayGasAndUpdateCctx - keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *senderChain, asset) + keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, senderChain, asset) // mock successful UpdateNonce - updatedNonce := keepertest.MockUpdateNonce(observerMock, *senderChain) + updatedNonce := keepertest.MockUpdateNonce(observerMock, senderChain) // call InitiateOutbound - cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + cctx := GetERC20Cctx(t, receiver, senderChain, asset, amount) cctx.GetCurrentOutboundParam().ReceiverChainId = chains.ZetaChainPrivnet.ChainId newStatus, err := k.InitiateOutbound(ctx, keeper.InitiateOutboundConfig{CCTX: cctx, ShouldPayGas: true}) require.NoError(t, err) @@ -352,10 +349,10 @@ func TestKeeper_InitiateOutboundZEVMDeposit(t *testing.T) { keepertest.MockGetSupportedChainFromChainID(observerMock, senderChain) // mock successful GetRevertGasLimit for ERC20 - keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain, 100) + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, senderChain, 100) // call InitiateOutbound - cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + cctx := GetERC20Cctx(t, receiver, senderChain, asset, amount) cctx.GetCurrentOutboundParam().ReceiverChainId = chains.ZetaChainPrivnet.ChainId cctx.OutboundParams = append(cctx.OutboundParams, cctx.GetCurrentOutboundParam()) newStatus, err := k.InitiateOutbound(ctx, keeper.InitiateOutboundConfig{CCTX: cctx, ShouldPayGas: true}) @@ -386,18 +383,27 @@ func TestKeeper_InitiateOutboundProcessCrosschainMsgPassing(t *testing.T) { receiverChain := getValidEthChain() // mock successful PayGasAndUpdateCctx - keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *receiverChain, "") + keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, receiverChain, "") // mock successful UpdateNonce - updatedNonce := keepertest.MockUpdateNonce(observerMock, *receiverChain) + nonce := uint64(1) + tss := sample.Tss() + observerMock.On("GetChainNonces", mock.Anything, receiverChain.ChainName.String()). + Return(observertypes.ChainNonces{Nonce: nonce}, true) + observerMock.On("GetTSS", mock.Anything). + Return(tss, true) + observerMock.On("GetPendingNonces", mock.Anything, tss.TssPubkey, mock.Anything). + Return(observertypes.PendingNonces{NonceHigh: int64(nonce)}, true) + observerMock.On("SetChainNonces", mock.Anything, mock.Anything) + observerMock.On("SetPendingNonces", mock.Anything, mock.Anything) // call InitiateOutbound - cctx := GetERC20Cctx(t, receiver, *receiverChain, "", amount) + cctx := GetERC20Cctx(t, receiver, receiverChain, "", amount) newStatus, err := k.InitiateOutbound(ctx, keeper.InitiateOutboundConfig{CCTX: cctx, ShouldPayGas: true}) require.NoError(t, err) require.Equal(t, types.CctxStatus_PendingOutbound, cctx.CctxStatus.Status) require.Equal(t, types.CctxStatus_PendingOutbound, newStatus) - require.Equal(t, updatedNonce, cctx.GetCurrentOutboundParam().TssNonce) + require.Equal(t, nonce, cctx.GetCurrentOutboundParam().TssNonce) }) t.Run("unable to process crosschain msg passing PayGasAndUpdateCctx fails", func(t *testing.T) { @@ -413,10 +419,10 @@ func TestKeeper_InitiateOutboundProcessCrosschainMsgPassing(t *testing.T) { receiverChain := getValidEthChain() // mock unsuccessful PayGasAndUpdateCctx - keepertest.MockFailedGetSupportedChainFromChainID(observerMock, nil) + keepertest.MockFailedGetSupportedChainFromChainID(observerMock, receiverChain) // call InitiateOutbound - cctx := GetERC20Cctx(t, receiver, *receiverChain, "", amount) + cctx := GetERC20Cctx(t, receiver, receiverChain, "", amount) newStatus, err := k.InitiateOutbound(ctx, keeper.InitiateOutboundConfig{CCTX: cctx, ShouldPayGas: true}) require.ErrorIs(t, err, observertypes.ErrSupportedChains) require.Equal(t, types.CctxStatus_Aborted, cctx.CctxStatus.Status) @@ -438,14 +444,14 @@ func TestKeeper_InitiateOutboundProcessCrosschainMsgPassing(t *testing.T) { receiverChain := getValidEthChain() // mock successful PayGasAndUpdateCctx - keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *receiverChain, "") + keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, receiverChain, "") // mock unsuccessful UpdateNonce observerMock.On("GetChainNonces", mock.Anything, receiverChain.ChainName.String()). Return(observertypes.ChainNonces{}, false) // call InitiateOutbound - cctx := GetERC20Cctx(t, receiver, *receiverChain, "", amount) + cctx := GetERC20Cctx(t, receiver, receiverChain, "", amount) newStatus, err := k.InitiateOutbound(ctx, keeper.InitiateOutboundConfig{CCTX: cctx, ShouldPayGas: true}) require.ErrorContains(t, err, "cannot find receiver chain nonce") require.Equal(t, types.CctxStatus_Aborted, cctx.CctxStatus.Status) @@ -467,7 +473,7 @@ func TestKeeper_InitiateOutboundFailures(t *testing.T) { receiverChain := getValidEthChain() receiverChain.ChainId = 123 // call InitiateOutbound - cctx := GetERC20Cctx(t, receiver, *receiverChain, "", amount) + cctx := GetERC20Cctx(t, receiver, receiverChain, "", amount) newStatus, err := k.InitiateOutbound(ctx, keeper.InitiateOutboundConfig{CCTX: cctx, ShouldPayGas: true}) require.Error(t, err) require.Equal(t, types.CctxStatus_PendingInbound, newStatus) diff --git a/x/crosschain/keeper/msg_server_add_inbound_tracker.go b/x/crosschain/keeper/msg_server_add_inbound_tracker.go index fd9b8fa2bd..ae35036e88 100644 --- a/x/crosschain/keeper/msg_server_add_inbound_tracker.go +++ b/x/crosschain/keeper/msg_server_add_inbound_tracker.go @@ -18,8 +18,8 @@ func (k msgServer) AddInboundTracker( msg *types.MsgAddInboundTracker, ) (*types.MsgAddInboundTrackerResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) - chain := k.GetObserverKeeper().GetSupportedChainFromChainID(ctx, msg.ChainId) - if chain == nil { + + if _, found := k.GetObserverKeeper().GetSupportedChainFromChainID(ctx, msg.ChainId); !found { return nil, observertypes.ErrSupportedChains } diff --git a/x/crosschain/keeper/msg_server_add_inbound_tracker_test.go b/x/crosschain/keeper/msg_server_add_inbound_tracker_test.go index 9d135d513d..0345cba1a1 100644 --- a/x/crosschain/keeper/msg_server_add_inbound_tracker_test.go +++ b/x/crosschain/keeper/msg_server_add_inbound_tracker_test.go @@ -33,7 +33,7 @@ func TestMsgServer_AddToInboundTracker(t *testing.T) { txHash := "string" chainID := getValidEthChainID() - observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(&chains.Chain{}) + observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(chains.Chain{}, true) observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(false) msg := types.MsgAddInboundTracker{ @@ -62,7 +62,7 @@ func TestMsgServer_AddToInboundTracker(t *testing.T) { chainID := getValidEthChainID() observerMock := keepertest.GetCrosschainObserverMock(t, k) - observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(nil) + observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(chains.Chain{}, false) msg := types.MsgAddInboundTracker{ Creator: sample.AccAddress(), @@ -92,7 +92,7 @@ func TestMsgServer_AddToInboundTracker(t *testing.T) { txHash := "string" chainID := getValidEthChainID() - observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(&chains.Chain{}) + observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(chains.Chain{}, true) observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(false) setSupportedChain(ctx, zk, chainID) @@ -127,7 +127,7 @@ func TestMsgServer_AddToInboundTracker(t *testing.T) { txHash := "string" chainID := getValidEthChainID() - observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(&chains.Chain{}) + observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(chains.Chain{}, true) observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(true) msg := types.MsgAddInboundTracker{ @@ -161,7 +161,7 @@ func TestMsgServer_AddToInboundTracker(t *testing.T) { txHash := "string" chainID := getValidEthChainID() - observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(&chains.Chain{}) + observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(chains.Chain{}, true) observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(false) lightclientMock.On("VerifyProof", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything). Return(nil, errors.New("error")) @@ -195,7 +195,7 @@ func TestMsgServer_AddToInboundTracker(t *testing.T) { txHash := "string" chainID := getValidEthChainID() - observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(&chains.Chain{}) + observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(chains.Chain{}, true) observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(false) lightclientMock.On("VerifyProof", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything). Return(sample.Bytes(), nil) @@ -231,7 +231,7 @@ func TestMsgServer_AddToInboundTracker(t *testing.T) { txHash := "string" chainID := getValidEthChainID() - observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(&chains.Chain{}) + observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(chains.Chain{}, true) observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(false) lightclientMock.On("VerifyProof", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything). Return(sample.Bytes(), nil) @@ -271,7 +271,7 @@ func TestMsgServer_AddToInboundTracker(t *testing.T) { txHash := "string" chainID := getValidEthChainID() - observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(&chains.Chain{}) + observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(chains.Chain{}, true) observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(false) observerMock.On("GetChainParamsByChainID", mock.Anything, mock.Anything). Return(sample.ChainParams(chains.Ethereum.ChainId), true) @@ -317,7 +317,7 @@ func TestMsgServer_AddToInboundTracker(t *testing.T) { observerMock := keepertest.GetCrosschainObserverMock(t, k) lightclientMock := keepertest.GetCrosschainLightclientMock(t, k) - observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(&chains.Chain{}) + observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(chains.Chain{}, true) observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(false) observerMock.On("GetChainParamsByChainID", mock.Anything, mock.Anything). Return(sample.ChainParams(chains.Ethereum.ChainId), true) diff --git a/x/crosschain/keeper/msg_server_add_outbound_tracker.go b/x/crosschain/keeper/msg_server_add_outbound_tracker.go index ce7b2f0c03..5a3c98e9e9 100644 --- a/x/crosschain/keeper/msg_server_add_outbound_tracker.go +++ b/x/crosschain/keeper/msg_server_add_outbound_tracker.go @@ -27,8 +27,7 @@ func (k msgServer) AddOutboundTracker( ctx := sdk.UnwrapSDKContext(goCtx) // check the chain is supported - chain := k.GetObserverKeeper().GetSupportedChainFromChainID(ctx, msg.ChainId) - if chain == nil { + if _, found := k.GetObserverKeeper().GetSupportedChainFromChainID(ctx, msg.ChainId); !found { return nil, observertypes.ErrSupportedChains } @@ -138,7 +137,7 @@ func verifyProofAndOutboundBody(ctx sdk.Context, k msgServer, msg *types.MsgAddO // get tss address var bitcoinChainID int64 - if chains.IsBitcoinChain(msg.ChainId) { + if chains.IsBitcoinChain(msg.ChainId, k.GetAuthorityKeeper().GetAdditionalChainList(ctx)) { bitcoinChainID = msg.ChainId } diff --git a/x/crosschain/keeper/msg_server_add_outbound_tracker_test.go b/x/crosschain/keeper/msg_server_add_outbound_tracker_test.go index e43800b2ac..7abe63fe15 100644 --- a/x/crosschain/keeper/msg_server_add_outbound_tracker_test.go +++ b/x/crosschain/keeper/msg_server_add_outbound_tracker_test.go @@ -39,7 +39,7 @@ func TestMsgServer_AddToOutboundTracker(t *testing.T) { authorityMock := keepertest.GetCrosschainAuthorityMock(t, k) observerMock := keepertest.GetCrosschainObserverMock(t, k) - observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(&chains.Chain{}) + observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(chains.Chain{}, true) observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(false) keepertest.MockCctxByNonce(t, ctx, *k, observerMock, types.CctxStatus_PendingOutbound, false) @@ -74,7 +74,7 @@ func TestMsgServer_AddToOutboundTracker(t *testing.T) { chainID := getEthereumChainID() hash := sample.Hash().Hex() - observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(&chains.Chain{}) + observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(chains.Chain{}, true) observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(true) keepertest.MockCctxByNonce(t, ctx, *k, observerMock, types.CctxStatus_PendingOutbound, false) @@ -110,7 +110,7 @@ func TestMsgServer_AddToOutboundTracker(t *testing.T) { existinghHash := sample.Hash().Hex() newHash := sample.Hash().Hex() - observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(&chains.Chain{}) + observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(chains.Chain{}, true) observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(false) keepertest.MockCctxByNonce(t, ctx, *k, observerMock, types.CctxStatus_PendingOutbound, false) @@ -163,7 +163,7 @@ func TestMsgServer_AddToOutboundTracker(t *testing.T) { } observerMock := keepertest.GetCrosschainObserverMock(t, k) - observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(&chains.Chain{}) + observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(chains.Chain{}, true) // set cctx status to outbound mined keepertest.MockCctxByNonce(t, ctx, *k, observerMock, types.CctxStatus_OutboundMined, false) @@ -187,7 +187,7 @@ func TestMsgServer_AddToOutboundTracker(t *testing.T) { admin := sample.AccAddress() observerMock := keepertest.GetCrosschainObserverMock(t, k) - observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(nil) + observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(chains.Chain{}, false) chainID := getEthereumChainID() @@ -214,7 +214,7 @@ func TestMsgServer_AddToOutboundTracker(t *testing.T) { observerMock := keepertest.GetCrosschainObserverMock(t, k) - observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(&chains.Chain{}) + observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(chains.Chain{}, true) keepertest.MockCctxByNonce(t, ctx, *k, observerMock, types.CctxStatus_PendingOutbound, true) chainID := getEthereumChainID() @@ -245,7 +245,7 @@ func TestMsgServer_AddToOutboundTracker(t *testing.T) { chainID := getEthereumChainID() newHash := sample.Hash().Hex() - observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(&chains.Chain{}) + observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(chains.Chain{}, true) observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(false) keepertest.MockCctxByNonce(t, ctx, *k, observerMock, types.CctxStatus_PendingOutbound, false) @@ -291,7 +291,7 @@ func TestMsgServer_AddToOutboundTracker(t *testing.T) { authorityMock := keepertest.GetCrosschainAuthorityMock(t, k) observerMock := keepertest.GetCrosschainObserverMock(t, k) - observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(&chains.Chain{}) + observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(chains.Chain{}, true) observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(false) keepertest.MockCctxByNonce(t, ctx, *k, observerMock, types.CctxStatus_PendingOutbound, false) @@ -340,7 +340,7 @@ func TestMsgServer_AddToOutboundTracker(t *testing.T) { observerMock := keepertest.GetCrosschainObserverMock(t, k) lightclientMock := keepertest.GetCrosschainLightclientMock(t, k) - observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(&chains.Chain{}) + observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(chains.Chain{}, true) observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(false) keepertest.MockCctxByNonce(t, ctx, *k, observerMock, types.CctxStatus_PendingOutbound, false) observerMock.On("GetTssAddress", mock.Anything, mock.Anything).Return(&observertypes.QueryGetTssAddressResponse{ @@ -359,6 +359,7 @@ func TestMsgServer_AddToOutboundTracker(t *testing.T) { Nonce: 42, } keepertest.MockCheckAuthorization(&authorityMock.Mock, &msg, authoritytypes.ErrUnauthorized) + keepertest.MockGetChainListEmpty(&authorityMock.Mock) _, err := msgServer.AddOutboundTracker(ctx, &msg) require.NoError(t, err) tracker, found := k.GetOutboundTracker(ctx, chainID, 42) @@ -384,7 +385,7 @@ func TestMsgServer_AddToOutboundTracker(t *testing.T) { observerMock := keepertest.GetCrosschainObserverMock(t, k) lightclientMock := keepertest.GetCrosschainLightclientMock(t, k) - observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(&chains.Chain{}) + observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(chains.Chain{}, true) observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(false) keepertest.MockCctxByNonce(t, ctx, *k, observerMock, types.CctxStatus_PendingOutbound, false) observerMock.On("GetTssAddress", mock.Anything, mock.Anything).Return(&observertypes.QueryGetTssAddressResponse{ @@ -418,6 +419,7 @@ func TestMsgServer_AddToOutboundTracker(t *testing.T) { Nonce: 42, } keepertest.MockCheckAuthorization(&authorityMock.Mock, &msg, authoritytypes.ErrUnauthorized) + keepertest.MockGetChainListEmpty(&authorityMock.Mock) _, err := msgServer.AddOutboundTracker(ctx, &msg) require.NoError(t, err) tracker, found := k.GetOutboundTracker(ctx, chainID, 42) @@ -444,7 +446,7 @@ func TestMsgServer_AddToOutboundTracker(t *testing.T) { observerMock := keepertest.GetCrosschainObserverMock(t, k) lightclientMock := keepertest.GetCrosschainLightclientMock(t, k) - observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(&chains.Chain{}) + observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(chains.Chain{}, true) observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(false) keepertest.MockCctxByNonce(t, ctx, *k, observerMock, types.CctxStatus_PendingOutbound, false) lightclientMock.On("VerifyProof", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything). @@ -481,7 +483,7 @@ func TestMsgServer_AddToOutboundTracker(t *testing.T) { observerMock := keepertest.GetCrosschainObserverMock(t, k) lightclientMock := keepertest.GetCrosschainLightclientMock(t, k) - observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(&chains.Chain{}) + observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(chains.Chain{}, true) observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(false) keepertest.MockCctxByNonce(t, ctx, *k, observerMock, types.CctxStatus_PendingOutbound, false) lightclientMock.On("VerifyProof", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything). @@ -500,6 +502,7 @@ func TestMsgServer_AddToOutboundTracker(t *testing.T) { Nonce: 42, } keepertest.MockCheckAuthorization(&authorityMock.Mock, &msg, authoritytypes.ErrUnauthorized) + keepertest.MockGetChainListEmpty(&authorityMock.Mock) _, err := msgServer.AddOutboundTracker(ctx, &msg) require.ErrorIs(t, err, observertypes.ErrTssNotFound) }) @@ -520,7 +523,7 @@ func TestMsgServer_AddToOutboundTracker(t *testing.T) { observerMock := keepertest.GetCrosschainObserverMock(t, k) lightclientMock := keepertest.GetCrosschainLightclientMock(t, k) - observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(&chains.Chain{}) + observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(chains.Chain{}, true) observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(false) keepertest.MockCctxByNonce(t, ctx, *k, observerMock, types.CctxStatus_PendingOutbound, false) observerMock.On("GetTssAddress", mock.Anything, mock.Anything).Return(&observertypes.QueryGetTssAddressResponse{ @@ -541,6 +544,7 @@ func TestMsgServer_AddToOutboundTracker(t *testing.T) { Nonce: 42, } keepertest.MockCheckAuthorization(&authorityMock.Mock, &msg, authoritytypes.ErrUnauthorized) + keepertest.MockGetChainListEmpty(&authorityMock.Mock) _, err := msgServer.AddOutboundTracker(ctx, &msg) require.ErrorIs(t, err, types.ErrTxBodyVerificationFail) }) diff --git a/x/crosschain/keeper/msg_server_migrate_tss_funds.go b/x/crosschain/keeper/msg_server_migrate_tss_funds.go index 05f218162f..f5558fe689 100644 --- a/x/crosschain/keeper/msg_server_migrate_tss_funds.go +++ b/x/crosschain/keeper/msg_server_migrate_tss_funds.go @@ -143,9 +143,14 @@ func (k Keeper) MigrateTSSFundsForChain( EffectiveGasPrice: sdkmath.Int{}, EffectiveGasLimit: 0, TssPubkey: currentTss.TssPubkey, - }}} + }}, + } + + // retrieve from authority keeper additional chains + additionalChains := k.GetAuthorityKeeper().GetAdditionalChainList(ctx) + // Set the sender and receiver addresses for EVM chain - if chains.IsEVMChain(chainID) { + if chains.IsEVMChain(chainID, additionalChains) { ethAddressOld, err := zetacrypto.GetTssAddrEVM(currentTss.TssPubkey) if err != nil { return err @@ -179,7 +184,7 @@ func (k Keeper) MigrateTSSFundsForChain( cctx.GetCurrentOutboundParam().Amount = amount.Sub(evmFee) } // Set the sender and receiver addresses for Bitcoin chain - if chains.IsBitcoinChain(chainID) { + if chains.IsBitcoinChain(chainID, additionalChains) { bitcoinNetParams, err := chains.BitcoinNetParamsFromChainID(chainID) if err != nil { return err diff --git a/x/crosschain/keeper/msg_server_migrate_tss_funds_test.go b/x/crosschain/keeper/msg_server_migrate_tss_funds_test.go index fbd3c870bf..9da596f876 100644 --- a/x/crosschain/keeper/msg_server_migrate_tss_funds_test.go +++ b/x/crosschain/keeper/msg_server_migrate_tss_funds_test.go @@ -99,7 +99,7 @@ func TestKeeper_MigrateTSSFundsForChain(t *testing.T) { msgServer := keeper.NewMsgServerImpl(*k) - indexString, _ := setupTssMigrationParams(zk, k, ctx, *chain, amount, true, true) + indexString, _ := setupTssMigrationParams(zk, k, ctx, chain, amount, true, true) gp, found := k.GetMedianGasPriceInUint(ctx, chain.ChainId) require.True(t, found) msg := crosschaintypes.MsgMigrateTssFunds{ @@ -108,6 +108,7 @@ func TestKeeper_MigrateTSSFundsForChain(t *testing.T) { Amount: amount, } keepertest.MockCheckAuthorization(&authorityMock.Mock, &msg, nil) + keepertest.MockGetChainListEmpty(&authorityMock.Mock) _, err := msgServer.MigrateTssFunds(ctx, &msg) require.NoError(t, err) hash := crypto.Keccak256Hash([]byte(indexString)) @@ -131,7 +132,7 @@ func TestKeeper_MigrateTSSFundsForChain(t *testing.T) { authorityMock := keepertest.GetCrosschainAuthorityMock(t, k) msgServer := keeper.NewMsgServerImpl(*k) - indexString, _ := setupTssMigrationParams(zk, k, ctx, *chain, amount, true, true) + indexString, _ := setupTssMigrationParams(zk, k, ctx, chain, amount, true, true) gp, found := k.GetMedianGasPriceInUint(ctx, chain.ChainId) require.True(t, found) @@ -141,6 +142,7 @@ func TestKeeper_MigrateTSSFundsForChain(t *testing.T) { Amount: amount, } keepertest.MockCheckAuthorization(&authorityMock.Mock, &msg, nil) + keepertest.MockGetChainListEmpty(&authorityMock.Mock) _, err := msgServer.MigrateTssFunds(ctx, &msg) require.NoError(t, err) hash := crypto.Keccak256Hash([]byte(indexString)) @@ -368,7 +370,7 @@ func TestMsgServer_MigrateTssFunds(t *testing.T) { msgServer := keeper.NewMsgServerImpl(*k) - indexString, _ := setupTssMigrationParams(zk, k, ctx, *chain, amount, true, true) + indexString, _ := setupTssMigrationParams(zk, k, ctx, chain, amount, true, true) msg := crosschaintypes.MsgMigrateTssFunds{ Creator: admin, @@ -376,6 +378,7 @@ func TestMsgServer_MigrateTssFunds(t *testing.T) { Amount: amount, } keepertest.MockCheckAuthorization(&authorityMock.Mock, &msg, nil) + keepertest.MockGetChainListEmpty(&authorityMock.Mock) _, err := msgServer.MigrateTssFunds(ctx, &msg) require.NoError(t, err) hash := crypto.Keccak256Hash([]byte(indexString)) @@ -398,7 +401,7 @@ func TestMsgServer_MigrateTssFunds(t *testing.T) { authorityMock := keepertest.GetCrosschainAuthorityMock(t, k) msgServer := keeper.NewMsgServerImpl(*k) - indexString, _ := setupTssMigrationParams(zk, k, ctx, *chain, amount, true, true) + indexString, _ := setupTssMigrationParams(zk, k, ctx, chain, amount, true, true) msg := crosschaintypes.MsgMigrateTssFunds{ Creator: admin, @@ -406,6 +409,7 @@ func TestMsgServer_MigrateTssFunds(t *testing.T) { Amount: amount, } keepertest.MockCheckAuthorization(&authorityMock.Mock, &msg, nil) + keepertest.MockGetChainListEmpty(&authorityMock.Mock) _, err := msgServer.MigrateTssFunds(ctx, &msg) require.ErrorContains(t, err, crosschaintypes.ErrCannotMigrateTssFunds.Error()) hash := crypto.Keccak256Hash([]byte(indexString)) @@ -425,7 +429,7 @@ func TestMsgServer_MigrateTssFunds(t *testing.T) { authorityMock := keepertest.GetCrosschainAuthorityMock(t, k) msgServer := keeper.NewMsgServerImpl(*k) - indexString, _ := setupTssMigrationParams(zk, k, ctx, *chain, amount, false, true) + indexString, _ := setupTssMigrationParams(zk, k, ctx, chain, amount, false, true) msg := crosschaintypes.MsgMigrateTssFunds{ Creator: admin, @@ -452,7 +456,7 @@ func TestMsgServer_MigrateTssFunds(t *testing.T) { authorityMock := keepertest.GetCrosschainAuthorityMock(t, k) msgServer := keeper.NewMsgServerImpl(*k) - indexString, tssPubkey := setupTssMigrationParams(zk, k, ctx, *chain, amount, true, true) + indexString, tssPubkey := setupTssMigrationParams(zk, k, ctx, chain, amount, true, true) k.GetObserverKeeper().SetPendingNonces(ctx, observertypes.PendingNonces{ NonceLow: 1, NonceHigh: 10, @@ -486,7 +490,7 @@ func TestMsgServer_MigrateTssFunds(t *testing.T) { authorityMock := keepertest.GetCrosschainAuthorityMock(t, k) msgServer := keeper.NewMsgServerImpl(*k) - indexString, tssPubkey := setupTssMigrationParams(zk, k, ctx, *chain, amount, true, true) + indexString, tssPubkey := setupTssMigrationParams(zk, k, ctx, chain, amount, true, true) k.GetObserverKeeper().SetPendingNonces(ctx, observertypes.PendingNonces{ NonceLow: 1, NonceHigh: 1, @@ -507,6 +511,7 @@ func TestMsgServer_MigrateTssFunds(t *testing.T) { Amount: amount, } keepertest.MockCheckAuthorization(&authorityMock.Mock, &msg, nil) + keepertest.MockGetChainListEmpty(&authorityMock.Mock) _, err := msgServer.MigrateTssFunds(ctx, &msg) require.ErrorIs(t, err, crosschaintypes.ErrCannotMigrateTssFunds) require.ErrorContains(t, err, "cannot migrate funds while there are pending migrations") @@ -532,7 +537,7 @@ func TestMsgServer_MigrateTssFunds(t *testing.T) { msgServer := keeper.NewMsgServerImpl(*k) - indexString, _ := setupTssMigrationParams(zk, k, ctx, *chain, amount, false, false) + indexString, _ := setupTssMigrationParams(zk, k, ctx, chain, amount, false, false) currentTss, found := k.GetObserverKeeper().GetTSS(ctx) require.True(t, found) newTss := sample.Tss() diff --git a/x/crosschain/keeper/msg_server_refund_aborted_tx_test.go b/x/crosschain/keeper/msg_server_refund_aborted_tx_test.go index bf3678ecaf..91ef323ad9 100644 --- a/x/crosschain/keeper/msg_server_refund_aborted_tx_test.go +++ b/x/crosschain/keeper/msg_server_refund_aborted_tx_test.go @@ -116,6 +116,7 @@ func TestMsgServer_RefundAbortedCCTX(t *testing.T) { RefundAddress: cctx.InboundParams.Sender, } keepertest.MockCheckAuthorization(&authorityMock.Mock, &msg, nil) + keepertest.MockGetChainListEmpty(&authorityMock.Mock) _, err := msgServer.RefundAbortedCCTX(ctx, &msg) require.NoError(t, err) @@ -160,6 +161,7 @@ func TestMsgServer_RefundAbortedCCTX(t *testing.T) { RefundAddress: cctx.InboundParams.Sender, } keepertest.MockCheckAuthorization(&authorityMock.Mock, &msg, nil) + keepertest.MockGetChainListEmpty(&authorityMock.Mock) _, err := msgServer.RefundAbortedCCTX(ctx, &msg) require.NoError(t, err) @@ -274,6 +276,7 @@ func TestMsgServer_RefundAbortedCCTX(t *testing.T) { RefundAddress: refundAddress.String(), } keepertest.MockCheckAuthorization(&authorityMock.Mock, &msg, nil) + keepertest.MockGetChainListEmpty(&authorityMock.Mock) _, err := msgServer.RefundAbortedCCTX(ctx, &msg) require.NoError(t, err) @@ -325,6 +328,7 @@ func TestMsgServer_RefundAbortedCCTX(t *testing.T) { RefundAddress: cctx.InboundParams.Sender, } keepertest.MockCheckAuthorization(&authorityMock.Mock, &msg, nil) + keepertest.MockGetChainListEmpty(&authorityMock.Mock) _, err := msgServer.RefundAbortedCCTX(ctx, &msg) require.NoError(t, err) diff --git a/x/crosschain/keeper/msg_server_vote_gas_price.go b/x/crosschain/keeper/msg_server_vote_gas_price.go index 2fd84affc3..a5fbaf4c0c 100644 --- a/x/crosschain/keeper/msg_server_vote_gas_price.go +++ b/x/crosschain/keeper/msg_server_vote_gas_price.go @@ -26,8 +26,8 @@ func (k msgServer) VoteGasPrice( ) (*types.MsgVoteGasPriceResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) - chain := k.zetaObserverKeeper.GetSupportedChainFromChainID(ctx, msg.ChainId) - if chain == nil { + chain, found := k.zetaObserverKeeper.GetSupportedChainFromChainID(ctx, msg.ChainId) + if !found { return nil, cosmoserrors.Wrap(types.ErrUnsupportedChain, fmt.Sprintf("ChainID : %d ", msg.ChainId)) } if ok := k.zetaObserverKeeper.IsNonTombstonedObserver(ctx, msg.Creator); !ok { diff --git a/x/crosschain/keeper/msg_server_vote_gas_price_test.go b/x/crosschain/keeper/msg_server_vote_gas_price_test.go index a876e2582c..b5da0f0c1e 100644 --- a/x/crosschain/keeper/msg_server_vote_gas_price_test.go +++ b/x/crosschain/keeper/msg_server_vote_gas_price_test.go @@ -21,7 +21,7 @@ func TestMsgServer_VoteGasPrice(t *testing.T) { }) observerMock := keepertest.GetCrosschainObserverMock(t, k) - keepertest.MockFailedGetSupportedChainFromChainID(observerMock, nil) + keepertest.MockFailedGetSupportedChainFromChainID(observerMock, sample.Chain(5)) msgServer := keeper.NewMsgServerImpl(*k) res, err := msgServer.VoteGasPrice(ctx, &types.MsgVoteGasPrice{ @@ -37,7 +37,7 @@ func TestMsgServer_VoteGasPrice(t *testing.T) { }) observerMock := keepertest.GetCrosschainObserverMock(t, k) - keepertest.MockGetSupportedChainFromChainID(observerMock, nil) + keepertest.MockGetSupportedChainFromChainID(observerMock, sample.Chain(5)) observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(false) msgServer := keeper.NewMsgServerImpl(*k) @@ -56,7 +56,7 @@ func TestMsgServer_VoteGasPrice(t *testing.T) { }) observerMock := keepertest.GetCrosschainObserverMock(t, k) - keepertest.MockGetSupportedChainFromChainID(observerMock, &chains.Chain{ + keepertest.MockGetSupportedChainFromChainID(observerMock, chains.Chain{ ChainId: 5, }) observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(true) @@ -81,7 +81,7 @@ func TestMsgServer_VoteGasPrice(t *testing.T) { }) observerMock := keepertest.GetCrosschainObserverMock(t, k) - keepertest.MockGetSupportedChainFromChainID(observerMock, &chains.Chain{ + keepertest.MockGetSupportedChainFromChainID(observerMock, chains.Chain{ ChainId: 5, }) observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(true) @@ -118,7 +118,7 @@ func TestMsgServer_VoteGasPrice(t *testing.T) { }) observerMock := keepertest.GetCrosschainObserverMock(t, k) - keepertest.MockGetSupportedChainFromChainID(observerMock, &chains.Chain{ + keepertest.MockGetSupportedChainFromChainID(observerMock, chains.Chain{ ChainId: 5, }) observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(true) @@ -164,7 +164,7 @@ func TestMsgServer_VoteGasPrice(t *testing.T) { }) observerMock := keepertest.GetCrosschainObserverMock(t, k) - keepertest.MockGetSupportedChainFromChainID(observerMock, &chains.Chain{ + keepertest.MockGetSupportedChainFromChainID(observerMock, chains.Chain{ ChainId: 5, }) observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(true) diff --git a/x/crosschain/keeper/msg_server_vote_inbound_tx_test.go b/x/crosschain/keeper/msg_server_vote_inbound_tx_test.go index 64a2153611..be03a407e5 100644 --- a/x/crosschain/keeper/msg_server_vote_inbound_tx_test.go +++ b/x/crosschain/keeper/msg_server_vote_inbound_tx_test.go @@ -53,10 +53,10 @@ func TestKeeper_VoteInbound(t *testing.T) { to, from := int64(1337), int64(101) supportedChains := zk.ObserverKeeper.GetSupportedChains(ctx) for _, chain := range supportedChains { - if chains.IsEVMChain(chain.ChainId) { + if chains.IsEVMChain(chain.ChainId, []chains.Chain{}) { from = chain.ChainId } - if chains.IsZetaChain(chain.ChainId) { + if chains.IsZetaChain(chain.ChainId, []chains.Chain{}) { to = chain.ChainId } } @@ -78,10 +78,14 @@ func TestKeeper_VoteInbound(t *testing.T) { ) require.NoError(t, err) } + + chain, found := zk.ObserverKeeper.GetSupportedChainFromChainID(ctx, msg.SenderChainId) + require.True(t, found) + ballot, _, _ := zk.ObserverKeeper.FindBallot( ctx, msg.Digest(), - zk.ObserverKeeper.GetSupportedChainFromChainID(ctx, msg.SenderChainId), + chain, observertypes.ObservationType_InboundTx, ) require.Equal(t, ballot.BallotStatus, observertypes.BallotStatus_BallotFinalized_SuccessObservation) @@ -201,10 +205,10 @@ func TestKeeper_VoteInbound(t *testing.T) { to, from := int64(1337), int64(101) supportedChains := zk.ObserverKeeper.GetSupportedChains(ctx) for _, chain := range supportedChains { - if chains.IsEVMChain(chain.ChainId) { + if chains.IsEVMChain(chain.ChainId, []chains.Chain{}) { from = chain.ChainId } - if chains.IsZetaChain(chain.ChainId) { + if chains.IsZetaChain(chain.ChainId, []chains.Chain{}) { to = chain.ChainId } } @@ -219,16 +223,20 @@ func TestKeeper_VoteInbound(t *testing.T) { ) require.NoError(t, err) } + + chain, found := zk.ObserverKeeper.GetSupportedChainFromChainID(ctx, msg.SenderChainId) + require.True(t, found) + ballot, _, _ := zk.ObserverKeeper.FindBallot( ctx, msg.Digest(), - zk.ObserverKeeper.GetSupportedChainFromChainID(ctx, msg.SenderChainId), + chain, observertypes.ObservationType_InboundTx, ) require.Equal(t, ballot.BallotStatus, observertypes.BallotStatus_BallotInProgress) require.Equal(t, ballot.Votes[0], observertypes.VoteType_SuccessObservation) require.Equal(t, ballot.Votes[1], observertypes.VoteType_NotYetVoted) - _, found := k.GetCrossChainTx(ctx, msg.Digest()) + _, found = k.GetCrossChainTx(ctx, msg.Digest()) require.False(t, found) }) @@ -307,7 +315,7 @@ func TestKeeper_SaveObservedInboundInformation(t *testing.T) { receiver := sample.EthAddress() amount := big.NewInt(42) senderChain := getValidEthChain() - cctx := GetERC20Cctx(t, receiver, *senderChain, "", amount) + cctx := GetERC20Cctx(t, receiver, senderChain, "", amount) eventIndex := sample.Uint64InRange(1, 100) k.SaveObservedInboundInformation(ctx, cctx, eventIndex) require.Equal(t, types.TxFinalizationStatus_Executed, cctx.InboundParams.TxFinalizationStatus) @@ -329,7 +337,7 @@ func TestKeeper_SaveObservedInboundInformation(t *testing.T) { receiver := sample.EthAddress() amount := big.NewInt(42) senderChain := getValidEthChain() - cctx := GetERC20Cctx(t, receiver, *senderChain, "", amount) + cctx := GetERC20Cctx(t, receiver, senderChain, "", amount) hash := sample.Hash() cctx.InboundParams.ObservedHash = hash.String() k.SetInboundTracker(ctx, types.InboundTracker{ diff --git a/x/crosschain/keeper/msg_server_vote_outbound_tx_test.go b/x/crosschain/keeper/msg_server_vote_outbound_tx_test.go index 1fe87d98ea..77e52acede 100644 --- a/x/crosschain/keeper/msg_server_vote_outbound_tx_test.go +++ b/x/crosschain/keeper/msg_server_vote_outbound_tx_test.go @@ -137,14 +137,14 @@ func TestKeeper_VoteOutbound(t *testing.T) { observer := sample.AccAddress() tss := sample.Tss() zk.ObserverKeeper.SetObserverSet(ctx, observertypes.ObserverSet{ObserverList: []string{observer}}) - cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + cctx := GetERC20Cctx(t, receiver, senderChain, asset, amount) cctx.GetCurrentOutboundParam().TssPubkey = tss.TssPubkey cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound k.SetCrossChainTx(ctx, *cctx) observerMock.On("GetTSS", ctx).Return(observertypes.TSS{}, true).Once() // Successfully mock VoteOnOutboundBallot - keepertest.MockVoteOnOutboundSuccessBallot(observerMock, ctx, cctx, *senderChain, observer) + keepertest.MockVoteOnOutboundSuccessBallot(observerMock, ctx, cctx, senderChain, observer) // Successfully mock GetOutbound keepertest.MockGetOutbound(observerMock, ctx) @@ -188,23 +188,22 @@ func TestKeeper_VoteOutbound(t *testing.T) { observer := sample.AccAddress() tss := sample.Tss() zk.ObserverKeeper.SetObserverSet(ctx, observertypes.ObserverSet{ObserverList: []string{observer}}) - cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + cctx := GetERC20Cctx(t, receiver, senderChain, asset, amount) cctx.GetCurrentOutboundParam().TssPubkey = tss.TssPubkey cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound k.SetCrossChainTx(ctx, *cctx) observerMock.On("GetTSS", ctx).Return(observertypes.TSS{}, true).Once() // Successfully mock VoteOnOutboundBallot - keepertest.MockVoteOnOutboundFailedBallot(observerMock, ctx, cctx, *senderChain, observer) + keepertest.MockVoteOnOutboundFailedBallot(observerMock, ctx, cctx, senderChain, observer) // Successfully mock GetOutbound keepertest.MockGetOutbound(observerMock, ctx) // Successfully mock ProcessOutbound - keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain, 100) - keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *senderChain, asset) - keepertest.MockGetSupportedChainFromChainID(observerMock, senderChain) - _ = keepertest.MockUpdateNonce(observerMock, *senderChain) + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, senderChain, 100) + keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, senderChain, asset) + _ = keepertest.MockUpdateNonce(observerMock, senderChain) //Successfully mock SaveOutbound keepertest.MockSaveOutboundNewRevertCreated(observerMock, ctx, cctx, tss) @@ -248,21 +247,21 @@ func TestKeeper_VoteOutbound(t *testing.T) { observer := sample.AccAddress() tss := sample.Tss() zk.ObserverKeeper.SetObserverSet(ctx, observertypes.ObserverSet{ObserverList: []string{observer}}) - cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + cctx := GetERC20Cctx(t, receiver, senderChain, asset, amount) cctx.GetCurrentOutboundParam().TssPubkey = tss.TssPubkey cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound k.SetCrossChainTx(ctx, *cctx) observerMock.On("GetTSS", ctx).Return(observertypes.TSS{}, true).Once() // Successfully mock VoteOnOutboundBallot - keepertest.MockVoteOnOutboundFailedBallot(observerMock, ctx, cctx, *senderChain, observer) + keepertest.MockVoteOnOutboundFailedBallot(observerMock, ctx, cctx, senderChain, observer) // Successfully mock GetOutbound keepertest.MockGetOutbound(observerMock, ctx) // Mock Failed ProcessOutbound - keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain, 100) - keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *senderChain, asset) + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, senderChain, 100) + keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, senderChain, asset) observerMock.On("GetChainNonces", mock.Anything, senderChain.ChainName.String()). Return(observertypes.ChainNonces{}, false) keepertest.MockGetSupportedChainFromChainID(observerMock, senderChain) @@ -312,7 +311,7 @@ func TestKeeper_VoteOutbound(t *testing.T) { observer := sample.AccAddress() tss := sample.Tss() zk.ObserverKeeper.SetObserverSet(ctx, observertypes.ObserverSet{ObserverList: []string{observer}}) - cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + cctx := GetERC20Cctx(t, receiver, senderChain, asset, amount) cctx.GetCurrentOutboundParam().TssPubkey = tss.TssPubkey cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound k.SetCrossChainTx(ctx, *cctx) @@ -321,7 +320,7 @@ func TestKeeper_VoteOutbound(t *testing.T) { observerMock.On("GetTSS", ctx).Return(observertypes.TSS{}, true).Once() // Successfully mock VoteOnOutboundBallot - keepertest.MockVoteOnOutboundFailedBallot(observerMock, ctx, cctx, *senderChain, observer) + keepertest.MockVoteOnOutboundFailedBallot(observerMock, ctx, cctx, senderChain, observer) // Successfully mock GetOutbound keepertest.MockGetOutbound(observerMock, ctx) @@ -330,7 +329,7 @@ func TestKeeper_VoteOutbound(t *testing.T) { fungibleMock.On("GetForeignCoinFromAsset", mock.Anything, mock.Anything, mock.Anything). Return(fungibletypes.ForeignCoins{}, false) - // Successfully mock GetSupportedChainFromChainID + // Successfully mock GetSupportedChainFromChainID keepertest.MockGetSupportedChainFromChainID(observerMock, senderChain) //Successfully mock SaveFailedOutbound @@ -379,7 +378,7 @@ func TestKeeper_VoteOutbound(t *testing.T) { }, ) sk.StakingKeeper.SetValidator(ctx, validator) - cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + cctx := GetERC20Cctx(t, receiver, senderChain, asset, amount) cctx.GetCurrentOutboundParam().TssPubkey = tss.TssPubkey cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound k.SetCrossChainTx(ctx, *cctx) @@ -426,7 +425,7 @@ func TestKeeper_VoteOutbound(t *testing.T) { require.NoError(t, err) zk.ObserverKeeper.SetObserverSet(ctx, observertypes.ObserverSet{ObserverList: []string{accAddress.String()}}) sk.StakingKeeper.SetValidator(ctx, validator) - cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + cctx := GetERC20Cctx(t, receiver, senderChain, asset, amount) cctx.GetCurrentOutboundParam().TssPubkey = tss.TssPubkey cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound k.SetCrossChainTx(ctx, *cctx) diff --git a/x/crosschain/keeper/msg_server_whitelist_erc20.go b/x/crosschain/keeper/msg_server_whitelist_erc20.go index 04ceb4a1a4..e3ace26baa 100644 --- a/x/crosschain/keeper/msg_server_whitelist_erc20.go +++ b/x/crosschain/keeper/msg_server_whitelist_erc20.go @@ -63,8 +63,8 @@ func (k msgServer) WhitelistERC20( return nil, errorsmod.Wrapf(types.ErrCannotFindTSSKeys, "Cannot create new admin cmd of type whitelistERC20") } - chain := k.zetaObserverKeeper.GetSupportedChainFromChainID(ctx, msg.ChainId) - if chain == nil { + chain, found := k.zetaObserverKeeper.GetSupportedChainFromChainID(ctx, msg.ChainId) + if !found { return nil, errorsmod.Wrapf(types.ErrInvalidChainID, "chain id (%d) not supported", msg.ChainId) } diff --git a/x/crosschain/keeper/refund.go b/x/crosschain/keeper/refund.go index 19afd1be1f..a741434705 100644 --- a/x/crosschain/keeper/refund.go +++ b/x/crosschain/keeper/refund.go @@ -70,7 +70,7 @@ func (k Keeper) RefundAmountOnZetaChainZeta( refundAmount := GetAbortedAmount(cctx) chainID := cctx.InboundParams.SenderChainId // check if chain is an EVM chain - if !chains.IsEVMChain(chainID) { + if !chains.IsEVMChain(chainID, k.GetAuthorityKeeper().GetAdditionalChainList(ctx)) { return errors.New("only EVM chains are supported for refund when coin type is Zeta") } if cctx.InboundParams.Amount.IsNil() || cctx.InboundParams.Amount.IsZero() { @@ -96,7 +96,7 @@ func (k Keeper) RefundAmountOnZetaChainERC20( if cctx.InboundParams.CoinType != coin.CoinType_ERC20 { return errors.New("unsupported coin type for refund on ZetaChain") } - if !chains.IsEVMChain(cctx.InboundParams.SenderChainId) { + if !chains.IsEVMChain(cctx.InboundParams.SenderChainId, k.GetAuthorityKeeper().GetAdditionalChainList(ctx)) { return errors.New("only EVM chains are supported for refund on ZetaChain") } diff --git a/x/crosschain/keeper/utils_test.go b/x/crosschain/keeper/utils_test.go index 4539bd1637..6da6a501a2 100644 --- a/x/crosschain/keeper/utils_test.go +++ b/x/crosschain/keeper/utils_test.go @@ -27,14 +27,14 @@ func getValidEthChainID() int64 { } // getValidEthChain() get a valid eth chain -func getValidEthChain() *chains.Chain { +func getValidEthChain() chains.Chain { goerli := chains.GoerliLocalnet - return &goerli + return goerli } -func getValidBTCChain() *chains.Chain { +func getValidBTCChain() chains.Chain { btcRegNet := chains.BitcoinRegtest - return &btcRegNet + return btcRegNet } func getValidBtcChainID() int64 { diff --git a/x/crosschain/migrations/v4/migrate.go b/x/crosschain/migrations/v4/migrate.go index 367e9c54eb..b71fe26b1b 100644 --- a/x/crosschain/migrations/v4/migrate.go +++ b/x/crosschain/migrations/v4/migrate.go @@ -177,7 +177,7 @@ func SetBitcoinFinalizedInbound(ctx sdk.Context, crosschainKeeper crosschainKeep for _, cctx := range crosschainKeeper.GetAllCrossChainTx(ctx) { if cctx.InboundParams != nil { // check if bitcoin inbound - if chains.IsBitcoinChain(cctx.InboundParams.SenderChainId) { + if chains.IsBitcoinChain(cctx.InboundParams.SenderChainId, []chains.Chain{}) { // add finalized inbound crosschainKeeper.AddFinalizedInbound( ctx, diff --git a/x/crosschain/migrations/v5/migrate.go b/x/crosschain/migrations/v5/migrate.go index fcb42dc4d0..bb650991f0 100644 --- a/x/crosschain/migrations/v5/migrate.go +++ b/x/crosschain/migrations/v5/migrate.go @@ -97,11 +97,11 @@ func SetZetaAccounting( switch cctx.InboundParams.CoinType { case coin.CoinType_ERC20: { - receiverChain := observerKeeper.GetSupportedChainFromChainID( + receiverChain, found := observerKeeper.GetSupportedChainFromChainID( ctx, cctx.GetCurrentOutboundParam().ReceiverChainId, ) - if receiverChain == nil { + if !found { ctx.Logger(). Error(fmt.Sprintf("Error getting chain from chain id: %d , cctx index", cctx.GetCurrentOutboundParam().ReceiverChainId), cctx.Index) continue diff --git a/x/crosschain/migrations/v5/migrate_test.go b/x/crosschain/migrations/v5/migrate_test.go index c95535a5b0..d3e55749c7 100644 --- a/x/crosschain/migrations/v5/migrate_test.go +++ b/x/crosschain/migrations/v5/migrate_test.go @@ -49,11 +49,11 @@ func TestMigrateStore(t *testing.T) { for _, cctx := range cctxListUpdated { switch cctx.InboundParams.CoinType { case coin.CoinType_ERC20: - receiverChain := zk.ObserverKeeper.GetSupportedChainFromChainID( + receiverChain, found := zk.ObserverKeeper.GetSupportedChainFromChainID( ctx, cctx.GetCurrentOutboundParam().ReceiverChainId, ) - require.NotNil(t, receiverChain) + require.True(t, found) if receiverChain.IsZetaChain() { require.True(t, cctx.CctxStatus.IsAbortRefunded) } else { diff --git a/x/crosschain/types/cctx_test.go b/x/crosschain/types/cctx_test.go index 1e2df98301..eecdf0cdf0 100644 --- a/x/crosschain/types/cctx_test.go +++ b/x/crosschain/types/cctx_test.go @@ -129,15 +129,6 @@ func TestCrossChainTx_Validate(t *testing.T) { require.ErrorContains(t, cctx.Validate(), "invalid index length 1") cctx = sample.CrossChainTx(t, "foo") cctx.InboundParams = sample.InboundParamsValidChainID(rand.New(rand.NewSource(42))) - cctx.InboundParams.SenderChainId = 1000 - require.ErrorContains(t, cctx.Validate(), "invalid sender chain id 1000") - cctx = sample.CrossChainTx(t, "foo") - cctx.OutboundParams = []*types.OutboundParams{sample.OutboundParamsValidChainID(rand.New(rand.NewSource(42)))} - cctx.InboundParams = sample.InboundParamsValidChainID(rand.New(rand.NewSource(42))) - cctx.InboundParams.ObservedHash = sample.Hash().String() - cctx.InboundParams.BallotIndex = sample.ZetaIndex(t) - cctx.OutboundParams[0].ReceiverChainId = 1000 - require.ErrorContains(t, cctx.Validate(), "invalid receiver chain id 1000") } func TestCrossChainTx_GetCurrentOutboundParam(t *testing.T) { diff --git a/x/crosschain/types/expected_keepers.go b/x/crosschain/types/expected_keepers.go index 6f35afa6c5..57f3d1492f 100644 --- a/x/crosschain/types/expected_keepers.go +++ b/x/crosschain/types/expected_keepers.go @@ -56,7 +56,7 @@ type ObserverKeeper interface { FindBallot( ctx sdk.Context, index string, - chain *chains.Chain, + chain chains.Chain, observationType observertypes.ObservationType, ) (ballot observertypes.Ballot, isNew bool, err error) AddBallotToList(ctx sdk.Context, ballot observertypes.Ballot) @@ -101,9 +101,9 @@ type ObserverKeeper interface { receiveStatus chains.ReceiveStatus, voter string, ) (bool, bool, observertypes.Ballot, string, error) - GetSupportedChainFromChainID(ctx sdk.Context, chainID int64) *chains.Chain - GetSupportedChains(ctx sdk.Context) []*chains.Chain - GetSupportedForeignChains(ctx sdk.Context) []*chains.Chain + GetSupportedChainFromChainID(ctx sdk.Context, chainID int64) (chains.Chain, bool) + GetSupportedChains(ctx sdk.Context) []chains.Chain + GetSupportedForeignChains(ctx sdk.Context) []chains.Chain } type FungibleKeeper interface { @@ -209,6 +209,7 @@ type FungibleKeeper interface { type AuthorityKeeper interface { CheckAuthorization(ctx sdk.Context, msg sdk.Msg) error + GetAdditionalChainList(ctx sdk.Context) (list []chains.Chain) } type LightclientKeeper interface { diff --git a/x/crosschain/types/inbound_params.go b/x/crosschain/types/inbound_params.go index f191d15e2d..18d75cd80f 100644 --- a/x/crosschain/types/inbound_params.go +++ b/x/crosschain/types/inbound_params.go @@ -2,8 +2,6 @@ package types import ( "fmt" - - "github.com/zeta-chain/zetacore/pkg/chains" ) func (m InboundParams) Validate() error { @@ -11,10 +9,6 @@ func (m InboundParams) Validate() error { return fmt.Errorf("sender cannot be empty") } - if chains.GetChainFromChainID(m.SenderChainId) == nil { - return fmt.Errorf("invalid sender chain id %d", m.SenderChainId) - } - if m.Amount.IsNil() { return fmt.Errorf("amount cannot be nil") } diff --git a/x/crosschain/types/inbound_params_test.go b/x/crosschain/types/inbound_params_test.go index 464f685475..42d92a8f3f 100644 --- a/x/crosschain/types/inbound_params_test.go +++ b/x/crosschain/types/inbound_params_test.go @@ -17,10 +17,6 @@ func TestInboundTxParams_Validate(t *testing.T) { inboundParams.Sender = "" require.ErrorContains(t, inboundParams.Validate(), "sender cannot be empty") - inboundParams = sample.InboundParamsValidChainID(r) - inboundParams.SenderChainId = 1000 - require.ErrorContains(t, inboundParams.Validate(), "invalid sender chain id 1000") - inboundParams = sample.InboundParamsValidChainID(r) inboundParams.Amount = sdkmath.Uint{} require.ErrorContains(t, inboundParams.Validate(), "amount cannot be nil") diff --git a/x/crosschain/types/message_add_inbound_tracker.go b/x/crosschain/types/message_add_inbound_tracker.go index 0734033569..1c4a0691e7 100644 --- a/x/crosschain/types/message_add_inbound_tracker.go +++ b/x/crosschain/types/message_add_inbound_tracker.go @@ -5,7 +5,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/zeta-chain/zetacore/pkg/chains" "github.com/zeta-chain/zetacore/pkg/coin" ) @@ -48,20 +47,10 @@ func (msg *MsgAddInboundTracker) ValidateBasic() error { if err != nil { return errorsmod.Wrapf(sdkerrors.ErrInvalidAddress, "invalid creator address (%s)", err) } - chain := chains.GetChainFromChainID(msg.ChainId) - if chain == nil { - return errorsmod.Wrapf(ErrInvalidChainID, "chain id (%d)", msg.ChainId) - } - if msg.Proof != nil && !chain.SupportMerkleProof() { - return errorsmod.Wrapf( - ErrProofVerificationFail, - "chain id %d does not support proof-based trackers", - msg.ChainId, - ) - } + _, ok := coin.CoinType_value[msg.CoinType.String()] if !ok { - return errorsmod.Wrapf(ErrProofVerificationFail, "coin-type not supported") + return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "coin-type not supported") } return nil } diff --git a/x/crosschain/types/message_add_inbound_tracker_test.go b/x/crosschain/types/message_add_inbound_tracker_test.go index 6251990d63..503c020c1d 100644 --- a/x/crosschain/types/message_add_inbound_tracker_test.go +++ b/x/crosschain/types/message_add_inbound_tracker_test.go @@ -10,7 +10,6 @@ import ( "github.com/zeta-chain/zetacore/pkg/chains" "github.com/zeta-chain/zetacore/pkg/coin" - "github.com/zeta-chain/zetacore/pkg/proofs" "github.com/zeta-chain/zetacore/testutil/sample" "github.com/zeta-chain/zetacore/x/crosschain/types" ) @@ -31,30 +30,6 @@ func TestMsgAddInboundTracker_ValidateBasic(t *testing.T) { ), err: sdkerrors.ErrInvalidAddress, }, - { - name: "invalid chain id", - msg: types.NewMsgAddInboundTracker( - sample.AccAddress(), - 42, - coin.CoinType_Gas, - "hash", - ), - err: errorsmod.Wrapf(types.ErrInvalidChainID, "chain id (%d)", 42), - }, - { - name: "invalid proof", - msg: &types.MsgAddInboundTracker{ - Creator: sample.AccAddress(), - ChainId: chains.ZetaChainTestnet.ChainId, - CoinType: coin.CoinType_Gas, - Proof: &proofs.Proof{}, - }, - err: errorsmod.Wrapf( - types.ErrProofVerificationFail, - "chain id %d does not support proof-based trackers", - chains.ZetaChainTestnet.ChainId, - ), - }, { name: "invalid coin type", msg: &types.MsgAddInboundTracker{ @@ -62,7 +37,7 @@ func TestMsgAddInboundTracker_ValidateBasic(t *testing.T) { ChainId: chains.ZetaChainTestnet.ChainId, CoinType: 5, }, - err: errorsmod.Wrapf(types.ErrProofVerificationFail, "coin-type not supported"), + err: errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "coin-type not supported"), }, { name: "valid", diff --git a/x/crosschain/types/message_migrate_tss_funds.go b/x/crosschain/types/message_migrate_tss_funds.go index 2de565c72d..0f4d5a2ecf 100644 --- a/x/crosschain/types/message_migrate_tss_funds.go +++ b/x/crosschain/types/message_migrate_tss_funds.go @@ -5,8 +5,6 @@ import ( sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - - "github.com/zeta-chain/zetacore/pkg/chains" ) const TypeMsgMigrateTssFunds = "MigrateTssFunds" @@ -47,9 +45,7 @@ func (msg *MsgMigrateTssFunds) ValidateBasic() error { if err != nil { return errorsmod.Wrapf(sdkerrors.ErrInvalidAddress, "invalid creator address (%s)", err) } - if chains.GetChainFromChainID(msg.ChainId) == nil { - return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "invalid chain id (%d)", msg.ChainId) - } + if msg.Amount.IsZero() { return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "amount cannot be zero") } diff --git a/x/crosschain/types/message_migrate_tss_funds_test.go b/x/crosschain/types/message_migrate_tss_funds_test.go index f07943bf59..5514af9034 100644 --- a/x/crosschain/types/message_migrate_tss_funds_test.go +++ b/x/crosschain/types/message_migrate_tss_funds_test.go @@ -29,15 +29,6 @@ func TestNewMsgMigrateTssFunds_ValidateBasic(t *testing.T) { ), error: true, }, - { - name: "invalid chain id", - msg: types.NewMsgMigrateTssFunds( - sample.AccAddress(), - 999, - sdkmath.NewUintFromString("100000"), - ), - error: true, - }, { name: "invalid amount", msg: types.NewMsgMigrateTssFunds( diff --git a/x/crosschain/types/outbound_params.go b/x/crosschain/types/outbound_params.go index 34458763dd..361462a1b4 100644 --- a/x/crosschain/types/outbound_params.go +++ b/x/crosschain/types/outbound_params.go @@ -3,8 +3,6 @@ package types import ( "fmt" "strconv" - - "github.com/zeta-chain/zetacore/pkg/chains" ) func (m OutboundParams) GetGasPriceUInt64() (uint64, error) { @@ -21,10 +19,6 @@ func (m OutboundParams) Validate() error { return fmt.Errorf("receiver cannot be empty") } - if chains.GetChainFromChainID(m.ReceiverChainId) == nil { - return fmt.Errorf("invalid receiver chain id %d", m.ReceiverChainId) - } - if m.Amount.IsNil() { return fmt.Errorf("amount cannot be nil") } diff --git a/x/crosschain/types/outbound_params_test.go b/x/crosschain/types/outbound_params_test.go index e5caa4b1b0..16bfc17844 100644 --- a/x/crosschain/types/outbound_params_test.go +++ b/x/crosschain/types/outbound_params_test.go @@ -16,10 +16,6 @@ func TestOutboundParams_Validate(t *testing.T) { outTxParams.Receiver = "" require.ErrorContains(t, outTxParams.Validate(), "receiver cannot be empty") - outTxParams = sample.OutboundParamsValidChainID(r) - outTxParams.ReceiverChainId = 1000 - require.ErrorContains(t, outTxParams.Validate(), "invalid receiver chain id 1000") - outTxParams = sample.OutboundParamsValidChainID(r) outTxParams.Amount = sdkmath.Uint{} require.ErrorContains(t, outTxParams.Validate(), "amount cannot be nil") diff --git a/x/crosschain/types/tx_body_verification.go b/x/crosschain/types/tx_body_verification.go index fbb8d4c6ea..84d71054f1 100644 --- a/x/crosschain/types/tx_body_verification.go +++ b/x/crosschain/types/tx_body_verification.go @@ -22,7 +22,10 @@ func VerifyInboundBody( tss observertypes.QueryGetTssAddressResponse, ) error { // verify message against transaction body - if chains.IsEVMChain(msg.ChainId) { + // NOTE: since this functionality is disabled on live network we don't provide on-chain additional chains for simplicity + // TODO: use authorityKeeper.GetChainInfo to provide additional chains + // https://github.com/zeta-chain/node/issues/2385 + if chains.IsEVMChain(msg.ChainId, []chains.Chain{}) { return verifyInboundBodyEVM(msg, txBytes, chainParams, tss) } @@ -79,9 +82,12 @@ func verifyInboundBodyEVM( // VerifyOutboundBody verifies the tx body for an outbound func VerifyOutboundBody(msg MsgAddOutboundTracker, txBytes []byte, tss observertypes.QueryGetTssAddressResponse) error { // verify message against transaction body - if chains.IsEVMChain(msg.ChainId) { + // NOTE: since this functionality is disabled on live network we don't provide on-chain additional chains for simplicity + // TODO: use authorityKeeper.GetChainInfo to provide additional chains + // https://github.com/zeta-chain/node/issues/2385 + if chains.IsEVMChain(msg.ChainId, []chains.Chain{}) { return verifyOutboundBodyEVM(msg, txBytes, tss.Eth) - } else if chains.IsBitcoinChain(msg.ChainId) { + } else if chains.IsBitcoinChain(msg.ChainId, []chains.Chain{}) { return verifyOutboundBodyBTC(msg, txBytes, tss.Btc) } return fmt.Errorf("cannot verify outbound body for chain %d", msg.ChainId) @@ -122,9 +128,6 @@ func verifyOutboundBodyEVM(msg MsgAddOutboundTracker, txBytes []byte, tssEth str // TODO: Implement tests for the function // https://github.com/zeta-chain/node/issues/1994 func verifyOutboundBodyBTC(msg MsgAddOutboundTracker, txBytes []byte, tssBtc string) error { - if !chains.IsBitcoinChain(msg.ChainId) { - return fmt.Errorf("not a Bitcoin chain ID %d", msg.ChainId) - } tx, err := btcutil.NewTxFromBytes(txBytes) if err != nil { return err diff --git a/x/crosschain/types/validate.go b/x/crosschain/types/validate.go index 58305ffa02..1f1dd3814d 100644 --- a/x/crosschain/types/validate.go +++ b/x/crosschain/types/validate.go @@ -20,15 +20,21 @@ func ValidateCCTXIndex(index string) error { } // ValidateHashForChain validates the hash for the chain +// NOTE: since these checks are currently not used, we don't provide additional chains for simplicity +// TODO: use authorityKeeper.GetChainInfo to provide additional chains +// https://github.com/zeta-chain/node/issues/2234 +// https://github.com/zeta-chain/node/issues/2385 +// NOTE: We should eventually not using these hard-coded checks at all since it might make the protocol too rigid +// Example: hash algorithm is changed for a chain: this required a upgrade on the protocol func ValidateHashForChain(hash string, chainID int64) error { - if chains.IsEthereumChain(chainID) || chains.IsZetaChain(chainID) { + if chains.IsEthereumChain(chainID, []chains.Chain{}) || chains.IsZetaChain(chainID, []chains.Chain{}) { _, err := hexutil.Decode(hash) if err != nil { return fmt.Errorf("hash must be a valid ethereum hash %s", hash) } return nil } - if chains.IsBitcoinChain(chainID) { + if chains.IsBitcoinChain(chainID, []chains.Chain{}) { r, err := regexp.Compile("^[a-fA-F0-9]{64}$") if err != nil { return fmt.Errorf("error compiling regex") @@ -42,18 +48,23 @@ func ValidateHashForChain(hash string, chainID int64) error { } // ValidateAddressForChain validates the address for the chain +// NOTE: since these checks are currently not used, we don't provide additional chains for simplicity +// TODO: use authorityKeeper.GetChainInfo to provide additional chains +// https://github.com/zeta-chain/node/issues/2234 +// https://github.com/zeta-chain/node/issues/2385 +// NOTE: We should eventually not using these hard-coded checks at all for same reasons as above func ValidateAddressForChain(address string, chainID int64) error { // we do not validate the address for zeta chain as the address field can be btc or eth address - if chains.IsZetaChain(chainID) { + if chains.IsZetaChain(chainID, []chains.Chain{}) { return nil } - if chains.IsEthereumChain(chainID) { + if chains.IsEthereumChain(chainID, []chains.Chain{}) { if !ethcommon.IsHexAddress(address) { return fmt.Errorf("invalid address %s , chain %d", address, chainID) } return nil } - if chains.IsBitcoinChain(chainID) { + if chains.IsBitcoinChain(chainID, []chains.Chain{}) { addr, err := chains.DecodeBtcAddress(address, chainID) if err != nil { return fmt.Errorf("invalid address %s , chain %d: %s", address, chainID, err) diff --git a/x/fungible/keeper/evm.go b/x/fungible/keeper/evm.go index 43bffb6e75..5a9d950b14 100644 --- a/x/fungible/keeper/evm.go +++ b/x/fungible/keeper/evm.go @@ -110,12 +110,13 @@ func (k Keeper) DeployZRC20Contract( erc20Contract string, gasLimit *big.Int, ) (common.Address, error) { - chain := chains.GetChainFromChainID(chainID) - if chain == nil { + chain, found := chains.GetChainFromChainID(chainID, k.GetAuthorityKeeper().GetAdditionalChainList(ctx)) + if !found { return common.Address{}, cosmoserrors.Wrapf(zetaObserverTypes.ErrSupportedChains, "chain %d not found", chainID) } + // Check if Contract has already been deployed for Asset - _, found := k.GetForeignCoinFromAsset(ctx, erc20Contract, chainID) + _, found = k.GetForeignCoinFromAsset(ctx, erc20Contract, chainID) if found { return common.Address{}, types.ErrForeignCoinAlreadyExist } diff --git a/x/fungible/keeper/gas_coin_and_pool.go b/x/fungible/keeper/gas_coin_and_pool.go index 1ee7ece40c..8e01e0dc49 100644 --- a/x/fungible/keeper/gas_coin_and_pool.go +++ b/x/fungible/keeper/gas_coin_and_pool.go @@ -28,8 +28,11 @@ func (k Keeper) SetupChainGasCoinAndPool( decimals uint8, gasLimit *big.Int, ) (ethcommon.Address, error) { - chain := chains.GetChainFromChainID(chainID) - if chain == nil { + // additional on-chain static chain information + additionalChains := k.GetAuthorityKeeper().GetAdditionalChainList(ctx) + + chain, found := chains.GetChainFromChainID(chainID, additionalChains) + if !found { return ethcommon.Address{}, zetaObserverTypes.ErrSupportedChains } name := fmt.Sprintf("%s-%s", gasAssetName, chain.ChainName) @@ -37,7 +40,7 @@ func (k Keeper) SetupChainGasCoinAndPool( transferGasLimit := gasLimit // Check if gas coin already exists - _, found := k.GetGasCoinForForeignCoin(ctx, chainID) + _, found = k.GetGasCoinForForeignCoin(ctx, chainID) if found { return ethcommon.Address{}, types.ErrForeignCoinAlreadyExist } @@ -45,7 +48,7 @@ func (k Keeper) SetupChainGasCoinAndPool( // default values if transferGasLimit == nil { transferGasLimit = big.NewInt(21_000) - if chains.IsBitcoinChain(chain.ChainId) { + if chains.IsBitcoinChain(chain.ChainId, additionalChains) { transferGasLimit = big.NewInt(100) // 100B for a typical tx } } diff --git a/x/fungible/keeper/grpc_query_gas_stability_pool.go b/x/fungible/keeper/grpc_query_gas_stability_pool.go index 321fdb7e5b..3541aad8d4 100644 --- a/x/fungible/keeper/grpc_query_gas_stability_pool.go +++ b/x/fungible/keeper/grpc_query_gas_stability_pool.go @@ -57,9 +57,6 @@ func (k Keeper) GasStabilityPoolBalanceAll( chains := k.observerKeeper.GetSupportedChains(ctx) balances := make([]types.QueryAllGasStabilityPoolBalanceResponse_Balance, 0, len(chains)) for _, chain := range chains { - if chain == nil { - return nil, status.Error(codes.Internal, "invalid chain") - } chainID := chain.ChainId balance, err := k.GetGasStabilityPoolBalance(ctx, chainID) diff --git a/x/fungible/keeper/grpc_query_gas_stability_pool_test.go b/x/fungible/keeper/grpc_query_gas_stability_pool_test.go index f503c76698..d2a256e927 100644 --- a/x/fungible/keeper/grpc_query_gas_stability_pool_test.go +++ b/x/fungible/keeper/grpc_query_gas_stability_pool_test.go @@ -79,32 +79,20 @@ func TestKeeper_GasStabilityPoolBalanceAll(t *testing.T) { UseObserverMock: true, }) observerMock := keepertest.GetFungibleObserverMock(t, k) - observerMock.On("GetSupportedChains", mock.Anything).Return([]*chains.Chain{}) + observerMock.On("GetSupportedChains", mock.Anything).Return([]chains.Chain{}) res, err := k.GasStabilityPoolBalanceAll(ctx, &types.QueryAllGasStabilityPoolBalance{}) require.NoError(t, err) require.Empty(t, res.Balances) }) - t.Run("should error if chain is nil", func(t *testing.T) { - k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ - UseObserverMock: true, - }) - observerMock := keepertest.GetFungibleObserverMock(t, k) - observerMock.On("GetSupportedChains", mock.Anything).Return([]*chains.Chain{nil}) - - res, err := k.GasStabilityPoolBalanceAll(ctx, &types.QueryAllGasStabilityPoolBalance{}) - require.Error(t, err) - require.Nil(t, res) - }) - t.Run("should error if system contracts not deployed", func(t *testing.T) { k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ UseObserverMock: true, }) observerMock := keepertest.GetFungibleObserverMock(t, k) chainID := 5 - observerMock.On("GetSupportedChains", mock.Anything).Return([]*chains.Chain{ + observerMock.On("GetSupportedChains", mock.Anything).Return([]chains.Chain{ { ChainName: chains.ChainName(chainID), ChainId: int64(chainID), @@ -124,7 +112,7 @@ func TestKeeper_GasStabilityPoolBalanceAll(t *testing.T) { observerMock := keepertest.GetFungibleObserverMock(t, k) chainID := 5 - observerMock.On("GetSupportedChains", mock.Anything).Return([]*chains.Chain{ + observerMock.On("GetSupportedChains", mock.Anything).Return([]chains.Chain{ { ChainName: chains.ChainName(chainID), ChainId: int64(chainID), diff --git a/x/fungible/keeper/msg_server_deploy_fungible_coin_zrc20_test.go b/x/fungible/keeper/msg_server_deploy_fungible_coin_zrc20_test.go index b37dd82cf7..903b63aa31 100644 --- a/x/fungible/keeper/msg_server_deploy_fungible_coin_zrc20_test.go +++ b/x/fungible/keeper/msg_server_deploy_fungible_coin_zrc20_test.go @@ -42,6 +42,7 @@ func TestMsgServer_DeployFungibleCoinZRC20(t *testing.T) { 1000000, ) keepertest.MockCheckAuthorization(&authorityMock.Mock, msg, nil) + keepertest.MockGetChainListEmpty(&authorityMock.Mock) res, err := msgServer.DeployFungibleCoinZRC20(ctx, msg) require.NoError(t, err) gasAddress := res.Address @@ -174,6 +175,7 @@ func TestMsgServer_DeployFungibleCoinZRC20(t *testing.T) { 1000000, ) keepertest.MockCheckAuthorization(&authorityMock.Mock, msg, nil) + keepertest.MockGetChainListEmpty(&authorityMock.Mock) _, err := keeper.NewMsgServerImpl(*k).DeployFungibleCoinZRC20(ctx, msg) require.Error(t, err) require.ErrorIs(t, err, observertypes.ErrSupportedChains) @@ -203,6 +205,7 @@ func TestMsgServer_DeployFungibleCoinZRC20(t *testing.T) { 1000000, ) keepertest.MockCheckAuthorization(&authorityMock.Mock, deployMsg, nil) + keepertest.MockGetChainListEmpty(&authorityMock.Mock) // Attempt to deploy the same gas token twice should result in error _, err := keeper.NewMsgServerImpl(*k).DeployFungibleCoinZRC20(ctx, deployMsg) diff --git a/x/fungible/keeper/msg_server_remove_foreign_coin_test.go b/x/fungible/keeper/msg_server_remove_foreign_coin_test.go index 01ac286e9e..9e02d8a6f0 100644 --- a/x/fungible/keeper/msg_server_remove_foreign_coin_test.go +++ b/x/fungible/keeper/msg_server_remove_foreign_coin_test.go @@ -25,6 +25,7 @@ func TestMsgServer_RemoveForeignCoin(t *testing.T) { admin := sample.AccAddress() authorityMock := keepertest.GetFungibleAuthorityMock(t, k) + keepertest.MockGetChainListEmpty(&authorityMock.Mock) chainID := getValidChainID(t) @@ -53,6 +54,7 @@ func TestMsgServer_RemoveForeignCoin(t *testing.T) { admin := sample.AccAddress() authorityMock := keepertest.GetFungibleAuthorityMock(t, k) + keepertest.MockGetChainListEmpty(&authorityMock.Mock) deploySystemContracts(t, ctx, k, sdkk.EvmKeeper) zrc20 := setupGasCoin(t, ctx, k, sdkk.EvmKeeper, chainID, "foo", "foo") diff --git a/x/fungible/keeper/msg_server_update_contract_bytecode_test.go b/x/fungible/keeper/msg_server_update_contract_bytecode_test.go index 287cc18046..dadb62d145 100644 --- a/x/fungible/keeper/msg_server_update_contract_bytecode_test.go +++ b/x/fungible/keeper/msg_server_update_contract_bytecode_test.go @@ -39,6 +39,7 @@ func TestKeeper_UpdateContractBytecode(t *testing.T) { msgServer := keeper.NewMsgServerImpl(*k) authorityMock := keepertest.GetFungibleAuthorityMock(t, k) + keepertest.MockGetChainListEmpty(&authorityMock.Mock) // sample chainIDs and addresses chainList := chains.DefaultChainsList() @@ -147,6 +148,7 @@ func TestKeeper_UpdateContractBytecode(t *testing.T) { codeHash, ) keepertest.MockCheckAuthorization(&authorityMock.Mock, msg, nil) + keepertest.MockGetChainListEmpty(&authorityMock.Mock) _, err = msgServer.UpdateContractBytecode(ctx, msg) require.NoError(t, err) balance, err = k.BalanceOfZRC4(ctx, zrc20, addr1) diff --git a/x/fungible/keeper/msg_server_update_system_contract_test.go b/x/fungible/keeper/msg_server_update_system_contract_test.go index bdea95980b..72b7bac265 100644 --- a/x/fungible/keeper/msg_server_update_system_contract_test.go +++ b/x/fungible/keeper/msg_server_update_system_contract_test.go @@ -30,6 +30,7 @@ func TestKeeper_UpdateSystemContract(t *testing.T) { admin := sample.AccAddress() authorityMock := keepertest.GetFungibleAuthorityMock(t, k) + keepertest.MockGetChainListEmpty(&authorityMock.Mock) queryZRC20SystemContract := func(contract common.Address) string { abi, err := zrc20.ZRC20MetaData.GetAbi() @@ -210,6 +211,7 @@ func TestKeeper_UpdateSystemContract(t *testing.T) { admin := sample.AccAddress() authorityMock := keepertest.GetFungibleAuthorityMock(t, k) + keepertest.MockGetChainListEmpty(&authorityMock.Mock) chains := chains.DefaultChainsList() require.True(t, len(chains) > 1) @@ -255,6 +257,7 @@ func TestKeeper_UpdateSystemContract(t *testing.T) { // can't update the system contract msg = types.NewMsgUpdateSystemContract(admin, newSystemContract.Hex()) keepertest.MockCheckAuthorization(&authorityMock.Mock, msg, nil) + keepertest.MockGetChainListEmpty(&authorityMock.Mock) _, err = msgServer.UpdateSystemContract(ctx, msg) require.ErrorIs(t, err, types.ErrContractCall) @@ -265,6 +268,7 @@ func TestKeeper_UpdateSystemContract(t *testing.T) { // can't update the system contract msg = types.NewMsgUpdateSystemContract(admin, newSystemContract.Hex()) keepertest.MockCheckAuthorization(&authorityMock.Mock, msg, nil) + keepertest.MockGetChainListEmpty(&authorityMock.Mock) _, err = msgServer.UpdateSystemContract(ctx, msg) require.ErrorIs(t, err, types.ErrContractCall) }) diff --git a/x/fungible/keeper/msg_server_update_zrc20_withdraw_fee_test.go b/x/fungible/keeper/msg_server_update_zrc20_withdraw_fee_test.go index fb156a1c36..160b2cfc46 100644 --- a/x/fungible/keeper/msg_server_update_zrc20_withdraw_fee_test.go +++ b/x/fungible/keeper/msg_server_update_zrc20_withdraw_fee_test.go @@ -31,6 +31,7 @@ func TestKeeper_UpdateZRC20WithdrawFee(t *testing.T) { // set coin admin admin := sample.AccAddress() authorityMock := keepertest.GetFungibleAuthorityMock(t, k) + keepertest.MockGetChainListEmpty(&authorityMock.Mock) // deploy the system contract and a ZRC20 contract deploySystemContracts(t, ctx, k, sdkk.EvmKeeper) diff --git a/x/fungible/types/expected_keepers.go b/x/fungible/types/expected_keepers.go index b2997566ff..ad0521ab81 100644 --- a/x/fungible/types/expected_keepers.go +++ b/x/fungible/types/expected_keepers.go @@ -36,7 +36,7 @@ type BankKeeper interface { } type ObserverKeeper interface { - GetSupportedChains(ctx sdk.Context) []*chains.Chain + GetSupportedChains(ctx sdk.Context) []chains.Chain } type EVMKeeper interface { @@ -60,4 +60,5 @@ type EVMKeeper interface { type AuthorityKeeper interface { CheckAuthorization(ctx sdk.Context, msg sdk.Msg) error + GetAdditionalChainList(ctx sdk.Context) (list []chains.Chain) } diff --git a/x/lightclient/keeper/grpc_query_prove.go b/x/lightclient/keeper/grpc_query_prove.go index 4a2017c65b..b231906501 100644 --- a/x/lightclient/keeper/grpc_query_prove.go +++ b/x/lightclient/keeper/grpc_query_prove.go @@ -24,7 +24,11 @@ func (k Keeper) Prove(c context.Context, req *types.QueryProveRequest) (*types.Q } ctx := sdk.UnwrapSDKContext(c) - blockHash, err := chains.StringToHash(req.ChainId, req.BlockHash) + // additionalChains is a list of additional chains to search from + // it is used in the protocol to dynamically support new chains without doing an upgrade + additionalChains := k.GetAuthorityKeeper().GetAdditionalChainList(ctx) + + blockHash, err := chains.StringToHash(req.ChainId, req.BlockHash, additionalChains) if err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) } @@ -40,7 +44,7 @@ func (k Keeper) Prove(c context.Context, req *types.QueryProveRequest) (*types.Q return nil, status.Error(codes.Internal, err.Error()) } if err == nil { - if chains.IsEVMChain(req.ChainId) { + if chains.IsEVMChain(req.ChainId, additionalChains) { var txx ethtypes.Transaction err = txx.UnmarshalBinary(txBytes) if err != nil { @@ -53,7 +57,7 @@ func (k Keeper) Prove(c context.Context, req *types.QueryProveRequest) (*types.Q ) } proven = true - } else if chains.IsBitcoinChain(req.ChainId) { + } else if chains.IsBitcoinChain(req.ChainId, additionalChains) { tx, err := btcutil.NewTxFromBytes(txBytes) if err != nil { return nil, status.Error(codes.Internal, fmt.Sprintf("failed to unmarshal btc transaction: %s", err)) diff --git a/x/lightclient/keeper/proof.go b/x/lightclient/keeper/proof.go index 7067ab3ac1..ddc26eb12f 100644 --- a/x/lightclient/keeper/proof.go +++ b/x/lightclient/keeper/proof.go @@ -23,8 +23,12 @@ func (k Keeper) VerifyProof( return nil, err } + // additionalChains is a list of additional chains to search from + // it is used in the protocol to dynamically support new chains without doing an upgrade + additionalChains := k.GetAuthorityKeeper().GetAdditionalChainList(ctx) + // get block header from the store - hashBytes, err := chains.StringToHash(chainID, blockHash) + hashBytes, err := chains.StringToHash(chainID, blockHash, additionalChains) if err != nil { return nil, cosmoserror.Wrapf( types.ErrInvalidBlockHash, diff --git a/x/lightclient/types/expected_keepers.go b/x/lightclient/types/expected_keepers.go index bee335d628..71f83b2c49 100644 --- a/x/lightclient/types/expected_keepers.go +++ b/x/lightclient/types/expected_keepers.go @@ -2,8 +2,11 @@ package types import ( sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/zeta-chain/zetacore/pkg/chains" ) type AuthorityKeeper interface { CheckAuthorization(ctx sdk.Context, msg sdk.Msg) error + GetAdditionalChainList(ctx sdk.Context) (list []chains.Chain) } diff --git a/x/lightclient/types/message_disable_verification_flags.go b/x/lightclient/types/message_disable_verification_flags.go index 5ee2964aa7..511821919c 100644 --- a/x/lightclient/types/message_disable_verification_flags.go +++ b/x/lightclient/types/message_disable_verification_flags.go @@ -4,8 +4,6 @@ import ( cosmoserrors "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - - "github.com/zeta-chain/zetacore/pkg/chains" ) const ( @@ -46,21 +44,12 @@ func (msg *MsgDisableHeaderVerification) ValidateBasic() error { if _, err := sdk.AccAddressFromBech32(msg.Creator); err != nil { return cosmoserrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid creator address (%s)", err) } - chainListForHeaderSupport := chains.ChainListForHeaderSupport() if len(msg.ChainIdList) == 0 { return cosmoserrors.Wrapf(sdkerrors.ErrInvalidRequest, "chain id list cannot be empty") } - if len(msg.ChainIdList) > len(chainListForHeaderSupport) { - return cosmoserrors.Wrapf(sdkerrors.ErrInvalidRequest, "chain id list cannot be greater than supported chains") - } - for _, chainID := range msg.ChainIdList { - if !chains.ChainIDInChainList(chainID, chainListForHeaderSupport) { - return cosmoserrors.Wrapf( - sdkerrors.ErrInvalidRequest, - "invalid chain id header not supported (%d)", - chainID, - ) - } + + if len(msg.ChainIdList) > MaxChainIDListLength { + return cosmoserrors.Wrapf(sdkerrors.ErrInvalidRequest, "chain id list too long") } return nil diff --git a/x/lightclient/types/message_disable_verification_flags_test.go b/x/lightclient/types/message_disable_verification_flags_test.go index 6ccde4a12b..8efb9d4c04 100644 --- a/x/lightclient/types/message_disable_verification_flags_test.go +++ b/x/lightclient/types/message_disable_verification_flags_test.go @@ -1,7 +1,6 @@ package types_test import ( - "fmt" "testing" sdk "github.com/cosmos/cosmos-sdk/types" @@ -43,26 +42,11 @@ func TestMsgDisableHeaderVerification_ValidateBasic(t *testing.T) { name: "chain id list is too long", msg: types.MsgDisableHeaderVerification{ Creator: sample.AccAddress(), - ChainIdList: make([]int64, 200), + ChainIdList: make([]int64, types.MaxChainIDListLength+1), }, err: func(t require.TestingT, err error, i ...interface{}) { require.ErrorIs(t, err, sdkerrors.ErrInvalidRequest) - require.ErrorContains(t, err, "chain id list cannot be greater than supported chains") - }, - }, - { - name: "invalid chain id", - msg: types.MsgDisableHeaderVerification{ - Creator: sample.AccAddress(), - ChainIdList: []int64{chains.ZetaChainPrivnet.ChainId}, - }, - err: func(t require.TestingT, err error, i ...interface{}) { - require.ErrorIs(t, err, sdkerrors.ErrInvalidRequest) - require.ErrorContains( - t, - err, - fmt.Sprintf("invalid chain id header not supported (%d)", chains.ZetaChainPrivnet.ChainId), - ) + require.ErrorContains(t, err, "chain id list too long") }, }, { diff --git a/x/lightclient/types/message_enable_verification_flags.go b/x/lightclient/types/message_enable_verification_flags.go index a77706699a..a0a9dac5bd 100644 --- a/x/lightclient/types/message_enable_verification_flags.go +++ b/x/lightclient/types/message_enable_verification_flags.go @@ -4,12 +4,14 @@ import ( cosmoserrors "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - - "github.com/zeta-chain/zetacore/pkg/chains" ) const ( TypeMsgEnableHeaderVerification = "enable_header_verification" + + // MaxChainIDListLength is the maximum number of chain IDs that can be enabled for header verification + // this is a value chosen arbitrarily to prevent abuse + MaxChainIDListLength = 200 ) var _ sdk.Msg = &MsgEnableHeaderVerification{} @@ -46,21 +48,12 @@ func (msg *MsgEnableHeaderVerification) ValidateBasic() error { if _, err := sdk.AccAddressFromBech32(msg.Creator); err != nil { return cosmoserrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid creator address (%s)", err) } - chainListForHeaderSupport := chains.ChainListForHeaderSupport() if len(msg.ChainIdList) == 0 { return cosmoserrors.Wrapf(sdkerrors.ErrInvalidRequest, "chain id list cannot be empty") } - if len(msg.ChainIdList) > len(chainListForHeaderSupport) { - return cosmoserrors.Wrapf(sdkerrors.ErrInvalidRequest, "chain id list cannot be greater than supported chains") - } - for _, chainID := range msg.ChainIdList { - if !chains.ChainIDInChainList(chainID, chainListForHeaderSupport) { - return cosmoserrors.Wrapf( - sdkerrors.ErrInvalidRequest, - "invalid chain id header not supported (%d)", - chainID, - ) - } + + if len(msg.ChainIdList) > MaxChainIDListLength { + return cosmoserrors.Wrapf(sdkerrors.ErrInvalidRequest, "chain id list too long") } return nil diff --git a/x/lightclient/types/message_enable_verification_flags_test.go b/x/lightclient/types/message_enable_verification_flags_test.go index 0bda67f1b9..2f738f36f0 100644 --- a/x/lightclient/types/message_enable_verification_flags_test.go +++ b/x/lightclient/types/message_enable_verification_flags_test.go @@ -1,7 +1,6 @@ package types_test import ( - "fmt" "testing" sdk "github.com/cosmos/cosmos-sdk/types" @@ -43,26 +42,11 @@ func TestMsgEnableHeaderVerification_ValidateBasic(t *testing.T) { name: "chain id list is too long", msg: types.MsgEnableHeaderVerification{ Creator: sample.AccAddress(), - ChainIdList: make([]int64, 200), + ChainIdList: make([]int64, types.MaxChainIDListLength+1), }, err: func(t require.TestingT, err error, i ...interface{}) { require.ErrorIs(t, err, sdkerrors.ErrInvalidRequest) - require.ErrorContains(t, err, "chain id list cannot be greater than supported chains") - }, - }, - { - name: "invalid chain id", - msg: types.MsgEnableHeaderVerification{ - Creator: sample.AccAddress(), - ChainIdList: []int64{chains.ZetaChainPrivnet.ChainId}, - }, - err: func(t require.TestingT, err error, i ...interface{}) { - require.ErrorIs(t, err, sdkerrors.ErrInvalidRequest) - require.ErrorContains( - t, - err, - fmt.Sprintf("invalid chain id header not supported (%d)", chains.ZetaChainPrivnet.ChainId), - ) + require.ErrorContains(t, err, "chain id list too long") }, }, { diff --git a/x/observer/keeper/chain_params.go b/x/observer/keeper/chain_params.go index a2354f9b2c..9277010c3c 100644 --- a/x/observer/keeper/chain_params.go +++ b/x/observer/keeper/chain_params.go @@ -43,41 +43,44 @@ func (k Keeper) GetChainParamsByChainID(ctx sdk.Context, chainID int64) (*types. // GetSupportedChainFromChainID returns the chain from the chain id // it returns nil if the chain doesn't exist or is not supported -func (k Keeper) GetSupportedChainFromChainID(ctx sdk.Context, chainID int64) *chains.Chain { +func (k Keeper) GetSupportedChainFromChainID(ctx sdk.Context, chainID int64) (chains.Chain, bool) { cpl, found := k.GetChainParamsList(ctx) if !found { - return nil + return chains.Chain{}, false } for _, cp := range cpl.ChainParams { if cp.ChainId == chainID && cp.IsSupported { - return chains.GetChainFromChainID(chainID) + return chains.GetChainFromChainID(chainID, k.GetAuthorityKeeper().GetAdditionalChainList(ctx)) } } - return nil + return chains.Chain{}, false } // GetSupportedChains returns the list of supported chains -func (k Keeper) GetSupportedChains(ctx sdk.Context) []*chains.Chain { +func (k Keeper) GetSupportedChains(ctx sdk.Context) []chains.Chain { cpl, found := k.GetChainParamsList(ctx) if !found { - return []*chains.Chain{} + return []chains.Chain{} } - var c []*chains.Chain + var c []chains.Chain for _, cp := range cpl.ChainParams { if cp.IsSupported { - c = append(c, chains.GetChainFromChainID(cp.ChainId)) + chain, found := chains.GetChainFromChainID(cp.ChainId, k.GetAuthorityKeeper().GetAdditionalChainList(ctx)) + if found { + c = append(c, chain) + } } } return c } // GetSupportedForeignChains returns the list of supported foreign chains -func (k Keeper) GetSupportedForeignChains(ctx sdk.Context) []*chains.Chain { +func (k Keeper) GetSupportedForeignChains(ctx sdk.Context) []chains.Chain { allChains := k.GetSupportedChains(ctx) - foreignChains := make([]*chains.Chain, 0) + foreignChains := make([]chains.Chain, 0) for _, chain := range allChains { if !chain.IsZetaChain() { foreignChains = append(foreignChains, chain) diff --git a/x/observer/keeper/chain_params_test.go b/x/observer/keeper/chain_params_test.go index 4d608f0462..733fafc0b8 100644 --- a/x/observer/keeper/chain_params_test.go +++ b/x/observer/keeper/chain_params_test.go @@ -16,26 +16,29 @@ func TestKeeper_GetSupportedChainFromChainID(t *testing.T) { k, ctx, _, _ := keepertest.ObserverKeeper(t) // no core params list - require.Nil(t, k.GetSupportedChainFromChainID(ctx, getValidEthChainIDWithIndex(t, 0))) + _, found := k.GetSupportedChainFromChainID(ctx, getValidEthChainIDWithIndex(t, 0)) + require.False(t, found) // core params list but chain not in list setSupportedChain(ctx, *k, getValidEthChainIDWithIndex(t, 0)) - require.Nil(t, k.GetSupportedChainFromChainID(ctx, getValidEthChainIDWithIndex(t, 1))) + _, found = k.GetSupportedChainFromChainID(ctx, getValidEthChainIDWithIndex(t, 1)) + require.False(t, found) // chain params list but chain not supported chainParams := sample.ChainParams(getValidEthChainIDWithIndex(t, 0)) k.SetChainParamsList(ctx, types.ChainParamsList{ ChainParams: []*types.ChainParams{chainParams}, }) - require.Nil(t, k.GetSupportedChainFromChainID(ctx, getValidEthChainIDWithIndex(t, 0))) + _, found = k.GetSupportedChainFromChainID(ctx, getValidEthChainIDWithIndex(t, 0)) + require.False(t, found) }) t.Run("return chain if chain found", func(t *testing.T) { k, ctx, _, _ := keepertest.ObserverKeeper(t) chainID := getValidEthChainIDWithIndex(t, 0) setSupportedChain(ctx, *k, getValidEthChainIDWithIndex(t, 1), chainID) - chain := k.GetSupportedChainFromChainID(ctx, chainID) - require.NotNil(t, chain) + chain, found := k.GetSupportedChainFromChainID(ctx, chainID) + require.True(t, found) require.EqualValues(t, chainID, chain.ChainId) }) } @@ -78,12 +81,14 @@ func TestKeeper_GetSupportedChains(t *testing.T) { t.Run("return list containing supported chains", func(t *testing.T) { k, ctx, _, _ := keepertest.ObserverKeeper(t) - require.Greater(t, len(chains.ExternalChainList()), 5) - supported1 := chains.ExternalChainList()[0] - supported2 := chains.ExternalChainList()[1] - unsupported := chains.ExternalChainList()[2] - supported3 := chains.ExternalChainList()[3] - supported4 := chains.ExternalChainList()[4] + chainList := chains.ExternalChainList([]chains.Chain{}) + + require.Greater(t, len(chainList), 5) + supported1 := chainList[0] + supported2 := chainList[1] + unsupported := chainList[2] + supported3 := chainList[3] + supported4 := chainList[4] var chainParamsList []*types.ChainParams chainParamsList = append(chainParamsList, sample.ChainParamsSupported(supported1.ChainId)) diff --git a/x/observer/keeper/grpc_query_supported_chain_test.go b/x/observer/keeper/grpc_query_supported_chain_test.go index 1b73c53394..0cdc276c9d 100644 --- a/x/observer/keeper/grpc_query_supported_chain_test.go +++ b/x/observer/keeper/grpc_query_supported_chain_test.go @@ -17,6 +17,6 @@ func TestKeeper_SupportedChains(t *testing.T) { res, err := k.SupportedChains(wctx, nil) require.NoError(t, err) - require.Equal(t, []*chains.Chain{}, res.Chains) + require.Equal(t, []chains.Chain{}, res.Chains) }) } diff --git a/x/observer/keeper/grpc_query_tss_funds_migrator_info.go b/x/observer/keeper/grpc_query_tss_funds_migrator_info.go index 7a2ab7e357..88558fd23a 100644 --- a/x/observer/keeper/grpc_query_tss_funds_migrator_info.go +++ b/x/observer/keeper/grpc_query_tss_funds_migrator_info.go @@ -22,7 +22,8 @@ func (k Keeper) TssFundsMigratorInfo( ctx := sdk.UnwrapSDKContext(goCtx) - if chains.GetChainFromChainID(req.ChainId) == nil { + _, found := chains.GetChainFromChainID(req.ChainId, k.GetAuthorityKeeper().GetAdditionalChainList(ctx)) + if !found { return nil, status.Error(codes.InvalidArgument, "invalid chain id") } diff --git a/x/observer/keeper/msg_server_remove_chain_params_test.go b/x/observer/keeper/msg_server_remove_chain_params_test.go index 5139f84086..c7b60d7c07 100644 --- a/x/observer/keeper/msg_server_remove_chain_params_test.go +++ b/x/observer/keeper/msg_server_remove_chain_params_test.go @@ -24,9 +24,11 @@ func TestMsgServer_RemoveChainParams(t *testing.T) { // mock the authority keeper for authorization authorityMock := keepertest.GetObserverAuthorityMock(t, k) - chain1 := chains.ExternalChainList()[0].ChainId - chain2 := chains.ExternalChainList()[1].ChainId - chain3 := chains.ExternalChainList()[2].ChainId + chainList := chains.ExternalChainList([]chains.Chain{}) + + chain1 := chainList[0].ChainId + chain2 := chainList[1].ChainId + chain3 := chainList[2].ChainId // set admin admin := sample.AccAddress() @@ -96,7 +98,7 @@ func TestMsgServer_RemoveChainParams(t *testing.T) { msg := types.MsgRemoveChainParams{ Creator: admin, - ChainId: chains.ExternalChainList()[0].ChainId, + ChainId: chains.ExternalChainList([]chains.Chain{})[0].ChainId, } keepertest.MockCheckAuthorization(&authorityMock.Mock, &msg, authoritytypes.ErrUnauthorized) _, err := srv.RemoveChainParams(sdk.WrapSDKContext(ctx), &msg) @@ -117,9 +119,11 @@ func TestMsgServer_RemoveChainParams(t *testing.T) { _, found := k.GetChainParamsList(ctx) require.False(t, found) + chainList := chains.ExternalChainList([]chains.Chain{}) + msg := types.MsgRemoveChainParams{ Creator: admin, - ChainId: chains.ExternalChainList()[0].ChainId, + ChainId: chainList[0].ChainId, } keepertest.MockCheckAuthorization(&authorityMock.Mock, &msg, nil) _, err := srv.RemoveChainParams(sdk.WrapSDKContext(ctx), &msg) @@ -128,16 +132,16 @@ func TestMsgServer_RemoveChainParams(t *testing.T) { // add chain params k.SetChainParamsList(ctx, types.ChainParamsList{ ChainParams: []*types.ChainParams{ - sample.ChainParams(chains.ExternalChainList()[0].ChainId), - sample.ChainParams(chains.ExternalChainList()[1].ChainId), - sample.ChainParams(chains.ExternalChainList()[2].ChainId), + sample.ChainParams(chainList[0].ChainId), + sample.ChainParams(chainList[1].ChainId), + sample.ChainParams(chainList[2].ChainId), }, }) // not found if chain ID not in list msg = types.MsgRemoveChainParams{ Creator: admin, - ChainId: chains.ExternalChainList()[3].ChainId, + ChainId: chainList[3].ChainId, } keepertest.MockCheckAuthorization(&authorityMock.Mock, &msg, nil) _, err = srv.RemoveChainParams(sdk.WrapSDKContext(ctx), &msg) diff --git a/x/observer/keeper/msg_server_reset_chain_nonces.go b/x/observer/keeper/msg_server_reset_chain_nonces.go index a3ea3ecc81..8cd61c97d6 100644 --- a/x/observer/keeper/msg_server_reset_chain_nonces.go +++ b/x/observer/keeper/msg_server_reset_chain_nonces.go @@ -27,8 +27,8 @@ func (k msgServer) ResetChainNonces( return nil, types.ErrTssNotFound } - chain := chains.GetChainFromChainID(msg.ChainId) - if chain == nil { + chain, found := chains.GetChainFromChainID(msg.ChainId, k.GetAuthorityKeeper().GetAdditionalChainList(ctx)) + if !found { return nil, types.ErrSupportedChains } diff --git a/x/observer/keeper/msg_server_reset_chain_nonces_test.go b/x/observer/keeper/msg_server_reset_chain_nonces_test.go index 53009d9608..0b1c76113c 100644 --- a/x/observer/keeper/msg_server_reset_chain_nonces_test.go +++ b/x/observer/keeper/msg_server_reset_chain_nonces_test.go @@ -74,6 +74,7 @@ func TestMsgServer_ResetChainNonces(t *testing.T) { ChainNonceHigh: 5, } keepertest.MockCheckAuthorization(&authorityMock.Mock, &msg, nil) + keepertest.MockGetChainListEmpty(&authorityMock.Mock) _, err := srv.ResetChainNonces(sdk.WrapSDKContext(ctx), &msg) require.ErrorIs(t, err, types.ErrSupportedChains) @@ -109,6 +110,7 @@ func TestMsgServer_ResetChainNonces(t *testing.T) { ChainNonceHigh: int64(nonceHigh), } keepertest.MockCheckAuthorization(&authorityMock.Mock, &msg, nil) + keepertest.MockGetChainListEmpty(&authorityMock.Mock) _, err := srv.ResetChainNonces(sdk.WrapSDKContext(ctx), &msg) require.NoError(t, err) diff --git a/x/observer/keeper/msg_server_update_chain_params_test.go b/x/observer/keeper/msg_server_update_chain_params_test.go index fc38200764..d8ad61820d 100644 --- a/x/observer/keeper/msg_server_update_chain_params_test.go +++ b/x/observer/keeper/msg_server_update_chain_params_test.go @@ -21,9 +21,11 @@ func TestMsgServer_UpdateChainParams(t *testing.T) { }) srv := keeper.NewMsgServerImpl(*k) - chain1 := chains.ExternalChainList()[0].ChainId - chain2 := chains.ExternalChainList()[1].ChainId - chain3 := chains.ExternalChainList()[2].ChainId + chainList := chains.ExternalChainList([]chains.Chain{}) + + chain1 := chainList[0].ChainId + chain2 := chainList[1].ChainId + chain3 := chainList[2].ChainId // set admin admin := sample.AccAddress() @@ -113,7 +115,7 @@ func TestMsgServer_UpdateChainParams(t *testing.T) { msg := types.MsgUpdateChainParams{ Creator: admin, - ChainParams: sample.ChainParams(chains.ExternalChainList()[0].ChainId), + ChainParams: sample.ChainParams(chains.ExternalChainList([]chains.Chain{})[0].ChainId), } keepertest.MockCheckAuthorization(&authorityMock.Mock, &msg, authoritytypes.ErrUnauthorized) _, err := srv.UpdateChainParams(sdk.WrapSDKContext(ctx), &msg) diff --git a/x/observer/keeper/msg_server_vote_blame.go b/x/observer/keeper/msg_server_vote_blame.go index 395b2fa9c1..217d5e5912 100644 --- a/x/observer/keeper/msg_server_vote_blame.go +++ b/x/observer/keeper/msg_server_vote_blame.go @@ -19,8 +19,8 @@ func (k msgServer) VoteBlame( observationType := types.ObservationType_TSSKeySign // GetChainFromChainID makes sure we are getting only supported chains , if a chain support has been turned on using gov proposal, this function returns nil - observationChain := k.GetSupportedChainFromChainID(ctx, vote.ChainId) - if observationChain == nil { + observationChain, found := k.GetSupportedChainFromChainID(ctx, vote.ChainId) + if !found { return nil, cosmoserrors.Wrap( crosschainTypes.ErrUnsupportedChain, fmt.Sprintf("ChainID %d, Blame vote", vote.ChainId), diff --git a/x/observer/keeper/msg_server_vote_block_header.go b/x/observer/keeper/msg_server_vote_block_header.go index 5e8c0e0bce..9ae7a35a56 100644 --- a/x/observer/keeper/msg_server_vote_block_header.go +++ b/x/observer/keeper/msg_server_vote_block_header.go @@ -18,8 +18,8 @@ func (k msgServer) VoteBlockHeader( ctx := sdk.UnwrapSDKContext(goCtx) // check if the chain is enabled - chain := k.GetSupportedChainFromChainID(ctx, msg.ChainId) - if chain == nil { + chain, found := k.GetSupportedChainFromChainID(ctx, msg.ChainId) + if !found { return nil, cosmoserrors.Wrapf(types.ErrSupportedChains, "chain id: %d", msg.ChainId) } diff --git a/x/observer/keeper/msg_server_vote_block_header_test.go b/x/observer/keeper/msg_server_vote_block_header_test.go index 0d41b1be0c..7ce0144e5f 100644 --- a/x/observer/keeper/msg_server_vote_block_header_test.go +++ b/x/observer/keeper/msg_server_vote_block_header_test.go @@ -93,6 +93,9 @@ func TestMsgServer_VoteBlockHeader(t *testing.T) { stakingMock := keepertest.GetObserverStakingMock(t, k) slashingMock := keepertest.GetObserverSlashingMock(t, k) lightclientMock := keepertest.GetObserverLightclientMock(t, k) + authorityMock := keepertest.GetObserverAuthorityMock(t, k) + + keepertest.MockGetChainListEmpty(&authorityMock.Mock) k.SetChainParamsList(ctx, types.ChainParamsList{ ChainParams: []*types.ChainParams{ @@ -131,6 +134,9 @@ func TestMsgServer_VoteBlockHeader(t *testing.T) { stakingMock := keepertest.GetObserverStakingMock(t, k) slashingMock := keepertest.GetObserverSlashingMock(t, k) lightclientMock := keepertest.GetObserverLightclientMock(t, k) + authorityMock := keepertest.GetObserverAuthorityMock(t, k) + + keepertest.MockGetChainListEmpty(&authorityMock.Mock) k.SetChainParamsList(ctx, types.ChainParamsList{ ChainParams: []*types.ChainParams{ @@ -176,6 +182,9 @@ func TestMsgServer_VoteBlockHeader(t *testing.T) { stakingMock := keepertest.GetObserverStakingMock(t, k) slashingMock := keepertest.GetObserverSlashingMock(t, k) lightclientMock := keepertest.GetObserverLightclientMock(t, k) + authorityMock := keepertest.GetObserverAuthorityMock(t, k) + + keepertest.MockGetChainListEmpty(&authorityMock.Mock) k.SetChainParamsList(ctx, types.ChainParamsList{ ChainParams: []*types.ChainParams{ @@ -250,6 +259,9 @@ func TestMsgServer_VoteBlockHeader(t *testing.T) { stakingMock := keepertest.GetObserverStakingMock(t, k) slashingMock := keepertest.GetObserverSlashingMock(t, k) lightclientMock := keepertest.GetObserverLightclientMock(t, k) + authorityMock := keepertest.GetObserverAuthorityMock(t, k) + + keepertest.MockGetChainListEmpty(&authorityMock.Mock) k.SetChainParamsList(ctx, types.ChainParamsList{ ChainParams: []*types.ChainParams{ diff --git a/x/observer/keeper/utils.go b/x/observer/keeper/utils.go index 8d37e82d57..3215a86307 100644 --- a/x/observer/keeper/utils.go +++ b/x/observer/keeper/utils.go @@ -56,7 +56,7 @@ func (k Keeper) IsNonTombstonedObserver(ctx sdk.Context, address string) bool { func (k Keeper) FindBallot( ctx sdk.Context, index string, - chain *chains.Chain, + chain chains.Chain, observationType types.ObservationType, ) (ballot types.Ballot, isNew bool, err error) { isNew = false diff --git a/x/observer/keeper/utils_test.go b/x/observer/keeper/utils_test.go index b11a4512ca..effd815ad5 100644 --- a/x/observer/keeper/utils_test.go +++ b/x/observer/keeper/utils_test.go @@ -314,7 +314,7 @@ func TestKeeper_FindBallot(t *testing.T) { t.Run("should err if chain params not found", func(t *testing.T) { k, ctx, _, _ := keepertest.ObserverKeeper(t) - _, _, err := k.FindBallot(ctx, "index", &chains.Chain{ + _, _, err := k.FindBallot(ctx, "index", chains.Chain{ ChainId: 987, }, types.ObservationType_InboundTx) require.Error(t, err) diff --git a/x/observer/keeper/vote_inbound.go b/x/observer/keeper/vote_inbound.go index b5fcdb1e38..676e93aeaa 100644 --- a/x/observer/keeper/vote_inbound.go +++ b/x/observer/keeper/vote_inbound.go @@ -29,8 +29,8 @@ func (k Keeper) VoteOnInboundBallot( // makes sure we are getting only supported chains // if a chain support has been turned on using gov proposal // this function returns nil - senderChain := k.GetSupportedChainFromChainID(ctx, senderChainID) - if senderChain == nil { + senderChain, found := k.GetSupportedChainFromChainID(ctx, senderChainID) + if !found { return false, false, sdkerrors.Wrap(types.ErrSupportedChains, fmt.Sprintf( "ChainID %d, Observation %s", senderChainID, @@ -44,8 +44,8 @@ func (k Keeper) VoteOnInboundBallot( } // makes sure we are getting only supported chains - receiverChain := k.GetSupportedChainFromChainID(ctx, receiverChainID) - if receiverChain == nil { + receiverChain, found := k.GetSupportedChainFromChainID(ctx, receiverChainID) + if !found { return false, false, sdkerrors.Wrap(types.ErrSupportedChains, fmt.Sprintf( "ChainID %d, Observation %s", receiverChainID, diff --git a/x/observer/keeper/vote_inbound_test.go b/x/observer/keeper/vote_inbound_test.go index 9f9fa09b58..99951e287c 100644 --- a/x/observer/keeper/vote_inbound_test.go +++ b/x/observer/keeper/vote_inbound_test.go @@ -114,6 +114,9 @@ func TestKeeper_VoteOnInboundBallot(t *testing.T) { observer := sample.AccAddress() stakingMock := keepertest.GetObserverStakingMock(t, k) slashingMock := keepertest.GetObserverSlashingMock(t, k) + authorityMock := keepertest.GetObserverAuthorityMock(t, k) + + keepertest.MockGetChainListEmpty(&authorityMock.Mock) k.SetCrosschainFlags(ctx, types.CrosschainFlags{ IsInboundEnabled: true, @@ -179,6 +182,9 @@ func TestKeeper_VoteOnInboundBallot(t *testing.T) { observer := sample.AccAddress() stakingMock := keepertest.GetObserverStakingMock(t, k) slashingMock := keepertest.GetObserverSlashingMock(t, k) + authorityMock := keepertest.GetObserverAuthorityMock(t, k) + + keepertest.MockGetChainListEmpty(&authorityMock.Mock) k.SetCrosschainFlags(ctx, types.CrosschainFlags{ IsInboundEnabled: true, @@ -221,6 +227,9 @@ func TestKeeper_VoteOnInboundBallot(t *testing.T) { observer := sample.AccAddress() stakingMock := keepertest.GetObserverStakingMock(t, k) slashingMock := keepertest.GetObserverSlashingMock(t, k) + authorityMock := keepertest.GetObserverAuthorityMock(t, k) + + keepertest.MockGetChainListEmpty(&authorityMock.Mock) k.SetCrosschainFlags(ctx, types.CrosschainFlags{ IsInboundEnabled: true, @@ -265,6 +274,9 @@ func TestKeeper_VoteOnInboundBallot(t *testing.T) { observer := sample.AccAddress() stakingMock := keepertest.GetObserverStakingMock(t, k) slashingMock := keepertest.GetObserverSlashingMock(t, k) + authorityMock := keepertest.GetObserverAuthorityMock(t, k) + + keepertest.MockGetChainListEmpty(&authorityMock.Mock) k.SetCrosschainFlags(ctx, types.CrosschainFlags{ IsInboundEnabled: true, @@ -316,6 +328,9 @@ func TestKeeper_VoteOnInboundBallot(t *testing.T) { observer := sample.AccAddress() stakingMock := keepertest.GetObserverStakingMock(t, k) slashingMock := keepertest.GetObserverSlashingMock(t, k) + authorityMock := keepertest.GetObserverAuthorityMock(t, k) + + keepertest.MockGetChainListEmpty(&authorityMock.Mock) // threshold high enough to not finalize ballot threshold, err := sdk.NewDecFromStr("0.7") @@ -369,6 +384,9 @@ func TestKeeper_VoteOnInboundBallot(t *testing.T) { observer := sample.AccAddress() stakingMock := keepertest.GetObserverStakingMock(t, k) slashingMock := keepertest.GetObserverSlashingMock(t, k) + authorityMock := keepertest.GetObserverAuthorityMock(t, k) + + keepertest.MockGetChainListEmpty(&authorityMock.Mock) k.SetCrosschainFlags(ctx, types.CrosschainFlags{ IsInboundEnabled: true, @@ -433,6 +451,9 @@ func TestKeeper_VoteOnInboundBallot(t *testing.T) { observer := sample.AccAddress() stakingMock := keepertest.GetObserverStakingMock(t, k) slashingMock := keepertest.GetObserverSlashingMock(t, k) + authorityMock := keepertest.GetObserverAuthorityMock(t, k) + + keepertest.MockGetChainListEmpty(&authorityMock.Mock) k.SetCrosschainFlags(ctx, types.CrosschainFlags{ IsInboundEnabled: true, diff --git a/x/observer/keeper/vote_outbound.go b/x/observer/keeper/vote_outbound.go index 0dc946f5b4..a8212980ed 100644 --- a/x/observer/keeper/vote_outbound.go +++ b/x/observer/keeper/vote_outbound.go @@ -23,8 +23,8 @@ func (k Keeper) VoteOnOutboundBallot( /* EDGE CASE : Params updated in during the finalization process i.e Inbound has been finalized but outbound is still pending */ - observationChain := k.GetSupportedChainFromChainID(ctx, outTxChainID) - if observationChain == nil { + observationChain, found := k.GetSupportedChainFromChainID(ctx, outTxChainID) + if !found { return false, false, ballot, "", observertypes.ErrSupportedChains } if observertypes.CheckReceiveStatus(receiveStatus) != nil { diff --git a/x/observer/keeper/vote_outbound_test.go b/x/observer/keeper/vote_outbound_test.go index 4d14e828ba..bc88b21303 100644 --- a/x/observer/keeper/vote_outbound_test.go +++ b/x/observer/keeper/vote_outbound_test.go @@ -102,6 +102,9 @@ func TestKeeper_VoteOnOutboundBallot(t *testing.T) { observer := sample.AccAddress() stakingMock := keepertest.GetObserverStakingMock(t, k) slashingMock := keepertest.GetObserverSlashingMock(t, k) + authorityMock := keepertest.GetObserverAuthorityMock(t, k) + + keepertest.MockGetChainListEmpty(&authorityMock.Mock) k.SetChainParamsList(ctx, types.ChainParamsList{ ChainParams: []*types.ChainParams{ @@ -140,6 +143,9 @@ func TestKeeper_VoteOnOutboundBallot(t *testing.T) { observer := sample.AccAddress() stakingMock := keepertest.GetObserverStakingMock(t, k) slashingMock := keepertest.GetObserverSlashingMock(t, k) + authorityMock := keepertest.GetObserverAuthorityMock(t, k) + + keepertest.MockGetChainListEmpty(&authorityMock.Mock) k.SetChainParamsList(ctx, types.ChainParamsList{ ChainParams: []*types.ChainParams{ @@ -182,6 +188,9 @@ func TestKeeper_VoteOnOutboundBallot(t *testing.T) { observer := sample.AccAddress() stakingMock := keepertest.GetObserverStakingMock(t, k) slashingMock := keepertest.GetObserverSlashingMock(t, k) + authorityMock := keepertest.GetObserverAuthorityMock(t, k) + + keepertest.MockGetChainListEmpty(&authorityMock.Mock) // threshold high enough to not finalize the ballot threshold, err := sdk.NewDecFromStr("0.7") @@ -228,6 +237,9 @@ func TestKeeper_VoteOnOutboundBallot(t *testing.T) { observer := sample.AccAddress() stakingMock := keepertest.GetObserverStakingMock(t, k) slashingMock := keepertest.GetObserverSlashingMock(t, k) + authorityMock := keepertest.GetObserverAuthorityMock(t, k) + + keepertest.MockGetChainListEmpty(&authorityMock.Mock) k.SetChainParamsList(ctx, types.ChainParamsList{ ChainParams: []*types.ChainParams{ @@ -286,6 +298,9 @@ func TestKeeper_VoteOnOutboundBallot(t *testing.T) { observer := sample.AccAddress() stakingMock := keepertest.GetObserverStakingMock(t, k) slashingMock := keepertest.GetObserverSlashingMock(t, k) + authorityMock := keepertest.GetObserverAuthorityMock(t, k) + + keepertest.MockGetChainListEmpty(&authorityMock.Mock) k.SetChainParamsList(ctx, types.ChainParamsList{ ChainParams: []*types.ChainParams{ diff --git a/x/observer/types/chain_params.go b/x/observer/types/chain_params.go index d67aa520ba..665be3de98 100644 --- a/x/observer/types/chain_params.go +++ b/x/observer/types/chain_params.go @@ -8,6 +8,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ethchains "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" "github.com/zeta-chain/zetacore/pkg/chains" ) @@ -54,15 +55,22 @@ func ValidateChainParams(params *ChainParams) error { if params == nil { return fmt.Errorf("chain params cannot be nil") } - chain := chains.GetChainFromChainID(params.ChainId) - if chain == nil { - return fmt.Errorf("ChainId %d not supported", params.ChainId) - } - // zeta chain skips the rest of the checks for now - if chain.IsZetaChain() { + + // TODO: ZetaChain chain params should be completely removed + // Once removed, this check is no longer necessary as all chasin params would need the same checks + // https://github.com/zeta-chain/node/issues/2419 + _, err := chains.ZetaChainFromChainID(params.ChainId) + if err == nil { + // zeta chain skips the rest of the checks for now return nil } + // ignore error from ZetaChainFromChainID if reason is chain is not zeta chain + // return error otherwise + if !errors.Is(err, chains.ErrNotZetaChain) { + return err + } + if params.ConfirmationCount == 0 { return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "ConfirmationCount must be greater than 0") } @@ -90,38 +98,36 @@ func ValidateChainParams(params *ChainParams) error { ) } - // chain type specific checks - if chains.IsBitcoinChain(params.ChainId) { - if params.WatchUtxoTicker == 0 || params.WatchUtxoTicker > 300 { - return errorsmod.Wrapf( - sdkerrors.ErrInvalidRequest, - "WatchUtxoTicker %d out of range", - params.WatchUtxoTicker, - ) - } + // if WatchUtxoTicker defined, check validity + if params.WatchUtxoTicker > 300 { + return errorsmod.Wrapf( + sdkerrors.ErrInvalidRequest, + "WatchUtxoTicker %d out of range", + params.WatchUtxoTicker, + ) } - if chains.IsEVMChain(params.ChainId) { - if !validChainContractAddress(params.ZetaTokenContractAddress) { - return errorsmod.Wrapf( - sdkerrors.ErrInvalidRequest, - "invalid ZetaTokenContractAddress %s", - params.ZetaTokenContractAddress, - ) - } - if !validChainContractAddress(params.ConnectorContractAddress) { - return errorsmod.Wrapf( - sdkerrors.ErrInvalidRequest, - "invalid ConnectorContractAddress %s", - params.ConnectorContractAddress, - ) - } - if !validChainContractAddress(params.Erc20CustodyContractAddress) { - return errorsmod.Wrapf( - sdkerrors.ErrInvalidRequest, - "invalid Erc20CustodyContractAddress %s", - params.Erc20CustodyContractAddress, - ) - } + + // if contract addresses are defined, check validity + if params.ZetaTokenContractAddress != "" && !validChainContractAddress(params.ZetaTokenContractAddress) { + return errorsmod.Wrapf( + sdkerrors.ErrInvalidRequest, + "invalid ZetaTokenContractAddress %s", + params.ZetaTokenContractAddress, + ) + } + if params.ConnectorContractAddress != "" && !validChainContractAddress(params.ConnectorContractAddress) { + return errorsmod.Wrapf( + sdkerrors.ErrInvalidRequest, + "invalid ConnectorContractAddress %s", + params.ConnectorContractAddress, + ) + } + if params.Erc20CustodyContractAddress != "" && !validChainContractAddress(params.Erc20CustodyContractAddress) { + return errorsmod.Wrapf( + sdkerrors.ErrInvalidRequest, + "invalid Erc20CustodyContractAddress %s", + params.Erc20CustodyContractAddress, + ) } if params.BallotThreshold.IsNil() || params.BallotThreshold.GT(sdk.OneDec()) { diff --git a/x/observer/types/chain_params_test.go b/x/observer/types/chain_params_test.go index 1703b43f54..dff1311a9c 100644 --- a/x/observer/types/chain_params_test.go +++ b/x/observer/types/chain_params_test.go @@ -99,9 +99,9 @@ func (s *UpdateChainParamsSuite) TestCommonParams() { s.Validate(s.btcParams) } -func (s *UpdateChainParamsSuite) TestBTCParams() { +func (s *UpdateChainParamsSuite) TestBTCParamsInvalid() { copy := *s.btcParams - copy.WatchUtxoTicker = 0 + copy.WatchUtxoTicker = 301 err := types.ValidateChainParams(©) require.NotNil(s.T(), err) } diff --git a/x/observer/types/expected_keepers.go b/x/observer/types/expected_keepers.go index 5eb8b03468..4a556d4fa4 100644 --- a/x/observer/types/expected_keepers.go +++ b/x/observer/types/expected_keepers.go @@ -5,6 +5,7 @@ import ( slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/zeta-chain/zetacore/pkg/chains" "github.com/zeta-chain/zetacore/pkg/proofs" authoritytypes "github.com/zeta-chain/zetacore/x/authority/types" ) @@ -33,6 +34,7 @@ type StakingHooks interface { type AuthorityKeeper interface { CheckAuthorization(ctx sdk.Context, msg sdk.Msg) error + GetAdditionalChainList(ctx sdk.Context) (list []chains.Chain) // SetPolicies is solely used for the migration of policies from observer to authority SetPolicies(ctx sdk.Context, policies authoritytypes.Policies) diff --git a/x/observer/types/message_remove_chain_params.go b/x/observer/types/message_remove_chain_params.go index b34574e4de..708f87290f 100644 --- a/x/observer/types/message_remove_chain_params.go +++ b/x/observer/types/message_remove_chain_params.go @@ -4,8 +4,6 @@ import ( cosmoserrors "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - - "github.com/zeta-chain/zetacore/pkg/chains" ) const TypeMsgRemoveChainParams = "remove_chain_params" @@ -46,11 +44,5 @@ func (msg *MsgRemoveChainParams) ValidateBasic() error { return cosmoserrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid creator address (%s)", err) } - // Check if chain exists - chain := chains.GetChainFromChainID(msg.ChainId) - if chain == nil { - return cosmoserrors.Wrapf(sdkerrors.ErrInvalidChainID, "invalid chain id (%d)", msg.ChainId) - } - return nil } diff --git a/x/observer/types/message_remove_chain_params_test.go b/x/observer/types/message_remove_chain_params_test.go index b81f29ff77..69f8f83103 100644 --- a/x/observer/types/message_remove_chain_params_test.go +++ b/x/observer/types/message_remove_chain_params_test.go @@ -22,26 +22,17 @@ func TestMsgRemoveChainParams_ValidateBasic(t *testing.T) { name: "valid message", msg: types.NewMsgRemoveChainParams( sample.AccAddress(), - chains.ExternalChainList()[0].ChainId, + chains.ExternalChainList([]chains.Chain{})[0].ChainId, ), }, { name: "invalid address", msg: types.NewMsgRemoveChainParams( "invalid_address", - chains.ExternalChainList()[0].ChainId, + chains.ExternalChainList([]chains.Chain{})[0].ChainId, ), err: sdkerrors.ErrInvalidAddress, }, - - { - name: "invalid chain ID", - msg: types.NewMsgRemoveChainParams( - sample.AccAddress(), - 999, - ), - err: sdkerrors.ErrInvalidChainID, - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/x/observer/types/message_reset_chain_nonces.go b/x/observer/types/message_reset_chain_nonces.go index ac14463af5..80e0a2d26b 100644 --- a/x/observer/types/message_reset_chain_nonces.go +++ b/x/observer/types/message_reset_chain_nonces.go @@ -6,8 +6,6 @@ import ( cosmoserrors "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - - "github.com/zeta-chain/zetacore/pkg/chains" ) const TypeMsgResetChainNonces = "reset_chain_nonces" @@ -55,12 +53,6 @@ func (msg *MsgResetChainNonces) ValidateBasic() error { return cosmoserrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid creator address (%s)", err) } - // Check if chain exists - chain := chains.GetChainFromChainID(msg.ChainId) - if chain == nil { - return cosmoserrors.Wrapf(sdkerrors.ErrInvalidChainID, "invalid chain id (%d)", msg.ChainId) - } - if msg.ChainNonceLow < 0 { return errors.New("chain nonce low must be greater or equal 0") } diff --git a/x/observer/types/message_reset_chain_nonces_test.go b/x/observer/types/message_reset_chain_nonces_test.go index d131d32ed6..41da6643d2 100644 --- a/x/observer/types/message_reset_chain_nonces_test.go +++ b/x/observer/types/message_reset_chain_nonces_test.go @@ -12,6 +12,8 @@ import ( ) func TestMsgResetChainNonces_ValidateBasic(t *testing.T) { + chainList := chains.ExternalChainList([]chains.Chain{}) + tests := []struct { name string msg types.MsgResetChainNonces @@ -21,7 +23,7 @@ func TestMsgResetChainNonces_ValidateBasic(t *testing.T) { name: "valid message chain nonce high greater than nonce low", msg: types.MsgResetChainNonces{ Creator: sample.AccAddress(), - ChainId: chains.ExternalChainList()[0].ChainId, + ChainId: chainList[0].ChainId, ChainNonceLow: 1, ChainNonceHigh: 5, }, @@ -31,7 +33,7 @@ func TestMsgResetChainNonces_ValidateBasic(t *testing.T) { name: "valid message chain nonce high same as nonce low", msg: types.MsgResetChainNonces{ Creator: sample.AccAddress(), - ChainId: chains.ExternalChainList()[0].ChainId, + ChainId: chainList[0].ChainId, ChainNonceLow: 1, ChainNonceHigh: 1, }, @@ -41,15 +43,7 @@ func TestMsgResetChainNonces_ValidateBasic(t *testing.T) { name: "invalid address", msg: types.MsgResetChainNonces{ Creator: "invalid_address", - ChainId: chains.ExternalChainList()[0].ChainId, - }, - wantErr: true, - }, - { - name: "invalid chain ID", - msg: types.MsgResetChainNonces{ - Creator: sample.AccAddress(), - ChainId: 999, + ChainId: chainList[0].ChainId, }, wantErr: true, }, @@ -57,7 +51,7 @@ func TestMsgResetChainNonces_ValidateBasic(t *testing.T) { name: "invalid chain nonce low", msg: types.MsgResetChainNonces{ Creator: sample.AccAddress(), - ChainId: chains.ExternalChainList()[0].ChainId, + ChainId: chainList[0].ChainId, ChainNonceLow: -1, }, wantErr: true, @@ -66,7 +60,7 @@ func TestMsgResetChainNonces_ValidateBasic(t *testing.T) { name: "invalid chain nonce high", msg: types.MsgResetChainNonces{ Creator: sample.AccAddress(), - ChainId: chains.ExternalChainList()[0].ChainId, + ChainId: chainList[0].ChainId, ChainNonceLow: 1, ChainNonceHigh: -1, }, @@ -76,7 +70,7 @@ func TestMsgResetChainNonces_ValidateBasic(t *testing.T) { name: "invalid chain nonce low greater than chain nonce high", msg: types.MsgResetChainNonces{ Creator: sample.AccAddress(), - ChainId: chains.ExternalChainList()[0].ChainId, + ChainId: chainList[0].ChainId, ChainNonceLow: 1, ChainNonceHigh: 0, }, diff --git a/x/observer/types/message_update_chain_params_test.go b/x/observer/types/message_update_chain_params_test.go index fe2d526631..69dd70ced8 100644 --- a/x/observer/types/message_update_chain_params_test.go +++ b/x/observer/types/message_update_chain_params_test.go @@ -13,6 +13,8 @@ import ( ) func TestMsgUpdateChainParams_ValidateBasic(t *testing.T) { + chainList := chains.ExternalChainList([]chains.Chain{}) + tests := []struct { name string msg *types.MsgUpdateChainParams @@ -22,14 +24,14 @@ func TestMsgUpdateChainParams_ValidateBasic(t *testing.T) { name: "valid message", msg: types.NewMsgUpdateChainParams( sample.AccAddress(), - sample.ChainParams(chains.ExternalChainList()[0].ChainId), + sample.ChainParams(chainList[0].ChainId), ), }, { name: "invalid address", msg: types.NewMsgUpdateChainParams( "invalid_address", - sample.ChainParams(chains.ExternalChainList()[0].ChainId), + sample.ChainParams(chainList[0].ChainId), ), err: sdkerrors.ErrInvalidAddress, }, diff --git a/x/observer/types/message_vote_blame.go b/x/observer/types/message_vote_blame.go index 2a06e84869..336a086185 100644 --- a/x/observer/types/message_vote_blame.go +++ b/x/observer/types/message_vote_blame.go @@ -5,8 +5,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/ethereum/go-ethereum/crypto" - - "github.com/zeta-chain/zetacore/pkg/chains" ) const TypeMsgVoteBlame = "vote_blame" @@ -34,9 +32,7 @@ func (m *MsgVoteBlame) ValidateBasic() error { if err != nil { return cosmoserrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid creator address (%s)", err) } - if chains.GetChainFromChainID(m.ChainId) == nil { - return cosmoserrors.Wrapf(sdkerrors.ErrInvalidChainID, "chain id (%d)", m.ChainId) - } + return nil } diff --git a/x/observer/types/message_vote_blame_test.go b/x/observer/types/message_vote_blame_test.go index 9514beac40..6385621a12 100644 --- a/x/observer/types/message_vote_blame_test.go +++ b/x/observer/types/message_vote_blame_test.go @@ -28,15 +28,6 @@ func TestNewMsgVoteBlameMsg_ValidateBasic(t *testing.T) { ), error: true, }, - { - name: "invalid chain id", - msg: types.NewMsgVoteBlameMsg( - sample.AccAddress(), - -1, - sample.BlameRecordsList(t, 1)[0], - ), - error: true, - }, { name: "valid", msg: types.NewMsgVoteBlameMsg( diff --git a/x/observer/types/message_vote_block_header.go b/x/observer/types/message_vote_block_header.go index 004b2ce199..ba52975251 100644 --- a/x/observer/types/message_vote_block_header.go +++ b/x/observer/types/message_vote_block_header.go @@ -6,7 +6,6 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/ethereum/go-ethereum/crypto" - "github.com/zeta-chain/zetacore/pkg/chains" "github.com/zeta-chain/zetacore/pkg/proofs" ) @@ -59,10 +58,6 @@ func (msg *MsgVoteBlockHeader) ValidateBasic() error { return cosmoserrors.Wrapf(sdkerrors.ErrInvalidAddress, err.Error()) } - if !chains.IsHeaderSupportedChain(msg.ChainId) { - return cosmoserrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid chain id (%d)", msg.ChainId) - } - if len(msg.BlockHash) != 32 { return cosmoserrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid block hash length (%d)", len(msg.BlockHash)) } diff --git a/x/observer/types/observer.pb.go b/x/observer/types/observer.pb.go index 13d3e1c998..2d21b13149 100644 --- a/x/observer/types/observer.pb.go +++ b/x/observer/types/observer.pb.go @@ -7,7 +7,6 @@ import ( fmt "fmt" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" - _ "github.com/zeta-chain/zetacore/pkg/chains" io "io" math "math" math_bits "math/bits" @@ -194,31 +193,30 @@ func init() { } var fileDescriptor_05af1bc65780862e = []byte{ - // 378 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x51, 0xdf, 0xaa, 0xd3, 0x30, - 0x18, 0x6f, 0xb6, 0x29, 0x9c, 0x1c, 0x8f, 0xeb, 0xc2, 0x84, 0x31, 0xa1, 0x8c, 0x79, 0x33, 0x86, - 0xb6, 0xa0, 0x4f, 0xa0, 0x43, 0x74, 0x38, 0x18, 0xb4, 0x1b, 0x82, 0x37, 0x23, 0x6d, 0x63, 0x1b, - 0x5c, 0x93, 0xd2, 0x7c, 0x95, 0xd5, 0xa7, 0xf0, 0x21, 0xbc, 0xf0, 0x51, 0xbc, 0xdc, 0xa5, 0x97, - 0xb2, 0xbd, 0x88, 0x24, 0x5d, 0x26, 0xc8, 0xb9, 0xca, 0xf7, 0xfb, 0x9b, 0x8b, 0x1f, 0x9e, 0x7f, - 0x63, 0x40, 0x93, 0x9c, 0x72, 0x11, 0x98, 0x4b, 0x56, 0x2c, 0x90, 0xb1, 0x62, 0xd5, 0x57, 0x56, - 0x5d, 0x0f, 0xbf, 0xac, 0x24, 0x48, 0xf2, 0xf4, 0xea, 0xf5, 0xad, 0xd7, 0xb7, 0x96, 0xf1, 0x30, - 0x93, 0x99, 0x34, 0xbe, 0x40, 0x5f, 0x6d, 0x64, 0x7c, 0x5f, 0x7d, 0xf9, 0x25, 0x0b, 0x0c, 0xa5, - 0x2e, 0x4f, 0xeb, 0x9d, 0xbe, 0xc4, 0xb7, 0xeb, 0x4b, 0x5b, 0xc4, 0x80, 0x3c, 0xc3, 0x77, 0xb6, - 0x7c, 0xb7, 0xe7, 0x0a, 0x46, 0x68, 0xd2, 0x9d, 0xdd, 0x84, 0x8f, 0x2c, 0xb9, 0xe2, 0x0a, 0xa6, - 0x1f, 0xf1, 0x60, 0x45, 0x15, 0xd8, 0xdc, 0x42, 0xd6, 0x02, 0xc8, 0x10, 0x3f, 0x48, 0xf4, 0x31, - 0x42, 0x13, 0x34, 0xeb, 0x85, 0x2d, 0x20, 0xcf, 0x31, 0xd9, 0x53, 0x05, 0xbb, 0x24, 0xa7, 0x22, - 0x63, 0xbb, 0x9c, 0xf1, 0x2c, 0x87, 0x51, 0x67, 0x82, 0x66, 0xdd, 0xd0, 0xd5, 0xca, 0xc2, 0x08, - 0xef, 0x0d, 0x3f, 0xdf, 0xe3, 0x7e, 0x5b, 0x4a, 0x81, 0x4b, 0xb1, 0x69, 0x4a, 0x46, 0x9e, 0xe0, - 0xc1, 0xdb, 0xa2, 0x84, 0xc6, 0x7e, 0xa6, 0x49, 0xd7, 0x21, 0x77, 0xf8, 0x66, 0x29, 0x62, 0x59, - 0x8b, 0x74, 0x73, 0x70, 0x11, 0x79, 0x8c, 0xf1, 0xba, 0x06, 0x8b, 0x3b, 0x5a, 0xde, 0x44, 0xd1, - 0x07, 0xd6, 0xbc, 0x63, 0xc2, 0xed, 0x6a, 0xb9, 0x85, 0x11, 0xcf, 0x84, 0xdb, 0x1b, 0xf7, 0x7e, - 0xfe, 0xf0, 0xd0, 0x7c, 0x85, 0x87, 0xb6, 0x75, 0x5b, 0xa6, 0x14, 0x58, 0xc8, 0xa8, 0x92, 0x42, - 0x87, 0xb7, 0x22, 0x65, 0x9f, 0xb9, 0x60, 0xa9, 0xeb, 0x98, 0xb0, 0x2c, 0x62, 0x05, 0x52, 0x63, - 0x44, 0xfa, 0xf8, 0xf6, 0x75, 0x5a, 0x70, 0xd1, 0x66, 0xdc, 0x4e, 0xdb, 0xf6, 0x66, 0xf9, 0xeb, - 0xe4, 0xa1, 0xe3, 0xc9, 0x43, 0x7f, 0x4e, 0x1e, 0xfa, 0x7e, 0xf6, 0x9c, 0xe3, 0xd9, 0x73, 0x7e, - 0x9f, 0x3d, 0xe7, 0x53, 0x90, 0x71, 0xc8, 0xeb, 0xd8, 0x4f, 0x64, 0x61, 0xf6, 0x78, 0xf1, 0xdf, - 0x34, 0x87, 0x7f, 0xdb, 0x43, 0x53, 0x32, 0x15, 0x3f, 0x34, 0xd3, 0xbc, 0xfa, 0x1b, 0x00, 0x00, - 0xff, 0xff, 0xc7, 0x4c, 0xd1, 0x68, 0x27, 0x02, 0x00, 0x00, + // 367 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0x51, 0xcf, 0x8a, 0xda, 0x40, + 0x1c, 0xce, 0xa8, 0x2d, 0x38, 0xd6, 0x1a, 0x07, 0x0b, 0x62, 0x21, 0x88, 0xbd, 0x88, 0xb4, 0x09, + 0xb4, 0x4f, 0xd0, 0x4a, 0x69, 0xa5, 0x82, 0x90, 0x28, 0x85, 0x5e, 0x64, 0x92, 0x4c, 0x93, 0x01, + 0x33, 0x13, 0x32, 0xbf, 0x14, 0xd3, 0xa7, 0xe8, 0x43, 0xf4, 0xb0, 0x8f, 0xb2, 0x47, 0x8f, 0x7b, + 0x5c, 0xf4, 0x45, 0x96, 0x49, 0x76, 0x5c, 0xd8, 0xdb, 0xf7, 0xfd, 0xbe, 0x3f, 0xbf, 0xc3, 0x87, + 0x17, 0x7f, 0x19, 0xd0, 0x28, 0xa5, 0x5c, 0x78, 0x35, 0x92, 0x05, 0xf3, 0x64, 0xa8, 0x58, 0xf1, + 0x87, 0x15, 0x57, 0xe0, 0xe6, 0x85, 0x04, 0x49, 0xde, 0x5e, 0xbd, 0xae, 0xf1, 0xba, 0xc6, 0x32, + 0x19, 0x25, 0x32, 0x91, 0xb5, 0xcf, 0xd3, 0xa8, 0x89, 0xcc, 0x3e, 0xe2, 0xde, 0xe6, 0xd1, 0x11, + 0x30, 0x20, 0xef, 0x70, 0xdf, 0x04, 0xf6, 0x07, 0xae, 0x60, 0x8c, 0xa6, 0xed, 0x79, 0xd7, 0x7f, + 0x65, 0x8e, 0x6b, 0xae, 0x60, 0xf6, 0x13, 0x0f, 0xd7, 0x54, 0x81, 0xc9, 0x2d, 0x65, 0x29, 0x80, + 0x8c, 0xf0, 0x8b, 0x48, 0x83, 0x31, 0x9a, 0xa2, 0x79, 0xc7, 0x6f, 0x08, 0x79, 0x8f, 0xc9, 0x81, + 0x2a, 0xd8, 0x47, 0x29, 0x15, 0x09, 0xdb, 0xa7, 0x8c, 0x27, 0x29, 0x8c, 0x5b, 0x53, 0x34, 0x6f, + 0xfb, 0xb6, 0x56, 0x96, 0xb5, 0xf0, 0xbd, 0xbe, 0x2f, 0x0e, 0x78, 0xd0, 0x94, 0x52, 0xe0, 0x52, + 0x6c, 0xab, 0x9c, 0x91, 0x37, 0x78, 0xf8, 0x35, 0xcb, 0xa1, 0x32, 0xcf, 0xf4, 0xd1, 0xb6, 0x48, + 0x1f, 0x77, 0x57, 0x22, 0x94, 0xa5, 0x88, 0xb7, 0x47, 0x1b, 0x91, 0xd7, 0x18, 0x6f, 0x4a, 0x30, + 0xbc, 0xa5, 0xe5, 0x6d, 0x10, 0xfc, 0x60, 0xd5, 0x37, 0x26, 0xec, 0xb6, 0x96, 0x1b, 0x1a, 0xf0, + 0x44, 0xd8, 0x9d, 0x49, 0xe7, 0xe6, 0xbf, 0x83, 0x16, 0x6b, 0x3c, 0x32, 0xad, 0xbb, 0x3c, 0xa6, + 0xc0, 0x7c, 0x46, 0x95, 0x14, 0x3a, 0xbc, 0x13, 0x31, 0xfb, 0xcd, 0x05, 0x8b, 0x6d, 0xab, 0x0e, + 0xcb, 0x2c, 0x54, 0x20, 0x35, 0x47, 0x64, 0x80, 0x7b, 0x9f, 0xe3, 0x8c, 0x8b, 0x26, 0x63, 0xb7, + 0x9a, 0xb6, 0x2f, 0xab, 0xdb, 0xb3, 0x83, 0x4e, 0x67, 0x07, 0xdd, 0x9f, 0x1d, 0xf4, 0xef, 0xe2, + 0x58, 0xa7, 0x8b, 0x63, 0xdd, 0x5d, 0x1c, 0xeb, 0x97, 0x97, 0x70, 0x48, 0xcb, 0xd0, 0x8d, 0x64, + 0x56, 0x4f, 0xf8, 0xe1, 0xd9, 0x9a, 0xc7, 0xa7, 0x3d, 0xa1, 0xca, 0x99, 0x0a, 0x5f, 0xd6, 0xd3, + 0x7c, 0x7a, 0x08, 0x00, 0x00, 0xff, 0xff, 0x30, 0x6b, 0xf8, 0xf8, 0xfb, 0x01, 0x00, 0x00, } func (m *ObserverSet) Marshal() (dAtA []byte, err error) { diff --git a/x/observer/types/params.pb.go b/x/observer/types/params.pb.go index 0588f7228c..98b425f77e 100644 --- a/x/observer/types/params.pb.go +++ b/x/observer/types/params.pb.go @@ -8,7 +8,6 @@ import ( github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" - _ "github.com/zeta-chain/zetacore/pkg/chains" io "io" math "math" math_bits "math/bits" @@ -84,6 +83,7 @@ type ChainParams struct { BallotThreshold github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,14,opt,name=ballot_threshold,json=ballotThreshold,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"ballot_threshold"` MinObserverDelegation github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,15,opt,name=min_observer_delegation,json=minObserverDelegation,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"min_observer_delegation"` IsSupported bool `protobuf:"varint,16,opt,name=is_supported,json=isSupported,proto3" json:"is_supported,omitempty"` + GatewayAddress string `protobuf:"bytes,17,opt,name=gateway_address,json=gatewayAddress,proto3" json:"gateway_address,omitempty"` } func (m *ChainParams) Reset() { *m = ChainParams{} } @@ -203,6 +203,13 @@ func (m *ChainParams) GetIsSupported() bool { return false } +func (m *ChainParams) GetGatewayAddress() string { + if m != nil { + return m.GatewayAddress + } + return "" +} + // Deprecated(v17) type Params struct { // Deprecated(v17):Moved into the emissions module @@ -260,47 +267,47 @@ func init() { } var fileDescriptor_e7fa4666eddf88e5 = []byte{ - // 626 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x94, 0xc1, 0x4e, 0xd4, 0x40, - 0x18, 0xc7, 0xb7, 0x2e, 0x22, 0xcc, 0x02, 0x0b, 0x0d, 0x6a, 0x81, 0xa4, 0xac, 0x24, 0x6a, 0x43, - 0x42, 0x6b, 0xd0, 0xa3, 0x92, 0xc8, 0x72, 0x21, 0x62, 0x24, 0x05, 0x0f, 0x7a, 0x70, 0x32, 0x3b, - 0x1d, 0xda, 0xc9, 0xb6, 0xfd, 0x9a, 0x99, 0x29, 0x82, 0x4f, 0xe1, 0x3b, 0xf8, 0x32, 0x1c, 0x39, - 0x1a, 0x0f, 0xc4, 0xc0, 0x8b, 0x98, 0x4e, 0xa7, 0xcb, 0x0a, 0x86, 0x83, 0xa7, 0xce, 0x7c, 0xff, - 0xdf, 0xff, 0xbf, 0xdf, 0x6c, 0xbf, 0x0e, 0xf2, 0xbe, 0x31, 0x45, 0x68, 0x42, 0x78, 0x1e, 0xe8, - 0x15, 0x08, 0x16, 0xc0, 0x40, 0x32, 0x71, 0xcc, 0x44, 0x50, 0x10, 0x41, 0x32, 0xe9, 0x17, 0x02, - 0x14, 0xd8, 0x2b, 0x23, 0xd2, 0x6f, 0x48, 0xbf, 0x21, 0x97, 0x17, 0x63, 0x88, 0x41, 0x73, 0x41, - 0xb5, 0xaa, 0x2d, 0xcb, 0xeb, 0x77, 0x85, 0x37, 0x8b, 0x3b, 0xd8, 0x62, 0x18, 0x07, 0xba, 0x24, - 0xcd, 0xa3, 0x66, 0xd7, 0xbe, 0xa0, 0x6e, 0xbf, 0xda, 0xef, 0xeb, 0xfe, 0xf6, 0xb8, 0x54, 0xf6, - 0x3b, 0x34, 0xa3, 0x11, 0x5c, 0xf7, 0xec, 0x58, 0xbd, 0xb6, 0xd7, 0xd9, 0xf4, 0xfc, 0x3b, 0x9a, - 0xf6, 0xc7, 0x32, 0xc2, 0x0e, 0xbd, 0xde, 0xac, 0xfd, 0x98, 0x44, 0x9d, 0x31, 0xd1, 0x5e, 0x42, - 0x53, 0x75, 0x38, 0x8f, 0x9c, 0x4e, 0xcf, 0xf2, 0xda, 0xe1, 0x03, 0xbd, 0xdf, 0x8d, 0xec, 0x0d, - 0x64, 0x53, 0xc8, 0x8f, 0xb8, 0xc8, 0x88, 0xe2, 0x90, 0x63, 0x0a, 0x65, 0xae, 0x1c, 0xab, 0x67, - 0x79, 0x13, 0xe1, 0xc2, 0xb8, 0xd2, 0xaf, 0x04, 0xdb, 0x43, 0xf3, 0x31, 0x91, 0xb8, 0x10, 0x9c, - 0x32, 0xac, 0x38, 0x1d, 0x32, 0xe1, 0xdc, 0xd3, 0xf0, 0x5c, 0x4c, 0xe4, 0x7e, 0x55, 0x3e, 0xd4, - 0x55, 0xfb, 0x29, 0x9a, 0xe3, 0xf9, 0x00, 0xca, 0x3c, 0x6a, 0xb8, 0xb6, 0xe6, 0x66, 0x4d, 0xd5, - 0x60, 0xcf, 0x51, 0x17, 0x4a, 0xf5, 0x17, 0x37, 0x51, 0xe7, 0x35, 0x65, 0x03, 0xae, 0xa3, 0x85, - 0xaf, 0x44, 0xd1, 0x04, 0x97, 0xea, 0x04, 0x1a, 0xf4, 0xbe, 0x46, 0xbb, 0x5a, 0xf8, 0xa8, 0x4e, - 0xc0, 0xb0, 0x6f, 0x90, 0x7e, 0xd9, 0x58, 0xc1, 0x90, 0x55, 0x47, 0xca, 0x95, 0x20, 0x54, 0x61, - 0x12, 0x45, 0x82, 0x49, 0xe9, 0x4c, 0xf5, 0x2c, 0x6f, 0x3a, 0x74, 0x2a, 0xe4, 0xb0, 0x22, 0xfa, - 0x06, 0x78, 0x5b, 0xeb, 0xf6, 0x6b, 0xb4, 0x4c, 0x21, 0xcf, 0x19, 0x55, 0x20, 0x6e, 0xbb, 0xa7, - 0x6b, 0xf7, 0x88, 0xb8, 0xe9, 0xee, 0x23, 0x97, 0x09, 0xba, 0xf9, 0x02, 0xd3, 0x52, 0x2a, 0x88, - 0x4e, 0x6f, 0x27, 0x20, 0x9d, 0xb0, 0xa2, 0xa9, 0x7e, 0x0d, 0xfd, 0xa3, 0x85, 0xd1, 0xdf, 0x22, - 0x69, 0xc2, 0xa2, 0x32, 0x65, 0x98, 0xe7, 0x8a, 0x89, 0x63, 0x92, 0x3a, 0x33, 0xfa, 0x1d, 0x3a, - 0x0d, 0x71, 0x60, 0x80, 0x5d, 0xa3, 0xdb, 0x5b, 0x68, 0xe5, 0xb6, 0x3b, 0x05, 0x18, 0x92, 0x84, - 0x91, 0xc8, 0x99, 0xd5, 0xf6, 0xa5, 0x9b, 0xf6, 0xbd, 0x06, 0xb0, 0x3f, 0xa1, 0xf9, 0x01, 0x49, - 0x53, 0x50, 0x58, 0x25, 0x82, 0xc9, 0x04, 0xd2, 0xc8, 0x99, 0xab, 0x9a, 0xde, 0xf6, 0xcf, 0x2e, - 0x56, 0x5b, 0xbf, 0x2e, 0x56, 0x9f, 0xc5, 0x5c, 0x25, 0xe5, 0xc0, 0xa7, 0x90, 0x05, 0x14, 0x64, - 0x06, 0xd2, 0x3c, 0x36, 0x64, 0x34, 0x0c, 0xd4, 0x69, 0xc1, 0xa4, 0xbf, 0xc3, 0x68, 0xd8, 0xad, - 0x73, 0x0e, 0x9b, 0x18, 0xfb, 0x08, 0x3d, 0xce, 0x78, 0x8e, 0x9b, 0x19, 0xc6, 0x11, 0x4b, 0x59, - 0xac, 0x07, 0xcc, 0xe9, 0xfe, 0xd7, 0x2f, 0x3c, 0xcc, 0x78, 0xfe, 0xc1, 0xa4, 0xed, 0x8c, 0xc2, - 0xec, 0x27, 0x68, 0x86, 0x4b, 0x2c, 0xcb, 0xa2, 0x00, 0xa1, 0x58, 0xe4, 0xcc, 0xf7, 0x2c, 0x6f, - 0x2a, 0xec, 0x70, 0x79, 0xd0, 0x94, 0xd6, 0xb6, 0xd0, 0xa4, 0xf9, 0x3e, 0x5e, 0xa1, 0x47, 0xe6, - 0xbc, 0x19, 0x51, 0xa5, 0xe0, 0xea, 0x14, 0x0f, 0x52, 0xa0, 0x43, 0xa9, 0x67, 0xb6, 0x1d, 0x2e, - 0xd6, 0xea, 0x7b, 0x23, 0x6e, 0x6b, 0x6d, 0x7b, 0xf7, 0xec, 0xd2, 0xb5, 0xce, 0x2f, 0x5d, 0xeb, - 0xf7, 0xa5, 0x6b, 0x7d, 0xbf, 0x72, 0x5b, 0xe7, 0x57, 0x6e, 0xeb, 0xe7, 0x95, 0xdb, 0xfa, 0x1c, - 0x8c, 0xf5, 0x5e, 0x4d, 0xd9, 0xc6, 0x8d, 0x7b, 0xe1, 0xe4, 0xfa, 0x16, 0xd1, 0x07, 0x19, 0x4c, - 0xea, 0x7b, 0xe1, 0xe5, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa1, 0x11, 0xb3, 0xd5, 0xce, 0x04, - 0x00, 0x00, + // 636 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x94, 0x41, 0x4f, 0xd4, 0x4e, + 0x18, 0xc6, 0xb7, 0xff, 0xe5, 0x8f, 0x30, 0x0b, 0xbb, 0xd0, 0xa0, 0x16, 0x48, 0xca, 0x4a, 0xa2, + 0x36, 0x24, 0xb4, 0x06, 0x3d, 0x2a, 0x89, 0x2c, 0x17, 0x22, 0x46, 0x52, 0xf0, 0xa0, 0x07, 0x27, + 0xb3, 0xd3, 0xa1, 0x9d, 0x6c, 0xdb, 0x77, 0x33, 0x33, 0x05, 0xd6, 0x4f, 0xe1, 0xc7, 0xe2, 0xe0, + 0x81, 0xa3, 0xf1, 0x40, 0x0c, 0x7c, 0x11, 0xd3, 0xe9, 0x74, 0x59, 0xc1, 0x70, 0xf0, 0xb4, 0xd3, + 0xf7, 0xf9, 0x3d, 0x4f, 0x67, 0xfa, 0xbe, 0x3b, 0xc8, 0xfb, 0xca, 0x14, 0xa1, 0x09, 0xe1, 0x79, + 0xa0, 0x57, 0x20, 0x58, 0x00, 0x7d, 0xc9, 0xc4, 0x09, 0x13, 0xc1, 0x90, 0x08, 0x92, 0x49, 0x7f, + 0x28, 0x40, 0x81, 0xbd, 0x3a, 0x26, 0xfd, 0x9a, 0xf4, 0x6b, 0x72, 0x65, 0x29, 0x86, 0x18, 0x34, + 0x17, 0x94, 0xab, 0xca, 0xb2, 0xb2, 0x71, 0x5f, 0x78, 0xbd, 0xa8, 0xd8, 0xf5, 0x2f, 0xa8, 0xd3, + 0x2b, 0xc9, 0x03, 0xfd, 0xce, 0x7d, 0x2e, 0x95, 0xfd, 0x0e, 0xcd, 0x69, 0x33, 0xae, 0xf6, 0xe1, + 0x58, 0xdd, 0xa6, 0xd7, 0xda, 0xf2, 0xfc, 0x7b, 0x36, 0xe2, 0x4f, 0x64, 0x84, 0x2d, 0x7a, 0xf3, + 0xb0, 0xfe, 0x7d, 0x1a, 0xb5, 0x26, 0x44, 0x7b, 0x19, 0xcd, 0x54, 0xe1, 0x3c, 0x72, 0x5a, 0x5d, + 0xcb, 0x6b, 0x86, 0x0f, 0xf4, 0xf3, 0x5e, 0x64, 0x6f, 0x22, 0x9b, 0x42, 0x7e, 0xcc, 0x45, 0x46, + 0x14, 0x87, 0x1c, 0x53, 0x28, 0x72, 0xe5, 0x58, 0x5d, 0xcb, 0x9b, 0x0a, 0x17, 0x27, 0x95, 0x5e, + 0x29, 0xd8, 0x1e, 0x5a, 0x88, 0x89, 0xc4, 0x43, 0xc1, 0x29, 0xc3, 0x8a, 0xd3, 0x01, 0x13, 0xce, + 0x7f, 0x1a, 0x6e, 0xc7, 0x44, 0x1e, 0x94, 0xe5, 0x23, 0x5d, 0xb5, 0x9f, 0xa2, 0x36, 0xcf, 0xfb, + 0x50, 0xe4, 0x51, 0xcd, 0x35, 0x35, 0x37, 0x6f, 0xaa, 0x06, 0x7b, 0x8e, 0x3a, 0x50, 0xa8, 0x3f, + 0xb8, 0xa9, 0x2a, 0xaf, 0x2e, 0x1b, 0x70, 0x03, 0x2d, 0x9e, 0x12, 0x45, 0x13, 0x5c, 0xa8, 0x33, + 0xa8, 0xd1, 0xff, 0x35, 0xda, 0xd1, 0xc2, 0x47, 0x75, 0x06, 0x86, 0x7d, 0x83, 0x74, 0x03, 0xb1, + 0x82, 0x01, 0x2b, 0x8f, 0x94, 0x2b, 0x41, 0xa8, 0xc2, 0x24, 0x8a, 0x04, 0x93, 0xd2, 0x99, 0xe9, + 0x5a, 0xde, 0x6c, 0xe8, 0x94, 0xc8, 0x51, 0x49, 0xf4, 0x0c, 0xf0, 0xb6, 0xd2, 0xed, 0xd7, 0x68, + 0x85, 0x42, 0x9e, 0x33, 0xaa, 0x40, 0xdc, 0x75, 0xcf, 0x56, 0xee, 0x31, 0x71, 0xdb, 0xdd, 0x43, + 0x2e, 0x13, 0x74, 0xeb, 0x05, 0xa6, 0x85, 0x54, 0x10, 0x8d, 0xee, 0x26, 0x20, 0x9d, 0xb0, 0xaa, + 0xa9, 0x5e, 0x05, 0xfd, 0x65, 0x0b, 0xe3, 0xcf, 0x22, 0x69, 0xc2, 0xa2, 0x22, 0x65, 0x98, 0xe7, + 0x8a, 0x89, 0x13, 0x92, 0x3a, 0x73, 0xba, 0x87, 0x4e, 0x4d, 0x1c, 0x1a, 0x60, 0xcf, 0xe8, 0xf6, + 0x36, 0x5a, 0xbd, 0xeb, 0x4e, 0x01, 0x06, 0x24, 0x61, 0x24, 0x72, 0xe6, 0xb5, 0x7d, 0xf9, 0xb6, + 0x7d, 0xbf, 0x06, 0xec, 0x4f, 0x68, 0xa1, 0x4f, 0xd2, 0x14, 0x14, 0x56, 0x89, 0x60, 0x32, 0x81, + 0x34, 0x72, 0xda, 0xe5, 0xa6, 0x77, 0xfc, 0xf3, 0xcb, 0xb5, 0xc6, 0xcf, 0xcb, 0xb5, 0x67, 0x31, + 0x57, 0x49, 0xd1, 0xf7, 0x29, 0x64, 0x01, 0x05, 0x99, 0x81, 0x34, 0x3f, 0x9b, 0x32, 0x1a, 0x04, + 0x6a, 0x34, 0x64, 0xd2, 0xdf, 0x65, 0x34, 0xec, 0x54, 0x39, 0x47, 0x75, 0x8c, 0x7d, 0x8c, 0x1e, + 0x67, 0x3c, 0xc7, 0xf5, 0x0c, 0xe3, 0x88, 0xa5, 0x2c, 0xd6, 0x03, 0xe6, 0x74, 0xfe, 0xe9, 0x0d, + 0x0f, 0x33, 0x9e, 0x7f, 0x30, 0x69, 0xbb, 0xe3, 0x30, 0xfb, 0x09, 0x9a, 0xe3, 0x12, 0xcb, 0x62, + 0x38, 0x04, 0xa1, 0x58, 0xe4, 0x2c, 0x74, 0x2d, 0x6f, 0x26, 0x6c, 0x71, 0x79, 0x58, 0x97, 0xca, + 0xd1, 0x8b, 0x89, 0x62, 0xa7, 0x64, 0x34, 0xee, 0xcc, 0xa2, 0xee, 0x4c, 0xdb, 0x94, 0x4d, 0x33, + 0xd6, 0xb7, 0xd1, 0xb4, 0xf9, 0x23, 0xbd, 0x42, 0x8f, 0xcc, 0x87, 0xc9, 0x88, 0x2a, 0x04, 0x57, + 0x23, 0xdc, 0x4f, 0x81, 0x0e, 0xa4, 0x1e, 0xee, 0x66, 0xb8, 0x54, 0xa9, 0xef, 0x8d, 0xb8, 0xa3, + 0xb5, 0x9d, 0xbd, 0xf3, 0x2b, 0xd7, 0xba, 0xb8, 0x72, 0xad, 0x5f, 0x57, 0xae, 0xf5, 0xed, 0xda, + 0x6d, 0x5c, 0x5c, 0xbb, 0x8d, 0x1f, 0xd7, 0x6e, 0xe3, 0x73, 0x30, 0x71, 0xc8, 0x72, 0x1c, 0x37, + 0x6f, 0x5d, 0x20, 0x67, 0x37, 0x57, 0x88, 0x3e, 0x71, 0x7f, 0x5a, 0x5f, 0x20, 0x2f, 0x7f, 0x07, + 0x00, 0x00, 0xff, 0xff, 0xf4, 0x06, 0xb1, 0x0a, 0xcb, 0x04, 0x00, 0x00, } func (m *ChainParamsList) Marshal() (dAtA []byte, err error) { @@ -360,6 +367,15 @@ func (m *ChainParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.GatewayAddress) > 0 { + i -= len(m.GatewayAddress) + copy(dAtA[i:], m.GatewayAddress) + i = encodeVarintParams(dAtA, i, uint64(len(m.GatewayAddress))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x8a + } if m.IsSupported { i-- if m.IsSupported { @@ -559,6 +575,10 @@ func (m *ChainParams) Size() (n int) { if m.IsSupported { n += 3 } + l = len(m.GatewayAddress) + if l > 0 { + n += 2 + l + sovParams(uint64(l)) + } return n } @@ -1029,6 +1049,38 @@ func (m *ChainParams) Unmarshal(dAtA []byte) error { } } m.IsSupported = bool(v != 0) + case 17: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field GatewayAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.GatewayAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipParams(dAtA[iNdEx:]) diff --git a/x/observer/types/query.pb.go b/x/observer/types/query.pb.go index 38d676df2b..6efedd0393 100644 --- a/x/observer/types/query.pb.go +++ b/x/observer/types/query.pb.go @@ -1329,7 +1329,7 @@ func (m *QuerySupportedChains) XXX_DiscardUnknown() { var xxx_messageInfo_QuerySupportedChains proto.InternalMessageInfo type QuerySupportedChainsResponse struct { - Chains []*chains.Chain `protobuf:"bytes,1,rep,name=chains,proto3" json:"chains,omitempty"` + Chains []chains.Chain `protobuf:"bytes,1,rep,name=chains,proto3" json:"chains"` } func (m *QuerySupportedChainsResponse) Reset() { *m = QuerySupportedChainsResponse{} } @@ -1365,7 +1365,7 @@ func (m *QuerySupportedChainsResponse) XXX_DiscardUnknown() { var xxx_messageInfo_QuerySupportedChainsResponse proto.InternalMessageInfo -func (m *QuerySupportedChainsResponse) GetChains() []*chains.Chain { +func (m *QuerySupportedChainsResponse) GetChains() []chains.Chain { if m != nil { return m.Chains } @@ -2301,150 +2301,150 @@ func init() { } var fileDescriptor_25b2aa420449a0c0 = []byte{ - // 2284 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x5a, 0xcf, 0x6f, 0x1b, 0xc7, - 0x15, 0xf6, 0x4a, 0x89, 0x22, 0x8d, 0x6c, 0xfd, 0x18, 0xcb, 0xb6, 0x42, 0x3b, 0xb2, 0x3c, 0x92, - 0x63, 0x59, 0x91, 0xb9, 0xb6, 0xec, 0xd4, 0xbf, 0x63, 0x8b, 0x6e, 0x24, 0xd9, 0x49, 0x6c, 0x87, - 0x74, 0x1b, 0xc0, 0x48, 0xcb, 0x2e, 0xc9, 0x21, 0xb9, 0xf5, 0x6a, 0x87, 0xd9, 0x19, 0x39, 0x61, - 0x54, 0x01, 0x45, 0x6f, 0xcd, 0xa1, 0x28, 0x50, 0xa0, 0xbd, 0x15, 0xb9, 0xf4, 0x58, 0xa0, 0x08, - 0x50, 0xb4, 0x40, 0xd1, 0x43, 0x4e, 0xcd, 0xa1, 0x87, 0x14, 0x2d, 0x8a, 0x9e, 0xda, 0xc0, 0xee, - 0x1f, 0x52, 0xec, 0xcc, 0x5b, 0x72, 0x77, 0xb9, 0xbb, 0x1c, 0xca, 0xea, 0x89, 0xdc, 0xd9, 0x79, - 0x6f, 0xbe, 0xef, 0xed, 0xcc, 0x7b, 0xdf, 0xce, 0x2c, 0x3a, 0xf3, 0x29, 0x15, 0x56, 0xb5, 0x69, - 0xd9, 0xae, 0x29, 0xff, 0x31, 0x8f, 0x9a, 0xac, 0xc2, 0xa9, 0xf7, 0x94, 0x7a, 0xe6, 0x47, 0xdb, - 0xd4, 0x6b, 0xe7, 0x5b, 0x1e, 0x13, 0x0c, 0x1f, 0xef, 0x74, 0xcc, 0x07, 0x1d, 0xf3, 0x41, 0xc7, - 0xdc, 0x72, 0x95, 0xf1, 0x2d, 0xc6, 0xcd, 0x8a, 0xc5, 0xa9, 0xb2, 0x32, 0x9f, 0x5e, 0xa8, 0x50, - 0x61, 0x5d, 0x30, 0x5b, 0x56, 0xc3, 0x76, 0x2d, 0x61, 0x33, 0x57, 0x39, 0xca, 0xcd, 0x34, 0x58, - 0x83, 0xc9, 0xbf, 0xa6, 0xff, 0x0f, 0x5a, 0x4f, 0x34, 0x18, 0x6b, 0x38, 0xd4, 0xb4, 0x5a, 0xb6, - 0x69, 0xb9, 0x2e, 0x13, 0xd2, 0x84, 0xc3, 0xdd, 0xa5, 0x2c, 0x94, 0x15, 0xcb, 0x71, 0x98, 0x80, - 0x9e, 0x99, 0x7c, 0x2a, 0x8e, 0xb5, 0x45, 0xa1, 0x63, 0x3e, 0xab, 0xa3, 0x6c, 0x2f, 0xbb, 0xcc, - 0xad, 0xd2, 0x00, 0xc2, 0x6a, 0x66, 0x7f, 0x8f, 0x71, 0xae, 0x8c, 0xea, 0x8e, 0xd5, 0xd0, 0x82, - 0xfd, 0x84, 0xb6, 0x1b, 0xd4, 0xd5, 0x41, 0xe3, 0xb2, 0x1a, 0x2d, 0x5b, 0xd5, 0x2a, 0xdb, 0x76, - 0x03, 0x9a, 0xcb, 0x59, 0xfd, 0x83, 0x3f, 0x3a, 0x28, 0x5a, 0x96, 0x67, 0x6d, 0x05, 0x78, 0xcf, - 0x67, 0xf6, 0xa4, 0x6e, 0xcd, 0x76, 0x1b, 0xd1, 0xa8, 0x9c, 0xce, 0xb2, 0x10, 0x9c, 0x67, 0xc0, - 0x6d, 0x3d, 0x69, 0xa8, 0x38, 0x73, 0xf8, 0xe9, 0xd3, 0xb7, 0xe5, 0x31, 0x56, 0xe7, 0xf0, 0x03, - 0x7d, 0x2f, 0xf5, 0x19, 0xbe, 0x5c, 0xdf, 0x76, 0x6b, 0xbc, 0xbc, 0x65, 0x37, 0x3c, 0x4b, 0x30, - 0x08, 0x08, 0x39, 0x8d, 0x16, 0xde, 0xf7, 0xe7, 0xe8, 0x23, 0xce, 0xd7, 0xfd, 0xfb, 0xef, 0xc1, - 0xed, 0xbb, 0x6e, 0x9d, 0xad, 0x39, 0x4e, 0x91, 0x7e, 0xb4, 0x4d, 0xb9, 0x20, 0x3f, 0x33, 0xd0, - 0x62, 0x76, 0x3f, 0xde, 0x62, 0x2e, 0xa7, 0xb8, 0x8e, 0x0e, 0xf7, 0x8e, 0xc5, 0x67, 0x8d, 0xf9, - 0xe1, 0xa5, 0xf1, 0xd5, 0xf3, 0xf9, 0x8c, 0x85, 0x93, 0x07, 0xd7, 0x61, 0xcf, 0x85, 0x97, 0xbe, - 0xfa, 0xf7, 0xc9, 0x03, 0xc5, 0x69, 0x11, 0x1b, 0x95, 0x93, 0x9b, 0x68, 0x3e, 0x15, 0x0f, 0x80, - 0xc6, 0xaf, 0xa2, 0x51, 0x35, 0x0f, 0xed, 0xda, 0xac, 0x31, 0x6f, 0x2c, 0x0d, 0x17, 0x5f, 0x91, - 0xd7, 0x77, 0x6b, 0xe4, 0xa7, 0x06, 0x3a, 0x95, 0x61, 0x0f, 0x64, 0x6a, 0x08, 0xf7, 0x92, 0x91, - 0xae, 0xf6, 0xce, 0x65, 0x2a, 0xce, 0x85, 0xac, 0xa2, 0x9c, 0x84, 0xb2, 0x41, 0xc5, 0x1d, 0xdf, - 0xdd, 0x7d, 0x39, 0xa9, 0x02, 0x12, 0x33, 0xe8, 0x65, 0xdb, 0xad, 0xd1, 0x4f, 0xe4, 0xb0, 0x63, - 0x45, 0x75, 0x41, 0x18, 0x3a, 0x9e, 0x68, 0x03, 0xc0, 0x1f, 0xa2, 0xf1, 0x50, 0x33, 0x20, 0x5e, - 0xca, 0x44, 0x1c, 0xea, 0x0f, 0x48, 0xc3, 0x2e, 0x48, 0x0d, 0x40, 0xae, 0x39, 0x4e, 0x02, 0xc8, - 0x75, 0x84, 0xba, 0xb9, 0x0d, 0x86, 0x7b, 0x3d, 0xaf, 0x12, 0x61, 0xde, 0x4f, 0x84, 0x79, 0x95, - 0x3e, 0x21, 0x11, 0xe6, 0x1f, 0x5a, 0x0d, 0x0a, 0xb6, 0xc5, 0x90, 0x25, 0xf9, 0xa3, 0x01, 0xbc, - 0xe2, 0xc3, 0xa4, 0xf1, 0x1a, 0x7e, 0x41, 0x5e, 0x78, 0x23, 0x82, 0x7c, 0x48, 0x22, 0x3f, 0xd3, - 0x17, 0xb9, 0x82, 0x13, 0x81, 0x5e, 0x47, 0x27, 0x02, 0xe4, 0x0f, 0x55, 0x76, 0xf8, 0xff, 0x84, - 0xe8, 0x4b, 0x03, 0xbd, 0x96, 0x32, 0x10, 0x04, 0xe9, 0x03, 0x34, 0x11, 0xcd, 0x4f, 0x10, 0xa7, - 0xe5, 0xcc, 0x38, 0x45, 0x7c, 0x41, 0xa4, 0x0e, 0xb5, 0xc2, 0x8d, 0xfb, 0x17, 0xab, 0x60, 0xf1, - 0x46, 0xc7, 0x6c, 0xcb, 0xe7, 0xa2, 0xb1, 0x78, 0x7f, 0x04, 0x6b, 0x37, 0xd9, 0x3c, 0x23, 0x0a, - 0xc6, 0x3e, 0x44, 0x81, 0xcc, 0x20, 0x1c, 0x2c, 0xbd, 0x47, 0xa5, 0x52, 0x90, 0x20, 0x1f, 0xa0, - 0xc3, 0x91, 0x56, 0x40, 0x71, 0x05, 0x0d, 0x3f, 0x2a, 0x95, 0x60, 0xe8, 0xf9, 0xec, 0x94, 0x51, - 0x2a, 0xc1, 0x80, 0xbe, 0x09, 0x79, 0x1b, 0xbd, 0xda, 0x71, 0xc8, 0xf9, 0x5a, 0xad, 0xe6, 0x51, - 0xde, 0x99, 0x4c, 0x4b, 0x68, 0xaa, 0x62, 0x8b, 0x2a, 0xb3, 0xdd, 0x72, 0x27, 0x48, 0x43, 0x32, - 0x48, 0x13, 0xd0, 0x7e, 0x07, 0x62, 0x75, 0xbb, 0x9b, 0x5c, 0xc2, 0x6e, 0x00, 0xde, 0x14, 0x1a, - 0xa6, 0xa2, 0x09, 0xa9, 0xc5, 0xff, 0xeb, 0xb7, 0x54, 0x44, 0x55, 0x3a, 0x1b, 0x2b, 0xfa, 0x7f, - 0xc9, 0x67, 0x06, 0x5a, 0xee, 0x75, 0x51, 0x68, 0xaf, 0xdb, 0xae, 0xe5, 0xd8, 0x9f, 0xd2, 0xda, - 0x26, 0xb5, 0x1b, 0x4d, 0x11, 0x40, 0x5b, 0x45, 0x47, 0xea, 0xc1, 0x9d, 0xb2, 0xcf, 0xb2, 0xdc, - 0x94, 0xf7, 0xe1, 0x21, 0x1e, 0xee, 0xdc, 0x7c, 0x4c, 0x85, 0xa5, 0x4c, 0x07, 0xa0, 0xf3, 0x3e, - 0x7a, 0x43, 0x0b, 0xcb, 0x00, 0xfc, 0x7e, 0x80, 0x8e, 0x06, 0x95, 0x60, 0xd3, 0xe6, 0x82, 0x79, - 0xed, 0xfd, 0x5e, 0xb2, 0xbf, 0x31, 0xd0, 0xb1, 0x9e, 0x21, 0x00, 0xe1, 0x1a, 0x1a, 0xf5, 0x4b, - 0x8c, 0x63, 0x73, 0x01, 0xcb, 0x54, 0x77, 0x96, 0xbc, 0x22, 0x38, 0x7f, 0xd7, 0xe6, 0x62, 0xff, - 0x96, 0x65, 0x13, 0xcd, 0x48, 0x98, 0x9b, 0x16, 0xff, 0x2e, 0x13, 0xb4, 0x16, 0xc4, 0xe1, 0x0d, - 0x34, 0xad, 0x74, 0x65, 0xd9, 0xae, 0x51, 0x57, 0xd8, 0x75, 0x9b, 0x7a, 0x10, 0xd3, 0x29, 0x75, - 0xe3, 0x6e, 0xa7, 0x1d, 0x2f, 0xa0, 0x43, 0x4f, 0x99, 0xa0, 0x5e, 0xd9, 0x52, 0x0f, 0x07, 0x42, - 0x7d, 0x50, 0x36, 0xc2, 0x03, 0x23, 0x97, 0xd0, 0x91, 0xd8, 0x48, 0x10, 0x8e, 0xe3, 0x68, 0xac, - 0x69, 0xf1, 0xb2, 0xdf, 0x59, 0x2d, 0xfb, 0xd1, 0xe2, 0x68, 0x13, 0x3a, 0x91, 0xf7, 0xd0, 0x9c, - 0xb4, 0x2a, 0xc8, 0x31, 0x0b, 0xed, 0xee, 0xa8, 0x7b, 0x41, 0x4a, 0x04, 0x1a, 0xf3, 0xfd, 0x7a, - 0x32, 0x88, 0x3d, 0xb0, 0x8d, 0x5e, 0xd8, 0xb8, 0x80, 0xc6, 0xfc, 0xeb, 0xb2, 0x68, 0xb7, 0xa8, - 0xe4, 0x35, 0xb1, 0x7a, 0x3a, 0xf3, 0x69, 0xf9, 0xfe, 0x1f, 0xb5, 0x5b, 0xb4, 0x38, 0xfa, 0x14, - 0xfe, 0x91, 0x3f, 0x0c, 0xa1, 0x93, 0xa9, 0x2c, 0x20, 0x0a, 0x03, 0x05, 0xfc, 0x2d, 0x34, 0x22, - 0x41, 0xfa, 0x91, 0x1e, 0x96, 0x33, 0xb4, 0x1f, 0x22, 0xc9, 0xb8, 0x08, 0x56, 0xf8, 0x03, 0x34, - 0xa5, 0xee, 0xca, 0x49, 0xa0, 0xb8, 0x0d, 0x4b, 0x6e, 0x2b, 0x99, 0x9e, 0x1e, 0x74, 0x8d, 0x24, - 0xc5, 0x49, 0x16, 0x6d, 0xc0, 0xf7, 0xd1, 0x21, 0x60, 0xc1, 0x85, 0x25, 0xb6, 0xf9, 0xec, 0x4b, - 0xd2, 0xeb, 0xd9, 0x4c, 0xaf, 0x2a, 0x2a, 0x25, 0x69, 0x50, 0x3c, 0x58, 0x09, 0x5d, 0x11, 0x8c, - 0xa6, 0x64, 0xe0, 0x1e, 0x40, 0xdf, 0x12, 0x15, 0xe4, 0x0a, 0x9a, 0x8d, 0xb7, 0x75, 0xa2, 0x78, - 0x02, 0x8d, 0x05, 0x6e, 0x55, 0x09, 0x1c, 0x2b, 0x76, 0x1b, 0xc8, 0x51, 0x98, 0xec, 0xa5, 0xed, - 0x56, 0x8b, 0x79, 0x82, 0xd6, 0x64, 0x8a, 0xe1, 0xe4, 0x43, 0xa8, 0xe3, 0xb1, 0xf6, 0x8e, 0xd7, - 0x1b, 0x68, 0x44, 0x49, 0x74, 0x58, 0xae, 0x8b, 0x49, 0x74, 0x5a, 0x4f, 0x1a, 0x79, 0x10, 0xf2, - 0xaa, 0x2a, 0x81, 0x0d, 0xb9, 0x85, 0x48, 0x44, 0xb7, 0x3d, 0x94, 0xaf, 0x1c, 0xeb, 0xcc, 0xd3, - 0xad, 0x7d, 0x1e, 0xe8, 0xf5, 0x34, 0x07, 0x80, 0xf2, 0x1d, 0x74, 0x50, 0x79, 0x50, 0xef, 0x34, - 0xfa, 0x0a, 0x50, 0xf9, 0x2b, 0x8e, 0x57, 0xbb, 0x17, 0xe4, 0x44, 0x4c, 0xa0, 0x42, 0x1f, 0xa8, - 0x7c, 0x6e, 0x4c, 0x8a, 0x06, 0x77, 0x01, 0xc9, 0x83, 0x44, 0x24, 0x2b, 0xba, 0x48, 0xe4, 0x54, - 0x8d, 0xa0, 0x09, 0xc9, 0xe5, 0xfb, 0xac, 0x46, 0xd7, 0xd4, 0xbb, 0x60, 0xb6, 0x5c, 0xfe, 0x61, - 0x17, 0x63, 0xc4, 0xa6, 0x1b, 0xad, 0xf0, 0x7b, 0xa5, 0x56, 0xb4, 0xc2, 0x7e, 0xc6, 0xdd, 0xee, - 0x45, 0x58, 0x29, 0x27, 0xe0, 0xdb, 0xaf, 0x9a, 0xf2, 0x45, 0x48, 0x29, 0x27, 0x51, 0xba, 0x87, - 0xc6, 0x43, 0xcd, 0x5a, 0x4a, 0x39, 0xc2, 0x28, 0x74, 0xb1, 0x7f, 0x05, 0x66, 0x1e, 0x12, 0xb8, - 0x3f, 0x55, 0x3a, 0xbb, 0x04, 0xeb, 0x8e, 0xd5, 0xe8, 0x4c, 0xa6, 0x1f, 0x1b, 0x90, 0x1d, 0x93, - 0xba, 0x00, 0xb5, 0xef, 0xa1, 0xa9, 0xf8, 0x1e, 0x83, 0xde, 0xac, 0x8a, 0xfa, 0x83, 0x32, 0x3a, - 0x59, 0x8d, 0x36, 0x93, 0x63, 0x50, 0x9b, 0x36, 0xa8, 0x78, 0x47, 0x6e, 0x4b, 0x04, 0xd8, 0xbe, - 0x03, 0x42, 0x21, 0x74, 0x03, 0x10, 0x5d, 0x47, 0x23, 0x6a, 0x07, 0x03, 0x70, 0x2c, 0x64, 0xe2, - 0x00, 0x63, 0x30, 0x21, 0x27, 0x41, 0xcf, 0x97, 0x9a, 0xec, 0xe3, 0x20, 0x8d, 0xdd, 0x09, 0x4d, - 0x19, 0x3f, 0x26, 0x73, 0x69, 0x3d, 0x00, 0xc0, 0xf7, 0xd1, 0x61, 0xc7, 0xe2, 0xa2, 0x1c, 0x8c, - 0x51, 0x0e, 0xcf, 0xe3, 0x7c, 0x26, 0x9a, 0x77, 0x2d, 0x2e, 0xa2, 0x4e, 0xa7, 0x9d, 0x78, 0x13, - 0xb9, 0x07, 0x18, 0x0b, 0x8e, 0xb5, 0x45, 0x93, 0x0a, 0xef, 0x59, 0x34, 0x25, 0x37, 0x94, 0x7a, - 0x0b, 0xd6, 0xa4, 0x6c, 0x0f, 0x95, 0xdd, 0x6a, 0x50, 0xc5, 0x7b, 0x7d, 0x75, 0x34, 0x11, 0x02, - 0x67, 0x6e, 0x9d, 0x01, 0x09, 0x92, 0x5d, 0x35, 0xfc, 0xee, 0xc5, 0x31, 0x35, 0x94, 0x5b, 0x67, - 0x84, 0x76, 0x57, 0x87, 0xba, 0x47, 0xab, 0xcc, 0xab, 0xed, 0xfb, 0xcb, 0xd8, 0xef, 0x8c, 0xee, - 0x5b, 0x5f, 0x74, 0x1c, 0xa0, 0xb2, 0x11, 0xa3, 0x32, 0xac, 0x47, 0x05, 0xe6, 0x66, 0x97, 0xd0, - 0xfe, 0xad, 0xc1, 0x12, 0xbc, 0x7b, 0x41, 0xf8, 0x65, 0xaa, 0x5d, 0x73, 0x6b, 0xf2, 0xe5, 0xa6, - 0x7f, 0xfd, 0xf1, 0xf3, 0xab, 0x7c, 0x9d, 0x02, 0x7d, 0xae, 0x2e, 0x48, 0x1d, 0xde, 0xc8, 0x92, - 0x9d, 0xa6, 0x3c, 0xd6, 0xe1, 0x81, 0x1f, 0xeb, 0xea, 0xe7, 0x8b, 0xe8, 0x65, 0x39, 0x10, 0xfe, - 0xb3, 0x81, 0x46, 0x03, 0xf5, 0x88, 0x2f, 0x64, 0x7a, 0x49, 0xd2, 0xb4, 0xb9, 0xd5, 0x41, 0x4c, - 0x14, 0x01, 0x72, 0xef, 0x27, 0x7f, 0xff, 0xef, 0x2f, 0x86, 0xbe, 0x8d, 0x0b, 0x72, 0x83, 0xed, - 0x9c, 0xda, 0x6b, 0xeb, 0x6c, 0xb1, 0x75, 0x74, 0xab, 0xb9, 0xd3, 0x23, 0xde, 0x76, 0xcd, 0x9d, - 0x88, 0xba, 0xdc, 0xc5, 0xff, 0x34, 0x10, 0xee, 0x55, 0x80, 0xf8, 0x7a, 0x7f, 0x58, 0xa9, 0xea, - 0x37, 0x77, 0x63, 0x6f, 0xc6, 0xc0, 0xee, 0x6d, 0xc9, 0xee, 0x16, 0xbe, 0x99, 0xc8, 0x0e, 0x28, - 0x55, 0xda, 0x21, 0x56, 0x49, 0x44, 0xf1, 0xaf, 0x0d, 0x34, 0x1e, 0x52, 0x63, 0xf8, 0x5c, 0x7f, - 0x50, 0xa1, 0xee, 0xb9, 0x37, 0x07, 0xea, 0xde, 0x01, 0x7f, 0x56, 0x82, 0x5f, 0xc0, 0xa7, 0x12, - 0xc1, 0x77, 0xd2, 0x22, 0xa7, 0x02, 0xff, 0xd6, 0x40, 0x93, 0x31, 0x71, 0xa7, 0x33, 0x81, 0x62, - 0x26, 0xb9, 0xab, 0x03, 0x9b, 0x74, 0xc0, 0xae, 0x48, 0xb0, 0xaf, 0xe3, 0xc5, 0x44, 0xb0, 0x3c, - 0x86, 0xed, 0x3f, 0x06, 0x3a, 0x9a, 0xac, 0xf6, 0xf0, 0xad, 0xfe, 0x18, 0x32, 0x85, 0x66, 0xee, - 0xf6, 0xde, 0x1d, 0x00, 0x97, 0x82, 0xe4, 0x72, 0x03, 0x5f, 0x4b, 0xe4, 0xd2, 0xa0, 0xa2, 0x1c, - 0x56, 0x7f, 0xe5, 0x3a, 0xf3, 0x54, 0x83, 0xb9, 0x13, 0x64, 0x98, 0x5d, 0xfc, 0x85, 0x81, 0x26, - 0xa2, 0xc3, 0xe0, 0xcb, 0x83, 0x02, 0x0b, 0x18, 0x5d, 0x19, 0xdc, 0x10, 0x98, 0x9c, 0x93, 0x4c, - 0xce, 0xe0, 0xd3, 0x5a, 0x4c, 0x7c, 0xd0, 0x11, 0x91, 0xa4, 0x87, 0xb8, 0x57, 0x11, 0x6a, 0x22, - 0x4e, 0xd0, 0x78, 0xe4, 0xbc, 0x44, 0xbc, 0x8c, 0x97, 0x12, 0x11, 0x87, 0x34, 0xa9, 0xb9, 0x23, - 0x65, 0xf0, 0xae, 0x3f, 0xf7, 0x27, 0x42, 0x9e, 0xd6, 0x1c, 0x47, 0x07, 0x77, 0xa2, 0x92, 0xd5, - 0xc1, 0x9d, 0xac, 0x4d, 0xc9, 0x92, 0xc4, 0x4d, 0xf0, 0x7c, 0x3f, 0xdc, 0xf8, 0x4f, 0x06, 0x9a, - 0x8c, 0xc9, 0x36, 0x9d, 0x14, 0x99, 0xaa, 0x2f, 0x75, 0x52, 0x64, 0xba, 0xf2, 0xec, 0x33, 0x45, - 0xe2, 0xa2, 0x14, 0xff, 0xd2, 0x40, 0x23, 0x4a, 0xec, 0xe1, 0x55, 0xad, 0x71, 0x23, 0x7a, 0x33, - 0x77, 0x71, 0x20, 0x1b, 0x80, 0xb8, 0x20, 0x21, 0xbe, 0x86, 0x8f, 0x27, 0x42, 0x54, 0x92, 0x13, - 0xff, 0xc5, 0x40, 0xd3, 0x3d, 0x62, 0x12, 0x5f, 0xd3, 0xc8, 0x68, 0x29, 0x1a, 0x35, 0x77, 0x7d, - 0x4f, 0xb6, 0x80, 0xf9, 0xaa, 0xc4, 0x7c, 0x11, 0x5f, 0x08, 0x63, 0xee, 0x3d, 0xc3, 0xe2, 0x4d, - 0xf6, 0x71, 0x4c, 0xe1, 0xe2, 0xbf, 0x19, 0x68, 0xba, 0x47, 0x48, 0xea, 0x30, 0x49, 0x53, 0xb2, - 0x3a, 0x4c, 0x52, 0x95, 0x2b, 0xb9, 0x23, 0x99, 0xdc, 0xc4, 0xd7, 0x93, 0x6b, 0xa8, 0x54, 0x3f, - 0xf1, 0x12, 0x1a, 0x93, 0xcd, 0xbb, 0xbe, 0xb4, 0xc1, 0x1b, 0x54, 0xc4, 0x24, 0x25, 0xd6, 0x5b, - 0x6f, 0x09, 0x6a, 0x57, 0xa7, 0x54, 0xa5, 0xe8, 0x57, 0xb2, 0x2a, 0x09, 0xad, 0xe0, 0xe5, 0xd4, - 0xa4, 0x68, 0x39, 0x4e, 0x59, 0x71, 0xf0, 0x00, 0xe8, 0x37, 0x06, 0x3a, 0x22, 0x9d, 0xf1, 0x98, - 0x12, 0xc4, 0x37, 0xb5, 0x63, 0x9b, 0x24, 0x4b, 0x73, 0x6f, 0xed, 0xd5, 0x1c, 0xc8, 0x6c, 0x4a, - 0x32, 0x05, 0x7c, 0x3b, 0xfb, 0xe9, 0xa8, 0x25, 0x6c, 0xb9, 0x35, 0x75, 0x70, 0x10, 0xaa, 0x54, - 0xe6, 0x8e, 0x6c, 0xd9, 0xc5, 0x5f, 0x1a, 0xe8, 0x50, 0x64, 0x0b, 0x1a, 0x7f, 0x4b, 0x6b, 0xb1, - 0xf6, 0xec, 0xe4, 0xe7, 0x2e, 0x0f, 0x6c, 0x07, 0x64, 0x6e, 0x49, 0x32, 0x57, 0xf1, 0xe5, 0xd4, - 0x27, 0x23, 0x38, 0x0f, 0xf4, 0xa6, 0xb9, 0x13, 0xdf, 0x5f, 0xdf, 0xc5, 0xbf, 0x1a, 0x42, 0x73, - 0xd9, 0xdb, 0xe8, 0x78, 0x63, 0x40, 0x70, 0x69, 0x87, 0x02, 0xb9, 0xcd, 0x17, 0x77, 0x04, 0xb4, - 0x2b, 0x92, 0xf6, 0x87, 0xf8, 0xb1, 0x0e, 0xed, 0x72, 0x53, 0xee, 0xb6, 0xdb, 0x55, 0xcb, 0x31, - 0x77, 0x12, 0x4f, 0x25, 0x76, 0x93, 0x22, 0xf3, 0x99, 0x21, 0x4f, 0x6d, 0xb0, 0xa9, 0x87, 0xba, - 0x73, 0x08, 0x94, 0x3b, 0xaf, 0x6f, 0x00, 0x74, 0xe6, 0x25, 0x9d, 0x1c, 0x9e, 0x4d, 0xa4, 0xe3, - 0x83, 0xf8, 0xdc, 0x40, 0xa8, 0x7b, 0x6e, 0x80, 0x35, 0x8a, 0x42, 0xcf, 0x41, 0x46, 0xee, 0xd2, - 0x60, 0x46, 0x80, 0xed, 0x8c, 0xc4, 0x76, 0x0a, 0x9f, 0x4c, 0xc4, 0x26, 0xba, 0x98, 0x7e, 0x6f, - 0xa0, 0xa9, 0xc8, 0xc1, 0x99, 0xaf, 0x2b, 0xf4, 0x92, 0x4e, 0xd2, 0x51, 0x69, 0xee, 0xda, 0x5e, - 0x4c, 0x01, 0xf4, 0xb2, 0x04, 0xbd, 0x88, 0x49, 0x22, 0xe8, 0xe8, 0x79, 0xe6, 0x5f, 0x0d, 0x34, - 0x93, 0x74, 0x86, 0xa8, 0x93, 0xa7, 0x32, 0x8e, 0x2e, 0x75, 0xf2, 0x54, 0xd6, 0xd1, 0x25, 0x79, - 0x53, 0x72, 0x30, 0xf1, 0xb9, 0xfe, 0x1c, 0x62, 0x32, 0x3a, 0x72, 0xb4, 0x3d, 0x80, 0x86, 0x8e, - 0xc6, 0xff, 0xca, 0xe0, 0x86, 0x5a, 0x8a, 0xb4, 0xda, 0xb5, 0x88, 0x28, 0xd2, 0x90, 0x27, 0x7d, - 0x45, 0xba, 0x37, 0xdc, 0xc9, 0xdf, 0x15, 0xf4, 0x51, 0xa4, 0x21, 0xdc, 0xbe, 0x74, 0x9a, 0x49, - 0xfa, 0x66, 0x44, 0x67, 0xce, 0x64, 0x7c, 0xab, 0xa2, 0x33, 0x67, 0xb2, 0x3e, 0x55, 0xe9, 0x13, - 0xf9, 0x86, 0x4c, 0xae, 0x11, 0x6b, 0xfc, 0x0f, 0x03, 0x1d, 0x4b, 0xf9, 0x9a, 0x07, 0xdf, 0xde, - 0x1b, 0x9a, 0xee, 0x07, 0x43, 0xb9, 0xb5, 0x17, 0xf0, 0x00, 0x94, 0x2e, 0x49, 0x4a, 0x79, 0xbc, - 0x92, 0x46, 0x69, 0xcd, 0x71, 0xe2, 0x3e, 0x78, 0xe1, 0xee, 0x57, 0xcf, 0xe6, 0x8c, 0xaf, 0x9f, - 0xcd, 0x19, 0xdf, 0x3c, 0x9b, 0x33, 0x7e, 0xfe, 0x7c, 0xee, 0xc0, 0xd7, 0xcf, 0xe7, 0x0e, 0xfc, - 0xeb, 0xf9, 0xdc, 0x81, 0xc7, 0x66, 0xc3, 0x16, 0xcd, 0xed, 0x4a, 0xbe, 0xca, 0xb6, 0x12, 0x85, - 0xe6, 0x27, 0xa1, 0xe4, 0xd6, 0x6e, 0x51, 0x5e, 0x19, 0x91, 0x9f, 0x48, 0x5d, 0xfc, 0x5f, 0x00, - 0x00, 0x00, 0xff, 0xff, 0xc1, 0xd9, 0x00, 0xc6, 0x18, 0x28, 0x00, 0x00, + // 2285 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x5a, 0xcf, 0x6f, 0xdc, 0xc6, + 0x15, 0x36, 0xa5, 0x44, 0x91, 0x9e, 0x6c, 0xfd, 0x18, 0xcb, 0xb6, 0xb2, 0x76, 0x64, 0x99, 0x92, + 0x63, 0x59, 0x91, 0x97, 0xb6, 0xec, 0xd4, 0xbf, 0xe2, 0xd8, 0x5a, 0x37, 0x92, 0xec, 0x24, 0xb6, + 0xb3, 0xeb, 0x36, 0x80, 0xd1, 0x76, 0xcb, 0xdd, 0x9d, 0xdd, 0x65, 0x4d, 0x71, 0x36, 0x9c, 0x91, + 0x93, 0x8d, 0x2a, 0xa0, 0xe8, 0xad, 0x39, 0x14, 0x05, 0x0a, 0xb4, 0xb7, 0x22, 0x97, 0x1e, 0x0b, + 0x14, 0x01, 0x8a, 0x16, 0x28, 0x7a, 0xc8, 0xa9, 0x39, 0xf4, 0x90, 0xa2, 0x45, 0xd1, 0x53, 0x6b, + 0xd8, 0xfd, 0x43, 0x0a, 0x0e, 0x1f, 0x77, 0x49, 0x2e, 0xc9, 0x9d, 0x95, 0x95, 0xd3, 0x2e, 0x87, + 0xef, 0xbd, 0xf9, 0xbe, 0xc7, 0x99, 0x37, 0x1f, 0x67, 0x08, 0x67, 0x3e, 0xa5, 0xc2, 0xac, 0x36, + 0x4d, 0xcb, 0x31, 0xe4, 0x3f, 0xe6, 0x52, 0x83, 0x55, 0x38, 0x75, 0x9f, 0x50, 0xd7, 0xf8, 0x68, + 0x9b, 0xba, 0xed, 0x7c, 0xcb, 0x65, 0x82, 0x91, 0xe3, 0x1d, 0xc3, 0x7c, 0x60, 0x98, 0x0f, 0x0c, + 0x73, 0xcb, 0x55, 0xc6, 0xb7, 0x18, 0x37, 0x2a, 0x26, 0xa7, 0xbe, 0x97, 0xf1, 0xe4, 0x42, 0x85, + 0x0a, 0xf3, 0x82, 0xd1, 0x32, 0x1b, 0x96, 0x63, 0x0a, 0x8b, 0x39, 0x7e, 0xa0, 0xdc, 0x4c, 0x83, + 0x35, 0x98, 0xfc, 0x6b, 0x78, 0xff, 0xb0, 0xf5, 0x44, 0x83, 0xb1, 0x86, 0x4d, 0x0d, 0xb3, 0x65, + 0x19, 0xa6, 0xe3, 0x30, 0x21, 0x5d, 0x38, 0xde, 0x5d, 0xca, 0x42, 0x59, 0x31, 0x6d, 0x9b, 0x09, + 0xb4, 0xcc, 0xe4, 0x53, 0xb1, 0xcd, 0x2d, 0x8a, 0x86, 0xf9, 0x2c, 0x43, 0xd9, 0x5e, 0x76, 0x98, + 0x53, 0xa5, 0x01, 0x84, 0xd5, 0x4c, 0x7b, 0x97, 0x71, 0xee, 0x3b, 0xd5, 0x6d, 0xb3, 0xa1, 0x04, + 0xfb, 0x31, 0x6d, 0x37, 0xa8, 0xa3, 0x82, 0xc6, 0x61, 0x35, 0x5a, 0x36, 0xab, 0x55, 0xb6, 0xed, + 0x04, 0x34, 0x97, 0xb3, 0xec, 0x83, 0x3f, 0x2a, 0x28, 0x5a, 0xa6, 0x6b, 0x6e, 0x05, 0x78, 0xcf, + 0x67, 0x5a, 0x52, 0xa7, 0x66, 0x39, 0x8d, 0x68, 0x56, 0x4e, 0x67, 0x79, 0x08, 0xce, 0x33, 0xe0, + 0xb6, 0x1e, 0x37, 0xfc, 0x3c, 0x73, 0xfc, 0xe9, 0x63, 0xdb, 0x72, 0x19, 0xab, 0x73, 0xfc, 0x41, + 0xdb, 0x4b, 0x7d, 0xba, 0x2f, 0xd7, 0xb7, 0x9d, 0x1a, 0x2f, 0x6f, 0x59, 0x0d, 0xd7, 0x14, 0x0c, + 0x13, 0xa2, 0x9f, 0x86, 0x85, 0x0f, 0xbc, 0x31, 0xfa, 0x90, 0xf3, 0x75, 0xef, 0xfe, 0xfb, 0x78, + 0xfb, 0x8e, 0x53, 0x67, 0x6b, 0xb6, 0x5d, 0xa4, 0x1f, 0x6d, 0x53, 0x2e, 0xf4, 0x9f, 0x6b, 0xb0, + 0x98, 0x6d, 0xc7, 0x5b, 0xcc, 0xe1, 0x94, 0xd4, 0xe1, 0x70, 0x6f, 0x5f, 0x7c, 0x56, 0x9b, 0x1f, + 0x5e, 0x1a, 0x5f, 0x3d, 0x9f, 0xcf, 0x98, 0x38, 0x79, 0x0c, 0x1d, 0x8e, 0x5c, 0x78, 0xe9, 0xab, + 0xff, 0x9c, 0x3c, 0x50, 0x9c, 0x16, 0xb1, 0x5e, 0xb9, 0x7e, 0x03, 0xe6, 0x53, 0xf1, 0x20, 0x68, + 0xf2, 0x2a, 0x8c, 0xfa, 0xe3, 0xd0, 0xaa, 0xcd, 0x6a, 0xf3, 0xda, 0xd2, 0x70, 0xf1, 0x15, 0x79, + 0x7d, 0xa7, 0xa6, 0xff, 0x4c, 0x83, 0x53, 0x19, 0xfe, 0x48, 0xa6, 0x06, 0xa4, 0x97, 0x8c, 0x0c, + 0xb5, 0x77, 0x2e, 0x53, 0x71, 0x2e, 0xfa, 0x2a, 0xe4, 0x24, 0x94, 0x0d, 0x2a, 0x6e, 0x7b, 0xe1, + 0xee, 0xc9, 0x41, 0x15, 0x90, 0x98, 0x81, 0x97, 0x2d, 0xa7, 0x46, 0x3f, 0x91, 0xdd, 0x8e, 0x15, + 0xfd, 0x0b, 0x9d, 0xc1, 0xf1, 0x44, 0x1f, 0x04, 0xfe, 0x00, 0xc6, 0x43, 0xcd, 0x88, 0x78, 0x29, + 0x13, 0x71, 0xc8, 0x1e, 0x91, 0x86, 0x43, 0xe8, 0x35, 0x04, 0xb9, 0x66, 0xdb, 0x09, 0x20, 0xd7, + 0x01, 0xba, 0xb5, 0x0d, 0xbb, 0x7b, 0x3d, 0xef, 0x17, 0xc2, 0xbc, 0x57, 0x08, 0xf3, 0x7e, 0xf9, + 0xc4, 0x42, 0x98, 0x7f, 0x60, 0x36, 0x28, 0xfa, 0x16, 0x43, 0x9e, 0xfa, 0x9f, 0x34, 0xe4, 0x15, + 0xef, 0x26, 0x8d, 0xd7, 0xf0, 0x0b, 0xf2, 0x22, 0x1b, 0x11, 0xe4, 0x43, 0x12, 0xf9, 0x99, 0xbe, + 0xc8, 0x7d, 0x38, 0x11, 0xe8, 0x75, 0x38, 0x11, 0x20, 0x7f, 0xe0, 0x57, 0x87, 0x6f, 0x26, 0x45, + 0x5f, 0x6a, 0xf0, 0x5a, 0x4a, 0x47, 0x98, 0xa4, 0x0f, 0x61, 0x22, 0x5a, 0x9f, 0x30, 0x4f, 0xcb, + 0x99, 0x79, 0x8a, 0xc4, 0xc2, 0x4c, 0x1d, 0x6a, 0x85, 0x1b, 0xf7, 0x2f, 0x57, 0xc1, 0xe4, 0x8d, + 0xf6, 0xd9, 0x96, 0xcf, 0x45, 0x61, 0xf2, 0xfe, 0x18, 0xe7, 0x6e, 0xb2, 0x7b, 0x46, 0x16, 0xb4, + 0x7d, 0xc8, 0x82, 0x3e, 0x03, 0x24, 0x98, 0x7a, 0x0f, 0x4b, 0xa5, 0xa0, 0x40, 0xde, 0x87, 0xc3, + 0x91, 0x56, 0x44, 0x71, 0x05, 0x86, 0x1f, 0x96, 0x4a, 0xd8, 0xf5, 0x7c, 0x76, 0xc9, 0x28, 0x95, + 0xb0, 0x43, 0xcf, 0x45, 0x7f, 0x07, 0x5e, 0xed, 0x04, 0xe4, 0x7c, 0xad, 0x56, 0x73, 0x29, 0xef, + 0x0c, 0xa6, 0x25, 0x98, 0xaa, 0x58, 0xa2, 0xca, 0x2c, 0xa7, 0xdc, 0x49, 0xd2, 0x90, 0x4c, 0xd2, + 0x04, 0xb6, 0xdf, 0xc6, 0x5c, 0xdd, 0xea, 0x16, 0x97, 0x70, 0x18, 0x84, 0x37, 0x05, 0xc3, 0x54, + 0x34, 0xb1, 0xb4, 0x78, 0x7f, 0xbd, 0x96, 0x8a, 0xa8, 0xca, 0x60, 0x63, 0x45, 0xef, 0xaf, 0xfe, + 0x99, 0x06, 0xcb, 0xbd, 0x21, 0x0a, 0xed, 0x75, 0xcb, 0x31, 0x6d, 0xeb, 0x53, 0x5a, 0xdb, 0xa4, + 0x56, 0xa3, 0x29, 0x02, 0x68, 0xab, 0x70, 0xa4, 0x1e, 0xdc, 0x29, 0x7b, 0x2c, 0xcb, 0x4d, 0x79, + 0x1f, 0x1f, 0xe2, 0xe1, 0xce, 0xcd, 0x47, 0x54, 0x98, 0xbe, 0xeb, 0x00, 0x74, 0x3e, 0x80, 0x37, + 0x94, 0xb0, 0x0c, 0xc0, 0xef, 0x87, 0x70, 0x34, 0x58, 0x09, 0x36, 0x2d, 0x2e, 0x98, 0xdb, 0xde, + 0xef, 0x29, 0xfb, 0x5b, 0x0d, 0x8e, 0xf5, 0x74, 0x81, 0x08, 0xd7, 0x60, 0xd4, 0x5b, 0x62, 0x6c, + 0x8b, 0x0b, 0x9c, 0xa6, 0xaa, 0xa3, 0xe4, 0x15, 0xc1, 0xf9, 0x7b, 0x16, 0x17, 0xfb, 0x37, 0x2d, + 0x9b, 0x30, 0x23, 0x61, 0x6e, 0x9a, 0xfc, 0xbb, 0x4c, 0xd0, 0x5a, 0x90, 0x87, 0x37, 0x60, 0xda, + 0xd7, 0x95, 0x65, 0xab, 0x46, 0x1d, 0x61, 0xd5, 0x2d, 0xea, 0x62, 0x4e, 0xa7, 0xfc, 0x1b, 0x77, + 0x3a, 0xed, 0x64, 0x01, 0x0e, 0x3d, 0x61, 0x82, 0xba, 0x65, 0xd3, 0x7f, 0x38, 0x98, 0xea, 0x83, + 0xb2, 0x11, 0x1f, 0x98, 0x7e, 0x09, 0x8e, 0xc4, 0x7a, 0xc2, 0x74, 0x1c, 0x87, 0xb1, 0xa6, 0xc9, + 0xcb, 0x9e, 0xb1, 0x3f, 0xed, 0x47, 0x8b, 0xa3, 0x4d, 0x34, 0xd2, 0xdf, 0x87, 0x39, 0xe9, 0x55, + 0x90, 0x7d, 0x16, 0xda, 0xdd, 0x5e, 0xf7, 0x82, 0x54, 0x17, 0x30, 0xe6, 0xc5, 0x75, 0x65, 0x12, + 0x7b, 0x60, 0x6b, 0xbd, 0xb0, 0x49, 0x01, 0xc6, 0xbc, 0xeb, 0xb2, 0x68, 0xb7, 0xa8, 0xe4, 0x35, + 0xb1, 0x7a, 0x3a, 0xf3, 0x69, 0x79, 0xf1, 0x1f, 0xb6, 0x5b, 0xb4, 0x38, 0xfa, 0x04, 0xff, 0xe9, + 0x7f, 0x1c, 0x82, 0x93, 0xa9, 0x2c, 0x30, 0x0b, 0x03, 0x25, 0xfc, 0x6d, 0x18, 0x91, 0x20, 0xbd, + 0x4c, 0x0f, 0xcb, 0x11, 0xda, 0x0f, 0x91, 0x64, 0x5c, 0x44, 0x2f, 0xf2, 0x21, 0x4c, 0xf9, 0x77, + 0xe5, 0x20, 0xf0, 0xb9, 0x0d, 0x4b, 0x6e, 0x2b, 0x99, 0x91, 0xee, 0x77, 0x9d, 0x24, 0xc5, 0x49, + 0x16, 0x6d, 0x20, 0xf7, 0xe0, 0x10, 0xb2, 0xe0, 0xc2, 0x14, 0xdb, 0x7c, 0xf6, 0x25, 0x19, 0xf5, + 0x6c, 0x66, 0x54, 0x3f, 0x2b, 0x25, 0xe9, 0x50, 0x3c, 0x58, 0x09, 0x5d, 0xe9, 0x04, 0xa6, 0x64, + 0xe2, 0xee, 0xa3, 0x6d, 0x89, 0x0a, 0xfd, 0x0a, 0xcc, 0xc6, 0xdb, 0x3a, 0x59, 0x3c, 0x01, 0x63, + 0x41, 0x58, 0x7f, 0x09, 0x1c, 0x2b, 0x76, 0x1b, 0xf4, 0xa3, 0x38, 0xd8, 0x4b, 0xdb, 0xad, 0x16, + 0x73, 0x05, 0xad, 0xc9, 0x12, 0xc3, 0xf5, 0x0a, 0xae, 0xe3, 0xb1, 0xf6, 0x4e, 0xd4, 0x02, 0x8c, + 0xf8, 0x12, 0x1d, 0xa7, 0xeb, 0x62, 0x12, 0x9d, 0xd6, 0xe3, 0x46, 0x1e, 0x85, 0xbc, 0x74, 0xc7, + 0x29, 0x8b, 0x9e, 0xfa, 0x4d, 0xd0, 0x23, 0xea, 0xed, 0x81, 0x7c, 0xf1, 0x58, 0x67, 0xae, 0xea, + 0x0a, 0xe8, 0xa2, 0x6a, 0x4f, 0x0b, 0x80, 0x58, 0xdf, 0x85, 0x83, 0x7e, 0x04, 0xff, 0xcd, 0x46, + 0x5d, 0x07, 0xfa, 0xf1, 0x8a, 0xe3, 0xd5, 0xee, 0x85, 0x7e, 0x22, 0x26, 0x53, 0xd1, 0x06, 0xd7, + 0x3f, 0x27, 0x26, 0x48, 0x83, 0xbb, 0x88, 0xe4, 0x7e, 0x22, 0x92, 0x15, 0x55, 0x24, 0x72, 0xc0, + 0x46, 0xd0, 0x84, 0x44, 0xf3, 0x3d, 0x56, 0xa3, 0x6b, 0xfe, 0x1b, 0x61, 0xb6, 0x68, 0xfe, 0x51, + 0x17, 0x63, 0xc4, 0xa7, 0x9b, 0xad, 0xf0, 0xdb, 0xa5, 0x52, 0xb6, 0xc2, 0x71, 0xc6, 0x9d, 0xee, + 0x45, 0x58, 0x2f, 0x27, 0xe0, 0xdb, 0xaf, 0x95, 0xe5, 0x8b, 0x90, 0x5e, 0x4e, 0xa2, 0x74, 0x17, + 0xc6, 0x43, 0xcd, 0x4a, 0x7a, 0x39, 0xc2, 0x28, 0x74, 0xb1, 0x7f, 0xcb, 0xcc, 0x3c, 0x96, 0x71, + 0x6f, 0xa8, 0x74, 0xf6, 0x0a, 0xd6, 0x6d, 0xb3, 0xd1, 0x19, 0x4c, 0x3f, 0xd1, 0xb0, 0x46, 0x26, + 0x99, 0x20, 0xb5, 0xef, 0xc3, 0x54, 0x7c, 0xa7, 0x41, 0x6d, 0x54, 0x45, 0xe3, 0xe1, 0xcc, 0x9c, + 0xac, 0x46, 0x9b, 0xf5, 0x63, 0xb8, 0x42, 0x6d, 0x50, 0xf1, 0xae, 0xdc, 0x9c, 0x08, 0xb0, 0x7d, + 0x07, 0xe5, 0x42, 0xe8, 0x06, 0x22, 0xba, 0x0e, 0x23, 0xfe, 0x3e, 0x06, 0xe2, 0x58, 0xc8, 0xc4, + 0x81, 0xce, 0xe8, 0xa2, 0x9f, 0x44, 0x55, 0x5f, 0x6a, 0xb2, 0x8f, 0x83, 0x62, 0x76, 0x3b, 0x34, + 0x64, 0xbc, 0x9c, 0xcc, 0xa5, 0x59, 0x20, 0x80, 0x1f, 0xc0, 0x61, 0xdb, 0xe4, 0xa2, 0x1c, 0xf4, + 0x51, 0x0e, 0x8f, 0xe3, 0x7c, 0x26, 0x9a, 0xf7, 0x4c, 0x2e, 0xa2, 0x41, 0xa7, 0xed, 0x78, 0x93, + 0x7e, 0x17, 0x31, 0x16, 0x6c, 0x73, 0x8b, 0x26, 0x2d, 0xbf, 0x67, 0x61, 0x4a, 0x6e, 0x2b, 0xf5, + 0x2e, 0x5b, 0x93, 0xb2, 0x3d, 0xb4, 0xf8, 0x56, 0x83, 0xb5, 0xbc, 0x37, 0x56, 0x47, 0x19, 0x01, + 0x06, 0x73, 0xea, 0x0c, 0x49, 0xe8, 0xd9, 0x6b, 0x87, 0x67, 0x5e, 0x1c, 0xf3, 0xbb, 0x72, 0xea, + 0x4c, 0xa7, 0xdd, 0xd9, 0xe1, 0xdf, 0xa3, 0x55, 0xe6, 0xd6, 0xf6, 0xfd, 0x95, 0xec, 0xf7, 0x5a, + 0xf7, 0xdd, 0x2f, 0xda, 0x0f, 0x52, 0xd9, 0x88, 0x51, 0x19, 0x56, 0xa3, 0x82, 0x63, 0xb3, 0x4b, + 0x68, 0xff, 0xe6, 0x60, 0x09, 0xdf, 0xc0, 0x30, 0xfd, 0xb2, 0xd4, 0xae, 0x39, 0x35, 0xf9, 0x8a, + 0xd3, 0x7f, 0xfd, 0xf1, 0xea, 0xab, 0x7c, 0xa9, 0x42, 0x95, 0xee, 0x5f, 0xe8, 0x75, 0x7c, 0x2f, + 0x4b, 0x0e, 0x9a, 0xf2, 0x58, 0x87, 0x07, 0x7e, 0xac, 0xab, 0x9f, 0x2f, 0xc2, 0xcb, 0xb2, 0x23, + 0xf2, 0x17, 0x0d, 0x46, 0x03, 0x0d, 0x49, 0x2e, 0x64, 0x46, 0x49, 0x52, 0xb6, 0xb9, 0xd5, 0x41, + 0x5c, 0x7c, 0x02, 0xfa, 0xdd, 0x9f, 0xfe, 0xe3, 0x7f, 0xbf, 0x1c, 0xfa, 0x36, 0x29, 0xc8, 0x6d, + 0xb6, 0x73, 0xfe, 0x8e, 0x5b, 0x67, 0xa3, 0xad, 0xa3, 0x5e, 0x8d, 0x9d, 0x1e, 0x09, 0xb7, 0x6b, + 0xec, 0x44, 0x34, 0xe6, 0x2e, 0xf9, 0x97, 0x06, 0xa4, 0x57, 0x07, 0x92, 0xeb, 0xfd, 0x61, 0xa5, + 0x6a, 0xe0, 0xdc, 0x5b, 0x7b, 0x73, 0x46, 0x76, 0xef, 0x48, 0x76, 0x37, 0xc9, 0x8d, 0x44, 0x76, + 0x48, 0xa9, 0xd2, 0x0e, 0xb1, 0x4a, 0x22, 0x4a, 0x7e, 0xa3, 0xc1, 0x78, 0x48, 0x93, 0x91, 0x73, + 0xfd, 0x41, 0x85, 0xcc, 0x73, 0x6f, 0x0e, 0x64, 0xde, 0x01, 0x7f, 0x56, 0x82, 0x5f, 0x20, 0xa7, + 0x12, 0xc1, 0x77, 0xca, 0x22, 0xa7, 0x82, 0xfc, 0x4e, 0x83, 0xc9, 0x98, 0xc4, 0x53, 0x19, 0x40, + 0x31, 0x97, 0xdc, 0xd5, 0x81, 0x5d, 0x3a, 0x60, 0x57, 0x24, 0xd8, 0xd7, 0xc9, 0x62, 0x22, 0x58, + 0x1e, 0xc3, 0xf6, 0x5f, 0x0d, 0x8e, 0x26, 0xab, 0x3d, 0x72, 0xb3, 0x3f, 0x86, 0x4c, 0xa1, 0x99, + 0xbb, 0xb5, 0xf7, 0x00, 0xc8, 0xa5, 0x20, 0xb9, 0xbc, 0x45, 0xae, 0x25, 0x72, 0x69, 0x50, 0x51, + 0x0e, 0xab, 0xbf, 0x72, 0x9d, 0xb9, 0x7e, 0x83, 0xb1, 0x13, 0x54, 0x98, 0x5d, 0xf2, 0x85, 0x06, + 0x13, 0xd1, 0x6e, 0xc8, 0xe5, 0x41, 0x81, 0x05, 0x8c, 0xae, 0x0c, 0xee, 0x88, 0x4c, 0xce, 0x49, + 0x26, 0x67, 0xc8, 0x69, 0x25, 0x26, 0x1e, 0xe8, 0x88, 0x48, 0x52, 0x43, 0xdc, 0xab, 0x08, 0x15, + 0x11, 0x27, 0x68, 0x3c, 0xfd, 0xbc, 0x44, 0xbc, 0x4c, 0x96, 0x12, 0x11, 0x87, 0x34, 0xa9, 0xb1, + 0x23, 0x65, 0xf0, 0xae, 0x37, 0xf6, 0x27, 0x42, 0x91, 0xd6, 0x6c, 0x5b, 0x05, 0x77, 0xa2, 0x92, + 0x55, 0xc1, 0x9d, 0xac, 0x4d, 0xf5, 0x25, 0x89, 0x5b, 0x27, 0xf3, 0xfd, 0x70, 0x93, 0x3f, 0x6b, + 0x30, 0x19, 0x93, 0x6d, 0x2a, 0x25, 0x32, 0x55, 0x5f, 0xaa, 0x94, 0xc8, 0x74, 0xe5, 0xd9, 0x67, + 0x88, 0xc4, 0x45, 0x29, 0xf9, 0x95, 0x06, 0x23, 0xbe, 0xd8, 0x23, 0xab, 0x4a, 0xfd, 0x46, 0xf4, + 0x66, 0xee, 0xe2, 0x40, 0x3e, 0x08, 0x71, 0x41, 0x42, 0x7c, 0x8d, 0x1c, 0x4f, 0x84, 0xe8, 0x4b, + 0x4e, 0xf2, 0x57, 0x0d, 0xa6, 0x7b, 0xc4, 0x24, 0xb9, 0xa6, 0x50, 0xd1, 0x52, 0x34, 0x6a, 0xee, + 0xfa, 0x9e, 0x7c, 0x11, 0xf3, 0x55, 0x89, 0xf9, 0x22, 0xb9, 0x10, 0xc6, 0xdc, 0x7b, 0x92, 0xc5, + 0x9b, 0xec, 0xe3, 0x98, 0xc2, 0x25, 0x7f, 0xd7, 0x60, 0xba, 0x47, 0x48, 0xaa, 0x30, 0x49, 0x53, + 0xb2, 0x2a, 0x4c, 0x52, 0x95, 0xab, 0x7e, 0x5b, 0x32, 0xb9, 0x41, 0xae, 0x27, 0xaf, 0xa1, 0x52, + 0xfd, 0xc4, 0x97, 0xd0, 0x98, 0x6c, 0xde, 0xf5, 0xa4, 0x0d, 0xd9, 0xa0, 0x22, 0x26, 0x29, 0x89, + 0xda, 0x7c, 0x4b, 0x50, 0xbb, 0x2a, 0x4b, 0x55, 0x8a, 0x7e, 0xd5, 0x57, 0x25, 0xa1, 0x15, 0xb2, + 0x9c, 0x5a, 0x14, 0x4d, 0xdb, 0x2e, 0xfb, 0x1c, 0x5c, 0x04, 0xfa, 0x54, 0x83, 0x23, 0x32, 0x18, + 0x8f, 0x29, 0x41, 0x72, 0x43, 0x39, 0xb7, 0x49, 0xb2, 0x34, 0xf7, 0xf6, 0x5e, 0xdd, 0x91, 0xcc, + 0xa6, 0x24, 0x53, 0x20, 0xb7, 0xb2, 0x9f, 0x8e, 0x3f, 0x85, 0x4d, 0xa7, 0xe6, 0x1f, 0x1f, 0x84, + 0x56, 0x2a, 0x63, 0x47, 0xb6, 0xec, 0x92, 0x2f, 0x35, 0x38, 0x14, 0xd9, 0x88, 0x26, 0xdf, 0x52, + 0x9a, 0xac, 0x3d, 0xfb, 0xf9, 0xb9, 0xcb, 0x03, 0xfb, 0x21, 0x99, 0x9b, 0x92, 0xcc, 0x55, 0x72, + 0x39, 0xf5, 0xc9, 0x08, 0xce, 0x03, 0xbd, 0x69, 0xec, 0xc4, 0x77, 0xd9, 0x77, 0xc9, 0xaf, 0x87, + 0x60, 0x2e, 0x7b, 0x33, 0x9d, 0x6c, 0x0c, 0x08, 0x2e, 0xed, 0x68, 0x20, 0xb7, 0xf9, 0xe2, 0x81, + 0x90, 0x76, 0x45, 0xd2, 0xfe, 0x1e, 0x79, 0xa4, 0x42, 0xbb, 0xdc, 0x94, 0x7b, 0xee, 0x56, 0xd5, + 0xb4, 0x8d, 0x9d, 0xc4, 0xb3, 0x89, 0xdd, 0xa4, 0xcc, 0x7c, 0xa6, 0xc9, 0xb3, 0x1b, 0x62, 0xa8, + 0xa1, 0xee, 0x1c, 0x05, 0xe5, 0xce, 0xab, 0x3b, 0x20, 0x9d, 0x79, 0x49, 0x27, 0x47, 0x66, 0x13, + 0xe9, 0x78, 0x20, 0x3e, 0xd7, 0x00, 0xba, 0xa7, 0x07, 0x44, 0x61, 0x51, 0xe8, 0x39, 0xce, 0xc8, + 0x5d, 0x1a, 0xcc, 0x09, 0xb1, 0x9d, 0x91, 0xd8, 0x4e, 0x91, 0x93, 0x89, 0xd8, 0x44, 0x17, 0xd3, + 0x1f, 0x34, 0x98, 0x8a, 0x1c, 0x9f, 0x79, 0xba, 0x42, 0xad, 0xe8, 0x24, 0x1d, 0x98, 0xe6, 0xae, + 0xed, 0xc5, 0x15, 0x41, 0x2f, 0x4b, 0xd0, 0x8b, 0x44, 0x4f, 0x04, 0x1d, 0x3d, 0xd5, 0xfc, 0x9b, + 0x06, 0x33, 0x49, 0x27, 0x89, 0x2a, 0x75, 0x2a, 0xe3, 0x00, 0x53, 0xa5, 0x4e, 0x65, 0x1d, 0x60, + 0xea, 0x6f, 0x4a, 0x0e, 0x06, 0x39, 0xd7, 0x9f, 0x43, 0x4c, 0x46, 0x47, 0x0e, 0xb8, 0x07, 0xd0, + 0xd0, 0xd1, 0xfc, 0x5f, 0x19, 0xdc, 0x51, 0x49, 0x91, 0x56, 0xbb, 0x1e, 0x11, 0x45, 0x1a, 0x8a, + 0xa4, 0xae, 0x48, 0xf7, 0x86, 0x3b, 0xf9, 0xeb, 0x82, 0x3e, 0x8a, 0x34, 0x84, 0xdb, 0x93, 0x4e, + 0x33, 0x49, 0x5f, 0x8e, 0xa8, 0x8c, 0x99, 0x8c, 0x2f, 0x56, 0x54, 0xc6, 0x4c, 0xd6, 0x07, 0x2b, + 0x7d, 0x32, 0xdf, 0x90, 0xc5, 0x35, 0xe2, 0x4d, 0xfe, 0xa9, 0xc1, 0xb1, 0x94, 0x6f, 0x7a, 0xc8, + 0xad, 0xbd, 0xa1, 0xe9, 0x7e, 0x36, 0x94, 0x5b, 0x7b, 0x81, 0x08, 0x48, 0xe9, 0x92, 0xa4, 0x94, + 0x27, 0x2b, 0x69, 0x94, 0xd6, 0x6c, 0x3b, 0x1e, 0x83, 0x17, 0xee, 0x7c, 0xf5, 0x6c, 0x4e, 0xfb, + 0xfa, 0xd9, 0x9c, 0xf6, 0xf4, 0xd9, 0x9c, 0xf6, 0x8b, 0xe7, 0x73, 0x07, 0xbe, 0x7e, 0x3e, 0x77, + 0xe0, 0xdf, 0xcf, 0xe7, 0x0e, 0x3c, 0x32, 0x1a, 0x96, 0x68, 0x6e, 0x57, 0xf2, 0x55, 0xb6, 0x95, + 0x28, 0x34, 0x3f, 0x09, 0x15, 0xb7, 0x76, 0x8b, 0xf2, 0xca, 0x88, 0xfc, 0x50, 0xea, 0xe2, 0xff, + 0x03, 0x00, 0x00, 0xff, 0xff, 0x7d, 0x2a, 0xd9, 0xa1, 0x1e, 0x28, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -8220,7 +8220,7 @@ func (m *QuerySupportedChainsResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Chains = append(m.Chains, &chains.Chain{}) + m.Chains = append(m.Chains, chains.Chain{}) if err := m.Chains[len(m.Chains)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } diff --git a/zetaclient/chains/evm/observer/inbound.go b/zetaclient/chains/evm/observer/inbound.go index ce7924f150..180b6f161b 100644 --- a/zetaclient/chains/evm/observer/inbound.go +++ b/zetaclient/chains/evm/observer/inbound.go @@ -642,8 +642,11 @@ func (ob *Observer) BuildInboundVoteMsgForDepositedEvent( func (ob *Observer) BuildInboundVoteMsgForZetaSentEvent( event *zetaconnector.ZetaConnectorNonEthZetaSent, ) *types.MsgVoteInbound { - destChain := chains.GetChainFromChainID(event.DestinationChainId.Int64()) - if destChain == nil { + destChain, found := chains.GetChainFromChainID( + event.DestinationChainId.Int64(), + ob.AppContext().GetAdditionalChains(), + ) + if !found { ob.Logger().Inbound.Warn().Msgf("chain id not supported %d", event.DestinationChainId.Int64()) return nil } @@ -667,7 +670,7 @@ func (ob *Observer) BuildInboundVoteMsgForZetaSentEvent( if strings.EqualFold(destAddr, paramsDest.ZetaTokenContractAddress) { ob.Logger().Inbound.Warn(). - Msgf("potential attack attempt: %s destination address is ZETA token contract address %s", destChain, destAddr) + Msgf("potential attack attempt: %s destination address is ZETA token contract address %s", destChain.String(), destAddr) return nil } } diff --git a/zetaclient/chains/evm/observer/observer_test.go b/zetaclient/chains/evm/observer/observer_test.go index 2e7cdd5434..8daca344c8 100644 --- a/zetaclient/chains/evm/observer/observer_test.go +++ b/zetaclient/chains/evm/observer/observer_test.go @@ -64,6 +64,7 @@ func getAppContext( newChainParams, &chaincfg.RegressionNetParams, *sample.CrosschainFlags(), + []chains.Chain{}, sample.HeaderSupportedChains(), zerolog.Logger{}, ) diff --git a/zetaclient/chains/evm/signer/outbound_data.go b/zetaclient/chains/evm/signer/outbound_data.go index 070c73597e..3e84fa83db 100644 --- a/zetaclient/chains/evm/signer/outbound_data.go +++ b/zetaclient/chains/evm/signer/outbound_data.go @@ -16,6 +16,7 @@ import ( "github.com/zeta-chain/zetacore/x/crosschain/types" "github.com/zeta-chain/zetacore/zetaclient/chains/evm/observer" "github.com/zeta-chain/zetacore/zetaclient/chains/interfaces" + clientcontext "github.com/zeta-chain/zetacore/zetaclient/context" ) const ( @@ -69,7 +70,7 @@ func (txData *OutboundData) SetupGas( cctx *types.CrossChainTx, logger zerolog.Logger, client interfaces.EVMRPCClient, - chain *chains.Chain, + chain chains.Chain, ) error { txData.gasLimit = cctx.GetCurrentOutboundParam().GasLimit if txData.gasLimit < MinGasLimit { @@ -89,10 +90,10 @@ func (txData *OutboundData) SetupGas( // we should possibly remove it completely and return an error if no GasPrice is provided because it means no fee is processed on ZetaChain specified, ok := new(big.Int).SetString(cctx.GetCurrentOutboundParam().GasPrice, 10) if !ok { - if chains.IsEthereumChain(chain.ChainId) { + if chain.Network == chains.Network_eth { suggested, err := client.SuggestGasPrice(context.Background()) if err != nil { - return errors.Join(err, fmt.Errorf("cannot get gas price from chain %s ", chain)) + return errors.Join(err, fmt.Errorf("cannot get gas price from chain %s ", chain.String())) } txData.gasPrice = roundUpToNearestGwei(suggested) } else { @@ -111,6 +112,7 @@ func (txData *OutboundData) SetupGas( // cctx will be skipped and false otherwise. // 3. error func NewOutboundData( + appontext *clientcontext.AppContext, cctx *types.CrossChainTx, evmObserver *observer.Observer, evmRPC interfaces.EVMRPCClient, @@ -132,8 +134,8 @@ func NewOutboundData( return nil, true, nil } - toChain := chains.GetChainFromChainID(txData.toChainID.Int64()) - if toChain == nil { + toChain, found := chains.GetChainFromChainID(txData.toChainID.Int64(), appontext.GetAdditionalChains()) + if !found { return nil, true, fmt.Errorf("unknown chain: %d", txData.toChainID.Int64()) } @@ -156,7 +158,7 @@ func NewOutboundData( // Get sendHash logger.Info(). - Msgf("chain %s minting %d to %s, nonce %d, finalized zeta bn %d", toChain, cctx.InboundParams.Amount, txData.to.Hex(), nonce, cctx.InboundParams.FinalizedZetaHeight) + Msgf("chain %s minting %d to %s, nonce %d, finalized zeta bn %d", toChain.String(), cctx.InboundParams.Amount, txData.to.Hex(), nonce, cctx.InboundParams.FinalizedZetaHeight) cctxIndex, err := hex.DecodeString(cctx.Index[2:]) // remove the leading 0x if err != nil || len(cctxIndex) != 32 { return nil, true, fmt.Errorf("decode CCTX %s error", cctx.Index) diff --git a/zetaclient/chains/evm/signer/outbound_data_test.go b/zetaclient/chains/evm/signer/outbound_data_test.go index d7df5a33d1..f5e3d39d3b 100644 --- a/zetaclient/chains/evm/signer/outbound_data_test.go +++ b/zetaclient/chains/evm/signer/outbound_data_test.go @@ -53,14 +53,14 @@ func TestSigner_SetupGas(t *testing.T) { t.Run("SetupGas_success", func(t *testing.T) { chain := chains.BscMainnet - err := txData.SetupGas(cctx, logger, evmSigner.EvmClient(), &chain) + err := txData.SetupGas(cctx, logger, evmSigner.EvmClient(), chain) require.NoError(t, err) }) t.Run("SetupGas_error", func(t *testing.T) { cctx.GetCurrentOutboundParam().GasPrice = "invalidGasPrice" chain := chains.BscMainnet - err := txData.SetupGas(cctx, logger, evmSigner.EvmClient(), &chain) + err := txData.SetupGas(cctx, logger, evmSigner.EvmClient(), chain) require.ErrorContains(t, err, "cannot convert gas price") }) } @@ -75,7 +75,14 @@ func TestSigner_NewOutboundData(t *testing.T) { t.Run("NewOutboundData success", func(t *testing.T) { cctx := getCCTX(t) - _, skip, err := NewOutboundData(cctx, mockObserver, evmSigner.EvmClient(), zerolog.Logger{}, 123) + _, skip, err := NewOutboundData( + evmSigner.AppContext(), + cctx, + mockObserver, + evmSigner.EvmClient(), + zerolog.Logger{}, + 123, + ) require.False(t, skip) require.NoError(t, err) }) @@ -83,7 +90,14 @@ func TestSigner_NewOutboundData(t *testing.T) { t.Run("NewOutboundData skip", func(t *testing.T) { cctx := getCCTX(t) cctx.CctxStatus.Status = types.CctxStatus_Aborted - _, skip, err := NewOutboundData(cctx, mockObserver, evmSigner.EvmClient(), zerolog.Logger{}, 123) + _, skip, err := NewOutboundData( + evmSigner.AppContext(), + cctx, + mockObserver, + evmSigner.EvmClient(), + zerolog.Logger{}, + 123, + ) require.NoError(t, err) require.True(t, skip) }) @@ -91,7 +105,14 @@ func TestSigner_NewOutboundData(t *testing.T) { t.Run("NewOutboundData unknown chain", func(t *testing.T) { cctx := getInvalidCCTX(t) require.NoError(t, err) - _, skip, err := NewOutboundData(cctx, mockObserver, evmSigner.EvmClient(), zerolog.Logger{}, 123) + _, skip, err := NewOutboundData( + evmSigner.AppContext(), + cctx, + mockObserver, + evmSigner.EvmClient(), + zerolog.Logger{}, + 123, + ) require.ErrorContains(t, err, "unknown chain") require.True(t, skip) }) @@ -100,7 +121,14 @@ func TestSigner_NewOutboundData(t *testing.T) { cctx := getCCTX(t) require.NoError(t, err) cctx.GetCurrentOutboundParam().GasPrice = "invalidGasPrice" - _, skip, err := NewOutboundData(cctx, mockObserver, evmSigner.EvmClient(), zerolog.Logger{}, 123) + _, skip, err := NewOutboundData( + evmSigner.AppContext(), + cctx, + mockObserver, + evmSigner.EvmClient(), + zerolog.Logger{}, + 123, + ) require.True(t, skip) require.ErrorContains(t, err, "cannot convert gas price") }) diff --git a/zetaclient/chains/evm/signer/signer.go b/zetaclient/chains/evm/signer/signer.go index 873d865fb9..e90af35366 100644 --- a/zetaclient/chains/evm/signer/signer.go +++ b/zetaclient/chains/evm/signer/signer.go @@ -364,7 +364,7 @@ func (signer *Signer) TryProcessOutbound( } // Setup Transaction input - txData, skipTx, err := NewOutboundData(cctx, evmObserver, signer.client, logger, height) + txData, skipTx, err := NewOutboundData(signer.AppContext(), cctx, evmObserver, signer.client, logger, height) if err != nil { logger.Err(err).Msg("error setting up transaction input fields") return @@ -373,8 +373,14 @@ func (signer *Signer) TryProcessOutbound( return } - // Get destination chain for logging - toChain := chains.GetChainFromChainID(txData.toChainID.Int64()) + toChain, found := chains.GetChainFromChainID( + txData.toChainID.Int64(), + signer.AppContext().GetAdditionalChains(), + ) + if !found { + logger.Warn().Msgf("unknown chain: %d", txData.toChainID.Int64()) + return + } // Get cross-chain flags crossChainflags := signer.AppContext().GetCrossChainFlags() @@ -426,7 +432,7 @@ func (signer *Signer) TryProcessOutbound( logger.Info().Msgf( "SignWithdrawTx: %d => %s, nonce %d, gasPrice %d", cctx.InboundParams.SenderChainId, - toChain, + toChain.String(), cctx.GetCurrentOutboundParam().TssNonce, txData.gasPrice, ) @@ -435,7 +441,7 @@ func (signer *Signer) TryProcessOutbound( logger.Info().Msgf( "SignERC20WithdrawTx: %d => %s, nonce %d, gasPrice %d", cctx.InboundParams.SenderChainId, - toChain, + toChain.String(), cctx.GetCurrentOutboundParam().TssNonce, txData.gasPrice, ) @@ -444,7 +450,7 @@ func (signer *Signer) TryProcessOutbound( logger.Info().Msgf( "SignOutbound: %d => %s, nonce %d, gasPrice %d", cctx.InboundParams.SenderChainId, - toChain, + toChain.String(), cctx.GetCurrentOutboundParam().TssNonce, txData.gasPrice, ) @@ -460,7 +466,7 @@ func (signer *Signer) TryProcessOutbound( logger.Info().Msgf( "SignRevertTx: %d => %s, nonce %d, gasPrice %d", cctx.InboundParams.SenderChainId, - toChain, cctx.GetCurrentOutboundParam().TssNonce, + toChain.String(), cctx.GetCurrentOutboundParam().TssNonce, txData.gasPrice, ) txData.srcChainID = big.NewInt(cctx.OutboundParams[0].ReceiverChainId) @@ -470,7 +476,7 @@ func (signer *Signer) TryProcessOutbound( logger.Info().Msgf( "SignWithdrawTx: %d => %s, nonce %d, gasPrice %d", cctx.InboundParams.SenderChainId, - toChain, + toChain.String(), cctx.GetCurrentOutboundParam().TssNonce, txData.gasPrice, ) @@ -478,7 +484,7 @@ func (signer *Signer) TryProcessOutbound( case coin.CoinType_ERC20: logger.Info().Msgf("SignERC20WithdrawTx: %d => %s, nonce %d, gasPrice %d", cctx.InboundParams.SenderChainId, - toChain, + toChain.String(), cctx.GetCurrentOutboundParam().TssNonce, txData.gasPrice, ) @@ -492,7 +498,7 @@ func (signer *Signer) TryProcessOutbound( logger.Info().Msgf( "SignRevertTx: %d => %s, nonce %d, gasPrice %d", cctx.InboundParams.SenderChainId, - toChain, + toChain.String(), cctx.GetCurrentOutboundParam().TssNonce, txData.gasPrice, ) @@ -508,7 +514,7 @@ func (signer *Signer) TryProcessOutbound( logger.Info().Msgf( "SignOutbound: %d => %s, nonce %d, gasPrice %d", cctx.InboundParams.SenderChainId, - toChain, + toChain.String(), cctx.GetCurrentOutboundParam().TssNonce, txData.gasPrice, ) @@ -522,7 +528,7 @@ func (signer *Signer) TryProcessOutbound( logger.Info().Msgf( "Key-sign success: %d => %s, nonce %d", cctx.InboundParams.SenderChainId, - toChain, + toChain.String(), cctx.GetCurrentOutboundParam().TssNonce, ) @@ -540,45 +546,52 @@ func (signer *Signer) BroadcastOutbound( txData *OutboundData, ) { // Get destination chain for logging - toChain := chains.GetChainFromChainID(txData.toChainID.Int64()) + toChain, found := chains.GetChainFromChainID( + txData.toChainID.Int64(), + signer.AppContext().GetAdditionalChains(), + ) + if !found { + logger.Warn().Msgf("BroadcastOutbound: unknown chain %d", txData.toChainID.Int64()) + return + } + if tx == nil { logger.Warn().Msgf("BroadcastOutbound: no tx to broadcast %s", cctx.Index) + return } // broadcast transaction - if tx != nil { - outboundHash := tx.Hash().Hex() - - // try broacasting tx with increasing backoff (1s, 2s, 4s, 8s, 16s) in case of RPC error - backOff := broadcastBackoff - for i := 0; i < broadcastRetries; i++ { - time.Sleep(backOff) - err := signer.Broadcast(tx) - if err != nil { - log.Warn(). - Err(err). - Msgf("BroadcastOutbound: error broadcasting tx %s on chain %d nonce %d retry %d signer %s", - outboundHash, toChain.ChainId, cctx.GetCurrentOutboundParam().TssNonce, i, myID) - retry, report := zetacore.HandleBroadcastError( - err, - strconv.FormatUint(cctx.GetCurrentOutboundParam().TssNonce, 10), - toChain.String(), - outboundHash, - ) - if report { - signer.reportToOutboundTracker(zetacoreClient, toChain.ChainId, tx.Nonce(), outboundHash, logger) - } - if !retry { - break - } - backOff *= 2 - continue + outboundHash := tx.Hash().Hex() + + // try broacasting tx with increasing backoff (1s, 2s, 4s, 8s, 16s) in case of RPC error + backOff := broadcastBackoff + for i := 0; i < broadcastRetries; i++ { + time.Sleep(backOff) + err := signer.Broadcast(tx) + if err != nil { + log.Warn(). + Err(err). + Msgf("BroadcastOutbound: error broadcasting tx %s on chain %d nonce %d retry %d signer %s", + outboundHash, toChain.ChainId, cctx.GetCurrentOutboundParam().TssNonce, i, myID) + retry, report := zetacore.HandleBroadcastError( + err, + strconv.FormatUint(cctx.GetCurrentOutboundParam().TssNonce, 10), + toChain.String(), + outboundHash, + ) + if report { + signer.reportToOutboundTracker(zetacoreClient, toChain.ChainId, tx.Nonce(), outboundHash, logger) + } + if !retry { + break } - logger.Info().Msgf("BroadcastOutbound: broadcasted tx %s on chain %d nonce %d signer %s", - outboundHash, toChain.ChainId, cctx.GetCurrentOutboundParam().TssNonce, myID) - signer.reportToOutboundTracker(zetacoreClient, toChain.ChainId, tx.Nonce(), outboundHash, logger) - break // successful broadcast; no need to retry + backOff *= 2 + continue } + logger.Info().Msgf("BroadcastOutbound: broadcasted tx %s on chain %d nonce %d signer %s", + outboundHash, toChain.ChainId, cctx.GetCurrentOutboundParam().TssNonce, myID) + signer.reportToOutboundTracker(zetacoreClient, toChain.ChainId, tx.Nonce(), outboundHash, logger) + break // successful broadcast; no need to retry } } diff --git a/zetaclient/chains/evm/signer/signer_test.go b/zetaclient/chains/evm/signer/signer_test.go index 3165c20348..f682bb15f0 100644 --- a/zetaclient/chains/evm/signer/signer_test.go +++ b/zetaclient/chains/evm/signer/signer_test.go @@ -178,7 +178,14 @@ func TestSigner_SignOutbound(t *testing.T) { cctx := getCCTX(t) mockObserver, err := getNewEvmChainObserver(t, tss) require.NoError(t, err) - txData, skip, err := NewOutboundData(cctx, mockObserver, evmSigner.EvmClient(), zerolog.Logger{}, 123) + txData, skip, err := NewOutboundData( + evmSigner.AppContext(), + cctx, + mockObserver, + evmSigner.EvmClient(), + zerolog.Logger{}, + 123, + ) require.False(t, skip) require.NoError(t, err) @@ -212,7 +219,14 @@ func TestSigner_SignRevertTx(t *testing.T) { cctx := getCCTX(t) mockObserver, err := getNewEvmChainObserver(t, tss) require.NoError(t, err) - txData, skip, err := NewOutboundData(cctx, mockObserver, evmSigner.EvmClient(), zerolog.Logger{}, 123) + txData, skip, err := NewOutboundData( + evmSigner.AppContext(), + cctx, + mockObserver, + evmSigner.EvmClient(), + zerolog.Logger{}, + 123, + ) require.False(t, skip) require.NoError(t, err) @@ -250,7 +264,14 @@ func TestSigner_SignCancelTx(t *testing.T) { cctx := getCCTX(t) mockObserver, err := getNewEvmChainObserver(t, tss) require.NoError(t, err) - txData, skip, err := NewOutboundData(cctx, mockObserver, evmSigner.EvmClient(), zerolog.Logger{}, 123) + txData, skip, err := NewOutboundData( + evmSigner.AppContext(), + cctx, + mockObserver, + evmSigner.EvmClient(), + zerolog.Logger{}, + 123, + ) require.False(t, skip) require.NoError(t, err) @@ -288,7 +309,14 @@ func TestSigner_SignWithdrawTx(t *testing.T) { cctx := getCCTX(t) mockObserver, err := getNewEvmChainObserver(t, tss) require.NoError(t, err) - txData, skip, err := NewOutboundData(cctx, mockObserver, evmSigner.EvmClient(), zerolog.Logger{}, 123) + txData, skip, err := NewOutboundData( + evmSigner.AppContext(), + cctx, + mockObserver, + evmSigner.EvmClient(), + zerolog.Logger{}, + 123, + ) require.False(t, skip) require.NoError(t, err) @@ -324,7 +352,14 @@ func TestSigner_SignCommandTx(t *testing.T) { cctx := getCCTX(t) mockObserver, err := getNewEvmChainObserver(t, nil) require.NoError(t, err) - txData, skip, err := NewOutboundData(cctx, mockObserver, evmSigner.EvmClient(), zerolog.Logger{}, 123) + txData, skip, err := NewOutboundData( + evmSigner.AppContext(), + cctx, + mockObserver, + evmSigner.EvmClient(), + zerolog.Logger{}, + 123, + ) require.False(t, skip) require.NoError(t, err) @@ -369,7 +404,14 @@ func TestSigner_SignERC20WithdrawTx(t *testing.T) { cctx := getCCTX(t) mockObserver, err := getNewEvmChainObserver(t, tss) require.NoError(t, err) - txData, skip, err := NewOutboundData(cctx, mockObserver, evmSigner.EvmClient(), zerolog.Logger{}, 123) + txData, skip, err := NewOutboundData( + evmSigner.AppContext(), + cctx, + mockObserver, + evmSigner.EvmClient(), + zerolog.Logger{}, + 123, + ) require.False(t, skip) require.NoError(t, err) @@ -407,7 +449,14 @@ func TestSigner_BroadcastOutbound(t *testing.T) { cctx := getCCTX(t) mockObserver, err := getNewEvmChainObserver(t, nil) require.NoError(t, err) - txData, skip, err := NewOutboundData(cctx, mockObserver, evmSigner.EvmClient(), zerolog.Logger{}, 123) + txData, skip, err := NewOutboundData( + evmSigner.AppContext(), + cctx, + mockObserver, + evmSigner.EvmClient(), + zerolog.Logger{}, + 123, + ) require.False(t, skip) require.NoError(t, err) @@ -457,7 +506,14 @@ func TestSigner_SignWhitelistERC20Cmd(t *testing.T) { cctx := getCCTX(t) mockObserver, err := getNewEvmChainObserver(t, tss) require.NoError(t, err) - txData, skip, err := NewOutboundData(cctx, mockObserver, evmSigner.EvmClient(), zerolog.Logger{}, 123) + txData, skip, err := NewOutboundData( + evmSigner.AppContext(), + cctx, + mockObserver, + evmSigner.EvmClient(), + zerolog.Logger{}, + 123, + ) require.False(t, skip) require.NoError(t, err) @@ -500,7 +556,14 @@ func TestSigner_SignMigrateTssFundsCmd(t *testing.T) { cctx := getCCTX(t) mockObserver, err := getNewEvmChainObserver(t, tss) require.NoError(t, err) - txData, skip, err := NewOutboundData(cctx, mockObserver, evmSigner.EvmClient(), zerolog.Logger{}, 123) + txData, skip, err := NewOutboundData( + evmSigner.AppContext(), + cctx, + mockObserver, + evmSigner.EvmClient(), + zerolog.Logger{}, + 123, + ) require.False(t, skip) require.NoError(t, err) diff --git a/zetaclient/chains/interfaces/interfaces.go b/zetaclient/chains/interfaces/interfaces.go index d1c4a0f292..77c2cbd966 100644 --- a/zetaclient/chains/interfaces/interfaces.go +++ b/zetaclient/chains/interfaces/interfaces.go @@ -71,7 +71,7 @@ type ZetacoreClient interface { UpdateAppContext(appContext *clientcontext.AppContext, logger zerolog.Logger) error GetUpgradePlan() (*upgradetypes.Plan, error) GetChainParams() ([]*observertypes.ChainParams, error) - GetSupportedChains() ([]*chains.Chain, error) + GetSupportedChains() ([]chains.Chain, error) GetCurrentTss() (observertypes.TSS, error) GetBlockHeaderEnabledChains() ([]lightclienttypes.HeaderSupportedChain, error) PostVoteInbound(gasLimit, retryGasLimit uint64, msg *crosschaintypes.MsgVoteInbound) (string, string, error) diff --git a/zetaclient/config/types.go b/zetaclient/config/types.go index 6e1b8e935e..b83e3cc814 100644 --- a/zetaclient/config/types.go +++ b/zetaclient/config/types.go @@ -88,6 +88,9 @@ type Config struct { func NewConfig() Config { return Config{ EVMChainConfigs: make(map[int64]EVMConfig), + ComplianceConfig: ComplianceConfig{ + RestrictedAddresses: make([]string, 0), + }, } } diff --git a/zetaclient/context/app_context.go b/zetaclient/context/app_context.go index 2bd43a6f14..b2cb5b2c4f 100644 --- a/zetaclient/context/app_context.go +++ b/zetaclient/context/app_context.go @@ -25,6 +25,10 @@ type AppContext struct { btcNetParams *chaincfg.Params crosschainFlags observertypes.CrosschainFlags + // additionalChains is a list of additional static chain information to use when searching from chain IDs + // it is stored in the protocol to dynamically support new chains without doing an upgrade + additionalChain []chains.Chain + // blockHeaderEnabledChains is used to store the list of chains that have block header verification enabled // All chains in this list will have Enabled flag set to true blockHeaderEnabledChains []lightclienttypes.HeaderSupportedChain @@ -40,6 +44,7 @@ func New(cfg config.Config) *AppContext { chainsEnabled: []chains.Chain{}, chainParamMap: make(map[int64]*observertypes.ChainParams), crosschainFlags: observertypes.CrosschainFlags{}, + additionalChain: []chains.Chain{}, blockHeaderEnabledChains: []lightclienttypes.HeaderSupportedChain{}, mu: sync.RWMutex{}, } @@ -151,6 +156,18 @@ func (a *AppContext) GetCrossChainFlags() observertypes.CrosschainFlags { return a.crosschainFlags } +// GetAdditionalChains returns additional chains +func (a *AppContext) GetAdditionalChains() []chains.Chain { + a.mu.RLock() + defer a.mu.RUnlock() + + // deep copy additional chains + additionalChains := make([]chains.Chain, len(a.additionalChain)) + copy(additionalChains, a.additionalChain) + + return a.additionalChain +} + // GetBlockHeaderEnabledChains checks if block header verification is enabled for a specific chain func (a *AppContext) GetBlockHeaderEnabledChains(chainID int64) (lightclienttypes.HeaderSupportedChain, bool) { a.mu.RLock() @@ -172,6 +189,7 @@ func (a *AppContext) Update( chainParamMap map[int64]*observertypes.ChainParams, btcNetParams *chaincfg.Params, crosschainFlags observertypes.CrosschainFlags, + additionalChains []chains.Chain, blockHeaderEnabledChains []lightclienttypes.HeaderSupportedChain, logger zerolog.Logger, ) { @@ -207,6 +225,7 @@ func (a *AppContext) Update( a.chainParamMap = chainParamMap a.currentTssPubkey = tssPubKey a.crosschainFlags = crosschainFlags + a.additionalChain = additionalChains a.blockHeaderEnabledChains = blockHeaderEnabledChains } diff --git a/zetaclient/context/app_context_test.go b/zetaclient/context/app_context_test.go index 7ec1e8f939..c6dafbcace 100644 --- a/zetaclient/context/app_context_test.go +++ b/zetaclient/context/app_context_test.go @@ -41,6 +41,9 @@ func Test_NewAppContext(t *testing.T) { // assert crosschain flags require.Equal(t, observertypes.CrosschainFlags{}, appContext.GetCrossChainFlags()) + + // assert additional chains + require.Empty(t, appContext.GetAdditionalChains()) }) } @@ -77,6 +80,11 @@ func Test_UpdateAndGetters(t *testing.T) { btcNetParams := &chaincfg.MainNetParams tssPubKey := "tsspubkeytest" ccFlags := *sample.CrosschainFlags() + additionalChains := []chains.Chain{ + sample.Chain(1), + sample.Chain(2), + sample.Chain(3), + } headerSupportedChains := sample.HeaderSupportedChains() // feed app context fields @@ -88,6 +96,7 @@ func Test_UpdateAndGetters(t *testing.T) { chainParamMap, btcNetParams, ccFlags, + additionalChains, headerSupportedChains, log.Logger, ) @@ -127,6 +136,10 @@ func Test_UpdateAndGetters(t *testing.T) { result := appContext.GetCrossChainFlags() require.Equal(t, ccFlags, result) }) + t.Run("should get additional chains", func(t *testing.T) { + result := appContext.GetAdditionalChains() + require.Equal(t, additionalChains, result) + }) t.Run("should get block header enabled chains", func(t *testing.T) { for _, chain := range headerSupportedChains { result, found := appContext.GetBlockHeaderEnabledChains(chain.ChainId) @@ -224,6 +237,7 @@ func makeAppContext( newChainParams, &chaincfg.RegressionNetParams, ccFlags, + []chains.Chain{}, headerSupportedChains, zerolog.Logger{}, ) diff --git a/zetaclient/orchestrator/chain_activate.go b/zetaclient/orchestrator/chain_activate.go index 9432b67011..613fd3ade4 100644 --- a/zetaclient/orchestrator/chain_activate.go +++ b/zetaclient/orchestrator/chain_activate.go @@ -33,6 +33,18 @@ func (oc *Orchestrator) WatchEnabledChains() { } // ActivateAndDeactivateChains activates and deactivates chains according to chain params and config file +// +// The chains to be activated: +// - chain params flag 'IsSupported' is true AND +// - chain is configured in config file +// +// The chains to be deactivated: +// - chain params flag 'IsSupported' is false OR +// - chain is not configured in config file +// +// Note: +// - zetaclient will reload config file periodically and update in-memory config accordingly. +// - As an tss signer, please make sure the config file is always well configured and not missing any chain func (oc *Orchestrator) ActivateAndDeactivateChains() { // create new signer and observer maps // Note: the keys of the two maps are chain IDs and they are always exactly matched diff --git a/zetaclient/orchestrator/chain_activate_test.go b/zetaclient/orchestrator/chain_activate_test.go index be470967fb..aa826bc9f7 100644 --- a/zetaclient/orchestrator/chain_activate_test.go +++ b/zetaclient/orchestrator/chain_activate_test.go @@ -60,6 +60,7 @@ func createTestAppContext( chainParamMap, &chaincfg.MainNetParams, *ccFlags, + []chains.Chain{}, headerSupportedChains, zerolog.Logger{}, ) diff --git a/zetaclient/orchestrator/orchestrator.go b/zetaclient/orchestrator/orchestrator.go index 4995c36935..55829071a4 100644 --- a/zetaclient/orchestrator/orchestrator.go +++ b/zetaclient/orchestrator/orchestrator.go @@ -86,8 +86,11 @@ type Orchestrator struct { // mu protects fields from concurrent access mu sync.Mutex - // stop channel and flag to avoid closing twice - stop chan struct{} + // stop channel + stop chan struct{} + + // stop flag to used to prevent the 'stop' channel from being closed multiple times (panic). + // the 'stop' channel will be closed either by system signals or by the 'WatchUpgradePlan' goroutine stopped bool } @@ -368,9 +371,10 @@ func (oc *Orchestrator) SchedulePendingCctxs() { // #nosec G701 range is verified zetaHeight := uint64(bn) - if chains.IsEVMChain(c.ChainId) { + additionalChains := oc.appContext.GetAdditionalChains() + if chains.IsEVMChain(c.ChainId, additionalChains) { oc.ScheduleCctxEVM(zetaHeight, c.ChainId, cctxList, ob, signer) - } else if chains.IsBitcoinChain(c.ChainId) { + } else if chains.IsBitcoinChain(c.ChainId, additionalChains) { oc.ScheduleCctxBTC(zetaHeight, c.ChainId, cctxList, ob, signer) } else { oc.logger.Std.Error().Msgf("StartCctxScheduler: unsupported chain %d", c.ChainId) diff --git a/zetaclient/orchestrator/orchestrator_test.go b/zetaclient/orchestrator/orchestrator_test.go index 492d6e6d01..b3d9f099e7 100644 --- a/zetaclient/orchestrator/orchestrator_test.go +++ b/zetaclient/orchestrator/orchestrator_test.go @@ -85,6 +85,7 @@ func CreateTestAppContext( chainParamsMap, &chaincfg.RegressionNetParams, *ccFlags, + []chains.Chain{}, verificationFlags, zerolog.Logger{}, ) diff --git a/zetaclient/supplychecker/zeta_supply_checker.go b/zetaclient/supplychecker/zeta_supply_checker.go index f068a9ef59..c119ff50a4 100644 --- a/zetaclient/supplychecker/zeta_supply_checker.go +++ b/zetaclient/supplychecker/zeta_supply_checker.go @@ -68,12 +68,15 @@ func NewZetaSupplyChecker( } for chainID := range zetaSupplyChecker.evmClient { - chain := chains.GetChainFromChainID(chainID) - if chain.IsExternalChain() && chains.IsEVMChain(chain.ChainId) && !chains.IsEthereumChain(chain.ChainId) { - zetaSupplyChecker.externalEvmChain = append(zetaSupplyChecker.externalEvmChain, *chain) + chain, found := chains.GetChainFromChainID(chainID, appContext.GetAdditionalChains()) + if !found { + return zetaSupplyChecker, fmt.Errorf("chain not found for chain id %d", chainID) } - if chains.IsEthereumChain(chain.ChainId) { - zetaSupplyChecker.ethereumChain = *chain + if chain.IsExternalChain() && chain.IsEVMChain() && + chain.Network != chains.Network_eth { + zetaSupplyChecker.externalEvmChain = append(zetaSupplyChecker.externalEvmChain, chain) + } else { + zetaSupplyChecker.ethereumChain = chain } } diff --git a/zetaclient/testutils/mocks/zetacore_client.go b/zetaclient/testutils/mocks/zetacore_client.go index 01c07e042f..bb4cae6b2d 100644 --- a/zetaclient/testutils/mocks/zetacore_client.go +++ b/zetaclient/testutils/mocks/zetacore_client.go @@ -80,7 +80,7 @@ func (m *MockZetacoreClient) GetChainParams() ([]*observerTypes.ChainParams, err return nil, nil } -func (m *MockZetacoreClient) GetSupportedChains() ([]*chains.Chain, error) { +func (m *MockZetacoreClient) GetSupportedChains() ([]chains.Chain, error) { if m.paused { return nil, errors.New(ErrMsgPaused) } diff --git a/zetaclient/zetacore/client.go b/zetaclient/zetacore/client.go index 7d1cb52599..722e53d3b3 100644 --- a/zetaclient/zetacore/client.go +++ b/zetaclient/zetacore/client.go @@ -117,7 +117,7 @@ func NewClient( seqMap[keyType] = 0 } - zetaChain, err := chains.ZetaChainFromChainID(chainID) + zetaChain, err := chains.ZetaChainFromCosmosChainID(chainID) if err != nil { return nil, fmt.Errorf("invalid chain id %s, %w", chainID, err) } @@ -143,7 +143,7 @@ func (c *Client) UpdateChainID(chainID string) error { if c.chainID != chainID { c.chainID = chainID - zetaChain, err := chains.ZetaChainFromChainID(chainID) + zetaChain, err := chains.ZetaChainFromCosmosChainID(chainID) if err != nil { return fmt.Errorf("invalid chain id %s, %w", chainID, err) } @@ -227,7 +227,13 @@ func (c *Client) UpdateAppContext(appContext *context.AppContext, logger zerolog } supportedChainsMap := make(map[int64]chains.Chain) for _, chain := range supportedChains { - supportedChainsMap[chain.ChainId] = *chain + supportedChainsMap[chain.ChainId] = chain + } + + // get additional chains that were dynamically to zetacore to support new chains + additionalChains, err := c.GetAdditionalChains() + if err != nil { + return fmt.Errorf("failed to additional chains: %w", err) } // get latest chain parameters @@ -257,9 +263,15 @@ func (c *Client) UpdateAppContext(appContext *context.AppContext, logger zerolog continue } + // just in case (zetacore already validated) + err := observertypes.ValidateChainParams(chainParam) + if err != nil { + return errors.Wrapf(err, "Invalid chain params for chain %d", chainParam.ChainId) + } + // zetaclient detects Bitcoin network (regnet, testnet, mainnet) from chain params in zetacore // The network params will be used by TSS to calculate the correct TSS address. - if chains.IsBitcoinChain(chainParam.ChainId) { + if chains.IsBitcoinChain(chainParam.ChainId, additionalChains) { btcNetParams, err = chains.BitcoinNetParamsFromChainID(chainParam.ChainId) if err != nil { return errors.Wrapf(err, "BitcoinNetParamsFromChainID failed for chain %d", chainParam.ChainId) @@ -304,6 +316,7 @@ func (c *Client) UpdateAppContext(appContext *context.AppContext, logger zerolog chainParamMap, btcNetParams, crosschainFlags, + additionalChains, blockHeaderEnabledChains, logger, ) diff --git a/zetaclient/zetacore/query.go b/zetaclient/zetacore/query.go index e90be274ff..52a9a8e5fc 100644 --- a/zetaclient/zetacore/query.go +++ b/zetaclient/zetacore/query.go @@ -19,6 +19,7 @@ import ( "github.com/zeta-chain/zetacore/cmd/zetacored/config" "github.com/zeta-chain/zetacore/pkg/chains" "github.com/zeta-chain/zetacore/pkg/proofs" + authoritytypes "github.com/zeta-chain/zetacore/x/authority/types" crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" lightclienttypes "github.com/zeta-chain/zetacore/x/lightclient/types" observertypes "github.com/zeta-chain/zetacore/x/observer/types" @@ -480,7 +481,7 @@ func (c *Client) GetBlockHeaderChainState(chainID int64) (lightclienttypes.Query } // GetSupportedChains returns the supported chains -func (c *Client) GetSupportedChains() ([]*chains.Chain, error) { +func (c *Client) GetSupportedChains() ([]chains.Chain, error) { client := observertypes.NewQueryClient(c.grpcConn) resp, err := client.SupportedChains(context.Background(), &observertypes.QuerySupportedChains{}) if err != nil { @@ -489,6 +490,16 @@ func (c *Client) GetSupportedChains() ([]*chains.Chain, error) { return resp.GetChains(), nil } +// GetAdditionalChains returns the additional chains +func (c *Client) GetAdditionalChains() ([]chains.Chain, error) { + client := authoritytypes.NewQueryClient(c.grpcConn) + resp, err := client.ChainInfo(context.Background(), &authoritytypes.QueryGetChainInfoRequest{}) + if err != nil { + return nil, err + } + return resp.GetChainInfo().Chains, nil +} + // GetPendingNonces returns the pending nonces func (c *Client) GetPendingNonces() (*observertypes.QueryAllPendingNoncesResponse, error) { client := observertypes.NewQueryClient(c.grpcConn) diff --git a/zetaclient/zetacore/query_test.go b/zetaclient/zetacore/query_test.go index 70898b8e11..baba533cfa 100644 --- a/zetaclient/zetacore/query_test.go +++ b/zetaclient/zetacore/query_test.go @@ -1,6 +1,7 @@ package zetacore import ( + authoritytypes "github.com/zeta-chain/zetacore/x/authority/types" "net" "testing" @@ -815,7 +816,7 @@ func TestZetacore_GetBlockHeaderChainState(t *testing.T) { func TestZetacore_GetSupportedChains(t *testing.T) { expectedOutput := observertypes.QuerySupportedChainsResponse{ - Chains: []*chains.Chain{ + Chains: []chains.Chain{ { ChainName: chains.BitcoinMainnet.ChainName, ChainId: chains.BitcoinMainnet.ChainId, @@ -850,6 +851,29 @@ func TestZetacore_GetSupportedChains(t *testing.T) { require.Equal(t, expectedOutput.Chains, resp) } +func TestZetacore_GetAdditionalChains(t *testing.T) { + expectedOutput := authoritytypes.QueryGetChainInfoResponse{ + ChainInfo: authoritytypes.ChainInfo{ + Chains: []chains.Chain{ + chains.BitcoinMainnet, + chains.Ethereum, + }, + }, + } + input := observertypes.QuerySupportedChains{} + method := "/zetachain.zetacore.authority.Query/ChainInfo" + server := setupMockServer(t, authoritytypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + client, err := setupZetacoreClient() + require.NoError(t, err) + + resp, err := client.GetAdditionalChains() + require.NoError(t, err) + require.Equal(t, expectedOutput.ChainInfo.Chains, resp) +} + func TestZetacore_GetPendingNonces(t *testing.T) { expectedOutput := observertypes.QueryAllPendingNoncesResponse{ PendingNonces: []observertypes.PendingNonces{ diff --git a/zetaclient/zetacore/tx.go b/zetaclient/zetacore/tx.go index abfb2ed036..c320981249 100644 --- a/zetaclient/zetacore/tx.go +++ b/zetaclient/zetacore/tx.go @@ -59,13 +59,13 @@ func GetInboundVoteMessage( } // GasPriceMultiplier returns the gas price multiplier for the given chain -func GasPriceMultiplier(chainID int64) (float64, error) { - if chains.IsEVMChain(chainID) { +func GasPriceMultiplier(chain chains.Chain) (float64, error) { + if chain.IsEVMChain() { return clientcommon.EVMOutboundGasPriceMultiplier, nil - } else if chains.IsBitcoinChain(chainID) { + } else if chain.IsBitcoinChain() { return clientcommon.BTCOutboundGasPriceMultiplier, nil } - return 0, fmt.Errorf("cannot get gas price multiplier for unknown chain %d", chainID) + return 0, fmt.Errorf("cannot get gas price multiplier for unknown chain %d", chain.ChainId) } // WrapMessageWithAuthz wraps a message with an authz message @@ -87,7 +87,7 @@ func (c *Client) WrapMessageWithAuthz(msg sdk.Msg) (sdk.Msg, clientauthz.Signer, // TODO(revamp): rename to PostVoteGasPrice func (c *Client) PostGasPrice(chain chains.Chain, gasPrice uint64, supply string, blockNum uint64) (string, error) { // apply gas price multiplier for the chain - multiplier, err := GasPriceMultiplier(chain.ChainId) + multiplier, err := GasPriceMultiplier(chain) if err != nil { return "", err } diff --git a/zetaclient/zetacore/tx_test.go b/zetaclient/zetacore/tx_test.go index a647725301..5bf8babb3d 100644 --- a/zetaclient/zetacore/tx_test.go +++ b/zetaclient/zetacore/tx_test.go @@ -4,6 +4,8 @@ import ( "bytes" "encoding/hex" "errors" + "github.com/zeta-chain/zetacore/testutil/sample" + authoritytypes "github.com/zeta-chain/zetacore/x/authority/types" "math/big" "net" "os" @@ -41,68 +43,70 @@ const ( func Test_GasPriceMultiplier(t *testing.T) { tt := []struct { name string - chainID int64 + chain chains.Chain multiplier float64 fail bool }{ { name: "get Ethereum multiplier", - chainID: 1, + chain: chains.Ethereum, multiplier: 1.2, fail: false, }, { name: "get Goerli multiplier", - chainID: 5, + chain: chains.Goerli, multiplier: 1.2, fail: false, }, { name: "get BSC multiplier", - chainID: 56, + chain: chains.BscMainnet, multiplier: 1.2, fail: false, }, { name: "get BSC Testnet multiplier", - chainID: 97, + chain: chains.BscTestnet, multiplier: 1.2, fail: false, }, { name: "get Polygon multiplier", - chainID: 137, + chain: chains.Polygon, multiplier: 1.2, fail: false, }, { name: "get Mumbai Testnet multiplier", - chainID: 80001, + chain: chains.Mumbai, multiplier: 1.2, fail: false, }, { name: "get Bitcoin multiplier", - chainID: 8332, + chain: chains.BitcoinMainnet, multiplier: 2.0, fail: false, }, { name: "get Bitcoin Testnet multiplier", - chainID: 18332, + chain: chains.BitcoinTestnet, multiplier: 2.0, fail: false, }, { - name: "get unknown chain gas price multiplier", - chainID: 1234, + name: "get unknown chain gas price multiplier", + chain: chains.Chain{ + Consensus: chains.Consensus_tendermint, + }, multiplier: 1.0, fail: true, }, } for _, tc := range tt { t.Run(tc.name, func(t *testing.T) { - multiplier, err := GasPriceMultiplier(tc.chainID) + multiplier, err := GasPriceMultiplier(tc.chain) if tc.fail { require.Error(t, err) return @@ -209,6 +213,7 @@ func TestZetacore_UpdateAppContext(t *testing.T) { grpcmock.RegisterService(upgradetypes.RegisterQueryServer), grpcmock.RegisterService(observertypes.RegisterQueryServer), grpcmock.RegisterService(lightclienttypes.RegisterQueryServer), + grpcmock.RegisterService(authoritytypes.RegisterQueryServer), grpcmock.WithPlanner(planner.FirstMatch()), grpcmock.WithListener(listener), func(s *grpcmock.Server) { @@ -238,7 +243,7 @@ func TestZetacore_UpdateAppContext(t *testing.T) { UnlimitedTimes(). WithPayload(observertypes.QuerySupportedChains{}). Return(observertypes.QuerySupportedChainsResponse{ - Chains: []*chains.Chain{ + Chains: []chains.Chain{ { ChainId: chains.ZetaChainMainnet.ChainId, IsExternal: chains.ZetaChainMainnet.IsExternal, @@ -305,6 +310,20 @@ func TestZetacore_UpdateAppContext(t *testing.T) { Enabled: false, }, }}) + + method = "/zetachain.zetacore.authority.Query/ChainInfo" + s.ExpectUnary(method). + UnlimitedTimes(). + WithPayload(authoritytypes.QueryGetChainInfoRequest{}). + Return(authoritytypes.QueryGetChainInfoResponse{ + ChainInfo: authoritytypes.ChainInfo{ + Chains: []chains.Chain{ + sample.Chain(1000), + sample.Chain(1001), + sample.Chain(1002), + }, + }, + }) }, )(t)