|
|
@ -690,10 +690,15 @@ func (consensus *Consensus) commitBlock(blk *types.Block, committedMsg *FBFTMess |
|
|
|
// This function must be called with enabled leader rotation.
|
|
|
|
// This function must be called with enabled leader rotation.
|
|
|
|
func (consensus *Consensus) rotateLeader(epoch *big.Int) { |
|
|
|
func (consensus *Consensus) rotateLeader(epoch *big.Int) { |
|
|
|
var ( |
|
|
|
var ( |
|
|
|
bc = consensus.Blockchain() |
|
|
|
bc = consensus.Blockchain() |
|
|
|
prev = consensus.getLeaderPubKey() |
|
|
|
prev = consensus.getLeaderPubKey() |
|
|
|
leader = consensus.getLeaderPubKey() |
|
|
|
leader = consensus.getLeaderPubKey() |
|
|
|
|
|
|
|
curBlock = bc.CurrentBlock() |
|
|
|
|
|
|
|
curNumber = curBlock.NumberU64() |
|
|
|
|
|
|
|
curEpoch = curBlock.Epoch().Uint64() |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
const blocksCountAliveness = 10 |
|
|
|
|
|
|
|
|
|
|
|
utils.Logger().Info().Msgf("[Rotating leader] epoch: %v rotation:%v external rotation %v", epoch.Uint64(), bc.Config().IsLeaderRotationInternalValidators(epoch), bc.Config().IsLeaderRotationExternalValidatorsAllowed(epoch)) |
|
|
|
utils.Logger().Info().Msgf("[Rotating leader] epoch: %v rotation:%v external rotation %v", epoch.Uint64(), bc.Config().IsLeaderRotationInternalValidators(epoch), bc.Config().IsLeaderRotationExternalValidatorsAllowed(epoch)) |
|
|
|
ss, err := bc.ReadShardState(epoch) |
|
|
|
ss, err := bc.ReadShardState(epoch) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
@ -741,18 +746,59 @@ func (consensus *Consensus) rotateLeader(epoch *big.Int) { |
|
|
|
var ( |
|
|
|
var ( |
|
|
|
wasFound bool |
|
|
|
wasFound bool |
|
|
|
next *bls.PublicKeyWrapper |
|
|
|
next *bls.PublicKeyWrapper |
|
|
|
|
|
|
|
offset = 1 |
|
|
|
) |
|
|
|
) |
|
|
|
if bc.Config().IsLeaderRotationExternalValidatorsAllowed(epoch) { |
|
|
|
|
|
|
|
wasFound, next = consensus.Decider.NthNextValidator(committee.Slots, leader, 1) |
|
|
|
for { |
|
|
|
} else { |
|
|
|
if bc.Config().IsLeaderRotationExternalValidatorsAllowed(epoch) { |
|
|
|
wasFound, next = consensus.Decider.NthNextHmy(shard.Schedule.InstanceForEpoch(epoch), leader, 1) |
|
|
|
wasFound, next = consensus.Decider.NthNextValidator(committee.Slots, leader, offset) |
|
|
|
} |
|
|
|
} else { |
|
|
|
if !wasFound { |
|
|
|
wasFound, next = consensus.Decider.NthNextHmy(shard.Schedule.InstanceForEpoch(epoch), leader, offset) |
|
|
|
utils.Logger().Error().Msg("Failed to get next leader") |
|
|
|
} |
|
|
|
return |
|
|
|
if !wasFound { |
|
|
|
} else { |
|
|
|
utils.Logger().Error().Msg("Failed to get next leader") |
|
|
|
|
|
|
|
// Seems like nothing we can do here.
|
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
members := consensus.Decider.Participants() |
|
|
|
|
|
|
|
mask := bls.NewMask(members) |
|
|
|
|
|
|
|
skipped := 0 |
|
|
|
|
|
|
|
for i := 0; i < blocksCountAliveness; i++ { |
|
|
|
|
|
|
|
header := bc.GetHeaderByNumber(curNumber - uint64(i)) |
|
|
|
|
|
|
|
if header == nil { |
|
|
|
|
|
|
|
utils.Logger().Error().Msgf("Failed to get header by number %d", curNumber-uint64(i)) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// if epoch is different, we should not check this block.
|
|
|
|
|
|
|
|
if header.Epoch().Uint64() != curEpoch { |
|
|
|
|
|
|
|
break |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// Populate the mask with the bitmap.
|
|
|
|
|
|
|
|
err = mask.SetMask(header.LastCommitBitmap()) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
utils.Logger().Err(err).Msg("Failed to set mask") |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
ok, err := mask.KeyEnabled(next.Bytes) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
utils.Logger().Err(err).Msg("Failed to get key enabled") |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if !ok { |
|
|
|
|
|
|
|
skipped++ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// no signature from the next leader at all, we should skip it.
|
|
|
|
|
|
|
|
if skipped >= blocksCountAliveness { |
|
|
|
|
|
|
|
// Next leader is not signing blocks, we should skip it.
|
|
|
|
|
|
|
|
offset++ |
|
|
|
|
|
|
|
continue |
|
|
|
|
|
|
|
} |
|
|
|
consensus.setLeaderPubKey(next) |
|
|
|
consensus.setLeaderPubKey(next) |
|
|
|
|
|
|
|
break |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if consensus.isLeader() && !consensus.getLeaderPubKey().Object.IsEqual(prev.Object) { |
|
|
|
if consensus.isLeader() && !consensus.getLeaderPubKey().Object.IsEqual(prev.Object) { |
|
|
|
// leader changed
|
|
|
|
// leader changed
|
|
|
|
go func() { |
|
|
|
go func() { |
|
|
|