-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTransaction.java
More file actions
107 lines (85 loc) · 3.93 KB
/
Transaction.java
File metadata and controls
107 lines (85 loc) · 3.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import java.security.*;
import java.util.ArrayList;
public class Transaction {
public String transactionId; // this is also the hash of the transaction
public PublicKey sender; // senders address/public key
public PublicKey recipient; // recipients address/public key
public float value;
public byte[] signature; // this is to prevent anybody else from spending funds in our wallet
public ArrayList<TransactionInput> inputs = new ArrayList<TransactionInput>();
public ArrayList<TransactionOutputs> outputs = new ArrayList<TransactionOutputs>();
private static int sequence = 0; // a rough count of how many transactions have been generated
// Constructor:
public Transaction(PublicKey from, PublicKey to, float value, ArrayList<TransactionInput> inputs) {
this.sender = from;
this.recipient = to;
this.value = value;
this.inputs = inputs;
}
// This calculates the transaction hash (which will be used as its Id
private String calculateHash() {
sequence++; // increase the sequence to avoid 2 identical transactions having the same hash
return StringUtil.applySha256(StringUtil.getStringFromKey(sender) + StringUtil.getStringFromKey(recipient)
+ Float.toString(value) + sequence);
}
// Signs all the data we don't wish to be tampered with.
public void generateSignature(PrivateKey privateKey) {
String data = StringUtil.getStringFromKey(sender) + StringUtil.getStringFromKey(recipient)
+ Float.toString(value);
signature = StringUtil.applyECDSASig(privateKey, data);
}
// Verifies the data we signed hasn't been tampered with
public boolean verifySignature() {
String data = StringUtil.getStringFromKey(sender) + StringUtil.getStringFromKey(recipient)
+ Float.toString(value);
return StringUtil.verifyECDSASig(sender, data, signature);
}
// Returns true if new transaction could be created
public boolean processTransaction() {
if(verifySignature() == false) {
System.out.println("#Transaction Signature failed to verify");
return false;
}
//gather transaction inputs (Make sure they are unspent)
for(TransactionInput i : inputs) {
i.UTXO = Chain.UTXOs.get(i.transactionOutputId);
}
//check if transaction is valid
if(getInputsValue() < Chain.minimumTransaction) {
System.out.println("Transaction Inputs too small: " + getInputsValue());
return false;
}
//generate transaction outputs
float leftOver = getInputsValue() - value; //get value of inputs then the left over change
transactionId = calculateHash();
outputs.add(new TransactionOutputs(this.recipient, value, transactionId)); //send value to recipient
outputs.add(new TransactionOutputs(this.sender, leftOver, transactionId)); //send the left over 'change' back to sender
// add outputs to Unspent list
for(TransactionOutputs o : outputs) {
Chain.UTXOs.put(o.id, o);
}
//Remove transaction inputs from UTXO lists as spent
for(TransactionInput i : inputs) {
if(i.UTXO == null) continue; // if transaction can't be found skip it
Chain.UTXOs.remove(i.UTXO.id);
}
return true;
}
// returns sum of inputs(UTXOs) values
public float getInputsValue() {
float total = 0;
for (TransactionInput i : inputs) {
if(i.UTXO == null) continue; // if Transaction can't be found skip it
total+= i.UTXO.value;
}
return total;
}
//returns sum of outputs
public float getOutputsValue() {
float total = 0;
for (TransactionOutputs o : outputs) {
total += o.value;
}
return total;
}
}