-
Notifications
You must be signed in to change notification settings - Fork 124
Lazy loading of account assets and storage #401
Description
The current TransactionInputs object implies that we need to load the full Account object to execute/prove transactions. This may be fine for small accounts, but for accounts which hold a lot of assets or use a lot of storage this may cause issues. Moreover, with our current structure we don't really use account code from the account object (it is loaded into the transaction compiler separately).
To improve on the above, we can load only assets and storage items which are actually needed for transaction execution. One way to do this is to replace Account in TransactionInputs with something like AccountStub and then load additional data via the DataStore. For example, TransactionInputs could look like so:
pub struct TransactionInputs {
account: AccountStub,
account_seed: Option<Word>,
block_header: BlockHeader,
block_chain: ChainMmr,
input_notes: InputNotes,
}
pub struct AccountStub {
id: AccountId,
vault_root: Digest,
storage_root: Digest,
code_root: Digest,
nonce: Felt,
}Then, we'd update DataStore trait to look something like:
pub trait DataStore {
/// Same method as we have now.
fn get_transaction_inputs(
&self,
account_id: AccountId,
block_ref: u32,
notes: &[NoteId],
) -> Result<TransactionInputs, DataStoreError>;
/// Same method as we have now.
fn get_account_code(&self, account_id: AccountId) -> Result<ModuleAst, DataStoreError>;
/// Returns the data that needs to be added to the advice provider's Merkle store and advice map
/// to make access to the specified asset possible.
fn get_asset_vault_access_witness(
&self,
account_id: AccountId,
asset_key: Digest,
) -> Result<AccountDataAccessWitness, DataStoreError>;
/// Returns the data that needs to be added to the advice provider's Merkle store and advice map
/// to make access to the specified storage map item possible.
fn get_storage_map_access_witness(
&self,
account_id: AccountId,
slot_index: u8,
item_key: Digest,
) -> Result<AccountDataAccessWitness, DataStoreError>;
/// Returns the data that needs to be added to the advice provider's Merkle store and advice map
/// to make access to the specified storage array item possible.
fn get_storage_array_access_witness(
&self,
account_id: AccountId,
slot_index: u8,
item_index: u64,
) -> Result<AccountDataAccessWitness, DataStoreError>;
}
pub struct AccountDataAccessWitness {
/// Items to be added to the advice map.
map_items: BTreeMap<Digest, Vec<Felt>>,
/// Nodes to be added to the Merkle store.
store_nodes: Vec<InnerNodeInfo>,
}Then, we'd modify the TransactionHost to keep track of assets and items which have been accessed, and then when a previously un-accesses item is accessed, the host would requested it from the data store. To support this, we'd need to introduce 3 new events - one to fire right before each of the above accesses.