sui_move_natives_latest/
transaction_context.rs

1// Copyright (c) Mysten Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use better_any::{Tid, TidAble};
5use move_binary_format::errors::{PartialVMError, PartialVMResult};
6use move_core_types::{account_address::AccountAddress, vm_status::StatusCode};
7use move_vm_runtime::native_extensions::NativeExtensionMarker;
8use std::{cell::RefCell, rc::Rc};
9use sui_types::{
10    base_types::{ObjectID, SuiAddress, TxContext},
11    committee::EpochId,
12    digests::TransactionDigest,
13};
14
15// TransactionContext is a wrapper around TxContext that is exposed to NativeContextExtensions
16// in order to provide transaction context information to Move native functions.
17// Holds a Rc<RefCell<TxContext>> to allow for mutation of the TxContext.
18#[derive(Tid)]
19pub struct TransactionContext {
20    pub(crate) tx_context: Rc<RefCell<TxContext>>,
21    test_only: bool,
22}
23
24impl NativeExtensionMarker<'_> for TransactionContext {}
25
26impl TransactionContext {
27    pub fn new(tx_context: Rc<RefCell<TxContext>>) -> Self {
28        Self {
29            tx_context,
30            test_only: false,
31        }
32    }
33
34    pub fn new_for_testing(tx_context: Rc<RefCell<TxContext>>) -> Self {
35        Self {
36            tx_context,
37            test_only: true,
38        }
39    }
40
41    pub fn sender(&self) -> SuiAddress {
42        self.tx_context.borrow().sender()
43    }
44
45    pub fn epoch(&self) -> EpochId {
46        self.tx_context.borrow().epoch()
47    }
48
49    pub fn epoch_timestamp_ms(&self) -> u64 {
50        self.tx_context.borrow().epoch_timestamp_ms()
51    }
52
53    pub fn digest(&self) -> TransactionDigest {
54        self.tx_context.borrow().digest()
55    }
56
57    pub fn sponsor(&self) -> Option<SuiAddress> {
58        self.tx_context.borrow().sponsor()
59    }
60
61    pub fn rgp(&self) -> u64 {
62        self.tx_context.borrow().rgp()
63    }
64
65    pub fn gas_price(&self) -> u64 {
66        self.tx_context.borrow().gas_price()
67    }
68
69    pub fn gas_budget(&self) -> u64 {
70        self.tx_context.borrow().gas_budget()
71    }
72
73    pub fn ids_created(&self) -> u64 {
74        self.tx_context.borrow().ids_created()
75    }
76
77    pub fn fresh_id(&self) -> ObjectID {
78        self.tx_context.borrow_mut().fresh_id()
79    }
80
81    //
82    // Test only function
83    //
84    pub fn replace(
85        &self,
86        sender: AccountAddress,
87        tx_hash: Vec<u8>,
88        epoch: u64,
89        epoch_timestamp_ms: u64,
90        ids_created: u64,
91        rgp: u64,
92        gas_price: u64,
93        gas_budget: u64,
94        sponsor: Option<AccountAddress>,
95    ) -> PartialVMResult<()> {
96        if !self.test_only {
97            return Err(
98                PartialVMError::new(StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR)
99                    .with_message("`replace` called on a non testing scenario".to_string()),
100            );
101        }
102        self.tx_context.borrow_mut().replace(
103            sender,
104            tx_hash,
105            epoch,
106            epoch_timestamp_ms,
107            ids_created,
108            rgp,
109            gas_price,
110            gas_budget,
111            sponsor,
112        );
113        Ok(())
114    }
115}