1
1
//! The blockchain manager handler functions.
2
+ use std:: { collections:: HashMap , sync:: Arc } ;
3
+
2
4
use bytes:: Bytes ;
3
5
use futures:: { TryFutureExt , TryStreamExt } ;
4
6
use monero_serai:: {
5
7
block:: Block ,
6
8
transaction:: { Input , Transaction } ,
7
9
} ;
8
10
use rayon:: prelude:: * ;
9
- use std:: ops:: ControlFlow ;
10
- use std:: { collections:: HashMap , sync:: Arc } ;
11
11
use tower:: { Service , ServiceExt } ;
12
- use tracing:: { info, instrument} ;
12
+ use tracing:: { info, instrument, Span } ;
13
13
14
14
use cuprate_blockchain:: service:: { BlockchainReadHandle , BlockchainWriteHandle } ;
15
15
use cuprate_consensus:: {
@@ -21,12 +21,13 @@ use cuprate_consensus::{
21
21
BlockChainContextRequest , BlockChainContextResponse , ExtendedConsensusError ,
22
22
} ;
23
23
use cuprate_consensus_context:: NewBlockData ;
24
+ use cuprate_fast_sync:: { block_to_verified_block_information, fast_sync_stop_height} ;
24
25
use cuprate_helper:: cast:: usize_to_u64;
25
26
use cuprate_p2p:: { block_downloader:: BlockBatch , constants:: LONG_BAN , BroadcastRequest } ;
26
27
use cuprate_txpool:: service:: interface:: TxpoolWriteRequest ;
27
28
use cuprate_types:: {
28
29
blockchain:: { BlockchainReadRequest , BlockchainResponse , BlockchainWriteRequest } ,
29
- AltBlockInformation , HardFork , TransactionVerificationData , VerifiedBlockInformation ,
30
+ AltBlockInformation , Chain , HardFork , TransactionVerificationData , VerifiedBlockInformation ,
30
31
} ;
31
32
32
33
use crate :: {
@@ -166,6 +167,11 @@ impl super::BlockchainManager {
166
167
/// This function will panic if any internal service returns an unexpected error that we cannot
167
168
/// recover from or if the incoming batch contains no blocks.
168
169
async fn handle_incoming_block_batch_main_chain ( & mut self , batch : BlockBatch ) {
170
+ if batch. blocks . last ( ) . unwrap ( ) . 0 . number ( ) . unwrap ( ) < fast_sync_stop_height ( ) {
171
+ self . handle_incoming_block_batch_fast_sync ( batch) . await ;
172
+ return ;
173
+ }
174
+
169
175
let Ok ( ( prepped_blocks, mut output_cache) ) = batch_prepare_main_chain_blocks (
170
176
batch. blocks ,
171
177
& mut self . blockchain_context_service ,
@@ -195,7 +201,32 @@ impl super::BlockchainManager {
195
201
196
202
self . add_valid_block_to_main_chain ( verified_block) . await ;
197
203
}
198
- info ! ( "Successfully added block batch" ) ;
204
+ info ! ( fast_sync = false , "Successfully added block batch" ) ;
205
+ }
206
+
207
+ /// Handles an incoming block batch while we are under the fast sync height.
208
+ ///
209
+ /// # Panics
210
+ ///
211
+ /// This function will panic if any internal service returns an unexpected error that we cannot
212
+ /// recover from.
213
+ async fn handle_incoming_block_batch_fast_sync ( & mut self , batch : BlockBatch ) {
214
+ let mut valid_blocks = Vec :: with_capacity ( batch. blocks . len ( ) ) ;
215
+ for ( block, txs) in batch. blocks {
216
+ let block = block_to_verified_block_information (
217
+ block,
218
+ txs,
219
+ self . blockchain_context_service . blockchain_context ( ) ,
220
+ ) ;
221
+ self . add_valid_block_to_blockchain_cache ( & block) . await ;
222
+
223
+ valid_blocks. push ( block) ;
224
+ }
225
+
226
+ self . batch_add_valid_block_to_blockchain_database ( valid_blocks)
227
+ . await ;
228
+
229
+ info ! ( fast_sync = true , "Successfully added block batch" ) ;
199
230
}
200
231
201
232
/// Handles an incoming [`BlockBatch`] that does not follow the main-chain.
@@ -212,7 +243,6 @@ impl super::BlockchainManager {
212
243
/// recover from.
213
244
async fn handle_incoming_block_batch_alt_chain ( & mut self , mut batch : BlockBatch ) {
214
245
// TODO: this needs testing (this whole section does but alt-blocks specifically).
215
-
216
246
let mut blocks = batch. blocks . into_iter ( ) ;
217
247
218
248
while let Some ( ( block, txs) ) = blocks. next ( ) {
@@ -248,6 +278,8 @@ impl super::BlockchainManager {
248
278
Ok ( AddAltBlock :: Cached ) => ( ) ,
249
279
}
250
280
}
281
+
282
+ info ! ( alt_chain = true , "Successfully added block batch" ) ;
251
283
}
252
284
253
285
/// Handles an incoming alt [`Block`].
@@ -284,9 +316,10 @@ impl super::BlockchainManager {
284
316
unreachable ! ( ) ;
285
317
} ;
286
318
287
- if chain. is_some ( ) {
288
- // The block could also be in the main-chain here under some circumstances.
289
- return Ok ( AddAltBlock :: Cached ) ;
319
+ match chain {
320
+ Some ( ( Chain :: Alt ( _) , _) ) => return Ok ( AddAltBlock :: Cached ) ,
321
+ Some ( ( Chain :: Main , _) ) => anyhow:: bail!( "Alt block already in main chain" ) ,
322
+ None => ( ) ,
290
323
}
291
324
292
325
let alt_block_info =
@@ -458,6 +491,36 @@ impl super::BlockchainManager {
458
491
} )
459
492
. collect :: < Vec < [ u8 ; 32 ] > > ( ) ;
460
493
494
+ self . add_valid_block_to_blockchain_cache ( & verified_block)
495
+ . await ;
496
+
497
+ self . blockchain_write_handle
498
+ . ready ( )
499
+ . await
500
+ . expect ( PANIC_CRITICAL_SERVICE_ERROR )
501
+ . call ( BlockchainWriteRequest :: WriteBlock ( verified_block) )
502
+ . await
503
+ . expect ( PANIC_CRITICAL_SERVICE_ERROR ) ;
504
+
505
+ self . txpool_write_handle
506
+ . ready ( )
507
+ . await
508
+ . expect ( PANIC_CRITICAL_SERVICE_ERROR )
509
+ . call ( TxpoolWriteRequest :: NewBlock { spent_key_images } )
510
+ . await
511
+ . expect ( PANIC_CRITICAL_SERVICE_ERROR ) ;
512
+ }
513
+
514
+ /// Adds a [`VerifiedBlockInformation`] to the blockchain context cache.
515
+ ///
516
+ /// # Panics
517
+ ///
518
+ /// This function will panic if any internal service returns an unexpected error that we cannot
519
+ /// recover from.
520
+ async fn add_valid_block_to_blockchain_cache (
521
+ & mut self ,
522
+ verified_block : & VerifiedBlockInformation ,
523
+ ) {
461
524
self . blockchain_context_service
462
525
. ready ( )
463
526
. await
@@ -474,28 +537,33 @@ impl super::BlockchainManager {
474
537
} ) )
475
538
. await
476
539
. expect ( PANIC_CRITICAL_SERVICE_ERROR ) ;
540
+ }
477
541
542
+ /// Batch writes the [`VerifiedBlockInformation`]s to the database.
543
+ ///
544
+ /// The blocks must be sequential.
545
+ ///
546
+ /// # Panics
547
+ ///
548
+ /// This function will panic if any internal service returns an unexpected error that we cannot
549
+ /// recover from.
550
+ async fn batch_add_valid_block_to_blockchain_database (
551
+ & mut self ,
552
+ blocks : Vec < VerifiedBlockInformation > ,
553
+ ) {
478
554
self . blockchain_write_handle
479
555
. ready ( )
480
556
. await
481
557
. expect ( PANIC_CRITICAL_SERVICE_ERROR )
482
- . call ( BlockchainWriteRequest :: WriteBlock ( verified_block) )
483
- . await
484
- . expect ( PANIC_CRITICAL_SERVICE_ERROR ) ;
485
-
486
- self . txpool_write_handle
487
- . ready ( )
488
- . await
489
- . expect ( PANIC_CRITICAL_SERVICE_ERROR )
490
- . call ( TxpoolWriteRequest :: NewBlock { spent_key_images } )
558
+ . call ( BlockchainWriteRequest :: BatchWriteBlocks ( blocks) )
491
559
. await
492
560
. expect ( PANIC_CRITICAL_SERVICE_ERROR ) ;
493
561
}
494
562
}
495
563
496
564
/// The result from successfully adding an alt-block.
497
565
enum AddAltBlock {
498
- /// The alt-block was cached or was already present in the DB .
566
+ /// The alt-block was cached.
499
567
Cached ,
500
568
/// The chain was reorged.
501
569
Reorged ,
0 commit comments