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