Manual Seal: Calculate the block's post hash (#10498)

* calculate the post hash

* Add test

Co-authored-by: tgmichel <telmo@purestake.com>
This commit is contained in:
Joshy Orndorff
2022-01-10 06:55:05 -05:00
committed by GitHub
parent 3093bed933
commit 2178cb1939
2 changed files with 86 additions and 2 deletions
@@ -253,7 +253,8 @@ mod tests {
use sc_consensus::ImportedAux;
use sc_transaction_pool::{BasicPool, Options, RevalidationType};
use sc_transaction_pool_api::{MaintainedTransactionPool, TransactionPool, TransactionSource};
use sp_runtime::generic::BlockId;
use sp_inherents::InherentData;
use sp_runtime::generic::{BlockId, Digest, DigestItem};
use substrate_test_runtime_client::{
AccountKeyring::*, DefaultTestClientBuilderExt, TestClientBuilder, TestClientBuilderExt,
};
@@ -265,6 +266,35 @@ mod tests {
const SOURCE: TransactionSource = TransactionSource::External;
struct TestDigestProvider<C> {
_client: Arc<C>,
}
impl<B, C> ConsensusDataProvider<B> for TestDigestProvider<C>
where
B: BlockT,
C: ProvideRuntimeApi<B> + Send + Sync,
{
type Transaction = TransactionFor<C, B>;
fn create_digest(
&self,
_parent: &B::Header,
_inherents: &InherentData,
) -> Result<Digest, Error> {
Ok(Digest { logs: vec![] })
}
fn append_block_import(
&self,
_parent: &B::Header,
params: &mut BlockImportParams<B, Self::Transaction>,
_inherents: &InherentData,
) -> Result<(), Error> {
params.post_digests.push(DigestItem::Other(vec![1]));
Ok(())
}
}
#[tokio::test]
async fn instant_seal() {
let builder = TestClientBuilder::new();
@@ -519,4 +549,53 @@ mod tests {
// assert that fork block is in the db
assert!(client.header(&BlockId::Hash(imported.hash)).unwrap().is_some())
}
#[tokio::test]
async fn manual_seal_post_hash() {
let builder = TestClientBuilder::new();
let (client, select_chain) = builder.build_with_longest_chain();
let client = Arc::new(client);
let spawner = sp_core::testing::TaskExecutor::new();
let pool = Arc::new(BasicPool::with_revalidation_type(
Options::default(),
true.into(),
api(),
None,
RevalidationType::Full,
spawner.clone(),
0,
));
let env = ProposerFactory::new(spawner.clone(), client.clone(), pool.clone(), None, None);
let (mut sink, commands_stream) = futures::channel::mpsc::channel(1024);
let future = run_manual_seal(ManualSealParams {
block_import: client.clone(),
env,
client: client.clone(),
pool: pool.clone(),
commands_stream,
select_chain,
// use a provider that pushes some post digest data
consensus_data_provider: Some(Box::new(TestDigestProvider { _client: client.clone() })),
create_inherent_data_providers: |_, _| async { Ok(()) },
});
std::thread::spawn(|| {
let rt = tokio::runtime::Runtime::new().unwrap();
rt.block_on(future);
});
let (tx, rx) = futures::channel::oneshot::channel();
sink.send(EngineCommand::SealNewBlock {
parent_hash: None,
sender: Some(tx),
create_empty: true,
finalize: false,
})
.await
.unwrap();
let created_block = rx.await.unwrap().unwrap();
// assert that the background task returned the actual header hash
let header = client.header(&BlockId::Number(1)).unwrap().unwrap();
assert_eq!(header.hash(), created_block.hash);
}
}
@@ -153,9 +153,14 @@ pub async fn seal_block<B, BI, SC, C, E, TP, CIDP>(
digest_provider.append_block_import(&parent, &mut params, &inherent_data)?;
}
// Make sure we return the same post-hash that will be calculated when importing the block
// This is important in case the digest_provider added any signature, seal, ect.
let mut post_header = header.clone();
post_header.digest_mut().logs.extend(params.post_digests.iter().cloned());
match block_import.import_block(params, HashMap::new()).await? {
ImportResult::Imported(aux) =>
Ok(CreatedBlock { hash: <B as BlockT>::Header::hash(&header), aux }),
Ok(CreatedBlock { hash: <B as BlockT>::Header::hash(&post_header), aux }),
other => Err(other.into()),
}
};