MegaEngine is a distributed peer-to-peer (P2P) network for Git repositories. It enables nodes to discover, announce, and synchronize Git repositories across a decentralized network using the gossip protocol over QUIC transport.
- Decentralized Node Discovery: Nodes automatically discover each other and exchange node information via gossip protocol
- Repository Synchronization: Nodes announce and sync repository inventory across the network
- Bundle Transfer: P2P transfer of Git bundle files between nodes with integrity verification
- Automatic Bundle Sync: Periodic background task that automatically downloads bundles for external repositories
- Repository Cloning: Clone repositories from bundles using the
repo clonecommand - QUIC Transport: Uses QUIC protocol for reliable, low-latency peer-to-peer communication
- Gossip Protocol: Implements epidemic message propagation with TTL and deduplication
- Cryptographic Identity: Each node has a unique EdDSA-based identity (
did:keyformat) - SQLite Persistence: Stores repositories and node information persistently
- CLI Interface: Easy-to-use command-line tool for managing nodes and repositories
βββββββββββββββββββββββββββββββββββββββ
β CLI Interface β
β (node start, repo add, auth init) β
ββββββββββββββββ¬βββββββββββββββββββββββ
β
ββββββββββββββββΌβββββββββββββββββββββββ
β Node / Repository Manager β
β (NodeManager, RepoManager) β
ββββββββββββββββ¬βββββββββββββββββββββββ
β
ββββββββββββββββΌβββββββββββββββββββββββ
β Gossip Protocol Service β
β (message relay, dedup, TTL) β
ββββββββββββββββ¬βββββββββββββββββββββββ
β
ββββββββββββββββΌβββββββββββββββββββββββ
β QUIC Connection Manager β
β (peer connections, message send) β
ββββββββββββββββ¬βββββββββββββββββββββββ
β
ββββββββββββββββΌβββββββββββββββββββββββ
β SQLite Storage / Sea-ORM β
β (repos, nodes persistence) β
βββββββββββββββββββββββββββββββββββββββ
- Rust 1.70+ (2021 edition)
- Git (for git operations and bundle/tar packing)
- OpenSSL development libraries (for TLS)
cargo build --releaseSet the root directory for MegaEngine data (default: ~/.megaengine):
export MEGAENGINE_ROOT=/path/to/megaengine-dataThis example demonstrates how to set up a two-node network where the first node adds a repository, and the second node automatically synchronizes and clones it.
- Create a test Git repository (or use an existing one):
mkdir -p E:\git_test\tiny cd E:\git_test\tiny git init # Add some content git add . git commit -m "Initial commit"
Terminal 1 - Initialize the first node's keypair:
cargo run -- auth initTerminal 2 - Initialize the second node's keypair with a custom root directory:
cargo run -- --root ~/.megaengine2 auth initOutput will show the keypair location and the DID key for each node.
Terminal 1 - Start the first node (node1):
cargo run -- node start --alias node1 --addr 127.0.0.1:9000 --cert-path certKeep this terminal running.
Terminal 2 - Start the second node (node2) with node1 as bootstrap node:
cargo run -- --root ~/.megaengine2 node start --alias node2 --cert-path cert --bootstrap-node did:key:z2DUYGZos3YrXrD4pQ9aAku2g7btumKcfTiMSyBC8btqFDJ@127.0.0.1:9000 --addr 127.0.0.1:9001Keep this terminal running as well.
Note: Replace did:key:z2DUYGZos3YrXrD4pQ9aAku2g7btumKcfTiMSyBC8btqFDJ with the actual DID key from the first node's auth init output.
Terminal 3 - Add a repository on node1:
cargo run -- repo add --path /path/to/git_test/tiny --description "Tiny"The output will display the repo ID. Save this ID for later use.
The second node will automatically:
- Discover the repository announcement via gossip protocol
- Periodically request the bundle from node1 (every 60 seconds by default)
- Download the bundle file
- Store it locally
Monitor the output from Terminal 2 to see the synchronization progress.
Terminal 3 - List repositories on node2:
cargo run -- --root ~/.megaengine2 repo listYou should see the "Tiny" repository announced by node1.
Terminal 3 - Clone the repository on node2:
cargo run -- --root ~/.megaengine2 repo clone --repo-id <repo_id> --output ./tinyReplace <repo_id> with the ID from Step 3.
The cloned repository will be available at ./tiny on node2.
When the repository creator (node1) pushes new commits, node2 will automatically synchronize them.
Terminal 3 - Make a change in the original repository on node1:
cd E:\git_test\tiny
# Add or modify some files
echo "Updated content" >> README.md
git add README.md
git commit -m "Update repository"Terminal 3 - Update the repository bundle on node1:
cargo run -- repo listYou'll see the status indicator changes to β οΈ HAS UPDATES, showing new commits are available.
Terminal 3 - Node2 will automatically discover and download the updated bundle
Monitor Terminal 2 output - you should see automatic bundle sync activity. The background task runs every 60 seconds and will:
- Detect the repository update announcement via gossip protocol
- Request the updated bundle from node1
- Download and store the new bundle
Terminal 3 - Check repository status on node2:
cargo run -- --root ~/.megaengine2 repo listYou should see the repository status has changed, indicating updates are available.
Terminal 3 - Pull the latest updates to the cloned repository on node2:
cargo run -- --root ~/.megaengine2 repo pull --repo-id <repo_id>Replace <repo_id> with the repository ID from Step 3.
The cloned repository at ./tiny will be updated with the latest commits from the bundle.
did:key:z2DSQWVWxVg2Dq8qvq7TqJG75gY2hh9cT6RkzzgYpf7YptF
β β β
| | Ed25519 public key (base58 encoded)
| Multibase encoding
DID scheme
did:repo:zW1iF5iwCChifAcjZUrDbwD9o8LS76kFsz6bTZFEJhEqVCU
β β
| SHA3-256(root_commit + creator_pubkey)
Multibase encoding
-
Message Types:
NodeAnnouncement: Advertises node metadata (alias, addresses, type)RepoAnnouncement: Lists repositories owned by a node
-
TTL (Time-to-Live): Default 16 hops, decremented on each relay
-
Deduplication: Tracks seen message hashes in a 5-minute sliding window
-
Broadcast Interval: 10 seconds
MegaEngine implements a multi-frame bundle transfer protocol for P2P repository synchronization:
- Request: Request a bundle for a repository from a peer
- Start: Initiates bundle transfer with metadata (file_name, total_size)
- Chunk: Transfers data in 64KB chunks
- Done: Signals transfer completion
- Discovery: Node learns about external repository via gossip
- Request: Background task periodically requests missing bundles from repo owner
- Generation: Owner generates bundle from local repository
- Transfer: Bundle is sent to requester in multiple frames
- Storage: Received bundle is stored locally and marked in database
- Restoration: User can clone repository from stored bundle
- Runs every 60 seconds by default
- Checks for external repositories with empty bundle field
- Automatically requests missing bundles from repository owners
Data is persisted in SQLite at $MEGAENGINE_ROOT/megaengine.db:
- repos: Repository metadata (id, name, creator, description, path, refs, timestamps)
- nodes: Node information (id, alias, addresses, node_type, version, timestamps)
MEGAENGINE_ROOT: Root directory for data storage (default:~/.megaengine)RUST_LOG: Logging level (e.g.,megaengine=debug)
- QUIC Server:
0.0.0.0:9000(configurable via--addr)