Skip to main content

oxilean_std/distributed_systems_theory/
functions.rs

1//! Auto-generated module
2//!
3//! ๐Ÿค– Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4#![allow(clippy::items_after_test_module)]
5
6use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
7use std::collections::{HashMap, HashSet, VecDeque};
8
9use super::types::{
10    ByzantineFaultTolerance, CAPClass, CAPProperty, CAPTheorem, ConsistencyLevel, FLPImpossibility,
11    GCounter, LamportClock, LamportTimestamp, PNCounter, PaxosAcceptor, PaxosProtocol, RaftNode,
12    RaftProtocol, RaftRole, ThreePCParticipant, TwoPCOutcome, TwoPCParticipant, TwoPCState,
13    TwoPSet, VectorClock,
14};
15
16pub fn app(f: Expr, a: Expr) -> Expr {
17    Expr::App(Box::new(f), Box::new(a))
18}
19pub fn app2(f: Expr, a: Expr, b: Expr) -> Expr {
20    app(app(f, a), b)
21}
22pub fn app3(f: Expr, a: Expr, b: Expr, c: Expr) -> Expr {
23    app(app2(f, a, b), c)
24}
25pub fn cst(s: &str) -> Expr {
26    Expr::Const(Name::str(s), vec![])
27}
28pub fn prop() -> Expr {
29    Expr::Sort(Level::zero())
30}
31pub fn type0() -> Expr {
32    Expr::Sort(Level::succ(Level::zero()))
33}
34pub fn pi(bi: BinderInfo, name: &str, dom: Expr, body: Expr) -> Expr {
35    Expr::Pi(bi, Name::str(name), Box::new(dom), Box::new(body))
36}
37pub fn arrow(a: Expr, b: Expr) -> Expr {
38    pi(BinderInfo::Default, "_", a, b)
39}
40pub fn bvar(n: u32) -> Expr {
41    Expr::BVar(n)
42}
43pub fn nat_ty() -> Expr {
44    cst("Nat")
45}
46pub fn bool_ty() -> Expr {
47    cst("Bool")
48}
49pub fn real_ty() -> Expr {
50    cst("Real")
51}
52pub fn list_ty(elem: Expr) -> Expr {
53    app(cst("List"), elem)
54}
55/// `DistributedSystem : Nat โ†’ Prop` โ€” a system with n nodes
56pub fn distributed_system_ty() -> Expr {
57    arrow(nat_ty(), prop())
58}
59/// `CAPConsistency : Prop โ†’ Prop` โ€” system satisfies strong consistency
60pub fn cap_consistency_ty() -> Expr {
61    arrow(prop(), prop())
62}
63/// `CAPAvailability : Prop โ†’ Prop` โ€” system satisfies availability
64pub fn cap_availability_ty() -> Expr {
65    arrow(prop(), prop())
66}
67/// `CAPPartitionTolerance : Prop โ†’ Prop` โ€” system tolerates network partitions
68pub fn cap_partition_tolerance_ty() -> Expr {
69    arrow(prop(), prop())
70}
71/// `CAPTheorem : Prop โ†’ Prop`
72/// No distributed system can simultaneously guarantee all three CAP properties.
73pub fn cap_theorem_ty() -> Expr {
74    arrow(prop(), prop())
75}
76/// `ConsensusProtocol : Nat โ†’ Prop` โ€” consensus protocol for n nodes
77pub fn consensus_protocol_ty() -> Expr {
78    arrow(nat_ty(), prop())
79}
80/// `PaxosProtocol : Nat โ†’ Nat โ†’ Prop` โ€” Paxos with n nodes and f fault tolerance
81pub fn paxos_protocol_ty() -> Expr {
82    arrow(nat_ty(), arrow(nat_ty(), prop()))
83}
84/// `RaftProtocol : Nat โ†’ Nat โ†’ Prop` โ€” Raft consensus protocol
85pub fn raft_protocol_ty() -> Expr {
86    arrow(nat_ty(), arrow(nat_ty(), prop()))
87}
88/// `PBFTProtocol : Nat โ†’ Nat โ†’ Prop` โ€” Practical Byzantine Fault Tolerance
89pub fn pbft_protocol_ty() -> Expr {
90    arrow(nat_ty(), arrow(nat_ty(), prop()))
91}
92/// `ByzantineFaultTolerance : Prop โ†’ Nat โ†’ Prop`
93/// Protocol P tolerates up to f Byzantine faults.
94pub fn byzantine_fault_tolerance_ty() -> Expr {
95    arrow(prop(), arrow(nat_ty(), prop()))
96}
97/// `AtomicBroadcast : Prop โ†’ Prop` โ€” total-order multicast
98pub fn atomic_broadcast_ty() -> Expr {
99    arrow(prop(), prop())
100}
101/// `VectorClock : Nat โ†’ Prop` โ€” vector clock for n processes
102pub fn vector_clock_ty() -> Expr {
103    arrow(nat_ty(), prop())
104}
105/// `LamportTimestamp : Prop โ†’ Nat` โ€” Lamport logical timestamp of event
106pub fn lamport_timestamp_ty() -> Expr {
107    arrow(prop(), nat_ty())
108}
109/// `CausallyPrecedes : Prop โ†’ Prop โ†’ Prop` โ€” happens-before relation
110pub fn causally_precedes_ty() -> Expr {
111    arrow(prop(), arrow(prop(), prop()))
112}
113/// `CRDT : Prop โ†’ Prop` โ€” a Conflict-free Replicated Data Type
114pub fn crdt_ty() -> Expr {
115    arrow(prop(), prop())
116}
117/// `StateBasedCRDT : Prop โ†’ Prop` โ€” state-based (convergent) CRDT
118pub fn state_based_crdt_ty() -> Expr {
119    arrow(prop(), prop())
120}
121/// `OpBasedCRDT : Prop โ†’ Prop` โ€” operation-based (commutative) CRDT
122pub fn op_based_crdt_ty() -> Expr {
123    arrow(prop(), prop())
124}
125/// `EventualConsistency : Prop โ†’ Prop`
126pub fn eventual_consistency_ty() -> Expr {
127    arrow(prop(), prop())
128}
129/// `StrongEventualConsistency : Prop โ†’ Prop`
130pub fn strong_eventual_consistency_ty() -> Expr {
131    arrow(prop(), prop())
132}
133/// `Linearizability : Prop โ†’ Prop` โ€” correctness condition for concurrent objects
134pub fn linearizability_ty() -> Expr {
135    arrow(prop(), prop())
136}
137/// `Serializability : Prop โ†’ Prop` โ€” correctness condition for transactions
138pub fn serializability_ty() -> Expr {
139    arrow(prop(), prop())
140}
141/// `StrictSerializability : Prop โ†’ Prop` โ€” serializability + real-time order
142pub fn strict_serializability_ty() -> Expr {
143    arrow(prop(), prop())
144}
145/// `TwoPhaseCommit : Nat โ†’ Prop` โ€” 2PC protocol with n participants
146pub fn two_phase_commit_ty() -> Expr {
147    arrow(nat_ty(), prop())
148}
149/// `ThreePhaseCommit : Nat โ†’ Prop` โ€” 3PC protocol (non-blocking)
150pub fn three_phase_commit_ty() -> Expr {
151    arrow(nat_ty(), prop())
152}
153/// `SafetyProperty : Prop โ†’ Prop` โ€” TLA+ style safety predicate
154pub fn safety_property_ty() -> Expr {
155    arrow(prop(), prop())
156}
157/// `LivenessProperty : Prop โ†’ Prop` โ€” TLA+ style liveness predicate
158pub fn liveness_property_ty() -> Expr {
159    arrow(prop(), prop())
160}
161/// `FLPImpossibility : Prop`
162/// In an asynchronous system with even one crash failure, consensus is impossible.
163pub fn flp_impossibility_ty() -> Expr {
164    prop()
165}
166/// `FischerLynchPatersonThm : Prop โ†’ Prop`
167/// The FLP impossibility result.
168pub fn flp_theorem_ty() -> Expr {
169    arrow(prop(), prop())
170}
171/// `ByzantineGeneralsProblem : Nat โ†’ Nat โ†’ Prop`
172/// Byzantine Generals: n generals, f traitors; solvable iff n โ‰ฅ 3f+1.
173pub fn byzantine_generals_ty() -> Expr {
174    arrow(nat_ty(), arrow(nat_ty(), prop()))
175}
176/// `PaxosCorrectness : Prop โ†’ Prop` โ€” Paxos safety + liveness under benign failures
177pub fn paxos_correctness_ty() -> Expr {
178    arrow(prop(), prop())
179}
180/// `RaftLeaderElection : Prop โ†’ Prop` โ€” Raft elects at most one leader per term
181pub fn raft_leader_election_ty() -> Expr {
182    arrow(prop(), prop())
183}
184/// `VectorClockConsistency : Prop โ†’ Prop`
185/// Vector clocks characterize causal ordering exactly.
186pub fn vector_clock_consistency_ty() -> Expr {
187    arrow(prop(), prop())
188}
189/// Build the distributed systems theory environment.
190pub fn build_distributed_systems_env(env: &mut Environment) {
191    let axioms: &[(&str, Expr)] = &[
192        ("DistributedSystem", distributed_system_ty()),
193        ("CAPConsistency", cap_consistency_ty()),
194        ("CAPAvailability", cap_availability_ty()),
195        ("CAPPartitionTolerance", cap_partition_tolerance_ty()),
196        ("CAPTheorem", cap_theorem_ty()),
197        ("ConsensusProtocol", consensus_protocol_ty()),
198        ("PaxosProtocol", paxos_protocol_ty()),
199        ("RaftProtocol", raft_protocol_ty()),
200        ("PBFTProtocol", pbft_protocol_ty()),
201        ("ByzantineFaultTolerance", byzantine_fault_tolerance_ty()),
202        ("AtomicBroadcast", atomic_broadcast_ty()),
203        ("VectorClock", vector_clock_ty()),
204        ("LamportTimestamp", lamport_timestamp_ty()),
205        ("CausallyPrecedes", causally_precedes_ty()),
206        ("CRDT", crdt_ty()),
207        ("StateBasedCRDT", state_based_crdt_ty()),
208        ("OpBasedCRDT", op_based_crdt_ty()),
209        ("EventualConsistency", eventual_consistency_ty()),
210        (
211            "StrongEventualConsistency",
212            strong_eventual_consistency_ty(),
213        ),
214        ("Linearizability", linearizability_ty()),
215        ("Serializability", serializability_ty()),
216        ("StrictSerializability", strict_serializability_ty()),
217        ("TwoPhaseCommit", two_phase_commit_ty()),
218        ("ThreePhaseCommit", three_phase_commit_ty()),
219        ("SafetyProperty", safety_property_ty()),
220        ("LivenessProperty", liveness_property_ty()),
221        ("FLPImpossibility", flp_impossibility_ty()),
222        ("FLPTheorem", flp_theorem_ty()),
223        ("ByzantineGeneralsProblem", byzantine_generals_ty()),
224        ("PaxosCorrectness", paxos_correctness_ty()),
225        ("RaftLeaderElection", raft_leader_election_ty()),
226        ("VectorClockConsistency", vector_clock_consistency_ty()),
227        ("ProcessId", nat_ty()),
228        ("LogicalTime", nat_ty()),
229        ("Term", nat_ty()),
230        ("LogIndex", nat_ty()),
231        ("NodeState", arrow(nat_ty(), prop())),
232        ("MessageHistory", list_ty(prop())),
233        ("TransactionLog", list_ty(prop())),
234        ("PartitionEvent", prop()),
235    ];
236    for (name, ty) in axioms {
237        env.add(Declaration::Axiom {
238            name: Name::str(*name),
239            univ_params: vec![],
240            ty: ty.clone(),
241        })
242        .ok();
243    }
244}
245/// Run a single round of Paxos with `acceptors`.
246///
247/// The proposer uses `proposal_number` and `proposed_value`.
248/// Returns `Some(decided_value)` if a quorum is reached, `None` otherwise.
249pub fn paxos_round(
250    acceptors: &mut Vec<PaxosAcceptor>,
251    proposal_number: u64,
252    proposed_value: u64,
253) -> Option<u64> {
254    let n = acceptors.len();
255    let quorum = n / 2 + 1;
256    let mut promises = Vec::new();
257    for acc in acceptors.iter_mut() {
258        if let Some(p) = acc.prepare(proposal_number) {
259            promises.push(p);
260        }
261    }
262    if promises.len() < quorum {
263        return None;
264    }
265    let value_to_propose = promises
266        .iter()
267        .filter(|(n, v)| *n > 0 && v.is_some())
268        .max_by_key(|(n, _)| *n)
269        .and_then(|(_, v)| *v)
270        .unwrap_or(proposed_value);
271    let mut accepts = 0;
272    for acc in acceptors.iter_mut() {
273        if acc.accept(proposal_number, value_to_propose) {
274            accepts += 1;
275        }
276    }
277    if accepts >= quorum {
278        Some(value_to_propose)
279    } else {
280        None
281    }
282}
283/// Run a full 2PC protocol.
284///
285/// Returns `Committed` if all participants vote yes, `Aborted` otherwise.
286pub fn two_phase_commit(participants: &mut Vec<TwoPCParticipant>) -> TwoPCOutcome {
287    let all_yes = participants.iter_mut().all(|p| p.prepare());
288    let outcome = if all_yes {
289        TwoPCOutcome::Committed
290    } else {
291        TwoPCOutcome::Aborted
292    };
293    for p in participants.iter_mut() {
294        p.decide(outcome == TwoPCOutcome::Committed);
295    }
296    outcome
297}
298/// Run a full 3PC protocol. Returns `true` if committed.
299pub fn three_phase_commit(participants: &mut Vec<ThreePCParticipant>) -> bool {
300    let all_yes = participants.iter_mut().all(|p| p.can_commit());
301    if !all_yes {
302        for p in participants.iter_mut() {
303            p.abort();
304        }
305        return false;
306    }
307    for p in participants.iter_mut() {
308        p.pre_commit();
309    }
310    for p in participants.iter_mut() {
311        p.do_commit();
312    }
313    true
314}
315/// Check if a system of `n` nodes can tolerate `f` Byzantine faults.
316///
317/// The classical result: need n โ‰ฅ 3f+1 for Byzantine agreement.
318pub fn can_tolerate_byzantine(n: usize, f: usize) -> bool {
319    n > 3 * f
320}
321/// Compute the maximum number of Byzantine faults tolerated by `n` nodes.
322pub fn max_byzantine_faults(n: usize) -> usize {
323    if n < 4 {
324        0
325    } else {
326        (n - 1) / 3
327    }
328}
329/// Check if FLP impossibility applies to the given system model.
330///
331/// FLP applies to asynchronous systems with at least 1 crash-faulty node.
332/// Returns `true` if consensus is impossible (async + crash-faulty).
333pub fn flp_impossibility(asynchronous: bool, n_faulty: usize) -> bool {
334    asynchronous && n_faulty >= 1
335}
336/// Given the chosen CAP properties, determine if the combination is achievable.
337///
338/// According to the CAP theorem, a distributed system can satisfy at most 2 of 3.
339/// Returns `true` if the combination is feasible.
340pub fn cap_feasible(properties: &HashSet<CAPProperty>) -> bool {
341    !(properties.contains(&CAPProperty::Consistency)
342        && properties.contains(&CAPProperty::Availability)
343        && properties.contains(&CAPProperty::PartitionTolerance))
344}
345/// Determine the CAP class from the set of supported properties.
346pub fn cap_classify(properties: &HashSet<CAPProperty>) -> Option<CAPClass> {
347    let c = properties.contains(&CAPProperty::Consistency);
348    let a = properties.contains(&CAPProperty::Availability);
349    let p = properties.contains(&CAPProperty::PartitionTolerance);
350    match (c, a, p) {
351        (true, false, true) => Some(CAPClass::CP),
352        (false, true, true) => Some(CAPClass::AP),
353        (true, true, false) => Some(CAPClass::CA),
354        _ => None,
355    }
356}
357#[cfg(test)]
358mod tests {
359    use super::*;
360    #[test]
361    fn test_lamport_clock() {
362        let mut c1 = LamportClock::new();
363        let mut c2 = LamportClock::new();
364        let t1 = c1.tick();
365        assert_eq!(t1, 1);
366        let t2 = c1.tick();
367        assert_eq!(t2, 2);
368        let t3 = c2.receive(t2);
369        assert_eq!(t3, 3, "After receiving t=2, c2 should be at max(0,2)+1 = 3");
370        let t4 = c2.tick();
371        assert_eq!(t4, 4);
372    }
373    #[test]
374    fn test_vector_clock_causality() {
375        let mut vc1 = VectorClock::new(0, 2);
376        let mut vc2 = VectorClock::new(1, 2);
377        vc1.tick();
378        vc2.receive(&vc1);
379        vc2.tick();
380        assert!(
381            vc1.causally_precedes(&vc2),
382            "vc1 should causally precede vc2"
383        );
384        assert!(
385            !vc2.causally_precedes(&vc1),
386            "vc2 should NOT causally precede vc1"
387        );
388        let mut vc3 = VectorClock::new(1, 2);
389        vc3.tick();
390        let vc1_copy = VectorClock {
391            clocks: vec![1, 0],
392            process_id: 0,
393        };
394        assert!(
395            vc1_copy.concurrent(&vc3),
396            "vc1=[1,0] and vc3=[0,1] should be concurrent"
397        );
398    }
399    #[test]
400    fn test_g_counter_crdt() {
401        let mut r0 = GCounter::new(0, 3);
402        let mut r1 = GCounter::new(1, 3);
403        let mut r2 = GCounter::new(2, 3);
404        r0.increment_by(5);
405        r1.increment_by(3);
406        r2.increment_by(2);
407        r0.merge(&r1);
408        r0.merge(&r2);
409        assert_eq!(r0.value(), 10, "G-Counter total should be 5+3+2=10");
410        r0.merge(&r1);
411        assert_eq!(r0.value(), 10, "G-Counter merge should be idempotent");
412    }
413    #[test]
414    fn test_pn_counter_crdt() {
415        let mut r0 = PNCounter::new(0, 2);
416        let mut r1 = PNCounter::new(1, 2);
417        r0.increment();
418        r0.increment();
419        r1.increment();
420        r1.decrement();
421        r0.merge(&r1);
422        assert_eq!(r0.value(), 2, "PN-Counter: 2 + 0 = 2");
423    }
424    #[test]
425    fn test_two_pset_crdt() {
426        let mut s1: TwoPSet<u32> = TwoPSet::new();
427        let mut s2: TwoPSet<u32> = TwoPSet::new();
428        s1.add(1u32);
429        s1.add(2u32);
430        s2.add(2u32);
431        s2.add(3u32);
432        s1.remove(2u32);
433        s1.merge(&s2);
434        assert!(s1.contains(&1u32), "1 should be present");
435        assert!(!s1.contains(&2u32), "2 was removed, should not be present");
436        assert!(s1.contains(&3u32), "3 should be present from s2");
437        s1.add(2u32);
438        assert!(!s1.contains(&2u32), "Cannot re-add tombstoned element");
439    }
440    #[test]
441    fn test_paxos_round() {
442        let mut acceptors: Vec<PaxosAcceptor> = (0..5).map(|_| PaxosAcceptor::new()).collect();
443        let result = paxos_round(&mut acceptors, 1, 42);
444        assert_eq!(
445            result,
446            Some(42),
447            "Paxos should decide value 42 with fresh acceptors"
448        );
449        let result2 = paxos_round(&mut acceptors, 2, 99);
450        assert!(result2.is_some(), "Second Paxos round should also decide");
451        assert_eq!(
452            result2,
453            Some(42),
454            "Paxos should preserve previously accepted value 42"
455        );
456    }
457    #[test]
458    fn test_raft_election() {
459        let n = 5;
460        let mut nodes: Vec<RaftNode> = (0..n).map(RaftNode::new).collect();
461        nodes[0].start_election();
462        assert_eq!(nodes[0].role, RaftRole::Candidate);
463        assert_eq!(nodes[0].current_term, 1);
464        let term = nodes[0].current_term;
465        let log_len = nodes[0].log.len();
466        for voter_id in 1..n {
467            let granted = nodes[voter_id].request_vote(0, term, log_len);
468            if granted {
469                let became_leader = nodes[0].receive_vote(voter_id, n);
470                if became_leader {
471                    break;
472                }
473            }
474        }
475        assert_eq!(
476            nodes[0].role,
477            RaftRole::Leader,
478            "Node 0 should win election with majority"
479        );
480    }
481    #[test]
482    fn test_two_phase_commit() {
483        let mut ps: Vec<TwoPCParticipant> =
484            (0..4).map(|i| TwoPCParticipant::new(i, true)).collect();
485        let outcome = two_phase_commit(&mut ps);
486        assert_eq!(outcome, TwoPCOutcome::Committed, "All-yes should commit");
487        assert!(ps.iter().all(|p| p.state == TwoPCState::Committed));
488        let mut ps2: Vec<TwoPCParticipant> = vec![
489            TwoPCParticipant::new(0, true),
490            TwoPCParticipant::new(1, false),
491            TwoPCParticipant::new(2, true),
492        ];
493        let outcome2 = two_phase_commit(&mut ps2);
494        assert_eq!(outcome2, TwoPCOutcome::Aborted, "One-no should abort");
495        assert!(ps2.iter().all(|p| p.state == TwoPCState::Aborted));
496    }
497    #[test]
498    fn test_cap_theorem() {
499        let cp: HashSet<CAPProperty> = [CAPProperty::Consistency, CAPProperty::PartitionTolerance]
500            .iter()
501            .cloned()
502            .collect();
503        assert!(cap_feasible(&cp), "CP should be feasible");
504        assert_eq!(cap_classify(&cp), Some(CAPClass::CP));
505        let all: HashSet<CAPProperty> = [
506            CAPProperty::Consistency,
507            CAPProperty::Availability,
508            CAPProperty::PartitionTolerance,
509        ]
510        .iter()
511        .cloned()
512        .collect();
513        assert!(!cap_feasible(&all), "All-three CAP should be infeasible");
514        assert_eq!(cap_classify(&all), None);
515    }
516    #[test]
517    fn test_byzantine_faults() {
518        assert!(
519            can_tolerate_byzantine(4, 1),
520            "4 nodes can tolerate 1 Byzantine fault"
521        );
522        assert!(
523            !can_tolerate_byzantine(3, 1),
524            "3 nodes cannot tolerate 1 Byzantine fault"
525        );
526        assert_eq!(
527            max_byzantine_faults(10),
528            3,
529            "10 nodes: max Byzantine faults = 3"
530        );
531        assert_eq!(
532            max_byzantine_faults(3),
533            0,
534            "3 nodes: cannot tolerate any Byzantine fault"
535        );
536        assert!(flp_impossibility(true, 1), "Async + 1 faulty: FLP applies");
537        assert!(
538            !flp_impossibility(false, 1),
539            "Sync system: FLP does not apply"
540        );
541    }
542    #[test]
543    fn test_consistency_levels() {
544        assert!(ConsistencyLevel::Linearizable.implies(ConsistencyLevel::Eventual));
545        assert!(ConsistencyLevel::Linearizable.implies(ConsistencyLevel::Causal));
546        assert!(!ConsistencyLevel::Eventual.implies(ConsistencyLevel::Causal));
547        assert_eq!(ConsistencyLevel::Linearizable.name(), "Linearizable");
548        assert_eq!(ConsistencyLevel::Eventual.name(), "Eventual");
549    }
550    #[test]
551    fn test_build_env() {
552        let mut env = Environment::new();
553        build_distributed_systems_env(&mut env);
554        assert!(env.get(&Name::str("PaxosProtocol")).is_some());
555        assert!(env.get(&Name::str("VectorClock")).is_some());
556        assert!(env.get(&Name::str("CAPTheorem")).is_some());
557        assert!(env.get(&Name::str("TwoPhaseCommit")).is_some());
558        assert!(env.get(&Name::str("FLPImpossibility")).is_some());
559    }
560}
561/// Build the distributed systems theory environment (alias for build_distributed_systems_env).
562pub fn build_env(env: &mut Environment) {
563    build_distributed_systems_env(env);
564}
565/// `FLPImpossibilityStrong : Nat โ†’ Prop`
566/// In any asynchronous model with โ‰ฅ1 crash failure, consensus on n nodes is impossible.
567pub fn dst_ext_flp_impossibility_strong_ty() -> Expr {
568    arrow(nat_ty(), prop())
569}
570/// `AsyncConsensusLowerBound : Nat โ†’ Nat โ†’ Prop`
571/// Any asynchronous consensus protocol must take ฮฉ(fยทlog n) message rounds.
572pub fn dst_ext_async_consensus_lower_bound_ty() -> Expr {
573    arrow(nat_ty(), arrow(nat_ty(), prop()))
574}
575/// `CrashFailureModel : Nat โ†’ Nat โ†’ Prop`
576/// System with n processes where at most f can crash.
577pub fn dst_ext_crash_failure_model_ty() -> Expr {
578    arrow(nat_ty(), arrow(nat_ty(), prop()))
579}
580/// `OmissionFailureModel : Nat โ†’ Nat โ†’ Prop`
581/// System where processes may omit sends/receives.
582pub fn dst_ext_omission_failure_model_ty() -> Expr {
583    arrow(nat_ty(), arrow(nat_ty(), prop()))
584}
585/// `TimedAsynchronousModel : Real โ†’ Real โ†’ Prop`
586/// Partially synchronous model with bounds on message delay.
587pub fn dst_ext_timed_async_model_ty() -> Expr {
588    arrow(real_ty(), arrow(real_ty(), prop()))
589}
590/// `PaxosSafety : Prop`
591/// Paxos never decides two different values (agreement property).
592pub fn dst_ext_paxos_safety_ty() -> Expr {
593    prop()
594}
595/// `PaxosLiveness : Nat โ†’ Prop`
596/// Paxos eventually decides a value when at most f < n/2 processes fail.
597pub fn dst_ext_paxos_liveness_ty() -> Expr {
598    arrow(nat_ty(), prop())
599}
600/// `MultiPaxos : Nat โ†’ Nat โ†’ Prop`
601/// Multi-Paxos protocol for replicated state machine with n replicas and f faults.
602pub fn dst_ext_multi_paxos_ty() -> Expr {
603    arrow(nat_ty(), arrow(nat_ty(), prop()))
604}
605/// `PaxosPhaseOneMessage : Nat โ†’ Prop`
606/// Paxos Phase 1 (Prepare/Promise) message type parametrized by ballot number.
607pub fn dst_ext_paxos_phase1_ty() -> Expr {
608    arrow(nat_ty(), prop())
609}
610/// `PaxosPhaseTwoMessage : Nat โ†’ Real โ†’ Prop`
611/// Paxos Phase 2 (Accept/Accepted) message type.
612pub fn dst_ext_paxos_phase2_ty() -> Expr {
613    arrow(nat_ty(), arrow(real_ty(), prop()))
614}
615/// `RaftLeaderUniqueness : Prop`
616/// In any given term, at most one leader is elected.
617pub fn dst_ext_raft_leader_uniqueness_ty() -> Expr {
618    prop()
619}
620/// `RaftLogMatching : Prop`
621/// If two logs have an entry with the same index and term, they agree on all prior entries.
622pub fn dst_ext_raft_log_matching_ty() -> Expr {
623    prop()
624}
625/// `RaftLeaderCompleteness : Prop`
626/// A committed log entry will always be present in all future leaders' logs.
627pub fn dst_ext_raft_leader_completeness_ty() -> Expr {
628    prop()
629}
630/// `RaftStateMachineSafety : Prop`
631/// All state machines apply the same commands in the same order.
632pub fn dst_ext_raft_state_machine_safety_ty() -> Expr {
633    prop()
634}
635/// `RaftMembershipChange : Nat โ†’ Nat โ†’ Prop`
636/// Joint consensus for cluster membership changes from n1 to n2 nodes.
637pub fn dst_ext_raft_membership_change_ty() -> Expr {
638    arrow(nat_ty(), arrow(nat_ty(), prop()))
639}
640/// `PBFTSafety : Nat โ†’ Prop`
641/// PBFT guarantees safety with n โ‰ฅ 3f+1 replicas and up to f Byzantine faults.
642pub fn dst_ext_pbft_safety_ty() -> Expr {
643    arrow(nat_ty(), prop())
644}
645/// `PBFTLiveness : Nat โ†’ Prop`
646/// PBFT guarantees liveness under weak synchrony assumptions.
647pub fn dst_ext_pbft_liveness_ty() -> Expr {
648    arrow(nat_ty(), prop())
649}
650/// `ThresholdSignature : Nat โ†’ Nat โ†’ Prop`
651/// (t, n)-threshold signature scheme: t-of-n parties must cooperate to sign.
652pub fn dst_ext_threshold_signature_ty() -> Expr {
653    arrow(nat_ty(), arrow(nat_ty(), prop()))
654}
655/// `ByzantineAgreement : Nat โ†’ Nat โ†’ Prop`
656/// Byzantine agreement with n generals and f traitors is solvable iff n โ‰ฅ 3f+1.
657pub fn dst_ext_byzantine_agreement_ty() -> Expr {
658    arrow(nat_ty(), arrow(nat_ty(), prop()))
659}
660/// `AuthenticatedByzantine : Nat โ†’ Nat โ†’ Prop`
661/// Byzantine agreement with digital signatures requires only n โ‰ฅ 2f+1.
662pub fn dst_ext_authenticated_byzantine_ty() -> Expr {
663    arrow(nat_ty(), arrow(nat_ty(), prop()))
664}
665/// `ConsistentHashing : Nat โ†’ Nat โ†’ Prop`
666/// Consistent hashing ring with n virtual nodes and k keys.
667pub fn dst_ext_consistent_hashing_ty() -> Expr {
668    arrow(nat_ty(), arrow(nat_ty(), prop()))
669}
670/// `ConsistentHashingBalance : Nat โ†’ Real โ†’ Prop`
671/// Expected load per node is (1/n) ยฑ ฮต with high probability.
672pub fn dst_ext_consistent_hashing_balance_ty() -> Expr {
673    arrow(nat_ty(), arrow(real_ty(), prop()))
674}
675/// `DHTChord : Nat โ†’ Prop`
676/// Chord DHT with identifier space 2^n, O(log n) lookup hops.
677pub fn dst_ext_dht_chord_ty() -> Expr {
678    arrow(nat_ty(), prop())
679}
680/// `DHTKademlia : Nat โ†’ Prop`
681/// Kademlia DHT using XOR metric for routing table.
682pub fn dst_ext_dht_kademlia_ty() -> Expr {
683    arrow(nat_ty(), prop())
684}
685/// `DHTLookupComplexity : Nat โ†’ Prop`
686/// Any DHT lookup terminates in O(log n) steps for n nodes.
687pub fn dst_ext_dht_lookup_complexity_ty() -> Expr {
688    arrow(nat_ty(), prop())
689}
690/// `EventualConsistencyConvergence : Real โ†’ Prop`
691/// After quiescing for time ฮด, all replicas return the same value.
692pub fn dst_ext_eventual_consistency_convergence_ty() -> Expr {
693    arrow(real_ty(), prop())
694}
695/// `MonotonicReadConsistency : Prop`
696/// Once a client reads a value, subsequent reads never return older values.
697pub fn dst_ext_monotonic_read_consistency_ty() -> Expr {
698    prop()
699}
700/// `MonotonicWriteConsistency : Prop`
701/// A process's writes are serialized in the order they were issued.
702pub fn dst_ext_monotonic_write_consistency_ty() -> Expr {
703    prop()
704}
705/// `ReadYourWritesConsistency : Prop`
706/// A process always sees its own writes reflected in subsequent reads.
707pub fn dst_ext_read_your_writes_ty() -> Expr {
708    prop()
709}
710/// `WritesFollowReadsConsistency : Prop`
711/// Writes following a read are sequenced after the read's value.
712pub fn dst_ext_writes_follow_reads_ty() -> Expr {
713    prop()
714}
715/// `CRDTStrongEventualConsistency : Prop`
716/// CRDTs guarantee SEC: all replicas that receive the same updates converge.
717pub fn dst_ext_crdt_sec_ty() -> Expr {
718    prop()
719}
720/// `CRDTJoinSemilattice : Prop`
721/// State-based CRDT state forms a join-semilattice with โŠ” as merge.
722pub fn dst_ext_crdt_join_semilattice_ty() -> Expr {
723    prop()
724}
725/// `CRDTInflation : Prop`
726/// Every CRDTupdate is monotone: s โŠ‘ update(s).
727pub fn dst_ext_crdt_inflation_ty() -> Expr {
728    prop()
729}
730/// `OrSetCRDT : Prop`
731/// Observed-Remove Set: add wins over concurrent remove.
732pub fn dst_ext_or_set_crdt_ty() -> Expr {
733    prop()
734}
735/// `MVRegisterCRDT : Prop`
736/// Multi-Value Register: concurrent writes create a set of concurrent values.
737pub fn dst_ext_mv_register_crdt_ty() -> Expr {
738    prop()
739}
740/// `NTPSyncBound : Real โ†’ Real โ†’ Prop`
741/// NTP achieves clock synchronization within ฮด ms of UTC given RTT โ‰ค ฮ” ms.
742pub fn dst_ext_ntp_sync_bound_ty() -> Expr {
743    arrow(real_ty(), arrow(real_ty(), prop()))
744}
745/// `ClockDriftRate : Real โ†’ Prop`
746/// A physical clock drifts at most ฯ from real time.
747pub fn dst_ext_clock_drift_rate_ty() -> Expr {
748    arrow(real_ty(), prop())
749}
750/// `ChristianAlgorithm : Real โ†’ Prop`
751/// Christian's algorithm achieves synchronization within (ฮ”/2) ms.
752pub fn dst_ext_christian_algorithm_ty() -> Expr {
753    arrow(real_ty(), prop())
754}
755/// `BerkeleyAlgorithm : Nat โ†’ Real โ†’ Prop`
756/// Berkeley average-based clock sync for n nodes with drift โ‰ค ฮด.
757pub fn dst_ext_berkeley_algorithm_ty() -> Expr {
758    arrow(nat_ty(), arrow(real_ty(), prop()))
759}
760/// `HappensBefore : Prop โ†’ Prop โ†’ Prop`
761/// Lamport's happens-before relation: a โ†’ b if a caused b.
762pub fn dst_ext_happens_before_ty() -> Expr {
763    arrow(prop(), arrow(prop(), prop()))
764}
765/// `LamportClockConsistency : Prop`
766/// If a โ†’ b then L(a) < L(b) (clock condition).
767pub fn dst_ext_lamport_clock_consistency_ty() -> Expr {
768    prop()
769}
770/// `VectorClockCharacterization : Prop`
771/// VC(a) < VC(b) iff a โ†’ b (strong clock condition for vector clocks).
772pub fn dst_ext_vector_clock_characterization_ty() -> Expr {
773    prop()
774}
775/// `CausalDelivery : Prop`
776/// Causal broadcast: messages are delivered in causal order.
777pub fn dst_ext_causal_delivery_ty() -> Expr {
778    prop()
779}
780/// `CausalConsistency : Prop`
781/// All processes agree on the order of causally related operations.
782pub fn dst_ext_causal_consistency_ty() -> Expr {
783    prop()
784}
785/// `SnapshotIsolation : Prop`
786/// Transactions read from a consistent snapshot; writes conflict only on concurrent updates.
787pub fn dst_ext_snapshot_isolation_ty() -> Expr {
788    prop()
789}
790/// `RepeatableRead : Prop`
791/// Once a transaction reads a value, subsequent reads return the same value.
792pub fn dst_ext_repeatable_read_ty() -> Expr {
793    prop()
794}
795/// `PhantomRead : Prop`
796/// Phantom read anomaly: a query returns different rows when re-executed in the same transaction.
797pub fn dst_ext_phantom_read_ty() -> Expr {
798    prop()
799}
800/// `WriteSkew : Prop`
801/// Write skew anomaly: two concurrent transactions read overlapping data and write disjoint data.
802pub fn dst_ext_write_skew_ty() -> Expr {
803    prop()
804}
805/// Register all extended distributed systems theory axioms into the environment.
806pub fn register_distributed_systems_extended(env: &mut Environment) -> Result<(), String> {
807    let axioms: &[(&str, Expr)] = &[
808        (
809            "FLPImpossibilityStrong",
810            dst_ext_flp_impossibility_strong_ty(),
811        ),
812        (
813            "AsyncConsensusLowerBound",
814            dst_ext_async_consensus_lower_bound_ty(),
815        ),
816        ("CrashFailureModel", dst_ext_crash_failure_model_ty()),
817        ("OmissionFailureModel", dst_ext_omission_failure_model_ty()),
818        ("TimedAsynchronousModel", dst_ext_timed_async_model_ty()),
819        ("PaxosSafety", dst_ext_paxos_safety_ty()),
820        ("PaxosLiveness", dst_ext_paxos_liveness_ty()),
821        ("MultiPaxos", dst_ext_multi_paxos_ty()),
822        ("PaxosPhaseOneMessage", dst_ext_paxos_phase1_ty()),
823        ("PaxosPhaseTwoMessage", dst_ext_paxos_phase2_ty()),
824        ("RaftLeaderUniqueness", dst_ext_raft_leader_uniqueness_ty()),
825        ("RaftLogMatching", dst_ext_raft_log_matching_ty()),
826        (
827            "RaftLeaderCompleteness",
828            dst_ext_raft_leader_completeness_ty(),
829        ),
830        (
831            "RaftStateMachineSafety",
832            dst_ext_raft_state_machine_safety_ty(),
833        ),
834        ("RaftMembershipChange", dst_ext_raft_membership_change_ty()),
835        ("PBFTSafety", dst_ext_pbft_safety_ty()),
836        ("PBFTLiveness", dst_ext_pbft_liveness_ty()),
837        ("ThresholdSignature", dst_ext_threshold_signature_ty()),
838        ("ByzantineAgreement", dst_ext_byzantine_agreement_ty()),
839        (
840            "AuthenticatedByzantine",
841            dst_ext_authenticated_byzantine_ty(),
842        ),
843        ("ConsistentHashing", dst_ext_consistent_hashing_ty()),
844        (
845            "ConsistentHashingBalance",
846            dst_ext_consistent_hashing_balance_ty(),
847        ),
848        ("DHTChord", dst_ext_dht_chord_ty()),
849        ("DHTKademlia", dst_ext_dht_kademlia_ty()),
850        ("DHTLookupComplexity", dst_ext_dht_lookup_complexity_ty()),
851        (
852            "EventualConsistencyConvergence",
853            dst_ext_eventual_consistency_convergence_ty(),
854        ),
855        (
856            "MonotonicReadConsistency",
857            dst_ext_monotonic_read_consistency_ty(),
858        ),
859        (
860            "MonotonicWriteConsistency",
861            dst_ext_monotonic_write_consistency_ty(),
862        ),
863        ("ReadYourWrites", dst_ext_read_your_writes_ty()),
864        ("WritesFollowReads", dst_ext_writes_follow_reads_ty()),
865        ("CRDTStrongEventualConsistency", dst_ext_crdt_sec_ty()),
866        ("CRDTJoinSemilattice", dst_ext_crdt_join_semilattice_ty()),
867        ("CRDTInflation", dst_ext_crdt_inflation_ty()),
868        ("OrSetCRDT", dst_ext_or_set_crdt_ty()),
869        ("MVRegisterCRDT", dst_ext_mv_register_crdt_ty()),
870        ("NTPSyncBound", dst_ext_ntp_sync_bound_ty()),
871        ("ClockDriftRate", dst_ext_clock_drift_rate_ty()),
872        ("ChristianAlgorithm", dst_ext_christian_algorithm_ty()),
873        ("BerkeleyAlgorithm", dst_ext_berkeley_algorithm_ty()),
874        ("HappensBefore", dst_ext_happens_before_ty()),
875        (
876            "LamportClockConsistency",
877            dst_ext_lamport_clock_consistency_ty(),
878        ),
879        (
880            "VectorClockCharacterization",
881            dst_ext_vector_clock_characterization_ty(),
882        ),
883        ("CausalDelivery", dst_ext_causal_delivery_ty()),
884        ("CausalConsistency", dst_ext_causal_consistency_ty()),
885        ("SnapshotIsolation", dst_ext_snapshot_isolation_ty()),
886        ("RepeatableRead", dst_ext_repeatable_read_ty()),
887        ("PhantomRead", dst_ext_phantom_read_ty()),
888        ("WriteSkew", dst_ext_write_skew_ty()),
889    ];
890    for (name, ty) in axioms {
891        env.add(Declaration::Axiom {
892            name: Name::str(*name),
893            univ_params: vec![],
894            ty: ty.clone(),
895        })
896        .map_err(|e| format!("Failed to register {}: {:?}", name, e))?;
897    }
898    Ok(())
899}
900/// Simple multiplicative hash mixing two u64 values.
901pub fn dst_ext_mix_hash(a: u64, b: u64) -> u64 {
902    let mut h = a.wrapping_mul(6364136223846793005).wrapping_add(b);
903    h ^= h >> 33;
904    h = h.wrapping_mul(0xff51afd7ed558ccd);
905    h ^= h >> 33;
906    h
907}