Ctrl K
ComunidadGuías…

docker-compose.regtest.yml

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Local regtest e2e stack: bitcoind + postgres + 3 Spark Operators + our SSP.
#
# Usage:
#   git submodule update --init --recursive
#   SPARK_ADMIN_TOKEN=regtest-spark-admin-token docker compose -f docker-compose.regtest.yml up --build -d
#   ./e2e/e2e.sh   # resets a separate test project and tears it down afterward
#   docker compose -f docker-compose.regtest.yml down
#
# Sources default to the pinned Git submodules in vendor/. Override SPARK_REF
# or LDK_SERVER_REF to build from other local checkouts.
#
# Host ports: bitcoind RPC uses BITCOIN_RPC_PORT (8332 by default), SOs use
# 8535-8537, and SSP uses 5000. PostgreSQL and bitcoind ZMQ stay private.

x-operator-common: &operator-common
  image: ${SPARK_OPERATOR_IMAGE:-open-ssp-spark-operator:regtest}
  build:
    context: ${SPARK_REF:-./vendor/spark}
    dockerfile: Dockerfile
  depends_on:
    postgres:
      condition: service_healthy
    bitcoin-init:
      condition: service_completed_successfully
    cert-init:
      condition: service_completed_successfully
  restart: unless-stopped
  entrypoint: ["/bin/sh", "-c"]
  volumes:
    - ./e2e/upstream/entrypoint.sh:/opt/spark/entrypoint.sh:ro
    - ./e2e/upstream/config.json:/opt/spark/config.json:ro
    - ./e2e/upstream/operator.config.yaml:/opt/spark/operator.config.yaml:ro
    - ./e2e/upstream/operator_0.key:/opt/spark/keys/operator_0.key:ro
    - ./e2e/upstream/operator_1.key:/opt/spark/keys/operator_1.key:ro
    - ./e2e/upstream/operator_2.key:/opt/spark/keys/operator_2.key:ro
    - tls-certs:/opt/spark/tls:ro

services:
  cert-init:
    image: alpine:3.20
    restart: "no"
    entrypoint: ["/bin/sh", "-c"]
    command:
      - |
        set -e
        apk add --no-cache openssl > /dev/null
        for i in 0 1 2; do
          KEY="/tls/server_$${i}.key"
          CERT="/tls/server_$${i}.crt"
          if [ -f "$$KEY" ] && [ -f "$$CERT" ] \
            && openssl x509 -in "$$CERT" -noout -ext basicConstraints 2>/dev/null \
              | grep -q "CA:FALSE"; then
            echo "TLS key/cert for operator $$i already exist, skipping"
            continue
          fi
          echo "Generating TLS server key/cert for operator $$i..."
          TMP_KEY="$${KEY}.tmp"
          TMP_CERT="$${CERT}.tmp"
          openssl genrsa -out "$$TMP_KEY" 2048 2>/dev/null
          openssl req -new -x509 \
            -key "$$TMP_KEY" -out "$$TMP_CERT" \
            -days 3650 \
            -subj "/CN=spark-operator-$${i}" \
            -addext "subjectAltName = DNS:spark-operator-$${i},DNS:localhost,DNS:spark-operator-$${i}.minikube.local" \
            -addext "basicConstraints = critical,CA:FALSE" \
            -addext "keyUsage = critical,digitalSignature,keyEncipherment" \
            -addext "extendedKeyUsage = serverAuth"
          mv "$$TMP_KEY" "$$KEY"
          mv "$$TMP_CERT" "$$CERT"
        done
        echo "TLS certificates ready"
    volumes:
      - tls-certs:/tls

  postgres:
    image: postgres:16-bookworm
    environment:
      POSTGRES_HOST_AUTH_METHOD: trust
    volumes:
      - postgres-data:/var/lib/postgresql/data
      - ./e2e/upstream/init-databases.sh:/docker-entrypoint-initdb.d/init-databases.sh:ro
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 2s
      timeout: 5s
      retries: 30
      start_period: 30s

  bitcoind:
    image: lncm/bitcoind:v28.0
    command:
      - -conf=/bitcoin.conf
    ports:
      - "127.0.0.1:${BITCOIN_RPC_PORT:-8332}:8332"
    volumes:
      - bitcoind-data:/data/.bitcoin
      - ./e2e/upstream/bitcoin.conf:/bitcoin.conf:ro
    healthcheck:
      test: ["CMD", "bitcoin-cli", "-regtest", "-rpcuser=testutil", "-rpcpassword=testutilpassword", "-rpcport=8332", "getblockchaininfo"]
      interval: 2s
      timeout: 5s
      retries: 15

  bitcoin-init:
    image: lncm/bitcoind:v28.0
    depends_on:
      bitcoind:
        condition: service_healthy
    restart: "no"
    entrypoint: ["/bin/sh", "-c"]
    command:
      - |
        set -e
        CLI="bitcoin-cli -regtest -rpcuser=testutil -rpcpassword=testutilpassword -rpcconnect=bitcoind -rpcport=8332"
        if ! $$CLI listwallets | grep -q '"default"'; then
          if $$CLI listwalletdir | grep -q '"name": "default"'; then
            $$CLI loadwallet default > /dev/null
          else
            $$CLI createwallet default false false '' false true > /dev/null
          fi
        fi
        BALANCE=$$($$CLI -rpcwallet=default getbalance)
        case "$$BALANCE" in
          0|0.00000000) NEEDS_FUND=1 ;;
          *) NEEDS_FUND=0 ;;
        esac
        if [ "$$NEEDS_FUND" = "1" ]; then
          ADDRESS=$$($$CLI -rpcwallet=default getnewaddress)
          $$CLI generatetoaddress 101 "$$ADDRESS" > /dev/null
          echo "Funded wallet with 101 blocks"
        fi
        echo "Bitcoin wallet ready"
        if ! $$CLI listwallets | grep -q '"ssp-withdrawals"'; then
          if $$CLI listwalletdir | grep -q '"name": "ssp-withdrawals"'; then
            $$CLI loadwallet ssp-withdrawals > /dev/null
          else
            $$CLI createwallet ssp-withdrawals false false '' false true > /dev/null
          fi
        fi
        if [ "$$($$CLI -rpcwallet=ssp-withdrawals getbalance)" = "0.00000000" ]; then
          ADDRESS=$$($$CLI -rpcwallet=ssp-withdrawals getnewaddress '' bech32m)
          $$CLI -rpcwallet=default sendtoaddress "$$ADDRESS" 1 > /dev/null
          MINE_ADDRESS=$$($$CLI -rpcwallet=default getnewaddress)
          $$CLI generatetoaddress 3 "$$MINE_ADDRESS" > /dev/null
        fi

  bitcoin-miner:
    image: lncm/bitcoind:v28.0
    depends_on:
      bitcoin-init:
        condition: service_completed_successfully
    restart: unless-stopped
    entrypoint: ["/bin/sh", "-c"]
    command:
      - |
        CLI="bitcoin-cli -regtest -rpcuser=testutil -rpcpassword=testutilpassword -rpcconnect=bitcoind -rpcport=8332"
        while true; do
          ADDRESS=$$($$CLI -rpcwallet=default getnewaddress 2>&1) || { sleep 10; continue; }
          $$CLI generatetoaddress 1 "$$ADDRESS" > /dev/null 2>&1 && \
            echo "$$(date): Mined 1 block" || \
            echo "$$(date): ERROR: Failed to mine block"
          sleep 10
        done

  electrs:
    image: coffernetwork/regtest-electrs:28.1@sha256:7cd973541afc28e75ff18b93050df4e91749b38af031930ed2b77f4088a3d246
    depends_on:
      bitcoind:
        condition: service_healthy
    command:
      - --network=regtest
      - --jsonrpc-import
      - --cookie=testutil:testutilpassword
      - --daemon-rpc-addr=bitcoind:8332
      - --db-dir=/electrs
      - --electrum-rpc-addr=0.0.0.0:60401
      - --http-addr=0.0.0.0:3002
      - --monitoring-addr=0.0.0.0:24224
      - --cors=*
      - --address-search
    ports:
      - "127.0.0.1:30000:3002"
    volumes:
      - electrs-data:/electrs
    restart: unless-stopped

  spark-operator-0:
    <<: *operator-common
    command:
      - /opt/spark/entrypoint.sh 0
    ports:
      - "127.0.0.1:8535:8535"
    expose:
      - "8536"
    networks:
      default:
        aliases:
          - spark-operator-0.minikube.local

  spark-operator-1:
    <<: *operator-common
    command:
      - /opt/spark/entrypoint.sh 1
    ports:
      - "127.0.0.1:8536:8535"
    expose:
      - "8536"
    networks:
      default:
        aliases:
          - spark-operator-1.minikube.local

  spark-operator-2:
    <<: *operator-common
    command:
      - /opt/spark/entrypoint.sh 2
    ports:
      - "127.0.0.1:8537:8535"
    expose:
      - "8536"
    networks:
      default:
        aliases:
          - spark-operator-2.minikube.local

  # ---- Lightning backend ---------------------------------------------------
  # Built from a local ldk-server checkout (set LDK_SERVER_REF). The SSP talks
  # to it over gRPC whenever LDK_GRPC_ADDR and credentials are set.
  ldk-server:
    image: ${LDK_SERVER_IMAGE:-open-ssp-ldk-server:regtest}
    build:
      context: ${LDK_SERVER_REF:-./vendor/ldk-server}
      dockerfile: Dockerfile
    depends_on:
      bitcoind:
        condition: service_healthy
    ports:
      - "127.0.0.1:3536:3536"
      - "127.0.0.1:19735:9735"
    healthcheck:
      test: ["CMD-SHELL", "test -r /data/regtest/macaroons/admin.macaroon && ldk-server-cli --base-url localhost:3536 --macaroon $$(tr -d '[:space:]' < /data/regtest/macaroons/admin.macaroon) --tls-cert /data/tls.crt get-node-info >/dev/null"]
      interval: 10s
      timeout: 5s
      retries: 12
    volumes:
      - ldk-data:/data
      - ./e2e/ldk-server-config.toml:/config.toml:ro
    entrypoint: ["/bin/sh", "-c"]
    command:
      - |
        ldk-server /config.toml &
        PID=$$!
        trap 'kill -TERM "$$PID"' TERM INT
        while kill -0 "$$PID" 2>/dev/null; do
          if [ -f /data/regtest/macaroons/admin.macaroon ] && [ -f /data/tls.crt ]; then
            chmod 0755 /data/regtest /data/regtest/macaroons
            chmod 0444 /data/regtest/macaroons/admin.macaroon /data/tls.crt
            break
          fi
          sleep 1
        done
        wait "$$PID"
    restart: unless-stopped

  # Second node: LN counterparty for e2e send/receive (channel peer for ldk-server).
  ldk-server-2:
    image: ${LDK_SERVER_IMAGE:-open-ssp-ldk-server:regtest}
    build:
      context: ${LDK_SERVER_REF:-./vendor/ldk-server}
      dockerfile: Dockerfile
    depends_on:
      bitcoind:
        condition: service_healthy
    ports:
      - "127.0.0.1:3537:3536"
      - "127.0.0.1:19736:9735"
    volumes:
      - ldk-data-2:/data
      - ./e2e/ldk-server-2-config.toml:/config.toml:ro
    entrypoint: ["/bin/sh", "-c"]
    command:
      - |
        ldk-server /config.toml &
        PID=$$!
        trap 'kill -TERM "$$PID"' TERM INT
        while kill -0 "$$PID" 2>/dev/null; do
          if [ -f /data/regtest/macaroons/admin.macaroon ] && [ -f /data/tls.crt ]; then
            chmod 0755 /data/regtest /data/regtest/macaroons
            chmod 0444 /data/regtest/macaroons/admin.macaroon /data/tls.crt
            break
          fi
          sleep 1
        done
        wait "$$PID"
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "test -r /data/regtest/macaroons/admin.macaroon && ldk-server-cli --base-url localhost:3536 --macaroon $$(tr -d '[:space:]' < /data/regtest/macaroons/admin.macaroon) --tls-cert /data/tls.crt get-node-info >/dev/null"]
      interval: 10s
      timeout: 5s
      retries: 12

  ssp:
    # Prebuilt: docker compose pull (needs GHCR access); or --build locally.
    image: ${SSP_IMAGE:-ghcr.io/benthecarman/open-ssp:latest}
    build:
      context: .
      dockerfile: ssp.Dockerfile
    depends_on:
      spark-operator-0:
        condition: service_started
      spark-operator-1:
        condition: service_started
      spark-operator-2:
        condition: service_started
      ldk-server:
        condition: service_healthy
    ports:
      - "127.0.0.1:5000:5000"
    extra_hosts:
      - "host.docker.internal:host-gateway"
    healthcheck:
      test: ["CMD", "open-ssp", "healthcheck"]
      interval: 10s
      timeout: 5s
      retries: 12
    volumes:
      - ssp-data:/data
      - ldk-data:/ldk-data:ro
      - tls-certs:/tls:ro
    environment:
      SSP_LISTEN_ADDR: 0.0.0.0:5000
      SSP_CORS_ORIGINS: ${SSP_CORS_ORIGINS:-}
      SSP_NETWORK: ${SSP_NETWORK:-REGTEST}
      SSP_DATA_DIR: /data
      SSP_PUBLIC_URL: http://ssp:5000
      SSP_WEBHOOK_ALLOW_LOCAL: ${SSP_WEBHOOK_ALLOW_LOCAL:-0}
      SSP_INSTANT_MAX_OUTSTANDING_SATS: ${SSP_INSTANT_MAX_OUTSTANDING_SATS:-0}
      SSP_INSTANT_MAX_DEPOSIT_SATS: ${SSP_INSTANT_MAX_DEPOSIT_SATS:-0}
      COOP_BITCOIN_RPC_URL: http://bitcoind:8332/wallet/ssp-withdrawals
      COOP_BITCOIN_RPC_USER: testutil
      COOP_BITCOIN_RPC_PASSWORD: testutilpassword
      SPARK_MNEMONIC_FILE: /data/spark.mnemonic
      SO_HOSTS: ${SO_HOSTS:-spark-operator-0.minikube.local:8535,spark-operator-1.minikube.local:8535,spark-operator-2.minikube.local:8535}
      SO_IDENTITY_PUBKEYS: ${SO_IDENTITY_PUBKEYS:-0322ca18fc489ae25418a0e768273c2c61cabb823edfb14feb891e9bec62016510,0341727a6c41b168f07eb50865ab8c397a53c7eef628ac1020956b705e43b6cb27,0305ab8d485cc752394de4981f8a5ae004f2becfea6f432c9a59d5022d8764f0a6}
      SO_CERT_FILES: /tls/server_0.crt,/tls/server_1.crt,/tls/server_2.crt
      SSP_OPERATOR_HOSTS: spark-operator-0.minikube.local:8536,spark-operator-1.minikube.local:8536,spark-operator-2.minikube.local:8536
      SSP_OPERATOR_CERT_FILES: /tls/server_0.crt,/tls/server_1.crt,/tls/server_2.crt
      # Regtest withdrawal fees can require leaves smaller than 330 sats.
      SSP_MIN_SPLIT_CHILD_SATS: 1
      SPARK_ADMIN_TOKEN: ${SPARK_ADMIN_TOKEN:?set SPARK_ADMIN_TOKEN}
      # Live LDK backend: bitcoind-backed ldk-server above.
      LDK_GRPC_ADDR: ${LDK_GRPC_ADDR:-ldk-server:3536}
      LDK_MACAROON: ${LDK_MACAROON:-}
      LDK_MACAROON_FILE: ${LDK_MACAROON_FILE:-/ldk-data/regtest/macaroons/admin.macaroon}
      LDK_TLS_CERT_FILE: ${LDK_TLS_CERT_FILE:-/ldk-data/tls.crt}
      SSP_SWAP_FEE_SATS: 0
      SSP_FROST_THRESHOLD: 2
      RUST_LOG: info

  # The second SSP gives each Breez wallet a distinct Lightning node. This
  # prevents the test from paying an invoice back to the same node.
  ssp-2:
    image: ${SSP_IMAGE:-ghcr.io/benthecarman/open-ssp:latest}
    build:
      context: .
      dockerfile: ssp.Dockerfile
    depends_on:
      spark-operator-0:
        condition: service_started
      spark-operator-1:
        condition: service_started
      spark-operator-2:
        condition: service_started
      ldk-server-2:
        condition: service_healthy
    ports:
      - "127.0.0.1:5001:5000"
    extra_hosts:
      - "host.docker.internal:host-gateway"
    healthcheck:
      test: ["CMD", "open-ssp", "healthcheck"]
      interval: 10s
      timeout: 5s
      retries: 12
    volumes:
      - ssp-data-2:/data
      - ldk-data-2:/ldk-data:ro
      - tls-certs:/tls:ro
    environment:
      SSP_LISTEN_ADDR: 0.0.0.0:5000
      SSP_NETWORK: REGTEST
      SSP_DATA_DIR: /data
      SSP_PUBLIC_URL: http://ssp-2:5000
      SSP_WEBHOOK_ALLOW_LOCAL: ${SSP_WEBHOOK_ALLOW_LOCAL:-0}
      SSP_INSTANT_MAX_OUTSTANDING_SATS: ${SSP_INSTANT_MAX_OUTSTANDING_SATS:-0}
      SSP_INSTANT_MAX_DEPOSIT_SATS: ${SSP_INSTANT_MAX_DEPOSIT_SATS:-0}
      SPARK_MNEMONIC_FILE: /data/spark.mnemonic
      SO_HOSTS: spark-operator-0.minikube.local:8535,spark-operator-1.minikube.local:8535,spark-operator-2.minikube.local:8535
      SO_IDENTITY_PUBKEYS: 0322ca18fc489ae25418a0e768273c2c61cabb823edfb14feb891e9bec62016510,0341727a6c41b168f07eb50865ab8c397a53c7eef628ac1020956b705e43b6cb27,0305ab8d485cc752394de4981f8a5ae004f2becfea6f432c9a59d5022d8764f0a6
      SO_CERT_FILES: /tls/server_0.crt,/tls/server_1.crt,/tls/server_2.crt
      SSP_OPERATOR_HOSTS: spark-operator-0.minikube.local:8536,spark-operator-1.minikube.local:8536,spark-operator-2.minikube.local:8536
      SSP_OPERATOR_CERT_FILES: /tls/server_0.crt,/tls/server_1.crt,/tls/server_2.crt
      SSP_MIN_SPLIT_CHILD_SATS: 330
      SPARK_ADMIN_TOKEN: ${SPARK_ADMIN_TOKEN:?set SPARK_ADMIN_TOKEN}
      LDK_GRPC_ADDR: ldk-server-2:3536
      LDK_MACAROON_FILE: /ldk-data/regtest/macaroons/admin.macaroon
      LDK_TLS_CERT_FILE: /ldk-data/tls.crt
      SSP_SWAP_FEE_SATS: 0
      SSP_FROST_THRESHOLD: 2
      RUST_LOG: info

volumes:
  postgres-data:
  bitcoind-data:
  electrs-data:
  tls-certs:
  ldk-data:
  ldk-data-2:
  ssp-data:
  ssp-data-2: