Skip to main content

miden_objects/decoded/account/
patch.rs

1use miden_protobuf::unwrap_infallible;
2pub use proto::account::DecodedAccountVaultPatchEntry as AccountVaultPatchEntry;
3
4use crate::decoded::VerificationError;
5use crate::{Verify, proto};
6
7#[cfg(test)]
8mod tests;
9
10impl Verify for AccountVaultPatchEntry {
11    type Verified = (miden_protocol::asset::AssetId, miden_protocol::Word);
12    type Error = miden_protocol::errors::AssetError;
13    fn verify(self) -> Result<Self::Verified, Self::Error> {
14        Ok((self.asset_id.try_into()?, self.value))
15    }
16}
17
18pub use proto::account::DecodedAccountVaultPatch as AccountVaultPatch;
19
20impl Verify for AccountVaultPatch {
21    type Verified = miden_protocol::account::AccountVaultPatch;
22    type Error = VerificationError;
23    fn verify(self) -> Result<Self::Verified, Self::Error> {
24        let mut entries = alloc::collections::BTreeMap::new();
25        for entry in self.entries.into_inner() {
26            let (id, value) = entry.verify()?;
27            if entries.insert(id, value).is_some() {
28                return Err(VaultPatchError::DuplicateAssetId(id).into());
29            }
30        }
31        Ok(Self::Verified::new(entries)?)
32    }
33}
34
35#[derive(Debug, thiserror::Error)]
36pub enum VaultPatchError {
37    #[error("duplicate vault asset ID {0}")]
38    DuplicateAssetId(miden_protocol::asset::AssetId),
39}
40
41pub use proto::account::DecodedPrivateAccountUpdate as PrivateAccountUpdate;
42
43impl Verify for PrivateAccountUpdate {
44    type Verified = miden_protocol::account::AccountUpdateDetails;
45    type Error = core::convert::Infallible;
46    fn verify(self) -> Result<Self::Verified, Self::Error> {
47        Ok(Self::Verified::Private)
48    }
49}
50
51pub use proto::account::DecodedStorageMapPatchEntries as StorageMapPatchEntries;
52
53impl Verify for StorageMapPatchEntries {
54    type Verified = miden_protocol::account::StorageMapPatchEntries;
55    type Error = StorageMapPatchError;
56    fn verify(self) -> Result<Self::Verified, Self::Error> {
57        let mut entries = alloc::collections::BTreeMap::new();
58        for entry in self.entries.into_inner() {
59            let (key, value) = unwrap_infallible(entry.verify());
60            if entries.insert(key, value).is_some() {
61                return Err(StorageMapPatchError::DuplicateKey(key));
62            }
63        }
64        Ok(Self::Verified::from_raw(entries))
65    }
66}
67
68pub use proto::account::DecodedStorageMapPatch as StorageMapPatch;
69
70impl Verify for StorageMapPatch {
71    type Verified = miden_protocol::account::StorageMapPatch;
72    type Error = StorageMapPatchError;
73    fn verify(self) -> Result<Self::Verified, Self::Error> {
74        use proto::account::storage_map_patch::DecodedOperation;
75        match self.operation {
76            DecodedOperation::Create(entries) => {
77                Ok(Self::Verified::Create { entries: entries.verify()? })
78            },
79            DecodedOperation::Update(entries) => {
80                let entries = entries.verify()?;
81                if entries.is_empty() {
82                    return Err(StorageMapPatchError::EmptyUpdate);
83                }
84                Ok(Self::Verified::Update { entries })
85            },
86            DecodedOperation::Remove(()) => Ok(Self::Verified::Remove),
87        }
88    }
89}
90
91#[derive(Debug, thiserror::Error)]
92pub enum StorageMapPatchError {
93    #[error("entries must be non-empty for an update operation")]
94    EmptyUpdate,
95    #[error("duplicate storage map key {0:?}")]
96    DuplicateKey(miden_protocol::account::StorageMapKey),
97}
98
99pub use proto::account::DecodedStorageValuePatch as StorageValuePatch;
100
101impl Verify for StorageValuePatch {
102    type Verified = miden_protocol::account::StorageValuePatch;
103    type Error = core::convert::Infallible;
104    fn verify(self) -> Result<Self::Verified, Self::Error> {
105        use proto::account::storage_value_patch::DecodedOperation;
106        Ok(match self.operation {
107            DecodedOperation::Create(value) => Self::Verified::Create { value },
108            DecodedOperation::Update(value) => Self::Verified::Update { value },
109            DecodedOperation::Remove(()) => Self::Verified::Remove,
110        })
111    }
112}
113
114pub use proto::account::DecodedStorageSlotPatch as StorageSlotPatch;
115
116impl Verify for StorageSlotPatch {
117    type Verified = (
118        miden_protocol::account::StorageSlotName,
119        miden_protocol::account::StorageSlotPatch,
120    );
121    type Error = VerificationError;
122    fn verify(self) -> Result<Self::Verified, Self::Error> {
123        use miden_protocol::account::{StorageSlotName, StorageSlotPatch};
124        use proto::account::storage_slot_patch::DecodedPatch;
125        let name = StorageSlotName::new(self.slot_name)?;
126        let patch = match self.patch {
127            DecodedPatch::Value(value) => {
128                StorageSlotPatch::Value(unwrap_infallible(value.verify()))
129            },
130            DecodedPatch::Map(map) => StorageSlotPatch::Map(map.verify()?),
131        };
132        Ok((name, patch))
133    }
134}
135
136pub use proto::account::DecodedAccountStoragePatch as AccountStoragePatch;
137
138impl Verify for AccountStoragePatch {
139    type Verified = miden_protocol::account::AccountStoragePatch;
140    type Error = VerificationError;
141    fn verify(self) -> Result<Self::Verified, Self::Error> {
142        let slots = self.slots.verify()?;
143        Ok(Self::Verified::from_entries(slots)?)
144    }
145}
146
147pub use proto::account::DecodedAccountPatch as AccountPatch;
148
149impl Verify for AccountPatch {
150    type Verified = miden_protocol::account::AccountPatch;
151    type Error = VerificationError;
152    fn verify(self) -> Result<Self::Verified, Self::Error> {
153        if self.version != proto::account::AccountPatchVersion::V1 {
154            return Err(AccountPatchError::UnspecifiedVersion.into());
155        }
156        Ok(Self::Verified::new(
157            self.account_id.verify()?,
158            self.storage.verify()?,
159            self.vault.verify()?,
160            self.code.verify()?,
161            self.final_nonce.into_inner(),
162        )?)
163    }
164}
165
166#[derive(Debug, thiserror::Error)]
167pub enum AccountPatchError {
168    #[error("account patch version is unspecified")]
169    UnspecifiedVersion,
170}
171
172pub use proto::account::DecodedAccountUpdateDetails as AccountUpdateDetails;
173
174impl Verify for AccountUpdateDetails {
175    type Verified = miden_protocol::account::AccountUpdateDetails;
176    type Error = VerificationError;
177    fn verify(self) -> Result<Self::Verified, Self::Error> {
178        use proto::account::account_update_details::DecodedUpdate;
179        match self.update {
180            DecodedUpdate::Private(value) => Ok(unwrap_infallible(value.verify())),
181            DecodedUpdate::Public(patch) => Ok(Self::Verified::Public(patch.verify()?)),
182        }
183    }
184}