diff --git a/.gitignore b/.gitignore index 800140cb0..cdbb87517 100644 --- a/.gitignore +++ b/.gitignore @@ -174,4 +174,5 @@ src/dragonx-cli src/dragonx-tx src/dragonxd.exe src/dragonx-cli.exe -src/dragonx-tx.exe \ No newline at end of file +src/dragonx-tx.exe +doc/relnotes/ \ No newline at end of file diff --git a/build.sh b/build.sh index c499e6202..2ad3722e3 100755 --- a/build.sh +++ b/build.sh @@ -80,8 +80,12 @@ package_release() { echo "Packaging release for $platform..." mkdir -p "$release_subdir" - # Copy bootstrap script - cp "$SCRIPT_DIR/util/bootstrap-dragonx.sh" "$release_subdir/" + # Copy bootstrap script (platform-appropriate) + if [ "$platform" = "win64" ]; then + cp "$SCRIPT_DIR/util/bootstrap-dragonx.bat" "$release_subdir/" + else + cp "$SCRIPT_DIR/util/bootstrap-dragonx.sh" "$release_subdir/" + fi # Copy common files cp "$SCRIPT_DIR/contrib/asmap/asmap.dat" "$release_subdir/" 2>/dev/null || true diff --git a/util/bootstrap-dragonx.bat b/util/bootstrap-dragonx.bat new file mode 100644 index 000000000..5ee071cd3 --- /dev/null +++ b/util/bootstrap-dragonx.bat @@ -0,0 +1,264 @@ +@echo off +REM Copyright 2024 The Hush Developers +REM Copyright 2024 The DragonX Developers +REM Released under the GPLv3 +REM +REM Download and apply a DRAGONX blockchain bootstrap on Windows. +REM Safely preserves wallet.dat and configuration files. + +setlocal enabledelayedexpansion + +set "BOOTSTRAP_BASE_URL=https://bootstrap.dragonx.is" +set "BOOTSTRAP_FALLBACK_URL=https://bootstrap2.dragonx.is" +set "BOOTSTRAP_FILE=DRAGONX.zip" +set "CHAIN_NAME=DRAGONX" + +REM Data directory on Windows +set "DATADIR=%APPDATA%\Hush\%CHAIN_NAME%" + +REM Find dragonx-cli relative to this script +set "CLI=" +set "SCRIPT_DIR=%~dp0" +if exist "%SCRIPT_DIR%dragonx-cli.exe" ( + set "CLI=%SCRIPT_DIR%dragonx-cli.exe" +) + +echo ============================================ +echo DragonX Bootstrap Installer +echo ============================================ +echo. +echo [INFO] Data directory: %DATADIR% +echo. + +REM Step 1: Stop daemon if running +call :stop_daemon +if errorlevel 1 goto :error_exit + +REM Step 2: Clean old chain data +call :clean_chain_data +if errorlevel 1 goto :error_exit + +REM Step 3: Download bootstrap +call :download_bootstrap +if errorlevel 1 goto :error_exit + +REM Step 4: Extract bootstrap +call :extract_bootstrap +if errorlevel 1 goto :error_exit + +echo. +echo [INFO] Bootstrap installation complete! +echo [INFO] You can now start DragonX with: dragonxd.exe +echo. +goto :EOF + +REM ============================================ +REM Stop daemon if running +REM ============================================ +:stop_daemon +if "%CLI%"=="" ( + echo [WARN] dragonx-cli.exe not found next to this script. + echo [WARN] Please make sure the DragonX daemon is stopped before continuing. + set /p "ANSWER=Is the DragonX daemon stopped? (y/N): " + if /i not "!ANSWER!"=="y" ( + echo [ERROR] Please stop the daemon first and run this script again. + exit /b 1 + ) + exit /b 0 +) + +"%CLI%" getinfo >nul 2>&1 +if errorlevel 1 ( + echo [INFO] Daemon is not running. + exit /b 0 +) + +echo [INFO] Stopping DragonX daemon... +"%CLI%" stop >nul 2>&1 + +set "TRIES=0" +:wait_loop +"%CLI%" getinfo >nul 2>&1 +if errorlevel 1 goto :daemon_stopped +timeout /t 2 /nobreak >nul +set /a TRIES+=1 +if %TRIES% geq 60 ( + echo [ERROR] Daemon did not stop after 120 seconds. Please stop it manually and retry. + exit /b 1 +) +goto :wait_loop + +:daemon_stopped +echo [INFO] Daemon stopped. +exit /b 0 + +REM ============================================ +REM Clean blockchain data, preserving wallet and config +REM ============================================ +:clean_chain_data +if not exist "%DATADIR%" ( + echo [INFO] Data directory does not exist yet, creating it. + mkdir "%DATADIR%" + exit /b 0 +) + +echo [INFO] Cleaning blockchain data from %DATADIR% ... + +REM Preserve wallet.dat and config +set "TMPDIR=%TEMP%\dragonx-bootstrap-%RANDOM%" +mkdir "%TMPDIR%" 2>nul + +for %%F in (wallet.dat DRAGONX.conf peers.dat) do ( + if exist "%DATADIR%\%%F" ( + copy /y "%DATADIR%\%%F" "%TMPDIR%\%%F" >nul + ) +) + +REM Remove blockchain directories and files +for %%D in (blocks chainstate notarizations komodo) do ( + if exist "%DATADIR%\%%D" ( + rmdir /s /q "%DATADIR%\%%D" 2>nul + ) +) +for %%F in (db.log debug.log fee_estimates.dat banlist.dat) do ( + if exist "%DATADIR%\%%F" ( + del /f /q "%DATADIR%\%%F" 2>nul + ) +) + +REM Restore preserved files +for %%F in (wallet.dat DRAGONX.conf peers.dat) do ( + if exist "%TMPDIR%\%%F" ( + copy /y "%TMPDIR%\%%F" "%DATADIR%\%%F" >nul + ) +) +rmdir /s /q "%TMPDIR%" 2>nul + +echo [INFO] Blockchain data cleaned. +exit /b 0 + +REM ============================================ +REM Download bootstrap (with fallback) +REM ============================================ +:download_bootstrap +echo [INFO] Downloading bootstrap from %BOOTSTRAP_BASE_URL% ... +echo [INFO] This may take a while depending on your connection speed. + +REM Try primary URL +call :do_download "%BOOTSTRAP_BASE_URL%" +if not errorlevel 1 goto :download_verify + +echo [WARN] Primary download failed, trying fallback %BOOTSTRAP_FALLBACK_URL% ... +call :do_download "%BOOTSTRAP_FALLBACK_URL%" +if errorlevel 1 ( + echo [ERROR] Download failed from both primary and fallback servers. + exit /b 1 +) + +:download_verify +echo [INFO] Bootstrap download complete. + +REM Verify SHA256 checksum +echo [INFO] Verifying checksum... +pushd "%DATADIR%" + +REM Read expected hash from the .sha256 file (format: "hash filename" or "hash *filename") +set "EXPECTED_HASH=" +for /f "tokens=1" %%A in (%BOOTSTRAP_FILE%.sha256) do ( + set "EXPECTED_HASH=%%A" +) + +if "%EXPECTED_HASH%"=="" ( + echo [WARN] Could not read expected checksum, skipping verification. + goto :verify_done +) + +REM Use certutil to compute SHA256 +certutil -hashfile "%BOOTSTRAP_FILE%" SHA256 > "%TEMP%\dragonx_hash.tmp" 2>nul +if errorlevel 1 ( + echo [WARN] certutil not available, skipping checksum verification. + goto :verify_done +) + +REM certutil outputs hash on the second line +set "ACTUAL_HASH=" +set "LINE_NUM=0" +for /f "skip=1 tokens=*" %%H in (%TEMP%\dragonx_hash.tmp) do ( + if not defined ACTUAL_HASH ( + set "ACTUAL_HASH=%%H" + ) +) +REM Remove spaces from certutil output +set "ACTUAL_HASH=!ACTUAL_HASH: =!" +del /f /q "%TEMP%\dragonx_hash.tmp" 2>nul + +if /i "!ACTUAL_HASH!"=="!EXPECTED_HASH!" ( + echo [INFO] SHA256 checksum verified. +) else ( + echo [ERROR] SHA256 checksum verification failed! The download may be corrupted. + echo [ERROR] Expected: !EXPECTED_HASH! + echo [ERROR] Got: !ACTUAL_HASH! + popd + exit /b 1 +) + +:verify_done +REM Clean up checksum files +del /f /q "%BOOTSTRAP_FILE%.md5" 2>nul +del /f /q "%BOOTSTRAP_FILE%.sha256" 2>nul +popd +exit /b 0 + +REM ============================================ +REM Download files from a given base URL +REM Usage: call :do_download "base_url" +REM ============================================ +:do_download +set "BASE=%~1" + +REM Use PowerShell to download (available on all modern Windows) +echo [INFO] Downloading %BASE%/%BOOTSTRAP_FILE% ... +powershell -NoProfile -Command ^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; try { (New-Object Net.WebClient).DownloadFile('%BASE%/%BOOTSTRAP_FILE%', '%DATADIR%\%BOOTSTRAP_FILE%') } catch { exit 1 }" +if errorlevel 1 exit /b 1 + +echo [INFO] Downloading checksums... +powershell -NoProfile -Command ^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; try { (New-Object Net.WebClient).DownloadFile('%BASE%/%BOOTSTRAP_FILE%.md5', '%DATADIR%\%BOOTSTRAP_FILE%.md5') } catch { exit 1 }" +if errorlevel 1 exit /b 1 + +powershell -NoProfile -Command ^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; try { (New-Object Net.WebClient).DownloadFile('%BASE%/%BOOTSTRAP_FILE%.sha256', '%DATADIR%\%BOOTSTRAP_FILE%.sha256') } catch { exit 1 }" +if errorlevel 1 exit /b 1 + +exit /b 0 + +REM ============================================ +REM Extract bootstrap zip +REM ============================================ +:extract_bootstrap +echo [INFO] Extracting bootstrap... +pushd "%DATADIR%" + +REM Use PowerShell to extract zip, excluding wallet.dat and .conf files +powershell -NoProfile -Command ^ + "Add-Type -AssemblyName System.IO.Compression.FileSystem; $zip = [System.IO.Compression.ZipFile]::OpenRead('%DATADIR%\%BOOTSTRAP_FILE%'); foreach ($entry in $zip.Entries) { if ($entry.Name -eq 'wallet.dat' -or $entry.Name -like '*.conf') { continue } $dest = Join-Path '%DATADIR%' $entry.FullName; if ($entry.FullName.EndsWith('/')) { New-Item -ItemType Directory -Force -Path $dest | Out-Null } else { $parent = Split-Path $dest -Parent; if (-not (Test-Path $parent)) { New-Item -ItemType Directory -Force -Path $parent | Out-Null } [System.IO.Compression.ZipFileExtensions]::ExtractToFile($entry, $dest, $true) } }; $zip.Dispose()" +if errorlevel 1 ( + echo [ERROR] Extraction failed. + popd + exit /b 1 +) + +echo [INFO] Bootstrap extracted successfully. + +REM Clean up archive +del /f /q "%BOOTSTRAP_FILE%" 2>nul +echo [INFO] Removed downloaded archive to save disk space. + +popd +exit /b 0 + +:error_exit +echo. +echo [ERROR] Bootstrap installation failed. +exit /b 1 diff --git a/util/bootstrap-dragonx.sh b/util/bootstrap-dragonx.sh index 1b2b56091..be80fcd26 100755 --- a/util/bootstrap-dragonx.sh +++ b/util/bootstrap-dragonx.sh @@ -9,6 +9,7 @@ set -euo pipefail BOOTSTRAP_BASE_URL="https://bootstrap.dragonx.is" +BOOTSTRAP_FALLBACK_URL="https://bootstrap2.dragonx.is" BOOTSTRAP_FILE="DRAGONX.zip" CHAIN_NAME="DRAGONX" @@ -118,35 +119,49 @@ clean_chain_data() { info "Blockchain data cleaned." } -# Download a file via wget or curl +# Download a file via wget or curl (returns non-zero on failure) download_file() { local url="$1" local outfile="$2" if command -v wget &>/dev/null; then - wget --progress=bar:force -O "$outfile" "$url" || error "Download failed: $url" + wget --progress=bar:force -O "$outfile" "$url" elif command -v curl &>/dev/null; then - curl -L --progress-bar -o "$outfile" "$url" || error "Download failed: $url" + curl -L --progress-bar -o "$outfile" "$url" else error "Neither wget nor curl found. Please install one and retry." fi } +# Try downloading from a given base URL; returns non-zero on failure +download_from() { + local base_url="$1" + local outfile="$DATADIR/$BOOTSTRAP_FILE" + local md5file="$DATADIR/${BOOTSTRAP_FILE}.md5" + local sha256file="$DATADIR/${BOOTSTRAP_FILE}.sha256" + + info "Downloading bootstrap from $base_url ..." + info "This may take a while depending on your connection speed." + + download_file "$base_url/$BOOTSTRAP_FILE" "$outfile" || return 1 + info "Bootstrap download complete." + + info "Downloading checksums..." + download_file "$base_url/${BOOTSTRAP_FILE}.md5" "$md5file" || return 1 + download_file "$base_url/${BOOTSTRAP_FILE}.sha256" "$sha256file" || return 1 + return 0 +} + # Download the bootstrap and verify checksums download_bootstrap() { local outfile="$DATADIR/$BOOTSTRAP_FILE" local md5file="$DATADIR/${BOOTSTRAP_FILE}.md5" local sha256file="$DATADIR/${BOOTSTRAP_FILE}.sha256" - info "Downloading bootstrap from $BOOTSTRAP_BASE_URL ..." - info "This may take a while depending on your connection speed." - - download_file "$BOOTSTRAP_BASE_URL/$BOOTSTRAP_FILE" "$outfile" - info "Bootstrap download complete." - - info "Downloading checksums..." - download_file "$BOOTSTRAP_BASE_URL/${BOOTSTRAP_FILE}.md5" "$md5file" - download_file "$BOOTSTRAP_BASE_URL/${BOOTSTRAP_FILE}.sha256" "$sha256file" + if ! download_from "$BOOTSTRAP_BASE_URL"; then + warn "Primary download failed, trying fallback $BOOTSTRAP_FALLBACK_URL ..." + download_from "$BOOTSTRAP_FALLBACK_URL" || error "Download failed from both primary and fallback servers." + fi # Verify checksums info "Verifying checksums..."