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}