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