xin-153 Broadcast syncInfo when consecutive timeouts of same round (#65)

* Broadcast syncInfo when consecutive timeouts of same round

* add test

* revert test period
This commit is contained in:
Liam 2022-03-05 01:52:20 +01:00 committed by GitHub
parent e493ddfd6d
commit d975ba4014
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 74 additions and 22 deletions

View file

@ -45,6 +45,7 @@ type XDPoS_v2 struct {
waitPeriodCh chan int
timeoutWorker *countdown.CountdownTimer // Timer to generate broadcast timeout msg if threashold reached
timeoutCount int // number of timeout being sent
timeoutPool *utils.Pool
votePool *utils.Pool
@ -62,7 +63,7 @@ type XDPoS_v2 struct {
func New(config *params.XDPoSConfig, db ethdb.Database, waitPeriodCh chan int) *XDPoS_v2 {
// Setup Timer
duration := time.Duration(config.V2.TimeoutWorkerDuration) * time.Second
duration := time.Duration(config.V2.TimeoutPeriod) * time.Second
timer := countdown.NewCountDown(duration)
timeoutPool := utils.NewPool(config.V2.CertThreshold)
@ -162,7 +163,7 @@ func (x *XDPoS_v2) Initial(chain consensus.ChainReader, masternodes []common.Add
}
// Initial timeout
log.Info("[Initial] miner wait period", "period", x.config.WaitPeriod)
log.Info("[Initial] miner wait period", "period", x.config.V2.WaitPeriod)
// avoid deadlock
go func() {
x.waitPeriodCh <- x.config.V2.WaitPeriod
@ -1184,6 +1185,7 @@ func (x *XDPoS_v2) processTC(blockChainReader consensus.ChainReader, timeoutCert
*/
func (x *XDPoS_v2) setNewRound(blockChainReader consensus.ChainReader, round utils.Round) error {
x.currentRound = round
x.timeoutCount = 0
//TODO: tell miner now it's a new round and start mine if it's leader
x.timeoutWorker.Reset(blockChainReader)
//TODO: vote pools
@ -1352,6 +1354,14 @@ func (x *XDPoS_v2) OnCountdownTimeout(time time.Time, chain interface{}) error {
log.Error("Error while sending out timeout message at time: ", time)
return err
}
x.timeoutCount++
if x.timeoutCount%x.config.V2.TimeoutSyncThreshold == 0 {
log.Info("[OnCountdownTimeout] timeout sync threadhold reached, send syncInfo message")
syncInfo := x.getSyncInfo()
x.broadcastToBftChannel(syncInfo)
}
return nil
}

View file

@ -1,11 +1,13 @@
package tests
import (
"fmt"
"testing"
"github.com/XinFinOrg/XDPoSChain/accounts"
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
"github.com/XinFinOrg/XDPoSChain/log"
"github.com/XinFinOrg/XDPoSChain/params"
"github.com/stretchr/testify/assert"
)
@ -19,9 +21,47 @@ func TestCountdownTimeoutToSendTimeoutMessage(t *testing.T) {
assert.Equal(t, poolSize, 1)
assert.NotNil(t, timeoutMsg)
assert.Equal(t, uint64(1350), timeoutMsg.(*utils.Timeout).GapNumber)
fmt.Println(timeoutMsg.(*utils.Timeout).GapNumber)
assert.Equal(t, utils.Round(1), timeoutMsg.(*utils.Timeout).Round)
}
func TestSyncInfoAfterReachTimeoutSnycThreadhold(t *testing.T) {
blockchain, _, _, _, _, _ := PrepareXDCTestBlockChainForV2Engine(t, 2251, params.TestXDPoSMockChainConfig, 0)
engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2
// Because messages are sending async and on random order, so use this way to test
var timeoutCounter, syncInfoCounter int
for i := 0; i < 3; i++ {
obj := <-engineV2.BroadcastCh
switch v := obj.(type) {
case *utils.Timeout:
timeoutCounter++
case *utils.SyncInfo:
syncInfoCounter++
default:
log.Error("Unknown message type received", "value", v)
}
}
assert.Equal(t, 2, timeoutCounter)
assert.Equal(t, 1, syncInfoCounter)
t.Log("waiting for another consecutive period")
// another consecutive period
for i := 0; i < 3; i++ {
obj := <-engineV2.BroadcastCh
switch v := obj.(type) {
case *utils.Timeout:
timeoutCounter++
case *utils.SyncInfo:
syncInfoCounter++
default:
log.Error("Unknown message type received", "value", v)
}
}
assert.Equal(t, 4, timeoutCounter)
assert.Equal(t, 2, syncInfoCounter)
}
// Timeout handler
func TestTimeoutMessageHandlerSuccessfullyGenerateTCandSyncInfo(t *testing.T) {
blockchain, _, _, _, _, _ := PrepareXDCTestBlockChainForV2Engine(t, 11, params.TestXDPoSMockChainConfig, 0)

View file

@ -36,23 +36,25 @@ var (
var (
XDPoSV2Config = &V2{
TimeoutWorkerDuration: 50,
CertThreshold: common.MaxMasternodesV2*2/3 + 1,
TimeoutPeriod: 50,
CertThreshold: common.MaxMasternodesV2*2/3 + 1,
}
TestXDPoSV2Config = &V2{
TimeoutWorkerDuration: 10,
CertThreshold: 3,
WaitPeriod: 1,
MinePeriod: 2,
SwitchBlock: big.NewInt(900),
SkipV2Validation: true,
SwitchBlock: big.NewInt(900),
CertThreshold: 3,
TimeoutSyncThreshold: 2,
TimeoutPeriod: 10,
WaitPeriod: 1,
MinePeriod: 2,
SkipV2Validation: true,
}
DevnetXDPoSV2Config = &V2{
SwitchBlock: big.NewInt(7218000),
TimeoutWorkerDuration: 50,
CertThreshold: 6,
WaitPeriod: 2,
MinePeriod: 10,
SwitchBlock: big.NewInt(7218000),
CertThreshold: 6,
TimeoutSyncThreshold: 5,
TimeoutPeriod: 50,
WaitPeriod: 2,
MinePeriod: 10,
}
// XDPoSChain mainnet config
@ -202,18 +204,18 @@ type XDPoSConfig struct {
RewardCheckpoint uint64 `json:"rewardCheckpoint"` // Checkpoint block for calculate rewards.
Gap uint64 `json:"gap"` // Gap time preparing for the next epoch
FoudationWalletAddr common.Address `json:"foudationWalletAddr"` // Foundation Address Wallet
WaitPeriod int `json:"waitPeriod"` // Miner wait period
SkipV1Validation bool //Skip Block Validation for testing purpose, V1 consensus only
V2 *V2 `json:"v2"`
}
type V2 struct {
WaitPeriod int `json:"waitPeriod"` // Miner wait period to check mine event
MinePeriod int `json:"minePeriod"` // Miner mine period to mine a block
SwitchBlock *big.Int `json:"switchBlock"` // v1 to v2 switch block number
TimeoutWorkerDuration int64 `json:"timeoutWorkerDuration"` // Duration in ms
CertThreshold int `json:"certificateThreshold"` // Necessary number of messages from master nodes to form a certificate
SkipV2Validation bool //Skip Block Validation for testing purpose, V2 consensus only
WaitPeriod int `json:"waitPeriod"` // Miner wait period to check mine event
MinePeriod int `json:"minePeriod"` // Miner mine period to mine a block
SwitchBlock *big.Int `json:"switchBlock"` // v1 to v2 switch block number
TimeoutSyncThreshold int `json:"timeoutSyncThreshold"` // send syncInfo after number of timeout
TimeoutPeriod int `json:"timeoutPeriod"` // Duration in ms
CertThreshold int `json:"certificateThreshold"` // Necessary number of messages from master nodes to form a certificate
SkipV2Validation bool //Skip Block Validation for testing purpose, V2 consensus only
}
// String implements the stringer interface, returning the consensus engine details.