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}