Skip to main content

miden_testing/mock_chain/
auth.rs

1// AUTH
2// ================================================================================================
3use alloc::vec::Vec;
4
5use miden_protocol::Word;
6use miden_protocol::account::AccountComponent;
7use miden_protocol::account::auth::{AuthScheme, AuthSecretKey, PublicKeyCommitment};
8use miden_protocol::testing::noop_auth_component::NoopAuthComponent;
9use miden_standards::account::auth::{
10    AuthMultisig,
11    AuthMultisigConfig,
12    AuthMultisigPsm,
13    AuthMultisigPsmConfig,
14    AuthSingleSig,
15    AuthSingleSigAcl,
16    AuthSingleSigAclConfig,
17    PsmConfig,
18};
19use miden_standards::testing::account_component::{
20    ConditionalAuthComponent,
21    IncrNonceAuthComponent,
22};
23use miden_tx::auth::BasicAuthenticator;
24use rand::SeedableRng;
25use rand_chacha::ChaCha20Rng;
26
27/// Specifies which authentication mechanism is desired for accounts
28#[derive(Debug, Clone)]
29pub enum Auth {
30    /// Creates a secret key for the account and creates a [BasicAuthenticator] used to
31    /// authenticate the account with [AuthSingleSig].
32    BasicAuth { auth_scheme: AuthScheme },
33
34    /// Multisig
35    Multisig {
36        threshold: u32,
37        approvers: Vec<(PublicKeyCommitment, AuthScheme)>,
38        proc_threshold_map: Vec<(Word, u32)>,
39    },
40
41    /// Multisig with a private state manager.
42    MultisigPsm {
43        threshold: u32,
44        approvers: Vec<(PublicKeyCommitment, AuthScheme)>,
45        psm_config: PsmConfig,
46        proc_threshold_map: Vec<(Word, u32)>,
47    },
48
49    /// Creates a secret key for the account, and creates a [BasicAuthenticator] used to
50    /// authenticate the account with [AuthSingleSigAcl]. Authentication will only be
51    /// triggered if any of the procedures specified in the list are called during execution.
52    Acl {
53        auth_trigger_procedures: Vec<Word>,
54        allow_unauthorized_output_notes: bool,
55        allow_unauthorized_input_notes: bool,
56        auth_scheme: AuthScheme,
57    },
58
59    /// Creates a mock authentication mechanism for the account that only increments the nonce.
60    IncrNonce,
61
62    /// Creates a mock authentication mechanism for the account that does nothing.
63    Noop,
64
65    /// Creates a mock authentication mechanism for the account that conditionally succeeds and
66    /// conditionally increments the nonce based on the authentication arguments.
67    ///
68    /// The auth procedure expects the first three arguments as [99, 98, 97] to succeed.
69    /// In case it succeeds, it conditionally increments the nonce based on the fourth argument.
70    Conditional,
71}
72
73impl Auth {
74    /// Converts `self` into its corresponding authentication [`AccountComponent`] and an optional
75    /// [`BasicAuthenticator`]. The component is always returned, but the authenticator is only
76    /// `Some` when [`Auth::BasicAuth`] is passed."
77    pub fn build_component(&self) -> (AccountComponent, Option<BasicAuthenticator>) {
78        match self {
79            Auth::BasicAuth { auth_scheme } => {
80                let mut rng = ChaCha20Rng::from_seed(Default::default());
81                let sec_key = AuthSecretKey::with_scheme_and_rng(*auth_scheme, &mut rng)
82                    .expect("failed to create secret key");
83                let pub_key = sec_key.public_key().to_commitment();
84
85                let component = AuthSingleSig::new(pub_key, *auth_scheme).into();
86                let authenticator = BasicAuthenticator::new(&[sec_key]);
87
88                (component, Some(authenticator))
89            },
90            Auth::Multisig { threshold, approvers, proc_threshold_map } => {
91                let config = AuthMultisigConfig::new(approvers.clone(), *threshold)
92                    .and_then(|cfg| cfg.with_proc_thresholds(proc_threshold_map.clone()))
93                    .expect("invalid multisig config");
94                let component =
95                    AuthMultisig::new(config).expect("multisig component creation failed").into();
96
97                (component, None)
98            },
99            Auth::MultisigPsm {
100                threshold,
101                approvers,
102                psm_config,
103                proc_threshold_map,
104            } => {
105                let config = AuthMultisigPsmConfig::new(approvers.clone(), *threshold, *psm_config)
106                    .and_then(|cfg| cfg.with_proc_thresholds(proc_threshold_map.clone()))
107                    .expect("invalid multisig psm config");
108                let component = AuthMultisigPsm::new(config)
109                    .expect("multisig psm component creation failed")
110                    .into();
111
112                (component, None)
113            },
114            Auth::Acl {
115                auth_trigger_procedures,
116                allow_unauthorized_output_notes,
117                allow_unauthorized_input_notes,
118                auth_scheme,
119            } => {
120                let mut rng = ChaCha20Rng::from_seed(Default::default());
121                let sec_key = AuthSecretKey::with_scheme_and_rng(*auth_scheme, &mut rng)
122                    .expect("failed to create secret key");
123                let pub_key = sec_key.public_key().to_commitment();
124
125                let component = AuthSingleSigAcl::new(
126                    pub_key,
127                    *auth_scheme,
128                    AuthSingleSigAclConfig::new()
129                        .with_auth_trigger_procedures(auth_trigger_procedures.clone())
130                        .with_allow_unauthorized_output_notes(*allow_unauthorized_output_notes)
131                        .with_allow_unauthorized_input_notes(*allow_unauthorized_input_notes),
132                )
133                .expect("component creation failed")
134                .into();
135                let authenticator = BasicAuthenticator::new(&[sec_key]);
136
137                (component, Some(authenticator))
138            },
139            Auth::IncrNonce => (IncrNonceAuthComponent.into(), None),
140            Auth::Noop => (NoopAuthComponent.into(), None),
141            Auth::Conditional => (ConditionalAuthComponent.into(), None),
142        }
143    }
144}
145
146impl From<Auth> for AccountComponent {
147    fn from(auth: Auth) -> Self {
148        let (component, _) = auth.build_component();
149        component
150    }
151}