Skip to main content

miden_standards/account/auth/
singlesig.rs

1use miden_protocol::Word;
2use miden_protocol::account::auth::{AuthScheme, PublicKeyCommitment};
3use miden_protocol::account::component::{
4    AccountComponentMetadata,
5    SchemaType,
6    StorageSchema,
7    StorageSlotSchema,
8};
9use miden_protocol::account::{AccountComponent, StorageSlot, StorageSlotName};
10use miden_protocol::utils::sync::LazyLock;
11
12use crate::account::components::singlesig_library;
13
14static PUBKEY_SLOT_NAME: LazyLock<StorageSlotName> = LazyLock::new(|| {
15    StorageSlotName::new("miden::standards::auth::singlesig::pub_key")
16        .expect("storage slot name should be valid")
17});
18
19static SCHEME_ID_SLOT_NAME: LazyLock<StorageSlotName> = LazyLock::new(|| {
20    StorageSlotName::new("miden::standards::auth::singlesig::scheme")
21        .expect("storage slot name should be valid")
22});
23
24/// An [`AccountComponent`] implementing the signature scheme for authentication
25/// of transactions.
26///
27/// This component exports `auth_tx`, which loads the public key and signature scheme id from
28/// storage and delegates transaction authentication to
29/// `miden::standards::auth::signature::authenticate_transaction`.
30///
31/// When linking against this component, the `miden::standards` library must be available to the
32/// assembler (which also implies availability of `miden::protocol`). This is the case when using
33/// [`CodeBuilder`][builder].
34///
35/// This component supports all account types.
36///
37/// [builder]: crate::code_builder::CodeBuilder
38pub struct AuthSingleSig {
39    pub_key: PublicKeyCommitment,
40    auth_scheme: AuthScheme,
41}
42
43impl AuthSingleSig {
44    /// The name of the component.
45    pub const NAME: &'static str = "miden::auth::singlesig";
46
47    /// Creates a new [`AuthSingleSig`] component with the given `public_key`.
48    pub fn new(pub_key: PublicKeyCommitment, auth_scheme: AuthScheme) -> Self {
49        Self { pub_key, auth_scheme }
50    }
51
52    /// Returns the [`StorageSlotName`] where the public key is stored.
53    pub fn public_key_slot() -> &'static StorageSlotName {
54        &PUBKEY_SLOT_NAME
55    }
56
57    // Returns the [`StorageSlotName`] where the scheme ID is stored.
58    pub fn scheme_id_slot() -> &'static StorageSlotName {
59        &SCHEME_ID_SLOT_NAME
60    }
61
62    /// Returns the storage slot schema for the public key slot.
63    pub fn public_key_slot_schema() -> (StorageSlotName, StorageSlotSchema) {
64        (
65            Self::public_key_slot().clone(),
66            StorageSlotSchema::value("Public key commitment", SchemaType::pub_key()),
67        )
68    }
69    /// Returns the storage slot schema for the scheme ID slot.
70    pub fn auth_scheme_slot_schema() -> (StorageSlotName, StorageSlotSchema) {
71        (
72            Self::scheme_id_slot().clone(),
73            StorageSlotSchema::value("Scheme ID", SchemaType::auth_scheme()),
74        )
75    }
76}
77
78impl From<AuthSingleSig> for AccountComponent {
79    fn from(basic_signature: AuthSingleSig) -> Self {
80        let storage_schema = StorageSchema::new(vec![
81            AuthSingleSig::public_key_slot_schema(),
82            AuthSingleSig::auth_scheme_slot_schema(),
83        ])
84        .expect("storage schema should be valid");
85
86        let metadata = AccountComponentMetadata::new(AuthSingleSig::NAME)
87            .with_description("Authentication component using ECDSA K256 Keccak or Rpo Falcon 512 signature scheme")
88            .with_supports_all_types()
89            .with_storage_schema(storage_schema);
90
91        let storage_slots = vec![
92            StorageSlot::with_value(
93                AuthSingleSig::public_key_slot().clone(),
94                basic_signature.pub_key.into(),
95            ),
96            StorageSlot::with_value(
97                AuthSingleSig::scheme_id_slot().clone(),
98                Word::from([basic_signature.auth_scheme.as_u8(), 0, 0, 0]),
99            ),
100        ];
101
102        AccountComponent::new(singlesig_library(), storage_slots, metadata).expect(
103            "singlesig component should satisfy the requirements of a valid account component",
104        )
105    }
106}