1pub mod error;
5mod object_store_trait;
6mod read_store;
7mod shared_in_memory_store;
8mod write_store;
9
10use crate::base_types::{
11 ConsensusObjectSequenceKey, FullObjectID, FullObjectRef, SuiAddress, TransactionDigest,
12 VersionNumber,
13};
14use crate::committee::EpochId;
15use crate::effects::{TransactionEffects, TransactionEffectsAPI};
16use crate::error::{ExecutionError, SuiError, SuiErrorKind};
17use crate::execution::{DynamicallyLoadedObjectMetadata, ExecutionResults};
18use crate::full_checkpoint_content::ObjectSet;
19use crate::message_envelope::Message;
20use crate::move_package::MovePackage;
21use crate::storage::error::Error as StorageError;
22use crate::transaction::TransactionData;
23use crate::transaction::{SenderSignedData, TransactionDataAPI};
24use crate::{
25 base_types::{ObjectID, ObjectRef, SequenceNumber},
26 error::SuiResult,
27 object::Object,
28};
29use itertools::Itertools;
30use move_binary_format::CompiledModule;
31use move_core_types::language_storage::{ModuleId, TypeTag};
32pub use object_store_trait::ObjectStore;
33pub use read_store::BalanceInfo;
34pub use read_store::BalanceIterator;
35pub use read_store::CoinInfo;
36pub use read_store::DynamicFieldIndexInfo;
37pub use read_store::DynamicFieldKey;
38pub use read_store::EpochInfo;
39pub use read_store::OwnedObjectInfo;
40pub use read_store::ReadStore;
41pub use read_store::RpcIndexes;
42pub use read_store::RpcStateReader;
43pub use read_store::TransactionInfo;
44use serde::{Deserialize, Serialize};
45use serde_with::serde_as;
46pub use shared_in_memory_store::SharedInMemoryStore;
47pub use shared_in_memory_store::SingleCheckpointSharedInMemoryStore;
48use std::collections::{BTreeMap, BTreeSet};
49use std::fmt::{Display, Formatter};
50use std::sync::Arc;
51pub use write_store::WriteStore;
52
53#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
55pub enum InputKey {
56 VersionedObject {
57 id: FullObjectID,
58 version: SequenceNumber,
59 },
60 Package {
61 id: ObjectID,
62 },
63}
64
65impl InputKey {
66 pub fn id(&self) -> FullObjectID {
67 match self {
68 InputKey::VersionedObject { id, .. } => *id,
69 InputKey::Package { id } => FullObjectID::Fastpath(*id),
70 }
71 }
72
73 pub fn version(&self) -> Option<SequenceNumber> {
74 match self {
75 InputKey::VersionedObject { version, .. } => Some(*version),
76 InputKey::Package { .. } => None,
77 }
78 }
79
80 pub fn is_cancelled(&self) -> bool {
81 match self {
82 InputKey::VersionedObject { version, .. } => version.is_cancelled(),
83 InputKey::Package { .. } => false,
84 }
85 }
86}
87
88impl From<&Object> for InputKey {
89 fn from(obj: &Object) -> Self {
90 if obj.is_package() {
91 InputKey::Package { id: obj.id() }
92 } else {
93 InputKey::VersionedObject {
94 id: obj.full_id(),
95 version: obj.version(),
96 }
97 }
98 }
99}
100
101#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
102pub enum WriteKind {
103 Mutate,
105 Create,
107 Unwrap,
109}
110
111#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
112pub enum DeleteKind {
113 Normal,
115 UnwrapThenDelete,
118 Wrap,
120}
121
122#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
123pub enum MarkerValue {
124 Received,
127 FastpathStreamEnded,
131 ConsensusStreamEnded(TransactionDigest),
134}
135
136#[derive(Debug)]
143pub enum DeleteKindWithOldVersion {
144 Normal(SequenceNumber),
145 UnwrapThenDeleteDEPRECATED(SequenceNumber),
147 UnwrapThenDelete,
148 Wrap(SequenceNumber),
149}
150
151impl DeleteKindWithOldVersion {
152 pub fn old_version(&self) -> Option<SequenceNumber> {
153 match self {
154 DeleteKindWithOldVersion::Normal(version)
155 | DeleteKindWithOldVersion::UnwrapThenDeleteDEPRECATED(version)
156 | DeleteKindWithOldVersion::Wrap(version) => Some(*version),
157 DeleteKindWithOldVersion::UnwrapThenDelete => None,
158 }
159 }
160
161 pub fn to_delete_kind(&self) -> DeleteKind {
162 match self {
163 DeleteKindWithOldVersion::Normal(_) => DeleteKind::Normal,
164 DeleteKindWithOldVersion::UnwrapThenDeleteDEPRECATED(_)
165 | DeleteKindWithOldVersion::UnwrapThenDelete => DeleteKind::UnwrapThenDelete,
166 DeleteKindWithOldVersion::Wrap(_) => DeleteKind::Wrap,
167 }
168 }
169}
170
171#[derive(Debug)]
172pub enum ObjectChange {
173 Write(Object, WriteKind),
174 Delete(DeleteKindWithOldVersion),
176}
177
178pub trait StorageView: Storage + ParentSync + ChildObjectResolver {}
179impl<T: Storage + ParentSync + ChildObjectResolver> StorageView for T {}
180
181pub trait ChildObjectResolver {
184 fn read_child_object(
186 &self,
187 parent: &ObjectID,
188 child: &ObjectID,
189 child_version_upper_bound: SequenceNumber,
190 ) -> SuiResult<Option<Object>>;
191
192 fn get_object_received_at_version(
198 &self,
199 owner: &ObjectID,
200 receiving_object_id: &ObjectID,
201 receive_object_at_version: SequenceNumber,
202 epoch_id: EpochId,
203 ) -> SuiResult<Option<Object>>;
204}
205
206pub struct DenyListResult {
207 pub result: Result<(), ExecutionError>,
210 pub num_non_gas_coin_owners: u64,
212}
213
214pub trait Storage {
216 fn reset(&mut self);
217
218 fn read_object(&self, id: &ObjectID) -> Option<&Object>;
219
220 fn record_execution_results(&mut self, results: ExecutionResults)
221 -> Result<(), ExecutionError>;
222
223 fn save_loaded_runtime_objects(
224 &mut self,
225 loaded_runtime_objects: BTreeMap<ObjectID, DynamicallyLoadedObjectMetadata>,
226 );
227
228 fn save_wrapped_object_containers(
229 &mut self,
230 wrapped_object_containers: BTreeMap<ObjectID, ObjectID>,
231 );
232
233 fn check_coin_deny_list(
236 &self,
237 receiving_funds_type_and_owners: BTreeMap<TypeTag, BTreeSet<SuiAddress>>,
238 ) -> DenyListResult;
239
240 fn record_generated_object_ids(&mut self, generated_ids: BTreeSet<ObjectID>);
241}
242
243pub type PackageFetchResults<Package> = Result<Vec<Package>, Vec<ObjectID>>;
244
245#[derive(Clone, Debug)]
246pub struct PackageObject {
247 package_object: Object,
248}
249
250impl PackageObject {
251 pub fn new(package_object: Object) -> Self {
252 assert!(package_object.is_package());
253 Self { package_object }
254 }
255
256 pub fn object(&self) -> &Object {
257 &self.package_object
258 }
259
260 pub fn move_package(&self) -> &MovePackage {
261 self.package_object.data.try_as_package().unwrap()
262 }
263}
264
265impl From<PackageObject> for Object {
266 fn from(package_object_arc: PackageObject) -> Self {
267 package_object_arc.package_object
268 }
269}
270
271pub trait BackingPackageStore {
272 fn get_package_object(&self, package_id: &ObjectID) -> SuiResult<Option<PackageObject>>;
273}
274
275impl<S: ?Sized + BackingPackageStore> BackingPackageStore for Box<S> {
276 fn get_package_object(&self, package_id: &ObjectID) -> SuiResult<Option<PackageObject>> {
277 BackingPackageStore::get_package_object(self.as_ref(), package_id)
278 }
279}
280
281impl<S: ?Sized + BackingPackageStore> BackingPackageStore for Arc<S> {
282 fn get_package_object(&self, package_id: &ObjectID) -> SuiResult<Option<PackageObject>> {
283 BackingPackageStore::get_package_object(self.as_ref(), package_id)
284 }
285}
286
287impl<S: ?Sized + BackingPackageStore> BackingPackageStore for &S {
288 fn get_package_object(&self, package_id: &ObjectID) -> SuiResult<Option<PackageObject>> {
289 BackingPackageStore::get_package_object(*self, package_id)
290 }
291}
292
293impl<S: ?Sized + BackingPackageStore> BackingPackageStore for &mut S {
294 fn get_package_object(&self, package_id: &ObjectID) -> SuiResult<Option<PackageObject>> {
295 BackingPackageStore::get_package_object(*self, package_id)
296 }
297}
298
299pub fn load_package_object_from_object_store(
300 store: &impl ObjectStore,
301 package_id: &ObjectID,
302) -> SuiResult<Option<PackageObject>> {
303 let package = store.get_object(package_id);
304 if let Some(obj) = &package {
305 fp_ensure!(
306 obj.is_package(),
307 SuiErrorKind::BadObjectType {
308 error: format!("Package expected, Move object found: {package_id}"),
309 }
310 .into()
311 );
312 }
313 Ok(package.map(PackageObject::new))
314}
315
316pub fn get_package_objects<'a>(
320 store: &impl BackingPackageStore,
321 package_ids: impl IntoIterator<Item = &'a ObjectID>,
322) -> SuiResult<PackageFetchResults<PackageObject>> {
323 let packages: Vec<Result<_, _>> = package_ids
324 .into_iter()
325 .map(|id| match store.get_package_object(id) {
326 Ok(None) => Ok(Err(*id)),
327 Ok(Some(o)) => Ok(Ok(o)),
328 Err(x) => Err(x),
329 })
330 .collect::<SuiResult<_>>()?;
331
332 let (fetched, failed_to_fetch): (Vec<_>, Vec<_>) = packages.into_iter().partition_result();
333 if !failed_to_fetch.is_empty() {
334 Ok(Err(failed_to_fetch))
335 } else {
336 Ok(Ok(fetched))
337 }
338}
339
340pub fn get_module(
341 store: impl BackingPackageStore,
342 module_id: &ModuleId,
343) -> Result<Option<Vec<u8>>, SuiError> {
344 Ok(store
345 .get_package_object(&ObjectID::from(*module_id.address()))?
346 .and_then(|package| {
347 package
348 .move_package()
349 .serialized_module_map()
350 .get(module_id.name().as_str())
351 .cloned()
352 }))
353}
354
355pub fn get_module_by_id<S: BackingPackageStore>(
356 store: &S,
357 id: &ModuleId,
358) -> anyhow::Result<Option<CompiledModule>, SuiError> {
359 Ok(get_module(store, id)?
360 .map(|bytes| CompiledModule::deserialize_with_defaults(&bytes).unwrap()))
361}
362
363pub struct PostExecutionPackageResolver {
368 backing_store: Arc<dyn BackingPackageStore>,
369 new_packages: BTreeMap<ObjectID, PackageObject>,
370}
371
372impl PostExecutionPackageResolver {
373 pub fn new(
374 backing_store: Arc<dyn BackingPackageStore>,
375 output_objects: &Option<Vec<Object>>,
376 ) -> Self {
377 let new_packages = output_objects
378 .iter()
379 .flatten()
380 .filter_map(|o| {
381 if o.is_package() {
382 Some((o.id(), PackageObject::new(o.clone())))
383 } else {
384 None
385 }
386 })
387 .collect();
388 Self {
389 backing_store,
390 new_packages,
391 }
392 }
393}
394
395impl BackingPackageStore for PostExecutionPackageResolver {
396 fn get_package_object(&self, package_id: &ObjectID) -> SuiResult<Option<PackageObject>> {
397 if let Some(package) = self.new_packages.get(package_id) {
398 Ok(Some(package.clone()))
399 } else {
400 self.backing_store.get_package_object(package_id)
401 }
402 }
403}
404
405pub trait ParentSync {
406 fn get_latest_parent_entry_ref_deprecated(&self, object_id: ObjectID) -> Option<ObjectRef>;
409}
410
411impl<S: ParentSync> ParentSync for std::sync::Arc<S> {
412 fn get_latest_parent_entry_ref_deprecated(&self, object_id: ObjectID) -> Option<ObjectRef> {
413 ParentSync::get_latest_parent_entry_ref_deprecated(self.as_ref(), object_id)
414 }
415}
416
417impl<S: ParentSync> ParentSync for &S {
418 fn get_latest_parent_entry_ref_deprecated(&self, object_id: ObjectID) -> Option<ObjectRef> {
419 ParentSync::get_latest_parent_entry_ref_deprecated(*self, object_id)
420 }
421}
422
423impl<S: ParentSync> ParentSync for &mut S {
424 fn get_latest_parent_entry_ref_deprecated(&self, object_id: ObjectID) -> Option<ObjectRef> {
425 ParentSync::get_latest_parent_entry_ref_deprecated(*self, object_id)
426 }
427}
428
429impl<S: ChildObjectResolver> ChildObjectResolver for std::sync::Arc<S> {
430 fn read_child_object(
431 &self,
432 parent: &ObjectID,
433 child: &ObjectID,
434 child_version_upper_bound: SequenceNumber,
435 ) -> SuiResult<Option<Object>> {
436 ChildObjectResolver::read_child_object(
437 self.as_ref(),
438 parent,
439 child,
440 child_version_upper_bound,
441 )
442 }
443 fn get_object_received_at_version(
444 &self,
445 owner: &ObjectID,
446 receiving_object_id: &ObjectID,
447 receive_object_at_version: SequenceNumber,
448 epoch_id: EpochId,
449 ) -> SuiResult<Option<Object>> {
450 ChildObjectResolver::get_object_received_at_version(
451 self.as_ref(),
452 owner,
453 receiving_object_id,
454 receive_object_at_version,
455 epoch_id,
456 )
457 }
458}
459
460impl<S: ChildObjectResolver> ChildObjectResolver for &S {
461 fn read_child_object(
462 &self,
463 parent: &ObjectID,
464 child: &ObjectID,
465 child_version_upper_bound: SequenceNumber,
466 ) -> SuiResult<Option<Object>> {
467 ChildObjectResolver::read_child_object(*self, parent, child, child_version_upper_bound)
468 }
469 fn get_object_received_at_version(
470 &self,
471 owner: &ObjectID,
472 receiving_object_id: &ObjectID,
473 receive_object_at_version: SequenceNumber,
474 epoch_id: EpochId,
475 ) -> SuiResult<Option<Object>> {
476 ChildObjectResolver::get_object_received_at_version(
477 *self,
478 owner,
479 receiving_object_id,
480 receive_object_at_version,
481 epoch_id,
482 )
483 }
484}
485
486impl<S: ChildObjectResolver> ChildObjectResolver for &mut S {
487 fn read_child_object(
488 &self,
489 parent: &ObjectID,
490 child: &ObjectID,
491 child_version_upper_bound: SequenceNumber,
492 ) -> SuiResult<Option<Object>> {
493 ChildObjectResolver::read_child_object(*self, parent, child, child_version_upper_bound)
494 }
495 fn get_object_received_at_version(
496 &self,
497 owner: &ObjectID,
498 receiving_object_id: &ObjectID,
499 receive_object_at_version: SequenceNumber,
500 epoch_id: EpochId,
501 ) -> SuiResult<Option<Object>> {
502 ChildObjectResolver::get_object_received_at_version(
503 *self,
504 owner,
505 receiving_object_id,
506 receive_object_at_version,
507 epoch_id,
508 )
509 }
510}
511
512#[serde_as]
513#[derive(Eq, PartialEq, Clone, Copy, PartialOrd, Ord, Hash, Serialize, Deserialize, Debug)]
514pub struct ObjectKey(pub ObjectID, pub VersionNumber);
515
516impl ObjectKey {
517 pub const ZERO: ObjectKey = ObjectKey(ObjectID::ZERO, VersionNumber::MIN);
518
519 pub fn max_for_id(id: &ObjectID) -> Self {
520 Self(*id, VersionNumber::MAX)
521 }
522
523 pub fn min_for_id(id: &ObjectID) -> Self {
524 Self(*id, VersionNumber::MIN)
525 }
526}
527
528impl From<ObjectRef> for ObjectKey {
529 fn from(object_ref: ObjectRef) -> Self {
530 ObjectKey::from(&object_ref)
531 }
532}
533
534impl From<&ObjectRef> for ObjectKey {
535 fn from(object_ref: &ObjectRef) -> Self {
536 Self(object_ref.0, object_ref.1)
537 }
538}
539
540#[serde_as]
541#[derive(Eq, PartialEq, Clone, Copy, PartialOrd, Ord, Hash, Serialize, Deserialize, Debug)]
542pub struct ConsensusObjectKey(pub ConsensusObjectSequenceKey, pub VersionNumber);
543
544#[serde_as]
548#[derive(Eq, PartialEq, Clone, Copy, PartialOrd, Ord, Hash, Serialize, Deserialize, Debug)]
549pub enum FullObjectKey {
550 Fastpath(ObjectKey),
551 Consensus(ConsensusObjectKey),
552}
553
554impl FullObjectKey {
555 pub fn max_for_id(id: &FullObjectID) -> Self {
556 match id {
557 FullObjectID::Fastpath(object_id) => Self::Fastpath(ObjectKey::max_for_id(object_id)),
558 FullObjectID::Consensus(consensus_object_sequence_key) => Self::Consensus(
559 ConsensusObjectKey(*consensus_object_sequence_key, VersionNumber::MAX),
560 ),
561 }
562 }
563
564 pub fn min_for_id(id: &FullObjectID) -> Self {
565 match id {
566 FullObjectID::Fastpath(object_id) => Self::Fastpath(ObjectKey::min_for_id(object_id)),
567 FullObjectID::Consensus(consensus_object_sequence_key) => Self::Consensus(
568 ConsensusObjectKey(*consensus_object_sequence_key, VersionNumber::MIN),
569 ),
570 }
571 }
572
573 pub fn new(object_id: FullObjectID, version: VersionNumber) -> Self {
574 match object_id {
575 FullObjectID::Fastpath(object_id) => Self::Fastpath(ObjectKey(object_id, version)),
576 FullObjectID::Consensus(consensus_object_sequence_key) => {
577 Self::Consensus(ConsensusObjectKey(consensus_object_sequence_key, version))
578 }
579 }
580 }
581
582 pub fn id(&self) -> FullObjectID {
583 match self {
584 FullObjectKey::Fastpath(object_key) => FullObjectID::Fastpath(object_key.0),
585 FullObjectKey::Consensus(consensus_object_key) => {
586 FullObjectID::Consensus(consensus_object_key.0)
587 }
588 }
589 }
590
591 pub fn version(&self) -> VersionNumber {
592 match self {
593 FullObjectKey::Fastpath(object_key) => object_key.1,
594 FullObjectKey::Consensus(consensus_object_key) => consensus_object_key.1,
595 }
596 }
597}
598
599impl From<FullObjectRef> for FullObjectKey {
600 fn from(object_ref: FullObjectRef) -> Self {
601 FullObjectKey::from(&object_ref)
602 }
603}
604
605impl From<&FullObjectRef> for FullObjectKey {
606 fn from(object_ref: &FullObjectRef) -> Self {
607 FullObjectKey::new(object_ref.0, object_ref.1)
608 }
609}
610
611#[derive(Clone)]
612pub enum ObjectOrTombstone {
613 Object(Object),
614 Tombstone(ObjectRef),
615}
616
617impl ObjectOrTombstone {
618 pub fn as_objref(&self) -> ObjectRef {
619 match self {
620 ObjectOrTombstone::Object(obj) => obj.compute_object_reference(),
621 ObjectOrTombstone::Tombstone(obref) => *obref,
622 }
623 }
624}
625
626impl From<Object> for ObjectOrTombstone {
627 fn from(object: Object) -> Self {
628 ObjectOrTombstone::Object(object)
629 }
630}
631
632pub fn transaction_non_shared_input_object_keys(
635 tx: &SenderSignedData,
636) -> SuiResult<Vec<ObjectKey>> {
637 use crate::transaction::InputObjectKind as I;
638 Ok(tx
639 .intent_message()
640 .value
641 .input_objects()?
642 .into_iter()
643 .filter_map(|object| match object {
644 I::MovePackage(_) | I::SharedMoveObject { .. } => None,
645 I::ImmOrOwnedMoveObject(obj) => Some(obj.into()),
646 })
647 .collect())
648}
649
650pub fn transaction_receiving_object_keys(tx: &SenderSignedData) -> Vec<ObjectKey> {
651 tx.intent_message()
652 .value
653 .receiving_objects()
654 .into_iter()
655 .map(|oref| oref.into())
656 .collect()
657}
658
659impl Display for DeleteKind {
660 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
661 match self {
662 DeleteKind::Wrap => write!(f, "Wrap"),
663 DeleteKind::Normal => write!(f, "Normal"),
664 DeleteKind::UnwrapThenDelete => write!(f, "UnwrapThenDelete"),
665 }
666 }
667}
668
669pub trait BackingStore:
670 BackingPackageStore + ChildObjectResolver + ObjectStore + ParentSync
671{
672 fn as_object_store(&self) -> &dyn ObjectStore;
673}
674
675impl<T> BackingStore for T
676where
677 T: BackingPackageStore,
678 T: ChildObjectResolver,
679 T: ObjectStore,
680 T: ParentSync,
681{
682 fn as_object_store(&self) -> &dyn ObjectStore {
683 self
684 }
685}
686
687pub fn get_transaction_input_objects(
688 object_store: &dyn ObjectStore,
689 effects: &TransactionEffects,
690) -> Result<Vec<Object>, StorageError> {
691 let input_object_keys = effects
692 .modified_at_versions()
693 .into_iter()
694 .map(|(object_id, version)| ObjectKey(object_id, version))
695 .collect::<Vec<_>>();
696
697 let input_objects = object_store
698 .multi_get_objects_by_key(&input_object_keys)
699 .into_iter()
700 .enumerate()
701 .map(|(idx, maybe_object)| {
702 maybe_object.ok_or_else(|| {
703 StorageError::custom(format!(
704 "missing input object key {:?} from tx {} effects {}",
705 input_object_keys[idx],
706 effects.transaction_digest(),
707 effects.digest()
708 ))
709 })
710 })
711 .collect::<Result<Vec<_>, _>>()?;
712 Ok(input_objects)
713}
714
715pub fn get_transaction_output_objects(
716 object_store: &dyn ObjectStore,
717 effects: &TransactionEffects,
718) -> Result<Vec<Object>, StorageError> {
719 let output_object_keys = effects
720 .all_changed_objects()
721 .into_iter()
722 .map(|(object_ref, _owner, _kind)| ObjectKey::from(object_ref))
723 .collect::<Vec<_>>();
724
725 let output_objects = object_store
726 .multi_get_objects_by_key(&output_object_keys)
727 .into_iter()
728 .enumerate()
729 .map(|(idx, maybe_object)| {
730 maybe_object.ok_or_else(|| {
731 StorageError::custom(format!(
732 "missing output object key {:?} from tx {} effects {}",
733 output_object_keys[idx],
734 effects.transaction_digest(),
735 effects.digest()
736 ))
737 })
738 })
739 .collect::<Result<Vec<_>, _>>()?;
740 Ok(output_objects)
741}
742
743pub fn get_transaction_object_set(
745 transaction: &TransactionData,
746 effects: &TransactionEffects,
747 unchanged_loaded_runtime_objects: &[ObjectKey],
748) -> BTreeSet<ObjectKey> {
749 let input_objects = transaction
754 .input_objects()
755 .expect("txn was executed and must have valid input objects")
756 .into_iter()
757 .filter_map(|input| {
758 input
759 .version()
760 .map(|version| ObjectKey(input.object_id(), version))
761 });
762
763 let modified_set = effects
765 .object_changes()
766 .into_iter()
767 .flat_map(|change| {
768 [
769 change
770 .input_version
771 .map(|version| ObjectKey(change.id, version)),
772 change
773 .output_version
774 .map(|version| ObjectKey(change.id, version)),
775 ]
776 })
777 .flatten();
778
779 let unchanged_consensus =
781 effects
782 .unchanged_consensus_objects()
783 .into_iter()
784 .flat_map(|unchanged| {
785 if let crate::effects::UnchangedConsensusKind::ReadOnlyRoot((version, _)) =
786 unchanged.1
787 {
788 Some(ObjectKey(unchanged.0, version))
789 } else {
790 None
791 }
792 });
793
794 input_objects
795 .chain(modified_set)
796 .chain(unchanged_consensus)
797 .chain(unchanged_loaded_runtime_objects.iter().copied())
798 .collect()
799}
800
801pub struct TrackingBackingStore<'a> {
806 inner: &'a dyn crate::storage::BackingStore,
807 read_objects: std::cell::RefCell<ObjectSet>,
808}
809
810impl<'a> TrackingBackingStore<'a> {
811 pub fn new(inner: &'a dyn crate::storage::BackingStore) -> Self {
812 Self {
813 inner,
814 read_objects: Default::default(),
815 }
816 }
817
818 pub fn into_read_objects(self) -> ObjectSet {
819 self.read_objects.into_inner()
820 }
821
822 fn track_object(&self, object: &Object) {
823 self.read_objects.borrow_mut().insert(object.clone());
824 }
825}
826
827impl BackingPackageStore for TrackingBackingStore<'_> {
828 fn get_package_object(
829 &self,
830 package_id: &ObjectID,
831 ) -> crate::error::SuiResult<Option<PackageObject>> {
832 self.inner.get_package_object(package_id).inspect(|o| {
833 o.as_ref()
834 .inspect(|package| self.track_object(package.object()));
835 })
836 }
837}
838
839impl ChildObjectResolver for TrackingBackingStore<'_> {
840 fn read_child_object(
841 &self,
842 parent: &ObjectID,
843 child: &ObjectID,
844 child_version_upper_bound: SequenceNumber,
845 ) -> crate::error::SuiResult<Option<Object>> {
846 self.inner
847 .read_child_object(parent, child, child_version_upper_bound)
848 .inspect(|o| {
849 o.as_ref().inspect(|object| self.track_object(object));
850 })
851 }
852
853 fn get_object_received_at_version(
854 &self,
855 owner: &ObjectID,
856 receiving_object_id: &ObjectID,
857 receive_object_at_version: SequenceNumber,
858 epoch_id: crate::committee::EpochId,
859 ) -> crate::error::SuiResult<Option<Object>> {
860 self.inner
861 .get_object_received_at_version(
862 owner,
863 receiving_object_id,
864 receive_object_at_version,
865 epoch_id,
866 )
867 .inspect(|o| {
868 o.as_ref().inspect(|object| self.track_object(object));
869 })
870 }
871}
872
873impl crate::storage::ObjectStore for TrackingBackingStore<'_> {
874 fn get_object(&self, object_id: &ObjectID) -> Option<Object> {
875 self.inner
876 .get_object(object_id)
877 .inspect(|o| self.track_object(o))
878 }
879
880 fn get_object_by_key(
881 &self,
882 object_id: &ObjectID,
883 version: crate::base_types::VersionNumber,
884 ) -> Option<Object> {
885 self.inner
886 .get_object_by_key(object_id, version)
887 .inspect(|o| self.track_object(o))
888 }
889}
890
891impl ParentSync for TrackingBackingStore<'_> {
892 fn get_latest_parent_entry_ref_deprecated(
893 &self,
894 object_id: ObjectID,
895 ) -> Option<crate::base_types::ObjectRef> {
896 self.inner.get_latest_parent_entry_ref_deprecated(object_id)
897 }
898}