1use crate::{
6 Digest, EpochId, GasCostSummary, ObjectId,
7 execution_status::ExecutionStatus,
8 object::{Owner, Version},
9};
10
11#[derive(Eq, PartialEq, Clone, Debug)]
31#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
32#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
33pub struct TransactionEffectsV1 {
34 #[cfg_attr(feature = "schemars", schemars(flatten))]
36 pub status: ExecutionStatus,
37 #[cfg_attr(feature = "schemars", schemars(with = "crate::_schemars::U64"))]
39 pub epoch: EpochId,
40 pub gas_used: GasCostSummary,
42 pub transaction_digest: Digest,
44 pub gas_object_index: Option<u32>,
48 pub events_digest: Option<Digest>,
51 #[cfg_attr(feature = "proptest", any(proptest::collection::size_range(0..=5).lift()))]
53 pub dependencies: Vec<Digest>,
54 #[cfg_attr(feature = "schemars", schemars(with = "crate::_schemars::U64"))]
56 pub lamport_version: Version,
57 #[cfg_attr(feature = "proptest", any(proptest::collection::size_range(0..=2).lift()))]
59 pub changed_objects: Vec<ChangedObject>,
60 #[cfg_attr(feature = "proptest", any(proptest::collection::size_range(0..=2).lift()))]
66 pub unchanged_shared_objects: Vec<UnchangedSharedObject>,
67 pub auxiliary_data_digest: Option<Digest>,
72}
73
74impl TransactionEffectsV1 {
75 pub fn status(&self) -> &ExecutionStatus {
77 &self.status
78 }
79
80 pub fn epoch(&self) -> EpochId {
82 self.epoch
83 }
84
85 pub fn gas_summary(&self) -> &GasCostSummary {
87 &self.gas_used
88 }
89}
90
91#[derive(Eq, PartialEq, Clone, Debug)]
101#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
102#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
103#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
104pub struct ChangedObject {
105 pub object_id: ObjectId,
107 pub input_state: ObjectIn,
109 pub output_state: ObjectOut,
111 pub id_operation: IdOperation,
115}
116
117#[derive(Eq, PartialEq, Clone, Debug)]
127#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
128#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
129#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
130pub struct UnchangedSharedObject {
131 pub object_id: ObjectId,
132 pub kind: UnchangedSharedKind,
133}
134
135#[derive(Eq, PartialEq, Clone, Debug)]
155#[cfg_attr(
156 feature = "schemars",
157 derive(schemars::JsonSchema),
158 schemars(tag = "kind", rename_all = "snake_case")
159)]
160#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
161pub enum UnchangedSharedKind {
162 ReadOnlyRoot {
166 #[cfg_attr(feature = "schemars", schemars(with = "crate::_schemars::U64"))]
167 version: Version,
168 digest: Digest,
169 },
170 MutateDeleted {
172 #[cfg_attr(feature = "schemars", schemars(with = "crate::_schemars::U64"))]
173 version: Version,
174 },
175 ReadDeleted {
177 #[cfg_attr(feature = "schemars", schemars(with = "crate::_schemars::U64"))]
178 version: Version,
179 },
180 Cancelled {
183 #[cfg_attr(feature = "schemars", schemars(with = "crate::_schemars::U64"))]
184 version: Version,
185 },
186 PerEpochConfig,
189}
190
191impl UnchangedSharedKind {
192 crate::def_is!(
193 ReadOnlyRoot,
194 MutateDeleted,
195 ReadDeleted,
196 Cancelled,
197 PerEpochConfig
198 );
199}
200
201#[derive(Eq, PartialEq, Clone, Debug)]
218#[cfg_attr(
219 feature = "schemars",
220 derive(schemars::JsonSchema),
221 schemars(tag = "state", rename_all = "snake_case")
222)]
223#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
224pub enum ObjectIn {
225 Missing,
226 Data {
228 #[cfg_attr(feature = "schemars", schemars(with = "crate::_schemars::U64"))]
229 version: Version,
230 digest: Digest,
231 owner: Owner,
232 },
233}
234
235impl ObjectIn {
236 crate::def_is!(Missing, Data);
237
238 pub fn version_opt(&self) -> Option<Version> {
239 if let Self::Data { version, .. } = self {
240 Some(*version)
241 } else {
242 None
243 }
244 }
245
246 pub fn version(&self) -> Version {
247 self.version_opt().expect("object does not exist")
248 }
249
250 pub fn digest_opt(&self) -> Option<Digest> {
251 if let Self::Data { digest, .. } = self {
252 Some(*digest)
253 } else {
254 None
255 }
256 }
257
258 pub fn digest(&self) -> Digest {
259 self.digest_opt().expect("object does not exist")
260 }
261
262 pub fn owner_opt(&self) -> Option<Owner> {
263 if let Self::Data { owner, .. } = self {
264 Some(*owner)
265 } else {
266 None
267 }
268 }
269
270 pub fn owner(&self) -> Owner {
271 self.owner_opt().expect("object does not exist")
272 }
273}
274
275#[derive(Eq, PartialEq, Clone, Debug)]
292#[cfg_attr(
293 feature = "schemars",
294 derive(schemars::JsonSchema),
295 schemars(tag = "state", rename_all = "snake_case")
296)]
297#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
298pub enum ObjectOut {
299 Missing,
301 ObjectWrite { digest: Digest, owner: Owner },
303 PackageWrite {
306 #[cfg_attr(feature = "schemars", schemars(with = "crate::_schemars::U64"))]
307 version: Version,
308 digest: Digest,
309 },
310}
311
312impl ObjectOut {
313 crate::def_is!(Missing, ObjectWrite, PackageWrite);
314
315 pub fn object_digest_opt(&self) -> Option<Digest> {
316 if let Self::ObjectWrite { digest, .. } = self {
317 Some(*digest)
318 } else {
319 None
320 }
321 }
322
323 pub fn object_digest(&self) -> Digest {
324 self.object_digest_opt().expect("object does not exist")
325 }
326
327 pub fn object_owner_opt(&self) -> Option<Owner> {
328 if let Self::ObjectWrite { owner, .. } = self {
329 Some(*owner)
330 } else {
331 None
332 }
333 }
334
335 pub fn object_owner(&self) -> Owner {
336 self.object_owner_opt().expect("object does not exist")
337 }
338
339 pub fn package_version_opt(&self) -> Option<Version> {
340 if let Self::PackageWrite { version, .. } = self {
341 Some(*version)
342 } else {
343 None
344 }
345 }
346
347 pub fn package_version(&self) -> Version {
348 self.package_version_opt().expect("object does not exist")
349 }
350
351 pub fn package_digest_opt(&self) -> Option<Digest> {
352 if let Self::PackageWrite { digest, .. } = self {
353 Some(*digest)
354 } else {
355 None
356 }
357 }
358
359 pub fn package_digest(&self) -> Digest {
360 self.package_digest_opt().expect("package does not exist")
361 }
362}
363
364#[derive(Eq, PartialEq, Copy, Clone, Debug)]
380#[cfg_attr(
381 feature = "serde",
382 derive(serde::Serialize, serde::Deserialize),
383 serde(rename_all = "lowercase")
384)]
385#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
386#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
387pub enum IdOperation {
388 None,
389 Created,
390 Deleted,
391}
392
393impl IdOperation {
394 crate::def_is!(None, Created, Deleted);
395}
396
397#[cfg(feature = "serde")]
398#[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
399mod serialization {
400 use serde::{Deserialize, Deserializer, Serialize, Serializer};
401
402 use super::*;
403
404 #[derive(serde::Serialize)]
405 struct ReadableTransactionEffectsV1Ref<'a> {
406 #[serde(flatten)]
407 status: &'a ExecutionStatus,
408 #[serde(with = "crate::_serde::ReadableDisplay")]
409 epoch: &'a EpochId,
410 gas_used: &'a GasCostSummary,
411 transaction_digest: &'a Digest,
412 gas_object_index: &'a Option<u32>,
413 events_digest: &'a Option<Digest>,
414 dependencies: &'a Vec<Digest>,
415 #[serde(with = "crate::_serde::ReadableDisplay")]
416 lamport_version: &'a Version,
417 changed_objects: &'a Vec<ChangedObject>,
418 unchanged_shared_objects: &'a Vec<UnchangedSharedObject>,
419 auxiliary_data_digest: &'a Option<Digest>,
420 }
421
422 #[derive(serde::Deserialize)]
423 struct ReadableTransactionEffectsV1 {
424 #[serde(flatten)]
425 status: ExecutionStatus,
426 #[serde(with = "crate::_serde::ReadableDisplay")]
427 epoch: EpochId,
428 gas_used: GasCostSummary,
429 transaction_digest: Digest,
430 gas_object_index: Option<u32>,
431 events_digest: Option<Digest>,
432 dependencies: Vec<Digest>,
433 #[serde(with = "crate::_serde::ReadableDisplay")]
434 lamport_version: Version,
435 changed_objects: Vec<ChangedObject>,
436 unchanged_shared_objects: Vec<UnchangedSharedObject>,
437 auxiliary_data_digest: Option<Digest>,
438 }
439
440 #[derive(serde::Serialize)]
441 struct BinaryTransactionEffectsV1Ref<'a> {
442 status: &'a ExecutionStatus,
443 epoch: &'a EpochId,
444 gas_used: &'a GasCostSummary,
445 transaction_digest: &'a Digest,
446 gas_object_index: &'a Option<u32>,
447 events_digest: &'a Option<Digest>,
448 dependencies: &'a Vec<Digest>,
449 lamport_version: &'a Version,
450 changed_objects: &'a Vec<ChangedObject>,
451 unchanged_shared_objects: &'a Vec<UnchangedSharedObject>,
452 auxiliary_data_digest: &'a Option<Digest>,
453 }
454
455 #[derive(serde::Deserialize)]
456 struct BinaryTransactionEffectsV1 {
457 status: ExecutionStatus,
458 epoch: EpochId,
459 gas_used: GasCostSummary,
460 transaction_digest: Digest,
461 gas_object_index: Option<u32>,
462 events_digest: Option<Digest>,
463 dependencies: Vec<Digest>,
464 lamport_version: Version,
465 changed_objects: Vec<ChangedObject>,
466 unchanged_shared_objects: Vec<UnchangedSharedObject>,
467 auxiliary_data_digest: Option<Digest>,
468 }
469
470 impl Serialize for TransactionEffectsV1 {
471 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
472 where
473 S: Serializer,
474 {
475 let Self {
476 status,
477 epoch,
478 gas_used,
479 transaction_digest,
480 gas_object_index,
481 events_digest,
482 dependencies,
483 lamport_version,
484 changed_objects,
485 unchanged_shared_objects,
486 auxiliary_data_digest,
487 } = self;
488 if serializer.is_human_readable() {
489 let readable = ReadableTransactionEffectsV1Ref {
490 status,
491 epoch,
492 gas_used,
493 transaction_digest,
494 gas_object_index,
495 events_digest,
496 dependencies,
497 lamport_version,
498 changed_objects,
499 unchanged_shared_objects,
500 auxiliary_data_digest,
501 };
502 readable.serialize(serializer)
503 } else {
504 let binary = BinaryTransactionEffectsV1Ref {
505 status,
506 epoch,
507 gas_used,
508 transaction_digest,
509 gas_object_index,
510 events_digest,
511 dependencies,
512 lamport_version,
513 changed_objects,
514 unchanged_shared_objects,
515 auxiliary_data_digest,
516 };
517 binary.serialize(serializer)
518 }
519 }
520 }
521
522 impl<'de> Deserialize<'de> for TransactionEffectsV1 {
523 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
524 where
525 D: Deserializer<'de>,
526 {
527 if deserializer.is_human_readable() {
528 let ReadableTransactionEffectsV1 {
529 status,
530 epoch,
531 gas_used,
532 transaction_digest,
533 gas_object_index,
534 events_digest,
535 dependencies,
536 lamport_version,
537 changed_objects,
538 unchanged_shared_objects,
539 auxiliary_data_digest,
540 } = Deserialize::deserialize(deserializer)?;
541 Ok(Self {
542 status,
543 epoch,
544 gas_used,
545 transaction_digest,
546 gas_object_index,
547 events_digest,
548 dependencies,
549 lamport_version,
550 changed_objects,
551 unchanged_shared_objects,
552 auxiliary_data_digest,
553 })
554 } else {
555 let BinaryTransactionEffectsV1 {
556 status,
557 epoch,
558 gas_used,
559 transaction_digest,
560 gas_object_index,
561 events_digest,
562 dependencies,
563 lamport_version,
564 changed_objects,
565 unchanged_shared_objects,
566 auxiliary_data_digest,
567 } = Deserialize::deserialize(deserializer)?;
568 Ok(Self {
569 status,
570 epoch,
571 gas_used,
572 transaction_digest,
573 gas_object_index,
574 events_digest,
575 dependencies,
576 lamport_version,
577 changed_objects,
578 unchanged_shared_objects,
579 auxiliary_data_digest,
580 })
581 }
582 }
583 }
584
585 #[derive(serde::Serialize, serde::Deserialize)]
586 #[serde(tag = "kind", rename_all = "snake_case")]
587 enum ReadableUnchangedSharedKind {
588 ReadOnlyRoot {
589 #[serde(with = "crate::_serde::ReadableDisplay")]
590 version: Version,
591 digest: Digest,
592 },
593 MutateDeleted {
594 #[serde(with = "crate::_serde::ReadableDisplay")]
595 version: Version,
596 },
597 ReadDeleted {
598 #[serde(with = "crate::_serde::ReadableDisplay")]
599 version: Version,
600 },
601 Cancelled {
602 #[serde(with = "crate::_serde::ReadableDisplay")]
603 version: Version,
604 },
605 PerEpochConfig,
606 }
607
608 #[derive(serde::Serialize, serde::Deserialize)]
609 enum BinaryUnchangedSharedKind {
610 ReadOnlyRoot { version: Version, digest: Digest },
611 MutateDeleted { version: Version },
612 ReadDeleted { version: Version },
613 Cancelled { version: Version },
614 PerEpochConfig,
615 }
616
617 impl Serialize for UnchangedSharedKind {
618 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
619 where
620 S: Serializer,
621 {
622 if serializer.is_human_readable() {
623 let readable = match self.clone() {
624 UnchangedSharedKind::ReadOnlyRoot { version, digest } => {
625 ReadableUnchangedSharedKind::ReadOnlyRoot { version, digest }
626 }
627 UnchangedSharedKind::MutateDeleted { version } => {
628 ReadableUnchangedSharedKind::MutateDeleted { version }
629 }
630 UnchangedSharedKind::ReadDeleted { version } => {
631 ReadableUnchangedSharedKind::ReadDeleted { version }
632 }
633 UnchangedSharedKind::Cancelled { version } => {
634 ReadableUnchangedSharedKind::Cancelled { version }
635 }
636 UnchangedSharedKind::PerEpochConfig => {
637 ReadableUnchangedSharedKind::PerEpochConfig
638 }
639 };
640 readable.serialize(serializer)
641 } else {
642 let binary = match self.clone() {
643 UnchangedSharedKind::ReadOnlyRoot { version, digest } => {
644 BinaryUnchangedSharedKind::ReadOnlyRoot { version, digest }
645 }
646 UnchangedSharedKind::MutateDeleted { version } => {
647 BinaryUnchangedSharedKind::MutateDeleted { version }
648 }
649 UnchangedSharedKind::ReadDeleted { version } => {
650 BinaryUnchangedSharedKind::ReadDeleted { version }
651 }
652 UnchangedSharedKind::Cancelled { version } => {
653 BinaryUnchangedSharedKind::Cancelled { version }
654 }
655 UnchangedSharedKind::PerEpochConfig => {
656 BinaryUnchangedSharedKind::PerEpochConfig
657 }
658 };
659 binary.serialize(serializer)
660 }
661 }
662 }
663
664 impl<'de> Deserialize<'de> for UnchangedSharedKind {
665 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
666 where
667 D: Deserializer<'de>,
668 {
669 if deserializer.is_human_readable() {
670 ReadableUnchangedSharedKind::deserialize(deserializer).map(
671 |readable| match readable {
672 ReadableUnchangedSharedKind::ReadOnlyRoot { version, digest } => {
673 Self::ReadOnlyRoot { version, digest }
674 }
675 ReadableUnchangedSharedKind::MutateDeleted { version } => {
676 Self::MutateDeleted { version }
677 }
678 ReadableUnchangedSharedKind::ReadDeleted { version } => {
679 Self::ReadDeleted { version }
680 }
681 ReadableUnchangedSharedKind::Cancelled { version } => {
682 Self::Cancelled { version }
683 }
684 ReadableUnchangedSharedKind::PerEpochConfig => Self::PerEpochConfig,
685 },
686 )
687 } else {
688 BinaryUnchangedSharedKind::deserialize(deserializer).map(|binary| match binary {
689 BinaryUnchangedSharedKind::ReadOnlyRoot { version, digest } => {
690 Self::ReadOnlyRoot { version, digest }
691 }
692 BinaryUnchangedSharedKind::MutateDeleted { version } => {
693 Self::MutateDeleted { version }
694 }
695 BinaryUnchangedSharedKind::ReadDeleted { version } => {
696 Self::ReadDeleted { version }
697 }
698 BinaryUnchangedSharedKind::Cancelled { version } => Self::Cancelled { version },
699 BinaryUnchangedSharedKind::PerEpochConfig => Self::PerEpochConfig,
700 })
701 }
702 }
703 }
704
705 #[derive(serde::Serialize, serde::Deserialize)]
706 #[serde(tag = "state", rename_all = "snake_case")]
707 enum ReadableObjectIn {
708 Missing,
709 Data {
710 #[serde(with = "crate::_serde::ReadableDisplay")]
711 version: Version,
712 digest: Digest,
713 owner: Owner,
714 },
715 }
716
717 #[derive(serde::Serialize, serde::Deserialize)]
718 enum BinaryObjectIn {
719 Missing,
720 Data {
721 version: Version,
722 digest: Digest,
723 owner: Owner,
724 },
725 }
726
727 impl Serialize for ObjectIn {
728 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
729 where
730 S: Serializer,
731 {
732 if serializer.is_human_readable() {
733 let readable = match self.clone() {
734 ObjectIn::Missing => ReadableObjectIn::Missing,
735 ObjectIn::Data {
736 version,
737 digest,
738 owner,
739 } => ReadableObjectIn::Data {
740 version,
741 digest,
742 owner,
743 },
744 };
745 readable.serialize(serializer)
746 } else {
747 let binary = match self.clone() {
748 ObjectIn::Missing => BinaryObjectIn::Missing,
749 ObjectIn::Data {
750 version,
751 digest,
752 owner,
753 } => BinaryObjectIn::Data {
754 version,
755 digest,
756 owner,
757 },
758 };
759 binary.serialize(serializer)
760 }
761 }
762 }
763
764 impl<'de> Deserialize<'de> for ObjectIn {
765 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
766 where
767 D: Deserializer<'de>,
768 {
769 if deserializer.is_human_readable() {
770 ReadableObjectIn::deserialize(deserializer).map(|readable| match readable {
771 ReadableObjectIn::Missing => Self::Missing,
772 ReadableObjectIn::Data {
773 version,
774 digest,
775 owner,
776 } => Self::Data {
777 version,
778 digest,
779 owner,
780 },
781 })
782 } else {
783 BinaryObjectIn::deserialize(deserializer).map(|binary| match binary {
784 BinaryObjectIn::Missing => Self::Missing,
785 BinaryObjectIn::Data {
786 version,
787 digest,
788 owner,
789 } => Self::Data {
790 version,
791 digest,
792 owner,
793 },
794 })
795 }
796 }
797 }
798
799 #[derive(serde::Serialize, serde::Deserialize)]
800 #[serde(tag = "state", rename_all = "snake_case")]
801 enum ReadableObjectOut {
802 Missing,
803 ObjectWrite {
804 digest: Digest,
805 owner: Owner,
806 },
807 PackageWrite {
808 #[serde(with = "crate::_serde::ReadableDisplay")]
809 version: Version,
810 digest: Digest,
811 },
812 }
813
814 #[derive(serde::Serialize, serde::Deserialize)]
815 enum BinaryObjectOut {
816 Missing,
817 ObjectWrite {
818 digest: Digest,
819 owner: Owner,
820 },
821 PackageWrite {
822 #[serde(with = "crate::_serde::ReadableDisplay")]
823 version: Version,
824 digest: Digest,
825 },
826 }
827
828 impl Serialize for ObjectOut {
829 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
830 where
831 S: Serializer,
832 {
833 if serializer.is_human_readable() {
834 let readable = match self.clone() {
835 ObjectOut::Missing => ReadableObjectOut::Missing,
836 ObjectOut::ObjectWrite { digest, owner } => {
837 ReadableObjectOut::ObjectWrite { digest, owner }
838 }
839 ObjectOut::PackageWrite { version, digest } => {
840 ReadableObjectOut::PackageWrite { version, digest }
841 }
842 };
843 readable.serialize(serializer)
844 } else {
845 let binary = match self.clone() {
846 ObjectOut::Missing => BinaryObjectOut::Missing,
847 ObjectOut::ObjectWrite { digest, owner } => {
848 BinaryObjectOut::ObjectWrite { digest, owner }
849 }
850 ObjectOut::PackageWrite { version, digest } => {
851 BinaryObjectOut::PackageWrite { version, digest }
852 }
853 };
854 binary.serialize(serializer)
855 }
856 }
857 }
858
859 impl<'de> Deserialize<'de> for ObjectOut {
860 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
861 where
862 D: Deserializer<'de>,
863 {
864 if deserializer.is_human_readable() {
865 ReadableObjectOut::deserialize(deserializer).map(|readable| match readable {
866 ReadableObjectOut::Missing => Self::Missing,
867 ReadableObjectOut::ObjectWrite { digest, owner } => {
868 Self::ObjectWrite { digest, owner }
869 }
870 ReadableObjectOut::PackageWrite { version, digest } => {
871 Self::PackageWrite { version, digest }
872 }
873 })
874 } else {
875 BinaryObjectOut::deserialize(deserializer).map(|binary| match binary {
876 BinaryObjectOut::Missing => Self::Missing,
877 BinaryObjectOut::ObjectWrite { digest, owner } => {
878 Self::ObjectWrite { digest, owner }
879 }
880 BinaryObjectOut::PackageWrite { version, digest } => {
881 Self::PackageWrite { version, digest }
882 }
883 })
884 }
885 }
886 }
887}