lunalib 1.5.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of lunalib might be problematic. Click here for more details.

Files changed (53) hide show
  1. core/__init__.py +0 -0
  2. core/blockchain.py +172 -0
  3. core/crypto.py +32 -0
  4. core/wallet.py +408 -0
  5. gtx/__init__.py +0 -0
  6. gtx/bill_registry.py +122 -0
  7. gtx/digital_bill.py +273 -0
  8. gtx/genesis.py +338 -0
  9. lunalib/__init__.py +21 -0
  10. lunalib/cli.py +18 -0
  11. lunalib/core/__init__.py +0 -0
  12. lunalib/core/blockchain.py +803 -0
  13. lunalib/core/crypto.py +270 -0
  14. lunalib/core/mempool.py +342 -0
  15. lunalib/core/sm2.py +723 -0
  16. lunalib/core/wallet.py +1342 -0
  17. lunalib/core/wallet_manager.py +638 -0
  18. lunalib/core/wallet_sync_helper.py +163 -0
  19. lunalib/gtx/__init__.py +0 -0
  20. lunalib/gtx/bill_registry.py +122 -0
  21. lunalib/gtx/digital_bill.py +273 -0
  22. lunalib/gtx/genesis.py +349 -0
  23. lunalib/luna_lib.py +87 -0
  24. lunalib/mining/__init__.py +0 -0
  25. lunalib/mining/cuda_manager.py +137 -0
  26. lunalib/mining/difficulty.py +106 -0
  27. lunalib/mining/miner.py +617 -0
  28. lunalib/requirements.txt +44 -0
  29. lunalib/storage/__init__.py +0 -0
  30. lunalib/storage/cache.py +148 -0
  31. lunalib/storage/database.py +222 -0
  32. lunalib/storage/encryption.py +105 -0
  33. lunalib/transactions/__init__.py +0 -0
  34. lunalib/transactions/security.py +234 -0
  35. lunalib/transactions/transactions.py +399 -0
  36. lunalib/transactions/validator.py +71 -0
  37. lunalib-1.5.1.dist-info/METADATA +283 -0
  38. lunalib-1.5.1.dist-info/RECORD +53 -0
  39. lunalib-1.5.1.dist-info/WHEEL +5 -0
  40. lunalib-1.5.1.dist-info/entry_points.txt +2 -0
  41. lunalib-1.5.1.dist-info/top_level.txt +6 -0
  42. mining/__init__.py +0 -0
  43. mining/cuda_manager.py +137 -0
  44. mining/difficulty.py +106 -0
  45. mining/miner.py +107 -0
  46. storage/__init__.py +0 -0
  47. storage/cache.py +148 -0
  48. storage/database.py +222 -0
  49. storage/encryption.py +105 -0
  50. transactions/__init__.py +0 -0
  51. transactions/security.py +172 -0
  52. transactions/transactions.py +424 -0
  53. transactions/validator.py +71 -0
@@ -0,0 +1,617 @@
1
+ # lunalib/mining/miner.py
2
+ import time
3
+ import hashlib
4
+ import json
5
+ import threading
6
+ from typing import Dict, Optional, List, Union, Callable
7
+ from ..mining.difficulty import DifficultySystem
8
+ from ..gtx.digital_bill import DigitalBill
9
+ from ..transactions.transactions import TransactionManager
10
+ from ..core.blockchain import BlockchainManager
11
+ from ..core.mempool import MempoolManager
12
+
13
+ class GenesisMiner:
14
+ """Mines GTX Genesis bills AND regular transfer transactions with configurable difficulty"""
15
+
16
+ def __init__(self, network_endpoints: List[str] = None):
17
+ self.difficulty_system = DifficultySystem()
18
+ self.transaction_manager = TransactionManager(network_endpoints)
19
+ self.blockchain_manager = BlockchainManager(network_endpoints[0] if network_endpoints else "https://bank.linglin.art")
20
+ self.mempool_manager = MempoolManager(network_endpoints)
21
+
22
+ self.mining_active = False
23
+ self.current_thread = None
24
+ self.mining_stats = {
25
+ "bills_mined": 0,
26
+ "blocks_mined": 0,
27
+ "total_mining_time": 0,
28
+ "total_hash_attempts": 0
29
+ }
30
+
31
+ print("🔧 GenesisMiner initialized with integrated lunalib components")
32
+
33
+ def mine_bill(self, denomination: float, user_address: str, bill_data: Dict = None) -> Dict:
34
+ """Mine a GTX Genesis bill using DigitalBill system"""
35
+ try:
36
+ difficulty = self.difficulty_system.get_bill_difficulty(denomination)
37
+
38
+ # Create digital bill using GTX system
39
+ digital_bill = DigitalBill(
40
+ denomination=denomination,
41
+ user_address=user_address,
42
+ difficulty=difficulty,
43
+ bill_data=bill_data or {}
44
+ )
45
+
46
+ print(f"⛏️ Mining GTX ${denomination:,} Bill - Difficulty: {difficulty} zeros")
47
+
48
+ start_time = time.time()
49
+ mining_result = self._perform_bill_mining(digital_bill, difficulty)
50
+
51
+ if mining_result["success"]:
52
+ mining_time = time.time() - start_time
53
+
54
+ # Finalize the bill
55
+ bill = digital_bill.finalize(
56
+ hash=mining_result["hash"],
57
+ nonce=mining_result["nonce"],
58
+ mining_time=mining_time
59
+ )
60
+
61
+ # Update mining statistics
62
+ self.mining_stats["bills_mined"] += 1
63
+ self.mining_stats["total_mining_time"] += mining_time
64
+ self.mining_stats["total_hash_attempts"] += mining_result["nonce"]
65
+
66
+ print(f"✅ Successfully mined GTX ${denomination:,} bill!")
67
+ print(f"⏱️ Mining time: {mining_time:.2f}s")
68
+ print(f"📊 Hash attempts: {mining_result['nonce']:,}")
69
+ print(f"🔗 Bill hash: {mining_result['hash'][:32]}...")
70
+
71
+ # Convert to GTX Genesis transaction
72
+ gtx_transaction = self._create_gtx_genesis_transaction(bill)
73
+ return {
74
+ "success": True,
75
+ "type": "bill",
76
+ "bill": bill,
77
+ "transaction": gtx_transaction,
78
+ "mining_time": mining_time,
79
+ "hash_attempts": mining_result["nonce"]
80
+ }
81
+ else:
82
+ return {"success": False, "error": "Bill mining failed"}
83
+
84
+ except Exception as e:
85
+ print(f"[X]Error mining bill: {e}")
86
+ return {"success": False, "error": str(e)}
87
+
88
+ def mine_transaction_block(self, miner_address: str, previous_hash: str = None, block_height: int = None) -> Dict:
89
+ """Mine a block containing transactions from mempool"""
90
+ try:
91
+ # Get current blockchain state if not provided
92
+ if previous_hash is None or block_height is None:
93
+ current_height = self.blockchain_manager.get_blockchain_height()
94
+ latest_block = self.blockchain_manager.get_latest_block()
95
+ block_height = current_height + 1
96
+ previous_hash = latest_block.get('hash', '0' * 64) if latest_block else '0' * 64
97
+
98
+ # Get transactions from mempool
99
+ pending_txs = self.mempool_manager.get_pending_transactions()
100
+ transactions = pending_txs[:10] # Limit block size
101
+
102
+ if not transactions:
103
+ return {"success": False, "error": "No transactions in mempool"}
104
+
105
+ # Calculate block difficulty
106
+ difficulty = self.difficulty_system.get_transaction_block_difficulty(transactions)
107
+
108
+ print(f"⛏️ Mining Transaction Block #{block_height} - Difficulty: {difficulty} zeros")
109
+ print(f"📦 Transactions: {len(transactions)} | Previous Hash: {previous_hash[:16]}...")
110
+
111
+ # Create block structure for mining
112
+ block_data = {
113
+ "index": block_height,
114
+ "previous_hash": previous_hash,
115
+ "timestamp": time.time(),
116
+ "transactions": transactions,
117
+ "miner": miner_address,
118
+ "difficulty": difficulty,
119
+ "nonce": 0,
120
+ "version": "1.0"
121
+ }
122
+
123
+ start_time = time.time()
124
+ mining_result = self._perform_block_mining(block_data, difficulty)
125
+
126
+ if mining_result["success"]:
127
+ mining_time = time.time() - start_time
128
+
129
+ # Add hash and nonce to block_data for validation
130
+ block_data["hash"] = mining_result["hash"]
131
+ block_data["nonce"] = mining_result["nonce"]
132
+
133
+ # Create reward transaction WITH VALIDATION
134
+ reward_tx = self._create_mining_reward_transaction(
135
+ miner_address=miner_address,
136
+ block_height=block_height,
137
+ transactions=transactions,
138
+ block_data=block_data # Pass block data for validation
139
+ )
140
+
141
+ # Add reward transaction
142
+ block_data["transactions"].append(reward_tx)
143
+
144
+ # Calculate merkleroot for submission
145
+ merkleroot = self._calculate_merkleroot(transactions) # Without reward
146
+
147
+ # Finalize block
148
+ block = {
149
+ **block_data,
150
+ "hash": mining_result["hash"],
151
+ "nonce": mining_result["nonce"],
152
+ "merkleroot": merkleroot,
153
+ "transactions_hash": merkleroot,
154
+ "mining_time": mining_time,
155
+ "reward": reward_tx["amount"],
156
+ "transaction_count": len(block_data["transactions"]),
157
+ "timestamp": block_data["timestamp"] # Ensure timestamp is included
158
+ }
159
+
160
+ # Update mining statistics
161
+ self.mining_stats["blocks_mined"] += 1
162
+ self.mining_stats["total_mining_time"] += mining_time
163
+ self.mining_stats["total_hash_attempts"] += mining_result["nonce"]
164
+
165
+ print(f"✅ Successfully mined and validated Transaction Block #{block_height}!")
166
+ print(f"⏱️ Mining time: {mining_time:.2f}s")
167
+ print(f"💰 Block reward: {block['reward']:.6f} LUN")
168
+ print(f"📊 Transactions: {block['transaction_count']}")
169
+ print(f"🔗 Block hash: {mining_result['hash'][:32]}...")
170
+
171
+ # Submit block to blockchain
172
+ submission_success = self.blockchain_manager.submit_mined_block(block)
173
+ if submission_success:
174
+ print("✅ Block successfully submitted to blockchain!")
175
+ # Clear mined transactions from local mempool
176
+ self._clear_mined_transactions(transactions)
177
+ else:
178
+ print("⚠️ Block mined but submission failed")
179
+
180
+ return {
181
+ "success": True,
182
+ "type": "block",
183
+ "block": block,
184
+ "submitted": submission_success,
185
+ "mining_time": mining_time,
186
+ "hash_attempts": mining_result["nonce"]
187
+ }
188
+ else:
189
+ return {"success": False, "error": "Block mining failed"}
190
+
191
+ except Exception as e:
192
+ print(f"❌ Error mining block: {e}")
193
+ import traceback
194
+ traceback.print_exc()
195
+ return {"success": False, "error": str(e)}
196
+
197
+ def _perform_bill_mining(self, digital_bill: DigitalBill, difficulty: int) -> Dict:
198
+ """Perform proof-of-work mining for GTX bills"""
199
+ target = "0" * difficulty
200
+ nonce = 0
201
+ start_time = time.time()
202
+ last_update = start_time
203
+
204
+ while self.mining_active:
205
+ mining_data = digital_bill.get_mining_data(nonce)
206
+ data_string = json.dumps(mining_data, sort_keys=True)
207
+ bill_hash = hashlib.sha256(data_string.encode()).hexdigest()
208
+
209
+ if bill_hash.startswith(target):
210
+ mining_time = time.time() - start_time
211
+ return {
212
+ "success": True,
213
+ "hash": bill_hash,
214
+ "nonce": nonce,
215
+ "mining_time": mining_time
216
+ }
217
+
218
+ nonce += 1
219
+
220
+ # Progress updates every 5 seconds
221
+ current_time = time.time()
222
+ if current_time - last_update >= 5:
223
+ hashrate = nonce / (current_time - start_time)
224
+ print(f"⏳ Bill mining: {nonce:,} attempts | Rate: {hashrate:,.0f} H/s")
225
+ last_update = current_time
226
+
227
+ return {"success": False, "error": "Mining stopped"}
228
+
229
+ def _perform_block_mining(self, block_data: Dict, difficulty: int) -> Dict:
230
+ """Perform proof-of-work mining for transaction blocks"""
231
+ target = "0" * difficulty
232
+ nonce = 0
233
+ start_time = time.time()
234
+ last_update = start_time
235
+
236
+ while self.mining_active:
237
+ # Update nonce for this attempt
238
+ block_data["nonce"] = nonce
239
+
240
+ # Create block hash
241
+ block_string = json.dumps(block_data, sort_keys=True)
242
+ block_hash = hashlib.sha256(block_string.encode()).hexdigest()
243
+
244
+ if block_hash.startswith(target):
245
+ mining_time = time.time() - start_time
246
+ return {
247
+ "success": True,
248
+ "hash": block_hash,
249
+ "nonce": nonce,
250
+ "mining_time": mining_time
251
+ }
252
+
253
+ nonce += 1
254
+
255
+ # Progress updates every 5 seconds
256
+ current_time = time.time()
257
+ if current_time - last_update >= 5:
258
+ hashrate = nonce / (current_time - start_time)
259
+ print(f"Block mining: {nonce:,} attempts | Rate: {hashrate:,.0f} H/s")
260
+ last_update = current_time
261
+
262
+ return {"success": False, "error": "Mining stopped"}
263
+
264
+ def _create_gtx_genesis_transaction(self, bill: Dict) -> Dict:
265
+ """Create GTX Genesis transaction from mined bill"""
266
+ return self.transaction_manager.create_gtx_transaction(bill)
267
+
268
+ def _create_mining_reward_transaction(self, miner_address: str, block_height: int,
269
+ transactions: List[Dict], block_data: Dict = None) -> Dict:
270
+ """Create mining reward transaction with validation of the mining proof"""
271
+
272
+ # Calculate reward
273
+ base_reward = 1.0 # Base block reward
274
+ total_fees = sum(tx.get('fee', 0) for tx in transactions)
275
+ total_reward = base_reward + total_fees
276
+
277
+ # If block_data is provided, validate the mining proof
278
+ if block_data:
279
+ print("🔍 Validating mining proof before creating reward...")
280
+
281
+ # Extract mining proof components
282
+ block_hash = block_data.get('hash', '')
283
+ difficulty = block_data.get('difficulty', 0)
284
+ nonce = block_data.get('nonce', 0)
285
+ timestamp = block_data.get('timestamp', time.time())
286
+ previous_hash = block_data.get('previous_hash', '0' * 64)
287
+ miner = block_data.get('miner', miner_address)
288
+
289
+ # Calculate merkleroot from transactions
290
+ merkleroot = self._calculate_merkleroot(transactions)
291
+
292
+ print(f"📊 Mining proof components:")
293
+ print(f" Block hash: {block_hash[:16]}...")
294
+ print(f" Difficulty: {difficulty}")
295
+ print(f" Nonce: {nonce}")
296
+ print(f" Timestamp: {timestamp}")
297
+ print(f" Previous hash: {previous_hash[:16]}...")
298
+ print(f" Miner: {miner}")
299
+ print(f" Merkleroot: {merkleroot[:16]}...")
300
+
301
+ # Validate difficulty requirement
302
+ if not block_hash.startswith('0' * difficulty):
303
+ print(f"❌ FAIL: Hash doesn't start with {difficulty} zeros")
304
+ raise ValueError(f"Invalid mining proof: Hash doesn't meet difficulty requirement")
305
+
306
+ # Try multiple validation methods
307
+ validation_passed = False
308
+
309
+ # Method 1: Original format (what server likely expects)
310
+ original_string = f"{previous_hash}{timestamp}{merkleroot}{miner}{nonce}"
311
+ original_hash = hashlib.sha256(original_string.encode()).hexdigest()
312
+
313
+ print(f"🔍 Original format validation:")
314
+ print(f" String: {original_string[:80]}...")
315
+ print(f" Calculated: {original_hash[:16]}...")
316
+
317
+ if original_hash == block_hash:
318
+ validation_passed = True
319
+ print("✅ Original format validation passed")
320
+
321
+ # Method 2: JSON format (what miner might be using)
322
+ if not validation_passed:
323
+ mining_json = {
324
+ "index": block_height,
325
+ "previous_hash": previous_hash,
326
+ "timestamp": timestamp,
327
+ "transactions": transactions,
328
+ "miner": miner,
329
+ "difficulty": difficulty,
330
+ "nonce": nonce,
331
+ "version": "1.0"
332
+ }
333
+
334
+ json_string = json.dumps(mining_json, sort_keys=True)
335
+ json_hash = hashlib.sha256(json_string.encode()).hexdigest()
336
+
337
+ print(f"🔍 JSON format validation:")
338
+ print(f" String: {json_string[:100]}...")
339
+ print(f" Calculated: {json_hash[:16]}...")
340
+
341
+ if json_hash == block_hash:
342
+ validation_passed = True
343
+ print("✅ JSON format validation passed")
344
+
345
+ # Method 3: JSON without transactions (for empty blocks)
346
+ if not validation_passed and len(transactions) == 0:
347
+ mining_json_empty = {
348
+ "index": block_height,
349
+ "previous_hash": previous_hash,
350
+ "timestamp": timestamp,
351
+ "transactions": [],
352
+ "miner": miner,
353
+ "difficulty": difficulty,
354
+ "nonce": nonce,
355
+ "version": "1.0"
356
+ }
357
+
358
+ json_string_empty = json.dumps(mining_json_empty, sort_keys=True)
359
+ json_hash_empty = hashlib.sha256(json_string_empty.encode()).hexdigest()
360
+
361
+ print(f"🔍 JSON empty format validation:")
362
+ print(f" Calculated: {json_hash_empty[:16]}...")
363
+
364
+ if json_hash_empty == block_hash:
365
+ validation_passed = True
366
+ print("✅ JSON empty format validation passed")
367
+
368
+ if not validation_passed:
369
+ print("❌ All validation methods failed")
370
+ raise ValueError("Invalid mining proof: Hash verification failed")
371
+
372
+ print("✅ Mining proof validation successful!")
373
+
374
+ # Create the reward transaction
375
+ return self.transaction_manager.create_reward_transaction(
376
+ to_address=miner_address,
377
+ amount=total_reward,
378
+ block_height=block_height,
379
+ reward_type="block"
380
+ )
381
+
382
+ def _calculate_merkleroot(self, transactions: List[Dict]) -> str:
383
+ """Calculate merkle root from transactions"""
384
+ if not transactions:
385
+ return "0" * 64
386
+
387
+ tx_hashes = []
388
+ for tx in transactions:
389
+ if 'hash' in tx:
390
+ tx_hashes.append(tx['hash'])
391
+ else:
392
+ tx_string = json.dumps(tx, sort_keys=True)
393
+ tx_hashes.append(hashlib.sha256(tx_string.encode()).hexdigest())
394
+
395
+ # Simple merkle root calculation
396
+ while len(tx_hashes) > 1:
397
+ new_hashes = []
398
+ for i in range(0, len(tx_hashes), 2):
399
+ if i + 1 < len(tx_hashes):
400
+ combined = tx_hashes[i] + tx_hashes[i + 1]
401
+ else:
402
+ combined = tx_hashes[i] + tx_hashes[i]
403
+ new_hash = hashlib.sha256(combined.encode()).hexdigest()
404
+ new_hashes.append(new_hash)
405
+ tx_hashes = new_hashes
406
+
407
+ return tx_hashes[0] if tx_hashes else "0" * 64
408
+
409
+ def _clear_mined_transactions(self, mined_transactions: List[Dict]):
410
+ """Remove mined transactions from local mempool"""
411
+ for tx in mined_transactions:
412
+ tx_hash = tx.get('hash')
413
+ if tx_hash:
414
+ self.mempool_manager.remove_transaction(tx_hash)
415
+
416
+ print(f"Cleared {len(mined_transactions)} mined transactions from mempool")
417
+
418
+ def start_auto_bill_mining(self, denominations: List[float], user_address: str,
419
+ callback: Callable = None) -> bool:
420
+ """Start auto-mining multiple GTX bills"""
421
+ if self.mining_active:
422
+ print("Mining already active")
423
+ return False
424
+
425
+ self.mining_active = True
426
+
427
+ def auto_mine():
428
+ results = []
429
+ for denomination in denominations:
430
+ if not self.mining_active:
431
+ break
432
+
433
+ print(f"Starting auto-mining for ${denomination:,} bill...")
434
+ result = self.mine_bill(denomination, user_address)
435
+ results.append(result)
436
+
437
+ if callback:
438
+ callback(result)
439
+
440
+ # Brief pause between bills
441
+ time.sleep(1)
442
+
443
+ print("Auto bill mining completed")
444
+ return results
445
+
446
+ self.current_thread = threading.Thread(target=auto_mine, daemon=True)
447
+ self.current_thread.start()
448
+ print(f"Started auto-mining {len(denominations)} bills")
449
+ return True
450
+
451
+ def start_continuous_block_mining(self, miner_address: str, callback: Callable = None) -> bool:
452
+ """Start continuous transaction block mining"""
453
+ if self.mining_active:
454
+ print("⚠️ Mining already active")
455
+ return False
456
+
457
+ self.mining_active = True
458
+
459
+ def continuous_mine():
460
+ block_height = self.blockchain_manager.get_blockchain_height() + 1
461
+ latest_block = self.blockchain_manager.get_latest_block()
462
+ previous_hash = latest_block.get('hash', '0' * 64) if latest_block else '0' * 64
463
+
464
+ while self.mining_active:
465
+ # Check mempool for transactions
466
+ pending_count = len(self.mempool_manager.get_pending_transactions())
467
+
468
+ if pending_count > 0:
469
+ print(f"🔄 Mining block #{block_height} with {pending_count} pending transactions...")
470
+
471
+ result = self.mine_transaction_block(miner_address, previous_hash, block_height)
472
+
473
+ if result.get("success"):
474
+ if callback:
475
+ callback(result)
476
+
477
+ # Update for next block
478
+ block_height += 1
479
+ previous_hash = result["block"]["hash"]
480
+
481
+ # Brief pause between blocks
482
+ time.sleep(2)
483
+ else:
484
+ print("⏳ No transactions in mempool, waiting...")
485
+ time.sleep(10) # Wait longer if no transactions
486
+
487
+ self.current_thread = threading.Thread(target=continuous_mine, daemon=True)
488
+ self.current_thread.start()
489
+ print("Started continuous block mining")
490
+ return True
491
+
492
+ def start_hybrid_mining(self, miner_address: str, bill_denominations: List[float] = None,
493
+ callback: Callable = None) -> bool:
494
+ """Start hybrid mining - both GTX bills and transaction blocks"""
495
+ if self.mining_active:
496
+ print("Mining already active")
497
+ return False
498
+
499
+ self.mining_active = True
500
+
501
+ def hybrid_mine():
502
+ # Mine GTX bills first if denominations provided
503
+ if bill_denominations:
504
+ for denomination in bill_denominations:
505
+ if not self.mining_active:
506
+ break
507
+
508
+ print(f"Mining GTX ${denomination:,} bill...")
509
+ bill_result = self.mine_bill(denomination, miner_address)
510
+
511
+ if callback:
512
+ callback({"type": "bill", "data": bill_result})
513
+
514
+ time.sleep(1)
515
+
516
+ # Switch to continuous block mining
517
+ block_height = self.blockchain_manager.get_blockchain_height() + 1
518
+ latest_block = self.blockchain_manager.get_latest_block()
519
+ previous_hash = latest_block.get('hash', '0' * 64) if latest_block else '0' * 64
520
+
521
+ while self.mining_active:
522
+ pending_count = len(self.mempool_manager.get_pending_transactions())
523
+
524
+ if pending_count > 0:
525
+ print(f"🔄 Mining transaction block #{block_height}...")
526
+
527
+ block_result = self.mine_transaction_block(miner_address, previous_hash, block_height)
528
+
529
+ if block_result.get("success"):
530
+ if callback:
531
+ callback({"type": "block", "data": block_result})
532
+
533
+ block_height += 1
534
+ previous_hash = block_result["block"]["hash"]
535
+
536
+ time.sleep(2)
537
+ else:
538
+ print("⏳ No transactions, checking again in 10s...")
539
+ time.sleep(10)
540
+
541
+ self.current_thread = threading.Thread(target=hybrid_mine, daemon=True)
542
+ self.current_thread.start()
543
+ print("Started hybrid mining (bills + blocks)")
544
+ return True
545
+
546
+ def get_mining_stats(self) -> Dict:
547
+ """Get comprehensive mining statistics"""
548
+ pending_txs = self.mempool_manager.get_pending_transactions()
549
+
550
+ return {
551
+ "mining_active": self.mining_active,
552
+ "bills_mined": self.mining_stats["bills_mined"],
553
+ "blocks_mined": self.mining_stats["blocks_mined"],
554
+ "total_mining_time": self.mining_stats["total_mining_time"],
555
+ "total_hash_attempts": self.mining_stats["total_hash_attempts"],
556
+ "mempool_size": len(pending_txs),
557
+ "pending_transactions": [
558
+ {
559
+ "hash": tx.get('hash', '')[:16] + '...',
560
+ "from": tx.get('from', ''),
561
+ "to": tx.get('to', ''),
562
+ "amount": tx.get('amount', 0),
563
+ "fee": tx.get('fee', 0),
564
+ "type": tx.get('type', 'unknown')
565
+ }
566
+ for tx in pending_txs[:5] # Show first 5
567
+ ],
568
+ "average_hashrate": (
569
+ self.mining_stats["total_hash_attempts"] / self.mining_stats["total_mining_time"]
570
+ if self.mining_stats["total_mining_time"] > 0 else 0
571
+ )
572
+ }
573
+
574
+ def stop_mining(self):
575
+ """Stop all mining activities"""
576
+ self.mining_active = False
577
+ if self.current_thread and self.current_thread.is_alive():
578
+ self.current_thread.join(timeout=5)
579
+ print("Mining stopped")
580
+
581
+ stats = self.get_mining_stats()
582
+ print(f"Final statistics:")
583
+ print(f"Bills mined: {stats['bills_mined']}")
584
+ print(f"Blocks mined: {stats['blocks_mined']}")
585
+ print(f"Total mining time: {stats['total_mining_time']:.2f}s")
586
+ print(f"Average hashrate: {stats['average_hashrate']:,.0f} H/s")
587
+ print(f"Mempool size: {stats['mempool_size']} transactions")
588
+
589
+ def submit_transaction(self, transaction: Dict) -> bool:
590
+ """Submit transaction to mempool for mining"""
591
+ try:
592
+ success = self.mempool_manager.add_transaction(transaction)
593
+ if success:
594
+ print(f"📨 Added transaction to mining mempool: {transaction.get('hash', '')[:16]}...")
595
+ return success
596
+ except Exception as e:
597
+ print(f"Error submitting transaction: {e}")
598
+ return False
599
+
600
+ def get_network_status(self) -> Dict:
601
+ """Get current network and blockchain status"""
602
+ try:
603
+ height = self.blockchain_manager.get_blockchain_height()
604
+ connected = self.blockchain_manager.check_network_connection()
605
+ mempool_size = len(self.mempool_manager.get_pending_transactions())
606
+
607
+ return {
608
+ "network_connected": connected,
609
+ "blockchain_height": height,
610
+ "mempool_size": mempool_size,
611
+ "mining_active": self.mining_active
612
+ }
613
+ except Exception as e:
614
+ return {
615
+ "network_connected": False,
616
+ "error": str(e)
617
+ }
@@ -0,0 +1,44 @@
1
+ # Core dependencies
2
+ requests>=2.31.0 # HTTP requests for blockchain API calls
3
+ cryptography>=41.0.0 # Encryption for wallet security
4
+ qrcode[pil]>=7.4.0 # QR code generation for addresses
5
+ Pillow>=10.0.0 # Image processing for QR codes
6
+
7
+ # Development and testing
8
+ pytest>=7.4.0 # Test framework
9
+ pytest-cov>=4.1.0 # Test coverage
10
+ pytest-mock>=3.11.0 # Mocking for tests
11
+ coverage>=7.0.0 # Coverage reporting
12
+
13
+ # Code quality and formatting
14
+ black>=23.0.0 # Code formatting
15
+ flake8>=6.0.0 # Linting
16
+ mypy>=1.5.0 # Type checking
17
+ isort>=5.12.0 # Import sorting
18
+ bandit>=1.7.0 # Security scanning
19
+
20
+ # Packaging and distribution
21
+ build>=0.10.0 # Package building
22
+ twine>=4.0.0 # Package uploading
23
+
24
+ # Documentation
25
+ sphinx>=7.0.0 # Documentation generation
26
+ sphinx-rtd-theme>=1.3.0 # ReadTheDocs theme
27
+
28
+ # Type stubs for better IDE support
29
+ types-requests>=2.31.0
30
+ typing-extensions>=4.8.0 # Additional type hints
31
+
32
+ # Optional GPU acceleration (choose one based on your hardware)
33
+ # Uncomment the appropriate line for your setup:
34
+
35
+ # NVIDIA CUDA 12.x (latest)
36
+ #cupy-cuda12x>=12.0.0
37
+
38
+ # NVIDIA CUDA 11.x
39
+ # cupy-cuda11x>=11.0.0
40
+
41
+ # AMD ROCm
42
+ # cupy-rocm-5-0>=12.0.0
43
+
44
+ # CPU-only fallback (slower but works everywhere)
File without changes