mirror of
https://github.com/serai-dex/serai.git
synced 2025-01-24 11:36:18 +00:00
Clean generics in Tendermint with a monolith with associated types
This commit is contained in:
parent
8d3efd6259
commit
6838d5c922
9 changed files with 218 additions and 269 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -7536,6 +7536,7 @@ dependencies = [
|
||||||
"pallet-session",
|
"pallet-session",
|
||||||
"sc-basic-authorship",
|
"sc-basic-authorship",
|
||||||
"sc-client-api",
|
"sc-client-api",
|
||||||
|
"sc-client-db",
|
||||||
"sc-consensus",
|
"sc-consensus",
|
||||||
"sc-executor",
|
"sc-executor",
|
||||||
"sc-network",
|
"sc-network",
|
||||||
|
|
|
@ -38,6 +38,7 @@ sc-executor = { git = "https://github.com/serai-dex/substrate" }
|
||||||
sc-network = { git = "https://github.com/serai-dex/substrate" }
|
sc-network = { git = "https://github.com/serai-dex/substrate" }
|
||||||
sc-network-gossip = { git = "https://github.com/serai-dex/substrate" }
|
sc-network-gossip = { git = "https://github.com/serai-dex/substrate" }
|
||||||
sc-service = { git = "https://github.com/serai-dex/substrate" }
|
sc-service = { git = "https://github.com/serai-dex/substrate" }
|
||||||
|
sc-client-db = { git = "https://github.com/serai-dex/substrate" }
|
||||||
sc-client-api = { git = "https://github.com/serai-dex/substrate" }
|
sc-client-api = { git = "https://github.com/serai-dex/substrate" }
|
||||||
sc-consensus = { git = "https://github.com/serai-dex/substrate" }
|
sc-consensus = { git = "https://github.com/serai-dex/substrate" }
|
||||||
|
|
||||||
|
|
|
@ -2,45 +2,25 @@ use std::{sync::Arc, collections::HashMap};
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
use sp_inherents::CreateInherentDataProviders;
|
use sp_consensus::{Error, CacheKeyId};
|
||||||
use sp_runtime::traits::Block;
|
|
||||||
use sp_api::TransactionFor;
|
|
||||||
|
|
||||||
use sp_consensus::{Error, CacheKeyId, Environment};
|
|
||||||
use sc_consensus::{BlockCheckParams, BlockImportParams, ImportResult, BlockImport};
|
use sc_consensus::{BlockCheckParams, BlockImportParams, ImportResult, BlockImport};
|
||||||
|
|
||||||
use sc_client_api::Backend;
|
use crate::{types::TendermintAuthor, tendermint::TendermintImport};
|
||||||
|
|
||||||
use sp_tendermint::TendermintApi;
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
tendermint::{TendermintClient, TendermintImport},
|
|
||||||
Announce,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<
|
impl<T: TendermintAuthor> BlockImport<T::Block> for TendermintImport<T>
|
||||||
B: Block,
|
|
||||||
Be: Backend<B> + 'static,
|
|
||||||
C: TendermintClient<B, Be>,
|
|
||||||
CIDP: CreateInherentDataProviders<B, ()> + 'static,
|
|
||||||
E: Send + Sync + Environment<B> + 'static,
|
|
||||||
A: Announce<B>,
|
|
||||||
> BlockImport<B> for TendermintImport<B, Be, C, CIDP, E, A>
|
|
||||||
where
|
where
|
||||||
TransactionFor<C, B>: Send + Sync + 'static,
|
Arc<T::Client>: BlockImport<T::Block, Transaction = T::BackendTransaction>,
|
||||||
Arc<C>: BlockImport<B, Transaction = TransactionFor<C, B>>,
|
<Arc<T::Client> as BlockImport<T::Block>>::Error: Into<Error>,
|
||||||
<Arc<C> as BlockImport<B>>::Error: Into<Error>,
|
|
||||||
C::Api: TendermintApi<B>,
|
|
||||||
{
|
{
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Transaction = TransactionFor<C, B>;
|
type Transaction = T::BackendTransaction;
|
||||||
|
|
||||||
// TODO: Is there a DoS where you send a block without justifications, causing it to error,
|
// TODO: Is there a DoS where you send a block without justifications, causing it to error,
|
||||||
// yet adding it to the blacklist in the process preventing further syncing?
|
// yet adding it to the blacklist in the process preventing further syncing?
|
||||||
async fn check_block(
|
async fn check_block(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut block: BlockCheckParams<B>,
|
mut block: BlockCheckParams<T::Block>,
|
||||||
) -> Result<ImportResult, Self::Error> {
|
) -> Result<ImportResult, Self::Error> {
|
||||||
self.verify_order(block.parent_hash, block.number)?;
|
self.verify_order(block.parent_hash, block.number)?;
|
||||||
|
|
||||||
|
@ -55,7 +35,7 @@ where
|
||||||
|
|
||||||
async fn import_block(
|
async fn import_block(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut block: BlockImportParams<B, TransactionFor<C, B>>,
|
mut block: BlockImportParams<T::Block, Self::Transaction>,
|
||||||
new_cache: HashMap<CacheKeyId, Vec<u8>>,
|
new_cache: HashMap<CacheKeyId, Vec<u8>>,
|
||||||
) -> Result<ImportResult, Self::Error> {
|
) -> Result<ImportResult, Self::Error> {
|
||||||
self.check(&mut block).await?;
|
self.check(&mut block).await?;
|
||||||
|
|
|
@ -8,15 +8,14 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use sp_core::Decode;
|
use sp_core::Decode;
|
||||||
use sp_inherents::CreateInherentDataProviders;
|
|
||||||
use sp_runtime::traits::{Header, Block};
|
use sp_runtime::traits::{Header, Block};
|
||||||
use sp_api::{BlockId, TransactionFor};
|
use sp_api::BlockId;
|
||||||
|
|
||||||
use sp_consensus::{Error, Environment};
|
use sp_consensus::Error;
|
||||||
use sc_consensus::{BlockImportStatus, BlockImportError, BlockImport, Link, BasicQueue};
|
use sc_consensus::{BlockImportStatus, BlockImportError, BlockImport, Link, BasicQueue};
|
||||||
|
|
||||||
use sc_service::ImportQueue;
|
use sc_service::ImportQueue;
|
||||||
use sc_client_api::Backend;
|
use sc_client_api::{HeaderBackend, BlockBackend};
|
||||||
|
|
||||||
use substrate_prometheus_endpoint::Registry;
|
use substrate_prometheus_endpoint::Registry;
|
||||||
|
|
||||||
|
@ -25,13 +24,9 @@ use tendermint_machine::{
|
||||||
TendermintMachine,
|
TendermintMachine,
|
||||||
};
|
};
|
||||||
|
|
||||||
use sp_tendermint::TendermintApi;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
CONSENSUS_ID,
|
CONSENSUS_ID, types::TendermintAuthor, validators::TendermintValidators,
|
||||||
validators::TendermintValidators,
|
tendermint::TendermintImport,
|
||||||
tendermint::{TendermintClient, TendermintImport},
|
|
||||||
Announce,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type TendermintImportQueue<Block, Transaction> = BasicQueue<Block, Transaction>;
|
pub type TendermintImportQueue<Block, Transaction> = BasicQueue<Block, Transaction>;
|
||||||
|
@ -82,28 +77,19 @@ impl<'a, B: Block, T: Send> Future for ImportFuture<'a, B, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn import_queue<
|
pub fn import_queue<T: TendermintAuthor>(
|
||||||
B: Block,
|
client: Arc<T::Client>,
|
||||||
Be: Backend<B> + 'static,
|
announce: T::Announce,
|
||||||
C: TendermintClient<B, Be>,
|
providers: Arc<T::CIDP>,
|
||||||
CIDP: CreateInherentDataProviders<B, ()> + 'static,
|
env: T::Environment,
|
||||||
E: Send + Sync + Environment<B> + 'static,
|
|
||||||
A: Announce<B>,
|
|
||||||
>(
|
|
||||||
client: Arc<C>,
|
|
||||||
announce: A,
|
|
||||||
providers: Arc<CIDP>,
|
|
||||||
env: E,
|
|
||||||
spawner: &impl sp_core::traits::SpawnEssentialNamed,
|
spawner: &impl sp_core::traits::SpawnEssentialNamed,
|
||||||
registry: Option<&Registry>,
|
registry: Option<&Registry>,
|
||||||
) -> (impl Future<Output = ()>, TendermintImportQueue<B, TransactionFor<C, B>>)
|
) -> (impl Future<Output = ()>, TendermintImportQueue<T::Block, T::BackendTransaction>)
|
||||||
where
|
where
|
||||||
TransactionFor<C, B>: Send + Sync + 'static,
|
Arc<T::Client>: BlockImport<T::Block, Transaction = T::BackendTransaction>,
|
||||||
Arc<C>: BlockImport<B, Transaction = TransactionFor<C, B>>,
|
<Arc<T::Client> as BlockImport<T::Block>>::Error: Into<Error>,
|
||||||
<Arc<C> as BlockImport<B>>::Error: Into<Error>,
|
|
||||||
C::Api: TendermintApi<B>,
|
|
||||||
{
|
{
|
||||||
let import = TendermintImport::new(client, announce, providers, env);
|
let import = TendermintImport::<T>::new(client, announce, providers, env);
|
||||||
|
|
||||||
let authority = {
|
let authority = {
|
||||||
let machine_clone = import.machine.clone();
|
let machine_clone = import.machine.clone();
|
||||||
|
@ -120,7 +106,7 @@ where
|
||||||
Ok(best) => BlockNumber(best + 1),
|
Ok(best) => BlockNumber(best + 1),
|
||||||
Err(_) => panic!("BlockNumber exceeded u64"),
|
Err(_) => panic!("BlockNumber exceeded u64"),
|
||||||
},
|
},
|
||||||
Commit::<TendermintValidators<B, Be, C>>::decode(
|
Commit::<TendermintValidators<T>>::decode(
|
||||||
&mut import_clone
|
&mut import_clone
|
||||||
.client
|
.client
|
||||||
.justifications(&BlockId::Number(best))
|
.justifications(&BlockId::Number(best))
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
use std::{sync::Arc, future::Future};
|
use std::{marker::PhantomData, boxed::Box, sync::Arc, future::Future, error::Error};
|
||||||
|
|
||||||
use sp_runtime::traits::Block as BlockTrait;
|
use sp_runtime::traits::Block as BlockTrait;
|
||||||
use sp_api::TransactionFor;
|
use sp_inherents::CreateInherentDataProviders;
|
||||||
|
use sp_consensus::DisableProofRecording;
|
||||||
|
use sp_api::{TransactionFor, ProvideRuntimeApi};
|
||||||
|
|
||||||
use sc_executor::{NativeVersion, NativeExecutionDispatch, NativeElseWasmExecutor};
|
use sc_executor::{NativeVersion, NativeExecutionDispatch, NativeElseWasmExecutor};
|
||||||
use sc_transaction_pool::FullPool;
|
use sc_transaction_pool::FullPool;
|
||||||
|
@ -11,6 +13,9 @@ use substrate_prometheus_endpoint::Registry;
|
||||||
|
|
||||||
use serai_runtime::{self, opaque::Block, RuntimeApi};
|
use serai_runtime::{self, opaque::Block, RuntimeApi};
|
||||||
|
|
||||||
|
mod types;
|
||||||
|
use types::{TendermintClientMinimal, TendermintAuthor};
|
||||||
|
|
||||||
mod validators;
|
mod validators;
|
||||||
|
|
||||||
mod tendermint;
|
mod tendermint;
|
||||||
|
@ -49,6 +54,39 @@ pub trait Announce<B: BlockTrait>: Send + Sync + Clone + 'static {
|
||||||
fn announce(&self, hash: B::Hash);
|
fn announce(&self, hash: B::Hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Cidp;
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl CreateInherentDataProviders<Block, ()> for Cidp {
|
||||||
|
type InherentDataProviders = (sp_timestamp::InherentDataProvider,);
|
||||||
|
async fn create_inherent_data_providers(
|
||||||
|
&self,
|
||||||
|
_: <Block as BlockTrait>::Hash,
|
||||||
|
_: (),
|
||||||
|
) -> Result<Self::InherentDataProviders, Box<dyn Send + Sync + Error>> {
|
||||||
|
Ok((sp_timestamp::InherentDataProvider::from_system_time(),))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TendermintAuthorFirm<A: Announce<Block>>(PhantomData<A>);
|
||||||
|
impl<A: Announce<Block>> TendermintClientMinimal for TendermintAuthorFirm<A> {
|
||||||
|
type Block = Block;
|
||||||
|
type Backend = sc_client_db::Backend<Block>;
|
||||||
|
type Api = <FullClient as ProvideRuntimeApi<Block>>::Api;
|
||||||
|
type Client = FullClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A: Announce<Block>> TendermintAuthor for TendermintAuthorFirm<A> {
|
||||||
|
type CIDP = Cidp;
|
||||||
|
type Environment = sc_basic_authorship::ProposerFactory<
|
||||||
|
FullPool<Block, FullClient>,
|
||||||
|
Self::Backend,
|
||||||
|
Self::Client,
|
||||||
|
DisableProofRecording,
|
||||||
|
>;
|
||||||
|
|
||||||
|
type Announce = A;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn import_queue<A: Announce<Block>>(
|
pub fn import_queue<A: Announce<Block>>(
|
||||||
task_manager: &TaskManager,
|
task_manager: &TaskManager,
|
||||||
client: Arc<FullClient>,
|
client: Arc<FullClient>,
|
||||||
|
@ -56,10 +94,10 @@ pub fn import_queue<A: Announce<Block>>(
|
||||||
pool: Arc<FullPool<Block, FullClient>>,
|
pool: Arc<FullPool<Block, FullClient>>,
|
||||||
registry: Option<&Registry>,
|
registry: Option<&Registry>,
|
||||||
) -> (impl Future<Output = ()>, TendermintImportQueue<Block, TransactionFor<FullClient, Block>>) {
|
) -> (impl Future<Output = ()>, TendermintImportQueue<Block, TransactionFor<FullClient, Block>>) {
|
||||||
import_queue::import_queue(
|
import_queue::import_queue::<TendermintAuthorFirm<A>>(
|
||||||
client.clone(),
|
client.clone(),
|
||||||
announce,
|
announce,
|
||||||
Arc::new(|_, _| async { Ok(sp_timestamp::InherentDataProvider::from_system_time()) }),
|
Arc::new(Cidp),
|
||||||
sc_basic_authorship::ProposerFactory::new(
|
sc_basic_authorship::ProposerFactory::new(
|
||||||
task_manager.spawn_handle(),
|
task_manager.spawn_handle(),
|
||||||
client,
|
client,
|
||||||
|
|
|
@ -17,103 +17,48 @@ use sp_runtime::{
|
||||||
Digest, Justification,
|
Digest, Justification,
|
||||||
};
|
};
|
||||||
use sp_blockchain::HeaderBackend;
|
use sp_blockchain::HeaderBackend;
|
||||||
use sp_api::{BlockId, TransactionFor, ProvideRuntimeApi};
|
use sp_api::BlockId;
|
||||||
|
|
||||||
use sp_consensus::{Error, BlockOrigin, Proposer, Environment};
|
use sp_consensus::{Error, BlockOrigin, Proposer, Environment};
|
||||||
use sc_consensus::{ForkChoiceStrategy, BlockImportParams, BlockImport, import_queue::IncomingBlock};
|
use sc_consensus::{ForkChoiceStrategy, BlockImportParams, import_queue::IncomingBlock};
|
||||||
|
|
||||||
use sc_service::ImportQueue;
|
use sc_service::ImportQueue;
|
||||||
use sc_client_api::{BlockBackend, Backend, Finalizer};
|
use sc_client_api::Finalizer;
|
||||||
|
|
||||||
use tendermint_machine::{
|
use tendermint_machine::{
|
||||||
ext::{BlockError, Commit, Network},
|
ext::{BlockError, Commit, Network},
|
||||||
SignedMessage, TendermintHandle,
|
SignedMessage, TendermintHandle,
|
||||||
};
|
};
|
||||||
|
|
||||||
use sp_tendermint::TendermintApi;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
CONSENSUS_ID,
|
CONSENSUS_ID,
|
||||||
|
types::TendermintAuthor,
|
||||||
validators::TendermintValidators,
|
validators::TendermintValidators,
|
||||||
import_queue::{ImportFuture, TendermintImportQueue},
|
import_queue::{ImportFuture, TendermintImportQueue},
|
||||||
Announce,
|
Announce,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait TendermintClient<B: Block, Be: Backend<B> + 'static>:
|
pub(crate) struct TendermintImport<T: TendermintAuthor> {
|
||||||
Send
|
_ta: PhantomData<T>,
|
||||||
+ Sync
|
|
||||||
+ HeaderBackend<B>
|
|
||||||
+ BlockBackend<B>
|
|
||||||
+ BlockImport<B, Transaction = TransactionFor<Self, B>>
|
|
||||||
+ Finalizer<B, Be>
|
|
||||||
+ ProvideRuntimeApi<B>
|
|
||||||
+ 'static
|
|
||||||
where
|
|
||||||
TransactionFor<Self, B>: Send + Sync + 'static,
|
|
||||||
Self::Api: TendermintApi<B>,
|
|
||||||
{
|
|
||||||
}
|
|
||||||
impl<
|
|
||||||
B: Send + Sync + Block + 'static,
|
|
||||||
Be: Send + Sync + Backend<B> + 'static,
|
|
||||||
C: Send
|
|
||||||
+ Sync
|
|
||||||
+ HeaderBackend<B>
|
|
||||||
+ BlockBackend<B>
|
|
||||||
+ BlockImport<B, Transaction = TransactionFor<C, B>>
|
|
||||||
+ Finalizer<B, Be>
|
|
||||||
+ ProvideRuntimeApi<B>
|
|
||||||
+ 'static,
|
|
||||||
> TendermintClient<B, Be> for C
|
|
||||||
where
|
|
||||||
TransactionFor<C, B>: Send + Sync + 'static,
|
|
||||||
C::Api: TendermintApi<B>,
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) struct TendermintImport<
|
validators: Arc<TendermintValidators<T>>,
|
||||||
B: Block,
|
|
||||||
Be: Backend<B> + 'static,
|
|
||||||
C: TendermintClient<B, Be>,
|
|
||||||
CIDP: CreateInherentDataProviders<B, ()> + 'static,
|
|
||||||
E: Send + Sync + Environment<B> + 'static,
|
|
||||||
A: Announce<B>,
|
|
||||||
> where
|
|
||||||
TransactionFor<C, B>: Send + Sync + 'static,
|
|
||||||
C::Api: TendermintApi<B>,
|
|
||||||
{
|
|
||||||
_block: PhantomData<B>,
|
|
||||||
_backend: PhantomData<Be>,
|
|
||||||
|
|
||||||
validators: Arc<TendermintValidators<B, Be, C>>,
|
importing_block: Arc<RwLock<Option<<T::Block as Block>::Hash>>>,
|
||||||
|
|
||||||
importing_block: Arc<RwLock<Option<B::Hash>>>,
|
|
||||||
pub(crate) machine: Arc<RwLock<Option<TendermintHandle<Self>>>>,
|
pub(crate) machine: Arc<RwLock<Option<TendermintHandle<Self>>>>,
|
||||||
|
|
||||||
pub(crate) client: Arc<C>,
|
pub(crate) client: Arc<T::Client>,
|
||||||
announce: A,
|
announce: T::Announce,
|
||||||
providers: Arc<CIDP>,
|
providers: Arc<T::CIDP>,
|
||||||
|
|
||||||
env: Arc<AsyncRwLock<E>>,
|
env: Arc<AsyncRwLock<T::Environment>>,
|
||||||
pub(crate) queue: Arc<AsyncRwLock<Option<TendermintImportQueue<B, TransactionFor<C, B>>>>>,
|
pub(crate) queue:
|
||||||
|
Arc<AsyncRwLock<Option<TendermintImportQueue<T::Block, T::BackendTransaction>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<T: TendermintAuthor> Clone for TendermintImport<T> {
|
||||||
B: Block,
|
|
||||||
Be: Backend<B> + 'static,
|
|
||||||
C: TendermintClient<B, Be>,
|
|
||||||
CIDP: CreateInherentDataProviders<B, ()> + 'static,
|
|
||||||
E: Send + Sync + Environment<B> + 'static,
|
|
||||||
A: Announce<B>,
|
|
||||||
> Clone for TendermintImport<B, Be, C, CIDP, E, A>
|
|
||||||
where
|
|
||||||
TransactionFor<C, B>: Send + Sync + 'static,
|
|
||||||
C::Api: TendermintApi<B>,
|
|
||||||
{
|
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
TendermintImport {
|
TendermintImport {
|
||||||
_block: PhantomData,
|
_ta: PhantomData,
|
||||||
_backend: PhantomData,
|
|
||||||
|
|
||||||
validators: self.validators.clone(),
|
validators: self.validators.clone(),
|
||||||
|
|
||||||
|
@ -130,27 +75,15 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<T: TendermintAuthor> TendermintImport<T> {
|
||||||
B: Block,
|
|
||||||
Be: Backend<B> + 'static,
|
|
||||||
C: TendermintClient<B, Be>,
|
|
||||||
CIDP: CreateInherentDataProviders<B, ()> + 'static,
|
|
||||||
E: Send + Sync + Environment<B> + 'static,
|
|
||||||
A: Announce<B>,
|
|
||||||
> TendermintImport<B, Be, C, CIDP, E, A>
|
|
||||||
where
|
|
||||||
TransactionFor<C, B>: Send + Sync + 'static,
|
|
||||||
C::Api: TendermintApi<B>,
|
|
||||||
{
|
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
client: Arc<C>,
|
client: Arc<T::Client>,
|
||||||
announce: A,
|
announce: T::Announce,
|
||||||
providers: Arc<CIDP>,
|
providers: Arc<T::CIDP>,
|
||||||
env: E,
|
env: T::Environment,
|
||||||
) -> TendermintImport<B, Be, C, CIDP, E, A> {
|
) -> TendermintImport<T> {
|
||||||
TendermintImport {
|
TendermintImport {
|
||||||
_block: PhantomData,
|
_ta: PhantomData,
|
||||||
_backend: PhantomData,
|
|
||||||
|
|
||||||
validators: Arc::new(TendermintValidators::new(client.clone())),
|
validators: Arc::new(TendermintValidators::new(client.clone())),
|
||||||
|
|
||||||
|
@ -168,8 +101,8 @@ where
|
||||||
|
|
||||||
async fn check_inherents(
|
async fn check_inherents(
|
||||||
&self,
|
&self,
|
||||||
block: B,
|
block: T::Block,
|
||||||
providers: CIDP::InherentDataProviders,
|
providers: <T::CIDP as CreateInherentDataProviders<T::Block, ()>>::InherentDataProviders,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
// TODO
|
// TODO
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -178,8 +111,8 @@ where
|
||||||
// Ensure this is part of a sequential import
|
// Ensure this is part of a sequential import
|
||||||
pub(crate) fn verify_order(
|
pub(crate) fn verify_order(
|
||||||
&self,
|
&self,
|
||||||
parent: B::Hash,
|
parent: <T::Block as Block>::Hash,
|
||||||
number: <B::Header as Header>::Number,
|
number: <<T::Block as Block>::Header as Header>::Number,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let info = self.client.info();
|
let info = self.client.info();
|
||||||
if (info.best_hash != parent) || ((info.best_number + 1u16.into()) != number) {
|
if (info.best_hash != parent) || ((info.best_number + 1u16.into()) != number) {
|
||||||
|
@ -193,7 +126,7 @@ where
|
||||||
// Tendermint's propose message could be rewritten as a seal OR Tendermint could produce blocks
|
// Tendermint's propose message could be rewritten as a seal OR Tendermint could produce blocks
|
||||||
// which this checks the proposer slot for, and then tells the Tendermint machine
|
// which this checks the proposer slot for, and then tells the Tendermint machine
|
||||||
// While those would be more seamless with Substrate, there's no actual benefit to doing so
|
// While those would be more seamless with Substrate, there's no actual benefit to doing so
|
||||||
fn verify_origin(&self, hash: B::Hash) -> Result<(), Error> {
|
fn verify_origin(&self, hash: <T::Block as Block>::Hash) -> Result<(), Error> {
|
||||||
if let Some(tm_hash) = *self.importing_block.read().unwrap() {
|
if let Some(tm_hash) = *self.importing_block.read().unwrap() {
|
||||||
if hash == tm_hash {
|
if hash == tm_hash {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
@ -205,14 +138,14 @@ where
|
||||||
// Errors if the justification isn't valid
|
// Errors if the justification isn't valid
|
||||||
pub(crate) fn verify_justification(
|
pub(crate) fn verify_justification(
|
||||||
&self,
|
&self,
|
||||||
hash: B::Hash,
|
hash: <T::Block as Block>::Hash,
|
||||||
justification: &Justification,
|
justification: &Justification,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
if justification.0 != CONSENSUS_ID {
|
if justification.0 != CONSENSUS_ID {
|
||||||
Err(Error::InvalidJustification)?;
|
Err(Error::InvalidJustification)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let commit: Commit<TendermintValidators<B, Be, C>> =
|
let commit: Commit<TendermintValidators<T>> =
|
||||||
Commit::decode(&mut justification.1.as_ref()).map_err(|_| Error::InvalidJustification)?;
|
Commit::decode(&mut justification.1.as_ref()).map_err(|_| Error::InvalidJustification)?;
|
||||||
if !self.verify_commit(hash, &commit) {
|
if !self.verify_commit(hash, &commit) {
|
||||||
Err(Error::InvalidJustification)?;
|
Err(Error::InvalidJustification)?;
|
||||||
|
@ -223,7 +156,10 @@ where
|
||||||
// Verifies the justifications aren't malformed, not that the block is justified
|
// Verifies the justifications aren't malformed, not that the block is justified
|
||||||
// Errors if justifications is neither empty nor a sinlge Tendermint justification
|
// Errors if justifications is neither empty nor a sinlge Tendermint justification
|
||||||
// If the block does have a justification, finalized will be set to true
|
// If the block does have a justification, finalized will be set to true
|
||||||
fn verify_justifications<T>(&self, block: &mut BlockImportParams<B, T>) -> Result<(), Error> {
|
fn verify_justifications<BT>(
|
||||||
|
&self,
|
||||||
|
block: &mut BlockImportParams<T::Block, BT>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
if !block.finalized {
|
if !block.finalized {
|
||||||
if let Some(justifications) = &block.justifications {
|
if let Some(justifications) = &block.justifications {
|
||||||
let mut iter = justifications.iter();
|
let mut iter = justifications.iter();
|
||||||
|
@ -238,7 +174,10 @@ where
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn check<T>(&self, block: &mut BlockImportParams<B, T>) -> Result<(), Error> {
|
pub(crate) async fn check<BT>(
|
||||||
|
&self,
|
||||||
|
block: &mut BlockImportParams<T::Block, BT>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
if block.finalized {
|
if block.finalized {
|
||||||
if block.fork_choice.is_none() {
|
if block.fork_choice.is_none() {
|
||||||
// Since we alw1ays set the fork choice, this means something else marked the block as
|
// Since we alw1ays set the fork choice, this means something else marked the block as
|
||||||
|
@ -261,7 +200,7 @@ where
|
||||||
if let Some(body) = block.body.clone() {
|
if let Some(body) = block.body.clone() {
|
||||||
self
|
self
|
||||||
.check_inherents(
|
.check_inherents(
|
||||||
B::new(block.header.clone(), body),
|
T::Block::new(block.header.clone(), body),
|
||||||
self.providers.create_inherent_data_providers(*block.header.parent_hash(), ()).await?,
|
self.providers.create_inherent_data_providers(*block.header.parent_hash(), ()).await?,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -281,7 +220,7 @@ where
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn get_proposal(&mut self, header: &B::Header) -> B {
|
pub(crate) async fn get_proposal(&mut self, header: &<T::Block as Block>::Header) -> T::Block {
|
||||||
let inherent_data =
|
let inherent_data =
|
||||||
match self.providers.create_inherent_data_providers(header.hash(), ()).await {
|
match self.providers.create_inherent_data_providers(header.hash(), ()).await {
|
||||||
Ok(providers) => match providers.create_inherent_data() {
|
Ok(providers) => match providers.create_inherent_data() {
|
||||||
|
@ -315,30 +254,19 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<
|
impl<T: TendermintAuthor> Network for TendermintImport<T> {
|
||||||
B: Block,
|
|
||||||
Be: Backend<B> + 'static,
|
|
||||||
C: TendermintClient<B, Be>,
|
|
||||||
CIDP: CreateInherentDataProviders<B, ()> + 'static,
|
|
||||||
E: Send + Sync + Environment<B> + 'static,
|
|
||||||
A: Announce<B>,
|
|
||||||
> Network for TendermintImport<B, Be, C, CIDP, E, A>
|
|
||||||
where
|
|
||||||
TransactionFor<C, B>: Send + Sync + 'static,
|
|
||||||
C::Api: TendermintApi<B>,
|
|
||||||
{
|
|
||||||
type ValidatorId = u16;
|
type ValidatorId = u16;
|
||||||
type SignatureScheme = TendermintValidators<B, Be, C>;
|
type SignatureScheme = TendermintValidators<T>;
|
||||||
type Weights = TendermintValidators<B, Be, C>;
|
type Weights = TendermintValidators<T>;
|
||||||
type Block = B;
|
type Block = T::Block;
|
||||||
|
|
||||||
const BLOCK_TIME: u32 = { (serai_runtime::MILLISECS_PER_BLOCK / 1000) as u32 };
|
const BLOCK_TIME: u32 = { (serai_runtime::MILLISECS_PER_BLOCK / 1000) as u32 };
|
||||||
|
|
||||||
fn signature_scheme(&self) -> Arc<TendermintValidators<B, Be, C>> {
|
fn signature_scheme(&self) -> Arc<TendermintValidators<T>> {
|
||||||
self.validators.clone()
|
self.validators.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn weights(&self) -> Arc<TendermintValidators<B, Be, C>> {
|
fn weights(&self) -> Arc<TendermintValidators<T>> {
|
||||||
self.validators.clone()
|
self.validators.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,7 +290,7 @@ where
|
||||||
// the node.
|
// the node.
|
||||||
//
|
//
|
||||||
// When Tendermint completes, the block is finalized, setting it as the tip regardless of work.
|
// When Tendermint completes, the block is finalized, setting it as the tip regardless of work.
|
||||||
async fn validate(&mut self, block: &B) -> Result<(), BlockError> {
|
async fn validate(&mut self, block: &T::Block) -> Result<(), BlockError> {
|
||||||
let hash = block.hash();
|
let hash = block.hash();
|
||||||
let (header, body) = block.clone().deconstruct();
|
let (header, body) = block.clone().deconstruct();
|
||||||
let parent = *header.parent_hash();
|
let parent = *header.parent_hash();
|
||||||
|
@ -407,7 +335,11 @@ where
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn add_block(&mut self, block: B, commit: Commit<TendermintValidators<B, Be, C>>) -> B {
|
async fn add_block(
|
||||||
|
&mut self,
|
||||||
|
block: T::Block,
|
||||||
|
commit: Commit<TendermintValidators<T>>,
|
||||||
|
) -> T::Block {
|
||||||
let hash = block.hash();
|
let hash = block.hash();
|
||||||
let justification = (CONSENSUS_ID, commit.encode());
|
let justification = (CONSENSUS_ID, commit.encode());
|
||||||
debug_assert!(self.verify_justification(hash, &justification).is_ok());
|
debug_assert!(self.verify_justification(hash, &justification).is_ok());
|
||||||
|
|
75
substrate/tendermint/client/src/types.rs
Normal file
75
substrate/tendermint/client/src/types.rs
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
use sp_inherents::CreateInherentDataProviders;
|
||||||
|
use sp_runtime::traits::{Header, Block};
|
||||||
|
|
||||||
|
use sp_blockchain::HeaderBackend;
|
||||||
|
use sp_api::{StateBackend, StateBackendFor, TransactionFor, ApiExt, ProvideRuntimeApi};
|
||||||
|
|
||||||
|
use sp_consensus::Environment;
|
||||||
|
use sc_consensus::BlockImport;
|
||||||
|
|
||||||
|
use sc_client_api::{BlockBackend, Backend, Finalizer};
|
||||||
|
|
||||||
|
use sp_tendermint::TendermintApi;
|
||||||
|
|
||||||
|
use crate::Announce;
|
||||||
|
|
||||||
|
/// Trait consolidating all generics required by sc_tendermint for processing.
|
||||||
|
pub trait TendermintClient: Send + Sync + 'static {
|
||||||
|
type Block: Block;
|
||||||
|
type Backend: Backend<Self::Block> + 'static;
|
||||||
|
|
||||||
|
/// TransactionFor<Client, Block>
|
||||||
|
type BackendTransaction: Send + Sync + 'static;
|
||||||
|
/// StateBackendFor<Client, Block>
|
||||||
|
type StateBackend: StateBackend<
|
||||||
|
<<Self::Block as Block>::Header as Header>::Hashing,
|
||||||
|
Transaction = Self::BackendTransaction,
|
||||||
|
>;
|
||||||
|
// Client::Api
|
||||||
|
type Api: ApiExt<Self::Block, StateBackend = Self::StateBackend> + TendermintApi<Self::Block>;
|
||||||
|
type Client: Send
|
||||||
|
+ Sync
|
||||||
|
+ HeaderBackend<Self::Block>
|
||||||
|
+ BlockBackend<Self::Block>
|
||||||
|
+ BlockImport<Self::Block, Transaction = Self::BackendTransaction>
|
||||||
|
+ Finalizer<Self::Block, Self::Backend>
|
||||||
|
+ ProvideRuntimeApi<Self::Block, Api = Self::Api>
|
||||||
|
+ 'static;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Trait implementable on firm types to automatically provide a full TendermintClient impl.
|
||||||
|
pub trait TendermintClientMinimal: Send + Sync + 'static {
|
||||||
|
type Block: Block;
|
||||||
|
type Backend: Backend<Self::Block> + 'static;
|
||||||
|
type Api: ApiExt<Self::Block> + TendermintApi<Self::Block>;
|
||||||
|
type Client: Send
|
||||||
|
+ Sync
|
||||||
|
+ HeaderBackend<Self::Block>
|
||||||
|
+ BlockBackend<Self::Block>
|
||||||
|
+ BlockImport<Self::Block, Transaction = TransactionFor<Self::Client, Self::Block>>
|
||||||
|
+ Finalizer<Self::Block, Self::Backend>
|
||||||
|
+ ProvideRuntimeApi<Self::Block, Api = Self::Api>
|
||||||
|
+ 'static;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: TendermintClientMinimal> TendermintClient for T
|
||||||
|
where
|
||||||
|
<T::Client as ProvideRuntimeApi<T::Block>>::Api: TendermintApi<T::Block>,
|
||||||
|
TransactionFor<T::Client, T::Block>: Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
type Block = T::Block;
|
||||||
|
type Backend = T::Backend;
|
||||||
|
|
||||||
|
type BackendTransaction = TransactionFor<T::Client, T::Block>;
|
||||||
|
type StateBackend = StateBackendFor<T::Client, T::Block>;
|
||||||
|
type Api = <T::Client as ProvideRuntimeApi<T::Block>>::Api;
|
||||||
|
type Client = T::Client;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Trait consolidating additional generics required by sc_tendermint for authoring.
|
||||||
|
pub trait TendermintAuthor: TendermintClient {
|
||||||
|
type CIDP: CreateInherentDataProviders<Self::Block, ()> + 'static;
|
||||||
|
type Environment: Send + Sync + Environment<Self::Block> + 'static;
|
||||||
|
|
||||||
|
type Announce: Announce<Self::Block>;
|
||||||
|
}
|
|
@ -6,17 +6,16 @@ use sp_application_crypto::{
|
||||||
sr25519::{Public, Pair, Signature},
|
sr25519::{Public, Pair, Signature},
|
||||||
};
|
};
|
||||||
|
|
||||||
use sp_runtime::traits::Block;
|
|
||||||
use sp_staking::SessionIndex;
|
use sp_staking::SessionIndex;
|
||||||
use sp_api::{BlockId, TransactionFor};
|
use sp_api::{BlockId, ProvideRuntimeApi};
|
||||||
|
|
||||||
use sc_client_api::Backend;
|
use sc_client_api::HeaderBackend;
|
||||||
|
|
||||||
use tendermint_machine::ext::{BlockNumber, Round, Weights, SignatureScheme};
|
use tendermint_machine::ext::{BlockNumber, Round, Weights, SignatureScheme};
|
||||||
|
|
||||||
use sp_tendermint::TendermintApi;
|
use sp_tendermint::TendermintApi;
|
||||||
|
|
||||||
use crate::tendermint::TendermintClient;
|
use crate::types::TendermintClient;
|
||||||
|
|
||||||
struct TendermintValidatorsStruct {
|
struct TendermintValidatorsStruct {
|
||||||
session: SessionIndex,
|
session: SessionIndex,
|
||||||
|
@ -29,13 +28,7 @@ struct TendermintValidatorsStruct {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TendermintValidatorsStruct {
|
impl TendermintValidatorsStruct {
|
||||||
fn from_module<B: Block, Be: Backend<B> + 'static, C: TendermintClient<B, Be>>(
|
fn from_module<T: TendermintClient>(client: &Arc<T::Client>) -> TendermintValidatorsStruct {
|
||||||
client: &Arc<C>,
|
|
||||||
) -> TendermintValidatorsStruct
|
|
||||||
where
|
|
||||||
TransactionFor<C, B>: Send + Sync + 'static,
|
|
||||||
C::Api: TendermintApi<B>,
|
|
||||||
{
|
|
||||||
let last = client.info().best_hash;
|
let last = client.info().best_hash;
|
||||||
let api = client.runtime_api();
|
let api = client.runtime_api();
|
||||||
let session = api.current_session(&BlockId::Hash(last)).unwrap();
|
let session = api.current_session(&BlockId::Hash(last)).unwrap();
|
||||||
|
@ -56,23 +49,13 @@ impl TendermintValidatorsStruct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrap every access of the validators struct in something which forces calling refresh
|
// Wrap every access of the validators struct in something which forces calling refresh
|
||||||
struct Refresh<B: Block, Be: Backend<B> + 'static, C: TendermintClient<B, Be>>
|
struct Refresh<T: TendermintClient> {
|
||||||
where
|
_tc: PhantomData<T>,
|
||||||
TransactionFor<C, B>: Send + Sync + 'static,
|
client: Arc<T::Client>,
|
||||||
C::Api: TendermintApi<B>,
|
|
||||||
{
|
|
||||||
_block: PhantomData<B>,
|
|
||||||
_backend: PhantomData<Be>,
|
|
||||||
|
|
||||||
client: Arc<C>,
|
|
||||||
_refresh: Arc<RwLock<TendermintValidatorsStruct>>,
|
_refresh: Arc<RwLock<TendermintValidatorsStruct>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B: Block, Be: Backend<B> + 'static, C: TendermintClient<B, Be>> Refresh<B, Be, C>
|
impl<T: TendermintClient> Refresh<T> {
|
||||||
where
|
|
||||||
TransactionFor<C, B>: Send + Sync + 'static,
|
|
||||||
C::Api: TendermintApi<B>,
|
|
||||||
{
|
|
||||||
// If the session has changed, re-create the struct with the data on it
|
// If the session has changed, re-create the struct with the data on it
|
||||||
fn refresh(&self) {
|
fn refresh(&self) {
|
||||||
let session = self._refresh.read().unwrap().session;
|
let session = self._refresh.read().unwrap().session;
|
||||||
|
@ -83,16 +66,12 @@ where
|
||||||
.current_session(&BlockId::Hash(self.client.info().best_hash))
|
.current_session(&BlockId::Hash(self.client.info().best_hash))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
{
|
{
|
||||||
*self._refresh.write().unwrap() = TendermintValidatorsStruct::from_module(&self.client);
|
*self._refresh.write().unwrap() = TendermintValidatorsStruct::from_module::<T>(&self.client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B: Block, Be: Backend<B> + 'static, C: TendermintClient<B, Be>> Deref for Refresh<B, Be, C>
|
impl<T: TendermintClient> Deref for Refresh<T> {
|
||||||
where
|
|
||||||
TransactionFor<C, B>: Send + Sync + 'static,
|
|
||||||
C::Api: TendermintApi<B>,
|
|
||||||
{
|
|
||||||
type Target = RwLock<TendermintValidatorsStruct>;
|
type Target = RwLock<TendermintValidatorsStruct>;
|
||||||
fn deref(&self) -> &RwLock<TendermintValidatorsStruct> {
|
fn deref(&self) -> &RwLock<TendermintValidatorsStruct> {
|
||||||
self.refresh();
|
self.refresh();
|
||||||
|
@ -100,37 +79,19 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct TendermintValidators<
|
pub(crate) struct TendermintValidators<T: TendermintClient>(Refresh<T>);
|
||||||
B: Block,
|
|
||||||
Be: Backend<B> + 'static,
|
|
||||||
C: TendermintClient<B, Be>,
|
|
||||||
>(Refresh<B, Be, C>)
|
|
||||||
where
|
|
||||||
TransactionFor<C, B>: Send + Sync + 'static,
|
|
||||||
C::Api: TendermintApi<B>;
|
|
||||||
|
|
||||||
impl<B: Block, Be: Backend<B> + 'static, C: TendermintClient<B, Be>> TendermintValidators<B, Be, C>
|
impl<T: TendermintClient> TendermintValidators<T> {
|
||||||
where
|
pub(crate) fn new(client: Arc<T::Client>) -> TendermintValidators<T> {
|
||||||
TransactionFor<C, B>: Send + Sync + 'static,
|
|
||||||
C::Api: TendermintApi<B>,
|
|
||||||
{
|
|
||||||
pub(crate) fn new(client: Arc<C>) -> TendermintValidators<B, Be, C> {
|
|
||||||
TendermintValidators(Refresh {
|
TendermintValidators(Refresh {
|
||||||
_block: PhantomData,
|
_tc: PhantomData,
|
||||||
_backend: PhantomData,
|
_refresh: Arc::new(RwLock::new(TendermintValidatorsStruct::from_module::<T>(&client))),
|
||||||
|
|
||||||
_refresh: Arc::new(RwLock::new(TendermintValidatorsStruct::from_module(&client))),
|
|
||||||
client,
|
client,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B: Block, Be: Backend<B> + 'static, C: TendermintClient<B, Be>> SignatureScheme
|
impl<T: TendermintClient> SignatureScheme for TendermintValidators<T> {
|
||||||
for TendermintValidators<B, Be, C>
|
|
||||||
where
|
|
||||||
TransactionFor<C, B>: Send + Sync + 'static,
|
|
||||||
C::Api: TendermintApi<B>,
|
|
||||||
{
|
|
||||||
type ValidatorId = u16;
|
type ValidatorId = u16;
|
||||||
type Signature = Signature;
|
type Signature = Signature;
|
||||||
type AggregateSignature = Vec<Signature>;
|
type AggregateSignature = Vec<Signature>;
|
||||||
|
@ -160,12 +121,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B: Block, Be: Backend<B> + 'static, C: TendermintClient<B, Be>> Weights
|
impl<T: TendermintClient> Weights for TendermintValidators<T> {
|
||||||
for TendermintValidators<B, Be, C>
|
|
||||||
where
|
|
||||||
TransactionFor<C, B>: Send + Sync + 'static,
|
|
||||||
C::Api: TendermintApi<B>,
|
|
||||||
{
|
|
||||||
type ValidatorId = u16;
|
type ValidatorId = u16;
|
||||||
|
|
||||||
fn total_weight(&self) -> u64 {
|
fn total_weight(&self) -> u64 {
|
||||||
|
|
|
@ -2,41 +2,21 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
use sp_inherents::CreateInherentDataProviders;
|
use sp_consensus::{Error, CacheKeyId};
|
||||||
use sp_runtime::traits::Block;
|
|
||||||
use sp_api::TransactionFor;
|
|
||||||
|
|
||||||
use sp_consensus::{Error, CacheKeyId, Environment};
|
|
||||||
use sc_consensus::{BlockImportParams, BlockImport, Verifier};
|
use sc_consensus::{BlockImportParams, BlockImport, Verifier};
|
||||||
|
|
||||||
use sc_client_api::Backend;
|
use crate::{types::TendermintAuthor, tendermint::TendermintImport};
|
||||||
|
|
||||||
use sp_tendermint::TendermintApi;
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
tendermint::{TendermintClient, TendermintImport},
|
|
||||||
Announce,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<
|
impl<T: TendermintAuthor> Verifier<T::Block> for TendermintImport<T>
|
||||||
B: Block,
|
|
||||||
Be: Backend<B> + 'static,
|
|
||||||
C: TendermintClient<B, Be>,
|
|
||||||
CIDP: CreateInherentDataProviders<B, ()> + 'static,
|
|
||||||
E: Send + Sync + Environment<B> + 'static,
|
|
||||||
A: Announce<B>,
|
|
||||||
> Verifier<B> for TendermintImport<B, Be, C, CIDP, E, A>
|
|
||||||
where
|
where
|
||||||
TransactionFor<C, B>: Send + Sync + 'static,
|
Arc<T::Client>: BlockImport<T::Block, Transaction = T::BackendTransaction>,
|
||||||
Arc<C>: BlockImport<B, Transaction = TransactionFor<C, B>>,
|
<Arc<T::Client> as BlockImport<T::Block>>::Error: Into<Error>,
|
||||||
<Arc<C> as BlockImport<B>>::Error: Into<Error>,
|
|
||||||
C::Api: TendermintApi<B>,
|
|
||||||
{
|
{
|
||||||
async fn verify(
|
async fn verify(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut block: BlockImportParams<B, ()>,
|
mut block: BlockImportParams<T::Block, ()>,
|
||||||
) -> Result<(BlockImportParams<B, ()>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
|
) -> Result<(BlockImportParams<T::Block, ()>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
|
||||||
self.check(&mut block).await.map_err(|e| format!("{}", e))?;
|
self.check(&mut block).await.map_err(|e| format!("{}", e))?;
|
||||||
Ok((block, None))
|
Ok((block, None))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue