miden_objects/transaction/inputs/
account.rs

1use crate::{
2    Digest,
3    account::{AccountCode, AccountId, PartialAccount, PartialStorage},
4    asset::PartialVault,
5    block::AccountWitness,
6    crypto::merkle::{SmtProof, SmtProofError},
7    utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable},
8};
9
10// ACCOUNT INPUTS
11// ================================================================================================
12
13/// Contains information about an account, with everything required to execute a transaction.
14///
15/// `AccountInputs` combines a partial account representation with the merkle proof that verifies
16/// the account's inclusion in the account tree. The partial account should contain verifiable
17/// access to the parts of the state of the account of which the transaction will make use.
18#[derive(Clone, Debug, PartialEq, Eq)]
19pub struct AccountInputs {
20    /// Partial representation of the account's state.
21    partial_account: PartialAccount,
22    /// Proof of the account's inclusion in the account tree for this account's state commitment.
23    witness: AccountWitness,
24}
25
26impl AccountInputs {
27    /// Creates a new instance of `AccountInputs` with the specified partial account and witness.
28    pub fn new(partial_account: PartialAccount, witness: AccountWitness) -> AccountInputs {
29        AccountInputs { partial_account, witness }
30    }
31
32    /// Returns the account ID.
33    pub fn id(&self) -> AccountId {
34        self.partial_account.id()
35    }
36
37    /// Returns a reference to the partial account representation.
38    pub fn account(&self) -> &PartialAccount {
39        &self.partial_account
40    }
41
42    /// Returns a reference to the account code.
43    pub fn code(&self) -> &AccountCode {
44        self.partial_account.code()
45    }
46
47    /// Returns a reference to the partial representation of the account storage.
48    pub fn storage(&self) -> &PartialStorage {
49        self.partial_account.storage()
50    }
51
52    /// Returns a reference to the partial vault representation of the account.
53    pub fn vault(&self) -> &PartialVault {
54        self.partial_account.vault()
55    }
56
57    /// Returns a reference to the account's witness.
58    pub fn witness(&self) -> &AccountWitness {
59        &self.witness
60    }
61
62    /// Decomposes the `AccountInputs` into its constituent parts.
63    pub fn into_parts(self) -> (PartialAccount, AccountWitness) {
64        (self.partial_account, self.witness)
65    }
66
67    /// Computes the account root based on the account witness.
68    /// This root should be equal to the account root in the reference block header.
69    pub fn compute_account_root(&self) -> Result<Digest, SmtProofError> {
70        let smt_merkle_path = self.witness.path().clone();
71        let smt_leaf = self.witness.leaf();
72        let root = SmtProof::new(smt_merkle_path, smt_leaf)?.compute_root();
73
74        Ok(root)
75    }
76}
77
78impl Serializable for AccountInputs {
79    fn write_into<W: ByteWriter>(&self, target: &mut W) {
80        target.write(&self.partial_account);
81        target.write(&self.witness);
82    }
83}
84
85impl Deserializable for AccountInputs {
86    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
87        let partial_account = source.read()?;
88        let witness = source.read()?;
89
90        Ok(AccountInputs { partial_account, witness })
91    }
92}
93
94// TESTS
95// ================================================================================================
96
97#[cfg(test)]
98mod tests {
99    use alloc::vec::Vec;
100
101    use miden_crypto::merkle::MerklePath;
102    use vm_core::{
103        Felt,
104        utils::{Deserializable, Serializable},
105    };
106    use vm_processor::SMT_DEPTH;
107
108    use crate::{
109        account::{Account, AccountCode, AccountId, AccountStorage},
110        asset::AssetVault,
111        block::AccountWitness,
112        testing::account_id::ACCOUNT_ID_REGULAR_PUBLIC_ACCOUNT_IMMUTABLE_CODE,
113        transaction::AccountInputs,
114    };
115
116    #[test]
117    fn serde_roundtrip() {
118        let id = AccountId::try_from(ACCOUNT_ID_REGULAR_PUBLIC_ACCOUNT_IMMUTABLE_CODE).unwrap();
119        let code = AccountCode::mock();
120        let vault = AssetVault::new(&[]).unwrap();
121        let storage = AccountStorage::new(vec![]).unwrap();
122        let account = Account::from_parts(id, vault, storage, code, Felt::new(10));
123
124        let commitment = account.commitment();
125
126        let mut merkle_nodes = Vec::with_capacity(SMT_DEPTH as usize);
127        for _ in 0..(SMT_DEPTH as usize) {
128            merkle_nodes.push(commitment);
129        }
130        let merkle_path = MerklePath::new(merkle_nodes);
131
132        let fpi_inputs = AccountInputs::new(
133            account.into(),
134            AccountWitness::new(id, commitment, merkle_path).unwrap(),
135        );
136
137        let serialized = fpi_inputs.to_bytes();
138        let deserialized = AccountInputs::read_from_bytes(&serialized).unwrap();
139        assert_eq!(deserialized, fpi_inputs);
140    }
141}