code: func (c *Clique) verifyCascadingFields(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error {
  	// The genesis block is the always valid dead-end
  	number := header.Number.Uint64()
  	if number == 0 {
  		return nil
  	}
  	// Ensure that the block's timestamp isn't too close to it's parent
  	var parent *types.Header
  	if len(parents) > 0 {
  		parent = parents[len(parents)-1]
  	} else {
  		parent = chain.GetHeader(header.ParentHash, number-1)
  	}
  	if parent == nil || parent.Number.Uint64() != number-1 || parent.Hash() != header.ParentHash {
  		return consensus.ErrUnknownAncestor
  	}
  	if parent.Time+c.config.Period > header.Time {
  		return ErrInvalidTimestamp
  	}
  	// Retrieve the snapshot needed to verify this header and cache it
  	snap, err := c.snapshot(chain, number-1, header.ParentHash, parents)
  	if err != nil {
  		return err
  	}
  	// If the block is a checkpoint block, verify the signer list
  	if number%c.config.Epoch == 0 {
  		signers := make([]byte, len(snap.Signers)*common.AddressLength)
  		for i, signer := range snap.signers() {
  			copy(signers[i*common.AddressLength:], signer[:])
  		}
  		extraSuffix := len(header.Extra) - extraSeal
  		if !bytes.Equal(header.Extra[extraVanity:extraSuffix], signers) {
  			return errMismatchingCheckpointSigners
  		}
  	}
  	// All basic checks passed, verify the seal and return
  	return c.verifySeal(chain, header, parents)
  }
docs: // verifyCascadingFields verifies all the header fields that are not standalone,
  // rather depend on a batch of previous headers. The caller may optionally pass
  // in a batch of parents (ascending order) to avoid looking those up from the
  // database. This is useful for concurrently verifying a batch of new headers.