@Override
  protected PendingPeerRequest sendRequest() {
    final List<Hash> blockHashes =
        headers.stream().map(BlockHeader::getHash).collect(Collectors.toList());
    LOG.atTrace()
        .setMessage("Requesting {} bodies with hashes {}.")
        .addArgument(blockHashes.size())
        .addArgument(blockHashes)
        .log();
    final long minimumRequiredBlockNumber = headers.get(headers.size() - 1).getNumber();

    return sendRequestToPeer(
        peer -> {
          LOG.atTrace()
              .setMessage("Requesting {} bodies from peer {}.")
              .addArgument(blockHashes.size())
              .addArgument(peer)
              .log();
          return peer.getBodies(blockHashes);
        },
        minimumRequiredBlockNumber);
  }
Requests bodies from a peer by header, matches up headers to bodies, and returns blocks.
ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/task/GetBodiesFromPeerTask.java