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