multiversx_chain_vm/host/context/
tx_context_ref.rs

1use std::{ops::Deref, sync::Arc};
2
3use crate::host::context::{TxContext, TxResult};
4
5use super::{BlockchainUpdate, TxPanic};
6
7/// The VM API implementation based on a blockchain mock written in Rust.
8/// Implemented as a smart pointer to a TxContext structure, which tracks a blockchain transaction.
9#[derive(Debug)]
10pub struct TxContextRef(pub Arc<TxContext>);
11
12impl Deref for TxContextRef {
13    type Target = TxContext;
14    fn deref(&self) -> &Self::Target {
15        self.0.deref()
16    }
17}
18
19impl Clone for TxContextRef {
20    fn clone(&self) -> Self {
21        Self(self.0.clone())
22    }
23}
24
25impl TxContextRef {
26    pub fn new(tx_context_arc: Arc<TxContext>) -> Self {
27        Self(tx_context_arc)
28    }
29
30    pub fn dummy() -> Self {
31        Self::new(Arc::new(TxContext::dummy()))
32    }
33
34    pub fn into_blockchain_updates(self) -> BlockchainUpdate {
35        let tx_context = Arc::try_unwrap(self.0).unwrap();
36        let tx_cache = Arc::try_unwrap(tx_context.tx_cache).unwrap();
37        tx_cache.into_blockchain_updates()
38    }
39
40    /// Consumes the current API and returns the contained output.
41    /// Should be called at the end of a tx execution.
42    /// Will fail if any other references to the tx context survive, this must be the last.
43    pub fn into_tx_result(self) -> TxResult {
44        // TODO: investigate if we can also destroy the Arc
45        // can be done if we can make sure that no more references exist at this point
46        // let tx_context = Arc::try_unwrap(self.0).unwrap();
47        std::mem::take(&mut *self.tx_result_cell.lock().unwrap())
48    }
49
50    /// The current method for signalling that the current execution is failed, and with what error.
51    ///
52    /// Note: does not terminate execution or panic, that is handled separately.
53    pub fn replace_tx_result_with_error(self, tx_panic: TxPanic) {
54        let _ = std::mem::replace(
55            &mut *self.tx_result_cell.lock().unwrap(),
56            TxResult::from_panic_obj(&tx_panic),
57        );
58    }
59
60    /// Returns true if the references point to the same `TxContext`.
61    pub fn ptr_eq(this: &Self, other: &Self) -> bool {
62        Arc::ptr_eq(&this.0, &other.0)
63    }
64
65    pub fn into_ref(self) -> Arc<TxContext> {
66        self.0
67    }
68}