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