oasis_core_runtime/host/
mod.rs1use async_trait::async_trait;
3use thiserror::Error;
4
5use crate::{
6 common::{crypto::signature::PublicKey, namespace::Namespace},
7 enclave_rpc,
8 protocol::Protocol,
9 storage::mkvs::sync,
10 types::{self, Body},
11};
12
13pub mod attestation;
14pub mod bundle_manager;
15pub mod log_manager;
16pub mod volume_manager;
17
18#[derive(Error, Debug)]
20pub enum Error {
21 #[error("bad response from host")]
22 BadResponse,
23
24 #[error("{0}")]
25 Host(#[from] types::Error),
26
27 #[error("{0}")]
28 Decode(#[from] cbor::DecodeError),
29}
30
31#[derive(Clone, Default, Debug)]
33pub struct SubmitTxOpts {
34 pub runtime_id: Option<Namespace>,
36 pub wait: bool,
38 pub prove: bool,
40}
41
42#[derive(Clone, Default, Debug)]
44pub struct TxResult {
45 pub output: Vec<u8>,
47 pub round: u64,
49 pub batch_order: u32,
51 pub proof: Option<sync::Proof>,
53}
54
55#[derive(Clone, Default, Debug)]
57pub struct RegisterNotifyOpts {
58 pub runtime_block: bool,
60 pub runtime_event: Vec<Vec<u8>>,
62}
63
64#[async_trait]
66pub trait Host: Send + Sync {
67 async fn identity(&self) -> Result<PublicKey, Error>;
69
70 async fn submit_tx(&self, data: Vec<u8>, opts: SubmitTxOpts)
72 -> Result<Option<TxResult>, Error>;
73
74 async fn register_notify(&self, opts: RegisterNotifyOpts) -> Result<(), Error>;
76
77 fn bundle_manager(&self) -> &dyn bundle_manager::BundleManager;
79
80 fn volume_manager(&self) -> &dyn volume_manager::VolumeManager;
82
83 fn log_manager(&self) -> &dyn log_manager::LogManager;
85
86 fn attestation(&self) -> &dyn attestation::Attestation;
88}
89
90#[async_trait]
91impl Host for Protocol {
92 async fn identity(&self) -> Result<PublicKey, Error> {
93 match self.call_host_async(Body::HostIdentityRequest {}).await? {
94 Body::HostIdentityResponse { node_id } => Ok(node_id),
95 _ => Err(Error::BadResponse),
96 }
97 }
98
99 async fn submit_tx(
100 &self,
101 data: Vec<u8>,
102 opts: SubmitTxOpts,
103 ) -> Result<Option<TxResult>, Error> {
104 match self
105 .call_host_async(Body::HostSubmitTxRequest {
106 runtime_id: opts.runtime_id.unwrap_or_else(|| self.get_runtime_id()),
107 data,
108 wait: opts.wait,
109 prove: opts.prove,
110 })
111 .await?
112 {
113 Body::HostSubmitTxResponse {
114 output,
115 round,
116 batch_order,
117 proof,
118 } => {
119 if opts.wait {
120 Ok(Some(TxResult {
121 output,
122 round,
123 batch_order,
124 proof,
125 }))
126 } else {
127 Ok(None)
129 }
130 }
131 _ => Err(Error::BadResponse),
132 }
133 }
134
135 async fn register_notify(&self, opts: RegisterNotifyOpts) -> Result<(), Error> {
136 match self
137 .call_host_async(Body::HostRegisterNotifyRequest {
138 runtime_block: opts.runtime_block,
139 runtime_event: match opts.runtime_event {
140 tags if tags.is_empty() => None,
141 tags => Some(types::RegisterNotifyRuntimeEvent { tags }),
142 },
143 })
144 .await?
145 {
146 Body::Empty {} => Ok(()),
147 _ => Err(Error::BadResponse),
148 }
149 }
150
151 fn bundle_manager(&self) -> &dyn bundle_manager::BundleManager {
152 self
153 }
154
155 fn volume_manager(&self) -> &dyn volume_manager::VolumeManager {
156 self
157 }
158
159 fn log_manager(&self) -> &dyn log_manager::LogManager {
160 self
161 }
162
163 fn attestation(&self) -> &dyn attestation::Attestation {
164 self
165 }
166}
167
168pub(super) async fn host_rpc_call<Rq: cbor::Encode, Rs: cbor::Decode>(
170 protocol: &Protocol,
171 endpoint: &str,
172 method: &str,
173 args: Rq,
174) -> Result<Rs, Error> {
175 match protocol
176 .call_host_async(Body::HostRPCCallRequest {
177 endpoint: endpoint.to_string(),
178 request_id: 0,
179 request: cbor::to_vec(enclave_rpc::types::Request {
180 method: method.to_string(),
181 args: cbor::to_value(args),
182 }),
183 kind: enclave_rpc::types::Kind::LocalQuery,
184 nodes: vec![],
185 })
186 .await?
187 {
188 Body::HostRPCCallResponse { response, .. } => Ok(cbor::from_slice(&response)?),
189 _ => Err(Error::BadResponse),
190 }
191}