1use crate::accumulators::funds_read::AccountFundsRead;
5use crate::authority::AuthorityStore;
6use crate::authority::authority_per_epoch_store::AuthorityPerEpochStore;
7use crate::authority::authority_store::{ExecutionLockWriteGuard, SuiLockResult};
8use crate::authority::backpressure::BackpressureManager;
9use crate::authority::epoch_start_configuration::EpochFlag;
10use crate::authority::epoch_start_configuration::EpochStartConfiguration;
11use crate::global_state_hasher::GlobalStateHashStore;
12use crate::transaction_outputs::TransactionOutputs;
13use either::Either;
14use itertools::Itertools;
15use mysten_common::ZipDebugEqIteratorExt;
16use sui_types::accumulator_event::AccumulatorEvent;
17use sui_types::bridge::Bridge;
18
19use futures::{FutureExt, future::BoxFuture};
20use prometheus::Registry;
21use std::collections::HashSet;
22use std::path::Path;
23use std::sync::Arc;
24use sui_config::ExecutionCacheConfig;
25use sui_protocol_config::ProtocolVersion;
26use sui_types::base_types::{FullObjectID, VerifiedExecutionData};
27use sui_types::digests::{TransactionDigest, TransactionEffectsDigest};
28use sui_types::effects::{TransactionEffects, TransactionEvents};
29use sui_types::error::{SuiError, SuiErrorKind, SuiResult, UserInputError};
30use sui_types::executable_transaction::VerifiedExecutableTransaction;
31use sui_types::messages_checkpoint::CheckpointSequenceNumber;
32use sui_types::object::Object;
33use sui_types::storage::{
34 BackingPackageStore, BackingStore, ChildObjectResolver, FullObjectKey, MarkerValue, ObjectKey,
35 ObjectOrTombstone, ObjectStore, PackageObject, ParentSync,
36};
37use sui_types::sui_system_state::SuiSystemState;
38use sui_types::transaction::VerifiedTransaction;
39use sui_types::{
40 base_types::{EpochId, ObjectID, ObjectRef, SequenceNumber},
41 object::Owner,
42 storage::InputKey,
43};
44use typed_store::rocks::DBBatch;
45
46pub(crate) mod cache_types;
47pub mod metrics;
48mod object_locks;
49pub mod writeback_cache;
50
51pub use writeback_cache::WritebackCache;
52
53use metrics::ExecutionCacheMetrics;
54
55#[derive(Clone)]
60pub struct ExecutionCacheTraitPointers {
61 pub object_cache_reader: Arc<dyn ObjectCacheRead>,
62 pub transaction_cache_reader: Arc<dyn TransactionCacheRead>,
63 pub cache_writer: Arc<dyn ExecutionCacheWrite>,
64 pub backing_store: Arc<dyn BackingStore + Send + Sync>,
65 pub child_object_resolver: Arc<dyn ChildObjectResolver + Send + Sync>,
66 pub backing_package_store: Arc<dyn BackingPackageStore + Send + Sync>,
67 pub object_store: Arc<dyn ObjectStore + Send + Sync>,
68 pub reconfig_api: Arc<dyn ExecutionCacheReconfigAPI>,
69 pub global_state_hash_store: Arc<dyn GlobalStateHashStore>,
70 pub checkpoint_cache: Arc<dyn CheckpointCache>,
71 pub state_sync_store: Arc<dyn StateSyncAPI>,
72 pub cache_commit: Arc<dyn ExecutionCacheCommit>,
73 pub testing_api: Arc<dyn TestingAPI>,
74 pub account_funds_read: Arc<dyn AccountFundsRead>,
75}
76
77impl ExecutionCacheTraitPointers {
78 pub fn new<T>(cache: Arc<T>) -> Self
79 where
80 T: ObjectCacheRead
81 + TransactionCacheRead
82 + ExecutionCacheWrite
83 + BackingStore
84 + BackingPackageStore
85 + ObjectStore
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 child_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 for ((idx, (id, version)), has_key) in move_object_keys.iter().zip_debug_eq(
284 self.multi_object_exists_by_key(
285 &move_object_keys
286 .iter()
287 .map(|(_, k)| ObjectKey(k.0.id(), *k.1))
288 .collect::<Vec<_>>(),
289 )
290 .into_iter(),
291 ) {
292 if has_key {
294 results[*idx] = true;
295 } else if receiving_objects.contains(&InputKey::VersionedObject {
296 id: **id,
297 version: **version,
298 }) {
299 let is_available = self
306 .get_object(&id.id())
307 .map(|obj| obj.version() >= **version)
308 .unwrap_or(false)
309 || self.fastpath_stream_ended_at_version_or_after(id.id(), **version, epoch);
310 results[*idx] = is_available;
311 } else {
312 let is_consensus_stream_ended = self
315 .get_consensus_stream_end_tx_digest(FullObjectKey::new(**id, **version), epoch)
316 .is_some();
317 results[*idx] = is_consensus_stream_ended;
318 }
319 }
320
321 package_object_keys.into_iter().for_each(|(idx, id)| {
322 results[idx] = self.get_package_object(id).is_ok_and(|p| p.is_some());
325 });
326
327 results
328 }
329
330 fn multi_input_objects_available_cache_only(&self, keys: &[InputKey]) -> Vec<bool>;
331
332 fn find_object_lt_or_eq_version(
337 &self,
338 object_id: ObjectID,
339 version: SequenceNumber,
340 ) -> Option<Object>;
341
342 fn get_lock(&self, obj_ref: ObjectRef, epoch_store: &AuthorityPerEpochStore) -> SuiLockResult;
343
344 fn _get_live_objref(&self, object_id: ObjectID) -> SuiResult<ObjectRef>;
346
347 fn check_owned_objects_are_live(&self, owned_object_refs: &[ObjectRef]) -> SuiResult;
350
351 fn get_sui_system_state_object_unsafe(&self) -> SuiResult<SuiSystemState>;
352
353 fn get_bridge_object_unsafe(&self) -> SuiResult<Bridge>;
354
355 fn get_marker_value(&self, object_key: FullObjectKey, epoch_id: EpochId)
359 -> Option<MarkerValue>;
360
361 fn get_latest_marker(
363 &self,
364 object_id: FullObjectID,
365 epoch_id: EpochId,
366 ) -> Option<(SequenceNumber, MarkerValue)>;
367
368 fn get_last_consensus_stream_end_info(
371 &self,
372 object_id: FullObjectID,
373 epoch_id: EpochId,
374 ) -> Option<(SequenceNumber, TransactionDigest)> {
375 match self.get_latest_marker(object_id, epoch_id) {
376 Some((version, MarkerValue::ConsensusStreamEnded(digest))) => Some((version, digest)),
377 _ => None,
378 }
379 }
380
381 fn get_consensus_stream_end_tx_digest(
384 &self,
385 object_key: FullObjectKey,
386 epoch_id: EpochId,
387 ) -> Option<TransactionDigest> {
388 match self.get_marker_value(object_key, epoch_id) {
389 Some(MarkerValue::ConsensusStreamEnded(digest)) => Some(digest),
390 _ => None,
391 }
392 }
393
394 fn have_received_object_at_version(
395 &self,
396 object_key: FullObjectKey,
397 epoch_id: EpochId,
398 ) -> bool {
399 matches!(
400 self.get_marker_value(object_key, epoch_id),
401 Some(MarkerValue::Received)
402 )
403 }
404
405 fn fastpath_stream_ended_at_version_or_after(
406 &self,
407 object_id: ObjectID,
408 version: SequenceNumber,
409 epoch_id: EpochId,
410 ) -> bool {
411 let full_id = FullObjectID::Fastpath(object_id); matches!(
413 self.get_latest_marker(full_id, epoch_id),
414 Some((marker_version, MarkerValue::FastpathStreamEnded)) if marker_version >= version
415 )
416 }
417
418 fn get_highest_pruned_checkpoint(&self) -> Option<CheckpointSequenceNumber>;
420
421 fn notify_read_input_objects<'a>(
429 &'a self,
430 input_and_receiving_keys: &'a [InputKey],
431 receiving_keys: &'a HashSet<InputKey>,
432 epoch: EpochId,
433 ) -> BoxFuture<'a, ()>;
434}
435
436pub trait TransactionCacheRead: Send + Sync {
437 fn multi_get_transaction_blocks(
438 &self,
439 digests: &[TransactionDigest],
440 ) -> Vec<Option<Arc<VerifiedTransaction>>>;
441
442 fn get_transaction_block(
443 &self,
444 digest: &TransactionDigest,
445 ) -> Option<Arc<VerifiedTransaction>> {
446 self.multi_get_transaction_blocks(&[*digest])
447 .pop()
448 .expect("multi-get must return correct number of items")
449 }
450
451 fn multi_get_executed_effects_digests(
452 &self,
453 digests: &[TransactionDigest],
454 ) -> Vec<Option<TransactionEffectsDigest>>;
455
456 fn is_tx_already_executed(&self, digest: &TransactionDigest) -> bool {
457 self.multi_get_executed_effects_digests(&[*digest])
458 .pop()
459 .expect("multi-get must return correct number of items")
460 .is_some()
461 }
462
463 fn multi_get_executed_effects(
464 &self,
465 digests: &[TransactionDigest],
466 ) -> Vec<Option<TransactionEffects>> {
467 let effects_digests = self.multi_get_executed_effects_digests(digests);
468 assert_eq!(effects_digests.len(), digests.len());
469
470 let mut results = vec![None; digests.len()];
471 let mut fetch_digests = Vec::with_capacity(digests.len());
472 let mut fetch_indices = Vec::with_capacity(digests.len());
473
474 for (i, digest) in effects_digests.into_iter().enumerate() {
475 if let Some(digest) = digest {
476 fetch_digests.push(digest);
477 fetch_indices.push(i);
478 }
479 }
480
481 let effects = self.multi_get_effects(&fetch_digests);
482 for (i, effects) in fetch_indices.into_iter().zip_debug_eq(effects.into_iter()) {
483 results[i] = effects;
484 }
485
486 results
487 }
488
489 fn get_executed_effects(&self, digest: &TransactionDigest) -> Option<TransactionEffects> {
490 self.multi_get_executed_effects(&[*digest])
491 .pop()
492 .expect("multi-get must return correct number of items")
493 }
494
495 fn transaction_executed_in_last_epoch(
496 &self,
497 digest: &TransactionDigest,
498 current_epoch: EpochId,
499 ) -> bool;
500
501 fn multi_get_effects(
502 &self,
503 digests: &[TransactionEffectsDigest],
504 ) -> Vec<Option<TransactionEffects>>;
505
506 fn get_effects(&self, digest: &TransactionEffectsDigest) -> Option<TransactionEffects> {
507 self.multi_get_effects(&[*digest])
508 .pop()
509 .expect("multi-get must return correct number of items")
510 }
511
512 fn multi_get_events(&self, digests: &[TransactionDigest]) -> Vec<Option<TransactionEvents>>;
513
514 fn get_events(&self, digest: &TransactionDigest) -> Option<TransactionEvents> {
515 self.multi_get_events(&[*digest])
516 .pop()
517 .expect("multi-get must return correct number of items")
518 }
519
520 fn get_unchanged_loaded_runtime_objects(
521 &self,
522 digest: &TransactionDigest,
523 ) -> Option<Vec<ObjectKey>>;
524
525 fn take_accumulator_events(&self, digest: &TransactionDigest) -> Option<Vec<AccumulatorEvent>>;
526
527 fn notify_read_executed_effects_digests<'a>(
528 &'a self,
529 task_name: &'static str,
530 digests: &'a [TransactionDigest],
531 ) -> BoxFuture<'a, Vec<TransactionEffectsDigest>>;
532
533 fn notify_read_executed_effects<'a>(
546 &'a self,
547 task_name: &'static str,
548 digests: &'a [TransactionDigest],
549 ) -> BoxFuture<'a, Vec<TransactionEffects>> {
550 async move {
551 self.notify_read_executed_effects_may_fail(task_name, digests)
552 .await
553 .unwrap_or_else(|e| panic!("effects must exist: {e}"))
554 }
555 .boxed()
556 }
557
558 fn notify_read_executed_effects_may_fail<'a>(
563 &'a self,
564 task_name: &'static str,
565 digests: &'a [TransactionDigest],
566 ) -> BoxFuture<'a, SuiResult<Vec<TransactionEffects>>> {
567 async move {
568 let effects_digests = self
569 .notify_read_executed_effects_digests(task_name, digests)
570 .await;
571 self.multi_get_effects(&effects_digests)
572 .into_iter()
573 .zip_debug_eq(digests)
574 .map(|(e, digest)| {
575 e.ok_or_else(|| {
576 SuiError::from(SuiErrorKind::TransactionEffectsNotFound { digest: *digest })
577 })
578 })
579 .collect()
580 }
581 .boxed()
582 }
583}
584
585pub trait ExecutionCacheWrite: Send + Sync {
586 fn write_transaction_outputs(&self, epoch_id: EpochId, tx_outputs: Arc<TransactionOutputs>);
604
605 fn validate_owned_object_versions(&self, owned_input_objects: &[ObjectRef]) -> SuiResult;
608
609 #[cfg(test)]
613 fn write_object_entry_for_test(&self, object: Object);
614}
615
616pub trait CheckpointCache: Send + Sync {
617 fn deprecated_get_transaction_checkpoint(
622 &self,
623 digest: &TransactionDigest,
624 ) -> Option<(EpochId, CheckpointSequenceNumber)>;
625
626 fn deprecated_multi_get_transaction_checkpoint(
627 &self,
628 digests: &[TransactionDigest],
629 ) -> Vec<Option<(EpochId, CheckpointSequenceNumber)>>;
630
631 fn deprecated_insert_finalized_transactions(
632 &self,
633 digests: &[TransactionDigest],
634 epoch: EpochId,
635 sequence: CheckpointSequenceNumber,
636 );
637}
638
639pub trait ExecutionCacheReconfigAPI: Send + Sync {
640 fn insert_genesis_object(&self, object: Object);
641 fn bulk_insert_genesis_objects(&self, objects: &[Object]);
642
643 fn set_epoch_start_configuration(&self, epoch_start_config: &EpochStartConfiguration);
644
645 fn update_epoch_flags_metrics(&self, old: &[EpochFlag], new: &[EpochFlag]);
646
647 fn clear_state_end_of_epoch(&self, execution_guard: &ExecutionLockWriteGuard<'_>);
648
649 fn expensive_check_sui_conservation(
650 &self,
651 old_epoch_store: &AuthorityPerEpochStore,
652 ) -> SuiResult;
653
654 fn checkpoint_db(&self, path: &Path) -> SuiResult;
655
656 fn maybe_reaccumulate_state_hash(
659 &self,
660 cur_epoch_store: &AuthorityPerEpochStore,
661 new_protocol_version: ProtocolVersion,
662 );
663
664 fn reconfigure_cache<'a>(
668 &'a self,
669 epoch_start_config: &'a EpochStartConfiguration,
670 ) -> BoxFuture<'a, ()>;
671}
672
673pub trait StateSyncAPI: Send + Sync {
677 fn insert_transaction_and_effects(
678 &self,
679 transaction: &VerifiedTransaction,
680 transaction_effects: &TransactionEffects,
681 );
682
683 fn multi_insert_transaction_and_effects(
684 &self,
685 transactions_and_effects: &[VerifiedExecutionData],
686 );
687}
688
689pub trait TestingAPI: Send + Sync {
690 fn database_for_testing(&self) -> Arc<AuthorityStore>;
691
692 fn cache_for_testing(&self) -> &WritebackCache;
693}
694
695macro_rules! implement_storage_traits {
696 ($implementor: ident) => {
697 impl ObjectStore for $implementor {
698 fn get_object(&self, object_id: &ObjectID) -> Option<Object> {
699 ObjectCacheRead::get_object(self, object_id)
700 }
701
702 fn get_object_by_key(
703 &self,
704 object_id: &ObjectID,
705 version: sui_types::base_types::VersionNumber,
706 ) -> Option<Object> {
707 ObjectCacheRead::get_object_by_key(self, object_id, version)
708 }
709 }
710
711 impl ChildObjectResolver for $implementor {
712 fn read_child_object(
713 &self,
714 parent: &ObjectID,
715 child: &ObjectID,
716 child_version_upper_bound: SequenceNumber,
717 ) -> SuiResult<Option<Object>> {
718 let Some(child_object) =
719 self.find_object_lt_or_eq_version(*child, child_version_upper_bound)
720 else {
721 return Ok(None);
722 };
723
724 let parent = *parent;
725 if child_object.owner != Owner::ObjectOwner(parent.into()) {
726 return Err(SuiErrorKind::InvalidChildObjectAccess {
727 object: *child,
728 given_parent: parent,
729 actual_owner: child_object.owner.clone(),
730 }
731 .into());
732 }
733 Ok(Some(child_object))
734 }
735
736 fn get_object_received_at_version(
737 &self,
738 owner: &ObjectID,
739 receiving_object_id: &ObjectID,
740 receive_object_at_version: SequenceNumber,
741 epoch_id: EpochId,
742 ) -> SuiResult<Option<Object>> {
743 let Some(recv_object) = ObjectCacheRead::get_object_by_key(
744 self,
745 receiving_object_id,
746 receive_object_at_version,
747 ) else {
748 return Ok(None);
749 };
750
751 if recv_object.owner != Owner::AddressOwner((*owner).into())
757 || self.have_received_object_at_version(
758 FullObjectKey::new(
760 FullObjectID::new(*receiving_object_id, None),
761 receive_object_at_version,
762 ),
763 epoch_id,
764 )
765 {
766 return Ok(None);
767 }
768
769 Ok(Some(recv_object))
770 }
771 }
772
773 impl BackingPackageStore for $implementor {
774 fn get_package_object(
775 &self,
776 package_id: &ObjectID,
777 ) -> SuiResult<Option<PackageObject>> {
778 ObjectCacheRead::get_package_object(self, package_id)
779 }
780 }
781
782 impl ParentSync for $implementor {
783 fn get_latest_parent_entry_ref_deprecated(
784 &self,
785 object_id: ObjectID,
786 ) -> Option<ObjectRef> {
787 ObjectCacheRead::get_latest_object_ref_or_tombstone(self, object_id)
788 }
789 }
790 };
791}
792
793macro_rules! implement_passthrough_traits {
795 ($implementor: ident) => {
796 impl CheckpointCache for $implementor {
797 fn deprecated_get_transaction_checkpoint(
798 &self,
799 digest: &TransactionDigest,
800 ) -> Option<(EpochId, CheckpointSequenceNumber)> {
801 self.store
802 .deprecated_get_transaction_checkpoint(digest)
803 .expect("db error")
804 }
805
806 fn deprecated_multi_get_transaction_checkpoint(
807 &self,
808 digests: &[TransactionDigest],
809 ) -> Vec<Option<(EpochId, CheckpointSequenceNumber)>> {
810 self.store
811 .deprecated_multi_get_transaction_checkpoint(digests)
812 .expect("db error")
813 }
814
815 fn deprecated_insert_finalized_transactions(
816 &self,
817 digests: &[TransactionDigest],
818 epoch: EpochId,
819 sequence: CheckpointSequenceNumber,
820 ) {
821 self.store
822 .deprecated_insert_finalized_transactions(digests, epoch, sequence)
823 .expect("db error");
824 }
825 }
826
827 impl ExecutionCacheReconfigAPI for $implementor {
828 fn insert_genesis_object(&self, object: Object) {
829 self.insert_genesis_object_impl(object)
830 }
831
832 fn bulk_insert_genesis_objects(&self, objects: &[Object]) {
833 self.bulk_insert_genesis_objects_impl(objects)
834 }
835
836 fn set_epoch_start_configuration(&self, epoch_start_config: &EpochStartConfiguration) {
837 self.store
838 .set_epoch_start_configuration(epoch_start_config)
839 .expect("db error");
840 }
841
842 fn update_epoch_flags_metrics(&self, old: &[EpochFlag], new: &[EpochFlag]) {
843 self.store.update_epoch_flags_metrics(old, new)
844 }
845
846 fn clear_state_end_of_epoch(&self, execution_guard: &ExecutionLockWriteGuard<'_>) {
847 self.clear_state_end_of_epoch_impl(execution_guard)
848 }
849
850 fn expensive_check_sui_conservation(
851 &self,
852 old_epoch_store: &AuthorityPerEpochStore,
853 ) -> SuiResult {
854 self.store
855 .expensive_check_sui_conservation(self, old_epoch_store)
856 }
857
858 fn checkpoint_db(&self, path: &std::path::Path) -> SuiResult {
859 self.store.perpetual_tables.checkpoint_db(path)
860 }
861
862 fn maybe_reaccumulate_state_hash(
863 &self,
864 cur_epoch_store: &AuthorityPerEpochStore,
865 new_protocol_version: ProtocolVersion,
866 ) {
867 self.store
868 .maybe_reaccumulate_state_hash(cur_epoch_store, new_protocol_version)
869 }
870
871 fn reconfigure_cache<'a>(
872 &'a self,
873 _: &'a EpochStartConfiguration,
874 ) -> BoxFuture<'a, ()> {
875 std::future::ready(()).boxed()
879 }
880 }
881
882 impl TestingAPI for $implementor {
883 fn database_for_testing(&self) -> Arc<AuthorityStore> {
884 self.store.clone()
885 }
886
887 fn cache_for_testing(&self) -> &WritebackCache {
888 self
889 }
890 }
891 };
892}
893
894use implement_passthrough_traits;
895
896implement_storage_traits!(WritebackCache);
897
898pub trait ExecutionCacheAPI:
899 ObjectCacheRead
900 + ExecutionCacheWrite
901 + ExecutionCacheCommit
902 + ExecutionCacheReconfigAPI
903 + CheckpointCache
904 + StateSyncAPI
905{
906}