use thruput_sys::FFIDataBuffer;
use thruput_xdr::exec_result::ExecResult;
pub use thruput_trace::db_conflict::{
DbConflictCode, DbConflictDiagnostic, DbConflictResult,
};
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum TryCommitResult {
Ok,
TxDeterministicError,
TxRootFrameReverted,
TxNonDeterministicError(DbConflictResult),
FailedGasSponsorship,
TxValidationFailure,
SystemError,
Unrecoverable,
}
impl TryCommitResult {
pub(crate) fn from_ffi(
result_code: i32,
serialized_conflict: &FFIDataBuffer,
) -> Self {
match result_code {
x if x == ExecResult::ExecResultOK.0 => Self::Ok,
x if x == ExecResult::ExecResultTxDeterministicError.0 => {
Self::TxDeterministicError
}
x if x == ExecResult::ExecResultTxRootFrameReverted.0 => {
Self::TxRootFrameReverted
}
x if x == ExecResult::ExecResultTxNonDeterministicError.0 => {
Self::TxNonDeterministicError(decode_conflict(
serialized_conflict,
))
}
x if x == ExecResult::ExecResultFailedGasSponsorship.0 => {
Self::FailedGasSponsorship
}
x if x == ExecResult::ExecResultTxValidationFailure.0 => {
Self::TxValidationFailure
}
x if x == ExecResult::ExecResultSystemError.0 => Self::SystemError,
x if x == ExecResult::ExecResultUnrecoverable.0 => {
Self::Unrecoverable
}
other => panic!(
"try_commit_transaction returned unknown ExecResult code: {other}"
),
}
}
pub fn exec_result(&self) -> ExecResult {
match self {
Self::Ok => ExecResult::ExecResultOK,
Self::TxDeterministicError => {
ExecResult::ExecResultTxDeterministicError
}
Self::TxRootFrameReverted => {
ExecResult::ExecResultTxRootFrameReverted
}
Self::TxNonDeterministicError(_) => {
ExecResult::ExecResultTxNonDeterministicError
}
Self::FailedGasSponsorship => {
ExecResult::ExecResultFailedGasSponsorship
}
Self::TxValidationFailure => {
ExecResult::ExecResultTxValidationFailure
}
Self::SystemError => ExecResult::ExecResultSystemError,
Self::Unrecoverable => ExecResult::ExecResultUnrecoverable,
}
}
}
fn decode_conflict(serialized_conflict: &FFIDataBuffer) -> DbConflictResult {
match serialized_conflict.as_slice() {
Some(bytes) => xdrs::txs::decode(bytes).unwrap_or_else(|e| {
panic!(
"failed to decode DbConflictResult ({} bytes): {e}",
bytes.len()
)
}),
None => panic!(
"try_commit_transaction reported a nondeterministic error but the \
serialized conflict buffer was null (host-side serialization failed)"
),
}
}