|
| 1 | +(**************************************************************************) |
| 2 | +(**************************************************************************) |
| 3 | +(**** ****) |
| 4 | +(**** Equivalence of state-based and operation-based conflict-free ****) |
| 5 | +(**** replicated data types ****) |
| 6 | +(**** ****) |
| 7 | +(**************************************************************************) |
| 8 | +(**************************************************************************) |
| 9 | + |
| 10 | +Require Import Coq.Lists.List. |
| 11 | +Require Import Coq.Sorting.Permutation. |
| 12 | +Require Import main.tactics. |
| 13 | + |
| 14 | +Require main.crdt.operation_crdt. |
| 15 | + |
| 16 | +Import Coq.Lists.List.ListNotations. |
| 17 | + |
| 18 | +(* We can emulate a state-based CRDT with an operation-based CRDT. *) |
| 19 | + |
| 20 | +Definition operation_crdt_data_from_state_crdt |
| 21 | + [A Q] |
| 22 | + (crdt : state_crdt.Crdt A Q) |
| 23 | +: operation_crdt.CrdtData A Q |
| 24 | +:= |
| 25 | + {| |
| 26 | + operation_crdt.State := crdt.(state_crdt.State); |
| 27 | + operation_crdt.Operation := crdt.(state_crdt.State); |
| 28 | + operation_crdt.initial := crdt.(state_crdt.initial); |
| 29 | + operation_crdt.update x s := crdt.(state_crdt.update) x s; |
| 30 | + operation_crdt.interpret o s := crdt.(state_crdt.merge) o s; |
| 31 | + operation_crdt.query s := crdt.(state_crdt.query) s; |
| 32 | + operation_crdt.Precondition _ _ := True; |
| 33 | + |}. |
| 34 | + |
| 35 | +Program Definition operation_crdt_from_state_crdt |
| 36 | + [A Q] |
| 37 | + (crdt : state_crdt.Crdt A Q) |
| 38 | +: operation_crdt.Crdt (operation_crdt_data_from_state_crdt crdt) |
| 39 | +:= {| operation_crdt.commutativity := _ |}. |
| 40 | +Next Obligation. |
| 41 | + clean. |
| 42 | + pose proof (crdt.(state_crdt.semilattice _ _)). |
| 43 | + rewrite state_crdt.associativity |
| 44 | + with (initial := crdt.(state_crdt.initial)); search. |
| 45 | + rewrite state_crdt.commutativity |
| 46 | + with (initial := crdt.(state_crdt.initial)) (x := o1); search. |
| 47 | +Qed. |
| 48 | + |
| 49 | +(* |
| 50 | + We can emulate an operation-based CRDT with a state-based CRDT if the |
| 51 | + delivery precondition and equality on operations are decidable and there is a |
| 52 | + way to order any given set of operations. The order can be completely |
| 53 | + arbitrary. |
| 54 | +*) |
| 55 | + |
| 56 | +#[local] Obligation Tactic := auto. (* `search` diverges here, sadly. *) |
| 57 | + |
| 58 | +Program Definition state_crdt_from_operation_crdt |
| 59 | + [A Q] |
| 60 | + [crdt_data : operation_crdt.CrdtData A Q] |
| 61 | + (crdt : operation_crdt.Crdt crdt_data) |
| 62 | + (precondition : |
| 63 | + forall s o, |
| 64 | + {crdt_data.(operation_crdt.Precondition) s o} + |
| 65 | + {~ crdt_data.(operation_crdt.Precondition) s o}) |
| 66 | + (equal : |
| 67 | + forall (o1 o2 : crdt_data.(operation_crdt.Operation)), |
| 68 | + {o1 = o2} + {o1 <> o2}) |
| 69 | + (permute : |
| 70 | + list crdt_data.(operation_crdt.Operation) -> |
| 71 | + list crdt_data.(operation_crdt.Operation)) |
| 72 | + (H1 : forall os, Permutation os (permute os)) |
| 73 | + (H : forall os1 os2, Permutation os1 os2 -> permute os1 = permute os2) |
| 74 | +: state_crdt.Crdt A Q := |
| 75 | + {| |
| 76 | + state_crdt.State := |
| 77 | + list crdt_data.(operation_crdt.Operation) * |
| 78 | + list crdt_data.(operation_crdt.Operation); |
| 79 | + state_crdt.initial := ([], []); |
| 80 | + state_crdt.merge '(_, _) '(_, _) := _; |
| 81 | + state_crdt.update _ '(_, _) := _; |
| 82 | + state_crdt.query '(_, delivered) := |
| 83 | + crdt_data.(operation_crdt.query) |
| 84 | + (operation_crdt.run crdt_data delivered); |
| 85 | + |}. |
| 86 | +Next Obligation. |
| 87 | + clean. |
| 88 | + split; search. |
| 89 | +Admitted. |
| 90 | +Next Obligation. |
| 91 | +Admitted. |
0 commit comments