astreum 0.1.16__py3-none-any.whl → 0.1.18__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 astreum might be problematic. Click here for more details.

astreum/node/__init__.py CHANGED
@@ -1,480 +1,475 @@
1
- import os
2
- import time
3
- import threading
4
- import random
5
- from typing import Tuple, Optional, List, Dict
6
- import json
7
- from cryptography.hazmat.primitives.asymmetric import ed25519
8
- from cryptography.hazmat.primitives import serialization
1
+ # import time
2
+ # import threading
3
+ # from typing import List
4
+ # from cryptography.hazmat.primitives.asymmetric import ed25519
5
+ # from cryptography.hazmat.primitives import serialization
9
6
 
10
- from .relay import Relay, Topic
11
- from .relay.peer import Peer
12
- from .models import Storage, Block, Transaction
13
- from .machine import AstreumMachine
14
- from .utils import encode, decode, hash_data
15
- from astreum.lispeum.storage import store_expr, get_expr_from_storage
7
+ # from .relay import Relay, Topic
8
+ # from .machine import AstreumMachine
9
+ # from .utils import hash_data
10
+ # from .validation.block import Block
11
+ # from .storage import Storage
16
12
 
17
- # Import our validation components using the new functional approach
18
- from .validation import (
19
- validate_block,
20
- create_block,
21
- create_genesis_block,
22
- compute_vdf,
23
- verify_vdf,
24
- select_validator,
25
- select_validator_for_slot,
26
- Account,
27
- get_validator_stake,
28
- is_validator,
29
- VALIDATION_ADDRESS,
30
- BURN_ADDRESS,
31
- MIN_STAKE_AMOUNT,
32
- SLOT_DURATION,
33
- VDF_DIFFICULTY
34
- )
35
- from .validation.state import (
36
- add_block_to_state,
37
- validate_and_apply_block,
38
- create_account_state,
39
- get_validator_for_slot,
40
- select_best_chain,
41
- compare_chains,
42
- get_validator_set
43
- )
44
- from .validation.adapter import BlockAdapter, TransactionAdapter, AccountAdapter
13
+ # # Import our validation components using the new functional approach
14
+ # from .validation import (
15
+ # validate_block,
16
+ # create_block,
17
+ # create_genesis_block,
18
+ # compute_vdf,
19
+ # verify_vdf,
20
+ # select_validator,
21
+ # select_validator_for_slot,
22
+ # get_validator_stake,
23
+ # is_validator,
24
+ # VALIDATION_ADDRESS,
25
+ # BURN_ADDRESS,
26
+ # MIN_STAKE_AMOUNT,
27
+ # SLOT_DURATION,
28
+ # VDF_DIFFICULTY
29
+ # )
30
+ # from .validation.state import (
31
+ # add_block_to_state,
32
+ # validate_and_apply_block,
33
+ # create_account_state,
34
+ # get_validator_for_slot,
35
+ # select_best_chain,
36
+ # compare_chains,
37
+ # get_validator_set
38
+ # )
39
+ # from .validation.adapter import BlockAdapter, TransactionAdapter
45
40
 
46
- class Node:
47
- def __init__(self, config: dict):
48
- # Ensure config is a dictionary, but allow it to be None
49
- self.config = config if config is not None else {}
50
-
51
- # Handle validation key if provided
52
- self.validation_private_key = None
53
- self.validation_public_key = None
54
- self.is_validator = False
55
-
56
- # Extract validation private key from config
57
- if 'validation_private_key' in self.config:
58
- try:
59
- key_bytes = bytes.fromhex(self.config['validation_private_key'])
60
- self.validation_private_key = ed25519.Ed25519PrivateKey.from_private_bytes(key_bytes)
61
- self.validation_public_key = self.validation_private_key.public_key()
62
- self.is_validator = True
41
+ # class Node:
42
+ # def __init__(self, config: dict):
43
+ # # Ensure config is a dictionary, but allow it to be None
44
+ # self.config = config if config is not None else {}
45
+
46
+ # # Handle validation key if provided
47
+ # self.validation_private_key = None
48
+ # self.validation_public_key = None
49
+ # self.is_validator = False
50
+
51
+ # # Extract validation private key from config
52
+ # if 'validation_private_key' in self.config:
53
+ # try:
54
+ # key_bytes = bytes.fromhex(self.config['validation_private_key'])
55
+ # self.validation_private_key = ed25519.Ed25519PrivateKey.from_private_bytes(key_bytes)
56
+ # self.validation_public_key = self.validation_private_key.public_key()
57
+ # self.is_validator = True
63
58
 
64
- # Set validation_route to True in config so relay will join validation route
65
- self.config['validation_route'] = True
66
- print(f"Node is configured as a validator with validation key")
67
- except Exception as e:
68
- print(f"Error loading validation private key: {e}")
69
-
70
- # Initialize relay with our config
71
- self.relay = Relay(self.config)
72
-
73
- # Get the node_id from relay
74
- self.node_id = self.relay.node_id
75
-
76
- # Initialize storage
77
- self.storage = Storage(self.config)
78
- self.storage.node = self # Set the storage node reference to self
79
-
80
- # Initialize blockchain state
81
- self.blockchain = create_account_state(self.config)
82
-
83
- # Store our validator info if we're a validator
84
- if self.is_validator and self.validation_public_key:
85
- self.validator_address = self.validation_public_key.public_bytes(
86
- encoding=serialization.Encoding.Raw,
87
- format=serialization.PublicFormat.Raw
88
- )
89
- self.validator_private_bytes = self.validation_private_key.private_bytes(
90
- encoding=serialization.Encoding.Raw,
91
- format=serialization.PrivateFormat.Raw,
92
- encryption_algorithm=serialization.NoEncryption()
93
- )
94
- print(f"Registered validator with address: {self.validator_address.hex()}")
95
- else:
96
- self.validator_address = None
97
- self.validator_private_bytes = None
98
-
99
- # Latest block of the chain this node is following
100
- self.latest_block = None
101
- self.followed_chain_id = self.config.get('followed_chain_id', None)
102
-
103
- # Initialize machine
104
- self.machine = AstreumMachine(node=self)
105
-
106
- # Register message handlers
107
- self.relay.message_handlers[Topic.PEER_ROUTE] = self._handle_peer_route
108
- self.relay.message_handlers[Topic.PING] = self._handle_ping
109
- self.relay.message_handlers[Topic.PONG] = self._handle_pong
110
- self.relay.message_handlers[Topic.OBJECT_REQUEST] = self._handle_object_request
111
- self.relay.message_handlers[Topic.OBJECT_RESPONSE] = self._handle_object_response
112
- self.relay.message_handlers[Topic.ROUTE_REQUEST] = self._handle_route_request
113
- self.relay.message_handlers[Topic.ROUTE] = self._handle_route
114
- self.relay.message_handlers[Topic.LATEST_BLOCK_REQUEST] = self._handle_latest_block_request
115
- self.relay.message_handlers[Topic.LATEST_BLOCK] = self._handle_latest_block
116
- self.relay.message_handlers[Topic.TRANSACTION] = self._handle_transaction
117
- self.relay.message_handlers[Topic.BLOCK_REQUEST] = self._handle_block_request
118
- self.relay.message_handlers[Topic.BLOCK_RESPONSE] = self._handle_block_response
119
-
120
- # Initialize latest block from storage if available
121
- self._initialize_latest_block()
122
-
123
- # Candidate chains that might be adopted
124
- self.candidate_chains = {} # chain_id -> {'latest_block': block, 'timestamp': time.time()}
125
- self.pending_blocks = {} # block_hash -> {'block': block, 'timestamp': time.time()}
126
-
127
- # Threads for validation and chain monitoring
128
- self.running = False
129
- self.main_chain_validation_thread = None
130
- self.candidate_chain_validation_thread = None
131
-
132
- # Pending transactions for a block
133
- self.pending_transactions = {} # tx_hash -> {'transaction': tx, 'timestamp': time.time()}
134
-
135
- # Last block production attempt time
136
- self.last_block_attempt_time = 0
59
+ # # Set validation_route to True in config so relay will join validation route
60
+ # self.config['validation_route'] = True
61
+ # print(f"Node is configured as a validator with validation key")
62
+ # except Exception as e:
63
+ # print(f"Error loading validation private key: {e}")
64
+
65
+ # # Initialize relay with our config
66
+ # self.relay = Relay(self.config)
67
+
68
+ # # Get the node_id from relay
69
+ # self.node_id = self.relay.node_id
70
+
71
+ # # Initialize storage
72
+ # self.storage = Storage(self.config)
73
+ # self.storage.node = self # Set the storage node reference to self
74
+
75
+ # # Initialize blockchain state
76
+ # self.blockchain = create_account_state(self.config)
77
+
78
+ # # Store our validator info if we're a validator
79
+ # if self.is_validator and self.validation_public_key:
80
+ # self.validator_address = self.validation_public_key.public_bytes(
81
+ # encoding=serialization.Encoding.Raw,
82
+ # format=serialization.PublicFormat.Raw
83
+ # )
84
+ # self.validator_private_bytes = self.validation_private_key.private_bytes(
85
+ # encoding=serialization.Encoding.Raw,
86
+ # format=serialization.PrivateFormat.Raw,
87
+ # encryption_algorithm=serialization.NoEncryption()
88
+ # )
89
+ # print(f"Registered validator with address: {self.validator_address.hex()}")
90
+ # else:
91
+ # self.validator_address = None
92
+ # self.validator_private_bytes = None
93
+
94
+ # # Latest block of the chain this node is following
95
+ # self.latest_block = None
96
+ # self.followed_chain_id = self.config.get('followed_chain_id', None)
97
+
98
+ # # Initialize machine
99
+ # self.machine = AstreumMachine(node=self)
100
+
101
+ # # Register message handlers
102
+ # self.relay.message_handlers[Topic.PEER_ROUTE] = self._handle_peer_route
103
+ # self.relay.message_handlers[Topic.PING] = self._handle_ping
104
+ # self.relay.message_handlers[Topic.PONG] = self._handle_pong
105
+ # self.relay.message_handlers[Topic.OBJECT_REQUEST] = self._handle_object_request
106
+ # self.relay.message_handlers[Topic.OBJECT_RESPONSE] = self._handle_object_response
107
+ # self.relay.message_handlers[Topic.ROUTE_REQUEST] = self._handle_route_request
108
+ # self.relay.message_handlers[Topic.ROUTE] = self._handle_route
109
+ # self.relay.message_handlers[Topic.LATEST_BLOCK_REQUEST] = self._handle_latest_block_request
110
+ # self.relay.message_handlers[Topic.LATEST_BLOCK] = self._handle_latest_block
111
+ # self.relay.message_handlers[Topic.TRANSACTION] = self._handle_transaction
112
+ # self.relay.message_handlers[Topic.BLOCK_REQUEST] = self._handle_block_request
113
+ # self.relay.message_handlers[Topic.BLOCK_RESPONSE] = self._handle_block_response
114
+
115
+ # # Initialize latest block from storage if available
116
+ # self._initialize_latest_block()
117
+
118
+ # # Candidate chains that might be adopted
119
+ # self.candidate_chains = {} # chain_id -> {'latest_block': block, 'timestamp': time.time()}
120
+ # self.pending_blocks = {} # block_hash -> {'block': block, 'timestamp': time.time()}
121
+
122
+ # # Threads for validation and chain monitoring
123
+ # self.running = False
124
+ # self.main_chain_validation_thread = None
125
+ # self.candidate_chain_validation_thread = None
126
+
127
+ # # Pending transactions for a block
128
+ # self.pending_transactions = {} # tx_hash -> {'transaction': tx, 'timestamp': time.time()}
129
+
130
+ # # Last block production attempt time
131
+ # self.last_block_attempt_time = 0
137
132
 
138
- def start(self):
139
- """Start the node."""
140
- self.running = True
141
-
142
- # Start relay
143
- self.relay.start()
144
-
145
- # Start chain monitoring thread
146
- self.main_chain_validation_thread = threading.Thread(
147
- target=self._main_chain_validation_loop,
148
- name="MainChainValidation"
149
- )
150
- self.main_chain_validation_thread.daemon = True
151
- self.main_chain_validation_thread.start()
152
-
153
- self.candidate_chain_validation_thread = threading.Thread(
154
- target=self._candidate_chain_validation_loop,
155
- name="CandidateChainValidation"
156
- )
157
- self.candidate_chain_validation_thread.daemon = True
158
- self.candidate_chain_validation_thread.start()
159
-
160
- # Set up recurring block query tasks
161
- main_query_thread = threading.Thread(
162
- target=self._block_query_loop,
163
- args=('main',),
164
- daemon=True
165
- )
166
- main_query_thread.start()
167
-
168
- validation_query_thread = threading.Thread(
169
- target=self._block_query_loop,
170
- args=('validation',),
171
- daemon=True
172
- )
173
- validation_query_thread.start()
174
-
175
- print(f"Node started with ID {self.node_id.hex()}")
133
+ # def start(self):
134
+ # """Start the node."""
135
+ # self.running = True
136
+
137
+ # # Start relay
138
+ # self.relay.start()
139
+
140
+ # # Start chain monitoring thread
141
+ # self.main_chain_validation_thread = threading.Thread(
142
+ # target=self._main_chain_validation_loop,
143
+ # name="MainChainValidation"
144
+ # )
145
+ # self.main_chain_validation_thread.daemon = True
146
+ # self.main_chain_validation_thread.start()
147
+
148
+ # self.candidate_chain_validation_thread = threading.Thread(
149
+ # target=self._candidate_chain_validation_loop,
150
+ # name="CandidateChainValidation"
151
+ # )
152
+ # self.candidate_chain_validation_thread.daemon = True
153
+ # self.candidate_chain_validation_thread.start()
154
+
155
+ # # Set up recurring block query tasks
156
+ # main_query_thread = threading.Thread(
157
+ # target=self._block_query_loop,
158
+ # args=('main',),
159
+ # daemon=True
160
+ # )
161
+ # main_query_thread.start()
162
+
163
+ # validation_query_thread = threading.Thread(
164
+ # target=self._block_query_loop,
165
+ # args=('validation',),
166
+ # daemon=True
167
+ # )
168
+ # validation_query_thread.start()
169
+
170
+ # print(f"Node started with ID {self.node_id.hex()}")
176
171
 
177
- def stop(self):
178
- """Stop the node and all its services."""
179
- self.running = False
172
+ # def stop(self):
173
+ # """Stop the node and all its services."""
174
+ # self.running = False
180
175
 
181
- # Stop all threads
182
- if self.main_chain_validation_thread and self.main_chain_validation_thread.is_alive():
183
- self.main_chain_validation_thread.join(timeout=1.0)
176
+ # # Stop all threads
177
+ # if self.main_chain_validation_thread and self.main_chain_validation_thread.is_alive():
178
+ # self.main_chain_validation_thread.join(timeout=1.0)
184
179
 
185
- if self.candidate_chain_validation_thread and self.candidate_chain_validation_thread.is_alive():
186
- self.candidate_chain_validation_thread.join(timeout=1.0)
180
+ # if self.candidate_chain_validation_thread and self.candidate_chain_validation_thread.is_alive():
181
+ # self.candidate_chain_validation_thread.join(timeout=1.0)
187
182
 
188
- # Stop relay last
189
- if self.relay:
190
- self.relay.stop()
183
+ # # Stop relay last
184
+ # if self.relay:
185
+ # self.relay.stop()
191
186
 
192
- print("Node stopped")
187
+ # print("Node stopped")
193
188
 
194
- def _main_chain_validation_loop(self):
195
- """
196
- Main validation loop for the primary blockchain.
197
- This thread prioritizes validating blocks on the main chain we're following.
198
- """
199
- while self.running:
200
- try:
201
- # Update latest block if we don't have one yet
202
- if not self.latest_block and hasattr(self.blockchain, 'get_latest_block'):
203
- self.latest_block = self.blockchain.get_latest_block()
189
+ # def _main_chain_validation_loop(self):
190
+ # """
191
+ # Main validation loop for the primary blockchain.
192
+ # This thread prioritizes validating blocks on the main chain we're following.
193
+ # """
194
+ # while self.running:
195
+ # try:
196
+ # # Update latest block if we don't have one yet
197
+ # if not self.latest_block and hasattr(self.blockchain, 'get_latest_block'):
198
+ # self.latest_block = self.blockchain.get_latest_block()
204
199
 
205
- # Process any blocks that extend our main chain immediately
206
- self._process_main_chain_blocks()
200
+ # # Process any blocks that extend our main chain immediately
201
+ # self._process_main_chain_blocks()
207
202
 
208
- # Attempt block production if we are a validator
209
- if self.is_validator and self.validator_address:
210
- self._attempt_block_production()
203
+ # # Attempt block production if we are a validator
204
+ # if self.is_validator and self.validator_address:
205
+ # self._attempt_block_production()
211
206
 
212
- # Cleanup old items
213
- self._prune_pending_items()
207
+ # # Cleanup old items
208
+ # self._prune_pending_items()
214
209
 
215
- # Sleep to prevent high CPU usage
216
- time.sleep(0.1) # Short sleep for main chain validation
217
- except Exception as e:
218
- print(f"Error in main chain validation loop: {e}")
219
- time.sleep(1) # Longer sleep on error
210
+ # # Sleep to prevent high CPU usage
211
+ # time.sleep(0.1) # Short sleep for main chain validation
212
+ # except Exception as e:
213
+ # print(f"Error in main chain validation loop: {e}")
214
+ # time.sleep(1) # Longer sleep on error
220
215
 
221
- def _candidate_chain_validation_loop(self):
222
- """
223
- Validation loop for candidate chains (potential forks).
224
- This thread handles validation of blocks from alternate chains
225
- without slowing down the main chain processing.
226
- """
227
- while self.running:
228
- try:
229
- # Process candidate chains
230
- self._evaluate_candidate_chains()
216
+ # def _candidate_chain_validation_loop(self):
217
+ # """
218
+ # Validation loop for candidate chains (potential forks).
219
+ # This thread handles validation of blocks from alternate chains
220
+ # without slowing down the main chain processing.
221
+ # """
222
+ # while self.running:
223
+ # try:
224
+ # # Process candidate chains
225
+ # self._evaluate_candidate_chains()
231
226
 
232
- # Prune old candidate chains
233
- self._prune_candidate_chains()
227
+ # # Prune old candidate chains
228
+ # self._prune_candidate_chains()
234
229
 
235
- # Sleep longer for candidate chain validation (lower priority)
236
- time.sleep(1) # Longer sleep for candidate chain validation
237
- except Exception as e:
238
- print(f"Error in candidate chain validation loop: {e}")
239
- time.sleep(2) # Even longer sleep on error
230
+ # # Sleep longer for candidate chain validation (lower priority)
231
+ # time.sleep(1) # Longer sleep for candidate chain validation
232
+ # except Exception as e:
233
+ # print(f"Error in candidate chain validation loop: {e}")
234
+ # time.sleep(2) # Even longer sleep on error
240
235
 
241
- def _prune_pending_items(self):
242
- """Remove old pending blocks and transactions."""
243
- current_time = time.time()
244
-
245
- # Prune old pending blocks (older than 1 hour)
246
- blocks_to_remove = [
247
- block_hash for block_hash, data in self.pending_blocks.items()
248
- if current_time - data['timestamp'] > 3600 # 1 hour
249
- ]
250
- for block_hash in blocks_to_remove:
251
- del self.pending_blocks[block_hash]
236
+ # def _prune_pending_items(self):
237
+ # """Remove old pending blocks and transactions."""
238
+ # current_time = time.time()
239
+
240
+ # # Prune old pending blocks (older than 1 hour)
241
+ # blocks_to_remove = [
242
+ # block_hash for block_hash, data in self.pending_blocks.items()
243
+ # if current_time - data['timestamp'] > 3600 # 1 hour
244
+ # ]
245
+ # for block_hash in blocks_to_remove:
246
+ # del self.pending_blocks[block_hash]
252
247
 
253
- # Prune old pending transactions (older than 30 minutes)
254
- txs_to_remove = [
255
- tx_hash for tx_hash, data in self.pending_transactions.items()
256
- if current_time - data['timestamp'] > 1800 # 30 minutes
257
- ]
258
- for tx_hash in txs_to_remove:
259
- del self.pending_transactions[tx_hash]
248
+ # # Prune old pending transactions (older than 30 minutes)
249
+ # txs_to_remove = [
250
+ # tx_hash for tx_hash, data in self.pending_transactions.items()
251
+ # if current_time - data['timestamp'] > 1800 # 30 minutes
252
+ # ]
253
+ # for tx_hash in txs_to_remove:
254
+ # del self.pending_transactions[tx_hash]
260
255
 
261
- def _process_main_chain_blocks(self):
262
- """
263
- Process blocks that extend our current main chain.
264
- Prioritizes blocks that build on our latest block.
265
- """
266
- # Skip if we don't have a latest block yet
267
- if not self.latest_block:
268
- return
256
+ # def _process_main_chain_blocks(self):
257
+ # """
258
+ # Process blocks that extend our current main chain.
259
+ # Prioritizes blocks that build on our latest block.
260
+ # """
261
+ # # Skip if we don't have a latest block yet
262
+ # if not self.latest_block:
263
+ # return
269
264
 
270
- # Get the hash of our latest block
271
- latest_hash = self.latest_block.get_hash()
265
+ # # Get the hash of our latest block
266
+ # latest_hash = self.latest_block.get_hash()
272
267
 
273
- # Find any pending blocks that build on our latest block
274
- main_chain_blocks = []
275
- for block_hash, data in list(self.pending_blocks.items()):
276
- block = data['block']
268
+ # # Find any pending blocks that build on our latest block
269
+ # main_chain_blocks = []
270
+ # for block_hash, data in list(self.pending_blocks.items()):
271
+ # block = data['block']
277
272
 
278
- # Check if this block extends our latest block
279
- if block.previous == latest_hash:
280
- main_chain_blocks.append(block)
273
+ # # Check if this block extends our latest block
274
+ # if block.previous == latest_hash:
275
+ # main_chain_blocks.append(block)
281
276
 
282
- # Process found blocks
283
- for block in main_chain_blocks:
284
- self._validate_and_process_main_chain_block(block)
277
+ # # Process found blocks
278
+ # for block in main_chain_blocks:
279
+ # self._validate_and_process_main_chain_block(block)
285
280
 
286
- def _validate_and_process_main_chain_block(self, block: Block):
287
- """
288
- Validate and process a block that extends our main chain.
289
-
290
- Args:
291
- block: Block to validate and process
292
- """
293
- try:
294
- # Validate block
295
- is_valid = validate_block(block, self.blockchain.get_accounts_at_block(block.previous), self.blockchain.get_blocks())
281
+ # def _validate_and_process_main_chain_block(self, block: Block):
282
+ # """
283
+ # Validate and process a block that extends our main chain.
284
+
285
+ # Args:
286
+ # block: Block to validate and process
287
+ # """
288
+ # try:
289
+ # # Validate block
290
+ # is_valid = validate_block(block, self.blockchain.get_accounts_at_block(block.previous), self.blockchain.get_blocks())
296
291
 
297
- if is_valid:
298
- # Apply block to our state
299
- success = validate_and_apply_block(self.blockchain, block)
300
- if success:
301
- print(f"Applied valid block {block.number} to blockchain state")
302
- self._update_latest_block(block)
303
- blocks_to_remove = [block.get_hash()]
304
- for block_hash in blocks_to_remove:
305
- if block_hash in self.pending_blocks:
306
- del self.pending_blocks[block_hash]
307
- print(f"Added block {block.number} to blockchain")
308
- return True
309
- except Exception as e:
310
- print(f"Error validating main chain block {block.number}: {e}")
292
+ # if is_valid:
293
+ # # Apply block to our state
294
+ # success = validate_and_apply_block(self.blockchain, block)
295
+ # if success:
296
+ # print(f"Applied valid block {block.number} to blockchain state")
297
+ # self._update_latest_block(block)
298
+ # blocks_to_remove = [block.get_hash()]
299
+ # for block_hash in blocks_to_remove:
300
+ # if block_hash in self.pending_blocks:
301
+ # del self.pending_blocks[block_hash]
302
+ # print(f"Added block {block.number} to blockchain")
303
+ # return True
304
+ # except Exception as e:
305
+ # print(f"Error validating main chain block {block.number}: {e}")
311
306
 
312
- return False
307
+ # return False
313
308
 
314
- def _evaluate_candidate_chains(self):
315
- """
316
- Evaluate candidate chains to determine if any should become our main chain.
317
- This will validate pending blocks and look for chains with higher cumulative difficulty.
318
- """
319
- # Skip if no candidate chains
320
- if not self.candidate_chains:
321
- return
309
+ # def _evaluate_candidate_chains(self):
310
+ # """
311
+ # Evaluate candidate chains to determine if any should become our main chain.
312
+ # This will validate pending blocks and look for chains with higher cumulative difficulty.
313
+ # """
314
+ # # Skip if no candidate chains
315
+ # if not self.candidate_chains:
316
+ # return
322
317
 
323
- # For each candidate chain, validate blocks and calculate metrics
324
- for chain_id, data in list(self.candidate_chains.items()):
325
- latest_candidate_block = data['latest_block']
318
+ # # For each candidate chain, validate blocks and calculate metrics
319
+ # for chain_id, data in list(self.candidate_chains.items()):
320
+ # latest_candidate_block = data['latest_block']
326
321
 
327
- # Build the chain backwards
328
- chain_blocks = self._build_chain_from_latest(latest_candidate_block)
322
+ # # Build the chain backwards
323
+ # chain_blocks = self._build_chain_from_latest(latest_candidate_block)
329
324
 
330
- # Skip if we couldn't build a complete chain
331
- if not chain_blocks:
332
- continue
325
+ # # Skip if we couldn't build a complete chain
326
+ # if not chain_blocks:
327
+ # continue
333
328
 
334
- # Validate the entire chain
335
- valid_chain = self._validate_candidate_chain(chain_blocks)
329
+ # # Validate the entire chain
330
+ # valid_chain = self._validate_candidate_chain(chain_blocks)
336
331
 
337
- # If valid and better than our current chain, switch to it
338
- if valid_chain and self._is_better_chain(chain_blocks):
339
- self._switch_to_new_chain(chain_blocks)
332
+ # # If valid and better than our current chain, switch to it
333
+ # if valid_chain and self._is_better_chain(chain_blocks):
334
+ # self._switch_to_new_chain(chain_blocks)
340
335
 
341
- def _build_chain_from_latest(self, latest_block: Block) -> List[Block]:
342
- """
343
- Build a chain from the latest block back to a known point in our blockchain.
336
+ # def _build_chain_from_latest(self, latest_block: Block) -> List[Block]:
337
+ # """
338
+ # Build a chain from the latest block back to a known point in our blockchain.
344
339
 
345
- Args:
346
- latest_block: Latest block in the candidate chain
340
+ # Args:
341
+ # latest_block: Latest block in the candidate chain
347
342
 
348
- Returns:
349
- List of blocks in the chain, ordered from oldest to newest
350
- """
351
- chain_blocks = [latest_block]
352
- current_block = latest_block
353
-
354
- # Track visited blocks to avoid cycles
355
- visited = {current_block.get_hash()}
356
-
357
- # Build chain backwards until we either:
358
- # 1. Find a block in our main chain
359
- # 2. Run out of blocks
360
- # 3. Detect a cycle
361
- while current_block.number > 0:
362
- previous_hash = current_block.previous
343
+ # Returns:
344
+ # List of blocks in the chain, ordered from oldest to newest
345
+ # """
346
+ # chain_blocks = [latest_block]
347
+ # current_block = latest_block
348
+
349
+ # # Track visited blocks to avoid cycles
350
+ # visited = {current_block.get_hash()}
351
+
352
+ # # Build chain backwards until we either:
353
+ # # 1. Find a block in our main chain
354
+ # # 2. Run out of blocks
355
+ # # 3. Detect a cycle
356
+ # while current_block.number > 0:
357
+ # previous_hash = current_block.previous
363
358
 
364
- # Check if we have this block in our blockchain
365
- if hasattr(self.blockchain, 'has_block') and self.blockchain.has_block(previous_hash):
366
- # Found connection to our main chain
367
- previous_block = self.blockchain.get_block(previous_hash)
368
- chain_blocks.insert(0, previous_block)
369
- break
359
+ # # Check if we have this block in our blockchain
360
+ # if hasattr(self.blockchain, 'has_block') and self.blockchain.has_block(previous_hash):
361
+ # # Found connection to our main chain
362
+ # previous_block = self.blockchain.get_block(previous_hash)
363
+ # chain_blocks.insert(0, previous_block)
364
+ # break
370
365
 
371
- # Check if block is in pending blocks
372
- elif previous_hash in self.pending_blocks:
373
- previous_block = self.pending_blocks[previous_hash]['block']
366
+ # # Check if block is in pending blocks
367
+ # elif previous_hash in self.pending_blocks:
368
+ # previous_block = self.pending_blocks[previous_hash]['block']
374
369
 
375
- # Check for cycles
376
- if previous_hash in visited:
377
- print(f"Cycle detected in candidate chain at block {previous_block.number}")
378
- return []
370
+ # # Check for cycles
371
+ # if previous_hash in visited:
372
+ # print(f"Cycle detected in candidate chain at block {previous_block.number}")
373
+ # return []
379
374
 
380
- visited.add(previous_hash)
381
- chain_blocks.insert(0, previous_block)
382
- current_block = previous_block
383
- else:
384
- # Missing block, cannot validate the chain
385
- print(f"Missing block {previous_hash.hex()} in candidate chain")
386
- return []
375
+ # visited.add(previous_hash)
376
+ # chain_blocks.insert(0, previous_block)
377
+ # current_block = previous_block
378
+ # else:
379
+ # # Missing block, cannot validate the chain
380
+ # print(f"Missing block {previous_hash.hex()} in candidate chain")
381
+ # return []
387
382
 
388
- return chain_blocks
383
+ # return chain_blocks
389
384
 
390
- def _validate_candidate_chain(self, chain_blocks: List[Block]) -> bool:
391
- """
392
- Validate a candidate chain of blocks.
385
+ # def _validate_candidate_chain(self, chain_blocks: List[Block]) -> bool:
386
+ # """
387
+ # Validate a candidate chain of blocks.
393
388
 
394
- Args:
395
- chain_blocks: List of blocks in the chain (oldest to newest)
389
+ # Args:
390
+ # chain_blocks: List of blocks in the chain (oldest to newest)
396
391
 
397
- Returns:
398
- True if the chain is valid, False otherwise
399
- """
400
- # Validate each block in the chain
401
- for i, block in enumerate(chain_blocks):
402
- # Skip first block, it's either genesis or a block we already have
403
- if i == 0:
404
- continue
392
+ # Returns:
393
+ # True if the chain is valid, False otherwise
394
+ # """
395
+ # # Validate each block in the chain
396
+ # for i, block in enumerate(chain_blocks):
397
+ # # Skip first block, it's either genesis or a block we already have
398
+ # if i == 0:
399
+ # continue
405
400
 
406
- # Validate block connections
407
- if block.previous != chain_blocks[i-1].get_hash():
408
- print(f"Invalid chain: block {block.number} does not reference previous block")
409
- return False
401
+ # # Validate block connections
402
+ # if block.previous != chain_blocks[i-1].get_hash():
403
+ # print(f"Invalid chain: block {block.number} does not reference previous block")
404
+ # return False
410
405
 
411
- # Validate block
412
- is_valid = validate_block(block, self.blockchain.get_accounts_at_block(block.previous), self.blockchain.get_blocks())
413
- if not is_valid:
414
- print(f"Invalid chain: block {block.number} is invalid")
415
- return False
406
+ # # Validate block
407
+ # is_valid = validate_block(block, self.blockchain.get_accounts_at_block(block.previous), self.blockchain.get_blocks())
408
+ # if not is_valid:
409
+ # print(f"Invalid chain: block {block.number} is invalid")
410
+ # return False
416
411
 
417
- return True
412
+ # return True
418
413
 
419
- def _is_better_chain(self, chain_blocks: List[Block]) -> bool:
420
- """
421
- Determine if a candidate chain is better than our current chain.
414
+ # def _is_better_chain(self, chain_blocks: List[Block]) -> bool:
415
+ # """
416
+ # Determine if a candidate chain is better than our current chain.
422
417
 
423
- Args:
424
- chain_blocks: List of blocks in the candidate chain
418
+ # Args:
419
+ # chain_blocks: List of blocks in the candidate chain
425
420
 
426
- Returns:
427
- True if the candidate chain is better, False otherwise
428
- """
429
- # Get the latest block from the candidate chain
430
- candidate_latest = chain_blocks[-1]
431
-
432
- # If we don't have a latest block, any valid chain is better
433
- if not self.latest_block:
434
- return True
421
+ # Returns:
422
+ # True if the candidate chain is better, False otherwise
423
+ # """
424
+ # # Get the latest block from the candidate chain
425
+ # candidate_latest = chain_blocks[-1]
426
+
427
+ # # If we don't have a latest block, any valid chain is better
428
+ # if not self.latest_block:
429
+ # return True
435
430
 
436
- # Compare block numbers (longest chain rule)
437
- if candidate_latest.number > self.latest_block.number:
438
- print(f"Candidate chain is longer: {candidate_latest.number} vs {self.latest_block.number}")
439
- return True
431
+ # # Compare block numbers (longest chain rule)
432
+ # if candidate_latest.number > self.latest_block.number:
433
+ # print(f"Candidate chain is longer: {candidate_latest.number} vs {self.latest_block.number}")
434
+ # return True
440
435
 
441
- return False
442
-
443
- def _switch_to_new_chain(self, chain_blocks: List[Block]):
444
- """
445
- Switch to a new chain by adding all blocks to our blockchain.
446
-
447
- Args:
448
- chain_blocks: List of blocks in the chain (oldest to newest)
449
- """
450
- # Find the point where the chains diverge
451
- divergence_point = 0
452
- for i, block in enumerate(chain_blocks):
453
- # Check if we have this block in our blockchain
454
- if hasattr(self.blockchain, 'has_block') and self.blockchain.has_block(block.get_hash()):
455
- divergence_point = i + 1
456
- else:
457
- break
436
+ # return False
437
+
438
+ # def _switch_to_new_chain(self, chain_blocks: List[Block]):
439
+ # """
440
+ # Switch to a new chain by adding all blocks to our blockchain.
441
+
442
+ # Args:
443
+ # chain_blocks: List of blocks in the chain (oldest to newest)
444
+ # """
445
+ # # Find the point where the chains diverge
446
+ # divergence_point = 0
447
+ # for i, block in enumerate(chain_blocks):
448
+ # # Check if we have this block in our blockchain
449
+ # if hasattr(self.blockchain, 'has_block') and self.blockchain.has_block(block.get_hash()):
450
+ # divergence_point = i + 1
451
+ # else:
452
+ # break
458
453
 
459
- # Add all blocks after the divergence point
460
- for i in range(divergence_point, len(chain_blocks)):
461
- block = chain_blocks[i]
454
+ # # Add all blocks after the divergence point
455
+ # for i in range(divergence_point, len(chain_blocks)):
456
+ # block = chain_blocks[i]
462
457
 
463
- # Add block to blockchain
464
- if hasattr(self.blockchain, 'add_block'):
465
- try:
466
- self.blockchain.add_block(block)
458
+ # # Add block to blockchain
459
+ # if hasattr(self.blockchain, 'add_block'):
460
+ # try:
461
+ # self.blockchain.add_block(block)
467
462
 
468
- # Remove from pending blocks
469
- block_hash = block.get_hash()
470
- if block_hash in self.pending_blocks:
471
- del self.pending_blocks[block_hash]
463
+ # # Remove from pending blocks
464
+ # block_hash = block.get_hash()
465
+ # if block_hash in self.pending_blocks:
466
+ # del self.pending_blocks[block_hash]
472
467
 
473
- print(f"Added block {block.number} to blockchain")
474
- except Exception as e:
475
- print(f"Error adding block {block.number} to blockchain: {e}")
476
- return
468
+ # print(f"Added block {block.number} to blockchain")
469
+ # except Exception as e:
470
+ # print(f"Error adding block {block.number} to blockchain: {e}")
471
+ # return
477
472
 
478
- # Update latest block
479
- self._update_latest_block(chain_blocks[-1])
480
- print(f"Switched to new chain, latest block: {self.latest_block.number}")
473
+ # # Update latest block
474
+ # self._update_latest_block(chain_blocks[-1])
475
+ # print(f"Switched to new chain, latest block: {self.latest_block.number}")