Merge pull request #385 from XinFinOrg/dev-upgrade

Dev upgrade resolve sync issue
This commit is contained in:
Liam 2023-12-30 01:21:34 +11:00 committed by GitHub
commit 42f0f649ed
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 325 additions and 25 deletions

View file

@ -433,6 +433,15 @@ func (x *XDPoS) GetCurrentEpochSwitchBlock(chain consensus.ChainReader, blockNum
} }
} }
func (x *XDPoS) CalculateMissingRounds(chain consensus.ChainReader, header *types.Header) (*utils.PublicApiMissedRoundsMetadata, error) {
switch x.config.BlockConsensusVersion(header.Number, header.Extra, ExtraFieldCheck) {
case params.ConsensusEngineVersion2:
return x.EngineV2.CalculateMissingRounds(chain, header)
default: // Default "v1"
return nil, fmt.Errorf("Not supported in the v1 consensus")
}
}
// Same DB across all consensus engines // Same DB across all consensus engines
func (x *XDPoS) GetDb() ethdb.Database { func (x *XDPoS) GetDb() ethdb.Database {
return x.db return x.db

View file

@ -23,6 +23,7 @@ import (
"github.com/XinFinOrg/XDPoSChain/consensus" "github.com/XinFinOrg/XDPoSChain/consensus"
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils" "github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
"github.com/XinFinOrg/XDPoSChain/core/types" "github.com/XinFinOrg/XDPoSChain/core/types"
"github.com/XinFinOrg/XDPoSChain/params"
"github.com/XinFinOrg/XDPoSChain/rlp" "github.com/XinFinOrg/XDPoSChain/rlp"
"github.com/XinFinOrg/XDPoSChain/rpc" "github.com/XinFinOrg/XDPoSChain/rpc"
) )
@ -53,6 +54,7 @@ type NetworkInformation struct {
XDCXListingAddress common.Address XDCXListingAddress common.Address
XDCZAddress common.Address XDCZAddress common.Address
LendingAddress common.Address LendingAddress common.Address
ConsensusConfigs params.XDPoSConfig
} }
type SignerTypes struct { type SignerTypes struct {
@ -222,16 +224,7 @@ func (api *API) GetV2BlockByHeader(header *types.Header, uncle bool) *V2BlockInf
} }
func (api *API) GetV2BlockByNumber(number *rpc.BlockNumber) *V2BlockInfo { func (api *API) GetV2BlockByNumber(number *rpc.BlockNumber) *V2BlockInfo {
var header *types.Header header := api.getHeaderFromApiBlockNum(number)
if number == nil || *number == rpc.LatestBlockNumber {
header = api.chain.CurrentHeader()
} else if *number == rpc.CommittedBlockNumber {
hash := api.XDPoS.EngineV2.GetLatestCommittedBlockInfo().Hash
header = api.chain.GetHeaderByHash(hash)
} else {
header = api.chain.GetHeaderByNumber(uint64(number.Int64()))
}
if header == nil { if header == nil {
return &V2BlockInfo{ return &V2BlockInfo{
Number: big.NewInt(number.Int64()), Number: big.NewInt(number.Int64()),
@ -278,9 +271,31 @@ func (api *API) NetworkInformation() NetworkInformation {
info.XDCXListingAddress = common.XDCXListingSMC info.XDCXListingAddress = common.XDCXListingSMC
info.XDCZAddress = common.TRC21IssuerSMC info.XDCZAddress = common.TRC21IssuerSMC
} }
info.ConsensusConfigs = *api.XDPoS.config
return info return info
} }
/*
An API exclusively for V2 consensus, designed to assist in troubleshooting miners by identifying who mined during their allocated term.
*/
func (api *API) GetMissedRoundsInEpochByBlockNum(number *rpc.BlockNumber) (*utils.PublicApiMissedRoundsMetadata, error) {
return api.XDPoS.CalculateMissingRounds(api.chain, api.getHeaderFromApiBlockNum(number))
}
func (api *API) getHeaderFromApiBlockNum(number *rpc.BlockNumber) *types.Header {
var header *types.Header
if number == nil || *number == rpc.LatestBlockNumber {
header = api.chain.CurrentHeader()
} else if *number == rpc.CommittedBlockNumber {
hash := api.XDPoS.EngineV2.GetLatestCommittedBlockInfo().Hash
header = api.chain.GetHeaderByHash(hash)
} else {
header = api.chain.GetHeaderByNumber(uint64(number.Int64()))
}
return header
}
func calculateSigners(message map[string]SignerTypes, pool map[string]map[common.Hash]utils.PoolObj, masternodes []common.Address) { func calculateSigners(message map[string]SignerTypes, pool map[string]map[common.Hash]utils.PoolObj, masternodes []common.Address) {
for name, objs := range pool { for name, objs := range pool {
var currentSigners []common.Address var currentSigners []common.Address

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
} }
@ -360,7 +360,7 @@ func (x *XDPoS_v2) Prepare(chain consensus.ChainReader, header *types.Header) er
} }
if header.Coinbase != signer { if header.Coinbase != signer {
log.Error("[Prepare] The mined blocker header coinbase address mismatch with waller address", "headerCoinbase", header.Coinbase.Hex(), "WalletAddress", signer.Hex()) log.Error("[Prepare] The mined blocker header coinbase address mismatch with wallet address", "headerCoinbase", header.Coinbase.Hex(), "WalletAddress", signer.Hex())
return consensus.ErrCoinbaseMismatch return consensus.ErrCoinbaseMismatch
} }
@ -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

@ -163,3 +163,54 @@ func (x *XDPoS_v2) GetSignersFromSnapshot(chain consensus.ChainReader, header *t
snap, err := x.getSnapshot(chain, header.Number.Uint64(), false) snap, err := x.getSnapshot(chain, header.Number.Uint64(), false)
return snap.NextEpochMasterNodes, err return snap.NextEpochMasterNodes, err
} }
func (x *XDPoS_v2) CalculateMissingRounds(chain consensus.ChainReader, header *types.Header) (*utils.PublicApiMissedRoundsMetadata, error) {
var missedRounds []utils.MissedRoundInfo
switchInfo, err := x.getEpochSwitchInfo(chain, header, header.Hash())
if err != nil {
return nil, err
}
masternodes := switchInfo.Masternodes
// Loop through from the epoch switch block to the current "header" block
nextHeader := header
for nextHeader.Number.Cmp(switchInfo.EpochSwitchBlockInfo.Number) > 0 {
parentHeader := chain.GetHeaderByHash(nextHeader.ParentHash)
parentRound, err := x.GetRoundNumber(parentHeader)
if err != nil {
return nil, err
}
currRound, err := x.GetRoundNumber(nextHeader)
if err != nil {
return nil, err
}
// This indicates that an increment in the round number is missing during the block production process.
if parentRound+1 != currRound {
// We need to iterate from the parentRound to the currRound to determine which miner did not perform mining.
for i := parentRound + 1; i < currRound; i++ {
leaderIndex := uint64(i) % x.config.Epoch % uint64(len(masternodes))
whosTurn := masternodes[leaderIndex]
missedRounds = append(
missedRounds,
utils.MissedRoundInfo{
Round: i,
Miner: whosTurn,
CurrentBlockHash: nextHeader.Hash(),
CurrentBlockNum: nextHeader.Number,
ParentBlockHash: parentHeader.Hash(),
ParentBlockNum: parentHeader.Number,
},
)
}
}
// Assign the pointer to the next one
nextHeader = parentHeader
}
missedRoundsMetadata := &utils.PublicApiMissedRoundsMetadata{
EpochRound: switchInfo.EpochSwitchBlockInfo.Round,
EpochBlockNumber: switchInfo.EpochSwitchBlockInfo.Number,
MissedRounds: missedRounds,
}
return missedRoundsMetadata, nil
}

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

@ -193,7 +193,7 @@ func (x *XDPoS_v2) onVotePoolThresholdReached(chain consensus.ChainReader, poole
func (x *XDPoS_v2) verifyVotingRule(blockChainReader consensus.ChainReader, blockInfo *types.BlockInfo, quorumCert *types.QuorumCert) (bool, error) { func (x *XDPoS_v2) verifyVotingRule(blockChainReader consensus.ChainReader, blockInfo *types.BlockInfo, quorumCert *types.QuorumCert) (bool, error) {
// Make sure this node has not voted for this round. // Make sure this node has not voted for this round.
if x.currentRound <= x.highestVotedRound { if x.currentRound <= x.highestVotedRound {
log.Warn("Failed to pass the voting rule verification, currentRound is not large then highestVoteRound", "x.currentRound", x.currentRound, "x.highestVotedRound", x.highestVotedRound) log.Info("Failed to pass the voting rule verification, currentRound is not large then highestVoteRound", "x.currentRound", x.currentRound, "x.highestVotedRound", x.highestVotedRound)
return false, nil return false, nil
} }
/* /*
@ -203,7 +203,7 @@ func (x *XDPoS_v2) verifyVotingRule(blockChainReader consensus.ChainReader, bloc
header's QC's ProposedBlockInfo.Round > lockQuorumCert's ProposedBlockInfo.Round header's QC's ProposedBlockInfo.Round > lockQuorumCert's ProposedBlockInfo.Round
*/ */
if blockInfo.Round != x.currentRound { if blockInfo.Round != x.currentRound {
log.Warn("Failed to pass the voting rule verification, blockRound is not equal currentRound", "x.currentRound", x.currentRound, "blockInfo.Round", blockInfo.Round) log.Info("Failed to pass the voting rule verification, blockRound is not equal currentRound", "x.currentRound", x.currentRound, "blockInfo.Round", blockInfo.Round)
return false, nil return false, nil
} }
// XDPoS v1.0 switch to v2.0, the proposed block can always pass voting rule // XDPoS v1.0 switch to v2.0, the proposed block can always pass voting rule

View file

@ -57,3 +57,17 @@ type PublicApiSnapshot struct {
Votes []*clique.Vote `json:"votes"` // List of votes cast in chronological order Votes []*clique.Vote `json:"votes"` // List of votes cast in chronological order
Tally map[common.Address]clique.Tally `json:"tally"` // Current vote tally to avoid recalculating Tally map[common.Address]clique.Tally `json:"tally"` // Current vote tally to avoid recalculating
} }
type MissedRoundInfo struct {
Round types.Round
Miner common.Address
CurrentBlockHash common.Hash
CurrentBlockNum *big.Int
ParentBlockHash common.Hash
ParentBlockNum *big.Int
}
type PublicApiMissedRoundsMetadata struct {
EpochRound types.Round
EpochBlockNumber *big.Int
MissedRounds []MissedRoundInfo
}

View file

@ -0,0 +1,34 @@
package tests
import (
"math/big"
"testing"
"github.com/XinFinOrg/XDPoSChain/accounts/abi/bind/backends"
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
"github.com/XinFinOrg/XDPoSChain/core"
"github.com/XinFinOrg/XDPoSChain/crypto"
"github.com/XinFinOrg/XDPoSChain/params"
"github.com/stretchr/testify/assert"
)
var (
voterKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee04aefe388d1e14474d32c45c72ce7b7a")
voterAddr = crypto.PubkeyToAddress(voterKey.PublicKey) //xdc5F74529C0338546f82389402a01c31fB52c6f434
)
func TestConfigApi(t *testing.T) {
bc := backends.NewXDCSimulatedBackend(core.GenesisAlloc{
voterAddr: {Balance: new(big.Int).SetUint64(10000000000)},
}, 10000000, params.TestXDPoSMockChainConfig)
engine := bc.GetBlockChain().Engine().(*XDPoS.XDPoS)
info := engine.APIs(bc.GetBlockChain())[0].Service.(*XDPoS.API).NetworkInformation()
assert.Equal(t, info.NetworkId, big.NewInt(1337))
assert.Equal(t, info.ConsensusConfigs.V2.CurrentConfig.MaxMasternodes, 18)
assert.Equal(t, info.ConsensusConfigs.V2.CurrentConfig.CertThreshold, 0.667)
assert.Equal(t, info.ConsensusConfigs.V2.CurrentConfig.MinePeriod, 2)
assert.Equal(t, info.ConsensusConfigs.V2.CurrentConfig.TimeoutSyncThreshold, 2)
}

View file

@ -0,0 +1,111 @@
package engine_v2_tests
import (
"math/big"
"testing"
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
"github.com/XinFinOrg/XDPoSChain/core/types"
"github.com/XinFinOrg/XDPoSChain/params"
"github.com/XinFinOrg/XDPoSChain/rpc"
"github.com/stretchr/testify/assert"
)
func TestGetMissedRoundsInEpochByBlockNumOnlyForV2Consensus(t *testing.T) {
_, bc, _, _, _ := PrepareXDCTestBlockChainWith128Candidates(t, 1802, params.TestXDPoSMockChainConfig)
engine := bc.GetBlockChain().Engine().(*XDPoS.XDPoS)
blockNum := rpc.BlockNumber(123)
data, err := engine.APIs(bc.GetBlockChain())[0].Service.(*XDPoS.API).GetMissedRoundsInEpochByBlockNum(&blockNum)
assert.EqualError(t, err, "Not supported in the v1 consensus")
assert.Nil(t, data)
}
func TestGetMissedRoundsInEpochByBlockNumReturnEmptyForV2(t *testing.T) {
_, bc, cb, _, _ := PrepareXDCTestBlockChainWith128Candidates(t, 1802, params.TestXDPoSMockChainConfig)
engine := bc.GetBlockChain().Engine().(*XDPoS.XDPoS)
blockNum := rpc.BlockNumber(cb.NumberU64())
data, err := engine.APIs(bc.GetBlockChain())[0].Service.(*XDPoS.API).GetMissedRoundsInEpochByBlockNum(&blockNum)
assert.Nil(t, err)
assert.Equal(t, types.Round(900), data.EpochRound)
assert.Equal(t, big.NewInt(1800), data.EpochBlockNumber)
assert.Equal(t, 0, len(data.MissedRounds))
blockNum = rpc.BlockNumber(1800)
data, err = engine.APIs(bc.GetBlockChain())[0].Service.(*XDPoS.API).GetMissedRoundsInEpochByBlockNum(&blockNum)
assert.Nil(t, err)
assert.Equal(t, types.Round(900), data.EpochRound)
assert.Equal(t, big.NewInt(1800), data.EpochBlockNumber)
assert.Equal(t, 0, len(data.MissedRounds))
blockNum = rpc.BlockNumber(1801)
data, err = engine.APIs(bc.GetBlockChain())[0].Service.(*XDPoS.API).GetMissedRoundsInEpochByBlockNum(&blockNum)
assert.Nil(t, err)
assert.Equal(t, types.Round(900), data.EpochRound)
assert.Equal(t, big.NewInt(1800), data.EpochBlockNumber)
assert.Equal(t, 0, len(data.MissedRounds))
}
func TestGetMissedRoundsInEpochByBlockNumReturnEmptyForV2FistEpoch(t *testing.T) {
_, bc, _, _, _ := PrepareXDCTestBlockChainWith128Candidates(t, 1802, params.TestXDPoSMockChainConfig)
engine := bc.GetBlockChain().Engine().(*XDPoS.XDPoS)
blockNum := rpc.BlockNumber(901)
data, err := engine.APIs(bc.GetBlockChain())[0].Service.(*XDPoS.API).GetMissedRoundsInEpochByBlockNum(&blockNum)
assert.Nil(t, err)
assert.Equal(t, types.Round(1), data.EpochRound)
assert.Equal(t, big.NewInt(901), data.EpochBlockNumber)
assert.Equal(t, 0, len(data.MissedRounds))
}
func TestGetMissedRoundsInEpochByBlockNum(t *testing.T) {
blockchain, bc, currentBlock, signer, signFn := PrepareXDCTestBlockChainWith128Candidates(t, 1802, params.TestXDPoSMockChainConfig)
chainConfig := params.TestXDPoSMockChainConfig
engine := bc.GetBlockChain().Engine().(*XDPoS.XDPoS)
blockCoinBase := signer.Hex()
startingBlockNum := currentBlock.Number().Int64() + 1
// Skipped the round
roundNumber := startingBlockNum - chainConfig.XDPoS.V2.SwitchBlock.Int64() + 2
block := CreateBlock(blockchain, chainConfig, currentBlock, int(startingBlockNum), roundNumber, blockCoinBase, signer, signFn, nil, nil, "b345a8560bd51926803dd17677c9f0751193914a851a4ec13063d6bf50220b53")
err := blockchain.InsertBlock(block)
if err != nil {
t.Fatal(err)
}
// Update Signer as there is no previous signer assigned
err = UpdateSigner(blockchain)
if err != nil {
t.Fatal(err)
}
blockNum := rpc.BlockNumber(1803)
data, err := engine.APIs(bc.GetBlockChain())[0].Service.(*XDPoS.API).GetMissedRoundsInEpochByBlockNum(&blockNum)
assert.Nil(t, err)
assert.Equal(t, types.Round(900), data.EpochRound)
assert.Equal(t, big.NewInt(1800), data.EpochBlockNumber)
assert.Equal(t, 2, len(data.MissedRounds))
assert.NotEmpty(t, data.MissedRounds[0].Miner)
assert.Equal(t, data.MissedRounds[0].Round, types.Round(903))
assert.Equal(t, data.MissedRounds[0].CurrentBlockNum, big.NewInt(1803))
assert.Equal(t, data.MissedRounds[0].ParentBlockNum, big.NewInt(1802))
assert.NotEmpty(t, data.MissedRounds[1].Miner)
assert.Equal(t, data.MissedRounds[1].Round, types.Round(904))
assert.Equal(t, data.MissedRounds[0].CurrentBlockNum, big.NewInt(1803))
assert.Equal(t, data.MissedRounds[0].ParentBlockNum, big.NewInt(1802))
assert.NotEqual(t, data.MissedRounds[0].Miner, data.MissedRounds[1].Miner)
}

View file

@ -545,6 +545,18 @@ func PrepareXDCTestBlockChainWith128Candidates(t *testing.T, numOfBlocks int, ch
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
// First v2 block
if (int64(i) - chainConfig.XDPoS.V2.SwitchBlock.Int64()) == 1 {
lastv1BlockNumber := block.Header().Number.Uint64() - 1
checkpointBlockNumber := lastv1BlockNumber - lastv1BlockNumber%chainConfig.XDPoS.Epoch
checkpointHeader := blockchain.GetHeaderByNumber(checkpointBlockNumber)
err := engine.EngineV2.Initial(blockchain, checkpointHeader)
if err != nil {
panic(err)
}
}
currentBlock = block currentBlock = block
} }

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

@ -146,6 +146,9 @@ func (q *queue) Reset() {
// Close marks the end of the sync, unblocking WaitResults. // Close marks the end of the sync, unblocking WaitResults.
// It may be called even if the queue is already closed. // It may be called even if the queue is already closed.
func (q *queue) Close() { func (q *queue) Close() {
q.lock.Lock()
defer q.lock.Unlock()
q.closed = true q.closed = true
q.active.Broadcast() q.active.Broadcast()
} }
@ -507,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

@ -156,6 +156,12 @@ web3._extend({
name: 'getLatestPoolStatus', name: 'getLatestPoolStatus',
call: 'XDPoS_getLatestPoolStatus' call: 'XDPoS_getLatestPoolStatus'
}), }),
new web3._extend.Method({
name: 'getMissedRoundsInEpochByBlockNum',
call: 'XDPoS_getMissedRoundsInEpochByBlockNum',
params: 1,
inputFormatter: [web3._extend.formatters.inputBlockNumberFormatter]
}),
], ],
properties: [ properties: [
new web3._extend.Property({ new web3._extend.Property({

View file

@ -21,10 +21,10 @@ import (
) )
const ( const (
VersionMajor = 1 // Major version component of the current release VersionMajor = 2 // Major version component of the current release
VersionMinor = 5 // 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 = "" // Version metadata to append to the version string VersionMeta = "beta1" // Version metadata to append to the version string
) )
// Version holds the textual version string. // Version holds the textual version string.