diff --git a/consensus/bor/bor.go b/consensus/bor/bor.go index 994465155efaf65dbafb906181846db6564a8977..84fabf3336685fc8a33671fea37bfe9e94f6a3a0 100644 --- a/consensus/bor/bor.go +++ b/consensus/bor/bor.go @@ -429,8 +429,9 @@ func (c *Bor) verifyCascadingFields(chain consensus.ChainReader, header *types.H return err } - // If the block is a sprint end block, verify the validator list - if number%c.config.Sprint == 0 { + isSprintEnd := (number+1)%c.config.Sprint == 0 + // verify the validator list in the last sprint block + if isSprintEnd { validatorsBytes := make([]byte, len(snap.ValidatorSet.Validators)*validatorHeaderBytesLength) currentValidators := snap.ValidatorSet.Copy().Validators @@ -439,6 +440,10 @@ func (c *Bor) verifyCascadingFields(chain consensus.ChainReader, header *types.H for i, validator := range currentValidators { copy(validatorsBytes[i*validatorHeaderBytesLength:], validator.HeaderBytes()) } + // len(header.Extra) >= extraVanity+extraSeal has already been validated in validateHeaderExtraField, so this won't result in a panic + if !bytes.Equal(header.Extra[extraVanity : len(header.Extra)-extraSeal], validatorsBytes) { + return errMismatchingSprintValidators + } } // All basic checks passed, verify the seal and return @@ -474,7 +479,7 @@ func (c *Bor) snapshot(chain consensus.ChainReader, number uint64, hash common.H // up more headers than allowed to be reorged (chain reinit from a freezer), // consider the checkpoint trusted and snapshot it. // TODO fix this - if number == 0 /* || (number%c.config.Sprint == 0 && (len(headers) > params.ImmutabilityThreshold || chain.GetHeaderByNumber(number-1) == nil)) */ { + if number == 0 { checkpoint := chain.GetHeaderByNumber(number) if checkpoint != nil { // get checkpoint data diff --git a/consensus/bor/bor_test/helper.go b/consensus/bor/bor_test/helper.go index 9a5c0facc561a073075ff4150a590103ce8f3908..1ead54ed88a9d02c3bdc2a5c8176700dfd6a2ab2 100644 --- a/consensus/bor/bor_test/helper.go +++ b/consensus/bor/bor_test/helper.go @@ -105,7 +105,16 @@ func buildMinimalNextHeader(t *testing.T, block *types.Block, borConfig *params. header.Number.Add(header.Number, big.NewInt(1)) header.ParentHash = block.Hash() header.Time += bor.CalcProducerDelay(header.Number.Uint64(), borConfig.Period, borConfig.Sprint, borConfig.ProducerDelay) - header.Extra = make([]byte, 97) // vanity (32) + extraSeal (65) + isSprintEnd := (header.Number.Uint64()+1)%borConfig.Sprint == 0 + if isSprintEnd { + header.Extra = make([]byte, 32 + 40 + 65) // vanity + validatorBytes + extraSeal + // the genesis file was initialized with a validator 0x71562b71999873db5b286df957af199ec94617f7 with power 10 + // So, if you change ./genesis.json, do change the following as well + validatorBytes, _ := hex.DecodeString("71562b71999873db5b286df957af199ec94617f7000000000000000000000000000000000000000a") + copy(header.Extra[32:72], validatorBytes) + } else { + header.Extra = make([]byte, 32 + 65) // vanity + extraSeal + } _key, _ := hex.DecodeString(privKey) sig, err := secp256k1.Sign(crypto.Keccak256(bor.BorRLP(header)), _key) if err != nil {