12
12
# See the License for the specific language governing permissions and
13
13
# limitations under the License.
14
14
15
- import datetime
16
15
import sys
17
16
import time
18
17
from cProfile import Profile
53
52
from hathor .reward_lock import is_spent_reward_locked
54
53
from hathor .stratum import StratumFactory
55
54
from hathor .transaction import BaseTransaction , Block , MergeMinedBlock , Transaction , TxVersion
56
- from hathor .transaction .exceptions import TxValidationError
57
55
from hathor .transaction .storage .exceptions import TransactionDoesNotExist
58
56
from hathor .transaction .storage .transaction_storage import TransactionStorage
59
57
from hathor .transaction .storage .tx_allow_scope import TxAllowScope
@@ -115,7 +113,6 @@ def __init__(
115
113
checkpoints : Optional [list [Checkpoint ]] = None ,
116
114
rng : Optional [Random ] = None ,
117
115
environment_info : Optional [EnvironmentInfo ] = None ,
118
- full_verification : bool = False ,
119
116
enable_event_queue : bool = False ,
120
117
poa_block_producer : PoaBlockProducer | None = None ,
121
118
# Websocket factory
@@ -223,10 +220,6 @@ def __init__(
223
220
# Thread pool used to resolve pow when sending tokens
224
221
self .pow_thread_pool = ThreadPool (minthreads = 0 , maxthreads = settings .MAX_POW_THREADS , name = 'Pow thread pool' )
225
222
226
- # Full verification execute all validations for transactions and blocks when initializing the node
227
- # Can be activated on the command line with --full-verification
228
- self ._full_verification = full_verification
229
-
230
223
# List of whitelisted peers
231
224
self .peers_whitelist : list [PeerId ] = []
232
225
@@ -272,33 +265,16 @@ def start(self) -> None:
272
265
)
273
266
sys .exit (- 1 )
274
267
275
- # If it's a full verification, we save on the storage that we are starting it
276
- # this is required because if we stop the initilization in the middle, the metadata
277
- # saved on the storage is not reliable anymore, only if we finish it
278
- if self ._full_verification :
279
- self .tx_storage .start_full_verification ()
280
- else :
281
- # If it's a fast initialization and the last time a full initialization stopped in the middle
282
- # we can't allow the full node to continue, so we need to remove the storage and do a full sync
283
- # or execute an initialization with full verification
284
- if self .tx_storage .is_running_full_verification ():
285
- self .log .error (
286
- 'Error initializing node. The last time you started your node you did a full verification '
287
- 'that was stopped in the middle. The storage is not reliable anymore and, because of that, '
288
- 'you must initialize with a full verification again or remove your storage and do a full sync.'
289
- )
290
- sys .exit (- 1 )
291
-
292
- # If self.tx_storage.is_running_manager() is True, the last time the node was running it had a sudden crash
293
- # because of that, we must run a full verification because some storage data might be wrong.
294
- # The metadata is the only piece of the storage that may be wrong, not the blocks and transactions.
295
- if self .tx_storage .is_running_manager ():
296
- self .log .error (
297
- 'Error initializing node. The last time you executed your full node it wasn\' t stopped correctly. '
298
- 'The storage is not reliable anymore and, because of that, so you must run a full verification '
299
- 'or remove your storage and do a full sync.'
300
- )
301
- sys .exit (- 1 )
268
+ # If self.tx_storage.is_running_manager() is True, the last time the node was running it had a sudden crash
269
+ # because of that, we must run a sync from scratch or from a snapshot.
270
+ # The metadata is the only piece of the storage that may be wrong, not the blocks and transactions.
271
+ if self .tx_storage .is_running_manager ():
272
+ self .log .error (
273
+ 'Error initializing node. The last time you executed your full node it wasn\' t stopped correctly. '
274
+ 'The storage is not reliable anymore and, because of that you must remove your storage and do a'
275
+ 'sync from scratch or from a snapshot.'
276
+ )
277
+ sys .exit (- 1 )
302
278
303
279
if self ._enable_event_queue :
304
280
self ._event_manager .start (str (self .my_peer .id ))
@@ -312,16 +288,7 @@ def start(self) -> None:
312
288
self .tx_storage .disable_lock ()
313
289
# Open scope for initialization.
314
290
self .tx_storage .set_allow_scope (TxAllowScope .VALID | TxAllowScope .PARTIAL | TxAllowScope .INVALID )
315
- # Initialize manager's components.
316
- if self ._full_verification :
317
- self .tx_storage .reset_indexes ()
318
- self ._initialize_components_full_verification ()
319
- # Before calling self._initialize_components_full_verification() I start 'full verification' mode and
320
- # after that I need to finish it. It's just to know if the full node has stopped a full initialization
321
- # in the middle.
322
- self .tx_storage .finish_full_verification ()
323
- else :
324
- self ._initialize_components_new ()
291
+ self ._initialize_components ()
325
292
self .tx_storage .set_allow_scope (TxAllowScope .VALID )
326
293
self .tx_storage .enable_lock ()
327
294
@@ -414,159 +381,7 @@ def stop_profiler(self, save_to: Optional[str] = None) -> None:
414
381
if save_to :
415
382
self .profiler .dump_stats (save_to )
416
383
417
- def _initialize_components_full_verification (self ) -> None :
418
- """You are not supposed to run this method manually. You should run `doStart()` to initialize the
419
- manager.
420
-
421
- This method runs through all transactions, verifying them and updating our wallet.
422
- """
423
- assert not self ._enable_event_queue , 'this method cannot be used if the events feature is enabled.'
424
- assert self ._full_verification
425
-
426
- self .log .info ('initialize' )
427
- if self .wallet :
428
- self .wallet ._manually_initialize ()
429
- t0 = time .time ()
430
- t1 = t0
431
- cnt = 0
432
- cnt2 = 0
433
- t2 = t0
434
- h = 0
435
-
436
- block_count = 0
437
- tx_count = 0
438
-
439
- self .tx_storage .pre_init ()
440
- assert self .tx_storage .indexes is not None
441
-
442
- self ._verify_soft_voided_txs ()
443
-
444
- # Checkpoints as {height: hash}
445
- checkpoint_heights = {}
446
- for cp in self .checkpoints :
447
- checkpoint_heights [cp .height ] = cp .hash
448
-
449
- # self.start_profiler()
450
- self .log .debug ('reset all metadata' )
451
- for tx in self .tx_storage .get_all_transactions ():
452
- tx .reset_metadata ()
453
-
454
- self .log .debug ('load blocks and transactions' )
455
- for tx in self .tx_storage ._topological_sort_dfs ():
456
- tx_meta = tx .get_metadata ()
457
-
458
- t2 = time .time ()
459
- dt = LogDuration (t2 - t1 )
460
- dcnt = cnt - cnt2
461
- tx_rate = '?' if dt == 0 else dcnt / dt
462
- h = max (h , (tx .static_metadata .height if isinstance (tx , Block ) else 0 ))
463
- if dt > 30 :
464
- ts_date = datetime .datetime .fromtimestamp (self .tx_storage .latest_timestamp )
465
- if h == 0 :
466
- self .log .debug ('start loading transactions...' )
467
- else :
468
- self .log .info ('load transactions...' , tx_rate = tx_rate , tx_new = dcnt , dt = dt ,
469
- total = cnt , latest_ts = ts_date , height = h )
470
- t1 = t2
471
- cnt2 = cnt
472
- cnt += 1
473
-
474
- # It's safe to skip block weight verification during initialization because
475
- # we trust the difficulty stored in metadata
476
- skip_block_weight_verification = True
477
- if block_count % self ._settings .VERIFY_WEIGHT_EVERY_N_BLOCKS == 0 :
478
- skip_block_weight_verification = False
479
-
480
- try :
481
- # TODO: deal with invalid tx
482
- tx ._update_parents_children_metadata ()
483
-
484
- if self .tx_storage .can_validate_full (tx ):
485
- tx .update_initial_metadata ()
486
- if tx .is_genesis :
487
- assert tx .validate_checkpoint (self .checkpoints )
488
- assert self .verification_service .validate_full (
489
- tx ,
490
- skip_block_weight_verification = skip_block_weight_verification
491
- )
492
- self .tx_storage .add_to_indexes (tx )
493
- with self .tx_storage .allow_only_valid_context ():
494
- self .consensus_algorithm .unsafe_update (tx )
495
- self .tx_storage .indexes .update (tx )
496
- if self .tx_storage .indexes .mempool_tips is not None :
497
- self .tx_storage .indexes .mempool_tips .update (tx ) # XXX: move to indexes.update
498
- self .tx_storage .save_transaction (tx , only_metadata = True )
499
- else :
500
- assert self .verification_service .validate_basic (
501
- tx ,
502
- skip_block_weight_verification = skip_block_weight_verification
503
- )
504
- self .tx_storage .save_transaction (tx , only_metadata = True )
505
- except (InvalidNewTransaction , TxValidationError ):
506
- self .log .error ('unexpected error when initializing' , tx = tx , exc_info = True )
507
- raise
508
-
509
- if tx .is_block :
510
- block_count += 1
511
-
512
- # this works because blocks on the best chain are iterated from lower to higher height
513
- assert tx_meta .validation .is_at_least_basic ()
514
- assert isinstance (tx , Block )
515
- blk_height = tx .get_height ()
516
- if not tx_meta .voided_by and tx_meta .validation .is_fully_connected ():
517
- # XXX: this might not be needed when making a full init because the consensus should already have
518
- self .tx_storage .indexes .height .add_reorg (blk_height , tx .hash , tx .timestamp )
519
-
520
- # Check if it's a checkpoint block
521
- if blk_height in checkpoint_heights :
522
- if tx .hash == checkpoint_heights [blk_height ]:
523
- del checkpoint_heights [blk_height ]
524
- else :
525
- # If the hash is different from checkpoint hash, we stop the node
526
- self .log .error ('Error initializing the node. Checkpoint validation error.' )
527
- sys .exit ()
528
- else :
529
- tx_count += 1
530
-
531
- if time .time () - t2 > 1 :
532
- dt = LogDuration (time .time () - t2 )
533
- self .log .warn ('tx took too long to load' , tx = tx .hash_hex , dt = dt )
534
-
535
- # we have to have a best_block by now
536
- # assert best_block is not None
537
-
538
- self .tx_storage .indexes ._manually_initialize (self .tx_storage )
539
-
540
- self .log .debug ('done loading transactions' )
541
-
542
- # Check if all checkpoints in database are ok
543
- my_best_height = self .tx_storage .get_height_best_block ()
544
- if checkpoint_heights :
545
- # If I have checkpoints that were not validated I must check if they are all in a height I still don't have
546
- first = min (list (checkpoint_heights .keys ()))
547
- if first <= my_best_height :
548
- # If the height of the first checkpoint not validated is lower than the height of the best block
549
- # Then it's missing this block
550
- self .log .error ('Error initializing the node. Checkpoint validation error.' )
551
- sys .exit ()
552
-
553
- best_height = self .tx_storage .get_height_best_block ()
554
- if best_height != h :
555
- self .log .warn ('best height doesn\' t match' , best_height = best_height , max_height = h )
556
-
557
- # self.stop_profiler(save_to='profiles/initializing.prof')
558
- self .state = self .NodeState .READY
559
-
560
- total_load_time = LogDuration (t2 - t0 )
561
- tx_rate = '?' if total_load_time == 0 else cnt / total_load_time
562
-
563
- environment_info = self .environment_info .as_dict () if self .environment_info else {}
564
-
565
- # Changing the field names in this log could impact log collectors that parse them
566
- self .log .info ('ready' , vertex_count = cnt , tx_rate = tx_rate , total_load_time = total_load_time , height = h ,
567
- blocks = block_count , txs = tx_count , ** environment_info )
568
-
569
- def _initialize_components_new (self ) -> None :
384
+ def _initialize_components (self ) -> None :
570
385
"""You are not supposed to run this method manually. You should run `doStart()` to initialize the
571
386
manager.
572
387
@@ -593,10 +408,6 @@ def _initialize_components_new(self) -> None:
593
408
started_at = started_at , last_started_at = last_started_at )
594
409
595
410
self ._verify_soft_voided_txs ()
596
-
597
- # TODO: move support for full-verification here, currently we rely on the original _initialize_components
598
- # method for full-verification to work, if we implement it here we'll reduce a lot of duplicate and
599
- # complex code
600
411
self .tx_storage .indexes ._manually_initialize (self .tx_storage )
601
412
602
413
# Verify if all checkpoints that exist in the database are correct
0 commit comments