Skip to main content

miden_protocol/transaction/inputs/
account.rs

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