mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-22 06:34:32 +00:00
Merge pull request #385 from XinFinOrg/dev-upgrade
Dev upgrade resolve sync issue
This commit is contained in:
commit
42f0f649ed
16 changed files with 325 additions and 25 deletions
|
|
@ -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
|
||||
func (x *XDPoS) GetDb() ethdb.Database {
|
||||
return x.db
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/consensus"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
"github.com/XinFinOrg/XDPoSChain/params"
|
||||
"github.com/XinFinOrg/XDPoSChain/rlp"
|
||||
"github.com/XinFinOrg/XDPoSChain/rpc"
|
||||
)
|
||||
|
|
@ -53,6 +54,7 @@ type NetworkInformation struct {
|
|||
XDCXListingAddress common.Address
|
||||
XDCZAddress common.Address
|
||||
LendingAddress common.Address
|
||||
ConsensusConfigs params.XDPoSConfig
|
||||
}
|
||||
|
||||
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 {
|
||||
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()))
|
||||
}
|
||||
|
||||
header := api.getHeaderFromApiBlockNum(number)
|
||||
if header == nil {
|
||||
return &V2BlockInfo{
|
||||
Number: big.NewInt(number.Int64()),
|
||||
|
|
@ -278,9 +271,31 @@ func (api *API) NetworkInformation() NetworkInformation {
|
|||
info.XDCXListingAddress = common.XDCXListingSMC
|
||||
info.XDCZAddress = common.TRC21IssuerSMC
|
||||
}
|
||||
info.ConsensusConfigs = *api.XDPoS.config
|
||||
|
||||
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) {
|
||||
for name, objs := range pool {
|
||||
var currentSigners []common.Address
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -360,7 +360,7 @@ func (x *XDPoS_v2) Prepare(chain consensus.ChainReader, header *types.Header) er
|
|||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -163,3 +163,54 @@ func (x *XDPoS_v2) GetSignersFromSnapshot(chain consensus.ChainReader, header *t
|
|||
snap, err := x.getSnapshot(chain, header.Number.Uint64(), false)
|
||||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
// Make sure this node has not voted for this round.
|
||||
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
|
||||
}
|
||||
/*
|
||||
|
|
@ -203,7 +203,7 @@ func (x *XDPoS_v2) verifyVotingRule(blockChainReader consensus.ChainReader, bloc
|
|||
header's QC's ProposedBlockInfo.Round > lockQuorumCert's ProposedBlockInfo.Round
|
||||
*/
|
||||
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
|
||||
}
|
||||
// XDPoS v1.0 switch to v2.0, the proposed block can always pass voting rule
|
||||
|
|
|
|||
|
|
@ -57,3 +57,17 @@ type PublicApiSnapshot struct {
|
|||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
|
|
|||
34
consensus/tests/api_test.go
Normal file
34
consensus/tests/api_test.go
Normal 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)
|
||||
}
|
||||
111
consensus/tests/engine_v2_tests/api_test.go
Normal file
111
consensus/tests/engine_v2_tests/api_test.go
Normal 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)
|
||||
}
|
||||
|
|
@ -545,6 +545,18 @@ func PrepareXDCTestBlockChainWith128Candidates(t *testing.T, numOfBlocks int, ch
|
|||
if err != nil {
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -146,6 +146,9 @@ func (q *queue) Reset() {
|
|||
// Close marks the end of the sync, unblocking WaitResults.
|
||||
// It may be called even if the queue is already closed.
|
||||
func (q *queue) Close() {
|
||||
q.lock.Lock()
|
||||
defer q.lock.Unlock()
|
||||
|
||||
q.closed = true
|
||||
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
|
||||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,6 +156,12 @@ web3._extend({
|
|||
name: 'getLatestPoolStatus',
|
||||
call: 'XDPoS_getLatestPoolStatus'
|
||||
}),
|
||||
new web3._extend.Method({
|
||||
name: 'getMissedRoundsInEpochByBlockNum',
|
||||
call: 'XDPoS_getMissedRoundsInEpochByBlockNum',
|
||||
params: 1,
|
||||
inputFormatter: [web3._extend.formatters.inputBlockNumberFormatter]
|
||||
}),
|
||||
],
|
||||
properties: [
|
||||
new web3._extend.Property({
|
||||
|
|
|
|||
|
|
@ -21,10 +21,10 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
VersionMajor = 1 // Major version component of the current release
|
||||
VersionMinor = 5 // Minor version component of the current release
|
||||
VersionPatch = 0 // Patch version component of the current release
|
||||
VersionMeta = "" // Version metadata to append to the version string
|
||||
VersionMajor = 2 // Major version component of the current release
|
||||
VersionMinor = 0 // Minor 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
|
||||
)
|
||||
|
||||
// Version holds the textual version string.
|
||||
|
|
|
|||
Loading…
Reference in a new issue