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
}
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 {
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.
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
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)
if err != nil {
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 {
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
}

View file

@ -25,7 +25,7 @@ func (x *XDPoS_v2) yourturn(chain consensus.ChainReader, round types.Round, pare
}
var masterNodes []common.Address
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 {
log.Error("[yourturn] Cannot calcMasternodes at gap num ", "err", err, "parent number", parent.Number)
return false, err

View file

@ -115,7 +115,7 @@ func (x *XDPoS_v2) verifyHeader(chain consensus.ChainReader, header *types.Heade
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
if err != nil {
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)
}
/*
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) {
b, err := json.Marshal(params.TestXDPoSMockChainConfig)
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
index := int(header.Number.Int64() - int64(q.resultOffset))
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")
return nil, false, errInvalidChain
}

View file

@ -37,9 +37,9 @@ func AttachConsensusV2Hooks(adaptor *XDPoS.XDPoS, bc *core.BlockChain, chainConf
break
}
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)
return []common.Address{}, fmt.Errorf("parentHeader is nil")
}

View file

@ -23,7 +23,7 @@ import (
const (
VersionMajor = 2 // Major 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
)