# BitcoinConfig.psm1
# Advanced Bitcoin configuration module for Anya Core Installer
# Implements advanced Bitcoin configuration options (TODO.md: Bitcoin Layer Integration)
# Import required modules
using namespace System.Management.Automation
using namespace System.Collections.Generic
using namespace System.IO
# Module version
$script:ModuleVersion = "0.2.0"
# Bitcoin network types
enum BitcoinNetwork {
Mainnet
Testnet
Regtest
Signet
}
# Bitcoin configuration parameters class
class BitcoinConfigParams {
[string]$DataDir
[BitcoinNetwork]$Network = [BitcoinNetwork]::Mainnet
[int]$RPCPort = 8332
[string]$RPCUser
[string]$RPCPassword
[bool]$EnablePruning = $false
[int]$PruneSize = 0
[bool]$EnableTor = $false
[bool]$EnableZmq = $false
[string[]]$ExtraOptions = @()
[bool]$EnableIndexing = $false
[bool]$EnableCompactFilters = $false
[bool]$EnableMempool = $true
[int]$DbCache = 450
[int]$MaxConnections = 125
# Advanced options
[bool]$EnableRBF = $true
[bool]$EnableAssumeUTXO = $false
[string]$AssumeUTXOHash
[int]$AssumeUTXOSize
[bool]$EnableUpnp = $false
[bool]$EnableNatpmp = $false
[bool]$EnableCompactBlocks = $true
[bool]$EnableBlockFilterIndex = $false
[bool]$EnableTxIndex = $false
[bool]$EnableCoinstatsIndex = $false
# Lightning options
[bool]$ConfigureLightning = $false
[string]$LightningImplementation = "LND"
[int]$LightningPort = 9735
[int]$LightningRPCPort = 10009
# Validation
[void]ValidateConfiguration() {
if ($this.EnablePruning -and $this.PruneSize -lt 550) {
throw "Prune size must be at least 550 MB"
}
if ($this.EnablePruning -and $this.EnableIndexing) {
throw "Cannot enable both pruning and indexing"
}
if ($this.EnableAssumeUTXO -and [string]::IsNullOrEmpty($this.AssumeUTXOHash)) {
throw "AssumeUTXO hash must be specified when enabling AssumeUTXO"
}
}
}
# Function to create a bitcoin.conf file
function New-BitcoinConfig {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[BitcoinConfigParams]$ConfigParams,
[Parameter(Mandatory = $true)]
[string]$OutputPath,
[Parameter()]
[switch]$Force
)
try {
# Validate configuration parameters
$ConfigParams.ValidateConfiguration()
# Create the directory if it doesn't exist
$configDir = [Path]::GetDirectoryName($OutputPath)
if (-not (Test-Path -Path $configDir)) {
New-Item -Path $configDir -ItemType Directory -Force | Out-Null
}
# Check if file exists and force is not specified
if ((Test-Path -Path $OutputPath) -and -not $Force) {
throw "Configuration file already exists. Use -Force to overwrite."
}
# Generate the configuration file content
$configContent = @"
# Bitcoin configuration file generated by Anya Core Installer
# Generated on: $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")
# Configuration version: $script:ModuleVersion
# Network settings
"@
# Add network settings
switch ($ConfigParams.Network) {
([BitcoinNetwork]::Testnet) { $configContent += "`ntestnet=1" }
([BitcoinNetwork]::Regtest) { $configContent += "`nregtest=1" }
([BitcoinNetwork]::Signet) { $configContent += "`nsignet=1" }
}
# Add data directory setting if specified
if (-not [string]::IsNullOrEmpty($ConfigParams.DataDir)) {
$configContent += "`ndatadir=$($ConfigParams.DataDir)"
}
# Add RPC settings
$configContent += @"
# RPC settings
server=1
rpcport=$($ConfigParams.RPCPort)
rpcuser=$($ConfigParams.RPCUser)
rpcpassword=$($ConfigParams.RPCPassword)
rpcallowip=127.0.0.1
"@
# Add pruning settings if enabled
if ($ConfigParams.EnablePruning) {
$configContent += @"
# Pruning settings
prune=$($ConfigParams.PruneSize)
"@
}
# Add ZMQ settings if enabled
if ($ConfigParams.EnableZmq) {
$configContent += @"
# ZMQ settings
zmqpubrawblock=tcp://127.0.0.1:28332
zmqpubrawtx=tcp://127.0.0.1:28333
zmqpubhashblock=tcp://127.0.0.1:28334
"@
}
# Add Tor settings if enabled
if ($ConfigParams.EnableTor) {
$configContent += @"
# Tor settings
proxy=127.0.0.1:9050
listen=1
bind=127.0.0.1
onlynet=onion
"@
}
# Add indexing settings if enabled
if ($ConfigParams.EnableIndexing) {
$configContent += @"
# Indexing settings
txindex=1
"@
}
# Add compact filters if enabled
if ($ConfigParams.EnableCompactFilters) {
$configContent += @"
# Compact filters settings
peerblockfilters=1
blockfilterindex=1
"@
}
# Add mempool settings
$configContent += @"
# Mempool settings
persistmempool=$([int]$ConfigParams.EnableMempool)
"@
# Add advanced settings
$configContent += @"
# Advanced settings
dbcache=$($ConfigParams.DbCache)
maxconnections=$($ConfigParams.MaxConnections)
"@
# Add advanced RBF settings
if ($ConfigParams.EnableRBF) {
$configContent += "`nmempoolfullrbf=1"
}
# Add AssumeUTXO if enabled
if ($ConfigParams.EnableAssumeUTXO) {
$configContent += @"
# AssumeUTXO settings
assumeutxo=$($ConfigParams.AssumeUTXOHash)
"@
if ($ConfigParams.AssumeUTXOSize -gt 0) {
$configContent += "`nmaximagesize=$($ConfigParams.AssumeUTXOSize)"
}
}
# Add UPnP and NAT-PMP settings
if ($ConfigParams.EnableUpnp) {
$configContent += "`nupnp=1"
} else {
$configContent += "`nupnp=0"
}
if ($ConfigParams.EnableNatpmp) {
$configContent += "`nnatpmp=1"
} else {
$configContent += "`nnatpmp=0"
}
# Add Compact Blocks settings
if ($ConfigParams.EnableCompactBlocks) {
$configContent += "`nhighbandwidthnodes=1"
} else {
$configContent += "`nhighbandwidthnodes=0"
}
# Add additional index options
if ($ConfigParams.EnableBlockFilterIndex) {
$configContent += "`nblockfilterindex=basic"
}
if ($ConfigParams.EnableTxIndex) {
$configContent += "`ntxindex=1"
}
if ($ConfigParams.EnableCoinstatsIndex) {
$configContent += "`ncoinstatsindex=1"
}
# Add extra options if provided
if ($ConfigParams.ExtraOptions.Count -gt 0) {
$configContent += @"
# Extra options
$($ConfigParams.ExtraOptions -join "`n")
"@
}
# Write the configuration to the file
$configContent | Out-File -FilePath $OutputPath -Encoding utf8 -Force
# Generate Lightning configuration if enabled
if ($ConfigParams.ConfigureLightning) {
$lightningDir = Join-Path -Path (Split-Path -Path $OutputPath -Parent) -ChildPath "lightning"
if (-not (Test-Path -Path $lightningDir)) {
New-Item -Path $lightningDir -ItemType Directory -Force | Out-Null
}
$lightningConfig = @"
# Lightning configuration for $($ConfigParams.LightningImplementation)
# Generated on: $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")
bitcoin.active=1
"@
# Add network-specific settings
switch ($ConfigParams.Network) {
([BitcoinNetwork]::Mainnet) { $lightningConfig += "`nbitcoin.mainnet=1" }
([BitcoinNetwork]::Testnet) { $lightningConfig += "`nbitcoin.testnet=1" }
([BitcoinNetwork]::Regtest) { $lightningConfig += "`nbitcoin.regtest=1" }
([BitcoinNetwork]::Signet) { $lightningConfig += "`nbitcoin.signet=1" }
}
# Add Bitcoin RPC settings
$lightningConfig += @"
bitcoin.node=bitcoind
bitcoind.rpcuser=$($ConfigParams.RPCUser)
bitcoind.rpcpass=$($ConfigParams.RPCPassword)
bitcoind.rpcport=$($ConfigParams.RPCPort)
bitcoind.zmqpubrawblock=tcp://127.0.0.1:28332
bitcoind.zmqpubrawtx=tcp://127.0.0.1:28333
listen=0.0.0.0:$($ConfigParams.LightningPort)
rpclisten=0.0.0.0:$($ConfigParams.LightningRPCPort)
"@
# Write the Lightning configuration
$lightningConfigPath = Join-Path -Path $lightningDir -ChildPath "$($ConfigParams.LightningImplementation.ToLower()).conf"
$lightningConfig | Out-File -FilePath $lightningConfigPath -Encoding utf8 -Force
}
Write-Verbose "Bitcoin configuration successfully created at $OutputPath"
if ($ConfigParams.ConfigureLightning) {
Write-Verbose "Lightning configuration created for $($ConfigParams.LightningImplementation)"
}
return $true
}
catch {
Write-Error "Failed to create Bitcoin configuration: $_"
return $false
}
}
# Function to set up a complete Bitcoin environment
function Install-BitcoinEnvironment {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string]$InstallPath,
[Parameter()]
[BitcoinConfigParams]$ConfigParams = [BitcoinConfigParams]::new(),
[Parameter()]
[switch]$WithLightning,
[Parameter()]
[switch]$DownloadBinaries,
[Parameter()]
[switch]$Force
)
try {
# Create installation directory if it doesn't exist
if (-not (Test-Path -Path $InstallPath)) {
New-Item -Path $InstallPath -ItemType Directory -Force | Out-Null
Write-Verbose "Created installation directory at $InstallPath"
}
# Configure Lightning if requested
if ($WithLightning) {
$ConfigParams.ConfigureLightning = $true
}
# Create config file
$bitcoinConfigPath = Join-Path -Path $InstallPath -ChildPath "bitcoin.conf"
$configResult = New-BitcoinConfig -ConfigParams $ConfigParams -OutputPath $bitcoinConfigPath -Force:$Force
if (-not $configResult) {
throw "Failed to create Bitcoin configuration"
}
# Download binaries if requested
if ($DownloadBinaries) {
$binariesPath = Join-Path -Path $InstallPath -ChildPath "bin"
if (-not (Test-Path -Path $binariesPath)) {
New-Item -Path $binariesPath -ItemType Directory -Force | Out-Null
}
# Determine platform and architecture
$platform = if ($IsWindows) { "win" } elseif ($IsLinux) { "linux" } elseif ($IsMacOS) { "osx" } else { throw "Unsupported platform" }
$arch = if ([Environment]::Is64BitOperatingSystem) { "x86_64" } else { "x86" }
# Determine Bitcoin Core version (using the latest stable version)
$bitcoinVersion = "25.0"
# Construct download URL
$downloadUrl = "https://bitcoincore.org/bin/bitcoin-core-$bitcoinVersion/bitcoin-$bitcoinVersion-$platform-$arch.zip"
$downloadPath = Join-Path -Path $env:TEMP -ChildPath "bitcoin-$bitcoinVersion-$platform-$arch.zip"
# Download Bitcoin Core
Write-Verbose "Downloading Bitcoin Core $bitcoinVersion for $platform-$arch..."
Invoke-WebRequest -Uri $downloadUrl -OutFile $downloadPath
# Extract binaries
Write-Verbose "Extracting Bitcoin Core binaries..."
Expand-Archive -Path $downloadPath -DestinationPath $binariesPath -Force
# Move binaries to the bin directory (adjusting the path structure)
Get-ChildItem -Path "$binariesPath/bitcoin-$bitcoinVersion/bin" -File | Move-Item -Destination $binariesPath
# Clean up
Remove-Item -Path $downloadPath -Force
Remove-Item -Path "$binariesPath/bitcoin-$bitcoinVersion" -Recurse -Force
Write-Verbose "Bitcoin Core binaries installed at $binariesPath"
# If Lightning is enabled, download Lightning implementation
if ($WithLightning) {
$lightningDir = Join-Path -Path $InstallPath -ChildPath "lightning/bin"
if (-not (Test-Path -Path $lightningDir)) {
New-Item -Path $lightningDir -ItemType Directory -Force | Out-Null
}
# Determine Lightning implementation and version
$lightningImpl = $ConfigParams.LightningImplementation.ToLower()
$lightningVersion = "0.17.0-beta" # Example for LND
# Construct download URL (this is an example for LND, would need adjustment for other implementations)
$lightningUrl = "https://github.com/lightningnetwork/lnd/releases/download/v$lightningVersion/lnd-$platform-$arch-v$lightningVersion.tar.gz"
$lightningPath = Join-Path -Path $env:TEMP -ChildPath "lnd-$platform-$arch-v$lightningVersion.tar.gz"
# Download Lightning implementation
Write-Verbose "Downloading $lightningImpl $lightningVersion..."
Invoke-WebRequest -Uri $lightningUrl -OutFile $lightningPath
# Extract binaries (this would need platform-specific extraction commands)
Write-Verbose "Extracting $lightningImpl binaries..."
# Example for Windows - would need to adjust for other platforms
if ($IsWindows) {
tar -xzf $lightningPath -C $lightningDir
} else {
tar -xzf $lightningPath -C $lightningDir
}
# Clean up
Remove-Item -Path $lightningPath -Force
Write-Verbose "$lightningImpl binaries installed at $lightningDir"
}
}
# Create a simple verification script
$verificationScript = @"
#!/usr/bin/env pwsh
# Bitcoin environment verification script
Write-Host "Verifying Bitcoin environment..."
`$configPath = Join-Path -Path "`$PSScriptRoot" -ChildPath "bitcoin.conf"
if (Test-Path -Path `$configPath) {
Write-Host "Bitcoin configuration found at `$configPath"
`$configContent = Get-Content -Path `$configPath -Raw
Write-Host "Configuration version: `$(`$configContent -match 'Configuration version: (.+)' | ForEach-Object { `$matches[1] })"
} else {
Write-Host "Bitcoin configuration not found at `$configPath" -ForegroundColor Red
}
# Check for binaries
`$binPath = Join-Path -Path "`$PSScriptRoot" -ChildPath "bin/bitcoind"
if (!(Test-Path -Path `$binPath) -and `$IsWindows) {
`$binPath = Join-Path -Path "`$PSScriptRoot" -ChildPath "bin/bitcoind.exe"
}
if (Test-Path -Path `$binPath) {
Write-Host "Bitcoin daemon found at `$binPath"
try {
`$version = & `$binPath --version | Select-Object -First 1
Write-Host "Bitcoin version: `$version"
} catch {
Write-Host "Failed to get Bitcoin version: `$_" -ForegroundColor Yellow
}
} else {
Write-Host "Bitcoin daemon not found at `$binPath" -ForegroundColor Yellow
}
# Check for Lightning if configured
`$lightningConfigPath = Join-Path -Path "`$PSScriptRoot" -ChildPath "lightning"
if (Test-Path -Path `$lightningConfigPath) {
Write-Host "Lightning configuration directory found at `$lightningConfigPath"
Get-ChildItem -Path `$lightningConfigPath -Filter "*.conf" | ForEach-Object {
Write-Host "Lightning configuration file found: `$(`$_.Name)"
}
# Check for Lightning binaries
`$lightningBinPath = Join-Path -Path "`$PSScriptRoot" -ChildPath "lightning/bin"
if (Test-Path -Path `$lightningBinPath) {
Write-Host "Lightning binaries directory found at `$lightningBinPath"
Get-ChildItem -Path `$lightningBinPath -File | ForEach-Object {
Write-Host "Lightning binary found: `$(`$_.Name)"
}
}
}
Write-Host "Verification complete!"
"@
$verificationPath = Join-Path -Path $InstallPath -ChildPath "verify-environment.ps1"
$verificationScript | Out-File -FilePath $verificationPath -Encoding utf8 -Force
if ($IsLinux -or $IsMacOS) {
# Make verification script executable on Unix-like systems
chmod +x $verificationPath
}
Write-Verbose "Environment verification script created at $verificationPath"
return $true
}
catch {
Write-Error "Failed to set up Bitcoin environment: $_"
return $false
}
}
# Function to update an existing Bitcoin configuration with advanced options
function Update-BitcoinConfig {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string]$ConfigPath,
[Parameter()]
[hashtable]$UpdateParams = @{},
[Parameter()]
[switch]$Backup
)
try {
# Check if the configuration file exists
if (-not (Test-Path -Path $ConfigPath)) {
throw "Configuration file not found at $ConfigPath"
}
# Create a backup if requested
if ($Backup) {
$backupPath = "$ConfigPath.$(Get-Date -Format 'yyyyMMddHHmmss').bak"
Copy-Item -Path $ConfigPath -Destination $backupPath -Force
Write-Verbose "Created backup at $backupPath"
}
# Read the existing configuration
$existingConfig = Get-Content -Path $ConfigPath -Raw
# Update each parameter
foreach ($key in $UpdateParams.Keys) {
$value = $UpdateParams[$key]
# Check if the parameter already exists
if ($existingConfig -match "(?m)^$key=.*$") {
# Replace the existing value
$existingConfig = $existingConfig -replace "(?m)^$key=.*$", "$key=$value"
Write-Verbose "Updated parameter $key=$value"
} else {
# Add the parameter at the end
$existingConfig += "`n$key=$value"
Write-Verbose "Added parameter $key=$value"
}
}
# Write the updated configuration back to the file
$existingConfig | Out-File -FilePath $ConfigPath -Encoding utf8 -Force
Write-Verbose "Bitcoin configuration updated at $ConfigPath"
return $true
}
catch {
Write-Error "Failed to update Bitcoin configuration: $_"
return $false
}
}
# Function to determine the optimal Bitcoin configuration for the current system
function Get-OptimalBitcoinConfig {
[CmdletBinding()]
param()
try {
# Get system information
$totalMemoryGB = [math]::Round((Get-CimInstance -ClassName Win32_ComputerSystem).TotalPhysicalMemory / 1GB)
$cpuCount = (Get-CimInstance -ClassName Win32_Processor).NumberOfLogicalProcessors
$diskInfo = Get-CimInstance -ClassName Win32_LogicalDisk | Where-Object { $_.DriveType -eq 3 } | Select-Object -First 1
$freeSpaceGB = [math]::Round($diskInfo.FreeSpace / 1GB)
# Create a new configuration object
$config = [BitcoinConfigParams]::new()
# Set DB cache based on available memory
if ($totalMemoryGB -ge 32) {
$config.DbCache = 8192
} elseif ($totalMemoryGB -ge 16) {
$config.DbCache = 4096
} elseif ($totalMemoryGB -ge 8) {
$config.DbCache = 2048
} elseif ($totalMemoryGB -ge 4) {
$config.DbCache = 1024
} else {
$config.DbCache = 450
}
# Set max connections based on available CPU cores
if ($cpuCount -ge 16) {
$config.MaxConnections = 256
} elseif ($cpuCount -ge 8) {
$config.MaxConnections = 125
} elseif ($cpuCount -ge 4) {
$config.MaxConnections = 75
} else {
$config.MaxConnections = 50
}
# Determine if pruning should be enabled based on available disk space
if ($freeSpaceGB -lt 500) {
$config.EnablePruning = $true
$config.PruneSize = 550
} elseif ($freeSpaceGB -lt 1000) {
$config.EnablePruning = $true
$config.PruneSize = 2000
} else {
$config.EnableIndexing = $true
$config.EnableTxIndex = $true
}
# Set advanced options based on system capabilities
$config.EnableRBF = $true
$config.EnableCompactBlocks = $true
if ($cpuCount -ge 8 -and $totalMemoryGB -ge 16) {
$config.EnableCoinstatsIndex = $true
$config.EnableBlockFilterIndex = $true
}
# Set network options based on system capabilities
if ($totalMemoryGB -ge 8) {
$config.EnableUpnp = $true
$config.EnableNatpmp = $true
}
# Consider Lightning if system has sufficient resources
if ($totalMemoryGB -ge 8 -and $cpuCount -ge 4 -and $freeSpaceGB -ge 500) {
$config.ConfigureLightning = $true
}
return $config
}
catch {
Write-Error "Failed to determine optimal Bitcoin configuration: $_"
return $null
}
}
# Export module functions
Export-ModuleMember -Function New-BitcoinConfig, Install-BitcoinEnvironment, Update-BitcoinConfig, Get-OptimalBitcoinConfig