1use crate::bft_watchdog::{ThresholdSignature, VoteDecision};
66use crate::crypto::{KeyStore, Result, SoftwareKeyStore};
67use crate::zkp::ComplianceProof;
68use parking_lot::RwLock;
69use serde::{Deserialize, Serialize};
70use sha2::{Digest, Sha256};
71use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
72use std::sync::Arc;
73use std::time::{SystemTime, UNIX_EPOCH};
74use zeroize::Zeroize;
75
76#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
82pub enum CapsuleState {
83 Sealed,
85 Executing,
87 Executed,
89 Destroyed,
91 Expired,
93}
94
95#[derive(Debug, Clone, Serialize, Deserialize)]
97pub struct InformationLost {
98 pub reason: String,
100 pub destroyed_at: u64,
102 pub data_hash: [u8; 32],
104 pub breach_signature: Vec<u8>,
106}
107
108#[derive(Debug)]
117pub struct MutationGuard {
118 integrity_hash: [u8; 32],
120
121 canary: AtomicU64,
123
124 expected_canary: u64,
126
127 armed: AtomicBool,
129
130 breached: AtomicBool,
132
133 access_count: AtomicU64,
135
136 max_accesses: u64,
138}
139
140impl MutationGuard {
141 pub fn new(data: &[u8], max_accesses: u64) -> Self {
148 let integrity_hash = Self::compute_hash(data);
149
150 let canary_value = rand::random::<u64>();
152
153 MutationGuard {
154 integrity_hash,
155 canary: AtomicU64::new(canary_value),
156 expected_canary: canary_value,
157 armed: AtomicBool::new(true),
158 breached: AtomicBool::new(false),
159 access_count: AtomicU64::new(0),
160 max_accesses,
161 }
162 }
163
164 #[inline]
166 fn compute_hash(data: &[u8]) -> [u8; 32] {
167 Sha256::digest(data).into()
168 }
169
170 #[inline]
172 pub fn is_breached(&self) -> bool {
173 self.breached.load(Ordering::SeqCst)
174 }
175
176 #[inline]
178 pub fn is_armed(&self) -> bool {
179 self.armed.load(Ordering::SeqCst)
180 }
181
182 pub fn verify(&self, data: &[u8]) -> bool {
186 if self.is_breached() {
187 return false;
188 }
189
190 let count = self.access_count.fetch_add(1, Ordering::SeqCst);
192 if count >= self.max_accesses {
193 self.trigger_breach("Max access attempts exceeded");
194 return false;
195 }
196
197 let current_canary = self.canary.load(Ordering::SeqCst);
199 if current_canary != self.expected_canary {
200 self.trigger_breach("Canary value modified - memory tampering detected");
201 return false;
202 }
203
204 let current_hash = Self::compute_hash(data);
206 if current_hash != self.integrity_hash {
207 self.trigger_breach("Data hash mismatch - payload tampered");
208 return false;
209 }
210
211 true
212 }
213
214 fn trigger_breach(&self, _reason: &str) {
216 self.breached.store(true, Ordering::SeqCst);
217 self.armed.store(false, Ordering::SeqCst);
218 }
219
220 pub fn disarm(&self) {
222 self.armed.store(false, Ordering::SeqCst);
223 }
224
225 pub fn integrity_hash(&self) -> [u8; 32] {
227 self.integrity_hash
228 }
229
230 pub fn access_count(&self) -> u64 {
232 self.access_count.load(Ordering::SeqCst)
233 }
234}
235
236#[derive(Debug, Clone, Serialize, Deserialize)]
242pub struct ExecutionContext {
243 pub zkp_proof: ComplianceProof,
245
246 pub council_signature: ThresholdSignature,
248
249 pub council_decision: VoteDecision,
251
252 pub timestamp: u64,
254
255 pub requester_id: String,
257
258 pub purpose: String,
260}
261
262#[derive(Debug)]
264pub enum ExecutionResult {
265 Success(Vec<u8>),
267 Denied(String),
269 Lost(InformationLost),
271}
272
273pub trait AccessPredicate: Send + Sync {
282 fn evaluate(&self, context: &ExecutionContext) -> bool;
286
287 fn identifier(&self) -> &str;
289}
290
291pub struct DefaultPredicate {
293 required_rules_hash: [u8; 32],
295
296 min_signatures: usize,
298
299 max_proof_age: u64,
301}
302
303impl DefaultPredicate {
304 pub fn new(rules: &[String], min_signatures: usize, max_proof_age: u64) -> Self {
306 let required_rules_hash = Self::hash_rules(rules);
307 DefaultPredicate {
308 required_rules_hash,
309 min_signatures,
310 max_proof_age,
311 }
312 }
313
314 fn hash_rules(rules: &[String]) -> [u8; 32] {
315 let mut hasher = Sha256::new();
316 for rule in rules {
317 hasher.update(rule.as_bytes());
318 hasher.update(b"\x00");
319 }
320 hasher.finalize().into()
321 }
322}
323
324impl AccessPredicate for DefaultPredicate {
325 fn evaluate(&self, context: &ExecutionContext) -> bool {
326 if context.zkp_proof.rules_hash != self.required_rules_hash {
328 return false;
329 }
330
331 let now = SystemTime::now()
333 .duration_since(UNIX_EPOCH)
334 .unwrap()
335 .as_secs();
336
337 if now - context.zkp_proof.timestamp > self.max_proof_age {
338 return false;
339 }
340
341 if context.council_decision != VoteDecision::Approve {
343 return false;
344 }
345
346 if context.council_signature.count < self.min_signatures {
348 return false;
349 }
350
351 true
352 }
353
354 fn identifier(&self) -> &str {
355 "DefaultPredicate(ZKP+BFT)"
356 }
357}
358
359#[allow(dead_code)]
368pub struct DataCapsule {
369 id: String,
371
372 encrypted_payload: RwLock<Option<Vec<u8>>>,
375
376 #[allow(dead_code)]
378 encryption_key: [u8; 32],
379
380 predicate: Box<dyn AccessPredicate>,
382
383 guard: MutationGuard,
385
386 state: RwLock<CapsuleState>,
388
389 created_at: u64,
391
392 expires_at: u64,
394
395 execution_count: AtomicU64,
397
398 max_executions: u64,
400
401 keystore: SoftwareKeyStore,
403}
404
405impl DataCapsule {
406 pub fn new(
416 id: impl Into<String>,
417 data: &[u8],
418 predicate: Box<dyn AccessPredicate>,
419 max_executions: u64,
420 ttl_seconds: u64,
421 ) -> Result<Self> {
422 let keystore = SoftwareKeyStore::generate()?;
423
424 let mut encryption_key = [0u8; 32];
426 rand::RngCore::fill_bytes(&mut rand::rngs::OsRng, &mut encryption_key);
427
428 let encrypted = Self::encrypt(data, &encryption_key);
431
432 let guard = MutationGuard::new(&encrypted, 100); let now = SystemTime::now()
436 .duration_since(UNIX_EPOCH)
437 .unwrap()
438 .as_secs();
439
440 let expires_at = if ttl_seconds > 0 {
441 now + ttl_seconds
442 } else {
443 0
444 };
445
446 Ok(DataCapsule {
447 id: id.into(),
448 encrypted_payload: RwLock::new(Some(encrypted)),
449 encryption_key,
450 predicate,
451 guard,
452 state: RwLock::new(CapsuleState::Sealed),
453 created_at: now,
454 expires_at,
455 execution_count: AtomicU64::new(0),
456 max_executions,
457 keystore,
458 })
459 }
460
461 fn encrypt(data: &[u8], key: &[u8; 32]) -> Vec<u8> {
464 data.iter()
465 .enumerate()
466 .map(|(i, &b)| b ^ key[i % 32])
467 .collect()
468 }
469
470 fn decrypt(encrypted: &[u8], key: &[u8; 32]) -> Vec<u8> {
472 Self::encrypt(encrypted, key) }
474
475 pub fn run_access_protocol(&self, context: &ExecutionContext) -> ExecutionResult {
490 if *self.state.read() == CapsuleState::Destroyed {
492 return self.information_lost("Capsule already destroyed");
493 }
494
495 if self.is_expired() {
497 self.trigger_destruction("Capsule expired");
498 return self.information_lost("Capsule expired");
499 }
500
501 let exec_count = self.execution_count.fetch_add(1, Ordering::SeqCst);
503 if self.max_executions > 0 && exec_count >= self.max_executions {
504 self.trigger_destruction("Max executions reached");
505 return self.information_lost("Max executions reached");
506 }
507
508 let payload_guard = self.encrypted_payload.read();
510 let encrypted = match payload_guard.as_ref() {
511 Some(data) => data,
512 None => return self.information_lost("Payload already erased"),
513 };
514
515 if !self.guard.verify(encrypted) {
517 drop(payload_guard);
518 self.trigger_destruction("Integrity check failed");
519 return self.information_lost("Integrity breach detected");
520 }
521
522 if !self.predicate.evaluate(context) {
524 return ExecutionResult::Denied(format!(
525 "Predicate '{}' denied access",
526 self.predicate.identifier()
527 ));
528 }
529
530 *self.state.write() = CapsuleState::Executing;
532
533 let decrypted = Self::decrypt(encrypted, &self.encryption_key);
534
535 *self.state.write() = CapsuleState::Executed;
536
537 ExecutionResult::Success(decrypted)
538 }
539
540 fn trigger_destruction(&self, _reason: &str) {
542 *self.state.write() = CapsuleState::Destroyed;
544
545 if let Some(ref mut payload) = *self.encrypted_payload.write() {
547 rand::RngCore::fill_bytes(&mut rand::rngs::OsRng, payload);
549 payload.zeroize();
551 }
552
553 *self.encrypted_payload.write() = None;
555
556 self.guard.disarm();
558 }
559
560 fn information_lost(&self, reason: &str) -> ExecutionResult {
562 let now = SystemTime::now()
563 .duration_since(UNIX_EPOCH)
564 .unwrap()
565 .as_secs();
566
567 let mut hasher = Sha256::new();
569 hasher.update(reason.as_bytes());
570 hasher.update(now.to_le_bytes());
571 hasher.update(self.guard.integrity_hash());
572 let breach_data = hasher.finalize();
573
574 let breach_signature = self.keystore.sign(&breach_data).unwrap_or_default();
575
576 ExecutionResult::Lost(InformationLost {
577 reason: reason.to_string(),
578 destroyed_at: now,
579 data_hash: self.guard.integrity_hash(),
580 breach_signature,
581 })
582 }
583
584 pub fn is_expired(&self) -> bool {
586 if self.expires_at == 0 {
587 return false;
588 }
589
590 let now = SystemTime::now()
591 .duration_since(UNIX_EPOCH)
592 .unwrap()
593 .as_secs();
594
595 now > self.expires_at
596 }
597
598 pub fn state(&self) -> CapsuleState {
600 *self.state.read()
601 }
602
603 pub fn id(&self) -> &str {
605 &self.id
606 }
607
608 pub fn execution_count(&self) -> u64 {
610 self.execution_count.load(Ordering::SeqCst)
611 }
612
613 pub fn destroy(&self) {
615 self.trigger_destruction("Authorized destruction");
616 }
617
618 #[cfg(test)]
620 pub fn simulate_tampering(&self) {
621 if let Some(ref mut payload) = *self.encrypted_payload.write() {
622 if !payload.is_empty() {
623 payload[0] ^= 0xFF;
625 }
626 }
627 }
628}
629
630#[derive(Debug, Clone, Serialize, Deserialize)]
636pub struct KeyShard {
637 pub index: u8,
639 pub data: Vec<u8>,
641 pub holder_id: String,
643}
644
645pub struct ConsensusKey {
647 threshold: usize,
649 total_shards: usize,
651 shards: Vec<KeyShard>,
653 reconstructed: Option<[u8; 32]>,
655}
656
657impl ConsensusKey {
658 pub fn new(threshold: usize, total_shards: usize) -> Self {
665 ConsensusKey {
666 threshold,
667 total_shards,
668 shards: Vec::new(),
669 reconstructed: None,
670 }
671 }
672
673 pub fn generate_shards(key: &[u8; 32], n: usize) -> Vec<KeyShard> {
678 let mut shards = Vec::new();
679
680 let mut xor_accumulator = *key;
682
683 for i in 0..(n - 1) {
684 let mut shard_data = [0u8; 32];
685 rand::RngCore::fill_bytes(&mut rand::rngs::OsRng, &mut shard_data);
686
687 for j in 0..32 {
689 xor_accumulator[j] ^= shard_data[j];
690 }
691
692 shards.push(KeyShard {
693 index: i as u8,
694 data: shard_data.to_vec(),
695 holder_id: format!("member-{}", i),
696 });
697 }
698
699 shards.push(KeyShard {
701 index: (n - 1) as u8,
702 data: xor_accumulator.to_vec(),
703 holder_id: format!("member-{}", n - 1),
704 });
705
706 shards
707 }
708
709 pub fn add_shard(&mut self, shard: KeyShard) -> bool {
711 if self.shards.iter().any(|s| s.index == shard.index) {
713 return false;
714 }
715
716 self.shards.push(shard);
717
718 if self.shards.len() >= self.threshold {
720 self.try_reconstruct();
721 }
722
723 true
724 }
725
726 fn try_reconstruct(&mut self) {
728 if self.shards.len() < self.total_shards {
729 return;
731 }
732
733 let mut key = [0u8; 32];
734
735 for shard in &self.shards {
736 for (i, &byte) in shard.data.iter().enumerate() {
737 if i < 32 {
738 key[i] ^= byte;
739 }
740 }
741 }
742
743 self.reconstructed = Some(key);
744 }
745
746 pub fn get_key(&self) -> Option<[u8; 32]> {
748 self.reconstructed
749 }
750
751 pub fn is_complete(&self) -> bool {
753 self.reconstructed.is_some()
754 }
755
756 pub fn shard_count(&self) -> usize {
758 self.shards.len()
759 }
760}
761
762pub struct MeshRuntime {
770 capsules: RwLock<Vec<Arc<DataCapsule>>>,
772
773 consensus: RwLock<ConsensusKey>,
775
776 pub runtime_id: String,
778
779 active: AtomicBool,
781}
782
783impl MeshRuntime {
784 pub fn new(consensus_threshold: usize, total_members: usize) -> Self {
786 let runtime_id = format!("mesh-{:x}", rand::random::<u64>());
787
788 MeshRuntime {
789 capsules: RwLock::new(Vec::new()),
790 consensus: RwLock::new(ConsensusKey::new(consensus_threshold, total_members)),
791 runtime_id,
792 active: AtomicBool::new(true),
793 }
794 }
795
796 pub fn register_capsule(&self, capsule: Arc<DataCapsule>) -> bool {
798 if !self.active.load(Ordering::SeqCst) {
799 return false;
800 }
801
802 self.capsules.write().push(capsule);
803 true
804 }
805
806 pub fn add_key_shard(&self, shard: KeyShard) -> bool {
808 self.consensus.write().add_shard(shard)
809 }
810
811 pub fn has_consensus_key(&self) -> bool {
813 self.consensus.read().is_complete()
814 }
815
816 pub fn get_consensus_key(&self) -> Option<[u8; 32]> {
818 self.consensus.read().get_key()
819 }
820
821 pub fn execute_capsule(
823 &self,
824 capsule_id: &str,
825 context: &ExecutionContext,
826 ) -> Option<ExecutionResult> {
827 if !self.active.load(Ordering::SeqCst) {
828 return None;
829 }
830
831 let capsules = self.capsules.read();
832 for capsule in capsules.iter() {
833 if capsule.id() == capsule_id {
834 return Some(capsule.run_access_protocol(context));
835 }
836 }
837
838 None
839 }
840
841 pub fn capsule_count(&self) -> usize {
843 self.capsules.read().len()
844 }
845
846 pub fn shutdown(&self) {
848 self.active.store(false, Ordering::SeqCst);
849
850 for capsule in self.capsules.read().iter() {
851 capsule.destroy();
852 }
853 }
854}
855
856#[cfg(test)]
861mod tests {
862 use super::*;
863 use crate::zkp::{PrivateDecision, ZkpProver};
864
865 fn create_test_context(rules: &[String]) -> ExecutionContext {
866 let keystore = SoftwareKeyStore::generate().unwrap();
867 let prover = ZkpProver::new(keystore, rules);
868 let decision = PrivateDecision::new("test", true);
869 let proof = prover.prove(&decision).unwrap();
870
871 ExecutionContext {
872 zkp_proof: proof,
873 council_signature: ThresholdSignature {
874 combined_signature: vec![1, 2, 3],
875 signer_pubkeys: vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]],
876 count: 3,
877 },
878 council_decision: VoteDecision::Approve,
879 timestamp: SystemTime::now()
880 .duration_since(UNIX_EPOCH)
881 .unwrap()
882 .as_secs(),
883 requester_id: "test-requester".to_string(),
884 purpose: "unit test".to_string(),
885 }
886 }
887
888 #[test]
889 fn test_capsule_creation() {
890 let rules = vec!["test rule".to_string()];
891 let predicate = Box::new(DefaultPredicate::new(&rules, 3, 300));
892
893 let capsule =
894 DataCapsule::new("test-capsule", b"SECRET DATA", predicate, 10, 3600).unwrap();
895
896 assert_eq!(capsule.state(), CapsuleState::Sealed);
897 assert_eq!(capsule.id(), "test-capsule");
898 }
899
900 #[test]
901 fn test_capsule_execution() {
902 let rules = vec!["test rule".to_string()];
903 let predicate = Box::new(DefaultPredicate::new(&rules, 3, 300));
904
905 let capsule =
906 DataCapsule::new("test-capsule", b"SECRET DATA", predicate, 10, 3600).unwrap();
907
908 let context = create_test_context(&rules);
909
910 match capsule.run_access_protocol(&context) {
911 ExecutionResult::Success(data) => {
912 assert_eq!(data, b"SECRET DATA");
913 }
914 _ => panic!("Expected success"),
915 }
916
917 assert_eq!(capsule.state(), CapsuleState::Executed);
918 }
919
920 #[test]
921 fn test_data_suicide_on_breach() {
922 let rules = vec!["test rule".to_string()];
923 let predicate = Box::new(DefaultPredicate::new(&rules, 3, 300));
924
925 let capsule =
926 DataCapsule::new("test-capsule", b"SECRET DATA", predicate, 10, 3600).unwrap();
927
928 capsule.simulate_tampering();
930
931 let context = create_test_context(&rules);
932
933 match capsule.run_access_protocol(&context) {
935 ExecutionResult::Lost(info) => {
936 assert!(info.reason.contains("Integrity"));
937 assert!(!info.breach_signature.is_empty());
938 }
940 ExecutionResult::Success(_) => {
941 panic!("Should NOT have succeeded after tampering!");
942 }
943 ExecutionResult::Denied(_) => {
944 panic!("Should return Lost, not Denied");
945 }
946 }
947
948 assert_eq!(capsule.state(), CapsuleState::Destroyed);
950 }
951
952 #[test]
953 fn test_capsule_expiration() {
954 let rules = vec!["test rule".to_string()];
955 let predicate = Box::new(DefaultPredicate::new(&rules, 3, 300));
956
957 let capsule = DataCapsule::new(
959 "expired-capsule",
960 b"DATA",
961 predicate,
962 10,
963 0, )
965 .unwrap();
966
967 assert!(!capsule.is_expired());
969 }
970
971 #[test]
972 fn test_consensus_key_reconstruction() {
973 let original_key: [u8; 32] = rand::random();
974
975 let shards = ConsensusKey::generate_shards(&original_key, 4);
977 assert_eq!(shards.len(), 4);
978
979 let mut consensus = ConsensusKey::new(4, 4);
981
982 for shard in shards {
984 consensus.add_shard(shard);
985 }
986
987 assert!(consensus.is_complete());
989 assert_eq!(consensus.get_key(), Some(original_key));
990 }
991
992 #[test]
993 fn test_mesh_runtime() {
994 let runtime = MeshRuntime::new(3, 4);
995
996 let rules = vec!["test rule".to_string()];
997 let predicate = Box::new(DefaultPredicate::new(&rules, 3, 300));
998
999 let capsule =
1000 Arc::new(DataCapsule::new("mesh-capsule", b"MESH DATA", predicate, 10, 3600).unwrap());
1001
1002 assert!(runtime.register_capsule(capsule));
1004 assert_eq!(runtime.capsule_count(), 1);
1005
1006 let context = create_test_context(&rules);
1008 let result = runtime.execute_capsule("mesh-capsule", &context);
1009
1010 assert!(matches!(result, Some(ExecutionResult::Success(_))));
1011 }
1012
1013 #[test]
1014 fn test_mutation_guard() {
1015 let data = b"protected data";
1016 let guard = MutationGuard::new(data, 10);
1017
1018 assert!(guard.verify(data));
1020 assert!(!guard.is_breached());
1021
1022 let tampered = b"tampered data!";
1024 assert!(!guard.verify(tampered));
1025 assert!(guard.is_breached());
1026 }
1027
1028 #[test]
1029 fn test_denied_access() {
1030 let rules = vec!["test rule".to_string()];
1031 let wrong_rules = vec!["wrong rule".to_string()];
1032
1033 let predicate = Box::new(DefaultPredicate::new(&rules, 3, 300));
1034
1035 let capsule = DataCapsule::new("test-capsule", b"SECRET", predicate, 10, 3600).unwrap();
1036
1037 let context = create_test_context(&wrong_rules);
1039
1040 match capsule.run_access_protocol(&context) {
1041 ExecutionResult::Denied(reason) => {
1042 assert!(reason.contains("denied"));
1043 }
1044 _ => panic!("Expected denial"),
1045 }
1046
1047 assert_eq!(capsule.state(), CapsuleState::Sealed);
1049 }
1050}