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