1pub mod error;
6mod object_store_trait;
7mod read_store;
8mod shared_in_memory_store;
9mod write_store;
10
11use std::{
12 cell::RefCell,
13 collections::BTreeMap,
14 fmt::{Display, Formatter},
15 rc::Rc,
16 sync::Arc,
17};
18
19use itertools::Itertools;
20use move_binary_format::CompiledModule;
21use move_core_types::language_storage::ModuleId;
22pub use object_store_trait::ObjectStore;
23pub use read_store::{
24 AccountOwnedObjectInfo, CoinInfo, DynamicFieldIteratorItem, DynamicFieldKey, EpochInfo,
25 OwnedObjectCursor, OwnedObjectIteratorItem, PackageVersionInfo, PackageVersionIteratorItem,
26 PackageVersionKey, ReadStore, TransactionInfo,
27};
28use serde::{Deserialize, Serialize};
29use serde_with::serde_as;
30pub use shared_in_memory_store::{SharedInMemoryStore, SingleCheckpointSharedInMemoryStore};
31pub use write_store::WriteStore;
32
33use crate::{
34 auth_context::AuthContext,
35 base_types::{
36 Identifier, ObjectID, ObjectRef, SequenceNumber, TransactionDigest, VersionNumber,
37 },
38 committee::EpochId,
39 effects::{TransactionEffects, TransactionEffectsAPI},
40 error::{ExecutionError, IotaError, IotaResult},
41 execution::{DynamicallyLoadedObjectMetadata, ExecutionResults},
42 move_package::MovePackage,
43 object::Object,
44 storage::error::Error as StorageError,
45 transaction::{SenderSignedData, TransactionDataAPI},
46};
47
48#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
50pub enum InputKey {
51 VersionedObject {
52 id: ObjectID,
53 version: SequenceNumber,
54 },
55 Package {
56 id: ObjectID,
57 },
58}
59
60impl InputKey {
61 pub fn id(&self) -> ObjectID {
62 match self {
63 InputKey::VersionedObject { id, .. } => *id,
64 InputKey::Package { id } => *id,
65 }
66 }
67
68 pub fn version(&self) -> Option<SequenceNumber> {
69 match self {
70 InputKey::VersionedObject { version, .. } => Some(*version),
71 InputKey::Package { .. } => None,
72 }
73 }
74
75 pub fn is_cancelled(&self) -> bool {
76 match self {
77 InputKey::VersionedObject { version, .. } => version.is_cancelled(),
78 InputKey::Package { .. } => false,
79 }
80 }
81}
82
83impl From<&Object> for InputKey {
84 fn from(obj: &Object) -> Self {
85 if obj.is_package() {
86 InputKey::Package { id: obj.id() }
87 } else {
88 InputKey::VersionedObject {
89 id: obj.id(),
90 version: obj.version(),
91 }
92 }
93 }
94}
95
96#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
97pub enum WriteKind {
98 Mutate,
100 Create,
102 Unwrap,
105}
106
107#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
108pub enum DeleteKind {
109 Normal,
111 UnwrapThenDelete,
114 Wrap,
117}
118
119#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
120pub enum MarkerValue {
121 Received,
125 OwnedDeleted,
128 SharedDeleted(TransactionDigest),
131}
132
133#[derive(Debug)]
139pub enum DeleteKindWithOldVersion {
140 Normal(SequenceNumber),
141 UnwrapThenDelete,
142 Wrap(SequenceNumber),
143}
144
145impl DeleteKindWithOldVersion {
146 pub fn old_version(&self) -> Option<SequenceNumber> {
147 match self {
148 DeleteKindWithOldVersion::Normal(version) | DeleteKindWithOldVersion::Wrap(version) => {
149 Some(*version)
150 }
151 DeleteKindWithOldVersion::UnwrapThenDelete => None,
152 }
153 }
154
155 pub fn to_delete_kind(&self) -> DeleteKind {
156 match self {
157 DeleteKindWithOldVersion::Normal(_) => DeleteKind::Normal,
158 DeleteKindWithOldVersion::UnwrapThenDelete => DeleteKind::UnwrapThenDelete,
159 DeleteKindWithOldVersion::Wrap(_) => DeleteKind::Wrap,
160 }
161 }
162}
163
164#[derive(Debug)]
165pub enum ObjectChange {
166 Write(Object, WriteKind),
167 Delete(DeleteKindWithOldVersion),
169}
170
171pub trait StorageView: Storage + ChildObjectResolver {}
172impl<T: Storage + ChildObjectResolver> StorageView for T {}
173
174pub trait ChildObjectResolver {
177 fn read_child_object(
179 &self,
180 parent: &ObjectID,
181 child: &ObjectID,
182 child_version_upper_bound: SequenceNumber,
183 ) -> IotaResult<Option<Object>>;
184
185 fn get_object_received_at_version(
192 &self,
193 owner: &ObjectID,
194 receiving_object_id: &ObjectID,
195 receive_object_at_version: SequenceNumber,
196 epoch_id: EpochId,
197 ) -> IotaResult<Option<Object>>;
198}
199
200pub struct DenyListResult {
201 pub result: Result<(), ExecutionError>,
205 pub num_non_gas_coin_owners: u64,
207}
208
209pub trait Storage {
212 fn reset(&mut self);
213
214 fn read_object(&self, id: &ObjectID) -> Option<&Object>;
215
216 fn record_execution_results(&mut self, results: ExecutionResults);
217
218 fn save_loaded_runtime_objects(
219 &mut self,
220 loaded_runtime_objects: BTreeMap<ObjectID, DynamicallyLoadedObjectMetadata>,
221 );
222
223 fn save_wrapped_object_containers(
224 &mut self,
225 wrapped_object_containers: BTreeMap<ObjectID, ObjectID>,
226 );
227
228 fn check_coin_deny_list(&self, written_objects: &BTreeMap<ObjectID, Object>) -> DenyListResult;
231
232 fn read_auth_context(&self) -> Option<Rc<RefCell<AuthContext>>>;
233}
234
235pub type PackageFetchResults<Package> = Result<Vec<Package>, Vec<ObjectID>>;
236
237#[derive(Clone, Debug)]
238pub struct PackageObject {
239 package_object: Object,
240}
241
242impl PackageObject {
243 pub fn new(package_object: Object) -> Self {
244 assert!(package_object.is_package());
245 Self { package_object }
246 }
247
248 pub fn object(&self) -> &Object {
249 &self.package_object
250 }
251
252 pub fn move_package(&self) -> &MovePackage {
253 self.package_object.data.as_package_opt().unwrap()
254 }
255}
256
257impl From<PackageObject> for Object {
258 fn from(package_object_arc: PackageObject) -> Self {
259 package_object_arc.package_object
260 }
261}
262
263pub trait BackingPackageStore {
264 fn get_package_object(&self, package_id: &ObjectID) -> IotaResult<Option<PackageObject>>;
265}
266
267impl<S: ?Sized + BackingPackageStore> BackingPackageStore for Box<S> {
268 fn get_package_object(&self, package_id: &ObjectID) -> IotaResult<Option<PackageObject>> {
269 BackingPackageStore::get_package_object(self.as_ref(), package_id)
270 }
271}
272
273impl<S: ?Sized + BackingPackageStore> BackingPackageStore for Arc<S> {
274 fn get_package_object(&self, package_id: &ObjectID) -> IotaResult<Option<PackageObject>> {
275 BackingPackageStore::get_package_object(self.as_ref(), package_id)
276 }
277}
278
279impl<S: ?Sized + BackingPackageStore> BackingPackageStore for &S {
280 fn get_package_object(&self, package_id: &ObjectID) -> IotaResult<Option<PackageObject>> {
281 BackingPackageStore::get_package_object(*self, package_id)
282 }
283}
284
285impl<S: ?Sized + BackingPackageStore> BackingPackageStore for &mut S {
286 fn get_package_object(&self, package_id: &ObjectID) -> IotaResult<Option<PackageObject>> {
287 BackingPackageStore::get_package_object(*self, package_id)
288 }
289}
290
291pub fn load_package_object_from_object_store(
292 store: &impl ObjectStore,
293 package_id: &ObjectID,
294) -> IotaResult<Option<PackageObject>> {
295 let package = store.try_get_object(package_id)?;
296 if let Some(obj) = &package {
297 fp_ensure!(
298 obj.is_package(),
299 IotaError::BadObjectType {
300 error: format!("Package expected, Move object found: {package_id}"),
301 }
302 );
303 }
304 Ok(package.map(PackageObject::new))
305}
306
307pub fn get_package_objects<'a>(
312 store: &impl BackingPackageStore,
313 package_ids: impl IntoIterator<Item = &'a ObjectID>,
314) -> IotaResult<PackageFetchResults<PackageObject>> {
315 let packages: Vec<Result<_, _>> = package_ids
316 .into_iter()
317 .map(|id| match store.get_package_object(id) {
318 Ok(None) => Ok(Err(*id)),
319 Ok(Some(o)) => Ok(Ok(o)),
320 Err(x) => Err(x),
321 })
322 .collect::<IotaResult<_>>()?;
323
324 let (fetched, failed_to_fetch): (Vec<_>, Vec<_>) = packages.into_iter().partition_result();
325 if !failed_to_fetch.is_empty() {
326 Ok(Err(failed_to_fetch))
327 } else {
328 Ok(Ok(fetched))
329 }
330}
331
332pub fn get_module(
333 store: impl BackingPackageStore,
334 module_id: &ModuleId,
335) -> Result<Option<Vec<u8>>, IotaError> {
336 Ok(store
337 .get_package_object(&ObjectID::new(module_id.address().into_bytes()))?
338 .and_then(|package| {
339 package
340 .move_package()
341 .serialized_module_map()
342 .get(&Identifier::new_unchecked(module_id.name().as_str()))
343 .cloned()
344 }))
345}
346
347pub fn get_module_by_id<S: BackingPackageStore>(
348 store: &S,
349 id: &ModuleId,
350) -> anyhow::Result<Option<CompiledModule>, IotaError> {
351 Ok(get_module(store, id)?
352 .map(|bytes| CompiledModule::deserialize_with_defaults(&bytes).unwrap()))
353}
354
355pub struct PostExecutionPackageResolver {
361 backing_store: Arc<dyn BackingPackageStore>,
362 new_packages: BTreeMap<ObjectID, PackageObject>,
363}
364
365impl PostExecutionPackageResolver {
366 pub fn new(
367 backing_store: Arc<dyn BackingPackageStore>,
368 output_objects: &Option<Vec<Object>>,
369 ) -> Self {
370 let new_packages = output_objects
371 .iter()
372 .flatten()
373 .filter_map(|o| {
374 if o.is_package() {
375 Some((o.id(), PackageObject::new(o.clone())))
376 } else {
377 None
378 }
379 })
380 .collect();
381 Self {
382 backing_store,
383 new_packages,
384 }
385 }
386}
387
388impl BackingPackageStore for PostExecutionPackageResolver {
389 fn get_package_object(&self, package_id: &ObjectID) -> IotaResult<Option<PackageObject>> {
390 if let Some(package) = self.new_packages.get(package_id) {
391 Ok(Some(package.clone()))
392 } else {
393 self.backing_store.get_package_object(package_id)
394 }
395 }
396}
397
398impl<S: ChildObjectResolver> ChildObjectResolver for std::sync::Arc<S> {
399 fn read_child_object(
400 &self,
401 parent: &ObjectID,
402 child: &ObjectID,
403 child_version_upper_bound: SequenceNumber,
404 ) -> IotaResult<Option<Object>> {
405 ChildObjectResolver::read_child_object(
406 self.as_ref(),
407 parent,
408 child,
409 child_version_upper_bound,
410 )
411 }
412 fn get_object_received_at_version(
413 &self,
414 owner: &ObjectID,
415 receiving_object_id: &ObjectID,
416 receive_object_at_version: SequenceNumber,
417 epoch_id: EpochId,
418 ) -> IotaResult<Option<Object>> {
419 ChildObjectResolver::get_object_received_at_version(
420 self.as_ref(),
421 owner,
422 receiving_object_id,
423 receive_object_at_version,
424 epoch_id,
425 )
426 }
427}
428
429impl<S: ChildObjectResolver> ChildObjectResolver for &S {
430 fn read_child_object(
431 &self,
432 parent: &ObjectID,
433 child: &ObjectID,
434 child_version_upper_bound: SequenceNumber,
435 ) -> IotaResult<Option<Object>> {
436 ChildObjectResolver::read_child_object(*self, parent, child, child_version_upper_bound)
437 }
438 fn get_object_received_at_version(
439 &self,
440 owner: &ObjectID,
441 receiving_object_id: &ObjectID,
442 receive_object_at_version: SequenceNumber,
443 epoch_id: EpochId,
444 ) -> IotaResult<Option<Object>> {
445 ChildObjectResolver::get_object_received_at_version(
446 *self,
447 owner,
448 receiving_object_id,
449 receive_object_at_version,
450 epoch_id,
451 )
452 }
453}
454
455impl<S: ChildObjectResolver> ChildObjectResolver for &mut S {
456 fn read_child_object(
457 &self,
458 parent: &ObjectID,
459 child: &ObjectID,
460 child_version_upper_bound: SequenceNumber,
461 ) -> IotaResult<Option<Object>> {
462 ChildObjectResolver::read_child_object(*self, parent, child, child_version_upper_bound)
463 }
464 fn get_object_received_at_version(
465 &self,
466 owner: &ObjectID,
467 receiving_object_id: &ObjectID,
468 receive_object_at_version: SequenceNumber,
469 epoch_id: EpochId,
470 ) -> IotaResult<Option<Object>> {
471 ChildObjectResolver::get_object_received_at_version(
472 *self,
473 owner,
474 receiving_object_id,
475 receive_object_at_version,
476 epoch_id,
477 )
478 }
479}
480
481#[serde_as]
483#[derive(Eq, PartialEq, Clone, Copy, PartialOrd, Ord, Hash, Serialize, Deserialize, Debug)]
484pub struct ObjectKey(pub ObjectID, pub VersionNumber);
485
486impl ObjectKey {
487 pub const ZERO: ObjectKey = ObjectKey(ObjectID::ZERO, VersionNumber::MIN_VALID_INCL);
488
489 pub fn max_for_id(id: &ObjectID) -> Self {
490 Self(*id, VersionNumber::MAX_VALID_EXCL)
491 }
492
493 pub fn min_for_id(id: &ObjectID) -> Self {
494 Self(*id, VersionNumber::MIN_VALID_INCL)
495 }
496}
497
498impl From<ObjectRef> for ObjectKey {
499 fn from(object_ref: ObjectRef) -> Self {
500 ObjectKey::from(&object_ref)
501 }
502}
503
504impl From<&ObjectRef> for ObjectKey {
505 fn from(object_ref: &ObjectRef) -> Self {
506 Self(object_ref.object_id, object_ref.version)
507 }
508}
509
510#[derive(Clone)]
511pub enum ObjectOrTombstone {
512 Object(Object),
513 Tombstone(ObjectRef),
514}
515
516impl ObjectOrTombstone {
517 pub fn as_objref(&self) -> ObjectRef {
518 match self {
519 ObjectOrTombstone::Object(obj) => obj.compute_object_reference(),
520 ObjectOrTombstone::Tombstone(obref) => *obref,
521 }
522 }
523}
524
525impl From<Object> for ObjectOrTombstone {
526 fn from(object: Object) -> Self {
527 ObjectOrTombstone::Object(object)
528 }
529}
530
531pub fn transaction_non_shared_input_object_keys(
535 tx: &SenderSignedData,
536) -> IotaResult<Vec<ObjectKey>> {
537 use crate::transaction::InputObjectKind as I;
538 Ok(tx
539 .input_objects()?
540 .into_iter()
541 .filter_map(|object| match object {
542 I::MovePackage(_) | I::SharedMoveObject { .. } => None,
543 I::ImmOrOwnedMoveObject(obj) => Some(obj.into()),
544 })
545 .collect())
546}
547
548pub fn transaction_receiving_object_keys(tx: &SenderSignedData) -> Vec<ObjectKey> {
549 tx.intent_message()
550 .value
551 .receiving_objects()
552 .into_iter()
553 .map(|oref| oref.into())
554 .collect()
555}
556
557impl Display for DeleteKind {
558 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
559 match self {
560 DeleteKind::Wrap => write!(f, "Wrap"),
561 DeleteKind::Normal => write!(f, "Normal"),
562 DeleteKind::UnwrapThenDelete => write!(f, "UnwrapThenDelete"),
563 }
564 }
565}
566
567pub trait BackingStore: BackingPackageStore + ChildObjectResolver + ObjectStore {
568 fn as_object_store(&self) -> &dyn ObjectStore;
569}
570
571impl<T> BackingStore for T
572where
573 T: BackingPackageStore,
574 T: ChildObjectResolver,
575 T: ObjectStore,
576{
577 fn as_object_store(&self) -> &dyn ObjectStore {
578 self
579 }
580}
581
582pub fn get_transaction_input_objects(
583 object_store: &dyn ObjectStore,
584 effects: &TransactionEffects,
585) -> Result<Vec<Object>, StorageError> {
586 let input_object_keys = effects
587 .modified_at_versions()
588 .into_iter()
589 .map(|(object_id, version)| ObjectKey(object_id, version))
590 .collect::<Vec<_>>();
591
592 let input_objects = object_store
593 .multi_get_objects_by_key(&input_object_keys)
594 .into_iter()
595 .enumerate()
596 .map(|(idx, maybe_object)| {
597 maybe_object.ok_or_else(|| {
598 StorageError::custom(format!(
599 "missing input object key {:?} from tx {}",
600 input_object_keys[idx],
601 effects.transaction_digest()
602 ))
603 })
604 })
605 .collect::<Result<Vec<_>, _>>()?;
606 Ok(input_objects)
607}
608
609pub fn get_transaction_output_objects(
610 object_store: &dyn ObjectStore,
611 effects: &TransactionEffects,
612) -> Result<Vec<Object>, StorageError> {
613 let output_object_keys = effects
614 .all_changed_objects()
615 .into_iter()
616 .map(|(object_ref, _owner, _kind)| ObjectKey::from(object_ref))
617 .collect::<Vec<_>>();
618
619 let output_objects = object_store
620 .multi_get_objects_by_key(&output_object_keys)
621 .into_iter()
622 .enumerate()
623 .map(|(idx, maybe_object)| {
624 maybe_object.ok_or_else(|| {
625 StorageError::custom(format!(
626 "missing output object key {:?} from tx {}",
627 output_object_keys[idx],
628 effects.transaction_digest()
629 ))
630 })
631 })
632 .collect::<Result<Vec<_>, _>>()?;
633 Ok(output_objects)
634}