Merge branch 'sunny/get_all_delegations_validator_querier' of https://github.com/cosmos/cosmos-sdk into sunny/get_all_delegations_validator_querier
Merge
This commit is contained in:
commit
a6af76e4be
|
@ -20,6 +20,7 @@ FEATURES
|
||||||
* [cli] [\#2569](https://github.com/cosmos/cosmos-sdk/pull/2569) Add commands to query validator unbondings and redelegations
|
* [cli] [\#2569](https://github.com/cosmos/cosmos-sdk/pull/2569) Add commands to query validator unbondings and redelegations
|
||||||
* [cli] [\#2524](https://github.com/cosmos/cosmos-sdk/issues/2524) Add support offline mode to `gaiacli tx sign`. Lookups are not performed if the flag `--offline` is on.
|
* [cli] [\#2524](https://github.com/cosmos/cosmos-sdk/issues/2524) Add support offline mode to `gaiacli tx sign`. Lookups are not performed if the flag `--offline` is on.
|
||||||
* [cli] [\#2558](https://github.com/cosmos/cosmos-sdk/issues/2558) Rename --print-sigs to --validate-signatures. It now performs a complete set of sanity checks and reports to the user. Also added --print-signature-only to print the signature only, not the whole transaction.
|
* [cli] [\#2558](https://github.com/cosmos/cosmos-sdk/issues/2558) Rename --print-sigs to --validate-signatures. It now performs a complete set of sanity checks and reports to the user. Also added --print-signature-only to print the signature only, not the whole transaction.
|
||||||
|
* [cli] [\#2704](https://github.com/cosmos/cosmos-sdk/pull/2704) New add-genesis-account convenience command to populate genesis.json with genesis accounts.
|
||||||
|
|
||||||
* SDK
|
* SDK
|
||||||
* [\#1336](https://github.com/cosmos/cosmos-sdk/issues/1336) Mechanism for SDK Users to configure their own Bech32 prefixes instead of using the default cosmos prefixes.
|
* [\#1336](https://github.com/cosmos/cosmos-sdk/issues/1336) Mechanism for SDK Users to configure their own Bech32 prefixes instead of using the default cosmos prefixes.
|
||||||
|
@ -47,8 +48,7 @@ BUG FIXES
|
||||||
* Gaia
|
* Gaia
|
||||||
* [\#2670](https://github.com/cosmos/cosmos-sdk/issues/2670) [x/stake] fixed incorrect `IterateBondedValidators` and split into two functions: `IterateBondedValidators` and `IterateLastBlockConsValidators`
|
* [\#2670](https://github.com/cosmos/cosmos-sdk/issues/2670) [x/stake] fixed incorrect `IterateBondedValidators` and split into two functions: `IterateBondedValidators` and `IterateLastBlockConsValidators`
|
||||||
* [\#2691](https://github.com/cosmos/cosmos-sdk/issues/2691) Fix local testnet creation by using a single canonical genesis time
|
* [\#2691](https://github.com/cosmos/cosmos-sdk/issues/2691) Fix local testnet creation by using a single canonical genesis time
|
||||||
- [\#2670](https://github.com/cosmos/cosmos-sdk/issues/2670) [x/stake] fixed incorrent `IterateBondedValidators` and split into two functions: `IterateBondedValidators` and `IterateLastBlockConsValidators`
|
* [\#2648](https://github.com/cosmos/cosmos-sdk/issues/2648) [gaiad] Fix `gaiad export` / `gaiad import` consistency, test in CI
|
||||||
- [\#2648](https://github.com/cosmos/cosmos-sdk/issues/2648) [gaiad] Fix `gaiad export` / `gaiad import` consistency, test in CI
|
|
||||||
|
|
||||||
* SDK
|
* SDK
|
||||||
* [\#2625](https://github.com/cosmos/cosmos-sdk/issues/2625) [x/gov] fix AppendTag function usage error
|
* [\#2625](https://github.com/cosmos/cosmos-sdk/issues/2625) [x/gov] fix AppendTag function usage error
|
||||||
|
|
|
@ -298,7 +298,7 @@
|
||||||
"model",
|
"model",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "7e9e6cabbd393fc208072eedef99188d0ce788b6"
|
revision = "0b1957f9d949dfa3084171a6ec5642b38055276a"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
@ -434,7 +434,7 @@
|
||||||
version = "v0.11.1"
|
version = "v0.11.1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:395820b381043b9d2204e181ddf0f9147397c4a7b8f5dc3162de4cfcddf4589a"
|
digest = "1:ba2ba7d6a0853472bdb7a64c4f9c1d5f9cba0eb7aac0b024654104387bf5eb57"
|
||||||
name = "github.com/tendermint/tendermint"
|
name = "github.com/tendermint/tendermint"
|
||||||
packages = [
|
packages = [
|
||||||
"abci/client",
|
"abci/client",
|
||||||
|
@ -500,8 +500,8 @@
|
||||||
"version",
|
"version",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "03e42d2e3866f01a00625f608e3bbfaeb30690de"
|
revision = "80d0a362500fea2dd089258319075a54e5d40a2d"
|
||||||
version = "v0.26.1-rc0"
|
version = "v0.26.1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:7886f86064faff6f8d08a3eb0e8c773648ff5a2e27730831e2bfbf07467f6666"
|
digest = "1:7886f86064faff6f8d08a3eb0e8c773648ff5a2e27730831e2bfbf07467f6666"
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
|
|
||||||
[[override]]
|
[[override]]
|
||||||
name = "github.com/tendermint/tendermint"
|
name = "github.com/tendermint/tendermint"
|
||||||
version = "v0.26.1-rc0" # TODO replace w/ 0.26.1
|
version = "v0.26.1"
|
||||||
|
|
||||||
## deps without releases:
|
## deps without releases:
|
||||||
|
|
||||||
|
|
39
Makefile
39
Makefile
|
@ -1,11 +1,9 @@
|
||||||
PACKAGES_NOSIMULATION=$(shell go list ./... | grep -v '/simulation')
|
PACKAGES_NOSIMULATION=$(shell go list ./... | grep -v '/simulation')
|
||||||
PACKAGES_SIMTEST=$(shell go list ./... | grep '/simulation')
|
PACKAGES_SIMTEST=$(shell go list ./... | grep '/simulation')
|
||||||
VERSION := $(shell git describe --tags --long | sed 's/v\(.*\)/\1/')
|
VERSION := $(subst v,,$(shell git describe --tags --long))
|
||||||
BUILD_TAGS = netgo ledger
|
BUILD_TAGS = netgo
|
||||||
BUILD_FLAGS = -tags "${BUILD_TAGS}" -ldflags "-X github.com/cosmos/cosmos-sdk/version.Version=${VERSION}"
|
BUILD_FLAGS = -tags "${BUILD_TAGS}" -ldflags "-X github.com/cosmos/cosmos-sdk/version.Version=${VERSION}"
|
||||||
GCC := $(shell command -v gcc 2> /dev/null)
|
|
||||||
LEDGER_ENABLED ?= true
|
LEDGER_ENABLED ?= true
|
||||||
UNAME_S := $(shell uname -s)
|
|
||||||
GOTOOLS = \
|
GOTOOLS = \
|
||||||
github.com/golang/dep/cmd/dep \
|
github.com/golang/dep/cmd/dep \
|
||||||
github.com/alecthomas/gometalinter \
|
github.com/alecthomas/gometalinter \
|
||||||
|
@ -20,23 +18,30 @@ ci: get_tools get_vendor_deps install test_cover test_lint test
|
||||||
########################################
|
########################################
|
||||||
### Build/Install
|
### Build/Install
|
||||||
|
|
||||||
check-ledger:
|
|
||||||
ifeq ($(LEDGER_ENABLED),true)
|
ifeq ($(LEDGER_ENABLED),true)
|
||||||
ifeq ($(UNAME_S),OpenBSD)
|
ifeq ($(OS),Windows_NT)
|
||||||
$(info "OpenBSD detected, disabling ledger support (https://github.com/cosmos/cosmos-sdk/issues/1988)")
|
GCCEXE = $(shell where gcc.exe 2> NUL)
|
||||||
TMP_BUILD_TAGS := $(BUILD_TAGS)
|
ifeq ($(GCCEXE),)
|
||||||
BUILD_TAGS = $(filter-out ledger, $(TMP_BUILD_TAGS))
|
$(error gcc.exe not installed for ledger support, please install or set LEDGER_ENABLED=false)
|
||||||
else
|
else
|
||||||
ifndef GCC
|
BUILD_TAGS += ledger
|
||||||
$(error "gcc not installed for ledger support, please install or set LEDGER_ENABLED to false in the Makefile")
|
endif
|
||||||
|
else
|
||||||
|
UNAME_S = $(shell uname -s)
|
||||||
|
ifeq ($(UNAME_S),OpenBSD)
|
||||||
|
$(warning OpenBSD detected, disabling ledger support (https://github.com/cosmos/cosmos-sdk/issues/1988))
|
||||||
|
else
|
||||||
|
GCC = $(shell command -v gcc 2> /dev/null)
|
||||||
|
ifeq ($(GCC),)
|
||||||
|
$(error gcc not installed for ledger support, please install or set LEDGER_ENABLED=false)
|
||||||
|
else
|
||||||
|
BUILD_TAGS += ledger
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
else
|
|
||||||
TMP_BUILD_TAGS := $(BUILD_TAGS)
|
|
||||||
BUILD_TAGS = $(filter-out ledger, $(TMP_BUILD_TAGS))
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
build: check-ledger update_gaia_lite_docs
|
build:
|
||||||
ifeq ($(OS),Windows_NT)
|
ifeq ($(OS),Windows_NT)
|
||||||
go build $(BUILD_FLAGS) -o build/gaiad.exe ./cmd/gaia/cmd/gaiad
|
go build $(BUILD_FLAGS) -o build/gaiad.exe ./cmd/gaia/cmd/gaiad
|
||||||
go build $(BUILD_FLAGS) -o build/gaiacli.exe ./cmd/gaia/cmd/gaiacli
|
go build $(BUILD_FLAGS) -o build/gaiacli.exe ./cmd/gaia/cmd/gaiacli
|
||||||
|
@ -101,7 +106,7 @@ check_tools:
|
||||||
|
|
||||||
update_tools:
|
update_tools:
|
||||||
@echo "--> Updating tools to correct version"
|
@echo "--> Updating tools to correct version"
|
||||||
./scripts/get_tools.sh
|
$(MAKE) -C scripts get_tools
|
||||||
|
|
||||||
update_dev_tools:
|
update_dev_tools:
|
||||||
@echo "--> Downloading linters (this may take awhile)"
|
@echo "--> Downloading linters (this may take awhile)"
|
||||||
|
@ -110,7 +115,7 @@ update_dev_tools:
|
||||||
|
|
||||||
get_tools:
|
get_tools:
|
||||||
@echo "--> Installing tools"
|
@echo "--> Installing tools"
|
||||||
./scripts/get_tools.sh
|
$(MAKE) -C scripts get_tools
|
||||||
|
|
||||||
get_dev_tools:
|
get_dev_tools:
|
||||||
@echo "--> Downloading linters (this may take awhile)"
|
@echo "--> Downloading linters (this may take awhile)"
|
||||||
|
|
10
PENDING.md
10
PENDING.md
|
@ -5,10 +5,13 @@ BREAKING CHANGES
|
||||||
* Gaia REST API (`gaiacli advanced rest-server`)
|
* Gaia REST API (`gaiacli advanced rest-server`)
|
||||||
|
|
||||||
* Gaia CLI (`gaiacli`)
|
* Gaia CLI (`gaiacli`)
|
||||||
|
* [cli] [\#2727](https://github.com/cosmos/cosmos-sdk/pull/2727) Fix unbonding command flow
|
||||||
|
* [cli] [\#2786](https://github.com/cosmos/cosmos-sdk/pull/2786) Fix redelegation command flow
|
||||||
|
|
||||||
* Gaia
|
* Gaia
|
||||||
|
|
||||||
* SDK
|
* SDK
|
||||||
|
* [\#2752](https://github.com/cosmos/cosmos-sdk/pull/2752) Don't hardcode bondable denom.
|
||||||
|
|
||||||
* Tendermint
|
* Tendermint
|
||||||
|
|
||||||
|
@ -23,6 +26,7 @@ FEATURES
|
||||||
* Gaia
|
* Gaia
|
||||||
|
|
||||||
* SDK
|
* SDK
|
||||||
|
* [simulator] \#2682 MsgEditValidator now looks at the validator's max rate, thus it now succeeds a significant portion of the time
|
||||||
|
|
||||||
* Tendermint
|
* Tendermint
|
||||||
|
|
||||||
|
@ -32,10 +36,13 @@ IMPROVEMENTS
|
||||||
* Gaia REST API (`gaiacli advanced rest-server`)
|
* Gaia REST API (`gaiacli advanced rest-server`)
|
||||||
|
|
||||||
* Gaia CLI (`gaiacli`)
|
* Gaia CLI (`gaiacli`)
|
||||||
|
* [\#2749](https://github.com/cosmos/cosmos-sdk/pull/2749) Add --chain-id flag to gaiad testnet
|
||||||
|
|
||||||
* Gaia
|
* Gaia
|
||||||
|
- #2672 [Makefile] Updated for better Windows compatibility and ledger support logic, get_tools was rewritten as a cross-compatible Makefile.
|
||||||
|
|
||||||
* SDK
|
* SDK
|
||||||
|
- [x/mock/simulation] [\#2720] major cleanup, introduction of helper objects, reorganization
|
||||||
|
|
||||||
* Tendermint
|
* Tendermint
|
||||||
|
|
||||||
|
@ -47,7 +54,10 @@ BUG FIXES
|
||||||
* Gaia CLI (`gaiacli`)
|
* Gaia CLI (`gaiacli`)
|
||||||
|
|
||||||
* Gaia
|
* Gaia
|
||||||
|
* [\#2723] Use `cosmosvalcons` Bech32 prefix in `tendermint show-address`
|
||||||
|
* [\#2742](https://github.com/cosmos/cosmos-sdk/issues/2742) Fix time format of TimeoutCommit override
|
||||||
|
|
||||||
* SDK
|
* SDK
|
||||||
|
|
||||||
* Tendermint
|
* Tendermint
|
||||||
|
* [\#2797](https://github.com/tendermint/tendermint/pull/2797) AddressBook requires addresses to have IDs; Do not crap out immediately after sending pex addrs in seed mode
|
||||||
|
|
|
@ -31,6 +31,7 @@ import (
|
||||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||||
"github.com/cosmos/cosmos-sdk/x/slashing"
|
"github.com/cosmos/cosmos-sdk/x/slashing"
|
||||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||||
|
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -265,7 +266,7 @@ func TestCoinSend(t *testing.T) {
|
||||||
coins := acc.GetCoins()
|
coins := acc.GetCoins()
|
||||||
mycoins := coins[0]
|
mycoins := coins[0]
|
||||||
|
|
||||||
require.Equal(t, "steak", mycoins.Denom)
|
require.Equal(t, stakeTypes.DefaultBondDenom, mycoins.Denom)
|
||||||
require.Equal(t, initialBalance[0].Amount.SubRaw(1), mycoins.Amount)
|
require.Equal(t, initialBalance[0].Amount.SubRaw(1), mycoins.Amount)
|
||||||
|
|
||||||
// query receiver
|
// query receiver
|
||||||
|
@ -273,7 +274,7 @@ func TestCoinSend(t *testing.T) {
|
||||||
coins = acc.GetCoins()
|
coins = acc.GetCoins()
|
||||||
mycoins = coins[0]
|
mycoins = coins[0]
|
||||||
|
|
||||||
require.Equal(t, "steak", mycoins.Denom)
|
require.Equal(t, stakeTypes.DefaultBondDenom, mycoins.Denom)
|
||||||
require.Equal(t, int64(1), mycoins.Amount.Int64())
|
require.Equal(t, int64(1), mycoins.Amount.Int64())
|
||||||
|
|
||||||
// test failure with too little gas
|
// test failure with too little gas
|
||||||
|
@ -326,7 +327,7 @@ func DisabledTestIBCTransfer(t *testing.T) {
|
||||||
coins := acc.GetCoins()
|
coins := acc.GetCoins()
|
||||||
mycoins := coins[0]
|
mycoins := coins[0]
|
||||||
|
|
||||||
require.Equal(t, "steak", mycoins.Denom)
|
require.Equal(t, stakeTypes.DefaultBondDenom, mycoins.Denom)
|
||||||
require.Equal(t, initialBalance[0].Amount.SubRaw(1), mycoins.Amount)
|
require.Equal(t, initialBalance[0].Amount.SubRaw(1), mycoins.Amount)
|
||||||
|
|
||||||
// TODO: query ibc egress packet state
|
// TODO: query ibc egress packet state
|
||||||
|
@ -514,7 +515,7 @@ func TestValidatorQuery(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBonding(t *testing.T) {
|
func TestBonding(t *testing.T) {
|
||||||
name, password, denom := "test", "1234567890", "steak"
|
name, password, denom := "test", "1234567890", stakeTypes.DefaultBondDenom
|
||||||
addr, seed := CreateAddr(t, name, password, GetKeyBase(t))
|
addr, seed := CreateAddr(t, name, password, GetKeyBase(t))
|
||||||
|
|
||||||
cleanup, valPubKeys, operAddrs, port := InitializeTestLCD(t, 2, []sdk.AccAddress{addr})
|
cleanup, valPubKeys, operAddrs, port := InitializeTestLCD(t, 2, []sdk.AccAddress{addr})
|
||||||
|
@ -568,7 +569,7 @@ func TestBonding(t *testing.T) {
|
||||||
// sender should have not received any coins as the unbonding has only just begun
|
// sender should have not received any coins as the unbonding has only just begun
|
||||||
acc = getAccount(t, port, addr)
|
acc = getAccount(t, port, addr)
|
||||||
coins = acc.GetCoins()
|
coins = acc.GetCoins()
|
||||||
require.Equal(t, int64(40), coins.AmountOf("steak").Int64())
|
require.Equal(t, int64(40), coins.AmountOf(stakeTypes.DefaultBondDenom).Int64())
|
||||||
|
|
||||||
unbonding := getUndelegation(t, port, addr, operAddrs[0])
|
unbonding := getUndelegation(t, port, addr, operAddrs[0])
|
||||||
require.Equal(t, "30", unbonding.Balance.Amount.String())
|
require.Equal(t, "30", unbonding.Balance.Amount.String())
|
||||||
|
@ -667,11 +668,11 @@ func TestDeposit(t *testing.T) {
|
||||||
|
|
||||||
// query proposal
|
// query proposal
|
||||||
proposal = getProposal(t, port, proposalID)
|
proposal = getProposal(t, port, proposalID)
|
||||||
require.True(t, proposal.GetTotalDeposit().IsEqual(sdk.Coins{sdk.NewInt64Coin("steak", 10)}))
|
require.True(t, proposal.GetTotalDeposit().IsEqual(sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 10)}))
|
||||||
|
|
||||||
// query deposit
|
// query deposit
|
||||||
deposit := getDeposit(t, port, proposalID, addr)
|
deposit := getDeposit(t, port, proposalID, addr)
|
||||||
require.True(t, deposit.Amount.IsEqual(sdk.Coins{sdk.NewInt64Coin("steak", 10)}))
|
require.True(t, deposit.Amount.IsEqual(sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 10)}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVote(t *testing.T) {
|
func TestVote(t *testing.T) {
|
||||||
|
@ -865,7 +866,7 @@ func doSendWithGas(t *testing.T, port, seed, name, password string, addr sdk.Acc
|
||||||
sequence := acc.GetSequence()
|
sequence := acc.GetSequence()
|
||||||
chainID := viper.GetString(client.FlagChainID)
|
chainID := viper.GetString(client.FlagChainID)
|
||||||
// send
|
// send
|
||||||
coinbz, err := cdc.MarshalJSON(sdk.NewInt64Coin("steak", 1))
|
coinbz, err := cdc.MarshalJSON(sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 1))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -951,7 +952,7 @@ func doIBCTransfer(t *testing.T, port, seed, name, password string, addr sdk.Acc
|
||||||
"account_number":"%d",
|
"account_number":"%d",
|
||||||
"sequence":"%d"
|
"sequence":"%d"
|
||||||
}
|
}
|
||||||
}`, "steak", name, password, chainID, accnum, sequence))
|
}`, stakeTypes.DefaultBondDenom, name, password, chainID, accnum, sequence))
|
||||||
|
|
||||||
res, body := Request(t, port, "POST", fmt.Sprintf("/ibc/testchain/%s/send", receiveAddr), jsonStr)
|
res, body := Request(t, port, "POST", fmt.Sprintf("/ibc/testchain/%s/send", receiveAddr), jsonStr)
|
||||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||||
|
@ -1100,7 +1101,7 @@ func doDelegate(t *testing.T, port, seed, name, password string,
|
||||||
"account_number":"%d",
|
"account_number":"%d",
|
||||||
"sequence":"%d"
|
"sequence":"%d"
|
||||||
}
|
}
|
||||||
}`, delAddr, valAddr, "steak", amount, name, password, chainID, accnum, sequence))
|
}`, delAddr, valAddr, stakeTypes.DefaultBondDenom, amount, name, password, chainID, accnum, sequence))
|
||||||
|
|
||||||
res, body := Request(t, port, "POST", fmt.Sprintf("/stake/delegators/%s/delegations", delAddr), jsonStr)
|
res, body := Request(t, port, "POST", fmt.Sprintf("/stake/delegators/%s/delegations", delAddr), jsonStr)
|
||||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||||
|
@ -1354,7 +1355,7 @@ func doSubmitProposal(t *testing.T, port, seed, name, password string, proposerA
|
||||||
"description": "test",
|
"description": "test",
|
||||||
"proposal_type": "Text",
|
"proposal_type": "Text",
|
||||||
"proposer": "%s",
|
"proposer": "%s",
|
||||||
"initial_deposit": [{ "denom": "steak", "amount": "%d" }],
|
"initial_deposit": [{ "denom": "%s", "amount": "%d" }],
|
||||||
"base_req": {
|
"base_req": {
|
||||||
"name": "%s",
|
"name": "%s",
|
||||||
"password": "%s",
|
"password": "%s",
|
||||||
|
@ -1362,7 +1363,7 @@ func doSubmitProposal(t *testing.T, port, seed, name, password string, proposerA
|
||||||
"account_number":"%d",
|
"account_number":"%d",
|
||||||
"sequence":"%d"
|
"sequence":"%d"
|
||||||
}
|
}
|
||||||
}`, proposerAddr, amount, name, password, chainID, accnum, sequence))
|
}`, proposerAddr, stakeTypes.DefaultBondDenom, amount, name, password, chainID, accnum, sequence))
|
||||||
res, body := Request(t, port, "POST", "/gov/proposals", jsonStr)
|
res, body := Request(t, port, "POST", "/gov/proposals", jsonStr)
|
||||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||||
|
|
||||||
|
@ -1384,7 +1385,7 @@ func doDeposit(t *testing.T, port, seed, name, password string, proposerAddr sdk
|
||||||
// deposit on proposal
|
// deposit on proposal
|
||||||
jsonStr := []byte(fmt.Sprintf(`{
|
jsonStr := []byte(fmt.Sprintf(`{
|
||||||
"depositer": "%s",
|
"depositer": "%s",
|
||||||
"amount": [{ "denom": "steak", "amount": "%d" }],
|
"amount": [{ "denom": "%s", "amount": "%d" }],
|
||||||
"base_req": {
|
"base_req": {
|
||||||
"name": "%s",
|
"name": "%s",
|
||||||
"password": "%s",
|
"password": "%s",
|
||||||
|
@ -1392,7 +1393,7 @@ func doDeposit(t *testing.T, port, seed, name, password string, proposerAddr sdk
|
||||||
"account_number":"%d",
|
"account_number":"%d",
|
||||||
"sequence": "%d"
|
"sequence": "%d"
|
||||||
}
|
}
|
||||||
}`, proposerAddr, amount, name, password, chainID, accnum, sequence))
|
}`, proposerAddr, stakeTypes.DefaultBondDenom, amount, name, password, chainID, accnum, sequence))
|
||||||
res, body := Request(t, port, "POST", fmt.Sprintf("/gov/proposals/%d/deposits", proposalID), jsonStr)
|
res, body := Request(t, port, "POST", fmt.Sprintf("/gov/proposals/%d/deposits", proposalID), jsonStr)
|
||||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||||
|
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||||
"github.com/tendermint/tendermint/crypto/secp256k1"
|
"github.com/tendermint/tendermint/crypto/secp256k1"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
|
@ -227,7 +228,7 @@ func InitializeTestLCD(
|
||||||
msg := stake.NewMsgCreateValidator(
|
msg := stake.NewMsgCreateValidator(
|
||||||
sdk.ValAddress(operAddr),
|
sdk.ValAddress(operAddr),
|
||||||
pubKey,
|
pubKey,
|
||||||
sdk.NewCoin("steak", sdk.NewInt(int64(delegation))),
|
sdk.NewCoin(stakeTypes.DefaultBondDenom, sdk.NewInt(int64(delegation))),
|
||||||
stake.Description{Moniker: fmt.Sprintf("validator-%d", i+1)},
|
stake.Description{Moniker: fmt.Sprintf("validator-%d", i+1)},
|
||||||
stake.NewCommissionMsg(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()),
|
stake.NewCommissionMsg(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()),
|
||||||
)
|
)
|
||||||
|
@ -245,7 +246,7 @@ func InitializeTestLCD(
|
||||||
valOperAddrs = append(valOperAddrs, sdk.ValAddress(operAddr))
|
valOperAddrs = append(valOperAddrs, sdk.ValAddress(operAddr))
|
||||||
|
|
||||||
accAuth := auth.NewBaseAccountWithAddress(sdk.AccAddress(operAddr))
|
accAuth := auth.NewBaseAccountWithAddress(sdk.AccAddress(operAddr))
|
||||||
accAuth.Coins = sdk.Coins{sdk.NewInt64Coin("steak", 150)}
|
accAuth.Coins = sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 150)}
|
||||||
accs = append(accs, gapp.NewGenesisAccount(&accAuth))
|
accs = append(accs, gapp.NewGenesisAccount(&accAuth))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,7 +260,7 @@ func InitializeTestLCD(
|
||||||
// add some tokens to init accounts
|
// add some tokens to init accounts
|
||||||
for _, addr := range initAddrs {
|
for _, addr := range initAddrs {
|
||||||
accAuth := auth.NewBaseAccountWithAddress(addr)
|
accAuth := auth.NewBaseAccountWithAddress(addr)
|
||||||
accAuth.Coins = sdk.Coins{sdk.NewInt64Coin("steak", 100)}
|
accAuth.Coins = sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 100)}
|
||||||
acc := gapp.NewGenesisAccount(&accAuth)
|
acc := gapp.NewGenesisAccount(&accAuth)
|
||||||
genesisState.Accounts = append(genesisState.Accounts, acc)
|
genesisState.Accounts = append(genesisState.Accounts, acc)
|
||||||
genesisState.StakeData.Pool.LooseTokens = genesisState.StakeData.Pool.LooseTokens.Add(sdk.NewDec(100))
|
genesisState.StakeData.Pool.LooseTokens = genesisState.StakeData.Pool.LooseTokens.Add(sdk.NewDec(100))
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
"github.com/cosmos/cosmos-sdk/x/mint"
|
"github.com/cosmos/cosmos-sdk/x/mint"
|
||||||
"github.com/cosmos/cosmos-sdk/x/slashing"
|
"github.com/cosmos/cosmos-sdk/x/slashing"
|
||||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||||
|
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||||
tmtypes "github.com/tendermint/tendermint/types"
|
tmtypes "github.com/tendermint/tendermint/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -26,7 +27,7 @@ var (
|
||||||
// bonded tokens given to genesis validators/accounts
|
// bonded tokens given to genesis validators/accounts
|
||||||
freeFermionVal = int64(100)
|
freeFermionVal = int64(100)
|
||||||
freeFermionsAcc = sdk.NewInt(150)
|
freeFermionsAcc = sdk.NewInt(150)
|
||||||
bondDenom = "steak"
|
bondDenom = stakeTypes.DefaultBondDenom
|
||||||
)
|
)
|
||||||
|
|
||||||
// State to Unmarshal
|
// State to Unmarshal
|
||||||
|
@ -286,9 +287,11 @@ func CollectStdTxs(cdc *codec.Codec, moniker string, genTxsDir string, genDoc tm
|
||||||
|
|
||||||
func NewDefaultGenesisAccount(addr sdk.AccAddress) GenesisAccount {
|
func NewDefaultGenesisAccount(addr sdk.AccAddress) GenesisAccount {
|
||||||
accAuth := auth.NewBaseAccountWithAddress(addr)
|
accAuth := auth.NewBaseAccountWithAddress(addr)
|
||||||
accAuth.Coins = []sdk.Coin{
|
coins :=sdk.Coins{
|
||||||
{"fooToken", sdk.NewInt(1000)},
|
{"fooToken", sdk.NewInt(1000)},
|
||||||
{"steak", freeFermionsAcc},
|
{bondDenom, freeFermionsAcc},
|
||||||
}
|
}
|
||||||
|
coins.Sort()
|
||||||
|
accAuth.Coins = coins
|
||||||
return NewGenesisAccount(&accAuth)
|
return NewGenesisAccount(&accAuth)
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,10 +92,8 @@ func TestGaiaAppGenState(t *testing.T) {
|
||||||
func makeMsg(name string, pk crypto.PubKey) auth.StdTx {
|
func makeMsg(name string, pk crypto.PubKey) auth.StdTx {
|
||||||
desc := stake.NewDescription(name, "", "", "")
|
desc := stake.NewDescription(name, "", "", "")
|
||||||
comm := stakeTypes.CommissionMsg{}
|
comm := stakeTypes.CommissionMsg{}
|
||||||
msg := stake.NewMsgCreateValidator(
|
msg := stake.NewMsgCreateValidator(sdk.ValAddress(pk.Address()), pk, sdk.NewInt64Coin(bondDenom,
|
||||||
sdk.ValAddress(pk.Address()), pk,
|
50), desc, comm)
|
||||||
sdk.NewInt64Coin(bondDenom, 50), desc, comm,
|
|
||||||
)
|
|
||||||
return auth.NewStdTx([]sdk.Msg{msg}, auth.StdFee{}, nil, "")
|
return auth.NewStdTx([]sdk.Msg{msg}, auth.StdFee{}, nil, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ import (
|
||||||
slashingsim "github.com/cosmos/cosmos-sdk/x/slashing/simulation"
|
slashingsim "github.com/cosmos/cosmos-sdk/x/slashing/simulation"
|
||||||
stake "github.com/cosmos/cosmos-sdk/x/stake"
|
stake "github.com/cosmos/cosmos-sdk/x/stake"
|
||||||
stakesim "github.com/cosmos/cosmos-sdk/x/stake/simulation"
|
stakesim "github.com/cosmos/cosmos-sdk/x/stake/simulation"
|
||||||
|
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -62,7 +63,7 @@ func appStateFn(r *rand.Rand, accs []simulation.Account) json.RawMessage {
|
||||||
|
|
||||||
// Randomly generate some genesis accounts
|
// Randomly generate some genesis accounts
|
||||||
for _, acc := range accs {
|
for _, acc := range accs {
|
||||||
coins := sdk.Coins{sdk.Coin{"steak", sdk.NewInt(amount)}}
|
coins := sdk.Coins{sdk.Coin{stakeTypes.DefaultBondDenom, sdk.NewInt(amount)}}
|
||||||
genesisAccounts = append(genesisAccounts, GenesisAccount{
|
genesisAccounts = append(genesisAccounts, GenesisAccount{
|
||||||
Address: acc.Address,
|
Address: acc.Address,
|
||||||
Coins: coins,
|
Coins: coins,
|
||||||
|
@ -73,7 +74,7 @@ func appStateFn(r *rand.Rand, accs []simulation.Account) json.RawMessage {
|
||||||
govGenesis := gov.GenesisState{
|
govGenesis := gov.GenesisState{
|
||||||
StartingProposalID: uint64(r.Intn(100)),
|
StartingProposalID: uint64(r.Intn(100)),
|
||||||
DepositParams: gov.DepositParams{
|
DepositParams: gov.DepositParams{
|
||||||
MinDeposit: sdk.Coins{sdk.NewInt64Coin("steak", int64(r.Intn(1e3)))},
|
MinDeposit: sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, int64(r.Intn(1e3)))},
|
||||||
MaxDepositPeriod: time.Duration(r.Intn(2*172800)) * time.Second,
|
MaxDepositPeriod: time.Duration(r.Intn(2*172800)) * time.Second,
|
||||||
},
|
},
|
||||||
VotingParams: gov.VotingParams{
|
VotingParams: gov.VotingParams{
|
||||||
|
@ -91,7 +92,7 @@ func appStateFn(r *rand.Rand, accs []simulation.Account) json.RawMessage {
|
||||||
Params: stake.Params{
|
Params: stake.Params{
|
||||||
UnbondingTime: time.Duration(r.Intn(60*60*24*3*2)) * time.Second,
|
UnbondingTime: time.Duration(r.Intn(60*60*24*3*2)) * time.Second,
|
||||||
MaxValidators: uint16(r.Intn(250)),
|
MaxValidators: uint16(r.Intn(250)),
|
||||||
BondDenom: "steak",
|
BondDenom: stakeTypes.DefaultBondDenom,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
fmt.Printf("Selected randomly generated staking parameters: %+v\n", stakeGenesis)
|
fmt.Printf("Selected randomly generated staking parameters: %+v\n", stakeGenesis)
|
||||||
|
@ -113,7 +114,7 @@ func appStateFn(r *rand.Rand, accs []simulation.Account) json.RawMessage {
|
||||||
Inflation: sdk.NewDecWithPrec(int64(r.Intn(99)), 2),
|
Inflation: sdk.NewDecWithPrec(int64(r.Intn(99)), 2),
|
||||||
},
|
},
|
||||||
Params: mint.Params{
|
Params: mint.Params{
|
||||||
MintDenom: "steak",
|
MintDenom: stakeTypes.DefaultBondDenom,
|
||||||
InflationRateChange: sdk.NewDecWithPrec(int64(r.Intn(99)), 2),
|
InflationRateChange: sdk.NewDecWithPrec(int64(r.Intn(99)), 2),
|
||||||
InflationMax: sdk.NewDecWithPrec(20, 2),
|
InflationMax: sdk.NewDecWithPrec(20, 2),
|
||||||
InflationMin: sdk.NewDecWithPrec(7, 2),
|
InflationMin: sdk.NewDecWithPrec(7, 2),
|
||||||
|
|
|
@ -29,6 +29,7 @@ import (
|
||||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||||
|
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -55,10 +56,10 @@ func TestGaiaCLIMinimumFees(t *testing.T) {
|
||||||
barAddr, _ := executeGetAddrPK(t, fmt.Sprintf("gaiacli keys show bar --output=json --home=%s", gaiacliHome))
|
barAddr, _ := executeGetAddrPK(t, fmt.Sprintf("gaiacli keys show bar --output=json --home=%s", gaiacliHome))
|
||||||
|
|
||||||
fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
||||||
require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf("steak").Int64())
|
require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom).Int64())
|
||||||
|
|
||||||
success := executeWrite(t, fmt.Sprintf(
|
success := executeWrite(t, fmt.Sprintf(
|
||||||
"gaiacli tx send %v --amount=10steak --to=%s --from=foo", flags, barAddr), app.DefaultKeyPass)
|
"gaiacli tx send %v --amount=10%s --to=%s --from=foo", flags, stakeTypes.DefaultBondDenom, barAddr), app.DefaultKeyPass)
|
||||||
require.False(t, success)
|
require.False(t, success)
|
||||||
tests.WaitForNextNBlocksTM(2, port)
|
tests.WaitForNextNBlocksTM(2, port)
|
||||||
|
|
||||||
|
@ -121,40 +122,40 @@ func TestGaiaCLISend(t *testing.T) {
|
||||||
barAddr, _ := executeGetAddrPK(t, fmt.Sprintf("gaiacli keys show bar --output=json --home=%s", gaiacliHome))
|
barAddr, _ := executeGetAddrPK(t, fmt.Sprintf("gaiacli keys show bar --output=json --home=%s", gaiacliHome))
|
||||||
|
|
||||||
fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
||||||
require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf("steak").Int64())
|
require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom).Int64())
|
||||||
|
|
||||||
executeWrite(t, fmt.Sprintf("gaiacli tx send %v --amount=10steak --to=%s --from=foo", flags, barAddr), app.DefaultKeyPass)
|
executeWrite(t, fmt.Sprintf("gaiacli tx send %v --amount=10%s --to=%s --from=foo", flags, stakeTypes.DefaultBondDenom, barAddr), app.DefaultKeyPass)
|
||||||
tests.WaitForNextNBlocksTM(2, port)
|
tests.WaitForNextNBlocksTM(2, port)
|
||||||
|
|
||||||
barAcc := executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", barAddr, flags))
|
barAcc := executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", barAddr, flags))
|
||||||
require.Equal(t, int64(10), barAcc.GetCoins().AmountOf("steak").Int64())
|
require.Equal(t, int64(10), barAcc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom).Int64())
|
||||||
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
||||||
require.Equal(t, int64(40), fooAcc.GetCoins().AmountOf("steak").Int64())
|
require.Equal(t, int64(40), fooAcc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom).Int64())
|
||||||
|
|
||||||
// Test --dry-run
|
// Test --dry-run
|
||||||
success := executeWrite(t, fmt.Sprintf("gaiacli tx send %v --amount=10steak --to=%s --from=foo --dry-run", flags, barAddr), app.DefaultKeyPass)
|
success := executeWrite(t, fmt.Sprintf("gaiacli tx send %v --amount=10%s --to=%s --from=foo --dry-run", flags, stakeTypes.DefaultBondDenom, barAddr), app.DefaultKeyPass)
|
||||||
require.True(t, success)
|
require.True(t, success)
|
||||||
// Check state didn't change
|
// Check state didn't change
|
||||||
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
||||||
require.Equal(t, int64(40), fooAcc.GetCoins().AmountOf("steak").Int64())
|
require.Equal(t, int64(40), fooAcc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom).Int64())
|
||||||
|
|
||||||
// test autosequencing
|
// test autosequencing
|
||||||
executeWrite(t, fmt.Sprintf("gaiacli tx send %v --amount=10steak --to=%s --from=foo", flags, barAddr), app.DefaultKeyPass)
|
executeWrite(t, fmt.Sprintf("gaiacli tx send %v --amount=10%s --to=%s --from=foo", flags, stakeTypes.DefaultBondDenom, barAddr), app.DefaultKeyPass)
|
||||||
tests.WaitForNextNBlocksTM(2, port)
|
tests.WaitForNextNBlocksTM(2, port)
|
||||||
|
|
||||||
barAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", barAddr, flags))
|
barAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", barAddr, flags))
|
||||||
require.Equal(t, int64(20), barAcc.GetCoins().AmountOf("steak").Int64())
|
require.Equal(t, int64(20), barAcc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom).Int64())
|
||||||
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
||||||
require.Equal(t, int64(30), fooAcc.GetCoins().AmountOf("steak").Int64())
|
require.Equal(t, int64(30), fooAcc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom).Int64())
|
||||||
|
|
||||||
// test memo
|
// test memo
|
||||||
executeWrite(t, fmt.Sprintf("gaiacli tx send %v --amount=10steak --to=%s --from=foo --memo 'testmemo'", flags, barAddr), app.DefaultKeyPass)
|
executeWrite(t, fmt.Sprintf("gaiacli tx send %v --amount=10%s --to=%s --from=foo --memo 'testmemo'", flags, stakeTypes.DefaultBondDenom, barAddr), app.DefaultKeyPass)
|
||||||
tests.WaitForNextNBlocksTM(2, port)
|
tests.WaitForNextNBlocksTM(2, port)
|
||||||
|
|
||||||
barAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", barAddr, flags))
|
barAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", barAddr, flags))
|
||||||
require.Equal(t, int64(30), barAcc.GetCoins().AmountOf("steak").Int64())
|
require.Equal(t, int64(30), barAcc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom).Int64())
|
||||||
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
||||||
require.Equal(t, int64(20), fooAcc.GetCoins().AmountOf("steak").Int64())
|
require.Equal(t, int64(20), fooAcc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom).Int64())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGaiaCLIGasAuto(t *testing.T) {
|
func TestGaiaCLIGasAuto(t *testing.T) {
|
||||||
|
@ -172,26 +173,26 @@ func TestGaiaCLIGasAuto(t *testing.T) {
|
||||||
barAddr, _ := executeGetAddrPK(t, fmt.Sprintf("gaiacli keys show bar --output=json --home=%s", gaiacliHome))
|
barAddr, _ := executeGetAddrPK(t, fmt.Sprintf("gaiacli keys show bar --output=json --home=%s", gaiacliHome))
|
||||||
|
|
||||||
fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
||||||
require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf("steak").Int64())
|
require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom).Int64())
|
||||||
|
|
||||||
// Test failure with auto gas disabled and very little gas set by hand
|
// Test failure with auto gas disabled and very little gas set by hand
|
||||||
success := executeWrite(t, fmt.Sprintf("gaiacli tx send %v --gas=10 --amount=10steak --to=%s --from=foo", flags, barAddr), app.DefaultKeyPass)
|
success := executeWrite(t, fmt.Sprintf("gaiacli tx send %v --gas=10 --amount=10%s --to=%s --from=foo", flags, stakeTypes.DefaultBondDenom, barAddr), app.DefaultKeyPass)
|
||||||
require.False(t, success)
|
require.False(t, success)
|
||||||
tests.WaitForNextNBlocksTM(2, port)
|
tests.WaitForNextNBlocksTM(2, port)
|
||||||
// Check state didn't change
|
// Check state didn't change
|
||||||
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
||||||
require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf("steak").Int64())
|
require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom).Int64())
|
||||||
|
|
||||||
// Test failure with negative gas
|
// Test failure with negative gas
|
||||||
success = executeWrite(t, fmt.Sprintf("gaiacli tx send %v --gas=-100 --amount=10steak --to=%s --from=foo", flags, barAddr), app.DefaultKeyPass)
|
success = executeWrite(t, fmt.Sprintf("gaiacli tx send %v --gas=-100 --amount=10%s --to=%s --from=foo", flags, stakeTypes.DefaultBondDenom, barAddr), app.DefaultKeyPass)
|
||||||
require.False(t, success)
|
require.False(t, success)
|
||||||
|
|
||||||
// Test failure with 0 gas
|
// Test failure with 0 gas
|
||||||
success = executeWrite(t, fmt.Sprintf("gaiacli tx send %v --gas=0 --amount=10steak --to=%s --from=foo", flags, barAddr), app.DefaultKeyPass)
|
success = executeWrite(t, fmt.Sprintf("gaiacli tx send %v --gas=0 --amount=10%s --to=%s --from=foo", flags, stakeTypes.DefaultBondDenom, barAddr), app.DefaultKeyPass)
|
||||||
require.False(t, success)
|
require.False(t, success)
|
||||||
|
|
||||||
// Enable auto gas
|
// Enable auto gas
|
||||||
success, stdout, _ := executeWriteRetStdStreams(t, fmt.Sprintf("gaiacli tx send %v --json --gas=simulate --amount=10steak --to=%s --from=foo", flags, barAddr), app.DefaultKeyPass)
|
success, stdout, _ := executeWriteRetStdStreams(t, fmt.Sprintf("gaiacli tx send %v --json --gas=simulate --amount=10%s --to=%s --from=foo", flags, stakeTypes.DefaultBondDenom, barAddr), app.DefaultKeyPass)
|
||||||
require.True(t, success)
|
require.True(t, success)
|
||||||
// check that gas wanted == gas used
|
// check that gas wanted == gas used
|
||||||
cdc := app.MakeCodec()
|
cdc := app.MakeCodec()
|
||||||
|
@ -205,7 +206,7 @@ func TestGaiaCLIGasAuto(t *testing.T) {
|
||||||
tests.WaitForNextNBlocksTM(2, port)
|
tests.WaitForNextNBlocksTM(2, port)
|
||||||
// Check state has changed accordingly
|
// Check state has changed accordingly
|
||||||
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
||||||
require.Equal(t, int64(40), fooAcc.GetCoins().AmountOf("steak").Int64())
|
require.Equal(t, int64(40), fooAcc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom).Int64())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGaiaCLICreateValidator(t *testing.T) {
|
func TestGaiaCLICreateValidator(t *testing.T) {
|
||||||
|
@ -223,13 +224,13 @@ func TestGaiaCLICreateValidator(t *testing.T) {
|
||||||
barAddr, barPubKey := executeGetAddrPK(t, fmt.Sprintf("gaiacli keys show bar --output=json --home=%s", gaiacliHome))
|
barAddr, barPubKey := executeGetAddrPK(t, fmt.Sprintf("gaiacli keys show bar --output=json --home=%s", gaiacliHome))
|
||||||
barCeshPubKey := sdk.MustBech32ifyConsPub(barPubKey)
|
barCeshPubKey := sdk.MustBech32ifyConsPub(barPubKey)
|
||||||
|
|
||||||
executeWrite(t, fmt.Sprintf("gaiacli tx send %v --amount=10steak --to=%s --from=foo", flags, barAddr), app.DefaultKeyPass)
|
executeWrite(t, fmt.Sprintf("gaiacli tx send %v --amount=10%s --to=%s --from=foo", flags, stakeTypes.DefaultBondDenom, barAddr), app.DefaultKeyPass)
|
||||||
tests.WaitForNextNBlocksTM(2, port)
|
tests.WaitForNextNBlocksTM(2, port)
|
||||||
|
|
||||||
barAcc := executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", barAddr, flags))
|
barAcc := executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", barAddr, flags))
|
||||||
require.Equal(t, int64(10), barAcc.GetCoins().AmountOf("steak").Int64())
|
require.Equal(t, int64(10), barAcc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom).Int64())
|
||||||
fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
||||||
require.Equal(t, int64(40), fooAcc.GetCoins().AmountOf("steak").Int64())
|
require.Equal(t, int64(40), fooAcc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom).Int64())
|
||||||
|
|
||||||
defaultParams := stake.DefaultParams()
|
defaultParams := stake.DefaultParams()
|
||||||
initialPool := stake.InitialPool()
|
initialPool := stake.InitialPool()
|
||||||
|
@ -239,7 +240,7 @@ func TestGaiaCLICreateValidator(t *testing.T) {
|
||||||
cvStr := fmt.Sprintf("gaiacli tx create-validator %v", flags)
|
cvStr := fmt.Sprintf("gaiacli tx create-validator %v", flags)
|
||||||
cvStr += fmt.Sprintf(" --from=%s", "bar")
|
cvStr += fmt.Sprintf(" --from=%s", "bar")
|
||||||
cvStr += fmt.Sprintf(" --pubkey=%s", barCeshPubKey)
|
cvStr += fmt.Sprintf(" --pubkey=%s", barCeshPubKey)
|
||||||
cvStr += fmt.Sprintf(" --amount=%v", "2steak")
|
cvStr += fmt.Sprintf(" --amount=%v", fmt.Sprintf("2%s", stakeTypes.DefaultBondDenom))
|
||||||
cvStr += fmt.Sprintf(" --moniker=%v", "bar-vally")
|
cvStr += fmt.Sprintf(" --moniker=%v", "bar-vally")
|
||||||
cvStr += fmt.Sprintf(" --commission-rate=%v", "0.05")
|
cvStr += fmt.Sprintf(" --commission-rate=%v", "0.05")
|
||||||
cvStr += fmt.Sprintf(" --commission-max-rate=%v", "0.20")
|
cvStr += fmt.Sprintf(" --commission-max-rate=%v", "0.20")
|
||||||
|
@ -265,7 +266,7 @@ func TestGaiaCLICreateValidator(t *testing.T) {
|
||||||
tests.WaitForNextNBlocksTM(2, port)
|
tests.WaitForNextNBlocksTM(2, port)
|
||||||
|
|
||||||
barAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", barAddr, flags))
|
barAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", barAddr, flags))
|
||||||
require.Equal(t, int64(8), barAcc.GetCoins().AmountOf("steak").Int64(), "%v", barAcc)
|
require.Equal(t, int64(8), barAcc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom).Int64(), "%v", barAcc)
|
||||||
|
|
||||||
validator := executeGetValidator(t, fmt.Sprintf("gaiacli query validator %s --output=json %v", sdk.ValAddress(barAddr), flags))
|
validator := executeGetValidator(t, fmt.Sprintf("gaiacli query validator %s --output=json %v", sdk.ValAddress(barAddr), flags))
|
||||||
require.Equal(t, validator.OperatorAddr, sdk.ValAddress(barAddr))
|
require.Equal(t, validator.OperatorAddr, sdk.ValAddress(barAddr))
|
||||||
|
@ -287,7 +288,7 @@ func TestGaiaCLICreateValidator(t *testing.T) {
|
||||||
|
|
||||||
/* // this won't be what we expect because we've only started unbonding, haven't completed
|
/* // this won't be what we expect because we've only started unbonding, haven't completed
|
||||||
barAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query account %v %v", barCech, flags))
|
barAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query account %v %v", barCech, flags))
|
||||||
require.Equal(t, int64(9), barAcc.GetCoins().AmountOf("steak").Int64(), "%v", barAcc)
|
require.Equal(t, int64(9), barAcc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom).Int64(), "%v", barAcc)
|
||||||
*/
|
*/
|
||||||
validator = executeGetValidator(t, fmt.Sprintf("gaiacli query validator %s --output=json %v", sdk.ValAddress(barAddr), flags))
|
validator = executeGetValidator(t, fmt.Sprintf("gaiacli query validator %s --output=json %v", sdk.ValAddress(barAddr), flags))
|
||||||
require.Equal(t, "1.0000000000", validator.Tokens.String())
|
require.Equal(t, "1.0000000000", validator.Tokens.String())
|
||||||
|
@ -319,7 +320,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
|
||||||
fooAddr, _ := executeGetAddrPK(t, fmt.Sprintf("gaiacli keys show foo --output=json --home=%s", gaiacliHome))
|
fooAddr, _ := executeGetAddrPK(t, fmt.Sprintf("gaiacli keys show foo --output=json --home=%s", gaiacliHome))
|
||||||
|
|
||||||
fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
||||||
require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf("steak").Int64())
|
require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom).Int64())
|
||||||
|
|
||||||
proposalsQuery, _ := tests.ExecuteT(t, fmt.Sprintf("gaiacli query proposals %v", flags), "")
|
proposalsQuery, _ := tests.ExecuteT(t, fmt.Sprintf("gaiacli query proposals %v", flags), "")
|
||||||
require.Equal(t, "No matching proposals found", proposalsQuery)
|
require.Equal(t, "No matching proposals found", proposalsQuery)
|
||||||
|
@ -327,7 +328,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
|
||||||
// submit a test proposal
|
// submit a test proposal
|
||||||
spStr := fmt.Sprintf("gaiacli tx submit-proposal %v", flags)
|
spStr := fmt.Sprintf("gaiacli tx submit-proposal %v", flags)
|
||||||
spStr += fmt.Sprintf(" --from=%s", "foo")
|
spStr += fmt.Sprintf(" --from=%s", "foo")
|
||||||
spStr += fmt.Sprintf(" --deposit=%s", "5steak")
|
spStr += fmt.Sprintf(" --deposit=%s", fmt.Sprintf("5%s", stakeTypes.DefaultBondDenom))
|
||||||
spStr += fmt.Sprintf(" --type=%s", "Text")
|
spStr += fmt.Sprintf(" --type=%s", "Text")
|
||||||
spStr += fmt.Sprintf(" --title=%s", "Test")
|
spStr += fmt.Sprintf(" --title=%s", "Test")
|
||||||
spStr += fmt.Sprintf(" --description=%s", "test")
|
spStr += fmt.Sprintf(" --description=%s", "test")
|
||||||
|
@ -350,7 +351,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
|
||||||
tests.WaitForNextNBlocksTM(2, port)
|
tests.WaitForNextNBlocksTM(2, port)
|
||||||
|
|
||||||
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
||||||
require.Equal(t, int64(45), fooAcc.GetCoins().AmountOf("steak").Int64())
|
require.Equal(t, int64(45), fooAcc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom).Int64())
|
||||||
|
|
||||||
proposal1 := executeGetProposal(t, fmt.Sprintf("gaiacli query proposal --proposal-id=1 --output=json %v", flags))
|
proposal1 := executeGetProposal(t, fmt.Sprintf("gaiacli query proposal --proposal-id=1 --output=json %v", flags))
|
||||||
require.Equal(t, uint64(1), proposal1.GetProposalID())
|
require.Equal(t, uint64(1), proposal1.GetProposalID())
|
||||||
|
@ -362,11 +363,11 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
|
||||||
deposit := executeGetDeposit(t,
|
deposit := executeGetDeposit(t,
|
||||||
fmt.Sprintf("gaiacli query deposit --proposal-id=1 --depositer=%s --output=json %v",
|
fmt.Sprintf("gaiacli query deposit --proposal-id=1 --depositer=%s --output=json %v",
|
||||||
fooAddr, flags))
|
fooAddr, flags))
|
||||||
require.Equal(t, int64(5), deposit.Amount.AmountOf("steak").Int64())
|
require.Equal(t, int64(5), deposit.Amount.AmountOf(stakeTypes.DefaultBondDenom).Int64())
|
||||||
|
|
||||||
depositStr := fmt.Sprintf("gaiacli tx deposit %v", flags)
|
depositStr := fmt.Sprintf("gaiacli tx deposit %v", flags)
|
||||||
depositStr += fmt.Sprintf(" --from=%s", "foo")
|
depositStr += fmt.Sprintf(" --from=%s", "foo")
|
||||||
depositStr += fmt.Sprintf(" --deposit=%s", "10steak")
|
depositStr += fmt.Sprintf(" --deposit=%s", fmt.Sprintf("10%s", stakeTypes.DefaultBondDenom))
|
||||||
depositStr += fmt.Sprintf(" --proposal-id=%s", "1")
|
depositStr += fmt.Sprintf(" --proposal-id=%s", "1")
|
||||||
|
|
||||||
// Test generate only
|
// Test generate only
|
||||||
|
@ -386,15 +387,15 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
|
||||||
deposits := executeGetDeposits(t,
|
deposits := executeGetDeposits(t,
|
||||||
fmt.Sprintf("gaiacli query deposits --proposal-id=1 --output=json %v", flags))
|
fmt.Sprintf("gaiacli query deposits --proposal-id=1 --output=json %v", flags))
|
||||||
require.Len(t, deposits, 1)
|
require.Len(t, deposits, 1)
|
||||||
require.Equal(t, int64(15), deposits[0].Amount.AmountOf("steak").Int64())
|
require.Equal(t, int64(15), deposits[0].Amount.AmountOf(stakeTypes.DefaultBondDenom).Int64())
|
||||||
|
|
||||||
deposit = executeGetDeposit(t,
|
deposit = executeGetDeposit(t,
|
||||||
fmt.Sprintf("gaiacli query deposit --proposal-id=1 --depositer=%s --output=json %v",
|
fmt.Sprintf("gaiacli query deposit --proposal-id=1 --depositer=%s --output=json %v",
|
||||||
fooAddr, flags))
|
fooAddr, flags))
|
||||||
require.Equal(t, int64(15), deposit.Amount.AmountOf("steak").Int64())
|
require.Equal(t, int64(15), deposit.Amount.AmountOf(stakeTypes.DefaultBondDenom).Int64())
|
||||||
|
|
||||||
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
||||||
require.Equal(t, int64(35), fooAcc.GetCoins().AmountOf("steak").Int64())
|
require.Equal(t, int64(35), fooAcc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom).Int64())
|
||||||
proposal1 = executeGetProposal(t, fmt.Sprintf("gaiacli query proposal --proposal-id=1 --output=json %v", flags))
|
proposal1 = executeGetProposal(t, fmt.Sprintf("gaiacli query proposal --proposal-id=1 --output=json %v", flags))
|
||||||
require.Equal(t, uint64(1), proposal1.GetProposalID())
|
require.Equal(t, uint64(1), proposal1.GetProposalID())
|
||||||
require.Equal(t, gov.StatusVotingPeriod, proposal1.GetStatus())
|
require.Equal(t, gov.StatusVotingPeriod, proposal1.GetStatus())
|
||||||
|
@ -435,7 +436,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
|
||||||
// submit a second test proposal
|
// submit a second test proposal
|
||||||
spStr = fmt.Sprintf("gaiacli tx submit-proposal %v", flags)
|
spStr = fmt.Sprintf("gaiacli tx submit-proposal %v", flags)
|
||||||
spStr += fmt.Sprintf(" --from=%s", "foo")
|
spStr += fmt.Sprintf(" --from=%s", "foo")
|
||||||
spStr += fmt.Sprintf(" --deposit=%s", "5steak")
|
spStr += fmt.Sprintf(" --deposit=%s", fmt.Sprintf("5%s", stakeTypes.DefaultBondDenom))
|
||||||
spStr += fmt.Sprintf(" --type=%s", "Text")
|
spStr += fmt.Sprintf(" --type=%s", "Text")
|
||||||
spStr += fmt.Sprintf(" --title=%s", "Apples")
|
spStr += fmt.Sprintf(" --title=%s", "Apples")
|
||||||
spStr += fmt.Sprintf(" --description=%s", "test")
|
spStr += fmt.Sprintf(" --description=%s", "test")
|
||||||
|
@ -464,8 +465,8 @@ func TestGaiaCLISendGenerateSignAndBroadcast(t *testing.T) {
|
||||||
|
|
||||||
// Test generate sendTx with default gas
|
// Test generate sendTx with default gas
|
||||||
success, stdout, stderr := executeWriteRetStdStreams(t, fmt.Sprintf(
|
success, stdout, stderr := executeWriteRetStdStreams(t, fmt.Sprintf(
|
||||||
"gaiacli tx send %v --amount=10steak --to=%s --from=foo --generate-only",
|
"gaiacli tx send %v --amount=10%s --to=%s --from=foo --generate-only",
|
||||||
flags, barAddr), []string{}...)
|
flags, stakeTypes.DefaultBondDenom, barAddr), []string{}...)
|
||||||
require.True(t, success)
|
require.True(t, success)
|
||||||
require.Empty(t, stderr)
|
require.Empty(t, stderr)
|
||||||
msg := unmarshalStdTx(t, stdout)
|
msg := unmarshalStdTx(t, stdout)
|
||||||
|
@ -475,8 +476,8 @@ func TestGaiaCLISendGenerateSignAndBroadcast(t *testing.T) {
|
||||||
|
|
||||||
// Test generate sendTx with --gas=$amount
|
// Test generate sendTx with --gas=$amount
|
||||||
success, stdout, stderr = executeWriteRetStdStreams(t, fmt.Sprintf(
|
success, stdout, stderr = executeWriteRetStdStreams(t, fmt.Sprintf(
|
||||||
"gaiacli tx send %v --amount=10steak --to=%s --from=foo --gas=100 --generate-only",
|
"gaiacli tx send %v --amount=10%s --to=%s --from=foo --gas=100 --generate-only",
|
||||||
flags, barAddr), []string{}...)
|
flags, stakeTypes.DefaultBondDenom, barAddr), []string{}...)
|
||||||
require.True(t, success)
|
require.True(t, success)
|
||||||
require.Empty(t, stderr)
|
require.Empty(t, stderr)
|
||||||
msg = unmarshalStdTx(t, stdout)
|
msg = unmarshalStdTx(t, stdout)
|
||||||
|
@ -486,8 +487,8 @@ func TestGaiaCLISendGenerateSignAndBroadcast(t *testing.T) {
|
||||||
|
|
||||||
// Test generate sendTx, estimate gas
|
// Test generate sendTx, estimate gas
|
||||||
success, stdout, stderr = executeWriteRetStdStreams(t, fmt.Sprintf(
|
success, stdout, stderr = executeWriteRetStdStreams(t, fmt.Sprintf(
|
||||||
"gaiacli tx send %v --amount=10steak --to=%s --from=foo --gas=simulate --generate-only",
|
"gaiacli tx send %v --amount=10%s --to=%s --from=foo --gas=simulate --generate-only",
|
||||||
flags, barAddr), []string{}...)
|
flags, stakeTypes.DefaultBondDenom, barAddr), []string{}...)
|
||||||
require.True(t, success)
|
require.True(t, success)
|
||||||
require.NotEmpty(t, stderr)
|
require.NotEmpty(t, stderr)
|
||||||
msg = unmarshalStdTx(t, stdout)
|
msg = unmarshalStdTx(t, stdout)
|
||||||
|
@ -526,7 +527,7 @@ func TestGaiaCLISendGenerateSignAndBroadcast(t *testing.T) {
|
||||||
|
|
||||||
// Test broadcast
|
// Test broadcast
|
||||||
fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
||||||
require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf("steak").Int64())
|
require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom).Int64())
|
||||||
|
|
||||||
success, stdout, _ = executeWriteRetStdStreams(t, fmt.Sprintf(
|
success, stdout, _ = executeWriteRetStdStreams(t, fmt.Sprintf(
|
||||||
"gaiacli tx broadcast %v --json %v", flags, signedTxFile.Name()))
|
"gaiacli tx broadcast %v --json %v", flags, signedTxFile.Name()))
|
||||||
|
@ -540,9 +541,9 @@ func TestGaiaCLISendGenerateSignAndBroadcast(t *testing.T) {
|
||||||
tests.WaitForNextNBlocksTM(2, port)
|
tests.WaitForNextNBlocksTM(2, port)
|
||||||
|
|
||||||
barAcc := executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", barAddr, flags))
|
barAcc := executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", barAddr, flags))
|
||||||
require.Equal(t, int64(10), barAcc.GetCoins().AmountOf("steak").Int64())
|
require.Equal(t, int64(10), barAcc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom).Int64())
|
||||||
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
||||||
require.Equal(t, int64(40), fooAcc.GetCoins().AmountOf("steak").Int64())
|
require.Equal(t, int64(40), fooAcc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom).Int64())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGaiaCLIConfig(t *testing.T) {
|
func TestGaiaCLIConfig(t *testing.T) {
|
||||||
|
|
|
@ -42,6 +42,7 @@ func main() {
|
||||||
rootCmd.AddCommand(gaiaInit.CollectGenTxsCmd(ctx, cdc))
|
rootCmd.AddCommand(gaiaInit.CollectGenTxsCmd(ctx, cdc))
|
||||||
rootCmd.AddCommand(gaiaInit.TestnetFilesCmd(ctx, cdc, server.AppInit{}))
|
rootCmd.AddCommand(gaiaInit.TestnetFilesCmd(ctx, cdc, server.AppInit{}))
|
||||||
rootCmd.AddCommand(gaiaInit.GenTxCmd(ctx, cdc))
|
rootCmd.AddCommand(gaiaInit.GenTxCmd(ctx, cdc))
|
||||||
|
rootCmd.AddCommand(gaiaInit.AddGenesisAccountCmd(ctx, cdc))
|
||||||
|
|
||||||
server.AddCommands(ctx, cdc, rootCmd, appInit,
|
server.AddCommands(ctx, cdc, rootCmd, appInit,
|
||||||
newApp, exportAppStateAndTMValidators)
|
newApp, exportAppStateAndTMValidators)
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
package init
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/cmd/gaia/app"
|
||||||
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
|
"github.com/cosmos/cosmos-sdk/server"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
"github.com/tendermint/tendermint/libs/cli"
|
||||||
|
"github.com/tendermint/tendermint/libs/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddGenesisAccountCmd returns add-genesis-account cobra Command
|
||||||
|
func AddGenesisAccountCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "add-genesis-account [address] [coin][,[coin]]",
|
||||||
|
Short: "Add genesis account to genesis.json",
|
||||||
|
Args: cobra.ExactArgs(2),
|
||||||
|
RunE: func(_ *cobra.Command, args []string) error {
|
||||||
|
config := ctx.Config
|
||||||
|
config.SetRoot(viper.GetString(cli.HomeFlag))
|
||||||
|
|
||||||
|
addr, err := sdk.AccAddressFromBech32(args[0])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
coins, err := sdk.ParseCoins(args[1])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
coins.Sort()
|
||||||
|
|
||||||
|
genFile := config.GenesisFile()
|
||||||
|
if !common.FileExists(genFile) {
|
||||||
|
return fmt.Errorf("%s does not exist, run `gaiad init` first", genFile)
|
||||||
|
}
|
||||||
|
genDoc, err := loadGenesisDoc(cdc, genFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var appState app.GenesisState
|
||||||
|
if err = cdc.UnmarshalJSON(genDoc.AppState, &appState); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
acc := auth.NewBaseAccountWithAddress(addr)
|
||||||
|
acc.Coins = coins
|
||||||
|
appState.Accounts = append(appState.Accounts, app.NewGenesisAccount(&acc))
|
||||||
|
|
||||||
|
appStateJSON, err := cdc.MarshalJSON(appState)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ExportGenesisFile(genFile, genDoc.ChainID, nil, appStateJSON)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.Flags().String(cli.HomeFlag, app.DefaultNodeHome, "node's home directory")
|
||||||
|
return cmd
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ import (
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
|
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
|
||||||
"github.com/cosmos/cosmos-sdk/x/stake/client/cli"
|
"github.com/cosmos/cosmos-sdk/x/stake/client/cli"
|
||||||
|
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
cfg "github.com/tendermint/tendermint/config"
|
cfg "github.com/tendermint/tendermint/config"
|
||||||
|
@ -21,7 +22,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defaultAmount = "100steak"
|
defaultAmount = "100" + stakeTypes.DefaultBondDenom
|
||||||
defaultCommissionRate = "0.1"
|
defaultCommissionRate = "0.1"
|
||||||
defaultCommissionMaxRate = "0.2"
|
defaultCommissionMaxRate = "0.2"
|
||||||
defaultCommissionMaxChangeRate = "0.01"
|
defaultCommissionMaxChangeRate = "0.01"
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||||
authtx "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
|
authtx "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
|
||||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||||
|
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/server"
|
"github.com/cosmos/cosmos-sdk/server"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
@ -75,14 +76,20 @@ Example:
|
||||||
cmd.Flags().String(flagStartingIPAddress, "192.168.0.1",
|
cmd.Flags().String(flagStartingIPAddress, "192.168.0.1",
|
||||||
"Starting IP address (192.168.0.1 results in persistent peers list ID0@192.168.0.1:46656, ID1@192.168.0.2:46656, ...)")
|
"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(client.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created")
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func initTestnet(config *cfg.Config, cdc *codec.Codec) error {
|
func initTestnet(config *cfg.Config, cdc *codec.Codec) error {
|
||||||
|
var chainID string
|
||||||
outDir := viper.GetString(flagOutputDir)
|
outDir := viper.GetString(flagOutputDir)
|
||||||
numValidators := viper.GetInt(flagNumValidators)
|
numValidators := viper.GetInt(flagNumValidators)
|
||||||
|
|
||||||
chainID := "chain-" + cmn.RandStr(6)
|
chainID = viper.GetString(client.FlagChainID)
|
||||||
|
if chainID == "" {
|
||||||
|
chainID = "chain-" + cmn.RandStr(6)
|
||||||
|
}
|
||||||
|
|
||||||
monikers := make([]string, numValidators)
|
monikers := make([]string, numValidators)
|
||||||
nodeIDs := make([]string, numValidators)
|
nodeIDs := make([]string, numValidators)
|
||||||
|
@ -174,14 +181,14 @@ func initTestnet(config *cfg.Config, cdc *codec.Codec) error {
|
||||||
Address: addr,
|
Address: addr,
|
||||||
Coins: sdk.Coins{
|
Coins: sdk.Coins{
|
||||||
sdk.NewInt64Coin(fmt.Sprintf("%sToken", nodeDirName), 1000),
|
sdk.NewInt64Coin(fmt.Sprintf("%sToken", nodeDirName), 1000),
|
||||||
sdk.NewInt64Coin("steak", 150),
|
sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 150),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
msg := stake.NewMsgCreateValidator(
|
msg := stake.NewMsgCreateValidator(
|
||||||
sdk.ValAddress(addr),
|
sdk.ValAddress(addr),
|
||||||
valPubKeys[i],
|
valPubKeys[i],
|
||||||
sdk.NewInt64Coin("steak", 100),
|
sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 100),
|
||||||
stake.NewDescription(nodeDirName, "", "", ""),
|
stake.NewDescription(nodeDirName, "", "", ""),
|
||||||
stake.NewCommissionMsg(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()),
|
stake.NewCommissionMsg(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()),
|
||||||
)
|
)
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||||
)
|
)
|
||||||
|
|
||||||
const stakingToken = "steak"
|
const stakingToken = "stake"
|
||||||
|
|
||||||
const moduleName = "simplestake"
|
const moduleName = "simplestake"
|
||||||
|
|
||||||
|
|
|
@ -75,10 +75,10 @@ func TestBonding(t *testing.T) {
|
||||||
_, _, err := stakeKeeper.unbondWithoutCoins(ctx, addr)
|
_, _, err := stakeKeeper.unbondWithoutCoins(ctx, addr)
|
||||||
require.Equal(t, err, ErrInvalidUnbond(DefaultCodespace))
|
require.Equal(t, err, ErrInvalidUnbond(DefaultCodespace))
|
||||||
|
|
||||||
_, err = stakeKeeper.bondWithoutCoins(ctx, addr, pubKey, sdk.NewInt64Coin("steak", 10))
|
_, err = stakeKeeper.bondWithoutCoins(ctx, addr, pubKey, sdk.NewInt64Coin("stake", 10))
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
power, err := stakeKeeper.bondWithoutCoins(ctx, addr, pubKey, sdk.NewInt64Coin("steak", 10))
|
power, err := stakeKeeper.bondWithoutCoins(ctx, addr, pubKey, sdk.NewInt64Coin("stake", 10))
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
require.Equal(t, int64(20), power)
|
require.Equal(t, int64(20), power)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
###
|
||||||
|
# Find OS and Go environment
|
||||||
|
# GO contains the Go binary
|
||||||
|
# FS contains the OS file separator
|
||||||
|
###
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
GO := $(shell where go.exe 2> NUL)
|
||||||
|
FS := \\
|
||||||
|
else
|
||||||
|
GO := $(shell command -v go 2> /dev/null)
|
||||||
|
FS := /
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(GO),)
|
||||||
|
$(error could not find go. Is it in PATH? $(GO))
|
||||||
|
endif
|
||||||
|
|
||||||
|
GOPATH ?= $(shell $(GO) env GOPATH)
|
||||||
|
GITHUBDIR := $(GOPATH)$(FS)src$(FS)github.com
|
||||||
|
|
||||||
|
###
|
||||||
|
# Functions
|
||||||
|
###
|
||||||
|
|
||||||
|
go_get = $(if $(findstring Windows_NT,$(OS)),\
|
||||||
|
IF NOT EXIST $(GITHUBDIR)$(FS)$(1)$(FS) ( mkdir $(GITHUBDIR)$(FS)$(1) ) else (cd .) &\
|
||||||
|
IF NOT EXIST $(GITHUBDIR)$(FS)$(1)$(FS)$(2)$(FS) ( cd $(GITHUBDIR)$(FS)$(1) && git clone https://github.com/$(1)/$(2) ) else (cd .) &\
|
||||||
|
,\
|
||||||
|
mkdir -p $(GITHUBDIR)$(FS)$(1) &&\
|
||||||
|
(test ! -d $(GITHUBDIR)$(FS)$(1)$(FS)$(2) && cd $(GITHUBDIR)$(FS)$(1) && git clone https://github.com/$(1)/$(2)) || true &&\
|
||||||
|
)\
|
||||||
|
cd $(GITHUBDIR)$(FS)$(1)$(FS)$(2) && git fetch origin && git checkout -q $(3)
|
||||||
|
|
||||||
|
go_install = $(call go_get,$(1),$(2),$(3)) && cd $(GITHUBDIR)$(FS)$(1)$(FS)$(2) && $(GO) install
|
||||||
|
|
||||||
|
###
|
||||||
|
# get_tools
|
||||||
|
###
|
||||||
|
all: get_tools
|
||||||
|
get_tools: dep gometalinter statik
|
||||||
|
|
||||||
|
dep:
|
||||||
|
$(call go_get,golang,dep,22125cfaa6ddc71e145b1535d4b7ee9744fefff2)
|
||||||
|
cd $(GITHUBDIR)$(FS)golang$(FS)dep$(FS)cmd$(FS)dep && $(GO) install
|
||||||
|
|
||||||
|
#v2.0.11
|
||||||
|
gometalinter:
|
||||||
|
$(call go_install,alecthomas,gometalinter,17a7ffa42374937bfecabfb8d2efbd4db0c26741)
|
||||||
|
|
||||||
|
statik:
|
||||||
|
$(call go_install,rakyll,statik,v0.1.5)
|
||||||
|
|
||||||
|
.PHONY: all get_tools dep gometalinter statik
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# This file downloads all of the binary dependencies we have, and checks out a
|
|
||||||
# specific git hash.
|
|
||||||
#
|
|
||||||
# repos it installs:
|
|
||||||
# github.com/golang/dep/cmd/dep
|
|
||||||
# gopkg.in/alecthomas/gometalinter.v2
|
|
||||||
# github.com/rakyll/statiik
|
|
||||||
|
|
||||||
## check if GOPATH is set
|
|
||||||
if [ -z ${GOPATH+x} ]; then
|
|
||||||
echo "please set GOPATH (https://github.com/golang/go/wiki/SettingGOPATH)"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
mkdir -p "$GOPATH/src/github.com"
|
|
||||||
cd "$GOPATH/src/github.com" || exit 1
|
|
||||||
|
|
||||||
installFromGithub() {
|
|
||||||
repo=$1
|
|
||||||
commit=$2
|
|
||||||
# optional
|
|
||||||
subdir=$3
|
|
||||||
echo "--> Installing $repo ($commit)..."
|
|
||||||
if [ ! -d "$repo" ]; then
|
|
||||||
mkdir -p "$repo"
|
|
||||||
git clone "https://github.com/$repo.git" "$repo"
|
|
||||||
fi
|
|
||||||
if [ ! -z ${subdir+x} ] && [ ! -d "$repo/$subdir" ]; then
|
|
||||||
echo "ERROR: no such directory $repo/$subdir"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
pushd "$repo" && \
|
|
||||||
git fetch origin && \
|
|
||||||
git checkout -q "$commit" && \
|
|
||||||
if [ ! -z ${subdir+x} ]; then cd "$subdir" || exit 1; fi && \
|
|
||||||
go install && \
|
|
||||||
if [ ! -z ${subdir+x} ]; then cd - || exit 1; fi && \
|
|
||||||
popd || exit 1
|
|
||||||
echo "--> Done"
|
|
||||||
echo ""
|
|
||||||
}
|
|
||||||
|
|
||||||
installFromGithub golang/dep 22125cfaa6ddc71e145b1535d4b7ee9744fefff2 cmd/dep
|
|
||||||
## gometalinter v2.0.11
|
|
||||||
installFromGithub alecthomas/gometalinter 17a7ffa42374937bfecabfb8d2efbd4db0c26741
|
|
||||||
installFromGithub rakyll/statik v0.1.5
|
|
|
@ -17,7 +17,7 @@ echo "Using temporary log directory: $tmpdir"
|
||||||
sim() {
|
sim() {
|
||||||
seed=$1
|
seed=$1
|
||||||
echo "Running full Gaia simulation with seed $seed. This may take awhile!"
|
echo "Running full Gaia simulation with seed $seed. This may take awhile!"
|
||||||
file="$tmpdir/gaia-simulation-seed-$seed-date-$(date -Iseconds -u).stdout"
|
file="$tmpdir/gaia-simulation-seed-$seed-date-$(date -u +"%Y-%m-%dT%H:%M:%S+00:00").stdout"
|
||||||
echo "Writing stdout to $file..."
|
echo "Writing stdout to $file..."
|
||||||
go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=$blocks \
|
go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=$blocks \
|
||||||
-SimulationVerbose=true -SimulationCommit=true -SimulationSeed=$seed -v -timeout 24h > $file
|
-SimulationVerbose=true -SimulationCommit=true -SimulationSeed=$seed -v -timeout 24h > $file
|
||||||
|
|
|
@ -63,17 +63,17 @@ func ShowValidatorCmd(ctx *Context) *cobra.Command {
|
||||||
func ShowAddressCmd(ctx *Context) *cobra.Command {
|
func ShowAddressCmd(ctx *Context) *cobra.Command {
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "show-address",
|
Use: "show-address",
|
||||||
Short: "Shows this node's tendermint validator address",
|
Short: "Shows this node's tendermint validator consensus address",
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
cfg := ctx.Config
|
cfg := ctx.Config
|
||||||
privValidator := pvm.LoadOrGenFilePV(cfg.PrivValidatorFile())
|
privValidator := pvm.LoadOrGenFilePV(cfg.PrivValidatorFile())
|
||||||
valAddr := (sdk.ValAddress)(privValidator.Address)
|
valConsAddr := (sdk.ConsAddress)(privValidator.Address)
|
||||||
|
|
||||||
if viper.GetBool(client.FlagJson) {
|
if viper.GetBool(client.FlagJson) {
|
||||||
return printlnJSON(valAddr)
|
return printlnJSON(valConsAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println(valAddr.String())
|
fmt.Println(valConsAddr.String())
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
@ -92,7 +93,7 @@ func interceptLoadConfig() (conf *cfg.Config, err error) {
|
||||||
conf.P2P.RecvRate = 5120000
|
conf.P2P.RecvRate = 5120000
|
||||||
conf.P2P.SendRate = 5120000
|
conf.P2P.SendRate = 5120000
|
||||||
conf.TxIndex.IndexAllTags = true
|
conf.TxIndex.IndexAllTags = true
|
||||||
conf.Consensus.TimeoutCommit = 5000
|
conf.Consensus.TimeoutCommit = 5 * time.Second
|
||||||
cfg.WriteConfigFile(configFilePath, conf)
|
cfg.WriteConfigFile(configFilePath, conf)
|
||||||
// Fall through, just so that its parsed into memory.
|
// Fall through, just so that its parsed into memory.
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,8 +49,8 @@ func TestSameDenomAsCoin(t *testing.T) {
|
||||||
{NewInt64Coin("A", 1), NewInt64Coin("A", 1), true},
|
{NewInt64Coin("A", 1), NewInt64Coin("A", 1), true},
|
||||||
{NewInt64Coin("A", 1), NewInt64Coin("a", 1), false},
|
{NewInt64Coin("A", 1), NewInt64Coin("a", 1), false},
|
||||||
{NewInt64Coin("a", 1), NewInt64Coin("b", 1), false},
|
{NewInt64Coin("a", 1), NewInt64Coin("b", 1), false},
|
||||||
{NewInt64Coin("steak", 1), NewInt64Coin("steak", 10), true},
|
{NewInt64Coin("stake", 1), NewInt64Coin("stake", 10), true},
|
||||||
{NewInt64Coin("steak", -11), NewInt64Coin("steak", 10), true},
|
{NewInt64Coin("stake", -11), NewInt64Coin("stake", 10), true},
|
||||||
}
|
}
|
||||||
|
|
||||||
for tcIndex, tc := range cases {
|
for tcIndex, tc := range cases {
|
||||||
|
@ -107,8 +107,8 @@ func TestIsEqualCoin(t *testing.T) {
|
||||||
{NewInt64Coin("A", 1), NewInt64Coin("A", 1), true},
|
{NewInt64Coin("A", 1), NewInt64Coin("A", 1), true},
|
||||||
{NewInt64Coin("A", 1), NewInt64Coin("a", 1), false},
|
{NewInt64Coin("A", 1), NewInt64Coin("a", 1), false},
|
||||||
{NewInt64Coin("a", 1), NewInt64Coin("b", 1), false},
|
{NewInt64Coin("a", 1), NewInt64Coin("b", 1), false},
|
||||||
{NewInt64Coin("steak", 1), NewInt64Coin("steak", 10), false},
|
{NewInt64Coin("stake", 1), NewInt64Coin("stake", 10), false},
|
||||||
{NewInt64Coin("steak", -11), NewInt64Coin("steak", 10), false},
|
{NewInt64Coin("stake", -11), NewInt64Coin("stake", 10), false},
|
||||||
}
|
}
|
||||||
|
|
||||||
for tcIndex, tc := range cases {
|
for tcIndex, tc := range cases {
|
||||||
|
|
|
@ -21,8 +21,8 @@ func TestSortJSON(t *testing.T) {
|
||||||
want: "",
|
want: "",
|
||||||
wantErr: true},
|
wantErr: true},
|
||||||
// genesis.json
|
// genesis.json
|
||||||
{unsortedJSON: `{"consensus_params":{"block_size_params":{"max_bytes":22020096,"max_txs":100000,"max_gas":-1},"tx_size_params":{"max_bytes":10240,"max_gas":-1},"block_gossip_params":{"block_part_size_bytes":65536},"evidence_params":{"max_age":100000}},"validators":[{"pub_key":{"type":"AC26791624DE60","value":"c7UMMAbjFuc5GhGPy0E5q5tefy12p9Tq0imXqdrKXwo="},"power":100,"name":""}],"app_hash":"","genesis_time":"2018-05-11T15:52:25.424795506Z","chain_id":"test-chain-Q6VeoW","app_state":{"accounts":[{"address":"718C9C23F98C9642569742ADDD9F9AB9743FBD5D","coins":[{"denom":"Token","amount":1000},{"denom":"steak","amount":50}]}],"stake":{"pool":{"total_supply":50,"bonded_shares":"0","unbonded_shares":"0","bonded_pool":0,"unbonded_pool":0,"inflation_last_time":0,"inflation":"7/100"},"params":{"inflation_rate_change":"13/100","inflation_max":"1/5","inflation_min":"7/100","goal_bonded":"67/100","max_validators":100,"bond_denom":"steak"},"candidates":null,"bonds":null}}}`,
|
{unsortedJSON: `{"consensus_params":{"block_size_params":{"max_bytes":22020096,"max_txs":100000,"max_gas":-1},"tx_size_params":{"max_bytes":10240,"max_gas":-1},"block_gossip_params":{"block_part_size_bytes":65536},"evidence_params":{"max_age":100000}},"validators":[{"pub_key":{"type":"AC26791624DE60","value":"c7UMMAbjFuc5GhGPy0E5q5tefy12p9Tq0imXqdrKXwo="},"power":100,"name":""}],"app_hash":"","genesis_time":"2018-05-11T15:52:25.424795506Z","chain_id":"test-chain-Q6VeoW","app_state":{"accounts":[{"address":"718C9C23F98C9642569742ADDD9F9AB9743FBD5D","coins":[{"denom":"Token","amount":1000},{"denom":"stake","amount":50}]}],"stake":{"pool":{"total_supply":50,"bonded_shares":"0","unbonded_shares":"0","bonded_pool":0,"unbonded_pool":0,"inflation_last_time":0,"inflation":"7/100"},"params":{"inflation_rate_change":"13/100","inflation_max":"1/5","inflation_min":"7/100","goal_bonded":"67/100","max_validators":100,"bond_denom":"stake"},"candidates":null,"bonds":null}}}`,
|
||||||
want: `{"app_hash":"","app_state":{"accounts":[{"address":"718C9C23F98C9642569742ADDD9F9AB9743FBD5D","coins":[{"amount":1000,"denom":"Token"},{"amount":50,"denom":"steak"}]}],"stake":{"bonds":null,"candidates":null,"params":{"bond_denom":"steak","goal_bonded":"67/100","inflation_max":"1/5","inflation_min":"7/100","inflation_rate_change":"13/100","max_validators":100},"pool":{"bonded_pool":0,"bonded_shares":"0","inflation":"7/100","inflation_last_time":0,"total_supply":50,"unbonded_pool":0,"unbonded_shares":"0"}}},"chain_id":"test-chain-Q6VeoW","consensus_params":{"block_gossip_params":{"block_part_size_bytes":65536},"block_size_params":{"max_bytes":22020096,"max_gas":-1,"max_txs":100000},"evidence_params":{"max_age":100000},"tx_size_params":{"max_bytes":10240,"max_gas":-1}},"genesis_time":"2018-05-11T15:52:25.424795506Z","validators":[{"name":"","power":100,"pub_key":{"type":"AC26791624DE60","value":"c7UMMAbjFuc5GhGPy0E5q5tefy12p9Tq0imXqdrKXwo="}}]}`,
|
want: `{"app_hash":"","app_state":{"accounts":[{"address":"718C9C23F98C9642569742ADDD9F9AB9743FBD5D","coins":[{"amount":1000,"denom":"Token"},{"amount":50,"denom":"stake"}]}],"stake":{"bonds":null,"candidates":null,"params":{"bond_denom":"stake","goal_bonded":"67/100","inflation_max":"1/5","inflation_min":"7/100","inflation_rate_change":"13/100","max_validators":100},"pool":{"bonded_pool":0,"bonded_shares":"0","inflation":"7/100","inflation_last_time":0,"total_supply":50,"unbonded_pool":0,"unbonded_shares":"0"}}},"chain_id":"test-chain-Q6VeoW","consensus_params":{"block_gossip_params":{"block_part_size_bytes":65536},"block_size_params":{"max_bytes":22020096,"max_gas":-1,"max_txs":100000},"evidence_params":{"max_age":100000},"tx_size_params":{"max_bytes":10240,"max_gas":-1}},"genesis_time":"2018-05-11T15:52:25.424795506Z","validators":[{"name":"","power":100,"pub_key":{"type":"AC26791624DE60","value":"c7UMMAbjFuc5GhGPy0E5q5tefy12p9Tq0imXqdrKXwo="}}]}`,
|
||||||
wantErr: false},
|
wantErr: false},
|
||||||
// from the TXSpec:
|
// from the TXSpec:
|
||||||
{unsortedJSON: `{"chain_id":"test-chain-1","sequence":1,"fee_bytes":{"amount":[{"amount":5,"denom":"photon"}],"gas":10000},"msg_bytes":{"inputs":[{"address":"696E707574","coins":[{"amount":10,"denom":"atom"}]}],"outputs":[{"address":"6F7574707574","coins":[{"amount":10,"denom":"atom"}]}]},"alt_bytes":null}`,
|
{unsortedJSON: `{"chain_id":"test-chain-1","sequence":1,"fee_bytes":{"amount":[{"amount":5,"denom":"photon"}],"gas":10000},"msg_bytes":{"inputs":[{"address":"696E707574","coins":[{"amount":10,"denom":"atom"}]}],"outputs":[{"address":"6F7574707574","coins":[{"amount":10,"denom":"atom"}]}]},"alt_bytes":null}`,
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||||
"github.com/tendermint/tendermint/crypto/ed25519"
|
"github.com/tendermint/tendermint/crypto/ed25519"
|
||||||
|
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -46,7 +47,7 @@ func TestTxBuilderBuild(t *testing.T) {
|
||||||
SimulateGas: false,
|
SimulateGas: false,
|
||||||
ChainID: "test-chain",
|
ChainID: "test-chain",
|
||||||
Memo: "hello",
|
Memo: "hello",
|
||||||
Fee: "1steak",
|
Fee: "1" + stakeTypes.DefaultBondDenom,
|
||||||
},
|
},
|
||||||
defaultMsg,
|
defaultMsg,
|
||||||
StdSignMsg{
|
StdSignMsg{
|
||||||
|
@ -55,7 +56,7 @@ func TestTxBuilderBuild(t *testing.T) {
|
||||||
Sequence: 1,
|
Sequence: 1,
|
||||||
Memo: "hello",
|
Memo: "hello",
|
||||||
Msgs: defaultMsg,
|
Msgs: defaultMsg,
|
||||||
Fee: auth.NewStdFee(100, sdk.NewCoin("steak", sdk.NewInt(1))),
|
Fee: auth.NewStdFee(100, sdk.NewCoin(stakeTypes.DefaultBondDenom, sdk.NewInt(1))),
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
|
|
|
@ -15,41 +15,40 @@ const (
|
||||||
costAddCoins sdk.Gas = 10
|
costAddCoins sdk.Gas = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Keeper
|
||||||
|
|
||||||
|
var _ Keeper = (*BaseKeeper)(nil)
|
||||||
|
|
||||||
// Keeper defines a module interface that facilitates the transfer of coins
|
// Keeper defines a module interface that facilitates the transfer of coins
|
||||||
// between accounts.
|
// between accounts.
|
||||||
type Keeper interface {
|
type Keeper interface {
|
||||||
SendKeeper
|
SendKeeper
|
||||||
|
|
||||||
SetCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) sdk.Error
|
SetCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) sdk.Error
|
||||||
SubtractCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, sdk.Tags, sdk.Error)
|
SubtractCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, sdk.Tags, sdk.Error)
|
||||||
AddCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, sdk.Tags, sdk.Error)
|
AddCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, sdk.Tags, sdk.Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ Keeper = (*BaseKeeper)(nil)
|
|
||||||
|
|
||||||
// BaseKeeper manages transfers between accounts. It implements the Keeper
|
// BaseKeeper manages transfers between accounts. It implements the Keeper
|
||||||
// interface.
|
// interface.
|
||||||
type BaseKeeper struct {
|
type BaseKeeper struct {
|
||||||
am auth.AccountKeeper
|
BaseSendKeeper
|
||||||
|
|
||||||
|
ak auth.AccountKeeper
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBaseKeeper returns a new BaseKeeper
|
// NewBaseKeeper returns a new BaseKeeper
|
||||||
func NewBaseKeeper(am auth.AccountKeeper) BaseKeeper {
|
func NewBaseKeeper(ak auth.AccountKeeper) BaseKeeper {
|
||||||
return BaseKeeper{am: am}
|
return BaseKeeper{
|
||||||
}
|
BaseSendKeeper: NewBaseSendKeeper(ak),
|
||||||
|
ak: ak,
|
||||||
// GetCoins returns the coins at the addr.
|
}
|
||||||
func (keeper BaseKeeper) GetCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins {
|
|
||||||
return getCoins(ctx, keeper.am, addr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetCoins sets the coins at the addr.
|
// SetCoins sets the coins at the addr.
|
||||||
func (keeper BaseKeeper) SetCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) sdk.Error {
|
func (keeper BaseKeeper) SetCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) sdk.Error {
|
||||||
return setCoins(ctx, keeper.am, addr, amt)
|
return setCoins(ctx, keeper.ak, addr, amt)
|
||||||
}
|
|
||||||
|
|
||||||
// HasCoins returns whether or not an account has at least amt coins.
|
|
||||||
func (keeper BaseKeeper) HasCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) bool {
|
|
||||||
return hasCoins(ctx, keeper.am, addr, amt)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SubtractCoins subtracts amt from the coins at the addr.
|
// SubtractCoins subtracts amt from the coins at the addr.
|
||||||
|
@ -57,7 +56,7 @@ func (keeper BaseKeeper) SubtractCoins(
|
||||||
ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins,
|
ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins,
|
||||||
) (sdk.Coins, sdk.Tags, sdk.Error) {
|
) (sdk.Coins, sdk.Tags, sdk.Error) {
|
||||||
|
|
||||||
return subtractCoins(ctx, keeper.am, addr, amt)
|
return subtractCoins(ctx, keeper.ak, addr, amt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddCoins adds amt to the coins at the addr.
|
// AddCoins adds amt to the coins at the addr.
|
||||||
|
@ -65,28 +64,17 @@ func (keeper BaseKeeper) AddCoins(
|
||||||
ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins,
|
ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins,
|
||||||
) (sdk.Coins, sdk.Tags, sdk.Error) {
|
) (sdk.Coins, sdk.Tags, sdk.Error) {
|
||||||
|
|
||||||
return addCoins(ctx, keeper.am, addr, amt)
|
return addCoins(ctx, keeper.ak, addr, amt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendCoins moves coins from one account to another
|
//-----------------------------------------------------------------------------
|
||||||
func (keeper BaseKeeper) SendCoins(
|
// Send Keeper
|
||||||
ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins,
|
|
||||||
) (sdk.Tags, sdk.Error) {
|
|
||||||
|
|
||||||
return sendCoins(ctx, keeper.am, fromAddr, toAddr, amt)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InputOutputCoins handles a list of inputs and outputs
|
|
||||||
func (keeper BaseKeeper) InputOutputCoins(ctx sdk.Context, inputs []Input, outputs []Output) (sdk.Tags, sdk.Error) {
|
|
||||||
return inputOutputCoins(ctx, keeper.am, inputs, outputs)
|
|
||||||
}
|
|
||||||
|
|
||||||
//______________________________________________________________________________________________
|
|
||||||
|
|
||||||
// SendKeeper defines a module interface that facilitates the transfer of coins
|
// SendKeeper defines a module interface that facilitates the transfer of coins
|
||||||
// between accounts without the possibility of creating coins.
|
// between accounts without the possibility of creating coins.
|
||||||
type SendKeeper interface {
|
type SendKeeper interface {
|
||||||
ViewKeeper
|
ViewKeeper
|
||||||
|
|
||||||
SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) (sdk.Tags, sdk.Error)
|
SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) (sdk.Tags, sdk.Error)
|
||||||
InputOutputCoins(ctx sdk.Context, inputs []Input, outputs []Output) (sdk.Tags, sdk.Error)
|
InputOutputCoins(ctx sdk.Context, inputs []Input, outputs []Output) (sdk.Tags, sdk.Error)
|
||||||
}
|
}
|
||||||
|
@ -96,22 +84,17 @@ var _ SendKeeper = (*BaseSendKeeper)(nil)
|
||||||
// SendKeeper only allows transfers between accounts without the possibility of
|
// SendKeeper only allows transfers between accounts without the possibility of
|
||||||
// creating coins. It implements the SendKeeper interface.
|
// creating coins. It implements the SendKeeper interface.
|
||||||
type BaseSendKeeper struct {
|
type BaseSendKeeper struct {
|
||||||
am auth.AccountKeeper
|
BaseViewKeeper
|
||||||
|
|
||||||
|
ak auth.AccountKeeper
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBaseSendKeeper returns a new BaseSendKeeper.
|
// NewBaseSendKeeper returns a new BaseSendKeeper.
|
||||||
func NewBaseSendKeeper(am auth.AccountKeeper) BaseSendKeeper {
|
func NewBaseSendKeeper(ak auth.AccountKeeper) BaseSendKeeper {
|
||||||
return BaseSendKeeper{am: am}
|
return BaseSendKeeper{
|
||||||
}
|
BaseViewKeeper: NewBaseViewKeeper(ak),
|
||||||
|
ak: ak,
|
||||||
// GetCoins returns the coins at the addr.
|
}
|
||||||
func (keeper BaseSendKeeper) GetCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins {
|
|
||||||
return getCoins(ctx, keeper.am, addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasCoins returns whether or not an account has at least amt coins.
|
|
||||||
func (keeper BaseSendKeeper) HasCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) bool {
|
|
||||||
return hasCoins(ctx, keeper.am, addr, amt)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendCoins moves coins from one account to another
|
// SendCoins moves coins from one account to another
|
||||||
|
@ -119,7 +102,7 @@ func (keeper BaseSendKeeper) SendCoins(
|
||||||
ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins,
|
ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins,
|
||||||
) (sdk.Tags, sdk.Error) {
|
) (sdk.Tags, sdk.Error) {
|
||||||
|
|
||||||
return sendCoins(ctx, keeper.am, fromAddr, toAddr, amt)
|
return sendCoins(ctx, keeper.ak, fromAddr, toAddr, amt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// InputOutputCoins handles a list of inputs and outputs
|
// InputOutputCoins handles a list of inputs and outputs
|
||||||
|
@ -127,10 +110,13 @@ func (keeper BaseSendKeeper) InputOutputCoins(
|
||||||
ctx sdk.Context, inputs []Input, outputs []Output,
|
ctx sdk.Context, inputs []Input, outputs []Output,
|
||||||
) (sdk.Tags, sdk.Error) {
|
) (sdk.Tags, sdk.Error) {
|
||||||
|
|
||||||
return inputOutputCoins(ctx, keeper.am, inputs, outputs)
|
return inputOutputCoins(ctx, keeper.ak, inputs, outputs)
|
||||||
}
|
}
|
||||||
|
|
||||||
//______________________________________________________________________________________________
|
//-----------------------------------------------------------------------------
|
||||||
|
// View Keeper
|
||||||
|
|
||||||
|
var _ ViewKeeper = (*BaseViewKeeper)(nil)
|
||||||
|
|
||||||
// ViewKeeper defines a module interface that facilitates read only access to
|
// ViewKeeper defines a module interface that facilitates read only access to
|
||||||
// account balances.
|
// account balances.
|
||||||
|
@ -139,29 +125,29 @@ type ViewKeeper interface {
|
||||||
HasCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) bool
|
HasCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ ViewKeeper = (*BaseViewKeeper)(nil)
|
|
||||||
|
|
||||||
// BaseViewKeeper implements a read only keeper implementation of ViewKeeper.
|
// BaseViewKeeper implements a read only keeper implementation of ViewKeeper.
|
||||||
type BaseViewKeeper struct {
|
type BaseViewKeeper struct {
|
||||||
am auth.AccountKeeper
|
ak auth.AccountKeeper
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBaseViewKeeper returns a new BaseViewKeeper.
|
// NewBaseViewKeeper returns a new BaseViewKeeper.
|
||||||
func NewBaseViewKeeper(am auth.AccountKeeper) BaseViewKeeper {
|
func NewBaseViewKeeper(ak auth.AccountKeeper) BaseViewKeeper {
|
||||||
return BaseViewKeeper{am: am}
|
return BaseViewKeeper{
|
||||||
|
ak: ak,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCoins returns the coins at the addr.
|
// GetCoins returns the coins at the addr.
|
||||||
func (keeper BaseViewKeeper) GetCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins {
|
func (keeper BaseViewKeeper) GetCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins {
|
||||||
return getCoins(ctx, keeper.am, addr)
|
return getCoins(ctx, keeper.ak, addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasCoins returns whether or not an account has at least amt coins.
|
// HasCoins returns whether or not an account has at least amt coins.
|
||||||
func (keeper BaseViewKeeper) HasCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) bool {
|
func (keeper BaseViewKeeper) HasCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) bool {
|
||||||
return hasCoins(ctx, keeper.am, addr, amt)
|
return hasCoins(ctx, keeper.ak, addr, amt)
|
||||||
}
|
}
|
||||||
|
|
||||||
//______________________________________________________________________________________________
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
func getCoins(ctx sdk.Context, am auth.AccountKeeper, addr sdk.AccAddress) sdk.Coins {
|
func getCoins(ctx sdk.Context, am auth.AccountKeeper, addr sdk.AccAddress) sdk.Coins {
|
||||||
ctx.GasMeter().ConsumeGas(costGetCoins, "getCoins")
|
ctx.GasMeter().ConsumeGas(costGetCoins, "getCoins")
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -20,7 +21,7 @@ func TestTickExpiredDepositPeriod(t *testing.T) {
|
||||||
require.False(t, inactiveQueue.Valid())
|
require.False(t, inactiveQueue.Valid())
|
||||||
inactiveQueue.Close()
|
inactiveQueue.Close()
|
||||||
|
|
||||||
newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin("steak", 5)})
|
newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 5)})
|
||||||
|
|
||||||
res := govHandler(ctx, newProposalMsg)
|
res := govHandler(ctx, newProposalMsg)
|
||||||
require.True(t, res.IsOK())
|
require.True(t, res.IsOK())
|
||||||
|
@ -62,7 +63,7 @@ func TestTickMultipleExpiredDepositPeriod(t *testing.T) {
|
||||||
require.False(t, inactiveQueue.Valid())
|
require.False(t, inactiveQueue.Valid())
|
||||||
inactiveQueue.Close()
|
inactiveQueue.Close()
|
||||||
|
|
||||||
newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin("steak", 5)})
|
newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 5)})
|
||||||
|
|
||||||
res := govHandler(ctx, newProposalMsg)
|
res := govHandler(ctx, newProposalMsg)
|
||||||
require.True(t, res.IsOK())
|
require.True(t, res.IsOK())
|
||||||
|
@ -79,7 +80,7 @@ func TestTickMultipleExpiredDepositPeriod(t *testing.T) {
|
||||||
require.False(t, inactiveQueue.Valid())
|
require.False(t, inactiveQueue.Valid())
|
||||||
inactiveQueue.Close()
|
inactiveQueue.Close()
|
||||||
|
|
||||||
newProposalMsg2 := NewMsgSubmitProposal("Test2", "test2", ProposalTypeText, addrs[1], sdk.Coins{sdk.NewInt64Coin("steak", 5)})
|
newProposalMsg2 := NewMsgSubmitProposal("Test2", "test2", ProposalTypeText, addrs[1], sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 5)})
|
||||||
res = govHandler(ctx, newProposalMsg2)
|
res = govHandler(ctx, newProposalMsg2)
|
||||||
require.True(t, res.IsOK())
|
require.True(t, res.IsOK())
|
||||||
|
|
||||||
|
@ -121,7 +122,7 @@ func TestTickPassedDepositPeriod(t *testing.T) {
|
||||||
require.False(t, activeQueue.Valid())
|
require.False(t, activeQueue.Valid())
|
||||||
activeQueue.Close()
|
activeQueue.Close()
|
||||||
|
|
||||||
newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin("steak", 5)})
|
newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 5)})
|
||||||
|
|
||||||
res := govHandler(ctx, newProposalMsg)
|
res := govHandler(ctx, newProposalMsg)
|
||||||
require.True(t, res.IsOK())
|
require.True(t, res.IsOK())
|
||||||
|
@ -140,7 +141,7 @@ func TestTickPassedDepositPeriod(t *testing.T) {
|
||||||
require.False(t, inactiveQueue.Valid())
|
require.False(t, inactiveQueue.Valid())
|
||||||
inactiveQueue.Close()
|
inactiveQueue.Close()
|
||||||
|
|
||||||
newDepositMsg := NewMsgDeposit(addrs[1], proposalID, sdk.Coins{sdk.NewInt64Coin("steak", 5)})
|
newDepositMsg := NewMsgDeposit(addrs[1], proposalID, sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 5)})
|
||||||
res = govHandler(ctx, newDepositMsg)
|
res = govHandler(ctx, newDepositMsg)
|
||||||
require.True(t, res.IsOK())
|
require.True(t, res.IsOK())
|
||||||
|
|
||||||
|
@ -163,7 +164,7 @@ func TestTickPassedVotingPeriod(t *testing.T) {
|
||||||
require.False(t, activeQueue.Valid())
|
require.False(t, activeQueue.Valid())
|
||||||
activeQueue.Close()
|
activeQueue.Close()
|
||||||
|
|
||||||
newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin("steak", 5)})
|
newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 5)})
|
||||||
|
|
||||||
res := govHandler(ctx, newProposalMsg)
|
res := govHandler(ctx, newProposalMsg)
|
||||||
require.True(t, res.IsOK())
|
require.True(t, res.IsOK())
|
||||||
|
@ -174,7 +175,7 @@ func TestTickPassedVotingPeriod(t *testing.T) {
|
||||||
newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second)
|
newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second)
|
||||||
ctx = ctx.WithBlockHeader(newHeader)
|
ctx = ctx.WithBlockHeader(newHeader)
|
||||||
|
|
||||||
newDepositMsg := NewMsgDeposit(addrs[1], proposalID, sdk.Coins{sdk.NewInt64Coin("steak", 5)})
|
newDepositMsg := NewMsgDeposit(addrs[1], proposalID, sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 5)})
|
||||||
res = govHandler(ctx, newDepositMsg)
|
res = govHandler(ctx, newDepositMsg)
|
||||||
require.True(t, res.IsOK())
|
require.True(t, res.IsOK())
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GenesisState - all staking state that must be provided at genesis
|
// GenesisState - all staking state that must be provided at genesis
|
||||||
|
@ -43,7 +44,7 @@ func DefaultGenesisState() GenesisState {
|
||||||
return GenesisState{
|
return GenesisState{
|
||||||
StartingProposalID: 1,
|
StartingProposalID: 1,
|
||||||
DepositParams: DepositParams{
|
DepositParams: DepositParams{
|
||||||
MinDeposit: sdk.Coins{sdk.NewInt64Coin("steak", 10)},
|
MinDeposit: sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 10)},
|
||||||
MaxDepositPeriod: time.Duration(172800) * time.Second,
|
MaxDepositPeriod: time.Duration(172800) * time.Second,
|
||||||
},
|
},
|
||||||
VotingParams: VotingParams{
|
VotingParams: VotingParams{
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetSetProposal(t *testing.T) {
|
func TestGetSetProposal(t *testing.T) {
|
||||||
|
@ -69,14 +70,14 @@ func TestDeposits(t *testing.T) {
|
||||||
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||||
proposalID := proposal.GetProposalID()
|
proposalID := proposal.GetProposalID()
|
||||||
|
|
||||||
fourSteak := sdk.Coins{sdk.NewInt64Coin("steak", 4)}
|
fourSteak := sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 4)}
|
||||||
fiveSteak := sdk.Coins{sdk.NewInt64Coin("steak", 5)}
|
fiveSteak := sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 5)}
|
||||||
|
|
||||||
addr0Initial := keeper.ck.GetCoins(ctx, addrs[0])
|
addr0Initial := keeper.ck.GetCoins(ctx, addrs[0])
|
||||||
addr1Initial := keeper.ck.GetCoins(ctx, addrs[1])
|
addr1Initial := keeper.ck.GetCoins(ctx, addrs[1])
|
||||||
|
|
||||||
// require.True(t, addr0Initial.IsEqual(sdk.Coins{sdk.NewInt64Coin("steak", 42)}))
|
// require.True(t, addr0Initial.IsEqual(sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 42)}))
|
||||||
require.Equal(t, sdk.Coins{sdk.NewInt64Coin("steak", 42)}, addr0Initial)
|
require.Equal(t, sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 42)}, addr0Initial)
|
||||||
|
|
||||||
require.True(t, proposal.GetTotalDeposit().IsEqual(sdk.Coins{}))
|
require.True(t, proposal.GetTotalDeposit().IsEqual(sdk.Coins{}))
|
||||||
|
|
||||||
|
|
|
@ -7,16 +7,21 @@ import (
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/cosmos/cosmos-sdk/x/mock"
|
"github.com/cosmos/cosmos-sdk/x/mock"
|
||||||
|
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
coinsPos = sdk.Coins{sdk.NewInt64Coin("steak", 1000)}
|
coinsPos = sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 1000)}
|
||||||
coinsZero = sdk.Coins{}
|
coinsZero = sdk.Coins{}
|
||||||
coinsNeg = sdk.Coins{sdk.NewInt64Coin("steak", -10000)}
|
coinsNeg = sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, -10000)}
|
||||||
coinsPosNotAtoms = sdk.Coins{sdk.NewInt64Coin("foo", 10000)}
|
coinsPosNotAtoms = sdk.Coins{sdk.NewInt64Coin("foo", 10000)}
|
||||||
coinsMulti = sdk.Coins{sdk.NewInt64Coin("foo", 10000), sdk.NewInt64Coin("steak", 1000)}
|
coinsMulti = sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 1000), sdk.NewInt64Coin("foo", 10000)}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
coinsMulti.Sort()
|
||||||
|
}
|
||||||
|
|
||||||
// test ValidateBasic for MsgCreateValidator
|
// test ValidateBasic for MsgCreateValidator
|
||||||
func TestMsgSubmitProposal(t *testing.T) {
|
func TestMsgSubmitProposal(t *testing.T) {
|
||||||
_, addrs, _, _ := mock.CreateGenAccounts(1, sdk.Coins{})
|
_, addrs, _, _ := mock.CreateGenAccounts(1, sdk.Coins{})
|
||||||
|
@ -42,9 +47,9 @@ func TestMsgSubmitProposal(t *testing.T) {
|
||||||
for i, tc := range tests {
|
for i, tc := range tests {
|
||||||
msg := NewMsgSubmitProposal(tc.title, tc.description, tc.proposalType, tc.proposerAddr, tc.initialDeposit)
|
msg := NewMsgSubmitProposal(tc.title, tc.description, tc.proposalType, tc.proposerAddr, tc.initialDeposit)
|
||||||
if tc.expectPass {
|
if tc.expectPass {
|
||||||
require.Nil(t, msg.ValidateBasic(), "test: %v", i)
|
require.NoError(t, msg.ValidateBasic(), "test: %v", i)
|
||||||
} else {
|
} else {
|
||||||
require.NotNil(t, msg.ValidateBasic(), "test: %v", i)
|
require.Error(t, msg.ValidateBasic(), "test: %v", i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,9 +73,9 @@ func TestMsgDeposit(t *testing.T) {
|
||||||
for i, tc := range tests {
|
for i, tc := range tests {
|
||||||
msg := NewMsgDeposit(tc.depositerAddr, tc.proposalID, tc.depositAmount)
|
msg := NewMsgDeposit(tc.depositerAddr, tc.proposalID, tc.depositAmount)
|
||||||
if tc.expectPass {
|
if tc.expectPass {
|
||||||
require.Nil(t, msg.ValidateBasic(), "test: %v", i)
|
require.NoError(t, msg.ValidateBasic(), "test: %v", i)
|
||||||
} else {
|
} else {
|
||||||
require.NotNil(t, msg.ValidateBasic(), "test: %v", i)
|
require.Error(t, msg.ValidateBasic(), "test: %v", i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,10 +11,11 @@ import (
|
||||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||||
"github.com/cosmos/cosmos-sdk/x/mock/simulation"
|
"github.com/cosmos/cosmos-sdk/x/mock/simulation"
|
||||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||||
|
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
denom = "steak"
|
denom = stakeTypes.DefaultBondDenom
|
||||||
)
|
)
|
||||||
|
|
||||||
// SimulateSubmittingVotingAndSlashingForProposal simulates creating a msg Submit Proposal
|
// SimulateSubmittingVotingAndSlashingForProposal simulates creating a msg Submit Proposal
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"github.com/tendermint/tendermint/crypto/ed25519"
|
"github.com/tendermint/tendermint/crypto/ed25519"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||||
|
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -25,7 +26,7 @@ func createValidators(t *testing.T, stakeHandler sdk.Handler, ctx sdk.Context, a
|
||||||
|
|
||||||
for i := 0; i < len(addrs); i++ {
|
for i := 0; i < len(addrs); i++ {
|
||||||
valCreateMsg := stake.NewMsgCreateValidator(
|
valCreateMsg := stake.NewMsgCreateValidator(
|
||||||
addrs[i], pubkeys[i], sdk.NewInt64Coin("steak", coinAmt[i]), testDescription, testCommissionMsg,
|
addrs[i], pubkeys[i], sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, coinAmt[i]), testDescription, testCommissionMsg,
|
||||||
)
|
)
|
||||||
|
|
||||||
res := stakeHandler(ctx, valCreateMsg)
|
res := stakeHandler(ctx, valCreateMsg)
|
||||||
|
@ -289,7 +290,7 @@ func TestTallyDelgatorOverride(t *testing.T) {
|
||||||
createValidators(t, stakeHandler, ctx, valAddrs, []int64{5, 6, 7})
|
createValidators(t, stakeHandler, ctx, valAddrs, []int64{5, 6, 7})
|
||||||
stake.EndBlocker(ctx, sk)
|
stake.EndBlocker(ctx, sk)
|
||||||
|
|
||||||
delegator1Msg := stake.NewMsgDelegate(addrs[3], sdk.ValAddress(addrs[2]), sdk.NewInt64Coin("steak", 30))
|
delegator1Msg := stake.NewMsgDelegate(addrs[3], sdk.ValAddress(addrs[2]), sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 30))
|
||||||
stakeHandler(ctx, delegator1Msg)
|
stakeHandler(ctx, delegator1Msg)
|
||||||
|
|
||||||
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||||
|
@ -326,7 +327,7 @@ func TestTallyDelgatorInherit(t *testing.T) {
|
||||||
createValidators(t, stakeHandler, ctx, valAddrs, []int64{5, 6, 7})
|
createValidators(t, stakeHandler, ctx, valAddrs, []int64{5, 6, 7})
|
||||||
stake.EndBlocker(ctx, sk)
|
stake.EndBlocker(ctx, sk)
|
||||||
|
|
||||||
delegator1Msg := stake.NewMsgDelegate(addrs[3], sdk.ValAddress(addrs[2]), sdk.NewInt64Coin("steak", 30))
|
delegator1Msg := stake.NewMsgDelegate(addrs[3], sdk.ValAddress(addrs[2]), sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 30))
|
||||||
stakeHandler(ctx, delegator1Msg)
|
stakeHandler(ctx, delegator1Msg)
|
||||||
|
|
||||||
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||||
|
@ -361,9 +362,9 @@ func TestTallyDelgatorMultipleOverride(t *testing.T) {
|
||||||
createValidators(t, stakeHandler, ctx, valAddrs, []int64{5, 6, 7})
|
createValidators(t, stakeHandler, ctx, valAddrs, []int64{5, 6, 7})
|
||||||
stake.EndBlocker(ctx, sk)
|
stake.EndBlocker(ctx, sk)
|
||||||
|
|
||||||
delegator1Msg := stake.NewMsgDelegate(addrs[3], sdk.ValAddress(addrs[2]), sdk.NewInt64Coin("steak", 10))
|
delegator1Msg := stake.NewMsgDelegate(addrs[3], sdk.ValAddress(addrs[2]), sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 10))
|
||||||
stakeHandler(ctx, delegator1Msg)
|
stakeHandler(ctx, delegator1Msg)
|
||||||
delegator1Msg2 := stake.NewMsgDelegate(addrs[3], sdk.ValAddress(addrs[1]), sdk.NewInt64Coin("steak", 10))
|
delegator1Msg2 := stake.NewMsgDelegate(addrs[3], sdk.ValAddress(addrs[1]), sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 10))
|
||||||
stakeHandler(ctx, delegator1Msg2)
|
stakeHandler(ctx, delegator1Msg2)
|
||||||
|
|
||||||
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||||
|
@ -393,24 +394,24 @@ func TestTallyDelgatorMultipleInherit(t *testing.T) {
|
||||||
stakeHandler := stake.NewHandler(sk)
|
stakeHandler := stake.NewHandler(sk)
|
||||||
|
|
||||||
val1CreateMsg := stake.NewMsgCreateValidator(
|
val1CreateMsg := stake.NewMsgCreateValidator(
|
||||||
sdk.ValAddress(addrs[0]), ed25519.GenPrivKey().PubKey(), sdk.NewInt64Coin("steak", 25), testDescription, testCommissionMsg,
|
sdk.ValAddress(addrs[0]), ed25519.GenPrivKey().PubKey(), sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 25), testDescription, testCommissionMsg,
|
||||||
)
|
)
|
||||||
stakeHandler(ctx, val1CreateMsg)
|
stakeHandler(ctx, val1CreateMsg)
|
||||||
|
|
||||||
val2CreateMsg := stake.NewMsgCreateValidator(
|
val2CreateMsg := stake.NewMsgCreateValidator(
|
||||||
sdk.ValAddress(addrs[1]), ed25519.GenPrivKey().PubKey(), sdk.NewInt64Coin("steak", 6), testDescription, testCommissionMsg,
|
sdk.ValAddress(addrs[1]), ed25519.GenPrivKey().PubKey(), sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 6), testDescription, testCommissionMsg,
|
||||||
)
|
)
|
||||||
stakeHandler(ctx, val2CreateMsg)
|
stakeHandler(ctx, val2CreateMsg)
|
||||||
|
|
||||||
val3CreateMsg := stake.NewMsgCreateValidator(
|
val3CreateMsg := stake.NewMsgCreateValidator(
|
||||||
sdk.ValAddress(addrs[2]), ed25519.GenPrivKey().PubKey(), sdk.NewInt64Coin("steak", 7), testDescription, testCommissionMsg,
|
sdk.ValAddress(addrs[2]), ed25519.GenPrivKey().PubKey(), sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 7), testDescription, testCommissionMsg,
|
||||||
)
|
)
|
||||||
stakeHandler(ctx, val3CreateMsg)
|
stakeHandler(ctx, val3CreateMsg)
|
||||||
|
|
||||||
delegator1Msg := stake.NewMsgDelegate(addrs[3], sdk.ValAddress(addrs[2]), sdk.NewInt64Coin("steak", 10))
|
delegator1Msg := stake.NewMsgDelegate(addrs[3], sdk.ValAddress(addrs[2]), sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 10))
|
||||||
stakeHandler(ctx, delegator1Msg)
|
stakeHandler(ctx, delegator1Msg)
|
||||||
|
|
||||||
delegator1Msg2 := stake.NewMsgDelegate(addrs[3], sdk.ValAddress(addrs[1]), sdk.NewInt64Coin("steak", 10))
|
delegator1Msg2 := stake.NewMsgDelegate(addrs[3], sdk.ValAddress(addrs[1]), sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 10))
|
||||||
stakeHandler(ctx, delegator1Msg2)
|
stakeHandler(ctx, delegator1Msg2)
|
||||||
|
|
||||||
stake.EndBlocker(ctx, sk)
|
stake.EndBlocker(ctx, sk)
|
||||||
|
@ -447,10 +448,10 @@ func TestTallyJailedValidator(t *testing.T) {
|
||||||
createValidators(t, stakeHandler, ctx, valAddrs, []int64{25, 6, 7})
|
createValidators(t, stakeHandler, ctx, valAddrs, []int64{25, 6, 7})
|
||||||
stake.EndBlocker(ctx, sk)
|
stake.EndBlocker(ctx, sk)
|
||||||
|
|
||||||
delegator1Msg := stake.NewMsgDelegate(addrs[3], sdk.ValAddress(addrs[2]), sdk.NewInt64Coin("steak", 10))
|
delegator1Msg := stake.NewMsgDelegate(addrs[3], sdk.ValAddress(addrs[2]), sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 10))
|
||||||
stakeHandler(ctx, delegator1Msg)
|
stakeHandler(ctx, delegator1Msg)
|
||||||
|
|
||||||
delegator1Msg2 := stake.NewMsgDelegate(addrs[3], sdk.ValAddress(addrs[1]), sdk.NewInt64Coin("steak", 10))
|
delegator1Msg2 := stake.NewMsgDelegate(addrs[3], sdk.ValAddress(addrs[1]), sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 10))
|
||||||
stakeHandler(ctx, delegator1Msg2)
|
stakeHandler(ctx, delegator1Msg2)
|
||||||
|
|
||||||
val2, found := sk.GetValidator(ctx, sdk.ValAddress(addrs[1]))
|
val2, found := sk.GetValidator(ctx, sdk.ValAddress(addrs[1]))
|
||||||
|
|
|
@ -17,6 +17,7 @@ import (
|
||||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||||
"github.com/cosmos/cosmos-sdk/x/mock"
|
"github.com/cosmos/cosmos-sdk/x/mock"
|
||||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||||
|
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// initialize the mock application for this module
|
// initialize the mock application for this module
|
||||||
|
@ -44,7 +45,7 @@ func getMockApp(t *testing.T, numGenAccs int) (*mock.App, Keeper, stake.Keeper,
|
||||||
|
|
||||||
require.NoError(t, mapp.CompleteSetup(keyStake, tkeyStake, keyGov, keyGlobalParams, tkeyGlobalParams))
|
require.NoError(t, mapp.CompleteSetup(keyStake, tkeyStake, keyGov, keyGlobalParams, tkeyGlobalParams))
|
||||||
|
|
||||||
genAccs, addrs, pubKeys, privKeys := mock.CreateGenAccounts(numGenAccs, sdk.Coins{sdk.NewInt64Coin("steak", 42)})
|
genAccs, addrs, pubKeys, privKeys := mock.CreateGenAccounts(numGenAccs, sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 42)})
|
||||||
|
|
||||||
mock.SetGenesis(mapp, genAccs)
|
mock.SetGenesis(mapp, genAccs)
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package mint
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
)
|
)
|
||||||
|
@ -18,7 +19,7 @@ type Params struct {
|
||||||
// default minting module parameters
|
// default minting module parameters
|
||||||
func DefaultParams() Params {
|
func DefaultParams() Params {
|
||||||
return Params{
|
return Params{
|
||||||
MintDenom: "steak",
|
MintDenom: stakeTypes.DefaultBondDenom,
|
||||||
InflationRateChange: sdk.NewDecWithPrec(13, 2),
|
InflationRateChange: sdk.NewDecWithPrec(13, 2),
|
||||||
InflationMax: sdk.NewDecWithPrec(20, 2),
|
InflationMax: sdk.NewDecWithPrec(20, 2),
|
||||||
InflationMin: sdk.NewDecWithPrec(7, 2),
|
InflationMin: sdk.NewDecWithPrec(7, 2),
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
package simulation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
|
||||||
|
"github.com/tendermint/tendermint/crypto"
|
||||||
|
"github.com/tendermint/tendermint/crypto/ed25519"
|
||||||
|
"github.com/tendermint/tendermint/crypto/secp256k1"
|
||||||
|
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Account contains a privkey, pubkey, address tuple
|
||||||
|
// eventually more useful data can be placed in here.
|
||||||
|
// (e.g. number of coins)
|
||||||
|
type Account struct {
|
||||||
|
PrivKey crypto.PrivKey
|
||||||
|
PubKey crypto.PubKey
|
||||||
|
Address sdk.AccAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
// are two accounts equal
|
||||||
|
func (acc Account) Equals(acc2 Account) bool {
|
||||||
|
return acc.Address.Equals(acc2.Address)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RandomAcc pick a random account from an array
|
||||||
|
func RandomAcc(r *rand.Rand, accs []Account) Account {
|
||||||
|
return accs[r.Intn(
|
||||||
|
len(accs),
|
||||||
|
)]
|
||||||
|
}
|
||||||
|
|
||||||
|
// RandomAccounts generates n random accounts
|
||||||
|
func RandomAccounts(r *rand.Rand, n int) []Account {
|
||||||
|
accs := make([]Account, n)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
// don't need that much entropy for simulation
|
||||||
|
privkeySeed := make([]byte, 15)
|
||||||
|
r.Read(privkeySeed)
|
||||||
|
useSecp := r.Int63()%2 == 0
|
||||||
|
if useSecp {
|
||||||
|
accs[i].PrivKey = secp256k1.GenPrivKeySecp256k1(privkeySeed)
|
||||||
|
} else {
|
||||||
|
accs[i].PrivKey = ed25519.GenPrivKeyFromSecret(privkeySeed)
|
||||||
|
}
|
||||||
|
accs[i].PubKey = accs[i].PrivKey.PubKey()
|
||||||
|
accs[i].Address = sdk.AccAddress(accs[i].PubKey.Address())
|
||||||
|
}
|
||||||
|
return accs
|
||||||
|
}
|
|
@ -2,26 +2,24 @@
|
||||||
Package simulation implements a simulation framework for any state machine
|
Package simulation implements a simulation framework for any state machine
|
||||||
built on the SDK which utilizes auth.
|
built on the SDK which utilizes auth.
|
||||||
|
|
||||||
It is primarily intended for fuzz testing the integration of modules.
|
It is primarily intended for fuzz testing the integration of modules. It will
|
||||||
It will test that the provided operations are interoperable,
|
test that the provided operations are interoperable, and that the desired
|
||||||
and that the desired invariants hold.
|
invariants hold. It can additionally be used to detect what the performance
|
||||||
It can additionally be used to detect what the performance benchmarks in the
|
benchmarks in the system are, by using benchmarking mode and cpu / mem
|
||||||
system are, by using benchmarking mode and cpu / mem profiling.
|
profiling. If it detects a failure, it provides the entire log of what was ran.
|
||||||
If it detects a failure, it provides the entire log of what was ran,
|
|
||||||
|
|
||||||
The simulator takes as input: a random seed, the set of operations to run,
|
The simulator takes as input: a random seed, the set of operations to run, the
|
||||||
the invariants to test, and additional parameters to configure how long to run,
|
invariants to test, and additional parameters to configure how long to run, and
|
||||||
and misc. parameters that affect simulation speed.
|
misc. parameters that affect simulation speed.
|
||||||
|
|
||||||
It is intended that every module provides a list of Operations which will randomly
|
It is intended that every module provides a list of Operations which will
|
||||||
create and run a message / tx in a manner that is interesting to fuzz, and verify that
|
randomly create and run a message / tx in a manner that is interesting to fuzz,
|
||||||
the state transition was executed as expected.
|
and verify that the state transition was executed as expected. Each module
|
||||||
Each module should additionally provide methods to assert that the desired invariants hold.
|
should additionally provide methods to assert that the desired invariants hold.
|
||||||
|
|
||||||
Then to perform a randomized simulation, select the set of desired operations,
|
Then to perform a randomized simulation, select the set of desired operations,
|
||||||
the weightings for each, the invariants you want to test, and how long to run it for.
|
the weightings for each, the invariants you want to test, and how long to run
|
||||||
Then run simulation.Simulate!
|
it for. Then run simulation.Simulate! The simulator will handle things like
|
||||||
The simulator will handle things like ensuring that validators periodically double signing,
|
ensuring that validators periodically double signing, or go offline.
|
||||||
or go offline.
|
|
||||||
*/
|
*/
|
||||||
package simulation
|
package simulation
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
package simulation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
)
|
||||||
|
|
||||||
|
type eventStats map[string]uint
|
||||||
|
|
||||||
|
func newEventStats() eventStats {
|
||||||
|
events := make(map[string]uint)
|
||||||
|
return events
|
||||||
|
}
|
||||||
|
|
||||||
|
func (es eventStats) tally(eventDesc string) {
|
||||||
|
es[eventDesc]++
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pretty-print events as a table
|
||||||
|
func (es eventStats) Print() {
|
||||||
|
var keys []string
|
||||||
|
for key := range es {
|
||||||
|
keys = append(keys, key)
|
||||||
|
}
|
||||||
|
sort.Strings(keys)
|
||||||
|
fmt.Printf("Event statistics: \n")
|
||||||
|
for _, key := range keys {
|
||||||
|
fmt.Printf(" % 60s => %d\n", key, es[key])
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package simulation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||||
|
)
|
||||||
|
|
||||||
|
// An Invariant is a function which tests a particular invariant.
|
||||||
|
// If the invariant has been broken, it should return an error
|
||||||
|
// containing a descriptive message about what happened.
|
||||||
|
// The simulator will then halt and print the logs.
|
||||||
|
type Invariant func(app *baseapp.BaseApp) error
|
||||||
|
|
||||||
|
// group of Invarient
|
||||||
|
type Invariants []Invariant
|
||||||
|
|
||||||
|
// assertAll asserts the all invariants against application state
|
||||||
|
func (invs Invariants) assertAll(t *testing.T, app *baseapp.BaseApp,
|
||||||
|
event string, displayLogs func()) {
|
||||||
|
|
||||||
|
for i := 0; i < len(invs); i++ {
|
||||||
|
if err := invs[i](app); err != nil {
|
||||||
|
fmt.Printf("Invariants broken after %s\n%s\n", event, err.Error())
|
||||||
|
displayLogs()
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,201 @@
|
||||||
|
package simulation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"sort"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
|
cmn "github.com/tendermint/tendermint/libs/common"
|
||||||
|
tmtypes "github.com/tendermint/tendermint/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type mockValidator struct {
|
||||||
|
val abci.ValidatorUpdate
|
||||||
|
livenessState int
|
||||||
|
}
|
||||||
|
|
||||||
|
type mockValidators map[string]mockValidator
|
||||||
|
|
||||||
|
// get mockValidators from abci validators
|
||||||
|
func newMockValidators(r *rand.Rand, abciVals []abci.ValidatorUpdate,
|
||||||
|
params Params) mockValidators {
|
||||||
|
|
||||||
|
validators := make(mockValidators)
|
||||||
|
for _, validator := range abciVals {
|
||||||
|
str := fmt.Sprintf("%v", validator.PubKey)
|
||||||
|
liveliness := GetMemberOfInitialState(r,
|
||||||
|
params.InitialLivenessWeightings)
|
||||||
|
|
||||||
|
validators[str] = mockValidator{
|
||||||
|
val: validator,
|
||||||
|
livenessState: liveliness,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return validators
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO describe usage
|
||||||
|
func (vals mockValidators) getKeys() []string {
|
||||||
|
keys := make([]string, len(vals))
|
||||||
|
i := 0
|
||||||
|
for key := range vals {
|
||||||
|
keys[i] = key
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
sort.Strings(keys)
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
//_________________________________________________________________________________
|
||||||
|
|
||||||
|
// randomProposer picks a random proposer from the current validator set
|
||||||
|
func (vals mockValidators) randomProposer(r *rand.Rand) cmn.HexBytes {
|
||||||
|
keys := vals.getKeys()
|
||||||
|
if len(keys) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
key := keys[r.Intn(len(keys))]
|
||||||
|
proposer := vals[key].val
|
||||||
|
pk, err := tmtypes.PB2TM.PubKey(proposer.PubKey)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return pk.Address()
|
||||||
|
}
|
||||||
|
|
||||||
|
// updateValidators mimicks Tendermint's update logic
|
||||||
|
// nolint: unparam
|
||||||
|
func updateValidators(tb testing.TB, r *rand.Rand, params Params,
|
||||||
|
current map[string]mockValidator, updates []abci.ValidatorUpdate,
|
||||||
|
event func(string)) map[string]mockValidator {
|
||||||
|
|
||||||
|
for _, update := range updates {
|
||||||
|
str := fmt.Sprintf("%v", update.PubKey)
|
||||||
|
|
||||||
|
if update.Power == 0 {
|
||||||
|
if _, ok := current[str]; !ok {
|
||||||
|
tb.Fatalf("tried to delete a nonexistent validator")
|
||||||
|
}
|
||||||
|
event("endblock/validatorupdates/kicked")
|
||||||
|
delete(current, str)
|
||||||
|
|
||||||
|
} else if mVal, ok := current[str]; ok {
|
||||||
|
// validator already exists
|
||||||
|
mVal.val = update
|
||||||
|
event("endblock/validatorupdates/updated")
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Set this new validator
|
||||||
|
current[str] = mockValidator{
|
||||||
|
update,
|
||||||
|
GetMemberOfInitialState(r, params.InitialLivenessWeightings),
|
||||||
|
}
|
||||||
|
event("endblock/validatorupdates/added")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return current
|
||||||
|
}
|
||||||
|
|
||||||
|
// RandomRequestBeginBlock generates a list of signing validators according to
|
||||||
|
// the provided list of validators, signing fraction, and evidence fraction
|
||||||
|
func RandomRequestBeginBlock(r *rand.Rand, params Params,
|
||||||
|
validators mockValidators, pastTimes []time.Time,
|
||||||
|
pastVoteInfos [][]abci.VoteInfo,
|
||||||
|
event func(string), header abci.Header) abci.RequestBeginBlock {
|
||||||
|
|
||||||
|
if len(validators) == 0 {
|
||||||
|
return abci.RequestBeginBlock{
|
||||||
|
Header: header,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
voteInfos := make([]abci.VoteInfo, len(validators))
|
||||||
|
for i, key := range validators.getKeys() {
|
||||||
|
mVal := validators[key]
|
||||||
|
mVal.livenessState = params.LivenessTransitionMatrix.NextState(r, mVal.livenessState)
|
||||||
|
signed := true
|
||||||
|
|
||||||
|
if mVal.livenessState == 1 {
|
||||||
|
// spotty connection, 50% probability of success
|
||||||
|
// See https://github.com/golang/go/issues/23804#issuecomment-365370418
|
||||||
|
// for reasoning behind computing like this
|
||||||
|
signed = r.Int63()%2 == 0
|
||||||
|
} else if mVal.livenessState == 2 {
|
||||||
|
// offline
|
||||||
|
signed = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if signed {
|
||||||
|
event("beginblock/signing/signed")
|
||||||
|
} else {
|
||||||
|
event("beginblock/signing/missed")
|
||||||
|
}
|
||||||
|
|
||||||
|
pubkey, err := tmtypes.PB2TM.PubKey(mVal.val.PubKey)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
voteInfos[i] = abci.VoteInfo{
|
||||||
|
Validator: abci.Validator{
|
||||||
|
Address: pubkey.Address(),
|
||||||
|
Power: mVal.val.Power,
|
||||||
|
},
|
||||||
|
SignedLastBlock: signed,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// return if no past times
|
||||||
|
if len(pastTimes) <= 0 {
|
||||||
|
return abci.RequestBeginBlock{
|
||||||
|
Header: header,
|
||||||
|
LastCommitInfo: abci.LastCommitInfo{
|
||||||
|
Votes: voteInfos,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Determine capacity before allocation
|
||||||
|
evidence := make([]abci.Evidence, 0)
|
||||||
|
for r.Float64() < params.EvidenceFraction {
|
||||||
|
|
||||||
|
height := header.Height
|
||||||
|
time := header.Time
|
||||||
|
vals := voteInfos
|
||||||
|
|
||||||
|
if r.Float64() < params.PastEvidenceFraction {
|
||||||
|
height = int64(r.Intn(int(header.Height) - 1))
|
||||||
|
time = pastTimes[height]
|
||||||
|
vals = pastVoteInfos[height]
|
||||||
|
}
|
||||||
|
validator := vals[r.Intn(len(vals))].Validator
|
||||||
|
|
||||||
|
var totalVotingPower int64
|
||||||
|
for _, val := range vals {
|
||||||
|
totalVotingPower += val.Validator.Power
|
||||||
|
}
|
||||||
|
|
||||||
|
evidence = append(evidence,
|
||||||
|
abci.Evidence{
|
||||||
|
Type: tmtypes.ABCIEvidenceTypeDuplicateVote,
|
||||||
|
Validator: validator,
|
||||||
|
Height: height,
|
||||||
|
Time: time,
|
||||||
|
TotalVotingPower: totalVotingPower,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
event("beginblock/evidence")
|
||||||
|
}
|
||||||
|
|
||||||
|
return abci.RequestBeginBlock{
|
||||||
|
Header: header,
|
||||||
|
LastCommitInfo: abci.LastCommitInfo{
|
||||||
|
Votes: voteInfos,
|
||||||
|
},
|
||||||
|
ByzantineValidators: evidence,
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,112 @@
|
||||||
|
package simulation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"sort"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Operation runs a state machine transition, and ensures the transition
|
||||||
|
// happened as expected. The operation could be running and testing a fuzzed
|
||||||
|
// transaction, or doing the same for a message.
|
||||||
|
//
|
||||||
|
// For ease of debugging, an operation returns a descriptive message "action",
|
||||||
|
// which details what this fuzzed state machine transition actually did.
|
||||||
|
//
|
||||||
|
// Operations can optionally provide a list of "FutureOperations" to run later
|
||||||
|
// These will be ran at the beginning of the corresponding block.
|
||||||
|
type Operation func(r *rand.Rand, app *baseapp.BaseApp,
|
||||||
|
ctx sdk.Context, accounts []Account, event func(string)) (
|
||||||
|
action string, futureOps []FutureOperation, err error)
|
||||||
|
|
||||||
|
// queue of operations
|
||||||
|
type OperationQueue map[int][]Operation
|
||||||
|
|
||||||
|
func newOperationQueue() OperationQueue {
|
||||||
|
operationQueue := make(OperationQueue)
|
||||||
|
return operationQueue
|
||||||
|
}
|
||||||
|
|
||||||
|
// adds all future operations into the operation queue.
|
||||||
|
func queueOperations(queuedOps OperationQueue,
|
||||||
|
queuedTimeOps []FutureOperation, futureOps []FutureOperation) {
|
||||||
|
|
||||||
|
if futureOps == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, futureOp := range futureOps {
|
||||||
|
if futureOp.BlockHeight != 0 {
|
||||||
|
if val, ok := queuedOps[futureOp.BlockHeight]; ok {
|
||||||
|
queuedOps[futureOp.BlockHeight] = append(val, futureOp.Op)
|
||||||
|
} else {
|
||||||
|
queuedOps[futureOp.BlockHeight] = []Operation{futureOp.Op}
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Replace with proper sorted data structure, so don't have the
|
||||||
|
// copy entire slice
|
||||||
|
index := sort.Search(
|
||||||
|
len(queuedTimeOps),
|
||||||
|
func(i int) bool {
|
||||||
|
return queuedTimeOps[i].BlockTime.After(futureOp.BlockTime)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
queuedTimeOps = append(queuedTimeOps, FutureOperation{})
|
||||||
|
copy(queuedTimeOps[index+1:], queuedTimeOps[index:])
|
||||||
|
queuedTimeOps[index] = futureOp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//________________________________________________________________________
|
||||||
|
|
||||||
|
// FutureOperation is an operation which will be ran at the beginning of the
|
||||||
|
// provided BlockHeight. If both a BlockHeight and BlockTime are specified, it
|
||||||
|
// will use the BlockHeight. In the (likely) event that multiple operations
|
||||||
|
// are queued at the same block height, they will execute in a FIFO pattern.
|
||||||
|
type FutureOperation struct {
|
||||||
|
BlockHeight int
|
||||||
|
BlockTime time.Time
|
||||||
|
Op Operation
|
||||||
|
}
|
||||||
|
|
||||||
|
//________________________________________________________________________
|
||||||
|
|
||||||
|
// WeightedOperation is an operation with associated weight.
|
||||||
|
// This is used to bias the selection operation within the simulator.
|
||||||
|
type WeightedOperation struct {
|
||||||
|
Weight int
|
||||||
|
Op Operation
|
||||||
|
}
|
||||||
|
|
||||||
|
// WeightedOperations is the group of all weighted operations to simulate.
|
||||||
|
type WeightedOperations []WeightedOperation
|
||||||
|
|
||||||
|
func (ops WeightedOperations) totalWeight() int {
|
||||||
|
totalOpWeight := 0
|
||||||
|
for _, op := range ops {
|
||||||
|
totalOpWeight += op.Weight
|
||||||
|
}
|
||||||
|
return totalOpWeight
|
||||||
|
}
|
||||||
|
|
||||||
|
type selectOpFn func(r *rand.Rand) Operation
|
||||||
|
|
||||||
|
func (ops WeightedOperations) getSelectOpFn() selectOpFn {
|
||||||
|
totalOpWeight := ops.totalWeight()
|
||||||
|
return func(r *rand.Rand) Operation {
|
||||||
|
x := r.Intn(totalOpWeight)
|
||||||
|
for i := 0; i < len(ops); i++ {
|
||||||
|
if x <= ops[i].Weight {
|
||||||
|
return ops[i].Op
|
||||||
|
}
|
||||||
|
x -= ops[i].Weight
|
||||||
|
}
|
||||||
|
// shouldn't happen
|
||||||
|
return ops[0].Op
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,15 +15,18 @@ const (
|
||||||
onOperation bool = false
|
onOperation bool = false
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TODO explain transitional matrix usage
|
||||||
var (
|
var (
|
||||||
// Currently there are 3 different liveness types, fully online, spotty connection, offline.
|
// Currently there are 3 different liveness types,
|
||||||
|
// fully online, spotty connection, offline.
|
||||||
defaultLivenessTransitionMatrix, _ = CreateTransitionMatrix([][]int{
|
defaultLivenessTransitionMatrix, _ = CreateTransitionMatrix([][]int{
|
||||||
{90, 20, 1},
|
{90, 20, 1},
|
||||||
{10, 50, 5},
|
{10, 50, 5},
|
||||||
{0, 10, 1000},
|
{0, 10, 1000},
|
||||||
})
|
})
|
||||||
|
|
||||||
// 3 states: rand in range [0, 4*provided blocksize], rand in range [0, 2 * provided blocksize], 0
|
// 3 states: rand in range [0, 4*provided blocksize],
|
||||||
|
// rand in range [0, 2 * provided blocksize], 0
|
||||||
defaultBlockSizeTransitionMatrix, _ = CreateTransitionMatrix([][]int{
|
defaultBlockSizeTransitionMatrix, _ = CreateTransitionMatrix([][]int{
|
||||||
{85, 5, 0},
|
{85, 5, 0},
|
||||||
{15, 92, 1},
|
{15, 92, 1},
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
package simulation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/mock"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
letterIdxBits = 6 // 6 bits to represent a letter index
|
||||||
|
letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
|
||||||
|
letterIdxMax = 63 / letterIdxBits // # of letter indices fitting in 63 bits
|
||||||
|
)
|
||||||
|
|
||||||
|
// shamelessly copied from
|
||||||
|
// https://stackoverflow.com/questions/22892120/how-to-generate-a-random-string-of-a-fixed-length-in-golang#31832326
|
||||||
|
// Generate a random string of a particular length
|
||||||
|
func RandStringOfLength(r *rand.Rand, n int) string {
|
||||||
|
b := make([]byte, n)
|
||||||
|
// A src.Int63() generates 63 random bits, enough for letterIdxMax characters!
|
||||||
|
for i, cache, remain := n-1, r.Int63(), letterIdxMax; i >= 0; {
|
||||||
|
if remain == 0 {
|
||||||
|
cache, remain = r.Int63(), letterIdxMax
|
||||||
|
}
|
||||||
|
if idx := int(cache & letterIdxMask); idx < len(letterBytes) {
|
||||||
|
b[i] = letterBytes[idx]
|
||||||
|
i--
|
||||||
|
}
|
||||||
|
cache >>= letterIdxBits
|
||||||
|
remain--
|
||||||
|
}
|
||||||
|
return string(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate a random amount
|
||||||
|
func RandomAmount(r *rand.Rand, max sdk.Int) sdk.Int {
|
||||||
|
return sdk.NewInt(int64(r.Intn(int(max.Int64()))))
|
||||||
|
}
|
||||||
|
|
||||||
|
// RandomDecAmount generates a random decimal amount
|
||||||
|
func RandomDecAmount(r *rand.Rand, max sdk.Dec) sdk.Dec {
|
||||||
|
randInt := big.NewInt(0).Rand(r, max.Int)
|
||||||
|
return sdk.NewDecFromBigIntWithPrec(randInt, sdk.Precision)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RandomSetGenesis wraps mock.RandomSetGenesis, but using simulation accounts
|
||||||
|
func RandomSetGenesis(r *rand.Rand, app *mock.App, accs []Account, denoms []string) {
|
||||||
|
addrs := make([]sdk.AccAddress, len(accs))
|
||||||
|
for i := 0; i < len(accs); i++ {
|
||||||
|
addrs[i] = accs[i].Address
|
||||||
|
}
|
||||||
|
mock.RandomSetGenesis(r, app, addrs, denoms)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RandTimestamp generates a random timestamp
|
||||||
|
func RandTimestamp(r *rand.Rand) time.Time {
|
||||||
|
// json.Marshal breaks for timestamps greater with year greater than 9999
|
||||||
|
unixTime := r.Int63n(253373529600)
|
||||||
|
return time.Unix(unixTime, 0)
|
||||||
|
}
|
|
@ -1,488 +0,0 @@
|
||||||
package simulation
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"math/rand"
|
|
||||||
"os"
|
|
||||||
"os/signal"
|
|
||||||
"runtime/debug"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
|
||||||
cmn "github.com/tendermint/tendermint/libs/common"
|
|
||||||
tmtypes "github.com/tendermint/tendermint/types"
|
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Simulate tests application by sending random messages.
|
|
||||||
func Simulate(t *testing.T, app *baseapp.BaseApp,
|
|
||||||
appStateFn func(r *rand.Rand, accs []Account) json.RawMessage,
|
|
||||||
ops []WeightedOperation, setups []RandSetup,
|
|
||||||
invariants []Invariant, numBlocks int, blockSize int, commit bool) error {
|
|
||||||
|
|
||||||
time := time.Now().UnixNano()
|
|
||||||
return SimulateFromSeed(t, app, appStateFn, time, ops, setups, invariants, numBlocks, blockSize, commit)
|
|
||||||
}
|
|
||||||
|
|
||||||
func initChain(r *rand.Rand, params Params, accounts []Account, setups []RandSetup, app *baseapp.BaseApp,
|
|
||||||
appStateFn func(r *rand.Rand, accounts []Account) json.RawMessage) (validators map[string]mockValidator) {
|
|
||||||
res := app.InitChain(abci.RequestInitChain{AppStateBytes: appStateFn(r, accounts)})
|
|
||||||
validators = make(map[string]mockValidator)
|
|
||||||
for _, validator := range res.Validators {
|
|
||||||
str := fmt.Sprintf("%v", validator.PubKey)
|
|
||||||
validators[str] = mockValidator{validator, GetMemberOfInitialState(r, params.InitialLivenessWeightings)}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < len(setups); i++ {
|
|
||||||
setups[i](r, accounts)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func randTimestamp(r *rand.Rand) time.Time {
|
|
||||||
// json.Marshal breaks for timestamps greater with year greater than 9999
|
|
||||||
unixTime := r.Int63n(253373529600)
|
|
||||||
return time.Unix(unixTime, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SimulateFromSeed tests an application by running the provided
|
|
||||||
// operations, testing the provided invariants, but using the provided seed.
|
|
||||||
func SimulateFromSeed(tb testing.TB, app *baseapp.BaseApp,
|
|
||||||
appStateFn func(r *rand.Rand, accs []Account) json.RawMessage,
|
|
||||||
seed int64, ops []WeightedOperation, setups []RandSetup, invariants []Invariant,
|
|
||||||
numBlocks int, blockSize int, commit bool) (simError error) {
|
|
||||||
|
|
||||||
// in case we have to end early, don't os.Exit so that we can run cleanup code.
|
|
||||||
stopEarly := false
|
|
||||||
testingMode, t, b := getTestingMode(tb)
|
|
||||||
fmt.Printf("Starting SimulateFromSeed with randomness created with seed %d\n", int(seed))
|
|
||||||
r := rand.New(rand.NewSource(seed))
|
|
||||||
params := RandomParams(r) // := DefaultParams()
|
|
||||||
fmt.Printf("Randomized simulation params: %+v\n", params)
|
|
||||||
timestamp := randTimestamp(r)
|
|
||||||
fmt.Printf("Starting the simulation from time %v, unixtime %v\n", timestamp.UTC().Format(time.UnixDate), timestamp.Unix())
|
|
||||||
timeDiff := maxTimePerBlock - minTimePerBlock
|
|
||||||
|
|
||||||
accs := RandomAccounts(r, params.NumKeys)
|
|
||||||
|
|
||||||
// Setup event stats
|
|
||||||
events := make(map[string]uint)
|
|
||||||
event := func(what string) {
|
|
||||||
events[what]++
|
|
||||||
}
|
|
||||||
|
|
||||||
validators := initChain(r, params, accs, setups, app, appStateFn)
|
|
||||||
// Second variable to keep pending validator set (delayed one block since TM 0.24)
|
|
||||||
// Initially this is the same as the initial validator set
|
|
||||||
nextValidators := validators
|
|
||||||
|
|
||||||
header := abci.Header{Height: 1, Time: timestamp, ProposerAddress: randomProposer(r, validators)}
|
|
||||||
opCount := 0
|
|
||||||
|
|
||||||
// Setup code to catch SIGTERM's
|
|
||||||
c := make(chan os.Signal)
|
|
||||||
signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
|
|
||||||
go func() {
|
|
||||||
receivedSignal := <-c
|
|
||||||
fmt.Printf("\nExiting early due to %s, on block %d, operation %d\n", receivedSignal, header.Height, opCount)
|
|
||||||
simError = fmt.Errorf("Exited due to %s", receivedSignal)
|
|
||||||
stopEarly = true
|
|
||||||
}()
|
|
||||||
|
|
||||||
var pastTimes []time.Time
|
|
||||||
var pastVoteInfos [][]abci.VoteInfo
|
|
||||||
|
|
||||||
request := RandomRequestBeginBlock(r, params, validators, pastTimes, pastVoteInfos, event, header)
|
|
||||||
// These are operations which have been queued by previous operations
|
|
||||||
operationQueue := make(map[int][]Operation)
|
|
||||||
timeOperationQueue := []FutureOperation{}
|
|
||||||
var blockLogBuilders []*strings.Builder
|
|
||||||
|
|
||||||
if testingMode {
|
|
||||||
blockLogBuilders = make([]*strings.Builder, numBlocks)
|
|
||||||
}
|
|
||||||
displayLogs := logPrinter(testingMode, blockLogBuilders)
|
|
||||||
blockSimulator := createBlockSimulator(testingMode, tb, t, params, event, invariants, ops, operationQueue, timeOperationQueue, numBlocks, blockSize, displayLogs)
|
|
||||||
if !testingMode {
|
|
||||||
b.ResetTimer()
|
|
||||||
} else {
|
|
||||||
// Recover logs in case of panic
|
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
fmt.Println("Panic with err\n", r)
|
|
||||||
stackTrace := string(debug.Stack())
|
|
||||||
fmt.Println(stackTrace)
|
|
||||||
displayLogs()
|
|
||||||
simError = fmt.Errorf("Simulation halted due to panic on block %d", header.Height)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < numBlocks && !stopEarly; i++ {
|
|
||||||
// Log the header time for future lookup
|
|
||||||
pastTimes = append(pastTimes, header.Time)
|
|
||||||
pastVoteInfos = append(pastVoteInfos, request.LastCommitInfo.Votes)
|
|
||||||
|
|
||||||
// Construct log writer
|
|
||||||
logWriter := addLogMessage(testingMode, blockLogBuilders, i)
|
|
||||||
|
|
||||||
// Run the BeginBlock handler
|
|
||||||
logWriter("BeginBlock")
|
|
||||||
app.BeginBlock(request)
|
|
||||||
|
|
||||||
if testingMode {
|
|
||||||
// Make sure invariants hold at beginning of block
|
|
||||||
assertAllInvariants(t, app, invariants, "BeginBlock", displayLogs)
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx := app.NewContext(false, header)
|
|
||||||
|
|
||||||
// Run queued operations. Ignores blocksize if blocksize is too small
|
|
||||||
logWriter("Queued operations")
|
|
||||||
numQueuedOpsRan := runQueuedOperations(operationQueue, int(header.Height), tb, r, app, ctx, accs, logWriter, displayLogs, event)
|
|
||||||
numQueuedTimeOpsRan := runQueuedTimeOperations(timeOperationQueue, header.Time, tb, r, app, ctx, accs, logWriter, displayLogs, event)
|
|
||||||
if testingMode && onOperation {
|
|
||||||
// Make sure invariants hold at end of queued operations
|
|
||||||
assertAllInvariants(t, app, invariants, "QueuedOperations", displayLogs)
|
|
||||||
}
|
|
||||||
|
|
||||||
logWriter("Standard operations")
|
|
||||||
operations := blockSimulator(r, app, ctx, accs, header, logWriter)
|
|
||||||
opCount += operations + numQueuedOpsRan + numQueuedTimeOpsRan
|
|
||||||
if testingMode {
|
|
||||||
// Make sure invariants hold at end of block
|
|
||||||
assertAllInvariants(t, app, invariants, "StandardOperations", displayLogs)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := app.EndBlock(abci.RequestEndBlock{})
|
|
||||||
header.Height++
|
|
||||||
header.Time = header.Time.Add(time.Duration(minTimePerBlock) * time.Second).Add(time.Duration(int64(r.Intn(int(timeDiff)))) * time.Second)
|
|
||||||
header.ProposerAddress = randomProposer(r, validators)
|
|
||||||
logWriter("EndBlock")
|
|
||||||
|
|
||||||
if testingMode {
|
|
||||||
// Make sure invariants hold at end of block
|
|
||||||
assertAllInvariants(t, app, invariants, "EndBlock", displayLogs)
|
|
||||||
}
|
|
||||||
if commit {
|
|
||||||
app.Commit()
|
|
||||||
}
|
|
||||||
|
|
||||||
if header.ProposerAddress == nil {
|
|
||||||
fmt.Printf("\nSimulation stopped early as all validators have been unbonded, there is nobody left propose a block!\n")
|
|
||||||
stopEarly = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate a random RequestBeginBlock with the current validator set for the next block
|
|
||||||
request = RandomRequestBeginBlock(r, params, validators, pastTimes, pastVoteInfos, event, header)
|
|
||||||
|
|
||||||
// Update the validator set, which will be reflected in the application on the next block
|
|
||||||
validators = nextValidators
|
|
||||||
nextValidators = updateValidators(tb, r, params, validators, res.ValidatorUpdates, event)
|
|
||||||
}
|
|
||||||
if stopEarly {
|
|
||||||
DisplayEvents(events)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fmt.Printf("\nSimulation complete. Final height (blocks): %d, final time (seconds), : %v, operations ran %d\n", header.Height, header.Time, opCount)
|
|
||||||
DisplayEvents(events)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type blockSimFn func(
|
|
||||||
r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
|
|
||||||
accounts []Account, header abci.Header, logWriter func(string),
|
|
||||||
) (opCount int)
|
|
||||||
|
|
||||||
// Returns a function to simulate blocks. Written like this to avoid constant parameters being passed everytime, to minimize
|
|
||||||
// memory overhead
|
|
||||||
func createBlockSimulator(testingMode bool, tb testing.TB, t *testing.T, params Params,
|
|
||||||
event func(string), invariants []Invariant,
|
|
||||||
ops []WeightedOperation, operationQueue map[int][]Operation, timeOperationQueue []FutureOperation,
|
|
||||||
totalNumBlocks int, avgBlockSize int, displayLogs func()) blockSimFn {
|
|
||||||
|
|
||||||
var (
|
|
||||||
lastBlocksizeState = 0 // state for [4 * uniform distribution]
|
|
||||||
totalOpWeight = 0
|
|
||||||
blocksize int
|
|
||||||
)
|
|
||||||
|
|
||||||
for i := 0; i < len(ops); i++ {
|
|
||||||
totalOpWeight += ops[i].Weight
|
|
||||||
}
|
|
||||||
selectOp := func(r *rand.Rand) Operation {
|
|
||||||
x := r.Intn(totalOpWeight)
|
|
||||||
for i := 0; i < len(ops); i++ {
|
|
||||||
if x <= ops[i].Weight {
|
|
||||||
return ops[i].Op
|
|
||||||
}
|
|
||||||
x -= ops[i].Weight
|
|
||||||
}
|
|
||||||
// shouldn't happen
|
|
||||||
return ops[0].Op
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
|
|
||||||
accounts []Account, header abci.Header, logWriter func(string)) (opCount int) {
|
|
||||||
fmt.Printf("\rSimulating... block %d/%d, operation %d/%d. ", header.Height, totalNumBlocks, opCount, blocksize)
|
|
||||||
lastBlocksizeState, blocksize = getBlockSize(r, params, lastBlocksizeState, avgBlockSize)
|
|
||||||
for j := 0; j < blocksize; j++ {
|
|
||||||
logUpdate, futureOps, err := selectOp(r)(r, app, ctx, accounts, event)
|
|
||||||
logWriter(logUpdate)
|
|
||||||
if err != nil {
|
|
||||||
displayLogs()
|
|
||||||
tb.Fatalf("error on operation %d within block %d, %v", header.Height, opCount, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
queueOperations(operationQueue, timeOperationQueue, futureOps)
|
|
||||||
if testingMode {
|
|
||||||
if onOperation {
|
|
||||||
assertAllInvariants(t, app, invariants, fmt.Sprintf("operation: %v", logUpdate), displayLogs)
|
|
||||||
}
|
|
||||||
if opCount%50 == 0 {
|
|
||||||
fmt.Printf("\rSimulating... block %d/%d, operation %d/%d. ", header.Height, totalNumBlocks, opCount, blocksize)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
opCount++
|
|
||||||
}
|
|
||||||
return opCount
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTestingMode(tb testing.TB) (testingMode bool, t *testing.T, b *testing.B) {
|
|
||||||
testingMode = false
|
|
||||||
if _t, ok := tb.(*testing.T); ok {
|
|
||||||
t = _t
|
|
||||||
testingMode = true
|
|
||||||
} else {
|
|
||||||
b = tb.(*testing.B)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// getBlockSize returns a block size as determined from the transition matrix.
|
|
||||||
// It targets making average block size the provided parameter. The three
|
|
||||||
// states it moves between are:
|
|
||||||
// "over stuffed" blocks with average size of 2 * avgblocksize,
|
|
||||||
// normal sized blocks, hitting avgBlocksize on average,
|
|
||||||
// and empty blocks, with no txs / only txs scheduled from the past.
|
|
||||||
func getBlockSize(r *rand.Rand, params Params, lastBlockSizeState, avgBlockSize int) (state, blocksize int) {
|
|
||||||
// TODO: Make default blocksize transition matrix actually make the average
|
|
||||||
// blocksize equal to avgBlockSize.
|
|
||||||
state = params.BlockSizeTransitionMatrix.NextState(r, lastBlockSizeState)
|
|
||||||
if state == 0 {
|
|
||||||
blocksize = r.Intn(avgBlockSize * 4)
|
|
||||||
} else if state == 1 {
|
|
||||||
blocksize = r.Intn(avgBlockSize * 2)
|
|
||||||
} else {
|
|
||||||
blocksize = 0
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// adds all future operations into the operation queue.
|
|
||||||
func queueOperations(queuedOperations map[int][]Operation, queuedTimeOperations []FutureOperation, futureOperations []FutureOperation) {
|
|
||||||
if futureOperations == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, futureOp := range futureOperations {
|
|
||||||
if futureOp.BlockHeight != 0 {
|
|
||||||
if val, ok := queuedOperations[futureOp.BlockHeight]; ok {
|
|
||||||
queuedOperations[futureOp.BlockHeight] = append(val, futureOp.Op)
|
|
||||||
} else {
|
|
||||||
queuedOperations[futureOp.BlockHeight] = []Operation{futureOp.Op}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// TODO: Replace with proper sorted data structure, so don't have the copy entire slice
|
|
||||||
index := sort.Search(len(queuedTimeOperations), func(i int) bool { return queuedTimeOperations[i].BlockTime.After(futureOp.BlockTime) })
|
|
||||||
queuedTimeOperations = append(queuedTimeOperations, FutureOperation{})
|
|
||||||
copy(queuedTimeOperations[index+1:], queuedTimeOperations[index:])
|
|
||||||
queuedTimeOperations[index] = futureOp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// nolint: errcheck
|
|
||||||
func runQueuedOperations(queueOperations map[int][]Operation, height int, tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
|
|
||||||
accounts []Account, logWriter func(string), displayLogs func(), event func(string)) (numOpsRan int) {
|
|
||||||
if queuedOps, ok := queueOperations[height]; ok {
|
|
||||||
numOps := len(queuedOps)
|
|
||||||
for i := 0; i < numOps; i++ {
|
|
||||||
// For now, queued operations cannot queue more operations.
|
|
||||||
// If a need arises for us to support queued messages to queue more messages, this can
|
|
||||||
// be changed.
|
|
||||||
logUpdate, _, err := queuedOps[i](r, app, ctx, accounts, event)
|
|
||||||
logWriter(logUpdate)
|
|
||||||
if err != nil {
|
|
||||||
displayLogs()
|
|
||||||
tb.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete(queueOperations, height)
|
|
||||||
return numOps
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func runQueuedTimeOperations(queueOperations []FutureOperation, currentTime time.Time, tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
|
|
||||||
accounts []Account, logWriter func(string), displayLogs func(), event func(string)) (numOpsRan int) {
|
|
||||||
|
|
||||||
numOpsRan = 0
|
|
||||||
for len(queueOperations) > 0 && currentTime.After(queueOperations[0].BlockTime) {
|
|
||||||
// For now, queued operations cannot queue more operations.
|
|
||||||
// If a need arises for us to support queued messages to queue more messages, this can
|
|
||||||
// be changed.
|
|
||||||
logUpdate, _, err := queueOperations[0].Op(r, app, ctx, accounts, event)
|
|
||||||
logWriter(logUpdate)
|
|
||||||
if err != nil {
|
|
||||||
displayLogs()
|
|
||||||
tb.FailNow()
|
|
||||||
}
|
|
||||||
queueOperations = queueOperations[1:]
|
|
||||||
numOpsRan++
|
|
||||||
}
|
|
||||||
return numOpsRan
|
|
||||||
}
|
|
||||||
|
|
||||||
func getKeys(validators map[string]mockValidator) []string {
|
|
||||||
keys := make([]string, len(validators))
|
|
||||||
i := 0
|
|
||||||
for key := range validators {
|
|
||||||
keys[i] = key
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
sort.Strings(keys)
|
|
||||||
return keys
|
|
||||||
}
|
|
||||||
|
|
||||||
// randomProposer picks a random proposer from the current validator set
|
|
||||||
func randomProposer(r *rand.Rand, validators map[string]mockValidator) cmn.HexBytes {
|
|
||||||
keys := getKeys(validators)
|
|
||||||
if len(keys) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
key := keys[r.Intn(len(keys))]
|
|
||||||
proposer := validators[key].val
|
|
||||||
pk, err := tmtypes.PB2TM.PubKey(proposer.PubKey)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return pk.Address()
|
|
||||||
}
|
|
||||||
|
|
||||||
// RandomRequestBeginBlock generates a list of signing validators according to the provided list of validators, signing fraction, and evidence fraction
|
|
||||||
// nolint: unparam
|
|
||||||
func RandomRequestBeginBlock(r *rand.Rand, params Params, validators map[string]mockValidator,
|
|
||||||
pastTimes []time.Time, pastVoteInfos [][]abci.VoteInfo, event func(string), header abci.Header) abci.RequestBeginBlock {
|
|
||||||
if len(validators) == 0 {
|
|
||||||
return abci.RequestBeginBlock{Header: header}
|
|
||||||
}
|
|
||||||
voteInfos := make([]abci.VoteInfo, len(validators))
|
|
||||||
i := 0
|
|
||||||
for _, key := range getKeys(validators) {
|
|
||||||
mVal := validators[key]
|
|
||||||
mVal.livenessState = params.LivenessTransitionMatrix.NextState(r, mVal.livenessState)
|
|
||||||
signed := true
|
|
||||||
|
|
||||||
if mVal.livenessState == 1 {
|
|
||||||
// spotty connection, 50% probability of success
|
|
||||||
// See https://github.com/golang/go/issues/23804#issuecomment-365370418
|
|
||||||
// for reasoning behind computing like this
|
|
||||||
signed = r.Int63()%2 == 0
|
|
||||||
} else if mVal.livenessState == 2 {
|
|
||||||
// offline
|
|
||||||
signed = false
|
|
||||||
}
|
|
||||||
if signed {
|
|
||||||
event("beginblock/signing/signed")
|
|
||||||
} else {
|
|
||||||
event("beginblock/signing/missed")
|
|
||||||
}
|
|
||||||
pubkey, err := tmtypes.PB2TM.PubKey(mVal.val.PubKey)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
voteInfos[i] = abci.VoteInfo{
|
|
||||||
Validator: abci.Validator{
|
|
||||||
Address: pubkey.Address(),
|
|
||||||
Power: mVal.val.Power,
|
|
||||||
},
|
|
||||||
SignedLastBlock: signed,
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
// TODO: Determine capacity before allocation
|
|
||||||
evidence := make([]abci.Evidence, 0)
|
|
||||||
// Anything but the first block
|
|
||||||
if len(pastTimes) > 0 {
|
|
||||||
for r.Float64() < params.EvidenceFraction {
|
|
||||||
height := header.Height
|
|
||||||
time := header.Time
|
|
||||||
vals := voteInfos
|
|
||||||
if r.Float64() < params.PastEvidenceFraction {
|
|
||||||
height = int64(r.Intn(int(header.Height) - 1))
|
|
||||||
time = pastTimes[height]
|
|
||||||
vals = pastVoteInfos[height]
|
|
||||||
}
|
|
||||||
validator := vals[r.Intn(len(vals))].Validator
|
|
||||||
var totalVotingPower int64
|
|
||||||
for _, val := range vals {
|
|
||||||
totalVotingPower += val.Validator.Power
|
|
||||||
}
|
|
||||||
evidence = append(evidence, abci.Evidence{
|
|
||||||
Type: tmtypes.ABCIEvidenceTypeDuplicateVote,
|
|
||||||
Validator: validator,
|
|
||||||
Height: height,
|
|
||||||
Time: time,
|
|
||||||
TotalVotingPower: totalVotingPower,
|
|
||||||
})
|
|
||||||
event("beginblock/evidence")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return abci.RequestBeginBlock{
|
|
||||||
Header: header,
|
|
||||||
LastCommitInfo: abci.LastCommitInfo{
|
|
||||||
Votes: voteInfos,
|
|
||||||
},
|
|
||||||
ByzantineValidators: evidence,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// updateValidators mimicks Tendermint's update logic
|
|
||||||
// nolint: unparam
|
|
||||||
func updateValidators(tb testing.TB, r *rand.Rand, params Params, current map[string]mockValidator, updates []abci.ValidatorUpdate, event func(string)) map[string]mockValidator {
|
|
||||||
|
|
||||||
for _, update := range updates {
|
|
||||||
str := fmt.Sprintf("%v", update.PubKey)
|
|
||||||
switch {
|
|
||||||
case update.Power == 0:
|
|
||||||
if _, ok := current[str]; !ok {
|
|
||||||
tb.Fatalf("tried to delete a nonexistent validator")
|
|
||||||
}
|
|
||||||
|
|
||||||
event("endblock/validatorupdates/kicked")
|
|
||||||
delete(current, str)
|
|
||||||
default:
|
|
||||||
// Does validator already exist?
|
|
||||||
if mVal, ok := current[str]; ok {
|
|
||||||
mVal.val = update
|
|
||||||
event("endblock/validatorupdates/updated")
|
|
||||||
} else {
|
|
||||||
// Set this new validator
|
|
||||||
current[str] = mockValidator{update, GetMemberOfInitialState(r, params.InitialLivenessWeightings)}
|
|
||||||
event("endblock/validatorupdates/added")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return current
|
|
||||||
}
|
|
|
@ -0,0 +1,330 @@
|
||||||
|
package simulation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"runtime/debug"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RandSetup performs the random setup the mock module needs.
|
||||||
|
type RandSetup func(r *rand.Rand, accounts []Account)
|
||||||
|
|
||||||
|
// AppStateFn returns the app state json bytes
|
||||||
|
type AppStateFn func(r *rand.Rand, accs []Account) json.RawMessage
|
||||||
|
|
||||||
|
// Simulate tests application by sending random messages.
|
||||||
|
func Simulate(t *testing.T, app *baseapp.BaseApp,
|
||||||
|
appStateFn AppStateFn, ops WeightedOperations, setups []RandSetup,
|
||||||
|
invariants Invariants, numBlocks int, blockSize int, commit bool) error {
|
||||||
|
|
||||||
|
time := time.Now().UnixNano()
|
||||||
|
return SimulateFromSeed(t, app, appStateFn, time, ops,
|
||||||
|
setups, invariants, numBlocks, blockSize, commit)
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize the chain for the simulation
|
||||||
|
func initChain(r *rand.Rand, params Params, accounts []Account,
|
||||||
|
setups []RandSetup, app *baseapp.BaseApp,
|
||||||
|
appStateFn AppStateFn) mockValidators {
|
||||||
|
|
||||||
|
req := abci.RequestInitChain{
|
||||||
|
AppStateBytes: appStateFn(r, accounts),
|
||||||
|
}
|
||||||
|
res := app.InitChain(req)
|
||||||
|
validators := newMockValidators(r, res.Validators, params)
|
||||||
|
|
||||||
|
for i := 0; i < len(setups); i++ {
|
||||||
|
setups[i](r, accounts)
|
||||||
|
}
|
||||||
|
return validators
|
||||||
|
}
|
||||||
|
|
||||||
|
// SimulateFromSeed tests an application by running the provided
|
||||||
|
// operations, testing the provided invariants, but using the provided seed.
|
||||||
|
// TODO split this monster function up
|
||||||
|
func SimulateFromSeed(tb testing.TB, app *baseapp.BaseApp,
|
||||||
|
appStateFn AppStateFn, seed int64, ops WeightedOperations,
|
||||||
|
setups []RandSetup, invariants Invariants,
|
||||||
|
numBlocks int, blockSize int, commit bool) (simError error) {
|
||||||
|
|
||||||
|
// in case we have to end early, don't os.Exit so that we can run cleanup code.
|
||||||
|
stopEarly := false
|
||||||
|
testingMode, t, b := getTestingMode(tb)
|
||||||
|
fmt.Printf("Starting SimulateFromSeed with randomness "+
|
||||||
|
"created with seed %d\n", int(seed))
|
||||||
|
|
||||||
|
r := rand.New(rand.NewSource(seed))
|
||||||
|
params := RandomParams(r) // := DefaultParams()
|
||||||
|
fmt.Printf("Randomized simulation params: %+v\n", params)
|
||||||
|
|
||||||
|
timestamp := RandTimestamp(r)
|
||||||
|
fmt.Printf("Starting the simulation from time %v, unixtime %v\n",
|
||||||
|
timestamp.UTC().Format(time.UnixDate), timestamp.Unix())
|
||||||
|
|
||||||
|
timeDiff := maxTimePerBlock - minTimePerBlock
|
||||||
|
accs := RandomAccounts(r, params.NumKeys)
|
||||||
|
eventStats := newEventStats()
|
||||||
|
|
||||||
|
// Second variable to keep pending validator set (delayed one block since
|
||||||
|
// TM 0.24) Initially this is the same as the initial validator set
|
||||||
|
validators := initChain(r, params, accs, setups, app, appStateFn)
|
||||||
|
nextValidators := validators
|
||||||
|
|
||||||
|
header := abci.Header{
|
||||||
|
Height: 1,
|
||||||
|
Time: timestamp,
|
||||||
|
ProposerAddress: validators.randomProposer(r),
|
||||||
|
}
|
||||||
|
opCount := 0
|
||||||
|
|
||||||
|
// Setup code to catch SIGTERM's
|
||||||
|
c := make(chan os.Signal)
|
||||||
|
signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
|
||||||
|
go func() {
|
||||||
|
receivedSignal := <-c
|
||||||
|
fmt.Printf("\nExiting early due to %s, on block %d, operation %d\n",
|
||||||
|
receivedSignal, header.Height, opCount)
|
||||||
|
simError = fmt.Errorf("Exited due to %s", receivedSignal)
|
||||||
|
stopEarly = true
|
||||||
|
}()
|
||||||
|
|
||||||
|
var pastTimes []time.Time
|
||||||
|
var pastVoteInfos [][]abci.VoteInfo
|
||||||
|
|
||||||
|
request := RandomRequestBeginBlock(r, params,
|
||||||
|
validators, pastTimes, pastVoteInfos, eventStats.tally, header)
|
||||||
|
|
||||||
|
// These are operations which have been queued by previous operations
|
||||||
|
operationQueue := newOperationQueue()
|
||||||
|
timeOperationQueue := []FutureOperation{}
|
||||||
|
var blockLogBuilders []*strings.Builder
|
||||||
|
|
||||||
|
if testingMode {
|
||||||
|
blockLogBuilders = make([]*strings.Builder, numBlocks)
|
||||||
|
}
|
||||||
|
displayLogs := logPrinter(testingMode, blockLogBuilders)
|
||||||
|
blockSimulator := createBlockSimulator(
|
||||||
|
testingMode, tb, t, params, eventStats.tally, invariants,
|
||||||
|
ops, operationQueue, timeOperationQueue,
|
||||||
|
numBlocks, blockSize, displayLogs)
|
||||||
|
|
||||||
|
if !testingMode {
|
||||||
|
b.ResetTimer()
|
||||||
|
} else {
|
||||||
|
// Recover logs in case of panic
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
fmt.Println("Panic with err\n", r)
|
||||||
|
stackTrace := string(debug.Stack())
|
||||||
|
fmt.Println(stackTrace)
|
||||||
|
displayLogs()
|
||||||
|
simError = fmt.Errorf(
|
||||||
|
"Simulation halted due to panic on block %d",
|
||||||
|
header.Height)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO split up the contents of this for loop into new functions
|
||||||
|
for i := 0; i < numBlocks && !stopEarly; i++ {
|
||||||
|
|
||||||
|
// Log the header time for future lookup
|
||||||
|
pastTimes = append(pastTimes, header.Time)
|
||||||
|
pastVoteInfos = append(pastVoteInfos, request.LastCommitInfo.Votes)
|
||||||
|
|
||||||
|
// Construct log writer
|
||||||
|
logWriter := addLogMessage(testingMode, blockLogBuilders, i)
|
||||||
|
|
||||||
|
// Run the BeginBlock handler
|
||||||
|
logWriter("BeginBlock")
|
||||||
|
app.BeginBlock(request)
|
||||||
|
|
||||||
|
if testingMode {
|
||||||
|
invariants.assertAll(t, app, "BeginBlock", displayLogs)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := app.NewContext(false, header)
|
||||||
|
|
||||||
|
// Run queued operations. Ignores blocksize if blocksize is too small
|
||||||
|
logWriter("Queued operations")
|
||||||
|
numQueuedOpsRan := runQueuedOperations(
|
||||||
|
operationQueue, int(header.Height),
|
||||||
|
tb, r, app, ctx, accs, logWriter,
|
||||||
|
displayLogs, eventStats.tally)
|
||||||
|
|
||||||
|
numQueuedTimeOpsRan := runQueuedTimeOperations(
|
||||||
|
timeOperationQueue, header.Time,
|
||||||
|
tb, r, app, ctx, accs,
|
||||||
|
logWriter, displayLogs, eventStats.tally)
|
||||||
|
|
||||||
|
if testingMode && onOperation {
|
||||||
|
invariants.assertAll(t, app, "QueuedOperations", displayLogs)
|
||||||
|
}
|
||||||
|
|
||||||
|
logWriter("Standard operations")
|
||||||
|
operations := blockSimulator(r, app, ctx, accs, header, logWriter)
|
||||||
|
opCount += operations + numQueuedOpsRan + numQueuedTimeOpsRan
|
||||||
|
if testingMode {
|
||||||
|
invariants.assertAll(t, app, "StandardOperations", displayLogs)
|
||||||
|
}
|
||||||
|
|
||||||
|
res := app.EndBlock(abci.RequestEndBlock{})
|
||||||
|
header.Height++
|
||||||
|
header.Time = header.Time.Add(
|
||||||
|
time.Duration(minTimePerBlock) * time.Second)
|
||||||
|
header.Time = header.Time.Add(
|
||||||
|
time.Duration(int64(r.Intn(int(timeDiff)))) * time.Second)
|
||||||
|
header.ProposerAddress = validators.randomProposer(r)
|
||||||
|
logWriter("EndBlock")
|
||||||
|
|
||||||
|
if testingMode {
|
||||||
|
invariants.assertAll(t, app, "EndBlock", displayLogs)
|
||||||
|
}
|
||||||
|
if commit {
|
||||||
|
app.Commit()
|
||||||
|
}
|
||||||
|
|
||||||
|
if header.ProposerAddress == nil {
|
||||||
|
fmt.Printf("\nSimulation stopped early as all validators " +
|
||||||
|
"have been unbonded, there is nobody left propose a block!\n")
|
||||||
|
stopEarly = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate a random RequestBeginBlock with the current validator set
|
||||||
|
// for the next block
|
||||||
|
request = RandomRequestBeginBlock(r, params, validators,
|
||||||
|
pastTimes, pastVoteInfos, eventStats.tally, header)
|
||||||
|
|
||||||
|
// Update the validator set, which will be reflected in the application
|
||||||
|
// on the next block
|
||||||
|
validators = nextValidators
|
||||||
|
nextValidators = updateValidators(tb, r, params,
|
||||||
|
validators, res.ValidatorUpdates, eventStats.tally)
|
||||||
|
}
|
||||||
|
|
||||||
|
if stopEarly {
|
||||||
|
eventStats.Print()
|
||||||
|
return simError
|
||||||
|
}
|
||||||
|
fmt.Printf("\nSimulation complete. Final height (blocks): %d, "+
|
||||||
|
"final time (seconds), : %v, operations ran %d\n",
|
||||||
|
header.Height, header.Time, opCount)
|
||||||
|
|
||||||
|
eventStats.Print()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//______________________________________________________________________________
|
||||||
|
|
||||||
|
type blockSimFn func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
|
||||||
|
accounts []Account, header abci.Header, logWriter func(string)) (opCount int)
|
||||||
|
|
||||||
|
// Returns a function to simulate blocks. Written like this to avoid constant
|
||||||
|
// parameters being passed everytime, to minimize memory overhead.
|
||||||
|
func createBlockSimulator(testingMode bool, tb testing.TB, t *testing.T, params Params,
|
||||||
|
event func(string), invariants Invariants, ops WeightedOperations,
|
||||||
|
operationQueue OperationQueue, timeOperationQueue []FutureOperation,
|
||||||
|
totalNumBlocks int, avgBlockSize int, displayLogs func()) blockSimFn {
|
||||||
|
|
||||||
|
var lastBlocksizeState = 0 // state for [4 * uniform distribution]
|
||||||
|
var blocksize int
|
||||||
|
selectOp := ops.getSelectOpFn()
|
||||||
|
|
||||||
|
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
|
||||||
|
accounts []Account, header abci.Header, logWriter func(string)) (opCount int) {
|
||||||
|
|
||||||
|
fmt.Printf("\rSimulating... block %d/%d, operation %d/%d. ",
|
||||||
|
header.Height, totalNumBlocks, opCount, blocksize)
|
||||||
|
lastBlocksizeState, blocksize = getBlockSize(r, params, lastBlocksizeState, avgBlockSize)
|
||||||
|
|
||||||
|
for i := 0; i < blocksize; i++ {
|
||||||
|
|
||||||
|
logUpdate, futureOps, err := selectOp(r)(r, app, ctx, accounts, event)
|
||||||
|
logWriter(logUpdate)
|
||||||
|
if err != nil {
|
||||||
|
displayLogs()
|
||||||
|
tb.Fatalf("error on operation %d within block %d, %v",
|
||||||
|
header.Height, opCount, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
queueOperations(operationQueue, timeOperationQueue, futureOps)
|
||||||
|
if testingMode {
|
||||||
|
if onOperation {
|
||||||
|
eventStr := fmt.Sprintf("operation: %v", logUpdate)
|
||||||
|
invariants.assertAll(t, app, eventStr, displayLogs)
|
||||||
|
}
|
||||||
|
if opCount%50 == 0 {
|
||||||
|
fmt.Printf("\rSimulating... block %d/%d, operation %d/%d. ",
|
||||||
|
header.Height, totalNumBlocks, opCount, blocksize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
opCount++
|
||||||
|
}
|
||||||
|
return opCount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// nolint: errcheck
|
||||||
|
func runQueuedOperations(queueOps map[int][]Operation,
|
||||||
|
height int, tb testing.TB, r *rand.Rand, app *baseapp.BaseApp,
|
||||||
|
ctx sdk.Context, accounts []Account, logWriter func(string),
|
||||||
|
displayLogs func(), tallyEvent func(string)) (numOpsRan int) {
|
||||||
|
|
||||||
|
queuedOp, ok := queueOps[height]
|
||||||
|
if !ok {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
numOpsRan = len(queuedOp)
|
||||||
|
for i := 0; i < numOpsRan; i++ {
|
||||||
|
|
||||||
|
// For now, queued operations cannot queue more operations.
|
||||||
|
// If a need arises for us to support queued messages to queue more messages, this can
|
||||||
|
// be changed.
|
||||||
|
logUpdate, _, err := queuedOp[i](r, app, ctx, accounts, tallyEvent)
|
||||||
|
logWriter(logUpdate)
|
||||||
|
if err != nil {
|
||||||
|
displayLogs()
|
||||||
|
tb.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete(queueOps, height)
|
||||||
|
return numOpsRan
|
||||||
|
}
|
||||||
|
|
||||||
|
func runQueuedTimeOperations(queueOps []FutureOperation,
|
||||||
|
currentTime time.Time, tb testing.TB, r *rand.Rand,
|
||||||
|
app *baseapp.BaseApp, ctx sdk.Context, accounts []Account,
|
||||||
|
logWriter func(string), displayLogs func(), tallyEvent func(string)) (numOpsRan int) {
|
||||||
|
|
||||||
|
numOpsRan = 0
|
||||||
|
for len(queueOps) > 0 && currentTime.After(queueOps[0].BlockTime) {
|
||||||
|
|
||||||
|
// For now, queued operations cannot queue more operations.
|
||||||
|
// If a need arises for us to support queued messages to queue more messages, this can
|
||||||
|
// be changed.
|
||||||
|
logUpdate, _, err := queueOps[0].Op(r, app, ctx, accounts, tallyEvent)
|
||||||
|
logWriter(logUpdate)
|
||||||
|
if err != nil {
|
||||||
|
displayLogs()
|
||||||
|
tb.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
queueOps = queueOps[1:]
|
||||||
|
numOpsRan++
|
||||||
|
}
|
||||||
|
return numOpsRan
|
||||||
|
}
|
|
@ -5,12 +5,11 @@ import (
|
||||||
"math/rand"
|
"math/rand"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TransitionMatrix is _almost_ a left stochastic matrix.
|
// TransitionMatrix is _almost_ a left stochastic matrix. It is technically
|
||||||
// It is technically not one due to not normalizing the column values.
|
// not one due to not normalizing the column values. In the future, if we want
|
||||||
// In the future, if we want to find the steady state distribution,
|
// to find the steady state distribution, it will be quite easy to normalize
|
||||||
// it will be quite easy to normalize these values to get a stochastic matrix.
|
// these values to get a stochastic matrix. Floats aren't currently used as
|
||||||
// Floats aren't currently used as the default due to non-determinism across
|
// the default due to non-determinism across architectures
|
||||||
// architectures
|
|
||||||
type TransitionMatrix struct {
|
type TransitionMatrix struct {
|
||||||
weights [][]int
|
weights [][]int
|
||||||
// total in each column
|
// total in each column
|
||||||
|
@ -24,7 +23,8 @@ func CreateTransitionMatrix(weights [][]int) (TransitionMatrix, error) {
|
||||||
n := len(weights)
|
n := len(weights)
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
if len(weights[i]) != n {
|
if len(weights[i]) != n {
|
||||||
return TransitionMatrix{}, fmt.Errorf("Transition Matrix: Non-square matrix provided, error on row %d", i)
|
return TransitionMatrix{},
|
||||||
|
fmt.Errorf("Transition Matrix: Non-square matrix provided, error on row %d", i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
totals := make([]int, n)
|
totals := make([]int, n)
|
||||||
|
@ -36,8 +36,8 @@ func CreateTransitionMatrix(weights [][]int) (TransitionMatrix, error) {
|
||||||
return TransitionMatrix{weights, totals, n}, nil
|
return TransitionMatrix{weights, totals, n}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NextState returns the next state randomly chosen using r, and the weightings provided
|
// NextState returns the next state randomly chosen using r, and the weightings
|
||||||
// in the transition matrix.
|
// provided in the transition matrix.
|
||||||
func (t TransitionMatrix) NextState(r *rand.Rand, i int) int {
|
func (t TransitionMatrix) NextState(r *rand.Rand, i int) int {
|
||||||
randNum := r.Intn(t.totals[i])
|
randNum := r.Intn(t.totals[i])
|
||||||
for row := 0; row < t.n; row++ {
|
for row := 0; row < t.n; row++ {
|
||||||
|
|
|
@ -1,87 +0,0 @@
|
||||||
package simulation
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math/rand"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
|
||||||
"github.com/tendermint/tendermint/crypto"
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
|
||||||
// Operation runs a state machine transition,
|
|
||||||
// and ensures the transition happened as expected.
|
|
||||||
// The operation could be running and testing a fuzzed transaction,
|
|
||||||
// or doing the same for a message.
|
|
||||||
//
|
|
||||||
// For ease of debugging,
|
|
||||||
// an operation returns a descriptive message "action",
|
|
||||||
// which details what this fuzzed state machine transition actually did.
|
|
||||||
//
|
|
||||||
// Operations can optionally provide a list of "FutureOperations" to run later
|
|
||||||
// These will be ran at the beginning of the corresponding block.
|
|
||||||
Operation func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
|
|
||||||
accounts []Account, event func(string),
|
|
||||||
) (action string, futureOperations []FutureOperation, err error)
|
|
||||||
|
|
||||||
// RandSetup performs the random setup the mock module needs.
|
|
||||||
RandSetup func(r *rand.Rand, accounts []Account)
|
|
||||||
|
|
||||||
// An Invariant is a function which tests a particular invariant.
|
|
||||||
// If the invariant has been broken, it should return an error
|
|
||||||
// containing a descriptive message about what happened.
|
|
||||||
// The simulator will then halt and print the logs.
|
|
||||||
Invariant func(app *baseapp.BaseApp) error
|
|
||||||
|
|
||||||
// Account contains a privkey, pubkey, address tuple
|
|
||||||
// eventually more useful data can be placed in here.
|
|
||||||
// (e.g. number of coins)
|
|
||||||
Account struct {
|
|
||||||
PrivKey crypto.PrivKey
|
|
||||||
PubKey crypto.PubKey
|
|
||||||
Address sdk.AccAddress
|
|
||||||
}
|
|
||||||
|
|
||||||
mockValidator struct {
|
|
||||||
val abci.ValidatorUpdate
|
|
||||||
livenessState int
|
|
||||||
}
|
|
||||||
|
|
||||||
// FutureOperation is an operation which will be ran at the
|
|
||||||
// beginning of the provided BlockHeight.
|
|
||||||
// If both a BlockHeight and BlockTime are specified, it will use the BlockHeight.
|
|
||||||
// In the (likely) event that multiple operations are queued at the same
|
|
||||||
// block height, they will execute in a FIFO pattern.
|
|
||||||
FutureOperation struct {
|
|
||||||
BlockHeight int
|
|
||||||
BlockTime time.Time
|
|
||||||
Op Operation
|
|
||||||
}
|
|
||||||
|
|
||||||
// WeightedOperation is an operation with associated weight.
|
|
||||||
// This is used to bias the selection operation within the simulator.
|
|
||||||
WeightedOperation struct {
|
|
||||||
Weight int
|
|
||||||
Op Operation
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// TODO remove? not being called anywhere
|
|
||||||
// PeriodicInvariant returns an Invariant function closure that asserts
|
|
||||||
// a given invariant if the mock application's last block modulo the given
|
|
||||||
// period is congruent to the given offset.
|
|
||||||
func PeriodicInvariant(invariant Invariant, period int, offset int) Invariant {
|
|
||||||
return func(app *baseapp.BaseApp) error {
|
|
||||||
if int(app.LastBlockHeight())%period == offset {
|
|
||||||
return invariant(app)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// nolint
|
|
||||||
func (acc Account) Equals(acc2 Account) bool {
|
|
||||||
return acc.Address.Equals(acc2.Address)
|
|
||||||
}
|
|
|
@ -2,139 +2,47 @@ package simulation
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/tendermint/tendermint/crypto/ed25519"
|
|
||||||
"github.com/tendermint/tendermint/crypto/secp256k1"
|
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
||||||
"github.com/cosmos/cosmos-sdk/x/mock"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// shamelessly copied from https://stackoverflow.com/questions/22892120/how-to-generate-a-random-string-of-a-fixed-length-in-golang#31832326
|
func getTestingMode(tb testing.TB) (testingMode bool, t *testing.T, b *testing.B) {
|
||||||
// TODO we should probably move this to tendermint/libs/common/random.go
|
testingMode = false
|
||||||
|
if _t, ok := tb.(*testing.T); ok {
|
||||||
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
t = _t
|
||||||
const (
|
testingMode = true
|
||||||
letterIdxBits = 6 // 6 bits to represent a letter index
|
|
||||||
letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
|
|
||||||
letterIdxMax = 63 / letterIdxBits // # of letter indices fitting in 63 bits
|
|
||||||
)
|
|
||||||
|
|
||||||
// Generate a random string of a particular length
|
|
||||||
func RandStringOfLength(r *rand.Rand, n int) string {
|
|
||||||
b := make([]byte, n)
|
|
||||||
// A src.Int63() generates 63 random bits, enough for letterIdxMax characters!
|
|
||||||
for i, cache, remain := n-1, r.Int63(), letterIdxMax; i >= 0; {
|
|
||||||
if remain == 0 {
|
|
||||||
cache, remain = r.Int63(), letterIdxMax
|
|
||||||
}
|
|
||||||
if idx := int(cache & letterIdxMask); idx < len(letterBytes) {
|
|
||||||
b[i] = letterBytes[idx]
|
|
||||||
i--
|
|
||||||
}
|
|
||||||
cache >>= letterIdxBits
|
|
||||||
remain--
|
|
||||||
}
|
|
||||||
return string(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pretty-print events as a table
|
|
||||||
func DisplayEvents(events map[string]uint) {
|
|
||||||
var keys []string
|
|
||||||
for key := range events {
|
|
||||||
keys = append(keys, key)
|
|
||||||
}
|
|
||||||
sort.Strings(keys)
|
|
||||||
fmt.Printf("Event statistics: \n")
|
|
||||||
for _, key := range keys {
|
|
||||||
fmt.Printf(" % 60s => %d\n", key, events[key])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RandomAcc pick a random account from an array
|
|
||||||
func RandomAcc(r *rand.Rand, accs []Account) Account {
|
|
||||||
return accs[r.Intn(
|
|
||||||
len(accs),
|
|
||||||
)]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate a random amount
|
|
||||||
func RandomAmount(r *rand.Rand, max sdk.Int) sdk.Int {
|
|
||||||
return sdk.NewInt(int64(r.Intn(int(max.Int64()))))
|
|
||||||
}
|
|
||||||
|
|
||||||
// RandomDecAmount generates a random decimal amount
|
|
||||||
func RandomDecAmount(r *rand.Rand, max sdk.Dec) sdk.Dec {
|
|
||||||
randInt := big.NewInt(0).Rand(r, max.Int)
|
|
||||||
return sdk.NewDecFromBigIntWithPrec(randInt, sdk.Precision)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RandomAccounts generates n random accounts
|
|
||||||
func RandomAccounts(r *rand.Rand, n int) []Account {
|
|
||||||
accs := make([]Account, n)
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
// don't need that much entropy for simulation
|
|
||||||
privkeySeed := make([]byte, 15)
|
|
||||||
r.Read(privkeySeed)
|
|
||||||
useSecp := r.Int63()%2 == 0
|
|
||||||
if useSecp {
|
|
||||||
accs[i].PrivKey = secp256k1.GenPrivKeySecp256k1(privkeySeed)
|
|
||||||
} else {
|
} else {
|
||||||
accs[i].PrivKey = ed25519.GenPrivKeyFromSecret(privkeySeed)
|
b = tb.(*testing.B)
|
||||||
}
|
}
|
||||||
accs[i].PubKey = accs[i].PrivKey.PubKey()
|
return
|
||||||
accs[i].Address = sdk.AccAddress(accs[i].PubKey.Address())
|
|
||||||
}
|
|
||||||
return accs
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Builds a function to add logs for this particular block
|
// Builds a function to add logs for this particular block
|
||||||
func addLogMessage(testingmode bool, blockLogBuilders []*strings.Builder, height int) func(string) {
|
func addLogMessage(testingmode bool,
|
||||||
if testingmode {
|
blockLogBuilders []*strings.Builder, height int) func(string) {
|
||||||
|
|
||||||
|
if !testingmode {
|
||||||
|
return func(_ string) {}
|
||||||
|
}
|
||||||
|
|
||||||
blockLogBuilders[height] = &strings.Builder{}
|
blockLogBuilders[height] = &strings.Builder{}
|
||||||
return func(x string) {
|
return func(x string) {
|
||||||
(*blockLogBuilders[height]).WriteString(x)
|
(*blockLogBuilders[height]).WriteString(x)
|
||||||
(*blockLogBuilders[height]).WriteString("\n")
|
(*blockLogBuilders[height]).WriteString("\n")
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return func(x string) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// assertAllInvariants asserts a list of provided invariants against application state
|
|
||||||
func assertAllInvariants(t *testing.T, app *baseapp.BaseApp,
|
|
||||||
invariants []Invariant, where string, displayLogs func()) {
|
|
||||||
|
|
||||||
for i := 0; i < len(invariants); i++ {
|
|
||||||
err := invariants[i](app)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Invariants broken after %s\n", where)
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
displayLogs()
|
|
||||||
t.Fatal()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RandomSetGenesis wraps mock.RandomSetGenesis, but using simulation accounts
|
|
||||||
func RandomSetGenesis(r *rand.Rand, app *mock.App, accs []Account, denoms []string) {
|
|
||||||
addrs := make([]sdk.AccAddress, len(accs))
|
|
||||||
for i := 0; i < len(accs); i++ {
|
|
||||||
addrs[i] = accs[i].Address
|
|
||||||
}
|
|
||||||
mock.RandomSetGenesis(r, app, addrs, denoms)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a function to print out the logs
|
// Creates a function to print out the logs
|
||||||
func logPrinter(testingmode bool, logs []*strings.Builder) func() {
|
func logPrinter(testingmode bool, logs []*strings.Builder) func() {
|
||||||
if testingmode {
|
if !testingmode {
|
||||||
|
return func() {}
|
||||||
|
}
|
||||||
|
|
||||||
return func() {
|
return func() {
|
||||||
numLoggers := 0
|
numLoggers := 0
|
||||||
for i := 0; i < len(logs); i++ {
|
for i := 0; i < len(logs); i++ {
|
||||||
|
@ -144,28 +52,71 @@ func logPrinter(testingmode bool, logs []*strings.Builder) func() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var f *os.File
|
var f *os.File
|
||||||
if numLoggers > 10 {
|
if numLoggers > 10 {
|
||||||
fileName := fmt.Sprintf("simulation_log_%s.txt", time.Now().Format("2006-01-02 15:04:05"))
|
fileName := fmt.Sprintf("simulation_log_%s.txt",
|
||||||
fmt.Printf("Too many logs to display, instead writing to %s\n", fileName)
|
time.Now().Format("2006-01-02 15:04:05"))
|
||||||
|
fmt.Printf("Too many logs to display, instead writing to %s\n",
|
||||||
|
fileName)
|
||||||
f, _ = os.Create(fileName)
|
f, _ = os.Create(fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < numLoggers; i++ {
|
for i := 0; i < numLoggers; i++ {
|
||||||
if f != nil {
|
if f == nil {
|
||||||
|
fmt.Printf("Begin block %d\n", i+1)
|
||||||
|
fmt.Println((*logs[i]).String())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
_, err := f.WriteString(fmt.Sprintf("Begin block %d\n", i+1))
|
_, err := f.WriteString(fmt.Sprintf("Begin block %d\n", i+1))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("Failed to write logs to file")
|
panic("Failed to write logs to file")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = f.WriteString((*logs[i]).String())
|
_, err = f.WriteString((*logs[i]).String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("Failed to write logs to file")
|
panic("Failed to write logs to file")
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
fmt.Printf("Begin block %d\n", i+1)
|
|
||||||
fmt.Println((*logs[i]).String())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return func() {}
|
// getBlockSize returns a block size as determined from the transition matrix.
|
||||||
|
// It targets making average block size the provided parameter. The three
|
||||||
|
// states it moves between are:
|
||||||
|
// - "over stuffed" blocks with average size of 2 * avgblocksize,
|
||||||
|
// - normal sized blocks, hitting avgBlocksize on average,
|
||||||
|
// - and empty blocks, with no txs / only txs scheduled from the past.
|
||||||
|
func getBlockSize(r *rand.Rand, params Params,
|
||||||
|
lastBlockSizeState, avgBlockSize int) (state, blocksize int) {
|
||||||
|
|
||||||
|
// TODO: Make default blocksize transition matrix actually make the average
|
||||||
|
// blocksize equal to avgBlockSize.
|
||||||
|
state = params.BlockSizeTransitionMatrix.NextState(r, lastBlockSizeState)
|
||||||
|
switch state {
|
||||||
|
case 0:
|
||||||
|
blocksize = r.Intn(avgBlockSize * 4)
|
||||||
|
case 1:
|
||||||
|
blocksize = r.Intn(avgBlockSize * 2)
|
||||||
|
default:
|
||||||
|
blocksize = 0
|
||||||
|
}
|
||||||
|
return state, blocksize
|
||||||
|
}
|
||||||
|
|
||||||
|
// PeriodicInvariant returns an Invariant function closure that asserts a given
|
||||||
|
// invariant if the mock application's last block modulo the given period is
|
||||||
|
// congruent to the given offset.
|
||||||
|
//
|
||||||
|
// NOTE this function is intended to be used manually used while running
|
||||||
|
// computationally heavy simulations.
|
||||||
|
// TODO reference this function in the codebase probably through use of a switch
|
||||||
|
func PeriodicInvariant(invariant Invariant, period int, offset int) Invariant {
|
||||||
|
return func(app *baseapp.BaseApp) error {
|
||||||
|
if int(app.LastBlockHeight())%period == offset {
|
||||||
|
return invariant(app)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,15 +3,17 @@ package slashing
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
|
"github.com/tendermint/tendermint/crypto/ed25519"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||||
"github.com/cosmos/cosmos-sdk/x/mock"
|
"github.com/cosmos/cosmos-sdk/x/mock"
|
||||||
"github.com/cosmos/cosmos-sdk/x/params"
|
"github.com/cosmos/cosmos-sdk/x/params"
|
||||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||||
"github.com/stretchr/testify/require"
|
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
|
||||||
"github.com/tendermint/tendermint/crypto/ed25519"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -93,8 +95,8 @@ func checkValidatorSigningInfo(t *testing.T, mapp *mock.App, keeper Keeper,
|
||||||
func TestSlashingMsgs(t *testing.T) {
|
func TestSlashingMsgs(t *testing.T) {
|
||||||
mapp, stakeKeeper, keeper := getMockApp(t)
|
mapp, stakeKeeper, keeper := getMockApp(t)
|
||||||
|
|
||||||
genCoin := sdk.NewInt64Coin("steak", 42)
|
genCoin := sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 42)
|
||||||
bondCoin := sdk.NewInt64Coin("steak", 10)
|
bondCoin := sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 10)
|
||||||
|
|
||||||
acc1 := &auth.BaseAccount{
|
acc1 := &auth.BaseAccount{
|
||||||
Address: addr1,
|
Address: addr1,
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||||
"github.com/cosmos/cosmos-sdk/x/params"
|
"github.com/cosmos/cosmos-sdk/x/params"
|
||||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||||
|
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO remove dependencies on staking (should only refer to validator set type from sdk)
|
// TODO remove dependencies on staking (should only refer to validator set type from sdk)
|
||||||
|
@ -120,7 +121,7 @@ func NewTestMsgCreateValidator(address sdk.ValAddress, pubKey crypto.PubKey, amt
|
||||||
DelegatorAddr: sdk.AccAddress(address),
|
DelegatorAddr: sdk.AccAddress(address),
|
||||||
ValidatorAddr: address,
|
ValidatorAddr: address,
|
||||||
PubKey: pubKey,
|
PubKey: pubKey,
|
||||||
Delegation: sdk.NewCoin("steak", amt),
|
Delegation: sdk.NewCoin(stakeTypes.DefaultBondDenom, amt),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,6 +129,6 @@ func newTestMsgDelegate(delAddr sdk.AccAddress, valAddr sdk.ValAddress, delAmoun
|
||||||
return stake.MsgDelegate{
|
return stake.MsgDelegate{
|
||||||
DelegatorAddr: delAddr,
|
DelegatorAddr: delAddr,
|
||||||
ValidatorAddr: valAddr,
|
ValidatorAddr: valAddr,
|
||||||
Delegation: sdk.NewCoin("steak", delAmount),
|
Delegation: sdk.NewCoin(stakeTypes.DefaultBondDenom, delAmount),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,13 +3,15 @@ package stake
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||||
"github.com/cosmos/cosmos-sdk/x/mock"
|
"github.com/cosmos/cosmos-sdk/x/mock"
|
||||||
"github.com/cosmos/cosmos-sdk/x/params"
|
"github.com/cosmos/cosmos-sdk/x/params"
|
||||||
"github.com/stretchr/testify/require"
|
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// getMockApp returns an initialized mock application for this module.
|
// getMockApp returns an initialized mock application for this module.
|
||||||
|
@ -100,8 +102,8 @@ func checkDelegation(
|
||||||
func TestStakeMsgs(t *testing.T) {
|
func TestStakeMsgs(t *testing.T) {
|
||||||
mApp, keeper := getMockApp(t)
|
mApp, keeper := getMockApp(t)
|
||||||
|
|
||||||
genCoin := sdk.NewInt64Coin("steak", 42)
|
genCoin := sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 42)
|
||||||
bondCoin := sdk.NewInt64Coin("steak", 10)
|
bondCoin := sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 10)
|
||||||
|
|
||||||
acc1 := &auth.BaseAccount{
|
acc1 := &auth.BaseAccount{
|
||||||
Address: addr1,
|
Address: addr1,
|
||||||
|
|
|
@ -2,6 +2,7 @@ package cli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/client"
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
"github.com/cosmos/cosmos-sdk/client/context"
|
"github.com/cosmos/cosmos-sdk/client/context"
|
||||||
"github.com/cosmos/cosmos-sdk/client/utils"
|
"github.com/cosmos/cosmos-sdk/client/utils"
|
||||||
|
@ -210,26 +211,11 @@ func GetCmdDelegate(cdc *codec.Codec) *cobra.Command {
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCmdRedelegate implements the redelegate validator command.
|
// GetCmdRedelegate the begin redelegation command.
|
||||||
func GetCmdRedelegate(storeName string, cdc *codec.Codec) *cobra.Command {
|
func GetCmdRedelegate(storeName string, cdc *codec.Codec) *cobra.Command {
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "redelegate",
|
Use: "redelegate",
|
||||||
Short: "redelegate illiquid tokens from one validator to another",
|
Short: "redelegate illiquid tokens from one validator to another",
|
||||||
}
|
|
||||||
|
|
||||||
cmd.AddCommand(
|
|
||||||
client.PostCommands(
|
|
||||||
GetCmdBeginRedelegate(storeName, cdc),
|
|
||||||
)...)
|
|
||||||
|
|
||||||
return cmd
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetCmdBeginRedelegate the begin redelegation command.
|
|
||||||
func GetCmdBeginRedelegate(storeName string, cdc *codec.Codec) *cobra.Command {
|
|
||||||
cmd := &cobra.Command{
|
|
||||||
Use: "begin",
|
|
||||||
Short: "begin redelegation",
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc)
|
txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc)
|
||||||
cliCtx := context.NewCLIContext().
|
cliCtx := context.NewCLIContext().
|
||||||
|
@ -284,22 +270,7 @@ func GetCmdBeginRedelegate(storeName string, cdc *codec.Codec) *cobra.Command {
|
||||||
func GetCmdUnbond(storeName string, cdc *codec.Codec) *cobra.Command {
|
func GetCmdUnbond(storeName string, cdc *codec.Codec) *cobra.Command {
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "unbond",
|
Use: "unbond",
|
||||||
Short: "begin or complete unbonding shares from a validator",
|
Short: "unbond shares from a validator",
|
||||||
}
|
|
||||||
|
|
||||||
cmd.AddCommand(
|
|
||||||
client.PostCommands(
|
|
||||||
GetCmdBeginUnbonding(storeName, cdc),
|
|
||||||
)...)
|
|
||||||
|
|
||||||
return cmd
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetCmdBeginUnbonding implements the begin unbonding validator command.
|
|
||||||
func GetCmdBeginUnbonding(storeName string, cdc *codec.Codec) *cobra.Command {
|
|
||||||
cmd := &cobra.Command{
|
|
||||||
Use: "begin",
|
|
||||||
Short: "begin unbonding",
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc)
|
txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc)
|
||||||
cliCtx := context.NewCLIContext().
|
cliCtx := context.NewCLIContext().
|
||||||
|
|
|
@ -142,7 +142,7 @@ func TestUnbondingDelegation(t *testing.T) {
|
||||||
ValidatorAddr: addrVals[0],
|
ValidatorAddr: addrVals[0],
|
||||||
CreationHeight: 0,
|
CreationHeight: 0,
|
||||||
MinTime: time.Unix(0, 0),
|
MinTime: time.Unix(0, 0),
|
||||||
Balance: sdk.NewInt64Coin("steak", 5),
|
Balance: sdk.NewInt64Coin(types.DefaultBondDenom, 5),
|
||||||
}
|
}
|
||||||
|
|
||||||
// set and retrieve a record
|
// set and retrieve a record
|
||||||
|
@ -152,7 +152,7 @@ func TestUnbondingDelegation(t *testing.T) {
|
||||||
require.True(t, ubd.Equal(resUnbond))
|
require.True(t, ubd.Equal(resUnbond))
|
||||||
|
|
||||||
// modify a records, save, and retrieve
|
// modify a records, save, and retrieve
|
||||||
ubd.Balance = sdk.NewInt64Coin("steak", 21)
|
ubd.Balance = sdk.NewInt64Coin(types.DefaultBondDenom, 21)
|
||||||
keeper.SetUnbondingDelegation(ctx, ubd)
|
keeper.SetUnbondingDelegation(ctx, ubd)
|
||||||
|
|
||||||
resUnbonds := keeper.GetUnbondingDelegations(ctx, addrDels[0], 5)
|
resUnbonds := keeper.GetUnbondingDelegations(ctx, addrDels[0], 5)
|
||||||
|
|
|
@ -178,7 +178,7 @@ func TestQueryDelegation(t *testing.T) {
|
||||||
pool = keeper.GetPool(ctx)
|
pool = keeper.GetPool(ctx)
|
||||||
keeper.SetValidatorByPowerIndex(ctx, val2, pool)
|
keeper.SetValidatorByPowerIndex(ctx, val2, pool)
|
||||||
|
|
||||||
keeper.Delegate(ctx, addrAcc2, sdk.NewCoin("steak", sdk.NewInt(20)), val1, true)
|
keeper.Delegate(ctx, addrAcc2, sdk.NewCoin(types.DefaultBondDenom, sdk.NewInt(20)), val1, true)
|
||||||
|
|
||||||
// apply TM updates
|
// apply TM updates
|
||||||
keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||||
|
@ -358,7 +358,7 @@ func TestQueryRedelegations(t *testing.T) {
|
||||||
keeper.SetValidator(ctx, val1)
|
keeper.SetValidator(ctx, val1)
|
||||||
keeper.SetValidator(ctx, val2)
|
keeper.SetValidator(ctx, val2)
|
||||||
|
|
||||||
keeper.Delegate(ctx, addrAcc2, sdk.NewCoin("steak", sdk.NewInt(100)), val1, true)
|
keeper.Delegate(ctx, addrAcc2, sdk.NewCoin(types.DefaultBondDenom, sdk.NewInt(100)), val1, true)
|
||||||
keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||||
|
|
||||||
keeper.BeginRedelegation(ctx, addrAcc2, val1.GetOperator(), val2.GetOperator(), sdk.NewDec(20))
|
keeper.BeginRedelegation(ctx, addrAcc2, val1.GetOperator(), val2.GetOperator(), sdk.NewDec(20))
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"github.com/cosmos/cosmos-sdk/x/mock/simulation"
|
"github.com/cosmos/cosmos-sdk/x/mock/simulation"
|
||||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||||
"github.com/cosmos/cosmos-sdk/x/stake/keeper"
|
"github.com/cosmos/cosmos-sdk/x/stake/keeper"
|
||||||
|
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -48,7 +49,7 @@ func SupplyInvariants(ck bank.Keeper, k stake.Keeper,
|
||||||
loose := sdk.ZeroDec()
|
loose := sdk.ZeroDec()
|
||||||
bonded := sdk.ZeroDec()
|
bonded := sdk.ZeroDec()
|
||||||
am.IterateAccounts(ctx, func(acc auth.Account) bool {
|
am.IterateAccounts(ctx, func(acc auth.Account) bool {
|
||||||
loose = loose.Add(sdk.NewDecFromInt(acc.GetCoins().AmountOf("steak")))
|
loose = loose.Add(sdk.NewDecFromInt(acc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom)))
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
k.IterateUnbondingDelegations(ctx, func(_ int64, ubd stake.UnbondingDelegation) bool {
|
k.IterateUnbondingDelegations(ctx, func(_ int64, ubd stake.UnbondingDelegation) bool {
|
||||||
|
@ -70,19 +71,19 @@ func SupplyInvariants(ck bank.Keeper, k stake.Keeper,
|
||||||
feePool := d.GetFeePool(ctx)
|
feePool := d.GetFeePool(ctx)
|
||||||
|
|
||||||
// add outstanding fees
|
// add outstanding fees
|
||||||
loose = loose.Add(sdk.NewDecFromInt(f.GetCollectedFees(ctx).AmountOf("steak")))
|
loose = loose.Add(sdk.NewDecFromInt(f.GetCollectedFees(ctx).AmountOf(stakeTypes.DefaultBondDenom)))
|
||||||
|
|
||||||
// add community pool
|
// add community pool
|
||||||
loose = loose.Add(feePool.CommunityPool.AmountOf("steak"))
|
loose = loose.Add(feePool.CommunityPool.AmountOf(stakeTypes.DefaultBondDenom))
|
||||||
|
|
||||||
// add validator distribution pool
|
// add validator distribution pool
|
||||||
loose = loose.Add(feePool.ValPool.AmountOf("steak"))
|
loose = loose.Add(feePool.ValPool.AmountOf(stakeTypes.DefaultBondDenom))
|
||||||
|
|
||||||
// add validator distribution commission and yet-to-be-withdrawn-by-delegators
|
// add validator distribution commission and yet-to-be-withdrawn-by-delegators
|
||||||
d.IterateValidatorDistInfos(ctx,
|
d.IterateValidatorDistInfos(ctx,
|
||||||
func(_ int64, distInfo distribution.ValidatorDistInfo) (stop bool) {
|
func(_ int64, distInfo distribution.ValidatorDistInfo) (stop bool) {
|
||||||
loose = loose.Add(distInfo.DelPool.AmountOf("steak"))
|
loose = loose.Add(distInfo.DelPool.AmountOf(stakeTypes.DefaultBondDenom))
|
||||||
loose = loose.Add(distInfo.ValCommission.AmountOf("steak"))
|
loose = loose.Add(distInfo.ValCommission.AmountOf(stakeTypes.DefaultBondDenom))
|
||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
@ -26,11 +26,11 @@ func SimulateMsgCreateValidator(m auth.AccountKeeper, k stake.Keeper) simulation
|
||||||
Moniker: simulation.RandStringOfLength(r, 10),
|
Moniker: simulation.RandStringOfLength(r, 10),
|
||||||
}
|
}
|
||||||
|
|
||||||
maxCommission := sdk.NewInt(10)
|
maxCommission := sdk.NewDecWithPrec(r.Int63n(1000), 3)
|
||||||
commission := stake.NewCommissionMsg(
|
commission := stake.NewCommissionMsg(
|
||||||
sdk.NewDecWithPrec(simulation.RandomAmount(r, maxCommission).Int64(), 1),
|
simulation.RandomDecAmount(r, maxCommission),
|
||||||
sdk.NewDecWithPrec(simulation.RandomAmount(r, maxCommission).Int64(), 1),
|
maxCommission,
|
||||||
sdk.NewDecWithPrec(simulation.RandomAmount(r, maxCommission).Int64(), 1),
|
simulation.RandomDecAmount(r, maxCommission),
|
||||||
)
|
)
|
||||||
|
|
||||||
acc := simulation.RandomAcc(r, accs)
|
acc := simulation.RandomAcc(r, accs)
|
||||||
|
@ -85,11 +85,10 @@ func SimulateMsgEditValidator(k stake.Keeper) simulation.Operation {
|
||||||
Details: simulation.RandStringOfLength(r, 10),
|
Details: simulation.RandStringOfLength(r, 10),
|
||||||
}
|
}
|
||||||
|
|
||||||
maxCommission := sdk.NewInt(10)
|
|
||||||
newCommissionRate := sdk.NewDecWithPrec(simulation.RandomAmount(r, maxCommission).Int64(), 1)
|
|
||||||
|
|
||||||
val := keeper.RandomValidator(r, k, ctx)
|
val := keeper.RandomValidator(r, k, ctx)
|
||||||
address := val.GetOperator()
|
address := val.GetOperator()
|
||||||
|
newCommissionRate := simulation.RandomDecAmount(r, val.Commission.MaxRate)
|
||||||
|
|
||||||
msg := stake.MsgEditValidator{
|
msg := stake.MsgEditValidator{
|
||||||
Description: description,
|
Description: description,
|
||||||
ValidatorAddr: address,
|
ValidatorAddr: address,
|
||||||
|
|
|
@ -28,7 +28,7 @@ var (
|
||||||
|
|
||||||
func NewTestMsgCreateValidator(address sdk.ValAddress, pubKey crypto.PubKey, amt int64) MsgCreateValidator {
|
func NewTestMsgCreateValidator(address sdk.ValAddress, pubKey crypto.PubKey, amt int64) MsgCreateValidator {
|
||||||
return types.NewMsgCreateValidator(
|
return types.NewMsgCreateValidator(
|
||||||
address, pubKey, sdk.NewCoin("steak", sdk.NewInt(amt)), Description{}, commissionMsg,
|
address, pubKey, sdk.NewCoin(types.DefaultBondDenom, sdk.NewInt(amt)), Description{}, commissionMsg,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ func NewTestMsgCreateValidatorWithCommission(address sdk.ValAddress, pubKey cryp
|
||||||
commission := NewCommissionMsg(commissionRate, sdk.OneDec(), sdk.ZeroDec())
|
commission := NewCommissionMsg(commissionRate, sdk.OneDec(), sdk.ZeroDec())
|
||||||
|
|
||||||
return types.NewMsgCreateValidator(
|
return types.NewMsgCreateValidator(
|
||||||
address, pubKey, sdk.NewCoin("steak", sdk.NewInt(amt)), Description{}, commission,
|
address, pubKey, sdk.NewCoin(types.DefaultBondDenom, sdk.NewInt(amt)), Description{}, commission,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ func NewTestMsgDelegate(delAddr sdk.AccAddress, valAddr sdk.ValAddress, amt int6
|
||||||
return MsgDelegate{
|
return MsgDelegate{
|
||||||
DelegatorAddr: delAddr,
|
DelegatorAddr: delAddr,
|
||||||
ValidatorAddr: valAddr,
|
ValidatorAddr: valAddr,
|
||||||
Delegation: sdk.NewCoin("steak", sdk.NewInt(amt)),
|
Delegation: sdk.NewCoin(types.DefaultBondDenom, sdk.NewInt(amt)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,6 +57,6 @@ func NewTestMsgCreateValidatorOnBehalfOf(delAddr sdk.AccAddress, valAddr sdk.Val
|
||||||
DelegatorAddr: delAddr,
|
DelegatorAddr: delAddr,
|
||||||
ValidatorAddr: valAddr,
|
ValidatorAddr: valAddr,
|
||||||
PubKey: valPubKey,
|
PubKey: valPubKey,
|
||||||
Delegation: sdk.NewCoin("steak", sdk.NewInt(amt)),
|
Delegation: sdk.NewCoin(types.DefaultBondDenom, sdk.NewInt(amt)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ type (
|
||||||
// Commission defines a commission parameters for a given validator.
|
// Commission defines a commission parameters for a given validator.
|
||||||
Commission struct {
|
Commission struct {
|
||||||
Rate sdk.Dec `json:"rate"` // the commission rate charged to delegators
|
Rate sdk.Dec `json:"rate"` // the commission rate charged to delegators
|
||||||
MaxRate sdk.Dec `json:"max_rate"` // maximum commission rate which validator can ever charge
|
MaxRate sdk.Dec `json:"max_rate"` // maximum commission rate which this validator can ever charge
|
||||||
MaxChangeRate sdk.Dec `json:"max_change_rate"` // maximum daily increase of the validator commission
|
MaxChangeRate sdk.Dec `json:"max_change_rate"` // maximum daily increase of the validator commission
|
||||||
UpdateTime time.Time `json:"update_time"` // the last time the commission rate was changed
|
UpdateTime time.Time `json:"update_time"` // the last time the commission rate was changed
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
coinPos = sdk.NewInt64Coin("steak", 1000)
|
coinPos = sdk.NewInt64Coin(DefaultBondDenom, 1000)
|
||||||
coinZero = sdk.NewInt64Coin("steak", 0)
|
coinZero = sdk.NewInt64Coin(DefaultBondDenom, 0)
|
||||||
coinNeg = sdk.NewInt64Coin("steak", -10000)
|
coinNeg = sdk.NewInt64Coin(DefaultBondDenom, -10000)
|
||||||
)
|
)
|
||||||
|
|
||||||
// test ValidateBasic for MsgCreateValidator
|
// test ValidateBasic for MsgCreateValidator
|
||||||
|
|
|
@ -19,6 +19,9 @@ const (
|
||||||
// if this is 1, the validator set at the end of a block will sign the block after the next.
|
// if this is 1, the validator set at the end of a block will sign the block after the next.
|
||||||
// Constant as this should not change without a hard fork.
|
// Constant as this should not change without a hard fork.
|
||||||
ValidatorUpdateDelay int64 = 1
|
ValidatorUpdateDelay int64 = 1
|
||||||
|
|
||||||
|
// Default bondable coin denomination
|
||||||
|
DefaultBondDenom = "STAKE"
|
||||||
)
|
)
|
||||||
|
|
||||||
// nolint - Keys for parameter access
|
// nolint - Keys for parameter access
|
||||||
|
@ -59,7 +62,7 @@ func DefaultParams() Params {
|
||||||
return Params{
|
return Params{
|
||||||
UnbondingTime: defaultUnbondingTime,
|
UnbondingTime: defaultUnbondingTime,
|
||||||
MaxValidators: 100,
|
MaxValidators: 100,
|
||||||
BondDenom: "steak",
|
BondDenom: DefaultBondDenom,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +72,7 @@ func (p Params) HumanReadableString() string {
|
||||||
|
|
||||||
resp := "Params \n"
|
resp := "Params \n"
|
||||||
resp += fmt.Sprintf("Unbonding Time: %s\n", p.UnbondingTime)
|
resp += fmt.Sprintf("Unbonding Time: %s\n", p.UnbondingTime)
|
||||||
resp += fmt.Sprintf("Max Validators: %d: \n", p.MaxValidators)
|
resp += fmt.Sprintf("Max Validators: %d\n", p.MaxValidators)
|
||||||
resp += fmt.Sprintf("Bonded Coin Denomination: %s\n", p.BondDenom)
|
resp += fmt.Sprintf("Bonded Coin Denomination: %s\n", p.BondDenom)
|
||||||
return resp
|
return resp
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue