-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathIotaAPIUtils.java
More file actions
156 lines (125 loc) · 5.99 KB
/
IotaAPIUtils.java
File metadata and controls
156 lines (125 loc) · 5.99 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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package jota.utils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jota.model.Bundle;
import jota.model.Input;
import jota.model.Transaction;
/**
* Client Side computation service
*
* @author davassi
*/
public class IotaAPIUtils {
private static final Logger log = LoggerFactory.getLogger(IotaAPIUtils.class);
/**
* Generates a new address
*
* @param seed
* @param index
* @param checksum
* @return an String with address
*/
public static String newAddress(String seed, int index, boolean checksum) {
final int[] key = Signing.key(Converter.trits(seed), index, 2);
final int[] digests = Signing.digests(key);
final int[] addressTrits = Signing.address(digests);
String address = Converter.trytes(addressTrits);
if (checksum) {
address = Checksum.addChecksum(address);
}
return address;
}
public static String transactionTrytes(Transaction trx) {
int[] valueTrits = Converter.trits(trx.getValue());
while (valueTrits.length < 81) {
valueTrits[valueTrits.length] = 0;
}
int[] timestampTrits = Converter.trits(trx.getTimestamp());
while (timestampTrits.length < 27) {
timestampTrits[timestampTrits.length] = 0;
}
int[] currentIndexTrits = Converter.trits(trx.getTimestamp());
while (currentIndexTrits.length < 27) {
currentIndexTrits[currentIndexTrits.length] = 0;
}
int[] lastIndexTrits = Converter.trits(trx.getCurrentIndex());
while (lastIndexTrits.length < 27) {
lastIndexTrits[lastIndexTrits.length] = 0;
}
return trx.getSignatureFragments()
+ trx.getAddress()
+ Converter.trytes(valueTrits)
+ trx.getTag()
+ Converter.trytes(timestampTrits)
+ Converter.trytes(currentIndexTrits)
+ Converter.trytes(lastIndexTrits)
+ trx.getBundle()
+ trx.getTrunkTransaction()
+ trx.getBranchTransaction()
+ trx.getNonce();
}
public static List<String> signInputsAndReturn(final String seed,
final List<Input> inputs,
final Bundle bundle,
final List<String> signatureFragments) {
bundle.finalize();
bundle.addTrytes(signatureFragments);
// SIGNING OF INPUTS
//
// Here we do the actual signing of the inputs
// Iterate over all bundle transactions, find the inputs
// Get the corresponding private key and calculate the signatureFragment
for (int i = 0; i < bundle.getTransactions().size(); i++) {
if (Long.parseLong(bundle.getTransactions().get(i).getValue()) < 0) {
String thisAddress = bundle.getTransactions().get(i).getAddress();
// Get the corresponding keyIndex of the address
int keyIndex = 0;
for (int k = 0; k < inputs.size(); k++) {
if (inputs.get(k).getAddress().equals(thisAddress)) {
keyIndex = inputs.get(k).getKeyIndex();
break;
}
}
String bundleHash = bundle.getTransactions().get(i).getBundle();
// Get corresponding private key of address
int[] key = Signing.key(Converter.trits(seed), keyIndex, 2);
// First 6561 trits for the firstFragment
int[] firstFragment = Arrays.copyOfRange(key, 0, 6561);
// Get the normalized bundle hash
int[] normalizedBundleHash = bundle.normalizedBundle(bundleHash);
// First bundle fragment uses 27 trytes
int[] firstBundleFragment = Arrays.copyOfRange(normalizedBundleHash, 0, 27);
// Calculate the new signatureFragment with the first bundle fragment
int[] firstSignedFragment = Signing.signatureFragment(firstBundleFragment, firstFragment);
// Convert signature to trytes and assign the new signatureFragment
bundle.getTransactions().get(i).setSignatureFragments(Converter.trytes(firstSignedFragment));
// Because the signature is > 2187 trytes, we need to
// find the second transaction to add the remainder of the signature
for (int j = 0; j < bundle.getTransactions().size(); j++) {
// Same address as well as value = 0 (as we already spent the input)
if (bundle.getTransactions().get(j).getAddress() == thisAddress && Long.parseLong(bundle.getTransactions().get(j).getValue()) == 0) {
// Use the second 6562 trits
int[] secondFragment = Arrays.copyOfRange(key, 6561, 6561 * 2);
// The second 27 to 54 trytes of the bundle hash
int[] secondBundleFragment = Arrays.copyOfRange(normalizedBundleHash, 27, 27 * 2);
// Calculate the new signature
int[] secondSignedFragment = Signing.signatureFragment(secondBundleFragment, secondFragment);
// Convert signature to trytes and assign it again to this bundle entry
bundle.getTransactions().get(j).setSignatureFragments(Converter.trytes(secondSignedFragment));
}
}
}
}
List<String> bundleTrytes = new ArrayList<>();
// Convert all bundle entries into trytes
for (Transaction tx : bundle.getTransactions()) {
bundleTrytes.add(IotaAPIUtils.transactionTrytes(tx));
}
Collections.reverse(bundleTrytes);
return bundleTrytes;
}
}