Skip to main content

kinetic_core/
traits.rs

1//! Core trait abstractions and dependency inversion interfaces for the Kinetic engine.
2//!
3//! Defines the abstract contracts for Kinetic's three primary pluggable backends:
4//!
5//! - `VdfEngine`: CPU-bound Wesolowski VDF proof evaluation and verification (chiavdf).
6//! - `StorageEngine`: Key-value persistence and prefix scanning (Sled B-tree).
7//! - `GovernanceEngine`: Protocol proposal verification and state transitions.
8//!
9//! These traits enable `kinetic-core` to be network-agnostic. The concrete implementations
10//! live in `kinetic-vdf`, `kinetic-storage`, and `kinetic-core/src/governance/engine/`
11//! respectively. The active `GovernanceEngine` is selected at compile time from `network.json`
12//! via the `GOVERNANCE_MODEL` constant.
13
14use crate::error::{GovernanceError, StorageError, VdfError};
15use crate::governance::types::{GovernanceEffect, GovernanceState, SignedGovernanceMessage};
16use crate::types::{Commitment, VdfProof};
17
18/// Abstract interface for Verifiable Delay Function (VDF) computation engines.
19///
20/// The canonical implementation in `kinetic-vdf` wraps the `chiavdf` Wesolowski
21/// VDF library. The challenge is always a 32-byte SHA-256 hash derived from
22/// `network_id || name || salt || drand_signature_hex`.
23pub trait VdfEngine: Send + Sync {
24    /// Evaluates the VDF sequentially for the given number of iterations.
25    ///
26    /// This is a **CPU-intensive, sequential operation** that blocks the calling
27    /// thread for the full duration (seconds to minutes depending on hardware
28    /// and iteration count). It must not be called on an async executor thread.
29    ///
30    /// # Errors
31    ///
32    /// - Returns [`VdfError::LockFileError`] (`KIN-VDF-001`) if the serialization lock file cannot be created.
33    /// - Returns [`VdfError::LockAcquireError`] (`KIN-VDF-002`) if the lock cannot be acquired (retryable).
34    /// - Returns [`VdfError::DiscriminantError`] (`KIN-VDF-003`) if discriminant generation fails.
35    /// - Returns [`VdfError::ProofGenerationError`] (`KIN-VDF-004`) if chiavdf prover panics or fails.
36    /// - Returns [`VdfError::UnsupportedPlatform`] (`KIN-VDF-005`) if the platform is not supported.
37    fn evaluate(&self, challenge: &Commitment, iterations: u64) -> Result<VdfProof, VdfError>;
38
39    /// Instantly verifies a provided VDF proof against a challenge and target iteration count.
40    ///
41    /// Unlike [`evaluate`](Self::evaluate), verification is O(log n) and non-blocking.
42    ///
43    /// # Returns
44    ///
45    /// `Ok(true)` if the proof is valid for the given challenge and iteration count.
46    /// `Ok(false)` if the proof is structurally valid but does not verify.
47    ///
48    /// # Errors
49    ///
50    /// - Returns [`VdfError::DiscriminantError`] (`KIN-VDF-003`) if discriminant creation from the challenge fails.
51    /// - Returns [`VdfError::InvalidProof`] (`KIN-VDF-006`) if the proof bytes are malformed or too large.
52    fn verify(
53        &self,
54        challenge: &Commitment,
55        proof: &VdfProof,
56        iterations: u64,
57    ) -> Result<bool, VdfError>;
58}
59
60/// Abstract interface for local embedded database storage engines.
61///
62/// The canonical implementation in `kinetic-storage` wraps a Sled B-tree database.
63/// All keys in Kinetic are namespaced with a `{NETWORK_ID}_` prefix so that multiple
64/// TLD networks can share a physical database file without key collisions.
65pub trait StorageEngine: Send + Sync {
66    /// Stores a key-value byte pair, overwriting any existing entry.
67    ///
68    /// # Errors
69    ///
70    /// - Returns [`StorageError::OperationFailed`] (`KIN-STO-003`) if the write fails.
71    fn put(&self, key: &[u8], value: &[u8]) -> Result<(), StorageError>;
72
73    /// Retrieves the stored value for a given key.
74    ///
75    /// # Returns
76    ///
77    /// - `Ok(Some(bytes))` if the key exists.
78    /// - `Ok(None)` if the key has never been written.
79    ///
80    /// # Errors
81    ///
82    /// - Returns [`StorageError::OperationFailed`] (`KIN-STO-003`) if the read fails.
83    fn get(&self, key: &[u8]) -> Result<Option<bytes::Bytes>, StorageError>;
84
85    /// Removes an entry by key.
86    ///
87    /// This is a no-op if the key does not exist — no error is returned for
88    /// missing keys.
89    ///
90    /// # Errors
91    ///
92    /// - Returns [`StorageError::OperationFailed`] (`KIN-STO-003`) if the deletion fails.
93    fn delete(&self, key: &[u8]) -> Result<(), StorageError>;
94
95    /// Iterates over all key-value pairs whose keys begin with `prefix`, up to an optional `limit`.
96    ///
97    /// # Returns
98    ///
99    /// A `Vec` of `(key_bytes, value_bytes)` pairs. Returns an empty Vec if no
100    /// keys match the prefix.
101    ///
102    /// # Errors
103    ///
104    /// - Returns [`StorageError::OperationFailed`] (`KIN-STO-003`) if prefix iteration fails.
105    #[allow(clippy::type_complexity)]
106    fn scan_prefix(
107        &self,
108        prefix: &[u8],
109        limit: Option<usize>,
110    ) -> Result<Vec<(Vec<u8>, Vec<u8>)>, StorageError>;
111}
112
113/// Abstract interface for protocol governance state verification and action execution.
114///
115/// Four concrete engines are available (selected at compile time via `GOVERNANCE_MODEL`):
116/// `sovereign`, `council`, `permissionless`. See `kinetic-core/src/governance/engine/`.
117///
118/// The engine is always called in a two-step sequence:
119/// 1. [`verify_action`](Self::verify_action) — validates signatures, thresholds, and timelocks.
120/// 2. [`execute_action`](Self::execute_action) — mutates state and returns side effects.
121pub trait GovernanceEngine: Send + Sync {
122    /// Verifies whether a signed governance message meets threshold and timelock requirements.
123    ///
124    /// Does **not** mutate `state` on its own — state changes only happen in
125    /// [`execute_action`](Self::execute_action).
126    ///
127    /// # Returns
128    ///
129    /// - `Ok(Some(effect))` if the message is valid and immediately executable (no timelock).
130    /// - `Ok(None)` if the message is valid but waiting in a timelock queue.
131    ///
132    /// # Errors
133    ///
134    /// - Returns [`GovernanceError::InsufficientSignatures`] (`KIN-GOV-016`) if required signatures or threshold are not met.
135    /// - Returns [`GovernanceError::StaleProposal`] (`KIN-GOV-004`) if the proposal timestamp is outside the replay window.
136    /// - Returns [`GovernanceError::TimelockNotExpired`] (`KIN-GOV-005`) if the mandatory delay has not elapsed.
137    /// - Returns [`GovernanceError::GovernanceDisabled`] (`KIN-GOV-002`) if governance actions are disabled in this mode.
138    /// - Returns [`GovernanceError::KeyLengthMismatch`] (`KIN-GOV-003`) if a key length is invalid.
139    /// - Returns [`GovernanceError::MissingRootKey`] (`KIN-GOV-001`) if the root key is unconfigured.
140    fn verify_action(
141        &self,
142        state: &mut GovernanceState,
143        msg: &SignedGovernanceMessage,
144        current_time_sec: u64,
145    ) -> Result<Option<GovernanceEffect>, GovernanceError>;
146
147    /// Executes a previously verified governance action, applying state changes.
148    ///
149    /// Must only be called after [`verify_action`](Self::verify_action) returns `Ok(_)`.
150    /// The `wait_time` parameter is the remaining timelock seconds to apply for deferred effects.
151    ///
152    /// # Returns
153    ///
154    /// `Some(effect)` if a state-changing side effect was produced (e.g. key rotation,
155    /// council change). `None` if the action was enqueued for a future timelock.
156    fn execute_action(
157        &self,
158        state: &mut GovernanceState,
159        msg: &SignedGovernanceMessage,
160        current_time_sec: u64,
161    ) -> Option<GovernanceEffect>;
162}