Commit 83b88f85 authored by liuyuhang's avatar liuyuhang

1、修改可变系统参数范围以及默认值

2、加入对于代理挖矿的投票 3、加入提案撤销某个board的新提案
parent a3a0d677
...@@ -81,7 +81,7 @@ func addProposalBoardFlags(cmd *cobra.Command) { ...@@ -81,7 +81,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 +173,27 @@ func addVoteProposalBoardFlags(cmd *cobra.Command) { ...@@ -173,22 +173,27 @@ 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
} }
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 {
......
...@@ -12,6 +12,7 @@ import ( ...@@ -12,6 +12,7 @@ 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/spf13/cobra" "github.com/spf13/cobra"
"strings"
) )
// ProposalProjectCmd 创建提案命令 // ProposalProjectCmd 创建提案命令
...@@ -201,12 +202,14 @@ func addPubVoteProposalProjectFlags(cmd *cobra.Command) { ...@@ -201,12 +202,14 @@ 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", "o", 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 +218,12 @@ func pubVoteProposalProject(cmd *cobra.Command, args []string) { ...@@ -215,9 +218,12 @@ func pubVoteProposalProject(cmd *cobra.Command, args []string) {
isopp = true isopp = true
} }
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 {
......
...@@ -12,6 +12,7 @@ import ( ...@@ -12,6 +12,7 @@ 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/spf13/cobra" "github.com/spf13/cobra"
"strings"
) )
// ProposalRuleCmd 创建提案命令 // ProposalRuleCmd 创建提案命令
...@@ -142,12 +143,14 @@ func addVoteProposalRuleFlags(cmd *cobra.Command) { ...@@ -142,12 +143,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 +158,12 @@ func voteProposalRule(cmd *cobra.Command, args []string) { ...@@ -155,9 +158,12 @@ func voteProposalRule(cmd *cobra.Command, args []string) {
isapp = true isapp = true
} }
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 {
......
...@@ -14,19 +14,21 @@ import ( ...@@ -14,19 +14,21 @@ 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"
"syscall"
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 * 1000 // 创建者消耗金额
boardAttendRatio int32 = 66 // 董事会成员参与率,以%计,可修改
boardApproveRatio int32 = 66 // 董事会成员赞成率,以%计,可修改 boardApproveRatio int32 = 66 // 董事会成员赞成率,以%计,可修改
pubAttendRatio int32 = 50 // 全体持票人参与率,以%计 pubAttendRatio int32 = 75 // 全体持票人参与率,以%计
pubApproveRatio int32 = 50 // 全体持票人赞成率,以%计 pubApproveRatio int32 = 66 // 全体持票人赞成率,以%计
pubOpposeRatio int32 = 33 // 全体持票人否决率,以%计 pubOpposeRatio int32 = 33 // 全体持票人否决率,以%计
) )
...@@ -187,15 +189,33 @@ func (a *action) votePropBoard(voteProb *auty.VoteProposalBoard) (*types.Receipt ...@@ -187,15 +189,33 @@ func (a *action) votePropBoard(voteProb *auty.VoteProposalBoard) (*types.Receipt
return nil, err return nil, err
} }
// 挖矿地址验证
if len(voteProb.OriginAddr) > 0 {
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 +225,10 @@ func (a *action) votePropBoard(voteProb *auty.VoteProposalBoard) (*types.Receipt ...@@ -205,8 +225,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 +271,11 @@ func (a *action) votePropBoard(voteProb *auty.VoteProposalBoard) (*types.Receipt ...@@ -249,7 +271,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 +351,11 @@ func (a *action) tmintPropBoard(tmintProb *auty.TerminateProposalBoard) (*types. ...@@ -325,7 +351,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 +376,34 @@ func (a *action) getTotalVotes(height int64) (int32, error) { ...@@ -346,6 +376,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 {
...@@ -416,7 +474,7 @@ func (a *action) getActiveRule() (*auty.RuleConfig, error) { ...@@ -416,7 +474,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 +483,15 @@ func (a *action) checkVotesRecord(key []byte) (*auty.VotesRecord, error) { ...@@ -425,10 +483,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
} }
} }
......
This diff is collapsed.
...@@ -12,6 +12,11 @@ import ( ...@@ -12,6 +12,11 @@ import (
"github.com/33cn/chain33/common/address" "github.com/33cn/chain33/common/address"
) )
const (
maxBoardPeriodAmount = types.Coin * 10000 * 300 // 每个时期董事会审批最大额度200万
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)
...@@ -30,6 +35,20 @@ func (a *action) propProject(prob *auty.ProposalProject) (*types.Receipt, error) ...@@ -30,6 +35,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 +94,9 @@ func (a *action) propProject(prob *auty.ProposalProject) (*types.Receipt, error) ...@@ -75,6 +94,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 +211,7 @@ func (a *action) votePropProject(voteProb *auty.VoteProposalProject) (*types.Rec ...@@ -189,7 +211,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)
...@@ -244,6 +266,13 @@ func (a *action) votePropProject(voteProb *auty.VoteProposalProject) (*types.Rec ...@@ -244,6 +266,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 +319,33 @@ func (a *action) pubVotePropProject(voteProb *auty.PubVoteProposalProject) (*typ ...@@ -290,15 +319,33 @@ func (a *action) pubVotePropProject(voteProb *auty.PubVoteProposalProject) (*typ
return nil, err return nil, err
} }
// 挖矿地址验证
if len(voteProb.OriginAddr) > 0 {
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 +356,10 @@ func (a *action) pubVotePropProject(voteProb *auty.PubVoteProposalProject) (*typ ...@@ -309,8 +356,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 { //投反对票
...@@ -333,6 +382,13 @@ func (a *action) pubVotePropProject(voteProb *auty.PubVoteProposalProject) (*typ ...@@ -333,6 +382,13 @@ func (a *action) pubVotePropProject(voteProb *auty.PubVoteProposalProject) (*typ
} }
logs = append(logs, receiptPrj.Logs...) logs = append(logs, receiptPrj.Logs...)
kv = append(kv, receiptPrj.KV...) kv = append(kv, receiptPrj.KV...)
// 需要更新该董事会的累计审批金
pakv, err := a.updatePeriodAmount(cur.PropProject.Amount)
if err != nil {
alog.Error("pubVotePropProject ", "addr", cur.Address, "execaddr", a.execaddr, "updatePeriodAmount fail", err)
return nil, err
}
kv = append(kv, pakv)
} }
key := propProjectID(voteProb.ProposalID) key := propProjectID(voteProb.ProposalID)
...@@ -439,6 +495,13 @@ func (a *action) tmintPropProject(tmintProb *auty.TerminateProposalProject) (*ty ...@@ -439,6 +495,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 +536,12 @@ func (a *action) getProposalProject(ID string) (*auty.AutonomyProposalProject, e ...@@ -473,12 +536,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 +586,26 @@ func copyAutonomyProposalProject(cur *auty.AutonomyProposalProject) *auty.Autono ...@@ -523,3 +586,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
}
\ No newline at end of file
...@@ -12,15 +12,30 @@ import ( ...@@ -12,15 +12,30 @@ import (
"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
)
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.BoardAttendRatio < minBoardAttendRatio && prob.RuleCfg.BoardApproveRatio < minBoardApproveRatio &&
prob.RuleCfg.PubOpposeRatio <= 0 && prob.RuleCfg.ProposalAmount <= 0 && prob.RuleCfg.LargeProjectAmount <= 0 && prob.RuleCfg.PubOpposeRatio <= minPubOpposeRatio && 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.BoardAttendRatio > MaxBoardAttendRatio || prob.RuleCfg.BoardApproveRatio > maxBoardApproveRatio || prob.RuleCfg.PubOpposeRatio > maxPubOpposeRatio {
alog.Error("propRule RuleCfg invaild", "BoardAttendRatio", prob.RuleCfg.BoardAttendRatio, "BoardApproveRatio", alog.Error("propRule RuleCfg invaild", "BoardAttendRatio", prob.RuleCfg.BoardAttendRatio, "BoardApproveRatio",
prob.RuleCfg.BoardApproveRatio, "PubOpposeRatio", prob.RuleCfg.PubOpposeRatio) prob.RuleCfg.BoardApproveRatio, "PubOpposeRatio", prob.RuleCfg.PubOpposeRatio)
return nil, types.ErrInvalidParam return nil, types.ErrInvalidParam
...@@ -152,15 +167,33 @@ func (a *action) votePropRule(voteProb *auty.VoteProposalRule) (*types.Receipt, ...@@ -152,15 +167,33 @@ func (a *action) votePropRule(voteProb *auty.VoteProposalRule) (*types.Receipt,
return nil, err return nil, err
} }
// 挖矿地址验证
if len(voteProb.OriginAddr) > 0 {
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 +204,10 @@ func (a *action) votePropRule(voteProb *auty.VoteProposalRule) (*types.Receipt, ...@@ -171,8 +204,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 {
......
...@@ -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;
// 全体持票人投票结果
VoteResult voteResult = 3;
// 状态
int32 status = 4;
string address = 5;
int64 height = 6;
int32 index = 7;
string proposalID = 8;
}
// 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
...@@ -45,4 +45,11 @@ message RuleConfig { ...@@ -45,4 +45,11 @@ message RuleConfig {
int64 largeProjectAmount = 5; int64 largeProjectAmount = 5;
// 重大项目公示时间(以区块数为单位) // 重大项目公示时间(以区块数为单位)
int32 publicPeriod = 6; int32 publicPeriod = 6;
}
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 {
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -23,4 +23,10 @@ var ( ...@@ -23,4 +23,10 @@ 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")
) )
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment