use sc_client_api::{backend::Finalizer, client::BlockBackend};
use sc_consensus::{BlockImport, BlockImportParams, ForkChoiceStrategy};
use sc_service::client::Client;
use sp_consensus::Error as ConsensusError;
use sp_runtime::{traits::Block as BlockT, Justification, Justifications};
pub use sp_consensus::BlockOrigin;
pub trait ClientExt<Block: BlockT>: Sized {
fn finalize_block(
&self,
hash: Block::Hash,
justification: Option<Justification>,
) -> sp_blockchain::Result<()>;
fn genesis_hash(&self) -> <Block as BlockT>::Hash;
}
#[async_trait::async_trait]
pub trait ClientBlockImportExt<Block: BlockT>: Sized {
async fn import(&self, origin: BlockOrigin, block: Block) -> Result<(), ConsensusError>;
async fn import_as_best(&self, origin: BlockOrigin, block: Block)
-> Result<(), ConsensusError>;
async fn import_as_final(
&self,
origin: BlockOrigin,
block: Block,
) -> Result<(), ConsensusError>;
async fn import_justified(
&self,
origin: BlockOrigin,
block: Block,
justifications: Justifications,
) -> Result<(), ConsensusError>;
}
impl<B, E, RA, Block> ClientExt<Block> for Client<B, E, Block, RA>
where
B: sc_client_api::backend::Backend<Block>,
E: sc_client_api::CallExecutor<Block> + sc_executor::RuntimeVersionOf + 'static,
Self: BlockImport<Block, Error = ConsensusError>,
Block: BlockT,
{
fn finalize_block(
&self,
hash: Block::Hash,
justification: Option<Justification>,
) -> sp_blockchain::Result<()> {
Finalizer::finalize_block(self, hash, justification, true)
}
fn genesis_hash(&self) -> <Block as BlockT>::Hash {
self.block_hash(0u32.into()).unwrap().unwrap()
}
}
#[async_trait::async_trait]
impl<Block: BlockT, T> ClientBlockImportExt<Block> for std::sync::Arc<T>
where
for<'r> &'r T: BlockImport<Block, Error = ConsensusError>,
T: Send + Sync,
{
async fn import(&self, origin: BlockOrigin, block: Block) -> Result<(), ConsensusError> {
let (header, extrinsics) = block.deconstruct();
let mut import = BlockImportParams::new(origin, header);
import.body = Some(extrinsics);
import.fork_choice = Some(ForkChoiceStrategy::LongestChain);
BlockImport::import_block(self, import).await.map(|_| ())
}
async fn import_as_best(
&self,
origin: BlockOrigin,
block: Block,
) -> Result<(), ConsensusError> {
let (header, extrinsics) = block.deconstruct();
let mut import = BlockImportParams::new(origin, header);
import.body = Some(extrinsics);
import.fork_choice = Some(ForkChoiceStrategy::Custom(true));
BlockImport::import_block(self, import).await.map(|_| ())
}
async fn import_as_final(
&self,
origin: BlockOrigin,
block: Block,
) -> Result<(), ConsensusError> {
let (header, extrinsics) = block.deconstruct();
let mut import = BlockImportParams::new(origin, header);
import.body = Some(extrinsics);
import.finalized = true;
import.fork_choice = Some(ForkChoiceStrategy::Custom(true));
BlockImport::import_block(self, import).await.map(|_| ())
}
async fn import_justified(
&self,
origin: BlockOrigin,
block: Block,
justifications: Justifications,
) -> Result<(), ConsensusError> {
let (header, extrinsics) = block.deconstruct();
let mut import = BlockImportParams::new(origin, header);
import.justifications = Some(justifications);
import.body = Some(extrinsics);
import.finalized = true;
import.fork_choice = Some(ForkChoiceStrategy::LongestChain);
BlockImport::import_block(self, import).await.map(|_| ())
}
}
#[async_trait::async_trait]
impl<B, E, RA, Block: BlockT> ClientBlockImportExt<Block> for Client<B, E, Block, RA>
where
Self: BlockImport<Block, Error = ConsensusError>,
RA: Send + Sync,
B: Send + Sync,
E: Send + Sync,
{
async fn import(&self, origin: BlockOrigin, block: Block) -> Result<(), ConsensusError> {
let (header, extrinsics) = block.deconstruct();
let mut import = BlockImportParams::new(origin, header);
import.body = Some(extrinsics);
import.fork_choice = Some(ForkChoiceStrategy::LongestChain);
BlockImport::import_block(self, import).await.map(|_| ())
}
async fn import_as_best(
&self,
origin: BlockOrigin,
block: Block,
) -> Result<(), ConsensusError> {
let (header, extrinsics) = block.deconstruct();
let mut import = BlockImportParams::new(origin, header);
import.body = Some(extrinsics);
import.fork_choice = Some(ForkChoiceStrategy::Custom(true));
BlockImport::import_block(self, import).await.map(|_| ())
}
async fn import_as_final(
&self,
origin: BlockOrigin,
block: Block,
) -> Result<(), ConsensusError> {
let (header, extrinsics) = block.deconstruct();
let mut import = BlockImportParams::new(origin, header);
import.body = Some(extrinsics);
import.finalized = true;
import.fork_choice = Some(ForkChoiceStrategy::Custom(true));
BlockImport::import_block(self, import).await.map(|_| ())
}
async fn import_justified(
&self,
origin: BlockOrigin,
block: Block,
justifications: Justifications,
) -> Result<(), ConsensusError> {
let (header, extrinsics) = block.deconstruct();
let mut import = BlockImportParams::new(origin, header);
import.justifications = Some(justifications);
import.body = Some(extrinsics);
import.finalized = true;
import.fork_choice = Some(ForkChoiceStrategy::LongestChain);
BlockImport::import_block(self, import).await.map(|_| ())
}
}