Skip to content
Draft
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
3 changes: 2 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ CONSENSUS_CLIENT_URI=http://...
EXECUTION_CLIENT_URI=http://...
KEYS_API_URI=https://...
LIDO_LOCATOR_ADDRESS=0x1...
CSM_MODULE_ADDRESS=0x...
CS_MODULE_ADDRESS=0x...
CURATED_MODULE_ADDRESS=0x...
MEMBER_PRIV_KEY=aaa...
PINATA_JWT=...
STORACHA_AUTH_SECRET=...
Expand Down
2 changes: 1 addition & 1 deletion .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ Describe how you tested the changes:
## Checklist
- [ ] Documentation updated (if required)
- [ ] New tests added (if applicable)
- [ ] `CSM_STATE_VERSION` is bumped (if the new version affects data in the cache)
- [ ] `STAKING_MODULE_STATE_VERSION` is bumped (if the new version affects data in the cache)
6 changes: 4 additions & 2 deletions .github/workflows/ci-daily-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ jobs:
CONSENSUS_CLIENT_URI: ${{ secrets.CONSENSUS_CLIENT_URI }}
KEYS_API_URI: ${{ secrets.KEYS_API_URI }}
LIDO_LOCATOR_ADDRESS: ${{ secrets.LIDO_LOCATOR_ADDRESS }}
CSM_MODULE_ADDRESS: ${{ secrets.CSM_MODULE_ADDRESS }}
CS_MODULE_ADDRESS: ${{ secrets.CS_MODULE_ADDRESS }}
CURATED_MODULE_ADDRESS: ${{ secrets.CURATED_MODULE_ADDRESS }}
PINATA_JWT: ${{ secrets.PINATA_JWT }}
PINATA_DEDICATED_GATEWAY_URL: ${{ secrets.PINATA_DEDICATED_GATEWAY_URL }}
PINATA_DEDICATED_GATEWAY_TOKEN: ${{ secrets.PINATA_DEDICATED_GATEWAY_TOKEN}}
Expand All @@ -39,7 +40,8 @@ jobs:
CONSENSUS_CLIENT_URI=${CONSENSUS_CLIENT_URI}
KEYS_API_URI=${KEYS_API_URI}
LIDO_LOCATOR_ADDRESS=${LIDO_LOCATOR_ADDRESS}
CSM_MODULE_ADDRESS=${CSM_MODULE_ADDRESS}
CS_MODULE_ADDRESS=${CS_MODULE_ADDRESS}
CURATED_MODULE_ADDRESS=${CURATED_MODULE_ADDRESS}
GW3_ACCESS_KEY=${GW3_ACCESS_KEY}
GW3_SECRET_KEY=${GW3_SECRET_KEY}
PINATA_JWT=${PINATA_JWT}
Expand Down
35 changes: 2 additions & 33 deletions .github/workflows/mainnet_fork_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,38 +26,6 @@ jobs:
steps:
- uses: actions/checkout@v3

# TODO: Remove after upgrade to CSM v2 on Mainnet.
- name: Checkout CSM repo
uses: actions/checkout@v4
with:
repository: 'lidofinance/community-staking-module'
ref: 'develop'
path: 'testruns/community-staking-module'
persist-credentials: false

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
with:
version: ${{ env.FORGE_REV }}

- name: Install node
uses: actions/setup-node@v4
with:
node-version-file: "testruns/community-staking-module/.nvmrc"
cache: 'yarn'
cache-dependency-path: "testruns/community-staking-module/yarn.lock"

- name: Install Just
run: cargo install "[email protected]"

- name: Install dependencies
working-directory: testruns/community-staking-module
run: just deps

- name: Build contracts
working-directory: testruns/community-staking-module
run: just build

- name: Set up Python 3.12
uses: actions/setup-python@v4
with:
Expand All @@ -82,7 +50,8 @@ jobs:
CONSENSUS_CLIENT_URI: ${{ secrets.CONSENSUS_CLIENT_URI }}
KEYS_API_URI: ${{ secrets.KEYS_API_URI }}
LIDO_LOCATOR_ADDRESS: "0xC1d0b3DE6792Bf6b4b37EccdcC24e45978Cfd2Eb"
CSM_MODULE_ADDRESS: "0xdA7dE2ECdDfccC6c3AF10108Db212ACBBf9EA83F"
CS_MODULE_ADDRESS: "0xdA7dE2ECdDfccC6c3AF10108Db212ACBBf9EA83F"
CURATED_MODULE_ADDRESS: "0xdA7dE2ECdDfccC6c3AF10108Db212ACBBf9EA83F" # TODO: replace with actual address
PINATA_JWT: ${{ secrets.PINATA_JWT }}
PINATA_DEDICATED_GATEWAY_URL: ${{ secrets.PINATA_DEDICATED_GATEWAY_URL }}
PINATA_DEDICATED_GATEWAY_TOKEN: ${{ secrets.PINATA_DEDICATED_GATEWAY_TOKEN }}
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ jobs:
TESTNET_EXECUTION_CLIENT_URI: ${{ secrets.TESTNET_EXECUTION_CLIENT_URI }}
TESTNET_CONSENSUS_CLIENT_URI: ${{ secrets.TESTNET_CONSENSUS_CLIENT_URI }}
TESTNET_KAPI_URI: ${{ secrets.TESTNET_KAPI_URI }}
CSM_MODULE_ADDRESS: "0xdA7dE2ECdDfccC6c3AF10108Db212ACBBf9EA83F"
CS_MODULE_ADDRESS: "0xdA7dE2ECdDfccC6c3AF10108Db212ACBBf9EA83F"
CURATED_MODULE_ADDRESS: "0xdA7dE2ECdDfccC6c3AF10108Db212ACBBf9EA83F" # TODO: replace with actual address
PINATA_JWT: ${{ secrets.PINATA_JWT }}
PINATA_DEDICATED_GATEWAY_URL: ${{ secrets.PINATA_DEDICATED_GATEWAY_URL }}
PINATA_DEDICATED_GATEWAY_TOKEN: ${{ secrets.PINATA_DEDICATED_GATEWAY_TOKEN }}
Expand Down
159 changes: 79 additions & 80 deletions README.md

Large diffs are not rendered by default.

149 changes: 149 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
# Usage:
# Local development: docker compose up -d
# External PostgreSQL: PERFORMANCE_DB_HOST=your-host docker compose up -d performance-collector performance-web
# Run init-db only: docker compose up init-db

x-healthcheck-defaults: &healthcheck-defaults
interval: 30s
timeout: 10s
retries: 3
start_period: 40s

x-performance-db-env: &performance-db-env
PERFORMANCE_DB_HOST: ${PERFORMANCE_DB_HOST:-postgres}
PERFORMANCE_DB_PORT: ${PERFORMANCE_DB_PORT:-5432}
PERFORMANCE_DB_NAME: ${PERFORMANCE_DB_NAME:-performance}
PERFORMANCE_DB_USER: ${PERFORMANCE_DB_USER:-performance}
PERFORMANCE_DB_PASSWORD: ${PERFORMANCE_DB_PASSWORD:-performance}

services:
# ---------------------------------------------------------------------------
# Database Layer
# ---------------------------------------------------------------------------

postgres:
image: postgres:15
container_name: staking-module-oracle-postgres
environment:
POSTGRES_USER: ${PERFORMANCE_DB_ADMIN_USER:-postgres}
POSTGRES_PASSWORD: ${PERFORMANCE_DB_ADMIN_PASSWORD:-postgres}
POSTGRES_DB: postgres
ports:
- "${POSTGRES_PORT:-5432}:5432"
volumes:
- postgres-data:/var/lib/postgresql/data
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${PERFORMANCE_DB_ADMIN_USER:-postgres}"]
interval: 5s
timeout: 5s
retries: 5

# One-time database initialization (creates user and database)
# For external PostgreSQL: set PERFORMANCE_DB_HOST to your external host
init-db:
image: postgres:15
container_name: staking-module-oracle-init-db
depends_on:
postgres:
condition: service_healthy
environment:
<<: *performance-db-env
PERFORMANCE_DB_ADMIN_USER: ${PERFORMANCE_DB_ADMIN_USER:-postgres}
PERFORMANCE_DB_ADMIN_PASSWORD: ${PERFORMANCE_DB_ADMIN_PASSWORD:-postgres}
volumes:
- ./scripts:/scripts:ro
entrypoint: ["/bin/bash", "/scripts/init_performance_db.sh"]
restart: "no"

# ---------------------------------------------------------------------------
# Performance Sidecar
# ---------------------------------------------------------------------------

performance-collector:
build: .
container_name: staking-module-oracle-performance-collector
command: ["-m", "src.main", "performance_collector"]
depends_on:
init-db:
condition: service_completed_successfully
environment:
<<: *performance-db-env
CONSENSUS_CLIENT_URI: ${CONSENSUS_CLIENT_URI}
MAX_CYCLE_LIFETIME_IN_SECONDS: ${MAX_CYCLE_LIFETIME_IN_SECONDS:-60000}
ports:
- "${PERFORMANCE_COLLECTOR_PROMETHEUS_PORT:-9000}:9000"
- "${PERFORMANCE_COLLECTOR_HEALTH_PORT:-9010}:9010"
healthcheck:
<<: *healthcheck-defaults
test: ["CMD", "curl", "-f", "http://localhost:9010/healthcheck"]

performance-web:
build: .
container_name: staking-module-oracle-performance-web
command: ["-m", "src.main", "performance_web_server"]
depends_on:
init-db:
condition: service_completed_successfully
environment:
<<: *performance-db-env
ports:
- "${PERFORMANCE_WEB_PORT:-9020}:9020"
healthcheck:
<<: *healthcheck-defaults
test: ["CMD", "curl", "-f", "http://localhost:9020/health"]

# ---------------------------------------------------------------------------
# Staking Module Oracles
# ---------------------------------------------------------------------------

csm-oracle:
build: .
container_name: csm-oracle
command: ["-m", "src.main", "csm"]
environment:
CS_MODULE_ADDRESS: ${CS_MODULE_ADDRESS}
CONSENSUS_CLIENT_URI: ${CONSENSUS_CLIENT_URI}
EXECUTION_CLIENT_URI: ${EXECUTION_CLIENT_URI}
KEYS_API_URI: ${KEYS_API_URI}
PERFORMANCE_COLLECTOR_URI: http://performance-web:9020/
LIDO_IPFS_HOST: ${LIDO_IPFS_HOST:-}
LIDO_IPFS_TOKEN: ${LIDO_IPFS_TOKEN:-}
PROMETHEUS_PORT: 9000
HEALTHCHECK_SERVER_PORT: 9010
ports:
- "${CSM_ORACLE_PROMETHEUS_PORT:-9001}:9000"
- "${CSM_ORACLE_HEALTH_PORT:-9011}:9010"
restart: unless-stopped
healthcheck:
<<: *healthcheck-defaults
test: ["CMD", "curl", "-f", "http://localhost:9010/healthcheck"]

# cm-oracle:
# build: .
# container_name: cm-oracle
# command: ["-m", "src.main", "cm"]
# environment:
# CURATED_MODULE_ADDRESS: ${CURATED_MODULE_ADDRESS}
# CONSENSUS_CLIENT_URI: ${CONSENSUS_CLIENT_URI}
# EXECUTION_CLIENT_URI: ${EXECUTION_CLIENT_URI}
# KEYS_API_URI: ${KEYS_API_URI}
# PERFORMANCE_COLLECTOR_URI: http://performance-web:9020/
# LIDO_IPFS_HOST: ${LIDO_IPFS_HOST:-}
# LIDO_IPFS_TOKEN: ${LIDO_IPFS_TOKEN:-}
# PROMETHEUS_PORT: 9000
# HEALTHCHECK_SERVER_PORT: 9010
# ports:
# - "${CSM_ORACLE_PROMETHEUS_PORT:-9002}:9000"
# - "${CSM_ORACLE_HEALTH_PORT:-9012}:9010"
# restart: unless-stopped
# healthcheck:
# <<: *healthcheck-defaults
# test: ["CMD", "curl", "-f", "http://localhost:9010/healthcheck"]

volumes:
postgres-data:

networks:
default:
name: oracle-network
6 changes: 4 additions & 2 deletions docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,15 @@ export KEYS_API_URI=...
export LIDO_LOCATOR_ADDRESS=...
```

Required variables for CSM module
Required variables for Staking Module Oracle

```bash
export EXECUTION_CLIENT_URI=...
export CONSENSUS_CLIENT_URI=...
export KEYS_API_URI=...
export LIDO_LOCATOR_ADDRESS=...
export CSM_MODULE_ADDRESS=...
export CS_MODULE_ADDRESS=...
export CURATED_MODULE_ADDRESS=...
export MAX_CYCLE_LIFETIME_IN_SECONDS=60000 # Reasonable high value to make sure the oracle has enough time to process the whole frame.
```

Expand All @@ -67,6 +68,7 @@ Where `<module>` is one of:
- `accounting`
- `ejector`
- `csm`
- `cm`
- `check`

## Code quality
Expand Down
100 changes: 100 additions & 0 deletions scripts/init_performance_db.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#!/bin/bash
#
# Script to initialize the Performance database.
# This creates the required user and database for the Performance Collector and Web Server.
#

set -e

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}

log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}

log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}

# Admin connection settings
DB_HOST="${PERFORMANCE_DB_HOST:-localhost}"
DB_PORT="${PERFORMANCE_DB_PORT:-5432}"
ADMIN_USER="${PERFORMANCE_DB_ADMIN_USER:-postgres}"
ADMIN_PASSWORD="${PERFORMANCE_DB_ADMIN_PASSWORD}"

# New user/database settings
DB_NAME="${PERFORMANCE_DB_NAME:-performance}"
DB_USER="${PERFORMANCE_DB_USER:-performance}"
DB_PASSWORD="${PERFORMANCE_DB_PASSWORD:-performance}"

# Validate required variables
if [ -z "$ADMIN_PASSWORD" ]; then
log_error "PERFORMANCE_DB_ADMIN_PASSWORD is required"
exit 1
fi

log_info "Connecting to PostgreSQL at ${DB_HOST}:${DB_PORT} as ${ADMIN_USER}"

# Export password for psql
export PGPASSWORD="$ADMIN_PASSWORD"

# Function to run SQL command
run_sql() {
psql -h "$DB_HOST" -p "$DB_PORT" -U "$ADMIN_USER" -d postgres -tAc "$1"
}

# Check if user exists
user_exists() {
local result
result=$(run_sql "SELECT 1 FROM pg_roles WHERE rolname='$DB_USER'" 2>/dev/null)
[ "$result" = "1" ]
}

# Check if database exists
db_exists() {
local result
result=$(run_sql "SELECT 1 FROM pg_database WHERE datname='$DB_NAME'" 2>/dev/null)
[ "$result" = "1" ]
}

# Create user if not exists
if user_exists; then
log_warn "User '$DB_USER' already exists, skipping creation"
else
log_info "Creating user '$DB_USER'..."
run_sql "CREATE USER $DB_USER WITH PASSWORD '$DB_PASSWORD'"
log_info "User '$DB_USER' created successfully"
fi

# Create database if not exists
if db_exists; then
log_warn "Database '$DB_NAME' already exists, skipping creation"
else
log_info "Creating database '$DB_NAME' with owner '$DB_USER'..."
run_sql "CREATE DATABASE $DB_NAME OWNER $DB_USER"
log_info "Database '$DB_NAME' created successfully"
fi

# Grant privileges
log_info "Granting privileges..."
run_sql "GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $DB_USER"

# Connect to the new database and grant schema privileges
export PGPASSWORD="$ADMIN_PASSWORD"
psql -h "$DB_HOST" -p "$DB_PORT" -U "$ADMIN_USER" -d "$DB_NAME" -c "GRANT ALL ON SCHEMA public TO $DB_USER"

log_info "Database initialization completed successfully!"
log_info ""
log_info "Connection details:"
log_info " Host: $DB_HOST"
log_info " Port: $DB_PORT"
log_info " Database: $DB_NAME"
log_info " User: $DB_USER"
7 changes: 3 additions & 4 deletions src/constants.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from packaging.version import Version

from src.types import Gwei

# https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#misc
FAR_FUTURE_EPOCH = 2**64 - 1
# https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#time-parameters-1
Expand Down Expand Up @@ -50,7 +49,7 @@
SHARE_RATE_PRECISION_E27 = 10**PRECISION_E27
TOTAL_BASIS_POINTS = 10000

# Lido CSM constants for network performance calculation
# Lido Staking Module constants for network performance calculation
ATTESTATIONS_WEIGHT = 54
BLOCKS_WEIGHT = 8
SYNC_WEIGHT = 2
Expand All @@ -62,7 +61,7 @@
UINT256_MAX = 2**256 - 1

ALLOWED_KAPI_VERSION = Version('1.5.0')
CSM_STATE_VERSION = 1
CSM_LOGS_VERSION = 1
STAKING_MODULE_STATE_VERSION = 1
STAKING_MODULE_LOGS_VERSION = 1

GENESIS_VALIDATORS_ROOT = bytes([0] * 32) # all zeros for deposits
Loading