pm_accounts/oracle/
mod.rs

1use std::sync::Arc;
2
3use rand::Rng;
4
5use miden_assembly::{
6    ast::{Module, ModuleKind},
7    DefaultSourceManager, LibraryPath,
8};
9use miden_client::{
10    account::{Account, AccountBuilder, AccountStorageMode, AccountType as ClientAccountType},
11    auth::AuthSecretKey,
12    crypto::FeltRng,
13    Client,
14};
15use miden_client::{crypto::SecretKey, Felt, Word, ZERO};
16use miden_lib::{account::auth::RpoFalcon512, transaction::TransactionKernel};
17use miden_objects::{
18    account::{AccountComponent, StorageSlot},
19    assembly::Library,
20    crypto::dsa::rpo_falcon512::PublicKey,
21};
22
23pub const ORACLE_ACCOUNT_MASM: &str = include_str!("oracle.masm");
24
25pub fn get_oracle_component_library() -> Library {
26    let source_manager = Arc::new(DefaultSourceManager::default());
27    let oracle_component_module = Module::parser(ModuleKind::Library)
28        .parse_str(
29            LibraryPath::new("oracle_component::oracle_module").unwrap(),
30            ORACLE_ACCOUNT_MASM,
31            &source_manager,
32        )
33        .unwrap();
34
35    TransactionKernel::assembler()
36        .with_debug_mode(true)
37        .assemble_library([oracle_component_module])
38        .expect("assembly should succeed")
39}
40
41pub struct OracleAccountBuilder<'a, T: FeltRng> {
42    client: Option<&'a mut Client<T>>,
43    account_type: String, // Temporary fix, because AccountType is not consistent between the Client and the Object
44    storage_slots: Vec<StorageSlot>,
45}
46
47impl<'a, T: FeltRng> OracleAccountBuilder<'a, T> {
48    pub fn new() -> Self {
49        let default_storage_slots = {
50            let mut slots = vec![
51                StorageSlot::Value([Felt::new(2), ZERO, ZERO, ZERO]),
52                StorageSlot::empty_map(),
53            ];
54            slots.extend((0..252).map(|_| StorageSlot::empty_value()));
55            slots
56        };
57
58        Self {
59            client: None,
60            account_type: ClientAccountType::RegularAccountImmutableCode.to_string(),
61            storage_slots: default_storage_slots,
62        }
63    }
64
65    pub fn with_account_type(mut self, account_type: ClientAccountType) -> Self {
66        self.account_type = account_type.to_string();
67        self
68    }
69
70    pub fn with_storage_slots(mut self, slots: Vec<StorageSlot>) -> Self {
71        self.storage_slots = slots;
72        self
73    }
74
75    pub fn with_client(mut self, client: &'a mut Client<T>) -> Self {
76        self.client = Some(client);
77        self
78    }
79
80    pub async fn build(self) -> (Account, Word) {
81        let client_account_type: ClientAccountType = self.account_type.parse().unwrap();
82        let oracle_component =
83            AccountComponent::new(get_oracle_component_library(), self.storage_slots)
84                .unwrap()
85                .with_supports_all_types();
86
87        let client = self.client.expect("build must have a Miden Client!");
88        let client_rng = client.rng();
89        let private_key = SecretKey::with_rng(client_rng);
90        let public_key = private_key.public_key();
91        let auth_component: RpoFalcon512 = RpoFalcon512::new(PublicKey::new(public_key.into()));
92        let from_seed = client_rng.gen();
93        let anchor_block = client.get_latest_epoch_block().await.unwrap();
94
95        let (account, account_seed) = AccountBuilder::new(from_seed)
96            .account_type(client_account_type)
97            .storage_mode(AccountStorageMode::Public)
98            .with_component(auth_component)
99            .with_component(oracle_component)
100            .anchor((&anchor_block).try_into().unwrap())
101            .build()
102            .unwrap();
103        client
104            .add_account(
105                &account,
106                Some(account_seed),
107                &AuthSecretKey::RpoFalcon512(private_key),
108                true,
109            )
110            .await
111            .unwrap();
112
113        (account, account_seed)
114    }
115}
116
117impl<'a, T: FeltRng> Default for OracleAccountBuilder<'a, T> {
118    fn default() -> Self {
119        Self::new()
120    }
121}