pm_accounts/oracle/
mod.rs1use 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, 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}