Skip to main content

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, Validators,
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    HostFetchConsensusValidatorsRequest {
267        height: u64,
268    },
269    HostFetchConsensusValidatorsResponse {
270        validators: Validators,
271    },
272    HostFetchConsensusEventsRequest(HostFetchConsensusEventsRequest),
273    HostFetchConsensusEventsResponse(HostFetchConsensusEventsResponse),
274    HostFetchTxBatchRequest {
275        #[cbor(optional)]
276        offset: Option<Hash>,
277        limit: u32,
278    },
279    HostFetchTxBatchResponse {
280        #[cbor(optional)]
281        batch: Option<TxnBatch>,
282    },
283    HostFetchBlockMetadataTxRequest {
284        height: u64,
285    },
286    HostFetchBlockMetadataTxResponse {
287        signed_tx: SignedTransaction,
288        proof: Proof,
289    },
290    HostFetchGenesisHeightRequest {},
291    HostFetchGenesisHeightResponse {
292        height: u64,
293    },
294    HostProveFreshnessRequest {
295        blob: Vec<u8>,
296    },
297    HostProveFreshnessResponse {
298        signed_tx: SignedTransaction,
299        proof: Proof,
300    },
301    HostIdentityRequest {},
302    HostIdentityResponse {
303        node_id: signature::PublicKey,
304    },
305    HostSubmitTxRequest {
306        runtime_id: Namespace,
307        data: Vec<u8>,
308        wait: bool,
309        prove: bool,
310    },
311    HostSubmitTxResponse {
312        output: Vec<u8>,
313        round: u64,
314        batch_order: u32,
315        proof: Option<sync::Proof>,
316    },
317}
318
319impl Default for Body {
320    fn default() -> Self {
321        Self::Empty {}
322    }
323}
324
325/// A serializable error.
326#[derive(Clone, Debug, Default, Error, cbor::Encode, cbor::Decode)]
327#[error("module: {module} code: {code} message: {message}")]
328pub struct Error {
329    #[cbor(optional)]
330    pub module: String,
331
332    #[cbor(optional)]
333    pub code: u32,
334
335    #[cbor(optional)]
336    pub message: String,
337}
338
339impl Error {
340    /// Create a new error.
341    pub fn new(module: &str, code: u32, msg: &str) -> Self {
342        Self {
343            module: module.to_owned(),
344            code,
345            message: msg.to_owned(),
346        }
347    }
348}
349
350impl From<anyhow::Error> for Error {
351    fn from(err: anyhow::Error) -> Self {
352        Self {
353            module: "unknown".to_string(),
354            code: 1,
355            message: err.to_string(),
356        }
357    }
358}
359
360/// Runtime information request.
361#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
362pub struct RuntimeInfoRequest {
363    pub runtime_id: Namespace,
364    pub consensus_backend: String,
365    pub consensus_protocol_version: Version,
366    pub consensus_chain_context: String,
367
368    #[cbor(optional)]
369    pub local_config: BTreeMap<String, cbor::Value>,
370}
371
372/// Set of supported runtime features.
373#[derive(Clone, Debug, cbor::Encode, cbor::Decode)]
374pub struct Features {
375    /// Schedule control feature.
376    #[cbor(optional)]
377    pub schedule_control: Option<FeatureScheduleControl>,
378    /// A feature specifying that the runtime supports updating key manager's quote policy.
379    #[cbor(optional)]
380    pub key_manager_quote_policy_updates: bool,
381    /// A feature specifying that the runtime supports updating key manager's status.
382    #[cbor(optional)]
383    pub key_manager_status_updates: bool,
384    /// A feature specifying that the runtime supports endorsed TEE capabilities.
385    #[cbor(optional)]
386    pub endorsed_capability_tee: bool,
387}
388
389impl Default for Features {
390    fn default() -> Self {
391        Self {
392            schedule_control: None,
393            key_manager_quote_policy_updates: true,
394            key_manager_status_updates: true,
395            endorsed_capability_tee: true,
396        }
397    }
398}
399
400/// A feature specifying that the runtime supports controlling the scheduling of batches. This means
401/// that the scheduler should only take priority into account and ignore weights, leaving it up to
402/// the runtime to decide which transactions to include.
403#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
404pub struct FeatureScheduleControl {
405    /// Size of the initial batch of transactions.
406    pub initial_batch_size: u32,
407}
408
409/// Runtime information response.
410#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
411pub struct RuntimeInfoResponse {
412    /// The runtime protocol version supported by the runtime.
413    pub protocol_version: Version,
414
415    /// The version of the runtime.
416    pub runtime_version: Version,
417
418    /// Describes the features supported by the runtime.
419    pub features: Features,
420}
421
422/// Batch execution mode.
423#[derive(Clone, Debug, PartialEq, Eq, cbor::Encode, cbor::Decode)]
424#[cbor(with_default)]
425#[derive(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    #[default]
430    Execute = 0,
431    /// Execution mode where the runtime is in control of scheduling and may arbitrarily modify the
432    /// batch during execution.
433    ///
434    /// This execution mode will only be used in case the runtime advertises to support the schedule
435    /// control feature. In this case the call will only contain up to InitialBatchSize transactions
436    /// and the runtime will need to request more if it needs more.
437    Schedule = 1,
438}
439
440/// Result of a CheckTx operation.
441#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
442pub struct CheckTxResult {
443    pub error: Error,
444    pub meta: Option<CheckTxMetadata>,
445}
446
447/// CheckTx transaction metadata.
448#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
449pub struct CheckTxMetadata {
450    #[cbor(optional)]
451    pub priority: u64,
452
453    #[cbor(optional)]
454    pub sender: Vec<u8>,
455    #[cbor(optional)]
456    pub sender_seq: u64,
457    #[cbor(optional)]
458    pub sender_state_seq: u64,
459}
460
461/// Consensus event kind.
462#[derive(Clone, Copy, Debug, cbor::Encode, cbor::Decode)]
463#[repr(u8)]
464pub enum EventKind {
465    Staking = 1,
466    Registry = 2,
467    RootHash = 3,
468    Governance = 4,
469}
470
471/// Request to host to fetch the consensus events for the given height.
472#[derive(Clone, Debug, cbor::Encode, cbor::Decode)]
473#[cbor(no_default)]
474pub struct HostFetchConsensusEventsRequest {
475    pub height: u64,
476    pub kind: EventKind,
477}
478
479/// Response from host fetching the consensus events for the given height.
480#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
481pub struct HostFetchConsensusEventsResponse {
482    pub events: Vec<consensus::Event>,
483}
484
485/// Registration for runtime event notifications.
486#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
487pub struct RegisterNotifyRuntimeEvent {
488    /// Event tags to subscribe to.
489    pub tags: Vec<Vec<u8>>,
490}
491
492/// An event notification.
493#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
494pub struct RuntimeNotifyEvent {
495    /// Header of the block that emitted the event.
496    pub block: roothash::AnnotatedBlock,
497    /// Matching tags.
498    pub tags: Vec<Vec<u8>>,
499}
500
501#[derive(Clone, Copy, Debug, cbor::Encode, cbor::Decode)]
502#[repr(u8)]
503#[derive(Default)]
504pub enum MessageType {
505    /// Invalid message (should never be seen on the wire).
506    #[default]
507    Invalid = 0,
508    /// Request.
509    Request = 1,
510    /// Response.
511    Response = 2,
512}
513
514/// Runtime protocol message.
515#[derive(Debug, Default, cbor::Encode, cbor::Decode)]
516pub struct Message {
517    /// Unique request identifier.
518    pub id: u64,
519    /// Message type.
520    pub message_type: MessageType,
521    /// Message body.
522    pub body: Body,
523}