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