@Override
  public synchronized void remove(
      final PendingTransaction invalidatedTx, final PoolRemovalReason reason) {

    final var senderTxs = txsBySender.get(invalidatedTx.getSender());
    if (senderTxs != null && senderTxs.containsKey(invalidatedTx.getNonce())) {
      // gaps are allowed here then just remove
      senderTxs.remove(invalidatedTx.getNonce());
      processRemove(senderTxs, invalidatedTx.getTransaction(), reason);
      if (senderTxs.isEmpty()) {
        txsBySender.remove(invalidatedTx.getSender());
      }
    } else {
      nextLayer.remove(invalidatedTx, reason);
    }
  }
We only want to promote transactions that have gap == 0, so there will be no gap in the prev
layers. A promoted transaction is removed from this layer, and the gap data is updated for its
sender.

@param promotionFilter the prev layer's promotion filter
@param freeSpace max amount of memory promoted txs can occupy
@param freeSlots max number of promoted txs
@return a list of transactions promoted to the prev layer
ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/SparseTransactions.java