public List<LogWithMetadata> matchingLogs(
      final Hash blockHash,
      final TransactionWithMetadata transactionWithMetaData,
      final Supplier<Boolean> isQueryAlive) {
    if (transactionWithMetaData.getTransactionIndex().isEmpty()) {
      throw new RuntimeException(
          "Cannot find logs because transaction "
              + transactionWithMetaData.getTransaction().getHash()
              + " does not have a transaction index");
    }

    try {
      final Optional<BlockHeader> blockHeader = getBlockHeader(blockHash, isQueryAlive);
      if (blockHeader.isEmpty()) {
        return Collections.emptyList();
      }
      // receipts and transactions should exist if the header exists, so throwing is ok.
      final List<TransactionReceipt> receipts = getReceipts(blockHash, isQueryAlive);
      final List<Transaction> transactions = getTransactions(blockHash, isQueryAlive);
      final long number = blockHeader.get().getNumber();
      final boolean removed = getRemoved(blockHash, isQueryAlive);

      final int transactionIndex = transactionWithMetaData.getTransactionIndex().get();
      final int logIndexOffset =
          logIndexOffset(
              transactionWithMetaData.getTransaction().getHash(), receipts, transactions);

      return LogWithMetadata.generate(
          logIndexOffset,
          receipts.get(transactionIndex),
          number,
          blockHash,
          transactions.get(transactionIndex).getHash(),
          transactionIndex,
          removed);

    } catch (final Exception e) {
      throw new RuntimeException(e);
    }
  }
Retrieve logs from the range of blocks with optional filtering based on logger address and log
topics.

@param fromBlockNumber The block number defining the first block in the search range
    (inclusive).
@param toBlockNumber The block number defining the last block in the search range (inclusive).
@param query Constraints on required topics by topic index. For a given index if the set of
    topics is non-empty, the topic at this index must match one of the values in the set.
@param isQueryAlive Whether the backend query should stay alive.
@return The set of logs matching the given constraints.
ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueries.java