import java.security.PublicKey;import java.util.function.Function;import java.util.stream.Collectors;import java.util.stream.IntStream;import java.util.*;public class TxHandler {        public UTXOPool ledge;    public TxHandler(UTXOPool utxoPool) {        this.ledge = new UTXOPool(utxoPool);    }    public boolean isValidTx(Transaction tx) {        return (allInputsInPool(tx) &&                 allInputSignaturesValid(tx) &&                 noInputsClaimedMultiple(tx) &&                 allOutputsNonNegative(tx) &&                 (transactionFee(tx) >= 0.0));     }    public Transaction handleTxs(Transaction possibleTxs) {        return Arrays.stream(possibleTxs)                .filter( tx -> isValidTx(tx))                .peek(this::updatePoolLedger)                .toArray(Transaction::new);    }        private void updatePoolLedger(Transaction tx) {        tx.getInputs().forEach(inp -> ledge.removeUTXO(new UTXO(inp.prevTxHash, inp.outputIndex)));        IntStream.range(0, tx.numOutputs())                .forEach(idx -> ledge.addUTXO(new UTXO(tx.getHash(), idx), tx.getOutput(idx)));            }    private boolean allInputsInPool(Transaction tx) {        return tx.getInputs().stream()                 .map(inp ->  new UTXO(inp.prevTxHash,inp.outputIndex))                 .allMatch( utxo -> ledge.contains(utxo));         }    private boolean allInputSignaturesValid(Transaction tx) {        return IntStream.range(0, tx.numInputs())                .allMatch(idx -> {                                        Transaction.Input inp = tx.getInput(idx);                    byte mg = tx.getRawDataToSign(idx);                                        byte sg = inp.signature;                    PublicKey pksign = ledge.getTxOutput(new UTXO(inp.prevTxHash, inp.outputIndex)).address;                                        return Crypto.verifySignature(pksign, mg, sg);                });    }    private boolean noInputsClaimedMultiple(Transaction tx) {                return tx.getInputs().stream()                .map(inp -> new UTXO(inp.prevTxHash,inp.outputIndex))                 .collect(Collectors.toSet())                 .size() == tx.numInputs();    }    private boolean allOutputsNonNegative(Transaction tx) {        return tx.getOutputs().stream()                .allMatch(o -> o.value>=0);     }    private double transactionFee(Transaction tx) {        double ipSum, outSum;        ipSum = tx.getInputs().stream()                .mapToDouble(inp -> ledge.getTxOutput(new UTXO(inp.prevTxHash,inp.outputIndex)).value)                .sum();        outSum = tx.getOutputs().stream()                .mapToDouble(o -> o.value)                .sum();        return ipSum – outSum;    }    }