├── .dockerignore ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── config.yml │ ├── documentation.yml │ ├── feature_request.yml │ └── questions.yml ├── pull_request_template.md └── workflows │ ├── branch.yml │ ├── cosmovisor.yml │ ├── goreleaser.yml │ ├── pull-request.yml │ ├── release.yml │ └── unit-coverage.yml ├── .gitignore ├── .golangci.yml ├── .goreleaser.yml ├── .testcoverage.yml ├── Dockerfile ├── Makefile ├── app ├── ante.go ├── app.go ├── encoding.go ├── export.go ├── genesis.go ├── precompiles.go ├── simulation_test.go ├── upgrades.go ├── upgrades │ ├── v4 │ │ ├── constants.go │ │ └── upgrades.go │ ├── v5 │ │ ├── constants.go │ │ └── upgrades.go │ ├── v6 │ │ ├── constants.go │ │ └── upgrades.go │ ├── v7 │ │ ├── constants.go │ │ └── upgrades.go │ └── v8 │ │ ├── constants.go │ │ └── upgrades.go └── utils.go ├── buf.work.yaml ├── cmd └── exrpd │ ├── cmd │ ├── config.go │ ├── genaccounts.go │ └── root.go │ └── main.go ├── docs ├── docs.go ├── static │ └── openapi.yml └── template │ └── index.tpl ├── go.mod ├── go.sum ├── local-node.sh ├── proto ├── buf.gen.gogo.yaml ├── buf.lock ├── buf.yaml ├── poa │ ├── genesis.proto │ ├── params.proto │ ├── query.proto │ └── tx.proto └── scripts │ ├── protoc-swagger-gen.sh │ └── protocgen.sh ├── readme.md ├── scripts └── mockgen.sh ├── tests ├── integration │ ├── network.go │ ├── poa_test.go │ ├── slashing_test.go │ ├── suite.go │ └── suite_test.go ├── sim │ └── params.json └── upgrade │ ├── README.md │ ├── network.go │ ├── suite.go │ ├── suite_test.go │ └── upgrade-state.json ├── testutil ├── integration │ ├── common │ │ ├── factory │ │ │ ├── base.go │ │ │ ├── distribution.go │ │ │ ├── factory.go │ │ │ ├── fund.go │ │ │ ├── helper.go │ │ │ ├── sign.go │ │ │ ├── staking.go │ │ │ └── types.go │ │ ├── grpc │ │ │ ├── account.go │ │ │ ├── authz.go │ │ │ ├── bank.go │ │ │ ├── distribution.go │ │ │ ├── feemarket.go │ │ │ ├── gov.go │ │ │ ├── grpc.go │ │ │ └── staking.go │ │ ├── keyring │ │ │ └── keyring.go │ │ └── network │ │ │ └── network.go │ └── exrp │ │ ├── common │ │ ├── clients.go │ │ ├── config.go │ │ ├── consensus.go │ │ ├── network.go │ │ └── setup.go │ │ ├── integration │ │ ├── abci.go │ │ ├── config.go │ │ ├── ibc.go │ │ ├── keepers.go │ │ ├── network.go │ │ ├── setup.go │ │ └── unit_network.go │ │ ├── upgrade │ │ ├── abci.go │ │ ├── config.go │ │ ├── ibc.go │ │ ├── keepers.go │ │ ├── network.go │ │ └── unit_network.go │ │ └── utils │ │ ├── abci.go │ │ └── gov.go └── sample │ └── sample.go ├── tools ├── cosmovisor │ ├── Dockerfile │ └── init.sh └── tools.go └── x └── poa ├── ante ├── poa.go └── poa_test.go ├── keeper ├── common_test.go ├── genesis.go ├── keeper.go ├── keeper_test.go ├── msg_server.go ├── msg_server_add_validator.go ├── msg_server_add_validator_test.go ├── msg_server_remove_validator.go ├── msg_server_remove_validator_test.go ├── params.go ├── query.go └── query_params.go ├── module.go ├── module_simulation.go ├── simulation ├── proposals.go └── proposals_test.go ├── testutil ├── expected_keepers_mock.go ├── expected_msg_server.go ├── expected_msg_server_mock.go ├── keys.go ├── keys_mock.go ├── staking_hooks.go ├── staking_hooks_mock.go ├── tx.go └── tx_mock.go └── types ├── codec.go ├── errors.go ├── events.go ├── expected_keepers.go ├── genesis.go ├── genesis.pb.go ├── keys.go ├── message_add_validator.go ├── message_remove_validator.go ├── params.go ├── params.pb.go ├── query.pb.go ├── query.pb.gw.go ├── tx.pb.go └── types.go /.dockerignore: -------------------------------------------------------------------------------- 1 | .github 2 | .gitignore 3 | .idea 4 | Dockerfile 5 | release 6 | build 7 | .dockerignore 8 | 9 | vue/node_modules 10 | vue/dist 11 | build/ 12 | release/ 13 | .idea/ 14 | .vscode/ 15 | .DS_Store 16 | 17 | 18 | .exrpd/ 19 | 20 | bin/ -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # CODEOWNERS: https://help.github.com/articles/about-codeowners/ 2 | 3 | * @xrplevm/core -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: "🐞 Bug Report" 2 | description: "Report a reproducible bug" 3 | labels: ["bug"] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: Thank you for reporting a bug! Your feedback helps us improve. Please complete the form below with as much detail as possible. 8 | - type: textarea 9 | attributes: 10 | label: Steps to reproduce 11 | description: Provide a detailed list of steps to reproduce the bug. 12 | placeholder: "1. 2. 3. 4." 13 | value: "Bug steps" 14 | validations: 15 | required: true 16 | - type: textarea 17 | attributes: 18 | label: Expected behavior 19 | description: Describe what you expected to happen. 20 | placeholder: "Expected behavior" 21 | value: "Expected behavior" 22 | validations: 23 | required: true 24 | - type: textarea 25 | attributes: 26 | label: Actual behavior 27 | description: Describe what actually happened. 28 | placeholder: "Actual behavior" 29 | value: "Actual behavior" 30 | validations: 31 | required: true 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: EVM Sidechain docs 4 | url: https://opensource.ripple.com/docs/evm-sidechain/intro-to-evm-sidechain/ 5 | about: Learn more about the EVM Sidechain. 6 | - name: Peersyst 7 | url: https://peersyst.com 8 | about: Contact us for any questions or support. 9 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/documentation.yml: -------------------------------------------------------------------------------- 1 | name: "📃 Documentation Bug" 2 | description: "Report inaccuracies or omissions in the documentation." 3 | title: "[docs] " 4 | labels: ["docs"] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: Thank you for helping us improve the documentation! Your contribution is invaluable in enhancing the user experience. 9 | - type: textarea 10 | attributes: 11 | label: Summary 12 | description: "Please succinctly describe the inaccuracies or omissions you have identified in the documentation." 13 | placeholder: "Enter a brief summary of the issue." 14 | validations: 15 | required: true 16 | - type: input 17 | attributes: 18 | label: Link to the Related Documentation Page 19 | description: "Please provide a link to the documentation page that requires attention." 20 | placeholder: "Enter the URL of the documentation page." 21 | validations: 22 | required: true 23 | - type: textarea 24 | attributes: 25 | label: Describe the Issue 26 | description: "Please provide a detailed description of the inaccuracies or omissions you have observed in the documentation." 27 | placeholder: "Enter a detailed description of the issue." 28 | validations: 29 | required: true 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: "🙋‍♂️ Feature Request" 2 | description: "Request the addition of a new feature." 3 | labels: ["feature", "request"] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: Thank you for helping us enhance the project! Your input is greatly appreciated in making it even better. 8 | - type: textarea 9 | attributes: 10 | label: Feature Request 11 | description: "Please describe the feature you would like to request." 12 | placeholder: "Enter details about the feature you want." 13 | value: "I want to request a feature that..." 14 | validations: 15 | required: true 16 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/questions.yml: -------------------------------------------------------------------------------- 1 | name: "❓ Questions and Discussions" 2 | description: "Initiate a conversation or seek clarification on specific aspects." 3 | labels: ["question"] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: Thank you for starting this discussion! Your engagement is valued. 8 | - type: input 9 | attributes: 10 | label: Question or Discussion 11 | description: "Please provide a brief description of your question or the topic you wish to discuss." 12 | placeholder: "Enter your question or discussion topic here." 13 | value: "I have a question about..." 14 | validations: 15 | required: true 16 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # PR Name 2 | 3 | ## Motivation 💡 4 | 5 | 8 | 9 | - Issue 10 | 11 | ## Changes 🛠 12 | 13 | 16 | 17 | - 1st change ✨ 18 | - 2nd change ✨ 19 | 20 | ## Considerations 🤔 21 | 22 | 25 | 26 | - Warning... ⚠️ 27 | - This part could be improved... 28 | 29 | ## Dependencies 📦 30 | 31 | 34 | 35 | - [Main](link-to-branch) 36 | -------------------------------------------------------------------------------- /.github/workflows/branch.yml: -------------------------------------------------------------------------------- 1 | name: "Branch" 2 | 3 | on: 4 | push: 5 | branches: 6 | - "main" 7 | 8 | concurrency: 9 | # Cancel old runs if there is a new commit in the same branch 10 | group: ${{ github.workflow }}-${{ github.ref }} 11 | cancel-in-progress: true 12 | 13 | jobs: 14 | integration: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Retrieve branch name 18 | run: echo "BRANCH=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV 19 | - uses: actions/checkout@v2 20 | - uses: docker/setup-qemu-action@v2 21 | - uses: docker/setup-buildx-action@v2 22 | - uses: actions/cache@v3 23 | with: 24 | path: /tmp/.buildx-cache 25 | key: ${{ github.job }}-${{ runner.os }}-${{ env.BRANCH }}-buildx 26 | restore-keys: | 27 | ${{ github.job }}-${{ runner.os }}-${{ env.BRANCH }}-buildx 28 | # Docker login 29 | - uses: docker/login-action@v2 30 | with: 31 | username: ${{ secrets.DOCKER_USERNAME }} 32 | password: ${{ secrets.DOCKER_PUSH_TOKEN }} 33 | # Build and push docker image 34 | - name: Build docker image 35 | uses: docker/build-push-action@v4 36 | with: 37 | target: release 38 | push: true 39 | tags: peersyst/exrp:${{ env.BRANCH }} 40 | cache-from: type=local,src=/tmp/.buildx-cache 41 | cache-to: type=local,dest=/tmp/.buildx-cache-new 42 | - name: Move cache 43 | if: always() 44 | run: | 45 | rm -rf /tmp/.buildx-cache 46 | mv /tmp/.buildx-cache-new /tmp/.buildx-cache 47 | -------------------------------------------------------------------------------- /.github/workflows/cosmovisor.yml: -------------------------------------------------------------------------------- 1 | name: "Cosmovisor" 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | tag: 7 | description: The docker tag for the publish 8 | required: true 9 | 10 | jobs: 11 | release: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v4 15 | - uses: docker/setup-qemu-action@v2 16 | - uses: docker/setup-buildx-action@v2 17 | # Docker login 18 | - uses: docker/login-action@v2 19 | with: 20 | username: ${{ secrets.DOCKER_USERNAME }} 21 | password: ${{ secrets.DOCKER_PUSH_TOKEN }} 22 | # Build and push docker image 23 | - name: Build docker image 24 | uses: docker/build-push-action@v4 25 | with: 26 | file: tools/cosmovisor/Dockerfile 27 | push: true 28 | tags: | 29 | peersyst/exrp-cosmovisor:${{ github.event.inputs.tag }} 30 | peersyst/exrp-cosmovisor:latest 31 | -------------------------------------------------------------------------------- /.github/workflows/goreleaser.yml: -------------------------------------------------------------------------------- 1 | name: GoReleaser 2 | on: 3 | workflow_dispatch: 4 | inputs: 5 | commit_branch: 6 | description: The branch or the commit sha to push tag to 7 | required: true 8 | workflow_call: 9 | inputs: 10 | commit_branch: 11 | type: string 12 | description: The branch or the commit sha to push tag to 13 | required: true 14 | 15 | jobs: 16 | release: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - name: Free disk space 20 | run: rm -rf /opt/hostedtoolcache 21 | - uses: actions/checkout@v4 22 | with: 23 | ref: ${{ inputs.commit_branch }} 24 | fetch-depth: 0 25 | fetch-tags: true 26 | - uses: docker/setup-qemu-action@v2 27 | - uses: docker/setup-buildx-action@v2 28 | # Build and push docker image 29 | - name: Run go releaser 30 | run: | 31 | docker run --rm -e CGO_ENABLED -e GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} \ 32 | -v /var/run/docker.sock:/var/run/docker.sock -v $PWD:/go/src/exrp -w /go/src/exrp \ 33 | goreleaser/goreleaser-cross:v1.22 release --clean --skip validate -------------------------------------------------------------------------------- /.github/workflows/pull-request.yml: -------------------------------------------------------------------------------- 1 | name: "Pull Request" 2 | 3 | on: 4 | pull_request: 5 | types: [opened, synchronize] 6 | 7 | concurrency: 8 | # Cancel old runs if there is a new commit in the same branch 9 | group: ${{ github.workflow }}-${{ github.ref }} 10 | cancel-in-progress: true 11 | 12 | jobs: 13 | integration: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v2 17 | - uses: docker/setup-qemu-action@v2 18 | - uses: docker/setup-buildx-action@v2 19 | - uses: actions/cache@v3 20 | with: 21 | path: /tmp/.buildx-cache 22 | key: ${{ github.job }}-${{ runner.os }}-${{ github.event.pull_request.number }}-buildx 23 | restore-keys: | 24 | ${{ github.job }}-${{ runner.os }}-${{ github.event.pull_request.number }}-buildx 25 | # Build docker image 26 | - name: Build docker image 27 | uses: docker/build-push-action@v4 28 | with: 29 | target: integration 30 | push: false 31 | cache-from: type=local,src=/tmp/.buildx-cache 32 | cache-to: type=local,dest=/tmp/.buildx-cache-new 33 | - name: Move cache 34 | if: always() 35 | run: | 36 | rm -rf /tmp/.buildx-cache 37 | mv /tmp/.buildx-cache-new /tmp/.buildx-cache -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: 3 | workflow_dispatch: 4 | inputs: 5 | commit_branch: 6 | description: The branch or the commit sha to push tag to 7 | required: true 8 | tag: 9 | description: The tag of the release 10 | required: true 11 | is_latest_release: 12 | description: Is this the latest release 13 | type: boolean 14 | required: true 15 | permissions: 16 | contents: write 17 | jobs: 18 | release: 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: actions/checkout@v4 22 | with: 23 | ref: ${{ github.event.inputs.commit_branch }} 24 | fetch-depth: 0 25 | fetch-tags: true 26 | - uses: docker/setup-qemu-action@v2 27 | - uses: docker/setup-buildx-action@v2 28 | - name: Free disk space 29 | run: rm -rf /opt/hostedtoolcache 30 | # Docker login 31 | - uses: docker/login-action@v2 32 | with: 33 | username: ${{ secrets.DOCKER_USERNAME }} 34 | password: ${{ secrets.DOCKER_PUSH_TOKEN }} 35 | - run: | 36 | TAG=${{ github.event.inputs.tag }} 37 | echo "VERSION=${TAG#v}" >> $GITHUB_ENV 38 | # Build and push docker image 39 | - name: Build docker image 40 | uses: docker/build-push-action@v4 41 | with: 42 | target: release 43 | push: true 44 | build-args: VERSION=${{ env.VERSION }} 45 | tags: | 46 | peersyst/exrp:${{ github.event.inputs.tag }} 47 | ${{ fromJSON('["", "peersyst/exrp:latest"]')[github.event.inputs.is_latest_release == 'true'] }} 48 | - name: Publish the Release 49 | uses: softprops/action-gh-release@v1 50 | with: 51 | tag_name: ${{ github.event.inputs.tag }} 52 | prerelease: steps.check-prerelease.outputs.match == 'true' 53 | target_commitish: ${{ github.event.inputs.commit_branch }} 54 | env: 55 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 56 | goreleaser: 57 | needs: [ release ] 58 | uses: ./.github/workflows/goreleaser.yml 59 | secrets: inherit 60 | with: 61 | commit_branch: ${{ github.event.inputs.commit_branch }} 62 | -------------------------------------------------------------------------------- /.github/workflows/unit-coverage.yml: -------------------------------------------------------------------------------- 1 | name: Coverage 2 | on: 3 | push: 4 | branches: [ main ] 5 | pull_request: 6 | branches: [ '**' ] 7 | jobs: 8 | build: 9 | name: Unit test 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v3 13 | - uses: actions/setup-go@v3 14 | 15 | - name: Generate unit test coverage 16 | run: make coverage-unit 17 | 18 | - name: Check unit test coverage 19 | uses: vladopajic/go-test-coverage@v2 20 | with: 21 | # Configure action using config file (option 1) 22 | config: ./.testcoverage.yml 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | vue/node_modules 2 | vue/dist 3 | build/ 4 | release/ 5 | .idea/ 6 | .vscode/ 7 | .DS_Store 8 | 9 | 10 | .exrpd/ 11 | *.out 12 | *.html 13 | 14 | bin/ -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | run: 2 | tests: true 3 | timeout: 5m 4 | concurrency: 4 5 | 6 | linters: 7 | enable: 8 | - dogsled 9 | - dupl 10 | - errcheck 11 | - goconst 12 | - gocritic 13 | - gofumpt 14 | - revive 15 | - gosec 16 | - gosimple 17 | - govet 18 | - ineffassign 19 | - misspell 20 | - nakedret 21 | - prealloc 22 | - exportloopref 23 | - staticcheck 24 | - stylecheck 25 | - typecheck 26 | - unconvert 27 | - unparam 28 | - unused 29 | - nolintlint 30 | - asciicheck 31 | - exportloopref 32 | - gofumpt 33 | - gomodguard 34 | 35 | linters-settings: 36 | dogsled: 37 | max-blank-identifiers: 3 38 | golint: 39 | min-confidence: 0 40 | maligned: 41 | suggest-new: true 42 | misspell: 43 | locale: US 44 | nolintlint: 45 | allow-unused: false 46 | allow-leading-space: true 47 | require-explanation: false 48 | require-specific: false 49 | gofumpt: 50 | lang-version: "1.22" 51 | gomodguard: 52 | blocked: 53 | versions: # List of blocked module version constraints 54 | - https://github.com/etcd-io/etcd: # Blocked module with version constraint 55 | version: ">= 3.4.10 || ~3.3.23" # Version constraint, see https://github.com/Masterminds/semver#basic-comparisons 56 | reason: "CVE-2020-15114; CVE-2020-15136; CVE-2020-15115" # Reason why the version constraint exists. (Optional) 57 | - https://github.com/dgrijalva/jwt-go: # Blocked module with version constraint 58 | version: ">= 4.0.0-preview1" # Version constraint, see https://github.com/Masterminds/semver#basic-comparisons 59 | reason: "CVE-2020-26160" # Reason why the version constraint exists. (Optional) 60 | -------------------------------------------------------------------------------- /.goreleaser.yml: -------------------------------------------------------------------------------- 1 | before: 2 | hooks: 3 | - go mod download 4 | 5 | builds: 6 | - id: "exrpd-darwin-amd64" 7 | main: ./cmd/exrpd 8 | binary: bin/exrpd 9 | env: 10 | - CGO_ENABLED=1 11 | - CC=o64-clang 12 | - CXX=o64-clang++ 13 | goos: 14 | - darwin 15 | goarch: 16 | - amd64 17 | flags: 18 | - -tags=cgo 19 | ldflags: 20 | - -s -w -X github.com/cosmos/cosmos-sdk/version.Name=exrp -X github.com/cosmos/cosmos-sdk/version.AppName=exrpd -X github.com/cosmos/cosmos-sdk/version.Version={{.Version}} -X github.com/cosmos/cosmos-sdk/version.Commit={{.Commit}} 21 | - id: "exrpd-darwin-arm64" 22 | main: ./cmd/exrpd 23 | binary: bin/exrpd 24 | env: 25 | - CGO_ENABLED=1 26 | - CC=oa64-clang 27 | - CXX=oa64-clang++ 28 | goos: 29 | - darwin 30 | goarch: 31 | - arm64 32 | flags: 33 | - -tags=cgo 34 | ldflags: 35 | - -s -w -X github.com/cosmos/cosmos-sdk/version.Name=exrp -X github.com/cosmos/cosmos-sdk/version.AppName=exrpd -X github.com/cosmos/cosmos-sdk/version.Version={{.Version}} -X github.com/cosmos/cosmos-sdk/version.Commit={{.Commit}} 36 | - id: "exrpd-linux-amd64" 37 | main: ./cmd/exrpd 38 | binary: bin/exrpd 39 | env: 40 | - CGO_ENABLED=1 41 | - CC=gcc 42 | - CXX=g++ 43 | goos: 44 | - linux 45 | goarch: 46 | - amd64 47 | flags: 48 | - -tags=cgo 49 | ldflags: 50 | - -s -w -X github.com/cosmos/cosmos-sdk/version.Name=exrp -X github.com/cosmos/cosmos-sdk/version.AppName=exrpd -X github.com/cosmos/cosmos-sdk/version.Version={{.Version}} -X github.com/cosmos/cosmos-sdk/version.Commit={{.Commit}} 51 | - id: "exrpd-linux-arm64" 52 | main: ./cmd/exrpd 53 | binary: bin/exrpd 54 | env: 55 | - CGO_ENABLED=1 56 | - CC=aarch64-linux-gnu-gcc 57 | - CXX=aarch64-linux-gnu-g++ 58 | goos: 59 | - linux 60 | goarch: 61 | - arm64 62 | flags: 63 | - -tags=cgo 64 | ldflags: 65 | - -s -w -X github.com/cosmos/cosmos-sdk/version.Name=exrp -X github.com/cosmos/cosmos-sdk/version.AppName=exrpd -X github.com/cosmos/cosmos-sdk/version.Version={{.Version}} -X github.com/cosmos/cosmos-sdk/version.Commit={{.Commit}} 66 | - id: "exrpd-windows" 67 | main: ./cmd/exrpd 68 | binary: bin/exrpd 69 | env: 70 | - CGO_ENABLED=1 71 | - CC=x86_64-w64-mingw32-gcc 72 | - CXX=x86_64-w64-mingw32-g++ 73 | goos: 74 | - windows 75 | goarch: 76 | - amd64 77 | flags: 78 | - -tags=cgo 79 | - -buildmode=exe 80 | ldflags: 81 | - -s -w -X github.com/cosmos/cosmos-sdk/version.Name=exrp -X github.com/cosmos/cosmos-sdk/version.AppName=exrpd -X github.com/cosmos/cosmos-sdk/version.Version={{.Version}} -X github.com/cosmos/cosmos-sdk/version.Commit={{.Commit}} 82 | 83 | archives: 84 | - name_template: '{{ .ProjectName }}_{{ .Version }}_{{- title .Os }}_{{ .Arch }}' 85 | format_overrides: 86 | - goos: windows 87 | format: zip 88 | builds: 89 | - exrpd-darwin-amd64 90 | - exrpd-darwin-arm64 91 | - exrpd-windows 92 | - exrpd-linux-amd64 93 | - exrpd-linux-arm64 94 | 95 | checksum: 96 | name_template: 'checksums.txt' -------------------------------------------------------------------------------- /.testcoverage.yml: -------------------------------------------------------------------------------- 1 | # (mandatory) 2 | # Path to coverage profile file (output of `go test -coverprofile` command). 3 | # 4 | # For cases where there are many coverage profiles, such as when running 5 | # unit tests and integration tests separately, you can combine all those 6 | # profiles into one. In this case, the profile should have a comma-separated list 7 | # of profile files, e.g., 'cover_unit.out,cover_integration.out'. 8 | profile: coverage_unit.out 9 | 10 | # (optional; but recommended to set) 11 | # When specified reported file paths will not contain local prefix in the output. 12 | local-prefix: "github.com/xrplevm/node" 13 | 14 | # Holds coverage thresholds percentages, values should be in range [0-100]. 15 | threshold: 16 | # (optional; default 0) 17 | # Minimum overall project coverage percentage required. 18 | total: 70 19 | 20 | # Holds regexp rules which will override thresholds for matched files or packages 21 | # using their paths. 22 | # 23 | # First rule from this list that matches file or package is going to apply 24 | # new threshold to it. If project has multiple rules that match same path, 25 | # override rules should be listed in order from specific to more general rules. 26 | # override: 27 | # Increase coverage threshold to 100% for `foo` package 28 | # (default is 80, as configured above in this example). 29 | # - path: ^pkg/lib/foo$ 30 | # threshold: 100 31 | 32 | # Holds regexp rules which will exclude matched files or packages 33 | # from coverage statistics. 34 | exclude: 35 | # Exclude files or packages matching their paths 36 | paths: 37 | - cmd 38 | - docs 39 | - app 40 | - tools 41 | - tests 42 | - \.pb\.go$ 43 | - \.pb\.gw\.go$ 44 | - module.go$ 45 | - \/testutil\/ 46 | - \/client\/ 47 | 48 | # File name of go-test-coverage breakdown file, which can be used to 49 | # analyze coverage difference. 50 | breakdown-file-name: '' 51 | 52 | diff: 53 | # File name of go-test-coverage breakdown file which will be used to 54 | # report coverage difference. 55 | base-breakdown-file-name: '' -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.22.11 AS base 2 | USER root 3 | RUN apt update && \ 4 | apt-get install -y \ 5 | build-essential \ 6 | ca-certificates 7 | WORKDIR /app 8 | COPY . . 9 | RUN make install 10 | 11 | 12 | FROM base AS build 13 | ARG VERSION=0.0.0 14 | RUN make build 15 | 16 | 17 | FROM base AS integration 18 | RUN make lint 19 | # Unit tests 20 | RUN make test-poa 21 | # Integration tests 22 | RUN make test-integration 23 | RUN make test-upgrade 24 | # Simulation tests 25 | RUN make test-sim-benchmark-simulation 26 | RUN make test-sim-full-app-fast 27 | 28 | RUN touch /test.lock 29 | 30 | FROM golang:1.22.11 AS release 31 | WORKDIR / 32 | COPY --from=integration /test.lock /test.lock 33 | COPY --from=build /app/bin/exrpd /usr/bin/exrpd 34 | ENTRYPOINT ["/bin/sh", "-ec"] 35 | CMD ["exrpd"] -------------------------------------------------------------------------------- /app/ante.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/client" 5 | "github.com/cosmos/cosmos-sdk/codec" 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" 8 | "github.com/evmos/evmos/v20/app/ante" 9 | ethante "github.com/evmos/evmos/v20/app/ante/evm" 10 | etherminttypes "github.com/evmos/evmos/v20/types" 11 | poaante "github.com/xrplevm/node/v8/x/poa/ante" 12 | ) 13 | 14 | type AnteHandlerOptions ante.HandlerOptions 15 | 16 | func NewAnteHandlerOptionsFromApp(app *App, txConfig client.TxConfig, maxGasWanted uint64) *AnteHandlerOptions { 17 | return &AnteHandlerOptions{ 18 | Cdc: app.appCodec, 19 | AccountKeeper: app.AccountKeeper, 20 | BankKeeper: app.BankKeeper, 21 | ExtensionOptionChecker: etherminttypes.HasDynamicFeeExtensionOption, 22 | EvmKeeper: app.EvmKeeper, 23 | FeegrantKeeper: app.FeeGrantKeeper, 24 | IBCKeeper: app.IBCKeeper, 25 | FeeMarketKeeper: app.FeeMarketKeeper, 26 | SignModeHandler: txConfig.SignModeHandler(), 27 | SigGasConsumer: ante.SigVerificationGasConsumer, 28 | MaxTxGasWanted: maxGasWanted, 29 | TxFeeChecker: ethante.NewDynamicFeeChecker(app.EvmKeeper), 30 | StakingKeeper: app.StakingKeeper, 31 | DistributionKeeper: app.DistrKeeper, 32 | ExtraDecorator: poaante.NewPoaDecorator(), 33 | AuthzDisabledMsgTypes: []string{ 34 | sdk.MsgTypeURL(&stakingtypes.MsgUndelegate{}), 35 | sdk.MsgTypeURL(&stakingtypes.MsgBeginRedelegate{}), 36 | sdk.MsgTypeURL(&stakingtypes.MsgCancelUnbondingDelegation{}), 37 | sdk.MsgTypeURL(&stakingtypes.MsgDelegate{}), 38 | }, 39 | } 40 | } 41 | 42 | func (aa *AnteHandlerOptions) Validate() error { 43 | return (*ante.HandlerOptions)(aa).Validate() 44 | } 45 | 46 | func (aa *AnteHandlerOptions) Options() ante.HandlerOptions { 47 | return ante.HandlerOptions(*aa) 48 | } 49 | 50 | func (aa *AnteHandlerOptions) WithCodec(cdc codec.BinaryCodec) *AnteHandlerOptions { 51 | aa.Cdc = cdc 52 | return aa 53 | } 54 | 55 | func (aa *AnteHandlerOptions) WithMaxTxGasWanted(maxTxGasWanted uint64) *AnteHandlerOptions { 56 | aa.MaxTxGasWanted = maxTxGasWanted 57 | return aa 58 | } 59 | -------------------------------------------------------------------------------- /app/encoding.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | // MakeEncodingConfig creates an EncodingConfig for testing 4 | // func MakeEncodingConfig() params.EncodingConfig { 5 | // return evmenc.MakeConfig(ModuleBasics) 6 | // } 7 | -------------------------------------------------------------------------------- /app/genesis.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "encoding/json" 5 | 6 | sdkmath "cosmossdk.io/math" 7 | 8 | feemarkettypes "github.com/evmos/evmos/v20/x/feemarket/types" 9 | ) 10 | 11 | // GenesisState The genesis state of the blockchain is represented here as a map of raw json 12 | // messages key'd by a identifier string. 13 | // The identifier is used to determine which module genesis information belongs 14 | // to so it may be appropriately routed during init chain. 15 | // Within this application default genesis information is retrieved from 16 | // the ModuleBasicManager which populates json from each BasicModule 17 | // object provided to it during init. 18 | type GenesisState map[string]json.RawMessage 19 | 20 | // NewDefaultGenesisState generates the default state for the application. 21 | func NewDefaultGenesisState(app *App) GenesisState { 22 | genState := app.BasicModuleManager.DefaultGenesis(app.AppCodec()) 23 | // Set default feemarket params 24 | var feeMarketState feemarkettypes.GenesisState 25 | app.cdc.MustUnmarshalJSON(genState[feemarkettypes.ModuleName], &feeMarketState) 26 | feeMarketState.Params.NoBaseFee = true 27 | feeMarketState.Params.BaseFee = sdkmath.NewInt(0) 28 | genState[feemarkettypes.ModuleName] = app.cdc.MustMarshalJSON(&feeMarketState) 29 | 30 | return genState 31 | } 32 | -------------------------------------------------------------------------------- /app/precompiles.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "fmt" 5 | 6 | govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" 7 | 8 | authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper" 9 | bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" 10 | distributionkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" 11 | channelkeeper "github.com/cosmos/ibc-go/v8/modules/core/04-channel/keeper" 12 | "github.com/ethereum/go-ethereum/common" 13 | bankprecompile "github.com/evmos/evmos/v20/precompiles/bank" 14 | "github.com/evmos/evmos/v20/precompiles/bech32" 15 | distprecompile "github.com/evmos/evmos/v20/precompiles/distribution" 16 | govprecompile "github.com/evmos/evmos/v20/precompiles/gov" 17 | ics20precompile "github.com/evmos/evmos/v20/precompiles/ics20" 18 | "github.com/evmos/evmos/v20/precompiles/p256" 19 | stakingprecompile "github.com/evmos/evmos/v20/precompiles/staking" 20 | erc20Keeper "github.com/evmos/evmos/v20/x/erc20/keeper" 21 | "github.com/evmos/evmos/v20/x/evm/core/vm" 22 | transferkeeper "github.com/evmos/evmos/v20/x/ibc/transfer/keeper" 23 | stakingkeeper "github.com/evmos/evmos/v20/x/staking/keeper" 24 | "golang.org/x/exp/maps" 25 | ) 26 | 27 | const bech32PrecompileBaseGas = 6_000 28 | 29 | // AvailableStaticPrecompiles returns the list of all available static precompiled contracts. 30 | // NOTE: this should only be used during initialization of the Keeper. 31 | func NewAvailableStaticPrecompiles( 32 | stakingKeeper stakingkeeper.Keeper, 33 | distributionKeeper distributionkeeper.Keeper, 34 | bankKeeper bankkeeper.Keeper, 35 | erc20Keeper erc20Keeper.Keeper, 36 | authzKeeper authzkeeper.Keeper, 37 | transferKeeper transferkeeper.Keeper, 38 | channelKeeper channelkeeper.Keeper, 39 | govKeeper govkeeper.Keeper, 40 | ) map[common.Address]vm.PrecompiledContract { 41 | // Clone the mapping from the latest EVM fork. 42 | precompiles := maps.Clone(vm.PrecompiledContractsBerlin) 43 | 44 | // secp256r1 precompile as per EIP-7212 45 | p256Precompile := &p256.Precompile{} 46 | 47 | bech32Precompile, err := bech32.NewPrecompile(bech32PrecompileBaseGas) 48 | if err != nil { 49 | panic(fmt.Errorf("failed to instantiate bech32 precompile: %w", err)) 50 | } 51 | 52 | stakingPrecompile, err := stakingprecompile.NewPrecompile(stakingKeeper, authzKeeper) 53 | if err != nil { 54 | panic(fmt.Errorf("failed to instantiate staking precompile: %w", err)) 55 | } 56 | 57 | distributionPrecompile, err := distprecompile.NewPrecompile( 58 | distributionKeeper, 59 | stakingKeeper, 60 | authzKeeper, 61 | ) 62 | if err != nil { 63 | panic(fmt.Errorf("failed to instantiate distribution precompile: %w", err)) 64 | } 65 | 66 | ibcTransferPrecompile, err := ics20precompile.NewPrecompile( 67 | stakingKeeper, 68 | transferKeeper, 69 | channelKeeper, 70 | authzKeeper, 71 | ) 72 | if err != nil { 73 | panic(fmt.Errorf("failed to instantiate ICS20 precompile: %w", err)) 74 | } 75 | 76 | bankPrecompile, err := bankprecompile.NewPrecompile(bankKeeper, erc20Keeper) 77 | if err != nil { 78 | panic(fmt.Errorf("failed to instantiate bank precompile: %w", err)) 79 | } 80 | 81 | govPrecompile, err := govprecompile.NewPrecompile(govKeeper, authzKeeper) 82 | if err != nil { 83 | panic(fmt.Errorf("failed to instantiate gov precompile: %w", err)) 84 | } 85 | 86 | // Stateless precompiles 87 | precompiles[bech32Precompile.Address()] = bech32Precompile 88 | precompiles[p256Precompile.Address()] = p256Precompile 89 | 90 | // Stateful precompiles 91 | precompiles[stakingPrecompile.Address()] = stakingPrecompile 92 | precompiles[distributionPrecompile.Address()] = distributionPrecompile 93 | precompiles[ibcTransferPrecompile.Address()] = ibcTransferPrecompile 94 | precompiles[bankPrecompile.Address()] = bankPrecompile 95 | precompiles[govPrecompile.Address()] = govPrecompile 96 | return precompiles 97 | } 98 | -------------------------------------------------------------------------------- /app/simulation_test.go: -------------------------------------------------------------------------------- 1 | package app_test 2 | 3 | import ( 4 | "math/rand" 5 | "os" 6 | "testing" 7 | "time" 8 | 9 | "cosmossdk.io/log" 10 | 11 | "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" 12 | sdk "github.com/cosmos/cosmos-sdk/types" 13 | "github.com/evmos/evmos/v20/crypto/ethsecp256k1" 14 | 15 | dbm "github.com/cosmos/cosmos-db" 16 | "github.com/cosmos/cosmos-sdk/baseapp" 17 | "github.com/cosmos/cosmos-sdk/client/flags" 18 | "github.com/cosmos/cosmos-sdk/server" 19 | simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" 20 | simulationtypes "github.com/cosmos/cosmos-sdk/types/simulation" 21 | "github.com/cosmos/cosmos-sdk/x/simulation" 22 | simcli "github.com/cosmos/cosmos-sdk/x/simulation/client/cli" 23 | "github.com/evmos/evmos/v20/app/ante" 24 | "github.com/stretchr/testify/require" 25 | "github.com/xrplevm/node/v8/app" 26 | ) 27 | 28 | func init() { 29 | simcli.GetSimulatorFlags() 30 | } 31 | 32 | const SimAppChainID = "simulation_777-1" 33 | 34 | // NewSimApp disable feemarket on native tx, otherwise the cosmos-sdk simulation tests will fail. 35 | func NewSimApp(logger log.Logger, db dbm.DB, config simulationtypes.Config) (*app.App, error) { 36 | appOptions := make(simtestutil.AppOptionsMap, 0) 37 | appOptions[flags.FlagHome] = app.DefaultNodeHome 38 | appOptions[server.FlagInvCheckPeriod] = simcli.FlagPeriodValue 39 | 40 | bApp := app.New( 41 | logger, 42 | db, 43 | nil, 44 | false, 45 | map[int64]bool{}, 46 | app.DefaultNodeHome, 47 | simcli.FlagPeriodValue, 48 | appOptions, 49 | baseapp.SetChainID(config.ChainID), 50 | ) 51 | handlerOpts := app.NewAnteHandlerOptionsFromApp(bApp, bApp.GetTxConfig(), 0) 52 | if err := handlerOpts.Validate(); err != nil { 53 | panic(err) 54 | } 55 | bApp.SetAnteHandler(ante.NewAnteHandler(handlerOpts.Options())) 56 | 57 | if err := bApp.LoadLatestVersion(); err != nil { 58 | return nil, err 59 | } 60 | return bApp, nil 61 | } 62 | 63 | // RandomAccounts generates n random accounts 64 | func RandomAccounts(r *rand.Rand, n int) []simulationtypes.Account { 65 | accs := make([]simulationtypes.Account, n) 66 | 67 | for i := 0; i < n; i++ { 68 | // don't need that much entropy for simulation 69 | privkeySeed := make([]byte, 32) 70 | r.Read(privkeySeed) 71 | 72 | accs[i].PrivKey = ðsecp256k1.PrivKey{Key: privkeySeed} 73 | accs[i].PubKey = accs[i].PrivKey.PubKey() 74 | accs[i].Address = sdk.AccAddress(accs[i].PubKey.Address()) 75 | 76 | accs[i].ConsKey = ed25519.GenPrivKeyFromSecret(privkeySeed) 77 | } 78 | 79 | return accs 80 | } 81 | 82 | // BenchmarkSimulation run the chain simulation 83 | // Running using starport command: 84 | // `ignite chain simulate -v --numBlocks 200 --blockSize 50` 85 | // Running as go benchmark test: 86 | // `go test -benchmem -run=^$ -bench ^BenchmarkSimulation ./app -NumBlocks=200 -BlockSize 50 -Commit=true -Verbose=true -Enabled=true` 87 | // 88 | //nolint:dupl 89 | func BenchmarkSimulation(b *testing.B) { 90 | simcli.FlagSeedValue = time.Now().Unix() 91 | simcli.FlagVerboseValue = false 92 | simcli.FlagCommitValue = true 93 | simcli.FlagEnabledValue = true 94 | 95 | config := simcli.NewConfigFromFlags() 96 | config.ChainID = SimAppChainID 97 | db, dir, logger, _, err := simtestutil.SetupSimulation( 98 | config, 99 | "leveldb-bApp-sim", 100 | "Simulation", 101 | simcli.FlagVerboseValue, 102 | simcli.FlagEnabledValue, 103 | ) 104 | 105 | require.NoError(b, err, "simulation setup failed") 106 | 107 | config.ChainID = SimAppChainID 108 | 109 | b.Cleanup(func() { 110 | require.NoError(b, db.Close()) 111 | require.NoError(b, os.RemoveAll(dir)) 112 | }) 113 | 114 | bApp, _ := NewSimApp(logger, db, config) 115 | 116 | // Run randomized simulations 117 | _, simParams, simErr := simulation.SimulateFromSeed( 118 | b, 119 | os.Stdout, 120 | bApp.BaseApp, 121 | simtestutil.AppStateFn( 122 | bApp.AppCodec(), 123 | bApp.SimulationManager(), 124 | app.NewDefaultGenesisState(bApp), 125 | ), 126 | RandomAccounts, 127 | simtestutil.SimulationOperations(bApp, bApp.AppCodec(), config), 128 | bApp.ModuleAccountAddrs(), 129 | config, 130 | bApp.AppCodec(), 131 | ) 132 | 133 | // export state and simParams before the simulation error is checked 134 | err = simtestutil.CheckExportSimulation(bApp, config, simParams) 135 | require.NoError(b, err) 136 | require.NoError(b, simErr) 137 | 138 | if config.Commit { 139 | simtestutil.PrintStats(db) 140 | } 141 | } 142 | 143 | //nolint:dupl 144 | func TestFullAppSimulation(t *testing.T) { 145 | simcli.FlagSeedValue = time.Now().Unix() 146 | simcli.FlagVerboseValue = false 147 | simcli.FlagCommitValue = true 148 | simcli.FlagEnabledValue = true 149 | 150 | config := simcli.NewConfigFromFlags() 151 | config.ChainID = SimAppChainID 152 | db, dir, logger, _, err := simtestutil.SetupSimulation( 153 | config, 154 | "leveldb-bApp-sim", 155 | "Simulation", 156 | simcli.FlagVerboseValue, 157 | simcli.FlagEnabledValue, 158 | ) 159 | 160 | require.NoError(t, err, "simulation setup failed") 161 | 162 | config.ChainID = SimAppChainID 163 | 164 | t.Cleanup(func() { 165 | require.NoError(t, db.Close()) 166 | require.NoError(t, os.RemoveAll(dir)) 167 | }) 168 | 169 | bApp, _ := NewSimApp(logger, db, config) 170 | 171 | // Run randomized simulations 172 | _, simParams, simErr := simulation.SimulateFromSeed( 173 | t, 174 | os.Stdout, 175 | bApp.BaseApp, 176 | simtestutil.AppStateFn( 177 | bApp.AppCodec(), 178 | bApp.SimulationManager(), 179 | app.NewDefaultGenesisState(bApp), 180 | ), 181 | RandomAccounts, 182 | simtestutil.SimulationOperations(bApp, bApp.AppCodec(), config), 183 | bApp.ModuleAccountAddrs(), 184 | config, 185 | bApp.AppCodec(), 186 | ) 187 | 188 | // export state and simParams before the simulation error is checked 189 | err = simtestutil.CheckExportSimulation(bApp, config, simParams) 190 | require.NoError(t, err) 191 | require.NoError(t, simErr) 192 | 193 | if config.Commit { 194 | simtestutil.PrintStats(db) 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /app/upgrades.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "fmt" 5 | 6 | storetypes "cosmossdk.io/store/types" 7 | upgradetypes "cosmossdk.io/x/upgrade/types" 8 | authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 9 | govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" 10 | ratelimittypes "github.com/cosmos/ibc-apps/modules/rate-limiting/v8/types" 11 | icahosttypes "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/host/types" 12 | v4 "github.com/xrplevm/node/v8/app/upgrades/v4" 13 | v5 "github.com/xrplevm/node/v8/app/upgrades/v5" 14 | v6 "github.com/xrplevm/node/v8/app/upgrades/v6" 15 | v7 "github.com/xrplevm/node/v8/app/upgrades/v7" 16 | v8 "github.com/xrplevm/node/v8/app/upgrades/v8" 17 | ) 18 | 19 | func (app *App) setupUpgradeHandlers() { 20 | authAddr := authtypes.NewModuleAddress(govtypes.ModuleName).String() 21 | app.UpgradeKeeper.SetUpgradeHandler( 22 | v4.UpgradeName, 23 | v4.CreateUpgradeHandler( 24 | app.mm, 25 | app.configurator, 26 | app.appCodec, 27 | app.GetKey("upgrade"), 28 | app.ConsensusParamsKeeper, 29 | authAddr, 30 | app.EvmKeeper, 31 | app.Erc20Keeper, 32 | app.GovKeeper, 33 | ), 34 | ) 35 | app.UpgradeKeeper.SetUpgradeHandler( 36 | v5.UpgradeName, 37 | v5.CreateUpgradeHandler( 38 | app.mm, 39 | app.configurator, 40 | ), 41 | ) 42 | app.UpgradeKeeper.SetUpgradeHandler( 43 | v6.UpgradeName, 44 | v6.CreateUpgradeHandler( 45 | app.mm, 46 | app.configurator, 47 | ), 48 | ) 49 | app.UpgradeKeeper.SetUpgradeHandler( 50 | v7.UpgradeName, 51 | v7.CreateUpgradeHandler( 52 | app.mm, 53 | app.configurator, 54 | ), 55 | ) 56 | app.UpgradeKeeper.SetUpgradeHandler( 57 | v8.UpgradeName, 58 | v8.CreateUpgradeHandler( 59 | app.mm, 60 | app.configurator, 61 | ), 62 | ) 63 | 64 | // When a planned update height is reached, the old binary will panic 65 | // writing on disk the height and name of the update that triggered it 66 | // This will read that value, and execute the preparations for the upgrade. 67 | upgradeInfo, err := app.UpgradeKeeper.ReadUpgradeInfoFromDisk() 68 | if err != nil { 69 | panic(fmt.Errorf("failed to read upgrade info from disk: %w", err)) 70 | } 71 | 72 | if app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) { 73 | return 74 | } 75 | 76 | var storeUpgrades *storetypes.StoreUpgrades 77 | 78 | switch upgradeInfo.Name { 79 | case v4.UpgradeName: 80 | storeUpgrades = &storetypes.StoreUpgrades{ 81 | Added: []string{ 82 | icahosttypes.StoreKey, 83 | ratelimittypes.ModuleName, 84 | }, 85 | Deleted: []string{}, 86 | } 87 | case v5.UpgradeName, v6.UpgradeName: 88 | // No store upgrades for v5 89 | storeUpgrades = &storetypes.StoreUpgrades{} 90 | } 91 | 92 | if storeUpgrades != nil { 93 | // configure store loader that checks if version == upgradeHeight and applies store upgrades 94 | app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, storeUpgrades)) 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /app/upgrades/v4/constants.go: -------------------------------------------------------------------------------- 1 | package v4 2 | 3 | const ( 4 | // UpgradeName is the shared upgrade plan name for mainnet 5 | UpgradeName = "v4.0.0" 6 | ) 7 | -------------------------------------------------------------------------------- /app/upgrades/v4/upgrades.go: -------------------------------------------------------------------------------- 1 | package v4 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | 7 | "cosmossdk.io/log" 8 | storetypes "cosmossdk.io/store/types" 9 | upgradetypes "cosmossdk.io/x/upgrade/types" 10 | 11 | "github.com/cosmos/cosmos-sdk/codec" 12 | "github.com/cosmos/cosmos-sdk/runtime" 13 | sdk "github.com/cosmos/cosmos-sdk/types" 14 | "github.com/cosmos/cosmos-sdk/types/module" 15 | consensusparamskeeper "github.com/cosmos/cosmos-sdk/x/consensus/keeper" 16 | govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" 17 | govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" 18 | erc20keeper "github.com/evmos/evmos/v20/x/erc20/keeper" 19 | erc20types "github.com/evmos/evmos/v20/x/erc20/types" 20 | evmkeeper "github.com/evmos/evmos/v20/x/evm/keeper" 21 | "github.com/evmos/evmos/v20/x/evm/types" 22 | ) 23 | 24 | const ( 25 | XrpAddress = "0xD4949664cD82660AaE99bEdc034a0deA8A0bd517" 26 | XrpOwnerAddress = "ethm1zrxl239wa6ad5xge3gs68rt98227xgnjq0xyw2" 27 | ) 28 | 29 | // CreateUpgradeHandler creates an SDK upgrade handler for v13 30 | func CreateUpgradeHandler( 31 | mm *module.Manager, 32 | configurator module.Configurator, 33 | cdc codec.Codec, 34 | upgradeKey *storetypes.KVStoreKey, 35 | consensusParamsKeeper consensusparamskeeper.Keeper, 36 | authAddr string, 37 | ek *evmkeeper.Keeper, 38 | erc20k erc20keeper.Keeper, 39 | gk govkeeper.Keeper, 40 | ) upgradetypes.UpgradeHandler { 41 | return func(c context.Context, _ upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) { 42 | ctx := sdk.UnwrapSDKContext(c) 43 | logger := ctx.Logger().With("upgrade", UpgradeName) 44 | 45 | // Fix previous consensusparams upgrade 46 | logger.Info("Fixing previous consensusparams upgrade...") 47 | storesvc := runtime.NewKVStoreService(upgradeKey) 48 | consensuskeeper := consensusparamskeeper.NewKeeper( 49 | cdc, 50 | storesvc, 51 | authAddr, 52 | runtime.EventService{}, 53 | ) 54 | consensusParams, err := consensuskeeper.ParamsStore.Get(ctx) 55 | if err != nil { 56 | return nil, err 57 | } 58 | err = consensusParamsKeeper.ParamsStore.Set(ctx, consensusParams) 59 | if err != nil { 60 | return nil, err 61 | } 62 | 63 | logger.Debug("Enabling gov precompile...") 64 | if err := EnableGovPrecompile(ctx, ek); err != nil { 65 | logger.Error("error while enabling gov precompile", "error", err.Error()) 66 | } 67 | 68 | // run the sdk v0.50 migrations 69 | logger.Debug("Running module migrations...") 70 | vm, err = mm.RunMigrations(ctx, configurator, vm) 71 | if err != nil { 72 | return vm, err 73 | } 74 | 75 | logger.Debug("Updating expedited prop params...") 76 | if err := UpdateExpeditedPropsParams(ctx, gk); err != nil { 77 | logger.Error("error while updating gov params", "error", err.Error()) 78 | } 79 | 80 | logger.Debug("Assigning XRP owner address...") 81 | err = AssignXrpOwnerAddress(ctx, erc20k, sdk.MustAccAddressFromBech32(XrpOwnerAddress)) 82 | if err != nil { 83 | logger.Error("error while assigning XRP owner address", "error", err.Error()) 84 | return vm, err 85 | } 86 | 87 | err = AddCodeToERC20Extensions(ctx, logger, erc20k) 88 | if err != nil { 89 | logger.Error("error while adding code hashes", "error", err.Error()) 90 | return vm, err 91 | } 92 | return vm, nil 93 | } 94 | } 95 | 96 | func EnableGovPrecompile(ctx sdk.Context, ek *evmkeeper.Keeper) error { 97 | // Enable gov precompile 98 | params := ek.GetParams(ctx) 99 | params.ActiveStaticPrecompiles = append(params.ActiveStaticPrecompiles, types.GovPrecompileAddress) 100 | if err := params.Validate(); err != nil { 101 | return err 102 | } 103 | return ek.SetParams(ctx, params) 104 | } 105 | 106 | func UpdateExpeditedPropsParams(ctx sdk.Context, gk govkeeper.Keeper) error { 107 | params, err := gk.Params.Get(ctx) 108 | if err != nil { 109 | return err 110 | } 111 | 112 | // use the same denom as the min deposit denom 113 | // also amount must be greater than MinDeposit amount 114 | denom := params.MinDeposit[0].Denom 115 | expDepAmt := params.ExpeditedMinDeposit[0].Amount 116 | if expDepAmt.LTE(params.MinDeposit[0].Amount) { 117 | expDepAmt = params.MinDeposit[0].Amount.MulRaw(govv1.DefaultMinExpeditedDepositTokensRatio) 118 | } 119 | params.ExpeditedMinDeposit = sdk.NewCoins(sdk.NewCoin(denom, expDepAmt)) 120 | 121 | // if expedited voting period > voting period 122 | // set expedited voting period to be half the voting period 123 | if params.ExpeditedVotingPeriod != nil && params.VotingPeriod != nil && *params.ExpeditedVotingPeriod > *params.VotingPeriod { 124 | expPeriod := *params.VotingPeriod / 2 125 | params.ExpeditedVotingPeriod = &expPeriod 126 | } 127 | 128 | if err := params.ValidateBasic(); err != nil { 129 | return err 130 | } 131 | return gk.Params.Set(ctx, params) 132 | } 133 | 134 | func AssignXrpOwnerAddress(ctx sdk.Context, ek erc20keeper.Keeper, address sdk.AccAddress) error { 135 | tokenPairID := ek.GetTokenPairID(ctx, XrpAddress) 136 | tokenPair, found := ek.GetTokenPair(ctx, tokenPairID) 137 | if !found { 138 | return errors.New("token pair not found") 139 | } 140 | ek.SetTokenPairOwnerAddress(ctx, tokenPair, address.String()) 141 | return nil 142 | } 143 | 144 | // AddCodeToERC20Extensions adds code and code hash to the ERC20 precompiles with the EVM. 145 | func AddCodeToERC20Extensions( 146 | ctx sdk.Context, 147 | logger log.Logger, 148 | erc20Keeper erc20keeper.Keeper, 149 | ) (err error) { 150 | logger.Info("Adding code to erc20 extensions...") 151 | 152 | erc20Keeper.IterateTokenPairs(ctx, func(tokenPair erc20types.TokenPair) bool { 153 | logger.Info("Adding code to erc20 extensions", "tokenPair", tokenPair) 154 | err = erc20Keeper.RegisterERC20CodeHash(ctx, tokenPair.GetERC20Contract()) 155 | return err != nil 156 | }) 157 | 158 | logger.Info("Done with erc20 extensions") 159 | return err 160 | } 161 | -------------------------------------------------------------------------------- /app/upgrades/v5/constants.go: -------------------------------------------------------------------------------- 1 | package v5 2 | 3 | const ( 4 | UpgradeName = "v5.0.0" 5 | ) 6 | -------------------------------------------------------------------------------- /app/upgrades/v5/upgrades.go: -------------------------------------------------------------------------------- 1 | package v5 2 | 3 | import ( 4 | "context" 5 | 6 | upgradetypes "cosmossdk.io/x/upgrade/types" 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | "github.com/cosmos/cosmos-sdk/types/module" 9 | ) 10 | 11 | func CreateUpgradeHandler( 12 | mm *module.Manager, 13 | configurator module.Configurator, 14 | ) upgradetypes.UpgradeHandler { 15 | return func(c context.Context, _ upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) { 16 | ctx := sdk.UnwrapSDKContext(c) 17 | logger := ctx.Logger().With("upgrade", UpgradeName) 18 | logger.Info("Running v5 upgrade handler...") 19 | return mm.RunMigrations(ctx, configurator, vm) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/upgrades/v6/constants.go: -------------------------------------------------------------------------------- 1 | package v6 2 | 3 | const ( 4 | UpgradeName = "v6.0.0" 5 | ) 6 | -------------------------------------------------------------------------------- /app/upgrades/v6/upgrades.go: -------------------------------------------------------------------------------- 1 | package v6 2 | 3 | import ( 4 | "context" 5 | 6 | upgradetypes "cosmossdk.io/x/upgrade/types" 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | "github.com/cosmos/cosmos-sdk/types/module" 9 | ) 10 | 11 | func CreateUpgradeHandler( 12 | mm *module.Manager, 13 | configurator module.Configurator, 14 | ) upgradetypes.UpgradeHandler { 15 | return func(c context.Context, _ upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) { 16 | ctx := sdk.UnwrapSDKContext(c) 17 | logger := ctx.Logger().With("upgrade", UpgradeName) 18 | logger.Info("Running v6 upgrade handler...") 19 | return mm.RunMigrations(ctx, configurator, vm) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/upgrades/v7/constants.go: -------------------------------------------------------------------------------- 1 | package v7 2 | 3 | const ( 4 | UpgradeName = "v7.0.0" 5 | ) 6 | -------------------------------------------------------------------------------- /app/upgrades/v7/upgrades.go: -------------------------------------------------------------------------------- 1 | package v7 2 | 3 | import ( 4 | "context" 5 | 6 | upgradetypes "cosmossdk.io/x/upgrade/types" 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | "github.com/cosmos/cosmos-sdk/types/module" 9 | ) 10 | 11 | func CreateUpgradeHandler( 12 | mm *module.Manager, 13 | configurator module.Configurator, 14 | ) upgradetypes.UpgradeHandler { 15 | return func(c context.Context, _ upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) { 16 | ctx := sdk.UnwrapSDKContext(c) 17 | logger := ctx.Logger().With("upgrade", UpgradeName) 18 | logger.Info("Running v7 upgrade handler...") 19 | return mm.RunMigrations(ctx, configurator, vm) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/upgrades/v8/constants.go: -------------------------------------------------------------------------------- 1 | package v8 2 | 3 | const ( 4 | UpgradeName = "v8.0.0" 5 | ) 6 | -------------------------------------------------------------------------------- /app/upgrades/v8/upgrades.go: -------------------------------------------------------------------------------- 1 | package v8 2 | 3 | import ( 4 | "context" 5 | 6 | upgradetypes "cosmossdk.io/x/upgrade/types" 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | "github.com/cosmos/cosmos-sdk/types/module" 9 | ) 10 | 11 | func CreateUpgradeHandler( 12 | mm *module.Manager, 13 | configurator module.Configurator, 14 | ) upgradetypes.UpgradeHandler { 15 | return func(c context.Context, _ upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) { 16 | ctx := sdk.UnwrapSDKContext(c) 17 | logger := ctx.Logger().With("upgrade", UpgradeName) 18 | logger.Info("Running v8 upgrade handler...") 19 | return mm.RunMigrations(ctx, configurator, vm) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/utils.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/types/module" 5 | authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 6 | ) 7 | 8 | // RandomGenesisAccounts defines the default RandomGenesisAccountsFn used on the SDK. 9 | // It creates a slice of BaseAccount, ContinuousVestingAccount and DelayedVestingAccount. 10 | func RandomGenesisAccounts(simState *module.SimulationState) authtypes.GenesisAccounts { 11 | genesisAccs := make(authtypes.GenesisAccounts, len(simState.Accounts)) 12 | for i, acc := range simState.Accounts { 13 | bacc := authtypes.NewBaseAccountWithAddress(acc.Address) 14 | genesisAccs[i] = bacc 15 | } 16 | return genesisAccs 17 | } 18 | -------------------------------------------------------------------------------- /buf.work.yaml: -------------------------------------------------------------------------------- 1 | # This workspace file points to the roots found in your 2 | # previous "buf.yaml" configuration. 3 | version: v1 4 | directories: 5 | - proto 6 | -------------------------------------------------------------------------------- /cmd/exrpd/cmd/config.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | -------------------------------------------------------------------------------- /cmd/exrpd/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "cosmossdk.io/math" 8 | 9 | sdk "github.com/cosmos/cosmos-sdk/types" 10 | ethermint "github.com/evmos/evmos/v20/types" 11 | 12 | svrcmd "github.com/cosmos/cosmos-sdk/server/cmd" 13 | 14 | "github.com/xrplevm/node/v8/app" 15 | "github.com/xrplevm/node/v8/cmd/exrpd/cmd" 16 | ) 17 | 18 | func main() { 19 | initSDKConfig() 20 | registerDenoms() 21 | rootCmd, _ := cmd.NewRootCmd() 22 | if err := svrcmd.Execute(rootCmd, "", app.DefaultNodeHome); err != nil { 23 | fmt.Fprintln(rootCmd.OutOrStderr(), err) 24 | os.Exit(1) 25 | } 26 | } 27 | 28 | func initSDKConfig() { 29 | // Set prefixes 30 | accountPubKeyPrefix := app.AccountAddressPrefix + "pub" 31 | validatorAddressPrefix := app.AccountAddressPrefix + "valoper" 32 | validatorPubKeyPrefix := app.AccountAddressPrefix + "valoperpub" 33 | consNodeAddressPrefix := app.AccountAddressPrefix + "valcons" 34 | consNodePubKeyPrefix := app.AccountAddressPrefix + "valconspub" 35 | 36 | // Set and seal config 37 | config := sdk.GetConfig() 38 | config.SetBech32PrefixForAccount(app.AccountAddressPrefix, accountPubKeyPrefix) 39 | config.SetBech32PrefixForValidator(validatorAddressPrefix, validatorPubKeyPrefix) 40 | config.SetBech32PrefixForConsensusNode(consNodeAddressPrefix, consNodePubKeyPrefix) 41 | config.SetCoinType(app.Bip44CoinType) 42 | config.SetPurpose(sdk.Purpose) // Shared 43 | // config.SetFullFundraiserPath(ethermint.BIP44HDPath) // nolint: staticcheck 44 | config.Seal() 45 | } 46 | 47 | func registerDenoms() { 48 | if err := sdk.RegisterDenom(app.DisplayDenom, math.LegacyOneDec()); err != nil { 49 | panic(err) 50 | } 51 | 52 | if err := sdk.RegisterDenom(app.BaseDenom, math.LegacyNewDecWithPrec(1, ethermint.BaseDenomUnit)); err != nil { 53 | panic(err) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /docs/docs.go: -------------------------------------------------------------------------------- 1 | package docs 2 | 3 | import ( 4 | "embed" 5 | httptemplate "html/template" 6 | "net/http" 7 | 8 | "github.com/gorilla/mux" 9 | ) 10 | 11 | const ( 12 | apiFile = "/static/openapi.yml" 13 | indexFile = "template/index.tpl" 14 | ) 15 | 16 | //go:embed static 17 | var Static embed.FS 18 | 19 | //go:embed template 20 | var template embed.FS 21 | 22 | func RegisterOpenAPIService(appName string, rtr *mux.Router) { 23 | rtr.Handle(apiFile, http.FileServer(http.FS(Static))) 24 | rtr.HandleFunc("/", handler(appName)) 25 | } 26 | 27 | // handler returns an http handler that servers OpenAPI console for an OpenAPI spec at specURL. 28 | func handler(title string) http.HandlerFunc { 29 | t, _ := httptemplate.ParseFS(template, indexFile) 30 | 31 | return func(w http.ResponseWriter, _ *http.Request) { 32 | //nolint:errcheck 33 | t.Execute(w, struct { 34 | Title string 35 | URL string 36 | }{ 37 | title, 38 | apiFile, 39 | }) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /docs/template/index.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{ .Title }} 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 24 | 25 | 26 | Footer 27 | © 2022 GitHub, Inc. 28 | Footer navigation 29 | -------------------------------------------------------------------------------- /proto/buf.gen.gogo.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | plugins: 3 | - name: gocosmos 4 | out: . 5 | opt: plugins=grpc,Mgoogle/protobuf/any.proto=github.com/cosmos/cosmos-sdk/codec/types 6 | - name: grpc-gateway 7 | out: . 8 | opt: logtostderr=true,allow_colon_final_segments=true 9 | -------------------------------------------------------------------------------- /proto/buf.lock: -------------------------------------------------------------------------------- 1 | # Generated by buf. DO NOT EDIT. 2 | version: v1 3 | deps: 4 | - remote: buf.build 5 | owner: cosmos 6 | repository: cosmos-proto 7 | commit: 1935555c206d4afb9e94615dfd0fad31 8 | - remote: buf.build 9 | owner: cosmos 10 | repository: cosmos-sdk 11 | commit: 508e19f5f37549e3a471a2a59b903c00 12 | - remote: buf.build 13 | owner: cosmos 14 | repository: gogo-proto 15 | commit: 34d970b699f84aa382f3c29773a60836 16 | - remote: buf.build 17 | owner: googleapis 18 | repository: googleapis 19 | commit: 783e4b5374fa488ab068d08af9658438 20 | -------------------------------------------------------------------------------- /proto/buf.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | name: buf.build/xrplevm/node 3 | deps: 4 | - buf.build/cosmos/cosmos-sdk 5 | - buf.build/cosmos/cosmos-proto 6 | - buf.build/cosmos/gogo-proto 7 | - buf.build/googleapis/googleapis 8 | lint: 9 | use: 10 | - DEFAULT 11 | - COMMENTS 12 | - FILE_LOWER_SNAKE_CASE 13 | except: 14 | - UNARY_RPC 15 | - COMMENT_FIELD 16 | - SERVICE_SUFFIX 17 | - PACKAGE_VERSION_SUFFIX 18 | - RPC_REQUEST_STANDARD_NAME 19 | - RPC_REQUEST_RESPONSE_UNIQUE 20 | - RPC_RESPONSE_STANDARD_NAME 21 | - RPC_REQUEST_RESPONSE_UNIQUE 22 | - COMMENT_MESSAGE 23 | - ENUM_ZERO_VALUE_SUFFIX 24 | breaking: 25 | use: 26 | - FILE 27 | -------------------------------------------------------------------------------- /proto/poa/genesis.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package poa; 3 | 4 | import "gogoproto/gogo.proto"; 5 | import "poa/params.proto"; 6 | 7 | option go_package = "github.com/xrplevm/node/v8/x/poa/types"; 8 | 9 | // GenesisState defines the poa module's genesis state. 10 | message GenesisState { Params params = 1 [ (gogoproto.nullable) = false ]; } 11 | -------------------------------------------------------------------------------- /proto/poa/params.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package poa; 3 | 4 | option go_package = "github.com/xrplevm/node/v8/x/poa/types"; 5 | 6 | // Params defines the parameters for the module. 7 | message Params {} 8 | -------------------------------------------------------------------------------- /proto/poa/query.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package poa; 3 | 4 | import "gogoproto/gogo.proto"; 5 | import "google/api/annotations.proto"; 6 | import "poa/params.proto"; 7 | 8 | option go_package = "github.com/xrplevm/node/v8/x/poa/types"; 9 | 10 | // Query defines the gRPC querier service. 11 | service Query { 12 | // Parameters queries the parameters of the module. 13 | rpc Params(QueryParamsRequest) returns (QueryParamsResponse) { 14 | option (google.api.http).get = "/exrp/poa/params"; 15 | } 16 | } 17 | 18 | // QueryParamsRequest is request type for the Query/Params RPC method. 19 | message QueryParamsRequest {} 20 | 21 | // QueryParamsResponse is response type for the Query/Params RPC method. 22 | message QueryParamsResponse { 23 | // params holds all the parameters of this module. 24 | Params params = 1 [ (gogoproto.nullable) = false ]; 25 | } -------------------------------------------------------------------------------- /proto/poa/tx.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package poa; 3 | 4 | import "gogoproto/gogo.proto"; 5 | import "cosmos_proto/cosmos.proto"; 6 | import "cosmos/msg/v1/msg.proto"; 7 | import "cosmos/staking/v1beta1/staking.proto"; 8 | import "google/protobuf/any.proto"; 9 | import "amino/amino.proto"; 10 | 11 | option go_package = "github.com/xrplevm/node/v8/x/poa/types"; 12 | 13 | // Msg defines the Msg service. 14 | service Msg { 15 | option (cosmos.msg.v1.service) = true; 16 | 17 | // Adds a new validator into the authority 18 | rpc AddValidator(MsgAddValidator) returns (MsgAddValidatorResponse); 19 | // Removes an existing validator from the authority 20 | rpc RemoveValidator(MsgRemoveValidator) returns (MsgRemoveValidatorResponse); 21 | } 22 | 23 | // MsgAddValidator defines a message for adding a new validator 24 | message MsgAddValidator { 25 | option (cosmos.msg.v1.signer) = "authority"; 26 | 27 | string authority = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; 28 | string validator_address = 2 29 | [ (amino.dont_omitempty) = false, (cosmos_proto.scalar) = "cosmos.AddressString" ]; 30 | cosmos.staking.v1beta1.Description description = 3 31 | [ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; 32 | google.protobuf.Any pubkey = 4 33 | [ (cosmos_proto.accepts_interface) = "cosmos.crypto.PubKey" ]; 34 | } 35 | // MsgAddValidatorResponse defines the response for adding a new validator 36 | message MsgAddValidatorResponse {} 37 | 38 | // MsgRemoveValidator defines a message for removing an existing validator 39 | message MsgRemoveValidator { 40 | option (cosmos.msg.v1.signer) = "authority"; 41 | 42 | string authority = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; 43 | string validator_address = 2 44 | [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; 45 | } 46 | // MsgRemoveValidatorResponse defines the response for removing an existing 47 | // validator 48 | message MsgRemoveValidatorResponse {} 49 | -------------------------------------------------------------------------------- /proto/scripts/protoc-swagger-gen.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eo pipefail 4 | 5 | mkdir -p ./tmp-swagger-gen 6 | cd proto 7 | proto_dirs=$(find ./ -path -prune -o -name '*.proto' -print0 | xargs -0 -n1 dirname | sort | uniq) 8 | for dir in $proto_dirs; do 9 | # generate swagger files (filter query files) 10 | query_file=$(find "${dir}" -maxdepth 1 \( -name 'query.proto' -o -name 'service.proto' \)) 11 | if [[ ! -z "$query_file" ]]; then 12 | buf generate --template buf.gen.swagger.yaml $query_file 13 | fi 14 | done 15 | 16 | cd .. 17 | 18 | # combine swagger files 19 | # uses nodejs package `swagger-combine`. 20 | # all the individual swagger files need to be configured in `config.json` for merging 21 | swagger-combine ./docs/client/config.json -o ./docs/client/swagger-ui/swagger.yaml -f yaml --continueOnConflictingPaths true --includeDefinitions true 22 | 23 | # clean swagger files 24 | rm -rf ./tmp-swagger-gen -------------------------------------------------------------------------------- /proto/scripts/protocgen.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eo pipefail 4 | echo "Generating gogo proto code" 5 | cd proto 6 | proto_dirs=$(find ./ -path -prune -o -name '*.proto' -print0 | xargs -0 -n1 dirname | sort | uniq) 7 | for dir in $proto_dirs; do 8 | for file in $(find "${dir}" -maxdepth 1 -name '*.proto'); do 9 | if grep "option go_package" $file &> /dev/null ; then 10 | buf generate --template buf.gen.gogo.yaml $file 11 | fi 12 | done 13 | done 14 | cd .. 15 | # move proto files to the right places 16 | cp -r proto/github.com/xrplevm/node/v*/* ./ 17 | rm -rf proto/github.com -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | 5 | 6 |
7 |

XRPL EVM Sidechain node

8 |
9 | 10 |
11 | 12 | Version 13 | 14 | 15 | License 16 | 17 | 18 | GoDoc 19 | 20 | 21 | Go report card 22 | 23 |
24 |
25 | 26 | Discord 27 | 28 | 29 | Code Coverage 30 | 31 | 32 | Twitter Follow Peersyst 33 | 34 |
35 | 36 | ## About 37 | 38 | The XRP Ledger Ethereum Virtual Machine (EVM) sidechain is a fast and secure blockchain that brings web3 applications to the XRP Ledger community. 39 | 40 | ## Quick Start 41 | 42 | To learn how the XRPL EVM Sidechain works from a high-level perspective, 43 | go to the [Protocol Overview](https://docs.xrplevm.org/introduction) section of the documentation. 44 | 45 | ## Documentation 46 | 47 | Find all the documentation at [docs.xrplevm.org](https://docs.xrplevm.org). 48 | Head over there and check it out. 49 | 50 | ## Installation 51 | 52 | For prerequisites and detailed build instructions 53 | please read the [Join the EVM Sidechian](https://opensource.ripple.com/docs/evm-sidechain/join-evm-sidechain-devnet/) instructions. 54 | 55 | Or check out the latest [release](https://github.com/xrplevm/node/releases). 56 | 57 | ## Community 58 | 59 | The following chat channels and forums are great spots to ask questions about the XRPL EVM Sidechain: 60 | 61 | - [Peersyst Twitter](https://twitter.com/Peersyst) 62 | - [XRPL EVM Sidechian Discord](https://discord.gg/xrplevm) 63 | 64 | ## Contributing 65 | 66 | Looking for a good place to start contributing? 67 | Check out some 68 | [`good first issues`](https://github.com/xrplevm/node/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22). 69 | 70 | For additional instructions, standards and style guides, please refer to the [Contributing](./CONTRIBUTING.md) document. 71 | -------------------------------------------------------------------------------- /scripts/mockgen.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | mockgen -source=x/poa/types/expected_keepers.go -package testutil -destination=x/poa/testutil/expected_keepers_mock.go 4 | mockgen -source=x/poa/testutil/tx.go -package testutil -destination=x/poa/testutil/tx_mock.go 5 | mockgen -source=x/poa/testutil/keys.go -package testutil -destination=x/poa/testutil/keys_mock.go 6 | mockgen -source=x/poa/testutil/expected_msg_server.go -package testutil -destination=x/poa/testutil/expected_msg_server_mock.go 7 | mockgen -source=x/poa/testutil/staking_hooks.go -package testutil -destination=x/poa/testutil/staking_hooks_mock.go -------------------------------------------------------------------------------- /tests/integration/network.go: -------------------------------------------------------------------------------- 1 | package integration 2 | 3 | import ( 4 | authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 5 | "github.com/cosmos/cosmos-sdk/x/authz" 6 | banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" 7 | distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" 8 | govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1" 9 | slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" 10 | stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" 11 | erc20types "github.com/evmos/evmos/v20/x/erc20/types" 12 | evmtypes "github.com/evmos/evmos/v20/x/evm/types" 13 | feemarkettypes "github.com/evmos/evmos/v20/x/feemarket/types" 14 | commonnetwork "github.com/xrplevm/node/v8/testutil/integration/common/network" 15 | exrpcommon "github.com/xrplevm/node/v8/testutil/integration/exrp/common" 16 | exrpintegration "github.com/xrplevm/node/v8/testutil/integration/exrp/integration" 17 | poatypes "github.com/xrplevm/node/v8/x/poa/types" 18 | ) 19 | 20 | var _ commonnetwork.Network = (*Network)(nil) 21 | 22 | type Network struct { 23 | exrpintegration.IntegrationNetwork 24 | } 25 | 26 | func NewIntegrationNetwork(opts ...exrpcommon.ConfigOption) *Network { 27 | network := exrpintegration.New(opts...) 28 | return &Network{ 29 | IntegrationNetwork: *network, 30 | } 31 | } 32 | 33 | func (n *Network) SetupSdkConfig() { 34 | exrpcommon.SetupSdkConfig() 35 | } 36 | 37 | func (n *Network) GetERC20Client() erc20types.QueryClient { 38 | return exrpcommon.GetERC20Client(n) 39 | } 40 | 41 | func (n *Network) GetEvmClient() evmtypes.QueryClient { 42 | return exrpcommon.GetEvmClient(n) 43 | } 44 | 45 | func (n *Network) GetGovClient() govtypes.QueryClient { 46 | return exrpcommon.GetGovClient(n) 47 | } 48 | 49 | func (n *Network) GetBankClient() banktypes.QueryClient { 50 | return exrpcommon.GetBankClient(n) 51 | } 52 | 53 | func (n *Network) GetFeeMarketClient() feemarkettypes.QueryClient { 54 | return exrpcommon.GetFeeMarketClient(n) 55 | } 56 | 57 | func (n *Network) GetAuthClient() authtypes.QueryClient { 58 | return exrpcommon.GetAuthClient(n) 59 | } 60 | 61 | func (n *Network) GetAuthzClient() authz.QueryClient { 62 | return exrpcommon.GetAuthzClient(n) 63 | } 64 | 65 | func (n *Network) GetStakingClient() stakingtypes.QueryClient { 66 | return exrpcommon.GetStakingClient(n) 67 | } 68 | 69 | func (n *Network) GetSlashingClient() slashingtypes.QueryClient { 70 | return exrpcommon.GetSlashingClient(n) 71 | } 72 | 73 | func (n *Network) GetDistrClient() distrtypes.QueryClient { 74 | return exrpcommon.GetDistrClient(n) 75 | } 76 | 77 | func (n *Network) GetPoaClient() poatypes.QueryClient { 78 | return exrpcommon.GetPoaClient(n) 79 | } 80 | -------------------------------------------------------------------------------- /tests/integration/slashing_test.go: -------------------------------------------------------------------------------- 1 | package integration 2 | 3 | import ( 4 | "time" 5 | 6 | "cosmossdk.io/math" 7 | sdktypes "github.com/cosmos/cosmos-sdk/types" 8 | "github.com/cosmos/cosmos-sdk/types/address" 9 | govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" 10 | slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" 11 | "github.com/stretchr/testify/require" 12 | "github.com/xrplevm/node/v8/testutil/integration/exrp/utils" 13 | ) 14 | 15 | // Slashing tests 16 | 17 | func (s *TestSuite) TestSlashing_ChangeParams() { 18 | tt := []struct { 19 | name string 20 | newParams slashingtypes.Params 21 | expectedError string 22 | }{ 23 | { 24 | name: "change slashing params - invalid slash fraction double sign", 25 | newParams: slashingtypes.NewParams( 26 | 200, 27 | math.LegacyOneDec(), 28 | time.Second, 29 | math.LegacyZeroDec(), 30 | math.LegacyOneDec(), 31 | ), 32 | expectedError: "slash fraction downtime must be zero: 1.000000000000000000", 33 | }, 34 | { 35 | name: "change slashing params - invalid slash fraction downtime", 36 | newParams: slashingtypes.NewParams( 37 | 200, 38 | math.LegacyOneDec(), 39 | time.Second, 40 | math.LegacyOneDec(), 41 | math.LegacyZeroDec(), 42 | ), 43 | expectedError: "slash fraction double sign must be zero: 1.000000000000000000", 44 | }, 45 | { 46 | name: "change slashing params - success", 47 | newParams: slashingtypes.NewParams( 48 | 200, 49 | math.LegacyOneDec(), 50 | time.Second, 51 | math.LegacyZeroDec(), 52 | math.LegacyZeroDec(), 53 | ), 54 | }, 55 | } 56 | 57 | for _, tc := range tt { 58 | s.Run(tc.name, func() { 59 | authority := sdktypes.AccAddress(address.Module("gov")) 60 | msg := &slashingtypes.MsgUpdateParams{ 61 | Authority: authority.String(), 62 | Params: tc.newParams, 63 | } 64 | 65 | proposal, err := utils.SubmitAndAwaitProposalResolution(s.factory, s.Network(), s.keyring.GetKeys(), "test", msg) 66 | require.NoError(s.T(), err) 67 | 68 | if tc.expectedError != "" { 69 | require.Equal(s.T(), govv1.ProposalStatus_PROPOSAL_STATUS_FAILED, proposal.Status) 70 | require.Equal(s.T(), proposal.FailedReason, tc.expectedError) 71 | } else { 72 | require.Equal(s.T(), govv1.ProposalStatus_PROPOSAL_STATUS_PASSED, proposal.Status) 73 | } 74 | }) 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /tests/integration/suite.go: -------------------------------------------------------------------------------- 1 | package integration 2 | 3 | import ( 4 | sdkmath "cosmossdk.io/math" 5 | sdk "github.com/cosmos/cosmos-sdk/types" 6 | evmtypes "github.com/evmos/evmos/v20/x/evm/types" 7 | "github.com/stretchr/testify/suite" 8 | "github.com/xrplevm/node/v8/app" 9 | factory "github.com/xrplevm/node/v8/testutil/integration/common/factory" 10 | "github.com/xrplevm/node/v8/testutil/integration/common/grpc" 11 | "github.com/xrplevm/node/v8/testutil/integration/common/keyring" 12 | exrpcommon "github.com/xrplevm/node/v8/testutil/integration/exrp/common" 13 | ) 14 | 15 | type TestSuite struct { 16 | suite.Suite 17 | 18 | network *Network 19 | keyring keyring.Keyring 20 | factory factory.CoreTxFactory 21 | grpcHandler grpc.Handler 22 | } 23 | 24 | func (s *TestSuite) Network() *Network { 25 | return s.network 26 | } 27 | 28 | func (s *TestSuite) SetupSuite() { 29 | s.network.SetupSdkConfig() 30 | s.Require().Equal(sdk.GetConfig().GetBech32AccountAddrPrefix(), "ethm") 31 | } 32 | 33 | func (s *TestSuite) SetupTest() { 34 | // Check that the network was created successfully 35 | kr := keyring.New(5) 36 | 37 | customGenesis := exrpcommon.CustomGenesisState{} 38 | 39 | evmGen := evmtypes.DefaultGenesisState() 40 | 41 | evmGen.Params.EvmDenom = app.BaseDenom 42 | 43 | customGenesis[evmtypes.ModuleName] = evmGen 44 | 45 | s.network = NewIntegrationNetwork( 46 | exrpcommon.WithPreFundedAccounts(kr.GetAllAccAddrs()...), 47 | exrpcommon.WithAmountOfValidators(5), 48 | exrpcommon.WithCustomGenesis(customGenesis), 49 | exrpcommon.WithBondDenom("apoa"), 50 | exrpcommon.WithMaxValidators(7), 51 | exrpcommon.WithMinDepositAmt(sdkmath.NewInt(1)), 52 | exrpcommon.WithValidatorOperators(kr.GetAllAccAddrs()), 53 | ) 54 | s.Require().NotNil(s.network) 55 | 56 | grpcHandler := grpc.NewIntegrationHandler(s.network) 57 | 58 | s.factory = factory.New(s.network, grpcHandler) 59 | s.keyring = kr 60 | s.grpcHandler = grpcHandler 61 | } 62 | -------------------------------------------------------------------------------- /tests/integration/suite_test.go: -------------------------------------------------------------------------------- 1 | package integration 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/suite" 7 | ) 8 | 9 | func TestIntegrationTestSuite(t *testing.T) { 10 | suite.Run(t, new(TestSuite)) 11 | } 12 | -------------------------------------------------------------------------------- /tests/sim/params.json: -------------------------------------------------------------------------------- 1 | { 2 | "op_weight_msg_create_validator": 0, 3 | "op_weight_msg_edit_validator": 0, 4 | "op_weight_msg_delegate": 0, 5 | "op_weight_msg_begin_redelegate": 0, 6 | "op_weight_msg_undelegate": 0, 7 | "op_weight_msg_cancel_unbonding_delegation": 0, 8 | "op_weight_msg_update_params": 0, 9 | "slash_fraction_double_sign": "0", 10 | "slash_fraction_downtime": "0", 11 | "stake_per_account": "1000000" 12 | } -------------------------------------------------------------------------------- /tests/upgrade/README.md: -------------------------------------------------------------------------------- 1 | # Upgrade testsuite 2 | 3 | ## Download exported state 4 | 5 | ```bash 6 | 7 | ``` 8 | 9 | ## Setup 10 | 11 | Set the `UPGRADE_STATE_FILE` environment variable to the path to the exported state file. 12 | ```bash 13 | UPGRADE_STATE_FILE="path/to/exported-state.json" 14 | ``` -------------------------------------------------------------------------------- /tests/upgrade/network.go: -------------------------------------------------------------------------------- 1 | package testupgrade 2 | 3 | import ( 4 | authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 5 | "github.com/cosmos/cosmos-sdk/x/authz" 6 | banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" 7 | distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" 8 | govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1" 9 | stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" 10 | erc20types "github.com/evmos/evmos/v20/x/erc20/types" 11 | evmtypes "github.com/evmos/evmos/v20/x/evm/types" 12 | feemarkettypes "github.com/evmos/evmos/v20/x/feemarket/types" 13 | commonnetwork "github.com/xrplevm/node/v8/testutil/integration/common/network" 14 | exrpcommon "github.com/xrplevm/node/v8/testutil/integration/exrp/common" 15 | upgradenetwork "github.com/xrplevm/node/v8/testutil/integration/exrp/upgrade" 16 | poatypes "github.com/xrplevm/node/v8/x/poa/types" 17 | ) 18 | 19 | var _ commonnetwork.Network = (*UpgradeTestNetwork)(nil) 20 | 21 | type UpgradeTestNetwork struct { 22 | upgradenetwork.UpgradeIntegrationNetwork 23 | } 24 | 25 | func NewUpgradeTestNetwork(opts ...exrpcommon.ConfigOption) *UpgradeTestNetwork { 26 | network := upgradenetwork.New(opts...) 27 | return &UpgradeTestNetwork{ 28 | UpgradeIntegrationNetwork: *network, 29 | } 30 | } 31 | 32 | func (n *UpgradeTestNetwork) SetupSdkConfig() { 33 | exrpcommon.SetupSdkConfig() 34 | } 35 | 36 | func (n *UpgradeTestNetwork) GetERC20Client() erc20types.QueryClient { 37 | return exrpcommon.GetERC20Client(n) 38 | } 39 | 40 | func (n *UpgradeTestNetwork) GetEvmClient() evmtypes.QueryClient { 41 | return exrpcommon.GetEvmClient(n) 42 | } 43 | 44 | func (n *UpgradeTestNetwork) GetGovClient() govtypes.QueryClient { 45 | return exrpcommon.GetGovClient(n) 46 | } 47 | 48 | func (n *UpgradeTestNetwork) GetBankClient() banktypes.QueryClient { 49 | return exrpcommon.GetBankClient(n) 50 | } 51 | 52 | func (n *UpgradeTestNetwork) GetFeeMarketClient() feemarkettypes.QueryClient { 53 | return exrpcommon.GetFeeMarketClient(n) 54 | } 55 | 56 | func (n *UpgradeTestNetwork) GetAuthClient() authtypes.QueryClient { 57 | return exrpcommon.GetAuthClient(n) 58 | } 59 | 60 | func (n *UpgradeTestNetwork) GetAuthzClient() authz.QueryClient { 61 | return exrpcommon.GetAuthzClient(n) 62 | } 63 | 64 | func (n *UpgradeTestNetwork) GetStakingClient() stakingtypes.QueryClient { 65 | return exrpcommon.GetStakingClient(n) 66 | } 67 | 68 | func (n *UpgradeTestNetwork) GetDistrClient() distrtypes.QueryClient { 69 | return exrpcommon.GetDistrClient(n) 70 | } 71 | 72 | func (n *UpgradeTestNetwork) GetPoaClient() poatypes.QueryClient { 73 | return exrpcommon.GetPoaClient(n) 74 | } 75 | -------------------------------------------------------------------------------- /tests/upgrade/suite.go: -------------------------------------------------------------------------------- 1 | package testupgrade 2 | 3 | import ( 4 | "os" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | "github.com/stretchr/testify/suite" 8 | exrpupgrade "github.com/xrplevm/node/v8/testutil/integration/exrp/upgrade" 9 | ) 10 | 11 | const defaultStateFile = "upgrade-state.json" 12 | 13 | type UpgradeTestSuite struct { 14 | suite.Suite 15 | 16 | network *UpgradeTestNetwork 17 | } 18 | 19 | func (s *UpgradeTestSuite) Network() *UpgradeTestNetwork { 20 | return s.network 21 | } 22 | 23 | func (s *UpgradeTestSuite) SetupTest() { 24 | // Get the state file from the environment variable, or use the default one 25 | stateFile := os.Getenv("UPGRADE_STATE_FILE") 26 | if stateFile == "" { 27 | stateFile = defaultStateFile 28 | } 29 | s.Require().NotEmpty(stateFile) 30 | 31 | // Setup the SDK config 32 | s.network.SetupSdkConfig() 33 | 34 | s.Require().Equal(sdk.GetConfig().GetBech32AccountAddrPrefix(), "ethm") 35 | 36 | // Create the network 37 | s.network = NewUpgradeTestNetwork( 38 | exrpupgrade.WithGenesisFile(stateFile), 39 | ) 40 | 41 | // Check that the network was created successfully 42 | s.Require().NotNil(s.network) 43 | } 44 | -------------------------------------------------------------------------------- /tests/upgrade/suite_test.go: -------------------------------------------------------------------------------- 1 | package testupgrade 2 | 3 | import ( 4 | "testing" 5 | 6 | banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" 7 | stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" 8 | "github.com/stretchr/testify/suite" 9 | "github.com/xrplevm/node/v8/app" 10 | ) 11 | 12 | func TestUpgradeTestSuite(t *testing.T) { 13 | suite.Run(t, new(UpgradeTestSuite)) 14 | } 15 | 16 | func (s *UpgradeTestSuite) TestUpgrade() { 17 | denom := s.network.GetDenom() 18 | s.Require().NotEmpty(denom) 19 | s.Require().Equal(denom, app.BaseDenom) 20 | 21 | balances, err := s.Network().GetBankClient().AllBalances(s.network.GetContext(), &banktypes.QueryAllBalancesRequest{ 22 | Address: "ethm1fl48vsnmsdzcv85q5d2q4z5ajdha8yu3w48d64", 23 | }) 24 | 25 | s.T().Log("balances", balances) 26 | s.Require().NoError(err) 27 | 28 | err = s.network.NextBlock() 29 | s.Require().NoError(err) 30 | 31 | res, err := s.Network().GetStakingClient().Validators(s.network.GetContext(), &stakingtypes.QueryValidatorsRequest{}) 32 | s.Require().NoError(err) 33 | 34 | s.T().Log("validators", len(res.Validators)) 35 | s.Require().Equal(len(res.Validators), 1) 36 | } 37 | -------------------------------------------------------------------------------- /testutil/integration/common/factory/base.go: -------------------------------------------------------------------------------- 1 | // Copyright Tharsis Labs Ltd.(Evmos) 2 | // SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE) 3 | package factory 4 | 5 | import ( 6 | "fmt" 7 | 8 | errorsmod "cosmossdk.io/errors" 9 | abcitypes "github.com/cometbft/cometbft/abci/types" 10 | "github.com/cosmos/cosmos-sdk/client" 11 | cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" 12 | sdktypes "github.com/cosmos/cosmos-sdk/types" 13 | testutiltypes "github.com/cosmos/cosmos-sdk/types/module/testutil" 14 | authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" 15 | "github.com/xrplevm/node/v8/testutil/integration/common/grpc" 16 | "github.com/xrplevm/node/v8/testutil/integration/common/network" 17 | ) 18 | 19 | // BaseTxFactory is the interface that wraps the common methods to build and broadcast transactions 20 | // within cosmos chains 21 | type BaseTxFactory interface { 22 | // BuildCosmosTx builds a Cosmos tx with the provided private key and txArgs 23 | BuildCosmosTx(privKey cryptotypes.PrivKey, txArgs CosmosTxArgs) (authsigning.Tx, error) 24 | // SignCosmosTx signs a Cosmos transaction with the provided 25 | // private key and tx builder 26 | SignCosmosTx(privKey cryptotypes.PrivKey, txBuilder client.TxBuilder) error 27 | // ExecuteCosmosTx builds, signs and broadcasts a Cosmos tx with the provided private key and txArgs 28 | ExecuteCosmosTx(privKey cryptotypes.PrivKey, txArgs CosmosTxArgs) (abcitypes.ExecTxResult, error) 29 | // EncodeTx encodes the provided transaction 30 | EncodeTx(tx sdktypes.Tx) ([]byte, error) 31 | // CommitCosmosTx creates, signs and commits a cosmos tx 32 | // (produces a block with the specified transaction) 33 | CommitCosmosTx(privKey cryptotypes.PrivKey, txArgs CosmosTxArgs) (abcitypes.ExecTxResult, error) 34 | } 35 | 36 | // baseTxFactory is the struct of the basic tx factory 37 | // to build and broadcast transactions. 38 | // This is to simulate the behavior of a real user. 39 | type baseTxFactory struct { 40 | grpcHandler grpc.Handler 41 | network network.Network 42 | ec testutiltypes.TestEncodingConfig 43 | } 44 | 45 | // newBaseTxFactory instantiates a new baseTxFactory 46 | func newBaseTxFactory( 47 | network network.Network, 48 | grpcHandler grpc.Handler, 49 | ) BaseTxFactory { 50 | return &baseTxFactory{ 51 | grpcHandler: grpcHandler, 52 | network: network, 53 | ec: network.GetEncodingConfig(), 54 | } 55 | } 56 | 57 | func (tf *baseTxFactory) BuildCosmosTx(privKey cryptotypes.PrivKey, txArgs CosmosTxArgs) (authsigning.Tx, error) { 58 | txBuilder, err := tf.buildTx(privKey, txArgs) 59 | if err != nil { 60 | return nil, errorsmod.Wrap(err, "failed to build tx") 61 | } 62 | return txBuilder.GetTx(), nil 63 | } 64 | 65 | // ExecuteCosmosTx creates, signs and broadcasts a Cosmos transaction 66 | func (tf *baseTxFactory) ExecuteCosmosTx(privKey cryptotypes.PrivKey, txArgs CosmosTxArgs) (abcitypes.ExecTxResult, error) { 67 | signedTx, err := tf.BuildCosmosTx(privKey, txArgs) 68 | if err != nil { 69 | return abcitypes.ExecTxResult{}, errorsmod.Wrap(err, "failed to build tx") 70 | } 71 | 72 | txBytes, err := tf.EncodeTx(signedTx) 73 | if err != nil { 74 | return abcitypes.ExecTxResult{}, errorsmod.Wrap(err, "failed to encode tx") 75 | } 76 | 77 | return tf.network.BroadcastTxSync(txBytes) 78 | } 79 | 80 | // CommitCosmosTx creates and signs a Cosmos transaction, and then includes it in 81 | // a block and commits the state changes on the chain 82 | func (tf *baseTxFactory) CommitCosmosTx(privKey cryptotypes.PrivKey, txArgs CosmosTxArgs) (abcitypes.ExecTxResult, error) { 83 | signedTx, err := tf.BuildCosmosTx(privKey, txArgs) 84 | if err != nil { 85 | return abcitypes.ExecTxResult{}, errorsmod.Wrap(err, "failed to build tx") 86 | } 87 | 88 | txBytes, err := tf.EncodeTx(signedTx) 89 | if err != nil { 90 | return abcitypes.ExecTxResult{}, errorsmod.Wrap(err, "failed to encode tx") 91 | } 92 | 93 | blockRes, err := tf.network.NextBlockWithTxs(txBytes) 94 | if err != nil { 95 | return abcitypes.ExecTxResult{}, errorsmod.Wrap(err, "failed to include the tx in a block") 96 | } 97 | txResCount := len(blockRes.TxResults) 98 | if txResCount != 1 { 99 | return abcitypes.ExecTxResult{}, fmt.Errorf("expected to receive only one tx result, but got %d", txResCount) 100 | } 101 | return *blockRes.TxResults[0], nil 102 | } 103 | 104 | // SignCosmosTx is a helper function that signs a Cosmos transaction 105 | // with the provided private key and transaction builder 106 | func (tf *baseTxFactory) SignCosmosTx(privKey cryptotypes.PrivKey, txBuilder client.TxBuilder) error { 107 | txConfig := tf.ec.TxConfig 108 | signMode, err := authsigning.APISignModeToInternal(txConfig.SignModeHandler().DefaultMode()) 109 | if err != nil { 110 | return errorsmod.Wrap(err, "invalid sign mode") 111 | } 112 | signerData, err := tf.setSignatures(privKey, txBuilder, signMode) 113 | if err != nil { 114 | return errorsmod.Wrap(err, "failed to set tx signatures") 115 | } 116 | 117 | return tf.signWithPrivKey(privKey, txBuilder, signerData, signMode) 118 | } 119 | -------------------------------------------------------------------------------- /testutil/integration/common/factory/distribution.go: -------------------------------------------------------------------------------- 1 | // Copyright Tharsis Labs Ltd.(Evmos) 2 | // SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE) 3 | package factory 4 | 5 | import ( 6 | "fmt" 7 | 8 | cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" 9 | sdk "github.com/cosmos/cosmos-sdk/types" 10 | distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" 11 | ) 12 | 13 | type DistributionTxFactory interface { 14 | // SetWithdrawAddress is a method to create and broadcast a MsgSetWithdrawAddress 15 | SetWithdrawAddress(delegatorPriv cryptotypes.PrivKey, withdrawerAddr sdk.AccAddress) error 16 | // WithdrawDelegationRewards is a method to create and broadcast a MsgWithdrawDelegationRewards 17 | WithdrawDelegationRewards(delegatorPriv cryptotypes.PrivKey, validatorAddr string) error 18 | // WithdrawValidatorCommission is a method to create and broadcast a MsgWithdrawValidatorCommission 19 | WithdrawValidatorCommission(validatorPriv cryptotypes.PrivKey) error 20 | } 21 | 22 | type distributionTxFactory struct { 23 | BaseTxFactory 24 | } 25 | 26 | func newDistrTxFactory(bf BaseTxFactory) DistributionTxFactory { 27 | return &distributionTxFactory{bf} 28 | } 29 | 30 | func (tf *distributionTxFactory) SetWithdrawAddress(delegatorPriv cryptotypes.PrivKey, withdrawerAddr sdk.AccAddress) error { 31 | delegatorAccAddr := sdk.AccAddress(delegatorPriv.PubKey().Address()) 32 | 33 | msg := distrtypes.NewMsgSetWithdrawAddress( 34 | delegatorAccAddr, 35 | withdrawerAddr, 36 | ) 37 | 38 | resp, err := tf.ExecuteCosmosTx(delegatorPriv, CosmosTxArgs{ 39 | Msgs: []sdk.Msg{msg}, 40 | }) 41 | 42 | if resp.Code != 0 { 43 | err = fmt.Errorf("received error code %d on SetWithdrawAddress transaction. Logs: %s", resp.Code, resp.Log) 44 | } 45 | 46 | return err 47 | } 48 | 49 | // WithdrawDelegationRewards will withdraw any unclaimed staking rewards for the delegator associated with 50 | // the given private key from the validator. 51 | // The validator address should be in the format `evmosvaloper1...`. 52 | func (tf *distributionTxFactory) WithdrawDelegationRewards(delegatorPriv cryptotypes.PrivKey, validatorAddr string) error { 53 | delegatorAccAddr := sdk.AccAddress(delegatorPriv.PubKey().Address()) 54 | 55 | msg := distrtypes.NewMsgWithdrawDelegatorReward( 56 | delegatorAccAddr.String(), 57 | validatorAddr, 58 | ) 59 | 60 | resp, err := tf.ExecuteCosmosTx(delegatorPriv, CosmosTxArgs{ 61 | Msgs: []sdk.Msg{msg}, 62 | }) 63 | 64 | if resp.Code != 0 { 65 | err = fmt.Errorf("received error code %d on WithdrawDelegationRewards transaction. Logs: %s", resp.Code, resp.Log) 66 | } 67 | 68 | return err 69 | } 70 | 71 | func (tf *distributionTxFactory) WithdrawValidatorCommission(validatorPriv cryptotypes.PrivKey) error { 72 | validatorAddr := sdk.ValAddress(validatorPriv.PubKey().Address()) 73 | 74 | msg := distrtypes.NewMsgWithdrawValidatorCommission( 75 | validatorAddr.String(), 76 | ) 77 | 78 | resp, err := tf.ExecuteCosmosTx(validatorPriv, CosmosTxArgs{ 79 | Msgs: []sdk.Msg{msg}, 80 | }) 81 | 82 | if resp.Code != 0 { 83 | err = fmt.Errorf("received error code %d on WithdrawValidatorCommission transaction. Logs: %s", resp.Code, resp.Log) 84 | } 85 | 86 | return err 87 | } 88 | -------------------------------------------------------------------------------- /testutil/integration/common/factory/factory.go: -------------------------------------------------------------------------------- 1 | // Copyright Tharsis Labs Ltd.(Evmos) 2 | // SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE) 3 | 4 | package factory 5 | 6 | import ( 7 | "github.com/xrplevm/node/v8/testutil/integration/common/grpc" 8 | "github.com/xrplevm/node/v8/testutil/integration/common/network" 9 | ) 10 | 11 | const ( 12 | GasAdjustment = float64(1.7) 13 | ) 14 | 15 | // CoreTxFactory is the interface that wraps the methods 16 | // to build and broadcast cosmos transactions, and also 17 | // includes module-specific transactions 18 | type CoreTxFactory interface { 19 | BaseTxFactory 20 | DistributionTxFactory 21 | StakingTxFactory 22 | FundTxFactory 23 | } 24 | 25 | var _ CoreTxFactory = (*IntegrationTxFactory)(nil) 26 | 27 | // IntegrationTxFactory is a helper struct to build and broadcast transactions 28 | // to the network on integration tests. This is to simulate the behavior of a real user. 29 | type IntegrationTxFactory struct { 30 | BaseTxFactory 31 | DistributionTxFactory 32 | StakingTxFactory 33 | FundTxFactory 34 | } 35 | 36 | // New creates a new IntegrationTxFactory instance 37 | func New( 38 | network network.Network, 39 | grpcHandler grpc.Handler, 40 | ) CoreTxFactory { 41 | bf := newBaseTxFactory(network, grpcHandler) 42 | return &IntegrationTxFactory{ 43 | bf, 44 | newDistrTxFactory(bf), 45 | newStakingTxFactory(bf), 46 | newFundTxFactory(bf), 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /testutil/integration/common/factory/fund.go: -------------------------------------------------------------------------------- 1 | // Copyright Tharsis Labs Ltd.(Evmos) 2 | // SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE) 3 | 4 | package factory 5 | 6 | import ( 7 | "fmt" 8 | 9 | sdktypes "github.com/cosmos/cosmos-sdk/types" 10 | banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" 11 | "github.com/xrplevm/node/v8/testutil/integration/common/keyring" 12 | ) 13 | 14 | // FundTxFactory is the interface that wraps the common methods to fund accounts 15 | // via a bank send transaction 16 | type FundTxFactory interface { 17 | // FundAccount funds the given account with the given amount. 18 | FundAccount(sender keyring.Key, receiver sdktypes.AccAddress, amount sdktypes.Coins) error 19 | } 20 | 21 | // baseTxFactory is the struct of the basic tx factory 22 | // to build and broadcast transactions. 23 | // This is to simulate the behavior of a real user. 24 | type fundTxFactory struct { 25 | BaseTxFactory 26 | } 27 | 28 | // newBaseTxFactory instantiates a new baseTxFactory 29 | func newFundTxFactory(bf BaseTxFactory) FundTxFactory { 30 | return &fundTxFactory{bf} 31 | } 32 | 33 | // FundAccount funds the given account with the given amount of coins. 34 | func (tf *fundTxFactory) FundAccount(sender keyring.Key, receiver sdktypes.AccAddress, coins sdktypes.Coins) error { 35 | bankmsg := banktypes.NewMsgSend( 36 | sender.AccAddr, 37 | receiver, 38 | coins, 39 | ) 40 | txArgs := CosmosTxArgs{Msgs: []sdktypes.Msg{bankmsg}} 41 | txRes, err := tf.ExecuteCosmosTx(sender.Priv, txArgs) 42 | if err != nil { 43 | return err 44 | } 45 | 46 | if txRes.Code != 0 { 47 | return fmt.Errorf("transaction returned non-zero code %d", txRes.Code) 48 | } 49 | 50 | return nil 51 | } 52 | -------------------------------------------------------------------------------- /testutil/integration/common/factory/helper.go: -------------------------------------------------------------------------------- 1 | // Copyright Tharsis Labs Ltd.(Evmos) 2 | // SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE) 3 | 4 | package factory 5 | 6 | import ( 7 | "math/big" 8 | 9 | errorsmod "cosmossdk.io/errors" 10 | sdkmath "cosmossdk.io/math" 11 | "github.com/cosmos/cosmos-sdk/client" 12 | cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" 13 | sdktypes "github.com/cosmos/cosmos-sdk/types" 14 | authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" 15 | ) 16 | 17 | // EncodeTx encodes the tx using the txConfig's encoder. 18 | func (tf *baseTxFactory) EncodeTx(tx sdktypes.Tx) ([]byte, error) { 19 | txConfig := tf.ec.TxConfig 20 | txBytes, err := txConfig.TxEncoder()(tx) 21 | if err != nil { 22 | return nil, errorsmod.Wrap(err, "failed to encode tx") 23 | } 24 | return txBytes, nil 25 | } 26 | 27 | // buildTx builds a tx with the provided private key and txArgs 28 | func (tf *baseTxFactory) buildTx(privKey cryptotypes.PrivKey, txArgs CosmosTxArgs) (client.TxBuilder, error) { 29 | txConfig := tf.ec.TxConfig 30 | txBuilder := txConfig.NewTxBuilder() 31 | 32 | if err := txBuilder.SetMsgs(txArgs.Msgs...); err != nil { 33 | return nil, errorsmod.Wrap(err, "failed to set tx msgs") 34 | } 35 | 36 | if txArgs.FeeGranter != nil { 37 | txBuilder.SetFeeGranter(txArgs.FeeGranter) 38 | } 39 | 40 | senderAddress := sdktypes.AccAddress(privKey.PubKey().Address().Bytes()) 41 | 42 | if txArgs.FeeGranter != nil { 43 | txBuilder.SetFeeGranter(txArgs.FeeGranter) 44 | } 45 | 46 | txBuilder.SetFeePayer(senderAddress) 47 | 48 | // need to sign the tx to simulate the tx to get the gas estimation 49 | signMode, err := authsigning.APISignModeToInternal(txConfig.SignModeHandler().DefaultMode()) 50 | if err != nil { 51 | return nil, errorsmod.Wrap(err, "invalid sign mode") 52 | } 53 | signerData, err := tf.setSignatures(privKey, txBuilder, signMode) 54 | if err != nil { 55 | return nil, errorsmod.Wrap(err, "failed to set tx signatures") 56 | } 57 | 58 | gasLimit, err := tf.estimateGas(txArgs, txBuilder) 59 | if err != nil { 60 | return nil, errorsmod.Wrap(err, "failed to estimate gas") 61 | } 62 | txBuilder.SetGasLimit(gasLimit) 63 | 64 | fees := txArgs.Fees 65 | if fees.IsZero() { 66 | fees, err = tf.calculateFees(txArgs.GasPrice, gasLimit) 67 | if err != nil { 68 | return nil, errorsmod.Wrap(err, "failed to calculate fees") 69 | } 70 | } 71 | txBuilder.SetFeeAmount(fees) 72 | 73 | if err := tf.signWithPrivKey(privKey, txBuilder, signerData, signMode); err != nil { 74 | return nil, errorsmod.Wrap(err, "failed to sign Cosmos Tx") 75 | } 76 | 77 | return txBuilder, nil 78 | } 79 | 80 | // calculateFees calculates the fees for the transaction. 81 | func (tf *baseTxFactory) calculateFees(gasPrice *sdkmath.Int, gasLimit uint64) (sdktypes.Coins, error) { 82 | denom := tf.network.GetDenom() 83 | var fees sdktypes.Coins 84 | if gasPrice != nil { 85 | fees = sdktypes.Coins{{Denom: denom, Amount: gasPrice.MulRaw(int64(gasLimit))}} //#nosec G115 86 | } else { 87 | resp, err := tf.grpcHandler.GetBaseFee() 88 | if err != nil { 89 | return sdktypes.Coins{}, errorsmod.Wrap(err, "failed to get base fee") 90 | } 91 | price := resp.BaseFee 92 | fees = sdktypes.Coins{{Denom: denom, Amount: price.MulRaw(int64(gasLimit))}} //#nosec G115 93 | } 94 | return fees, nil 95 | } 96 | 97 | // estimateGas estimates the gas needed for the transaction. 98 | func (tf *baseTxFactory) estimateGas(txArgs CosmosTxArgs, txBuilder client.TxBuilder) (uint64, error) { 99 | txConfig := tf.ec.TxConfig 100 | simulateBytes, err := txConfig.TxEncoder()(txBuilder.GetTx()) 101 | if err != nil { 102 | return 0, errorsmod.Wrap(err, "failed to encode tx") 103 | } 104 | 105 | var gasLimit uint64 106 | if txArgs.Gas == nil { 107 | simulateRes, err := tf.network.Simulate(simulateBytes) 108 | if err != nil { 109 | return 0, errorsmod.Wrap(err, "failed to simulate tx") 110 | } 111 | 112 | gasAdj := new(big.Float).SetFloat64(GasAdjustment) 113 | gasUsed := new(big.Float).SetUint64(simulateRes.GasInfo.GasUsed) 114 | gasLimit, _ = gasAdj.Mul(gasAdj, gasUsed).Uint64() 115 | } else { 116 | gasLimit = *txArgs.Gas 117 | } 118 | return gasLimit, nil 119 | } 120 | -------------------------------------------------------------------------------- /testutil/integration/common/factory/sign.go: -------------------------------------------------------------------------------- 1 | // Copyright Tharsis Labs Ltd.(Evmos) 2 | // SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE) 3 | 4 | package factory 5 | 6 | import ( 7 | "context" 8 | 9 | errorsmod "cosmossdk.io/errors" 10 | "github.com/cosmos/cosmos-sdk/client" 11 | cosmostx "github.com/cosmos/cosmos-sdk/client/tx" 12 | cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" 13 | sdktypes "github.com/cosmos/cosmos-sdk/types" 14 | "github.com/cosmos/cosmos-sdk/types/tx/signing" 15 | authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" 16 | ) 17 | 18 | // setSignatures is a helper function that sets the signature for 19 | // the transaction in the tx builder. It returns the signerData to be used 20 | // when signing the transaction (e.g. when calling signWithPrivKey) 21 | func (tf *baseTxFactory) setSignatures(privKey cryptotypes.PrivKey, txBuilder client.TxBuilder, signMode signing.SignMode) (signerData authsigning.SignerData, err error) { 22 | senderAddress := sdktypes.AccAddress(privKey.PubKey().Address().Bytes()) 23 | account, err := tf.grpcHandler.GetAccount(senderAddress.String()) 24 | if err != nil { 25 | return signerData, err 26 | } 27 | sequence := account.GetSequence() 28 | signerData = authsigning.SignerData{ 29 | ChainID: tf.network.GetChainID(), 30 | AccountNumber: account.GetAccountNumber(), 31 | Sequence: sequence, 32 | Address: senderAddress.String(), 33 | PubKey: privKey.PubKey(), 34 | } 35 | 36 | sigsV2 := signing.SignatureV2{ 37 | PubKey: privKey.PubKey(), 38 | Data: &signing.SingleSignatureData{ 39 | SignMode: signMode, 40 | Signature: nil, 41 | }, 42 | Sequence: sequence, 43 | } 44 | 45 | return signerData, txBuilder.SetSignatures(sigsV2) 46 | } 47 | 48 | // signWithPrivKey is a helper function that signs a transaction 49 | // with the provided private key 50 | func (tf *baseTxFactory) signWithPrivKey(privKey cryptotypes.PrivKey, txBuilder client.TxBuilder, signerData authsigning.SignerData, signMode signing.SignMode) error { 51 | txConfig := tf.ec.TxConfig 52 | signature, err := cosmostx.SignWithPrivKey(context.TODO(), signMode, signerData, txBuilder, privKey, txConfig, signerData.Sequence) 53 | if err != nil { 54 | return errorsmod.Wrap(err, "failed to sign tx") 55 | } 56 | 57 | return txBuilder.SetSignatures(signature) 58 | } 59 | -------------------------------------------------------------------------------- /testutil/integration/common/factory/staking.go: -------------------------------------------------------------------------------- 1 | // Copyright Tharsis Labs Ltd.(Evmos) 2 | // SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE) 3 | 4 | package factory 5 | 6 | import ( 7 | "fmt" 8 | 9 | "cosmossdk.io/math" 10 | cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" 11 | sdk "github.com/cosmos/cosmos-sdk/types" 12 | stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" 13 | ) 14 | 15 | type StakingTxFactory interface { 16 | // Delegate is a method to create and execute a MsgDelegate paying always the same fee amount 17 | // The tx is included in a block and committed in the chain state 18 | Delegate(delegatorPriv cryptotypes.PrivKey, validatorAddr string, amount sdk.Coin) error 19 | // CreateValidator is a method to create and broadcast a MsgCreateValidator 20 | CreateValidator(operatorPriv cryptotypes.PrivKey, pubKey cryptotypes.PubKey, selfDelegation sdk.Coin, description stakingtypes.Description, commission stakingtypes.CommissionRates, minSelfDelegation math.Int) error 21 | } 22 | 23 | type stakingTxFactory struct { 24 | BaseTxFactory 25 | } 26 | 27 | func newStakingTxFactory(bf BaseTxFactory) StakingTxFactory { 28 | return &stakingTxFactory{bf} 29 | } 30 | 31 | // Delegate on behalf of the account associated with the given private key. 32 | // The defined amount will delegated to the specified validator. 33 | // The validator address should be in the format `evmosvaloper1...`. 34 | func (tf *stakingTxFactory) Delegate(delegatorPriv cryptotypes.PrivKey, validatorAddr string, amount sdk.Coin) error { 35 | delegatorAccAddr := sdk.AccAddress(delegatorPriv.PubKey().Address()) 36 | 37 | msgDelegate := stakingtypes.NewMsgDelegate( 38 | delegatorAccAddr.String(), 39 | validatorAddr, 40 | amount, 41 | ) 42 | 43 | // set gas and gas prices to pay the same fees 44 | // every time this function is called 45 | feesToPay := math.NewInt(1e16) 46 | gas := uint64(400_000) 47 | gasPrice := feesToPay.QuoRaw(int64(gas)) //#nosec G115 -- gas will not exceed int64 48 | 49 | res, err := tf.CommitCosmosTx(delegatorPriv, CosmosTxArgs{ 50 | Msgs: []sdk.Msg{msgDelegate}, 51 | Gas: &gas, 52 | GasPrice: &gasPrice, 53 | }) 54 | 55 | if res.IsErr() { 56 | return fmt.Errorf("tx result with code %d. Logs: %s", res.Code, res.Log) 57 | } 58 | 59 | return err 60 | } 61 | 62 | // CreateValidator executes the transaction to create a validator 63 | // with the parameters specified 64 | func (tf *stakingTxFactory) CreateValidator(operatorPriv cryptotypes.PrivKey, pubKey cryptotypes.PubKey, selfDelegation sdk.Coin, description stakingtypes.Description, commission stakingtypes.CommissionRates, minSelfDelegation math.Int) error { 65 | operatorAccAddr := sdk.ValAddress(operatorPriv.PubKey().Address()) 66 | 67 | msgCreateValidator, err := stakingtypes.NewMsgCreateValidator( 68 | operatorAccAddr.String(), 69 | pubKey, 70 | selfDelegation, 71 | description, 72 | commission, 73 | minSelfDelegation, 74 | ) 75 | if err != nil { 76 | return err 77 | } 78 | 79 | resp, err := tf.ExecuteCosmosTx(operatorPriv, CosmosTxArgs{ 80 | Msgs: []sdk.Msg{msgCreateValidator}, 81 | }) 82 | 83 | if resp.Code != 0 { 84 | err = fmt.Errorf("received error code %d on CreateValidator transaction. Logs: %s", resp.Code, resp.Log) 85 | } 86 | 87 | return err 88 | } 89 | -------------------------------------------------------------------------------- /testutil/integration/common/factory/types.go: -------------------------------------------------------------------------------- 1 | // Copyright Tharsis Labs Ltd.(Evmos) 2 | // SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE) 3 | package factory 4 | 5 | import ( 6 | sdkmath "cosmossdk.io/math" 7 | sdktypes "github.com/cosmos/cosmos-sdk/types" 8 | ) 9 | 10 | // CosmosTxArgs contains the params to create a cosmos tx 11 | type CosmosTxArgs struct { 12 | // ChainID is the chain's id in cosmos format, e.g. 'evmos_9000-1' 13 | ChainID string 14 | // Gas to be used on the tx 15 | Gas *uint64 16 | // GasPrice to use on tx 17 | GasPrice *sdkmath.Int 18 | // Fees is the fee to be used on the tx (amount and denom) 19 | Fees sdktypes.Coins 20 | // FeeGranter is the account address of the fee granter 21 | FeeGranter sdktypes.AccAddress 22 | // Msgs slice of messages to include on the tx 23 | Msgs []sdktypes.Msg 24 | } 25 | -------------------------------------------------------------------------------- /testutil/integration/common/grpc/account.go: -------------------------------------------------------------------------------- 1 | // Copyright Tharsis Labs Ltd.(Evmos) 2 | // SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE) 3 | package grpc 4 | 5 | import ( 6 | "context" 7 | 8 | sdk "github.com/cosmos/cosmos-sdk/types" 9 | authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 10 | ) 11 | 12 | // GetAccount returns the account for the given address. 13 | func (gqh *IntegrationHandler) GetAccount(address string) (sdk.AccountI, error) { 14 | authClient := gqh.network.GetAuthClient() 15 | res, err := authClient.Account(context.Background(), &authtypes.QueryAccountRequest{ 16 | Address: address, 17 | }) 18 | if err != nil { 19 | return nil, err 20 | } 21 | 22 | encodingCgf := gqh.network.GetEncodingConfig() 23 | var acc sdk.AccountI 24 | if err = encodingCgf.InterfaceRegistry.UnpackAny(res.Account, &acc); err != nil { 25 | return nil, err 26 | } 27 | return acc, nil 28 | } 29 | -------------------------------------------------------------------------------- /testutil/integration/common/grpc/authz.go: -------------------------------------------------------------------------------- 1 | // Copyright Tharsis Labs Ltd.(Evmos) 2 | // SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE) 3 | 4 | package grpc 5 | 6 | import ( 7 | "context" 8 | 9 | "github.com/cosmos/cosmos-sdk/x/authz" 10 | ) 11 | 12 | // GetGrants returns the grants for the given grantee and granter combination. 13 | // 14 | // NOTE: To extract the concrete authorizations, use the GetAuthorizations method. 15 | func (gqh *IntegrationHandler) GetGrants(grantee, granter string) ([]*authz.Grant, error) { 16 | authzClient := gqh.network.GetAuthzClient() 17 | res, err := authzClient.Grants(context.Background(), &authz.QueryGrantsRequest{ 18 | Grantee: grantee, 19 | Granter: granter, 20 | }) 21 | if err != nil { 22 | return nil, err 23 | } 24 | 25 | return res.Grants, nil 26 | } 27 | 28 | // GetGrantsByGrantee returns the grants for the given grantee. 29 | // 30 | // NOTE: To extract the concrete authorizations, use the GetAuthorizationsByGrantee method. 31 | func (gqh *IntegrationHandler) GetGrantsByGrantee(grantee string) ([]*authz.GrantAuthorization, error) { 32 | authzClient := gqh.network.GetAuthzClient() 33 | res, err := authzClient.GranteeGrants(context.Background(), &authz.QueryGranteeGrantsRequest{ 34 | Grantee: grantee, 35 | }) 36 | if err != nil { 37 | return nil, err 38 | } 39 | 40 | return res.Grants, nil 41 | } 42 | 43 | // GetGrantsByGranter returns the grants for the given granter. 44 | // 45 | // NOTE: To extract the concrete authorizations, use the GetAuthorizationsByGranter method. 46 | func (gqh *IntegrationHandler) GetGrantsByGranter(granter string) ([]*authz.GrantAuthorization, error) { 47 | authzClient := gqh.network.GetAuthzClient() 48 | res, err := authzClient.GranterGrants(context.Background(), &authz.QueryGranterGrantsRequest{ 49 | Granter: granter, 50 | }) 51 | if err != nil { 52 | return nil, err 53 | } 54 | 55 | return res.Grants, nil 56 | } 57 | 58 | // GetAuthorizations returns the concrete authorizations for the given grantee and granter combination. 59 | func (gqh *IntegrationHandler) GetAuthorizations(grantee, granter string) ([]authz.Authorization, error) { 60 | encodingCfg := gqh.network.GetEncodingConfig() 61 | 62 | grants, err := gqh.GetGrants(grantee, granter) 63 | if err != nil { 64 | return nil, err 65 | } 66 | 67 | auths := make([]authz.Authorization, 0, len(grants)) 68 | for _, grant := range grants { 69 | var auth authz.Authorization 70 | err := encodingCfg.InterfaceRegistry.UnpackAny(grant.Authorization, &auth) 71 | if err != nil { 72 | return nil, err 73 | } 74 | 75 | auths = append(auths, auth) 76 | } 77 | 78 | return auths, nil 79 | } 80 | 81 | // GetAuthorizationsByGrantee returns the concrete authorizations for the given grantee. 82 | func (gqh *IntegrationHandler) GetAuthorizationsByGrantee(grantee string) ([]authz.Authorization, error) { 83 | grants, err := gqh.GetGrantsByGrantee(grantee) 84 | if err != nil { 85 | return nil, err 86 | } 87 | 88 | return gqh.unpackGrantAuthzs(grants) 89 | } 90 | 91 | // GetAuthorizationsByGranter returns the concrete authorizations for the given granter. 92 | func (gqh *IntegrationHandler) GetAuthorizationsByGranter(granter string) ([]authz.Authorization, error) { 93 | grants, err := gqh.GetGrantsByGranter(granter) 94 | if err != nil { 95 | return nil, err 96 | } 97 | 98 | return gqh.unpackGrantAuthzs(grants) 99 | } 100 | 101 | // unpackGrantAuthzs unpacks the given grant authorization. 102 | func (gqh *IntegrationHandler) unpackGrantAuthzs(grantAuthzs []*authz.GrantAuthorization) ([]authz.Authorization, error) { 103 | encodingCfg := gqh.network.GetEncodingConfig() 104 | 105 | auths := make([]authz.Authorization, 0, len(grantAuthzs)) 106 | for _, grantAuthz := range grantAuthzs { 107 | var auth authz.Authorization 108 | err := encodingCfg.InterfaceRegistry.UnpackAny(grantAuthz.Authorization, &auth) 109 | if err != nil { 110 | return nil, err 111 | } 112 | 113 | auths = append(auths, auth) 114 | } 115 | 116 | return auths, nil 117 | } 118 | -------------------------------------------------------------------------------- /testutil/integration/common/grpc/bank.go: -------------------------------------------------------------------------------- 1 | // Copyright Tharsis Labs Ltd.(Evmos) 2 | // SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE) 3 | 4 | package grpc 5 | 6 | import ( 7 | "context" 8 | 9 | sdktypes "github.com/cosmos/cosmos-sdk/types" 10 | banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" 11 | ) 12 | 13 | // GetBalance returns the balance for the given address and denom. 14 | func (gqh *IntegrationHandler) GetBalance(address sdktypes.AccAddress, denom string) (*banktypes.QueryBalanceResponse, error) { 15 | bankClient := gqh.network.GetBankClient() 16 | return bankClient.Balance(context.Background(), &banktypes.QueryBalanceRequest{ 17 | Address: address.String(), 18 | Denom: denom, 19 | }) 20 | } 21 | 22 | // GetAllBalances returns all the balances for the given address. 23 | func (gqh *IntegrationHandler) GetAllBalances(address sdktypes.AccAddress) (*banktypes.QueryAllBalancesResponse, error) { 24 | bankClient := gqh.network.GetBankClient() 25 | return bankClient.AllBalances(context.Background(), &banktypes.QueryAllBalancesRequest{ 26 | Address: address.String(), 27 | }) 28 | } 29 | 30 | // GetTotalSupply returns all the balances for the given address. 31 | func (gqh *IntegrationHandler) GetTotalSupply() (*banktypes.QueryTotalSupplyResponse, error) { 32 | bankClient := gqh.network.GetBankClient() 33 | return bankClient.TotalSupply(context.Background(), &banktypes.QueryTotalSupplyRequest{}) 34 | } 35 | 36 | // GetSpendableBalance returns the spendable balance for the given denomination. 37 | func (gqh *IntegrationHandler) GetSpendableBalance(address sdktypes.AccAddress, denom string) (*banktypes.QuerySpendableBalanceByDenomResponse, error) { 38 | bankClient := gqh.network.GetBankClient() 39 | return bankClient.SpendableBalanceByDenom(context.Background(), &banktypes.QuerySpendableBalanceByDenomRequest{Address: address.String(), Denom: denom}) 40 | } 41 | -------------------------------------------------------------------------------- /testutil/integration/common/grpc/distribution.go: -------------------------------------------------------------------------------- 1 | // Copyright Tharsis Labs Ltd.(Evmos) 2 | // SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE) 3 | package grpc 4 | 5 | import ( 6 | "context" 7 | 8 | distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" 9 | ) 10 | 11 | // GetDelegationTotalRewards returns the total delegation rewards for the given delegator. 12 | func (gqh *IntegrationHandler) GetDelegationTotalRewards(delegatorAddress string) (*distrtypes.QueryDelegationTotalRewardsResponse, error) { 13 | distrClient := gqh.network.GetDistrClient() 14 | return distrClient.DelegationTotalRewards(context.Background(), &distrtypes.QueryDelegationTotalRewardsRequest{ 15 | DelegatorAddress: delegatorAddress, 16 | }) 17 | } 18 | 19 | // GetDelegationRewards returns the delegation rewards for the given delegator and validator. 20 | func (gqh *IntegrationHandler) GetDelegationRewards(delegatorAddress string, validatorAddress string) (*distrtypes.QueryDelegationRewardsResponse, error) { 21 | distrClient := gqh.network.GetDistrClient() 22 | return distrClient.DelegationRewards(context.Background(), &distrtypes.QueryDelegationRewardsRequest{ 23 | DelegatorAddress: delegatorAddress, 24 | ValidatorAddress: validatorAddress, 25 | }) 26 | } 27 | 28 | // GetDelegatorWithdrawAddr returns the withdraw address the given delegator. 29 | func (gqh *IntegrationHandler) GetDelegatorWithdrawAddr(delegatorAddress string) (*distrtypes.QueryDelegatorWithdrawAddressResponse, error) { 30 | distrClient := gqh.network.GetDistrClient() 31 | return distrClient.DelegatorWithdrawAddress(context.Background(), &distrtypes.QueryDelegatorWithdrawAddressRequest{ 32 | DelegatorAddress: delegatorAddress, 33 | }) 34 | } 35 | 36 | // GetValidatorCommission returns the commission for the given validator. 37 | func (gqh *IntegrationHandler) GetValidatorCommission(validatorAddress string) (*distrtypes.QueryValidatorCommissionResponse, error) { 38 | distrClient := gqh.network.GetDistrClient() 39 | return distrClient.ValidatorCommission(context.Background(), &distrtypes.QueryValidatorCommissionRequest{ 40 | ValidatorAddress: validatorAddress, 41 | }) 42 | } 43 | 44 | // GetValidatorOutstandingRewards returns the delegation rewards for the given delegator and validator. 45 | func (gqh *IntegrationHandler) GetValidatorOutstandingRewards(validatorAddress string) (*distrtypes.QueryValidatorOutstandingRewardsResponse, error) { 46 | distrClient := gqh.network.GetDistrClient() 47 | return distrClient.ValidatorOutstandingRewards(context.Background(), &distrtypes.QueryValidatorOutstandingRewardsRequest{ 48 | ValidatorAddress: validatorAddress, 49 | }) 50 | } 51 | 52 | // GetCommunityPool queries the community pool coins. 53 | func (gqh *IntegrationHandler) GetCommunityPool() (*distrtypes.QueryCommunityPoolResponse, error) { 54 | distrClient := gqh.network.GetDistrClient() 55 | return distrClient.CommunityPool(context.Background(), &distrtypes.QueryCommunityPoolRequest{}) 56 | } 57 | -------------------------------------------------------------------------------- /testutil/integration/common/grpc/feemarket.go: -------------------------------------------------------------------------------- 1 | package grpc 2 | 3 | import ( 4 | "context" 5 | 6 | feemarkettypes "github.com/evmos/evmos/v20/x/feemarket/types" 7 | ) 8 | 9 | // GetBaseFee returns the base fee from the feemarket module. 10 | func (gqh *IntegrationHandler) GetBaseFee() (*feemarkettypes.QueryBaseFeeResponse, error) { 11 | feeMarketClient := gqh.network.GetFeeMarketClient() 12 | return feeMarketClient.BaseFee(context.Background(), &feemarkettypes.QueryBaseFeeRequest{}) 13 | } 14 | -------------------------------------------------------------------------------- /testutil/integration/common/grpc/gov.go: -------------------------------------------------------------------------------- 1 | // Copyright Tharsis Labs Ltd.(Evmos) 2 | // SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE) 3 | 4 | package grpc 5 | 6 | import ( 7 | "fmt" 8 | "slices" 9 | 10 | govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1" 11 | ) 12 | 13 | // GetGovParams returns the gov params from the gov module. 14 | func (gqh *IntegrationHandler) GetGovParams(paramsType string) (*govtypes.QueryParamsResponse, error) { 15 | possibleTypes := []string{"deposit", "tallying", "voting"} 16 | if !slices.Contains(possibleTypes, paramsType) { 17 | return nil, fmt.Errorf("invalid params type: %s\npossible types: %s", paramsType, possibleTypes) 18 | } 19 | 20 | govClient := gqh.network.GetGovClient() 21 | return govClient.Params(gqh.network.GetContext(), &govtypes.QueryParamsRequest{ParamsType: paramsType}) 22 | } 23 | 24 | // GetProposal returns the proposal from the gov module. 25 | func (gqh *IntegrationHandler) GetProposal(proposalID uint64) (*govtypes.QueryProposalResponse, error) { 26 | govClient := gqh.network.GetGovClient() 27 | return govClient.Proposal(gqh.network.GetContext(), &govtypes.QueryProposalRequest{ProposalId: proposalID}) 28 | } 29 | -------------------------------------------------------------------------------- /testutil/integration/common/grpc/grpc.go: -------------------------------------------------------------------------------- 1 | // Copyright Tharsis Labs Ltd.(Evmos) 2 | // SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE) 3 | 4 | package grpc 5 | 6 | import ( 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | "github.com/cosmos/cosmos-sdk/x/authz" 9 | banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" 10 | distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" 11 | stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" 12 | feemarkettypes "github.com/evmos/evmos/v20/x/feemarket/types" 13 | network "github.com/xrplevm/node/v8/testutil/integration/common/network" 14 | ) 15 | 16 | // Handler is an interface that defines the common methods that are used to query 17 | // the network's modules via gRPC. 18 | type Handler interface { 19 | // Account methods 20 | GetAccount(address string) (sdk.AccountI, error) 21 | 22 | // Authz methods 23 | GetAuthorizations(grantee, granter string) ([]authz.Authorization, error) 24 | GetAuthorizationsByGrantee(grantee string) ([]authz.Authorization, error) 25 | GetAuthorizationsByGranter(granter string) ([]authz.Authorization, error) 26 | GetGrants(grantee, granter string) ([]*authz.Grant, error) 27 | GetGrantsByGrantee(grantee string) ([]*authz.GrantAuthorization, error) 28 | GetGrantsByGranter(granter string) ([]*authz.GrantAuthorization, error) 29 | 30 | // Bank methods 31 | GetBalance(address sdk.AccAddress, denom string) (*banktypes.QueryBalanceResponse, error) 32 | GetSpendableBalance(address sdk.AccAddress, denom string) (*banktypes.QuerySpendableBalanceByDenomResponse, error) 33 | GetAllBalances(address sdk.AccAddress) (*banktypes.QueryAllBalancesResponse, error) 34 | GetTotalSupply() (*banktypes.QueryTotalSupplyResponse, error) 35 | 36 | // Staking methods 37 | GetDelegation(delegatorAddress string, validatorAddress string) (*stakingtypes.QueryDelegationResponse, error) 38 | GetDelegatorDelegations(delegatorAddress string) (*stakingtypes.QueryDelegatorDelegationsResponse, error) 39 | GetValidatorDelegations(validatorAddress string) (*stakingtypes.QueryValidatorDelegationsResponse, error) 40 | GetRedelegations(delegatorAddress, srcValidator, dstValidator string) (*stakingtypes.QueryRedelegationsResponse, error) 41 | GetValidatorUnbondingDelegations(validatorAddress string) (*stakingtypes.QueryValidatorUnbondingDelegationsResponse, error) 42 | GetDelegatorUnbondingDelegations(delegatorAddress string) (*stakingtypes.QueryDelegatorUnbondingDelegationsResponse, error) 43 | 44 | // Distribution methods 45 | GetDelegationTotalRewards(delegatorAddress string) (*distrtypes.QueryDelegationTotalRewardsResponse, error) 46 | GetDelegationRewards(delegatorAddress string, validatorAddress string) (*distrtypes.QueryDelegationRewardsResponse, error) 47 | GetDelegatorWithdrawAddr(delegatorAddress string) (*distrtypes.QueryDelegatorWithdrawAddressResponse, error) 48 | GetValidatorCommission(validatorAddress string) (*distrtypes.QueryValidatorCommissionResponse, error) 49 | GetValidatorOutstandingRewards(validatorAddress string) (*distrtypes.QueryValidatorOutstandingRewardsResponse, error) 50 | GetCommunityPool() (*distrtypes.QueryCommunityPoolResponse, error) 51 | GetBondedValidators() (*stakingtypes.QueryValidatorsResponse, error) 52 | 53 | // FeeMarket methods 54 | GetBaseFee() (*feemarkettypes.QueryBaseFeeResponse, error) 55 | } 56 | 57 | var _ Handler = (*IntegrationHandler)(nil) 58 | 59 | // IntegrationHandler is a helper struct to query the network's modules 60 | // via gRPC. This is to simulate the behavior of a real user and avoid querying 61 | // the modules directly. 62 | type IntegrationHandler struct { 63 | network network.Network 64 | } 65 | 66 | // NewIntegrationHandler creates a new IntegrationHandler instance. 67 | func NewIntegrationHandler(network network.Network) *IntegrationHandler { 68 | return &IntegrationHandler{ 69 | network: network, 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /testutil/integration/common/grpc/staking.go: -------------------------------------------------------------------------------- 1 | // Copyright Tharsis Labs Ltd.(Evmos) 2 | // SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE) 3 | package grpc 4 | 5 | import ( 6 | "context" 7 | 8 | stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" 9 | ) 10 | 11 | // GetDelegation returns the delegation for the given delegator and validator addresses. 12 | func (gqh *IntegrationHandler) GetDelegation(delegatorAddress string, validatorAddress string) (*stakingtypes.QueryDelegationResponse, error) { 13 | stakingClient := gqh.network.GetStakingClient() 14 | return stakingClient.Delegation(context.Background(), &stakingtypes.QueryDelegationRequest{ 15 | DelegatorAddr: delegatorAddress, 16 | ValidatorAddr: validatorAddress, 17 | }) 18 | } 19 | 20 | // GetValidatorDelegations returns the delegations to a given validator. 21 | func (gqh *IntegrationHandler) GetValidatorDelegations(validatorAddress string) (*stakingtypes.QueryValidatorDelegationsResponse, error) { 22 | stakingClient := gqh.network.GetStakingClient() 23 | return stakingClient.ValidatorDelegations(context.Background(), &stakingtypes.QueryValidatorDelegationsRequest{ 24 | ValidatorAddr: validatorAddress, 25 | }) 26 | } 27 | 28 | // GetDelegatorDelegations returns the delegations to a given delegator. 29 | func (gqh *IntegrationHandler) GetDelegatorDelegations(delegatorAddress string) (*stakingtypes.QueryDelegatorDelegationsResponse, error) { 30 | stakingClient := gqh.network.GetStakingClient() 31 | return stakingClient.DelegatorDelegations(context.Background(), &stakingtypes.QueryDelegatorDelegationsRequest{ 32 | DelegatorAddr: delegatorAddress, 33 | }) 34 | } 35 | 36 | // GetRedelegations returns the redelegations to a given delegator and validators. 37 | func (gqh *IntegrationHandler) GetRedelegations(delegatorAddress, srcValidator, dstValidator string) (*stakingtypes.QueryRedelegationsResponse, error) { 38 | stakingClient := gqh.network.GetStakingClient() 39 | return stakingClient.Redelegations(context.Background(), &stakingtypes.QueryRedelegationsRequest{ 40 | DelegatorAddr: delegatorAddress, 41 | SrcValidatorAddr: srcValidator, 42 | DstValidatorAddr: dstValidator, 43 | }) 44 | } 45 | 46 | // GetValidatorUnbondingDelegations returns the unbonding delegations to a given validator. 47 | func (gqh *IntegrationHandler) GetValidatorUnbondingDelegations(validatorAddress string) (*stakingtypes.QueryValidatorUnbondingDelegationsResponse, error) { 48 | stakingClient := gqh.network.GetStakingClient() 49 | return stakingClient.ValidatorUnbondingDelegations(context.Background(), &stakingtypes.QueryValidatorUnbondingDelegationsRequest{ 50 | ValidatorAddr: validatorAddress, 51 | }) 52 | } 53 | 54 | // GetDelegatorUnbondingDelegations returns all the unbonding delegations for given delegator. 55 | func (gqh *IntegrationHandler) GetDelegatorUnbondingDelegations(delegatorAddress string) (*stakingtypes.QueryDelegatorUnbondingDelegationsResponse, error) { 56 | stakingClient := gqh.network.GetStakingClient() 57 | return stakingClient.DelegatorUnbondingDelegations(context.Background(), &stakingtypes.QueryDelegatorUnbondingDelegationsRequest{ 58 | DelegatorAddr: delegatorAddress, 59 | }) 60 | } 61 | 62 | // GetValidators returns the list of all bonded validators. 63 | func (gqh *IntegrationHandler) GetBondedValidators() (*stakingtypes.QueryValidatorsResponse, error) { 64 | stakingClient := gqh.network.GetStakingClient() 65 | return stakingClient.Validators(context.Background(), &stakingtypes.QueryValidatorsRequest{ 66 | Status: stakingtypes.BondStatusBonded, 67 | }) 68 | } 69 | -------------------------------------------------------------------------------- /testutil/integration/common/keyring/keyring.go: -------------------------------------------------------------------------------- 1 | // Copyright Tharsis Labs Ltd.(Evmos) 2 | // SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE) 3 | package keyring 4 | 5 | import ( 6 | "fmt" 7 | 8 | "github.com/ethereum/go-ethereum/common" 9 | 10 | cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" 11 | sdktypes "github.com/cosmos/cosmos-sdk/types" 12 | utiltx "github.com/evmos/evmos/v20/testutil/tx" 13 | ) 14 | 15 | type Key struct { 16 | Addr common.Address 17 | AccAddr sdktypes.AccAddress 18 | Priv cryptotypes.PrivKey 19 | } 20 | 21 | func NewKey() Key { 22 | addr, privKey := utiltx.NewAddrKey() 23 | return Key{ 24 | Addr: addr, 25 | AccAddr: sdktypes.AccAddress(addr.Bytes()), 26 | Priv: privKey, 27 | } 28 | } 29 | 30 | type Keyring interface { 31 | // GetPrivKey returns the private key of the account at the given keyring index. 32 | GetPrivKey(index int) cryptotypes.PrivKey 33 | // GetAddr returns the address of the account at the given keyring index. 34 | GetAddr(index int) common.Address 35 | // GetAccAddr returns the SDK address of the account at the given keyring index. 36 | GetAccAddr(index int) sdktypes.AccAddress 37 | // GetAllAccAddrs returns all the SDK addresses of the accounts in the keyring. 38 | GetAllAccAddrs() []sdktypes.AccAddress 39 | // GetKey returns the key at the given keyring index 40 | GetKey(index int) Key 41 | // GetKeys returns all the keys 42 | GetKeys() []Key 43 | 44 | // AddKey adds a new account to the keyring 45 | AddKey() int 46 | 47 | // Sign signs message with the specified account. 48 | Sign(index int, msg []byte) ([]byte, error) 49 | } 50 | 51 | // IntegrationKeyring is a keyring designed for integration tests. 52 | type IntegrationKeyring struct { 53 | keys []Key 54 | } 55 | 56 | var _ Keyring = (*IntegrationKeyring)(nil) 57 | 58 | // New returns a new keyring with nAccs accounts. 59 | func New(nAccs int) Keyring { 60 | accs := make([]Key, 0, nAccs) 61 | for i := 0; i < nAccs; i++ { 62 | acc := NewKey() 63 | accs = append(accs, acc) 64 | } 65 | return &IntegrationKeyring{ 66 | keys: accs, 67 | } 68 | } 69 | 70 | // GetPrivKey returns the private key of the specified account. 71 | func (kr *IntegrationKeyring) GetPrivKey(index int) cryptotypes.PrivKey { 72 | return kr.keys[index].Priv 73 | } 74 | 75 | // GetAddr returns the address of the specified account. 76 | func (kr *IntegrationKeyring) GetAddr(index int) common.Address { 77 | return kr.keys[index].Addr 78 | } 79 | 80 | // GetAccAddr returns the sdk address of the specified account. 81 | func (kr *IntegrationKeyring) GetAccAddr(index int) sdktypes.AccAddress { 82 | return kr.keys[index].AccAddr 83 | } 84 | 85 | // GetAllAccAddrs returns all the sdk addresses of the accounts in the keyring. 86 | func (kr *IntegrationKeyring) GetAllAccAddrs() []sdktypes.AccAddress { 87 | accs := make([]sdktypes.AccAddress, 0, len(kr.keys)) 88 | for _, key := range kr.keys { 89 | accs = append(accs, key.AccAddr) 90 | } 91 | return accs 92 | } 93 | 94 | // GetKey returns the key specified by index 95 | func (kr *IntegrationKeyring) GetKey(index int) Key { 96 | return kr.keys[index] 97 | } 98 | 99 | // GetKey returns the key specified by index 100 | func (kr *IntegrationKeyring) GetKeys() []Key { 101 | return kr.keys 102 | } 103 | 104 | // AddKey adds a new account to the keyring. It returns the index for the key 105 | func (kr *IntegrationKeyring) AddKey() int { 106 | acc := NewKey() 107 | index := len(kr.keys) 108 | kr.keys = append(kr.keys, acc) 109 | return index 110 | } 111 | 112 | // Sign signs message with the specified key. 113 | func (kr *IntegrationKeyring) Sign(index int, msg []byte) ([]byte, error) { 114 | privKey := kr.GetPrivKey(index) 115 | if privKey == nil { 116 | return nil, fmt.Errorf("no private key for account %d", index) 117 | } 118 | return privKey.Sign(msg) 119 | } 120 | -------------------------------------------------------------------------------- /testutil/integration/common/network/network.go: -------------------------------------------------------------------------------- 1 | // Copyright Tharsis Labs Ltd.(Evmos) 2 | // SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE) 3 | 4 | package network 5 | 6 | import ( 7 | "testing" 8 | "time" 9 | 10 | sdkmath "cosmossdk.io/math" 11 | abcitypes "github.com/cometbft/cometbft/abci/types" 12 | sdktypes "github.com/cosmos/cosmos-sdk/types" 13 | sdktestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" 14 | txtypes "github.com/cosmos/cosmos-sdk/types/tx" 15 | authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 16 | authz "github.com/cosmos/cosmos-sdk/x/authz" 17 | banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" 18 | distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" 19 | govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1" 20 | stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" 21 | ibctesting "github.com/cosmos/ibc-go/v8/testing" 22 | feemarkettypes "github.com/evmos/evmos/v20/x/feemarket/types" 23 | ) 24 | 25 | // Network is the interface that wraps the common methods to interact with integration test network. 26 | // 27 | // It was designed to avoid users to access module's keepers directly and force integration tests 28 | // to be closer to the real user's behavior. 29 | type Network interface { 30 | GetContext() sdktypes.Context 31 | GetChainID() string 32 | GetDenom() string 33 | GetOtherDenoms() []string 34 | GetValidators() []stakingtypes.Validator 35 | GetMinDepositAmt() sdkmath.Int 36 | NextBlock() error 37 | NextBlockAfter(duration time.Duration) error 38 | NextBlockWithTxs(txBytes ...[]byte) (*abcitypes.ResponseFinalizeBlock, error) 39 | 40 | // Clients 41 | GetAuthClient() authtypes.QueryClient 42 | GetAuthzClient() authz.QueryClient 43 | GetBankClient() banktypes.QueryClient 44 | GetStakingClient() stakingtypes.QueryClient 45 | GetDistrClient() distrtypes.QueryClient 46 | GetFeeMarketClient() feemarkettypes.QueryClient 47 | GetGovClient() govtypes.QueryClient 48 | 49 | BroadcastTxSync(txBytes []byte) (abcitypes.ExecTxResult, error) 50 | Simulate(txBytes []byte) (*txtypes.SimulateResponse, error) 51 | CheckTx(txBytes []byte) (*abcitypes.ResponseCheckTx, error) 52 | 53 | // GetIBCChain returns the IBC test chain. 54 | // NOTE: this is only used for testing IBC related functionality. 55 | // The idea is to deprecate this eventually. 56 | GetIBCChain(t *testing.T, coord *ibctesting.Coordinator) *ibctesting.TestChain 57 | GetEncodingConfig() sdktestutil.TestEncodingConfig 58 | } 59 | -------------------------------------------------------------------------------- /testutil/integration/exrp/common/clients.go: -------------------------------------------------------------------------------- 1 | // Copyright Tharsis Labs Ltd.(Evmos) 2 | // SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE) 3 | package exrpcommon 4 | 5 | import ( 6 | "github.com/cosmos/cosmos-sdk/baseapp" 7 | sdktypes "github.com/cosmos/cosmos-sdk/types" 8 | "github.com/cosmos/cosmos-sdk/types/module/testutil" 9 | authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" 10 | authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 11 | "github.com/cosmos/cosmos-sdk/x/authz" 12 | authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper" 13 | bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" 14 | banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" 15 | distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" 16 | distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" 17 | govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" 18 | govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1" 19 | slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" 20 | slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" 21 | stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" 22 | stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" 23 | 24 | erc20keeper "github.com/evmos/evmos/v20/x/erc20/keeper" 25 | erc20types "github.com/evmos/evmos/v20/x/erc20/types" 26 | evmkeeper "github.com/evmos/evmos/v20/x/evm/keeper" 27 | evmtypes "github.com/evmos/evmos/v20/x/evm/types" 28 | feemarketkeeper "github.com/evmos/evmos/v20/x/feemarket/keeper" 29 | feemarkettypes "github.com/evmos/evmos/v20/x/feemarket/types" 30 | poakeeper "github.com/xrplevm/node/v8/x/poa/keeper" 31 | poatypes "github.com/xrplevm/node/v8/x/poa/types" 32 | ) 33 | 34 | type NetworkKeepers interface { 35 | GetContext() sdktypes.Context 36 | GetEncodingConfig() testutil.TestEncodingConfig 37 | 38 | ERC20Keeper() erc20keeper.Keeper 39 | EvmKeeper() evmkeeper.Keeper 40 | GovKeeper() *govkeeper.Keeper 41 | BankKeeper() bankkeeper.Keeper 42 | StakingKeeper() *stakingkeeper.Keeper 43 | SlashingKeeper() slashingkeeper.Keeper 44 | DistrKeeper() distrkeeper.Keeper 45 | AccountKeeper() authkeeper.AccountKeeper 46 | AuthzKeeper() authzkeeper.Keeper 47 | FeeMarketKeeper() feemarketkeeper.Keeper 48 | PoaKeeper() poakeeper.Keeper 49 | } 50 | 51 | func getQueryHelper(ctx sdktypes.Context, encCfg testutil.TestEncodingConfig) *baseapp.QueryServiceTestHelper { 52 | interfaceRegistry := encCfg.InterfaceRegistry 53 | // This is needed so that state changes are not committed in precompiles 54 | // simulations. 55 | cacheCtx, _ := ctx.CacheContext() 56 | return baseapp.NewQueryServerTestHelper(cacheCtx, interfaceRegistry) 57 | } 58 | 59 | func GetERC20Client(n NetworkKeepers) erc20types.QueryClient { 60 | queryHelper := getQueryHelper(n.GetContext(), n.GetEncodingConfig()) 61 | erc20types.RegisterQueryServer(queryHelper, n.ERC20Keeper()) 62 | return erc20types.NewQueryClient(queryHelper) 63 | } 64 | 65 | func GetEvmClient(n NetworkKeepers) evmtypes.QueryClient { 66 | queryHelper := getQueryHelper(n.GetContext(), n.GetEncodingConfig()) 67 | evmtypes.RegisterQueryServer(queryHelper, n.EvmKeeper()) 68 | return evmtypes.NewQueryClient(queryHelper) 69 | } 70 | 71 | func GetGovClient(n NetworkKeepers) govtypes.QueryClient { 72 | queryHelper := getQueryHelper(n.GetContext(), n.GetEncodingConfig()) 73 | govtypes.RegisterQueryServer(queryHelper, govkeeper.NewQueryServer(n.GovKeeper())) 74 | return govtypes.NewQueryClient(queryHelper) 75 | } 76 | 77 | func GetBankClient(n NetworkKeepers) banktypes.QueryClient { 78 | queryHelper := getQueryHelper(n.GetContext(), n.GetEncodingConfig()) 79 | banktypes.RegisterQueryServer(queryHelper, n.BankKeeper()) 80 | return banktypes.NewQueryClient(queryHelper) 81 | } 82 | 83 | func GetFeeMarketClient(n NetworkKeepers) feemarkettypes.QueryClient { 84 | queryHelper := getQueryHelper(n.GetContext(), n.GetEncodingConfig()) 85 | feemarkettypes.RegisterQueryServer(queryHelper, n.FeeMarketKeeper()) 86 | return feemarkettypes.NewQueryClient(queryHelper) 87 | } 88 | 89 | func GetAuthClient(n NetworkKeepers) authtypes.QueryClient { 90 | queryHelper := getQueryHelper(n.GetContext(), n.GetEncodingConfig()) 91 | authtypes.RegisterQueryServer(queryHelper, authkeeper.NewQueryServer(n.AccountKeeper())) 92 | return authtypes.NewQueryClient(queryHelper) 93 | } 94 | 95 | func GetAuthzClient(n NetworkKeepers) authz.QueryClient { 96 | queryHelper := getQueryHelper(n.GetContext(), n.GetEncodingConfig()) 97 | authz.RegisterQueryServer(queryHelper, n.AuthzKeeper()) 98 | return authz.NewQueryClient(queryHelper) 99 | } 100 | 101 | func GetStakingClient(n NetworkKeepers) stakingtypes.QueryClient { 102 | queryHelper := getQueryHelper(n.GetContext(), n.GetEncodingConfig()) 103 | stakingtypes.RegisterQueryServer(queryHelper, stakingkeeper.Querier{Keeper: n.StakingKeeper()}) 104 | return stakingtypes.NewQueryClient(queryHelper) 105 | } 106 | 107 | func GetSlashingClient(n NetworkKeepers) slashingtypes.QueryClient { 108 | queryHelper := getQueryHelper(n.GetContext(), n.GetEncodingConfig()) 109 | slashingtypes.RegisterQueryServer(queryHelper, slashingkeeper.Querier{Keeper: n.SlashingKeeper()}) 110 | return slashingtypes.NewQueryClient(queryHelper) 111 | } 112 | 113 | func GetDistrClient(n NetworkKeepers) distrtypes.QueryClient { 114 | queryHelper := getQueryHelper(n.GetContext(), n.GetEncodingConfig()) 115 | distrtypes.RegisterQueryServer(queryHelper, distrkeeper.Querier{Keeper: n.DistrKeeper()}) 116 | return distrtypes.NewQueryClient(queryHelper) 117 | } 118 | 119 | func GetPoaClient(n NetworkKeepers) poatypes.QueryClient { 120 | queryHelper := getQueryHelper(n.GetContext(), n.GetEncodingConfig()) 121 | poatypes.RegisterQueryServer(queryHelper, poakeeper.Querier{Keeper: n.PoaKeeper()}) 122 | return poatypes.NewQueryClient(queryHelper) 123 | } 124 | -------------------------------------------------------------------------------- /testutil/integration/exrp/common/config.go: -------------------------------------------------------------------------------- 1 | package exrpcommon 2 | 3 | import ( 4 | "math/big" 5 | 6 | sdkmath "cosmossdk.io/math" 7 | "github.com/cosmos/cosmos-sdk/baseapp" 8 | sdktypes "github.com/cosmos/cosmos-sdk/types" 9 | banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" 10 | evmostypes "github.com/evmos/evmos/v20/types" 11 | "github.com/xrplevm/node/v8/app" 12 | ) 13 | 14 | const ( 15 | bip44CoinType = 60 16 | ChainID = "exrp_1440002-1" 17 | ) 18 | 19 | // Config defines the configuration for a chain. 20 | // It allows for customization of the network to adjust to 21 | // testing needs. 22 | type Config struct { 23 | ChainID string 24 | EIP155ChainID *big.Int 25 | AmountOfValidators int 26 | PreFundedAccounts []sdktypes.AccAddress 27 | Balances []banktypes.Balance 28 | BondDenom string 29 | MaxValidators uint32 30 | Denom string 31 | CustomGenesisState CustomGenesisState 32 | GenesisBytes []byte 33 | OtherCoinDenom []string 34 | OperatorsAddrs []sdktypes.AccAddress 35 | CustomBaseAppOpts []func(*baseapp.BaseApp) 36 | MinDepositAmt sdkmath.Int 37 | Quorum string 38 | } 39 | 40 | type CustomGenesisState map[string]interface{} 41 | 42 | // DefaultConfig returns the default configuration for a chain. 43 | func DefaultConfig() Config { 44 | return Config{ 45 | ChainID: ChainID, 46 | EIP155ChainID: big.NewInt(1440002), 47 | Balances: nil, 48 | Denom: app.BaseDenom, 49 | } 50 | } 51 | 52 | // ConfigOption defines a function that can modify the NetworkConfig. 53 | // The purpose of this is to force to be declarative when the default configuration 54 | // requires to be changed. 55 | type ConfigOption func(*Config) 56 | 57 | // WithChainID sets a custom chainID for the network. It panics if the chainID is invalid. 58 | func WithChainID(chainID string) ConfigOption { 59 | chainIDNum, err := evmostypes.ParseChainID(chainID) 60 | if err != nil { 61 | panic(err) 62 | } 63 | return func(cfg *Config) { 64 | cfg.ChainID = chainID 65 | cfg.EIP155ChainID = chainIDNum 66 | } 67 | } 68 | 69 | // WithAmountOfValidators sets the amount of validators for the network. 70 | func WithAmountOfValidators(amount int) ConfigOption { 71 | return func(cfg *Config) { 72 | cfg.AmountOfValidators = amount 73 | } 74 | } 75 | 76 | // WithPreFundedAccounts sets the pre-funded accounts for the network. 77 | func WithPreFundedAccounts(accounts ...sdktypes.AccAddress) ConfigOption { 78 | return func(cfg *Config) { 79 | cfg.PreFundedAccounts = accounts 80 | } 81 | } 82 | 83 | // WithBalances sets the specific balances for the pre-funded accounts, that 84 | // are being set up for the network. 85 | func WithBalances(balances ...banktypes.Balance) ConfigOption { 86 | return func(cfg *Config) { 87 | cfg.Balances = append(cfg.Balances, balances...) 88 | } 89 | } 90 | 91 | // WithBondDenom sets the bond denom for the network. 92 | func WithBondDenom(denom string) ConfigOption { 93 | return func(cfg *Config) { 94 | cfg.BondDenom = denom 95 | } 96 | } 97 | 98 | // WithMaxValidators sets the max validators for the network. 99 | func WithMaxValidators(maxValidators uint32) ConfigOption { 100 | return func(cfg *Config) { 101 | cfg.MaxValidators = maxValidators 102 | } 103 | } 104 | 105 | // WithDenom sets the denom for the network. 106 | func WithDenom(denom string) ConfigOption { 107 | return func(cfg *Config) { 108 | cfg.Denom = denom 109 | } 110 | } 111 | 112 | // WithCustomGenesis sets the custom genesis of the network for specific modules. 113 | func WithCustomGenesis(customGenesis CustomGenesisState) ConfigOption { 114 | return func(cfg *Config) { 115 | cfg.CustomGenesisState = customGenesis 116 | } 117 | } 118 | 119 | // WithOtherDenoms sets other possible coin denominations for the network. 120 | func WithOtherDenoms(otherDenoms []string) ConfigOption { 121 | return func(cfg *Config) { 122 | cfg.OtherCoinDenom = otherDenoms 123 | } 124 | } 125 | 126 | // WithValidatorOperators overwrites the used operator address for the network instantiation. 127 | func WithValidatorOperators(keys []sdktypes.AccAddress) ConfigOption { 128 | return func(cfg *Config) { 129 | cfg.OperatorsAddrs = keys 130 | } 131 | } 132 | 133 | // WithCustomBaseAppOpts sets custom base app options for the network. 134 | func WithCustomBaseAppOpts(opts ...func(*baseapp.BaseApp)) ConfigOption { 135 | return func(cfg *Config) { 136 | cfg.CustomBaseAppOpts = opts 137 | } 138 | } 139 | 140 | // WithMinDepositAmt sets the min deposit amount for the network. 141 | func WithMinDepositAmt(minDepositAmt sdkmath.Int) ConfigOption { 142 | return func(cfg *Config) { 143 | cfg.MinDepositAmt = minDepositAmt 144 | } 145 | } 146 | 147 | func WithQuorum(quorum string) ConfigOption { 148 | return func(cfg *Config) { 149 | cfg.Quorum = quorum 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /testutil/integration/exrp/common/consensus.go: -------------------------------------------------------------------------------- 1 | package exrpcommon 2 | 3 | import ( 4 | "time" 5 | 6 | cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" 7 | cmttypes "github.com/cometbft/cometbft/types" 8 | ) 9 | 10 | // DefaultConsensusParams defines the default Tendermint consensus params used in 11 | // Evmos testing. 12 | var DefaultConsensusParams = &cmtproto.ConsensusParams{ 13 | Block: &cmtproto.BlockParams{ 14 | MaxBytes: 200000, 15 | MaxGas: -1, // no limit 16 | }, 17 | Evidence: &cmtproto.EvidenceParams{ 18 | MaxAgeNumBlocks: 302400, 19 | MaxAgeDuration: 504 * time.Hour, // 3 weeks is the max duration 20 | MaxBytes: 10000, 21 | }, 22 | Validator: &cmtproto.ValidatorParams{ 23 | PubKeyTypes: []string{ 24 | cmttypes.ABCIPubKeyTypeEd25519, 25 | }, 26 | }, 27 | } 28 | -------------------------------------------------------------------------------- /testutil/integration/exrp/common/network.go: -------------------------------------------------------------------------------- 1 | package exrpcommon 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | sdktypes "github.com/cosmos/cosmos-sdk/types" 8 | ibctesting "github.com/cosmos/ibc-go/v8/testing" 9 | 10 | abcitypes "github.com/cometbft/cometbft/abci/types" 11 | sdktestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" 12 | txtypes "github.com/cosmos/cosmos-sdk/types/tx" 13 | stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" 14 | ) 15 | 16 | type Network interface { 17 | // Keepers 18 | NetworkKeepers 19 | 20 | // Clients 21 | BroadcastTxSync(txBytes []byte) (abcitypes.ExecTxResult, error) 22 | Simulate(txBytes []byte) (*txtypes.SimulateResponse, error) 23 | CheckTx(txBytes []byte) (*abcitypes.ResponseCheckTx, error) 24 | 25 | // GetIBCChain returns the IBC test chain. 26 | // NOTE: this is only used for testing IBC related functionality. 27 | // The idea is to deprecate this eventually. 28 | GetIBCChain(t *testing.T, coord *ibctesting.Coordinator) *ibctesting.TestChain 29 | GetEncodingConfig() sdktestutil.TestEncodingConfig 30 | 31 | // Getters 32 | GetContext() sdktypes.Context 33 | GetChainID() string 34 | GetBondDenom() string 35 | GetDenom() string 36 | GetOtherDenoms() []string 37 | GetValidators() []stakingtypes.Validator 38 | 39 | // ABCI 40 | NextBlock() error 41 | NextBlockAfter(duration time.Duration) error 42 | NextBlockWithTxs(txBytes ...[]byte) (*abcitypes.ResponseFinalizeBlock, error) 43 | } 44 | -------------------------------------------------------------------------------- /testutil/integration/exrp/common/setup.go: -------------------------------------------------------------------------------- 1 | package exrpcommon 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "cosmossdk.io/log" 8 | "github.com/cosmos/cosmos-sdk/baseapp" 9 | sdktypes "github.com/cosmos/cosmos-sdk/types" 10 | 11 | dbm "github.com/cosmos/cosmos-db" 12 | simutils "github.com/cosmos/cosmos-sdk/testutil/sims" 13 | "github.com/cosmos/gogoproto/proto" 14 | "github.com/xrplevm/node/v8/app" 15 | 16 | authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 17 | banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" 18 | distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" 19 | genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" 20 | govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" 21 | govtypesv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" 22 | capabilitytypes "github.com/cosmos/ibc-go/modules/capability/types" 23 | erc20types "github.com/evmos/evmos/v20/x/erc20/types" 24 | evmtypes "github.com/evmos/evmos/v20/x/evm/types" 25 | feemarkettypes "github.com/evmos/evmos/v20/x/feemarket/types" 26 | ) 27 | 28 | // GenSetupFn is the type for the module genesis setup functions 29 | type GenSetupFn func(exrpApp *app.App, genesisState app.GenesisState, customGenesis interface{}) (app.GenesisState, error) 30 | 31 | var genesisSetupFunctions = map[string]GenSetupFn{ 32 | evmtypes.ModuleName: GenStateSetter[*evmtypes.GenesisState](evmtypes.ModuleName), 33 | erc20types.ModuleName: GenStateSetter[*erc20types.GenesisState](erc20types.ModuleName), 34 | govtypes.ModuleName: GenStateSetter[*govtypesv1.GenesisState](govtypes.ModuleName), 35 | feemarkettypes.ModuleName: GenStateSetter[*feemarkettypes.GenesisState](feemarkettypes.ModuleName), 36 | distrtypes.ModuleName: GenStateSetter[*distrtypes.GenesisState](distrtypes.ModuleName), 37 | banktypes.ModuleName: GenStateSetter[*banktypes.GenesisState](banktypes.ModuleName), 38 | authtypes.ModuleName: GenStateSetter[*authtypes.GenesisState](authtypes.ModuleName), 39 | capabilitytypes.ModuleName: GenStateSetter[*capabilitytypes.GenesisState](capabilitytypes.ModuleName), 40 | genutiltypes.ModuleName: GenStateSetter[*genutiltypes.GenesisState](genutiltypes.ModuleName), 41 | } 42 | 43 | // GenStateSetter is a generic function to set module-specific genesis state 44 | func GenStateSetter[T proto.Message](moduleName string) GenSetupFn { 45 | return func(exrpApp *app.App, genesisState app.GenesisState, customGenesis interface{}) (app.GenesisState, error) { 46 | moduleGenesis, ok := customGenesis.(T) 47 | if !ok { 48 | return nil, fmt.Errorf("invalid type %T for %s module genesis state", customGenesis, moduleName) 49 | } 50 | 51 | genesisState[moduleName] = exrpApp.AppCodec().MustMarshalJSON(moduleGenesis) 52 | return genesisState, nil 53 | } 54 | } 55 | 56 | // CustomizeGenesis modifies genesis state if there're any custom genesis state 57 | // for specific modules 58 | func CustomizeGenesis(exrpApp *app.App, customGen CustomGenesisState, genesisState app.GenesisState) (app.GenesisState, error) { 59 | var err error 60 | for mod, modGenState := range customGen { 61 | if fn, found := genesisSetupFunctions[mod]; found { 62 | genesisState, err = fn(exrpApp, genesisState, modGenState) 63 | if err != nil { 64 | return genesisState, err 65 | } 66 | } else { 67 | panic(fmt.Sprintf("module %s not found in genesis setup functions", mod)) 68 | } 69 | } 70 | return genesisState, err 71 | } 72 | 73 | func SetupSdkConfig() { 74 | accountPubKeyPrefix := app.AccountAddressPrefix + "pub" 75 | validatorAddressPrefix := app.AccountAddressPrefix + "valoper" 76 | validatorPubKeyPrefix := app.AccountAddressPrefix + "valoperpub" 77 | consNodeAddressPrefix := app.AccountAddressPrefix + "valcons" 78 | consNodePubKeyPrefix := app.AccountAddressPrefix + "valconspub" 79 | 80 | // Set config 81 | config := sdktypes.GetConfig() 82 | config.SetBech32PrefixForAccount(app.AccountAddressPrefix, accountPubKeyPrefix) 83 | config.SetBech32PrefixForValidator(validatorAddressPrefix, validatorPubKeyPrefix) 84 | config.SetBech32PrefixForConsensusNode(consNodeAddressPrefix, consNodePubKeyPrefix) 85 | config.SetCoinType(bip44CoinType) 86 | config.SetPurpose(sdktypes.Purpose) // Shared 87 | config.Seal() 88 | } 89 | 90 | func MustGetIntegrationTestNodeHome() string { 91 | wd, err := os.Getwd() 92 | if err != nil { 93 | panic(err) 94 | } 95 | 96 | return wd + "/../../" 97 | } 98 | 99 | // createExrpApp creates an exrp app 100 | func CreateExrpApp(chainID string, customBaseAppOptions ...func(*baseapp.BaseApp)) *app.App { 101 | testNodeHome := MustGetIntegrationTestNodeHome() 102 | // Create exrp app 103 | db := dbm.NewMemDB() 104 | logger := log.NewNopLogger() 105 | loadLatest := true 106 | skipUpgradeHeights := map[int64]bool{} 107 | homePath := testNodeHome 108 | invCheckPeriod := uint(5) 109 | appOptions := simutils.NewAppOptionsWithFlagHome(homePath) 110 | baseAppOptions := append(customBaseAppOptions, baseapp.SetChainID(chainID)) //nolint:gocritic 111 | 112 | return app.New( 113 | logger, 114 | db, 115 | nil, 116 | loadLatest, 117 | skipUpgradeHeights, 118 | homePath, 119 | invCheckPeriod, 120 | appOptions, 121 | baseAppOptions..., 122 | ) 123 | } 124 | -------------------------------------------------------------------------------- /testutil/integration/exrp/integration/abci.go: -------------------------------------------------------------------------------- 1 | // Copyright Tharsis Labs Ltd.(Evmos) 2 | // SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE) 3 | package exrpintegration 4 | 5 | import ( 6 | "time" 7 | 8 | storetypes "cosmossdk.io/store/types" 9 | abcitypes "github.com/cometbft/cometbft/abci/types" 10 | cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" 11 | cmttypes "github.com/cometbft/cometbft/types" 12 | ) 13 | 14 | // NextBlock is a private helper function that runs the EndBlocker logic, commits the changes, 15 | // updates the header and runs the BeginBlocker 16 | func (n *IntegrationNetwork) NextBlock() error { 17 | return n.NextBlockAfter(time.Second) 18 | } 19 | 20 | // NextBlockAfter is a private helper function that runs the FinalizeBlock logic, updates the context and 21 | // commits the changes to have a block time after the given duration. 22 | func (n *IntegrationNetwork) NextBlockAfter(duration time.Duration) error { 23 | _, err := n.finalizeBlockAndCommit(duration, nil, nil) 24 | return err 25 | } 26 | 27 | // NextBlockWithTxs is a helper function that runs the FinalizeBlock logic 28 | // with the provided tx bytes, updates the context and 29 | // commits the changes to have a block time after the given duration. 30 | func (n *IntegrationNetwork) NextBlockWithTxs(txBytes ...[]byte) (*abcitypes.ResponseFinalizeBlock, error) { 31 | return n.finalizeBlockAndCommit(time.Second, n.valFlags, nil, txBytes...) 32 | } 33 | 34 | // NextNBlocksWithValidatorFlags is a helper function that runs the FinalizeBlock logic 35 | // with the provided validator flags, updates the context and 36 | // commits the changes to have a block time after the given duration. 37 | func (n *IntegrationNetwork) NextNBlocksWithValidatorFlags(blocks int64, validatorFlags []cmtproto.BlockIDFlag) error { 38 | for i := int64(0); i < blocks; i++ { 39 | _, err := n.finalizeBlockAndCommit(time.Second, validatorFlags, nil) 40 | if err != nil { 41 | return err 42 | } 43 | } 44 | return nil 45 | } 46 | 47 | // NextBlockWithMisBehaviors is a helper function that runs the FinalizeBlock logic 48 | // with the provided misbehaviors, updates the context and 49 | // commits the changes to have a block time after the given duration. 50 | func (n *IntegrationNetwork) NextBlockWithMisBehaviors(misbehaviors []abcitypes.Misbehavior) error { 51 | _, err := n.finalizeBlockAndCommit(time.Second, n.valFlags, misbehaviors) 52 | return err 53 | } 54 | 55 | // finalizeBlockAndCommit is a private helper function that runs the FinalizeBlock logic 56 | // with the provided txBytes, updates the context and 57 | // commits the changes to have a block time after the given duration. 58 | func (n *IntegrationNetwork) finalizeBlockAndCommit(duration time.Duration, vFlags []cmtproto.BlockIDFlag, misbehaviors []abcitypes.Misbehavior, txBytes ...[]byte) (*abcitypes.ResponseFinalizeBlock, error) { 59 | header := n.ctx.BlockHeader() 60 | // Update block header and BeginBlock 61 | header.Height++ 62 | header.AppHash = n.app.LastCommitID().Hash 63 | // Calculate new block time after duration 64 | newBlockTime := header.Time.Add(duration) 65 | header.Time = newBlockTime 66 | 67 | var validatorFlags []cmtproto.BlockIDFlag 68 | if len(vFlags) > 0 { 69 | validatorFlags = vFlags 70 | } else { 71 | validatorFlags = n.valFlags 72 | } 73 | 74 | // FinalizeBlock to run endBlock, deliverTx & beginBlock logic 75 | req := BuildFinalizeBlockReq(header, n.valSet.Validators, validatorFlags, misbehaviors, txBytes...) 76 | 77 | res, err := n.app.FinalizeBlock(req) 78 | if err != nil { 79 | return nil, err 80 | } 81 | 82 | newCtx := n.app.BaseApp.NewContextLegacy(false, header) 83 | 84 | // Update context header 85 | newCtx = newCtx.WithMinGasPrices(n.ctx.MinGasPrices()) 86 | newCtx = newCtx.WithKVGasConfig(n.ctx.KVGasConfig()) 87 | newCtx = newCtx.WithTransientKVGasConfig(n.ctx.TransientKVGasConfig()) 88 | newCtx = newCtx.WithConsensusParams(n.ctx.ConsensusParams()) 89 | // This might have to be changed with time if we want to test gas limits 90 | newCtx = newCtx.WithBlockGasMeter(storetypes.NewInfiniteGasMeter()) 91 | newCtx = newCtx.WithVoteInfos(req.DecidedLastCommit.GetVotes()) 92 | n.ctx = newCtx 93 | 94 | // commit changes 95 | _, err = n.app.Commit() 96 | 97 | return res, err 98 | } 99 | 100 | // buildFinalizeBlockReq is a helper function to build 101 | // properly the FinalizeBlock request 102 | func BuildFinalizeBlockReq(header cmtproto.Header, validators []*cmttypes.Validator, validatorFlags []cmtproto.BlockIDFlag, misbehaviors []abcitypes.Misbehavior, txs ...[]byte) *abcitypes.RequestFinalizeBlock { 103 | // add validator's commit info to allocate corresponding tokens to validators 104 | ci := GetCommitInfo(validators, validatorFlags) 105 | return &abcitypes.RequestFinalizeBlock{ 106 | Misbehavior: misbehaviors, 107 | Height: header.Height, 108 | DecidedLastCommit: ci, 109 | Hash: header.AppHash, 110 | NextValidatorsHash: header.ValidatorsHash, 111 | ProposerAddress: header.ProposerAddress, 112 | Time: header.Time, 113 | Txs: txs, 114 | } 115 | } 116 | 117 | func GetCommitInfo(validators []*cmttypes.Validator, validatorFlags []cmtproto.BlockIDFlag) abcitypes.CommitInfo { 118 | voteInfos := make([]abcitypes.VoteInfo, len(validators)) 119 | for i, val := range validators { 120 | voteInfos[i] = abcitypes.VoteInfo{ 121 | Validator: abcitypes.Validator{ 122 | Address: val.Address, 123 | Power: val.VotingPower, 124 | }, 125 | BlockIdFlag: validatorFlags[i], 126 | } 127 | } 128 | return abcitypes.CommitInfo{Votes: voteInfos} 129 | } 130 | -------------------------------------------------------------------------------- /testutil/integration/exrp/integration/config.go: -------------------------------------------------------------------------------- 1 | // Copyright Tharsis Labs Ltd.(Evmos) 2 | // SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE) 3 | 4 | package exrpintegration 5 | 6 | import ( 7 | "fmt" 8 | 9 | sdktypes "github.com/cosmos/cosmos-sdk/types" 10 | authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 11 | banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" 12 | stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" 13 | testtx "github.com/evmos/evmos/v20/testutil/tx" 14 | exrpcommon "github.com/xrplevm/node/v8/testutil/integration/exrp/common" 15 | ) 16 | 17 | // DefaultIntegrationConfig returns the default configuration for a chain. 18 | func DefaultIntegrationConfig() exrpcommon.Config { 19 | account, _ := testtx.NewAccAddressAndKey() 20 | config := exrpcommon.DefaultConfig() 21 | config.AmountOfValidators = 3 22 | config.PreFundedAccounts = []sdktypes.AccAddress{account} 23 | return config 24 | } 25 | 26 | // getGenAccountsAndBalances takes the network configuration and returns the used 27 | // genesis accounts and balances. 28 | // 29 | // NOTE: If the balances are set, the pre-funded accounts are ignored. 30 | func getGenAccountsAndBalances(cfg exrpcommon.Config, validators []stakingtypes.Validator) (genAccounts []authtypes.GenesisAccount, balances []banktypes.Balance) { 31 | if len(cfg.Balances) > 0 { 32 | balances = cfg.Balances 33 | accounts := getAccAddrsFromBalances(balances) 34 | genAccounts = createGenesisAccounts(accounts) 35 | } else { 36 | genAccounts = createGenesisAccounts(cfg.PreFundedAccounts) 37 | balances = createBalances(cfg.PreFundedAccounts, append(cfg.OtherCoinDenom, cfg.Denom)) 38 | } 39 | 40 | // append validators to genesis accounts and balances 41 | valAccs := make([]sdktypes.AccAddress, len(validators)) 42 | for i, v := range validators { 43 | valAddr, err := sdktypes.ValAddressFromBech32(v.OperatorAddress) 44 | if err != nil { 45 | panic(fmt.Sprintf("failed to derive validator address from %q: %s", v.OperatorAddress, err.Error())) 46 | } 47 | valAccs[i] = sdktypes.AccAddress(valAddr.Bytes()) 48 | } 49 | genAccounts = append(genAccounts, createGenesisAccounts(valAccs)...) 50 | 51 | return 52 | } 53 | -------------------------------------------------------------------------------- /testutil/integration/exrp/integration/ibc.go: -------------------------------------------------------------------------------- 1 | // Copyright Tharsis Labs Ltd.(Evmos) 2 | // SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE) 3 | package exrpintegration 4 | 5 | import ( 6 | "testing" 7 | 8 | ibctesting "github.com/cosmos/ibc-go/v8/testing" 9 | ) 10 | 11 | // GetIBCChain returns a TestChain instance for the given network. 12 | // Note: the sender accounts are not populated. Do not use this accounts to send transactions during tests. 13 | // The keyring should be used instead. 14 | func (n *IntegrationNetwork) GetIBCChain(t *testing.T, coord *ibctesting.Coordinator) *ibctesting.TestChain { 15 | return &ibctesting.TestChain{ 16 | TB: t, 17 | Coordinator: coord, 18 | ChainID: n.GetChainID(), 19 | App: n.app, 20 | CurrentHeader: n.ctx.BlockHeader(), 21 | QueryServer: n.app.GetIBCKeeper(), 22 | TxConfig: n.app.GetTxConfig(), 23 | Codec: n.app.AppCodec(), 24 | Vals: n.valSet, 25 | NextVals: n.valSet, 26 | Signers: n.valSigners, 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /testutil/integration/exrp/integration/keepers.go: -------------------------------------------------------------------------------- 1 | package exrpintegration 2 | 3 | import ( 4 | authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" 5 | authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper" 6 | bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" 7 | distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" 8 | govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" 9 | slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" 10 | stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" 11 | 12 | erc20keeper "github.com/evmos/evmos/v20/x/erc20/keeper" 13 | evmkeeper "github.com/evmos/evmos/v20/x/evm/keeper" 14 | feemarketkeeper "github.com/evmos/evmos/v20/x/feemarket/keeper" 15 | poakeeper "github.com/xrplevm/node/v8/x/poa/keeper" 16 | ) 17 | 18 | func (n *IntegrationNetwork) BankKeeper() bankkeeper.Keeper { 19 | return n.app.BankKeeper 20 | } 21 | 22 | func (n *IntegrationNetwork) ERC20Keeper() erc20keeper.Keeper { 23 | return n.app.Erc20Keeper 24 | } 25 | 26 | func (n *IntegrationNetwork) EvmKeeper() evmkeeper.Keeper { 27 | return *n.app.EvmKeeper 28 | } 29 | 30 | func (n *IntegrationNetwork) GovKeeper() *govkeeper.Keeper { 31 | return &n.app.GovKeeper 32 | } 33 | 34 | func (n *IntegrationNetwork) StakingKeeper() *stakingkeeper.Keeper { 35 | return n.app.StakingKeeper.Keeper 36 | } 37 | 38 | func (n *IntegrationNetwork) SlashingKeeper() slashingkeeper.Keeper { 39 | return n.app.SlashingKeeper 40 | } 41 | 42 | func (n *IntegrationNetwork) DistrKeeper() distrkeeper.Keeper { 43 | return n.app.DistrKeeper 44 | } 45 | 46 | func (n *IntegrationNetwork) AccountKeeper() authkeeper.AccountKeeper { 47 | return n.app.AccountKeeper 48 | } 49 | 50 | func (n *IntegrationNetwork) AuthzKeeper() authzkeeper.Keeper { 51 | return n.app.AuthzKeeper 52 | } 53 | 54 | func (n *IntegrationNetwork) FeeMarketKeeper() feemarketkeeper.Keeper { 55 | return n.app.FeeMarketKeeper 56 | } 57 | 58 | func (n *IntegrationNetwork) PoaKeeper() poakeeper.Keeper { 59 | return n.app.PoaKeeper 60 | } 61 | -------------------------------------------------------------------------------- /testutil/integration/exrp/integration/unit_network.go: -------------------------------------------------------------------------------- 1 | // Copyright Tharsis Labs Ltd.(Evmos) 2 | // SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE) 3 | package exrpintegration 4 | 5 | import ( 6 | sdktypes "github.com/cosmos/cosmos-sdk/types" 7 | "github.com/ethereum/go-ethereum/common" 8 | "github.com/evmos/evmos/v20/x/evm/statedb" 9 | inflationtypes "github.com/evmos/evmos/v20/x/inflation/v1/types" 10 | "github.com/xrplevm/node/v8/app" 11 | exrpcommon "github.com/xrplevm/node/v8/testutil/integration/exrp/common" 12 | ) 13 | 14 | // UnitTestIntegrationNetwork is the implementation of the Network interface for unit tests. 15 | // It embeds the IntegrationNetwork struct to reuse its methods and 16 | // makes the App public for easier testing. 17 | type UnitTestIntegrationNetwork struct { 18 | IntegrationNetwork 19 | App *app.App 20 | } 21 | 22 | var _ Network = (*UnitTestIntegrationNetwork)(nil) 23 | 24 | // NewUnitTestNetwork configures and initializes a new Evmos Network instance with 25 | // the given configuration options. If no configuration options are provided 26 | // it uses the default configuration. 27 | // 28 | // It panics if an error occurs. 29 | // Note: Only uses for Unit Tests 30 | func NewUnitTestNetwork(opts ...exrpcommon.ConfigOption) *UnitTestIntegrationNetwork { 31 | network := New(opts...) 32 | return &UnitTestIntegrationNetwork{ 33 | IntegrationNetwork: *network, 34 | App: network.app, 35 | } 36 | } 37 | 38 | // GetStateDB returns the state database for the current block. 39 | func (n *UnitTestIntegrationNetwork) GetStateDB() *statedb.StateDB { 40 | headerHash := n.GetContext().HeaderHash() 41 | return statedb.New( 42 | n.GetContext(), 43 | n.App.EvmKeeper, 44 | statedb.NewEmptyTxConfig(common.BytesToHash(headerHash)), 45 | ) 46 | } 47 | 48 | // FundAccount funds the given account with the given amount of coins. 49 | func (n *UnitTestIntegrationNetwork) FundAccount(addr sdktypes.AccAddress, coins sdktypes.Coins) error { 50 | ctx := n.GetContext() 51 | 52 | if err := n.app.BankKeeper.MintCoins(ctx, inflationtypes.ModuleName, coins); err != nil { 53 | return err 54 | } 55 | 56 | return n.app.BankKeeper.SendCoinsFromModuleToAccount(ctx, inflationtypes.ModuleName, addr, coins) 57 | } 58 | -------------------------------------------------------------------------------- /testutil/integration/exrp/upgrade/abci.go: -------------------------------------------------------------------------------- 1 | // Copyright Tharsis Labs Ltd.(Evmos) 2 | // SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE) 3 | package exrpupgrade 4 | 5 | import ( 6 | "time" 7 | 8 | storetypes "cosmossdk.io/store/types" 9 | abcitypes "github.com/cometbft/cometbft/abci/types" 10 | cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" 11 | cmttypes "github.com/cometbft/cometbft/types" 12 | ) 13 | 14 | // NextBlock is a private helper function that runs the EndBlocker logic, commits the changes, 15 | // updates the header and runs the BeginBlocker 16 | func (n *UpgradeIntegrationNetwork) NextBlock() error { 17 | return n.NextBlockAfter(time.Second) 18 | } 19 | 20 | // NextBlockAfter is a private helper function that runs the FinalizeBlock logic, updates the context and 21 | // commits the changes to have a block time after the given duration. 22 | func (n *UpgradeIntegrationNetwork) NextBlockAfter(duration time.Duration) error { 23 | _, err := n.finalizeBlockAndCommit(duration) 24 | return err 25 | } 26 | 27 | // NextBlockWithTxs is a helper function that runs the FinalizeBlock logic 28 | // with the provided tx bytes, updates the context and 29 | // commits the changes to have a block time after the given duration. 30 | func (n *UpgradeIntegrationNetwork) NextBlockWithTxs(txBytes ...[]byte) (*abcitypes.ResponseFinalizeBlock, error) { 31 | return n.finalizeBlockAndCommit(time.Second, txBytes...) 32 | } 33 | 34 | // finalizeBlockAndCommit is a private helper function that runs the FinalizeBlock logic 35 | // with the provided txBytes, updates the context and 36 | // commits the changes to have a block time after the given duration. 37 | func (n *UpgradeIntegrationNetwork) finalizeBlockAndCommit(duration time.Duration, txBytes ...[]byte) (*abcitypes.ResponseFinalizeBlock, error) { 38 | header := n.ctx.BlockHeader() 39 | // Update block header and BeginBlock 40 | header.Height++ 41 | header.AppHash = n.app.LastCommitID().Hash 42 | // Calculate new block time after duration 43 | newBlockTime := header.Time.Add(duration) 44 | header.Time = newBlockTime 45 | 46 | // FinalizeBlock to run endBlock, deliverTx & beginBlock logic 47 | req := BuildFinalizeBlockReq(header, n.valSet.Validators, txBytes...) 48 | 49 | res, err := n.app.FinalizeBlock(req) 50 | if err != nil { 51 | return nil, err 52 | } 53 | 54 | newCtx := n.app.BaseApp.NewContextLegacy(false, header) 55 | 56 | // Update context header 57 | newCtx = newCtx.WithMinGasPrices(n.ctx.MinGasPrices()) 58 | newCtx = newCtx.WithKVGasConfig(n.ctx.KVGasConfig()) 59 | newCtx = newCtx.WithTransientKVGasConfig(n.ctx.TransientKVGasConfig()) 60 | newCtx = newCtx.WithConsensusParams(n.ctx.ConsensusParams()) 61 | // This might have to be changed with time if we want to test gas limits 62 | newCtx = newCtx.WithBlockGasMeter(storetypes.NewInfiniteGasMeter()) 63 | newCtx = newCtx.WithVoteInfos(req.DecidedLastCommit.GetVotes()) 64 | n.ctx = newCtx 65 | 66 | // commit changes 67 | _, err = n.app.Commit() 68 | 69 | return res, err 70 | } 71 | 72 | // buildFinalizeBlockReq is a helper function to build 73 | // properly the FinalizeBlock request 74 | func BuildFinalizeBlockReq(header cmtproto.Header, validators []*cmttypes.Validator, txs ...[]byte) *abcitypes.RequestFinalizeBlock { 75 | // add validator's commit info to allocate corresponding tokens to validators 76 | ci := GetCommitInfo(validators) 77 | return &abcitypes.RequestFinalizeBlock{ 78 | Misbehavior: nil, 79 | Height: header.Height, 80 | DecidedLastCommit: ci, 81 | Hash: header.AppHash, 82 | NextValidatorsHash: header.ValidatorsHash, 83 | ProposerAddress: header.ProposerAddress, 84 | Time: header.Time, 85 | Txs: txs, 86 | } 87 | } 88 | 89 | func GetCommitInfo(validators []*cmttypes.Validator) abcitypes.CommitInfo { 90 | voteInfos := make([]abcitypes.VoteInfo, len(validators)) 91 | for i, val := range validators { 92 | voteInfos[i] = abcitypes.VoteInfo{ 93 | Validator: abcitypes.Validator{ 94 | Address: val.Address, 95 | Power: val.VotingPower, 96 | }, 97 | BlockIdFlag: cmtproto.BlockIDFlagCommit, 98 | } 99 | } 100 | return abcitypes.CommitInfo{Votes: voteInfos} 101 | } 102 | -------------------------------------------------------------------------------- /testutil/integration/exrp/upgrade/config.go: -------------------------------------------------------------------------------- 1 | // Copyright Tharsis Labs Ltd.(Evmos) 2 | // SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE) 3 | 4 | package exrpupgrade 5 | 6 | import ( 7 | "os" 8 | 9 | exrpcommon "github.com/xrplevm/node/v8/testutil/integration/exrp/common" 10 | ) 11 | 12 | func DefaultUpgradeConfig() exrpcommon.Config { 13 | return exrpcommon.DefaultConfig() 14 | } 15 | 16 | // WithGenesisFile sets the genesis file for the network. 17 | func WithGenesisFile(genesisFile string) exrpcommon.ConfigOption { 18 | return func(cfg *exrpcommon.Config) { 19 | genesisBytes, err := os.ReadFile(genesisFile) 20 | if err != nil { 21 | panic(err) 22 | } 23 | cfg.GenesisBytes = genesisBytes 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /testutil/integration/exrp/upgrade/ibc.go: -------------------------------------------------------------------------------- 1 | // Copyright Tharsis Labs Ltd.(Evmos) 2 | // SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE) 3 | package exrpupgrade 4 | 5 | import ( 6 | "testing" 7 | 8 | ibctesting "github.com/cosmos/ibc-go/v8/testing" 9 | ) 10 | 11 | // GetIBCChain returns a TestChain instance for the given network. 12 | // Note: the sender accounts are not populated. Do not use this accounts to send transactions during tests. 13 | // The keyring should be used instead. 14 | func (n *UpgradeIntegrationNetwork) GetIBCChain(t *testing.T, coord *ibctesting.Coordinator) *ibctesting.TestChain { 15 | return &ibctesting.TestChain{ 16 | TB: t, 17 | Coordinator: coord, 18 | ChainID: n.GetChainID(), 19 | App: n.app, 20 | CurrentHeader: n.ctx.BlockHeader(), 21 | QueryServer: n.app.GetIBCKeeper(), 22 | TxConfig: n.app.GetTxConfig(), 23 | Codec: n.app.AppCodec(), 24 | Vals: n.valSet, 25 | NextVals: n.valSet, 26 | Signers: n.valSigners, 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /testutil/integration/exrp/upgrade/keepers.go: -------------------------------------------------------------------------------- 1 | package exrpupgrade 2 | 3 | import ( 4 | authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" 5 | authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper" 6 | bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" 7 | distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" 8 | govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" 9 | slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" 10 | stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" 11 | 12 | erc20keeper "github.com/evmos/evmos/v20/x/erc20/keeper" 13 | evmkeeper "github.com/evmos/evmos/v20/x/evm/keeper" 14 | feemarketkeeper "github.com/evmos/evmos/v20/x/feemarket/keeper" 15 | poakeeper "github.com/xrplevm/node/v8/x/poa/keeper" 16 | ) 17 | 18 | func (n *UpgradeIntegrationNetwork) BankKeeper() bankkeeper.Keeper { 19 | return n.app.BankKeeper 20 | } 21 | 22 | func (n *UpgradeIntegrationNetwork) ERC20Keeper() erc20keeper.Keeper { 23 | return n.app.Erc20Keeper 24 | } 25 | 26 | func (n *UpgradeIntegrationNetwork) EvmKeeper() evmkeeper.Keeper { 27 | return *n.app.EvmKeeper 28 | } 29 | 30 | func (n *UpgradeIntegrationNetwork) GovKeeper() *govkeeper.Keeper { 31 | return &n.app.GovKeeper 32 | } 33 | 34 | func (n *UpgradeIntegrationNetwork) StakingKeeper() *stakingkeeper.Keeper { 35 | return n.app.StakingKeeper.Keeper 36 | } 37 | 38 | func (n *UpgradeIntegrationNetwork) SlashingKeeper() slashingkeeper.Keeper { 39 | return n.app.SlashingKeeper 40 | } 41 | 42 | func (n *UpgradeIntegrationNetwork) DistrKeeper() distrkeeper.Keeper { 43 | return n.app.DistrKeeper 44 | } 45 | 46 | func (n *UpgradeIntegrationNetwork) AccountKeeper() authkeeper.AccountKeeper { 47 | return n.app.AccountKeeper 48 | } 49 | 50 | func (n *UpgradeIntegrationNetwork) AuthzKeeper() authzkeeper.Keeper { 51 | return n.app.AuthzKeeper 52 | } 53 | 54 | func (n *UpgradeIntegrationNetwork) FeeMarketKeeper() feemarketkeeper.Keeper { 55 | return n.app.FeeMarketKeeper 56 | } 57 | 58 | func (n *UpgradeIntegrationNetwork) PoaKeeper() poakeeper.Keeper { 59 | return n.app.PoaKeeper 60 | } 61 | -------------------------------------------------------------------------------- /testutil/integration/exrp/upgrade/unit_network.go: -------------------------------------------------------------------------------- 1 | // Copyright Tharsis Labs Ltd.(Evmos) 2 | // SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE) 3 | package exrpupgrade 4 | 5 | import ( 6 | sdktypes "github.com/cosmos/cosmos-sdk/types" 7 | "github.com/ethereum/go-ethereum/common" 8 | "github.com/evmos/evmos/v20/x/evm/statedb" 9 | inflationtypes "github.com/evmos/evmos/v20/x/inflation/v1/types" 10 | "github.com/xrplevm/node/v8/app" 11 | exrpcommon "github.com/xrplevm/node/v8/testutil/integration/exrp/common" 12 | ) 13 | 14 | // UnitTestUpgradeNetwork is the implementation of the Network interface for unit tests. 15 | // It embeds the IntegrationNetwork struct to reuse its methods and 16 | // makes the App public for easier testing. 17 | type UnitTestUpgradeNetwork struct { 18 | UpgradeIntegrationNetwork 19 | App *app.App 20 | } 21 | 22 | var _ Network = (*UnitTestUpgradeNetwork)(nil) 23 | 24 | // NewUnitTestNetwork configures and initializes a new Evmos Network instance with 25 | // the given configuration options. If no configuration options are provided 26 | // it uses the default configuration. 27 | // 28 | // It panics if an error occurs. 29 | // Note: Only uses for Unit Tests 30 | func NewUnitTestUpgradeNetwork(opts ...exrpcommon.ConfigOption) *UnitTestUpgradeNetwork { 31 | network := New(opts...) 32 | return &UnitTestUpgradeNetwork{ 33 | UpgradeIntegrationNetwork: *network, 34 | App: network.app, 35 | } 36 | } 37 | 38 | // GetStateDB returns the state database for the current block. 39 | func (n *UnitTestUpgradeNetwork) GetStateDB() *statedb.StateDB { 40 | headerHash := n.GetContext().HeaderHash() 41 | return statedb.New( 42 | n.GetContext(), 43 | n.App.EvmKeeper, 44 | statedb.NewEmptyTxConfig(common.BytesToHash(headerHash)), 45 | ) 46 | } 47 | 48 | // FundAccount funds the given account with the given amount of coins. 49 | func (n *UnitTestUpgradeNetwork) FundAccount(addr sdktypes.AccAddress, coins sdktypes.Coins) error { 50 | ctx := n.GetContext() 51 | 52 | if err := n.app.BankKeeper.MintCoins(ctx, inflationtypes.ModuleName, coins); err != nil { 53 | return err 54 | } 55 | 56 | return n.app.BankKeeper.SendCoinsFromModuleToAccount(ctx, inflationtypes.ModuleName, addr, coins) 57 | } 58 | -------------------------------------------------------------------------------- /testutil/integration/exrp/utils/abci.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" 5 | ) 6 | 7 | type ValidatorFlagOverride struct { 8 | Index int 9 | Flag cmtproto.BlockIDFlag 10 | } 11 | 12 | func NewValidatorFlagOverride(index int, flag cmtproto.BlockIDFlag) ValidatorFlagOverride { 13 | return ValidatorFlagOverride{ 14 | Index: index, 15 | Flag: flag, 16 | } 17 | } 18 | 19 | func NewValidatorFlags(n int, overrides ...ValidatorFlagOverride) []cmtproto.BlockIDFlag { 20 | flags := make([]cmtproto.BlockIDFlag, n) 21 | for i := range flags { 22 | flags[i] = cmtproto.BlockIDFlagCommit 23 | } 24 | 25 | for _, override := range overrides { 26 | flags[override.Index] = override.Flag 27 | } 28 | 29 | return flags 30 | } 31 | -------------------------------------------------------------------------------- /testutil/sample/sample.go: -------------------------------------------------------------------------------- 1 | package sample 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" 5 | sdk "github.com/cosmos/cosmos-sdk/types" 6 | ) 7 | 8 | // AccAddress returns a sample account address 9 | func AccAddress() string { 10 | pk := ed25519.GenPrivKey().PubKey() 11 | addr := pk.Address() 12 | return sdk.AccAddress(addr).String() 13 | } 14 | -------------------------------------------------------------------------------- /tools/cosmovisor/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.20-alpine AS build 2 | 3 | ENV COSMOS_VERSION=v0.46.12 4 | 5 | RUN apk update 6 | RUN apk add --no-cache gcc libc-dev make git 7 | 8 | WORKDIR /root 9 | RUN git clone --depth 1 --branch $COSMOS_VERSION https://github.com/cosmos/cosmos-sdk.git 10 | WORKDIR /root/cosmos-sdk/cosmovisor 11 | RUN make cosmovisor 12 | 13 | 14 | FROM alpine:3.17.3 15 | 16 | ENV DAEMON_HOME=/root/.exrpd 17 | ENV DAEMON_NAME=exrpd 18 | ENV DAEMON_ALLOW_DOWNLOAD_BINARIES=true 19 | ENV DAEMON_RESTART_AFTER_UPGRADE=true 20 | 21 | COPY --from=build /root/cosmos-sdk/cosmovisor/cosmovisor /usr/local/bin/cosmovisor 22 | COPY --from=peersyst/xrp-evm-blockchain:latest /usr/bin/exrpd /usr/local/bin/exrpd 23 | COPY --from=peersyst/exrp:v2.0.0 /usr/bin/exrpd /usr/local/bin/exrpd_v2.0.0 24 | COPY --from=peersyst/exrp:v3.0.0 /usr/bin/exrpd /usr/local/bin/exrpd_v3.0.0 25 | 26 | ADD tools/cosmovisor/init.sh /usr/local/bin/initialize 27 | RUN chmod +x /usr/local/bin/initialize 28 | 29 | RUN apk add gcompat 30 | RUN ln -sf ../../lib/libgcompat.so.0 /usr/lib/libresolv.so.2 31 | 32 | CMD ["cosmovisor"] 33 | -------------------------------------------------------------------------------- /tools/cosmovisor/init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | mkdir -p $DAEMON_HOME/cosmovisor/genesis/bin 4 | ln -s /usr/local/bin/exrpd $DAEMON_HOME/cosmovisor/genesis/bin/exrpd 5 | mkdir -p $DAEMON_HOME/cosmovisor/upgrades/v2.0.0/bin 6 | cp /usr/local/bin/exrpd_v2.0.0 $DAEMON_HOME/cosmovisor/upgrades/v2.0.0/bin/exrpd 7 | mkdir -p $DAEMON_HOME/cosmovisor/upgrades/v3.0.0/bin 8 | cp /usr/local/bin/exrpd_v3.0.0 $DAEMON_HOME/cosmovisor/upgrades/v3.0.0/bin/exrpd 9 | 10 | ln -s $DAEMON_HOME/cosmovisor/upgrades/v2.0.0 $DAEMON_HOME/cosmovisor/current -------------------------------------------------------------------------------- /tools/tools.go: -------------------------------------------------------------------------------- 1 | //go:build tools 2 | 3 | package tools 4 | 5 | import ( 6 | _ "github.com/cosmos/gogoproto/protoc-gen-gocosmos" 7 | _ "github.com/golang/protobuf/protoc-gen-go" 8 | _ "github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway" 9 | _ "github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger" 10 | _ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2" 11 | ) 12 | -------------------------------------------------------------------------------- /x/poa/ante/poa.go: -------------------------------------------------------------------------------- 1 | package ante 2 | 3 | import ( 4 | "errors" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" 8 | ) 9 | 10 | type PoaDecorator struct{} 11 | 12 | func NewPoaDecorator() PoaDecorator { 13 | return PoaDecorator{} 14 | } 15 | 16 | func (cbd PoaDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) { 17 | // loop through all the messages and check if the message type is allowed 18 | for _, msg := range tx.GetMsgs() { 19 | if sdk.MsgTypeURL(msg) == sdk.MsgTypeURL(&stakingtypes.MsgUndelegate{}) || 20 | sdk.MsgTypeURL(msg) == sdk.MsgTypeURL(&stakingtypes.MsgBeginRedelegate{}) || 21 | sdk.MsgTypeURL(msg) == sdk.MsgTypeURL(&stakingtypes.MsgDelegate{}) || 22 | sdk.MsgTypeURL(msg) == sdk.MsgTypeURL(&stakingtypes.MsgCancelUnbondingDelegation{}) { 23 | return ctx, errors.New("tx type not allowed") 24 | } 25 | } 26 | 27 | return next(ctx, tx, simulate) 28 | } 29 | -------------------------------------------------------------------------------- /x/poa/ante/poa_test.go: -------------------------------------------------------------------------------- 1 | package ante 2 | 3 | import ( 4 | "errors" 5 | "testing" 6 | "time" 7 | 8 | storetypes "cosmossdk.io/store/types" 9 | 10 | tmproto "github.com/cometbft/cometbft/proto/tendermint/types" 11 | sdktestutil "github.com/cosmos/cosmos-sdk/testutil" 12 | sdk "github.com/cosmos/cosmos-sdk/types" 13 | stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" 14 | "github.com/golang/mock/gomock" 15 | "github.com/stretchr/testify/require" 16 | "github.com/xrplevm/node/v8/x/poa/testutil" 17 | "github.com/xrplevm/node/v8/x/poa/types" 18 | ) 19 | 20 | func setupPoaDecorator(t *testing.T) ( 21 | PoaDecorator, 22 | sdk.Context, 23 | ) { 24 | key := storetypes.NewKVStoreKey(types.StoreKey) 25 | tsKey := storetypes.NewTransientStoreKey("transient_test") 26 | testCtx := sdktestutil.DefaultContextWithDB(t, key, tsKey) 27 | ctx := testCtx.Ctx.WithBlockHeader(tmproto.Header{Time: time.Now()}) 28 | 29 | return NewPoaDecorator(), ctx 30 | } 31 | 32 | func TestPoaDecorator_AnteHandle(t *testing.T) { 33 | tt := []struct { 34 | name string 35 | msgs []sdk.Msg 36 | expectedError error 37 | }{ 38 | { 39 | name: "should return error - tx not allowed", 40 | msgs: []sdk.Msg{ 41 | &stakingtypes.MsgUndelegate{}, 42 | &stakingtypes.MsgBeginRedelegate{}, 43 | &stakingtypes.MsgDelegate{}, 44 | &stakingtypes.MsgCancelUnbondingDelegation{}, 45 | }, 46 | expectedError: errors.New("tx type not allowed"), 47 | }, 48 | { 49 | name: "should not return error", 50 | msgs: []sdk.Msg{ 51 | &stakingtypes.MsgEditValidator{}, 52 | }, 53 | }, 54 | } 55 | 56 | for _, tc := range tt { 57 | pd, ctx := setupPoaDecorator(t) 58 | 59 | ctrl := gomock.NewController(t) 60 | txMock := testutil.NewMockTx(ctrl) 61 | txMock.EXPECT().GetMsgs().Return(tc.msgs).AnyTimes() 62 | 63 | mockNext := func(ctx sdk.Context, _ sdk.Tx, _ bool) (sdk.Context, error) { 64 | return ctx, nil 65 | } 66 | 67 | _, err := pd.AnteHandle(ctx, txMock, false, mockNext) 68 | if tc.expectedError != nil { 69 | require.Error(t, err) 70 | require.Equal(t, tc.expectedError, err) 71 | } else { 72 | require.NoError(t, err) 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /x/poa/keeper/common_test.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | storetypes "cosmossdk.io/store/types" 8 | tmproto "github.com/cometbft/cometbft/proto/tendermint/types" 9 | "github.com/cosmos/cosmos-sdk/baseapp" 10 | 11 | sdktestutil "github.com/cosmos/cosmos-sdk/testutil" 12 | sdk "github.com/cosmos/cosmos-sdk/types" 13 | moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" 14 | paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" 15 | "github.com/golang/mock/gomock" 16 | "github.com/xrplevm/node/v8/x/poa/testutil" 17 | "github.com/xrplevm/node/v8/x/poa/types" 18 | 19 | stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" 20 | ) 21 | 22 | const ( 23 | accountAddressPrefix = "ethm" 24 | bip44CoinType = 60 25 | ) 26 | 27 | func setupSdkConfig() { 28 | accountPubKeyPrefix := accountAddressPrefix + "pub" 29 | validatorAddressPrefix := accountAddressPrefix + "valoper" 30 | validatorPubKeyPrefix := accountAddressPrefix + "valoperpub" 31 | consNodeAddressPrefix := accountAddressPrefix + "valcons" 32 | consNodePubKeyPrefix := accountAddressPrefix + "valconspub" 33 | 34 | // Set config 35 | config := sdk.GetConfig() 36 | config.SetBech32PrefixForAccount(accountAddressPrefix, accountPubKeyPrefix) 37 | config.SetBech32PrefixForValidator(validatorAddressPrefix, validatorPubKeyPrefix) 38 | config.SetBech32PrefixForConsensusNode(consNodeAddressPrefix, consNodePubKeyPrefix) 39 | config.SetCoinType(bip44CoinType) 40 | config.SetPurpose(sdk.Purpose) // Shared 41 | } 42 | 43 | func getStakingKeeperMock(t *testing.T, ctx sdk.Context, setExpectations func(ctx sdk.Context, stakingKeeper *testutil.MockStakingKeeper)) *testutil.MockStakingKeeper { 44 | ctrl := gomock.NewController(t) 45 | stakingKeeper := testutil.NewMockStakingKeeper(ctrl) 46 | setExpectations(ctx, stakingKeeper) 47 | return stakingKeeper 48 | } 49 | 50 | func getBankKeeperMock(t *testing.T, ctx sdk.Context, setExpectations func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper)) *testutil.MockBankKeeper { 51 | ctrl := gomock.NewController(t) 52 | bankKeeper := testutil.NewMockBankKeeper(ctrl) 53 | setExpectations(ctx, bankKeeper) 54 | return bankKeeper 55 | } 56 | 57 | func getCtxMock(t *testing.T, key *storetypes.KVStoreKey, tsKey *storetypes.TransientStoreKey) sdk.Context { 58 | setupSdkConfig() 59 | 60 | testCtx := sdktestutil.DefaultContextWithDB(t, key, tsKey) 61 | ctx := testCtx.Ctx.WithBlockHeader(tmproto.Header{Time: time.Now()}) 62 | return ctx 63 | } 64 | 65 | func getMockedPoAKeeper(t *testing.T, key *storetypes.KVStoreKey, tsKey *storetypes.TransientStoreKey, ctx sdk.Context, stakingKeeper *testutil.MockStakingKeeper, bankKeeper *testutil.MockBankKeeper) *Keeper { 66 | encCfg := moduletestutil.MakeTestEncodingConfig() 67 | 68 | types.RegisterInterfaces(encCfg.InterfaceRegistry) 69 | stakingtypes.RegisterInterfaces(encCfg.InterfaceRegistry) 70 | 71 | msr := baseapp.NewMsgServiceRouter() 72 | msr.SetInterfaceRegistry(encCfg.InterfaceRegistry) 73 | 74 | ctrl := gomock.NewController(t) 75 | stakingMsr := testutil.NewMockStakingMsgServer(ctrl) 76 | 77 | stakingMsr.EXPECT().CreateValidator(gomock.Any(), gomock.Any()).Return(&stakingtypes.MsgCreateValidatorResponse{}, nil).AnyTimes() 78 | 79 | poaKeeper := NewKeeper( 80 | encCfg.Codec, 81 | paramtypes.NewSubspace(encCfg.Codec, encCfg.Amino, key, tsKey, "poa"), 82 | msr, 83 | bankKeeper, 84 | stakingKeeper, 85 | "ethm1wunfhl05vc8r8xxnnp8gt62wa54r6y52pg03zq", 86 | ) 87 | poaKeeper.SetParams(ctx, types.DefaultParams()) 88 | types.RegisterMsgServer(msr, NewMsgServerImpl(*poaKeeper)) 89 | stakingtypes.RegisterMsgServer(msr, stakingMsr) 90 | 91 | return poaKeeper 92 | } 93 | 94 | func setupPoaKeeper(t *testing.T, setStakingExpectations func(ctx sdk.Context, stakingKeeper *testutil.MockStakingKeeper), setBankExpectations func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper)) (*Keeper, sdk.Context) { 95 | key := storetypes.NewKVStoreKey(types.StoreKey) 96 | tsKey := storetypes.NewTransientStoreKey("test") 97 | 98 | ctx := getCtxMock(t, key, tsKey) 99 | stakingKeeper := getStakingKeeperMock(t, ctx, setStakingExpectations) 100 | bankKeeper := getBankKeeperMock(t, ctx, setBankExpectations) 101 | 102 | return getMockedPoAKeeper(t, key, tsKey, ctx, stakingKeeper, bankKeeper), ctx 103 | } 104 | -------------------------------------------------------------------------------- /x/poa/keeper/genesis.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | "github.com/xrplevm/node/v8/x/poa/types" 6 | ) 7 | 8 | // InitGenesis initializes the module's state from a provided genesis state. 9 | func (k Keeper) InitGenesis(ctx sdk.Context, genState types.GenesisState) { 10 | // this line is used by starport scaffolding # genesis/module/init 11 | k.SetParams(ctx, genState.Params) 12 | } 13 | 14 | // ExportGenesis returns the module's exported genesis 15 | func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { 16 | genesis := types.DefaultGenesis() 17 | genesis.Params = k.GetParams(ctx) 18 | 19 | // this line is used by starport scaffolding # genesis/module/export 20 | 21 | return genesis 22 | } 23 | -------------------------------------------------------------------------------- /x/poa/keeper/msg_server.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "github.com/xrplevm/node/v8/x/poa/types" 5 | ) 6 | 7 | type msgServer struct { 8 | Keeper 9 | } 10 | 11 | // NewMsgServerImpl returns an implementation of the MsgServer interface 12 | // for the provided Keeper. 13 | func NewMsgServerImpl(keeper Keeper) types.MsgServer { 14 | return &msgServer{Keeper: keeper} 15 | } 16 | 17 | var _ types.MsgServer = msgServer{} 18 | -------------------------------------------------------------------------------- /x/poa/keeper/msg_server_add_validator.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "context" 5 | 6 | "cosmossdk.io/errors" 7 | 8 | sdk "github.com/cosmos/cosmos-sdk/types" 9 | gov "github.com/cosmos/cosmos-sdk/x/gov/types" 10 | "github.com/xrplevm/node/v8/x/poa/types" 11 | ) 12 | 13 | func (k msgServer) AddValidator(goCtx context.Context, msg *types.MsgAddValidator) (*types.MsgAddValidatorResponse, error) { 14 | if k.authority != msg.Authority { 15 | return nil, errors.Wrapf(gov.ErrInvalidSigner, "expected %s got %s", k.authority, msg.Authority) 16 | } 17 | 18 | ctx := sdk.UnwrapSDKContext(goCtx) 19 | err := k.ExecuteAddValidator(ctx, msg) 20 | if err != nil { 21 | return nil, err 22 | } 23 | 24 | return &types.MsgAddValidatorResponse{}, nil 25 | } 26 | -------------------------------------------------------------------------------- /x/poa/keeper/msg_server_add_validator_test.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "errors" 5 | "testing" 6 | 7 | types1 "github.com/cosmos/cosmos-sdk/codec/types" 8 | govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" 9 | stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" 10 | "github.com/golang/mock/gomock" 11 | "github.com/stretchr/testify/require" 12 | "github.com/xrplevm/node/v8/x/poa/testutil" 13 | "github.com/xrplevm/node/v8/x/poa/types" 14 | ) 15 | 16 | func TestMsgServer_AddValidator(t *testing.T) { 17 | poaKeeper, ctx := poaKeeperTestSetup(t) 18 | 19 | ctrl := gomock.NewController(t) 20 | pubKey := testutil.NewMockPubKey(ctrl) 21 | msgPubKey, _ := types1.NewAnyWithValue(pubKey) 22 | msgServer := NewMsgServerImpl(*poaKeeper) 23 | 24 | tt := []struct { 25 | name string 26 | authority string 27 | validatorAddress string 28 | expectedErr error 29 | }{ 30 | { 31 | name: "should fail - invalid authority address", 32 | authority: "invalidauthority", 33 | validatorAddress: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", 34 | expectedErr: govtypes.ErrInvalidSigner, 35 | }, 36 | { 37 | name: "should fail - invalid validator address", 38 | authority: poaKeeper.GetAuthority(), 39 | validatorAddress: "invalidvalidatoraddress", 40 | expectedErr: errors.New("decoding bech32 failed"), 41 | }, 42 | { 43 | name: "should pass", 44 | authority: poaKeeper.GetAuthority(), 45 | validatorAddress: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", 46 | }, 47 | } 48 | 49 | for _, tc := range tt { 50 | t.Run(tc.name, func(t *testing.T) { 51 | msg := &types.MsgAddValidator{ 52 | Authority: tc.authority, 53 | ValidatorAddress: tc.validatorAddress, 54 | Description: stakingtypes.Description{ 55 | Moniker: "test", 56 | Identity: "test", 57 | Website: "test", 58 | SecurityContact: "test", 59 | Details: "test", 60 | }, 61 | Pubkey: msgPubKey, 62 | } 63 | 64 | _, err := msgServer.AddValidator(ctx, msg) 65 | if tc.expectedErr != nil { 66 | require.Error(t, err) 67 | require.Contains(t, err.Error(), tc.expectedErr.Error()) 68 | } else { 69 | require.NoError(t, err) 70 | } 71 | }) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /x/poa/keeper/msg_server_remove_validator.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "context" 5 | 6 | "cosmossdk.io/errors" 7 | 8 | gov "github.com/cosmos/cosmos-sdk/x/gov/types" 9 | 10 | sdk "github.com/cosmos/cosmos-sdk/types" 11 | "github.com/xrplevm/node/v8/x/poa/types" 12 | ) 13 | 14 | func (k msgServer) RemoveValidator(goCtx context.Context, msg *types.MsgRemoveValidator) (*types.MsgRemoveValidatorResponse, error) { 15 | if k.authority != msg.Authority { 16 | return nil, errors.Wrapf(gov.ErrInvalidSigner, "expected %s got %s", k.authority, msg.Authority) 17 | } 18 | 19 | ctx := sdk.UnwrapSDKContext(goCtx) 20 | err := k.ExecuteRemoveValidator(ctx, msg.ValidatorAddress) 21 | if err != nil { 22 | return nil, err 23 | } 24 | 25 | return &types.MsgRemoveValidatorResponse{}, nil 26 | } 27 | -------------------------------------------------------------------------------- /x/poa/keeper/msg_server_remove_validator_test.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "errors" 5 | "testing" 6 | 7 | govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" 8 | "github.com/stretchr/testify/require" 9 | "github.com/xrplevm/node/v8/x/poa/types" 10 | ) 11 | 12 | func TestMsgServer_RemoveValidator(t *testing.T) { 13 | poaKeeper, ctx := poaKeeperTestSetup(t) 14 | 15 | msgServer := NewMsgServerImpl(*poaKeeper) 16 | 17 | tt := []struct { 18 | name string 19 | authority string 20 | validatorAddress string 21 | expectedErr error 22 | }{ 23 | { 24 | name: "should fail - invalid authority address", 25 | authority: "invalidauthority", 26 | validatorAddress: "ethmvaloper1a0pd5cyew47pvgf7rd7axxy3humv9ev0urudmu", 27 | expectedErr: govtypes.ErrInvalidSigner, 28 | }, 29 | { 30 | name: "should fail - invalid validator address", 31 | authority: poaKeeper.GetAuthority(), 32 | validatorAddress: "invalidvalidatoraddress", 33 | expectedErr: errors.New("decoding bech32 failed"), 34 | }, 35 | { 36 | name: "should pass", 37 | authority: poaKeeper.GetAuthority(), 38 | validatorAddress: "ethmvaloper1a0pd5cyew47pvgf7rd7axxy3humv9ev0urudmu", 39 | }, 40 | } 41 | 42 | for _, tc := range tt { 43 | t.Run(tc.name, func(t *testing.T) { 44 | msg := &types.MsgRemoveValidator{ 45 | Authority: tc.authority, 46 | ValidatorAddress: tc.validatorAddress, 47 | } 48 | 49 | _, err := msgServer.RemoveValidator(ctx, msg) 50 | if tc.expectedErr != nil { 51 | require.Error(t, err) 52 | require.Contains(t, err.Error(), tc.expectedErr.Error()) 53 | } else { 54 | require.NoError(t, err) 55 | } 56 | }) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /x/poa/keeper/params.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | "github.com/xrplevm/node/v8/x/poa/types" 6 | ) 7 | 8 | // GetParams get all parameters as types.Params 9 | func (k Keeper) GetParams(_ sdk.Context) types.Params { 10 | return types.NewParams() 11 | } 12 | 13 | // SetParams set the params 14 | func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { 15 | k.paramstore.SetParamSet(ctx, ¶ms) 16 | } 17 | -------------------------------------------------------------------------------- /x/poa/keeper/query.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "github.com/xrplevm/node/v8/x/poa/types" 5 | ) 6 | 7 | var _ types.QueryServer = Keeper{} 8 | -------------------------------------------------------------------------------- /x/poa/keeper/query_params.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "context" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | "github.com/xrplevm/node/v8/x/poa/types" 8 | "google.golang.org/grpc/codes" 9 | "google.golang.org/grpc/status" 10 | ) 11 | 12 | func (k Keeper) Params(goCtx context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { 13 | if req == nil { 14 | return nil, status.Error(codes.InvalidArgument, "invalid request") 15 | } 16 | ctx := sdk.UnwrapSDKContext(goCtx) 17 | 18 | return &types.QueryParamsResponse{Params: k.GetParams(ctx)}, nil 19 | } 20 | -------------------------------------------------------------------------------- /x/poa/module.go: -------------------------------------------------------------------------------- 1 | package poa 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | 8 | "cosmossdk.io/core/appmodule" 9 | 10 | // this line is used by starport scaffolding # 1 11 | 12 | "github.com/cosmos/cosmos-sdk/client" 13 | "github.com/cosmos/cosmos-sdk/codec" 14 | cdctypes "github.com/cosmos/cosmos-sdk/codec/types" 15 | sdk "github.com/cosmos/cosmos-sdk/types" 16 | "github.com/cosmos/cosmos-sdk/types/module" 17 | "github.com/grpc-ecosystem/grpc-gateway/runtime" 18 | "github.com/xrplevm/node/v8/x/poa/keeper" 19 | "github.com/xrplevm/node/v8/x/poa/types" 20 | ) 21 | 22 | var ( 23 | _ module.AppModuleBasic = (*AppModule)(nil) 24 | _ module.AppModuleSimulation = (*AppModule)(nil) 25 | _ module.HasGenesis = (*AppModule)(nil) 26 | _ appmodule.AppModule = (*AppModule)(nil) 27 | ) 28 | 29 | // ---------------------------------------------------------------------------- 30 | // AppModuleBasic 31 | // ---------------------------------------------------------------------------- 32 | 33 | // AppModuleBasic implements the AppModuleBasic interface that defines the independent methods a Cosmos SDK module needs to implement. 34 | type AppModuleBasic struct { 35 | cdc codec.BinaryCodec 36 | } 37 | 38 | func NewAppModuleBasic(cdc codec.BinaryCodec) AppModuleBasic { 39 | return AppModuleBasic{cdc: cdc} 40 | } 41 | 42 | // Name returns the name of the module as a string 43 | func (AppModuleBasic) Name() string { 44 | return types.ModuleName 45 | } 46 | 47 | // RegisterLegacyAminoCodec registers the amino codec for the module, which is used to marshal and unmarshal structs to/from []byte in order to persist them in the module's KVStore 48 | func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { 49 | types.RegisterCodec(cdc) 50 | } 51 | 52 | // RegisterInterfaces registers a module's interface types and their concrete implementations as proto.Message 53 | func (a AppModuleBasic) RegisterInterfaces(reg cdctypes.InterfaceRegistry) { 54 | types.RegisterInterfaces(reg) 55 | } 56 | 57 | // DefaultGenesis returns a default GenesisState for the module, marshaled to json.RawMessage. The default GenesisState need to be defined by the module developer and is primarily used for testing 58 | func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { 59 | return cdc.MustMarshalJSON(types.DefaultGenesis()) 60 | } 61 | 62 | // ValidateGenesis used to validate the GenesisState, given in its json.RawMessage form 63 | func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, _ client.TxEncodingConfig, bz json.RawMessage) error { 64 | var genState types.GenesisState 65 | if err := cdc.UnmarshalJSON(bz, &genState); err != nil { 66 | return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err) 67 | } 68 | return genState.Validate() 69 | } 70 | 71 | // RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the module 72 | func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) { 73 | if err := types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)); err != nil { 74 | panic(err) 75 | } 76 | } 77 | 78 | // ---------------------------------------------------------------------------- 79 | // AppModule 80 | // ---------------------------------------------------------------------------- 81 | 82 | // AppModule implements the AppModule interface that defines the inter-dependent methods that modules need to implement 83 | type AppModule struct { 84 | AppModuleBasic 85 | keeper keeper.Keeper 86 | bk types.BankKeeper 87 | sk types.StakingKeeper 88 | ak types.AccountKeeper 89 | registry cdctypes.InterfaceRegistry 90 | } 91 | 92 | func NewAppModule( 93 | cdc codec.Codec, 94 | keeper keeper.Keeper, 95 | bk types.BankKeeper, 96 | sk types.StakingKeeper, 97 | ak types.AccountKeeper, 98 | registry cdctypes.InterfaceRegistry, 99 | ) AppModule { 100 | return AppModule{ 101 | AppModuleBasic: NewAppModuleBasic(cdc), 102 | keeper: keeper, 103 | bk: bk, 104 | sk: sk, 105 | ak: ak, 106 | registry: registry, 107 | } 108 | } 109 | 110 | // RegisterServices registers a gRPC query service to respond to the module-specific gRPC queries 111 | func (am AppModule) RegisterServices(cfg module.Configurator) { 112 | types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) 113 | types.RegisterQueryServer(cfg.QueryServer(), am.keeper) 114 | } 115 | 116 | // RegisterInvariants registers the invariants of the module. If an invariant deviates from its predicted value, the InvariantRegistry triggers appropriate logic (most often the chain will be halted) 117 | func (am AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {} 118 | 119 | // InitGenesis performs the module's genesis initialization. It returns no validator updates. 120 | func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, gs json.RawMessage) { 121 | var genState types.GenesisState 122 | // Initialize global index to index in genesis state 123 | cdc.MustUnmarshalJSON(gs, &genState) 124 | 125 | am.keeper.InitGenesis(ctx, genState) 126 | 127 | // To create module account 128 | am.ak.GetModuleAccount(ctx, am.Name()) 129 | } 130 | 131 | // ExportGenesis returns the module's exported genesis state as raw JSON bytes. 132 | func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage { 133 | genState := am.keeper.ExportGenesis(ctx) 134 | return cdc.MustMarshalJSON(genState) 135 | } 136 | 137 | // ConsensusVersion is a sequence number for state-breaking change of the module. It should be incremented on each consensus-breaking change introduced by the module. To avoid wrong/empty versions, the initial version should be set to 1 138 | func (AppModule) ConsensusVersion() uint64 { return 1 } 139 | 140 | // IsOnePerModuleType implements the depinject.OnePerModuleType interface. 141 | func (am AppModule) IsOnePerModuleType() {} 142 | 143 | // IsAppModule implements the appmodule.AppModule interface. 144 | func (am AppModule) IsAppModule() {} 145 | -------------------------------------------------------------------------------- /x/poa/module_simulation.go: -------------------------------------------------------------------------------- 1 | package poa 2 | 3 | import ( 4 | "math/rand" 5 | 6 | "github.com/cosmos/cosmos-sdk/baseapp" 7 | "github.com/cosmos/cosmos-sdk/types/module" 8 | simtypes "github.com/cosmos/cosmos-sdk/types/simulation" 9 | 10 | "github.com/cosmos/cosmos-sdk/x/simulation" 11 | 12 | "github.com/xrplevm/node/v8/testutil/sample" 13 | poasimulation "github.com/xrplevm/node/v8/x/poa/simulation" 14 | "github.com/xrplevm/node/v8/x/poa/types" 15 | ) 16 | 17 | // avoid unused import issue 18 | var ( 19 | _ = sample.AccAddress 20 | _ = simulation.MsgEntryKind 21 | _ = baseapp.Paramspace 22 | _ = rand.Rand{} 23 | ) 24 | 25 | const ( 26 | // this line is used by starport scaffolding # simapp/module/const 27 | ) 28 | 29 | // GenerateGenesisState creates a randomized GenState of the module 30 | func (AppModule) GenerateGenesisState(simState *module.SimulationState) { 31 | accs := make([]string, len(simState.Accounts)) 32 | for i, acc := range simState.Accounts { 33 | accs[i] = acc.Address.String() 34 | } 35 | poaGenesis := types.GenesisState{ 36 | Params: types.DefaultParams(), 37 | // this line is used by starport scaffolding # simapp/module/genesisState 38 | } 39 | simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(&poaGenesis) 40 | } 41 | 42 | // ProposalMsgs returns msgs used for governance proposals for simulations. 43 | func (am AppModule) ProposalMsgs(_ module.SimulationState) []simtypes.WeightedProposalMsg { 44 | return poasimulation.ProposalMsgs() 45 | } 46 | 47 | // RegisterStoreDecoder registers a decoder 48 | func (am AppModule) RegisterStoreDecoder(_ simtypes.StoreDecoderRegistry) {} 49 | 50 | // WeightedOperations returns the all the gov module operations with their respective weights. 51 | func (am AppModule) WeightedOperations(_ module.SimulationState) []simtypes.WeightedOperation { 52 | operations := make([]simtypes.WeightedOperation, 0) 53 | // this line is used by starport scaffolding # simapp/module/operation 54 | 55 | return operations 56 | } 57 | -------------------------------------------------------------------------------- /x/poa/simulation/proposals.go: -------------------------------------------------------------------------------- 1 | package simulation 2 | 3 | import ( 4 | "math/rand" 5 | 6 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | "github.com/cosmos/cosmos-sdk/types/address" 9 | simtypes "github.com/cosmos/cosmos-sdk/types/simulation" 10 | "github.com/cosmos/cosmos-sdk/x/simulation" 11 | stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" 12 | "github.com/xrplevm/node/v8/x/poa/types" 13 | ) 14 | 15 | const ( 16 | //nolint:gosec 17 | OpWeightMsgAddValidator = "op_weight_msg_add_validator" 18 | DefaultWeightMsgAddValidator int = 100 19 | 20 | //nolint:gosec 21 | OpWeightMsgRemoveValidator = "op_weight_msg_remove_validator" 22 | DefaultWeightMsgRemoveValidator int = 5 23 | ) 24 | 25 | func ProposalMsgs() []simtypes.WeightedProposalMsg { 26 | return []simtypes.WeightedProposalMsg{ 27 | simulation.NewWeightedProposalMsg( 28 | OpWeightMsgAddValidator, 29 | DefaultWeightMsgAddValidator, 30 | simulateMsgAddValidator, 31 | ), 32 | simulation.NewWeightedProposalMsg( 33 | OpWeightMsgRemoveValidator, 34 | DefaultWeightMsgRemoveValidator, 35 | simulateMsgRemoveValidator, 36 | ), 37 | } 38 | } 39 | 40 | // MsgAddValidator simulation functions 41 | 42 | // randomDescription generates a random description for a validator 43 | func randomDescription(r *rand.Rand) stakingtypes.Description { 44 | return stakingtypes.Description{ 45 | Moniker: simtypes.RandStringOfLength(r, 10), 46 | Identity: simtypes.RandStringOfLength(r, 10), 47 | Website: simtypes.RandStringOfLength(r, 10), 48 | SecurityContact: simtypes.RandStringOfLength(r, 10), 49 | Details: simtypes.RandStringOfLength(r, 10), 50 | } 51 | } 52 | 53 | // randomMsgAddValidator generates a random MsgAddValidator message 54 | func randomMsgAddValidator(r *rand.Rand, authAddr sdk.AccAddress) (*types.MsgAddValidator, error) { 55 | validatorAccs := simtypes.RandomAccounts(r, 1) 56 | 57 | validatorAcc := validatorAccs[0] 58 | pubkey, err := codectypes.NewAnyWithValue(validatorAcc.PubKey) 59 | if err != nil { 60 | return nil, err 61 | } 62 | 63 | return &types.MsgAddValidator{ 64 | Authority: authAddr.String(), 65 | Description: randomDescription(r), 66 | ValidatorAddress: validatorAcc.Address.String(), 67 | Pubkey: pubkey, 68 | }, nil 69 | } 70 | 71 | // SimulateMsgAddValidator simulates the MsgAddValidator message 72 | func simulateMsgAddValidator(r *rand.Rand, _ sdk.Context, _ []simtypes.Account) sdk.Msg { 73 | var authAddr sdk.AccAddress = address.Module("gov") 74 | 75 | randMsg, err := randomMsgAddValidator(r, authAddr) 76 | if err != nil { 77 | panic(err) 78 | } 79 | return randMsg 80 | } 81 | 82 | // MsgRemoveValidator simulation functions 83 | 84 | // randomMsgRemoveValidator generates a random MsgRemoveValidator message 85 | func randomMsgRemoveValidator(r *rand.Rand, authAddr sdk.AccAddress, accs []simtypes.Account) *types.MsgRemoveValidator { 86 | rmValidator, _ := simtypes.RandomAcc(r, accs) 87 | 88 | return &types.MsgRemoveValidator{ 89 | Authority: authAddr.String(), 90 | ValidatorAddress: rmValidator.Address.String(), 91 | } 92 | } 93 | 94 | // SimulateMsgRemoveValidator simulates the MsgRemoveValidator message 95 | func simulateMsgRemoveValidator(r *rand.Rand, _ sdk.Context, accs []simtypes.Account) sdk.Msg { 96 | var authAddr sdk.AccAddress = address.Module("gov") 97 | 98 | randMsg := randomMsgRemoveValidator(r, authAddr, accs) 99 | return randMsg 100 | } 101 | -------------------------------------------------------------------------------- /x/poa/simulation/proposals_test.go: -------------------------------------------------------------------------------- 1 | package simulation 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "testing" 7 | 8 | tmproto "github.com/cometbft/cometbft/proto/tendermint/types" 9 | "github.com/cosmos/cosmos-sdk/types/address" 10 | simtypes "github.com/cosmos/cosmos-sdk/types/simulation" 11 | "github.com/stretchr/testify/require" 12 | "github.com/xrplevm/node/v8/x/poa/types" 13 | 14 | sdk "github.com/cosmos/cosmos-sdk/types" 15 | ) 16 | 17 | func TestProposalMsgs(t *testing.T) { 18 | s := rand.NewSource(1) 19 | //nolint:gosec 20 | r := rand.New(s) 21 | 22 | ctx := sdk.NewContext(nil, tmproto.Header{}, true, nil) 23 | accounts := simtypes.RandomAccounts(r, 3) 24 | 25 | // execute ProposalMsgs function 26 | weightedProposalMsgs := ProposalMsgs() 27 | require.Equal(t, 2, len(weightedProposalMsgs)) 28 | 29 | w0 := weightedProposalMsgs[0] 30 | 31 | // tests w0 interface: 32 | require.Equal(t, OpWeightMsgAddValidator, w0.AppParamsKey()) 33 | require.Equal(t, DefaultWeightMsgAddValidator, w0.DefaultWeight()) 34 | 35 | msg := w0.MsgSimulatorFn()(r, ctx, accounts) 36 | msgAddValidator, ok := msg.(*types.MsgAddValidator) 37 | require.True(t, ok) 38 | 39 | fmt.Println(msgAddValidator) 40 | require.Equal(t, sdk.AccAddress(address.Module("gov")).String(), msgAddValidator.Authority) 41 | 42 | w1 := weightedProposalMsgs[1] 43 | 44 | // tests w0 interface: 45 | require.Equal(t, OpWeightMsgRemoveValidator, w1.AppParamsKey()) 46 | require.Equal(t, DefaultWeightMsgRemoveValidator, w1.DefaultWeight()) 47 | 48 | msg = w1.MsgSimulatorFn()(r, ctx, accounts) 49 | msgRemoveValidator, ok := msg.(*types.MsgRemoveValidator) 50 | require.True(t, ok) 51 | 52 | fmt.Println(msgRemoveValidator) 53 | require.Equal(t, sdk.AccAddress(address.Module("gov")).String(), msgRemoveValidator.Authority) 54 | } 55 | -------------------------------------------------------------------------------- /x/poa/testutil/expected_msg_server.go: -------------------------------------------------------------------------------- 1 | package testutil 2 | 3 | import ( 4 | context "context" 5 | 6 | stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" 7 | ) 8 | 9 | // MsgServer is the server API for Msg service. 10 | type StakingMsgServer interface { 11 | // CreateValidator defines a method for creating a new validator. 12 | CreateValidator(context.Context, *stakingtypes.MsgCreateValidator) (*stakingtypes.MsgCreateValidatorResponse, error) 13 | // EditValidator defines a method for editing an existing validator. 14 | EditValidator(context.Context, *stakingtypes.MsgEditValidator) (*stakingtypes.MsgEditValidatorResponse, error) 15 | // Delegate defines a method for performing a delegation of coins 16 | // from a delegator to a validator. 17 | Delegate(context.Context, *stakingtypes.MsgDelegate) (*stakingtypes.MsgDelegateResponse, error) 18 | // BeginRedelegate defines a method for performing a redelegation 19 | // of coins from a delegator and source validator to a destination validator. 20 | BeginRedelegate(context.Context, *stakingtypes.MsgBeginRedelegate) (*stakingtypes.MsgBeginRedelegateResponse, error) 21 | // Undelegate defines a method for performing an undelegation from a 22 | // delegate and a validator. 23 | Undelegate(context.Context, *stakingtypes.MsgUndelegate) (*stakingtypes.MsgUndelegateResponse, error) 24 | // CancelUnbondingDelegation defines a method for performing canceling the unbonding delegation 25 | // and delegate back to previous validator. 26 | // 27 | // Since: cosmos-sdk 0.46 28 | CancelUnbondingDelegation(context.Context, *stakingtypes.MsgCancelUnbondingDelegation) (*stakingtypes.MsgCancelUnbondingDelegationResponse, error) 29 | // UpdateParams defines an operation for updating the x/staking module 30 | // parameters. 31 | // Since: cosmos-sdk 0.47 32 | UpdateParams(context.Context, *stakingtypes.MsgUpdateParams) (*stakingtypes.MsgUpdateParamsResponse, error) 33 | } 34 | -------------------------------------------------------------------------------- /x/poa/testutil/keys.go: -------------------------------------------------------------------------------- 1 | package testutil 2 | 3 | import ( 4 | cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" 5 | ) 6 | 7 | type PubKey interface { 8 | cryptotypes.PubKey 9 | } 10 | -------------------------------------------------------------------------------- /x/poa/testutil/keys_mock.go: -------------------------------------------------------------------------------- 1 | // Code generated by MockGen. DO NOT EDIT. 2 | // Source: x/poa/testutil/keys.go 3 | 4 | // Package testutil is a generated GoMock package. 5 | package testutil 6 | 7 | import ( 8 | reflect "reflect" 9 | 10 | types "github.com/cosmos/cosmos-sdk/crypto/types" 11 | gomock "github.com/golang/mock/gomock" 12 | ) 13 | 14 | // MockPubKey is a mock of PubKey interface. 15 | type MockPubKey struct { 16 | ctrl *gomock.Controller 17 | recorder *MockPubKeyMockRecorder 18 | } 19 | 20 | // MockPubKeyMockRecorder is the mock recorder for MockPubKey. 21 | type MockPubKeyMockRecorder struct { 22 | mock *MockPubKey 23 | } 24 | 25 | // NewMockPubKey creates a new mock instance. 26 | func NewMockPubKey(ctrl *gomock.Controller) *MockPubKey { 27 | mock := &MockPubKey{ctrl: ctrl} 28 | mock.recorder = &MockPubKeyMockRecorder{mock} 29 | return mock 30 | } 31 | 32 | // EXPECT returns an object that allows the caller to indicate expected use. 33 | func (m *MockPubKey) EXPECT() *MockPubKeyMockRecorder { 34 | return m.recorder 35 | } 36 | 37 | // Address mocks base method. 38 | func (m *MockPubKey) Address() types.Address { 39 | m.ctrl.T.Helper() 40 | ret := m.ctrl.Call(m, "Address") 41 | ret0, _ := ret[0].(types.Address) 42 | return ret0 43 | } 44 | 45 | // Address indicates an expected call of Address. 46 | func (mr *MockPubKeyMockRecorder) Address() *gomock.Call { 47 | mr.mock.ctrl.T.Helper() 48 | return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Address", reflect.TypeOf((*MockPubKey)(nil).Address)) 49 | } 50 | 51 | // Bytes mocks base method. 52 | func (m *MockPubKey) Bytes() []byte { 53 | m.ctrl.T.Helper() 54 | ret := m.ctrl.Call(m, "Bytes") 55 | ret0, _ := ret[0].([]byte) 56 | return ret0 57 | } 58 | 59 | // Bytes indicates an expected call of Bytes. 60 | func (mr *MockPubKeyMockRecorder) Bytes() *gomock.Call { 61 | mr.mock.ctrl.T.Helper() 62 | return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Bytes", reflect.TypeOf((*MockPubKey)(nil).Bytes)) 63 | } 64 | 65 | // Equals mocks base method. 66 | func (m *MockPubKey) Equals(arg0 types.PubKey) bool { 67 | m.ctrl.T.Helper() 68 | ret := m.ctrl.Call(m, "Equals", arg0) 69 | ret0, _ := ret[0].(bool) 70 | return ret0 71 | } 72 | 73 | // Equals indicates an expected call of Equals. 74 | func (mr *MockPubKeyMockRecorder) Equals(arg0 interface{}) *gomock.Call { 75 | mr.mock.ctrl.T.Helper() 76 | return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Equals", reflect.TypeOf((*MockPubKey)(nil).Equals), arg0) 77 | } 78 | 79 | // ProtoMessage mocks base method. 80 | func (m *MockPubKey) ProtoMessage() { 81 | m.ctrl.T.Helper() 82 | m.ctrl.Call(m, "ProtoMessage") 83 | } 84 | 85 | // ProtoMessage indicates an expected call of ProtoMessage. 86 | func (mr *MockPubKeyMockRecorder) ProtoMessage() *gomock.Call { 87 | mr.mock.ctrl.T.Helper() 88 | return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProtoMessage", reflect.TypeOf((*MockPubKey)(nil).ProtoMessage)) 89 | } 90 | 91 | // Reset mocks base method. 92 | func (m *MockPubKey) Reset() { 93 | m.ctrl.T.Helper() 94 | m.ctrl.Call(m, "Reset") 95 | } 96 | 97 | // Reset indicates an expected call of Reset. 98 | func (mr *MockPubKeyMockRecorder) Reset() *gomock.Call { 99 | mr.mock.ctrl.T.Helper() 100 | return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Reset", reflect.TypeOf((*MockPubKey)(nil).Reset)) 101 | } 102 | 103 | // String mocks base method. 104 | func (m *MockPubKey) String() string { 105 | m.ctrl.T.Helper() 106 | ret := m.ctrl.Call(m, "String") 107 | ret0, _ := ret[0].(string) 108 | return ret0 109 | } 110 | 111 | // String indicates an expected call of String. 112 | func (mr *MockPubKeyMockRecorder) String() *gomock.Call { 113 | mr.mock.ctrl.T.Helper() 114 | return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "String", reflect.TypeOf((*MockPubKey)(nil).String)) 115 | } 116 | 117 | // Type mocks base method. 118 | func (m *MockPubKey) Type() string { 119 | m.ctrl.T.Helper() 120 | ret := m.ctrl.Call(m, "Type") 121 | ret0, _ := ret[0].(string) 122 | return ret0 123 | } 124 | 125 | // Type indicates an expected call of Type. 126 | func (mr *MockPubKeyMockRecorder) Type() *gomock.Call { 127 | mr.mock.ctrl.T.Helper() 128 | return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Type", reflect.TypeOf((*MockPubKey)(nil).Type)) 129 | } 130 | 131 | // VerifySignature mocks base method. 132 | func (m *MockPubKey) VerifySignature(msg, sig []byte) bool { 133 | m.ctrl.T.Helper() 134 | ret := m.ctrl.Call(m, "VerifySignature", msg, sig) 135 | ret0, _ := ret[0].(bool) 136 | return ret0 137 | } 138 | 139 | // VerifySignature indicates an expected call of VerifySignature. 140 | func (mr *MockPubKeyMockRecorder) VerifySignature(msg, sig interface{}) *gomock.Call { 141 | mr.mock.ctrl.T.Helper() 142 | return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VerifySignature", reflect.TypeOf((*MockPubKey)(nil).VerifySignature), msg, sig) 143 | } 144 | -------------------------------------------------------------------------------- /x/poa/testutil/staking_hooks.go: -------------------------------------------------------------------------------- 1 | package testutil 2 | 3 | import ( 4 | "context" 5 | 6 | "cosmossdk.io/math" 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | ) 9 | 10 | type StakingHooks interface { 11 | AfterValidatorCreated(ctx context.Context, valAddr sdk.ValAddress) error // Must be called when a validator is created 12 | BeforeValidatorModified(ctx context.Context, valAddr sdk.ValAddress) error // Must be called when a validator's state changes 13 | AfterValidatorRemoved(ctx context.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) error // Must be called when a validator is deleted 14 | 15 | AfterValidatorBonded(ctx context.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) error // Must be called when a validator is bonded 16 | AfterValidatorBeginUnbonding(ctx context.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) error // Must be called when a validator begins unbonding 17 | 18 | BeforeDelegationCreated(ctx context.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error // Must be called when a delegation is created 19 | BeforeDelegationSharesModified(ctx context.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error // Must be called when a delegation's shares are modified 20 | BeforeDelegationRemoved(ctx context.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error // Must be called when a delegation is removed 21 | AfterDelegationModified(ctx context.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error 22 | BeforeValidatorSlashed(ctx context.Context, valAddr sdk.ValAddress, fraction math.LegacyDec) error 23 | AfterUnbondingInitiated(ctx context.Context, id uint64) error 24 | } 25 | -------------------------------------------------------------------------------- /x/poa/testutil/tx.go: -------------------------------------------------------------------------------- 1 | package testutil 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | protov2 "google.golang.org/protobuf/proto" 6 | ) 7 | 8 | type Tx interface { 9 | sdk.HasMsgs 10 | 11 | // GetMsgsV2 gets the transaction's messages as google.golang.org/protobuf/proto.Message's. 12 | GetMsgsV2() ([]protov2.Message, error) 13 | } 14 | -------------------------------------------------------------------------------- /x/poa/testutil/tx_mock.go: -------------------------------------------------------------------------------- 1 | // Code generated by MockGen. DO NOT EDIT. 2 | // Source: x/poa/testutil/tx.go 3 | 4 | // Package testutil is a generated GoMock package. 5 | package testutil 6 | 7 | import ( 8 | reflect "reflect" 9 | 10 | types "github.com/cosmos/cosmos-sdk/types" 11 | gomock "github.com/golang/mock/gomock" 12 | proto "google.golang.org/protobuf/proto" 13 | ) 14 | 15 | // MockTx is a mock of Tx interface. 16 | type MockTx struct { 17 | ctrl *gomock.Controller 18 | recorder *MockTxMockRecorder 19 | } 20 | 21 | // MockTxMockRecorder is the mock recorder for MockTx. 22 | type MockTxMockRecorder struct { 23 | mock *MockTx 24 | } 25 | 26 | // NewMockTx creates a new mock instance. 27 | func NewMockTx(ctrl *gomock.Controller) *MockTx { 28 | mock := &MockTx{ctrl: ctrl} 29 | mock.recorder = &MockTxMockRecorder{mock} 30 | return mock 31 | } 32 | 33 | // EXPECT returns an object that allows the caller to indicate expected use. 34 | func (m *MockTx) EXPECT() *MockTxMockRecorder { 35 | return m.recorder 36 | } 37 | 38 | // GetMsgs mocks base method. 39 | func (m *MockTx) GetMsgs() []types.Msg { 40 | m.ctrl.T.Helper() 41 | ret := m.ctrl.Call(m, "GetMsgs") 42 | ret0, _ := ret[0].([]types.Msg) 43 | return ret0 44 | } 45 | 46 | // GetMsgs indicates an expected call of GetMsgs. 47 | func (mr *MockTxMockRecorder) GetMsgs() *gomock.Call { 48 | mr.mock.ctrl.T.Helper() 49 | return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMsgs", reflect.TypeOf((*MockTx)(nil).GetMsgs)) 50 | } 51 | 52 | // GetMsgsV2 mocks base method. 53 | func (m *MockTx) GetMsgsV2() ([]proto.Message, error) { 54 | m.ctrl.T.Helper() 55 | ret := m.ctrl.Call(m, "GetMsgsV2") 56 | ret0, _ := ret[0].([]proto.Message) 57 | ret1, _ := ret[1].(error) 58 | return ret0, ret1 59 | } 60 | 61 | // GetMsgsV2 indicates an expected call of GetMsgsV2. 62 | func (mr *MockTxMockRecorder) GetMsgsV2() *gomock.Call { 63 | mr.mock.ctrl.T.Helper() 64 | return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMsgsV2", reflect.TypeOf((*MockTx)(nil).GetMsgsV2)) 65 | } 66 | -------------------------------------------------------------------------------- /x/poa/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/codec" 5 | cdctypes "github.com/cosmos/cosmos-sdk/codec/types" 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | "github.com/cosmos/cosmos-sdk/types/msgservice" 8 | govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" 9 | ) 10 | 11 | func RegisterCodec(cdc *codec.LegacyAmino) { 12 | cdc.RegisterConcrete(&MsgAddValidator{}, "poa/AddValidator", nil) 13 | cdc.RegisterConcrete(&MsgRemoveValidator{}, "poa/RemoveValidator", nil) 14 | // this line is used by starport scaffolding # 2 15 | } 16 | 17 | func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { 18 | registry.RegisterImplementations((*sdk.Msg)(nil), 19 | &MsgAddValidator{}, 20 | ) 21 | registry.RegisterImplementations((*sdk.Msg)(nil), 22 | &MsgRemoveValidator{}, 23 | ) 24 | registry.RegisterImplementations( 25 | (*govtypes.Content)(nil), 26 | ) 27 | // this line is used by starport scaffolding # 3 28 | 29 | msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) 30 | } 31 | 32 | var ( 33 | Amino = codec.NewLegacyAmino() 34 | ModuleCdc = codec.NewProtoCodec(cdctypes.NewInterfaceRegistry()) 35 | ) 36 | -------------------------------------------------------------------------------- /x/poa/types/errors.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // DONTCOVER 4 | 5 | import ( 6 | sdkerrors "cosmossdk.io/errors" 7 | ) 8 | 9 | // x/poa module sentinel errors 10 | var ( 11 | ErrAddressHasBankTokens = sdkerrors.Register(ModuleName, 1, "address already has bank tokens") 12 | ErrAddressHasBondedTokens = sdkerrors.Register(ModuleName, 2, "address already has bonded tokens") 13 | ErrAddressHasUnbondingTokens = sdkerrors.Register(ModuleName, 3, "address already has unbonding tokens") 14 | ErrAddressHasDelegatedTokens = sdkerrors.Register(ModuleName, 4, "address already has delegated tokens") 15 | ErrInvalidValidatorStatus = sdkerrors.Register(ModuleName, 5, "invalid validator status") 16 | ErrAddressIsNotAValidator = sdkerrors.Register(ModuleName, 6, "address is not a validator") 17 | ErrMaxValidatorsReached = sdkerrors.Register(ModuleName, 7, "maximum number of validators reached") 18 | ) 19 | -------------------------------------------------------------------------------- /x/poa/types/events.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | EventTypeAddValidator = "add_validator" 5 | EventTypeRemoveValidator = "remove_validator" 6 | AttributeValidator = "address" 7 | AttributeHeight = "height" 8 | AttributeStakingTokens = "staking_tokens" 9 | AttributeBankTokens = "bank_tokens" 10 | ) 11 | -------------------------------------------------------------------------------- /x/poa/types/expected_keepers.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "context" 5 | 6 | "cosmossdk.io/math" 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" 9 | slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" 10 | stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" 11 | ) 12 | 13 | // AccountKeeper defines the expected account keeper used for simulations (noalias) 14 | type AccountKeeper interface { 15 | GetAccount(ctx context.Context, addr sdk.AccAddress) sdk.AccountI 16 | GetModuleAccount(ctx context.Context, moduleName string) sdk.ModuleAccountI 17 | // Methods imported from account should be defined here 18 | } 19 | 20 | // BankKeeper defines the expected interface needed to retrieve account balances. 21 | type BankKeeper interface { 22 | SpendableCoins(ctx context.Context, addr sdk.AccAddress) sdk.Coins 23 | GetBalance(ctx context.Context, addr sdk.AccAddress, denom string) sdk.Coin 24 | MintCoins(ctx context.Context, moduleName string, amt sdk.Coins) error 25 | BurnCoins(ctx context.Context, moduleName string, amt sdk.Coins) error 26 | SendCoinsFromModuleToAccount(ctx context.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error 27 | SendCoinsFromAccountToModule(ctx context.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error 28 | IterateAllBalances(ctx context.Context, cb func(address sdk.AccAddress, coin sdk.Coin) (stop bool)) 29 | } 30 | 31 | // StakingKeeper defines the expected interface needed to retrieve account balances. 32 | type StakingKeeper interface { 33 | GetParams(ctx context.Context) (stakingtypes.Params, error) 34 | GetValidator(ctx context.Context, addr sdk.ValAddress) (validator stakingtypes.Validator, err error) 35 | GetValidators(ctx context.Context, maxRetrieve uint32) (validators []stakingtypes.Validator, err error) 36 | GetAllValidators(ctx context.Context) (validators []stakingtypes.Validator, err error) 37 | GetAllDelegations(ctx context.Context) (delegations []stakingtypes.Delegation, err error) 38 | GetAllDelegatorDelegations(ctx context.Context, delegator sdk.AccAddress) ([]stakingtypes.Delegation, error) 39 | GetUnbondingDelegationsFromValidator(ctx context.Context, validator sdk.ValAddress) ([]stakingtypes.UnbondingDelegation, error) 40 | SlashUnbondingDelegation(ctx context.Context, ubd stakingtypes.UnbondingDelegation, infractionHeight int64, slashFactor math.LegacyDec) (totalSlashAmount math.Int, err error) 41 | RemoveDelegation(ctx context.Context, delegation stakingtypes.Delegation) error 42 | RemoveValidatorTokensAndShares(ctx context.Context, validator stakingtypes.Validator, sharesToRemove math.LegacyDec) (stakingtypes.Validator, math.Int, error) 43 | RemoveValidatorTokens(ctx context.Context, validator stakingtypes.Validator, tokensToRemove math.Int) (stakingtypes.Validator, error) 44 | BondDenom(ctx context.Context) (string, error) 45 | Unbond(ctx context.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress, shares math.LegacyDec) (amount math.Int, err error) 46 | Hooks() stakingtypes.StakingHooks 47 | } 48 | 49 | type SlashingKeeper interface { 50 | GetParams(ctx context.Context) (params slashingtypes.Params, err error) 51 | } 52 | 53 | type GovKeeper interface { 54 | SubmitProposal(ctx context.Context, messages []sdk.Msg, metadata string) (v1.Proposal, error) 55 | } 56 | -------------------------------------------------------------------------------- /x/poa/types/genesis.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | // this line is used by starport scaffolding # genesis/types/import 5 | ) 6 | 7 | // DefaultIndex is the default global index 8 | const DefaultIndex uint64 = 1 9 | 10 | // DefaultGenesis returns the default genesis state 11 | func DefaultGenesis() *GenesisState { 12 | return &GenesisState{ 13 | // this line is used by starport scaffolding # genesis/types/default 14 | Params: DefaultParams(), 15 | } 16 | } 17 | 18 | // Validate performs basic genesis state validation returning an error upon any 19 | // failure. 20 | func (gs GenesisState) Validate() error { 21 | // this line is used by starport scaffolding # genesis/types/validate 22 | 23 | return gs.Params.Validate() 24 | } 25 | -------------------------------------------------------------------------------- /x/poa/types/keys.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // ModuleName defines the module name 5 | ModuleName = "poa" 6 | 7 | // StoreKey defines the primary module store key 8 | StoreKey = ModuleName 9 | 10 | // RouterKey defines the module's message routing key 11 | RouterKey = ModuleName 12 | 13 | // MemStoreKey defines the in-memory store key 14 | MemStoreKey = "mem_" + ModuleName 15 | ) 16 | 17 | func KeyPrefix(p string) []byte { 18 | return []byte(p) 19 | } 20 | -------------------------------------------------------------------------------- /x/poa/types/message_add_validator.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 5 | cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" 8 | ) 9 | 10 | var ( 11 | _ sdk.Msg = &MsgAddValidator{} 12 | _ codectypes.UnpackInterfacesMessage = (*MsgAddValidator)(nil) 13 | ) 14 | 15 | func NewMsgAddValidator(authority string, address string, pubKey cryptotypes.PubKey, description stakingtypes.Description) (*MsgAddValidator, error) { 16 | var pkAny *codectypes.Any 17 | if pubKey != nil { 18 | var err error 19 | if pkAny, err = codectypes.NewAnyWithValue(pubKey); err != nil { 20 | return nil, err 21 | } 22 | } 23 | return &MsgAddValidator{ 24 | Authority: authority, 25 | ValidatorAddress: address, 26 | Pubkey: pkAny, 27 | Description: description, 28 | }, nil 29 | } 30 | 31 | // UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces 32 | func (msg *MsgAddValidator) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { 33 | var pubKey cryptotypes.PubKey 34 | return unpacker.UnpackAny(msg.Pubkey, &pubKey) 35 | } 36 | -------------------------------------------------------------------------------- /x/poa/types/message_remove_validator.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | ) 6 | 7 | var _ sdk.Msg = &MsgRemoveValidator{} 8 | 9 | func NewMsgRemoveValidator(authority string, address string) *MsgRemoveValidator { 10 | return &MsgRemoveValidator{ 11 | Authority: authority, 12 | ValidatorAddress: address, 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /x/poa/types/params.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" 5 | ) 6 | 7 | var _ paramtypes.ParamSet = (*Params)(nil) 8 | 9 | // ParamKeyTable the param key table for launch module 10 | func ParamKeyTable() paramtypes.KeyTable { 11 | return paramtypes.NewKeyTable().RegisterParamSet(&Params{}) 12 | } 13 | 14 | // NewParams creates a new Params instance 15 | func NewParams() Params { 16 | return Params{} 17 | } 18 | 19 | // DefaultParams returns a default set of parameters 20 | func DefaultParams() Params { 21 | return NewParams() 22 | } 23 | 24 | // ParamSetPairs get the params.ParamSet 25 | func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { 26 | return paramtypes.ParamSetPairs{} 27 | } 28 | 29 | // Validate validates the set of params 30 | func (p *Params) Validate() error { 31 | return nil 32 | } 33 | -------------------------------------------------------------------------------- /x/poa/types/types.go: -------------------------------------------------------------------------------- 1 | package types 2 | --------------------------------------------------------------------------------