resolve sync issue by passing right round number (#384)

This commit is contained in:
Liam 2023-12-27 22:14:13 +11:00 committed by GitHub
parent e30d909643
commit c7a42fd7c9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 54 additions and 9 deletions

View file

@ -336,7 +336,7 @@ func (x *XDPoS_v2) Prepare(chain consensus.ChainReader, header *types.Header) er
return err return err
} }
if isEpochSwitchBlock { if isEpochSwitchBlock {
masterNodes, penalties, err := x.calcMasternodes(chain, header.Number, header.ParentHash) masterNodes, penalties, err := x.calcMasternodes(chain, header.Number, header.ParentHash, currentRound)
if err != nil { if err != nil {
return err return err
} }
@ -997,9 +997,9 @@ func (x *XDPoS_v2) GetStandbynodes(chain consensus.ChainReader, header *types.He
} }
// Calculate masternodes for a block number and parent hash. In V2, truncating candidates[:MaxMasternodes] is done in this function. // Calculate masternodes for a block number and parent hash. In V2, truncating candidates[:MaxMasternodes] is done in this function.
func (x *XDPoS_v2) calcMasternodes(chain consensus.ChainReader, blockNum *big.Int, parentHash common.Hash) ([]common.Address, []common.Address, error) { func (x *XDPoS_v2) calcMasternodes(chain consensus.ChainReader, blockNum *big.Int, parentHash common.Hash, round types.Round) ([]common.Address, []common.Address, error) {
// using new max masterndoes // using new max masterndoes
maxMasternodes := x.config.V2.Config(uint64(x.currentRound)).MaxMasternodes maxMasternodes := x.config.V2.Config(uint64(round)).MaxMasternodes
snap, err := x.getSnapshot(chain, blockNum.Uint64(), false) snap, err := x.getSnapshot(chain, blockNum.Uint64(), false)
if err != nil { if err != nil {
log.Error("[calcMasternodes] Adaptor v2 getSnapshot has error", "err", err) log.Error("[calcMasternodes] Adaptor v2 getSnapshot has error", "err", err)
@ -1081,7 +1081,7 @@ func (x *XDPoS_v2) allowedToSend(chain consensus.ChainReader, blockHeader *types
for _, mn := range masterNodes { for _, mn := range masterNodes {
log.Debug("[allowedToSend] Master node list", "masterNodeAddress", mn.Hash()) log.Debug("[allowedToSend] Master node list", "masterNodeAddress", mn.Hash())
} }
log.Info("[allowedToSend] Not in the Masternode list, not suppose to send message", "sendType", sendType, "MyAddress", signer.Hex()) log.Debug("[allowedToSend] Not in the Masternode list, not suppose to send message", "sendType", sendType, "MyAddress", signer.Hex())
return false return false
} }

View file

@ -25,7 +25,7 @@ func (x *XDPoS_v2) yourturn(chain consensus.ChainReader, round types.Round, pare
} }
var masterNodes []common.Address var masterNodes []common.Address
if isEpochSwitch { if isEpochSwitch {
masterNodes, _, err = x.calcMasternodes(chain, big.NewInt(0).Add(parent.Number, big.NewInt(1)), parent.Hash()) masterNodes, _, err = x.calcMasternodes(chain, big.NewInt(0).Add(parent.Number, big.NewInt(1)), parent.Hash(), round)
if err != nil { if err != nil {
log.Error("[yourturn] Cannot calcMasternodes at gap num ", "err", err, "parent number", parent.Number) log.Error("[yourturn] Cannot calcMasternodes at gap num ", "err", err, "parent number", parent.Number)
return false, err return false, err

View file

@ -115,7 +115,7 @@ func (x *XDPoS_v2) verifyHeader(chain consensus.ChainReader, header *types.Heade
return utils.ErrInvalidCheckpointSigners return utils.ErrInvalidCheckpointSigners
} }
localMasterNodes, localPenalties, err := x.calcMasternodes(chain, header.Number, header.ParentHash) localMasterNodes, localPenalties, err := x.calcMasternodes(chain, header.Number, header.ParentHash, round)
masterNodes = localMasterNodes masterNodes = localMasterNodes
if err != nil { if err != nil {
log.Error("[verifyHeader] Fail to calculate master nodes list with penalty", "Number", header.Number, "Hash", header.Hash()) log.Error("[verifyHeader] Fail to calculate master nodes list with penalty", "Number", header.Number, "Hash", header.Hash())

View file

@ -260,6 +260,50 @@ func TestConfigSwitchOnDifferentCertThreshold(t *testing.T) {
assert.Equal(t, utils.ErrValidatorNotWithinMasternodes, err) assert.Equal(t, utils.ErrValidatorNotWithinMasternodes, err)
} }
/*
1. Insert 20 masternode before gap block
2. Prepare 20 masternode block header with round 9000
3. verify this header while node is on round 899,
This is to simulate node is syncing from remote during config switch
*/
func TestConfigSwitchOnDifferentMasternodeCount(t *testing.T) {
b, err := json.Marshal(params.TestXDPoSMockChainConfig)
assert.Nil(t, err)
configString := string(b)
var config params.ChainConfig
err = json.Unmarshal([]byte(configString), &config)
assert.Nil(t, err)
// Enable verify
config.XDPoS.V2.SkipV2Validation = false
// Block 901 is the first v2 block with round of 1
blockchain, _, currentBlock, _, _, _ := PrepareXDCTestBlockChainForV2Engine(t, int(config.XDPoS.Epoch)*2, &config, nil)
adaptor := blockchain.Engine().(*XDPoS.XDPoS)
x := adaptor.EngineV2
// Generate round 900 header, num 1800
header1800 := blockchain.GetBlockByNumber(1800).Header()
snap, err := x.GetSnapshot(blockchain, currentBlock.Header())
assert.Nil(t, err)
assert.Equal(t, len(snap.NextEpochMasterNodes), 20)
header1800.Validators = []byte{}
for i := 0; i < 20; i++ {
header1800.Validators = append(header1800.Validators, snap.NextEpochMasterNodes[i].Bytes()...)
}
round, err := x.GetRoundNumber(header1800)
assert.Nil(t, err)
assert.Equal(t, round, types.Round(900))
adaptor.EngineV2.SetNewRoundFaker(blockchain, 899, false)
err = adaptor.VerifyHeader(blockchain, header1800, true)
// error ErrValidatorNotWithinMasternodes means verifyQC is passed and move to next verification process
assert.Equal(t, utils.ErrValidatorNotWithinMasternodes, err)
}
func TestConfigSwitchOnDifferentMindPeriod(t *testing.T) { func TestConfigSwitchOnDifferentMindPeriod(t *testing.T) {
b, err := json.Marshal(params.TestXDPoSMockChainConfig) b, err := json.Marshal(params.TestXDPoSMockChainConfig)
assert.Nil(t, err) assert.Nil(t, err)

View file

@ -510,6 +510,7 @@ func (q *queue) reserveHeaders(p *peerConnection, count int, taskPool map[common
// If we're the first to request this task, initialise the result container // If we're the first to request this task, initialise the result container
index := int(header.Number.Int64() - int64(q.resultOffset)) index := int(header.Number.Int64() - int64(q.resultOffset))
if index >= len(q.resultCache) || index < 0 { if index >= len(q.resultCache) || index < 0 {
log.Error("index allocation went beyond available resultCache space", "index", index, "len.resultCache", len(q.resultCache), "blockNum", header.Number.Int64(), "resultOffset", q.resultOffset)
common.Report("index allocation went beyond available resultCache space") common.Report("index allocation went beyond available resultCache space")
return nil, false, errInvalidChain return nil, false, errInvalidChain
} }

View file

@ -37,9 +37,9 @@ func AttachConsensusV2Hooks(adaptor *XDPoS.XDPoS, bc *core.BlockChain, chainConf
break break
} }
log.Info("[V2 Hook Penalty] parentHeader is nil, wait block to be writen in disk", "parentNumber", parentNumber) log.Info("[V2 Hook Penalty] parentHeader is nil, wait block to be writen in disk", "parentNumber", parentNumber)
time.Sleep(200 * time.Millisecond) // 0.2s time.Sleep(time.Second) // 1s
if timeout > 50 { // wait over 10s if timeout > 30 { // wait over 30s
log.Error("[V2 Hook Penalty] parentHeader is nil, wait too long not writen in to disk", "parentNumber", parentNumber) log.Error("[V2 Hook Penalty] parentHeader is nil, wait too long not writen in to disk", "parentNumber", parentNumber)
return []common.Address{}, fmt.Errorf("parentHeader is nil") return []common.Address{}, fmt.Errorf("parentHeader is nil")
} }

View file

@ -23,7 +23,7 @@ import (
const ( const (
VersionMajor = 2 // Major version component of the current release VersionMajor = 2 // Major version component of the current release
VersionMinor = 0 // Minor version component of the current release VersionMinor = 0 // Minor version component of the current release
VersionPatch = 0 // Patch version component of the current release VersionPatch = 1 // Patch version component of the current release
VersionMeta = "beta1" // Version metadata to append to the version string VersionMeta = "beta1" // Version metadata to append to the version string
) )