Skip to main content

iota_types/
transaction_executor.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5use std::{collections::BTreeMap, time::Duration};
6
7use iota_sdk_types::{ObjectId, TransactionDigest};
8
9use crate::{
10    effects::{TransactionEffects, TransactionEvents},
11    error::{ExecutionError, IotaError},
12    execution::ExecutionResult,
13    messages_checkpoint::CheckpointSequenceNumber,
14    object::Object,
15    quorum_driver_types::{
16        ExecuteTransactionRequestV1, ExecuteTransactionResponseV1, QuorumDriverError,
17    },
18    transaction::TransactionData,
19};
20
21/// Trait to define the interface for how the REST service interacts with a
22/// QuorumDriver or a simulated transaction executor.
23#[async_trait::async_trait]
24pub trait TransactionExecutor: Send + Sync {
25    async fn execute_transaction(
26        &self,
27        request: ExecuteTransactionRequestV1,
28        skip_certification: bool,
29        client_addr: Option<std::net::SocketAddr>,
30    ) -> Result<ExecuteTransactionResponseV1, QuorumDriverError>;
31
32    fn simulate_transaction(
33        &self,
34        transaction: TransactionData,
35        checks: VmChecks,
36    ) -> Result<SimulateTransactionResult, IotaError>;
37
38    /// Wait for the given transactions to be included in a checkpoint.
39    ///
40    /// Returns a mapping from transaction digest to
41    /// `(checkpoint_sequence_number, checkpoint_timestamp_ms)`.
42    /// On timeout, returns partial results for any transactions that were
43    /// already checkpointed.
44    async fn wait_for_checkpoint_inclusion(
45        &self,
46        digests: &[TransactionDigest],
47        timeout: Duration,
48    ) -> Result<BTreeMap<TransactionDigest, (CheckpointSequenceNumber, u64)>, IotaError>;
49
50    /// Read authoritative effects, events, and input/output objects for a
51    /// locally-executed transaction from the cache. Used by callers that
52    /// have already waited for checkpoint inclusion and want to discard any
53    /// uncertified single-validator copies.
54    ///
55    /// Returns `Ok(None)` if the tx is not in the cache, or if the executor
56    /// does not maintain a local cache (e.g. simulacrum).
57    fn read_transaction_from_cache(
58        &self,
59        digest: &TransactionDigest,
60        include_events: bool,
61        include_input_objects: bool,
62        include_output_objects: bool,
63    ) -> Result<Option<CachedTransactionData>, IotaError> {
64        // Default: no cache — safe fallback for executors like simulacrum.
65        let _ = (
66            digest,
67            include_events,
68            include_input_objects,
69            include_output_objects,
70        );
71        Ok(None)
72    }
73}
74
75/// Authoritative per-transaction data read from a local cache.
76pub struct CachedTransactionData {
77    pub effects: TransactionEffects,
78    pub events: Option<TransactionEvents>,
79    pub input_objects: Option<Vec<Object>>,
80    pub output_objects: Option<Vec<Object>>,
81}
82
83pub struct SimulateTransactionResult {
84    pub effects: TransactionEffects,
85    pub events: Option<TransactionEvents>,
86    pub input_objects: BTreeMap<ObjectId, Object>,
87    pub output_objects: BTreeMap<ObjectId, Object>,
88    pub execution_result: Result<Vec<ExecutionResult>, ExecutionError>,
89    pub mock_gas_id: Option<ObjectId>,
90    pub suggested_gas_price: Option<u64>,
91}
92
93#[derive(Default, Debug, Copy, Clone)]
94pub enum VmChecks {
95    #[default]
96    Enabled,
97    Disabled,
98}
99
100impl VmChecks {
101    pub fn disabled(self) -> bool {
102        matches!(self, Self::Disabled)
103    }
104
105    pub fn enabled(self) -> bool {
106        matches!(self, Self::Enabled)
107    }
108}