1use 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#[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 #[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, SharedObject, }
100
101#[derive(Serialize, Deserialize, Clone, Debug)]
103pub enum EffectsFinalityInfo {
104 Certified(AuthorityStrongQuorumSignInfo),
106
107 Checkpointed(EpochId, CheckpointSequenceNumber),
109
110 QuorumExecuted(EpochId),
112}
113
114pub 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: Option<TransactionEvents>,
141 pub input_objects: Option<Vec<Object>>,
143 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 pub input_objects: Option<Vec<Object>>,
177 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}