Skip to main content

thruput_trace/
db_conflict.rs

1// -*-Rust-*-
2// Generated Code: DO NOT CHECK IN
3
4// Generated from xdrc commit: 6ab835b07c234abb4b0b50b61d687904727a4f32
5
6// clang-format off
7
8#![allow(non_camel_case_types)]
9#![allow(non_snake_case)]
10#![allow(non_upper_case_globals)]
11#![allow(unused_imports)]
12#![allow(dead_code)]
13#![allow(unused_variables)]
14#![allow(clippy::unnecessary_cast)]
15
16use crate::*;
17use core::option::Option;
18use core::ops::{Deref, DerefMut};
19
20#[cfg(feature = "std")]
21use std::io::{Read, Write};
22use xdrs::*;
23
24
25#[cfg(feature = "serde")]
26use ::serde::{{Serialize, Deserialize}};
27
28
29
30// clang-format on
31
32/// Reason a storage delta could not be applied during two-phase commit.
33/// These are the nondeterministic failures of try_push_new_subtransaction:
34/// any of them causes ExecResultTxNonDeterministicError, and the transaction
35/// is excluded from the block. Codes are intentionally coarse; finer-grained
36/// detail may be added later behind a debug-only extension.
37#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
38#[cfg_attr(feature = "serde", serde(transparent))]
39#[derive(ReadXDR, WriteXDR, ConstXDRSize)]
40#[derive(schemars::JsonSchema)]
41#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
42#[derive(Copy)]
43#[repr(transparent)]
44pub struct DbConflictCode(pub i32);
45
46impl DbConflictCode {
47    /// Exclusive-lock collision: the key is exclusively locked by another
48    /// transaction (committed or concurrent), an exclusive lock could not be
49    /// acquired because other transactions hold the key, or an exclusive-lock
50    /// flag was used on a key type that does not support it.
51    pub const ExclusiveLockDenied: Self = Self(0);
52
53    /// Two transactions created different item types at the same key.
54    pub const TypeMismatch: Self = Self(1);
55
56    /// Two transactions wrote irreconcilable values of the same type at the
57    /// same key: different bytestrings, different nnint base values,
58    /// different auth-data bases, or different contract / deployment hashes.
59    pub const ValueMismatch: Self = Self(2);
60
61    /// A nonnegative int would go below zero given the deltas in this block.
62    /// A native-token balance that cannot cover its debits reports
63    /// InsufficientFunds instead.
64    pub const BoundsExceeded: Self = Self(3);
65
66    /// Integer overflow combining deltas on a nonnegative int or balance.
67    pub const Overflow: Self = Self(4);
68
69    /// Replay-protection conflict: uniquifier expired, already consumed (in
70    /// a prior block or by a concurrent transaction), or consumed twice by
71    /// this transaction.
72    pub const ReplayProtection: Self = Self(5);
73
74    /// A retrocausal queue already has a consumer in this block.
75    pub const QueueConsumer: Self = Self(6);
76
77    /// A per-item capacity limit was hit: replay-cache active heights or
78    /// nonces, retrocausal-queue block entries, or auth signer slots.
79    pub const CapacityExceeded: Self = Self(7);
80
81    /// The native-token balance at the diagnostic's address cannot cover the
82    /// debits in this block, or a newly created balance item cannot cover
83    /// its own storage cost. Storage written under a contract's address is
84    /// charged to that contract's balance, so a deployment reports this at
85    /// the new contract's address when it holds no native tokens.
86    pub const InsufficientFunds: Self = Self(8);
87
88    /// An auth-data change would register a public key in a slot while
89    /// another slot of the same address already holds that key, whether
90    /// committed or set by the same change. The table would count one
91    /// key's weight twice, so the change is refused.
92    pub const DuplicateSigner: Self = Self(9);
93}
94impl From<i32> for DbConflictCode {
95    fn from(v: i32) -> Self {
96        Self(v)
97    }
98}
99#[cfg(feature = "std")]
100impl core::fmt::Display for DbConflictCode {
101    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
102        match self.0 {
103            x if x == Self::ExclusiveLockDenied.0 => {
104                write!(f, "DbConflictCode::ExclusiveLockDenied")
105            },
106            x if x == Self::TypeMismatch.0 => {
107                write!(f, "DbConflictCode::TypeMismatch")
108            },
109            x if x == Self::ValueMismatch.0 => {
110                write!(f, "DbConflictCode::ValueMismatch")
111            },
112            x if x == Self::BoundsExceeded.0 => {
113                write!(f, "DbConflictCode::BoundsExceeded")
114            },
115            x if x == Self::Overflow.0 => {
116                write!(f, "DbConflictCode::Overflow")
117            },
118            x if x == Self::ReplayProtection.0 => {
119                write!(f, "DbConflictCode::ReplayProtection")
120            },
121            x if x == Self::QueueConsumer.0 => {
122                write!(f, "DbConflictCode::QueueConsumer")
123            },
124            x if x == Self::CapacityExceeded.0 => {
125                write!(f, "DbConflictCode::CapacityExceeded")
126            },
127            x if x == Self::InsufficientFunds.0 => {
128                write!(f, "DbConflictCode::InsufficientFunds")
129            },
130            x if x == Self::DuplicateSigner.0 => {
131                write!(f, "DbConflictCode::DuplicateSigner")
132            },
133            _ => {
134                write!(f, "DbConflictCode({})", self.0)
135            }
136        }
137    }
138}
139
140
141/// How much conflict diagnostic detail try_push_new_subtransaction reports
142/// on failure. Selected by the database from the block's execution mode:
143/// proposal blocks report First (release builds) or All (debug builds);
144/// validation and viewing blocks report None.
145#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
146#[cfg_attr(feature = "serde", serde(transparent))]
147#[derive(ReadXDR, WriteXDR, ConstXDRSize)]
148#[derive(schemars::JsonSchema)]
149#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
150#[derive(Copy)]
151#[repr(transparent)]
152pub struct DbDiagnosticLevel(pub i32);
153
154impl DbDiagnosticLevel {
155    /// No diagnostics (validation / viewing; previous behavior).
156    pub const kDbDiagnosticNone: Self = Self(0);
157
158    /// Report only the first conflict encountered (proposal, release builds).
159    pub const kDbDiagnosticFirst: Self = Self(1);
160
161    /// Report a best-effort list of all conflicting deltas in the batch
162    /// (proposal, debug builds — SDK testing).
163    pub const kDbDiagnosticAll: Self = Self(2);
164}
165impl From<i32> for DbDiagnosticLevel {
166    fn from(v: i32) -> Self {
167        Self(v)
168    }
169}
170#[cfg(feature = "std")]
171impl core::fmt::Display for DbDiagnosticLevel {
172    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
173        match self.0 {
174            x if x == Self::kDbDiagnosticNone.0 => {
175                write!(f, "DbDiagnosticLevel::kDbDiagnosticNone")
176            },
177            x if x == Self::kDbDiagnosticFirst.0 => {
178                write!(f, "DbDiagnosticLevel::kDbDiagnosticFirst")
179            },
180            x if x == Self::kDbDiagnosticAll.0 => {
181                write!(f, "DbDiagnosticLevel::kDbDiagnosticAll")
182            },
183            _ => {
184                write!(f, "DbDiagnosticLevel({})", self.0)
185            }
186        }
187    }
188}
189
190
191/// One conflicting storage op. Fixed-size: `ContractAddress[32]` plus a
192/// fixed-size StorageKey plus the code — no heap allocation.
193#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
194#[derive(ReadXDR, WriteXDR, ConstXDRSize)]
195#[derive(schemars::JsonSchema)]
196#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
197#[repr(C)]
198pub struct DbConflictDiagnostic {
199    pub addrkey: AddressAndKey,
200    pub code: DbConflictCode,
201}
202
203/// Conflict diagnostics attached to a failed try_push_new_subtransaction.
204/// The discriminant is the DbDiagnosticLevel the database selected from
205/// the block's execution mode, so the variable-length arm is only ever
206/// constructed in kDbDiagnosticAll mode (debug-build proposals); prod
207/// levels are allocation-free by construction.
208#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
209#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
210#[derive(ReadXDR, WriteXDR, ConstXDRSize)]
211#[derive(schemars::JsonSchema)]
212#[repr(i32)]
213#[non_exhaustive]
214pub enum DbConflictResult {
215    // case kDbDiagnosticNone:
216    //   void;
217    kDbDiagnosticNone = DbDiagnosticLevel::kDbDiagnosticNone.0 as i32,
218    // case kDbDiagnosticFirst:
219    //   DbConflictDiagnostic first;
220    kDbDiagnosticFirst { first: DbConflictDiagnostic } = DbDiagnosticLevel::kDbDiagnosticFirst.0 as i32,
221    // case kDbDiagnosticAll:
222    //   VecM<DbConflictDiagnostic> conflicts;
223    kDbDiagnosticAll { conflicts: VecM<DbConflictDiagnostic> } = DbDiagnosticLevel::kDbDiagnosticAll.0 as i32,
224    
225}
226
227/// Reason the executor refused a transaction's contract attachments
228/// (Transaction.contracts_to_deploy) at proposal time. Any of them drops the
229/// transaction from the proposal; none is a contract fault. The RV32 codes
230/// name which check of the artifact failed, so an author can tell a
231/// toolchain/node mismatch from an oversized or corrupt build.
232#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
233#[cfg_attr(feature = "serde", serde(transparent))]
234#[derive(ReadXDR, WriteXDR, ConstXDRSize)]
235#[derive(schemars::JsonSchema)]
236#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
237#[derive(Copy)]
238#[repr(transparent)]
239pub struct ContractRejectCode(pub i32);
240
241impl ContractRejectCode {
242    /// The transaction attaches more contracts than the chain's
243    /// max_new_contracts_per_tx permits.
244    pub const ContractRejectTooMany: Self = Self(0);
245
246    /// The contract blob exceeds the chain's max_contract_size_bytes.
247    pub const ContractRejectBlobTooLarge: Self = Self(1);
248
249    /// The attachment is not an RV32 contract. Native contracts are registered
250    /// at genesis; RV32 is the only deployable type.
251    pub const ContractRejectNotDeployable: Self = Self(2);
252
253    /// The same contract is attached more than once.
254    pub const ContractRejectDuplicate: Self = Self(3);
255
256    /// The blob is not a readable RV32 artifact: too short, wrong magic, wrong
257    /// header size, or its length disagrees with the section sizes the header
258    /// declares.
259    pub const ContractRejectMalformedArtifact: Self = Self(4);
260
261    /// The artifact's format version is not the one this node reads.
262    pub const ContractRejectUnsupportedFormat: Self = Self(5);
263
264    /// The artifact's VM profile, flags, entry ABI, or syscall ABI is not one
265    /// this node runs.
266    pub const ContractRejectUnsupportedAbi: Self = Self(6);
267
268    /// The gas schedule (version, digest) stamped into the artifact is not one
269    /// the node accepts: the artifact was lowered by a toolchain whose gas
270    /// schedule differs from the node's.
271    pub const ContractRejectGasScheduleMismatch: Self = Self(7);
272
273    /// The declared guest memory exceeds the chain's max_rv32_memory_bytes.
274    pub const ContractRejectMemoryTooLarge: Self = Self(8);
275
276    /// The code section is empty or exceeds the chain's max_rv32_code_bytes.
277    pub const ContractRejectCodeSizeInvalid: Self = Self(9);
278
279    /// The initial memory image does not fit in the declared guest memory, or
280    /// an empty image declares a nonzero load address.
281    pub const ContractRejectInitialMemoryInvalid: Self = Self(10);
282
283    /// A section's bytes do not match the SHA-256 digest the header records.
284    pub const ContractRejectDigestMismatch: Self = Self(11);
285
286    /// The code does not translate: it contains an unsupported or malformed
287    /// instruction.
288    pub const ContractRejectInvalidProgram: Self = Self(12);
289}
290impl From<i32> for ContractRejectCode {
291    fn from(v: i32) -> Self {
292        Self(v)
293    }
294}
295#[cfg(feature = "std")]
296impl core::fmt::Display for ContractRejectCode {
297    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
298        match self.0 {
299            x if x == Self::ContractRejectTooMany.0 => {
300                write!(f, "ContractRejectCode::ContractRejectTooMany")
301            },
302            x if x == Self::ContractRejectBlobTooLarge.0 => {
303                write!(f, "ContractRejectCode::ContractRejectBlobTooLarge")
304            },
305            x if x == Self::ContractRejectNotDeployable.0 => {
306                write!(f, "ContractRejectCode::ContractRejectNotDeployable")
307            },
308            x if x == Self::ContractRejectDuplicate.0 => {
309                write!(f, "ContractRejectCode::ContractRejectDuplicate")
310            },
311            x if x == Self::ContractRejectMalformedArtifact.0 => {
312                write!(f, "ContractRejectCode::ContractRejectMalformedArtifact")
313            },
314            x if x == Self::ContractRejectUnsupportedFormat.0 => {
315                write!(f, "ContractRejectCode::ContractRejectUnsupportedFormat")
316            },
317            x if x == Self::ContractRejectUnsupportedAbi.0 => {
318                write!(f, "ContractRejectCode::ContractRejectUnsupportedAbi")
319            },
320            x if x == Self::ContractRejectGasScheduleMismatch.0 => {
321                write!(f, "ContractRejectCode::ContractRejectGasScheduleMismatch")
322            },
323            x if x == Self::ContractRejectMemoryTooLarge.0 => {
324                write!(f, "ContractRejectCode::ContractRejectMemoryTooLarge")
325            },
326            x if x == Self::ContractRejectCodeSizeInvalid.0 => {
327                write!(f, "ContractRejectCode::ContractRejectCodeSizeInvalid")
328            },
329            x if x == Self::ContractRejectInitialMemoryInvalid.0 => {
330                write!(f, "ContractRejectCode::ContractRejectInitialMemoryInvalid")
331            },
332            x if x == Self::ContractRejectDigestMismatch.0 => {
333                write!(f, "ContractRejectCode::ContractRejectDigestMismatch")
334            },
335            x if x == Self::ContractRejectInvalidProgram.0 => {
336                write!(f, "ContractRejectCode::ContractRejectInvalidProgram")
337            },
338            _ => {
339                write!(f, "ContractRejectCode({})", self.0)
340            }
341        }
342    }
343}
344
345
346/// The first contract attachment the executor refused.
347#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
348#[derive(ReadXDR, WriteXDR, ConstXDRSize)]
349#[derive(schemars::JsonSchema)]
350#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
351#[repr(C)]
352pub struct ContractRejectDiagnostic {
353    /// Position in Transaction.contracts_to_deploy of the refused contract.
354    /// For ContractRejectTooMany, the first position past the limit.
355    pub contract_index: u32,
356    pub code: ContractRejectCode,
357}
358
359#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
360#[cfg_attr(feature = "serde", serde(transparent))]
361#[derive(ReadXDR, WriteXDR, ConstXDRSize)]
362#[derive(schemars::JsonSchema)]
363#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
364#[derive(Copy)]
365#[repr(transparent)]
366pub struct TxFailureKind(pub i32);
367
368impl TxFailureKind {
369    /// Two-phase commit could not apply the transaction's storage deltas.
370    pub const TxFailureDbConflict: Self = Self(0);
371
372    /// The executor refused a contract attachment before execution.
373    pub const TxFailureContractRejected: Self = Self(1);
374}
375impl From<i32> for TxFailureKind {
376    fn from(v: i32) -> Self {
377        Self(v)
378    }
379}
380#[cfg(feature = "std")]
381impl core::fmt::Display for TxFailureKind {
382    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
383        match self.0 {
384            x if x == Self::TxFailureDbConflict.0 => {
385                write!(f, "TxFailureKind::TxFailureDbConflict")
386            },
387            x if x == Self::TxFailureContractRejected.0 => {
388                write!(f, "TxFailureKind::TxFailureContractRejected")
389            },
390            _ => {
391                write!(f, "TxFailureKind({})", self.0)
392            }
393        }
394    }
395}
396
397
398#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
399#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
400#[derive(ReadXDR, WriteXDR, ConstXDRSize)]
401#[derive(schemars::JsonSchema)]
402#[repr(i32)]
403#[non_exhaustive]
404pub enum TxFailureCause {
405    // case TxFailureDbConflict:
406    //   DbConflictDiagnostic conflict;
407    TxFailureDbConflict { conflict: DbConflictDiagnostic } = TxFailureKind::TxFailureDbConflict.0 as i32,
408    // case TxFailureContractRejected:
409    //   ContractRejectDiagnostic contract;
410    TxFailureContractRejected { contract: ContractRejectDiagnostic } = TxFailureKind::TxFailureContractRejected.0 as i32,
411    
412}
413
414/// Best-effort diagnostic for a transaction the proposer excluded from a
415/// proposal: the executing block height of the failed attempt plus why it
416/// failed -- the first conflicting storage op the database reported during
417/// two-phase commit, or the first contract attachment the executor refused.
418/// Fixed-size by construction; the wire and caches carry exactly one
419/// diagnostic per failure to bound memory end to end.
420#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
421#[derive(ReadXDR, WriteXDR, ConstXDRSize)]
422#[derive(schemars::JsonSchema)]
423#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
424#[repr(C)]
425pub struct TxFailureDiagnostic {
426    pub attempt_height: BlockHeight,
427    pub cause: TxFailureCause,
428}
429
430
431//
432// XDR internals below this point
433//
434
435impl DbConflictResult {
436    #[allow(clippy::match_single_binding)]
437    pub fn level(&self) -> DbDiagnosticLevel {
438        match self {
439            
440            _ => (unsafe { *(self as *const Self as *const i32) }).into(),
441        }
442    }
443}
444
445impl TxFailureCause {
446    #[allow(clippy::match_single_binding)]
447    pub fn kind(&self) -> TxFailureKind {
448        match self {
449            
450            _ => (unsafe { *(self as *const Self as *const i32) }).into(),
451        }
452    }
453}
454
455