diff --git a/src/BitcoinLotto.java b/src/BitcoinLotto.java
index 12c85b8..67f0f47 100644
--- a/src/BitcoinLotto.java
+++ b/src/BitcoinLotto.java
@@ -1,309 +1,206 @@
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Timer;
-import java.util.prefs.Preferences;
-
-import org.bitcoinj.core.Address;
-import org.bitcoinj.params.MainNetParams;
-
-public class BitcoinLotto {
-
- public static void main(String[] args) {
- BitcoinLotto thisLotto = new BitcoinLotto();
- thisLotto.startGui();
- }
-
- private Status lottoStatus = Status.MAIN_MENU;
- private Boolean isInitialized = false;
- private Address[] addressArray;
- private SearchThread[] threadArray;
- private Timer guiTimer;
-
- private GuiUpdateTimer guiUpdateTimer;
-
- private PrimaryWindow primaryWindow;
- private long totalCheckCount = 0;
- private long startTime = 0;
- private int threadCount = 1;
-
- private int activeThreadCount = 0; // threads loaded and running
- private long pausedTimeTotal = 0;
-
- private long pauseStartTime = 0;
- private String prefsNode = "com/github/traxm/BitcoinLotto";
- private String prefsFileString = "filePath";
-
- private String prefsThreadString = "threadCount";
-
- public Address[] getAddressArray() {
- return addressArray;
- }
-
- public void initializeLookupAddresses(File thisFile) {
- /*
- * Read the address file and populate an array with the data
- */
-
- String[] addressStringArray;
- Address thisAddress = null;
- ArrayList
addressList = null;
-
- addressStringArray = readLines(thisFile);
- addressList = new ArrayList();
-
- for (int i = 0; i < addressStringArray.length; i++) {
- try {
- thisAddress = Address.fromString(MainNetParams.get(), addressStringArray[i]);
- } catch (org.bitcoinj.core.AddressFormatException ex) {
- primaryWindow.showFileErrorMessage();
- return;
- }
- addressList.add(thisAddress);
- }
-
- addressArray = new Address[addressList.size()];
- addressArray = addressList.toArray(addressArray);
-
- // Check to see if any addresses entries were read
- if (addressArray == null || addressArray.length <= 0)
- return;
-
- // Update the UI with the number of addresses loaded
- primaryWindow.setTotalAddressLabel(addressArray.length);
-
- // Allow the user to start the lotto
- primaryWindow.enableStartButton();
-
- // Save the file path for future use
- saveFilePath(thisFile);
-
- // Write a small test file to confirm that any matched addresses can be saved
- writeStarterFile();
-
- isInitialized = true;
- }
-
- private Boolean isFileAvailable(String filePath) {
- // Checks to see if a last address file is available to load
-
- if (filePath == null)
- return false;
-
- File tempFile = new File(filePath);
- return tempFile.exists();
- }
-
- public Boolean isInitialized() {
- return isInitialized;
- }
-
- public void logAddressCheck() {
- // Track address checks
-
- totalCheckCount++;
- }
-
- public void notifySuccess(String matchAddress, String matchKey) {
- primaryWindow.setSuccessLabel(true, matchAddress, matchKey);
- }
-
- public void pauseAllThreads() {
- /*
- * End each thread based on user input
- */
-
- lottoStatus = Status.PAUSED;
-
- for (int i = 0; i < this.threadArray.length; i++)
- this.threadArray[i].stopThread();
-
- pauseStartTime = System.nanoTime();
- activeThreadCount = 0;
- primaryWindow.setThreadsActiveLabel(activeThreadCount);
- }
-
- private String[] readLines(File thisFile) {
- /*
- * Read lines from a file
- */
-
- BufferedReader bufferedReader;
-
- FileInputStream thisStream;
- List lines = null;
- try {
- thisStream = new FileInputStream(thisFile);
- bufferedReader = new BufferedReader(new InputStreamReader(thisStream));
-
- lines = new ArrayList();
- String line = null;
-
- while ((line = bufferedReader.readLine()) != null) {
- lines.add(line);
- }
-
- bufferedReader.close();
- } catch (FileNotFoundException e) {
- primaryWindow.showFileErrorMessage();
- e.printStackTrace();
-
- } catch (IOException e) {
- primaryWindow.showFileErrorMessage();
- e.printStackTrace();
- }
-
- return lines.toArray(new String[lines.size()]);
- }
-
- public void resumeAllThreads() {
- /*
- * Create and start new threads based on user input
- */
-
- lottoStatus = Status.RUNNING;
-
- this.startThreads(threadCount);
-
- // Update the paused time
- this.pausedTimeTotal += (System.nanoTime() - this.pauseStartTime);
- }
-
- private void saveFilePath(File thisFile) {
- // Saves the file path for future use
- String filePathString = thisFile.getAbsolutePath();
-
- Preferences prefs = Preferences.userRoot().node(prefsNode);
- prefs.put(prefsFileString, filePathString);
- }
-
- private void saveThreadCount(int threadCount) {
- // Saves the file path for future use
- Preferences prefs = Preferences.userRoot().node(prefsNode);
- prefs.putInt(prefsThreadString, threadCount);
- }
-
- private void startGui() {
- /*
- * Create a frame and populate with components
- */
- primaryWindow = new PrimaryWindow(this);
-
- // Check to see if an existing address file is available
- Preferences prefs = Preferences.userRoot().node(prefsNode);
- // Does the preference entry exist
- // Is the file available
- if (isFileAvailable(prefs.get(prefsFileString, null))) {
- // Load the existing file
- System.out.println(isFileAvailable(prefs.get(prefsFileString, null)));
- primaryWindow.setAddressFile(new File(prefs.get(prefsFileString, null)));
-
- // Set the thread count
- primaryWindow.setThreadCount(prefs.getInt(this.prefsThreadString, 4));
- }
-
- primaryWindow.setWindowEnabled(true);
-
- }
-
- public void startLotto(int threadCount) throws URISyntaxException {
- /*
- * Start the lottery process
- */
-
- // Swap the active panel (0 is the main menu and 1 is the working panel)
- primaryWindow.setPanel(1);
-
- // Create the worker threads
- startThreads(threadCount);
-
- // Set a timer to update UI components
- guiTimer = new Timer();
- guiUpdateTimer = new GuiUpdateTimer(this);
- guiTimer.schedule(guiUpdateTimer, 0, 20);
-
- // Start tracking time
- startTime = System.nanoTime();
-
- // Save thread count for future use
- this.saveThreadCount(threadCount);
-
- }
-
- private void startThreads(int thisCount) {
- /*
- * Create and start worker threads
- */
-
- // Thread count is pulled from user input
- threadCount = thisCount;
-
- // Create the thread array
- threadArray = new SearchThread[threadCount];
-
- // Create specified threads
- for (int i = 0; i < threadCount; i++) {
- SearchThread thisThread = new SearchThread(); // Create a Search Thread instance
- threadArray[i] = thisThread; // Add the instance to the thread array
- thisThread.initialize(this, (i + 1) * 1000); // Initialize the thread and pass startup delay/sleep duration
- }
-
- // Start each of the threads
- for (int i = 0; i < threadCount; i++) {
- threadArray[i].start();
- }
-
- // Update the lotto status
- lottoStatus = Status.RUNNING;
- }
-
- public void updateGuiElements() {
- // Update all gui values
-
- if (lottoStatus == Status.PAUSED)
- return;
-
- this.primaryWindow.setScanAttemptsLabel(totalCheckCount);
-
- long duration = System.nanoTime() - startTime - this.pausedTimeTotal;
- this.primaryWindow.setTimeLabel(duration / 1000000, totalCheckCount);
- }
-
- public void updateThreadCount() {
- // Called by threads at start - active threads communicated via UI
-
- if (activeThreadCount > threadCount)
- return;
-
- activeThreadCount++;
- primaryWindow.setThreadsActiveLabel(activeThreadCount);
- }
-
- private void writeStarterFile() {
- // Writes a blank file to confirm write process functions as intended
- String thisString = "Ignore this file";
- FileWriter thisFile;
- try {
- thisFile = new FileWriter("testFilePleaseIgnore.txt");
- BufferedWriter writer = new BufferedWriter(thisFile);
- writer.write(thisString);
- writer.close();
- } catch (IOException e) {
- // Exit
- primaryWindow.showFileErrorMessage();
- }
- }
-
-}
-
-enum Status {
- MAIN_MENU, RUNNING, PAUSED;
-}
\ No newline at end of file
+import java.io.File;
+import java.net.URISyntaxException;
+import java.util.Timer;
+import java.util.prefs.Preferences;
+
+import org.bitcoinj.core.Address;
+import org.bitcoinj.script.Script.ScriptType;
+
+public class BitcoinLotto {
+
+ public static void main(String[] args) {
+ BitcoinLotto thisLotto = new BitcoinLotto();
+ thisLotto.startGui();
+ }
+
+ private Status lottoStatus = Status.MAIN_MENU;
+ private FileStatus fileStatus = FileStatus.FILE_NOT_LOADED;
+ private Boolean isInitialized = false;
+ private Address[][] p2pkh_address_array; // Array of address arrays
+ private int[][] indexArray; // Array of index values (to lookup address arrays based on prefix)
+ private SearchThread[] threadArray;
+ private Timer guiTimer;
+
+ private GuiUpdateTimer guiUpdateTimer;
+
+ private PrimaryWindow primaryWindow;
+ private long totalCheckCount = 0;
+ private long startTime = 0;
+ private int threadCount = 1;
+
+ private int activeThreadCount = 0; // threads loaded and running
+ private long pausedTimeTotal = 0;
+
+ private long pauseStartTime = 0;
+ public static String prefsNode = "com/github/traxm/BitcoinLotto";
+ public static String prefsFileString = "filePath";
+ public static String prefsThreadString = "threadCount";
+
+ public Address[][] getAddressArray() {
+
+ return this.p2pkh_address_array;
+
+ }
+
+ public int[][] getIndexArray() {
+ return this.indexArray;
+ }
+
+ public Boolean isInitialized() {
+ return isInitialized;
+ }
+
+ public void logAddressCheck() {
+ // Track address checks
+
+ totalCheckCount++;
+ }
+
+ public void notifySuccess(String matchAddress, String matchKey) {
+ primaryWindow.setSuccessLabel(true, matchAddress, matchKey);
+ }
+
+ public void pauseAllThreads() {
+ /*
+ * End each thread based on user input
+ */
+
+ lottoStatus = Status.PAUSED;
+
+ for (int i = 0; i < this.threadArray.length; i++)
+ this.threadArray[i].stopThread();
+
+ pauseStartTime = System.nanoTime();
+ activeThreadCount = 0;
+ primaryWindow.setThreadsActiveLabel(activeThreadCount);
+ }
+
+ public void resumeAllThreads() {
+ /*
+ * Create and start new threads based on user input
+ */
+
+ lottoStatus = Status.RUNNING;
+
+ this.startThreads(threadCount);
+
+ // Update the paused time
+ this.pausedTimeTotal += (System.nanoTime() - this.pauseStartTime);
+ }
+
+ private void saveThreadCount(int threadCount) {
+ // Saves the file path for future use
+ Preferences prefs = Preferences.userRoot().node(prefsNode);
+ prefs.putInt(prefsThreadString, threadCount);
+ }
+
+ private void startGui() {
+ /*
+ * Create a frame and populate with components
+ */
+ primaryWindow = new PrimaryWindow(this);
+
+ primaryWindow.setWindowEnabled(true);
+
+ // Check to see if an existing address file is available
+ Preferences prefs = Preferences.userRoot().node(prefsNode);
+ // Does the preference entry exist
+ // Is the file available
+ if (LoadAddresses.isFileAvailable(prefs.get(prefsFileString, null))) {
+ // Load the existing file
+ primaryWindow.setAddressFile(new File(prefs.get(prefsFileString, null)));
+
+ // Set the thread count
+ primaryWindow.setThreadCount(prefs.getInt(BitcoinLotto.prefsThreadString, 4));
+ }
+ }
+
+ public void startLotto(int threadCount) throws URISyntaxException {
+ /*
+ * Start the lottery process
+ */
+
+ // Swap the active panel (0 is the main menu and 1 is the working panel)
+ primaryWindow.setPanel(1);
+
+ // Create the worker threads
+ startThreads(threadCount);
+
+ // Set a timer to update UI components
+ guiTimer = new Timer();
+ guiUpdateTimer = new GuiUpdateTimer(this);
+ guiTimer.schedule(guiUpdateTimer, 0, 20);
+
+ // Start tracking time
+ startTime = System.nanoTime();
+
+ // Save thread count for future use
+ this.saveThreadCount(threadCount);
+
+ }
+
+ private void startThreads(int thisCount) {
+ /*
+ * Create and start worker threads
+ */
+
+ // Thread count is pulled from user input
+ threadCount = thisCount;
+
+ // Create the thread array
+ threadArray = new SearchThread[threadCount];
+
+ // Create specified threads
+ for (int i = 0; i < threadCount; i++) {
+ SearchThread thisThread = new SearchThread(this, ScriptType.P2SH, (i + 1) * 1000); // Create a Search Thread
+ // instance
+ threadArray[i] = thisThread; // Add the instance to the thread array
+ }
+
+ // Start each of the threads
+ for (int i = 0; i < threadCount; i++) {
+ threadArray[i].start();
+ }
+
+ // Update the lotto status
+ lottoStatus = Status.RUNNING;
+ }
+
+ public void updateGuiElements() {
+ // Update all gui values
+
+ if (lottoStatus == Status.PAUSED)
+ return;
+
+ this.primaryWindow.setScanAttemptsLabel(totalCheckCount);
+
+ long duration = System.nanoTime() - startTime - this.pausedTimeTotal;
+ this.primaryWindow.setTimeLabel(duration / 1000000, totalCheckCount);
+ }
+
+ public void updateThreadCount() {
+ // Called by threads at start - active threads communicated via UI
+
+ if (activeThreadCount > threadCount)
+ return;
+
+ activeThreadCount++;
+ primaryWindow.setThreadsActiveLabel(activeThreadCount);
+ }
+
+ public void setAddressArray(Address[][] thisAddressArray, int[][] thisIntArray) {
+ this.p2pkh_address_array = thisAddressArray;
+ this.indexArray = thisIntArray;
+
+ this.fileStatus = FileStatus.FILE_LOADED;
+ }
+
+}
+
+enum FileStatus {
+ FILE_LOADED, FILE_LOADING, FILE_NOT_LOADED;
+}
+
+enum Status {
+ MAIN_MENU, RUNNING, PAUSED;
+}
diff --git a/src/GuiUpdateTimer.java b/src/GuiUpdateTimer.java
index 279e760..8bcb83f 100644
--- a/src/GuiUpdateTimer.java
+++ b/src/GuiUpdateTimer.java
@@ -1,19 +1,19 @@
-import java.util.TimerTask;
-
-public class GuiUpdateTimer extends TimerTask {
-
- private BitcoinLotto bitcoinLotto;
-
- public GuiUpdateTimer(BitcoinLotto thisLotto) {
- bitcoinLotto = thisLotto;
- }
-
-
- @Override
- public void run() {
- bitcoinLotto.updateGuiElements();
- }
-
-
-
-}
+import java.util.TimerTask;
+
+public class GuiUpdateTimer extends TimerTask {
+
+ private BitcoinLotto bitcoinLotto;
+
+ public GuiUpdateTimer(BitcoinLotto thisLotto) {
+ bitcoinLotto = thisLotto;
+ }
+
+
+ @Override
+ public void run() {
+ bitcoinLotto.updateGuiElements();
+ }
+
+
+
+}
diff --git a/src/LoadAddresses.java b/src/LoadAddresses.java
new file mode 100644
index 0000000..b1257ca
--- /dev/null
+++ b/src/LoadAddresses.java
@@ -0,0 +1,286 @@
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.prefs.Preferences;
+import org.bitcoinj.core.Address;
+import org.bitcoinj.params.MainNetParams;
+
+public class LoadAddresses extends Thread {
+
+ private BitcoinLotto bitcoinLotto;
+ private PrimaryWindow primaryWindow;
+
+ private File tempFile;
+
+ private ProcessStatus thisProcessStatus = ProcessStatus.NOT_INITIALIZED;
+ private Boolean isErrorShown = false;
+
+ long addressCount = 0;
+ char[] charArray;
+ int[][] addressIndex; // Index values for address prefixes
+ IndexHelper[] helperArray;
+
+ @Override
+ public void run() {
+ initializeLookupAddresses();
+ }
+
+ public LoadAddresses(BitcoinLotto thisLotto, PrimaryWindow thisWindow, File thisFile) {
+ this.bitcoinLotto = thisLotto;
+ this.tempFile = thisFile;
+ this.primaryWindow = thisWindow;
+ thisProcessStatus = ProcessStatus.INITIALIZED;
+
+ // Setup the character array
+
+ charArray = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray();
+
+ // Populate the address index array
+ addressIndex = new int[charArray.length][charArray.length];
+ int counterValue = 0;
+ for (int i = 0; i < charArray.length; i++) {
+ for (int j = 0; j < charArray.length; j++) {
+ addressIndex[i][j] = counterValue;
+ counterValue++;
+ // System.out.println("set val " + i + " " + j + " to " + (counterValue-1));
+ }
+ }
+
+ }
+
+ private void initializeLookupAddresses() {
+ /*
+ * Read the address file and populate an array with the data
+ */
+
+ if (this.thisProcessStatus != ProcessStatus.INITIALIZED)
+ return;
+
+ primaryWindow.setStatusTextPane("LOADING ADDRESS FILE
");
+
+ String[] addressStringArray;
+ addressStringArray = readLines(this.tempFile);
+
+ // Create index helper objects to speed process
+ helperArray = new IndexHelper[addressStringArray.length];
+ for (int i = 0; i < addressStringArray.length; i++) {
+ helperArray[i] = new IndexHelper(addressStringArray[i]);
+ }
+
+ // Get address arrays for the three address types
+ bitcoinLotto.setAddressArray(getAddressesFromArray(addressStringArray), this.addressIndex);
+
+ primaryWindow.setStatusTextPane("--------------------
");
+ primaryWindow.setStatusTextPane("FINISHED LOADING " + String.format("%,d", addressCount) + " ADDRESSES" + "
");
+
+
+ // Update the UI with the number of addresses loaded
+ primaryWindow.setTotalAddressLabel(this.getTotalAddressCount());
+
+ // Allow the user to start the lotto
+ primaryWindow.setStartButtonEnabled(true);
+
+ // Save the file path for future use
+ saveFilePath(this.tempFile);
+
+ // Write a small test file to confirm that any matched addresses can be saved
+ writeStarterFile();
+
+ }
+
+ private Address[][] getAddressesFromArray(String[] sourceAddresses) {
+
+ Address thisAddress = null;
+ ArrayList addressList = null;
+
+ addressList = new ArrayList();
+
+ for (int i = 0; i < sourceAddresses.length; i++) {
+
+ // Skip broken addresses
+ if (sourceAddresses[i].length() > 35 || sourceAddresses[i].isEmpty())
+ continue;
+
+ // Only pull addresses of the specified type (we ignore bech32 since it
+ // represents a small portion of addresses)
+
+ // Create an address object from the string
+ try {
+ thisAddress = Address.fromString(MainNetParams.get(), sourceAddresses[i]);
+ } catch (org.bitcoinj.core.AddressFormatException ex) {
+ // ex.printStackTrace();
+ if (!this.isErrorShown) {
+ primaryWindow.showFileErrorMessage();
+ primaryWindow.setStatusTextPane("Address format problem on entry " + sourceAddresses[i] + "
");
+ }
+ this.isErrorShown = true;
+ //System.out.println("bad address on line " + i + ": " + sourceAddresses[i]);
+ primaryWindow.setStatusTextPane("Address format problem on entry " + sourceAddresses[i] + "
");
+ continue;
+ }
+ addressList.add(thisAddress);
+ }
+
+ Address[] tempAddressArray = new Address[addressList.size()];
+ tempAddressArray = addressList.toArray(tempAddressArray);
+ return this.setSegmentedArray_2d(tempAddressArray);
+ }
+
+ private Address[][] setSegmentedArray_2d(Address[] thisAddressArray) {
+ // Returns a 2D array divided by addresses starting letter
+
+ // Create an arraylist to house the Address arrays
+ ArrayList thisList = new ArrayList();
+
+ // Add an array based on each char to the list
+ for (int i = 0; i < charArray.length; i++) {
+ for (int j = 0; j < charArray.length; j++) {
+ Address[] thisArray = getSegmentedArray(thisAddressArray, charArray[i], charArray[j]);
+ thisList.add(thisArray);
+ }
+ }
+
+ // Create the final 3D array
+ Address[][] tempArray = new Address[thisList.size()][];
+ for (int i = 0; i < thisList.size(); i++)
+ tempArray[i] = thisList.get(i);
+
+ return tempArray;
+ }
+
+ private Address[] getSegmentedArray(Address[] thisArray, char firstPrefix, char secondPrefix) {
+ // Returns an array of addresses with a specific leading char
+ ArrayList thisList = new ArrayList();
+
+ for (int i = 0; i < helperArray.length; i++) {
+ if (helperArray[i].isMatch(firstPrefix, secondPrefix)) {
+ thisList.add(thisArray[i]);
+ addressCount++;
+ if (addressCount % 1000 == 0)
+ primaryWindow.setStatusTextPane("Loading addresses : " + String.format("%,d", addressCount) + "
");
+ continue;
+ }
+ }
+
+ Address[] tempArray = new Address[thisList.size()];
+ return thisList.toArray(tempArray);
+ }
+
+ private String[] readLines(File thisFile) {
+ /*
+ * Read lines from a file
+ */
+
+ long startTime = System.nanoTime();
+
+ BufferedReader bufferedReader;
+
+ FileInputStream thisStream;
+ List lines = null;
+ try {
+ thisStream = new FileInputStream(thisFile);
+ bufferedReader = new BufferedReader(new InputStreamReader(thisStream));
+
+ lines = new ArrayList();
+ String line = null;
+
+ while ((line = bufferedReader.readLine()) != null) {
+ // only add addresses starting with 1
+ if (line.charAt(0) == '1')
+ lines.add(line);
+ }
+
+ bufferedReader.close();
+ } catch (FileNotFoundException e) {
+ primaryWindow.showFileErrorMessage();
+ e.printStackTrace();
+
+ } catch (IOException e) {
+ primaryWindow.showFileErrorMessage();
+ e.printStackTrace();
+ }
+
+ long endTime = System.nanoTime();
+
+ primaryWindow.setStatusTextPane("File text read time " + ((endTime - startTime)/10000000) + "ms");
+
+ return lines.toArray(new String[lines.size()]);
+ }
+
+ private long getTotalAddressCount() {
+ // Counts the number of addresses across all arrays
+
+ Address[][] thisArray = this.bitcoinLotto.getAddressArray();
+
+ long totalCount = 0;
+
+ for (int i = 0; i < thisArray.length; i++)
+ totalCount += thisArray[i].length;
+
+ return totalCount;
+ }
+
+ private void saveFilePath(File thisFile) {
+ // Saves the file path for future use
+ String filePathString = thisFile.getAbsolutePath();
+
+ Preferences prefs = Preferences.userRoot().node(BitcoinLotto.prefsNode);
+ prefs.put(BitcoinLotto.prefsFileString, filePathString);
+ }
+
+ public static Boolean isFileAvailable(String filePath) {
+ // Checks to see if a last address file is available to load
+
+ if (filePath == null)
+ return false;
+
+ File tempFile = new File(filePath);
+ return tempFile.exists();
+ }
+
+ public void writeStarterFile() {
+ // Writes a blank file to confirm write process functions as intended
+ String thisString = "Ignore this file";
+ FileWriter thisFile;
+ try {
+ thisFile = new FileWriter("testFilePleaseIgnore.txt");
+ BufferedWriter writer = new BufferedWriter(thisFile);
+ writer.write(thisString);
+ writer.close();
+ } catch (IOException e) {
+ //Exit
+ primaryWindow.showFileErrorMessage();
+ }
+ }
+
+ enum ProcessStatus {
+ NOT_INITIALIZED, INITIALIZING, INITIALIZED;
+ }
+
+ class IndexHelper {
+
+ public IndexHelper(String thisString) {
+ char1 = thisString.charAt(1);
+ char2 = thisString.charAt(2);
+ }
+
+ public Boolean isMatch(char c1, char c2) {
+ if (c1 != char1) return false;
+ if (c2 != char2) return false;
+
+ return true;
+ }
+
+ // Use custom class to only perform string operations once
+ char char1;
+ char char2;
+ }
+
+}
diff --git a/src/PrimaryWindow.java b/src/PrimaryWindow.java
index 5312caa..d44bbab 100644
--- a/src/PrimaryWindow.java
+++ b/src/PrimaryWindow.java
@@ -1,431 +1,475 @@
-import javax.swing.JFrame;
-import javax.swing.JPanel;
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-
-import java.awt.Font;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.io.File;
-import java.net.URISyntaxException;
-
-import javax.swing.SwingConstants;
-import javax.swing.UIManager;
-import javax.swing.UIManager.LookAndFeelInfo;
-import javax.swing.UnsupportedLookAndFeelException;
-import javax.swing.filechooser.FileNameExtensionFilter;
-import javax.swing.JButton;
-import javax.swing.JTextField;
-import javax.swing.SpinnerModel;
-import javax.swing.SpinnerNumberModel;
-import java.awt.CardLayout;
-import javax.swing.JTextArea;
-import javax.swing.JSeparator;
-import javax.swing.JSpinner;
-import javax.swing.JProgressBar;
-import java.awt.Color;
-import javax.swing.JFileChooser;
-import java.awt.SystemColor;
-
-public class PrimaryWindow {
-
- private JFrame frmBitcoinLotto;
- private JTextField fileAddressField;
- private JButton startButton;
- private BitcoinLotto bitcoinLotto;
- private JPanel mainPanel;
- private JPanel workingPanel;
- private JButton pauseButton;
- private JProgressBar progressBar;
- private JSpinner threadSpinner;
- private JButton loadFileButton;
-
- private JLabel totalAttemptsLabel;
- private JLabel attemptsPerSecondLabel;
- private JLabel totalAddressLabel;
- private JLabel successLabel;
- private JLabel timeLabel;
- private JLabel threadCountLabel;
- private JLabel matchedKeyLabel;
- private JLabel matchedAddressLabel;
-
- /*
- * Create the application.
- */
- public PrimaryWindow(BitcoinLotto thisLotto) {
- bitcoinLotto = thisLotto;
- initialize();
- }
-
- public void setWindowEnabled(Boolean thisBool) {
- this.frmBitcoinLotto.setVisible(thisBool);
- }
-
- /**
- * Initialize the contents of the frame.
- */
- private void initialize() {
-
- UIManager.put("ProgressBar[Enabled+Finished].foregroundPainter", Color.black);
-
- try {
- for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
- if ("Nimbus".equals(info.getName())) {
- UIManager.setLookAndFeel(info.getClassName());
- break;
- }
- }
- } catch (Exception e) {
- try {
- UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
- } catch (ClassNotFoundException | InstantiationException | IllegalAccessException
- | UnsupportedLookAndFeelException e1) {
- e1.printStackTrace();
- }
- }
-
- frmBitcoinLotto = new JFrame();
- frmBitcoinLotto.setTitle("Bitcoin Lotto");
- frmBitcoinLotto.setBounds(100, 100, 450, 700);
- frmBitcoinLotto.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- frmBitcoinLotto.getContentPane().setLayout(null);
-
- JPanel panel = new JPanel();
- panel.setBounds(0, 0, 434, 661);
- frmBitcoinLotto.getContentPane().add(panel);
- panel.setLayout(new CardLayout(0, 0));
-
- mainPanel = new JPanel();
- panel.add(mainPanel, "name_432466542248400");
- mainPanel.setLayout(null);
-
- JLabel lblBitcoinLotto = new JLabel("Bitcoin Lotto!");
- lblBitcoinLotto.setBounds(34, 11, 365, 75);
- mainPanel.add(lblBitcoinLotto);
- lblBitcoinLotto.setHorizontalAlignment(SwingConstants.CENTER);
- lblBitcoinLotto.setFont(new Font("Tahoma", Font.PLAIN, 62));
-
- loadFileButton = new JButton("Load Address File");
- loadFileButton.setBounds(10, 513, 300, 54);
- loadFileButton.addActionListener(new FileBrowserListener());
- mainPanel.add(loadFileButton);
- loadFileButton.setFont(new Font("Tahoma", Font.PLAIN, 24));
-
- fileAddressField = new JTextField();
- fileAddressField.setBounds(10, 472, 396, 25);
- mainPanel.add(fileAddressField);
- fileAddressField.setColumns(10);
-
- JLabel lblLottoThreads = new JLabel("Lotto Threads");
- lblLottoThreads.setBounds(10, 364, 414, 33);
- mainPanel.add(lblLottoThreads);
- lblLottoThreads.setHorizontalAlignment(SwingConstants.CENTER);
- lblLottoThreads.setFont(new Font("Tahoma", Font.PLAIN, 24));
-
- startButton = new JButton("Start Lotto!");
- startButton.setBounds(10, 585, 300, 65);
- mainPanel.add(startButton);
- startButton.setFont(new Font("Tahoma", Font.PLAIN, 24));
- startButton.setEnabled(false);
-
- JButton btnExit = new JButton("Exit");
- btnExit.setBounds(320, 585, 104, 65);
- btnExit.setBackground(Color.red);
- mainPanel.add(btnExit);
- btnExit.setFont(new Font("Tahoma", Font.PLAIN, 24));
-
- JTextArea txtrTheBitcoinLotto = new JTextArea();
- txtrTheBitcoinLotto.setFont(new Font("Monospaced", Font.PLAIN, 12));
- txtrTheBitcoinLotto.setForeground(Color.BLACK);
- txtrTheBitcoinLotto.setBackground(SystemColor.controlHighlight);
- txtrTheBitcoinLotto.setEditable(false);
- txtrTheBitcoinLotto.setWrapStyleWord(true);
- txtrTheBitcoinLotto.setLineWrap(true);
- txtrTheBitcoinLotto.setText(
- "The Bitcoin Lotto creates random bitcoin private/public key pairs and compares the addresses to a list of existing addresses. In the event that an address is matched, the public/private keys are saved to a text file in the program directory.\r\n\r\n- Step 1: Load a text file of bitcoin addresses which you would like to check for matches (one address per line)\r\n- Step 2: Start the lotto");
- txtrTheBitcoinLotto.setBounds(10, 97, 414, 213);
- mainPanel.add(txtrTheBitcoinLotto);
-
- JSeparator separator = new JSeparator();
- separator.setBounds(22, 351, 390, 2);
- mainPanel.add(separator);
-
- threadSpinner = new JSpinner();
- threadSpinner.setFont(new Font("Tahoma", Font.PLAIN, 22));
- threadSpinner.setBounds(165, 406, 104, 35);
- mainPanel.add(threadSpinner);
- SpinnerModel spinnerModel = new SpinnerNumberModel(4, 1, 64, 1);
- threadSpinner.setModel(spinnerModel);
-
- ((JSpinner.DefaultEditor) threadSpinner.getEditor()).getTextField().setEditable(false);
-
- btnExit.addActionListener(new ExitListener());
- startButton.addActionListener(new StartListener());
- startButton.setBackground(Color.green);
-
- workingPanel = new JPanel();
- panel.add(workingPanel, "name_432575102303500");
- workingPanel.setLayout(null);
-
- JLabel lblBitcoinLotto_1 = new JLabel("Bitcoin Lotto!");
- lblBitcoinLotto_1.setBounds(76, 5, 281, 51);
- lblBitcoinLotto_1.setHorizontalAlignment(SwingConstants.CENTER);
- lblBitcoinLotto_1.setFont(new Font("Tahoma", Font.PLAIN, 42));
- workingPanel.add(lblBitcoinLotto_1);
-
- JLabel label_1 = new JLabel("Lottery Attempts");
- label_1.setBounds(10, 65, 414, 51);
- label_1.setHorizontalAlignment(SwingConstants.CENTER);
- label_1.setFont(new Font("Tahoma", Font.PLAIN, 32));
- workingPanel.add(label_1);
-
- totalAttemptsLabel = new JLabel("0");
- totalAttemptsLabel.setBounds(10, 110, 414, 34);
- totalAttemptsLabel.setHorizontalAlignment(SwingConstants.CENTER);
- totalAttemptsLabel.setFont(new Font("Tahoma", Font.PLAIN, 32));
- workingPanel.add(totalAttemptsLabel);
-
- JLabel label_3 = new JLabel("Time Elapsed");
- label_3.setBounds(152, 246, 130, 27);
- label_3.setHorizontalAlignment(SwingConstants.CENTER);
- label_3.setFont(new Font("Tahoma", Font.PLAIN, 22));
- workingPanel.add(label_3);
-
- timeLabel = new JLabel("0");
- timeLabel.setBounds(128, 270, 177, 29);
- timeLabel.setHorizontalAlignment(SwingConstants.CENTER);
- timeLabel.setFont(new Font("Tahoma", Font.PLAIN, 24));
- workingPanel.add(timeLabel);
-
- pauseButton = new JButton("Pause Lotto");
- pauseButton.setBounds(10, 541, 414, 51);
- pauseButton.setFont(new Font("Tahoma", Font.PLAIN, 32));
- pauseButton.addActionListener(new PauseListener());
- pauseButton.setBackground(Color.yellow);
- workingPanel.add(pauseButton);
-
- JButton exitButton = new JButton("Exit");
- exitButton.setBounds(312, 603, 112, 47);
- exitButton.setFont(new Font("Tahoma", Font.PLAIN, 32));
- exitButton.setBackground(Color.red);
- exitButton.addActionListener(new ExitListener());
- workingPanel.add(exitButton);
-
- progressBar = new JProgressBar();
- progressBar.setIndeterminate(true);
- progressBar.setBounds(18, 164, 398, 34);
- workingPanel.add(progressBar);
-
- JLabel lblAverageSpeedper = new JLabel("Attempts per second");
- lblAverageSpeedper.setHorizontalAlignment(SwingConstants.CENTER);
- lblAverageSpeedper.setFont(new Font("Tahoma", Font.PLAIN, 18));
- lblAverageSpeedper.setBounds(10, 310, 414, 27);
- workingPanel.add(lblAverageSpeedper);
-
- attemptsPerSecondLabel = new JLabel("0");
- attemptsPerSecondLabel.setHorizontalAlignment(SwingConstants.CENTER);
- attemptsPerSecondLabel.setFont(new Font("Tahoma", Font.PLAIN, 24));
- attemptsPerSecondLabel.setBounds(128, 334, 177, 29);
- workingPanel.add(attemptsPerSecondLabel);
-
- JLabel lblAnyMatchesThis = new JLabel("Any matches this session?");
- lblAnyMatchesThis.setHorizontalAlignment(SwingConstants.CENTER);
- lblAnyMatchesThis.setFont(new Font("Tahoma", Font.PLAIN, 22));
- lblAnyMatchesThis.setBounds(10, 380, 414, 27);
- workingPanel.add(lblAnyMatchesThis);
-
- successLabel = new JLabel("NO");
- successLabel.setForeground(Color.RED);
- successLabel.setHorizontalAlignment(SwingConstants.CENTER);
- successLabel.setFont(new Font("Tahoma", Font.PLAIN, 36));
- successLabel.setBounds(119, 409, 195, 47);
- workingPanel.add(successLabel);
-
- JSeparator separator_1 = new JSeparator();
- separator_1.setBounds(26, 522, 398, 8);
- workingPanel.add(separator_1);
-
- totalAddressLabel = new JLabel("0");
- totalAddressLabel.setHorizontalAlignment(SwingConstants.LEFT);
- totalAddressLabel.setFont(new Font("Tahoma", Font.PLAIN, 12));
- totalAddressLabel.setBounds(137, 212, 122, 15);
- workingPanel.add(totalAddressLabel);
-
- JLabel addressTotal = new JLabel("Target Addresses:");
- addressTotal.setHorizontalAlignment(SwingConstants.RIGHT);
- addressTotal.setFont(new Font("Tahoma", Font.PLAIN, 12));
- addressTotal.setBounds(5, 212, 122, 15);
- workingPanel.add(addressTotal);
-
- threadCountLabel = new JLabel("0");
- threadCountLabel.setHorizontalAlignment(SwingConstants.LEFT);
- threadCountLabel.setFont(new Font("Tahoma", Font.PLAIN, 12));
- threadCountLabel.setBounds(359, 212, 57, 15);
- workingPanel.add(threadCountLabel);
-
- JLabel lblThreadsActive = new JLabel("Threads Active:");
- lblThreadsActive.setHorizontalAlignment(SwingConstants.RIGHT);
- lblThreadsActive.setFont(new Font("Tahoma", Font.PLAIN, 12));
- lblThreadsActive.setBounds(258, 212, 95, 15);
- workingPanel.add(lblThreadsActive);
-
- JLabel matchedAddress = new JLabel("Matched Address:");
- matchedAddress.setHorizontalAlignment(SwingConstants.LEFT);
- matchedAddress.setBounds(10, 441, 106, 15);
- workingPanel.add(matchedAddress);
-
- JLabel matchedKey = new JLabel("Matched Private Key:");
- matchedKey.setHorizontalAlignment(SwingConstants.LEFT);
- matchedKey.setBounds(10, 479, 152, 15);
- workingPanel.add(matchedKey);
-
- matchedAddressLabel = new JLabel("Address");
- matchedAddressLabel.setForeground(Color.BLACK);
- matchedAddressLabel.setFont(new Font("Tahoma", Font.PLAIN, 11));
- matchedAddressLabel.setHorizontalAlignment(SwingConstants.LEFT);
- matchedAddressLabel.setBounds(10, 456, 414, 21);
- matchedAddressLabel.setText("none");
- workingPanel.add(matchedAddressLabel);
-
- matchedKeyLabel = new JLabel("Address");
- matchedKeyLabel.setFont(new Font("Tahoma", Font.PLAIN, 11));
- matchedKeyLabel.setHorizontalAlignment(SwingConstants.LEFT);
- matchedKeyLabel.setBounds(10, 492, 414, 21);
- matchedKeyLabel.setText("none");
- workingPanel.add(matchedKeyLabel);
-
- }
-
- public void setPanel(int panelIndex) {
- switch (panelIndex) {
- case 0:
- mainPanel.setVisible(true);
- workingPanel.setVisible(false);
- break;
- case 1:
- mainPanel.setVisible(false);
- workingPanel.setVisible(true);
- break;
- }
- }
-
- public void setScanAttemptsLabel(long thisLong) {
- this.totalAttemptsLabel.setText(String.format("%,d", thisLong));
- }
-
- public void setTotalAddressLabel(long thisLong) {
- this.totalAddressLabel.setText(String.format("%,d", thisLong));
- }
-
- public void setSuccessLabel(Boolean thisBool, String matchedAddress, String matchedPrivateKey) {
- if (thisBool) {
- this.successLabel.setText("YES!!!1!");
- this.successLabel.setForeground(Color.GREEN);
-
- this.matchedAddressLabel.setText(matchedAddress);
- this.matchedKeyLabel.setText(matchedPrivateKey);
- }
- }
-
- public void setThreadsActiveLabel(int thisThreadCount) {
- this.threadCountLabel.setText(String.format("%,d", thisThreadCount));
- }
-
- public void enableStartButton() {
- startButton.setEnabled(true);
- }
-
- public void setAddressFile(File thisFile) {
- fileAddressField.setText(thisFile.getPath());
- bitcoinLotto.initializeLookupAddresses(thisFile);
- }
-
- public void setThreadCount(int thisInt) {
- threadSpinner.setValue(Integer.valueOf(thisInt));
- }
-
- public void setTimeLabel(long duration, long addressesChecked) {
-
- long second = (duration / 1000) % 60;
- long minute = (duration / (1000 * 60)) % 60;
- long hour = (duration / (1000 * 60 * 60)) % 24;
-
- String time = String.format("%02d:%02d:%02d", hour, minute, second);
- this.timeLabel.setText(String.format(time));
-
- // Set attempts per second
- duration /= 1000;
- if (duration <= 0)
- return;
- attemptsPerSecondLabel.setText(String.format("%,d", addressesChecked / duration));
- }
-
- public void showFileErrorMessage() {
- JOptionPane.showMessageDialog(frmBitcoinLotto, "File read/write failed.");
- }
-
- public void showAddressFormatMessage() {
- JOptionPane.showMessageDialog(frmBitcoinLotto, "One or more addresses are have incorrect formats");
- }
-
- public class PauseListener implements ActionListener {
-
- Boolean isPaused = false;
-
- @Override
- public void actionPerformed(ActionEvent arg0) {
-
- if (isPaused) {
- isPaused = false;
- pauseButton.setBackground(Color.yellow);
- pauseButton.setText("Pause Lotto");
- progressBar.setVisible(true);
- bitcoinLotto.resumeAllThreads();
- } else {
- isPaused = true;
- pauseButton.setBackground(Color.green);
- pauseButton.setText("Resume Lotto");
- progressBar.setVisible(false);
- bitcoinLotto.pauseAllThreads();
- }
- }
- }
-
- public class StartListener implements ActionListener {
- @Override
- public void actionPerformed(ActionEvent arg0) {
- try {
- int cpuThreads = (Integer) threadSpinner.getValue();
- startButton.setText("Loading...");
- bitcoinLotto.startLotto(cpuThreads);
- } catch (URISyntaxException e) {
- e.printStackTrace();
- }
- }
- }
-
- public class FileBrowserListener implements ActionListener {
- @Override
- public void actionPerformed(ActionEvent arg0) {
- JFileChooser fileChooser = new JFileChooser();
- FileNameExtensionFilter filter = new FileNameExtensionFilter("TEXT FILES", "txt", "text");
- fileChooser.setFileFilter(filter);
-
- int returnVal = fileChooser.showOpenDialog(frmBitcoinLotto);
-
- if (returnVal == JFileChooser.APPROVE_OPTION) {
- File thisFile = fileChooser.getSelectedFile();
- setAddressFile(thisFile);
- }
- }
- }
-
- public class ExitListener implements ActionListener {
- @Override
- public void actionPerformed(ActionEvent arg0) {
- System.exit(0);
- }
- }
-
-
-}
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+
+import java.awt.Font;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+
+import javax.swing.SwingConstants;
+import javax.swing.UIManager;
+import javax.swing.UIManager.LookAndFeelInfo;
+import javax.swing.UnsupportedLookAndFeelException;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.DefaultEditorKit;
+import javax.swing.text.Document;
+import javax.swing.text.html.HTMLDocument;
+import javax.swing.text.html.HTMLEditorKit;
+import javax.swing.JButton;
+import javax.swing.JTextField;
+import javax.swing.SpinnerModel;
+import javax.swing.SpinnerNumberModel;
+import java.awt.CardLayout;
+import javax.swing.JTextArea;
+import javax.swing.JSeparator;
+import javax.swing.JSpinner;
+import javax.swing.JProgressBar;
+import javax.swing.JScrollPane;
+
+import java.awt.Color;
+import javax.swing.JFileChooser;
+import java.awt.SystemColor;
+import javax.swing.JTextPane;
+
+public class PrimaryWindow {
+
+ private JFrame frmBitcoinLotto;
+ private JTextField fileAddressField;
+ private JButton startButton;
+ private BitcoinLotto bitcoinLotto;
+ private JPanel mainPanel;
+ private JPanel workingPanel;
+ private JButton pauseButton;
+ private JProgressBar progressBar;
+ private JSpinner threadSpinner;
+ private JButton loadFileButton;
+ private JTextPane statusTextPane;
+
+ private JLabel totalAttemptsLabel;
+ private JLabel attemptsPerSecondLabel;
+ private JLabel totalAddressLabel;
+ private JLabel successLabel;
+ private JLabel timeLabel;
+ private JLabel threadCountLabel;
+ private JLabel matchedKeyLabel;
+ private JLabel matchedAddressLabel;
+ private JScrollPane scrollPane;
+
+ /*
+ * Create the application.
+ */
+ public PrimaryWindow(BitcoinLotto thisLotto) {
+ bitcoinLotto = thisLotto;
+ initialize();
+ }
+
+ public void setWindowEnabled(Boolean thisBool) {
+ this.frmBitcoinLotto.setVisible(thisBool);
+ }
+
+ /**
+ * Initialize the contents of the frame.
+ */
+ private void initialize() {
+
+ UIManager.put("ProgressBar[Enabled+Finished].foregroundPainter", Color.black);
+
+ try {
+ for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
+ if ("Nimbus".equals(info.getName())) {
+ UIManager.setLookAndFeel(info.getClassName());
+ break;
+ }
+ }
+ } catch (Exception e) {
+ try {
+ UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
+ } catch (ClassNotFoundException | InstantiationException | IllegalAccessException
+ | UnsupportedLookAndFeelException e1) {
+ e1.printStackTrace();
+ }
+ }
+
+ frmBitcoinLotto = new JFrame();
+ frmBitcoinLotto.setTitle("Bitcoin Lotto");
+ frmBitcoinLotto.setBounds(100, 100, 450, 700);
+ frmBitcoinLotto.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ frmBitcoinLotto.getContentPane().setLayout(null);
+
+ JPanel panel = new JPanel();
+ panel.setBounds(0, 0, 434, 661);
+ frmBitcoinLotto.getContentPane().add(panel);
+ panel.setLayout(new CardLayout(0, 0));
+
+ mainPanel = new JPanel();
+ panel.add(mainPanel, "name_432466542248400");
+ mainPanel.setLayout(null);
+
+ JLabel lblBitcoinLotto = new JLabel("Bitcoin Lotto!");
+ lblBitcoinLotto.setBounds(34, 11, 365, 75);
+ mainPanel.add(lblBitcoinLotto);
+ lblBitcoinLotto.setHorizontalAlignment(SwingConstants.CENTER);
+ lblBitcoinLotto.setFont(new Font("Tahoma", Font.PLAIN, 62));
+
+ loadFileButton = new JButton("Choose Address File");
+ loadFileButton.setBounds(19, 455, 211, 33);
+ loadFileButton.addActionListener(new FileBrowserListener());
+ mainPanel.add(loadFileButton);
+ loadFileButton.setFont(new Font("Tahoma", Font.PLAIN, 18));
+
+ fileAddressField = new JTextField();
+ fileAddressField.setBounds(19, 419, 396, 25);
+ mainPanel.add(fileAddressField);
+ fileAddressField.setColumns(10);
+
+ JLabel lblLottoThreads = new JLabel("Lotto Threads");
+ lblLottoThreads.setBounds(10, 331, 414, 33);
+ mainPanel.add(lblLottoThreads);
+ lblLottoThreads.setHorizontalAlignment(SwingConstants.CENTER);
+ lblLottoThreads.setFont(new Font("Tahoma", Font.PLAIN, 24));
+
+ startButton = new JButton("Start Lotto!");
+ startButton.setBounds(10, 499, 300, 65);
+ mainPanel.add(startButton);
+ startButton.setFont(new Font("Tahoma", Font.PLAIN, 24));
+ startButton.setEnabled(false);
+
+ JButton btnExit = new JButton("Exit");
+ btnExit.setBounds(320, 499, 104, 65);
+ btnExit.setBackground(Color.red);
+ mainPanel.add(btnExit);
+ btnExit.setFont(new Font("Tahoma", Font.PLAIN, 24));
+
+ JTextArea txtrTheBitcoinLotto = new JTextArea();
+ txtrTheBitcoinLotto.setFont(new Font("Monospaced", Font.PLAIN, 12));
+ txtrTheBitcoinLotto.setForeground(Color.BLACK);
+ txtrTheBitcoinLotto.setBackground(SystemColor.controlHighlight);
+ txtrTheBitcoinLotto.setEditable(false);
+ txtrTheBitcoinLotto.setWrapStyleWord(true);
+ txtrTheBitcoinLotto.setLineWrap(true);
+ txtrTheBitcoinLotto.setText(
+ "The Bitcoin Lotto creates random bitcoin private/public key pairs and compares the addresses to a list of existing addresses. In the event that an address is matched, the public/private keys are saved to a text file in the program directory.\r\n\r\n- Step 1: Load a text file of bitcoin addresses which you would like to check for matches (one address per line)\r\n- Step 2: Start the lotto");
+ txtrTheBitcoinLotto.setBounds(10, 97, 414, 213);
+ mainPanel.add(txtrTheBitcoinLotto);
+
+ JSeparator separator = new JSeparator();
+ separator.setBounds(22, 321, 390, 2);
+ mainPanel.add(separator);
+
+ threadSpinner = new JSpinner();
+ threadSpinner.setFont(new Font("Tahoma", Font.PLAIN, 22));
+ threadSpinner.setBounds(165, 373, 104, 35);
+ mainPanel.add(threadSpinner);
+ SpinnerModel spinnerModel = new SpinnerNumberModel(4, 1, 64, 1);
+ threadSpinner.setModel(spinnerModel);
+
+ ((JSpinner.DefaultEditor) threadSpinner.getEditor()).getTextField().setEditable(false);
+
+ btnExit.addActionListener(new ExitListener());
+ startButton.addActionListener(new StartListener());
+ startButton.setBackground(Color.green);
+
+ statusTextPane = new JTextPane();
+ statusTextPane.setForeground(Color.BLUE);
+ statusTextPane.setBackground(Color.WHITE);
+ statusTextPane.setContentType("text/html");
+ statusTextPane.setEditable(false);
+ //statusTextPane.setBounds(10, 585, 151, 65);
+ statusTextPane.setAutoscrolls(true);
+ mainPanel.add(statusTextPane);
+
+ scrollPane = new JScrollPane(statusTextPane);
+ scrollPane.setBounds(10, 570, 414, 80);
+ scrollPane.setAutoscrolls(true);
+ mainPanel.add(scrollPane);
+
+
+ workingPanel = new JPanel();
+ panel.add(workingPanel, "name_432575102303500");
+ workingPanel.setLayout(null);
+
+ JLabel lblBitcoinLotto_1 = new JLabel("Bitcoin Lotto!");
+ lblBitcoinLotto_1.setBounds(76, 5, 281, 51);
+ lblBitcoinLotto_1.setHorizontalAlignment(SwingConstants.CENTER);
+ lblBitcoinLotto_1.setFont(new Font("Tahoma", Font.PLAIN, 42));
+ workingPanel.add(lblBitcoinLotto_1);
+
+ JLabel label_1 = new JLabel("Lottery Attempts");
+ label_1.setBounds(10, 65, 414, 51);
+ label_1.setHorizontalAlignment(SwingConstants.CENTER);
+ label_1.setFont(new Font("Tahoma", Font.PLAIN, 32));
+ workingPanel.add(label_1);
+
+ totalAttemptsLabel = new JLabel("0");
+ totalAttemptsLabel.setBounds(10, 110, 414, 34);
+ totalAttemptsLabel.setHorizontalAlignment(SwingConstants.CENTER);
+ totalAttemptsLabel.setFont(new Font("Tahoma", Font.PLAIN, 32));
+ workingPanel.add(totalAttemptsLabel);
+
+ JLabel label_3 = new JLabel("Time Elapsed");
+ label_3.setBounds(152, 246, 130, 27);
+ label_3.setHorizontalAlignment(SwingConstants.CENTER);
+ label_3.setFont(new Font("Tahoma", Font.PLAIN, 22));
+ workingPanel.add(label_3);
+
+ timeLabel = new JLabel("0");
+ timeLabel.setBounds(128, 270, 177, 29);
+ timeLabel.setHorizontalAlignment(SwingConstants.CENTER);
+ timeLabel.setFont(new Font("Tahoma", Font.PLAIN, 24));
+ workingPanel.add(timeLabel);
+
+ pauseButton = new JButton("Pause Lotto");
+ pauseButton.setBounds(10, 541, 414, 51);
+ pauseButton.setFont(new Font("Tahoma", Font.PLAIN, 32));
+ pauseButton.addActionListener(new PauseListener());
+ pauseButton.setBackground(Color.yellow);
+ workingPanel.add(pauseButton);
+
+ JButton exitButton = new JButton("Exit");
+ exitButton.setBounds(312, 603, 112, 47);
+ exitButton.setFont(new Font("Tahoma", Font.PLAIN, 32));
+ exitButton.setBackground(Color.red);
+ exitButton.addActionListener(new ExitListener());
+ workingPanel.add(exitButton);
+
+ progressBar = new JProgressBar();
+ progressBar.setIndeterminate(true);
+ progressBar.setBounds(18, 164, 398, 34);
+ workingPanel.add(progressBar);
+
+ JLabel lblAverageSpeedper = new JLabel("Attempts per second");
+ lblAverageSpeedper.setHorizontalAlignment(SwingConstants.CENTER);
+ lblAverageSpeedper.setFont(new Font("Tahoma", Font.PLAIN, 18));
+ lblAverageSpeedper.setBounds(10, 310, 414, 27);
+ workingPanel.add(lblAverageSpeedper);
+
+ attemptsPerSecondLabel = new JLabel("0");
+ attemptsPerSecondLabel.setHorizontalAlignment(SwingConstants.CENTER);
+ attemptsPerSecondLabel.setFont(new Font("Tahoma", Font.PLAIN, 24));
+ attemptsPerSecondLabel.setBounds(128, 334, 177, 29);
+ workingPanel.add(attemptsPerSecondLabel);
+
+ JLabel lblAnyMatchesThis = new JLabel("Any matches this session?");
+ lblAnyMatchesThis.setHorizontalAlignment(SwingConstants.CENTER);
+ lblAnyMatchesThis.setFont(new Font("Tahoma", Font.PLAIN, 22));
+ lblAnyMatchesThis.setBounds(10, 380, 414, 27);
+ workingPanel.add(lblAnyMatchesThis);
+
+ successLabel = new JLabel("NO");
+ successLabel.setForeground(Color.RED);
+ successLabel.setHorizontalAlignment(SwingConstants.CENTER);
+ successLabel.setFont(new Font("Tahoma", Font.PLAIN, 36));
+ successLabel.setBounds(119, 409, 195, 47);
+ workingPanel.add(successLabel);
+
+ JSeparator separator_1 = new JSeparator();
+ separator_1.setBounds(26, 522, 398, 8);
+ workingPanel.add(separator_1);
+
+ totalAddressLabel = new JLabel("0");
+ totalAddressLabel.setHorizontalAlignment(SwingConstants.LEFT);
+ totalAddressLabel.setFont(new Font("Tahoma", Font.PLAIN, 12));
+ totalAddressLabel.setBounds(138, 198, 122, 15);
+ workingPanel.add(totalAddressLabel);
+
+ JLabel addressTotal = new JLabel("Target Addresses:");
+ addressTotal.setHorizontalAlignment(SwingConstants.RIGHT);
+ addressTotal.setFont(new Font("Tahoma", Font.PLAIN, 12));
+ addressTotal.setBounds(6, 198, 122, 15);
+ workingPanel.add(addressTotal);
+
+ threadCountLabel = new JLabel("0");
+ threadCountLabel.setHorizontalAlignment(SwingConstants.LEFT);
+ threadCountLabel.setFont(new Font("Tahoma", Font.PLAIN, 12));
+ threadCountLabel.setBounds(360, 198, 57, 15);
+ workingPanel.add(threadCountLabel);
+
+ JLabel lblThreadsActive = new JLabel("Threads Active:");
+ lblThreadsActive.setHorizontalAlignment(SwingConstants.RIGHT);
+ lblThreadsActive.setFont(new Font("Tahoma", Font.PLAIN, 12));
+ lblThreadsActive.setBounds(259, 198, 95, 15);
+ workingPanel.add(lblThreadsActive);
+
+ JLabel matchedAddress = new JLabel("Matched Public Address:");
+ matchedAddress.setHorizontalAlignment(SwingConstants.LEFT);
+ matchedAddress.setBounds(10, 441, 137, 15);
+ workingPanel.add(matchedAddress);
+
+ JLabel matchedKey = new JLabel("Matched Private Key:");
+ matchedKey.setHorizontalAlignment(SwingConstants.LEFT);
+ matchedKey.setBounds(10, 479, 152, 15);
+ workingPanel.add(matchedKey);
+
+ matchedAddressLabel = new JLabel("Address");
+ matchedAddressLabel.setForeground(Color.BLACK);
+ matchedAddressLabel.setFont(new Font("Tahoma", Font.PLAIN, 11));
+ matchedAddressLabel.setHorizontalAlignment(SwingConstants.LEFT);
+ matchedAddressLabel.setBounds(10, 456, 414, 21);
+ matchedAddressLabel.setText("none");
+ workingPanel.add(matchedAddressLabel);
+
+ matchedKeyLabel = new JLabel("Address");
+ matchedKeyLabel.setFont(new Font("Tahoma", Font.PLAIN, 11));
+ matchedKeyLabel.setHorizontalAlignment(SwingConstants.LEFT);
+ matchedKeyLabel.setBounds(10, 492, 414, 21);
+ matchedKeyLabel.setText("none");
+ workingPanel.add(matchedKeyLabel);
+
+ }
+
+ public void setPanel(int panelIndex) {
+ switch (panelIndex) {
+ case 0:
+ mainPanel.setVisible(true);
+ workingPanel.setVisible(false);
+ break;
+ case 1:
+ mainPanel.setVisible(false);
+ workingPanel.setVisible(true);
+ break;
+ }
+ }
+
+ public void setScanAttemptsLabel(long thisLong) {
+ this.totalAttemptsLabel.setText(String.format("%,d", thisLong));
+ }
+
+ public void setTotalAddressLabel(long thisLong) {
+ this.totalAddressLabel.setText(String.format("%,d", thisLong));
+ }
+
+ public void setSuccessLabel(Boolean thisBool, String matchedAddress, String matchedPrivateKey) {
+ if (thisBool) {
+ this.successLabel.setText("YES!!");
+ this.successLabel.setForeground(Color.GREEN);
+
+ this.matchedAddressLabel.setText(matchedAddress);
+ this.matchedKeyLabel.setText(matchedPrivateKey);
+ }
+ }
+
+ public void setThreadsActiveLabel(int thisThreadCount) {
+ this.threadCountLabel.setText(String.format("%,d", thisThreadCount));
+ }
+
+ public void setStartButtonEnabled(Boolean thisBool) {
+ startButton.setEnabled(thisBool);
+ }
+
+ public void setAddressFile(File thisFile) {
+
+ this.setStartButtonEnabled(false);
+
+ fileAddressField.setText(thisFile.getPath());
+
+ //Set the new address file
+ LoadAddresses loader = new LoadAddresses(this.bitcoinLotto, this, thisFile);
+ loader.run();
+ }
+
+ public void setThreadCount(int thisInt) {
+ threadSpinner.setValue(Integer.valueOf(thisInt));
+ }
+
+ public void setTimeLabel(long duration, long addressesChecked) {
+
+ long second = (duration / 1000) % 60;
+ long minute = (duration / (1000 * 60)) % 60;
+ long hour = (duration / (1000 * 60 * 60)) % 24;
+
+ String time = String.format("%04d:%02d:%02d", hour, minute, second);
+ this.timeLabel.setText(String.format(time));
+
+ // Set attempts per second
+ duration /= 1000;
+ if (duration <= 0)
+ return;
+ attemptsPerSecondLabel.setText(String.format("%,d", addressesChecked / duration));
+ }
+
+ public void showFileErrorMessage() {
+ JOptionPane.showMessageDialog(frmBitcoinLotto, "File read/write failed.");
+ }
+
+ public void showAddressFormatMessage() {
+ JOptionPane.showMessageDialog(frmBitcoinLotto, "One or more addresses are have incorrect formats");
+ }
+
+ public void setStatusTextPane(String thisString) {
+
+ HTMLDocument doc = (HTMLDocument) statusTextPane.getDocument();
+ HTMLEditorKit editorKit = (HTMLEditorKit)statusTextPane.getEditorKit();
+ try {
+ editorKit.insertHTML(doc, doc.getLength(), thisString, 0, 0, null);
+ statusTextPane.setCaretPosition(doc.getLength());
+ } catch (BadLocationException | IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ public class PauseListener implements ActionListener {
+
+ Boolean isPaused = false;
+
+ @Override
+ public void actionPerformed(ActionEvent arg0) {
+
+ if (isPaused) {
+ isPaused = false;
+ pauseButton.setBackground(Color.yellow);
+ pauseButton.setText("Pause Lotto");
+ progressBar.setVisible(true);
+ bitcoinLotto.resumeAllThreads();
+ } else {
+ isPaused = true;
+ pauseButton.setBackground(Color.green);
+ pauseButton.setText("Resume Lotto");
+ progressBar.setVisible(false);
+ bitcoinLotto.pauseAllThreads();
+ }
+ }
+ }
+
+ public class StartListener implements ActionListener {
+ @Override
+ public void actionPerformed(ActionEvent arg0) {
+ try {
+ int cpuThreads = (Integer) threadSpinner.getValue();
+ startButton.setText("Loading...");
+ bitcoinLotto.startLotto(cpuThreads);
+ } catch (URISyntaxException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public class FileBrowserListener implements ActionListener {
+ @Override
+ public void actionPerformed(ActionEvent arg0) {
+ JFileChooser fileChooser = new JFileChooser();
+ FileNameExtensionFilter filter = new FileNameExtensionFilter("TEXT FILES", "txt", "text");
+ fileChooser.setFileFilter(filter);
+
+ int returnVal = fileChooser.showOpenDialog(frmBitcoinLotto);
+
+ if (returnVal == JFileChooser.APPROVE_OPTION) {
+ File thisFile = fileChooser.getSelectedFile();
+ setAddressFile(thisFile);
+ }
+ }
+ }
+
+ public class ExitListener implements ActionListener {
+ @Override
+ public void actionPerformed(ActionEvent arg0) {
+ System.exit(0);
+ }
+ }
+
+}
diff --git a/src/SearchThread.java b/src/SearchThread.java
index 24f683a..a8810ea 100644
--- a/src/SearchThread.java
+++ b/src/SearchThread.java
@@ -1,113 +1,162 @@
-import java.io.BufferedWriter;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.util.Random;
-
-import org.bitcoinj.core.Address;
-import org.bitcoinj.core.ECKey;
-import org.bitcoinj.params.MainNetParams;
-import org.bitcoinj.script.Script.ScriptType;
-
-public class SearchThread extends Thread {
-
- private BitcoinLotto bitcoinLotto;
- private Address[] addressArray;
-
- private Boolean isInterrupted = false;
- private int startDelay = 0;
-
- @Override
- public void run() {
- try {
- try {
- if (startDelay > 0)
- Thread.sleep(startDelay);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
-
- //If the start delay is greater than zero assume this is the initial run (ie not a resumed event)
- if (startDelay > 0 && !isInterrupted) {
- bitcoinLotto.updateThreadCount();
- checkAddresses();
- }
-
- } catch (IOException | URISyntaxException e) {
- e.printStackTrace();
- }
- }
-
- public void initialize(BitcoinLotto thisLotto, int thisStartDelay) {
- bitcoinLotto = thisLotto;
- addressArray = thisLotto.getAddressArray();
- startDelay = thisStartDelay;
- }
-
- private void checkAddresses() throws IOException, URISyntaxException {
-
- while (!isInterrupted) {
- //Generate a random address/key combination
- ECKey thisKey = new ECKey();
- //Create an address object
- Address pubAddress = Address.fromKey(MainNetParams.get(), thisKey, ScriptType.P2PKH);
- //Compare the newly-created address against the address list
- if (evaluateAddress(pubAddress))
- //If an address miraculously matches something from the address list
- handleMatch(thisKey);
- }
- }
-
- private Boolean evaluateAddress(Address thisAddress) {
-
- bitcoinLotto.logAddressCheck();
-
- for (int i = 0; i < addressArray.length; i++) {
- if (thisAddress.equals(addressArray[i]))
- return true;
- }
- return false;
- }
-
- private void handleMatch(ECKey thisKey) throws IOException {
- /*
- * Called if an address match is made. Saves the info to a text file.
- */
-
- String thisString = "";
-
- thisString += Address.fromKey(MainNetParams.get(), thisKey, ScriptType.P2PKH);
- thisString += "\n";
- thisString += thisKey.getPrivateKeyAsHex();
- thisString += "\n";
- thisString += thisKey.getPublicKeyAsHex();
- thisString += "\n";
- thisString += thisKey.getPrivateKeyAsWiF(MainNetParams.get());
-
- int randomInt = new Random().nextInt(9999999);
-
- FileWriter thisFile = new FileWriter("bitcoinLottoWinner" + randomInt + ".txt");
- BufferedWriter writer = new BufferedWriter(thisFile);
- writer.write(thisString);
- writer.close();
-
- //Notifies the primary class so UI elements can be updated
- bitcoinLotto.notifySuccess(Address.fromKey(MainNetParams.get(), thisKey, ScriptType.P2PKH).toString(),
- thisKey.getPrivateKeyAsWiF(MainNetParams.get()));
- }
-
- public void resumeThread() {
- isInterrupted = false;
- try {
- checkAddresses();
- } catch (IOException | URISyntaxException e) {
- e.printStackTrace();
- }
- }
-
- public void stopThread() {
- isInterrupted = true;
- }
-
-
-}
+import java.io.BufferedWriter;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.Random;
+
+import org.bitcoinj.core.Address;
+import org.bitcoinj.core.ECKey;
+import org.bitcoinj.params.MainNetParams;
+import org.bitcoinj.script.Script.ScriptType;
+
+public class SearchThread extends Thread {
+
+ private BitcoinLotto bitcoinLotto;
+ private Address[][] addressArray;
+ private int[][] indexArray;
+ private char[] charArray;
+
+ private Boolean isInterrupted = false;
+ private int startDelay = 0;
+
+ @Override
+ public void run() {
+ try {
+ try {
+ if (startDelay > 0)
+ Thread.sleep(startDelay);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ // If the start delay is greater than zero assume this is the initial run (ie
+ // not a resumed event)
+ if (startDelay > 0 && !isInterrupted) {
+ // Create the character array to speed searches
+ this.charArray = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray();
+ // Update the active thread count
+ bitcoinLotto.updateThreadCount();
+ // Start checking addresses
+ checkAddresses();
+ }
+
+ } catch (IOException | URISyntaxException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public SearchThread(BitcoinLotto thisLotto, ScriptType thisType, int thisStartDelay) {
+ bitcoinLotto = thisLotto;
+ addressArray = thisLotto.getAddressArray();
+ this.indexArray = thisLotto.getIndexArray();
+ startDelay = thisStartDelay;
+ }
+
+ private void checkAddresses() throws IOException, URISyntaxException {
+
+ ECKey thisKey;
+ Address pubAddress;
+
+ while (!isInterrupted) {
+ // Generate a random address/key combination
+ thisKey = new ECKey();
+ // Create an address object based on the address format
+ pubAddress = Address.fromKey(MainNetParams.get(), thisKey, ScriptType.P2PKH);
+
+ // Get the correct address array
+ Address[] thisAddressArray = this.getAddressArray(pubAddress);
+ if (evaluateAddress(pubAddress, thisAddressArray))
+ // If an address miraculously matches something from the address list
+ handleMatch(thisKey);
+ }
+ }
+
+ private Boolean evaluateAddress(Address thisAddress, Address[] thisArray) {
+
+ bitcoinLotto.logAddressCheck();
+
+ if (thisArray.length <= 0)
+ return false;
+
+ //System.out.println(thisAddress + " - " + thisArray[0]);
+
+ for (int i = 0; i < thisArray.length; i++) {
+ if (thisAddress.equals(thisArray[i]))
+ return true;
+
+ }
+ return false;
+ }
+
+ private Address[] getAddressArray(Address thisAddress) {
+ // Retrieves the correct address based on leading prefix
+
+ String thisString = thisAddress.toString();
+ char firstChar = thisString.charAt(1);
+ char secondChar = thisString.charAt(2);
+
+ int indexVal = this.getLookupIndex(firstChar, secondChar);
+
+ return this.addressArray[indexVal];
+ }
+
+ private int getLookupIndex(char firstChar, char secondChar) {
+ // Returns an index to lookup the correct segmented address array
+
+ int firstVal = -1;
+ int secondVal = -1;
+
+ for (int i = 0; i < charArray.length; i++) {
+ if (charArray[i] == firstChar)
+ firstVal = i;
+ if (charArray[i] == secondChar)
+ secondVal = i;
+
+ if (firstVal > 0 && secondVal > 0) break;
+ }
+
+ return this.indexArray[firstVal][secondVal];
+
+ }
+
+ private void handleMatch(ECKey thisKey) throws IOException {
+ /*
+ * Called if an address match is made. Saves the info to a text file.
+ */
+
+ String thisString = "";
+
+ thisString += Address.fromKey(MainNetParams.get(), thisKey, ScriptType.P2PKH);
+ thisString += "\n";
+ thisString += thisKey.getPrivateKeyAsHex();
+ thisString += "\n";
+ thisString += thisKey.getPublicKeyAsHex();
+ thisString += "\n";
+ thisString += thisKey.getPrivateKeyAsWiF(MainNetParams.get());
+
+ int randomInt = new Random().nextInt(9999999);
+
+ FileWriter thisFile = new FileWriter("bitcoinLottoWinner" + randomInt + ".txt");
+ BufferedWriter writer = new BufferedWriter(thisFile);
+ writer.write(thisString);
+ writer.close();
+
+ // Notifies the primary class so UI elements can be updated
+ bitcoinLotto.notifySuccess(Address.fromKey(MainNetParams.get(), thisKey, ScriptType.P2PKH).toString(),
+ thisKey.getPrivateKeyAsWiF(MainNetParams.get()));
+ }
+
+ public void resumeThread() {
+ isInterrupted = false;
+ try {
+ checkAddresses();
+ } catch (IOException | URISyntaxException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void stopThread() {
+ isInterrupted = true;
+ }
+
+}