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.
- lunalib/core/__init__.py +14 -0
- lunalib/core/blockchain.py +183 -3
- lunalib/core/daemon.py +494 -0
- lunalib/core/p2p.py +361 -0
- lunalib/core/sm2.py +723 -723
- lunalib/core/wallet.py +714 -478
- lunalib/core/wallet_manager.py +638 -638
- lunalib/core/wallet_sync_helper.py +163 -163
- lunalib/gtx/digital_bill.py +10 -2
- lunalib/gtx/genesis.py +23 -24
- lunalib/mining/__init__.py +5 -0
- lunalib/mining/cuda_manager.py +23 -28
- lunalib/mining/difficulty.py +38 -0
- lunalib/mining/miner.py +526 -17
- lunalib/storage/cache.py +13 -4
- lunalib/storage/database.py +14 -5
- lunalib/storage/encryption.py +11 -2
- lunalib/transactions/security.py +19 -10
- lunalib/transactions/transactions.py +50 -41
- lunalib-1.7.2.dist-info/METADATA +27 -0
- lunalib-1.7.2.dist-info/RECORD +33 -0
- lunalib-1.7.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 -408
- 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.5.1.dist-info/METADATA +0 -283
- lunalib-1.5.1.dist-info/RECORD +0 -53
- lunalib-1.5.1.dist-info/entry_points.txt +0 -2
- lunalib-1.5.1.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 -424
- transactions/validator.py +0 -71
- {lunalib-1.5.1.dist-info → lunalib-1.7.2.dist-info}/WHEEL +0 -0
lunalib/storage/database.py
CHANGED
|
@@ -3,6 +3,15 @@ import sqlite3
|
|
|
3
3
|
import json
|
|
4
4
|
import time
|
|
5
5
|
from typing import Dict, List, Optional, Any
|
|
6
|
+
import sys
|
|
7
|
+
|
|
8
|
+
# --- Unicode-safe print for Windows console ---
|
|
9
|
+
def safe_print(*args, **kwargs):
|
|
10
|
+
try:
|
|
11
|
+
print(*args, **kwargs)
|
|
12
|
+
except UnicodeEncodeError:
|
|
13
|
+
encoding = getattr(sys.stdout, 'encoding', 'utf-8')
|
|
14
|
+
print(*(str(a).encode(encoding, errors='replace').decode(encoding) for a in args), **kwargs)
|
|
6
15
|
|
|
7
16
|
class WalletDatabase:
|
|
8
17
|
"""Manages wallet data storage"""
|
|
@@ -96,7 +105,7 @@ class WalletDatabase:
|
|
|
96
105
|
return True
|
|
97
106
|
|
|
98
107
|
except Exception as e:
|
|
99
|
-
|
|
108
|
+
safe_print(f"Save wallet error: {e}")
|
|
100
109
|
return False
|
|
101
110
|
|
|
102
111
|
def load_wallet(self, address: str) -> Optional[Dict]:
|
|
@@ -122,7 +131,7 @@ class WalletDatabase:
|
|
|
122
131
|
}
|
|
123
132
|
|
|
124
133
|
except Exception as e:
|
|
125
|
-
|
|
134
|
+
safe_print(f"Load wallet error: {e}")
|
|
126
135
|
|
|
127
136
|
return None
|
|
128
137
|
|
|
@@ -157,7 +166,7 @@ class WalletDatabase:
|
|
|
157
166
|
return True
|
|
158
167
|
|
|
159
168
|
except Exception as e:
|
|
160
|
-
|
|
169
|
+
safe_print(f"Save transaction error: {e}")
|
|
161
170
|
return False
|
|
162
171
|
|
|
163
172
|
def get_wallet_transactions(self, wallet_address: str, limit: int = 100) -> List[Dict]:
|
|
@@ -187,7 +196,7 @@ class WalletDatabase:
|
|
|
187
196
|
return transactions
|
|
188
197
|
|
|
189
198
|
except Exception as e:
|
|
190
|
-
|
|
199
|
+
safe_print(f"Get transactions error: {e}")
|
|
191
200
|
return []
|
|
192
201
|
|
|
193
202
|
def save_pending_transaction(self, transaction: Dict, wallet_address: str) -> bool:
|
|
@@ -218,5 +227,5 @@ class WalletDatabase:
|
|
|
218
227
|
return True
|
|
219
228
|
|
|
220
229
|
except Exception as e:
|
|
221
|
-
|
|
230
|
+
safe_print(f"Save pending transaction error: {e}")
|
|
222
231
|
return False
|
lunalib/storage/encryption.py
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import json
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
# --- Unicode-safe print for Windows console ---
|
|
6
|
+
def safe_print(*args, **kwargs):
|
|
7
|
+
try:
|
|
8
|
+
print(*args, **kwargs)
|
|
9
|
+
except UnicodeEncodeError:
|
|
10
|
+
encoding = getattr(sys.stdout, 'encoding', 'utf-8')
|
|
11
|
+
print(*(str(a).encode(encoding, errors='replace').decode(encoding) for a in args), **kwargs)
|
|
3
12
|
import base64
|
|
4
13
|
import hashlib
|
|
5
14
|
from cryptography.fernet import Fernet
|
|
@@ -37,7 +46,7 @@ class EncryptionManager:
|
|
|
37
46
|
}
|
|
38
47
|
|
|
39
48
|
except Exception as e:
|
|
40
|
-
|
|
49
|
+
safe_print(f"Encryption error: {e}")
|
|
41
50
|
return {}
|
|
42
51
|
|
|
43
52
|
def decrypt_wallet(self, encrypted_data: Dict, password: str) -> Optional[Dict]:
|
|
@@ -65,7 +74,7 @@ class EncryptionManager:
|
|
|
65
74
|
return wallet_data
|
|
66
75
|
|
|
67
76
|
except Exception as e:
|
|
68
|
-
|
|
77
|
+
safe_print(f"Decryption error: {e}")
|
|
69
78
|
return None
|
|
70
79
|
|
|
71
80
|
def _derive_key(self, password: str) -> bytes:
|
lunalib/transactions/security.py
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import time
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
# --- Unicode-safe print for Windows console ---
|
|
5
|
+
def safe_print(*args, **kwargs):
|
|
6
|
+
try:
|
|
7
|
+
print(*args, **kwargs)
|
|
8
|
+
except UnicodeEncodeError:
|
|
9
|
+
encoding = getattr(sys.stdout, 'encoding', 'utf-8')
|
|
10
|
+
print(*(str(a).encode(encoding, errors='replace').decode(encoding) for a in args), **kwargs)
|
|
2
11
|
import hashlib
|
|
3
12
|
from typing import Dict, Tuple
|
|
4
13
|
|
|
@@ -17,11 +26,11 @@ class TransactionSecurity:
|
|
|
17
26
|
from ..core.crypto import KeyManager as SM2KeyManager
|
|
18
27
|
self.key_manager = SM2KeyManager()
|
|
19
28
|
self.sm2_available = True
|
|
20
|
-
|
|
29
|
+
safe_print("[SECURITY] SM2 KeyManager loaded successfully")
|
|
21
30
|
except ImportError as e:
|
|
22
31
|
self.key_manager = None
|
|
23
32
|
self.sm2_available = False
|
|
24
|
-
|
|
33
|
+
safe_print(f"[SECURITY] SM2 KeyManager not available: {e}")
|
|
25
34
|
|
|
26
35
|
def validate_transaction_security(self, transaction: Dict) -> Tuple[bool, str]:
|
|
27
36
|
"""Comprehensive transaction security validation with SM2"""
|
|
@@ -114,22 +123,22 @@ class TransactionSecurity:
|
|
|
114
123
|
|
|
115
124
|
# For unsigned test transactions
|
|
116
125
|
if signature in ["system", "unsigned", "test"]:
|
|
117
|
-
|
|
126
|
+
safe_print(f"[SECURITY] Skipping signature check for system/unsigned transaction")
|
|
118
127
|
return True
|
|
119
128
|
|
|
120
129
|
# Check SM2 signature length (should be 128 hex chars = 64 bytes)
|
|
121
130
|
if len(signature) != 128:
|
|
122
|
-
|
|
131
|
+
safe_print(f"[SECURITY] Invalid SM2 signature length: {len(signature)} (expected 128)")
|
|
123
132
|
return False
|
|
124
133
|
|
|
125
134
|
# Check if all characters are valid hex
|
|
126
135
|
if not all(c in "0123456789abcdefABCDEF" for c in signature):
|
|
127
|
-
|
|
136
|
+
safe_print(f"[SECURITY] Signature contains non-hex characters")
|
|
128
137
|
return False
|
|
129
138
|
|
|
130
139
|
# Check public key format (should start with '04' for uncompressed)
|
|
131
140
|
if not public_key.startswith('04'):
|
|
132
|
-
|
|
141
|
+
safe_print(f"[SECURITY] Invalid public key format: {public_key[:20]}...")
|
|
133
142
|
return False
|
|
134
143
|
|
|
135
144
|
# Use KeyManager for verification if available
|
|
@@ -139,15 +148,15 @@ class TransactionSecurity:
|
|
|
139
148
|
|
|
140
149
|
# Verify signature
|
|
141
150
|
is_valid = self.key_manager.verify_signature(signing_data, signature, public_key)
|
|
142
|
-
|
|
151
|
+
safe_print(f"[SECURITY] SM2 signature verification: {is_valid}")
|
|
143
152
|
return is_valid
|
|
144
153
|
|
|
145
154
|
# Fallback: Basic format check if SM2 not available
|
|
146
|
-
|
|
155
|
+
safe_print(f"[SECURITY] SM2 not available, using basic signature validation")
|
|
147
156
|
return len(signature) == 128 and signature.startswith(('04', '03', '02'))
|
|
148
157
|
|
|
149
158
|
except Exception as e:
|
|
150
|
-
|
|
159
|
+
safe_print(f"[SECURITY] Signature validation error: {e}")
|
|
151
160
|
return False
|
|
152
161
|
|
|
153
162
|
def _get_signing_data(self, transaction: Dict) -> str:
|
|
@@ -174,7 +183,7 @@ class TransactionSecurity:
|
|
|
174
183
|
|
|
175
184
|
def _validate_signature(self, transaction: Dict) -> bool:
|
|
176
185
|
"""Legacy signature validation (for backward compatibility)"""
|
|
177
|
-
|
|
186
|
+
safe_print(f"[SECURITY] Using legacy signature validation")
|
|
178
187
|
return self._validate_signature_sm2(transaction)
|
|
179
188
|
|
|
180
189
|
def _check_rate_limit(self, address: str) -> bool:
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# lunalib/transactions/transactions.py
|
|
2
2
|
import time
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
# --- Unicode-safe print for Windows console ---
|
|
6
|
+
def safe_print(*args, **kwargs):
|
|
7
|
+
try:
|
|
8
|
+
print(*args, **kwargs)
|
|
9
|
+
except UnicodeEncodeError:
|
|
10
|
+
encoding = getattr(sys.stdout, 'encoding', 'utf-8')
|
|
11
|
+
print(*(str(a).encode(encoding, errors='replace').decode(encoding) for a in args), **kwargs)
|
|
3
12
|
import hashlib
|
|
4
13
|
import json
|
|
5
14
|
from typing import Dict, Optional, Tuple, List
|
|
@@ -9,10 +18,10 @@ from ..core.mempool import MempoolManager
|
|
|
9
18
|
try:
|
|
10
19
|
from ..core.crypto import KeyManager as SM2KeyManager
|
|
11
20
|
SM2_AVAILABLE = True
|
|
12
|
-
|
|
21
|
+
safe_print("DEBUG: Using SM2 KeyManager from crypto module")
|
|
13
22
|
except ImportError as e:
|
|
14
23
|
SM2_AVAILABLE = False
|
|
15
|
-
|
|
24
|
+
safe_print(f"WARNING: SM2 KeyManager not available: {e}")
|
|
16
25
|
|
|
17
26
|
class TransactionSecurity:
|
|
18
27
|
"""Transaction security validation and risk assessment"""
|
|
@@ -71,7 +80,7 @@ class TransactionManager:
|
|
|
71
80
|
if SM2_AVAILABLE:
|
|
72
81
|
self.key_manager = SM2KeyManager()
|
|
73
82
|
else:
|
|
74
|
-
|
|
83
|
+
safe_print("ERROR: SM2 KeyManager not available - cannot sign transactions")
|
|
75
84
|
self.key_manager = None
|
|
76
85
|
|
|
77
86
|
def create_transaction(self, from_address: str, to_address: str, amount: float,
|
|
@@ -99,33 +108,33 @@ class TransactionManager:
|
|
|
99
108
|
# Sign the transaction data
|
|
100
109
|
tx_string = self._get_signing_data(transaction)
|
|
101
110
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
111
|
+
safe_print(f"[TRANSACTIONS CREATE DEBUG] Signing data: {tx_string}")
|
|
112
|
+
safe_print(f"[TRANSACTIONS CREATE DEBUG] Private key available: {bool(private_key)}")
|
|
113
|
+
safe_print(f"[TRANSACTIONS CREATE DEBUG] Private key length: {len(private_key)}")
|
|
105
114
|
|
|
106
115
|
signature = self.key_manager.sign_data(tx_string, private_key)
|
|
107
116
|
|
|
108
117
|
# Get public key from private key
|
|
109
118
|
public_key = self.key_manager.derive_public_key(private_key)
|
|
110
119
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
120
|
+
safe_print(f"[TRANSACTIONS CREATE DEBUG] Generated signature: {signature}")
|
|
121
|
+
safe_print(f"[TRANSACTIONS CREATE DEBUG] Generated public key: {public_key}")
|
|
122
|
+
safe_print(f"[TRANSACTIONS CREATE DEBUG] Signature length: {len(signature)}")
|
|
123
|
+
safe_print(f"[TRANSACTIONS CREATE DEBUG] Public key length: {len(public_key)}")
|
|
115
124
|
|
|
116
125
|
transaction["signature"] = signature
|
|
117
126
|
transaction["public_key"] = public_key
|
|
118
127
|
|
|
119
128
|
# Immediately test verification
|
|
120
129
|
test_verify = self.key_manager.verify_signature(tx_string, signature, public_key)
|
|
121
|
-
|
|
130
|
+
safe_print(f"[TRANSACTIONS CREATE DEBUG] Immediate self-verification: {test_verify}")
|
|
122
131
|
|
|
123
132
|
if not test_verify:
|
|
124
|
-
|
|
125
|
-
|
|
133
|
+
safe_print(f"[TRANSACTIONS CREATE ERROR] Signature doesn't verify immediately!")
|
|
134
|
+
safe_print(f"[TRANSACTIONS CREATE ERROR] This suggests an SM2 implementation issue")
|
|
126
135
|
|
|
127
136
|
except Exception as e:
|
|
128
|
-
|
|
137
|
+
safe_print(f"[TRANSACTIONS CREATE ERROR] Signing failed: {e}")
|
|
129
138
|
import traceback
|
|
130
139
|
traceback.print_exc()
|
|
131
140
|
transaction["signature"] = "unsigned"
|
|
@@ -226,55 +235,55 @@ class TransactionManager:
|
|
|
226
235
|
|
|
227
236
|
# System transactions are always valid
|
|
228
237
|
if signature in ["system", "unsigned", "test"]:
|
|
229
|
-
|
|
238
|
+
safe_print(f"[TRANSACTIONS] Skipping signature check for {signature} transaction")
|
|
230
239
|
return True
|
|
231
240
|
|
|
232
241
|
if not self.key_manager:
|
|
233
|
-
|
|
242
|
+
safe_print("[TRANSACTIONS] No key manager available for verification")
|
|
234
243
|
return False
|
|
235
244
|
|
|
236
245
|
# Check SM2 signature format
|
|
237
246
|
if len(signature) != 128:
|
|
238
|
-
|
|
247
|
+
safe_print(f"[TRANSACTIONS] Invalid SM2 signature length: {len(signature)} (expected 128)")
|
|
239
248
|
return False
|
|
240
249
|
|
|
241
250
|
# Get signing data (without public_key!)
|
|
242
251
|
sign_data = self._get_signing_data(transaction)
|
|
243
252
|
public_key = transaction.get("public_key", "")
|
|
244
253
|
|
|
245
|
-
|
|
246
|
-
|
|
254
|
+
safe_print(f"[TRANSACTIONS VERIFY] Signing data length: {len(sign_data)}")
|
|
255
|
+
safe_print(f"[TRANSACTIONS VERIFY] Signing data (first 100 chars): {sign_data[:100]}")
|
|
247
256
|
|
|
248
257
|
# Try to verify with KeyManager
|
|
249
|
-
|
|
258
|
+
safe_print(f"[TRANSACTIONS] Attempting verification...")
|
|
250
259
|
is_valid = self.key_manager.verify_signature(sign_data, signature, public_key)
|
|
251
260
|
|
|
252
|
-
|
|
261
|
+
safe_print(f"[TRANSACTIONS] SM2 signature verification result: {is_valid}")
|
|
253
262
|
|
|
254
263
|
return is_valid
|
|
255
264
|
|
|
256
265
|
except Exception as e:
|
|
257
|
-
|
|
266
|
+
safe_print(f"[TRANSACTIONS] Verification error: {e}")
|
|
258
267
|
import traceback
|
|
259
268
|
traceback.print_exc()
|
|
260
269
|
return False
|
|
261
270
|
def _debug_signature_issue(self, transaction: Dict, sign_data: str, signature: str, public_key: str):
|
|
262
271
|
"""Debug why signature verification is failing"""
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
272
|
+
safe_print("\n" + "="*60)
|
|
273
|
+
safe_print("DEBUGGING SIGNATURE ISSUE")
|
|
274
|
+
safe_print("="*60)
|
|
266
275
|
|
|
267
276
|
# 1. Check if we can sign and verify a simple test
|
|
268
|
-
|
|
277
|
+
safe_print("\n1. Testing SM2 with simple message...")
|
|
269
278
|
test_message = "Simple test message"
|
|
270
279
|
test_private = self.key_manager.generate_private_key()
|
|
271
280
|
test_public = self.key_manager.derive_public_key(test_private)
|
|
272
281
|
test_sig = self.key_manager.sign_data(test_message, test_private)
|
|
273
282
|
test_valid = self.key_manager.verify_signature(test_message, test_sig, test_public)
|
|
274
|
-
|
|
283
|
+
safe_print(f" Simple test verification: {test_valid}")
|
|
275
284
|
|
|
276
285
|
# 2. Try to recreate what was signed during transaction creation
|
|
277
|
-
|
|
286
|
+
safe_print("\n2. Reconstructing original transaction data...")
|
|
278
287
|
# Create the exact transaction data that should have been signed
|
|
279
288
|
reconstructed = {
|
|
280
289
|
"amount": float(transaction["amount"]),
|
|
@@ -289,23 +298,23 @@ class TransactionManager:
|
|
|
289
298
|
|
|
290
299
|
import json
|
|
291
300
|
reconstructed_json = json.dumps(reconstructed, sort_keys=True)
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
301
|
+
safe_print(f" Reconstructed JSON: {reconstructed_json}")
|
|
302
|
+
safe_print(f" Current signing data: {sign_data}")
|
|
303
|
+
safe_print(f" Are they equal? {reconstructed_json == sign_data}")
|
|
304
|
+
safe_print(f" Length difference: {len(reconstructed_json)} vs {len(sign_data)}")
|
|
296
305
|
|
|
297
306
|
# 3. Check for whitespace differences
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
307
|
+
safe_print("\n3. Checking for whitespace differences...")
|
|
308
|
+
safe_print(f" Reconstructed has spaces: {' ' in reconstructed_json}")
|
|
309
|
+
safe_print(f" Sign data has spaces: {' ' in sign_data}")
|
|
301
310
|
|
|
302
311
|
# 4. Check float formatting
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
312
|
+
safe_print("\n4. Checking float formatting...")
|
|
313
|
+
safe_print(f" Amount in tx: {transaction['amount']} (type: {type(transaction['amount'])})")
|
|
314
|
+
safe_print(f" Amount in reconstructed: {reconstructed['amount']} (type: {type(reconstructed['amount'])})")
|
|
306
315
|
|
|
307
316
|
# 5. Try different JSON serialization options
|
|
308
|
-
|
|
317
|
+
safe_print("\n5. Trying different JSON formats...")
|
|
309
318
|
formats = [
|
|
310
319
|
("Compact", lambda x: json.dumps(x, sort_keys=True, separators=(',', ':'))),
|
|
311
320
|
("Default", lambda x: json.dumps(x, sort_keys=True)),
|
|
@@ -315,9 +324,9 @@ class TransactionManager:
|
|
|
315
324
|
for name, formatter in formats:
|
|
316
325
|
formatted = formatter(reconstructed)
|
|
317
326
|
is_valid_test = self.key_manager.verify_signature(formatted, signature, public_key)
|
|
318
|
-
|
|
327
|
+
safe_print(f" {name} format: {is_valid_test} (length: {len(formatted)})")
|
|
319
328
|
|
|
320
|
-
|
|
329
|
+
safe_print("="*60 + "\n")
|
|
321
330
|
def assess_transaction_risk(self, transaction: Dict) -> Tuple[str, str]:
|
|
322
331
|
"""Assess transaction risk level"""
|
|
323
332
|
return self.security.assess_risk(transaction)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: lunalib
|
|
3
|
+
Version: 1.7.2
|
|
4
|
+
Summary: Cryptocurrency Ecosystem library (LunaLib)
|
|
5
|
+
Home-page:
|
|
6
|
+
Author: Ling Lin
|
|
7
|
+
Author-email:
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.7
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
Requires-Dist: cryptography
|
|
14
|
+
Requires-Dist: requests
|
|
15
|
+
Requires-Dist: numpy
|
|
16
|
+
Requires-Dist: pytest
|
|
17
|
+
Requires-Dist: pandas
|
|
18
|
+
Requires-Dist: base58
|
|
19
|
+
Dynamic: author
|
|
20
|
+
Dynamic: classifier
|
|
21
|
+
Dynamic: description
|
|
22
|
+
Dynamic: description-content-type
|
|
23
|
+
Dynamic: requires-dist
|
|
24
|
+
Dynamic: requires-python
|
|
25
|
+
Dynamic: summary
|
|
26
|
+
|
|
27
|
+
A modular cryptocurrency ecosystem library including blockchain, wallet, mining, storage, and transaction management.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
lunalib/__init__.py,sha256=fEvoHvfcC6ilDGQrhXaVmcdB4yDmuijxz6YZHkjbuBg,527
|
|
2
|
+
lunalib/cli.py,sha256=SyuJIhvqld-XL9ks9XFOuyqVb44qyBUbahlqE_RDVkM,524
|
|
3
|
+
lunalib/luna_lib.py,sha256=ue9Bs93xjpg7_GHSUJPKBhf8nF5YcbCIdoMIu-jDgG4,2748
|
|
4
|
+
lunalib/core/__init__.py,sha256=V86B0jI8snFIg8yCyd_Qoi2Tl6elQn_1cT-oeR6Ig3s,361
|
|
5
|
+
lunalib/core/blockchain.py,sha256=yhK_PcyYuH5rAAbRZar-8DbF2kMWde7Ku2TOa1FIbrE,44530
|
|
6
|
+
lunalib/core/crypto.py,sha256=R_f2sj7ASNnMW8Dtf2LIWTw-vCUjXD33zJPqPcPQVB8,10684
|
|
7
|
+
lunalib/core/daemon.py,sha256=VhEky7-h-mwCBVFJp7DtoMkpvmGbdcbuoG9qNkbEvbg,21048
|
|
8
|
+
lunalib/core/mempool.py,sha256=itYFGQEuUde0Xh6WXcEz_n8hDsNhxkEAlRQ5g_Qiygg,14845
|
|
9
|
+
lunalib/core/p2p.py,sha256=cj3dda05oL6W5oMsvJ_HT3U0qr1FL6DR-YI78k3InKg,13784
|
|
10
|
+
lunalib/core/sm2.py,sha256=Eq8Er3XQW5rYJXwaPT5vw5NoVXbSWhyuvjoG1LMo-NQ,23454
|
|
11
|
+
lunalib/core/wallet.py,sha256=RCLim7zvAU_Dze5zRJBaYh-ISAMXaZE2NwPU2BtxTwo,62131
|
|
12
|
+
lunalib/core/wallet_manager.py,sha256=KK58hrr_xF1vZ4qI6x_BJqrs9XXh5m0XbZYnZmi9yoU,26031
|
|
13
|
+
lunalib/core/wallet_sync_helper.py,sha256=CGfSBXvf8vg4SGsLaxsjGwHVbD9dmfcuMrZ_CO0J5lE,6282
|
|
14
|
+
lunalib/gtx/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
|
+
lunalib/gtx/bill_registry.py,sha256=J1TivYIzmJEVQHNJrZxqOOEbUSlJs7rQIXfSA90ztL4,4333
|
|
16
|
+
lunalib/gtx/digital_bill.py,sha256=xi2d7RVBGFwDOr8ulMCgvXXebHKl9LeeW9f5H4j_P_A,10977
|
|
17
|
+
lunalib/gtx/genesis.py,sha256=dDiLz-jW0zr5WUifYo9lzsrafQGOuZ9oakv_TX6QdPg,16028
|
|
18
|
+
lunalib/mining/__init__.py,sha256=kOwXt_fwjHLUvV3XxieG2LZyKMW316brXLF8V8lHBUo,193
|
|
19
|
+
lunalib/mining/cuda_manager.py,sha256=VjVx9KLhT2F1jOOhva8ioGP32oQIAciZjf1irWl1jJY,5136
|
|
20
|
+
lunalib/mining/difficulty.py,sha256=hKCtvEovb4le5Fnhz6Mm8-Cugjm_CduJnZA2aNC2eyU,5326
|
|
21
|
+
lunalib/mining/miner.py,sha256=WP5UBOajLYT9JzAjLAshwq-f8CsLKYdLJpUX9kY2PdI,48898
|
|
22
|
+
lunalib/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
23
|
+
lunalib/storage/cache.py,sha256=U-riY8OTzxCOpl8yvhpbU3YUysEKgrPlmhO4F4cI9FM,5352
|
|
24
|
+
lunalib/storage/database.py,sha256=2f3Ie6JnuK7L0YGtAdZt5mgj90pokneXhSQKUyvx8Pc,8219
|
|
25
|
+
lunalib/storage/encryption.py,sha256=59g8vFFPAkc_L7t2TXas9Rs4oB3JB1t5ikmDbs4aaqM,4399
|
|
26
|
+
lunalib/transactions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
27
|
+
lunalib/transactions/security.py,sha256=cQJRasJ37Z8mJo8gt0JJOb0_M9CQ0QScr67y3M_NP4Q,10309
|
|
28
|
+
lunalib/transactions/transactions.py,sha256=3PgyW8gDQwY-gAPGY_T3m7RE_9HzEIOjTf6CWCsOKFY,18151
|
|
29
|
+
lunalib/transactions/validator.py,sha256=FQ-jVjj8VoVTlq65blB_hprAwJOtpc2peYdQk_L2xmg,2730
|
|
30
|
+
lunalib-1.7.2.dist-info/METADATA,sha256=mGCHaUW-45XaO5hJtKzFaE-WmJi9UDDTxMpSPcmlfQg,797
|
|
31
|
+
lunalib-1.7.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
32
|
+
lunalib-1.7.2.dist-info/top_level.txt,sha256=eLcoOCtOwfvoqUu5g5CNBZB9bdhGXbTwmjuOM7i8ylw,8
|
|
33
|
+
lunalib-1.7.2.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
lunalib
|
core/__init__.py
DELETED
|
File without changes
|
core/blockchain.py
DELETED
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
from storage.cache import BlockchainCache
|
|
2
|
-
import requests
|
|
3
|
-
import time
|
|
4
|
-
import json
|
|
5
|
-
from typing import Dict, List, Optional, Tuple
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class BlockchainManager:
|
|
9
|
-
"""Manages blockchain interactions and scanning"""
|
|
10
|
-
|
|
11
|
-
def __init__(self, endpoint_url="https://bank.linglin.art"):
|
|
12
|
-
self.endpoint_url = endpoint_url.rstrip('/')
|
|
13
|
-
self.cache = BlockchainCache()
|
|
14
|
-
self.network_connected = False
|
|
15
|
-
|
|
16
|
-
def get_blockchain_height(self) -> int:
|
|
17
|
-
"""Get current blockchain height"""
|
|
18
|
-
try:
|
|
19
|
-
# Try height endpoint first
|
|
20
|
-
response = requests.get(f'{self.endpoint_url}/blockchain/height', timeout=10)
|
|
21
|
-
if response.status_code == 200:
|
|
22
|
-
data = response.json()
|
|
23
|
-
return data.get('height', 0)
|
|
24
|
-
|
|
25
|
-
# Fallback to blocks endpoint
|
|
26
|
-
response = requests.get(f'{self.endpoint_url}/blockchain/blocks', timeout=10)
|
|
27
|
-
if response.status_code == 200:
|
|
28
|
-
data = response.json()
|
|
29
|
-
blocks = data.get('blocks', [])
|
|
30
|
-
return len(blocks)
|
|
31
|
-
|
|
32
|
-
except Exception as e:
|
|
33
|
-
print(f"Blockchain height error: {e}")
|
|
34
|
-
|
|
35
|
-
return 0
|
|
36
|
-
|
|
37
|
-
def get_block(self, height: int) -> Optional[Dict]:
|
|
38
|
-
"""Get block by height"""
|
|
39
|
-
# Check cache first
|
|
40
|
-
cached_block = self.cache.get_block(height)
|
|
41
|
-
if cached_block:
|
|
42
|
-
return cached_block
|
|
43
|
-
|
|
44
|
-
try:
|
|
45
|
-
response = requests.get(f'{self.endpoint_url}/blockchain/block/{height}', timeout=10)
|
|
46
|
-
if response.status_code == 200:
|
|
47
|
-
block = response.json()
|
|
48
|
-
self.cache.save_block(height, block.get('hash', ''), block)
|
|
49
|
-
return block
|
|
50
|
-
except Exception as e:
|
|
51
|
-
print(f"Get block error: {e}")
|
|
52
|
-
|
|
53
|
-
return None
|
|
54
|
-
|
|
55
|
-
def get_blocks_range(self, start_height: int, end_height: int) -> List[Dict]:
|
|
56
|
-
"""Get range of blocks"""
|
|
57
|
-
blocks = []
|
|
58
|
-
|
|
59
|
-
# Check cache first
|
|
60
|
-
cached_blocks = self.cache.get_block_range(start_height, end_height)
|
|
61
|
-
if len(cached_blocks) == (end_height - start_height + 1):
|
|
62
|
-
return cached_blocks
|
|
63
|
-
|
|
64
|
-
try:
|
|
65
|
-
response = requests.get(
|
|
66
|
-
f'{self.endpoint_url}/blockchain/range?start={start_height}&end={end_height}',
|
|
67
|
-
timeout=30
|
|
68
|
-
)
|
|
69
|
-
if response.status_code == 200:
|
|
70
|
-
blocks = response.json().get('blocks', [])
|
|
71
|
-
# Cache the blocks
|
|
72
|
-
for block in blocks:
|
|
73
|
-
height = block.get('index', 0)
|
|
74
|
-
self.cache.save_block(height, block.get('hash', ''), block)
|
|
75
|
-
else:
|
|
76
|
-
# Fallback: get blocks individually
|
|
77
|
-
for height in range(start_height, end_height + 1):
|
|
78
|
-
block = self.get_block(height)
|
|
79
|
-
if block:
|
|
80
|
-
blocks.append(block)
|
|
81
|
-
time.sleep(0.01) # Be nice to the API
|
|
82
|
-
|
|
83
|
-
except Exception as e:
|
|
84
|
-
print(f"Get blocks range error: {e}")
|
|
85
|
-
|
|
86
|
-
return blocks
|
|
87
|
-
|
|
88
|
-
def get_mempool(self) -> List[Dict]:
|
|
89
|
-
"""Get current mempool transactions"""
|
|
90
|
-
try:
|
|
91
|
-
response = requests.get(f'{self.endpoint_url}/mempool', timeout=10)
|
|
92
|
-
if response.status_code == 200:
|
|
93
|
-
return response.json()
|
|
94
|
-
except Exception as e:
|
|
95
|
-
print(f"Mempool error: {e}")
|
|
96
|
-
|
|
97
|
-
return []
|
|
98
|
-
|
|
99
|
-
def broadcast_transaction(self, transaction: Dict) -> bool:
|
|
100
|
-
"""Broadcast transaction to network"""
|
|
101
|
-
try:
|
|
102
|
-
response = requests.post(
|
|
103
|
-
f'{self.endpoint_url}/mempool/add',
|
|
104
|
-
json=transaction,
|
|
105
|
-
timeout=30
|
|
106
|
-
)
|
|
107
|
-
return response.status_code == 201
|
|
108
|
-
except Exception as e:
|
|
109
|
-
print(f"Broadcast error: {e}")
|
|
110
|
-
return False
|
|
111
|
-
|
|
112
|
-
def check_network_connection(self) -> bool:
|
|
113
|
-
"""Check if network is accessible"""
|
|
114
|
-
try:
|
|
115
|
-
response = requests.get(f'{self.endpoint_url}/health', timeout=5)
|
|
116
|
-
self.network_connected = response.status_code == 200
|
|
117
|
-
return self.network_connected
|
|
118
|
-
except:
|
|
119
|
-
self.network_connected = False
|
|
120
|
-
return False
|
|
121
|
-
|
|
122
|
-
def scan_transactions_for_address(self, address: str, start_height: int = 0, end_height: int = None) -> List[Dict]:
|
|
123
|
-
"""Scan blockchain for transactions involving an address"""
|
|
124
|
-
if end_height is None:
|
|
125
|
-
end_height = self.get_blockchain_height()
|
|
126
|
-
|
|
127
|
-
transactions = []
|
|
128
|
-
|
|
129
|
-
# Scan in batches for efficiency
|
|
130
|
-
batch_size = 100
|
|
131
|
-
for batch_start in range(start_height, end_height + 1, batch_size):
|
|
132
|
-
batch_end = min(batch_start + batch_size - 1, end_height)
|
|
133
|
-
blocks = self.get_blocks_range(batch_start, batch_end)
|
|
134
|
-
|
|
135
|
-
for block in blocks:
|
|
136
|
-
block_transactions = self._find_address_transactions(block, address)
|
|
137
|
-
transactions.extend(block_transactions)
|
|
138
|
-
|
|
139
|
-
return transactions
|
|
140
|
-
|
|
141
|
-
def _find_address_transactions(self, block: Dict, address: str) -> List[Dict]:
|
|
142
|
-
"""Find transactions in block that involve the address"""
|
|
143
|
-
transactions = []
|
|
144
|
-
address_lower = address.lower()
|
|
145
|
-
|
|
146
|
-
# Check block reward
|
|
147
|
-
miner = block.get('miner', '').lower()
|
|
148
|
-
if miner == address_lower:
|
|
149
|
-
reward_tx = {
|
|
150
|
-
'type': 'reward',
|
|
151
|
-
'from': 'network',
|
|
152
|
-
'to': address,
|
|
153
|
-
'amount': block.get('reward', 0),
|
|
154
|
-
'block_height': block.get('index'),
|
|
155
|
-
'timestamp': block.get('timestamp'),
|
|
156
|
-
'hash': f"reward_{block.get('index')}_{address}",
|
|
157
|
-
'status': 'confirmed'
|
|
158
|
-
}
|
|
159
|
-
transactions.append(reward_tx)
|
|
160
|
-
|
|
161
|
-
# Check regular transactions
|
|
162
|
-
for tx in block.get('transactions', []):
|
|
163
|
-
from_addr = (tx.get('from') or '').lower()
|
|
164
|
-
to_addr = (tx.get('to') or '').lower()
|
|
165
|
-
|
|
166
|
-
if from_addr == address_lower or to_addr == address_lower:
|
|
167
|
-
enhanced_tx = tx.copy()
|
|
168
|
-
enhanced_tx['block_height'] = block.get('index')
|
|
169
|
-
enhanced_tx['status'] = 'confirmed'
|
|
170
|
-
transactions.append(enhanced_tx)
|
|
171
|
-
|
|
172
|
-
return transactions
|
core/crypto.py
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import hashlib
|
|
2
|
-
import secrets
|
|
3
|
-
from typing import Optional
|
|
4
|
-
|
|
5
|
-
class KeyManager:
|
|
6
|
-
"""Manages cryptographic keys and signing"""
|
|
7
|
-
|
|
8
|
-
def generate_private_key(self):
|
|
9
|
-
"""Generate a new private key"""
|
|
10
|
-
return secrets.token_hex(32)
|
|
11
|
-
|
|
12
|
-
def derive_public_key(self, private_key):
|
|
13
|
-
"""Derive public key from private key"""
|
|
14
|
-
return hashlib.sha256(private_key.encode()).hexdigest()
|
|
15
|
-
|
|
16
|
-
def derive_address(self, public_key):
|
|
17
|
-
"""Derive address from public key"""
|
|
18
|
-
address_hash = hashlib.sha256(public_key.encode()).hexdigest()
|
|
19
|
-
return f"LUN_{address_hash[:16]}_{secrets.token_hex(4)}"
|
|
20
|
-
|
|
21
|
-
def sign_data(self, data, private_key):
|
|
22
|
-
"""Sign data with private key"""
|
|
23
|
-
# In production, use proper ECDSA
|
|
24
|
-
# For now, simplified implementation
|
|
25
|
-
sign_string = data + private_key
|
|
26
|
-
return hashlib.sha256(sign_string.encode()).hexdigest()
|
|
27
|
-
|
|
28
|
-
def verify_signature(self, data, signature, public_key):
|
|
29
|
-
"""Verify signature with public key"""
|
|
30
|
-
# Simplified verification
|
|
31
|
-
expected_public = self.derive_public_key(public_key)
|
|
32
|
-
return public_key == expected_public
|