Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(bpos): adjust the judgment rules of IllegalProposal and IllegalVotes #2218

Merged
merged 14 commits into from
Aug 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions cmd/script/api/dposmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package api
import (
"encoding/json"
"fmt"
"math"
"strconv"
"time"

Expand Down Expand Up @@ -88,7 +89,7 @@ func newDposManager(L *lua.LState) int {
TimeSource: medianTime,
})

mockManager.Consensus = NewConsensus(dposManager, 5*time.Second, mockManager.Handler)
mockManager.Consensus = NewConsensus(dposManager, 5*time.Second, mockManager.Handler, math.MaxUint32)
mockManager.Dispatcher, mockManager.IllegalMonitor = NewDispatcherAndIllegalMonitor(ProposalDispatcherConfig{
EventMonitor: mockManager.EventMonitor,
Consensus: mockManager.Consensus,
Expand Down Expand Up @@ -324,7 +325,7 @@ func dposManagerSignVote(L *lua.LState) int {
return 1
}

//mock object of dpos manager
// mock object of dpos manager
type manager struct {
*DPOSManager
Account account.Account
Expand Down
18 changes: 16 additions & 2 deletions common/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,9 @@ func GetDefaultParams() *Configuration {
MaxInactiveRoundsOfRandomNode: 36 * 8,
RevertToPOWNoBlockTime: 12 * 3600,
StopConfirmBlockTime: 11 * 3600,
RevertToPOWNoBlockTimeV1: 2 * 3600, // todo complete me
StopConfirmBlockTimeV1: 6600, // todo complete me
ChangeViewV1Height: math.MaxUint32, // todo complete me
DPoSV2IllegalPenalty: 20000000000,
DPOSNodeCrossChainHeight: math.MaxUint32,
DPoSV2DepositCoinMinLockTime: 7200,
Expand Down Expand Up @@ -360,6 +363,9 @@ func (p *Configuration) TestNet() *Configuration {
p.MaxReservedCustomIDLength = 255
p.DPoSConfiguration.RevertToPOWNoBlockTime = 12 * 3600
p.DPoSConfiguration.StopConfirmBlockTime = 11 * 3600
p.DPoSConfiguration.RevertToPOWNoBlockTimeV1 = 2 * 3600 // todo complete me
p.DPoSConfiguration.StopConfirmBlockTimeV1 = 6600 // todo complete me
p.DPoSConfiguration.ChangeViewV1Height = math.MaxUint32 // todo complete me
p.DPoSConfiguration.RevertToPOWStartHeight = 815060
p.HalvingRewardHeight = 877880 //767000 + 154 * 720
p.HalvingRewardInterval = 1051200 //4 * 365 * 720
Expand Down Expand Up @@ -484,6 +490,9 @@ func (p *Configuration) RegNet() *Configuration {
p.MaxReservedCustomIDLength = 255
p.DPoSConfiguration.RevertToPOWNoBlockTime = 12 * 3600
p.DPoSConfiguration.StopConfirmBlockTime = 11 * 3600
p.DPoSConfiguration.RevertToPOWNoBlockTimeV1 = 2 * 3600 // todo complete me
p.DPoSConfiguration.StopConfirmBlockTimeV1 = 6600 // todo complete me
p.DPoSConfiguration.ChangeViewV1Height = math.MaxUint32 // todo complete me
p.DPoSConfiguration.RevertToPOWStartHeight = 706240
p.HalvingRewardHeight = 801240 //690360 + 154 * 720
p.HalvingRewardInterval = 1051200 //4 * 365 * 720
Expand Down Expand Up @@ -721,6 +730,12 @@ type DPoSConfiguration struct {
RevertToPOWNoBlockTime int64 `screw:"--reverttopownoblocktime" usage:"defines how long time does it take to revert to POW mode"`
// StopConfirmBlockTime defines how long time dose it take before stop confirm block.
StopConfirmBlockTime int64 `screw:"--stopconfirmblocktime" usage:"defines how long time does it take to stop confirm block"`
// RevertToPOWInterval defines how long time does it take to revert to POW mode.
RevertToPOWNoBlockTimeV1 int64 `screw:"--reverttopownoblocktimev1" usage:"defines how long time does it take to revert to POW mode"`
// StopConfirmBlockTime defines how long time dose it take before stop confirm block.
StopConfirmBlockTimeV1 int64 `screw:"--stopconfirmblocktimev1" usage:"defines how long time does it take to stop confirm block"`
// ChangeViewV1Height defines the height of ChangeView version 1.0
ChangeViewV1Height uint32 `screw:"--changeviewv1height" usage:"defines how the height of ChangeView version 1.0"`
// RevertToPOWStartHeight defines the start height to allow to revert to POW mode.
RevertToPOWStartHeight uint32 `screw:"--reverttopowstartheight" usage:"defines the start height to allow to revert to POW mode"`
// DPoSV2RewardAccumulateAddress defines the dposv2 reward accumulating address
Expand Down Expand Up @@ -910,9 +925,8 @@ func (p *Configuration) newRewardPerBlock(targetTimePerBlock time.Duration, heig
generatedBlocksPerYear := 365 * 24 * 60 * 60 / blockGenerateInterval
factor := uint32(1)
if height >= p.HalvingRewardHeight {
factor = 2 + (height-p.HalvingRewardHeight)/p.HalvingRewardInterval
factor = 2 + (height-p.HalvingRewardHeight)/p.HalvingRewardInterval // HalvingRewardHeight: 1051200
}

return common.Fixed64(float64(newInflationPerYear) / float64(generatedBlocksPerYear) / math.Pow(2, float64(factor-1)))
}

Expand Down
13 changes: 12 additions & 1 deletion core/transaction/illegalproposaltransaction.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// Copyright (c) 2017-2021 The Elastos Foundation
// Use of this source code is governed by an MIT
// license that can be found in the LICENSE file.
//
package transaction

import (
"bytes"
"errors"
"fmt"
"math"

"github.com/elastos/Elastos.ELA/blockchain"
Expand All @@ -20,6 +20,17 @@ type IllegalProposalTransaction struct {
BaseTransaction
}

func (t *IllegalProposalTransaction) HeightVersionCheck() error {
blockHeight := t.parameters.BlockHeight
chainParams := t.parameters.Config

if blockHeight < chainParams.DPoSConfiguration.ChangeViewV1Height {
return errors.New(fmt.Sprintf("not support %s transaction "+
"before ChangeViewV1Height", t.TxType().Name()))
}
return nil
}

func (t *IllegalProposalTransaction) CheckTransactionInput() error {
if len(t.Inputs()) != 0 {
return errors.New("no cost transactions must has no input")
Expand Down
7 changes: 6 additions & 1 deletion core/transaction/illegalvotetransaction.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Copyright (c) 2017-2021 The Elastos Foundation
// Use of this source code is governed by an MIT
// license that can be found in the LICENSE file.
//
package transaction

import (
Expand Down Expand Up @@ -102,6 +101,12 @@ func (t *IllegalVoteTransaction) CheckDPOSIllegalVotes(d *payload.DPOSIllegalVot
return errors.New("should be same sponsor")
}

if t.parameters.BlockHeight <= t.parameters.Config.DPoSConfiguration.ChangeViewV1Height {
if !d.Evidence.Proposal.Hash().IsEqual(d.CompareEvidence.Proposal.Hash()) {
return errors.New("should be same proposal")
}
}

if d.Evidence.Proposal.ViewOffset != d.CompareEvidence.Proposal.ViewOffset {
return errors.New("should in same view")
}
Expand Down
8 changes: 7 additions & 1 deletion core/transaction/reverttopowtransaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,13 @@ func (t *RevertToPOWTransaction) SpecialContextCheck() (result elaerr.ELAError,
switch p.Type {
case payload.NoBlock:
lastBlockTime := int64(t.parameters.BlockChain.BestChain.Timestamp)
noBlockTime := t.parameters.Config.DPoSConfiguration.RevertToPOWNoBlockTime

var noBlockTime int64
if t.parameters.BlockHeight < t.parameters.Config.DPoSConfiguration.ChangeViewV1Height {
noBlockTime = t.parameters.Config.DPoSConfiguration.RevertToPOWNoBlockTime
} else {
noBlockTime = t.parameters.Config.DPoSConfiguration.RevertToPOWNoBlockTimeV1
}

if t.parameters.TimeStamp == 0 {
// is not in block, check by local time.
Expand Down
12 changes: 10 additions & 2 deletions dpos/arbitrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,15 @@ func (a *Arbitrator) OnBlockReceived(b *types.Block, confirmed bool) {
if b.Height >= a.cfg.ChainParams.DPoSConfiguration.RevertToPOWStartHeight {
lastBlockTimestamp := int64(a.cfg.Arbitrators.GetLastBlockTimestamp())
localTimestamp := a.cfg.Chain.TimeSource.AdjustedTime().Unix()
if localTimestamp-lastBlockTimestamp >= a.cfg.ChainParams.DPoSConfiguration.StopConfirmBlockTime {

var stopConfirmTime int64
if b.Height < a.cfg.ChainParams.DPoSConfiguration.ChangeViewV1Height {
stopConfirmTime = a.cfg.ChainParams.DPoSConfiguration.StopConfirmBlockTime
} else {
stopConfirmTime = a.cfg.ChainParams.DPoSConfiguration.StopConfirmBlockTimeV1
}

if localTimestamp-lastBlockTimestamp >= stopConfirmTime {
return
}
}
Expand Down Expand Up @@ -281,7 +289,7 @@ func NewArbitrator(account account.Account, cfg Config) (*Arbitrator, error) {

consensus := manager.NewConsensus(dposManager,
cfg.ChainParams.DPoSConfiguration.SignTolerance,
dposHandlerSwitch)
dposHandlerSwitch, cfg.ChainParams.DPoSConfiguration.ChangeViewV1Height)
proposalDispatcher, illegalMonitor := manager.NewDispatcherAndIllegalMonitor(
manager.ProposalDispatcherConfig{
EventMonitor: eventMonitor,
Expand Down
35 changes: 25 additions & 10 deletions dpos/manager/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@ import (
const (
consensusReady = iota
consensusRunning

DefaultViewOffset = 0
)

type Consensus struct {
finishedHeight uint32
consensusStatus uint32
viewOffset uint32

Expand All @@ -29,16 +32,17 @@ type Consensus struct {
}

func NewConsensus(manager *DPOSManager, tolerance time.Duration,
viewListener ViewListener) *Consensus {
viewListener ViewListener, changeViewV1Height uint32) *Consensus {
c := &Consensus{
consensusStatus: consensusReady,
viewOffset: 0,
viewOffset: DefaultViewOffset,
manager: manager,
currentView: view{
publicKey: manager.publicKey,
signTolerance: tolerance,
listener: viewListener,
arbitrators: manager.arbitrators,
publicKey: manager.publicKey,
signTolerance: tolerance,
listener: viewListener,
arbitrators: manager.arbitrators,
changeViewV1Height: changeViewV1Height,
},
}

Expand All @@ -58,7 +62,8 @@ func (c *Consensus) SetRunning() {
c.resetViewOffset()
}

func (c *Consensus) SetReady() {
func (c *Consensus) SetReady(height uint32) {
c.finishedHeight = height
c.consensusStatus = consensusReady
c.resetViewOffset()
}
Expand Down Expand Up @@ -108,12 +113,22 @@ func (c *Consensus) ProcessBlock(b *types.Block) {
}

func (c *Consensus) ChangeView() {
c.currentView.ChangeView(&c.viewOffset, c.manager.timeSource.AdjustedTime())
if c.finishedHeight < c.manager.chainParams.DPoSConfiguration.ChangeViewV1Height {
c.currentView.ChangeView(&c.viewOffset, c.manager.timeSource.AdjustedTime())
} else {
c.currentView.ChangeViewV1(&c.viewOffset, c.manager.timeSource.AdjustedTime())
}

}

func (c *Consensus) TryChangeView() bool {
if c.IsRunning() {
return c.currentView.TryChangeView(&c.viewOffset, c.manager.timeSource.AdjustedTime())
if c.finishedHeight < c.manager.chainParams.DPoSConfiguration.ChangeViewV1Height {
return c.currentView.TryChangeView(&c.viewOffset, c.manager.timeSource.AdjustedTime())
} else {
return c.currentView.TryChangeViewV1(&c.viewOffset, c.manager.timeSource.AdjustedTime())
}

}
return false
}
Expand All @@ -135,5 +150,5 @@ func (c *Consensus) RecoverFromConsensusStatus(status *msg.ConsensusStatus) erro
}

func (c *Consensus) resetViewOffset() {
c.viewOffset = 0
c.viewOffset = DefaultViewOffset
}
11 changes: 7 additions & 4 deletions dpos/manager/dposmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,10 +248,13 @@ func (d *DPOSManager) OnProposalReceived(id dpeer.PID, p *payload.DPOSProposal)
if d.consensus.viewOffset != 0 && d.arbitrators.HasArbitersHalfMinorityCount(count) {
log.Info("[OnProposalReceived] has minority not handled" +
" proposals, need recover")
if d.recoverAbnormalState() {
log.Info("[OnProposalReceived] recover start")
} else {
log.Error("[OnProposalReceived] has no active peers recover failed")

if d.consensus.finishedHeight < d.chainParams.DPoSConfiguration.ChangeViewV1Height {
if d.recoverAbnormalState() {
log.Info("[OnProposalReceived] recover start")
} else {
log.Error("[OnProposalReceived] has no active peers recover failed")
}
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions dpos/manager/dposnormalhandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ func (h *DPOSNormalHandler) ProcessProposal(id peer.PID, p *payload.DPOSProposal
func (h *DPOSNormalHandler) ChangeView(firstBlockHash *common.Uint256) {
log.Info("[OnViewChanged] clean proposal")
h.proposalDispatcher.CleanProposals(true)
// sign proposal with same view offset to me
for _, v := range h.proposalDispatcher.precociousProposals {
if h.consensus.GetViewOffset() == v.ViewOffset {
h.proposalDispatcher.ProcessProposal(peer.PID{}, v, false)
}
}
}

func (h *DPOSNormalHandler) TryStartNewConsensus(b *types.Block) bool {
Expand Down
2 changes: 2 additions & 0 deletions dpos/manager/dposondutyhandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/elastos/Elastos.ELA/dpos/log"
"github.com/elastos/Elastos.ELA/dpos/p2p/peer"
"github.com/elastos/Elastos.ELA/p2p/msg"
"time"
)

type DPOSOnDutyHandler struct {
Expand Down Expand Up @@ -64,6 +65,7 @@ func (h *DPOSOnDutyHandler) TryStartNewConsensus(b *types.Block) bool {
result := false

if h.consensus.IsReady() {
log.Info("############# start new consensus at ", b.Height, "current time:", time.Now())
log.Info("[OnDuty][OnBlockReceived] received first unsigned block, start consensus")
h.consensus.StartConsensus(b)
h.proposalDispatcher.StartProposal(b)
Expand Down
Loading
Loading