Commit 60f2071b authored by jiangpeng's avatar jiangpeng

dapp/vote:update

parent d42515f7
......@@ -23,7 +23,7 @@ func Cmd() *cobra.Command {
cmd.AddCommand(
//create tx
createGroupCMD(),
updateMemberCMD(),
updateGroupCMD(),
createVoteCMD(),
commitVoteCMD(),
//query rpc
......
......@@ -3,6 +3,7 @@ package commands
import (
"fmt"
"os"
"time"
"github.com/33cn/chain33/types"
vty "github.com/33cn/plugin/plugin/dapp/vote/types"
......@@ -22,7 +23,7 @@ func createGroupCMD() *cobra.Command {
func createGroupFlags(cmd *cobra.Command) {
cmd.Flags().StringP("name", "n", "", "group name")
cmd.Flags().StringArrayP("admins", "a", nil, "group admin address array")
cmd.Flags().StringArrayP("admins", "a", nil, "group admin address array, default set creator as admin")
cmd.Flags().StringArrayP("members", "m", nil, "group member address array")
cmd.Flags().UintSliceP("weights", "w", nil, "member vote weight array")
markRequired(cmd, "name")
......@@ -37,12 +38,14 @@ func createGroup(cmd *cobra.Command, args []string) {
if name == "" {
fmt.Fprintf(os.Stderr, "ErrNilGroupName")
return
}
if len(weights) == 0 {
weights = make([]uint, len(memberAddrs))
}
if len(weights) != len(memberAddrs) {
fmt.Fprintf(os.Stderr, "member address array length should equal with vote weight array length")
return
}
members := make([]*vty.GroupMember, 0)
......@@ -58,40 +61,46 @@ func createGroup(cmd *cobra.Command, args []string) {
sendCreateTxRPC(cmd, vty.NameCreateGroupAction, params)
}
func updateMemberCMD() *cobra.Command {
func updateGroupCMD() *cobra.Command {
cmd := &cobra.Command{
Use: "updateMember",
Short: "create tx(update group members)",
Run: updateMember,
Example: "updateMember -g=id -a=addMember1 -a=addMember2 -r=removeMember1 ...",
Use: "updateGroup",
Short: "create tx(update group members or admin)",
Run: updateGroup,
Example: "updateGroup -g=id -a=addMember1 -a=addMember2 -r=removeMember1 ...",
}
updateMemberFlags(cmd)
updateGroupFlags(cmd)
return cmd
}
func updateMemberFlags(cmd *cobra.Command) {
func updateGroupFlags(cmd *cobra.Command) {
cmd.Flags().StringP("groupID", "g", "", "group id")
cmd.Flags().StringArrayP("addMembers", "a", nil, "group member address array for adding")
cmd.Flags().UintSliceP("weights", "w", nil, "member vote weight array for adding")
cmd.Flags().StringArrayP("removeMembers", "r", nil, "group member address array for removing")
cmd.Flags().StringArrayP("addAdmins", "d", nil, "group admin address array for adding")
cmd.Flags().StringArrayP("removeAdmins", "m", nil, "group admin address array for removing")
markRequired(cmd, "groupID")
}
func updateMember(cmd *cobra.Command, args []string) {
func updateGroup(cmd *cobra.Command, args []string) {
groupID, _ := cmd.Flags().GetString("groupID")
addAddrs, _ := cmd.Flags().GetStringArray("addMembers")
weights, _ := cmd.Flags().GetUintSlice("weights")
removeAddrs, _ := cmd.Flags().GetStringArray("removeMembers")
addAdmins, _ := cmd.Flags().GetStringArray("addAdmins")
removeAdmins, _ := cmd.Flags().GetStringArray("removeAdmins")
if groupID == "" {
fmt.Fprintf(os.Stderr, "ErrNilGroupID")
return
}
if len(weights) == 0 {
weights = make([]uint, len(addAddrs))
}
if len(weights) != len(addAddrs) {
fmt.Fprintf(os.Stderr, "member address array length should equal with vote weight array length")
return
}
addMembers := make([]*vty.GroupMember, 0)
......@@ -99,12 +108,14 @@ func updateMember(cmd *cobra.Command, args []string) {
addMembers = append(addMembers, &vty.GroupMember{Addr: addr, VoteWeight: uint32(weights[i])})
}
params := &vty.UpdateMember{
params := &vty.UpdateGroup{
GroupID: groupID,
RemoveMemberAddrs: removeAddrs,
RemoveMembers: removeAddrs,
AddMembers: addMembers,
AddAdmins: addAdmins,
RemoveAdmins: removeAdmins,
}
sendCreateTxRPC(cmd, vty.NameUpdateMemberAction, params)
sendCreateTxRPC(cmd, vty.NameUpdateGroupAction, params)
}
func createVoteCMD() *cobra.Command {
......@@ -119,40 +130,47 @@ func createVoteCMD() *cobra.Command {
func createVoteFlags(cmd *cobra.Command) {
cmd.Flags().StringP("name", "n", "", "vote name")
cmd.Flags().StringArrayP("groupIDs", "g", nil, "related group id array")
cmd.Flags().StringP("groupID", "g", "", "belonging group id")
cmd.Flags().StringArrayP("options", "o", nil, "vote option array")
cmd.Flags().Int64P("beginTime", "b", 0, "vote begin unix timestamp, default set now time")
cmd.Flags().Int64P("endTime", "e", 0, "vote end unix timestamp, default set beginTime + 300 seconds")
cmd.Flags().Int64P("beginTime", "b", 0, "vote begin unix timestamp, default set current time")
cmd.Flags().StringP("duration", "d", "24h", "vote duration time, such as(10s, 10m, 10h), default 24h")
markRequired(cmd, "name", "groupIDs", "options")
markRequired(cmd, "name", "groupID", "options")
}
func createVote(cmd *cobra.Command, args []string) {
name, _ := cmd.Flags().GetString("name")
groupIDs, _ := cmd.Flags().GetStringArray("groupIDs")
groupID, _ := cmd.Flags().GetString("groupID")
options, _ := cmd.Flags().GetStringArray("options")
beginTime, _ := cmd.Flags().GetInt64("beginTime")
endTime, _ := cmd.Flags().GetInt64("endTime")
duration, _ := cmd.Flags().GetString("duration")
if name == "" {
fmt.Fprintf(os.Stderr, "ErrNilVoteName")
return
}
if len(groupIDs) == 0 {
fmt.Fprintf(os.Stderr, "ErrNilGroupIDs")
if len(groupID) == 0 {
fmt.Fprintf(os.Stderr, "ErrNilGroupID")
return
}
if len(options) == 0 {
fmt.Fprintf(os.Stderr, "ErrNilOptions")
return
}
if beginTime == 0 {
beginTime = types.Now().Unix()
}
if endTime == 0 {
endTime = beginTime + 300
dt, err := time.ParseDuration(duration)
if err != nil {
fmt.Fprintf(os.Stderr, "InvalidDurationTime:"+err.Error())
return
}
endTime := beginTime + int64(dt/time.Second)
params := &vty.CreateVote{
Name: name,
VoteGroups: groupIDs,
GroupID: groupID,
VoteOptions: options,
BeginTimestamp: beginTime,
EndTimestamp: endTime,
......@@ -172,26 +190,77 @@ func commitVoteCMD() *cobra.Command {
func commitVoteFlags(cmd *cobra.Command) {
cmd.Flags().StringP("voteID", "v", "", "vote id")
cmd.Flags().StringP("groupID", "g", "", "belonging group id")
cmd.Flags().Uint32P("optionIndex", "o", 0, "voting option index in option array")
markRequired(cmd, "voteID", "groupID", "optionIndex")
markRequired(cmd, "voteID", "optionIndex")
}
func commitVote(cmd *cobra.Command, args []string) {
voteID, _ := cmd.Flags().GetString("voteID")
groupID, _ := cmd.Flags().GetString("groupID")
optionIndex, _ := cmd.Flags().GetUint32("optionIndex")
if voteID == "" {
fmt.Fprintf(os.Stderr, "ErrNilVoteID")
}
if len(groupID) == 0 {
fmt.Fprintf(os.Stderr, "ErrNilGroupID")
return
}
params := &vty.CommitVote{
VoteID: voteID,
GroupID: groupID,
OptionIndex: optionIndex,
}
sendCreateTxRPC(cmd, vty.NameCommitVoteAction, params)
}
func closeVoteCMD() *cobra.Command {
cmd := &cobra.Command{
Use: "closeVote",
Short: "create tx(close vote)",
Run: closeVote,
}
closeVoteFlags(cmd)
return cmd
}
func closeVoteFlags(cmd *cobra.Command) {
cmd.Flags().StringP("voteID", "v", "", "vote id")
markRequired(cmd, "voteID")
}
func closeVote(cmd *cobra.Command, args []string) {
voteID, _ := cmd.Flags().GetString("voteID")
if voteID == "" {
fmt.Fprintf(os.Stderr, "ErrNilVoteID")
return
}
params := &vty.CloseVote{
VoteID: voteID,
}
sendCreateTxRPC(cmd, vty.NameCloseVoteAction, params)
}
func updateMemberCMD() *cobra.Command {
cmd := &cobra.Command{
Use: "updateMember",
Short: "create tx(update member name)",
Run: updateMember,
}
updateMemberFlags(cmd)
return cmd
}
func updateMemberFlags(cmd *cobra.Command) {
cmd.Flags().StringP("name", "n", "", "member name")
markRequired(cmd, "name")
}
func updateMember(cmd *cobra.Command, args []string) {
name, _ := cmd.Flags().GetString("name")
if name == "" {
fmt.Fprintf(os.Stderr, "ErrNilMemberName")
return
}
params := &vty.UpdateMember{
Name: name,
}
sendCreateTxRPC(cmd, vty.NameUpdateMemberAction, params)
}
......@@ -12,35 +12,37 @@ import (
func groupInfoCMD() *cobra.Command {
cmd := &cobra.Command{
Use: "groupInfo",
Short: "show group info",
Short: "get group infos",
Run: groupInfo,
Example: "groupInfo -g=id1 -g=id2...",
}
groupInfoFlags(cmd)
return cmd
}
func groupInfoFlags(cmd *cobra.Command) {
cmd.Flags().StringP("groupID", "g", "", "group id")
markRequired(cmd, "groupID")
cmd.Flags().StringArrayP("groupIDs", "g", nil, "group id array")
markRequired(cmd, "groupIDs")
}
func groupInfo(cmd *cobra.Command, args []string) {
groupID, _ := cmd.Flags().GetString("groupID")
if len(groupID) == 0 {
fmt.Fprintf(os.Stderr, "ErrNilGroupID")
groupIDs, _ := cmd.Flags().GetStringArray("groupIDs")
if len(groupIDs) == 0 {
fmt.Fprintf(os.Stderr, "ErrNilGroupIDs")
return
}
params := &types.ReqString{
Data: groupID,
params := &vty.ReqStrings{
Items: groupIDs,
}
info := &vty.GroupVoteInfo{}
sendQueryRPC(cmd, "GetGroup", params, info)
info := &vty.GroupInfos{}
sendQueryRPC(cmd, "GetGroups", params, info)
}
func voteInfoCMD() *cobra.Command {
cmd := &cobra.Command{
Use: "voteInfo",
Short: "show vote info",
Short: "get vote info",
Run: voteInfo,
}
voteInfoFlags(cmd)
......@@ -48,27 +50,28 @@ func voteInfoCMD() *cobra.Command {
}
func voteInfoFlags(cmd *cobra.Command) {
cmd.Flags().StringP("voteID", "v", "", "vote id")
cmd.Flags().StringArrayP("voteIDs", "v", nil, "vote id array")
markRequired(cmd, "voteID")
}
func voteInfo(cmd *cobra.Command, args []string) {
voteID, _ := cmd.Flags().GetString("voteID")
if len(voteID) == 0 {
voteIDs, _ := cmd.Flags().GetStringArray("voteIDs")
if len(voteIDs) == 0 {
fmt.Fprintf(os.Stderr, "ErrNilVoteID")
return
}
params := &types.ReqString{
Data: voteID,
params := &vty.ReqStrings{
Items: voteIDs,
}
info := &vty.VoteInfo{}
sendQueryRPC(cmd, "GetVote", params, info)
info := &vty.ReplyVoteList{}
sendQueryRPC(cmd, "GetVotes", params, info)
}
func memberInfoCMD() *cobra.Command {
cmd := &cobra.Command{
Use: "memberInfo",
Short: "show member info",
Short: "get member info",
Run: memberInfo,
}
memberInfoFlags(cmd)
......@@ -76,21 +79,22 @@ func memberInfoCMD() *cobra.Command {
}
func memberInfoFlags(cmd *cobra.Command) {
cmd.Flags().StringP("addr", "a", "", "member address")
cmd.Flags().StringArrayP("addrs", "a", nil, "member address array")
markRequired(cmd, "addr")
}
func memberInfo(cmd *cobra.Command, args []string) {
addr, _ := cmd.Flags().GetString("addr")
if len(addr) == 0 {
addrs, _ := cmd.Flags().GetStringArray("addr")
if len(addrs) == 0 {
fmt.Fprintf(os.Stderr, "ErrNilAddress")
return
}
params := &types.ReqString{
Data: addr,
params := &vty.ReqStrings{
Items: addrs,
}
info := &vty.MemberInfo{}
sendQueryRPC(cmd, "GetMember", params, info)
info := &vty.MemberInfos{}
sendQueryRPC(cmd, "GetMembers", params, info)
}
func listGroupCMD() *cobra.Command {
......@@ -104,7 +108,7 @@ func listGroupCMD() *cobra.Command {
}
func listGroup(cmd *cobra.Command, args []string) {
runListCMD(cmd, args, "ListGroup", &vty.GroupVoteInfos{})
runListCMD(cmd, "ListGroup", &vty.GroupInfos{})
}
func listVoteCMD() *cobra.Command {
......@@ -113,12 +117,22 @@ func listVoteCMD() *cobra.Command {
Short: "show vote list",
Run: listVote,
}
listCmdFlags(cmd)
listVoteFlags(cmd)
return cmd
}
func listVoteFlags(cmd *cobra.Command) {
cmd.Flags().StringP("groupID", "g", "", "list vote belongs to specified group, list all if not set")
listCmdFlags(cmd)
}
func listVote(cmd *cobra.Command, args []string) {
runListCMD(cmd, args, "ListVote", &vty.VoteInfos{})
groupID, _ := cmd.Flags().GetString("groupID")
listReq := getListReq(cmd)
req := &vty.ReqListVote{
GroupID: groupID,
ListReq: listReq,
}
sendQueryRPC(cmd, "ListVote", req, &vty.ReplyVoteList{})
}
func listMemberCMD() *cobra.Command {
......@@ -132,23 +146,28 @@ func listMemberCMD() *cobra.Command {
}
func listMember(cmd *cobra.Command, args []string) {
runListCMD(cmd, args, "ListMember", &vty.MemberInfos{})
runListCMD(cmd, "ListMember", &vty.MemberInfos{})
}
func listCmdFlags(cmd *cobra.Command) {
cmd.Flags().StringP("startItem", "s", "", "list start item id, default nil value")
cmd.Flags().Uint32P("count", "c", 10, "list count, default 10")
cmd.Flags().Uint32P("direction", "d", 0, "list direction, default 1 (Ascending order)")
cmd.Flags().Uint32P("direction", "d", 1, "list direction, default 1 (Ascending order)")
}
func runListCMD(cmd *cobra.Command, funcName string, reply types.Message) {
req := getListReq(cmd)
sendQueryRPC(cmd, funcName, req, reply)
}
func runListCMD(cmd *cobra.Command, args []string, funcName string, reply types.Message) {
func getListReq(cmd *cobra.Command) *vty.ReqListItem {
startID, _ := cmd.Flags().GetString("startItem")
count, _ := cmd.Flags().GetUint32("count")
direction, _ := cmd.Flags().GetUint32("direction")
params := &vty.ReqListItem{
req := &vty.ReqListItem{
StartItemID: startID,
Count: int32(count),
Direction: int32(direction),
}
sendQueryRPC(cmd, funcName, params, reply)
return req
}
......@@ -3,6 +3,8 @@ package executor
import (
"encoding/hex"
"github.com/33cn/chain33/system/dapp"
dbm "github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/types"
vty "github.com/33cn/plugin/plugin/dapp/vote/types"
......@@ -51,14 +53,15 @@ func (a *action) createGroup(create *vty.CreateGroup) (*types.Receipt, error) {
receipt := &types.Receipt{Ty: types.ExecOk}
xhash := hex.EncodeToString(a.txHash)
group := &vty.GroupInfo{}
group.Name = create.Name
group.ID = formatGroupID(xhash)
group.ID = formatGroupID(dapp.HeightIndexStr(a.height, int64(a.index)))
//添加创建者作为默认管理员
group.Admins = append(group.Admins, create.Admins...)
if !checkSliceItemExist(a.fromAddr, create.Admins) {
group.Admins = append(group.Admins, a.fromAddr)
for _, addr := range create.GetAdmins() {
if addr != a.fromAddr {
group.Admins = append(group.Admins, addr)
}
}
group.Members = create.Members
......@@ -77,13 +80,13 @@ func (a *action) createGroup(create *vty.CreateGroup) (*types.Receipt, error) {
return receipt, nil
}
func (a *action) updateMember(update *vty.UpdateMember) (*types.Receipt, error) {
func (a *action) updateGroup(update *vty.UpdateGroup) (*types.Receipt, error) {
receipt := &types.Receipt{Ty: types.ExecOk}
group, err := a.getGroupInfo(update.GroupID)
if err != nil {
elog.Error("vote exec updateMember", "txHash", a.txHash, "err", err)
elog.Error("vote exec updateGroup", "txHash", a.txHash, "err", err)
return nil, errStateDBGet
}
addrMap := make(map[string]int)
......@@ -91,20 +94,43 @@ func (a *action) updateMember(update *vty.UpdateMember) (*types.Receipt, error)
addrMap[member.Addr] = index
}
// remove members
for _, addr := range update.GetRemoveMemberAddrs() {
for _, addr := range update.GetRemoveMembers() {
if index, ok := addrMap[addr]; ok {
group.Members = append(group.Members[:index], group.Members[index+1:]...)
delete(addrMap, addr)
}
}
// add members
for _, member := range update.GetAddMembers() {
if _, ok := addrMap[member.Addr]; !ok {
group.Members = append(group.Members, member)
}
}
adminMap := make(map[string]int)
for index, addr := range group.Admins {
adminMap[addr] = index
}
// remove admins
for _, addr := range update.GetRemoveAdmins() {
if index, ok := adminMap[addr]; ok {
group.Admins = append(group.Admins[:index], group.Admins[index+1:]...)
delete(adminMap, addr)
}
}
// add admins
for _, addr := range update.GetAddAdmins() {
if _, ok := adminMap[addr]; !ok {
group.Admins = append(group.Admins, addr)
}
}
groupValue := types.Encode(group)
receipt.KV = append(receipt.KV, &types.KeyValue{Key: formatStateIDKey(group.ID), Value: groupValue})
receipt.Logs = append(receipt.Logs, &types.ReceiptLog{Ty: vty.TyUpdateMemberLog, Log: groupValue})
receipt.Logs = append(receipt.Logs, &types.ReceiptLog{Ty: vty.TyUpdateGroupLog, Log: groupValue})
return receipt, nil
}
......@@ -114,17 +140,17 @@ func (a *action) createVote(create *vty.CreateVote) (*types.Receipt, error) {
receipt := &types.Receipt{Ty: types.ExecOk}
vote := &vty.VoteInfo{}
vote.ID = formatVoteID(hex.EncodeToString(a.txHash))
vote.ID = formatVoteID(dapp.HeightIndexStr(a.height, int64(a.index)))
vote.BeginTimestamp = create.BeginTimestamp
vote.EndTimestamp = create.EndTimestamp
vote.Name = create.Name
vote.VoteGroups = create.VoteGroups
vote.GroupID = create.GroupID
vote.VoteOptions = make([]*vty.VoteOption, 0)
for _, option := range create.VoteOptions {
vote.VoteOptions = append(vote.VoteOptions, &vty.VoteOption{Option: option})
}
vote.Creator = a.fromAddr
voteValue := types.Encode(vote)
receipt.KV = append(receipt.KV, &types.KeyValue{Key: formatStateIDKey(vote.ID), Value: voteValue})
receipt.Logs = append(receipt.Logs, &types.ReceiptLog{Ty: vty.TyCreateVoteLog, Log: voteValue})
......@@ -136,9 +162,13 @@ func (a *action) commitVote(commit *vty.CommitVote) (*types.Receipt, error) {
receipt := &types.Receipt{Ty: types.ExecOk}
vote, err := a.getVoteInfo(commit.VoteID)
group, err1 := a.getGroupInfo(commit.GroupID)
if err != nil || err1 != nil {
elog.Error("vote exec commitVote", "txHash", a.txHash, "err", err, "err1", err1)
if err != nil {
elog.Error("vote exec commitVote", "txHash", a.txHash, "get vote err", err)
return nil, errStateDBGet
}
group, err := a.getGroupInfo(vote.GroupID)
if err != nil {
elog.Error("vote exec commitVote", "txHash", a.txHash, "get group err", err)
return nil, errStateDBGet
}
......@@ -147,10 +177,34 @@ func (a *action) commitVote(commit *vty.CommitVote) (*types.Receipt, error) {
vote.VoteOptions[commit.OptionIndex].Score += member.VoteWeight
}
}
vote.VotedMembers = append(vote.VotedMembers, a.fromAddr)
info := &vty.CommitInfo{Addr: a.fromAddr}
vote.CommitInfos = append(vote.CommitInfos, info)
voteValue := types.Encode(vote)
info.TxHash = hex.EncodeToString(a.txHash)
receipt.KV = append(receipt.KV, &types.KeyValue{Key: formatStateIDKey(vote.ID), Value: voteValue})
receipt.Logs = append(receipt.Logs, &types.ReceiptLog{Ty: vty.TyCommitVoteLog, Log: voteValue})
receipt.Logs = append(receipt.Logs, &types.ReceiptLog{Ty: vty.TyCommitVoteLog, Log: types.Encode(info)})
return receipt, nil
}
func (a *action) closeVote(close *vty.CloseVote) (*types.Receipt, error) {
receipt := &types.Receipt{Ty: types.ExecOk}
vote, err := a.getVoteInfo(close.VoteID)
if err != nil {
elog.Error("vote exec commitVote", "txHash", a.txHash, "get vote err", err)
return nil, errStateDBGet
}
vote.Status = voteStatusClosed
voteValue := types.Encode(vote)
receipt.KV = append(receipt.KV, &types.KeyValue{Key: formatStateIDKey(vote.ID), Value: voteValue})
receipt.Logs = append(receipt.Logs, &types.ReceiptLog{Ty: vty.TyCloseVoteLog, Log: voteValue})
return receipt, nil
}
func (a *action) updateMember(update *vty.UpdateMember) (*types.Receipt, error) {
receipt := &types.Receipt{Ty: types.ExecOk}
return receipt, nil
}
......@@ -20,12 +20,16 @@ func (v *vote) CheckTx(tx *types.Transaction, index int) error {
}
if action.Ty == vty.TyCreateGroupAction {
err = v.checkCreateGroup(action.GetCreateGroup())
} else if action.Ty == vty.TyUpdateMemberAction {
err = v.checkUpdateMember(action.GetUpdateMember())
} else if action.Ty == vty.TyUpdateGroupAction {
err = v.checkUpdateGroup(action.GetUpdateGroup(), tx, index)
} else if action.Ty == vty.TyCreateVoteAction {
err = v.checkCreateVote(action.GetCreateVote())
err = v.checkCreateVote(action.GetCreateVote(), tx, index)
} else if action.Ty == vty.TyCommitVoteAction {
err = v.checkCommitVote(action.GetCommitVote(), tx, index)
} else if action.Ty == vty.TyCloseVoteAction {
err = v.checkCloseVote(action.GetCloseVote(), tx, index)
} else if action.Ty == vty.TyUpdateMemberAction {
err = v.checkUpdateMember(action.GetUpdateMember())
} else {
err = types.ErrActionNotSupport
}
......@@ -68,19 +72,35 @@ func (v *vote) checkCreateGroup(create *vty.CreateGroup) error {
return nil
}
func (v *vote) checkUpdateMember(update *vty.UpdateMember) error {
func (v *vote) checkUpdateGroup(update *vty.UpdateGroup, tx *types.Transaction, index int) error {
action := newAction(v, tx, index)
groupInfo, err := action.getGroupInfo(update.GetGroupID())
if err != nil {
return err
}
if !checkSliceItemExist(action.fromAddr, groupInfo.GetAdmins()) {
return errAddrPermissionDenied
}
if len(update.GetGroupID()) != IDLen {
return errInvalidGroupID
//防止将管理员全部删除
if len(update.RemoveAdmins) >= len(update.AddAdmins)+len(groupInfo.GetAdmins()) {
return errAddrPermissionDenied
}
addrs := make([]string, 0, len(update.RemoveMembers)+len(update.AddAdmins)+len(update.RemoveAdmins))
addrs = append(addrs, update.RemoveMembers...)
addrs = append(addrs, update.AddAdmins...)
addrs = append(addrs, update.RemoveAdmins...)
for _, member := range update.AddMembers {
if len(member.Addr) != addrLen {
return types.ErrInvalidAddress
}
}
for _, addr := range update.RemoveMemberAddrs {
for _, addr := range addrs {
if len(addr) != addrLen {
elog.Error("checkUpdateGroup", "invalid addr", addr)
return types.ErrInvalidAddress
}
}
......@@ -88,12 +108,21 @@ func (v *vote) checkUpdateMember(update *vty.UpdateMember) error {
return nil
}
func (v *vote) checkCreateVote(create *vty.CreateVote) error {
func (v *vote) checkCreateVote(create *vty.CreateVote, tx *types.Transaction, index int) error {
if create.GetName() == "" {
return errEmptyName
}
action := newAction(v, tx, index)
groupInfo, err := action.getGroupInfo(create.GetGroupID())
if err != nil {
return err
}
if !checkSliceItemExist(action.fromAddr, groupInfo.GetAdmins()) {
return errAddrPermissionDenied
}
if create.GetEndTimestamp() <= v.GetBlockTime() || create.EndTimestamp <= create.BeginTimestamp {
return errInvalidVoteTime
}
......@@ -102,29 +131,13 @@ func (v *vote) checkCreateVote(create *vty.CreateVote) error {
return errInvalidVoteOption
}
if len(create.VoteGroups) == 0 {
return errEmptyVoteGroup
}
if checkSliceItemDuplicate(create.VoteGroups) {
return errDuplicateGroup
}
return nil
}
func (v *vote) checkCommitVote(commit *vty.CommitVote, tx *types.Transaction, index int) error {
voteID := commit.GetVoteID()
groupID := commit.GetGroupID()
if len(voteID) != IDLen {
return errInvalidVoteID
}
if len(groupID) != IDLen {
return errInvalidGroupID
}
action := newAction(v, tx, index)
voteInfo, err := action.getVoteInfo(voteID)
voteInfo, err := action.getVoteInfo(commit.GetVoteID())
if err != nil {
return err
}
......@@ -133,29 +146,52 @@ func (v *vote) checkCommitVote(commit *vty.CommitVote, tx *types.Transaction, in
return errVoteAlreadyFinished
}
if voteInfo.Status == voteStatusClosed {
return errVoteAlreadyClosed
}
if commit.OptionIndex >= uint32(len(voteInfo.VoteOptions)) {
return errInvalidOptionIndex
}
//check group validity
if !checkSliceItemExist(commit.GroupID, voteInfo.VoteGroups) {
return errInvalidGroupID
groupInfo, err := action.getGroupInfo(voteInfo.GroupID)
if err != nil {
return err
}
// check if exist in group members
if !checkMemberExist(action.fromAddr, groupInfo.Members) {
return errAddrPermissionDenied
}
// check if already vote
if checkSliceItemExist(action.fromAddr, voteInfo.VotedMembers) {
for _, info := range voteInfo.GetCommitInfos() {
if action.fromAddr == info.Addr {
return errAlreadyVoted
}
}
return nil
}
groupInfo, err := action.getGroupInfo(commit.GroupID)
func (v *vote) checkCloseVote(close *vty.CloseVote, tx *types.Transaction, index int) error {
action := newAction(v, tx, index)
voteInfo, err := action.getVoteInfo(close.GetVoteID())
if err != nil {
return err
}
// check if exist in group members
if !checkMemberExist(action.fromAddr, groupInfo.Members) {
return errInvalidGroupMember
if voteInfo.Creator != action.fromAddr {
return errAddrPermissionDenied
}
if voteInfo.Status == voteStatusClosed {
return errVoteAlreadyClosed
}
return nil
}
func (v *vote) checkUpdateMember(update *vty.UpdateMember) error {
if update.GetName() == "" {
return errEmptyName
}
return nil
}
......@@ -21,4 +21,6 @@ var (
errAlreadyVoted = errors.New("errAlreadyVoted")
errInvalidGroupMember = errors.New("errInvalidGroupMember")
errVoteAlreadyFinished = errors.New("errVoteAlreadyFinished")
errVoteAlreadyClosed = errors.New("errVoteAlreadyClosed")
errAddrPermissionDenied = errors.New("errAddrPermissionDenied")
)
......@@ -15,9 +15,9 @@ func (v *vote) Exec_CreateGroup(payload *votetypes.CreateGroup, tx *types.Transa
return action.createGroup(payload)
}
func (v *vote) Exec_UpdateMember(payload *votetypes.UpdateMember, tx *types.Transaction, index int) (*types.Receipt, error) {
func (v *vote) Exec_UpdateGroup(payload *votetypes.UpdateGroup, tx *types.Transaction, index int) (*types.Receipt, error) {
action := newAction(v, tx, index)
return action.updateMember(payload)
return action.updateGroup(payload)
}
func (v *vote) Exec_CreateVote(payload *votetypes.CreateVote, tx *types.Transaction, index int) (*types.Receipt, error) {
......@@ -29,3 +29,13 @@ func (v *vote) Exec_CommitVote(payload *votetypes.CommitVote, tx *types.Transact
action := newAction(v, tx, index)
return action.commitVote(payload)
}
func (v *vote) Exec_CloseVote(payload *votetypes.CloseVote, tx *types.Transaction, index int) (*types.Receipt, error) {
action := newAction(v, tx, index)
return action.closeVote(payload)
}
func (v *vote) Exec_UpdateMember(payload *votetypes.UpdateMember, tx *types.Transaction, index int) (*types.Receipt, error) {
action := newAction(v, tx, index)
return action.updateMember(payload)
}
......@@ -17,7 +17,7 @@ func (v *vote) ExecLocal_CreateGroup(payload *vty.CreateGroup, tx *types.Transac
groupInfo := decodeGroupInfo(receiptData.Logs[0].Log)
table := newGroupTable(v.GetLocalDB())
err := table.Add(&vty.GroupVoteInfo{GroupInfo: groupInfo})
err := table.Add(groupInfo)
if err != nil {
elog.Error("execLocal createGroup", "txHash", hex.EncodeToString(tx.Hash()), "table add", err)
return nil, err
......@@ -40,31 +40,31 @@ func (v *vote) ExecLocal_CreateGroup(payload *vty.CreateGroup, tx *types.Transac
return v.addAutoRollBack(tx, dbSet.KV), nil
}
func (v *vote) ExecLocal_UpdateMember(update *vty.UpdateMember, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
func (v *vote) ExecLocal_UpdateGroup(update *vty.UpdateGroup, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
dbSet := &types.LocalDBSet{}
groupInfo := decodeGroupInfo(receiptData.Logs[0].Log)
table := newGroupTable(v.GetLocalDB())
err := table.Replace(&vty.GroupVoteInfo{GroupInfo: groupInfo})
err := table.Replace(groupInfo)
if err != nil {
elog.Error("execLocal updateMember", "txHash", hex.EncodeToString(tx.Hash()), "groupID", groupInfo.ID, "table replace", err)
elog.Error("execLocal UpdateGroup", "txHash", hex.EncodeToString(tx.Hash()), "groupID", groupInfo.ID, "table replace", err)
return nil, err
}
kvs, err := table.Save()
if err != nil {
elog.Error("execLocal updateMember", "txHash", hex.EncodeToString(tx.Hash()), "groupID", groupInfo.ID, "table save", err)
elog.Error("execLocal UpdateGroup", "txHash", hex.EncodeToString(tx.Hash()), "groupID", groupInfo.ID, "table save", err)
return nil, err
}
dbSet.KV = kvs
kvs, err = v.addGroupMember(groupInfo.GetID(), update.AddMembers)
if err != nil {
elog.Error("execLocal updateMember", "txHash", hex.EncodeToString(tx.Hash()), "addMemberErr", err)
elog.Error("execLocal UpdateGroup", "txHash", hex.EncodeToString(tx.Hash()), "addMemberErr", err)
return nil, err
}
dbSet.KV = append(dbSet.KV, kvs...)
kvs, err = v.removeGroupMember(groupInfo.GetID(), update.RemoveMemberAddrs)
kvs, err = v.removeGroupMember(groupInfo.GetID(), update.RemoveMembers)
if err != nil {
elog.Error("execLocal updateMember", "txHash", hex.EncodeToString(tx.Hash()), "removeMemberErr", err)
elog.Error("execLocal UpdateGroup", "txHash", hex.EncodeToString(tx.Hash()), "removeMemberErr", err)
return nil, err
}
dbSet.KV = append(dbSet.KV, kvs...)
......@@ -87,47 +87,97 @@ func (v *vote) ExecLocal_CreateVote(payload *vty.CreateVote, tx *types.Transacti
return nil, err
}
dbSet.KV = kvs
//auto gen for localdb auto rollback
return v.addAutoRollBack(tx, dbSet.KV), nil
}
// 在关联的投票组表中记录voteID信息
table = newGroupTable(v.GetLocalDB())
for _, groupID := range voteInfo.VoteGroups {
row, err := table.GetData([]byte(groupID))
func (v *vote) ExecLocal_CommitVote(payload *vty.CommitVote, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
dbSet := &types.LocalDBSet{}
//implement code, add customize kv to dbSet...
commitInfo := decodeCommitInfo(receiptData.Logs[0].Log)
table := newVoteTable(v.GetLocalDB())
row, err := table.GetData([]byte(formatVoteID(payload.GetVoteID())))
if err != nil {
continue
elog.Error("execLocal commitVote", "txHash", hex.EncodeToString(tx.Hash()), "voteTable get", err)
return nil, err
}
if info, ok := row.Data.(*vty.GroupVoteInfo); ok {
info.VoteIDs = append(info.VoteIDs, voteInfo.ID)
err = table.Replace(info)
voteInfo, ok := row.Data.(*vty.VoteInfo)
if !ok {
elog.Error("execLocal commitVote", "txHash", hex.EncodeToString(tx.Hash()), "voteInfo type asset", err)
return nil, types.ErrTypeAsset
}
voteInfo.CommitInfos = append(voteInfo.CommitInfos, commitInfo)
err = table.Replace(voteInfo)
if err != nil {
elog.Error("execLocal createVote", "txHash", hex.EncodeToString(tx.Hash()),
"groupID", groupID, "groupTable replace", err)
elog.Error("execLocal commitVote", "txHash", hex.EncodeToString(tx.Hash()), "voteTable replace", err)
return nil, err
}
kvs, err := table.Save()
if err != nil {
elog.Error("execLocal commitVote", "txHash", hex.EncodeToString(tx.Hash()), "voteTable save", err)
return nil, err
}
dbSet.KV = kvs
//auto gen for localdb auto rollback
return v.addAutoRollBack(tx, dbSet.KV), nil
}
func (v *vote) ExecLocal_CloseVote(payload *vty.CloseVote, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
dbSet := &types.LocalDBSet{}
table := newVoteTable(v.GetLocalDB())
row, err := table.GetData([]byte(formatVoteID(payload.GetVoteID())))
if err != nil {
elog.Error("execLocal closeVote", "txHash", hex.EncodeToString(tx.Hash()), "voteTable get", err)
return nil, err
}
kvs, err = table.Save()
voteInfo, ok := row.Data.(*vty.VoteInfo)
if !ok {
elog.Error("execLocal closeVote", "txHash", hex.EncodeToString(tx.Hash()), "voteInfo type asset", err)
return nil, types.ErrTypeAsset
}
voteInfo.Status = voteStatusClosed
err = table.Replace(voteInfo)
if err != nil {
elog.Error("execLocal createVote", "txHash", hex.EncodeToString(tx.Hash()), "groupTable save", err)
elog.Error("execLocal closeVote", "txHash", hex.EncodeToString(tx.Hash()), "voteTable replace", err)
return nil, err
}
dbSet.KV = append(dbSet.KV, kvs...)
kvs, err := table.Save()
if err != nil {
elog.Error("execLocal closeVote", "txHash", hex.EncodeToString(tx.Hash()), "voteTable save", err)
return nil, err
}
dbSet.KV = kvs
//auto gen for localdb auto rollback
return v.addAutoRollBack(tx, dbSet.KV), nil
}
func (v *vote) ExecLocal_CommitVote(payload *vty.CommitVote, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
func (v *vote) ExecLocal_UpdateMember(payload *vty.UpdateMember, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
dbSet := &types.LocalDBSet{}
//implement code, add customize kv to dbSet...
voteInfo := decodeVoteInfo(receiptData.Logs[0].Log)
table := newVoteTable(v.GetLocalDB())
err := table.Replace(voteInfo)
table := newMemberTable(v.GetLocalDB())
row, err := table.GetData([]byte(tx.From()))
if err != nil {
elog.Error("execLocal updateMember", "txHash", hex.EncodeToString(tx.Hash()), "memberTable get", err)
return nil, err
}
memberInfo, ok := row.Data.(*vty.MemberInfo)
if !ok {
elog.Error("execLocal updateMember", "txHash", hex.EncodeToString(tx.Hash()), "memberInfo type asset", err)
return nil, types.ErrTypeAsset
}
memberInfo.Name = payload.GetName()
err = table.Replace(memberInfo)
if err != nil {
elog.Error("execLocal commitVote", "txHash", hex.EncodeToString(tx.Hash()), "voteTable add", err)
elog.Error("execLocal updateMember", "txHash", hex.EncodeToString(tx.Hash()), "memberTable replace", err)
return nil, err
}
kvs, err := table.Save()
if err != nil {
elog.Error("execLocal commitVote", "txHash", hex.EncodeToString(tx.Hash()), "voteTable save", err)
elog.Error("execLocal updateMember", "txHash", hex.EncodeToString(tx.Hash()), "memberTable save", err)
return nil, err
}
dbSet.KV = kvs
......
......@@ -5,36 +5,48 @@ import (
vty "github.com/33cn/plugin/plugin/dapp/vote/types"
)
// Query_GroupInfo query group info
func (v *vote) Query_GetGroup(in *types.ReqString) (types.Message, error) {
func (v *vote) getGroup(groupID string) (*vty.GroupInfo, error) {
if len(in.GetData()) != IDLen {
if len(groupID) != IDLen {
return nil, errInvalidGroupID
}
groupID := in.Data
table := newGroupTable(v.GetLocalDB())
row, err := table.GetData([]byte(groupID))
if err != nil {
elog.Error("query getGroup", "id", groupID, "err", err)
elog.Error("query getGroup", "groupID", groupID, "err", err)
return nil, err
}
info, ok := row.Data.(*vty.GroupVoteInfo)
info, ok := row.Data.(*vty.GroupInfo)
if !ok {
return nil, types.ErrTypeAsset
}
return info, nil
}
func (v *vote) Query_GetVote(in *types.ReqString) (types.Message, error) {
// Query_GroupInfo query group info
func (v *vote) Query_GetGroups(in *vty.ReqStrings) (types.Message, error) {
if in == nil {
return nil, types.ErrInvalidParam
}
infos := &vty.GroupInfos{GroupList: make([]*vty.GroupInfo, 0, len(in.GetItems()))}
for _, id := range in.GetItems() {
info, err := v.getGroup(id)
if err != nil {
return nil, err
}
infos.GroupList = append(infos.GroupList, info)
}
return infos, nil
}
if len(in.GetData()) != IDLen {
func (v *vote) getVote(voteID string) (*vty.VoteInfo, error) {
if len(voteID) != IDLen {
return nil, errInvalidVoteID
}
voteID := in.Data
table := newVoteTable(v.GetLocalDB())
row, err := table.GetData([]byte(voteID))
......@@ -49,15 +61,30 @@ func (v *vote) Query_GetVote(in *types.ReqString) (types.Message, error) {
}
return info, nil
}
func (v *vote) Query_GetVotes(in *vty.ReqStrings) (types.Message, error) {
if in == nil {
return nil, types.ErrInvalidParam
}
infos := &vty.VoteInfos{VoteList: make([]*vty.VoteInfo, 0, len(in.GetItems()))}
for _, id := range in.GetItems() {
info, err := v.getVote(id)
if err != nil {
return nil, err
}
infos.VoteList = append(infos.VoteList, info)
}
return classifyVoteList(infos), nil
}
func (v *vote) Query_GetMember(in *types.ReqString) (types.Message, error) {
func (v *vote) getMember(addr string) (*vty.MemberInfo, error) {
if len(in.GetData()) != addrLen {
if len(addr) != addrLen {
return nil, types.ErrInvalidAddress
}
addr := in.Data
table := newMemberTable(v.GetLocalDB())
row, err := table.GetData([]byte(addr))
......@@ -73,6 +100,22 @@ func (v *vote) Query_GetMember(in *types.ReqString) (types.Message, error) {
return info, nil
}
func (v *vote) Query_GetMembers(in *vty.ReqStrings) (types.Message, error) {
if in == nil {
return nil, types.ErrInvalidParam
}
infos := &vty.MemberInfos{MemberList: make([]*vty.MemberInfo, 0, len(in.GetItems()))}
for _, id := range in.GetItems() {
info, err := v.getMember(id)
if err != nil {
return nil, err
}
infos.MemberList = append(infos.MemberList, info)
}
return infos, nil
}
func (v *vote) Query_ListGroup(in *vty.ReqListItem) (types.Message, error) {
if in == nil {
......@@ -87,9 +130,9 @@ func (v *vote) Query_ListGroup(in *vty.ReqListItem) (types.Message, error) {
return nil, err
}
list := &vty.GroupVoteInfos{GroupList: make([]*vty.GroupVoteInfo, 0)}
list := &vty.GroupInfos{GroupList: make([]*vty.GroupInfo, 0, len(rows))}
for _, row := range rows {
info, ok := row.Data.(*vty.GroupVoteInfo)
info, ok := row.Data.(*vty.GroupInfo)
if !ok {
return nil, types.ErrTypeAsset
}
......@@ -99,21 +142,28 @@ func (v *vote) Query_ListGroup(in *vty.ReqListItem) (types.Message, error) {
return list, nil
}
func (v *vote) Query_ListVote(in *vty.ReqListItem) (types.Message, error) {
func (v *vote) Query_ListVote(in *vty.ReqListVote) (types.Message, error) {
if in == nil {
if in.GetListReq() == nil {
return nil, types.ErrInvalidParam
}
table := newVoteTable(v.GetLocalDB())
var primaryKey []byte
primaryKey = append(primaryKey, []byte(in.StartItemID)...)
rows, err := table.ListIndex(voteTablePrimary, nil, primaryKey, in.Count, in.Direction)
//指定了组ID,则查询对应组下的投票列表
groupID := in.GetGroupID()
indexName := voteTablePrimary
var prefix, primaryKey []byte
if len(groupID) > 0 {
indexName = groupTablePrimary
prefix = []byte(groupID)
}
primaryKey = append(primaryKey, []byte(in.GetListReq().GetStartItemID())...)
rows, err := table.ListIndex(indexName, prefix, primaryKey, in.GetListReq().Count, in.GetListReq().Direction)
if err != nil {
elog.Error("query listVote", "err", err, "param", in)
return nil, err
}
list := &vty.VoteInfos{VoteList: make([]*vty.VoteInfo, 0)}
list := &vty.VoteInfos{VoteList: make([]*vty.VoteInfo, 0, len(rows))}
for _, row := range rows {
info, ok := row.Data.(*vty.VoteInfo)
if !ok {
......@@ -122,7 +172,7 @@ func (v *vote) Query_ListVote(in *vty.ReqListItem) (types.Message, error) {
list.VoteList = append(list.VoteList, info)
}
return list, nil
return classifyVoteList(list), nil
}
func (v *vote) Query_ListMember(in *vty.ReqListItem) (types.Message, error) {
......@@ -139,7 +189,7 @@ func (v *vote) Query_ListMember(in *vty.ReqListItem) (types.Message, error) {
return nil, err
}
list := &vty.MemberInfos{MemberList: make([]*vty.MemberInfo, 0)}
list := &vty.MemberInfos{MemberList: make([]*vty.MemberInfo, 0, len(rows))}
for _, row := range rows {
info, ok := row.Data.(*vty.MemberInfo)
if !ok {
......
......@@ -22,6 +22,7 @@ var voteTableOpt = &table.Option{
Prefix: keyPrefixLocalDB,
Name: "vote",
Primary: voteTablePrimary,
Index: []string{groupTablePrimary},
}
var memberTableOpt = &table.Option{
......@@ -53,18 +54,18 @@ func newMemberTable(kvDB db.KV) *table.Table {
//groupTableRow table meta 结构
type groupTableRow struct {
*vty.GroupVoteInfo
*vty.GroupInfo
}
//CreateRow 新建数据行
func (r *groupTableRow) CreateRow() *table.Row {
return &table.Row{Data: &vty.GroupVoteInfo{}}
return &table.Row{Data: &vty.GroupInfo{}}
}
//SetPayload 设置数据
func (r *groupTableRow) SetPayload(data types.Message) error {
if d, ok := data.(*vty.GroupVoteInfo); ok {
r.GroupVoteInfo = d
if d, ok := data.(*vty.GroupInfo); ok {
r.GroupInfo = d
return nil
}
return types.ErrTypeAsset
......@@ -73,7 +74,7 @@ func (r *groupTableRow) SetPayload(data types.Message) error {
//Get 按照indexName 查询 indexValue
func (r *groupTableRow) Get(key string) ([]byte, error) {
if key == groupTablePrimary {
return []byte(r.GroupVoteInfo.GetGroupInfo().GetID()), nil
return []byte(r.GroupInfo.GetID()), nil
}
return nil, types.ErrNotFound
}
......@@ -101,6 +102,8 @@ func (r *voteTableRow) SetPayload(data types.Message) error {
func (r *voteTableRow) Get(key string) ([]byte, error) {
if key == voteTablePrimary {
return []byte(r.VoteInfo.GetID()), nil
} else if key == groupTablePrimary {
return []byte(r.VoteInfo.GetGroupID()), nil
}
return nil, types.ErrNotFound
}
......
......@@ -7,17 +7,22 @@ import (
)
const (
voteStatusNormal = iota
voteStatusClosed
)
const (
// IDLen length of groupID or voteID
IDLen = 65
IDLen = 19
addrLen = 34
)
func formatGroupID(txHash string) string {
return "g" + txHash
func formatGroupID(id string) string {
return "g" + id
}
func formatVoteID(txHash string) string {
return "v" + txHash
func formatVoteID(id string) string {
return "v" + id
}
func checkMemberExist(addr string, members []*vty.GroupMember) bool {
......@@ -76,3 +81,27 @@ func decodeVoteInfo(data []byte) *vty.VoteInfo {
mustDecodeProto(data, info)
return info
}
func decodeCommitInfo(data []byte) *vty.CommitInfo {
info := &vty.CommitInfo{}
mustDecodeProto(data, info)
return info
}
func classifyVoteList(infos *vty.VoteInfos) *vty.ReplyVoteList {
reply := &vty.ReplyVoteList{}
for _, voteInfo := range infos.GetVoteList() {
if voteInfo.Status == voteStatusClosed {
reply.ClosedList = append(reply.ClosedList, voteInfo)
} else if voteInfo.BeginTimestamp > types.Now().Unix() {
reply.PendingList = append(reply.PendingList, voteInfo)
} else if voteInfo.EndTimestamp > types.Now().Unix() {
reply.OngoingList = append(reply.OngoingList, voteInfo)
} else {
reply.FinishedList = append(reply.FinishedList, voteInfo)
}
}
return reply
}
......@@ -7,9 +7,11 @@ message VoteAction {
int32 ty = 1;
oneof value {
CreateGroup createGroup = 2; //创建投票组
UpdateMember updateMember = 3; //更新组成员
UpdateGroup updateGroup = 3; //更新组成员
CreateVote createVote = 4; //创建一个投票
CommitVote commitVote = 5; //组员提交投票
CloseVote closeVote = 6;
UpdateMember updateMember = 7;
}
}
......@@ -23,13 +25,16 @@ message CreateGroup {
string name = 1; //投票组名称
repeated string admins = 2; //管理员地址列表
repeated GroupMember members = 3; //组员
string description = 4;
}
//更新投票组
message UpdateMember {
message UpdateGroup {
string groupID = 1; //投票组ID
repeated GroupMember addMembers = 2; //需要增加的组成员
repeated string removeMemberAddrs = 3; //删除组成员的地址列表
repeated string removeMembers = 3; //删除组成员的地址列表
repeated string addAdmins = 4;
repeated string removeAdmins = 5;
}
// 投票组信息
......@@ -41,6 +46,11 @@ message GroupInfo {
string creator = 4; //创建者
repeated string admins = 5; //管理员列表
repeated GroupMember members = 6; //成员列表
string description = 7;
}
message GroupInfos {
repeated GroupInfo groupList = 1; //投票组信息列表
}
//投票选项
......@@ -52,17 +62,30 @@ message VoteOption {
// 创建投票交易,请求结构
message CreateVote {
string name = 1; //投票名称
repeated string voteGroups = 2; //投票关联组列表
string groupID = 2; //投票关联组列表
repeated string voteOptions = 3; //投票选项列表
int64 beginTimestamp = 4; //投票开始时间戳
int64 endTimestamp = 5; //投票结束时间戳
string description = 6;
}
// 创建提交投票交易,请求结构
message CommitVote {
string voteID = 1; //投票ID
string groupID = 2; //所属投票组ID
uint32 optionIndex = 3; //投票选项数组下标,下标对应投票内容
uint32 optionIndex = 2; //投票选项数组下标,下标对应投票内容
}
message CommitInfo {
string addr = 1;
string txHash = 2;
}
message CloseVote {
string voteID = 1;
}
message UpdateMember {
string name = 1;
}
//投票信息
......@@ -70,40 +93,50 @@ message VoteInfo {
string ID = 1; //投票ID
string name = 2; //投票名称
string creator = 3; //投票创建者
repeated string voteGroups = 4; //投票关联的投票组
string creator = 3; //创建者
string groupID = 4; //投票关联的投票组
repeated VoteOption voteOptions = 5; //投票的选项
int64 beginTimestamp = 6; //投票开始时间戳
int64 endTimestamp = 7; //投票结束时间戳
repeated string votedMembers = 8; //已投票的成员
repeated CommitInfo commitInfos = 8; //已投票的提交信息
string description = 9;
uint32 status = 10;
}
message VoteInfos {
repeated VoteInfo voteList = 1; //投票信息列表
}
message GroupVoteInfo {
GroupInfo groupInfo = 1; // 投票组信息
repeated string voteIDs = 2; //投票组关联的投票ID信息
}
message GroupVoteInfos {
repeated GroupVoteInfo groupList = 1; //投票组信息列表
}
message MemberInfo {
string addr = 1; //地址
repeated string groupIDs = 2; //所属投票组的ID列表
string name = 2;
repeated string groupIDs = 3; //所属投票组的ID列表
}
message MemberInfos {
repeated MemberInfo memberList = 1; //投票组成员信息列表
}
message ReqStrings {
repeated string items = 1;
}
//列表请求结构
message ReqListItem {
string startItemID = 1; //列表开始的ID,如请求组列表即groupID,不包含在结果中
int32 count = 2; //请求列表项数量
int32 direction = 3; // 0表示根据ID降序,1表示升序
}
message ReqListVote {
string groupID = 1;
ReqListItem listReq = 2;
}
message ReplyVoteList {
repeated VoteInfo pendingList = 1;
repeated VoteInfo ongoingList = 2;
repeated VoteInfo finishedList = 3;
repeated VoteInfo closedList = 4;
}
......@@ -17,28 +17,36 @@ import (
const (
TyUnknowAction = iota + 100
TyCreateGroupAction
TyUpdateMemberAction
TyUpdateGroupAction
TyCreateVoteAction
TyCommitVoteAction
TyCloseVoteAction
TyUpdateMemberAction
NameCreateGroupAction = "CreateGroup"
NameUpdateMemberAction = "UpdateMember"
NameUpdateGroupAction = "UpdateGroup"
NameCreateVoteAction = "CreateVote"
NameCommitVoteAction = "CommitVote"
NameCloseVoteAction = "CloseVote"
NameUpdateMemberAction = "UpdateMember"
)
// log类型id值
const (
TyUnknownLog = iota + 100
TyCreateGroupLog
TyUpdateMemberLog
TyUpdateGroupLog
TyCreateVoteLog
TyCommitVoteLog
TyCloseVoteLog
TyUpdateMemberLog
NameCreateGroupLog = "CreateGroupLog"
NameUpdateMemberLog = "UpdateMemberLog"
NameUpdateGroupLog = "UpdateGroupLog"
NameCreateVoteLog = "CreateVoteLog"
NameCommitVoteLog = "CommitVoteLog"
NameCloseVoteLog = "CloseVoteLog"
NameUpdateMemberLog = "UpdateMemberLog"
)
var (
......@@ -47,16 +55,20 @@ var (
//定义actionMap
actionMap = map[string]int32{
NameCreateGroupAction: TyCreateGroupAction,
NameUpdateMemberAction: TyUpdateMemberAction,
NameUpdateGroupAction: TyUpdateGroupAction,
NameCreateVoteAction: TyCreateVoteAction,
NameCommitVoteAction: TyCommitVoteAction,
NameCloseVoteAction: TyCloseVoteAction,
NameUpdateMemberAction: TyUpdateMemberAction,
}
//定义log的id和具体log类型及名称,填入具体自定义log类型
logMap = map[int64]*types.LogInfo{
TyCreateGroupLog: {Ty: reflect.TypeOf(GroupInfo{}), Name: NameCreateGroupLog},
TyUpdateMemberLog: {Ty: reflect.TypeOf(GroupInfo{}), Name: NameUpdateMemberLog},
TyUpdateGroupLog: {Ty: reflect.TypeOf(GroupInfo{}), Name: NameUpdateGroupLog},
TyCreateVoteLog: {Ty: reflect.TypeOf(VoteInfo{}), Name: NameCreateVoteLog},
TyCommitVoteLog: {Ty: reflect.TypeOf(VoteInfo{}), Name: NameCommitVoteLog},
TyCommitVoteLog: {Ty: reflect.TypeOf(CommitInfo{}), Name: NameCommitVoteLog},
TyCloseVoteLog: {Ty: reflect.TypeOf(VoteInfo{}), Name: NameCloseVoteLog},
TyUpdateMemberLog: {Ty: reflect.TypeOf(MemberInfo{}), Name: NameUpdateMemberLog},
}
tlog = log.New("module", "vote.types")
)
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment