use crate::authority::AuthorityHash;
use crate::errors::RuntimeError;
use crate::manifest::DensorManifest;
use crate::receipt::RuntimeReceiptV1;
use crate::stage::{RuntimeStage, StageReceipt, StageReceiptSummary};
pub struct Runtime<'m> {
manifest: &'m DensorManifest,
stages: Vec<StageReceiptSummary>,
}
impl<'m> Runtime<'m> {
pub fn start(manifest: &'m DensorManifest) -> Result<Self, RuntimeError> {
manifest.validate()?;
Ok(Runtime {
manifest,
stages: Vec::new(),
})
}
fn gate(&self, stage_id: &str, authorities: &[AuthorityHash]) -> Result<(), RuntimeError> {
if authorities.is_empty() {
return Err(RuntimeError::MissingAuthority {
stage: stage_id.to_string(),
});
}
for a in authorities {
if !self.manifest.permits_authority(a) {
return Err(RuntimeError::AuthorityMismatch {
stage: stage_id.to_string(),
authority: a.name.clone(),
});
}
}
Ok(())
}
pub fn run_stage<I, O, S: RuntimeStage<I, O>>(
&mut self,
stage: &S,
input: I,
) -> Result<O, RuntimeError> {
self.gate(stage.stage_id(), stage.authority_hashes())?;
let receipt: StageReceipt<O> = stage.execute(input)?;
self.gate(&receipt.stage_id, &receipt.authority_hashes)?;
self.stages.push(receipt.summary());
Ok(receipt.output)
}
pub fn seal(self) -> RuntimeReceiptV1 {
RuntimeReceiptV1::build(self.manifest, self.stages)
}
}