everything but IBC module

This commit is contained in:
Sunny Aggarwal 2018-03-21 23:21:46 +01:00
parent 2fc5cc6bcd
commit 131289ce70
9 changed files with 226 additions and 217 deletions

View File

@ -59,12 +59,12 @@ func NewBasecoinApp(logger log.Logger, db dbm.DB) *BasecoinApp {
coinKeeper := bank.NewCoinKeeper(app.accountMapper) coinKeeper := bank.NewCoinKeeper(app.accountMapper)
coolKeeper := cool.NewKeeper(app.capKeyMainStore, coinKeeper) coolKeeper := cool.NewKeeper(app.capKeyMainStore, coinKeeper)
ibcMapper := ibc.NewIBCMapper(app.cdc, app.capKeyIBCStore) ibcMapper := ibc.NewIBCMapper(app.cdc, app.capKeyIBCStore)
stakingMapper := staking.NewMapper(app.capKeyStakingStore) stakeKeeper := staking.NewKeeper(app.capKeyStakingStore, coinKeeper)
app.Router(). app.Router().
AddRoute("bank", coinKeeper.Handler). AddRoute("bank", coinKeeper.Handler).
AddRoute("cool", coolKeeper.Handler). AddRoute("cool", coolKeeper.Handler).
AddRoute("ibc", ibc.NewHandler(ibcMapper, coinKeeper)). AddRoute("ibc", ibc.NewHandler(ibcMapper, coinKeeper)).
AddRoute("staking", staking.NewHandler(stakingMapper, coinKeeper)) AddRoute("staking", stakeKeeper.Handler)
// initialize BaseApp // initialize BaseApp
app.SetTxDecoder(app.txDecoder) app.SetTxDecoder(app.txDecoder)

View File

@ -6,11 +6,16 @@ import (
const ( const (
// Staking errors reserve 300 - 399. // Staking errors reserve 300 - 399.
CodeEmptyValidator sdk.CodeType = 300 CodeEmptyValidator sdk.CodeType = 300
CodeInvalidUnbond sdk.CodeType = 301 CodeInvalidUnbond sdk.CodeType = 301
CodeEmptyStake sdk.CodeType = 302 CodeEmptyStake sdk.CodeType = 302
CodeIncorrectStakingToken sdk.CodeType = 303
) )
func ErrIncorrectStakingToken() sdk.Error {
return newError(CodeIncorrectStakingToken, "")
}
func ErrEmptyValidator() sdk.Error { func ErrEmptyValidator() sdk.Error {
return newError(CodeEmptyValidator, "") return newError(CodeEmptyValidator, "")
} }

View File

@ -4,29 +4,21 @@ import (
abci "github.com/tendermint/abci/types" abci "github.com/tendermint/abci/types"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/bank"
) )
func NewHandler(sm StakingMapper, ck bank.CoinKeeper) sdk.Handler { func (k Keeper) Handler(ctx sdk.Context, msg sdk.Msg) sdk.Result {
return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { switch msg := msg.(type) {
switch msg := msg.(type) { case BondMsg:
case BondMsg: return handleBondMsg(ctx, k, msg)
return handleBondMsg(ctx, sm, ck, msg) case UnbondMsg:
case UnbondMsg: return handleUnbondMsg(ctx, k, msg)
return handleUnbondMsg(ctx, sm, ck, msg) default:
default: return sdk.ErrUnknownRequest("No match for message type.").Result()
return sdk.ErrUnknownRequest("No match for message type.").Result()
}
} }
} }
func handleBondMsg(ctx sdk.Context, sm StakingMapper, ck bank.CoinKeeper, msg BondMsg) sdk.Result { func handleBondMsg(ctx sdk.Context, k Keeper, msg BondMsg) sdk.Result {
_, err := ck.SubtractCoins(ctx, msg.Address, []sdk.Coin{msg.Stake}) _, err := k.Bond(ctx, msg.Address, msg.Stake)
if err != nil {
return err.Result()
}
power, err := sm.Bond(ctx, msg.Address, msg.PubKey, msg.Stake.Amount)
if err != nil { if err != nil {
return err.Result() return err.Result()
} }
@ -42,8 +34,8 @@ func handleBondMsg(ctx sdk.Context, sm StakingMapper, ck bank.CoinKeeper, msg Bo
} }
} }
func handleUnbondMsg(ctx sdk.Context, sm StakingMapper, ck bank.CoinKeeper, msg UnbondMsg) sdk.Result { func handleUnbondMsg(ctx sdk.Context, k Keeper, msg UnbondMsg) sdk.Result {
pubKey, power, err := sm.Unbond(ctx, msg.Address) pubKey, power, err := k.Unbond(ctx, msg.Address)
if err != nil { if err != nil {
return err.Result() return err.Result()
} }
@ -52,7 +44,7 @@ func handleUnbondMsg(ctx sdk.Context, sm StakingMapper, ck bank.CoinKeeper, msg
Denom: "mycoin", Denom: "mycoin",
Amount: power, Amount: power,
} }
_, err = ck.AddCoins(ctx, msg.Address, sdk.Coins{stake}) _, err = k.ck.AddCoins(ctx, msg.Address, sdk.Coins{stake})
if err != nil { if err != nil {
return err.Result() return err.Result()
} }

88
x/staking/keeper.go Normal file
View File

@ -0,0 +1,88 @@
package staking
import (
crypto "github.com/tendermint/go-crypto"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/wire"
"github.com/cosmos/cosmos-sdk/x/bank"
)
const stakingToken = "steak"
type Keeper struct {
ck bank.CoinKeeper
key sdk.StoreKey
cdc *wire.Codec
}
func NewKeeper(key sdk.StoreKey, coinKeeper bank.CoinKeeper) Keeper {
cdc := wire.NewCodec()
return Keeper{
key: key,
cdc: cdc,
ck: coinKeeper,
}
}
func (k Keeper) getBondInfo(ctx sdk.Context, addr sdk.Address) bondInfo {
store := ctx.KVStore(k.key)
bz := store.Get(addr)
if bz == nil {
return bondInfo{}
}
var bi bondInfo
err := k.cdc.UnmarshalBinary(bz, &bi)
if err != nil {
panic(err)
}
return bi
}
func (k Keeper) setBondInfo(ctx sdk.Context, addr sdk.Address, bi bondInfo) {
store := ctx.KVStore(k.key)
bz, err := k.cdc.MarshalBinary(bi)
if err != nil {
panic(err)
}
store.Set(addr, bz)
}
func (k Keeper) deleteBondInfo(ctx sdk.Context, addr sdk.Address) {
store := ctx.KVStore(k.key)
store.Delete(addr)
}
func (k Keeper) Bond(ctx sdk.Context, addr sdk.Address, pubKey crypto.PubKey, stake sdk.Coin) (int64, sdk.Error) {
if stake.Denom != stakingToken {
return 0, ErrIncorrectStakingToken()
}
_, err := k.ck.SubtractCoins(ctx, addr, []sdk.Coin{stake})
if err != nil {
return 0, err
}
bi := k.getBondInfo(ctx, addr)
if bi.isEmpty() {
bi = bondInfo{
PubKey: pubKey,
Power: 0,
}
}
bi.Power = bi.Power + stake.Amount
k.setBondInfo(ctx, addr, bi)
return bi.Power, nil
}
func (k Keeper) Unbond(ctx sdk.Context, addr sdk.Address) (crypto.PubKey, int64, sdk.Error) {
bi := k.getBondInfo(ctx, addr)
if bi.isEmpty() {
return crypto.PubKey{}, 0, ErrInvalidUnbond()
}
k.deleteBondInfo(ctx, addr)
return bi.PubKey, bi.Power, nil
}

View File

@ -13,6 +13,7 @@ import (
"github.com/cosmos/cosmos-sdk/store" "github.com/cosmos/cosmos-sdk/store"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/bank"
) )
func setupMultiStore() (sdk.MultiStore, *sdk.KVStoreKey) { func setupMultiStore() (sdk.MultiStore, *sdk.KVStoreKey) {
@ -24,14 +25,14 @@ func setupMultiStore() (sdk.MultiStore, *sdk.KVStoreKey) {
return ms, capKey return ms, capKey
} }
func TestStakingMapperGetSet(t *testing.T) { func TestKeeperGetSet(t *testing.T) {
ms, capKey := setupMultiStore() ms, capKey := setupMultiStore()
ctx := sdk.NewContext(ms, abci.Header{}, false, nil) ctx := sdk.NewContext(ms, abci.Header{}, false, nil)
stakingMapper := NewMapper(capKey) stakeKeeper := NewKeeper(capKey, bank.NewCoinKeeper(nil))
addr := sdk.Address([]byte("some-address")) addr := sdk.Address([]byte("some-address"))
bi := stakingMapper.getBondInfo(ctx, addr) bi := stakeKeeper.getBondInfo(ctx, addr)
assert.Equal(t, bi, bondInfo{}) assert.Equal(t, bi, bondInfo{})
privKey := crypto.GenPrivKeyEd25519() privKey := crypto.GenPrivKeyEd25519()
@ -41,9 +42,9 @@ func TestStakingMapperGetSet(t *testing.T) {
Power: int64(10), Power: int64(10),
} }
fmt.Printf("Pubkey: %v\n", privKey.PubKey()) fmt.Printf("Pubkey: %v\n", privKey.PubKey())
stakingMapper.setBondInfo(ctx, addr, bi) stakeKeeper.setBondInfo(ctx, addr, bi)
savedBi := stakingMapper.getBondInfo(ctx, addr) savedBi := stakeKeeper.getBondInfo(ctx, addr)
assert.NotNil(t, savedBi) assert.NotNil(t, savedBi)
fmt.Printf("Bond Info: %v\n", savedBi) fmt.Printf("Bond Info: %v\n", savedBi)
assert.Equal(t, int64(10), savedBi.Power) assert.Equal(t, int64(10), savedBi.Power)
@ -53,24 +54,24 @@ func TestBonding(t *testing.T) {
ms, capKey := setupMultiStore() ms, capKey := setupMultiStore()
ctx := sdk.NewContext(ms, abci.Header{}, false, nil) ctx := sdk.NewContext(ms, abci.Header{}, false, nil)
stakingMapper := NewMapper(capKey) stakeKeeper := NewKeeper(capKey, bank.NewCoinKeeper(nil))
addr := sdk.Address([]byte("some-address")) addr := sdk.Address([]byte("some-address"))
privKey := crypto.GenPrivKeyEd25519() privKey := crypto.GenPrivKeyEd25519()
pubKey := privKey.PubKey() pubKey := privKey.PubKey()
_, _, err := stakingMapper.Unbond(ctx, addr) _, _, err := stakeKeeper.Unbond(ctx, addr)
assert.Equal(t, err, ErrInvalidUnbond()) assert.Equal(t, err, ErrInvalidUnbond())
_, err = stakingMapper.Bond(ctx, addr, pubKey, 10) _, err = stakeKeeper.Bond(ctx, addr, pubKey, 10)
assert.Nil(t, err) assert.Nil(t, err)
power, err := stakingMapper.Bond(ctx, addr, pubKey, 10) power, err := stakeKeeper.Bond(ctx, addr, pubKey, 10)
assert.Equal(t, int64(20), power) assert.Equal(t, int64(20), power)
pk, _, err := stakingMapper.Unbond(ctx, addr) pk, _, err := stakeKeeper.Unbond(ctx, addr)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, pubKey, pk) assert.Equal(t, pubKey, pk)
_, _, err = stakingMapper.Unbond(ctx, addr) _, _, err = stakeKeeper.Unbond(ctx, addr)
assert.Equal(t, err, ErrInvalidUnbond()) assert.Equal(t, err, ErrInvalidUnbond())
} }

View File

@ -1,92 +0,0 @@
package staking
import (
crypto "github.com/tendermint/go-crypto"
sdk "github.com/cosmos/cosmos-sdk/types"
wire "github.com/cosmos/cosmos-sdk/wire"
)
type StakingMapper struct {
key sdk.StoreKey
cdc *wire.Codec
}
func NewMapper(key sdk.StoreKey) StakingMapper {
cdc := wire.NewCodec()
return StakingMapper{
key: key,
cdc: cdc,
}
}
func (sm StakingMapper) getBondInfo(ctx sdk.Context, addr sdk.Address) bondInfo {
store := ctx.KVStore(sm.key)
bz := store.Get(addr)
if bz == nil {
return bondInfo{}
}
var bi bondInfo
err := sm.cdc.UnmarshalBinary(bz, &bi)
if err != nil {
panic(err)
}
return bi
}
func (sm StakingMapper) setBondInfo(ctx sdk.Context, addr sdk.Address, bi bondInfo) {
store := ctx.KVStore(sm.key)
bz, err := sm.cdc.MarshalBinary(bi)
if err != nil {
panic(err)
}
store.Set(addr, bz)
}
func (sm StakingMapper) deleteBondInfo(ctx sdk.Context, addr sdk.Address) {
store := ctx.KVStore(sm.key)
store.Delete(addr)
}
func (sm StakingMapper) Bond(ctx sdk.Context, addr sdk.Address, pubKey crypto.PubKey, power int64) (int64, sdk.Error) {
bi := sm.getBondInfo(ctx, addr)
if bi.isEmpty() {
bi = bondInfo{
PubKey: pubKey,
Power: power,
}
sm.setBondInfo(ctx, addr, bi)
return bi.Power, nil
}
newPower := bi.Power + power
newBi := bondInfo{
PubKey: bi.PubKey,
Power: newPower,
}
sm.setBondInfo(ctx, addr, newBi)
return newBi.Power, nil
}
func (sm StakingMapper) Unbond(ctx sdk.Context, addr sdk.Address) (crypto.PubKey, int64, sdk.Error) {
bi := sm.getBondInfo(ctx, addr)
if bi.isEmpty() {
return crypto.PubKey{}, 0, ErrInvalidUnbond()
}
sm.deleteBondInfo(ctx, addr)
return bi.PubKey, bi.Power, nil
}
type bondInfo struct {
PubKey crypto.PubKey
Power int64
}
func (bi bondInfo) isEmpty() bool {
if bi == (bondInfo{}) {
return true
}
return false
}

95
x/staking/msgs.go Normal file
View File

@ -0,0 +1,95 @@
package staking
import (
"encoding/json"
crypto "github.com/tendermint/go-crypto"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// -------------------------
// BondMsg
type BondMsg struct {
Address sdk.Address `json:"address"`
Stake sdk.Coin `json:"coins"`
PubKey crypto.PubKey `json:"pub_key"`
}
func NewBondMsg(addr sdk.Address, stake sdk.Coin, pubKey crypto.PubKey) BondMsg {
return BondMsg{
Address: addr,
Stake: stake,
PubKey: pubKey,
}
}
func (msg BondMsg) Type() string {
return "staking"
}
func (msg BondMsg) ValidateBasic() sdk.Error {
if msg.Stake.IsZero() {
return ErrEmptyStake()
}
if msg.PubKey.Empty() {
return sdk.ErrInvalidPubKey("BondMsg.PubKey must not be empty")
}
return nil
}
func (msg BondMsg) Get(key interface{}) interface{} {
return nil
}
func (msg BondMsg) GetSignBytes() []byte {
bz, err := json.Marshal(msg)
if err != nil {
panic(err)
}
return bz
}
func (msg BondMsg) GetSigners() []sdk.Address {
return []sdk.Address{msg.Address}
}
// -------------------------
// UnbondMsg
type UnbondMsg struct {
Address sdk.Address `json:"address"`
}
func NewUnbondMsg(addr sdk.Address) UnbondMsg {
return UnbondMsg{
Address: addr,
}
}
func (msg UnbondMsg) Type() string {
return "staking"
}
func (msg UnbondMsg) ValidateBasic() sdk.Error {
return nil
}
func (msg UnbondMsg) Get(key interface{}) interface{} {
return nil
}
func (msg UnbondMsg) GetSignBytes() []byte {
bz, err := json.Marshal(msg)
if err != nil {
panic(err)
}
return bz
}
func (msg UnbondMsg) GetSigners() []sdk.Address {
return []sdk.Address{msg.Address}
}

View File

@ -1,95 +1,15 @@
package staking package staking
import ( import crypto "github.com/tendermint/go-crypto"
"encoding/json"
crypto "github.com/tendermint/go-crypto" type bondInfo struct {
PubKey crypto.PubKey
sdk "github.com/cosmos/cosmos-sdk/types" Power int64
)
// -------------------------
// BondMsg
type BondMsg struct {
Address sdk.Address `json:"address"`
Stake sdk.Coin `json:"coins"`
PubKey crypto.PubKey `json:"pub_key"`
} }
func NewBondMsg(addr sdk.Address, stake sdk.Coin, pubKey crypto.PubKey) BondMsg { func (bi bondInfo) isEmpty() bool {
return BondMsg{ if bi == (bondInfo{}) {
Address: addr, return true
Stake: stake,
PubKey: pubKey,
} }
} return false
func (msg BondMsg) Type() string {
return "staking"
}
func (msg BondMsg) ValidateBasic() sdk.Error {
if msg.Stake.IsZero() {
return ErrEmptyStake()
}
if msg.PubKey.Empty() {
return sdk.ErrInvalidPubKey("BondMsg.PubKey must not be empty")
}
return nil
}
func (msg BondMsg) Get(key interface{}) interface{} {
return nil
}
func (msg BondMsg) GetSignBytes() []byte {
bz, err := json.Marshal(msg)
if err != nil {
panic(err)
}
return bz
}
func (msg BondMsg) GetSigners() []sdk.Address {
return []sdk.Address{msg.Address}
}
// -------------------------
// UnbondMsg
type UnbondMsg struct {
Address sdk.Address `json:"address"`
}
func NewUnbondMsg(addr sdk.Address) UnbondMsg {
return UnbondMsg{
Address: addr,
}
}
func (msg UnbondMsg) Type() string {
return "staking"
}
func (msg UnbondMsg) ValidateBasic() sdk.Error {
return nil
}
func (msg UnbondMsg) Get(key interface{}) interface{} {
return nil
}
func (msg UnbondMsg) GetSignBytes() []byte {
bz, err := json.Marshal(msg)
if err != nil {
panic(err)
}
return bz
}
func (msg UnbondMsg) GetSigners() []sdk.Address {
return []sdk.Address{msg.Address}
} }