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