sui_single_node_benchmark/
single_node.rs1use crate::command::Component;
5use crate::mock_storage::InMemoryObjectStore;
6use std::collections::{BTreeMap, HashMap};
7use std::sync::Arc;
8use sui_core::authority::authority_per_epoch_store::AuthorityPerEpochStore;
9use sui_core::authority::authority_store_tables::LiveObject;
10use sui_core::authority::shared_object_version_manager::{
11 AssignedTxAndVersions, AssignedVersions, Schedulable,
12};
13use sui_core::authority::test_authority_builder::TestAuthorityBuilder;
14use sui_core::authority::{AuthorityState, ExecutionEnv};
15use sui_core::authority_server::{ValidatorService, ValidatorServiceMetrics};
16use sui_core::checkpoints::checkpoint_executor::CheckpointExecutor;
17use sui_core::consensus_adapter::{
18 ConnectionMonitorStatusForTests, ConsensusAdapter, ConsensusAdapterMetrics,
19};
20use sui_core::execution_scheduler::SchedulingSource;
21use sui_core::global_state_hasher::GlobalStateHasher;
22use sui_core::mock_checkpoint_builder::{MockCheckpointBuilder, ValidatorKeypairProvider};
23use sui_core::mock_consensus::{ConsensusMode, MockConsensusClient};
24use sui_test_transaction_builder::{PublishData, TestTransactionBuilder};
25use sui_types::base_types::{AuthorityName, ObjectRef, SuiAddress, TransactionDigest};
26use sui_types::committee::Committee;
27use sui_types::crypto::{AccountKeyPair, AuthoritySignature, Signer};
28use sui_types::effects::{TransactionEffects, TransactionEffectsAPI};
29use sui_types::executable_transaction::VerifiedExecutableTransaction;
30use sui_types::execution_params::ExecutionOrEarlyError;
31use sui_types::messages_checkpoint::{VerifiedCheckpoint, VerifiedCheckpointContents};
32use sui_types::messages_grpc::HandleTransactionResponse;
33use sui_types::object::Object;
34use sui_types::transaction::{
35 CertifiedTransaction, DEFAULT_VALIDATOR_GAS_PRICE, Transaction, TransactionDataAPI,
36 VerifiedCertificate, VerifiedTransaction,
37};
38
39#[derive(Clone)]
40pub struct SingleValidator {
41 validator_service: Arc<ValidatorService>,
42 epoch_store: Arc<AuthorityPerEpochStore>,
43}
44
45impl SingleValidator {
46 pub(crate) async fn new(genesis_objects: &[Object], component: Component) -> Self {
47 let validator = TestAuthorityBuilder::new()
48 .disable_indexer()
49 .with_starting_objects(genesis_objects)
50 .insert_genesis_checkpoint()
52 .build()
53 .await;
54 let epoch_store = validator.epoch_store_for_testing().clone();
55 let consensus_mode = match component {
56 Component::ValidatorWithFakeConsensus => ConsensusMode::DirectSequencing,
57 _ => ConsensusMode::Noop,
58 };
59 let consensus_adapter = Arc::new(ConsensusAdapter::new(
60 Arc::new(MockConsensusClient::new(
61 Arc::downgrade(&validator),
62 consensus_mode,
63 )),
64 validator.checkpoint_store.clone(),
65 validator.name,
66 Arc::new(ConnectionMonitorStatusForTests {}),
67 100_000,
68 100_000,
69 None,
70 None,
71 ConsensusAdapterMetrics::new_test(),
72 epoch_store.protocol_config().clone(),
73 ));
74 let validator_service = Arc::new(ValidatorService::new_for_tests(
78 validator,
79 consensus_adapter,
80 Arc::new(ValidatorServiceMetrics::new_for_tests()),
81 ));
82 Self {
83 validator_service,
84 epoch_store,
85 }
86 }
87
88 pub fn get_validator(&self) -> &Arc<AuthorityState> {
89 self.validator_service.validator_state()
90 }
91
92 pub fn get_epoch_store(&self) -> &Arc<AuthorityPerEpochStore> {
93 &self.epoch_store
94 }
95
96 pub async fn publish_package(
98 &self,
99 publish_data: PublishData,
100 sender: SuiAddress,
101 keypair: &AccountKeyPair,
102 gas: ObjectRef,
103 ) -> (ObjectRef, ObjectRef) {
104 let tx_builder = TestTransactionBuilder::new(sender, gas, DEFAULT_VALIDATOR_GAS_PRICE)
105 .publish_with_data_async(publish_data)
106 .await;
107 let transaction = tx_builder.build_and_sign(keypair);
108 let effects = self.execute_raw_transaction(transaction).await;
109 let package = effects
110 .all_changed_objects()
111 .into_iter()
112 .filter_map(|(oref, owner, _)| owner.is_immutable().then_some(oref))
113 .next()
114 .unwrap();
115 let updated_gas = effects.gas_object().0;
116 (package, updated_gas)
117 }
118
119 pub async fn execute_raw_transaction(&self, transaction: Transaction) -> TransactionEffects {
120 let executable = VerifiedExecutableTransaction::new_from_quorum_execution(
121 VerifiedTransaction::new_unchecked(transaction),
122 0,
123 );
124 let effects = self
125 .get_validator()
126 .try_execute_immediately(
127 &executable,
128 ExecutionEnv::new().with_scheduling_source(SchedulingSource::NonFastPath),
129 &self.epoch_store,
130 )
131 .await
132 .unwrap()
133 .0;
134 assert!(effects.status().is_ok());
135 effects
136 }
137
138 pub async fn execute_dry_run(&self, transaction: Transaction) -> TransactionEffects {
139 let effects = self
140 .get_validator()
141 .dry_exec_transaction_for_benchmark(
142 transaction.data().intent_message().value.clone(),
143 *transaction.digest(),
144 )
145 .unwrap()
146 .2;
147 assert!(effects.status().is_ok());
148 effects
149 }
150
151 pub async fn execute_certificate(
152 &self,
153 cert: CertifiedTransaction,
154 assigned_versions: &AssignedVersions,
155 component: Component,
156 ) -> TransactionEffects {
157 let effects = match component {
158 Component::Baseline => {
159 let cert = VerifiedExecutableTransaction::new_from_certificate(
160 VerifiedCertificate::new_unchecked(cert),
161 );
162 self.get_validator()
163 .try_execute_immediately(
164 &cert,
165 ExecutionEnv::new().with_assigned_versions(assigned_versions.clone()),
166 &self.epoch_store,
167 )
168 .await
169 .unwrap()
170 .0
171 }
172 Component::WithTxManager => {
173 let cert = VerifiedCertificate::new_unchecked(cert);
174 if cert.is_consensus_tx() {
175 self.get_validator().execution_scheduler().enqueue(
178 vec![(
179 VerifiedExecutableTransaction::new_from_certificate(cert.clone())
180 .into(),
181 ExecutionEnv::new().with_assigned_versions(assigned_versions.clone()),
182 )],
183 &self.epoch_store,
184 );
185 }
186 self.get_validator()
187 .wait_for_certificate_execution(&cert, &self.epoch_store)
188 .await
189 .unwrap()
190 }
191 Component::ValidatorWithoutConsensus | Component::ValidatorWithFakeConsensus => {
192 let response = self
193 .validator_service
194 .execute_certificate_for_testing(cert)
195 .await
196 .unwrap()
197 .into_inner();
198 response.signed_effects.into_data()
199 }
200 Component::TxnSigning | Component::CheckpointExecutor | Component::ExecutionOnly => {
201 unreachable!()
202 }
203 };
204 assert!(effects.status().is_ok());
205 effects
206 }
207
208 pub(crate) async fn execute_transaction_in_memory(
209 &self,
210 store: InMemoryObjectStore,
211 transaction: CertifiedTransaction,
212 assigned_versions: &AssignedVersions,
213 ) -> TransactionEffects {
214 let input_objects = transaction.transaction_data().input_objects().unwrap();
215 let objects = store
216 .read_objects_for_execution(&transaction.key(), assigned_versions, &input_objects)
217 .unwrap();
218
219 let executable = VerifiedExecutableTransaction::new_from_certificate(
220 VerifiedCertificate::new_unchecked(transaction),
221 );
222 let (gas_status, input_objects) = sui_transaction_checks::check_certificate_input(
223 &executable,
224 objects,
225 self.epoch_store.protocol_config(),
226 self.epoch_store.reference_gas_price(),
227 )
228 .unwrap();
229 let (kind, signer, gas_data) = executable.transaction_data().execution_parts();
230 let (inner_temp_store, _, effects, _timings, _) =
231 self.epoch_store.executor().execute_transaction_to_effects(
232 &store,
233 self.epoch_store.protocol_config(),
234 self.get_validator().metrics.limits_metrics.clone(),
235 false,
236 ExecutionOrEarlyError::Ok(()),
237 &self.epoch_store.epoch(),
238 0,
239 input_objects,
240 gas_data,
241 gas_status,
242 kind,
243 signer,
244 *executable.digest(),
245 &mut None,
246 );
247 assert!(effects.status().is_ok());
248 store.commit_objects(inner_temp_store);
249 effects
250 }
251
252 pub async fn sign_transaction(&self, transaction: Transaction) -> HandleTransactionResponse {
253 self.validator_service
254 .handle_transaction_for_benchmarking(transaction)
255 .await
256 .unwrap()
257 .into_inner()
258 }
259
260 pub(crate) async fn build_checkpoints(
261 &self,
262 transactions: Vec<CertifiedTransaction>,
263 mut all_effects: BTreeMap<TransactionDigest, TransactionEffects>,
264 checkpoint_size: usize,
265 ) -> Vec<(VerifiedCheckpoint, VerifiedCheckpointContents)> {
266 let mut builder = MockCheckpointBuilder::new(
267 self.get_validator()
268 .get_checkpoint_store()
269 .get_latest_certified_checkpoint()
270 .unwrap()
271 .unwrap(),
272 );
273 let mut checkpoints = vec![];
274 for transaction in transactions {
275 let effects = all_effects.remove(transaction.digest()).unwrap();
276 builder.push_transaction(
277 VerifiedTransaction::new_unchecked(transaction.into_unsigned()),
278 effects,
279 );
280 if builder.size() == checkpoint_size {
281 let (checkpoint, _, full_contents) = builder.build(self, 0);
282 checkpoints.push((checkpoint, full_contents));
283 }
284 }
285 if builder.size() > 0 {
286 let (checkpoint, _, full_contents) = builder.build(self, 0);
287 checkpoints.push((checkpoint, full_contents));
288 }
289 checkpoints
290 }
291
292 pub fn create_checkpoint_executor(&self) -> CheckpointExecutor {
293 let validator = self.get_validator();
294 CheckpointExecutor::new_for_tests(
295 self.epoch_store.clone(),
296 validator.get_checkpoint_store().clone(),
297 validator.clone(),
298 Arc::new(GlobalStateHasher::new_for_tests(
299 validator.get_global_state_hash_store().clone(),
300 )),
301 )
302 }
303
304 pub(crate) fn create_in_memory_store(&self) -> InMemoryObjectStore {
305 let objects: HashMap<_, _> = self
306 .get_validator()
307 .get_global_state_hash_store()
308 .iter_cached_live_object_set_for_testing(false)
309 .map(|o| match o {
310 LiveObject::Normal(object) => (object.id(), object),
311 LiveObject::Wrapped(_) => unreachable!(),
312 })
313 .collect();
314 InMemoryObjectStore::new(objects)
315 }
316
317 pub(crate) async fn assigned_shared_object_versions(
318 &self,
319 transactions: &[CertifiedTransaction],
320 ) -> AssignedTxAndVersions {
321 let transactions: Vec<_> = transactions
322 .iter()
323 .map(|tx| {
324 VerifiedExecutableTransaction::new_from_certificate(
325 VerifiedCertificate::new_unchecked(tx.clone()),
326 )
327 })
328 .collect();
329 let assignables: Vec<_> = transactions.iter().map(Schedulable::Transaction).collect();
330 self.epoch_store
331 .assign_shared_object_versions_idempotent(
332 self.get_validator().get_object_cache_reader().as_ref(),
333 assignables.iter(),
334 )
335 .unwrap()
336 }
337}
338
339impl ValidatorKeypairProvider for SingleValidator {
340 fn get_validator_key(&self, name: &AuthorityName) -> &dyn Signer<AuthoritySignature> {
341 assert_eq!(name, &self.get_validator().name);
342 &*self.get_validator().secret
343 }
344
345 fn get_committee(&self) -> &Committee {
346 self.epoch_store.committee().as_ref()
347 }
348}