diff --git a/examples/example_22.conf b/examples/example_22.conf
new file mode 100644
index 0000000..fb09d31
--- /dev/null
+++ b/examples/example_22.conf
@@ -0,0 +1,13 @@
+PERMUTATION_CHECK
+bc1q9fdjavqhzdttar9kjchpw3rerkzfs3zvgrwg9e
+9
+lady
+oblige
+cable
+hidden
+surface
+marriage
+grit
+priority
+forget
+m/84'/0'/0'/0/0
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index ead4a63..d3e32eb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
com.pawelgorny
lostword
- 0.13.3
+ 0.14.0
jar
@@ -23,17 +23,17 @@
com.google.guava
guava
- 30.0-jre
+ 31.0.1-jre
org.slf4j
slf4j-log4j12
- 1.7.26
+ 1.7.32
com.google.code.gson
gson
- 2.8.6
+ 2.8.8
@@ -50,21 +50,21 @@
org.apache.maven.plugins
maven-jar-plugin
- 2.3.2
-
- lostWord
-
+ 3.2.0
org.apache.maven.plugins
maven-compiler-plugin
+ 3.8.1
1.8
1.8
+ org.apache.maven.plugins
maven-assembly-plugin
+ 3.3.0
@@ -74,7 +74,6 @@
jar-with-dependencies
- lostWord
diff --git a/src/main/java/com/pawelgorny/lostword/WorkerPermutationCheck.java b/src/main/java/com/pawelgorny/lostword/WorkerPermutationCheck.java
index 42415e3..df6e4dd 100644
--- a/src/main/java/com/pawelgorny/lostword/WorkerPermutationCheck.java
+++ b/src/main/java/com/pawelgorny/lostword/WorkerPermutationCheck.java
@@ -2,11 +2,16 @@
import org.bitcoinj.core.Utils;
import org.bitcoinj.crypto.MnemonicException;
+import org.bouncycastle.crypto.macs.HMac;
import java.security.MessageDigest;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
public class WorkerPermutationCheck extends Worker{
@@ -28,15 +33,67 @@ public void run() throws InterruptedException, MnemonicException {
String[] words = new String[0];
words = configuration.getWORDS().toArray(words);
start = System.currentTimeMillis();
- printAllRecursive(configuration.getSIZE(), words);
+ THREADS = Math.min(THREADS, configuration.getSIZE());
+ List> workPerThread = new ArrayList<>(THREADS);
+ int tIx=0;
+ for(String w:words){
+ if (workPerThread.size()==tIx){
+ workPerThread.add(new ArrayList<>(1));
+ }
+ workPerThread.get(tIx).add(w);
+ tIx=(++tIx%THREADS);
+ }
+ final List SHA_256_DIGESTS= new ArrayList<>(THREADS);
+ final List SHA_512_DIGESTS= new ArrayList<>(THREADS);
+
+ final CountDownLatch latch = new CountDownLatch(THREADS);
+ final ExecutorService executorService = Executors.newFixedThreadPool(THREADS);
+
+ for(tIx=0; tIx WORDS_TO_WORK = workPerThread.get(tIx);
+ executorService.submit(() -> {
+ final HMac LOCAL_SHA_512_DIGEST = SHA_512_DIGESTS.get(T_NUMBER);
+ final MessageDigest LOCAL_SHA_256_DIGEST = SHA_256_DIGESTS.get(T_NUMBER);
+ if (REPORTER) {
+ start = System.currentTimeMillis();
+ }
+ for (String PREFIX : WORDS_TO_WORK) {
+ if (RESULT != null) {
+ break;
+ }
+ List seedToProcess = new ArrayList<>(configuration.getWORDS());
+ for (int i = 0; i < configuration.getSIZE(); i++) {
+ if (seedToProcess.get(i).equals(PREFIX)) {
+ seedToProcess.remove(i);
+ break;
+ }
+ }
+ String[] target = new String[configuration.getSIZE()];
+ String[] toProcess = new String[configuration.getSIZE() - 1];
+ toProcess = seedToProcess.toArray(toProcess);
+ target[0] = PREFIX;
+ checkAllRecursive(configuration.getSIZE() - 1, toProcess, target, LOCAL_SHA_512_DIGEST, LOCAL_SHA_256_DIGEST, REPORTER);
+ }
+ latch.countDown();
+ });
+ }
+ latch.await();
+ executorService.shutdown();
}
- private boolean printAllRecursive(int n, String[] elements) {
+ private boolean checkAllRecursive(int n, String[] elements, final String[] target, HMac LOCAL_SHA_512_DIGEST, MessageDigest LOCAL_SHA_256_DIGEST, Boolean REPORTER) {
if(n == 1) {
- return checkElements(elements);
+ return checkElements(target, elements, LOCAL_SHA_512_DIGEST, LOCAL_SHA_256_DIGEST, REPORTER);
} else {
for(int i = 0; i < n-1; i++) {
- if (printAllRecursive(n - 1, elements)){
+ if (checkAllRecursive(n - 1, elements, target, LOCAL_SHA_512_DIGEST, LOCAL_SHA_256_DIGEST, REPORTER)){
return true;
}
if(n % 2 == 0) {
@@ -45,24 +102,25 @@ private boolean printAllRecursive(int n, String[] elements) {
swap(elements, 0, n - 1);
}
}
- if (printAllRecursive(n - 1, elements)){
+ if (checkAllRecursive(n - 1, elements, target, LOCAL_SHA_512_DIGEST, LOCAL_SHA_256_DIGEST, REPORTER)){
return true;
}
}
return RESULT!=null;
}
- private boolean checkElements(String[] input) {
- List mnemonic = Arrays.asList(input);
+ private boolean checkElements(String[] target, String[] input, HMac LOCAL_SHA_512_DIGEST, MessageDigest LOCAL_SHA_256_DIGEST, Boolean REPORTER) {
+ System.arraycopy(input,0, target, 1, input.length);
+ List mnemonic = Arrays.asList(target);
try {
- boolean result = check(mnemonic, null, SHA_256_DIGEST);
+ boolean result = check(mnemonic, LOCAL_SHA_512_DIGEST, LOCAL_SHA_256_DIGEST);
if (result){
RESULT = new Result(mnemonic);
}
}catch (MnemonicException e){
System.out.println(e.getLocalizedMessage());
}
- if (System.currentTimeMillis()-start > STATUS_PERIOD){
+ if (REPORTER && (System.currentTimeMillis()-start > STATUS_PERIOD)){
System.out.println(SDTF.format(new Date())+ " Alive!");
start = System.currentTimeMillis();
}