sui_sdk_types/effects/
v2.rs

1use crate::Address;
2use crate::Digest;
3use crate::EpochId;
4use crate::GasCostSummary;
5use crate::TypeTag;
6use crate::execution_status::ExecutionStatus;
7use crate::object::Owner;
8use crate::object::Version;
9
10/// Version 2 of TransactionEffects
11///
12/// # BCS
13///
14/// The BCS serialized form for this type is defined by the following ABNF:
15///
16/// ```text
17/// effects-v2 = execution-status
18///              u64                                ; epoch
19///              gas-cost-summary
20///              digest                             ; transaction digest
21///              (option u32)                       ; gas object index
22///              (option digest)                    ; events digest
23///              (vector digest)                    ; list of transaction dependencies
24///              u64                                ; lamport version
25///              (vector changed-object)
26///              (vector unchanged-consensus-object)
27///              (option digest)                    ; auxiliary data digest
28/// ```
29#[derive(Eq, PartialEq, Clone, Debug)]
30#[cfg_attr(
31    feature = "serde",
32    derive(serde_derive::Serialize, serde_derive::Deserialize)
33)]
34#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
35pub struct TransactionEffectsV2 {
36    /// The status of the execution
37    pub status: ExecutionStatus,
38
39    /// The epoch when this transaction was executed.
40    pub epoch: EpochId,
41
42    /// The gas used by this transaction
43    pub gas_used: GasCostSummary,
44
45    /// The transaction digest
46    pub transaction_digest: Digest,
47
48    /// The updated gas object reference, as an index into the `changed_objects` vector.
49    /// Having a dedicated field for convenient access.
50    /// System transaction that don't require gas will leave this as None.
51    pub gas_object_index: Option<u32>,
52
53    /// The digest of the events emitted during execution,
54    /// can be None if the transaction does not emit any event.
55    pub events_digest: Option<Digest>,
56
57    /// The set of transaction digests this transaction depends on.
58    #[cfg_attr(feature = "proptest", any(proptest::collection::size_range(0..=5).lift()))]
59    pub dependencies: Vec<Digest>,
60
61    /// The version number of all the written Move objects by this transaction.
62    pub lamport_version: Version,
63
64    /// Objects whose state are changed in the object store.
65    #[cfg_attr(feature = "proptest", any(proptest::collection::size_range(0..=2).lift()))]
66    pub changed_objects: Vec<ChangedObject>,
67
68    /// Consensus objects that are not mutated in this transaction. Unlike owned objects,
69    /// read-only consensus objects' version are not committed in the transaction,
70    /// and in order for a node to catch up and execute it without consensus sequencing,
71    /// the version needs to be committed in the effects.
72    #[cfg_attr(feature = "proptest", any(proptest::collection::size_range(0..=2).lift()))]
73    pub unchanged_consensus_objects: Vec<UnchangedConsensusObject>,
74
75    /// Auxiliary data that are not protocol-critical, generated as part of the effects but are stored separately.
76    /// Storing it separately allows us to avoid bloating the effects with data that are not critical.
77    /// It also provides more flexibility on the format and type of the data.
78    pub auxiliary_data_digest: Option<Digest>,
79}
80
81/// Input/output state of an object that was changed during execution
82///
83/// # BCS
84///
85/// The BCS serialized form for this type is defined by the following ABNF:
86///
87/// ```text
88/// changed-object = address object-in object-out id-operation
89/// ```
90#[derive(Eq, PartialEq, Clone, Debug)]
91#[cfg_attr(
92    feature = "serde",
93    derive(serde_derive::Serialize, serde_derive::Deserialize)
94)]
95#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
96pub struct ChangedObject {
97    /// Id of the object
98    pub object_id: Address,
99
100    /// State of the object in the store prior to this transaction.
101    pub input_state: ObjectIn,
102
103    /// State of the object in the store after this transaction.
104    pub output_state: ObjectOut,
105
106    /// Whether this object ID is created or deleted in this transaction.
107    /// This information isn't required by the protocol but is useful for providing more detailed
108    /// semantics on object changes.
109    pub id_operation: IdOperation,
110}
111
112/// A Consensus object that wasn't changed during execution
113///
114/// # BCS
115///
116/// The BCS serialized form for this type is defined by the following ABNF:
117///
118/// ```text
119/// unchanged-consensus-object = address unchanged-consensus-object-kind
120/// ```
121#[derive(Eq, PartialEq, Clone, Debug)]
122#[cfg_attr(
123    feature = "serde",
124    derive(serde_derive::Serialize, serde_derive::Deserialize)
125)]
126#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
127pub struct UnchangedConsensusObject {
128    pub object_id: Address,
129    pub kind: UnchangedConsensusKind,
130}
131
132/// Type of unchanged consensus object
133///
134/// # BCS
135///
136/// The BCS serialized form for this type is defined by the following ABNF:
137///
138/// ```text
139/// unchanged-consensus-object-kind =  read-only-root
140///                                 =/ mutate-deleted
141///                                 =/ read-deleted
142///                                 =/ canceled
143///                                 =/ per-epoch-config
144///
145/// read-only-root                           = %x00 u64 digest
146/// mutate-deleted                           = %x01 u64
147/// read-deleted                             = %x02 u64
148/// canceled                                 = %x03 u64
149/// per-epoch-config                         = %x04
150/// per-epoch-config-with-sequence-number    = %x05 u64
151/// ```
152#[derive(Eq, PartialEq, Clone, Debug)]
153#[cfg_attr(
154    feature = "serde",
155    derive(serde_derive::Serialize, serde_derive::Deserialize)
156)]
157#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
158#[non_exhaustive]
159pub enum UnchangedConsensusKind {
160    /// Read-only consensus objects from the input. We don't really need ObjectDigest
161    /// for protocol correctness, but it will make it easier to verify untrusted read.
162    ReadOnlyRoot { version: Version, digest: Digest },
163
164    /// Deleted consensus objects that appear mutably/owned in the input.
165    MutateDeleted { version: Version },
166
167    /// Deleted consensus objects that appear as read-only in the input.
168    ReadDeleted { version: Version },
169
170    /// Consensus objects in canceled transaction. The sequence number embed cancellation reason.
171    Canceled { version: Version },
172
173    /// Read of a per-epoch config object that should remain the same during an epoch.
174    PerEpochConfig,
175}
176
177/// State of an object prior to execution
178///
179/// If an object exists (at root-level) in the store prior to this transaction,
180/// it should be Exist, otherwise it's NonExist, e.g. wrapped objects should be
181/// NonExist.
182///
183/// # BCS
184///
185/// The BCS serialized form for this type is defined by the following ABNF:
186///
187/// ```text
188/// object-in = object-in-not-exist / object-in-exist
189///
190/// object-in-not-exist = %x00
191/// object-in-exist     = %x01 u64 digest owner
192/// ```
193#[derive(Eq, PartialEq, Clone, Debug)]
194#[cfg_attr(
195    feature = "serde",
196    derive(serde_derive::Serialize, serde_derive::Deserialize)
197)]
198#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
199#[non_exhaustive]
200pub enum ObjectIn {
201    NotExist,
202
203    /// The old version, digest and owner.
204    Exist {
205        version: Version,
206        digest: Digest,
207        owner: Owner,
208    },
209}
210
211/// State of an object after execution
212///
213/// # BCS
214///
215/// The BCS serialized form for this type is defined by the following ABNF:
216///
217/// ```text
218/// object-out  =  object-out-not-exist
219///             =/ object-out-object-write
220///             =/ object-out-package-write
221///
222///
223/// object-out-not-exist        = %x00
224/// object-out-object-write     = %x01 digest owner
225/// object-out-package-write    = %x02 version digest
226/// ```
227#[derive(Eq, PartialEq, Clone, Debug)]
228#[cfg_attr(
229    feature = "serde",
230    derive(serde_derive::Serialize, serde_derive::Deserialize)
231)]
232#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
233#[non_exhaustive]
234pub enum ObjectOut {
235    /// Same definition as in ObjectIn.
236    NotExist,
237
238    /// Any written object, including all of mutated, created, unwrapped today.
239    ObjectWrite { digest: Digest, owner: Owner },
240
241    /// Packages writes need to be tracked separately with version because
242    /// we don't use lamport version for package publish and upgrades.
243    PackageWrite { version: Version, digest: Digest },
244
245    /// This isn't an object write, but a special write to an accumulator.
246    AccumulatorWrite(AccumulatorWrite),
247}
248
249#[derive(Eq, PartialEq, Clone, Debug)]
250#[cfg_attr(
251    feature = "serde",
252    derive(serde_derive::Serialize, serde_derive::Deserialize)
253)]
254#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
255pub struct AccumulatorWrite {
256    /// Accumulator objects are named by an address (can be an account address or a UID)
257    /// and a type tag.
258    address: Address,
259    type_: TypeTag,
260
261    /// The operation to be applied to the accumulator.
262    operation: AccumulatorOperation,
263    /// The value to be merged into or split from the accumulator.
264    value: AccumulatorValue,
265}
266
267impl AccumulatorWrite {
268    pub fn new(
269        address: Address,
270        type_: TypeTag,
271        operation: AccumulatorOperation,
272        value: u64,
273    ) -> Self {
274        Self {
275            address,
276            type_,
277            operation,
278            value: AccumulatorValue::Integer(value),
279        }
280    }
281
282    pub fn address(&self) -> &Address {
283        &self.address
284    }
285
286    pub fn accumulator_type(&self) -> &TypeTag {
287        &self.type_
288    }
289
290    pub fn operation(&self) -> AccumulatorOperation {
291        self.operation
292    }
293
294    pub fn value(&self) -> u64 {
295        match self.value {
296            AccumulatorValue::Integer(value) => value,
297        }
298    }
299}
300
301#[derive(Eq, PartialEq, Clone, Copy, Debug)]
302#[cfg_attr(
303    feature = "serde",
304    derive(serde_derive::Serialize, serde_derive::Deserialize)
305)]
306#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
307#[non_exhaustive]
308pub enum AccumulatorOperation {
309    /// Merge the value into the accumulator.
310    Merge,
311    /// Split the value from the accumulator.
312    Split,
313}
314
315#[derive(Eq, PartialEq, Clone, Debug)]
316#[cfg_attr(
317    feature = "serde",
318    derive(serde_derive::Serialize, serde_derive::Deserialize)
319)]
320#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
321#[non_exhaustive]
322enum AccumulatorValue {
323    Integer(u64),
324}
325
326/// Defines what happened to an ObjectId during execution
327///
328/// # BCS
329///
330/// The BCS serialized form for this type is defined by the following ABNF:
331///
332/// ```text
333/// id-operation =  id-operation-none
334///              =/ id-operation-created
335///              =/ id-operation-deleted
336///
337/// id-operation-none       = %x00
338/// id-operation-created    = %x01
339/// id-operation-deleted    = %x02
340/// ```
341#[derive(Eq, PartialEq, Copy, Clone, Debug)]
342#[cfg_attr(
343    feature = "serde",
344    derive(serde_derive::Serialize, serde_derive::Deserialize)
345)]
346#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
347#[non_exhaustive]
348pub enum IdOperation {
349    None,
350    Created,
351    Deleted,
352}
353
354impl TransactionEffectsV2 {
355    /// The status of the execution
356    pub fn status(&self) -> &ExecutionStatus {
357        &self.status
358    }
359
360    /// The epoch when this transaction was executed.
361    pub fn epoch(&self) -> EpochId {
362        self.epoch
363    }
364
365    /// The gas used in this transaction.
366    pub fn gas_summary(&self) -> &GasCostSummary {
367        &self.gas_used
368    }
369}