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#[allow(clippy::double_must_use)]
57#[async_trait]
58pub trait Host: Send + Sync {
59 async fn identity(&self) -> Result<PublicKey, Error>;
61
62 async fn submit_tx(&self, data: Vec<u8>, opts: SubmitTxOpts)
64 -> Result<Option<TxResult>, Error>;
65
66 fn bundle_manager(&self) -> &dyn bundle_manager::BundleManager;
68
69 fn volume_manager(&self) -> &dyn volume_manager::VolumeManager;
71
72 fn log_manager(&self) -> &dyn log_manager::LogManager;
74
75 fn attestation(&self) -> &dyn attestation::Attestation;
77}
78
79#[allow(clippy::double_must_use)]
80#[async_trait]
81impl Host for Protocol {
82 async fn identity(&self) -> Result<PublicKey, Error> {
83 match self.call_host_async(Body::HostIdentityRequest {}).await? {
84 Body::HostIdentityResponse { node_id } => Ok(node_id),
85 _ => Err(Error::BadResponse),
86 }
87 }
88
89 async fn submit_tx(
90 &self,
91 data: Vec<u8>,
92 opts: SubmitTxOpts,
93 ) -> Result<Option<TxResult>, Error> {
94 match self
95 .call_host_async(Body::HostSubmitTxRequest {
96 runtime_id: opts.runtime_id.unwrap_or_else(|| self.get_runtime_id()),
97 data,
98 wait: opts.wait,
99 prove: opts.prove,
100 })
101 .await?
102 {
103 Body::HostSubmitTxResponse {
104 output,
105 round,
106 batch_order,
107 proof,
108 } => {
109 if opts.wait {
110 Ok(Some(TxResult {
111 output,
112 round,
113 batch_order,
114 proof,
115 }))
116 } else {
117 Ok(None)
119 }
120 }
121 _ => Err(Error::BadResponse),
122 }
123 }
124
125 fn bundle_manager(&self) -> &dyn bundle_manager::BundleManager {
126 self
127 }
128
129 fn volume_manager(&self) -> &dyn volume_manager::VolumeManager {
130 self
131 }
132
133 fn log_manager(&self) -> &dyn log_manager::LogManager {
134 self
135 }
136
137 fn attestation(&self) -> &dyn attestation::Attestation {
138 self
139 }
140}
141
142pub(super) async fn host_rpc_call<Rq: cbor::Encode, Rs: cbor::Decode>(
144 protocol: &Protocol,
145 endpoint: &str,
146 method: &str,
147 args: Rq,
148) -> Result<Rs, Error> {
149 match protocol
150 .call_host_async(Body::HostRPCCallRequest {
151 endpoint: endpoint.to_string(),
152 request_id: 0,
153 request: cbor::to_vec(enclave_rpc::types::Request {
154 method: method.to_string(),
155 args: cbor::to_value(args),
156 }),
157 kind: enclave_rpc::types::Kind::LocalQuery,
158 nodes: vec![],
159 })
160 .await?
161 {
162 Body::HostRPCCallResponse { response, .. } => Ok(cbor::from_slice(&response)?),
163 _ => Err(Error::BadResponse),
164 }
165}