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