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