diff --git a/common/constants.go b/common/constants.go index 8d755d2e7d..4439f36a1d 100644 --- a/common/constants.go +++ b/common/constants.go @@ -24,6 +24,7 @@ const ( var TIP2019Block = big.NewInt(1050000) var TIPSigning = big.NewInt(3000000) +var TIPRandomize = big.NewInt(901) var IsTestnet bool = false var StoreRewardFolder string var RollbackHash Hash diff --git a/consensus/XDPoS/XDPoS.go b/consensus/XDPoS/XDPoS.go index 562b3cb770..8639ba8153 100644 --- a/consensus/XDPoS/XDPoS.go +++ b/consensus/XDPoS/XDPoS.go @@ -226,7 +226,7 @@ type XDPoS struct { lock sync.RWMutex // Protects the signer fields BlockSigners *lru.Cache - HookReward func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) (error, map[string]interface{}) + HookReward func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) (error, map[string]interface{}) HookPenalty func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error) HookPenaltyTIPSigning func(chain consensus.ChainReader, header *types.Header, candidate []common.Address) ([]common.Address, error) HookValidator func(header *types.Header, signers []common.Address) ([]byte, error) @@ -739,7 +739,7 @@ func (c *XDPoS) GetValidator(creator common.Address, chain consensus.ChainReader return common.Address{}, fmt.Errorf("couldn't find checkpoint header") } } - m, err := GetM1M2FromCheckpointHeader(cpHeader) + m, err := GetM1M2FromCheckpointHeader(cpHeader, header, chain.Config()) if err != nil { return common.Address{}, err } @@ -1125,7 +1125,7 @@ func GetMasternodesFromCheckpointHeader(checkpointHeader *types.Header) []common } // Get m2 list from checkpoint block. -func GetM1M2FromCheckpointHeader(checkpointHeader *types.Header) (map[common.Address]common.Address, error) { +func GetM1M2FromCheckpointHeader(checkpointHeader *types.Header, currentHeader *types.Header, config *params.ChainConfig) (map[common.Address]common.Address, error) { if checkpointHeader.Number.Uint64()%common.EpocBlockRandomize != 0 { return nil, errors.New("This block is not checkpoint block epoc.") } @@ -1134,13 +1134,24 @@ func GetM1M2FromCheckpointHeader(checkpointHeader *types.Header) (map[common.Add masternodes := GetMasternodesFromCheckpointHeader(checkpointHeader) validators := ExtractValidatorsFromBytes(checkpointHeader.Validators) - if len(validators) < len(masternodes) { - return nil, errors.New("len(m2) is less than len(m1)") + maxMNs := len(masternodes) + if len(validators) < maxMNs { + return nil, errors.New("len(m2) is less than len(m1)") } - if len(masternodes) > 0 { - for i, m1 := range masternodes { - m1m2[m1] = masternodes[validators[i]%int64(len(masternodes))] + if maxMNs > 0 { + isForked := config.IsTIPRandomize(currentHeader.Number) + moveM2 := uint64(0) + if isForked { + moveM2 = (currentHeader.Number.Uint64() % config.XDPoS.Epoch) / uint64(maxMNs) } + for i, m1 := range masternodes { + m2Index := uint64(validators[i] % int64(maxMNs)) + m2Index = m2Index + moveM2 + if m2Index >= common.MaxMasternodes { + m2Index = m2Index - common.MaxMasternodes + } + m1m2[m1] = masternodes[m2Index] + } } return m1m2, nil } diff --git a/eth/backend.go b/eth/backend.go index 0cd9ed3adb..e44fa24b58 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -322,7 +322,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { c.HookPenaltyTIPSigning = func(chain consensus.ChainReader, header *types.Header, candidates []common.Address) ([]common.Address, error) { prevEpoc := header.Number.Uint64() - chain.Config().XDPoS.Epoch combackEpoch := uint64(0) - comebackLength := uint64((common.LimitPenaltyEpoch + 1) * chain.Config().XDPoS.Epoch) + comebackLength := (common.LimitPenaltyEpoch + 1) * chain.Config().XDPoS.Epoch if header.Number.Uint64() > comebackLength { combackEpoch = header.Number.Uint64() - comebackLength }