Skip to main content

confium_coordinator/coordinator/
session.rs

1//! Coordinator session state machine.
2
3use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5
6/// Unique session identifier.
7pub type SessionId = String;
8
9/// Quorum identifier.
10pub type QuorumId = String;
11
12/// Signer identifier (typically their actor ID).
13pub type SignerId = String;
14
15/// Session state.
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
17#[serde(rename_all = "snake_case")]
18pub enum SessionState {
19    /// Session created; awaiting signer commitments.
20    Pending,
21    /// T commitments received; awaiting shares.
22    CommitmentsCollected,
23    /// T shares received; signature aggregated.
24    Completed,
25    /// Unlock window elapsed before T commitments/shares.
26    Expired,
27    /// Aborted due to error or admin action.
28    Aborted,
29}
30
31/// A signing session request from an application.
32#[derive(Debug, Clone, Serialize, Deserialize)]
33pub struct SessionRequest {
34    /// Quorum authorizing this signature.
35    pub quorum_id: QuorumId,
36    /// Threshold scheme (e.g., "FROST-ed25519").
37    pub scheme: String,
38    /// Message to be signed (digest bytes).
39    pub message: Vec<u8>,
40    /// Threshold T.
41    pub threshold: u32,
42    /// Total parties N.
43    pub num_parties: u32,
44    /// Unlock window in minutes.
45    pub unlock_window_minutes: u32,
46    /// Requesting actor.
47    pub requested_by: SignerId,
48}
49
50/// A commitment submitted by a signer (round 1).
51#[derive(Debug, Clone, Serialize, Deserialize)]
52pub struct Commitment {
53    /// Submitting signer.
54    pub signer_id: SignerId,
55    /// Commitment bytes (algorithm-specific).
56    pub bytes: Vec<u8>,
57    /// Signer's identity signature on the commitment (non-repudiation).
58    pub signer_signature: Vec<u8>,
59    /// When the commitment was submitted.
60    pub submitted_at: DateTime<Utc>,
61}
62
63/// A share submitted by a signer (round 2).
64#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct Share {
66    /// Submitting signer.
67    pub signer_id: SignerId,
68    /// Share bytes (algorithm-specific).
69    pub bytes: Vec<u8>,
70    /// Signer's identity signature on the share.
71    pub signer_signature: Vec<u8>,
72    /// When the share was submitted.
73    pub submitted_at: DateTime<Utc>,
74}
75
76/// The final aggregated signature.
77#[derive(Debug, Clone, Serialize, Deserialize)]
78pub struct AggregatedSignature {
79    /// Signature bytes.
80    pub bytes: Vec<u8>,
81    /// Algorithm identifier.
82    pub algorithm: String,
83    /// When aggregation completed.
84    pub completed_at: DateTime<Utc>,
85    /// List of signers who contributed.
86    pub contributing_signers: Vec<SignerId>,
87}
88
89/// Session errors.
90#[derive(Debug, thiserror::Error)]
91pub enum SessionError {
92    /// Session not found.
93    #[error("session not found: {0}")]
94    NotFound(SessionId),
95    /// Session in wrong state.
96    #[error("session {session_id} in state {current_state:?}, expected {expected}")]
97    InvalidState {
98        /// Session ID.
99        session_id: SessionId,
100        /// Current state.
101        current_state: SessionState,
102        /// Expected state description.
103        expected: &'static str,
104    },
105    /// Threshold not met.
106    #[error("threshold not met: have {have}, need {need}")]
107    ThresholdNotMet {
108        /// Count received.
109        have: usize,
110        /// Threshold.
111        need: u32,
112    },
113    /// Signer already submitted.
114    #[error("signer {signer} already submitted to session {session}")]
115    DuplicateSubmission {
116        /// Signer ID.
117        signer: SignerId,
118        /// Session ID.
119        session: SessionId,
120    },
121    /// Unlock window expired.
122    #[error("session {0} unlock window expired")]
123    Expired(SessionId),
124    /// Unauthorized signer.
125    #[error("signer {0} not authorized for this quorum")]
126    UnauthorizedSigner(SignerId),
127    /// Threshold signing engine failed.
128    #[error("signing failed: {0}")]
129    SigningFailed(String),
130}