use std::sync::Arc;
use anyhow::Result;
use async_trait::async_trait;
use tokio::sync::mpsc;
use crate::{
core::{
app,
common::version,
config::Config,
consensus::{roothash, verifier::TrustRoot},
dispatcher::{PostInitState, PreInitState},
start_runtime,
},
crypto,
types::transaction,
};
mod client;
mod env;
mod notifier;
pub mod prelude;
mod processor;
mod registration;
pub use crate::modules::rofl::app_id::AppId;
pub use client::Client;
pub use env::Environment;
#[allow(unused_variables)]
#[async_trait]
pub trait App: Send + Sync + 'static {
const VERSION: version::Version;
fn id() -> AppId;
fn consensus_trust_root() -> Option<TrustRoot>;
fn new_transaction<B>(&self, method: &str, body: B) -> transaction::Transaction
where
B: cbor::Encode,
{
let mut tx = transaction::Transaction::new(method, body);
tx.set_fee_proxy("rofl", Self::id().as_ref());
tx
}
async fn run(self: Arc<Self>, env: Environment<Self>)
where
Self: Sized,
{
}
async fn on_runtime_block(self: Arc<Self>, env: Environment<Self>, round: u64)
where
Self: Sized,
{
}
fn start(self)
where
Self: Sized,
{
start_runtime(
Box::new(|state: PreInitState<'_>| -> PostInitState {
let hi = state.protocol.get_host_info();
crypto::signature::context::set_chain_context(
hi.runtime_id,
&hi.consensus_chain_context,
);
PostInitState {
app: Some(Box::new(AppWrapper::new(self, &state))),
..Default::default()
}
}),
Config {
version: Self::VERSION,
trust_root: Self::consensus_trust_root(),
..Default::default()
},
);
}
}
struct AppWrapper {
cmdq: mpsc::Sender<processor::Command>,
}
impl AppWrapper {
fn new<A>(app: A, state: &PreInitState<'_>) -> Self
where
A: App,
{
Self {
cmdq: processor::Processor::start(app, state),
}
}
}
#[async_trait]
impl app::App for AppWrapper {
async fn on_runtime_block(&self, blk: &roothash::AnnotatedBlock) -> Result<()> {
self.cmdq
.send(processor::Command::ProcessRuntimeBlock(blk.clone()))
.await?;
Ok(())
}
async fn on_runtime_event(
&self,
_blk: &roothash::AnnotatedBlock,
_tags: &[Vec<u8>],
) -> Result<()> {
Ok(())
}
}