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:
Federico Kunze 2018-11-12 23:13:05 +01:00
commit a6af76e4be
59 changed files with 1347 additions and 1073 deletions

View File

@ -20,6 +20,7 @@ FEATURES
* [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] [\#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
* [\#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
* [\#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
- [\#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
* [\#2625](https://github.com/cosmos/cosmos-sdk/issues/2625) [x/gov] fix AppendTag function usage error

8
Gopkg.lock generated
View File

@ -298,7 +298,7 @@
"model",
]
pruneopts = "UT"
revision = "7e9e6cabbd393fc208072eedef99188d0ce788b6"
revision = "0b1957f9d949dfa3084171a6ec5642b38055276a"
[[projects]]
branch = "master"
@ -434,7 +434,7 @@
version = "v0.11.1"
[[projects]]
digest = "1:395820b381043b9d2204e181ddf0f9147397c4a7b8f5dc3162de4cfcddf4589a"
digest = "1:ba2ba7d6a0853472bdb7a64c4f9c1d5f9cba0eb7aac0b024654104387bf5eb57"
name = "github.com/tendermint/tendermint"
packages = [
"abci/client",
@ -500,8 +500,8 @@
"version",
]
pruneopts = "UT"
revision = "03e42d2e3866f01a00625f608e3bbfaeb30690de"
version = "v0.26.1-rc0"
revision = "80d0a362500fea2dd089258319075a54e5d40a2d"
version = "v0.26.1"
[[projects]]
digest = "1:7886f86064faff6f8d08a3eb0e8c773648ff5a2e27730831e2bfbf07467f6666"

View File

@ -36,7 +36,7 @@
[[override]]
name = "github.com/tendermint/tendermint"
version = "v0.26.1-rc0" # TODO replace w/ 0.26.1
version = "v0.26.1"
## deps without releases:

View File

@ -1,11 +1,9 @@
PACKAGES_NOSIMULATION=$(shell go list ./... | grep -v '/simulation')
PACKAGES_SIMTEST=$(shell go list ./... | grep '/simulation')
VERSION := $(shell git describe --tags --long | sed 's/v\(.*\)/\1/')
BUILD_TAGS = netgo ledger
VERSION := $(subst v,,$(shell git describe --tags --long))
BUILD_TAGS = netgo
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
UNAME_S := $(shell uname -s)
GOTOOLS = \
github.com/golang/dep/cmd/dep \
github.com/alecthomas/gometalinter \
@ -20,23 +18,30 @@ ci: get_tools get_vendor_deps install test_cover test_lint test
########################################
### Build/Install
check-ledger:
ifeq ($(LEDGER_ENABLED),true)
ifeq ($(UNAME_S),OpenBSD)
$(info "OpenBSD detected, disabling ledger support (https://github.com/cosmos/cosmos-sdk/issues/1988)")
TMP_BUILD_TAGS := $(BUILD_TAGS)
BUILD_TAGS = $(filter-out ledger, $(TMP_BUILD_TAGS))
else
ifndef GCC
$(error "gcc not installed for ledger support, please install or set LEDGER_ENABLED to false in the Makefile")
endif
endif
else
TMP_BUILD_TAGS := $(BUILD_TAGS)
BUILD_TAGS = $(filter-out ledger, $(TMP_BUILD_TAGS))
ifeq ($(OS),Windows_NT)
GCCEXE = $(shell where gcc.exe 2> NUL)
ifeq ($(GCCEXE),)
$(error gcc.exe not installed for ledger support, please install or set LEDGER_ENABLED=false)
else
BUILD_TAGS += ledger
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
build: check-ledger update_gaia_lite_docs
build:
ifeq ($(OS),Windows_NT)
go build $(BUILD_FLAGS) -o build/gaiad.exe ./cmd/gaia/cmd/gaiad
go build $(BUILD_FLAGS) -o build/gaiacli.exe ./cmd/gaia/cmd/gaiacli
@ -101,7 +106,7 @@ check_tools:
update_tools:
@echo "--> Updating tools to correct version"
./scripts/get_tools.sh
$(MAKE) -C scripts get_tools
update_dev_tools:
@echo "--> Downloading linters (this may take awhile)"
@ -110,7 +115,7 @@ update_dev_tools:
get_tools:
@echo "--> Installing tools"
./scripts/get_tools.sh
$(MAKE) -C scripts get_tools
get_dev_tools:
@echo "--> Downloading linters (this may take awhile)"

View File

@ -5,10 +5,13 @@ BREAKING CHANGES
* Gaia REST API (`gaiacli advanced rest-server`)
* 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
* SDK
* [\#2752](https://github.com/cosmos/cosmos-sdk/pull/2752) Don't hardcode bondable denom.
* Tendermint
@ -23,6 +26,7 @@ FEATURES
* Gaia
* SDK
* [simulator] \#2682 MsgEditValidator now looks at the validator's max rate, thus it now succeeds a significant portion of the time
* Tendermint
@ -32,10 +36,13 @@ IMPROVEMENTS
* Gaia REST API (`gaiacli advanced rest-server`)
* Gaia CLI (`gaiacli`)
* [\#2749](https://github.com/cosmos/cosmos-sdk/pull/2749) Add --chain-id flag to gaiad testnet
* Gaia
- #2672 [Makefile] Updated for better Windows compatibility and ledger support logic, get_tools was rewritten as a cross-compatible Makefile.
* SDK
- [x/mock/simulation] [\#2720] major cleanup, introduction of helper objects, reorganization
* Tendermint
@ -47,7 +54,10 @@ BUG FIXES
* Gaia CLI (`gaiacli`)
* 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
* 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

View File

@ -31,6 +31,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/gov"
"github.com/cosmos/cosmos-sdk/x/slashing"
"github.com/cosmos/cosmos-sdk/x/stake"
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
)
func init() {
@ -265,7 +266,7 @@ func TestCoinSend(t *testing.T) {
coins := acc.GetCoins()
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)
// query receiver
@ -273,7 +274,7 @@ func TestCoinSend(t *testing.T) {
coins = acc.GetCoins()
mycoins = coins[0]
require.Equal(t, "steak", mycoins.Denom)
require.Equal(t, stakeTypes.DefaultBondDenom, mycoins.Denom)
require.Equal(t, int64(1), mycoins.Amount.Int64())
// test failure with too little gas
@ -326,7 +327,7 @@ func DisabledTestIBCTransfer(t *testing.T) {
coins := acc.GetCoins()
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)
// TODO: query ibc egress packet state
@ -514,7 +515,7 @@ func TestValidatorQuery(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))
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
acc = getAccount(t, port, addr)
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])
require.Equal(t, "30", unbonding.Balance.Amount.String())
@ -667,11 +668,11 @@ func TestDeposit(t *testing.T) {
// query proposal
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
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) {
@ -865,7 +866,7 @@ func doSendWithGas(t *testing.T, port, seed, name, password string, addr sdk.Acc
sequence := acc.GetSequence()
chainID := viper.GetString(client.FlagChainID)
// send
coinbz, err := cdc.MarshalJSON(sdk.NewInt64Coin("steak", 1))
coinbz, err := cdc.MarshalJSON(sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 1))
if err != nil {
panic(err)
}
@ -951,7 +952,7 @@ func doIBCTransfer(t *testing.T, port, seed, name, password string, addr sdk.Acc
"account_number":"%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)
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",
"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)
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",
"proposal_type": "Text",
"proposer": "%s",
"initial_deposit": [{ "denom": "steak", "amount": "%d" }],
"initial_deposit": [{ "denom": "%s", "amount": "%d" }],
"base_req": {
"name": "%s",
"password": "%s",
@ -1362,7 +1363,7 @@ func doSubmitProposal(t *testing.T, port, seed, name, password string, proposerA
"account_number":"%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)
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
jsonStr := []byte(fmt.Sprintf(`{
"depositer": "%s",
"amount": [{ "denom": "steak", "amount": "%d" }],
"amount": [{ "denom": "%s", "amount": "%d" }],
"base_req": {
"name": "%s",
"password": "%s",
@ -1392,7 +1393,7 @@ func doDeposit(t *testing.T, port, seed, name, password string, proposerAddr sdk
"account_number":"%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)
require.Equal(t, http.StatusOK, res.StatusCode, body)

View File

@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"github.com/cosmos/cosmos-sdk/x/stake"
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
"github.com/tendermint/tendermint/crypto/secp256k1"
"io/ioutil"
"net"
@ -227,7 +228,7 @@ func InitializeTestLCD(
msg := stake.NewMsgCreateValidator(
sdk.ValAddress(operAddr),
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.NewCommissionMsg(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()),
)
@ -245,7 +246,7 @@ func InitializeTestLCD(
valOperAddrs = append(valOperAddrs, sdk.ValAddress(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))
}
@ -259,7 +260,7 @@ func InitializeTestLCD(
// add some tokens to init accounts
for _, addr := range initAddrs {
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)
genesisState.Accounts = append(genesisState.Accounts, acc)
genesisState.StakeData.Pool.LooseTokens = genesisState.StakeData.Pool.LooseTokens.Add(sdk.NewDec(100))

View File

@ -19,6 +19,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/mint"
"github.com/cosmos/cosmos-sdk/x/slashing"
"github.com/cosmos/cosmos-sdk/x/stake"
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
tmtypes "github.com/tendermint/tendermint/types"
)
@ -26,7 +27,7 @@ var (
// bonded tokens given to genesis validators/accounts
freeFermionVal = int64(100)
freeFermionsAcc = sdk.NewInt(150)
bondDenom = "steak"
bondDenom = stakeTypes.DefaultBondDenom
)
// State to Unmarshal
@ -286,9 +287,11 @@ func CollectStdTxs(cdc *codec.Codec, moniker string, genTxsDir string, genDoc tm
func NewDefaultGenesisAccount(addr sdk.AccAddress) GenesisAccount {
accAuth := auth.NewBaseAccountWithAddress(addr)
accAuth.Coins = []sdk.Coin{
coins :=sdk.Coins{
{"fooToken", sdk.NewInt(1000)},
{"steak", freeFermionsAcc},
{bondDenom, freeFermionsAcc},
}
coins.Sort()
accAuth.Coins = coins
return NewGenesisAccount(&accAuth)
}

View File

@ -92,10 +92,8 @@ func TestGaiaAppGenState(t *testing.T) {
func makeMsg(name string, pk crypto.PubKey) auth.StdTx {
desc := stake.NewDescription(name, "", "", "")
comm := stakeTypes.CommissionMsg{}
msg := stake.NewMsgCreateValidator(
sdk.ValAddress(pk.Address()), pk,
sdk.NewInt64Coin(bondDenom, 50), desc, comm,
)
msg := stake.NewMsgCreateValidator(sdk.ValAddress(pk.Address()), pk, sdk.NewInt64Coin(bondDenom,
50), desc, comm)
return auth.NewStdTx([]sdk.Msg{msg}, auth.StdFee{}, nil, "")
}

View File

@ -29,6 +29,7 @@ import (
slashingsim "github.com/cosmos/cosmos-sdk/x/slashing/simulation"
stake "github.com/cosmos/cosmos-sdk/x/stake"
stakesim "github.com/cosmos/cosmos-sdk/x/stake/simulation"
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
)
var (
@ -62,7 +63,7 @@ func appStateFn(r *rand.Rand, accs []simulation.Account) json.RawMessage {
// Randomly generate some genesis accounts
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{
Address: acc.Address,
Coins: coins,
@ -73,7 +74,7 @@ func appStateFn(r *rand.Rand, accs []simulation.Account) json.RawMessage {
govGenesis := gov.GenesisState{
StartingProposalID: uint64(r.Intn(100)),
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,
},
VotingParams: gov.VotingParams{
@ -91,7 +92,7 @@ func appStateFn(r *rand.Rand, accs []simulation.Account) json.RawMessage {
Params: stake.Params{
UnbondingTime: time.Duration(r.Intn(60*60*24*3*2)) * time.Second,
MaxValidators: uint16(r.Intn(250)),
BondDenom: "steak",
BondDenom: stakeTypes.DefaultBondDenom,
},
}
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),
},
Params: mint.Params{
MintDenom: "steak",
MintDenom: stakeTypes.DefaultBondDenom,
InflationRateChange: sdk.NewDecWithPrec(int64(r.Intn(99)), 2),
InflationMax: sdk.NewDecWithPrec(20, 2),
InflationMin: sdk.NewDecWithPrec(7, 2),

View File

@ -29,6 +29,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/gov"
"github.com/cosmos/cosmos-sdk/x/stake"
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
)
var (
@ -55,10 +56,10 @@ func TestGaiaCLIMinimumFees(t *testing.T) {
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))
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(
"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)
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))
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)
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))
require.Equal(t, int64(40), fooAcc.GetCoins().AmountOf("steak").Int64())
require.Equal(t, int64(40), fooAcc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom).Int64())
// 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)
// Check state didn't change
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
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)
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))
require.Equal(t, int64(30), fooAcc.GetCoins().AmountOf("steak").Int64())
require.Equal(t, int64(30), fooAcc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom).Int64())
// 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)
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))
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) {
@ -172,26 +173,26 @@ func TestGaiaCLIGasAuto(t *testing.T) {
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))
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
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)
tests.WaitForNextNBlocksTM(2, port)
// Check state didn't change
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
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)
// 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)
// 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)
// check that gas wanted == gas used
cdc := app.MakeCodec()
@ -205,7 +206,7 @@ func TestGaiaCLIGasAuto(t *testing.T) {
tests.WaitForNextNBlocksTM(2, port)
// Check state has changed accordingly
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) {
@ -223,13 +224,13 @@ func TestGaiaCLICreateValidator(t *testing.T) {
barAddr, barPubKey := executeGetAddrPK(t, fmt.Sprintf("gaiacli keys show bar --output=json --home=%s", gaiacliHome))
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)
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))
require.Equal(t, int64(40), fooAcc.GetCoins().AmountOf("steak").Int64())
require.Equal(t, int64(40), fooAcc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom).Int64())
defaultParams := stake.DefaultParams()
initialPool := stake.InitialPool()
@ -239,7 +240,7 @@ func TestGaiaCLICreateValidator(t *testing.T) {
cvStr := fmt.Sprintf("gaiacli tx create-validator %v", flags)
cvStr += fmt.Sprintf(" --from=%s", "bar")
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(" --commission-rate=%v", "0.05")
cvStr += fmt.Sprintf(" --commission-max-rate=%v", "0.20")
@ -265,7 +266,7 @@ func TestGaiaCLICreateValidator(t *testing.T) {
tests.WaitForNextNBlocksTM(2, port)
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))
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
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))
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))
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), "")
require.Equal(t, "No matching proposals found", proposalsQuery)
@ -327,7 +328,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
// submit a test proposal
spStr := fmt.Sprintf("gaiacli tx submit-proposal %v", flags)
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(" --title=%s", "Test")
spStr += fmt.Sprintf(" --description=%s", "test")
@ -350,7 +351,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
tests.WaitForNextNBlocksTM(2, port)
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))
require.Equal(t, uint64(1), proposal1.GetProposalID())
@ -362,11 +363,11 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
deposit := executeGetDeposit(t,
fmt.Sprintf("gaiacli query deposit --proposal-id=1 --depositer=%s --output=json %v",
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(" --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")
// Test generate only
@ -386,15 +387,15 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
deposits := executeGetDeposits(t,
fmt.Sprintf("gaiacli query deposits --proposal-id=1 --output=json %v", flags))
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,
fmt.Sprintf("gaiacli query deposit --proposal-id=1 --depositer=%s --output=json %v",
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))
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))
require.Equal(t, uint64(1), proposal1.GetProposalID())
require.Equal(t, gov.StatusVotingPeriod, proposal1.GetStatus())
@ -435,7 +436,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
// submit a second test proposal
spStr = fmt.Sprintf("gaiacli tx submit-proposal %v", flags)
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(" --title=%s", "Apples")
spStr += fmt.Sprintf(" --description=%s", "test")
@ -464,8 +465,8 @@ func TestGaiaCLISendGenerateSignAndBroadcast(t *testing.T) {
// Test generate sendTx with default gas
success, stdout, stderr := executeWriteRetStdStreams(t, fmt.Sprintf(
"gaiacli tx send %v --amount=10steak --to=%s --from=foo --generate-only",
flags, barAddr), []string{}...)
"gaiacli tx send %v --amount=10%s --to=%s --from=foo --generate-only",
flags, stakeTypes.DefaultBondDenom, barAddr), []string{}...)
require.True(t, success)
require.Empty(t, stderr)
msg := unmarshalStdTx(t, stdout)
@ -475,8 +476,8 @@ func TestGaiaCLISendGenerateSignAndBroadcast(t *testing.T) {
// Test generate sendTx with --gas=$amount
success, stdout, stderr = executeWriteRetStdStreams(t, fmt.Sprintf(
"gaiacli tx send %v --amount=10steak --to=%s --from=foo --gas=100 --generate-only",
flags, barAddr), []string{}...)
"gaiacli tx send %v --amount=10%s --to=%s --from=foo --gas=100 --generate-only",
flags, stakeTypes.DefaultBondDenom, barAddr), []string{}...)
require.True(t, success)
require.Empty(t, stderr)
msg = unmarshalStdTx(t, stdout)
@ -486,8 +487,8 @@ func TestGaiaCLISendGenerateSignAndBroadcast(t *testing.T) {
// Test generate sendTx, estimate gas
success, stdout, stderr = executeWriteRetStdStreams(t, fmt.Sprintf(
"gaiacli tx send %v --amount=10steak --to=%s --from=foo --gas=simulate --generate-only",
flags, barAddr), []string{}...)
"gaiacli tx send %v --amount=10%s --to=%s --from=foo --gas=simulate --generate-only",
flags, stakeTypes.DefaultBondDenom, barAddr), []string{}...)
require.True(t, success)
require.NotEmpty(t, stderr)
msg = unmarshalStdTx(t, stdout)
@ -526,7 +527,7 @@ func TestGaiaCLISendGenerateSignAndBroadcast(t *testing.T) {
// Test broadcast
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(
"gaiacli tx broadcast %v --json %v", flags, signedTxFile.Name()))
@ -540,9 +541,9 @@ func TestGaiaCLISendGenerateSignAndBroadcast(t *testing.T) {
tests.WaitForNextNBlocksTM(2, port)
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))
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) {

View File

@ -42,6 +42,7 @@ func main() {
rootCmd.AddCommand(gaiaInit.CollectGenTxsCmd(ctx, cdc))
rootCmd.AddCommand(gaiaInit.TestnetFilesCmd(ctx, cdc, server.AppInit{}))
rootCmd.AddCommand(gaiaInit.GenTxCmd(ctx, cdc))
rootCmd.AddCommand(gaiaInit.AddGenesisAccountCmd(ctx, cdc))
server.AddCommands(ctx, cdc, rootCmd, appInit,
newApp, exportAppStateAndTMValidators)

View File

@ -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
}

View File

@ -9,6 +9,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/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/viper"
cfg "github.com/tendermint/tendermint/config"
@ -21,7 +22,7 @@ import (
)
const (
defaultAmount = "100steak"
defaultAmount = "100" + stakeTypes.DefaultBondDenom
defaultCommissionRate = "0.1"
defaultCommissionMaxRate = "0.2"
defaultCommissionMaxChangeRate = "0.01"

View File

@ -14,6 +14,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/auth"
authtx "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
"github.com/cosmos/cosmos-sdk/x/stake"
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
"github.com/cosmos/cosmos-sdk/server"
"github.com/spf13/cobra"
@ -75,14 +76,20 @@ Example:
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, ...)")
cmd.Flags().String(client.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created")
return cmd
}
func initTestnet(config *cfg.Config, cdc *codec.Codec) error {
var chainID string
outDir := viper.GetString(flagOutputDir)
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)
nodeIDs := make([]string, numValidators)
@ -174,14 +181,14 @@ func initTestnet(config *cfg.Config, cdc *codec.Codec) error {
Address: addr,
Coins: sdk.Coins{
sdk.NewInt64Coin(fmt.Sprintf("%sToken", nodeDirName), 1000),
sdk.NewInt64Coin("steak", 150),
sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 150),
},
})
msg := stake.NewMsgCreateValidator(
sdk.ValAddress(addr),
valPubKeys[i],
sdk.NewInt64Coin("steak", 100),
sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 100),
stake.NewDescription(nodeDirName, "", "", ""),
stake.NewCommissionMsg(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()),
)

View File

@ -8,7 +8,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/bank"
)
const stakingToken = "steak"
const stakingToken = "stake"
const moduleName = "simplestake"

View File

@ -75,10 +75,10 @@ func TestBonding(t *testing.T) {
_, _, err := stakeKeeper.unbondWithoutCoins(ctx, addr)
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)
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.Equal(t, int64(20), power)

54
scripts/Makefile Normal file
View File

@ -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

View File

@ -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

View File

@ -17,7 +17,7 @@ echo "Using temporary log directory: $tmpdir"
sim() {
seed=$1
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..."
go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=$blocks \
-SimulationVerbose=true -SimulationCommit=true -SimulationSeed=$seed -v -timeout 24h > $file

View File

@ -63,17 +63,17 @@ func ShowValidatorCmd(ctx *Context) *cobra.Command {
func ShowAddressCmd(ctx *Context) *cobra.Command {
cmd := &cobra.Command{
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 {
cfg := ctx.Config
privValidator := pvm.LoadOrGenFilePV(cfg.PrivValidatorFile())
valAddr := (sdk.ValAddress)(privValidator.Address)
valConsAddr := (sdk.ConsAddress)(privValidator.Address)
if viper.GetBool(client.FlagJson) {
return printlnJSON(valAddr)
return printlnJSON(valConsAddr)
}
fmt.Println(valAddr.String())
fmt.Println(valConsAddr.String())
return nil
},
}

View File

@ -7,6 +7,7 @@ import (
"os/signal"
"path/filepath"
"syscall"
"time"
"github.com/pkg/errors"
"github.com/spf13/cobra"
@ -92,7 +93,7 @@ func interceptLoadConfig() (conf *cfg.Config, err error) {
conf.P2P.RecvRate = 5120000
conf.P2P.SendRate = 5120000
conf.TxIndex.IndexAllTags = true
conf.Consensus.TimeoutCommit = 5000
conf.Consensus.TimeoutCommit = 5 * time.Second
cfg.WriteConfigFile(configFilePath, conf)
// Fall through, just so that its parsed into memory.
}

View File

@ -49,8 +49,8 @@ func TestSameDenomAsCoin(t *testing.T) {
{NewInt64Coin("A", 1), NewInt64Coin("A", 1), true},
{NewInt64Coin("A", 1), NewInt64Coin("a", 1), false},
{NewInt64Coin("a", 1), NewInt64Coin("b", 1), false},
{NewInt64Coin("steak", 1), NewInt64Coin("steak", 10), true},
{NewInt64Coin("steak", -11), NewInt64Coin("steak", 10), true},
{NewInt64Coin("stake", 1), NewInt64Coin("stake", 10), true},
{NewInt64Coin("stake", -11), NewInt64Coin("stake", 10), true},
}
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), false},
{NewInt64Coin("a", 1), NewInt64Coin("b", 1), false},
{NewInt64Coin("steak", 1), NewInt64Coin("steak", 10), false},
{NewInt64Coin("steak", -11), NewInt64Coin("steak", 10), false},
{NewInt64Coin("stake", 1), NewInt64Coin("stake", 10), false},
{NewInt64Coin("stake", -11), NewInt64Coin("stake", 10), false},
}
for tcIndex, tc := range cases {

View File

@ -21,8 +21,8 @@ func TestSortJSON(t *testing.T) {
want: "",
wantErr: true},
// 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}}}`,
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="}}]}`,
{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":"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},
// 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}`,

View File

@ -10,6 +10,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/tendermint/tendermint/crypto/ed25519"
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
)
var (
@ -46,7 +47,7 @@ func TestTxBuilderBuild(t *testing.T) {
SimulateGas: false,
ChainID: "test-chain",
Memo: "hello",
Fee: "1steak",
Fee: "1" + stakeTypes.DefaultBondDenom,
},
defaultMsg,
StdSignMsg{
@ -55,7 +56,7 @@ func TestTxBuilderBuild(t *testing.T) {
Sequence: 1,
Memo: "hello",
Msgs: defaultMsg,
Fee: auth.NewStdFee(100, sdk.NewCoin("steak", sdk.NewInt(1))),
Fee: auth.NewStdFee(100, sdk.NewCoin(stakeTypes.DefaultBondDenom, sdk.NewInt(1))),
},
false,
},

View File

@ -15,41 +15,40 @@ const (
costAddCoins sdk.Gas = 10
)
//-----------------------------------------------------------------------------
// Keeper
var _ Keeper = (*BaseKeeper)(nil)
// Keeper defines a module interface that facilitates the transfer of coins
// between accounts.
type Keeper interface {
SendKeeper
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)
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
// interface.
type BaseKeeper struct {
am auth.AccountKeeper
BaseSendKeeper
ak auth.AccountKeeper
}
// NewBaseKeeper returns a new BaseKeeper
func NewBaseKeeper(am auth.AccountKeeper) BaseKeeper {
return BaseKeeper{am: am}
}
// 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)
func NewBaseKeeper(ak auth.AccountKeeper) BaseKeeper {
return BaseKeeper{
BaseSendKeeper: NewBaseSendKeeper(ak),
ak: ak,
}
}
// SetCoins sets the coins at the addr.
func (keeper BaseKeeper) SetCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) sdk.Error {
return setCoins(ctx, keeper.am, 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)
return setCoins(ctx, keeper.ak, addr, amt)
}
// 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,
) (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.
@ -65,28 +64,17 @@ func (keeper BaseKeeper) AddCoins(
ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins,
) (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(
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)
}
//______________________________________________________________________________________________
//-----------------------------------------------------------------------------
// Send Keeper
// SendKeeper defines a module interface that facilitates the transfer of coins
// between accounts without the possibility of creating coins.
type SendKeeper interface {
ViewKeeper
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)
}
@ -96,22 +84,17 @@ var _ SendKeeper = (*BaseSendKeeper)(nil)
// SendKeeper only allows transfers between accounts without the possibility of
// creating coins. It implements the SendKeeper interface.
type BaseSendKeeper struct {
am auth.AccountKeeper
BaseViewKeeper
ak auth.AccountKeeper
}
// NewBaseSendKeeper returns a new BaseSendKeeper.
func NewBaseSendKeeper(am auth.AccountKeeper) BaseSendKeeper {
return BaseSendKeeper{am: am}
}
// 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)
func NewBaseSendKeeper(ak auth.AccountKeeper) BaseSendKeeper {
return BaseSendKeeper{
BaseViewKeeper: NewBaseViewKeeper(ak),
ak: ak,
}
}
// 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,
) (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
@ -127,10 +110,13 @@ func (keeper BaseSendKeeper) InputOutputCoins(
ctx sdk.Context, inputs []Input, outputs []Output,
) (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
// account balances.
@ -139,29 +125,29 @@ type ViewKeeper interface {
HasCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) bool
}
var _ ViewKeeper = (*BaseViewKeeper)(nil)
// BaseViewKeeper implements a read only keeper implementation of ViewKeeper.
type BaseViewKeeper struct {
am auth.AccountKeeper
ak auth.AccountKeeper
}
// NewBaseViewKeeper returns a new BaseViewKeeper.
func NewBaseViewKeeper(am auth.AccountKeeper) BaseViewKeeper {
return BaseViewKeeper{am: am}
func NewBaseViewKeeper(ak auth.AccountKeeper) BaseViewKeeper {
return BaseViewKeeper{
ak: ak,
}
}
// GetCoins returns the coins at the addr.
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.
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 {
ctx.GasMeter().ConsumeGas(costGetCoins, "getCoins")

View File

@ -7,6 +7,7 @@ import (
"github.com/stretchr/testify/require"
sdk "github.com/cosmos/cosmos-sdk/types"
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
abci "github.com/tendermint/tendermint/abci/types"
)
@ -20,7 +21,7 @@ func TestTickExpiredDepositPeriod(t *testing.T) {
require.False(t, inactiveQueue.Valid())
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)
require.True(t, res.IsOK())
@ -62,7 +63,7 @@ func TestTickMultipleExpiredDepositPeriod(t *testing.T) {
require.False(t, inactiveQueue.Valid())
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)
require.True(t, res.IsOK())
@ -79,7 +80,7 @@ func TestTickMultipleExpiredDepositPeriod(t *testing.T) {
require.False(t, inactiveQueue.Valid())
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)
require.True(t, res.IsOK())
@ -121,7 +122,7 @@ func TestTickPassedDepositPeriod(t *testing.T) {
require.False(t, activeQueue.Valid())
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)
require.True(t, res.IsOK())
@ -140,7 +141,7 @@ func TestTickPassedDepositPeriod(t *testing.T) {
require.False(t, inactiveQueue.Valid())
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)
require.True(t, res.IsOK())
@ -163,7 +164,7 @@ func TestTickPassedVotingPeriod(t *testing.T) {
require.False(t, activeQueue.Valid())
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)
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)
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)
require.True(t, res.IsOK())

View File

@ -4,6 +4,7 @@ import (
"time"
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
@ -43,7 +44,7 @@ func DefaultGenesisState() GenesisState {
return GenesisState{
StartingProposalID: 1,
DepositParams: DepositParams{
MinDeposit: sdk.Coins{sdk.NewInt64Coin("steak", 10)},
MinDeposit: sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 10)},
MaxDepositPeriod: time.Duration(172800) * time.Second,
},
VotingParams: VotingParams{

View File

@ -9,6 +9,7 @@ import (
abci "github.com/tendermint/tendermint/abci/types"
sdk "github.com/cosmos/cosmos-sdk/types"
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
)
func TestGetSetProposal(t *testing.T) {
@ -69,14 +70,14 @@ func TestDeposits(t *testing.T) {
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
proposalID := proposal.GetProposalID()
fourSteak := sdk.Coins{sdk.NewInt64Coin("steak", 4)}
fiveSteak := sdk.Coins{sdk.NewInt64Coin("steak", 5)}
fourSteak := sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 4)}
fiveSteak := sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 5)}
addr0Initial := keeper.ck.GetCoins(ctx, addrs[0])
addr1Initial := keeper.ck.GetCoins(ctx, addrs[1])
// require.True(t, addr0Initial.IsEqual(sdk.Coins{sdk.NewInt64Coin("steak", 42)}))
require.Equal(t, sdk.Coins{sdk.NewInt64Coin("steak", 42)}, addr0Initial)
// require.True(t, addr0Initial.IsEqual(sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 42)}))
require.Equal(t, sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 42)}, addr0Initial)
require.True(t, proposal.GetTotalDeposit().IsEqual(sdk.Coins{}))

View File

@ -7,16 +7,21 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/mock"
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
)
var (
coinsPos = sdk.Coins{sdk.NewInt64Coin("steak", 1000)}
coinsPos = sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 1000)}
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)}
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
func TestMsgSubmitProposal(t *testing.T) {
_, addrs, _, _ := mock.CreateGenAccounts(1, sdk.Coins{})
@ -42,9 +47,9 @@ func TestMsgSubmitProposal(t *testing.T) {
for i, tc := range tests {
msg := NewMsgSubmitProposal(tc.title, tc.description, tc.proposalType, tc.proposerAddr, tc.initialDeposit)
if tc.expectPass {
require.Nil(t, msg.ValidateBasic(), "test: %v", i)
require.NoError(t, msg.ValidateBasic(), "test: %v", i)
} 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 {
msg := NewMsgDeposit(tc.depositerAddr, tc.proposalID, tc.depositAmount)
if tc.expectPass {
require.Nil(t, msg.ValidateBasic(), "test: %v", i)
require.NoError(t, msg.ValidateBasic(), "test: %v", i)
} else {
require.NotNil(t, msg.ValidateBasic(), "test: %v", i)
require.Error(t, msg.ValidateBasic(), "test: %v", i)
}
}
}

View File

@ -11,10 +11,11 @@ import (
"github.com/cosmos/cosmos-sdk/x/gov"
"github.com/cosmos/cosmos-sdk/x/mock/simulation"
"github.com/cosmos/cosmos-sdk/x/stake"
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
)
const (
denom = "steak"
denom = stakeTypes.DefaultBondDenom
)
// SimulateSubmittingVotingAndSlashingForProposal simulates creating a msg Submit Proposal

View File

@ -11,6 +11,7 @@ import (
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/cosmos/cosmos-sdk/x/stake"
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
)
var (
@ -25,7 +26,7 @@ func createValidators(t *testing.T, stakeHandler sdk.Handler, ctx sdk.Context, a
for i := 0; i < len(addrs); i++ {
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)
@ -289,7 +290,7 @@ func TestTallyDelgatorOverride(t *testing.T) {
createValidators(t, stakeHandler, ctx, valAddrs, []int64{5, 6, 7})
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)
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})
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)
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})
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)
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)
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
@ -393,24 +394,24 @@ func TestTallyDelgatorMultipleInherit(t *testing.T) {
stakeHandler := stake.NewHandler(sk)
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)
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)
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)
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)
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)
stake.EndBlocker(ctx, sk)
@ -447,10 +448,10 @@ func TestTallyJailedValidator(t *testing.T) {
createValidators(t, stakeHandler, ctx, valAddrs, []int64{25, 6, 7})
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)
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)
val2, found := sk.GetValidator(ctx, sdk.ValAddress(addrs[1]))

View File

@ -17,6 +17,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/bank"
"github.com/cosmos/cosmos-sdk/x/mock"
"github.com/cosmos/cosmos-sdk/x/stake"
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
)
// 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))
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)

View File

@ -2,6 +2,7 @@ package mint
import (
"fmt"
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)
@ -18,7 +19,7 @@ type Params struct {
// default minting module parameters
func DefaultParams() Params {
return Params{
MintDenom: "steak",
MintDenom: stakeTypes.DefaultBondDenom,
InflationRateChange: sdk.NewDecWithPrec(13, 2),
InflationMax: sdk.NewDecWithPrec(20, 2),
InflationMin: sdk.NewDecWithPrec(7, 2),

View File

@ -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
}

View File

@ -2,26 +2,24 @@
Package simulation implements a simulation framework for any state machine
built on the SDK which utilizes auth.
It is primarily intended for fuzz testing the integration of modules.
It will test that the provided operations are interoperable,
and that the desired invariants hold.
It can additionally be used to detect what the performance benchmarks in the
system are, by using benchmarking mode and cpu / mem profiling.
If it detects a failure, it provides the entire log of what was ran,
It is primarily intended for fuzz testing the integration of modules. It will
test that the provided operations are interoperable, and that the desired
invariants hold. It can additionally be used to detect what the performance
benchmarks in the system are, by using benchmarking mode and cpu / mem
profiling. 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 invariants to test, and additional parameters to configure how long to run,
and misc. parameters that affect simulation speed.
The simulator takes as input: a random seed, the set of operations to run, the
invariants to test, and additional parameters to configure how long to run, and
misc. parameters that affect simulation speed.
It is intended that every module provides a list of Operations which will randomly
create and run a message / tx in a manner that is interesting to fuzz, and verify that
the state transition was executed as expected.
Each module should additionally provide methods to assert that the desired invariants hold.
It is intended that every module provides a list of Operations which will
randomly create and run a message / tx in a manner that is interesting to fuzz,
and verify that the state transition was executed as expected. Each module
should additionally provide methods to assert that the desired invariants hold.
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.
Then run simulation.Simulate!
The simulator will handle things like ensuring that validators periodically double signing,
or go offline.
the weightings for each, the invariants you want to test, and how long to run
it for. Then run simulation.Simulate! The simulator will handle things like
ensuring that validators periodically double signing, or go offline.
*/
package simulation

View File

@ -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])
}
}

View File

@ -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()
}
}
}

View File

@ -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,
}
}

View File

@ -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
}
}

View File

@ -15,15 +15,18 @@ const (
onOperation bool = false
)
// TODO explain transitional matrix usage
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{
{90, 20, 1},
{10, 50, 5},
{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{
{85, 5, 0},
{15, 92, 1},

View File

@ -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)
}

View File

@ -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
}

View File

@ -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
}

View File

@ -5,12 +5,11 @@ import (
"math/rand"
)
// TransitionMatrix is _almost_ a left stochastic matrix.
// It is technically not one due to not normalizing the column values.
// In the future, if we want to find the steady state distribution,
// it will be quite easy to normalize these values to get a stochastic matrix.
// Floats aren't currently used as the default due to non-determinism across
// architectures
// TransitionMatrix is _almost_ a left stochastic matrix. It is technically
// not one due to not normalizing the column values. In the future, if we want
// to find the steady state distribution, it will be quite easy to normalize
// these values to get a stochastic matrix. Floats aren't currently used as
// the default due to non-determinism across architectures
type TransitionMatrix struct {
weights [][]int
// total in each column
@ -24,7 +23,8 @@ func CreateTransitionMatrix(weights [][]int) (TransitionMatrix, error) {
n := len(weights)
for i := 0; i < n; i++ {
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)
@ -36,8 +36,8 @@ func CreateTransitionMatrix(weights [][]int) (TransitionMatrix, error) {
return TransitionMatrix{weights, totals, n}, nil
}
// NextState returns the next state randomly chosen using r, and the weightings provided
// in the transition matrix.
// NextState returns the next state randomly chosen using r, and the weightings
// provided in the transition matrix.
func (t TransitionMatrix) NextState(r *rand.Rand, i int) int {
randNum := r.Intn(t.totals[i])
for row := 0; row < t.n; row++ {

View File

@ -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)
}

View File

@ -2,170 +2,121 @@ package simulation
import (
"fmt"
"math/big"
"math/rand"
"os"
"sort"
"strings"
"testing"
"time"
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/crypto/secp256k1"
"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
// TODO we should probably move this to tendermint/libs/common/random.go
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
const (
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--
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 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 {
accs[i].PrivKey = ed25519.GenPrivKeyFromSecret(privkeySeed)
}
accs[i].PubKey = accs[i].PrivKey.PubKey()
accs[i].Address = sdk.AccAddress(accs[i].PubKey.Address())
}
return accs
return
}
// Builds a function to add logs for this particular block
func addLogMessage(testingmode bool, blockLogBuilders []*strings.Builder, height int) func(string) {
if testingmode {
blockLogBuilders[height] = &strings.Builder{}
return func(x string) {
(*blockLogBuilders[height]).WriteString(x)
(*blockLogBuilders[height]).WriteString("\n")
}
}
return func(x string) {}
}
func addLogMessage(testingmode bool,
blockLogBuilders []*strings.Builder, height int) func(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()
}
if !testingmode {
return func(_ string) {}
}
}
// 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
blockLogBuilders[height] = &strings.Builder{}
return func(x string) {
(*blockLogBuilders[height]).WriteString(x)
(*blockLogBuilders[height]).WriteString("\n")
}
mock.RandomSetGenesis(r, app, addrs, denoms)
}
// Creates a function to print out the logs
func logPrinter(testingmode bool, logs []*strings.Builder) func() {
if testingmode {
return func() {
numLoggers := 0
for i := 0; i < len(logs); i++ {
// We're passed the last created block
if logs[i] == nil {
numLoggers = i
break
}
if !testingmode {
return func() {}
}
return func() {
numLoggers := 0
for i := 0; i < len(logs); i++ {
// We're passed the last created block
if logs[i] == nil {
numLoggers = i
break
}
var f *os.File
if numLoggers > 10 {
fileName := fmt.Sprintf("simulation_log_%s.txt", 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)
}
var f *os.File
if numLoggers > 10 {
fileName := fmt.Sprintf("simulation_log_%s.txt",
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)
}
for i := 0; i < numLoggers; i++ {
if f == nil {
fmt.Printf("Begin block %d\n", i+1)
fmt.Println((*logs[i]).String())
continue
}
for i := 0; i < numLoggers; i++ {
if f != nil {
_, err := f.WriteString(fmt.Sprintf("Begin block %d\n", i+1))
if err != nil {
panic("Failed to write logs to file")
}
_, err = f.WriteString((*logs[i]).String())
if err != nil {
panic("Failed to write logs to file")
}
} else {
fmt.Printf("Begin block %d\n", i+1)
fmt.Println((*logs[i]).String())
}
_, err := f.WriteString(fmt.Sprintf("Begin block %d\n", i+1))
if err != nil {
panic("Failed to write logs to file")
}
_, err = f.WriteString((*logs[i]).String())
if err != nil {
panic("Failed to write logs to file")
}
}
}
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
}
}

View File

@ -3,15 +3,17 @@ package slashing
import (
"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"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/bank"
"github.com/cosmos/cosmos-sdk/x/mock"
"github.com/cosmos/cosmos-sdk/x/params"
"github.com/cosmos/cosmos-sdk/x/stake"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto/ed25519"
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
)
var (
@ -93,8 +95,8 @@ func checkValidatorSigningInfo(t *testing.T, mapp *mock.App, keeper Keeper,
func TestSlashingMsgs(t *testing.T) {
mapp, stakeKeeper, keeper := getMockApp(t)
genCoin := sdk.NewInt64Coin("steak", 42)
bondCoin := sdk.NewInt64Coin("steak", 10)
genCoin := sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 42)
bondCoin := sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 10)
acc1 := &auth.BaseAccount{
Address: addr1,

View File

@ -21,6 +21,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/bank"
"github.com/cosmos/cosmos-sdk/x/params"
"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)
@ -120,7 +121,7 @@ func NewTestMsgCreateValidator(address sdk.ValAddress, pubKey crypto.PubKey, amt
DelegatorAddr: sdk.AccAddress(address),
ValidatorAddr: address,
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{
DelegatorAddr: delAddr,
ValidatorAddr: valAddr,
Delegation: sdk.NewCoin("steak", delAmount),
Delegation: sdk.NewCoin(stakeTypes.DefaultBondDenom, delAmount),
}
}

View File

@ -3,13 +3,15 @@ package stake
import (
"testing"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/bank"
"github.com/cosmos/cosmos-sdk/x/mock"
"github.com/cosmos/cosmos-sdk/x/params"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
)
// getMockApp returns an initialized mock application for this module.
@ -100,8 +102,8 @@ func checkDelegation(
func TestStakeMsgs(t *testing.T) {
mApp, keeper := getMockApp(t)
genCoin := sdk.NewInt64Coin("steak", 42)
bondCoin := sdk.NewInt64Coin("steak", 10)
genCoin := sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 42)
bondCoin := sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 10)
acc1 := &auth.BaseAccount{
Address: addr1,

View File

@ -2,6 +2,7 @@ package cli
import (
"fmt"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/client/utils"
@ -210,26 +211,11 @@ func GetCmdDelegate(cdc *codec.Codec) *cobra.Command {
return cmd
}
// GetCmdRedelegate implements the redelegate validator command.
// GetCmdRedelegate the begin redelegation command.
func GetCmdRedelegate(storeName string, cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "redelegate",
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 {
txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc)
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 {
cmd := &cobra.Command{
Use: "unbond",
Short: "begin or complete unbonding 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",
Short: "unbond shares from a validator",
RunE: func(cmd *cobra.Command, args []string) error {
txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc)
cliCtx := context.NewCLIContext().

View File

@ -142,7 +142,7 @@ func TestUnbondingDelegation(t *testing.T) {
ValidatorAddr: addrVals[0],
CreationHeight: 0,
MinTime: time.Unix(0, 0),
Balance: sdk.NewInt64Coin("steak", 5),
Balance: sdk.NewInt64Coin(types.DefaultBondDenom, 5),
}
// set and retrieve a record
@ -152,7 +152,7 @@ func TestUnbondingDelegation(t *testing.T) {
require.True(t, ubd.Equal(resUnbond))
// modify a records, save, and retrieve
ubd.Balance = sdk.NewInt64Coin("steak", 21)
ubd.Balance = sdk.NewInt64Coin(types.DefaultBondDenom, 21)
keeper.SetUnbondingDelegation(ctx, ubd)
resUnbonds := keeper.GetUnbondingDelegations(ctx, addrDels[0], 5)

View File

@ -178,7 +178,7 @@ func TestQueryDelegation(t *testing.T) {
pool = keeper.GetPool(ctx)
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
keeper.ApplyAndReturnValidatorSetUpdates(ctx)
@ -358,7 +358,7 @@ func TestQueryRedelegations(t *testing.T) {
keeper.SetValidator(ctx, val1)
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.BeginRedelegation(ctx, addrAcc2, val1.GetOperator(), val2.GetOperator(), sdk.NewDec(20))

View File

@ -12,6 +12,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/mock/simulation"
"github.com/cosmos/cosmos-sdk/x/stake"
"github.com/cosmos/cosmos-sdk/x/stake/keeper"
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
abci "github.com/tendermint/tendermint/abci/types"
)
@ -48,7 +49,7 @@ func SupplyInvariants(ck bank.Keeper, k stake.Keeper,
loose := sdk.ZeroDec()
bonded := sdk.ZeroDec()
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
})
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)
// 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
loose = loose.Add(feePool.CommunityPool.AmountOf("steak"))
loose = loose.Add(feePool.CommunityPool.AmountOf(stakeTypes.DefaultBondDenom))
// 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
d.IterateValidatorDistInfos(ctx,
func(_ int64, distInfo distribution.ValidatorDistInfo) (stop bool) {
loose = loose.Add(distInfo.DelPool.AmountOf("steak"))
loose = loose.Add(distInfo.ValCommission.AmountOf("steak"))
loose = loose.Add(distInfo.DelPool.AmountOf(stakeTypes.DefaultBondDenom))
loose = loose.Add(distInfo.ValCommission.AmountOf(stakeTypes.DefaultBondDenom))
return false
},
)

View File

@ -26,11 +26,11 @@ func SimulateMsgCreateValidator(m auth.AccountKeeper, k stake.Keeper) simulation
Moniker: simulation.RandStringOfLength(r, 10),
}
maxCommission := sdk.NewInt(10)
maxCommission := sdk.NewDecWithPrec(r.Int63n(1000), 3)
commission := stake.NewCommissionMsg(
sdk.NewDecWithPrec(simulation.RandomAmount(r, maxCommission).Int64(), 1),
sdk.NewDecWithPrec(simulation.RandomAmount(r, maxCommission).Int64(), 1),
sdk.NewDecWithPrec(simulation.RandomAmount(r, maxCommission).Int64(), 1),
simulation.RandomDecAmount(r, maxCommission),
maxCommission,
simulation.RandomDecAmount(r, maxCommission),
)
acc := simulation.RandomAcc(r, accs)
@ -85,11 +85,10 @@ func SimulateMsgEditValidator(k stake.Keeper) simulation.Operation {
Details: simulation.RandStringOfLength(r, 10),
}
maxCommission := sdk.NewInt(10)
newCommissionRate := sdk.NewDecWithPrec(simulation.RandomAmount(r, maxCommission).Int64(), 1)
val := keeper.RandomValidator(r, k, ctx)
address := val.GetOperator()
newCommissionRate := simulation.RandomDecAmount(r, val.Commission.MaxRate)
msg := stake.MsgEditValidator{
Description: description,
ValidatorAddr: address,

View File

@ -28,7 +28,7 @@ var (
func NewTestMsgCreateValidator(address sdk.ValAddress, pubKey crypto.PubKey, amt int64) MsgCreateValidator {
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())
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{
DelegatorAddr: delAddr,
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,
ValidatorAddr: valAddr,
PubKey: valPubKey,
Delegation: sdk.NewCoin("steak", sdk.NewInt(amt)),
Delegation: sdk.NewCoin(types.DefaultBondDenom, sdk.NewInt(amt)),
}
}

View File

@ -11,7 +11,7 @@ type (
// Commission defines a commission parameters for a given validator.
Commission struct {
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
UpdateTime time.Time `json:"update_time"` // the last time the commission rate was changed
}

View File

@ -10,9 +10,9 @@ import (
)
var (
coinPos = sdk.NewInt64Coin("steak", 1000)
coinZero = sdk.NewInt64Coin("steak", 0)
coinNeg = sdk.NewInt64Coin("steak", -10000)
coinPos = sdk.NewInt64Coin(DefaultBondDenom, 1000)
coinZero = sdk.NewInt64Coin(DefaultBondDenom, 0)
coinNeg = sdk.NewInt64Coin(DefaultBondDenom, -10000)
)
// test ValidateBasic for MsgCreateValidator

View File

@ -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.
// Constant as this should not change without a hard fork.
ValidatorUpdateDelay int64 = 1
// Default bondable coin denomination
DefaultBondDenom = "STAKE"
)
// nolint - Keys for parameter access
@ -59,7 +62,7 @@ func DefaultParams() Params {
return Params{
UnbondingTime: defaultUnbondingTime,
MaxValidators: 100,
BondDenom: "steak",
BondDenom: DefaultBondDenom,
}
}
@ -69,7 +72,7 @@ func (p Params) HumanReadableString() string {
resp := "Params \n"
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)
return resp
}