use miden_protocol::Word;
use miden_protocol::account::auth::{AuthScheme, PublicKeyCommitment};
use miden_protocol::account::component::{
AccountComponentMetadata,
SchemaType,
StorageSchema,
StorageSlotSchema,
};
use miden_protocol::account::{AccountComponent, AccountType, StorageSlot, StorageSlotName};
use miden_protocol::utils::sync::LazyLock;
use crate::account::components::singlesig_library;
static PUBKEY_SLOT_NAME: LazyLock<StorageSlotName> = LazyLock::new(|| {
StorageSlotName::new("miden::standards::auth::singlesig::pub_key")
.expect("storage slot name should be valid")
});
static SCHEME_ID_SLOT_NAME: LazyLock<StorageSlotName> = LazyLock::new(|| {
StorageSlotName::new("miden::standards::auth::singlesig::scheme")
.expect("storage slot name should be valid")
});
pub struct AuthSingleSig {
pub_key: PublicKeyCommitment,
auth_scheme: AuthScheme,
}
impl AuthSingleSig {
pub const NAME: &'static str = "miden::standards::components::auth::singlesig";
pub fn new(pub_key: PublicKeyCommitment, auth_scheme: AuthScheme) -> Self {
Self { pub_key, auth_scheme }
}
pub fn public_key_slot() -> &'static StorageSlotName {
&PUBKEY_SLOT_NAME
}
pub fn scheme_id_slot() -> &'static StorageSlotName {
&SCHEME_ID_SLOT_NAME
}
pub fn public_key_slot_schema() -> (StorageSlotName, StorageSlotSchema) {
(
Self::public_key_slot().clone(),
StorageSlotSchema::value("Public key commitment", SchemaType::pub_key()),
)
}
pub fn auth_scheme_slot_schema() -> (StorageSlotName, StorageSlotSchema) {
(
Self::scheme_id_slot().clone(),
StorageSlotSchema::value("Scheme ID", SchemaType::auth_scheme()),
)
}
pub fn component_metadata() -> AccountComponentMetadata {
let storage_schema = StorageSchema::new(vec![
Self::public_key_slot_schema(),
Self::auth_scheme_slot_schema(),
])
.expect("storage schema should be valid");
AccountComponentMetadata::new(Self::NAME, AccountType::all())
.with_description(
"Authentication component using ECDSA K256 Keccak or Falcon512 Poseidon2 signature scheme",
)
.with_storage_schema(storage_schema)
}
}
impl From<AuthSingleSig> for AccountComponent {
fn from(basic_signature: AuthSingleSig) -> Self {
let metadata = AuthSingleSig::component_metadata();
let storage_slots = vec![
StorageSlot::with_value(
AuthSingleSig::public_key_slot().clone(),
basic_signature.pub_key.into(),
),
StorageSlot::with_value(
AuthSingleSig::scheme_id_slot().clone(),
Word::from([basic_signature.auth_scheme.as_u8(), 0, 0, 0]),
),
];
AccountComponent::new(singlesig_library(), storage_slots, metadata).expect(
"singlesig component should satisfy the requirements of a valid account component",
)
}
}