1use 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#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
33pub struct ComputedBatch {
34 pub header: ComputeResultsHeader,
36 pub io_write_log: WriteLog,
38 pub state_write_log: WriteLog,
40 pub rak_sig: Signature,
43 pub messages: Vec<roothash::Message>,
45}
46
47#[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 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 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#[derive(Debug, cbor::Encode, cbor::Decode)]
96pub enum StorageSyncResponse {
97 ProofResponse(sync::ProofResponse),
98}
99
100#[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#[derive(Debug, cbor::Encode, cbor::Decode)]
110pub enum Body {
111 Empty {},
113
114 Error(Error),
116
117 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 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#[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 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#[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#[derive(Clone, Debug, cbor::Encode, cbor::Decode)]
374pub struct Features {
375 #[cbor(optional)]
377 pub schedule_control: Option<FeatureScheduleControl>,
378 #[cbor(optional)]
380 pub key_manager_quote_policy_updates: bool,
381 #[cbor(optional)]
383 pub key_manager_status_updates: bool,
384 #[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#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
404pub struct FeatureScheduleControl {
405 pub initial_batch_size: u32,
407}
408
409#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
411pub struct RuntimeInfoResponse {
412 pub protocol_version: Version,
414
415 pub runtime_version: Version,
417
418 pub features: Features,
420}
421
422#[derive(Clone, Debug, PartialEq, Eq, cbor::Encode, cbor::Decode)]
424#[cbor(with_default)]
425#[derive(Default)]
426pub enum ExecutionMode {
427 #[default]
430 Execute = 0,
431 Schedule = 1,
438}
439
440#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
442pub struct CheckTxResult {
443 pub error: Error,
444 pub meta: Option<CheckTxMetadata>,
445}
446
447#[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#[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#[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#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
481pub struct HostFetchConsensusEventsResponse {
482 pub events: Vec<consensus::Event>,
483}
484
485#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
487pub struct RegisterNotifyRuntimeEvent {
488 pub tags: Vec<Vec<u8>>,
490}
491
492#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
494pub struct RuntimeNotifyEvent {
495 pub block: roothash::AnnotatedBlock,
497 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 #[default]
507 Invalid = 0,
508 Request = 1,
510 Response = 2,
512}
513
514#[derive(Debug, Default, cbor::Encode, cbor::Decode)]
516pub struct Message {
517 pub id: u64,
519 pub message_type: MessageType,
521 pub body: Body,
523}