1pub mod error;
6mod object_store_trait;
7mod read_store;
8mod shared_in_memory_store;
9mod write_store;
10
11use std::{
12 collections::BTreeMap,
13 fmt::{Display, Formatter},
14 sync::Arc,
15};
16
17use itertools::Itertools;
18use move_binary_format::CompiledModule;
19use move_core_types::language_storage::ModuleId;
20pub use object_store_trait::ObjectStore;
21pub use read_store::{
22 AccountOwnedObjectInfo, CoinInfo, DynamicFieldIndexInfo, DynamicFieldKey, EpochInfo, ReadStore,
23 RestIndexes, RestStateReader, TransactionInfo,
24};
25use serde::{Deserialize, Serialize};
26use serde_with::serde_as;
27pub use shared_in_memory_store::{SharedInMemoryStore, SingleCheckpointSharedInMemoryStore};
28pub use write_store::WriteStore;
29
30use crate::{
31 auth_context::AuthContext,
32 base_types::{ObjectID, ObjectRef, SequenceNumber, TransactionDigest, VersionNumber},
33 committee::EpochId,
34 effects::{TransactionEffects, TransactionEffectsAPI},
35 error::{ExecutionError, IotaError, IotaResult},
36 execution::{DynamicallyLoadedObjectMetadata, ExecutionResults},
37 move_package::MovePackage,
38 object::Object,
39 storage::error::Error as StorageError,
40 transaction::{SenderSignedData, TransactionDataAPI},
41};
42
43#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
45pub enum InputKey {
46 VersionedObject {
47 id: ObjectID,
48 version: SequenceNumber,
49 },
50 Package {
51 id: ObjectID,
52 },
53}
54
55impl InputKey {
56 pub fn id(&self) -> ObjectID {
57 match self {
58 InputKey::VersionedObject { id, .. } => *id,
59 InputKey::Package { id } => *id,
60 }
61 }
62
63 pub fn version(&self) -> Option<SequenceNumber> {
64 match self {
65 InputKey::VersionedObject { version, .. } => Some(*version),
66 InputKey::Package { .. } => None,
67 }
68 }
69
70 pub fn is_cancelled(&self) -> bool {
71 match self {
72 InputKey::VersionedObject { version, .. } => version.is_cancelled(),
73 InputKey::Package { .. } => false,
74 }
75 }
76}
77
78impl From<&Object> for InputKey {
79 fn from(obj: &Object) -> Self {
80 if obj.is_package() {
81 InputKey::Package { id: obj.id() }
82 } else {
83 InputKey::VersionedObject {
84 id: obj.id(),
85 version: obj.version(),
86 }
87 }
88 }
89}
90
91#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
92pub enum WriteKind {
93 Mutate,
95 Create,
97 Unwrap,
100}
101
102#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
103pub enum DeleteKind {
104 Normal,
106 UnwrapThenDelete,
109 Wrap,
112}
113
114#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
115pub enum MarkerValue {
116 Received,
120 OwnedDeleted,
123 SharedDeleted(TransactionDigest),
126}
127
128#[derive(Debug)]
134pub enum DeleteKindWithOldVersion {
135 Normal(SequenceNumber),
136 UnwrapThenDelete,
137 Wrap(SequenceNumber),
138}
139
140impl DeleteKindWithOldVersion {
141 pub fn old_version(&self) -> Option<SequenceNumber> {
142 match self {
143 DeleteKindWithOldVersion::Normal(version) | DeleteKindWithOldVersion::Wrap(version) => {
144 Some(*version)
145 }
146 DeleteKindWithOldVersion::UnwrapThenDelete => None,
147 }
148 }
149
150 pub fn to_delete_kind(&self) -> DeleteKind {
151 match self {
152 DeleteKindWithOldVersion::Normal(_) => DeleteKind::Normal,
153 DeleteKindWithOldVersion::UnwrapThenDelete => DeleteKind::UnwrapThenDelete,
154 DeleteKindWithOldVersion::Wrap(_) => DeleteKind::Wrap,
155 }
156 }
157}
158
159#[derive(Debug)]
160pub enum ObjectChange {
161 Write(Object, WriteKind),
162 Delete(DeleteKindWithOldVersion),
164}
165
166pub trait StorageView: Storage + ChildObjectResolver {}
167impl<T: Storage + ChildObjectResolver> StorageView for T {}
168
169pub trait ChildObjectResolver {
172 fn read_child_object(
174 &self,
175 parent: &ObjectID,
176 child: &ObjectID,
177 child_version_upper_bound: SequenceNumber,
178 ) -> IotaResult<Option<Object>>;
179
180 fn get_object_received_at_version(
187 &self,
188 owner: &ObjectID,
189 receiving_object_id: &ObjectID,
190 receive_object_at_version: SequenceNumber,
191 epoch_id: EpochId,
192 ) -> IotaResult<Option<Object>>;
193}
194
195pub struct DenyListResult {
196 pub result: Result<(), ExecutionError>,
200 pub num_non_gas_coin_owners: u64,
202}
203
204pub trait Storage {
207 fn reset(&mut self);
208
209 fn read_object(&self, id: &ObjectID) -> Option<&Object>;
210
211 fn record_execution_results(&mut self, results: ExecutionResults);
212
213 fn save_loaded_runtime_objects(
214 &mut self,
215 loaded_runtime_objects: BTreeMap<ObjectID, DynamicallyLoadedObjectMetadata>,
216 );
217
218 fn save_wrapped_object_containers(
219 &mut self,
220 wrapped_object_containers: BTreeMap<ObjectID, ObjectID>,
221 );
222
223 fn check_coin_deny_list(&self, written_objects: &BTreeMap<ObjectID, Object>) -> DenyListResult;
226
227 fn read_auth_context(&self) -> Option<&AuthContext>;
228}
229
230pub type PackageFetchResults<Package> = Result<Vec<Package>, Vec<ObjectID>>;
231
232#[derive(Clone, Debug)]
233pub struct PackageObject {
234 package_object: Object,
235}
236
237impl PackageObject {
238 pub fn new(package_object: Object) -> Self {
239 assert!(package_object.is_package());
240 Self { package_object }
241 }
242
243 pub fn object(&self) -> &Object {
244 &self.package_object
245 }
246
247 pub fn move_package(&self) -> &MovePackage {
248 self.package_object.data.try_as_package().unwrap()
249 }
250}
251
252impl From<PackageObject> for Object {
253 fn from(package_object_arc: PackageObject) -> Self {
254 package_object_arc.package_object
255 }
256}
257
258pub trait BackingPackageStore {
259 fn get_package_object(&self, package_id: &ObjectID) -> IotaResult<Option<PackageObject>>;
260}
261
262impl<S: ?Sized + BackingPackageStore> BackingPackageStore for Box<S> {
263 fn get_package_object(&self, package_id: &ObjectID) -> IotaResult<Option<PackageObject>> {
264 BackingPackageStore::get_package_object(self.as_ref(), package_id)
265 }
266}
267
268impl<S: ?Sized + BackingPackageStore> BackingPackageStore for Arc<S> {
269 fn get_package_object(&self, package_id: &ObjectID) -> IotaResult<Option<PackageObject>> {
270 BackingPackageStore::get_package_object(self.as_ref(), package_id)
271 }
272}
273
274impl<S: ?Sized + BackingPackageStore> BackingPackageStore for &S {
275 fn get_package_object(&self, package_id: &ObjectID) -> IotaResult<Option<PackageObject>> {
276 BackingPackageStore::get_package_object(*self, package_id)
277 }
278}
279
280impl<S: ?Sized + BackingPackageStore> BackingPackageStore for &mut S {
281 fn get_package_object(&self, package_id: &ObjectID) -> IotaResult<Option<PackageObject>> {
282 BackingPackageStore::get_package_object(*self, package_id)
283 }
284}
285
286pub fn load_package_object_from_object_store(
287 store: &impl ObjectStore,
288 package_id: &ObjectID,
289) -> IotaResult<Option<PackageObject>> {
290 let package = store.try_get_object(package_id)?;
291 if let Some(obj) = &package {
292 fp_ensure!(
293 obj.is_package(),
294 IotaError::BadObjectType {
295 error: format!("Package expected, Move object found: {package_id}"),
296 }
297 );
298 }
299 Ok(package.map(PackageObject::new))
300}
301
302pub fn get_package_objects<'a>(
307 store: &impl BackingPackageStore,
308 package_ids: impl IntoIterator<Item = &'a ObjectID>,
309) -> IotaResult<PackageFetchResults<PackageObject>> {
310 let packages: Vec<Result<_, _>> = package_ids
311 .into_iter()
312 .map(|id| match store.get_package_object(id) {
313 Ok(None) => Ok(Err(*id)),
314 Ok(Some(o)) => Ok(Ok(o)),
315 Err(x) => Err(x),
316 })
317 .collect::<IotaResult<_>>()?;
318
319 let (fetched, failed_to_fetch): (Vec<_>, Vec<_>) = packages.into_iter().partition_result();
320 if !failed_to_fetch.is_empty() {
321 Ok(Err(failed_to_fetch))
322 } else {
323 Ok(Ok(fetched))
324 }
325}
326
327pub fn get_module(
328 store: impl BackingPackageStore,
329 module_id: &ModuleId,
330) -> Result<Option<Vec<u8>>, IotaError> {
331 Ok(store
332 .get_package_object(&ObjectID::from(*module_id.address()))?
333 .and_then(|package| {
334 package
335 .move_package()
336 .serialized_module_map()
337 .get(module_id.name().as_str())
338 .cloned()
339 }))
340}
341
342pub fn get_module_by_id<S: BackingPackageStore>(
343 store: &S,
344 id: &ModuleId,
345) -> anyhow::Result<Option<CompiledModule>, IotaError> {
346 Ok(get_module(store, id)?
347 .map(|bytes| CompiledModule::deserialize_with_defaults(&bytes).unwrap()))
348}
349
350pub struct PostExecutionPackageResolver {
356 backing_store: Arc<dyn BackingPackageStore>,
357 new_packages: BTreeMap<ObjectID, PackageObject>,
358}
359
360impl PostExecutionPackageResolver {
361 pub fn new(
362 backing_store: Arc<dyn BackingPackageStore>,
363 output_objects: &Option<Vec<Object>>,
364 ) -> Self {
365 let new_packages = output_objects
366 .iter()
367 .flatten()
368 .filter_map(|o| {
369 if o.is_package() {
370 Some((o.id(), PackageObject::new(o.clone())))
371 } else {
372 None
373 }
374 })
375 .collect();
376 Self {
377 backing_store,
378 new_packages,
379 }
380 }
381}
382
383impl BackingPackageStore for PostExecutionPackageResolver {
384 fn get_package_object(&self, package_id: &ObjectID) -> IotaResult<Option<PackageObject>> {
385 if let Some(package) = self.new_packages.get(package_id) {
386 Ok(Some(package.clone()))
387 } else {
388 self.backing_store.get_package_object(package_id)
389 }
390 }
391}
392
393impl<S: ChildObjectResolver> ChildObjectResolver for std::sync::Arc<S> {
394 fn read_child_object(
395 &self,
396 parent: &ObjectID,
397 child: &ObjectID,
398 child_version_upper_bound: SequenceNumber,
399 ) -> IotaResult<Option<Object>> {
400 ChildObjectResolver::read_child_object(
401 self.as_ref(),
402 parent,
403 child,
404 child_version_upper_bound,
405 )
406 }
407 fn get_object_received_at_version(
408 &self,
409 owner: &ObjectID,
410 receiving_object_id: &ObjectID,
411 receive_object_at_version: SequenceNumber,
412 epoch_id: EpochId,
413 ) -> IotaResult<Option<Object>> {
414 ChildObjectResolver::get_object_received_at_version(
415 self.as_ref(),
416 owner,
417 receiving_object_id,
418 receive_object_at_version,
419 epoch_id,
420 )
421 }
422}
423
424impl<S: ChildObjectResolver> ChildObjectResolver for &S {
425 fn read_child_object(
426 &self,
427 parent: &ObjectID,
428 child: &ObjectID,
429 child_version_upper_bound: SequenceNumber,
430 ) -> IotaResult<Option<Object>> {
431 ChildObjectResolver::read_child_object(*self, parent, child, child_version_upper_bound)
432 }
433 fn get_object_received_at_version(
434 &self,
435 owner: &ObjectID,
436 receiving_object_id: &ObjectID,
437 receive_object_at_version: SequenceNumber,
438 epoch_id: EpochId,
439 ) -> IotaResult<Option<Object>> {
440 ChildObjectResolver::get_object_received_at_version(
441 *self,
442 owner,
443 receiving_object_id,
444 receive_object_at_version,
445 epoch_id,
446 )
447 }
448}
449
450impl<S: ChildObjectResolver> ChildObjectResolver for &mut S {
451 fn read_child_object(
452 &self,
453 parent: &ObjectID,
454 child: &ObjectID,
455 child_version_upper_bound: SequenceNumber,
456 ) -> IotaResult<Option<Object>> {
457 ChildObjectResolver::read_child_object(*self, parent, child, child_version_upper_bound)
458 }
459 fn get_object_received_at_version(
460 &self,
461 owner: &ObjectID,
462 receiving_object_id: &ObjectID,
463 receive_object_at_version: SequenceNumber,
464 epoch_id: EpochId,
465 ) -> IotaResult<Option<Object>> {
466 ChildObjectResolver::get_object_received_at_version(
467 *self,
468 owner,
469 receiving_object_id,
470 receive_object_at_version,
471 epoch_id,
472 )
473 }
474}
475
476#[serde_as]
478#[derive(Eq, PartialEq, Clone, Copy, PartialOrd, Ord, Hash, Serialize, Deserialize, Debug)]
479pub struct ObjectKey(pub ObjectID, pub VersionNumber);
480
481impl ObjectKey {
482 pub const ZERO: ObjectKey = ObjectKey(ObjectID::ZERO, VersionNumber::MIN_VALID_INCL);
483
484 pub fn max_for_id(id: &ObjectID) -> Self {
485 Self(*id, VersionNumber::MAX_VALID_EXCL)
486 }
487
488 pub fn min_for_id(id: &ObjectID) -> Self {
489 Self(*id, VersionNumber::MIN_VALID_INCL)
490 }
491}
492
493impl From<ObjectRef> for ObjectKey {
494 fn from(object_ref: ObjectRef) -> Self {
495 ObjectKey::from(&object_ref)
496 }
497}
498
499impl From<&ObjectRef> for ObjectKey {
500 fn from(object_ref: &ObjectRef) -> Self {
501 Self(object_ref.0, object_ref.1)
502 }
503}
504
505#[derive(Clone)]
506pub enum ObjectOrTombstone {
507 Object(Object),
508 Tombstone(ObjectRef),
509}
510
511impl ObjectOrTombstone {
512 pub fn as_objref(&self) -> ObjectRef {
513 match self {
514 ObjectOrTombstone::Object(obj) => obj.compute_object_reference(),
515 ObjectOrTombstone::Tombstone(obref) => *obref,
516 }
517 }
518}
519
520impl From<Object> for ObjectOrTombstone {
521 fn from(object: Object) -> Self {
522 ObjectOrTombstone::Object(object)
523 }
524}
525
526pub fn transaction_non_shared_input_object_keys(
530 tx: &SenderSignedData,
531) -> IotaResult<Vec<ObjectKey>> {
532 use crate::transaction::InputObjectKind as I;
533 Ok(tx
534 .input_objects()?
535 .into_iter()
536 .filter_map(|object| match object {
537 I::MovePackage(_) | I::SharedMoveObject { .. } => None,
538 I::ImmOrOwnedMoveObject(obj) => Some(obj.into()),
539 })
540 .collect())
541}
542
543pub fn transaction_receiving_object_keys(tx: &SenderSignedData) -> Vec<ObjectKey> {
544 tx.intent_message()
545 .value
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::custom(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::custom(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}