lunalib 1.5.1__py3-none-any.whl → 1.7.2__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 (48) hide show
  1. lunalib/core/__init__.py +14 -0
  2. lunalib/core/blockchain.py +183 -3
  3. lunalib/core/daemon.py +494 -0
  4. lunalib/core/p2p.py +361 -0
  5. lunalib/core/sm2.py +723 -723
  6. lunalib/core/wallet.py +714 -478
  7. lunalib/core/wallet_manager.py +638 -638
  8. lunalib/core/wallet_sync_helper.py +163 -163
  9. lunalib/gtx/digital_bill.py +10 -2
  10. lunalib/gtx/genesis.py +23 -24
  11. lunalib/mining/__init__.py +5 -0
  12. lunalib/mining/cuda_manager.py +23 -28
  13. lunalib/mining/difficulty.py +38 -0
  14. lunalib/mining/miner.py +526 -17
  15. lunalib/storage/cache.py +13 -4
  16. lunalib/storage/database.py +14 -5
  17. lunalib/storage/encryption.py +11 -2
  18. lunalib/transactions/security.py +19 -10
  19. lunalib/transactions/transactions.py +50 -41
  20. lunalib-1.7.2.dist-info/METADATA +27 -0
  21. lunalib-1.7.2.dist-info/RECORD +33 -0
  22. lunalib-1.7.2.dist-info/top_level.txt +1 -0
  23. core/__init__.py +0 -0
  24. core/blockchain.py +0 -172
  25. core/crypto.py +0 -32
  26. core/wallet.py +0 -408
  27. gtx/__init__.py +0 -0
  28. gtx/bill_registry.py +0 -122
  29. gtx/digital_bill.py +0 -273
  30. gtx/genesis.py +0 -338
  31. lunalib/requirements.txt +0 -44
  32. lunalib-1.5.1.dist-info/METADATA +0 -283
  33. lunalib-1.5.1.dist-info/RECORD +0 -53
  34. lunalib-1.5.1.dist-info/entry_points.txt +0 -2
  35. lunalib-1.5.1.dist-info/top_level.txt +0 -6
  36. mining/__init__.py +0 -0
  37. mining/cuda_manager.py +0 -137
  38. mining/difficulty.py +0 -106
  39. mining/miner.py +0 -107
  40. storage/__init__.py +0 -0
  41. storage/cache.py +0 -148
  42. storage/database.py +0 -222
  43. storage/encryption.py +0 -105
  44. transactions/__init__.py +0 -0
  45. transactions/security.py +0 -172
  46. transactions/transactions.py +0 -424
  47. transactions/validator.py +0 -71
  48. {lunalib-1.5.1.dist-info → lunalib-1.7.2.dist-info}/WHEEL +0 -0
lunalib/core/__init__.py CHANGED
@@ -0,0 +1,14 @@
1
+ from .blockchain import BlockchainManager
2
+ from .wallet import LunaWallet
3
+ from .mempool import MempoolManager
4
+ from .p2p import P2PClient, HybridBlockchainClient
5
+ from .daemon import BlockchainDaemon
6
+
7
+ __all__ = [
8
+ 'BlockchainManager',
9
+ 'LunaWallet',
10
+ 'MempoolManager',
11
+ 'P2PClient',
12
+ 'HybridBlockchainClient',
13
+ 'BlockchainDaemon'
14
+ ]
@@ -4,17 +4,23 @@ from ..storage.cache import BlockchainCache
4
4
  import requests
5
5
  import time
6
6
  import json
7
- from typing import Dict, List, Optional, Tuple
7
+ import asyncio
8
+ import threading
9
+ from concurrent.futures import ThreadPoolExecutor, Future
10
+ from typing import Dict, List, Optional, Tuple, Callable
8
11
 
9
12
 
10
13
  class BlockchainManager:
11
14
  """Manages blockchain interactions and scanning with transaction broadcasting"""
12
15
 
13
- def __init__(self, endpoint_url="https://bank.linglin.art"):
16
+ def __init__(self, endpoint_url="https://bank.linglin.art", max_workers=10):
14
17
  self.endpoint_url = endpoint_url.rstrip('/')
15
18
  self.cache = BlockchainCache()
16
19
  self.network_connected = False
17
20
  self._stop_events = [] # Track background monitors so they can be stopped
21
+ self.executor = ThreadPoolExecutor(max_workers=max_workers, thread_name_prefix="BlockchainWorker")
22
+ self._async_tasks = {} # Track async tasks by ID
23
+ self._task_callbacks = {} # Callbacks for task completion
18
24
 
19
25
  # ------------------------------------------------------------------
20
26
  # Address helpers
@@ -26,6 +32,30 @@ class BlockchainManager:
26
32
  addr_str = str(addr).strip("'\" ").lower()
27
33
  return addr_str[4:] if addr_str.startswith('lun_') else addr_str
28
34
 
35
+ def broadcast_transaction_async(self, transaction: Dict, callback: Callable = None) -> str:
36
+ """Async version: Broadcast transaction in background thread
37
+
38
+ Returns: task_id that can be used to check status
39
+ """
40
+ task_id = f"broadcast_{transaction.get('hash', 'unknown')}_{int(time.time())}"
41
+
42
+ def _broadcast_task():
43
+ try:
44
+ success, message = self.broadcast_transaction(transaction)
45
+ if callback:
46
+ callback(success=success, result=message, error=None if success else message)
47
+ return (success, message)
48
+ except Exception as e:
49
+ print(f"❌ Async broadcast error: {e}")
50
+ if callback:
51
+ callback(success=False, result=None, error=str(e))
52
+ return (False, str(e))
53
+
54
+ future = self.executor.submit(_broadcast_task)
55
+ self._async_tasks[task_id] = future
56
+ print(f"🔄 Started async broadcast: {task_id}")
57
+ return task_id
58
+
29
59
  def broadcast_transaction(self, transaction: Dict) -> Tuple[bool, str]:
30
60
  """Broadcast transaction to mempool with enhanced error handling"""
31
61
  try:
@@ -210,6 +240,30 @@ class BlockchainManager:
210
240
 
211
241
  return None
212
242
 
243
+ def get_blocks_range_async(self, start_height: int, end_height: int, callback: Callable = None) -> str:
244
+ """Async version: Get range of blocks in background thread
245
+
246
+ Returns: task_id that can be used to check status
247
+ """
248
+ task_id = f"blocks_range_{start_height}_{end_height}_{int(time.time())}"
249
+
250
+ def _fetch_task():
251
+ try:
252
+ result = self.get_blocks_range(start_height, end_height)
253
+ if callback:
254
+ callback(success=True, result=result, error=None)
255
+ return result
256
+ except Exception as e:
257
+ print(f"❌ Async blocks fetch error: {e}")
258
+ if callback:
259
+ callback(success=False, result=None, error=str(e))
260
+ return None
261
+
262
+ future = self.executor.submit(_fetch_task)
263
+ self._async_tasks[task_id] = future
264
+ print(f"🔄 Started async blocks fetch: {task_id}")
265
+ return task_id
266
+
213
267
  def get_blocks_range(self, start_height: int, end_height: int) -> List[Dict]:
214
268
  """Get range of blocks"""
215
269
  blocks = []
@@ -286,6 +340,31 @@ class BlockchainManager:
286
340
 
287
341
  print(f"[SCAN] Found {len(transactions)} total transactions for {address}")
288
342
  return transactions
343
+
344
+ def scan_transactions_for_address_async(self, address: str, callback: Callable = None,
345
+ start_height: int = 0, end_height: int = None) -> str:
346
+ """Async version: Scan blockchain in background thread, call callback when done
347
+
348
+ Returns: task_id that can be used to check status
349
+ """
350
+ task_id = f"scan_{address}_{int(time.time())}"
351
+
352
+ def _scan_task():
353
+ try:
354
+ result = self.scan_transactions_for_address(address, start_height, end_height)
355
+ if callback:
356
+ callback(success=True, result=result, error=None)
357
+ return result
358
+ except Exception as e:
359
+ print(f"❌ Async scan error: {e}")
360
+ if callback:
361
+ callback(success=False, result=None, error=str(e))
362
+ return None
363
+
364
+ future = self.executor.submit(_scan_task)
365
+ self._async_tasks[task_id] = future
366
+ print(f"🔄 Started async scan task: {task_id}")
367
+ return task_id
289
368
 
290
369
  def scan_transactions_for_addresses(self, addresses: List[str], start_height: int = 0, end_height: int = None) -> Dict[str, List[Dict]]:
291
370
  """Scan the blockchain once for multiple addresses (rewards and transfers)."""
@@ -328,7 +407,84 @@ class BlockchainManager:
328
407
  print(f" - {addr}: {len(results[addr])} transactions")
329
408
 
330
409
  return results
410
+
411
+ def scan_transactions_for_addresses_async(self, addresses: List[str], callback: Callable = None,
412
+ start_height: int = 0, end_height: int = None) -> str:
413
+ """Async version: Scan blockchain for multiple addresses in background thread
414
+
415
+ Returns: task_id that can be used to check status
416
+ """
417
+ task_id = f"multi_scan_{int(time.time())}"
418
+
419
+ def _scan_task():
420
+ try:
421
+ result = self.scan_transactions_for_addresses(addresses, start_height, end_height)
422
+ if callback:
423
+ callback(success=True, result=result, error=None)
424
+ return result
425
+ except Exception as e:
426
+ print(f"❌ Async multi-scan error: {e}")
427
+ if callback:
428
+ callback(success=False, result=None, error=str(e))
429
+ return None
430
+
431
+ future = self.executor.submit(_scan_task)
432
+ self._async_tasks[task_id] = future
433
+ print(f"🔄 Started async multi-scan task: {task_id}")
434
+ return task_id
331
435
 
436
+ def get_task_status(self, task_id: str) -> Dict:
437
+ """Check status of an async task
438
+
439
+ Returns: {'status': 'running'|'completed'|'failed'|'not_found', 'result': any, 'error': str}
440
+ """
441
+ if task_id not in self._async_tasks:
442
+ return {'status': 'not_found', 'result': None, 'error': 'Task not found'}
443
+
444
+ future = self._async_tasks[task_id]
445
+
446
+ if future.running():
447
+ return {'status': 'running', 'result': None, 'error': None}
448
+ elif future.done():
449
+ try:
450
+ result = future.result(timeout=0)
451
+ return {'status': 'completed', 'result': result, 'error': None}
452
+ except Exception as e:
453
+ return {'status': 'failed', 'result': None, 'error': str(e)}
454
+ else:
455
+ return {'status': 'pending', 'result': None, 'error': None}
456
+
457
+ def cancel_task(self, task_id: str) -> bool:
458
+ """Cancel a running async task
459
+
460
+ Returns: True if cancelled, False otherwise
461
+ """
462
+ if task_id in self._async_tasks:
463
+ future = self._async_tasks[task_id]
464
+ if future.cancel():
465
+ del self._async_tasks[task_id]
466
+ print(f"✅ Task cancelled: {task_id}")
467
+ return True
468
+ return False
469
+
470
+ def get_active_tasks(self) -> List[str]:
471
+ """Get list of active task IDs"""
472
+ return [task_id for task_id, future in self._async_tasks.items() if future.running()]
473
+
474
+ def cleanup_completed_tasks(self):
475
+ """Remove completed tasks from tracking"""
476
+ completed = [task_id for task_id, future in self._async_tasks.items() if future.done()]
477
+ for task_id in completed:
478
+ del self._async_tasks[task_id]
479
+ if completed:
480
+ print(f"🧹 Cleaned up {len(completed)} completed tasks")
481
+
482
+ def shutdown(self):
483
+ """Shutdown the thread pool executor"""
484
+ print("🛑 Shutting down BlockchainManager executor...")
485
+ self.executor.shutdown(wait=True)
486
+ print("✅ Executor shutdown complete")
487
+
332
488
  def monitor_addresses(self, addresses: List[str], on_update, poll_interval: int = 15):
333
489
  """Start background monitor for addresses; returns a stop event."""
334
490
  import threading
@@ -379,6 +535,30 @@ class BlockchainManager:
379
535
  thread.start()
380
536
  return stop_event
381
537
 
538
+ def submit_mined_block_async(self, block_data: Dict, callback: Callable = None) -> str:
539
+ """Async version: Submit mined block in background thread
540
+
541
+ Returns: task_id that can be used to check status
542
+ """
543
+ task_id = f"submit_block_{block_data.get('index', 'unknown')}_{int(time.time())}"
544
+
545
+ def _submit_task():
546
+ try:
547
+ success = self.submit_mined_block(block_data)
548
+ if callback:
549
+ callback(success=success, result=block_data if success else None, error=None if success else "Submission failed")
550
+ return success
551
+ except Exception as e:
552
+ print(f"❌ Async block submission error: {e}")
553
+ if callback:
554
+ callback(success=False, result=None, error=str(e))
555
+ return False
556
+
557
+ future = self.executor.submit(_submit_task)
558
+ self._async_tasks[task_id] = future
559
+ print(f"🔄 Started async block submission: {task_id}")
560
+ return task_id
561
+
382
562
  def submit_mined_block(self, block_data: Dict) -> bool:
383
563
  """Submit a mined block to the network with built-in validation"""
384
564
  try:
@@ -736,7 +916,7 @@ class BlockchainManager:
736
916
  transactions.append(enhanced_tx)
737
917
  print(f"⬇️ Found outgoing transaction: {amount} LUN + {fee} fee")
738
918
 
739
- print(f"📊 Scan complete for block #{block.get('index')}: {len(transactions)} transactions found")
919
+ print(f" Scan complete for block #{block.get('index')}: {len(transactions)} transactions found")
740
920
  return transactions
741
921
  def _handle_regular_transfers(self, tx: Dict, address_lower: str) -> Dict:
742
922
  """Handle regular transfer transactions that might be in different formats"""