Create config for akd and vrf storages

This commit is contained in:
Matt Gibson 2025-12-09 16:17:52 -08:00
parent 0a818755f3
commit 8b750aee0a
No known key found for this signature in database
6 changed files with 143 additions and 14 deletions

View File

@ -14,6 +14,7 @@ config = { workspace = true }
serde = { workspace = true }
thiserror = "2.0.17"
tracing.workspace = true
hex = "0.4.3"
[lints]
workspace = true

View File

@ -0,0 +1,44 @@
use thiserror::Error;
mod storage_manager_config;
mod vrf_config;
pub use storage_manager_config::*;
pub use vrf_config::*;
#[derive(Error, Debug)]
pub enum ConfigError {
#[error("Failed to connect to database")]
DatabaseConnection(#[source] akd::errors::StorageError),
#[error("Configuration value 'cache_item_lifetime_ms' is invalid: value {value} exceeds maximum allowed ({max})")]
CacheLifetimeOutOfRange {
value: usize,
max: u64,
#[source]
source: std::num::TryFromIntError,
},
#[error("Configuration value 'cache_clean_frequency_ms' is invalid: value {value} exceeds maximum allowed ({max})")]
CacheCleanFrequencyOutOfRange {
value: usize,
max: u64,
#[source]
source: std::num::TryFromIntError,
},
#[error("{0}")]
Custom(String),
#[error("Invalid hex string for VRF key material")]
InvalidVrfKeyMaterialHex(#[source] hex::FromHexError),
#[error("VRF key material must be exactly 32 bytes, got {actual} bytes")]
VrfKeyMaterialInvalidLength { actual: usize },
}
impl ConfigError {
pub fn new(message: impl Into<String>) -> Self {
Self::Custom(message.into())
}
}

View File

@ -0,0 +1,59 @@
use std::time::Duration;
use crate::config::ConfigError;
use akd::storage::StorageManager;
use akd_storage::{db_config::DbConfig, DatabaseType};
use serde::{Deserialize, Serialize};
/// items live for 30s by default
pub const DEFAULT_ITEM_LIFETIME_MS: usize = 30_000;
/// clean the cache every 15s by default
pub const DEFAULT_CACHE_CLEAN_FREQUENCY_MS: usize = 15_000;
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct StorageManagerConfig {
pub db_config: DbConfig,
pub cache_limit_bytes: Option<usize>,
#[serde(default = "default_cache_item_lifetime_ms")]
pub cache_item_lifetime_ms: usize,
#[serde(default = "default_cache_clean_frequency_ms")]
pub cache_clean_frequency_ms: usize,
}
fn default_cache_item_lifetime_ms() -> usize {
DEFAULT_ITEM_LIFETIME_MS
}
fn default_cache_clean_frequency_ms() -> usize {
DEFAULT_CACHE_CLEAN_FREQUENCY_MS
}
impl StorageManagerConfig {
pub async fn create(&self) -> Result<StorageManager<DatabaseType>, ConfigError> {
Ok(StorageManager::new(
self.db_config
.connect()
.await
.map_err(ConfigError::DatabaseConnection)?,
Some(Duration::from_millis(
self.cache_item_lifetime_ms.try_into().map_err(|source| {
ConfigError::CacheLifetimeOutOfRange {
value: self.cache_item_lifetime_ms,
max: u64::MAX,
source,
}
})?,
)),
self.cache_limit_bytes,
Some(Duration::from_millis(
self.cache_clean_frequency_ms.try_into().map_err(|source| {
ConfigError::CacheCleanFrequencyOutOfRange {
value: self.cache_clean_frequency_ms,
max: u64::MAX,
source,
}
})?,
)),
))
}
}

View File

@ -0,0 +1,34 @@
use serde::{Deserialize, Serialize};
use crate::config::ConfigError;
use crate::VrfStorageType;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum VrfConfig {
HardCodedAkdVRF,
ConstantConfigurableVRF { key_material: String },
}
impl TryFrom<&VrfConfig> for VrfStorageType {
type Error = ConfigError;
fn try_from(config: &VrfConfig) -> Result<Self, ConfigError> {
match config {
VrfConfig::HardCodedAkdVRF => Ok(VrfStorageType::HardCodedAkdVRF),
VrfConfig::ConstantConfigurableVRF { key_material } => {
let key_material =
hex::decode(key_material).map_err(ConfigError::InvalidVrfKeyMaterialHex)?;
if key_material.len() != 32 {
return Err(ConfigError::VrfKeyMaterialInvalidLength {
actual: key_material.len(),
});
}
Ok(VrfStorageType::ConstantConfigurableVRF {
key_material: key_material.clone(),
})
}
}
}
}

View File

@ -1,3 +1,4 @@
pub mod config;
mod vrf_type;
pub use vrf_type::VrfStorageType;

View File

@ -1,19 +1,5 @@
use akd::ecvrf::{HardCodedAkdVRF, VRFKeyStorage, VrfError};
use async_trait::async_trait;
use serde::{Deserialize};
#[derive(Debug, Clone, Deserialize)]
pub enum VrfConfig {
HardCodedAkdVRF,
}
impl From<&VrfConfig> for VrfStorageType {
fn from(config: &VrfConfig) -> Self {
match config {
VrfConfig::HardCodedAkdVRF => VrfStorageType::HardCodedAkdVRF,
}
}
}
#[derive(Debug, Clone)]
pub enum VrfStorageType {
@ -22,6 +8,9 @@ pub enum VrfStorageType {
///
/// const KEY_MATERIAL: &str = "c9afa9d845ba75166b5c215767b1d6934e50c3db36e89b127b8a622b120f6721";
HardCodedAkdVRF,
ConstantConfigurableVRF {
key_material: Vec<u8>,
},
}
#[async_trait]
@ -29,6 +18,7 @@ impl VRFKeyStorage for VrfStorageType {
async fn retrieve(&self) -> Result<Vec<u8>, VrfError> {
match self {
VrfStorageType::HardCodedAkdVRF => HardCodedAkdVRF.retrieve().await,
VrfStorageType::ConstantConfigurableVRF { key_material } => Ok(key_material.clone()),
}
}
}