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