code: func (sp *serverPeer) OnGetBlocks(_ *peer.Peer, msg *wire.MsgGetBlocks) {
  	// Find the most recent known block in the best chain based on the block
  	// locator and fetch all of the block hashes after it until either
  	// wire.MaxBlocksPerMsg have been fetched or the provided stop hash is
  	// encountered.
  	//
  	// Use the block after the genesis block if no other blocks in the
  	// provided locator are known.  This does mean the client will start
  	// over with the genesis block if unknown block locators are provided.
  	//
  	// This mirrors the behavior in the reference implementation.
  	chain := sp.server.chain
  	hashList := chain.LocateBlocks(msg.BlockLocatorHashes, &msg.HashStop,
  		wire.MaxBlocksPerMsg)
  
  	// Generate inventory message.
  	invMsg := wire.NewMsgInv()
  	for i := range hashList {
  		iv := wire.NewInvVect(wire.InvTypeBlock, &hashList[i])
  		invMsg.AddInvVect(iv)
  	}
  
  	// Send the inventory message if there is anything to send.
  	if len(invMsg.InvList) > 0 {
  		invListLen := len(invMsg.InvList)
  		if invListLen == wire.MaxBlocksPerMsg {
  			// Intentionally use a copy of the final hash so there
  			// is not a reference into the inventory slice which
  			// would prevent the entire slice from being eligible
  			// for GC as soon as it's sent.
  			continueHash := invMsg.InvList[invListLen-1].Hash
  			sp.continueHash = &continueHash
  		}
  		sp.QueueMessage(invMsg, nil)
  	}
  }
docs: // OnGetBlocks is invoked when a peer receives a getblocks bitcoin
  // message.