Skip to content

Commit

Permalink
add min vote min requirement and force validator vote only on specifi…
Browse files Browse the repository at this point in the history
…c proposal
  • Loading branch information
ZhimaoL committed May 10, 2018
1 parent 94b0229 commit 1922314
Show file tree
Hide file tree
Showing 11 changed files with 185 additions and 72 deletions.
4 changes: 3 additions & 1 deletion param/holder.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,18 +108,20 @@ func (ph ParamHolder) InitParam(ctx sdk.Context) error {
return ErrParamHolderGenesisFailed().TraceCause(err, "")
}

// TODO need to init other proposal params
proposalParam := &ProposalParam{
ContentCensorshipDecideHr: int64(24 * 7),
ContentCensorshipPassRatio: sdk.NewRat(50, 100),
ContentCensorshipPassVotes: types.NewCoin(10000 * types.Decimals),
ContentCensorshipMinDeposit: types.NewCoin(100 * types.Decimals),

ChangeParamDecideHr: int64(24 * 7),
ChangeParamPassRatio: sdk.NewRat(70, 100),
ChangeParamPassVotes: types.NewCoin(1000000 * types.Decimals),
ChangeParamMinDeposit: types.NewCoin(100000 * types.Decimals),

ProtocolUpgradeDecideHr: int64(24 * 7),
ProtocolUpgradePassRatio: sdk.NewRat(80, 100),
ProtocolUpgradePassVotes: types.NewCoin(10000000 * types.Decimals),
ProtocolUpgradeMinDeposit: types.NewCoin(1000000 * types.Decimals),

NextProposalID: int64(0),
Expand Down
3 changes: 3 additions & 0 deletions param/param.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,15 @@ type ProposalParam struct {
ContentCensorshipDecideHr int64 `json:"content_censorship_decide_hr"`
ContentCensorshipMinDeposit types.Coin `json:"content_censorship_min_deposit"`
ContentCensorshipPassRatio sdk.Rat `json:"content_censorship_pass_ratio"`
ContentCensorshipPassVotes types.Coin `json:"content_censorship_pass_votes"`
ChangeParamDecideHr int64 `json:"change_param_decide_hr"`
ChangeParamMinDeposit types.Coin `json:"change_param_min_deposit"`
ChangeParamPassRatio sdk.Rat `json:"change_param_pass_ratio"`
ChangeParamPassVotes types.Coin `json:"change_param_pass_votes"`
ProtocolUpgradeDecideHr int64 `json:"protocol_upgrade_decide_hr"`
ProtocolUpgradeMinDeposit types.Coin `json:"protocol_upgrade_min_deposit"`
ProtocolUpgradePassRatio sdk.Rat `json:"protocol_upgrade_pass_ratio"`
ProtocolUpgradePassVotes types.Coin `json:"protocol_upgrade_pass_votes"`
}

type DeveloperParam struct {
Expand Down
27 changes: 17 additions & 10 deletions test/proposal/proposal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,28 @@ func TestForceValidatorVote(t *testing.T) {
baseTime := time.Now().Unix() + 100
lb := test.NewTestLinoBlockchain(t, test.DefaultNumOfVal)

totalLNO := types.LNO("1000000000")
depositLNO := types.LNO("3000000")

totalCoin, _ := types.LinoToCoin(totalLNO)
depositCoin, _ := types.LinoToCoin(depositLNO)

test.CreateAccount(t, accountName, lb, 0,
crypto.GenPrivKeyEd25519(), accountTransactionPriv, accountPostPriv, "1000000")
crypto.GenPrivKeyEd25519(), accountTransactionPriv, accountPostPriv, totalLNO)

test.CreateAccount(t, accountName2, lb, 1,
crypto.GenPrivKeyEd25519(), accountTransactionPriv2, accountPostPriv2, "1000000")
crypto.GenPrivKeyEd25519(), accountTransactionPriv2, accountPostPriv2, totalLNO)

voteDepositMsg := vote.NewVoterDepositMsg(accountName, types.LNO("3000"))
voteDepositMsg := vote.NewVoterDepositMsg(accountName, depositLNO)
test.SignCheckDeliver(t, lb, voteDepositMsg, 0, true, accountTransactionPriv, baseTime)

valDepositMsg := val.NewValidatorDepositMsg(accountName, types.LNO("3000"), validatorPriv.PubKey(), "")
valDepositMsg := val.NewValidatorDepositMsg(accountName, depositLNO, validatorPriv.PubKey(), "")
test.SignCheckDeliver(t, lb, valDepositMsg, 1, true, accountTransactionPriv, baseTime)

voteDepositMsg2 := vote.NewVoterDepositMsg(accountName2, types.LNO("3000"))
voteDepositMsg2 := vote.NewVoterDepositMsg(accountName2, depositLNO)
test.SignCheckDeliver(t, lb, voteDepositMsg2, 0, true, accountTransactionPriv2, baseTime)

valDepositMsg2 := val.NewValidatorDepositMsg(accountName2, types.LNO("3000"), validatorPriv2.PubKey(), "")
valDepositMsg2 := val.NewValidatorDepositMsg(accountName2, depositLNO, validatorPriv2.PubKey(), "")
test.SignCheckDeliver(t, lb, valDepositMsg2, 1, true, accountTransactionPriv2, baseTime)

test.CheckOncallValidatorList(t, accountName, true, lb)
Expand All @@ -59,8 +65,9 @@ func TestForceValidatorVote(t *testing.T) {
changeAllocationMsg := proposal.NewChangeGlobalAllocationParamMsg(accountName, desc)
test.SignCheckDeliver(t, lb, changeAllocationMsg, 2, true, accountTransactionPriv, baseTime)

test.CheckBalance(t, accountName, lb, types.NewCoin(894000*types.Decimals))
test.CheckBalance(t, accountName2, lb, types.NewCoin(994000*types.Decimals))
accBalance := totalCoin.Minus(depositCoin).Minus(depositCoin)
test.CheckBalance(t, accountName, lb, accBalance.Minus(test.ChangeParamMinDeposit))
test.CheckBalance(t, accountName2, lb, accBalance)

test.SimulateOneBlock(lb, baseTime)
// let validator 1 vote and validator 2 not vote.
Expand All @@ -72,6 +79,6 @@ func TestForceValidatorVote(t *testing.T) {
test.CheckGlobalAllocation(t, lb, desc)

// check validator 2 has been punished for not voting
test.CheckValidatorDeposit(t, accountName, lb, types.NewCoin(3000*types.Decimals))
test.CheckValidatorDeposit(t, accountName2, lb, types.NewCoin(3000*types.Decimals).Minus(test.PenaltyMissVote))
test.CheckValidatorDeposit(t, accountName, lb, depositCoin)
test.CheckValidatorDeposit(t, accountName2, lb, depositCoin.Minus(test.PenaltyMissVote))
}
16 changes: 9 additions & 7 deletions test/test_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,15 @@ var (
GenesisTotalLino types.LNO = "10000000000"
LNOPerValidator types.LNO = "100000000"

PenaltyMissVote types.Coin = types.NewCoin(200 * types.Decimals)
ProposalDecideHr int64 = 24 * 7
ParamChangeHr int64 = 24
CoinReturnIntervalHr int64 = 24 * 7
CoinReturnTimes int64 = 7
ConsumptionFrictionRate sdk.Rat = sdk.NewRat(5, 100)
ConsumptionFreezingPeriodHr int64 = 24 * 7
PenaltyMissVote types.Coin = types.NewCoin(200 * types.Decimals)
ChangeParamMinDeposit types.Coin = types.NewCoin(100000 * types.Decimals)

ProposalDecideHr int64 = 24 * 7
ParamChangeHr int64 = 24
CoinReturnIntervalHr int64 = 24 * 7
CoinReturnTimes int64 = 7
ConsumptionFrictionRate sdk.Rat = sdk.NewRat(5, 100)
ConsumptionFreezingPeriodHr int64 = 24 * 7
)

func loggerAndDB() (log.Logger, dbm.DB) {
Expand Down
1 change: 1 addition & 0 deletions tx/global/model/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func NewGlobalStorage(key sdk.StoreKey) GlobalStorage {
cdc.RegisterConcrete(param.ValidatorParam{}, "param/validator", nil)
cdc.RegisterConcrete(param.CoinDayParam{}, "param/coinDay", nil)
cdc.RegisterConcrete(param.BandwidthParam{}, "param/bandwidth", nil)
cdc.RegisterConcrete(param.AccountParam{}, "param/account", nil)

wire.RegisterCrypto(cdc)
return GlobalStorage{
Expand Down
25 changes: 14 additions & 11 deletions tx/proposal/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ type DecideProposalEvent struct {

func (dpe DecideProposalEvent) Execute(
ctx sdk.Context, voteManager vote.VoteManager, valManager val.ValidatorManager,
am acc.AccountManager, proposalManager ProposalManager, postManager post.PostManager, gm global.GlobalManager) sdk.Error {
// get the proposal ID we are going to decide
curID, err := proposalManager.GetCurrentProposal(ctx)
if err != nil {
return err
am acc.AccountManager, proposalManager ProposalManager, postManager post.PostManager,
gm global.GlobalManager) sdk.Error {
// check it is ongoing proposal
if !proposalManager.IsOngoingProposal(ctx, dpe.ProposalID) {
return ErrOngoingProposalNotFound()
}

// get all oncall validators (make sure they voted on certain type of proposal)
Expand All @@ -31,7 +31,8 @@ func (dpe DecideProposalEvent) Execute(
}

// calculate voting result
votingRes, err := voteManager.CalculateVotingResult(ctx, curID, lst.OncallValidators)
votingRes, err := voteManager.CalculateVotingResult(
ctx, dpe.ProposalID, dpe.ProposalType, lst.OncallValidators)
if err != nil {
return err
}
Expand Down Expand Up @@ -62,23 +63,24 @@ func (dpe DecideProposalEvent) Execute(
// execute proposal
switch dpe.ProposalType {
case types.ChangeParam:
if err := dpe.ExecuteChangeParam(ctx, curID, proposalManager, gm); err != nil {
if err := dpe.ExecuteChangeParam(ctx, dpe.ProposalID, proposalManager, gm); err != nil {
return err
}
case types.ContentCensorship:
if err := dpe.ExecuteContentCensorship(ctx, curID, proposalManager, postManager); err != nil {
if err := dpe.ExecuteContentCensorship(ctx, dpe.ProposalID, proposalManager, postManager); err != nil {
return err
}
case types.ProtocolUpgrade:
if err := dpe.ExecuteProtocolUpgrade(ctx, curID, proposalManager); err != nil {
if err := dpe.ExecuteProtocolUpgrade(ctx, dpe.ProposalID, proposalManager); err != nil {
return err
}
}
return nil
}

func (dpe DecideProposalEvent) ExecuteChangeParam(
ctx sdk.Context, curID types.ProposalKey, proposalManager ProposalManager, gm global.GlobalManager) sdk.Error {
ctx sdk.Context, curID types.ProposalKey, proposalManager ProposalManager,
gm global.GlobalManager) sdk.Error {
event, err := proposalManager.CreateParamChangeEvent(ctx, curID)
if err != nil {
return err
Expand All @@ -90,7 +92,8 @@ func (dpe DecideProposalEvent) ExecuteChangeParam(
}

func (dpe DecideProposalEvent) ExecuteContentCensorship(
ctx sdk.Context, curID types.ProposalKey, proposalManager ProposalManager, postManager post.PostManager) sdk.Error {
ctx sdk.Context, curID types.ProposalKey, proposalManager ProposalManager,
postManager post.PostManager) sdk.Error {
_, err := proposalManager.GetPermLink(ctx, curID)
if err != nil {
return err
Expand Down
7 changes: 4 additions & 3 deletions tx/proposal/event_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@ func TestDecideProposal(t *testing.T) {
user3 := createTestAccount(ctx, am, "user3")
user4 := createTestAccount(ctx, am, "user4")

voteParam, _ := pm.paramHolder.GetVoteParam(ctx)
proposalParam, _ := pm.paramHolder.GetProposalParam(ctx)

c1, c2, c3, c4 := voteParam.VoterMinDeposit.Plus(types.NewCoin(20)), voteParam.VoterMinDeposit.Plus(types.NewCoin(30)),
voteParam.VoterMinDeposit.Plus(types.NewCoin(50)), voteParam.VoterMinDeposit.Plus(types.NewCoin(10))
c1, c2, c3, c4 := proposalParam.ChangeParamPassVotes.Plus(types.NewCoin(20)), proposalParam.ChangeParamPassVotes.Plus(types.NewCoin(30)),
proposalParam.ChangeParamPassVotes.Plus(types.NewCoin(50)), proposalParam.ChangeParamPassVotes.Plus(types.NewCoin(10))
voteManager.AddVoter(ctx, user1, c1)
voteManager.AddVoter(ctx, user2, c2)
voteManager.AddVoter(ctx, user3, c3)
voteManager.AddVoter(ctx, user4, c4)

param1 := param.GlobalAllocationParam{
InfraAllocation: sdk.NewRat(50, 100),
}
Expand Down
15 changes: 9 additions & 6 deletions tx/proposal/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,12 @@ func handleChangeParamMsg(
}

proposal := pm.CreateChangeParamProposal(ctx, msg.GetParameter())
if _, err := pm.AddProposal(ctx, msg.GetCreator(), proposal); err != nil {
proposalID, err := pm.AddProposal(ctx, msg.GetCreator(), proposal)
if err != nil {
return err.Result()
}
// set a time event to decide the proposal
event, err := pm.CreateDecideProposalEvent(ctx, types.ChangeParam)
event, err := pm.CreateDecideProposalEvent(ctx, types.ChangeParam, proposalID)
if err != nil {
return err.Result()
}
Expand Down Expand Up @@ -73,11 +74,12 @@ func handleProtocolUpgradeMsg(
}

proposal := pm.CreateProtocolUpgradeProposal(ctx, msg.GetLink())
if _, err := pm.AddProposal(ctx, msg.GetCreator(), proposal); err != nil {
proposalID, err := pm.AddProposal(ctx, msg.GetCreator(), proposal)
if err != nil {
return err.Result()
}
// set a time event to decide the proposal
event, err := pm.CreateDecideProposalEvent(ctx, types.ProtocolUpgrade)
event, err := pm.CreateDecideProposalEvent(ctx, types.ProtocolUpgrade, proposalID)
if err != nil {
return err.Result()
}
Expand Down Expand Up @@ -112,11 +114,12 @@ func handleContentCensorshipMsg(
}

proposal := pm.CreateContentCensorshipProposal(ctx, msg.GetPermLink())
if _, err := pm.AddProposal(ctx, msg.GetCreator(), proposal); err != nil {
proposalID, err := pm.AddProposal(ctx, msg.GetCreator(), proposal)
if err != nil {
return err.Result()
}
// set a time event to decide the proposal
event, err := pm.CreateDecideProposalEvent(ctx, types.ContentCensorship)
event, err := pm.CreateDecideProposalEvent(ctx, types.ContentCensorship, proposalID)
if err != nil {
return err.Result()
}
Expand Down
53 changes: 42 additions & 11 deletions tx/proposal/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,20 @@ func (pm ProposalManager) IsProposalExist(ctx sdk.Context, proposalID types.Prop
return proposalByte != nil
}

func (pm ProposalManager) IsOngoingProposal(ctx sdk.Context, proposalID types.ProposalKey) bool {
lst, err := pm.storage.GetProposalList(ctx)
if err != nil {
return false
}

for _, id := range lst.OngoingProposal {
if id == proposalID {
return true
}
}
return false
}

func (pm ProposalManager) CreateContentCensorshipProposal(
ctx sdk.Context, permLink types.PermLink) model.Proposal {
return &model.ContentCensorshipProposal{
Expand Down Expand Up @@ -83,16 +97,22 @@ func (pm ProposalManager) AddProposal(
return newID, nil
}

func (pm ProposalManager) GetCurrentProposal(ctx sdk.Context) (types.ProposalKey, sdk.Error) {
lst, err := pm.storage.GetProposalList(ctx)
func (pm ProposalManager) GetProposalPassParam(
ctx sdk.Context, proposalType types.ProposalType) (sdk.Rat, types.Coin, sdk.Error) {
param, err := pm.paramHolder.GetProposalParam(ctx)
if err != nil {
return types.ProposalKey(""), err
}

if len(lst.OngoingProposal) == 0 {
return types.ProposalKey(""), ErrOngoingProposalNotFound()
return sdk.NewRat(1, 1), types.NewCoin(0), err
}
switch proposalType {
case types.ChangeParam:
return param.ChangeParamPassRatio, param.ChangeParamPassVotes, nil
case types.ContentCensorship:
return param.ContentCensorshipPassRatio, param.ContentCensorshipPassVotes, nil
case types.ProtocolUpgrade:
return param.ProtocolUpgradePassRatio, param.ProtocolUpgradePassVotes, nil
default:
return sdk.NewRat(1, 1), types.NewCoin(0), ErrWrongProposalType()
}
return lst.OngoingProposal[0], nil
}

func (pm ProposalManager) UpdateProposalStatus(
Expand All @@ -113,8 +133,18 @@ func (pm ProposalManager) UpdateProposalStatus(
proposalInfo.AgreeVotes = res.AgreeVotes
proposalInfo.DisagreeVotes = res.DisagreeVotes

// TODO consider different types of propsal
if proposalInfo.AgreeVotes.IsGT(proposalInfo.DisagreeVotes) {
// calculate if agree votes meet minimum pass requirement
ratio, minVotes, err := pm.GetProposalPassParam(ctx, proposalType)
if err != nil {
return types.ProposalNotPass, err
}

totalVotes := res.AgreeVotes.Plus(res.DisagreeVotes)
if !totalVotes.IsGT(minVotes) {
return types.ProposalNotPass, nil
}
actualRatio := res.AgreeVotes.ToRat().Quo(totalVotes.ToRat())
if !actualRatio.LT(ratio) {
proposalInfo.Result = types.ProposalPass
}

Expand All @@ -139,9 +169,10 @@ func (pm ProposalManager) UpdateProposalStatus(
}

func (pm ProposalManager) CreateDecideProposalEvent(
ctx sdk.Context, proposalType types.ProposalType) (types.Event, sdk.Error) {
ctx sdk.Context, proposalType types.ProposalType, proposalID types.ProposalKey) (types.Event, sdk.Error) {
event := DecideProposalEvent{
ProposalType: proposalType,
ProposalID: proposalID,
}
return event, nil
}
Expand Down
Loading

0 comments on commit 1922314

Please sign in to comment.