revised use of EndBlock/BeginBlock, basecoin updated for staking/slashing

This commit is contained in:
rigelrozanski 2018-06-01 14:24:48 -07:00
parent 537ce91e33
commit 0ef3259a39
16 changed files with 194 additions and 144 deletions

View File

@ -4,3 +4,4 @@
* [ ] Updated all code comments where relevant * [ ] Updated all code comments where relevant
* [ ] Wrote tests * [ ] Wrote tests
* [ ] Updated CHANGELOG.md * [ ] Updated CHANGELOG.md
* [ ] Updated Basecoin / other examples

View File

@ -4,16 +4,19 @@
BREAKING CHANGES BREAKING CHANGES
* [cli] rearranged commands under subcommands * [cli] rearranged commands under subcommands
* [stake] remove Tick and add EndBlocker
FEATURES FEATURES
IMPROVEMENTS IMPROVEMENTS
* bank module uses go-wire codec instead of 'encoding/json' * bank module uses go-wire codec instead of 'encoding/json'
* auth module uses go-wire codec instead of 'encoding/json' * auth module uses go-wire codec instead of 'encoding/json'
* revised use of endblock and beginblock
FIXES FIXES
* [cli] fixed cli-bash tests * [cli] fixed cli-bash tests
* [ci] added cli-bash tests * [ci] added cli-bash tests
* [basecoin] updated basecoin for stake and slashing
## 0.18.1 ## 0.18.1

View File

@ -85,8 +85,8 @@ func NewGaiaApp(logger log.Logger, db dbm.DB) *GaiaApp {
// initialize BaseApp // initialize BaseApp
app.SetInitChainer(app.initChainer) app.SetInitChainer(app.initChainer)
app.SetBeginBlocker(slashing.NewBeginBlocker(app.slashingKeeper)) app.SetBeginBlocker(app.BeginBlocker)
app.SetEndBlocker(stake.NewEndBlocker(app.stakeKeeper)) app.SetEndBlocker(app.EndBlocker)
app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, app.feeCollectionKeeper)) app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, app.feeCollectionKeeper))
app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyIBC, app.keyStake, app.keySlashing) app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyIBC, app.keyStake, app.keySlashing)
err := app.LoadLatestVersion(app.keyMain) err := app.LoadLatestVersion(app.keyMain)
@ -110,6 +110,24 @@ func MakeCodec() *wire.Codec {
return cdc return cdc
} }
// application updates every end block
func (app *GaiaApp) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock {
tags := slashing.BeginBlocker(ctx, req, app.slashingKeeper)
return abci.ResponseBeginBlock{
Tags: tags.ToKVPairs(),
}
}
// application updates every end block
func (app *GaiaApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
validatorUpdates := stake.EndBlocker(ctx, app.stakeKeeper)
return abci.ResponseEndBlock{
ValidatorUpdates: validatorUpdates,
}
}
// custom logic for gaia initialization // custom logic for gaia initialization
func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain { func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
stateJSON := req.GenesisBytes stateJSON := req.GenesisBytes
@ -134,7 +152,7 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci
return abci.ResponseInitChain{} return abci.ResponseInitChain{}
} }
// export the state of gaia for a genesis f // export the state of gaia for a genesis file
func (app *GaiaApp) ExportAppStateJSON() (appState json.RawMessage, err error) { func (app *GaiaApp) ExportAppStateJSON() (appState json.RawMessage, err error) {
ctx := app.NewContext(true, abci.Header{}) ctx := app.NewContext(true, abci.Header{})

View File

@ -1,7 +1,6 @@
package app package app
import ( import (
"encoding/json"
"fmt" "fmt"
"os" "os"
"testing" "testing"
@ -139,30 +138,6 @@ func TestMsgs(t *testing.T) {
} }
} }
func setGenesisAccounts(gapp *GaiaApp, accs ...*auth.BaseAccount) error {
genaccs := make([]GenesisAccount, len(accs))
for i, acc := range accs {
genaccs[i] = NewGenesisAccount(acc)
}
genesisState := GenesisState{
Accounts: genaccs,
StakeData: stake.DefaultGenesisState(),
}
stateBytes, err := json.MarshalIndent(genesisState, "", "\t")
if err != nil {
return err
}
// Initialize the chain
vals := []abci.Validator{}
gapp.InitChain(abci.RequestInitChain{vals, stateBytes})
gapp.Commit()
return nil
}
func TestGenesis(t *testing.T) { func TestGenesis(t *testing.T) {
logger, dbs := loggerAndDB() logger, dbs := loggerAndDB()
gapp := NewGaiaApp(logger, dbs) gapp := NewGaiaApp(logger, dbs)
@ -178,7 +153,7 @@ func TestGenesis(t *testing.T) {
} }
err = setGenesis(gapp, baseAcc) err = setGenesis(gapp, baseAcc)
assert.Nil(t, err) require.Nil(t, err)
// A checkTx context // A checkTx context
ctx := gapp.BaseApp.NewContext(true, abci.Header{}) ctx := gapp.BaseApp.NewContext(true, abci.Header{})

View File

@ -95,7 +95,7 @@ func GaiaAppGenTx(cdc *wire.Codec, pk crypto.PubKey) (
return nil, nil, tmtypes.GenesisValidator{}, errors.New("Must specify --name (validator moniker)") return nil, nil, tmtypes.GenesisValidator{}, errors.New("Must specify --name (validator moniker)")
} }
var addr sdk.Address var addr sdk.Address
var secret string var secret string
addr, secret, err = server.GenerateSaveCoinKey(clientRoot, name, "1234567890", overwrite) addr, secret, err = server.GenerateSaveCoinKey(clientRoot, name, "1234567890", overwrite)
if err != nil { if err != nil {

View File

@ -14,6 +14,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/bank" "github.com/cosmos/cosmos-sdk/x/bank"
"github.com/cosmos/cosmos-sdk/x/ibc" "github.com/cosmos/cosmos-sdk/x/ibc"
"github.com/cosmos/cosmos-sdk/x/slashing"
"github.com/cosmos/cosmos-sdk/x/stake" "github.com/cosmos/cosmos-sdk/x/stake"
"github.com/cosmos/cosmos-sdk/examples/basecoin/types" "github.com/cosmos/cosmos-sdk/examples/basecoin/types"
@ -29,10 +30,11 @@ type BasecoinApp struct {
cdc *wire.Codec cdc *wire.Codec
// keys to access the substores // keys to access the substores
keyMain *sdk.KVStoreKey keyMain *sdk.KVStoreKey
keyAccount *sdk.KVStoreKey keyAccount *sdk.KVStoreKey
keyIBC *sdk.KVStoreKey keyIBC *sdk.KVStoreKey
keyStake *sdk.KVStoreKey keyStake *sdk.KVStoreKey
keySlashing *sdk.KVStoreKey
// Manage getting and setting accounts // Manage getting and setting accounts
accountMapper auth.AccountMapper accountMapper auth.AccountMapper
@ -40,6 +42,7 @@ type BasecoinApp struct {
coinKeeper bank.Keeper coinKeeper bank.Keeper
ibcMapper ibc.Mapper ibcMapper ibc.Mapper
stakeKeeper stake.Keeper stakeKeeper stake.Keeper
slashingKeeper slashing.Keeper
} }
func NewBasecoinApp(logger log.Logger, db dbm.DB) *BasecoinApp { func NewBasecoinApp(logger log.Logger, db dbm.DB) *BasecoinApp {
@ -49,12 +52,13 @@ func NewBasecoinApp(logger log.Logger, db dbm.DB) *BasecoinApp {
// Create your application object. // Create your application object.
var app = &BasecoinApp{ var app = &BasecoinApp{
BaseApp: bam.NewBaseApp(appName, cdc, logger, db), BaseApp: bam.NewBaseApp(appName, cdc, logger, db),
cdc: cdc, cdc: cdc,
keyMain: sdk.NewKVStoreKey("main"), keyMain: sdk.NewKVStoreKey("main"),
keyAccount: sdk.NewKVStoreKey("acc"), keyAccount: sdk.NewKVStoreKey("acc"),
keyIBC: sdk.NewKVStoreKey("ibc"), keyIBC: sdk.NewKVStoreKey("ibc"),
keyStake: sdk.NewKVStoreKey("stake"), keyStake: sdk.NewKVStoreKey("stake"),
keySlashing: sdk.NewKVStoreKey("slashing"),
} }
// Define the accountMapper. // Define the accountMapper.
@ -68,6 +72,7 @@ func NewBasecoinApp(logger log.Logger, db dbm.DB) *BasecoinApp {
app.coinKeeper = bank.NewKeeper(app.accountMapper) app.coinKeeper = bank.NewKeeper(app.accountMapper)
app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace)) app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace))
app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.coinKeeper, app.RegisterCodespace(stake.DefaultCodespace)) app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.coinKeeper, app.RegisterCodespace(stake.DefaultCodespace))
app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.RegisterCodespace(slashing.DefaultCodespace))
// register message routes // register message routes
app.Router(). app.Router().
@ -78,8 +83,10 @@ func NewBasecoinApp(logger log.Logger, db dbm.DB) *BasecoinApp {
// Initialize BaseApp. // Initialize BaseApp.
app.SetInitChainer(app.initChainer) app.SetInitChainer(app.initChainer)
app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyIBC, app.keyStake) app.SetBeginBlocker(app.BeginBlocker)
app.SetEndBlocker(app.EndBlocker)
app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, app.feeCollectionKeeper)) app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, app.feeCollectionKeeper))
app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyIBC, app.keyStake, app.keySlashing)
err := app.LoadLatestVersion(app.keyMain) err := app.LoadLatestVersion(app.keyMain)
if err != nil { if err != nil {
cmn.Exit(err.Error()) cmn.Exit(err.Error())
@ -94,6 +101,7 @@ func MakeCodec() *wire.Codec {
sdk.RegisterWire(cdc) // Register Msgs sdk.RegisterWire(cdc) // Register Msgs
bank.RegisterWire(cdc) bank.RegisterWire(cdc)
stake.RegisterWire(cdc) stake.RegisterWire(cdc)
slashing.RegisterWire(cdc)
ibc.RegisterWire(cdc) ibc.RegisterWire(cdc)
// register custom AppAccount // register custom AppAccount
@ -102,6 +110,24 @@ func MakeCodec() *wire.Codec {
return cdc return cdc
} }
// application updates every end block
func (app *BasecoinApp) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock {
tags := slashing.BeginBlocker(ctx, req, app.slashingKeeper)
return abci.ResponseBeginBlock{
Tags: tags.ToKVPairs(),
}
}
// application updates every end block
func (app *BasecoinApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
validatorUpdates := stake.EndBlocker(ctx, app.stakeKeeper)
return abci.ResponseEndBlock{
ValidatorUpdates: validatorUpdates,
}
}
// Custom logic for basecoin initialization // Custom logic for basecoin initialization
func (app *BasecoinApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain { func (app *BasecoinApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
stateJSON := req.GenesisBytes stateJSON := req.GenesisBytes
@ -121,6 +147,10 @@ func (app *BasecoinApp) initChainer(ctx sdk.Context, req abci.RequestInitChain)
} }
app.accountMapper.SetAccount(ctx, acc) app.accountMapper.SetAccount(ctx, acc)
} }
// load the initial stake information
stake.InitGenesis(ctx, app.stakeKeeper, genesisState.StakeData)
return abci.ResponseInitChain{} return abci.ResponseInitChain{}
} }

View File

@ -11,9 +11,11 @@ import (
"github.com/cosmos/cosmos-sdk/examples/basecoin/types" "github.com/cosmos/cosmos-sdk/examples/basecoin/types"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/wire"
"github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/bank" "github.com/cosmos/cosmos-sdk/x/bank"
"github.com/cosmos/cosmos-sdk/x/ibc" "github.com/cosmos/cosmos-sdk/x/ibc"
"github.com/cosmos/cosmos-sdk/x/stake"
abci "github.com/tendermint/abci/types" abci "github.com/tendermint/abci/types"
crypto "github.com/tendermint/go-crypto" crypto "github.com/tendermint/go-crypto"
@ -85,28 +87,18 @@ var (
} }
) )
func loggerAndDB() (log.Logger, dbm.DB) { func setGenesis(bapp *BasecoinApp, accs ...auth.BaseAccount) error {
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app")
db := dbm.NewMemDB()
return logger, db
}
func newBasecoinApp() *BasecoinApp {
logger, db := loggerAndDB()
return NewBasecoinApp(logger, db)
}
func setGenesisAccounts(bapp *BasecoinApp, accs ...auth.BaseAccount) error {
genaccs := make([]*types.GenesisAccount, len(accs)) genaccs := make([]*types.GenesisAccount, len(accs))
for i, acc := range accs { for i, acc := range accs {
genaccs[i] = types.NewGenesisAccount(&types.AppAccount{acc, accName}) genaccs[i] = types.NewGenesisAccount(&types.AppAccount{acc, accName})
} }
genesisState := types.GenesisState{ genesisState := types.GenesisState{
Accounts: genaccs, Accounts: genaccs,
StakeData: stake.DefaultGenesisState(),
} }
stateBytes, err := json.MarshalIndent(genesisState, "", "\t") stateBytes, err := wire.MarshalJSONIndent(bapp.cdc, genesisState)
if err != nil { if err != nil {
return err return err
} }
@ -119,10 +111,46 @@ func setGenesisAccounts(bapp *BasecoinApp, accs ...auth.BaseAccount) error {
return nil return nil
} }
func loggerAndDB() (log.Logger, dbm.DB) {
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app")
db := dbm.NewMemDB()
return logger, db
}
func newBasecoinApp() *BasecoinApp {
logger, db := loggerAndDB()
return NewBasecoinApp(logger, db)
}
//func setGenesisAccounts(bapp *BasecoinApp, accs ...auth.BaseAccount) error {
//genaccs := make([]*types.GenesisAccount, len(accs))
//for i, acc := range accs {
//genaccs[i] = types.NewGenesisAccount(&types.AppAccount{acc, accName})
//}
//genesisState := types.GenesisState{
//Accounts: genaccs,
//StakeData: stake.DefaultGenesisState(),
//}
//stateBytes, err := json.MarshalIndent(genesisState, "", "\t")
//if err != nil {
//return err
//}
//// Initialize the chain
//vals := []abci.Validator{}
//bapp.InitChain(abci.RequestInitChain{vals, stateBytes})
//bapp.Commit()
//return nil
//}
//_______________________________________________________________________ //_______________________________________________________________________
func TestMsgs(t *testing.T) { func TestMsgs(t *testing.T) {
bapp := newBasecoinApp() bapp := newBasecoinApp()
require.Nil(t, setGenesis(bapp))
msgs := []struct { msgs := []struct {
msg sdk.Msg msg sdk.Msg
@ -193,8 +221,8 @@ func TestGenesis(t *testing.T) {
} }
acc := &types.AppAccount{baseAcc, "foobart"} acc := &types.AppAccount{baseAcc, "foobart"}
err = setGenesisAccounts(bapp, baseAcc) err = setGenesis(bapp, baseAcc)
assert.Nil(t, err) require.Nil(t, err)
// A checkTx context // A checkTx context
ctx := bapp.BaseApp.NewContext(true, abci.Header{}) ctx := bapp.BaseApp.NewContext(true, abci.Header{})
@ -222,8 +250,9 @@ func TestMsgChangePubKey(t *testing.T) {
} }
// Construct genesis state // Construct genesis state
err = setGenesisAccounts(bapp, baseAcc) err = setGenesis(bapp, baseAcc)
assert.Nil(t, err) require.Nil(t, err)
// A checkTx context (true) // A checkTx context (true)
ctxCheck := bapp.BaseApp.NewContext(true, abci.Header{}) ctxCheck := bapp.BaseApp.NewContext(true, abci.Header{})
res1 := bapp.accountMapper.GetAccount(ctxCheck, addr1) res1 := bapp.accountMapper.GetAccount(ctxCheck, addr1)
@ -276,8 +305,9 @@ func TestMsgSendWithAccounts(t *testing.T) {
} }
// Construct genesis state // Construct genesis state
err = setGenesisAccounts(bapp, baseAcc) err = setGenesis(bapp, baseAcc)
assert.Nil(t, err) require.Nil(t, err)
// A checkTx context (true) // A checkTx context (true)
ctxCheck := bapp.BaseApp.NewContext(true, abci.Header{}) ctxCheck := bapp.BaseApp.NewContext(true, abci.Header{})
res1 := bapp.accountMapper.GetAccount(ctxCheck, addr1) res1 := bapp.accountMapper.GetAccount(ctxCheck, addr1)
@ -320,8 +350,9 @@ func TestMsgSendMultipleOut(t *testing.T) {
Coins: genCoins, Coins: genCoins,
} }
err = setGenesisAccounts(bapp, acc1, acc2) // Construct genesis state
assert.Nil(t, err) err = setGenesis(bapp, acc1, acc2)
require.Nil(t, err)
// Simulate a Block // Simulate a Block
SignCheckDeliver(t, bapp, sendMsg2, []int64{0}, true, priv1) SignCheckDeliver(t, bapp, sendMsg2, []int64{0}, true, priv1)
@ -353,7 +384,7 @@ func TestSengMsgMultipleInOut(t *testing.T) {
Coins: genCoins, Coins: genCoins,
} }
err = setGenesisAccounts(bapp, acc1, acc2, acc4) err = setGenesis(bapp, acc1, acc2, acc4)
assert.Nil(t, err) assert.Nil(t, err)
// CheckDeliver // CheckDeliver
@ -377,7 +408,11 @@ func TestMsgSendDependent(t *testing.T) {
Coins: genCoins, Coins: genCoins,
} }
err = setGenesisAccounts(bapp, acc1) // Construct genesis state
err = setGenesis(bapp, acc1)
require.Nil(t, err)
err = setGenesis(bapp, acc1)
assert.Nil(t, err) assert.Nil(t, err)
// CheckDeliver // CheckDeliver
@ -438,8 +473,9 @@ func TestIBCMsgs(t *testing.T) {
} }
acc1 := &types.AppAccount{baseAcc, "foobart"} acc1 := &types.AppAccount{baseAcc, "foobart"}
err := setGenesisAccounts(bapp, baseAcc) err := setGenesis(bapp, baseAcc)
assert.Nil(t, err) assert.Nil(t, err)
// A checkTx context (true) // A checkTx context (true)
ctxCheck := bapp.BaseApp.NewContext(true, abci.Header{}) ctxCheck := bapp.BaseApp.NewContext(true, abci.Header{})
res1 := bapp.accountMapper.GetAccount(ctxCheck, addr1) res1 := bapp.accountMapper.GetAccount(ctxCheck, addr1)

View File

@ -4,6 +4,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/wire" "github.com/cosmos/cosmos-sdk/wire"
"github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/stake"
) )
var _ auth.Account = (*AppAccount)(nil) var _ auth.Account = (*AppAccount)(nil)
@ -41,7 +42,8 @@ func GetAccountDecoder(cdc *wire.Codec) auth.AccountDecoder {
// State to Unmarshal // State to Unmarshal
type GenesisState struct { type GenesisState struct {
Accounts []*GenesisAccount `json:"accounts"` Accounts []*GenesisAccount `json:"accounts"`
StakeData stake.GenesisState `json:"stake"`
} }
// GenesisAccount doesn't need pubkey or sequence // GenesisAccount doesn't need pubkey or sequence

View File

@ -21,7 +21,7 @@ func GetCmdQuerySigningInfo(storeName string, cdc *wire.Codec) *cobra.Command {
Args: cobra.ExactArgs(1), Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
pk, err := sdk.GetValPubKeyBech32Cosmos(args[0]) pk, err := sdk.GetValPubKeyBech32(args[0])
if err != nil { if err != nil {
return err return err
} }

View File

@ -21,7 +21,7 @@ func GetCmdUnrevoke(cdc *wire.Codec) *cobra.Command {
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc))
validatorAddr, err := sdk.GetAccAddressBech32Cosmos(args[0]) validatorAddr, err := sdk.GetAccAddressBech32(args[0])
if err != nil { if err != nil {
return err return err
} }

View File

@ -18,7 +18,7 @@ func TestHandleDoubleSign(t *testing.T) {
addr, val, amt := addrs[0], pks[0], int64(100) addr, val, amt := addrs[0], pks[0], int64(100)
got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, val, amt)) got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, val, amt))
require.True(t, got.IsOK()) require.True(t, got.IsOK())
sk.Tick(ctx) stake.EndBlocker(ctx, sk)
require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins - amt}}) require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins - amt}})
require.Equal(t, sdk.NewRat(amt), sk.Validator(ctx, addr).GetPower()) require.Equal(t, sdk.NewRat(amt), sk.Validator(ctx, addr).GetPower())
@ -41,7 +41,7 @@ func TestHandleAbsentValidator(t *testing.T) {
slh := NewHandler(keeper) slh := NewHandler(keeper)
got := sh(ctx, newTestMsgCreateValidator(addr, val, amt)) got := sh(ctx, newTestMsgCreateValidator(addr, val, amt))
require.True(t, got.IsOK()) require.True(t, got.IsOK())
sk.Tick(ctx) stake.EndBlocker(ctx, sk)
require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins - amt}}) require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins - amt}})
require.Equal(t, sdk.NewRat(amt), sk.Validator(ctx, addr).GetPower()) require.Equal(t, sdk.NewRat(amt), sk.Validator(ctx, addr).GetPower())
info, found := keeper.getValidatorSigningInfo(ctx, val.Address()) info, found := keeper.getValidatorSigningInfo(ctx, val.Address())

View File

@ -10,49 +10,45 @@ import (
tmtypes "github.com/tendermint/tendermint/types" tmtypes "github.com/tendermint/tendermint/types"
) )
func NewBeginBlocker(sk Keeper) sdk.BeginBlocker { // slash begin blocker functionality
return func(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock { func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, sk Keeper) (tags sdk.Tags) {
// Tag the height
heightBytes := make([]byte, 8)
binary.LittleEndian.PutUint64(heightBytes, uint64(req.Header.Height))
tags := sdk.NewTags("height", heightBytes)
// Deal with any equivocation evidence // Tag the height
for _, evidence := range req.ByzantineValidators { heightBytes := make([]byte, 8)
var pk crypto.PubKey binary.LittleEndian.PutUint64(heightBytes, uint64(req.Header.Height))
sk.cdc.MustUnmarshalBinaryBare(evidence.PubKey, &pk)
switch string(evidence.Type) {
case tmtypes.DUPLICATE_VOTE:
sk.handleDoubleSign(ctx, evidence.Height, evidence.Time, pk)
default:
ctx.Logger().With("module", "x/slashing").Error(fmt.Sprintf("Ignored unknown evidence type: %s", string(evidence.Type)))
}
}
// Figure out which validators were absent // TODO Add some more tags so clients can track slashing events
absent := make(map[crypto.PubKey]struct{}) tags = sdk.NewTags("height", heightBytes)
for _, pubkey := range req.AbsentValidators {
var pk crypto.PubKey
sk.cdc.MustUnmarshalBinaryBare(pubkey, &pk)
absent[pk] = struct{}{}
}
// Iterate over all the validators which *should* have signed this block // Deal with any equivocation evidence
sk.stakeKeeper.IterateValidatorsBonded(ctx, func(_ int64, validator sdk.Validator) (stop bool) { for _, evidence := range req.ByzantineValidators {
pubkey := validator.GetPubKey() var pk crypto.PubKey
present := true sk.cdc.MustUnmarshalBinaryBare(evidence.PubKey, &pk)
if _, ok := absent[pubkey]; ok { switch string(evidence.Type) {
present = false case tmtypes.DUPLICATE_VOTE:
} sk.handleDoubleSign(ctx, evidence.Height, evidence.Time, pk)
sk.handleValidatorSignature(ctx, pubkey, present) default:
return false ctx.Logger().With("module", "x/slashing").Error(fmt.Sprintf("Ignored unknown evidence type: %s", string(evidence.Type)))
})
// Return the begin block response
// TODO Return something composable, so other modules can also have BeginBlockers
// TODO Add some more tags so clients can track slashing events
return abci.ResponseBeginBlock{
Tags: tags.ToKVPairs(),
} }
} }
// Figure out which validators were absent
absent := make(map[crypto.PubKey]struct{})
for _, pubkey := range req.AbsentValidators {
var pk crypto.PubKey
sk.cdc.MustUnmarshalBinaryBare(pubkey, &pk)
absent[pk] = struct{}{}
}
// Iterate over all the validators which *should* have signed this block
sk.stakeKeeper.IterateValidatorsBonded(ctx, func(_ int64, validator sdk.Validator) (stop bool) {
pubkey := validator.GetPubKey()
present := true
if _, ok := absent[pubkey]; ok {
present = false
}
sk.handleValidatorSignature(ctx, pubkey, present)
return false
})
return
} }

View File

@ -25,13 +25,27 @@ func NewHandler(k Keeper) sdk.Handler {
} }
} }
// NewEndBlocker generates sdk.EndBlocker // Called every block, process inflation, update validator set
// Performs tick functionality func EndBlocker(ctx sdk.Context, k Keeper) (ValidatorUpdates []abci.Validator) {
func NewEndBlocker(k Keeper) sdk.EndBlocker { pool := k.GetPool(ctx)
return func(ctx sdk.Context, req abci.RequestEndBlock) (res abci.ResponseEndBlock) {
res.ValidatorUpdates = k.Tick(ctx) // Process Validator Provisions
return blockTime := ctx.BlockHeader().Time // XXX assuming in seconds, confirm
if pool.InflationLastTime+blockTime >= 3600 {
pool.InflationLastTime = blockTime
pool = k.processProvisions(ctx)
} }
// save the params
k.setPool(ctx, pool)
// reset the intra-transaction counter
k.setIntraTxCounter(ctx, 0)
// calculate validator set changes
ValidatorUpdates = k.getTendermintUpdates(ctx)
k.clearTendermintUpdates(ctx)
return
} }
//_____________________________________________________________________ //_____________________________________________________________________

View File

@ -2,7 +2,6 @@ package stake
import ( import (
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
abci "github.com/tendermint/abci/types"
) )
const ( const (
@ -12,30 +11,6 @@ const (
var hrsPerYrRat = sdk.NewRat(hrsPerYr) // as defined by a julian year of 365.25 days var hrsPerYrRat = sdk.NewRat(hrsPerYr) // as defined by a julian year of 365.25 days
// Tick - called at the end of every block
func (k Keeper) Tick(ctx sdk.Context) (change []abci.Validator) {
p := k.GetPool(ctx)
// Process Validator Provisions
blockTime := ctx.BlockHeader().Time // XXX assuming in seconds, confirm
if p.InflationLastTime+blockTime >= 3600 {
p.InflationLastTime = blockTime
p = k.processProvisions(ctx)
}
// save the params
k.setPool(ctx, p)
// reset the intra-transaction counter
k.setIntraTxCounter(ctx, 0)
// calculate validator set changes
change = k.getTendermintUpdates(ctx)
k.clearTendermintUpdates(ctx)
return change
}
// process provisions for an hour period // process provisions for an hour period
func (k Keeper) processProvisions(ctx sdk.Context) Pool { func (k Keeper) processProvisions(ctx sdk.Context) Pool {

View File

@ -636,9 +636,9 @@ func (k Keeper) getPool(store sdk.KVStore) (pool Pool) {
return return
} }
func (k Keeper) setPool(ctx sdk.Context, p Pool) { func (k Keeper) setPool(ctx sdk.Context, pool Pool) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
b := k.cdc.MustMarshalBinary(p) b := k.cdc.MustMarshalBinary(pool)
store.Set(PoolKey, b) store.Set(PoolKey, b)
} }