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
|
@@ -1,163 +1,163 @@
|
|
|
1
|
-
# lunalib/wallet_sync_helper.py
|
|
2
|
-
"""
|
|
3
|
-
Wallet Sync Helper
|
|
4
|
-
|
|
5
|
-
Provides integration between LunaWallet, BlockchainManager, MempoolManager,
|
|
6
|
-
and the WalletStateManager for seamless real-time balance and transaction updates.
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
from typing import List, Dict, Optional, Callable
|
|
10
|
-
from .wallet_manager import get_wallet_manager
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class WalletSyncHelper:
|
|
14
|
-
"""
|
|
15
|
-
Helper class to sync LunaWallet with WalletStateManager using data from
|
|
16
|
-
BlockchainManager and MempoolManager.
|
|
17
|
-
"""
|
|
18
|
-
|
|
19
|
-
def __init__(self, wallet=None, blockchain=None, mempool=None):
|
|
20
|
-
"""
|
|
21
|
-
Initialize sync helper.
|
|
22
|
-
|
|
23
|
-
Parameters:
|
|
24
|
-
wallet: LunaWallet instance
|
|
25
|
-
blockchain: BlockchainManager instance
|
|
26
|
-
mempool: MempoolManager instance
|
|
27
|
-
"""
|
|
28
|
-
self.wallet = wallet
|
|
29
|
-
self.blockchain = blockchain
|
|
30
|
-
self.mempool = mempool
|
|
31
|
-
self.state_manager = get_wallet_manager()
|
|
32
|
-
|
|
33
|
-
def register_wallets_from_lunawallet(self) -> Dict:
|
|
34
|
-
"""Register all wallets from LunaWallet into the state manager"""
|
|
35
|
-
if not self.wallet:
|
|
36
|
-
print("⚠️ No wallet instance provided")
|
|
37
|
-
return {}
|
|
38
|
-
|
|
39
|
-
addresses = list(self.wallet.wallets.keys())
|
|
40
|
-
if not addresses:
|
|
41
|
-
print("⚠️ No wallets registered in LunaWallet")
|
|
42
|
-
return {}
|
|
43
|
-
|
|
44
|
-
print(f"📱 Registering {len(addresses)} wallets with state manager...")
|
|
45
|
-
states = self.state_manager.register_wallets(addresses)
|
|
46
|
-
print(f"✅ Registered {len(states)} wallets")
|
|
47
|
-
|
|
48
|
-
return states
|
|
49
|
-
|
|
50
|
-
def sync_wallets_now(self) -> Dict:
|
|
51
|
-
"""
|
|
52
|
-
Perform a single synchronization of all registered wallets.
|
|
53
|
-
|
|
54
|
-
Returns: Dictionary of wallet addresses and their updated summaries
|
|
55
|
-
"""
|
|
56
|
-
if not self.blockchain or not self.mempool:
|
|
57
|
-
print("⚠️ Blockchain or mempool not provided")
|
|
58
|
-
return {}
|
|
59
|
-
|
|
60
|
-
addresses = list(self.state_manager.wallet_states.keys())
|
|
61
|
-
if not addresses:
|
|
62
|
-
print("⚠️ No wallets registered")
|
|
63
|
-
return {}
|
|
64
|
-
|
|
65
|
-
print(f"🔄 Syncing {len(addresses)} wallets...")
|
|
66
|
-
|
|
67
|
-
try:
|
|
68
|
-
# Get data from blockchain and mempool
|
|
69
|
-
blockchain_txs = self.blockchain.scan_transactions_for_addresses(addresses)
|
|
70
|
-
mempool_txs = self.mempool.get_pending_transactions_for_addresses(addresses)
|
|
71
|
-
|
|
72
|
-
# Sync the state manager
|
|
73
|
-
self.state_manager.sync_wallets_from_sources(blockchain_txs, mempool_txs)
|
|
74
|
-
|
|
75
|
-
# Update LunaWallet balances if available
|
|
76
|
-
if self.wallet:
|
|
77
|
-
self._update_lunawallet_balances()
|
|
78
|
-
|
|
79
|
-
# Return summaries
|
|
80
|
-
return self.state_manager.get_all_summaries()
|
|
81
|
-
|
|
82
|
-
except Exception as e:
|
|
83
|
-
print(f"❌ Sync error: {e}")
|
|
84
|
-
return {}
|
|
85
|
-
|
|
86
|
-
def _update_lunawallet_balances(self):
|
|
87
|
-
"""Update LunaWallet instance balances from state manager"""
|
|
88
|
-
if not self.wallet:
|
|
89
|
-
return
|
|
90
|
-
|
|
91
|
-
balances = self.state_manager.get_all_balances()
|
|
92
|
-
|
|
93
|
-
for address, balance_data in balances.items():
|
|
94
|
-
if address in self.wallet.wallets:
|
|
95
|
-
wallet_data = self.wallet.wallets[address]
|
|
96
|
-
wallet_data['balance'] = balance_data['confirmed_balance']
|
|
97
|
-
wallet_data['available_balance'] = balance_data['available_balance']
|
|
98
|
-
|
|
99
|
-
# Update current wallet if one is selected
|
|
100
|
-
if self.wallet.current_wallet_address in balances:
|
|
101
|
-
balance_data = balances[self.wallet.current_wallet_address]
|
|
102
|
-
self.wallet.balance = balance_data['confirmed_balance']
|
|
103
|
-
self.wallet.available_balance = balance_data['available_balance']
|
|
104
|
-
|
|
105
|
-
def start_continuous_sync(self, poll_interval: int = 30,
|
|
106
|
-
on_balance_update: Optional[Callable] = None,
|
|
107
|
-
on_transaction_update: Optional[Callable] = None) -> None:
|
|
108
|
-
"""
|
|
109
|
-
Start continuous synchronization in the background.
|
|
110
|
-
|
|
111
|
-
Parameters:
|
|
112
|
-
poll_interval: Seconds between syncs
|
|
113
|
-
on_balance_update: Callback function(balance_data) for balance updates
|
|
114
|
-
on_transaction_update: Callback function(transaction_data) for transaction updates
|
|
115
|
-
"""
|
|
116
|
-
|
|
117
|
-
if on_balance_update:
|
|
118
|
-
self.state_manager.on_balance_update(on_balance_update)
|
|
119
|
-
|
|
120
|
-
if on_transaction_update:
|
|
121
|
-
self.state_manager.on_transaction_update(on_transaction_update)
|
|
122
|
-
|
|
123
|
-
def get_blockchain_data(addresses):
|
|
124
|
-
try:
|
|
125
|
-
return self.blockchain.scan_transactions_for_addresses(addresses)
|
|
126
|
-
except Exception as e:
|
|
127
|
-
print(f"⚠️ Blockchain scan error: {e}")
|
|
128
|
-
return {}
|
|
129
|
-
|
|
130
|
-
def get_mempool_data(addresses):
|
|
131
|
-
try:
|
|
132
|
-
return self.mempool.get_pending_transactions_for_addresses(addresses)
|
|
133
|
-
except Exception as e:
|
|
134
|
-
print(f"⚠️ Mempool fetch error: {e}")
|
|
135
|
-
return {}
|
|
136
|
-
|
|
137
|
-
self.state_manager.sync_wallets_background(
|
|
138
|
-
get_blockchain_data,
|
|
139
|
-
get_mempool_data,
|
|
140
|
-
poll_interval
|
|
141
|
-
)
|
|
142
|
-
|
|
143
|
-
def get_wallet_balance(self, address: str) -> Optional[Dict]:
|
|
144
|
-
"""Get current balance for a wallet"""
|
|
145
|
-
return self.state_manager.get_balance(address)
|
|
146
|
-
|
|
147
|
-
def get_wallet_transactions(self, address: str, tx_type: str = 'all') -> List[Dict]:
|
|
148
|
-
"""Get transactions for a wallet"""
|
|
149
|
-
return self.state_manager.get_transactions(address, tx_type)
|
|
150
|
-
|
|
151
|
-
def get_wallet_summary(self, address: str) -> Optional[Dict]:
|
|
152
|
-
"""Get complete summary for a wallet"""
|
|
153
|
-
return self.state_manager.get_wallet_summary(address)
|
|
154
|
-
|
|
155
|
-
def get_all_wallets_summary(self) -> Dict:
|
|
156
|
-
"""Get summaries for all wallets"""
|
|
157
|
-
return self.state_manager.get_all_summaries()
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
# Convenience function to create sync helper
|
|
161
|
-
def create_wallet_sync_helper(wallet=None, blockchain=None, mempool=None) -> WalletSyncHelper:
|
|
162
|
-
"""Create a new WalletSyncHelper instance"""
|
|
163
|
-
return WalletSyncHelper(wallet, blockchain, mempool)
|
|
1
|
+
# lunalib/wallet_sync_helper.py
|
|
2
|
+
"""
|
|
3
|
+
Wallet Sync Helper
|
|
4
|
+
|
|
5
|
+
Provides integration between LunaWallet, BlockchainManager, MempoolManager,
|
|
6
|
+
and the WalletStateManager for seamless real-time balance and transaction updates.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from typing import List, Dict, Optional, Callable
|
|
10
|
+
from .wallet_manager import get_wallet_manager
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class WalletSyncHelper:
|
|
14
|
+
"""
|
|
15
|
+
Helper class to sync LunaWallet with WalletStateManager using data from
|
|
16
|
+
BlockchainManager and MempoolManager.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(self, wallet=None, blockchain=None, mempool=None):
|
|
20
|
+
"""
|
|
21
|
+
Initialize sync helper.
|
|
22
|
+
|
|
23
|
+
Parameters:
|
|
24
|
+
wallet: LunaWallet instance
|
|
25
|
+
blockchain: BlockchainManager instance
|
|
26
|
+
mempool: MempoolManager instance
|
|
27
|
+
"""
|
|
28
|
+
self.wallet = wallet
|
|
29
|
+
self.blockchain = blockchain
|
|
30
|
+
self.mempool = mempool
|
|
31
|
+
self.state_manager = get_wallet_manager()
|
|
32
|
+
|
|
33
|
+
def register_wallets_from_lunawallet(self) -> Dict:
|
|
34
|
+
"""Register all wallets from LunaWallet into the state manager"""
|
|
35
|
+
if not self.wallet:
|
|
36
|
+
print("⚠️ No wallet instance provided")
|
|
37
|
+
return {}
|
|
38
|
+
|
|
39
|
+
addresses = list(self.wallet.wallets.keys())
|
|
40
|
+
if not addresses:
|
|
41
|
+
print("⚠️ No wallets registered in LunaWallet")
|
|
42
|
+
return {}
|
|
43
|
+
|
|
44
|
+
print(f"📱 Registering {len(addresses)} wallets with state manager...")
|
|
45
|
+
states = self.state_manager.register_wallets(addresses)
|
|
46
|
+
print(f"✅ Registered {len(states)} wallets")
|
|
47
|
+
|
|
48
|
+
return states
|
|
49
|
+
|
|
50
|
+
def sync_wallets_now(self) -> Dict:
|
|
51
|
+
"""
|
|
52
|
+
Perform a single synchronization of all registered wallets.
|
|
53
|
+
|
|
54
|
+
Returns: Dictionary of wallet addresses and their updated summaries
|
|
55
|
+
"""
|
|
56
|
+
if not self.blockchain or not self.mempool:
|
|
57
|
+
print("⚠️ Blockchain or mempool not provided")
|
|
58
|
+
return {}
|
|
59
|
+
|
|
60
|
+
addresses = list(self.state_manager.wallet_states.keys())
|
|
61
|
+
if not addresses:
|
|
62
|
+
print("⚠️ No wallets registered")
|
|
63
|
+
return {}
|
|
64
|
+
|
|
65
|
+
print(f"🔄 Syncing {len(addresses)} wallets...")
|
|
66
|
+
|
|
67
|
+
try:
|
|
68
|
+
# Get data from blockchain and mempool
|
|
69
|
+
blockchain_txs = self.blockchain.scan_transactions_for_addresses(addresses)
|
|
70
|
+
mempool_txs = self.mempool.get_pending_transactions_for_addresses(addresses)
|
|
71
|
+
|
|
72
|
+
# Sync the state manager
|
|
73
|
+
self.state_manager.sync_wallets_from_sources(blockchain_txs, mempool_txs)
|
|
74
|
+
|
|
75
|
+
# Update LunaWallet balances if available
|
|
76
|
+
if self.wallet:
|
|
77
|
+
self._update_lunawallet_balances()
|
|
78
|
+
|
|
79
|
+
# Return summaries
|
|
80
|
+
return self.state_manager.get_all_summaries()
|
|
81
|
+
|
|
82
|
+
except Exception as e:
|
|
83
|
+
print(f"❌ Sync error: {e}")
|
|
84
|
+
return {}
|
|
85
|
+
|
|
86
|
+
def _update_lunawallet_balances(self):
|
|
87
|
+
"""Update LunaWallet instance balances from state manager"""
|
|
88
|
+
if not self.wallet:
|
|
89
|
+
return
|
|
90
|
+
|
|
91
|
+
balances = self.state_manager.get_all_balances()
|
|
92
|
+
|
|
93
|
+
for address, balance_data in balances.items():
|
|
94
|
+
if address in self.wallet.wallets:
|
|
95
|
+
wallet_data = self.wallet.wallets[address]
|
|
96
|
+
wallet_data['balance'] = balance_data['confirmed_balance']
|
|
97
|
+
wallet_data['available_balance'] = balance_data['available_balance']
|
|
98
|
+
|
|
99
|
+
# Update current wallet if one is selected
|
|
100
|
+
if self.wallet.current_wallet_address in balances:
|
|
101
|
+
balance_data = balances[self.wallet.current_wallet_address]
|
|
102
|
+
self.wallet.balance = balance_data['confirmed_balance']
|
|
103
|
+
self.wallet.available_balance = balance_data['available_balance']
|
|
104
|
+
|
|
105
|
+
def start_continuous_sync(self, poll_interval: int = 30,
|
|
106
|
+
on_balance_update: Optional[Callable] = None,
|
|
107
|
+
on_transaction_update: Optional[Callable] = None) -> None:
|
|
108
|
+
"""
|
|
109
|
+
Start continuous synchronization in the background.
|
|
110
|
+
|
|
111
|
+
Parameters:
|
|
112
|
+
poll_interval: Seconds between syncs
|
|
113
|
+
on_balance_update: Callback function(balance_data) for balance updates
|
|
114
|
+
on_transaction_update: Callback function(transaction_data) for transaction updates
|
|
115
|
+
"""
|
|
116
|
+
|
|
117
|
+
if on_balance_update:
|
|
118
|
+
self.state_manager.on_balance_update(on_balance_update)
|
|
119
|
+
|
|
120
|
+
if on_transaction_update:
|
|
121
|
+
self.state_manager.on_transaction_update(on_transaction_update)
|
|
122
|
+
|
|
123
|
+
def get_blockchain_data(addresses):
|
|
124
|
+
try:
|
|
125
|
+
return self.blockchain.scan_transactions_for_addresses(addresses)
|
|
126
|
+
except Exception as e:
|
|
127
|
+
print(f"⚠️ Blockchain scan error: {e}")
|
|
128
|
+
return {}
|
|
129
|
+
|
|
130
|
+
def get_mempool_data(addresses):
|
|
131
|
+
try:
|
|
132
|
+
return self.mempool.get_pending_transactions_for_addresses(addresses)
|
|
133
|
+
except Exception as e:
|
|
134
|
+
print(f"⚠️ Mempool fetch error: {e}")
|
|
135
|
+
return {}
|
|
136
|
+
|
|
137
|
+
self.state_manager.sync_wallets_background(
|
|
138
|
+
get_blockchain_data,
|
|
139
|
+
get_mempool_data,
|
|
140
|
+
poll_interval
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
def get_wallet_balance(self, address: str) -> Optional[Dict]:
|
|
144
|
+
"""Get current balance for a wallet"""
|
|
145
|
+
return self.state_manager.get_balance(address)
|
|
146
|
+
|
|
147
|
+
def get_wallet_transactions(self, address: str, tx_type: str = 'all') -> List[Dict]:
|
|
148
|
+
"""Get transactions for a wallet"""
|
|
149
|
+
return self.state_manager.get_transactions(address, tx_type)
|
|
150
|
+
|
|
151
|
+
def get_wallet_summary(self, address: str) -> Optional[Dict]:
|
|
152
|
+
"""Get complete summary for a wallet"""
|
|
153
|
+
return self.state_manager.get_wallet_summary(address)
|
|
154
|
+
|
|
155
|
+
def get_all_wallets_summary(self) -> Dict:
|
|
156
|
+
"""Get summaries for all wallets"""
|
|
157
|
+
return self.state_manager.get_all_summaries()
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
# Convenience function to create sync helper
|
|
161
|
+
def create_wallet_sync_helper(wallet=None, blockchain=None, mempool=None) -> WalletSyncHelper:
|
|
162
|
+
"""Create a new WalletSyncHelper instance"""
|
|
163
|
+
return WalletSyncHelper(wallet, blockchain, mempool)
|
lunalib/gtx/digital_bill.py
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
def safe_print(*args, **kwargs):
|
|
3
|
+
encoding = sys.stdout.encoding or 'utf-8'
|
|
4
|
+
try:
|
|
5
|
+
print(*args, **kwargs)
|
|
6
|
+
except UnicodeEncodeError:
|
|
7
|
+
print(*(str(a).encode(encoding, errors='replace').decode(encoding) for a in args), **kwargs)
|
|
8
|
+
safe_print("Warning: cryptography library not available. Using fallback methods.")
|
|
1
9
|
import time
|
|
2
10
|
import hashlib
|
|
3
11
|
import secrets
|
|
@@ -12,7 +20,7 @@ try:
|
|
|
12
20
|
from cryptography.exceptions import InvalidSignature
|
|
13
21
|
CRYPTOGRAPHY_AVAILABLE = True
|
|
14
22
|
except ImportError:
|
|
15
|
-
|
|
23
|
+
safe_print("Warning: cryptography library not available. Using fallback methods.")
|
|
16
24
|
CRYPTOGRAPHY_AVAILABLE = False
|
|
17
25
|
|
|
18
26
|
from .bill_registry import BillRegistry
|
|
@@ -182,7 +190,7 @@ class DigitalBill:
|
|
|
182
190
|
|
|
183
191
|
return self.signature
|
|
184
192
|
except Exception as e:
|
|
185
|
-
|
|
193
|
+
safe_print(f"Cryptographic signing failed, using fallback: {e}")
|
|
186
194
|
return self._sign_fallback(private_key)
|
|
187
195
|
|
|
188
196
|
def _sign_fallback(self, private_key):
|
lunalib/gtx/genesis.py
CHANGED
|
@@ -48,7 +48,7 @@ class GTXGenesis:
|
|
|
48
48
|
return {'valid': False, 'error': 'Bill not found in registry'}
|
|
49
49
|
|
|
50
50
|
# DEBUG: Print what we received
|
|
51
|
-
|
|
51
|
+
safe_print(f"DEBUG: Full bill record: {bill_record}")
|
|
52
52
|
|
|
53
53
|
# Extract the actual bill_data from the metadata field
|
|
54
54
|
bill_data = bill_record.get('metadata', {})
|
|
@@ -56,7 +56,7 @@ class GTXGenesis:
|
|
|
56
56
|
return {'valid': False, 'error': 'No bill data found in metadata'}
|
|
57
57
|
|
|
58
58
|
# DEBUG: Print the extracted bill_data
|
|
59
|
-
|
|
59
|
+
safe_print(f"DEBUG: Extracted bill_data: {bill_data}")
|
|
60
60
|
|
|
61
61
|
# Extract signature components from bill_data (not from bill_record)
|
|
62
62
|
public_key = bill_data.get('public_key')
|
|
@@ -68,10 +68,10 @@ class GTXGenesis:
|
|
|
68
68
|
timestamp = bill_data.get('timestamp', 0)
|
|
69
69
|
bill_type = bill_data.get('type', 'GTX_Genesis')
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
71
|
+
safe_print(f"🔍 GTXGenesis.verify_bill() for {front_serial}:")
|
|
72
|
+
safe_print(f" Signature: {signature}")
|
|
73
|
+
safe_print(f" Public Key: {public_key}")
|
|
74
|
+
safe_print(f" Metadata Hash: {metadata_hash}")
|
|
75
75
|
|
|
76
76
|
# Use the same verification logic as the endpoint
|
|
77
77
|
verification_method = "unknown"
|
|
@@ -81,7 +81,7 @@ class GTXGenesis:
|
|
|
81
81
|
if metadata_hash and signature == metadata_hash:
|
|
82
82
|
signature_valid = True
|
|
83
83
|
verification_method = "signature_is_metadata_hash"
|
|
84
|
-
|
|
84
|
+
safe_print(f"✅ Verified: signature matches metadata_hash")
|
|
85
85
|
|
|
86
86
|
# METHOD 2: Check hash of public_key + metadata_hash
|
|
87
87
|
elif signature_valid is None and metadata_hash and public_key and signature:
|
|
@@ -90,7 +90,7 @@ class GTXGenesis:
|
|
|
90
90
|
if signature == expected_signature:
|
|
91
91
|
signature_valid = True
|
|
92
92
|
verification_method = "metadata_hash_signature"
|
|
93
|
-
|
|
93
|
+
safe_print(f"Verified: hash(public_key + metadata_hash)")
|
|
94
94
|
|
|
95
95
|
# METHOD 3: Check DigitalBill calculated hash
|
|
96
96
|
elif signature_valid is None:
|
|
@@ -122,32 +122,31 @@ class GTXGenesis:
|
|
|
122
122
|
if signature == calculated_hash:
|
|
123
123
|
signature_valid = True
|
|
124
124
|
verification_method = "digital_bill_calculate_hash"
|
|
125
|
-
|
|
125
|
+
safe_print(f"Verified: DigitalBill.calculate_hash()")
|
|
126
126
|
print(f" Calculated hash: {calculated_hash}")
|
|
127
127
|
|
|
128
128
|
# Approach 2: Use the verify() method (checks all signature types)
|
|
129
129
|
elif digital_bill.verify():
|
|
130
130
|
signature_valid = True
|
|
131
131
|
verification_method = "digital_bill_verify_method"
|
|
132
|
-
|
|
132
|
+
safe_print(f"Verified: DigitalBill.verify()")
|
|
133
133
|
|
|
134
134
|
# Approach 3: Check if signature matches metadata_hash generation
|
|
135
135
|
elif signature == digital_bill._generate_metadata_hash():
|
|
136
136
|
signature_valid = True
|
|
137
137
|
verification_method = "digital_bill_metadata_hash"
|
|
138
|
-
|
|
138
|
+
safe_print(f"Verified: matches generated metadata_hash")
|
|
139
139
|
|
|
140
140
|
else:
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
141
|
+
safe_print(f"DigitalBill verification failed:")
|
|
142
|
+
safe_print(f" Calculated hash: {calculated_hash}")
|
|
143
|
+
safe_print(f" Signature: {signature}")
|
|
144
|
+
safe_print(f" Metadata hash: {metadata_hash}")
|
|
145
|
+
safe_print(f" Public key: {public_key}")
|
|
147
146
|
except Exception as e:
|
|
148
|
-
|
|
147
|
+
safe_print(f"DigitalBill verification error: {e}")
|
|
149
148
|
import traceback
|
|
150
|
-
|
|
149
|
+
safe_print(f"Traceback: {traceback.format_exc()}")
|
|
151
150
|
|
|
152
151
|
# METHOD 4: Check simple concatenation hash
|
|
153
152
|
elif signature_valid is None and signature:
|
|
@@ -156,7 +155,7 @@ class GTXGenesis:
|
|
|
156
155
|
if signature == expected_simple_hash:
|
|
157
156
|
signature_valid = True
|
|
158
157
|
verification_method = "simple_hash"
|
|
159
|
-
|
|
158
|
+
safe_print(f"✅ Verified: hash(serial+denom+issued+timestamp)")
|
|
160
159
|
|
|
161
160
|
# METHOD 5: Check bill JSON hash
|
|
162
161
|
elif signature_valid is None:
|
|
@@ -173,19 +172,19 @@ class GTXGenesis:
|
|
|
173
172
|
if signature == bill_json_hash:
|
|
174
173
|
signature_valid = True
|
|
175
174
|
verification_method = "bill_json_hash"
|
|
176
|
-
|
|
175
|
+
safe_print(f"Verified: hash(bill_data_json)")
|
|
177
176
|
|
|
178
177
|
# Final fallback: accept any non-empty signature temporarily
|
|
179
178
|
if signature_valid is None and signature and len(signature) > 10:
|
|
180
179
|
signature_valid = True
|
|
181
180
|
verification_method = "fallback_accept"
|
|
182
|
-
|
|
181
|
+
safe_print(f"Using fallback acceptance for signature")
|
|
183
182
|
|
|
184
183
|
# If all methods failed
|
|
185
184
|
if signature_valid is None:
|
|
186
185
|
signature_valid = False
|
|
187
186
|
verification_method = "all_failed"
|
|
188
|
-
|
|
187
|
+
safe_print(f"All verification methods failed")
|
|
189
188
|
|
|
190
189
|
# Return result in same format as endpoint
|
|
191
190
|
if signature_valid:
|
|
@@ -337,7 +336,7 @@ class GTXGenesis:
|
|
|
337
336
|
return computed_hash == bill_info['hash']
|
|
338
337
|
|
|
339
338
|
except Exception as e:
|
|
340
|
-
|
|
339
|
+
safe_print(f"Bill verification error: {e}")
|
|
341
340
|
return False
|
|
342
341
|
|
|
343
342
|
def _get_denomination_breakdown(self, bills: List[Dict]) -> Dict[int, int]:
|
lunalib/mining/__init__.py
CHANGED
lunalib/mining/cuda_manager.py
CHANGED
|
@@ -47,7 +47,7 @@ class CUDAManager:
|
|
|
47
47
|
self.cuda_available = False
|
|
48
48
|
|
|
49
49
|
def cuda_mine_batch(self, mining_data: Dict, difficulty: int, batch_size: int = 100000) -> Optional[Dict]:
|
|
50
|
-
"""Mine using CUDA acceleration"""
|
|
50
|
+
"""Mine using CUDA acceleration with CPU-side hash computation"""
|
|
51
51
|
if not self.cuda_available:
|
|
52
52
|
return None
|
|
53
53
|
|
|
@@ -56,24 +56,27 @@ class CUDAManager:
|
|
|
56
56
|
nonce_start = 0
|
|
57
57
|
start_time = time.time()
|
|
58
58
|
|
|
59
|
+
# Pre-compute the base string without nonce for efficiency
|
|
60
|
+
base_data = {k: v for k, v in mining_data.items() if k != 'nonce'}
|
|
61
|
+
|
|
59
62
|
while True:
|
|
60
|
-
#
|
|
61
|
-
|
|
62
|
-
|
|
63
|
+
# Generate nonces on GPU for parallel processing
|
|
64
|
+
nonces_gpu = cp.arange(nonce_start, nonce_start + batch_size, dtype=cp.int64)
|
|
65
|
+
nonces_cpu = cp.asnumpy(nonces_gpu) # Transfer to CPU for hashing
|
|
63
66
|
|
|
64
|
-
# Compute hashes on GPU
|
|
65
|
-
hashes = self.
|
|
67
|
+
# Compute hashes in parallel on CPU (GPU hash acceleration requires custom CUDA kernels)
|
|
68
|
+
hashes = self._compute_hashes_parallel(base_data, nonces_cpu)
|
|
66
69
|
|
|
67
70
|
# Check for successful hash
|
|
68
71
|
for i, hash_hex in enumerate(hashes):
|
|
69
72
|
if hash_hex.startswith(target):
|
|
70
73
|
mining_time = time.time() - start_time
|
|
71
|
-
successful_nonce =
|
|
74
|
+
successful_nonce = int(nonces_cpu[i])
|
|
72
75
|
|
|
73
76
|
return {
|
|
74
77
|
"success": True,
|
|
75
78
|
"hash": hash_hex,
|
|
76
|
-
"nonce":
|
|
79
|
+
"nonce": successful_nonce,
|
|
77
80
|
"mining_time": mining_time,
|
|
78
81
|
"method": "cuda"
|
|
79
82
|
}
|
|
@@ -85,36 +88,28 @@ class CUDAManager:
|
|
|
85
88
|
current_time = time.time()
|
|
86
89
|
hashrate = nonce_start / (current_time - start_time)
|
|
87
90
|
print(f"⏳ CUDA: {nonce_start:,} attempts | {hashrate:,.0f} H/s")
|
|
91
|
+
|
|
92
|
+
# Timeout check
|
|
93
|
+
if time.time() - start_time > 300: # 5 minutes timeout
|
|
94
|
+
break
|
|
88
95
|
|
|
89
96
|
except Exception as e:
|
|
90
97
|
print(f"CUDA mining error: {e}")
|
|
91
98
|
|
|
92
99
|
return None
|
|
93
100
|
|
|
94
|
-
def
|
|
95
|
-
"""
|
|
96
|
-
|
|
101
|
+
def _compute_hashes_parallel(self, base_data: Dict, nonces: list) -> list:
|
|
102
|
+
"""Compute SHA256 hashes in parallel on CPU (string operations not supported on GPU)"""
|
|
103
|
+
hashes = []
|
|
97
104
|
|
|
98
105
|
for nonce in nonces:
|
|
106
|
+
# Create mining data with current nonce
|
|
107
|
+
mining_data = base_data.copy()
|
|
99
108
|
mining_data["nonce"] = int(nonce)
|
|
100
|
-
data_string = json.dumps(mining_data, sort_keys=True)
|
|
101
|
-
mining_strings.append(data_string.encode())
|
|
102
109
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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())
|
|
110
|
+
# Compute hash
|
|
111
|
+
data_string = json.dumps(mining_data, sort_keys=True)
|
|
112
|
+
hash_obj = hashlib.sha256(data_string.encode())
|
|
118
113
|
hashes.append(hash_obj.hexdigest())
|
|
119
114
|
|
|
120
115
|
return hashes
|
lunalib/mining/difficulty.py
CHANGED
|
@@ -65,6 +65,44 @@ class DifficultySystem:
|
|
|
65
65
|
|
|
66
66
|
return base_reward * (1 + time_bonus)
|
|
67
67
|
|
|
68
|
+
def calculate_block_reward(self, difficulty: int) -> float:
|
|
69
|
+
"""Calculate block reward based on difficulty using exponential system
|
|
70
|
+
|
|
71
|
+
Reward = 10^(difficulty - 1)
|
|
72
|
+
difficulty 1 = 1 LKC (10^0)
|
|
73
|
+
difficulty 2 = 10 LKC (10^1)
|
|
74
|
+
difficulty 3 = 100 LKC (10^2)
|
|
75
|
+
difficulty 9 = 100,000,000 LKC (10^8)
|
|
76
|
+
"""
|
|
77
|
+
if difficulty < 1:
|
|
78
|
+
difficulty = 1
|
|
79
|
+
elif difficulty > 9:
|
|
80
|
+
difficulty = 9
|
|
81
|
+
|
|
82
|
+
return 10 ** (difficulty - 1)
|
|
83
|
+
|
|
84
|
+
def validate_block_hash(self, block_hash: str, difficulty: int) -> bool:
|
|
85
|
+
"""Validate that block hash meets difficulty requirement"""
|
|
86
|
+
if not block_hash or difficulty < 1:
|
|
87
|
+
return False
|
|
88
|
+
|
|
89
|
+
target_prefix = "0" * difficulty
|
|
90
|
+
return block_hash.startswith(target_prefix)
|
|
91
|
+
|
|
92
|
+
def validate_block_structure(self, block: dict) -> tuple:
|
|
93
|
+
"""Validate block has all required fields
|
|
94
|
+
|
|
95
|
+
Returns: (is_valid, error_message)
|
|
96
|
+
"""
|
|
97
|
+
required_fields = ['index', 'previous_hash', 'timestamp', 'transactions',
|
|
98
|
+
'miner', 'difficulty', 'nonce', 'hash', 'reward']
|
|
99
|
+
|
|
100
|
+
for field in required_fields:
|
|
101
|
+
if field not in block:
|
|
102
|
+
return False, f"Missing required field: {field}"
|
|
103
|
+
|
|
104
|
+
return True, ""
|
|
105
|
+
|
|
68
106
|
def get_difficulty_name(self, difficulty_level):
|
|
69
107
|
"""Get human-readable name for difficulty level"""
|
|
70
108
|
names = {
|