{"id":13606379,"url":"https://github.com/uwplse/verdi-raft","last_synced_at":"2025-04-09T23:18:25.002Z","repository":{"id":37789435,"uuid":"69508239","full_name":"uwplse/verdi-raft","owner":"uwplse","description":"An implementation of the Raft distributed consensus protocol, verified in Coq using the Verdi framework","archived":false,"fork":false,"pushed_at":"2023-12-08T14:05:25.000Z","size":3100,"stargazers_count":186,"open_issues_count":15,"forks_count":19,"subscribers_count":54,"default_branch":"master","last_synced_at":"2025-04-09T23:18:19.877Z","etag":null,"topics":["consensus","coq","distributed-systems","key-value","proof","raft","verdi"],"latest_commit_sha":null,"homepage":"","language":"Coq","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/uwplse.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2016-09-28T22:18:33.000Z","updated_at":"2025-04-05T12:48:04.000Z","dependencies_parsed_at":"2023-02-08T01:47:36.069Z","dependency_job_id":"5c82e2f5-2b9c-4f86-9fcb-889a0b12d530","html_url":"https://github.com/uwplse/verdi-raft","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uwplse%2Fverdi-raft","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uwplse%2Fverdi-raft/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uwplse%2Fverdi-raft/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uwplse%2Fverdi-raft/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/uwplse","download_url":"https://codeload.github.com/uwplse/verdi-raft/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248125593,"owners_count":21051771,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["consensus","coq","distributed-systems","key-value","proof","raft","verdi"],"created_at":"2024-08-01T19:01:08.641Z","updated_at":"2025-04-09T23:18:24.975Z","avatar_url":"https://github.com/uwplse.png","language":"Coq","funding_links":[],"categories":["Projects","Coq"],"sub_categories":["Verified Software"],"readme":"\u003c!---\nThis file was generated from `meta.yml`, please do not edit manually.\nFollow the instructions on https://github.com/coq-community/templates to regenerate.\n---\u003e\n# Verdi Raft\n\n[![Docker CI][docker-action-shield]][docker-action-link]\n\n[docker-action-shield]: https://github.com/uwplse/verdi-raft/actions/workflows/docker-action.yml/badge.svg?branch=master\n[docker-action-link]: https://github.com/uwplse/verdi-raft/actions/workflows/docker-action.yml\n\n\n\n\nRaft is a distributed consensus algorithm that is designed to be easy to understand\nand is equivalent to Paxos in fault tolerance and performance. Verdi Raft is a\nverified implementation of Raft in Coq, constructed using the Verdi framework.\nIncluded is a verified fault-tolerant key-value store using Raft.\n\n## Meta\n\n- Author(s):\n  - Justin Adsuara\n  - Steve Anton\n  - Ryan Doenges\n  - Karl Palmskog\n  - Pavel Panchekha\n  - Zachary Tatlock\n  - James R. Wilcox\n  - Doug Woos\n- License: [BSD 2-Clause \"Simplified\" license](LICENSE)\n- Compatible Coq versions: 8.14 or later\n- Additional dependencies:\n  - [Verdi](https://github.com/uwplse/verdi)\n  - [StructTact](https://github.com/uwplse/StructTact)\n  - [Cheerios](https://github.com/uwplse/cheerios)\n- Coq namespace: `VerdiRaft`\n- Related publication(s):\n  - [Verdi: A Framework for Implementing and Verifying Distributed Systems](https://homes.cs.washington.edu/~mernst/pubs/verify-distsystem-pldi2015.pdf) doi:[10.1145/2737924.2737958](https://doi.org/10.1145/2737924.2737958)\n  - [Planning for Change in a Formal Verification of the Raft Consensus Protocol](https://homes.cs.washington.edu/~mernst/pubs/raft-proof-cpp2016.pdf) doi:[10.1145/2854065.2854081](https://doi.org/10.1145/2854065.2854081)\n\n## Optional requirements\n\nExecutable `vard` key-value store:\n- [`OCaml`](https://ocaml.org/docs/install.html) (4.02.3 or later)\n- [`OCamlbuild`](https://github.com/ocaml/ocamlbuild)\n- [`verdi-runtime`](https://github.com/DistributedComponents/verdi-runtime)\n- [`cheerios-runtime`](https://github.com/uwplse/cheerios)\n\nClient for `vard`:\n- [`Python 2.7`](https://www.python.org/download/releases/2.7/)\n\nIntegration testing of `vard`:\n- [`Python 2.7`](https://www.python.org/download/releases/2.7/)\n\nUnit testing of unverified `vard` code:\n- [`OUnit`](http://ounit.forge.ocamlcore.org) (2.0.0 or later)\n\n## Building and installation instructions\n\nWe recommend installing the dependencies of Verdi Raft via\n[opam](http://opam.ocaml.org/doc/Install.html):\n```shell\nopam repo add coq-extra-dev https://coq.inria.fr/opam/extra-dev\nopam install coq-struct-tact coq-cheerios coq-verdi\n```\n\nThen, run `make` in the root directory. This will compile the Raft\nimplementation and proof interfaces, and check all the proofs.\nTo speed up proof checking on multi-core machines, use `make -jX`,\nwhere `X` is at least the number of cores on your machine.\n\nTo build the `vard` key-value store program in `extraction/vard`,\nyou first need to install its requirements. Then, run `make vard`\nin the root directory. If the Coq implementation has been compiled\nas above, this simply compiles the extracted OCaml code to a native\nexecutable; otherwise, the implementation is extracted to OCaml and\ncompiled without checking any proofs.\n\n## Files\n\nThe `Raft` and `RaftProofs` subdirectories of `theories` contain the implementation\nand verification of Raft. For each proof interface file in `Raft`, there is a\ncorresponding proof file in `RaftProofs`. The files in the `Raft`\nsubdirectory include:\n\n- `Raft.v`: an implementation of Raft in Verdi\n- `RaftRefinementInterface.v`: an application of the ghost-variable transformer\n  to Raft which tracks several ghost variables used in the\n  verification of Raft\n- `CommonTheorems.v`: several useful theorems about functions used by\n  the Raft implementation\n- `OneLeaderPerTermInterface`: a statement of Raft's *election\n  safety* property. See also the corresponding proof file in `RaftProofs`.\n    - `CandidatesVoteForSelvesInterface.v`, `VotesCorrectInterface.v`, and\n      `CroniesCorrectInterface.v`: statements of properties used by the proof\n      `OneLeaderPerTermProof.v`\n- `LogMatchingInterface.v`: a statement of Raft's *log matching*\n    property. See also `LogMatchingProof.v` in `RaftProofs`\n    - `LeaderSublogInterface.v`, `SortedInterface.v`, and `UniqueIndicesInterface.v`: statements\n      of properties used by `LogMatchingProof.v`\n\nThe file `EndToEndLinearizability.v` in `RaftProofs` uses the proofs of\nall proof interfaces to show Raft's *linearizability* property.\n\n## The `vard` Key-Value Store\n\n`vard` is a simple key-value store implemented using\nVerdi. `vard` is specified and verified against Verdi's state-machine\nsemantics in the `VarD.v` example system distributed with Verdi. When the Raft transformer\nis applied, `vard` can be run as a strongly-consistent, fault-tolerant key-value store\nalong the lines of [`etcd`](https://github.com/coreos/etcd).\n\nAfter running `make vard` in the root directory, OCaml code for `vard`\nis extracted, compiled, and linked against a Verdi shim and some `vard`-specific\nserialization/debugging code, to produce a `vard.native` binary in `extraction/vard`.\n\nRunning `make bench-vard` in `extraction/vard` will produce some \nbenchmark numbers, which are largely meaningless on\n`localhost` (multiple processes writing and fsync-ing to the same disk\nand communicating over loopback doesn't accurately model real-world\nuse cases). Running `make debug` will get you a `tmux` session where\nyou can play around with a vard cluster in debug mode; look in\n`bench/vard.py` for a simple Python `vard` client.\n\nAs the name suggests, `vard` is designed to be comparable to the `etcd`\nkey-value store (although it currently supports many fewer\nfeatures). To that end, we include a very simple `etcd` \"client\" which\ncan be used for benchmarking. Running `make bench-etcd` will run the\nvard benchmarks against `etcd` (although see above for why these results\nare not particularly meaningful). See below for instructions to run\nboth stores on a cluster in order to get a more useful performance\ncomparison.\n\n### Running `vard` on a cluster\n\n`vard` accepts the following command-line options:\n\n```\n-me NAME             name for this node\n-port PORT           port for client commands\n-dbpath DIRECTORY    directory for storing database files\n-node NAME,IP:PORT   node in the cluster\n-debug               run in debug mode\n```\n\nNote that `vard` node names are integers starting from 0.\n\nFor example, to run `vard` on a cluster with IP addresses\n`192.168.0.1`, `192.168.0.2`, `192.168.0.3`, client (input) port 8000,\nand port 9000 for inter-node communication, use the following:\n\n```\n# on 192.168.0.1\n$ ./vard.native -dbpath /tmp/vard-8000 -port 8000 -me 0 -node 0,192.168.0.1:9000 \\\n                -node 1,192.168.0.2:9000 -node 2,192.168.0.3:9000\n\n# on 192.168.0.2\n$ ./vard.native -dbpath /tmp/vard-8000 -port 8000 -me 1 -node 0,192.168.0.1:9000 \\\n                -node 1,192.168.0.2:9000 -node 2,192.168.0.3:9000\n\n# on 192.168.0.3\n$ ./vard.native -dbpath /tmp/vard-8000 -port 8000 -me 2 -node 0,192.168.0.1:9000 \\\n                    -node 1,192.168.0.2:9000 -node 2,192.168.0.3:9000\n```\n\nWhen the cluster is set up, a benchmark can be run as follows:\n\n```\n# on the client machine\n$ python2 bench/setup.py --service vard --keys 50 \\\n                         --cluster \"192.168.0.1:8000,192.168.0.2:8000,192.168.0.3:8000\"\n$ python2 bench/bench.py --service vard --keys 50 \\\n                         --cluster \"192.168.0.1:8000,192.168.0.2:8000,192.168.0.3:8000\" \\\n                         --threads 8 --requests 100\n```\n\n### Running `etcd` on a cluster\n\nWe can compare numbers for `vard` and `etcd` running on the same cluster as\nfollows:\n\n```\n# on 192.168.0.1\n$ etcd --name=one \\\n --listen-client-urls http://192.168.0.1:8000 \\\n --advertise-client-urls http://192.168.0.1:8000 \\\n --initial-advertise-peer-urls http://192.168.0.1:9000 \\\n --listen-peer-urls http://192.168.0.1:9000 \\\n --data-dir=/tmp/etcd \\\n --initial-cluster \"one=http://192.168.0.1:9000,two=http://192.168.0.2:9000,three=http://192.168.0.3:9000\"\n\n# on 192.168.0.2\n$ etcd --name=two \\\n --listen-client-urls http://192.168.0.2:8000 \\\n --advertise-client-urls http://192.168.0.2:8000 \\\n --initial-advertise-peer-urls http://192.168.0.2:9000 \\\n --listen-peer-urls http://192.168.0.2:9000 \\\n --data-dir=/tmp/etcd \\\n --initial-cluster \"one=http://192.168.0.1:9000,two=http://192.168.0.2:9000,three=http://192.168.0.3:9000\"\n\n# on 192.168.0.3\n$ etcd --name=three \\\n --listen-client-urls http://192.168.0.3:8000 \\\n --advertise-client-urls http://192.168.0.3:8000 \\\n --initial-advertise-peer-urls http://192.168.0.3:9000 \\\n --listen-peer-urls http://192.168.0.3:9000 \\\n --data-dir=/tmp/etcd \\\n --initial-cluster \"one=http://192.168.0.1:9000,two=http://192.168.0.2:9000,three=http://192.168.0.3:9000\"\n\n# on the client machine\n$ python2 bench/setup.py --service etcd --keys 50 \\\n                         --cluster \"192.168.0.1:8000,192.168.0.2:8000,192.168.0.3:8000\"\n$ python2 bench/bench.py --service etcd --keys 50 \\\n                         --cluster \"192.168.0.1:8000,192.168.0.2:8000,192.168.0.3:8000\" \\\n                         --threads 8 --requests 100\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuwplse%2Fverdi-raft","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fuwplse%2Fverdi-raft","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuwplse%2Fverdi-raft/lists"}