Commit 4016e4d3 authored by mdj33's avatar mdj33

improved by issue specification

parent 2b013042
......@@ -12,6 +12,7 @@ import (
"github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types"
auty "github.com/33cn/plugin/plugin/dapp/autonomy/types"
"github.com/pkg/errors"
"github.com/33cn/chain33/common/address"
ticket "github.com/33cn/plugin/plugin/dapp/ticket/executor"
......@@ -51,60 +52,76 @@ func newAction(a *Autonomy, tx *types.Transaction, index int32) *action {
a.GetBlockTime(), a.GetHeight(), index, dapp.ExecAddress(string(tx.Execer))}
}
func (a *action) propBoard(prob *auty.ProposalBoard) (*types.Receipt, error) {
if prob.StartBlockHeight < a.height || prob.EndBlockHeight < a.height ||
prob.StartBlockHeight+startEndBlockPeriod > prob.EndBlockHeight {
alog.Error("propBoard height invaild", "StartBlockHeight", prob.StartBlockHeight, "EndBlockHeight",
prob.EndBlockHeight, "height", a.height)
return nil, auty.ErrSetBlockHeight
func (a *action) getPropBoard(prob *auty.ProposalBoard) (*auty.ActiveBoard, error) {
mpBd, err := filterPropBoard(prob.Boards)
if err != nil {
return nil, err
}
if len(prob.Boards) == 0 {
alog.Error("propBoard ", "proposal boards number is zero", len(prob.Boards))
return nil, auty.ErrBoardNumber
switch prob.BoardUpdate {
case auty.BoardUpdate_WHOLE:
return &auty.ActiveBoard{Boards: prob.Boards}, nil
case auty.BoardUpdate_ADD:
return a.addPropBoard(prob, mpBd)
case auty.BoardUpdate_DEL:
return a.delPropBoard(prob, mpBd)
default:
return nil, errors.Wrapf(types.ErrInvalidParam, "board update param=%d", prob.BoardUpdate)
}
}
func (a *action) getOldPropBoard(prob *auty.ProposalBoard) (*auty.ActiveBoard, error) {
mpBd, err := filterPropBoard(prob.Boards)
if err != nil {
return nil, err
}
//replace all
if !prob.Update {
return &auty.ActiveBoard{
Boards: prob.Boards,
}, nil
}
// only add member
return a.addPropBoard(prob, mpBd)
}
func filterPropBoard(boards []string) (map[string]struct{}, error) {
mpBd := make(map[string]struct{})
for _, board := range prob.Boards {
for _, board := range boards {
if err := address.CheckAddress(board); err != nil {
alog.Error("propBoard ", "addr", board, "check toAddr error", err)
return nil, types.ErrInvalidAddress
return nil, errors.Wrapf(types.ErrInvalidAddress, "addr", board)
}
// 提案board重复地址去重复
if _, ok := mpBd[board]; ok {
err := auty.ErrRepeatAddr
alog.Error("propBoard ", "addr", board, "propBoard have repeat addr ", err)
return nil, err
return nil, errors.Wrapf(auty.ErrRepeatAddr, "propBoard addr=%s repeated", board)
}
mpBd[board] = struct{}{}
}
return mpBd, nil
}
func (a *action) propBoard(prob *auty.ProposalBoard) (*types.Receipt, error) {
if prob.StartBlockHeight < a.height || prob.EndBlockHeight < a.height ||
prob.StartBlockHeight+startEndBlockPeriod > prob.EndBlockHeight {
alog.Error("propBoard height invaild", "StartBlockHeight", prob.StartBlockHeight, "EndBlockHeight",
prob.EndBlockHeight, "height", a.height)
return nil, auty.ErrSetBlockHeight
}
if len(prob.Boards) == 0 {
alog.Error("propBoard ", "proposal boards number is zero", len(prob.Boards))
return nil, auty.ErrBoardNumber
}
var act *auty.ActiveBoard
var err error
if prob.Update {
act, err = a.getActiveBoard()
if err != nil {
alog.Error("propBoard ", "addr", a.fromaddr, "execaddr", a.execaddr, "getActiveBoard failed", err)
return nil, err
}
for _, board := range act.Boards {
if _, ok := mpBd[board]; ok {
err := auty.ErrRepeatAddr
alog.Error("propBoard ", "addr", board, "propBoard update have repeat addr in boards", err)
return nil, err
}
}
for _, board := range act.Revboards {
if _, ok := mpBd[board]; ok {
err := auty.ErrRepeatAddr
alog.Error("propBoard ", "addr", board, "propBoard update have repeat addr in revboards ", err)
return nil, err
}
}
act.Boards = append(act.Boards, prob.Boards...)
cfg := a.api.GetConfig()
if cfg.IsDappFork(a.height, auty.AutonomyX, auty.ForkAutonomyDelRule) {
act, err = a.getPropBoard(prob)
} else {
act = &auty.ActiveBoard{
Boards: prob.Boards,
}
act, err = a.getOldPropBoard(prob)
}
if len(act.Boards) > maxBoards || len(act.Boards) < minBoards {
......@@ -280,10 +297,27 @@ func (a *action) votePropBoard(voteProb *auty.VoteProposalBoard) (*types.Receipt
voteProb.ProposalID, "err", err)
return nil, err
}
if voteProb.Approve {
cur.VoteResult.ApproveVotes += vtCouts
cfg := a.api.GetConfig()
//fork之后增加了弃权选项
if cfg.IsDappFork(a.height, auty.AutonomyX, auty.ForkAutonomyDelRule) {
switch voteProb.VoteOption {
case auty.VoteOption_APPROVE:
cur.VoteResult.ApproveVotes += vtCouts
case auty.VoteOption_OPPOSE:
cur.VoteResult.OpposeVotes += vtCouts
case auty.VoteOption_QUIT:
cur.VoteResult.QuitVotes += vtCouts
default:
return nil, errors.Wrapf(types.ErrInvalidParam, "vote option=%d", voteProb.VoteOption)
}
} else {
cur.VoteResult.OpposeVotes += vtCouts
if voteProb.Approve {
cur.VoteResult.ApproveVotes += vtCouts
} else {
cur.VoteResult.OpposeVotes += vtCouts
}
}
var logs []*types.ReceiptLog
......@@ -300,12 +334,20 @@ func (a *action) votePropBoard(voteProb *auty.VoteProposalBoard) (*types.Receipt
kv = append(kv, receipt.KV...)
}
if cur.VoteResult.TotalVotes != 0 &&
cur.VoteResult.ApproveVotes+cur.VoteResult.OpposeVotes != 0 &&
float32(cur.VoteResult.ApproveVotes+cur.VoteResult.OpposeVotes)/float32(cur.VoteResult.TotalVotes) > float32(pubAttendRatio)/100.0 &&
float32(cur.VoteResult.ApproveVotes)/float32(cur.VoteResult.ApproveVotes+cur.VoteResult.OpposeVotes) > float32(pubApproveRatio)/100.0 {
cur.VoteResult.Pass = true
cur.PropBoard.RealEndBlockHeight = a.height
if cfg.IsDappFork(a.height, auty.AutonomyX, auty.ForkAutonomyDelRule) {
if isApproved(cur.VoteResult.TotalVotes, cur.VoteResult.ApproveVotes, cur.VoteResult.OpposeVotes, cur.VoteResult.QuitVotes,
cur.CurRule.PubAttendRatio, cur.CurRule.PubApproveRatio) {
cur.VoteResult.Pass = true
cur.PropBoard.RealEndBlockHeight = a.height
}
} else {
if cur.VoteResult.TotalVotes != 0 &&
cur.VoteResult.ApproveVotes+cur.VoteResult.OpposeVotes != 0 &&
float32(cur.VoteResult.ApproveVotes+cur.VoteResult.OpposeVotes)/float32(cur.VoteResult.TotalVotes) > float32(pubAttendRatio)/100.0 &&
float32(cur.VoteResult.ApproveVotes)/float32(cur.VoteResult.ApproveVotes+cur.VoteResult.OpposeVotes) > float32(pubApproveRatio)/100.0 {
cur.VoteResult.Pass = true
cur.PropBoard.RealEndBlockHeight = a.height
}
}
key := propBoardID(voteProb.ProposalID)
......@@ -320,8 +362,14 @@ func (a *action) votePropBoard(voteProb *auty.VoteProposalBoard) (*types.Receipt
// 更新当前具有权利的董事会成员
if cur.VoteResult.Pass {
if !cur.PropBoard.Update { // 非update才进行高度重写
cur.Board.StartHeight = a.height
if a.api.GetConfig().IsDappFork(a.height, auty.AutonomyX, auty.ForkAutonomyDelRule) {
if cur.PropBoard.BoardUpdate == auty.BoardUpdate_WHOLE {
cur.Board.StartHeight = a.height
}
} else {
if !cur.PropBoard.Update { // 非update才进行高度重写
cur.Board.StartHeight = a.height
}
}
kv = append(kv, &types.KeyValue{Key: activeBoardID(), Value: types.Encode(cur.Board)})
}
......@@ -336,6 +384,26 @@ func (a *action) votePropBoard(voteProb *auty.VoteProposalBoard) (*types.Receipt
return &types.Receipt{Ty: types.ExecOk, KV: kv, Logs: logs}, nil
}
//统计参与率的时候,计算弃权票,但是统计赞成率的时候,忽略弃权票。比如10票,4票赞成,3票反对,2票弃权,那么参与率是 90%, 赞成 4/7 反对 3/7
func isApproved(totalVotes, approveVotes, opposeVotes, quitVotes, attendRation, approveRatio int32) bool {
if attendRation <= 0 {
attendRation = pubAttendRatio
}
if approveRatio <= 0 {
approveRatio = pubApproveRatio
}
//参与率计算弃权票
attendVotes := approveVotes + opposeVotes + quitVotes
//赞成率,忽略弃权票
validVotes := approveVotes + opposeVotes
if totalVotes != 0 && attendVotes != 0 &&
attendVotes*100 > attendRation*totalVotes &&
approveVotes*100 > approveRatio*validVotes {
return true
}
return false
}
func (a *action) tmintPropBoard(tmintProb *auty.TerminateProposalBoard) (*types.Receipt, error) {
cur, err := a.getProposalBoard(tmintProb.ProposalID)
if err != nil {
......@@ -371,11 +439,16 @@ func (a *action) tmintPropBoard(tmintProb *auty.TerminateProposalBoard) (*types.
cur.VoteResult.TotalVotes = vtCouts
}
if float32(cur.VoteResult.ApproveVotes+cur.VoteResult.OpposeVotes)/float32(cur.VoteResult.TotalVotes) > float32(pubAttendRatio)/100.0 &&
float32(cur.VoteResult.ApproveVotes)/float32(cur.VoteResult.ApproveVotes+cur.VoteResult.OpposeVotes) > float32(pubApproveRatio)/100.0 {
cur.VoteResult.Pass = true
if a.api.GetConfig().IsDappFork(a.height, auty.AutonomyX, auty.ForkAutonomyDelRule) {
cur.VoteResult.Pass = isApproved(cur.VoteResult.TotalVotes, cur.VoteResult.ApproveVotes, cur.VoteResult.OpposeVotes, cur.VoteResult.QuitVotes,
cur.CurRule.PubAttendRatio, cur.CurRule.PubApproveRatio)
} else {
cur.VoteResult.Pass = false
if float32(cur.VoteResult.ApproveVotes+cur.VoteResult.OpposeVotes)/float32(cur.VoteResult.TotalVotes) > float32(pubAttendRatio)/100.0 &&
float32(cur.VoteResult.ApproveVotes)/float32(cur.VoteResult.ApproveVotes+cur.VoteResult.OpposeVotes) > float32(pubApproveRatio)/100.0 {
cur.VoteResult.Pass = true
} else {
cur.VoteResult.Pass = false
}
}
cur.PropBoard.RealEndBlockHeight = a.height
......@@ -399,8 +472,14 @@ func (a *action) tmintPropBoard(tmintProb *auty.TerminateProposalBoard) (*types.
// 更新当前具有权利的董事会成员
if cur.VoteResult.Pass {
if !cur.PropBoard.Update { // 非update才进行高度重写
cur.Board.StartHeight = a.height
if a.api.GetConfig().IsDappFork(a.height, auty.AutonomyX, auty.ForkAutonomyDelRule) {
if cur.PropBoard.BoardUpdate == auty.BoardUpdate_WHOLE {
cur.Board.StartHeight = a.height
}
} else {
if !cur.PropBoard.Update { // 非update才进行高度重写
cur.Board.StartHeight = a.height
}
}
kv = append(kv, &types.KeyValue{Key: activeBoardID(), Value: types.Encode(cur.Board)})
}
......@@ -507,6 +586,7 @@ func (a *action) getProposalBoard(ID string) (*auty.AutonomyProposalBoard, error
}
func (a *action) getActiveRule() (*auty.RuleConfig, error) {
cfg := a.api.GetConfig()
// 获取当前生效提案规则,并且将不修改的规则补齐
rule := &auty.RuleConfig{}
value, err := a.db.Get(activeRuleID())
......@@ -516,12 +596,28 @@ func (a *action) getActiveRule() (*auty.RuleConfig, error) {
if err != nil {
return nil, err
}
//在fork之前可能有修改了规则,但是这两个值没有修改到
if cfg.IsDappFork(a.height, auty.AutonomyX, auty.ForkAutonomyDelRule) {
if rule.PubApproveRatio <= 0 {
rule.PubApproveRatio = pubApproveRatio
}
if rule.PubAttendRatio <= 0 {
rule.PubAttendRatio = pubAttendRatio
}
}
} else { // 载入系统默认值
rule.BoardApproveRatio = boardApproveRatio
rule.PubOpposeRatio = pubOpposeRatio
rule.ProposalAmount = proposalAmount * cfg.GetCoinPrecision()
rule.LargeProjectAmount = largeProjectAmount * cfg.GetCoinPrecision()
rule.PublicPeriod = publicPeriod
if cfg.IsDappFork(a.height, auty.AutonomyX, auty.ForkAutonomyDelRule) {
rule.PubAttendRatio = pubAttendRatio
rule.PubApproveRatio = pubApproveRatio
}
}
return rule, nil
}
......@@ -550,6 +646,77 @@ func (a *action) checkVotesRecord(addrs []string, key []byte) (*auty.VotesRecord
return &votes, nil
}
//新增addr场景,任一probAddr在当前board里即返回true
func checkAddrInBoard(act *auty.ActiveBoard, probAddrs map[string]struct{}) bool {
for _, board := range act.Boards {
if _, ok := probAddrs[board]; ok {
alog.Info("propBoard repeated addr in boards", "addr", board)
return true
}
}
for _, board := range act.Revboards {
if _, ok := probAddrs[board]; ok {
alog.Info("propBoard repeated addr in revboards", "addr", board)
return true
}
}
return false
}
func (a *action) addPropBoard(prob *auty.ProposalBoard, mpBd map[string]struct{}) (*auty.ActiveBoard, error) {
// only add member
act, err := a.getActiveBoard()
if err != nil {
alog.Error("propBoard ", "addr", a.fromaddr, "execaddr", a.execaddr, "getActiveBoard failed", err)
return nil, err
}
if checkAddrInBoard(act, mpBd) {
return nil, errors.Wrap(auty.ErrRepeatAddr, "repeated addr in current boards")
}
act.Boards = append(act.Boards, prob.Boards...)
return act, nil
}
//删除addr场景,若任一proposal addr不存在 则返回true,
func checkAddrNotInBoard(act *auty.ActiveBoard, prob *auty.ProposalBoard) error {
actBoards := make(map[string]bool)
for _, board := range act.Boards {
actBoards[board] = true
}
for _, addr := range prob.Boards {
if !actBoards[addr] {
return errors.Wrapf(types.ErrNotFound, "addr=%s not in boards", addr)
}
}
return nil
}
//这里只考虑Board,不考虑revBoard
func (a *action) delPropBoard(prob *auty.ProposalBoard, mpBd map[string]struct{}) (*auty.ActiveBoard, error) {
act, err := a.getActiveBoard()
if err != nil {
alog.Error("propBoard ", "addr", a.fromaddr, "execaddr", a.execaddr, "getActiveBoard failed", err)
return nil, err
}
err = checkAddrNotInBoard(act, prob)
if err != nil {
return nil, err
}
var newBoard []string
for _, board := range act.Boards {
if _, ok := mpBd[board]; !ok {
newBoard = append(newBoard, board)
}
}
act.Boards = newBoard
return act, nil
}
// getReceiptLog 根据提案信息获取log
// 状态变化:
func getReceiptLog(pre, cur *auty.AutonomyProposalBoard, ty int32) *types.ReceiptLog {
......
......@@ -7,6 +7,8 @@ package executor
import (
"sort"
"github.com/pkg/errors"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/types"
auty "github.com/33cn/plugin/plugin/dapp/autonomy/types"
......@@ -30,11 +32,21 @@ func (a *action) propChange(prob *auty.ProposalChange) (*types.Receipt, error) {
alog.Error("propChange ", "addr", a.fromaddr, "execaddr", a.execaddr, "getActiveBoard failed", err)
return nil, err
}
// 检查是否符合提案修改
new, err := a.checkChangeable(act, prob.Changes)
if err != nil {
alog.Error("propChange ", "addr", a.fromaddr, "execaddr", a.execaddr, "checkChangeable failed", err)
return nil, err
var new *auty.ActiveBoard
if a.api.GetConfig().IsDappFork(a.height, auty.AutonomyX, auty.ForkAutonomyDelRule) {
//替换成员方案
new, err = a.replaceBoard(act, prob.Changes)
if err != nil {
return nil, err
}
} else {
new, err = a.checkChangeable(act, prob.Changes)
if err != nil {
alog.Error("propChange ", "addr", a.fromaddr, "execaddr", a.execaddr, "checkChangeable failed", err)
return nil, err
}
}
// 获取当前生效提案规则,并且将不修改的规则补齐
......@@ -167,20 +179,32 @@ func (a *action) votePropChange(voteProb *auty.VoteProposalChange) (*types.Recei
return nil, err
}
// 董事会成员验证
cfg := a.api.GetConfig()
// 董事会成员验证,把剔除的原成员放回来
mpBd := make(map[string]struct{})
for _, b := range cur.Board.Boards {
mpBd[b] = struct{}{}
}
for _, ch := range cur.PropChange.Changes {
if ch.Cancel {
mpBd[ch.Addr] = struct{}{}
} else {
if _, ok := mpBd[ch.Addr]; ok {
delete(mpBd, ch.Addr)
if cfg.IsDappFork(a.height, auty.AutonomyX, auty.ForkAutonomyDelRule) {
for _, b := range cur.Board.Boards {
if b == cur.PropChange.Changes[0].Addr {
mpBd[cur.Address] = struct{}{}
continue
}
mpBd[b] = struct{}{}
}
} else {
for _, b := range cur.Board.Boards {
mpBd[b] = struct{}{}
}
for _, ch := range cur.PropChange.Changes {
if ch.Cancel {
mpBd[ch.Addr] = struct{}{}
} else {
if _, ok := mpBd[ch.Addr]; ok {
delete(mpBd, ch.Addr)
}
}
}
}
if _, ok := mpBd[a.fromaddr]; !ok {
err = auty.ErrNoActiveBoard
alog.Error("votePropChange ", "addr", a.fromaddr, "this addr is not active board member",
......@@ -191,10 +215,23 @@ func (a *action) votePropChange(voteProb *auty.VoteProposalChange) (*types.Recei
// 更新投票记录
votes.Address = append(votes.Address, a.fromaddr)
if voteProb.Approve {
cur.VoteResult.ApproveVotes++
if cfg.IsDappFork(a.height, auty.AutonomyX, auty.ForkAutonomyDelRule) {
switch voteProb.Vote {
case auty.VoteOption_APPROVE:
cur.VoteResult.ApproveVotes++
case auty.VoteOption_OPPOSE:
cur.VoteResult.OpposeVotes++
case auty.VoteOption_QUIT:
cur.VoteResult.QuitVotes++
default:
return nil, errors.Wrapf(types.ErrInvalidParam, "vote option=%d", voteProb.Vote)
}
} else {
cur.VoteResult.OpposeVotes++
if voteProb.Approve {
cur.VoteResult.ApproveVotes++
} else {
cur.VoteResult.OpposeVotes++
}
}
var logs []*types.ReceiptLog
......@@ -319,6 +356,52 @@ func (a *action) getProposalChange(ID string) (*auty.AutonomyProposalChange, err
return cur, nil
}
//新的方案只允许替换board里面的成员,而且是本用户申请,不允许从revBoard恢复
func (a *action) replaceBoard(act *auty.ActiveBoard, change []*auty.Change) (*auty.ActiveBoard, error) {
//一个成员只允许替换一个新的
if len(change) > 1 {
return nil, errors.Wrapf(types.ErrInvalidParam, "only allow one addr to be replaced,change=%d", len(change))
}
//只允许替换,不允许恢复操作
if !change[0].Cancel || len(change[0].Addr) <= 0 {
return nil, errors.Wrapf(types.ErrInvalidParam, "cancel=%d not allow to addr=%s", change[0].Cancel, change[0].Addr)
}
mpBd := make(map[string]struct{})
mpRbd := make(map[string]struct{})
for _, b := range act.Boards {
mpBd[b] = struct{}{}
}
for _, b := range act.Revboards {
mpRbd[b] = struct{}{}
}
//发起者必须是董事会成员
if _, ok := mpBd[a.fromaddr]; !ok {
return nil, errors.Wrap(types.ErrNotAllow, "from addr should be in boards")
}
//待替换地址不能在board和revBoard里面
if _, ok := mpBd[change[0].Addr]; ok {
return nil, errors.Wrapf(types.ErrNotAllow, "new addr=%s in boards", change[0].Addr)
}
if _, ok := mpRbd[change[0].Addr]; ok {
return nil, errors.Wrapf(types.ErrNotAllow, "new addr=%s in rev boards", change[0].Addr)
}
//替换board
for i, k := range act.Boards {
if k == a.fromaddr {
act.Boards[i] = change[0].Addr
break
}
}
//当前地址追加到revBoards
act.Revboards = append(act.Revboards, a.fromaddr)
return act, nil
}
func (a *action) checkChangeable(act *auty.ActiveBoard, change []*auty.Change) (*auty.ActiveBoard, error) {
mpBd := make(map[string]struct{})
mpRbd := make(map[string]struct{})
......
......@@ -8,6 +8,7 @@ import (
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/types"
auty "github.com/33cn/plugin/plugin/dapp/autonomy/types"
"github.com/pkg/errors"
"github.com/33cn/chain33/common/address"
)
......@@ -217,11 +218,25 @@ func (a *action) votePropProject(voteProb *auty.VoteProposalProject) (*types.Rec
// 更新已经投票地址
votes.Address = append(votes.Address, a.fromaddr)
// 更新投票结果
if voteProb.Approve {
cur.BoardVoteRes.ApproveVotes++
if a.api.GetConfig().IsDappFork(a.height, auty.AutonomyX, auty.ForkAutonomyDelRule) {
switch voteProb.Vote {
case auty.VoteOption_APPROVE:
cur.BoardVoteRes.ApproveVotes++
case auty.VoteOption_OPPOSE:
cur.BoardVoteRes.OpposeVotes++
case auty.VoteOption_QUIT:
cur.BoardVoteRes.QuitVotes++
default:
return nil, errors.Wrapf(types.ErrInvalidParam, "vote option=%d", voteProb.Vote)
}
} else {
cur.BoardVoteRes.OpposeVotes++
if voteProb.Approve {
cur.BoardVoteRes.ApproveVotes++
} else {
cur.BoardVoteRes.OpposeVotes++
}
}
var logs []*types.ReceiptLog
......
......@@ -8,6 +8,7 @@ import (
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/types"
auty "github.com/33cn/plugin/plugin/dapp/autonomy/types"
"github.com/pkg/errors"
"github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/system/dapp"
......@@ -18,10 +19,23 @@ const (
minBoardApproveRatio = 50
// 最大董事会赞成率
maxBoardApproveRatio = 66
// 最小全体持票人否决率
minPubOpposeRatio = 33
// 最大全体持票人否决率
maxPubOpposeRatio = 50
//不能设置太低和太高,太低就容易作弊,太高则有可能很难达到
// 最小全体持票人参与率
minPubAttendRatio = 50
// 最大全体持票人参与率
maxPubAttendRatio = 80
// 最小全体持票人赞成率
minPubApproveRatio = 50
// 最大全体持票人赞成率
maxPubApproveRatio = 80
// 最小公示周期
minPublicPeriod int32 = 17280 * 7
// 最大公示周期
......@@ -36,6 +50,13 @@ const (
maxProposalAmount = 2000
)
func checkParaInvalid(param, min, max int64) bool {
if param > 0 && ((param > max) || param < min) {
return true
}
return false
}
func (a *action) propRule(prob *auty.ProposalRule) (*types.Receipt, error) {
cfg := a.api.GetConfig()
//如果全小于等于0,则说明该提案规则参数不正确
......@@ -44,11 +65,13 @@ func (a *action) propRule(prob *auty.ProposalRule) (*types.Receipt, error) {
alog.Error("propRule ", "ProposalRule RuleCfg invaild or have no modify param", prob.RuleCfg)
return nil, types.ErrInvalidParam
}
if (prob.RuleCfg.BoardApproveRatio > 0 && (prob.RuleCfg.BoardApproveRatio > maxBoardApproveRatio || prob.RuleCfg.BoardApproveRatio < minBoardApproveRatio)) ||
(prob.RuleCfg.PubOpposeRatio > 0 && (prob.RuleCfg.PubOpposeRatio > maxPubOpposeRatio || prob.RuleCfg.PubOpposeRatio < minPubOpposeRatio)) ||
(prob.RuleCfg.PublicPeriod > 0 && (prob.RuleCfg.PublicPeriod > maxPublicPeriod || prob.RuleCfg.PublicPeriod < minPublicPeriod)) ||
(prob.RuleCfg.LargeProjectAmount > 0 && (prob.RuleCfg.LargeProjectAmount > maxLargeProjectAmount*cfg.GetCoinPrecision() || prob.RuleCfg.LargeProjectAmount < minLargeProjectAmount*cfg.GetCoinPrecision())) ||
(prob.RuleCfg.ProposalAmount > 0 && (prob.RuleCfg.ProposalAmount > maxProposalAmount*cfg.GetCoinPrecision() || prob.RuleCfg.ProposalAmount < minProposalAmount*cfg.GetCoinPrecision())) {
if checkParaInvalid(int64(prob.RuleCfg.BoardApproveRatio), minBoardApproveRatio, maxBoardApproveRatio) ||
checkParaInvalid(int64(prob.RuleCfg.PubOpposeRatio), minPubOpposeRatio, maxPubOpposeRatio) ||
checkParaInvalid(int64(prob.RuleCfg.PublicPeriod), int64(minPublicPeriod), int64(maxPublicPeriod)) ||
checkParaInvalid(prob.RuleCfg.LargeProjectAmount, minLargeProjectAmount*cfg.GetCoinPrecision(), maxLargeProjectAmount*cfg.GetCoinPrecision()) ||
checkParaInvalid(prob.RuleCfg.ProposalAmount, minProposalAmount*cfg.GetCoinPrecision(), maxProposalAmount*cfg.GetCoinPrecision()) ||
checkParaInvalid(int64(prob.RuleCfg.PubAttendRatio), minPubAttendRatio, maxPubAttendRatio) ||
checkParaInvalid(int64(prob.RuleCfg.PubApproveRatio), minPubApproveRatio, maxPubApproveRatio) {
alog.Error("propRule RuleCfg invaild", "ruleCfg", prob.RuleCfg)
return nil, types.ErrInvalidParam
}
......@@ -230,10 +253,24 @@ func (a *action) votePropRule(voteProb *auty.VoteProposalRule) (*types.Receipt,
voteProb.ProposalID, "err", err)
return nil, err
}
if voteProb.Approve {
cur.VoteResult.ApproveVotes += vtCouts
cfg := a.api.GetConfig()
if cfg.IsDappFork(a.height, auty.AutonomyX, auty.ForkAutonomyDelRule) {
switch voteProb.Vote {
case auty.VoteOption_APPROVE:
cur.VoteResult.ApproveVotes += vtCouts
case auty.VoteOption_OPPOSE:
cur.VoteResult.OpposeVotes += vtCouts
case auty.VoteOption_QUIT:
cur.VoteResult.QuitVotes += vtCouts
default:
return nil, errors.Wrapf(types.ErrInvalidParam, "wrong vote value=%d", voteProb.Vote)
}
} else {
cur.VoteResult.OpposeVotes += vtCouts
if voteProb.Approve {
cur.VoteResult.ApproveVotes += vtCouts
} else {
cur.VoteResult.OpposeVotes += vtCouts
}
}
var logs []*types.ReceiptLog
......@@ -250,12 +287,20 @@ func (a *action) votePropRule(voteProb *auty.VoteProposalRule) (*types.Receipt,
kv = append(kv, receipt.KV...)
}
if cur.VoteResult.TotalVotes != 0 &&
cur.VoteResult.ApproveVotes+cur.VoteResult.OpposeVotes != 0 &&
float32(cur.VoteResult.ApproveVotes+cur.VoteResult.OpposeVotes)/float32(cur.VoteResult.TotalVotes) > float32(pubAttendRatio)/100.0 &&
float32(cur.VoteResult.ApproveVotes)/float32(cur.VoteResult.ApproveVotes+cur.VoteResult.OpposeVotes) > float32(pubApproveRatio)/100.0 {
cur.VoteResult.Pass = true
cur.PropRule.RealEndBlockHeight = a.height
if cfg.IsDappFork(a.height, auty.AutonomyX, auty.ForkAutonomyDelRule) {
if isApproved(cur.VoteResult.TotalVotes, cur.VoteResult.ApproveVotes, cur.VoteResult.OpposeVotes, cur.VoteResult.QuitVotes,
cur.CurRule.PubAttendRatio, cur.CurRule.PubApproveRatio) {
cur.VoteResult.Pass = true
cur.PropRule.RealEndBlockHeight = a.height
}
} else {
if cur.VoteResult.TotalVotes != 0 &&
cur.VoteResult.ApproveVotes+cur.VoteResult.OpposeVotes != 0 &&
float32(cur.VoteResult.ApproveVotes+cur.VoteResult.OpposeVotes)/float32(cur.VoteResult.TotalVotes) > float32(pubAttendRatio)/100.0 &&
float32(cur.VoteResult.ApproveVotes)/float32(cur.VoteResult.ApproveVotes+cur.VoteResult.OpposeVotes) > float32(pubApproveRatio)/100.0 {
cur.VoteResult.Pass = true
cur.PropRule.RealEndBlockHeight = a.height
}
}
key := propRuleID(voteProb.ProposalID)
......@@ -320,11 +365,16 @@ func (a *action) tmintPropRule(tmintProb *auty.TerminateProposalRule) (*types.Re
cur.VoteResult.TotalVotes = vtCouts
}
if float32(cur.VoteResult.ApproveVotes+cur.VoteResult.OpposeVotes)/float32(cur.VoteResult.TotalVotes) > float32(pubAttendRatio)/100.0 &&
float32(cur.VoteResult.ApproveVotes)/float32(cur.VoteResult.ApproveVotes+cur.VoteResult.OpposeVotes) > float32(pubApproveRatio)/100.0 {
cur.VoteResult.Pass = true
if a.api.GetConfig().IsDappFork(a.height, auty.AutonomyX, auty.ForkAutonomyDelRule) {
cur.VoteResult.Pass = isApproved(cur.VoteResult.TotalVotes, cur.VoteResult.ApproveVotes, cur.VoteResult.OpposeVotes, cur.VoteResult.QuitVotes,
cur.CurRule.PubAttendRatio, cur.CurRule.PubApproveRatio)
} else {
cur.VoteResult.Pass = false
if float32(cur.VoteResult.ApproveVotes+cur.VoteResult.OpposeVotes)/float32(cur.VoteResult.TotalVotes) > float32(pubAttendRatio)/100.0 &&
float32(cur.VoteResult.ApproveVotes)/float32(cur.VoteResult.ApproveVotes+cur.VoteResult.OpposeVotes) > float32(pubApproveRatio)/100.0 {
cur.VoteResult.Pass = true
} else {
cur.VoteResult.Pass = false
}
}
cur.PropRule.RealEndBlockHeight = a.height
......@@ -466,5 +516,12 @@ func upgradeRule(cur, modify *auty.RuleConfig) *auty.RuleConfig {
if modify.PublicPeriod > 0 {
new.PublicPeriod = modify.PublicPeriod
}
if modify.PubAttendRatio > 0 {
new.PubAttendRatio = modify.PubAttendRatio
}
if modify.PubApproveRatio > 0 {
new.PubApproveRatio = modify.PubApproveRatio
}
return &new
}
......@@ -25,6 +25,16 @@ message AutonomyProposalBoard {
string proposalID = 9;
}
enum BoardUpdate {
INV = 0;
//新增
ADD = 1;
//剔除
DEL = 2;
//整体替换
WHOLE = 3;
}
// action
message ProposalBoard {
// 提案时间
......@@ -41,6 +51,10 @@ message ProposalBoard {
int64 startBlockHeight = 6; // 提案开始投票高度
int64 endBlockHeight = 7; // 提案结束投票高度
int64 realEndBlockHeight = 8; // 实际提案结束投票高度
//代替update,并扩展
BoardUpdate boardUpdate = 9;
}
message RevokeProposalBoard {
......@@ -50,7 +64,10 @@ message RevokeProposalBoard {
message VoteProposalBoard {
string proposalID = 1;
bool approve = 2;
//真正投票地址
repeated string originAddr = 3;
//代替approve,并增加了弃权选项
VoteOption voteOption = 4;
}
message TerminateProposalBoard {
......
......@@ -54,6 +54,7 @@ message RevokeProposalChange {
message VoteProposalChange {
string proposalID = 1;
bool approve = 2;
VoteOption vote = 3;
}
message TerminateProposalChange {
......
......@@ -16,6 +16,8 @@ message VoteResult {
int32 opposeVotes = 3;
// 是否通过
bool pass = 4;
//弃权票
int32 quitVotes = 5;
}
message PublicVote {
......@@ -44,6 +46,22 @@ message RuleConfig {
int64 largeProjectAmount = 4;
// 重大项目公示时间(以区块数为单位)
int32 publicPeriod = 5;
// 全体持票人参与率
int32 pubAttendRatio = 6;
// 全体持票人赞成率
int32 pubApproveRatio = 7;
}
//三种投票选项
enum VoteOption {
INVALID = 0;
//支持
APPROVE = 1;
//反对
OPPOSE = 2;
//弃权
QUIT = 3;
}
message ActiveBoard {
......
......@@ -59,6 +59,7 @@ message RevokeProposalProject {
message VoteProposalProject {
string proposalID = 1;
bool approve = 2;
VoteOption vote = 3;
}
message PubVoteProposalProject {
......
......@@ -44,6 +44,7 @@ message VoteProposalRule {
string proposalID = 1;
bool approve = 2;
repeated string originAddr = 3;
VoteOption vote = 4;
}
message TerminateProposalRule {
......
......@@ -12,6 +12,11 @@ import (
var name string
var (
//ForkAutonomyDelRule fork for delete boards member rules
ForkAutonomyDelRule = "ForkAutonomyDelRule"
)
func init() {
name = AutonomyX
types.AllowUserExec = append(types.AllowUserExec, []byte(name))
......@@ -22,6 +27,7 @@ func init() {
//InitFork ...
func InitFork(cfg *types.Chain33Config) {
cfg.RegisterDappFork(AutonomyX, "Enable", 0)
cfg.RegisterDappFork(AutonomyX, ForkAutonomyDelRule, 9500000)
}
//InitExecutor ...
......
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