proposer: return optional block (#2834)

This opens up the proposer to only optionally create blocks. Nodes may
only make blocks when there are transactions or the chain is scheduled.

---------

Co-authored-by: command-bot <>
This commit is contained in:
asynchronous rob
2024-01-04 10:57:10 -08:00
committed by GitHub
parent e07476e34e
commit 19de1c9660
5 changed files with 41 additions and 10 deletions
+11 -4
View File
@@ -172,12 +172,14 @@ where
inherent_data: (ParachainInherentData, InherentData), inherent_data: (ParachainInherentData, InherentData),
proposal_duration: Duration, proposal_duration: Duration,
max_pov_size: usize, max_pov_size: usize,
) -> Result<(Collation, ParachainBlockData<Block>, Block::Hash), Box<dyn Error + Send + 'static>> ) -> Result<
{ Option<(Collation, ParachainBlockData<Block>, Block::Hash)>,
Box<dyn Error + Send + 'static>,
> {
let mut digest = additional_pre_digest.into().unwrap_or_default(); let mut digest = additional_pre_digest.into().unwrap_or_default();
digest.push(slot_claim.pre_digest.clone()); digest.push(slot_claim.pre_digest.clone());
let proposal = self let maybe_proposal = self
.proposer .proposer
.propose( .propose(
&parent_header, &parent_header,
@@ -190,6 +192,11 @@ where
.await .await
.map_err(|e| Box::new(e) as Box<dyn Error + Send>)?; .map_err(|e| Box::new(e) as Box<dyn Error + Send>)?;
let proposal = match maybe_proposal {
None => return Ok(None),
Some(p) => p,
};
let sealed_importable = seal::<_, P>( let sealed_importable = seal::<_, P>(
proposal.block, proposal.block,
proposal.storage_changes, proposal.storage_changes,
@@ -234,7 +241,7 @@ where
); );
} }
Ok((collation, block_data, post_hash)) Ok(Some((collation, block_data, post_hash)))
} else { } else {
Err(Box::<dyn Error + Send + Sync>::from("Unable to produce collation") Err(Box::<dyn Error + Send + Sync>::from("Unable to produce collation")
as Box<dyn Error + Send>) as Box<dyn Error + Send>)
@@ -203,7 +203,7 @@ where
.await .await
); );
let (collation, _, post_hash) = try_request!( let maybe_collation = try_request!(
collator collator
.collate( .collate(
&parent_header, &parent_header,
@@ -220,8 +220,14 @@ where
.await .await
); );
let result_sender = Some(collator.collator_service().announce_with_barrier(post_hash)); if let Some((collation, _, post_hash)) = maybe_collation {
request.complete(Some(CollationResult { collation, result_sender })); let result_sender =
Some(collator.collator_service().announce_with_barrier(post_hash));
request.complete(Some(CollationResult { collation, result_sender }));
} else {
request.complete(None);
tracing::debug!(target: crate::LOG_TARGET, "No block proposal");
}
} }
} }
} }
@@ -359,7 +359,7 @@ where
) )
.await .await
{ {
Ok((collation, block_data, new_block_hash)) => { Ok(Some((collation, block_data, new_block_hash))) => {
// Here we are assuming that the import logic protects against equivocations // Here we are assuming that the import logic protects against equivocations
// and provides sybil-resistance, as it should. // and provides sybil-resistance, as it should.
collator.collator_service().announce_block(new_block_hash, None); collator.collator_service().announce_block(new_block_hash, None);
@@ -387,6 +387,10 @@ where
parent_hash = new_block_hash; parent_hash = new_block_hash;
parent_header = block_data.into_header(); parent_header = block_data.into_header();
}, },
Ok(None) => {
tracing::debug!(target: crate::LOG_TARGET, "No block proposal");
break
},
Err(err) => { Err(err) => {
tracing::error!(target: crate::LOG_TARGET, ?err); tracing::error!(target: crate::LOG_TARGET, ?err);
break break
+3 -2
View File
@@ -76,7 +76,7 @@ pub trait ProposerInterface<Block: BlockT> {
inherent_digests: Digest, inherent_digests: Digest,
max_duration: Duration, max_duration: Duration,
block_size_limit: Option<usize>, block_size_limit: Option<usize>,
) -> Result<Proposal<Block, StorageProof>, Error>; ) -> Result<Option<Proposal<Block, StorageProof>>, Error>;
} }
/// A simple wrapper around a Substrate proposer for creating collations. /// A simple wrapper around a Substrate proposer for creating collations.
@@ -109,7 +109,7 @@ where
inherent_digests: Digest, inherent_digests: Digest,
max_duration: Duration, max_duration: Duration,
block_size_limit: Option<usize>, block_size_limit: Option<usize>,
) -> Result<Proposal<B, StorageProof>, Error> { ) -> Result<Option<Proposal<B, StorageProof>>, Error> {
let proposer = self let proposer = self
.inner .inner
.init(parent_header) .init(parent_header)
@@ -127,6 +127,7 @@ where
proposer proposer
.propose(inherent_data, inherent_digests, max_duration, block_size_limit) .propose(inherent_data, inherent_digests, max_duration, block_size_limit)
.await .await
.map(Some)
.map_err(|e| Error::proposing(anyhow::Error::new(e)).into()) .map_err(|e| Error::proposing(anyhow::Error::new(e)).into())
} }
} }
+13
View File
@@ -0,0 +1,13 @@
title: "proposer: return optional block"
doc:
- audience: Node Dev
description: |
The `ProposerInterface` trait now returns an optional `Proposal`, allowing
for no block to be created. This is a breaking change that only impacts custom
`ProposerInterface` implementations. The change allows more flexibility in choosing
when to create blocks.
crates:
- name: "cumulus-client-consensus-aura"
- name: "cumulus-client-consensus-proposer"