lunalib 1.2.3__py3-none-any.whl → 1.5.2__py3-none-any.whl

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