lunalib 1.2.3__py3-none-any.whl → 1.5.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.
- lunalib/core/blockchain.py +315 -150
- lunalib/core/crypto.py +265 -27
- lunalib/core/mempool.py +104 -102
- lunalib/core/sm2.py +723 -0
- lunalib/core/wallet.py +1026 -319
- lunalib/core/wallet_manager.py +638 -0
- lunalib/core/wallet_sync_helper.py +163 -0
- lunalib/mining/miner.py +24 -15
- lunalib/storage/cache.py +13 -4
- lunalib/storage/database.py +14 -5
- lunalib/storage/encryption.py +11 -2
- lunalib/transactions/security.py +96 -25
- lunalib/transactions/transactions.py +256 -431
- lunalib-1.5.2.dist-info/METADATA +20 -0
- lunalib-1.5.2.dist-info/RECORD +31 -0
- lunalib-1.5.2.dist-info/top_level.txt +1 -0
- core/__init__.py +0 -0
- core/blockchain.py +0 -172
- core/crypto.py +0 -32
- core/wallet.py +0 -347
- gtx/__init__.py +0 -0
- gtx/bill_registry.py +0 -122
- gtx/digital_bill.py +0 -273
- gtx/genesis.py +0 -338
- lunalib/requirements.txt +0 -44
- lunalib-1.2.3.dist-info/METADATA +0 -283
- lunalib-1.2.3.dist-info/RECORD +0 -50
- lunalib-1.2.3.dist-info/entry_points.txt +0 -2
- lunalib-1.2.3.dist-info/top_level.txt +0 -6
- mining/__init__.py +0 -0
- mining/cuda_manager.py +0 -137
- mining/difficulty.py +0 -106
- mining/miner.py +0 -107
- storage/__init__.py +0 -0
- storage/cache.py +0 -148
- storage/database.py +0 -222
- storage/encryption.py +0 -105
- transactions/__init__.py +0 -0
- transactions/security.py +0 -172
- transactions/transactions.py +0 -379
- transactions/validator.py +0 -71
- {lunalib-1.2.3.dist-info → lunalib-1.5.2.dist-info}/WHEEL +0 -0
lunalib-1.2.3.dist-info/RECORD
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
core/blockchain.py,sha256=KHlw1KsBUd1wkmxDunyyJiZMOlUx-Vr4wiDTl8YXdlo,6711
|
|
3
|
-
core/crypto.py,sha256=rBqSbr12Lh_0FdaYQ6XqLA4k8zdZb6MJs-eAjauwm1Q,1202
|
|
4
|
-
core/wallet.py,sha256=R3LVUqGaI42gDw_8lxYFsTetpVwvQvuWeMDsoO6t1eE,13934
|
|
5
|
-
gtx/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
-
gtx/bill_registry.py,sha256=J1TivYIzmJEVQHNJrZxqOOEbUSlJs7rQIXfSA90ztL4,4333
|
|
7
|
-
gtx/digital_bill.py,sha256=EnQvAztMNE9uHuxXWmShEpNl084y-clHagK5s1Amvpc,10614
|
|
8
|
-
gtx/genesis.py,sha256=U6CEWcLAR1kb0CfhNQyFMIzh350OeQNNnWxycVJpPWc,15353
|
|
9
|
-
lunalib/__init__.py,sha256=fEvoHvfcC6ilDGQrhXaVmcdB4yDmuijxz6YZHkjbuBg,527
|
|
10
|
-
lunalib/cli.py,sha256=SyuJIhvqld-XL9ks9XFOuyqVb44qyBUbahlqE_RDVkM,524
|
|
11
|
-
lunalib/luna_lib.py,sha256=ue9Bs93xjpg7_GHSUJPKBhf8nF5YcbCIdoMIu-jDgG4,2748
|
|
12
|
-
lunalib/requirements.txt,sha256=3vNUgubGo8tCgeq5HwdGQcwrABxKthSlYsVp_76ckzw,1576
|
|
13
|
-
lunalib/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
|
-
lunalib/core/blockchain.py,sha256=EiWGgy9aJTW7zrxgtxLSv1H1X3A-8v6ISINQEzf1yY0,30178
|
|
15
|
-
lunalib/core/crypto.py,sha256=rBqSbr12Lh_0FdaYQ6XqLA4k8zdZb6MJs-eAjauwm1Q,1202
|
|
16
|
-
lunalib/core/mempool.py,sha256=N8va24VwQOvzbFcO5c99fDchjYZ3Fm70BkS8XSAg7yo,15373
|
|
17
|
-
lunalib/core/wallet.py,sha256=uXyu4RwBB5Xv8_jfHk5roTV9R6RlwVvsQGPFiM7-JjQ,26969
|
|
18
|
-
lunalib/gtx/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
|
-
lunalib/gtx/bill_registry.py,sha256=J1TivYIzmJEVQHNJrZxqOOEbUSlJs7rQIXfSA90ztL4,4333
|
|
20
|
-
lunalib/gtx/digital_bill.py,sha256=EnQvAztMNE9uHuxXWmShEpNl084y-clHagK5s1Amvpc,10614
|
|
21
|
-
lunalib/gtx/genesis.py,sha256=Mic48kI93fzMoz3Zm8xXGk8MXqUhfpLsNFLs8-ZJdCE,15939
|
|
22
|
-
lunalib/mining/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
23
|
-
lunalib/mining/cuda_manager.py,sha256=PUnmVvpu98OTZNdKIIYpVXnY__Ng4pHyZoh8wU-tDCM,5174
|
|
24
|
-
lunalib/mining/difficulty.py,sha256=tzIYmdcm1Xr9-8wyTwwkXJvJoGDyE77o_nu9d81VGvI,3927
|
|
25
|
-
lunalib/mining/miner.py,sha256=rH7Bhm378Rro4FlLqts3qYemHormtFnvz-R9SgJ0eu4,27520
|
|
26
|
-
lunalib/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
27
|
-
lunalib/storage/cache.py,sha256=1lNAeUop7ZanyjDUBSLJR6B0ATe6c_Kj0NAU9PAG2P0,4997
|
|
28
|
-
lunalib/storage/database.py,sha256=TjK9xUE8QRsUn3EqNHny1qyddUVlgTJFzhNCw8td7IM,7859
|
|
29
|
-
lunalib/storage/encryption.py,sha256=i_99Qk3I_gAZXwx00tL2Gy5mcALaDUC8olXZJUPAqMw,4054
|
|
30
|
-
lunalib/transactions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
31
|
-
lunalib/transactions/security.py,sha256=j23f2xjSaslQDD83_skdTSTL6FGEFD91D8xOaD6gf_M,6716
|
|
32
|
-
lunalib/transactions/transactions.py,sha256=JuSAQtEhKljFuuZe6zLGNWjUHwOM_fiBo0p4xAfFTFg,25014
|
|
33
|
-
lunalib/transactions/validator.py,sha256=FQ-jVjj8VoVTlq65blB_hprAwJOtpc2peYdQk_L2xmg,2730
|
|
34
|
-
mining/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
35
|
-
mining/cuda_manager.py,sha256=PUnmVvpu98OTZNdKIIYpVXnY__Ng4pHyZoh8wU-tDCM,5174
|
|
36
|
-
mining/difficulty.py,sha256=tzIYmdcm1Xr9-8wyTwwkXJvJoGDyE77o_nu9d81VGvI,3927
|
|
37
|
-
mining/miner.py,sha256=-Zlu6jWmW4YcFZDTz_sw_ZkvdXM-69gE89aOO7VWs2A,3800
|
|
38
|
-
storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
39
|
-
storage/cache.py,sha256=1lNAeUop7ZanyjDUBSLJR6B0ATe6c_Kj0NAU9PAG2P0,4997
|
|
40
|
-
storage/database.py,sha256=TjK9xUE8QRsUn3EqNHny1qyddUVlgTJFzhNCw8td7IM,7859
|
|
41
|
-
storage/encryption.py,sha256=i_99Qk3I_gAZXwx00tL2Gy5mcALaDUC8olXZJUPAqMw,4054
|
|
42
|
-
transactions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
43
|
-
transactions/security.py,sha256=j23f2xjSaslQDD83_skdTSTL6FGEFD91D8xOaD6gf_M,6716
|
|
44
|
-
transactions/transactions.py,sha256=M0SXPtqCLXDUsSDjqE3M16UeU3FEC_gr63ISKh0VQNA,15877
|
|
45
|
-
transactions/validator.py,sha256=FQ-jVjj8VoVTlq65blB_hprAwJOtpc2peYdQk_L2xmg,2730
|
|
46
|
-
lunalib-1.2.3.dist-info/METADATA,sha256=zmI7cZKFmbEu1q6iChYkXjTE438LV5Mv5NvYdSmYl5k,9689
|
|
47
|
-
lunalib-1.2.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
48
|
-
lunalib-1.2.3.dist-info/entry_points.txt,sha256=bdt2wU-9FZOkmQ2pSy46WrxJSkpRPhVDkRFL1K_kakQ,49
|
|
49
|
-
lunalib-1.2.3.dist-info/top_level.txt,sha256=jEsGPJDTyYkwfmrSSw1GvJ1UxcPvChzv0s6xx-PvaXg,45
|
|
50
|
-
lunalib-1.2.3.dist-info/RECORD,,
|
mining/__init__.py
DELETED
|
File without changes
|
mining/cuda_manager.py
DELETED
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
import time
|
|
2
|
-
from typing import Optional, Dict, Any
|
|
3
|
-
import hashlib
|
|
4
|
-
import json
|
|
5
|
-
|
|
6
|
-
try:
|
|
7
|
-
import cupy as cp
|
|
8
|
-
CUDA_AVAILABLE = True
|
|
9
|
-
except ImportError:
|
|
10
|
-
CUDA_AVAILABLE = False
|
|
11
|
-
cp = None
|
|
12
|
-
|
|
13
|
-
class CUDAManager:
|
|
14
|
-
"""Manages CUDA acceleration for mining operations"""
|
|
15
|
-
|
|
16
|
-
def __init__(self):
|
|
17
|
-
self.cuda_available = self._check_cuda()
|
|
18
|
-
self.device = None
|
|
19
|
-
|
|
20
|
-
if self.cuda_available:
|
|
21
|
-
self._initialize_cuda()
|
|
22
|
-
|
|
23
|
-
def _check_cuda(self) -> bool:
|
|
24
|
-
"""Check if CUDA is available"""
|
|
25
|
-
try:
|
|
26
|
-
if not CUDA_AVAILABLE:
|
|
27
|
-
return False
|
|
28
|
-
|
|
29
|
-
if cp.cuda.runtime.getDeviceCount() > 0:
|
|
30
|
-
print("✅ CUDA is available for accelerated mining")
|
|
31
|
-
return True
|
|
32
|
-
else:
|
|
33
|
-
print("❌ CUDA drivers found but no GPU available")
|
|
34
|
-
return False
|
|
35
|
-
except Exception as e:
|
|
36
|
-
print(f"❌ CUDA check failed: {e}")
|
|
37
|
-
return False
|
|
38
|
-
|
|
39
|
-
def _initialize_cuda(self):
|
|
40
|
-
"""Initialize CUDA device"""
|
|
41
|
-
try:
|
|
42
|
-
self.device = cp.cuda.Device(0)
|
|
43
|
-
self.device.use()
|
|
44
|
-
print(f"✅ Using CUDA device: {cp.cuda.runtime.getDeviceProperties(0)['name']}")
|
|
45
|
-
except Exception as e:
|
|
46
|
-
print(f"❌ CUDA initialization failed: {e}")
|
|
47
|
-
self.cuda_available = False
|
|
48
|
-
|
|
49
|
-
def cuda_mine_batch(self, mining_data: Dict, difficulty: int, batch_size: int = 100000) -> Optional[Dict]:
|
|
50
|
-
"""Mine using CUDA acceleration"""
|
|
51
|
-
if not self.cuda_available:
|
|
52
|
-
return None
|
|
53
|
-
|
|
54
|
-
try:
|
|
55
|
-
target = "0" * difficulty
|
|
56
|
-
nonce_start = 0
|
|
57
|
-
start_time = time.time()
|
|
58
|
-
|
|
59
|
-
while True:
|
|
60
|
-
# Prepare batch data for GPU
|
|
61
|
-
nonces = cp.arange(nonce_start, nonce_start + batch_size, dtype=cp.uint64)
|
|
62
|
-
mining_strings = self._prepare_mining_batch(mining_data, nonces)
|
|
63
|
-
|
|
64
|
-
# Compute hashes on GPU
|
|
65
|
-
hashes = self._compute_hashes_gpu(mining_strings)
|
|
66
|
-
|
|
67
|
-
# Check for successful hash
|
|
68
|
-
for i, hash_hex in enumerate(hashes):
|
|
69
|
-
if hash_hex.startswith(target):
|
|
70
|
-
mining_time = time.time() - start_time
|
|
71
|
-
successful_nonce = nonce_start + i
|
|
72
|
-
|
|
73
|
-
return {
|
|
74
|
-
"success": True,
|
|
75
|
-
"hash": hash_hex,
|
|
76
|
-
"nonce": int(successful_nonce),
|
|
77
|
-
"mining_time": mining_time,
|
|
78
|
-
"method": "cuda"
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
nonce_start += batch_size
|
|
82
|
-
|
|
83
|
-
# Progress update
|
|
84
|
-
if nonce_start % (batch_size * 10) == 0:
|
|
85
|
-
current_time = time.time()
|
|
86
|
-
hashrate = nonce_start / (current_time - start_time)
|
|
87
|
-
print(f"⏳ CUDA: {nonce_start:,} attempts | {hashrate:,.0f} H/s")
|
|
88
|
-
|
|
89
|
-
except Exception as e:
|
|
90
|
-
print(f"CUDA mining error: {e}")
|
|
91
|
-
|
|
92
|
-
return None
|
|
93
|
-
|
|
94
|
-
def _prepare_mining_batch(self, mining_data: Dict, nonces) -> Any:
|
|
95
|
-
"""Prepare batch mining data for GPU"""
|
|
96
|
-
mining_strings = []
|
|
97
|
-
|
|
98
|
-
for nonce in nonces:
|
|
99
|
-
mining_data["nonce"] = int(nonce)
|
|
100
|
-
data_string = json.dumps(mining_data, sort_keys=True)
|
|
101
|
-
mining_strings.append(data_string.encode())
|
|
102
|
-
|
|
103
|
-
return cp.array(mining_strings)
|
|
104
|
-
|
|
105
|
-
def _compute_hashes_gpu(self, mining_strings) -> list:
|
|
106
|
-
"""Compute SHA256 hashes on GPU"""
|
|
107
|
-
# Convert to CuPy array if needed
|
|
108
|
-
if not isinstance(mining_strings, cp.ndarray):
|
|
109
|
-
mining_strings = cp.array(mining_strings)
|
|
110
|
-
|
|
111
|
-
# This is a simplified implementation
|
|
112
|
-
# In a real implementation, you'd use proper CUDA kernels
|
|
113
|
-
hashes = []
|
|
114
|
-
for data in mining_strings:
|
|
115
|
-
# For now, fall back to CPU hashing
|
|
116
|
-
# A real implementation would use CUDA-accelerated hashing
|
|
117
|
-
hash_obj = hashlib.sha256(data.tobytes())
|
|
118
|
-
hashes.append(hash_obj.hexdigest())
|
|
119
|
-
|
|
120
|
-
return hashes
|
|
121
|
-
|
|
122
|
-
def get_cuda_info(self) -> Dict[str, Any]:
|
|
123
|
-
"""Get CUDA device information"""
|
|
124
|
-
if not self.cuda_available:
|
|
125
|
-
return {"available": False}
|
|
126
|
-
|
|
127
|
-
try:
|
|
128
|
-
props = cp.cuda.runtime.getDeviceProperties(0)
|
|
129
|
-
return {
|
|
130
|
-
"available": True,
|
|
131
|
-
"device_name": props.get('name', 'Unknown'),
|
|
132
|
-
"compute_capability": f"{props.get('major', 0)}.{props.get('minor', 0)}",
|
|
133
|
-
"total_memory": props.get('totalGlobalMem', 0),
|
|
134
|
-
"multiprocessors": props.get('multiProcessorCount', 0)
|
|
135
|
-
}
|
|
136
|
-
except Exception as e:
|
|
137
|
-
return {"available": False, "error": str(e)}
|
mining/difficulty.py
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
# difficulty.py
|
|
2
|
-
class DifficultySystem:
|
|
3
|
-
"""9-tier difficulty system for mining and transactions"""
|
|
4
|
-
|
|
5
|
-
def get_bill_difficulty(self, denomination):
|
|
6
|
-
"""Get mining difficulty based on bill denomination - 9 tiers"""
|
|
7
|
-
if denomination <= 0:
|
|
8
|
-
return 1 # Handle negative/zero amounts
|
|
9
|
-
elif denomination <= 1:
|
|
10
|
-
return 1 # Trivial
|
|
11
|
-
elif denomination <= 10:
|
|
12
|
-
return 2 # Very Easy
|
|
13
|
-
elif denomination <= 100:
|
|
14
|
-
return 3 # Easy
|
|
15
|
-
elif denomination <= 1000:
|
|
16
|
-
return 4 # Moderate
|
|
17
|
-
elif denomination <= 10000:
|
|
18
|
-
return 5 # Standard
|
|
19
|
-
elif denomination <= 100000:
|
|
20
|
-
return 6 # Challenging
|
|
21
|
-
elif denomination <= 1000000:
|
|
22
|
-
return 7 # Hard
|
|
23
|
-
elif denomination <= 10000000:
|
|
24
|
-
return 8 # Very Hard
|
|
25
|
-
else:
|
|
26
|
-
return 9 # Extreme
|
|
27
|
-
|
|
28
|
-
def get_transaction_difficulty(self, amount):
|
|
29
|
-
"""Get transaction difficulty based on amount - 9 tiers"""
|
|
30
|
-
if amount <= 0:
|
|
31
|
-
return 1 # Handle negative/zero amounts
|
|
32
|
-
elif amount <= 0.001:
|
|
33
|
-
return 1 # Trivial
|
|
34
|
-
elif amount <= 0.01:
|
|
35
|
-
return 2 # Very Easy
|
|
36
|
-
elif amount <= 0.1:
|
|
37
|
-
return 3 # Easy
|
|
38
|
-
elif amount <= 1.0:
|
|
39
|
-
return 4 # Moderate
|
|
40
|
-
elif amount <= 10.0:
|
|
41
|
-
return 5 # Standard
|
|
42
|
-
elif amount <= 100.0:
|
|
43
|
-
return 6 # Challenging
|
|
44
|
-
elif amount <= 1000.0:
|
|
45
|
-
return 7 # Hard
|
|
46
|
-
elif amount <= 10000.0:
|
|
47
|
-
return 8 # Very Hard
|
|
48
|
-
else:
|
|
49
|
-
return 9 # Extreme
|
|
50
|
-
|
|
51
|
-
def calculate_mining_reward(self, denomination, mining_time):
|
|
52
|
-
"""Calculate mining reward with time-based bonus"""
|
|
53
|
-
if denomination <= 0:
|
|
54
|
-
return 0
|
|
55
|
-
|
|
56
|
-
base_reward = denomination # Full denomination as base reward
|
|
57
|
-
|
|
58
|
-
# Time bonus - faster mining gets higher reward
|
|
59
|
-
if mining_time < 10:
|
|
60
|
-
time_bonus = 0.5 # 50% bonus for very fast mining
|
|
61
|
-
elif mining_time < 30:
|
|
62
|
-
time_bonus = 0.2 # 20% bonus for fast mining
|
|
63
|
-
else:
|
|
64
|
-
time_bonus = 0.0 # No bonus for slow mining
|
|
65
|
-
|
|
66
|
-
return base_reward * (1 + time_bonus)
|
|
67
|
-
|
|
68
|
-
def get_difficulty_name(self, difficulty_level):
|
|
69
|
-
"""Get human-readable name for difficulty level"""
|
|
70
|
-
names = {
|
|
71
|
-
1: "Trivial",
|
|
72
|
-
2: "Very Easy",
|
|
73
|
-
3: "Easy",
|
|
74
|
-
4: "Moderate",
|
|
75
|
-
5: "Standard",
|
|
76
|
-
6: "Challenging",
|
|
77
|
-
7: "Hard",
|
|
78
|
-
8: "Very Hard",
|
|
79
|
-
9: "Extreme"
|
|
80
|
-
}
|
|
81
|
-
return names.get(difficulty_level, "Unknown")
|
|
82
|
-
|
|
83
|
-
def get_difficulty_color(self, difficulty_level):
|
|
84
|
-
"""Get color representation for difficulty level"""
|
|
85
|
-
colors = {
|
|
86
|
-
1: "🟢", # Green - Trivial
|
|
87
|
-
2: "🟢", # Green - Very Easy
|
|
88
|
-
3: "🟡", # Yellow - Easy
|
|
89
|
-
4: "🟡", # Yellow - Moderate
|
|
90
|
-
5: "🟠", # Orange - Standard
|
|
91
|
-
6: "🟠", # Orange - Challenging
|
|
92
|
-
7: "🔴", # Red - Hard
|
|
93
|
-
8: "🔴", # Red - Very Hard
|
|
94
|
-
9: "💀" # Skull - Extreme
|
|
95
|
-
}
|
|
96
|
-
return colors.get(difficulty_level, "⚫")
|
|
97
|
-
|
|
98
|
-
def get_expected_mining_time(self, difficulty_level, hashrate=1000000):
|
|
99
|
-
"""Get expected mining time in seconds based on difficulty and hashrate"""
|
|
100
|
-
if difficulty_level < 1 or difficulty_level > 9:
|
|
101
|
-
return float('inf')
|
|
102
|
-
|
|
103
|
-
# Rough estimate: each difficulty level increases time by ~16x
|
|
104
|
-
base_time = 0.1 # base time for difficulty 1
|
|
105
|
-
time_multiplier = 16 ** (difficulty_level - 1)
|
|
106
|
-
return base_time * time_multiplier / max(1, hashrate / 1000000)
|
mining/miner.py
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import time
|
|
2
|
-
import hashlib
|
|
3
|
-
import json
|
|
4
|
-
import threading
|
|
5
|
-
from typing import Dict, Optional
|
|
6
|
-
from mining.difficulty import DifficultySystem
|
|
7
|
-
from gtx.digital_bill import DigitalBill
|
|
8
|
-
|
|
9
|
-
class GenesisMiner:
|
|
10
|
-
"""Mines GTX Genesis bills with configurable difficulty"""
|
|
11
|
-
|
|
12
|
-
def __init__(self):
|
|
13
|
-
self.difficulty_system = DifficultySystem()
|
|
14
|
-
self.mining_active = False
|
|
15
|
-
self.current_thread = None
|
|
16
|
-
|
|
17
|
-
def mine_bill(self, denomination, user_address, bill_data=None):
|
|
18
|
-
"""Mine a GTX Genesis bill"""
|
|
19
|
-
difficulty = self.difficulty_system.get_bill_difficulty(denomination)
|
|
20
|
-
|
|
21
|
-
digital_bill = DigitalBill(
|
|
22
|
-
denomination=denomination,
|
|
23
|
-
user_address=user_address,
|
|
24
|
-
difficulty=difficulty,
|
|
25
|
-
bill_data=bill_data or {}
|
|
26
|
-
)
|
|
27
|
-
|
|
28
|
-
print(f"⛏️ Mining GTX ${denomination:,} Bill - Difficulty: {difficulty} zeros")
|
|
29
|
-
|
|
30
|
-
start_time = time.time()
|
|
31
|
-
mining_result = self._perform_mining(digital_bill, difficulty)
|
|
32
|
-
|
|
33
|
-
if mining_result["success"]:
|
|
34
|
-
mining_time = time.time() - start_time
|
|
35
|
-
bill = digital_bill.finalize(
|
|
36
|
-
hash=mining_result["hash"],
|
|
37
|
-
nonce=mining_result["nonce"],
|
|
38
|
-
mining_time=mining_time
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
print(f"✅ Successfully mined GTX ${denomination:,} bill!")
|
|
42
|
-
print(f"⏱️ Mining time: {mining_time:.2f}s")
|
|
43
|
-
|
|
44
|
-
return bill
|
|
45
|
-
else:
|
|
46
|
-
return {"success": False, "error": "Mining failed"}
|
|
47
|
-
|
|
48
|
-
def _perform_mining(self, digital_bill, difficulty):
|
|
49
|
-
"""Perform proof-of-work mining"""
|
|
50
|
-
target = "0" * difficulty
|
|
51
|
-
nonce = 0
|
|
52
|
-
start_time = time.time()
|
|
53
|
-
|
|
54
|
-
while self.mining_active:
|
|
55
|
-
mining_data = digital_bill.get_mining_data(nonce)
|
|
56
|
-
data_string = json.dumps(mining_data, sort_keys=True)
|
|
57
|
-
bill_hash = hashlib.sha256(data_string.encode()).hexdigest()
|
|
58
|
-
|
|
59
|
-
if bill_hash.startswith(target):
|
|
60
|
-
mining_time = time.time() - start_time
|
|
61
|
-
return {
|
|
62
|
-
"success": True,
|
|
63
|
-
"hash": bill_hash,
|
|
64
|
-
"nonce": nonce,
|
|
65
|
-
"mining_time": mining_time
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
nonce += 1
|
|
69
|
-
|
|
70
|
-
# Progress updates
|
|
71
|
-
if nonce % 100000 == 0:
|
|
72
|
-
current_time = time.time()
|
|
73
|
-
hashrate = nonce / (current_time - start_time)
|
|
74
|
-
print(f"⏳ Attempts: {nonce:,} | Rate: {hashrate:,.0f} H/s")
|
|
75
|
-
|
|
76
|
-
return {"success": False, "error": "Mining stopped"}
|
|
77
|
-
|
|
78
|
-
def start_auto_mining(self, denominations, user_address, callback=None):
|
|
79
|
-
"""Start auto-mining multiple bills"""
|
|
80
|
-
self.mining_active = True
|
|
81
|
-
|
|
82
|
-
def auto_mine():
|
|
83
|
-
results = []
|
|
84
|
-
for denomination in denominations:
|
|
85
|
-
if not self.mining_active:
|
|
86
|
-
break
|
|
87
|
-
|
|
88
|
-
result = self.mine_bill(denomination, user_address)
|
|
89
|
-
results.append(result)
|
|
90
|
-
|
|
91
|
-
if callback:
|
|
92
|
-
callback(result)
|
|
93
|
-
|
|
94
|
-
time.sleep(1)
|
|
95
|
-
|
|
96
|
-
return results
|
|
97
|
-
|
|
98
|
-
self.current_thread = threading.Thread(target=auto_mine, daemon=True)
|
|
99
|
-
self.current_thread.start()
|
|
100
|
-
return True
|
|
101
|
-
|
|
102
|
-
def stop_mining(self):
|
|
103
|
-
"""Stop all mining activities"""
|
|
104
|
-
self.mining_active = False
|
|
105
|
-
if self.current_thread:
|
|
106
|
-
self.current_thread.join(timeout=5)
|
|
107
|
-
print("🛑 Mining stopped")
|
storage/__init__.py
DELETED
|
File without changes
|
storage/cache.py
DELETED
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import sqlite3
|
|
3
|
-
import pickle
|
|
4
|
-
import gzip
|
|
5
|
-
import time
|
|
6
|
-
from typing import Dict, List, Optional
|
|
7
|
-
|
|
8
|
-
class BlockchainCache:
|
|
9
|
-
"""Caches blockchain data to avoid repeated network requests"""
|
|
10
|
-
|
|
11
|
-
def __init__(self, cache_dir=None):
|
|
12
|
-
if cache_dir is None:
|
|
13
|
-
cache_dir = os.path.join(os.path.expanduser("~"), ".luna_wallet")
|
|
14
|
-
self.cache_dir = cache_dir
|
|
15
|
-
self.cache_file = os.path.join(cache_dir, "blockchain_cache.db")
|
|
16
|
-
self._init_cache()
|
|
17
|
-
|
|
18
|
-
def _init_cache(self):
|
|
19
|
-
"""Initialize cache database"""
|
|
20
|
-
conn = sqlite3.connect(self.cache_file)
|
|
21
|
-
cursor = conn.cursor()
|
|
22
|
-
|
|
23
|
-
cursor.execute('''
|
|
24
|
-
CREATE TABLE IF NOT EXISTS blocks (
|
|
25
|
-
height INTEGER PRIMARY KEY,
|
|
26
|
-
hash TEXT UNIQUE,
|
|
27
|
-
block_data BLOB,
|
|
28
|
-
timestamp REAL,
|
|
29
|
-
last_accessed REAL
|
|
30
|
-
)
|
|
31
|
-
''')
|
|
32
|
-
|
|
33
|
-
cursor.execute('''
|
|
34
|
-
CREATE TABLE IF NOT EXISTS mempool (
|
|
35
|
-
tx_hash TEXT PRIMARY KEY,
|
|
36
|
-
tx_data BLOB,
|
|
37
|
-
received_time REAL,
|
|
38
|
-
address_involved TEXT
|
|
39
|
-
)
|
|
40
|
-
''')
|
|
41
|
-
|
|
42
|
-
cursor.execute('''
|
|
43
|
-
CREATE TABLE IF NOT EXISTS cache_meta (
|
|
44
|
-
key TEXT PRIMARY KEY,
|
|
45
|
-
value TEXT
|
|
46
|
-
)
|
|
47
|
-
''')
|
|
48
|
-
|
|
49
|
-
conn.commit()
|
|
50
|
-
conn.close()
|
|
51
|
-
|
|
52
|
-
def save_block(self, height: int, block_hash: str, block_data: Dict):
|
|
53
|
-
"""Save block to cache"""
|
|
54
|
-
try:
|
|
55
|
-
conn = sqlite3.connect(self.cache_file)
|
|
56
|
-
cursor = conn.cursor()
|
|
57
|
-
|
|
58
|
-
compressed_data = gzip.compress(pickle.dumps(block_data))
|
|
59
|
-
|
|
60
|
-
cursor.execute('''
|
|
61
|
-
INSERT OR REPLACE INTO blocks
|
|
62
|
-
(height, hash, block_data, timestamp, last_accessed)
|
|
63
|
-
VALUES (?, ?, ?, ?, ?)
|
|
64
|
-
''', (height, block_hash, compressed_data, time.time(), time.time()))
|
|
65
|
-
|
|
66
|
-
conn.commit()
|
|
67
|
-
conn.close()
|
|
68
|
-
except Exception as e:
|
|
69
|
-
print(f"Cache save error: {e}")
|
|
70
|
-
|
|
71
|
-
def get_block(self, height: int) -> Optional[Dict]:
|
|
72
|
-
"""Get block from cache"""
|
|
73
|
-
try:
|
|
74
|
-
conn = sqlite3.connect(self.cache_file)
|
|
75
|
-
cursor = conn.cursor()
|
|
76
|
-
|
|
77
|
-
cursor.execute('SELECT block_data FROM blocks WHERE height = ?', (height,))
|
|
78
|
-
result = cursor.fetchone()
|
|
79
|
-
|
|
80
|
-
if result:
|
|
81
|
-
# Update access time
|
|
82
|
-
cursor.execute('UPDATE blocks SET last_accessed = ? WHERE height = ?',
|
|
83
|
-
(time.time(), height))
|
|
84
|
-
conn.commit()
|
|
85
|
-
conn.close()
|
|
86
|
-
|
|
87
|
-
return pickle.loads(gzip.decompress(result[0]))
|
|
88
|
-
|
|
89
|
-
conn.close()
|
|
90
|
-
except Exception as e:
|
|
91
|
-
print(f"Cache read error: {e}")
|
|
92
|
-
|
|
93
|
-
return None
|
|
94
|
-
|
|
95
|
-
def get_block_range(self, start_height: int, end_height: int) -> List[Dict]:
|
|
96
|
-
"""Get multiple blocks from cache"""
|
|
97
|
-
blocks = []
|
|
98
|
-
try:
|
|
99
|
-
conn = sqlite3.connect(self.cache_file)
|
|
100
|
-
cursor = conn.cursor()
|
|
101
|
-
|
|
102
|
-
cursor.execute('''
|
|
103
|
-
SELECT height, block_data FROM blocks
|
|
104
|
-
WHERE height BETWEEN ? AND ?
|
|
105
|
-
ORDER BY height
|
|
106
|
-
''', (start_height, end_height))
|
|
107
|
-
|
|
108
|
-
results = cursor.fetchall()
|
|
109
|
-
conn.close()
|
|
110
|
-
|
|
111
|
-
for height, block_data in results:
|
|
112
|
-
try:
|
|
113
|
-
block = pickle.loads(gzip.decompress(block_data))
|
|
114
|
-
blocks.append(block)
|
|
115
|
-
except:
|
|
116
|
-
continue
|
|
117
|
-
|
|
118
|
-
except Exception as e:
|
|
119
|
-
print(f"Block range cache error: {e}")
|
|
120
|
-
|
|
121
|
-
return blocks
|
|
122
|
-
|
|
123
|
-
def get_highest_cached_height(self) -> int:
|
|
124
|
-
"""Get the highest block height in cache"""
|
|
125
|
-
try:
|
|
126
|
-
conn = sqlite3.connect(self.cache_file)
|
|
127
|
-
cursor = conn.cursor()
|
|
128
|
-
|
|
129
|
-
cursor.execute('SELECT MAX(height) FROM blocks')
|
|
130
|
-
result = cursor.fetchone()
|
|
131
|
-
conn.close()
|
|
132
|
-
|
|
133
|
-
return result[0] if result[0] is not None else -1
|
|
134
|
-
except:
|
|
135
|
-
return -1
|
|
136
|
-
|
|
137
|
-
def clear_old_blocks(self, max_age_hours=24):
|
|
138
|
-
"""Clear blocks older than specified hours"""
|
|
139
|
-
try:
|
|
140
|
-
cutoff = time.time() - (max_age_hours * 3600)
|
|
141
|
-
conn = sqlite3.connect(self.cache_file)
|
|
142
|
-
cursor = conn.cursor()
|
|
143
|
-
|
|
144
|
-
cursor.execute('DELETE FROM blocks WHERE last_accessed < ?', (cutoff,))
|
|
145
|
-
conn.commit()
|
|
146
|
-
conn.close()
|
|
147
|
-
except Exception as e:
|
|
148
|
-
print(f"Cache cleanup error: {e}")
|