praborrow_core/lib.rs
1//! Core primitives for distributed ownership enforcement.
2//!
3//! This crate provides `Sovereign<T>`, a wrapper type that tracks ownership
4//! across network boundaries. When a resource is "annexed" (moved to another node),
5//! local access is prohibited.
6//!
7//! # The Garuda Proof System
8//!
9//! With `praborrow-prover`, this crate now supports **formally verified** state
10//! transitions. Use `annex_verified()` to require SMT proof before annexation.
11//!
12//! # Safety
13//! Uses `UnsafeCell` and `AtomicU8` for interior mutability with thread-safety.
14//! The `Send`/`Sync` implementations are safe when `T` is `Send`/`Sync`.
15
16use std::ops::{Deref, DerefMut};
17use std::sync::atomic::{AtomicU8, Ordering};
18use std::cell::UnsafeCell;
19use std::marker::PhantomData;
20
21/// The state of a Sovereign resource.
22/// 0: Domestic (Local jurisdiction)
23/// 1: Exiled (Foreign jurisdiction - moved to another node)
24#[derive(Debug, PartialEq, Eq, Clone, Copy)]
25#[repr(u8)]
26pub enum SovereignState {
27 Domestic = 0,
28 Exiled = 1,
29}
30
31/// A wrapper that enforces ownership semantics across network boundaries.
32///
33/// "Memory safety with sovereign integrity."
34pub struct Sovereign<T> {
35 inner: UnsafeCell<T>,
36 state: AtomicU8,
37}
38
39impl<T> Sovereign<T> {
40 /// Creates a new Sovereign resource under domestic jurisdiction.
41 pub fn new(value: T) -> Self {
42 Self {
43 inner: UnsafeCell::new(value),
44 state: AtomicU8::new(SovereignState::Domestic as u8),
45 }
46 }
47
48 /// Annexes the resource, moving it to foreign jurisdiction.
49 ///
50 /// Once annexed, the resource cannot be accessed locally.
51 /// Access attempts will result in a Sovereignty Violation (panic).
52 pub fn annex(&self) -> Result<(), String> {
53 let current = self.state.load(Ordering::SeqCst);
54 if current == SovereignState::Exiled as u8 {
55 return Err("Resource is already under foreign jurisdiction.".to_string());
56 }
57
58 // Diplomatically transition state
59 self.state.store(SovereignState::Exiled as u8, Ordering::SeqCst);
60 Ok(())
61 }
62
63 /// Returns a reference to the inner value without jurisdiction check.
64 ///
65 /// # Safety
66 /// This is safe because we're returning a shared reference and the caller
67 /// is responsible for ensuring the resource is domestic.
68 pub fn inner_ref(&self) -> &T {
69 // SAFETY: We're only reading, and this is safe when called from
70 // contexts that have already verified jurisdiction.
71 unsafe { &*self.inner.get() }
72 }
73
74 /// Returns the current state of the resource.
75 pub fn state(&self) -> SovereignState {
76 match self.state.load(Ordering::SeqCst) {
77 0 => SovereignState::Domestic,
78 _ => SovereignState::Exiled,
79 }
80 }
81
82 /// Checks if the resource is currently domestic.
83 fn verify_jurisdiction(&self) {
84 if self.state.load(Ordering::SeqCst) == SovereignState::Exiled as u8 {
85 panic!("SOVEREIGNTY VIOLATION: Resource is under foreign jurisdiction.");
86 }
87 }
88}
89
90impl<T> Deref for Sovereign<T> {
91 type Target = T;
92
93 fn deref(&self) -> &Self::Target {
94 self.verify_jurisdiction();
95 // SAFETY: We've verified the resource is domestic, so access is valid.
96 unsafe { &*self.inner.get() }
97 }
98}
99
100impl<T> DerefMut for Sovereign<T> {
101 fn deref_mut(&mut self) -> &mut Self::Target {
102 self.verify_jurisdiction();
103 // SAFETY: We've verified the resource is domestic and have &mut self.
104 unsafe { &mut *self.inner.get() }
105 }
106}
107
108// SAFETY: Sovereign<T> is Send/Sync if T is Send/Sync, as we use AtomicU8 for state
109// and check it before access. The UnsafeCell is protected by the atomic state check.
110unsafe impl<T: Send> Send for Sovereign<T> {}
111unsafe impl<T: Sync> Sync for Sovereign<T> {}
112
113/// Protocol for enforcing constitutional invariants (runtime checks).
114pub trait CheckProtocol {
115 /// Enforces all invariants, panicking if any are violated.
116 fn enforce_law(&self);
117}
118
119/// A value carrying cryptographic proof of verification.
120///
121/// This type can only be constructed by successful SMT verification.
122/// Its existence in a type signature proves that formal verification occurred.
123///
124/// # Type Safety Guarantee
125///
126/// `ProofCarrying<T>` cannot be forged - the private `_proof` field
127/// ensures only the prover crate can construct it.
128#[derive(Debug)]
129pub struct ProofCarrying<T> {
130 /// The carried value.
131 pub value: T,
132 /// Private marker ensuring construction only via verification.
133 _proof: PhantomData<()>,
134}
135
136impl<T> ProofCarrying<T> {
137 /// Creates a new proof-carrying value.
138 ///
139 /// This should only be called after successful verification.
140 #[doc(hidden)]
141 pub fn new_unchecked(value: T) -> Self {
142 Self {
143 value,
144 _proof: PhantomData,
145 }
146 }
147
148 /// Extracts the inner value, consuming the proof.
149 pub fn into_inner(self) -> T {
150 self.value
151 }
152}
153
154impl<T: Clone> Clone for ProofCarrying<T> {
155 fn clone(&self) -> Self {
156 Self {
157 value: self.value.clone(),
158 _proof: PhantomData,
159 }
160 }
161}
162
163/// Error type for verified annexation operations.
164#[derive(Debug, Clone, PartialEq, Eq)]
165pub enum AnnexError {
166 /// Resource is already under foreign jurisdiction.
167 AlreadyExiled,
168 /// SMT verification failed.
169 VerificationFailed(String),
170 /// Prover encountered an error.
171 ProverError(String),
172}
173
174impl std::fmt::Display for AnnexError {
175 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
176 match self {
177 AnnexError::AlreadyExiled => write!(f, "Resource is already under foreign jurisdiction"),
178 AnnexError::VerificationFailed(msg) => write!(f, "Verification failed: {}", msg),
179 AnnexError::ProverError(msg) => write!(f, "Prover error: {}", msg),
180 }
181 }
182}
183
184impl std::error::Error for AnnexError {}
185
186/// Error returned when a lease operation fails.
187#[derive(Debug, Clone, PartialEq, Eq)]
188pub enum LeaseError {
189 /// Resource is already leased to another holder.
190 AlreadyLeased,
191 /// Resource is under foreign jurisdiction.
192 ForeignJurisdiction,
193}
194
195/// Represents a lease on a Sovereign resource.
196pub struct Lease<T> {
197 /// The holder's unique identifier.
198 pub holder: u128,
199 /// Duration of the lease.
200 pub duration: std::time::Duration,
201 /// Phantom data for the resource type.
202 _phantom: PhantomData<T>,
203}
204
205impl<T> Lease<T> {
206 /// Creates a new lease.
207 pub fn new(holder: u128, duration: std::time::Duration) -> Self {
208 Self {
209 holder,
210 duration,
211 _phantom: PhantomData,
212 }
213 }
214}
215
216/// Trait for distributed borrow operations.
217pub trait DistributedBorrow<T> {
218 /// Attempt to acquire a lease on the resource.
219 fn try_hire(&self, candidate_id: u128, term: std::time::Duration) -> Result<Lease<T>, LeaseError>;
220}
221
222impl<T> DistributedBorrow<T> for Sovereign<T> {
223 fn try_hire(&self, candidate_id: u128, term: std::time::Duration) -> Result<Lease<T>, LeaseError> {
224 let current = self.state.load(Ordering::SeqCst);
225 if current == SovereignState::Exiled as u8 {
226 return Err(LeaseError::AlreadyLeased);
227 }
228
229 // Transition to exiled state (leased)
230 self.state.store(SovereignState::Exiled as u8, Ordering::SeqCst);
231 Ok(Lease::new(candidate_id, term))
232 }
233}
234
235/// Extension trait for Sovereign types whose inner types implement formal verification.
236///
237/// This trait is automatically implemented for `Sovereign<T>` where `T` can be
238/// formally verified via the Garuda Proof System.
239pub trait VerifiedAnnex<T> {
240 /// Annexes the resource after successful formal verification.
241 ///
242 /// Unlike `annex()`, this method requires mathematical proof that all
243 /// invariants are satisfied before the state transition occurs.
244 ///
245 /// # Returns
246 ///
247 /// - `Ok(ProofCarrying<()>)` - Verification passed, resource is now Exiled
248 /// - `Err(AnnexError)` - Verification failed or resource already Exiled
249 ///
250 /// # Example
251 ///
252 /// ```ignore
253 /// use praborrow_core::{Sovereign, VerifiedAnnex};
254 ///
255 /// let resource = Sovereign::new(MyVerifiableStruct { balance: 100 });
256 ///
257 /// // This will run SMT verification before annexing
258 /// match resource.annex_verified() {
259 /// Ok(proof) => println!("Annexation proven safe!"),
260 /// Err(e) => println!("Cannot annex: {}", e),
261 /// }
262 /// ```
263 fn annex_verified(&self) -> Result<ProofCarrying<()>, AnnexError>;
264}
265
266// Note: The actual implementation of VerifiedAnnex requires praborrow-prover,
267// which would create a circular dependency. Instead, the implementation is
268// provided via blanket impl in praborrow-prover or via the facade crate.
269//
270// Users should use the `praborrow` facade crate for full functionality.
271
272#[cfg(test)]
273mod tests {
274 use super::*;
275
276 #[test]
277 fn test_sovereign_new() {
278 let s = Sovereign::new(42i32);
279 assert_eq!(s.state(), SovereignState::Domestic);
280 }
281
282 #[test]
283 fn test_sovereign_deref() {
284 let s = Sovereign::new(42i32);
285 assert_eq!(*s, 42);
286 }
287
288 #[test]
289 fn test_sovereign_deref_mut() {
290 let mut s = Sovereign::new(42i32);
291 *s = 100;
292 assert_eq!(*s, 100);
293 }
294
295 #[test]
296 fn test_sovereign_annex() {
297 let s = Sovereign::new(42i32);
298 assert!(s.annex().is_ok());
299 assert_eq!(s.state(), SovereignState::Exiled);
300 }
301
302 #[test]
303 fn test_sovereign_double_annex() {
304 let s = Sovereign::new(42i32);
305 assert!(s.annex().is_ok());
306 assert!(s.annex().is_err());
307 }
308
309 #[test]
310 #[should_panic(expected = "SOVEREIGNTY VIOLATION")]
311 fn test_sovereignty_violation() {
312 let s = Sovereign::new(42i32);
313 s.annex().unwrap();
314 let _ = *s; // This should panic
315 }
316
317 #[test]
318 fn test_proof_carrying() {
319 let proof = ProofCarrying::new_unchecked(42i32);
320 assert_eq!(proof.value, 42);
321 assert_eq!(proof.into_inner(), 42);
322 }
323
324 #[test]
325 fn test_annex_error_display() {
326 let e = AnnexError::AlreadyExiled;
327 assert!(e.to_string().contains("foreign jurisdiction"));
328
329 let e = AnnexError::VerificationFailed("test".to_string());
330 assert!(e.to_string().contains("test"));
331 }
332}