A smol implementation of narwhal - a mempool narwhal DAG-based consensus mechanism.
- 🐍 Python 3.9+
- 📦 UV package manager
- 🍺 Homebrew (for macOS users)
For macOS:
brew install gmp
export CFLAGS="-I/opt/homebrew/include"
export LDFLAGS="-L/opt/homebrew/lib"
Set up your development environment with these steps:
# Create and activate venv
uv venv
source .venv/bin/activate
# Install dependencies
uv pip install -r requirements.txt
python test_launcher.py --validators <number_of_validators> [optional arguments]
Required:
--validators
: Number of validators to run
Optional:
--workers
: Number of workers per validator (default: 1)--test-id
: Test name (default: "test")--calf
: Path to the executable (default: "target/release/calf")--build
: Build the binary in release mode automatically
Before running, ensure you have:
- ✅ The calf executable at
target/release/calf
(or specify a different path with--calf
) - ✅ A
committee.json
file in your working directory (or specify a different path with--committee-path
)
Learn more about Narwhal and DAG-based consensus:
- Narwhal & Tusk: A DAG-based Mempool and Efficient BFT Consensus
- Deep Dive into Narwhal & Tusk
- Narwhal and Tusk: A DAG-based Mempool and BFT Consensus
- Narwhal/Bullshark: DAG-based Mempool and Efficient BFT Consensus
The project includes a real-time DAG visualizer that helps you understand the certificate creation and DAG growth process.
- Make sure you have the required Python dependencies installed:
pip install matplotlib networkx numpy
- Start the narwhal network using the test launcher:
python test_launcher.py --validators 4
- In a separate terminal, run the visualizer:
python visualizer.py test
The visualizer will show:
- Certificates as colored nodes (each color represents a validator)
- Edges showing the relationships between certificates
- Round numbers inside each node
- Hover tooltips with detailed information:
- Certificate ID
- Round number
- Author
- Number of incoming edges (votes)
- Number of parent certificates
- The visualization updates every 2 seconds
- Only the last 5 rounds are shown to maintain performance
- You can adjust these settings in
visualizer.py
:visible_rounds
: Number of rounds to display (default: 5)update_interval
: Seconds between updates (default: 2.0)max_stored_rounds
: Maximum rounds to keep in memory (default: 10)