oasis_runtime_sdk/modules/rofl/app/
mod.rs1use std::{collections::BTreeMap, sync::Arc};
3
4use anyhow::Result;
5use async_trait::async_trait;
6use base64::prelude::*;
7use tokio::sync::mpsc;
8
9use crate::{
10 core::{
11 app,
12 common::version,
13 config::Config,
14 consensus::{roothash, verifier::TrustRoot},
15 dispatcher::{PostInitState, PreInitState},
16 start_runtime,
17 },
18 crypto,
19 types::transaction,
20};
21
22pub mod client;
23mod env;
24pub mod init;
25mod notifier;
26pub mod prelude;
27mod processor;
28mod registration;
29mod watchdog;
30
31pub use crate::modules::rofl::app_id::AppId;
32pub use client::Client;
33pub use env::Environment;
34
35#[allow(unused_variables)]
37#[async_trait]
38pub trait App: Send + Sync + 'static {
39 const VERSION: version::Version;
41
42 fn id() -> AppId {
44 #[allow(clippy::option_env_unwrap)]
46 AppId::from_bech32(
47 option_env!("ROFL_APP_ID").expect("Override App::id or specify ROFL_APP_ID."),
48 )
49 .expect("Corrupted ROFL_APP_ID (must be Bech32-encoded ROFL app ID).")
50 }
51
52 fn consensus_trust_root() -> Option<TrustRoot> {
55 option_env!("ROFL_CONSENSUS_TRUST_ROOT").map(|raw_trust_root| {
57 cbor::from_slice(
59 &BASE64_STANDARD
60 .decode(raw_trust_root)
61 .expect("Corrupted ROFL_CONSENSUS_TRUST_ROOT (must be Base64-encoded CBOR)."),
62 )
63 .expect("Corrupted ROFL_CONSENSUS_TRUST_ROOT (must be Base64-encoded CBOR).")
64 })
65 }
66
67 fn new_transaction<B>(&self, method: &str, body: B) -> transaction::Transaction
69 where
70 B: cbor::Encode,
71 {
72 let mut tx = transaction::Transaction::new(method, body);
73 tx.set_fee_proxy("rofl", Self::id().as_ref());
75 tx
76 }
77
78 async fn get_metadata(
83 self: Arc<Self>,
84 env: Environment<Self>,
85 ) -> Result<BTreeMap<String, String>>
86 where
87 Self: Sized,
88 {
89 Ok(BTreeMap::new())
90 }
91
92 async fn post_registration_init(self: Arc<Self>, env: Environment<Self>)
98 where
99 Self: Sized,
100 {
101 init::post_registration_init();
103 }
104
105 async fn run(self: Arc<Self>, env: Environment<Self>)
107 where
108 Self: Sized,
109 {
110 }
112
113 async fn on_runtime_block(self: Arc<Self>, env: Environment<Self>, round: u64)
115 where
116 Self: Sized,
117 {
118 }
120
121 fn start(self)
123 where
124 Self: Sized,
125 {
126 start_runtime(
127 Box::new(|state: PreInitState<'_>| -> PostInitState {
128 let hi = state.protocol.get_host_info();
130 crypto::signature::context::set_chain_context(
131 hi.runtime_id,
132 &hi.consensus_chain_context,
133 );
134
135 PostInitState {
136 app: Some(Box::new(AppWrapper::new(self, &state))),
137 ..Default::default()
138 }
139 }),
140 Config {
141 version: Self::VERSION,
142 trust_root: Self::consensus_trust_root(),
143 ..Default::default()
144 },
145 );
146 }
147}
148
149struct AppWrapper {
150 cmdq: mpsc::Sender<processor::Command>,
151}
152
153impl AppWrapper {
154 fn new<A>(app: A, state: &PreInitState<'_>) -> Self
155 where
156 A: App,
157 {
158 Self {
159 cmdq: processor::Processor::start(app, state),
160 }
161 }
162}
163
164#[async_trait]
165impl app::App for AppWrapper {
166 async fn on_runtime_block(&self, blk: &roothash::AnnotatedBlock) -> Result<()> {
167 self.cmdq
168 .send(processor::Command::ProcessRuntimeBlock(blk.clone()))
169 .await?;
170 Ok(())
171 }
172
173 async fn on_runtime_event(
174 &self,
175 _blk: &roothash::AnnotatedBlock,
176 _tags: &[Vec<u8>],
177 ) -> Result<()> {
178 Ok(())
179 }
180}