1616
1717use crate :: * ;
1818use cumulus_client_collator:: service:: ServiceInterface as CollatorServiceInterface ;
19- use cumulus_client_consensus_common:: ParachainBlockImportMarker ;
19+ use cumulus_client_consensus_common:: { self as consensus_common , ParachainBlockImportMarker } ;
2020use cumulus_client_consensus_proposer:: ProposerInterface ;
2121use cumulus_primitives_core:: {
22- relay_chain:: { BlockId as RBlockId , Hash as PHash } ,
22+ relay_chain:: { BlockId as RBlockId , Hash as PHash , ValidationCode } ,
2323 CollectCollationInfo , ParaId , PersistedValidationData ,
2424} ;
2525use cumulus_relay_chain_interface:: { OverseerHandle , RelayChainInterface } ;
2626use futures:: prelude:: * ;
2727use nimbus_primitives:: { DigestsProvider , NimbusApi , NimbusId } ;
2828use polkadot_node_primitives:: CollationResult ;
2929use polkadot_primitives:: CollatorPair ;
30- use sc_client_api:: { BlockBackend , BlockOf } ;
31- use sp_api:: ProvideRuntimeApi ;
30+ use sc_client_api:: { AuxStore , BlockBackend , BlockOf , StateBackend } ;
31+ use sp_api:: { CallApiAt , ProvideRuntimeApi } ;
3232use sp_blockchain:: HeaderBackend ;
33+ use sp_consensus_slots:: { Slot , SlotDuration } ;
3334use sp_core:: Decode ;
3435use sp_inherents:: CreateInherentDataProviders ;
3536use sp_keystore:: KeystorePtr ;
@@ -44,6 +45,11 @@ pub struct Params<Proposer, BI, ParaClient, RClient, CIDP, CS, ADP = ()> {
4445 pub para_id : ParaId ,
4546 /// A handle to the relay-chain client's "Overseer" or task orchestrator.
4647 pub overseer_handle : OverseerHandle ,
48+ /// The length of slots in the relay chain.
49+ pub relay_chain_slot_duration : Duration ,
50+ /// The length of slots in this parachain.
51+ /// If the parachain doesn't have slot and rely only on relay slots, set it to None.
52+ pub slot_duration : Option < SlotDuration > ,
4753 /// The underlying block proposer this should call into.
4854 pub proposer : Proposer ,
4955 /// The block import handle.
@@ -79,8 +85,10 @@ pub async fn run<Block, BI, CIDP, Backend, Client, RClient, Proposer, CS, ADP>(
7985 BI : BlockImport < Block > + ParachainBlockImportMarker + Send + Sync + ' static ,
8086 Client : ProvideRuntimeApi < Block >
8187 + BlockOf
88+ + AuxStore
8289 + HeaderBackend < Block >
8390 + BlockBackend < Block >
91+ + CallApiAt < Block >
8492 + Send
8593 + Sync
8694 + ' static ,
@@ -112,6 +120,9 @@ pub async fn run<Block, BI, CIDP, Backend, Client, RClient, Proposer, CS, ADP>(
112120 ..
113121 } = params;
114122
123+ let mut last_processed_slot = 0 ;
124+ let mut last_relay_chain_block = Default :: default ( ) ;
125+
115126 while let Some ( request) = collation_requests. next ( ) . await {
116127 macro_rules! reject_with_error {
117128 ( $err: expr) => { {
@@ -142,6 +153,25 @@ pub async fn run<Block, BI, CIDP, Backend, Client, RClient, Proposer, CS, ADP>(
142153 continue ;
143154 }
144155
156+ let Ok ( Some ( code) ) = para_client
157+ . state_at ( parent_hash)
158+ . map_err ( drop)
159+ . and_then ( |s| {
160+ s. storage ( & sp_core:: storage:: well_known_keys:: CODE )
161+ . map_err ( drop)
162+ } )
163+ else {
164+ continue ;
165+ } ;
166+
167+ super :: check_validation_code_or_log (
168+ & ValidationCode :: from ( code) . hash ( ) ,
169+ para_id,
170+ & relay_client,
171+ * request. relay_parent ( ) ,
172+ )
173+ . await ;
174+
145175 let relay_parent_header = match relay_client
146176 . header ( RBlockId :: hash ( * request. relay_parent ( ) ) )
147177 . await
@@ -165,6 +195,54 @@ pub async fn run<Block, BI, CIDP, Backend, Client, RClient, Proposer, CS, ADP>(
165195 Err ( e) => reject_with_error ! ( e) ,
166196 } ;
167197
198+ // Determine which is the current slot
199+ let ( slot_now, timestamp) = match consensus_common:: relay_slot_and_timestamp (
200+ & relay_parent_header,
201+ params. relay_chain_slot_duration ,
202+ ) {
203+ None => {
204+ tracing:: trace!(
205+ target: crate :: LOG_TARGET ,
206+ relay_parent = ?relay_parent_header,
207+ relay_chain_slot_duration = ?params. relay_chain_slot_duration,
208+ "Fail to get the relay slot for this relay block!"
209+ ) ;
210+ continue ;
211+ }
212+ Some ( ( relay_slot, relay_timestamp) ) => {
213+ let our_slot = if let Some ( slot_duration) = params. slot_duration {
214+ Slot :: from_timestamp ( relay_timestamp, slot_duration)
215+ } else {
216+ // If there is no slot duration, we assume that the parachain use the relay slot directly
217+ relay_slot
218+ } ;
219+ tracing:: debug!(
220+ target: crate :: LOG_TARGET ,
221+ ?relay_slot,
222+ para_slot = ?our_slot,
223+ ?relay_timestamp,
224+ slot_duration = ?params. slot_duration,
225+ relay_chain_slot_duration = ?params. relay_chain_slot_duration,
226+ "Adjusted relay-chain slot to parachain slot"
227+ ) ;
228+ ( our_slot, relay_timestamp)
229+ }
230+ } ;
231+
232+ // With async backing this function will be called every relay chain block.
233+ //
234+ // Most parachains currently run with 12 seconds slots and thus, they would try to
235+ // produce multiple blocks per slot which very likely would fail on chain. Thus, we have
236+ // this "hack" to only produce one block per slot per relay chain fork.
237+ //
238+ // With https://github.com/paritytech/polkadot-sdk/issues/3168 this implementation will be
239+ // obsolete and also the underlying issue will be fixed.
240+ if last_processed_slot >= * slot_now
241+ && last_relay_chain_block < * relay_parent_header. number ( )
242+ {
243+ continue ;
244+ }
245+
168246 let inherent_data = try_request ! (
169247 create_inherent_data(
170248 & create_inherent_data_providers,
@@ -174,6 +252,7 @@ pub async fn run<Block, BI, CIDP, Backend, Client, RClient, Proposer, CS, ADP>(
174252 & relay_client,
175253 * request. relay_parent( ) ,
176254 nimbus_id. clone( ) ,
255+ Some ( timestamp)
177256 )
178257 . await
179258 ) ;
@@ -216,5 +295,8 @@ pub async fn run<Block, BI, CIDP, Backend, Client, RClient, Proposer, CS, ADP>(
216295 request. complete ( None ) ;
217296 tracing:: debug!( target: crate :: LOG_TARGET , "No block proposal" ) ;
218297 }
298+
299+ last_processed_slot = * slot_now;
300+ last_relay_chain_block = * relay_parent_header. number ( ) ;
219301 }
220302}
0 commit comments