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