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