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