oasis_core_runtime/
types.rs

1//! Types used by the worker-host protocol.
2use std::collections::BTreeMap;
3
4use thiserror::Error;
5
6use crate::{
7    common::{
8        crypto::{
9            hash::Hash,
10            signature::{self, Signature},
11            x25519,
12        },
13        namespace::Namespace,
14        sgx::{ias::AVR, Quote, QuotePolicy},
15        version::Version,
16    },
17    consensus::{
18        self,
19        beacon::EpochTime,
20        registry::EndorsedCapabilityTEE,
21        roothash::{self, Block, ComputeResultsHeader, Header},
22        state::keymanager::Status as KeyManagerStatus,
23        transaction::{Proof, SignedTransaction},
24        LightBlock,
25    },
26    enclave_rpc,
27    storage::mkvs::{sync, WriteLog},
28    transaction::types::TxnBatch,
29};
30
31/// Computed batch.
32#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
33pub struct ComputedBatch {
34    /// Compute results header.
35    pub header: ComputeResultsHeader,
36    /// Log that generates the I/O tree.
37    pub io_write_log: WriteLog,
38    /// Log of changes to the state tree.
39    pub state_write_log: WriteLog,
40    /// If this runtime uses a TEE, then this is the signature of the batch's
41    /// BatchSigMessage with the node's RAK for this runtime.
42    pub rak_sig: Signature,
43    /// Messages emitted by the runtime.
44    pub messages: Vec<roothash::Message>,
45}
46
47/// Storage sync request.
48#[derive(Debug, cbor::Encode, cbor::Decode)]
49pub enum StorageSyncRequest {
50    SyncGet(sync::GetRequest),
51    SyncGetPrefixes(sync::GetPrefixesRequest),
52    SyncIterate(sync::IterateRequest),
53}
54
55#[derive(Debug)]
56pub struct StorageSyncRequestWithEndpoint {
57    pub endpoint: HostStorageEndpoint,
58    pub request: StorageSyncRequest,
59}
60
61impl cbor::Encode for StorageSyncRequestWithEndpoint {
62    fn into_cbor_value(self) -> cbor::Value {
63        let mut request = cbor::EncodeAsMap::into_cbor_map(self.request);
64        // Add endpoint to the given map.
65        let key = cbor::values::IntoCborValue::into_cbor_value("endpoint");
66        request.push((key, self.endpoint.into_cbor_value()));
67        cbor::Value::Map(request)
68    }
69}
70
71impl cbor::Decode for StorageSyncRequestWithEndpoint {
72    fn try_from_cbor_value(value: cbor::Value) -> Result<Self, cbor::DecodeError> {
73        match value {
74            cbor::Value::Map(mut items) => {
75                // Take the endpoint field from the map and decode the rest.
76                let key = cbor::values::IntoCborValue::into_cbor_value("endpoint");
77                let (index, _) = items
78                    .iter()
79                    .enumerate()
80                    .find(|(_, v)| v.0 == key)
81                    .ok_or(cbor::DecodeError::MissingField)?;
82                let endpoint = items.remove(index).1;
83
84                Ok(Self {
85                    endpoint: cbor::Decode::try_from_cbor_value(endpoint)?,
86                    request: cbor::Decode::try_from_cbor_value(cbor::Value::Map(items))?,
87                })
88            }
89            _ => Err(cbor::DecodeError::UnexpectedType),
90        }
91    }
92}
93
94/// Storage sync response.
95#[derive(Debug, cbor::Encode, cbor::Decode)]
96pub enum StorageSyncResponse {
97    ProofResponse(sync::ProofResponse),
98}
99
100/// Host storage endpoint.
101#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, cbor::Encode, cbor::Decode)]
102#[repr(u8)]
103pub enum HostStorageEndpoint {
104    Runtime = 0,
105    Consensus = 1,
106}
107
108/// Runtime host protocol message body.
109#[derive(Debug, cbor::Encode, cbor::Decode)]
110pub enum Body {
111    // An empty body.
112    Empty {},
113
114    // An error response.
115    Error(Error),
116
117    // Runtime interface.
118    RuntimeInfoRequest(RuntimeInfoRequest),
119    RuntimeInfoResponse(RuntimeInfoResponse),
120    RuntimePingRequest {},
121    RuntimeShutdownRequest {},
122    RuntimeAbortRequest {},
123    RuntimeAbortResponse {},
124    RuntimeCapabilityTEERakInitRequest {
125        target_info: Vec<u8>,
126    },
127    RuntimeCapabilityTEERakInitResponse {},
128    RuntimeCapabilityTEERakReportRequest {},
129    RuntimeCapabilityTEERakReportResponse {
130        rak_pub: signature::PublicKey,
131        rek_pub: x25519::PublicKey,
132        report: Vec<u8>,
133        nonce: String,
134    },
135    RuntimeCapabilityTEERakAvrRequest {
136        avr: AVR,
137    },
138    RuntimeCapabilityTEERakAvrResponse {},
139    RuntimeCapabilityTEERakQuoteRequest {
140        quote: Quote,
141    },
142    RuntimeCapabilityTEERakQuoteResponse {
143        height: u64,
144        signature: Signature,
145    },
146    RuntimeCapabilityTEEUpdateEndorsementRequest {
147        ect: EndorsedCapabilityTEE,
148    },
149    RuntimeCapabilityTEEUpdateEndorsementResponse {},
150    RuntimeRPCCallRequest {
151        request: Vec<u8>,
152        kind: enclave_rpc::types::Kind,
153        peer_id: Vec<u8>,
154    },
155    RuntimeRPCCallResponse {
156        response: Vec<u8>,
157    },
158    RuntimeLocalRPCCallRequest {
159        request: Vec<u8>,
160    },
161    RuntimeLocalRPCCallResponse {
162        response: Vec<u8>,
163    },
164    RuntimeCheckTxBatchRequest {
165        consensus_block: LightBlock,
166        inputs: TxnBatch,
167        block: Block,
168        epoch: EpochTime,
169        max_messages: u32,
170    },
171    RuntimeCheckTxBatchResponse {
172        results: Vec<CheckTxResult>,
173    },
174    RuntimeExecuteTxBatchRequest {
175        #[cbor(optional)]
176        mode: ExecutionMode,
177        consensus_block: LightBlock,
178        round_results: roothash::RoundResults,
179        io_root: Hash,
180        #[cbor(optional)]
181        inputs: Option<TxnBatch>,
182        #[cbor(optional)]
183        in_msgs: Vec<roothash::IncomingMessage>,
184        block: Block,
185        epoch: EpochTime,
186        max_messages: u32,
187    },
188    RuntimeExecuteTxBatchResponse {
189        batch: ComputedBatch,
190
191        tx_hashes: Vec<Hash>,
192        tx_reject_hashes: Vec<Hash>,
193        tx_input_root: Hash,
194        tx_input_write_log: WriteLog,
195    },
196    RuntimeKeyManagerStatusUpdateRequest {
197        status: KeyManagerStatus,
198    },
199    RuntimeKeyManagerStatusUpdateResponse {},
200    RuntimeKeyManagerQuotePolicyUpdateRequest {
201        policy: QuotePolicy,
202    },
203    RuntimeKeyManagerQuotePolicyUpdateResponse {},
204    RuntimeQueryRequest {
205        consensus_block: LightBlock,
206        header: Header,
207        epoch: EpochTime,
208        max_messages: u32,
209        method: String,
210        #[cbor(optional)]
211        args: Vec<u8>,
212    },
213    RuntimeQueryResponse {
214        #[cbor(optional)]
215        data: Vec<u8>,
216    },
217    RuntimeConsensusSyncRequest {
218        height: u64,
219    },
220    RuntimeConsensusSyncResponse {},
221    RuntimeNotifyRequest {
222        #[cbor(optional)]
223        runtime_block: Option<roothash::AnnotatedBlock>,
224        #[cbor(optional)]
225        runtime_event: Option<RuntimeNotifyEvent>,
226    },
227    RuntimeNotifyResponse {},
228
229    // Host interface.
230    HostRPCCallRequest {
231        endpoint: String,
232        request_id: u64,
233        request: Vec<u8>,
234        kind: enclave_rpc::types::Kind,
235        nodes: Vec<signature::PublicKey>,
236    },
237    HostRPCCallResponse {
238        response: Vec<u8>,
239        node: signature::PublicKey,
240    },
241    HostSubmitPeerFeedbackRequest {
242        endpoint: String,
243        request_id: u64,
244        peer_feedback: enclave_rpc::types::PeerFeedback,
245    },
246    HostSubmitPeerFeedbackResponse {},
247    HostStorageSyncRequest(StorageSyncRequestWithEndpoint),
248    HostStorageSyncResponse(StorageSyncResponse),
249    HostLocalStorageGetRequest {
250        key: Vec<u8>,
251    },
252    HostLocalStorageGetResponse {
253        value: Vec<u8>,
254    },
255    HostLocalStorageSetRequest {
256        key: Vec<u8>,
257        value: Vec<u8>,
258    },
259    HostLocalStorageSetResponse {},
260    HostFetchConsensusBlockRequest {
261        height: u64,
262    },
263    HostFetchConsensusBlockResponse {
264        block: LightBlock,
265    },
266    HostFetchConsensusEventsRequest(HostFetchConsensusEventsRequest),
267    HostFetchConsensusEventsResponse(HostFetchConsensusEventsResponse),
268    HostFetchTxBatchRequest {
269        #[cbor(optional)]
270        offset: Option<Hash>,
271        limit: u32,
272    },
273    HostFetchTxBatchResponse {
274        #[cbor(optional)]
275        batch: Option<TxnBatch>,
276    },
277    HostFetchBlockMetadataTxRequest {
278        height: u64,
279    },
280    HostFetchBlockMetadataTxResponse {
281        signed_tx: SignedTransaction,
282        proof: Proof,
283    },
284    HostFetchGenesisHeightRequest {},
285    HostFetchGenesisHeightResponse {
286        height: u64,
287    },
288    HostProveFreshnessRequest {
289        blob: Vec<u8>,
290    },
291    HostProveFreshnessResponse {
292        signed_tx: SignedTransaction,
293        proof: Proof,
294    },
295    HostIdentityRequest {},
296    HostIdentityResponse {
297        node_id: signature::PublicKey,
298    },
299    HostSubmitTxRequest {
300        runtime_id: Namespace,
301        data: Vec<u8>,
302        wait: bool,
303        prove: bool,
304    },
305    HostSubmitTxResponse {
306        output: Vec<u8>,
307        round: u64,
308        batch_order: u32,
309        proof: Option<sync::Proof>,
310    },
311    HostRegisterNotifyRequest {
312        #[cbor(optional)]
313        runtime_block: bool,
314        #[cbor(optional)]
315        runtime_event: Option<RegisterNotifyRuntimeEvent>,
316    },
317    HostRegisterNotifyResponse {},
318}
319
320impl Default for Body {
321    fn default() -> Self {
322        Self::Empty {}
323    }
324}
325
326/// A serializable error.
327#[derive(Clone, Debug, Default, Error, cbor::Encode, cbor::Decode)]
328#[error("module: {module} code: {code} message: {message}")]
329pub struct Error {
330    #[cbor(optional)]
331    pub module: String,
332
333    #[cbor(optional)]
334    pub code: u32,
335
336    #[cbor(optional)]
337    pub message: String,
338}
339
340impl Error {
341    /// Create a new error.
342    pub fn new(module: &str, code: u32, msg: &str) -> Self {
343        Self {
344            module: module.to_owned(),
345            code,
346            message: msg.to_owned(),
347        }
348    }
349}
350
351impl From<anyhow::Error> for Error {
352    fn from(err: anyhow::Error) -> Self {
353        Self {
354            module: "unknown".to_string(),
355            code: 1,
356            message: err.to_string(),
357        }
358    }
359}
360
361/// Runtime information request.
362#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
363pub struct RuntimeInfoRequest {
364    pub runtime_id: Namespace,
365    pub consensus_backend: String,
366    pub consensus_protocol_version: Version,
367    pub consensus_chain_context: String,
368
369    #[cbor(optional)]
370    pub local_config: BTreeMap<String, cbor::Value>,
371}
372
373/// Set of supported runtime features.
374#[derive(Clone, Debug, cbor::Encode, cbor::Decode)]
375pub struct Features {
376    /// Schedule control feature.
377    #[cbor(optional)]
378    pub schedule_control: Option<FeatureScheduleControl>,
379    /// A feature specifying that the runtime supports updating key manager's quote policy.
380    #[cbor(optional)]
381    pub key_manager_quote_policy_updates: bool,
382    /// A feature specifying that the runtime supports updating key manager's status.
383    #[cbor(optional)]
384    pub key_manager_status_updates: bool,
385    /// A feature specifying that the runtime supports endorsed TEE capabilities.
386    #[cbor(optional)]
387    pub endorsed_capability_tee: bool,
388}
389
390impl Default for Features {
391    fn default() -> Self {
392        Self {
393            schedule_control: None,
394            key_manager_quote_policy_updates: true,
395            key_manager_status_updates: true,
396            endorsed_capability_tee: true,
397        }
398    }
399}
400
401/// A feature specifying that the runtime supports controlling the scheduling of batches. This means
402/// that the scheduler should only take priority into account and ignore weights, leaving it up to
403/// the runtime to decide which transactions to include.
404#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
405pub struct FeatureScheduleControl {
406    /// Size of the initial batch of transactions.
407    pub initial_batch_size: u32,
408}
409
410/// Runtime information response.
411#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
412pub struct RuntimeInfoResponse {
413    /// The runtime protocol version supported by the runtime.
414    pub protocol_version: Version,
415
416    /// The version of the runtime.
417    pub runtime_version: Version,
418
419    /// Describes the features supported by the runtime.
420    pub features: Features,
421}
422
423/// Batch execution mode.
424#[derive(Clone, Debug, PartialEq, Eq, cbor::Encode, cbor::Decode)]
425#[cbor(with_default)]
426pub enum ExecutionMode {
427    /// Execution mode where the batch of transactions is executed as-is without the ability to
428    /// perform and modifications to the batch.
429    Execute = 0,
430    /// Execution mode where the runtime is in control of scheduling and may arbitrarily modify the
431    /// batch during execution.
432    ///
433    /// This execution mode will only be used in case the runtime advertises to support the schedule
434    /// control feature. In this case the call will only contain up to InitialBatchSize transactions
435    /// and the runtime will need to request more if it needs more.
436    Schedule = 1,
437}
438
439impl Default for ExecutionMode {
440    fn default() -> Self {
441        Self::Execute
442    }
443}
444
445/// Result of a CheckTx operation.
446#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
447pub struct CheckTxResult {
448    pub error: Error,
449    pub meta: Option<CheckTxMetadata>,
450}
451
452/// CheckTx transaction metadata.
453#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
454pub struct CheckTxMetadata {
455    #[cbor(optional)]
456    pub priority: u64,
457
458    #[cbor(optional)]
459    pub sender: Vec<u8>,
460    #[cbor(optional)]
461    pub sender_seq: u64,
462    #[cbor(optional)]
463    pub sender_state_seq: u64,
464}
465
466/// Consensus event kind.
467#[derive(Clone, Copy, Debug, cbor::Encode, cbor::Decode)]
468#[repr(u8)]
469pub enum EventKind {
470    Staking = 1,
471    Registry = 2,
472    RootHash = 3,
473    Governance = 4,
474}
475
476/// Request to host to fetch the consensus events for the given height.
477#[derive(Clone, Debug, cbor::Encode, cbor::Decode)]
478#[cbor(no_default)]
479pub struct HostFetchConsensusEventsRequest {
480    pub height: u64,
481    pub kind: EventKind,
482}
483
484/// Response from host fetching the consensus events for the given height.
485#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
486pub struct HostFetchConsensusEventsResponse {
487    pub events: Vec<consensus::Event>,
488}
489
490/// Registration for runtime event notifications.
491#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
492pub struct RegisterNotifyRuntimeEvent {
493    /// Event tags to subscribe to.
494    pub tags: Vec<Vec<u8>>,
495}
496
497/// An event notification.
498#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
499pub struct RuntimeNotifyEvent {
500    /// Header of the block that emitted the event.
501    pub block: roothash::AnnotatedBlock,
502    /// Matching tags.
503    pub tags: Vec<Vec<u8>>,
504}
505
506#[derive(Clone, Copy, Debug, cbor::Encode, cbor::Decode)]
507#[repr(u8)]
508pub enum MessageType {
509    /// Invalid message (should never be seen on the wire).
510    Invalid = 0,
511    /// Request.
512    Request = 1,
513    /// Response.
514    Response = 2,
515}
516
517impl Default for MessageType {
518    fn default() -> Self {
519        Self::Invalid
520    }
521}
522
523/// Runtime protocol message.
524#[derive(Debug, Default, cbor::Encode, cbor::Decode)]
525pub struct Message {
526    /// Unique request identifier.
527    pub id: u64,
528    /// Message type.
529    pub message_type: MessageType,
530    /// Message body.
531    pub body: Body,
532}