Skip to content

Instantly share code, notes, and snippets.

@108anup
Created December 31, 2016 07:36
Show Gist options
  • Save 108anup/62425d98f119a2a25fe57845518019be to your computer and use it in GitHub Desktop.
Save 108anup/62425d98f119a2a25fe57845518019be to your computer and use it in GitHub Desktop.
Bitcoin and Cryptocurrency Technologies - Assignment 1
import java.util.HashSet;
import java.util.ArrayList;
public class TxHandler {
private UTXOPool utxoPool;
/**
* 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.
*/
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) {
ArrayList<Transaction.Input> inputs = tx.getInputs();
ArrayList<Transaction.Output> outputs = tx.getOutputs();
double ipSum = 0;
double opSum = 0;
for(int i = 0; i<outputs.size(); i++){
//Output value is non negative
if(outputs.get(i).value<0)
return false;
opSum += outputs.get(i).value;
}
Crypto crypto = new Crypto();
HashSet<UTXO> claimed = new HashSet<UTXO>();
for(int i= 0; i<inputs.size(); i++){
Transaction.Input ip = inputs.get(i);
UTXO u = new UTXO(ip.prevTxHash,ip.outputIndex);
Transaction.Output correspondingTO = utxoPool.getTxOutput(u);
//Output claimed for input is in UTXO Pool
if(correspondingTO == null)
return false;
//The Tx has been verified by the user which is giving the input (taken from corresponding Output in UTXO Pool)
if(!crypto.verifySignature(correspondingTO.address,tx.getRawDataToSign(i),ip.signature))
return false;
//Check Double Spending aka the same UTXO is not claimed more than once
if(claimed.contains(u))
return false;
else{
ipSum += correspondingTO.value;
claimed.add(u);
}
}
//Output is less than equal to input
if(opSum > ipSum)
return false;
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> maximalSelected = new ArrayList<Transaction>();
for(int j = 0; j<possibleTxs.length; j++){
Transaction tx = possibleTxs[j];
if(isValidTx(tx)){
maximalSelected.add(tx);
ArrayList<Transaction.Input> inputs = tx.getInputs();
ArrayList<Transaction.Output> outputs = tx.getOutputs();
//Remove the UTXOs claimed in this transaction
for(int i= 0; i<inputs.size(); i++){
Transaction.Input ip = inputs.get(i);
UTXO u = new UTXO(ip.prevTxHash,ip.outputIndex);
utxoPool.removeUTXO(u);
}
//Add UTXOs generated in this transaction
//These can be used by subsequent transactions
for(int i= 0; i<outputs.size(); i++){
UTXO u = new UTXO(tx.getHash(),i);
utxoPool.addUTXO(u,outputs.get(i));
}
}
}
return maximalSelected.toArray(new Transaction[maximalSelected.size()]);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment