Skip to main content

iota_types/
messages_grpc.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5use iota_sdk_types::{ObjectId, TransactionDigest, TransactionEffectsDigest, Version};
6use move_core_types::annotated_value::MoveStructLayout;
7use serde::{Deserialize, Serialize};
8
9use crate::{
10    committee::EpochId,
11    crypto::{AuthoritySignInfo, AuthorityStrongQuorumSignInfo},
12    effects::{
13        SignedTransactionEffects, TransactionEffects, TransactionEffectsExtForTesting,
14        TransactionEvents, VerifiedSignedTransactionEffects,
15    },
16    error::IotaError,
17    messages_consensus::SignedAuthorityCapabilitiesV1,
18    object::Object,
19    transaction::{CertifiedTransaction, SenderSignedData, SignedTransaction},
20};
21
22/// Request for validator health information.
23#[derive(Clone, Debug, Default, Serialize, Deserialize)]
24pub struct ValidatorHealthRequest {}
25
26/// Response with validator health metrics.
27#[derive(Clone, Debug, Default, Serialize, Deserialize)]
28pub struct ValidatorHealthResponse {
29    /// Number of in-flight execution transactions from execution scheduler.
30    pub num_inflight_execution_transactions: u64,
31    /// Number of in-flight consensus transactions.
32    pub num_inflight_consensus_transactions: u64,
33    /// Sequence number of the last locally built checkpoint.
34    pub last_locally_built_checkpoint: u64,
35}
36
37#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize)]
38pub enum ObjectInfoRequestKind {
39    /// Request the latest object state.
40    LatestObjectInfo,
41    /// Request a specific version of the object.
42    /// This is used only for debugging purpose and will not work as a generic
43    /// solution since we don't keep around all historic object versions.
44    /// No production code should depend on this kind.
45    PastObjectInfoDebug(Version),
46}
47
48/// Layout generation options -- you can either generate or not generate the
49/// layout.
50#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize)]
51pub enum LayoutGenerationOption {
52    Generate,
53    None,
54}
55
56/// A request for information about an object and optionally its
57/// parent certificate at a specific version.
58#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize)]
59pub struct ObjectInfoRequest {
60    /// The id of the object to retrieve, at the latest version.
61    pub object_id: ObjectId,
62    /// if true return the layout of the object.
63    pub generate_layout: LayoutGenerationOption,
64    /// The type of request, either latest object info or the past.
65    pub request_kind: ObjectInfoRequestKind,
66}
67
68impl ObjectInfoRequest {
69    pub fn past_object_info_debug_request(
70        object_id: ObjectId,
71        version: Version,
72        generate_layout: LayoutGenerationOption,
73    ) -> Self {
74        ObjectInfoRequest {
75            object_id,
76            generate_layout,
77            request_kind: ObjectInfoRequestKind::PastObjectInfoDebug(version),
78        }
79    }
80
81    pub fn latest_object_info_request(
82        object_id: ObjectId,
83        generate_layout: LayoutGenerationOption,
84    ) -> Self {
85        ObjectInfoRequest {
86            object_id,
87            generate_layout,
88            request_kind: ObjectInfoRequestKind::LatestObjectInfo,
89        }
90    }
91}
92
93/// This message provides information about the latest object and its lock.
94#[derive(Debug, Clone, Serialize, Deserialize)]
95pub struct ObjectInfoResponse {
96    /// Value of the requested object in this authority
97    pub object: Object,
98    /// Schema of the Move value inside this object.
99    /// None if the object is a Move package, or the request did not ask for the
100    /// layout
101    pub layout: Option<MoveStructLayout>,
102    /// Transaction the object is locked on in this authority.
103    /// None if the object is not currently locked by this authority.
104    /// This should be only used for debugging purpose, such as from iota-tool.
105    /// No prod clients should rely on it.
106    pub lock_for_debugging: Option<SignedTransaction>,
107}
108
109/// Verified version of `ObjectInfoResponse`. `layout` and `lock_for_debugging`
110/// are skipped because they are not needed and we don't want to verify them.
111#[derive(Debug, Clone)]
112pub struct VerifiedObjectInfoResponse {
113    /// Value of the requested object in this authority
114    pub object: Object,
115}
116
117#[derive(Clone, Debug, Serialize, Deserialize)]
118pub struct TransactionInfoRequest {
119    pub transaction_digest: TransactionDigest,
120}
121
122#[expect(clippy::large_enum_variant)]
123#[derive(Clone, Debug, Serialize, Deserialize)]
124pub enum TransactionStatus {
125    /// Signature over the transaction.
126    Signed(AuthoritySignInfo),
127    /// For executed transaction, we could return an optional certificate
128    /// signature on the transaction (i.e. the signature part of the
129    /// CertifiedTransaction), as well as the signed effects.
130    /// The certificate signature is optional because for transactions executed
131    /// in previous epochs, we won't keep around the certificate signatures.
132    Executed(
133        Option<AuthorityStrongQuorumSignInfo>,
134        SignedTransactionEffects,
135        TransactionEvents,
136    ),
137}
138
139impl TransactionStatus {
140    pub fn into_signed_for_testing(self) -> AuthoritySignInfo {
141        match self {
142            Self::Signed(s) => s,
143            _ => unreachable!("Incorrect response type"),
144        }
145    }
146
147    pub fn into_effects_for_testing(self) -> SignedTransactionEffects {
148        match self {
149            Self::Executed(_, e, _) => e,
150            _ => unreachable!("Incorrect response type"),
151        }
152    }
153}
154
155impl PartialEq for TransactionStatus {
156    fn eq(&self, other: &Self) -> bool {
157        match self {
158            Self::Signed(s1) => match other {
159                Self::Signed(s2) => s1.epoch == s2.epoch,
160                _ => false,
161            },
162            Self::Executed(c1, e1, ev1) => match other {
163                Self::Executed(c2, e2, ev2) => {
164                    c1.as_ref().map(|a| a.epoch) == c2.as_ref().map(|a| a.epoch)
165                        && e1.epoch() == e2.epoch()
166                        && e1.digest() == e2.digest()
167                        && ev1.digest() == ev2.digest()
168                }
169                _ => false,
170            },
171        }
172    }
173}
174
175#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
176pub struct HandleTransactionResponse {
177    pub status: TransactionStatus,
178}
179
180#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
181pub struct TransactionInfoResponse {
182    pub transaction: SenderSignedData,
183    pub status: TransactionStatus,
184}
185
186#[derive(Clone, Debug, Serialize, Deserialize)]
187pub struct SubmitCertificateResponse {
188    /// If transaction is already executed, return same result as
189    /// handle_certificate
190    pub executed: Option<HandleCertificateResponseV1>,
191}
192
193#[derive(Clone, Debug)]
194pub struct VerifiedHandleCertificateResponse {
195    pub signed_effects: VerifiedSignedTransactionEffects,
196    pub events: TransactionEvents,
197}
198
199#[derive(Serialize, Deserialize, Clone, Debug)]
200pub struct SystemStateRequest {
201    // This is needed to make gRPC happy.
202    pub _unused: bool,
203}
204
205/// Response type for version 1 of the handle certificate validator API.
206///
207/// The corresponding version 1 request type allows for a client to request
208/// events as well as input/output objects from a transaction's execution. Given
209/// Validators operate with very aggressive object pruning, the return of
210/// input/output objects is only done immediately after the transaction has been
211/// executed locally on the validator and will not be returned for requests to
212/// previously executed transactions.
213#[derive(Clone, Debug, Serialize, Deserialize)]
214pub struct HandleCertificateResponseV1 {
215    pub signed_effects: SignedTransactionEffects,
216    pub events: Option<TransactionEvents>,
217
218    /// If requested, will include all initial versions of objects modified in
219    /// this transaction. This includes owned objects included as input into
220    /// the transaction as well as the assigned versions of shared objects.
221    // TODO: In the future we may want to include shared objects or child objects which were read
222    //  but not modified during execution.
223    pub input_objects: Option<Vec<Object>>,
224
225    /// If requested, will include all changed objects, including mutated,
226    /// created and unwrapped objects. In other words, all objects that
227    /// still exist in the object state after this transaction.
228    pub output_objects: Option<Vec<Object>>,
229    pub auxiliary_data: Option<Vec<u8>>,
230}
231
232#[derive(Clone, Debug, Serialize, Deserialize)]
233pub struct HandleCertificateRequestV1 {
234    pub certificate: CertifiedTransaction,
235
236    pub include_events: bool,
237    pub include_input_objects: bool,
238    pub include_output_objects: bool,
239    pub include_auxiliary_data: bool,
240}
241
242impl HandleCertificateRequestV1 {
243    pub fn new(certificate: CertifiedTransaction) -> Self {
244        Self {
245            certificate,
246            include_events: false,
247            include_input_objects: false,
248            include_output_objects: false,
249            include_auxiliary_data: false,
250        }
251    }
252
253    pub fn with_events(mut self) -> Self {
254        self.include_events = true;
255        self
256    }
257
258    pub fn with_input_objects(mut self) -> Self {
259        self.include_input_objects = true;
260        self
261    }
262
263    pub fn with_output_objects(mut self) -> Self {
264        self.include_output_objects = true;
265        self
266    }
267
268    pub fn with_auxiliary_data(mut self) -> Self {
269        self.include_auxiliary_data = true;
270        self
271    }
272}
273
274/// Response type for the handle Soft Bundle certificates validator API.
275/// If `wait_for_effects` is true, it is guaranteed that:
276///  - Number of responses will be equal to the number of input transactions.
277///  - The order of the responses matches the order of the input transactions.
278///
279/// Otherwise, `responses` will be empty.
280#[derive(Clone, Debug, Serialize, Deserialize)]
281pub struct HandleSoftBundleCertificatesResponseV1 {
282    pub responses: Vec<HandleCertificateResponseV1>,
283}
284
285/// Soft Bundle request.  See [SIP-19](https://github.com/sui-foundation/sips/blob/main/sips/sip-19.md).
286#[derive(Clone, Debug, Serialize, Deserialize)]
287pub struct HandleSoftBundleCertificatesRequestV1 {
288    pub certificates: Vec<CertifiedTransaction>,
289
290    pub wait_for_effects: bool,
291    pub include_events: bool,
292    pub include_input_objects: bool,
293    pub include_output_objects: bool,
294    pub include_auxiliary_data: bool,
295}
296
297#[derive(Clone, Debug, Serialize, Deserialize)]
298pub struct HandleCapabilityNotificationRequestV1 {
299    pub message: SignedAuthorityCapabilitiesV1,
300}
301
302#[derive(Clone, Debug, Serialize, Deserialize)]
303pub struct HandleCapabilityNotificationResponseV1 {
304    // This is needed to make gRPC happy.
305    pub _unused: bool,
306}
307
308// =========== TransactionDriver types ===========
309
310/// Full executed transaction data returned from validators.
311#[derive(Clone, Debug, Serialize, Deserialize)]
312pub struct ExecutedData {
313    pub effects: TransactionEffects,
314    pub events: Option<TransactionEvents>,
315    pub input_objects: Vec<Object>,
316    pub output_objects: Vec<Object>,
317}
318
319impl Default for ExecutedData {
320    fn default() -> Self {
321        Self {
322            effects: TransactionEffects::new_empty_v1_for_testing(TransactionDigest::default()),
323            events: None,
324            input_objects: Vec::new(),
325            output_objects: Vec::new(),
326        }
327    }
328}
329
330/// Request to query the finality status of one or more previously submitted
331/// transactions.
332#[derive(Clone, Debug, Serialize, Deserialize)]
333pub struct GetTxStatusRequest {
334    pub queries: Vec<TxStatusQuery>,
335}
336
337/// A single transaction status query.
338#[derive(Clone, Debug, Serialize, Deserialize)]
339pub struct TxStatusQuery {
340    pub transaction_digest: TransactionDigest,
341    /// When true, execution details (effects, events, objects) are included
342    /// in the response for this transaction.
343    pub include_details: bool,
344}
345
346/// Streamed status update for ValidatorV2 RPCs (`submit_tx` and
347/// `get_tx_status`). Covers every state a transaction can be in.
348#[derive(Clone, Debug, Serialize, Deserialize)]
349pub enum TxStatusUpdate {
350    /// The transaction passed validation and was submitted to consensus.
351    Submitted,
352    /// The transaction was executed and finalized.
353    Executed {
354        effects_digest: TransactionEffectsDigest,
355        details: Option<Box<ExecutedData>>,
356    },
357    /// The transaction was rejected.
358    Rejected { error: IotaError },
359    /// Transaction status has expired from the cache or timed out.
360    Expired { epoch: EpochId },
361}