1use crate::accumulators::funds_read::AccountFundsRead;
5use crate::authority::AuthorityStore;
6use crate::authority::authority_per_epoch_store::AuthorityPerEpochStore;
7use crate::authority::authority_store::ExecutionLockWriteGuard;
8#[cfg(test)]
9use crate::authority::authority_store::SuiLockResult;
10use crate::authority::backpressure::BackpressureManager;
11use crate::authority::epoch_start_configuration::EpochFlag;
12use crate::authority::epoch_start_configuration::EpochStartConfiguration;
13use crate::global_state_hasher::GlobalStateHashStore;
14use crate::transaction_outputs::TransactionOutputs;
15use either::Either;
16use itertools::Itertools;
17use mysten_common::ZipDebugEqIteratorExt;
18use sui_types::accumulator_event::AccumulatorEvent;
19use sui_types::bridge::Bridge;
20
21use futures::{FutureExt, future::BoxFuture};
22use prometheus::Registry;
23use std::collections::HashSet;
24use std::path::Path;
25use std::sync::Arc;
26use sui_config::ExecutionCacheConfig;
27use sui_protocol_config::ProtocolVersion;
28use sui_types::base_types::{FullObjectID, VerifiedExecutionData};
29use sui_types::digests::{TransactionDigest, TransactionEffectsDigest};
30use sui_types::effects::{TransactionEffects, TransactionEvents};
31use sui_types::error::{SuiError, SuiErrorKind, SuiResult, UserInputError};
32use sui_types::executable_transaction::VerifiedExecutableTransaction;
33use sui_types::messages_checkpoint::CheckpointSequenceNumber;
34use sui_types::object::Object;
35use sui_types::storage::{
36 BackingPackageStore, BackingStore, FullObjectKey, MarkerValue, ObjectKey, ObjectOrTombstone,
37 ObjectStore, PackageObject, ParentSync, RuntimeObjectResolver,
38};
39use sui_types::sui_system_state::SuiSystemState;
40use sui_types::transaction::VerifiedTransaction;
41use sui_types::{
42 base_types::{EpochId, ObjectID, ObjectRef, SequenceNumber},
43 object::Owner,
44 storage::InputKey,
45};
46use typed_store::rocks::DBBatch;
47
48pub(crate) mod cache_types;
49pub mod metrics;
50mod object_locks;
51pub mod writeback_cache;
52
53pub use writeback_cache::WritebackCache;
54
55use metrics::ExecutionCacheMetrics;
56
57#[derive(Clone)]
62pub struct ExecutionCacheTraitPointers {
63 pub object_cache_reader: Arc<dyn ObjectCacheRead>,
64 pub transaction_cache_reader: Arc<dyn TransactionCacheRead>,
65 pub cache_writer: Arc<dyn ExecutionCacheWrite>,
66 pub backing_store: Arc<dyn BackingStore + Send + Sync>,
67 pub runtime_object_resolver: Arc<dyn RuntimeObjectResolver + Send + Sync>,
68 pub backing_package_store: Arc<dyn BackingPackageStore + Send + Sync>,
69 pub object_store: Arc<dyn ObjectStore + Send + Sync>,
70 pub reconfig_api: Arc<dyn ExecutionCacheReconfigAPI>,
71 pub global_state_hash_store: Arc<dyn GlobalStateHashStore>,
72 pub checkpoint_cache: Arc<dyn CheckpointCache>,
73 pub state_sync_store: Arc<dyn StateSyncAPI>,
74 pub cache_commit: Arc<dyn ExecutionCacheCommit>,
75 pub testing_api: Arc<dyn TestingAPI>,
76 pub account_funds_read: Arc<dyn AccountFundsRead>,
77}
78
79impl ExecutionCacheTraitPointers {
80 pub fn new<T>(cache: Arc<T>) -> Self
81 where
82 T: ObjectCacheRead
83 + TransactionCacheRead
84 + ExecutionCacheWrite
85 + BackingStore
86 + ExecutionCacheReconfigAPI
87 + GlobalStateHashStore
88 + CheckpointCache
89 + StateSyncAPI
90 + ExecutionCacheCommit
91 + TestingAPI
92 + AccountFundsRead
93 + 'static,
94 {
95 Self {
96 object_cache_reader: cache.clone(),
97 transaction_cache_reader: cache.clone(),
98 cache_writer: cache.clone(),
99 backing_store: cache.clone(),
100 runtime_object_resolver: cache.clone(),
101 backing_package_store: cache.clone(),
102 object_store: cache.clone(),
103 reconfig_api: cache.clone(),
104 global_state_hash_store: cache.clone(),
105 checkpoint_cache: cache.clone(),
106 state_sync_store: cache.clone(),
107 cache_commit: cache.clone(),
108 testing_api: cache.clone(),
109 account_funds_read: cache.clone(),
110 }
111 }
112}
113
114pub fn build_execution_cache(
115 cache_config: &ExecutionCacheConfig,
116 prometheus_registry: &Registry,
117 store: &Arc<AuthorityStore>,
118 backpressure_manager: Arc<BackpressureManager>,
119) -> ExecutionCacheTraitPointers {
120 let execution_cache_metrics = Arc::new(ExecutionCacheMetrics::new(prometheus_registry));
121
122 ExecutionCacheTraitPointers::new(
123 WritebackCache::new(
124 cache_config,
125 store.clone(),
126 execution_cache_metrics,
127 backpressure_manager,
128 )
129 .into(),
130 )
131}
132
133pub fn build_execution_cache_from_env(
136 prometheus_registry: &Registry,
137 store: &Arc<AuthorityStore>,
138) -> ExecutionCacheTraitPointers {
139 let execution_cache_metrics = Arc::new(ExecutionCacheMetrics::new(prometheus_registry));
140
141 ExecutionCacheTraitPointers::new(
142 WritebackCache::new(
143 &Default::default(),
144 store.clone(),
145 execution_cache_metrics,
146 BackpressureManager::new_for_tests(),
147 )
148 .into(),
149 )
150}
151
152pub type Batch = (Vec<Arc<TransactionOutputs>>, DBBatch);
153
154pub trait ExecutionCacheCommit: Send + Sync {
155 fn build_db_batch(&self, epoch: EpochId, digests: &[TransactionDigest]) -> Batch;
157
158 fn set_highest_committed_checkpoint_in_batch(
165 &self,
166 batch: &mut Batch,
167 checkpoint: CheckpointSequenceNumber,
168 );
169
170 fn commit_transaction_outputs(
174 &self,
175 epoch: EpochId,
176 batch: Batch,
177 digests: &[TransactionDigest],
178 );
179
180 fn persist_transaction(&self, transaction: &VerifiedExecutableTransaction);
184
185 fn approximate_pending_transaction_count(&self) -> u64;
187}
188
189pub trait ObjectCacheRead: Send + Sync {
190 fn get_package_object(&self, id: &ObjectID) -> SuiResult<Option<PackageObject>>;
191 fn force_reload_system_packages(&self, system_package_ids: &[ObjectID]);
192
193 fn get_object(&self, id: &ObjectID) -> Option<Object>;
194
195 fn get_objects(&self, objects: &[ObjectID]) -> Vec<Option<Object>> {
196 let mut ret = Vec::with_capacity(objects.len());
197 for object_id in objects {
198 ret.push(self.get_object(object_id));
199 }
200 ret
201 }
202
203 fn get_latest_object_ref_or_tombstone(&self, object_id: ObjectID) -> Option<ObjectRef>;
204
205 fn get_latest_object_or_tombstone(
206 &self,
207 object_id: ObjectID,
208 ) -> Option<(ObjectKey, ObjectOrTombstone)>;
209
210 fn get_object_by_key(&self, object_id: &ObjectID, version: SequenceNumber) -> Option<Object>;
211
212 fn multi_get_objects_by_key(&self, object_keys: &[ObjectKey]) -> Vec<Option<Object>>;
213
214 fn object_exists_by_key(&self, object_id: &ObjectID, version: SequenceNumber) -> bool;
215
216 fn multi_object_exists_by_key(&self, object_keys: &[ObjectKey]) -> Vec<bool>;
217
218 fn multi_get_objects_with_more_accurate_error_return(
226 &self,
227 object_refs: &[ObjectRef],
228 ) -> Result<Vec<Object>, SuiError> {
229 let objects = self
230 .multi_get_objects_by_key(&object_refs.iter().map(ObjectKey::from).collect::<Vec<_>>());
231 let mut result = Vec::new();
232 for (object_opt, object_ref) in objects.into_iter().zip_debug_eq(object_refs) {
233 match object_opt {
234 None => {
235 let live_objref = self._get_live_objref(object_ref.0)?;
236 let error = if live_objref.1 >= object_ref.1 {
237 UserInputError::ObjectVersionUnavailableForConsumption {
238 provided_obj_ref: *object_ref,
239 current_version: live_objref.1,
240 }
241 } else {
242 UserInputError::ObjectNotFound {
243 object_id: object_ref.0,
244 version: Some(object_ref.1),
245 }
246 };
247 return Err(SuiErrorKind::UserInputError { error }.into());
248 }
249 Some(object) => {
250 result.push(object);
251 }
252 }
253 }
254 assert_eq!(result.len(), object_refs.len());
255 Ok(result)
256 }
257
258 fn multi_input_objects_available(
262 &self,
263 keys: &[InputKey],
264 receiving_objects: &HashSet<InputKey>,
265 epoch: EpochId,
266 ) -> Vec<bool> {
267 let mut results = vec![false; keys.len()];
268 let non_canceled_keys = keys.iter().enumerate().filter(|(idx, key)| {
269 if key.is_cancelled() {
270 results[*idx] = true;
272 false
273 } else {
274 true
275 }
276 });
277 let (move_object_keys, package_object_keys): (Vec<_>, Vec<_>) = non_canceled_keys
278 .partition_map(|(idx, key)| match key {
279 InputKey::VersionedObject { id, version } => Either::Left((idx, (id, version))),
280 InputKey::Package { id } => Either::Right((idx, id)),
281 });
282
283 let (consensus_keys, fastpath_keys): (Vec<_>, Vec<_>) = (0..move_object_keys.len())
287 .partition(|i| matches!(move_object_keys[*i].1.0, FullObjectID::Consensus(_)));
288 let object_key = |i: &usize| {
289 let (id, version) = move_object_keys[*i].1;
290 ObjectKey(id.id(), *version)
291 };
292 let mut has_keys = vec![false; move_object_keys.len()];
293 for (i, object) in consensus_keys.iter().zip_debug_eq(
294 self.multi_get_objects_by_key(&consensus_keys.iter().map(object_key).collect_vec()),
295 ) {
296 has_keys[*i] = object.is_some_and(|o| o.full_id() == *move_object_keys[*i].1.0);
297 }
298 for (i, exists) in fastpath_keys.iter().zip_debug_eq(
299 self.multi_object_exists_by_key(&fastpath_keys.iter().map(object_key).collect_vec()),
300 ) {
301 has_keys[*i] = exists;
302 }
303
304 for ((idx, (id, version)), has_key) in move_object_keys.iter().zip_debug_eq(has_keys) {
305 if has_key {
307 results[*idx] = true;
308 } else if receiving_objects.contains(&InputKey::VersionedObject {
309 id: **id,
310 version: **version,
311 }) {
312 let is_available = self
319 .get_object(&id.id())
320 .map(|obj| obj.version() >= **version)
321 .unwrap_or(false)
322 || self.fastpath_stream_ended_at_version_or_after(id.id(), **version, epoch);
323 results[*idx] = is_available;
324 } else {
325 let is_consensus_stream_ended = self
328 .get_consensus_stream_end_tx_digest(FullObjectKey::new(**id, **version), epoch)
329 .is_some();
330 results[*idx] = is_consensus_stream_ended;
331 }
332 }
333
334 package_object_keys.into_iter().for_each(|(idx, id)| {
335 results[idx] = self.get_package_object(id).is_ok_and(|p| p.is_some());
338 });
339
340 results
341 }
342
343 fn multi_input_objects_available_cache_only(&self, keys: &[InputKey]) -> Vec<bool>;
344
345 fn find_object_lt_or_eq_version(
350 &self,
351 object_id: ObjectID,
352 version: SequenceNumber,
353 ) -> Option<Object>;
354
355 #[cfg(test)]
357 fn get_lock(&self, obj_ref: ObjectRef, epoch_store: &AuthorityPerEpochStore) -> SuiLockResult;
358
359 fn _get_live_objref(&self, object_id: ObjectID) -> SuiResult<ObjectRef>;
361
362 fn get_sui_system_state_object_unsafe(&self) -> SuiResult<SuiSystemState>;
363
364 fn get_bridge_object_unsafe(&self) -> SuiResult<Bridge>;
365
366 fn get_marker_value(&self, object_key: FullObjectKey, epoch_id: EpochId)
370 -> Option<MarkerValue>;
371
372 fn get_latest_marker(
374 &self,
375 object_id: FullObjectID,
376 epoch_id: EpochId,
377 ) -> Option<(SequenceNumber, MarkerValue)>;
378
379 fn get_last_consensus_stream_end_info(
382 &self,
383 object_id: FullObjectID,
384 epoch_id: EpochId,
385 ) -> Option<(SequenceNumber, TransactionDigest)> {
386 match self.get_latest_marker(object_id, epoch_id) {
387 Some((version, MarkerValue::ConsensusStreamEnded(digest))) => Some((version, digest)),
388 _ => None,
389 }
390 }
391
392 fn get_consensus_stream_end_tx_digest(
395 &self,
396 object_key: FullObjectKey,
397 epoch_id: EpochId,
398 ) -> Option<TransactionDigest> {
399 match self.get_marker_value(object_key, epoch_id) {
400 Some(MarkerValue::ConsensusStreamEnded(digest)) => Some(digest),
401 _ => None,
402 }
403 }
404
405 fn have_received_object_at_version(
406 &self,
407 object_key: FullObjectKey,
408 epoch_id: EpochId,
409 ) -> bool {
410 matches!(
411 self.get_marker_value(object_key, epoch_id),
412 Some(MarkerValue::Received)
413 )
414 }
415
416 fn fastpath_stream_ended_at_version_or_after(
417 &self,
418 object_id: ObjectID,
419 version: SequenceNumber,
420 epoch_id: EpochId,
421 ) -> bool {
422 let full_id = FullObjectID::Fastpath(object_id); matches!(
424 self.get_latest_marker(full_id, epoch_id),
425 Some((marker_version, MarkerValue::FastpathStreamEnded)) if marker_version >= version
426 )
427 }
428
429 fn get_highest_pruned_checkpoint(&self) -> Option<CheckpointSequenceNumber>;
431
432 fn notify_read_input_objects<'a>(
440 &'a self,
441 input_and_receiving_keys: &'a [InputKey],
442 receiving_keys: &'a HashSet<InputKey>,
443 epoch: EpochId,
444 ) -> BoxFuture<'a, ()>;
445}
446
447pub trait TransactionCacheRead: Send + Sync {
448 fn multi_get_transaction_blocks(
449 &self,
450 digests: &[TransactionDigest],
451 ) -> Vec<Option<Arc<VerifiedTransaction>>>;
452
453 fn get_transaction_block(
454 &self,
455 digest: &TransactionDigest,
456 ) -> Option<Arc<VerifiedTransaction>> {
457 self.multi_get_transaction_blocks(&[*digest])
458 .pop()
459 .expect("multi-get must return correct number of items")
460 }
461
462 fn multi_get_executed_effects_digests(
463 &self,
464 digests: &[TransactionDigest],
465 ) -> Vec<Option<TransactionEffectsDigest>>;
466
467 fn is_tx_already_executed(&self, digest: &TransactionDigest) -> bool {
468 self.multi_get_executed_effects_digests(&[*digest])
469 .pop()
470 .expect("multi-get must return correct number of items")
471 .is_some()
472 }
473
474 fn multi_get_executed_effects(
475 &self,
476 digests: &[TransactionDigest],
477 ) -> Vec<Option<TransactionEffects>> {
478 let effects_digests = self.multi_get_executed_effects_digests(digests);
479 assert_eq!(effects_digests.len(), digests.len());
480
481 let mut results = vec![None; digests.len()];
482 let mut fetch_digests = Vec::with_capacity(digests.len());
483 let mut fetch_indices = Vec::with_capacity(digests.len());
484
485 for (i, digest) in effects_digests.into_iter().enumerate() {
486 if let Some(digest) = digest {
487 fetch_digests.push(digest);
488 fetch_indices.push(i);
489 }
490 }
491
492 let effects = self.multi_get_effects(&fetch_digests);
493 for (i, effects) in fetch_indices.into_iter().zip_debug_eq(effects) {
494 results[i] = effects;
495 }
496
497 results
498 }
499
500 fn get_executed_effects(&self, digest: &TransactionDigest) -> Option<TransactionEffects> {
501 self.multi_get_executed_effects(&[*digest])
502 .pop()
503 .expect("multi-get must return correct number of items")
504 }
505
506 fn transaction_executed_in_last_epoch(
507 &self,
508 digest: &TransactionDigest,
509 current_epoch: EpochId,
510 ) -> bool;
511
512 fn multi_get_effects(
513 &self,
514 digests: &[TransactionEffectsDigest],
515 ) -> Vec<Option<TransactionEffects>>;
516
517 fn get_effects(&self, digest: &TransactionEffectsDigest) -> Option<TransactionEffects> {
518 self.multi_get_effects(&[*digest])
519 .pop()
520 .expect("multi-get must return correct number of items")
521 }
522
523 fn multi_get_events(&self, digests: &[TransactionDigest]) -> Vec<Option<TransactionEvents>>;
524
525 fn get_events(&self, digest: &TransactionDigest) -> Option<TransactionEvents> {
526 self.multi_get_events(&[*digest])
527 .pop()
528 .expect("multi-get must return correct number of items")
529 }
530
531 fn get_unchanged_loaded_runtime_objects(
532 &self,
533 digest: &TransactionDigest,
534 ) -> Option<Vec<ObjectKey>>;
535
536 fn multi_get_unchanged_loaded_runtime_objects(
537 &self,
538 digests: &[TransactionDigest],
539 ) -> Vec<Option<Vec<ObjectKey>>> {
540 digests
541 .iter()
542 .map(|digest| self.get_unchanged_loaded_runtime_objects(digest))
543 .collect()
544 }
545
546 fn take_accumulator_events(&self, digest: &TransactionDigest) -> Option<Vec<AccumulatorEvent>>;
547
548 fn notify_read_executed_effects_digests<'a>(
549 &'a self,
550 task_name: &'static str,
551 digests: &'a [TransactionDigest],
552 ) -> BoxFuture<'a, Vec<TransactionEffectsDigest>>;
553
554 fn notify_read_executed_effects<'a>(
567 &'a self,
568 task_name: &'static str,
569 digests: &'a [TransactionDigest],
570 ) -> BoxFuture<'a, Vec<TransactionEffects>> {
571 async move {
572 self.notify_read_executed_effects_may_fail(task_name, digests)
573 .await
574 .unwrap_or_else(|e| panic!("effects must exist: {e}"))
575 }
576 .boxed()
577 }
578
579 fn notify_read_executed_effects_may_fail<'a>(
584 &'a self,
585 task_name: &'static str,
586 digests: &'a [TransactionDigest],
587 ) -> BoxFuture<'a, SuiResult<Vec<TransactionEffects>>> {
588 async move {
589 let effects_digests = self
590 .notify_read_executed_effects_digests(task_name, digests)
591 .await;
592 self.multi_get_effects(&effects_digests)
593 .into_iter()
594 .zip_debug_eq(digests)
595 .map(|(e, digest)| {
596 e.ok_or_else(|| {
597 SuiError::from(SuiErrorKind::TransactionEffectsNotFound { digest: *digest })
598 })
599 })
600 .collect()
601 }
602 .boxed()
603 }
604}
605
606pub trait ExecutionCacheWrite: Send + Sync {
607 fn write_transaction_outputs(&self, epoch_id: EpochId, tx_outputs: Arc<TransactionOutputs>);
625
626 fn validate_owned_object_versions(&self, owned_input_objects: &[ObjectRef]) -> SuiResult;
629
630 #[cfg(test)]
634 fn write_object_entry_for_test(&self, object: Object);
635}
636
637pub trait CheckpointCache: Send + Sync {
638 fn deprecated_get_transaction_checkpoint(
643 &self,
644 digest: &TransactionDigest,
645 ) -> Option<(EpochId, CheckpointSequenceNumber)>;
646
647 fn deprecated_multi_get_transaction_checkpoint(
648 &self,
649 digests: &[TransactionDigest],
650 ) -> Vec<Option<(EpochId, CheckpointSequenceNumber)>>;
651
652 fn deprecated_insert_finalized_transactions(
653 &self,
654 digests: &[TransactionDigest],
655 epoch: EpochId,
656 sequence: CheckpointSequenceNumber,
657 );
658}
659
660pub trait ExecutionCacheReconfigAPI: Send + Sync {
661 fn insert_genesis_object(&self, object: Object);
662 fn bulk_insert_genesis_objects(&self, objects: &[Object]);
663
664 fn set_epoch_start_configuration(&self, epoch_start_config: &EpochStartConfiguration);
665
666 fn update_epoch_flags_metrics(&self, old: &[EpochFlag], new: &[EpochFlag]);
667
668 fn clear_state_end_of_epoch(&self, execution_guard: &ExecutionLockWriteGuard<'_>);
669
670 fn expensive_check_sui_conservation(
671 &self,
672 old_epoch_store: &AuthorityPerEpochStore,
673 ) -> SuiResult;
674
675 fn checkpoint_db(&self, path: &Path) -> SuiResult;
676
677 fn maybe_reaccumulate_state_hash(
680 &self,
681 cur_epoch_store: &AuthorityPerEpochStore,
682 new_protocol_version: ProtocolVersion,
683 );
684
685 fn reconfigure_cache<'a>(
689 &'a self,
690 epoch_start_config: &'a EpochStartConfiguration,
691 ) -> BoxFuture<'a, ()>;
692}
693
694pub trait StateSyncAPI: Send + Sync {
698 fn insert_transaction_and_effects(
699 &self,
700 transaction: &VerifiedTransaction,
701 transaction_effects: &TransactionEffects,
702 );
703
704 fn multi_insert_transaction_and_effects(
705 &self,
706 transactions_and_effects: &[VerifiedExecutionData],
707 );
708}
709
710pub trait TestingAPI: Send + Sync {
711 fn database_for_testing(&self) -> Arc<AuthorityStore>;
712
713 fn cache_for_testing(&self) -> &WritebackCache;
714}
715
716macro_rules! implement_storage_traits {
717 ($implementor: ident) => {
718 impl ObjectStore for $implementor {
719 fn get_object(&self, object_id: &ObjectID) -> Option<Object> {
720 ObjectCacheRead::get_object(self, object_id)
721 }
722
723 fn get_object_by_key(
724 &self,
725 object_id: &ObjectID,
726 version: sui_types::base_types::VersionNumber,
727 ) -> Option<Object> {
728 ObjectCacheRead::get_object_by_key(self, object_id, version)
729 }
730
731 fn load_implicitly_read_system_object(
732 &self,
733 object_id: &ObjectID,
734 version: sui_types::base_types::ConsensusObjectVersion,
735 ) -> Option<Object> {
736 $implementor::load_implicitly_read_system_object(self, object_id, version)
737 }
738 }
739
740 impl RuntimeObjectResolver for $implementor {
741 fn read_child_object(
742 &self,
743 parent: &ObjectID,
744 child: &ObjectID,
745 child_version_upper_bound: SequenceNumber,
746 ) -> SuiResult<Option<Object>> {
747 let Some(child_object) =
748 self.find_object_lt_or_eq_version(*child, child_version_upper_bound)
749 else {
750 return Ok(None);
751 };
752
753 let parent = *parent;
754 if child_object.owner != Owner::ObjectOwner(parent.into()) {
755 return Err(SuiErrorKind::InvalidChildObjectAccess {
756 object: *child,
757 given_parent: parent,
758 actual_owner: child_object.owner.clone(),
759 }
760 .into());
761 }
762 Ok(Some(child_object))
763 }
764
765 fn get_object_received_at_version(
766 &self,
767 owner: &ObjectID,
768 receiving_object_id: &ObjectID,
769 receive_object_at_version: SequenceNumber,
770 epoch_id: EpochId,
771 ) -> SuiResult<Option<Object>> {
772 let Some(recv_object) = ObjectCacheRead::get_object_by_key(
773 self,
774 receiving_object_id,
775 receive_object_at_version,
776 ) else {
777 return Ok(None);
778 };
779
780 if recv_object.owner != Owner::AddressOwner((*owner).into())
786 || self.have_received_object_at_version(
787 FullObjectKey::new(
789 FullObjectID::new(*receiving_object_id, None),
790 receive_object_at_version,
791 ),
792 epoch_id,
793 )
794 {
795 return Ok(None);
796 }
797
798 Ok(Some(recv_object))
799 }
800 }
801
802 impl BackingPackageStore for $implementor {
803 fn get_package_object(
804 &self,
805 package_id: &ObjectID,
806 ) -> SuiResult<Option<PackageObject>> {
807 ObjectCacheRead::get_package_object(self, package_id)
808 }
809 }
810
811 impl ParentSync for $implementor {
812 fn get_latest_parent_entry_ref_deprecated(
813 &self,
814 object_id: ObjectID,
815 ) -> Option<ObjectRef> {
816 ObjectCacheRead::get_latest_object_ref_or_tombstone(self, object_id)
817 }
818 }
819 };
820}
821
822macro_rules! implement_passthrough_traits {
824 ($implementor: ident) => {
825 impl CheckpointCache for $implementor {
826 fn deprecated_get_transaction_checkpoint(
827 &self,
828 digest: &TransactionDigest,
829 ) -> Option<(EpochId, CheckpointSequenceNumber)> {
830 self.store
831 .deprecated_get_transaction_checkpoint(digest)
832 .expect("db error")
833 }
834
835 fn deprecated_multi_get_transaction_checkpoint(
836 &self,
837 digests: &[TransactionDigest],
838 ) -> Vec<Option<(EpochId, CheckpointSequenceNumber)>> {
839 self.store
840 .deprecated_multi_get_transaction_checkpoint(digests)
841 .expect("db error")
842 }
843
844 fn deprecated_insert_finalized_transactions(
845 &self,
846 digests: &[TransactionDigest],
847 epoch: EpochId,
848 sequence: CheckpointSequenceNumber,
849 ) {
850 self.store
851 .deprecated_insert_finalized_transactions(digests, epoch, sequence)
852 .expect("db error");
853 }
854 }
855
856 impl ExecutionCacheReconfigAPI for $implementor {
857 fn insert_genesis_object(&self, object: Object) {
858 self.insert_genesis_object_impl(object)
859 }
860
861 fn bulk_insert_genesis_objects(&self, objects: &[Object]) {
862 self.bulk_insert_genesis_objects_impl(objects)
863 }
864
865 fn set_epoch_start_configuration(&self, epoch_start_config: &EpochStartConfiguration) {
866 self.store
867 .set_epoch_start_configuration(epoch_start_config)
868 .expect("db error");
869 }
870
871 fn update_epoch_flags_metrics(&self, old: &[EpochFlag], new: &[EpochFlag]) {
872 self.store.update_epoch_flags_metrics(old, new)
873 }
874
875 fn clear_state_end_of_epoch(&self, execution_guard: &ExecutionLockWriteGuard<'_>) {
876 self.clear_state_end_of_epoch_impl(execution_guard)
877 }
878
879 fn expensive_check_sui_conservation(
880 &self,
881 old_epoch_store: &AuthorityPerEpochStore,
882 ) -> SuiResult {
883 self.store
884 .expensive_check_sui_conservation(self, old_epoch_store)
885 }
886
887 fn checkpoint_db(&self, path: &std::path::Path) -> SuiResult {
888 self.store.perpetual_tables.checkpoint_db(path)
889 }
890
891 fn maybe_reaccumulate_state_hash(
892 &self,
893 cur_epoch_store: &AuthorityPerEpochStore,
894 new_protocol_version: ProtocolVersion,
895 ) {
896 self.store
897 .maybe_reaccumulate_state_hash(cur_epoch_store, new_protocol_version)
898 }
899
900 fn reconfigure_cache<'a>(
901 &'a self,
902 _: &'a EpochStartConfiguration,
903 ) -> BoxFuture<'a, ()> {
904 std::future::ready(()).boxed()
908 }
909 }
910
911 impl TestingAPI for $implementor {
912 fn database_for_testing(&self) -> Arc<AuthorityStore> {
913 self.store.clone()
914 }
915
916 fn cache_for_testing(&self) -> &WritebackCache {
917 self
918 }
919 }
920 };
921}
922
923use implement_passthrough_traits;
924
925implement_storage_traits!(WritebackCache);
926
927pub trait ExecutionCacheAPI:
928 ObjectCacheRead
929 + ExecutionCacheWrite
930 + ExecutionCacheCommit
931 + ExecutionCacheReconfigAPI
932 + CheckpointCache
933 + StateSyncAPI
934{
935}