├── README.md ├── bmc.jpg ├── example address lists ├── addressListLarge.txt └── addressListSmall.txt ├── license.txt └── src ├── AddressGroup.java ├── BitcoinMicroCollider.java ├── FileStatus.java ├── GuiUpdateTimer.java ├── LoadAddresses.java ├── PrimaryWindow.java └── SearchThread.java /README.md: -------------------------------------------------------------------------------- 1 | # Bitcoin Micro Collider 2 | 3 | Bitcoin Micro Collider is a bitcoin address/key generator which compares randomly generated address/key combinations against a list of addresses provided by the user. 4 | 5 | For example, if a user supplied a list of all bitcoin addresses containing bitcoin balances, the program would generate random address/key combinations until a match was found against an address containing a balance. The program would alert the user and save the address/key combination to a text file for future use. The user would have the option to utilize the private key to take control of the address and it's underlying holdings. 6 |

7 | 8 |

9 | 10 | # How to use Bitcoin Micro Collider 11 | 12 | Step 0: **Install a Java runtime environment on your computer**. If you don't already have this installed, a Java runtime can be downloaded from ninite.com (for example Java AdoptOpenJDK). 13 | 14 | Step 1: **Download the Bitcoin Micro Collider executable JAR or EXE file [here](https://github.com/traxm/Bitcoin-Micro-Collider/releases)**. 15 | 16 | Step 2: **Create or download a list of bitcoin addresses to scan**. The file needs to be in text format with each address on a separate line. Example file pre-populated with addresses [here](https://github.com/traxm/Bitcoin-Micro-Collider/tree/master/example%20address%20lists). 17 | 18 | Step 3: **Open the executable JAR file** called BitcoinMicroCollider.jar 19 | 20 | Step 4: **Click "Load Address File"** and browse to the bitcoin address text file 21 | 22 | Step 5: Wait while the file is loaded (this can take some time for large files) 23 | 24 | Step 6: After the text file has been loaded, the **"Start Collider"** button will turn green. Click this button to begin the collider process. 25 | -------------------------------------------------------------------------------- /bmc.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/traxm/Bitcoin-Micro-Collider/a120432e09a923ecc2a33a8ffb8f8a4aecab691e/bmc.jpg -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 BitcoinLotto contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/AddressGroup.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | 3 | import org.bitcoinj.core.Address; 4 | 5 | public class AddressGroup { 6 | 7 | ArrayList
addressList; 8 | Address[] addressArray; 9 | 10 | boolean isFinalized = false; //Has the arraylist been coverted to an array 11 | 12 | 13 | public AddressGroup() { 14 | addressList = new ArrayList
(); 15 | } 16 | 17 | public void addAddressArray(Address[] thisArray) { 18 | for (int i=0; i < thisArray.length; i++) { 19 | addressList.add(thisArray[i]); 20 | } 21 | } 22 | 23 | public void addAddress(Address thisAddress) { 24 | addressList.add(thisAddress); 25 | } 26 | 27 | public Address[] getAddressArray() { 28 | return addressArray; 29 | } 30 | 31 | public void finalizeGroup() { 32 | 33 | addressArray = new Address[addressList.size()]; 34 | 35 | for (int i = 0; i < addressList.size(); i++) 36 | addressArray[i] = addressList.get(i); 37 | 38 | addressList = null; 39 | 40 | isFinalized = true; 41 | } 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/BitcoinMicroCollider.java: -------------------------------------------------------------------------------- 1 | import java.io.File; 2 | import java.net.URISyntaxException; 3 | import java.util.Timer; 4 | import java.util.prefs.Preferences; 5 | 6 | import org.bitcoinj.script.Script.ScriptType; 7 | 8 | public class BitcoinMicroCollider { 9 | 10 | public static void main(String[] args) { 11 | BitcoinMicroCollider thisCollider = new BitcoinMicroCollider(); 12 | 13 | boolean isResetFilePath = false; 14 | if (args != null && args.length > 0 && !args[0].isEmpty()) 15 | isResetFilePath = args[0].equals("resetFilePath") ? true : false; 16 | 17 | 18 | charArray = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray(); 19 | 20 | 21 | thisCollider.startGui(isResetFilePath); 22 | } 23 | 24 | private Status colliderStatus = Status.MAIN_MENU; 25 | private FileStatus fileStatus = FileStatus.FILE_NOT_LOADED; 26 | private Boolean isInitialized = false; 27 | private AddressGroup[][][][] p2pkh_address_array; // Array of address arrays 28 | private SearchThread[] threadArray; 29 | private Timer guiTimer; 30 | private String[] addressLabelArray = new String[10]; 31 | public static char[] charArray; 32 | 33 | 34 | private GuiUpdateTimer guiUpdateTimer; 35 | 36 | private PrimaryWindow primaryWindow; 37 | private long totalCheckCount = 0; 38 | private long startTime = 0; 39 | private int threadCount = 1; 40 | 41 | private int activeThreadCount = 0; // threads loaded and running 42 | private long pausedTimeTotal = 0; 43 | 44 | private long pauseStartTime = 0; 45 | public static String prefsNode = "com/github/traxm/Bitcoin-Micro-Collider"; 46 | public static String prefsFileString = "filePath"; 47 | public static String prefsThreadString = "threadCount"; 48 | 49 | public AddressGroup[][][][] getAddressArray() { 50 | return this.p2pkh_address_array; 51 | } 52 | 53 | 54 | 55 | public Boolean isInitialized() { 56 | return isInitialized; 57 | } 58 | 59 | public void logAddressCheck() { 60 | // Track address checks 61 | 62 | totalCheckCount++; 63 | } 64 | 65 | public void notifySuccess(String matchAddress, String matchKey) { 66 | primaryWindow.setSuccessLabel(true, matchAddress, matchKey); 67 | } 68 | 69 | public void pauseAllThreads() { 70 | /* 71 | * End each thread based on user input 72 | */ 73 | 74 | colliderStatus = Status.PAUSED; 75 | 76 | for (int i = 0; i < this.threadArray.length; i++) 77 | this.threadArray[i].stopThread(); 78 | 79 | pauseStartTime = System.nanoTime(); 80 | activeThreadCount = 0; 81 | primaryWindow.setThreadsActiveLabel(activeThreadCount); 82 | } 83 | 84 | public void resumeAllThreads() { 85 | /* 86 | * Create and start new threads based on user input 87 | */ 88 | 89 | colliderStatus = Status.RUNNING; 90 | 91 | this.startThreads(threadCount); 92 | 93 | // Update the paused time 94 | this.pausedTimeTotal += (System.nanoTime() - this.pauseStartTime); 95 | } 96 | 97 | private void saveThreadCount(int threadCount) { 98 | // Saves the file path for future use 99 | Preferences prefs = Preferences.userRoot().node(prefsNode); 100 | prefs.putInt(prefsThreadString, threadCount); 101 | } 102 | 103 | private void startGui(boolean resetFilePath) { 104 | /* 105 | * Create a frame and populate with components 106 | */ 107 | primaryWindow = new PrimaryWindow(this); 108 | 109 | primaryWindow.setWindowEnabled(true); 110 | 111 | // Check to see if an existing address file is available 112 | Preferences prefs = Preferences.userRoot().node(prefsNode); 113 | // Does the preference entry exist 114 | // Is the file available 115 | if (LoadAddresses.isFileAvailable(prefs.get(prefsFileString, null))) { 116 | // Load the existing file 117 | if (!resetFilePath) 118 | primaryWindow.setAddressFile(new File(prefs.get(prefsFileString, null))); 119 | 120 | // Set the thread count 121 | primaryWindow.setThreadCount(prefs.getInt(BitcoinMicroCollider.prefsThreadString, 4)); 122 | } 123 | 124 | 125 | } 126 | 127 | public void startCollider(int threadCount) throws URISyntaxException { 128 | /* 129 | * Start the lottery process 130 | */ 131 | 132 | // Swap the active panel (0 is the main menu and 1 is the working panel) 133 | primaryWindow.setPanel(1); 134 | 135 | // Create the worker threads 136 | startThreads(threadCount); 137 | 138 | // Set a timer to update UI components 139 | guiTimer = new Timer(); 140 | guiUpdateTimer = new GuiUpdateTimer(this); 141 | guiTimer.schedule(guiUpdateTimer, 0, 20); 142 | 143 | // Start tracking time 144 | startTime = System.nanoTime(); 145 | 146 | // Save thread count for future use 147 | this.saveThreadCount(threadCount); 148 | 149 | } 150 | 151 | private void startThreads(int thisCount) { 152 | /* 153 | * Create and start worker threads 154 | */ 155 | 156 | // Thread count is pulled from user input 157 | threadCount = thisCount; 158 | 159 | // Create the thread array 160 | threadArray = new SearchThread[threadCount]; 161 | 162 | // Create specified threads 163 | for (int i = 0; i < threadCount; i++) { 164 | SearchThread thisThread = new SearchThread(this, ScriptType.P2SH, (i + 1) * 1000, i == 0); // Create a Search Thread 165 | // instance 166 | threadArray[i] = thisThread; // Add the instance to the thread array 167 | } 168 | 169 | // Start each of the threads 170 | for (int i = 0; i < threadCount; i++) { 171 | threadArray[i].start(); 172 | } 173 | 174 | // Update the collider status 175 | colliderStatus = Status.RUNNING; 176 | } 177 | 178 | public void updateGuiElements() { 179 | // Update all gui values 180 | 181 | if (colliderStatus == Status.PAUSED) 182 | return; 183 | 184 | this.primaryWindow.setScanAttemptsLabel(totalCheckCount); 185 | 186 | long duration = System.nanoTime() - startTime - this.pausedTimeTotal; 187 | this.primaryWindow.setTimeLabel(duration / 1000000, totalCheckCount); 188 | 189 | this.primaryWindow.setAddressLabels(this.addressLabelArray); 190 | } 191 | 192 | public String[] getAddressLabelArray() { 193 | return this.addressLabelArray; 194 | } 195 | 196 | public void updateThreadCount() { 197 | // Called by threads at start - active threads communicated via UI 198 | 199 | if (activeThreadCount > threadCount) 200 | return; 201 | 202 | activeThreadCount++; 203 | primaryWindow.setThreadsActiveLabel(activeThreadCount); 204 | } 205 | 206 | public void setAddressArray(AddressGroup[][][][] thisAddressArray) { 207 | this.p2pkh_address_array = thisAddressArray; 208 | } 209 | 210 | public void setFileStatus(FileStatus thisStatus) { 211 | this.fileStatus = thisStatus; 212 | } 213 | 214 | public FileStatus getFileStatus() { 215 | return this.fileStatus; 216 | } 217 | 218 | public int[] getLookupIndex(String thisString) { 219 | return getLookupIndex(thisString.toCharArray()); 220 | } 221 | 222 | 223 | public int[] getLookupIndex(char[] charLookupArray) { 224 | // Returns an index to lookup the correct segmented address array 225 | 226 | int firstVal = -1; 227 | int secondVal = -1; 228 | int thirdVal = -1; 229 | int fourthVal = -1; 230 | 231 | 232 | for (int i = 0; i < charArray.length; i++) { 233 | if (charArray[i] == charLookupArray[1]) 234 | firstVal = i; 235 | if (charArray[i] == charLookupArray[2]) 236 | secondVal = i; 237 | if (charArray[i] == charLookupArray[3]) 238 | thirdVal = i; 239 | if (charArray[i] == charLookupArray[4]) 240 | fourthVal = i; 241 | 242 | 243 | 244 | if (firstVal > 0 245 | && secondVal > 0 246 | && thirdVal > 0 247 | && fourthVal > 0 248 | ) break; 249 | } 250 | 251 | 252 | 253 | return new int[] { firstVal, secondVal, thirdVal, fourthVal }; 254 | 255 | } 256 | } 257 | 258 | enum Status { 259 | MAIN_MENU, RUNNING, PAUSED; 260 | } 261 | -------------------------------------------------------------------------------- /src/FileStatus.java: -------------------------------------------------------------------------------- 1 | 2 | public enum FileStatus { 3 | 4 | FILE_LOADED, FILE_LOADING, FILE_NOT_LOADED; 5 | 6 | } 7 | -------------------------------------------------------------------------------- /src/GuiUpdateTimer.java: -------------------------------------------------------------------------------- 1 | import java.util.TimerTask; 2 | 3 | public class GuiUpdateTimer extends TimerTask { 4 | 5 | private BitcoinMicroCollider bitcoinCollider; 6 | 7 | public GuiUpdateTimer(BitcoinMicroCollider thisCollider) { 8 | bitcoinCollider = thisCollider; 9 | } 10 | 11 | 12 | @Override 13 | public void run() { 14 | bitcoinCollider.updateGuiElements(); 15 | 16 | } 17 | 18 | 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/LoadAddresses.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedWriter; 2 | import java.io.File; 3 | import java.io.FileInputStream; 4 | import java.io.FileNotFoundException; 5 | import java.io.FileWriter; 6 | import java.io.IOException; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | import java.util.Scanner; 10 | import java.util.prefs.Preferences; 11 | import org.bitcoinj.core.Address; 12 | import org.bitcoinj.params.MainNetParams; 13 | 14 | public class LoadAddresses extends Thread { 15 | 16 | private int addressLimit = 10000000; 17 | private int reportingIncrement = 50000; 18 | 19 | private BitcoinMicroCollider bitcoinCollider; 20 | private PrimaryWindow primaryWindow; 21 | 22 | private File tempFile; 23 | 24 | private ProcessStatus thisProcessStatus = ProcessStatus.NOT_INITIALIZED; 25 | private Boolean isErrorShown = false; 26 | 27 | @Override 28 | public void run() { 29 | initializeLookupAddresses(); 30 | } 31 | 32 | public LoadAddresses(BitcoinMicroCollider thisCollider, PrimaryWindow thisWindow, File thisFile) { 33 | this.bitcoinCollider = thisCollider; 34 | this.tempFile = thisFile; 35 | this.primaryWindow = thisWindow; 36 | thisProcessStatus = ProcessStatus.INITIALIZED; 37 | 38 | 39 | 40 | } 41 | 42 | private void initializeLookupAddresses() { 43 | /* 44 | * Read the address file and populate an array with the data 45 | */ 46 | 47 | if (this.thisProcessStatus != ProcessStatus.INITIALIZED) 48 | return; 49 | 50 | primaryWindow.setStatusTextPane("LOADING ADDRESS FILE
"); 51 | 52 | String[] addressStringArray; 53 | addressStringArray = readLines(this.tempFile); 54 | 55 | 56 | // Get address arrays for the three address types 57 | bitcoinCollider.setAddressArray(getAddressesFromArray(addressStringArray)); 58 | 59 | //Clear the array 60 | addressStringArray = null; 61 | 62 | long addressCount = this.getTotalAddressCount(); 63 | 64 | primaryWindow.setStatusTextPane("--------------------
"); 65 | primaryWindow.setStatusTextPane("FINISHED LOADING " + String.format("%,d", addressCount) + " ADDRESSES" + "
"); 66 | 67 | bitcoinCollider.setFileStatus(FileStatus.FILE_LOADED); 68 | 69 | // Update the UI with the number of addresses loaded 70 | primaryWindow.setTotalAddressLabel(addressCount); 71 | 72 | // Allow the user to start the collider 73 | primaryWindow.setStartButtonEnabled(true); 74 | primaryWindow.setLoadFileButtonEnabled(true); 75 | 76 | // Save the file path for future use 77 | saveFilePath(this.tempFile); 78 | 79 | // Write a small test file to confirm that any matched addresses can be saved 80 | writeStarterFile(); 81 | 82 | } 83 | 84 | private AddressGroup[][][][] getAddressesFromArray(String[] sourceAddresses) { 85 | 86 | Address thisAddress = null; 87 | ArrayList
addressList = null; 88 | 89 | addressList = new ArrayList
(); 90 | 91 | for (int i = 0; i < sourceAddresses.length; i++) { 92 | 93 | // Skip broken addresses 94 | if (sourceAddresses[i].length() > 35 || sourceAddresses[i].isEmpty()) 95 | continue; 96 | 97 | // Only pull addresses of the specified type (we ignore bech32 since it 98 | // represents a small portion of addresses) 99 | 100 | // Create an address object from the string 101 | try { 102 | thisAddress = Address.fromString(MainNetParams.get(), sourceAddresses[i]); 103 | } catch (org.bitcoinj.core.AddressFormatException ex) { 104 | // ex.printStackTrace(); 105 | if (!this.isErrorShown) { 106 | primaryWindow.showFileErrorMessage(); 107 | primaryWindow.setStatusTextPane("Address format problem on entry " + sourceAddresses[i] + "
"); 108 | } 109 | this.isErrorShown = true; 110 | //System.out.println("bad address on line " + i + ": " + sourceAddresses[i]); 111 | primaryWindow.setStatusTextPane("Address format problem on entry " + sourceAddresses[i] + "
"); 112 | continue; 113 | } 114 | addressList.add(thisAddress); 115 | 116 | //Update the UI 117 | if (i % reportingIncrement == 0) 118 | primaryWindow.setStatusTextPane("Sorting addresses : " + String.format("%,d", i) + "
"); 119 | 120 | } 121 | 122 | Address[] tempAddressArray = new Address[addressList.size()]; 123 | 124 | for (int i=0; i < addressList.size(); i++ ) { 125 | tempAddressArray[i] = addressList.get(i); 126 | 127 | //Update the UI 128 | if (i % reportingIncrement == 0) 129 | primaryWindow.setStatusTextPane("Populating addresses : " + String.format("%,d", i) + "
"); 130 | } 131 | 132 | 133 | return this.createSegmentedArray(tempAddressArray); 134 | } 135 | 136 | private AddressGroup[][][][] createSegmentedArray(Address[] thisAddressArray) { 137 | // Returns a 3D array divided by addresses starting letter 138 | 139 | 140 | int arrayLength = BitcoinMicroCollider.charArray.length; 141 | 142 | AddressGroup[][][][] tempArray = new AddressGroup[arrayLength][arrayLength][arrayLength][arrayLength]; 143 | 144 | 145 | //Create the address groups 146 | for (int a = 0; a < arrayLength; a++) { 147 | for (int b = 0; b < arrayLength; b++) { 148 | for (int c = 0; c < arrayLength; c++) { 149 | for (int d = 0; d < arrayLength; d++) { 150 | tempArray[a][b][c][d] = new AddressGroup(); 151 | 152 | 153 | } 154 | } 155 | } 156 | } 157 | 158 | 159 | //Populate the array with sorted addresses 160 | for (int i = 0; i < thisAddressArray.length; i++) { 161 | IndexHelper thisHelper = new IndexHelper(thisAddressArray[i].toString()); 162 | int[] lookupIndex = thisHelper.getLookupIndex(); 163 | tempArray[lookupIndex[0]] [lookupIndex[1]] [lookupIndex[2]] [lookupIndex[3]].addAddress(thisAddressArray[i]); 164 | 165 | } 166 | 167 | 168 | for (int a = 0; a < arrayLength; a++) { 169 | for (int b = 0; b < arrayLength; b++) { 170 | for (int c = 0; c < arrayLength; c++) { 171 | for (int d = 0; d < arrayLength; d++) { 172 | tempArray[a][b][c][d].finalizeGroup(); 173 | 174 | } 175 | } 176 | } 177 | } 178 | 179 | 180 | return tempArray; 181 | } 182 | 183 | 184 | private String[] readLines(File thisFile) { 185 | /* 186 | * Read lines from a file 187 | */ 188 | 189 | int lineCounter = 0; 190 | 191 | long startTime = System.nanoTime(); 192 | 193 | Scanner thisScanner = null; 194 | 195 | 196 | FileInputStream thisStream = null; 197 | List linesList = null; 198 | try { 199 | 200 | linesList = new ArrayList(); 201 | String line = null; 202 | 203 | thisStream = new FileInputStream(thisFile); 204 | thisScanner = new Scanner(thisStream, "UTF-8"); 205 | 206 | while (thisScanner.hasNextLine() && lineCounter < addressLimit) { 207 | 208 | line = thisScanner.nextLine(); 209 | 210 | // only add addresses starting with 1 211 | if (line.charAt(0) == '1') { 212 | linesList.add(line); 213 | lineCounter++; 214 | //System.out.println("Read: " + line); 215 | //System.out.println("Added a Line " + linesList.size()); 216 | if (lineCounter % reportingIncrement == 0) 217 | primaryWindow.setStatusTextPane("Reading addresses : " + String.format("%,d", lineCounter) + "
"); 218 | 219 | } 220 | } 221 | 222 | } catch (FileNotFoundException e) { 223 | primaryWindow.showFileErrorMessage(); 224 | e.printStackTrace(); 225 | 226 | } finally { 227 | if (thisStream != null) 228 | try { 229 | thisStream.close(); 230 | } catch (IOException e) { 231 | e.printStackTrace(); 232 | } 233 | 234 | if (thisStream != null) 235 | try { 236 | thisStream.close(); 237 | } catch (IOException e) { 238 | e.printStackTrace(); 239 | } 240 | } 241 | 242 | long endTime = System.nanoTime(); 243 | 244 | primaryWindow.setStatusTextPane("File text read time " + ((endTime - startTime)/10000000) + "ms"); 245 | primaryWindow.setStatusTextPane("Loading addresses into memory...
"); 246 | 247 | 248 | String[] returnArray = new String[linesList.size()]; 249 | 250 | for (int i=0; i < linesList.size(); i++) { 251 | returnArray[i] =linesList.get(i); 252 | 253 | if (i % reportingIncrement == 0) 254 | primaryWindow.setStatusTextPane("Converting addresses : " + String.format("%,d", i) + "
"); 255 | 256 | } 257 | 258 | return returnArray; 259 | 260 | 261 | 262 | //return linesList.toArray(new String[linesList.size()]); 263 | } 264 | 265 | private long getTotalAddressCount() { 266 | // Counts the number of addresses across all arrays 267 | 268 | AddressGroup[][][][] thisArray = this.bitcoinCollider.getAddressArray(); 269 | 270 | long totalCount = 0; 271 | 272 | for (int a = 0; a < thisArray.length; a++) 273 | for (int b = 0; b < thisArray[a].length; b++) { 274 | for (int c = 0; c < thisArray[a][b].length; c++) 275 | for (int d = 0; d < thisArray[a][b][c].length; d++) { 276 | totalCount += thisArray[a][b][c][d].getAddressArray().length; 277 | } 278 | } 279 | 280 | 281 | return totalCount; 282 | } 283 | 284 | private void saveFilePath(File thisFile) { 285 | // Saves the file path for future use 286 | String filePathString = thisFile.getAbsolutePath(); 287 | 288 | Preferences prefs = Preferences.userRoot().node(BitcoinMicroCollider.prefsNode); 289 | prefs.put(BitcoinMicroCollider.prefsFileString, filePathString); 290 | } 291 | 292 | public static Boolean isFileAvailable(String filePath) { 293 | // Checks to see if a last address file is available to load 294 | 295 | if (filePath == null) 296 | return false; 297 | 298 | File tempFile = new File(filePath); 299 | return tempFile.exists(); 300 | } 301 | 302 | public void writeStarterFile() { 303 | // Writes a blank file to confirm write process functions as intended 304 | String thisString = "Ignore this file"; 305 | FileWriter thisFile; 306 | try { 307 | thisFile = new FileWriter("testFilePleaseIgnore.txt"); 308 | BufferedWriter writer = new BufferedWriter(thisFile); 309 | writer.write(thisString); 310 | writer.close(); 311 | } catch (IOException e) { 312 | //Exit 313 | primaryWindow.showFileErrorMessage(); 314 | } 315 | } 316 | 317 | enum ProcessStatus { 318 | NOT_INITIALIZED, INITIALIZING, INITIALIZED; 319 | } 320 | 321 | class IndexHelper { 322 | 323 | char[] charArray; 324 | 325 | public IndexHelper(String thisString) { 326 | charArray = thisString.toCharArray(); 327 | 328 | } 329 | 330 | public int[] getLookupIndex() { 331 | return bitcoinCollider.getLookupIndex(charArray); 332 | } 333 | 334 | } 335 | 336 | 337 | } 338 | -------------------------------------------------------------------------------- /src/PrimaryWindow.java: -------------------------------------------------------------------------------- 1 | import javax.swing.JFrame; 2 | import javax.swing.JPanel; 3 | import javax.swing.JLabel; 4 | import javax.swing.JOptionPane; 5 | 6 | import java.awt.Font; 7 | import java.awt.Insets; 8 | import java.awt.event.ActionEvent; 9 | import java.awt.event.ActionListener; 10 | import java.io.File; 11 | import java.io.IOException; 12 | import java.net.URISyntaxException; 13 | 14 | import javax.swing.SwingConstants; 15 | import javax.swing.UIManager; 16 | import javax.swing.UIManager.LookAndFeelInfo; 17 | import javax.swing.UnsupportedLookAndFeelException; 18 | import javax.swing.filechooser.FileNameExtensionFilter; 19 | import javax.swing.text.BadLocationException; 20 | import javax.swing.text.DefaultEditorKit; 21 | import javax.swing.text.Document; 22 | import javax.swing.text.html.HTMLDocument; 23 | import javax.swing.text.html.HTMLEditorKit; 24 | import javax.swing.BorderFactory; 25 | import javax.swing.JButton; 26 | import javax.swing.JTextField; 27 | import javax.swing.SpinnerModel; 28 | import javax.swing.SpinnerNumberModel; 29 | import java.awt.CardLayout; 30 | import javax.swing.JTextArea; 31 | import javax.swing.JSeparator; 32 | import javax.swing.JSpinner; 33 | import javax.swing.JProgressBar; 34 | import javax.swing.JScrollPane; 35 | 36 | import java.awt.Color; 37 | import java.awt.Dimension; 38 | 39 | import javax.swing.JFileChooser; 40 | import java.awt.SystemColor; 41 | import javax.swing.JTextPane; 42 | 43 | public class PrimaryWindow { 44 | 45 | private JFrame mbcFrame; 46 | private JTextField fileAddressField; 47 | private JButton startButton; 48 | private BitcoinMicroCollider microCollider; 49 | private JPanel mainPanel; 50 | private JPanel workingPanel; 51 | private JButton pauseButton; 52 | private JProgressBar progressBar; 53 | private JSpinner threadSpinner; 54 | private JButton loadFileButton; 55 | private JTextPane statusTextPane; 56 | 57 | private JLabel totalAttemptsLabel; 58 | private JLabel attemptsPerSecondLabel; 59 | private JLabel totalAddressLabel; 60 | private JLabel successLabel; 61 | private JLabel timeLabel; 62 | private JLabel threadCountLabel; 63 | private JLabel matchedKeyLabel; 64 | private JLabel matchedAddressLabel; 65 | private JScrollPane scrollPane; 66 | private JLabel[] addressLabelArray = new JLabel[10]; 67 | 68 | 69 | private Color color_1; 70 | private Color color_2; 71 | private Color color_3; 72 | private Color color_4; 73 | private Color color_5; 74 | private Color exitColor; 75 | private Color acceptColor; 76 | private Color pauseColor; 77 | private Color disabledColor; 78 | 79 | 80 | 81 | /* 82 | * Create the application. 83 | */ 84 | public PrimaryWindow(BitcoinMicroCollider thisCollider) { 85 | microCollider = thisCollider; 86 | initialize(); 87 | } 88 | 89 | public void setWindowEnabled(Boolean thisBool) { 90 | //this.mbcFrame.setResizable(false); 91 | this.mbcFrame.setVisible(thisBool); 92 | } 93 | 94 | /** 95 | * Initialize the contents of the frame. 96 | */ 97 | private void initialize() { 98 | 99 | UIManager.put("ProgressBar[Enabled+Finished].foregroundPainter", Color.black); 100 | 101 | try { 102 | for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { 103 | if ("Nimbus".equals(info.getName())) { 104 | UIManager.setLookAndFeel(info.getClassName()); 105 | break; 106 | } 107 | } 108 | } catch (Exception e) { 109 | try { 110 | UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); 111 | } catch (ClassNotFoundException | InstantiationException | IllegalAccessException 112 | | UnsupportedLookAndFeelException e1) { 113 | e1.printStackTrace(); 114 | } 115 | } 116 | 117 | color_1 = Color.decode("#4A6491"); 118 | color_2 = Color.decode("#30395C"); 119 | color_3 = Color.decode("#4A6491"); 120 | color_4 = Color.decode("#EC7263"); 121 | color_5 = Color.decode("#D0E4F2"); 122 | exitColor = Color.decode("#C1292E"); 123 | acceptColor = Color.decode("#4CB963"); 124 | pauseColor = Color.decode("#F5F749"); 125 | disabledColor = Color.decode("#545454"); 126 | 127 | UIManager.getLookAndFeelDefaults().put("nimbusOrange", color_3); 128 | 129 | 130 | 131 | mbcFrame = new JFrame(); 132 | mbcFrame.setTitle("Bitcoin Micro Collider"); 133 | mbcFrame.setBounds(100, 100, 450, 700); 134 | mbcFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 135 | mbcFrame.getContentPane().setLayout(null); 136 | mbcFrame.setBackground(color_1); 137 | 138 | JPanel panel = new JPanel(); 139 | panel.setBounds(0, 0, 434, 661); 140 | mbcFrame.getContentPane().add(panel); 141 | panel.setLayout(new CardLayout(0, 0)); 142 | 143 | mainPanel = new JPanel(); 144 | mainPanel.setBackground(color_1); 145 | panel.add(mainPanel, "name_432466542248400"); 146 | mainPanel.setLayout(null); 147 | 148 | JLabel mcLabel = new JLabel("Bitcoin Micro Collider!"); 149 | mcLabel.setBounds(0, 0, panel.getWidth(), 86); 150 | mainPanel.add(mcLabel); 151 | mcLabel.setHorizontalAlignment(SwingConstants.CENTER); 152 | mcLabel.setFont(new Font("Tahoma", Font.PLAIN, 36)); 153 | mcLabel.setForeground(color_5); 154 | mcLabel.setBackground(color_2); 155 | mcLabel.setBorder(BorderFactory.createEmptyBorder()); 156 | mcLabel.setOpaque(true); 157 | 158 | loadFileButton = new JButton("Choose Address File"); 159 | loadFileButton.setBounds(19, 455, 211, 33); 160 | loadFileButton.addActionListener(new FileBrowserListener()); 161 | loadFileButton.setForeground(color_2); 162 | mainPanel.add(loadFileButton); 163 | loadFileButton.setFont(new Font("Tahoma", Font.PLAIN, 18)); 164 | 165 | fileAddressField = new JTextField(); 166 | fileAddressField.setBounds(19, 419, 396, 25); 167 | mainPanel.add(fileAddressField); 168 | fileAddressField.setColumns(10); 169 | 170 | JLabel threadsLabel = new JLabel("Collider Threads"); 171 | threadsLabel.setBounds(10, 331, 414, 33); 172 | mainPanel.add(threadsLabel); 173 | threadsLabel.setHorizontalAlignment(SwingConstants.CENTER); 174 | threadsLabel.setFont(new Font("Tahoma", Font.PLAIN, 24)); 175 | threadsLabel.setForeground(color_5); 176 | 177 | startButton = new JButton("Start Collider!"); 178 | startButton.setBounds(10, 499, 300, 65); 179 | mainPanel.add(startButton); 180 | startButton.setFont(new Font("Tahoma", Font.PLAIN, 32)); 181 | startButton.setForeground(color_2); 182 | this.setStartButtonEnabled(false); 183 | this.setLoadFileButtonEnabled(true); 184 | 185 | JButton btnExit = new JButton("Exit"); 186 | btnExit.setBounds(320, 499, 104, 65); 187 | btnExit.setBackground(exitColor); 188 | btnExit.setForeground(color_2); 189 | mainPanel.add(btnExit); 190 | btnExit.setFont(new Font("Tahoma", Font.PLAIN, 24)); 191 | 192 | JTextArea mcTextArea = new JTextArea(); 193 | mcTextArea.setTabSize(0); 194 | mcTextArea.setFont(new Font("Arial", Font.PLAIN, 14)); 195 | mcTextArea.setForeground(color_5); 196 | mcTextArea.setBackground(color_3); 197 | mcTextArea.setEditable(false); 198 | mcTextArea.setWrapStyleWord(true); 199 | mcTextArea.setLineWrap(true); 200 | mcTextArea.setBorder(BorderFactory.createEmptyBorder(25,25,25,25)); 201 | mcTextArea.setText( 202 | "The Bitcoin Micro Collider 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 collider"); 203 | mcTextArea.setBounds(0, 84, panel.getWidth(), 221); 204 | mainPanel.add(mcTextArea); 205 | 206 | JSeparator separator = new JSeparator(); 207 | separator.setBounds(22, 321, 390, 2); 208 | mainPanel.add(separator); 209 | 210 | threadSpinner = new JSpinner(); 211 | threadSpinner.setFont(new Font("Tahoma", Font.PLAIN, 22)); 212 | threadSpinner.setBounds(165, 373, 104, 35); 213 | mainPanel.add(threadSpinner); 214 | SpinnerModel spinnerModel = new SpinnerNumberModel(4, 1, 64, 1); 215 | threadSpinner.setModel(spinnerModel); 216 | 217 | ((JSpinner.DefaultEditor) threadSpinner.getEditor()).getTextField().setEditable(false); 218 | 219 | btnExit.addActionListener(new ExitListener()); 220 | startButton.addActionListener(new StartListener()); 221 | 222 | statusTextPane = new JTextPane(); 223 | statusTextPane.setForeground(Color.BLUE); 224 | statusTextPane.setBackground(Color.WHITE); 225 | statusTextPane.setContentType("text/html"); 226 | statusTextPane.setEditable(false); 227 | //statusTextPane.setBounds(10, 585, 151, 65); 228 | statusTextPane.setAutoscrolls(true); 229 | mainPanel.add(statusTextPane); 230 | 231 | scrollPane = new JScrollPane(statusTextPane); 232 | scrollPane.setBounds(10, 570, 415, 80); 233 | scrollPane.setAutoscrolls(true); 234 | mainPanel.add(scrollPane); 235 | 236 | 237 | workingPanel = new JPanel(); 238 | workingPanel.setBackground(color_1); 239 | panel.add(workingPanel, "name_432575102303500"); 240 | workingPanel.setLayout(null); 241 | 242 | JLabel mcLabel_1 = new JLabel("Bitcoin Micro Collider!"); 243 | mcLabel_1.setBounds(0, 0, panel.getWidth(), 51); 244 | mcLabel_1.setFont(new Font("Tahoma", Font.PLAIN, 34)); 245 | mcLabel_1.setHorizontalAlignment(SwingConstants.CENTER); 246 | mcLabel_1.setOpaque(true); 247 | mcLabel_1.setForeground(color_5); 248 | mcLabel_1.setBackground(color_2); 249 | mcLabel_1.setBorder(BorderFactory.createEmptyBorder()); 250 | workingPanel.add(mcLabel_1); 251 | 252 | JLabel label_1 = new JLabel("Collider Attempts"); 253 | label_1.setBounds(10, 65, 414, 51); 254 | label_1.setHorizontalAlignment(SwingConstants.CENTER); 255 | label_1.setFont(new Font("Tahoma", Font.PLAIN, 32)); 256 | label_1.setForeground(color_5); 257 | workingPanel.add(label_1); 258 | 259 | totalAttemptsLabel = new JLabel("0"); 260 | totalAttemptsLabel.setBounds(10, 110, 414, 34); 261 | totalAttemptsLabel.setHorizontalAlignment(SwingConstants.CENTER); 262 | totalAttemptsLabel.setFont(new Font("Tahoma", Font.PLAIN, 32)); 263 | totalAttemptsLabel.setForeground(color_5); 264 | workingPanel.add(totalAttemptsLabel); 265 | 266 | JLabel label_3 = new JLabel("Time Elapsed"); 267 | label_3.setBounds(152, 224, 130, 27); 268 | label_3.setHorizontalAlignment(SwingConstants.CENTER); 269 | label_3.setFont(new Font("Tahoma", Font.PLAIN, 22)); 270 | label_3.setForeground(color_5); 271 | workingPanel.add(label_3); 272 | 273 | timeLabel = new JLabel("0"); 274 | timeLabel.setBounds(128, 248, 177, 29); 275 | timeLabel.setHorizontalAlignment(SwingConstants.CENTER); 276 | timeLabel.setFont(new Font("Tahoma", Font.PLAIN, 24)); 277 | timeLabel.setForeground(color_5); 278 | workingPanel.add(timeLabel); 279 | 280 | pauseButton = new JButton("Pause Collider"); 281 | pauseButton.setBounds(10, 601, 284, 50); 282 | pauseButton.setFont(new Font("Tahoma", Font.PLAIN, 32)); 283 | pauseButton.addActionListener(new PauseListener()); 284 | pauseButton.setBackground(pauseColor); 285 | workingPanel.add(pauseButton); 286 | 287 | JButton exitButton = new JButton("Exit"); 288 | exitButton.setBounds(312, 603, 112, 50); 289 | exitButton.setFont(new Font("Tahoma", Font.PLAIN, 32)); 290 | exitButton.setBackground(exitColor); 291 | exitButton.addActionListener(new ExitListener()); 292 | workingPanel.add(exitButton); 293 | 294 | progressBar = new JProgressBar(); 295 | progressBar.setIndeterminate(true); 296 | progressBar.setBounds(18, 164, 398, 34); 297 | workingPanel.add(progressBar); 298 | 299 | 300 | JLabel lblAverageSpeedper = new JLabel("Attempts per second"); 301 | lblAverageSpeedper.setHorizontalAlignment(SwingConstants.CENTER); 302 | lblAverageSpeedper.setFont(new Font("Tahoma", Font.PLAIN, 18)); 303 | lblAverageSpeedper.setBounds(10, 282, 414, 27); 304 | lblAverageSpeedper.setForeground(color_5); 305 | workingPanel.add(lblAverageSpeedper); 306 | 307 | attemptsPerSecondLabel = new JLabel("0"); 308 | attemptsPerSecondLabel.setHorizontalAlignment(SwingConstants.CENTER); 309 | attemptsPerSecondLabel.setFont(new Font("Tahoma", Font.PLAIN, 24)); 310 | attemptsPerSecondLabel.setBounds(128, 306, 177, 29); 311 | attemptsPerSecondLabel.setForeground(color_5); 312 | workingPanel.add(attemptsPerSecondLabel); 313 | 314 | JLabel lblAnyMatchesThis = new JLabel("Any matches this session?"); 315 | lblAnyMatchesThis.setHorizontalAlignment(SwingConstants.CENTER); 316 | lblAnyMatchesThis.setFont(new Font("Tahoma", Font.PLAIN, 22)); 317 | lblAnyMatchesThis.setBounds(10, 445, 414, 27); 318 | lblAnyMatchesThis.setForeground(color_5); 319 | workingPanel.add(lblAnyMatchesThis); 320 | 321 | successLabel = new JLabel("NO"); 322 | successLabel.setForeground(Color.RED); 323 | successLabel.setHorizontalAlignment(SwingConstants.CENTER); 324 | successLabel.setFont(new Font("Tahoma", Font.PLAIN, 36)); 325 | successLabel.setBounds(119, 474, 195, 47); 326 | workingPanel.add(successLabel); 327 | 328 | JSeparator separator_1 = new JSeparator(); 329 | separator_1.setBounds(18, 582, 398, 8); 330 | workingPanel.add(separator_1); 331 | 332 | totalAddressLabel = new JLabel("0"); 333 | totalAddressLabel.setHorizontalAlignment(SwingConstants.LEFT); 334 | totalAddressLabel.setFont(new Font("Tahoma", Font.PLAIN, 12)); 335 | totalAddressLabel.setBounds(138, 198, 122, 15); 336 | totalAddressLabel.setForeground(color_5); 337 | workingPanel.add(totalAddressLabel); 338 | 339 | JLabel addressTotal = new JLabel("Target Addresses:"); 340 | addressTotal.setHorizontalAlignment(SwingConstants.RIGHT); 341 | addressTotal.setFont(new Font("Tahoma", Font.PLAIN, 12)); 342 | addressTotal.setBounds(6, 198, 122, 15); 343 | addressTotal.setForeground(color_5); 344 | workingPanel.add(addressTotal); 345 | 346 | threadCountLabel = new JLabel("0"); 347 | threadCountLabel.setHorizontalAlignment(SwingConstants.LEFT); 348 | threadCountLabel.setFont(new Font("Tahoma", Font.PLAIN, 12)); 349 | threadCountLabel.setBounds(360, 198, 57, 15); 350 | threadCountLabel.setForeground(color_5); 351 | workingPanel.add(threadCountLabel); 352 | 353 | JLabel lblThreadsActive = new JLabel("Threads Active:"); 354 | lblThreadsActive.setHorizontalAlignment(SwingConstants.RIGHT); 355 | lblThreadsActive.setFont(new Font("Tahoma", Font.PLAIN, 12)); 356 | lblThreadsActive.setBounds(259, 198, 95, 15); 357 | lblThreadsActive.setForeground(color_5); 358 | workingPanel.add(lblThreadsActive); 359 | 360 | JLabel matchedAddress = new JLabel("Matched Public Address:"); 361 | matchedAddress.setHorizontalAlignment(SwingConstants.LEFT); 362 | matchedAddress.setBounds(10, 506, 137, 15); 363 | matchedAddress.setForeground(color_5); 364 | workingPanel.add(matchedAddress); 365 | 366 | JLabel matchedKey = new JLabel("Matched Private Key:"); 367 | matchedKey.setHorizontalAlignment(SwingConstants.LEFT); 368 | matchedKey.setBounds(10, 544, 152, 15); 369 | matchedKey.setForeground(color_5); 370 | workingPanel.add(matchedKey); 371 | 372 | matchedAddressLabel = new JLabel("Address"); 373 | matchedAddressLabel.setForeground(Color.BLACK); 374 | matchedAddressLabel.setFont(new Font("Tahoma", Font.PLAIN, 11)); 375 | matchedAddressLabel.setHorizontalAlignment(SwingConstants.LEFT); 376 | matchedAddressLabel.setBounds(10, 521, 414, 21); 377 | matchedAddressLabel.setText("none"); 378 | matchedAddressLabel.setForeground(color_5); 379 | workingPanel.add(matchedAddressLabel); 380 | 381 | matchedKeyLabel = new JLabel("Address"); 382 | matchedKeyLabel.setFont(new Font("Tahoma", Font.PLAIN, 11)); 383 | matchedKeyLabel.setHorizontalAlignment(SwingConstants.LEFT); 384 | matchedKeyLabel.setBounds(10, 557, 414, 21); 385 | matchedKeyLabel.setText("none"); 386 | matchedKeyLabel.setForeground(color_5); 387 | workingPanel.add(matchedKeyLabel); 388 | 389 | JLabel addLabel_1 = new JLabel("1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2"); 390 | addressLabelArray[0] = addLabel_1; 391 | addLabel_1.setFont(new Font("Tahoma", Font.PLAIN, 10)); 392 | addLabel_1.setForeground(Color.WHITE); 393 | addLabel_1.setBounds(10, 342, 209, 15); 394 | workingPanel.add(addLabel_1); 395 | 396 | JLabel addLabel_2 = new JLabel("1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2"); 397 | addressLabelArray[1] = addLabel_2; 398 | addLabel_2.setForeground(Color.WHITE); 399 | addLabel_2.setFont(new Font("Tahoma", Font.PLAIN, 10)); 400 | addLabel_2.setBounds(10, 365, 209, 15); 401 | workingPanel.add(addLabel_2); 402 | 403 | 404 | JLabel addLabel_3 = new JLabel("1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2"); 405 | addressLabelArray[2] = addLabel_3; 406 | addLabel_3.setForeground(Color.WHITE); 407 | addLabel_3.setFont(new Font("Tahoma", Font.PLAIN, 10)); 408 | addLabel_3.setBounds(10, 384, 209, 15); 409 | workingPanel.add(addLabel_3); 410 | 411 | JLabel addLabel_4 = new JLabel("1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2"); 412 | addressLabelArray[3] = addLabel_4; 413 | addLabel_4.setForeground(Color.WHITE); 414 | addLabel_4.setFont(new Font("Tahoma", Font.PLAIN, 10)); 415 | addLabel_4.setBounds(10, 405, 209, 15); 416 | workingPanel.add(addLabel_4); 417 | 418 | JLabel addLabel_5 = new JLabel("1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2"); 419 | addressLabelArray[4] = addLabel_5; 420 | addLabel_5.setForeground(Color.WHITE); 421 | addLabel_5.setFont(new Font("Tahoma", Font.PLAIN, 10)); 422 | addLabel_5.setBounds(10, 426, 209, 15); 423 | workingPanel.add(addLabel_5); 424 | 425 | JLabel addLabel_6 = new JLabel("1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2"); 426 | addressLabelArray[5] = addLabel_6; 427 | addLabel_6.setForeground(Color.WHITE); 428 | addLabel_6.setFont(new Font("Tahoma", Font.PLAIN, 10)); 429 | addLabel_6.setBounds(225, 342, 209, 15); 430 | workingPanel.add(addLabel_6); 431 | 432 | JLabel addLabel_7 = new JLabel("1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2"); 433 | addressLabelArray[6] = addLabel_7; 434 | addLabel_7.setForeground(Color.WHITE); 435 | addLabel_7.setFont(new Font("Tahoma", Font.PLAIN, 10)); 436 | addLabel_7.setBounds(225, 365, 209, 15); 437 | workingPanel.add(addLabel_7); 438 | 439 | JLabel addLabel_8 = new JLabel("1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2"); 440 | addressLabelArray[7] = addLabel_8; 441 | addLabel_8.setForeground(Color.WHITE); 442 | addLabel_8.setFont(new Font("Tahoma", Font.PLAIN, 10)); 443 | addLabel_8.setBounds(225, 384, 209, 15); 444 | workingPanel.add(addLabel_8); 445 | 446 | JLabel addLabel_9 = new JLabel("1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2"); 447 | addressLabelArray[8] = addLabel_9; 448 | addLabel_9.setForeground(Color.WHITE); 449 | addLabel_9.setFont(new Font("Tahoma", Font.PLAIN, 10)); 450 | addLabel_9.setBounds(225, 405, 209, 15); 451 | workingPanel.add(addLabel_9); 452 | 453 | JLabel addLabel_10 = new JLabel("1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2"); 454 | addressLabelArray[9] = addLabel_10; 455 | addLabel_10.setForeground(Color.WHITE); 456 | addLabel_10.setFont(new Font("Tahoma", Font.PLAIN, 10)); 457 | addLabel_10.setBounds(225, 426, 209, 15); 458 | workingPanel.add(addLabel_10); 459 | 460 | } 461 | 462 | public void setPanel(int panelIndex) { 463 | switch (panelIndex) { 464 | case 0: 465 | mainPanel.setVisible(true); 466 | workingPanel.setVisible(false); 467 | break; 468 | case 1: 469 | mainPanel.setVisible(false); 470 | workingPanel.setVisible(true); 471 | break; 472 | } 473 | } 474 | 475 | public void setScanAttemptsLabel(long thisLong) { 476 | this.totalAttemptsLabel.setText(String.format("%,d", thisLong)); 477 | } 478 | 479 | public void setTotalAddressLabel(long thisLong) { 480 | this.totalAddressLabel.setText(String.format("%,d", thisLong)); 481 | } 482 | 483 | public void setSuccessLabel(Boolean thisBool, String matchedAddress, String matchedPrivateKey) { 484 | if (thisBool) { 485 | this.successLabel.setText("YES!!"); 486 | this.successLabel.setForeground(Color.GREEN); 487 | 488 | this.matchedAddressLabel.setText(matchedAddress); 489 | this.matchedKeyLabel.setText(matchedPrivateKey); 490 | } 491 | } 492 | 493 | public void setThreadsActiveLabel(int thisThreadCount) { 494 | this.threadCountLabel.setText(String.format("%,d", thisThreadCount)); 495 | } 496 | 497 | public void setLoadFileButtonEnabled(Boolean thisBool) { 498 | FileStatus thisStatus = this.microCollider.getFileStatus(); 499 | 500 | if (thisBool) { 501 | loadFileButton.setText("Choose Address File"); 502 | } else { 503 | if (thisStatus == FileStatus.FILE_LOADING) 504 | loadFileButton.setText("Loading..."); 505 | else if (thisStatus == FileStatus.FILE_NOT_LOADED) 506 | loadFileButton.setText("Choose Address File"); 507 | } 508 | 509 | loadFileButton.setEnabled(thisBool); 510 | } 511 | 512 | public void setStartButtonEnabled(Boolean thisBool) { 513 | FileStatus thisStatus = this.microCollider.getFileStatus(); 514 | 515 | if (thisBool) { 516 | startButton.setText("Start Collider"); 517 | startButton.setBackground(this.acceptColor); 518 | } else { 519 | if (thisStatus == FileStatus.FILE_LOADING) 520 | startButton.setText("Loading..."); 521 | else if (thisStatus == FileStatus.FILE_NOT_LOADED) 522 | startButton.setText("Waiting on file"); 523 | startButton.setBackground(disabledColor); 524 | } 525 | 526 | startButton.setEnabled(thisBool); 527 | 528 | } 529 | 530 | public void setAddressFile(File thisFile) { 531 | 532 | this.microCollider.setFileStatus(FileStatus.FILE_LOADING); 533 | this.setStartButtonEnabled(false); 534 | this.setLoadFileButtonEnabled(false); 535 | fileAddressField.setText(thisFile.getPath()); 536 | 537 | //Set the new address file 538 | LoadAddresses loader = new LoadAddresses(this.microCollider, this, thisFile); 539 | loader.start(); 540 | //loader.run(); 541 | } 542 | 543 | public void setThreadCount(int thisInt) { 544 | threadSpinner.setValue(Integer.valueOf(thisInt)); 545 | } 546 | 547 | public void setTimeLabel(long duration, long addressesChecked) { 548 | 549 | long second = (duration / 1000) % 60; 550 | long minute = (duration / (1000 * 60)) % 60; 551 | long hour = (duration / (1000 * 60 * 60)); 552 | 553 | String time = String.format("%04d:%02d:%02d", hour, minute, second); 554 | this.timeLabel.setText(String.format(time)); 555 | 556 | // Set attempts per second 557 | duration /= 1000; 558 | if (duration <= 0) 559 | return; 560 | attemptsPerSecondLabel.setText(String.format("%,d", addressesChecked / duration)); 561 | } 562 | 563 | public void showFileErrorMessage() { 564 | JOptionPane.showMessageDialog(mbcFrame, "File read/write failed."); 565 | } 566 | 567 | public void showAddressFormatMessage() { 568 | JOptionPane.showMessageDialog(mbcFrame, "One or more addresses are have incorrect formats"); 569 | } 570 | 571 | public void setStatusTextPane(String thisString) { 572 | 573 | HTMLDocument doc = (HTMLDocument) statusTextPane.getDocument(); 574 | HTMLEditorKit editorKit = (HTMLEditorKit)statusTextPane.getEditorKit(); 575 | try { 576 | editorKit.insertHTML(doc, doc.getLength(), thisString, 0, 0, null); 577 | statusTextPane.setCaretPosition(doc.getLength()); 578 | } catch (BadLocationException | IOException e) { 579 | e.printStackTrace(); 580 | } 581 | } 582 | 583 | public class PauseListener implements ActionListener { 584 | 585 | Boolean isPaused = false; 586 | 587 | @Override 588 | public void actionPerformed(ActionEvent arg0) { 589 | 590 | if (isPaused) { 591 | isPaused = false; 592 | pauseButton.setBackground(pauseColor); 593 | pauseButton.setText("Pause Collider"); 594 | progressBar.setVisible(true); 595 | microCollider.resumeAllThreads(); 596 | } else { 597 | isPaused = true; 598 | pauseButton.setBackground(acceptColor); 599 | pauseButton.setText("Resume Collider"); 600 | progressBar.setVisible(false); 601 | microCollider.pauseAllThreads(); 602 | } 603 | } 604 | } 605 | 606 | public void setAddressLabels(String[] thisStringArray) { 607 | //Set text for each of the address labels 608 | 609 | for (int i=0; i < this.addressLabelArray.length; i++) { 610 | this.addressLabelArray[i].setText(thisStringArray[i]); 611 | } 612 | } 613 | 614 | public class StartListener implements ActionListener { 615 | @Override 616 | public void actionPerformed(ActionEvent arg0) { 617 | try { 618 | int cpuThreads = (Integer) threadSpinner.getValue(); 619 | startButton.setText("Loading..."); 620 | microCollider.startCollider(cpuThreads); 621 | } catch (URISyntaxException e) { 622 | e.printStackTrace(); 623 | } 624 | } 625 | } 626 | 627 | public class FileBrowserListener implements ActionListener { 628 | @Override 629 | public void actionPerformed(ActionEvent arg0) { 630 | JFileChooser fileChooser = new JFileChooser(); 631 | FileNameExtensionFilter filter = new FileNameExtensionFilter("TEXT FILES", "txt", "text"); 632 | fileChooser.setFileFilter(filter); 633 | 634 | int returnVal = fileChooser.showOpenDialog(mbcFrame); 635 | 636 | if (returnVal == JFileChooser.APPROVE_OPTION) { 637 | File thisFile = fileChooser.getSelectedFile(); 638 | setAddressFile(thisFile); 639 | } 640 | } 641 | } 642 | 643 | public class ExitListener implements ActionListener { 644 | @Override 645 | public void actionPerformed(ActionEvent arg0) { 646 | System.exit(0); 647 | } 648 | } 649 | 650 | } 651 | -------------------------------------------------------------------------------- /src/SearchThread.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedWriter; 2 | import java.io.FileWriter; 3 | import java.io.IOException; 4 | import java.net.URISyntaxException; 5 | import java.util.Random; 6 | 7 | import org.bitcoinj.core.Address; 8 | import org.bitcoinj.core.ECKey; 9 | import org.bitcoinj.params.MainNetParams; 10 | import org.bitcoinj.script.Script.ScriptType; 11 | 12 | public class SearchThread extends Thread { 13 | 14 | private BitcoinMicroCollider bitcoinCollider; 15 | private AddressGroup[][][][] addressArray; 16 | private String[] labelArray; //For gui 17 | private int thisThreadAddressCount = 0; 18 | private int labelCounter = 0; 19 | 20 | private Boolean isInterrupted = false; 21 | private int startDelay = 0; 22 | private Boolean isStringLabelProvider = false; //Does this thread populate the gui labels 23 | private String thisString; 24 | 25 | 26 | @Override 27 | public void run() { 28 | try { 29 | try { 30 | if (startDelay > 0) 31 | Thread.sleep(startDelay); 32 | } catch (InterruptedException e) { 33 | e.printStackTrace(); 34 | } 35 | 36 | // If the start delay is greater than zero assume this is the initial run (ie 37 | // not a resumed event) 38 | if (startDelay > 0 && !isInterrupted) { 39 | // Update the active thread count 40 | bitcoinCollider.updateThreadCount(); 41 | // Start checking addresses 42 | checkAddresses(); 43 | } 44 | 45 | } catch (IOException | URISyntaxException e) { 46 | e.printStackTrace(); 47 | } 48 | } 49 | 50 | public SearchThread(BitcoinMicroCollider thisCollider, ScriptType thisType, int thisStartDelay, Boolean isGuiProvider) { 51 | bitcoinCollider = thisCollider; 52 | addressArray = thisCollider.getAddressArray(); 53 | this.isStringLabelProvider = isGuiProvider; 54 | startDelay = thisStartDelay; 55 | 56 | if (this.isStringLabelProvider) 57 | labelArray = bitcoinCollider.getAddressLabelArray(); 58 | 59 | } 60 | 61 | private void checkAddresses() throws IOException, URISyntaxException { 62 | 63 | ECKey thisKey; 64 | Address pubAddress; 65 | 66 | while (!isInterrupted) { 67 | // Generate a random address/key combination 68 | thisKey = new ECKey(); 69 | // Create an address object based on the address format 70 | pubAddress = Address.fromKey(MainNetParams.get(), thisKey, ScriptType.P2PKH); 71 | 72 | // Get the correct address group 73 | if (evaluateAddress(pubAddress, this.getAddressArray(pubAddress))) 74 | // If an address miraculously matches something from the address list 75 | handleMatch(thisKey); 76 | } 77 | } 78 | 79 | private Boolean evaluateAddress(Address thisAddress, AddressGroup thisGroup) { 80 | 81 | bitcoinCollider.logAddressCheck(); 82 | thisThreadAddressCount++; 83 | if (this.isStringLabelProvider) 84 | this.updateGuiElements(thisAddress); 85 | 86 | 87 | if (thisGroup.getAddressArray().length <= 0) { 88 | //Debug 89 | //System.out.println("skipping prefix value not indexed"); 90 | return false; 91 | } 92 | 93 | 94 | //Debugging 95 | //System.out.println("----- testing against addresses count of : " + thisGroup.getAddressArray().length); 96 | 97 | for (int i = 0; i < thisGroup.getAddressArray().length; i++) { 98 | 99 | //Debugging 100 | //String string1 = thisAddress.toString(); 101 | //String string2 = thisGroup.getAddressArray()[i].toString(); 102 | //System.out.println("comparing " + string1 + " to " + string2); 103 | 104 | if (thisAddress.equals(thisGroup.getAddressArray()[i])) 105 | return true; 106 | 107 | } 108 | return false; 109 | } 110 | 111 | private AddressGroup getAddressArray(Address thisAddress) { 112 | // Retrieves the correct address based on leading prefix 113 | 114 | thisString = thisAddress.toString(); 115 | int[] indexVal = bitcoinCollider.getLookupIndex(thisString); 116 | return this.addressArray[indexVal[0]][indexVal[1]][indexVal[2]][indexVal[3]]; 117 | } 118 | 119 | 120 | 121 | private void handleMatch(ECKey thisKey) throws IOException { 122 | /* 123 | * Called if an address match is made. Saves the info to a text file. 124 | */ 125 | 126 | String thisString = ""; 127 | 128 | thisString += Address.fromKey(MainNetParams.get(), thisKey, ScriptType.P2PKH); 129 | thisString += "\n"; 130 | thisString += thisKey.getPrivateKeyAsHex(); 131 | thisString += "\n"; 132 | thisString += thisKey.getPublicKeyAsHex(); 133 | thisString += "\n"; 134 | thisString += thisKey.getPrivateKeyAsWiF(MainNetParams.get()); 135 | 136 | int randomInt = new Random().nextInt(9999999); 137 | 138 | FileWriter thisFile = new FileWriter("bitcoin_Collider_Match_" + randomInt + ".txt"); 139 | BufferedWriter writer = new BufferedWriter(thisFile); 140 | writer.write(thisString); 141 | writer.close(); 142 | 143 | // Notifies the primary class so UI elements can be updated 144 | bitcoinCollider.notifySuccess(Address.fromKey(MainNetParams.get(), thisKey, ScriptType.P2PKH).toString(), 145 | thisKey.getPrivateKeyAsWiF(MainNetParams.get())); 146 | } 147 | 148 | private void updateGuiElements(Address thisAddress) { 149 | //Populate the label array with some addresses checked 150 | if (thisThreadAddressCount % 25 == 0) { 151 | labelArray[labelCounter] = thisAddress.toString(); 152 | 153 | this.labelCounter++; 154 | if (this.labelCounter >= 10) this.labelCounter = 0; 155 | } 156 | } 157 | 158 | public void resumeThread() { 159 | isInterrupted = false; 160 | try { 161 | checkAddresses(); 162 | } catch (IOException | URISyntaxException e) { 163 | e.printStackTrace(); 164 | } 165 | } 166 | 167 | public void stopThread() { 168 | isInterrupted = true; 169 | } 170 | 171 | 172 | 173 | 174 | } 175 | --------------------------------------------------------------------------------