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