oasis_core_runtime/enclave_rpc/
transport.rs

1use std::sync::Arc;
2
3use anyhow::{anyhow, Error as AnyError};
4use async_trait::async_trait;
5
6use crate::{common::crypto::signature, types::Body, Protocol};
7
8use super::types;
9
10// Enclave's response.
11pub struct EnclaveResponse {
12    // Actual response data.
13    pub data: Vec<u8>,
14    // The public key of the node that generated the response.
15    pub node: signature::PublicKey,
16}
17
18/// An EnclaveRPC transport.
19#[async_trait]
20pub trait Transport: Send + Sync {
21    async fn write_noise_session(
22        &self,
23        request_id: u64,
24        session_id: types::SessionID,
25        data: Vec<u8>,
26        untrusted_plaintext: String,
27        nodes: Vec<signature::PublicKey>,
28    ) -> Result<EnclaveResponse, AnyError> {
29        let frame = types::Frame {
30            session: session_id,
31            untrusted_plaintext,
32            payload: data,
33        };
34
35        self.write_message_impl(
36            request_id,
37            cbor::to_vec(frame),
38            types::Kind::NoiseSession,
39            nodes,
40        )
41        .await
42    }
43
44    async fn write_insecure_query(
45        &self,
46        request_id: u64,
47        data: Vec<u8>,
48        nodes: Vec<signature::PublicKey>,
49    ) -> Result<EnclaveResponse, AnyError> {
50        self.write_message_impl(request_id, data, types::Kind::InsecureQuery, nodes)
51            .await
52    }
53
54    async fn write_message_impl(
55        &self,
56        request_id: u64,
57        data: Vec<u8>,
58        kind: types::Kind,
59        nodes: Vec<signature::PublicKey>,
60    ) -> Result<EnclaveResponse, AnyError>;
61
62    async fn submit_peer_feedback(
63        &self,
64        request_id: u64,
65        feedback: types::PeerFeedback,
66    ) -> Result<(), AnyError>;
67}
68
69/// A transport implementation which can be used from inside the runtime and uses the Runtime Host
70/// Protocol to transport EnclaveRPC frames.
71pub struct RuntimeTransport {
72    pub protocol: Arc<Protocol>,
73    pub endpoint: String,
74}
75
76impl RuntimeTransport {
77    pub fn new(protocol: Arc<Protocol>, endpoint: &str) -> Self {
78        Self {
79            protocol,
80            endpoint: endpoint.to_string(),
81        }
82    }
83}
84
85#[async_trait]
86impl Transport for RuntimeTransport {
87    async fn write_message_impl(
88        &self,
89        request_id: u64,
90        data: Vec<u8>,
91        kind: types::Kind,
92        nodes: Vec<signature::PublicKey>,
93    ) -> Result<EnclaveResponse, AnyError> {
94        let rsp = self
95            .protocol
96            .call_host_async(Body::HostRPCCallRequest {
97                endpoint: self.endpoint.clone(),
98                request_id,
99                request: data,
100                kind,
101                nodes,
102            })
103            .await?;
104
105        match rsp {
106            Body::HostRPCCallResponse { response, node } => Ok(EnclaveResponse {
107                data: response,
108                node,
109            }),
110            _ => Err(anyhow!("bad response type")),
111        }
112    }
113
114    async fn submit_peer_feedback(
115        &self,
116        request_id: u64,
117        peer_feedback: types::PeerFeedback,
118    ) -> Result<(), AnyError> {
119        let rsp = self
120            .protocol
121            .call_host_async(Body::HostSubmitPeerFeedbackRequest {
122                endpoint: self.endpoint.clone(),
123                request_id,
124                peer_feedback,
125            })
126            .await?;
127
128        match rsp {
129            Body::HostSubmitPeerFeedbackResponse {} => Ok(()),
130            _ => Err(anyhow!("bad response type")),
131        }
132    }
133}