@@ -7,6 +7,7 @@ use sc_client_api::{AuxStore, BlockBackend};
7
7
use sp_api:: ProvideRuntimeApi ;
8
8
use sp_block_builder:: BlockBuilder ;
9
9
use sp_blockchain:: HeaderBackend ;
10
+ use sp_consensus_slots:: Slot ;
10
11
use sp_domains:: core_api:: DomainCoreApi ;
11
12
use sp_domains:: {
12
13
Bundle , BundleProducerElectionApi , DomainId , DomainsApi , OperatorId , OperatorPublicKey ,
40
41
keystore : KeystorePtr ,
41
42
bundle_producer_election_solver : BundleProducerElectionSolver < Block , CBlock , CClient > ,
42
43
domain_bundle_proposer : DomainBundleProposer < Block , Client , CBlock , CClient , TransactionPool > ,
44
+ // TODO: both `skip_empty_bundle_production` and `skip_out_of_order_slot` are only used in the
45
+ // tests, we should introduce a trait for `DomainBundleProducer` and use a wrapper of `DomainBundleProducer`
46
+ // in the test, both `skip_empty_bundle_production` and `skip_out_of_order_slot` should move into the wrapper
47
+ // to keep the production code clean.
43
48
skip_empty_bundle_production : bool ,
49
+ skip_out_of_order_slot : bool ,
50
+ last_processed_slot : Option < Slot > ,
44
51
}
45
52
46
53
impl < Block , CBlock , Client , CClient , TransactionPool > Clone
59
66
bundle_producer_election_solver : self . bundle_producer_election_solver . clone ( ) ,
60
67
domain_bundle_proposer : self . domain_bundle_proposer . clone ( ) ,
61
68
skip_empty_bundle_production : self . skip_empty_bundle_production ,
69
+ skip_out_of_order_slot : self . skip_out_of_order_slot ,
70
+ last_processed_slot : None ,
62
71
}
63
72
}
64
73
}
92
101
bundle_sender : Arc < BundleSender < Block , CBlock > > ,
93
102
keystore : KeystorePtr ,
94
103
skip_empty_bundle_production : bool ,
104
+ skip_out_of_order_slot : bool ,
95
105
) -> Self {
96
106
let bundle_producer_election_solver = BundleProducerElectionSolver :: < Block , CBlock , _ > :: new (
97
107
keystore. clone ( ) ,
@@ -106,6 +116,8 @@ where
106
116
bundle_producer_election_solver,
107
117
domain_bundle_proposer,
108
118
skip_empty_bundle_production,
119
+ skip_out_of_order_slot,
120
+ last_processed_slot : None ,
109
121
}
110
122
}
111
123
@@ -131,7 +143,16 @@ where
131
143
// already processed a block higher than the local best and submitted the receipt to
132
144
// the parent chain, we ought to catch up with the consensus block processing before
133
145
// producing new bundle.
134
- !domain_best_number. is_zero ( ) && domain_best_number <= head_receipt_number
146
+ let is_operator_lagging =
147
+ !domain_best_number. is_zero ( ) && domain_best_number <= head_receipt_number;
148
+
149
+ let skip_out_of_order_slot = self . skip_out_of_order_slot
150
+ && self
151
+ . last_processed_slot
152
+ . map ( |last_slot| last_slot >= slot)
153
+ . unwrap_or ( false ) ;
154
+
155
+ is_operator_lagging || skip_out_of_order_slot
135
156
} ;
136
157
137
158
if should_skip_slot {
@@ -182,6 +203,8 @@ where
182
203
return Ok ( None ) ;
183
204
}
184
205
206
+ self . last_processed_slot . replace ( slot) ;
207
+
185
208
info ! ( "🔖 Producing bundle at slot {:?}" , slot_info. slot) ;
186
209
187
210
let to_sign = bundle_header. hash ( ) ;
0 commit comments