1414// You should have received a copy of the GNU General Public License
1515// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
1616
17- //! This provides the option to run a basic relay-chain driven Aura implementation
17+ //! This provides the option to run a basic relay-chain driven Aura implementation.
18+ //!
19+ //! This collator only builds on top of the most recently included block, limiting the
20+ //! block time to a maximum of two times the relay-chain block time, and requiring the
21+ //! block to be built and distributed to validators between two relay-chain blocks.
1822//!
1923//! For more information about AuRa, the Substrate crate should be checked.
2024
@@ -59,6 +63,8 @@ use sp_state_machine::StorageChanges;
5963use sp_timestamp:: Timestamp ;
6064use std:: { convert:: TryFrom , error:: Error , fmt:: Debug , hash:: Hash , sync:: Arc , time:: Duration } ;
6165
66+ use crate :: collator as collator_util;
67+
6268/// Parameters for [`run`].
6369pub struct Params < BI , CIDP , Client , RClient , SO , Proposer , CS > {
6470 pub create_inherent_data_providers : CIDP ,
@@ -110,6 +116,20 @@ pub async fn run<Block, P, BI, CIDP, Client, RClient, SO, Proposer, CS>(
110116 )
111117 . await ;
112118
119+ let mut collator = {
120+ let params = collator_util:: Params {
121+ create_inherent_data_providers : params. create_inherent_data_providers ,
122+ block_import : params. block_import ,
123+ relay_client : params. relay_client . clone ( ) ,
124+ keystore : params. keystore . clone ( ) ,
125+ para_id : params. para_id ,
126+ proposer : params. proposer ,
127+ collator_service : params. collator_service ,
128+ } ;
129+
130+ collator_util:: Collator :: < Block , P , _ , _ , _ , _ , _ > :: new ( params)
131+ } ;
132+
113133 while let Some ( request) = collation_requests. next ( ) . await {
114134 macro_rules! reject_with_error {
115135 ( $err: expr) => { {
@@ -135,7 +155,7 @@ pub async fn run<Block, P, BI, CIDP, Client, RClient, SO, Proposer, CS>(
135155
136156 let parent_hash = parent_header. hash ( ) ;
137157
138- if !params . collator_service . check_block_status ( parent_hash, & parent_header) {
158+ if !collator . collator_service ( ) . check_block_status ( parent_hash, & parent_header) {
139159 continue
140160 }
141161
@@ -145,7 +165,7 @@ pub async fn run<Block, P, BI, CIDP, Client, RClient, SO, Proposer, CS>(
145165 Ok ( Some ( h) ) => h,
146166 } ;
147167
148- let claim = match claim_slot :: < _ , _ , P > (
168+ let claim = match collator_util :: claim_slot :: < _ , _ , P > (
149169 & * params. para_client ,
150170 parent_hash,
151171 & relay_parent_header,
@@ -161,217 +181,33 @@ pub async fn run<Block, P, BI, CIDP, Client, RClient, SO, Proposer, CS>(
161181 } ;
162182
163183 let ( parachain_inherent_data, other_inherent_data) = try_request ! (
164- create_inherent_data(
184+ collator . create_inherent_data(
165185 * request. relay_parent( ) ,
166186 & validation_data,
167187 parent_hash,
168- params. para_id,
169- claim. timestamp,
170- & params. relay_client,
171- & params. create_inherent_data_providers,
172- )
173- . await
188+ claim. timestamp( ) ,
189+ ) . await
174190 ) ;
175191
176- let proposal = try_request ! (
177- params
178- . proposer
179- . propose(
180- & parent_header,
181- & parachain_inherent_data,
182- other_inherent_data,
183- Digest { logs: vec![ claim. pre_digest] } ,
184- // TODO [https://github.com/paritytech/cumulus/issues/2439]
185- // We should call out to a pluggable interface that provides
186- // the proposal duration.
187- Duration :: from_millis( 500 ) ,
188- // Set the block limit to 50% of the maximum PoV size.
189- //
190- // TODO: If we got benchmarking that includes the proof size,
191- // we should be able to use the maximum pov size.
192- Some ( ( validation_data. max_pov_size / 2 ) as usize ) ,
193- )
194- . await
192+ let ( collation, _, post_hash) = try_request ! (
193+ collator. collate(
194+ & parent_header,
195+ & claim,
196+ None ,
197+ ( parachain_inherent_data, other_inherent_data) ,
198+ // TODO [https://github.com/paritytech/cumulus/issues/2439]
199+ // We should call out to a pluggable interface that provides
200+ // the proposal duration.
201+ Duration :: from_millis( 500 ) ,
202+ // Set the block limit to 50% of the maximum PoV size.
203+ //
204+ // TODO: If we got benchmarking that includes the proof size,
205+ // we should be able to use the maximum pov size.
206+ ( validation_data. max_pov_size / 2 ) as usize ,
207+ ) . await
195208 ) ;
196209
197- let sealed_importable = try_request ! ( seal:: <_, _, P >(
198- proposal. block,
199- proposal. storage_changes,
200- & claim. author_pub,
201- & params. keystore,
202- ) ) ;
203-
204- let post_hash = sealed_importable. post_hash ( ) ;
205- let block = Block :: new (
206- sealed_importable. post_header ( ) ,
207- sealed_importable
208- . body
209- . as_ref ( )
210- . expect ( "body always created with this `propose` fn; qed" )
211- . clone ( ) ,
212- ) ;
213-
214- try_request ! ( params. block_import. import_block( sealed_importable) . await ) ;
215-
216- let response = if let Some ( ( collation, b) ) = params. collator_service . build_collation (
217- & parent_header,
218- post_hash,
219- ParachainCandidate { block, proof : proposal. proof } ,
220- ) {
221- tracing:: info!(
222- target: crate :: LOG_TARGET ,
223- "PoV size {{ header: {}kb, extrinsics: {}kb, storage_proof: {}kb }}" ,
224- b. header( ) . encode( ) . len( ) as f64 / 1024f64 ,
225- b. extrinsics( ) . encode( ) . len( ) as f64 / 1024f64 ,
226- b. storage_proof( ) . encode( ) . len( ) as f64 / 1024f64 ,
227- ) ;
228-
229- if let MaybeCompressedPoV :: Compressed ( ref pov) = collation. proof_of_validity {
230- tracing:: info!(
231- target: crate :: LOG_TARGET ,
232- "Compressed PoV size: {}kb" ,
233- pov. block_data. 0 . len( ) as f64 / 1024f64 ,
234- ) ;
235- }
236-
237- let result_sender = params. collator_service . announce_with_barrier ( post_hash) ;
238- Some ( CollationResult { collation, result_sender : Some ( result_sender) } )
239- } else {
240- None
241- } ;
242-
243- request. complete ( response) ;
210+ let result_sender = Some ( collator. collator_service ( ) . announce_with_barrier ( post_hash) ) ;
211+ request. complete ( Some ( CollationResult { collation, result_sender } ) ) ;
244212 }
245213}
246-
247- /// A claim on an Aura slot.
248- struct SlotClaim < Pub > {
249- author_pub : Pub ,
250- pre_digest : sp_runtime:: DigestItem ,
251- timestamp : Timestamp ,
252- }
253-
254- async fn claim_slot < B , C , P > (
255- client : & C ,
256- parent_hash : B :: Hash ,
257- relay_parent_header : & PHeader ,
258- slot_duration : SlotDuration ,
259- relay_chain_slot_duration : SlotDuration ,
260- keystore : & KeystorePtr ,
261- ) -> Result < Option < SlotClaim < P :: Public > > , Box < dyn Error > >
262- where
263- B : BlockT ,
264- C : ProvideRuntimeApi < B > + Send + Sync + ' static ,
265- C :: Api : AuraApi < B , P :: Public > ,
266- P : Pair ,
267- P :: Public : Encode + Decode ,
268- P :: Signature : Encode + Decode ,
269- {
270- // load authorities
271- let authorities = client. runtime_api ( ) . authorities ( parent_hash) . map_err ( Box :: new) ?;
272-
273- // Determine the current slot and timestamp based on the relay-parent's.
274- let ( slot_now, timestamp) =
275- match sc_consensus_babe:: find_pre_digest :: < PBlock > ( relay_parent_header) {
276- Ok ( babe_pre_digest) => {
277- let t =
278- Timestamp :: new ( relay_chain_slot_duration. as_millis ( ) * * babe_pre_digest. slot ( ) ) ;
279- let slot = Slot :: from_timestamp ( t, slot_duration) ;
280-
281- ( slot, t)
282- } ,
283- Err ( _) => return Ok ( None ) ,
284- } ;
285-
286- // Try to claim the slot locally.
287- let author_pub = {
288- let res = aura_internal:: claim_slot :: < P > ( slot_now, & authorities, keystore) . await ;
289- match res {
290- Some ( p) => p,
291- None => return Ok ( None ) ,
292- }
293- } ;
294-
295- // Produce the pre-digest.
296- let pre_digest = aura_internal:: pre_digest :: < P > ( slot_now) ;
297-
298- Ok ( Some ( SlotClaim { author_pub, pre_digest, timestamp } ) )
299- }
300-
301- // This explicitly creates the inherent data for parachains, as well as overriding the
302- // timestamp based on the slot number.
303- async fn create_inherent_data < B : BlockT > (
304- relay_parent : PHash ,
305- validation_data : & PersistedValidationData ,
306- parent_hash : B :: Hash ,
307- para_id : ParaId ,
308- timestamp : Timestamp ,
309- relay_chain_interface : & impl RelayChainInterface ,
310- create_inherent_data_providers : & impl CreateInherentDataProviders < B , ( ) > ,
311- ) -> Result < ( ParachainInherentData , InherentData ) , Box < dyn Error > > {
312- let paras_inherent_data = ParachainInherentData :: create_at (
313- relay_parent,
314- relay_chain_interface,
315- validation_data,
316- para_id,
317- )
318- . await ;
319-
320- let paras_inherent_data = match paras_inherent_data {
321- Some ( p) => p,
322- None =>
323- return Err ( format ! ( "Could not create paras inherent data at {:?}" , relay_parent) . into ( ) ) ,
324- } ;
325-
326- let mut other_inherent_data = create_inherent_data_providers
327- . create_inherent_data_providers ( parent_hash, ( ) )
328- . map_err ( |e| e as Box < dyn Error > )
329- . await ?
330- . create_inherent_data ( )
331- . await
332- . map_err ( Box :: new) ?;
333-
334- other_inherent_data. replace_data ( sp_timestamp:: INHERENT_IDENTIFIER , & timestamp) ;
335-
336- Ok ( ( paras_inherent_data, other_inherent_data) )
337- }
338-
339- fn seal < B : BlockT , T , P > (
340- pre_sealed : B ,
341- storage_changes : StorageChanges < T , HashFor < B > > ,
342- author_pub : & P :: Public ,
343- keystore : & KeystorePtr ,
344- ) -> Result < BlockImportParams < B , T > , Box < dyn Error > >
345- where
346- P : Pair ,
347- P :: Signature : Encode + Decode + TryFrom < Vec < u8 > > ,
348- P :: Public : AppPublic ,
349- {
350- let ( pre_header, body) = pre_sealed. deconstruct ( ) ;
351- let pre_hash = pre_header. hash ( ) ;
352- let block_number = * pre_header. number ( ) ;
353-
354- // seal the block.
355- let block_import_params = {
356- let seal_digest =
357- aura_internal:: seal :: < _ , P > ( & pre_hash, & author_pub, keystore) . map_err ( Box :: new) ?;
358- let mut block_import_params = BlockImportParams :: new ( BlockOrigin :: Own , pre_header) ;
359- block_import_params. post_digests . push ( seal_digest) ;
360- block_import_params. body = Some ( body. clone ( ) ) ;
361- block_import_params. state_action =
362- StateAction :: ApplyChanges ( sc_consensus:: StorageChanges :: Changes ( storage_changes) ) ;
363- block_import_params. fork_choice = Some ( ForkChoiceStrategy :: LongestChain ) ;
364- block_import_params
365- } ;
366- let post_hash = block_import_params. post_hash ( ) ;
367-
368- tracing:: info!(
369- target: crate :: LOG_TARGET ,
370- "🔖 Pre-sealed block for proposal at {}. Hash now {:?}, previously {:?}." ,
371- block_number,
372- post_hash,
373- pre_hash,
374- ) ;
375-
376- Ok ( block_import_params)
377- }
0 commit comments