iota_types/effects/
test_effects_builder.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5use 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    /// Override the execution status if provided.
22    status: Option<ExecutionStatus>,
23    /// Provide the assigned versions for all shared objects.
24    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        // TODO: This does not yet support deleted shared objects.
60        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        // TODO: Include receiving objects in the object changes as well.
84        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                                // Digest must change with a mutation.
101                                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                            // Digest must change with a mutation.
130                            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}