Merge branch 'develop' into cwgoes/fix-signing-info-bugs
This commit is contained in:
commit
2c4d9a0be4
|
@ -56,6 +56,7 @@ jobs:
|
|||
name: Get metalinter
|
||||
command: |
|
||||
export PATH="$GOBIN:$PATH"
|
||||
make get_tools
|
||||
make get_dev_tools
|
||||
- run:
|
||||
name: Lint source
|
||||
|
|
29
Makefile
29
Makefile
|
@ -6,6 +6,10 @@ BUILD_FLAGS = -tags "${BUILD_TAGS}" -ldflags "-X github.com/cosmos/cosmos-sdk/ve
|
|||
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 \
|
||||
github.com/rakyll/statik
|
||||
all: get_tools get_vendor_deps install install_examples install_cosmos-sdk-cli test_lint test
|
||||
|
||||
########################################
|
||||
|
@ -91,22 +95,27 @@ dist:
|
|||
### Tools & dependencies
|
||||
|
||||
check_tools:
|
||||
cd tools && $(MAKE) check_tools
|
||||
|
||||
check_dev_tools:
|
||||
cd tools && $(MAKE) check_dev_tools
|
||||
@# https://stackoverflow.com/a/25668869
|
||||
@echo "Found tools: $(foreach tool,$(notdir $(GOTOOLS)),\
|
||||
$(if $(shell which $(tool)),$(tool),$(error "No $(tool) in PATH")))"
|
||||
|
||||
update_tools:
|
||||
cd tools && $(MAKE) update_tools
|
||||
@echo "--> Updating tools to correct version"
|
||||
./scripts/get_tools.sh
|
||||
|
||||
update_dev_tools:
|
||||
cd tools && $(MAKE) update_dev_tools
|
||||
@echo "--> Downloading linters (this may take awhile)"
|
||||
$(GOPATH)/src/github.com/alecthomas/gometalinter/scripts/install.sh -b $(GOBIN)
|
||||
go get -u github.com/tendermint/lint/golint
|
||||
|
||||
get_tools:
|
||||
cd tools && $(MAKE) get_tools
|
||||
@echo "--> Installing tools"
|
||||
./scripts/get_tools.sh
|
||||
|
||||
get_dev_tools:
|
||||
cd tools && $(MAKE) get_dev_tools
|
||||
@echo "--> Downloading linters (this may take awhile)"
|
||||
$(GOPATH)/src/github.com/alecthomas/gometalinter/scripts/install.sh -b $(GOBIN)
|
||||
go get github.com/tendermint/lint/golint
|
||||
|
||||
get_vendor_deps:
|
||||
@echo "--> Generating vendor directory via dep ensure"
|
||||
|
@ -181,8 +190,8 @@ test_cover:
|
|||
@export VERSION=$(VERSION); bash tests/test_cover.sh
|
||||
|
||||
test_lint:
|
||||
gometalinter.v2 --config=tools/gometalinter.json ./...
|
||||
!(gometalinter.v2 --exclude /usr/lib/go/src/ --exclude client/lcd/statik/statik.go --disable-all --enable='errcheck' --vendor ./... | grep -v "client/")
|
||||
gometalinter --config=tools/gometalinter.json ./...
|
||||
!(gometalinter --exclude /usr/lib/go/src/ --exclude client/lcd/statik/statik.go --exclude 'vendor/*' --disable-all --enable='errcheck' --vendor ./... | grep -v "client/")
|
||||
find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" | xargs gofmt -d -s
|
||||
dep status >> /dev/null
|
||||
!(grep -n branch Gopkg.toml)
|
||||
|
|
|
@ -44,7 +44,7 @@ BREAKING CHANGES
|
|||
* [simulation] \#2162 Added back correct supply invariants
|
||||
* [x/slashing] \#2430 Simulate more slashes, check if validator is jailed before jailing
|
||||
* [x/stake] \#2393 Removed `CompleteUnbonding` and `CompleteRedelegation` Msg types, and instead added unbonding/redelegation queues to endblocker
|
||||
|
||||
|
||||
* SDK
|
||||
* [core] \#2219 Update to Tendermint 0.24.0
|
||||
* Validator set updates delayed by one block
|
||||
|
@ -70,13 +70,14 @@ BREAKING CHANGES
|
|||
* [x/staking] \#2236 more distribution hooks for distribution
|
||||
* [x/stake] \#2394 Split up UpdateValidator into distinct state transitions applied only in EndBlock
|
||||
* [x/slashing] \#2480 Fix signing info handling bugs & faulty slashing
|
||||
* [x/stake] \#2412 Added an unbonding validator queue to EndBlock to automatically update validator.Status when finished Unbonding
|
||||
|
||||
* Tendermint
|
||||
* Update tendermint version from v0.23.0 to v0.25.0, notable changes
|
||||
* Mempool now won't build too large blocks, or too computationally expensive blocks
|
||||
* Maximum tx sizes and gas are now removed, and are implicitly the blocks maximums
|
||||
* ABCI validators no longer send the pubkey. The pubkey is only sent in validator updates
|
||||
* Validator set changes are now delayed by one block
|
||||
* Validator set changes are now delayed by one block
|
||||
* Block header now includes the next validator sets hash
|
||||
* BFT time is implemented
|
||||
* Secp256k1 signature format has changed
|
||||
|
@ -92,6 +93,7 @@ FEATURES
|
|||
* [gaia-lite] [\#1953](https://github.com/cosmos/cosmos-sdk/issues/1953) Add /sign endpoint to sign transactions generated with `generate_only=true`.
|
||||
* [gaia-lite] [\#1954](https://github.com/cosmos/cosmos-sdk/issues/1954) Add /broadcast endpoint to broadcast transactions signed by the /sign endpoint.
|
||||
* [gaia-lite] [\#2113](https://github.com/cosmos/cosmos-sdk/issues/2113) Rename `/accounts/{address}/send` to `/bank/accounts/{address}/transfers`, rename `/accounts/{address}` to `/auth/accounts/{address}`
|
||||
* [gaia-lite] [\#2478](https://github.com/cosmos/cosmos-sdk/issues/2478) Add query gov proposal's deposits endpoint
|
||||
|
||||
* Gaia CLI (`gaiacli`)
|
||||
* [cli] Cmds to query staking pool and params
|
||||
|
@ -171,6 +173,7 @@ IMPROVEMENTS
|
|||
calls which includes dynamic consumption of value length.
|
||||
* [types/decimal] \#2378 - Added truncate functionality to decimal
|
||||
* [client] [\#1184](https://github.com/cosmos/cosmos-sdk/issues/1184) Remove unused `client/tx/sign.go`.
|
||||
* [tools] \#2464 Lock binary dependencies to a specific version
|
||||
|
||||
* Tendermint
|
||||
|
||||
|
|
|
@ -10,19 +10,19 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/rpc"
|
||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
p2p "github.com/tendermint/tendermint/p2p"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
cryptoKeys "github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||
p2p "github.com/tendermint/tendermint/p2p"
|
||||
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||
|
||||
client "github.com/cosmos/cosmos-sdk/client"
|
||||
keys "github.com/cosmos/cosmos-sdk/client/keys"
|
||||
rpc "github.com/cosmos/cosmos-sdk/client/rpc"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
tests "github.com/cosmos/cosmos-sdk/tests"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
@ -613,7 +613,7 @@ func TestSubmitProposal(t *testing.T) {
|
|||
defer cleanup()
|
||||
|
||||
// create SubmitProposal TX
|
||||
resultTx := doSubmitProposal(t, port, seed, name, password, addr)
|
||||
resultTx := doSubmitProposal(t, port, seed, name, password, addr, 5)
|
||||
tests.WaitForHeight(resultTx.Height+1, port)
|
||||
|
||||
// check if tx was committed
|
||||
|
@ -635,7 +635,7 @@ func TestDeposit(t *testing.T) {
|
|||
defer cleanup()
|
||||
|
||||
// create SubmitProposal TX
|
||||
resultTx := doSubmitProposal(t, port, seed, name, password, addr)
|
||||
resultTx := doSubmitProposal(t, port, seed, name, password, addr, 5)
|
||||
tests.WaitForHeight(resultTx.Height+1, port)
|
||||
|
||||
// check if tx was committed
|
||||
|
@ -650,7 +650,7 @@ func TestDeposit(t *testing.T) {
|
|||
require.Equal(t, "Test", proposal.GetTitle())
|
||||
|
||||
// create SubmitProposal TX
|
||||
resultTx = doDeposit(t, port, seed, name, password, addr, proposalID)
|
||||
resultTx = doDeposit(t, port, seed, name, password, addr, proposalID, 5)
|
||||
tests.WaitForHeight(resultTx.Height+1, port)
|
||||
|
||||
// query proposal
|
||||
|
@ -669,7 +669,7 @@ func TestVote(t *testing.T) {
|
|||
defer cleanup()
|
||||
|
||||
// create SubmitProposal TX
|
||||
resultTx := doSubmitProposal(t, port, seed, name, password, addr)
|
||||
resultTx := doSubmitProposal(t, port, seed, name, password, addr, 5)
|
||||
tests.WaitForHeight(resultTx.Height+1, port)
|
||||
|
||||
// check if tx was committed
|
||||
|
@ -684,7 +684,7 @@ func TestVote(t *testing.T) {
|
|||
require.Equal(t, "Test", proposal.GetTitle())
|
||||
|
||||
// create SubmitProposal TX
|
||||
resultTx = doDeposit(t, port, seed, name, password, addr, proposalID)
|
||||
resultTx = doDeposit(t, port, seed, name, password, addr, proposalID, 5)
|
||||
tests.WaitForHeight(resultTx.Height+1, port)
|
||||
|
||||
// query proposal
|
||||
|
@ -725,27 +725,52 @@ func TestProposalsQuery(t *testing.T) {
|
|||
defer cleanup()
|
||||
|
||||
// Addr1 proposes (and deposits) proposals #1 and #2
|
||||
resultTx := doSubmitProposal(t, port, seed, name, password1, addr)
|
||||
resultTx := doSubmitProposal(t, port, seed, name, password1, addr, 5)
|
||||
var proposalID1 int64
|
||||
cdc.UnmarshalBinaryBare(resultTx.DeliverTx.GetData(), &proposalID1)
|
||||
tests.WaitForHeight(resultTx.Height+1, port)
|
||||
resultTx = doSubmitProposal(t, port, seed, name, password1, addr)
|
||||
resultTx = doSubmitProposal(t, port, seed, name, password1, addr, 5)
|
||||
var proposalID2 int64
|
||||
cdc.UnmarshalBinaryBare(resultTx.DeliverTx.GetData(), &proposalID2)
|
||||
tests.WaitForHeight(resultTx.Height+1, port)
|
||||
|
||||
// Addr2 proposes (and deposits) proposals #3
|
||||
resultTx = doSubmitProposal(t, port, seed2, name2, password2, addr2)
|
||||
resultTx = doSubmitProposal(t, port, seed2, name2, password2, addr2, 5)
|
||||
var proposalID3 int64
|
||||
cdc.UnmarshalBinaryBare(resultTx.DeliverTx.GetData(), &proposalID3)
|
||||
tests.WaitForHeight(resultTx.Height+1, port)
|
||||
|
||||
// Addr2 deposits on proposals #2 & #3
|
||||
resultTx = doDeposit(t, port, seed2, name2, password2, addr2, proposalID2)
|
||||
resultTx = doDeposit(t, port, seed2, name2, password2, addr2, proposalID2, 5)
|
||||
tests.WaitForHeight(resultTx.Height+1, port)
|
||||
resultTx = doDeposit(t, port, seed2, name2, password2, addr2, proposalID3)
|
||||
resultTx = doDeposit(t, port, seed2, name2, password2, addr2, proposalID3, 5)
|
||||
tests.WaitForHeight(resultTx.Height+1, port)
|
||||
|
||||
// check deposits match proposal and individual deposits
|
||||
deposits := getDeposits(t, port, proposalID1)
|
||||
require.Len(t, deposits, 1)
|
||||
deposit := getDeposit(t, port, proposalID1, addr)
|
||||
require.Equal(t, deposit, deposits[0])
|
||||
|
||||
deposits = getDeposits(t, port, proposalID2)
|
||||
require.Len(t, deposits, 2)
|
||||
deposit = getDeposit(t, port, proposalID2, addr)
|
||||
require.Equal(t, deposit, deposits[0])
|
||||
deposit = getDeposit(t, port, proposalID2, addr2)
|
||||
require.Equal(t, deposit, deposits[1])
|
||||
|
||||
deposits = getDeposits(t, port, proposalID3)
|
||||
require.Len(t, deposits, 1)
|
||||
deposit = getDeposit(t, port, proposalID3, addr2)
|
||||
require.Equal(t, deposit, deposits[0])
|
||||
|
||||
// increasing the amount of the deposit should update the existing one
|
||||
resultTx = doDeposit(t, port, seed, name, password1, addr, proposalID1, 1)
|
||||
tests.WaitForHeight(resultTx.Height+1, port)
|
||||
|
||||
deposits = getDeposits(t, port, proposalID1)
|
||||
require.Len(t, deposits, 1)
|
||||
|
||||
// Only proposals #1 should be in Deposit Period
|
||||
proposals := getProposalsFilterStatus(t, port, gov.StatusDepositPeriod)
|
||||
require.Len(t, proposals, 1)
|
||||
|
@ -1168,6 +1193,15 @@ func getProposal(t *testing.T, port string, proposalID int64) gov.Proposal {
|
|||
return proposal
|
||||
}
|
||||
|
||||
func getDeposits(t *testing.T, port string, proposalID int64) []gov.Deposit {
|
||||
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals/%d/deposits", proposalID), nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
var deposits []gov.Deposit
|
||||
err := cdc.UnmarshalJSON([]byte(body), &deposits)
|
||||
require.Nil(t, err)
|
||||
return deposits
|
||||
}
|
||||
|
||||
func getDeposit(t *testing.T, port string, proposalID int64, depositerAddr sdk.AccAddress) gov.Deposit {
|
||||
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals/%d/deposits/%s", proposalID, depositerAddr), nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
|
@ -1245,7 +1279,7 @@ func getProposalsFilterStatus(t *testing.T, port string, status gov.ProposalStat
|
|||
return proposals
|
||||
}
|
||||
|
||||
func doSubmitProposal(t *testing.T, port, seed, name, password string, proposerAddr sdk.AccAddress) (resultTx ctypes.ResultBroadcastTxCommit) {
|
||||
func doSubmitProposal(t *testing.T, port, seed, name, password string, proposerAddr sdk.AccAddress, amount int64) (resultTx ctypes.ResultBroadcastTxCommit) {
|
||||
|
||||
acc := getAccount(t, port, proposerAddr)
|
||||
accnum := acc.GetAccountNumber()
|
||||
|
@ -1259,7 +1293,7 @@ func doSubmitProposal(t *testing.T, port, seed, name, password string, proposerA
|
|||
"description": "test",
|
||||
"proposal_type": "Text",
|
||||
"proposer": "%s",
|
||||
"initial_deposit": [{ "denom": "steak", "amount": "5" }],
|
||||
"initial_deposit": [{ "denom": "steak", "amount": "%d" }],
|
||||
"base_req": {
|
||||
"name": "%s",
|
||||
"password": "%s",
|
||||
|
@ -1267,7 +1301,7 @@ func doSubmitProposal(t *testing.T, port, seed, name, password string, proposerA
|
|||
"account_number":"%d",
|
||||
"sequence":"%d"
|
||||
}
|
||||
}`, proposerAddr, name, password, chainID, accnum, sequence))
|
||||
}`, proposerAddr, amount, name, password, chainID, accnum, sequence))
|
||||
res, body := Request(t, port, "POST", "/gov/proposals", jsonStr)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
|
||||
|
@ -1278,7 +1312,7 @@ func doSubmitProposal(t *testing.T, port, seed, name, password string, proposerA
|
|||
return results
|
||||
}
|
||||
|
||||
func doDeposit(t *testing.T, port, seed, name, password string, proposerAddr sdk.AccAddress, proposalID int64) (resultTx ctypes.ResultBroadcastTxCommit) {
|
||||
func doDeposit(t *testing.T, port, seed, name, password string, proposerAddr sdk.AccAddress, proposalID int64, amount int64) (resultTx ctypes.ResultBroadcastTxCommit) {
|
||||
|
||||
acc := getAccount(t, port, proposerAddr)
|
||||
accnum := acc.GetAccountNumber()
|
||||
|
@ -1289,7 +1323,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": "5" }],
|
||||
"amount": [{ "denom": "steak", "amount": "%d" }],
|
||||
"base_req": {
|
||||
"name": "%s",
|
||||
"password": "%s",
|
||||
|
@ -1297,7 +1331,7 @@ func doDeposit(t *testing.T, port, seed, name, password string, proposerAddr sdk
|
|||
"account_number":"%d",
|
||||
"sequence": "%d"
|
||||
}
|
||||
}`, proposerAddr, name, password, chainID, accnum, sequence))
|
||||
}`, proposerAddr, 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)
|
||||
|
||||
|
|
|
@ -88,12 +88,41 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio
|
|||
|
||||
// add handlers
|
||||
app.bankKeeper = bank.NewBaseKeeper(app.accountMapper)
|
||||
app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams)
|
||||
app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.tkeyStake, app.bankKeeper, app.RegisterCodespace(stake.DefaultCodespace))
|
||||
app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.paramsKeeper.Getter(), app.RegisterCodespace(slashing.DefaultCodespace))
|
||||
app.stakeKeeper = app.stakeKeeper.WithHooks(app.slashingKeeper.Hooks())
|
||||
app.govKeeper = gov.NewKeeper(app.cdc, app.keyGov, app.paramsKeeper.Setter(), app.bankKeeper, app.stakeKeeper, app.RegisterCodespace(gov.DefaultCodespace))
|
||||
app.feeCollectionKeeper = auth.NewFeeCollectionKeeper(app.cdc, app.keyFeeCollection)
|
||||
|
||||
app.paramsKeeper = params.NewKeeper(
|
||||
app.cdc,
|
||||
app.keyParams, app.tkeyParams,
|
||||
)
|
||||
|
||||
app.stakeKeeper = stake.NewKeeper(
|
||||
app.cdc,
|
||||
app.keyStake, app.tkeyStake,
|
||||
app.bankKeeper, app.paramsKeeper.Subspace(stake.DefaultParamspace),
|
||||
app.RegisterCodespace(stake.DefaultCodespace),
|
||||
)
|
||||
|
||||
app.slashingKeeper = slashing.NewKeeper(
|
||||
app.cdc,
|
||||
app.keySlashing,
|
||||
app.stakeKeeper, app.paramsKeeper.Subspace(slashing.DefaultParamspace),
|
||||
app.RegisterCodespace(slashing.DefaultCodespace),
|
||||
)
|
||||
|
||||
app.stakeKeeper = app.stakeKeeper.WithHooks(
|
||||
app.slashingKeeper.Hooks(),
|
||||
)
|
||||
|
||||
app.govKeeper = gov.NewKeeper(
|
||||
app.cdc,
|
||||
app.keyGov,
|
||||
app.paramsKeeper, app.paramsKeeper.Subspace(gov.DefaultParamspace), app.bankKeeper, app.stakeKeeper,
|
||||
app.RegisterCodespace(gov.DefaultCodespace),
|
||||
)
|
||||
|
||||
app.feeCollectionKeeper = auth.NewFeeCollectionKeeper(
|
||||
app.cdc,
|
||||
app.keyFeeCollection,
|
||||
)
|
||||
|
||||
// register message routes
|
||||
app.Router().
|
||||
|
@ -184,7 +213,7 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci
|
|||
}
|
||||
|
||||
// load the address to pubkey map
|
||||
slashing.InitGenesis(ctx, app.slashingKeeper, genesisState.StakeData)
|
||||
slashing.InitGenesis(ctx, app.slashingKeeper, genesisState.SlashingData, genesisState.StakeData)
|
||||
|
||||
gov.InitGenesis(ctx, app.govKeeper, genesisState.GovData)
|
||||
err = GaiaValidateGenesisState(genesisState)
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
"github.com/cosmos/cosmos-sdk/x/slashing"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/tendermint/tendermint/libs/db"
|
||||
|
@ -21,8 +22,9 @@ func setGenesis(gapp *GaiaApp, accs ...*auth.BaseAccount) error {
|
|||
}
|
||||
|
||||
genesisState := GenesisState{
|
||||
Accounts: genaccs,
|
||||
StakeData: stake.DefaultGenesisState(),
|
||||
Accounts: genaccs,
|
||||
StakeData: stake.DefaultGenesisState(),
|
||||
SlashingData: slashing.DefaultGenesisState(),
|
||||
}
|
||||
|
||||
stateBytes, err := codec.MarshalJSONIndent(gapp.cdc, genesisState)
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||
"github.com/cosmos/cosmos-sdk/x/slashing"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
|
@ -31,9 +32,10 @@ var (
|
|||
|
||||
// State to Unmarshal
|
||||
type GenesisState struct {
|
||||
Accounts []GenesisAccount `json:"accounts"`
|
||||
StakeData stake.GenesisState `json:"stake"`
|
||||
GovData gov.GenesisState `json:"gov"`
|
||||
Accounts []GenesisAccount `json:"accounts"`
|
||||
StakeData stake.GenesisState `json:"stake"`
|
||||
GovData gov.GenesisState `json:"gov"`
|
||||
SlashingData slashing.GenesisState `json:"slashing"`
|
||||
}
|
||||
|
||||
// GenesisAccount doesn't need pubkey or sequence
|
||||
|
@ -168,6 +170,8 @@ func GaiaAppGenState(cdc *codec.Codec, appGenTxs []json.RawMessage) (genesisStat
|
|||
// start with the default staking genesis state
|
||||
stakeData := stake.DefaultGenesisState()
|
||||
|
||||
slashingData := slashing.DefaultGenesisState()
|
||||
|
||||
// get genesis flag account information
|
||||
genaccs := make([]GenesisAccount, len(appGenTxs))
|
||||
for i, appGenTx := range appGenTxs {
|
||||
|
@ -190,9 +194,10 @@ func GaiaAppGenState(cdc *codec.Codec, appGenTxs []json.RawMessage) (genesisStat
|
|||
|
||||
// create the final app state
|
||||
genesisState = GenesisState{
|
||||
Accounts: genaccs,
|
||||
StakeData: stakeData,
|
||||
GovData: gov.DefaultGenesisState(),
|
||||
Accounts: genaccs,
|
||||
StakeData: stakeData,
|
||||
GovData: gov.DefaultGenesisState(),
|
||||
SlashingData: slashingData,
|
||||
}
|
||||
|
||||
return
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||
govsim "github.com/cosmos/cosmos-sdk/x/gov/simulation"
|
||||
"github.com/cosmos/cosmos-sdk/x/mock/simulation"
|
||||
"github.com/cosmos/cosmos-sdk/x/slashing"
|
||||
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"
|
||||
|
@ -52,9 +53,11 @@ func appStateFn(r *rand.Rand, accs []simulation.Account) json.RawMessage {
|
|||
Coins: coins,
|
||||
})
|
||||
}
|
||||
govGenesis := gov.DefaultGenesisState()
|
||||
|
||||
// Default genesis state
|
||||
govGenesis := gov.DefaultGenesisState()
|
||||
stakeGenesis := stake.DefaultGenesisState()
|
||||
slashingGenesis := slashing.DefaultGenesisState()
|
||||
var validators []stake.Validator
|
||||
var delegations []stake.Delegation
|
||||
// XXX Try different numbers of initially bonded validators
|
||||
|
@ -74,9 +77,10 @@ func appStateFn(r *rand.Rand, accs []simulation.Account) json.RawMessage {
|
|||
stakeGenesis.Params.InflationMax = sdk.NewDec(0)
|
||||
stakeGenesis.Params.InflationMin = sdk.NewDec(0)
|
||||
genesis := GenesisState{
|
||||
Accounts: genesisAccounts,
|
||||
StakeData: stakeGenesis,
|
||||
GovData: govGenesis,
|
||||
Accounts: genesisAccounts,
|
||||
StakeData: stakeGenesis,
|
||||
SlashingData: slashingGenesis,
|
||||
GovData: govGenesis,
|
||||
}
|
||||
|
||||
// Marshal genesis
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||
"github.com/cosmos/cosmos-sdk/x/slashing"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
@ -69,8 +70,9 @@ func NewTestGaiaAppGenState(
|
|||
}
|
||||
|
||||
return GenesisState{
|
||||
Accounts: genAccs,
|
||||
StakeData: stakeData,
|
||||
GovData: gov.DefaultGenesisState(),
|
||||
Accounts: genAccs,
|
||||
StakeData: stakeData,
|
||||
SlashingData: slashing.DefaultGenesisState(),
|
||||
GovData: gov.DefaultGenesisState(),
|
||||
}, nil
|
||||
}
|
||||
|
|
|
@ -135,6 +135,7 @@ type GaiaApp struct {
|
|||
tkeyStake *sdk.TransientStoreKey
|
||||
keySlashing *sdk.KVStoreKey
|
||||
keyParams *sdk.KVStoreKey
|
||||
tkeyParams *sdk.TransientStoreKey
|
||||
|
||||
// Manage getting and setting accounts
|
||||
accountMapper auth.AccountMapper
|
||||
|
@ -161,6 +162,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, baseAppOptions ...func(*bam.BaseAp
|
|||
tkeyStake: sdk.NewTransientStoreKey("transient_stake"),
|
||||
keySlashing: sdk.NewKVStoreKey("slashing"),
|
||||
keyParams: sdk.NewKVStoreKey("params"),
|
||||
tkeyParams: sdk.NewTransientStoreKey("transient_params"),
|
||||
}
|
||||
|
||||
// define the accountMapper
|
||||
|
@ -172,9 +174,9 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, baseAppOptions ...func(*bam.BaseAp
|
|||
|
||||
// add handlers
|
||||
app.bankKeeper = bank.NewBaseKeeper(app.accountMapper)
|
||||
app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams)
|
||||
app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.tkeyStake, app.bankKeeper, app.RegisterCodespace(stake.DefaultCodespace))
|
||||
app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.paramsKeeper.Getter(), app.RegisterCodespace(slashing.DefaultCodespace))
|
||||
app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams, app.tkeyParams)
|
||||
app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.tkeyStake, app.bankKeeper, app.paramsKeeper.Subspace(stake.DefaultParamspace), app.RegisterCodespace(stake.DefaultCodespace))
|
||||
app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.paramsKeeper.Subspace(slashing.DefaultParamspace), app.RegisterCodespace(slashing.DefaultCodespace))
|
||||
|
||||
// register message routes
|
||||
app.Router().
|
||||
|
@ -186,7 +188,8 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, baseAppOptions ...func(*bam.BaseAp
|
|||
app.SetBeginBlocker(app.BeginBlocker)
|
||||
app.SetEndBlocker(app.EndBlocker)
|
||||
app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, app.feeCollectionKeeper))
|
||||
app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyStake, app.keySlashing)
|
||||
app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyStake, app.keySlashing, app.keyParams)
|
||||
app.MountStore(app.tkeyParams, sdk.StoreTypeTransient)
|
||||
err := app.LoadLatestVersion(app.keyMain)
|
||||
if err != nil {
|
||||
cmn.Exit(err.Error())
|
||||
|
@ -252,6 +255,8 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci
|
|||
panic(err) // TODO https://github.com/cosmos/cosmos-sdk/issues/468 // return sdk.ErrGenesisParse("").TraceCause(err, "")
|
||||
}
|
||||
|
||||
slashing.InitGenesis(ctx, app.slashingKeeper, genesisState.SlashingData, genesisState.StakeData)
|
||||
|
||||
return abci.ResponseInitChain{
|
||||
Validators: validators,
|
||||
}
|
||||
|
|
|
@ -1,5 +1,20 @@
|
|||
# End-Block
|
||||
|
||||
## Unbonding Validator Queue
|
||||
|
||||
For all unbonding validators that have finished their unbonding period, this switches their validator.Status
|
||||
from sdk.Unbonding to sdk.Unbonded
|
||||
|
||||
```golang
|
||||
validatorQueue(currTime time.Time):
|
||||
// unbonding validators are in ordered queue from oldest to newest
|
||||
for all unbondingValidators whose CompleteTime < currTime:
|
||||
validator = GetValidator(unbondingValidator.ValidatorAddr)
|
||||
validator.Status = sdk.Bonded
|
||||
SetValidator(unbondingValidator)
|
||||
return
|
||||
```
|
||||
|
||||
## Validator Set Changes
|
||||
|
||||
The Tendermint validator set may be updated by state transitions that run at
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
#!/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
|
|
@ -13,13 +13,13 @@ import (
|
|||
func newGasKVStore() KVStore {
|
||||
meter := sdk.NewGasMeter(1000)
|
||||
mem := dbStoreAdapter{dbm.NewMemDB()}
|
||||
return NewGasKVStore(meter, sdk.DefaultGasConfig(), mem)
|
||||
return NewGasKVStore(meter, sdk.KVGasConfig(), mem)
|
||||
}
|
||||
|
||||
func TestGasKVStoreBasic(t *testing.T) {
|
||||
mem := dbStoreAdapter{dbm.NewMemDB()}
|
||||
meter := sdk.NewGasMeter(1000)
|
||||
st := NewGasKVStore(meter, sdk.DefaultGasConfig(), mem)
|
||||
st := NewGasKVStore(meter, sdk.KVGasConfig(), mem)
|
||||
require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty")
|
||||
st.Set(keyFmt(1), valFmt(1))
|
||||
require.Equal(t, valFmt(1), st.Get(keyFmt(1)))
|
||||
|
@ -31,7 +31,7 @@ func TestGasKVStoreBasic(t *testing.T) {
|
|||
func TestGasKVStoreIterator(t *testing.T) {
|
||||
mem := dbStoreAdapter{dbm.NewMemDB()}
|
||||
meter := sdk.NewGasMeter(1000)
|
||||
st := NewGasKVStore(meter, sdk.DefaultGasConfig(), mem)
|
||||
st := NewGasKVStore(meter, sdk.KVGasConfig(), mem)
|
||||
require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty")
|
||||
require.Empty(t, st.Get(keyFmt(2)), "Expected `key2` to be empty")
|
||||
st.Set(keyFmt(1), valFmt(1))
|
||||
|
@ -55,14 +55,14 @@ func TestGasKVStoreIterator(t *testing.T) {
|
|||
func TestGasKVStoreOutOfGasSet(t *testing.T) {
|
||||
mem := dbStoreAdapter{dbm.NewMemDB()}
|
||||
meter := sdk.NewGasMeter(0)
|
||||
st := NewGasKVStore(meter, sdk.DefaultGasConfig(), mem)
|
||||
st := NewGasKVStore(meter, sdk.KVGasConfig(), mem)
|
||||
require.Panics(t, func() { st.Set(keyFmt(1), valFmt(1)) }, "Expected out-of-gas")
|
||||
}
|
||||
|
||||
func TestGasKVStoreOutOfGasIterator(t *testing.T) {
|
||||
mem := dbStoreAdapter{dbm.NewMemDB()}
|
||||
meter := sdk.NewGasMeter(200)
|
||||
st := NewGasKVStore(meter, sdk.DefaultGasConfig(), mem)
|
||||
st := NewGasKVStore(meter, sdk.KVGasConfig(), mem)
|
||||
st.Set(keyFmt(1), valFmt(1))
|
||||
iterator := st.Iterator(nil, nil)
|
||||
iterator.Next()
|
||||
|
|
|
@ -26,6 +26,9 @@ func cloneAppend(bz []byte, tail []byte) (res []byte) {
|
|||
}
|
||||
|
||||
func (s prefixStore) key(key []byte) (res []byte) {
|
||||
if key == nil {
|
||||
panic("nil key on prefixStore")
|
||||
}
|
||||
res = cloneAppend(s.prefix, key)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ type kvpair struct {
|
|||
value []byte
|
||||
}
|
||||
|
||||
func setRandomKVPairs(t *testing.T, store KVStore) []kvpair {
|
||||
func genRandomKVPairs(t *testing.T) []kvpair {
|
||||
kvps := make([]kvpair, 20)
|
||||
|
||||
for i := 0; i < 20; i++ {
|
||||
|
@ -25,17 +25,26 @@ func setRandomKVPairs(t *testing.T, store KVStore) []kvpair {
|
|||
rand.Read(kvps[i].key)
|
||||
kvps[i].value = make([]byte, 32)
|
||||
rand.Read(kvps[i].value)
|
||||
|
||||
store.Set(kvps[i].key, kvps[i].value)
|
||||
}
|
||||
|
||||
return kvps
|
||||
}
|
||||
|
||||
func setRandomKVPairs(t *testing.T, store KVStore) []kvpair {
|
||||
kvps := genRandomKVPairs(t)
|
||||
for _, kvp := range kvps {
|
||||
store.Set(kvp.key, kvp.value)
|
||||
}
|
||||
return kvps
|
||||
}
|
||||
|
||||
func testPrefixStore(t *testing.T, baseStore KVStore, prefix []byte) {
|
||||
prefixStore := baseStore.Prefix(prefix)
|
||||
prefixPrefixStore := prefixStore.Prefix([]byte("prefix"))
|
||||
|
||||
require.Panics(t, func() { prefixStore.Get(nil) })
|
||||
require.Panics(t, func() { prefixStore.Set(nil, []byte{}) })
|
||||
|
||||
kvps := setRandomKVPairs(t, prefixPrefixStore)
|
||||
|
||||
for i := 0; i < 20; i++ {
|
||||
|
@ -81,7 +90,7 @@ func TestCacheKVStorePrefix(t *testing.T) {
|
|||
func TestGasKVStorePrefix(t *testing.T) {
|
||||
meter := sdk.NewGasMeter(100000000)
|
||||
mem := dbStoreAdapter{dbm.NewMemDB()}
|
||||
gasStore := NewGasKVStore(meter, sdk.DefaultGasConfig(), mem)
|
||||
gasStore := NewGasKVStore(meter, sdk.KVGasConfig(), mem)
|
||||
|
||||
testPrefixStore(t, gasStore, []byte("test"))
|
||||
}
|
||||
|
@ -109,6 +118,33 @@ func TestPrefixStoreIterate(t *testing.T) {
|
|||
pIter.Close()
|
||||
}
|
||||
|
||||
func incFirstByte(bz []byte) {
|
||||
if bz[0] == byte(255) {
|
||||
bz[0] = byte(0)
|
||||
return
|
||||
}
|
||||
bz[0]++
|
||||
}
|
||||
|
||||
func TestCloneAppend(t *testing.T) {
|
||||
kvps := genRandomKVPairs(t)
|
||||
for _, kvp := range kvps {
|
||||
bz := cloneAppend(kvp.key, kvp.value)
|
||||
require.Equal(t, bz, append(kvp.key, kvp.value...))
|
||||
|
||||
incFirstByte(bz)
|
||||
require.NotEqual(t, bz, append(kvp.key, kvp.value...))
|
||||
|
||||
bz = cloneAppend(kvp.key, kvp.value)
|
||||
incFirstByte(kvp.key)
|
||||
require.NotEqual(t, bz, append(kvp.key, kvp.value...))
|
||||
|
||||
bz = cloneAppend(kvp.key, kvp.value)
|
||||
incFirstByte(kvp.value)
|
||||
require.NotEqual(t, bz, append(kvp.key, kvp.value...))
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrefixStoreIteratorEdgeCase(t *testing.T) {
|
||||
db := dbm.NewMemDB()
|
||||
baseStore := dbStoreAdapter{db}
|
||||
|
|
170
tools/Makefile
170
tools/Makefile
|
@ -1,170 +0,0 @@
|
|||
all: get_tools
|
||||
|
||||
|
||||
########################################
|
||||
### DEP
|
||||
|
||||
DEP = github.com/golang/dep/cmd/dep
|
||||
GOLINT = github.com/tendermint/lint/golint
|
||||
GOMETALINTER = gopkg.in/alecthomas/gometalinter.v2
|
||||
UNCONVERT = github.com/mdempsky/unconvert
|
||||
INEFFASSIGN = github.com/gordonklaus/ineffassign
|
||||
MISSPELL = github.com/client9/misspell/cmd/misspell
|
||||
ERRCHECK = github.com/kisielk/errcheck
|
||||
UNPARAM = mvdan.cc/unparam
|
||||
STATIK = github.com/rakyll/statik
|
||||
|
||||
DEP_CHECK := $(shell command -v dep 2> /dev/null)
|
||||
GOLINT_CHECK := $(shell command -v golint 2> /dev/null)
|
||||
GOMETALINTER_CHECK := $(shell command -v gometalinter.v2 2> /dev/null)
|
||||
UNCONVERT_CHECK := $(shell command -v unconvert 2> /dev/null)
|
||||
INEFFASSIGN_CHECK := $(shell command -v ineffassign 2> /dev/null)
|
||||
MISSPELL_CHECK := $(shell command -v misspell 2> /dev/null)
|
||||
ERRCHECK_CHECK := $(shell command -v errcheck 2> /dev/null)
|
||||
UNPARAM_CHECK := $(shell command -v unparam 2> /dev/null)
|
||||
STATIK_CHECK := $(shell command -v statik 2> /dev/null)
|
||||
|
||||
check_tools:
|
||||
ifndef DEP_CHECK
|
||||
@echo "No dep in path. Install with 'make get_tools'."
|
||||
else
|
||||
@echo "Found dep in path."
|
||||
endif
|
||||
|
||||
check_dev_tools:
|
||||
$(MAKE) check_tools
|
||||
ifndef GOLINT_CHECK
|
||||
@echo "No golint in path. Install with 'make get_tools'."
|
||||
else
|
||||
@echo "Found golint in path."
|
||||
endif
|
||||
ifndef GOMETALINTER_CHECK
|
||||
@echo "No gometalinter in path. Install with 'make get_tools'."
|
||||
else
|
||||
@echo "Found gometalinter in path."
|
||||
endif
|
||||
ifndef UNCONVERT_CHECK
|
||||
@echo "No unconvert in path. Install with 'make get_tools'."
|
||||
else
|
||||
@echo "Found unconvert in path."
|
||||
endif
|
||||
ifndef INEFFASSIGN_CHECK
|
||||
@echo "No ineffassign in path. Install with 'make get_tools'."
|
||||
else
|
||||
@echo "Found ineffassign in path."
|
||||
endif
|
||||
ifndef MISSPELL_CHECK
|
||||
@echo "No misspell in path. Install with 'make get_tools'."
|
||||
else
|
||||
@echo "Found misspell in path."
|
||||
endif
|
||||
ifndef ERRCHECK_CHECK
|
||||
@echo "No errcheck in path. Install with 'make get_tools'."
|
||||
else
|
||||
@echo "Found errcheck in path."
|
||||
endif
|
||||
ifndef UNPARAM_CHECK
|
||||
@echo "No unparam in path. Install with 'make get_tools'."
|
||||
else
|
||||
@echo "Found unparam in path."
|
||||
endif
|
||||
ifndef STATIK_CHECK
|
||||
@echo "No statik in path. Install with 'make get_tools'."
|
||||
else
|
||||
@echo "Found statik in path."
|
||||
endif
|
||||
|
||||
|
||||
get_tools:
|
||||
ifdef DEP_CHECK
|
||||
@echo "Dep is already installed. Run 'make update_tools' to update."
|
||||
else
|
||||
@echo "Installing dep"
|
||||
go get -v $(DEP)
|
||||
endif
|
||||
ifdef STATIK_CHECK
|
||||
@echo "Statik is already installed. Run 'make update_tools' to update."
|
||||
else
|
||||
@echo "Installing statik"
|
||||
go version
|
||||
go get -v $(STATIK)
|
||||
endif
|
||||
|
||||
get_dev_tools:
|
||||
$(MAKE) get_tools
|
||||
ifdef GOLINT_CHECK
|
||||
@echo "Golint is already installed. Run 'make update_tools' to update."
|
||||
else
|
||||
@echo "Installing golint"
|
||||
go get -v $(GOLINT)
|
||||
endif
|
||||
ifdef GOMETALINTER_CHECK
|
||||
@echo "Gometalinter.v2 is already installed. Run 'make update_tools' to update."
|
||||
else
|
||||
@echo "Installing gometalinter.v2"
|
||||
go get -v $(GOMETALINTER)
|
||||
endif
|
||||
ifdef UNCONVERT_CHECK
|
||||
@echo "Unconvert is already installed. Run 'make update_tools' to update."
|
||||
else
|
||||
@echo "Installing unconvert"
|
||||
go get -v $(UNCONVERT)
|
||||
endif
|
||||
ifdef INEFFASSIGN_CHECK
|
||||
@echo "Ineffassign is already installed. Run 'make update_tools' to update."
|
||||
else
|
||||
@echo "Installing ineffassign"
|
||||
go get -v $(INEFFASSIGN)
|
||||
endif
|
||||
ifdef MISSPELL_CHECK
|
||||
@echo "misspell is already installed. Run 'make update_tools' to update."
|
||||
else
|
||||
@echo "Installing misspell"
|
||||
go get -v $(MISSPELL)
|
||||
endif
|
||||
ifdef ERRCHECK_CHECK
|
||||
@echo "errcheck is already installed. Run 'make update_tools' to update."
|
||||
else
|
||||
@echo "Installing errcheck"
|
||||
go get -v $(ERRCHECK)
|
||||
endif
|
||||
ifdef UNPARAM_CHECK
|
||||
@echo "unparam is already installed. Run 'make update_tools' to update."
|
||||
else
|
||||
@echo "Installing unparam"
|
||||
go get -v $(UNPARAM)
|
||||
endif
|
||||
ifdef STATIK_CHECK
|
||||
@echo "statik is already installed. Run 'make update_tools' to update."
|
||||
else
|
||||
@echo "Installing statik"
|
||||
go get -v $(STATIK)
|
||||
endif
|
||||
|
||||
update_tools:
|
||||
@echo "Updating dep"
|
||||
go get -u -v $(DEP)
|
||||
|
||||
update_dev_tools:
|
||||
$(MAKE) update_tools
|
||||
@echo "Updating tendermint/golint"
|
||||
go get -u -v $(GOLINT)
|
||||
@echo "Updating gometalinter.v2"
|
||||
go get -u -v $(GOMETALINTER)
|
||||
@echo "Updating unconvert"
|
||||
go get -u -v $(UNCONVERT)
|
||||
@echo "Updating ineffassign"
|
||||
go get -u -v $(INEFFASSIGN)
|
||||
@echo "Updating misspell"
|
||||
go get -u -v $(MISSPELL)
|
||||
@echo "Updating errcheck"
|
||||
go get -u -v $(ERRCHECK)
|
||||
@echo "Updating unparam"
|
||||
go get -u -v $(UNPARAM)
|
||||
@echo "Updating statik"
|
||||
go get -u -v $(STATIK)
|
||||
|
||||
# To avoid unintended conflicts with file names, always add to .PHONY
|
||||
# unless there is a reason not to.
|
||||
# https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html
|
||||
.PHONY: check_tools get_tools update_tools check_dev_tools get_dev_tools update_dev_tools
|
|
@ -6,5 +6,5 @@
|
|||
"Deadline": "500s",
|
||||
"Vendor": true,
|
||||
"Cyclo": 11,
|
||||
"Exclude": ["/usr/lib/go/src/", "client/lcd/statik/statik.go"]
|
||||
"Exclude": ["/usr/lib/go/src/", "client/lcd/statik/statik.go", "vendor/*"]
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@ type Context struct {
|
|||
}
|
||||
|
||||
// create a new context
|
||||
// nolint: unparam
|
||||
func NewContext(ms MultiStore, header abci.Header, isCheckTx bool, logger log.Logger) Context {
|
||||
c := Context{
|
||||
Context: context.Background(),
|
||||
|
@ -74,7 +73,7 @@ func (c Context) Value(key interface{}) interface{} {
|
|||
|
||||
// KVStore fetches a KVStore from the MultiStore.
|
||||
func (c Context) KVStore(key StoreKey) KVStore {
|
||||
return c.multiStore().GetKVStore(key).Gas(c.GasMeter(), cachedDefaultGasConfig)
|
||||
return c.multiStore().GetKVStore(key).Gas(c.GasMeter(), cachedKVGasConfig)
|
||||
}
|
||||
|
||||
// TransientStore fetches a TransientStore from the MultiStore.
|
||||
|
@ -189,7 +188,9 @@ func (c Context) WithBlockTime(newTime time.Time) Context {
|
|||
}
|
||||
|
||||
func (c Context) WithBlockHeight(height int64) Context {
|
||||
return c.withValue(contextKeyBlockHeight, height)
|
||||
newHeader := c.BlockHeader()
|
||||
newHeader.Height = height
|
||||
return c.withValue(contextKeyBlockHeight, height).withValue(contextKeyBlockHeader, newHeader)
|
||||
}
|
||||
|
||||
func (c Context) WithConsensusParams(params *abci.ConsensusParams) Context {
|
||||
|
|
|
@ -164,15 +164,16 @@ func TestContextWithCustom(t *testing.T) {
|
|||
meter := types.NewGasMeter(10000)
|
||||
minFees := types.Coins{types.NewInt64Coin("feeCoin", 1)}
|
||||
|
||||
ctx = types.NewContext(nil, header, ischeck, logger).
|
||||
ctx = types.NewContext(nil, header, ischeck, logger)
|
||||
require.Equal(t, header, ctx.BlockHeader())
|
||||
|
||||
ctx = ctx.
|
||||
WithBlockHeight(height).
|
||||
WithChainID(chainid).
|
||||
WithTxBytes(txbytes).
|
||||
WithVoteInfos(voteinfos).
|
||||
WithGasMeter(meter).
|
||||
WithMinimumFees(minFees)
|
||||
|
||||
require.Equal(t, header, ctx.BlockHeader())
|
||||
require.Equal(t, height, ctx.BlockHeight())
|
||||
require.Equal(t, chainid, ctx.ChainID())
|
||||
require.Equal(t, ischeck, ctx.IsCheckTx())
|
||||
|
|
|
@ -13,7 +13,7 @@ const (
|
|||
)
|
||||
|
||||
var (
|
||||
cachedDefaultGasConfig = DefaultGasConfig()
|
||||
cachedKVGasConfig = KVGasConfig()
|
||||
cachedTransientGasConfig = TransientGasConfig()
|
||||
)
|
||||
|
||||
|
@ -86,8 +86,8 @@ type GasConfig struct {
|
|||
IterNextCostFlat Gas
|
||||
}
|
||||
|
||||
// DefaultGasConfig returns a default gas config for KVStores.
|
||||
func DefaultGasConfig() GasConfig {
|
||||
// KVGasConfig returns a default gas config for KVStores.
|
||||
func KVGasConfig() GasConfig {
|
||||
return GasConfig{
|
||||
HasCost: 10,
|
||||
DeleteCost: 10,
|
||||
|
@ -103,5 +103,5 @@ func DefaultGasConfig() GasConfig {
|
|||
// TransientGasConfig returns a default gas config for TransientStores.
|
||||
func TransientGasConfig() GasConfig {
|
||||
// TODO: define gasconfig for transient stores
|
||||
return DefaultGasConfig()
|
||||
return KVGasConfig()
|
||||
}
|
||||
|
|
|
@ -31,13 +31,12 @@ func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *codec.Codec)
|
|||
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/deposits", RestProposalID), depositHandlerFn(cdc, cliCtx)).Methods("POST")
|
||||
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/votes", RestProposalID), voteHandlerFn(cdc, cliCtx)).Methods("POST")
|
||||
|
||||
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}", RestProposalID), queryProposalHandlerFn(cdc)).Methods("GET")
|
||||
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/deposits/{%s}", RestProposalID, RestDepositer), queryDepositHandlerFn(cdc)).Methods("GET")
|
||||
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/votes/{%s}", RestProposalID, RestVoter), queryVoteHandlerFn(cdc)).Methods("GET")
|
||||
|
||||
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/votes", RestProposalID), queryVotesOnProposalHandlerFn(cdc)).Methods("GET")
|
||||
|
||||
r.HandleFunc("/gov/proposals", queryProposalsWithParameterFn(cdc)).Methods("GET")
|
||||
r.HandleFunc("/gov/proposals", queryProposalsWithParameterFn(cdc, cliCtx)).Methods("GET")
|
||||
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}", RestProposalID), queryProposalHandlerFn(cdc, cliCtx)).Methods("GET")
|
||||
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/deposits", RestProposalID), queryDepositsHandlerFn(cdc, cliCtx)).Methods("GET")
|
||||
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/deposits/{%s}", RestProposalID, RestDepositer), queryDepositHandlerFn(cdc, cliCtx)).Methods("GET")
|
||||
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/votes", RestProposalID), queryVotesOnProposalHandlerFn(cdc, cliCtx)).Methods("GET")
|
||||
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/votes/{%s}", RestProposalID, RestVoter), queryVoteHandlerFn(cdc, cliCtx)).Methods("GET")
|
||||
}
|
||||
|
||||
type postProposalReq struct {
|
||||
|
@ -164,7 +163,7 @@ func voteHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc
|
|||
}
|
||||
}
|
||||
|
||||
func queryProposalHandlerFn(cdc *codec.Codec) http.HandlerFunc {
|
||||
func queryProposalHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
strProposalID := vars[RestProposalID]
|
||||
|
@ -180,8 +179,6 @@ func queryProposalHandlerFn(cdc *codec.Codec) http.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
||||
|
||||
params := gov.QueryProposalParams{
|
||||
ProposalID: proposalID,
|
||||
}
|
||||
|
@ -198,11 +195,41 @@ func queryProposalHandlerFn(cdc *codec.Codec) http.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
w.Write(res)
|
||||
utils.PostProcessResponse(w, cdc, res, cliCtx.Indent)
|
||||
}
|
||||
}
|
||||
|
||||
func queryDepositHandlerFn(cdc *codec.Codec) http.HandlerFunc {
|
||||
func queryDepositsHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
strProposalID := vars[RestProposalID]
|
||||
|
||||
proposalID, ok := utils.ParseInt64OrReturnBadRequest(w, strProposalID)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
params := gov.QueryDepositsParams{
|
||||
ProposalID: proposalID,
|
||||
}
|
||||
|
||||
bz, err := cdc.MarshalJSON(params)
|
||||
if err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
res, err := cliCtx.QueryWithData("custom/gov/deposits", bz)
|
||||
if err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
utils.PostProcessResponse(w, cdc, res, cliCtx.Indent)
|
||||
}
|
||||
}
|
||||
|
||||
func queryDepositHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
strProposalID := vars[RestProposalID]
|
||||
|
@ -232,8 +259,6 @@ func queryDepositHandlerFn(cdc *codec.Codec) http.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
||||
|
||||
params := gov.QueryDepositParams{
|
||||
ProposalID: proposalID,
|
||||
Depositer: depositerAddr,
|
||||
|
@ -265,11 +290,11 @@ func queryDepositHandlerFn(cdc *codec.Codec) http.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
w.Write(res)
|
||||
utils.PostProcessResponse(w, cdc, res, cliCtx.Indent)
|
||||
}
|
||||
}
|
||||
|
||||
func queryVoteHandlerFn(cdc *codec.Codec) http.HandlerFunc {
|
||||
func queryVoteHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
strProposalID := vars[RestProposalID]
|
||||
|
@ -299,8 +324,6 @@ func queryVoteHandlerFn(cdc *codec.Codec) http.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
||||
|
||||
params := gov.QueryVoteParams{
|
||||
Voter: voterAddr,
|
||||
ProposalID: proposalID,
|
||||
|
@ -335,12 +358,12 @@ func queryVoteHandlerFn(cdc *codec.Codec) http.HandlerFunc {
|
|||
utils.WriteErrorResponse(w, http.StatusNotFound, err.Error())
|
||||
return
|
||||
}
|
||||
w.Write(res)
|
||||
utils.PostProcessResponse(w, cdc, res, cliCtx.Indent)
|
||||
}
|
||||
}
|
||||
|
||||
// todo: Split this functionality into helper functions to remove the above
|
||||
func queryVotesOnProposalHandlerFn(cdc *codec.Codec) http.HandlerFunc {
|
||||
func queryVotesOnProposalHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
strProposalID := vars[RestProposalID]
|
||||
|
@ -356,8 +379,6 @@ func queryVotesOnProposalHandlerFn(cdc *codec.Codec) http.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
||||
|
||||
params := gov.QueryVotesParams{
|
||||
ProposalID: proposalID,
|
||||
}
|
||||
|
@ -373,12 +394,12 @@ func queryVotesOnProposalHandlerFn(cdc *codec.Codec) http.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
w.Write(res)
|
||||
utils.PostProcessResponse(w, cdc, res, cliCtx.Indent)
|
||||
}
|
||||
}
|
||||
|
||||
// todo: Split this functionality into helper functions to remove the above
|
||||
func queryProposalsWithParameterFn(cdc *codec.Codec) http.HandlerFunc {
|
||||
func queryProposalsWithParameterFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
bechVoterAddr := r.URL.Query().Get(RestVoter)
|
||||
bechDepositerAddr := r.URL.Query().Get(RestDepositer)
|
||||
|
@ -430,20 +451,18 @@ func queryProposalsWithParameterFn(cdc *codec.Codec) http.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
||||
|
||||
res, err := cliCtx.QueryWithData("custom/gov/proposals", bz)
|
||||
if err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(res)
|
||||
utils.PostProcessResponse(w, cdc, res, cliCtx.Indent)
|
||||
}
|
||||
}
|
||||
|
||||
// todo: Split this functionality into helper functions to remove the above
|
||||
func queryTallyOnProposalHandlerFn(cdc *codec.Codec) http.HandlerFunc {
|
||||
func queryTallyOnProposalHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
strProposalID := vars[RestProposalID]
|
||||
|
@ -461,8 +480,6 @@ func queryTallyOnProposalHandlerFn(cdc *codec.Codec) http.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
||||
|
||||
params := gov.QueryTallyParams{
|
||||
ProposalID: proposalID,
|
||||
}
|
||||
|
@ -480,6 +497,6 @@ func queryTallyOnProposalHandlerFn(cdc *codec.Codec) http.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
w.Write(res)
|
||||
utils.PostProcessResponse(w, cdc, res, cliCtx.Indent)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,17 +7,34 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/x/params"
|
||||
)
|
||||
|
||||
// nolint
|
||||
// Parameter store default namestore
|
||||
const (
|
||||
ParamStoreKeyDepositProcedure = "gov/depositprocedure"
|
||||
ParamStoreKeyVotingProcedure = "gov/votingprocedure"
|
||||
ParamStoreKeyTallyingProcedure = "gov/tallyingprocedure"
|
||||
DefaultParamspace = "gov"
|
||||
)
|
||||
|
||||
// Parameter store key
|
||||
var (
|
||||
ParamStoreKeyDepositProcedure = []byte("depositprocedure")
|
||||
ParamStoreKeyVotingProcedure = []byte("votingprocedure")
|
||||
ParamStoreKeyTallyingProcedure = []byte("tallyingprocedure")
|
||||
)
|
||||
|
||||
// Type declaration for parameters
|
||||
func ParamTypeTable() params.TypeTable {
|
||||
return params.NewTypeTable(
|
||||
ParamStoreKeyDepositProcedure, DepositProcedure{},
|
||||
ParamStoreKeyVotingProcedure, VotingProcedure{},
|
||||
ParamStoreKeyTallyingProcedure, TallyingProcedure{},
|
||||
)
|
||||
}
|
||||
|
||||
// Governance Keeper
|
||||
type Keeper struct {
|
||||
// The reference to the ParamSetter to get and set Global Params
|
||||
ps params.Setter
|
||||
// The reference to the Param Keeper to get and set Global Params
|
||||
paramsKeeper params.Keeper
|
||||
|
||||
// The reference to the Paramstore to get and set gov specific params
|
||||
paramSpace params.Subspace
|
||||
|
||||
// The reference to the CoinKeeper to modify balances
|
||||
ck bank.Keeper
|
||||
|
@ -43,15 +60,16 @@ type Keeper struct {
|
|||
// - depositing funds into proposals, and activating upon sufficient funds being deposited
|
||||
// - users voting on proposals, with weight proportional to stake in the system
|
||||
// - and tallying the result of the vote.
|
||||
func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, ps params.Setter, ck bank.Keeper, ds sdk.DelegationSet, codespace sdk.CodespaceType) Keeper {
|
||||
func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, paramsKeeper params.Keeper, paramSpace params.Subspace, ck bank.Keeper, ds sdk.DelegationSet, codespace sdk.CodespaceType) Keeper {
|
||||
return Keeper{
|
||||
storeKey: key,
|
||||
ps: ps,
|
||||
ck: ck,
|
||||
ds: ds,
|
||||
vs: ds.GetValidatorSet(),
|
||||
cdc: cdc,
|
||||
codespace: codespace,
|
||||
storeKey: key,
|
||||
paramsKeeper: paramsKeeper,
|
||||
paramSpace: paramSpace.WithTypeTable(ParamTypeTable()),
|
||||
ck: ck,
|
||||
ds: ds,
|
||||
vs: ds.GetValidatorSet(),
|
||||
cdc: cdc,
|
||||
codespace: codespace,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -210,7 +228,7 @@ func (keeper Keeper) activateVotingPeriod(ctx sdk.Context, proposal Proposal) {
|
|||
// nolint: errcheck
|
||||
func (keeper Keeper) GetDepositProcedure(ctx sdk.Context) DepositProcedure {
|
||||
var depositProcedure DepositProcedure
|
||||
keeper.ps.Get(ctx, ParamStoreKeyDepositProcedure, &depositProcedure)
|
||||
keeper.paramSpace.Get(ctx, ParamStoreKeyDepositProcedure, &depositProcedure)
|
||||
return depositProcedure
|
||||
}
|
||||
|
||||
|
@ -218,7 +236,7 @@ func (keeper Keeper) GetDepositProcedure(ctx sdk.Context) DepositProcedure {
|
|||
// nolint: errcheck
|
||||
func (keeper Keeper) GetVotingProcedure(ctx sdk.Context) VotingProcedure {
|
||||
var votingProcedure VotingProcedure
|
||||
keeper.ps.Get(ctx, ParamStoreKeyVotingProcedure, &votingProcedure)
|
||||
keeper.paramSpace.Get(ctx, ParamStoreKeyVotingProcedure, &votingProcedure)
|
||||
return votingProcedure
|
||||
}
|
||||
|
||||
|
@ -226,23 +244,23 @@ func (keeper Keeper) GetVotingProcedure(ctx sdk.Context) VotingProcedure {
|
|||
// nolint: errcheck
|
||||
func (keeper Keeper) GetTallyingProcedure(ctx sdk.Context) TallyingProcedure {
|
||||
var tallyingProcedure TallyingProcedure
|
||||
keeper.ps.Get(ctx, ParamStoreKeyTallyingProcedure, &tallyingProcedure)
|
||||
keeper.paramSpace.Get(ctx, ParamStoreKeyTallyingProcedure, &tallyingProcedure)
|
||||
return tallyingProcedure
|
||||
}
|
||||
|
||||
// nolint: errcheck
|
||||
func (keeper Keeper) setDepositProcedure(ctx sdk.Context, depositProcedure DepositProcedure) {
|
||||
keeper.ps.Set(ctx, ParamStoreKeyDepositProcedure, &depositProcedure)
|
||||
keeper.paramSpace.Set(ctx, ParamStoreKeyDepositProcedure, &depositProcedure)
|
||||
}
|
||||
|
||||
// nolint: errcheck
|
||||
func (keeper Keeper) setVotingProcedure(ctx sdk.Context, votingProcedure VotingProcedure) {
|
||||
keeper.ps.Set(ctx, ParamStoreKeyVotingProcedure, &votingProcedure)
|
||||
keeper.paramSpace.Set(ctx, ParamStoreKeyVotingProcedure, &votingProcedure)
|
||||
}
|
||||
|
||||
// nolint: errcheck
|
||||
func (keeper Keeper) setTallyingProcedure(ctx sdk.Context, tallyingProcedure TallyingProcedure) {
|
||||
keeper.ps.Set(ctx, ParamStoreKeyTallyingProcedure, &tallyingProcedure)
|
||||
keeper.paramSpace.Set(ctx, ParamStoreKeyTallyingProcedure, &tallyingProcedure)
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
|
|
|
@ -118,7 +118,7 @@ type QueryDepositsParams struct {
|
|||
|
||||
// nolint: unparam
|
||||
func queryDeposits(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) {
|
||||
var params QueryDepositParams
|
||||
var params QueryDepositsParams
|
||||
err2 := keeper.cdc.UnmarshalJSON(req.Data, ¶ms)
|
||||
if err2 != nil {
|
||||
return []byte{}, sdk.ErrUnknownRequest(fmt.Sprintf("incorrectly formatted request data - %s", err2.Error()))
|
||||
|
|
|
@ -23,21 +23,23 @@ func TestGovWithRandomMessages(t *testing.T) {
|
|||
bank.RegisterCodec(mapp.Cdc)
|
||||
gov.RegisterCodec(mapp.Cdc)
|
||||
mapper := mapp.AccountMapper
|
||||
|
||||
bankKeeper := bank.NewBaseKeeper(mapper)
|
||||
stakeKey := sdk.NewKVStoreKey("stake")
|
||||
stakeTKey := sdk.NewTransientStoreKey("transient_stake")
|
||||
stakeKeeper := stake.NewKeeper(mapp.Cdc, stakeKey, stakeTKey, bankKeeper, stake.DefaultCodespace)
|
||||
paramKey := sdk.NewKVStoreKey("params")
|
||||
paramKeeper := params.NewKeeper(mapp.Cdc, paramKey)
|
||||
paramTKey := sdk.NewTransientStoreKey("transient_params")
|
||||
paramKeeper := params.NewKeeper(mapp.Cdc, paramKey, paramTKey)
|
||||
stakeKeeper := stake.NewKeeper(mapp.Cdc, stakeKey, stakeTKey, bankKeeper, paramKeeper.Subspace(stake.DefaultParamspace), stake.DefaultCodespace)
|
||||
govKey := sdk.NewKVStoreKey("gov")
|
||||
govKeeper := gov.NewKeeper(mapp.Cdc, govKey, paramKeeper.Setter(), bankKeeper, stakeKeeper, gov.DefaultCodespace)
|
||||
govKeeper := gov.NewKeeper(mapp.Cdc, govKey, paramKeeper, paramKeeper.Subspace(gov.DefaultParamspace), bankKeeper, stakeKeeper, gov.DefaultCodespace)
|
||||
mapp.Router().AddRoute("gov", gov.NewHandler(govKeeper))
|
||||
mapp.SetEndBlocker(func(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
|
||||
gov.EndBlocker(ctx, govKeeper)
|
||||
return abci.ResponseEndBlock{}
|
||||
})
|
||||
|
||||
err := mapp.CompleteSetup(stakeKey, stakeTKey, paramKey, govKey)
|
||||
err := mapp.CompleteSetup(stakeKey, stakeTKey, paramKey, paramTKey, govKey)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
|
|
@ -27,20 +27,22 @@ func getMockApp(t *testing.T, numGenAccs int) (*mock.App, Keeper, stake.Keeper,
|
|||
RegisterCodec(mapp.Cdc)
|
||||
|
||||
keyGlobalParams := sdk.NewKVStoreKey("params")
|
||||
tkeyGlobalParams := sdk.NewTransientStoreKey("transient_params")
|
||||
keyStake := sdk.NewKVStoreKey("stake")
|
||||
tkeyStake := sdk.NewTransientStoreKey("transient_stake")
|
||||
keyGov := sdk.NewKVStoreKey("gov")
|
||||
|
||||
pk := params.NewKeeper(mapp.Cdc, keyGlobalParams)
|
||||
pk := params.NewKeeper(mapp.Cdc, keyGlobalParams, tkeyGlobalParams)
|
||||
ck := bank.NewBaseKeeper(mapp.AccountMapper)
|
||||
sk := stake.NewKeeper(mapp.Cdc, keyStake, tkeyStake, ck, mapp.RegisterCodespace(stake.DefaultCodespace))
|
||||
keeper := NewKeeper(mapp.Cdc, keyGov, pk.Setter(), ck, sk, DefaultCodespace)
|
||||
sk := stake.NewKeeper(mapp.Cdc, keyStake, tkeyStake, ck, pk.Subspace(stake.DefaultParamspace), mapp.RegisterCodespace(stake.DefaultCodespace))
|
||||
keeper := NewKeeper(mapp.Cdc, keyGov, pk, pk.Subspace("testgov"), ck, sk, DefaultCodespace)
|
||||
|
||||
mapp.Router().AddRoute("gov", NewHandler(keeper))
|
||||
|
||||
mapp.SetEndBlocker(getEndBlocker(keeper))
|
||||
mapp.SetInitChainer(getInitChainer(mapp, keeper, sk))
|
||||
|
||||
require.NoError(t, mapp.CompleteSetup(keyStake, keyGov, keyGlobalParams, tkeyStake))
|
||||
require.NoError(t, mapp.CompleteSetup(keyStake, tkeyStake, keyGov, keyGlobalParams, tkeyGlobalParams))
|
||||
|
||||
genAccs, addrs, pubKeys, privKeys := mock.CreateGenAccounts(numGenAccs, sdk.Coins{sdk.NewInt64Coin("steak", 42)})
|
||||
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
package params
|
||||
|
||||
/*
|
||||
Package params provides a globally available parameter store.
|
||||
|
||||
There are two main types, Keeper and Space. Space is an isolated namespace for a
|
||||
paramstore, where keys are prefixed by preconfigured spacename. Keeper has a
|
||||
permission to access all existing spaces and create new space.
|
||||
|
||||
Space can be used by the individual keepers, who needs a private parameter store
|
||||
that the other keeper are not able to modify. Keeper can be used by the Governance
|
||||
keeper, who need to modify any parameter in case of the proposal passes.
|
||||
|
||||
Basic Usage:
|
||||
|
||||
First, declare parameter space and parameter keys for the module. Then include
|
||||
params.Store in the keeper. Since we prefix the keys with the spacename, it is
|
||||
recommended to use the same name with the module's.
|
||||
|
||||
const (
|
||||
DefaultParamspace = "mymodule"
|
||||
)
|
||||
|
||||
const (
|
||||
KeyParameter1 = "myparameter1"
|
||||
KeyParameter2 = "myparameter2"
|
||||
)
|
||||
|
||||
type Keeper struct {
|
||||
cdc *wire.Codec
|
||||
key sdk.StoreKey
|
||||
|
||||
ps params.Subspace
|
||||
}
|
||||
|
||||
Pass a params.Store to NewKeeper with DefaultParamSpace (or another)
|
||||
|
||||
app.myKeeper = mymodule.NewKeeper(app.paramStore.SubStore(mymodule.DefaultParamspace))
|
||||
|
||||
Now we can access to the paramstore using Paramstore Keys
|
||||
|
||||
k.ps.Get(KeyParameter1, ¶m)
|
||||
k.ps.Set(KeyParameter2, param)
|
||||
|
||||
Genesis Usage:
|
||||
|
||||
Declare a struct for parameters and make it implement ParamStruct. It will then
|
||||
be able to be passed to SetFromParamStruct.
|
||||
|
||||
type MyParams struct {
|
||||
Parameter1 uint64
|
||||
Parameter2 string
|
||||
}
|
||||
|
||||
func (p *MyParams) KeyFieldPairs() params.KeyFieldPairs {
|
||||
return params.KeyFieldPairs {
|
||||
{KeyParameter1, &p.Parameter1},
|
||||
{KeyParameter2, &p.Parameter2},
|
||||
}
|
||||
}
|
||||
|
||||
func InitGenesis(ctx sdk.Context, k Keeper, data GenesisState) {
|
||||
k.ps.SetFromParamStruct(ctx, &data.params)
|
||||
}
|
||||
|
||||
The method is pointer receiver because there could be a case that we read from
|
||||
the store and set the result to the struct.
|
||||
|
||||
Master Permission Usage:
|
||||
|
||||
Keepers that require master permission to the paramstore, such as gov, can take
|
||||
params.Keeper itself to access all substores(using GetSubstore)
|
||||
|
||||
type MasterKeeper struct {
|
||||
ps params.Store
|
||||
}
|
||||
|
||||
func (k MasterKeeper) SetParam(ctx sdk.Context, space string, key string, param interface{}) {
|
||||
store, ok := k.ps.GetSubstore(space)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
store.Set(ctx, key, param)
|
||||
}
|
||||
*/
|
|
@ -1,406 +1,57 @@
|
|||
package params
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/x/params/subspace"
|
||||
)
|
||||
|
||||
// Keeper manages global parameter store
|
||||
// Keeper of the global paramstore
|
||||
type Keeper struct {
|
||||
cdc *codec.Codec
|
||||
key sdk.StoreKey
|
||||
cdc *codec.Codec
|
||||
key sdk.StoreKey
|
||||
tkey sdk.StoreKey
|
||||
|
||||
spaces map[string]*Subspace
|
||||
}
|
||||
|
||||
// NewKeeper constructs a new Keeper
|
||||
func NewKeeper(cdc *codec.Codec, key sdk.StoreKey) Keeper {
|
||||
return Keeper{
|
||||
cdc: cdc,
|
||||
key: key,
|
||||
}
|
||||
}
|
||||
// NewKeeper constructs a params keeper
|
||||
func NewKeeper(cdc *codec.Codec, key *sdk.KVStoreKey, tkey *sdk.TransientStoreKey) (k Keeper) {
|
||||
k = Keeper{
|
||||
cdc: cdc,
|
||||
key: key,
|
||||
tkey: tkey,
|
||||
|
||||
// InitKeeper constructs a new Keeper with initial parameters
|
||||
// nolint: errcheck
|
||||
func InitKeeper(ctx sdk.Context, cdc *codec.Codec, key sdk.StoreKey, params ...interface{}) Keeper {
|
||||
if len(params)%2 != 0 {
|
||||
panic("Odd params list length for InitKeeper")
|
||||
}
|
||||
|
||||
k := NewKeeper(cdc, key)
|
||||
|
||||
for i := 0; i < len(params); i += 2 {
|
||||
k.set(ctx, params[i].(string), params[i+1])
|
||||
spaces: make(map[string]*Subspace),
|
||||
}
|
||||
|
||||
return k
|
||||
}
|
||||
|
||||
// get automatically unmarshalls parameter to pointer
|
||||
func (k Keeper) get(ctx sdk.Context, key string, ptr interface{}) error {
|
||||
store := ctx.KVStore(k.key)
|
||||
bz := store.Get([]byte(key))
|
||||
return k.cdc.UnmarshalBinary(bz, ptr)
|
||||
}
|
||||
|
||||
// getRaw returns raw byte slice
|
||||
func (k Keeper) getRaw(ctx sdk.Context, key string) []byte {
|
||||
store := ctx.KVStore(k.key)
|
||||
return store.Get([]byte(key))
|
||||
}
|
||||
|
||||
// set automatically marshalls and type check parameter
|
||||
func (k Keeper) set(ctx sdk.Context, key string, param interface{}) error {
|
||||
store := ctx.KVStore(k.key)
|
||||
bz := store.Get([]byte(key))
|
||||
if bz != nil {
|
||||
ptrty := reflect.PtrTo(reflect.TypeOf(param))
|
||||
ptr := reflect.New(ptrty).Interface()
|
||||
|
||||
if k.cdc.UnmarshalBinary(bz, ptr) != nil {
|
||||
return fmt.Errorf("Type mismatch with stored param and provided param")
|
||||
}
|
||||
// Allocate subspace used for keepers
|
||||
func (k Keeper) Subspace(spacename string) Subspace {
|
||||
_, ok := k.spaces[spacename]
|
||||
if ok {
|
||||
panic("subspace already occupied")
|
||||
}
|
||||
|
||||
bz, err := k.cdc.MarshalBinary(param)
|
||||
if err != nil {
|
||||
return err
|
||||
if spacename == "" {
|
||||
panic("cannot use empty string for subspace")
|
||||
}
|
||||
store.Set([]byte(key), bz)
|
||||
|
||||
return nil
|
||||
space := subspace.NewSubspace(k.cdc, k.key, k.tkey, spacename)
|
||||
|
||||
k.spaces[spacename] = &space
|
||||
|
||||
return space
|
||||
}
|
||||
|
||||
// setRaw sets raw byte slice
|
||||
func (k Keeper) setRaw(ctx sdk.Context, key string, param []byte) {
|
||||
store := ctx.KVStore(k.key)
|
||||
store.Set([]byte(key), param)
|
||||
}
|
||||
|
||||
// Getter returns readonly struct
|
||||
func (k Keeper) Getter() Getter {
|
||||
return Getter{k}
|
||||
}
|
||||
|
||||
// Setter returns read/write struct
|
||||
func (k Keeper) Setter() Setter {
|
||||
return Setter{Getter{k}}
|
||||
}
|
||||
|
||||
// Getter exposes methods related with only getting params
|
||||
type Getter struct {
|
||||
k Keeper
|
||||
}
|
||||
|
||||
// Get exposes get
|
||||
func (k Getter) Get(ctx sdk.Context, key string, ptr interface{}) error {
|
||||
return k.k.get(ctx, key, ptr)
|
||||
}
|
||||
|
||||
// GetRaw exposes getRaw
|
||||
func (k Getter) GetRaw(ctx sdk.Context, key string) []byte {
|
||||
return k.k.getRaw(ctx, key)
|
||||
}
|
||||
|
||||
// GetString is helper function for string params
|
||||
func (k Getter) GetString(ctx sdk.Context, key string) (res string, err error) {
|
||||
store := ctx.KVStore(k.k.key)
|
||||
bz := store.Get([]byte(key))
|
||||
err = k.k.cdc.UnmarshalBinary(bz, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// GetBool is helper function for bool params
|
||||
func (k Getter) GetBool(ctx sdk.Context, key string) (res bool, err error) {
|
||||
store := ctx.KVStore(k.k.key)
|
||||
bz := store.Get([]byte(key))
|
||||
err = k.k.cdc.UnmarshalBinary(bz, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// GetInt16 is helper function for int16 params
|
||||
func (k Getter) GetInt16(ctx sdk.Context, key string) (res int16, err error) {
|
||||
store := ctx.KVStore(k.k.key)
|
||||
bz := store.Get([]byte(key))
|
||||
err = k.k.cdc.UnmarshalBinary(bz, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// GetInt32 is helper function for int32 params
|
||||
func (k Getter) GetInt32(ctx sdk.Context, key string) (res int32, err error) {
|
||||
store := ctx.KVStore(k.k.key)
|
||||
bz := store.Get([]byte(key))
|
||||
err = k.k.cdc.UnmarshalBinary(bz, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// GetInt64 is helper function for int64 params
|
||||
func (k Getter) GetInt64(ctx sdk.Context, key string) (res int64, err error) {
|
||||
store := ctx.KVStore(k.k.key)
|
||||
bz := store.Get([]byte(key))
|
||||
err = k.k.cdc.UnmarshalBinary(bz, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// GetUint16 is helper function for uint16 params
|
||||
func (k Getter) GetUint16(ctx sdk.Context, key string) (res uint16, err error) {
|
||||
store := ctx.KVStore(k.k.key)
|
||||
bz := store.Get([]byte(key))
|
||||
err = k.k.cdc.UnmarshalBinary(bz, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// GetUint32 is helper function for uint32 params
|
||||
func (k Getter) GetUint32(ctx sdk.Context, key string) (res uint32, err error) {
|
||||
store := ctx.KVStore(k.k.key)
|
||||
bz := store.Get([]byte(key))
|
||||
err = k.k.cdc.UnmarshalBinary(bz, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// GetUint64 is helper function for uint64 params
|
||||
func (k Getter) GetUint64(ctx sdk.Context, key string) (res uint64, err error) {
|
||||
store := ctx.KVStore(k.k.key)
|
||||
bz := store.Get([]byte(key))
|
||||
err = k.k.cdc.UnmarshalBinary(bz, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// GetInt is helper function for sdk.Int params
|
||||
func (k Getter) GetInt(ctx sdk.Context, key string) (res sdk.Int, err error) {
|
||||
store := ctx.KVStore(k.k.key)
|
||||
bz := store.Get([]byte(key))
|
||||
err = k.k.cdc.UnmarshalBinary(bz, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// GetUint is helper function for sdk.Uint params
|
||||
func (k Getter) GetUint(ctx sdk.Context, key string) (res sdk.Uint, err error) {
|
||||
store := ctx.KVStore(k.k.key)
|
||||
bz := store.Get([]byte(key))
|
||||
err = k.k.cdc.UnmarshalBinary(bz, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// GetDec is helper function for decimal params
|
||||
func (k Getter) GetDec(ctx sdk.Context, key string) (res sdk.Dec, err error) {
|
||||
store := ctx.KVStore(k.k.key)
|
||||
bz := store.Get([]byte(key))
|
||||
err = k.k.cdc.UnmarshalBinary(bz, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// GetStringWithDefault is helper function for string params with default value
|
||||
func (k Getter) GetStringWithDefault(ctx sdk.Context, key string, def string) (res string) {
|
||||
store := ctx.KVStore(k.k.key)
|
||||
bz := store.Get([]byte(key))
|
||||
if bz == nil {
|
||||
return def
|
||||
}
|
||||
k.k.cdc.MustUnmarshalBinary(bz, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// GetBoolWithDefault is helper function for bool params with default value
|
||||
func (k Getter) GetBoolWithDefault(ctx sdk.Context, key string, def bool) (res bool) {
|
||||
store := ctx.KVStore(k.k.key)
|
||||
bz := store.Get([]byte(key))
|
||||
if bz == nil {
|
||||
return def
|
||||
}
|
||||
k.k.cdc.MustUnmarshalBinary(bz, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// GetInt16WithDefault is helper function for int16 params with default value
|
||||
func (k Getter) GetInt16WithDefault(ctx sdk.Context, key string, def int16) (res int16) {
|
||||
store := ctx.KVStore(k.k.key)
|
||||
bz := store.Get([]byte(key))
|
||||
if bz == nil {
|
||||
return def
|
||||
}
|
||||
k.k.cdc.MustUnmarshalBinary(bz, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// GetInt32WithDefault is helper function for int32 params with default value
|
||||
func (k Getter) GetInt32WithDefault(ctx sdk.Context, key string, def int32) (res int32) {
|
||||
store := ctx.KVStore(k.k.key)
|
||||
bz := store.Get([]byte(key))
|
||||
if bz == nil {
|
||||
return def
|
||||
}
|
||||
k.k.cdc.MustUnmarshalBinary(bz, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// GetInt64WithDefault is helper function for int64 params with default value
|
||||
func (k Getter) GetInt64WithDefault(ctx sdk.Context, key string, def int64) (res int64) {
|
||||
store := ctx.KVStore(k.k.key)
|
||||
bz := store.Get([]byte(key))
|
||||
if bz == nil {
|
||||
return def
|
||||
}
|
||||
k.k.cdc.MustUnmarshalBinary(bz, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// GetUint16WithDefault is helper function for uint16 params with default value
|
||||
func (k Getter) GetUint16WithDefault(ctx sdk.Context, key string, def uint16) (res uint16) {
|
||||
store := ctx.KVStore(k.k.key)
|
||||
bz := store.Get([]byte(key))
|
||||
if bz == nil {
|
||||
return def
|
||||
}
|
||||
k.k.cdc.MustUnmarshalBinary(bz, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// GetUint32WithDefault is helper function for uint32 params with default value
|
||||
func (k Getter) GetUint32WithDefault(ctx sdk.Context, key string, def uint32) (res uint32) {
|
||||
store := ctx.KVStore(k.k.key)
|
||||
bz := store.Get([]byte(key))
|
||||
if bz == nil {
|
||||
return def
|
||||
}
|
||||
k.k.cdc.MustUnmarshalBinary(bz, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// GetUint64WithDefault is helper function for uint64 params with default value
|
||||
func (k Getter) GetUint64WithDefault(ctx sdk.Context, key string, def uint64) (res uint64) {
|
||||
store := ctx.KVStore(k.k.key)
|
||||
bz := store.Get([]byte(key))
|
||||
if bz == nil {
|
||||
return def
|
||||
}
|
||||
k.k.cdc.MustUnmarshalBinary(bz, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// GetIntWithDefault is helper function for sdk.Int params with default value
|
||||
func (k Getter) GetIntWithDefault(ctx sdk.Context, key string, def sdk.Int) (res sdk.Int) {
|
||||
store := ctx.KVStore(k.k.key)
|
||||
bz := store.Get([]byte(key))
|
||||
if bz == nil {
|
||||
return def
|
||||
}
|
||||
k.k.cdc.MustUnmarshalBinary(bz, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// GetUintWithDefault is helper function for sdk.Uint params with default value
|
||||
func (k Getter) GetUintWithDefault(ctx sdk.Context, key string, def sdk.Uint) (res sdk.Uint) {
|
||||
store := ctx.KVStore(k.k.key)
|
||||
bz := store.Get([]byte(key))
|
||||
if bz == nil {
|
||||
return def
|
||||
}
|
||||
k.k.cdc.MustUnmarshalBinary(bz, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// GetDecWithDefault is helper function for sdk.Dec params with default value
|
||||
func (k Getter) GetDecWithDefault(ctx sdk.Context, key string, def sdk.Dec) (res sdk.Dec) {
|
||||
store := ctx.KVStore(k.k.key)
|
||||
bz := store.Get([]byte(key))
|
||||
if bz == nil {
|
||||
return def
|
||||
}
|
||||
k.k.cdc.MustUnmarshalBinary(bz, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// Setter exposes all methods including Set
|
||||
type Setter struct {
|
||||
Getter
|
||||
}
|
||||
|
||||
// Set exposes set
|
||||
func (k Setter) Set(ctx sdk.Context, key string, param interface{}) error {
|
||||
return k.k.set(ctx, key, param)
|
||||
}
|
||||
|
||||
// SetRaw exposes setRaw
|
||||
func (k Setter) SetRaw(ctx sdk.Context, key string, param []byte) {
|
||||
k.k.setRaw(ctx, key, param)
|
||||
}
|
||||
|
||||
// SetString is helper function for string params
|
||||
func (k Setter) SetString(ctx sdk.Context, key string, param string) {
|
||||
if err := k.k.set(ctx, key, param); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// SetBool is helper function for bool params
|
||||
func (k Setter) SetBool(ctx sdk.Context, key string, param bool) {
|
||||
if err := k.k.set(ctx, key, param); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// SetInt16 is helper function for int16 params
|
||||
func (k Setter) SetInt16(ctx sdk.Context, key string, param int16) {
|
||||
if err := k.k.set(ctx, key, param); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// SetInt32 is helper function for int32 params
|
||||
func (k Setter) SetInt32(ctx sdk.Context, key string, param int32) {
|
||||
if err := k.k.set(ctx, key, param); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// SetInt64 is helper function for int64 params
|
||||
func (k Setter) SetInt64(ctx sdk.Context, key string, param int64) {
|
||||
if err := k.k.set(ctx, key, param); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// SetUint16 is helper function for uint16 params
|
||||
func (k Setter) SetUint16(ctx sdk.Context, key string, param uint16) {
|
||||
if err := k.k.set(ctx, key, param); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// SetUint32 is helper function for uint32 params
|
||||
func (k Setter) SetUint32(ctx sdk.Context, key string, param uint32) {
|
||||
if err := k.k.set(ctx, key, param); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// SetUint64 is helper function for uint64 params
|
||||
func (k Setter) SetUint64(ctx sdk.Context, key string, param uint64) {
|
||||
if err := k.k.set(ctx, key, param); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// SetInt is helper function for sdk.Int params
|
||||
func (k Setter) SetInt(ctx sdk.Context, key string, param sdk.Int) {
|
||||
if err := k.k.set(ctx, key, param); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// SetUint is helper function for sdk.Uint params
|
||||
func (k Setter) SetUint(ctx sdk.Context, key string, param sdk.Uint) {
|
||||
if err := k.k.set(ctx, key, param); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// SetDec is helper function for decimal params
|
||||
func (k Setter) SetDec(ctx sdk.Context, key string, param sdk.Dec) {
|
||||
if err := k.k.set(ctx, key, param); err != nil {
|
||||
panic(err)
|
||||
// Get existing substore from keeper
|
||||
func (k Keeper) GetSubspace(storename string) (Subspace, bool) {
|
||||
space, ok := k.spaces[storename]
|
||||
if !ok {
|
||||
return Subspace{}, false
|
||||
}
|
||||
return *space, ok
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package params
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
dbm "github.com/tendermint/tendermint/libs/db"
|
||||
|
@ -14,15 +15,30 @@ import (
|
|||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
func defaultContext(key sdk.StoreKey) sdk.Context {
|
||||
func defaultContext(key sdk.StoreKey, tkey sdk.StoreKey) sdk.Context {
|
||||
db := dbm.NewMemDB()
|
||||
cms := store.NewCommitMultiStore(db)
|
||||
cms.MountStoreWithDB(key, sdk.StoreTypeIAVL, db)
|
||||
cms.MountStoreWithDB(tkey, sdk.StoreTypeTransient, db)
|
||||
cms.LoadLatestVersion()
|
||||
ctx := sdk.NewContext(cms, abci.Header{}, false, log.NewNopLogger())
|
||||
return ctx
|
||||
}
|
||||
|
||||
type invalid struct{}
|
||||
|
||||
type s struct {
|
||||
I int
|
||||
}
|
||||
|
||||
func createTestCodec() *codec.Codec {
|
||||
cdc := codec.New()
|
||||
sdk.RegisterCodec(cdc)
|
||||
cdc.RegisterConcrete(s{}, "test/s", nil)
|
||||
cdc.RegisterConcrete(invalid{}, "test/invalid", nil)
|
||||
return cdc
|
||||
}
|
||||
|
||||
func TestKeeper(t *testing.T) {
|
||||
kvs := []struct {
|
||||
key string
|
||||
|
@ -33,248 +49,120 @@ func TestKeeper(t *testing.T) {
|
|||
{"key3", 182},
|
||||
{"key4", 17582},
|
||||
{"key5", 2768554},
|
||||
{"key6", 1157279},
|
||||
{"key7", 9058701},
|
||||
}
|
||||
|
||||
table := NewTypeTable(
|
||||
[]byte("key1"), int64(0),
|
||||
[]byte("key2"), int64(0),
|
||||
[]byte("key3"), int64(0),
|
||||
[]byte("key4"), int64(0),
|
||||
[]byte("key5"), int64(0),
|
||||
[]byte("key6"), int64(0),
|
||||
[]byte("key7"), int64(0),
|
||||
[]byte("extra1"), bool(false),
|
||||
[]byte("extra2"), string(""),
|
||||
)
|
||||
|
||||
skey := sdk.NewKVStoreKey("test")
|
||||
ctx := defaultContext(skey)
|
||||
setter := NewKeeper(codec.New(), skey).Setter()
|
||||
tkey := sdk.NewTransientStoreKey("transient_test")
|
||||
ctx := defaultContext(skey, tkey)
|
||||
store := NewKeeper(codec.New(), skey, tkey).Subspace("test").WithTypeTable(table)
|
||||
|
||||
for _, kv := range kvs {
|
||||
err := setter.Set(ctx, kv.key, kv.param)
|
||||
assert.Nil(t, err)
|
||||
for i, kv := range kvs {
|
||||
require.NotPanics(t, func() { store.Set(ctx, []byte(kv.key), kv.param) }, "store.Set panics, tc #%d", i)
|
||||
}
|
||||
|
||||
for _, kv := range kvs {
|
||||
for i, kv := range kvs {
|
||||
var param int64
|
||||
err := setter.Get(ctx, kv.key, ¶m)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, kv.param, param)
|
||||
require.NotPanics(t, func() { store.Get(ctx, []byte(kv.key), ¶m) }, "store.Get panics, tc #%d", i)
|
||||
require.Equal(t, kv.param, param, "stored param not equal, tc #%d", i)
|
||||
}
|
||||
|
||||
cdc := codec.New()
|
||||
for _, kv := range kvs {
|
||||
for i, kv := range kvs {
|
||||
var param int64
|
||||
bz := setter.GetRaw(ctx, kv.key)
|
||||
err := cdc.UnmarshalBinary(bz, ¶m)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, kv.param, param)
|
||||
bz := store.GetRaw(ctx, []byte(kv.key))
|
||||
err := cdc.UnmarshalJSON(bz, ¶m)
|
||||
require.Nil(t, err, "err is not nil, tc #%d", i)
|
||||
require.Equal(t, kv.param, param, "stored param not equal, tc #%d", i)
|
||||
}
|
||||
|
||||
for _, kv := range kvs {
|
||||
for i, kv := range kvs {
|
||||
var param bool
|
||||
err := setter.Get(ctx, kv.key, ¶m)
|
||||
assert.NotNil(t, err)
|
||||
require.Panics(t, func() { store.Get(ctx, []byte(kv.key), ¶m) }, "invalid store.Get not panics, tc #%d", i)
|
||||
}
|
||||
|
||||
for _, kv := range kvs {
|
||||
err := setter.Set(ctx, kv.key, true)
|
||||
assert.NotNil(t, err)
|
||||
for i, kv := range kvs {
|
||||
require.Panics(t, func() { store.Set(ctx, []byte(kv.key), true) }, "invalid store.Set not panics, tc #%d", i)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetter(t *testing.T) {
|
||||
func TestGet(t *testing.T) {
|
||||
key := sdk.NewKVStoreKey("test")
|
||||
ctx := defaultContext(key)
|
||||
keeper := NewKeeper(codec.New(), key)
|
||||
|
||||
g := keeper.Getter()
|
||||
s := keeper.Setter()
|
||||
tkey := sdk.NewTransientStoreKey("transient_test")
|
||||
ctx := defaultContext(key, tkey)
|
||||
keeper := NewKeeper(createTestCodec(), key, tkey)
|
||||
|
||||
kvs := []struct {
|
||||
key string
|
||||
param interface{}
|
||||
zero interface{}
|
||||
ptr interface{}
|
||||
}{
|
||||
{"string", "test"},
|
||||
{"bool", true},
|
||||
{"int16", int16(1)},
|
||||
{"int32", int32(1)},
|
||||
{"int64", int64(1)},
|
||||
{"uint16", uint16(1)},
|
||||
{"uint32", uint32(1)},
|
||||
{"uint64", uint64(1)},
|
||||
{"int", sdk.NewInt(1)},
|
||||
{"uint", sdk.NewUint(1)},
|
||||
{"rat", sdk.NewDec(1)},
|
||||
{"string", "test", "", new(string)},
|
||||
{"bool", true, false, new(bool)},
|
||||
{"int16", int16(1), int16(0), new(int16)},
|
||||
{"int32", int32(1), int32(0), new(int32)},
|
||||
{"int64", int64(1), int64(0), new(int64)},
|
||||
{"uint16", uint16(1), uint16(0), new(uint16)},
|
||||
{"uint32", uint32(1), uint32(0), new(uint32)},
|
||||
{"uint64", uint64(1), uint64(0), new(uint64)},
|
||||
{"int", sdk.NewInt(1), *new(sdk.Int), new(sdk.Int)},
|
||||
{"uint", sdk.NewUint(1), *new(sdk.Uint), new(sdk.Uint)},
|
||||
{"dec", sdk.NewDec(1), *new(sdk.Dec), new(sdk.Dec)},
|
||||
{"struct", s{1}, s{0}, new(s)},
|
||||
}
|
||||
|
||||
assert.NotPanics(t, func() { s.SetString(ctx, kvs[0].key, "test") })
|
||||
assert.NotPanics(t, func() { s.SetBool(ctx, kvs[1].key, true) })
|
||||
assert.NotPanics(t, func() { s.SetInt16(ctx, kvs[2].key, int16(1)) })
|
||||
assert.NotPanics(t, func() { s.SetInt32(ctx, kvs[3].key, int32(1)) })
|
||||
assert.NotPanics(t, func() { s.SetInt64(ctx, kvs[4].key, int64(1)) })
|
||||
assert.NotPanics(t, func() { s.SetUint16(ctx, kvs[5].key, uint16(1)) })
|
||||
assert.NotPanics(t, func() { s.SetUint32(ctx, kvs[6].key, uint32(1)) })
|
||||
assert.NotPanics(t, func() { s.SetUint64(ctx, kvs[7].key, uint64(1)) })
|
||||
assert.NotPanics(t, func() { s.SetInt(ctx, kvs[8].key, sdk.NewInt(1)) })
|
||||
assert.NotPanics(t, func() { s.SetUint(ctx, kvs[9].key, sdk.NewUint(1)) })
|
||||
assert.NotPanics(t, func() { s.SetDec(ctx, kvs[10].key, sdk.NewDec(1)) })
|
||||
table := NewTypeTable(
|
||||
[]byte("string"), string(""),
|
||||
[]byte("bool"), bool(false),
|
||||
[]byte("int16"), int16(0),
|
||||
[]byte("int32"), int32(0),
|
||||
[]byte("int64"), int64(0),
|
||||
[]byte("uint16"), uint16(0),
|
||||
[]byte("uint32"), uint32(0),
|
||||
[]byte("uint64"), uint64(0),
|
||||
[]byte("int"), sdk.Int{},
|
||||
[]byte("uint"), sdk.Uint{},
|
||||
[]byte("dec"), sdk.Dec{},
|
||||
[]byte("struct"), s{},
|
||||
)
|
||||
|
||||
var res interface{}
|
||||
var err error
|
||||
store := keeper.Subspace("test").WithTypeTable(table)
|
||||
|
||||
// String
|
||||
def0 := "default"
|
||||
res, err = g.GetString(ctx, kvs[0].key)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, kvs[0].param, res)
|
||||
for i, kv := range kvs {
|
||||
require.False(t, store.Modified(ctx, []byte(kv.key)), "store.Modified returns true before setting, tc #%d", i)
|
||||
require.NotPanics(t, func() { store.Set(ctx, []byte(kv.key), kv.param) }, "store.Set panics, tc #%d", i)
|
||||
require.True(t, store.Modified(ctx, []byte(kv.key)), "store.Modified returns false after setting, tc #%d", i)
|
||||
}
|
||||
|
||||
_, err = g.GetString(ctx, "invalid")
|
||||
assert.NotNil(t, err)
|
||||
for i, kv := range kvs {
|
||||
require.NotPanics(t, func() { store.GetIfExists(ctx, []byte("invalid"), kv.ptr) }, "store.GetIfExists panics when no value exists, tc #%d", i)
|
||||
require.Equal(t, kv.zero, reflect.ValueOf(kv.ptr).Elem().Interface(), "store.GetIfExists unmarshalls when no value exists, tc #%d", i)
|
||||
require.Panics(t, func() { store.Get(ctx, []byte("invalid"), kv.ptr) }, "invalid store.Get not panics when no value exists, tc #%d", i)
|
||||
require.Equal(t, kv.zero, reflect.ValueOf(kv.ptr).Elem().Interface(), "invalid store.Get unmarshalls when no value exists, tc #%d", i)
|
||||
|
||||
res = g.GetStringWithDefault(ctx, kvs[0].key, def0)
|
||||
assert.Equal(t, kvs[0].param, res)
|
||||
require.NotPanics(t, func() { store.GetIfExists(ctx, []byte(kv.key), kv.ptr) }, "store.GetIfExists panics, tc #%d", i)
|
||||
require.Equal(t, kv.param, reflect.ValueOf(kv.ptr).Elem().Interface(), "stored param not equal, tc #%d", i)
|
||||
require.NotPanics(t, func() { store.Get(ctx, []byte(kv.key), kv.ptr) }, "store.Get panics, tc #%d", i)
|
||||
require.Equal(t, kv.param, reflect.ValueOf(kv.ptr).Elem().Interface(), "stored param not equal, tc #%d", i)
|
||||
|
||||
res = g.GetStringWithDefault(ctx, "invalid", def0)
|
||||
assert.Equal(t, def0, res)
|
||||
|
||||
// Bool
|
||||
def1 := false
|
||||
res, err = g.GetBool(ctx, kvs[1].key)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, kvs[1].param, res)
|
||||
|
||||
_, err = g.GetBool(ctx, "invalid")
|
||||
assert.NotNil(t, err)
|
||||
|
||||
res = g.GetBoolWithDefault(ctx, kvs[1].key, def1)
|
||||
assert.Equal(t, kvs[1].param, res)
|
||||
|
||||
res = g.GetBoolWithDefault(ctx, "invalid", def1)
|
||||
assert.Equal(t, def1, res)
|
||||
|
||||
// Int16
|
||||
def2 := int16(0)
|
||||
res, err = g.GetInt16(ctx, kvs[2].key)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, kvs[2].param, res)
|
||||
|
||||
_, err = g.GetInt16(ctx, "invalid")
|
||||
assert.NotNil(t, err)
|
||||
|
||||
res = g.GetInt16WithDefault(ctx, kvs[2].key, def2)
|
||||
assert.Equal(t, kvs[2].param, res)
|
||||
|
||||
res = g.GetInt16WithDefault(ctx, "invalid", def2)
|
||||
assert.Equal(t, def2, res)
|
||||
|
||||
// Int32
|
||||
def3 := int32(0)
|
||||
res, err = g.GetInt32(ctx, kvs[3].key)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, kvs[3].param, res)
|
||||
|
||||
_, err = g.GetInt32(ctx, "invalid")
|
||||
assert.NotNil(t, err)
|
||||
|
||||
res = g.GetInt32WithDefault(ctx, kvs[3].key, def3)
|
||||
assert.Equal(t, kvs[3].param, res)
|
||||
|
||||
res = g.GetInt32WithDefault(ctx, "invalid", def3)
|
||||
assert.Equal(t, def3, res)
|
||||
|
||||
// Int64
|
||||
def4 := int64(0)
|
||||
res, err = g.GetInt64(ctx, kvs[4].key)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, kvs[4].param, res)
|
||||
|
||||
_, err = g.GetInt64(ctx, "invalid")
|
||||
assert.NotNil(t, err)
|
||||
|
||||
res = g.GetInt64WithDefault(ctx, kvs[4].key, def4)
|
||||
assert.Equal(t, kvs[4].param, res)
|
||||
|
||||
res = g.GetInt64WithDefault(ctx, "invalid", def4)
|
||||
assert.Equal(t, def4, res)
|
||||
|
||||
// Uint16
|
||||
def5 := uint16(0)
|
||||
res, err = g.GetUint16(ctx, kvs[5].key)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, kvs[5].param, res)
|
||||
|
||||
_, err = g.GetUint16(ctx, "invalid")
|
||||
assert.NotNil(t, err)
|
||||
|
||||
res = g.GetUint16WithDefault(ctx, kvs[5].key, def5)
|
||||
assert.Equal(t, kvs[5].param, res)
|
||||
|
||||
res = g.GetUint16WithDefault(ctx, "invalid", def5)
|
||||
assert.Equal(t, def5, res)
|
||||
|
||||
// Uint32
|
||||
def6 := uint32(0)
|
||||
res, err = g.GetUint32(ctx, kvs[6].key)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, kvs[6].param, res)
|
||||
|
||||
_, err = g.GetUint32(ctx, "invalid")
|
||||
assert.NotNil(t, err)
|
||||
|
||||
res = g.GetUint32WithDefault(ctx, kvs[6].key, def6)
|
||||
assert.Equal(t, kvs[6].param, res)
|
||||
|
||||
res = g.GetUint32WithDefault(ctx, "invalid", def6)
|
||||
assert.Equal(t, def6, res)
|
||||
|
||||
// Uint64
|
||||
def7 := uint64(0)
|
||||
res, err = g.GetUint64(ctx, kvs[7].key)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, kvs[7].param, res)
|
||||
|
||||
_, err = g.GetUint64(ctx, "invalid")
|
||||
assert.NotNil(t, err)
|
||||
|
||||
res = g.GetUint64WithDefault(ctx, kvs[7].key, def7)
|
||||
assert.Equal(t, kvs[7].param, res)
|
||||
|
||||
res = g.GetUint64WithDefault(ctx, "invalid", def7)
|
||||
assert.Equal(t, def7, res)
|
||||
|
||||
// Int
|
||||
def8 := sdk.NewInt(0)
|
||||
res, err = g.GetInt(ctx, kvs[8].key)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, kvs[8].param, res)
|
||||
|
||||
_, err = g.GetInt(ctx, "invalid")
|
||||
assert.NotNil(t, err)
|
||||
|
||||
res = g.GetIntWithDefault(ctx, kvs[8].key, def8)
|
||||
assert.Equal(t, kvs[8].param, res)
|
||||
|
||||
res = g.GetIntWithDefault(ctx, "invalid", def8)
|
||||
assert.Equal(t, def8, res)
|
||||
|
||||
// Uint
|
||||
def9 := sdk.NewUint(0)
|
||||
res, err = g.GetUint(ctx, kvs[9].key)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, kvs[9].param, res)
|
||||
|
||||
_, err = g.GetUint(ctx, "invalid")
|
||||
assert.NotNil(t, err)
|
||||
|
||||
res = g.GetUintWithDefault(ctx, kvs[9].key, def9)
|
||||
assert.Equal(t, kvs[9].param, res)
|
||||
|
||||
res = g.GetUintWithDefault(ctx, "invalid", def9)
|
||||
assert.Equal(t, def9, res)
|
||||
|
||||
// Rat
|
||||
def10 := sdk.NewDec(0)
|
||||
res, err = g.GetDec(ctx, kvs[10].key)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, kvs[10].param, res)
|
||||
|
||||
_, err = g.GetDec(ctx, "invalid")
|
||||
assert.NotNil(t, err)
|
||||
|
||||
res = g.GetDecWithDefault(ctx, kvs[10].key, def10)
|
||||
assert.Equal(t, kvs[10].param, res)
|
||||
|
||||
res = g.GetDecWithDefault(ctx, "invalid", def10)
|
||||
assert.Equal(t, def10, res)
|
||||
require.Panics(t, func() { store.Get(ctx, []byte("invalid"), kv.ptr) }, "invalid store.Get not panics when no value exists, tc #%d", i)
|
||||
require.Equal(t, kv.param, reflect.ValueOf(kv.ptr).Elem().Interface(), "invalid store.Get unmarshalls when no value existt, tc #%d", i)
|
||||
|
||||
require.Panics(t, func() { store.Get(ctx, []byte(kv.key), nil) }, "invalid store.Get not panics when the pointer is nil, tc #%d", i)
|
||||
require.Panics(t, func() { store.Get(ctx, []byte(kv.key), new(invalid)) }, "invalid store.Get not panics when the pointer is different type, tc #%d", i)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
package params
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// GenesisState defines initial activated msg types
|
||||
type GenesisState struct {
|
||||
ActivatedTypes []string `json:"activated-types"`
|
||||
}
|
||||
|
||||
// ActivatedParamKey - paramstore key for msg type activation
|
||||
func ActivatedParamKey(ty string) string {
|
||||
return "Activated/" + ty
|
||||
}
|
||||
|
||||
// InitGenesis stores activated type to param store
|
||||
// nolint: errcheck
|
||||
func InitGenesis(ctx sdk.Context, k Keeper, data GenesisState) {
|
||||
for _, ty := range data.ActivatedTypes {
|
||||
k.set(ctx, ActivatedParamKey(ty), true)
|
||||
}
|
||||
}
|
||||
|
||||
// NewAnteHandler returns an AnteHandler that checks
|
||||
// whether msg type is activate or not
|
||||
func NewAnteHandler(k Keeper) sdk.AnteHandler {
|
||||
return func(ctx sdk.Context, tx sdk.Tx, simulate bool) (sdk.Context, sdk.Result, bool) {
|
||||
for _, msg := range tx.GetMsgs() {
|
||||
ok := k.Getter().GetBoolWithDefault(ctx, ActivatedParamKey(msg.Type()), false)
|
||||
if !ok {
|
||||
return ctx, sdk.ErrUnauthorized("deactivated msg type").Result(), true
|
||||
}
|
||||
}
|
||||
return ctx, sdk.Result{}, false
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package params
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/x/params/subspace"
|
||||
)
|
||||
|
||||
// re-export types from subspace
|
||||
type (
|
||||
Subspace = subspace.Subspace
|
||||
ReadOnlySubspace = subspace.ReadOnlySubspace
|
||||
ParamSet = subspace.ParamSet
|
||||
KeyValuePairs = subspace.KeyValuePairs
|
||||
TypeTable = subspace.TypeTable
|
||||
)
|
||||
|
||||
// re-export functions from subspace
|
||||
func NewTypeTable(keytypes ...interface{}) TypeTable {
|
||||
return subspace.NewTypeTable(keytypes...)
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package subspace
|
||||
|
||||
/*
|
||||
To prevent namespace collision between consumer modules, we define type
|
||||
"space". A Space can only be generated by the keeper, and the keeper checks
|
||||
the existence of the space having the same name before generating the
|
||||
space.
|
||||
|
||||
Consumer modules must take a space (via Keeper.Subspace), not the keeper
|
||||
itself. This isolates each modules from the others and make them modify the
|
||||
parameters safely. Keeper can be treated as master permission for all
|
||||
subspaces (via Keeper.GetSubspace), so should be passed to proper modules
|
||||
(ex. gov)
|
||||
*/
|
|
@ -0,0 +1,15 @@
|
|||
package subspace
|
||||
|
||||
// Used for associating paramsubspace key and field of param structs
|
||||
type KeyValuePair struct {
|
||||
Key []byte
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
// Slice of KeyFieldPair
|
||||
type KeyValuePairs []KeyValuePair
|
||||
|
||||
// Interface for structs containing parameters for a module
|
||||
type ParamSet interface {
|
||||
KeyValuePairs() KeyValuePairs
|
||||
}
|
|
@ -0,0 +1,198 @@
|
|||
package subspace
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// Additional capicity to be allocated for Subspace.name
|
||||
// So we don't have to allocate extra space each time appending to the key
|
||||
const extraKeyCap = 20
|
||||
|
||||
// Individual parameter store for each keeper
|
||||
// Transient store persists for a block, so we use it for
|
||||
// recording whether the parameter has been changed or not
|
||||
type Subspace struct {
|
||||
cdc *codec.Codec
|
||||
key sdk.StoreKey // []byte -> []byte, stores parameter
|
||||
tkey sdk.StoreKey // []byte -> bool, stores parameter change
|
||||
|
||||
name []byte
|
||||
|
||||
table TypeTable
|
||||
}
|
||||
|
||||
// NewSubspace constructs a store with namestore
|
||||
func NewSubspace(cdc *codec.Codec, key sdk.StoreKey, tkey sdk.StoreKey, name string) (res Subspace) {
|
||||
res = Subspace{
|
||||
cdc: cdc,
|
||||
key: key,
|
||||
tkey: tkey,
|
||||
}
|
||||
|
||||
namebz := []byte(name)
|
||||
res.name = make([]byte, len(namebz), len(namebz)+extraKeyCap)
|
||||
copy(res.name, namebz)
|
||||
return
|
||||
}
|
||||
|
||||
// WithTypeTable initializes TypeTable and returns modified Subspace
|
||||
func (s Subspace) WithTypeTable(table TypeTable) (res Subspace) {
|
||||
if table == nil {
|
||||
panic("SetTypeTable() called with nil TypeTable")
|
||||
}
|
||||
if s.table != nil {
|
||||
panic("SetTypeTable() called on initialized Subspace")
|
||||
}
|
||||
|
||||
res = Subspace{
|
||||
cdc: s.cdc,
|
||||
key: s.key,
|
||||
tkey: s.tkey,
|
||||
name: s.name,
|
||||
table: table,
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Returns a KVStore identical with ctx.KVStore(s.key).Prefix()
|
||||
func (s Subspace) kvStore(ctx sdk.Context) sdk.KVStore {
|
||||
// append here is safe, appends within a function won't cause
|
||||
// weird side effects when its singlethreaded
|
||||
return ctx.KVStore(s.key).Prefix(append(s.name, '/'))
|
||||
}
|
||||
|
||||
// Returns a KVStore identical with ctx.TransientStore(s.tkey).Prefix()
|
||||
func (s Subspace) transientStore(ctx sdk.Context) sdk.KVStore {
|
||||
// append here is safe, appends within a function won't cause
|
||||
// weird side effects when its singlethreaded
|
||||
return ctx.TransientStore(s.tkey).Prefix(append(s.name, '/'))
|
||||
}
|
||||
|
||||
// Get parameter from store
|
||||
func (s Subspace) Get(ctx sdk.Context, key []byte, ptr interface{}) {
|
||||
store := s.kvStore(ctx)
|
||||
bz := store.Get(key)
|
||||
err := s.cdc.UnmarshalJSON(bz, ptr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// GetIfExists do not modify ptr if the stored parameter is nil
|
||||
func (s Subspace) GetIfExists(ctx sdk.Context, key []byte, ptr interface{}) {
|
||||
store := s.kvStore(ctx)
|
||||
bz := store.Get(key)
|
||||
if bz == nil {
|
||||
return
|
||||
}
|
||||
err := s.cdc.UnmarshalJSON(bz, ptr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Get raw bytes of parameter from store
|
||||
func (s Subspace) GetRaw(ctx sdk.Context, key []byte) []byte {
|
||||
store := s.kvStore(ctx)
|
||||
return store.Get(key)
|
||||
}
|
||||
|
||||
// Check if the parameter is set in the store
|
||||
func (s Subspace) Has(ctx sdk.Context, key []byte) bool {
|
||||
store := s.kvStore(ctx)
|
||||
return store.Has(key)
|
||||
}
|
||||
|
||||
// Returns true if the parameter is set in the block
|
||||
func (s Subspace) Modified(ctx sdk.Context, key []byte) bool {
|
||||
tstore := s.transientStore(ctx)
|
||||
return tstore.Has(key)
|
||||
}
|
||||
|
||||
// Set parameter, return error if stored parameter has different type from input
|
||||
// Also set to the transient store to record change
|
||||
func (s Subspace) Set(ctx sdk.Context, key []byte, param interface{}) {
|
||||
store := s.kvStore(ctx)
|
||||
|
||||
ty, ok := s.table[string(key)]
|
||||
if !ok {
|
||||
panic("Parameter not registered")
|
||||
}
|
||||
|
||||
pty := reflect.TypeOf(param)
|
||||
if pty.Kind() == reflect.Ptr {
|
||||
pty = pty.Elem()
|
||||
}
|
||||
|
||||
if pty != ty {
|
||||
panic("Type mismatch with registered table")
|
||||
}
|
||||
|
||||
bz, err := s.cdc.MarshalJSON(param)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
store.Set(key, bz)
|
||||
|
||||
tstore := s.transientStore(ctx)
|
||||
tstore.Set(key, []byte{})
|
||||
|
||||
}
|
||||
|
||||
// Get to ParamSet
|
||||
func (s Subspace) GetParamSet(ctx sdk.Context, ps ParamSet) {
|
||||
for _, pair := range ps.KeyValuePairs() {
|
||||
s.Get(ctx, pair.Key, pair.Value)
|
||||
}
|
||||
}
|
||||
|
||||
// Set from ParamSet
|
||||
func (s Subspace) SetParamSet(ctx sdk.Context, ps ParamSet) {
|
||||
for _, pair := range ps.KeyValuePairs() {
|
||||
// pair.Field is a pointer to the field, so indirecting the ptr.
|
||||
// go-amino automatically handles it but just for sure,
|
||||
// since SetStruct is meant to be used in InitGenesis
|
||||
// so this method will not be called frequently
|
||||
v := reflect.Indirect(reflect.ValueOf(pair.Value)).Interface()
|
||||
s.Set(ctx, pair.Key, v)
|
||||
}
|
||||
}
|
||||
|
||||
// Returns name of Subspace
|
||||
func (s Subspace) Name() string {
|
||||
return string(s.name)
|
||||
}
|
||||
|
||||
// Wrapper of Subspace, provides immutable functions only
|
||||
type ReadOnlySubspace struct {
|
||||
s Subspace
|
||||
}
|
||||
|
||||
// Exposes Get
|
||||
func (ros ReadOnlySubspace) Get(ctx sdk.Context, key []byte, ptr interface{}) {
|
||||
ros.s.Get(ctx, key, ptr)
|
||||
}
|
||||
|
||||
// Exposes GetRaw
|
||||
func (ros ReadOnlySubspace) GetRaw(ctx sdk.Context, key []byte) []byte {
|
||||
return ros.s.GetRaw(ctx, key)
|
||||
}
|
||||
|
||||
// Exposes Has
|
||||
func (ros ReadOnlySubspace) Has(ctx sdk.Context, key []byte) bool {
|
||||
return ros.s.Has(ctx, key)
|
||||
}
|
||||
|
||||
// Exposes Modified
|
||||
func (ros ReadOnlySubspace) Modified(ctx sdk.Context, key []byte) bool {
|
||||
return ros.s.Modified(ctx, key)
|
||||
}
|
||||
|
||||
// Exposes Space
|
||||
func (ros ReadOnlySubspace) Name() string {
|
||||
return ros.s.Name()
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package subspace
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// TypeTable subspaces appropriate type for each parameter key
|
||||
type TypeTable map[string]reflect.Type
|
||||
|
||||
// Constructs new table
|
||||
func NewTypeTable(keytypes ...interface{}) (res TypeTable) {
|
||||
if len(keytypes)%2 != 0 {
|
||||
panic("odd number arguments in NewTypeTypeTable")
|
||||
}
|
||||
|
||||
res = make(map[string]reflect.Type)
|
||||
|
||||
for i := 0; i < len(keytypes); i += 2 {
|
||||
res = res.RegisterType(keytypes[i].([]byte), keytypes[i+1])
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Register single key-type pair
|
||||
func (t TypeTable) RegisterType(key []byte, ty interface{}) TypeTable {
|
||||
keystr := string(key)
|
||||
if _, ok := t[keystr]; ok {
|
||||
panic("duplicate parameter key")
|
||||
}
|
||||
|
||||
rty := reflect.TypeOf(ty)
|
||||
|
||||
// Indirect rty if it is ptr
|
||||
if rty.Kind() == reflect.Ptr {
|
||||
rty = rty.Elem()
|
||||
}
|
||||
|
||||
t[keystr] = rty
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
// Register multiple pairs from ParamSet
|
||||
func (t TypeTable) RegisterParamSet(ps ParamSet) TypeTable {
|
||||
for _, kvp := range ps.KeyValuePairs() {
|
||||
t = t.RegisterType(kvp.Key, kvp.Value)
|
||||
}
|
||||
return t
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package subspace
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
dbm "github.com/tendermint/tendermint/libs/db"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/store"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// Keys for parameter access
|
||||
const (
|
||||
TestParamStore = "ParamsTest"
|
||||
)
|
||||
|
||||
// Returns components for testing
|
||||
func DefaultTestComponents(t *testing.T, table TypeTable) (sdk.Context, Subspace, func() sdk.CommitID) {
|
||||
cdc := codec.New()
|
||||
key := sdk.NewKVStoreKey("params")
|
||||
tkey := sdk.NewTransientStoreKey("tparams")
|
||||
db := dbm.NewMemDB()
|
||||
ms := store.NewCommitMultiStore(db)
|
||||
ms.WithTracer(os.Stdout)
|
||||
ms.WithTracingContext(sdk.TraceContext{})
|
||||
ms.MountStoreWithDB(key, sdk.StoreTypeIAVL, db)
|
||||
ms.MountStoreWithDB(tkey, sdk.StoreTypeTransient, db)
|
||||
err := ms.LoadLatestVersion()
|
||||
require.Nil(t, err)
|
||||
ctx := sdk.NewContext(ms, abci.Header{}, false, log.NewTMLogger(os.Stdout))
|
||||
subspace := NewSubspace(cdc, key, tkey, TestParamStore).WithTypeTable(table)
|
||||
|
||||
return ctx, subspace, ms.Commit
|
||||
}
|
|
@ -28,18 +28,21 @@ func getMockApp(t *testing.T) (*mock.App, stake.Keeper, Keeper) {
|
|||
keyStake := sdk.NewKVStoreKey("stake")
|
||||
tkeyStake := sdk.NewTransientStoreKey("transient_stake")
|
||||
keySlashing := sdk.NewKVStoreKey("slashing")
|
||||
keyParams := sdk.NewKVStoreKey("params")
|
||||
bankKeeper := bank.NewBaseKeeper(mapp.AccountMapper)
|
||||
paramsKeeper := params.NewKeeper(mapp.Cdc, keyParams)
|
||||
stakeKeeper := stake.NewKeeper(mapp.Cdc, keyStake, tkeyStake, bankKeeper, mapp.RegisterCodespace(stake.DefaultCodespace))
|
||||
|
||||
keeper := NewKeeper(mapp.Cdc, keySlashing, stakeKeeper, paramsKeeper.Getter(), mapp.RegisterCodespace(DefaultCodespace))
|
||||
keyParams := sdk.NewKVStoreKey("params")
|
||||
tkeyParams := sdk.NewTransientStoreKey("transient_params")
|
||||
bankKeeper := bank.NewBaseKeeper(mapp.AccountMapper)
|
||||
|
||||
paramsKeeper := params.NewKeeper(mapp.Cdc, keyParams, tkeyParams)
|
||||
stakeKeeper := stake.NewKeeper(mapp.Cdc, keyStake, tkeyStake, bankKeeper, paramsKeeper.Subspace(stake.DefaultParamspace), mapp.RegisterCodespace(stake.DefaultCodespace))
|
||||
keeper := NewKeeper(mapp.Cdc, keySlashing, stakeKeeper, paramsKeeper.Subspace(DefaultParamspace), mapp.RegisterCodespace(DefaultCodespace))
|
||||
mapp.Router().AddRoute("stake", stake.NewHandler(stakeKeeper))
|
||||
mapp.Router().AddRoute("slashing", NewHandler(keeper))
|
||||
|
||||
mapp.SetEndBlocker(getEndBlocker(stakeKeeper))
|
||||
mapp.SetInitChainer(getInitChainer(mapp, stakeKeeper))
|
||||
require.NoError(t, mapp.CompleteSetup(keyStake, keySlashing, keyParams, tkeyStake))
|
||||
|
||||
require.NoError(t, mapp.CompleteSetup(keyStake, tkeyStake, keySlashing, keyParams, tkeyParams))
|
||||
|
||||
return mapp, stakeKeeper, keeper
|
||||
}
|
||||
|
|
|
@ -5,10 +5,24 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||
)
|
||||
|
||||
// InitGenesis initializes the keeper's address to pubkey map.
|
||||
func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) {
|
||||
for _, validator := range data.Validators {
|
||||
// GenesisState - all slashing state that must be provided at genesis
|
||||
type GenesisState struct {
|
||||
Params Params
|
||||
}
|
||||
|
||||
// HubDefaultGenesisState - default GenesisState used by Cosmos Hub
|
||||
func DefaultGenesisState() GenesisState {
|
||||
return GenesisState{
|
||||
Params: DefaultParams(),
|
||||
}
|
||||
}
|
||||
|
||||
// InitGenesis initialize default parameters
|
||||
// and the keeper's address to pubkey map
|
||||
func InitGenesis(ctx sdk.Context, keeper Keeper, data GenesisState, sdata types.GenesisState) {
|
||||
for _, validator := range sdata.Validators {
|
||||
keeper.addPubkey(ctx, validator.GetConsPubKey())
|
||||
}
|
||||
return
|
||||
|
||||
keeper.paramspace.SetParamSet(ctx, &data.Params)
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
|
||||
func TestCannotUnjailUnlessJailed(t *testing.T) {
|
||||
// initial setup
|
||||
ctx, ck, sk, _, keeper := createTestInput(t)
|
||||
ctx, ck, sk, _, keeper := createTestInput(t, DefaultParams())
|
||||
slh := NewHandler(keeper)
|
||||
amtInt := int64(100)
|
||||
addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)
|
||||
|
@ -30,7 +30,7 @@ func TestCannotUnjailUnlessJailed(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestJailedValidatorDelegations(t *testing.T) {
|
||||
ctx, _, stakeKeeper, _, slashingKeeper := createTestInput(t)
|
||||
ctx, _, stakeKeeper, _, slashingKeeper := createTestInput(t, DefaultParams())
|
||||
|
||||
stakeParams := stakeKeeper.GetParams(ctx)
|
||||
stakeParams.UnbondingTime = 0
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
)
|
||||
|
||||
func TestHookOnValidatorBonded(t *testing.T) {
|
||||
ctx, _, _, _, keeper := createTestInput(t)
|
||||
ctx, _, _, _, keeper := createTestInput(t, DefaultParams())
|
||||
addr := sdk.ConsAddress(addrs[0])
|
||||
keeper.onValidatorBonded(ctx, addr)
|
||||
period := keeper.getValidatorSlashingPeriodForHeight(ctx, addr, ctx.BlockHeight())
|
||||
|
@ -17,7 +17,7 @@ func TestHookOnValidatorBonded(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestHookOnValidatorBeginUnbonding(t *testing.T) {
|
||||
ctx, _, _, _, keeper := createTestInput(t)
|
||||
ctx, _, _, _, keeper := createTestInput(t, DefaultParams())
|
||||
addr := sdk.ConsAddress(addrs[0])
|
||||
keeper.onValidatorBonded(ctx, addr)
|
||||
keeper.onValidatorBeginUnbonding(ctx, addr)
|
||||
|
|
|
@ -19,18 +19,19 @@ type Keeper struct {
|
|||
storeKey sdk.StoreKey
|
||||
cdc *codec.Codec
|
||||
validatorSet sdk.ValidatorSet
|
||||
params params.Getter
|
||||
paramspace params.Subspace
|
||||
|
||||
// codespace
|
||||
codespace sdk.CodespaceType
|
||||
}
|
||||
|
||||
// NewKeeper creates a slashing keeper
|
||||
func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, vs sdk.ValidatorSet, params params.Getter, codespace sdk.CodespaceType) Keeper {
|
||||
func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, vs sdk.ValidatorSet, paramspace params.Subspace, codespace sdk.CodespaceType) Keeper {
|
||||
keeper := Keeper{
|
||||
storeKey: key,
|
||||
cdc: cdc,
|
||||
validatorSet: vs,
|
||||
params: params,
|
||||
paramspace: paramspace.WithTypeTable(ParamTypeTable()),
|
||||
codespace: codespace,
|
||||
}
|
||||
return keeper
|
||||
|
|
|
@ -12,10 +12,12 @@ import (
|
|||
|
||||
// Have to change these parameters for tests
|
||||
// lest the tests take forever
|
||||
func init() {
|
||||
defaultSignedBlocksWindow = 1000
|
||||
defaultDowntimeUnbondDuration = 60 * 60
|
||||
defaultDoubleSignUnbondDuration = 60 * 60
|
||||
func keeperTestParams() Params {
|
||||
params := DefaultParams()
|
||||
params.SignedBlocksWindow = 1000
|
||||
params.DowntimeUnbondDuration = 60 * 60
|
||||
params.DoubleSignUnbondDuration = 60 * 60
|
||||
return params
|
||||
}
|
||||
|
||||
// ______________________________________________________________
|
||||
|
@ -25,7 +27,7 @@ func init() {
|
|||
func TestHandleDoubleSign(t *testing.T) {
|
||||
|
||||
// initial setup
|
||||
ctx, ck, sk, _, keeper := createTestInput(t)
|
||||
ctx, ck, sk, _, keeper := createTestInput(t, keeperTestParams())
|
||||
// validator added pre-genesis
|
||||
ctx = ctx.WithBlockHeight(-1)
|
||||
amtInt := int64(100)
|
||||
|
@ -67,7 +69,7 @@ func TestHandleDoubleSign(t *testing.T) {
|
|||
func TestSlashingPeriodCap(t *testing.T) {
|
||||
|
||||
// initial setup
|
||||
ctx, ck, sk, _, keeper := createTestInput(t)
|
||||
ctx, ck, sk, _, keeper := createTestInput(t, DefaultParams())
|
||||
amtInt := int64(100)
|
||||
operatorAddr, amt := addrs[0], sdk.NewInt(amtInt)
|
||||
valConsPubKey, valConsAddr := pks[0], pks[0].Address()
|
||||
|
@ -132,7 +134,7 @@ func TestSlashingPeriodCap(t *testing.T) {
|
|||
func TestHandleAbsentValidator(t *testing.T) {
|
||||
|
||||
// initial setup
|
||||
ctx, ck, sk, _, keeper := createTestInput(t)
|
||||
ctx, ck, sk, _, keeper := createTestInput(t, keeperTestParams())
|
||||
amtInt := int64(100)
|
||||
addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)
|
||||
sh := stake.NewHandler(sk)
|
||||
|
@ -284,7 +286,7 @@ func TestHandleAbsentValidator(t *testing.T) {
|
|||
// and that they are not immediately jailed
|
||||
func TestHandleNewValidator(t *testing.T) {
|
||||
// initial setup
|
||||
ctx, ck, sk, _, keeper := createTestInput(t)
|
||||
ctx, ck, sk, _, keeper := createTestInput(t, keeperTestParams())
|
||||
addr, val, amt := addrs[0], pks[0], int64(100)
|
||||
sh := stake.NewHandler(sk)
|
||||
|
||||
|
@ -323,7 +325,7 @@ func TestHandleNewValidator(t *testing.T) {
|
|||
func TestHandleAlreadyJailed(t *testing.T) {
|
||||
|
||||
// initial setup
|
||||
ctx, _, sk, _, keeper := createTestInput(t)
|
||||
ctx, _, sk, _, keeper := createTestInput(t, DefaultParams())
|
||||
amtInt := int64(100)
|
||||
addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)
|
||||
sh := stake.NewHandler(sk)
|
||||
|
@ -371,7 +373,7 @@ func TestHandleAlreadyJailed(t *testing.T) {
|
|||
func TestValidatorDippingInAndOut(t *testing.T) {
|
||||
|
||||
// initial setup
|
||||
ctx, _, sk, _, keeper := createTestInput(t)
|
||||
ctx, _, sk, _, keeper := createTestInput(t, keeperTestParams())
|
||||
params := sk.GetParams(ctx)
|
||||
params.MaxValidators = 1
|
||||
sk.SetParams(ctx, params)
|
||||
|
|
|
@ -4,77 +4,119 @@ import (
|
|||
"time"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/params"
|
||||
)
|
||||
|
||||
// nolint
|
||||
// Default parameter namespace
|
||||
const (
|
||||
MaxEvidenceAgeKey = "slashing/MaxEvidenceAge"
|
||||
SignedBlocksWindowKey = "slashing/SignedBlocksWindow"
|
||||
MinSignedPerWindowKey = "slashing/MinSignedPerWindow"
|
||||
DoubleSignUnbondDurationKey = "slashing/DoubleSignUnbondDuration"
|
||||
DowntimeUnbondDurationKey = "slashing/DowntimeUnbondDuration"
|
||||
SlashFractionDoubleSignKey = "slashing/SlashFractionDoubleSign"
|
||||
SlashFractionDowntimeKey = "slashing/SlashFractionDowntime"
|
||||
DefaultParamspace = "slashing"
|
||||
)
|
||||
|
||||
// Parameter store key
|
||||
var (
|
||||
KeyMaxEvidenceAge = []byte("MaxEvidenceAge")
|
||||
KeySignedBlocksWindow = []byte("SignedBlocksWindow")
|
||||
KeyMinSignedPerWindow = []byte("MinSignedPerWindow")
|
||||
KeyDoubleSignUnbondDuration = []byte("DoubleSignUnbondDuration")
|
||||
KeyDowntimeUnbondDuration = []byte("DowntimeUnbondDuration")
|
||||
KeySlashFractionDoubleSign = []byte("SlashFractionDoubleSign")
|
||||
KeySlashFractionDowntime = []byte("SlashFractionDowntime")
|
||||
)
|
||||
|
||||
// ParamTypeTable for slashing module
|
||||
func ParamTypeTable() params.TypeTable {
|
||||
return params.NewTypeTable().RegisterParamSet(&Params{})
|
||||
}
|
||||
|
||||
// Params - used for initializing default parameter for slashing at genesis
|
||||
type Params struct {
|
||||
MaxEvidenceAge time.Duration `json:"max-evidence-age"`
|
||||
SignedBlocksWindow int64 `json:"signed-blocks-window"`
|
||||
MinSignedPerWindow sdk.Dec `json:"min-signed-per-window"`
|
||||
DoubleSignUnbondDuration time.Duration `json:"double-sign-unbond-duration"`
|
||||
DowntimeUnbondDuration time.Duration `json:"downtime-unbond-duration"`
|
||||
SlashFractionDoubleSign sdk.Dec `json:"slash-fraction-double-sign"`
|
||||
SlashFractionDowntime sdk.Dec `json:"slash-fraction-downtime"`
|
||||
}
|
||||
|
||||
// Implements params.ParamStruct
|
||||
func (p *Params) KeyValuePairs() params.KeyValuePairs {
|
||||
return params.KeyValuePairs{
|
||||
{KeyMaxEvidenceAge, &p.MaxEvidenceAge},
|
||||
{KeySignedBlocksWindow, &p.SignedBlocksWindow},
|
||||
{KeyMinSignedPerWindow, &p.MinSignedPerWindow},
|
||||
{KeyDoubleSignUnbondDuration, &p.DoubleSignUnbondDuration},
|
||||
{KeyDowntimeUnbondDuration, &p.DowntimeUnbondDuration},
|
||||
{KeySlashFractionDoubleSign, &p.SlashFractionDoubleSign},
|
||||
{KeySlashFractionDowntime, &p.SlashFractionDowntime},
|
||||
}
|
||||
}
|
||||
|
||||
// Default parameters used by Cosmos Hub
|
||||
func DefaultParams() Params {
|
||||
return Params{
|
||||
// defaultMaxEvidenceAge = 60 * 60 * 24 * 7 * 3
|
||||
// TODO Temporarily set to 2 minutes for testnets.
|
||||
MaxEvidenceAge: 60 * 2 * time.Second,
|
||||
|
||||
// TODO Temporarily set to five minutes for testnets
|
||||
DoubleSignUnbondDuration: 60 * 5 * time.Second,
|
||||
|
||||
// TODO Temporarily set to 100 blocks for testnets
|
||||
SignedBlocksWindow: 100,
|
||||
|
||||
// TODO Temporarily set to 10 minutes for testnets
|
||||
DowntimeUnbondDuration: 60 * 10 * time.Second,
|
||||
|
||||
MinSignedPerWindow: sdk.NewDecWithPrec(5, 1),
|
||||
|
||||
SlashFractionDoubleSign: sdk.NewDec(1).Quo(sdk.NewDec(20)),
|
||||
|
||||
SlashFractionDowntime: sdk.NewDec(1).Quo(sdk.NewDec(100)),
|
||||
}
|
||||
}
|
||||
|
||||
// MaxEvidenceAge - Max age for evidence - 21 days (3 weeks)
|
||||
// MaxEvidenceAge = 60 * 60 * 24 * 7 * 3
|
||||
func (k Keeper) MaxEvidenceAge(ctx sdk.Context) time.Duration {
|
||||
return time.Duration(k.params.GetInt64WithDefault(ctx, MaxEvidenceAgeKey, defaultMaxEvidenceAge)) * time.Second
|
||||
func (k Keeper) MaxEvidenceAge(ctx sdk.Context) (res time.Duration) {
|
||||
k.paramspace.Get(ctx, KeyMaxEvidenceAge, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// SignedBlocksWindow - sliding window for downtime slashing
|
||||
func (k Keeper) SignedBlocksWindow(ctx sdk.Context) int64 {
|
||||
return k.params.GetInt64WithDefault(ctx, SignedBlocksWindowKey, defaultSignedBlocksWindow)
|
||||
func (k Keeper) SignedBlocksWindow(ctx sdk.Context) (res int64) {
|
||||
k.paramspace.Get(ctx, KeySignedBlocksWindow, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// Downtime slashing thershold - default 50%
|
||||
// Downtime slashing thershold - default 50% of the SignedBlocksWindow
|
||||
func (k Keeper) MinSignedPerWindow(ctx sdk.Context) int64 {
|
||||
minSignedPerWindow := k.params.GetDecWithDefault(ctx, MinSignedPerWindowKey, defaultMinSignedPerWindow)
|
||||
var minSignedPerWindow sdk.Dec
|
||||
k.paramspace.Get(ctx, KeyMinSignedPerWindow, &minSignedPerWindow)
|
||||
signedBlocksWindow := k.SignedBlocksWindow(ctx)
|
||||
return sdk.NewDec(signedBlocksWindow).Mul(minSignedPerWindow).RoundInt64()
|
||||
}
|
||||
|
||||
// Double-sign unbond duration
|
||||
func (k Keeper) DoubleSignUnbondDuration(ctx sdk.Context) time.Duration {
|
||||
return time.Duration(k.params.GetInt64WithDefault(ctx, DoubleSignUnbondDurationKey, defaultDoubleSignUnbondDuration)) * time.Second
|
||||
func (k Keeper) DoubleSignUnbondDuration(ctx sdk.Context) (res time.Duration) {
|
||||
k.paramspace.Get(ctx, KeyDoubleSignUnbondDuration, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// Downtime unbond duration
|
||||
func (k Keeper) DowntimeUnbondDuration(ctx sdk.Context) time.Duration {
|
||||
return time.Duration(k.params.GetInt64WithDefault(ctx, DowntimeUnbondDurationKey, defaultDowntimeUnbondDuration)) * time.Second
|
||||
func (k Keeper) DowntimeUnbondDuration(ctx sdk.Context) (res time.Duration) {
|
||||
k.paramspace.Get(ctx, KeyDowntimeUnbondDuration, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// SlashFractionDoubleSign - currently default 5%
|
||||
func (k Keeper) SlashFractionDoubleSign(ctx sdk.Context) sdk.Dec {
|
||||
return k.params.GetDecWithDefault(ctx, SlashFractionDoubleSignKey, defaultSlashFractionDoubleSign)
|
||||
func (k Keeper) SlashFractionDoubleSign(ctx sdk.Context) (res sdk.Dec) {
|
||||
k.paramspace.Get(ctx, KeySlashFractionDoubleSign, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// SlashFractionDowntime - currently default 1%
|
||||
func (k Keeper) SlashFractionDowntime(ctx sdk.Context) sdk.Dec {
|
||||
return k.params.GetDecWithDefault(ctx, SlashFractionDowntimeKey, defaultSlashFractionDowntime)
|
||||
func (k Keeper) SlashFractionDowntime(ctx sdk.Context) (res sdk.Dec) {
|
||||
k.paramspace.Get(ctx, KeySlashFractionDowntime, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// declared as var because of keeper_test.go
|
||||
// TODO: make it const or parameter of NewKeeper
|
||||
|
||||
var (
|
||||
// defaultMaxEvidenceAge = 60 * 60 * 24 * 7 * 3
|
||||
// TODO Temporarily set to 2 minutes for testnets.
|
||||
defaultMaxEvidenceAge int64 = 60 * 2
|
||||
|
||||
// TODO Temporarily set to five minutes for testnets
|
||||
defaultDoubleSignUnbondDuration int64 = 60 * 5
|
||||
|
||||
// TODO Temporarily set to 10000 blocks for testnets
|
||||
defaultSignedBlocksWindow int64 = 10000
|
||||
|
||||
// TODO Temporarily set to 10 minutes for testnets
|
||||
defaultDowntimeUnbondDuration int64 = 60 * 10
|
||||
|
||||
defaultMinSignedPerWindow = sdk.NewDecWithPrec(5, 1)
|
||||
|
||||
defaultSlashFractionDoubleSign = sdk.NewDec(1).Quo(sdk.NewDec(20))
|
||||
|
||||
defaultSlashFractionDowntime = sdk.NewDec(1).Quo(sdk.NewDec(100))
|
||||
)
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
)
|
||||
|
||||
func TestGetSetValidatorSigningInfo(t *testing.T) {
|
||||
ctx, _, _, _, keeper := createTestInput(t)
|
||||
ctx, _, _, _, keeper := createTestInput(t, DefaultParams())
|
||||
info, found := keeper.getValidatorSigningInfo(ctx, sdk.ConsAddress(addrs[0]))
|
||||
require.False(t, found)
|
||||
newInfo := ValidatorSigningInfo{
|
||||
|
@ -29,7 +29,7 @@ func TestGetSetValidatorSigningInfo(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestGetSetValidatorSigningBitArray(t *testing.T) {
|
||||
ctx, _, _, _, keeper := createTestInput(t)
|
||||
ctx, _, _, _, keeper := createTestInput(t, DefaultParams())
|
||||
missed := keeper.getValidatorSigningBitArray(ctx, sdk.ConsAddress(addrs[0]), 0)
|
||||
require.False(t, missed) // treat empty key as not missed
|
||||
keeper.setValidatorSigningBitArray(ctx, sdk.ConsAddress(addrs[0]), 0, true)
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
)
|
||||
|
||||
func TestGetSetValidatorSlashingPeriod(t *testing.T) {
|
||||
ctx, _, _, _, keeper := createTestInput(t)
|
||||
ctx, _, _, _, keeper := createTestInput(t, DefaultParams())
|
||||
addr := sdk.ConsAddress(addrs[0])
|
||||
height := int64(5)
|
||||
require.Panics(t, func() { keeper.getValidatorSlashingPeriodForHeight(ctx, addr, height) })
|
||||
|
@ -60,7 +60,7 @@ func TestGetSetValidatorSlashingPeriod(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestValidatorSlashingPeriodCap(t *testing.T) {
|
||||
ctx, _, _, _, keeper := createTestInput(t)
|
||||
ctx, _, _, _, keeper := createTestInput(t, DefaultParams())
|
||||
addr := sdk.ConsAddress(addrs[0])
|
||||
height := int64(5)
|
||||
newPeriod := ValidatorSlashingPeriod{
|
||||
|
|
|
@ -49,12 +49,13 @@ func createTestCodec() *codec.Codec {
|
|||
return cdc
|
||||
}
|
||||
|
||||
func createTestInput(t *testing.T) (sdk.Context, bank.Keeper, stake.Keeper, params.Setter, Keeper) {
|
||||
func createTestInput(t *testing.T, defaults Params) (sdk.Context, bank.Keeper, stake.Keeper, params.Subspace, Keeper) {
|
||||
keyAcc := sdk.NewKVStoreKey("acc")
|
||||
keyStake := sdk.NewKVStoreKey("stake")
|
||||
tkeyStake := sdk.NewTransientStoreKey("transient_stake")
|
||||
keySlashing := sdk.NewKVStoreKey("slashing")
|
||||
keyParams := sdk.NewKVStoreKey("params")
|
||||
tkeyParams := sdk.NewTransientStoreKey("transient_params")
|
||||
db := dbm.NewMemDB()
|
||||
ms := store.NewCommitMultiStore(db)
|
||||
ms.MountStoreWithDB(keyAcc, sdk.StoreTypeIAVL, db)
|
||||
|
@ -62,14 +63,16 @@ func createTestInput(t *testing.T) (sdk.Context, bank.Keeper, stake.Keeper, para
|
|||
ms.MountStoreWithDB(keyStake, sdk.StoreTypeIAVL, db)
|
||||
ms.MountStoreWithDB(keySlashing, sdk.StoreTypeIAVL, db)
|
||||
ms.MountStoreWithDB(keyParams, sdk.StoreTypeIAVL, db)
|
||||
ms.MountStoreWithDB(tkeyParams, sdk.StoreTypeTransient, db)
|
||||
err := ms.LoadLatestVersion()
|
||||
require.Nil(t, err)
|
||||
ctx := sdk.NewContext(ms, abci.Header{Time: time.Unix(0, 0)}, false, log.NewTMLogger(os.Stdout))
|
||||
cdc := createTestCodec()
|
||||
accountMapper := auth.NewAccountMapper(cdc, keyAcc, auth.ProtoBaseAccount)
|
||||
|
||||
ck := bank.NewBaseKeeper(accountMapper)
|
||||
params := params.NewKeeper(cdc, keyParams)
|
||||
sk := stake.NewKeeper(cdc, keyStake, tkeyStake, ck, stake.DefaultCodespace)
|
||||
paramsKeeper := params.NewKeeper(cdc, keyParams, tkeyParams)
|
||||
sk := stake.NewKeeper(cdc, keyStake, tkeyStake, ck, paramsKeeper.Subspace(stake.DefaultParamspace), stake.DefaultCodespace)
|
||||
genesis := stake.DefaultGenesisState()
|
||||
|
||||
genesis.Pool.LooseTokens = sdk.NewDec(initCoins.MulRaw(int64(len(addrs))).Int64())
|
||||
|
@ -83,9 +86,15 @@ func createTestInput(t *testing.T) (sdk.Context, bank.Keeper, stake.Keeper, para
|
|||
})
|
||||
}
|
||||
require.Nil(t, err)
|
||||
keeper := NewKeeper(cdc, keySlashing, sk, params.Getter(), DefaultCodespace)
|
||||
paramstore := paramsKeeper.Subspace(DefaultParamspace)
|
||||
keeper := NewKeeper(cdc, keySlashing, sk, paramstore, DefaultCodespace)
|
||||
sk = sk.WithHooks(keeper.Hooks())
|
||||
return ctx, ck, sk, params.Setter(), keeper
|
||||
|
||||
require.NotPanics(t, func() {
|
||||
InitGenesis(ctx, keeper, GenesisState{defaults}, genesis)
|
||||
})
|
||||
|
||||
return ctx, ck, sk, paramstore, keeper
|
||||
}
|
||||
|
||||
func newPubKey(pk string) (res crypto.PubKey) {
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
)
|
||||
|
||||
func TestBeginBlocker(t *testing.T) {
|
||||
ctx, ck, sk, _, keeper := createTestInput(t)
|
||||
ctx, ck, sk, _, keeper := createTestInput(t, DefaultParams())
|
||||
addr, pk, amt := addrs[2], pks[2], sdk.NewInt(100)
|
||||
|
||||
// bond the validator
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"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"
|
||||
"github.com/tendermint/tendermint/crypto/ed25519"
|
||||
|
@ -36,15 +37,21 @@ func getMockApp(t *testing.T) (*mock.App, Keeper) {
|
|||
RegisterCodec(mApp.Cdc)
|
||||
|
||||
keyStake := sdk.NewKVStoreKey("stake")
|
||||
|
||||
tkeyStake := sdk.NewTransientStoreKey("transient_stake")
|
||||
keyParams := sdk.NewKVStoreKey("params")
|
||||
tkeyParams := sdk.NewTransientStoreKey("transient_params")
|
||||
|
||||
bankKeeper := bank.NewBaseKeeper(mApp.AccountMapper)
|
||||
keeper := NewKeeper(mApp.Cdc, keyStake, tkeyStake, bankKeeper, mApp.RegisterCodespace(DefaultCodespace))
|
||||
pk := params.NewKeeper(mApp.Cdc, keyParams, tkeyParams)
|
||||
|
||||
keeper := NewKeeper(mApp.Cdc, keyStake, tkeyStake, bankKeeper, pk.Subspace(DefaultParamspace), mApp.RegisterCodespace(DefaultCodespace))
|
||||
|
||||
mApp.Router().AddRoute("stake", NewHandler(keeper))
|
||||
mApp.SetEndBlocker(getEndBlocker(keeper))
|
||||
mApp.SetInitChainer(getInitChainer(mApp, keeper))
|
||||
|
||||
require.NoError(t, mApp.CompleteSetup(keyStake, tkeyStake))
|
||||
require.NoError(t, mApp.CompleteSetup(keyStake, tkeyStake, keyParams, tkeyParams))
|
||||
return mApp, keeper
|
||||
}
|
||||
|
||||
|
|
|
@ -464,15 +464,17 @@ func GetCmdQueryParams(storeName string, cdc *codec.Codec) *cobra.Command {
|
|||
Short: "Query the current staking parameters information",
|
||||
Args: cobra.NoArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
key := stake.ParamKey
|
||||
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
||||
|
||||
res, err := cliCtx.QueryStore(key, storeName)
|
||||
bz, err := cliCtx.QueryWithData("custom/stake/"+stake.QueryParameters, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
params := types.MustUnmarshalParams(cdc, res)
|
||||
var params stake.Params
|
||||
err = cdc.UnmarshalJSON(bz, ¶ms)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch viper.Get(cli.OutputFlag) {
|
||||
case "text":
|
||||
|
|
|
@ -35,6 +35,8 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
|
|||
func EndBlocker(ctx sdk.Context, k keeper.Keeper) (ValidatorUpdates []abci.ValidatorUpdate) {
|
||||
endBlockerTags := sdk.EmptyTags()
|
||||
|
||||
k.UnbondAllMatureValidatorQueue(ctx)
|
||||
|
||||
matureUnbonds := k.DequeueAllMatureUnbondingQueue(ctx, ctx.BlockHeader().Time)
|
||||
for _, dvPair := range matureUnbonds {
|
||||
err := k.CompleteUnbonding(ctx, dvPair.DelegatorAddr, dvPair.ValidatorAddr)
|
||||
|
|
|
@ -629,6 +629,56 @@ func TestJailValidator(t *testing.T) {
|
|||
require.True(t, got.IsOK(), "expected ok, got %v", got)
|
||||
}
|
||||
|
||||
func TestValidatorQueue(t *testing.T) {
|
||||
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
|
||||
validatorAddr, delegatorAddr := sdk.ValAddress(keep.Addrs[0]), keep.Addrs[1]
|
||||
|
||||
// set the unbonding time
|
||||
params := keeper.GetParams(ctx)
|
||||
params.UnbondingTime = 7 * time.Second
|
||||
keeper.SetParams(ctx, params)
|
||||
|
||||
// create the validator
|
||||
msgCreateValidator := newTestMsgCreateValidator(validatorAddr, keep.PKs[0], 10)
|
||||
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
||||
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
||||
|
||||
// bond a delegator
|
||||
msgDelegate := newTestMsgDelegate(delegatorAddr, validatorAddr, 10)
|
||||
got = handleMsgDelegate(ctx, msgDelegate, keeper)
|
||||
require.True(t, got.IsOK(), "expected ok, got %v", got)
|
||||
|
||||
EndBlocker(ctx, keeper)
|
||||
|
||||
// unbond the all self-delegation to put validator in unbonding state
|
||||
msgBeginUnbondingValidator := NewMsgBeginUnbonding(sdk.AccAddress(validatorAddr), validatorAddr, sdk.NewDec(10))
|
||||
got = handleMsgBeginUnbonding(ctx, msgBeginUnbondingValidator, keeper)
|
||||
require.True(t, got.IsOK(), "expected no error: %v", got)
|
||||
var finishTime time.Time
|
||||
types.MsgCdc.MustUnmarshalBinary(got.Data, &finishTime)
|
||||
ctx = ctx.WithBlockTime(finishTime)
|
||||
EndBlocker(ctx, keeper)
|
||||
origHeader := ctx.BlockHeader()
|
||||
|
||||
validator, found := keeper.GetValidator(ctx, validatorAddr)
|
||||
require.True(t, found)
|
||||
require.True(t, validator.GetStatus() == sdk.Unbonding, "%v", validator)
|
||||
|
||||
// should still be unbonding at time 6 seconds later
|
||||
ctx = ctx.WithBlockTime(origHeader.Time.Add(time.Second * 6))
|
||||
EndBlocker(ctx, keeper)
|
||||
validator, found = keeper.GetValidator(ctx, validatorAddr)
|
||||
require.True(t, found)
|
||||
require.True(t, validator.GetStatus() == sdk.Unbonding, "%v", validator)
|
||||
|
||||
// should be in unbonded state at time 7 seconds later
|
||||
ctx = ctx.WithBlockTime(origHeader.Time.Add(time.Second * 7))
|
||||
EndBlocker(ctx, keeper)
|
||||
validator, found = keeper.GetValidator(ctx, validatorAddr)
|
||||
require.True(t, found)
|
||||
require.True(t, validator.GetStatus() == sdk.Unbonded, "%v", validator)
|
||||
}
|
||||
|
||||
func TestUnbondingPeriod(t *testing.T) {
|
||||
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
|
||||
validatorAddr := sdk.ValAddress(keep.Addrs[0])
|
||||
|
|
|
@ -437,7 +437,7 @@ func (k Keeper) unbond(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValA
|
|||
//______________________________________________________________________________________________________
|
||||
|
||||
// get info for begin functions: MinTime and CreationHeight
|
||||
func (k Keeper) getBeginInfo(ctx sdk.Context, params types.Params, valSrcAddr sdk.ValAddress) (
|
||||
func (k Keeper) getBeginInfo(ctx sdk.Context, valSrcAddr sdk.ValAddress) (
|
||||
minTime time.Time, height int64, completeNow bool) {
|
||||
|
||||
validator, found := k.GetValidator(ctx, valSrcAddr)
|
||||
|
@ -446,11 +446,11 @@ func (k Keeper) getBeginInfo(ctx sdk.Context, params types.Params, valSrcAddr sd
|
|||
case !found || validator.Status == sdk.Bonded:
|
||||
|
||||
// the longest wait - just unbonding period from now
|
||||
minTime = ctx.BlockHeader().Time.Add(params.UnbondingTime)
|
||||
height = ctx.BlockHeader().Height
|
||||
minTime = ctx.BlockHeader().Time.Add(k.UnbondingTime(ctx))
|
||||
height = ctx.BlockHeight()
|
||||
return minTime, height, false
|
||||
|
||||
case validator.IsUnbonded(ctx):
|
||||
case validator.Status == sdk.Unbonded:
|
||||
return minTime, height, true
|
||||
|
||||
case validator.Status == sdk.Unbonding:
|
||||
|
@ -474,15 +474,14 @@ func (k Keeper) BeginUnbonding(ctx sdk.Context,
|
|||
}
|
||||
|
||||
// create the unbonding delegation
|
||||
params := k.GetParams(ctx)
|
||||
minTime, height, completeNow := k.getBeginInfo(ctx, params, valAddr)
|
||||
minTime, height, completeNow := k.getBeginInfo(ctx, valAddr)
|
||||
|
||||
returnAmount, err := k.unbond(ctx, delAddr, valAddr, sharesAmount)
|
||||
if err != nil {
|
||||
return types.UnbondingDelegation{}, err
|
||||
}
|
||||
|
||||
balance := sdk.NewCoin(params.BondDenom, returnAmount.RoundInt())
|
||||
balance := sdk.NewCoin(k.BondDenom(ctx), returnAmount.RoundInt())
|
||||
|
||||
// no need to create the ubd object just complete now
|
||||
if completeNow {
|
||||
|
@ -537,8 +536,7 @@ func (k Keeper) BeginRedelegation(ctx sdk.Context, delAddr sdk.AccAddress,
|
|||
return types.Redelegation{}, err
|
||||
}
|
||||
|
||||
params := k.GetParams(ctx)
|
||||
returnCoin := sdk.NewCoin(params.BondDenom, returnAmount.RoundInt())
|
||||
returnCoin := sdk.Coin{k.BondDenom(ctx), returnAmount.RoundInt()}
|
||||
dstValidator, found := k.GetValidator(ctx, valDstAddr)
|
||||
if !found {
|
||||
return types.Redelegation{}, types.ErrBadRedelegationDst(k.Codespace())
|
||||
|
@ -549,7 +547,7 @@ func (k Keeper) BeginRedelegation(ctx sdk.Context, delAddr sdk.AccAddress,
|
|||
}
|
||||
|
||||
// create the unbonding delegation
|
||||
minTime, height, completeNow := k.getBeginInfo(ctx, params, valSrcAddr)
|
||||
minTime, height, completeNow := k.getBeginInfo(ctx, valSrcAddr)
|
||||
|
||||
if completeNow { // no need to create the redelegation object
|
||||
return types.Redelegation{MinTime: minTime}, nil
|
||||
|
|
|
@ -374,12 +374,8 @@ func TestUndelegateFromUnbondedValidator(t *testing.T) {
|
|||
}
|
||||
keeper.SetDelegation(ctx, delegation)
|
||||
|
||||
header := ctx.BlockHeader()
|
||||
blockHeight := int64(10)
|
||||
header.Height = blockHeight
|
||||
blockTime := time.Unix(333, 0)
|
||||
header.Time = blockTime
|
||||
ctx = ctx.WithBlockHeader(header)
|
||||
ctx = ctx.WithBlockHeight(10)
|
||||
ctx = ctx.WithBlockTime(time.Unix(333, 0))
|
||||
|
||||
// unbond the all self-delegation to put validator in unbonding state
|
||||
_, err := keeper.BeginUnbonding(ctx, val0AccAddr, addrVals[0], sdk.NewDec(10))
|
||||
|
@ -391,17 +387,12 @@ func TestUndelegateFromUnbondedValidator(t *testing.T) {
|
|||
|
||||
validator, found := keeper.GetValidator(ctx, addrVals[0])
|
||||
require.True(t, found)
|
||||
require.Equal(t, blockHeight, validator.UnbondingHeight)
|
||||
require.Equal(t, ctx.BlockHeight(), validator.UnbondingHeight)
|
||||
params := keeper.GetParams(ctx)
|
||||
require.True(t, blockTime.Add(params.UnbondingTime).Equal(validator.UnbondingMinTime))
|
||||
require.True(t, ctx.BlockHeader().Time.Add(params.UnbondingTime).Equal(validator.UnbondingMinTime))
|
||||
|
||||
// change the context to one which makes the validator considered unbonded
|
||||
header = ctx.BlockHeader()
|
||||
blockHeight2 := int64(20)
|
||||
header.Height = blockHeight2
|
||||
blockTime2 := time.Unix(444, 0).Add(params.UnbondingTime)
|
||||
header.Time = blockTime2
|
||||
ctx = ctx.WithBlockHeader(header)
|
||||
// unbond the validator
|
||||
keeper.unbondingToUnbonded(ctx, validator)
|
||||
|
||||
// unbond some of the other delegation's shares
|
||||
_, err = keeper.BeginUnbonding(ctx, addrDels[0], addrVals[0], sdk.NewDec(6))
|
||||
|
@ -696,12 +687,8 @@ func TestRedelegateFromUnbondedValidator(t *testing.T) {
|
|||
validator2 = testingUpdateValidator(keeper, ctx, validator2)
|
||||
require.Equal(t, sdk.Bonded, validator2.Status)
|
||||
|
||||
header := ctx.BlockHeader()
|
||||
blockHeight := int64(10)
|
||||
header.Height = blockHeight
|
||||
blockTime := time.Unix(333, 0)
|
||||
header.Time = blockTime
|
||||
ctx = ctx.WithBlockHeader(header)
|
||||
ctx = ctx.WithBlockHeight(10)
|
||||
ctx = ctx.WithBlockTime(time.Unix(333, 0))
|
||||
|
||||
// unbond the all self-delegation to put validator in unbonding state
|
||||
_, err := keeper.BeginUnbonding(ctx, val0AccAddr, addrVals[0], sdk.NewDec(10))
|
||||
|
@ -713,23 +700,18 @@ func TestRedelegateFromUnbondedValidator(t *testing.T) {
|
|||
|
||||
validator, found := keeper.GetValidator(ctx, addrVals[0])
|
||||
require.True(t, found)
|
||||
require.Equal(t, blockHeight, validator.UnbondingHeight)
|
||||
require.Equal(t, ctx.BlockHeight(), validator.UnbondingHeight)
|
||||
params := keeper.GetParams(ctx)
|
||||
require.True(t, blockTime.Add(params.UnbondingTime).Equal(validator.UnbondingMinTime))
|
||||
require.True(t, ctx.BlockHeader().Time.Add(params.UnbondingTime).Equal(validator.UnbondingMinTime))
|
||||
|
||||
// change the context to one which makes the validator considered unbonded
|
||||
header = ctx.BlockHeader()
|
||||
blockHeight2 := int64(20)
|
||||
header.Height = blockHeight2
|
||||
blockTime2 := time.Unix(444, 0).Add(params.UnbondingTime)
|
||||
header.Time = blockTime2
|
||||
ctx = ctx.WithBlockHeader(header)
|
||||
// unbond the validator
|
||||
keeper.unbondingToUnbonded(ctx, validator)
|
||||
|
||||
// unbond some of the other delegation's shares
|
||||
// redelegate some of the delegation's shares
|
||||
_, err = keeper.BeginRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1], sdk.NewDec(6))
|
||||
require.NoError(t, err)
|
||||
|
||||
// no ubd should have been found, coins should have been returned direcly to account
|
||||
ubd, found := keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
||||
require.False(t, found, "%v", ubd)
|
||||
// no red should have been found
|
||||
red, found := keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
||||
require.False(t, found, "%v", red)
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
"github.com/cosmos/cosmos-sdk/x/params"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||
)
|
||||
|
||||
|
@ -15,17 +16,19 @@ type Keeper struct {
|
|||
cdc *codec.Codec
|
||||
bankKeeper bank.Keeper
|
||||
hooks sdk.StakingHooks
|
||||
paramstore params.Subspace
|
||||
|
||||
// codespace
|
||||
codespace sdk.CodespaceType
|
||||
}
|
||||
|
||||
func NewKeeper(cdc *codec.Codec, key, tkey sdk.StoreKey, ck bank.Keeper, codespace sdk.CodespaceType) Keeper {
|
||||
func NewKeeper(cdc *codec.Codec, key, tkey sdk.StoreKey, ck bank.Keeper, paramstore params.Subspace, codespace sdk.CodespaceType) Keeper {
|
||||
keeper := Keeper{
|
||||
storeKey: key,
|
||||
storeTKey: tkey,
|
||||
cdc: cdc,
|
||||
bankKeeper: ck,
|
||||
paramstore: paramstore.WithTypeTable(ParamTypeTable()),
|
||||
hooks: nil,
|
||||
codespace: codespace,
|
||||
}
|
||||
|
@ -48,29 +51,6 @@ func (k Keeper) Codespace() sdk.CodespaceType {
|
|||
return k.codespace
|
||||
}
|
||||
|
||||
//_________________________________________________________________________
|
||||
// some generic reads/writes that don't need their own files
|
||||
|
||||
// load/save the global staking params
|
||||
func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
|
||||
b := store.Get(ParamKey)
|
||||
if b == nil {
|
||||
panic("Stored params should not have been nil")
|
||||
}
|
||||
|
||||
k.cdc.MustUnmarshalBinary(b, ¶ms)
|
||||
return
|
||||
}
|
||||
|
||||
// set the params
|
||||
func (k Keeper) SetParams(ctx sdk.Context, params types.Params) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
b := k.cdc.MustMarshalBinary(params)
|
||||
store.Set(ParamKey, b)
|
||||
}
|
||||
|
||||
//_______________________________________________________________________
|
||||
|
||||
// load/save the pool
|
||||
|
|
|
@ -13,7 +13,8 @@ import (
|
|||
//nolint
|
||||
var (
|
||||
// Keys for store prefixes
|
||||
ParamKey = []byte{0x00} // key for parameters relating to staking
|
||||
// TODO DEPRECATED: delete in next release and reorder keys
|
||||
// ParamKey = []byte{0x00} // key for parameters relating to staking
|
||||
PoolKey = []byte{0x01} // key for the staking pools
|
||||
ValidatorsKey = []byte{0x02} // prefix for each key to a validator
|
||||
ValidatorsByConsAddrKey = []byte{0x03} // prefix for each key to a validator index, by pubkey
|
||||
|
@ -28,6 +29,7 @@ var (
|
|||
RedelegationByValDstIndexKey = []byte{0x0C} // prefix for each key for an redelegation, by destination validator operator
|
||||
UnbondingQueueKey = []byte{0x0D} // prefix for the timestamps in unbonding queue
|
||||
RedelegationQueueKey = []byte{0x0E} // prefix for the timestamps in redelegations queue
|
||||
ValidatorQueueKey = []byte{0x0F} // prefix for the timestamps in validator queue
|
||||
)
|
||||
|
||||
const maxDigitsForAccount = 12 // ~220,000,000 atoms created at launch
|
||||
|
@ -85,6 +87,12 @@ func getValidatorPowerRank(validator types.Validator) []byte {
|
|||
return key
|
||||
}
|
||||
|
||||
// gets the prefix for all unbonding delegations from a delegator
|
||||
func GetValidatorQueueTimeKey(timestamp time.Time) []byte {
|
||||
bz := types.MsgCdc.MustMarshalBinary(timestamp)
|
||||
return append(ValidatorQueueKey, bz...)
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
|
||||
// gets the key for delegator bond with validator
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
package keeper
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/params"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||
)
|
||||
|
||||
// Default parameter namespace
|
||||
const (
|
||||
DefaultParamspace = "stake"
|
||||
)
|
||||
|
||||
// ParamTable for stake module
|
||||
func ParamTypeTable() params.TypeTable {
|
||||
return params.NewTypeTable().RegisterParamSet(&types.Params{})
|
||||
}
|
||||
|
||||
// InflationRateChange - Maximum annual change in inflation rate
|
||||
func (k Keeper) InflationRateChange(ctx sdk.Context) (res sdk.Dec) {
|
||||
k.paramstore.Get(ctx, types.KeyInflationRateChange, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// InflationMax - Maximum inflation rate
|
||||
func (k Keeper) InflationMax(ctx sdk.Context) (res sdk.Dec) {
|
||||
k.paramstore.Get(ctx, types.KeyInflationMax, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// InflationMin - Minimum inflation rate
|
||||
func (k Keeper) InflationMin(ctx sdk.Context) (res sdk.Dec) {
|
||||
k.paramstore.Get(ctx, types.KeyInflationMin, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// GoalBonded - Goal of percent bonded atoms
|
||||
func (k Keeper) GoalBonded(ctx sdk.Context) (res sdk.Dec) {
|
||||
k.paramstore.Get(ctx, types.KeyGoalBonded, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// UnbondingTime
|
||||
func (k Keeper) UnbondingTime(ctx sdk.Context) (res time.Duration) {
|
||||
k.paramstore.Get(ctx, types.KeyUnbondingTime, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// MaxValidators - Maximum number of validators
|
||||
func (k Keeper) MaxValidators(ctx sdk.Context) (res uint16) {
|
||||
k.paramstore.Get(ctx, types.KeyMaxValidators, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// BondDenom - Bondable coin denomination
|
||||
func (k Keeper) BondDenom(ctx sdk.Context) (res string) {
|
||||
k.paramstore.Get(ctx, types.KeyBondDenom, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// Get all parameteras as types.Params
|
||||
func (k Keeper) GetParams(ctx sdk.Context) (res types.Params) {
|
||||
res.InflationRateChange = k.InflationRateChange(ctx)
|
||||
res.InflationMax = k.InflationMax(ctx)
|
||||
res.InflationMin = k.InflationMin(ctx)
|
||||
res.GoalBonded = k.GoalBonded(ctx)
|
||||
res.UnbondingTime = k.UnbondingTime(ctx)
|
||||
res.MaxValidators = k.MaxValidators(ctx)
|
||||
res.BondDenom = k.BondDenom(ctx)
|
||||
return
|
||||
}
|
||||
|
||||
// set the params
|
||||
func (k Keeper) SetParams(ctx sdk.Context, params types.Params) {
|
||||
k.paramstore.SetParamSet(ctx, ¶ms)
|
||||
}
|
|
@ -46,7 +46,7 @@ func (k Keeper) Slash(ctx sdk.Context, consAddr sdk.ConsAddress, infractionHeigh
|
|||
}
|
||||
|
||||
// should not be slashing unbonded
|
||||
if validator.IsUnbonded(ctx) {
|
||||
if validator.Status == sdk.Unbonded {
|
||||
panic(fmt.Sprintf("should not be slashing unbonded validator: %s", validator.GetOperator()))
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
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/params"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||
)
|
||||
|
||||
|
@ -90,12 +91,16 @@ func CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) (sdk.Context
|
|||
keyStake := sdk.NewKVStoreKey("stake")
|
||||
tkeyStake := sdk.NewTransientStoreKey("transient_stake")
|
||||
keyAcc := sdk.NewKVStoreKey("acc")
|
||||
keyParams := sdk.NewKVStoreKey("params")
|
||||
tkeyParams := sdk.NewTransientStoreKey("transient_params")
|
||||
|
||||
db := dbm.NewMemDB()
|
||||
ms := store.NewCommitMultiStore(db)
|
||||
ms.MountStoreWithDB(tkeyStake, sdk.StoreTypeTransient, nil)
|
||||
ms.MountStoreWithDB(keyStake, sdk.StoreTypeIAVL, db)
|
||||
ms.MountStoreWithDB(keyAcc, sdk.StoreTypeIAVL, db)
|
||||
ms.MountStoreWithDB(keyParams, sdk.StoreTypeIAVL, db)
|
||||
ms.MountStoreWithDB(tkeyParams, sdk.StoreTypeTransient, db)
|
||||
err := ms.LoadLatestVersion()
|
||||
require.Nil(t, err)
|
||||
|
||||
|
@ -106,8 +111,11 @@ func CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) (sdk.Context
|
|||
keyAcc, // target store
|
||||
auth.ProtoBaseAccount, // prototype
|
||||
)
|
||||
|
||||
ck := bank.NewBaseKeeper(accountMapper)
|
||||
keeper := NewKeeper(cdc, keyStake, tkeyStake, ck, types.DefaultCodespace)
|
||||
|
||||
pk := params.NewKeeper(cdc, keyParams, tkeyParams)
|
||||
keeper := NewKeeper(cdc, keyStake, tkeyStake, ck, pk.Subspace(DefaultParamspace), types.DefaultCodespace)
|
||||
keeper.SetPool(ctx, types.InitialPool())
|
||||
keeper.SetParams(ctx, types.DefaultParams())
|
||||
keeper.InitIntraTxCounter(ctx)
|
||||
|
@ -116,7 +124,7 @@ func CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) (sdk.Context
|
|||
for _, addr := range Addrs {
|
||||
pool := keeper.GetPool(ctx)
|
||||
_, _, err := ck.AddCoins(ctx, addr, sdk.Coins{
|
||||
{keeper.GetParams(ctx).BondDenom, sdk.NewInt(initCoins)},
|
||||
{keeper.BondDenom(ctx), sdk.NewInt(initCoins)},
|
||||
})
|
||||
require.Nil(t, err)
|
||||
pool.LooseTokens = pool.LooseTokens.Add(sdk.NewDec(initCoins))
|
||||
|
|
|
@ -131,8 +131,9 @@ func (k Keeper) unbondedToBonded(ctx sdk.Context, validator types.Validator) typ
|
|||
return k.bondValidator(ctx, validator)
|
||||
}
|
||||
|
||||
// switches a validator from unbonding state to unbonded state
|
||||
func (k Keeper) unbondingToUnbonded(ctx sdk.Context, validator types.Validator) types.Validator {
|
||||
if validator.Status != sdk.Unbonded {
|
||||
if validator.Status != sdk.Unbonding {
|
||||
panic(fmt.Sprintf("bad state transition unbondingToBonded, validator: %v\n", validator))
|
||||
}
|
||||
return k.completeUnbondingValidator(ctx, validator)
|
||||
|
@ -213,6 +214,9 @@ func (k Keeper) beginUnbondingValidator(ctx sdk.Context, validator types.Validat
|
|||
|
||||
k.SetValidatorByPowerIndex(ctx, validator, pool)
|
||||
|
||||
// Adds to unbonding validator queue
|
||||
k.InsertValidatorQueue(ctx, validator)
|
||||
|
||||
// call the unbond hook if present
|
||||
if k.hooks != nil {
|
||||
k.hooks.OnValidatorBeginUnbonding(ctx, validator.ConsAddress())
|
||||
|
|
|
@ -3,6 +3,7 @@ package keeper
|
|||
import (
|
||||
"container/list"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||
|
@ -238,7 +239,7 @@ func (k Keeper) GetValidatorsBonded(ctx sdk.Context) (validators []types.Validat
|
|||
store := ctx.KVStore(k.storeKey)
|
||||
|
||||
// add the actual validator power sorted store
|
||||
maxValidators := k.GetParams(ctx).MaxValidators
|
||||
maxValidators := k.MaxValidators(ctx)
|
||||
validators = make([]types.Validator, maxValidators)
|
||||
|
||||
iterator := sdk.KVStorePrefixIterator(store, ValidatorsBondedIndexKey)
|
||||
|
@ -263,7 +264,7 @@ func (k Keeper) GetValidatorsBonded(ctx sdk.Context) (validators []types.Validat
|
|||
// get the group of bonded validators sorted by power-rank
|
||||
func (k Keeper) GetBondedValidatorsByPower(ctx sdk.Context) []types.Validator {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
maxValidators := k.GetParams(ctx).MaxValidators
|
||||
maxValidators := k.MaxValidators(ctx)
|
||||
validators := make([]types.Validator, maxValidators)
|
||||
|
||||
iterator := sdk.KVStoreReversePrefixIterator(store, ValidatorsByPowerIndexKey)
|
||||
|
@ -281,3 +282,69 @@ func (k Keeper) GetBondedValidatorsByPower(ctx sdk.Context) []types.Validator {
|
|||
}
|
||||
return validators[:i] // trim
|
||||
}
|
||||
|
||||
// gets a specific validator queue timeslice. A timeslice is a slice of ValAddresses corresponding to unbonding validators
|
||||
// that expire at a certain time.
|
||||
func (k Keeper) GetValidatorQueueTimeSlice(ctx sdk.Context, timestamp time.Time) (valAddrs []sdk.ValAddress) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
bz := store.Get(GetValidatorQueueTimeKey(timestamp))
|
||||
if bz == nil {
|
||||
return []sdk.ValAddress{}
|
||||
}
|
||||
k.cdc.MustUnmarshalBinary(bz, &valAddrs)
|
||||
return valAddrs
|
||||
}
|
||||
|
||||
// Sets a specific validator queue timeslice.
|
||||
func (k Keeper) SetValidatorQueueTimeSlice(ctx sdk.Context, timestamp time.Time, keys []sdk.ValAddress) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
bz := k.cdc.MustMarshalBinary(keys)
|
||||
store.Set(GetValidatorQueueTimeKey(timestamp), bz)
|
||||
}
|
||||
|
||||
// Insert an validator address to the appropriate timeslice in the validator queue
|
||||
func (k Keeper) InsertValidatorQueue(ctx sdk.Context, val types.Validator) {
|
||||
timeSlice := k.GetValidatorQueueTimeSlice(ctx, val.UnbondingMinTime)
|
||||
if len(timeSlice) == 0 {
|
||||
k.SetValidatorQueueTimeSlice(ctx, val.UnbondingMinTime, []sdk.ValAddress{val.OperatorAddr})
|
||||
} else {
|
||||
timeSlice = append(timeSlice, val.OperatorAddr)
|
||||
k.SetValidatorQueueTimeSlice(ctx, val.UnbondingMinTime, timeSlice)
|
||||
}
|
||||
}
|
||||
|
||||
// Returns all the validator queue timeslices from time 0 until endTime
|
||||
func (k Keeper) ValidatorQueueIterator(ctx sdk.Context, endTime time.Time) sdk.Iterator {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
return store.Iterator(ValidatorQueueKey, sdk.InclusiveEndBytes(GetValidatorQueueTimeKey(endTime)))
|
||||
}
|
||||
|
||||
// Returns a concatenated list of all the timeslices before currTime, and deletes the timeslices from the queue
|
||||
func (k Keeper) GetAllMatureValidatorQueue(ctx sdk.Context, currTime time.Time) (matureValsAddrs []sdk.ValAddress) {
|
||||
// gets an iterator for all timeslices from time 0 until the current Blockheader time
|
||||
validatorTimesliceIterator := k.ValidatorQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||
for ; validatorTimesliceIterator.Valid(); validatorTimesliceIterator.Next() {
|
||||
timeslice := []sdk.ValAddress{}
|
||||
k.cdc.MustUnmarshalBinary(validatorTimesliceIterator.Value(), ×lice)
|
||||
matureValsAddrs = append(matureValsAddrs, timeslice...)
|
||||
}
|
||||
return matureValsAddrs
|
||||
}
|
||||
|
||||
// Unbonds all the unbonding validators that have finished their unbonding period
|
||||
func (k Keeper) UnbondAllMatureValidatorQueue(ctx sdk.Context) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
validatorTimesliceIterator := k.ValidatorQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||
for ; validatorTimesliceIterator.Valid(); validatorTimesliceIterator.Next() {
|
||||
timeslice := []sdk.ValAddress{}
|
||||
k.cdc.MustUnmarshalBinary(validatorTimesliceIterator.Value(), ×lice)
|
||||
for _, valAddr := range timeslice {
|
||||
val, found := k.GetValidator(ctx, valAddr)
|
||||
if !found || val.GetStatus() != sdk.Unbonding {
|
||||
continue
|
||||
}
|
||||
k.unbondingToUnbonded(ctx, val)
|
||||
}
|
||||
store.Delete(validatorTimesliceIterator.Key())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
"github.com/cosmos/cosmos-sdk/x/mock"
|
||||
"github.com/cosmos/cosmos-sdk/x/mock/simulation"
|
||||
"github.com/cosmos/cosmos-sdk/x/params"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||
)
|
||||
|
||||
|
@ -23,7 +24,11 @@ func TestStakeWithRandomMessages(t *testing.T) {
|
|||
bankKeeper := bank.NewBaseKeeper(mapper)
|
||||
stakeKey := sdk.NewKVStoreKey("stake")
|
||||
stakeTKey := sdk.NewTransientStoreKey("transient_stake")
|
||||
stakeKeeper := stake.NewKeeper(mapp.Cdc, stakeKey, stakeTKey, bankKeeper, stake.DefaultCodespace)
|
||||
paramsKey := sdk.NewKVStoreKey("params")
|
||||
paramsTKey := sdk.NewTransientStoreKey("transient_params")
|
||||
|
||||
paramstore := params.NewKeeper(mapp.Cdc, paramsKey, paramsTKey).Subspace(stake.DefaultParamspace)
|
||||
stakeKeeper := stake.NewKeeper(mapp.Cdc, stakeKey, stakeTKey, bankKeeper, paramstore, stake.DefaultCodespace)
|
||||
mapp.Router().AddRoute("stake", stake.NewHandler(stakeKeeper))
|
||||
mapp.SetEndBlocker(func(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
|
||||
validatorUpdates := stake.EndBlocker(ctx, stakeKeeper)
|
||||
|
@ -32,7 +37,7 @@ func TestStakeWithRandomMessages(t *testing.T) {
|
|||
}
|
||||
})
|
||||
|
||||
err := mapp.CompleteSetup(stakeKey, stakeTKey)
|
||||
err := mapp.CompleteSetup(stakeKey, stakeTKey, paramsKey, paramsTKey)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
|
|
@ -38,7 +38,6 @@ var (
|
|||
GetValidatorsByPowerIndexKey = keeper.GetValidatorsByPowerIndexKey
|
||||
GetDelegationKey = keeper.GetDelegationKey
|
||||
GetDelegationsKey = keeper.GetDelegationsKey
|
||||
ParamKey = keeper.ParamKey
|
||||
PoolKey = keeper.PoolKey
|
||||
ValidatorsKey = keeper.ValidatorsKey
|
||||
ValidatorsByConsAddrKey = keeper.ValidatorsByConsAddrKey
|
||||
|
@ -58,6 +57,14 @@ var (
|
|||
GetREDsToValDstIndexKey = keeper.GetREDsToValDstIndexKey
|
||||
GetREDsByDelToValDstIndexKey = keeper.GetREDsByDelToValDstIndexKey
|
||||
|
||||
DefaultParamspace = keeper.DefaultParamspace
|
||||
KeyInflationRateChange = types.KeyInflationRateChange
|
||||
KeyInflationMax = types.KeyInflationMax
|
||||
KeyGoalBonded = types.KeyGoalBonded
|
||||
KeyUnbondingTime = types.KeyUnbondingTime
|
||||
KeyMaxValidators = types.KeyMaxValidators
|
||||
KeyBondDenom = types.KeyBondDenom
|
||||
|
||||
DefaultParams = types.DefaultParams
|
||||
InitialPool = types.InitialPool
|
||||
NewValidator = types.NewValidator
|
||||
|
@ -79,6 +86,18 @@ var (
|
|||
NewQuerier = querier.NewQuerier
|
||||
)
|
||||
|
||||
const (
|
||||
QueryValidators = querier.QueryValidators
|
||||
QueryValidator = querier.QueryValidator
|
||||
QueryDelegator = querier.QueryDelegator
|
||||
QueryDelegation = querier.QueryDelegation
|
||||
QueryUnbondingDelegation = querier.QueryUnbondingDelegation
|
||||
QueryDelegatorValidators = querier.QueryDelegatorValidators
|
||||
QueryDelegatorValidator = querier.QueryDelegatorValidator
|
||||
QueryPool = querier.QueryPool
|
||||
QueryParameters = querier.QueryParameters
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultCodespace = types.DefaultCodespace
|
||||
CodeInvalidValidator = types.CodeInvalidValidator
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/params"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -21,6 +22,19 @@ const (
|
|||
ValidatorUpdateDelay int64 = 1
|
||||
)
|
||||
|
||||
// nolint - Keys for parameter access
|
||||
var (
|
||||
KeyInflationRateChange = []byte("InflationRateChange")
|
||||
KeyInflationMax = []byte("InflationMax")
|
||||
KeyInflationMin = []byte("InflationMin")
|
||||
KeyGoalBonded = []byte("GoalBonded")
|
||||
KeyUnbondingTime = []byte("UnbondingTime")
|
||||
KeyMaxValidators = []byte("MaxValidators")
|
||||
KeyBondDenom = []byte("BondDenom")
|
||||
)
|
||||
|
||||
var _ params.ParamSet = (*Params)(nil)
|
||||
|
||||
// Params defines the high level settings for staking
|
||||
type Params struct {
|
||||
InflationRateChange sdk.Dec `json:"inflation_rate_change"` // maximum annual change in inflation rate
|
||||
|
@ -34,6 +48,19 @@ type Params struct {
|
|||
BondDenom string `json:"bond_denom"` // bondable coin denomination
|
||||
}
|
||||
|
||||
// Implements params.ParamSet
|
||||
func (p *Params) KeyValuePairs() params.KeyValuePairs {
|
||||
return params.KeyValuePairs{
|
||||
{KeyInflationRateChange, &p.InflationRateChange},
|
||||
{KeyInflationMax, &p.InflationMax},
|
||||
{KeyInflationMin, &p.InflationMin},
|
||||
{KeyGoalBonded, &p.GoalBonded},
|
||||
{KeyUnbondingTime, &p.UnbondingTime},
|
||||
{KeyMaxValidators, &p.MaxValidators},
|
||||
{KeyBondDenom, &p.BondDenom},
|
||||
}
|
||||
}
|
||||
|
||||
// Equal returns a boolean determining if two Param types are identical.
|
||||
func (p Params) Equal(p2 Params) bool {
|
||||
bz1 := MsgCdc.MustMarshalBinary(&p)
|
||||
|
|
|
@ -435,21 +435,6 @@ func (v Validator) BondedTokens() sdk.Dec {
|
|||
return sdk.ZeroDec()
|
||||
}
|
||||
|
||||
// TODO remove this once the validator queue logic is implemented
|
||||
// Returns if the validator should be considered unbonded
|
||||
func (v Validator) IsUnbonded(ctx sdk.Context) bool {
|
||||
switch v.Status {
|
||||
case sdk.Unbonded:
|
||||
return true
|
||||
case sdk.Unbonding:
|
||||
ctxTime := ctx.BlockHeader().Time
|
||||
if ctxTime.After(v.UnbondingMinTime) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
//______________________________________________________________________
|
||||
|
||||
// ensure fulfills the sdk validator types
|
||||
|
|
Loading…
Reference in New Issue