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