transaction_fuzzer/
executor.rs1use std::{fmt::Debug, path::PathBuf, sync::Arc};
7
8use iota_core::{
9 authority::{AuthorityState, test_authority_builder::TestAuthorityBuilder},
10 test_utils::send_and_confirm_transaction,
11};
12use iota_move_build::BuildConfig;
13use iota_types::{
14 base_types::ObjectID,
15 effects::{TransactionEffects, TransactionEffectsAPI},
16 error::IotaError,
17 execution_status::{ExecutionFailureStatus, ExecutionStatus},
18 object::Object,
19 transaction::{Transaction, TransactionData},
20 utils::to_sender_signed_transaction,
21};
22use tokio::runtime::Runtime;
23
24use crate::account_universe::{AccountCurrent, PUBLISH_BUDGET};
25
26pub type ExecutionResult = Result<ExecutionStatus, IotaError>;
27
28fn build_test_modules(test_dir: &str) -> (Vec<u8>, Vec<Vec<u8>>) {
29 let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
30 path.extend(["data", test_dir]);
31 let with_unpublished_deps = false;
32 let config = BuildConfig::new_for_testing();
33 let package = config.build(&path).unwrap();
34 (
35 package.get_package_digest(with_unpublished_deps).to_vec(),
36 package.get_package_bytes(with_unpublished_deps),
37 )
38}
39
40pub fn assert_is_acceptable_result(result: &ExecutionResult) {
43 if let Ok(
44 e @ ExecutionStatus::Failure {
45 error: ExecutionFailureStatus::InvariantViolation,
46 command: _,
47 },
48 ) = result
49 {
50 panic!("Invariant violation: {e:#?}")
51 }
52}
53
54#[derive(Clone)]
55pub struct Executor {
56 pub state: Arc<AuthorityState>,
57 pub rt: Arc<Runtime>,
58}
59
60impl Debug for Executor {
61 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62 f.debug_struct("Executor").finish()
63 }
64}
65
66impl Default for Executor {
67 fn default() -> Self {
68 Self::new()
69 }
70}
71
72impl Executor {
73 pub fn new() -> Self {
74 let rt = Runtime::new().unwrap();
75 let state = rt.block_on(TestAuthorityBuilder::new().build());
76 Self {
77 state,
78 rt: Arc::new(rt),
79 }
80 }
81
82 pub fn new_with_rgp(rgp: u64) -> Self {
83 let rt = Runtime::new().unwrap();
84 let state = rt.block_on(
85 TestAuthorityBuilder::new()
86 .with_reference_gas_price(rgp)
87 .build(),
88 );
89 Self {
90 state,
91 rt: Arc::new(rt),
92 }
93 }
94
95 pub fn get_reference_gas_price(&self) -> u64 {
96 self.state.reference_gas_price_for_testing().unwrap()
97 }
98
99 pub fn add_object(&mut self, object: Object) {
100 self.rt.block_on(self.state.insert_genesis_object(object));
101 }
102
103 pub fn add_objects(&mut self, objects: &[Object]) {
104 self.rt.block_on(self.state.insert_genesis_objects(objects));
105 }
106
107 pub fn execute_transaction(&mut self, txn: Transaction) -> ExecutionResult {
108 self.rt
109 .block_on(send_and_confirm_transaction(&self.state, None, txn))
110 .map(|(_, effects)| effects.into_data().status().clone())
111 }
112
113 pub fn publish(
114 &mut self,
115 package_name: &str,
116 dep_ids: Vec<ObjectID>,
117 account: &mut AccountCurrent,
118 ) -> TransactionEffects {
119 let (_, modules) = build_test_modules(package_name);
120 let gas_object = account.new_gas_object(self);
123 let data = TransactionData::new_module(
124 account.initial_data.account.address,
125 gas_object.compute_object_reference(),
126 modules,
127 dep_ids,
128 PUBLISH_BUDGET,
129 1000,
130 );
131 let txn = to_sender_signed_transaction(data, &account.initial_data.account.key);
132 let effects = self
133 .rt
134 .block_on(send_and_confirm_transaction(&self.state, None, txn))
135 .unwrap()
136 .1
137 .into_data();
138
139 assert!(
140 matches!(effects.status(), ExecutionStatus::Success),
141 "{:?}",
142 effects.status()
143 );
144 effects
145 }
146
147 pub fn execute_transactions(
148 &mut self,
149 txn: impl IntoIterator<Item = Transaction>,
150 ) -> Vec<ExecutionResult> {
151 txn.into_iter()
152 .map(|txn| self.execute_transaction(txn))
153 .collect()
154 }
155}