3
3
// SPDX-License-Identifier: Apache-2.0
4
4
5
5
use std:: {
6
+ cmp:: max,
6
7
collections:: { BTreeMap , BTreeSet , VecDeque } ,
7
8
pin:: Pin ,
8
9
sync:: Arc ,
@@ -122,6 +123,13 @@ pub(crate) struct AuthorityService<C: CoreThreadDispatcher> {
122
123
/// useful to them (communicated inside their block bundles).
123
124
/// Keyed by the peer’s AuthorityIndex.
124
125
useful_authorities_to_peer : Arc < RwLock < BTreeMap < AuthorityIndex , BTreeSet < AuthorityIndex > > > > ,
126
+ /// For each peer `i`, stores a vector where each entry at index `j`
127
+ /// represents the last round in which a received bundle from peer `i`
128
+ /// contained a useful shard from a block created by authority `j`.
129
+ last_round_with_useful_shards_from_peer : Arc < RwLock < Vec < Vec < Round > > > > ,
130
+ /// For each peer `i`, stores a set of authority indices representing the
131
+ /// authors of blocks whose shards were reported as useful by peer `i`.
132
+ peers_reporting_useful_shards : Arc < RwLock < Vec < BTreeSet < AuthorityIndex > > > > ,
125
133
}
126
134
127
135
impl < C : CoreThreadDispatcher > AuthorityService < C > {
@@ -141,6 +149,7 @@ impl<C: CoreThreadDispatcher> AuthorityService<C> {
141
149
context. clone ( ) ,
142
150
core_dispatcher. clone ( ) ,
143
151
) ) ;
152
+ let committee_size = context. committee . size ( ) ;
144
153
145
154
Self {
146
155
context,
@@ -157,6 +166,17 @@ impl<C: CoreThreadDispatcher> AuthorityService<C> {
157
166
useful_authorities_from_peer : Arc :: new ( RwLock :: new ( BTreeMap :: new ( ) ) ) ,
158
167
useful_authorities_to_peer : Arc :: new ( RwLock :: new ( BTreeMap :: new ( ) ) ) ,
159
168
transaction_message_sender,
169
+ last_round_with_useful_shards_from_peer : Arc :: new ( RwLock :: new ( vec ! [
170
+ vec![
171
+ GENESIS_ROUND ;
172
+ committee_size
173
+ ] ;
174
+ committee_size
175
+ ] ) ) ,
176
+ peers_reporting_useful_shards : Arc :: new ( RwLock :: new ( vec ! [
177
+ BTreeSet :: new( ) ;
178
+ committee_size
179
+ ] ) ) ,
160
180
}
161
181
}
162
182
}
@@ -181,6 +201,11 @@ impl<C: CoreThreadDispatcher> NetworkService for AuthorityService<C> {
181
201
let mut guard = self . useful_authorities_to_peer . write ( ) ;
182
202
guard. insert ( peer, useful_authorities_to_peer) ;
183
203
}
204
+ let useful_shards_authors_to_peer = serialized_block_bundle_parts. useful_shards_authors ( ) ;
205
+ {
206
+ let mut guard = self . peers_reporting_useful_shards . write ( ) ;
207
+ guard[ peer] = useful_shards_authors_to_peer;
208
+ }
184
209
185
210
// 1. Create a verified block and make some preliminary checks
186
211
let SerializedHeaderAndTransactions {
@@ -556,6 +581,7 @@ impl<C: CoreThreadDispatcher> NetworkService for AuthorityService<C> {
556
581
. map_err ( |_| ConsensusError :: Shutdown ) ?;
557
582
558
583
// 11. Add the block to dag, add its missing ancestors to the set
584
+ let block_round = verified_block. round ( ) ;
559
585
let ( missing_block_ancestors, missing_block_committed_transactions) = self
560
586
. core_dispatcher
561
587
. add_blocks ( vec ! [ verified_block] )
@@ -597,6 +623,20 @@ impl<C: CoreThreadDispatcher> NetworkService for AuthorityService<C> {
597
623
self . useful_authorities_from_peer . write ( ) ;
598
624
useful_authorities_from_peer_write_guard. insert ( peer, useful_authorities) ;
599
625
}
626
+ {
627
+ let useful_shard_authors = additional_block_headers
628
+ . iter ( )
629
+ . map ( |block_header| block_header. author ( ) )
630
+ . collect :: < Vec < _ > > ( ) ;
631
+ let mut last_round_with_useful_shards_from_peer_write_guard =
632
+ self . last_round_with_useful_shards_from_peer . write ( ) ;
633
+ for author in useful_shard_authors {
634
+ last_round_with_useful_shards_from_peer_write_guard[ peer] [ author] = max (
635
+ last_round_with_useful_shards_from_peer_write_guard[ peer] [ author] ,
636
+ block_round,
637
+ ) ;
638
+ }
639
+ }
600
640
601
641
// 14. schedule the fetching of missing ancestors (if any) from this peer
602
642
if !missing_ancestors. is_empty ( ) {
@@ -662,6 +702,9 @@ impl<C: CoreThreadDispatcher> NetworkService for AuthorityService<C> {
662
702
let dag_state = Arc :: clone ( & self . dag_state ) ;
663
703
let useful_authorities_from_peer = Arc :: clone ( & self . useful_authorities_from_peer ) ;
664
704
let useful_authorities_to_peer = Arc :: clone ( & self . useful_authorities_to_peer ) ;
705
+ let last_round_with_useful_shards_from_peer =
706
+ Arc :: clone ( & self . last_round_with_useful_shards_from_peer ) ;
707
+ let peers_reporting_useful_shards = Arc :: clone ( & self . peers_reporting_useful_shards ) ;
665
708
let committee = self
666
709
. context
667
710
. committee
@@ -675,6 +718,12 @@ impl<C: CoreThreadDispatcher> NetworkService for AuthorityService<C> {
675
718
. get ( & peer)
676
719
. map ( |authorities| authorities. iter ( ) . cloned ( ) . collect :: < BTreeSet < _ > > ( ) ) ;
677
720
drop ( useful_authorities_to_peer_guard) ;
721
+
722
+ let peers_reporting_useful_shards_guard = peers_reporting_useful_shards. read ( ) ;
723
+ let peers_reporting_useful_shards_read =
724
+ peers_reporting_useful_shards_guard[ peer] . clone ( ) ;
725
+ drop ( peers_reporting_useful_shards_guard) ;
726
+
678
727
let useful_authorities_from_peer_guard = useful_authorities_from_peer. read ( ) ;
679
728
let useful_authorities_from_peer_read =
680
729
match useful_authorities_from_peer_guard. get ( & peer) {
@@ -683,6 +732,12 @@ impl<C: CoreThreadDispatcher> NetworkService for AuthorityService<C> {
683
732
} ;
684
733
drop ( useful_authorities_from_peer_guard) ;
685
734
735
+ let last_round_with_useful_shards_from_peer_guard =
736
+ last_round_with_useful_shards_from_peer. read ( ) ;
737
+ let last_round_with_useful_shards_from_peer_read =
738
+ last_round_with_useful_shards_from_peer_guard[ peer] . clone ( ) ;
739
+ drop ( last_round_with_useful_shards_from_peer_guard) ;
740
+
686
741
let mut dag_state_guard = dag_state. write ( ) ;
687
742
let block_headers = match useful_authorities_to_peer_read {
688
743
None => dag_state_guard. take_unknown_headers_for_authority ( peer, block. round ( ) ) ,
@@ -692,15 +747,25 @@ impl<C: CoreThreadDispatcher> NetworkService for AuthorityService<C> {
692
747
authorities,
693
748
) ,
694
749
} ;
695
- let serialized_shards =
696
- dag_state_guard. take_unknown_shards_for_authority ( peer, block. round ( ) ) ;
750
+
751
+ let serialized_shards = dag_state_guard. take_useful_shards_for_authority (
752
+ peer,
753
+ block. round ( ) ,
754
+ peers_reporting_useful_shards_read,
755
+ ) ;
697
756
drop ( dag_state_guard) ;
698
757
758
+ let useful_shards_authors = DagState :: get_useful_shards_authors (
759
+ last_round_with_useful_shards_from_peer_read,
760
+ block. round ( ) ,
761
+ ) ;
762
+
699
763
let block_bundle = BlockBundle {
700
764
verified_block : block,
701
765
verified_headers : block_headers,
702
766
serialized_shards,
703
767
useful_authorities : useful_authorities_from_peer_read,
768
+ useful_shards_authors,
704
769
} ;
705
770
async move {
706
771
match SerializedBlockBundle :: try_from ( block_bundle) {
@@ -1672,6 +1737,7 @@ mod tests {
1672
1737
verified_headers : headers. clone ( ) ,
1673
1738
serialized_shards : vec ! [ ] ,
1674
1739
useful_authorities : ( 0u8 ..( committee_size as u8 ) ) . map ( Into :: into) . collect ( ) ,
1740
+ useful_shards_authors : ( 0u8 ..( committee_size as u8 ) ) . map ( Into :: into) . collect ( ) ,
1675
1741
} ;
1676
1742
let serialized_big_block_bundle = SerializedBlockBundle :: try_from (
1677
1743
SerializedBlockBundleParts :: try_from ( big_block_bundle) . unwrap ( ) ,
@@ -1701,6 +1767,7 @@ mod tests {
1701
1767
verified_headers : headers. clone ( ) ,
1702
1768
serialized_shards : vec ! [ ] ,
1703
1769
useful_authorities : ( 0u8 ..( committee_size as u8 ) ) . map ( Into :: into) . collect ( ) ,
1770
+ useful_shards_authors : ( 0u8 ..( committee_size as u8 ) ) . map ( Into :: into) . collect ( ) ,
1704
1771
} ;
1705
1772
let serialized_block_bundle_with_big_round = SerializedBlockBundle :: try_from (
1706
1773
SerializedBlockBundleParts :: try_from ( block_bundle_with_big_rounds) . unwrap ( ) ,
@@ -1738,6 +1805,7 @@ mod tests {
1738
1805
verified_headers : headers. clone ( ) ,
1739
1806
serialized_shards : vec ! [ ] ,
1740
1807
useful_authorities : ( 0u8 ..( committee_size as u8 ) ) . map ( Into :: into) . collect ( ) ,
1808
+ useful_shards_authors : ( 0u8 ..( committee_size as u8 ) ) . map ( Into :: into) . collect ( ) ,
1741
1809
} ;
1742
1810
let serialized_block_bundle = SerializedBlockBundle :: try_from (
1743
1811
SerializedBlockBundleParts :: try_from ( block_bundle) . unwrap ( ) ,
@@ -2235,6 +2303,9 @@ mod tests {
2235
2303
useful_authorities : ( 0u8 ..( context. committee . size ( ) as u8 ) )
2236
2304
. map ( Into :: into)
2237
2305
. collect ( ) ,
2306
+ useful_shards_authors : ( 0u8 ..( context. committee . size ( ) as u8 ) )
2307
+ . map ( Into :: into)
2308
+ . collect ( ) ,
2238
2309
} ;
2239
2310
let serialized_block_bundle = SerializedBlockBundle :: try_from (
2240
2311
SerializedBlockBundleParts :: try_from ( block_bundle) . unwrap ( ) ,
@@ -2378,6 +2449,9 @@ mod tests {
2378
2449
useful_authorities : ( 0u8 ..( context. committee . size ( ) as u8 ) )
2379
2450
. map ( Into :: into)
2380
2451
. collect ( ) ,
2452
+ useful_shards_authors : ( 0u8 ..( context. committee . size ( ) as u8 ) )
2453
+ . map ( Into :: into)
2454
+ . collect ( ) ,
2381
2455
} ;
2382
2456
let serialized_block_bundle = SerializedBlockBundle :: try_from (
2383
2457
SerializedBlockBundleParts :: try_from ( block_bundle) . unwrap ( ) ,
0 commit comments