Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ gossipsub/topology.json
shadow-gossipsub.yaml
message_propagation.png

# Simnet simulation outputs
simnet.log
simnet_propagation.png

# Go build artifacts
*.out

Expand All @@ -23,3 +27,9 @@ message_propagation.png
# Coverage files
coverage.out
*.coverprofile

# Python virtual environment
.venv/
__pycache__/
*.pyc
*.pyo
98 changes: 90 additions & 8 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co

## Project Overview

This is a GossipSub simulation framework for testing Ethereum attestation propagation using the Shadow discrete-event network simulator. The project simulates libp2p GossipSub networks with realistic network conditions and Ethereum consensus-specs parameters.
This is a GossipSub simulation framework for testing Ethereum attestation propagation. The project supports two simulation approaches:

1. **Shadow Simulator**: Discrete-event network simulator that runs the actual GossipSub binary in a simulated network environment
2. **Simnet**: Go's deterministic network simulation using `testing/synctest` for fast, reproducible tests

Both approaches simulate libp2p GossipSub networks with realistic network conditions and Ethereum consensus-specs parameters.

## Architecture

Expand All @@ -15,12 +20,23 @@ This is a GossipSub simulation framework for testing Ethereum attestation propag
- **generators.go**: Three topology generators (mesh, tree, random-regular)
- **gen/main.go**: CLI tool for generating topology files

- **gossipsub/**: GossipSub simulation binary
- **main.go**: Simulation entry point using go-libp2p-pubsub
- **gossipsub/**: GossipSub simulation binaries and tests
- **main.go**: Shadow simulation entry point using go-libp2p-pubsub
- **simnet_test.go**: Simnet test using Go 1.25+ testing/synctest
- Implements Ethereum consensus-specs GossipSub parameters
- Uses deterministic peer IDs for reproducibility
- All nodes publish one message each (N nodes → N messages total)

- **networkinfo/**: Network configuration parser
- **networkinfo.go**: Parses Shadow YAML and GML graph files
- **types.go**: Data structures for host network information
- Extracts bandwidth, latency, and message size per host

- **shadowconfig/**: Shadow configuration parser
- **shadowconfig.go**: Parses Shadow YAML configuration
- Extracts node network IDs and process arguments
- Used by simnet to configure network conditions

- **network_graph.py**: Shadow configuration generator
- Generates realistic network graphs with global latencies
- Distributes nodes across geographic locations
Expand All @@ -31,11 +47,16 @@ This is a GossipSub simulation framework for testing Ethereum attestation propag
- Checks that all nodes received the message
- Used in CI tests

- **plot_propagation.py**: Message propagation visualization
- **plot_propagation.py**: Shadow message propagation visualization
- Parses Shadow logs to extract message reception timestamps
- Plots average messages per node over time
- Generates message_propagation.png

- **plot_simnet_propagation.py**: Simnet message propagation visualization
- Parses simnet.log to extract message reception timestamps
- Plots average messages per node over time
- Generates simnet_propagation.png

- **shadow.template.yaml**: Shadow configuration template

- **pyproject.toml**: Python project configuration
Expand Down Expand Up @@ -65,19 +86,28 @@ Python dependencies defined in `pyproject.toml`:
## Development Commands

### Make Commands (Primary Interface)

**Shadow Simulation:**
```bash
make help # Show all available commands
make all # Build, run simulation, test, and plot (default)
make all # Build, run Shadow simulation, test, and plot (default)
make build # Build GossipSub binary
make build-topology-gen # Build topology generator
make generate-topology # Generate topology file
make generate-config # Generate Shadow configuration
make run-sim # Run complete Shadow simulation
make test # Test simulation results
make plot # Plot message propagation over time
make test # Test Shadow simulation results
make plot # Plot Shadow message propagation over time
make clean # Clean build artifacts and results
```

**Simnet Simulation:**
```bash
make run-simnet # Run simnet test (requires Go 1.25+)
make plot-simnet # Plot simnet message propagation
make all-simnet # Run simnet and plot (complete workflow)
```

### Configuration Variables
```bash
# Topology settings
Expand Down Expand Up @@ -130,7 +160,9 @@ uv run plot_propagation.py 10
shadow shadow-gossipsub.yaml
```

## Simulation Workflow
## Simulation Workflows

### Shadow Simulation Workflow

1. **Topology Generation**
- Makefile generates topology.json using topology-gen
Expand All @@ -144,6 +176,7 @@ shadow shadow-gossipsub.yaml
- Geographic distribution: Australia, Europe, Asia, Americas, Africa

3. **GossipSub Simulation**
- Shadow runs gossipsub binary for each node in simulated network
- Each node loads topology and creates libp2p host
- Deterministic peer IDs (seed-based key generation)
- All nodes start synchronized at 2000/01/01 00:02:00
Expand All @@ -156,6 +189,45 @@ shadow shadow-gossipsub.yaml
- Verifies all nodes received all N messages
- Reports pass/fail for each node

### Simnet Simulation Workflow

1. **Configuration Loading**
- Simnet test reads shadow-gossipsub.yaml and graph.gml
- Parses network parameters (bandwidth, latency, message size)
- Loads topology.json for peer connections
- Requires Go 1.25+ for testing/synctest support

2. **Network Setup**
- Creates simulated network using simlibp2p and simnet packages
- Configures per-host bandwidth and latency based on Shadow config
- Uses IP-to-host-ID mapping for latency calculations
- Latency applied on downlink (receiver adds latency based on sender)

3. **GossipSub Test Execution**
- Creates libp2p hosts for all nodes in deterministic simulation
- Establishes connections based on topology
- All nodes subscribe to test topic
- Every node publishes one message
- Tracks received message count per node using atomic counters

4. **Result Validation**
- Test verifies each node received exactly N messages
- Logs reception timestamps to simnet.log for plotting
- Test fails if any node didn't receive all messages
- Validates complete message propagation across the network

## Shadow vs Simnet

| Aspect | Shadow | Simnet |
|--------|--------|--------|
| **Execution** | Discrete-event simulator, runs actual binaries | Go test using testing/synctest |
| **Speed** | Slower (minutes for 10 nodes) | Faster (seconds for 20 nodes) |
| **Realism** | High (realistic network, process isolation) | Medium (simulated network in memory) |
| **Debugging** | Harder (separate processes) | Easier (single process, Go debugger) |
| **Requirements** | Shadow v3.2.0+ | Go 1.25+ |
| **Use Case** | Final validation, realistic scenarios | Development, quick iteration |
| **Determinism** | Deterministic with same config | Fully deterministic (synctest) |

## GossipSub Parameters

The simulation uses Ethereum consensus-specs parameters:
Expand Down Expand Up @@ -254,17 +326,27 @@ make all
- shimlog: Shadow internal logs

### Troubleshooting

**Shadow:**
- **"Topology file is required"**: Makefile generates this automatically
- **"cannot find binary path"**: Check gossipsub/gossipsub exists
- **Shadow simulation hangs**: Check Shadow version (requires v3.2.0)
- **All nodes didn't receive message**: Check Shadow logs for connection errors

**Simnet:**
- **"no test files" or build constraint error**: Requires Go 1.25+ for testing/synctest
- **Test fails with wrong message count**: Check simnet.log for errors, ensure topology is connected
- **Network latency errors**: Verify shadow-gossipsub.yaml and graph.gml are generated
- **Plot script fails**: Run `make run-simnet` first to generate simnet.log

## Module Structure

The project uses `github.com/ethp2p/attsim` with key dependencies:
- go-libp2p v0.41.1
- go-libp2p-pubsub v0.15.0
- go-log/v2 v2.8.2
- github.com/marcopolo/simnet (for simnet simulation)
- testing/synctest (Go 1.25+ standard library, for deterministic testing)

## Related Projects

Expand Down
30 changes: 24 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Makefile for attsim GossipSub Shadow simulation

.PHONY: all build build-topology-gen generate-topology generate-config run-sim test plot clean help check-deps
.PHONY: all all-simnet build build-topology-gen generate-topology generate-config run-sim run-simnet test plot plot-simnet clean help check-deps

# Default parameters
NODE_COUNT ?= 10
Expand Down Expand Up @@ -58,10 +58,10 @@ run-sim: build generate-config
shadow --progress $(PROGRESS) shadow-gossipsub.yaml
@echo "GossipSub simulation completed"

# Run the complete Shadow simulation
# Run the complete simnet simulation
run-simnet: generate-config
@echo "Starting GossipSub simnet simulation ($(NODE_COUNT) nodes, $(MSG_SIZE) byte message)..."
cd $(GOSSIPSUB_DIR) && go test -v .
cd $(GOSSIPSUB_DIR) && go test -v . 2>&1 | tee ../simnet.log
@echo "GossipSub simnet simulation completed"

# Test simulation results
Expand All @@ -75,6 +75,13 @@ plot:
uv run plot_propagation.py $(NODE_COUNT)
@test -f message_propagation.png && echo "Plot generated: message_propagation.png" || echo "Plot generation failed"

# Plot simnet message propagation
plot-simnet:
@echo "Plotting simnet message propagation..."
@test -f simnet.log || (echo "Error: simnet.log not found. Run 'make run-simnet' first" && exit 1)
uv run plot_simnet_propagation.py simnet.log
@test -f simnet_propagation.png && echo "Plot generated: simnet_propagation.png" || echo "Plot generation failed"

# Clean build artifacts and simulation results
clean:
@echo "Cleaning up..."
Expand All @@ -83,13 +90,18 @@ clean:
rm -f shadow-gossipsub.yaml
rm -f graph.gml
rm -f message_propagation.png
rm -f simnet_propagation.png
rm -f simnet.log
rm -rf shadow.data/
rm -f $(TOPOLOGY_GEN_DIR)/topology-gen
@echo "Cleanup completed"

# Complete workflow: build, run, test, and plot
all: run-sim test plot

# Complete simnet workflow: run and plot
all-simnet: run-simnet plot-simnet

# Help target
help:
@echo "attsim GossipSub Shadow Simulation"
Expand All @@ -102,9 +114,12 @@ help:
@echo " build - Build the GossipSub simulation binary"
@echo " generate-config - Generate Shadow configuration"
@echo " run-sim - Run complete Shadow simulation"
@echo " run-simnet - Run complete simnet simulation (requires Go 1.25+)"
@echo " test - Test simulation results"
@echo " plot - Plot message propagation over time"
@echo " all - Run simulation, test, and plot (default)"
@echo " plot - Plot message propagation over time (Shadow)"
@echo " plot-simnet - Plot message propagation over time (simnet)"
@echo " all - Run Shadow simulation, test, and plot (default)"
@echo " all-simnet - Run simnet simulation and plot"
@echo " clean - Clean up build artifacts and results"
@echo " help - Show this help message"
@echo ""
Expand All @@ -118,11 +133,14 @@ help:
@echo " LOG_LEVEL - Log level (default: $(LOG_LEVEL))"
@echo ""
@echo "Examples:"
@echo " make all # Run simulation, test, and plot (random-regular)"
@echo " make all # Run Shadow simulation, test, and plot"
@echo " make all-simnet # Run simnet simulation and plot"
@echo " make run-sim NODE_COUNT=20 MSG_SIZE=512 # Custom parameters"
@echo " make run-sim TOPOLOGY_TYPE=mesh NODE_COUNT=10 # Mesh topology"
@echo " make run-sim TOPOLOGY_TYPE=tree NODE_COUNT=31 BRANCHING=2 # Tree topology"
@echo " make run-sim TOPOLOGY_TYPE=random-regular PEER_COUNT=6 # Random-regular with 6 peers"
@echo " make run-sim PROGRESS=true # Run with progress bar"
@echo " make test # Test existing simulation results"
@echo " make plot NODE_COUNT=10 # Plot message propagation"
@echo " make run-simnet NODE_COUNT=10 # Run simnet simulation"
@echo " make plot-simnet # Plot simnet propagation"
Loading