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 #[error(
87 "Transaction is already being processed in transaction orchestrator (most likely by quorum driver), wait for results"
88 )]
89 PendingExecutionInTransactionOrchestrator,
90}
91
92pub type GroupedErrors = Vec<(SuiError, StakeUnit, Vec<ConciseAuthorityPublicKeyBytes>)>;
93
94#[derive(Serialize, Deserialize, Clone, Debug, schemars::JsonSchema)]
95pub enum ExecuteTransactionRequestType {
96 WaitForEffectsCert,
97 WaitForLocalExecution,
98}
99
100#[derive(Debug)]
101pub enum TransactionType {
102 SingleWriter, SharedObject, }
105
106#[derive(Serialize, Deserialize, Clone, Debug)]
108pub enum EffectsFinalityInfo {
109 Certified(AuthorityStrongQuorumSignInfo),
111
112 Checkpointed(EpochId, CheckpointSequenceNumber),
114
115 QuorumExecuted(EpochId),
117}
118
119pub type IsTransactionExecutedLocally = bool;
124
125#[derive(Serialize, Deserialize, Clone, Debug)]
126pub enum ExecuteTransactionResponse {
127 EffectsCert(
128 Box<(
129 FinalizedEffects,
130 TransactionEvents,
131 IsTransactionExecutedLocally,
132 )>,
133 ),
134}
135
136#[derive(Clone, Debug)]
137pub struct QuorumDriverRequest {
138 pub transaction: VerifiedTransaction,
139}
140
141#[derive(Debug, Clone)]
142pub struct QuorumDriverResponse {
143 pub effects_cert: VerifiedCertifiedTransactionEffects,
144 pub events: Option<TransactionEvents>,
146 pub input_objects: Option<Vec<Object>>,
148 pub output_objects: Option<Vec<Object>>,
150 pub auxiliary_data: Option<Vec<u8>>,
151}
152
153#[derive(Serialize, Deserialize, Clone, Debug)]
154pub struct ExecuteTransactionRequestV3 {
155 pub transaction: Transaction,
156
157 pub include_events: bool,
158 pub include_input_objects: bool,
159 pub include_output_objects: bool,
160 pub include_auxiliary_data: bool,
161}
162
163impl ExecuteTransactionRequestV3 {
164 pub fn new_v2<T: Into<Transaction>>(transaction: T) -> Self {
165 Self {
166 transaction: transaction.into(),
167 include_events: true,
168 include_input_objects: false,
169 include_output_objects: false,
170 include_auxiliary_data: false,
171 }
172 }
173}
174
175#[derive(Serialize, Deserialize, Clone, Debug)]
176pub struct ExecuteTransactionResponseV3 {
177 pub effects: FinalizedEffects,
178
179 pub events: Option<TransactionEvents>,
180 pub input_objects: Option<Vec<Object>>,
182 pub output_objects: Option<Vec<Object>>,
184 pub auxiliary_data: Option<Vec<u8>>,
185}
186
187#[derive(Serialize, Deserialize, Clone, Debug)]
188pub struct FinalizedEffects {
189 pub effects: TransactionEffects,
190 pub finality_info: EffectsFinalityInfo,
191}
192
193impl FinalizedEffects {
194 pub fn new_from_effects_cert(effects_cert: CertifiedTransactionEffects) -> Self {
195 let (data, sig) = effects_cert.into_data_and_sig();
196 Self {
197 effects: data,
198 finality_info: EffectsFinalityInfo::Certified(sig),
199 }
200 }
201
202 pub fn epoch(&self) -> EpochId {
203 match &self.finality_info {
204 EffectsFinalityInfo::Certified(cert) => cert.epoch,
205 EffectsFinalityInfo::Checkpointed(epoch, _) => *epoch,
206 EffectsFinalityInfo::QuorumExecuted(epoch) => *epoch,
207 }
208 }
209
210 pub fn data(&self) -> &TransactionEffects {
211 &self.effects
212 }
213}