iota_core/
transaction_outputs.rs1use std::{
6 collections::{HashMap, HashSet},
7 sync::Arc,
8};
9
10use iota_types::{
11 base_types::ObjectRef,
12 effects::{TransactionEffects, TransactionEffectsAPI, TransactionEvents},
13 inner_temporary_store::{InnerTemporaryStore, WrittenObjects},
14 storage::{MarkerValue, ObjectKey},
15 transaction::{TransactionDataAPI, VerifiedTransaction},
16};
17
18pub struct TransactionOutputs {
20 pub transaction: Arc<VerifiedTransaction>,
21 pub effects: TransactionEffects,
22 pub events: TransactionEvents,
23
24 pub markers: Vec<(ObjectKey, MarkerValue)>,
25 pub wrapped: Vec<ObjectKey>,
26 pub deleted: Vec<ObjectKey>,
27 pub live_object_markers_to_delete: Vec<ObjectRef>,
28 pub new_live_object_markers_to_init: Vec<ObjectRef>,
29 pub written: WrittenObjects,
30}
31
32impl TransactionOutputs {
33 pub fn build_transaction_outputs(
36 transaction: VerifiedTransaction,
37 effects: TransactionEffects,
38 inner_temporary_store: InnerTemporaryStore,
39 ) -> TransactionOutputs {
40 let InnerTemporaryStore {
41 input_objects,
42 mutable_inputs,
43 written,
44 events,
45 loaded_runtime_objects: _,
46 binary_config: _,
47 runtime_packages_loaded_from_db: _,
48 lamport_version,
49 } = inner_temporary_store;
50
51 let tx_digest = *transaction.digest();
52
53 let deleted: HashMap<_, _> = effects.all_tombstones().into_iter().collect();
54
55 let modified_at: HashSet<_> = effects.modified_at_versions().into_iter().collect();
58 let possible_to_receive = transaction.transaction_data().receiving_objects();
59 let received_objects = possible_to_receive
60 .iter()
61 .cloned()
62 .filter(|obj_ref| modified_at.contains(&(obj_ref.0, obj_ref.1)));
63
64 let markers: Vec<_> = {
69 let received = received_objects
70 .clone()
71 .map(|objref| (ObjectKey::from(objref), MarkerValue::Received));
72
73 let deleted = deleted.into_iter().map(|(object_id, version)| {
74 let object_key = ObjectKey(object_id, version);
75 if input_objects
76 .get(&object_id)
77 .is_some_and(|object| object.is_shared())
78 {
79 (object_key, MarkerValue::SharedDeleted(tx_digest))
80 } else {
81 (object_key, MarkerValue::OwnedDeleted)
82 }
83 });
84
85 let smeared_objects = effects.deleted_mutably_accessed_shared_objects();
90 let shared_smears = smeared_objects.into_iter().map(move |object_id| {
91 (
92 ObjectKey(object_id, lamport_version),
93 MarkerValue::SharedDeleted(tx_digest),
94 )
95 });
96
97 received.chain(deleted).chain(shared_smears).collect()
98 };
99
100 let live_object_markers_to_delete: Vec<_> = mutable_inputs
101 .into_iter()
102 .filter_map(|(id, ((version, digest), owner))| {
103 owner.is_address_owned().then_some((id, version, digest))
104 })
105 .chain(received_objects)
106 .collect();
107
108 let new_live_object_markers_to_init: Vec<_> = written
109 .values()
110 .filter_map(|new_object| {
111 if new_object.is_address_owned() {
112 Some(new_object.compute_object_reference())
113 } else {
114 None
115 }
116 })
117 .collect();
118
119 let deleted = effects
120 .deleted()
121 .into_iter()
122 .chain(effects.unwrapped_then_deleted())
123 .map(ObjectKey::from)
124 .collect();
125
126 let wrapped = effects.wrapped().into_iter().map(ObjectKey::from).collect();
127
128 TransactionOutputs {
129 transaction: Arc::new(transaction),
130 effects,
131 events,
132 markers,
133 wrapped,
134 deleted,
135 live_object_markers_to_delete,
136 new_live_object_markers_to_init,
137 written,
138 }
139 }
140}