pub struct AccountDelta { /* private fields */ }Expand description
The AccountDelta stores the differences between two account states, which can result from
one or more transaction.
The differences are represented as follows:
- storage: an
AccountStorageDeltathat contains the changes to the account storage. - vault: an
AccountVaultDeltaobject that contains the changes to the account vault. - nonce: if the nonce of the account has changed, the delta of the nonce is stored, i.e. the value by which the nonce increased.
- code: an
AccountCodefor new accounts andNonefor others.
The presence of the code in a delta signals if the delta is a full state or partial state
delta. A full state delta must be converted into an Account object, while a partial state
delta must be applied to an existing Account.
TODO(code_upgrades): The ability to track account code updates is an outstanding feature. For that reason, the account code is not considered as part of the “nonce must be incremented if state changed” check.
Implementations§
Source§impl AccountDelta
impl AccountDelta
Sourcepub fn new(
account_id: AccountId,
storage: AccountStorageDelta,
vault: AccountVaultDelta,
nonce_delta: Felt,
) -> Result<Self, AccountDeltaError>
pub fn new( account_id: AccountId, storage: AccountStorageDelta, vault: AccountVaultDelta, nonce_delta: Felt, ) -> Result<Self, AccountDeltaError>
Returns new AccountDelta instantiated from the provided components.
§Errors
- Returns an error if storage or vault were updated, but the nonce_delta is 0.
Sourcepub fn merge(&mut self, other: Self) -> Result<(), AccountDeltaError>
pub fn merge(&mut self, other: Self) -> Result<(), AccountDeltaError>
Merge another AccountDelta into this one.
Sourcepub fn vault_mut(&mut self) -> &mut AccountVaultDelta
pub fn vault_mut(&mut self) -> &mut AccountVaultDelta
Returns a mutable reference to the account vault delta.
Sourcepub fn with_code(self, code: Option<AccountCode>) -> Self
pub fn with_code(self, code: Option<AccountCode>) -> Self
Sets the AccountCode of the delta.
Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Returns true if this account delta does not contain any vault, storage or nonce updates.
Sourcepub fn is_full_state(&self) -> bool
pub fn is_full_state(&self) -> bool
Returns true if this delta is a “full state” delta, false otherwise, i.e. if it is a
“partial state” delta.
See the type-level docs for more on this distinction.
Sourcepub fn storage(&self) -> &AccountStorageDelta
pub fn storage(&self) -> &AccountStorageDelta
Returns storage updates for this account delta.
Sourcepub fn vault(&self) -> &AccountVaultDelta
pub fn vault(&self) -> &AccountVaultDelta
Returns vault updates for this account delta.
Sourcepub fn nonce_delta(&self) -> Felt
pub fn nonce_delta(&self) -> Felt
Returns the amount by which the nonce was incremented.
Sourcepub fn code(&self) -> Option<&AccountCode>
pub fn code(&self) -> Option<&AccountCode>
Returns a reference to the account code of this delta, if present.
Sourcepub fn into_parts(
self,
) -> (AccountStorageDelta, AccountVaultDelta, Option<AccountCode>, Felt)
pub fn into_parts( self, ) -> (AccountStorageDelta, AccountVaultDelta, Option<AccountCode>, Felt)
Converts this storage delta into individual delta components.
Sourcepub fn to_commitment(&self) -> Word
pub fn to_commitment(&self) -> Word
Computes the commitment to the account delta.
§Computation
The delta is a sequential hash over a vector of field elements which starts out empty and
is appended to in the following way. Whenever sorting is expected, it is that of a
LexicographicWord. The WORD layout is in memory-order.
- Append
[[nonce_delta, 0, account_id_suffix, account_id_prefix], EMPTY_WORD], where account_id_{prefix,suffix} are the prefix and suffix felts of the native account id and nonce_delta is the value by which the nonce was incremented. - Fungible Asset Delta
- For each updated fungible asset, sorted by its vault key, whose amount delta is
non-zero:
- Append
[domain = 1, was_added, 0, 0]. - Append
[amount, 0, faucet_id_suffix, faucet_id_prefix]where amount is the delta by which the fungible asset’s amount has changed and was_added is a boolean flag indicating whether the amount was added (1) or subtracted (0).
- Append
- For each updated fungible asset, sorted by its vault key, whose amount delta is
non-zero:
- Non-Fungible Asset Delta
- For each updated non-fungible asset, sorted by its vault key:
- Append
[domain = 1, was_added, 0, 0]where was_added is a boolean flag indicating whether the asset was added (1) or removed (0). Note that the domain is the same for assets sincefaucet_id_prefixis at the same position in the layout for both assets, and, by design, it is never the same for fungible and non-fungible assets. - Append
[hash0, hash1, hash2, faucet_id_prefix], i.e. the non-fungible asset.
- Append
- For each updated non-fungible asset, sorted by its vault key:
- Storage Slots are sorted by slot ID and are iterated in this order. For each slot whose
value has changed, depending on the slot type:
- Value Slot
- Append
[[domain = 2, 0, slot_id_suffix, slot_id_prefix], NEW_VALUE]whereNEW_VALUEis the new value of the slot andslot_id_{suffix, prefix}is the identifier of the slot.
- Append
- Map Slot
- For each key-value pair, sorted by key, whose new value is different from the previous
value in the map:
- Append
[KEY, NEW_VALUE].
- Append
- Append
[[domain = 3, num_changed_entries, slot_id_suffix, slot_id_prefix], 0, 0, 0, 0], whereslot_id_{suffix, prefix}are the slot identifiers andnum_changed_entriesis the number of changed key-value pairs in the map.- For partial state deltas, the map header must only be included if
num_changed_entriesis not zero. - For full state deltas, the map header must always be included.
- For partial state deltas, the map header must only be included if
- For each key-value pair, sorted by key, whose new value is different from the previous
value in the map:
- Value Slot
§Rationale
The rationale for this layout is that hashing in the VM should be as efficient as possible and minimize the number of branches to be as efficient as possible. Every high-level section in this bullet point list should add an even number of words since the hasher operates on double words. In the VM, each permutation is done immediately, so adding an uneven number of words in a given step will result in more difficulty in the MASM implementation.
§New Accounts
The delta for new accounts (a full state delta) must commit to all the storage slots of the account, even if the storage slots have a default value (e.g. the empty word for value slots or an empty storage map). This ensures the full state delta commits to the exact storage slots that are contained in the account.
§Security
The general concern with the commitment is that two distinct deltas must never hash to the same commitment. E.g. a commitment of a delta that changes a key-value pair in a storage map slot should be different from a delta that adds a non-fungible asset to the vault. If not, a delta can be crafted in the VM that sets a map key but a malicious actor crafts a delta outside the VM that adds a non-fungible asset. To prevent that, a couple of measures are taken.
- Because multiple unrelated contexts (e.g. vaults and storage slots) are hashed in the same hasher, domain separators are used to disambiguate. For each changed asset and each changed slot in the delta, a domain separator is hashed into the delta. The domain separator is always at the same index in each layout so it cannot be maliciously crafted (see below for an example).
- Storage value slots:
- since only changed value slots are included in the delta, there is no ambiguity between a value slot being set to EMPTY_WORD and its value being unchanged.
- Storage map slots:
- Map slots append a header which summarizes the changes in the slot, in particular the slot ID and number of changed entries.
- Two distinct storage map slots use the same domain but are disambiguated due to inclusion of the slot ID.
§Domain Separators
As an example for ambiguity, consider these two deltas:
[
ID_AND_NONCE, EMPTY_WORD,
[/* no fungible asset delta */],
[[domain = 1, was_added = 0, 0, 0], NON_FUNGIBLE_ASSET],
[/* no storage delta */]
][
ID_AND_NONCE, EMPTY_WORD,
[/* no fungible asset delta */],
[/* no non-fungible asset delta */],
[[domain = 2, 0, slot_id_suffix = 0, slot_id_prefix = 0], NEW_VALUE]
]NEW_VALUE is user-controllable so it can be crafted to match NON_FUNGIBLE_ASSET. The
domain separator is then the only value that differentiates these two deltas. This shows the
importance of placing the domain separators in the same index within each word’s layout
which makes it easy to see that this value cannot be crafted to be the same.
§Number of Changed Entries
As an example for ambiguity, consider these two deltas:
[
ID_AND_NONCE, EMPTY_WORD,
[/* no fungible asset delta */],
[/* no non-fungible asset delta */],
[domain = 3, num_changed_entries = 0, slot_id_suffix = 20, slot_id_prefix = 21, 0, 0, 0, 0]
[domain = 3, num_changed_entries = 0, slot_id_suffix = 42, slot_id_prefix = 43, 0, 0, 0, 0]
][
ID_AND_NONCE, EMPTY_WORD,
[/* no fungible asset delta */],
[/* no non-fungible asset delta */],
[KEY0, VALUE0],
[domain = 3, num_changed_entries = 1, slot_id_suffix = 42, slot_id_prefix = 43, 0, 0, 0, 0]
]The keys and values of map slots are user-controllable so KEY0 and VALUE0 could be
crafted to match the first map header in the first delta. So, without having
num_changed_entries included in the commitment, these deltas would be ambiguous. A delta
with two empty maps could have the same commitment as a delta with one map entry where one
key-value pair has changed.
§New Accounts
The number of changed entries of a storage map can be validly zero when an empty storage map is added to a new account. In such cases, the number of changed key-value pairs is 0, but the map must still be committed to, in order to differentiate between a slot being an empty map or not being present at all.
Trait Implementations§
Source§impl Clone for AccountDelta
impl Clone for AccountDelta
Source§fn clone(&self) -> AccountDelta
fn clone(&self) -> AccountDelta
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for AccountDelta
impl Debug for AccountDelta
Source§impl Deserializable for AccountDelta
impl Deserializable for AccountDelta
Source§fn read_from<R: ByteReader>(
source: &mut R,
) -> Result<Self, DeserializationError>
fn read_from<R: ByteReader>( source: &mut R, ) -> Result<Self, DeserializationError>
source, attempts to deserialize these bytes
into Self, and returns the result. Read moreSource§fn read_from_bytes(bytes: &[u8]) -> Result<Self, DeserializationError>
fn read_from_bytes(bytes: &[u8]) -> Result<Self, DeserializationError>
Source§impl PartialEq for AccountDelta
impl PartialEq for AccountDelta
Source§impl SequentialCommit for AccountDelta
impl SequentialCommit for AccountDelta
Source§fn to_elements(&self) -> Vec<Felt>
fn to_elements(&self) -> Vec<Felt>
Reduces the delta to a sequence of field elements.
See AccountDelta::to_commitment() for more details.
Source§type Commitment = Word
type Commitment = Word
Source§fn to_commitment(&self) -> Self::Commitment
fn to_commitment(&self) -> Self::Commitment
Source§impl Serializable for AccountDelta
impl Serializable for AccountDelta
Source§fn write_into<W: ByteWriter>(&self, target: &mut W)
fn write_into<W: ByteWriter>(&self, target: &mut W)
self into bytes and writes these bytes into the target.Source§fn get_size_hint(&self) -> usize
fn get_size_hint(&self) -> usize
Source§impl TryFrom<&AccountDelta> for Account
impl TryFrom<&AccountDelta> for Account
Source§fn try_from(delta: &AccountDelta) -> Result<Self, Self::Error>
fn try_from(delta: &AccountDelta) -> Result<Self, Self::Error>
Converts an AccountDelta into an Account.
Conceptually, this applies the delta onto an empty account.
§Errors
Returns an error if:
- If the delta is not a full state delta. See
AccountDeltafor details. - If any vault delta operation removes an asset.
- If any vault delta operation adds an asset that would overflow the maximum representable amount.
- If any storage delta update violates account storage constraints.
Source§type Error = AccountError
type Error = AccountError
Source§impl TryFrom<Account> for AccountDelta
impl TryFrom<Account> for AccountDelta
Source§fn try_from(account: Account) -> Result<Self, Self::Error>
fn try_from(account: Account) -> Result<Self, Self::Error>
Converts an Account into an AccountDelta.
§Errors
Returns an error if:
- the account has a seed. Accounts with seeds have a nonce of 0. Representing such accounts as deltas is not possible because deltas with a non-empty state change need a nonce_delta greater than 0.
Source§type Error = AccountError
type Error = AccountError
impl Eq for AccountDelta
impl StructuralPartialEq for AccountDelta
Auto Trait Implementations§
impl Freeze for AccountDelta
impl RefUnwindSafe for AccountDelta
impl Send for AccountDelta
impl Sync for AccountDelta
impl Unpin for AccountDelta
impl UnwindSafe for AccountDelta
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<D> OwoColorize for D
impl<D> OwoColorize for D
Source§fn fg<C>(&self) -> FgColorDisplay<'_, C, Self>where
C: Color,
fn fg<C>(&self) -> FgColorDisplay<'_, C, Self>where
C: Color,
Source§fn bg<C>(&self) -> BgColorDisplay<'_, C, Self>where
C: Color,
fn bg<C>(&self) -> BgColorDisplay<'_, C, Self>where
C: Color,
Source§fn black(&self) -> FgColorDisplay<'_, Black, Self>
fn black(&self) -> FgColorDisplay<'_, Black, Self>
Source§fn on_black(&self) -> BgColorDisplay<'_, Black, Self>
fn on_black(&self) -> BgColorDisplay<'_, Black, Self>
Source§fn red(&self) -> FgColorDisplay<'_, Red, Self>
fn red(&self) -> FgColorDisplay<'_, Red, Self>
Source§fn on_red(&self) -> BgColorDisplay<'_, Red, Self>
fn on_red(&self) -> BgColorDisplay<'_, Red, Self>
Source§fn green(&self) -> FgColorDisplay<'_, Green, Self>
fn green(&self) -> FgColorDisplay<'_, Green, Self>
Source§fn on_green(&self) -> BgColorDisplay<'_, Green, Self>
fn on_green(&self) -> BgColorDisplay<'_, Green, Self>
Source§fn yellow(&self) -> FgColorDisplay<'_, Yellow, Self>
fn yellow(&self) -> FgColorDisplay<'_, Yellow, Self>
Source§fn on_yellow(&self) -> BgColorDisplay<'_, Yellow, Self>
fn on_yellow(&self) -> BgColorDisplay<'_, Yellow, Self>
Source§fn blue(&self) -> FgColorDisplay<'_, Blue, Self>
fn blue(&self) -> FgColorDisplay<'_, Blue, Self>
Source§fn on_blue(&self) -> BgColorDisplay<'_, Blue, Self>
fn on_blue(&self) -> BgColorDisplay<'_, Blue, Self>
Source§fn magenta(&self) -> FgColorDisplay<'_, Magenta, Self>
fn magenta(&self) -> FgColorDisplay<'_, Magenta, Self>
Source§fn on_magenta(&self) -> BgColorDisplay<'_, Magenta, Self>
fn on_magenta(&self) -> BgColorDisplay<'_, Magenta, Self>
Source§fn purple(&self) -> FgColorDisplay<'_, Magenta, Self>
fn purple(&self) -> FgColorDisplay<'_, Magenta, Self>
Source§fn on_purple(&self) -> BgColorDisplay<'_, Magenta, Self>
fn on_purple(&self) -> BgColorDisplay<'_, Magenta, Self>
Source§fn cyan(&self) -> FgColorDisplay<'_, Cyan, Self>
fn cyan(&self) -> FgColorDisplay<'_, Cyan, Self>
Source§fn on_cyan(&self) -> BgColorDisplay<'_, Cyan, Self>
fn on_cyan(&self) -> BgColorDisplay<'_, Cyan, Self>
Source§fn white(&self) -> FgColorDisplay<'_, White, Self>
fn white(&self) -> FgColorDisplay<'_, White, Self>
Source§fn on_white(&self) -> BgColorDisplay<'_, White, Self>
fn on_white(&self) -> BgColorDisplay<'_, White, Self>
Source§fn default_color(&self) -> FgColorDisplay<'_, Default, Self>
fn default_color(&self) -> FgColorDisplay<'_, Default, Self>
Source§fn on_default_color(&self) -> BgColorDisplay<'_, Default, Self>
fn on_default_color(&self) -> BgColorDisplay<'_, Default, Self>
Source§fn bright_black(&self) -> FgColorDisplay<'_, BrightBlack, Self>
fn bright_black(&self) -> FgColorDisplay<'_, BrightBlack, Self>
Source§fn on_bright_black(&self) -> BgColorDisplay<'_, BrightBlack, Self>
fn on_bright_black(&self) -> BgColorDisplay<'_, BrightBlack, Self>
Source§fn bright_red(&self) -> FgColorDisplay<'_, BrightRed, Self>
fn bright_red(&self) -> FgColorDisplay<'_, BrightRed, Self>
Source§fn on_bright_red(&self) -> BgColorDisplay<'_, BrightRed, Self>
fn on_bright_red(&self) -> BgColorDisplay<'_, BrightRed, Self>
Source§fn bright_green(&self) -> FgColorDisplay<'_, BrightGreen, Self>
fn bright_green(&self) -> FgColorDisplay<'_, BrightGreen, Self>
Source§fn on_bright_green(&self) -> BgColorDisplay<'_, BrightGreen, Self>
fn on_bright_green(&self) -> BgColorDisplay<'_, BrightGreen, Self>
Source§fn bright_yellow(&self) -> FgColorDisplay<'_, BrightYellow, Self>
fn bright_yellow(&self) -> FgColorDisplay<'_, BrightYellow, Self>
Source§fn on_bright_yellow(&self) -> BgColorDisplay<'_, BrightYellow, Self>
fn on_bright_yellow(&self) -> BgColorDisplay<'_, BrightYellow, Self>
Source§fn bright_blue(&self) -> FgColorDisplay<'_, BrightBlue, Self>
fn bright_blue(&self) -> FgColorDisplay<'_, BrightBlue, Self>
Source§fn on_bright_blue(&self) -> BgColorDisplay<'_, BrightBlue, Self>
fn on_bright_blue(&self) -> BgColorDisplay<'_, BrightBlue, Self>
Source§fn bright_magenta(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
fn bright_magenta(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
Source§fn on_bright_magenta(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
fn on_bright_magenta(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
Source§fn bright_purple(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
fn bright_purple(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
Source§fn on_bright_purple(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
fn on_bright_purple(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
Source§fn bright_cyan(&self) -> FgColorDisplay<'_, BrightCyan, Self>
fn bright_cyan(&self) -> FgColorDisplay<'_, BrightCyan, Self>
Source§fn on_bright_cyan(&self) -> BgColorDisplay<'_, BrightCyan, Self>
fn on_bright_cyan(&self) -> BgColorDisplay<'_, BrightCyan, Self>
Source§fn bright_white(&self) -> FgColorDisplay<'_, BrightWhite, Self>
fn bright_white(&self) -> FgColorDisplay<'_, BrightWhite, Self>
Source§fn on_bright_white(&self) -> BgColorDisplay<'_, BrightWhite, Self>
fn on_bright_white(&self) -> BgColorDisplay<'_, BrightWhite, Self>
Source§fn bold(&self) -> BoldDisplay<'_, Self>
fn bold(&self) -> BoldDisplay<'_, Self>
Source§fn dimmed(&self) -> DimDisplay<'_, Self>
fn dimmed(&self) -> DimDisplay<'_, Self>
Source§fn italic(&self) -> ItalicDisplay<'_, Self>
fn italic(&self) -> ItalicDisplay<'_, Self>
Source§fn underline(&self) -> UnderlineDisplay<'_, Self>
fn underline(&self) -> UnderlineDisplay<'_, Self>
Source§fn blink(&self) -> BlinkDisplay<'_, Self>
fn blink(&self) -> BlinkDisplay<'_, Self>
Source§fn blink_fast(&self) -> BlinkFastDisplay<'_, Self>
fn blink_fast(&self) -> BlinkFastDisplay<'_, Self>
Source§fn reversed(&self) -> ReversedDisplay<'_, Self>
fn reversed(&self) -> ReversedDisplay<'_, Self>
Source§fn strikethrough(&self) -> StrikeThroughDisplay<'_, Self>
fn strikethrough(&self) -> StrikeThroughDisplay<'_, Self>
Source§fn color<Color>(&self, color: Color) -> FgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
fn color<Color>(&self, color: Color) -> FgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
OwoColorize::fg or
a color-specific method, such as OwoColorize::green, Read moreSource§fn on_color<Color>(&self, color: Color) -> BgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
fn on_color<Color>(&self, color: Color) -> BgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
OwoColorize::bg or
a color-specific method, such as OwoColorize::on_yellow, Read more