use std::time::Duration;
pub struct CeremonyController {
namespace: Option<String>,
}
impl CeremonyController {
pub fn new(namespace: Option<String>) -> Self {
Self { namespace }
}
pub async fn run(&self) -> anyhow::Result<()> {
loop {
self.reconcile_once().await?;
tokio::time::sleep(Duration::from_secs(10)).await;
}
}
pub async fn reconcile_once(&self) -> anyhow::Result<()> {
tracing::info!(namespace = ?self.namespace, "reconciliation pass");
Ok(())
}
pub fn execute_ceremony(
scheme: &str,
threshold: u32,
party_count: u32,
message: &[u8],
) -> anyhow::Result<Vec<u8>> {
tracing::info!(
scheme,
threshold,
party_count,
msg_len = message.len(),
"executing ceremony"
);
let (public_key, shares) = match scheme {
"cmp20" => {
let kg = confium_tc_cmp20::inprocess::keygen(threshold, party_count as usize)?;
(kg.public_key, kg.shares)
}
"gg18" => {
let kg = confium_tc_gg18::inprocess::keygen(threshold, party_count as usize)?;
(kg.public_key, kg.shares)
}
other => anyhow::bail!("unknown scheme: {other}"),
};
let sig = match scheme {
"cmp20" => confium_tc_cmp20::inprocess::sign(&shares, threshold, message)?,
"gg18" => confium_tc_gg18::inprocess::sign(&shares, threshold, message)?,
_ => unreachable!(),
};
tracing::info!(
pk_len = public_key.len(),
sig_len = sig.len(),
"ceremony completed"
);
Ok(sig)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn execute_ceremony_cmp20() {
let sig = CeremonyController::execute_ceremony("cmp20", 2, 3, b"release artifact").unwrap();
assert_eq!(sig.len(), 64);
}
#[test]
fn execute_ceremony_gg18() {
let sig = CeremonyController::execute_ceremony("gg18", 2, 3, b"release artifact").unwrap();
assert_eq!(sig.len(), 64);
}
#[test]
fn execute_ceremony_rejects_unknown_scheme() {
assert!(CeremonyController::execute_ceremony("bogus", 2, 3, b"msg").is_err());
}
}