1use crate::digest::EffectsAuxiliaryDataDigest;
2use crate::execution_status::ExecutionStatus;
3use crate::object::Owner;
4use crate::object::Version;
5use crate::EpochId;
6use crate::GasCostSummary;
7use crate::ObjectDigest;
8use crate::ObjectId;
9use crate::TransactionDigest;
10use crate::TransactionEventsDigest;
11
12#[derive(Eq, PartialEq, Clone, Debug)]
32#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
33pub struct TransactionEffectsV2 {
34 pub status: ExecutionStatus,
36
37 pub epoch: EpochId,
39
40 pub gas_used: GasCostSummary,
42
43 pub transaction_digest: TransactionDigest,
45
46 pub gas_object_index: Option<u32>,
50
51 pub events_digest: Option<TransactionEventsDigest>,
54
55 #[cfg_attr(feature = "proptest", any(proptest::collection::size_range(0..=5).lift()))]
57 pub dependencies: Vec<TransactionDigest>,
58
59 pub lamport_version: Version,
61
62 #[cfg_attr(feature = "proptest", any(proptest::collection::size_range(0..=2).lift()))]
64 pub changed_objects: Vec<ChangedObject>,
65
66 #[cfg_attr(feature = "proptest", any(proptest::collection::size_range(0..=2).lift()))]
71 pub unchanged_shared_objects: Vec<UnchangedSharedObject>,
72
73 pub auxiliary_data_digest: Option<EffectsAuxiliaryDataDigest>,
77}
78
79#[derive(Eq, PartialEq, Clone, Debug)]
89#[cfg_attr(
90 feature = "serde",
91 derive(serde_derive::Serialize, serde_derive::Deserialize)
92)]
93#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
94pub struct ChangedObject {
95 pub object_id: ObjectId,
97
98 pub input_state: ObjectIn,
100
101 pub output_state: ObjectOut,
103
104 pub id_operation: IdOperation,
108}
109
110#[derive(Eq, PartialEq, Clone, Debug)]
120#[cfg_attr(
121 feature = "serde",
122 derive(serde_derive::Serialize, serde_derive::Deserialize)
123)]
124#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
125pub struct UnchangedSharedObject {
126 pub object_id: ObjectId,
127 pub kind: UnchangedSharedKind,
128}
129
130#[derive(Eq, PartialEq, Clone, Debug)]
151#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
152pub enum UnchangedSharedKind {
153 ReadOnlyRoot {
156 version: Version,
157 digest: ObjectDigest,
158 },
159
160 MutateDeleted { version: Version },
162
163 ReadDeleted { version: Version },
165
166 Canceled { version: Version },
168
169 PerEpochConfig,
172
173 PerEpochConfigWithSequenceNumber { version: Version },
175}
176
177#[derive(Eq, PartialEq, Clone, Debug)]
194#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
195pub enum ObjectIn {
196 NotExist,
197
198 Exist {
200 version: Version,
201 digest: ObjectDigest,
202 owner: Owner,
203 },
204}
205
206#[derive(Eq, PartialEq, Clone, Debug)]
223#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
224pub enum ObjectOut {
225 NotExist,
227
228 ObjectWrite { digest: ObjectDigest, owner: Owner },
230
231 PackageWrite {
234 version: Version,
235 digest: ObjectDigest,
236 },
237}
238
239#[derive(Eq, PartialEq, Copy, Clone, Debug)]
255#[cfg_attr(
256 feature = "serde",
257 derive(serde_derive::Serialize, serde_derive::Deserialize),
258 serde(rename_all = "lowercase")
259)]
260#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
261pub enum IdOperation {
262 None,
263 Created,
264 Deleted,
265}
266
267impl TransactionEffectsV2 {
268 pub fn status(&self) -> &ExecutionStatus {
270 &self.status
271 }
272
273 pub fn epoch(&self) -> EpochId {
275 self.epoch
276 }
277
278 pub fn gas_summary(&self) -> &GasCostSummary {
280 &self.gas_used
281 }
282}
283
284#[cfg(feature = "serde")]
285#[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
286mod serialization {
287 use serde::Deserialize;
288 use serde::Deserializer;
289 use serde::Serialize;
290 use serde::Serializer;
291
292 use super::*;
293
294 #[derive(serde_derive::Serialize)]
295 struct ReadableTransactionEffectsV2Ref<'a> {
296 #[serde(flatten)]
297 status: &'a ExecutionStatus,
298 #[serde(with = "crate::_serde::ReadableDisplay")]
299 epoch: &'a EpochId,
300 gas_used: &'a GasCostSummary,
301 transaction_digest: &'a TransactionDigest,
302 gas_object_index: &'a Option<u32>,
303 events_digest: &'a Option<TransactionEventsDigest>,
304 dependencies: &'a Vec<TransactionDigest>,
305 #[serde(with = "crate::_serde::ReadableDisplay")]
306 lamport_version: &'a Version,
307 changed_objects: &'a Vec<ChangedObject>,
308 unchanged_shared_objects: &'a Vec<UnchangedSharedObject>,
309 auxiliary_data_digest: &'a Option<EffectsAuxiliaryDataDigest>,
310 }
311
312 #[derive(serde_derive::Deserialize)]
313 struct ReadableTransactionEffectsV2 {
314 #[serde(flatten)]
315 status: ExecutionStatus,
316 #[serde(with = "crate::_serde::ReadableDisplay")]
317 epoch: EpochId,
318 gas_used: GasCostSummary,
319 transaction_digest: TransactionDigest,
320 gas_object_index: Option<u32>,
321 events_digest: Option<TransactionEventsDigest>,
322 dependencies: Vec<TransactionDigest>,
323 #[serde(with = "crate::_serde::ReadableDisplay")]
324 lamport_version: Version,
325 changed_objects: Vec<ChangedObject>,
326 unchanged_shared_objects: Vec<UnchangedSharedObject>,
327 auxiliary_data_digest: Option<EffectsAuxiliaryDataDigest>,
328 }
329
330 #[derive(serde_derive::Serialize)]
331 struct BinaryTransactionEffectsV2Ref<'a> {
332 status: &'a ExecutionStatus,
333 epoch: &'a EpochId,
334 gas_used: &'a GasCostSummary,
335 transaction_digest: &'a TransactionDigest,
336 gas_object_index: &'a Option<u32>,
337 events_digest: &'a Option<TransactionEventsDigest>,
338 dependencies: &'a Vec<TransactionDigest>,
339 lamport_version: &'a Version,
340 changed_objects: &'a Vec<ChangedObject>,
341 unchanged_shared_objects: &'a Vec<UnchangedSharedObject>,
342 auxiliary_data_digest: &'a Option<EffectsAuxiliaryDataDigest>,
343 }
344
345 #[derive(serde_derive::Deserialize)]
346 struct BinaryTransactionEffectsV2 {
347 status: ExecutionStatus,
348 epoch: EpochId,
349 gas_used: GasCostSummary,
350 transaction_digest: TransactionDigest,
351 gas_object_index: Option<u32>,
352 events_digest: Option<TransactionEventsDigest>,
353 dependencies: Vec<TransactionDigest>,
354 lamport_version: Version,
355 changed_objects: Vec<ChangedObject>,
356 unchanged_shared_objects: Vec<UnchangedSharedObject>,
357 auxiliary_data_digest: Option<EffectsAuxiliaryDataDigest>,
358 }
359
360 impl Serialize for TransactionEffectsV2 {
361 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
362 where
363 S: Serializer,
364 {
365 let Self {
366 status,
367 epoch,
368 gas_used,
369 transaction_digest,
370 gas_object_index,
371 events_digest,
372 dependencies,
373 lamport_version,
374 changed_objects,
375 unchanged_shared_objects,
376 auxiliary_data_digest,
377 } = self;
378 if serializer.is_human_readable() {
379 let readable = ReadableTransactionEffectsV2Ref {
380 status,
381 epoch,
382 gas_used,
383 transaction_digest,
384 gas_object_index,
385 events_digest,
386 dependencies,
387 lamport_version,
388 changed_objects,
389 unchanged_shared_objects,
390 auxiliary_data_digest,
391 };
392 readable.serialize(serializer)
393 } else {
394 let binary = BinaryTransactionEffectsV2Ref {
395 status,
396 epoch,
397 gas_used,
398 transaction_digest,
399 gas_object_index,
400 events_digest,
401 dependencies,
402 lamport_version,
403 changed_objects,
404 unchanged_shared_objects,
405 auxiliary_data_digest,
406 };
407 binary.serialize(serializer)
408 }
409 }
410 }
411
412 impl<'de> Deserialize<'de> for TransactionEffectsV2 {
413 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
414 where
415 D: Deserializer<'de>,
416 {
417 if deserializer.is_human_readable() {
418 let ReadableTransactionEffectsV2 {
419 status,
420 epoch,
421 gas_used,
422 transaction_digest,
423 gas_object_index,
424 events_digest,
425 dependencies,
426 lamport_version,
427 changed_objects,
428 unchanged_shared_objects,
429 auxiliary_data_digest,
430 } = Deserialize::deserialize(deserializer)?;
431 Ok(Self {
432 status,
433 epoch,
434 gas_used,
435 transaction_digest,
436 gas_object_index,
437 events_digest,
438 dependencies,
439 lamport_version,
440 changed_objects,
441 unchanged_shared_objects,
442 auxiliary_data_digest,
443 })
444 } else {
445 let BinaryTransactionEffectsV2 {
446 status,
447 epoch,
448 gas_used,
449 transaction_digest,
450 gas_object_index,
451 events_digest,
452 dependencies,
453 lamport_version,
454 changed_objects,
455 unchanged_shared_objects,
456 auxiliary_data_digest,
457 } = Deserialize::deserialize(deserializer)?;
458 Ok(Self {
459 status,
460 epoch,
461 gas_used,
462 transaction_digest,
463 gas_object_index,
464 events_digest,
465 dependencies,
466 lamport_version,
467 changed_objects,
468 unchanged_shared_objects,
469 auxiliary_data_digest,
470 })
471 }
472 }
473 }
474
475 #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
476 #[serde(tag = "kind", rename_all = "snake_case")]
477 enum ReadableUnchangedSharedKind {
478 ReadOnlyRoot {
479 #[serde(with = "crate::_serde::ReadableDisplay")]
480 version: Version,
481 digest: ObjectDigest,
482 },
483 MutateDeleted {
484 #[serde(with = "crate::_serde::ReadableDisplay")]
485 version: Version,
486 },
487 ReadDeleted {
488 #[serde(with = "crate::_serde::ReadableDisplay")]
489 version: Version,
490 },
491 Canceled {
492 #[serde(with = "crate::_serde::ReadableDisplay")]
493 version: Version,
494 },
495 PerEpochConfig,
496 PerEpochConfigWithSequenceNumber {
497 #[serde(with = "crate::_serde::ReadableDisplay")]
498 version: Version,
499 },
500 }
501
502 #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
503 enum BinaryUnchangedSharedKind {
504 ReadOnlyRoot {
505 version: Version,
506 digest: ObjectDigest,
507 },
508 MutateDeleted {
509 version: Version,
510 },
511 ReadDeleted {
512 version: Version,
513 },
514 Canceled {
515 version: Version,
516 },
517 PerEpochConfig,
518 PerEpochConfigWithSequenceNumber {
519 version: Version,
520 },
521 }
522
523 impl Serialize for UnchangedSharedKind {
524 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
525 where
526 S: Serializer,
527 {
528 if serializer.is_human_readable() {
529 let readable = match self.clone() {
530 UnchangedSharedKind::ReadOnlyRoot { version, digest } => {
531 ReadableUnchangedSharedKind::ReadOnlyRoot { version, digest }
532 }
533 UnchangedSharedKind::MutateDeleted { version } => {
534 ReadableUnchangedSharedKind::MutateDeleted { version }
535 }
536 UnchangedSharedKind::ReadDeleted { version } => {
537 ReadableUnchangedSharedKind::ReadDeleted { version }
538 }
539 UnchangedSharedKind::Canceled { version } => {
540 ReadableUnchangedSharedKind::Canceled { version }
541 }
542 UnchangedSharedKind::PerEpochConfig => {
543 ReadableUnchangedSharedKind::PerEpochConfig
544 }
545 UnchangedSharedKind::PerEpochConfigWithSequenceNumber { version } => {
546 ReadableUnchangedSharedKind::PerEpochConfigWithSequenceNumber { version }
547 }
548 };
549 readable.serialize(serializer)
550 } else {
551 let binary = match self.clone() {
552 UnchangedSharedKind::ReadOnlyRoot { version, digest } => {
553 BinaryUnchangedSharedKind::ReadOnlyRoot { version, digest }
554 }
555 UnchangedSharedKind::MutateDeleted { version } => {
556 BinaryUnchangedSharedKind::MutateDeleted { version }
557 }
558 UnchangedSharedKind::ReadDeleted { version } => {
559 BinaryUnchangedSharedKind::ReadDeleted { version }
560 }
561 UnchangedSharedKind::Canceled { version } => {
562 BinaryUnchangedSharedKind::Canceled { version }
563 }
564 UnchangedSharedKind::PerEpochConfig => {
565 BinaryUnchangedSharedKind::PerEpochConfig
566 }
567 UnchangedSharedKind::PerEpochConfigWithSequenceNumber { version } => {
568 BinaryUnchangedSharedKind::PerEpochConfigWithSequenceNumber { version }
569 }
570 };
571 binary.serialize(serializer)
572 }
573 }
574 }
575
576 impl<'de> Deserialize<'de> for UnchangedSharedKind {
577 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
578 where
579 D: Deserializer<'de>,
580 {
581 if deserializer.is_human_readable() {
582 ReadableUnchangedSharedKind::deserialize(deserializer).map(
583 |readable| match readable {
584 ReadableUnchangedSharedKind::ReadOnlyRoot { version, digest } => {
585 Self::ReadOnlyRoot { version, digest }
586 }
587 ReadableUnchangedSharedKind::MutateDeleted { version } => {
588 Self::MutateDeleted { version }
589 }
590 ReadableUnchangedSharedKind::ReadDeleted { version } => {
591 Self::ReadDeleted { version }
592 }
593 ReadableUnchangedSharedKind::Canceled { version } => {
594 Self::Canceled { version }
595 }
596 ReadableUnchangedSharedKind::PerEpochConfig => Self::PerEpochConfig,
597 ReadableUnchangedSharedKind::PerEpochConfigWithSequenceNumber {
598 version,
599 } => Self::PerEpochConfigWithSequenceNumber { version },
600 },
601 )
602 } else {
603 BinaryUnchangedSharedKind::deserialize(deserializer).map(|binary| match binary {
604 BinaryUnchangedSharedKind::ReadOnlyRoot { version, digest } => {
605 Self::ReadOnlyRoot { version, digest }
606 }
607 BinaryUnchangedSharedKind::MutateDeleted { version } => {
608 Self::MutateDeleted { version }
609 }
610 BinaryUnchangedSharedKind::ReadDeleted { version } => {
611 Self::ReadDeleted { version }
612 }
613 BinaryUnchangedSharedKind::Canceled { version } => Self::Canceled { version },
614 BinaryUnchangedSharedKind::PerEpochConfig => Self::PerEpochConfig,
615 BinaryUnchangedSharedKind::PerEpochConfigWithSequenceNumber { version } => {
616 Self::PerEpochConfigWithSequenceNumber { version }
617 }
618 })
619 }
620 }
621 }
622
623 #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
624 #[serde(tag = "state", rename_all = "snake_case")]
625 enum ReadableObjectIn {
626 NotExist,
627 Exist {
628 #[serde(with = "crate::_serde::ReadableDisplay")]
629 version: Version,
630 digest: ObjectDigest,
631 owner: Owner,
632 },
633 }
634
635 #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
636 enum BinaryObjectIn {
637 NotExist,
638 Exist {
639 version: Version,
640 digest: ObjectDigest,
641 owner: Owner,
642 },
643 }
644
645 impl Serialize for ObjectIn {
646 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
647 where
648 S: Serializer,
649 {
650 if serializer.is_human_readable() {
651 let readable = match self.clone() {
652 ObjectIn::NotExist => ReadableObjectIn::NotExist,
653 ObjectIn::Exist {
654 version,
655 digest,
656 owner,
657 } => ReadableObjectIn::Exist {
658 version,
659 digest,
660 owner,
661 },
662 };
663 readable.serialize(serializer)
664 } else {
665 let binary = match self.clone() {
666 ObjectIn::NotExist => BinaryObjectIn::NotExist,
667 ObjectIn::Exist {
668 version,
669 digest,
670 owner,
671 } => BinaryObjectIn::Exist {
672 version,
673 digest,
674 owner,
675 },
676 };
677 binary.serialize(serializer)
678 }
679 }
680 }
681
682 impl<'de> Deserialize<'de> for ObjectIn {
683 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
684 where
685 D: Deserializer<'de>,
686 {
687 if deserializer.is_human_readable() {
688 ReadableObjectIn::deserialize(deserializer).map(|readable| match readable {
689 ReadableObjectIn::NotExist => Self::NotExist,
690 ReadableObjectIn::Exist {
691 version,
692 digest,
693 owner,
694 } => Self::Exist {
695 version,
696 digest,
697 owner,
698 },
699 })
700 } else {
701 BinaryObjectIn::deserialize(deserializer).map(|binary| match binary {
702 BinaryObjectIn::NotExist => Self::NotExist,
703 BinaryObjectIn::Exist {
704 version,
705 digest,
706 owner,
707 } => Self::Exist {
708 version,
709 digest,
710 owner,
711 },
712 })
713 }
714 }
715 }
716
717 #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
718 #[serde(tag = "state", rename_all = "snake_case")]
719 enum ReadableObjectOut {
720 NotExist,
721 ObjectWrite {
722 digest: ObjectDigest,
723 owner: Owner,
724 },
725 PackageWrite {
726 #[serde(with = "crate::_serde::ReadableDisplay")]
727 version: Version,
728 digest: ObjectDigest,
729 },
730 }
731
732 #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
733 enum BinaryObjectOut {
734 NotExist,
735 ObjectWrite {
736 digest: ObjectDigest,
737 owner: Owner,
738 },
739 PackageWrite {
740 #[serde(with = "crate::_serde::ReadableDisplay")]
741 version: Version,
742 digest: ObjectDigest,
743 },
744 }
745
746 impl Serialize for ObjectOut {
747 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
748 where
749 S: Serializer,
750 {
751 if serializer.is_human_readable() {
752 let readable = match self.clone() {
753 ObjectOut::NotExist => ReadableObjectOut::NotExist,
754 ObjectOut::ObjectWrite { digest, owner } => {
755 ReadableObjectOut::ObjectWrite { digest, owner }
756 }
757 ObjectOut::PackageWrite { version, digest } => {
758 ReadableObjectOut::PackageWrite { version, digest }
759 }
760 };
761 readable.serialize(serializer)
762 } else {
763 let binary = match self.clone() {
764 ObjectOut::NotExist => BinaryObjectOut::NotExist,
765 ObjectOut::ObjectWrite { digest, owner } => {
766 BinaryObjectOut::ObjectWrite { digest, owner }
767 }
768 ObjectOut::PackageWrite { version, digest } => {
769 BinaryObjectOut::PackageWrite { version, digest }
770 }
771 };
772 binary.serialize(serializer)
773 }
774 }
775 }
776
777 impl<'de> Deserialize<'de> for ObjectOut {
778 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
779 where
780 D: Deserializer<'de>,
781 {
782 if deserializer.is_human_readable() {
783 ReadableObjectOut::deserialize(deserializer).map(|readable| match readable {
784 ReadableObjectOut::NotExist => Self::NotExist,
785 ReadableObjectOut::ObjectWrite { digest, owner } => {
786 Self::ObjectWrite { digest, owner }
787 }
788 ReadableObjectOut::PackageWrite { version, digest } => {
789 Self::PackageWrite { version, digest }
790 }
791 })
792 } else {
793 BinaryObjectOut::deserialize(deserializer).map(|binary| match binary {
794 BinaryObjectOut::NotExist => Self::NotExist,
795 BinaryObjectOut::ObjectWrite { digest, owner } => {
796 Self::ObjectWrite { digest, owner }
797 }
798 BinaryObjectOut::PackageWrite { version, digest } => {
799 Self::PackageWrite { version, digest }
800 }
801 })
802 }
803 }
804 }
805}