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