mirror of
https://github.com/datahaven-xyz/datahaven
synced 2026-05-23 17:28:23 +00:00
docs: 📚 Add Snowbridge relay documentation
Add comprehensive documentation for the 4 Snowbridge relays: - Beacon Relay: Syncs Ethereum beacon chain finality to DataHaven - BEEFY Relay: Submits DataHaven BEEFY proofs to Ethereum - Execution Relay: Delivers Ethereum messages to DataHaven - Solochain Relay: Sends DataHaven messages to Ethereum Each document includes: - CLI flags and configuration file structure - Key requirements (Ethereum/Substrate private keys) - Docker and Kubernetes deployment examples - Multi-instance deployment for high availability - Monitoring and troubleshooting guides Also updates README.md with Snowbridge section and relay overview table. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
948a57832e
commit
67bc549b1b
5 changed files with 1490 additions and 0 deletions
|
|
@ -15,6 +15,12 @@ This directory contains comprehensive documentation for setting up and operating
|
|||
- [Indexer Setup](./storagehub-indexer.md) - Indexer node configuration and operations
|
||||
- [Fisherman Setup](./storagehub-fisherman.md) - Fisherman node configuration and operations
|
||||
|
||||
### Snowbridge Relays
|
||||
- [Beacon Relay](./snowbridge-beacon-relay.md) - Ethereum beacon chain → DataHaven
|
||||
- [BEEFY Relay](./snowbridge-beefy-relay.md) - DataHaven BEEFY finality → Ethereum
|
||||
- [Execution Relay](./snowbridge-execution-relay.md) - Ethereum messages → DataHaven
|
||||
- [Solochain Relay](./snowbridge-solochain-relay.md) - DataHaven messages → Ethereum
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### Node Types Overview
|
||||
|
|
@ -29,6 +35,15 @@ This directory contains comprehensive documentation for setting up and operating
|
|||
| **Indexer** | Blockchain data indexer | None | No | Yes (PostgreSQL) |
|
||||
| **Fisherman** | Storage provider monitor | 1 (BCSV ECDSA) | No | Yes (PostgreSQL) |
|
||||
|
||||
### Snowbridge Relays Overview
|
||||
|
||||
| Relay | Direction | Keys Required | Persistent Storage |
|
||||
|-------|-----------|---------------|-------------------|
|
||||
| **Beacon Relay** | Ethereum → DataHaven | Substrate | Yes (datastore) |
|
||||
| **BEEFY Relay** | DataHaven → Ethereum | Ethereum | No |
|
||||
| **Execution Relay** | Ethereum → DataHaven | Substrate | Yes (datastore) |
|
||||
| **Solochain Relay** | DataHaven → Ethereum | Ethereum + Substrate | Yes (datastore) |
|
||||
|
||||
### Common CLI Flags
|
||||
|
||||
All node types support standard Substrate flags:
|
||||
|
|
@ -71,6 +86,8 @@ All node types support standard Substrate flags:
|
|||
|
||||
- [Main Repository](https://github.com/Moonsong-Labs/datahaven)
|
||||
- [StorageHub Repository](https://github.com/Moonsong-Labs/storage-hub)
|
||||
- [Snowbridge Repository](https://github.com/datahaven-xyz/snowbridge) (solochain branch)
|
||||
- [Snowbridge Documentation](https://docs.snowbridge.network)
|
||||
- [E2E Testing Guide](../test/README.md)
|
||||
- [Docker Compose Guide](../operator/DOCKER-COMPOSE.md)
|
||||
- [Kubernetes Deployment](../deploy/charts/node/README.md)
|
||||
|
|
|
|||
335
docs/snowbridge-beacon-relay.md
Normal file
335
docs/snowbridge-beacon-relay.md
Normal file
|
|
@ -0,0 +1,335 @@
|
|||
# Snowbridge Beacon Relay
|
||||
|
||||
## Overview
|
||||
|
||||
The Beacon Relay syncs Ethereum beacon chain (consensus layer) finality to the DataHaven blockchain. It monitors the Ethereum beacon chain and submits sync committee updates and finality proofs to the `EthereumBeaconClient` pallet on DataHaven.
|
||||
|
||||
## Purpose
|
||||
|
||||
- Relay Ethereum beacon chain finality to DataHaven
|
||||
- Submit sync committee updates for light client verification
|
||||
- Enable trustless verification of Ethereum state on DataHaven
|
||||
- Support cross-chain message verification from Ethereum
|
||||
|
||||
## Direction
|
||||
|
||||
```
|
||||
Ethereum Beacon Chain → DataHaven
|
||||
```
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker with `linux/amd64` platform support
|
||||
- Access to Ethereum consensus layer (beacon) endpoint
|
||||
- Access to DataHaven node WebSocket endpoint
|
||||
- Substrate account with balance for transaction fees
|
||||
- Persistent storage for relay datastore
|
||||
|
||||
## Key Requirements
|
||||
|
||||
### Substrate Private Key
|
||||
|
||||
The Beacon Relay requires a **Substrate private key** to sign and submit extrinsics to the DataHaven chain.
|
||||
|
||||
| Key Type | Purpose |
|
||||
|----------|---------|
|
||||
| Substrate (sr25519/ecdsa) | Sign beacon update extrinsics on DataHaven |
|
||||
|
||||
### Account Funding
|
||||
|
||||
The relay account must be funded with HAVE tokens to pay for transaction fees when submitting beacon updates.
|
||||
|
||||
**Recommended Balance**: 100+ HAVE for continuous operations
|
||||
|
||||
## CLI Flags
|
||||
|
||||
### Required Flags
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--config <PATH>` | Path to the JSON configuration file |
|
||||
|
||||
### Private Key Flags (One Required)
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--substrate.private-key <KEY>` | Substrate private key URI directly |
|
||||
| `--substrate.private-key-file <PATH>` | Path to file containing the private key |
|
||||
| `--substrate.private-key-id <ID>` | AWS Secrets Manager secret ID for the private key |
|
||||
|
||||
## Configuration File
|
||||
|
||||
### Structure
|
||||
|
||||
```json
|
||||
{
|
||||
"source": {
|
||||
"beacon": {
|
||||
"endpoint": "http://beacon-node:4000",
|
||||
"stateEndpoint": "http://beacon-node:4000",
|
||||
"spec": {
|
||||
"syncCommitteeSize": 512,
|
||||
"slotsInEpoch": 32,
|
||||
"epochsPerSyncCommitteePeriod": 256,
|
||||
"forkVersions": {
|
||||
"deneb": 0,
|
||||
"electra": 0
|
||||
}
|
||||
},
|
||||
"datastore": {
|
||||
"location": "/relay-data",
|
||||
"maxEntries": 100
|
||||
}
|
||||
}
|
||||
},
|
||||
"sink": {
|
||||
"parachain": {
|
||||
"endpoint": "ws://datahaven-node:9944",
|
||||
"maxWatchedExtrinsics": 8,
|
||||
"headerRedundancy": 20
|
||||
},
|
||||
"updateSlotInterval": 30
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Configuration Parameters
|
||||
|
||||
#### Source (Beacon Chain)
|
||||
|
||||
| Parameter | Description | Example |
|
||||
|-----------|-------------|---------|
|
||||
| `source.beacon.endpoint` | Beacon chain HTTP API endpoint | `http://beacon-node:4000` |
|
||||
| `source.beacon.stateEndpoint` | Beacon chain state endpoint (usually same as above) | `http://beacon-node:4000` |
|
||||
| `source.beacon.spec.syncCommitteeSize` | Size of sync committee | `512` |
|
||||
| `source.beacon.spec.slotsInEpoch` | Slots per epoch | `32` |
|
||||
| `source.beacon.spec.epochsPerSyncCommitteePeriod` | Epochs per sync committee period | `256` |
|
||||
| `source.beacon.spec.forkVersions` | Fork version configuration | `{"deneb": 0, "electra": 0}` |
|
||||
| `source.beacon.datastore.location` | Path to persistent datastore | `/relay-data` |
|
||||
| `source.beacon.datastore.maxEntries` | Maximum datastore entries | `100` |
|
||||
|
||||
#### Sink (DataHaven)
|
||||
|
||||
| Parameter | Description | Example |
|
||||
|-----------|-------------|---------|
|
||||
| `sink.parachain.endpoint` | DataHaven WebSocket endpoint | `ws://datahaven-node:9944` |
|
||||
| `sink.parachain.maxWatchedExtrinsics` | Max concurrent watched extrinsics | `8` |
|
||||
| `sink.parachain.headerRedundancy` | Header redundancy factor | `20` |
|
||||
| `sink.updateSlotInterval` | Slot interval for updates | `30` |
|
||||
|
||||
## Initialization: Beacon Client Pallet
|
||||
|
||||
Before starting the Beacon Relay, the `EthereumBeaconClient` pallet must be initialized with a checkpoint.
|
||||
|
||||
### Generate Initial Checkpoint
|
||||
|
||||
```bash
|
||||
docker run --rm \
|
||||
-v $(pwd)/beacon-relay.json:/app/beacon-relay.json:ro \
|
||||
-v $(pwd)/checkpoint.json:/app/dump-initial-checkpoint.json \
|
||||
-v $(pwd)/datastore:/data \
|
||||
--platform linux/amd64 \
|
||||
datahavenxyz/snowbridge-relay:latest \
|
||||
generate-beacon-checkpoint --config beacon-relay.json --export-json
|
||||
```
|
||||
|
||||
### Submit Checkpoint to DataHaven
|
||||
|
||||
The checkpoint must be submitted via a sudo call to `EthereumBeaconClient.force_checkpoint`:
|
||||
|
||||
```typescript
|
||||
import { createClient } from 'polkadot-api';
|
||||
import { datahaven } from '@polkadot-api/descriptors';
|
||||
|
||||
const client = createClient(wsProvider);
|
||||
const api = client.getTypedApi(datahaven);
|
||||
|
||||
const forceCheckpointCall = api.tx.EthereumBeaconClient.force_checkpoint({
|
||||
update: checkpoint // Parsed from dump-initial-checkpoint.json
|
||||
});
|
||||
|
||||
const tx = api.tx.Sudo.sudo({
|
||||
call: forceCheckpointCall.decodedCall
|
||||
});
|
||||
|
||||
await tx.signAndSubmit(sudoSigner);
|
||||
```
|
||||
|
||||
## Running the Relay
|
||||
|
||||
### Docker Run
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
--name snowbridge-beacon-relay \
|
||||
--platform linux/amd64 \
|
||||
--add-host host.docker.internal:host-gateway \
|
||||
--network datahaven-network \
|
||||
-v $(pwd)/beacon-relay.json:/configs/beacon-relay.json:ro \
|
||||
-v $(pwd)/relay-data:/relay-data \
|
||||
--pull always \
|
||||
datahavenxyz/snowbridge-relay:latest \
|
||||
run beacon \
|
||||
--config /configs/beacon-relay.json \
|
||||
--substrate.private-key "0x..."
|
||||
```
|
||||
|
||||
### Docker Compose
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
beacon-relay:
|
||||
image: datahavenxyz/snowbridge-relay:latest
|
||||
container_name: snowbridge-beacon-relay
|
||||
platform: linux/amd64
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./configs/beacon-relay.json:/configs/beacon-relay.json:ro
|
||||
- beacon-relay-data:/relay-data
|
||||
command:
|
||||
- "run"
|
||||
- "beacon"
|
||||
- "--config"
|
||||
- "/configs/beacon-relay.json"
|
||||
- "--substrate.private-key-file"
|
||||
- "/secrets/substrate-key"
|
||||
secrets:
|
||||
- substrate-key
|
||||
|
||||
volumes:
|
||||
beacon-relay-data:
|
||||
|
||||
secrets:
|
||||
substrate-key:
|
||||
file: ./secrets/beacon-relay-substrate-key
|
||||
```
|
||||
|
||||
## Kubernetes Deployment
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: dh-beacon-relay
|
||||
spec:
|
||||
serviceName: dh-beacon-relay
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: dh-beacon-relay
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: dh-beacon-relay
|
||||
spec:
|
||||
containers:
|
||||
- name: beacon-relay
|
||||
image: datahavenxyz/snowbridge-relay:latest
|
||||
imagePullPolicy: Always
|
||||
args:
|
||||
- "run"
|
||||
- "beacon"
|
||||
- "--config"
|
||||
- "/configs/beacon-relay.json"
|
||||
- "--substrate.private-key-file"
|
||||
- "/secrets/dh-beacon-relay-substrate-key"
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /configs
|
||||
readOnly: true
|
||||
- name: secrets
|
||||
mountPath: /secrets
|
||||
readOnly: true
|
||||
- name: relay-data
|
||||
mountPath: /relay-data
|
||||
resources:
|
||||
requests:
|
||||
memory: "512Mi"
|
||||
cpu: "250m"
|
||||
limits:
|
||||
memory: "1Gi"
|
||||
cpu: "500m"
|
||||
volumes:
|
||||
- name: config
|
||||
configMap:
|
||||
name: beacon-relay-config
|
||||
- name: secrets
|
||||
secret:
|
||||
secretName: dh-beacon-relay-substrate-key
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: relay-data
|
||||
spec:
|
||||
accessModes: [ "ReadWriteOnce" ]
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
```
|
||||
|
||||
## Monitoring
|
||||
|
||||
### Health Checks
|
||||
|
||||
The relay logs sync committee updates and beacon chain state:
|
||||
|
||||
```bash
|
||||
# View relay logs
|
||||
docker logs -f snowbridge-beacon-relay
|
||||
|
||||
# Check for successful updates
|
||||
docker logs snowbridge-beacon-relay 2>&1 | grep -i "submitted\|update"
|
||||
```
|
||||
|
||||
### Key Metrics to Monitor
|
||||
|
||||
- Beacon chain slot lag
|
||||
- Sync committee update frequency
|
||||
- Transaction success rate
|
||||
- Account balance (for fees)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Issue: Beacon Chain Not Ready
|
||||
|
||||
**Symptoms**: Relay fails to start or continuously retries
|
||||
|
||||
**Check**:
|
||||
1. Beacon chain endpoint is accessible
|
||||
2. Beacon chain has finalized blocks
|
||||
3. Network connectivity between relay and beacon node
|
||||
|
||||
```bash
|
||||
# Test beacon chain connectivity
|
||||
curl http://beacon-node:4000/eth/v1/beacon/states/head/finality_checkpoints
|
||||
```
|
||||
|
||||
### Issue: Checkpoint Submission Failed
|
||||
|
||||
**Check**:
|
||||
1. Sudo account has sufficient balance
|
||||
2. Checkpoint data is valid
|
||||
3. DataHaven node is synced
|
||||
|
||||
### Issue: Transaction Failures
|
||||
|
||||
**Check**:
|
||||
1. Relay account has sufficient HAVE balance
|
||||
2. DataHaven node is accessible
|
||||
3. No duplicate relayers submitting same updates
|
||||
|
||||
## Security Considerations
|
||||
|
||||
1. **Private Key Protection**: Store private keys securely (AWS Secrets Manager, Kubernetes secrets, or encrypted files)
|
||||
2. **Network Security**: Restrict access to relay endpoints
|
||||
3. **Access Control**: Use dedicated accounts with minimal required permissions
|
||||
4. **Monitoring**: Set up alerts for relay failures
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [BEEFY Relay](./snowbridge-beefy-relay.md)
|
||||
- [Execution Relay](./snowbridge-execution-relay.md)
|
||||
- [Solochain Relay](./snowbridge-solochain-relay.md)
|
||||
- [Snowbridge Documentation](https://docs.snowbridge.network)
|
||||
- [DataHaven Snowbridge Repository](https://github.com/datahaven-xyz/snowbridge)
|
||||
353
docs/snowbridge-beefy-relay.md
Normal file
353
docs/snowbridge-beefy-relay.md
Normal file
|
|
@ -0,0 +1,353 @@
|
|||
# Snowbridge BEEFY Relay
|
||||
|
||||
## Overview
|
||||
|
||||
The BEEFY Relay submits DataHaven BEEFY (Bridge Efficiency Enabling Finality Yielder) finality proofs to the `BeefyClient` smart contract on Ethereum. This enables trustless verification of DataHaven state on Ethereum.
|
||||
|
||||
## Purpose
|
||||
|
||||
- Relay DataHaven BEEFY finality proofs to Ethereum
|
||||
- Submit validator set commitments to BeefyClient contract
|
||||
- Enable trustless verification of DataHaven state on Ethereum
|
||||
- Support cross-chain message verification to Ethereum
|
||||
|
||||
## Direction
|
||||
|
||||
```
|
||||
DataHaven → Ethereum
|
||||
```
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker with `linux/amd64` platform support
|
||||
- Access to DataHaven node WebSocket endpoint
|
||||
- Access to Ethereum execution layer WebSocket endpoint
|
||||
- Ethereum account with ETH for gas fees
|
||||
- Deployed BeefyClient and Gateway contracts on Ethereum
|
||||
|
||||
## Key Requirements
|
||||
|
||||
### Ethereum Private Key
|
||||
|
||||
The BEEFY Relay requires an **Ethereum private key** to sign and submit transactions to the BeefyClient contract.
|
||||
|
||||
| Key Type | Purpose |
|
||||
|----------|---------|
|
||||
| Ethereum (secp256k1) | Sign Ethereum transactions to BeefyClient contract |
|
||||
|
||||
### Account Funding
|
||||
|
||||
The relay account must be funded with ETH to pay for gas when submitting BEEFY proofs.
|
||||
|
||||
**Recommended Balance**: 0.5+ ETH for continuous operations (gas costs vary with network conditions)
|
||||
|
||||
## CLI Flags
|
||||
|
||||
### Required Flags
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--config <PATH>` | Path to the JSON configuration file |
|
||||
|
||||
### Private Key Flags (One Required)
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--ethereum.private-key <KEY>` | Ethereum private key directly |
|
||||
| `--ethereum.private-key-file <PATH>` | Path to file containing the private key |
|
||||
| `--ethereum.private-key-id <ID>` | AWS Secrets Manager secret ID for the private key |
|
||||
|
||||
### Optional Flags
|
||||
|
||||
| Flag | Description | Default |
|
||||
|------|-------------|---------|
|
||||
| `--on-demand` | Synchronize commitments on demand | `false` |
|
||||
|
||||
## Configuration File
|
||||
|
||||
### Structure
|
||||
|
||||
```json
|
||||
{
|
||||
"source": {
|
||||
"polkadot": {
|
||||
"endpoint": "ws://datahaven-node:9944"
|
||||
}
|
||||
},
|
||||
"sink": {
|
||||
"ethereum": {
|
||||
"endpoint": "ws://ethereum-node:8546",
|
||||
"gas-limit": ""
|
||||
},
|
||||
"descendants-until-final": 3,
|
||||
"contracts": {
|
||||
"BeefyClient": "0x4826533B4897376654Bb4d4AD88B7faFD0C98528",
|
||||
"Gateway": "0x8f86403A4DE0BB5791fa46B8e795C547942fE4Cf"
|
||||
}
|
||||
},
|
||||
"on-demand-sync": {
|
||||
"max-tokens": 5,
|
||||
"refill-amount": 1,
|
||||
"refill-period": 3600
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Configuration Parameters
|
||||
|
||||
#### Source (DataHaven)
|
||||
|
||||
| Parameter | Description | Example |
|
||||
|-----------|-------------|---------|
|
||||
| `source.polkadot.endpoint` | DataHaven WebSocket endpoint | `ws://datahaven-node:9944` |
|
||||
|
||||
#### Sink (Ethereum)
|
||||
|
||||
| Parameter | Description | Example |
|
||||
|-----------|-------------|---------|
|
||||
| `sink.ethereum.endpoint` | Ethereum WebSocket endpoint | `ws://ethereum-node:8546` |
|
||||
| `sink.ethereum.gas-limit` | Optional gas limit override | `""` (empty for auto) |
|
||||
| `sink.descendants-until-final` | Blocks to wait for finality | `3` |
|
||||
| `sink.contracts.BeefyClient` | BeefyClient contract address | `0x...` |
|
||||
| `sink.contracts.Gateway` | Gateway contract address | `0x...` |
|
||||
|
||||
#### On-Demand Sync (Rate Limiting)
|
||||
|
||||
| Parameter | Description | Example |
|
||||
|-----------|-------------|---------|
|
||||
| `on-demand-sync.max-tokens` | Maximum tokens for rate limiting | `5` |
|
||||
| `on-demand-sync.refill-amount` | Tokens to refill per period | `1` |
|
||||
| `on-demand-sync.refill-period` | Refill period in seconds | `3600` |
|
||||
|
||||
## Prerequisites: BEEFY Protocol Ready
|
||||
|
||||
Before starting the BEEFY Relay, the BEEFY protocol must be active on DataHaven.
|
||||
|
||||
### Check BEEFY Status
|
||||
|
||||
```bash
|
||||
# Using curl with JSON-RPC
|
||||
curl -s -H "Content-Type: application/json" \
|
||||
-d '{"id":1, "jsonrpc":"2.0", "method": "beefy_getFinalizedHead"}' \
|
||||
http://localhost:9944
|
||||
|
||||
# Should return a non-zero block hash when ready
|
||||
```
|
||||
|
||||
### Automated Wait (Test Environment)
|
||||
|
||||
The test framework automatically waits for BEEFY with a 60-second timeout:
|
||||
|
||||
```typescript
|
||||
const waitBeefyReady = async (pollIntervalMs: number, timeoutMs: number) => {
|
||||
// Poll beefy_getFinalizedHead until it returns a non-zero hash
|
||||
};
|
||||
```
|
||||
|
||||
## Running the Relay
|
||||
|
||||
### Docker Run
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
--name snowbridge-beefy-relay \
|
||||
--platform linux/amd64 \
|
||||
--add-host host.docker.internal:host-gateway \
|
||||
--network datahaven-network \
|
||||
-v $(pwd)/beefy-relay.json:/configs/beefy-relay.json:ro \
|
||||
--pull always \
|
||||
datahavenxyz/snowbridge-relay:latest \
|
||||
run beefy \
|
||||
--config /configs/beefy-relay.json \
|
||||
--ethereum.private-key "0x..."
|
||||
```
|
||||
|
||||
### Docker Compose
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
beefy-relay:
|
||||
image: datahavenxyz/snowbridge-relay:latest
|
||||
container_name: snowbridge-beefy-relay
|
||||
platform: linux/amd64
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./configs/beefy-relay.json:/configs/beefy-relay.json:ro
|
||||
command:
|
||||
- "run"
|
||||
- "beefy"
|
||||
- "--config"
|
||||
- "/configs/beefy-relay.json"
|
||||
- "--ethereum.private-key-file"
|
||||
- "/secrets/ethereum-key"
|
||||
secrets:
|
||||
- ethereum-key
|
||||
|
||||
secrets:
|
||||
ethereum-key:
|
||||
file: ./secrets/beefy-relay-ethereum-key
|
||||
```
|
||||
|
||||
## Kubernetes Deployment
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: dh-beefy-relay
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: dh-beefy-relay
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: dh-beefy-relay
|
||||
spec:
|
||||
containers:
|
||||
- name: beefy-relay
|
||||
image: datahavenxyz/snowbridge-relay:latest
|
||||
imagePullPolicy: Always
|
||||
args:
|
||||
- "run"
|
||||
- "beefy"
|
||||
- "--config"
|
||||
- "/configs/beefy-relay.json"
|
||||
- "--ethereum.private-key-file"
|
||||
- "/secrets/dh-beefy-relay-ethereum-key"
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /configs
|
||||
readOnly: true
|
||||
- name: secrets
|
||||
mountPath: /secrets
|
||||
readOnly: true
|
||||
resources:
|
||||
requests:
|
||||
memory: "256Mi"
|
||||
cpu: "100m"
|
||||
limits:
|
||||
memory: "512Mi"
|
||||
cpu: "250m"
|
||||
volumes:
|
||||
- name: config
|
||||
configMap:
|
||||
name: beefy-relay-config
|
||||
- name: secrets
|
||||
secret:
|
||||
secretName: dh-beefy-relay-ethereum-key
|
||||
```
|
||||
|
||||
Note: BEEFY Relay does **not** require persistent storage (no `volumeClaimTemplates`).
|
||||
|
||||
## Contract Requirements
|
||||
|
||||
### BeefyClient Contract
|
||||
|
||||
The BeefyClient contract must be deployed on Ethereum and initialized with:
|
||||
- Initial validator set
|
||||
- Initial BEEFY authority set ID
|
||||
|
||||
### Gateway Contract
|
||||
|
||||
The Gateway contract coordinates cross-chain message passing and interacts with BeefyClient for verification.
|
||||
|
||||
### Get Contract Addresses
|
||||
|
||||
Contract addresses are typically stored in a deployments file after contract deployment:
|
||||
|
||||
```typescript
|
||||
const deployments = await parseDeploymentsFile();
|
||||
const beefyClientAddress = deployments.BeefyClient;
|
||||
const gatewayAddress = deployments.Gateway;
|
||||
```
|
||||
|
||||
## Monitoring
|
||||
|
||||
### Health Checks
|
||||
|
||||
```bash
|
||||
# View relay logs
|
||||
docker logs -f snowbridge-beefy-relay
|
||||
|
||||
# Check for BEEFY proof submissions
|
||||
docker logs snowbridge-beefy-relay 2>&1 | grep -i "submit\|proof\|commitment"
|
||||
```
|
||||
|
||||
### Key Metrics to Monitor
|
||||
|
||||
- BEEFY finality lag (DataHaven blocks behind)
|
||||
- Ethereum transaction success rate
|
||||
- Gas costs and account balance
|
||||
- BeefyClient contract state
|
||||
|
||||
### Ethereum Contract State
|
||||
|
||||
```bash
|
||||
# Check BeefyClient latest commitment (using cast from Foundry)
|
||||
cast call $BEEFY_CLIENT "latestBeefyBlock()" --rpc-url $ETH_RPC_URL
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Issue: BEEFY Not Ready
|
||||
|
||||
**Symptoms**: Relay fails to start with "BEEFY protocol not ready"
|
||||
|
||||
**Check**:
|
||||
1. DataHaven network has active validators
|
||||
2. BEEFY pallet is enabled in runtime
|
||||
3. Sufficient blocks have been produced for BEEFY finality
|
||||
|
||||
```bash
|
||||
# Check BEEFY finalized head
|
||||
curl -s -H "Content-Type: application/json" \
|
||||
-d '{"id":1, "jsonrpc":"2.0", "method": "beefy_getFinalizedHead"}' \
|
||||
http://localhost:9944
|
||||
```
|
||||
|
||||
### Issue: Ethereum Transaction Failures
|
||||
|
||||
**Check**:
|
||||
1. Relay account has sufficient ETH for gas
|
||||
2. BeefyClient contract is deployed and initialized
|
||||
3. Gas price is appropriate for network conditions
|
||||
4. No competing relayers submitting same proofs
|
||||
|
||||
### Issue: Rate Limiting
|
||||
|
||||
**Symptoms**: Relay slows down or stops submitting proofs
|
||||
|
||||
**Check**:
|
||||
1. `on-demand-sync` configuration is appropriate
|
||||
2. Increase `max-tokens` if needed for higher throughput
|
||||
3. Ensure `refill-period` matches expected submission frequency
|
||||
|
||||
## Security Considerations
|
||||
|
||||
1. **Private Key Protection**: Store Ethereum private keys securely
|
||||
2. **Gas Management**: Monitor gas costs and set appropriate limits
|
||||
3. **Access Control**: Use dedicated accounts with minimal ETH
|
||||
4. **Monitoring**: Set up alerts for transaction failures and low balance
|
||||
|
||||
## Economics
|
||||
|
||||
### Gas Costs
|
||||
|
||||
- BEEFY proof submission: ~0.0003 ETH per message (varies with gas price)
|
||||
- Validator set updates: Higher gas cost (less frequent)
|
||||
|
||||
### Incentives
|
||||
|
||||
Relayers can earn incentives for successful proof submissions. See Snowbridge documentation for incentive structure.
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Beacon Relay](./snowbridge-beacon-relay.md)
|
||||
- [Execution Relay](./snowbridge-execution-relay.md)
|
||||
- [Solochain Relay](./snowbridge-solochain-relay.md)
|
||||
- [Snowbridge Documentation](https://docs.snowbridge.network)
|
||||
- [DataHaven Snowbridge Repository](https://github.com/datahaven-xyz/snowbridge)
|
||||
367
docs/snowbridge-execution-relay.md
Normal file
367
docs/snowbridge-execution-relay.md
Normal file
|
|
@ -0,0 +1,367 @@
|
|||
# Snowbridge Execution Relay
|
||||
|
||||
## Overview
|
||||
|
||||
The Execution Relay processes Ethereum execution layer events and delivers cross-chain messages to DataHaven. It monitors the Gateway contract on Ethereum and relays messages to the corresponding pallets on DataHaven.
|
||||
|
||||
## Purpose
|
||||
|
||||
- Relay Ethereum execution layer messages to DataHaven
|
||||
- Monitor Gateway contract for outbound messages
|
||||
- Submit message proofs to DataHaven for verification
|
||||
- Enable cross-chain token transfers and message passing from Ethereum
|
||||
|
||||
## Direction
|
||||
|
||||
```
|
||||
Ethereum Execution Layer → DataHaven
|
||||
```
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker with `linux/amd64` platform support
|
||||
- Access to Ethereum execution layer WebSocket endpoint
|
||||
- Access to Ethereum consensus layer (beacon) HTTP endpoint
|
||||
- Access to DataHaven node WebSocket endpoint
|
||||
- Substrate account with balance for transaction fees
|
||||
- Deployed Gateway contract on Ethereum
|
||||
- Persistent storage for relay datastore
|
||||
|
||||
## Key Requirements
|
||||
|
||||
### Substrate Private Key
|
||||
|
||||
The Execution Relay requires a **Substrate private key** to sign and submit extrinsics to DataHaven.
|
||||
|
||||
| Key Type | Purpose |
|
||||
|----------|---------|
|
||||
| Substrate (sr25519/ecdsa) | Sign message delivery extrinsics on DataHaven |
|
||||
|
||||
### Account Funding
|
||||
|
||||
The relay account must be funded with HAVE tokens to pay for transaction fees.
|
||||
|
||||
**Recommended Balance**: 100+ HAVE for continuous operations
|
||||
|
||||
## CLI Flags
|
||||
|
||||
### Required Flags
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--config <PATH>` | Path to the JSON configuration file |
|
||||
|
||||
### Private Key Flags (One Required)
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--substrate.private-key <KEY>` | Substrate private key URI directly |
|
||||
| `--substrate.private-key-file <PATH>` | Path to file containing the private key |
|
||||
| `--substrate.private-key-id <ID>` | AWS Secrets Manager secret ID for the private key |
|
||||
|
||||
## Configuration File
|
||||
|
||||
### Structure
|
||||
|
||||
```json
|
||||
{
|
||||
"source": {
|
||||
"ethereum": {
|
||||
"endpoint": "ws://ethereum-node:8546"
|
||||
},
|
||||
"contracts": {
|
||||
"Gateway": "0x8f86403A4DE0BB5791fa46B8e795C547942fE4Cf"
|
||||
},
|
||||
"beacon": {
|
||||
"endpoint": "http://beacon-node:4000",
|
||||
"stateEndpoint": "http://beacon-node:4000",
|
||||
"spec": {
|
||||
"syncCommitteeSize": 512,
|
||||
"slotsInEpoch": 32,
|
||||
"epochsPerSyncCommitteePeriod": 256,
|
||||
"forkVersions": {
|
||||
"deneb": 0,
|
||||
"electra": 0
|
||||
}
|
||||
},
|
||||
"datastore": {
|
||||
"location": "/relay-data",
|
||||
"maxEntries": 100
|
||||
}
|
||||
}
|
||||
},
|
||||
"sink": {
|
||||
"parachain": {
|
||||
"endpoint": "ws://datahaven-node:9944",
|
||||
"maxWatchedExtrinsics": 8,
|
||||
"headerRedundancy": 20
|
||||
}
|
||||
},
|
||||
"instantVerification": false,
|
||||
"schedule": {
|
||||
"id": null,
|
||||
"totalRelayerCount": 1,
|
||||
"sleepInterval": 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Configuration Parameters
|
||||
|
||||
#### Source (Ethereum)
|
||||
|
||||
| Parameter | Description | Example |
|
||||
|-----------|-------------|---------|
|
||||
| `source.ethereum.endpoint` | Ethereum execution layer WebSocket | `ws://ethereum-node:8546` |
|
||||
| `source.contracts.Gateway` | Gateway contract address | `0x...` |
|
||||
|
||||
#### Source (Beacon Chain)
|
||||
|
||||
| Parameter | Description | Example |
|
||||
|-----------|-------------|---------|
|
||||
| `source.beacon.endpoint` | Beacon chain HTTP API endpoint | `http://beacon-node:4000` |
|
||||
| `source.beacon.stateEndpoint` | Beacon chain state endpoint | `http://beacon-node:4000` |
|
||||
| `source.beacon.spec.*` | Beacon chain specification | See beacon spec parameters |
|
||||
| `source.beacon.datastore.location` | Path to persistent datastore | `/relay-data` |
|
||||
| `source.beacon.datastore.maxEntries` | Maximum datastore entries | `100` |
|
||||
|
||||
#### Sink (DataHaven)
|
||||
|
||||
| Parameter | Description | Example |
|
||||
|-----------|-------------|---------|
|
||||
| `sink.parachain.endpoint` | DataHaven WebSocket endpoint | `ws://datahaven-node:9944` |
|
||||
| `sink.parachain.maxWatchedExtrinsics` | Max concurrent watched extrinsics | `8` |
|
||||
| `sink.parachain.headerRedundancy` | Header redundancy factor | `20` |
|
||||
|
||||
#### Relay Settings
|
||||
|
||||
| Parameter | Description | Example |
|
||||
|-----------|-------------|---------|
|
||||
| `instantVerification` | Enable instant verification mode | `false` |
|
||||
| `schedule.id` | Relayer instance ID (for multi-instance) | `null` or `0` |
|
||||
| `schedule.totalRelayerCount` | Total number of relayer instances | `1` |
|
||||
| `schedule.sleepInterval` | Seconds between message checks | `1` |
|
||||
|
||||
## Multi-Instance Deployment
|
||||
|
||||
For high-availability or load distribution, multiple Execution Relayers can be deployed:
|
||||
|
||||
```json
|
||||
{
|
||||
"schedule": {
|
||||
"id": 0,
|
||||
"totalRelayerCount": 3,
|
||||
"sleepInterval": 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Each instance should have a unique `id` (0, 1, 2, ...) and the same `totalRelayerCount`.
|
||||
|
||||
## Running the Relay
|
||||
|
||||
### Docker Run
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
--name snowbridge-execution-relay \
|
||||
--platform linux/amd64 \
|
||||
--add-host host.docker.internal:host-gateway \
|
||||
--network datahaven-network \
|
||||
-v $(pwd)/execution-relay.json:/configs/execution-relay.json:ro \
|
||||
-v $(pwd)/relay-data:/relay-data \
|
||||
--pull always \
|
||||
datahavenxyz/snowbridge-relay:latest \
|
||||
run execution \
|
||||
--config /configs/execution-relay.json \
|
||||
--substrate.private-key "0x..."
|
||||
```
|
||||
|
||||
### Docker Compose
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
execution-relay:
|
||||
image: datahavenxyz/snowbridge-relay:latest
|
||||
container_name: snowbridge-execution-relay
|
||||
platform: linux/amd64
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./configs/execution-relay.json:/configs/execution-relay.json:ro
|
||||
- execution-relay-data:/relay-data
|
||||
command:
|
||||
- "run"
|
||||
- "execution"
|
||||
- "--config"
|
||||
- "/configs/execution-relay.json"
|
||||
- "--substrate.private-key-file"
|
||||
- "/secrets/substrate-key"
|
||||
secrets:
|
||||
- substrate-key
|
||||
|
||||
volumes:
|
||||
execution-relay-data:
|
||||
|
||||
secrets:
|
||||
substrate-key:
|
||||
file: ./secrets/execution-relay-substrate-key
|
||||
```
|
||||
|
||||
## Kubernetes Deployment
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: dh-execution-relay
|
||||
spec:
|
||||
serviceName: dh-execution-relay
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: dh-execution-relay
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: dh-execution-relay
|
||||
spec:
|
||||
containers:
|
||||
- name: execution-relay
|
||||
image: datahavenxyz/snowbridge-relay:latest
|
||||
imagePullPolicy: Always
|
||||
args:
|
||||
- "run"
|
||||
- "execution"
|
||||
- "--config"
|
||||
- "/configs/execution-relay.json"
|
||||
- "--substrate.private-key-file"
|
||||
- "/secrets/dh-execution-relay-substrate-key"
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /configs
|
||||
readOnly: true
|
||||
- name: secrets
|
||||
mountPath: /secrets
|
||||
readOnly: true
|
||||
- name: relay-data
|
||||
mountPath: /relay-data
|
||||
resources:
|
||||
requests:
|
||||
memory: "512Mi"
|
||||
cpu: "250m"
|
||||
limits:
|
||||
memory: "1Gi"
|
||||
cpu: "500m"
|
||||
volumes:
|
||||
- name: config
|
||||
configMap:
|
||||
name: execution-relay-config
|
||||
- name: secrets
|
||||
secret:
|
||||
secretName: dh-execution-relay-substrate-key
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: relay-data
|
||||
spec:
|
||||
accessModes: [ "ReadWriteOnce" ]
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
```
|
||||
|
||||
## Message Flow
|
||||
|
||||
### Ethereum → DataHaven Message Flow
|
||||
|
||||
1. User calls Gateway contract on Ethereum
|
||||
2. Gateway emits `OutboundMessageAccepted` event
|
||||
3. Execution Relay monitors for Gateway events
|
||||
4. Relay constructs message proof using beacon chain state
|
||||
5. Relay submits proof to DataHaven via `EthereumInboundQueue` pallet
|
||||
6. DataHaven verifies proof against beacon client state
|
||||
7. Message is dispatched to target pallet
|
||||
|
||||
### Supported Message Types
|
||||
|
||||
- Token transfers (ERC-20 tokens to DataHaven)
|
||||
- Arbitrary cross-chain messages
|
||||
- Smart contract calls
|
||||
|
||||
## Monitoring
|
||||
|
||||
### Health Checks
|
||||
|
||||
```bash
|
||||
# View relay logs
|
||||
docker logs -f snowbridge-execution-relay
|
||||
|
||||
# Check for message processing
|
||||
docker logs snowbridge-execution-relay 2>&1 | grep -i "message\|submit\|proof"
|
||||
```
|
||||
|
||||
### Key Metrics to Monitor
|
||||
|
||||
- Message queue depth
|
||||
- Message delivery success rate
|
||||
- Ethereum event processing lag
|
||||
- Account balance (for fees)
|
||||
- Beacon chain sync status
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Issue: Messages Not Being Delivered
|
||||
|
||||
**Check**:
|
||||
1. Gateway contract address is correct
|
||||
2. Ethereum endpoint is accessible
|
||||
3. Beacon chain is synced
|
||||
4. DataHaven node is accessible
|
||||
|
||||
```bash
|
||||
# Check Ethereum connectivity
|
||||
curl -X POST -H "Content-Type: application/json" \
|
||||
--data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
|
||||
http://ethereum-node:8545
|
||||
```
|
||||
|
||||
### Issue: Proof Verification Failures
|
||||
|
||||
**Check**:
|
||||
1. Beacon Relay is running and synced
|
||||
2. `EthereumBeaconClient` pallet has recent updates
|
||||
3. Beacon chain spec matches configuration
|
||||
|
||||
### Issue: High Latency
|
||||
|
||||
**Solutions**:
|
||||
1. Reduce `sleepInterval` for faster message detection
|
||||
2. Deploy multiple relay instances
|
||||
3. Ensure low-latency connections to endpoints
|
||||
|
||||
## Security Considerations
|
||||
|
||||
1. **Private Key Protection**: Store Substrate private keys securely
|
||||
2. **Network Security**: Use secure connections (WSS) when possible
|
||||
3. **Access Control**: Use dedicated accounts with minimal permissions
|
||||
4. **Monitoring**: Set up alerts for message delivery failures
|
||||
|
||||
## Economics
|
||||
|
||||
### Transaction Costs
|
||||
|
||||
- Message delivery: ~0.012 DOT equivalent per message (varies with message size)
|
||||
- Relayers earn incentives for successful deliveries
|
||||
|
||||
### Incentive Structure
|
||||
|
||||
Relayers can claim incentives from the protocol for successful message deliveries. See Snowbridge documentation for details.
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Beacon Relay](./snowbridge-beacon-relay.md)
|
||||
- [BEEFY Relay](./snowbridge-beefy-relay.md)
|
||||
- [Solochain Relay](./snowbridge-solochain-relay.md)
|
||||
- [Snowbridge Documentation](https://docs.snowbridge.network)
|
||||
- [DataHaven Snowbridge Repository](https://github.com/datahaven-xyz/snowbridge)
|
||||
418
docs/snowbridge-solochain-relay.md
Normal file
418
docs/snowbridge-solochain-relay.md
Normal file
|
|
@ -0,0 +1,418 @@
|
|||
# Snowbridge Solochain Relay
|
||||
|
||||
## Overview
|
||||
|
||||
The Solochain Relay handles DataHaven-specific operations, including relaying outbound messages from DataHaven to Ethereum and managing validator reward distributions. This relay is specific to the DataHaven solochain implementation of Snowbridge.
|
||||
|
||||
## Purpose
|
||||
|
||||
- Relay DataHaven outbound messages to Ethereum
|
||||
- Submit messages to the Gateway contract on Ethereum
|
||||
- Handle validator reward synchronization
|
||||
- Enable cross-chain token transfers from DataHaven to Ethereum
|
||||
|
||||
## Direction
|
||||
|
||||
```
|
||||
DataHaven → Ethereum (with bidirectional monitoring)
|
||||
```
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker with `linux/amd64` platform support
|
||||
- Access to DataHaven node WebSocket endpoint
|
||||
- Access to Ethereum execution layer WebSocket endpoint
|
||||
- Access to Ethereum consensus layer (beacon) HTTP endpoint
|
||||
- Ethereum account with ETH for gas fees
|
||||
- Substrate account for DataHaven operations
|
||||
- Deployed BeefyClient, Gateway, and RewardsRegistry contracts on Ethereum
|
||||
- Persistent storage for relay datastore
|
||||
|
||||
## Key Requirements
|
||||
|
||||
### Both Ethereum and Substrate Private Keys
|
||||
|
||||
The Solochain Relay requires **both** an Ethereum private key and a Substrate private key.
|
||||
|
||||
| Key Type | Purpose |
|
||||
|----------|---------|
|
||||
| Ethereum (secp256k1) | Sign Ethereum transactions to Gateway contract |
|
||||
| Substrate (sr25519/ecdsa) | Sign DataHaven operations |
|
||||
|
||||
### Account Funding
|
||||
|
||||
| Account | Funding Required |
|
||||
|---------|-----------------|
|
||||
| Ethereum | 0.5+ ETH for gas fees |
|
||||
| Substrate | 100+ HAVE for transaction fees |
|
||||
|
||||
## CLI Flags
|
||||
|
||||
### Required Flags
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--config <PATH>` | Path to the JSON configuration file |
|
||||
|
||||
### Ethereum Private Key Flags (One Required)
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--ethereum.private-key <KEY>` | Ethereum private key directly |
|
||||
| `--ethereum.private-key-file <PATH>` | Path to file containing the private key |
|
||||
| `--ethereum.private-key-id <ID>` | AWS Secrets Manager secret ID for the private key |
|
||||
|
||||
### Substrate Private Key Flag
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--substrate.private-key <KEY>` | Substrate private key URI |
|
||||
|
||||
## Configuration File
|
||||
|
||||
### Structure
|
||||
|
||||
```json
|
||||
{
|
||||
"source": {
|
||||
"ethereum": {
|
||||
"endpoint": "ws://ethereum-node:8546"
|
||||
},
|
||||
"solochain": {
|
||||
"endpoint": "ws://datahaven-node:9944"
|
||||
},
|
||||
"contracts": {
|
||||
"BeefyClient": "0x4826533B4897376654Bb4d4AD88B7faFD0C98528",
|
||||
"Gateway": "0x8f86403A4DE0BB5791fa46B8e795C547942fE4Cf"
|
||||
},
|
||||
"beacon": {
|
||||
"endpoint": "http://beacon-node:4000",
|
||||
"stateEndpoint": "http://beacon-node:4000",
|
||||
"spec": {
|
||||
"syncCommitteeSize": 512,
|
||||
"slotsInEpoch": 32,
|
||||
"epochsPerSyncCommitteePeriod": 256,
|
||||
"forkVersions": {
|
||||
"deneb": 0,
|
||||
"electra": 0
|
||||
}
|
||||
},
|
||||
"datastore": {
|
||||
"location": "/relay-data",
|
||||
"maxEntries": 100
|
||||
}
|
||||
}
|
||||
},
|
||||
"sink": {
|
||||
"ethereum": {
|
||||
"endpoint": "ws://ethereum-node:8546"
|
||||
},
|
||||
"contracts": {
|
||||
"Gateway": "0x8f86403A4DE0BB5791fa46B8e795C547942fE4Cf"
|
||||
}
|
||||
},
|
||||
"schedule": {
|
||||
"id": 0,
|
||||
"totalRelayerCount": 1,
|
||||
"sleepInterval": 10
|
||||
},
|
||||
"reward-address": "0x4c5859f0F772848b2D91F1D83E2Fe57935348029",
|
||||
"ofac": {
|
||||
"enabled": false,
|
||||
"apiKey": ""
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Configuration Parameters
|
||||
|
||||
#### Source Configuration
|
||||
|
||||
| Parameter | Description | Example |
|
||||
|-----------|-------------|---------|
|
||||
| `source.ethereum.endpoint` | Ethereum WebSocket endpoint | `ws://ethereum-node:8546` |
|
||||
| `source.solochain.endpoint` | DataHaven WebSocket endpoint | `ws://datahaven-node:9944` |
|
||||
| `source.contracts.BeefyClient` | BeefyClient contract address | `0x...` |
|
||||
| `source.contracts.Gateway` | Gateway contract address | `0x...` |
|
||||
| `source.beacon.*` | Beacon chain configuration | See beacon spec |
|
||||
|
||||
#### Sink Configuration
|
||||
|
||||
| Parameter | Description | Example |
|
||||
|-----------|-------------|---------|
|
||||
| `sink.ethereum.endpoint` | Ethereum WebSocket endpoint | `ws://ethereum-node:8546` |
|
||||
| `sink.contracts.Gateway` | Gateway contract address | `0x...` |
|
||||
|
||||
#### Schedule Configuration
|
||||
|
||||
| Parameter | Description | Example |
|
||||
|-----------|-------------|---------|
|
||||
| `schedule.id` | Relayer instance ID (for multi-instance) | `0` |
|
||||
| `schedule.totalRelayerCount` | Total number of relayer instances | `1` |
|
||||
| `schedule.sleepInterval` | Seconds between message checks | `10` |
|
||||
|
||||
#### Rewards Configuration
|
||||
|
||||
| Parameter | Description | Example |
|
||||
|-----------|-------------|---------|
|
||||
| `reward-address` | RewardsRegistry contract address | `0x...` |
|
||||
|
||||
#### OFAC Compliance (Optional)
|
||||
|
||||
| Parameter | Description | Example |
|
||||
|-----------|-------------|---------|
|
||||
| `ofac.enabled` | Enable OFAC sanctions screening | `false` |
|
||||
| `ofac.apiKey` | API key for OFAC screening service | `""` |
|
||||
|
||||
## Contract Requirements
|
||||
|
||||
### Required Contracts
|
||||
|
||||
1. **BeefyClient**: Verifies BEEFY finality proofs on Ethereum
|
||||
2. **Gateway**: Handles cross-chain message passing
|
||||
3. **RewardsRegistry**: Manages validator reward distribution
|
||||
|
||||
### Get Contract Addresses
|
||||
|
||||
```typescript
|
||||
const deployments = await parseDeploymentsFile();
|
||||
const beefyClientAddress = deployments.BeefyClient;
|
||||
const gatewayAddress = deployments.Gateway;
|
||||
const rewardsRegistryAddress = deployments.RewardsRegistry;
|
||||
```
|
||||
|
||||
## Running the Relay
|
||||
|
||||
### Docker Run
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
--name snowbridge-solochain-relay \
|
||||
--platform linux/amd64 \
|
||||
--add-host host.docker.internal:host-gateway \
|
||||
--network datahaven-network \
|
||||
-v $(pwd)/solochain-relay.json:/configs/solochain-relay.json:ro \
|
||||
-v $(pwd)/relay-data:/relay-data \
|
||||
--pull always \
|
||||
datahavenxyz/snowbridge-relay:latest \
|
||||
run solochain \
|
||||
--config /configs/solochain-relay.json \
|
||||
--ethereum.private-key "0x..." \
|
||||
--substrate.private-key "0x..."
|
||||
```
|
||||
|
||||
### Docker Compose
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
solochain-relay:
|
||||
image: datahavenxyz/snowbridge-relay:latest
|
||||
container_name: snowbridge-solochain-relay
|
||||
platform: linux/amd64
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./configs/solochain-relay.json:/configs/solochain-relay.json:ro
|
||||
- solochain-relay-data:/relay-data
|
||||
command:
|
||||
- "run"
|
||||
- "solochain"
|
||||
- "--config"
|
||||
- "/configs/solochain-relay.json"
|
||||
- "--ethereum.private-key-file"
|
||||
- "/secrets/ethereum-key"
|
||||
- "--substrate.private-key"
|
||||
- "${SUBSTRATE_PRIVATE_KEY}"
|
||||
secrets:
|
||||
- ethereum-key
|
||||
environment:
|
||||
- SUBSTRATE_PRIVATE_KEY=${SUBSTRATE_PRIVATE_KEY}
|
||||
|
||||
volumes:
|
||||
solochain-relay-data:
|
||||
|
||||
secrets:
|
||||
ethereum-key:
|
||||
file: ./secrets/solochain-relay-ethereum-key
|
||||
```
|
||||
|
||||
## Kubernetes Deployment
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: dh-solochain-relay
|
||||
spec:
|
||||
serviceName: dh-solochain-relay
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: dh-solochain-relay
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: dh-solochain-relay
|
||||
spec:
|
||||
containers:
|
||||
- name: solochain-relay
|
||||
image: datahavenxyz/snowbridge-relay:latest
|
||||
imagePullPolicy: Always
|
||||
args:
|
||||
- "run"
|
||||
- "solochain"
|
||||
- "--config"
|
||||
- "/configs/solochain-relay.json"
|
||||
- "--ethereum.private-key-file"
|
||||
- "/secrets/dh-solochain-relay-ethereum-key"
|
||||
- "--substrate.private-key"
|
||||
- "$(SUBSTRATE_PRIVATE_KEY)"
|
||||
env:
|
||||
- name: SUBSTRATE_PRIVATE_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: dh-solochain-relay-substrate-key
|
||||
key: private-key
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /configs
|
||||
readOnly: true
|
||||
- name: secrets
|
||||
mountPath: /secrets
|
||||
readOnly: true
|
||||
- name: relay-data
|
||||
mountPath: /relay-data
|
||||
resources:
|
||||
requests:
|
||||
memory: "512Mi"
|
||||
cpu: "250m"
|
||||
limits:
|
||||
memory: "1Gi"
|
||||
cpu: "500m"
|
||||
volumes:
|
||||
- name: config
|
||||
configMap:
|
||||
name: solochain-relay-config
|
||||
- name: secrets
|
||||
secret:
|
||||
secretName: dh-solochain-relay-ethereum-key
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: relay-data
|
||||
spec:
|
||||
accessModes: [ "ReadWriteOnce" ]
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
```
|
||||
|
||||
## Message Flow
|
||||
|
||||
### DataHaven → Ethereum Message Flow
|
||||
|
||||
1. User submits outbound message on DataHaven
|
||||
2. `EthereumOutboundQueue` pallet queues the message
|
||||
3. Solochain Relay monitors for outbound messages
|
||||
4. Relay constructs message proof using BEEFY finality
|
||||
5. Relay submits proof to Gateway contract on Ethereum
|
||||
6. Gateway verifies proof against BeefyClient
|
||||
7. Message is executed on Ethereum
|
||||
|
||||
### Reward Distribution Flow
|
||||
|
||||
1. Validators earn rewards on DataHaven
|
||||
2. Reward data is synchronized to RewardsRegistry contract
|
||||
3. Operators can claim rewards on Ethereum
|
||||
|
||||
## Multi-Instance Deployment
|
||||
|
||||
For high-availability, deploy multiple Solochain Relayers:
|
||||
|
||||
```json
|
||||
{
|
||||
"schedule": {
|
||||
"id": 0,
|
||||
"totalRelayerCount": 2,
|
||||
"sleepInterval": 10
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Instance 0**:
|
||||
```json
|
||||
{ "schedule": { "id": 0, "totalRelayerCount": 2, "sleepInterval": 10 } }
|
||||
```
|
||||
|
||||
**Instance 1**:
|
||||
```json
|
||||
{ "schedule": { "id": 1, "totalRelayerCount": 2, "sleepInterval": 10 } }
|
||||
```
|
||||
|
||||
## Monitoring
|
||||
|
||||
### Health Checks
|
||||
|
||||
```bash
|
||||
# View relay logs
|
||||
docker logs -f snowbridge-solochain-relay
|
||||
|
||||
# Check for message processing
|
||||
docker logs snowbridge-solochain-relay 2>&1 | grep -i "message\|submit\|reward"
|
||||
```
|
||||
|
||||
### Key Metrics to Monitor
|
||||
|
||||
- Outbound message queue depth
|
||||
- Message delivery success rate
|
||||
- Reward synchronization status
|
||||
- Ethereum and Substrate account balances
|
||||
- BEEFY finality status
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Issue: Messages Not Being Delivered
|
||||
|
||||
**Check**:
|
||||
1. BeefyClient has recent commitments (BEEFY Relay running)
|
||||
2. Gateway contract address is correct
|
||||
3. Both Ethereum and Substrate endpoints are accessible
|
||||
4. Account balances are sufficient
|
||||
|
||||
### Issue: Reward Synchronization Failures
|
||||
|
||||
**Check**:
|
||||
1. RewardsRegistry contract address is correct
|
||||
2. Ethereum account has sufficient gas
|
||||
3. Reward data is available on DataHaven
|
||||
|
||||
### Issue: OFAC Screening Failures
|
||||
|
||||
**Check**:
|
||||
1. API key is valid (if OFAC enabled)
|
||||
2. Network connectivity to OFAC service
|
||||
3. Consider disabling OFAC for testing environments
|
||||
|
||||
## Security Considerations
|
||||
|
||||
1. **Private Key Protection**: Secure both Ethereum and Substrate keys
|
||||
2. **Dual Account Management**: Monitor balances on both chains
|
||||
3. **Network Security**: Use secure connections (WSS) when possible
|
||||
4. **Access Control**: Use dedicated accounts with minimal permissions
|
||||
5. **OFAC Compliance**: Enable OFAC screening for production if required
|
||||
|
||||
## Dependencies
|
||||
|
||||
The Solochain Relay depends on:
|
||||
- **BEEFY Relay**: Must be running to provide finality proofs
|
||||
- **Beacon Relay**: Must be running for Ethereum light client state
|
||||
|
||||
Ensure both relays are operational before starting the Solochain Relay.
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Beacon Relay](./snowbridge-beacon-relay.md)
|
||||
- [BEEFY Relay](./snowbridge-beefy-relay.md)
|
||||
- [Execution Relay](./snowbridge-execution-relay.md)
|
||||
- [Snowbridge Documentation](https://docs.snowbridge.network)
|
||||
- [DataHaven Snowbridge Repository](https://github.com/datahaven-xyz/snowbridge)
|
||||
Loading…
Reference in a new issue