cleanup, move simplestaking to democoin
This commit is contained in:
@@ -12,11 +12,11 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc"
|
||||
"github.com/cosmos/cosmos-sdk/x/simplestake"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/examples/democoin/types"
|
||||
"github.com/cosmos/cosmos-sdk/examples/democoin/x/cool"
|
||||
"github.com/cosmos/cosmos-sdk/examples/democoin/x/pow"
|
||||
"github.com/cosmos/cosmos-sdk/examples/democoin/x/simplestake"
|
||||
"github.com/cosmos/cosmos-sdk/examples/democoin/x/sketchy"
|
||||
)
|
||||
|
||||
@@ -38,9 +38,6 @@ type DemocoinApp struct {
|
||||
|
||||
// Manage getting and setting accounts
|
||||
accountMapper sdk.AccountMapper
|
||||
|
||||
// Handle fees
|
||||
feeHandler sdk.FeeHandler
|
||||
}
|
||||
|
||||
func NewDemocoinApp(logger log.Logger, db dbm.DB) *DemocoinApp {
|
||||
@@ -50,7 +47,7 @@ func NewDemocoinApp(logger log.Logger, db dbm.DB) *DemocoinApp {
|
||||
|
||||
// Create your application object.
|
||||
var app = &DemocoinApp{
|
||||
BaseApp: bam.NewBaseApp(appName, logger, db),
|
||||
BaseApp: bam.NewBaseApp(appName, cdc, logger, db),
|
||||
cdc: cdc,
|
||||
capKeyMainStore: sdk.NewKVStoreKey("main"),
|
||||
capKeyAccountStore: sdk.NewKVStoreKey("acc"),
|
||||
@@ -80,65 +77,34 @@ func NewDemocoinApp(logger log.Logger, db dbm.DB) *DemocoinApp {
|
||||
AddRoute("ibc", ibc.NewHandler(ibcMapper, coinKeeper)).
|
||||
AddRoute("simplestake", simplestake.NewHandler(stakeKeeper))
|
||||
|
||||
// Define the feeHandler.
|
||||
app.feeHandler = auth.BurnFeeHandler
|
||||
|
||||
// Initialize BaseApp.
|
||||
app.SetTxDecoder(app.txDecoder)
|
||||
app.SetInitChainer(app.initChainerFn(coolKeeper, powKeeper))
|
||||
app.MountStoresIAVL(app.capKeyMainStore, app.capKeyAccountStore, app.capKeyPowStore, app.capKeyIBCStore, app.capKeyStakingStore)
|
||||
app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, app.feeHandler))
|
||||
app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, auth.BurnFeeHandler))
|
||||
err := app.LoadLatestVersion(app.capKeyMainStore)
|
||||
if err != nil {
|
||||
cmn.Exit(err.Error())
|
||||
}
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
// custom tx codec
|
||||
func MakeCodec() *wire.Codec {
|
||||
var cdc = wire.NewCodec()
|
||||
|
||||
// Register Msgs
|
||||
cdc.RegisterInterface((*sdk.Msg)(nil), nil)
|
||||
cdc.RegisterConcrete(bank.MsgSend{}, "democoin/Send", nil)
|
||||
cdc.RegisterConcrete(bank.MsgIssue{}, "democoin/Issue", nil)
|
||||
cdc.RegisterConcrete(cool.MsgQuiz{}, "democoin/Quiz", nil)
|
||||
cdc.RegisterConcrete(cool.MsgSetTrend{}, "democoin/SetTrend", nil)
|
||||
cdc.RegisterConcrete(pow.MsgMine{}, "democoin/Mine", nil)
|
||||
cdc.RegisterConcrete(ibc.IBCTransferMsg{}, "democoin/IBCTransferMsg", nil)
|
||||
cdc.RegisterConcrete(ibc.IBCReceiveMsg{}, "democoin/IBCReceiveMsg", nil)
|
||||
cdc.RegisterConcrete(simplestake.MsgBond{}, "democoin/BondMsg", nil)
|
||||
cdc.RegisterConcrete(simplestake.MsgUnbond{}, "democoin/UnbondMsg", nil)
|
||||
wire.RegisterCrypto(cdc) // Register crypto.
|
||||
sdk.RegisterWire(cdc) // Register Msgs
|
||||
cool.RegisterWire(cdc)
|
||||
pow.RegisterWire(cdc)
|
||||
bank.RegisterWire(cdc)
|
||||
ibc.RegisterWire(cdc)
|
||||
simplestake.RegisterWire(cdc)
|
||||
|
||||
// Register AppAccount
|
||||
cdc.RegisterInterface((*sdk.Account)(nil), nil)
|
||||
cdc.RegisterConcrete(&types.AppAccount{}, "democoin/Account", nil)
|
||||
|
||||
// Register crypto.
|
||||
wire.RegisterCrypto(cdc)
|
||||
|
||||
return cdc
|
||||
}
|
||||
|
||||
// custom logic for transaction decoding
|
||||
func (app *DemocoinApp) txDecoder(txBytes []byte) (sdk.Tx, sdk.Error) {
|
||||
var tx = sdk.StdTx{}
|
||||
|
||||
if len(txBytes) == 0 {
|
||||
return nil, sdk.ErrTxDecode("txBytes are empty")
|
||||
}
|
||||
|
||||
// StdTx.Msg is an interface. The concrete types
|
||||
// are registered by MakeTxCodec in bank.RegisterWire.
|
||||
err := app.cdc.UnmarshalBinary(txBytes, &tx)
|
||||
if err != nil {
|
||||
return nil, sdk.ErrTxDecode("").Trace(err.Error())
|
||||
}
|
||||
return tx, nil
|
||||
}
|
||||
|
||||
// custom logic for democoin initialization
|
||||
func (app *DemocoinApp) initChainerFn(coolKeeper cool.Keeper, powKeeper pow.Keeper) sdk.InitChainer {
|
||||
return func(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
|
||||
|
||||
@@ -17,12 +17,12 @@ import (
|
||||
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
|
||||
bankcmd "github.com/cosmos/cosmos-sdk/x/bank/client/cli"
|
||||
ibccmd "github.com/cosmos/cosmos-sdk/x/ibc/client/cli"
|
||||
simplestakingcmd "github.com/cosmos/cosmos-sdk/x/simplestake/client/cli"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/examples/democoin/app"
|
||||
"github.com/cosmos/cosmos-sdk/examples/democoin/types"
|
||||
coolcmd "github.com/cosmos/cosmos-sdk/examples/democoin/x/cool/client/cli"
|
||||
powcmd "github.com/cosmos/cosmos-sdk/examples/democoin/x/pow/client/cli"
|
||||
simplestakingcmd "github.com/cosmos/cosmos-sdk/examples/democoin/x/simplestake/client/cli"
|
||||
)
|
||||
|
||||
// rootCmd is the entry point for this binary
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package cool
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/wire"
|
||||
)
|
||||
|
||||
// Register concrete types on wire codec
|
||||
func RegisterWire(cdc *wire.Codec) {
|
||||
cdc.RegisterConcrete(MsgQuiz{}, "cool/Quiz", nil)
|
||||
cdc.RegisterConcrete(MsgSetTrend{}, "cool/SetTrend", nil)
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package pow
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/wire"
|
||||
)
|
||||
|
||||
// Register concrete types on wire codec
|
||||
func RegisterWire(cdc *wire.Codec) {
|
||||
cdc.RegisterConcrete(MsgMine{}, "pow/Mine", nil)
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/context"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/wire"
|
||||
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/examples/democoin/x/simplestake"
|
||||
)
|
||||
|
||||
const (
|
||||
flagStake = "stake"
|
||||
flagValidator = "validator"
|
||||
)
|
||||
|
||||
// simple bond tx
|
||||
func BondTxCmd(cdc *wire.Codec) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "bond",
|
||||
Short: "Bond to a validator",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
ctx := context.NewCoreContextFromViper()
|
||||
|
||||
from, err := ctx.GetFromAddress()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
stakeString := viper.GetString(flagStake)
|
||||
if len(stakeString) == 0 {
|
||||
return fmt.Errorf("specify coins to bond with --stake")
|
||||
}
|
||||
|
||||
valString := viper.GetString(flagValidator)
|
||||
if len(valString) == 0 {
|
||||
return fmt.Errorf("specify pubkey to bond to with --validator")
|
||||
}
|
||||
|
||||
stake, err := sdk.ParseCoin(stakeString)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: bech32 ...
|
||||
rawPubKey, err := hex.DecodeString(valString)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var pubKeyEd crypto.PubKeyEd25519
|
||||
copy(pubKeyEd[:], rawPubKey)
|
||||
|
||||
msg := simplestake.NewMsgBond(from, stake, pubKeyEd)
|
||||
|
||||
return sendMsg(cdc, msg)
|
||||
},
|
||||
}
|
||||
cmd.Flags().String(flagStake, "", "Amount of coins to stake")
|
||||
cmd.Flags().String(flagValidator, "", "Validator address to stake")
|
||||
return cmd
|
||||
}
|
||||
|
||||
// simple unbond tx
|
||||
func UnbondTxCmd(cdc *wire.Codec) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "unbond",
|
||||
Short: "Unbond from a validator",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
from, err := context.NewCoreContextFromViper().GetFromAddress()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
msg := simplestake.NewMsgUnbond(from)
|
||||
return sendMsg(cdc, msg)
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func sendMsg(cdc *wire.Codec, msg sdk.Msg) error {
|
||||
ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc))
|
||||
res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, msg, cdc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Committed at block %d. Hash: %s\n", res.Height, res.Hash.String())
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package simplestake
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// simple stake errors reserve 300 ~ 399.
|
||||
const (
|
||||
DefaultCodespace sdk.CodespaceType = 4
|
||||
|
||||
// simplestake errors reserve 300 - 399.
|
||||
CodeEmptyValidator sdk.CodeType = 300
|
||||
CodeInvalidUnbond sdk.CodeType = 301
|
||||
CodeEmptyStake sdk.CodeType = 302
|
||||
CodeIncorrectStakingToken sdk.CodeType = 303
|
||||
)
|
||||
|
||||
// nolint
|
||||
func ErrIncorrectStakingToken(codespace sdk.CodespaceType) sdk.Error {
|
||||
return newError(codespace, CodeIncorrectStakingToken, "")
|
||||
}
|
||||
func ErrEmptyValidator(codespace sdk.CodespaceType) sdk.Error {
|
||||
return newError(codespace, CodeEmptyValidator, "")
|
||||
}
|
||||
func ErrInvalidUnbond(codespace sdk.CodespaceType) sdk.Error {
|
||||
return newError(codespace, CodeInvalidUnbond, "")
|
||||
}
|
||||
func ErrEmptyStake(codespace sdk.CodespaceType) sdk.Error {
|
||||
return newError(codespace, CodeEmptyStake, "")
|
||||
}
|
||||
|
||||
// -----------------------------
|
||||
// Helpers
|
||||
|
||||
func newError(codespace sdk.CodespaceType, code sdk.CodeType, msg string) sdk.Error {
|
||||
return sdk.NewError(codespace, code, msg)
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package simplestake
|
||||
|
||||
import (
|
||||
abci "github.com/tendermint/abci/types"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// NewHandler returns a handler for "simplestake" type messages.
|
||||
func NewHandler(k Keeper) sdk.Handler {
|
||||
return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
|
||||
switch msg := msg.(type) {
|
||||
case MsgBond:
|
||||
return handleMsgBond(ctx, k, msg)
|
||||
case MsgUnbond:
|
||||
return handleMsgUnbond(ctx, k, msg)
|
||||
default:
|
||||
return sdk.ErrUnknownRequest("No match for message type.").Result()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func handleMsgBond(ctx sdk.Context, k Keeper, msg MsgBond) sdk.Result {
|
||||
power, err := k.Bond(ctx, msg.Address, msg.PubKey, msg.Stake)
|
||||
if err != nil {
|
||||
return err.Result()
|
||||
}
|
||||
|
||||
valSet := abci.Validator{
|
||||
PubKey: msg.PubKey.Bytes(),
|
||||
Power: power,
|
||||
}
|
||||
|
||||
return sdk.Result{
|
||||
Code: sdk.ABCICodeOK,
|
||||
ValidatorUpdates: abci.Validators{valSet},
|
||||
}
|
||||
}
|
||||
|
||||
func handleMsgUnbond(ctx sdk.Context, k Keeper, msg MsgUnbond) sdk.Result {
|
||||
pubKey, _, err := k.Unbond(ctx, msg.Address)
|
||||
if err != nil {
|
||||
return err.Result()
|
||||
}
|
||||
|
||||
valSet := abci.Validator{
|
||||
PubKey: pubKey.Bytes(),
|
||||
Power: int64(0),
|
||||
}
|
||||
|
||||
return sdk.Result{
|
||||
Code: sdk.ABCICodeOK,
|
||||
ValidatorUpdates: abci.Validators{valSet},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
package simplestake
|
||||
|
||||
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"
|
||||
|
||||
const moduleName = "simplestake"
|
||||
|
||||
// simple stake keeper
|
||||
type Keeper struct {
|
||||
ck bank.Keeper
|
||||
|
||||
key sdk.StoreKey
|
||||
cdc *wire.Codec
|
||||
codespace sdk.CodespaceType
|
||||
}
|
||||
|
||||
func NewKeeper(key sdk.StoreKey, coinKeeper bank.Keeper, codespace sdk.CodespaceType) Keeper {
|
||||
cdc := wire.NewCodec()
|
||||
wire.RegisterCrypto(cdc)
|
||||
return Keeper{
|
||||
key: key,
|
||||
cdc: cdc,
|
||||
ck: coinKeeper,
|
||||
codespace: codespace,
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
// register a bond with the keeper
|
||||
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(k.codespace)
|
||||
}
|
||||
|
||||
_, 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
|
||||
}
|
||||
|
||||
// register an unbond with the keeper
|
||||
func (k Keeper) Unbond(ctx sdk.Context, addr sdk.Address) (crypto.PubKey, int64, sdk.Error) {
|
||||
bi := k.getBondInfo(ctx, addr)
|
||||
if bi.isEmpty() {
|
||||
return nil, 0, ErrInvalidUnbond(k.codespace)
|
||||
}
|
||||
k.deleteBondInfo(ctx, addr)
|
||||
|
||||
returnedBond := sdk.Coin{stakingToken, bi.Power}
|
||||
|
||||
_, err := k.ck.AddCoins(ctx, addr, []sdk.Coin{returnedBond})
|
||||
if err != nil {
|
||||
return bi.PubKey, bi.Power, err
|
||||
}
|
||||
|
||||
return bi.PubKey, bi.Power, nil
|
||||
}
|
||||
|
||||
// FOR TESTING PURPOSES -------------------------------------------------
|
||||
|
||||
func (k Keeper) bondWithoutCoins(ctx sdk.Context, addr sdk.Address, pubKey crypto.PubKey, stake sdk.Coin) (int64, sdk.Error) {
|
||||
if stake.Denom != stakingToken {
|
||||
return 0, ErrIncorrectStakingToken(k.codespace)
|
||||
}
|
||||
|
||||
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) unbondWithoutCoins(ctx sdk.Context, addr sdk.Address) (crypto.PubKey, int64, sdk.Error) {
|
||||
bi := k.getBondInfo(ctx, addr)
|
||||
if bi.isEmpty() {
|
||||
return nil, 0, ErrInvalidUnbond(k.codespace)
|
||||
}
|
||||
k.deleteBondInfo(ctx, addr)
|
||||
|
||||
return bi.PubKey, bi.Power, nil
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package simplestake
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
abci "github.com/tendermint/abci/types"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
dbm "github.com/tendermint/tmlibs/db"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/store"
|
||||
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/bank"
|
||||
)
|
||||
|
||||
func setupMultiStore() (sdk.MultiStore, *sdk.KVStoreKey, *sdk.KVStoreKey) {
|
||||
db := dbm.NewMemDB()
|
||||
authKey := sdk.NewKVStoreKey("authkey")
|
||||
capKey := sdk.NewKVStoreKey("capkey")
|
||||
ms := store.NewCommitMultiStore(db)
|
||||
ms.MountStoreWithDB(capKey, sdk.StoreTypeIAVL, db)
|
||||
ms.MountStoreWithDB(authKey, sdk.StoreTypeIAVL, db)
|
||||
ms.LoadLatestVersion()
|
||||
return ms, authKey, capKey
|
||||
}
|
||||
|
||||
func TestKeeperGetSet(t *testing.T) {
|
||||
ms, _, capKey := setupMultiStore()
|
||||
|
||||
ctx := sdk.NewContext(ms, abci.Header{}, false, nil)
|
||||
stakeKeeper := NewKeeper(capKey, bank.NewKeeper(nil), DefaultCodespace)
|
||||
addr := sdk.Address([]byte("some-address"))
|
||||
|
||||
bi := stakeKeeper.getBondInfo(ctx, addr)
|
||||
assert.Equal(t, bi, bondInfo{})
|
||||
|
||||
privKey := crypto.GenPrivKeyEd25519()
|
||||
|
||||
bi = bondInfo{
|
||||
PubKey: privKey.PubKey(),
|
||||
Power: int64(10),
|
||||
}
|
||||
fmt.Printf("Pubkey: %v\n", privKey.PubKey())
|
||||
stakeKeeper.setBondInfo(ctx, addr, bi)
|
||||
|
||||
savedBi := stakeKeeper.getBondInfo(ctx, addr)
|
||||
assert.NotNil(t, savedBi)
|
||||
fmt.Printf("Bond Info: %v\n", savedBi)
|
||||
assert.Equal(t, int64(10), savedBi.Power)
|
||||
}
|
||||
|
||||
func TestBonding(t *testing.T) {
|
||||
ms, authKey, capKey := setupMultiStore()
|
||||
cdc := wire.NewCodec()
|
||||
auth.RegisterBaseAccount(cdc)
|
||||
|
||||
ctx := sdk.NewContext(ms, abci.Header{}, false, nil)
|
||||
|
||||
accountMapper := auth.NewAccountMapper(cdc, authKey, &auth.BaseAccount{})
|
||||
coinKeeper := bank.NewKeeper(accountMapper)
|
||||
stakeKeeper := NewKeeper(capKey, coinKeeper, DefaultCodespace)
|
||||
addr := sdk.Address([]byte("some-address"))
|
||||
privKey := crypto.GenPrivKeyEd25519()
|
||||
pubKey := privKey.PubKey()
|
||||
|
||||
_, _, err := stakeKeeper.unbondWithoutCoins(ctx, addr)
|
||||
assert.Equal(t, err, ErrInvalidUnbond(DefaultCodespace))
|
||||
|
||||
_, err = stakeKeeper.bondWithoutCoins(ctx, addr, pubKey, sdk.Coin{"steak", 10})
|
||||
assert.Nil(t, err)
|
||||
|
||||
power, err := stakeKeeper.bondWithoutCoins(ctx, addr, pubKey, sdk.Coin{"steak", 10})
|
||||
assert.Equal(t, int64(20), power)
|
||||
|
||||
pk, _, err := stakeKeeper.unbondWithoutCoins(ctx, addr)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, pubKey, pk)
|
||||
|
||||
_, _, err = stakeKeeper.unbondWithoutCoins(ctx, addr)
|
||||
assert.Equal(t, err, ErrInvalidUnbond(DefaultCodespace))
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package simplestake
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
//_________________________________________________________----
|
||||
|
||||
// simple bond message
|
||||
type MsgBond struct {
|
||||
Address sdk.Address `json:"address"`
|
||||
Stake sdk.Coin `json:"coins"`
|
||||
PubKey crypto.PubKey `json:"pub_key"`
|
||||
}
|
||||
|
||||
func NewMsgBond(addr sdk.Address, stake sdk.Coin, pubKey crypto.PubKey) MsgBond {
|
||||
return MsgBond{
|
||||
Address: addr,
|
||||
Stake: stake,
|
||||
PubKey: pubKey,
|
||||
}
|
||||
}
|
||||
|
||||
//nolint
|
||||
func (msg MsgBond) Type() string { return moduleName } //TODO update "stake/declarecandidacy"
|
||||
func (msg MsgBond) Get(key interface{}) (value interface{}) { return nil }
|
||||
func (msg MsgBond) GetSigners() []sdk.Address { return []sdk.Address{msg.Address} }
|
||||
|
||||
// basic validation of the bond message
|
||||
func (msg MsgBond) ValidateBasic() sdk.Error {
|
||||
if msg.Stake.IsZero() {
|
||||
return ErrEmptyStake(DefaultCodespace)
|
||||
}
|
||||
|
||||
if msg.PubKey == nil {
|
||||
return sdk.ErrInvalidPubKey("MsgBond.PubKey must not be empty")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// get bond message sign bytes
|
||||
func (msg MsgBond) GetSignBytes() []byte {
|
||||
bz, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return bz
|
||||
}
|
||||
|
||||
//_______________________________________________________________
|
||||
|
||||
// simple unbond message
|
||||
type MsgUnbond struct {
|
||||
Address sdk.Address `json:"address"`
|
||||
}
|
||||
|
||||
func NewMsgUnbond(addr sdk.Address) MsgUnbond {
|
||||
return MsgUnbond{
|
||||
Address: addr,
|
||||
}
|
||||
}
|
||||
|
||||
//nolint
|
||||
func (msg MsgUnbond) Type() string { return moduleName } //TODO update "stake/declarecandidacy"
|
||||
func (msg MsgUnbond) Get(key interface{}) (value interface{}) { return nil }
|
||||
func (msg MsgUnbond) GetSigners() []sdk.Address { return []sdk.Address{msg.Address} }
|
||||
func (msg MsgUnbond) ValidateBasic() sdk.Error { return nil }
|
||||
|
||||
// get unbond message sign bytes
|
||||
func (msg MsgUnbond) GetSignBytes() []byte {
|
||||
bz, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return bz
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package simplestake
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
func TestBondMsgValidation(t *testing.T) {
|
||||
privKey := crypto.GenPrivKeyEd25519()
|
||||
cases := []struct {
|
||||
valid bool
|
||||
msgBond MsgBond
|
||||
}{
|
||||
{true, NewMsgBond(sdk.Address{}, sdk.Coin{"mycoin", 5}, privKey.PubKey())},
|
||||
{false, NewMsgBond(sdk.Address{}, sdk.Coin{"mycoin", 0}, privKey.PubKey())},
|
||||
}
|
||||
|
||||
for i, tc := range cases {
|
||||
err := tc.msgBond.ValidateBasic()
|
||||
if tc.valid {
|
||||
assert.Nil(t, err, "%d: %+v", i, err)
|
||||
} else {
|
||||
assert.NotNil(t, err, "%d", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package simplestake
|
||||
|
||||
import crypto "github.com/tendermint/go-crypto"
|
||||
|
||||
type bondInfo struct {
|
||||
PubKey crypto.PubKey
|
||||
Power int64
|
||||
}
|
||||
|
||||
func (bi bondInfo) isEmpty() bool {
|
||||
if bi == (bondInfo{}) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package simplestake
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/wire"
|
||||
)
|
||||
|
||||
// Register concrete types on wire codec
|
||||
func RegisterWire(cdc *wire.Codec) {
|
||||
cdc.RegisterConcrete(MsgBond{}, "simplestake/BondMsg", nil)
|
||||
cdc.RegisterConcrete(MsgUnbond{}, "simplestake/UnbondMsg", nil)
|
||||
}
|
||||
Reference in New Issue
Block a user