Skip to content

Commit

Permalink
feat(bpos): adjust change view logic and revert to pow logic
Browse files Browse the repository at this point in the history
  • Loading branch information
RainFallsSilent committed Aug 4, 2023
1 parent 08cc331 commit be9dfa5
Show file tree
Hide file tree
Showing 8 changed files with 128 additions and 35 deletions.
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
20 changes: 20 additions & 0 deletions common/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,10 @@ func GetDefaultParams() *Configuration {
MaxInactiveRoundsOfRandomNode: 36 * 8,
RevertToPOWNoBlockTime: 12 * 3600,
StopConfirmBlockTime: 11 * 3600,
RevertToPOWV1Height: math.MaxUint32, // todo complete me
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 +364,10 @@ func (p *Configuration) TestNet() *Configuration {
p.MaxReservedCustomIDLength = 255
p.DPoSConfiguration.RevertToPOWNoBlockTime = 12 * 3600
p.DPoSConfiguration.StopConfirmBlockTime = 11 * 3600
p.DPoSConfiguration.RevertToPOWV1Height = math.MaxUint32 // todo complete me
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 +492,10 @@ func (p *Configuration) RegNet() *Configuration {
p.MaxReservedCustomIDLength = 255
p.DPoSConfiguration.RevertToPOWNoBlockTime = 12 * 3600
p.DPoSConfiguration.StopConfirmBlockTime = 11 * 3600
p.DPoSConfiguration.RevertToPOWV1Height = math.MaxUint32 // todo complete me
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 +733,14 @@ 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"`
// RevertToPOWV1Height defines how the height of POW mode of version 1.0
RevertToPOWV1Height uint32 `screw:"--reverttopowv1height" usage:"defines how the height of POW mode of version 1.0"`
// 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
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.RevertToPOWV1Height {
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.RevertToPOWV1Height {
stopConfirmTime = a.cfg.ChainParams.DPoSConfiguration.StopConfirmBlockTime
} else {
stopConfirmTime = a.cfg.ChainParams.DPoSConfiguration.StopConfirmBlockTime
}

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
29 changes: 21 additions & 8 deletions dpos/manager/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const (
)

type Consensus struct {
finishedHeight uint32
consensusStatus uint32
viewOffset uint32

Expand All @@ -31,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: 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 @@ -60,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 @@ -110,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 Down
8 changes: 4 additions & 4 deletions dpos/manager/proposaldispatcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -399,19 +399,19 @@ func (p *ProposalDispatcher) FinishConsensus(height uint32, blockHash common.Uin
p.cfg.Manager.changeOnDuty()
c := log.ConsensusEvent{EndTime: p.cfg.TimeSource.AdjustedTime(), Height: height}
p.cfg.EventMonitor.OnConsensusFinished(&c)
p.cfg.Consensus.SetReady()
p.cfg.Consensus.SetReady(height)
p.CleanProposals(false)
p.resetViewRequests = make(map[string]struct{}, 0)
}
}

func (p *ProposalDispatcher) resetConsensus() {
func (p *ProposalDispatcher) resetConsensus(height uint32) {
log.Info("[resetConsensus] start")
defer log.Info("[resetConsensus] end")

if p.cfg.Consensus.IsRunning() {
log.Info("[resetConsensus] reset view")
p.cfg.Consensus.SetReady()
p.cfg.Consensus.SetReady(height)
p.CleanProposals(false)
}
}
Expand Down Expand Up @@ -678,7 +678,7 @@ func (p *ProposalDispatcher) OnResponseResetViewReceived(msg *dmsg.ResetView) {
if len(p.resetViewRequests) >= p.cfg.Arbitrators.GetArbitersMajorityCount() {
log.Info("[OnResponseResetViewReceived] signer:", common.BytesToHexString(signer))
// do reset
p.resetConsensus()
p.resetConsensus(p.finishedHeight)
p.resetViewRequests = make(map[string]struct{}, 0)
}
}
Expand Down
67 changes: 52 additions & 15 deletions dpos/manager/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,22 @@ import (
"github.com/elastos/Elastos.ELA/dpos/state"
)

const (
ChangeViewAddStep = uint32(3)
ChangeViewMulStep = uint32(20)
)

type ViewListener interface {
OnViewChanged(isOnDuty bool)
}

type view struct {
publicKey []byte
signTolerance time.Duration
viewStartTime time.Time
isDposOnDuty bool
arbitrators state.Arbitrators
publicKey []byte
signTolerance time.Duration
viewStartTime time.Time
isDposOnDuty bool
changeViewV1Height uint32
arbitrators state.Arbitrators

listener ViewListener
}
Expand All @@ -46,16 +52,27 @@ func (v *view) ResetView(t time.Time) {
}

func (v *view) ChangeView(viewOffset *uint32, now time.Time) {
//offset, offsetTime := v.calculateOffsetTimeV0(v.viewStartTime, now)
//*viewOffset += uint32(offset)
offset, offsetTime := v.calculateOffsetTimeV0(v.viewStartTime, now)
*viewOffset += offset

v.viewStartTime = now.Add(-offsetTime)

if offset > 0 {
currentArbiter := v.arbitrators.GetNextOnDutyArbitrator(*viewOffset)

v.isDposOnDuty = bytes.Equal(currentArbiter, v.publicKey)
log.Info("current onduty arbiter:",
common.BytesToHexString(currentArbiter))

v.listener.OnViewChanged(v.isDposOnDuty)
}
}

func (v *view) ChangeViewV1(viewOffset *uint32, now time.Time) {
arbitersCount := v.arbitrators.GetArbitersCount()

offset, offsetTime := v.calculateOffsetTimeV1(*viewOffset, v.viewStartTime, now, uint32(arbitersCount))
*viewOffset = uint32(offset)

//offset, offsetTime := v.calculateOffsetTimeV2(*viewOffset, v.viewStartTime, now, uint32(arbitersCount))
//*viewOffset = uint32(offset)
*viewOffset = offset

v.viewStartTime = now.Add(-offsetTime)

Expand All @@ -81,15 +98,26 @@ func (v *view) calculateOffsetTimeV0(startTime time.Time,

func (v *view) calculateOffsetTimeV1(currentViewOffset uint32, startTime time.Time,
now time.Time, arbitersCount uint32) (uint32, time.Duration) {
step := float64(3)
duration := now.Sub(startTime)

currentOffset := currentViewOffset
duration := now.Sub(startTime)

offsetSeconds := time.Duration(5*math.Pow(step, float64(currentOffset/arbitersCount))) * time.Second
var offsetSeconds time.Duration
if currentOffset < arbitersCount {
offsetSeconds = 5 * time.Second
} else {
offsetSeconds = time.Duration(5+(currentOffset-arbitersCount)*ChangeViewAddStep*
uint32(math.Pow(float64(ChangeViewMulStep), float64(currentOffset/arbitersCount)))) * time.Second
}
for duration >= offsetSeconds {
currentOffset++
duration -= offsetSeconds
offsetSeconds = time.Duration(5*math.Pow(step, float64(currentOffset/arbitersCount))) * time.Second
if currentOffset < arbitersCount {
offsetSeconds = 5 * time.Second
} else {
offsetSeconds = time.Duration(5+(currentOffset-arbitersCount)*ChangeViewAddStep*
uint32(math.Pow(float64(ChangeViewMulStep), float64(currentOffset/arbitersCount)))) * time.Second
}
}

return currentOffset, duration
Expand Down Expand Up @@ -119,6 +147,15 @@ func (v *view) TryChangeView(viewOffset *uint32, now time.Time) bool {
return false
}

func (v *view) TryChangeViewV1(viewOffset *uint32, now time.Time) bool {
if now.After(v.viewStartTime.Add(v.signTolerance)) {
log.Info("[TryChangeView] succeed")
v.ChangeViewV1(viewOffset, now)
return true
}
return false
}

func (v *view) GetViewInterval() time.Duration {
return v.signTolerance
}
14 changes: 11 additions & 3 deletions pow/revertlistener.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,25 @@ func (pow *Service) ListenForRevert() {
go func() {
for {
time.Sleep(CheckRevertToPOWInterval)
if pow.chain.BestChain.Height < pow.chainParams.DPoSConfiguration.RevertToPOWStartHeight {
currentHeight := pow.chain.BestChain.Height
if currentHeight < pow.chainParams.DPoSConfiguration.RevertToPOWStartHeight {
continue
}
if pow.arbiters.IsInPOWMode() {
continue
}
lastBlockTimestamp := int64(pow.arbiters.GetLastBlockTimestamp())
localTimestamp := pow.chain.TimeSource.AdjustedTime().Unix()
var noBlockTime int64
if currentHeight < pow.chainParams.DPoSConfiguration.RevertToPOWV1Height {
noBlockTime = pow.chainParams.DPoSConfiguration.RevertToPOWNoBlockTime
} else {
noBlockTime = pow.chainParams.DPoSConfiguration.RevertToPOWNoBlockTimeV1
}

log.Debug("ListenForRevert lastBlockTimestamp:", lastBlockTimestamp,
"localTimestamp:", localTimestamp, "RevertToPOWNoBlockTime:", pow.chainParams.DPoSConfiguration.RevertToPOWNoBlockTime)
if localTimestamp-lastBlockTimestamp < pow.chainParams.DPoSConfiguration.RevertToPOWNoBlockTime {
"localTimestamp:", localTimestamp, "RevertToPOWNoBlockTime:", noBlockTime)
if localTimestamp-lastBlockTimestamp < noBlockTime {
continue
}

Expand Down

0 comments on commit be9dfa5

Please sign in to comment.