1use std::{sync::Arc, time::Duration};
6
7use fastcrypto::{hash::MultisetHash, traits::KeyPair};
8use iota_types::{
9 base_types::{
10 AuthorityName, ExecutionDigests, IotaAddress, ObjectID, ObjectRef, TransactionDigest,
11 random_object_ref,
12 },
13 committee::Committee,
14 crypto::{
15 AccountKeyPair, AuthorityKeyPair, AuthorityPublicKeyBytes, AuthoritySignInfo,
16 AuthoritySignature, Signer,
17 },
18 effects::{SignedTransactionEffects, TestEffectsBuilder},
19 error::IotaError,
20 message_envelope::Message,
21 signature_verification::VerifiedDigestCache,
22 transaction::{
23 CallArg, CertifiedTransaction, ObjectArg, SignedTransaction,
24 TEST_ONLY_GAS_UNIT_FOR_TRANSFER, Transaction, TransactionData,
25 },
26 utils::{create_fake_transaction, to_sender_signed_transaction},
27};
28use move_core_types::{account_address::AccountAddress, ident_str};
29use shared_crypto::intent::{Intent, IntentScope};
30use tokio::time::timeout;
31use tracing::{info, warn};
32
33use crate::{authority::AuthorityState, state_accumulator::StateAccumulator};
34
35const WAIT_FOR_TX_TIMEOUT: Duration = Duration::from_secs(15);
36
37pub async fn send_and_confirm_transaction(
38 authority: &AuthorityState,
39 fullnode: Option<&AuthorityState>,
40 transaction: Transaction,
41) -> Result<(CertifiedTransaction, SignedTransactionEffects), IotaError> {
42 let epoch_store = authority.load_epoch_store_one_call_per_task();
44 transaction.validity_check(epoch_store.protocol_config(), epoch_store.epoch())?;
45 let transaction = epoch_store.verify_transaction(transaction)?;
46 let response = authority
47 .handle_transaction(&epoch_store, transaction.clone())
48 .await?;
49 let vote = response.status.into_signed_for_testing();
50
51 let committee = authority.clone_committee_for_testing();
53 let certificate =
54 CertifiedTransaction::new(transaction.into_message(), vec![vote.clone()], &committee)
55 .unwrap()
56 .try_into_verified_for_testing(&committee, &Default::default())
57 .unwrap();
58
59 let state_acc = StateAccumulator::new_for_tests(authority.get_accumulator_store().clone());
67 let mut state = state_acc.accumulate_cached_live_object_set_for_testing();
68 let (result, _execution_error_opt) = authority.try_execute_for_test(&certificate)?;
69 let state_after = state_acc.accumulate_cached_live_object_set_for_testing();
70 let effects_acc = state_acc.accumulate_effects(&[result.inner().data().clone()]);
71 state.union(&effects_acc);
72
73 assert_eq!(state_after.digest(), state.digest());
74
75 if let Some(fullnode) = fullnode {
76 fullnode.try_execute_for_test(&certificate)?;
77 }
78 Ok((certificate.into_inner(), result.into_inner()))
79}
80
81#[cfg(test)]
82pub(crate) fn init_state_parameters_from_rng<R>(
83 rng: &mut R,
84) -> (iota_config::genesis::Genesis, AuthorityKeyPair)
85where
86 R: rand::CryptoRng + rand::RngCore,
87{
88 let dir = iota_macros::nondeterministic!(tempfile::TempDir::new().unwrap());
89 let network_config = iota_swarm_config::network_config_builder::ConfigBuilder::new(&dir)
90 .rng(rng)
91 .build();
92 let genesis = network_config.genesis;
93 let authority_key = network_config.validator_configs[0]
94 .authority_key_pair()
95 .copy();
96
97 (genesis, authority_key)
98}
99
100pub async fn wait_for_tx(digest: TransactionDigest, state: Arc<AuthorityState>) {
101 match timeout(
102 WAIT_FOR_TX_TIMEOUT,
103 state
104 .get_transaction_cache_reader()
105 .try_notify_read_executed_effects(&[digest]),
106 )
107 .await
108 {
109 Ok(_) => info!(?digest, "digest found"),
110 Err(e) => {
111 warn!(?digest, "digest not found!");
112 panic!("timed out waiting for effects of digest! {e}");
113 }
114 }
115}
116
117pub async fn wait_for_all_txes(digests: Vec<TransactionDigest>, state: Arc<AuthorityState>) {
118 match timeout(
119 WAIT_FOR_TX_TIMEOUT,
120 state
121 .get_transaction_cache_reader()
122 .try_notify_read_executed_effects(&digests),
123 )
124 .await
125 {
126 Ok(_) => info!(?digests, "all digests found"),
127 Err(e) => {
128 warn!(?digests, "some digests not found!");
129 panic!("timed out waiting for effects of digests! {e}");
130 }
131 }
132}
133
134pub fn create_fake_cert_and_effect_digest<'a>(
135 signers: impl Iterator<
136 Item = (
137 &'a AuthorityName,
138 &'a (dyn Signer<AuthoritySignature> + Send + Sync),
139 ),
140 >,
141 committee: &Committee,
142) -> (ExecutionDigests, CertifiedTransaction) {
143 let transaction = create_fake_transaction();
144 let cert = CertifiedTransaction::new(
145 transaction.data().clone(),
146 signers
147 .map(|(name, signer)| {
148 AuthoritySignInfo::new(
149 committee.epoch,
150 transaction.data(),
151 Intent::iota_app(IntentScope::SenderSignedTransaction),
152 *name,
153 signer,
154 )
155 })
156 .collect(),
157 committee,
158 )
159 .unwrap();
160 let effects = TestEffectsBuilder::new(transaction.data()).build();
161 (
162 ExecutionDigests::new(*transaction.digest(), effects.digest()),
163 cert,
164 )
165}
166
167pub fn make_transfer_iota_transaction(
168 gas_object: ObjectRef,
169 recipient: IotaAddress,
170 amount: Option<u64>,
171 sender: IotaAddress,
172 keypair: &AccountKeyPair,
173 gas_price: u64,
174) -> Transaction {
175 let data = TransactionData::new_transfer_iota(
176 recipient,
177 sender,
178 amount,
179 gas_object,
180 gas_price * TEST_ONLY_GAS_UNIT_FOR_TRANSFER,
181 gas_price,
182 );
183 to_sender_signed_transaction(data, keypair)
184}
185
186pub fn make_pay_iota_transaction(
187 gas_object: ObjectRef,
188 coins: Vec<ObjectRef>,
189 recipients: Vec<IotaAddress>,
190 amounts: Vec<u64>,
191 sender: IotaAddress,
192 keypair: &AccountKeyPair,
193 gas_price: u64,
194 gas_budget: u64,
195) -> Transaction {
196 let data = TransactionData::new_pay_iota(
197 sender, coins, recipients, amounts, gas_object, gas_budget, gas_price,
198 )
199 .unwrap();
200 to_sender_signed_transaction(data, keypair)
201}
202
203pub fn make_transfer_object_transaction(
204 object_ref: ObjectRef,
205 gas_object: ObjectRef,
206 sender: IotaAddress,
207 keypair: &AccountKeyPair,
208 recipient: IotaAddress,
209 gas_price: u64,
210) -> Transaction {
211 let data = TransactionData::new_transfer(
212 recipient,
213 object_ref,
214 sender,
215 gas_object,
216 gas_price * TEST_ONLY_GAS_UNIT_FOR_TRANSFER * 10,
217 gas_price,
218 );
219 to_sender_signed_transaction(data, keypair)
220}
221
222pub fn make_transfer_object_move_transaction(
223 src: IotaAddress,
224 keypair: &AccountKeyPair,
225 dest: IotaAddress,
226 object_ref: ObjectRef,
227 framework_obj_id: ObjectID,
228 gas_object_ref: ObjectRef,
229 gas_budget_in_units: u64,
230 gas_price: u64,
231) -> Transaction {
232 let args = vec![
233 CallArg::Object(ObjectArg::ImmOrOwnedObject(object_ref)),
234 CallArg::Pure(bcs::to_bytes(&AccountAddress::from(dest)).unwrap()),
235 ];
236
237 to_sender_signed_transaction(
238 TransactionData::new_move_call(
239 src,
240 framework_obj_id,
241 ident_str!("object_basics").to_owned(),
242 ident_str!("transfer").to_owned(),
243 Vec::new(),
244 gas_object_ref,
245 args,
246 gas_budget_in_units * gas_price,
247 gas_price,
248 )
249 .unwrap(),
250 keypair,
251 )
252}
253
254pub fn make_dummy_tx(
256 receiver: IotaAddress,
257 sender: IotaAddress,
258 sender_sec: &AccountKeyPair,
259) -> Transaction {
260 Transaction::from_data_and_signer(
261 TransactionData::new_transfer(
262 receiver,
263 random_object_ref(),
264 sender,
265 random_object_ref(),
266 TEST_ONLY_GAS_UNIT_FOR_TRANSFER * 10,
267 10,
268 ),
269 vec![sender_sec],
270 )
271}
272
273pub fn make_cert_with_large_committee(
275 committee: &Committee,
276 key_pairs: &[AuthorityKeyPair],
277 transaction: &Transaction,
278) -> CertifiedTransaction {
279 let len = committee.voting_rights.len();
281 assert_eq!(len, key_pairs.len());
282 let count = (len * 2).div_ceil(3);
283
284 let sigs: Vec<_> = key_pairs
285 .iter()
286 .take(count)
287 .map(|key_pair| {
288 SignedTransaction::new(
289 committee.epoch(),
290 transaction.clone().into_data(),
291 key_pair,
292 AuthorityPublicKeyBytes::from(key_pair.public()),
293 )
294 .auth_sig()
295 .clone()
296 })
297 .collect();
298
299 let cert = CertifiedTransaction::new(transaction.clone().into_data(), sigs, committee).unwrap();
300 cert.verify_signatures_authenticated(
301 committee,
302 &Default::default(),
303 Arc::new(VerifiedDigestCache::new_empty()),
304 )
305 .unwrap();
306 cert
307}