miden_tx/prover/
mast_store.rs

1use alloc::collections::BTreeMap;
2use alloc::sync::Arc;
3
4use miden_processor::MastForestStore;
5use miden_protocol::account::AccountCode;
6use miden_protocol::assembly::mast::MastForest;
7use miden_protocol::transaction::TransactionKernel;
8use miden_protocol::utils::sync::RwLock;
9use miden_protocol::{CoreLibrary, ProtocolLib, Word};
10use miden_standards::StandardsLib;
11
12// TRANSACTION MAST STORE
13// ================================================================================================
14
15/// A store for the code available during transaction execution.
16///
17/// Transaction MAST store contains a map between procedure MAST roots and [MastForest]s containing
18/// MASTs for these procedures. The VM will request [MastForest]s from the store when it encounters
19/// a procedure which it doesn't have the code for. Thus, to execute a program which makes
20/// references to external procedures, the store must be loaded with [MastForest]s containing these
21/// procedures.
22pub struct TransactionMastStore {
23    mast_forests: RwLock<BTreeMap<Word, Arc<MastForest>>>,
24}
25
26#[allow(clippy::new_without_default)]
27impl TransactionMastStore {
28    /// Returns a new [TransactionMastStore] instantiated with the default libraries.
29    ///
30    /// The default libraries include:
31    /// - Miden core library [`CoreLibrary`].
32    /// - Miden protocol library [`ProtocolLib`].
33    /// - Miden standards library [`StandardsLib`].
34    /// - Transaction kernel [`TransactionKernel::kernel`].
35    pub fn new() -> Self {
36        let mast_forests = RwLock::new(BTreeMap::new());
37        let store = Self { mast_forests };
38
39        // load transaction kernel MAST forest
40        let kernels_forest = TransactionKernel::kernel().mast_forest().clone();
41        store.insert(kernels_forest);
42
43        // load miden-core-lib MAST forest
44        let miden_core_lib_forest = CoreLibrary::default().mast_forest().clone();
45        store.insert(miden_core_lib_forest);
46
47        // load protocol lib MAST forest
48        let protocol_lib_forest = ProtocolLib::default().mast_forest().clone();
49        store.insert(protocol_lib_forest);
50
51        // load standards lib MAST forest
52        let standards_lib_forest = StandardsLib::default().mast_forest().clone();
53        store.insert(standards_lib_forest);
54
55        store
56    }
57
58    /// Registers all procedures of the provided [MastForest] with this store.
59    pub fn insert(&self, mast_forest: Arc<MastForest>) {
60        let mut mast_forests = self.mast_forests.write();
61
62        // only register procedures that are local to this forest
63        for proc_digest in mast_forest.local_procedure_digests() {
64            mast_forests.insert(proc_digest, mast_forest.clone());
65        }
66    }
67
68    /// Loads the provided account code into this store.
69    pub fn load_account_code(&self, code: &AccountCode) {
70        self.insert(code.mast().clone());
71    }
72}
73
74// MAST FOREST STORE IMPLEMENTATION
75// ================================================================================================
76
77impl MastForestStore for TransactionMastStore {
78    fn get(&self, procedure_root: &Word) -> Option<Arc<MastForest>> {
79        self.mast_forests.read().get(procedure_root).cloned()
80    }
81}