use std::sync::MutexGuard;
use super::Error;
use crate::backend::{SharedCommittable, Store, ChainQuery, Operation, ImportOperation};
use crate::{Block, BlockExecutor, AsExternalities, Auxiliary};
pub struct ImportAction<'a, 'executor, E: BlockExecutor, Ba> where
Ba: Store<Block=E::Block> + ?Sized,
Ba::Auxiliary: Auxiliary<E::Block>
{
executor: &'executor E,
backend: &'a Ba,
pending: Operation<E::Block, Ba::State, Ba::Auxiliary>,
_guard: MutexGuard<'a, ()>,
}
impl<'a, 'executor, E: BlockExecutor, Ba> From<ImportAction<'a, 'executor, E, Ba>> for
Operation<E::Block, Ba::State, Ba::Auxiliary> where
Ba: Store<Block=E::Block> + ?Sized,
Ba::Auxiliary: Auxiliary<E::Block>,
{
fn from(
action: ImportAction<'a, 'executor, E, Ba>
) -> Operation<E::Block, Ba::State, Ba::Auxiliary> {
action.pending
}
}
impl<'a, 'executor, E: BlockExecutor, Ba> ImportAction<'a, 'executor, E, Ba> where
Ba: Store<Block=E::Block> + ChainQuery + ?Sized,
Ba::Auxiliary: Auxiliary<E::Block>,
Ba::State: AsExternalities<E::Externalities>,
Ba: SharedCommittable<Operation=Operation<E::Block, <Ba as Store>::State, <Ba as Store>::Auxiliary>>,
Error: From<E::Error> + From<Ba::Error>,
{
pub fn new(executor: &'executor E, backend: &'a Ba, import_guard: MutexGuard<'a, ()>) -> Self {
Self {
executor, backend,
pending: Default::default(),
_guard: import_guard
}
}
pub fn backend(&self) -> &'a Ba {
self.backend
}
pub fn execute_block(
&self, block: Ba::Block
) -> Result<ImportOperation<E::Block, Ba::State>, Error> {
let mut state = self.backend().state_at(
&block.parent_id().ok_or(Error::IsGenesis)?
)?;
self.executor.execute_block(&block, state.as_externalities())?;
Ok(ImportOperation { block, state })
}
pub fn import_block(&mut self, block: E::Block) -> Result<(), Error> {
let operation = self.execute_block(block)?;
self.import_raw(operation);
Ok(())
}
pub fn import_raw(&mut self, operation: ImportOperation<E::Block, Ba::State>) {
self.pending.import_block.push(operation);
}
pub fn set_head(&mut self, head: <E::Block as Block>::Identifier) {
self.pending.set_head = Some(head);
}
pub fn insert_auxiliary(&mut self, aux: Ba::Auxiliary) {
self.pending.insert_auxiliaries.push(aux);
}
pub fn remove_auxiliary(&mut self, aux_key: <Ba::Auxiliary as Auxiliary<E::Block>>::Key) {
self.pending.remove_auxiliaries.push(aux_key);
}
pub fn commit(self) -> Result<(), Error> {
Ok(self.backend.commit(self.into())?)
}
}