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; + } + +}