{"id":29407234,"url":"https://github.com/oxarbitrage/zcash-p2p-spec","last_synced_at":"2026-02-03T08:31:47.580Z","repository":{"id":259123839,"uuid":"832814118","full_name":"oxarbitrage/zcash-p2p-spec","owner":"oxarbitrage","description":"Modelling the Zcash P2P network","archived":false,"fork":false,"pushed_at":"2024-11-05T19:44:56.000Z","size":1567,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-11T04:39:37.130Z","etag":null,"topics":["blockchain","p2p","pluscal","spec","tlaplus","zcash"],"latest_commit_sha":null,"homepage":"","language":"TLA","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/oxarbitrage.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,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-07-23T19:21:16.000Z","updated_at":"2025-04-29T02:57:13.000Z","dependencies_parsed_at":"2024-11-05T20:27:50.925Z","dependency_job_id":"9bdf7d46-d861-4b71-a5ca-f682880db1d4","html_url":"https://github.com/oxarbitrage/zcash-p2p-spec","commit_stats":null,"previous_names":["oxarbitrage/zcash-p2p-spec"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/oxarbitrage/zcash-p2p-spec","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxarbitrage%2Fzcash-p2p-spec","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxarbitrage%2Fzcash-p2p-spec/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxarbitrage%2Fzcash-p2p-spec/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxarbitrage%2Fzcash-p2p-spec/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oxarbitrage","download_url":"https://codeload.github.com/oxarbitrage/zcash-p2p-spec/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxarbitrage%2Fzcash-p2p-spec/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29038527,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-03T06:39:36.383Z","status":"ssl_error","status_checked_at":"2026-02-03T06:39:32.787Z","response_time":96,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["blockchain","p2p","pluscal","spec","tlaplus","zcash"],"created_at":"2025-07-11T00:41:23.904Z","updated_at":"2026-02-03T08:31:47.566Z","avatar_url":"https://github.com/oxarbitrage.png","language":"TLA","funding_links":[],"categories":[],"sub_categories":[],"readme":"# The Zcash P2P Protocol Specification\n\nThe Zcash P2P protocol is a decentralized system, inherited as a subset from the [Bitcoin P2P protocol](https://developer.bitcoin.org/reference/p2p_networking.html). The primary role of this protocol is to keep nodes synchronized with the network. Peers exchange a set of well-defined messages, but the synchronization algorithm is not standardized, allowing for variation in implementations.\n\nThis specification describes an approach where peers can connect to multiple other peers, aiming to load balance the workload and download blocks in parallel.\n\n## Motivation\n\nSpecifications are typically written to identify and fix bugs, justifying the effort involved. However, the primary motivations for this project are:\n\n- To learn more PlusCal and TLA+.\n- To formally define a blockchain synchronization algorithm.\n- To prove properties (liveness, safety, etc) of the resulting algorithm.\n\nThis is an ongoing project, and comments or contributions are highly encouraged.\n\n## Project Structure\n\nThe project consists of several files, with `p2p.tla` being the core specification. The distriubted algorithm is implemented in PlusCal while additional files are pure TLA+.\n\n- [Spec](p2p.tla)\n- [PDF's](documents/)\n- [Blockchain](Blockchain.tla)\n- [Operators](Operators.tla)\n- [Utils](Utils.tla)\n\n## Model Overview\n\nThe model operates based on initial network conditions defined in the `Blockchain.tla` module. Variables such as the number of peers, the blocks each peer holds, and the peer set of each peer influence the model's state and behavior during model checking with TLC.\n\n### Running the Model\n\nTo run the model, we use the [TLA+ for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=alygin.vscode-tlaplus) extension, which parses the PlusCal code into TLA+ and allows us to run the TLC model checker.\n\nThe Blockchain.tla module includes different initial conditions, labeled as `Blockchain1`, `Blockchain2`, etc.\n\nIn `p2p.cfg` assign the desired conditions, for example:\n\n```\nRunningBlockchain \u003c- Blockchain7\n```\n\nThen, run the TLC model checker against the parsed `p2p.tla` file.\n\n## Internals\n\nThe algorithm consists of two processes running in parallel.\n\n### LISTENER process\n\nThis process listens for incoming messages and calls the corresponding procedure when a message arrives on the channel established between two connected peers. The following are the supported messages in this specification:\n\n```mermaid\nflowchart TD\nLISTENER[[LISTENER]] --\u003e |Listen|addr\nLISTENER --\u003e |Listen|version\nLISTENER --\u003e |Listen|verack\nLISTENER --\u003e |Listen|getblocks\nLISTENER --\u003e |Listen|inv\nLISTENER --\u003e |Listen|getdata\n```\n\n### SYNCHRONIZER process\n\nThis process manages connections between peers. Connections are created between each peer listed in the `RunningBlockchain` sequence and their respective peers in the `peer_set`. Once connected, peers will request blocks and attempt to synchronize with the network.\n\nThe following diagram assumes a network of three peers (peer1, peer2, and peer3), where peer2 has peer1 and peer3 in its peer_set.\n\n`SYNCHRONIZER` will not open connections for peer1 and peer3 since they have no peers in their `peer_set`. For peer2, connections with peer1 and peer3 will be established, and blocks will be requested from both until peer2 is in sync, at which point the algorithm terminates.\n\n```mermaid\nflowchart TD\nSYNCHRONIZER[[SYNCHRONIZER]] --\u003e |For peer2|announce\nannounce --\u003e |Connect|peer1\nannounce --\u003e |Connect|peer3\nsync --\u003e |Request blocks|peer1\npeer1 --\u003e |Send blocks|sync\nsync --\u003e |Request blocks|peer3\npeer3 --\u003e |Send blocks|sync\nsync ---\u003e |Peer in sync|terminate\n```\n\n### Single Peer Synchronization\n\nLet's now consider a network with just two peers (peer1 and peer2), where peer1 is in the `peer_set` of peer2 and has blocks. The following diagram shows how the `SYNCHRONIZER` and `LISTENER` processes interact to synchronize peer2 with the rest of the network (peer1) at the message level.\n\n```mermaid\nflowchart TD\nLISTENER[[LISTENER]] --\u003e |Listen|addr\nLISTENER --\u003e |Listen|version\nLISTENER --\u003e |Listen|verack\nLISTENER --\u003e |Listen|getblocks\nLISTENER --\u003e |Listen|inv\nLISTENER --\u003e |Listen|getdata\n\nSYNCHRONIZER[[SYNCHRONIZER]] --\u003e |For peer2|announce\nannounce --\u003e |Start Connecting|send_addr_msg([SendAddrMsg])\nsend_addr_msg --\u003e |Process|addr\naddr --\u003e |Start Hansdhake|send_version_msg([SendVersionMsg])\nsend_version_msg --\u003e |Process|version\nversion --\u003e |More Hanshake|send_verack_msg([SendVerackMsg])\nsend_verack_msg --\u003e |End Handshake - Connected|verack\n\nannounce --\u003e |Await connected|sync\nsync --\u003e |Decide blocks to be requested|request_blocks\nrequest_blocks --\u003e |Request inv|send_getblocks_msg([SendGetBlocksMsg])\nsend_getblocks_msg --\u003e |Process|getblocks\ngetblocks --\u003e |Get inv|send_inv_msg([SendInvMsg])\nsend_inv_msg --\u003e |Process|inv\ninv --\u003e |Request data|send_getdata_msg([SendGetDataMsg])\nsend_getdata_msg --\u003e |Process|getdata\ngetdata --\u003e |Add data to peer|incorporate\nincorporate --\u003e |Sync loop|sync\nincorporate --\u003e |End algorithm|terminate\n```\n\n### Load balancing\n\nIn a network with three peers (peer1, peer2, and peer3), where only peer2 has peers in its `peer_set` (specifically, peer1 and peer3), the following sequence occurs:\n\nAfter connecting with both peers, the `SYNCHRONIZER` requests a batch of blocks from peer1. If this batch is insufficient for full synchronization, another batch is requested from peer3, and the process repeats until peer2 is fully synchronized.\n \n```mermaid\nsequenceDiagram\n    Peer2-\u003e\u003ePeer1: Request blocks\n    Peer1-\u003e\u003ePeer2: Send blocks\n\n    Peer2-\u003e\u003ePeer2: Need more blocks? YES\n    Peer2-\u003e\u003ePeer3: Request more blocks\n    Peer3 -\u003e\u003ePeer2: Send more blocks\n\n    Peer2-\u003e\u003ePeer2: Need more blocks? YES\n\n    Peer2-\u003e\u003ePeer1: Request more blocks\n    Peer1-\u003e\u003ePeer2: Send more blocks\n\n    Peer2-\u003e\u003ePeer2: Need more blocks? NO\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foxarbitrage%2Fzcash-p2p-spec","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foxarbitrage%2Fzcash-p2p-spec","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foxarbitrage%2Fzcash-p2p-spec/lists"}