move Bond/UnbondCoins to transact

working

...
This commit is contained in:
Ethan Buchman 2018-03-16 21:36:16 +01:00 committed by rigelrozanski
parent af6c1a3f02
commit 865b116837
6 changed files with 228 additions and 212 deletions

View File

@ -5,7 +5,6 @@ import (
"encoding/json"
"fmt"
"github.com/pkg/errors"
"github.com/spf13/cobra"
flag "github.com/spf13/pflag"
"github.com/spf13/viper"
@ -13,8 +12,8 @@ import (
crypto "github.com/tendermint/go-crypto"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/examples/basecoin/app"
coin "github.com/cosmos/cosmos-sdk/x/bank" // XXX fix
"github.com/cosmos/cosmos-sdk/client/builder"
"github.com/cosmos/cosmos-sdk/wire" // XXX fix
"github.com/cosmos/cosmos-sdk/x/stake"
)
@ -26,189 +25,183 @@ func PrefixedKey(app string, key []byte) []byte {
//nolint
var (
CmdQueryCandidates = &cobra.Command{
Use: "candidates",
Short: "Query for the set of validator-candidates pubkeys",
RunE: cmdQueryCandidates,
}
CmdQueryCandidate = &cobra.Command{
Use: "candidate",
Short: "Query a validator-candidate account",
RunE: cmdQueryCandidate,
}
CmdQueryDelegatorBond = &cobra.Command{
Use: "delegator-bond",
Short: "Query a delegators bond based on address and candidate pubkey",
RunE: cmdQueryDelegatorBond,
}
CmdQueryDelegatorCandidates = &cobra.Command{
Use: "delegator-candidates",
RunE: cmdQueryDelegatorCandidates,
Short: "Query all delegators candidates' pubkeys based on address",
}
FlagDelegatorAddress = "delegator-address"
fsValAddr = flag.NewFlagSet("", flag.ContinueOnError)
fsDelAddr = flag.NewFlagSet("", flag.ContinueOnError)
FlagValidatorAddr = "address"
FlagDelegatorAddr = "delegator-address"
)
func init() {
//Add Flags
fsPk := flag.NewFlagSet("", flag.ContinueOnError)
fsPk.String(FlagPubKey, "", "PubKey of the validator-candidate")
fsAddr := flag.NewFlagSet("", flag.ContinueOnError)
fsAddr.String(FlagDelegatorAddress, "", "Delegator Hex Address")
fsValAddr.String(FlagValidatorAddr, "", "Address of the validator/candidate")
fsDelAddr.String(FlagDelegatorAddr, "", "Delegator hex address")
CmdQueryCandidate.Flags().AddFlagSet(fsPk)
CmdQueryDelegatorBond.Flags().AddFlagSet(fsPk)
CmdQueryDelegatorBond.Flags().AddFlagSet(fsAddr)
CmdQueryDelegatorCandidates.Flags().AddFlagSet(fsAddr)
}
// XXX move to common directory in client helpers
func makeQuery(key, storeName string) (res []byte, err error) {
// create command to query for all candidates
func GetCmdQueryCandidates(cdc *wire.Codec, storeName string) *cobra.Command {
cmd := &cobra.Command{
Use: "candidates",
Short: "Query for the set of validator-candidates pubkeys",
RunE: func(cmd *cobra.Command, args []string) error {
path := fmt.Sprintf("/%s/key", a.storeName)
var pks []crypto.PubKey
uri := viper.GetString(client.FlagNode)
if uri == "" {
return res, errors.New("Must define which node to query with --node")
}
node := client.GetNode(uri)
prove := !viper.GetBool(client.FlagTrustNode)
key := PrefixedKey(stake.Name, stake.CandidatesAddrKey)
opts := rpcclient.ABCIQueryOptions{
Height: viper.GetInt64(client.FlagHeight),
Trusted: viper.GetBool(client.FlagTrustNode),
res, err := builder.Query(key, storeName)
if err != nil {
return err
}
// parse out the candidates
candidates := new(stake.Candidates)
err = cdc.UnmarshalJSON(res, candidates)
if err != nil {
return err
}
output, err := json.MarshalIndent(candidates, "", " ")
if err != nil {
return err
}
fmt.Println(string(output))
return nil
// TODO output with proofs / machine parseable etc.
},
}
result, err := node.ABCIQueryWithOptions(path, key, opts)
if err != nil {
return res, err
}
resp := result.Response
if resp.Code != uint32(0) {
return res, errors.Errorf("Query failed: (%d) %s", resp.Code, resp.Log)
}
return resp.val, nil
cmd.Flags().AddFlagSet(fsDelAddr)
return cmd
}
func cmdQueryCandidates(cmd *cobra.Command, args []string) error {
// get the command to query a candidate
func GetCmdQueryCandidate(cdc *wire.Codec, storeName string) *cobra.Command {
cmd := &cobra.Command{
Use: "candidate",
Short: "Query a validator-candidate account",
RunE: func(cmd *cobra.Command, args []string) error {
var pks []crypto.PubKey
addr, err := GetAddress(viper.GetString(FlagValidatorAddr))
if err != nil {
return err
}
prove := !viper.GetBool(client.FlagTrustNode)
key := PrefixedKey(stake.Name(), stake.CandidatesPubKeysKey)
prove := !viper.GetBool(client.FlagTrustNode)
key := PrefixedKey(stake.Name, stake.GetCandidateKey(addr))
res, err := makeQuery(key, "gaia-store-name") // XXX move gaia store name out of here
if err != nil {
return err
res, err := builder.Query(key, storeName)
if err != nil {
return err
}
// parse out the candidate
candidate := new(stake.Candidate)
err = cdc.UnmarshalBinary(res, candidate)
if err != nil {
return err
}
output, err := json.MarshalIndent(candidate, "", " ")
if err != nil {
return err
}
fmt.Println(string(output))
return nil
// TODO output with proofs / machine parseable etc.
},
}
// parse out the candidates
candidates := new(stake.Candidates)
cdc := app.MakeTxCodec() // XXX create custom Tx for Staking Module
err = cdc.UnmarshalBinary(res, candidates)
if err != nil {
return err
}
output, err := json.MarshalIndent(candidates, "", " ")
if err != nil {
return err
}
fmt.Println(string(output))
return nil
// TODO output with proofs / machine parseable etc.
cmd.Flags().AddFlagSet(fsValAddr)
return cmd
}
func cmdQueryCandidate(cmd *cobra.Command, args []string) error {
// get the command to query a single delegator bond
func GetCmdQueryDelegatorBond(cdc *wire.Codec, storeName string) *cobra.Command {
cmd := &cobra.Command{
Use: "delegator-bond",
Short: "Query a delegators bond based on address and candidate pubkey",
RunE: func(cmd *cobra.Command, args []string) error {
var candidate stake.Candidate
addr, err := GetAddress(viper.GetString(FlagValidatorAddr))
if err != nil {
return err
}
pk, err := GetPubKey(viper.GetString(FlagPubKey))
if err != nil {
return err
bz, err := hex.DecodeString(viper.GetString(FlagDelegatorAddr))
if err != nil {
return err
}
delegator := crypto.Address(bz)
prove := !viper.GetBool(client.FlagTrustNode)
key := PrefixedKey(stake.Name, stake.GetDelegatorBondKey(delegator, addr, cdc))
res, err := builder.Query(key, storeName)
if err != nil {
return err
}
// parse out the bond
var bond stake.DelegatorBond
err = cdc.UnmarshalBinary(res, bond)
if err != nil {
return err
}
output, err := json.MarshalIndent(bond, "", " ")
if err != nil {
return err
}
fmt.Println(string(output))
return nil
// TODO output with proofs / machine parseable etc.
},
}
prove := !viper.GetBool(client.FlagTrustNode)
key := PrefixedKey(stake.Name(), stake.GetCandidateKey(pk))
// parse out the candidate
candidate := new(stake.Candidate)
cdc := app.MakeTxCodec() // XXX create custom Tx for Staking Module
err = cdc.UnmarshalBinary(res, candidate)
if err != nil {
return err
}
output, err := json.MarshalIndent(candidate, "", " ")
if err != nil {
return err
}
fmt.Println(string(output))
return nil
// TODO output with proofs / machine parseable etc.
cmd.Flags().AddFlagSet(fsValAddr)
cmd.Flags().AddFlagSet(fsDelAddr)
return cmd
}
func cmdQueryDelegatorBond(cmd *cobra.Command, args []string) error {
// get the command to query all the candidates bonded to a delegator
func GetCmdQueryDelegatorBonds(cdc *wire.Codec, storeName string) *cobra.Command {
cmd := &cobra.Command{
Use: "delegator-candidates",
Short: "Query all delegators candidates' pubkeys based on address",
RunE: func(cmd *cobra.Command, args []string) error {
pk, err := GetPubKey(viper.GetString(FlagPubKey))
if err != nil {
return err
bz, err := hex.DecodeString(viper.GetString(FlagDelegatorAddr))
if err != nil {
return err
}
delegator := crypto.Address(bz)
prove := !viper.GetBool(client.FlagTrustNode)
key := PrefixedKey(stake.Name, stake.GetDelegatorBondsKey(delegator, cdc))
res, err := builder.Query(key, storeName)
if err != nil {
return err
}
// parse out the candidates list
var candidates []crypto.PubKey
err = cdc.UnmarshalBinary(res, candidates)
if err != nil {
return err
}
output, err := json.MarshalIndent(candidates, "", " ")
if err != nil {
return err
}
fmt.Println(string(output))
return nil
// TODO output with proofs / machine parseable etc.
},
}
bz, err := hex.DecodeString(viper.GetString(FlagDelegatorAddress))
if err != nil {
return err
}
delegator := crypto.Address(bz)
delegator = coin.ChainAddr(delegator)
prove := !viper.GetBool(client.FlagTrustNode)
key := PrefixedKey(stake.Name(), stake.GetDelegatorBondKey(delegator, pk))
// parse out the bond
var bond stake.DelegatorBond
cdc := app.MakeTxCodec() // XXX create custom Tx for Staking Module
err = cdc.UnmarshalBinary(res, bond)
if err != nil {
return err
}
output, err := json.MarshalIndent(bond, "", " ")
if err != nil {
return err
}
fmt.Println(string(output))
return nil
// TODO output with proofs / machine parseable etc.
}
func cmdQueryDelegatorCandidates(cmd *cobra.Command, args []string) error {
bz, err := hex.DecodeString(viper.GetString(FlagDelegatorAddress))
if err != nil {
return err
}
delegator := crypto.Address(bz)
delegator = coin.ChainAddr(delegator)
prove := !viper.GetBool(client.FlagTrustNode)
key := PrefixedKey(stake.Name(), stake.GetDelegatorBondsKey(delegator))
// parse out the candidates list
var candidates []crypto.PubKey
cdc := app.MakeTxCodec() // XXX create custom Tx for Staking Module
err = cdc.UnmarshalBinary(res, candidates)
if err != nil {
return err
}
output, err := json.MarshalIndent(candidates, "", " ")
if err != nil {
return err
}
fmt.Println(string(output))
return nil
// TODO output with proofs / machine parseable etc.
cmd.Flags().AddFlagSet(fsDelAddr)
return cmd
}

View File

@ -18,9 +18,10 @@ import (
// nolint
const (
FlagPubKey = "pubkey"
FlagAmount = "amount"
FlagShares = "shares"
FlagAddress = "address"
FlagPubKey = "pubkey"
FlagAmount = "amount"
FlagShares = "shares"
FlagMoniker = "moniker"
FlagIdentity = "keybase-sig"
@ -91,6 +92,11 @@ func cmdDeclareCandidacy(cmd *cobra.Command, args []string) error {
return err
}
addr, err := GetAddress(viper.GetString(FlagAddress))
if err != nil {
return err
}
pk, err := GetPubKey(viper.GetString(FlagPubKey))
if err != nil {
return err
@ -107,13 +113,13 @@ func cmdDeclareCandidacy(cmd *cobra.Command, args []string) error {
Details: viper.GetString(FlagDetails),
}
tx := stake.NewMsgDeclareCandidacy(amount, pk, description)
tx := stake.NewMsgDeclareCandidacy(addr, pk, amount, description)
return doTx(tx)
}
func cmdEditCandidacy(cmd *cobra.Command, args []string) error {
pk, err := GetPubKey(viper.GetString(FlagPubKey))
addr, err := GetAddress(viper.GetString(FlagAddress))
if err != nil {
return err
}
@ -125,7 +131,7 @@ func cmdEditCandidacy(cmd *cobra.Command, args []string) error {
Details: viper.GetString(FlagDetails),
}
tx := stake.NewMsgEditCandidacy(pk, description)
tx := stake.NewMsgEditCandidacy(addr, description)
return doTx(tx)
}
@ -135,12 +141,12 @@ func cmdDelegate(cmd *cobra.Command, args []string) error {
return err
}
pk, err := GetPubKey(viper.GetString(FlagPubKey))
addr, err := GetAddress(viper.GetString(FlagAddress))
if err != nil {
return err
}
tx := stake.NewMsgDelegate(amount, pk)
tx := stake.NewMsgDelegate(addr, amount)
return doTx(tx)
}
@ -162,15 +168,17 @@ func cmdUnbond(cmd *cobra.Command, args []string) error {
}
}
pk, err := GetPubKey(viper.GetString(FlagPubKey))
addr, err := GetAddress(viper.GetString(FlagAddress))
if err != nil {
return err
}
tx := stake.NewMsgUnbond(sharesStr, pk)
tx := stake.NewMsgUnbond(addr, sharesStr)
return doTx(tx)
}
//______________________________________________________________________________________
// GetPubKey - create the pubkey from a pubkey string
func GetPubKey(pubKeyStr string) (pk crypto.PubKey, err error) {
@ -193,7 +201,19 @@ func GetPubKey(pubKeyStr string) (pk crypto.PubKey, err error) {
return
}
//--------------------------------------------------------------------
// GetPubKey - create an Address from a pubkey string
func GetAddress(Address string) (addr sdk.Address, err error) {
if len(Address) == 0 {
return addr, errors.New("must use provide address")
}
bz, err := hex.DecodeString(addr)
if err != nil {
return nil, err
}
return sdk.Address(bz), nil
}
//______________________________________________________________________________________
// XXX consolidate to client
func doTx(tx []byte) {

View File

@ -249,7 +249,7 @@ func (tr transact) delegateWithCandidate(tx MsgDelegate, candidate *Candidate) s
}
// Account new shares, save
err := bond.BondCoins(candidate, tx.Bond, tr)
err := tr.BondCoins(bond, candidate, tx.Bond)
if err != nil {
return err
}
@ -259,6 +259,37 @@ func (tr transact) delegateWithCandidate(tx MsgDelegate, candidate *Candidate) s
return nil
}
// Perform all the actions required to bond tokens to a delegator bond from their account
func (tr *transact) BondCoins(bond *DelegatorBond, candidate *Candidate, tokens sdk.Coin) sdk.Error {
_, err := tr.coinKeeper.SubtractCoins(tr.ctx, candidate.Address, sdk.Coins{tokens})
if err != nil {
return err
}
newShares := candidate.addTokens(tokens.Amount, tr.gs)
bond.Shares = bond.Shares.Add(newShares)
return nil
}
// Perform all the actions required to bond tokens to a delegator bond from their account
func (tr *transact) UnbondCoins(bond *DelegatorBond, candidate *Candidate, shares sdk.Rat) sdk.Error {
// subtract bond tokens from delegator bond
if bond.Shares.LT(shares) {
return sdk.ErrInsufficientFunds("") // TODO
}
bond.Shares = bond.Shares.Sub(shares)
returnAmount := candidate.removeShares(shares, tr.gs)
returnCoins := sdk.Coins{{tr.params.BondDenom, returnAmount}}
_, err := tr.coinKeeper.AddCoins(tr.ctx, candidate.Address, returnCoins)
if err != nil {
return err
}
return nil
}
func (tr transact) unbond(tx MsgUnbond) sdk.Error {
// check if bond has any shares in it unbond

View File

@ -17,7 +17,7 @@ import (
func initAccounts(n int, amount int64) ([]sdk.Address, map[string]int64) {
accStore := map[string]int64{}
senders := newActors(n)
senders := newAddrs(n)
for _, sender := range senders {
accStore[string(sender.Address)] = amount
}
@ -49,9 +49,9 @@ func newMsgUnbond(shares string, pubKey crypto.PubKey) MsgUnbond {
func paramsNoInflation() Params {
return Params{
InflationRateChange: sdk.Zero,
InflationMax: sdk.Zero,
InflationMin: sdk.Zero,
InflationRateChange: sdk.ZeroRat,
InflationMax: sdk.ZeroRat,
InflationMin: sdk.ZeroRat,
GoalBonded: sdk.New(67, 100),
MaxVals: 100,
BondDenom: "fermion",

View File

@ -8,6 +8,9 @@ import (
crypto "github.com/tendermint/go-crypto"
)
// name to idetify transaction types
var Name = "stake"
//Verify interface at compile time
var _, _, _, _ sdk.Msg = &MsgDeclareCandidacy{}, &MsgEditCandidacy{}, &MsgDelegate{}, &MsgUnbond{}
@ -25,7 +28,7 @@ func NewMsgAddr(address sdk.Address) MsgAddr {
}
// nolint
func (msg MsgAddr) Type() string { return "stake" }
func (msg MsgAddr) Type() string { return Name }
func (msg MsgAddr) Get(key interface{}) (value interface{}) { return nil }
func (msg MsgAddr) GetSigners() []sdk.Address { return []sdk.Address{msg.Address} }
func (msg MsgAddr) String() string {
@ -50,7 +53,7 @@ type MsgDeclareCandidacy struct {
PubKey crypto.PubKey `json:"pubkey"`
}
func NewMsgDeclareCandidacy(bond sdk.Coin, address sdk.Address, pubkey crypto.PubKey, description Description) MsgDeclareCandidacy {
func NewMsgDeclareCandidacy(address sdk.Address, pubkey crypto.PubKey, bond sdk.Coin, description Description) MsgDeclareCandidacy {
return MsgDeclareCandidacy{
MsgAddr: NewMsgAddr(address),
Description: description,
@ -167,10 +170,10 @@ type MsgUnbond struct {
Shares string `json:"shares"`
}
func NewMsgUnbond(bond sdk.Coin, address sdk.Address) MsgDelegate {
return MsgDelegate{
func NewMsgUnbond(address sdk.Address, shares string) MsgUnbond {
return MsgUnbond{
MsgAddr: NewMsgAddr(address),
Bond: bond, // Shares: shares,
Shares: shares,
}
}

View File

@ -260,34 +260,3 @@ type DelegatorBond struct {
Address sdk.Address `json:"pub_key"`
Shares sdk.Rat `json:"shares"`
}
// Perform all the actions required to bond tokens to a delegator bond from their account
func (bond *DelegatorBond) BondCoins(candidate *Candidate, tokens sdk.Coin, tr transact) sdk.Error {
_, err := tr.coinKeeper.SubtractCoins(tr.ctx, candidate.Address, sdk.Coins{tokens})
if err != nil {
return err
}
newShares := candidate.addTokens(tokens.Amount, tr.gs)
bond.Shares = bond.Shares.Add(newShares)
return nil
}
// Perform all the actions required to bond tokens to a delegator bond from their account
func (bond *DelegatorBond) UnbondCoins(candidate *Candidate, shares int64, tr transact) sdk.Error {
// subtract bond tokens from delegator bond
if bond.Shares.LT(shares) {
return sdk.ErrInsufficientFunds("") // TODO
}
bond.Shares = bond.Shares.Sub(shares)
returnAmount := candidate.removeShares(shares, tr.gs)
returnCoins := sdk.Coins{{tr.params.BondDenom, returnAmount}}
_, err := tr.coinKeeper.AddCoins(tr.ctx, candidate.Address, returnCoins)
if err != nil {
return err
}
return nil
}