sui_move_natives_latest/object_runtime/
fingerprint.rs

1// Copyright (c) Mysten Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use move_binary_format::errors::{PartialVMError, PartialVMResult};
5use move_core_types::vm_status::StatusCode;
6use move_vm_types::values::Value;
7use sui_protocol_config::ProtocolConfig;
8use sui_types::base_types::{MoveObjectType, ObjectID};
9
10/// This type is used to track if an object has changed since it was read from storage. Ideally,
11/// this would just store the owner ID+type+BCS bytes of the object; however, due to pending
12/// rewrites in the adapter, that would be too much code churn. Instead, we use the `Value` since
13/// the `RuntimeResults` operate over `Value` and not BCS bytes.
14pub struct ObjectFingerprint(Option<ObjectFingerprint_>);
15
16enum ObjectFingerprint_ {
17    /// The object did not exist (as a child object) in storage at the start of the transaction.
18    Empty,
19    // The object was loaded as a child object from storage.
20    Preexisting {
21        owner: ObjectID,
22        ty: MoveObjectType,
23        value: Value,
24    },
25}
26
27impl ObjectFingerprint {
28    #[cfg(debug_assertions)]
29    pub fn is_disabled(&self) -> bool {
30        self.0.is_none()
31    }
32
33    /// Creates a new object fingerprint for a child object not found in storage.
34    /// Will be internally disabled if the feature is not enabled in the protocol config.
35    pub fn none(protocol_config: &ProtocolConfig) -> Self {
36        if !protocol_config.minimize_child_object_mutations() {
37            Self(None)
38        } else {
39            Self(Some(ObjectFingerprint_::Empty))
40        }
41    }
42
43    /// Creates a new object fingerprint for a child found in storage.
44    /// Will be internally disabled if the feature is not enabled in the protocol config.
45    pub fn preexisting(
46        protocol_config: &ProtocolConfig,
47        preexisting_owner: &ObjectID,
48        preexisting_type: &MoveObjectType,
49        preexisting_value: &Value,
50    ) -> PartialVMResult<Self> {
51        Ok(if !protocol_config.minimize_child_object_mutations() {
52            Self(None)
53        } else {
54            Self(Some(ObjectFingerprint_::Preexisting {
55                owner: *preexisting_owner,
56                ty: preexisting_type.clone(),
57                value: preexisting_value.copy_value()?,
58            }))
59        })
60    }
61
62    /// Checks if the object has changed since it was read from storage.
63    /// Gives an invariant violation if the fingerprint is disabled.
64    /// Gives an invariant violation if the values do not have the same layout, but the owner and
65    /// type are thesame.
66    pub fn object_has_changed(
67        &self,
68        final_owner: &ObjectID,
69        final_type: &MoveObjectType,
70        final_value: &Option<Value>,
71    ) -> PartialVMResult<bool> {
72        use ObjectFingerprint_ as F;
73        let Some(inner) = &self.0 else {
74            return Err(
75                PartialVMError::new(StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR).with_message(
76                    "Object fingerprint not enabled, yet we were asked for the changes".to_string(),
77                ),
78            );
79        };
80        Ok(match (inner, final_value) {
81            (F::Empty, None) => false,
82            (F::Empty, Some(_)) | (F::Preexisting { .. }, None) => true,
83            (
84                F::Preexisting {
85                    owner: preexisting_owner,
86                    ty: preexisting_type,
87                    value: preexisting_value,
88                },
89                Some(final_value),
90            ) => {
91                // owner changed or value changed.
92                // For the value, we must first check if the types are the same before comparing the
93                // values
94                !(preexisting_owner == final_owner
95                    && preexisting_type == final_type
96                    && preexisting_value.equals(final_value)?)
97            }
98        })
99    }
100}