Fred808 commited on
Commit
2ca6f28
Β·
verified Β·
1 Parent(s): 1cde484

Update parallel_miner_v3.py

Browse files
Files changed (1) hide show
  1. parallel_miner_v3.py +150 -354
parallel_miner_v3.py CHANGED
@@ -1,6 +1,5 @@
1
  """
2
- Real Bitcoin mining implementation with hardware-accurate SHA-256 and proper block finding
3
- Enhanced with mainnet integration and block submission
4
  """
5
  import hashlib
6
  import struct
@@ -10,8 +9,9 @@ import threading
10
  import multiprocessing
11
  from datetime import datetime
12
  from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
13
- from typing import Dict, Optional, Tuple, List
14
  from multiprocessing import Manager, Lock
 
15
 
16
  # Configure logging
17
  logging.basicConfig(
@@ -23,10 +23,6 @@ logging.basicConfig(
23
  ]
24
  )
25
 
26
- class BlockFoundException(Exception):
27
- """Exception raised when a block is found"""
28
- pass
29
-
30
  class HashUnit:
31
  """Individual mining unit that performs real SHA-256 operations at electron speed"""
32
  def __init__(self, unit_id: int):
@@ -34,7 +30,7 @@ class HashUnit:
34
  self.total_hashes = 0
35
  self.blocks_found = 0
36
  self.best_hash = None
37
- self.found_blocks = [] # List to store (hash, nonce, timestamp) tuples
38
  # Electron physics parameters - these determine processing capability
39
  self.electron_drift_velocity = 1.96e7 # m/s in silicon
40
  self.switching_frequency = 8.92e85 * 10020000 # Hz
@@ -54,11 +50,7 @@ class HashUnit:
54
  """Perform real double SHA-256 hash"""
55
  return hashlib.sha256(hashlib.sha256(header).digest()).digest()
56
 
57
- def count_leading_zeros(self, hash_hex: str) -> int:
58
- """Count leading zeros in hexadecimal representation"""
59
- return len(hash_hex) - len(hash_hex.lstrip('0'))
60
-
61
- def mine_range(self, block_header: bytes, target: int, nonce_start: int, nonce_range: int) -> Tuple[int, int, int, bytes]:
62
  """Mine a range of nonces with real SHA-256 at electron speed throughput"""
63
  best_hash = None
64
  best_nonce = None
@@ -91,12 +83,8 @@ class HashUnit:
91
  blocks_found += 1
92
  best_hash = hash_result
93
  best_nonce = nonce
94
- # Store block details with timestamp
95
- hash_hex = hash_result.hex()
96
- leading_zeros = self.count_leading_zeros(hash_hex)
97
- self.found_blocks.append((hash_hex, nonce, datetime.now().isoformat(), leading_zeros))
98
- logging.info(f"πŸŽ‰ VALID BLOCK FOUND! Hash: {hash_hex}")
99
- logging.info(f"πŸ”’ Leading zeros: {leading_zeros}")
100
  break
101
 
102
  # Track best hash even if not a valid block
@@ -104,11 +92,12 @@ class HashUnit:
104
  best_hash = hash_result
105
  best_nonce = nonce
106
 
 
107
  return self.total_hashes, blocks_found, best_nonce or -1, best_hash or b'\xff' * 32
108
 
109
  class MiningCore:
110
  """Mining core that manages multiple hash units"""
111
- def __init__(self, core_id: int, num_units: int = 18):
112
  self.core_id = core_id
113
  self.units = [HashUnit(i) for i in range(num_units)]
114
  self.total_hashes = 0
@@ -116,7 +105,7 @@ class MiningCore:
116
 
117
  def mine_parallel(self, block_header: bytes, target: int, base_nonce: int) -> Dict:
118
  """Mine in parallel across all units"""
119
- nonces_per_unit = 1111870
120
  results = []
121
 
122
  for i, unit in enumerate(self.units):
@@ -143,215 +132,9 @@ class MiningCore:
143
  'unit_results': results
144
  }
145
 
146
- class NetworkIntegration:
147
- """Mainnet integration for Bitcoin blockchain"""
148
-
149
- def __init__(self, wallet_address: str = None):
150
- self.api_base = "https://blockchain.info"
151
- self.node = "seed.bitcoin.sipa.be"
152
- self.is_mainnet = True
153
- self.wallet_address = wallet_address or "1Ks4WtCEK96BaBF7HSuCGt3rEpVKPqcJKf"
154
- self.connected = False
155
- self._template_cache = None
156
- self._last_cache_time = 0
157
-
158
- def connect(self) -> bool:
159
- """Connect to Bitcoin mainnet"""
160
- try:
161
- import requests
162
- response = requests.get(f"{self.api_base}/blockchain/blocks/last", timeout=10)
163
- self.connected = response.status_code == 200
164
- if self.connected:
165
- logging.info("βœ… Connected to Bitcoin mainnet")
166
- return self.connected
167
- except Exception as e:
168
- logging.error(f"❌ Failed to connect to mainnet: {e}")
169
- return False
170
-
171
- def get_block_template(self) -> Dict:
172
- """Get current block template from mainnet"""
173
- try:
174
- import requests
175
- import json
176
-
177
- # Cache template for 5 minutes
178
- current_time = time.time()
179
- if self._template_cache and current_time - self._last_cache_time < 300:
180
- return self._template_cache
181
-
182
- # Get latest block info
183
- response = requests.get("https://blockchain.info/latestblock", timeout=10)
184
- if response.status_code != 200:
185
- raise Exception(f"Failed to get latest block: {response.status_code}")
186
-
187
- latest = response.json()
188
- height = latest['height']
189
- current_block = latest['hash']
190
-
191
- logging.info(f"πŸ“¦ Current block height: {height}, hash: {current_block}")
192
-
193
- # Get network difficulty
194
- diff_response = requests.get("https://blockchain.info/q/getdifficulty", timeout=10)
195
- if diff_response.status_code != 200:
196
- raise Exception("Failed to get network difficulty")
197
-
198
- network_difficulty = float(diff_response.text)
199
- logging.info(f"🎯 Network difficulty: {network_difficulty:,.2f}")
200
-
201
- # Calculate target from difficulty
202
- max_target = 0x00000000FFFF0000000000000000000000000000000000000000000000000000
203
- target = int(max_target / network_difficulty)
204
-
205
- # Use standard Bitcoin difficulty 1 target bits
206
- bits = 0x1d00ffff
207
-
208
- template = {
209
- 'version': 0x20000000,
210
- 'previousblockhash': current_block,
211
- 'merkleroot': '0' * 64, # Will be calculated properly in submission
212
- 'time': int(time.time()),
213
- 'bits': bits,
214
- 'target': target,
215
- 'height': height,
216
- 'difficulty': network_difficulty
217
- }
218
-
219
- self._template_cache = template
220
- self._last_cache_time = current_time
221
-
222
- return template
223
-
224
- except Exception as e:
225
- logging.error(f"Error getting block template: {e}")
226
- # Fallback template
227
- return {
228
- 'version': 0x20000000,
229
- 'previousblockhash': '0' * 64,
230
- 'merkleroot': '0' * 64,
231
- 'time': int(time.time()),
232
- 'bits': 0x1d00ffff,
233
- 'target': 0x00000000FFFF0000000000000000000000000000000000000000000000000000,
234
- 'height': 820000,
235
- 'difficulty': 1.0
236
- }
237
-
238
- def submit_block(self, block_header: bytes, nonce: int) -> bool:
239
- """Submit found block to mainnet"""
240
- try:
241
- import requests
242
- import base58
243
-
244
- # Calculate the block hash
245
- block_hash = hashlib.sha256(hashlib.sha256(block_header).digest()).digest()
246
- hash_hex = block_hash.hex() # Use direct hex representation
247
-
248
- logging.info(f"πŸŽ‰ BLOCK FOUND! Submitting to mainnet...")
249
- logging.info(f"πŸ“€ Block Hash: {hash_hex}")
250
- logging.info(f"πŸ”’ Nonce: {nonce}")
251
- logging.info(f"πŸ’° Miner Address: {self.wallet_address}")
252
-
253
- # Get current template for block construction
254
- template = self.get_block_template()
255
-
256
- # Construct full block with proper coinbase transaction
257
- block_data = self._construct_block_data(block_header, nonce, template)
258
-
259
- # Submit to blockchain API
260
- submit_url = 'https://api.blockchain.info/haskoin-store/btc/block'
261
- headers = {'Content-Type': 'application/x-www-form-urlencoded'}
262
-
263
- logging.info("πŸ“‘ Submitting block to mainnet...")
264
- response = requests.post(submit_url, data={'block': block_data.hex()}, headers=headers, timeout=30)
265
-
266
- if response.status_code == 200:
267
- logging.info("βœ… Block successfully submitted to mainnet!")
268
- logging.info(f"πŸ’° Block reward will be sent to: {self.wallet_address}")
269
- return True
270
- else:
271
- error_msg = response.text if response.text else f"Status: {response.status_code}"
272
- logging.error(f"❌ Block submission failed: {error_msg}")
273
- return False
274
-
275
- except Exception as e:
276
- logging.error(f"❌ Error submitting block: {e}")
277
- return False
278
-
279
- def _construct_block_data(self, block_header: bytes, nonce: int, template: Dict) -> bytes:
280
- """Construct complete block data with coinbase transaction"""
281
- # Start with header including nonce
282
- block_data = bytearray(block_header[:-4] + struct.pack('<I', nonce))
283
-
284
- # Add transaction count (1 for coinbase only)
285
- block_data.extend(bytes([1]))
286
-
287
- # Create coinbase transaction
288
- coinbase_tx = self._create_coinbase_transaction(template)
289
- block_data.extend(coinbase_tx)
290
-
291
- return bytes(block_data)
292
-
293
- def _create_coinbase_transaction(self, template: Dict) -> bytes:
294
- """Create proper coinbase transaction"""
295
- import base58
296
-
297
- # Serialize transaction version
298
- tx_data = struct.pack('<I', 1) # Version 1
299
-
300
- # Input count (1 for coinbase)
301
- tx_data += bytes([1])
302
-
303
- # Previous output (null for coinbase)
304
- tx_data += b'\x00' * 32 # Null txid
305
- tx_data += struct.pack('<I', 0xFFFFFFFF) # -1 output index
306
-
307
- # Coinbase script
308
- block_height = template['height']
309
- block_height_hex = format(block_height, '06x') # 3 bytes for BIP34
310
-
311
- coinbase_script = (
312
- bytes([3]) + # Push 3 bytes
313
- bytes.fromhex(block_height_hex) + # Block height
314
- b'\x00' * 8 + # Extra nonce
315
- b'/Mined by BitCoin-Copilot/' # Miner tag
316
- )
317
-
318
- # Script length
319
- tx_data += bytes([len(coinbase_script)])
320
- tx_data += coinbase_script
321
- tx_data += struct.pack('<I', 0xFFFFFFFF) # Sequence
322
-
323
- # Output count (1 output)
324
- tx_data += bytes([1])
325
-
326
- # Output value (6.25 BTC in satoshis)
327
- tx_data += struct.pack('<Q', 625000000)
328
-
329
- # Create P2PKH script for wallet address
330
- try:
331
- # Decode base58 address to get pubkey hash
332
- decoded = base58.b58decode_check(self.wallet_address)
333
- pubkey_hash = decoded[1:] # Skip version byte
334
-
335
- # Build P2PKH script: OP_DUP OP_HASH160 <pubkey_hash> OP_EQUALVERIFY OP_CHECKSIG
336
- script_pubkey = bytes([0x76, 0xa9, 0x14]) + pubkey_hash + bytes([0x88, 0xac])
337
- tx_data += bytes([len(script_pubkey)])
338
- tx_data += script_pubkey
339
-
340
- except Exception as e:
341
- logging.warning(f"Could not decode wallet address, using fallback: {e}")
342
- # Fallback script
343
- script_pubkey = bytes([0x76, 0xa9, 0x14]) + b'\x00' * 20 + bytes([0x88, 0xac])
344
- tx_data += bytes([len(script_pubkey)])
345
- tx_data += script_pubkey
346
-
347
- # Locktime
348
- tx_data += struct.pack('<I', 0)
349
-
350
- return tx_data
351
-
352
  class ParallelMiner:
353
- """Top-level parallel miner managing multiple cores with mainnet integration"""
354
- def __init__(self, num_cores: int = 8, wallet_address: str = None):
355
  self.cores = [MiningCore(i) for i in range(num_cores)]
356
  self.start_time = None
357
  self.mining = False
@@ -359,26 +142,28 @@ class ParallelMiner:
359
  self.blocks_found = 0
360
  self.best_hash = None
361
  self.best_nonce = None
362
- self.best_hash_difficulty = 0
363
- self.network_difficulty = 0
364
  self.hashes_last_update = 0
365
  self.last_hashrate_update = time.time()
366
  self.current_hashrate = 0
367
  self.network = NetworkIntegration(wallet_address)
368
- self.network.connect()
369
 
370
- # Get initial network stats
371
  template = self.network.get_block_template()
372
  if template:
373
- self.network_difficulty = template.get('difficulty', 1.0)
374
- logging.info(f"🎯 Initial network difficulty: {self.network_difficulty:,.2f}")
375
- logging.info(f"πŸ’° Mining rewards to: {self.network.wallet_address}")
376
 
377
  def _setup_block_header(self) -> Tuple[bytes, int]:
378
- """Set up initial block header and target from mainnet"""
379
  try:
 
380
  template = self.network.get_block_template()
381
 
 
382
  version = template['version']
383
  prev_block = bytes.fromhex(template['previousblockhash'])
384
  merkle_root = bytes.fromhex(template['merkleroot'])
@@ -386,66 +171,54 @@ class ParallelMiner:
386
  bits = template['bits']
387
  target = template['target']
388
 
389
- # Pack header
390
- header = struct.pack('<I32s32sIII',
391
- version,
392
- prev_block,
393
- merkle_root,
394
- timestamp,
395
- bits,
396
- 0) # Nonce placeholder
397
-
398
- logging.info(f"πŸ“¦ Mining on block height: {template['height']}")
399
- logging.info(f"🎯 Network target: {hex(target)}")
400
- logging.info(f"πŸ“Š Network difficulty: {template.get('difficulty', 1.0):,.2f}")
401
 
402
- return header, target
 
403
 
404
  except Exception as e:
405
- logging.warning(f"Failed to get network template: {e}, using fallback")
406
- # Fallback values
407
- version = 0x20000000
408
  prev_block = b'\x00' * 32
409
  merkle_root = b'\x00' * 32
410
  timestamp = int(time.time())
411
  bits = 0x1d00ffff
412
- target = 0x00000000FFFF0000000000000000000000000000000000000000000000000000
413
 
414
- header = struct.pack('<I32s32sIII',
415
  version, prev_block, merkle_root,
416
- timestamp, bits, 0)
417
-
418
- return header, target
419
 
420
- def count_leading_zeros(self, hash_bytes: bytes) -> int:
421
- """Count leading zeros in hash bytes"""
422
- hash_hex = hash_bytes.hex()
423
- return len(hash_hex) - len(hash_hex.lstrip('0'))
424
 
425
  def start_mining(self, duration: int = 120):
426
- """Start mining across all cores with mainnet submission"""
427
  self.mining = True
428
  self.start_time = time.time()
429
  self.last_template_update = time.time()
430
  block_header, target = self._setup_block_header()
431
 
432
- logging.info("⛏️ Starting parallel mining on Bitcoin mainnet...")
433
- logging.info(f"πŸ”§ Cores: {len(self.cores)}")
434
- logging.info(f"βš™οΈ Units per core: {len(self.cores[0].units)}")
435
- logging.info(f"🎯 Target: {hex(target)}")
436
- logging.info("πŸ”— Connected to Bitcoin mainnet, getting real block templates")
437
 
438
  with ThreadPoolExecutor(max_workers=len(self.cores)) as executor:
439
  base_nonce = 0
440
 
441
  while self.mining and (duration is None or time.time() - self.start_time < duration):
442
- # Update block template every 10 minutes
443
  current_time = time.time()
444
- if current_time - self.last_template_update > 600:
445
  block_header, target = self._setup_block_header()
446
  self.last_template_update = current_time
447
- base_nonce = 0
448
- logging.info("πŸ”„ Updated block template from mainnet")
449
 
450
  futures = []
451
 
@@ -455,21 +228,20 @@ class ParallelMiner:
455
  core.mine_parallel,
456
  block_header,
457
  target,
458
- base_nonce + (core.core_id * 1000)
459
  )
460
  futures.append(future)
461
 
462
- # Process results
463
  for future in futures:
464
  result = future.result()
465
  core_id = result['core_id']
466
 
467
- # Update statistics
468
  new_hashes = result['total_hashes'] - self.hashes_last_update
469
  self.total_hashes += new_hashes
470
  self.blocks_found += result['blocks_found']
471
 
472
- # Update hash rate
473
  current_time = time.time()
474
  time_delta = current_time - self.last_hashrate_update
475
  if time_delta >= 1.0:
@@ -477,102 +249,126 @@ class ParallelMiner:
477
  self.hashes_last_update = result['total_hashes']
478
  self.last_hashrate_update = current_time
479
 
480
- # Log progress
481
  elapsed = time.time() - self.start_time
482
- if elapsed > 0:
483
- overall_hashrate = self.total_hashes / elapsed
484
- logging.info(f"🌟 Core {core_id}: {self.total_hashes:,} hashes, "
485
- f"{self.blocks_found} blocks, "
486
- f"{self.current_hashrate/1e6:.2f} MH/s, "
487
- f"Overall: {overall_hashrate/1e6:.2f} MH/s")
488
 
489
- # Check for found blocks
490
- for unit_result in result['unit_results']:
491
- if unit_result['nonce'] != -1:
492
- hash_result = unit_result['hash']
493
- nonce = unit_result['nonce']
494
- hash_int = int.from_bytes(hash_result, 'little')
495
-
496
- # Calculate hash info
497
- hash_hex = hash_result.hex()
498
- leading_zeros = self.count_leading_zeros(hash_result)
499
-
500
- # Found valid block!
501
- if hash_int < target:
502
- logging.info("πŸŽ‰ VALID BLOCK FOUND! Submitting to mainnet...")
503
- logging.info(f"πŸ† Hash: {hash_hex}")
504
- logging.info(f"πŸ”’ Leading zeros: {leading_zeros}")
505
- if self.network.submit_block(block_header, nonce):
506
- self.blocks_found += 1
507
- logging.info("πŸ’° Block successfully submitted! Waiting for confirmation...")
508
- else:
509
- logging.warning("⚠️ Block submission failed, but block is valid")
510
 
511
  # Track best hash
512
- if not self.best_hash or hash_int < int.from_bytes(self.best_hash, 'little'):
513
- self.best_hash = hash_result
514
- self.best_nonce = nonce
515
-
516
- # Calculate progress
517
- max_target = 0x00000000FFFF0000000000000000000000000000000000000000000000000000
518
- hash_difficulty = float(max_target) / float(hash_int) if hash_int > 0 else 0
519
- self.best_hash_difficulty = max(self.best_hash_difficulty, hash_difficulty)
520
 
521
- progress_percent = (hash_difficulty / self.network_difficulty) * 100
522
-
523
- logging.info(f"⭐ New best hash: {hash_hex}")
524
- logging.info(f"πŸ”’ Leading zeros: {leading_zeros}")
525
- logging.info(f"πŸ“Š Progress to target: {progress_percent:.8f}%")
526
- logging.info(f"🎯 Hash difficulty: {hash_difficulty:.8f}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
527
 
528
- base_nonce += len(self.cores) * 1000
529
 
530
  # Log final results
531
  self.log_final_results(duration)
532
 
533
  def log_final_results(self, duration: float):
534
  """Log final mining results"""
535
- logging.info("\n" + "="*60)
536
- logging.info("⛏️ MINING SESSION COMPLETED")
537
- logging.info("="*60)
538
- logging.info(f"⏱️ Duration: {duration:.2f} seconds")
539
- logging.info(f"πŸ”’ Total hashes: {self.total_hashes:,}")
540
- logging.info(f"πŸ’° Blocks found: {self.blocks_found}")
541
-
542
- if duration > 0:
543
- overall_hashrate = self.total_hashes / duration
544
- logging.info(f"⚑ Overall hash rate: {overall_hashrate/1e6:.2f} MH/s")
545
-
546
- logging.info(f"🎯 Best hash difficulty: {self.best_hash_difficulty:.8f}")
547
- logging.info(f"πŸ”— Network difficulty: {self.network_difficulty:,.2f}")
548
 
549
  # Log per-core stats
550
  for core in self.cores:
551
- logging.info(f"\nπŸ”© Core {core.core_id} final stats:")
552
- logging.info(f" Total hashes: {core.total_hashes:,}")
553
- logging.info(f" Blocks found: {core.blocks_found}")
554
 
555
  for unit in core.units:
556
- if unit.found_blocks:
557
- logging.info(f" ⚑ Unit {unit.unit_id}: {unit.total_hashes:,} hashes, {unit.blocks_found} blocks")
558
- for block_hash, nonce, timestamp, zeros in unit.found_blocks:
559
- logging.info(f" πŸŽ‰ Block found - Hash: {block_hash}, Nonce: {nonce}, Zeros: {zeros}, Time: {timestamp}")
560
-
561
- logging.info("="*60)
562
-
563
  if __name__ == "__main__":
564
- # Initialize miner with your wallet address
565
- miner = ParallelMiner(
566
- num_cores=7,
567
- wallet_address="1Ks4WtCEK96BaBF7HSuCGt3rEpVKPqcJKf" # Your Bitcoin address
568
- )
569
-
570
  try:
571
- # Start mining for 2 minutes (adjust as needed)
572
- miner.start_mining(duration=120)
573
  except KeyboardInterrupt:
574
  miner.mining = False
575
- logging.info("\nπŸ›‘ Mining stopped by user")
576
- except Exception as e:
577
- logging.error(f"❌ Mining error: {e}")
578
- miner.mining = False
 
1
  """
2
+ Bitcoin mining implementation with hardware-accurate SHA-256 and proper block finding
 
3
  """
4
  import hashlib
5
  import struct
 
9
  import multiprocessing
10
  from datetime import datetime
11
  from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
12
+ from typing import Dict, Optional, Tuple
13
  from multiprocessing import Manager, Lock
14
+ from network_integration import NetworkIntegration # Using consolidated network integration
15
 
16
  # Configure logging
17
  logging.basicConfig(
 
23
  ]
24
  )
25
 
 
 
 
 
26
  class HashUnit:
27
  """Individual mining unit that performs real SHA-256 operations at electron speed"""
28
  def __init__(self, unit_id: int):
 
30
  self.total_hashes = 0
31
  self.blocks_found = 0
32
  self.best_hash = None
33
+ self.found_blocks = [] # List to store (hash, nonce) tuples
34
  # Electron physics parameters - these determine processing capability
35
  self.electron_drift_velocity = 1.96e7 # m/s in silicon
36
  self.switching_frequency = 8.92e85 * 10020000 # Hz
 
50
  """Perform real double SHA-256 hash"""
51
  return hashlib.sha256(hashlib.sha256(header).digest()).digest()
52
 
53
+ def mine_range(self, block_header: bytes, target: int, nonce_start: int, nonce_range: int) -> Tuple[int, int, bytes]:
 
 
 
 
54
  """Mine a range of nonces with real SHA-256 at electron speed throughput"""
55
  best_hash = None
56
  best_nonce = None
 
83
  blocks_found += 1
84
  best_hash = hash_result
85
  best_nonce = nonce
86
+ # Store block details
87
+ self.found_blocks.append((hash_result.hex(), nonce))
 
 
 
 
88
  break
89
 
90
  # Track best hash even if not a valid block
 
92
  best_hash = hash_result
93
  best_nonce = nonce
94
 
95
+ # Return blocks found this cycle too
96
  return self.total_hashes, blocks_found, best_nonce or -1, best_hash or b'\xff' * 32
97
 
98
  class MiningCore:
99
  """Mining core that manages multiple hash units"""
100
+ def __init__(self, core_id: int, num_units: int = 8):
101
  self.core_id = core_id
102
  self.units = [HashUnit(i) for i in range(num_units)]
103
  self.total_hashes = 0
 
105
 
106
  def mine_parallel(self, block_header: bytes, target: int, base_nonce: int) -> Dict:
107
  """Mine in parallel across all units"""
108
+ nonces_per_unit = 3981870 # Each unit processes this many nonces per round
109
  results = []
110
 
111
  for i, unit in enumerate(self.units):
 
132
  'unit_results': results
133
  }
134
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
  class ParallelMiner:
136
+ """Top-level parallel miner managing multiple cores"""
137
+ def __init__(self, num_cores: int = 7, wallet_address: str = None):
138
  self.cores = [MiningCore(i) for i in range(num_cores)]
139
  self.start_time = None
140
  self.mining = False
 
142
  self.blocks_found = 0
143
  self.best_hash = None
144
  self.best_nonce = None
145
+ self.best_hash_difficulty = 0 # Stores the highest difficulty achieved
146
+ self.network_difficulty = 0 # Current network difficulty
147
  self.hashes_last_update = 0
148
  self.last_hashrate_update = time.time()
149
  self.current_hashrate = 0
150
  self.network = NetworkIntegration(wallet_address)
151
+ self.network.connect() # Connect to network
152
 
153
+ # Calculate initial network difficulty
154
  template = self.network.get_block_template()
155
  if template:
156
+ max_target = 0xFFFF * 2**(8*(0x1d - 3))
157
+ self.network_difficulty = max_target / template['target']
158
+ logging.info(f"Current network difficulty: {self.network_difficulty:,.2f}")
159
 
160
  def _setup_block_header(self) -> Tuple[bytes, int]:
161
+ """Set up initial block header and target from network"""
162
  try:
163
+ # Get block template from network
164
  template = self.network.get_block_template()
165
 
166
+ # Extract header fields
167
  version = template['version']
168
  prev_block = bytes.fromhex(template['previousblockhash'])
169
  merkle_root = bytes.fromhex(template['merkleroot'])
 
171
  bits = template['bits']
172
  target = template['target']
173
 
174
+ # Pack header fields
175
+ header = struct.pack('<I32s32sII',
176
+ version, prev_block, merkle_root,
177
+ timestamp, bits)
178
+ header += b'\x00' * 4 # Reserve space for nonce
 
 
 
 
 
 
 
179
 
180
+ logging.info(f"Mining on block height: {template['height']}")
181
+ logging.info(f"Network target: {hex(target)}")
182
 
183
  except Exception as e:
184
+ logging.warning(f"Failed to get network template: {e}, using fallback values")
185
+ # Fallback to test values
186
+ version = 2
187
  prev_block = b'\x00' * 32
188
  merkle_root = b'\x00' * 32
189
  timestamp = int(time.time())
190
  bits = 0x1d00ffff
191
+ target = 0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
192
 
193
+ header = struct.pack('<I32s32sII',
194
  version, prev_block, merkle_root,
195
+ timestamp, bits)
196
+ header += b'\x00' * 4 # Placeholder for nonce
 
197
 
198
+ return header, target
 
 
 
199
 
200
  def start_mining(self, duration: int = 120):
201
+ """Start mining across all cores"""
202
  self.mining = True
203
  self.start_time = time.time()
204
  self.last_template_update = time.time()
205
  block_header, target = self._setup_block_header()
206
 
207
+ logging.info("Starting parallel Bitcoin mining...")
208
+ logging.info(f"Cores: {len(self.cores)}")
209
+ logging.info(f"Units per core: {len(self.cores[0].units)}")
210
+ logging.info("Connected to network, getting block templates")
 
211
 
212
  with ThreadPoolExecutor(max_workers=len(self.cores)) as executor:
213
  base_nonce = 0
214
 
215
  while self.mining and (duration is None or time.time() - self.start_time < duration):
216
+ # Update block template every 30 seconds
217
  current_time = time.time()
218
+ if current_time - self.last_template_update > 600: # Update every 10 minutes
219
  block_header, target = self._setup_block_header()
220
  self.last_template_update = current_time
221
+ logging.info("Updated block template from network - continuing with current nonce range")
 
222
 
223
  futures = []
224
 
 
228
  core.mine_parallel,
229
  block_header,
230
  target,
231
+ base_nonce + (core.core_id * 100) # Each core gets different nonce range
232
  )
233
  futures.append(future)
234
 
235
+ # Process results
236
  for future in futures:
237
  result = future.result()
238
  core_id = result['core_id']
239
 
 
240
  new_hashes = result['total_hashes'] - self.hashes_last_update
241
  self.total_hashes += new_hashes
242
  self.blocks_found += result['blocks_found']
243
 
244
+ # Update hash rate every second
245
  current_time = time.time()
246
  time_delta = current_time - self.last_hashrate_update
247
  if time_delta >= 1.0:
 
249
  self.hashes_last_update = result['total_hashes']
250
  self.last_hashrate_update = current_time
251
 
252
+ # Log progress for this core
253
  elapsed = time.time() - self.start_time
 
 
 
 
 
 
254
 
255
+ logging.info(f"Core {core_id}: {self.total_hashes:,} hashes, {self.blocks_found} blocks, {self.current_hashrate/1000:.2f} KH/s")
256
+
257
+ # Check unit results for blocks
258
+ for unit in result['unit_results']:
259
+ if unit['nonce'] != -1:
260
+ # Found a block or better hash
261
+ current_hash_int = int.from_bytes(unit['hash'], byteorder='little')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
262
 
263
  # Track best hash
264
+ if not self.best_hash or current_hash_int < int.from_bytes(self.best_hash, byteorder='little'):
265
+ self.best_hash = unit['hash']
266
+ self.best_nonce = unit['nonce']
 
 
 
 
 
267
 
268
+ # Compare with current target and submit if valid
269
+ if current_hash_int < target: # Use current target, not new template target
270
+ logging.info(f"Found valid block! Hash is below target")
271
+ logging.info(f"Core {core_id}, Unit {unit['unit_id']} found the block")
272
+ logging.info(f"Block details:")
273
+ logging.info(f" Hash: {unit['hash'].hex()}")
274
+ logging.info(f" Nonce: {unit['nonce']}")
275
+ logging.info(f" Timestamp: {time.strftime('%Y-%m-%d %H:%M:%S')}")
276
+
277
+ # Prepare block data
278
+ block_data = block_header[:-4] + struct.pack('<I', unit['nonce'])
279
+
280
+ # Log submission attempt details
281
+ logging.info("Block submission details:")
282
+ logging.info(f"Block header length: {len(block_header)}")
283
+ logging.info(f"Final block data length: {len(block_data)}")
284
+ logging.info(f"Target used: {hex(target)}")
285
+ logging.info(f"Hash achieved: {hex(current_hash_int)}")
286
+
287
+ try:
288
+ logging.info("πŸ”„ Attempting to submit block to network...")
289
+ if self.network.submit_block(block_data, unit['nonce']):
290
+ logging.info("πŸŽ‰ Block successfully submitted to network! πŸŽ‰")
291
+ logging.info(f"Block hash: {unit['hash'].hex()}")
292
+ logging.info(f"Nonce: {unit['nonce']}")
293
+ logging.info(f"Difficulty: {self.network_difficulty:,.2f}")
294
+
295
+ # Extra verification
296
+ verify_hash = self.double_sha256(block_data)
297
+ verify_int = int.from_bytes(verify_hash, 'little')
298
+ logging.info(f"Verification hash: {hex(verify_int)}")
299
+ logging.info(f"Matches original: {verify_int == current_hash_int}")
300
+ else:
301
+ logging.error("❌ Block submission failed")
302
+ logging.error("Detailed diagnostics:")
303
+ logging.error(f"- Block header hex: {block_header.hex()}")
304
+ logging.error(f"- Final nonce used: {unit['nonce']}")
305
+ logging.error(f"- Hash achieved: {unit['hash'].hex()}")
306
+ logging.error("Common failure reasons:")
307
+ logging.error("- Network connectivity issues")
308
+ logging.error("- Block became stale")
309
+ logging.error("- Invalid block structure")
310
+ logging.error("- Target difficulty mismatch")
311
+ except Exception as e:
312
+ logging.error(f"❌ Exception during block submission: {str(e)}")
313
+ logging.error(f"Block data length: {len(block_data)}")
314
+ logging.error(f"Nonce value: {unit['nonce']}")
315
+ logging.exception("Full exception details:")
316
+ else:
317
+ hash_hex = hex(current_hash_int)[2:].zfill(64)
318
+ target_hex = hex(target)[2:].zfill(64)
319
+
320
+ # Calculate difficulty (max_target / hash)
321
+ max_target = 0xFFFF * 2**(8*(0x1d - 3))
322
+ hash_difficulty = float(max_target) / float(current_hash_int)
323
+
324
+ # Calculate percentage based on leading zeros
325
+ leading_zeros = len(hash_hex) - len(hash_hex.lstrip('0'))
326
+ target_zeros = len(target_hex) - len(target_hex.lstrip('0'))
327
+
328
+ # Progress based on zeros and first non-zero byte
329
+ first_byte_progress = (255 - int(hash_hex[leading_zeros:leading_zeros+2], 16)) / 255.0
330
+ progress_percent = (leading_zeros / float(target_zeros) + first_byte_progress / target_zeros) * 100
331
+
332
+ # Update best hash difficulty if this is higher
333
+ self.best_hash_difficulty = max(self.best_hash_difficulty, hash_difficulty)
334
+
335
+ logging.info(f"New best hash found!")
336
+ logging.info(f"Best hash: {hash_hex}")
337
+ logging.info(f"Need target: {target_hex}")
338
+ logging.info(f"Progress to target: {progress_percent:.8f}%")
339
+ logging.info(f"Hash difficulty: {hash_difficulty:.8f} (higher is better)")
340
 
341
+ base_nonce += len(self.cores) * 1500 # Increment base_nonce within the main loop
342
 
343
  # Log final results
344
  self.log_final_results(duration)
345
 
346
  def log_final_results(self, duration: float):
347
  """Log final mining results"""
348
+ logging.info("\nMining test completed:")
349
+ logging.info(f"Duration: {duration:.2f} seconds")
350
+ logging.info(f"Total hashes: {self.total_hashes:,}")
351
+ logging.info(f"Blocks found: {self.blocks_found}")
352
+ logging.info(f"Overall hash rate: {self.total_hashes/duration/1000:.2f} KH/s")
353
+ logging.info(f"Electron drift utilized: {self.cores[0].units[0].electron_drift_velocity:.2e} m/s")
354
+ logging.info(f"Switching frequency: {self.cores[0].units[0].switching_frequency:.2e} Hz")
 
 
 
 
 
 
355
 
356
  # Log per-core stats
357
  for core in self.cores:
358
+ logging.info(f"\nCore {core.core_id} final stats:")
359
+ logging.info(f"Total hashes: {core.total_hashes:,}")
360
+ logging.info(f"Blocks found: {core.blocks_found}")
361
 
362
  for unit in core.units:
363
+ logging.info(f" Unit {unit.unit_id}: {unit.total_hashes:,} hashes, {unit.blocks_found} blocks")
364
+ # Show block details if any found
365
+ for block_hash, nonce in unit.found_blocks:
366
+ logging.info(f" Block found - Hash: {block_hash}, Nonce: {nonce}")
367
+
 
 
368
  if __name__ == "__main__":
369
+ miner = ParallelMiner()
 
 
 
 
 
370
  try:
371
+ miner.start_mining(duration=500)
 
372
  except KeyboardInterrupt:
373
  miner.mining = False
374
+ logging.info("\nMining stopped by user")