-
-
Save takuti/50ef664cf49fc0a0c32bcca095b15062 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.ArrayList; | |
import java.util.HashSet; | |
public class TxHandler { | |
/** | |
* Creates a public ledger whose current UTXOPool (collection of unspent transaction outputs) is | |
* {@code utxoPool}. This should make a copy of utxoPool by using the UTXOPool(UTXOPool uPool) | |
* constructor. | |
*/ | |
private UTXOPool utxoPool; | |
public TxHandler(UTXOPool utxoPool) { | |
this.utxoPool = new UTXOPool(utxoPool); | |
} | |
/** | |
* @return true if: | |
* (1) all outputs claimed by {@code tx} are in the current UTXO pool, | |
* (2) the signatures on each input of {@code tx} are valid, | |
* (3) no UTXO is claimed multiple times by {@code tx}, | |
* (4) all of {@code tx}s output values are non-negative, and | |
* (5) the sum of {@code tx}s input values is greater than or equal to the sum of its output | |
* values; and false otherwise. | |
*/ | |
public boolean isValidTx(Transaction tx) { | |
HashSet<UTXO> claimedUTXO = new HashSet<>(); | |
double inTotal = 0.d; | |
for (int i = 0; i < tx.numInputs(); i++) { | |
Transaction.Input in = tx.getInput(i); | |
UTXO ut = new UTXO(in.prevTxHash, in.outputIndex); | |
// (1) | |
if (!utxoPool.contains(ut)) return false; | |
// (2) | |
Transaction.Output out = utxoPool.getTxOutput(ut); | |
if (!Crypto.verifySignature(out.address, tx.getRawDataToSign(i), in.signature)) return false; | |
// (3) | |
if (claimedUTXO.contains(ut)) return false; | |
claimedUTXO.add(ut); | |
// for (5) | |
inTotal += out.value; | |
} | |
for (Transaction.Output out : tx.getOutputs()) { | |
// (4) | |
if (out.value < 0.d) return false; | |
// (5) | |
inTotal -= out.value; | |
if (inTotal < 0.d) return false; // when total output value exceeds total input | |
} | |
return true; | |
} | |
/** | |
* Handles each epoch by receiving an unordered array of proposed transactions, checking each | |
* transaction for correctness, returning a mutually valid array of accepted transactions, and | |
* updating the current UTXO pool as appropriate. | |
*/ | |
public Transaction[] handleTxs(Transaction[] possibleTxs) { | |
ArrayList<Transaction> acceptedTxs = new ArrayList<>(); | |
for (Transaction tx : possibleTxs) { | |
if (!isValidTx(tx)) continue; | |
acceptedTxs.add(tx); | |
// remove spent from prev tx | |
for (Transaction.Input in : tx.getInputs()) { | |
UTXO ut = new UTXO(in.prevTxHash, in.outputIndex); | |
utxoPool.removeUTXO(ut); | |
} | |
// add coins created by this tx | |
for (int i = 0; i < tx.numOutputs(); i++) { | |
UTXO ut = new UTXO(tx.getHash(), i); | |
utxoPool.addUTXO(ut, tx.getOutput(i)); | |
} | |
} | |
return acceptedTxs.toArray(new Transaction[acceptedTxs.size()]); | |
} | |
public UTXOPool getUTXOPool() { | |
return utxoPool; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment