@@ -14,15 +14,15 @@ use tokio_util::sync::ReusableBoxFuture;
14
14
use tracing:: { debug, info, warn} ;
15
15
16
16
use crate :: {
17
- block:: { BlockAPI as _, BlockRef , SignedBlock , VerifiedBlock , GENESIS_ROUND } ,
17
+ block:: { BlockAPI as _, BlockRef , ExtendedBlock , SignedBlock , VerifiedBlock , GENESIS_ROUND } ,
18
18
block_verifier:: BlockVerifier ,
19
19
commit:: { CommitAPI as _, CommitRange , TrustedCommit } ,
20
20
commit_vote_monitor:: CommitVoteMonitor ,
21
21
context:: Context ,
22
22
core_thread:: CoreThreadDispatcher ,
23
23
dag_state:: DagState ,
24
24
error:: { ConsensusError , ConsensusResult } ,
25
- network:: { BlockStream , NetworkService } ,
25
+ network:: { BlockStream , ExtendedSerializedBlock , NetworkService } ,
26
26
stake_aggregator:: { QuorumThreshold , StakeAggregator } ,
27
27
storage:: Store ,
28
28
synchronizer:: SynchronizerHandle ,
@@ -38,7 +38,7 @@ pub(crate) struct AuthorityService<C: CoreThreadDispatcher> {
38
38
block_verifier : Arc < dyn BlockVerifier > ,
39
39
synchronizer : Arc < SynchronizerHandle > ,
40
40
core_dispatcher : Arc < C > ,
41
- rx_block_broadcaster : broadcast:: Receiver < VerifiedBlock > ,
41
+ rx_block_broadcaster : broadcast:: Receiver < ExtendedBlock > ,
42
42
subscription_counter : Arc < SubscriptionCounter > ,
43
43
dag_state : Arc < RwLock < DagState > > ,
44
44
store : Arc < dyn Store > ,
@@ -51,7 +51,7 @@ impl<C: CoreThreadDispatcher> AuthorityService<C> {
51
51
commit_vote_monitor : Arc < CommitVoteMonitor > ,
52
52
synchronizer : Arc < SynchronizerHandle > ,
53
53
core_dispatcher : Arc < C > ,
54
- rx_block_broadcaster : broadcast:: Receiver < VerifiedBlock > ,
54
+ rx_block_broadcaster : broadcast:: Receiver < ExtendedBlock > ,
55
55
dag_state : Arc < RwLock < DagState > > ,
56
56
store : Arc < dyn Store > ,
57
57
) -> Self {
@@ -78,15 +78,15 @@ impl<C: CoreThreadDispatcher> NetworkService for AuthorityService<C> {
78
78
async fn handle_send_block (
79
79
& self ,
80
80
peer : AuthorityIndex ,
81
- serialized_block : Bytes ,
81
+ serialized_block : ExtendedSerializedBlock ,
82
82
) -> ConsensusResult < ( ) > {
83
83
fail_point_async ! ( "consensus-rpc-response" ) ;
84
84
85
85
let peer_hostname = & self . context . committee . authority ( peer) . hostname ;
86
86
87
87
// TODO: dedup block verifications, here and with fetched blocks.
88
88
let signed_block: SignedBlock =
89
- bcs:: from_bytes ( & serialized_block) . map_err ( ConsensusError :: MalformedBlock ) ?;
89
+ bcs:: from_bytes ( & serialized_block. block ) . map_err ( ConsensusError :: MalformedBlock ) ?;
90
90
91
91
// Reject blocks not produced by the peer.
92
92
if peer != signed_block. author ( ) {
@@ -113,7 +113,7 @@ impl<C: CoreThreadDispatcher> NetworkService for AuthorityService<C> {
113
113
info ! ( "Invalid block from {}: {}" , peer, e) ;
114
114
return Err ( e) ;
115
115
}
116
- let verified_block = VerifiedBlock :: new_verified ( signed_block, serialized_block) ;
116
+ let verified_block = VerifiedBlock :: new_verified ( signed_block, serialized_block. block ) ;
117
117
let block_ref = verified_block. reference ( ) ;
118
118
debug ! ( "Received block {} via send block." , block_ref) ;
119
119
@@ -225,6 +225,75 @@ impl<C: CoreThreadDispatcher> NetworkService for AuthorityService<C> {
225
225
}
226
226
}
227
227
228
+ // ------------ After processing the block, process the excluded ancestors ------------
229
+
230
+ let mut excluded_ancestors = serialized_block
231
+ . excluded_ancestors
232
+ . into_iter ( )
233
+ . map ( |serialized| bcs:: from_bytes :: < BlockRef > ( & serialized) )
234
+ . collect :: < Result < Vec < BlockRef > , bcs:: Error > > ( )
235
+ . map_err ( ConsensusError :: MalformedBlock ) ?;
236
+
237
+ let excluded_ancestors_limit = self . context . committee . size ( ) * 2 ;
238
+ if excluded_ancestors. len ( ) > excluded_ancestors_limit {
239
+ debug ! (
240
+ "Dropping {} excluded ancestor(s) from {} {} due to size limit" ,
241
+ excluded_ancestors. len( ) - excluded_ancestors_limit,
242
+ peer,
243
+ peer_hostname,
244
+ ) ;
245
+ excluded_ancestors. truncate ( excluded_ancestors_limit) ;
246
+ }
247
+
248
+ self . context
249
+ . metrics
250
+ . node_metrics
251
+ . network_received_excluded_ancestors_from_authority
252
+ . with_label_values ( & [ peer_hostname] )
253
+ . inc_by ( excluded_ancestors. len ( ) as u64 ) ;
254
+
255
+ for excluded_ancestor in & excluded_ancestors {
256
+ let excluded_ancestor_hostname = & self
257
+ . context
258
+ . committee
259
+ . authority ( excluded_ancestor. author )
260
+ . hostname ;
261
+ self . context
262
+ . metrics
263
+ . node_metrics
264
+ . network_excluded_ancestors_count_by_authority
265
+ . with_label_values ( & [ excluded_ancestor_hostname] )
266
+ . inc ( ) ;
267
+ }
268
+
269
+ let missing_excluded_ancestors = self
270
+ . core_dispatcher
271
+ . check_block_refs ( excluded_ancestors)
272
+ . await
273
+ . map_err ( |_| ConsensusError :: Shutdown ) ?;
274
+
275
+ if !missing_excluded_ancestors. is_empty ( ) {
276
+ self . context
277
+ . metrics
278
+ . node_metrics
279
+ . network_excluded_ancestors_sent_to_fetch
280
+ . with_label_values ( & [ peer_hostname] )
281
+ . inc_by ( missing_excluded_ancestors. len ( ) as u64 ) ;
282
+
283
+ let synchronizer = self . synchronizer . clone ( ) ;
284
+ tokio:: spawn ( async move {
285
+ // schedule the fetching of them from this peer in the background
286
+ if let Err ( err) = synchronizer
287
+ . fetch_blocks ( missing_excluded_ancestors, peer)
288
+ . await
289
+ {
290
+ warn ! (
291
+ "Errored while trying to fetch missing excluded ancestors via synchronizer: {err}"
292
+ ) ;
293
+ }
294
+ } ) ;
295
+ }
296
+
228
297
Ok ( ( ) )
229
298
}
230
299
@@ -243,7 +312,10 @@ impl<C: CoreThreadDispatcher> NetworkService for AuthorityService<C> {
243
312
dag_state
244
313
. get_cached_blocks ( self . context . own_index , last_received + 1 )
245
314
. into_iter ( )
246
- . map ( |block| block. serialized ( ) . clone ( ) ) ,
315
+ . map ( |block| ExtendedSerializedBlock {
316
+ block : block. serialized ( ) . clone ( ) ,
317
+ excluded_ancestors : vec ! [ ] ,
318
+ } ) ,
247
319
) ;
248
320
249
321
let broadcasted_blocks = BroadcastedBlockStream :: new (
@@ -254,7 +326,7 @@ impl<C: CoreThreadDispatcher> NetworkService for AuthorityService<C> {
254
326
255
327
// Return a stream of blocks that first yields missed blocks as requested, then new blocks.
256
328
Ok ( Box :: pin ( missed_blocks. chain (
257
- broadcasted_blocks. map ( |block| block . serialized ( ) . clone ( ) ) ,
329
+ broadcasted_blocks. map ( ExtendedSerializedBlock :: from ) ,
258
330
) ) )
259
331
}
260
332
@@ -423,7 +495,7 @@ impl<C: CoreThreadDispatcher> NetworkService for AuthorityService<C> {
423
495
. get_last_cached_block_per_authority ( Round :: MAX ) ;
424
496
let highest_accepted_rounds = blocks
425
497
. into_iter ( )
426
- . map ( |block| block. round ( ) )
498
+ . map ( |( block, _ ) | block. round ( ) )
427
499
. collect :: < Vec < _ > > ( ) ;
428
500
429
501
// Own blocks do not go through the core dispatcher, so they need to be set separately.
@@ -516,7 +588,7 @@ impl SubscriptionCounter {
516
588
517
589
/// Each broadcasted block stream wraps a broadcast receiver for blocks.
518
590
/// It yields blocks that are broadcasted after the stream is created.
519
- type BroadcastedBlockStream = BroadcastStream < VerifiedBlock > ;
591
+ type BroadcastedBlockStream = BroadcastStream < ExtendedBlock > ;
520
592
521
593
/// Adapted from `tokio_stream::wrappers::BroadcastStream`. The main difference is that
522
594
/// this tolerates lags with only logging, without yielding errors.
@@ -612,15 +684,14 @@ async fn make_recv_future<T: Clone>(
612
684
mod tests {
613
685
use crate :: {
614
686
authority_service:: AuthorityService ,
615
- block:: BlockAPI ,
616
- block:: { BlockRef , SignedBlock , TestBlock , VerifiedBlock } ,
687
+ block:: { BlockAPI , BlockRef , SignedBlock , TestBlock , VerifiedBlock } ,
617
688
commit:: CommitRange ,
618
689
commit_vote_monitor:: CommitVoteMonitor ,
619
690
context:: Context ,
620
691
core_thread:: { CoreError , CoreThreadDispatcher } ,
621
692
dag_state:: DagState ,
622
693
error:: ConsensusResult ,
623
- network:: { BlockStream , NetworkClient , NetworkService } ,
694
+ network:: { BlockStream , ExtendedSerializedBlock , NetworkClient , NetworkService } ,
624
695
round_prober:: QuorumRound ,
625
696
storage:: mem_store:: MemStore ,
626
697
synchronizer:: Synchronizer ,
@@ -664,6 +735,13 @@ mod tests {
664
735
Ok ( block_refs)
665
736
}
666
737
738
+ async fn check_block_refs (
739
+ & self ,
740
+ _block_refs : Vec < BlockRef > ,
741
+ ) -> Result < BTreeSet < BlockRef > , CoreError > {
742
+ Ok ( BTreeSet :: new ( ) )
743
+ }
744
+
667
745
async fn new_block ( & self , _round : Round , _force : bool ) -> Result < ( ) , CoreError > {
668
746
Ok ( ( ) )
669
747
}
@@ -797,7 +875,11 @@ mod tests {
797
875
) ;
798
876
799
877
let service = authority_service. clone ( ) ;
800
- let serialized = input_block. serialized ( ) . clone ( ) ;
878
+ let serialized = ExtendedSerializedBlock {
879
+ block : input_block. serialized ( ) . clone ( ) ,
880
+ excluded_ancestors : vec ! [ ] ,
881
+ } ;
882
+
801
883
tokio:: spawn ( async move {
802
884
service
803
885
. handle_send_block ( context. committee . to_authority_index ( 0 ) . unwrap ( ) , serialized)
0 commit comments