• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

oasisprotocol / oasis-core / #6059

23 May 2025 08:33AM UTC coverage: 47.728% (+0.07%) from 47.66%
#6059

Pull #6197

kostko
go/runtime: Add log manager
Pull Request #6197: go/runtime: Add log manager

19 of 29 new or added lines in 5 files covered. (65.52%)

113 existing lines in 3 files now uncovered.

4579 of 9594 relevant lines covered (47.73%)

1.08 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/runtime/src/host/mod.rs
1
//! Host interface.
2
use async_trait::async_trait;
3
use thiserror::Error;
4

5
use crate::{
6
    common::{crypto::signature::PublicKey, namespace::Namespace},
7
    enclave_rpc,
8
    protocol::Protocol,
9
    storage::mkvs::sync,
10
    types::{self, Body},
11
};
12

13
pub mod bundle_manager;
14
pub mod log_manager;
15
pub mod volume_manager;
16

17
/// Errors.
18
#[derive(Error, Debug)]
19
pub enum Error {
20
    #[error("bad response from host")]
21
    BadResponse,
22

23
    #[error("{0}")]
24
    Host(#[from] types::Error),
25

26
    #[error("{0}")]
27
    Decode(#[from] cbor::DecodeError),
28
}
29

30
/// Transaction submission options.
31
#[derive(Clone, Default, Debug)]
32
pub struct SubmitTxOpts {
33
    /// Target runtime identifier. If not specified, own runtime identifier is used.
34
    pub runtime_id: Option<Namespace>,
35
    /// Whether the call should wait until the transaction is included in a block.
36
    pub wait: bool,
37
    /// Whether the response should include a proof of transaction being included in a block.
38
    pub prove: bool,
39
}
40

41
/// Transaction submission result.
42
#[derive(Clone, Default, Debug)]
43
pub struct TxResult {
44
    /// Transaction output.
45
    pub output: Vec<u8>,
46
    /// Round in which the transaction was executed.
47
    pub round: u64,
48
    /// Order of the transaction in the execution batch.
49
    pub batch_order: u32,
50
    /// Optional inclusion proof.
51
    pub proof: Option<sync::Proof>,
52
}
53

54
/// Notification registration options.
55
#[derive(Clone, Default, Debug)]
56
pub struct RegisterNotifyOpts {
57
    /// Subscribe to runtime block notifications.
58
    pub runtime_block: bool,
59
    /// Subscribe to runtime event notifications.
60
    pub runtime_event: Vec<Vec<u8>>,
61
}
62

63
/// Interface to the (untrusted) host node.
64
#[async_trait]
65
pub trait Host: Send + Sync {
66
    /// Returns the identity of the host node.
67
    async fn identity(&self) -> Result<PublicKey, Error>;
68

69
    /// Submit a transaction.
70
    async fn submit_tx(&self, data: Vec<u8>, opts: SubmitTxOpts)
71
        -> Result<Option<TxResult>, Error>;
72

73
    /// Register for receiving notifications.
74
    async fn register_notify(&self, opts: RegisterNotifyOpts) -> Result<(), Error>;
75

76
    /// Bundle manager interface.
77
    fn bundle_manager(&self) -> &dyn bundle_manager::BundleManager;
78

79
    /// Volume manager interface.
80
    fn volume_manager(&self) -> &dyn volume_manager::VolumeManager;
81

82
    /// Log manager interface.
83
    fn log_manager(&self) -> &dyn log_manager::LogManager;
84
}
85

86
#[async_trait]
87
impl Host for Protocol {
88
    async fn identity(&self) -> Result<PublicKey, Error> {
×
89
        match self.call_host_async(Body::HostIdentityRequest {}).await? {
×
90
            Body::HostIdentityResponse { node_id } => Ok(node_id),
×
91
            _ => Err(Error::BadResponse),
×
92
        }
93
    }
94

95
    async fn submit_tx(
96
        &self,
97
        data: Vec<u8>,
98
        opts: SubmitTxOpts,
99
    ) -> Result<Option<TxResult>, Error> {
100
        match self
×
101
            .call_host_async(Body::HostSubmitTxRequest {
×
102
                runtime_id: opts.runtime_id.unwrap_or_else(|| self.get_runtime_id()),
×
103
                data,
×
104
                wait: opts.wait,
×
105
                prove: opts.prove,
×
106
            })
107
            .await?
×
108
        {
109
            Body::HostSubmitTxResponse {
×
110
                output,
111
                round,
112
                batch_order,
113
                proof,
114
            } => {
115
                if opts.wait {
×
116
                    Ok(Some(TxResult {
×
117
                        output,
×
118
                        round,
119
                        batch_order,
120
                        proof,
×
121
                    }))
122
                } else {
123
                    // If we didn't wait for inclusion then there is no result.
124
                    Ok(None)
×
125
                }
126
            }
127
            _ => Err(Error::BadResponse),
×
128
        }
129
    }
130

131
    async fn register_notify(&self, opts: RegisterNotifyOpts) -> Result<(), Error> {
×
132
        match self
×
133
            .call_host_async(Body::HostRegisterNotifyRequest {
×
134
                runtime_block: opts.runtime_block,
×
135
                runtime_event: match opts.runtime_event {
136
                    tags if tags.is_empty() => None,
×
137
                    tags => Some(types::RegisterNotifyRuntimeEvent { tags }),
×
138
                },
139
            })
140
            .await?
×
141
        {
142
            Body::Empty {} => Ok(()),
×
143
            _ => Err(Error::BadResponse),
×
144
        }
145
    }
146

147
    fn bundle_manager(&self) -> &dyn bundle_manager::BundleManager {
×
148
        self
149
    }
150

151
    fn volume_manager(&self) -> &dyn volume_manager::VolumeManager {
×
152
        self
153
    }
154

NEW
155
    fn log_manager(&self) -> &dyn log_manager::LogManager {
×
156
        self
157
    }
158
}
159

160
/// Wrapper to call the host via local RPC.
161
pub(super) async fn host_rpc_call<Rq: cbor::Encode, Rs: cbor::Decode>(
×
162
    protocol: &Protocol,
163
    endpoint: &str,
164
    method: &str,
165
    args: Rq,
166
) -> Result<Rs, Error> {
167
    match protocol
×
168
        .call_host_async(Body::HostRPCCallRequest {
×
169
            endpoint: endpoint.to_string(),
×
170
            request_id: 0,
×
171
            request: cbor::to_vec(enclave_rpc::types::Request {
×
172
                method: method.to_string(),
×
173
                args: cbor::to_value(args),
×
174
            }),
175
            kind: enclave_rpc::types::Kind::LocalQuery,
×
176
            nodes: vec![],
×
177
        })
178
        .await?
×
179
    {
180
        Body::HostRPCCallResponse { response, .. } => Ok(cbor::from_slice(&response)?),
×
181
        _ => Err(Error::BadResponse),
×
182
    }
183
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc