Skip to content
This repository was archived by the owner on Jun 7, 2023. It is now read-only.

Commit 4c9e1ee

Browse files
committed
updated PearlDiver
1 parent 1c21140 commit 4c9e1ee

File tree

1 file changed

+115
-98
lines changed

1 file changed

+115
-98
lines changed

src/main/java/cfb/pearldiver/PearlDiver.java

Lines changed: 115 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,62 @@
11
package cfb.pearldiver;
22

3+
import static cfb.pearldiver.PearlDiver.State.CANCELLED;
4+
import static cfb.pearldiver.PearlDiver.State.COMPLETED;
5+
import static cfb.pearldiver.PearlDiver.State.RUNNING;
6+
import static jota.pow.JCurl.NUMBER_OF_ROUNDSP81;
7+
8+
39
/**
4-
* (c) 2016 Come-from-Beyond.
5-
*
6-
* See <https://github.com/iotaledger/PearlDiver>.
10+
* (c) 2016 Come-from-Beyond
11+
* See <https://github.com/iotaledger/iri/blob/dev/src/main/java/com/iota/iri/hash/PearlDiver.java
712
*/
813
public class PearlDiver {
914

10-
public static final int TRANSACTION_LENGTH = 8019;
15+
enum State {
16+
RUNNING,
17+
CANCELLED,
18+
COMPLETED
19+
}
20+
21+
private static final int TRANSACTION_LENGTH = 8019;
1122

1223
private static final int CURL_HASH_LENGTH = 243;
1324
private static final int CURL_STATE_LENGTH = CURL_HASH_LENGTH * 3;
1425

15-
private static final int RUNNING = 0;
16-
private static final int CANCELLED = 1;
17-
private static final int COMPLETED = 2;
18-
19-
private volatile int state;
26+
private static final long HIGH_BITS = 0b11111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111L;
27+
private static final long LOW_BITS = 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000L;
2028

21-
public synchronized void cancel() {
29+
private volatile State state;
30+
private final Object syncObj = new Object();
2231

23-
state = CANCELLED;
24-
25-
notifyAll();
32+
public void cancel() {
33+
synchronized (syncObj) {
34+
state = CANCELLED;
35+
syncObj.notifyAll();
36+
}
2637
}
2738

28-
public synchronized boolean search(final int[] transactionTrits, final int minWeightMagnitude, int numberOfThreads) {
39+
public synchronized boolean search(final int[] transactionTrits, final int minWeightMagnitude,
40+
int numberOfThreads) {
2941

3042
if (transactionTrits.length != TRANSACTION_LENGTH) {
31-
32-
throw new RuntimeException("Invalid transaction trits length: " + transactionTrits.length);
43+
throw new RuntimeException(
44+
"Invalid transaction trits length: " + transactionTrits.length);
3345
}
3446
if (minWeightMagnitude < 0 || minWeightMagnitude > CURL_HASH_LENGTH) {
35-
3647
throw new RuntimeException("Invalid min weight magnitude: " + minWeightMagnitude);
3748
}
3849

39-
state = RUNNING;
50+
synchronized (syncObj) {
51+
state = RUNNING;
52+
}
4053

4154
final long[] midCurlStateLow = new long[CURL_STATE_LENGTH], midCurlStateHigh = new long[CURL_STATE_LENGTH];
4255

4356
{
4457
for (int i = CURL_HASH_LENGTH; i < CURL_STATE_LENGTH; i++) {
45-
46-
midCurlStateLow[i] = 0b1111111111111111111111111111111111111111111111111111111111111111L;
47-
midCurlStateHigh[i] = 0b1111111111111111111111111111111111111111111111111111111111111111L;
58+
midCurlStateLow[i] = HIGH_BITS;
59+
midCurlStateHigh[i] = HIGH_BITS;
4860
}
4961

5062
int offset = 0;
@@ -54,25 +66,22 @@ public synchronized boolean search(final int[] transactionTrits, final int minWe
5466
for (int j = 0; j < CURL_HASH_LENGTH; j++) {
5567

5668
switch (transactionTrits[offset++]) {
57-
5869
case 0: {
70+
midCurlStateLow[j] = HIGH_BITS;
71+
midCurlStateHigh[j] = HIGH_BITS;
5972

60-
midCurlStateLow[j] = 0b1111111111111111111111111111111111111111111111111111111111111111L;
61-
midCurlStateHigh[j] = 0b1111111111111111111111111111111111111111111111111111111111111111L;
62-
63-
} break;
73+
}
74+
break;
6475

6576
case 1: {
66-
67-
midCurlStateLow[j] = 0b0000000000000000000000000000000000000000000000000000000000000000L;
68-
midCurlStateHigh[j] = 0b1111111111111111111111111111111111111111111111111111111111111111L;
69-
70-
} break;
77+
midCurlStateLow[j] = LOW_BITS;
78+
midCurlStateHigh[j] = HIGH_BITS;
79+
}
80+
break;
7181

7282
default: {
73-
74-
midCurlStateLow[j] = 0b1111111111111111111111111111111111111111111111111111111111111111L;
75-
midCurlStateHigh[j] = 0b0000000000000000000000000000000000000000000000000000000000000000L;
83+
midCurlStateLow[j] = HIGH_BITS;
84+
midCurlStateHigh[j] = LOW_BITS;
7685
}
7786
}
7887
}
@@ -89,16 +98,14 @@ public synchronized boolean search(final int[] transactionTrits, final int minWe
8998
midCurlStateLow[i] = 0b1111111111111111111111111111111111111111111111111111111111111111L;
9099
midCurlStateHigh[i] = 0b1111111111111111111111111111111111111111111111111111111111111111L;
91100

92-
}
93-
break;
101+
} break;
94102

95103
case 1: {
96104

97105
midCurlStateLow[i] = 0b0000000000000000000000000000000000000000000000000000000000000000L;
98106
midCurlStateHigh[i] = 0b1111111111111111111111111111111111111111111111111111111111111111L;
99107

100-
}
101-
break;
108+
} break;
102109

103110
default: {
104111

@@ -116,100 +123,117 @@ public synchronized boolean search(final int[] transactionTrits, final int minWe
116123
midCurlStateHigh[162 + 2] = 0b1111111111000000000111111111111111111000000000111111111111111111L;
117124
midCurlStateLow[162 + 3] = 0b1111111111000000000000000000000000000111111111111111111111111111L;
118125
midCurlStateHigh[162 + 3] = 0b0000000000111111111111111111111111111111111111111111111111111111L;
126+
119127
}
120128

121129
if (numberOfThreads <= 0) {
122-
123-
numberOfThreads = Runtime.getRuntime().availableProcessors() - 1;
124-
if (numberOfThreads < 1) {
125-
126-
numberOfThreads = 1;
127-
}
130+
numberOfThreads = Math.max(Runtime.getRuntime().availableProcessors() - 1, 1);
128131
}
129132

133+
Thread[] workers = new Thread[numberOfThreads];
134+
130135
while (numberOfThreads-- > 0) {
131136

132137
final int threadIndex = numberOfThreads;
133-
(new Thread(new Runnable() { public void run() {
138+
Thread worker = (new Thread() { public void run() {
134139

135140
final long[] midCurlStateCopyLow = new long[CURL_STATE_LENGTH], midCurlStateCopyHigh = new long[CURL_STATE_LENGTH];
136141
System.arraycopy(midCurlStateLow, 0, midCurlStateCopyLow, 0, CURL_STATE_LENGTH);
137142
System.arraycopy(midCurlStateHigh, 0, midCurlStateCopyHigh, 0, CURL_STATE_LENGTH);
138143
for (int i = threadIndex; i-- > 0; ) {
144+
increment(midCurlStateCopyLow, midCurlStateCopyHigh, 162 + CURL_HASH_LENGTH / 9,
145+
162 + (CURL_HASH_LENGTH / 9) * 2);
139146

140-
increment(midCurlStateCopyLow, midCurlStateCopyHigh, 162 + CURL_HASH_LENGTH / 9, 162 + (CURL_HASH_LENGTH / 9) * 2);
141147
}
142148

143149
final long[] curlStateLow = new long[CURL_STATE_LENGTH], curlStateHigh = new long[CURL_STATE_LENGTH];
144150
final long[] curlScratchpadLow = new long[CURL_STATE_LENGTH], curlScratchpadHigh = new long[CURL_STATE_LENGTH];
151+
long mask, outMask = 1;
145152
while (state == RUNNING) {
146153

147-
increment(midCurlStateCopyLow, midCurlStateCopyHigh, 162 + CURL_HASH_LENGTH / 9, 162 + (CURL_HASH_LENGTH / 9) * 2);
154+
increment(midCurlStateCopyLow, midCurlStateCopyHigh, 162 + (CURL_HASH_LENGTH / 9) * 2,
155+
CURL_HASH_LENGTH);
156+
148157
System.arraycopy(midCurlStateCopyLow, 0, curlStateLow, 0, CURL_STATE_LENGTH);
149158
System.arraycopy(midCurlStateCopyHigh, 0, curlStateHigh, 0, CURL_STATE_LENGTH);
150159
transform(curlStateLow, curlStateHigh, curlScratchpadLow, curlScratchpadHigh);
151160

152-
NEXT_BIT_INDEX:
153-
for (int bitIndex = 64; bitIndex-- > 0; ) {
154-
155-
for (int i = minWeightMagnitude; i-- > 0; ) {
156-
157-
if ((((int)(curlStateLow[CURL_HASH_LENGTH - 1 - i] >> bitIndex)) & 1) != (((int)(curlStateHigh[CURL_HASH_LENGTH - 1 - i] >> bitIndex)) & 1)) {
158-
159-
continue NEXT_BIT_INDEX;
160-
}
161+
mask = HIGH_BITS;
162+
for (int i = minWeightMagnitude; i-- > 0; ) {
163+
mask &= ~(curlStateLow[CURL_HASH_LENGTH - 1 - i] ^ curlStateHigh[
164+
CURL_HASH_LENGTH - 1 - i]);
165+
if (mask == 0) {
166+
break;
161167
}
168+
}
169+
if (mask == 0) {
170+
continue;
171+
}
162172

163-
synchronized (PearlDiver.this) {
164-
165-
if (state == RUNNING) {
166-
167-
state = COMPLETED;
168-
169-
for (int i = 0; i < CURL_HASH_LENGTH; i++) {
170-
171-
transactionTrits[TRANSACTION_LENGTH - CURL_HASH_LENGTH + i] = ((((int) (midCurlStateCopyLow[i] >> bitIndex)) & 1) == 0) ? 1 : (((((int) (midCurlStateCopyHigh[i] >> bitIndex)) & 1) == 0) ? -1 : 0);
172-
}
173-
174-
PearlDiver.this.notifyAll();
173+
synchronized (syncObj) {
174+
if (state == RUNNING) {
175+
state = COMPLETED;
176+
while ((outMask & mask) == 0) {
177+
outMask <<= 1;
175178
}
179+
for (int i = 0; i < CURL_HASH_LENGTH; i++) {
180+
transactionTrits[TRANSACTION_LENGTH - CURL_HASH_LENGTH + i] =
181+
(midCurlStateCopyLow[i] & outMask) == 0 ? 1
182+
: (midCurlStateCopyHigh[i] & outMask) == 0 ? -1 : 0;
183+
}
184+
syncObj.notifyAll();
176185
}
177-
178-
break;
179186
}
187+
break;
180188
}
181-
182-
}})).start();
189+
}
190+
});
191+
workers[threadIndex] = worker;
192+
worker.start();
183193
}
184194

185195
try {
186-
187-
while (state == RUNNING) {
188-
189-
wait();
196+
synchronized (syncObj) {
197+
if (state == RUNNING) {
198+
syncObj.wait();
199+
}
190200
}
191-
192201
} catch (final InterruptedException e) {
202+
synchronized (syncObj) {
203+
state = CANCELLED;
204+
}
205+
}
193206

194-
state = CANCELLED;
207+
for (Thread worker : workers) {
208+
try {
209+
worker.join();
210+
} catch (final InterruptedException e) {
211+
synchronized (syncObj) {
212+
state = CANCELLED;
213+
}
214+
}
195215
}
196216

197217
return state == COMPLETED;
198218
}
199219

200-
private static void transform(final long[] curlStateLow, final long[] curlStateHigh, final long[] curlScratchpadLow, final long[] curlScratchpadHigh) {
220+
private static void transform(final long[] curlStateLow, final long[] curlStateHigh,
221+
final long[] curlScratchpadLow, final long[] curlScratchpadHigh) {
201222

202223
int curlScratchpadIndex = 0;
203-
for (int round = 81; round-- > 0; ) {
204-
224+
for (int round = 0; round < NUMBER_OF_ROUNDSP81; round++) {
205225
System.arraycopy(curlStateLow, 0, curlScratchpadLow, 0, CURL_STATE_LENGTH);
206226
System.arraycopy(curlStateHigh, 0, curlScratchpadHigh, 0, CURL_STATE_LENGTH);
207227

208228
for (int curlStateIndex = 0; curlStateIndex < CURL_STATE_LENGTH; curlStateIndex++) {
209-
210229
final long alpha = curlScratchpadLow[curlScratchpadIndex];
211230
final long beta = curlScratchpadHigh[curlScratchpadIndex];
212-
final long gamma = curlScratchpadHigh[curlScratchpadIndex += (curlScratchpadIndex < 365 ? 364 : -365)];
231+
if (curlScratchpadIndex < 365) {
232+
curlScratchpadIndex += 364;
233+
} else {
234+
curlScratchpadIndex += -365;
235+
}
236+
final long gamma = curlScratchpadHigh[curlScratchpadIndex];
213237
final long delta = (alpha | (~gamma)) & (curlScratchpadLow[curlScratchpadIndex] ^ beta);
214238

215239
curlStateLow[curlStateIndex] = ~delta;
@@ -218,26 +242,19 @@ private static void transform(final long[] curlStateLow, final long[] curlStateH
218242
}
219243
}
220244

221-
private static void increment(final long[] midCurlStateCopyLow, final long[] midCurlStateCopyHigh, final int fromIndex, final int toIndex) {
245+
private static void increment(final long[] midCurlStateCopyLow,
246+
final long[] midCurlStateCopyHigh, final int fromIndex, final int toIndex) {
222247

223248
for (int i = fromIndex; i < toIndex; i++) {
224-
225-
if (midCurlStateCopyLow[i] == 0b0000000000000000000000000000000000000000000000000000000000000000L) {
226-
227-
midCurlStateCopyLow[i] = 0b1111111111111111111111111111111111111111111111111111111111111111L;
228-
midCurlStateCopyHigh[i] = 0b0000000000000000000000000000000000000000000000000000000000000000L;
229-
249+
if (midCurlStateCopyLow[i] == LOW_BITS) {
250+
midCurlStateCopyLow[i] = HIGH_BITS;
251+
midCurlStateCopyHigh[i] = LOW_BITS;
230252
} else {
231-
232-
if (midCurlStateCopyHigh[i] == 0b0000000000000000000000000000000000000000000000000000000000000000L) {
233-
234-
midCurlStateCopyHigh[i] = 0b1111111111111111111111111111111111111111111111111111111111111111L;
235-
253+
if (midCurlStateCopyHigh[i] == LOW_BITS) {
254+
midCurlStateCopyHigh[i] = HIGH_BITS;
236255
} else {
237-
238-
midCurlStateCopyLow[i] = 0b0000000000000000000000000000000000000000000000000000000000000000L;
256+
midCurlStateCopyLow[i] = LOW_BITS;
239257
}
240-
241258
break;
242259
}
243260
}

0 commit comments

Comments
 (0)