sui_types/
quorum_driver_types.rs

1// Copyright (c) 2021, Facebook, Inc. and its affiliates
2// Copyright (c) Mysten Labs, Inc.
3// SPDX-License-Identifier: Apache-2.0
4
5use std::collections::BTreeMap;
6use std::time::Duration;
7
8use crate::base_types::{AuthorityName, EpochId, ObjectRef, TransactionDigest};
9use crate::committee::StakeUnit;
10use crate::crypto::{AuthorityStrongQuorumSignInfo, ConciseAuthorityPublicKeyBytes};
11use crate::effects::{
12    CertifiedTransactionEffects, TransactionEffects, TransactionEvents,
13    VerifiedCertifiedTransactionEffects,
14};
15use crate::error::{ErrorCategory, SuiError};
16use crate::messages_checkpoint::CheckpointSequenceNumber;
17use crate::object::Object;
18use crate::transaction::{Transaction, VerifiedTransaction};
19use serde::{Deserialize, Serialize};
20use strum::AsRefStr;
21use thiserror::Error;
22
23pub type QuorumDriverResult = Result<QuorumDriverResponse, QuorumDriverError>;
24
25pub type QuorumDriverEffectsQueueResult =
26    Result<(Transaction, QuorumDriverResponse), (TransactionDigest, QuorumDriverError)>;
27
28pub const NON_RECOVERABLE_ERROR_MSG: &str =
29    "Transaction has non recoverable errors from at least 1/3 of validators";
30
31/// Client facing errors regarding transaction submission via Quorum Driver.
32/// Every invariant needs detailed documents to instruct client handling.
33#[derive(Eq, PartialEq, Clone, Debug, Error, Hash, AsRefStr)]
34pub enum QuorumDriverError {
35    #[error("QuorumDriver internal error: {0}.")]
36    QuorumDriverInternalError(SuiError),
37    #[error("Invalid user signature: {0}.")]
38    InvalidUserSignature(SuiError),
39    #[error(
40        "Failed to sign transaction by a quorum of validators because of locked objects: {conflicting_txes:?}"
41    )]
42    ObjectsDoubleUsed {
43        conflicting_txes: BTreeMap<TransactionDigest, (Vec<(AuthorityName, ObjectRef)>, StakeUnit)>,
44    },
45    #[error("Transaction timed out before reaching finality")]
46    TimeoutBeforeFinality,
47    #[error(
48        "Transaction timed out before reaching finality. Last recorded retriable error: {last_error}"
49    )]
50    TimeoutBeforeFinalityWithErrors {
51        last_error: String,
52        attempts: u32,
53        timeout: Duration,
54    },
55    #[error(
56        "Transaction failed to reach finality with transient error after {total_attempts} attempts."
57    )]
58    FailedWithTransientErrorAfterMaximumAttempts { total_attempts: u32 },
59    #[error("{NON_RECOVERABLE_ERROR_MSG}: {errors:?}.")]
60    NonRecoverableTransactionError { errors: GroupedErrors },
61    #[error(
62        "Transaction is not processed because {overloaded_stake} of validators by stake are overloaded with certificates pending execution."
63    )]
64    SystemOverload {
65        overloaded_stake: StakeUnit,
66        errors: GroupedErrors,
67    },
68    #[error("Transaction is already finalized but with different user signatures")]
69    TxAlreadyFinalizedWithDifferentUserSignatures,
70    #[error(
71        "Transaction is not processed because {overload_stake} of validators are overloaded and asked client to retry after {retry_after_secs}."
72    )]
73    SystemOverloadRetryAfter {
74        overload_stake: StakeUnit,
75        errors: GroupedErrors,
76        retry_after_secs: u64,
77    },
78
79    // Wrapped error from Transaction Driver.
80    #[error("Transaction processing failed. Details: {details}")]
81    TransactionFailed {
82        category: ErrorCategory,
83        details: String,
84    },
85}
86
87pub type GroupedErrors = Vec<(SuiError, StakeUnit, Vec<ConciseAuthorityPublicKeyBytes>)>;
88
89#[derive(Serialize, Deserialize, Clone, Debug, schemars::JsonSchema)]
90pub enum ExecuteTransactionRequestType {
91    WaitForEffectsCert,
92    WaitForLocalExecution,
93}
94
95#[derive(Debug)]
96pub enum TransactionType {
97    SingleWriter, // Txes that only use owned objects and/or immutable objects
98    SharedObject, // Txes that use at least one shared object
99}
100
101/// Proof of finality of transaction effects.
102#[derive(Serialize, Deserialize, Clone, Debug)]
103pub enum EffectsFinalityInfo {
104    /// Effects are certified by a quorum of validators.
105    Certified(AuthorityStrongQuorumSignInfo),
106
107    /// Effects are included in a checkpoint.
108    Checkpointed(EpochId, CheckpointSequenceNumber),
109
110    /// A quorum of validators have acknowledged effects.
111    QuorumExecuted(EpochId),
112}
113
114/// When requested to execute a transaction with WaitForLocalExecution,
115/// TransactionOrchestrator attempts to execute this transaction locally
116/// after it is finalized. This value represents whether the transaction
117/// is confirmed to be executed on this node before the response returns.
118pub type IsTransactionExecutedLocally = bool;
119
120#[derive(Serialize, Deserialize, Clone, Debug)]
121pub enum ExecuteTransactionResponse {
122    EffectsCert(
123        Box<(
124            FinalizedEffects,
125            TransactionEvents,
126            IsTransactionExecutedLocally,
127        )>,
128    ),
129}
130
131#[derive(Clone, Debug)]
132pub struct QuorumDriverRequest {
133    pub transaction: VerifiedTransaction,
134}
135
136#[derive(Debug, Clone)]
137pub struct QuorumDriverResponse {
138    pub effects_cert: VerifiedCertifiedTransactionEffects,
139    // pub events: TransactionEvents,
140    pub events: Option<TransactionEvents>,
141    // Input objects will only be populated in the happy path
142    pub input_objects: Option<Vec<Object>>,
143    // Output objects will only be populated in the happy path
144    pub output_objects: Option<Vec<Object>>,
145    pub auxiliary_data: Option<Vec<u8>>,
146}
147
148#[derive(Serialize, Deserialize, Clone, Debug)]
149pub struct ExecuteTransactionRequestV3 {
150    pub transaction: Transaction,
151
152    pub include_events: bool,
153    pub include_input_objects: bool,
154    pub include_output_objects: bool,
155    pub include_auxiliary_data: bool,
156}
157
158impl ExecuteTransactionRequestV3 {
159    pub fn new_v2<T: Into<Transaction>>(transaction: T) -> Self {
160        Self {
161            transaction: transaction.into(),
162            include_events: true,
163            include_input_objects: false,
164            include_output_objects: false,
165            include_auxiliary_data: false,
166        }
167    }
168}
169
170#[derive(Serialize, Deserialize, Clone, Debug)]
171pub struct ExecuteTransactionResponseV3 {
172    pub effects: FinalizedEffects,
173
174    pub events: Option<TransactionEvents>,
175    // Input objects will only be populated in the happy path
176    pub input_objects: Option<Vec<Object>>,
177    // Output objects will only be populated in the happy path
178    pub output_objects: Option<Vec<Object>>,
179    pub auxiliary_data: Option<Vec<u8>>,
180}
181
182#[derive(Serialize, Deserialize, Clone, Debug)]
183pub struct FinalizedEffects {
184    pub effects: TransactionEffects,
185    pub finality_info: EffectsFinalityInfo,
186}
187
188impl FinalizedEffects {
189    pub fn new_from_effects_cert(effects_cert: CertifiedTransactionEffects) -> Self {
190        let (data, sig) = effects_cert.into_data_and_sig();
191        Self {
192            effects: data,
193            finality_info: EffectsFinalityInfo::Certified(sig),
194        }
195    }
196
197    pub fn epoch(&self) -> EpochId {
198        match &self.finality_info {
199            EffectsFinalityInfo::Certified(cert) => cert.epoch,
200            EffectsFinalityInfo::Checkpointed(epoch, _) => *epoch,
201            EffectsFinalityInfo::QuorumExecuted(epoch) => *epoch,
202        }
203    }
204
205    pub fn data(&self) -> &TransactionEffects {
206        &self.effects
207    }
208}