code: func (b *BlockChain) CheckConnectBlockTemplate(block *btcutil.Block) error {
  	b.chainLock.Lock()
  	defer b.chainLock.Unlock()
  
  	// Skip the proof of work check as this is just a block template.
  	flags := BFNoPoWCheck
  
  	// This only checks whether the block can be connected to the tip of the
  	// current chain.
  	tip := b.bestChain.Tip()
  	header := block.MsgBlock().Header
  	if tip.hash != header.PrevBlock {
  		str := fmt.Sprintf("previous block must be the current chain tip %v, "+
  			"instead got %v", tip.hash, header.PrevBlock)
  		return ruleError(ErrPrevBlockNotBest, str)
  	}
  
  	err := checkBlockSanity(block, b.chainParams.PowLimit, b.timeSource, flags)
  	if err != nil {
  		return err
  	}
  
  	err = b.checkBlockContext(block, tip, flags)
  	if err != nil {
  		return err
  	}
  
  	// Leave the spent txouts entry nil in the state since the information
  	// is not needed and thus extra work can be avoided.
  	view := NewUtxoViewpoint()
  	view.SetBestHash(&tip.hash)
  	newNode := newBlockNode(&header, tip)
  	return b.checkConnectBlock(newNode, block, view, nil)
  }
docs: // CheckConnectBlockTemplate fully validates that connecting the passed block to
  // the main chain does not violate any consensus rules, aside from the proof of
  // work requirement. The block must connect to the current tip of the main chain.
  //
  // This function is safe for concurrent access.