2022-10-21 02:17:40 -04:00
|
|
|
use std::{
|
2022-10-22 01:43:07 -04:00
|
|
|
pin::Pin,
|
2022-10-21 02:17:40 -04:00
|
|
|
sync::{Arc, RwLock},
|
2022-10-22 03:41:49 -04:00
|
|
|
task::{Poll, /* Wake, Waker, */ Context},
|
2022-10-22 01:43:07 -04:00
|
|
|
future::Future,
|
2022-10-22 03:41:49 -04:00
|
|
|
time::SystemTime,
|
2022-10-21 02:17:40 -04:00
|
|
|
};
|
|
|
|
|
|
2022-10-22 02:15:22 -04:00
|
|
|
use sp_inherents::CreateInherentDataProviders;
|
|
|
|
|
use sp_runtime::traits::{Header, Block};
|
2022-10-20 03:50:06 -04:00
|
|
|
use sp_blockchain::HeaderBackend;
|
2022-10-22 03:41:49 -04:00
|
|
|
use sp_api::{BlockId, TransactionFor, ProvideRuntimeApi};
|
2022-10-20 03:50:06 -04:00
|
|
|
|
2022-10-22 02:15:22 -04:00
|
|
|
use sp_consensus::{Error, Environment};
|
|
|
|
|
use sc_consensus::{BlockImport, BlockImportStatus, BlockImportError, Link, BasicQueue};
|
2022-10-21 02:17:40 -04:00
|
|
|
|
2022-10-22 00:48:09 -04:00
|
|
|
use sc_service::ImportQueue;
|
2022-10-21 02:17:40 -04:00
|
|
|
use sc_client_api::{Backend, Finalizer};
|
|
|
|
|
|
|
|
|
|
use substrate_prometheus_endpoint::Registry;
|
|
|
|
|
|
2022-10-22 03:41:49 -04:00
|
|
|
use tendermint_machine::{ext::BlockNumber, TendermintMachine};
|
|
|
|
|
|
2022-10-22 02:15:22 -04:00
|
|
|
use crate::tendermint::TendermintImport;
|
2022-10-20 03:50:06 -04:00
|
|
|
|
2022-10-22 00:48:09 -04:00
|
|
|
pub type TendermintImportQueue<Block, Transaction> = BasicQueue<Block, Transaction>;
|
|
|
|
|
|
2022-10-22 01:43:07 -04:00
|
|
|
// Custom helpers for ImportQueue in order to obtain the result of a block's importing
|
|
|
|
|
struct ValidateLink<B: Block>(Option<(B::Hash, bool)>);
|
|
|
|
|
impl<B: Block> Link<B> for ValidateLink<B> {
|
|
|
|
|
fn blocks_processed(
|
|
|
|
|
&mut self,
|
|
|
|
|
imported: usize,
|
|
|
|
|
count: usize,
|
|
|
|
|
results: Vec<(
|
|
|
|
|
Result<BlockImportStatus<<B::Header as Header>::Number>, BlockImportError>,
|
|
|
|
|
B::Hash,
|
|
|
|
|
)>,
|
|
|
|
|
) {
|
|
|
|
|
assert_eq!(imported, 1);
|
|
|
|
|
assert_eq!(count, 1);
|
|
|
|
|
self.0 = Some((results[0].1, results[0].0.is_ok()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-22 02:15:22 -04:00
|
|
|
pub(crate) struct ImportFuture<'a, B: Block, T: Send>(
|
|
|
|
|
B::Hash,
|
|
|
|
|
RwLock<&'a mut TendermintImportQueue<B, T>>,
|
|
|
|
|
);
|
2022-10-22 01:43:07 -04:00
|
|
|
impl<'a, B: Block, T: Send> ImportFuture<'a, B, T> {
|
2022-10-22 02:15:22 -04:00
|
|
|
pub(crate) fn new(
|
|
|
|
|
hash: B::Hash,
|
|
|
|
|
queue: &'a mut TendermintImportQueue<B, T>,
|
|
|
|
|
) -> ImportFuture<B, T> {
|
2022-10-22 01:43:07 -04:00
|
|
|
ImportFuture(hash, RwLock::new(queue))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'a, B: Block, T: Send> Future for ImportFuture<'a, B, T> {
|
|
|
|
|
type Output = bool;
|
|
|
|
|
|
|
|
|
|
fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> {
|
|
|
|
|
let mut link = ValidateLink(None);
|
|
|
|
|
self.1.write().unwrap().poll_actions(ctx, &mut link);
|
|
|
|
|
if let Some(res) = link.0 {
|
|
|
|
|
assert_eq!(res.0, self.0);
|
|
|
|
|
Poll::Ready(res.1)
|
|
|
|
|
} else {
|
|
|
|
|
Poll::Pending
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-21 02:18:51 -04:00
|
|
|
pub fn import_queue<
|
|
|
|
|
B: Block,
|
|
|
|
|
Be: Backend<B> + 'static,
|
|
|
|
|
C: Send + Sync + HeaderBackend<B> + Finalizer<B, Be> + ProvideRuntimeApi<B> + 'static,
|
|
|
|
|
I: Send + Sync + BlockImport<B, Transaction = TransactionFor<C, B>> + 'static,
|
|
|
|
|
CIDP: CreateInherentDataProviders<B, ()> + 'static,
|
2022-10-21 23:36:24 -04:00
|
|
|
E: Send + Sync + Environment<B> + 'static,
|
2022-10-21 02:18:51 -04:00
|
|
|
>(
|
|
|
|
|
client: Arc<C>,
|
|
|
|
|
inner: I,
|
|
|
|
|
providers: Arc<CIDP>,
|
2022-10-21 23:36:24 -04:00
|
|
|
env: E,
|
2022-10-21 02:18:51 -04:00
|
|
|
spawner: &impl sp_core::traits::SpawnEssentialNamed,
|
|
|
|
|
registry: Option<&Registry>,
|
2022-10-22 03:41:49 -04:00
|
|
|
) -> (impl Future<Output = ()>, TendermintImportQueue<B, TransactionFor<C, B>>)
|
2022-10-21 02:18:51 -04:00
|
|
|
where
|
|
|
|
|
I::Error: Into<Error>,
|
2022-10-22 00:48:09 -04:00
|
|
|
TransactionFor<C, B>: Send + Sync + 'static,
|
2022-10-21 02:18:51 -04:00
|
|
|
{
|
2022-10-22 02:15:22 -04:00
|
|
|
let import = TendermintImport::new(client, inner, providers, env);
|
2022-10-22 03:41:49 -04:00
|
|
|
|
|
|
|
|
let authority = {
|
|
|
|
|
let machine_clone = import.machine.clone();
|
|
|
|
|
let mut import_clone = import.clone();
|
|
|
|
|
async move {
|
|
|
|
|
*machine_clone.write().unwrap() = Some(TendermintMachine::new(
|
|
|
|
|
import_clone.clone(),
|
|
|
|
|
// TODO
|
|
|
|
|
0,
|
|
|
|
|
(BlockNumber(1), SystemTime::now()),
|
|
|
|
|
import_clone
|
|
|
|
|
.get_proposal(&import_clone.client.header(BlockId::Number(0u8.into())).unwrap().unwrap())
|
|
|
|
|
.await,
|
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2022-10-21 02:18:51 -04:00
|
|
|
let boxed = Box::new(import.clone());
|
2022-10-22 06:24:39 -04:00
|
|
|
// Use None for the justification importer since justifications always come with blocks
|
|
|
|
|
// Therefore, they're never imported after the fact, mandating a importer
|
|
|
|
|
let queue = || BasicQueue::new(import.clone(), boxed.clone(), None, spawner, registry);
|
2022-10-21 02:18:51 -04:00
|
|
|
|
2022-10-22 03:41:49 -04:00
|
|
|
*futures::executor::block_on(import.queue.write()) = Some(queue());
|
|
|
|
|
(authority, queue())
|
2022-10-21 02:18:51 -04:00
|
|
|
}
|