├── 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 |
--------------------------------------------------------------------------------