iota_single_node_benchmark/tx_generator/
move_tx_generator.rs1use std::collections::HashMap;
6
7use iota_test_transaction_builder::TestTransactionBuilder;
8use iota_types::{
9 base_types::{IotaAddress, ObjectID, ObjectRef, SequenceNumber},
10 programmable_transaction_builder::ProgrammableTransactionBuilder,
11 transaction::{CallArg, DEFAULT_VALIDATOR_GAS_PRICE, ObjectArg, Transaction},
12};
13use move_core_types::identifier::Identifier;
14
15use crate::{mock_account::Account, tx_generator::TxGenerator};
16
17pub struct MoveTxGenerator {
18 move_package: ObjectID,
19 num_transfers: u64,
20 use_native_transfer: bool,
21 computation: u8,
22 root_objects: HashMap<IotaAddress, ObjectRef>,
23 shared_objects: Vec<(ObjectID, SequenceNumber)>,
24 num_mints: u16,
25 nft_size: u16,
26 use_batch_mint: bool,
27}
28
29impl MoveTxGenerator {
30 pub fn new(
31 move_package: ObjectID,
32 num_transfers: u64,
33 use_native_transfer: bool,
34 computation: u8,
35 root_objects: HashMap<IotaAddress, ObjectRef>,
36 shared_objects: Vec<(ObjectID, SequenceNumber)>,
37 num_mints: u16,
38 nft_size: u16,
39 use_batch_mint: bool,
40 ) -> Self {
41 Self {
42 move_package,
43 num_transfers,
44 use_native_transfer,
45 computation,
46 root_objects,
47 shared_objects,
48 num_mints,
49 nft_size,
50 use_batch_mint,
51 }
52 }
53}
54
55impl TxGenerator for MoveTxGenerator {
56 fn generate_tx(&self, account: Account) -> Transaction {
57 let pt = {
58 let mut builder = ProgrammableTransactionBuilder::new();
59 for i in 1..=self.num_transfers {
63 let object = account.gas_objects[i as usize];
64 if self.use_native_transfer {
65 builder.transfer_object(account.sender, object).unwrap();
66 } else {
67 builder
68 .move_call(
69 self.move_package,
70 Identifier::new("benchmark").unwrap(),
71 Identifier::new("transfer_coin").unwrap(),
72 vec![],
73 vec![CallArg::Object(ObjectArg::ImmOrOwnedObject(object))],
74 )
75 .unwrap();
76 }
77 }
78 for shared_object in &self.shared_objects {
79 builder
80 .move_call(
81 self.move_package,
82 Identifier::new("benchmark").unwrap(),
83 Identifier::new("increment_shared_counter").unwrap(),
84 vec![],
85 vec![CallArg::Object(ObjectArg::SharedObject {
86 id: shared_object.0,
87 initial_shared_version: shared_object.1,
88 mutable: true,
89 })],
90 )
91 .unwrap();
92 }
93
94 if !self.root_objects.is_empty() {
95 let root_object = self.root_objects.get(&account.sender).unwrap();
97 let root_object_arg = builder
98 .obj(ObjectArg::ImmOrOwnedObject(*root_object))
99 .unwrap();
100 builder.programmable_move_call(
101 self.move_package,
102 Identifier::new("benchmark").unwrap(),
103 Identifier::new("read_dynamic_fields").unwrap(),
104 vec![],
105 vec![root_object_arg],
106 );
107 }
108
109 if self.computation > 0 {
110 let computation_arg = builder.pure(self.computation as u64 * 100).unwrap();
112 builder.programmable_move_call(
113 self.move_package,
114 Identifier::new("benchmark").unwrap(),
115 Identifier::new("run_computation").unwrap(),
116 vec![],
117 vec![computation_arg],
118 );
119 }
120 if self.num_mints > 0 {
121 let mut contents = Vec::new();
123 assert!(self.nft_size >= 32, "NFT size must be at least 32 bytes");
124 for _ in 0..self.nft_size - 32 {
125 contents.push(7u8)
126 }
127 if self.use_batch_mint {
128 let mut recipients = Vec::new();
130 for _ in 0..self.num_mints {
131 recipients.push(account.sender)
132 }
133 let args = vec![
134 builder.pure(recipients).unwrap(),
135 builder.pure(contents).unwrap(),
136 ];
137 builder.programmable_move_call(
138 self.move_package,
139 Identifier::new("benchmark").unwrap(),
140 Identifier::new("batch_mint").unwrap(),
141 vec![],
142 args,
143 );
144 } else {
145 for _ in 0..self.num_mints {
147 let args = vec![
148 builder.pure(account.sender).unwrap(),
149 builder.pure(contents.clone()).unwrap(),
150 ];
151 builder.programmable_move_call(
152 self.move_package,
153 Identifier::new("benchmark").unwrap(),
154 Identifier::new("mint_one").unwrap(),
155 vec![],
156 args,
157 );
158 }
159 }
160 }
161 builder.finish()
162 };
163 TestTransactionBuilder::new(
164 account.sender,
165 account.gas_objects[0],
166 DEFAULT_VALIDATOR_GAS_PRICE,
167 )
168 .programmable(pt)
169 .build_and_sign(account.keypair.as_ref())
170 }
171
172 fn name(&self) -> &'static str {
173 "Programmable Move Transaction Generator"
174 }
175}