use std::collections::BTreeMap;
use thiserror::Error;
use crate::{
common::{
crypto::{
hash::Hash,
signature::{self, Signature},
x25519,
},
namespace::Namespace,
sgx::{ias::AVR, Quote, QuotePolicy},
version::Version,
},
consensus::{
self,
beacon::EpochTime,
roothash::{self, Block, ComputeResultsHeader, Header},
state::keymanager::Status as KeyManagerStatus,
transaction::{Proof, SignedTransaction},
LightBlock,
},
enclave_rpc,
storage::mkvs::{sync, WriteLog},
transaction::types::TxnBatch,
};
#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
pub struct ComputedBatch {
pub header: ComputeResultsHeader,
pub io_write_log: WriteLog,
pub state_write_log: WriteLog,
pub rak_sig: Signature,
pub messages: Vec<roothash::Message>,
}
#[derive(Debug, cbor::Encode, cbor::Decode)]
pub enum StorageSyncRequest {
SyncGet(sync::GetRequest),
SyncGetPrefixes(sync::GetPrefixesRequest),
SyncIterate(sync::IterateRequest),
}
#[derive(Debug)]
pub struct StorageSyncRequestWithEndpoint {
pub endpoint: HostStorageEndpoint,
pub request: StorageSyncRequest,
}
impl cbor::Encode for StorageSyncRequestWithEndpoint {
fn into_cbor_value(self) -> cbor::Value {
let mut request = cbor::EncodeAsMap::into_cbor_map(self.request);
let key = cbor::values::IntoCborValue::into_cbor_value("endpoint");
request.push((key, self.endpoint.into_cbor_value()));
cbor::Value::Map(request)
}
}
impl cbor::Decode for StorageSyncRequestWithEndpoint {
fn try_from_cbor_value(value: cbor::Value) -> Result<Self, cbor::DecodeError> {
match value {
cbor::Value::Map(mut items) => {
let key = cbor::values::IntoCborValue::into_cbor_value("endpoint");
let (index, _) = items
.iter()
.enumerate()
.find(|(_, v)| v.0 == key)
.ok_or(cbor::DecodeError::MissingField)?;
let endpoint = items.remove(index).1;
Ok(Self {
endpoint: cbor::Decode::try_from_cbor_value(endpoint)?,
request: cbor::Decode::try_from_cbor_value(cbor::Value::Map(items))?,
})
}
_ => Err(cbor::DecodeError::UnexpectedType),
}
}
}
#[derive(Debug, cbor::Encode, cbor::Decode)]
pub enum StorageSyncResponse {
ProofResponse(sync::ProofResponse),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, cbor::Encode, cbor::Decode)]
#[repr(u8)]
pub enum HostStorageEndpoint {
Runtime = 0,
Consensus = 1,
}
#[derive(Debug, cbor::Encode, cbor::Decode)]
pub enum Body {
Empty {},
Error(Error),
RuntimeInfoRequest(RuntimeInfoRequest),
RuntimeInfoResponse(RuntimeInfoResponse),
RuntimePingRequest {},
RuntimeShutdownRequest {},
RuntimeAbortRequest {},
RuntimeAbortResponse {},
RuntimeCapabilityTEERakInitRequest {
target_info: Vec<u8>,
},
RuntimeCapabilityTEERakInitResponse {},
RuntimeCapabilityTEERakReportRequest {},
RuntimeCapabilityTEERakReportResponse {
rak_pub: signature::PublicKey,
rek_pub: x25519::PublicKey,
report: Vec<u8>,
nonce: String,
},
RuntimeCapabilityTEERakAvrRequest {
avr: AVR,
},
RuntimeCapabilityTEERakAvrResponse {},
RuntimeCapabilityTEERakQuoteRequest {
quote: Quote,
},
RuntimeCapabilityTEERakQuoteResponse {
height: u64,
signature: Signature,
},
RuntimeRPCCallRequest {
request: Vec<u8>,
kind: enclave_rpc::types::Kind,
},
RuntimeRPCCallResponse {
response: Vec<u8>,
},
RuntimeLocalRPCCallRequest {
request: Vec<u8>,
},
RuntimeLocalRPCCallResponse {
response: Vec<u8>,
},
RuntimeCheckTxBatchRequest {
consensus_block: LightBlock,
inputs: TxnBatch,
block: Block,
epoch: EpochTime,
max_messages: u32,
},
RuntimeCheckTxBatchResponse {
results: Vec<CheckTxResult>,
},
RuntimeExecuteTxBatchRequest {
#[cbor(optional)]
mode: ExecutionMode,
consensus_block: LightBlock,
round_results: roothash::RoundResults,
io_root: Hash,
#[cbor(optional)]
inputs: Option<TxnBatch>,
#[cbor(optional)]
in_msgs: Vec<roothash::IncomingMessage>,
block: Block,
epoch: EpochTime,
max_messages: u32,
},
RuntimeExecuteTxBatchResponse {
batch: ComputedBatch,
tx_hashes: Vec<Hash>,
tx_reject_hashes: Vec<Hash>,
tx_input_root: Hash,
tx_input_write_log: WriteLog,
},
RuntimeKeyManagerStatusUpdateRequest {
status: KeyManagerStatus,
},
RuntimeKeyManagerStatusUpdateResponse {},
RuntimeKeyManagerQuotePolicyUpdateRequest {
policy: QuotePolicy,
},
RuntimeKeyManagerQuotePolicyUpdateResponse {},
RuntimeQueryRequest {
consensus_block: LightBlock,
header: Header,
epoch: EpochTime,
max_messages: u32,
method: String,
#[cbor(optional)]
args: Vec<u8>,
},
RuntimeQueryResponse {
#[cbor(optional)]
data: Vec<u8>,
},
RuntimeConsensusSyncRequest {
height: u64,
},
RuntimeConsensusSyncResponse {},
HostRPCCallRequest {
endpoint: String,
request: Vec<u8>,
kind: enclave_rpc::types::Kind,
nodes: Vec<signature::PublicKey>,
#[cbor(optional, rename = "pf")]
peer_feedback: Option<enclave_rpc::types::PeerFeedback>,
},
HostRPCCallResponse {
response: Vec<u8>,
node: signature::PublicKey,
},
HostStorageSyncRequest(StorageSyncRequestWithEndpoint),
HostStorageSyncResponse(StorageSyncResponse),
HostLocalStorageGetRequest {
key: Vec<u8>,
},
HostLocalStorageGetResponse {
value: Vec<u8>,
},
HostLocalStorageSetRequest {
key: Vec<u8>,
value: Vec<u8>,
},
HostLocalStorageSetResponse {},
HostFetchConsensusBlockRequest {
height: u64,
},
HostFetchConsensusBlockResponse {
block: LightBlock,
},
HostFetchConsensusEventsRequest(HostFetchConsensusEventsRequest),
HostFetchConsensusEventsResponse(HostFetchConsensusEventsResponse),
HostFetchTxBatchRequest {
#[cbor(optional)]
offset: Option<Hash>,
limit: u32,
},
HostFetchTxBatchResponse {
#[cbor(optional)]
batch: Option<TxnBatch>,
},
HostFetchBlockMetadataTxRequest {
height: u64,
},
HostFetchBlockMetadataTxResponse {
signed_tx: SignedTransaction,
proof: Proof,
},
HostFetchGenesisHeightRequest {},
HostFetchGenesisHeightResponse {
height: u64,
},
HostProveFreshnessRequest {
blob: Vec<u8>,
},
HostProveFreshnessResponse {
signed_tx: SignedTransaction,
proof: Proof,
},
HostIdentityRequest {},
HostIdentityResponse {
node_id: signature::PublicKey,
},
}
impl Default for Body {
fn default() -> Self {
Self::Empty {}
}
}
#[derive(Clone, Debug, Default, Error, cbor::Encode, cbor::Decode)]
#[error("module: {module} code: {code} message: {message}")]
pub struct Error {
#[cbor(optional)]
pub module: String,
#[cbor(optional)]
pub code: u32,
#[cbor(optional)]
pub message: String,
}
impl Error {
pub fn new(module: &str, code: u32, msg: &str) -> Self {
Self {
module: module.to_owned(),
code,
message: msg.to_owned(),
}
}
}
impl From<anyhow::Error> for Error {
fn from(err: anyhow::Error) -> Self {
Self {
module: "unknown".to_string(),
code: 1,
message: err.to_string(),
}
}
}
#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
pub struct RuntimeInfoRequest {
pub runtime_id: Namespace,
pub consensus_backend: String,
pub consensus_protocol_version: Version,
pub consensus_chain_context: String,
#[cbor(optional)]
pub local_config: BTreeMap<String, cbor::Value>,
}
#[derive(Clone, Debug, cbor::Encode, cbor::Decode)]
pub struct Features {
#[cbor(optional)]
pub schedule_control: Option<FeatureScheduleControl>,
#[cbor(optional)]
pub key_manager_quote_policy_updates: bool,
#[cbor(optional)]
pub key_manager_status_updates: bool,
#[cbor(optional)]
pub key_manager_master_secret_rotation: bool,
#[cbor(optional)]
pub same_block_consensus_validation: bool,
}
impl Default for Features {
fn default() -> Self {
Self {
schedule_control: None,
key_manager_quote_policy_updates: true,
key_manager_status_updates: true,
key_manager_master_secret_rotation: false,
same_block_consensus_validation: true,
}
}
}
#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
pub struct FeatureScheduleControl {
pub initial_batch_size: u32,
}
#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
pub struct RuntimeInfoResponse {
pub protocol_version: Version,
pub runtime_version: Version,
#[cbor(optional)]
pub features: Option<Features>,
}
#[derive(Clone, Debug, PartialEq, Eq, cbor::Encode, cbor::Decode)]
#[cbor(with_default)]
pub enum ExecutionMode {
Execute = 0,
Schedule = 1,
}
impl Default for ExecutionMode {
fn default() -> Self {
Self::Execute
}
}
#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
pub struct CheckTxResult {
pub error: Error,
pub meta: Option<CheckTxMetadata>,
}
#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
pub struct CheckTxMetadata {
#[cbor(optional)]
pub priority: u64,
#[cbor(optional)]
pub sender: Vec<u8>,
#[cbor(optional)]
pub sender_seq: u64,
#[cbor(optional)]
pub sender_state_seq: u64,
}
#[derive(Clone, Copy, Debug, cbor::Encode, cbor::Decode)]
#[repr(u8)]
pub enum EventKind {
Staking = 1,
Registry = 2,
RootHash = 3,
Governance = 4,
}
#[derive(Clone, Debug, cbor::Encode, cbor::Decode)]
#[cbor(no_default)]
pub struct HostFetchConsensusEventsRequest {
pub height: u64,
pub kind: EventKind,
}
#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
pub struct HostFetchConsensusEventsResponse {
pub events: Vec<consensus::Event>,
}
#[derive(Clone, Copy, Debug, cbor::Encode, cbor::Decode)]
#[repr(u8)]
pub enum MessageType {
Invalid = 0,
Request = 1,
Response = 2,
}
impl Default for MessageType {
fn default() -> Self {
Self::Invalid
}
}
#[derive(Debug, Default, cbor::Encode, cbor::Decode)]
pub struct Message {
pub id: u64,
pub message_type: MessageType,
pub body: Body,
}