1
+ package cfb .pearldiver ;
2
+
3
+ /**
4
+ * (c) 2016 Come-from-Beyond.
5
+ *
6
+ * See <https://github.com/iotaledger/PearlDiver>.
7
+ */
8
+ public class PearlDiver {
9
+
10
+ public static final int TRANSACTION_LENGTH = 8019 ;
11
+
12
+ private static final int CURL_HASH_LENGTH = 243 ;
13
+ private static final int CURL_STATE_LENGTH = CURL_HASH_LENGTH * 3 ;
14
+
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 ;
20
+
21
+ public synchronized void cancel () {
22
+
23
+ state = CANCELLED ;
24
+
25
+ notifyAll ();
26
+ }
27
+
28
+ public synchronized boolean search (final int [] transactionTrits , final int minWeightMagnitude , int numberOfThreads ) {
29
+
30
+ if (transactionTrits .length != TRANSACTION_LENGTH ) {
31
+
32
+ throw new RuntimeException ("Invalid transaction trits length: " + transactionTrits .length );
33
+ }
34
+ if (minWeightMagnitude < 0 || minWeightMagnitude > CURL_HASH_LENGTH ) {
35
+
36
+ throw new RuntimeException ("Invalid min weight magnitude: " + minWeightMagnitude );
37
+ }
38
+
39
+ state = RUNNING ;
40
+
41
+ final long [] midCurlStateLow = new long [CURL_STATE_LENGTH ], midCurlStateHigh = new long [CURL_STATE_LENGTH ];
42
+
43
+ {
44
+ for (int i = CURL_HASH_LENGTH ; i < CURL_STATE_LENGTH ; i ++) {
45
+
46
+ midCurlStateLow [i ] = 0b1111111111111111111111111111111111111111111111111111111111111111L;
47
+ midCurlStateHigh [i ] = 0b1111111111111111111111111111111111111111111111111111111111111111L;
48
+ }
49
+
50
+ int offset = 0 ;
51
+ final long [] curlScratchpadLow = new long [CURL_STATE_LENGTH ], curlScratchpadHigh = new long [CURL_STATE_LENGTH ];
52
+ for (int i = (TRANSACTION_LENGTH - CURL_HASH_LENGTH ) / CURL_HASH_LENGTH ; i -- > 0 ; ) {
53
+
54
+ for (int j = 0 ; j < CURL_HASH_LENGTH ; j ++) {
55
+
56
+ switch (transactionTrits [offset ++]) {
57
+
58
+ case 0 : {
59
+
60
+ midCurlStateLow [j ] = 0b1111111111111111111111111111111111111111111111111111111111111111L;
61
+ midCurlStateHigh [j ] = 0b1111111111111111111111111111111111111111111111111111111111111111L;
62
+
63
+ } break ;
64
+
65
+ case 1 : {
66
+
67
+ midCurlStateLow [j ] = 0b0000000000000000000000000000000000000000000000000000000000000000L;
68
+ midCurlStateHigh [j ] = 0b1111111111111111111111111111111111111111111111111111111111111111L;
69
+
70
+ } break ;
71
+
72
+ default : {
73
+
74
+ midCurlStateLow [j ] = 0b1111111111111111111111111111111111111111111111111111111111111111L;
75
+ midCurlStateHigh [j ] = 0b0000000000000000000000000000000000000000000000000000000000000000L;
76
+ }
77
+ }
78
+ }
79
+
80
+ transform (midCurlStateLow , midCurlStateHigh , curlScratchpadLow , curlScratchpadHigh );
81
+ }
82
+
83
+ midCurlStateLow [0 ] = 0b1101101101101101101101101101101101101101101101101101101101101101L;
84
+ midCurlStateHigh [0 ] = 0b1011011011011011011011011011011011011011011011011011011011011011L;
85
+ midCurlStateLow [1 ] = 0b1111000111111000111111000111111000111111000111111000111111000111L;
86
+ midCurlStateHigh [1 ] = 0b1000111111000111111000111111000111111000111111000111111000111111L;
87
+ midCurlStateLow [2 ] = 0b0111111111111111111000000000111111111111111111000000000111111111L;
88
+ midCurlStateHigh [2 ] = 0b1111111111000000000111111111111111111000000000111111111111111111L;
89
+ midCurlStateLow [3 ] = 0b1111111111000000000000000000000000000111111111111111111111111111L;
90
+ midCurlStateHigh [3 ] = 0b0000000000111111111111111111111111111111111111111111111111111111L;
91
+ }
92
+
93
+ if (numberOfThreads <= 0 ) {
94
+
95
+ numberOfThreads = Runtime .getRuntime ().availableProcessors () - 1 ;
96
+ if (numberOfThreads < 1 ) {
97
+
98
+ numberOfThreads = 1 ;
99
+ }
100
+ }
101
+
102
+ while (numberOfThreads -- > 0 ) {
103
+
104
+ final int threadIndex = numberOfThreads ;
105
+ (new Thread (new Runnable () { public void run () {
106
+
107
+ final long [] midCurlStateCopyLow = new long [CURL_STATE_LENGTH ], midCurlStateCopyHigh = new long [CURL_STATE_LENGTH ];
108
+ System .arraycopy (midCurlStateLow , 0 , midCurlStateCopyLow , 0 , CURL_STATE_LENGTH );
109
+ System .arraycopy (midCurlStateHigh , 0 , midCurlStateCopyHigh , 0 , CURL_STATE_LENGTH );
110
+ for (int i = threadIndex ; i -- > 0 ; ) {
111
+
112
+ increment (midCurlStateCopyLow , midCurlStateCopyHigh , CURL_HASH_LENGTH / 3 , (CURL_HASH_LENGTH / 3 ) * 2 );
113
+ }
114
+
115
+ final long [] curlStateLow = new long [CURL_STATE_LENGTH ], curlStateHigh = new long [CURL_STATE_LENGTH ];
116
+ final long [] curlScratchpadLow = new long [CURL_STATE_LENGTH ], curlScratchpadHigh = new long [CURL_STATE_LENGTH ];
117
+ while (state == RUNNING ) {
118
+
119
+ increment (midCurlStateCopyLow , midCurlStateCopyHigh , (CURL_HASH_LENGTH / 3 ) * 2 , CURL_HASH_LENGTH );
120
+ System .arraycopy (midCurlStateCopyLow , 0 , curlStateLow , 0 , CURL_STATE_LENGTH );
121
+ System .arraycopy (midCurlStateCopyHigh , 0 , curlStateHigh , 0 , CURL_STATE_LENGTH );
122
+ transform (curlStateLow , curlStateHigh , curlScratchpadLow , curlScratchpadHigh );
123
+
124
+ NEXT_BIT_INDEX :
125
+ for (int bitIndex = 64 ; bitIndex -- > 0 ; ) {
126
+
127
+ for (int i = minWeightMagnitude ; i -- > 0 ; ) {
128
+
129
+ if ((((int )(curlStateLow [CURL_HASH_LENGTH - 1 - i ] >> bitIndex )) & 1 ) != (((int )(curlStateHigh [CURL_HASH_LENGTH - 1 - i ] >> bitIndex )) & 1 )) {
130
+
131
+ continue NEXT_BIT_INDEX ;
132
+ }
133
+ }
134
+
135
+ synchronized (PearlDiver .this ) {
136
+
137
+ if (state == RUNNING ) {
138
+
139
+ state = COMPLETED ;
140
+
141
+ for (int i = 0 ; i < CURL_HASH_LENGTH ; i ++) {
142
+
143
+ transactionTrits [TRANSACTION_LENGTH - CURL_HASH_LENGTH + i ] = ((((int ) (midCurlStateCopyLow [i ] >> bitIndex )) & 1 ) == 0 ) ? 1 : (((((int ) (midCurlStateCopyHigh [i ] >> bitIndex )) & 1 ) == 0 ) ? -1 : 0 );
144
+ }
145
+
146
+ PearlDiver .this .notifyAll ();
147
+ }
148
+ }
149
+
150
+ break ;
151
+ }
152
+ }
153
+
154
+ }})).start ();
155
+ }
156
+
157
+ try {
158
+
159
+ while (state == RUNNING ) {
160
+
161
+ wait ();
162
+ }
163
+
164
+ } catch (final InterruptedException e ) {
165
+
166
+ state = CANCELLED ;
167
+ }
168
+
169
+ return state == COMPLETED ;
170
+ }
171
+
172
+ private static void transform (final long [] curlStateLow , final long [] curlStateHigh , final long [] curlScratchpadLow , final long [] curlScratchpadHigh ) {
173
+
174
+ int curlScratchpadIndex = 0 ;
175
+ for (int round = 27 ; round -- > 0 ; ) {
176
+
177
+ System .arraycopy (curlStateLow , 0 , curlScratchpadLow , 0 , CURL_STATE_LENGTH );
178
+ System .arraycopy (curlStateHigh , 0 , curlScratchpadHigh , 0 , CURL_STATE_LENGTH );
179
+
180
+ for (int curlStateIndex = 0 ; curlStateIndex < CURL_STATE_LENGTH ; curlStateIndex ++) {
181
+
182
+ final long alpha = curlScratchpadLow [curlScratchpadIndex ];
183
+ final long beta = curlScratchpadHigh [curlScratchpadIndex ];
184
+ final long gamma = curlScratchpadHigh [curlScratchpadIndex += (curlScratchpadIndex < 365 ? 364 : -365 )];
185
+ final long delta = (alpha | (~gamma )) & (curlScratchpadLow [curlScratchpadIndex ] ^ beta );
186
+
187
+ curlStateLow [curlStateIndex ] = ~delta ;
188
+ curlStateHigh [curlStateIndex ] = (alpha ^ gamma ) | delta ;
189
+ }
190
+ }
191
+ }
192
+
193
+ private static void increment (final long [] midCurlStateCopyLow , final long [] midCurlStateCopyHigh , final int fromIndex , final int toIndex ) {
194
+
195
+ for (int i = fromIndex ; i < toIndex ; i ++) {
196
+
197
+ if (midCurlStateCopyLow [i ] == 0b0000000000000000000000000000000000000000000000000000000000000000L) {
198
+
199
+ midCurlStateCopyLow [i ] = 0b1111111111111111111111111111111111111111111111111111111111111111L;
200
+ midCurlStateCopyHigh [i ] = 0b0000000000000000000000000000000000000000000000000000000000000000L;
201
+
202
+ } else {
203
+
204
+ if (midCurlStateCopyHigh [i ] == 0b0000000000000000000000000000000000000000000000000000000000000000L) {
205
+
206
+ midCurlStateCopyHigh [i ] = 0b1111111111111111111111111111111111111111111111111111111111111111L;
207
+
208
+ } else {
209
+
210
+ midCurlStateCopyLow [i ] = 0b0000000000000000000000000000000000000000000000000000000000000000L;
211
+ }
212
+
213
+ break ;
214
+ }
215
+ }
216
+ }
217
+ }
0 commit comments