This commit is contained in:
rhuairahrighairigh 2020-03-12 00:47:25 +00:00
parent 029842168a
commit 20bcfec407
4 changed files with 199 additions and 20 deletions

View File

@ -1,25 +1,24 @@
package committee package committee
// committee, subcommittee, council, caucus, commission, synod, board
/*
import ( import (
"fmt" "fmt"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/kava-labs/kava/x/committee/keeper" "github.com/kava-labs/kava/x/committee/keeper"
"github.com/kava-labs/kava/x/committee/types" "github.com/kava-labs/kava/x/committee/types"
) )
// NewHandler creates an sdk.Handler for committee messages // NewHandler creates an sdk.Handler for committee messages
func NewHandler(k keeper.Keeper) sdk.Handler { func NewHandler(k keeper.Keeper) sdk.Handler {
return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
ctx = ctx.WithEventManager(sdk.NewEventManager())
switch msg := msg.(type) { switch msg := msg.(type) {
case types.MsgSubmitProposal: case types.MsgSubmitProposal:
handleMsgSubmitProposal(ctx, k, msg) return handleMsgSubmitProposal(ctx, k, msg)
case types.MsgVote: case types.MsgVote:
handleMsgVote(ctx, k, msg) return handleMsgVote(ctx, k, msg)
default: default:
errMsg := fmt.Sprintf("unrecognized %s msg type: %T", types.ModuleName, msg) errMsg := fmt.Sprintf("unrecognized %s msg type: %T", types.ModuleName, msg)
return sdk.ErrUnknownRequest(errMsg).Result() return sdk.ErrUnknownRequest(errMsg).Result()
@ -28,21 +27,33 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
} }
func handleMsgSubmitProposal(ctx sdk.Context, k keeper.Keeper, msg types.MsgSubmitProposal) sdk.Result { func handleMsgSubmitProposal(ctx sdk.Context, k keeper.Keeper, msg types.MsgSubmitProposal) sdk.Result {
err := keeper.SubmitProposal(ctx, msg) proposalID, err := k.SubmitProposal(ctx, msg.Proposer, msg.CommitteeID, msg.PubProposal)
if err != nil { if err != nil {
return err.Result() return err.Result()
} }
return sdk.Result{} ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
// TODO sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(sdk.AttributeKeySender, msg.Proposer.String()),
),
)
return sdk.Result{
Data: GetKeyFromID(proposalID),
Events: ctx.EventManager().Events(),
}
} }
func handleMsgVote(ctx sdk.Context, k keeper.Keeper, msg types.MsgVote) sdk.Result { func handleMsgVote(ctx sdk.Context, k keeper.Keeper, msg types.MsgVote) sdk.Result {
err := keeper.AddVote(ctx, msg) err := k.AddVote(ctx, msg.ProposalID, msg.Voter)
if err != nil {
// Try closing proposal return err.Result()
_ = k.CloseOutProposal(ctx, proposalID) }
// Try closing proposal in case enough votes have been cast
_ = k.CloseOutProposal(ctx, msg.ProposalID)
// if err.Error() == "note enough votes to close proposal" { // TODO // if err.Error() == "note enough votes to close proposal" { // TODO
// return nil // This is not a reason to error // return nil // This is not a reason to error
// } // }
@ -50,10 +61,13 @@ func handleMsgVote(ctx sdk.Context, k keeper.Keeper, msg types.MsgVote) sdk.Resu
// return err // return err
// } // }
if err != nil { ctx.EventManager().EmitEvent(
return err.Result() sdk.NewEvent(
} sdk.EventTypeMessage,
// TODO sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(sdk.AttributeKeySender, msg.Voter.String()),
),
)
return sdk.Result{} return sdk.Result{Events: ctx.EventManager().Events()}
} }
*/

View File

@ -13,7 +13,6 @@ const (
// StoreKey Top level store key where all module items will be stored // StoreKey Top level store key where all module items will be stored
StoreKey = ModuleName StoreKey = ModuleName
/*
// RouterKey Top level router key // RouterKey Top level router key
RouterKey = ModuleName RouterKey = ModuleName
@ -22,7 +21,6 @@ const (
// DefaultParamspace default name for parameter store // DefaultParamspace default name for parameter store
DefaultParamspace = ModuleName DefaultParamspace = ModuleName
*/
) )
// Key prefixes // Key prefixes

View File

@ -1,11 +1,97 @@
package types package types
import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
const (
TypeMsgSubmitProposal = "submit_proposal"
TypeMsgVote = "vote"
)
var _, _ sdk.Msg = MsgSubmitProposal{}, MsgVote{}
// MsgSubmitProposal is used by committee members to create a new proposal that they can vote on. // MsgSubmitProposal is used by committee members to create a new proposal that they can vote on.
type MsgSubmitProposal struct { type MsgSubmitProposal struct {
PubProposal PubProposal `json:"pub_proposal" yaml:"pub_proposal"`
Proposer sdk.AccAddress `json:"proposer" yaml:"proposer"`
CommitteeID uint64
}
// NewMsgSubmitProposal creates a new MsgSubmitProposal instance
func NewMsgSubmitProposal(pubProposal PubProposal, proposer sdk.AccAddress, committeeID uint64) MsgSubmitProposal {
return MsgSubmitProposal{
PubProposal: pubProposal,
Proposer: proposer,
CommitteeID: committeeID,
}
}
// Route return the message type used for routing the message.
func (msg MsgSubmitProposal) Route() string { return RouterKey }
// Type returns a human-readable string for the message, intended for utilization within events.
func (msg MsgSubmitProposal) Type() string { return TypeMsgSubmitProposal }
// ValidateBasic does a simple validation check that doesn't require access to any other information.
func (msg MsgSubmitProposal) ValidateBasic() sdk.Error {
if msg.PubProposal == nil {
return sdk.ErrInternal("no proposal")
}
if msg.Proposer.Empty() {
return sdk.ErrInvalidAddress(msg.Proposer.String())
}
// TODO // TODO
// if !IsValidProposalType(msg.Content.ProposalType()) {
// return ErrInvalidProposalType(DefaultCodespace, msg.Content.ProposalType())
// }
return msg.PubProposal.ValidateBasic()
}
// GetSignBytes gets the canonical byte representation of the Msg.
func (msg MsgSubmitProposal) GetSignBytes() []byte {
bz := ModuleCdc.MustMarshalJSON(msg)
return sdk.MustSortJSON(bz)
}
// GetSigners returns the addresses of signers that must sign.
func (msg MsgSubmitProposal) GetSigners() []sdk.AccAddress {
return []sdk.AccAddress{msg.Proposer}
} }
// MsgVote is submitted by committee members to vote on proposals. // MsgVote is submitted by committee members to vote on proposals.
type MsgVote struct { type MsgVote struct {
// TODO ProposalID uint64 `json:"proposal_id" yaml:"proposal_id"`
Voter sdk.AccAddress `json:"voter" yaml:"voter"`
}
// NewMsgVote creates a message to cast a vote on an active proposal
func NewMsgVote(voter sdk.AccAddress, proposalID uint64) MsgVote {
return MsgVote{proposalID, voter}
}
// Route return the message type used for routing the message.
func (msg MsgVote) Route() string { return RouterKey }
// Type returns a human-readable string for the message, intended for utilization within events.
func (msg MsgVote) Type() string { return TypeMsgVote }
// ValidateBasic does a simple validation check that doesn't require access to any other information.
func (msg MsgVote) ValidateBasic() sdk.Error {
if msg.Voter.Empty() {
return sdk.ErrInvalidAddress(msg.Voter.String())
}
return nil
}
// GetSignBytes gets the canonical byte representation of the Msg.
func (msg MsgVote) GetSignBytes() []byte {
bz := ModuleCdc.MustMarshalJSON(msg)
return sdk.MustSortJSON(bz)
}
// GetSigners returns the addresses of signers that must sign.
func (msg MsgVote) GetSigners() []sdk.AccAddress {
return []sdk.AccAddress{msg.Voter}
} }

View File

@ -0,0 +1,81 @@
package types
import (
"testing"
"github.com/stretchr/testify/require"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/gov"
)
func TestMsgSubmitProposal_ValidateBasic(t *testing.T) {
addr := sdk.AccAddress([]byte("someName"))
tests := []struct {
name string
msg MsgSubmitProposal
expectPass bool
}{
{
name: "normal",
msg: MsgSubmitProposal{gov.NewTextProposal("A Title", "A proposal description."), addr, 3},
expectPass: true,
},
{
name: "empty address",
msg: MsgSubmitProposal{gov.NewTextProposal("A Title", "A proposal description."), nil, 3},
expectPass: false,
},
{
name: "invalid proposal",
msg: MsgSubmitProposal{gov.TextProposal{}, addr, 3},
expectPass: false,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
err := tc.msg.ValidateBasic()
if tc.expectPass {
require.NoError(t, err)
} else {
require.Error(t, err)
}
})
}
}
func TestMsgVote_ValidateBasic(t *testing.T) {
addr := sdk.AccAddress([]byte("someName"))
tests := []struct {
name string
msg MsgVote
expectPass bool
}{
{
name: "normal",
msg: MsgVote{5, addr},
expectPass: true,
},
{
name: "empty address",
msg: MsgVote{5, nil},
expectPass: false,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
err := tc.msg.ValidateBasic()
if tc.expectPass {
require.NoError(t, err)
} else {
require.Error(t, err)
}
})
}
}