mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 21:31:37 +00:00
Multi config bug fix (#216)
* refactor multi config remove pool cleaner correct message and log level
This commit is contained in:
parent
96339ec3ba
commit
c4f9a552e5
23 changed files with 319 additions and 200 deletions
|
|
@ -346,7 +346,8 @@ func startNode(ctx *cli.Context, stack *node.Node, cfg XDCConfig) {
|
|||
for range core.CheckpointCh {
|
||||
log.Info("Checkpoint!!! It's time to reconcile node's state...")
|
||||
log.Info("Update consensus parameters")
|
||||
engine.UpdateParams()
|
||||
chain := ethereum.BlockChain()
|
||||
engine.UpdateParams(chain.CurrentHeader())
|
||||
if common.IsTestnet {
|
||||
ok, err = ethereum.ValidateMasternodeTestnet()
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
ExtraFieldCheck = false
|
||||
SkipExtraFieldCheck = true
|
||||
ExtraFieldCheck = true
|
||||
SkipExtraFieldCheck = false
|
||||
)
|
||||
|
||||
func (x *XDPoS) SigHash(header *types.Header) (hash common.Hash) {
|
||||
|
|
@ -79,7 +79,7 @@ func (x *XDPoS) SubscribeForensicsEvent(ch chan<- types.ForensicsEvent) event.Su
|
|||
// New creates a XDPoS delegated-proof-of-stake consensus engine with the initial
|
||||
// signers set to the ones provided by the user.
|
||||
func New(config *params.XDPoSConfig, db ethdb.Database) *XDPoS {
|
||||
log.Info("[New] initial conensus engines")
|
||||
log.Info("[New] initialise consensus engines")
|
||||
// Set any missing consensus parameters to their defaults
|
||||
if config.Epoch == 0 {
|
||||
config.Epoch = utils.EpochLength
|
||||
|
|
@ -88,9 +88,9 @@ func New(config *params.XDPoSConfig, db ethdb.Database) *XDPoS {
|
|||
// For testing and testing project, default to mainnet config
|
||||
if config.V2 == nil {
|
||||
config.V2 = ¶ms.V2{
|
||||
FirstSwitchBlock: params.MainnetV2Configs[0].SwitchBlock,
|
||||
CurrentConfig: params.MainnetV2Configs[0],
|
||||
AllConfigs: params.MainnetV2Configs,
|
||||
SwitchBlock: params.XDCMainnetChainConfig.XDPoS.V2.SwitchBlock,
|
||||
CurrentConfig: params.MainnetV2Configs[0],
|
||||
AllConfigs: params.MainnetV2Configs,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -145,8 +145,14 @@ func NewFaker(db ethdb.Database, chainConfig *params.ChainConfig) *XDPoS {
|
|||
}
|
||||
|
||||
// Reset parameters after checkpoint due to config may change
|
||||
func (x *XDPoS) UpdateParams() {
|
||||
x.EngineV2.UpdateParams()
|
||||
func (x *XDPoS) UpdateParams(header *types.Header) {
|
||||
switch x.config.BlockConsensusVersion(header.Number, header.Extra, ExtraFieldCheck) {
|
||||
case params.ConsensusEngineVersion2:
|
||||
x.EngineV2.UpdateParams(header)
|
||||
return
|
||||
default: // Default "v1"
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (x *XDPoS) Initial(chain consensus.ChainReader, header *types.Header) error {
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ func New(config *params.XDPoSConfig, db ethdb.Database, waitPeriodCh chan int) *
|
|||
timeoutTimer.OnTimeoutFn = engine.OnCountdownTimeout
|
||||
|
||||
engine.periodicJob()
|
||||
config.BuildConfigIndex()
|
||||
config.V2.BuildConfigIndex()
|
||||
|
||||
return engine
|
||||
}
|
||||
|
|
@ -131,7 +131,13 @@ signing. It is the hash of the entire header apart from the 65 byte signature
|
|||
contained at the end of the extra data.
|
||||
*/
|
||||
|
||||
func (x *XDPoS_v2) UpdateParams() {
|
||||
func (x *XDPoS_v2) UpdateParams(header *types.Header) {
|
||||
_, round, _, err := x.getExtraFields(header)
|
||||
if err != nil {
|
||||
log.Error("[UpdateParams] retrieve round failed", "block", header.Number.Uint64(), "err", err)
|
||||
}
|
||||
x.config.V2.UpdateConfig(uint64(round))
|
||||
|
||||
// Setup timeoutTimer
|
||||
duration := time.Duration(x.config.V2.CurrentConfig.TimeoutPeriod) * time.Second
|
||||
x.timeoutWorker.SetTimeoutDuration(duration)
|
||||
|
|
@ -163,7 +169,7 @@ func (x *XDPoS_v2) initial(chain consensus.ChainReader, header *types.Header) er
|
|||
var quorumCert *types.QuorumCert
|
||||
var err error
|
||||
|
||||
if header.Number.Int64() == x.config.V2.FirstSwitchBlock.Int64() {
|
||||
if header.Number.Int64() == x.config.V2.SwitchBlock.Int64() {
|
||||
log.Info("[initial] highest QC for consensus v2 first block")
|
||||
blockInfo := &types.BlockInfo{
|
||||
Hash: header.Hash(),
|
||||
|
|
@ -193,13 +199,13 @@ func (x *XDPoS_v2) initial(chain consensus.ChainReader, header *types.Header) er
|
|||
}
|
||||
|
||||
// Initial first v2 snapshot
|
||||
lastGapNum := x.config.V2.FirstSwitchBlock.Uint64() - x.config.Gap
|
||||
lastGapNum := x.config.V2.SwitchBlock.Uint64() - x.config.Gap
|
||||
lastGapHeader := chain.GetHeaderByNumber(lastGapNum)
|
||||
|
||||
snap, _ := loadSnapshot(x.db, lastGapHeader.Hash())
|
||||
|
||||
if snap == nil {
|
||||
checkpointHeader := chain.GetHeaderByNumber(x.config.V2.FirstSwitchBlock.Uint64())
|
||||
checkpointHeader := chain.GetHeaderByNumber(x.config.V2.SwitchBlock.Uint64())
|
||||
|
||||
log.Info("[initial] init first snapshot")
|
||||
_, _, masternodes, err := x.getExtraFields(checkpointHeader)
|
||||
|
|
@ -246,7 +252,9 @@ func (x *XDPoS_v2) YourTurn(chain consensus.ChainReader, parent *types.Header, s
|
|||
}
|
||||
|
||||
waitedTime := time.Now().Unix() - parent.Time.Int64()
|
||||
if waitedTime < int64(x.config.V2.CurrentConfig.MinePeriod) {
|
||||
_, parentRound, _, err := x.getExtraFields(parent)
|
||||
minePeriod := x.config.V2.Config(uint64(parentRound) + 1).MinePeriod // plus 1 means current block
|
||||
if waitedTime < int64(minePeriod) {
|
||||
log.Trace("[YourTurn] wait after mine period", "minePeriod", x.config.V2.CurrentConfig.MinePeriod, "waitedTime", waitedTime)
|
||||
return false, nil
|
||||
}
|
||||
|
|
@ -718,7 +726,7 @@ func (x *XDPoS_v2) VerifyBlockInfo(blockChainReader consensus.ChainReader, block
|
|||
}
|
||||
|
||||
// Switch block is a v1 block, there is no valid extra to decode, nor its round
|
||||
if blockInfo.Number.Cmp(x.config.V2.FirstSwitchBlock) == 0 {
|
||||
if blockInfo.Number.Cmp(x.config.V2.SwitchBlock) == 0 {
|
||||
if blockInfo.Round != 0 {
|
||||
log.Error("[VerifyBlockInfo] Switch block round is not 0", "BlockInfoHash", blockInfo.Hash.Hex(), "BlockInfoNum", blockInfo.Number, "BlockInfoRound", blockInfo.Round, "blockHeaderNum", blockHeader.Number)
|
||||
return fmt.Errorf("[VerifyBlockInfo] switch block round have to be 0")
|
||||
|
|
@ -751,6 +759,12 @@ func (x *XDPoS_v2) verifyQC(blockChainReader consensus.ChainReader, quorumCert *
|
|||
4. Verify gapNumber = epochSwitchNumber - epochSwitchNumber%Epoch - Gap
|
||||
5. Verify blockInfo
|
||||
*/
|
||||
|
||||
if quorumCert == nil {
|
||||
log.Warn("[verifyQC] QC is Nil")
|
||||
return utils.ErrInvalidQC
|
||||
}
|
||||
|
||||
epochInfo, err := x.getEpochSwitchInfo(blockChainReader, parentHeader, quorumCert.ProposedBlockInfo.Hash)
|
||||
if err != nil {
|
||||
log.Error("[verifyQC] Error when getting epoch switch Info to verify QC", "Error", err)
|
||||
|
|
@ -763,13 +777,13 @@ func (x *XDPoS_v2) verifyQC(blockChainReader consensus.ChainReader, quorumCert *
|
|||
log.Warn("[verifyQC] duplicated signature in QC", "duplicate", common.Bytes2Hex(d))
|
||||
}
|
||||
}
|
||||
if quorumCert == nil {
|
||||
log.Warn("[verifyQC] QC is Nil")
|
||||
return utils.ErrInvalidQC
|
||||
} else if (quorumCert.ProposedBlockInfo.Number.Uint64() > x.config.V2.FirstSwitchBlock.Uint64()) && (signatures == nil || (len(signatures) < x.config.V2.CurrentConfig.CertThreshold)) {
|
||||
|
||||
qcRound := quorumCert.ProposedBlockInfo.Round
|
||||
certThreshold := x.config.V2.Config(uint64(qcRound)).CertThreshold
|
||||
if (qcRound > 0) && (signatures == nil || (len(signatures) < certThreshold)) {
|
||||
//First V2 Block QC, QC Signatures is initial nil
|
||||
log.Warn("[verifyHeader] Invalid QC Signature is nil or empty", "QC", quorumCert, "QCNumber", quorumCert.ProposedBlockInfo.Number, "Signatures len", len(signatures))
|
||||
return utils.ErrInvalidQC
|
||||
log.Warn("[verifyHeader] Invalid QC Signature is nil or less then config", "QC", quorumCert, "QCNumber", quorumCert.ProposedBlockInfo.Number, "Signatures len", len(signatures), "CertThreshold", certThreshold)
|
||||
return utils.ErrInvalidQCSignatures
|
||||
}
|
||||
start := time.Now()
|
||||
|
||||
|
|
@ -798,7 +812,7 @@ func (x *XDPoS_v2) verifyQC(blockChainReader consensus.ChainReader, quorumCert *
|
|||
}
|
||||
wg.Wait()
|
||||
elapsed := time.Since(start)
|
||||
log.Info("[verifyQC] time verify message signatures of qc", "elapsed", elapsed)
|
||||
log.Debug("[verifyQC] time verify message signatures of qc", "elapsed", elapsed)
|
||||
if haveError != nil {
|
||||
return haveError
|
||||
}
|
||||
|
|
@ -826,7 +840,7 @@ func (x *XDPoS_v2) processQC(blockChainReader consensus.ChainReader, incomingQuo
|
|||
log.Error("[processQC] Block not found using the QC", "quorumCert.ProposedBlockInfo.Hash", incomingQuorumCert.ProposedBlockInfo.Hash, "incomingQuorumCert.ProposedBlockInfo.Number", incomingQuorumCert.ProposedBlockInfo.Number)
|
||||
return fmt.Errorf("block not found, number: %v, hash: %v", incomingQuorumCert.ProposedBlockInfo.Number, incomingQuorumCert.ProposedBlockInfo.Hash)
|
||||
}
|
||||
if proposedBlockHeader.Number.Cmp(x.config.V2.FirstSwitchBlock) > 0 {
|
||||
if proposedBlockHeader.Number.Cmp(x.config.V2.SwitchBlock) > 0 {
|
||||
// Extra field contain parent information
|
||||
proposedBlockQuorumCert, round, _, err := x.getExtraFields(proposedBlockHeader)
|
||||
if err != nil {
|
||||
|
|
@ -882,7 +896,7 @@ func (x *XDPoS_v2) getSyncInfo() *types.SyncInfo {
|
|||
//Find parent and grandparent, check round number, if so, commit grandparent(grandGrandParent of currentBlock)
|
||||
func (x *XDPoS_v2) commitBlocks(blockChainReader consensus.ChainReader, proposedBlockHeader *types.Header, proposedBlockRound *types.Round, incomingQc *types.QuorumCert) (bool, error) {
|
||||
// XDPoS v1.0 switch to v2.0, skip commit
|
||||
if big.NewInt(0).Sub(proposedBlockHeader.Number, big.NewInt(2)).Cmp(x.config.V2.FirstSwitchBlock) <= 0 {
|
||||
if big.NewInt(0).Sub(proposedBlockHeader.Number, big.NewInt(2)).Cmp(x.config.V2.SwitchBlock) <= 0 {
|
||||
return false, nil
|
||||
}
|
||||
// Find the last two parent block and check their rounds are the continuous
|
||||
|
|
@ -959,7 +973,7 @@ func (x *XDPoS_v2) calcMasternodes(chain consensus.ChainReader, blockNum *big.In
|
|||
}
|
||||
candidates := snap.NextEpochMasterNodes
|
||||
|
||||
if blockNum.Uint64() == x.config.V2.FirstSwitchBlock.Uint64()+1 {
|
||||
if blockNum.Uint64() == x.config.V2.SwitchBlock.Uint64()+1 {
|
||||
log.Info("[calcMasternodes] examing first v2 block")
|
||||
return candidates, []common.Address{}, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,9 +82,9 @@ func (x *XDPoS_v2) getEpochSwitchInfo(chain consensus.ChainReader, header *types
|
|||
|
||||
// IsEpochSwitchAtRound() is used by miner to check whether it mines a block in the same epoch with parent
|
||||
func (x *XDPoS_v2) isEpochSwitchAtRound(round types.Round, parentHeader *types.Header) (bool, uint64, error) {
|
||||
epochNum := x.config.V2.FirstSwitchBlock.Uint64()/x.config.Epoch + uint64(round)/x.config.Epoch
|
||||
epochNum := x.config.V2.SwitchBlock.Uint64()/x.config.Epoch + uint64(round)/x.config.Epoch
|
||||
// if parent is last v1 block and this is first v2 block, this is treated as epoch switch
|
||||
if parentHeader.Number.Cmp(x.config.V2.FirstSwitchBlock) == 0 {
|
||||
if parentHeader.Number.Cmp(x.config.V2.SwitchBlock) == 0 {
|
||||
return true, epochNum, nil
|
||||
}
|
||||
|
||||
|
|
@ -111,13 +111,13 @@ func (x *XDPoS_v2) GetCurrentEpochSwitchBlock(chain consensus.ChainReader, block
|
|||
}
|
||||
|
||||
currentCheckpointNumber := epochSwitchInfo.EpochSwitchBlockInfo.Number.Uint64()
|
||||
epochNum := x.config.V2.FirstSwitchBlock.Uint64()/x.config.Epoch + uint64(epochSwitchInfo.EpochSwitchBlockInfo.Round)/x.config.Epoch
|
||||
epochNum := x.config.V2.SwitchBlock.Uint64()/x.config.Epoch + uint64(epochSwitchInfo.EpochSwitchBlockInfo.Round)/x.config.Epoch
|
||||
return currentCheckpointNumber, epochNum, nil
|
||||
}
|
||||
|
||||
func (x *XDPoS_v2) IsEpochSwitch(header *types.Header) (bool, uint64, error) {
|
||||
// Return true directly if we are examing the last v1 block. This could happen if the calling function is examing parent block
|
||||
if header.Number.Cmp(x.config.V2.FirstSwitchBlock) == 0 {
|
||||
if header.Number.Cmp(x.config.V2.SwitchBlock) == 0 {
|
||||
log.Info("[IsEpochSwitch] examing last v1 block")
|
||||
return true, header.Number.Uint64() / x.config.Epoch, nil
|
||||
}
|
||||
|
|
@ -129,9 +129,9 @@ func (x *XDPoS_v2) IsEpochSwitch(header *types.Header) (bool, uint64, error) {
|
|||
}
|
||||
parentRound := quorumCert.ProposedBlockInfo.Round
|
||||
epochStartRound := round - round%types.Round(x.config.Epoch)
|
||||
epochNum := x.config.V2.FirstSwitchBlock.Uint64()/x.config.Epoch + uint64(round)/x.config.Epoch
|
||||
epochNum := x.config.V2.SwitchBlock.Uint64()/x.config.Epoch + uint64(round)/x.config.Epoch
|
||||
// if parent is last v1 block and this is first v2 block, this is treated as epoch switch
|
||||
if quorumCert.ProposedBlockInfo.Number.Cmp(x.config.V2.FirstSwitchBlock) == 0 {
|
||||
if quorumCert.ProposedBlockInfo.Number.Cmp(x.config.V2.SwitchBlock) == 0 {
|
||||
log.Info("[IsEpochSwitch] true, parent equals V2.SwitchBlock", "round", round, "number", header.Number.Uint64(), "hash", header.Hash())
|
||||
return true, epochNum, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,15 +28,14 @@ func (x *XDPoS_v2) timeoutHandler(blockChainReader consensus.ChainReader, timeou
|
|||
log.Debug("[timeoutHandler] collect timeout", "number", numberOfTimeoutsInPool)
|
||||
|
||||
// Threshold reached
|
||||
isThresholdReached := numberOfTimeoutsInPool >= x.config.V2.CurrentConfig.CertThreshold
|
||||
certThreshold := x.config.V2.Config(uint64(x.currentRound)).CertThreshold
|
||||
isThresholdReached := numberOfTimeoutsInPool >= certThreshold
|
||||
if isThresholdReached {
|
||||
log.Info(fmt.Sprintf("Timeout pool threashold reached: %v, number of items in the pool: %v", isThresholdReached, numberOfTimeoutsInPool))
|
||||
err := x.onTimeoutPoolThresholdReached(blockChainReader, pooledTimeouts, timeout, timeout.GapNumber)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// clean up timeout message, regardless its GapNumber or round
|
||||
x.timeoutPool.Clear()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -82,6 +81,11 @@ func (x *XDPoS_v2) verifyTC(chain consensus.ChainReader, timeoutCert *types.Time
|
|||
- Use the above public key to find out the xdc address
|
||||
- Use the above xdc address to check against the master node list from step 1(For the received TC epoch)
|
||||
*/
|
||||
if timeoutCert == nil || timeoutCert.Signatures == nil {
|
||||
log.Warn("[verifyTC] TC or TC signatures is Nil")
|
||||
return utils.ErrInvalidTC
|
||||
}
|
||||
|
||||
snap, err := x.getSnapshot(chain, timeoutCert.GapNumber, true)
|
||||
if err != nil {
|
||||
log.Error("[verifyTC] Fail to get snapshot when verifying TC!", "TCGapNumber", timeoutCert.GapNumber)
|
||||
|
|
@ -92,16 +96,21 @@ func (x *XDPoS_v2) verifyTC(chain consensus.ChainReader, timeoutCert *types.Time
|
|||
return fmt.Errorf("Empty master node lists from snapshot")
|
||||
}
|
||||
|
||||
if timeoutCert == nil {
|
||||
log.Warn("[verifyTC] TC is Nil")
|
||||
return utils.ErrInvalidTC
|
||||
} else if timeoutCert.Signatures == nil || (len(timeoutCert.Signatures) < x.config.V2.CurrentConfig.CertThreshold) {
|
||||
log.Warn("[verifyTC] Invalid TC Signature is nil or empty", "timeoutCert.Round", timeoutCert.Round, "timeoutCert.GapNumber", timeoutCert.GapNumber, "Signatures len", len(timeoutCert.Signatures))
|
||||
return utils.ErrInvalidTC
|
||||
signatures, duplicates := UniqueSignatures(timeoutCert.Signatures)
|
||||
if len(duplicates) != 0 {
|
||||
for _, d := range duplicates {
|
||||
log.Warn("[verifyQC] duplicated signature in QC", "duplicate", common.Bytes2Hex(d))
|
||||
}
|
||||
}
|
||||
|
||||
certThreshold := x.config.V2.Config(uint64(timeoutCert.Round)).CertThreshold
|
||||
if len(signatures) < certThreshold {
|
||||
log.Warn("[verifyTC] Invalid TC Signature is nil or empty", "timeoutCert.Round", timeoutCert.Round, "timeoutCert.GapNumber", timeoutCert.GapNumber, "Signatures len", len(timeoutCert.Signatures), "CertThreshold", certThreshold)
|
||||
return utils.ErrInvalidTCSignatures
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(len(timeoutCert.Signatures))
|
||||
wg.Add(len(signatures))
|
||||
var haveError error
|
||||
|
||||
signedTimeoutObj := types.TimeoutSigHash(&types.TimeoutForSign{
|
||||
|
|
@ -109,17 +118,17 @@ func (x *XDPoS_v2) verifyTC(chain consensus.ChainReader, timeoutCert *types.Time
|
|||
GapNumber: timeoutCert.GapNumber,
|
||||
})
|
||||
|
||||
for _, signature := range timeoutCert.Signatures {
|
||||
for _, signature := range signatures {
|
||||
go func(sig types.Signature) {
|
||||
defer wg.Done()
|
||||
verified, _, err := x.verifyMsgSignature(signedTimeoutObj, sig, snap.NextEpochMasterNodes)
|
||||
if err != nil {
|
||||
log.Error("[verifyTC] Error while verfying TC message signatures", "timeoutCert.Round", timeoutCert.Round, "timeoutCert.GapNumber", timeoutCert.GapNumber, "Signatures len", len(timeoutCert.Signatures), "Error", err)
|
||||
log.Error("[verifyTC] Error while verfying TC message signatures", "timeoutCert.Round", timeoutCert.Round, "timeoutCert.GapNumber", timeoutCert.GapNumber, "Signatures len", len(signatures), "Error", err)
|
||||
haveError = fmt.Errorf("Error while verfying TC message signatures")
|
||||
return
|
||||
}
|
||||
if !verified {
|
||||
log.Warn("[verifyTC] Signature not verified doing TC verification", "timeoutCert.Round", timeoutCert.Round, "timeoutCert.GapNumber", timeoutCert.GapNumber, "Signatures len", len(timeoutCert.Signatures))
|
||||
log.Warn("[verifyTC] Signature not verified doing TC verification", "timeoutCert.Round", timeoutCert.Round, "timeoutCert.GapNumber", timeoutCert.GapNumber, "Signatures len", len(signatures))
|
||||
haveError = fmt.Errorf("Fail to verify TC due to signature mis-match")
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ func (x *XDPoS_v2) getExtraFields(header *types.Header) (*types.QuorumCert, type
|
|||
var masternodes []common.Address
|
||||
|
||||
// last v1 block
|
||||
if header.Number.Cmp(x.config.V2.FirstSwitchBlock) == 0 {
|
||||
if header.Number.Cmp(x.config.V2.SwitchBlock) == 0 {
|
||||
masternodes = decodeMasternodesFromHeaderExtra(header)
|
||||
return nil, types.Round(0), masternodes, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ func (x *XDPoS_v2) verifyHeader(chain consensus.ChainReader, header *types.Heade
|
|||
if parent == nil || parent.Number.Uint64() != number-1 || parent.Hash() != header.ParentHash {
|
||||
return consensus.ErrUnknownAncestor
|
||||
}
|
||||
if parent.Number.Uint64() > x.config.V2.FirstSwitchBlock.Uint64() && parent.Time.Uint64()+uint64(x.config.V2.CurrentConfig.MinePeriod) > header.Time.Uint64() {
|
||||
if parent.Number.Uint64() > x.config.V2.SwitchBlock.Uint64() && parent.Time.Uint64()+uint64(x.config.V2.CurrentConfig.MinePeriod) > header.Time.Uint64() {
|
||||
return utils.ErrInvalidTimestamp
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -75,7 +75,8 @@ func (x *XDPoS_v2) voteHandler(chain consensus.ChainReader, voteMsg *types.Vote)
|
|||
go x.ForensicsProcessor.DetectEquivocationInVotePool(voteMsg, x.votePool)
|
||||
go x.ForensicsProcessor.ProcessVoteEquivocation(chain, x, voteMsg)
|
||||
|
||||
thresholdReached := numberOfVotesInPool >= x.config.V2.CurrentConfig.CertThreshold
|
||||
certThreshold := x.config.V2.Config(uint64(voteMsg.ProposedBlockInfo.Round)).CertThreshold
|
||||
thresholdReached := numberOfVotesInPool >= certThreshold
|
||||
if thresholdReached {
|
||||
log.Info(fmt.Sprintf("[voteHandler] Vote pool threashold reached: %v, number of items in the pool: %v", thresholdReached, numberOfVotesInPool))
|
||||
|
||||
|
|
@ -113,46 +114,48 @@ func (x *XDPoS_v2) onVotePoolThresholdReached(chain consensus.ChainReader, poole
|
|||
// Filter out non-Master nodes signatures
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(len(pooledVotes))
|
||||
signatureSlice := make([]types.Signature, len(pooledVotes))
|
||||
signatures := make([]types.Signature, len(pooledVotes))
|
||||
counter := 0
|
||||
for h, vote := range pooledVotes {
|
||||
go func(hash common.Hash, v *types.Vote, i int) {
|
||||
defer wg.Done()
|
||||
verified, _, err := x.verifyMsgSignature(types.VoteSigHash(&types.VoteForSign{
|
||||
signedVote := types.VoteSigHash(&types.VoteForSign{
|
||||
ProposedBlockInfo: v.ProposedBlockInfo,
|
||||
GapNumber: v.GapNumber,
|
||||
}), v.Signature, masternodes)
|
||||
})
|
||||
verified, _, err := x.verifyMsgSignature(signedVote, v.Signature, masternodes)
|
||||
if err != nil {
|
||||
log.Warn("[onVotePoolThresholdReached] Skip not verified vote signatures when building QC", "Error", err.Error())
|
||||
log.Warn("[onVotePoolThresholdReached] Skip not verified vote signatures when building QC", "error", err.Error())
|
||||
} else if !verified {
|
||||
log.Warn("[onVotePoolThresholdReached] Skip not verified vote signatures when building QC", "verified", verified)
|
||||
} else {
|
||||
signatureSlice[i] = v.Signature
|
||||
signatures[i] = v.Signature
|
||||
}
|
||||
}(h, vote.(*types.Vote), counter)
|
||||
counter++
|
||||
}
|
||||
wg.Wait()
|
||||
elapsed := time.Since(start)
|
||||
log.Info("[onVotePoolThresholdReached] verify message signatures of vote pool took", "elapsed", elapsed)
|
||||
log.Debug("[onVotePoolThresholdReached] verify message signatures of vote pool took", "elapsed", elapsed)
|
||||
|
||||
// The signature list may contain empty entey. we only care the ones with values
|
||||
var validSignatureSlice []types.Signature
|
||||
for _, v := range signatureSlice {
|
||||
var validSignatures []types.Signature
|
||||
for _, v := range signatures {
|
||||
if len(v) != 0 {
|
||||
validSignatureSlice = append(validSignatureSlice, v)
|
||||
validSignatures = append(validSignatures, v)
|
||||
}
|
||||
}
|
||||
|
||||
// Skip and wait for the next vote to process again if valid votes is less than what we required
|
||||
if len(validSignatureSlice) < x.config.V2.CurrentConfig.CertThreshold {
|
||||
log.Warn("[onVotePoolThresholdReached] Not enough valid signatures to generate QC", "VotesSignaturesAfterFilter", validSignatureSlice, "NumberOfValidVotes", len(validSignatureSlice), "NumberOfVotes", len(pooledVotes))
|
||||
certThreshold := x.config.V2.Config(uint64(currentVoteMsg.(*types.Vote).ProposedBlockInfo.Round)).CertThreshold
|
||||
if len(validSignatures) < certThreshold {
|
||||
log.Warn("[onVotePoolThresholdReached] Not enough valid signatures to generate QC", "VotesSignaturesAfterFilter", validSignatures, "NumberOfValidVotes", len(validSignatures), "NumberOfVotes", len(pooledVotes))
|
||||
return nil
|
||||
}
|
||||
// Genrate QC
|
||||
quorumCert := &types.QuorumCert{
|
||||
ProposedBlockInfo: currentVoteMsg.(*types.Vote).ProposedBlockInfo,
|
||||
Signatures: validSignatureSlice,
|
||||
Signatures: validSignatures,
|
||||
GapNumber: currentVoteMsg.(*types.Vote).GapNumber,
|
||||
}
|
||||
err := x.processQC(chain, quorumCert)
|
||||
|
|
|
|||
|
|
@ -87,7 +87,9 @@ var (
|
|||
|
||||
ErrInvalidV2Extra = errors.New("Invalid v2 extra in the block")
|
||||
ErrInvalidQC = errors.New("Invalid QC content")
|
||||
ErrInvalidQCSignatures = errors.New("Invalid QC Signatures")
|
||||
ErrInvalidTC = errors.New("Invalid TC content")
|
||||
ErrInvalidTCSignatures = errors.New("Invalid TC Signatures")
|
||||
ErrEmptyBlockInfoHash = errors.New("BlockInfo hash is empty")
|
||||
ErrInvalidFieldInNonEpochSwitch = errors.New("Invalid field exist in a non-epoch swtich block")
|
||||
ErrValidatorNotWithinMasternodes = errors.New("Validaotor address is not in the master node list")
|
||||
|
|
|
|||
|
|
@ -302,7 +302,7 @@ func CreateBlock(blockchain *BlockChain, chainConfig *params.ChainConfig, starti
|
|||
}
|
||||
|
||||
// Inject the hardcoded master node list for the last v1 epoch block and all v1 epoch switch blocks (excluding genesis)
|
||||
if big.NewInt(int64(blockNumber)).Cmp(chainConfig.XDPoS.V2.FirstSwitchBlock) == 0 || blockNumber%int(chainConfig.XDPoS.Epoch) == 0 {
|
||||
if big.NewInt(int64(blockNumber)).Cmp(chainConfig.XDPoS.V2.SwitchBlock) == 0 || blockNumber%int(chainConfig.XDPoS.Epoch) == 0 {
|
||||
// reset extra
|
||||
header.Extra = []byte{}
|
||||
if len(header.Extra) < utils.ExtraVanity {
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ func TestAdaptorGetMasternodesFromCheckpointHeader(t *testing.T) {
|
|||
headerV1.Extra = common.Hex2Bytes("d7830100018358444388676f312e31352e38856c696e757800000000000000000278c350152e15fa6ffc712a5a73d704ce73e2e103d9e17ae3ff2c6712e44e25b09ac5ee91f6c9ff065551f0dcac6f00cae11192d462db709be3758ccef312ee5eea8d7bad5374c6a652150515d744508b61c1a4deb4e4e7bf057e4e3824c11fd2569bcb77a52905cda63b5a58507910bed335e4c9d87ae0ecdfafd400")
|
||||
masternodesV1 := adaptor.GetMasternodesFromCheckpointHeader(headerV1)
|
||||
headerV2 := currentBlock.Header()
|
||||
headerV2.Number.Add(blockchain.Config().XDPoS.V2.FirstSwitchBlock, big.NewInt(1))
|
||||
headerV2.Number.Add(blockchain.Config().XDPoS.V2.SwitchBlock, big.NewInt(1))
|
||||
headerV2.Validators = common.Hex2Bytes("0278c350152e15fa6ffc712a5a73d704ce73e2e103d9e17ae3ff2c6712e44e25b09ac5ee91f6c9ff065551f0dcac6f00cae11192d462db709be3758c")
|
||||
headerV2.Extra = []byte{2}
|
||||
masternodesV2 := adaptor.GetMasternodesFromCheckpointHeader(headerV2)
|
||||
|
|
@ -91,12 +91,12 @@ func TestAdaptorIsEpochSwitch(t *testing.T) {
|
|||
parentBlockInfo := &types.BlockInfo{
|
||||
Hash: header.ParentHash,
|
||||
Round: types.Round(0),
|
||||
Number: big.NewInt(0).Set(blockchain.Config().XDPoS.V2.FirstSwitchBlock),
|
||||
Number: big.NewInt(0).Set(blockchain.Config().XDPoS.V2.SwitchBlock),
|
||||
}
|
||||
quorumCert := &types.QuorumCert{
|
||||
ProposedBlockInfo: parentBlockInfo,
|
||||
Signatures: nil,
|
||||
GapNumber: blockchain.Config().XDPoS.V2.FirstSwitchBlock.Uint64() - blockchain.Config().XDPoS.Gap,
|
||||
GapNumber: blockchain.Config().XDPoS.V2.SwitchBlock.Uint64() - blockchain.Config().XDPoS.Gap,
|
||||
}
|
||||
extra := types.ExtraFields_v2{
|
||||
Round: 1,
|
||||
|
|
@ -105,19 +105,19 @@ func TestAdaptorIsEpochSwitch(t *testing.T) {
|
|||
extraBytes, err := extra.EncodeToBytes()
|
||||
assert.Nil(t, err)
|
||||
header.Extra = extraBytes
|
||||
header.Number.Add(blockchain.Config().XDPoS.V2.FirstSwitchBlock, big.NewInt(1))
|
||||
header.Number.Add(blockchain.Config().XDPoS.V2.SwitchBlock, big.NewInt(1))
|
||||
isEpochSwitchBlock, _, err = adaptor.IsEpochSwitch(header)
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, isEpochSwitchBlock, "header should be epoch switch", header)
|
||||
parentBlockInfo = &types.BlockInfo{
|
||||
Hash: header.ParentHash,
|
||||
Round: types.Round(1),
|
||||
Number: big.NewInt(0).Add(blockchain.Config().XDPoS.V2.FirstSwitchBlock, big.NewInt(1)),
|
||||
Number: big.NewInt(0).Add(blockchain.Config().XDPoS.V2.SwitchBlock, big.NewInt(1)),
|
||||
}
|
||||
quorumCert = &types.QuorumCert{
|
||||
ProposedBlockInfo: parentBlockInfo,
|
||||
Signatures: nil,
|
||||
GapNumber: blockchain.Config().XDPoS.V2.FirstSwitchBlock.Uint64() - blockchain.Config().XDPoS.Gap,
|
||||
GapNumber: blockchain.Config().XDPoS.V2.SwitchBlock.Uint64() - blockchain.Config().XDPoS.Gap,
|
||||
}
|
||||
extra = types.ExtraFields_v2{
|
||||
Round: 2,
|
||||
|
|
@ -126,19 +126,19 @@ func TestAdaptorIsEpochSwitch(t *testing.T) {
|
|||
extraBytes, err = extra.EncodeToBytes()
|
||||
assert.Nil(t, err)
|
||||
header.Extra = extraBytes
|
||||
header.Number.Add(blockchain.Config().XDPoS.V2.FirstSwitchBlock, big.NewInt(2))
|
||||
header.Number.Add(blockchain.Config().XDPoS.V2.SwitchBlock, big.NewInt(2))
|
||||
isEpochSwitchBlock, _, err = adaptor.IsEpochSwitch(header)
|
||||
assert.Nil(t, err)
|
||||
assert.False(t, isEpochSwitchBlock, "header should not be epoch switch", header)
|
||||
parentBlockInfo = &types.BlockInfo{
|
||||
Hash: header.ParentHash,
|
||||
Round: types.Round(blockchain.Config().XDPoS.Epoch) - 1,
|
||||
Number: big.NewInt(0).Add(blockchain.Config().XDPoS.V2.FirstSwitchBlock, big.NewInt(100)),
|
||||
Number: big.NewInt(0).Add(blockchain.Config().XDPoS.V2.SwitchBlock, big.NewInt(100)),
|
||||
}
|
||||
quorumCert = &types.QuorumCert{
|
||||
ProposedBlockInfo: parentBlockInfo,
|
||||
Signatures: nil,
|
||||
GapNumber: blockchain.Config().XDPoS.V2.FirstSwitchBlock.Uint64() - blockchain.Config().XDPoS.Gap,
|
||||
GapNumber: blockchain.Config().XDPoS.V2.SwitchBlock.Uint64() - blockchain.Config().XDPoS.Gap,
|
||||
}
|
||||
extra = types.ExtraFields_v2{
|
||||
Round: types.Round(blockchain.Config().XDPoS.Epoch) + 1,
|
||||
|
|
@ -147,19 +147,19 @@ func TestAdaptorIsEpochSwitch(t *testing.T) {
|
|||
extraBytes, err = extra.EncodeToBytes()
|
||||
assert.Nil(t, err)
|
||||
header.Extra = extraBytes
|
||||
header.Number.Add(blockchain.Config().XDPoS.V2.FirstSwitchBlock, big.NewInt(101))
|
||||
header.Number.Add(blockchain.Config().XDPoS.V2.SwitchBlock, big.NewInt(101))
|
||||
isEpochSwitchBlock, _, err = adaptor.IsEpochSwitch(header)
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, isEpochSwitchBlock, "header should be epoch switch", header)
|
||||
parentBlockInfo = &types.BlockInfo{
|
||||
Hash: header.ParentHash,
|
||||
Round: types.Round(blockchain.Config().XDPoS.Epoch) + 1,
|
||||
Number: big.NewInt(0).Add(blockchain.Config().XDPoS.V2.FirstSwitchBlock, big.NewInt(100)),
|
||||
Number: big.NewInt(0).Add(blockchain.Config().XDPoS.V2.SwitchBlock, big.NewInt(100)),
|
||||
}
|
||||
quorumCert = &types.QuorumCert{
|
||||
ProposedBlockInfo: parentBlockInfo,
|
||||
Signatures: nil,
|
||||
GapNumber: blockchain.Config().XDPoS.V2.FirstSwitchBlock.Uint64() - blockchain.Config().XDPoS.Gap,
|
||||
GapNumber: blockchain.Config().XDPoS.V2.SwitchBlock.Uint64() - blockchain.Config().XDPoS.Gap,
|
||||
}
|
||||
extra = types.ExtraFields_v2{
|
||||
Round: types.Round(blockchain.Config().XDPoS.Epoch) + 2,
|
||||
|
|
@ -168,7 +168,7 @@ func TestAdaptorIsEpochSwitch(t *testing.T) {
|
|||
extraBytes, err = extra.EncodeToBytes()
|
||||
assert.Nil(t, err)
|
||||
header.Extra = extraBytes
|
||||
header.Number.Add(blockchain.Config().XDPoS.V2.FirstSwitchBlock, big.NewInt(101))
|
||||
header.Number.Add(blockchain.Config().XDPoS.V2.SwitchBlock, big.NewInt(101))
|
||||
isEpochSwitchBlock, _, err = adaptor.IsEpochSwitch(header)
|
||||
assert.Nil(t, err)
|
||||
assert.False(t, isEpochSwitchBlock, "header should not be epoch switch", header)
|
||||
|
|
|
|||
|
|
@ -83,13 +83,13 @@ func TestIsYourTurnConsensusV2(t *testing.T) {
|
|||
|
||||
func TestIsYourTurnConsensusV2CrossConfig(t *testing.T) {
|
||||
// we skip test for v1 since it's hard to make a real genesis block
|
||||
blockchain, _, currentBlock, signer, signFn, _ := PrepareXDCTestBlockChainForV2Engine(t, 910, params.TestXDPoSMockChainConfig, nil)
|
||||
blockchain, _, currentBlock, signer, signFn, _ := PrepareXDCTestBlockChainForV2Engine(t, 909, params.TestXDPoSMockChainConfig, nil)
|
||||
firstMinePeriod := blockchain.Config().XDPoS.V2.CurrentConfig.MinePeriod
|
||||
|
||||
adaptor := blockchain.Engine().(*XDPoS.XDPoS)
|
||||
blockNum := 911 // 911 is new config switch block
|
||||
blockNum := 910 // 910 is new config switch block
|
||||
blockCoinBase := "0x111000000000000000000000000000000123"
|
||||
currentBlock = CreateBlock(blockchain, params.TestXDPoSMockChainConfig, currentBlock, blockNum, 1, blockCoinBase, signer, signFn, nil, nil)
|
||||
currentBlock = CreateBlock(blockchain, params.TestXDPoSMockChainConfig, currentBlock, blockNum, 10, blockCoinBase, signer, signFn, nil, nil)
|
||||
currentBlockHeader := currentBlock.Header()
|
||||
currentBlockHeader.Time = big.NewInt(time.Now().Unix())
|
||||
err := blockchain.InsertBlock(currentBlock)
|
||||
|
|
@ -100,8 +100,11 @@ func TestIsYourTurnConsensusV2CrossConfig(t *testing.T) {
|
|||
assert.Nil(t, err)
|
||||
assert.False(t, isYourTurn)
|
||||
|
||||
adaptor.UpdateParams(currentBlockHeader) // it will be triggered automatically on the real code by other process
|
||||
|
||||
// after new mine period
|
||||
secondMinePeriod := blockchain.Config().XDPoS.V2.CurrentConfig.MinePeriod
|
||||
|
||||
time.Sleep(time.Duration(secondMinePeriod-firstMinePeriod) * time.Second)
|
||||
isYourTurn, err = adaptor.YourTurn(blockchain, currentBlockHeader, common.HexToAddress("xdc0D3ab14BBaD3D99F4203bd7a11aCB94882050E7e"))
|
||||
assert.Nil(t, err)
|
||||
|
|
|
|||
|
|
@ -312,10 +312,10 @@ func PrepareXDCTestBlockChainForV2Engine(t *testing.T, numOfBlocks int, chainCon
|
|||
for i := 1; i <= numOfBlocks; i++ {
|
||||
blockCoinBase := fmt.Sprintf("0x111000000000000000000000000000000%03d", i)
|
||||
// for v2 blocks, fill in correct coinbase
|
||||
if int64(i) > chainConfig.XDPoS.V2.FirstSwitchBlock.Int64() {
|
||||
if int64(i) > chainConfig.XDPoS.V2.SwitchBlock.Int64() {
|
||||
blockCoinBase = signer.Hex()
|
||||
}
|
||||
roundNumber := int64(i) - chainConfig.XDPoS.V2.FirstSwitchBlock.Int64()
|
||||
roundNumber := int64(i) - chainConfig.XDPoS.V2.SwitchBlock.Int64()
|
||||
block := CreateBlock(blockchain, chainConfig, currentBlock, i, roundNumber, blockCoinBase, signer, signFn, nil, nil)
|
||||
|
||||
err = blockchain.InsertBlock(block)
|
||||
|
|
@ -348,7 +348,7 @@ func PrepareXDCTestBlockChainForV2Engine(t *testing.T, numOfBlocks int, chainCon
|
|||
}
|
||||
|
||||
// First v2 block
|
||||
if (int64(i) - chainConfig.XDPoS.V2.FirstSwitchBlock.Int64()) == 1 {
|
||||
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)
|
||||
|
|
@ -398,10 +398,10 @@ func PrepareXDCTestBlockChainWithPenaltyForV2Engine(t *testing.T, numOfBlocks in
|
|||
for i := 1; i <= numOfBlocks; i++ {
|
||||
blockCoinBase := fmt.Sprintf("0x111000000000000000000000000000000%03d", i)
|
||||
// for v2 blocks, fill in correct coinbase
|
||||
if int64(i) > chainConfig.XDPoS.V2.FirstSwitchBlock.Int64() {
|
||||
if int64(i) > chainConfig.XDPoS.V2.SwitchBlock.Int64() {
|
||||
blockCoinBase = signer.Hex()
|
||||
}
|
||||
roundNumber := int64(i) - chainConfig.XDPoS.V2.FirstSwitchBlock.Int64()
|
||||
roundNumber := int64(i) - chainConfig.XDPoS.V2.SwitchBlock.Int64()
|
||||
// use signer itself as penalty
|
||||
block := CreateBlock(blockchain, chainConfig, currentBlock, i, roundNumber, blockCoinBase, signer, signFn, signer[:], nil)
|
||||
|
||||
|
|
@ -426,7 +426,7 @@ func CreateBlock(blockchain *BlockChain, chainConfig *params.ChainConfig, starti
|
|||
merkleRoot := "35999dded35e8db12de7e6c1471eb9670c162eec616ecebbaf4fddd4676fb930"
|
||||
var header *types.Header
|
||||
|
||||
if big.NewInt(int64(blockNumber)).Cmp(chainConfig.XDPoS.V2.FirstSwitchBlock) == 1 { // Build engine v2 compatible extra data field
|
||||
if big.NewInt(int64(blockNumber)).Cmp(chainConfig.XDPoS.V2.SwitchBlock) == 1 { // Build engine v2 compatible extra data field
|
||||
extraInBytes := generateV2Extra(roundNumber, currentBlock, signer, signFn, signersKey)
|
||||
|
||||
header = &types.Header{
|
||||
|
|
@ -436,9 +436,9 @@ func CreateBlock(blockchain *BlockChain, chainConfig *params.ChainConfig, starti
|
|||
Coinbase: common.HexToAddress(blockCoinBase),
|
||||
Extra: extraInBytes,
|
||||
}
|
||||
if int64(blockNumber) == (chainConfig.XDPoS.V2.FirstSwitchBlock.Int64() + 1) { // This is the first v2 block, we need to copy the last v1 epoch master node list and inject into v2 validators
|
||||
if int64(blockNumber) == (chainConfig.XDPoS.V2.SwitchBlock.Int64() + 1) { // This is the first v2 block, we need to copy the last v1 epoch master node list and inject into v2 validators
|
||||
// Get last master node list from last v1 block
|
||||
lastv1Block := blockchain.GetBlockByNumber(chainConfig.XDPoS.V2.FirstSwitchBlock.Uint64())
|
||||
lastv1Block := blockchain.GetBlockByNumber(chainConfig.XDPoS.V2.SwitchBlock.Uint64())
|
||||
masternodesFromV1LastEpoch := decodeMasternodesFromHeaderExtra(lastv1Block.Header())
|
||||
for _, v := range masternodesFromV1LastEpoch {
|
||||
header.Validators = append(header.Validators, v[:]...)
|
||||
|
|
@ -446,7 +446,7 @@ func CreateBlock(blockchain *BlockChain, chainConfig *params.ChainConfig, starti
|
|||
} else if roundNumber%int64(chainConfig.XDPoS.Epoch) == 0 {
|
||||
// epoch switch blocks, copy the master node list and inject into v2 validators
|
||||
// Get last master node list from last v1 block
|
||||
lastv1Block := blockchain.GetBlockByNumber(chainConfig.XDPoS.V2.FirstSwitchBlock.Uint64())
|
||||
lastv1Block := blockchain.GetBlockByNumber(chainConfig.XDPoS.V2.SwitchBlock.Uint64())
|
||||
masternodesFromV1LastEpoch := decodeMasternodesFromHeaderExtra(lastv1Block.Header())
|
||||
for _, v := range masternodesFromV1LastEpoch {
|
||||
header.Validators = append(header.Validators, v[:]...)
|
||||
|
|
@ -465,7 +465,7 @@ func CreateBlock(blockchain *BlockChain, chainConfig *params.ChainConfig, starti
|
|||
}
|
||||
|
||||
// Inject the hardcoded master node list for the last v1 epoch block and all v1 epoch switch blocks (excluding genesis)
|
||||
if big.NewInt(int64(blockNumber)).Cmp(chainConfig.XDPoS.V2.FirstSwitchBlock) == 0 || blockNumber%int(chainConfig.XDPoS.Epoch) == 0 {
|
||||
if big.NewInt(int64(blockNumber)).Cmp(chainConfig.XDPoS.V2.SwitchBlock) == 0 || blockNumber%int(chainConfig.XDPoS.Epoch) == 0 {
|
||||
// reset extra
|
||||
header.Extra = []byte{}
|
||||
if len(header.Extra) < utils.ExtraVanity {
|
||||
|
|
@ -584,7 +584,7 @@ func findSignerAndSignFn(bc *BlockChain, header *types.Header, signer common.Add
|
|||
addressedSignFn := signFn
|
||||
|
||||
// If v2 block, we need to use extra data's round to find who is creating the block in order to verify the validator
|
||||
if header.Number.Cmp(config.XDPoS.V2.FirstSwitchBlock) > 0 {
|
||||
if header.Number.Cmp(config.XDPoS.V2.SwitchBlock) > 0 {
|
||||
var decodedExtraField types.ExtraFields_v2
|
||||
err := utils.DecodeBytesExtraFields(header.Extra, &decodedExtraField)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestInitialFirstV2Blcok(t *testing.T) {
|
||||
func TestInitialFirstV2Block(t *testing.T) {
|
||||
blockchain, _, currentBlock, _, _, _ := PrepareXDCTestBlockChainForV2Engine(t, 900, params.TestXDPoSMockChainConfig, nil)
|
||||
adaptor := blockchain.Engine().(*XDPoS.XDPoS)
|
||||
header := currentBlock.Header()
|
||||
|
|
@ -32,7 +32,7 @@ func TestInitialFirstV2Blcok(t *testing.T) {
|
|||
expectedQuorumCert := &types.QuorumCert{
|
||||
ProposedBlockInfo: blockInfo,
|
||||
Signatures: nil,
|
||||
GapNumber: blockchain.Config().XDPoS.V2.FirstSwitchBlock.Uint64() - blockchain.Config().XDPoS.Gap,
|
||||
GapNumber: blockchain.Config().XDPoS.V2.SwitchBlock.Uint64() - blockchain.Config().XDPoS.Gap,
|
||||
}
|
||||
assert.Equal(t, types.Round(1), round)
|
||||
assert.Equal(t, expectedQuorumCert, highQC)
|
||||
|
|
@ -104,7 +104,7 @@ func TestInitialOtherV2Block(t *testing.T) {
|
|||
expectedQuorumCert := &types.QuorumCert{
|
||||
ProposedBlockInfo: blockInfo,
|
||||
Signatures: []types.Signature{},
|
||||
GapNumber: blockchain.Config().XDPoS.V2.FirstSwitchBlock.Uint64() - blockchain.Config().XDPoS.Gap,
|
||||
GapNumber: blockchain.Config().XDPoS.V2.SwitchBlock.Uint64() - blockchain.Config().XDPoS.Gap,
|
||||
}
|
||||
assert.Equal(t, types.Round(11), round)
|
||||
assert.Equal(t, expectedQuorumCert, highQC)
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ func TestHookRewardV2(t *testing.T) {
|
|||
err = json.Unmarshal([]byte(configString), &config)
|
||||
assert.Nil(t, err)
|
||||
// set switch to 1800, so that it covers 901-1799, 1800-2700 two epochs
|
||||
config.XDPoS.V2.FirstSwitchBlock.SetUint64(1800)
|
||||
config.XDPoS.V2.SwitchBlock.SetUint64(1800)
|
||||
|
||||
blockchain, _, _, signer, signFn, _ := PrepareXDCTestBlockChainForV2Engine(t, int(config.XDPoS.Epoch)*5, &config, nil)
|
||||
|
||||
|
|
@ -104,7 +104,7 @@ func TestHookRewardV2SplitReward(t *testing.T) {
|
|||
err = json.Unmarshal([]byte(configString), &config)
|
||||
assert.Nil(t, err)
|
||||
// set switch to 1800, so that it covers 901-1799, 1800-2700 two epochs
|
||||
config.XDPoS.V2.FirstSwitchBlock.SetUint64(1800)
|
||||
config.XDPoS.V2.SwitchBlock.SetUint64(1800)
|
||||
|
||||
blockchain, _, _, signer, signFn, _ := PrepareXDCTestBlockChainForV2Engine(t, int(config.XDPoS.Epoch)*3, &config, nil)
|
||||
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ func TestTimeoutPeriodAndThreadholdConfigChange(t *testing.T) {
|
|||
err := blockchain.InsertBlock(currentBlock)
|
||||
assert.Nil(t, err)
|
||||
|
||||
engineV2.UpdateParams() // it will be triggered automatically on the real code by other process
|
||||
engineV2.UpdateParams(currentBlockHeader) // it will be triggered automatically on the real code by other process
|
||||
|
||||
t.Log("waiting for another consecutive period")
|
||||
// another consecutive period
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ func TestConfigSwitchOnDifferentCertThreshold(t *testing.T) {
|
|||
|
||||
adaptor := blockchain.Engine().(*XDPoS.XDPoS)
|
||||
|
||||
// Genrate QC
|
||||
// Genrate 911 QC
|
||||
proposedBlockInfo := &types.BlockInfo{
|
||||
Hash: blockchain.GetBlockByNumber(911).Hash(),
|
||||
Round: types.Round(11),
|
||||
|
|
@ -198,11 +198,11 @@ func TestConfigSwitchOnDifferentCertThreshold(t *testing.T) {
|
|||
acc1SignedHash := SignHashByPK(acc1Key, types.VoteSigHash(voteForSign).Bytes())
|
||||
acc2SignedHash := SignHashByPK(acc2Key, types.VoteSigHash(voteForSign).Bytes())
|
||||
acc3SignedHash := SignHashByPK(acc3Key, types.VoteSigHash(voteForSign).Bytes())
|
||||
var signatures []types.Signature
|
||||
signatures = append(signatures, acc1SignedHash, acc2SignedHash, acc3SignedHash)
|
||||
var signaturesFirst []types.Signature
|
||||
signaturesFirst = append(signaturesFirst, acc1SignedHash, acc2SignedHash, acc3SignedHash)
|
||||
quorumCert := &types.QuorumCert{
|
||||
ProposedBlockInfo: proposedBlockInfo,
|
||||
Signatures: signatures,
|
||||
Signatures: signaturesFirst,
|
||||
GapNumber: 450,
|
||||
}
|
||||
|
||||
|
|
@ -210,18 +210,53 @@ func TestConfigSwitchOnDifferentCertThreshold(t *testing.T) {
|
|||
Round: types.Round(12),
|
||||
QuorumCert: quorumCert,
|
||||
}
|
||||
extraInBytes, err := extra.EncodeToBytes()
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("Error encode extra into bytes: %v", err))
|
||||
}
|
||||
extraInBytes, _ := extra.EncodeToBytes()
|
||||
|
||||
// after 910 require 5 signs, but we only give 3 signs
|
||||
block912 := blockchain.GetBlockByNumber(912).Header()
|
||||
block912.Extra = extraInBytes
|
||||
err = adaptor.VerifyHeader(blockchain, block912, true)
|
||||
|
||||
// Error happens after verify QC, means verify QC passed
|
||||
assert.Equal(t, utils.ErrInvalidQC, err)
|
||||
assert.Equal(t, utils.ErrInvalidQCSignatures, err)
|
||||
|
||||
// Make we verification process use the corresponding config
|
||||
// Genrate 910 QC
|
||||
proposedBlockInfo = &types.BlockInfo{
|
||||
Hash: blockchain.GetBlockByNumber(910).Hash(),
|
||||
Round: types.Round(10),
|
||||
Number: blockchain.GetBlockByNumber(910).Number(),
|
||||
}
|
||||
voteForSign = &types.VoteForSign{
|
||||
ProposedBlockInfo: proposedBlockInfo,
|
||||
GapNumber: 450,
|
||||
}
|
||||
|
||||
// Sign from acc 1, 2, 3
|
||||
acc1SignedHash = SignHashByPK(acc1Key, types.VoteSigHash(voteForSign).Bytes())
|
||||
acc2SignedHash = SignHashByPK(acc2Key, types.VoteSigHash(voteForSign).Bytes())
|
||||
acc3SignedHash = SignHashByPK(acc3Key, types.VoteSigHash(voteForSign).Bytes())
|
||||
|
||||
var signaturesThr []types.Signature
|
||||
signaturesThr = append(signaturesThr, acc1SignedHash, acc2SignedHash, acc3SignedHash)
|
||||
quorumCert = &types.QuorumCert{
|
||||
ProposedBlockInfo: proposedBlockInfo,
|
||||
Signatures: signaturesThr,
|
||||
GapNumber: 450,
|
||||
}
|
||||
|
||||
extra = types.ExtraFields_v2{
|
||||
Round: types.Round(11),
|
||||
QuorumCert: quorumCert,
|
||||
}
|
||||
extraInBytes, _ = extra.EncodeToBytes()
|
||||
|
||||
// QC contains 910, so it requires 3 signatures, not use block number to determine which config to use
|
||||
block911 := blockchain.GetBlockByNumber(911).Header()
|
||||
block911.Extra = extraInBytes
|
||||
err = adaptor.VerifyHeader(blockchain, block911, true)
|
||||
|
||||
// error ErrValidatorNotWithinMasternodes means verifyQC is passed and move to next verification process
|
||||
assert.Equal(t, utils.ErrValidatorNotWithinMasternodes, err)
|
||||
}
|
||||
|
||||
func TestShouldFailIfNotEnoughQCSignatures(t *testing.T) {
|
||||
|
|
@ -271,7 +306,7 @@ func TestShouldFailIfNotEnoughQCSignatures(t *testing.T) {
|
|||
headerWithDuplicatedSignatures.Extra = extraInBytes
|
||||
// Happy path
|
||||
err = adaptor.VerifyHeader(blockchain, headerWithDuplicatedSignatures, true)
|
||||
assert.Equal(t, utils.ErrInvalidQC, err)
|
||||
assert.Equal(t, utils.ErrInvalidQCSignatures, err)
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -332,12 +367,12 @@ func TestShouldVerifyHeadersEvenIfParentsNotYetWrittenIntoDB(t *testing.T) {
|
|||
|
||||
// Create block 911 but don't write into DB
|
||||
blockNumber := 911
|
||||
roundNumber := int64(blockNumber) - config.XDPoS.V2.FirstSwitchBlock.Int64()
|
||||
roundNumber := int64(blockNumber) - config.XDPoS.V2.SwitchBlock.Int64()
|
||||
block911 := CreateBlock(blockchain, &config, block910, blockNumber, roundNumber, signer.Hex(), signer, signFn, nil, nil)
|
||||
|
||||
// Create block 912 and not write into DB as well
|
||||
blockNumber = 912
|
||||
roundNumber = int64(blockNumber) - config.XDPoS.V2.FirstSwitchBlock.Int64()
|
||||
roundNumber = int64(blockNumber) - config.XDPoS.V2.SwitchBlock.Int64()
|
||||
block912 := CreateBlock(blockchain, &config, block911, blockNumber, roundNumber, signer.Hex(), signer, signFn, nil, nil)
|
||||
|
||||
headersTobeVerified = append(headersTobeVerified, block910.Header(), block911.Header(), block912.Header())
|
||||
|
|
|
|||
|
|
@ -2541,7 +2541,7 @@ func (bc *BlockChain) UpdateM1() error {
|
|||
header := bc.CurrentHeader()
|
||||
var maxMasternodes int
|
||||
// check if block number is increase ms checkpoint
|
||||
if bc.chainConfig.IsTIPIncreaseMasternodes(header.Number) || (bc.chainConfig.XDPoS.V2.FirstSwitchBlock != nil && header.Number.Cmp(bc.chainConfig.XDPoS.V2.FirstSwitchBlock) == 1) {
|
||||
if bc.chainConfig.IsTIPIncreaseMasternodes(header.Number) || (bc.chainConfig.XDPoS.V2.SwitchBlock != nil && header.Number.Cmp(bc.chainConfig.XDPoS.V2.SwitchBlock) == 1) {
|
||||
// using new masterndoes
|
||||
maxMasternodes = common.MaxMasternodesV2
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -321,7 +321,6 @@ func GenesisBlockForTesting(db ethdb.Database, addr common.Address, balance *big
|
|||
// DefaultGenesisBlock returns the Ethereum main net genesis block.
|
||||
func DefaultGenesisBlock() *Genesis {
|
||||
config := params.XDCMainnetChainConfig
|
||||
config.XDPoS.V2 = nil
|
||||
return &Genesis{
|
||||
Config: config,
|
||||
Nonce: 0,
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ func AttachConsensusV2Hooks(adaptor *XDPoS.XDPoS, bc *core.BlockChain, chainConf
|
|||
|
||||
// get list check penalties signing block & list master nodes wil comeback
|
||||
// start to calc comeback at v2 block + limitPenaltyEpochV2 to avoid reading v1 blocks
|
||||
comebackHeight := (common.LimitPenaltyEpochV2+1)*chain.Config().XDPoS.Epoch + chain.Config().XDPoS.V2.FirstSwitchBlock.Uint64()
|
||||
comebackHeight := (common.LimitPenaltyEpochV2+1)*chain.Config().XDPoS.Epoch + chain.Config().XDPoS.V2.SwitchBlock.Uint64()
|
||||
penComebacks := []common.Address{}
|
||||
if number.Uint64() > comebackHeight {
|
||||
pens := adaptor.EngineV2.GetPreviousPenaltyByHash(chain, currentHash, common.LimitPenaltyEpochV2)
|
||||
|
|
@ -170,7 +170,7 @@ func AttachConsensusV2Hooks(adaptor *XDPoS.XDPoS, bc *core.BlockChain, chainConf
|
|||
}
|
||||
rewards := make(map[string]interface{})
|
||||
// skip hook reward if this is the first v2
|
||||
if number == chain.Config().XDPoS.V2.FirstSwitchBlock.Uint64()+1 {
|
||||
if number == chain.Config().XDPoS.V2.SwitchBlock.Uint64()+1 {
|
||||
return rewards, nil
|
||||
}
|
||||
start := time.Now()
|
||||
|
|
@ -235,7 +235,7 @@ func GetSigningTxCount(c *XDPoS.XDPoS, chain consensus.ChainReader, header *type
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if isEpochSwitch && i != chain.Config().XDPoS.V2.FirstSwitchBlock.Uint64()+1 {
|
||||
if isEpochSwitch && i != chain.Config().XDPoS.V2.SwitchBlock.Uint64()+1 {
|
||||
epochCount += 1
|
||||
if epochCount == signEpochCount {
|
||||
endBlockNumber = header.Number.Uint64() - 1
|
||||
|
|
|
|||
|
|
@ -291,7 +291,7 @@ func (self *worker) update() {
|
|||
// A real event arrived, process interesting content
|
||||
select {
|
||||
case v := <-WaitPeriodCh:
|
||||
log.Info("[worker] update mine period", "period", v)
|
||||
log.Info("[worker] update wait period", "period", v)
|
||||
waitPeriod = v
|
||||
timeout.Reset(time.Duration(waitPeriod) * time.Second)
|
||||
|
||||
|
|
|
|||
183
params/config.go
183
params/config.go
|
|
@ -19,8 +19,10 @@ package params
|
|||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"sync"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/log"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -39,7 +41,7 @@ var (
|
|||
var (
|
||||
MainnetV2Configs = map[uint64]*V2Config{
|
||||
Default: {
|
||||
SwitchBlock: big.NewInt(9999999999),
|
||||
SwitchRound: 0,
|
||||
CertThreshold: common.MaxMasternodesV2*2/3 + 1,
|
||||
TimeoutSyncThreshold: 3,
|
||||
TimeoutPeriod: 60,
|
||||
|
|
@ -47,7 +49,7 @@ var (
|
|||
MinePeriod: 10,
|
||||
},
|
||||
9999999999: {
|
||||
SwitchBlock: big.NewInt(9999999999),
|
||||
SwitchRound: 9999999999,
|
||||
CertThreshold: common.MaxMasternodesV2*2/3 + 1,
|
||||
TimeoutSyncThreshold: 3,
|
||||
TimeoutPeriod: 60,
|
||||
|
|
@ -57,31 +59,23 @@ var (
|
|||
}
|
||||
TestV2Configs = map[uint64]*V2Config{
|
||||
Default: {
|
||||
SwitchBlock: big.NewInt(900),
|
||||
SwitchRound: 0,
|
||||
CertThreshold: 3,
|
||||
TimeoutSyncThreshold: 2,
|
||||
TimeoutPeriod: 4,
|
||||
WaitPeriod: 1,
|
||||
MinePeriod: 2,
|
||||
},
|
||||
900: {
|
||||
SwitchBlock: big.NewInt(900),
|
||||
CertThreshold: 3,
|
||||
TimeoutSyncThreshold: 2,
|
||||
TimeoutPeriod: 4,
|
||||
WaitPeriod: 1,
|
||||
MinePeriod: 2,
|
||||
},
|
||||
910: {
|
||||
SwitchBlock: big.NewInt(910),
|
||||
10: {
|
||||
SwitchRound: 10,
|
||||
CertThreshold: 5,
|
||||
TimeoutSyncThreshold: 2,
|
||||
TimeoutPeriod: 4,
|
||||
WaitPeriod: 2,
|
||||
MinePeriod: 3,
|
||||
},
|
||||
1799: {
|
||||
SwitchBlock: big.NewInt(1799),
|
||||
899: {
|
||||
SwitchRound: 899,
|
||||
CertThreshold: 5,
|
||||
TimeoutSyncThreshold: 4,
|
||||
TimeoutPeriod: 5,
|
||||
|
|
@ -92,31 +86,23 @@ var (
|
|||
|
||||
DevnetV2Configs = map[uint64]*V2Config{
|
||||
Default: {
|
||||
SwitchBlock: big.NewInt(7074000),
|
||||
CertThreshold: 4,
|
||||
TimeoutSyncThreshold: 5,
|
||||
TimeoutPeriod: 10,
|
||||
WaitPeriod: 5,
|
||||
MinePeriod: 5,
|
||||
},
|
||||
7074000: {
|
||||
SwitchBlock: big.NewInt(7074000),
|
||||
SwitchRound: 0,
|
||||
CertThreshold: common.MaxMasternodesV2*2/3 + 1,
|
||||
TimeoutSyncThreshold: 5,
|
||||
TimeoutPeriod: 25,
|
||||
WaitPeriod: 10,
|
||||
MinePeriod: 10,
|
||||
},
|
||||
7224300: {
|
||||
SwitchBlock: big.NewInt(7224300),
|
||||
151919: {
|
||||
SwitchRound: 151919,
|
||||
CertThreshold: common.MaxMasternodesV2*1/2 + 1,
|
||||
TimeoutSyncThreshold: 8,
|
||||
TimeoutPeriod: 50,
|
||||
WaitPeriod: 5,
|
||||
MinePeriod: 20,
|
||||
},
|
||||
7242300: {
|
||||
SwitchBlock: big.NewInt(7242300),
|
||||
171000: {
|
||||
SwitchRound: 171000,
|
||||
CertThreshold: common.MaxMasternodesV2*2/3 + 1,
|
||||
TimeoutSyncThreshold: 5,
|
||||
TimeoutPeriod: 25,
|
||||
|
|
@ -142,9 +128,9 @@ var (
|
|||
Gap: 450,
|
||||
FoudationWalletAddr: common.HexToAddress("xdc92a289fe95a85c53b8d0d113cbaef0c1ec98ac65"),
|
||||
V2: &V2{
|
||||
FirstSwitchBlock: MainnetV2Configs[0].SwitchBlock,
|
||||
CurrentConfig: MainnetV2Configs[0],
|
||||
AllConfigs: MainnetV2Configs,
|
||||
SwitchBlock: big.NewInt(9999999999),
|
||||
CurrentConfig: MainnetV2Configs[0],
|
||||
AllConfigs: MainnetV2Configs,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -184,7 +170,7 @@ var (
|
|||
Gap: 450,
|
||||
FoudationWalletAddr: common.HexToAddress("xdc746249c61f5832c5eed53172776b460491bdcd5c"),
|
||||
V2: &V2{
|
||||
FirstSwitchBlock: TestV2Configs[0].SwitchBlock,
|
||||
SwitchBlock: big.NewInt(900),
|
||||
CurrentConfig: TestV2Configs[0],
|
||||
AllConfigs: TestV2Configs,
|
||||
SkipV2Validation: true,
|
||||
|
|
@ -209,9 +195,9 @@ var (
|
|||
Gap: 450,
|
||||
FoudationWalletAddr: common.HexToAddress("0x746249c61f5832c5eed53172776b460491bdcd5c"),
|
||||
V2: &V2{
|
||||
FirstSwitchBlock: DevnetV2Configs[0].SwitchBlock,
|
||||
CurrentConfig: DevnetV2Configs[0],
|
||||
AllConfigs: DevnetV2Configs,
|
||||
SwitchBlock: big.NewInt(7074000),
|
||||
CurrentConfig: DevnetV2Configs[0],
|
||||
AllConfigs: DevnetV2Configs,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -232,9 +218,9 @@ var (
|
|||
Period: 15,
|
||||
Epoch: 30000,
|
||||
V2: &V2{
|
||||
FirstSwitchBlock: MainnetV2Configs[0].SwitchBlock,
|
||||
CurrentConfig: MainnetV2Configs[0],
|
||||
AllConfigs: MainnetV2Configs,
|
||||
SwitchBlock: big.NewInt(9999999999),
|
||||
CurrentConfig: MainnetV2Configs[0],
|
||||
AllConfigs: MainnetV2Configs,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -275,9 +261,9 @@ var (
|
|||
FoudationWalletAddr: common.HexToAddress("0x0000000000000000000000000000000000000068"),
|
||||
Reward: 250,
|
||||
V2: &V2{
|
||||
FirstSwitchBlock: TestV2Configs[0].SwitchBlock,
|
||||
CurrentConfig: TestV2Configs[0],
|
||||
AllConfigs: TestV2Configs,
|
||||
SwitchBlock: big.NewInt(900),
|
||||
CurrentConfig: TestV2Configs[0],
|
||||
AllConfigs: TestV2Configs,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -347,27 +333,78 @@ type XDPoSConfig struct {
|
|||
}
|
||||
|
||||
type V2 struct {
|
||||
FirstSwitchBlock *big.Int `json:"switchBlock"`
|
||||
CurrentConfig *V2Config `json:"config"`
|
||||
AllConfigs map[uint64]*V2Config `json:"allConfigs"`
|
||||
configIndex []uint64 //list of switch block of configs
|
||||
SkipV2Validation bool //Skip Block Validation for testing purpose, V2 consensus only
|
||||
lock sync.RWMutex // Protects the signer fields
|
||||
|
||||
SwitchBlock *big.Int `json:"switchBlock"`
|
||||
CurrentConfig *V2Config `json:"config"`
|
||||
AllConfigs map[uint64]*V2Config `json:"allConfigs"`
|
||||
configIndex []uint64 //list of switch block of configs
|
||||
|
||||
SkipV2Validation bool //Skip Block Validation for testing purpose, V2 consensus only
|
||||
}
|
||||
|
||||
type V2Config 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
|
||||
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
|
||||
SwitchRound uint64 `json:"switchRound"` // v1 to v2 switch block number
|
||||
WaitPeriod int `json:"waitPeriod"` // Miner wait period to check mine event
|
||||
MinePeriod int `json:"minePeriod"` // Miner mine period to mine a block
|
||||
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
|
||||
}
|
||||
|
||||
// String implements the stringer interface, returning the consensus engine details.
|
||||
func (c *XDPoSConfig) BuildConfigIndex() {
|
||||
func (c *XDPoSConfig) String() string {
|
||||
return "XDPoS"
|
||||
}
|
||||
|
||||
func (c *XDPoSConfig) BlockConsensusVersion(num *big.Int, extraByte []byte, extraCheck bool) string {
|
||||
if extraCheck && (len(extraByte) == 0 || extraByte[0] != 2) {
|
||||
return ConsensusEngineVersion1
|
||||
}
|
||||
|
||||
if c.V2 != nil && c.V2.SwitchBlock != nil && num.Cmp(c.V2.SwitchBlock) > 0 {
|
||||
return ConsensusEngineVersion2
|
||||
}
|
||||
return ConsensusEngineVersion1
|
||||
}
|
||||
|
||||
func (v *V2) UpdateConfig(round uint64) {
|
||||
v.lock.Lock()
|
||||
defer v.lock.Unlock()
|
||||
|
||||
var index uint64
|
||||
|
||||
//find the right config
|
||||
for i := range v.configIndex {
|
||||
if v.configIndex[i] <= round {
|
||||
index = v.configIndex[i]
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
// update to current config
|
||||
log.Info("[updateV2Config] Update config", "index", index, "round", round, "SwitchRound", v.AllConfigs[index].SwitchRound)
|
||||
v.CurrentConfig = v.AllConfigs[index]
|
||||
}
|
||||
|
||||
func (v *V2) Config(round uint64) *V2Config {
|
||||
configRound := round - 1 //start from next block from SwitchRound number
|
||||
var index uint64
|
||||
|
||||
//find the right config
|
||||
for i := range v.configIndex {
|
||||
if v.configIndex[i] <= configRound {
|
||||
index = v.configIndex[i]
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return v.AllConfigs[index]
|
||||
}
|
||||
|
||||
func (v *V2) BuildConfigIndex() {
|
||||
var list []uint64
|
||||
|
||||
for i := range c.V2.AllConfigs {
|
||||
for i := range v.AllConfigs {
|
||||
list = append(list, i)
|
||||
}
|
||||
|
||||
|
|
@ -379,40 +416,12 @@ func (c *XDPoSConfig) BuildConfigIndex() {
|
|||
}
|
||||
}
|
||||
}
|
||||
c.V2.configIndex = list
|
||||
log.Info("[BuildConfigIndex] config list", "list", list)
|
||||
v.configIndex = list
|
||||
}
|
||||
|
||||
func (c *XDPoSConfig) String() string {
|
||||
return "XDPoS"
|
||||
}
|
||||
|
||||
func (c *XDPoSConfig) updateV2Config(num uint64) {
|
||||
var index uint64
|
||||
|
||||
//find the right config
|
||||
for i := range c.V2.configIndex {
|
||||
if c.V2.configIndex[i] <= num {
|
||||
index = c.V2.configIndex[i]
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
// update to current config
|
||||
c.V2.CurrentConfig = c.V2.AllConfigs[index]
|
||||
}
|
||||
|
||||
func (c *XDPoSConfig) BlockConsensusVersion(num *big.Int, extraByte []byte, skipExtraCheck bool) string {
|
||||
if !skipExtraCheck && (len(extraByte) == 0 || extraByte[0] != 2) {
|
||||
return ConsensusEngineVersion1
|
||||
}
|
||||
|
||||
if c.V2 != nil && c.V2.FirstSwitchBlock != nil && num.Cmp(c.V2.FirstSwitchBlock) > 0 {
|
||||
// We have to check each block configuration due to reorg chain case
|
||||
// Block may get rollback and old config need to apply to verify block
|
||||
c.updateV2Config(num.Uint64() - 1)
|
||||
return ConsensusEngineVersion2
|
||||
}
|
||||
return ConsensusEngineVersion1
|
||||
func (v *V2) ConfigIndex() []uint64 {
|
||||
return v.configIndex
|
||||
}
|
||||
|
||||
// String implements the fmt.Stringer interface.
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ import (
|
|||
"math/big"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCheckCompatible(t *testing.T) {
|
||||
|
|
@ -79,3 +81,39 @@ func TestCheckCompatible(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateV2Config(t *testing.T) {
|
||||
TestnetChainConfig.XDPoS.V2.BuildConfigIndex()
|
||||
c := TestnetChainConfig.XDPoS.V2.CurrentConfig
|
||||
assert.Equal(t, 3, c.CertThreshold)
|
||||
|
||||
TestnetChainConfig.XDPoS.V2.UpdateConfig(10)
|
||||
c = TestnetChainConfig.XDPoS.V2.CurrentConfig
|
||||
assert.Equal(t, 5, c.CertThreshold)
|
||||
|
||||
TestnetChainConfig.XDPoS.V2.UpdateConfig(899)
|
||||
c = TestnetChainConfig.XDPoS.V2.CurrentConfig
|
||||
assert.Equal(t, 4, c.TimeoutSyncThreshold)
|
||||
}
|
||||
|
||||
func TestV2Config(t *testing.T) {
|
||||
TestnetChainConfig.XDPoS.V2.BuildConfigIndex()
|
||||
c := TestnetChainConfig.XDPoS.V2.Config(1)
|
||||
assert.Equal(t, 3, c.CertThreshold)
|
||||
|
||||
c = TestnetChainConfig.XDPoS.V2.Config(5)
|
||||
assert.Equal(t, 3, c.CertThreshold)
|
||||
|
||||
c = TestnetChainConfig.XDPoS.V2.Config(10)
|
||||
assert.Equal(t, 3, c.CertThreshold)
|
||||
|
||||
c = TestnetChainConfig.XDPoS.V2.Config(11)
|
||||
assert.Equal(t, 5, c.CertThreshold)
|
||||
}
|
||||
|
||||
func TestBuildConfigIndex(t *testing.T) {
|
||||
TestnetChainConfig.XDPoS.V2.BuildConfigIndex()
|
||||
index := TestnetChainConfig.XDPoS.V2.ConfigIndex()
|
||||
expected := []uint64{0, 10, 899}
|
||||
assert.Equal(t, expected, index)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue