Unverified Commit 36fdfd31 authored by vipwzw's avatar vipwzw Committed by GitHub

Merge pull request #597 from lyh169/autonomyV2

Autonomy v2
parents 03f50573 fb8defde
...@@ -31,6 +31,7 @@ func AutonomyCmd() *cobra.Command { ...@@ -31,6 +31,7 @@ func AutonomyCmd() *cobra.Command {
VoteProposalBoardCmd(), VoteProposalBoardCmd(),
TerminateProposalBoardCmd(), TerminateProposalBoardCmd(),
ShowProposalBoardCmd(), ShowProposalBoardCmd(),
ShowActiveBoardCmd(),
) )
// project // project
...@@ -50,6 +51,7 @@ func AutonomyCmd() *cobra.Command { ...@@ -50,6 +51,7 @@ func AutonomyCmd() *cobra.Command {
VoteProposalRuleCmd(), VoteProposalRuleCmd(),
TerminateProposalRuleCmd(), TerminateProposalRuleCmd(),
ShowProposalRuleCmd(), ShowProposalRuleCmd(),
ShowActiveRuleCmd(),
) )
cmd.AddCommand( cmd.AddCommand(
...@@ -58,6 +60,15 @@ func AutonomyCmd() *cobra.Command { ...@@ -58,6 +60,15 @@ func AutonomyCmd() *cobra.Command {
ShowProposalCommentCmd(), ShowProposalCommentCmd(),
) )
// change
cmd.AddCommand(
ProposalChangeCmd(),
RevokeProposalChangeCmd(),
VoteProposalChangeCmd(),
TerminateProposalChangeCmd(),
ShowProposalChangeCmd(),
)
return cmd return cmd
} }
...@@ -81,7 +92,7 @@ func addProposalBoardFlags(cmd *cobra.Command) { ...@@ -81,7 +92,7 @@ func addProposalBoardFlags(cmd *cobra.Command) {
cmd.Flags().Int64P("endBlock", "e", 0, "end block height") cmd.Flags().Int64P("endBlock", "e", 0, "end block height")
cmd.MarkFlagRequired("endBlock") cmd.MarkFlagRequired("endBlock")
cmd.Flags().StringP("boards", "b", "", "addr1-addr2......addrN (3<=N<=30)") cmd.Flags().StringP("boards", "b", "", "addr1-addr2......addrN (20<=N<=40)")
cmd.MarkFlagRequired("boards") cmd.MarkFlagRequired("boards")
} }
...@@ -173,22 +184,30 @@ func addVoteProposalBoardFlags(cmd *cobra.Command) { ...@@ -173,22 +184,30 @@ func addVoteProposalBoardFlags(cmd *cobra.Command) {
cmd.Flags().StringP("proposalID", "p", "", "proposal ID") cmd.Flags().StringP("proposalID", "p", "", "proposal ID")
cmd.MarkFlagRequired("proposalID") cmd.MarkFlagRequired("proposalID")
cmd.Flags().Int32P("approve", "r", 1, "is approve, default true") cmd.Flags().Int32P("approve", "r", 1, "is approve, default true")
cmd.Flags().StringP("originAddr", "o", "", "origin address: addr1-addr2......addrN")
} }
func voteProposalBoard(cmd *cobra.Command, args []string) { func voteProposalBoard(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr") rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
ID, _ := cmd.Flags().GetString("proposalID") ID, _ := cmd.Flags().GetString("proposalID")
approve, _ := cmd.Flags().GetInt32("approve") approve, _ := cmd.Flags().GetInt32("approve")
originAddr, _ := cmd.Flags().GetString("originAddr")
var isapp bool var isapp bool
if approve == 0 { if approve == 0 {
isapp = false isapp = false
} else { } else {
isapp = true isapp = true
} }
var originAddrs []string
if len(originAddr) > 0 {
originAddrs = strings.Split(originAddr, "-")
}
params := &auty.VoteProposalBoard{ params := &auty.VoteProposalBoard{
ProposalID: ID, ProposalID: ID,
Approve: isapp, Approve: isapp,
OriginAddr: originAddrs,
} }
payLoad, err := json.Marshal(params) payLoad, err := json.Marshal(params)
if err != nil { if err != nil {
...@@ -246,7 +265,7 @@ func terminateProposalBoard(cmd *cobra.Command, args []string) { ...@@ -246,7 +265,7 @@ func terminateProposalBoard(cmd *cobra.Command, args []string) {
// ShowProposalBoardCmd 显示提案查询信息 // ShowProposalBoardCmd 显示提案查询信息
func ShowProposalBoardCmd() *cobra.Command { func ShowProposalBoardCmd() *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "showBoardInfo", Use: "showBoard",
Short: "show proposal board info", Short: "show proposal board info",
Run: showProposalBoard, Run: showProposalBoard,
} }
...@@ -305,3 +324,26 @@ func showProposalBoard(cmd *cobra.Command, args []string) { ...@@ -305,3 +324,26 @@ func showProposalBoard(cmd *cobra.Command, args []string) {
ctx := jsonrpc.NewRPCCtx(rpcLaddr, "Chain33.Query", params, rep) ctx := jsonrpc.NewRPCCtx(rpcLaddr, "Chain33.Query", params, rep)
ctx.Run() ctx.Run()
} }
// ShowActiveBoardCmd 显示提案查询信息
func ShowActiveBoardCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "showActiveBoard",
Short: "show active board",
Run: showActiveBoard,
}
return cmd
}
func showActiveBoard(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
params := rpctypes.Query4Jrpc{}
params.Execer = auty.AutonomyX
params.FuncName = auty.GetActiveBoard
params.Payload = types.MustPBToJSON(&types.ReqString{})
rep := &auty.ActiveBoard{}
ctx := jsonrpc.NewRPCCtx(rpcLaddr, "Chain33.Query", params, rep)
ctx.Run()
}
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package commands
import (
"strings"
"encoding/json"
jsonrpc "github.com/33cn/chain33/rpc/jsonclient"
rpctypes "github.com/33cn/chain33/rpc/types"
"github.com/33cn/chain33/types"
auty "github.com/33cn/plugin/plugin/dapp/autonomy/types"
"github.com/spf13/cobra"
)
// ProposalChangeCmd 创建提案命令
func ProposalChangeCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "proposalchange",
Short: "create proposal change",
Run: proposalChange,
}
addProposalChangeFlags(cmd)
return cmd
}
func addProposalChangeFlags(cmd *cobra.Command) {
cmd.Flags().Int32P("year", "y", 0, "year")
cmd.Flags().Int32P("month", "m", 0, "month")
cmd.Flags().Int32P("day", "d", 0, "day")
cmd.Flags().Int64P("startBlock", "s", 0, "start block height")
cmd.MarkFlagRequired("startBlock")
cmd.Flags().Int64P("endBlock", "e", 0, "end block height")
cmd.MarkFlagRequired("endBlock")
cmd.Flags().StringP("changes", "c", "", "addr1-true*addr2-false*addr3-true*......*addrN-false (1<=N<20)")
cmd.MarkFlagRequired("changes")
}
func proposalChange(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
year, _ := cmd.Flags().GetInt32("year")
month, _ := cmd.Flags().GetInt32("month")
day, _ := cmd.Flags().GetInt32("day")
startBlock, _ := cmd.Flags().GetInt64("startBlock")
endBlock, _ := cmd.Flags().GetInt64("endBlock")
changestr, _ := cmd.Flags().GetString("changes")
changeStr := strings.Split(changestr, "*")
var changes []*auty.Change
for _, chStr := range changeStr {
per := strings.Split(chStr, "-")
if len(per) == 2 {
if per[1] == "true" {
change := &auty.Change{
Cancel: true,
Addr: per[0],
}
changes = append(changes, change)
} else if per[1] == "false" {
change := &auty.Change{
Cancel: false,
Addr: per[0],
}
changes = append(changes, change)
}
}
}
params := &auty.ProposalChange{
Year: year,
Month: month,
Day: day,
Changes: changes,
StartBlockHeight: startBlock,
EndBlockHeight: endBlock,
}
payLoad, err := json.Marshal(params)
if err != nil {
return
}
pm := &rpctypes.CreateTxIn{
Execer: types.ExecName(auty.AutonomyX),
ActionName: "PropChange",
Payload: payLoad,
}
var res string
ctx := jsonrpc.NewRPCCtx(rpcLaddr, "Chain33.CreateTransaction", pm, &res)
ctx.RunWithoutMarshal()
}
// RevokeProposalChangeCmd 撤销提案
func RevokeProposalChangeCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "revokeChange",
Short: "revoke proposal change",
Run: revokeProposalChange,
}
addRevokeProposalChangeFlags(cmd)
return cmd
}
func addRevokeProposalChangeFlags(cmd *cobra.Command) {
cmd.Flags().StringP("proposalID", "p", "", "proposal ID")
cmd.MarkFlagRequired("proposalID")
}
func revokeProposalChange(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
ID, _ := cmd.Flags().GetString("proposalID")
params := &auty.RevokeProposalChange{
ProposalID: ID,
}
payLoad, err := json.Marshal(params)
if err != nil {
return
}
pm := &rpctypes.CreateTxIn{
Execer: types.ExecName(auty.AutonomyX),
ActionName: "RvkPropChange",
Payload: payLoad,
}
var res string
ctx := jsonrpc.NewRPCCtx(rpcLaddr, "Chain33.CreateTransaction", pm, &res)
ctx.RunWithoutMarshal()
}
// VoteProposalChangeCmd 投票提案
func VoteProposalChangeCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "voteChange",
Short: "vote proposal change",
Run: voteProposalChange,
}
addVoteProposalChangeFlags(cmd)
return cmd
}
func addVoteProposalChangeFlags(cmd *cobra.Command) {
cmd.Flags().StringP("proposalID", "p", "", "proposal ID")
cmd.MarkFlagRequired("proposalID")
cmd.Flags().Int32P("approve", "r", 1, "is approve, default true")
}
func voteProposalChange(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
ID, _ := cmd.Flags().GetString("proposalID")
approve, _ := cmd.Flags().GetInt32("approve")
var isapp bool
if approve == 0 {
isapp = false
} else {
isapp = true
}
params := &auty.VoteProposalChange{
ProposalID: ID,
Approve: isapp,
}
payLoad, err := json.Marshal(params)
if err != nil {
return
}
pm := &rpctypes.CreateTxIn{
Execer: types.ExecName(auty.AutonomyX),
ActionName: "VotePropChange",
Payload: payLoad,
}
var res string
ctx := jsonrpc.NewRPCCtx(rpcLaddr, "Chain33.CreateTransaction", pm, &res)
ctx.RunWithoutMarshal()
}
// TerminateProposalChangeCmd 终止提案
func TerminateProposalChangeCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "terminateChange",
Short: "terminate proposal change",
Run: terminateProposalChange,
}
addTerminateProposalChangeFlags(cmd)
return cmd
}
func addTerminateProposalChangeFlags(cmd *cobra.Command) {
cmd.Flags().StringP("proposalID", "p", "", "proposal ID")
cmd.MarkFlagRequired("proposalID")
}
func terminateProposalChange(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
ID, _ := cmd.Flags().GetString("proposalID")
params := &auty.RevokeProposalChange{
ProposalID: ID,
}
payLoad, err := json.Marshal(params)
if err != nil {
return
}
pm := &rpctypes.CreateTxIn{
Execer: types.ExecName(auty.AutonomyX),
ActionName: "TmintPropChange",
Payload: payLoad,
}
var res string
ctx := jsonrpc.NewRPCCtx(rpcLaddr, "Chain33.CreateTransaction", pm, &res)
ctx.RunWithoutMarshal()
}
// ShowProposalChangeCmd 显示提案查询信息
func ShowProposalChangeCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "showChange",
Short: "show proposal change info",
Run: showProposalChange,
}
addShowProposalChangeflags(cmd)
return cmd
}
func addShowProposalChangeflags(cmd *cobra.Command) {
cmd.Flags().Uint32P("type", "y", 0, "type(0:query by hash; 1:list)")
cmd.MarkFlagRequired("type")
cmd.Flags().StringP("proposalID", "p", "", "proposal ID")
cmd.Flags().Uint32P("status", "s", 0, "status")
cmd.Flags().StringP("addr", "a", "", "address")
cmd.Flags().Int32P("count", "c", 1, "count, default is 1")
cmd.Flags().Int32P("direction", "d", -1, "direction, default is reserve")
cmd.Flags().Int64P("height", "t", -1, "height, default is -1")
cmd.Flags().Int32P("index", "i", -1, "index, default is -1")
}
func showProposalChange(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
typ, _ := cmd.Flags().GetUint32("type")
propID, _ := cmd.Flags().GetString("proposalID")
status, _ := cmd.Flags().GetUint32("status")
addr, _ := cmd.Flags().GetString("addr")
count, _ := cmd.Flags().GetInt32("count")
direction, _ := cmd.Flags().GetInt32("direction")
height, _ := cmd.Flags().GetInt64("height")
index, _ := cmd.Flags().GetInt32("index")
var params rpctypes.Query4Jrpc
var rep interface{}
params.Execer = auty.AutonomyX
if 0 == typ {
req := types.ReqString{
Data: propID,
}
params.FuncName = auty.GetProposalChange
params.Payload = types.MustPBToJSON(&req)
} else if 1 == typ {
req := auty.ReqQueryProposalChange{
Status: int32(status),
Addr: addr,
Count: count,
Direction: direction,
Height: height,
Index: index,
}
params.FuncName = auty.ListProposalChange
params.Payload = types.MustPBToJSON(&req)
}
rep = &auty.ReplyQueryProposalChange{}
ctx := jsonrpc.NewRPCCtx(rpcLaddr, "Chain33.Query", params, rep)
ctx.Run()
}
...@@ -7,6 +7,8 @@ package commands ...@@ -7,6 +7,8 @@ package commands
import ( import (
"encoding/json" "encoding/json"
"strings"
jsonrpc "github.com/33cn/chain33/rpc/jsonclient" jsonrpc "github.com/33cn/chain33/rpc/jsonclient"
rpctypes "github.com/33cn/chain33/rpc/types" rpctypes "github.com/33cn/chain33/rpc/types"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
...@@ -200,13 +202,15 @@ func PubVoteProposalProjectCmd() *cobra.Command { ...@@ -200,13 +202,15 @@ func PubVoteProposalProjectCmd() *cobra.Command {
func addPubVoteProposalProjectFlags(cmd *cobra.Command) { func addPubVoteProposalProjectFlags(cmd *cobra.Command) {
cmd.Flags().StringP("proposalID", "p", "", "proposal ID") cmd.Flags().StringP("proposalID", "p", "", "proposal ID")
cmd.MarkFlagRequired("proposalID") cmd.MarkFlagRequired("proposalID")
cmd.Flags().Int32P("oppose", "o", 1, "is oppose, default true") cmd.Flags().Int32P("oppose", "s", 1, "is oppose, default true")
cmd.Flags().StringP("originAddr", "o", "", "origin address: addr1-addr2......addrN")
} }
func pubVoteProposalProject(cmd *cobra.Command, args []string) { func pubVoteProposalProject(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr") rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
ID, _ := cmd.Flags().GetString("proposalID") ID, _ := cmd.Flags().GetString("proposalID")
oppose, _ := cmd.Flags().GetInt32("oppose") oppose, _ := cmd.Flags().GetInt32("oppose")
originAddr, _ := cmd.Flags().GetString("originAddr")
var isopp bool var isopp bool
if oppose == 0 { if oppose == 0 {
...@@ -215,9 +219,15 @@ func pubVoteProposalProject(cmd *cobra.Command, args []string) { ...@@ -215,9 +219,15 @@ func pubVoteProposalProject(cmd *cobra.Command, args []string) {
isopp = true isopp = true
} }
var originAddrs []string
if len(originAddr) > 0 {
originAddrs = strings.Split(originAddr, "-")
}
params := &auty.PubVoteProposalProject{ params := &auty.PubVoteProposalProject{
ProposalID: ID, ProposalID: ID,
Oppose: isopp, Oppose: isopp,
OriginAddr: originAddrs,
} }
payLoad, err := json.Marshal(params) payLoad, err := json.Marshal(params)
if err != nil { if err != nil {
...@@ -273,7 +283,7 @@ func terminateProposalProject(cmd *cobra.Command, args []string) { ...@@ -273,7 +283,7 @@ func terminateProposalProject(cmd *cobra.Command, args []string) {
// ShowProposalProjectCmd 显示提案查询信息 // ShowProposalProjectCmd 显示提案查询信息
func ShowProposalProjectCmd() *cobra.Command { func ShowProposalProjectCmd() *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "showProjectInfo", Use: "showProject",
Short: "show proposal project info", Short: "show proposal project info",
Run: showProposalProject, Run: showProposalProject,
} }
......
...@@ -7,6 +7,8 @@ package commands ...@@ -7,6 +7,8 @@ package commands
import ( import (
"encoding/json" "encoding/json"
"strings"
jsonrpc "github.com/33cn/chain33/rpc/jsonclient" jsonrpc "github.com/33cn/chain33/rpc/jsonclient"
rpctypes "github.com/33cn/chain33/rpc/types" rpctypes "github.com/33cn/chain33/rpc/types"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
...@@ -52,7 +54,6 @@ func proposalRule(cmd *cobra.Command, args []string) { ...@@ -52,7 +54,6 @@ func proposalRule(cmd *cobra.Command, args []string) {
startBlock, _ := cmd.Flags().GetInt64("startBlock") startBlock, _ := cmd.Flags().GetInt64("startBlock")
endBlock, _ := cmd.Flags().GetInt64("endBlock") endBlock, _ := cmd.Flags().GetInt64("endBlock")
boardAttendRatio, _ := cmd.Flags().GetInt32("boardAttendRatio")
boardApproveRatio, _ := cmd.Flags().GetInt32("boardApproveRatio") boardApproveRatio, _ := cmd.Flags().GetInt32("boardApproveRatio")
pubOpposeRatio, _ := cmd.Flags().GetInt32("pubOpposeRatio") pubOpposeRatio, _ := cmd.Flags().GetInt32("pubOpposeRatio")
...@@ -65,7 +66,6 @@ func proposalRule(cmd *cobra.Command, args []string) { ...@@ -65,7 +66,6 @@ func proposalRule(cmd *cobra.Command, args []string) {
Month: month, Month: month,
Day: day, Day: day,
RuleCfg: &auty.RuleConfig{ RuleCfg: &auty.RuleConfig{
BoardAttendRatio: boardAttendRatio,
BoardApproveRatio: boardApproveRatio, BoardApproveRatio: boardApproveRatio,
PubOpposeRatio: pubOpposeRatio, PubOpposeRatio: pubOpposeRatio,
ProposalAmount: proposalAmount * types.Coin, ProposalAmount: proposalAmount * types.Coin,
...@@ -142,12 +142,14 @@ func addVoteProposalRuleFlags(cmd *cobra.Command) { ...@@ -142,12 +142,14 @@ func addVoteProposalRuleFlags(cmd *cobra.Command) {
cmd.Flags().StringP("proposalID", "p", "", "proposal ID") cmd.Flags().StringP("proposalID", "p", "", "proposal ID")
cmd.MarkFlagRequired("proposalID") cmd.MarkFlagRequired("proposalID")
cmd.Flags().Int32P("approve", "r", 1, "is approve, default true") cmd.Flags().Int32P("approve", "r", 1, "is approve, default true")
cmd.Flags().StringP("originAddr", "o", "", "origin address: addr1-addr2......addrN")
} }
func voteProposalRule(cmd *cobra.Command, args []string) { func voteProposalRule(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr") rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
ID, _ := cmd.Flags().GetString("proposalID") ID, _ := cmd.Flags().GetString("proposalID")
approve, _ := cmd.Flags().GetInt32("approve") approve, _ := cmd.Flags().GetInt32("approve")
originAddr, _ := cmd.Flags().GetString("originAddr")
var isapp bool var isapp bool
if approve == 0 { if approve == 0 {
isapp = false isapp = false
...@@ -155,9 +157,15 @@ func voteProposalRule(cmd *cobra.Command, args []string) { ...@@ -155,9 +157,15 @@ func voteProposalRule(cmd *cobra.Command, args []string) {
isapp = true isapp = true
} }
var originAddrs []string
if len(originAddr) > 0 {
originAddrs = strings.Split(originAddr, "-")
}
params := &auty.VoteProposalRule{ params := &auty.VoteProposalRule{
ProposalID: ID, ProposalID: ID,
Approve: isapp, Approve: isapp,
OriginAddr: originAddrs,
} }
payLoad, err := json.Marshal(params) payLoad, err := json.Marshal(params)
if err != nil { if err != nil {
...@@ -213,7 +221,7 @@ func terminateProposalRule(cmd *cobra.Command, args []string) { ...@@ -213,7 +221,7 @@ func terminateProposalRule(cmd *cobra.Command, args []string) {
// ShowProposalRuleCmd 显示提案查询信息 // ShowProposalRuleCmd 显示提案查询信息
func ShowProposalRuleCmd() *cobra.Command { func ShowProposalRuleCmd() *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "showRuleInfo", Use: "showRule",
Short: "show proposal rule info", Short: "show proposal rule info",
Run: showProposalRule, Run: showProposalRule,
} }
...@@ -273,6 +281,29 @@ func showProposalRule(cmd *cobra.Command, args []string) { ...@@ -273,6 +281,29 @@ func showProposalRule(cmd *cobra.Command, args []string) {
ctx.Run() ctx.Run()
} }
// ShowActiveRuleCmd 显示提案查询信息
func ShowActiveRuleCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "showActiveRule",
Short: "show active rule",
Run: showActiveRule,
}
return cmd
}
func showActiveRule(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
params := rpctypes.Query4Jrpc{}
params.Execer = auty.AutonomyX
params.FuncName = auty.GetActiveRule
params.Payload = types.MustPBToJSON(&types.ReqString{})
rep := &auty.RuleConfig{}
ctx := jsonrpc.NewRPCCtx(rpcLaddr, "Chain33.Query", params, rep)
ctx.Run()
}
// TransferFundCmd 资金转入自治系统合约中 // TransferFundCmd 资金转入自治系统合约中
func TransferFundCmd() *cobra.Command { func TransferFundCmd() *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
......
...@@ -134,3 +134,16 @@ func (a *Autonomy) listProposalBoard(req *auty.ReqQueryProposalBoard) (types.Mes ...@@ -134,3 +134,16 @@ func (a *Autonomy) listProposalBoard(req *auty.ReqQueryProposalBoard) (types.Mes
} }
return &rep, nil return &rep, nil
} }
func (a *Autonomy) getActiveBoard() (types.Message, error) {
value, err := a.GetStateDB().Get(activeBoardID())
if err != nil {
return nil, err
}
prop := &auty.ActiveBoard{}
err = types.Decode(value, prop)
if err != nil {
return nil, err
}
return prop, nil
}
...@@ -13,7 +13,6 @@ import ( ...@@ -13,7 +13,6 @@ import (
"github.com/33cn/chain33/util" "github.com/33cn/chain33/util"
auty "github.com/33cn/plugin/plugin/dapp/autonomy/types" auty "github.com/33cn/plugin/plugin/dapp/autonomy/types"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
func TestExecLocalBoard(t *testing.T) { func TestExecLocalBoard(t *testing.T) {
...@@ -49,14 +48,14 @@ func testexecLocalBoard(t *testing.T, auto bool) { ...@@ -49,14 +48,14 @@ func testexecLocalBoard(t *testing.T, auto bool) {
var err error var err error
if !auto { if !auto {
set, err = au.execLocalBoard(receipt) set, err = au.execLocalBoard(receipt)
require.NoError(t, err) assert.NoError(t, err)
require.NotNil(t, set) assert.NotNil(t, set)
} else { } else {
tx, err := types.CreateFormatTx(types.ExecName(auty.AutonomyX), nil) tx, err := types.CreateFormatTx(types.ExecName(auty.AutonomyX), nil)
assert.NoError(t, err) assert.NoError(t, err)
set, err = au.execAutoLocalBoard(tx, receipt) set, err = au.execAutoLocalBoard(tx, receipt)
require.NoError(t, err) assert.NoError(t, err)
require.NotNil(t, set) assert.NotNil(t, set)
} }
//save to database //save to database
...@@ -78,8 +77,8 @@ func testexecLocalBoard(t *testing.T, auto bool) { ...@@ -78,8 +77,8 @@ func testexecLocalBoard(t *testing.T, auto bool) {
{Ty: auty.TyLogRvkPropBoard, Log: types.Encode(receiptBoard1)}, {Ty: auty.TyLogRvkPropBoard, Log: types.Encode(receiptBoard1)},
}, },
}) })
require.NoError(t, err) assert.NoError(t, err)
require.NotNil(t, set) assert.NotNil(t, set)
} else { } else {
tx, err := types.CreateFormatTx(types.ExecName(auty.AutonomyX), nil) tx, err := types.CreateFormatTx(types.ExecName(auty.AutonomyX), nil)
assert.NoError(t, err) assert.NoError(t, err)
...@@ -89,8 +88,8 @@ func testexecLocalBoard(t *testing.T, auto bool) { ...@@ -89,8 +88,8 @@ func testexecLocalBoard(t *testing.T, auto bool) {
{Ty: auty.TyLogRvkPropBoard, Log: types.Encode(receiptBoard1)}, {Ty: auty.TyLogRvkPropBoard, Log: types.Encode(receiptBoard1)},
}, },
}) })
require.NoError(t, err) assert.NoError(t, err)
require.NotNil(t, set) assert.NotNil(t, set)
} }
//save to database //save to database
...@@ -114,8 +113,8 @@ func testexecLocalBoard(t *testing.T, auto bool) { ...@@ -114,8 +113,8 @@ func testexecLocalBoard(t *testing.T, auto bool) {
{Ty: auty.TyLogVotePropBoard, Log: types.Encode(receiptBoard2)}, {Ty: auty.TyLogVotePropBoard, Log: types.Encode(receiptBoard2)},
}, },
}) })
require.NoError(t, err) assert.NoError(t, err)
require.NotNil(t, set) assert.NotNil(t, set)
} else { } else {
tx, err := types.CreateFormatTx(types.ExecName(auty.AutonomyX), nil) tx, err := types.CreateFormatTx(types.ExecName(auty.AutonomyX), nil)
assert.NoError(t, err) assert.NoError(t, err)
...@@ -125,8 +124,8 @@ func testexecLocalBoard(t *testing.T, auto bool) { ...@@ -125,8 +124,8 @@ func testexecLocalBoard(t *testing.T, auto bool) {
{Ty: auty.TyLogVotePropBoard, Log: types.Encode(receiptBoard2)}, {Ty: auty.TyLogVotePropBoard, Log: types.Encode(receiptBoard2)},
}, },
}) })
require.NoError(t, err) assert.NoError(t, err)
require.NotNil(t, set) assert.NotNil(t, set)
} }
//save to database //save to database
...@@ -168,13 +167,13 @@ func testexecDelLocalBoard(t *testing.T) { ...@@ -168,13 +167,13 @@ func testexecDelLocalBoard(t *testing.T) {
tx, err := types.CreateFormatTx(types.ExecName(auty.AutonomyX), nil) tx, err := types.CreateFormatTx(types.ExecName(auty.AutonomyX), nil)
assert.NoError(t, err) assert.NoError(t, err)
set, err := au.execAutoLocalBoard(tx, receipt) set, err := au.execAutoLocalBoard(tx, receipt)
require.NoError(t, err) assert.NoError(t, err)
require.NotNil(t, set) assert.NotNil(t, set)
saveKvs(sdb, set.KV) saveKvs(sdb, set.KV)
set, err = au.execAutoDelLocal(tx, receipt) set, err = au.execAutoDelLocal(tx, receipt)
require.NoError(t, err) assert.NoError(t, err)
require.NotNil(t, set) assert.NotNil(t, set)
saveKvs(sdb, set.KV) saveKvs(sdb, set.KV)
// check // check
...@@ -206,8 +205,8 @@ func testexecDelLocalBoard(t *testing.T) { ...@@ -206,8 +205,8 @@ func testexecDelLocalBoard(t *testing.T) {
tx, err = types.CreateFormatTx(types.ExecName(auty.AutonomyX), nil) tx, err = types.CreateFormatTx(types.ExecName(auty.AutonomyX), nil)
assert.NoError(t, err) assert.NoError(t, err)
set, err = au.execAutoLocalBoard(tx, receipt) set, err = au.execAutoLocalBoard(tx, receipt)
require.NoError(t, err) assert.NoError(t, err)
require.NotNil(t, set) assert.NotNil(t, set)
saveKvs(sdb, set.KV) saveKvs(sdb, set.KV)
// 正常测试退回 // 正常测试退回
...@@ -215,15 +214,15 @@ func testexecDelLocalBoard(t *testing.T) { ...@@ -215,15 +214,15 @@ func testexecDelLocalBoard(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
set, err = au.execAutoLocalBoard(tx, recpt) set, err = au.execAutoLocalBoard(tx, recpt)
require.NoError(t, err) assert.NoError(t, err)
require.NotNil(t, set) assert.NotNil(t, set)
saveKvs(sdb, set.KV) saveKvs(sdb, set.KV)
// check // check
checkExecLocalBoard(t, kvdb, cur) checkExecLocalBoard(t, kvdb, cur)
set, err = au.execAutoDelLocal(tx, recpt) set, err = au.execAutoDelLocal(tx, recpt)
require.NoError(t, err) assert.NoError(t, err)
require.NotNil(t, set) assert.NotNil(t, set)
saveKvs(sdb, set.KV) saveKvs(sdb, set.KV)
// check // check
checkExecLocalBoard(t, kvdb, pre1) checkExecLocalBoard(t, kvdb, pre1)
...@@ -238,9 +237,9 @@ func TestGetProposalBoard(t *testing.T) { ...@@ -238,9 +237,9 @@ func TestGetProposalBoard(t *testing.T) {
tx := "1111111111111111111" tx := "1111111111111111111"
storedb.Set(propBoardID(tx), types.Encode(&auty.AutonomyProposalBoard{})) storedb.Set(propBoardID(tx), types.Encode(&auty.AutonomyProposalBoard{}))
rsp, err := au.getProposalBoard(&types.ReqString{Data: tx}) rsp, err := au.getProposalBoard(&types.ReqString{Data: tx})
require.NoError(t, err) assert.NoError(t, err)
require.NotNil(t, rsp) assert.NotNil(t, rsp)
require.Equal(t, len(rsp.(*auty.ReplyQueryProposalBoard).PropBoards), 1) assert.Equal(t, len(rsp.(*auty.ReplyQueryProposalBoard).PropBoards), 1)
} }
func TestListProposalBoard(t *testing.T) { func TestListProposalBoard(t *testing.T) {
...@@ -288,9 +287,9 @@ func TestListProposalBoard(t *testing.T) { ...@@ -288,9 +287,9 @@ func TestListProposalBoard(t *testing.T) {
cur.Index = int32(tcase.index) cur.Index = int32(tcase.index)
err := table.Replace(cur) err := table.Replace(cur)
require.NoError(t, err) assert.NoError(t, err)
kv, err := table.Save() kv, err := table.Save()
require.NoError(t, err) assert.NoError(t, err)
kvs = append(kvs, kv...) kvs = append(kvs, kv...)
} }
...@@ -303,12 +302,12 @@ func TestListProposalBoard(t *testing.T) { ...@@ -303,12 +302,12 @@ func TestListProposalBoard(t *testing.T) {
Index: -1, Index: -1,
} }
rsp, err := au.listProposalBoard(req) rsp, err := au.listProposalBoard(req)
require.NoError(t, err) assert.NoError(t, err)
require.Equal(t, len(rsp.(*auty.ReplyQueryProposalBoard).PropBoards), len(testcase2)) assert.Equal(t, len(rsp.(*auty.ReplyQueryProposalBoard).PropBoards), len(testcase2))
k := 2 k := 2
for _, tcase := range testcase2 { for _, tcase := range testcase2 {
require.Equal(t, rsp.(*auty.ReplyQueryProposalBoard).PropBoards[k].Height, tcase.height) assert.Equal(t, rsp.(*auty.ReplyQueryProposalBoard).PropBoards[k].Height, tcase.height)
require.Equal(t, rsp.(*auty.ReplyQueryProposalBoard).PropBoards[k].Index, int32(tcase.index)) assert.Equal(t, rsp.(*auty.ReplyQueryProposalBoard).PropBoards[k].Index, int32(tcase.index))
k-- k--
} }
...@@ -320,11 +319,11 @@ func TestListProposalBoard(t *testing.T) { ...@@ -320,11 +319,11 @@ func TestListProposalBoard(t *testing.T) {
Index: -1, Index: -1,
} }
rsp, err = au.listProposalBoard(req) rsp, err = au.listProposalBoard(req)
require.NoError(t, err) assert.NoError(t, err)
require.Equal(t, len(rsp.(*auty.ReplyQueryProposalBoard).PropBoards), len(testcase2)) assert.Equal(t, len(rsp.(*auty.ReplyQueryProposalBoard).PropBoards), len(testcase2))
for i, tcase := range testcase2 { for i, tcase := range testcase2 {
require.Equal(t, rsp.(*auty.ReplyQueryProposalBoard).PropBoards[i].Height, tcase.height) assert.Equal(t, rsp.(*auty.ReplyQueryProposalBoard).PropBoards[i].Height, tcase.height)
require.Equal(t, rsp.(*auty.ReplyQueryProposalBoard).PropBoards[i].Index, int32(tcase.index)) assert.Equal(t, rsp.(*auty.ReplyQueryProposalBoard).PropBoards[i].Index, int32(tcase.index))
} }
// 翻页查找 // 翻页查找
...@@ -335,12 +334,12 @@ func TestListProposalBoard(t *testing.T) { ...@@ -335,12 +334,12 @@ func TestListProposalBoard(t *testing.T) {
Index: -1, Index: -1,
} }
rsp, err = au.listProposalBoard(req) rsp, err = au.listProposalBoard(req)
require.NoError(t, err) assert.NoError(t, err)
require.Equal(t, len(rsp.(*auty.ReplyQueryProposalBoard).PropBoards), 1) assert.Equal(t, len(rsp.(*auty.ReplyQueryProposalBoard).PropBoards), 1)
height := rsp.(*auty.ReplyQueryProposalBoard).PropBoards[0].Height height := rsp.(*auty.ReplyQueryProposalBoard).PropBoards[0].Height
index := rsp.(*auty.ReplyQueryProposalBoard).PropBoards[0].Index index := rsp.(*auty.ReplyQueryProposalBoard).PropBoards[0].Index
require.Equal(t, height, testcase2[2].height) assert.Equal(t, height, testcase2[2].height)
require.Equal(t, index, int32(testcase2[2].index)) assert.Equal(t, index, int32(testcase2[2].index))
// //
req = &auty.ReqQueryProposalBoard{ req = &auty.ReqQueryProposalBoard{
Status: auty.AutonomyStatusProposalBoard, Status: auty.AutonomyStatusProposalBoard,
...@@ -350,12 +349,25 @@ func TestListProposalBoard(t *testing.T) { ...@@ -350,12 +349,25 @@ func TestListProposalBoard(t *testing.T) {
Index: index, Index: index,
} }
rsp, err = au.listProposalBoard(req) rsp, err = au.listProposalBoard(req)
require.NoError(t, err) assert.NoError(t, err)
require.Equal(t, len(rsp.(*auty.ReplyQueryProposalBoard).PropBoards), 2) assert.Equal(t, len(rsp.(*auty.ReplyQueryProposalBoard).PropBoards), 2)
require.Equal(t, rsp.(*auty.ReplyQueryProposalBoard).PropBoards[0].Height, testcase2[1].height) assert.Equal(t, rsp.(*auty.ReplyQueryProposalBoard).PropBoards[0].Height, testcase2[1].height)
require.Equal(t, rsp.(*auty.ReplyQueryProposalBoard).PropBoards[0].Index, int32(testcase2[1].index)) assert.Equal(t, rsp.(*auty.ReplyQueryProposalBoard).PropBoards[0].Index, int32(testcase2[1].index))
require.Equal(t, rsp.(*auty.ReplyQueryProposalBoard).PropBoards[1].Height, testcase2[0].height) assert.Equal(t, rsp.(*auty.ReplyQueryProposalBoard).PropBoards[1].Height, testcase2[0].height)
require.Equal(t, rsp.(*auty.ReplyQueryProposalBoard).PropBoards[1].Index, int32(testcase2[0].index)) assert.Equal(t, rsp.(*auty.ReplyQueryProposalBoard).PropBoards[1].Index, int32(testcase2[0].index))
}
func TestGetActiveBoard(t *testing.T) {
au := &Autonomy{
dapp.DriverBase{},
}
_, storedb, _ := util.CreateTestDB()
au.SetStateDB(storedb)
storedb.Set(activeBoardID(), types.Encode(&auty.ActiveBoard{Boards: []string{"111"}}))
rsp, err := au.getActiveBoard()
assert.NoError(t, err)
assert.NotNil(t, rsp)
assert.Equal(t, len(rsp.(*auty.ActiveBoard).Boards), 1)
} }
func checkExecLocalBoard(t *testing.T, kvdb db.KVDB, cur *auty.AutonomyProposalBoard) { func checkExecLocalBoard(t *testing.T, kvdb db.KVDB, cur *auty.AutonomyProposalBoard) {
......
...@@ -14,20 +14,22 @@ import ( ...@@ -14,20 +14,22 @@ import (
auty "github.com/33cn/plugin/plugin/dapp/autonomy/types" auty "github.com/33cn/plugin/plugin/dapp/autonomy/types"
"github.com/33cn/chain33/common/address" "github.com/33cn/chain33/common/address"
ticket "github.com/33cn/plugin/plugin/dapp/ticket/executor"
ticketTy "github.com/33cn/plugin/plugin/dapp/ticket/types"
) )
const ( const (
minBoards = 3 minBoards = 20
maxBoards = 30 maxBoards = 40
publicPeriod int32 = 120960 // 公示一周时间,以区块高度计算 publicPeriod int32 = 17280 * 7 // 公示一周时间,以区块高度计算
ticketPrice = types.Coin * 3000 // 单张票价 ticketPrice = types.Coin * 3000 // 单张票价
largeProjectAmount = types.Coin * 100 * 10000 // 重大项目公示金额阈值 largeProjectAmount = types.Coin * 100 * 10000 // 重大项目公示金额阈值
proposalAmount = types.Coin * 1000 // 创建者消耗金额 proposalAmount = types.Coin * 500 // 创建者消耗金额
boardAttendRatio int32 = 66 // 董事会成员参与率,以%计,可修改 boardApproveRatio int32 = 66 // 董事会成员赞成率,以%计,可修改
boardApproveRatio int32 = 66 // 董事会成员赞成率,以%计,可修改 pubAttendRatio int32 = 75 // 全体持票人参与率,以%计
pubAttendRatio int32 = 50 // 全体持票人参与率,以%计 pubApproveRatio int32 = 66 // 全体持票人赞成率,以%计
pubApproveRatio int32 = 50 // 全体持票人赞成率,以%计 pubOpposeRatio int32 = 33 // 全体持票人否决率,以%计
pubOpposeRatio int32 = 33 // 全体持票人否决率,以%计 startEndBlockPeriod = 720 // 提案开始结束最小周期
) )
type action struct { type action struct {
...@@ -55,17 +57,26 @@ func (a *action) propBoard(prob *auty.ProposalBoard) (*types.Receipt, error) { ...@@ -55,17 +57,26 @@ func (a *action) propBoard(prob *auty.ProposalBoard) (*types.Receipt, error) {
return nil, types.ErrInvalidParam return nil, types.ErrInvalidParam
} }
if prob.StartBlockHeight < a.height || prob.EndBlockHeight < a.height { if prob.StartBlockHeight < a.height || prob.EndBlockHeight < a.height ||
prob.StartBlockHeight+startEndBlockPeriod > prob.EndBlockHeight {
alog.Error("propBoard height invaild", "StartBlockHeight", prob.StartBlockHeight, "EndBlockHeight", alog.Error("propBoard height invaild", "StartBlockHeight", prob.StartBlockHeight, "EndBlockHeight",
prob.EndBlockHeight, "height", a.height) prob.EndBlockHeight, "height", a.height)
return nil, types.ErrInvalidParam return nil, types.ErrInvalidParam
} }
mpBd := make(map[string]struct{})
for _, board := range prob.Boards { for _, board := range prob.Boards {
if err := address.CheckAddress(board); err != nil { if err := address.CheckAddress(board); err != nil {
alog.Error("propBoard ", "addr", board, "check toAddr error", err) alog.Error("propBoard ", "addr", board, "check toAddr error", err)
return nil, types.ErrInvalidAddress return nil, types.ErrInvalidAddress
} }
// 提案board重复地址去重复
if _, ok := mpBd[board]; ok {
err := auty.ErrRepeatAddr
alog.Error("propBoard ", "addr", board, "propBoard have repeat addr ", err)
return nil, err
}
mpBd[board] = struct{}{}
} }
// 获取当前生效提案规则 // 获取当前生效提案规则
...@@ -187,15 +198,39 @@ func (a *action) votePropBoard(voteProb *auty.VoteProposalBoard) (*types.Receipt ...@@ -187,15 +198,39 @@ func (a *action) votePropBoard(voteProb *auty.VoteProposalBoard) (*types.Receipt
return nil, err return nil, err
} }
if len(voteProb.OriginAddr) > 0 {
for _, board := range voteProb.OriginAddr {
if err := address.CheckAddress(board); err != nil {
alog.Error("votePropBoard ", "addr", board, "check toAddr error", err)
return nil, types.ErrInvalidAddress
}
}
// 挖矿地址验证
addr, err := a.verifyMinerAddr(voteProb.OriginAddr, a.fromaddr)
if err != nil {
alog.Error("votePropBoard ", "from addr", a.fromaddr, "error addr", addr, "ProposalID",
voteProb.ProposalID, "err", err)
return nil, err
}
}
// 本次参与投票地址
var addrs []string
if len(voteProb.OriginAddr) == 0 {
addrs = append(addrs, a.fromaddr)
} else {
addrs = append(addrs, voteProb.OriginAddr...)
}
// 检查是否已经参与投票 // 检查是否已经参与投票
votes, err := a.checkVotesRecord(votesRecord(voteProb.ProposalID)) votes, err := a.checkVotesRecord(addrs, votesRecord(voteProb.ProposalID))
if err != nil { if err != nil {
alog.Error("votePropBoard ", "addr", a.fromaddr, "execaddr", a.execaddr, "checkVotesRecord failed", alog.Error("votePropBoard ", "addr", a.fromaddr, "execaddr", a.execaddr, "checkVotesRecord failed",
voteProb.ProposalID, "err", err) voteProb.ProposalID, "err", err)
return nil, err return nil, err
} }
// 更新投票记录 // 更新投票记录
votes.Address = append(votes.Address, a.fromaddr) votes.Address = append(votes.Address, addrs...)
if cur.GetVoteResult().TotalVotes == 0 { //需要统计票数 if cur.GetVoteResult().TotalVotes == 0 { //需要统计票数
vtCouts, err := a.getTotalVotes(start) vtCouts, err := a.getTotalVotes(start)
...@@ -205,8 +240,10 @@ func (a *action) votePropBoard(voteProb *auty.VoteProposalBoard) (*types.Receipt ...@@ -205,8 +240,10 @@ func (a *action) votePropBoard(voteProb *auty.VoteProposalBoard) (*types.Receipt
cur.VoteResult.TotalVotes = vtCouts cur.VoteResult.TotalVotes = vtCouts
} }
vtCouts, err := a.getAddressVotes(a.fromaddr, start) vtCouts, err := a.batchGetAddressVotes(addrs, start)
if err != nil { if err != nil {
alog.Error("votePropBoard ", "addr", a.fromaddr, "execaddr", a.execaddr, "batchGetAddressVotes failed",
voteProb.ProposalID, "err", err)
return nil, err return nil, err
} }
if voteProb.Approve { if voteProb.Approve {
...@@ -249,7 +286,11 @@ func (a *action) votePropBoard(voteProb *auty.VoteProposalBoard) (*types.Receipt ...@@ -249,7 +286,11 @@ func (a *action) votePropBoard(voteProb *auty.VoteProposalBoard) (*types.Receipt
// 更新当前具有权利的董事会成员 // 更新当前具有权利的董事会成员
if cur.VoteResult.Pass { if cur.VoteResult.Pass {
kv = append(kv, &types.KeyValue{Key: activeBoardID(), Value: types.Encode(cur.PropBoard)}) act := &auty.ActiveBoard{
Boards: cur.PropBoard.Boards,
StartHeight: a.height,
}
kv = append(kv, &types.KeyValue{Key: activeBoardID(), Value: types.Encode(act)})
} }
ty := auty.TyLogVotePropBoard ty := auty.TyLogVotePropBoard
...@@ -325,7 +366,11 @@ func (a *action) tmintPropBoard(tmintProb *auty.TerminateProposalBoard) (*types. ...@@ -325,7 +366,11 @@ func (a *action) tmintPropBoard(tmintProb *auty.TerminateProposalBoard) (*types.
// 更新当前具有权利的董事会成员 // 更新当前具有权利的董事会成员
if cur.VoteResult.Pass { if cur.VoteResult.Pass {
kv = append(kv, &types.KeyValue{Key: activeBoardID(), Value: types.Encode(cur.PropBoard)}) act := &auty.ActiveBoard{
Boards: cur.PropBoard.Boards,
StartHeight: a.height,
}
kv = append(kv, &types.KeyValue{Key: activeBoardID(), Value: types.Encode(act)})
} }
receiptLog := getReceiptLog(pre, cur, auty.TyLogTmintPropBoard) receiptLog := getReceiptLog(pre, cur, auty.TyLogTmintPropBoard)
...@@ -346,6 +391,34 @@ func (a *action) getTotalVotes(height int64) (int32, error) { ...@@ -346,6 +391,34 @@ func (a *action) getTotalVotes(height int64) (int32, error) {
return int32(account.Balance / ticketPrice), nil return int32(account.Balance / ticketPrice), nil
} }
func (a *action) verifyMinerAddr(addrs []string, bindAddr string) (string, error) {
// 验证绑定关系
for _, addr := range addrs {
value, err := a.db.Get(ticket.BindKey(addr))
if err != nil {
return addr, auty.ErrMinerAddr
}
tkBind := &ticketTy.TicketBind{}
err = types.Decode(value, tkBind)
if err != nil || tkBind.MinerAddress != bindAddr {
return addr, auty.ErrBindAddr
}
}
return "", nil
}
func (a *action) batchGetAddressVotes(addrs []string, height int64) (int32, error) {
total := int32(0)
for _, addr := range addrs {
count, err := a.getAddressVotes(addr, height)
if err != nil {
return 0, err
}
total += count
}
return total, nil
}
func (a *action) getAddressVotes(addr string, height int64) (int32, error) { func (a *action) getAddressVotes(addr string, height int64) (int32, error) {
account, err := a.getStartHeightVoteAccount(addr, auty.TicketX, height) account, err := a.getStartHeightVoteAccount(addr, auty.TicketX, height)
if err != nil { if err != nil {
...@@ -406,7 +479,6 @@ func (a *action) getActiveRule() (*auty.RuleConfig, error) { ...@@ -406,7 +479,6 @@ func (a *action) getActiveRule() (*auty.RuleConfig, error) {
return nil, err return nil, err
} }
} else { // 载入系统默认值 } else { // 载入系统默认值
rule.BoardAttendRatio = boardAttendRatio
rule.BoardApproveRatio = boardApproveRatio rule.BoardApproveRatio = boardApproveRatio
rule.PubOpposeRatio = pubOpposeRatio rule.PubOpposeRatio = pubOpposeRatio
rule.ProposalAmount = proposalAmount rule.ProposalAmount = proposalAmount
...@@ -416,7 +488,7 @@ func (a *action) getActiveRule() (*auty.RuleConfig, error) { ...@@ -416,7 +488,7 @@ func (a *action) getActiveRule() (*auty.RuleConfig, error) {
return rule, nil return rule, nil
} }
func (a *action) checkVotesRecord(key []byte) (*auty.VotesRecord, error) { func (a *action) checkVotesRecord(addrs []string, key []byte) (*auty.VotesRecord, error) {
var votes auty.VotesRecord var votes auty.VotesRecord
value, err := a.db.Get(key) value, err := a.db.Get(key)
if err == nil { if err == nil {
...@@ -425,10 +497,15 @@ func (a *action) checkVotesRecord(key []byte) (*auty.VotesRecord, error) { ...@@ -425,10 +497,15 @@ func (a *action) checkVotesRecord(key []byte) (*auty.VotesRecord, error) {
return nil, err return nil, err
} }
} }
mp := make(map[string]struct{}, len(addrs))
for _, addr := range addrs {
mp[addr] = struct{}{}
}
// 检查是否有重复 // 检查是否有重复
for _, addr := range votes.Address { for _, addr := range votes.Address {
if addr == a.fromaddr { if _, ok := mp[addr]; ok {
err := auty.ErrRepeatVoteAddr err := auty.ErrRepeatVoteAddr
alog.Error("autonomy ", "addr", addr, "err", err)
return nil, err return nil, err
} }
} }
......
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package executor
import (
"github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types"
auty "github.com/33cn/plugin/plugin/dapp/autonomy/types"
)
func (a *Autonomy) execAutoLocalChange(tx *types.Transaction, receiptData *types.ReceiptData) (*types.LocalDBSet, error) {
set, err := a.execLocalChange(receiptData)
if err != nil {
return set, err
}
dbSet := &types.LocalDBSet{}
dbSet.KV = a.AddRollbackKV(tx, tx.Execer, set.KV)
return dbSet, nil
}
func (a *Autonomy) execLocalChange(receiptData *types.ReceiptData) (*types.LocalDBSet, error) {
table := NewChangeTable(a.GetLocalDB())
for _, log := range receiptData.Logs {
switch log.Ty {
case auty.TyLogPropChange,
auty.TyLogRvkPropChange,
auty.TyLogVotePropChange,
auty.TyLogTmintPropChange:
{
var receipt auty.ReceiptProposalChange
err := types.Decode(log.Log, &receipt)
if err != nil {
return nil, err
}
err = table.Replace(receipt.Current)
if err != nil {
return nil, err
}
}
default:
break
}
}
kvs, err := table.Save()
if err != nil {
return nil, err
}
dbSet := &types.LocalDBSet{}
dbSet.KV = append(dbSet.KV, kvs...)
return dbSet, nil
}
func (a *Autonomy) getProposalChange(req *types.ReqString) (types.Message, error) {
if req == nil {
return nil, types.ErrInvalidParam
}
value, err := a.GetStateDB().Get(propChangeID(req.Data))
if err != nil {
return nil, err
}
prop := &auty.AutonomyProposalChange{}
err = types.Decode(value, prop)
if err != nil {
return nil, err
}
rep := &auty.ReplyQueryProposalChange{}
rep.PropChanges = append(rep.PropChanges, prop)
return rep, nil
}
func (a *Autonomy) listProposalChange(req *auty.ReqQueryProposalChange) (types.Message, error) {
if req == nil {
return nil, types.ErrInvalidParam
}
localDb := a.GetLocalDB()
query := NewChangeTable(localDb).GetQuery(localDb)
var primary []byte
if req.Height > 0 {
primary = []byte(dapp.HeightIndexStr(req.Height, int64(req.Index)))
}
indexName := ""
if req.Status > 0 && req.Addr != "" {
indexName = "addr_status"
} else if req.Status > 0 {
indexName = "status"
} else if req.Addr != "" {
indexName = "addr"
}
cur := &ChangeRow{
AutonomyProposalChange: &auty.AutonomyProposalChange{},
}
cur.Address = req.Addr
cur.Status = req.Status
cur.Height = req.Height
cur.Index = req.Index
prefix, err := cur.Get(indexName)
if err != nil {
alog.Error("Get", "indexName", indexName, "err", err)
return nil, err
}
rows, err := query.ListIndex(indexName, prefix, primary, req.Count, req.Direction)
if err != nil {
alog.Error("query List failed", "indexName", indexName, "prefix", "prefix", "key", string(primary), "err", err)
return nil, err
}
if len(rows) == 0 {
return nil, types.ErrNotFound
}
var rep auty.ReplyQueryProposalChange
for _, row := range rows {
r, ok := row.Data.(*auty.AutonomyProposalChange)
if !ok {
alog.Error("listProposalChange", "err", "bad row type")
return nil, types.ErrDecode
}
rep.PropChanges = append(rep.PropChanges, r)
}
return &rep, nil
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
package executor
import (
"fmt"
"github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/common/db/table"
"github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types"
auty "github.com/33cn/plugin/plugin/dapp/autonomy/types"
)
/*
table struct
data: autonomy change
index: status, addr
*/
var changeOpt = &table.Option{
Prefix: "LODB-autonomy",
Name: "change",
Primary: "heightindex",
Index: []string{"addr", "status", "addr_status"},
}
//NewChangeTable 新建表
func NewChangeTable(kvdb db.KV) *table.Table {
rowmeta := NewChangeRow()
table, err := table.NewTable(rowmeta, kvdb, changeOpt)
if err != nil {
panic(err)
}
return table
}
//ChangeRow table meta 结构
type ChangeRow struct {
*auty.AutonomyProposalChange
}
//NewChangeRow 新建一个meta 结构
func NewChangeRow() *ChangeRow {
return &ChangeRow{AutonomyProposalChange: &auty.AutonomyProposalChange{}}
}
//CreateRow 新建数据行(注意index 数据一定也要保存到数据中,不能就保存heightindex)
func (r *ChangeRow) CreateRow() *table.Row {
return &table.Row{Data: &auty.AutonomyProposalChange{}}
}
//SetPayload 设置数据
func (r *ChangeRow) SetPayload(data types.Message) error {
if d, ok := data.(*auty.AutonomyProposalChange); ok {
r.AutonomyProposalChange = d
return nil
}
return types.ErrTypeAsset
}
//Get 按照indexName 查询 indexValue
func (r *ChangeRow) Get(key string) ([]byte, error) {
if key == "heightindex" {
return []byte(dapp.HeightIndexStr(r.Height, int64(r.Index))), nil
} else if key == "status" {
return []byte(fmt.Sprintf("%2d", r.Status)), nil
} else if key == "addr" {
return []byte(r.Address), nil
} else if key == "addr_status" {
return []byte(fmt.Sprintf("%s:%2d", r.Address, r.Status)), nil
}
return nil, types.ErrNotFound
}
...@@ -104,3 +104,29 @@ func (a *Autonomy) Exec_CommentProp(payload *auty.Comment, tx *types.Transaction ...@@ -104,3 +104,29 @@ func (a *Autonomy) Exec_CommentProp(payload *auty.Comment, tx *types.Transaction
action := newAction(a, tx, int32(index)) action := newAction(a, tx, int32(index))
return action.commentProp(payload) return action.commentProp(payload)
} }
// 提案修改董事会成员相关
// Exec_PropChange 创建提案规则
func (a *Autonomy) Exec_PropChange(payload *auty.ProposalChange, tx *types.Transaction, index int) (*types.Receipt, error) {
action := newAction(a, tx, int32(index))
return action.propChange(payload)
}
// Exec_RvkPropChange 撤销提案规则
func (a *Autonomy) Exec_RvkPropChange(payload *auty.RevokeProposalChange, tx *types.Transaction, index int) (*types.Receipt, error) {
action := newAction(a, tx, int32(index))
return action.rvkPropChange(payload)
}
// Exec_VotePropChange 投票提案规则
func (a *Autonomy) Exec_VotePropChange(payload *auty.VoteProposalChange, tx *types.Transaction, index int) (*types.Receipt, error) {
action := newAction(a, tx, int32(index))
return action.votePropChange(payload)
}
// Exec_TmintPropChange 终止提案规则
func (a *Autonomy) Exec_TmintPropChange(payload *auty.TerminateProposalChange, tx *types.Transaction, index int) (*types.Receipt, error) {
action := newAction(a, tx, int32(index))
return action.tmintPropChange(payload)
}
...@@ -84,3 +84,25 @@ func (a *Autonomy) ExecLocal_TmintPropRule(payload *auty.TerminateProposalRule, ...@@ -84,3 +84,25 @@ func (a *Autonomy) ExecLocal_TmintPropRule(payload *auty.TerminateProposalRule,
func (a *Autonomy) ExecLocal_CommentProp(payload *auty.Comment, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) { func (a *Autonomy) ExecLocal_CommentProp(payload *auty.Comment, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return a.execAutoLocalCommentProp(tx, receiptData) return a.execAutoLocalCommentProp(tx, receiptData)
} }
// 提案修改董事会成员相关
// ExecLocal_PropChange 创建提案规则
func (a *Autonomy) ExecLocal_PropChange(payload *auty.ProposalChange, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return a.execAutoLocalChange(tx, receiptData)
}
// ExecLocal_RvkPropChange 撤销提案规则
func (a *Autonomy) ExecLocal_RvkPropChange(payload *auty.RevokeProposalChange, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return a.execAutoLocalChange(tx, receiptData)
}
// ExecLocal_VotePropChange 投票提案规则
func (a *Autonomy) ExecLocal_VotePropChange(payload *auty.VoteProposalChange, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return a.execAutoLocalChange(tx, receiptData)
}
// ExecLocal_TmintPropChange 终止提案规则
func (a *Autonomy) ExecLocal_TmintPropChange(payload *auty.TerminateProposalChange, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return a.execAutoLocalChange(tx, receiptData)
}
...@@ -70,3 +70,12 @@ func calcCommentHeight(ID, heightindex string) []byte { ...@@ -70,3 +70,12 @@ func calcCommentHeight(ID, heightindex string) []byte {
key := fmt.Sprintf(localCommentPrefix+"%s-"+"%s", ID, heightindex) key := fmt.Sprintf(localCommentPrefix+"%s-"+"%s", ID, heightindex)
return []byte(key) return []byte(key)
} }
var (
// change
changePrefix = idPrefix + "change" + "-"
)
func propChangeID(txHash string) []byte {
return []byte(fmt.Sprintf("%s%s", changePrefix, txHash))
}
...@@ -13,7 +13,6 @@ import ( ...@@ -13,7 +13,6 @@ import (
"github.com/33cn/chain33/util" "github.com/33cn/chain33/util"
auty "github.com/33cn/plugin/plugin/dapp/autonomy/types" auty "github.com/33cn/plugin/plugin/dapp/autonomy/types"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
func TestExecLocalProject(t *testing.T) { func TestExecLocalProject(t *testing.T) {
...@@ -51,14 +50,14 @@ func testexecLocalProject(t *testing.T, auto bool) { ...@@ -51,14 +50,14 @@ func testexecLocalProject(t *testing.T, auto bool) {
var err error var err error
if !auto { if !auto {
set, err = au.execLocalProject(receipt) set, err = au.execLocalProject(receipt)
require.NoError(t, err) assert.NoError(t, err)
require.NotNil(t, set) assert.NotNil(t, set)
} else { } else {
tx, err := types.CreateFormatTx(types.ExecName(auty.AutonomyX), nil) tx, err := types.CreateFormatTx(types.ExecName(auty.AutonomyX), nil)
assert.NoError(t, err) assert.NoError(t, err)
set, err = au.execAutoLocalProject(tx, receipt) set, err = au.execAutoLocalProject(tx, receipt)
require.NoError(t, err) assert.NoError(t, err)
require.NotNil(t, set) assert.NotNil(t, set)
} }
//save to database //save to database
...@@ -81,8 +80,8 @@ func testexecLocalProject(t *testing.T, auto bool) { ...@@ -81,8 +80,8 @@ func testexecLocalProject(t *testing.T, auto bool) {
{Ty: auty.TyLogRvkPropProject, Log: types.Encode(receiptProject1)}, {Ty: auty.TyLogRvkPropProject, Log: types.Encode(receiptProject1)},
}, },
}) })
require.NoError(t, err) assert.NoError(t, err)
require.NotNil(t, set) assert.NotNil(t, set)
} else { } else {
tx, err := types.CreateFormatTx(types.ExecName(auty.AutonomyX), nil) tx, err := types.CreateFormatTx(types.ExecName(auty.AutonomyX), nil)
assert.NoError(t, err) assert.NoError(t, err)
...@@ -92,8 +91,8 @@ func testexecLocalProject(t *testing.T, auto bool) { ...@@ -92,8 +91,8 @@ func testexecLocalProject(t *testing.T, auto bool) {
{Ty: auty.TyLogRvkPropProject, Log: types.Encode(receiptProject1)}, {Ty: auty.TyLogRvkPropProject, Log: types.Encode(receiptProject1)},
}, },
}) })
require.NoError(t, err) assert.NoError(t, err)
require.NotNil(t, set) assert.NotNil(t, set)
} }
//save to database //save to database
...@@ -118,8 +117,8 @@ func testexecLocalProject(t *testing.T, auto bool) { ...@@ -118,8 +117,8 @@ func testexecLocalProject(t *testing.T, auto bool) {
{Ty: auty.TyLogVotePropProject, Log: types.Encode(receiptProject2)}, {Ty: auty.TyLogVotePropProject, Log: types.Encode(receiptProject2)},
}, },
}) })
require.NoError(t, err) assert.NoError(t, err)
require.NotNil(t, set) assert.NotNil(t, set)
} else { } else {
tx, err := types.CreateFormatTx(types.ExecName(auty.AutonomyX), nil) tx, err := types.CreateFormatTx(types.ExecName(auty.AutonomyX), nil)
assert.NoError(t, err) assert.NoError(t, err)
...@@ -129,8 +128,8 @@ func testexecLocalProject(t *testing.T, auto bool) { ...@@ -129,8 +128,8 @@ func testexecLocalProject(t *testing.T, auto bool) {
{Ty: auty.TyLogVotePropProject, Log: types.Encode(receiptProject2)}, {Ty: auty.TyLogVotePropProject, Log: types.Encode(receiptProject2)},
}, },
}) })
require.NoError(t, err) assert.NoError(t, err)
require.NotNil(t, set) assert.NotNil(t, set)
} }
//save to database //save to database
...@@ -174,13 +173,13 @@ func testexecDelLocalProject(t *testing.T) { ...@@ -174,13 +173,13 @@ func testexecDelLocalProject(t *testing.T) {
tx, err := types.CreateFormatTx(types.ExecName(auty.AutonomyX), nil) tx, err := types.CreateFormatTx(types.ExecName(auty.AutonomyX), nil)
assert.NoError(t, err) assert.NoError(t, err)
set, err := au.execAutoLocalProject(tx, receipt) set, err := au.execAutoLocalProject(tx, receipt)
require.NoError(t, err) assert.NoError(t, err)
require.NotNil(t, set) assert.NotNil(t, set)
saveKvs(sdb, set.KV) saveKvs(sdb, set.KV)
set, err = au.execAutoDelLocal(tx, receipt) set, err = au.execAutoDelLocal(tx, receipt)
require.NoError(t, err) assert.NoError(t, err)
require.NotNil(t, set) assert.NotNil(t, set)
saveKvs(sdb, set.KV) saveKvs(sdb, set.KV)
// check // check
...@@ -211,8 +210,8 @@ func testexecDelLocalProject(t *testing.T) { ...@@ -211,8 +210,8 @@ func testexecDelLocalProject(t *testing.T) {
tx, err = types.CreateFormatTx(types.ExecName(auty.AutonomyX), nil) tx, err = types.CreateFormatTx(types.ExecName(auty.AutonomyX), nil)
assert.NoError(t, err) assert.NoError(t, err)
set, err = au.execAutoLocalProject(tx, receipt) set, err = au.execAutoLocalProject(tx, receipt)
require.NoError(t, err) assert.NoError(t, err)
require.NotNil(t, set) assert.NotNil(t, set)
saveKvs(sdb, set.KV) saveKvs(sdb, set.KV)
// 正常测试退回 // 正常测试退回
...@@ -220,15 +219,15 @@ func testexecDelLocalProject(t *testing.T) { ...@@ -220,15 +219,15 @@ func testexecDelLocalProject(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
set, err = au.execAutoLocalProject(tx, recpt) set, err = au.execAutoLocalProject(tx, recpt)
require.NoError(t, err) assert.NoError(t, err)
require.NotNil(t, set) assert.NotNil(t, set)
saveKvs(sdb, set.KV) saveKvs(sdb, set.KV)
// check // check
checkExecLocalProject(t, kvdb, cur) checkExecLocalProject(t, kvdb, cur)
set, err = au.execAutoDelLocal(tx, recpt) set, err = au.execAutoDelLocal(tx, recpt)
require.NoError(t, err) assert.NoError(t, err)
require.NotNil(t, set) assert.NotNil(t, set)
saveKvs(sdb, set.KV) saveKvs(sdb, set.KV)
checkExecLocalProject(t, kvdb, pre1) checkExecLocalProject(t, kvdb, pre1)
...@@ -243,9 +242,9 @@ func TestGetProposalProject(t *testing.T) { ...@@ -243,9 +242,9 @@ func TestGetProposalProject(t *testing.T) {
tx := "1111111111111111111" tx := "1111111111111111111"
storedb.Set(propProjectID(tx), types.Encode(&auty.AutonomyProposalProject{})) storedb.Set(propProjectID(tx), types.Encode(&auty.AutonomyProposalProject{}))
rsp, err := au.getProposalProject(&types.ReqString{Data: tx}) rsp, err := au.getProposalProject(&types.ReqString{Data: tx})
require.NoError(t, err) assert.NoError(t, err)
require.NotNil(t, rsp) assert.NotNil(t, rsp)
require.Equal(t, len(rsp.(*auty.ReplyQueryProposalProject).PropProjects), 1) assert.Equal(t, len(rsp.(*auty.ReplyQueryProposalProject).PropProjects), 1)
} }
func TestListProposalProject(t *testing.T) { func TestListProposalProject(t *testing.T) {
...@@ -295,9 +294,9 @@ func TestListProposalProject(t *testing.T) { ...@@ -295,9 +294,9 @@ func TestListProposalProject(t *testing.T) {
cur.Index = int32(tcase.index) cur.Index = int32(tcase.index)
err := table.Replace(cur) err := table.Replace(cur)
require.NoError(t, err) assert.NoError(t, err)
kv, err := table.Save() kv, err := table.Save()
require.NoError(t, err) assert.NoError(t, err)
kvs = append(kvs, kv...) kvs = append(kvs, kv...)
} }
saveKvs(sdb, kvs) saveKvs(sdb, kvs)
...@@ -310,12 +309,12 @@ func TestListProposalProject(t *testing.T) { ...@@ -310,12 +309,12 @@ func TestListProposalProject(t *testing.T) {
Index: -1, Index: -1,
} }
rsp, err := au.listProposalProject(req) rsp, err := au.listProposalProject(req)
require.NoError(t, err) assert.NoError(t, err)
require.Equal(t, len(rsp.(*auty.ReplyQueryProposalProject).PropProjects), len(testcase2)) assert.Equal(t, len(rsp.(*auty.ReplyQueryProposalProject).PropProjects), len(testcase2))
k := 2 k := 2
for _, tcase := range testcase2 { for _, tcase := range testcase2 {
require.Equal(t, rsp.(*auty.ReplyQueryProposalProject).PropProjects[k].Height, tcase.height) assert.Equal(t, rsp.(*auty.ReplyQueryProposalProject).PropProjects[k].Height, tcase.height)
require.Equal(t, rsp.(*auty.ReplyQueryProposalProject).PropProjects[k].Index, int32(tcase.index)) assert.Equal(t, rsp.(*auty.ReplyQueryProposalProject).PropProjects[k].Index, int32(tcase.index))
k-- k--
} }
...@@ -327,11 +326,11 @@ func TestListProposalProject(t *testing.T) { ...@@ -327,11 +326,11 @@ func TestListProposalProject(t *testing.T) {
Index: -1, Index: -1,
} }
rsp, err = au.listProposalProject(req) rsp, err = au.listProposalProject(req)
require.NoError(t, err) assert.NoError(t, err)
require.Equal(t, len(rsp.(*auty.ReplyQueryProposalProject).PropProjects), len(testcase2)) assert.Equal(t, len(rsp.(*auty.ReplyQueryProposalProject).PropProjects), len(testcase2))
for i, tcase := range testcase2 { for i, tcase := range testcase2 {
require.Equal(t, rsp.(*auty.ReplyQueryProposalProject).PropProjects[i].Height, tcase.height) assert.Equal(t, rsp.(*auty.ReplyQueryProposalProject).PropProjects[i].Height, tcase.height)
require.Equal(t, rsp.(*auty.ReplyQueryProposalProject).PropProjects[i].Index, int32(tcase.index)) assert.Equal(t, rsp.(*auty.ReplyQueryProposalProject).PropProjects[i].Index, int32(tcase.index))
} }
// 翻页查找 // 翻页查找
...@@ -342,12 +341,12 @@ func TestListProposalProject(t *testing.T) { ...@@ -342,12 +341,12 @@ func TestListProposalProject(t *testing.T) {
Index: -1, Index: -1,
} }
rsp, err = au.listProposalProject(req) rsp, err = au.listProposalProject(req)
require.NoError(t, err) assert.NoError(t, err)
require.Equal(t, len(rsp.(*auty.ReplyQueryProposalProject).PropProjects), 1) assert.Equal(t, len(rsp.(*auty.ReplyQueryProposalProject).PropProjects), 1)
height := rsp.(*auty.ReplyQueryProposalProject).PropProjects[0].Height height := rsp.(*auty.ReplyQueryProposalProject).PropProjects[0].Height
index := rsp.(*auty.ReplyQueryProposalProject).PropProjects[0].Index index := rsp.(*auty.ReplyQueryProposalProject).PropProjects[0].Index
require.Equal(t, height, testcase2[2].height) assert.Equal(t, height, testcase2[2].height)
require.Equal(t, index, int32(testcase2[2].index)) assert.Equal(t, index, int32(testcase2[2].index))
// //
req = &auty.ReqQueryProposalProject{ req = &auty.ReqQueryProposalProject{
Status: auty.AutonomyStatusProposalProject, Status: auty.AutonomyStatusProposalProject,
...@@ -357,12 +356,12 @@ func TestListProposalProject(t *testing.T) { ...@@ -357,12 +356,12 @@ func TestListProposalProject(t *testing.T) {
Index: index, Index: index,
} }
rsp, err = au.listProposalProject(req) rsp, err = au.listProposalProject(req)
require.NoError(t, err) assert.NoError(t, err)
require.Equal(t, len(rsp.(*auty.ReplyQueryProposalProject).PropProjects), 2) assert.Equal(t, len(rsp.(*auty.ReplyQueryProposalProject).PropProjects), 2)
require.Equal(t, rsp.(*auty.ReplyQueryProposalProject).PropProjects[0].Height, testcase2[1].height) assert.Equal(t, rsp.(*auty.ReplyQueryProposalProject).PropProjects[0].Height, testcase2[1].height)
require.Equal(t, rsp.(*auty.ReplyQueryProposalProject).PropProjects[0].Index, int32(testcase2[1].index)) assert.Equal(t, rsp.(*auty.ReplyQueryProposalProject).PropProjects[0].Index, int32(testcase2[1].index))
require.Equal(t, rsp.(*auty.ReplyQueryProposalProject).PropProjects[1].Height, testcase2[0].height) assert.Equal(t, rsp.(*auty.ReplyQueryProposalProject).PropProjects[1].Height, testcase2[0].height)
require.Equal(t, rsp.(*auty.ReplyQueryProposalProject).PropProjects[1].Index, int32(testcase2[0].index)) assert.Equal(t, rsp.(*auty.ReplyQueryProposalProject).PropProjects[1].Index, int32(testcase2[0].index))
} }
func checkExecLocalProject(t *testing.T, kvdb db.KVDB, cur *auty.AutonomyProposalProject) { func checkExecLocalProject(t *testing.T, kvdb db.KVDB, cur *auty.AutonomyProposalProject) {
......
...@@ -12,13 +12,19 @@ import ( ...@@ -12,13 +12,19 @@ import (
"github.com/33cn/chain33/common/address" "github.com/33cn/chain33/common/address"
) )
const (
maxBoardPeriodAmount = types.Coin * 10000 * 300 // 每个时期董事会审批最大额度300万
boardPeriod = 17280 * 30 * 1 // 时期为一个月
)
func (a *action) propProject(prob *auty.ProposalProject) (*types.Receipt, error) { func (a *action) propProject(prob *auty.ProposalProject) (*types.Receipt, error) {
if err := address.CheckAddress(prob.ToAddr); err != nil { if err := address.CheckAddress(prob.ToAddr); err != nil {
alog.Error("propProject ", "addr", prob.ToAddr, "check toAddr error", err) alog.Error("propProject ", "addr", prob.ToAddr, "check toAddr error", err)
return nil, types.ErrInvalidAddress return nil, types.ErrInvalidAddress
} }
if prob.StartBlockHeight < a.height || prob.EndBlockHeight < a.height || prob.Amount <= 0 { if prob.StartBlockHeight < a.height || prob.EndBlockHeight < a.height || prob.Amount <= 0 ||
prob.StartBlockHeight+startEndBlockPeriod > prob.EndBlockHeight {
alog.Error("propProject height or amount invaild", "StartBlockHeight", prob.StartBlockHeight, "EndBlockHeight", alog.Error("propProject height or amount invaild", "StartBlockHeight", prob.StartBlockHeight, "EndBlockHeight",
prob.EndBlockHeight, "height", a.height, "amount", prob.Amount) prob.EndBlockHeight, "height", a.height, "amount", prob.Amount)
return nil, types.ErrInvalidParam return nil, types.ErrInvalidParam
...@@ -30,6 +36,20 @@ func (a *action) propProject(prob *auty.ProposalProject) (*types.Receipt, error) ...@@ -30,6 +36,20 @@ func (a *action) propProject(prob *auty.ProposalProject) (*types.Receipt, error)
alog.Error("propProject ", "addr", a.fromaddr, "execaddr", a.execaddr, "get getActiveBoard failed", err) alog.Error("propProject ", "addr", a.fromaddr, "execaddr", a.execaddr, "get getActiveBoard failed", err)
return nil, err return nil, err
} }
// 检查是否可以对已审批额度归0,如果可以则设置kv
var kva *types.KeyValue
if a.height > pboard.StartHeight+boardPeriod {
pboard.StartHeight = a.height
pboard.Amount = 0
kva = &types.KeyValue{Key: activeBoardID(), Value: types.Encode(pboard)}
}
// 检查额度
pass := a.checkPeriodAmount(pboard, prob.Amount)
if !pass {
err = auty.ErrNoPeriodAmount
alog.Error("propProject ", "addr", a.fromaddr, "cumsum amount", pboard.Amount, "this period board have enough amount", err)
return nil, err
}
// 获取当前生效提案规则 // 获取当前生效提案规则
rule, err := a.getActiveRule() rule, err := a.getActiveRule()
if err != nil { if err != nil {
...@@ -75,6 +95,9 @@ func (a *action) propProject(prob *auty.ProposalProject) (*types.Receipt, error) ...@@ -75,6 +95,9 @@ func (a *action) propProject(prob *auty.ProposalProject) (*types.Receipt, error)
ProposalID: common.ToHex(a.txhash), ProposalID: common.ToHex(a.txhash),
} }
kv = append(kv, &types.KeyValue{Key: propProjectID(common.ToHex(a.txhash)), Value: types.Encode(cur)}) kv = append(kv, &types.KeyValue{Key: propProjectID(common.ToHex(a.txhash)), Value: types.Encode(cur)})
if kva != nil {
kv = append(kv, kva)
}
receiptLog := getProjectReceiptLog(nil, cur, auty.TyLogPropProject) receiptLog := getProjectReceiptLog(nil, cur, auty.TyLogPropProject)
logs = append(logs, receiptLog) logs = append(logs, receiptLog)
...@@ -189,7 +212,7 @@ func (a *action) votePropProject(voteProb *auty.VoteProposalProject) (*types.Rec ...@@ -189,7 +212,7 @@ func (a *action) votePropProject(voteProb *auty.VoteProposalProject) (*types.Rec
} }
// 检查是否已经参与投票 // 检查是否已经参与投票
votes, err := a.checkVotesRecord(boardVotesRecord(voteProb.ProposalID)) votes, err := a.checkVotesRecord([]string{a.fromaddr}, boardVotesRecord(voteProb.ProposalID))
if err != nil { if err != nil {
alog.Error("votePropProject ", "addr", a.fromaddr, "execaddr", a.execaddr, "checkVotesRecord boardVotesRecord failed", alog.Error("votePropProject ", "addr", a.fromaddr, "execaddr", a.execaddr, "checkVotesRecord boardVotesRecord failed",
voteProb.ProposalID, "err", err) voteProb.ProposalID, "err", err)
...@@ -220,9 +243,7 @@ func (a *action) votePropProject(voteProb *auty.VoteProposalProject) (*types.Rec ...@@ -220,9 +243,7 @@ func (a *action) votePropProject(voteProb *auty.VoteProposalProject) (*types.Rec
} }
if cur.BoardVoteRes.TotalVotes != 0 && if cur.BoardVoteRes.TotalVotes != 0 &&
cur.BoardVoteRes.ApproveVotes+cur.BoardVoteRes.OpposeVotes != 0 && float32(cur.BoardVoteRes.ApproveVotes)/float32(cur.BoardVoteRes.TotalVotes) >= float32(cur.CurRule.BoardApproveRatio)/100.0 {
float32(cur.BoardVoteRes.ApproveVotes+cur.BoardVoteRes.OpposeVotes)/float32(cur.BoardVoteRes.TotalVotes) >= float32(cur.CurRule.BoardAttendRatio)/100.0 &&
float32(cur.BoardVoteRes.ApproveVotes)/float32(cur.BoardVoteRes.ApproveVotes+cur.BoardVoteRes.OpposeVotes) >= float32(cur.CurRule.BoardApproveRatio)/100.0 {
cur.BoardVoteRes.Pass = true cur.BoardVoteRes.Pass = true
cur.PropProject.RealEndBlockHeight = a.height cur.PropProject.RealEndBlockHeight = a.height
} }
...@@ -244,6 +265,13 @@ func (a *action) votePropProject(voteProb *auty.VoteProposalProject) (*types.Rec ...@@ -244,6 +265,13 @@ func (a *action) votePropProject(voteProb *auty.VoteProposalProject) (*types.Rec
} }
logs = append(logs, receipt.Logs...) logs = append(logs, receipt.Logs...)
kv = append(kv, receipt.KV...) kv = append(kv, receipt.KV...)
// 需要更新该董事会的累计审批金
pakv, err := a.updatePeriodAmount(cur.PropProject.Amount)
if err != nil {
alog.Error("votePropProject ", "addr", cur.Address, "execaddr", a.execaddr, "updatePeriodAmount fail", err)
return nil, err
}
kv = append(kv, pakv)
} }
} }
kv = append(kv, &types.KeyValue{Key: key, Value: types.Encode(cur)}) kv = append(kv, &types.KeyValue{Key: key, Value: types.Encode(cur)})
...@@ -290,15 +318,39 @@ func (a *action) pubVotePropProject(voteProb *auty.PubVoteProposalProject) (*typ ...@@ -290,15 +318,39 @@ func (a *action) pubVotePropProject(voteProb *auty.PubVoteProposalProject) (*typ
return nil, err return nil, err
} }
if len(voteProb.OriginAddr) > 0 {
for _, board := range voteProb.OriginAddr {
if err := address.CheckAddress(board); err != nil {
alog.Error("pubVotePropProject ", "addr", board, "check toAddr error", err)
return nil, types.ErrInvalidAddress
}
}
// 挖矿地址验证
addr, err := a.verifyMinerAddr(voteProb.OriginAddr, a.fromaddr)
if err != nil {
alog.Error("pubVotePropProject ", "from addr", a.fromaddr, "error addr", addr, "ProposalID",
voteProb.ProposalID, "err", err)
return nil, err
}
}
// 本次参与投票地址
var addrs []string
if len(voteProb.OriginAddr) == 0 {
addrs = append(addrs, a.fromaddr)
} else {
addrs = append(addrs, voteProb.OriginAddr...)
}
// 检查是否已经参与投票 // 检查是否已经参与投票
votes, err := a.checkVotesRecord(votesRecord(voteProb.ProposalID)) votes, err := a.checkVotesRecord(addrs, votesRecord(voteProb.ProposalID))
if err != nil { if err != nil {
alog.Error("pubVotePropProject ", "addr", a.fromaddr, "execaddr", a.execaddr, "checkVotesRecord failed", alog.Error("pubVotePropProject ", "addr", a.fromaddr, "execaddr", a.execaddr, "checkVotesRecord failed",
voteProb.ProposalID, "err", err) voteProb.ProposalID, "err", err)
return nil, err return nil, err
} }
// 更新投票记录 // 更新投票记录
votes.Address = append(votes.Address, a.fromaddr) votes.Address = append(votes.Address, addrs...)
if cur.GetPubVote().TotalVotes == 0 { //需要统计总票数 if cur.GetPubVote().TotalVotes == 0 { //需要统计总票数
vtCouts, err := a.getTotalVotes(start) vtCouts, err := a.getTotalVotes(start)
...@@ -309,8 +361,10 @@ func (a *action) pubVotePropProject(voteProb *auty.PubVoteProposalProject) (*typ ...@@ -309,8 +361,10 @@ func (a *action) pubVotePropProject(voteProb *auty.PubVoteProposalProject) (*typ
} }
// 获取该地址票数 // 获取该地址票数
vtCouts, err := a.getAddressVotes(a.fromaddr, start) vtCouts, err := a.batchGetAddressVotes(addrs, start)
if err != nil { if err != nil {
alog.Error("pubVotePropProject ", "addr", a.fromaddr, "execaddr", a.execaddr, "batchGetAddressVotes failed",
voteProb.ProposalID, "err", err)
return nil, err return nil, err
} }
if voteProb.Oppose { //投反对票 if voteProb.Oppose { //投反对票
...@@ -391,16 +445,14 @@ func (a *action) tmintPropProject(tmintProb *auty.TerminateProposalProject) (*ty ...@@ -391,16 +445,14 @@ func (a *action) tmintPropProject(tmintProb *auty.TerminateProposalProject) (*ty
} }
if cur.BoardVoteRes.TotalVotes != 0 && if cur.BoardVoteRes.TotalVotes != 0 &&
cur.BoardVoteRes.ApproveVotes+cur.BoardVoteRes.OpposeVotes != 0 && float32(cur.BoardVoteRes.ApproveVotes)/float32(cur.BoardVoteRes.TotalVotes) >= float32(cur.CurRule.BoardApproveRatio)/100.0 {
float32(cur.BoardVoteRes.ApproveVotes+cur.BoardVoteRes.OpposeVotes)/float32(cur.BoardVoteRes.TotalVotes) >= float32(cur.CurRule.BoardAttendRatio)/100.0 &&
float32(cur.BoardVoteRes.ApproveVotes)/float32(cur.BoardVoteRes.ApproveVotes+cur.BoardVoteRes.OpposeVotes) >= float32(cur.CurRule.BoardApproveRatio)/100.0 {
cur.BoardVoteRes.Pass = true cur.BoardVoteRes.Pass = true
} else { } else {
cur.BoardVoteRes.Pass = false cur.BoardVoteRes.Pass = false
} }
if cur.PubVote.Publicity { if cur.PubVote.Publicity {
if cur.GetBoardVoteRes().TotalVotes == 0 { //需要统计总票数 if cur.PubVote.TotalVotes == 0 { //需要统计总票数
vtCouts, err := a.getTotalVotes(start) vtCouts, err := a.getTotalVotes(start)
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -439,6 +491,13 @@ func (a *action) tmintPropProject(tmintProb *auty.TerminateProposalProject) (*ty ...@@ -439,6 +491,13 @@ func (a *action) tmintPropProject(tmintProb *auty.TerminateProposalProject) (*ty
} }
logs = append(logs, receipt.Logs...) logs = append(logs, receipt.Logs...)
kv = append(kv, receipt.KV...) kv = append(kv, receipt.KV...)
// 需要更新该董事会的累计审批金
pakv, err := a.updatePeriodAmount(cur.PropProject.Amount)
if err != nil {
alog.Error("tmintPropProject ", "addr", cur.Address, "execaddr", a.execaddr, "updatePeriodAmount fail", err)
return nil, err
}
kv = append(kv, pakv)
} else { } else {
// 解冻项目金 // 解冻项目金
receiptPrj, err := a.coinsAccount.ExecActive(autonomyFundAddr, a.execaddr, cur.PropProject.Amount) receiptPrj, err := a.coinsAccount.ExecActive(autonomyFundAddr, a.execaddr, cur.PropProject.Amount)
...@@ -473,12 +532,12 @@ func (a *action) getProposalProject(ID string) (*auty.AutonomyProposalProject, e ...@@ -473,12 +532,12 @@ func (a *action) getProposalProject(ID string) (*auty.AutonomyProposalProject, e
return cur, nil return cur, nil
} }
func (a *action) getActiveBoard() (*auty.ProposalBoard, error) { func (a *action) getActiveBoard() (*auty.ActiveBoard, error) {
value, err := a.db.Get(activeBoardID()) value, err := a.db.Get(activeBoardID())
if err != nil { if err != nil {
return nil, err return nil, err
} }
pboard := &auty.ProposalBoard{} pboard := &auty.ActiveBoard{}
err = types.Decode(value, pboard) err = types.Decode(value, pboard)
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -523,3 +582,26 @@ func copyAutonomyProposalProject(cur *auty.AutonomyProposalProject) *auty.Autono ...@@ -523,3 +582,26 @@ func copyAutonomyProposalProject(cur *auty.AutonomyProposalProject) *auty.Autono
} }
return &newAut return &newAut
} }
func (a *action) checkPeriodAmount(act *auty.ActiveBoard, amount int64) bool {
if act == nil {
return false
}
if act.Amount+amount > maxBoardPeriodAmount {
return false
}
return true
}
func (a *action) updatePeriodAmount(amount int64) (*types.KeyValue, error) {
act, err := a.getActiveBoard()
if err != nil {
return nil, err
}
if a.height > act.StartHeight+boardPeriod {
act.StartHeight = a.height
act.Amount = 0
}
act.Amount += amount
return &types.KeyValue{Key: activeBoardID(), Value: types.Encode(act)}, nil
}
...@@ -19,6 +19,11 @@ func (a *Autonomy) Query_ListProposalBoard(in *auty.ReqQueryProposalBoard) (type ...@@ -19,6 +19,11 @@ func (a *Autonomy) Query_ListProposalBoard(in *auty.ReqQueryProposalBoard) (type
return a.listProposalBoard(in) return a.listProposalBoard(in)
} }
// Query_GetActiveBoard 查询当前board
func (a *Autonomy) Query_GetActiveBoard(in *types.ReqString) (types.Message, error) {
return a.getActiveBoard()
}
// Query_GetProposalProject 查询提案项目 // Query_GetProposalProject 查询提案项目
func (a *Autonomy) Query_GetProposalProject(in *types.ReqString) (types.Message, error) { func (a *Autonomy) Query_GetProposalProject(in *types.ReqString) (types.Message, error) {
return a.getProposalProject(in) return a.getProposalProject(in)
...@@ -39,7 +44,22 @@ func (a *Autonomy) Query_ListProposalRule(in *auty.ReqQueryProposalRule) (types. ...@@ -39,7 +44,22 @@ func (a *Autonomy) Query_ListProposalRule(in *auty.ReqQueryProposalRule) (types.
return a.listProposalRule(in) return a.listProposalRule(in)
} }
// Query_GetActiveRule 查询当前rule
func (a *Autonomy) Query_GetActiveRule(in *types.ReqString) (types.Message, error) {
return a.getActiveRule()
}
// Query_ListProposalComment 批量查询提案评论 // Query_ListProposalComment 批量查询提案评论
func (a *Autonomy) Query_ListProposalComment(in *auty.ReqQueryProposalComment) (types.Message, error) { func (a *Autonomy) Query_ListProposalComment(in *auty.ReqQueryProposalComment) (types.Message, error) {
return a.listProposalComment(in) return a.listProposalComment(in)
} }
// Query_GetProposalChange 查询提案修改董事会成员
func (a *Autonomy) Query_GetProposalChange(in *types.ReqString) (types.Message, error) {
return a.getProposalChange(in)
}
// Query_ListProposalChange 批量查询
func (a *Autonomy) Query_ListProposalChange(in *auty.ReqQueryProposalChange) (types.Message, error) {
return a.listProposalChange(in)
}
...@@ -124,6 +124,24 @@ func (a *Autonomy) listProposalRule(req *auty.ReqQueryProposalRule) (types.Messa ...@@ -124,6 +124,24 @@ func (a *Autonomy) listProposalRule(req *auty.ReqQueryProposalRule) (types.Messa
return &rep, nil return &rep, nil
} }
func (a *Autonomy) getActiveRule() (types.Message, error) {
rule := &auty.RuleConfig{}
value, err := a.GetStateDB().Get(activeRuleID())
if err == nil {
err = types.Decode(value, rule)
if err != nil {
return nil, err
}
} else { // 载入系统默认值
rule.BoardApproveRatio = boardApproveRatio
rule.PubOpposeRatio = pubOpposeRatio
rule.ProposalAmount = proposalAmount
rule.LargeProjectAmount = largeProjectAmount
rule.PublicPeriod = publicPeriod
}
return rule, nil
}
func (a *Autonomy) execAutoLocalCommentProp(tx *types.Transaction, receiptData *types.ReceiptData) (*types.LocalDBSet, error) { func (a *Autonomy) execAutoLocalCommentProp(tx *types.Transaction, receiptData *types.ReceiptData) (*types.LocalDBSet, error) {
set, err := a.execLocalCommentProp(receiptData) set, err := a.execLocalCommentProp(receiptData)
if err != nil { if err != nil {
......
This diff is collapsed.
...@@ -9,23 +9,51 @@ import ( ...@@ -9,23 +9,51 @@ import (
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
auty "github.com/33cn/plugin/plugin/dapp/autonomy/types" auty "github.com/33cn/plugin/plugin/dapp/autonomy/types"
"github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/system/dapp" "github.com/33cn/chain33/system/dapp"
) )
const (
// 最小董事会赞成率
minBoardApproveRatio = 50
// 最大董事会赞成率
maxBoardApproveRatio = 66
// 最小全体持票人否决率
minPubOpposeRatio = 33
// 最大全体持票人否决率
maxPubOpposeRatio = 50
// 最小公示周期
minPublicPeriod int32 = 17280 * 7
// 最大公示周期
maxPublicPeriod int32 = 17280 * 14
// 最小重大项目阈值
minLargeProjectAmount = types.Coin * 100 * 10000
// 最大重大项目阈值
maxLargeProjectAmount = types.Coin * 300 * 10000
// 最小提案金
minProposalAmount = types.Coin * 20
// 最大提案金
maxProposalAmount = types.Coin * 2000
)
func (a *action) propRule(prob *auty.ProposalRule) (*types.Receipt, error) { func (a *action) propRule(prob *auty.ProposalRule) (*types.Receipt, error) {
//如果全小于等于0,则说明该提案规则参数不正确 //如果全小于等于0,则说明该提案规则参数不正确
if prob.RuleCfg == nil || prob.RuleCfg.BoardAttendRatio <= 0 && prob.RuleCfg.BoardApproveRatio <= 0 && if prob.RuleCfg == nil || prob.RuleCfg.BoardApproveRatio <= 0 && prob.RuleCfg.PubOpposeRatio <= 0 &&
prob.RuleCfg.PubOpposeRatio <= 0 && prob.RuleCfg.ProposalAmount <= 0 && prob.RuleCfg.LargeProjectAmount <= 0 && prob.RuleCfg.ProposalAmount <= 0 && prob.RuleCfg.LargeProjectAmount <= 0 && prob.RuleCfg.PublicPeriod <= 0 {
prob.RuleCfg.PublicPeriod <= 0 {
alog.Error("propRule ", "ProposalRule RuleCfg invaild or have no modify param", prob.RuleCfg) alog.Error("propRule ", "ProposalRule RuleCfg invaild or have no modify param", prob.RuleCfg)
return nil, types.ErrInvalidParam return nil, types.ErrInvalidParam
} }
if prob.RuleCfg.BoardAttendRatio > 100 || prob.RuleCfg.BoardApproveRatio > 100 || prob.RuleCfg.PubOpposeRatio > 100 { if (prob.RuleCfg.BoardApproveRatio > 0 && (prob.RuleCfg.BoardApproveRatio > maxBoardApproveRatio || prob.RuleCfg.BoardApproveRatio < minBoardApproveRatio)) ||
alog.Error("propRule RuleCfg invaild", "BoardAttendRatio", prob.RuleCfg.BoardAttendRatio, "BoardApproveRatio", (prob.RuleCfg.PubOpposeRatio > 0 && (prob.RuleCfg.PubOpposeRatio > maxPubOpposeRatio || prob.RuleCfg.PubOpposeRatio < minPubOpposeRatio)) ||
prob.RuleCfg.BoardApproveRatio, "PubOpposeRatio", prob.RuleCfg.PubOpposeRatio) (prob.RuleCfg.PublicPeriod > 0 && (prob.RuleCfg.PublicPeriod > maxPublicPeriod || prob.RuleCfg.PublicPeriod < minPublicPeriod)) ||
(prob.RuleCfg.LargeProjectAmount > 0 && (prob.RuleCfg.LargeProjectAmount > maxLargeProjectAmount || prob.RuleCfg.LargeProjectAmount < minLargeProjectAmount)) ||
(prob.RuleCfg.ProposalAmount > 0 && (prob.RuleCfg.ProposalAmount > maxProposalAmount || prob.RuleCfg.ProposalAmount < minProposalAmount)) {
alog.Error("propRule RuleCfg invaild", "ruleCfg", prob.RuleCfg)
return nil, types.ErrInvalidParam return nil, types.ErrInvalidParam
} }
if prob.StartBlockHeight < a.height || prob.EndBlockHeight < a.height {
if prob.StartBlockHeight < a.height || prob.EndBlockHeight < a.height ||
prob.StartBlockHeight+startEndBlockPeriod > prob.EndBlockHeight {
alog.Error("propRule height invaild", "StartBlockHeight", prob.StartBlockHeight, "EndBlockHeight", alog.Error("propRule height invaild", "StartBlockHeight", prob.StartBlockHeight, "EndBlockHeight",
prob.EndBlockHeight, "height", a.height) prob.EndBlockHeight, "height", a.height)
return nil, types.ErrInvalidParam return nil, types.ErrInvalidParam
...@@ -152,15 +180,39 @@ func (a *action) votePropRule(voteProb *auty.VoteProposalRule) (*types.Receipt, ...@@ -152,15 +180,39 @@ func (a *action) votePropRule(voteProb *auty.VoteProposalRule) (*types.Receipt,
return nil, err return nil, err
} }
if len(voteProb.OriginAddr) > 0 {
for _, board := range voteProb.OriginAddr {
if err := address.CheckAddress(board); err != nil {
alog.Error("votePropRule ", "addr", board, "check toAddr error", err)
return nil, types.ErrInvalidAddress
}
}
// 挖矿地址验证
addr, err := a.verifyMinerAddr(voteProb.OriginAddr, a.fromaddr)
if err != nil {
alog.Error("votePropRule ", "from addr", a.fromaddr, "error addr", addr, "ProposalID",
voteProb.ProposalID, "err", err)
return nil, err
}
}
// 本次参与投票地址
var addrs []string
if len(voteProb.OriginAddr) == 0 {
addrs = append(addrs, a.fromaddr)
} else {
addrs = append(addrs, voteProb.OriginAddr...)
}
// 检查是否已经参与投票 // 检查是否已经参与投票
votes, err := a.checkVotesRecord(votesRecord(voteProb.ProposalID)) votes, err := a.checkVotesRecord(addrs, votesRecord(voteProb.ProposalID))
if err != nil { if err != nil {
alog.Error("votePropRule ", "addr", a.fromaddr, "execaddr", a.execaddr, "checkVotesRecord failed", alog.Error("votePropRule ", "addr", a.fromaddr, "execaddr", a.execaddr, "checkVotesRecord failed",
voteProb.ProposalID, "err", err) voteProb.ProposalID, "err", err)
return nil, err return nil, err
} }
// 更新投票记录 // 更新投票记录
votes.Address = append(votes.Address, a.fromaddr) votes.Address = append(votes.Address, addrs...)
if cur.GetVoteResult().TotalVotes == 0 { //需要统计票数 if cur.GetVoteResult().TotalVotes == 0 { //需要统计票数
vtCouts, err := a.getTotalVotes(start) vtCouts, err := a.getTotalVotes(start)
...@@ -171,8 +223,10 @@ func (a *action) votePropRule(voteProb *auty.VoteProposalRule) (*types.Receipt, ...@@ -171,8 +223,10 @@ func (a *action) votePropRule(voteProb *auty.VoteProposalRule) (*types.Receipt,
} }
// 获取可投票数 // 获取可投票数
vtCouts, err := a.getAddressVotes(a.fromaddr, start) vtCouts, err := a.batchGetAddressVotes(addrs, start)
if err != nil { if err != nil {
alog.Error("votePropRule ", "addr", a.fromaddr, "execaddr", a.execaddr, "batchGetAddressVotes failed",
voteProb.ProposalID, "err", err)
return nil, err return nil, err
} }
if voteProb.Approve { if voteProb.Approve {
...@@ -396,9 +450,6 @@ func upgradeRule(cur, modify *auty.RuleConfig) *auty.RuleConfig { ...@@ -396,9 +450,6 @@ func upgradeRule(cur, modify *auty.RuleConfig) *auty.RuleConfig {
return nil return nil
} }
new := *cur new := *cur
if modify.BoardAttendRatio > 0 {
new.BoardAttendRatio = modify.BoardAttendRatio
}
if modify.BoardApproveRatio > 0 { if modify.BoardApproveRatio > 0 {
new.BoardApproveRatio = modify.BoardApproveRatio new.BoardApproveRatio = modify.BoardApproveRatio
} }
......
...@@ -8,6 +8,7 @@ syntax = "proto3"; ...@@ -8,6 +8,7 @@ syntax = "proto3";
import "board.proto"; import "board.proto";
import "project.proto"; import "project.proto";
import "rule.proto"; import "rule.proto";
import "change.proto";
package types; package types;
...@@ -33,6 +34,11 @@ message AutonomyAction { ...@@ -33,6 +34,11 @@ message AutonomyAction {
// 发展基金转自治系统合约 // 发展基金转自治系统合约
TransferFund transfer = 14; TransferFund transfer = 14;
Comment commentProp = 15; Comment commentProp = 15;
// 提案改变董事会成员
ProposalChange propChange = 16;
RevokeProposalChange rvkPropChange = 17;
VoteProposalChange votePropChange = 18;
TerminateProposalChange tmintPropChange = 19;
} }
int32 ty = 16; int32 ty = 20;
} }
\ No newline at end of file
...@@ -46,6 +46,7 @@ message RevokeProposalBoard { ...@@ -46,6 +46,7 @@ message RevokeProposalBoard {
message VoteProposalBoard { message VoteProposalBoard {
string proposalID = 1; string proposalID = 1;
bool approve = 2; bool approve = 2;
repeated string originAddr = 3;
} }
message TerminateProposalBoard { message TerminateProposalBoard {
......
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
syntax = "proto3";
import "lcommon.proto";
package types;
message AutonomyProposalChange {
ProposalChange propChange = 1;
// 投票该提案的规则
RuleConfig curRule = 2;
// 投票董事会
ActiveBoard board = 3;
// 全体持票人投票结果
VoteResult voteResult = 4;
// 状态
int32 status = 5;
string address = 6;
int64 height = 7;
int32 index = 8;
string proposalID = 9;
}
// action
message ProposalChange {
// 提案时间
int32 year = 1;
int32 month = 2;
int32 day = 3;
// 修改董事会成员
repeated Change Changes = 4;
// 投票相关
int64 startBlockHeight = 5; // 提案开始投票高度
int64 endBlockHeight = 6; // 提案结束投票高度
int64 realEndBlockHeight = 7; // 实际提案结束投票高度
}
message Change {
// 1 取消 0 恢复
bool cancel = 1;
string addr = 2;
}
message RevokeProposalChange {
string proposalID = 1;
}
message VoteProposalChange {
string proposalID = 1;
bool approve = 2;
}
message TerminateProposalChange {
string proposalID = 1;
}
// receipt
message ReceiptProposalChange {
AutonomyProposalChange prev = 1;
AutonomyProposalChange current = 2;
}
message LocalProposalChange {
AutonomyProposalChange propBd = 1;
repeated string comments = 2;
}
// query
message ReqQueryProposalChange {
int32 status = 1;
string addr = 2;
int32 count = 3;
int32 direction = 4;
int64 height = 5;
int32 index = 6;
}
message ReplyQueryProposalChange {
repeated AutonomyProposalChange propChanges = 1;
}
\ No newline at end of file
...@@ -33,16 +33,21 @@ message VotesRecord { ...@@ -33,16 +33,21 @@ message VotesRecord {
} }
message RuleConfig { message RuleConfig {
// 董事会成员参与率,以%为单位,只保留整数部分 // 董事会成员赞成率,以%为单位,只保留整数部分
int32 boardAttendRatio = 1; int32 boardApproveRatio = 1;
// 董事会成员赞成率
int32 boardApproveRatio = 2;
// 全体持票人否决率 // 全体持票人否决率
int32 pubOpposeRatio = 3; int32 pubOpposeRatio = 2;
// 提案金额 // 提案金额
int64 proposalAmount = 4; int64 proposalAmount = 3;
// 重大项目公示金额阈值 // 重大项目公示金额阈值
int64 largeProjectAmount = 5; int64 largeProjectAmount = 4;
// 重大项目公示时间(以区块数为单位) // 重大项目公示时间(以区块数为单位)
int32 publicPeriod = 6; int32 publicPeriod = 5;
}
message ActiveBoard {
repeated string boards = 1;
repeated string revboards = 2;
int64 amount = 3;
int64 startHeight = 4;
} }
\ No newline at end of file
...@@ -63,6 +63,7 @@ message VoteProposalProject { ...@@ -63,6 +63,7 @@ message VoteProposalProject {
message PubVoteProposalProject { message PubVoteProposalProject {
string proposalID = 1; string proposalID = 1;
bool oppose = 2; bool oppose = 2;
repeated string originAddr = 3;
} }
message TerminateProposalProject { message TerminateProposalProject {
......
...@@ -42,6 +42,7 @@ message RevokeProposalRule { ...@@ -42,6 +42,7 @@ message RevokeProposalRule {
message VoteProposalRule { message VoteProposalRule {
string proposalID = 1; string proposalID = 1;
bool approve = 2; bool approve = 2;
repeated string originAddr = 3;
} }
message TerminateProposalRule { message TerminateProposalRule {
......
...@@ -96,3 +96,12 @@ func testListProposalBoardCmd(t *testing.T, jrpc *jsonclient.JSONClient) error { ...@@ -96,3 +96,12 @@ func testListProposalBoardCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
rep = &auty.ReplyQueryProposalBoard{} rep = &auty.ReplyQueryProposalBoard{}
return jrpc.Call("Chain33.Query", params, rep) return jrpc.Call("Chain33.Query", params, rep)
} }
func testGetActiveBoardCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
var rep interface{}
var params rpctypes.Query4Jrpc
params.FuncName = auty.GetActiveBoard
params.Payload = types.MustPBToJSON(&types.ReqString{})
rep = &auty.ActiveBoard{}
return jrpc.Call("Chain33.Query", params, rep)
}
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package rpc_test
import (
"testing"
"encoding/json"
"github.com/33cn/chain33/rpc/jsonclient"
rpctypes "github.com/33cn/chain33/rpc/types"
_ "github.com/33cn/chain33/system"
"github.com/33cn/chain33/types"
_ "github.com/33cn/plugin/plugin"
auty "github.com/33cn/plugin/plugin/dapp/autonomy/types"
)
func testPropChangeTxCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
params := &auty.ProposalChange{}
payLoad, err := json.Marshal(params)
if err != nil {
return err
}
pm := &rpctypes.CreateTxIn{
Execer: types.ExecName(auty.AutonomyX),
ActionName: "PropChange",
Payload: payLoad,
}
var res string
return jrpc.Call("Chain33.CreateTransaction", pm, &res)
}
func testRevokeProposalChangeTxCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
params := &auty.RevokeProposalChange{}
payLoad, err := json.Marshal(params)
if err != nil {
return err
}
pm := &rpctypes.CreateTxIn{
Execer: types.ExecName(auty.AutonomyX),
ActionName: "RvkPropChange",
Payload: payLoad,
}
var res string
return jrpc.Call("Chain33.CreateTransaction", pm, &res)
}
func testVoteProposalChangeTxCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
params := &auty.VoteProposalChange{}
payLoad, err := json.Marshal(params)
if err != nil {
return err
}
pm := &rpctypes.CreateTxIn{
Execer: types.ExecName(auty.AutonomyX),
ActionName: "VotePropChange",
Payload: payLoad,
}
var res string
return jrpc.Call("Chain33.CreateTransaction", pm, &res)
}
func testTerminateProposalChangeTxCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
params := &auty.TerminateProposalChange{}
payLoad, err := json.Marshal(params)
if err != nil {
return err
}
pm := &rpctypes.CreateTxIn{
Execer: types.ExecName(auty.AutonomyX),
ActionName: "TmintPropChange",
Payload: payLoad,
}
var res string
return jrpc.Call("Chain33.CreateTransaction", pm, &res)
}
func testGetProposalChangeCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
var rep interface{}
var params rpctypes.Query4Jrpc
req := &types.ReqString{}
params.FuncName = auty.GetProposalChange
params.Payload = types.MustPBToJSON(req)
rep = &auty.ReplyQueryProposalChange{}
return jrpc.Call("Chain33.Query", params, rep)
}
func testListProposalChangeCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
var rep interface{}
var params rpctypes.Query4Jrpc
req := &auty.ReqQueryProposalChange{}
params.FuncName = auty.ListProposalChange
params.Payload = types.MustPBToJSON(req)
rep = &auty.ReplyQueryProposalChange{}
return jrpc.Call("Chain33.Query", params, rep)
}
...@@ -42,6 +42,7 @@ func TestJRPCChannel(t *testing.T) { ...@@ -42,6 +42,7 @@ func TestJRPCChannel(t *testing.T) {
{fn: testTerminateProposalBoardTxCmd}, {fn: testTerminateProposalBoardTxCmd},
{fn: testGetProposalBoardCmd}, {fn: testGetProposalBoardCmd},
{fn: testListProposalBoardCmd}, {fn: testListProposalBoardCmd},
{fn: testGetActiveBoardCmd},
{fn: testPropProjectTxCmd}, {fn: testPropProjectTxCmd},
{fn: testRevokeProposalProjectTxCmd}, {fn: testRevokeProposalProjectTxCmd},
...@@ -57,10 +58,18 @@ func TestJRPCChannel(t *testing.T) { ...@@ -57,10 +58,18 @@ func TestJRPCChannel(t *testing.T) {
{fn: testTerminateProposalRuleTxCmd}, {fn: testTerminateProposalRuleTxCmd},
{fn: testGetProposalRuleCmd}, {fn: testGetProposalRuleCmd},
{fn: testListProposalRuleCmd}, {fn: testListProposalRuleCmd},
{fn: testGetActiveRuleCmd},
{fn: testTransferFundTxCmd}, {fn: testTransferFundTxCmd},
{fn: testCommentProposalTxCmd}, {fn: testCommentProposalTxCmd},
{fn: testListProposalCommentCmd}, {fn: testListProposalCommentCmd},
{fn: testPropChangeTxCmd},
{fn: testRevokeProposalChangeTxCmd},
{fn: testVoteProposalChangeTxCmd},
{fn: testTerminateProposalChangeTxCmd},
{fn: testGetProposalChangeCmd},
{fn: testListProposalChangeCmd},
} }
for index, testCase := range testCases { for index, testCase := range testCases {
err := testCase.fn(t, jrpcClient) err := testCase.fn(t, jrpcClient)
......
...@@ -97,6 +97,15 @@ func testListProposalRuleCmd(t *testing.T, jrpc *jsonclient.JSONClient) error { ...@@ -97,6 +97,15 @@ func testListProposalRuleCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
return jrpc.Call("Chain33.Query", params, rep) return jrpc.Call("Chain33.Query", params, rep)
} }
func testGetActiveRuleCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
var rep interface{}
var params rpctypes.Query4Jrpc
params.FuncName = auty.GetActiveRule
params.Payload = types.MustPBToJSON(&types.ReqString{})
rep = &auty.RuleConfig{}
return jrpc.Call("Chain33.Query", params, rep)
}
func testTransferFundTxCmd(t *testing.T, jrpc *jsonclient.JSONClient) error { func testTransferFundTxCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
params := &auty.TransferFund{} params := &auty.TransferFund{}
payLoad, err := json.Marshal(params) payLoad, err := json.Marshal(params)
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -25,6 +25,11 @@ const ( ...@@ -25,6 +25,11 @@ const (
AutonomyActionTransfer AutonomyActionTransfer
AutonomyActionCommentProp AutonomyActionCommentProp
AutonomyActionPropChange
AutonomyActionRvkPropChange
AutonomyActionVotePropChange
AutonomyActionTmintPropChange
//log for autonomy //log for autonomy
TyLogPropBoard = 2101 TyLogPropBoard = 2101
TyLogRvkPropBoard = 2102 TyLogRvkPropBoard = 2102
...@@ -43,6 +48,11 @@ const ( ...@@ -43,6 +48,11 @@ const (
TyLogTmintPropRule = 2124 TyLogTmintPropRule = 2124
TyLogCommentProp = 2131 TyLogCommentProp = 2131
TyLogPropChange = 2141
TyLogRvkPropChange = 2142
TyLogVotePropChange = 2143
TyLogTmintPropChange = 2144
) )
// Board status // Board status
...@@ -70,11 +80,21 @@ const ( ...@@ -70,11 +80,21 @@ const (
AutonomyStatusTmintPropRule AutonomyStatusTmintPropRule
) )
// Change status
const (
AutonomyStatusProposalChange = iota + 1
AutonomyStatusRvkPropChange
AutonomyStatusVotePropChange
AutonomyStatusTmintPropChange
)
const ( const (
// GetProposalBoard 用于在cmd里面的区分不同的查询 // GetProposalBoard 用于在cmd里面的区分不同的查询
GetProposalBoard = "GetProposalBoard" GetProposalBoard = "GetProposalBoard"
// ListProposalBoard 查询多个 // ListProposalBoard 查询多个
ListProposalBoard = "ListProposalBoard" ListProposalBoard = "ListProposalBoard"
// GetActiveBoard 查询当前的
GetActiveBoard = "GetActiveBoard"
// GetProposalProject 用于在cmd里面的区分不同的查询 // GetProposalProject 用于在cmd里面的区分不同的查询
GetProposalProject = "GetProposalProject" GetProposalProject = "GetProposalProject"
// ListProposalProject 查询多个 // ListProposalProject 查询多个
...@@ -83,8 +103,14 @@ const ( ...@@ -83,8 +103,14 @@ const (
GetProposalRule = "GetProposalRule" GetProposalRule = "GetProposalRule"
// ListProposalRule 查询多个 // ListProposalRule 查询多个
ListProposalRule = "ListProposalRule" ListProposalRule = "ListProposalRule"
// GetActiveRule 查询当前的
GetActiveRule = "GetActiveRule"
// ListProposalComment 查询多个 // ListProposalComment 查询多个
ListProposalComment = "ListProposalComment" ListProposalComment = "ListProposalComment"
// GetProposalChange 用于在cmd里面的区分不同的查询
GetProposalChange = "GetProposalChange"
// ListProposalChange 查询多个
ListProposalChange = "ListProposalChange"
) )
//包的名字可以通过配置文件来配置 //包的名字可以通过配置文件来配置
......
...@@ -23,4 +23,16 @@ var ( ...@@ -23,4 +23,16 @@ var (
ErrNoActiveBoard = errors.New("ErrNoActiveBoard") ErrNoActiveBoard = errors.New("ErrNoActiveBoard")
// ErrNoAutonomyExec 非Autonomy执行器 // ErrNoAutonomyExec 非Autonomy执行器
ErrNoAutonomyExec = errors.New("ErrNoAutonomyExec") ErrNoAutonomyExec = errors.New("ErrNoAutonomyExec")
// ErrNoPeriodAmount 当前没有足够额度
ErrNoPeriodAmount = errors.New("ErrNoPeriodAmount")
// ErrMinerAddr 无效挖矿地址
ErrMinerAddr = errors.New("ErrMinerAddr")
// ErrBindAddr 无效绑定地址
ErrBindAddr = errors.New("ErrBindAddr")
// ErrChangeBoardAddr 无效修改董事会成员地址
ErrChangeBoardAddr = errors.New("ErrChangeBoardAddr")
// ErrBoardNumber 董事会成员数错误
ErrBoardNumber = errors.New("ErrBoardNumber")
// ErrRepeatAddr 重复地址
ErrRepeatAddr = errors.New("ErrRepeatAddr")
) )
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -57,6 +57,11 @@ func (a *AutonomyType) GetLogMap() map[int64]*types.LogInfo { ...@@ -57,6 +57,11 @@ func (a *AutonomyType) GetLogMap() map[int64]*types.LogInfo {
TyLogTmintPropRule: {Ty: reflect.TypeOf(ReceiptProposalRule{}), Name: "LogTmintPropRule"}, TyLogTmintPropRule: {Ty: reflect.TypeOf(ReceiptProposalRule{}), Name: "LogTmintPropRule"},
TyLogCommentProp: {Ty: reflect.TypeOf(ReceiptProposalComment{}), Name: "LogCommentProp"}, TyLogCommentProp: {Ty: reflect.TypeOf(ReceiptProposalComment{}), Name: "LogCommentProp"},
TyLogPropChange: {Ty: reflect.TypeOf(ReceiptProposalChange{}), Name: "LogPropChange"},
TyLogRvkPropChange: {Ty: reflect.TypeOf(ReceiptProposalChange{}), Name: "LogRvkPropChange"},
TyLogVotePropChange: {Ty: reflect.TypeOf(ReceiptProposalChange{}), Name: "LogVotePropChange"},
TyLogTmintPropChange: {Ty: reflect.TypeOf(ReceiptProposalChange{}), Name: "LogTmintPropChange"},
} }
} }
...@@ -86,5 +91,10 @@ func (a *AutonomyType) GetTypeMap() map[string]int32 { ...@@ -86,5 +91,10 @@ func (a *AutonomyType) GetTypeMap() map[string]int32 {
"Transfer": AutonomyActionTransfer, "Transfer": AutonomyActionTransfer,
"CommentProp": AutonomyActionCommentProp, "CommentProp": AutonomyActionCommentProp,
"PropChange": AutonomyActionPropChange,
"RvkPropChange": AutonomyActionRvkPropChange,
"VotePropChange": AutonomyActionVotePropChange,
"TmintPropChange": AutonomyActionTmintPropChange,
} }
} }
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