code: func (lc *LightChain) InsertHeaderChain(chain []*types.Header, checkFreq int) (int, error) {
  	if atomic.LoadInt32(&lc.disableCheckFreq) == 1 {
  		checkFreq = 0
  	}
  	start := time.Now()
  	if i, err := lc.hc.ValidateHeaderChain(chain, checkFreq); err != nil {
  		return i, err
  	}
  
  	// Make sure only one thread manipulates the chain at once
  	lc.chainmu.Lock()
  	defer lc.chainmu.Unlock()
  
  	lc.wg.Add(1)
  	defer lc.wg.Done()
  
  	var events []interface{}
  	whFunc := func(header *types.Header) error {
  		status, err := lc.hc.WriteHeader(header)
  
  		switch status {
  		case core.CanonStatTy:
  			log.Debug("Inserted new header", "number", header.Number, "hash", header.Hash())
  			events = append(events, core.ChainEvent{Block: types.NewBlockWithHeader(header), Hash: header.Hash()})
  
  		case core.SideStatTy:
  			log.Debug("Inserted forked header", "number", header.Number, "hash", header.Hash())
  			events = append(events, core.ChainSideEvent{Block: types.NewBlockWithHeader(header)})
  		}
  		return err
  	}
  	i, err := lc.hc.InsertHeaderChain(chain, whFunc, start)
  	lc.postChainEvents(events)
  	return i, err
  }
docs: // InsertHeaderChain attempts to insert the given header chain in to the local
  // chain, possibly creating a reorg. If an error is returned, it will return the
  // index number of the failing header as well an error describing what went wrong.
  //
  // The verify parameter can be used to fine tune whether nonce verification
  // should be done or not. The reason behind the optional check is because some
  // of the header retrieval mechanisms already need to verfy nonces, as well as
  // because nonces can be verified sparsely, not needing to check each.
  //
  // In the case of a light chain, InsertHeaderChain also creates and posts light
  // chain events when necessary.