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