iota_types/effects/
test_effects_builder.rs1use std::collections::{BTreeMap, BTreeSet};
6
7use crate::{
8 base_types::{ObjectID, SequenceNumber},
9 digests::{ObjectDigest, TransactionEventsDigest},
10 effects::{EffectsObjectChange, IDOperation, ObjectIn, ObjectOut, TransactionEffects},
11 execution::SharedInput,
12 execution_status::ExecutionStatus,
13 gas::GasCostSummary,
14 message_envelope::Message,
15 object::Owner,
16 transaction::{InputObjectKind, SenderSignedData, TransactionDataAPI},
17};
18
19pub struct TestEffectsBuilder {
20 transaction: SenderSignedData,
21 status: Option<ExecutionStatus>,
23 shared_input_versions: BTreeMap<ObjectID, SequenceNumber>,
25 events_digest: Option<TransactionEventsDigest>,
26}
27
28impl TestEffectsBuilder {
29 pub fn new(transaction: &SenderSignedData) -> Self {
30 Self {
31 transaction: transaction.clone(),
32 status: None,
33 shared_input_versions: BTreeMap::new(),
34 events_digest: None,
35 }
36 }
37
38 pub fn with_status(mut self, status: ExecutionStatus) -> Self {
39 self.status = Some(status);
40 self
41 }
42
43 pub fn with_shared_input_versions(
44 mut self,
45 versions: BTreeMap<ObjectID, SequenceNumber>,
46 ) -> Self {
47 assert!(self.shared_input_versions.is_empty());
48 self.shared_input_versions = versions;
49 self
50 }
51
52 pub fn with_events_digest(mut self, digest: TransactionEventsDigest) -> Self {
53 self.events_digest = Some(digest);
54 self
55 }
56
57 pub fn build(self) -> TransactionEffects {
58 let status = self.status.unwrap_or(ExecutionStatus::Success);
59 let shared_objects = self
61 .shared_input_versions
62 .iter()
63 .map(|(id, version)| SharedInput::Existing((*id, *version, ObjectDigest::MIN)))
64 .collect();
65 let executed_epoch = 0;
66 let lamport_version = SequenceNumber::lamport_increment(
67 self.transaction
68 .transaction_data()
69 .input_objects()
70 .unwrap()
71 .iter()
72 .filter_map(|kind| kind.version())
73 .chain(
74 self.transaction
75 .transaction_data()
76 .receiving_objects()
77 .iter()
78 .map(|oref| oref.1),
79 )
80 .chain(self.shared_input_versions.values().copied()),
81 );
82 let sender = self.transaction.transaction_data().sender();
83 let changed_objects = self
85 .transaction
86 .transaction_data()
87 .input_objects()
88 .unwrap()
89 .iter()
90 .filter_map(|kind| match kind {
91 InputObjectKind::ImmOrOwnedMoveObject(oref) => {
92 Some((
93 oref.0,
94 EffectsObjectChange {
95 input_state: ObjectIn::Exist((
96 (oref.1, oref.2),
97 Owner::AddressOwner(sender),
98 )),
99 output_state: ObjectOut::ObjectWrite((
100 ObjectDigest::MAX,
102 Owner::AddressOwner(sender),
103 )),
104 id_operation: IDOperation::None,
105 },
106 ))
107 }
108 InputObjectKind::MovePackage(_) => None,
109 InputObjectKind::SharedMoveObject {
110 id,
111 initial_shared_version,
112 mutable,
113 } => mutable.then_some((
114 *id,
115 EffectsObjectChange {
116 input_state: ObjectIn::Exist((
117 (
118 *self
119 .shared_input_versions
120 .get(id)
121 .unwrap_or(initial_shared_version),
122 ObjectDigest::MIN,
123 ),
124 Owner::Shared {
125 initial_shared_version: *initial_shared_version,
126 },
127 )),
128 output_state: ObjectOut::ObjectWrite((
129 ObjectDigest::MAX,
131 Owner::Shared {
132 initial_shared_version: *initial_shared_version,
133 },
134 )),
135 id_operation: IDOperation::None,
136 },
137 )),
138 })
139 .collect();
140 let gas_object_id = self.transaction.transaction_data().gas()[0].0;
141 let event_digest = self.events_digest;
142 let dependencies = vec![];
143 TransactionEffects::new_from_execution_v1(
144 status,
145 executed_epoch,
146 GasCostSummary::default(),
147 shared_objects,
148 BTreeSet::new(),
149 self.transaction.digest(),
150 lamport_version,
151 changed_objects,
152 Some(gas_object_id),
153 event_digest,
154 dependencies,
155 )
156 }
157}