1use core::default::Default;
6use fastcrypto::hash::MultisetHash;
7use fastcrypto::traits::KeyPair;
8use sui_types::base_types::FullObjectRef;
9use sui_types::crypto::{AccountKeyPair, AuthorityKeyPair};
10use sui_types::utils::to_sender_signed_transaction;
11
12use super::shared_object_version_manager::AssignedVersions;
13use super::test_authority_builder::TestAuthorityBuilder;
14use super::*;
15
16#[cfg(test)]
17use super::shared_object_version_manager::{AssignedTxAndVersions, Schedulable};
18
19pub async fn send_and_confirm_transaction(
20 authority: &AuthorityState,
21 transaction: Transaction,
22) -> Result<(CertifiedTransaction, SignedTransactionEffects), SuiError> {
23 send_and_confirm_transaction_(
24 authority,
25 None, transaction,
27 false, )
29 .await
30}
31pub async fn send_and_confirm_transaction_(
32 authority: &AuthorityState,
33 fullnode: Option<&AuthorityState>,
34 transaction: Transaction,
35 with_shared: bool, ) -> Result<(CertifiedTransaction, SignedTransactionEffects), SuiError> {
37 let (txn, effects, _execution_error_opt) = send_and_confirm_transaction_with_execution_error(
38 authority,
39 fullnode,
40 transaction,
41 with_shared,
42 true,
43 )
44 .await?;
45 Ok((txn, effects))
46}
47
48pub async fn certify_transaction(
49 authority: &AuthorityState,
50 transaction: Transaction,
51) -> Result<VerifiedCertificate, SuiError> {
52 let epoch_store = authority.load_epoch_store_one_call_per_task();
54 transaction.validity_check(&epoch_store.tx_validity_check_context())?;
56 let transaction = epoch_store
57 .verify_transaction_require_no_aliases(transaction)
58 .unwrap()
59 .into_tx();
60
61 let response = authority
62 .handle_transaction(&epoch_store, transaction.clone())
63 .await?;
64 let vote = response.status.into_signed_for_testing();
65
66 let committee = authority.clone_committee_for_testing();
68 let certificate = CertifiedTransaction::new(transaction.into_message(), vec![vote], &committee)
69 .unwrap()
70 .try_into_verified_for_testing(&committee, &Default::default())
71 .unwrap();
72 Ok(certificate)
73}
74
75pub async fn execute_certificate_with_execution_error(
76 authority: &AuthorityState,
77 fullnode: Option<&AuthorityState>,
78 certificate: VerifiedCertificate,
79 with_shared: bool, fake_consensus: bool,
81) -> Result<
82 (
83 CertifiedTransaction,
84 SignedTransactionEffects,
85 Option<ExecutionError>,
86 ),
87 SuiError,
88> {
89 let epoch_store = authority.load_epoch_store_one_call_per_task();
90 let state_acc =
95 GlobalStateHasher::new_for_tests(authority.get_global_state_hash_store().clone());
96 let include_wrapped_tombstone = !authority
97 .epoch_store_for_testing()
98 .protocol_config()
99 .simplified_unwrap_then_delete();
100 let mut state =
101 state_acc.accumulate_cached_live_object_set_for_testing(include_wrapped_tombstone);
102
103 let assigned_versions = if with_shared {
104 if fake_consensus {
105 send_consensus(authority, &certificate).await
106 } else {
107 let assigned_versions = authority
109 .epoch_store_for_testing()
110 .assign_shared_object_versions_for_tests(
111 authority.get_object_cache_reader().as_ref(),
112 &vec![VerifiedExecutableTransaction::new_from_certificate(
113 certificate.clone(),
114 )],
115 )?;
116 assigned_versions
117 .into_map()
118 .get(&certificate.key())
119 .cloned()
120 .unwrap()
121 }
122 } else {
123 AssignedVersions::new(vec![], None)
124 };
125
126 let (result, execution_error_opt) = authority
129 .try_execute_for_test(
130 &certificate,
131 ExecutionEnv::new().with_assigned_versions(assigned_versions.clone()),
132 )
133 .await;
134 let state_after =
135 state_acc.accumulate_cached_live_object_set_for_testing(include_wrapped_tombstone);
136 let effects_acc = state_acc.accumulate_effects(
137 &[result.inner().data().clone()],
138 epoch_store.protocol_config(),
139 );
140 state.union(&effects_acc);
141
142 assert_eq!(state_after.digest(), state.digest());
143
144 if let Some(fullnode) = fullnode {
145 fullnode
146 .try_execute_for_test(
147 &certificate,
148 ExecutionEnv::new().with_assigned_versions(assigned_versions),
149 )
150 .await;
151 }
152 Ok((
153 certificate.into_inner(),
154 result.into_inner(),
155 execution_error_opt,
156 ))
157}
158
159pub async fn send_and_confirm_transaction_with_execution_error(
160 authority: &AuthorityState,
161 fullnode: Option<&AuthorityState>,
162 transaction: Transaction,
163 with_shared: bool, fake_consensus: bool, ) -> Result<
166 (
167 CertifiedTransaction,
168 SignedTransactionEffects,
169 Option<ExecutionError>,
170 ),
171 SuiError,
172> {
173 let certificate = certify_transaction(authority, transaction).await?;
174 execute_certificate_with_execution_error(
175 authority,
176 fullnode,
177 certificate,
178 with_shared,
179 fake_consensus,
180 )
181 .await
182}
183
184pub async fn init_state_validator_with_fullnode() -> (Arc<AuthorityState>, Arc<AuthorityState>) {
185 use sui_types::crypto::get_authority_key_pair;
186
187 let validator = TestAuthorityBuilder::new().build().await;
188 let fullnode_key_pair = get_authority_key_pair().1;
189 let fullnode = TestAuthorityBuilder::new()
190 .with_keypair(&fullnode_key_pair)
191 .build()
192 .await;
193 (validator, fullnode)
194}
195
196pub async fn init_state_with_committee(
197 genesis: &Genesis,
198 authority_key: &AuthorityKeyPair,
199) -> Arc<AuthorityState> {
200 TestAuthorityBuilder::new()
201 .with_genesis_and_keypair(genesis, authority_key)
202 .build()
203 .await
204}
205
206pub async fn init_state_with_ids<I: IntoIterator<Item = (SuiAddress, ObjectID)>>(
207 objects: I,
208) -> Arc<AuthorityState> {
209 let state = TestAuthorityBuilder::new().build().await;
210 for (address, object_id) in objects {
211 let obj = Object::with_id_owner_for_testing(object_id, address);
212 state.insert_genesis_object(obj).await;
214 }
215 state
216}
217
218pub async fn init_state_with_ids_and_versions<
219 I: IntoIterator<Item = (SuiAddress, ObjectID, SequenceNumber)>,
220>(
221 objects: I,
222) -> Arc<AuthorityState> {
223 let state = TestAuthorityBuilder::new().build().await;
224 for (address, object_id, version) in objects {
225 let obj = Object::with_id_owner_version_for_testing(
226 object_id,
227 version,
228 Owner::AddressOwner(address),
229 );
230 state.insert_genesis_object(obj).await;
231 }
232 state
233}
234
235pub async fn init_state_with_objects<I: IntoIterator<Item = Object>>(
236 objects: I,
237) -> Arc<AuthorityState> {
238 let dir = tempfile::TempDir::new().unwrap();
239 let network_config = sui_swarm_config::network_config_builder::ConfigBuilder::new(&dir).build();
240 let genesis = network_config.genesis;
241 let keypair = network_config.validator_configs[0]
242 .protocol_key_pair()
243 .copy();
244 init_state_with_objects_and_committee(objects, &genesis, &keypair).await
245}
246
247pub async fn init_state_with_objects_and_committee<I: IntoIterator<Item = Object>>(
248 objects: I,
249 genesis: &Genesis,
250 authority_key: &AuthorityKeyPair,
251) -> Arc<AuthorityState> {
252 let state = init_state_with_committee(genesis, authority_key).await;
253 for o in objects {
254 state.insert_genesis_object(o).await;
255 }
256 state
257}
258
259pub async fn init_state_with_object_id(
260 address: SuiAddress,
261 object: ObjectID,
262) -> Arc<AuthorityState> {
263 init_state_with_ids(std::iter::once((address, object))).await
264}
265
266pub async fn init_state_with_ids_and_expensive_checks<
267 I: IntoIterator<Item = (SuiAddress, ObjectID)>,
268>(
269 objects: I,
270 config: ExpensiveSafetyCheckConfig,
271) -> Arc<AuthorityState> {
272 let state = TestAuthorityBuilder::new()
273 .with_expensive_safety_checks(config)
274 .build()
275 .await;
276 for (address, object_id) in objects {
277 let obj = Object::with_id_owner_for_testing(object_id, address);
278 state.insert_genesis_object(obj).await;
280 }
281 state
282}
283
284pub fn init_transfer_transaction(
285 authority_state: &AuthorityState,
286 sender: SuiAddress,
287 secret: &AccountKeyPair,
288 recipient: SuiAddress,
289 object_ref: ObjectRef,
290 gas_object_ref: ObjectRef,
291 gas_budget: u64,
292 gas_price: u64,
293) -> VerifiedTransaction {
294 let data = TransactionData::new_transfer(
295 recipient,
296 FullObjectRef::from_fastpath_ref(object_ref),
297 sender,
298 gas_object_ref,
299 gas_budget,
300 gas_price,
301 );
302 let tx = to_sender_signed_transaction(data, secret);
303 authority_state
304 .epoch_store_for_testing()
305 .verify_transaction_require_no_aliases(tx)
306 .unwrap()
307 .into_tx()
308}
309
310pub fn init_certified_transfer_transaction(
311 sender: SuiAddress,
312 secret: &AccountKeyPair,
313 recipient: SuiAddress,
314 object_ref: ObjectRef,
315 gas_object_ref: ObjectRef,
316 authority_state: &AuthorityState,
317) -> VerifiedCertificate {
318 let rgp = authority_state.reference_gas_price_for_testing().unwrap();
319 let transfer_transaction = init_transfer_transaction(
320 authority_state,
321 sender,
322 secret,
323 recipient,
324 object_ref,
325 gas_object_ref,
326 rgp * TEST_ONLY_GAS_UNIT_FOR_TRANSFER,
327 rgp,
328 );
329 init_certified_transaction(transfer_transaction.into(), authority_state)
330}
331
332pub fn init_certified_transaction(
333 transaction: Transaction,
334 authority_state: &AuthorityState,
335) -> VerifiedCertificate {
336 let epoch_store = authority_state.epoch_store_for_testing();
337 let transaction = epoch_store
338 .verify_transaction_require_no_aliases(transaction)
339 .unwrap()
340 .into_tx();
341
342 let vote = VerifiedSignedTransaction::new(
343 0,
344 transaction.clone(),
345 authority_state.name,
346 &*authority_state.secret,
347 );
348 CertifiedTransaction::new(
349 transaction.into_message(),
350 vec![vote.auth_sig().clone()],
351 epoch_store.committee(),
352 )
353 .unwrap()
354 .try_into_verified_for_testing(epoch_store.committee(), &Default::default())
355 .unwrap()
356}
357
358pub async fn certify_shared_obj_transaction_no_execution(
359 authority: &AuthorityState,
360 transaction: Transaction,
361) -> Result<(VerifiedCertificate, AssignedVersions), SuiError> {
362 let epoch_store = authority.load_epoch_store_one_call_per_task();
363 let transaction = epoch_store
364 .verify_transaction_require_no_aliases(transaction)
365 .unwrap()
366 .into_tx();
367 let response = authority
368 .handle_transaction(&epoch_store, transaction.clone())
369 .await?;
370 let vote = response.status.into_signed_for_testing();
371
372 let committee = authority.clone_committee_for_testing();
374 let certificate =
375 CertifiedTransaction::new(transaction.into_message(), vec![vote.clone()], &committee)
376 .unwrap()
377 .try_into_verified_for_testing(&committee, &Default::default())
378 .unwrap();
379
380 let assigned_versions = send_consensus_no_execution(authority, &certificate).await;
381
382 Ok((certificate, assigned_versions))
383}
384
385pub async fn enqueue_all_and_execute_all(
386 authority: &AuthorityState,
387 certificates: Vec<(VerifiedCertificate, ExecutionEnv)>,
388) -> Result<Vec<TransactionEffects>, SuiError> {
389 authority.execution_scheduler.enqueue(
390 certificates
391 .iter()
392 .map(|(cert, env)| {
393 (
394 VerifiedExecutableTransaction::new_from_certificate(cert.clone()).into(),
395 env.clone(),
396 )
397 })
398 .collect(),
399 &authority.epoch_store_for_testing(),
400 );
401 let mut output = Vec::new();
402 for (cert, _) in certificates {
403 let effects = authority.notify_read_effects("", *cert.digest()).await?;
404 output.push(effects);
405 }
406 Ok(output)
407}
408
409pub async fn execute_sequenced_certificate_to_effects(
410 authority: &AuthorityState,
411 certificate: VerifiedCertificate,
412 assigned_versions: AssignedVersions,
413) -> (TransactionEffects, Option<ExecutionError>) {
414 let env = ExecutionEnv::new().with_assigned_versions(assigned_versions);
415 authority.execution_scheduler.enqueue(
416 vec![(
417 VerifiedExecutableTransaction::new_from_certificate(certificate.clone()).into(),
418 env.clone(),
419 )],
420 &authority.epoch_store_for_testing(),
421 );
422
423 let (result, execution_error_opt) = authority.try_execute_for_test(&certificate, env).await;
424 let effects = result.inner().data().clone();
425 (effects, execution_error_opt)
426}
427
428pub async fn send_consensus(
429 authority: &AuthorityState,
430 cert: &VerifiedCertificate,
431) -> AssignedVersions {
432 let assigned_versions = authority
433 .epoch_store_for_testing()
434 .assign_shared_object_versions_for_tests(
435 authority.get_object_cache_reader().as_ref(),
436 &vec![VerifiedExecutableTransaction::new_from_certificate(
437 cert.clone(),
438 )],
439 )
440 .unwrap();
441
442 let assigned_versions = assigned_versions
443 .into_map()
444 .get(&cert.key())
445 .cloned()
446 .unwrap_or_else(|| AssignedVersions::new(vec![], None));
447
448 let certs = vec![(
449 VerifiedExecutableTransaction::new_from_certificate(cert.clone()),
450 ExecutionEnv::new().with_assigned_versions(assigned_versions.clone()),
451 )];
452
453 authority
454 .execution_scheduler()
455 .enqueue_transactions(certs, &authority.epoch_store_for_testing());
456
457 assigned_versions
458}
459
460pub async fn send_consensus_no_execution(
461 authority: &AuthorityState,
462 cert: &VerifiedCertificate,
463) -> AssignedVersions {
464 let assigned_versions = authority
467 .epoch_store_for_testing()
468 .assign_shared_object_versions_for_tests(
469 authority.get_object_cache_reader().as_ref(),
470 &vec![VerifiedExecutableTransaction::new_from_certificate(
471 cert.clone(),
472 )],
473 )
474 .unwrap();
475
476 assigned_versions
477 .into_map()
478 .get(&cert.key())
479 .cloned()
480 .unwrap_or_else(|| AssignedVersions::new(vec![], None))
481}
482
483#[cfg(test)]
484pub async fn send_batch_consensus_no_execution<C>(
485 authority: &AuthorityState,
486 certificates: &[VerifiedCertificate],
487 consensus_handler: &mut crate::consensus_handler::ConsensusHandler<C>,
488 captured_transactions: &crate::consensus_test_utils::CapturedTransactions,
489) -> (Vec<Schedulable>, AssignedTxAndVersions)
490where
491 C: crate::checkpoints::CheckpointServiceNotify + Send + Sync + 'static,
492{
493 use crate::consensus_test_utils::TestConsensusCommit;
494 use sui_types::messages_consensus::ConsensusTransaction;
495
496 let consensus_transactions: Vec<ConsensusTransaction> = certificates
497 .iter()
498 .map(|cert| {
499 ConsensusTransaction::new_certificate_message(&authority.name, cert.clone().into())
500 })
501 .collect();
502
503 let epoch_store = authority.epoch_store_for_testing();
505 let round = epoch_store.get_highest_pending_checkpoint_height() + 1;
506 let timestamp_ms = epoch_store.epoch_start_state().epoch_start_timestamp_ms();
507 let sub_dag_index = 0;
508
509 let commit =
510 TestConsensusCommit::new(consensus_transactions, round, timestamp_ms, sub_dag_index);
511
512 consensus_handler
513 .handle_consensus_commit_for_test(commit)
514 .await;
515
516 tokio::time::sleep(std::time::Duration::from_millis(100)).await;
518
519 let (scheduled_txns, assigned_tx_and_versions) = {
520 let mut captured = captured_transactions.lock();
521 assert!(
522 !captured.is_empty(),
523 "Expected transactions to be scheduled"
524 );
525 let (scheduled_txns, assigned_tx_and_versions, _) = captured.remove(0);
526 (scheduled_txns, assigned_tx_and_versions)
527 };
528
529 (scheduled_txns, assigned_tx_and_versions)
530}