chore: remove simapp v1 (#23009)
This commit is contained in:
parent
150f2d6b3a
commit
4a073fa4a4
9
.github/workflows/build.yml
vendored
9
.github/workflows/build.yml
vendored
@ -18,7 +18,6 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
# go-arch: ["amd64", "arm", "arm64"]
|
||||
go-arch: ["amd64", "arm64"] # drop 32 bit support for now (and maybe forever)
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@ -48,19 +47,17 @@ jobs:
|
||||
###################
|
||||
#### Build App ####
|
||||
###################
|
||||
- name: Build
|
||||
run: GOARCH=${{ matrix.go-arch }} make build
|
||||
- name: Build v2
|
||||
run: GOARCH=${{ matrix.go-arch }} COSMOS_BUILD_OPTIONS=v2 make build
|
||||
- name: Build with rocksdb backend
|
||||
if: matrix.go-arch == 'amd64'
|
||||
run: GOARCH=${{ matrix.go-arch }} COSMOS_BUILD_OPTIONS="rocksdb" make build
|
||||
run: GOARCH=${{ matrix.go-arch }} COSMOS_BUILD_OPTIONS=v2,rocksdb make build
|
||||
- name: Build with BLS12381
|
||||
if: matrix.go-arch == 'amd64'
|
||||
run: GOARCH=${{ matrix.go-arch }} COSMOS_BUILD_OPTIONS="bls12381" make build
|
||||
run: GOARCH=${{ matrix.go-arch }} COSMOS_BUILD_OPTIONS=v2,bls12381 make build
|
||||
- name: Build with Secp_cgo
|
||||
if: matrix.go-arch == 'amd64'
|
||||
run: GOARCH=${{ matrix.go-arch }} COSMOS_BUILD_OPTIONS="secp" make build
|
||||
run: GOARCH=${{ matrix.go-arch }} COSMOS_BUILD_OPTIONS=v2,secp make build
|
||||
###################
|
||||
## Build Tooling ##
|
||||
###################
|
||||
|
||||
145
.github/workflows/sims-047.yml
vendored
145
.github/workflows/sims-047.yml
vendored
@ -1,145 +0,0 @@
|
||||
name: Sims release/0.47.x
|
||||
# Sims workflow runs multiple types of simulations (nondeterminism, import-export, after-import, multi-seed-short)
|
||||
# This workflow will run on all Pull Requests, if a .go, .mod or .sum file have been changed
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0,12 * * *"
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
concurrency:
|
||||
group: ci-${{ github.ref }}-sims-047
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
if: "!contains(github.event.head_commit.message, 'skip-sims')"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: "release/v0.47.x"
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.23"
|
||||
check-latest: true
|
||||
- run: make build
|
||||
|
||||
install-runsim:
|
||||
permissions:
|
||||
contents: none
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
steps:
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.23"
|
||||
check-latest: true
|
||||
- name: Install runsim
|
||||
run: go install github.com/cosmos/tools/cmd/runsim@v1.0.0
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/go/bin
|
||||
key: ${{ runner.os }}-go-runsim-binary
|
||||
|
||||
test-sim-import-export:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build, install-runsim]
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: "release/v0.47.x"
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.23"
|
||||
check-latest: true
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/go/bin
|
||||
key: ${{ runner.os }}-go-runsim-binary
|
||||
- name: test-sim-import-export
|
||||
run: |
|
||||
make test-sim-import-export
|
||||
|
||||
test-sim-after-import:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build, install-runsim]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: "release/v0.47.x"
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.23"
|
||||
check-latest: true
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/go/bin
|
||||
key: ${{ runner.os }}-go-runsim-binary
|
||||
- name: test-sim-after-import
|
||||
run: |
|
||||
make test-sim-after-import
|
||||
|
||||
test-sim-multi-seed-short:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build, install-runsim]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: "release/v0.47.x"
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.23"
|
||||
check-latest: true
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/go/bin
|
||||
key: ${{ runner.os }}-go-runsim-binary
|
||||
- name: test-sim-multi-seed-short
|
||||
run: |
|
||||
make test-sim-multi-seed-short
|
||||
|
||||
sims-notify-success:
|
||||
needs:
|
||||
[test-sim-multi-seed-short, test-sim-after-import, test-sim-import-export]
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ success() }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Get previous workflow status
|
||||
uses: ./.github/actions/last-workflow-status
|
||||
id: last_status
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Notify Slack on success
|
||||
if: ${{ steps.last_status.outputs.last_status == 'failure' }}
|
||||
uses: rtCamp/action-slack-notify@v2.3.2
|
||||
env:
|
||||
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
|
||||
SLACK_CHANNEL: sdk-sims
|
||||
SLACK_USERNAME: Sim Tests release/0.47.x
|
||||
SLACK_ICON_EMOJI: ":white_check_mark:"
|
||||
SLACK_COLOR: good
|
||||
SLACK_MESSAGE: 0.47.x Sims are passing
|
||||
SLACK_FOOTER: ""
|
||||
|
||||
sims-notify-failure:
|
||||
permissions:
|
||||
contents: none
|
||||
needs:
|
||||
[test-sim-multi-seed-short, test-sim-after-import, test-sim-import-export]
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ failure() }}
|
||||
steps:
|
||||
- name: Notify Slack on failure
|
||||
uses: rtCamp/action-slack-notify@v2.3.2
|
||||
env:
|
||||
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
|
||||
SLACK_CHANNEL: sdk-sims
|
||||
SLACK_USERNAME: Sim Tests release/0.47.x
|
||||
SLACK_ICON_EMOJI: ":skull:"
|
||||
SLACK_COLOR: danger
|
||||
SLACK_MESSAGE: 0.47.x Sims are failing
|
||||
SLACK_FOOTER: ""
|
||||
63
.github/workflows/test.yml
vendored
63
.github/workflows/test.yml
vendored
@ -114,46 +114,6 @@ jobs:
|
||||
name: "${{ github.sha }}-integration-coverage"
|
||||
path: ./tests/integration-profile.out
|
||||
|
||||
test-system: # v2 system tests are in v2-test.yml
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-tags: true
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.23"
|
||||
check-latest: true
|
||||
cache: true
|
||||
cache-dependency-path: |
|
||||
simapp/go.sum
|
||||
systemtest/go.sum
|
||||
- uses: technote-space/get-diff-action@v6.1.2
|
||||
id: git_diff
|
||||
with:
|
||||
PATTERNS: |
|
||||
**/*.go
|
||||
go.mod
|
||||
go.sum
|
||||
**/go.mod
|
||||
**/go.sum
|
||||
**/Makefile
|
||||
Makefile
|
||||
- name: Install musl lib for simd (docker) binary
|
||||
if: env.GIT_DIFF
|
||||
run: |
|
||||
sudo apt-get install -y musl
|
||||
- name: system tests v1
|
||||
if: env.GIT_DIFF
|
||||
run: |
|
||||
make test-system
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: "testnet-setup"
|
||||
path: ./systemtests/testnet/
|
||||
retention-days: 3
|
||||
|
||||
repo-analysis:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [tests, test-integration]
|
||||
@ -504,29 +464,6 @@ jobs:
|
||||
with:
|
||||
projectBaseDir: indexer/postgres/
|
||||
|
||||
test-simapp:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.23"
|
||||
check-latest: true
|
||||
cache: true
|
||||
cache-dependency-path: simapp/go.sum
|
||||
- uses: technote-space/get-diff-action@v6.1.2
|
||||
id: git_diff
|
||||
with:
|
||||
PATTERNS: |
|
||||
**/*.go
|
||||
simapp/go.mod
|
||||
simapp/go.sum
|
||||
- name: tests simapp
|
||||
if: env.GIT_DIFF
|
||||
run: |
|
||||
cd simapp
|
||||
go test -mod=readonly -timeout 30m -tags='norace ledger test_ledger_mock' ./...
|
||||
|
||||
test-simapp-v2:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
1
docs/build/packages/README.md
vendored
1
docs/build/packages/README.md
vendored
@ -50,4 +50,3 @@ For more information on SDK tooling, see the [Tooling](https://docs.cosmos.netwo
|
||||
## Example
|
||||
|
||||
* [SimApp v2](https://pkg.go.dev/cosmossdk.io/simapp/v2) - SimApp/v2 is **the** sample Cosmos SDK v2 chain. This package should not be imported in your application.
|
||||
* [SimApp](https://pkg.go.dev/cosmossdk.io/simapp) - SimApp is **the** sample Cosmos SDK chain. This package should not be imported in your application.
|
||||
|
||||
@ -14,7 +14,7 @@ use (
|
||||
./log
|
||||
./math
|
||||
./orm
|
||||
./simapp
|
||||
./simapp/v2
|
||||
./tests
|
||||
./tests/systemtests
|
||||
./schema
|
||||
|
||||
@ -12,6 +12,7 @@ MOCKS_DIR = $(CURDIR)/tests/mocks
|
||||
HTTPS_GIT := https://github.com/cosmos/cosmos-sdk.git
|
||||
DOCKER := $(shell which docker)
|
||||
PROJECT_NAME = $(shell git remote get-url origin | xargs basename -s .git)
|
||||
COSMOS_BUILD_OPTIONS := v2
|
||||
|
||||
rocksdb_version=v9.6.1
|
||||
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
# TODO: This should be ported to work with SimApp v2.
|
||||
|
||||
#? test-sim-nondeterminism: Run non-determinism test for simapp
|
||||
test-sim-nondeterminism:
|
||||
@echo "Running non-determinism test..."
|
||||
@cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout=30m -tags='sims' -run TestAppStateDeterminism \
|
||||
-NumBlocks=100 -BlockSize=200 -Period=0
|
||||
# @echo "Running non-determinism test..."
|
||||
# @cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout=30m -tags='sims' -run TestAppStateDeterminism \
|
||||
# -NumBlocks=100 -BlockSize=200 -Period=0
|
||||
|
||||
# Requires an exported plugin. See store/streaming/README.md for documentation.
|
||||
#
|
||||
@ -15,49 +16,47 @@ test-sim-nondeterminism:
|
||||
# export COSMOS_SDK_ABCI_V1=<path-to-sdk>/store/streaming/abci/examples/file/file
|
||||
# make test-sim-nondeterminism-streaming
|
||||
test-sim-nondeterminism-streaming:
|
||||
@echo "Running non-determinism-streaming test..."
|
||||
@cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout=30m -tags='sims' -run TestAppStateDeterminism \
|
||||
-NumBlocks=100 -BlockSize=200 -Period=0 -EnableStreaming=true
|
||||
# @echo "Running non-determinism-streaming test..."
|
||||
# @cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout=30m -tags='sims' -run TestAppStateDeterminism \
|
||||
# -NumBlocks=100 -BlockSize=200 -Period=0 -EnableStreaming=true
|
||||
|
||||
test-sim-custom-genesis-fast:
|
||||
@echo "Running custom genesis simulation..."
|
||||
@echo "By default, ${HOME}/.simapp/config/genesis.json will be used."
|
||||
@cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout=30m -tags='sims' -run TestFullAppSimulation -Genesis=${HOME}/.simapp/config/genesis.json \
|
||||
-NumBlocks=100 -BlockSize=200 -Seed=99 -Period=5 -SigverifyTx=false
|
||||
# @echo "Running custom genesis simulation..."
|
||||
# @echo "By default, ${HOME}/.simapp/config/genesis.json will be used."
|
||||
# @cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout=30m -tags='sims' -run TestFullAppSimulation -Genesis=${HOME}/.simapp/config/genesis.json \
|
||||
# -NumBlocks=100 -BlockSize=200 -Seed=99 -Period=5 -SigverifyTx=false
|
||||
|
||||
test-sim-import-export:
|
||||
@echo "Running application import/export simulation. This may take several minutes..."
|
||||
@cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout 20m -tags='sims' -run TestAppImportExport \
|
||||
-NumBlocks=50 -Period=5
|
||||
# @echo "Running application import/export simulation. This may take several minutes..."
|
||||
# @cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout 20m -tags='sims' -run TestAppImportExport \
|
||||
# -NumBlocks=50 -Period=5
|
||||
|
||||
test-sim-after-import:
|
||||
@echo "Running application simulation-after-import. This may take several minutes..."
|
||||
@cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout 30m -tags='sims' -run TestAppSimulationAfterImport \
|
||||
-NumBlocks=50 -Period=5
|
||||
|
||||
# @echo "Running application simulation-after-import. This may take several minutes..."
|
||||
# @cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout 30m -tags='sims' -run TestAppSimulationAfterImport \
|
||||
# -NumBlocks=50 -Period=5
|
||||
|
||||
test-sim-custom-genesis-multi-seed:
|
||||
@echo "Running multi-seed custom genesis simulation..."
|
||||
@echo "By default, ${HOME}/.simapp/config/genesis.json will be used."
|
||||
@cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout 30m -tags='sims' -run TestFullAppSimulation -Genesis=${HOME}/.simapp/config/genesis.json \
|
||||
-NumBlocks=400 -Period=5
|
||||
# @echo "Running multi-seed custom genesis simulation..."
|
||||
# @echo "By default, ${HOME}/.simapp/config/genesis.json will be used."
|
||||
# @cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout 30m -tags='sims' -run TestFullAppSimulation -Genesis=${HOME}/.simapp/config/genesis.json \
|
||||
# -NumBlocks=400 -Period=5
|
||||
|
||||
test-sim-multi-seed-long:
|
||||
@echo "Running long multi-seed application simulation. This may take awhile!"
|
||||
@cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout=2h -tags='sims' -run TestFullAppSimulation \
|
||||
-NumBlocks=150 -Period=50
|
||||
# @echo "Running long multi-seed application simulation. This may take awhile!"
|
||||
# @cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout=2h -tags='sims' -run TestFullAppSimulation \
|
||||
# -NumBlocks=150 -Period=50
|
||||
|
||||
test-sim-multi-seed-short:
|
||||
@echo "Running short multi-seed application simulation. This may take awhile!"
|
||||
@cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout 30m -tags='sims' -run TestFullAppSimulation \
|
||||
-NumBlocks=50 -Period=10 -FauxMerkle=true
|
||||
|
||||
# @echo "Running short multi-seed application simulation. This may take awhile!"
|
||||
# @cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout 30m -tags='sims' -run TestFullAppSimulation \
|
||||
# -NumBlocks=50 -Period=10 -FauxMerkle=true
|
||||
|
||||
test-sim-benchmark-invariants:
|
||||
@echo "Running simulation invariant benchmarks..."
|
||||
cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -benchmem -bench=BenchmarkInvariants -tags='sims' -run=^$ \
|
||||
-Enabled=true -NumBlocks=1000 -BlockSize=200 \
|
||||
-Period=1 -Commit=true -Seed=57 -v -timeout 24h
|
||||
# @echo "Running simulation invariant benchmarks..."
|
||||
# cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -benchmem -bench=BenchmarkInvariants -tags='sims' -run=^$ \
|
||||
# -Enabled=true -NumBlocks=1000 -BlockSize=200 \
|
||||
# -Period=1 -Commit=true -Seed=57 -v -timeout 24h
|
||||
|
||||
.PHONY: \
|
||||
test-sim-nondeterminism \
|
||||
|
||||
@ -1,22 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
SIMD_BIN=${SIMD_BIN:=$(which simd 2>/dev/null)}
|
||||
|
||||
if [ -z "$SIMD_BIN" ]; then echo "SIMD_BIN is not set. Make sure to run 'make install' before"; exit 1; fi
|
||||
SIMD_HOME=$($SIMD_BIN config home)
|
||||
if [ -d "$SIMD_HOME" ]; then rm -rv $SIMD_HOME; fi
|
||||
$SIMD_BIN config set client chain-id demo
|
||||
$SIMD_BIN config set client keyring-backend test
|
||||
$SIMD_BIN config set client keyring-default-keyname alice
|
||||
$SIMD_BIN config set app api.enable true
|
||||
$SIMD_BIN keys add alice --indiscreet
|
||||
$SIMD_BIN keys add bob --indiscreet
|
||||
$SIMD_BIN init test --chain-id demo
|
||||
# to change the voting_period
|
||||
jq '.app_state.gov.params.voting_period = "600s"' $SIMD_HOME/config/genesis.json > temp.json && mv temp.json $SIMD_HOME/config/genesis.json
|
||||
jq '.app_state.gov.params.expedited_voting_period = "300s"' $SIMD_HOME/config/genesis.json > temp.json && mv temp.json $SIMD_HOME/config/genesis.json
|
||||
jq '.app_state.mint.minter.inflation = "0.300000000000000000"' $SIMD_HOME/config/genesis.json > temp.json && mv temp.json $SIMD_HOME/config/genesis.json # to change the inflation
|
||||
$SIMD_BIN genesis add-genesis-account alice 5000000000stake --keyring-backend test
|
||||
$SIMD_BIN genesis add-genesis-account bob 5000000000stake --keyring-backend test
|
||||
$SIMD_BIN genesis gentx alice 1000000stake --chain-id demo
|
||||
$SIMD_BIN genesis collect-gentxs
|
||||
@ -15,7 +15,6 @@ import (
|
||||
cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1"
|
||||
cryptoenc "github.com/cometbft/cometbft/crypto/encoding"
|
||||
protoio "github.com/cosmos/gogoproto/io"
|
||||
"github.com/cosmos/gogoproto/proto"
|
||||
gogoproto "github.com/cosmos/gogoproto/proto"
|
||||
gogoany "github.com/cosmos/gogoproto/types/any"
|
||||
"google.golang.org/grpc/codes"
|
||||
@ -516,7 +515,7 @@ func ValidateVoteExtensions[T transaction.Tx](
|
||||
return nil
|
||||
}
|
||||
|
||||
marshalDelimitedFn := func(msg proto.Message) ([]byte, error) {
|
||||
marshalDelimitedFn := func(msg gogoproto.Message) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
if err := protoio.NewDelimitedWriter(&buf).WriteMsg(msg); err != nil {
|
||||
return nil, err
|
||||
|
||||
@ -1,63 +0,0 @@
|
||||
<!--
|
||||
Guiding Principles:
|
||||
Changelogs are for humans, not machines.
|
||||
There should be an entry for every single version.
|
||||
The same types of changes should be grouped.
|
||||
Versions and sections should be linkable.
|
||||
The latest version comes first.
|
||||
The release date of each version is displayed.
|
||||
Mention whether you follow Semantic Versioning.
|
||||
Usage:
|
||||
Change log entries are to be added to the Unreleased section under the
|
||||
appropriate stanza (see below). Each entry should ideally include a tag and
|
||||
the Github issue reference in the following format:
|
||||
* (<tag>) [#<issue-number>] Changelog message.
|
||||
Types of changes (Stanzas):
|
||||
"Features" for new features.
|
||||
"Improvements" for changes in existing functionality.
|
||||
"Deprecated" for soon-to-be removed features.
|
||||
"Bug Fixes" for any bug fixes.
|
||||
"API Breaking" for breaking exported APIs used by developers building on SDK.
|
||||
Ref: https://keepachangelog.com/en/1.0.0/
|
||||
-->
|
||||
|
||||
# Changelog
|
||||
|
||||
`SimApp` is an application built using the Cosmos SDK for testing and educational purposes.
|
||||
It won't be tagged or intended to be imported in an application.
|
||||
This changelog is aimed to help developers understand the wiring changes between SDK versions.
|
||||
It is an exautive list of changes that completes the SimApp section in the [UPGRADING.md](https://github.com/cosmos/cosmos-sdk/blob/main/UPGRADING.md#simapp)
|
||||
|
||||
## v0.50 to v0.52
|
||||
|
||||
Always refer to the [UPGRADING.md](https://github.com/cosmos/cosmos-sdk/blob/main/UPGRADING.md) to understand the changes.
|
||||
|
||||
* Update module path to new vanity url.
|
||||
* Wire new SDK modules (`epochs`, `accounts`, `protocolpool`).
|
||||
* Remove the crisis module from simapp.
|
||||
* Update `export` function to make use of the new module collections API.
|
||||
* Add example of how to define a custom mint function in `simapp/mint_fn.go`.
|
||||
* Add address codec in client context and signing context.
|
||||
* Update testnet command to match new module APIs.
|
||||
* [#20409](https://github.com/cosmos/cosmos-sdk/pull/20409) Add `tx` as `SkipStoreKeys` in `app_config.go`.
|
||||
* [#20485](https://github.com/cosmos/cosmos-sdk/pull/20485) The signature of `x/upgrade/types.UpgradeHandler` has changed to accept `appmodule.VersionMap` from `module.VersionMap`. These types are interchangeable, but usages of `UpradeKeeper.SetUpgradeHandler` may need to adjust their usages to match the new signature.
|
||||
* [#20740](https://github.com/cosmos/cosmos-sdk/pull/20740) Update `genutilcli.Commands` to use the genutil modules from the module manager.
|
||||
* [#20771](https://github.com/cosmos/cosmos-sdk/pull/20771) Use client/v2 `GetNodeHomeDirectory` helper in `app.go` and use the `DefaultNodeHome` constant everywhere in the app.
|
||||
* [#20490](https://github.com/cosmos/cosmos-sdk/pull/20490) Refactor simulations to make use of `testutil/sims` instead of `runsims`.
|
||||
* [#19726](https://github.com/cosmos/cosmos-sdk/pull/19726) Update APIs to match CometBFT v1.
|
||||
* [#21466](https://github.com/cosmos/cosmos-sdk/pull/21466) Allow chains to plug in their own public key types in `base.Account`
|
||||
* [#21508](https://github.com/cosmos/cosmos-sdk/pull/21508) Abstract the way we update the version of the app state in `app.go` using the interface `VersionModifier`.
|
||||
|
||||
<!-- TODO: move changelog.md elements to here -->
|
||||
|
||||
## v0.47 to v0.50
|
||||
|
||||
No changelog is provided for this migration. Please refer to the [UPGRADING.md](https://github.com/cosmos/cosmos-sdk/blob/main/UPGRADING.md#v050x)
|
||||
|
||||
## v0.46 to v0.47
|
||||
|
||||
No changelog is provided for this migration. Please refer to the [UPGRADING.md](https://github.com/cosmos/cosmos-sdk/blob/main/UPGRADING.md#v047x)
|
||||
|
||||
## v0.45 to v0.46
|
||||
|
||||
No changelog is provided for this migration. Please refer to the [UPGRADING.md](https://github.com/cosmos/cosmos-sdk/blob/main/UPGRADING.md#v046x)
|
||||
122
simapp/README.md
122
simapp/README.md
@ -1,122 +0,0 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# `SimApp`
|
||||
|
||||
`SimApp` is a CLI application built using the Cosmos SDK for testing and educational purposes.
|
||||
|
||||
## Running testnets with `simd`
|
||||
|
||||
Except stated otherwise, all participants in the testnet must follow through with each step.
|
||||
|
||||
### 1. Download and Setup
|
||||
|
||||
Download the Cosmos SDK and unzip it. You can do this manually (via the GitHub UI) or with the git clone command.
|
||||
|
||||
```sh
|
||||
git clone github.com/cosmos/cosmos-sdk.git
|
||||
```
|
||||
|
||||
Next, run this command to build the `simd` binary in the `build` directory.
|
||||
|
||||
```sh
|
||||
make build
|
||||
```
|
||||
|
||||
Use the following command and skip all the next steps to configure your SimApp node:
|
||||
|
||||
```sh
|
||||
make init-simapp
|
||||
```
|
||||
|
||||
If you’ve run `simd` in the past, you may need to reset your database before starting up a new testnet. You can do that with this command:
|
||||
|
||||
```sh
|
||||
# you need to provide the moniker and chain ID
|
||||
$ ./simd init [moniker] --chain-id [chain-id]
|
||||
```
|
||||
|
||||
The command should initialize a new working directory at the `~simapp` location.
|
||||
|
||||
The `moniker` and `chain-id` can be anything but you need to use the same `chain-id` subsequently.
|
||||
|
||||
|
||||
### 2. Create a New Key
|
||||
|
||||
Execute this command to create a new key.
|
||||
|
||||
```sh
|
||||
./simd keys add [key_name]
|
||||
```
|
||||
|
||||
The command will create a new key with your chosen name.
|
||||
|
||||
⚠️ Save the output somewhere safe; you’ll need the address later.
|
||||
|
||||
### 3. Add Genesis Account
|
||||
|
||||
Add a genesis account to your testnet blockchain.
|
||||
|
||||
```sh
|
||||
$ ./simd genesis add-genesis-account [key_name] [amount]
|
||||
```
|
||||
|
||||
Where `key_name` is the same key name as before, and the `amount` is something like `10000000000000000000000000stake`.
|
||||
|
||||
### 4. Add the Genesis Transaction
|
||||
|
||||
This creates the genesis transaction for your testnet chain.
|
||||
|
||||
```sh
|
||||
$ ./simd genesis gentx [key_name] [amount] --chain-id [chain-id]
|
||||
```
|
||||
|
||||
The amount should be at least `1000000000stake`. When you start your node, providing too much or too little may result in errors.
|
||||
|
||||
### 5. Create the Genesis File
|
||||
|
||||
A participant must create the genesis file `genesis.json` with every participant's transaction.
|
||||
|
||||
You can do this by gathering all the Genesis transactions under `config/gentx` and then executing this command.
|
||||
|
||||
```sh
|
||||
$ ./simd genesis collect-gentxs
|
||||
```
|
||||
|
||||
The command will create a new `genesis.json` file that includes data from all the validators. The command will create a new `genesis.json` file, including data from all the validators
|
||||
|
||||
Once you've received the super genesis file, overwrite your original `genesis.json` file with
|
||||
the new super `genesis.json`.
|
||||
|
||||
Modify your `config/config.toml` (in the simapp working directory) to include the other participants as
|
||||
persistent peers:
|
||||
|
||||
```
|
||||
# Comma-separated list of nodes to keep persistent connections to
|
||||
persistent_peers = "[validator_address]@[ip_address]:[port],[validator_address]@[ip_address]:[port]"
|
||||
```
|
||||
|
||||
You can find `validator_address` by executing:
|
||||
|
||||
```sh
|
||||
$ ./simd comet show-node-id
|
||||
```
|
||||
|
||||
The output will be the hex-encoded `validator_address`. The default `port` is 26656.
|
||||
|
||||
### 6. Start the Nodes
|
||||
|
||||
Finally, execute this command to start your nodes.
|
||||
|
||||
```sh
|
||||
$ ./simd start
|
||||
```
|
||||
|
||||
Now you have a small testnet that you can use to try out changes to the Cosmos SDK or CometBFT!
|
||||
|
||||
> ⚠️ NOTE: Sometimes, creating the network through the `collect-gents` will fail, and validators will start in a funny state (and then panic).
|
||||
>
|
||||
|
||||
If this happens, you can try to create and start the network first
|
||||
with a single validator and then add additional validators using a `create-validator` transaction.
|
||||
@ -1,84 +0,0 @@
|
||||
package simapp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
abci "github.com/cometbft/cometbft/api/cometbft/abci/v1"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
type (
|
||||
// VoteExtensionHandler defines a dummy vote extension handler for SimApp.
|
||||
//
|
||||
// NOTE: This implementation is solely used for testing purposes. DO NOT use
|
||||
// in a production application!
|
||||
VoteExtensionHandler struct{}
|
||||
|
||||
// VoteExtension defines the structure used to create a dummy vote extension.
|
||||
VoteExtension struct {
|
||||
Hash []byte
|
||||
Height int64
|
||||
Data []byte
|
||||
}
|
||||
)
|
||||
|
||||
func NewVoteExtensionHandler() *VoteExtensionHandler {
|
||||
return &VoteExtensionHandler{}
|
||||
}
|
||||
|
||||
func (h *VoteExtensionHandler) SetHandlers(bApp *baseapp.BaseApp) {
|
||||
bApp.SetExtendVoteHandler(h.ExtendVote())
|
||||
bApp.SetVerifyVoteExtensionHandler(h.VerifyVoteExtension())
|
||||
}
|
||||
|
||||
func (h *VoteExtensionHandler) ExtendVote() sdk.ExtendVoteHandler {
|
||||
return func(_ sdk.Context, req *abci.ExtendVoteRequest) (*abci.ExtendVoteResponse, error) {
|
||||
buf := make([]byte, 1024)
|
||||
|
||||
_, err := rand.Read(buf)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to generate random vote extension data: %w", err)
|
||||
}
|
||||
|
||||
ve := VoteExtension{
|
||||
Hash: req.Hash,
|
||||
Height: req.Height,
|
||||
Data: buf,
|
||||
}
|
||||
|
||||
bz, err := json.Marshal(ve)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to encode vote extension: %w", err)
|
||||
}
|
||||
|
||||
return &abci.ExtendVoteResponse{VoteExtension: bz}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (h *VoteExtensionHandler) VerifyVoteExtension() sdk.VerifyVoteExtensionHandler {
|
||||
return func(ctx sdk.Context, req *abci.VerifyVoteExtensionRequest) (*abci.VerifyVoteExtensionResponse, error) {
|
||||
var ve VoteExtension
|
||||
|
||||
if err := json.Unmarshal(req.VoteExtension, &ve); err != nil {
|
||||
return &abci.VerifyVoteExtensionResponse{Status: abci.VERIFY_VOTE_EXTENSION_STATUS_REJECT}, nil
|
||||
}
|
||||
|
||||
switch {
|
||||
case req.Height != ve.Height:
|
||||
return &abci.VerifyVoteExtensionResponse{Status: abci.VERIFY_VOTE_EXTENSION_STATUS_REJECT}, nil
|
||||
|
||||
case !bytes.Equal(req.Hash, ve.Hash):
|
||||
return &abci.VerifyVoteExtensionResponse{Status: abci.VERIFY_VOTE_EXTENSION_STATUS_REJECT}, nil
|
||||
|
||||
case len(ve.Data) != 1024:
|
||||
return &abci.VerifyVoteExtensionResponse{Status: abci.VERIFY_VOTE_EXTENSION_STATUS_REJECT}, nil
|
||||
}
|
||||
|
||||
return &abci.VerifyVoteExtensionResponse{Status: abci.VERIFY_VOTE_EXTENSION_STATUS_ACCEPT}, nil
|
||||
}
|
||||
}
|
||||
@ -1,50 +0,0 @@
|
||||
package simapp
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
circuitante "cosmossdk.io/x/circuit/ante"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/ante/unorderedtx"
|
||||
)
|
||||
|
||||
// HandlerOptions are the options required for constructing a default SDK AnteHandler.
|
||||
type HandlerOptions struct {
|
||||
ante.HandlerOptions
|
||||
CircuitKeeper circuitante.CircuitBreaker
|
||||
}
|
||||
|
||||
// NewAnteHandler returns an AnteHandler that checks and increments sequence
|
||||
// numbers, checks signatures & account numbers, and deducts fees from the first
|
||||
// signer.
|
||||
func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
|
||||
if options.AccountKeeper == nil {
|
||||
return nil, errors.New("account keeper is required for ante builder")
|
||||
}
|
||||
|
||||
if options.BankKeeper == nil {
|
||||
return nil, errors.New("bank keeper is required for ante builder")
|
||||
}
|
||||
|
||||
if options.SignModeHandler == nil {
|
||||
return nil, errors.New("sign mode handler is required for ante builder")
|
||||
}
|
||||
|
||||
anteDecorators := []sdk.AnteDecorator{
|
||||
ante.NewSetUpContextDecorator(options.Environment, options.ConsensusKeeper), // outermost AnteDecorator. SetUpContext must be called first
|
||||
circuitante.NewCircuitBreakerDecorator(options.CircuitKeeper),
|
||||
ante.NewExtensionOptionsDecorator(options.ExtensionOptionChecker),
|
||||
ante.NewValidateBasicDecorator(options.Environment),
|
||||
ante.NewTxTimeoutHeightDecorator(options.Environment),
|
||||
ante.NewUnorderedTxDecorator(unorderedtx.DefaultMaxTimeoutDuration, options.UnorderedTxManager, options.Environment, ante.DefaultSha256Cost),
|
||||
ante.NewValidateMemoDecorator(options.AccountKeeper),
|
||||
ante.NewConsumeGasForTxSizeDecorator(options.AccountKeeper),
|
||||
ante.NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, options.TxFeeChecker),
|
||||
ante.NewValidateSigCountDecorator(options.AccountKeeper),
|
||||
ante.NewSigVerificationDecorator(options.AccountKeeper, options.SignModeHandler, options.SigGasConsumer, options.AccountAbstractionKeeper),
|
||||
}
|
||||
|
||||
return sdk.ChainAnteDecorators(anteDecorators...), nil
|
||||
}
|
||||
403
simapp/app.go
403
simapp/app.go
@ -1,403 +0,0 @@
|
||||
package simapp
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
_ "github.com/jackc/pgx/v5/stdlib" // Import and register pgx driver
|
||||
|
||||
clienthelpers "cosmossdk.io/client/v2/helpers"
|
||||
"cosmossdk.io/core/address"
|
||||
"cosmossdk.io/core/appmodule"
|
||||
"cosmossdk.io/core/registry"
|
||||
corestore "cosmossdk.io/core/store"
|
||||
"cosmossdk.io/depinject"
|
||||
"cosmossdk.io/depinject/appconfig"
|
||||
_ "cosmossdk.io/indexer/postgres" // register the postgres indexer
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/x/accounts"
|
||||
basedepinject "cosmossdk.io/x/accounts/defaults/base/depinject"
|
||||
lockupdepinject "cosmossdk.io/x/accounts/defaults/lockup/depinject"
|
||||
multisigdepinject "cosmossdk.io/x/accounts/defaults/multisig/depinject"
|
||||
"cosmossdk.io/x/accounts/testing/account_abstraction"
|
||||
"cosmossdk.io/x/accounts/testing/counter"
|
||||
bankkeeper "cosmossdk.io/x/bank/keeper"
|
||||
circuitkeeper "cosmossdk.io/x/circuit/keeper"
|
||||
consensuskeeper "cosmossdk.io/x/consensus/keeper"
|
||||
distrkeeper "cosmossdk.io/x/distribution/keeper"
|
||||
feegrantkeeper "cosmossdk.io/x/feegrant/keeper"
|
||||
_ "cosmossdk.io/x/protocolpool"
|
||||
slashingkeeper "cosmossdk.io/x/slashing/keeper"
|
||||
stakingkeeper "cosmossdk.io/x/staking/keeper"
|
||||
upgradekeeper "cosmossdk.io/x/upgrade/keeper"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/runtime"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
"github.com/cosmos/cosmos-sdk/server/api"
|
||||
"github.com/cosmos/cosmos-sdk/server/config"
|
||||
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
||||
testdata_pulsar "github.com/cosmos/cosmos-sdk/testutil/testdata/testpb"
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/ante/unorderedtx"
|
||||
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||
authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
)
|
||||
|
||||
// DefaultNodeHome default home directories for the application daemon
|
||||
var DefaultNodeHome string
|
||||
|
||||
var (
|
||||
_ runtime.AppI = (*SimApp)(nil)
|
||||
_ servertypes.Application = (*SimApp)(nil)
|
||||
)
|
||||
|
||||
// SimApp extends an ABCI application, but with most of its parameters exported.
|
||||
// They are exported for convenience in creating helper functions, as object
|
||||
// capabilities aren't needed for testing.
|
||||
type SimApp struct {
|
||||
*runtime.App
|
||||
legacyAmino registry.AminoRegistrar
|
||||
appCodec codec.Codec
|
||||
txConfig client.TxConfig
|
||||
interfaceRegistry codectypes.InterfaceRegistry
|
||||
|
||||
// required keepers during wiring
|
||||
// others keepers are all in the app
|
||||
AccountsKeeper accounts.Keeper
|
||||
AuthKeeper authkeeper.AccountKeeper
|
||||
BankKeeper bankkeeper.Keeper
|
||||
StakingKeeper *stakingkeeper.Keeper
|
||||
SlashingKeeper slashingkeeper.Keeper
|
||||
DistrKeeper distrkeeper.Keeper
|
||||
UpgradeKeeper *upgradekeeper.Keeper
|
||||
FeeGrantKeeper feegrantkeeper.Keeper
|
||||
ConsensusParamsKeeper consensuskeeper.Keeper
|
||||
CircuitBreakerKeeper circuitkeeper.Keeper
|
||||
|
||||
// simulation manager
|
||||
sm *module.SimulationManager
|
||||
}
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
DefaultNodeHome, err = clienthelpers.GetNodeHomeDirectory(".simapp")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// AppConfig returns the default app config.
|
||||
func AppConfig() depinject.Config {
|
||||
return depinject.Configs(
|
||||
appconfig.Compose(appConfig), // Alternatively use appconfig.LoadYAML(AppConfigYAML)
|
||||
depinject.Provide(
|
||||
ProvideExampleMintFn, // optional: override the mint module's mint function with epoched minting
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// NewSimApp returns a reference to an initialized SimApp.
|
||||
func NewSimApp(
|
||||
logger log.Logger,
|
||||
db corestore.KVStoreWithBatch,
|
||||
traceStore io.Writer,
|
||||
loadLatest bool,
|
||||
appOpts servertypes.AppOptions,
|
||||
baseAppOptions ...func(*baseapp.BaseApp),
|
||||
) *SimApp {
|
||||
var (
|
||||
app = &SimApp{}
|
||||
appBuilder *runtime.AppBuilder
|
||||
|
||||
// merge the AppConfig and other configuration in one config
|
||||
appConfig = depinject.Configs(
|
||||
AppConfig(),
|
||||
depinject.Supply(
|
||||
// supply the application options
|
||||
appOpts,
|
||||
// supply the logger
|
||||
logger,
|
||||
// ADVANCED CONFIGURATION
|
||||
|
||||
//
|
||||
// AUTH
|
||||
//
|
||||
// For providing a custom function required in auth to generate custom account types
|
||||
// add it below. By default the auth module uses simulation.RandomGenesisAccounts.
|
||||
//
|
||||
// authtypes.RandomGenesisAccountsFn(simulation.RandomGenesisAccounts),
|
||||
//
|
||||
// For providing a custom a base account type add it below.
|
||||
// By default the auth module uses authtypes.ProtoBaseAccount().
|
||||
//
|
||||
// func() sdk.AccountI { return authtypes.ProtoBaseAccount() },
|
||||
//
|
||||
// For providing a different address codec, add it below.
|
||||
// By default the auth module uses a Bech32 address codec,
|
||||
// with the prefix defined in the auth module configuration.
|
||||
//
|
||||
// func() address.Codec { return <- custom address codec type -> }
|
||||
|
||||
//
|
||||
// STAKING
|
||||
//
|
||||
// For provinding a different validator and consensus address codec, add it below.
|
||||
// By default the staking module uses the bech32 prefix provided in the auth config,
|
||||
// and appends "valoper" and "valcons" for validator and consensus addresses respectively.
|
||||
// When providing a custom address codec in auth, custom address codecs must be provided here as well.
|
||||
//
|
||||
// func() runtime.ValidatorAddressCodec { return <- custom validator address codec type -> }
|
||||
// func() runtime.ConsensusAddressCodec { return <- custom consensus address codec type -> }
|
||||
|
||||
//
|
||||
// MINT
|
||||
//
|
||||
|
||||
// For providing a custom inflation function for x/mint add here your
|
||||
// custom function that implements the minttypes.MintFn interface.
|
||||
),
|
||||
depinject.Provide(
|
||||
// inject desired account types:
|
||||
multisigdepinject.ProvideAccount,
|
||||
basedepinject.ProvideAccount,
|
||||
lockupdepinject.ProvideAllLockupAccounts,
|
||||
|
||||
// provide base account options
|
||||
basedepinject.ProvideSecp256K1PubKey,
|
||||
// if you want to provide a custom public key you
|
||||
// can do it from here.
|
||||
// Example:
|
||||
// basedepinject.ProvideCustomPubkey[Ed25519PublicKey]()
|
||||
//
|
||||
// You can also provide a custom public key with a custom validation function:
|
||||
//
|
||||
// basedepinject.ProvideCustomPubKeyAndValidationFunc(func(pub Ed25519PublicKey) error {
|
||||
// if len(pub.Key) != 64 {
|
||||
// return fmt.Errorf("invalid pub key size")
|
||||
// }
|
||||
// })
|
||||
|
||||
// TESTING: do not add below account types
|
||||
counter.ProvideAccount,
|
||||
account_abstraction.ProvideAccount,
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
var appModules map[string]appmodule.AppModule
|
||||
if err := depinject.Inject(appConfig,
|
||||
&appBuilder,
|
||||
&appModules,
|
||||
&app.appCodec,
|
||||
&app.legacyAmino,
|
||||
&app.txConfig,
|
||||
&app.interfaceRegistry,
|
||||
&app.AuthKeeper,
|
||||
&app.AccountsKeeper,
|
||||
&app.BankKeeper,
|
||||
&app.StakingKeeper,
|
||||
&app.SlashingKeeper,
|
||||
&app.DistrKeeper,
|
||||
&app.UpgradeKeeper,
|
||||
&app.FeeGrantKeeper,
|
||||
&app.ConsensusParamsKeeper,
|
||||
&app.CircuitBreakerKeeper,
|
||||
); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Below we could construct and set an application specific mempool and
|
||||
// ABCI 1.0 PrepareProposal and ProcessProposal handlers. These defaults are
|
||||
// already set in the SDK's BaseApp, this shows an example of how to override
|
||||
// them.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// app.App = appBuilder.Build(...)
|
||||
// nonceMempool := mempool.NewSenderNonceMempool()
|
||||
// abciPropHandler := NewDefaultProposalHandler(nonceMempool, app.App.BaseApp)
|
||||
//
|
||||
// app.App.BaseApp.SetMempool(nonceMempool)
|
||||
// app.App.BaseApp.SetPrepareProposal(abciPropHandler.PrepareProposalHandler())
|
||||
// app.App.BaseApp.SetProcessProposal(abciPropHandler.ProcessProposalHandler())
|
||||
//
|
||||
// Alternatively, you can construct BaseApp options, append those to
|
||||
// baseAppOptions and pass them to the appBuilder.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// prepareOpt = func(app *baseapp.BaseApp) {
|
||||
// abciPropHandler := baseapp.NewDefaultProposalHandler(nonceMempool, app)
|
||||
// app.SetPrepareProposal(abciPropHandler.PrepareProposalHandler())
|
||||
// }
|
||||
// baseAppOptions = append(baseAppOptions, prepareOpt)
|
||||
|
||||
// create and set dummy vote extension handler
|
||||
voteExtOp := func(bApp *baseapp.BaseApp) {
|
||||
voteExtHandler := NewVoteExtensionHandler()
|
||||
voteExtHandler.SetHandlers(bApp)
|
||||
}
|
||||
baseAppOptions = append(baseAppOptions, voteExtOp, baseapp.SetOptimisticExecution())
|
||||
|
||||
app.App = appBuilder.Build(db, traceStore, baseAppOptions...)
|
||||
|
||||
/**** Module Options ****/
|
||||
|
||||
// RegisterUpgradeHandlers is used for registering any on-chain upgrades.
|
||||
app.RegisterUpgradeHandlers()
|
||||
|
||||
// add test gRPC service for testing gRPC queries in isolation
|
||||
testdata_pulsar.RegisterQueryServer(app.GRPCQueryRouter(), testdata_pulsar.QueryImpl{})
|
||||
|
||||
// create the simulation manager and define the order of the modules for deterministic simulations
|
||||
//
|
||||
// NOTE: this is not required apps that don't use the simulator for fuzz testing
|
||||
// transactions
|
||||
overrideModules := map[string]module.AppModuleSimulation{
|
||||
authtypes.ModuleName: auth.NewAppModule(app.appCodec, app.AuthKeeper, &app.AccountsKeeper, authsims.RandomGenesisAccounts, nil),
|
||||
}
|
||||
app.sm = module.NewSimulationManagerFromAppModules(app.ModuleManager.Modules, overrideModules)
|
||||
|
||||
app.sm.RegisterStoreDecoders()
|
||||
|
||||
// A custom InitChainer can be set if extra pre-init-genesis logic is required.
|
||||
// By default, when using app wiring enabled module, this is not required.
|
||||
// For instance, the upgrade module will set automatically the module version map in its init genesis thanks to app wiring.
|
||||
// However, when registering a module manually (i.e. that does not support app wiring), the module version map
|
||||
// must be set manually as follow. The upgrade module will de-duplicate the module version map.
|
||||
//
|
||||
// app.SetInitChainer(func(ctx sdk.Context, req *abci.InitChainRequest) (*abci.InitChainResponse, error) {
|
||||
// app.UpgradeKeeper.SetModuleVersionMap(ctx, app.ModuleManager.GetVersionMap())
|
||||
// return app.App.InitChainer(ctx, req)
|
||||
// })
|
||||
|
||||
// register custom snapshot extensions (if any)
|
||||
if manager := app.SnapshotManager(); manager != nil {
|
||||
if err := manager.RegisterExtensions(
|
||||
unorderedtx.NewSnapshotter(app.UnorderedTxManager),
|
||||
); err != nil {
|
||||
panic(fmt.Errorf("failed to register snapshot extension: %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
// set custom ante handlers
|
||||
app.setCustomAnteHandler()
|
||||
|
||||
if err := app.Load(loadLatest); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
// setCustomAnteHandler overwrites default ante handlers with custom ante handlers
|
||||
// set SkipAnteHandler to true in app config and set custom ante handler on baseapp
|
||||
func (app *SimApp) setCustomAnteHandler() {
|
||||
anteHandler, err := NewAnteHandler(
|
||||
HandlerOptions{
|
||||
ante.HandlerOptions{
|
||||
AccountKeeper: app.AuthKeeper,
|
||||
BankKeeper: app.BankKeeper,
|
||||
ConsensusKeeper: app.ConsensusParamsKeeper,
|
||||
SignModeHandler: app.txConfig.SignModeHandler(),
|
||||
FeegrantKeeper: app.FeeGrantKeeper,
|
||||
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
|
||||
UnorderedTxManager: app.UnorderedTxManager,
|
||||
Environment: app.AuthKeeper.Environment,
|
||||
AccountAbstractionKeeper: app.AccountsKeeper,
|
||||
},
|
||||
&app.CircuitBreakerKeeper,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Set the AnteHandler for the app
|
||||
app.SetAnteHandler(anteHandler)
|
||||
}
|
||||
|
||||
// LegacyAmino returns SimApp's amino codec.
|
||||
//
|
||||
// NOTE: This is solely to be used for testing purposes as it may be desirable
|
||||
// for modules to register their own custom testing types.
|
||||
func (app *SimApp) LegacyAmino() *codec.LegacyAmino {
|
||||
switch cdc := app.legacyAmino.(type) {
|
||||
case *codec.LegacyAmino:
|
||||
return cdc
|
||||
default:
|
||||
panic("unexpected codec type")
|
||||
}
|
||||
}
|
||||
|
||||
// AppCodec returns SimApp's app codec.
|
||||
//
|
||||
// NOTE: This is solely to be used for testing purposes as it may be desirable
|
||||
// for modules to register their own custom testing types.
|
||||
func (app *SimApp) AppCodec() codec.Codec {
|
||||
return app.appCodec
|
||||
}
|
||||
|
||||
// InterfaceRegistry returns SimApp's InterfaceRegistry.
|
||||
func (app *SimApp) InterfaceRegistry() codectypes.InterfaceRegistry {
|
||||
return app.interfaceRegistry
|
||||
}
|
||||
|
||||
// TxConfig returns SimApp's TxConfig
|
||||
func (app *SimApp) TxConfig() client.TxConfig {
|
||||
return app.txConfig
|
||||
}
|
||||
|
||||
// SimulationManager implements the SimulationApp interface
|
||||
func (app *SimApp) SimulationManager() *module.SimulationManager {
|
||||
return app.sm
|
||||
}
|
||||
|
||||
// RegisterAPIRoutes registers all application module routes with the provided
|
||||
// API server.
|
||||
func (app *SimApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) {
|
||||
app.App.RegisterAPIRoutes(apiSvr, apiConfig)
|
||||
// register swagger API in app.go so that other applications can override easily
|
||||
if err := server.RegisterSwaggerAPI(apiSvr.ClientCtx, apiSvr.Router, apiConfig.Swagger); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// GetMaccPerms returns a copy of the module account permissions
|
||||
//
|
||||
// NOTE: This is solely to be used for testing purposes.
|
||||
func GetMaccPerms() map[string][]string {
|
||||
dup := make(map[string][]string)
|
||||
for _, perms := range moduleAccPerms {
|
||||
dup[perms.Account] = perms.Permissions
|
||||
}
|
||||
|
||||
return dup
|
||||
}
|
||||
|
||||
// BlockedAddresses returns all the app's blocked account addresses.
|
||||
// This function takes an address.Codec parameter to maintain compatibility
|
||||
// with the signature of the same function in appV1.
|
||||
func BlockedAddresses(_ address.Codec) (map[string]bool, error) {
|
||||
result := make(map[string]bool)
|
||||
|
||||
if len(blockAccAddrs) > 0 {
|
||||
for _, addr := range blockAccAddrs {
|
||||
result[addr] = true
|
||||
}
|
||||
} else {
|
||||
for addr := range GetMaccPerms() {
|
||||
result[addr] = true
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
@ -1,301 +0,0 @@
|
||||
//nolint:unused,nolintlint // ignore unused code linting
|
||||
package simapp
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"google.golang.org/protobuf/types/known/durationpb"
|
||||
|
||||
accountsmodulev1 "cosmossdk.io/api/cosmos/accounts/module/v1"
|
||||
runtimev1alpha1 "cosmossdk.io/api/cosmos/app/runtime/v1alpha1"
|
||||
appv1alpha1 "cosmossdk.io/api/cosmos/app/v1alpha1"
|
||||
authmodulev1 "cosmossdk.io/api/cosmos/auth/module/v1"
|
||||
authzmodulev1 "cosmossdk.io/api/cosmos/authz/module/v1"
|
||||
bankmodulev1 "cosmossdk.io/api/cosmos/bank/module/v1"
|
||||
circuitmodulev1 "cosmossdk.io/api/cosmos/circuit/module/v1"
|
||||
consensusmodulev1 "cosmossdk.io/api/cosmos/consensus/module/v1"
|
||||
distrmodulev1 "cosmossdk.io/api/cosmos/distribution/module/v1"
|
||||
epochsmodulev1 "cosmossdk.io/api/cosmos/epochs/module/v1"
|
||||
evidencemodulev1 "cosmossdk.io/api/cosmos/evidence/module/v1"
|
||||
feegrantmodulev1 "cosmossdk.io/api/cosmos/feegrant/module/v1"
|
||||
genutilmodulev1 "cosmossdk.io/api/cosmos/genutil/module/v1"
|
||||
govmodulev1 "cosmossdk.io/api/cosmos/gov/module/v1"
|
||||
groupmodulev1 "cosmossdk.io/api/cosmos/group/module/v1"
|
||||
mintmodulev1 "cosmossdk.io/api/cosmos/mint/module/v1"
|
||||
nftmodulev1 "cosmossdk.io/api/cosmos/nft/module/v1"
|
||||
poolmodulev1 "cosmossdk.io/api/cosmos/protocolpool/module/v1"
|
||||
slashingmodulev1 "cosmossdk.io/api/cosmos/slashing/module/v1"
|
||||
stakingmodulev1 "cosmossdk.io/api/cosmos/staking/module/v1"
|
||||
txconfigv1 "cosmossdk.io/api/cosmos/tx/config/v1"
|
||||
upgrademodulev1 "cosmossdk.io/api/cosmos/upgrade/module/v1"
|
||||
validatemodulev1 "cosmossdk.io/api/cosmos/validate/module/v1"
|
||||
vestingmodulev1 "cosmossdk.io/api/cosmos/vesting/module/v1"
|
||||
"cosmossdk.io/depinject/appconfig"
|
||||
"cosmossdk.io/x/accounts"
|
||||
"cosmossdk.io/x/authz"
|
||||
_ "cosmossdk.io/x/authz/module" // import for side-effects
|
||||
_ "cosmossdk.io/x/bank" // import for side-effects
|
||||
banktypes "cosmossdk.io/x/bank/types"
|
||||
_ "cosmossdk.io/x/bank/v2" // import for side-effects
|
||||
bankv2types "cosmossdk.io/x/bank/v2/types"
|
||||
bankmodulev2 "cosmossdk.io/x/bank/v2/types/module"
|
||||
_ "cosmossdk.io/x/circuit" // import for side-effects
|
||||
circuittypes "cosmossdk.io/x/circuit/types"
|
||||
_ "cosmossdk.io/x/consensus" // import for side-effects
|
||||
consensustypes "cosmossdk.io/x/consensus/types"
|
||||
_ "cosmossdk.io/x/distribution" // import for side-effects
|
||||
distrtypes "cosmossdk.io/x/distribution/types"
|
||||
_ "cosmossdk.io/x/epochs" // import for side-effects
|
||||
epochstypes "cosmossdk.io/x/epochs/types"
|
||||
_ "cosmossdk.io/x/evidence" // import for side-effects
|
||||
evidencetypes "cosmossdk.io/x/evidence/types"
|
||||
"cosmossdk.io/x/feegrant"
|
||||
_ "cosmossdk.io/x/feegrant/module" // import for side-effects
|
||||
_ "cosmossdk.io/x/gov" // import for side-effects
|
||||
govtypes "cosmossdk.io/x/gov/types"
|
||||
"cosmossdk.io/x/group"
|
||||
_ "cosmossdk.io/x/group/module" // import for side-effects
|
||||
_ "cosmossdk.io/x/mint" // import for side-effects
|
||||
minttypes "cosmossdk.io/x/mint/types"
|
||||
"cosmossdk.io/x/nft"
|
||||
_ "cosmossdk.io/x/nft/module" // import for side-effects
|
||||
_ "cosmossdk.io/x/protocolpool" // import for side-effects
|
||||
pooltypes "cosmossdk.io/x/protocolpool/types"
|
||||
_ "cosmossdk.io/x/slashing" // import for side-effects
|
||||
slashingtypes "cosmossdk.io/x/slashing/types"
|
||||
_ "cosmossdk.io/x/staking" // import for side-effects
|
||||
stakingtypes "cosmossdk.io/x/staking/types"
|
||||
_ "cosmossdk.io/x/upgrade" // import for side-effects
|
||||
upgradetypes "cosmossdk.io/x/upgrade/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/runtime"
|
||||
_ "github.com/cosmos/cosmos-sdk/testutil/x/counter" // import for side-effects
|
||||
authtxconfig "github.com/cosmos/cosmos-sdk/x/auth/tx/config"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
_ "github.com/cosmos/cosmos-sdk/x/auth/vesting" // import for side-effects
|
||||
vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
|
||||
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/validate"
|
||||
)
|
||||
|
||||
var (
|
||||
// module account permissions
|
||||
moduleAccPerms = []*authmodulev1.ModuleAccountPermission{
|
||||
{Account: authtypes.FeeCollectorName},
|
||||
{Account: distrtypes.ModuleName},
|
||||
{Account: pooltypes.ModuleName},
|
||||
{Account: pooltypes.StreamAccount},
|
||||
{Account: pooltypes.ProtocolPoolDistrAccount},
|
||||
{Account: minttypes.ModuleName, Permissions: []string{authtypes.Minter}},
|
||||
{Account: stakingtypes.BondedPoolName, Permissions: []string{authtypes.Burner, stakingtypes.ModuleName}},
|
||||
{Account: stakingtypes.NotBondedPoolName, Permissions: []string{authtypes.Burner, stakingtypes.ModuleName}},
|
||||
{Account: govtypes.ModuleName, Permissions: []string{authtypes.Burner}},
|
||||
{Account: nft.ModuleName},
|
||||
}
|
||||
|
||||
// blocked account addresses
|
||||
blockAccAddrs = []string{
|
||||
authtypes.FeeCollectorName,
|
||||
distrtypes.ModuleName,
|
||||
minttypes.ModuleName,
|
||||
stakingtypes.BondedPoolName,
|
||||
stakingtypes.NotBondedPoolName,
|
||||
nft.ModuleName,
|
||||
// We allow the following module accounts to receive funds:
|
||||
// govtypes.ModuleName
|
||||
// pooltypes.ModuleName
|
||||
}
|
||||
|
||||
// application configuration (used by depinject)
|
||||
appConfig = &appv1alpha1.Config{
|
||||
Modules: []*appv1alpha1.ModuleConfig{
|
||||
{
|
||||
Name: runtime.ModuleName,
|
||||
Config: appconfig.WrapAny(&runtimev1alpha1.Module{
|
||||
AppName: "SimApp",
|
||||
// NOTE: upgrade module is required to be prioritized
|
||||
PreBlockers: []string{
|
||||
upgradetypes.ModuleName,
|
||||
},
|
||||
// During begin block slashing happens after distr.BeginBlocker so that
|
||||
// there is nothing left over in the validator fee pool, so as to keep the
|
||||
// CanWithdrawInvariant invariant.
|
||||
// NOTE: staking module is required if HistoricalEntries param > 0
|
||||
BeginBlockers: []string{
|
||||
minttypes.ModuleName,
|
||||
distrtypes.ModuleName,
|
||||
pooltypes.ModuleName,
|
||||
slashingtypes.ModuleName,
|
||||
evidencetypes.ModuleName,
|
||||
stakingtypes.ModuleName,
|
||||
authz.ModuleName,
|
||||
epochstypes.ModuleName,
|
||||
},
|
||||
EndBlockers: []string{
|
||||
govtypes.ModuleName,
|
||||
stakingtypes.ModuleName,
|
||||
feegrant.ModuleName,
|
||||
group.ModuleName,
|
||||
pooltypes.ModuleName,
|
||||
},
|
||||
// The following is mostly only needed when ModuleName != StoreKey name.
|
||||
OverrideStoreKeys: []*runtimev1alpha1.StoreKeyConfig{
|
||||
{
|
||||
ModuleName: authtypes.ModuleName,
|
||||
KvStoreKey: "acc",
|
||||
},
|
||||
{
|
||||
ModuleName: accounts.ModuleName,
|
||||
KvStoreKey: accounts.StoreKey,
|
||||
},
|
||||
},
|
||||
// NOTE: The genutils module must occur after staking so that pools are
|
||||
// properly initialized with tokens from genesis accounts.
|
||||
// NOTE: The genutils module must also occur after auth so that it can access the params from auth.
|
||||
InitGenesis: []string{
|
||||
consensustypes.ModuleName,
|
||||
accounts.ModuleName,
|
||||
authtypes.ModuleName,
|
||||
banktypes.ModuleName,
|
||||
bankv2types.ModuleName,
|
||||
distrtypes.ModuleName,
|
||||
stakingtypes.ModuleName,
|
||||
slashingtypes.ModuleName,
|
||||
govtypes.ModuleName,
|
||||
minttypes.ModuleName,
|
||||
genutiltypes.ModuleName,
|
||||
evidencetypes.ModuleName,
|
||||
authz.ModuleName,
|
||||
feegrant.ModuleName,
|
||||
nft.ModuleName,
|
||||
group.ModuleName,
|
||||
upgradetypes.ModuleName,
|
||||
vestingtypes.ModuleName,
|
||||
circuittypes.ModuleName,
|
||||
pooltypes.ModuleName,
|
||||
epochstypes.ModuleName,
|
||||
},
|
||||
// When ExportGenesis is not specified, the export genesis module order
|
||||
// is equal to the init genesis order
|
||||
// ExportGenesis: []string{},
|
||||
// Uncomment if you want to set a custom migration order here.
|
||||
// OrderMigrations: []string{},
|
||||
// SkipStoreKeys is an optional list of store keys to skip when constructing the
|
||||
// module's keeper. This is useful when a module does not have a store key.
|
||||
SkipStoreKeys: []string{
|
||||
authtxconfig.DepinjectModuleName,
|
||||
validate.ModuleName,
|
||||
},
|
||||
}),
|
||||
},
|
||||
{
|
||||
Name: authtxconfig.DepinjectModuleName, // x/auth/tx/config depinject module (not app module), use to provide tx configuration
|
||||
Config: appconfig.WrapAny(&txconfigv1.Config{}),
|
||||
},
|
||||
{
|
||||
Name: validate.ModuleName,
|
||||
Config: appconfig.WrapAny(&validatemodulev1.Module{}),
|
||||
},
|
||||
{
|
||||
Name: authtypes.ModuleName,
|
||||
Config: appconfig.WrapAny(&authmodulev1.Module{
|
||||
Bech32Prefix: "cosmos",
|
||||
ModuleAccountPermissions: moduleAccPerms,
|
||||
// By default modules authority is the governance module. This is configurable with the following:
|
||||
// Authority: "group", // A custom module authority can be set using a module name
|
||||
// Authority: "cosmos1cwwv22j5ca08ggdv9c2uky355k908694z577tv", // or a specific address
|
||||
}),
|
||||
},
|
||||
{
|
||||
Name: vestingtypes.ModuleName,
|
||||
Config: appconfig.WrapAny(&vestingmodulev1.Module{}),
|
||||
},
|
||||
{
|
||||
Name: banktypes.ModuleName,
|
||||
Config: appconfig.WrapAny(&bankmodulev1.Module{
|
||||
BlockedModuleAccountsOverride: blockAccAddrs,
|
||||
}),
|
||||
},
|
||||
{
|
||||
Name: stakingtypes.ModuleName,
|
||||
Config: appconfig.WrapAny(&stakingmodulev1.Module{
|
||||
// NOTE: specifying a prefix is only necessary when using bech32 addresses
|
||||
// If not specified, the auth Bech32Prefix appended with "valoper" and "valcons" is used by default
|
||||
Bech32PrefixValidator: "cosmosvaloper",
|
||||
Bech32PrefixConsensus: "cosmosvalcons",
|
||||
}),
|
||||
},
|
||||
{
|
||||
Name: slashingtypes.ModuleName,
|
||||
Config: appconfig.WrapAny(&slashingmodulev1.Module{}),
|
||||
},
|
||||
{
|
||||
Name: genutiltypes.ModuleName,
|
||||
Config: appconfig.WrapAny(&genutilmodulev1.Module{}),
|
||||
},
|
||||
{
|
||||
Name: authz.ModuleName,
|
||||
Config: appconfig.WrapAny(&authzmodulev1.Module{}),
|
||||
},
|
||||
{
|
||||
Name: upgradetypes.ModuleName,
|
||||
Config: appconfig.WrapAny(&upgrademodulev1.Module{}),
|
||||
},
|
||||
{
|
||||
Name: distrtypes.ModuleName,
|
||||
Config: appconfig.WrapAny(&distrmodulev1.Module{}),
|
||||
},
|
||||
{
|
||||
Name: evidencetypes.ModuleName,
|
||||
Config: appconfig.WrapAny(&evidencemodulev1.Module{}),
|
||||
},
|
||||
{
|
||||
Name: minttypes.ModuleName,
|
||||
Config: appconfig.WrapAny(&mintmodulev1.Module{}),
|
||||
},
|
||||
{
|
||||
Name: group.ModuleName,
|
||||
Config: appconfig.WrapAny(&groupmodulev1.Module{
|
||||
MaxExecutionPeriod: durationpb.New(time.Second * 1209600),
|
||||
MaxMetadataLen: 255,
|
||||
}),
|
||||
},
|
||||
{
|
||||
Name: nft.ModuleName,
|
||||
Config: appconfig.WrapAny(&nftmodulev1.Module{}),
|
||||
},
|
||||
{
|
||||
Name: feegrant.ModuleName,
|
||||
Config: appconfig.WrapAny(&feegrantmodulev1.Module{}),
|
||||
},
|
||||
{
|
||||
Name: govtypes.ModuleName,
|
||||
Config: appconfig.WrapAny(&govmodulev1.Module{}),
|
||||
},
|
||||
{
|
||||
Name: consensustypes.ModuleName,
|
||||
Config: appconfig.WrapAny(&consensusmodulev1.Module{}),
|
||||
},
|
||||
{
|
||||
Name: circuittypes.ModuleName,
|
||||
Config: appconfig.WrapAny(&circuitmodulev1.Module{}),
|
||||
},
|
||||
{
|
||||
Name: pooltypes.ModuleName,
|
||||
Config: appconfig.WrapAny(&poolmodulev1.Module{}),
|
||||
},
|
||||
{
|
||||
Name: accounts.ModuleName,
|
||||
Config: appconfig.WrapAny(&accountsmodulev1.Module{}),
|
||||
},
|
||||
{
|
||||
Name: epochstypes.ModuleName,
|
||||
Config: appconfig.WrapAny(&epochsmodulev1.Module{}),
|
||||
},
|
||||
{
|
||||
Name: bankv2types.ModuleName,
|
||||
Config: appconfig.WrapAny(&bankmodulev2.Module{}),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
@ -1,315 +0,0 @@
|
||||
package simapp
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
abci "github.com/cometbft/cometbft/api/cometbft/abci/v1"
|
||||
cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1"
|
||||
"github.com/cosmos/gogoproto/proto"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/mock/gomock"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"cosmossdk.io/core/appmodule"
|
||||
coretesting "cosmossdk.io/core/testing"
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/x/accounts"
|
||||
authzmodule "cosmossdk.io/x/authz/module"
|
||||
"cosmossdk.io/x/bank"
|
||||
banktypes "cosmossdk.io/x/bank/types"
|
||||
bankv2 "cosmossdk.io/x/bank/v2"
|
||||
"cosmossdk.io/x/distribution"
|
||||
"cosmossdk.io/x/epochs"
|
||||
"cosmossdk.io/x/evidence"
|
||||
feegrantmodule "cosmossdk.io/x/feegrant/module"
|
||||
"cosmossdk.io/x/gov"
|
||||
group "cosmossdk.io/x/group/module"
|
||||
"cosmossdk.io/x/mint"
|
||||
"cosmossdk.io/x/protocolpool"
|
||||
"cosmossdk.io/x/slashing"
|
||||
"cosmossdk.io/x/staking"
|
||||
"cosmossdk.io/x/upgrade"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/mock"
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
"github.com/cosmos/cosmos-sdk/types/msgservice"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/vesting"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil"
|
||||
)
|
||||
|
||||
func TestSimAppExportAndBlockedAddrs(t *testing.T) {
|
||||
db := coretesting.NewMemDB()
|
||||
logger := log.NewTestLogger(t)
|
||||
app := NewSimappWithCustomOptions(t, false, SetupOptions{
|
||||
Logger: logger.With("instance", "first"),
|
||||
DB: db,
|
||||
AppOpts: simtestutil.NewAppOptionsWithFlagHome(t.TempDir()),
|
||||
})
|
||||
|
||||
// BlockedAddresses returns a map of addresses in app v1 and a map of modules names in app di.
|
||||
blockedAddrs, err := BlockedAddresses(app.interfaceRegistry.SigningContext().AddressCodec())
|
||||
require.NoError(t, err)
|
||||
for acc := range blockedAddrs {
|
||||
var addr sdk.AccAddress
|
||||
if modAddr, err := app.InterfaceRegistry().SigningContext().AddressCodec().StringToBytes(acc); err == nil {
|
||||
addr = modAddr
|
||||
} else {
|
||||
addr = app.AuthKeeper.GetModuleAddress(acc)
|
||||
}
|
||||
|
||||
require.True(
|
||||
t,
|
||||
app.BankKeeper.BlockedAddr(addr),
|
||||
fmt.Sprintf("ensure that blocked addresses are properly set in bank keeper: %s should be blocked", acc),
|
||||
)
|
||||
}
|
||||
|
||||
// finalize block so we have CheckTx state set
|
||||
_, err = app.FinalizeBlock(&abci.FinalizeBlockRequest{
|
||||
Height: 1,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = app.Commit()
|
||||
require.NoError(t, err)
|
||||
|
||||
// Making a new app object with the db, so that initchain hasn't been called
|
||||
app2 := NewSimApp(logger.With("instance", "second"), db, nil, true, simtestutil.NewAppOptionsWithFlagHome(t.TempDir()))
|
||||
_, err = app2.ExportAppStateAndValidators(false, []string{}, []string{})
|
||||
require.NoError(t, err, "ExportAppStateAndValidators should not have an error")
|
||||
}
|
||||
|
||||
func TestRunMigrations(t *testing.T) {
|
||||
db := coretesting.NewMemDB()
|
||||
logger := log.NewTestLogger(t)
|
||||
app := NewSimApp(logger.With("instance", "simapp"), db, nil, true, simtestutil.NewAppOptionsWithFlagHome(t.TempDir()))
|
||||
|
||||
// Create a new baseapp and configurator for the purpose of this test.
|
||||
bApp := baseapp.NewBaseApp(app.Name(), logger.With("instance", "baseapp"), db, app.TxConfig().TxDecoder())
|
||||
bApp.SetCommitMultiStoreTracer(nil)
|
||||
bApp.SetInterfaceRegistry(app.InterfaceRegistry())
|
||||
app.BaseApp = bApp
|
||||
configurator := module.NewConfigurator(app.appCodec, bApp.MsgServiceRouter(), app.GRPCQueryRouter())
|
||||
|
||||
// We register all modules on the Configurator, except x/bank. x/bank will
|
||||
// serve as the test subject on which we run the migration tests.
|
||||
//
|
||||
// The loop below is the same as calling `RegisterServices` on
|
||||
// ModuleManager, except that we skip x/bank.
|
||||
for name, mod := range app.ModuleManager.Modules {
|
||||
if name == banktypes.ModuleName {
|
||||
continue
|
||||
}
|
||||
|
||||
if mod, ok := mod.(module.HasServices); ok {
|
||||
mod.RegisterServices(configurator)
|
||||
}
|
||||
|
||||
if mod, ok := mod.(interface {
|
||||
RegisterServices(grpc.ServiceRegistrar) error
|
||||
}); ok {
|
||||
err := mod.RegisterServices(configurator)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
require.NoError(t, configurator.Error())
|
||||
}
|
||||
|
||||
// Initialize the chain
|
||||
_, err := app.InitChain(&abci.InitChainRequest{})
|
||||
require.NoError(t, err)
|
||||
_, err = app.Commit()
|
||||
require.NoError(t, err)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
moduleName string
|
||||
fromVersion uint64
|
||||
toVersion uint64
|
||||
expRegErr bool // errors while registering migration
|
||||
expRegErrMsg string
|
||||
expRunErr bool // errors while running migration
|
||||
expRunErrMsg string
|
||||
expCalled int
|
||||
}{
|
||||
{
|
||||
"cannot register migration for version 0",
|
||||
"bank", 0, 1,
|
||||
true, "module migration versions should start at 1: invalid version", false, "", 0,
|
||||
},
|
||||
{
|
||||
"throws error on RunMigrations if no migration registered for bank",
|
||||
"", 1, 2,
|
||||
false, "", true, "no migrations found for module bank: not found", 0,
|
||||
},
|
||||
{
|
||||
"can register 1->2 migration handler for x/bank, cannot run migration",
|
||||
"bank", 1, 2,
|
||||
false, "", true, "no migration found for module bank from version 2 to version 3: not found", 0,
|
||||
},
|
||||
{
|
||||
"can register 2->3 migration handler for x/bank, can run migration",
|
||||
"bank", 2, bank.AppModule{}.ConsensusVersion(),
|
||||
false, "", false, "", int(bank.AppModule{}.ConsensusVersion() - 2), // minus 2 because 1-2 is run in the previous test case.
|
||||
},
|
||||
{
|
||||
"cannot register migration handler for same module & fromVersion",
|
||||
"bank", 1, 2,
|
||||
true, "another migration for module bank and version 1 already exists: internal logic error", false, "", 0,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(tt *testing.T) {
|
||||
var err error
|
||||
|
||||
// Since it's very hard to test actual in-place store migrations in
|
||||
// tests (due to the difficulty of maintaining multiple versions of a
|
||||
// module), we're just testing here that the migration logic is
|
||||
// called.
|
||||
called := 0
|
||||
|
||||
if tc.moduleName != "" {
|
||||
for i := tc.fromVersion; i < tc.toVersion; i++ {
|
||||
// Register migration for module from version `fromVersion` to `fromVersion+1`.
|
||||
tt.Logf("Registering migration for %q v%d", tc.moduleName, i)
|
||||
err = configurator.RegisterMigration(tc.moduleName, i, func(sdk.Context) error {
|
||||
called++
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if tc.expRegErr {
|
||||
require.EqualError(tt, err, tc.expRegErrMsg)
|
||||
|
||||
return
|
||||
}
|
||||
require.NoError(tt, err, "registering migration")
|
||||
}
|
||||
}
|
||||
|
||||
orderMigrations := module.DefaultMigrationsOrder(app.ModuleManager.ModuleNames())
|
||||
// Filter out benchmark module from migrations list
|
||||
filteredMigrations := make([]string, 0, len(app.ModuleManager.OrderMigrations))
|
||||
for _, name := range orderMigrations {
|
||||
if name != "benchmark" {
|
||||
filteredMigrations = append(filteredMigrations, name)
|
||||
}
|
||||
}
|
||||
app.ModuleManager.OrderMigrations = filteredMigrations
|
||||
|
||||
// Run migrations only for bank. That's why we put the initial
|
||||
// version for bank as 1, and for all other modules, we put as
|
||||
// their latest ConsensusVersion.
|
||||
_, err = app.ModuleManager.RunMigrations(
|
||||
app.NewContextLegacy(true, cmtproto.Header{Height: app.LastBlockHeight()}), configurator,
|
||||
appmodule.VersionMap{
|
||||
"accounts": accounts.AppModule{}.ConsensusVersion(),
|
||||
"bank": 1,
|
||||
"bankv2": bankv2.AppModule{}.ConsensusVersion(),
|
||||
"auth": auth.AppModule{}.ConsensusVersion(),
|
||||
"authz": authzmodule.AppModule{}.ConsensusVersion(),
|
||||
"staking": staking.AppModule{}.ConsensusVersion(),
|
||||
"mint": mint.AppModule{}.ConsensusVersion(),
|
||||
"distribution": distribution.AppModule{}.ConsensusVersion(),
|
||||
"slashing": slashing.AppModule{}.ConsensusVersion(),
|
||||
"gov": gov.AppModule{}.ConsensusVersion(),
|
||||
"group": group.AppModule{}.ConsensusVersion(),
|
||||
"upgrade": upgrade.AppModule{}.ConsensusVersion(),
|
||||
"vesting": vesting.AppModule{}.ConsensusVersion(),
|
||||
"feegrant": feegrantmodule.AppModule{}.ConsensusVersion(),
|
||||
"evidence": evidence.AppModule{}.ConsensusVersion(),
|
||||
"genutil": genutil.AppModule{}.ConsensusVersion(),
|
||||
"protocolpool": protocolpool.AppModule{}.ConsensusVersion(),
|
||||
"epochs": epochs.AppModule{}.ConsensusVersion(),
|
||||
},
|
||||
)
|
||||
if tc.expRunErr {
|
||||
require.EqualError(tt, err, tc.expRunErrMsg, "running migration")
|
||||
} else {
|
||||
require.NoError(tt, err, "running migration")
|
||||
// Make sure bank's migration is called.
|
||||
require.Equal(tt, tc.expCalled, called)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestInitGenesisOnMigration(t *testing.T) {
|
||||
db := coretesting.NewMemDB()
|
||||
app := NewSimApp(log.NewTestLogger(t), db, nil, true, simtestutil.NewAppOptionsWithFlagHome(t.TempDir()))
|
||||
ctx := app.NewContextLegacy(true, cmtproto.Header{Height: app.LastBlockHeight()})
|
||||
|
||||
// Create a mock module. This module will serve as the new module we're
|
||||
// adding during a migration.
|
||||
mockCtrl := gomock.NewController(t)
|
||||
t.Cleanup(mockCtrl.Finish)
|
||||
mockModule := mock.NewMockAppModuleWithAllExtensions(mockCtrl)
|
||||
mockDefaultGenesis := json.RawMessage(`{"key": "value"}`)
|
||||
mockModule.EXPECT().DefaultGenesis().Times(1).Return(mockDefaultGenesis)
|
||||
mockModule.EXPECT().InitGenesis(gomock.Eq(ctx), gomock.Eq(mockDefaultGenesis)).Times(1)
|
||||
mockModule.EXPECT().ConsensusVersion().Times(1).Return(uint64(0))
|
||||
|
||||
app.ModuleManager.Modules["mock"] = mockModule
|
||||
|
||||
// Run migrations only for "mock" module. We exclude it from
|
||||
// the VersionMap to simulate upgrading with a new module.
|
||||
_, err := app.ModuleManager.RunMigrations(ctx, app.Configurator(),
|
||||
appmodule.VersionMap{
|
||||
"bank": bank.AppModule{}.ConsensusVersion(),
|
||||
"auth": auth.AppModule{}.ConsensusVersion(),
|
||||
"authz": authzmodule.AppModule{}.ConsensusVersion(),
|
||||
"staking": staking.AppModule{}.ConsensusVersion(),
|
||||
"mint": mint.AppModule{}.ConsensusVersion(),
|
||||
"distribution": distribution.AppModule{}.ConsensusVersion(),
|
||||
"slashing": slashing.AppModule{}.ConsensusVersion(),
|
||||
"gov": gov.AppModule{}.ConsensusVersion(),
|
||||
"upgrade": upgrade.AppModule{}.ConsensusVersion(),
|
||||
"vesting": vesting.AppModule{}.ConsensusVersion(),
|
||||
"feegrant": feegrantmodule.AppModule{}.ConsensusVersion(),
|
||||
"evidence": evidence.AppModule{}.ConsensusVersion(),
|
||||
"genutil": genutil.AppModule{}.ConsensusVersion(),
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestUpgradeStateOnGenesis(t *testing.T) {
|
||||
db := coretesting.NewMemDB()
|
||||
app := NewSimappWithCustomOptions(t, false, SetupOptions{
|
||||
Logger: log.NewTestLogger(t),
|
||||
DB: db,
|
||||
AppOpts: simtestutil.NewAppOptionsWithFlagHome(t.TempDir()),
|
||||
})
|
||||
|
||||
// make sure the upgrade keeper has version map in state
|
||||
ctx := app.NewContext(false)
|
||||
vm, err := app.UpgradeKeeper.GetModuleVersionMap(ctx)
|
||||
require.NoError(t, err)
|
||||
for v, i := range app.ModuleManager.Modules {
|
||||
if i, ok := i.(appmodule.HasConsensusVersion); ok {
|
||||
require.Equal(t, vm[v], i.ConsensusVersion())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestMergedRegistry tests that fetching the gogo/protov2 merged registry
|
||||
// doesn't fail after loading all file descriptors.
|
||||
func TestMergedRegistry(t *testing.T) {
|
||||
r, err := proto.MergedRegistry()
|
||||
require.NoError(t, err)
|
||||
require.Greater(t, r.NumFiles(), 0)
|
||||
}
|
||||
|
||||
func TestProtoAnnotations(t *testing.T) {
|
||||
r, err := proto.MergedRegistry()
|
||||
require.NoError(t, err)
|
||||
err = msgservice.ValidateProtoAnnotations(r)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
@ -1,39 +0,0 @@
|
||||
//go:build benchmark
|
||||
|
||||
package simapp
|
||||
|
||||
import (
|
||||
runtimev1alpha1 "cosmossdk.io/api/cosmos/app/runtime/v1alpha1"
|
||||
appv1alpha1 "cosmossdk.io/api/cosmos/app/v1alpha1"
|
||||
benchmarkmodulev1 "cosmossdk.io/api/cosmos/benchmark/module/v1"
|
||||
"cosmossdk.io/depinject/appconfig"
|
||||
benchmark "cosmossdk.io/tools/benchmark/module"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// WARNING!
|
||||
// Enabling this module will produce 3M keys in the genesis state for the benchmark module.
|
||||
// Will also enable processing of benchmark transactions which can easily overwhelm the system.
|
||||
appConfig.Modules = append(appConfig.Modules, &appv1alpha1.ModuleConfig{
|
||||
Name: benchmark.ModuleName,
|
||||
Config: appconfig.WrapAny(&benchmarkmodulev1.Module{
|
||||
GenesisParams: &benchmarkmodulev1.GeneratorParams{
|
||||
Seed: 34,
|
||||
BucketCount: 3,
|
||||
GenesisCount: 3_000_000,
|
||||
KeyMean: 64,
|
||||
KeyStdDev: 12,
|
||||
ValueMean: 1024,
|
||||
ValueStdDev: 256,
|
||||
},
|
||||
}),
|
||||
})
|
||||
runtimeConfig := &runtimev1alpha1.Module{}
|
||||
err := appConfig.Modules[0].Config.UnmarshalTo(runtimeConfig)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("benchmark init: failed to unmarshal runtime module config: %w", err))
|
||||
}
|
||||
runtimeConfig.InitGenesis = append(runtimeConfig.InitGenesis, benchmark.ModuleName)
|
||||
appConfig.Modules[0].Config = appconfig.WrapAny(runtimeConfig)
|
||||
}
|
||||
266
simapp/export.go
266
simapp/export.go
@ -1,266 +0,0 @@
|
||||
package simapp
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1"
|
||||
|
||||
"cosmossdk.io/collections"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
slashingtypes "cosmossdk.io/x/slashing/types"
|
||||
"cosmossdk.io/x/staking"
|
||||
stakingtypes "cosmossdk.io/x/staking/types"
|
||||
|
||||
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// ExportAppStateAndValidators exports the state of the application for a genesis
|
||||
// file.
|
||||
func (app *SimApp) ExportAppStateAndValidators(forZeroHeight bool, jailAllowedAddrs, modulesToExport []string) (servertypes.ExportedApp, error) {
|
||||
// as if they could withdraw from the start of the next block
|
||||
ctx := app.NewContextLegacy(true, cmtproto.Header{Height: app.LastBlockHeight()})
|
||||
|
||||
// We export at last height + 1, because that's the height at which
|
||||
// CometBFT will start InitChain.
|
||||
height := app.LastBlockHeight() + 1
|
||||
if forZeroHeight {
|
||||
height = 0
|
||||
app.prepForZeroHeightGenesis(ctx, jailAllowedAddrs)
|
||||
}
|
||||
|
||||
genState, err := app.ModuleManager.ExportGenesisForModules(ctx, modulesToExport)
|
||||
if err != nil {
|
||||
return servertypes.ExportedApp{}, err
|
||||
}
|
||||
|
||||
appState, err := json.MarshalIndent(genState, "", " ")
|
||||
if err != nil {
|
||||
return servertypes.ExportedApp{}, err
|
||||
}
|
||||
|
||||
validators, err := staking.WriteValidators(ctx, app.StakingKeeper)
|
||||
|
||||
return servertypes.ExportedApp{
|
||||
AppState: appState,
|
||||
Validators: validators,
|
||||
Height: height,
|
||||
ConsensusParams: app.BaseApp.GetConsensusParams(ctx),
|
||||
}, err
|
||||
}
|
||||
|
||||
// prepForZeroHeightGenesis prepares for fresh start at zero height
|
||||
// NOTE zero height genesis is a temporary feature which will be deprecated
|
||||
//
|
||||
// in favor of export at a block height
|
||||
func (app *SimApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs []string) {
|
||||
applyAllowedAddrs := false
|
||||
|
||||
// check if there is a allowed address list
|
||||
if len(jailAllowedAddrs) > 0 {
|
||||
applyAllowedAddrs = true
|
||||
}
|
||||
|
||||
allowedAddrsMap := make(map[string]bool)
|
||||
|
||||
for _, addr := range jailAllowedAddrs {
|
||||
_, err := app.InterfaceRegistry().SigningContext().ValidatorAddressCodec().StringToBytes(addr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
allowedAddrsMap[addr] = true
|
||||
}
|
||||
|
||||
/* Handle fee distribution state. */
|
||||
|
||||
// withdraw all validator commission
|
||||
err := app.StakingKeeper.IterateValidators(ctx, func(_ int64, val sdk.ValidatorI) (stop bool) {
|
||||
valBz, err := app.StakingKeeper.ValidatorAddressCodec().StringToBytes(val.GetOperator())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_, _ = app.DistrKeeper.WithdrawValidatorCommission(ctx, valBz)
|
||||
return false
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// withdraw all delegator rewards
|
||||
dels, err := app.StakingKeeper.GetAllDelegations(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, delegation := range dels {
|
||||
valAddr, err := app.InterfaceRegistry().SigningContext().ValidatorAddressCodec().StringToBytes(delegation.ValidatorAddress)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
delAddr, err := app.InterfaceRegistry().SigningContext().AddressCodec().StringToBytes(delegation.DelegatorAddress)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
_, _ = app.DistrKeeper.WithdrawDelegationRewards(ctx, delAddr, valAddr)
|
||||
}
|
||||
|
||||
// clear validator slash events
|
||||
err = app.DistrKeeper.ValidatorSlashEvents.Clear(ctx, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// clear validator historical rewards
|
||||
err = app.DistrKeeper.ValidatorHistoricalRewards.Clear(ctx, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// set context height to zero
|
||||
height := ctx.BlockHeight()
|
||||
ctx = ctx.WithBlockHeight(0)
|
||||
|
||||
// reinitialize all validators
|
||||
err = app.StakingKeeper.IterateValidators(ctx, func(_ int64, val sdk.ValidatorI) (stop bool) {
|
||||
valBz, err := app.StakingKeeper.ValidatorAddressCodec().StringToBytes(val.GetOperator())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// donate any unwithdrawn outstanding reward tokens to the community pool
|
||||
rewards, err := app.DistrKeeper.GetValidatorOutstandingRewardsCoins(ctx, valBz)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
feePool, err := app.DistrKeeper.FeePool.Get(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
feePool.DecimalPool = feePool.DecimalPool.Add(rewards...) // distribution will allocate this to the protocolpool eventually
|
||||
if err := app.DistrKeeper.FeePool.Set(ctx, feePool); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := app.DistrKeeper.Hooks().AfterValidatorCreated(ctx, valBz); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return false
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// reinitialize all delegations
|
||||
for _, del := range dels {
|
||||
valAddr, err := app.InterfaceRegistry().SigningContext().ValidatorAddressCodec().StringToBytes(del.ValidatorAddress)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
delAddr, err := app.InterfaceRegistry().SigningContext().AddressCodec().StringToBytes(del.DelegatorAddress)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := app.DistrKeeper.Hooks().BeforeDelegationCreated(ctx, delAddr, valAddr); err != nil {
|
||||
// never called as BeforeDelegationCreated always returns nil
|
||||
panic(fmt.Errorf("error while incrementing period: %w", err))
|
||||
}
|
||||
|
||||
if err := app.DistrKeeper.Hooks().AfterDelegationModified(ctx, delAddr, valAddr); err != nil {
|
||||
// never called as AfterDelegationModified always returns nil
|
||||
panic(fmt.Errorf("error while creating a new delegation period record: %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
// reset context height
|
||||
ctx = ctx.WithBlockHeight(height)
|
||||
|
||||
/* Handle staking state. */
|
||||
|
||||
// iterate through redelegations, reset creation height
|
||||
err = app.StakingKeeper.IterateRedelegations(ctx, func(_ int64, red stakingtypes.Redelegation) (stop bool) {
|
||||
for i := range red.Entries {
|
||||
red.Entries[i].CreationHeight = 0
|
||||
}
|
||||
err = app.StakingKeeper.SetRedelegation(ctx, red)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return false
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// iterate through unbonding delegations, reset creation height
|
||||
err = app.StakingKeeper.UnbondingDelegations.Walk(
|
||||
ctx,
|
||||
nil,
|
||||
func(_ collections.Pair[[]byte, []byte], ubd stakingtypes.UnbondingDelegation) (stop bool, err error) {
|
||||
for i := range ubd.Entries {
|
||||
ubd.Entries[i].CreationHeight = 0
|
||||
}
|
||||
err = app.StakingKeeper.SetUnbondingDelegation(ctx, ubd)
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
return false, err
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// Iterate through validators by power descending, reset bond heights, and
|
||||
// update bond intra-tx counters.
|
||||
store := ctx.KVStore(app.GetKey(stakingtypes.StoreKey))
|
||||
iter := storetypes.KVStoreReversePrefixIterator(store, stakingtypes.ValidatorsKey)
|
||||
|
||||
for ; iter.Valid(); iter.Next() {
|
||||
addr := sdk.ValAddress(stakingtypes.AddressFromValidatorsKey(iter.Key()))
|
||||
validator, err := app.StakingKeeper.GetValidator(ctx, addr)
|
||||
if err != nil {
|
||||
panic("expected validator, not found")
|
||||
}
|
||||
|
||||
valAddr, err := app.StakingKeeper.ValidatorAddressCodec().BytesToString(addr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
validator.UnbondingHeight = 0
|
||||
if applyAllowedAddrs && !allowedAddrsMap[valAddr] {
|
||||
validator.Jailed = true
|
||||
}
|
||||
|
||||
if err = app.StakingKeeper.SetValidator(ctx, validator); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := iter.Close(); err != nil {
|
||||
app.Logger().Error("error while closing the key-value store reverse prefix iterator: ", err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
/* Handle slashing state. */
|
||||
|
||||
// reset start height on signing infos
|
||||
err = app.SlashingKeeper.ValidatorSigningInfo.Walk(ctx, nil, func(addr sdk.ConsAddress, info slashingtypes.ValidatorSigningInfo) (stop bool, err error) {
|
||||
info.StartHeight = 0
|
||||
err = app.SlashingKeeper.ValidatorSigningInfo.Set(ctx, addr, info)
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
package simapp
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
// GenesisState of the blockchain is represented here as a map of raw json
|
||||
// messages key'd by a identifier string.
|
||||
// The identifier is used to determine which module genesis information belongs
|
||||
// to so it may be appropriately routed during init chain.
|
||||
// Within this application default genesis information is retrieved from
|
||||
// the module manager which populates json from each module
|
||||
// object provided to it during init.
|
||||
type GenesisState map[string]json.RawMessage
|
||||
@ -1,47 +0,0 @@
|
||||
package simapp
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
)
|
||||
|
||||
var _ authtypes.GenesisAccount = (*SimGenesisAccount)(nil)
|
||||
|
||||
// SimGenesisAccount defines a type that implements the GenesisAccount interface
|
||||
// to be used for simulation accounts in the genesis state.
|
||||
type SimGenesisAccount struct {
|
||||
*authtypes.BaseAccount
|
||||
|
||||
// vesting account fields
|
||||
OriginalVesting sdk.Coins `json:"original_vesting" yaml:"original_vesting"` // total vesting coins upon initialization
|
||||
DelegatedFree sdk.Coins `json:"delegated_free" yaml:"delegated_free"` // delegated vested coins at time of delegation
|
||||
DelegatedVesting sdk.Coins `json:"delegated_vesting" yaml:"delegated_vesting"` // delegated vesting coins at time of delegation
|
||||
StartTime int64 `json:"start_time" yaml:"start_time"` // vesting start time (UNIX Epoch time)
|
||||
EndTime int64 `json:"end_time" yaml:"end_time"` // vesting end time (UNIX Epoch time)
|
||||
|
||||
// module account fields
|
||||
ModuleName string `json:"module_name" yaml:"module_name"` // name of the module account
|
||||
ModulePermissions []string `json:"module_permissions" yaml:"module_permissions"` // permissions of module account
|
||||
}
|
||||
|
||||
// Validate checks for errors on the vesting and module account parameters
|
||||
func (sga SimGenesisAccount) Validate() error {
|
||||
if !sga.OriginalVesting.IsZero() {
|
||||
if sga.StartTime >= sga.EndTime {
|
||||
return errors.New("vesting start-time cannot be after end-time")
|
||||
}
|
||||
}
|
||||
|
||||
if sga.ModuleName != "" {
|
||||
ma := authtypes.ModuleAccount{
|
||||
BaseAccount: sga.BaseAccount, Name: sga.ModuleName, Permissions: sga.ModulePermissions,
|
||||
}
|
||||
if err := ma.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return sga.BaseAccount.Validate()
|
||||
}
|
||||
@ -1,88 +0,0 @@
|
||||
package simapp_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cometbft/cometbft/crypto"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"cosmossdk.io/simapp"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
)
|
||||
|
||||
func TestSimGenesisAccountValidate(t *testing.T) {
|
||||
pubkey := secp256k1.GenPrivKey().PubKey()
|
||||
addr := sdk.AccAddress(pubkey.Address())
|
||||
|
||||
vestingStart := time.Now().UTC()
|
||||
|
||||
coins := sdk.NewCoins(sdk.NewInt64Coin("test", 1000))
|
||||
baseAcc := authtypes.NewBaseAccount(addr, pubkey, 0, 0)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
sga simapp.SimGenesisAccount
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
"valid basic account",
|
||||
simapp.SimGenesisAccount{
|
||||
BaseAccount: baseAcc,
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"invalid basic account with mismatching address/pubkey",
|
||||
simapp.SimGenesisAccount{
|
||||
BaseAccount: authtypes.NewBaseAccount(addr, secp256k1.GenPrivKey().PubKey(), 0, 0),
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"valid basic account with module name",
|
||||
simapp.SimGenesisAccount{
|
||||
BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(crypto.AddressHash([]byte("testmod"))), nil, 0, 0),
|
||||
ModuleName: "testmod",
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid basic account with invalid module name/pubkey pair",
|
||||
simapp.SimGenesisAccount{
|
||||
BaseAccount: baseAcc,
|
||||
ModuleName: "testmod",
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"valid basic account with valid vesting attributes",
|
||||
simapp.SimGenesisAccount{
|
||||
BaseAccount: baseAcc,
|
||||
OriginalVesting: coins,
|
||||
StartTime: vestingStart.Unix(),
|
||||
EndTime: vestingStart.Add(1 * time.Hour).Unix(),
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid basic account with invalid vesting end time",
|
||||
simapp.SimGenesisAccount{
|
||||
BaseAccount: baseAcc,
|
||||
OriginalVesting: coins,
|
||||
StartTime: vestingStart.Add(2 * time.Hour).Unix(),
|
||||
EndTime: vestingStart.Add(1 * time.Hour).Unix(),
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
require.Equal(t, tc.wantErr, tc.sga.Validate() != nil)
|
||||
})
|
||||
}
|
||||
}
|
||||
290
simapp/go.mod
290
simapp/go.mod
@ -1,290 +0,0 @@
|
||||
module cosmossdk.io/simapp
|
||||
|
||||
go 1.23.3
|
||||
|
||||
require (
|
||||
cosmossdk.io/api v0.8.0-rc.3
|
||||
cosmossdk.io/client/v2 v2.0.0-beta.6
|
||||
cosmossdk.io/collections v1.0.0-rc.1
|
||||
cosmossdk.io/core v1.0.0-alpha.6
|
||||
cosmossdk.io/core/testing v0.0.1
|
||||
cosmossdk.io/depinject v1.1.0
|
||||
cosmossdk.io/log v1.5.0
|
||||
cosmossdk.io/math v1.4.0
|
||||
cosmossdk.io/store v1.10.0-rc.1
|
||||
cosmossdk.io/tools/confix v0.0.0-20230613133644-0a778132a60f
|
||||
cosmossdk.io/x/accounts v0.0.0-20240913065641-0064ccbce64e
|
||||
cosmossdk.io/x/accounts/defaults/base v0.0.0-00010101000000-000000000000
|
||||
cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5
|
||||
cosmossdk.io/x/accounts/defaults/multisig v0.0.0-00010101000000-000000000000
|
||||
cosmossdk.io/x/authz v0.0.0-00010101000000-000000000000
|
||||
cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91
|
||||
cosmossdk.io/x/circuit v0.0.0-20230613133644-0a778132a60f
|
||||
cosmossdk.io/x/consensus v0.0.0-00010101000000-000000000000
|
||||
cosmossdk.io/x/distribution v0.0.0-20240227221813-a248d05f70f4
|
||||
cosmossdk.io/x/epochs v0.0.0-20240522060652-a1ae4c3e0337
|
||||
cosmossdk.io/x/evidence v0.0.0-20230613133644-0a778132a60f
|
||||
cosmossdk.io/x/feegrant v0.0.0-20230613133644-0a778132a60f
|
||||
cosmossdk.io/x/gov v0.0.0-20231113122742-912390d5fc4a
|
||||
cosmossdk.io/x/group v0.0.0-00010101000000-000000000000
|
||||
cosmossdk.io/x/mint v0.0.0-00010101000000-000000000000
|
||||
cosmossdk.io/x/nft v0.0.0-20230613133644-0a778132a60f
|
||||
cosmossdk.io/x/protocolpool v0.0.0-20230925135524-a1bc045b3190
|
||||
cosmossdk.io/x/slashing v0.0.0-00010101000000-000000000000
|
||||
cosmossdk.io/x/staking v0.0.0-20240226161501-23359a0b6d91
|
||||
cosmossdk.io/x/tx v1.0.0-alpha.3 // indirect
|
||||
cosmossdk.io/x/upgrade v0.0.0-20230613133644-0a778132a60f
|
||||
github.com/cometbft/cometbft v1.0.0
|
||||
github.com/cometbft/cometbft/api v1.0.0
|
||||
// this version is not used as it is always replaced by the latest Cosmos SDK version
|
||||
github.com/cosmos/cosmos-sdk v0.53.0
|
||||
github.com/cosmos/gogoproto v1.7.0
|
||||
github.com/spf13/cast v1.7.1 // indirect
|
||||
github.com/spf13/cobra v1.8.1
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/spf13/viper v1.19.0
|
||||
github.com/stretchr/testify v1.10.0
|
||||
go.uber.org/mock v0.5.0
|
||||
google.golang.org/grpc v1.68.1
|
||||
google.golang.org/protobuf v1.36.0
|
||||
)
|
||||
|
||||
require (
|
||||
cosmossdk.io/indexer/postgres v0.1.0
|
||||
cosmossdk.io/tools/benchmark v0.0.0-00010101000000-000000000000
|
||||
github.com/jackc/pgx/v5 v5.7.1
|
||||
)
|
||||
|
||||
require (
|
||||
buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.36.0-20241120201313-68e42a58b301.1 // indirect
|
||||
buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.36.0-20240130113600-88ef6483f90f.1 // indirect
|
||||
cloud.google.com/go v0.115.1 // indirect
|
||||
cloud.google.com/go/auth v0.8.1 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.5.0 // indirect
|
||||
cloud.google.com/go/iam v1.1.13 // indirect
|
||||
cloud.google.com/go/storage v1.43.0 // indirect
|
||||
cosmossdk.io/errors v1.0.1 // indirect
|
||||
cosmossdk.io/schema v1.0.0 // indirect
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
|
||||
github.com/99designs/keyring v1.2.2 // indirect
|
||||
github.com/DataDog/datadog-go v4.8.3+incompatible // indirect
|
||||
github.com/DataDog/zstd v1.5.5 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.1 // indirect
|
||||
github.com/aws/aws-sdk-go v1.55.5 // indirect
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
|
||||
github.com/bgentry/speakeasy v0.2.0 // indirect
|
||||
github.com/bits-and-blooms/bitset v1.10.0 // indirect
|
||||
github.com/bytedance/sonic v1.12.6 // indirect
|
||||
github.com/bytedance/sonic/loader v0.2.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/chzyer/readline v1.5.1 // indirect
|
||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||
github.com/cockroachdb/apd/v3 v3.2.1 // indirect
|
||||
github.com/cockroachdb/errors v1.11.3 // indirect
|
||||
github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect
|
||||
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
|
||||
github.com/cockroachdb/pebble v1.1.2 // indirect
|
||||
github.com/cockroachdb/redact v1.1.5 // indirect
|
||||
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
|
||||
github.com/cometbft/cometbft-db v1.0.1 // indirect
|
||||
github.com/cosmos/btcutil v1.0.5 // indirect
|
||||
github.com/cosmos/cosmos-db v1.1.1 // indirect
|
||||
github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect
|
||||
github.com/cosmos/go-bip39 v1.0.0 // indirect
|
||||
github.com/cosmos/gogogateway v1.2.0 // indirect
|
||||
github.com/cosmos/iavl v1.3.4 // indirect
|
||||
github.com/cosmos/ics23/go v0.11.0 // indirect
|
||||
github.com/cosmos/ledger-cosmos-go v0.14.0 // indirect
|
||||
github.com/creachadair/atomicfile v0.3.6 // indirect
|
||||
github.com/creachadair/tomledit v0.0.26 // indirect
|
||||
github.com/danieljoos/wincred v1.2.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
|
||||
github.com/dgraph-io/badger/v4 v4.5.0 // indirect
|
||||
github.com/dgraph-io/ristretto/v2 v2.0.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/dvsekhvalnov/jose2go v1.6.0 // indirect
|
||||
github.com/emicklei/dot v1.6.2 // indirect
|
||||
github.com/fatih/color v1.18.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.8.0 // indirect
|
||||
github.com/getsentry/sentry-go v0.27.0 // indirect
|
||||
github.com/go-kit/log v0.2.1 // indirect
|
||||
github.com/go-logfmt/logfmt v0.6.0 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
|
||||
github.com/gogo/googleapis v1.4.1 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/btree v1.1.3 // indirect
|
||||
github.com/google/flatbuffers v24.3.25+incompatible // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/orderedcode v0.0.1 // indirect
|
||||
github.com/google/s2a-go v0.1.8 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.13.0 // indirect
|
||||
github.com/gorilla/handlers v1.5.2 // indirect
|
||||
github.com/gorilla/mux v1.8.1 // indirect
|
||||
github.com/gorilla/websocket v1.5.3 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
|
||||
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-getter v1.7.6 // indirect
|
||||
github.com/hashicorp/go-hclog v1.6.3 // indirect
|
||||
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
|
||||
github.com/hashicorp/go-metrics v0.5.3 // indirect
|
||||
github.com/hashicorp/go-plugin v1.6.2 // indirect
|
||||
github.com/hashicorp/go-safetemp v1.0.0 // indirect
|
||||
github.com/hashicorp/go-version v1.7.0 // indirect
|
||||
github.com/hashicorp/golang-lru v1.0.2 // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/hashicorp/yamux v0.1.2 // indirect
|
||||
github.com/hdevalence/ed25519consensus v0.2.0 // indirect
|
||||
github.com/huandu/skiplist v1.2.1 // indirect
|
||||
github.com/iancoleman/strcase v0.3.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/jmhodges/levigo v1.0.0 // indirect
|
||||
github.com/klauspost/compress v1.17.11 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/lib/pq v1.10.9 // indirect
|
||||
github.com/linxGnu/grocksdb v1.9.3 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
github.com/magiconair/properties v1.8.9 // indirect
|
||||
github.com/manifoldco/promptui v0.9.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.14 // indirect
|
||||
github.com/mdp/qrterminal/v3 v3.2.0 // indirect
|
||||
github.com/minio/highwayhash v1.0.3 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/mtibben/percent v0.2.1 // indirect
|
||||
github.com/muesli/termenv v0.15.2 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a // indirect
|
||||
github.com/oklog/run v1.1.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||
github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_golang v1.20.5 // indirect
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.61.0 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
||||
github.com/rs/cors v1.11.1 // indirect
|
||||
github.com/rs/zerolog v1.33.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/sasha-s/go-deadlock v0.3.5 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spf13/afero v1.11.0 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/supranational/blst v0.3.13 // indirect
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect
|
||||
github.com/tendermint/go-amino v0.16.0 // indirect
|
||||
github.com/tidwall/btree v1.7.0 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ulikunitz/xz v0.5.12 // indirect
|
||||
github.com/zondax/hid v0.9.2 // indirect
|
||||
github.com/zondax/ledger-go v0.14.3 // indirect
|
||||
gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b // indirect
|
||||
gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 // indirect
|
||||
go.etcd.io/bbolt v1.4.0-alpha.0.0.20240404170359-43604f3112c5 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect
|
||||
go.opentelemetry.io/otel v1.28.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.28.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.28.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/arch v0.12.0 // indirect
|
||||
golang.org/x/crypto v0.31.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect
|
||||
golang.org/x/mod v0.22.0 // indirect
|
||||
golang.org/x/net v0.32.0 // indirect
|
||||
golang.org/x/oauth2 v0.24.0 // indirect
|
||||
golang.org/x/sync v0.10.0 // indirect
|
||||
golang.org/x/sys v0.28.0 // indirect
|
||||
golang.org/x/term v0.27.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
golang.org/x/time v0.6.0 // indirect
|
||||
golang.org/x/tools v0.27.0 // indirect
|
||||
google.golang.org/api v0.192.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20240814211410-ddb44dafa142 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
gotest.tools/v3 v3.5.1 // indirect
|
||||
pgregory.net/rapid v1.1.0 // indirect
|
||||
rsc.io/qr v0.2.0 // indirect
|
||||
sigs.k8s.io/yaml v1.4.0 // indirect
|
||||
)
|
||||
|
||||
// Here are the short-lived replace from the SimApp
|
||||
// Replace here are pending PRs, or version to be tagged
|
||||
// replace (
|
||||
// <temporary replace>
|
||||
// )
|
||||
|
||||
// SimApp on main always tests the latest extracted SDK modules importing the sdk
|
||||
replace (
|
||||
cosmossdk.io/client/v2 => ../client/v2
|
||||
cosmossdk.io/tools/benchmark => ../tools/benchmark
|
||||
cosmossdk.io/tools/confix => ../tools/confix
|
||||
cosmossdk.io/x/accounts => ../x/accounts
|
||||
cosmossdk.io/x/accounts/defaults/base => ../x/accounts/defaults/base
|
||||
cosmossdk.io/x/accounts/defaults/lockup => ../x/accounts/defaults/lockup
|
||||
cosmossdk.io/x/accounts/defaults/multisig => ../x/accounts/defaults/multisig
|
||||
cosmossdk.io/x/authz => ../x/authz
|
||||
cosmossdk.io/x/bank => ../x/bank
|
||||
cosmossdk.io/x/circuit => ../x/circuit
|
||||
cosmossdk.io/x/consensus => ../x/consensus
|
||||
cosmossdk.io/x/distribution => ../x/distribution
|
||||
cosmossdk.io/x/epochs => ../x/epochs
|
||||
cosmossdk.io/x/evidence => ../x/evidence
|
||||
cosmossdk.io/x/feegrant => ../x/feegrant
|
||||
cosmossdk.io/x/gov => ../x/gov
|
||||
cosmossdk.io/x/group => ../x/group
|
||||
cosmossdk.io/x/mint => ../x/mint
|
||||
cosmossdk.io/x/nft => ../x/nft
|
||||
cosmossdk.io/x/params => ../x/params
|
||||
cosmossdk.io/x/protocolpool => ../x/protocolpool
|
||||
cosmossdk.io/x/slashing => ../x/slashing
|
||||
cosmossdk.io/x/staking => ../x/staking
|
||||
cosmossdk.io/x/upgrade => ../x/upgrade
|
||||
)
|
||||
|
||||
// Below are the long-lived replace of the SimApp
|
||||
replace (
|
||||
// use cosmos fork of keyring
|
||||
github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0
|
||||
// Simapp always use the latest version of the cosmos-sdk
|
||||
github.com/cosmos/cosmos-sdk => ../.
|
||||
// Fix upstream GHSA-h395-qcrw-5vmq and GHSA-3vp4-m3rf-835h vulnerabilities.
|
||||
// TODO Remove it: https://github.com/cosmos/cosmos-sdk/issues/10409
|
||||
github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.9.1
|
||||
// replace broken goleveldb
|
||||
github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
|
||||
)
|
||||
1470
simapp/go.sum
1470
simapp/go.sum
File diff suppressed because it is too large
Load Diff
@ -1,139 +0,0 @@
|
||||
package simapp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
"cosmossdk.io/core/appmodule"
|
||||
"cosmossdk.io/core/event"
|
||||
"cosmossdk.io/math"
|
||||
banktypes "cosmossdk.io/x/bank/types"
|
||||
minttypes "cosmossdk.io/x/mint/types"
|
||||
stakingtypes "cosmossdk.io/x/staking/types"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
)
|
||||
|
||||
type MintBankKeeper interface {
|
||||
MintCoins(ctx context.Context, moduleName string, coins sdk.Coins) error
|
||||
SendCoinsFromModuleToModule(ctx context.Context, senderModule, recipientModule string, amt sdk.Coins) error
|
||||
}
|
||||
|
||||
// ProvideExampleMintFn returns the function used in x/mint's endblocker to mint new tokens.
|
||||
// Note that this function can not have the mint keeper as a parameter because it would create a cyclic dependency.
|
||||
func ProvideExampleMintFn(bankKeeper MintBankKeeper) minttypes.MintFn {
|
||||
return func(ctx context.Context, env appmodule.Environment, minter *minttypes.Minter, epochID string, epochNumber int64) error {
|
||||
// in this example we ignore epochNumber as we don't care what epoch we are in, we just assume we are being called every minute.
|
||||
if epochID != "minute" {
|
||||
return nil
|
||||
}
|
||||
|
||||
resp, err := env.QueryRouterService.Invoke(ctx, &stakingtypes.QueryParamsRequest{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stakingParams, ok := resp.(*stakingtypes.QueryParamsResponse)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected response type: %T", resp)
|
||||
}
|
||||
|
||||
resp, err = env.QueryRouterService.Invoke(ctx, &banktypes.QuerySupplyOfRequest{Denom: stakingParams.Params.BondDenom})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bankSupply, ok := resp.(*banktypes.QuerySupplyOfResponse)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected response type: %T", resp)
|
||||
}
|
||||
|
||||
stakingTokenSupply := bankSupply.Amount
|
||||
|
||||
resp, err = env.QueryRouterService.Invoke(ctx, &minttypes.QueryParamsRequest{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mintParams, ok := resp.(*minttypes.QueryParamsResponse)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected response type: %T", resp)
|
||||
}
|
||||
|
||||
resp, err = env.QueryRouterService.Invoke(ctx, &stakingtypes.QueryPoolRequest{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
stakingPool, ok := resp.(*stakingtypes.QueryPoolResponse)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected response type: %T", resp)
|
||||
}
|
||||
|
||||
// bondedRatio
|
||||
bondedRatio := math.LegacyNewDecFromInt(stakingPool.Pool.BondedTokens).QuoInt(stakingTokenSupply.Amount)
|
||||
minter.Inflation = minter.NextInflationRate(mintParams.Params, bondedRatio)
|
||||
minter.AnnualProvisions = minter.NextAnnualProvisions(mintParams.Params, stakingTokenSupply.Amount)
|
||||
|
||||
// to get a more accurate amount of tokens minted, we get, and later store, last minting time.
|
||||
// if this is the first time minting, we initialize the minter.Data with the current time - 60s
|
||||
// to mint tokens at the beginning. Note: this is a custom behavior to avoid breaking tests.
|
||||
if minter.Data == nil {
|
||||
minter.Data = make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(minter.Data, (uint64)(env.HeaderService.HeaderInfo(ctx).Time.UnixMilli()-60000))
|
||||
}
|
||||
|
||||
lastMint := binary.BigEndian.Uint64(minter.Data)
|
||||
binary.BigEndian.PutUint64(minter.Data, (uint64)(env.HeaderService.HeaderInfo(ctx).Time.UnixMilli()))
|
||||
|
||||
// calculate the amount of tokens to mint, based on the time since the last mint.
|
||||
msSinceLastMint := env.HeaderService.HeaderInfo(ctx).Time.UnixMilli() - (int64)(lastMint)
|
||||
provisionAmt := minter.AnnualProvisions.QuoInt64(31536000000).MulInt64(msSinceLastMint) // 31536000000 = milliseconds in a year
|
||||
mintedCoin := sdk.NewCoin(mintParams.Params.MintDenom, provisionAmt.TruncateInt())
|
||||
maxSupply := mintParams.Params.MaxSupply
|
||||
totalSupply := stakingTokenSupply.Amount
|
||||
|
||||
if !maxSupply.IsZero() {
|
||||
// supply is not infinite, check the amount to mint
|
||||
remainingSupply := maxSupply.Sub(totalSupply)
|
||||
|
||||
if remainingSupply.LTE(math.ZeroInt()) {
|
||||
// max supply reached, no new tokens will be minted
|
||||
// also handles the case where totalSupply > maxSupply
|
||||
return nil
|
||||
}
|
||||
|
||||
// if the amount to mint is greater than the remaining supply, mint the remaining supply
|
||||
if mintedCoin.Amount.GT(remainingSupply) {
|
||||
mintedCoin.Amount = remainingSupply
|
||||
}
|
||||
}
|
||||
|
||||
if mintedCoin.Amount.IsZero() {
|
||||
// skip as no coins need to be minted
|
||||
return nil
|
||||
}
|
||||
|
||||
mintedCoins := sdk.NewCoins(mintedCoin)
|
||||
if err := bankKeeper.MintCoins(ctx, minttypes.ModuleName, mintedCoins); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Example of custom send while minting
|
||||
// Send some tokens to a "team account"
|
||||
// if err = bankKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, ... ); err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
if err = bankKeeper.SendCoinsFromModuleToModule(ctx, minttypes.ModuleName, authtypes.FeeCollectorName, mintedCoins); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return env.EventService.EventManager(ctx).EmitKV(
|
||||
minttypes.EventTypeMint,
|
||||
event.NewAttribute(minttypes.AttributeKeyBondedRatio, bondedRatio.String()),
|
||||
event.NewAttribute(minttypes.AttributeKeyInflation, minter.Inflation.String()),
|
||||
event.NewAttribute(minttypes.AttributeKeyAnnualProvisions, minter.AnnualProvisions.String()),
|
||||
event.NewAttribute(sdk.AttributeKeyAmount, mintedCoin.Amount.String()),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
/*
|
||||
Package params defines the simulation parameters in the simapp.
|
||||
|
||||
It contains the default weights used for each transaction used on the module's
|
||||
simulation. These weights define the chance for a transaction to be simulated at
|
||||
any given operation.
|
||||
|
||||
You can replace the default values for the weights by providing a params.json
|
||||
file with the weights defined for each of the transaction operations:
|
||||
|
||||
{
|
||||
"op_weight_msg_send": 60,
|
||||
"op_weight_msg_delegate": 100,
|
||||
}
|
||||
|
||||
In the example above, the `MsgSend` has 60% chance to be simulated, while the
|
||||
`MsgDelegate` will always be simulated.
|
||||
*/
|
||||
package params
|
||||
@ -1,16 +0,0 @@
|
||||
package params
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||
)
|
||||
|
||||
// EncodingConfig specifies the concrete encoding types to use for a given app.
|
||||
// This is provided for compatibility between protobuf and amino implementations.
|
||||
type EncodingConfig struct {
|
||||
InterfaceRegistry types.InterfaceRegistry
|
||||
Codec codec.Codec
|
||||
TxConfig client.TxConfig
|
||||
Amino *codec.LegacyAmino
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
//go:build sims
|
||||
|
||||
package simapp
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/simsx"
|
||||
"testing"
|
||||
|
||||
simcli "github.com/cosmos/cosmos-sdk/x/simulation/client/cli"
|
||||
)
|
||||
|
||||
// Profile with:
|
||||
// /usr/local/go/bin/go test -benchmem -run=^$ cosmossdk.io/simapp -bench ^BenchmarkFullAppSimulation$ -Commit=true -cpuprofile cpu.out
|
||||
func BenchmarkFullAppSimulation(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
|
||||
config := simcli.NewConfigFromFlags()
|
||||
config.ChainID = simsx.SimAppChainID
|
||||
|
||||
simsx.RunWithSeed(b, config, NewSimApp, setupStateFactory, 1, nil)
|
||||
}
|
||||
@ -1,286 +0,0 @@
|
||||
//go:build sims
|
||||
|
||||
package simapp
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"io"
|
||||
"math/rand"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
abci "github.com/cometbft/cometbft/api/cometbft/abci/v1"
|
||||
cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
corestore "cosmossdk.io/core/store"
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/store"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
authzkeeper "cosmossdk.io/x/authz/keeper"
|
||||
"cosmossdk.io/x/feegrant"
|
||||
slashingtypes "cosmossdk.io/x/slashing/types"
|
||||
stakingtypes "cosmossdk.io/x/staking/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
||||
"github.com/cosmos/cosmos-sdk/simsx"
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
|
||||
"github.com/cosmos/cosmos-sdk/x/simulation"
|
||||
simcli "github.com/cosmos/cosmos-sdk/x/simulation/client/cli"
|
||||
)
|
||||
|
||||
// SimAppChainID hardcoded chainID for simulation
|
||||
|
||||
var FlagEnableStreamingValue bool
|
||||
|
||||
// Get flags every time the simulator is run
|
||||
func init() {
|
||||
simcli.GetSimulatorFlags()
|
||||
flag.BoolVar(&FlagEnableStreamingValue, "EnableStreaming", false, "Enable streaming service")
|
||||
}
|
||||
|
||||
// interBlockCacheOpt returns a BaseApp option function that sets the persistent
|
||||
// inter-block write-through cache.
|
||||
func interBlockCacheOpt() func(*baseapp.BaseApp) {
|
||||
return baseapp.SetInterBlockCache(store.NewCommitKVStoreCacheManager())
|
||||
}
|
||||
|
||||
func TestFullAppSimulation(t *testing.T) {
|
||||
simsx.Run(t, NewSimApp, setupStateFactory)
|
||||
}
|
||||
|
||||
func setupStateFactory(app *SimApp) simsx.SimStateFactory {
|
||||
blockedAddre, _ := BlockedAddresses(app.interfaceRegistry.SigningContext().AddressCodec())
|
||||
return simsx.SimStateFactory{
|
||||
Codec: app.AppCodec(),
|
||||
AppStateFn: simtestutil.AppStateFn(app.AppCodec(), app.AuthKeeper.AddressCodec(), app.StakingKeeper.ValidatorAddressCodec(), app.SimulationManager().Modules, app.DefaultGenesis()),
|
||||
BlockedAddr: blockedAddre,
|
||||
AccountSource: app.AuthKeeper,
|
||||
BalanceSource: app.BankKeeper,
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
exportAllModules []string
|
||||
exportWithValidatorSet []string
|
||||
)
|
||||
|
||||
func TestAppImportExport(t *testing.T) {
|
||||
simsx.Run(t, NewSimApp, setupStateFactory, func(t testing.TB, ti simsx.TestInstance[*SimApp], _ []simtypes.Account) {
|
||||
app := ti.App
|
||||
t.Log("exporting genesis...\n")
|
||||
exported, err := app.ExportAppStateAndValidators(false, exportWithValidatorSet, exportAllModules)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Log("importing genesis...\n")
|
||||
newTestInstance := simsx.NewSimulationAppInstance(t, ti.Cfg, NewSimApp)
|
||||
newApp := newTestInstance.App
|
||||
var genesisState GenesisState
|
||||
require.NoError(t, json.Unmarshal(exported.AppState, &genesisState))
|
||||
ctxB := newApp.NewContextLegacy(true, cmtproto.Header{Height: app.LastBlockHeight()})
|
||||
_, err = newApp.ModuleManager.InitGenesis(ctxB, genesisState)
|
||||
if IsEmptyValidatorSetErr(err) {
|
||||
t.Skip("Skipping simulation as all validators have been unbonded")
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
err = newApp.StoreConsensusParams(ctxB, exported.ConsensusParams)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Log("comparing stores...")
|
||||
// skip certain prefixes
|
||||
skipPrefixes := map[string][][]byte{
|
||||
stakingtypes.StoreKey: {
|
||||
stakingtypes.UnbondingQueueKey, stakingtypes.RedelegationQueueKey, stakingtypes.ValidatorQueueKey,
|
||||
},
|
||||
authzkeeper.StoreKey: {authzkeeper.GrantQueuePrefix},
|
||||
feegrant.StoreKey: {feegrant.FeeAllowanceQueueKeyPrefix},
|
||||
slashingtypes.StoreKey: {slashingtypes.ValidatorMissedBlockBitmapKeyPrefix},
|
||||
}
|
||||
AssertEqualStores(t, app, newApp, app.SimulationManager().StoreDecoders, skipPrefixes)
|
||||
})
|
||||
}
|
||||
|
||||
// Scenario:
|
||||
//
|
||||
// Start a fresh node and run n blocks, export state
|
||||
// set up a new node instance, Init chain from exported genesis
|
||||
// run new instance for n blocks
|
||||
func TestAppSimulationAfterImport(t *testing.T) {
|
||||
simsx.Run(t, NewSimApp, setupStateFactory, func(t testing.TB, ti simsx.TestInstance[*SimApp], accs []simtypes.Account) {
|
||||
app := ti.App
|
||||
t.Log("exporting genesis...\n")
|
||||
exported, err := app.ExportAppStateAndValidators(false, exportWithValidatorSet, exportAllModules)
|
||||
require.NoError(t, err)
|
||||
|
||||
importGenesisStateFactory := func(app *SimApp) simsx.SimStateFactory {
|
||||
return simsx.SimStateFactory{
|
||||
Codec: app.AppCodec(),
|
||||
AppStateFn: func(r *rand.Rand, _ []simtypes.Account, config simtypes.Config) (json.RawMessage, []simtypes.Account, string, time.Time) {
|
||||
t.Log("importing genesis...\n")
|
||||
genesisTimestamp := time.Unix(config.GenesisTime, 0)
|
||||
|
||||
_, err = app.InitChain(&abci.InitChainRequest{
|
||||
AppStateBytes: exported.AppState,
|
||||
ChainId: simsx.SimAppChainID,
|
||||
InitialHeight: exported.Height,
|
||||
Time: genesisTimestamp,
|
||||
})
|
||||
if IsEmptyValidatorSetErr(err) {
|
||||
t.Skip("Skipping simulation as all validators have been unbonded")
|
||||
return nil, nil, "", time.Time{}
|
||||
}
|
||||
require.NoError(t, err)
|
||||
// use accounts from initial run
|
||||
return exported.AppState, accs, config.ChainID, genesisTimestamp
|
||||
},
|
||||
BlockedAddr: must(BlockedAddresses(app.AuthKeeper.AddressCodec())),
|
||||
AccountSource: app.AuthKeeper,
|
||||
BalanceSource: app.BankKeeper,
|
||||
}
|
||||
}
|
||||
ti.Cfg.InitialBlockHeight = int(exported.Height)
|
||||
simsx.RunWithSeed(t, ti.Cfg, NewSimApp, importGenesisStateFactory, ti.Cfg.Seed, ti.Cfg.FuzzSeed)
|
||||
})
|
||||
}
|
||||
|
||||
func IsEmptyValidatorSetErr(err error) bool {
|
||||
return err != nil && strings.Contains(err.Error(), "validator set is empty after InitGenesis")
|
||||
}
|
||||
|
||||
func TestAppStateDeterminism(t *testing.T) {
|
||||
const numTimesToRunPerSeed = 3
|
||||
var seeds []int64
|
||||
if s := simcli.NewConfigFromFlags().Seed; s != simcli.DefaultSeedValue {
|
||||
// We will be overriding the random seed and just run a single simulation on the provided seed value
|
||||
for j := 0; j < numTimesToRunPerSeed; j++ { // multiple rounds
|
||||
seeds = append(seeds, s)
|
||||
}
|
||||
} else {
|
||||
// setup with 3 random seeds
|
||||
for i := 0; i < 3; i++ {
|
||||
seed := rand.Int63()
|
||||
for j := 0; j < numTimesToRunPerSeed; j++ { // multiple rounds
|
||||
seeds = append(seeds, seed)
|
||||
}
|
||||
}
|
||||
}
|
||||
// overwrite default app config
|
||||
interBlockCachingAppFactory := func(logger log.Logger, db corestore.KVStoreWithBatch, traceStore io.Writer, loadLatest bool, appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp)) *SimApp {
|
||||
if FlagEnableStreamingValue {
|
||||
m := map[string]any{
|
||||
"streaming.abci.keys": []string{"*"},
|
||||
"streaming.abci.plugin": "abci_v1",
|
||||
"streaming.abci.stop-node-on-err": true,
|
||||
}
|
||||
others := appOpts
|
||||
appOpts = simsx.AppOptionsFn(func(k string) any {
|
||||
if v, ok := m[k]; ok {
|
||||
return v
|
||||
}
|
||||
return others.Get(k)
|
||||
})
|
||||
}
|
||||
return NewSimApp(logger, db, nil, true, appOpts, append(baseAppOptions, interBlockCacheOpt())...)
|
||||
}
|
||||
var mx sync.Mutex
|
||||
appHashResults := make(map[int64][][]byte)
|
||||
appSimLogger := make(map[int64][]simulation.LogWriter)
|
||||
captureAndCheckHash := func(t testing.TB, ti simsx.TestInstance[*SimApp], _ []simtypes.Account) {
|
||||
seed, appHash := ti.Cfg.Seed, ti.App.LastCommitID().Hash
|
||||
mx.Lock()
|
||||
otherHashes, execWriters := appHashResults[seed], appSimLogger[seed]
|
||||
if len(otherHashes) < numTimesToRunPerSeed-1 {
|
||||
appHashResults[seed], appSimLogger[seed] = append(otherHashes, appHash), append(execWriters, ti.ExecLogWriter)
|
||||
} else { // cleanup
|
||||
delete(appHashResults, seed)
|
||||
delete(appSimLogger, seed)
|
||||
}
|
||||
mx.Unlock()
|
||||
|
||||
var failNow bool
|
||||
// and check that all app hashes per seed are equal for each iteration
|
||||
for i := 0; i < len(otherHashes); i++ {
|
||||
if !assert.Equal(t, otherHashes[i], appHash) {
|
||||
execWriters[i].PrintLogs()
|
||||
failNow = true
|
||||
}
|
||||
}
|
||||
if failNow {
|
||||
ti.ExecLogWriter.PrintLogs()
|
||||
t.Fatalf("non-determinism in seed %d", seed)
|
||||
}
|
||||
}
|
||||
// run simulations
|
||||
simsx.RunWithSeeds(t, interBlockCachingAppFactory, setupStateFactory, seeds, []byte{}, captureAndCheckHash)
|
||||
}
|
||||
|
||||
type ComparableStoreApp interface {
|
||||
LastBlockHeight() int64
|
||||
NewContextLegacy(isCheckTx bool, header cmtproto.Header) sdk.Context
|
||||
GetKey(storeKey string) *storetypes.KVStoreKey
|
||||
GetStoreKeys() []storetypes.StoreKey
|
||||
}
|
||||
|
||||
func AssertEqualStores(t testing.TB, app, newApp ComparableStoreApp, storeDecoders simtypes.StoreDecoderRegistry, skipPrefixes map[string][][]byte) {
|
||||
ctxA := app.NewContextLegacy(true, cmtproto.Header{Height: app.LastBlockHeight()})
|
||||
ctxB := newApp.NewContextLegacy(true, cmtproto.Header{Height: app.LastBlockHeight()})
|
||||
|
||||
storeKeys := app.GetStoreKeys()
|
||||
require.NotEmpty(t, storeKeys)
|
||||
|
||||
for _, appKeyA := range storeKeys {
|
||||
// only compare kvstores
|
||||
if _, ok := appKeyA.(*storetypes.KVStoreKey); !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
keyName := appKeyA.Name()
|
||||
appKeyB := newApp.GetKey(keyName)
|
||||
|
||||
storeA := ctxA.KVStore(appKeyA)
|
||||
storeB := ctxB.KVStore(appKeyB)
|
||||
|
||||
failedKVAs, failedKVBs := simtestutil.DiffKVStores(storeA, storeB, skipPrefixes[keyName])
|
||||
require.Equal(t, len(failedKVAs), len(failedKVBs), "unequal sets of key-values to compare %s, key stores %s and %s", keyName, appKeyA, appKeyB)
|
||||
|
||||
t.Logf("compared %d different key/value pairs between %s and %s\n", len(failedKVAs), appKeyA, appKeyB)
|
||||
if !assert.Equal(t, 0, len(failedKVAs), simtestutil.GetSimulationLog(keyName, storeDecoders, failedKVAs, failedKVBs)) {
|
||||
for _, v := range failedKVAs {
|
||||
t.Logf("store mismatch: %q\n", v)
|
||||
}
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func FuzzFullAppSimulation(f *testing.F) {
|
||||
f.Fuzz(func(t *testing.T, rawSeed []byte) {
|
||||
if len(rawSeed) < 8 {
|
||||
t.Skip()
|
||||
return
|
||||
}
|
||||
simsx.RunWithSeeds(
|
||||
t,
|
||||
NewSimApp,
|
||||
setupStateFactory,
|
||||
[]int64{int64(binary.BigEndian.Uint64(rawSeed))},
|
||||
rawSeed[8:],
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
func must[T any](r T, err error) T {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return r
|
||||
}
|
||||
@ -1,162 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"cosmossdk.io/client/v2/offchain"
|
||||
corestore "cosmossdk.io/core/store"
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/simapp"
|
||||
confixcmd "cosmossdk.io/tools/confix/cmd"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/debug"
|
||||
"github.com/cosmos/cosmos-sdk/client/keys"
|
||||
"github.com/cosmos/cosmos-sdk/client/pruning"
|
||||
"github.com/cosmos/cosmos-sdk/client/rpc"
|
||||
"github.com/cosmos/cosmos-sdk/client/snapshot"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil"
|
||||
genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
|
||||
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
|
||||
)
|
||||
|
||||
func initRootCmd(
|
||||
rootCmd *cobra.Command,
|
||||
moduleManager *module.Manager,
|
||||
) {
|
||||
cfg := sdk.GetConfig()
|
||||
cfg.Seal()
|
||||
|
||||
rootCmd.AddCommand(
|
||||
genutilcli.InitCmd(moduleManager),
|
||||
NewTestnetCmd(moduleManager),
|
||||
debug.Cmd(),
|
||||
confixcmd.ConfigCommand(),
|
||||
pruning.Cmd(newApp),
|
||||
snapshot.Cmd(newApp),
|
||||
)
|
||||
|
||||
server.AddCommands(rootCmd, newApp, server.StartCmdOptions[servertypes.Application]{})
|
||||
|
||||
// add keybase, auxiliary RPC, query, genesis, and tx child commands
|
||||
rootCmd.AddCommand(
|
||||
server.StatusCommand(),
|
||||
genesisCommand(moduleManager, appExport),
|
||||
queryCommand(),
|
||||
txCommand(),
|
||||
keys.Commands(),
|
||||
offchain.OffChain(),
|
||||
)
|
||||
}
|
||||
|
||||
// genesisCommand builds genesis-related `simd genesis` command. Users may provide application specific commands as a parameter
|
||||
func genesisCommand(moduleManager *module.Manager, appExport servertypes.AppExporter, cmds ...*cobra.Command) *cobra.Command {
|
||||
cmd := genutilcli.Commands(moduleManager.Modules[genutiltypes.ModuleName].(genutil.AppModule), moduleManager, appExport)
|
||||
for _, subCmd := range cmds {
|
||||
cmd.AddCommand(subCmd)
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func queryCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "query",
|
||||
Aliases: []string{"q"},
|
||||
Short: "Querying subcommands",
|
||||
DisableFlagParsing: false,
|
||||
SuggestionsMinimumDistance: 2,
|
||||
RunE: client.ValidateCmd,
|
||||
}
|
||||
|
||||
cmd.AddCommand(
|
||||
rpc.WaitTxCmd(),
|
||||
server.QueryBlockCmd(),
|
||||
authcmd.QueryTxsByEventsCmd(),
|
||||
server.QueryBlocksCmd(),
|
||||
authcmd.QueryTxCmd(),
|
||||
server.QueryBlockResultsCmd(),
|
||||
)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func txCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "tx",
|
||||
Short: "Transactions subcommands",
|
||||
DisableFlagParsing: false,
|
||||
SuggestionsMinimumDistance: 2,
|
||||
RunE: client.ValidateCmd,
|
||||
}
|
||||
|
||||
cmd.AddCommand(
|
||||
authcmd.GetSignCommand(),
|
||||
authcmd.GetSignBatchCommand(),
|
||||
authcmd.GetMultiSignCommand(),
|
||||
authcmd.GetMultiSignBatchCmd(),
|
||||
authcmd.GetValidateSignaturesCommand(),
|
||||
authcmd.GetBroadcastCommand(),
|
||||
authcmd.GetEncodeCommand(),
|
||||
authcmd.GetDecodeCommand(),
|
||||
authcmd.GetSimulateCmd(),
|
||||
)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// newApp creates the application
|
||||
func newApp(
|
||||
logger log.Logger,
|
||||
db corestore.KVStoreWithBatch,
|
||||
traceStore io.Writer,
|
||||
appOpts servertypes.AppOptions,
|
||||
) servertypes.Application {
|
||||
baseappOptions := server.DefaultBaseappOptions(appOpts)
|
||||
return simapp.NewSimApp(
|
||||
logger, db, traceStore, true,
|
||||
appOpts,
|
||||
baseappOptions...,
|
||||
)
|
||||
}
|
||||
|
||||
// appExport creates a new simapp (optionally at a given height) and exports state.
|
||||
func appExport(
|
||||
logger log.Logger,
|
||||
db corestore.KVStoreWithBatch,
|
||||
traceStore io.Writer,
|
||||
height int64,
|
||||
forZeroHeight bool,
|
||||
jailAllowedAddrs []string,
|
||||
appOpts servertypes.AppOptions,
|
||||
modulesToExport []string,
|
||||
) (servertypes.ExportedApp, error) {
|
||||
viperAppOpts, ok := appOpts.(*viper.Viper)
|
||||
if !ok {
|
||||
return servertypes.ExportedApp{}, errors.New("appOpts is not viper.Viper")
|
||||
}
|
||||
|
||||
// overwrite the FlagInvCheckPeriod
|
||||
viperAppOpts.Set(server.FlagInvCheckPeriod, 1)
|
||||
|
||||
var simApp *simapp.SimApp
|
||||
if height != -1 {
|
||||
simApp = simapp.NewSimApp(logger, db, traceStore, false, viperAppOpts)
|
||||
|
||||
if err := simApp.LoadHeight(height); err != nil {
|
||||
return servertypes.ExportedApp{}, err
|
||||
}
|
||||
} else {
|
||||
simApp = simapp.NewSimApp(logger, db, traceStore, true, viperAppOpts)
|
||||
}
|
||||
|
||||
return simApp.ExportAppStateAndValidators(forZeroHeight, jailAllowedAddrs, modulesToExport)
|
||||
}
|
||||
@ -1,128 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
cmtcfg "github.com/cometbft/cometbft/config"
|
||||
|
||||
clientconfig "github.com/cosmos/cosmos-sdk/client/config"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
serverconfig "github.com/cosmos/cosmos-sdk/server/config"
|
||||
)
|
||||
|
||||
// initCometBFTConfig helps to override default CometBFT Config values.
|
||||
// return cmtcfg.DefaultConfig if no custom configuration is required for the application.
|
||||
func initCometBFTConfig() *cmtcfg.Config {
|
||||
cfg := cmtcfg.DefaultConfig()
|
||||
|
||||
// display only error logs by default except for p2p and state
|
||||
cfg.LogLevel = "*:error,p2p:info,state:info"
|
||||
|
||||
// use previous db backend
|
||||
cfg.DBBackend = "goleveldb"
|
||||
|
||||
// these values put a higher strain on node memory
|
||||
// cfg.P2P.MaxNumInboundPeers = 100
|
||||
// cfg.P2P.MaxNumOutboundPeers = 40
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
||||
// initClientConfig helps to override default client config template and configs.
|
||||
// return "", nil if no custom configuration is required for the application.
|
||||
func initClientConfig() (string, interface{}) {
|
||||
type GasConfig struct {
|
||||
GasAdjustment float64 `mapstructure:"gas-adjustment"`
|
||||
}
|
||||
|
||||
type CustomClientConfig struct {
|
||||
clientconfig.Config `mapstructure:",squash"`
|
||||
|
||||
GasConfig GasConfig `mapstructure:"gas"`
|
||||
}
|
||||
|
||||
// Optionally allow the chain developer to overwrite the SDK's default client config.
|
||||
clientCfg := clientconfig.DefaultConfig()
|
||||
|
||||
// The SDK's default keyring backend is set to "os".
|
||||
// This is more secure than "test" and is the recommended value.
|
||||
//
|
||||
// In simapp, we set the default keyring backend to test, as SimApp is meant
|
||||
// to be an example and testing application.
|
||||
clientCfg.KeyringBackend = keyring.BackendTest
|
||||
|
||||
// Now we set the custom config default values.
|
||||
customClientConfig := CustomClientConfig{
|
||||
Config: *clientCfg,
|
||||
GasConfig: GasConfig{
|
||||
GasAdjustment: 1.5,
|
||||
},
|
||||
}
|
||||
|
||||
// The default SDK app template is defined in serverconfig.DefaultConfigTemplate.
|
||||
// We append the custom config template to the default one.
|
||||
// And we set the default config to the custom app template.
|
||||
customClientConfigTemplate := clientconfig.DefaultClientConfigTemplate + strings.TrimSpace(`
|
||||
# This is default the gas adjustment factor used in tx commands.
|
||||
# It can be overwritten by the --gas-adjustment flag in each tx command.
|
||||
gas-adjustment = {{ .GasConfig.GasAdjustment }}
|
||||
`)
|
||||
|
||||
return customClientConfigTemplate, customClientConfig
|
||||
}
|
||||
|
||||
// initAppConfig helps to override default appConfig template and configs.
|
||||
// return "", nil if no custom configuration is required for the application.
|
||||
func initAppConfig() (string, interface{}) {
|
||||
// The following code snippet is just for reference.
|
||||
|
||||
// CustomConfig defines an arbitrary custom config to extend app.toml.
|
||||
// If you don't need it, you can remove it.
|
||||
// If you wish to add fields that correspond to flags that aren't in the SDK server config,
|
||||
// this custom config can as well help.
|
||||
type CustomConfig struct {
|
||||
CustomField string `mapstructure:"custom-field"`
|
||||
}
|
||||
|
||||
type CustomAppConfig struct {
|
||||
serverconfig.Config `mapstructure:",squash"`
|
||||
|
||||
Custom CustomConfig `mapstructure:"custom"`
|
||||
}
|
||||
|
||||
// Optionally allow the chain developer to overwrite the SDK's default
|
||||
// server config.
|
||||
srvCfg := serverconfig.DefaultConfig()
|
||||
// The SDK's default minimum gas price is set to "" (empty value) inside
|
||||
// app.toml. If left empty by validators, the node will halt on startup.
|
||||
// However, the chain developer can set a default app.toml value for their
|
||||
// validators here.
|
||||
//
|
||||
// In summary:
|
||||
// - if you leave srvCfg.MinGasPrices = "", all validators MUST tweak their
|
||||
// own app.toml config,
|
||||
// - if you set srvCfg.MinGasPrices non-empty, validators CAN tweak their
|
||||
// own app.toml to override, or use this default value.
|
||||
//
|
||||
// In simapp, we set the min gas prices to 0.
|
||||
srvCfg.MinGasPrices = "0stake"
|
||||
|
||||
// Now we set the custom config default values.
|
||||
customAppConfig := CustomAppConfig{
|
||||
Config: *srvCfg,
|
||||
Custom: CustomConfig{
|
||||
CustomField: "anything",
|
||||
},
|
||||
}
|
||||
|
||||
// The default SDK app template is defined in serverconfig.DefaultConfigTemplate.
|
||||
// We append the custom config template to the default one.
|
||||
// And we set the default config to the custom app template.
|
||||
customAppTemplate := serverconfig.DefaultConfigTemplate + `
|
||||
[custom]
|
||||
# That field will be parsed by server.InterceptConfigsPreRunHandler and held by viper.
|
||||
# Do not forget to add quotes around the value if it is a string.
|
||||
custom-field = "{{ .Custom.CustomField }}"`
|
||||
|
||||
return customAppTemplate, customAppConfig
|
||||
}
|
||||
@ -1,154 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
authv1 "cosmossdk.io/api/cosmos/auth/module/v1"
|
||||
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
|
||||
stakingv1 "cosmossdk.io/api/cosmos/staking/module/v1"
|
||||
"cosmossdk.io/client/v2/autocli"
|
||||
"cosmossdk.io/core/address"
|
||||
"cosmossdk.io/core/registry"
|
||||
"cosmossdk.io/depinject"
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/simapp"
|
||||
basedepinject "cosmossdk.io/x/accounts/defaults/base/depinject"
|
||||
lockupdepinject "cosmossdk.io/x/accounts/defaults/lockup/depinject"
|
||||
multisigdepinject "cosmossdk.io/x/accounts/defaults/multisig/depinject"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/config"
|
||||
nodeservice "github.com/cosmos/cosmos-sdk/client/grpc/node"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/tx"
|
||||
authtxconfig "github.com/cosmos/cosmos-sdk/x/auth/tx/config"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
)
|
||||
|
||||
// NewRootCmd creates a new root command for simd. It is called once in the main function.
|
||||
func NewRootCmd() *cobra.Command {
|
||||
var (
|
||||
autoCliOpts autocli.AppOptions
|
||||
moduleManager *module.Manager
|
||||
clientCtx client.Context
|
||||
)
|
||||
|
||||
if err := depinject.Inject(
|
||||
depinject.Configs(simapp.AppConfig(),
|
||||
depinject.Supply(log.NewNopLogger()),
|
||||
depinject.Provide(
|
||||
ProvideClientContext,
|
||||
multisigdepinject.ProvideAccount,
|
||||
basedepinject.ProvideAccount,
|
||||
lockupdepinject.ProvideAllLockupAccounts,
|
||||
|
||||
// provide base account options
|
||||
basedepinject.ProvideSecp256K1PubKey,
|
||||
),
|
||||
),
|
||||
&autoCliOpts,
|
||||
&moduleManager,
|
||||
&clientCtx,
|
||||
); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
rootCmd := &cobra.Command{
|
||||
Use: "simd",
|
||||
Short: "simulation app",
|
||||
SilenceErrors: true,
|
||||
PersistentPreRunE: func(cmd *cobra.Command, _ []string) error {
|
||||
// set the default command outputs
|
||||
cmd.SetOut(cmd.OutOrStdout())
|
||||
cmd.SetErr(cmd.ErrOrStderr())
|
||||
|
||||
clientCtx = clientCtx.WithCmdContext(cmd.Context()).WithViper("")
|
||||
clientCtx, err := client.ReadPersistentCommandFlags(clientCtx, cmd.Flags())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
customClientTemplate, customClientConfig := initClientConfig()
|
||||
clientCtx, err = config.CreateClientConfig(clientCtx, customClientTemplate, customClientConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := client.SetCmdClientContextHandler(clientCtx, cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
customAppTemplate, customAppConfig := initAppConfig()
|
||||
customCMTConfig := initCometBFTConfig()
|
||||
|
||||
return server.InterceptConfigsPreRunHandler(cmd, customAppTemplate, customAppConfig, customCMTConfig)
|
||||
},
|
||||
}
|
||||
|
||||
initRootCmd(rootCmd, moduleManager)
|
||||
|
||||
nodeCmds := nodeservice.NewNodeCommands()
|
||||
autoCliOpts.ModuleOptions = make(map[string]*autocliv1.ModuleOptions)
|
||||
autoCliOpts.ModuleOptions[nodeCmds.Name()] = nodeCmds.AutoCLIOptions()
|
||||
|
||||
if err := autoCliOpts.EnhanceRootCommand(rootCmd); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return rootCmd
|
||||
}
|
||||
|
||||
func ProvideClientContext(
|
||||
appCodec codec.Codec,
|
||||
interfaceRegistry codectypes.InterfaceRegistry,
|
||||
txConfigOpts tx.ConfigOptions,
|
||||
legacyAmino registry.AminoRegistrar,
|
||||
addressCodec address.Codec,
|
||||
validatorAddressCodec address.ValidatorAddressCodec,
|
||||
consensusAddressCodec address.ConsensusAddressCodec,
|
||||
authConfig *authv1.Module,
|
||||
stakingConfig *stakingv1.Module,
|
||||
) client.Context {
|
||||
var err error
|
||||
|
||||
amino, ok := legacyAmino.(*codec.LegacyAmino)
|
||||
if !ok {
|
||||
panic("ProvideClientContext requires a *codec.LegacyAmino instance")
|
||||
}
|
||||
|
||||
clientCtx := client.Context{}.
|
||||
WithCodec(appCodec).
|
||||
WithInterfaceRegistry(interfaceRegistry).
|
||||
WithLegacyAmino(amino).
|
||||
WithInput(os.Stdin).
|
||||
WithAccountRetriever(types.AccountRetriever{}).
|
||||
WithAddressCodec(addressCodec).
|
||||
WithValidatorAddressCodec(validatorAddressCodec).
|
||||
WithConsensusAddressCodec(consensusAddressCodec).
|
||||
WithHomeDir(simapp.DefaultNodeHome).
|
||||
WithViper(""). // uses by default the binary name as prefix
|
||||
WithAddressPrefix(authConfig.Bech32Prefix).
|
||||
WithValidatorPrefix(stakingConfig.Bech32PrefixValidator)
|
||||
|
||||
// Read the config to overwrite the default values with the values from the config file
|
||||
customClientTemplate, customClientConfig := initClientConfig()
|
||||
clientCtx, err = config.CreateClientConfig(clientCtx, customClientTemplate, customClientConfig)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// textual is enabled by default, we need to re-create the tx config grpc instead of bank keeper.
|
||||
txConfigOpts.TextualCoinMetadataQueryFn = authtxconfig.NewGRPCCoinMetadataQueryFn(clientCtx)
|
||||
txConfig, err := tx.NewTxConfigWithOptions(clientCtx.Codec, txConfigOpts)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
clientCtx = clientCtx.WithTxConfig(txConfig)
|
||||
|
||||
return clientCtx
|
||||
}
|
||||
@ -1,43 +0,0 @@
|
||||
package cmd_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"cosmossdk.io/simapp"
|
||||
"cosmossdk.io/simapp/simd/cmd"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
svrcmd "github.com/cosmos/cosmos-sdk/server/cmd"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
|
||||
)
|
||||
|
||||
func TestInitCmd(t *testing.T) {
|
||||
rootCmd := cmd.NewRootCmd()
|
||||
rootCmd.SetArgs([]string{
|
||||
"init", // Test the init cmd
|
||||
"simapp-test", // Moniker
|
||||
fmt.Sprintf("--%s=%s", cli.FlagOverwrite, "true"), // Overwrite genesis.json, in case it already exists
|
||||
})
|
||||
|
||||
require.NoError(t, svrcmd.Execute(rootCmd, "", simapp.DefaultNodeHome))
|
||||
}
|
||||
|
||||
func TestHomeFlagRegistration(t *testing.T) {
|
||||
homeDir := "/tmp/foo"
|
||||
|
||||
rootCmd := cmd.NewRootCmd()
|
||||
rootCmd.SetArgs([]string{
|
||||
"query",
|
||||
fmt.Sprintf("--%s", flags.FlagHome),
|
||||
homeDir,
|
||||
})
|
||||
|
||||
require.NoError(t, svrcmd.Execute(rootCmd, "", simapp.DefaultNodeHome))
|
||||
|
||||
result, err := rootCmd.Flags().GetString(flags.FlagHome)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, result, homeDir)
|
||||
}
|
||||
@ -1,754 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
cmtconfig "github.com/cometbft/cometbft/config"
|
||||
cmttime "github.com/cometbft/cometbft/types/time"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
"cosmossdk.io/math/unsafe"
|
||||
banktypes "cosmossdk.io/x/bank/types"
|
||||
stakingtypes "cosmossdk.io/x/staking/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/hd"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
srvconfig "github.com/cosmos/cosmos-sdk/server/config"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
"github.com/cosmos/cosmos-sdk/version"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil"
|
||||
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
|
||||
)
|
||||
|
||||
var (
|
||||
flagNodeDirPrefix = "node-dir-prefix"
|
||||
flagNumValidators = "validator-count"
|
||||
flagOutputDir = "output-dir"
|
||||
flagNodeDaemonHome = "node-daemon-home"
|
||||
flagStartingIPAddress = "starting-ip-address"
|
||||
flagListenIPAddress = "listen-ip-address"
|
||||
flagEnableLogging = "enable-logging"
|
||||
flagGRPCAddress = "grpc.address"
|
||||
flagRPCAddress = "rpc.address"
|
||||
flagAPIAddress = "api.address"
|
||||
flagPrintMnemonic = "print-mnemonic"
|
||||
flagStakingDenom = "staking-denom"
|
||||
flagCommitTimeout = "commit-timeout"
|
||||
flagSingleHost = "single-host"
|
||||
|
||||
// default values
|
||||
defaultRPCPort = 26657
|
||||
defaultAPIPort = 1317
|
||||
defaultGRPCPort = 9090
|
||||
defaultListenIPAddress = "127.0.0.1"
|
||||
defaultStartingIPAddress = "192.168.0.1"
|
||||
defaultNodeDirPrefix = "node"
|
||||
defaultNodeDaemonHome = "simd"
|
||||
)
|
||||
|
||||
type initArgs struct {
|
||||
algo string
|
||||
chainID string
|
||||
keyringBackend string
|
||||
minGasPrices string
|
||||
nodeDaemonHome string
|
||||
nodeDirPrefix string
|
||||
numValidators int
|
||||
outputDir string
|
||||
startingIPAddress string
|
||||
listenIPAddress string
|
||||
singleMachine bool
|
||||
bondTokenDenom string
|
||||
|
||||
// start command arguments
|
||||
apiListenAddress string
|
||||
grpcListenAddress string
|
||||
rpcPort int
|
||||
apiPort int
|
||||
grpcPort int
|
||||
enableLogging bool
|
||||
printMnemonic bool
|
||||
}
|
||||
|
||||
func addTestnetFlagsToCmd(cmd *cobra.Command) {
|
||||
cmd.Flags().IntP(flagNumValidators, "n", 4, "Number of validators to initialize the testnet with")
|
||||
cmd.Flags().StringP(flagOutputDir, "o", "./.testnets", "Directory to store initialization data for the testnet")
|
||||
cmd.Flags().String(flags.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created")
|
||||
cmd.Flags().String(server.FlagMinGasPrices, fmt.Sprintf("0.000006%s", sdk.DefaultBondDenom), "Minimum gas prices to accept for transactions; All fees in a tx must meet this minimum (e.g. 0.01photino,0.001stake)")
|
||||
cmd.Flags().String(flags.FlagKeyType, string(hd.Secp256k1Type), "Key signing algorithm to generate keys for")
|
||||
|
||||
// support old flags name for backwards compatibility
|
||||
cmd.Flags().SetNormalizeFunc(func(f *pflag.FlagSet, name string) pflag.NormalizedName {
|
||||
if name == flags.FlagKeyAlgorithm {
|
||||
name = flags.FlagKeyType
|
||||
}
|
||||
|
||||
return pflag.NormalizedName(name)
|
||||
})
|
||||
}
|
||||
|
||||
// NewTestnetCmd creates a root testnet command with subcommands to run an in-process testnet or initialize
|
||||
// validator configuration files for running a multi-validator testnet in a separate process
|
||||
func NewTestnetCmd(mm *module.Manager) *cobra.Command {
|
||||
testnetCmd := &cobra.Command{
|
||||
Use: "testnet",
|
||||
Short: "subcommands for starting or configuring local testnets",
|
||||
DisableFlagParsing: true,
|
||||
SuggestionsMinimumDistance: 2,
|
||||
RunE: client.ValidateCmd,
|
||||
}
|
||||
|
||||
testnetCmd.AddCommand(testnetStartCmd(mm))
|
||||
testnetCmd.AddCommand(testnetInitFilesCmd(mm))
|
||||
|
||||
return testnetCmd
|
||||
}
|
||||
|
||||
// testnetInitFilesCmd returns a cmd to initialize all files for CometBFT testnet and application
|
||||
func testnetInitFilesCmd(mm *module.Manager) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "init-files",
|
||||
Short: "Initialize config directories & files for a multi-validator testnet running locally via separate processes (e.g. Docker Compose or similar)",
|
||||
Long: fmt.Sprintf(`init-files will setup one directory per validator and populate each with
|
||||
necessary files (private validator, genesis, config, etc.) for running validator nodes.
|
||||
|
||||
Booting up a network with these validator folders is intended to be used with Docker Compose,
|
||||
or a similar setup where each node has a manually configurable IP address.
|
||||
|
||||
Note, strict routability for addresses is turned off in the config file.
|
||||
|
||||
Example:
|
||||
%s testnet init-files --validator-count 4 --output-dir ./.testnets --starting-ip-address 192.168.10.2
|
||||
`, version.AppName),
|
||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||
clientCtx, err := client.GetClientQueryContext(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
config := client.GetConfigFromCmd(cmd)
|
||||
|
||||
args := initArgs{
|
||||
rpcPort: defaultRPCPort,
|
||||
apiPort: defaultAPIPort,
|
||||
grpcPort: defaultGRPCPort,
|
||||
apiListenAddress: defaultListenIPAddress,
|
||||
grpcListenAddress: defaultListenIPAddress,
|
||||
}
|
||||
args.outputDir, _ = cmd.Flags().GetString(flagOutputDir)
|
||||
args.keyringBackend, _ = cmd.Flags().GetString(flags.FlagKeyringBackend)
|
||||
args.chainID, _ = cmd.Flags().GetString(flags.FlagChainID)
|
||||
args.minGasPrices, _ = cmd.Flags().GetString(server.FlagMinGasPrices)
|
||||
args.nodeDirPrefix, _ = cmd.Flags().GetString(flagNodeDirPrefix)
|
||||
args.nodeDaemonHome, _ = cmd.Flags().GetString(flagNodeDaemonHome)
|
||||
args.startingIPAddress, _ = cmd.Flags().GetString(flagStartingIPAddress)
|
||||
args.listenIPAddress, _ = cmd.Flags().GetString(flagListenIPAddress)
|
||||
args.numValidators, _ = cmd.Flags().GetInt(flagNumValidators)
|
||||
args.algo, _ = cmd.Flags().GetString(flags.FlagKeyType)
|
||||
args.bondTokenDenom, _ = cmd.Flags().GetString(flagStakingDenom)
|
||||
args.singleMachine, _ = cmd.Flags().GetBool(flagSingleHost)
|
||||
config.Consensus.TimeoutCommit, err = cmd.Flags().GetDuration(flagCommitTimeout)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if args.chainID == "" {
|
||||
args.chainID = "chain-" + unsafe.Str(6)
|
||||
}
|
||||
|
||||
return initTestnetFiles(clientCtx, cmd, config, mm, args)
|
||||
},
|
||||
}
|
||||
|
||||
addTestnetFlagsToCmd(cmd)
|
||||
cmd.Flags().String(flagNodeDirPrefix, defaultNodeDirPrefix, "Prefix for the name of per-validator subdirectories (to be number-suffixed like node0, node1, ...)")
|
||||
cmd.Flags().String(flagNodeDaemonHome, defaultNodeDaemonHome, "Home directory of the node's daemon configuration")
|
||||
cmd.Flags().String(flagStartingIPAddress, defaultStartingIPAddress, "Starting IP address (192.168.0.1 results in persistent peers list ID0@192.168.0.1:46656, ID1@192.168.0.2:46656, ...)")
|
||||
cmd.Flags().String(flagListenIPAddress, defaultListenIPAddress, "TCP or UNIX socket IP address for the RPC server to listen on")
|
||||
cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|test)")
|
||||
cmd.Flags().Duration(flagCommitTimeout, 5*time.Second, "Time to wait after a block commit before starting on the new height")
|
||||
cmd.Flags().Bool(flagSingleHost, false, "Cluster runs on a single host machine with different ports")
|
||||
cmd.Flags().String(flagStakingDenom, sdk.DefaultBondDenom, "Default staking token denominator")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// testnetStartCmd returns a cmd to start multi validator in-process testnet
|
||||
func testnetStartCmd(mm *module.Manager) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "start",
|
||||
Short: "Launch an in-process multi-validator testnet",
|
||||
Long: fmt.Sprintf(`testnet will launch an in-process multi-validator testnet,
|
||||
and generate a directory for each validator populated with necessary
|
||||
configuration files (private validator, genesis, config, etc.).
|
||||
|
||||
Example:
|
||||
%s testnet --validator-count4 --output-dir ./.testnets
|
||||
`, version.AppName),
|
||||
RunE: func(cmd *cobra.Command, _ []string) (err error) {
|
||||
clientCtx, err := client.GetClientQueryContext(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
config := client.GetConfigFromCmd(cmd)
|
||||
|
||||
args := initArgs{
|
||||
singleMachine: true,
|
||||
bondTokenDenom: sdk.DefaultBondDenom,
|
||||
nodeDaemonHome: defaultNodeDaemonHome,
|
||||
nodeDirPrefix: defaultNodeDirPrefix,
|
||||
keyringBackend: keyring.BackendTest,
|
||||
}
|
||||
args.outputDir, _ = cmd.Flags().GetString(flagOutputDir)
|
||||
args.chainID, _ = cmd.Flags().GetString(flags.FlagChainID)
|
||||
args.minGasPrices, _ = cmd.Flags().GetString(server.FlagMinGasPrices)
|
||||
args.numValidators, _ = cmd.Flags().GetInt(flagNumValidators)
|
||||
args.algo, _ = cmd.Flags().GetString(flags.FlagKeyType)
|
||||
args.enableLogging, _ = cmd.Flags().GetBool(flagEnableLogging)
|
||||
|
||||
rpcAddress, _ := cmd.Flags().GetString(flagRPCAddress)
|
||||
args.listenIPAddress, args.rpcPort, err = parseURL(rpcAddress)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid rpc address: %w", err)
|
||||
}
|
||||
|
||||
apiAddress, _ := cmd.Flags().GetString(flagAPIAddress)
|
||||
args.apiListenAddress, args.apiPort, err = parseURL(apiAddress)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid api address: %w", err)
|
||||
}
|
||||
|
||||
grpcAddress, _ := cmd.Flags().GetString(flagGRPCAddress)
|
||||
// add scheme to avoid issues with parsing
|
||||
if !strings.Contains(grpcAddress, "://") {
|
||||
grpcAddress = "tcp://" + grpcAddress
|
||||
}
|
||||
args.grpcListenAddress, args.grpcPort, err = parseURL(grpcAddress)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid grpc address: %w", err)
|
||||
}
|
||||
|
||||
args.printMnemonic, _ = cmd.Flags().GetBool(flagPrintMnemonic)
|
||||
|
||||
if args.chainID == "" {
|
||||
args.chainID = "chain-" + unsafe.Str(6)
|
||||
}
|
||||
|
||||
return startTestnet(clientCtx, cmd, config, mm, args)
|
||||
},
|
||||
}
|
||||
|
||||
addTestnetFlagsToCmd(cmd)
|
||||
cmd.Flags().Bool(flagEnableLogging, false, "Enable INFO logging of CometBFT validator nodes")
|
||||
cmd.Flags().String(flagRPCAddress, "tcp://127.0.0.1:26657", "the RPC address to listen on")
|
||||
cmd.Flags().String(flagAPIAddress, "tcp://127.0.0.1:1317", "the address to listen on for REST API")
|
||||
cmd.Flags().String(flagGRPCAddress, "127.0.0.1:9090", "the gRPC server address to listen on")
|
||||
cmd.Flags().Bool(flagPrintMnemonic, true, "print mnemonic of first validator to stdout for manual testing")
|
||||
return cmd
|
||||
}
|
||||
|
||||
func parseURL(str string) (host string, port int, err error) {
|
||||
u, err := url.Parse(str)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
host = u.Hostname()
|
||||
|
||||
port, err = strconv.Atoi(u.Port())
|
||||
return
|
||||
}
|
||||
|
||||
const nodeDirPerm = 0o755
|
||||
|
||||
// initTestnetFiles initializes testnet files for a testnet to be run in a separate process
|
||||
func initTestnetFiles(
|
||||
clientCtx client.Context,
|
||||
cmd *cobra.Command,
|
||||
nodeConfig *cmtconfig.Config,
|
||||
mm *module.Manager,
|
||||
args initArgs,
|
||||
) error {
|
||||
nodeIDs := make([]string, args.numValidators)
|
||||
valPubKeys := make([]cryptotypes.PubKey, args.numValidators)
|
||||
|
||||
appConfig := srvconfig.DefaultConfig()
|
||||
appConfig.MinGasPrices = args.minGasPrices
|
||||
appConfig.API.Enable = true
|
||||
appConfig.GRPC.Enable = true
|
||||
appConfig.Telemetry.Enabled = true
|
||||
appConfig.Telemetry.PrometheusRetentionTime = 60
|
||||
appConfig.Telemetry.EnableHostnameLabel = false
|
||||
appConfig.Telemetry.GlobalLabels = [][]string{{"chain_id", args.chainID}}
|
||||
|
||||
var (
|
||||
genAccounts []authtypes.GenesisAccount
|
||||
genBalances []banktypes.Balance
|
||||
genFiles []string
|
||||
)
|
||||
var (
|
||||
rpcPort = args.rpcPort
|
||||
apiPort = args.apiPort
|
||||
grpcPort = args.grpcPort
|
||||
)
|
||||
p2pPortStart := 26656
|
||||
|
||||
inBuf := bufio.NewReader(cmd.InOrStdin())
|
||||
// generate private keys, node IDs, and initial transactions
|
||||
for i := 0; i < args.numValidators; i++ {
|
||||
var portOffset int
|
||||
if args.singleMachine {
|
||||
portOffset = i
|
||||
p2pPortStart = 16656 // use different start point to not conflict with rpc port
|
||||
nodeConfig.P2P.AddrBookStrict = false
|
||||
nodeConfig.P2P.PexReactor = false
|
||||
nodeConfig.P2P.AllowDuplicateIP = true
|
||||
appConfig.API.Address = fmt.Sprintf("tcp://%s:%d", args.apiListenAddress, apiPort+portOffset)
|
||||
appConfig.GRPC.Address = fmt.Sprintf("%s:%d", args.grpcListenAddress, grpcPort+portOffset)
|
||||
}
|
||||
|
||||
nodeDirName, nodeDir := getNodeDir(args, i)
|
||||
gentxsDir := filepath.Join(args.outputDir, "gentxs")
|
||||
|
||||
nodeConfig.SetRoot(nodeDir)
|
||||
nodeConfig.Moniker = nodeDirName
|
||||
nodeConfig.RPC.ListenAddress = fmt.Sprintf("tcp://%s:%d", args.listenIPAddress, rpcPort+portOffset)
|
||||
|
||||
if err := os.MkdirAll(filepath.Join(nodeDir, "config"), nodeDirPerm); err != nil {
|
||||
_ = os.RemoveAll(args.outputDir)
|
||||
return err
|
||||
}
|
||||
var (
|
||||
err error
|
||||
ip string
|
||||
)
|
||||
if args.singleMachine {
|
||||
ip = "127.0.0.1"
|
||||
} else {
|
||||
ip, err = getIP(i, args.startingIPAddress)
|
||||
if err != nil {
|
||||
_ = os.RemoveAll(args.outputDir)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
nodeIDs[i], valPubKeys[i], err = genutil.InitializeNodeValidatorFiles(nodeConfig, args.algo)
|
||||
if err != nil {
|
||||
_ = os.RemoveAll(args.outputDir)
|
||||
return err
|
||||
}
|
||||
|
||||
memo := fmt.Sprintf("%s@%s:%d", nodeIDs[i], ip, p2pPortStart+portOffset)
|
||||
genFiles = append(genFiles, nodeConfig.GenesisFile())
|
||||
|
||||
kb, err := keyring.New(sdk.KeyringServiceName(), args.keyringBackend, nodeDir, inBuf, clientCtx.Codec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
keyringAlgos, _ := kb.SupportedAlgorithms()
|
||||
algo, err := keyring.NewSigningAlgoFromString(args.algo, keyringAlgos)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
addr, secret, err := testutil.GenerateSaveCoinKey(kb, nodeDirName, "", true, algo, sdk.GetFullBIP44Path())
|
||||
if err != nil {
|
||||
_ = os.RemoveAll(args.outputDir)
|
||||
return err
|
||||
}
|
||||
|
||||
// if PrintMnemonic is set to true, we print the first validator node's secret to the network's logger
|
||||
// for debugging and manual testing
|
||||
if args.printMnemonic && i == 0 {
|
||||
printMnemonic(secret)
|
||||
}
|
||||
|
||||
info := map[string]string{"secret": secret}
|
||||
|
||||
cliPrint, err := json.Marshal(info)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// save private key seed words
|
||||
if err := writeFile(fmt.Sprintf("%v.json", "key_seed"), nodeDir, cliPrint); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
accTokens := sdk.TokensFromConsensusPower(1000, sdk.DefaultPowerReduction)
|
||||
accStakingTokens := sdk.TokensFromConsensusPower(500, sdk.DefaultPowerReduction)
|
||||
coins := sdk.Coins{
|
||||
sdk.NewCoin("testtoken", accTokens),
|
||||
sdk.NewCoin(args.bondTokenDenom, accStakingTokens),
|
||||
}
|
||||
|
||||
addrStr, err := clientCtx.AddressCodec.BytesToString(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
genBalances = append(genBalances, banktypes.Balance{Address: addrStr, Coins: coins.Sort()})
|
||||
genAccounts = append(genAccounts, authtypes.NewBaseAccount(addr, nil, 0, 0))
|
||||
|
||||
valStr, err := clientCtx.ValidatorAddressCodec.BytesToString(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
valTokens := sdk.TokensFromConsensusPower(100, sdk.DefaultPowerReduction)
|
||||
createValMsg, err := stakingtypes.NewMsgCreateValidator(
|
||||
valStr,
|
||||
valPubKeys[i],
|
||||
sdk.NewCoin(args.bondTokenDenom, valTokens),
|
||||
stakingtypes.NewDescription(nodeDirName, "", "", "", "", &stakingtypes.Metadata{}),
|
||||
stakingtypes.NewCommissionRates(math.LegacyOneDec(), math.LegacyOneDec(), math.LegacyOneDec()),
|
||||
math.OneInt(),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
txBuilder := clientCtx.TxConfig.NewTxBuilder()
|
||||
if err := txBuilder.SetMsgs(createValMsg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
txBuilder.SetMemo(memo)
|
||||
|
||||
txFactory := tx.Factory{}
|
||||
txFactory = txFactory.
|
||||
WithChainID(args.chainID).
|
||||
WithMemo(memo).
|
||||
WithKeybase(kb).
|
||||
WithTxConfig(clientCtx.TxConfig)
|
||||
|
||||
if err := tx.Sign(clientCtx, txFactory, nodeDirName, txBuilder, true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
txBz, err := clientCtx.TxConfig.TxJSONEncoder()(txBuilder.GetTx())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := writeFile(fmt.Sprintf("%v.json", nodeDirName), gentxsDir, txBz); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := srvconfig.SetConfigTemplate(srvconfig.DefaultConfigTemplate); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := srvconfig.WriteConfigFile(filepath.Join(nodeDir, "config", "app.toml"), appConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := initGenFiles(clientCtx, mm, args.chainID, genAccounts, genBalances, genFiles, args.numValidators); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err := collectGenFiles(
|
||||
clientCtx, nodeConfig, args.chainID, nodeIDs, valPubKeys, args.numValidators,
|
||||
args.outputDir, args.nodeDirPrefix, args.nodeDaemonHome,
|
||||
rpcPort, p2pPortStart, args.singleMachine,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Update viper root since root dir become rootdir/node/simd
|
||||
client.GetViperFromCmd(cmd).Set(flags.FlagHome, nodeConfig.RootDir)
|
||||
|
||||
cmd.PrintErrf("Successfully initialized %d node directories\n", args.numValidators)
|
||||
return nil
|
||||
}
|
||||
|
||||
func initGenFiles(
|
||||
clientCtx client.Context, mm *module.Manager, chainID string,
|
||||
genAccounts []authtypes.GenesisAccount, genBalances []banktypes.Balance,
|
||||
genFiles []string, numValidators int,
|
||||
) error {
|
||||
appGenState := mm.DefaultGenesis()
|
||||
|
||||
// set the accounts in the genesis state
|
||||
var authGenState authtypes.GenesisState
|
||||
clientCtx.Codec.MustUnmarshalJSON(appGenState[authtypes.ModuleName], &authGenState)
|
||||
|
||||
accounts, err := authtypes.PackAccounts(genAccounts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
authGenState.Accounts = accounts
|
||||
appGenState[authtypes.ModuleName] = clientCtx.Codec.MustMarshalJSON(&authGenState)
|
||||
|
||||
// set the balances in the genesis state
|
||||
var bankGenState banktypes.GenesisState
|
||||
clientCtx.Codec.MustUnmarshalJSON(appGenState[banktypes.ModuleName], &bankGenState)
|
||||
|
||||
bankGenState.Balances, err = banktypes.SanitizeGenesisBalances(genBalances, clientCtx.AddressCodec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, bal := range bankGenState.Balances {
|
||||
bankGenState.Supply = bankGenState.Supply.Add(bal.Coins...)
|
||||
}
|
||||
appGenState[banktypes.ModuleName] = clientCtx.Codec.MustMarshalJSON(&bankGenState)
|
||||
|
||||
appGenStateJSON, err := json.MarshalIndent(appGenState, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
appGenesis := genutiltypes.NewAppGenesisWithVersion(chainID, appGenStateJSON)
|
||||
// generate empty genesis files for each validator and save
|
||||
for i := 0; i < numValidators; i++ {
|
||||
if err := appGenesis.SaveAs(genFiles[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func collectGenFiles(
|
||||
clientCtx client.Context, nodeConfig *cmtconfig.Config, chainID string,
|
||||
nodeIDs []string, valPubKeys []cryptotypes.PubKey, numValidators int,
|
||||
outputDir, nodeDirPrefix, nodeDaemonHome string,
|
||||
rpcPortStart, p2pPortStart int,
|
||||
singleMachine bool,
|
||||
) error {
|
||||
var appState json.RawMessage
|
||||
genTime := cmttime.Now()
|
||||
|
||||
for i := 0; i < numValidators; i++ {
|
||||
if singleMachine {
|
||||
portOffset := i
|
||||
nodeConfig.RPC.ListenAddress = fmt.Sprintf("tcp://127.0.0.1:%d", rpcPortStart+portOffset)
|
||||
nodeConfig.P2P.ListenAddress = fmt.Sprintf("tcp://127.0.0.1:%d", p2pPortStart+portOffset)
|
||||
}
|
||||
|
||||
nodeDirName := fmt.Sprintf("%s%d", nodeDirPrefix, i)
|
||||
nodeDir := filepath.Join(outputDir, nodeDirName, nodeDaemonHome)
|
||||
gentxsDir := filepath.Join(outputDir, "gentxs")
|
||||
nodeConfig.Moniker = nodeDirName
|
||||
|
||||
nodeConfig.SetRoot(nodeDir)
|
||||
|
||||
nodeID, valPubKey := nodeIDs[i], valPubKeys[i]
|
||||
initCfg := genutiltypes.NewInitConfig(chainID, gentxsDir, nodeID, valPubKey)
|
||||
|
||||
appGenesis, err := genutiltypes.AppGenesisFromFile(nodeConfig.GenesisFile())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nodeAppState, err := genutil.GenAppStateFromConfig(clientCtx.Codec, clientCtx.TxConfig, nodeConfig, initCfg, appGenesis, genutiltypes.DefaultMessageValidator,
|
||||
clientCtx.ValidatorAddressCodec, clientCtx.AddressCodec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if appState == nil {
|
||||
// set the canonical application state (they should not differ)
|
||||
appState = nodeAppState
|
||||
}
|
||||
|
||||
genFile := nodeConfig.GenesisFile()
|
||||
|
||||
// overwrite each validator's genesis file to have a canonical genesis time
|
||||
if err := genutil.ExportGenesisFileWithTime(genFile, chainID, nil, appState, genTime); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getIP(i int, startingIPAddr string) (ip string, err error) {
|
||||
if len(startingIPAddr) == 0 {
|
||||
ip, err = server.ExternalIP()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return ip, nil
|
||||
}
|
||||
return calculateIP(startingIPAddr, i)
|
||||
}
|
||||
|
||||
func calculateIP(ip string, i int) (string, error) {
|
||||
ipv4 := net.ParseIP(ip).To4()
|
||||
if ipv4 == nil {
|
||||
return "", fmt.Errorf("%v: non ipv4 address", ip)
|
||||
}
|
||||
|
||||
for j := 0; j < i; j++ {
|
||||
ipv4[3]++
|
||||
}
|
||||
|
||||
return ipv4.String(), nil
|
||||
}
|
||||
|
||||
func writeFile(name, dir string, contents []byte) error {
|
||||
file := filepath.Join(dir, name)
|
||||
|
||||
if err := os.MkdirAll(dir, 0o755); err != nil {
|
||||
return fmt.Errorf("could not create directory %q: %w", dir, err)
|
||||
}
|
||||
|
||||
return os.WriteFile(file, contents, 0o600)
|
||||
}
|
||||
|
||||
// printMnemonic prints a provided mnemonic seed phrase on a network logger
|
||||
// for debugging and manual testing
|
||||
func printMnemonic(secret string) {
|
||||
lines := []string{
|
||||
"THIS MNEMONIC IS FOR TESTING PURPOSES ONLY",
|
||||
"DO NOT USE IN PRODUCTION",
|
||||
"",
|
||||
strings.Join(strings.Fields(secret)[0:8], " "),
|
||||
strings.Join(strings.Fields(secret)[8:16], " "),
|
||||
strings.Join(strings.Fields(secret)[16:24], " "),
|
||||
}
|
||||
|
||||
lineLengths := make([]int, len(lines))
|
||||
for i, line := range lines {
|
||||
lineLengths[i] = len(line)
|
||||
}
|
||||
|
||||
maxLineLength := 0
|
||||
for _, lineLen := range lineLengths {
|
||||
if lineLen > maxLineLength {
|
||||
maxLineLength = lineLen
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("\n\n")
|
||||
fmt.Println(strings.Repeat("+", maxLineLength+8))
|
||||
for _, line := range lines {
|
||||
fmt.Printf("++ %s ++\n", centerText(line, maxLineLength))
|
||||
}
|
||||
fmt.Println(strings.Repeat("+", maxLineLength+8))
|
||||
fmt.Printf("\n\n")
|
||||
}
|
||||
|
||||
// centerText centers text across a fixed width, filling either side with whitespace buffers
|
||||
func centerText(text string, width int) string {
|
||||
textLen := len(text)
|
||||
leftBuffer := strings.Repeat(" ", (width-textLen)/2)
|
||||
rightBuffer := strings.Repeat(" ", (width-textLen)/2+(width-textLen)%2)
|
||||
|
||||
return fmt.Sprintf("%s%s%s", leftBuffer, text, rightBuffer)
|
||||
}
|
||||
|
||||
func getNodeDir(args initArgs, nodeID int) (nodeDirName, nodeDir string) {
|
||||
nodeDirName = fmt.Sprintf("%s%d", args.nodeDirPrefix, nodeID)
|
||||
nodeDir = filepath.Join(args.outputDir, nodeDirName, args.nodeDaemonHome)
|
||||
return
|
||||
}
|
||||
|
||||
// startTestnet starts an in-process testnet
|
||||
func startTestnet(
|
||||
clientCtx client.Context,
|
||||
cmd *cobra.Command,
|
||||
nodeConfig *cmtconfig.Config,
|
||||
mm *module.Manager,
|
||||
args initArgs,
|
||||
) error {
|
||||
fmt.Printf(`Preparing test network with chain-id "%s"`, args.chainID)
|
||||
|
||||
args.outputDir = fmt.Sprintf("%s/%s", args.outputDir, args.chainID)
|
||||
err := initTestnetFiles(clientCtx, cmd, nodeConfig, mm, args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// slice to keep track of validator processes
|
||||
var processes []*exec.Cmd
|
||||
|
||||
// channel to signal shutdown
|
||||
shutdownCh := make(chan struct{})
|
||||
|
||||
fmt.Println("Starting test network...")
|
||||
// Start each validator in a separate process
|
||||
for i := 0; i < args.numValidators; i++ {
|
||||
_, nodeDir := getNodeDir(args, i)
|
||||
|
||||
// run start command
|
||||
binName := cmd.Root().Use
|
||||
cmdArgs := []string{"start", fmt.Sprintf("--%s=%s", flags.FlagHome, nodeDir)}
|
||||
runCmd := exec.Command(binName, cmdArgs...) // spawn new process
|
||||
|
||||
// Set stdout and stderr based on enableLogging flag
|
||||
if args.enableLogging {
|
||||
runCmd.Stdout = os.Stdout
|
||||
runCmd.Stderr = os.Stderr
|
||||
} else {
|
||||
runCmd.Stdout = io.Discard // discard output when logging is disabled
|
||||
runCmd.Stderr = io.Discard
|
||||
}
|
||||
|
||||
if err := runCmd.Start(); err != nil {
|
||||
return fmt.Errorf("failed to start validator %d: %w", i, err)
|
||||
}
|
||||
fmt.Printf("Started Validator %d\n", i+1)
|
||||
processes = append(processes, runCmd) // add to processes slice
|
||||
}
|
||||
|
||||
// goroutine to listen for Enter key press
|
||||
go func() {
|
||||
fmt.Println("Press the Enter Key to terminate all validator processes")
|
||||
if _, err := fmt.Scanln(); err == nil {
|
||||
close(shutdownCh) // Signal shutdown
|
||||
}
|
||||
}()
|
||||
|
||||
// goroutine to listen for Ctrl+C (SIGINT)
|
||||
sigCh := make(chan os.Signal, 1)
|
||||
signal.Notify(sigCh, os.Interrupt)
|
||||
go func() {
|
||||
<-sigCh // Wait for Ctrl+C
|
||||
fmt.Println("\nCtrl+C detected, terminating validator processes...")
|
||||
close(shutdownCh) // Signal shutdown
|
||||
}()
|
||||
|
||||
// block until shutdown signal is received
|
||||
<-shutdownCh
|
||||
|
||||
// terminate all validator processes
|
||||
fmt.Println("Shutting down validator processes...")
|
||||
for i, p := range processes {
|
||||
if err := p.Process.Kill(); err != nil {
|
||||
fmt.Printf("Failed to terminate validator %d process: %v\n", i+1, err)
|
||||
} else {
|
||||
fmt.Printf("Validator %d terminated\n", i+1)
|
||||
}
|
||||
}
|
||||
_ = os.RemoveAll(args.outputDir) // Clean up the output directory
|
||||
fmt.Println("Finished cleaning up test network")
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -1,88 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
corectx "cosmossdk.io/core/context"
|
||||
"cosmossdk.io/depinject"
|
||||
"cosmossdk.io/log"
|
||||
banktypes "cosmossdk.io/x/bank/types"
|
||||
"cosmossdk.io/x/staking"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/configurator"
|
||||
genutiltest "github.com/cosmos/cosmos-sdk/testutil/x/genutil"
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
|
||||
)
|
||||
|
||||
func Test_TestnetCmd(t *testing.T) {
|
||||
config := configurator.NewAppConfig(
|
||||
configurator.AccountsModule(),
|
||||
configurator.AuthModule(),
|
||||
configurator.BankModule(),
|
||||
configurator.GenutilModule(),
|
||||
configurator.StakingModule(),
|
||||
configurator.ConsensusModule(),
|
||||
configurator.TxModule(),
|
||||
configurator.ValidateModule(),
|
||||
configurator.MintModule(),
|
||||
)
|
||||
var moduleManager *module.Manager
|
||||
err := depinject.Inject(
|
||||
depinject.Configs(config,
|
||||
depinject.Supply(log.NewNopLogger()),
|
||||
),
|
||||
&moduleManager,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, moduleManager)
|
||||
require.Len(t, moduleManager.Modules, 9) // the registered above + runtime
|
||||
|
||||
home := t.TempDir()
|
||||
cdcOpts := codectestutil.CodecOptions{}
|
||||
encodingConfig := moduletestutil.MakeTestEncodingConfig(cdcOpts, auth.AppModule{}, staking.AppModule{})
|
||||
logger := log.NewNopLogger()
|
||||
viper := viper.New()
|
||||
cfg, err := genutiltest.CreateDefaultCometConfig(home)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = genutiltest.ExecInitCmd(moduleManager, home, encodingConfig.Codec)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = genutiltest.WriteAndTrackCometConfig(viper, home, cfg)
|
||||
require.NoError(t, err)
|
||||
clientCtx := client.Context{}.
|
||||
WithCodec(encodingConfig.Codec).
|
||||
WithHomeDir(home).
|
||||
WithTxConfig(encodingConfig.TxConfig).
|
||||
WithAddressCodec(cdcOpts.GetAddressCodec()).
|
||||
WithValidatorAddressCodec(cdcOpts.GetValidatorCodec())
|
||||
|
||||
ctx := context.Background()
|
||||
ctx = context.WithValue(ctx, corectx.ViperContextKey, viper)
|
||||
ctx = context.WithValue(ctx, corectx.LoggerContextKey, logger)
|
||||
ctx = context.WithValue(ctx, client.ClientContextKey, &clientCtx)
|
||||
cmd := testnetInitFilesCmd(moduleManager)
|
||||
cmd.SetArgs(
|
||||
[]string{fmt.Sprintf("--%s=test", flags.FlagKeyringBackend), fmt.Sprintf("--output-dir=%s", home)},
|
||||
)
|
||||
err = cmd.ExecuteContext(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
genFile := client.GetConfigFromCmd(cmd).GenesisFile()
|
||||
appState, _, err := genutiltypes.GenesisStateFromGenFile(genFile)
|
||||
require.NoError(t, err)
|
||||
|
||||
bankGenState := banktypes.GetGenesisStateFromAppState(encodingConfig.Codec, appState)
|
||||
require.NotEmpty(t, bankGenState.Supply.String())
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
clientv2helpers "cosmossdk.io/client/v2/helpers"
|
||||
"cosmossdk.io/simapp"
|
||||
"cosmossdk.io/simapp/simd/cmd"
|
||||
|
||||
svrcmd "github.com/cosmos/cosmos-sdk/server/cmd"
|
||||
)
|
||||
|
||||
func main() {
|
||||
rootCmd := cmd.NewRootCmd()
|
||||
if err := svrcmd.Execute(rootCmd, clientv2helpers.EnvPrefix, simapp.DefaultNodeHome); err != nil {
|
||||
fmt.Fprintln(rootCmd.OutOrStderr(), err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
@ -1,221 +0,0 @@
|
||||
package simapp
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
abci "github.com/cometbft/cometbft/api/cometbft/abci/v1"
|
||||
cmtjson "github.com/cometbft/cometbft/libs/json"
|
||||
cmttypes "github.com/cometbft/cometbft/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
corestore "cosmossdk.io/core/store"
|
||||
coretesting "cosmossdk.io/core/testing"
|
||||
"cosmossdk.io/log"
|
||||
sdkmath "cosmossdk.io/math"
|
||||
banktypes "cosmossdk.io/x/bank/types"
|
||||
minttypes "cosmossdk.io/x/mint/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/mock"
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
)
|
||||
|
||||
// SetupOptions defines arguments that are passed into `Simapp` constructor.
|
||||
type SetupOptions struct {
|
||||
Logger log.Logger
|
||||
DB corestore.KVStoreWithBatch
|
||||
AppOpts servertypes.AppOptions
|
||||
}
|
||||
|
||||
func setup(withGenesis bool, invCheckPeriod uint) (*SimApp, GenesisState) {
|
||||
db := coretesting.NewMemDB()
|
||||
|
||||
appOptions := make(simtestutil.AppOptionsMap, 0)
|
||||
appOptions[flags.FlagHome] = DefaultNodeHome
|
||||
appOptions[server.FlagInvCheckPeriod] = invCheckPeriod
|
||||
|
||||
app := NewSimApp(log.NewNopLogger(), db, nil, true, appOptions)
|
||||
if withGenesis {
|
||||
return app, app.DefaultGenesis()
|
||||
}
|
||||
return app, GenesisState{}
|
||||
}
|
||||
|
||||
// NewSimappWithCustomOptions initializes a new SimApp with custom options.
|
||||
func NewSimappWithCustomOptions(t *testing.T, isCheckTx bool, options SetupOptions) *SimApp {
|
||||
t.Helper()
|
||||
|
||||
privVal := mock.NewPV()
|
||||
pubKey, err := privVal.GetPubKey()
|
||||
require.NoError(t, err)
|
||||
// create validator set with single validator
|
||||
validator := cmttypes.NewValidator(pubKey, 1)
|
||||
valSet := cmttypes.NewValidatorSet([]*cmttypes.Validator{validator})
|
||||
|
||||
app := NewSimApp(options.Logger, options.DB, nil, true, options.AppOpts)
|
||||
|
||||
// generate genesis account
|
||||
senderPrivKey := secp256k1.GenPrivKey()
|
||||
acc := authtypes.NewBaseAccount(senderPrivKey.PubKey().Address().Bytes(), senderPrivKey.PubKey(), 0, 0)
|
||||
accAddr, err := app.InterfaceRegistry().SigningContext().AddressCodec().BytesToString(acc.GetAddress())
|
||||
require.NoError(t, err)
|
||||
|
||||
balance := banktypes.Balance{
|
||||
Address: accAddr,
|
||||
Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(100000000000000))),
|
||||
}
|
||||
|
||||
genesisState := app.DefaultGenesis()
|
||||
genesisState, err = simtestutil.GenesisStateWithValSet(app.AppCodec(), genesisState, valSet, []authtypes.GenesisAccount{acc}, balance)
|
||||
require.NoError(t, err)
|
||||
|
||||
if !isCheckTx {
|
||||
// init chain must be called to stop deliverState from being nil
|
||||
stateBytes, err := cmtjson.MarshalIndent(genesisState, "", " ")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Initialize the chain
|
||||
_, err = app.InitChain(&abci.InitChainRequest{
|
||||
Validators: []abci.ValidatorUpdate{},
|
||||
ConsensusParams: simtestutil.DefaultConsensusParams,
|
||||
AppStateBytes: stateBytes,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
// Setup initializes a new SimApp. A Nop logger is set in SimApp.
|
||||
func Setup(t *testing.T, isCheckTx bool) *SimApp {
|
||||
t.Helper()
|
||||
|
||||
privVal := mock.NewPV()
|
||||
pubKey, err := privVal.GetPubKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
// create validator set with single validator
|
||||
validator := cmttypes.NewValidator(pubKey, 1)
|
||||
valSet := cmttypes.NewValidatorSet([]*cmttypes.Validator{validator})
|
||||
|
||||
sApp, _ := setup(true, 0)
|
||||
// generate genesis account
|
||||
senderPrivKey := secp256k1.GenPrivKey()
|
||||
acc := authtypes.NewBaseAccount(senderPrivKey.PubKey().Address().Bytes(), senderPrivKey.PubKey(), 0, 0)
|
||||
accAddr, err := sApp.interfaceRegistry.SigningContext().AddressCodec().BytesToString(acc.GetAddress())
|
||||
require.NoError(t, err)
|
||||
balance := banktypes.Balance{
|
||||
Address: accAddr,
|
||||
Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(100000000000000))),
|
||||
}
|
||||
|
||||
app := SetupWithGenesisValSet(t, valSet, []authtypes.GenesisAccount{acc}, balance)
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
// SetupWithGenesisValSet initializes a new SimApp with a validator set and genesis accounts
|
||||
// that also act as delegators. For simplicity, each validator is bonded with a delegation
|
||||
// of one consensus engine unit in the default token of the simapp from first genesis
|
||||
// account. A Nop logger is set in SimApp.
|
||||
func SetupWithGenesisValSet(t *testing.T, valSet *cmttypes.ValidatorSet, genAccs []authtypes.GenesisAccount, balances ...banktypes.Balance) *SimApp {
|
||||
t.Helper()
|
||||
|
||||
app, genesisState := setup(true, 5)
|
||||
genesisState, err := simtestutil.GenesisStateWithValSet(app.AppCodec(), genesisState, valSet, genAccs, balances...)
|
||||
require.NoError(t, err)
|
||||
|
||||
stateBytes, err := json.MarshalIndent(genesisState, "", " ")
|
||||
require.NoError(t, err)
|
||||
|
||||
// init chain will set the validator set and initialize the genesis accounts
|
||||
_, err = app.InitChain(&abci.InitChainRequest{
|
||||
Validators: []abci.ValidatorUpdate{},
|
||||
ConsensusParams: simtestutil.DefaultConsensusParams,
|
||||
AppStateBytes: stateBytes,
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, err)
|
||||
_, err = app.FinalizeBlock(&abci.FinalizeBlockRequest{
|
||||
Height: app.LastBlockHeight() + 1,
|
||||
Hash: app.LastCommitID().Hash,
|
||||
NextValidatorsHash: valSet.Hash(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
// GenesisStateWithSingleValidator initializes GenesisState with a single validator and genesis accounts
|
||||
// that also act as delegators.
|
||||
func GenesisStateWithSingleValidator(t *testing.T, app *SimApp) GenesisState {
|
||||
t.Helper()
|
||||
|
||||
privVal := mock.NewPV()
|
||||
pubKey, err := privVal.GetPubKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
// create validator set with single validator
|
||||
validator := cmttypes.NewValidator(pubKey, 1)
|
||||
valSet := cmttypes.NewValidatorSet([]*cmttypes.Validator{validator})
|
||||
|
||||
// generate genesis account
|
||||
senderPrivKey := secp256k1.GenPrivKey()
|
||||
acc := authtypes.NewBaseAccount(senderPrivKey.PubKey().Address().Bytes(), senderPrivKey.PubKey(), 0, 0)
|
||||
accAddr, err := app.interfaceRegistry.SigningContext().AddressCodec().BytesToString(acc.GetAddress())
|
||||
require.NoError(t, err)
|
||||
balances := []banktypes.Balance{
|
||||
{
|
||||
Address: accAddr,
|
||||
Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(100000000000000))),
|
||||
},
|
||||
}
|
||||
|
||||
genesisState := app.DefaultGenesis()
|
||||
genesisState, err = simtestutil.GenesisStateWithValSet(app.AppCodec(), genesisState, valSet, []authtypes.GenesisAccount{acc}, balances...)
|
||||
require.NoError(t, err)
|
||||
|
||||
return genesisState
|
||||
}
|
||||
|
||||
// AddTestAddrsIncremental constructs and returns accNum amount of accounts with an
|
||||
// initial balance of accAmt in random order
|
||||
func AddTestAddrsIncremental(app *SimApp, ctx sdk.Context, accNum int, accAmt sdkmath.Int) []sdk.AccAddress {
|
||||
return addTestAddrs(app, ctx, accNum, accAmt, simtestutil.CreateIncrementalAccounts)
|
||||
}
|
||||
|
||||
func addTestAddrs(app *SimApp, ctx sdk.Context, accNum int, accAmt sdkmath.Int, strategy simtestutil.GenerateAccountStrategy) []sdk.AccAddress {
|
||||
testAddrs := strategy(accNum)
|
||||
bondDenom, err := app.StakingKeeper.BondDenom(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
initCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, accAmt))
|
||||
|
||||
for _, addr := range testAddrs {
|
||||
initAccountWithCoins(app, ctx, addr, initCoins)
|
||||
}
|
||||
|
||||
return testAddrs
|
||||
}
|
||||
|
||||
func initAccountWithCoins(app *SimApp, ctx sdk.Context, addr sdk.AccAddress, coins sdk.Coins) {
|
||||
err := app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, coins)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = app.BankKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, addr, coins)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
@ -1,42 +0,0 @@
|
||||
package simapp
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"cosmossdk.io/core/appmodule"
|
||||
corestore "cosmossdk.io/core/store"
|
||||
bankv2types "cosmossdk.io/x/bank/v2/types"
|
||||
upgradetypes "cosmossdk.io/x/upgrade/types"
|
||||
)
|
||||
|
||||
// UpgradeName defines the on-chain upgrade name for the sample SimApp upgrade
|
||||
// from v0.52.x to v0.54.x
|
||||
//
|
||||
// NOTE: This upgrade defines a reference implementation of what an upgrade
|
||||
// could look like when an application is migrating from Cosmos SDK version
|
||||
// v0.52.x to v0.54.x.
|
||||
const UpgradeName = "v052-to-v054"
|
||||
|
||||
func (app SimApp) RegisterUpgradeHandlers() {
|
||||
app.UpgradeKeeper.SetUpgradeHandler(
|
||||
UpgradeName,
|
||||
func(ctx context.Context, _ upgradetypes.Plan, fromVM appmodule.VersionMap) (appmodule.VersionMap, error) {
|
||||
return app.ModuleManager.RunMigrations(ctx, app.Configurator(), fromVM)
|
||||
},
|
||||
)
|
||||
|
||||
upgradeInfo, err := app.UpgradeKeeper.ReadUpgradeInfoFromDisk()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if upgradeInfo.Name == UpgradeName && !app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) {
|
||||
storeUpgrades := corestore.StoreUpgrades{
|
||||
Added: []string{bankv2types.StoreKey},
|
||||
Deleted: []string{},
|
||||
}
|
||||
|
||||
// configure store loader that checks if version == upgradeHeight and applies store upgrades
|
||||
app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, &storeUpgrades))
|
||||
}
|
||||
}
|
||||
@ -1,55 +0,0 @@
|
||||
package simapp
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"cosmossdk.io/collections"
|
||||
|
||||
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
)
|
||||
|
||||
// TestSyncAccountNumber tests if accounts module account number is set correctly with the value get from auth.
|
||||
// Also check if the store entry for auth GlobalAccountNumberKey is successfully deleted.
|
||||
func TestSyncAccountNumber(t *testing.T) {
|
||||
app := Setup(t, true)
|
||||
ctx := app.NewUncachedContext(true, cmtproto.Header{})
|
||||
|
||||
bytesKey := authtypes.GlobalAccountNumberKey
|
||||
store := app.AuthKeeper.KVStoreService.OpenKVStore(ctx)
|
||||
|
||||
// initially there is no value set yet
|
||||
v, err := store.Get(bytesKey)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, v)
|
||||
|
||||
// set value for legacy account number
|
||||
v, err = collections.Uint64Value.Encode(10)
|
||||
require.NoError(t, err)
|
||||
err = store.Set(bytesKey, v)
|
||||
require.NoError(t, err)
|
||||
|
||||
// make sure value are updated
|
||||
v, err = store.Get(bytesKey)
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, v)
|
||||
num, err := collections.Uint64Value.Decode(v)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(10), num)
|
||||
|
||||
err = authkeeper.MigrateAccountNumberUnsafe(ctx, &app.AuthKeeper)
|
||||
require.NoError(t, err)
|
||||
|
||||
// make sure the DB entry for this key is deleted
|
||||
v, err = store.Get(bytesKey)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, v)
|
||||
|
||||
// check if accounts's account number is updated
|
||||
currentNum, err := app.AccountsKeeper.AccountNumber.Peek(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(10), currentNum)
|
||||
}
|
||||
@ -6,3 +6,117 @@ sidebar_position: 1
|
||||
|
||||
SimApp is an application built using the Cosmos SDK for testing and educational purposes.
|
||||
`SimApp/v2` demonstrate a runtime/v2, server/v2 and store/v2 wiring.
|
||||
|
||||
## Running testnets with `simdv2`
|
||||
|
||||
Except stated otherwise, all participants in the testnet must follow through with each step.
|
||||
|
||||
### 1. Download and Setup
|
||||
|
||||
Download the Cosmos SDK and unzip it. You can do this manually (via the GitHub UI) or with the git clone command.
|
||||
|
||||
```sh
|
||||
git clone github.com/cosmos/cosmos-sdk.git
|
||||
```
|
||||
|
||||
Next, run this command to build the `simdv2` binary in the `build` directory.
|
||||
|
||||
```sh
|
||||
make build
|
||||
```
|
||||
|
||||
Use the following command and skip all the next steps to configure your SimApp node:
|
||||
|
||||
```sh
|
||||
make init-simapp-v2
|
||||
```
|
||||
|
||||
If you’ve run `simd` in the past, you may need to reset your database before starting up a new testnet. You can do that with this command:
|
||||
|
||||
```sh
|
||||
# you need to provide the moniker and chain ID
|
||||
$ ./simdv2 init [moniker] --chain-id [chain-id]
|
||||
```
|
||||
|
||||
The command should initialize a new working directory at the `~simappv2` location.
|
||||
|
||||
The `moniker` and `chain-id` can be anything but you need to use the same `chain-id` subsequently.
|
||||
|
||||
|
||||
### 2. Create a New Key
|
||||
|
||||
Execute this command to create a new key.
|
||||
|
||||
```sh
|
||||
./simdv2 keys add [key_name]
|
||||
```
|
||||
|
||||
The command will create a new key with your chosen name.
|
||||
|
||||
⚠️ Save the output somewhere safe; you’ll need the address later.
|
||||
|
||||
### 3. Add Genesis Account
|
||||
|
||||
Add a genesis account to your testnet blockchain.
|
||||
|
||||
```sh
|
||||
./simdv2 genesis add-genesis-account [key_name] [amount]
|
||||
```
|
||||
|
||||
Where `key_name` is the same key name as before, and the `amount` is something like `10000000000000000000000000stake`.
|
||||
|
||||
### 4. Add the Genesis Transaction
|
||||
|
||||
This creates the genesis transaction for your testnet chain.
|
||||
|
||||
```sh
|
||||
./simdv2 genesis gentx [key_name] [amount] --chain-id [chain-id]
|
||||
```
|
||||
|
||||
The amount should be at least `1000000000stake`. When you start your node, providing too much or too little may result in errors.
|
||||
|
||||
### 5. Create the Genesis File
|
||||
|
||||
A participant must create the genesis file `genesis.json` with every participant's transaction.
|
||||
|
||||
You can do this by gathering all the Genesis transactions under `config/gentx` and then executing this command.
|
||||
|
||||
```sh
|
||||
./simdv2 genesis collect-gentxs
|
||||
```
|
||||
|
||||
The command will create a new `genesis.json` file that includes data from all the validators. The command will create a new `genesis.json` file, including data from all the validators
|
||||
|
||||
Once you've received the super genesis file, overwrite your original `genesis.json` file with
|
||||
the new super `genesis.json`.
|
||||
|
||||
Modify your `config/config.toml` (in the simapp working directory) to include the other participants as
|
||||
persistent peers:
|
||||
|
||||
```toml
|
||||
# Comma-separated list of nodes to keep persistent connections to
|
||||
persistent_peers = "[validator_address]@[ip_address]:[port],[validator_address]@[ip_address]:[port]"
|
||||
```
|
||||
|
||||
You can find `validator_address` by executing:
|
||||
|
||||
```sh
|
||||
./simdv2 comet show-node-id
|
||||
```
|
||||
|
||||
The output will be the hex-encoded `validator_address`. The default `port` is 26656.
|
||||
|
||||
### 6. Start the Nodes
|
||||
|
||||
Finally, execute this command to start your nodes.
|
||||
|
||||
```sh
|
||||
./simdv2 start
|
||||
```
|
||||
|
||||
Now you have a small testnet that you can use to try out changes to the Cosmos SDK or CometBFT!
|
||||
|
||||
> ⚠️ NOTE: Sometimes, creating the network through the `collect-gents` will fail, and validators will start in a funny state (and then panic).
|
||||
|
||||
If this happens, you can try to create and start the network first
|
||||
with a single validator and then add additional validators using a `create-validator` transaction.
|
||||
|
||||
11
tests/go.mod
11
tests/go.mod
@ -9,11 +9,9 @@ require (
|
||||
cosmossdk.io/depinject v1.1.0
|
||||
cosmossdk.io/log v1.5.0
|
||||
cosmossdk.io/math v1.4.0
|
||||
cosmossdk.io/simapp v0.0.0-20230309163709-87da587416ba
|
||||
cosmossdk.io/store v1.10.0-rc.1
|
||||
cosmossdk.io/x/evidence v0.0.0-20230613133644-0a778132a60f
|
||||
cosmossdk.io/x/feegrant v0.0.0-20230613133644-0a778132a60f
|
||||
cosmossdk.io/x/nft v0.0.0-20230613133644-0a778132a60f // indirect
|
||||
cosmossdk.io/x/protocolpool v0.0.0-20230925135524-a1bc045b3190
|
||||
cosmossdk.io/x/tx v1.0.0-alpha.3
|
||||
cosmossdk.io/x/upgrade v0.0.0-20230613133644-0a778132a60f
|
||||
@ -71,11 +69,8 @@ require (
|
||||
cosmossdk.io/client/v2 v2.0.0-beta.6 // indirect
|
||||
cosmossdk.io/errors v1.0.1 // indirect
|
||||
cosmossdk.io/errors/v2 v2.0.0 // indirect
|
||||
cosmossdk.io/indexer/postgres v0.1.0 // indirect
|
||||
cosmossdk.io/schema v1.0.0 // indirect
|
||||
cosmossdk.io/server/v2/appmanager v0.0.0-00010101000000-000000000000 // indirect
|
||||
cosmossdk.io/tools/benchmark v0.0.0-00010101000000-000000000000 // indirect
|
||||
cosmossdk.io/x/circuit v0.0.0-20230613133644-0a778132a60f // indirect
|
||||
cosmossdk.io/x/epochs v0.0.0-20240522060652-a1ae4c3e0337 // indirect
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
|
||||
@ -159,10 +154,6 @@ require (
|
||||
github.com/huandu/skiplist v1.2.1 // indirect
|
||||
github.com/iancoleman/strcase v0.3.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||
github.com/jackc/pgx/v5 v5.7.1 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/jmhodges/levigo v1.0.0 // indirect
|
||||
github.com/klauspost/compress v1.17.11 // indirect
|
||||
@ -281,8 +272,6 @@ replace (
|
||||
|
||||
// Below are the long-lived replace for tests.
|
||||
replace (
|
||||
// We always want to test against the latest version of the simapp.
|
||||
cosmossdk.io/simapp => ../simapp
|
||||
github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0
|
||||
// We always want to test against the latest version of the SDK.
|
||||
github.com/cosmos/cosmos-sdk => ../.
|
||||
|
||||
@ -606,14 +606,6 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.7.1 h1:x7SYsPBYDkHDksogeSmZZ5xzThcTgRz++I5E+ePFUcs=
|
||||
github.com/jackc/pgx/v5 v5.7.1/go.mod h1:e7O26IywZZ+naJtWWos6i6fvWK+29etgITqrqHLfoZA=
|
||||
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
|
||||
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
github.com/jhump/protoreflect v1.17.0 h1:qOEr613fac2lOuTgWN4tPAtLL7fUSbuJL5X5XumQh94=
|
||||
github.com/jhump/protoreflect v1.17.0/go.mod h1:h9+vUUL38jiBzck8ck+6G/aeMX8Z4QUY/NiJPwPNi+8=
|
||||
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||
|
||||
@ -1,85 +0,0 @@
|
||||
package rootmulti_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
abci "github.com/cometbft/cometbft/api/cometbft/abci/v1"
|
||||
cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1"
|
||||
"gotest.tools/v3/assert"
|
||||
|
||||
coretesting "cosmossdk.io/core/testing"
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/simapp"
|
||||
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
)
|
||||
|
||||
func TestRollback(t *testing.T) {
|
||||
db := coretesting.NewMemDB()
|
||||
options := simapp.SetupOptions{
|
||||
Logger: log.NewNopLogger(),
|
||||
DB: db,
|
||||
AppOpts: simtestutil.NewAppOptionsWithFlagHome(t.TempDir()),
|
||||
}
|
||||
app := simapp.NewSimappWithCustomOptions(t, false, options)
|
||||
ver0 := app.LastBlockHeight()
|
||||
// commit 10 blocks
|
||||
for i := int64(1); i <= 10; i++ {
|
||||
header := cmtproto.Header{
|
||||
Height: ver0 + i,
|
||||
AppHash: app.LastCommitID().Hash,
|
||||
}
|
||||
|
||||
_, err := app.FinalizeBlock(&abci.FinalizeBlockRequest{
|
||||
Height: header.Height,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
ctx := app.NewContextLegacy(false, header)
|
||||
store := ctx.KVStore(app.GetKey("bank"))
|
||||
store.Set([]byte("key"), []byte(fmt.Sprintf("value%d", i)))
|
||||
_, err = app.FinalizeBlock(&abci.FinalizeBlockRequest{
|
||||
Height: header.Height,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
_, err = app.Commit()
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
assert.Equal(t, ver0+10, app.LastBlockHeight())
|
||||
store := app.NewContext(true).KVStore(app.GetKey("bank"))
|
||||
assert.DeepEqual(t, []byte("value10"), store.Get([]byte("key")))
|
||||
|
||||
// rollback 5 blocks
|
||||
target := ver0 + 5
|
||||
assert.NilError(t, app.CommitMultiStore().RollbackToVersion(target))
|
||||
assert.Equal(t, target, app.LastBlockHeight())
|
||||
|
||||
// recreate app to have clean check state
|
||||
app = simapp.NewSimApp(options.Logger, options.DB, nil, true, simtestutil.NewAppOptionsWithFlagHome(t.TempDir()))
|
||||
store = app.NewContext(true).KVStore(app.GetKey("bank"))
|
||||
assert.DeepEqual(t, []byte("value5"), store.Get([]byte("key")))
|
||||
|
||||
// commit another 5 blocks with different values
|
||||
for i := int64(6); i <= 10; i++ {
|
||||
header := cmtproto.Header{
|
||||
Height: ver0 + i,
|
||||
AppHash: app.LastCommitID().Hash,
|
||||
}
|
||||
_, err := app.FinalizeBlock(&abci.FinalizeBlockRequest{Height: header.Height})
|
||||
assert.NilError(t, err)
|
||||
ctx := app.NewContextLegacy(false, header)
|
||||
store := ctx.KVStore(app.GetKey("bank"))
|
||||
store.Set([]byte("key"), []byte(fmt.Sprintf("VALUE%d", i)))
|
||||
_, err = app.FinalizeBlock(&abci.FinalizeBlockRequest{
|
||||
Height: header.Height,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
_, err = app.Commit()
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
assert.Equal(t, ver0+10, app.LastBlockHeight())
|
||||
store = app.NewContext(true).KVStore(app.GetKey("bank"))
|
||||
assert.DeepEqual(t, []byte("VALUE10"), store.Get([]byte("key")))
|
||||
}
|
||||
@ -247,7 +247,7 @@ func (s *IntegrationTestSuite) setupStakingParams(ctx context.Context, sk *staki
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// update unbonding time
|
||||
params.UnbondingTime = time.Duration(time.Second * 10)
|
||||
params.UnbondingTime = time.Second * 10
|
||||
err = sk.Params.Set(ctx, params)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
@ -104,8 +104,8 @@ type StartupConfig struct {
|
||||
GasService gas.Service
|
||||
}
|
||||
|
||||
func DefaultStartUpConfig(t testing.TB) StartupConfig {
|
||||
t.Helper()
|
||||
func DefaultStartUpConfig(tb testing.TB) StartupConfig {
|
||||
tb.Helper()
|
||||
|
||||
priv := secp256k1.GenPrivKey()
|
||||
ba := authtypes.NewBaseAccount(
|
||||
@ -120,8 +120,8 @@ func DefaultStartUpConfig(t testing.TB) StartupConfig {
|
||||
sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(100000000000000)),
|
||||
),
|
||||
}
|
||||
homedir := t.TempDir()
|
||||
t.Logf("generated integration test app config; HomeDir=%s", homedir)
|
||||
homedir := tb.TempDir()
|
||||
tb.Logf("generated integration test app config; HomeDir=%s", homedir)
|
||||
return StartupConfig{
|
||||
ValidatorSet: CreateRandomValidatorSet,
|
||||
GenesisBehavior: Genesis_COMMIT,
|
||||
|
||||
@ -10,7 +10,6 @@ import (
|
||||
"cosmossdk.io/depinject"
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/math"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
_ "cosmossdk.io/x/accounts" // import as blank for app wiring
|
||||
_ "cosmossdk.io/x/bank" // import as blank for app wiring
|
||||
bankkeeper "cosmossdk.io/x/bank/keeper"
|
||||
@ -45,9 +44,8 @@ var (
|
||||
type fixture struct {
|
||||
app *integration.App
|
||||
|
||||
ctx context.Context
|
||||
cdc codec.Codec
|
||||
keys map[string]*storetypes.KVStoreKey
|
||||
ctx context.Context
|
||||
cdc codec.Codec
|
||||
|
||||
queryClient stakingkeeper.Querier
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@ go 1.23
|
||||
|
||||
require (
|
||||
cosmossdk.io/math v1.4.0
|
||||
cosmossdk.io/systemtests v1.0.0-rc.4.0.20241219115822-5bebfb028815
|
||||
cosmossdk.io/systemtests v1.0.0
|
||||
github.com/cosmos/cosmos-sdk v0.50.11
|
||||
)
|
||||
|
||||
|
||||
@ -16,8 +16,8 @@ cosmossdk.io/math v1.4.0 h1:XbgExXFnXmF/CccPPEto40gOO7FpWu9yWNAZPN3nkNQ=
|
||||
cosmossdk.io/math v1.4.0/go.mod h1:O5PkD4apz2jZs4zqFdTr16e1dcaQCc5z6lkEnrrppuk=
|
||||
cosmossdk.io/store v1.1.1 h1:NA3PioJtWDVU7cHHeyvdva5J/ggyLDkyH0hGHl2804Y=
|
||||
cosmossdk.io/store v1.1.1/go.mod h1:8DwVTz83/2PSI366FERGbWSH7hL6sB7HbYp8bqksNwM=
|
||||
cosmossdk.io/systemtests v1.0.0-rc.4.0.20241219115822-5bebfb028815 h1:ilHcBaGJrYhEKC2gO+DVBmWOPNt1VUWNQz3g7/9X4Ow=
|
||||
cosmossdk.io/systemtests v1.0.0-rc.4.0.20241219115822-5bebfb028815/go.mod h1:tTDdBl9wnIyP4L1Gi1/GXD1onPfaAOsscWCw7JUuJ/A=
|
||||
cosmossdk.io/systemtests v1.0.0 h1:VuEj4aA//v1icbMoA6UMuWOwO6ejb6uK7PzSBT+Y460=
|
||||
cosmossdk.io/systemtests v1.0.0/go.mod h1:6kl2MKa7tLoW8vgKx4ZgwAqWVD1T7eAiL5mc/9R7XGY=
|
||||
cosmossdk.io/x/tx v1.0.0-alpha.3 h1:+55/JFH5QRqnFhOI2heH3DKsaNL0RpXcJOQNzUvHiaQ=
|
||||
cosmossdk.io/x/tx v1.0.0-alpha.3/go.mod h1:h4pQ/j6Gfu8goB1R3Jbl4qY4RjYVNAsoylcleTXdSRg=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
|
||||
@ -6,7 +6,7 @@ import (
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"github.com/gogo/protobuf/types"
|
||||
"github.com/cosmos/gogoproto/types"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
|
||||
@ -16,6 +16,8 @@ import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
const valAddress = "val_address"
|
||||
|
||||
func setupContinuousAccount(t *testing.T, ctx context.Context, ss store.KVStoreService) *ContinuousLockingAccount {
|
||||
t.Helper()
|
||||
deps := makeMockDependencies(ss)
|
||||
@ -42,7 +44,7 @@ func TestContinuousAccountDelegate(t *testing.T) {
|
||||
acc := setupContinuousAccount(t, sdkCtx, ss)
|
||||
_, err := acc.Delegate(sdkCtx, &lockuptypes.MsgDelegate{
|
||||
Sender: "owner",
|
||||
ValidatorAddress: "val_address",
|
||||
ValidatorAddress: valAddress,
|
||||
Amount: sdk.NewCoin("test", math.NewInt(1)),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@ -61,7 +63,7 @@ func TestContinuousAccountDelegate(t *testing.T) {
|
||||
|
||||
_, err = acc.Delegate(sdkCtx, &lockuptypes.MsgDelegate{
|
||||
Sender: "owner",
|
||||
ValidatorAddress: "val_address",
|
||||
ValidatorAddress: valAddress,
|
||||
Amount: sdk.NewCoin("test", math.NewInt(5)),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@ -85,7 +87,7 @@ func TestContinuousAccountUndelegate(t *testing.T) {
|
||||
// Delegate first
|
||||
_, err := acc.Delegate(sdkCtx, &lockuptypes.MsgDelegate{
|
||||
Sender: "owner",
|
||||
ValidatorAddress: "val_address",
|
||||
ValidatorAddress: valAddress,
|
||||
Amount: sdk.NewCoin("test", math.NewInt(1)),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@ -97,21 +99,21 @@ func TestContinuousAccountUndelegate(t *testing.T) {
|
||||
// Undelegate
|
||||
_, err = acc.Undelegate(sdkCtx, &lockuptypes.MsgUndelegate{
|
||||
Sender: "owner",
|
||||
ValidatorAddress: "val_address",
|
||||
ValidatorAddress: valAddress,
|
||||
Amount: sdk.NewCoin("test", math.NewInt(1)),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
entries, err := acc.UnbondEntries.Get(sdkCtx, "val_address")
|
||||
entries, err := acc.UnbondEntries.Get(sdkCtx, valAddress)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, entries.Entries, 1)
|
||||
require.True(t, entries.Entries[0].Amount.Amount.Equal(math.NewInt(1)))
|
||||
require.True(t, entries.Entries[0].ValidatorAddress == "val_address")
|
||||
require.True(t, entries.Entries[0].ValidatorAddress == valAddress)
|
||||
|
||||
err = acc.checkUnbondingEntriesMature(sdkCtx)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = acc.UnbondEntries.Get(sdkCtx, "val_address")
|
||||
_, err = acc.UnbondEntries.Get(sdkCtx, valAddress)
|
||||
require.Error(t, err)
|
||||
|
||||
delLocking, err = acc.DelegatedLocking.Get(ctx, "test")
|
||||
|
||||
@ -41,7 +41,7 @@ func TestDelayedAccountDelegate(t *testing.T) {
|
||||
acc := setupDelayedAccount(t, sdkCtx, ss)
|
||||
_, err := acc.Delegate(sdkCtx, &lockuptypes.MsgDelegate{
|
||||
Sender: "owner",
|
||||
ValidatorAddress: "val_address",
|
||||
ValidatorAddress: valAddress,
|
||||
Amount: sdk.NewCoin("test", math.NewInt(1)),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@ -60,7 +60,7 @@ func TestDelayedAccountDelegate(t *testing.T) {
|
||||
|
||||
_, err = acc.Delegate(sdkCtx, &lockuptypes.MsgDelegate{
|
||||
Sender: "owner",
|
||||
ValidatorAddress: "val_address",
|
||||
ValidatorAddress: valAddress,
|
||||
Amount: sdk.NewCoin("test", math.NewInt(5)),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@ -84,7 +84,7 @@ func TestDelayedAccountUndelegate(t *testing.T) {
|
||||
// Delegate first
|
||||
_, err := acc.Delegate(sdkCtx, &lockuptypes.MsgDelegate{
|
||||
Sender: "owner",
|
||||
ValidatorAddress: "val_address",
|
||||
ValidatorAddress: valAddress,
|
||||
Amount: sdk.NewCoin("test", math.NewInt(1)),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@ -96,21 +96,21 @@ func TestDelayedAccountUndelegate(t *testing.T) {
|
||||
// Undelegate
|
||||
_, err = acc.Undelegate(sdkCtx, &lockuptypes.MsgUndelegate{
|
||||
Sender: "owner",
|
||||
ValidatorAddress: "val_address",
|
||||
ValidatorAddress: valAddress,
|
||||
Amount: sdk.NewCoin("test", math.NewInt(1)),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
entries, err := acc.UnbondEntries.Get(sdkCtx, "val_address")
|
||||
entries, err := acc.UnbondEntries.Get(sdkCtx, valAddress)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, entries.Entries, 1)
|
||||
require.True(t, entries.Entries[0].Amount.Amount.Equal(math.NewInt(1)))
|
||||
require.True(t, entries.Entries[0].ValidatorAddress == "val_address")
|
||||
require.True(t, entries.Entries[0].ValidatorAddress == valAddress)
|
||||
|
||||
err = acc.checkUnbondingEntriesMature(sdkCtx)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = acc.UnbondEntries.Get(sdkCtx, "val_address")
|
||||
_, err = acc.UnbondEntries.Get(sdkCtx, valAddress)
|
||||
require.Error(t, err)
|
||||
|
||||
delLocking, err = acc.DelegatedLocking.Get(ctx, "test")
|
||||
|
||||
@ -386,7 +386,7 @@ func (bva *BaseLockup) checkUnbondingEntriesMature(ctx context.Context) error {
|
||||
found := false
|
||||
// check if the entry is still exist in the unbonding entries
|
||||
for _, e := range stakingUnbonding {
|
||||
if e.CompletionTime.Equal(entry.EndTime) && entry.CreationHeight == entry.CreationHeight {
|
||||
if e.CompletionTime.Equal(entry.EndTime) && e.CreationHeight == entry.CreationHeight {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ func TestPeriodicAccountDelegate(t *testing.T) {
|
||||
acc := setupPeriodicAccount(t, sdkCtx, ss)
|
||||
_, err := acc.Delegate(sdkCtx, &lockuptypes.MsgDelegate{
|
||||
Sender: "owner",
|
||||
ValidatorAddress: "val_address",
|
||||
ValidatorAddress: valAddress,
|
||||
Amount: sdk.NewCoin("test", math.NewInt(1)),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@ -74,7 +74,7 @@ func TestPeriodicAccountDelegate(t *testing.T) {
|
||||
|
||||
_, err = acc.Delegate(sdkCtx, &lockuptypes.MsgDelegate{
|
||||
Sender: "owner",
|
||||
ValidatorAddress: "val_address",
|
||||
ValidatorAddress: valAddress,
|
||||
Amount: sdk.NewCoin("test", math.NewInt(5)),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@ -94,7 +94,7 @@ func TestPeriodicAccountDelegate(t *testing.T) {
|
||||
|
||||
_, err = acc.Delegate(sdkCtx, &lockuptypes.MsgDelegate{
|
||||
Sender: "owner",
|
||||
ValidatorAddress: "val_address",
|
||||
ValidatorAddress: valAddress,
|
||||
Amount: sdk.NewCoin("test", math.NewInt(4)),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@ -118,7 +118,7 @@ func TestPeriodicAccountUndelegate(t *testing.T) {
|
||||
// Delegate first
|
||||
_, err := acc.Delegate(sdkCtx, &lockuptypes.MsgDelegate{
|
||||
Sender: "owner",
|
||||
ValidatorAddress: "val_address",
|
||||
ValidatorAddress: valAddress,
|
||||
Amount: sdk.NewCoin("test", math.NewInt(1)),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@ -130,22 +130,22 @@ func TestPeriodicAccountUndelegate(t *testing.T) {
|
||||
// Undelegate
|
||||
_, err = acc.Undelegate(sdkCtx, &lockuptypes.MsgUndelegate{
|
||||
Sender: "owner",
|
||||
ValidatorAddress: "val_address",
|
||||
ValidatorAddress: valAddress,
|
||||
Amount: sdk.NewCoin("test", math.NewInt(1)),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// sequence should be the previous one
|
||||
entries, err := acc.UnbondEntries.Get(sdkCtx, "val_address")
|
||||
entries, err := acc.UnbondEntries.Get(sdkCtx, valAddress)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, entries.Entries, 1)
|
||||
require.True(t, entries.Entries[0].Amount.Amount.Equal(math.NewInt(1)))
|
||||
require.True(t, entries.Entries[0].ValidatorAddress == "val_address")
|
||||
require.True(t, entries.Entries[0].ValidatorAddress == valAddress)
|
||||
|
||||
err = acc.checkUnbondingEntriesMature(sdkCtx)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = acc.UnbondEntries.Get(sdkCtx, "val_address")
|
||||
_, err = acc.UnbondEntries.Get(sdkCtx, valAddress)
|
||||
require.Error(t, err)
|
||||
|
||||
delLocking, err = acc.DelegatedLocking.Get(ctx, "test")
|
||||
|
||||
@ -40,7 +40,7 @@ func TestPermanentAccountDelegate(t *testing.T) {
|
||||
acc := setupPermanentAccount(t, sdkCtx, ss)
|
||||
_, err := acc.Delegate(sdkCtx, &lockuptypes.MsgDelegate{
|
||||
Sender: "owner",
|
||||
ValidatorAddress: "val_address",
|
||||
ValidatorAddress: valAddress,
|
||||
Amount: sdk.NewCoin("test", math.NewInt(1)),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@ -60,7 +60,7 @@ func TestPermanentAccountUndelegate(t *testing.T) {
|
||||
// Delegate first
|
||||
_, err := acc.Delegate(sdkCtx, &lockuptypes.MsgDelegate{
|
||||
Sender: "owner",
|
||||
ValidatorAddress: "val_address",
|
||||
ValidatorAddress: valAddress,
|
||||
Amount: sdk.NewCoin("test", math.NewInt(1)),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@ -72,22 +72,22 @@ func TestPermanentAccountUndelegate(t *testing.T) {
|
||||
// Undelegate
|
||||
_, err = acc.Undelegate(sdkCtx, &lockuptypes.MsgUndelegate{
|
||||
Sender: "owner",
|
||||
ValidatorAddress: "val_address",
|
||||
ValidatorAddress: valAddress,
|
||||
Amount: sdk.NewCoin("test", math.NewInt(1)),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// sequence should be the previous one
|
||||
entries, err := acc.UnbondEntries.Get(sdkCtx, "val_address")
|
||||
entries, err := acc.UnbondEntries.Get(sdkCtx, valAddress)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, entries.Entries, 1)
|
||||
require.True(t, entries.Entries[0].Amount.Amount.Equal(math.NewInt(1)))
|
||||
require.True(t, entries.Entries[0].ValidatorAddress == "val_address")
|
||||
require.True(t, entries.Entries[0].ValidatorAddress == valAddress)
|
||||
|
||||
err = acc.checkUnbondingEntriesMature(sdkCtx)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = acc.UnbondEntries.Get(sdkCtx, "val_address")
|
||||
_, err = acc.UnbondEntries.Get(sdkCtx, valAddress)
|
||||
require.Error(t, err)
|
||||
|
||||
delLocking, err = acc.DelegatedLocking.Get(ctx, "test")
|
||||
|
||||
@ -100,7 +100,7 @@ func newMockContext(t *testing.T) (context.Context, store.KVStoreService) {
|
||||
return &stakingtypes.QueryUnbondingDelegationResponse{
|
||||
Unbond: stakingtypes.UnbondingDelegation{
|
||||
DelegatorAddress: "sender",
|
||||
ValidatorAddress: "val_address",
|
||||
ValidatorAddress: valAddress,
|
||||
Entries: []stakingtypes.UnbondingDelegationEntry{
|
||||
{
|
||||
CreationHeight: 1,
|
||||
|
||||
@ -80,7 +80,7 @@ require (
|
||||
github.com/go-logfmt/logfmt v0.6.0 // indirect
|
||||
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
|
||||
github.com/gogo/googleapis v1.4.1 // indirect
|
||||
github.com/gogo/protobuf v1.3.2
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
|
||||
Loading…
Reference in New Issue
Block a user