1use std::collections::BTreeMap;
7
8use serde::{Deserialize, Serialize};
9use strum::AsRefStr;
10use thiserror::Error;
11
12use crate::{
13 base_types::{AuthorityName, EpochId, ObjectRef, TransactionDigest},
14 committee::StakeUnit,
15 crypto::{AuthorityStrongQuorumSignInfo, ConciseAuthorityPublicKeyBytes},
16 effects::{
17 CertifiedTransactionEffects, TransactionEffects, TransactionEvents,
18 VerifiedCertifiedTransactionEffects,
19 },
20 error::IotaError,
21 messages_checkpoint::CheckpointSequenceNumber,
22 object::Object,
23 transaction::Transaction,
24};
25
26pub type QuorumDriverResult = Result<QuorumDriverResponse, QuorumDriverError>;
27
28pub type QuorumDriverEffectsQueueResult =
29 Result<(Transaction, QuorumDriverResponse), (TransactionDigest, QuorumDriverError)>;
30
31pub const NON_RECOVERABLE_ERROR_MSG: &str =
32 "Transaction has non recoverable errors from at least 1/3 of validators";
33
34#[derive(Eq, PartialEq, Clone, Debug, Serialize, Deserialize, Error, Hash, AsRefStr)]
37pub enum QuorumDriverError {
38 #[error("QuorumDriver internal error: {0:?}.")]
39 QuorumDriverInternal(IotaError),
40 #[error("Invalid user signature: {0:?}.")]
41 InvalidUserSignature(IotaError),
42 #[error(
43 "Failed to sign transaction by a quorum of validators because of locked objects: {:?}, retried a conflicting transaction {:?}, success: {:?}",
44 conflicting_txes,
45 retried_tx,
46 retried_tx_success
47 )]
48 ObjectsDoubleUsed {
49 conflicting_txes: BTreeMap<TransactionDigest, (Vec<(AuthorityName, ObjectRef)>, StakeUnit)>,
50 retried_tx: Option<TransactionDigest>,
51 retried_tx_success: Option<bool>,
52 },
53 #[error("Transaction timed out before reaching finality")]
54 TimeoutBeforeFinality,
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
80pub type GroupedErrors = Vec<(IotaError, StakeUnit, Vec<ConciseAuthorityPublicKeyBytes>)>;
81
82#[derive(Serialize, Deserialize, Clone, Debug, schemars::JsonSchema)]
83pub enum ExecuteTransactionRequestType {
84 WaitForEffectsCert,
85 WaitForLocalExecution,
86}
87
88#[derive(Serialize, Deserialize, Clone, Debug)]
89pub enum EffectsFinalityInfo {
90 Certified(AuthorityStrongQuorumSignInfo),
91 Checkpointed(EpochId, CheckpointSequenceNumber),
92}
93
94pub type IsTransactionExecutedLocally = bool;
99
100#[derive(Debug, Clone)]
101pub struct QuorumDriverResponse {
102 pub effects_cert: VerifiedCertifiedTransactionEffects,
103 pub events: Option<TransactionEvents>,
105 pub input_objects: Option<Vec<Object>>,
107 pub output_objects: Option<Vec<Object>>,
109 pub auxiliary_data: Option<Vec<u8>>,
110}
111
112#[derive(Serialize, Deserialize, Clone, Debug)]
113pub struct ExecuteTransactionRequestV1 {
114 pub transaction: Transaction,
115
116 pub include_events: bool,
117 pub include_input_objects: bool,
118 pub include_output_objects: bool,
119 pub include_auxiliary_data: bool,
120}
121
122impl ExecuteTransactionRequestV1 {
123 pub fn new<T: Into<Transaction>>(transaction: T) -> Self {
124 Self {
125 transaction: transaction.into(),
126 include_events: true,
127 include_input_objects: false,
128 include_output_objects: false,
129 include_auxiliary_data: false,
130 }
131 }
132}
133
134#[derive(Serialize, Deserialize, Clone, Debug)]
135pub struct ExecuteTransactionResponseV1 {
136 pub effects: FinalizedEffects,
137
138 pub events: Option<TransactionEvents>,
139 pub input_objects: Option<Vec<Object>>,
141 pub output_objects: Option<Vec<Object>>,
143 pub auxiliary_data: Option<Vec<u8>>,
144}
145
146#[derive(Serialize, Deserialize, Clone, Debug)]
147pub struct FinalizedEffects {
148 pub effects: TransactionEffects,
149 pub finality_info: EffectsFinalityInfo,
150}
151
152impl FinalizedEffects {
153 pub fn new_from_effects_cert(effects_cert: CertifiedTransactionEffects) -> Self {
154 let (data, sig) = effects_cert.into_data_and_sig();
155 Self {
156 effects: data,
157 finality_info: EffectsFinalityInfo::Certified(sig),
158 }
159 }
160
161 pub fn epoch(&self) -> EpochId {
162 match &self.finality_info {
163 EffectsFinalityInfo::Certified(cert) => cert.epoch,
164 EffectsFinalityInfo::Checkpointed(epoch, _) => *epoch,
165 }
166 }
167}