1use core::default::Default;
7
8use fastcrypto::{hash::MultisetHash, traits::KeyPair};
9use iota_move_build::{BuildConfig, CompiledPackage};
10use iota_types::{
11 crypto::{AccountKeyPair, AuthorityKeyPair, Signature},
12 messages_consensus::ConsensusTransaction,
13 move_package::UpgradePolicy,
14 programmable_transaction_builder::ProgrammableTransactionBuilder,
15 utils::to_sender_signed_transaction,
16};
17use move_core_types::account_address::AccountAddress;
18use move_symbol_pool::Symbol;
19
20use super::{test_authority_builder::TestAuthorityBuilder, *};
21use crate::{checkpoints::CheckpointServiceNoop, consensus_handler::SequencedConsensusTransaction};
22
23pub async fn send_and_confirm_transaction(
24 authority: &AuthorityState,
25 transaction: Transaction,
26) -> Result<(CertifiedTransaction, SignedTransactionEffects), IotaError> {
27 send_and_confirm_transaction_(
28 authority,
29 None, transaction,
31 false, )
33 .await
34}
35pub async fn send_and_confirm_transaction_(
36 authority: &AuthorityState,
37 fullnode: Option<&AuthorityState>,
38 transaction: Transaction,
39 with_shared: bool, ) -> Result<(CertifiedTransaction, SignedTransactionEffects), IotaError> {
41 let (txn, effects, _execution_error_opt) = send_and_confirm_transaction_with_execution_error(
42 authority,
43 fullnode,
44 transaction,
45 with_shared,
46 true,
47 )
48 .await?;
49 Ok((txn, effects))
50}
51
52pub async fn certify_transaction(
53 authority: &AuthorityState,
54 transaction: Transaction,
55) -> Result<VerifiedCertificate, IotaError> {
56 let epoch_store = authority.load_epoch_store_one_call_per_task();
58 transaction.validity_check(epoch_store.protocol_config(), epoch_store.epoch())?;
60 let transaction = epoch_store.verify_transaction(transaction).unwrap();
61
62 let response = authority
63 .handle_transaction(&epoch_store, transaction.clone())
64 .await?;
65 let vote = response.status.into_signed_for_testing();
66
67 let committee = authority.clone_committee_for_testing();
69 let certificate = CertifiedTransaction::new(transaction.into_message(), vec![vote], &committee)
70 .unwrap()
71 .try_into_verified_for_testing(&committee, &Default::default())
72 .unwrap();
73 Ok(certificate)
74}
75
76pub async fn execute_certificate_with_execution_error(
77 authority: &AuthorityState,
78 fullnode: Option<&AuthorityState>,
79 certificate: VerifiedCertificate,
80 with_shared: bool, fake_consensus: bool,
82) -> Result<
83 (
84 CertifiedTransaction,
85 SignedTransactionEffects,
86 Option<ExecutionError>,
87 ),
88 IotaError,
89> {
90 let state_acc = StateAccumulator::new_for_tests(authority.get_accumulator_store().clone());
95 let mut state = state_acc.accumulate_cached_live_object_set_for_testing();
96
97 if with_shared {
98 if fake_consensus {
99 send_consensus(authority, &certificate).await;
100 } else {
101 authority
103 .epoch_store_for_testing()
104 .assign_shared_object_versions_for_tests(
105 authority.get_object_cache_reader().as_ref(),
106 &vec![VerifiedExecutableTransaction::new_from_certificate(
107 certificate.clone(),
108 )],
109 )
110 .await?;
111 }
112 if let Some(fullnode) = fullnode {
113 fullnode
114 .epoch_store_for_testing()
115 .assign_shared_object_versions_for_tests(
116 fullnode.get_object_cache_reader().as_ref(),
117 &vec![VerifiedExecutableTransaction::new_from_certificate(
118 certificate.clone(),
119 )],
120 )
121 .await?;
122 }
123 }
124
125 let (result, execution_error_opt) = authority.try_execute_for_test(&certificate).await?;
130 let state_after = state_acc.accumulate_cached_live_object_set_for_testing();
131 let effects_acc = state_acc.accumulate_effects(vec![result.inner().data().clone()]);
132 state.union(&effects_acc);
133
134 assert_eq!(state_after.digest(), state.digest());
135
136 if let Some(fullnode) = fullnode {
137 fullnode.try_execute_for_test(&certificate).await?;
138 }
139 Ok((
140 certificate.into_inner(),
141 result.into_inner(),
142 execution_error_opt,
143 ))
144}
145
146pub async fn send_and_confirm_transaction_with_execution_error(
147 authority: &AuthorityState,
148 fullnode: Option<&AuthorityState>,
149 transaction: Transaction,
150 with_shared: bool, fake_consensus: bool, ) -> Result<
153 (
154 CertifiedTransaction,
155 SignedTransactionEffects,
156 Option<ExecutionError>,
157 ),
158 IotaError,
159> {
160 let certificate = certify_transaction(authority, transaction).await?;
161 execute_certificate_with_execution_error(
162 authority,
163 fullnode,
164 certificate,
165 with_shared,
166 fake_consensus,
167 )
168 .await
169}
170
171pub async fn init_state_validator_with_fullnode() -> (Arc<AuthorityState>, Arc<AuthorityState>) {
172 use iota_types::crypto::get_authority_key_pair;
173
174 let validator = TestAuthorityBuilder::new().build().await;
175 let fullnode_key_pair = get_authority_key_pair().1;
176 let fullnode = TestAuthorityBuilder::new()
177 .with_keypair(&fullnode_key_pair)
178 .build()
179 .await;
180 (validator, fullnode)
181}
182
183pub async fn init_state_with_committee(
184 genesis: &Genesis,
185 authority_key: &AuthorityKeyPair,
186) -> Arc<AuthorityState> {
187 TestAuthorityBuilder::new()
188 .with_genesis_and_keypair(genesis, authority_key)
189 .build()
190 .await
191}
192
193pub async fn init_state_with_ids<I: IntoIterator<Item = (IotaAddress, ObjectID)>>(
194 objects: I,
195) -> Arc<AuthorityState> {
196 let state = TestAuthorityBuilder::new().build().await;
197 for (address, object_id) in objects {
198 let obj = Object::with_id_owner_for_testing(object_id, address);
199 state.insert_genesis_object(obj).await;
201 }
202 state
203}
204
205pub async fn init_state_with_ids_and_versions<
206 I: IntoIterator<Item = (IotaAddress, ObjectID, SequenceNumber)>,
207>(
208 objects: I,
209) -> Arc<AuthorityState> {
210 let state = TestAuthorityBuilder::new().build().await;
211 for (address, object_id, version) in objects {
212 let obj = Object::with_id_owner_version_for_testing(object_id, version, address);
213 state.insert_genesis_object(obj).await;
214 }
215 state
216}
217
218pub async fn init_state_with_objects<I: IntoIterator<Item = Object>>(
219 objects: I,
220) -> Arc<AuthorityState> {
221 let dir = tempfile::TempDir::new().unwrap();
222 let network_config =
223 iota_swarm_config::network_config_builder::ConfigBuilder::new(&dir).build();
224 let genesis = network_config.genesis;
225 let keypair = network_config.validator_configs[0]
226 .authority_key_pair()
227 .copy();
228 init_state_with_objects_and_committee(objects, &genesis, &keypair).await
229}
230
231pub async fn init_state_with_objects_and_committee<I: IntoIterator<Item = Object>>(
232 objects: I,
233 genesis: &Genesis,
234 authority_key: &AuthorityKeyPair,
235) -> Arc<AuthorityState> {
236 let state = init_state_with_committee(genesis, authority_key).await;
237 for o in objects {
238 state.insert_genesis_object(o).await;
239 }
240 state
241}
242
243pub async fn init_state_with_object_id(
244 address: IotaAddress,
245 object: ObjectID,
246) -> Arc<AuthorityState> {
247 init_state_with_ids(std::iter::once((address, object))).await
248}
249
250pub async fn init_state_with_ids_and_expensive_checks<
251 I: IntoIterator<Item = (IotaAddress, ObjectID)>,
252>(
253 objects: I,
254 config: ExpensiveSafetyCheckConfig,
255) -> Arc<AuthorityState> {
256 let state = TestAuthorityBuilder::new()
257 .with_expensive_safety_checks(config)
258 .build()
259 .await;
260 for (address, object_id) in objects {
261 let obj = Object::with_id_owner_for_testing(object_id, address);
262 state.insert_genesis_object(obj).await;
264 }
265 state
266}
267
268pub fn init_transfer_transaction(
269 authority_state: &AuthorityState,
270 sender: IotaAddress,
271 secret: &AccountKeyPair,
272 recipient: IotaAddress,
273 object_ref: ObjectRef,
274 gas_object_ref: ObjectRef,
275 gas_budget: u64,
276 gas_price: u64,
277) -> VerifiedTransaction {
278 let data = TransactionData::new_transfer(
279 recipient,
280 object_ref,
281 sender,
282 gas_object_ref,
283 gas_budget,
284 gas_price,
285 );
286 let tx = to_sender_signed_transaction(data, secret);
287 authority_state
288 .epoch_store_for_testing()
289 .verify_transaction(tx)
290 .unwrap()
291}
292
293pub fn init_certified_transfer_transaction(
294 sender: IotaAddress,
295 secret: &AccountKeyPair,
296 recipient: IotaAddress,
297 object_ref: ObjectRef,
298 gas_object_ref: ObjectRef,
299 authority_state: &AuthorityState,
300) -> VerifiedCertificate {
301 let rgp = authority_state.reference_gas_price_for_testing().unwrap();
302 let transfer_transaction = init_transfer_transaction(
303 authority_state,
304 sender,
305 secret,
306 recipient,
307 object_ref,
308 gas_object_ref,
309 rgp * TEST_ONLY_GAS_UNIT_FOR_TRANSFER,
310 rgp,
311 );
312 init_certified_transaction(transfer_transaction.into(), authority_state)
313}
314
315pub fn init_certified_transaction(
316 transaction: Transaction,
317 authority_state: &AuthorityState,
318) -> VerifiedCertificate {
319 let epoch_store = authority_state.epoch_store_for_testing();
320 let transaction = epoch_store.verify_transaction(transaction).unwrap();
321
322 let vote = VerifiedSignedTransaction::new(
323 0,
324 transaction.clone(),
325 authority_state.name,
326 &*authority_state.secret,
327 );
328 CertifiedTransaction::new(
329 transaction.into_message(),
330 vec![vote.auth_sig().clone()],
331 epoch_store.committee(),
332 )
333 .unwrap()
334 .try_into_verified_for_testing(epoch_store.committee(), &Default::default())
335 .unwrap()
336}
337
338pub async fn certify_shared_obj_transaction_no_execution(
339 authority: &AuthorityState,
340 transaction: Transaction,
341) -> Result<VerifiedCertificate, IotaError> {
342 let epoch_store = authority.load_epoch_store_one_call_per_task();
343 let transaction = epoch_store.verify_transaction(transaction).unwrap();
344 let response = authority
345 .handle_transaction(&epoch_store, transaction.clone())
346 .await?;
347 let vote = response.status.into_signed_for_testing();
348
349 let committee = authority.clone_committee_for_testing();
351 let certificate =
352 CertifiedTransaction::new(transaction.into_message(), vec![vote.clone()], &committee)
353 .unwrap()
354 .try_into_verified_for_testing(&committee, &Default::default())
355 .unwrap();
356
357 send_consensus_no_execution(authority, &certificate).await;
358
359 Ok(certificate)
360}
361
362pub async fn enqueue_all_and_execute_all(
363 authority: &AuthorityState,
364 certificates: Vec<VerifiedCertificate>,
365) -> Result<Vec<TransactionEffects>, IotaError> {
366 authority.enqueue_certificates_for_execution(
367 certificates.clone(),
368 &authority.epoch_store_for_testing(),
369 );
370 let mut output = Vec::new();
371 for cert in certificates {
372 let effects = authority.notify_read_effects(&cert).await?;
373 output.push(effects);
374 }
375 Ok(output)
376}
377
378pub async fn execute_sequenced_certificate_to_effects(
379 authority: &AuthorityState,
380 certificate: VerifiedCertificate,
381) -> Result<(TransactionEffects, Option<ExecutionError>), IotaError> {
382 authority.enqueue_certificates_for_execution(
383 vec![certificate.clone()],
384 &authority.epoch_store_for_testing(),
385 );
386
387 let (result, execution_error_opt) = authority.try_execute_for_test(&certificate).await?;
388 let effects = result.inner().data().clone();
389 Ok((effects, execution_error_opt))
390}
391
392pub async fn send_consensus(authority: &AuthorityState, cert: &VerifiedCertificate) {
393 let transaction = SequencedConsensusTransaction::new_test(
394 ConsensusTransaction::new_certificate_message(&authority.name, cert.clone().into_inner()),
395 );
396
397 let certs = authority
398 .epoch_store_for_testing()
399 .process_consensus_transactions_for_tests(
400 vec![transaction],
401 &Arc::new(CheckpointServiceNoop {}),
402 authority.get_object_cache_reader().as_ref(),
403 &authority.metrics,
404 true,
405 )
406 .await
407 .unwrap();
408
409 authority
410 .transaction_manager()
411 .enqueue(certs, &authority.epoch_store_for_testing());
412}
413
414pub async fn send_consensus_no_execution(authority: &AuthorityState, cert: &VerifiedCertificate) {
415 let transaction = SequencedConsensusTransaction::new_test(
416 ConsensusTransaction::new_certificate_message(&authority.name, cert.clone().into_inner()),
417 );
418
419 authority
423 .epoch_store_for_testing()
424 .process_consensus_transactions_for_tests(
425 vec![transaction],
426 &Arc::new(CheckpointServiceNoop {}),
427 authority.get_object_cache_reader().as_ref(),
428 &authority.metrics,
429 true,
430 )
431 .await
432 .unwrap();
433}
434
435pub async fn send_batch_consensus_no_execution(
436 authority: &AuthorityState,
437 certificates: &[VerifiedCertificate],
438 skip_consensus_commit_prologue_in_test: bool,
439) -> Vec<VerifiedExecutableTransaction> {
440 let transactions = certificates
441 .iter()
442 .map(|cert| {
443 SequencedConsensusTransaction::new_test(ConsensusTransaction::new_certificate_message(
444 &authority.name,
445 cert.clone().into_inner(),
446 ))
447 })
448 .collect();
449
450 authority
454 .epoch_store_for_testing()
455 .process_consensus_transactions_for_tests(
456 transactions,
457 &Arc::new(CheckpointServiceNoop {}),
458 authority.get_object_cache_reader().as_ref(),
459 &authority.metrics,
460 skip_consensus_commit_prologue_in_test,
461 )
462 .await
463 .unwrap()
464}
465
466pub fn build_test_modules_with_dep_addr(
467 path: &Path,
468 dep_original_addresses: impl IntoIterator<Item = (&'static str, ObjectID)>,
469 dep_ids: impl IntoIterator<Item = (&'static str, ObjectID)>,
470) -> CompiledPackage {
471 let mut build_config = BuildConfig::new_for_testing();
472 for (addr_name, obj_id) in dep_original_addresses {
473 build_config
474 .config
475 .additional_named_addresses
476 .insert(addr_name.to_string(), AccountAddress::from(obj_id));
477 }
478 let mut package = build_config.build(path).unwrap();
479
480 let dep_id_mapping: BTreeMap<_, _> = dep_ids
481 .into_iter()
482 .map(|(dep_name, obj_id)| (Symbol::from(dep_name), obj_id))
483 .collect();
484
485 assert_eq!(
486 dep_id_mapping.len(),
487 package.dependency_ids.unpublished.len()
488 );
489 for unpublished_dep in &package.dependency_ids.unpublished {
490 let published_id = dep_id_mapping.get(unpublished_dep).unwrap();
491 assert!(
493 package
494 .dependency_ids
495 .published
496 .insert(*unpublished_dep, *published_id)
497 .is_none()
498 )
499 }
500
501 package.dependency_ids.unpublished.clear();
503 package
504}
505
506pub async fn publish_package_on_single_authority(
512 path: &Path,
513 sender: IotaAddress,
514 sender_key: &dyn Signer<Signature>,
515 gas_payment: ObjectRef,
516 dep_original_addresses: impl IntoIterator<Item = (&'static str, ObjectID)>,
517 dep_ids: Vec<ObjectID>,
518 state: &Arc<AuthorityState>,
519) -> IotaResult<(ObjectID, ObjectRef)> {
520 let mut build_config = BuildConfig::new_for_testing();
521 for (addr_name, obj_id) in dep_original_addresses {
522 build_config
523 .config
524 .additional_named_addresses
525 .insert(addr_name.to_string(), AccountAddress::from(obj_id));
526 }
527 let modules = build_config.build(path).unwrap().get_package_bytes(false);
528
529 let mut builder = ProgrammableTransactionBuilder::new();
530 let cap = builder.publish_upgradeable(modules, dep_ids);
531 builder.transfer_arg(sender, cap);
532 let pt = builder.finish();
533
534 let rgp = state.epoch_store_for_testing().reference_gas_price();
535 let txn_data = TransactionData::new_programmable(
536 sender,
537 vec![gas_payment],
538 pt,
539 rgp * TEST_ONLY_GAS_UNIT_FOR_PUBLISH,
540 rgp,
541 );
542
543 let signed = to_sender_signed_transaction(txn_data, sender_key);
544 let (_cert, effects) = send_and_confirm_transaction(state, signed).await?;
545 assert!(effects.data().status().is_ok());
546 let package_id = effects
547 .data()
548 .created()
549 .iter()
550 .find(|c| c.1 == Owner::Immutable)
551 .unwrap()
552 .0
553 .0;
554 let cap_object = effects
555 .data()
556 .created()
557 .iter()
558 .find(|c| matches!(c.1, Owner::AddressOwner(..)))
559 .unwrap()
560 .0;
561 Ok((package_id, cap_object))
562}
563
564pub async fn upgrade_package_on_single_authority(
565 path: &Path,
566 sender: IotaAddress,
567 sender_key: &dyn Signer<Signature>,
568 gas_payment: ObjectRef,
569 package_id: ObjectID,
570 upgrade_cap: ObjectRef,
571 dep_original_addresses: impl IntoIterator<Item = (&'static str, ObjectID)>,
572 dep_id_mapping: impl IntoIterator<Item = (&'static str, ObjectID)>,
573 state: &Arc<AuthorityState>,
574) -> IotaResult<ObjectID> {
575 let package = build_test_modules_with_dep_addr(path, dep_original_addresses, dep_id_mapping);
576
577 let with_unpublished_deps = false;
578 let modules = package.get_package_bytes(with_unpublished_deps);
579 let digest = package.get_package_digest(with_unpublished_deps).to_vec();
580
581 let rgp = state.epoch_store_for_testing().reference_gas_price();
582 let data = TransactionData::new_upgrade(
583 sender,
584 gas_payment,
585 package_id,
586 modules,
587 package.get_dependency_storage_package_ids(),
588 (upgrade_cap, Owner::AddressOwner(sender)),
589 UpgradePolicy::COMPATIBLE,
590 digest,
591 rgp * TEST_ONLY_GAS_UNIT_FOR_PUBLISH,
592 rgp,
593 )
594 .unwrap();
595 let signed = to_sender_signed_transaction(data, sender_key);
596 let (_cert, effects) = send_and_confirm_transaction(state, signed).await?;
597 assert!(effects.data().status().is_ok());
598 let package_id = effects
599 .data()
600 .created()
601 .iter()
602 .find(|c| c.1 == Owner::Immutable)
603 .unwrap()
604 .0
605 .0;
606 Ok(package_id)
607}