use blocks::{Block, BlockPointer};
use crypto::SignRing;
use recipe::BlockRecipe;
use storage::{StorageEngine, BlockStorage};
mod errors {
error_chain! {
links {
Blocks(::blocks::Error, ::blocks::ErrorKind);
Storage(::storage::Error, ::storage::ErrorKind);
}
}
}
pub use self::errors::{Result, Error, ErrorKind};
pub struct Engine {
storage: StorageEngine,
ring: SignRing,
head: BlockPointer,
}
impl Engine {
pub fn start(storage: StorageEngine, ring: SignRing) -> Result<Engine> {
let head = match storage.get_head() {
Ok(pointer) => {
pointer
},
Err(_) => {
BlockPointer::from_slice(&[
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
]).unwrap()
},
};
let mut engine = Engine {
storage,
ring,
head,
};
engine.init()?;
Ok(engine)
}
pub fn init(&mut self) -> Result<Block> {
let block = Block::init(self.head.clone(), &mut self.ring)?;
self.head = self.storage.push(&block)?;
Ok(block)
}
pub fn rekey(&mut self) -> Result<Block> {
let block = Block::rekey(self.head.clone(), &mut self.ring)?;
self.head = self.storage.push(&block)?;
Ok(block)
}
pub fn alert(&mut self, bytes: Vec<u8>) -> Result<Block> {
let block = Block::alert(self.head.clone(), &mut self.ring, bytes)?;
self.head = self.storage.push(&block)?;
Ok(block)
}
pub fn info(&mut self, bytes: Vec<u8>) -> Result<Block> {
let block = Block::info(self.head.clone(), &mut self.ring, bytes)?;
self.head = self.storage.push(&block)?;
Ok(block)
}
pub fn recipe(&mut self, recipe: BlockRecipe) -> Result<BlockPointer> {
let block = match recipe {
BlockRecipe::Rekey => {
self.rekey()?
},
BlockRecipe::Info(info) => {
self.info(info)?;
self.rekey()?
},
};
Ok(block.sha3())
}
pub fn storage(&self) -> &StorageEngine {
&self.storage
}
}