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, ReadStore,
23 RestStateReader,
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 base_types::{ObjectID, ObjectRef, SequenceNumber, TransactionDigest, VersionNumber},
32 committee::EpochId,
33 error::{ExecutionError, IotaError, IotaResult},
34 execution::{DynamicallyLoadedObjectMetadata, ExecutionResults},
35 move_package::MovePackage,
36 object::Object,
37 transaction::{SenderSignedData, TransactionDataAPI, TransactionKey},
38};
39
40#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
42pub enum InputKey {
43 VersionedObject {
44 id: ObjectID,
45 version: SequenceNumber,
46 },
47 Package {
48 id: ObjectID,
49 },
50}
51
52impl InputKey {
53 pub fn id(&self) -> ObjectID {
54 match self {
55 InputKey::VersionedObject { id, .. } => *id,
56 InputKey::Package { id } => *id,
57 }
58 }
59
60 pub fn version(&self) -> Option<SequenceNumber> {
61 match self {
62 InputKey::VersionedObject { version, .. } => Some(*version),
63 InputKey::Package { .. } => None,
64 }
65 }
66
67 pub fn is_cancelled(&self) -> bool {
68 match self {
69 InputKey::VersionedObject { version, .. } => version.is_cancelled(),
70 InputKey::Package { .. } => false,
71 }
72 }
73}
74
75impl From<&Object> for InputKey {
76 fn from(obj: &Object) -> Self {
77 if obj.is_package() {
78 InputKey::Package { id: obj.id() }
79 } else {
80 InputKey::VersionedObject {
81 id: obj.id(),
82 version: obj.version(),
83 }
84 }
85 }
86}
87
88#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
89pub enum WriteKind {
90 Mutate,
92 Create,
94 Unwrap,
97}
98
99#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
100pub enum DeleteKind {
101 Normal,
103 UnwrapThenDelete,
106 Wrap,
109}
110
111#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
112pub enum MarkerValue {
113 Received,
117 OwnedDeleted,
120 SharedDeleted(TransactionDigest),
123}
124
125#[derive(Debug)]
131pub enum DeleteKindWithOldVersion {
132 Normal(SequenceNumber),
133 UnwrapThenDelete,
134 Wrap(SequenceNumber),
135}
136
137impl DeleteKindWithOldVersion {
138 pub fn old_version(&self) -> Option<SequenceNumber> {
139 match self {
140 DeleteKindWithOldVersion::Normal(version) | DeleteKindWithOldVersion::Wrap(version) => {
141 Some(*version)
142 }
143 DeleteKindWithOldVersion::UnwrapThenDelete => None,
144 }
145 }
146
147 pub fn to_delete_kind(&self) -> DeleteKind {
148 match self {
149 DeleteKindWithOldVersion::Normal(_) => DeleteKind::Normal,
150 DeleteKindWithOldVersion::UnwrapThenDelete => DeleteKind::UnwrapThenDelete,
151 DeleteKindWithOldVersion::Wrap(_) => DeleteKind::Wrap,
152 }
153 }
154}
155
156#[derive(Debug)]
157pub enum ObjectChange {
158 Write(Object, WriteKind),
159 Delete(DeleteKindWithOldVersion),
161}
162
163pub trait StorageView: Storage + ChildObjectResolver {}
164impl<T: Storage + ChildObjectResolver> StorageView for T {}
165
166pub trait ChildObjectResolver {
169 fn read_child_object(
171 &self,
172 parent: &ObjectID,
173 child: &ObjectID,
174 child_version_upper_bound: SequenceNumber,
175 ) -> IotaResult<Option<Object>>;
176
177 fn get_object_received_at_version(
184 &self,
185 owner: &ObjectID,
186 receiving_object_id: &ObjectID,
187 receive_object_at_version: SequenceNumber,
188 epoch_id: EpochId,
189 ) -> IotaResult<Option<Object>>;
190}
191
192pub struct DenyListResult {
193 pub result: Result<(), ExecutionError>,
197 pub num_non_gas_coin_owners: u64,
199}
200
201pub trait Storage {
204 fn reset(&mut self);
205
206 fn read_object(&self, id: &ObjectID) -> Option<&Object>;
207
208 fn record_execution_results(&mut self, results: ExecutionResults);
209
210 fn save_loaded_runtime_objects(
211 &mut self,
212 loaded_runtime_objects: BTreeMap<ObjectID, DynamicallyLoadedObjectMetadata>,
213 );
214
215 fn save_wrapped_object_containers(
216 &mut self,
217 wrapped_object_containers: BTreeMap<ObjectID, ObjectID>,
218 );
219
220 fn check_coin_deny_list(&self, written_objects: &BTreeMap<ObjectID, Object>) -> DenyListResult;
223}
224
225pub type PackageFetchResults<Package> = Result<Vec<Package>, Vec<ObjectID>>;
226
227#[derive(Clone, Debug)]
228pub struct PackageObject {
229 package_object: Object,
230}
231
232impl PackageObject {
233 pub fn new(package_object: Object) -> Self {
234 assert!(package_object.is_package());
235 Self { package_object }
236 }
237
238 pub fn object(&self) -> &Object {
239 &self.package_object
240 }
241
242 pub fn move_package(&self) -> &MovePackage {
243 self.package_object.data.try_as_package().unwrap()
244 }
245}
246
247impl From<PackageObject> for Object {
248 fn from(package_object_arc: PackageObject) -> Self {
249 package_object_arc.package_object
250 }
251}
252
253pub trait BackingPackageStore {
254 fn get_package_object(&self, package_id: &ObjectID) -> IotaResult<Option<PackageObject>>;
255}
256
257impl<S: ?Sized + BackingPackageStore> BackingPackageStore for Box<S> {
258 fn get_package_object(&self, package_id: &ObjectID) -> IotaResult<Option<PackageObject>> {
259 BackingPackageStore::get_package_object(self.as_ref(), package_id)
260 }
261}
262
263impl<S: ?Sized + BackingPackageStore> BackingPackageStore for Arc<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 &S {
270 fn get_package_object(&self, package_id: &ObjectID) -> IotaResult<Option<PackageObject>> {
271 BackingPackageStore::get_package_object(*self, package_id)
272 }
273}
274
275impl<S: ?Sized + BackingPackageStore> BackingPackageStore for &mut S {
276 fn get_package_object(&self, package_id: &ObjectID) -> IotaResult<Option<PackageObject>> {
277 BackingPackageStore::get_package_object(*self, package_id)
278 }
279}
280
281pub fn load_package_object_from_object_store(
282 store: &impl ObjectStore,
283 package_id: &ObjectID,
284) -> IotaResult<Option<PackageObject>> {
285 let package = store.get_object(package_id)?;
286 if let Some(obj) = &package {
287 fp_ensure!(
288 obj.is_package(),
289 IotaError::BadObjectType {
290 error: format!("Package expected, Move object found: {package_id}"),
291 }
292 );
293 }
294 Ok(package.map(PackageObject::new))
295}
296
297pub fn get_package_objects<'a>(
302 store: &impl BackingPackageStore,
303 package_ids: impl IntoIterator<Item = &'a ObjectID>,
304) -> IotaResult<PackageFetchResults<PackageObject>> {
305 let packages: Vec<Result<_, _>> = package_ids
306 .into_iter()
307 .map(|id| match store.get_package_object(id) {
308 Ok(None) => Ok(Err(*id)),
309 Ok(Some(o)) => Ok(Ok(o)),
310 Err(x) => Err(x),
311 })
312 .collect::<IotaResult<_>>()?;
313
314 let (fetched, failed_to_fetch): (Vec<_>, Vec<_>) = packages.into_iter().partition_result();
315 if !failed_to_fetch.is_empty() {
316 Ok(Err(failed_to_fetch))
317 } else {
318 Ok(Ok(fetched))
319 }
320}
321
322pub fn get_module(
323 store: impl BackingPackageStore,
324 module_id: &ModuleId,
325) -> Result<Option<Vec<u8>>, IotaError> {
326 Ok(store
327 .get_package_object(&ObjectID::from(*module_id.address()))?
328 .and_then(|package| {
329 package
330 .move_package()
331 .serialized_module_map()
332 .get(module_id.name().as_str())
333 .cloned()
334 }))
335}
336
337pub fn get_module_by_id<S: BackingPackageStore>(
338 store: &S,
339 id: &ModuleId,
340) -> anyhow::Result<Option<CompiledModule>, IotaError> {
341 Ok(get_module(store, id)?
342 .map(|bytes| CompiledModule::deserialize_with_defaults(&bytes).unwrap()))
343}
344
345pub struct PostExecutionPackageResolver {
351 backing_store: Arc<dyn BackingPackageStore>,
352 new_packages: BTreeMap<ObjectID, PackageObject>,
353}
354
355impl PostExecutionPackageResolver {
356 pub fn new(
357 backing_store: Arc<dyn BackingPackageStore>,
358 output_objects: &Option<Vec<Object>>,
359 ) -> Self {
360 let new_packages = output_objects
361 .iter()
362 .flatten()
363 .filter_map(|o| {
364 if o.is_package() {
365 Some((o.id(), PackageObject::new(o.clone())))
366 } else {
367 None
368 }
369 })
370 .collect();
371 Self {
372 backing_store,
373 new_packages,
374 }
375 }
376}
377
378impl BackingPackageStore for PostExecutionPackageResolver {
379 fn get_package_object(&self, package_id: &ObjectID) -> IotaResult<Option<PackageObject>> {
380 if let Some(package) = self.new_packages.get(package_id) {
381 Ok(Some(package.clone()))
382 } else {
383 self.backing_store.get_package_object(package_id)
384 }
385 }
386}
387
388impl<S: ChildObjectResolver> ChildObjectResolver for std::sync::Arc<S> {
389 fn read_child_object(
390 &self,
391 parent: &ObjectID,
392 child: &ObjectID,
393 child_version_upper_bound: SequenceNumber,
394 ) -> IotaResult<Option<Object>> {
395 ChildObjectResolver::read_child_object(
396 self.as_ref(),
397 parent,
398 child,
399 child_version_upper_bound,
400 )
401 }
402 fn get_object_received_at_version(
403 &self,
404 owner: &ObjectID,
405 receiving_object_id: &ObjectID,
406 receive_object_at_version: SequenceNumber,
407 epoch_id: EpochId,
408 ) -> IotaResult<Option<Object>> {
409 ChildObjectResolver::get_object_received_at_version(
410 self.as_ref(),
411 owner,
412 receiving_object_id,
413 receive_object_at_version,
414 epoch_id,
415 )
416 }
417}
418
419impl<S: ChildObjectResolver> ChildObjectResolver for &S {
420 fn read_child_object(
421 &self,
422 parent: &ObjectID,
423 child: &ObjectID,
424 child_version_upper_bound: SequenceNumber,
425 ) -> IotaResult<Option<Object>> {
426 ChildObjectResolver::read_child_object(*self, parent, child, child_version_upper_bound)
427 }
428 fn get_object_received_at_version(
429 &self,
430 owner: &ObjectID,
431 receiving_object_id: &ObjectID,
432 receive_object_at_version: SequenceNumber,
433 epoch_id: EpochId,
434 ) -> IotaResult<Option<Object>> {
435 ChildObjectResolver::get_object_received_at_version(
436 *self,
437 owner,
438 receiving_object_id,
439 receive_object_at_version,
440 epoch_id,
441 )
442 }
443}
444
445impl<S: ChildObjectResolver> ChildObjectResolver for &mut S {
446 fn read_child_object(
447 &self,
448 parent: &ObjectID,
449 child: &ObjectID,
450 child_version_upper_bound: SequenceNumber,
451 ) -> IotaResult<Option<Object>> {
452 ChildObjectResolver::read_child_object(*self, parent, child, child_version_upper_bound)
453 }
454 fn get_object_received_at_version(
455 &self,
456 owner: &ObjectID,
457 receiving_object_id: &ObjectID,
458 receive_object_at_version: SequenceNumber,
459 epoch_id: EpochId,
460 ) -> IotaResult<Option<Object>> {
461 ChildObjectResolver::get_object_received_at_version(
462 *self,
463 owner,
464 receiving_object_id,
465 receive_object_at_version,
466 epoch_id,
467 )
468 }
469}
470
471#[serde_as]
473#[derive(Eq, PartialEq, Clone, Copy, PartialOrd, Ord, Hash, Serialize, Deserialize, Debug)]
474pub struct ObjectKey(pub ObjectID, pub VersionNumber);
475
476impl ObjectKey {
477 pub const ZERO: ObjectKey = ObjectKey(ObjectID::ZERO, VersionNumber::MIN);
478
479 pub fn max_for_id(id: &ObjectID) -> Self {
480 Self(*id, VersionNumber::MAX)
481 }
482
483 pub fn min_for_id(id: &ObjectID) -> Self {
484 Self(*id, VersionNumber::MIN)
485 }
486}
487
488impl From<ObjectRef> for ObjectKey {
489 fn from(object_ref: ObjectRef) -> Self {
490 ObjectKey::from(&object_ref)
491 }
492}
493
494impl From<&ObjectRef> for ObjectKey {
495 fn from(object_ref: &ObjectRef) -> Self {
496 Self(object_ref.0, object_ref.1)
497 }
498}
499
500#[derive(Clone)]
501pub enum ObjectOrTombstone {
502 Object(Object),
503 Tombstone(ObjectRef),
504}
505
506impl ObjectOrTombstone {
507 pub fn as_objref(&self) -> ObjectRef {
508 match self {
509 ObjectOrTombstone::Object(obj) => obj.compute_object_reference(),
510 ObjectOrTombstone::Tombstone(obref) => *obref,
511 }
512 }
513}
514
515impl From<Object> for ObjectOrTombstone {
516 fn from(object: Object) -> Self {
517 ObjectOrTombstone::Object(object)
518 }
519}
520
521pub fn transaction_non_shared_input_object_keys(
525 tx: &SenderSignedData,
526) -> IotaResult<Vec<ObjectKey>> {
527 use crate::transaction::InputObjectKind as I;
528 Ok(tx
529 .intent_message()
530 .value
531 .input_objects()?
532 .into_iter()
533 .filter_map(|object| match object {
534 I::MovePackage(_) | I::SharedMoveObject { .. } => None,
535 I::ImmOrOwnedMoveObject(obj) => Some(obj.into()),
536 })
537 .collect())
538}
539
540pub fn transaction_receiving_object_keys(tx: &SenderSignedData) -> Vec<ObjectKey> {
541 tx.intent_message()
542 .value
543 .receiving_objects()
544 .into_iter()
545 .map(|oref| oref.into())
546 .collect()
547}
548
549impl Display for DeleteKind {
550 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
551 match self {
552 DeleteKind::Wrap => write!(f, "Wrap"),
553 DeleteKind::Normal => write!(f, "Normal"),
554 DeleteKind::UnwrapThenDelete => write!(f, "UnwrapThenDelete"),
555 }
556 }
557}
558
559pub trait BackingStore: BackingPackageStore + ChildObjectResolver + ObjectStore {
560 fn as_object_store(&self) -> &dyn ObjectStore;
561}
562
563impl<T> BackingStore for T
564where
565 T: BackingPackageStore,
566 T: ChildObjectResolver,
567 T: ObjectStore,
568{
569 fn as_object_store(&self) -> &dyn ObjectStore {
570 self
571 }
572}
573
574pub trait GetSharedLocks: Send + Sync {
575 fn get_shared_locks(
576 &self,
577 key: &TransactionKey,
578 ) -> IotaResult<Option<Vec<(ObjectID, SequenceNumber)>>>;
579}