Commit 17a57671 authored by liuyuhang's avatar liuyuhang Committed by 33cn

add test and modify some logic

parent 5b29261b
......@@ -174,7 +174,7 @@ func (a *action) votePropBoard(voteProb *auty.VoteProposalBoard) (*types.Receipt
}
// 检查是否已经参与投票
votes, err := a.checkVotesRecord(voteProb.ProposalID)
votes, err := a.checkVotesRecord(votesRecord(voteProb.ProposalID))
if err != nil {
alog.Error("votePropBoard ", "addr", a.fromaddr, "execaddr", a.execaddr, "checkVotesRecord failed",
voteProb.ProposalID, "err", err)
......@@ -205,13 +205,8 @@ func (a *action) votePropBoard(voteProb *auty.VoteProposalBoard) (*types.Receipt
var logs []*types.ReceiptLog
var kv []*types.KeyValue
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 cur.Status == auty.AutonomyStatusProposalBoard {
receipt, err := a.coinsAccount.ExecTransferFrozen(cur.Address, autonomyAddr, a.execaddr, cur.CurRule.ProposalAmount)
if err != nil {
alog.Error("votePropBoard ", "addr", cur.Address, "execaddr", a.execaddr, "ExecTransferFrozen amount fail", err)
......@@ -221,6 +216,14 @@ 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
}
key := propBoardID(voteProb.ProposalID)
cur.Status = auty.AutonomyStatusVotePropBoard
if cur.VoteResult.Pass {
......@@ -229,7 +232,7 @@ func (a *action) votePropBoard(voteProb *auty.VoteProposalBoard) (*types.Receipt
kv = append(kv, &types.KeyValue{Key: key, Value: types.Encode(cur)})
// 更新VotesRecord
kv = append(kv, &types.KeyValue{Key: VotesRecord(voteProb.ProposalID), Value: types.Encode(votes)})
kv = append(kv, &types.KeyValue{Key: votesRecord(voteProb.ProposalID), Value: types.Encode(votes)})
// 更新当前具有权利的董事会成员
if cur.VoteResult.Pass {
......@@ -291,13 +294,17 @@ func (a *action) tmintPropBoard(tmintProb *auty.TerminateProposalBoard) (*types.
var logs []*types.ReceiptLog
var kv []*types.KeyValue
receipt, err := a.coinsAccount.ExecTransferFrozen(cur.Address, autonomyAddr, a.execaddr, cur.CurRule.ProposalAmount)
if err != nil {
alog.Error("votePropBoard ", "addr", a.fromaddr, "execaddr", a.execaddr, "ExecTransferFrozen amount fail", err)
return nil, err
// 未进行投票情况下,符合提案关闭的也需要扣除提案费用
if cur.Status == auty.AutonomyStatusProposalBoard {
receipt, err := a.coinsAccount.ExecTransferFrozen(cur.Address, autonomyAddr, a.execaddr, cur.CurRule.ProposalAmount)
if err != nil {
alog.Error("votePropBoard ", "addr", a.fromaddr, "execaddr", a.execaddr, "ExecTransferFrozen amount fail", err)
return nil, err
}
logs = append(logs, receipt.Logs...)
kv = append(kv, receipt.KV...)
}
logs = append(logs, receipt.Logs...)
kv = append(kv, receipt.KV...)
cur.Status = auty.AutonomyStatusTmintPropBoard
......@@ -369,9 +376,9 @@ func (a *action) getActiveRule() (*auty.RuleConfig, error) {
return rule, nil
}
func (a *action) checkVotesRecord(ID string) (*auty.VotesRecord, error) {
func (a *action) checkVotesRecord(key []byte) (*auty.VotesRecord, error) {
var votes auty.VotesRecord
value, err := a.db.Get(VotesRecord(ID))
value, err := a.db.Get(key)
if err == nil {
err = types.Decode(value, &votes)
if err != nil {
......
......@@ -17,7 +17,7 @@ var (
localPrefix = "LOCDB" + auty.AutonomyX + "-"
)
func VotesRecord(txHash string) []byte {
func votesRecord(txHash string) []byte {
return []byte(fmt.Sprintf("%s%s", votesRecordPrefix, txHash))
}
......@@ -25,6 +25,7 @@ var (
// board
boardPrefix = idPrefix + "board" + "-"
localBoardPrefix = localPrefix + "board" + "-"
boardVotesRecordPrefix = boardPrefix + "vote" + "-"
)
func activeBoardID() []byte {
......@@ -35,6 +36,10 @@ func propBoardID(txHash string) []byte {
return []byte(fmt.Sprintf("%s%s", boardPrefix, txHash))
}
func boardVotesRecord(txHash string) []byte {
return []byte(fmt.Sprintf("%s%s", boardVotesRecordPrefix, txHash))
}
func calcBoardKey4StatusHeight(status int32, heightindex string) []byte {
key := fmt.Sprintf(localBoardPrefix + "%d-" +"%s", status, heightindex)
return []byte(key)
......
......@@ -28,7 +28,11 @@ import (
// testLargeProjectAmount int64 = 1
//)
func InitProject(stateDB dbm.KV) {
const (
testProjectAmount int64 = types.Coin * 100 // 工程需要资金
)
func InitBoard(stateDB dbm.KV) {
// add active board
board := &auty.ProposalBoard{
Year: 2019,
......@@ -42,6 +46,18 @@ func InitProject(stateDB dbm.KV) {
stateDB.Set(activeBoardID(), types.Encode(board))
}
func InitRule(stateDB dbm.KV) {
// add active rule
rule := &auty.RuleConfig{
BoardAttendRatio: boardAttendRatio,
BoardApproveRatio: boardApproveRatio,
PubOpposeRatio: pubOpposeRatio,
ProposalAmount: proposalAmount,
LargeProjectAmount: types.Coin *100,
}
stateDB.Set(activeRuleID(), types.Encode(rule))
}
func TestPropProject(t *testing.T) {
env, exec, _, _ := InitEnv()
......@@ -92,7 +108,7 @@ func TestPropProject(t *testing.T) {
func TestRevokeProposalProject(t *testing.T) {
env, exec, stateDB, kvdb := InitEnv()
InitProject(stateDB)
InitBoard(stateDB)
// PropProject
testPropProject(t, env, exec, stateDB, kvdb, true)
//RevokeProposalProject
......@@ -101,16 +117,33 @@ func TestRevokeProposalProject(t *testing.T) {
func TestVoteProposalProject(t *testing.T) {
env, exec, stateDB, kvdb := InitEnv()
InitProject(stateDB)
InitBoard(stateDB)
// PropProject
testPropProject(t, env, exec, stateDB, kvdb, true)
//voteProposalProject
voteProposalProject(t, env, exec, stateDB, kvdb, true)
// check
checkVoteProposalProjectResult(t, stateDB, env.txHash)
}
func TestPubVoteProposalProject(t *testing.T) {
env, exec, stateDB, kvdb := InitEnv()
InitBoard(stateDB)
InitRule(stateDB)
// PropProject
testPropProject(t, env, exec, stateDB, kvdb, true)
// voteProposalProject
voteProposalProject(t, env, exec, stateDB, kvdb, true)
// pubVoteProposalProject
pubVoteProposalProject(t, env, exec, stateDB, kvdb, true) // 未通过全体持票人投票
// terminate
// check
checkPubVoteProposalProjectResult(t, stateDB, env.txHash)
}
func TestTerminateProposalProject(t *testing.T) {
env, exec, stateDB, kvdb := InitEnv()
InitProject(stateDB)
InitBoard(stateDB)
// PropProject
testPropProject(t, env, exec, stateDB, kvdb, true)
//terminateProposalProject
......@@ -122,7 +155,7 @@ func testPropProject(t *testing.T, env *execEnv, exec drivers.Driver, stateDB db
Year: 2019,
Month: 7,
Day: 10,
Amount: types.Coin * 100,
Amount: testProjectAmount,
ToAddr: AddrD,
StartBlockHeight: env.blockHeight + 5,
EndBlockHeight: env.blockHeight + 10,
......@@ -261,9 +294,9 @@ func voteProposalProject(t *testing.T, env *execEnv, exec drivers.Driver, stateD
}
records := []record{
{PrivKeyA, false},
{PrivKeyB, false},
{PrivKeyB, true},
{PrivKeyC, true},
{PrivKeyD, true},
//{PrivKeyD, true},
}
for _, record := range records {
......@@ -306,6 +339,20 @@ func voteProposalProject(t *testing.T, env *execEnv, exec drivers.Driver, stateD
api.On("StoreGet", mock.Anything).Return(&types.StoreReplyValue{Values:values}, nil).Once()
exec.SetAPI(api)
}
}
func voteProposalProjectTx(parm *auty.VoteProposalProject) (*types.Transaction, error) {
if parm == nil {
return nil, types.ErrInvalidParam
}
val := &auty.AutonomyAction{
Ty: auty.AutonomyActionVotePropProject,
Value: &auty.AutonomyAction_VotePropProject{VotePropProject: parm},
}
return types.CreateFormatTx(types.ExecName(auty.AutonomyX), types.Encode(val))
}
func checkVoteProposalProjectResult(t *testing.T, stateDB dbm.KV, proposalID string) {
// check
// balance
accCoin := account.NewCoinsAccount()
......@@ -313,7 +360,7 @@ func voteProposalProject(t *testing.T, env *execEnv, exec drivers.Driver, stateD
account := accCoin.LoadExecAccount(AddrA, address.ExecAddress(auty.AutonomyX))
require.Equal(t, int64(0), account.Frozen)
account = accCoin.LoadExecAccount(autonomyAddr, address.ExecAddress(auty.AutonomyX))
require.Equal(t, int64(proposalAmount), account.Balance)
require.Equal(t, int64(proposalAmount) - testProjectAmount, account.Balance)
// status
value, err := stateDB.Get(propProjectID(proposalID))
require.NoError(t, err)
......@@ -322,23 +369,114 @@ func voteProposalProject(t *testing.T, env *execEnv, exec drivers.Driver, stateD
require.NoError(t, err)
require.Equal(t, int32(auty.AutonomyStatusTmintPropProject), cur.Status)
require.Equal(t, AddrA, cur.Address)
//require.Equal(t, true, cur.VoteResult.Pass)
// check Project
au := &Autonomy{
drivers.DriverBase{},
}
func pubVoteProposalProject(t *testing.T, env *execEnv, exec drivers.Driver, stateDB dbm.KV, kvdb dbm.KVDB, save bool) {
api := new(apimock.QueueProtocolAPI)
api.On("StoreList", mock.Anything).Return(&types.StoreListReply{}, nil)
api.On("GetLastHeader", mock.Anything).Return(&types.Header{StateHash: []byte("")}, nil)
hear := &types.Header{StateHash: []byte("")}
api.On("GetHeaders", mock.Anything).
Return(&types.Headers{
Items:[]*types.Header{hear}}, nil)
acc := &types.Account{
Currency: 0,
Balance: total*4,
}
val := types.Encode(acc)
values := [][]byte{val}
api.On("StoreGet", mock.Anything).Return(&types.StoreReplyValue{Values:values}, nil).Once()
acc = &types.Account{
Currency: 0,
Balance: total,
}
val1 := types.Encode(acc)
values1 := [][]byte{val1}
api.On("StoreGet", mock.Anything).Return(&types.StoreReplyValue{Values:values1}, nil).Once()
exec.SetAPI(api)
proposalID := env.txHash
// 4人参与投票,3人赞成票,1人反对票
type record struct {
priv string
appr bool
}
records := []record{
{PrivKeyA, true},
{PrivKeyB, false},
{PrivKeyC, true},
//{PrivKeyD, true},
}
for _, record := range records {
opt := &auty.PubVoteProposalProject{
ProposalID:proposalID,
Oppose: record.appr,
}
tx, err := pubVoteProposalProjectTx(opt)
require.NoError(t, err)
tx, err = signTx(tx, record.priv)
require.NoError(t, err)
// 设定当前高度为投票高度
exec.SetEnv(env.startHeight, env.blockTime, env.difficulty)
receipt, err := exec.Exec(tx, int(1))
require.NoError(t, err)
require.NotNil(t, receipt)
if save {
for _, kv := range receipt.KV {
stateDB.Set(kv.Key, kv.Value)
}
}
receiptData := &types.ReceiptData{Ty: receipt.Ty, Logs: receipt.Logs}
set, err := exec.ExecLocal(tx, receiptData, int(1))
require.NoError(t, err)
require.NotNil(t, set)
if save {
for _, kv := range set.KV {
kvdb.Set(kv.Key, kv.Value)
}
}
// 每次需要重新设置
acc := &types.Account{
Currency: 0,
Balance: total,
}
val := types.Encode(acc)
values := [][]byte{val}
api.On("StoreGet", mock.Anything).Return(&types.StoreReplyValue{Values:values}, nil).Once()
exec.SetAPI(api)
}
au.SetStateDB(stateDB)
au.SetLocalDB(kvdb)
//action := newAction(au, &types.Transaction{}, 0)
}
func voteProposalProjectTx(parm *auty.VoteProposalProject) (*types.Transaction, error) {
func checkPubVoteProposalProjectResult(t *testing.T, stateDB dbm.KV, proposalID string) {
// check
// balance
accCoin := account.NewCoinsAccount()
accCoin.SetDB(stateDB)
account := accCoin.LoadExecAccount(AddrA, address.ExecAddress(auty.AutonomyX))
require.Equal(t, int64(0), account.Frozen)
account = accCoin.LoadExecAccount(autonomyAddr, address.ExecAddress(auty.AutonomyX))
require.Equal(t, int64(proposalAmount), account.Balance)
// status
value, err := stateDB.Get(propProjectID(proposalID))
require.NoError(t, err)
cur := &auty.AutonomyProposalProject{}
err = types.Decode(value, cur)
require.NoError(t, err)
require.Equal(t, int32(auty.AutonomyStatusTmintPropProject), cur.Status)
require.Equal(t, AddrA, cur.Address)
}
func pubVoteProposalProjectTx(parm *auty.PubVoteProposalProject) (*types.Transaction, error) {
if parm == nil {
return nil, types.ErrInvalidParam
}
val := &auty.AutonomyAction{
Ty: auty.AutonomyActionVotePropProject,
Value: &auty.AutonomyAction_VotePropProject{VotePropProject: parm},
Ty: auty.AutonomyActionPubVotePropProject,
Value: &auty.AutonomyAction_PubVotePropProject{PubVotePropProject: parm},
}
return types.CreateFormatTx(types.ExecName(auty.AutonomyX), types.Encode(val))
}
......
......@@ -143,7 +143,7 @@ func (a *action) votePropRule(voteProb *auty.VoteProposalRule) (*types.Receipt,
}
// 检查是否已经参与投票
votes, err := a.checkVotesRecord(voteProb.ProposalID)
votes, err := a.checkVotesRecord(votesRecord(voteProb.ProposalID))
if err != nil {
alog.Error("votePropRule ", "addr", a.fromaddr, "execaddr", a.execaddr, "checkVotesRecord failed",
voteProb.ProposalID, "err", err)
......@@ -175,13 +175,8 @@ func (a *action) votePropRule(voteProb *auty.VoteProposalRule) (*types.Receipt,
var logs []*types.ReceiptLog
var kv []*types.KeyValue
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 cur.Status == auty.AutonomyStatusProposalRule {
receipt, err := a.coinsAccount.ExecTransferFrozen(cur.Address, autonomyAddr, a.execaddr, cur.Rule.ProposalAmount)
if err != nil {
alog.Error("votePropRule ", "addr", cur.Address, "execaddr", a.execaddr, "ExecTransferFrozen amount fail", err)
......@@ -191,6 +186,14 @@ 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
}
key := propRuleID(voteProb.ProposalID)
cur.Status = auty.AutonomyStatusVotePropRule
if cur.VoteResult.Pass {
......@@ -199,7 +202,7 @@ func (a *action) votePropRule(voteProb *auty.VoteProposalRule) (*types.Receipt,
kv = append(kv, &types.KeyValue{Key: key, Value: types.Encode(cur)})
// 更新VotesRecord
kv = append(kv, &types.KeyValue{Key: VotesRecord(voteProb.ProposalID), Value: types.Encode(votes)})
kv = append(kv, &types.KeyValue{Key: votesRecord(voteProb.ProposalID), Value: types.Encode(votes)})
// 更新系统规则
if cur.VoteResult.Pass {
......@@ -228,7 +231,8 @@ func (a *action) tmintPropRule(tmintProb *auty.TerminateProposalRule) (*types.Re
pre := copyAutonomyProposalRule(cur)
// 检查当前状态
if cur.Status == auty.AutonomyStatusTmintPropRule {
if cur.Status == auty.AutonomyStatusTmintPropRule ||
cur.Status == auty.AutonomyStatusRvkPropRule {
err := auty.ErrProposalStatus
alog.Error("tmintPropRule ", "addr", a.fromaddr, "status", cur.Status, "status is not match",
tmintProb.ProposalID, "err", err)
......@@ -263,13 +267,18 @@ func (a *action) tmintPropRule(tmintProb *auty.TerminateProposalRule) (*types.Re
var logs []*types.ReceiptLog
var kv []*types.KeyValue
receipt, err := a.coinsAccount.ExecTransferFrozen(cur.Address, autonomyAddr, a.execaddr, cur.Rule.ProposalAmount)
if err != nil {
alog.Error("votePropRule ", "addr", a.fromaddr, "execaddr", a.execaddr, "ExecTransferFrozen amount fail", err)
return nil, err
// 未进行投票情况下,符合提案关闭的也需要扣除提案费用
if cur.Status == auty.AutonomyStatusProposalRule {
receipt, err := a.coinsAccount.ExecTransferFrozen(cur.Address, autonomyAddr, a.execaddr, cur.Rule.ProposalAmount)
if err != nil {
alog.Error("votePropRule ", "addr", a.fromaddr, "execaddr", a.execaddr, "ExecTransferFrozen amount fail", err)
return nil, err
}
logs = append(logs, receipt.Logs...)
kv = append(kv, receipt.KV...)
}
logs = append(logs, receipt.Logs...)
kv = append(kv, receipt.KV...)
cur.Status = auty.AutonomyStatusTmintPropRule
......
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