# Docker Compose Setup for DataHaven Network

This docker-compose configuration runs a local DataHaven network with:
- **2 Validator nodes**: Alice and Bob
- **1 Main Storage Provider (MSP)** node: Charlie (exposed as "msp")
- **2 Backup Storage Provider (BSP)** nodes: Dave (bsp01) and Eve (bsp02)
- **1 StorageHub Indexer** node: Full indexer with PostgreSQL database
- **1 Fisherman** node: Gustavo - monitors and validates storage providers
- **1 PostgreSQL database**: Shared database for indexer and fisherman

## Prerequisites

- Docker & Docker Compose installed
- Pre-built DataHaven binary (see Building section)

## Directory Structure

```
operator/
├── docker-compose.yml          # Main compose configuration
├── Dockerfile                  # Node image
├── scripts/
│   ├── docker-entrypoint.sh   # Unified key injection entrypoint
│   └── docker-prepare.sh      # Build preparation script
└── DOCKER-COMPOSE.md          # This file
```

## Building the Binary

Before running docker-compose, you need to build the DataHaven node binary.

### Option 1: Using the prepare script (Recommended)

```bash
# For development (faster blocks with fast-runtime feature)
./scripts/docker-prepare.sh --fast

# For production
./scripts/docker-prepare.sh
```

### Option 2: Manual build

```bash
# For development (faster blocks with fast-runtime feature)
cargo build --release --features fast-runtime

# For production
cargo build --release

# Copy binary to expected location
mkdir -p build
cp target/release/datahaven-node build/
```

The binary will be output to `target/release/datahaven-node` and copied to `build/datahaven-node`.

## Running the Network

Once the binary is built and copied, start the network:

```bash
# Start both validators
docker-compose up -d

# View logs
docker-compose logs -f

# View logs for specific node
docker-compose logs -f alice
docker-compose logs -f bob
docker-compose logs -f msp
docker-compose logs -f bsp01
docker-compose logs -f bsp02
docker-compose logs -f postgres
docker-compose logs -f indexer
docker-compose logs -f fisherman
```

### Key Injection

All nodes automatically inject the required keys on startup using the unified `docker-entrypoint.sh` script.

#### Validator Keys (Alice, Bob)
Validators require 4 keys:
1. **GRANDPA** (`gran`) - ed25519 - Finality gadget
2. **BABE** (`babe`) - sr25519 - Block authoring
3. **ImOnline** (`imon`) - sr25519 - Validator heartbeat
4. **BEEFY** (`beef`) - ecdsa - Bridge consensus

#### Storage Provider Keys (MSP/BSP)
Storage providers (both MSP and BSP) require 1 key:
1. **BCSV** (`bcsv`) - ecdsa - Storage provider identity

#### Fisherman Keys
Fisherman nodes require 1 key:
1. **BCSV** (`bcsv`) - ecdsa - Storage provider identity

Keys are derived from a test seed phrase using the pattern: `<seed>//<NodeName>` (e.g., `//Alice`, `//Bob`, `//Charlie`, `//Dave`, `//Eve`, `//Gustavo`).

**⚠️ Security Warning**: The default seed phrase is for **development only**. Never use this in production! To use custom seeds, modify the `SEED` environment variable in `docker-compose.yml`.

## Accessing the Nodes

All nodes are accessible on the following ports:

### Alice (Primary Validator)
- **WebSocket/RPC**: `ws://localhost:9944`
- **Prometheus Metrics**: `http://localhost:9615`
- **P2P**: `localhost:30333`

### Bob (Secondary Validator)
- **WebSocket/RPC**: `ws://localhost:9945`
- **Prometheus Metrics**: `http://localhost:9616`
- **P2P**: `localhost:30334`

### MSP (Main Storage Provider - Charlie)
- **WebSocket/RPC**: `ws://localhost:9946`
- **Prometheus Metrics**: `http://localhost:9617`
- **P2P**: `localhost:30335`
- **Storage Capacity**: 1 GiB
- **Jump Capacity**: 100 MiB
- **Charging Period**: 100 blocks

### BSP01 (Backup Storage Provider - Dave)
- **WebSocket/RPC**: `ws://localhost:9947`
- **Prometheus Metrics**: `http://localhost:9618`
- **P2P**: `localhost:30336`
- **Storage Capacity**: 1 GiB
- **Jump Capacity**: 100 MiB

### BSP02 (Backup Storage Provider - Eve)
- **WebSocket/RPC**: `ws://localhost:9948`
- **Prometheus Metrics**: `http://localhost:9619`
- **P2P**: `localhost:30337`
- **Storage Capacity**: 1 GiB
- **Jump Capacity**: 100 MiB

### PostgreSQL Database
- **Host**: `localhost:5432`
- **Database**: `datahaven`
- **Username**: `indexer`
- **Password**: `indexer`
- **Connection String**: `postgresql://indexer:indexer@localhost:5432/datahaven`

### Indexer (StorageHub Indexer)
- **WebSocket/RPC**: `ws://localhost:9949`
- **Prometheus Metrics**: `http://localhost:9620`
- **P2P**: `localhost:30338`
- **Mode**: Full indexer with database persistence

### Fisherman (Storage Provider Monitor - Gustavo)
- **WebSocket/RPC**: `ws://localhost:9950`
- **Prometheus Metrics**: `http://localhost:9621`
- **P2P**: `localhost:30339`
- **Role**: Monitors and validates storage provider behavior

## Network Communication

All nodes run on a shared Docker network (`datahaven-network`). All nodes use:
- `--discover-local` for automatic peer discovery via mDNS
- `--unsafe-force-node-key-generation` for automatic node key generation

The validators (Alice and Bob) will produce blocks, while the storage providers (MSP and BSPs) provide storage services.

**Note**: All nodes use libp2p as the network backend (`--network-backend=libp2p`).

### Docker Desktop for macOS
**Important**: On Docker Desktop for macOS, you must use the **experimental DockerVMM** virtualization framework for proper networking support.

To enable DockerVMM:
1. Open Docker Desktop settings
2. Go to "General" tab
3. Enable "Use experimental virtualization framework (DockerVMM)"
4. Restart Docker Desktop

**Note**: The default Apple Virtualization Framework will cause networking issues with peer-to-peer connections, resulting in connection failures and protocol handshake errors.

## Stopping the Network

```bash
# Stop all nodes
docker-compose down

# Stop and remove volumes (clears chain data)
docker-compose down -v
```

## Configuration Notes

### Node Flags
- `--chain=stagenet-local` - Use stagenet-local chain specification (ensures all nodes share same genesis)
- `--base-path=/data` - Base directory for chain data and keystore
- `--keystore-path=/data/keystore` - Keystore persisted in Docker volumes
- `--validator` - Enables validator mode (Alice & Bob only)
- `--pool-type=fork-aware` - Uses fork-aware transaction pool for better fork handling
- `--unsafe-force-node-key-generation` - Automatic P2P key generation
- `--unsafe-rpc-external` - RPC exposed externally (**development only!**)
- `--rpc-cors=all` - Allows all CORS origins
- `--force-authoring` - Forces block authoring even with a single validator (Alice only)
- `--no-prometheus` - Prometheus metrics disabled
- `--enable-offchain-indexing=true` - Enables offchain indexing
- `--discover-local` - Enables local peer discovery via mDNS
- `--alice` / `--bob` - Use well-known development identities
- `--provider` - Enables storage provider mode (MSP & BSP)
- `--provider-type=msp|bsp` - Type of storage provider
- `--max-storage-capacity` - Maximum storage capacity in bytes (1073741824 = 1 GiB)
- `--jump-capacity` - Jump capacity in bytes (104857600 = 100 MiB)
- `--msp-charging-period` - Charging period in blocks (MSP only)

### Node Types
The docker-compose setup includes five node types:
1. **Validators** (`NODE_TYPE=validator`) - Alice & Bob
   - Run consensus and produce blocks
   - Require 4 keys: gran, babe, imon, beef
2. **MSP** (`NODE_TYPE=msp`) - Charlie (name: msp)
   - Main Storage Provider with storage provider capabilities
   - Requires 1 key: bcsv
   - Additional flags: `--provider`, `--provider-type=msp`, `--msp-charging-period`, storage capacity settings
3. **BSP** (`NODE_TYPE=bsp`) - Dave (bsp01) & Eve (bsp02)
   - Backup Storage Provider with storage provider capabilities
   - Requires 1 key: bcsv
   - Additional flags: `--provider`, `--provider-type=bsp`, storage capacity settings
4. **Indexer** (no NODE_TYPE required) - StorageHub Indexer
   - Full indexer node with database persistence
   - No keys required (non-validating node)
   - Additional flags: `--indexer`, `--indexer-mode=full`, `--indexer-database-url`
5. **Fisherman** (`NODE_TYPE=fisherman`) - Gustavo
   - Monitors and validates storage provider behavior
   - Requires 1 key: bcsv
   - Additional flags: `--fisherman`, `--fisherman-database-url`

### Storage
- **Chain data**: Persisted in Docker volumes at `/data` (not using `--tmp`)
- **Keystore**: Persisted in Docker volumes at `/data/keystore` (`alice-keystore`, `bob-keystore`, `msp-keystore`, `bsp01-keystore`, `bsp02-keystore`, `fisherman-keystore`)
- **PostgreSQL data**: Persisted in `postgres-data` volume
- **Indexer data**: Persisted in `indexer-data` volume
- To clear all data and start fresh: `docker-compose down -v`

### User Permissions
- Containers run as `root` user to allow the entrypoint script to inject keys and set permissions
- The entrypoint script (`docker-entrypoint.sh`) switches to the `datahaven` user (UID 1001) before starting the node process
- Keystore and data directories are owned by `datahaven:datahaven`

### Security
All settings are configured for **local development only**:
- Uses well-known test seed phrase
- RPC exposed without authentication
- Unsafe flags enabled for convenience

## Troubleshooting

### Binary not found error
If you see "datahaven-node: No such file or directory", ensure:
1. You're in the operator directory: `cd operator`
2. You've built the binary: `cargo build --release`
3. You've copied it to the correct location: `cp target/release/datahaven-node build/`
   Or simply run: `./prepare-docker.sh`

### Nodes not connecting
Check the logs to ensure nodes are peering correctly:
```bash
# Check if Bob connected to Alice
docker-compose logs bob | grep -i "peer\|sync"

# Check if MSP connected to Alice
docker-compose logs msp | grep -i "peer\|sync"

# View Alice's peer connections
docker-compose logs alice | grep -i "peer"
```

You should see messages like:
- `Discovered new external address`
- `Syncing` or `best: #X`
- Connection established messages

If nodes are not connecting:
1. Ensure Alice started first and is running: `docker-compose ps alice`
2. Verify Alice is accessible on the Docker network: `docker exec datahaven-bob ping alice`
3. Check Alice's peer ID matches the bootnode address in the config

### Port conflicts
If ports are already in use, modify the port mappings in `docker-compose.yml`:
```yaml
ports:
  - "YOUR_PORT:9944"  # Change YOUR_PORT to an available port
```

### Key injection issues
If you see key injection errors in the logs:
```bash
# Check the logs for key injection
docker-compose logs alice | grep "🔑"

# Verify keystore contents
docker exec datahaven-alice ls -la /keystore
```

To regenerate keys, remove the keystore volumes and restart:
```bash
docker-compose down -v
docker-compose up -d
```

### Checking node keys
To verify that keys were injected successfully:
```bash
# Alice keys (validator - 4 keys)
docker exec datahaven-alice ls -la /keystore

# Bob keys (validator - 4 keys)
docker exec datahaven-bob ls -la /keystore

# MSP keys (storage provider - 1 key)
docker exec datahaven-msp ls -la /data/keystore

# BSP keys (storage provider - 1 key)
docker exec datahaven-bsp01 ls -la /data/keystore
docker exec datahaven-bsp02 ls -la /data/keystore

# Fisherman keys (storage provider monitor - 1 key)
docker exec datahaven-fisherman ls -la /data/keystore
```

Validators should show: `babe`, `gran`, `imon`, and `beef`
Storage providers (MSP/BSP) and Fisherman should show: `bcsv`

### Checking Database Status
To verify the PostgreSQL database is working:
```bash
# Check PostgreSQL is running
docker exec datahaven-postgres pg_isready -U indexer -d datahaven

# Connect to database
docker exec -it datahaven-postgres psql -U indexer -d datahaven

# View indexer tables (once running)
docker exec datahaven-postgres psql -U indexer -d datahaven -c "\dt"
```

