lunalib 1.7.3__py3-none-any.whl → 1.8.0__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.
Files changed (52) hide show
  1. lunalib/.gitignore +3 -0
  2. lunalib/__pycache__/__init__.cpython-310.pyc +0 -0
  3. lunalib/core/__pycache__/__init__.cpython-310.pyc +0 -0
  4. lunalib/core/__pycache__/blockchain.cpython-310.pyc +0 -0
  5. lunalib/core/__pycache__/crypto.cpython-310.pyc +0 -0
  6. lunalib/core/__pycache__/mempool.cpython-310.pyc +0 -0
  7. lunalib/core/__pycache__/wallet.cpython-310.pyc +0 -0
  8. lunalib/core/blockchain.py +13 -16
  9. lunalib/core/mempool.py +1 -0
  10. lunalib/core/wallet.py +121 -24
  11. lunalib/core/wallet_db.py +48 -47
  12. lunalib/gtx/__pycache__/__init__.cpython-310.pyc +0 -0
  13. lunalib/gtx/__pycache__/bill_registry.cpython-310.pyc +0 -0
  14. lunalib/gtx/__pycache__/digital_bill.cpython-310.pyc +0 -0
  15. lunalib/gtx/__pycache__/genesis.cpython-310.pyc +0 -0
  16. lunalib/mining/__pycache__/__init__.cpython-310.pyc +0 -0
  17. lunalib/mining/__pycache__/cuda_manager.cpython-310.pyc +0 -0
  18. lunalib/mining/__pycache__/difficulty.cpython-310.pyc +0 -0
  19. lunalib/mining/__pycache__/miner.cpython-310.pyc +0 -0
  20. lunalib/storage/__pycache__/__init__.cpython-310.pyc +0 -0
  21. lunalib/storage/__pycache__/cache.cpython-310.pyc +0 -0
  22. lunalib/storage/__pycache__/database.cpython-310.pyc +0 -0
  23. lunalib/storage/__pycache__/encryption.cpython-310.pyc +0 -0
  24. lunalib/tests/__pycache__/conftest.cpython-310-pytest-9.0.1.pyc +0 -0
  25. lunalib/tests/__pycache__/test_blockchain.cpython-310-pytest-9.0.1.pyc +0 -0
  26. lunalib/tests/__pycache__/test_crypto.cpython-310-pytest-9.0.1.pyc +0 -0
  27. lunalib/tests/__pycache__/test_gtx.cpython-310-pytest-9.0.1.pyc +0 -0
  28. lunalib/tests/__pycache__/test_mining.cpython-310-pytest-9.0.1.pyc +0 -0
  29. lunalib/tests/__pycache__/test_storage.cpython-310-pytest-9.0.1.pyc +0 -0
  30. lunalib/tests/__pycache__/test_transactions.cpython-310-pytest-9.0.1.pyc +0 -0
  31. lunalib/tests/__pycache__/test_wallet.cpython-310-pytest-9.0.1.pyc +0 -0
  32. lunalib/tests/conftest.py +41 -0
  33. lunalib/tests/init.py +0 -0
  34. lunalib/tests/integration/__pycache__/test_integration.cpython-310-pytest-9.0.1.pyc +0 -0
  35. lunalib/tests/integration/test_integration.py +62 -0
  36. lunalib/tests/test_blockchain.py +34 -0
  37. lunalib/tests/test_crypto.py +42 -0
  38. lunalib/tests/test_gtx.py +135 -0
  39. lunalib/tests/test_mining.py +244 -0
  40. lunalib/tests/test_security_suite.py +832 -0
  41. lunalib/tests/test_storage.py +84 -0
  42. lunalib/tests/test_transactions.py +103 -0
  43. lunalib/tests/test_wallet.py +91 -0
  44. lunalib/transactions/__pycache__/__init__.cpython-310.pyc +0 -0
  45. lunalib/transactions/__pycache__/security.cpython-310.pyc +0 -0
  46. lunalib/transactions/__pycache__/transactions.cpython-310.pyc +0 -0
  47. lunalib/transactions/__pycache__/validator.cpython-310.pyc +0 -0
  48. {lunalib-1.7.3.dist-info → lunalib-1.8.0.dist-info}/METADATA +1 -1
  49. lunalib-1.8.0.dist-info/RECORD +77 -0
  50. lunalib-1.7.3.dist-info/RECORD +0 -34
  51. {lunalib-1.7.3.dist-info → lunalib-1.8.0.dist-info}/WHEEL +0 -0
  52. {lunalib-1.7.3.dist-info → lunalib-1.8.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,42 @@
1
+ import pytest
2
+ from lunalib.core.crypto import KeyManager
3
+
4
+ class TestCrypto:
5
+ def test_key_generation(self):
6
+ """Test cryptographic key generation"""
7
+ key_manager = KeyManager()
8
+
9
+ private_key = key_manager.generate_private_key()
10
+ public_key = key_manager.derive_public_key(private_key)
11
+ address = key_manager.derive_address(public_key)
12
+
13
+ assert len(private_key) == 64 # 32 bytes in hex
14
+ assert len(public_key) == 64 # 32 bytes in hex
15
+ assert address.startswith("LUN_")
16
+
17
+ def test_data_signing(self):
18
+ """Test data signing and verification"""
19
+ key_manager = KeyManager()
20
+
21
+ private_key = key_manager.generate_private_key()
22
+ public_key = key_manager.derive_public_key(private_key)
23
+
24
+ test_data = "Hello, Luna Library!"
25
+ signature = key_manager.sign_data(test_data, private_key)
26
+
27
+ # Basic signature format check
28
+ assert len(signature) == 64
29
+ assert all(c in "0123456789abcdef" for c in signature.lower())
30
+
31
+ def test_address_generation_uniqueness(self):
32
+ """Test that addresses are unique"""
33
+ key_manager = KeyManager()
34
+
35
+ addresses = set()
36
+ for _ in range(10):
37
+ private_key = key_manager.generate_private_key()
38
+ public_key = key_manager.derive_public_key(private_key)
39
+ address = key_manager.derive_address(public_key)
40
+ addresses.add(address)
41
+
42
+ assert len(addresses) == 10 # All addresses should be unique
@@ -0,0 +1,135 @@
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
+ import pytest
9
+ from lunalib.gtx.genesis import GTXGenesis
10
+ from lunalib.gtx.digital_bill import DigitalBill
11
+ import time
12
+ class TestGTXGenesis:
13
+ def test_digital_bill_creation(self, test_gtx):
14
+ """Test digital bill creation"""
15
+ bill = test_gtx.create_genesis_bill(
16
+ denomination=1000,
17
+ user_address="LUN_test_address_123",
18
+ custom_data={"issuer": "test"}
19
+ )
20
+
21
+ assert bill.denomination == 1000
22
+ assert bill.user_address == "LUN_test_address_123"
23
+ assert bill.bill_data["issuer"] == "test"
24
+ assert bill.bill_serial.startswith("GTX1000_")
25
+
26
+ def test_bill_mining_data(self, test_gtx):
27
+ """Test bill mining data generation"""
28
+ bill = test_gtx.create_genesis_bill(100, "LUN_test")
29
+ mining_data = bill.get_mining_data(nonce=123)
30
+
31
+ assert mining_data["type"] == "GTX_Genesis"
32
+ assert mining_data["denomination"] == 100
33
+ assert mining_data["nonce"] == 123
34
+ assert "previous_hash" in mining_data
35
+
36
+ def test_bill_finalization(self, test_gtx):
37
+ """Test bill finalization after mining"""
38
+ bill = test_gtx.create_genesis_bill(1000, "LUN_test")
39
+
40
+ final_bill = bill.finalize(
41
+ hash="000abc123",
42
+ nonce=12345,
43
+ mining_time=3.2
44
+ )
45
+
46
+ assert final_bill["success"] is True
47
+ assert final_bill["hash"] == "000abc123"
48
+ assert final_bill["mining_time"] == 3.2
49
+ assert "transaction_data" in final_bill
50
+
51
+ def test_bill_verification(self, test_gtx, temp_dir):
52
+ """Test bill verification with proper bill data structure"""
53
+ import time
54
+ import hashlib
55
+ from unittest.mock import patch
56
+
57
+ # Create a complete bill_info structure that matches what register_bill expects
58
+ bill_serial = "GTX_TEST_12345"
59
+ timestamp = time.time()
60
+ denomination = 100
61
+ user_address = "LUN_test_verify"
62
+
63
+ # Create metadata that will pass one of the verification methods
64
+ metadata_hash = hashlib.sha256(f"test_metadata_{timestamp}".encode()).hexdigest()
65
+ public_key = f"pub_test_key_{timestamp}"
66
+ signature = metadata_hash # This will pass METHOD 1 verification
67
+
68
+ # Create the complete bill_info structure
69
+ bill_info = {
70
+ 'bill_serial': bill_serial,
71
+ 'denomination': denomination,
72
+ 'user_address': user_address,
73
+ 'hash': hashlib.sha256(bill_serial.encode()).hexdigest(),
74
+ 'mining_time': 1.5,
75
+ 'difficulty': 4,
76
+ 'luna_value': denomination,
77
+ 'timestamp': timestamp,
78
+ 'bill_data': {
79
+ 'public_key': public_key,
80
+ 'signature': signature,
81
+ 'metadata_hash': metadata_hash,
82
+ 'issued_to': user_address,
83
+ 'front_serial': bill_serial,
84
+ 'type': 'GTX_Genesis',
85
+ 'back_serial': ''
86
+ }
87
+ }
88
+
89
+ # Register the bill first
90
+ test_gtx.bill_registry.register_bill(bill_info)
91
+
92
+ # DEBUG: Check what get_bill returns
93
+ bill_data_from_registry = test_gtx.bill_registry.get_bill(bill_serial)
94
+ safe_print(f"DEBUG: Bill data from registry: {bill_data_from_registry}")
95
+
96
+ # Test verification - should pass METHOD 1
97
+ result = test_gtx.verify_bill(bill_serial)
98
+ safe_print(f"DEBUG: Verification result: {result}")
99
+
100
+ assert result["valid"] is True
101
+
102
+ def test_invalid_bill_verification(self, test_gtx):
103
+ """Test verification of non-existent bill"""
104
+ result = test_gtx.verify_bill("GTX_invalid_serial")
105
+ assert result["valid"] is False
106
+ assert "error" in result
107
+
108
+ def test_portfolio_management(self, test_gtx, temp_dir):
109
+ """Test user portfolio functionality"""
110
+ # Use a unique user address to avoid conflicts
111
+ unique_user = f"LUN_test_user_{int(time.time())}"
112
+
113
+ # Add some test bills to registry
114
+ for denom in [100, 1000, 10000]:
115
+ bill = test_gtx.create_genesis_bill(denom, unique_user)
116
+ final_bill = bill.finalize(f"000hash{denom}", 123, 1.0)
117
+
118
+ # Register the bill properly
119
+ bill_info = {
120
+ 'bill_serial': final_bill['bill_serial'],
121
+ 'denomination': denom,
122
+ 'user_address': unique_user,
123
+ 'hash': f"000hash{denom}",
124
+ 'mining_time': 1.0,
125
+ 'difficulty': 4,
126
+ 'luna_value': denom,
127
+ 'timestamp': final_bill['timestamp'],
128
+ 'bill_data': final_bill
129
+ }
130
+ test_gtx.bill_registry.register_bill(bill_info)
131
+
132
+ portfolio = test_gtx.get_user_portfolio(unique_user)
133
+
134
+ assert portfolio["user_address"] == unique_user
135
+ assert portfolio["total_bills"] == 3
@@ -0,0 +1,244 @@
1
+ import pytest
2
+ import time
3
+ from unittest.mock import Mock, patch
4
+ from lunalib.mining.miner import GenesisMiner
5
+ from lunalib.mining.difficulty import DifficultySystem
6
+
7
+ class TestMining:
8
+ def test_difficulty_system(self):
9
+ """Test difficulty calculations with 9-tier system"""
10
+ difficulty = DifficultySystem()
11
+
12
+ # Test bill difficulties - 9 tiers
13
+ assert difficulty.get_bill_difficulty(1) == 1 # Trivial
14
+ assert difficulty.get_bill_difficulty(5) == 2 # Very Easy
15
+ assert difficulty.get_bill_difficulty(50) == 3 # Easy
16
+ assert difficulty.get_bill_difficulty(500) == 4 # Moderate
17
+ assert difficulty.get_bill_difficulty(5000) == 5 # Standard
18
+ assert difficulty.get_bill_difficulty(50000) == 6 # Challenging
19
+ assert difficulty.get_bill_difficulty(500000) == 7 # Hard
20
+ assert difficulty.get_bill_difficulty(5000000) == 8 # Very Hard
21
+ assert difficulty.get_bill_difficulty(50000000) == 9 # Extreme
22
+
23
+ # Test transaction difficulties - 9 tiers
24
+ assert difficulty.get_transaction_difficulty(0.0005) == 1 # Trivial
25
+ assert difficulty.get_transaction_difficulty(0.005) == 2 # Very Easy
26
+ assert difficulty.get_transaction_difficulty(0.05) == 3 # Easy
27
+ assert difficulty.get_transaction_difficulty(0.5) == 4 # Moderate
28
+ assert difficulty.get_transaction_difficulty(5) == 5 # Standard
29
+ assert difficulty.get_transaction_difficulty(50) == 6 # Challenging
30
+ assert difficulty.get_transaction_difficulty(500) == 7 # Hard
31
+ assert difficulty.get_transaction_difficulty(5000) == 8 # Very Hard
32
+ assert difficulty.get_transaction_difficulty(50000) == 9 # Extreme
33
+
34
+ # Test edge cases and boundary values
35
+ assert difficulty.get_bill_difficulty(0) == 1 # Zero amount
36
+ assert difficulty.get_bill_difficulty(-100) == 1 # Negative amount
37
+ assert difficulty.get_bill_difficulty(999999999999) == 9 # Huge number
38
+
39
+ # Test boundary values for each tier
40
+ assert difficulty.get_bill_difficulty(1) == 1 # Tier 1 upper bound
41
+ assert difficulty.get_bill_difficulty(10) == 2 # Tier 2 upper bound
42
+ assert difficulty.get_bill_difficulty(100) == 3 # Tier 3 upper bound
43
+ assert difficulty.get_bill_difficulty(1000) == 4 # Tier 4 upper bound
44
+ assert difficulty.get_bill_difficulty(10000) == 5 # Tier 5 upper bound
45
+ assert difficulty.get_bill_difficulty(100000) == 6 # Tier 6 upper bound
46
+ assert difficulty.get_bill_difficulty(1000000) == 7 # Tier 7 upper bound
47
+ assert difficulty.get_bill_difficulty(10000000) == 8 # Tier 8 upper bound
48
+
49
+ # Test transaction edge cases
50
+ assert difficulty.get_transaction_difficulty(0) == 1 # Zero amount
51
+ assert difficulty.get_transaction_difficulty(-50) == 1 # Negative amount
52
+ assert difficulty.get_transaction_difficulty(999999999) == 9 # Huge amount
53
+
54
+ # Test difficulty names for all tiers
55
+ assert difficulty.get_difficulty_name(1) == "Trivial"
56
+ assert difficulty.get_difficulty_name(2) == "Very Easy"
57
+ assert difficulty.get_difficulty_name(3) == "Easy"
58
+ assert difficulty.get_difficulty_name(4) == "Moderate"
59
+ assert difficulty.get_difficulty_name(5) == "Standard"
60
+ assert difficulty.get_difficulty_name(6) == "Challenging"
61
+ assert difficulty.get_difficulty_name(7) == "Hard"
62
+ assert difficulty.get_difficulty_name(8) == "Very Hard"
63
+ assert difficulty.get_difficulty_name(9) == "Extreme"
64
+ assert difficulty.get_difficulty_name(999) == "Unknown" # Invalid level
65
+
66
+ # Test difficulty colors
67
+ assert difficulty.get_difficulty_color(1) == "🟢"
68
+ assert difficulty.get_difficulty_color(5) == "🟠"
69
+ assert difficulty.get_difficulty_color(9) == "💀"
70
+
71
+ # Test mining rewards with 9-tier system
72
+ reward_fast = difficulty.calculate_mining_reward(1000, 5) # 5 seconds - 50% bonus
73
+ reward_medium = difficulty.calculate_mining_reward(1000, 15) # 15 seconds - 20% bonus
74
+ reward_slow = difficulty.calculate_mining_reward(1000, 60) # 60 seconds - no bonus
75
+
76
+ assert reward_fast > reward_medium > reward_slow
77
+ assert reward_fast == 1500.0 # 1000 * 1.5
78
+ assert reward_medium == 1200.0 # 1000 * 1.2
79
+ assert reward_slow == 1000.0 # 1000 * 1.0
80
+
81
+ # Test expected mining time calculations for different tiers
82
+ time_trivial = difficulty.get_expected_mining_time(1, 1000000)
83
+ time_easy = difficulty.get_expected_mining_time(3, 1000000)
84
+ time_standard = difficulty.get_expected_mining_time(5, 1000000)
85
+ time_hard = difficulty.get_expected_mining_time(7, 1000000)
86
+ time_extreme = difficulty.get_expected_mining_time(9, 1000000)
87
+
88
+ # Higher difficulty should take exponentially longer
89
+ assert time_extreme > time_hard > time_standard > time_easy > time_trivial
90
+
91
+ # Test invalid difficulty levels
92
+ assert difficulty.get_expected_mining_time(0, 1000000) == float('inf')
93
+ assert difficulty.get_expected_mining_time(10, 1000000) == float('inf')
94
+
95
+ def test_mining_reward_calculation(self):
96
+ """Test mining reward calculations with 9-tier system"""
97
+ difficulty = DifficultySystem()
98
+
99
+ # Test base rewards for different denominations
100
+ reward_small = difficulty.calculate_mining_reward(10, 10) # Small bill, fast mining
101
+ reward_medium = difficulty.calculate_mining_reward(1000, 10) # Medium bill, fast mining
102
+ reward_large = difficulty.calculate_mining_reward(100000, 10) # Large bill, fast mining
103
+
104
+ # Test time-based bonuses across different tiers
105
+ reward_ultra_fast = difficulty.calculate_mining_reward(1000, 2) # 2 seconds - 50% bonus
106
+ reward_fast = difficulty.calculate_mining_reward(1000, 5) # 5 seconds - 50% bonus
107
+ reward_medium_time = difficulty.calculate_mining_reward(1000, 15) # 15 seconds - 20% bonus
108
+ reward_slow = difficulty.calculate_mining_reward(1000, 35) # 35 seconds - no bonus
109
+ reward_very_slow = difficulty.calculate_mining_reward(1000, 70) # 70 seconds - no bonus
110
+
111
+ # Verify bonus tiers work correctly
112
+ assert reward_ultra_fast == reward_fast == 1500.0 # Both get 50% bonus
113
+ assert reward_medium_time == 1200.0 # 20% bonus
114
+ assert reward_slow == reward_very_slow == 1000.0 # No bonus
115
+
116
+ # Verify faster mining always gives better rewards
117
+ assert reward_ultra_fast > reward_medium_time > reward_slow
118
+
119
+ # Test edge cases
120
+ zero_reward = difficulty.calculate_mining_reward(0, 5)
121
+ negative_reward = difficulty.calculate_mining_reward(-100, 5)
122
+ assert zero_reward == 0
123
+ assert negative_reward == 0
124
+
125
+ @patch('lunalib.mining.miner.GenesisMiner._perform_mining')
126
+ def test_bill_mining_success(self, mock_mining, test_miner, test_wallet):
127
+ """Test successful bill mining across different tiers"""
128
+ wallet, wallet_data = test_wallet
129
+
130
+ # Test mining for different difficulty tiers
131
+ test_cases = [
132
+ (10, 2), # Very Easy tier
133
+ (100, 3), # Easy tier
134
+ (1000, 4), # Moderate tier
135
+ (10000, 5), # Standard tier
136
+ ]
137
+
138
+ for denomination, expected_difficulty in test_cases:
139
+ # Mock successful mining
140
+ mock_mining.return_value = {
141
+ "success": True,
142
+ "hash": "0" * expected_difficulty + "abc123",
143
+ "nonce": 12345,
144
+ "mining_time": 2.5
145
+ }
146
+
147
+ result = test_miner.mine_bill(denomination, wallet_data['address'])
148
+
149
+ assert result['success'] is True
150
+ assert result['denomination'] == denomination
151
+ assert result['luna_value'] == denomination # 1:1 ratio
152
+ assert 'bill_serial' in result
153
+ assert 'mining_time' in result
154
+
155
+ @patch('lunalib.mining.miner.GenesisMiner._perform_mining')
156
+ def test_high_difficulty_mining(self, mock_mining, test_miner, test_wallet):
157
+ """Test mining for high difficulty tiers"""
158
+ wallet, wallet_data = test_wallet
159
+
160
+ # Test high difficulty bills
161
+ high_tier_cases = [
162
+ (100000, 6), # Challenging tier
163
+ (1000000, 7), # Hard tier
164
+ (10000000, 8), # Very Hard tier
165
+ ]
166
+
167
+ for denomination, expected_difficulty in high_tier_cases:
168
+ mock_mining.return_value = {
169
+ "success": True,
170
+ "hash": "0" * expected_difficulty + "def456",
171
+ "nonce": 99999,
172
+ "mining_time": 30.0 # Longer mining time for higher difficulty
173
+ }
174
+
175
+ result = test_miner.mine_bill(denomination, wallet_data['address'])
176
+
177
+ assert result['success'] is True
178
+ assert result['denomination'] == denomination
179
+ # High denomination bills might have additional validation
180
+ assert result['luna_value'] >= denomination
181
+
182
+ def test_mining_stop_functionality(self, test_miner):
183
+ """Test mining stop functionality"""
184
+ # Test starting and stopping mining
185
+ test_miner.mining_active = True
186
+ assert test_miner.mining_active is True
187
+
188
+ test_miner.stop_mining()
189
+ assert test_miner.mining_active is False
190
+
191
+ # Test stopping when already stopped
192
+ test_miner.stop_mining()
193
+ assert test_miner.mining_active is False
194
+
195
+ def test_invalid_denomination(self, test_miner, test_wallet):
196
+ """Test mining with invalid denominations"""
197
+ wallet, wallet_data = test_wallet
198
+
199
+ invalid_denominations = [
200
+ -100, # Negative
201
+ 0, # Zero
202
+ 999, # Unusual amount
203
+ -999999, # Large negative
204
+ ]
205
+
206
+ for invalid_denom in invalid_denominations:
207
+ result = test_miner.mine_bill(invalid_denom, wallet_data['address'])
208
+ assert result['success'] is False
209
+ assert 'error' in result
210
+
211
+ @patch('lunalib.mining.miner.GenesisMiner._perform_mining')
212
+ def test_mining_failure(self, mock_mining, test_miner, test_wallet):
213
+ """Test mining failure scenarios"""
214
+ wallet, wallet_data = test_wallet
215
+
216
+ # Mock mining failure
217
+ mock_mining.return_value = {
218
+ "success": False,
219
+ "error": "Mining timeout"
220
+ }
221
+
222
+ result = test_miner.mine_bill(100, wallet_data['address'])
223
+
224
+ assert result['success'] is False
225
+ assert 'error' in result
226
+
227
+ def test_difficulty_progression(self):
228
+ """Test that difficulty progression makes sense"""
229
+ difficulty = DifficultySystem()
230
+
231
+ # Test that each tier is more difficult than the previous
232
+ for i in range(1, 9):
233
+ time_lower = difficulty.get_expected_mining_time(i, 1000000)
234
+ time_higher = difficulty.get_expected_mining_time(i + 1, 1000000)
235
+ assert time_higher > time_lower, f"Tier {i+1} should be harder than tier {i}"
236
+
237
+ def test_mining_auto_stop(self, test_miner):
238
+ """Test that mining can be stopped automatically"""
239
+ test_miner.start_auto_mining([100, 200, 300], "test_address")
240
+ assert test_miner.mining_active is True
241
+
242
+ # Stop mining and verify
243
+ test_miner.stop_mining()
244
+ assert test_miner.mining_active is False