diff --git a/app/src/infinite_hashes/aps_miner/callbacks.py b/app/src/infinite_hashes/aps_miner/callbacks.py index a772e03..c64bca7 100644 --- a/app/src/infinite_hashes/aps_miner/callbacks.py +++ b/app/src/infinite_hashes/aps_miner/callbacks.py @@ -5,13 +5,38 @@ Future: integrate with ASIC routing logic. """ +import os + import structlog from .brainsproxy import update_routing_weights from .models import AuctionResult, BidResult +from .proxy_routing import pools_config_path, update_subnet_target_hashrate logger = structlog.get_logger(__name__) +PROXY_MODE_ENV = "APS_MINER_PROXY_MODE" +PROXY_MODE_IHP = "ihp" +PROXY_MODE_BRAIINS = "braiins" + + +def _resolve_proxy_mode() -> str: + raw_mode = os.environ.get(PROXY_MODE_ENV, "").strip().lower() + if raw_mode == PROXY_MODE_IHP: + return PROXY_MODE_IHP + if raw_mode == PROXY_MODE_BRAIINS: + return PROXY_MODE_BRAIINS + + configured_pools_path = os.environ.get("APS_MINER_POOLS_CONFIG_PATH", "").strip() + if configured_pools_path: + try: + if pools_config_path().exists(): + return PROXY_MODE_IHP + except OSError: + logger.warning("Unable to inspect APS_MINER_POOLS_CONFIG_PATH; falling back to braiins mode") + + return PROXY_MODE_BRAIINS + def handle_auction_results(result: AuctionResult) -> None: """ @@ -46,10 +71,14 @@ def handle_auction_results(result: AuctionResult) -> None: if lost_bids: _handle_lost_bids(lost_bids, result) + proxy_mode = _resolve_proxy_mode() try: - update_routing_weights(won_bids, lost_bids) + if proxy_mode == PROXY_MODE_IHP: + update_subnet_target_hashrate(won_bids, lost_bids) + else: + update_routing_weights(won_bids, lost_bids) except Exception: # noqa: BLE001 - logger.exception("Failed to update Braiins routing weights") + logger.exception("Failed to update proxy routing", proxy_mode=proxy_mode) def _handle_won_bids(won_bids: list[BidResult], result: AuctionResult) -> None: diff --git a/app/src/infinite_hashes/aps_miner/proxy_routing.py b/app/src/infinite_hashes/aps_miner/proxy_routing.py new file mode 100644 index 0000000..c24189c --- /dev/null +++ b/app/src/infinite_hashes/aps_miner/proxy_routing.py @@ -0,0 +1,140 @@ +""" +Integration helpers for InfiniteHash Proxy pool routing. + +This module updates subnet pool target hashrate in pools.toml so winning bids +receive an absolute allocation while private pools can consume the remainder. +""" + +from __future__ import annotations + +import os +from collections.abc import Iterable +from pathlib import Path + +import structlog +import tomlkit + +from .models import BidResult + +logger = structlog.get_logger(__name__) + +DEFAULT_POOLS_CONFIG_PATH = "/root/src/proxy/pools.toml" +DEFAULT_SUBNET_POOL_NAME = "central-proxy" +DEFAULT_RELOAD_SENTINEL_PATH = "/root/src/proxy/.reload-ihp" + + +def pools_config_path() -> Path: + configured_path = os.environ.get("APS_MINER_POOLS_CONFIG_PATH", DEFAULT_POOLS_CONFIG_PATH) + return Path(configured_path) + + +def reload_sentinel_path() -> Path: + configured_path = os.environ.get("APS_MINER_IHP_RELOAD_SENTINEL", DEFAULT_RELOAD_SENTINEL_PATH) + return Path(configured_path) + + +def _sum_hashrates_ph(bids: Iterable[BidResult]) -> float: + total = 0.0 + for bid in bids: + try: + total += float(bid.hashrate) + except (TypeError, ValueError): + logger.warning("Failed to parse bid hashrate for proxy routing", hashrate=bid.hashrate) + return total + + +def _format_target_hashrate_from_ph(total_ph: float) -> str: + target_th = max(total_ph, 0.0) * 1000.0 + target_str = f"{target_th:.3f}".rstrip("0").rstrip(".") + if not target_str: + target_str = "0" + return f"{target_str}TH/s" + + +def _is_subnet_pool(pool: dict, subnet_pool_name: str) -> bool: + pool_name = str(pool.get("name", "")).strip().lower() + return pool_name == subnet_pool_name + + +def update_subnet_target_hashrate(won_bids: Iterable[BidResult], _lost_bids: Iterable[BidResult]) -> None: + """ + Update the subnet pool target hashrate in pools.toml. + + Won hashrate is assigned to subnet pools as absolute `target_hashrate`. + Remaining hashrate continues to flow to private pools through their weights. + """ + config_path = pools_config_path() + if not config_path.exists(): + logger.info("InfiniteHash proxy pools config not present - skipping update", path=str(config_path)) + return + + subnet_pool_name = os.environ.get("APS_MINER_SUBNET_POOL_NAME", DEFAULT_SUBNET_POOL_NAME).strip().lower() + target_hashrate = _format_target_hashrate_from_ph(_sum_hashrates_ph(won_bids)) + + try: + with config_path.open("r", encoding="utf-8") as f: + doc = tomlkit.load(f) + except Exception: + logger.exception("Unable to load InfiniteHash proxy pools config", path=str(config_path)) + return + + pools_section = doc.get("pools") + if not isinstance(pools_section, dict): + logger.warning("Missing [pools] section in proxy config", path=str(config_path)) + return + + main_pools = pools_section.get("main") + if not isinstance(main_pools, list): + logger.warning("Missing [[pools.main]] entries in proxy config", path=str(config_path)) + return + + updated = False + matched = 0 + for pool in main_pools: + if not isinstance(pool, dict): + continue + if not _is_subnet_pool(pool, subnet_pool_name): + continue + + matched += 1 + old_target_hashrate = pool.get("target_hashrate") + if old_target_hashrate != target_hashrate: + pool["target_hashrate"] = target_hashrate + updated = True + + if "weight" in pool: + del pool["weight"] + updated = True + + if matched == 0: + logger.warning( + "No subnet pool entries matched for target hashrate update", + name=subnet_pool_name, + path=str(config_path), + ) + return + + if not updated: + logger.debug("Subnet target hashrate already up to date", target_hashrate=target_hashrate) + return + + try: + with config_path.open("w", encoding="utf-8") as f: + tomlkit.dump(doc, f) + except Exception: + logger.exception("Failed to persist proxy pools config updates", path=str(config_path)) + return + + sentinel_path = reload_sentinel_path() + try: + sentinel_path.parent.mkdir(parents=True, exist_ok=True) + sentinel_path.touch() + except Exception: + logger.exception("Failed to signal IHP proxy reload", sentinel=str(sentinel_path)) + + logger.info( + "Updated subnet target hashrate", + name=subnet_pool_name, + target_hashrate=target_hashrate, + matched_pools=matched, + ) diff --git a/app/src/infinite_hashes/aps_miner/tests/test_callbacks_proxy_mode.py b/app/src/infinite_hashes/aps_miner/tests/test_callbacks_proxy_mode.py new file mode 100644 index 0000000..754f369 --- /dev/null +++ b/app/src/infinite_hashes/aps_miner/tests/test_callbacks_proxy_mode.py @@ -0,0 +1,65 @@ +from __future__ import annotations + +from datetime import UTC, datetime + +from infinite_hashes.aps_miner import callbacks +from infinite_hashes.aps_miner.models import AuctionResult, BidResult + + +def _build_result() -> AuctionResult: + now = datetime.now(tz=UTC) + return AuctionResult( + epoch_start=1, + start_block=10, + end_block=20, + window_start_time=now, + window_end_time=now, + commitments_count=2, + all_winners=[], + my_bids=[ + BidResult(hashrate="0.1", price_fp18=1, won=True), + BidResult(hashrate="0.2", price_fp18=1, won=False), + ], + ) + + +def test_handle_auction_results_uses_ihp_proxy_when_configured(monkeypatch) -> None: + calls = {"ihp": 0, "braiins": 0} + + def _ihp_handler(*_args, **_kwargs) -> None: + calls["ihp"] += 1 + + def _braiins_handler(*_args, **_kwargs) -> None: + calls["braiins"] += 1 + + monkeypatch.setenv("APS_MINER_PROXY_MODE", "ihp") + monkeypatch.setattr(callbacks, "update_subnet_target_hashrate", _ihp_handler) + monkeypatch.setattr(callbacks, "update_routing_weights", _braiins_handler) + + callbacks.handle_auction_results(_build_result()) + + assert calls["ihp"] == 1 + assert calls["braiins"] == 0 + + +def test_handle_auction_results_auto_detects_ihp_proxy_from_pools_file(monkeypatch, tmp_path) -> None: + calls = {"ihp": 0, "braiins": 0} + + def _ihp_handler(*_args, **_kwargs) -> None: + calls["ihp"] += 1 + + def _braiins_handler(*_args, **_kwargs) -> None: + calls["braiins"] += 1 + + pools_file = tmp_path / "pools.toml" + pools_file.write_text("[pools]\n", encoding="utf-8") + + monkeypatch.delenv("APS_MINER_PROXY_MODE", raising=False) + monkeypatch.setenv("APS_MINER_POOLS_CONFIG_PATH", str(pools_file)) + monkeypatch.setattr(callbacks, "update_subnet_target_hashrate", _ihp_handler) + monkeypatch.setattr(callbacks, "update_routing_weights", _braiins_handler) + + callbacks.handle_auction_results(_build_result()) + + assert calls["ihp"] == 1 + assert calls["braiins"] == 0 diff --git a/app/src/infinite_hashes/aps_miner/tests/test_proxy_routing.py b/app/src/infinite_hashes/aps_miner/tests/test_proxy_routing.py new file mode 100644 index 0000000..e18c59d --- /dev/null +++ b/app/src/infinite_hashes/aps_miner/tests/test_proxy_routing.py @@ -0,0 +1,84 @@ +from __future__ import annotations + +import tomli + +from infinite_hashes.aps_miner.models import BidResult +from infinite_hashes.aps_miner.proxy_routing import update_subnet_target_hashrate + + +def test_update_subnet_target_hashrate_sets_absolute_target_and_keeps_private_weights(monkeypatch, tmp_path) -> None: + pools_file = tmp_path / "pools.toml" + sentinel_file = tmp_path / ".reload-ihp" + pools_file.write_text( + """ +[pools] +backup = { name = "backup", host = "backup.pool", port = 3333 } + +[[pools.main]] +name = "subnet" +host = "stratum.infinitehash.xyz" +port = 9332 +weight = 1 + +[[pools.main]] +name = "private" +host = "btc.global.luxor.tech" +port = 700 +weight = 7 +""", + encoding="utf-8", + ) + + monkeypatch.setenv("APS_MINER_POOLS_CONFIG_PATH", str(pools_file)) + monkeypatch.setenv("APS_MINER_SUBNET_POOL_NAME", "subnet") + monkeypatch.setenv("APS_MINER_IHP_RELOAD_SENTINEL", str(sentinel_file)) + + won_bids = [ + BidResult(hashrate="0.1", price_fp18=1, won=True), + BidResult(hashrate="0.2", price_fp18=1, won=True), + ] + lost_bids = [BidResult(hashrate="0.3", price_fp18=1, won=False)] + + update_subnet_target_hashrate(won_bids, lost_bids) + + with pools_file.open("rb") as f: + data = tomli.load(f) + + subnet_pool = data["pools"]["main"][0] + private_pool = data["pools"]["main"][1] + + assert subnet_pool["target_hashrate"] == "300TH/s" + assert "weight" not in subnet_pool + assert private_pool["weight"] == 7 + assert sentinel_file.exists() + + +def test_update_subnet_target_hashrate_sets_zero_when_no_wins(monkeypatch, tmp_path) -> None: + pools_file = tmp_path / "pools.toml" + sentinel_file = tmp_path / ".reload-ihp" + pools_file.write_text( + """ +[pools] +backup = { name = "backup", host = "backup.pool", port = 3333 } + +[[pools.main]] +name = "subnet" +host = "stratum.infinitehash.xyz" +port = 9332 +weight = 1 +""", + encoding="utf-8", + ) + + monkeypatch.setenv("APS_MINER_POOLS_CONFIG_PATH", str(pools_file)) + monkeypatch.setenv("APS_MINER_SUBNET_POOL_NAME", "subnet") + monkeypatch.setenv("APS_MINER_IHP_RELOAD_SENTINEL", str(sentinel_file)) + + update_subnet_target_hashrate([], [BidResult(hashrate="0.3", price_fp18=1, won=False)]) + + with pools_file.open("rb") as f: + data = tomli.load(f) + + subnet_pool = data["pools"]["main"][0] + assert subnet_pool["target_hashrate"] == "0TH/s" + assert sentinel_file.exists() diff --git a/envs/miner-ihp/docker-compose.yml b/envs/miner-ihp/docker-compose.yml new file mode 100644 index 0000000..18b76bf --- /dev/null +++ b/envs/miner-ihp/docker-compose.yml @@ -0,0 +1,110 @@ +services: + miner: + image: ghcr.io/backend-developers-ltd/infinitehash-subnet-prod@sha256:6dab0713c45901f589ba531567d84555a12a53aaf79d277639997e19916475ae + pull_policy: always + init: true + restart: unless-stopped + working_dir: /root/src + command: python -m infinite_hashes.aps_miner /root/src/config.toml + environment: + - PYTHONUNBUFFERED=1 + - APS_MINER_PROXY_MODE=ihp + - APS_MINER_POOLS_CONFIG_PATH=/root/src/proxy/pools.toml + - APS_MINER_SUBNET_POOL_NAME=${APS_MINER_SUBNET_POOL_NAME:-central-proxy} + - APS_MINER_IHP_RELOAD_SENTINEL=/root/src/proxy/.reload-ihp + extra_hosts: + - "host.docker.internal:host-gateway" + volumes: + - ./config.toml:/root/src/config.toml:ro + - ~/.bittensor:/root/.bittensor + - ./logs:/root/src/logs + - ./proxy:/root/src/proxy + depends_on: + ihp-postgres: + condition: service_healthy + ihp-proxy: + condition: service_started + logging: &logging + driver: journald + options: + tag: '{{.Name}}' + + ihp-postgres: + image: postgres:16-alpine + restart: unless-stopped + environment: + - POSTGRES_USER=ihp + - POSTGRES_PASSWORD=ihp + - POSTGRES_DB=ihp + volumes: + - ihp-postgres-data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ihp -d ihp"] + interval: 5s + timeout: 5s + retries: 5 + logging: + <<: *logging + + ihp-proxy: + image: backenddevelopersltd/infinitehash-proxy-server:v1-latest + restart: unless-stopped + stop_grace_period: 15s + env_file: + - ./proxy/.env + ports: + - "3333:3333" + - "9090:9090" + volumes: + - ./proxy/pools.toml:/etc/infinite-hash-proxy/pools.toml:ro + ulimits: + nofile: + soft: 65535 + hard: 65535 + depends_on: + ihp-postgres: + condition: service_healthy + logging: + <<: *logging + + ihp-api: + image: backenddevelopersltd/infinitehash-proxy-api:v1-latest + restart: unless-stopped + env_file: + - ./proxy/.env + ports: + - "8000:8000" + depends_on: + ihp-postgres: + condition: service_healthy + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "-O", "/dev/null", "http://localhost:8000/health"] + interval: 10s + timeout: 5s + retries: 5 + logging: + <<: *logging + + ihp-proxy-reloader: + image: alpine:3.20 + restart: unless-stopped + pid: "service:ihp-proxy" + command: > + sh -c "while true; do + if [ -f /config/.reload-ihp ]; then + echo \"$(date -u +\"%Y-%m-%dT%H:%M:%SZ\") IHP reloader: sending HUP to pid 1\"; + rm -f /config/.reload-ihp; + kill -HUP 1 || true; + fi; + sleep ${IHP_RELOAD_INTERVAL:-5}; + done" + volumes: + - ./proxy:/config + depends_on: + ihp-proxy: + condition: service_started + logging: + <<: *logging + +volumes: + ihp-postgres-data: diff --git a/installer/README.md b/installer/README.md index 67f5c8e..bc922d0 100644 --- a/installer/README.md +++ b/installer/README.md @@ -66,6 +66,26 @@ An installer for the APS miner (APScheduler-based miner) is also available: curl -s https://raw.githubusercontent.com/backend-developers-ltd/InfiniteHash/refs/heads/deploy-config-prod/installer/miner_install.sh | bash ``` -This script will prompt for TOML configuration values, generate `config.toml`, deploy the miner stack with Docker Compose, and install a cron job that keeps the compose file up to date by calling `installer/update_miner_compose.sh`. +This script prompts for TOML configuration values and proxy mode, generates `config.toml`, deploys the miner stack with Docker Compose, and installs a cron job that keeps the compose file up to date by calling `installer/update_miner_compose.sh`. -The miner bundle automatically provisions Braiins Farm Proxy (`farm-proxy` and configurator sidecar) and keeps the active profile in `brainsproxy/active_profile.toml` in sync with APS miner auction results. +For `ihp` mode, default proxy template files (`proxy/.env` and `proxy/pools.toml`) are generated directly by the installer script (inline templates), not downloaded from external template files. + +Proxy mode options: +- `InfiniteHash Proxy` (`ihp`, default on Enter) +- `Braiins Farm Proxy` (`braiins`, optional) + +In `braiins` mode, the installer provisions Braiins Farm Proxy (`farm-proxy` and configurator sidecar) and keeps `brainsproxy/active_profile.toml` in sync with APS miner auction results. + +### Routing identifiers by mode + +`ihp` mode: +- APS miner updates subnet allocation by pool `name` in `proxy/pools.toml` (`[[pools.main]]` entry), not by host/port. +- The miner container uses `APS_MINER_SUBNET_POOL_NAME` (default: `central-proxy`) to select which pool gets absolute `target_hashrate`. +- The selected pool name must exist in `proxy/pools.toml`; otherwise no subnet target update is applied. +- During installation, if `proxy/pools.toml` does not exist yet, the script asks for backup/private pool host/port/worker ID and writes those values to `pools.backup`. +- After updating `proxy/pools.toml`, APS miner touches reload sentinel `APS_MINER_IHP_RELOAD_SENTINEL` (default: `/root/src/proxy/.reload-ihp`); sidecar `ihp-proxy-reloader` then runs `kill -HUP 1` in `ihp-proxy` PID namespace. + +`braiins` mode: +- APS miner updates routing by Braiins goal names in `brainsproxy/active_profile.toml`. +- Expected goal names are `InfiniteHashLuxorGoal` (subnet side) and `MinerDefaultGoal` (non-subnet side). +- If you rename these goals manually, APS miner will not match them until code/config is aligned. diff --git a/installer/miner_install.sh b/installer/miner_install.sh index dd9bf39..61f8d32 100644 --- a/installer/miner_install.sh +++ b/installer/miner_install.sh @@ -5,6 +5,7 @@ set -euo pipefail ENV_NAME="${1:-prod}" WORKING_DIRECTORY=${2:-~/InfiniteHash-miner/} +GITHUB_URL="https://raw.githubusercontent.com/backend-developers-ltd/InfiniteHash/refs/heads" mkdir -p "${WORKING_DIRECTORY}" WORKING_DIRECTORY=$(realpath "${WORKING_DIRECTORY}") @@ -12,6 +13,78 @@ WORKING_DIRECTORY=$(realpath "${WORKING_DIRECTORY}") CONFIG_FILE="${WORKING_DIRECTORY}/config.toml" BRAIINSPROXY_DIR="${WORKING_DIRECTORY}/brainsproxy" BRAIINSPROXY_CONFIG_DIR="${BRAIINSPROXY_DIR}/config" +BRAIINSPROXY_ACTIVE_PROFILE="${BRAIINSPROXY_CONFIG_DIR}/active_profile.toml" +NEW_PROXY_DIR="${WORKING_DIRECTORY}/proxy" +NEW_PROXY_ENV_FILE="${NEW_PROXY_DIR}/.env" +NEW_PROXY_POOLS_FILE="${NEW_PROXY_DIR}/pools.toml" +PROXY_MODE_FILE="${WORKING_DIRECTORY}/proxy_mode" + +write_default_ihp_env() { + local destination="$1" + cat > "${destination}" <<'EOL' +IHP_POOL_CONFIG_PATH=/etc/infinite-hash-proxy/pools.toml +IHP_LISTEN_ADDR=0.0.0.0:3333 +IHP_METRICS_ADDR=0.0.0.0:9090 + +IHP_DATABASE_URL=postgresql+asyncpg://ihp:ihp@ihp-postgres:5432/ihp +IHP_COMPACTION_ENABLED=true +IHP_COMPACTION_INTERVAL_SECONDS=3600 +IHP_COMPACTION_RETENTION_HOURS=72 + +IHP_API_HOST=0.0.0.0 +IHP_API_PORT=8000 +IHP_API_LOG_LEVEL=INFO +IHP_API_DATABASE_URL=postgresql+asyncpg://ihp:ihp@ihp-postgres:5432/ihp +EOL +} + +write_default_ihp_pools() { + local destination="$1" + local backup_pool_host="$2" + local backup_pool_port="$3" + local backup_pool_worker_id="$4" + + cat > "${destination}" <> "${destination}" <> "${destination}" <<'EOL' +[[pools.main]] +name = "central-proxy" +host = "stratum.infinitehash.xyz" +port = 9332 +weight = 1 + +[extranonce] +extranonce2_size = 6 + +[routing] +rebalance_interval_seconds = 10 +grace_period_seconds = 60 +min_shares_for_estimate = 20 +rebalance_threshold_percent = 10 +min_reassign_interval_seconds = 45 +pool_connect_timeout_seconds = 10 +pool_read_timeout_seconds = 300 +pool_unhealthy_cooldown_seconds = 10 +worker_assignment_stale_threshold_seconds = 30 +disconnected_worker_retention_seconds = 900 + +[filters] +ban_nicehash = true +EOL +} if [ ! -f "${CONFIG_FILE}" ]; then echo "Creating config.toml file..." @@ -125,12 +198,72 @@ if [ -f "${HOTKEY_PUB_FILE}" ]; then fi HOTKEY_IDENTIFIER=${HOTKEY_SS58:-${BITTENSOR_WALLET_HOTKEY_NAME}} +PROXY_MODE="" +if [ -f "${PROXY_MODE_FILE}" ]; then + PROXY_MODE=$(tr -d '[:space:]' < "${PROXY_MODE_FILE}" | tr '[:upper:]' '[:lower:]') +fi + +if [ "${PROXY_MODE}" != "ihp" ] && [ "${PROXY_MODE}" != "braiins" ]; then + DEFAULT_MODE_SELECTION=1 + if [ -f "${BRAIINSPROXY_ACTIVE_PROFILE}" ]; then + DEFAULT_MODE_SELECTION=2 + echo "Detected existing Braiins profile. Defaulting selection to Braiins to avoid migration." + fi + + echo "" + echo "Choose proxy mode:" + echo " 1) InfiniteHash Proxy (ihp, default)" + echo " 2) Braiins Farm Proxy (braiins)" + read -r -p "Selection [${DEFAULT_MODE_SELECTION}]: " PROXY_MODE_SELECTION "${PROXY_MODE_FILE}" + echo "Proxy mode selected: ${PROXY_MODE}" +else + echo "Using existing proxy mode from ${PROXY_MODE_FILE}: ${PROXY_MODE}" +fi + mkdir -p "${WORKING_DIRECTORY}/logs" -mkdir -p "${BRAIINSPROXY_CONFIG_DIR}" -BRAIINSPROXY_ACTIVE_PROFILE="${BRAIINSPROXY_CONFIG_DIR}/active_profile.toml" +if [ "${PROXY_MODE}" = "ihp" ]; then + mkdir -p "${NEW_PROXY_DIR}" + + if [ ! -f "${NEW_PROXY_ENV_FILE}" ]; then + echo "Creating InfiniteHash Proxy environment file at ${NEW_PROXY_ENV_FILE}..." + write_default_ihp_env "${NEW_PROXY_ENV_FILE}" + else + echo "Using existing InfiniteHash Proxy environment file at ${NEW_PROXY_ENV_FILE}" + fi + + if [ ! -f "${NEW_PROXY_POOLS_FILE}" ]; then + echo "Creating InfiniteHash Proxy pools file at ${NEW_PROXY_POOLS_FILE}..." + DEFAULT_PRIVATE_POOL_HOST="btc.global.luxor.tech" + read -r -p "Enter IHP backup/private pool host [${DEFAULT_PRIVATE_POOL_HOST}]: " PRIVATE_POOL_HOST /tmp/update_miner_compose.sh chmod +x /tmp/update_miner_compose.sh @@ -228,3 +359,4 @@ CRON_CMD="*/15 * * * * cd ${WORKING_DIRECTORY} && curl -s ${GITHUB_URL}/deploy-c echo "Cron job installed successfully. It will run every 15 minutes." echo "Environment: ${ENV_NAME}" echo "Working directory: ${WORKING_DIRECTORY}" +echo "Proxy mode: ${PROXY_MODE}" diff --git a/installer/update_miner_compose.sh b/installer/update_miner_compose.sh index 4d0ed49..8c39d5a 100644 --- a/installer/update_miner_compose.sh +++ b/installer/update_miner_compose.sh @@ -11,12 +11,35 @@ mkdir -p "${WORKING_DIRECTORY}" cd "${WORKING_DIRECTORY}" mkdir -p logs -mkdir -p brainsproxy/config GITHUB_URL="https://raw.githubusercontent.com/backend-developers-ltd/InfiniteHash/refs/heads" +PROXY_MODE_FILE="${WORKING_DIRECTORY}/proxy_mode" + +PROXY_MODE="" +if [ -f "${PROXY_MODE_FILE}" ]; then + PROXY_MODE=$(tr -d '[:space:]' < "${PROXY_MODE_FILE}" | tr '[:upper:]' '[:lower:]') +fi + +if [ "${PROXY_MODE}" != "ihp" ] && [ "${PROXY_MODE}" != "braiins" ]; then + if [ -f "${WORKING_DIRECTORY}/brainsproxy/config/active_profile.toml" ]; then + PROXY_MODE="braiins" + elif [ -f "${WORKING_DIRECTORY}/proxy/pools.toml" ]; then + PROXY_MODE="ihp" + else + PROXY_MODE="ihp" + fi +fi + +if [ "${PROXY_MODE}" = "ihp" ]; then + COMPOSE_REMOTE_PATH="envs/miner-ihp/docker-compose.yml" + mkdir -p proxy +else + COMPOSE_REMOTE_PATH="envs/miner/docker-compose.yml" + mkdir -p brainsproxy/config +fi TEMP_FILE="/tmp/InfiniteHash_miner_compose_update.yml" -curl -s "${GITHUB_URL}/deploy-config-${ENV_NAME}/envs/miner/docker-compose.yml" > "${TEMP_FILE}" +curl -s "${GITHUB_URL}/deploy-config-${ENV_NAME}/${COMPOSE_REMOTE_PATH}" > "${TEMP_FILE}" LOCAL_FILE="${WORKING_DIRECTORY}/docker-compose.yml" @@ -51,3 +74,4 @@ if [ "${UPDATED}" = true ]; then fi echo "Update process completed." +echo "Proxy mode: ${PROXY_MODE}" diff --git a/tools/update_compose_digest.py b/tools/update_compose_digest.py index 4ca1e15..ee729a1 100644 --- a/tools/update_compose_digest.py +++ b/tools/update_compose_digest.py @@ -81,7 +81,14 @@ def main() -> None: "--miner-compose-path", type=Path, default=miner_default_path, - help=f"path to miner docker-compose.yml (default: {miner_default_path})", + help=f"path to Braiins miner docker-compose.yml (default: {miner_default_path})", + ) + miner_ihp_default_path = Path(__file__).resolve().parents[1] / "envs" / "miner-ihp" / "docker-compose.yml" + parser.add_argument( + "--miner-ihp-compose-path", + type=Path, + default=miner_ihp_default_path, + help=f"path to IHP miner docker-compose.yml (default: {miner_ihp_default_path})", ) args = parser.parse_args() @@ -92,7 +99,8 @@ def main() -> None: if args.target in ("validator", "all"): targets.append(("validator", args.compose_path)) if args.target in ("miner", "all"): - targets.append(("miner", args.miner_compose_path)) + targets.append(("miner-braiins", args.miner_compose_path)) + targets.append(("miner-ihp", args.miner_ihp_compose_path)) total_replacements = 0 for label, compose_path in targets: