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
transactions/security.py
DELETED
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
import time
|
|
2
|
-
import hashlib
|
|
3
|
-
from typing import Dict, Tuple
|
|
4
|
-
|
|
5
|
-
class TransactionSecurity:
|
|
6
|
-
"""Enhanced transaction security system"""
|
|
7
|
-
|
|
8
|
-
def __init__(self):
|
|
9
|
-
self.min_transaction_amount = 0.000001
|
|
10
|
-
self.max_transaction_amount = 100000000
|
|
11
|
-
self.required_fee = 0.00001
|
|
12
|
-
self.rate_limits = {}
|
|
13
|
-
self.blacklisted_addresses = set()
|
|
14
|
-
|
|
15
|
-
def validate_transaction_security(self, transaction: Dict) -> Tuple[bool, str]:
|
|
16
|
-
"""Comprehensive transaction security validation"""
|
|
17
|
-
tx_type = transaction.get("type", "").lower()
|
|
18
|
-
|
|
19
|
-
if tx_type == "gtx_genesis":
|
|
20
|
-
return self._validate_genesis_transaction(transaction)
|
|
21
|
-
elif tx_type == "reward":
|
|
22
|
-
return self._validate_reward_transaction(transaction)
|
|
23
|
-
elif tx_type == "transfer":
|
|
24
|
-
return self._validate_transfer_transaction(transaction)
|
|
25
|
-
else:
|
|
26
|
-
return False, f"Unknown transaction type: {tx_type}"
|
|
27
|
-
|
|
28
|
-
def _validate_genesis_transaction(self, transaction: Dict) -> Tuple[bool, str]:
|
|
29
|
-
"""Validate GTX Genesis transaction"""
|
|
30
|
-
required_fields = ["bill_serial", "denomination", "mining_difficulty", "hash", "nonce"]
|
|
31
|
-
for field in required_fields:
|
|
32
|
-
if field not in transaction:
|
|
33
|
-
return False, f"Missing GTX field: {field}"
|
|
34
|
-
|
|
35
|
-
# Validate denomination
|
|
36
|
-
denomination = transaction.get("denomination")
|
|
37
|
-
valid_denominations = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000]
|
|
38
|
-
if denomination not in valid_denominations:
|
|
39
|
-
return False, f"Invalid denomination: {denomination}"
|
|
40
|
-
|
|
41
|
-
# Validate mining proof
|
|
42
|
-
if not self._validate_mining_proof(transaction):
|
|
43
|
-
return False, "Invalid mining proof"
|
|
44
|
-
|
|
45
|
-
return True, "Valid GTX Genesis transaction"
|
|
46
|
-
|
|
47
|
-
def _validate_reward_transaction(self, transaction: Dict) -> Tuple[bool, str]:
|
|
48
|
-
"""Validate reward transaction"""
|
|
49
|
-
required_fields = ["from", "to", "amount", "block_height", "hash"]
|
|
50
|
-
for field in required_fields:
|
|
51
|
-
if field not in transaction:
|
|
52
|
-
return False, f"Missing reward field: {field}"
|
|
53
|
-
|
|
54
|
-
# Only network can create rewards
|
|
55
|
-
if transaction.get("from") != "network":
|
|
56
|
-
return False, "Unauthorized reward creation"
|
|
57
|
-
|
|
58
|
-
return True, "Valid reward transaction"
|
|
59
|
-
|
|
60
|
-
def _validate_transfer_transaction(self, transaction: Dict) -> Tuple[bool, str]:
|
|
61
|
-
"""Validate transfer transaction"""
|
|
62
|
-
required_fields = ["from", "to", "amount", "signature", "public_key", "nonce"]
|
|
63
|
-
for field in required_fields:
|
|
64
|
-
if field not in transaction:
|
|
65
|
-
return False, f"Missing field: {field}"
|
|
66
|
-
|
|
67
|
-
# Amount validation
|
|
68
|
-
amount = transaction.get("amount", 0)
|
|
69
|
-
if amount < self.min_transaction_amount:
|
|
70
|
-
return False, f"Amount below minimum: {self.min_transaction_amount}"
|
|
71
|
-
if amount > self.max_transaction_amount:
|
|
72
|
-
return False, f"Amount above maximum: {self.max_transaction_amount}"
|
|
73
|
-
|
|
74
|
-
# Fee validation
|
|
75
|
-
fee = transaction.get("fee", 0)
|
|
76
|
-
if fee < self.required_fee:
|
|
77
|
-
return False, f"Insufficient fee: {fee} (required: {self.required_fee})"
|
|
78
|
-
|
|
79
|
-
# Signature validation
|
|
80
|
-
if not self._validate_signature(transaction):
|
|
81
|
-
return False, "Invalid signature"
|
|
82
|
-
|
|
83
|
-
# Anti-spam checks
|
|
84
|
-
from_address = transaction.get("from", "")
|
|
85
|
-
if not self._check_rate_limit(from_address):
|
|
86
|
-
return False, "Rate limit exceeded"
|
|
87
|
-
|
|
88
|
-
if self._is_blacklisted(from_address):
|
|
89
|
-
return False, "Address is blacklisted"
|
|
90
|
-
|
|
91
|
-
return True, "Valid transfer transaction"
|
|
92
|
-
|
|
93
|
-
def _validate_mining_proof(self, transaction: Dict) -> bool:
|
|
94
|
-
"""Validate mining proof-of-work"""
|
|
95
|
-
try:
|
|
96
|
-
difficulty = transaction.get("mining_difficulty", 0)
|
|
97
|
-
bill_hash = transaction.get("hash", "")
|
|
98
|
-
|
|
99
|
-
# Verify difficulty requirement
|
|
100
|
-
target = "0" * difficulty
|
|
101
|
-
return bill_hash.startswith(target)
|
|
102
|
-
except:
|
|
103
|
-
return False
|
|
104
|
-
|
|
105
|
-
def _validate_signature(self, transaction: Dict) -> bool:
|
|
106
|
-
"""Validate transaction signature"""
|
|
107
|
-
try:
|
|
108
|
-
signature = transaction.get("signature", "")
|
|
109
|
-
public_key = transaction.get("public_key", "")
|
|
110
|
-
|
|
111
|
-
# Basic format validation
|
|
112
|
-
if len(signature) != 64:
|
|
113
|
-
return False
|
|
114
|
-
|
|
115
|
-
# In production, use proper ECDSA verification
|
|
116
|
-
# For now, simplified check
|
|
117
|
-
return all(c in "0123456789abcdef" for c in signature.lower())
|
|
118
|
-
except:
|
|
119
|
-
return False
|
|
120
|
-
|
|
121
|
-
def _check_rate_limit(self, address: str) -> bool:
|
|
122
|
-
"""Check transaction rate limiting"""
|
|
123
|
-
now = time.time()
|
|
124
|
-
|
|
125
|
-
if address not in self.rate_limits:
|
|
126
|
-
self.rate_limits[address] = []
|
|
127
|
-
|
|
128
|
-
# Remove old entries (older than 1 minute)
|
|
129
|
-
self.rate_limits[address] = [t for t in self.rate_limits[address] if now - t < 60]
|
|
130
|
-
|
|
131
|
-
# Check if over limit (10 transactions per minute)
|
|
132
|
-
if len(self.rate_limits[address]) >= 10:
|
|
133
|
-
return False
|
|
134
|
-
|
|
135
|
-
self.rate_limits[address].append(now)
|
|
136
|
-
return True
|
|
137
|
-
|
|
138
|
-
def _is_blacklisted(self, address: str) -> bool:
|
|
139
|
-
"""Check if address is blacklisted"""
|
|
140
|
-
return address.lower() in self.blacklisted_addresses
|
|
141
|
-
|
|
142
|
-
def blacklist_address(self, address: str):
|
|
143
|
-
"""Add address to blacklist"""
|
|
144
|
-
self.blacklisted_addresses.add(address.lower())
|
|
145
|
-
|
|
146
|
-
def calculate_security_score(self, transaction: Dict) -> int:
|
|
147
|
-
"""Calculate security score for transaction"""
|
|
148
|
-
score = 0
|
|
149
|
-
|
|
150
|
-
# Signature strength
|
|
151
|
-
signature = transaction.get("signature", "")
|
|
152
|
-
if len(signature) == 64:
|
|
153
|
-
score += 40
|
|
154
|
-
|
|
155
|
-
# Public key presence
|
|
156
|
-
if transaction.get("public_key"):
|
|
157
|
-
score += 20
|
|
158
|
-
|
|
159
|
-
# Timestamp freshness
|
|
160
|
-
timestamp = transaction.get("timestamp", 0)
|
|
161
|
-
if time.time() - timestamp < 600: # 10 minutes
|
|
162
|
-
score += 20
|
|
163
|
-
|
|
164
|
-
# Nonce uniqueness
|
|
165
|
-
if transaction.get("nonce"):
|
|
166
|
-
score += 10
|
|
167
|
-
|
|
168
|
-
# Additional security features
|
|
169
|
-
if transaction.get("security_hash"):
|
|
170
|
-
score += 10
|
|
171
|
-
|
|
172
|
-
return min(score, 100)
|
transactions/transactions.py
DELETED
|
@@ -1,424 +0,0 @@
|
|
|
1
|
-
import time
|
|
2
|
-
import hashlib
|
|
3
|
-
import json
|
|
4
|
-
from typing import Dict, Optional, Tuple, List
|
|
5
|
-
|
|
6
|
-
class TransactionSecurity:
|
|
7
|
-
"""Transaction security validation and risk assessment"""
|
|
8
|
-
|
|
9
|
-
def validate_transaction(self, transaction: Dict) -> Tuple[bool, str]:
|
|
10
|
-
"""Validate transaction structure"""
|
|
11
|
-
required_fields = ['from', 'to', 'amount', 'timestamp']
|
|
12
|
-
for field in required_fields:
|
|
13
|
-
if field not in transaction:
|
|
14
|
-
return False, f'Missing required field: {field}'
|
|
15
|
-
|
|
16
|
-
# Validate amount
|
|
17
|
-
if transaction['amount'] <= 0:
|
|
18
|
-
return False, 'Amount must be positive'
|
|
19
|
-
|
|
20
|
-
return True, 'Valid'
|
|
21
|
-
|
|
22
|
-
def validate_transaction_security(self, transaction: Dict) -> Tuple[bool, str]:
|
|
23
|
-
"""Enhanced security validation"""
|
|
24
|
-
required_fields = ['from', 'to', 'amount', 'timestamp', 'type']
|
|
25
|
-
for field in required_fields:
|
|
26
|
-
if field not in transaction:
|
|
27
|
-
return False, f'Missing required field: {field}'
|
|
28
|
-
|
|
29
|
-
# Validate amount
|
|
30
|
-
if transaction['amount'] <= 0:
|
|
31
|
-
return False, 'Invalid amount'
|
|
32
|
-
|
|
33
|
-
return True, 'Secure'
|
|
34
|
-
|
|
35
|
-
def assess_risk(self, transaction: Dict) -> Tuple[str, str]:
|
|
36
|
-
"""Assess transaction risk level"""
|
|
37
|
-
amount = transaction.get('amount', 0)
|
|
38
|
-
|
|
39
|
-
if amount > 100000:
|
|
40
|
-
return 'high', 'Large transaction amount'
|
|
41
|
-
elif amount > 10000:
|
|
42
|
-
return 'medium', 'Medium transaction amount'
|
|
43
|
-
else:
|
|
44
|
-
return 'low', 'Normal transaction'
|
|
45
|
-
|
|
46
|
-
class KeyManager:
|
|
47
|
-
"""Key management for transaction signing"""
|
|
48
|
-
|
|
49
|
-
def derive_public_key(self, private_key: str) -> str:
|
|
50
|
-
"""Derive public key from private key"""
|
|
51
|
-
if not private_key:
|
|
52
|
-
return "default_public_key"
|
|
53
|
-
return f"pub_{private_key[-16:]}"
|
|
54
|
-
|
|
55
|
-
def sign_data(self, data: str, private_key: str) -> str:
|
|
56
|
-
"""Sign data with private key"""
|
|
57
|
-
if not private_key:
|
|
58
|
-
return "default_signature"
|
|
59
|
-
return hashlib.sha256(f"{data}{private_key}".encode()).hexdigest()
|
|
60
|
-
|
|
61
|
-
class FeePoolManager:
|
|
62
|
-
"""Decentralized fee pool management"""
|
|
63
|
-
|
|
64
|
-
def __init__(self):
|
|
65
|
-
self.fee_pool_address = self._generate_fee_pool_address()
|
|
66
|
-
self.pending_fees = 0.0
|
|
67
|
-
self.distribution_blocks = 100 # Distribute fees every 100 blocks
|
|
68
|
-
self.last_distribution_block = 0
|
|
69
|
-
|
|
70
|
-
def _generate_fee_pool_address(self) -> str:
|
|
71
|
-
"""Generate deterministic fee pool address"""
|
|
72
|
-
base_data = "LUNA_FEE_POOL_V1"
|
|
73
|
-
return hashlib.sha256(base_data.encode()).hexdigest()[:32]
|
|
74
|
-
|
|
75
|
-
def collect_fee(self, fee_amount: float, transaction_hash: str) -> bool:
|
|
76
|
-
"""Collect fee into the pool"""
|
|
77
|
-
if fee_amount > 0:
|
|
78
|
-
self.pending_fees += fee_amount
|
|
79
|
-
return True
|
|
80
|
-
return False
|
|
81
|
-
|
|
82
|
-
def should_distribute(self, current_block_height: int) -> bool:
|
|
83
|
-
"""Check if it's time to distribute fees"""
|
|
84
|
-
return (current_block_height - self.last_distribution_block) >= self.distribution_blocks
|
|
85
|
-
|
|
86
|
-
def calculate_rewards(self, stakers: List[Dict], total_stake: float) -> List[Dict]:
|
|
87
|
-
"""Calculate rewards for stakers based on their stake"""
|
|
88
|
-
if total_stake <= 0 or self.pending_fees <= 0:
|
|
89
|
-
return []
|
|
90
|
-
|
|
91
|
-
rewards = []
|
|
92
|
-
for staker in stakers:
|
|
93
|
-
stake_amount = staker.get('stake', 0)
|
|
94
|
-
if stake_amount > 0:
|
|
95
|
-
share = stake_amount / total_stake
|
|
96
|
-
reward = self.pending_fees * share
|
|
97
|
-
rewards.append({
|
|
98
|
-
'address': staker['address'],
|
|
99
|
-
'reward': reward,
|
|
100
|
-
'stake_share': share
|
|
101
|
-
})
|
|
102
|
-
|
|
103
|
-
return rewards
|
|
104
|
-
|
|
105
|
-
def create_distribution_transactions(self, current_block_height: int,
|
|
106
|
-
stakers: List[Dict], total_stake: float) -> List[Dict]:
|
|
107
|
-
"""Create fee distribution transactions to stakers"""
|
|
108
|
-
if not self.should_distribute(current_block_height) or self.pending_fees <= 0:
|
|
109
|
-
return []
|
|
110
|
-
|
|
111
|
-
rewards = self.calculate_rewards(stakers, total_stake)
|
|
112
|
-
distribution_txs = []
|
|
113
|
-
|
|
114
|
-
for reward_info in rewards:
|
|
115
|
-
distribution_tx = {
|
|
116
|
-
"type": "fee_distribution",
|
|
117
|
-
"from": self.fee_pool_address,
|
|
118
|
-
"to": reward_info['address'],
|
|
119
|
-
"amount": reward_info['reward'],
|
|
120
|
-
"fee": 0.0,
|
|
121
|
-
"block_height": current_block_height,
|
|
122
|
-
"distribution_cycle": current_block_height // self.distribution_blocks,
|
|
123
|
-
"stake_share": reward_info['stake_share'],
|
|
124
|
-
"timestamp": time.time(),
|
|
125
|
-
"hash": self._generate_distribution_hash(reward_info['address'], reward_info['reward'], current_block_height)
|
|
126
|
-
}
|
|
127
|
-
distribution_txs.append(distribution_tx)
|
|
128
|
-
|
|
129
|
-
# Reset pending fees after distribution
|
|
130
|
-
self.pending_fees = 0.0
|
|
131
|
-
self.last_distribution_block = current_block_height
|
|
132
|
-
|
|
133
|
-
return distribution_txs
|
|
134
|
-
|
|
135
|
-
def _generate_distribution_hash(self, address: str, amount: float, block_height: int) -> str:
|
|
136
|
-
"""Generate unique hash for distribution transaction"""
|
|
137
|
-
data = f"fee_dist_{address}_{amount}_{block_height}_{time.time()}"
|
|
138
|
-
return hashlib.sha256(data.encode()).hexdigest()
|
|
139
|
-
|
|
140
|
-
class FeeCalculator:
|
|
141
|
-
"""Configurable fee calculation system"""
|
|
142
|
-
|
|
143
|
-
def __init__(self, fee_pool_manager: FeePoolManager):
|
|
144
|
-
self.fee_pool_manager = fee_pool_manager
|
|
145
|
-
self.fee_config = {
|
|
146
|
-
'transfer': 0.00001, # Default transfer fee
|
|
147
|
-
'gtx_genesis': 0.0, # No fee for GTX genesis
|
|
148
|
-
'reward': 0.0, # No fee for rewards
|
|
149
|
-
'stake': 0.0001, # Staking fee
|
|
150
|
-
'unstake': 0.0001, # Unstaking fee
|
|
151
|
-
'delegate': 0.00005, # Delegation fee
|
|
152
|
-
'fee_distribution': 0.0, # No fee for fee distributions
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
# Dynamic fee tiers based on transaction amount
|
|
156
|
-
self.amount_tiers = {
|
|
157
|
-
'micro': (0, 1, 0.000001),
|
|
158
|
-
'small': (1, 100, 0.00001),
|
|
159
|
-
'medium': (100, 10000, 0.0001),
|
|
160
|
-
'large': (10000, 100000, 0.001),
|
|
161
|
-
'xlarge': (100000, float('inf'), 0.01)
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
def set_fee(self, transaction_type: str, fee_amount: float):
|
|
165
|
-
"""Set custom fee for a transaction type"""
|
|
166
|
-
self.fee_config[transaction_type] = max(0.0, fee_amount)
|
|
167
|
-
|
|
168
|
-
def get_fee(self, transaction_type: str, amount: float = 0.0) -> float:
|
|
169
|
-
"""Get fee for transaction type and amount"""
|
|
170
|
-
base_fee = self.fee_config.get(transaction_type, 0.00001)
|
|
171
|
-
|
|
172
|
-
# Apply amount-based fee scaling
|
|
173
|
-
for tier_name, (min_amt, max_amt, tier_fee) in self.amount_tiers.items():
|
|
174
|
-
if min_amt <= amount < max_amt:
|
|
175
|
-
return max(base_fee, tier_fee)
|
|
176
|
-
|
|
177
|
-
return base_fee
|
|
178
|
-
|
|
179
|
-
def calculate_network_fee(self, transaction_size: int, priority: str = 'normal') -> float:
|
|
180
|
-
"""Calculate fee based on transaction size and priority"""
|
|
181
|
-
base_fee_per_byte = 0.0000001 # Base fee per byte
|
|
182
|
-
|
|
183
|
-
priority_multipliers = {
|
|
184
|
-
'low': 0.5,
|
|
185
|
-
'normal': 1.0,
|
|
186
|
-
'high': 2.0,
|
|
187
|
-
'urgent': 5.0
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
multiplier = priority_multipliers.get(priority, 1.0)
|
|
191
|
-
return transaction_size * base_fee_per_byte * multiplier
|
|
192
|
-
|
|
193
|
-
def process_transaction_fee(self, transaction: Dict) -> bool:
|
|
194
|
-
"""Process and collect transaction fee"""
|
|
195
|
-
fee = transaction.get('fee', 0)
|
|
196
|
-
if fee > 0:
|
|
197
|
-
return self.fee_pool_manager.collect_fee(fee, transaction.get('hash', ''))
|
|
198
|
-
return True
|
|
199
|
-
|
|
200
|
-
class TransactionManager:
|
|
201
|
-
"""Handles transaction creation, signing, and validation"""
|
|
202
|
-
|
|
203
|
-
def __init__(self):
|
|
204
|
-
self.security = TransactionSecurity()
|
|
205
|
-
self.key_manager = KeyManager()
|
|
206
|
-
self.fee_pool_manager = FeePoolManager()
|
|
207
|
-
self.fee_calculator = FeeCalculator(self.fee_pool_manager)
|
|
208
|
-
self.pending_by_address = {} # Track pending transactions by address
|
|
209
|
-
|
|
210
|
-
def create_transaction(self, from_address: str, to_address: str, amount: float,
|
|
211
|
-
private_key: Optional[str] = None, memo: str = "",
|
|
212
|
-
transaction_type: str = "transfer", fee_override: Optional[float] = None,
|
|
213
|
-
priority: str = 'normal') -> Dict:
|
|
214
|
-
"""Create and sign a transaction with configurable fees"""
|
|
215
|
-
|
|
216
|
-
# Calculate fee
|
|
217
|
-
if fee_override is not None:
|
|
218
|
-
fee = max(0.0, fee_override)
|
|
219
|
-
else:
|
|
220
|
-
fee = self.fee_calculator.get_fee(transaction_type, amount)
|
|
221
|
-
|
|
222
|
-
transaction = {
|
|
223
|
-
"type": transaction_type,
|
|
224
|
-
"from": from_address,
|
|
225
|
-
"to": to_address,
|
|
226
|
-
"amount": float(amount),
|
|
227
|
-
"fee": fee,
|
|
228
|
-
"nonce": int(time.time() * 1000),
|
|
229
|
-
"timestamp": time.time(),
|
|
230
|
-
"memo": memo,
|
|
231
|
-
"priority": priority,
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
# Only add cryptographic fields if private key is provided
|
|
235
|
-
if private_key:
|
|
236
|
-
transaction["public_key"] = self.key_manager.derive_public_key(private_key)
|
|
237
|
-
sign_data = self._get_signing_data(transaction)
|
|
238
|
-
signature = self.key_manager.sign_data(sign_data, private_key)
|
|
239
|
-
transaction["signature"] = signature
|
|
240
|
-
else:
|
|
241
|
-
# For unsigned transactions (like rewards or test transactions)
|
|
242
|
-
transaction["public_key"] = "unsigned"
|
|
243
|
-
transaction["signature"] = "unsigned"
|
|
244
|
-
|
|
245
|
-
transaction["hash"] = self._calculate_transaction_hash(transaction)
|
|
246
|
-
|
|
247
|
-
# Automatically collect fee
|
|
248
|
-
self.fee_calculator.process_transaction_fee(transaction)
|
|
249
|
-
|
|
250
|
-
return transaction
|
|
251
|
-
|
|
252
|
-
def distribute_fees(self, current_block_height: int, stakers: List[Dict], total_stake: float) -> List[Dict]:
|
|
253
|
-
"""Distribute collected fees to stakers"""
|
|
254
|
-
return self.fee_pool_manager.create_distribution_transactions(
|
|
255
|
-
current_block_height, stakers, total_stake
|
|
256
|
-
)
|
|
257
|
-
|
|
258
|
-
def get_fee_pool_balance(self) -> float:
|
|
259
|
-
"""Get current fee pool balance"""
|
|
260
|
-
return self.fee_pool_manager.pending_fees
|
|
261
|
-
|
|
262
|
-
def get_fee_pool_address(self) -> str:
|
|
263
|
-
"""Get fee pool address"""
|
|
264
|
-
return self.fee_pool_manager.fee_pool_address
|
|
265
|
-
|
|
266
|
-
def create_gtx_transaction(self, bill_info: Dict) -> Dict:
|
|
267
|
-
"""Create GTX Genesis transaction from mined bill"""
|
|
268
|
-
# Ensure we return a proper transaction structure
|
|
269
|
-
if "transaction_data" in bill_info:
|
|
270
|
-
return bill_info["transaction_data"]
|
|
271
|
-
else:
|
|
272
|
-
# Fallback: create basic transaction from bill info
|
|
273
|
-
return {
|
|
274
|
-
"type": "gtx_genesis",
|
|
275
|
-
"from": "mining",
|
|
276
|
-
"to": bill_info.get("owner_address", "unknown"),
|
|
277
|
-
"amount": bill_info.get("denomination", 0),
|
|
278
|
-
"fee": 0.0, # No fee for GTX genesis
|
|
279
|
-
"timestamp": time.time(),
|
|
280
|
-
"hash": f"gtx_{hashlib.sha256(json.dumps(bill_info).encode()).hexdigest()[:16]}"
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
def create_reward_transaction(self, to_address: str, amount: float, block_height: int) -> Dict:
|
|
284
|
-
"""Create block reward transaction"""
|
|
285
|
-
transaction = {
|
|
286
|
-
"type": "reward",
|
|
287
|
-
"from": "network",
|
|
288
|
-
"to": to_address,
|
|
289
|
-
"amount": float(amount),
|
|
290
|
-
"fee": 0.0, # No fee for rewards
|
|
291
|
-
"block_height": block_height,
|
|
292
|
-
"timestamp": time.time(),
|
|
293
|
-
"hash": self._generate_reward_hash(to_address, amount, block_height)
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
return transaction
|
|
297
|
-
|
|
298
|
-
def create_stake_transaction(self, from_address: str, amount: float,
|
|
299
|
-
private_key: Optional[str] = None) -> Dict:
|
|
300
|
-
"""Create staking transaction"""
|
|
301
|
-
return self.create_transaction(
|
|
302
|
-
from_address=from_address,
|
|
303
|
-
to_address="staking_pool",
|
|
304
|
-
amount=amount,
|
|
305
|
-
private_key=private_key,
|
|
306
|
-
transaction_type="stake"
|
|
307
|
-
)
|
|
308
|
-
|
|
309
|
-
def create_unstake_transaction(self, from_address: str, amount: float,
|
|
310
|
-
private_key: Optional[str] = None) -> Dict:
|
|
311
|
-
"""Create unstaking transaction"""
|
|
312
|
-
return self.create_transaction(
|
|
313
|
-
from_address="staking_pool",
|
|
314
|
-
to_address=from_address,
|
|
315
|
-
amount=amount,
|
|
316
|
-
private_key=private_key,
|
|
317
|
-
transaction_type="unstake"
|
|
318
|
-
)
|
|
319
|
-
|
|
320
|
-
def validate_transaction(self, transaction: Dict) -> Tuple[bool, str]:
|
|
321
|
-
"""Validate transaction using security module"""
|
|
322
|
-
return self.security.validate_transaction(transaction)
|
|
323
|
-
|
|
324
|
-
def validate_transaction_security(self, transaction: Dict) -> Tuple[bool, str]:
|
|
325
|
-
"""Validate transaction security"""
|
|
326
|
-
return self.security.validate_transaction_security(transaction)
|
|
327
|
-
|
|
328
|
-
def assess_transaction_risk(self, transaction: Dict) -> Tuple[str, str]:
|
|
329
|
-
"""Assess transaction risk level"""
|
|
330
|
-
return self.security.assess_risk(transaction)
|
|
331
|
-
|
|
332
|
-
def set_transaction_fee(self, transaction_type: str, fee_amount: float):
|
|
333
|
-
"""Set custom fee for transaction type"""
|
|
334
|
-
self.fee_calculator.set_fee(transaction_type, fee_amount)
|
|
335
|
-
|
|
336
|
-
def calculate_network_fee(self, transaction_size: int, priority: str = 'normal') -> float:
|
|
337
|
-
"""Calculate network fee based on size and priority"""
|
|
338
|
-
return self.fee_calculator.calculate_network_fee(transaction_size, priority)
|
|
339
|
-
|
|
340
|
-
def _get_signing_data(self, transaction: Dict) -> str:
|
|
341
|
-
"""Create data string for signing"""
|
|
342
|
-
parts = [
|
|
343
|
-
transaction["from"],
|
|
344
|
-
transaction["to"],
|
|
345
|
-
str(transaction["amount"]),
|
|
346
|
-
str(transaction.get("nonce", 0)),
|
|
347
|
-
str(transaction["timestamp"]),
|
|
348
|
-
transaction.get("memo", ""),
|
|
349
|
-
str(transaction.get("fee", 0)),
|
|
350
|
-
transaction.get("type", "transfer")
|
|
351
|
-
]
|
|
352
|
-
return "".join(parts)
|
|
353
|
-
|
|
354
|
-
def _calculate_transaction_hash(self, transaction: Dict) -> str:
|
|
355
|
-
"""Calculate transaction hash"""
|
|
356
|
-
# Create a copy without signature for consistent hashing
|
|
357
|
-
tx_copy = transaction.copy()
|
|
358
|
-
tx_copy.pop("signature", None)
|
|
359
|
-
data_string = json.dumps(tx_copy, sort_keys=True)
|
|
360
|
-
return hashlib.sha256(data_string.encode()).hexdigest() # FIXED: data_string instead of data
|
|
361
|
-
|
|
362
|
-
def _generate_reward_hash(self, to_address: str, amount: float, block_height: int) -> str:
|
|
363
|
-
"""Generate unique hash for reward transaction"""
|
|
364
|
-
data = f"reward_{to_address}_{amount}_{block_height}_{time.time()}"
|
|
365
|
-
return hashlib.sha256(data.encode()).hexdigest()
|
|
366
|
-
|
|
367
|
-
def validate_against_available_balance(self, from_address: str, amount: float,
|
|
368
|
-
available_balance: float) -> Tuple[bool, str]:
|
|
369
|
-
"""Validate that transaction amount doesn't exceed available balance"""
|
|
370
|
-
pending_amount = self.pending_by_address.get(from_address, 0.0)
|
|
371
|
-
total_pending = pending_amount + amount
|
|
372
|
-
|
|
373
|
-
if total_pending > available_balance:
|
|
374
|
-
shortage = total_pending - available_balance
|
|
375
|
-
return False, f'Insufficient available balance. Need {shortage} more (accounting for {pending_amount} in pending transactions)'
|
|
376
|
-
|
|
377
|
-
return True, 'Sufficient balance'
|
|
378
|
-
|
|
379
|
-
def add_pending_transaction(self, from_address: str, tx_hash: str, amount: float) -> bool:
|
|
380
|
-
"""Track a pending transaction (added to mempool)"""
|
|
381
|
-
if from_address not in self.pending_by_address:
|
|
382
|
-
self.pending_by_address[from_address] = 0.0
|
|
383
|
-
|
|
384
|
-
self.pending_by_address[from_address] += float(amount)
|
|
385
|
-
return True
|
|
386
|
-
|
|
387
|
-
def confirm_transaction(self, from_address: str, amount: float) -> bool:
|
|
388
|
-
"""Confirm a transaction (moved from mempool to blockchain)"""
|
|
389
|
-
if from_address in self.pending_by_address:
|
|
390
|
-
pending = self.pending_by_address[from_address]
|
|
391
|
-
new_pending = max(0.0, pending - float(amount))
|
|
392
|
-
|
|
393
|
-
if new_pending == 0:
|
|
394
|
-
del self.pending_by_address[from_address]
|
|
395
|
-
else:
|
|
396
|
-
self.pending_by_address[from_address] = new_pending
|
|
397
|
-
|
|
398
|
-
return True
|
|
399
|
-
return False
|
|
400
|
-
|
|
401
|
-
def get_pending_amount(self, from_address: str) -> float:
|
|
402
|
-
"""Get total pending transaction amount for address"""
|
|
403
|
-
return self.pending_by_address.get(from_address, 0.0)
|
|
404
|
-
|
|
405
|
-
def clear_pending_for_address(self, from_address: str) -> bool:
|
|
406
|
-
"""Clear all pending transactions for address (e.g., if they failed)"""
|
|
407
|
-
if from_address in self.pending_by_address:
|
|
408
|
-
del self.pending_by_address[from_address]
|
|
409
|
-
return True
|
|
410
|
-
|
|
411
|
-
# Additional validator class for backward compatibility
|
|
412
|
-
class TransactionValidator:
|
|
413
|
-
"""Transaction validator for risk assessment and validation"""
|
|
414
|
-
|
|
415
|
-
def __init__(self):
|
|
416
|
-
self.security = TransactionSecurity()
|
|
417
|
-
|
|
418
|
-
def assess_risk(self, transaction: Dict) -> Tuple[str, str]:
|
|
419
|
-
"""Assess transaction risk level"""
|
|
420
|
-
return self.security.assess_risk(transaction)
|
|
421
|
-
|
|
422
|
-
def validate(self, transaction: Dict) -> Tuple[bool, str]:
|
|
423
|
-
"""Validate transaction"""
|
|
424
|
-
return self.security.validate_transaction(transaction)
|
transactions/validator.py
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import time
|
|
2
|
-
from typing import Dict, Tuple, List
|
|
3
|
-
from .security import TransactionSecurity
|
|
4
|
-
|
|
5
|
-
class TransactionValidator:
|
|
6
|
-
"""Network-level transaction validation"""
|
|
7
|
-
|
|
8
|
-
def __init__(self):
|
|
9
|
-
self.security = TransactionSecurity()
|
|
10
|
-
self.recent_transactions = set()
|
|
11
|
-
self.max_recent_size = 10000
|
|
12
|
-
|
|
13
|
-
def validate_transaction(self, transaction: Dict) -> Tuple[bool, str]:
|
|
14
|
-
"""Main transaction validation entry point"""
|
|
15
|
-
|
|
16
|
-
# Check for duplicate transaction
|
|
17
|
-
tx_hash = transaction.get("hash")
|
|
18
|
-
if tx_hash in self.recent_transactions:
|
|
19
|
-
return False, "Duplicate transaction detected"
|
|
20
|
-
|
|
21
|
-
# Security validation
|
|
22
|
-
is_valid, message = self.security.validate_transaction_security(transaction)
|
|
23
|
-
if not is_valid:
|
|
24
|
-
return False, message
|
|
25
|
-
|
|
26
|
-
# Add to recent transactions
|
|
27
|
-
self._add_to_recent(tx_hash)
|
|
28
|
-
|
|
29
|
-
return True, message
|
|
30
|
-
|
|
31
|
-
def validate_transaction_batch(self, transactions: List[Dict]) -> Tuple[bool, List[str]]:
|
|
32
|
-
"""Validate multiple transactions"""
|
|
33
|
-
results = []
|
|
34
|
-
all_valid = True
|
|
35
|
-
|
|
36
|
-
for tx in transactions:
|
|
37
|
-
is_valid, message = self.validate_transaction(tx)
|
|
38
|
-
results.append(message)
|
|
39
|
-
if not is_valid:
|
|
40
|
-
all_valid = False
|
|
41
|
-
|
|
42
|
-
return all_valid, results
|
|
43
|
-
|
|
44
|
-
def verify_transaction_inclusion(self, transaction_hash: str, block_height: int) -> bool:
|
|
45
|
-
"""Verify transaction is included in blockchain"""
|
|
46
|
-
# This would typically query the blockchain
|
|
47
|
-
# For now, we'll assume if it passed validation it's included
|
|
48
|
-
return transaction_hash in self.recent_transactions
|
|
49
|
-
|
|
50
|
-
def get_transaction_risk_level(self, transaction: Dict) -> str:
|
|
51
|
-
"""Assess transaction risk level"""
|
|
52
|
-
amount = transaction.get("amount", 0)
|
|
53
|
-
security_score = self.security.calculate_security_score(transaction)
|
|
54
|
-
|
|
55
|
-
if amount > 1000000 and security_score < 80:
|
|
56
|
-
return "HIGH"
|
|
57
|
-
elif amount > 10000 and security_score < 60:
|
|
58
|
-
return "MEDIUM"
|
|
59
|
-
elif security_score < 40:
|
|
60
|
-
return "LOW"
|
|
61
|
-
else:
|
|
62
|
-
return "VERY_LOW"
|
|
63
|
-
|
|
64
|
-
def _add_to_recent(self, tx_hash: str):
|
|
65
|
-
"""Add transaction to recent set with size management"""
|
|
66
|
-
self.recent_transactions.add(tx_hash)
|
|
67
|
-
|
|
68
|
-
# Manage set size
|
|
69
|
-
if len(self.recent_transactions) > self.max_recent_size:
|
|
70
|
-
# Remove oldest entries (this is simplified)
|
|
71
|
-
self.recent_transactions = set(list(self.recent_transactions)[-self.max_recent_size:])
|
|
File without changes
|