oasis_core_runtime/transaction/
dispatcher.rs1use std::sync::{atomic::AtomicBool, Arc};
3
4use super::{context::Context, tags::Tags, types::TxnBatch};
5use crate::{
6    common::crypto::hash::Hash,
7    consensus::roothash,
8    types::{CheckTxResult, Error as RuntimeError},
9};
10
11pub trait Dispatcher: Send + Sync {
16    fn is_supported(&self) -> bool {
18        true
19    }
20
21    fn execute_batch(
27        &self,
28        ctx: Context,
29        batch: &TxnBatch,
30        in_msgs: &[roothash::IncomingMessage],
31    ) -> Result<ExecuteBatchResult, RuntimeError>;
32
33    fn schedule_and_execute_batch(
42        &self,
43        _ctx: Context,
44        _initial_batch: &mut TxnBatch,
45        _in_msgs: &[roothash::IncomingMessage],
46    ) -> Result<ExecuteBatchResult, RuntimeError> {
47        Err(RuntimeError::new(
48            "rhp/dispatcher",
49            3,
50            "scheduling not supported",
51        ))
52    }
53
54    fn check_batch(
62        &self,
63        ctx: Context,
64        batch: &TxnBatch,
65    ) -> Result<Vec<CheckTxResult>, RuntimeError>;
66
67    fn finalize(&self, _new_storage_root: Hash) {
69        }
71
72    fn set_abort_batch_flag(&mut self, _abort_batch: Arc<AtomicBool>) {
74        }
76
77    fn query(&self, _ctx: Context, _method: &str, _args: Vec<u8>) -> Result<Vec<u8>, RuntimeError> {
85        Err(RuntimeError::new(
87            "rhp/dispatcher",
88            2,
89            "query not supported",
90        ))
91    }
92}
93
94impl<T: Dispatcher + ?Sized> Dispatcher for Box<T> {
95    fn is_supported(&self) -> bool {
96        T::is_supported(&**self)
97    }
98
99    fn execute_batch(
100        &self,
101        ctx: Context,
102        batch: &TxnBatch,
103        in_msgs: &[roothash::IncomingMessage],
104    ) -> Result<ExecuteBatchResult, RuntimeError> {
105        T::execute_batch(&**self, ctx, batch, in_msgs)
106    }
107
108    fn schedule_and_execute_batch(
109        &self,
110        ctx: Context,
111        initial_batch: &mut TxnBatch,
112        in_msgs: &[roothash::IncomingMessage],
113    ) -> Result<ExecuteBatchResult, RuntimeError> {
114        T::schedule_and_execute_batch(&**self, ctx, initial_batch, in_msgs)
115    }
116
117    fn check_batch(
118        &self,
119        ctx: Context,
120        batch: &TxnBatch,
121    ) -> Result<Vec<CheckTxResult>, RuntimeError> {
122        T::check_batch(&**self, ctx, batch)
123    }
124
125    fn finalize(&self, new_storage_root: Hash) {
126        T::finalize(&**self, new_storage_root)
127    }
128
129    fn set_abort_batch_flag(&mut self, abort_batch: Arc<AtomicBool>) {
130        T::set_abort_batch_flag(&mut **self, abort_batch)
131    }
132
133    fn query(&self, ctx: Context, method: &str, args: Vec<u8>) -> Result<Vec<u8>, RuntimeError> {
134        T::query(&**self, ctx, method, args)
135    }
136}
137
138impl<T: Dispatcher + ?Sized> Dispatcher for Arc<T> {
139    fn is_supported(&self) -> bool {
140        T::is_supported(&**self)
141    }
142
143    fn execute_batch(
144        &self,
145        ctx: Context,
146        batch: &TxnBatch,
147        in_msgs: &[roothash::IncomingMessage],
148    ) -> Result<ExecuteBatchResult, RuntimeError> {
149        T::execute_batch(&**self, ctx, batch, in_msgs)
150    }
151
152    fn schedule_and_execute_batch(
153        &self,
154        ctx: Context,
155        initial_batch: &mut TxnBatch,
156        in_msgs: &[roothash::IncomingMessage],
157    ) -> Result<ExecuteBatchResult, RuntimeError> {
158        T::schedule_and_execute_batch(&**self, ctx, initial_batch, in_msgs)
159    }
160
161    fn check_batch(
162        &self,
163        ctx: Context,
164        batch: &TxnBatch,
165    ) -> Result<Vec<CheckTxResult>, RuntimeError> {
166        T::check_batch(&**self, ctx, batch)
167    }
168
169    fn finalize(&self, new_storage_root: Hash) {
170        T::finalize(&**self, new_storage_root)
171    }
172
173    fn set_abort_batch_flag(&mut self, _abort_batch: Arc<AtomicBool>) {
174        unimplemented!()
175    }
176
177    fn query(&self, ctx: Context, method: &str, args: Vec<u8>) -> Result<Vec<u8>, RuntimeError> {
178        T::query(&**self, ctx, method, args)
179    }
180}
181
182pub struct ExecuteTxResult {
184    pub output: Vec<u8>,
186    pub tags: Tags,
188}
189
190pub struct ExecuteBatchResult {
192    pub results: Vec<ExecuteTxResult>,
194    pub messages: Vec<roothash::Message>,
196    pub in_msgs_count: usize,
198    pub block_tags: Tags,
200    pub tx_reject_hashes: Vec<Hash>,
204}
205
206#[derive(Default)]
211pub struct NoopDispatcher;
212
213impl Dispatcher for NoopDispatcher {
214    fn is_supported(&self) -> bool {
215        false
216    }
217
218    fn execute_batch(
219        &self,
220        _ctx: Context,
221        _batch: &TxnBatch,
222        in_msgs: &[roothash::IncomingMessage],
223    ) -> Result<ExecuteBatchResult, RuntimeError> {
224        Ok(ExecuteBatchResult {
225            results: Vec::new(),
226            messages: Vec::new(),
227            block_tags: Tags::new(),
228            in_msgs_count: in_msgs.len(),
229            tx_reject_hashes: Vec::new(),
230        })
231    }
232
233    fn schedule_and_execute_batch(
234        &self,
235        _ctx: Context,
236        _initial_batch: &mut TxnBatch,
237        in_msgs: &[roothash::IncomingMessage],
238    ) -> Result<ExecuteBatchResult, RuntimeError> {
239        Ok(ExecuteBatchResult {
240            results: Vec::new(),
241            messages: Vec::new(),
242            block_tags: Tags::new(),
243            in_msgs_count: in_msgs.len(),
244            tx_reject_hashes: Vec::new(),
245        })
246    }
247
248    fn check_batch(
249        &self,
250        _ctx: Context,
251        _batch: &TxnBatch,
252    ) -> Result<Vec<CheckTxResult>, RuntimeError> {
253        Ok(Vec::new())
254    }
255}