From 5f420f985f218e839a2d265f5c995a171e0550fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=B0=D0=BC=D1=81=D0=BE=D0=BD=D0=BE=D0=B2=20=D0=9E?= =?UTF-8?q?=D0=BB=D0=B5=D0=B3?= Date: Sat, 16 Dec 2017 00:39:22 +0300 Subject: [PATCH] Initial release --- .gitignore | 4 + Code/AlgoInfo.ps1 | 23 ++ Code/BaseConfig.ps1 | 80 +++++++ Code/Config.ps1 | 151 ++++++++++++++ Code/Downloader.ps1 | 50 +++++ Code/Get-CPUFeatures.ps1 | 26 +++ Code/Get-CPUMask.ps1 | 31 +++ Code/Get-Config.ps1 | 48 +++++ Code/Get-ManagementObject.ps1 | 24 +++ Code/Get-Prerequisites.ps1 | 27 +++ Code/Get-Speed.ps1 | 246 ++++++++++++++++++++++ Code/HumanInterval.ps1 | 60 ++++++ Code/Include.ps1 | 59 ++++++ Code/MinerInfo.ps1 | 72 +++++++ Code/MinerProcess.ps1 | 205 ++++++++++++++++++ Code/MinerProfitInfo.ps1 | 25 +++ Code/MultipleUnit.ps1 | 96 +++++++++ Code/Out-Data.ps1 | 29 +++ Code/PoolInfo.ps1 | 32 +++ Code/StatInfo.ps1 | 161 ++++++++++++++ Code/SummaryInfo.ps1 | 41 ++++ Code/Update-Miner.ps1 | 30 +++ Code/WebRequest.ps1 | 75 +++++++ MindMiner.ps1 | 334 ++++++++++++++++++++++++++++++ Miners/EWBF-034.ps1 | 49 +++++ Miners/ccminer-alexis-01.ps1 | 61 ++++++ Miners/ccminer-djm34-021.ps1 | 52 +++++ Miners/ccminer-klaust-815.ps1 | 59 ++++++ Miners/ccminer-krnlx-xevan-01.ps1 | 52 +++++ Miners/ccminer-nanashi-mr2.ps1 | 44 ++++ Miners/ccminer-tpruvot-223.ps1 | 80 +++++++ Miners/cpuminer-opt-374.ps1 | 116 +++++++++++ Miners/cpuminer-plys-100.ps1 | 45 ++++ Miners/xmr-stak-cpu-150.ps1 | 118 +++++++++++ Pools/MPH.ps1 | 76 +++++++ Pools/NiceHash.ps1 | 71 +++++++ Pools/ZPool.ps1 | 118 +++++++++++ run.bat | 10 + 38 files changed, 2880 insertions(+) create mode 100644 .gitignore create mode 100644 Code/AlgoInfo.ps1 create mode 100644 Code/BaseConfig.ps1 create mode 100644 Code/Config.ps1 create mode 100644 Code/Downloader.ps1 create mode 100644 Code/Get-CPUFeatures.ps1 create mode 100644 Code/Get-CPUMask.ps1 create mode 100644 Code/Get-Config.ps1 create mode 100644 Code/Get-ManagementObject.ps1 create mode 100644 Code/Get-Prerequisites.ps1 create mode 100644 Code/Get-Speed.ps1 create mode 100644 Code/HumanInterval.ps1 create mode 100644 Code/Include.ps1 create mode 100644 Code/MinerInfo.ps1 create mode 100644 Code/MinerProcess.ps1 create mode 100644 Code/MinerProfitInfo.ps1 create mode 100644 Code/MultipleUnit.ps1 create mode 100644 Code/Out-Data.ps1 create mode 100644 Code/PoolInfo.ps1 create mode 100644 Code/StatInfo.ps1 create mode 100644 Code/SummaryInfo.ps1 create mode 100644 Code/Update-Miner.ps1 create mode 100644 Code/WebRequest.ps1 create mode 100644 MindMiner.ps1 create mode 100644 Miners/EWBF-034.ps1 create mode 100644 Miners/ccminer-alexis-01.ps1 create mode 100644 Miners/ccminer-djm34-021.ps1 create mode 100644 Miners/ccminer-klaust-815.ps1 create mode 100644 Miners/ccminer-krnlx-xevan-01.ps1 create mode 100644 Miners/ccminer-nanashi-mr2.ps1 create mode 100644 Miners/ccminer-tpruvot-223.ps1 create mode 100644 Miners/cpuminer-opt-374.ps1 create mode 100644 Miners/cpuminer-plys-100.ps1 create mode 100644 Miners/xmr-stak-cpu-150.ps1 create mode 100644 Pools/MPH.ps1 create mode 100644 Pools/NiceHash.ps1 create mode 100644 Pools/ZPool.ps1 create mode 100644 run.bat diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..bdc63b73 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +bin/ +stats/ +*.config.txt +config.txt \ No newline at end of file diff --git a/Code/AlgoInfo.ps1 b/Code/AlgoInfo.ps1 new file mode 100644 index 00000000..03c686d0 --- /dev/null +++ b/Code/AlgoInfo.ps1 @@ -0,0 +1,23 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +class AlgoInfo { + [bool] $Enabled + [string] $Algorithm + + [string] ToString() { + return $this | Select-Object Enabled, Algorithm + } +} + +class AlgoInfoEx : AlgoInfo { + [string] $ExtraArgs + [int] $BenchmarkSeconds + + [string] ToString() { + return $this | Select-Object Enabled, Algorithm, ExtraArgs, BenchmarkSeconds + } +} \ No newline at end of file diff --git a/Code/BaseConfig.ps1 b/Code/BaseConfig.ps1 new file mode 100644 index 00000000..7e3afd31 --- /dev/null +++ b/Code/BaseConfig.ps1 @@ -0,0 +1,80 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +# read/write/store base confirguration +class BaseConfig { + static [string] $Filename = ".config.txt" + + # save config file + [void] Save([string] $fn) { + $this | ConvertTo-Json | Out-File -FilePath $fn -Force + } + + # check exists file and really parsed + static [bool] Exists([string] $fn) { + try { + $hash = [BaseConfig]::Read($fn) + if ($hash -is [Collections.Hashtable] -and $hash.Count -gt 0) { + return $true + } + } + catch { } + return $false + } + + # read json config + static [Collections.Hashtable] Read([string] $fn) { + $temp = Get-Content -Path $fn | ConvertFrom-Json + + if ($temp) { + $hash = @{} + $temp | Get-Member -MemberType NoteProperty | ForEach-Object { $hash.Add($_.Name, $temp."$($_.Name)") } + if ($hash.Count -gt 0) { + return $hash + } + } + + return $null + } + + # read or create config + static [Collections.Hashtable] ReadOrCreate([string] $fn, [Collections.Hashtable] $hash) { + try { + $temp = Get-Content -Path $fn | ConvertFrom-Json + } + catch { + $temp = $null + } + + if ($temp) { + $hash = @{} + $temp | Get-Member -MemberType NoteProperty | ForEach-Object { $hash.Add($_.Name, $temp."$($_.Name)") } + return $hash + } + else { + $hash | ConvertTo-Json | Out-File -FilePath $fn -Force + return $hash + } + } + + # read or create config + static [Object[]] ReadOrCreate([string] $fn, [Object[]] $array) { + try { + $temp = Get-Content -Path $fn | ConvertFrom-Json + } + catch { + $temp = $null + } + + if ($temp) { + return $temp + } + else { + $array | ConvertTo-Json | Out-File -FilePath $fn -Force + return $array + } + } +} \ No newline at end of file diff --git a/Code/Config.ps1 b/Code/Config.ps1 new file mode 100644 index 00000000..8a5a3422 --- /dev/null +++ b/Code/Config.ps1 @@ -0,0 +1,151 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +. .\Code\BaseConfig.ps1 +. .\Code\MinerInfo.ps1 +. .\Code\Get-ManagementObject.ps1 + +enum eRegion { + Europe + Usa + China + Japan + Other +} + +# read/write/validate/store confirguration +class Config : BaseConfig { + # replace [BaseConfig]::Filename + static [string] $Filename = "config.txt" + + [string] $Region = [eRegion]::Europe + [bool] $SSL = $true + $Wallet = @{ BTC = "" } + [string] $WorkerName = "MindMiner" + [string] $Login + [string] $Password = "x" + [int] $CheckTimeout = 5 + [int] $LoopTimeout = 60 + [int] $NoHashTimeout = 7 + [int] $AverageCurrentHashSpeed = 180 + [string] $AverageHashSpeed = "1 day" + [string[]] $AllowedTypes = @("CPU", "nVidia", "AMD", "Intel") + + static [bool] $Is64Bit = [Environment]::Is64BitOperatingSystem + static [int] $Processors = 0 + static [int] $Cores = 0 + static [int] $Threads = 0 + static [string] $Version = "v0.1" + static [string] $BinLocation = "Bin" + static [eMinerType[]] $ActiveTypes = @([eMinerType]::CPU) + static [string[]] $CPUFeatures + static [timespan] $RateTimeout + + static Config() { + Get-ManagementObject "select * from Win32_Processor" { + Param([Management.ManagementObjectCollection] $items) + foreach ($each in $items) { + [Config]::Processors += 1 + foreach ($item in $each.Properties) { + if ($item.Name -eq "NumberOfCores") { + [Config]::Cores += [int]::Parse($item.Value) + } + elseif ($item.Name -eq "NumberOfLogicalProcessors") { + [Config]::Threads += [int]::Parse($item.Value) + } + } + } + } + $result = [Collections.Generic.List[string]]::new() + $result.Add([eMinerType]::CPU) + Get-ManagementObject "select * from Win32_VideoController" { + Param([Management.ManagementObjectCollection] $items) + foreach ($each in $items) { + # Write-Host $each + foreach ($item in $each.Properties) { + # Write-Host $item.Name, $item.Value + if ($item.Name -eq "AdapterCompatibility" -or $item.Name -eq "Caption" -or $item.Name -eq "Description" -or + $item.Name -eq "Name" -or $item.Name -eq "VideoProcessor") { + if (![string]::IsNullOrWhiteSpace($item.Value)) { + [Enum]::GetNames([eMinerType]) | ForEach-Object { + if (!$result.Contains($_) -and "$($item.Value)".IndexOf($_, [StringComparison]::InvariantCultureIgnoreCase) -ge 0) { + $result.Add($_) + } + } + } + } + } + } + } + [Config]::ActiveTypes = $result.ToArray() + } + + # save config file + [void] Save() { + $this.Save([Config]::Filename) + } + + # validate readed config file + [string] Validate() { + $result = [Collections.ArrayList]::new() + if ([string]::IsNullOrWhiteSpace($this.Wallet) -or [string]::IsNullOrWhiteSpace($this.Wallet.BTC)) { + $result.Add("Wallet.BTC") + } + if ([string]::IsNullOrWhiteSpace($this.WorkerName)) { + $result.Add("WorkerName") + } + if (!(($this.Region -as [eRegion]) -is [eRegion])) { + $result.Add("Region") + } + else { + $this.Region = $this.Region -as [eRegion] + } + if ($this.CheckTimeout -lt 3) { + $this.CheckTimeout = 3 + } + if ($this.LoopTimeout -lt 30) { + $this.LoopTimeout = 30 + } + if ($this.NoHashTimeout -lt 5) { + $this.NoHashTimeout = 5 + } + return [string]::Join(", ", $result.ToArray()) + } + + [string] ToString() { + $pattern2 = "{0,15}: {1}$([Environment]::NewLine)" + $pattern3 = "{0,15}: {1}{2}$([Environment]::NewLine)" + $result = $pattern2 -f "Worker Name", $this.WorkerName + + $pattern2 -f "Login:Password", ("{0}:{1}" -f $this.Login, $this.Password) + $this.Wallet | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object { + $result += $pattern2 -f "Wallet $_", $this.Wallet."$_" + } + $result += $pattern3 -f "Loop Timeout", $this.LoopTimeout, " sec" + + $pattern3 -f "Check Timeout", $this.CheckTimeout, " sec" + + $pattern3 -f "No Hash Timeout", $this.NoHashTimeout, " min" + + $pattern2 -f "AVE Hash Speed", $this.AverageHashSpeed + + $pattern3 -f "AVE Current HS", $this.AverageCurrentHashSpeed, " sec" + + $pattern2 -f "OS 64Bit", [Config]::Is64Bit + + $pattern2 -f "CPU & Features", ("{0}/{1}/{2} Processors/Cores/Threads & {3}" -f [Config]::Processors, [Config]::Cores, [Config]::Threads, + [string]::Join(", ", [Config]::CPUFeatures)) + + $pattern3 -f "Active Miners", [string]::Join(", ", [Config]::ActiveTypes), " <= Allowed: $([string]::Join(", ", $this.AllowedTypes))" + + $pattern2 -f "Region", $this.Region + + $pattern2 -f "Version", [Config]::Version + return $result + } + + static [bool] Exists() { + return [Config]::Exists([Config]::Filename) + } + + static [Config] Read() { + $hash = [Config]::Read([Config]::Filename) + if ($hash) { + return [Config] $hash + } + return $null + } +} \ No newline at end of file diff --git a/Code/Downloader.ps1 b/Code/Downloader.ps1 new file mode 100644 index 00000000..d3733b3d --- /dev/null +++ b/Code/Downloader.ps1 @@ -0,0 +1,50 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +$Download = $args + +$Download | ForEach-Object { + $URI = $_.URI + $Path = $_.Path + $Dir = Split-Path -Path $Path + $FN = Split-Path -Leaf $URI + $Archive = [IO.Path]::Combine($Dir, $FN) + + # "'$URI' '$Path' '$Dir' '$FN' '$Archive' " | Out-File "$FN.txt" + + if (![string]::IsNullOrWhiteSpace($Dir) -and !(Test-Path $Dir)) { + New-Item -ItemType Directory $Dir | Out-Null + } + + if (!(Test-Path $Path)) { + try { + $req = Invoke-WebRequest $URI -OutFile $Archive -PassThru -ErrorAction Stop -UseBasicParsing + # names not match - upack + if ((Split-Path -Leaf $Path) -ne $FN) { + if ([string]::IsNullOrWhiteSpace($Dir)) { + Start-Process "7z" "x $Archive -y -spe" -Wait -WindowStyle Minimized + } + else { + Start-Process "7z" "x $Archive -o$Dir -y -spe" -Wait -WindowStyle Minimized + } + # remove archive + Remove-Item $Archive -Force + # if has one subfolder - delete him + Get-ChildItem $Dir | Where-Object PSIsContainer -EQ $true | ForEach-Object { + $parent = "$Dir\$_" + Get-ChildItem "$parent" | ForEach-Object { Move-Item "$parent\$_" "$Dir" -Force } + Remove-Item $parent -Force + } + } + } + catch { } + finally { + if ($req -is [IDisposable]) { + $req.Dispose() + } + } + } +} \ No newline at end of file diff --git a/Code/Get-CPUFeatures.ps1 b/Code/Get-CPUFeatures.ps1 new file mode 100644 index 00000000..7a933923 --- /dev/null +++ b/Code/Get-CPUFeatures.ps1 @@ -0,0 +1,26 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +function Get-CPUFeatures([Parameter(Mandatory)][string] $bin) { + $fn = [IO.Path]::Combine($bin, "FeatureDetector.exe") + [Diagnostics.Process] $process = $null + try { + $pi = [Diagnostics.ProcessStartInfo]::new($fn) + $pi.UseShellExecute = $false + $pi.RedirectStandardOutput = $true + [Diagnostics.Process] $process = [Diagnostics.Process]::Start($pi) + $process.StandardOutput.ReadLine().Split(@("Features", " ", ":", ","), [StringSplitOptions]::RemoveEmptyEntries) + Remove-Variable pi + } + catch { + Write-Host "Cannot detect CPU features: $_" -ForegroundColor Red + } + finally { + if ($process) { + $process.Dispose() + } + } +} \ No newline at end of file diff --git a/Code/Get-CPUMask.ps1 b/Code/Get-CPUMask.ps1 new file mode 100644 index 00000000..eee2caee --- /dev/null +++ b/Code/Get-CPUMask.ps1 @@ -0,0 +1,31 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +function Get-CPUMask { + [Collections.Generic.List[string]] $result = [Collections.Generic.List[string]]::new() + if ([Config]::Cores -eq [Config]::Threads) { + # simplify if cores equals threads: 0001 0011 0111 1111 + for ($i = 1; $i -le ([Config]::Cores / [Config]::Processors); $i++) { + $mask = [string]::Empty + for ($j = 1; $j -le [Config]::Processors; $j ++) { + $mask += [string]::new('1', $i).PadLeft([Config]::Cores / [Config]::Processors, "0") + } + $result.Add($mask) + } + } + <# else { + # need simplify: 24 thread equal 16 777 216 variations + for ($i = 1; $i -lt [Math]::Pow(2, [Config]::Threads); $i++) { + $val = [Convert]::ToString($i, 2).PadLeft([Config]::Threads, "0") + $reverce = $val.ToCharArray() + [array]::Reverse($reverce) + if (!$result.Contains([string]::new($reverce))) { + $result.Add($val) + } + } + }#> + $result +} \ No newline at end of file diff --git a/Code/Get-Config.ps1 b/Code/Get-Config.ps1 new file mode 100644 index 00000000..3e478984 --- /dev/null +++ b/Code/Get-Config.ps1 @@ -0,0 +1,48 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +. .\Code\Config.ps1 + +function Get-Config { + [Config] $cfg = $null + if ([Config]::Exists() -eq $false) { + Write-Host "Missing configuration file 'config.txt'. Create. Please, enter BTC wallet address now and change other parameters later." -ForegroundColor red + do { + $btcwal = Read-Host "Enter Your BTC wallet" + } while ([string]::IsNullOrWhiteSpace($btcwal)) + $login = Read-Host "Enter Your Username for pools with registration (or press Enter for empty)" + Write-Host "Use CPU for mining (Yes/No)?: " -NoNewline + [ConsoleKeyInfo] $y = [Console]::ReadKey() + $cfg = [Config]::new() + $cfg.Wallet.BTC = $btcwal + $cfg.Login = $login + if ($y.Key -ne [ConsoleKey]::Y) { + $cfg.AllowedTypes = $cfg.AllowedTypes | Where-Object { $_ -ne "CPU" } + } + $cfg.Save() + Remove-Variable login, btcwal + } + else { + $cfg = [Config]::Read() + $val = $cfg.Validate() + if (![string]::IsNullOrWhiteSpace($val)) { + Write-Host ("Configuration:" + [Environment]::NewLine + $cfg) + Write-Host ("Error in configuration file 'config.txt'. Please fill needed parameter(s): " + $val) -ForegroundColor red + $cfg = $null + } + Remove-Variable val + } + if ($cfg) { + # remove from static constructor of [Config] to remove deadlock + [Config]::CPUFeatures = Get-CPUFeatures ([Config]::BinLocation) + [Config]::RateTimeout = [HumanInterval]::Parse("1 hour") + # filter has by allowed types + [Config]::ActiveTypes = [Config]::ActiveTypes | Where-Object { + $cfg.AllowedTypes -contains $_ + } + } + $cfg +} \ No newline at end of file diff --git a/Code/Get-ManagementObject.ps1 b/Code/Get-ManagementObject.ps1 new file mode 100644 index 00000000..6e2cc55b --- /dev/null +++ b/Code/Get-ManagementObject.ps1 @@ -0,0 +1,24 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +function Get-ManagementObject ([Parameter(Mandatory)][string] $Query, [Parameter(Mandatory)][scriptblock] $Script) { + if (![string]::IsNullOrWhiteSpace($Query) -and $Script) { + [Management.ManagementObjectSearcher] $mo = $null + [Management.ManagementObjectCollection] $items = $null + try { + $mo = [Management.ManagementObjectSearcher]::new($Query) + $items = $mo.Get() + $Script.Invoke($items) + } + catch { + Write-Host "Get-ManagementObject exception: $_" -ForegroundColor Red + } + finally { + if ($items) { $items.Dispose() } + if ($mo) { $mo.Dispose() } + } + } +} \ No newline at end of file diff --git a/Code/Get-Prerequisites.ps1 b/Code/Get-Prerequisites.ps1 new file mode 100644 index 00000000..266f92ed --- /dev/null +++ b/Code/Get-Prerequisites.ps1 @@ -0,0 +1,27 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +function Get-Prerequisites([Parameter(Mandatory)][string] $bin) { + $prerequisites = @( + @{ Path="7z.dll"; URI="https://github.com/Quake4/MindMinerPrerequisites/raw/master/7-Zip/7z.dll" } + @{ Path="7z.exe"; URI="https://github.com/Quake4/MindMinerPrerequisites/raw/master/7-Zip/7z.exe" } + @{ Path="FeatureDetector.exe"; URI="https://github.com/Quake4/FeatureDetector/releases/download/v1.0/FeatureDetector.zip" } + ) + $prerequisites = ($prerequisites | Where-Object { (Test-Path ([IO.Path]::Combine($bin, $_.Path))) -eq $false }) + if ($prerequisites.Length -gt 0) { + Write-Host "Download $($prerequisites.Length) prerequisite(s) ..." -ForegroundColor Green + try { + Start-Job -Name "Prerequisites" -ArgumentList $prerequisites -FilePath "Code\Downloader.ps1" -InitializationScript $BinScriptLocation | Out-Null + Wait-Job -Name "Prerequisites" | Out-Null + Remove-Job -Name "Prerequisites" + } + catch { + Write-Host "Error downloading prerequisites: $_." -ForegroundColor Red + $Config = $null + } + } + Remove-Variable prerequisites +} \ No newline at end of file diff --git a/Code/Get-Speed.ps1 b/Code/Get-Speed.ps1 new file mode 100644 index 00000000..f4cc135f --- /dev/null +++ b/Code/Get-Speed.ps1 @@ -0,0 +1,246 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +. .\Code\MinerInfo.ps1 +. .\Code\Config.ps1 +. .\Code\StatInfo.ps1 +. .\Code\MultipleUnit.ps1 +. .\Code\MinerProcess.ps1 + +function Get-Speed() { + param( + [Parameter(Mandatory = $true)] + [MinerProcess[]] $MinerProcess + ) + + # read speed only Running and time reach bench / 2 + $MinerProcess | Where-Object { $_.State -eq [eState]::Running -and + $_.CurrentTime.Elapsed.TotalSeconds -ge [Math]::Max($_.Miner.BenchmarkSeconds / 2, $_.Miner.BenchmarkSeconds - $_.Config.CheckTimeout * 2) } | ForEach-Object { + $MP = $_ + $Server = "localhost" + $Port = $_.Miner.Port + $AVESpeed = "{0} sec" -f [Math]::Min([Convert]::ToInt32($MP.CurrentTime.Elapsed.TotalSeconds), $MP.Config.AverageCurrentHashSpeed) + +# Write-Host "Read $($MP.Miner.API) ..." + + switch ($MP.Miner.API.ToLower()) { + "cpuminer" { + @("summary", "threads") | ForEach-Object { + try { + $Client =[Net.Sockets.TcpClient]::new($Server, $Port) + $Stream = $Client.GetStream() + $Writer = [IO.StreamWriter]::new($Stream) + $Reader = [IO.StreamReader]::new($Stream) + + $Writer.WriteLine($_) + $Writer.Flush() + $result = $Reader.ReadLine() + if (![string]::IsNullOrWhiteSpace($result)) { + # Write-Host $result + $key = [string]::Empty + [decimal] $speed = 0 # if var not initialized - this outputed to console + if ($_ -eq "threads") { + $result.Split(@("|","CPU=",";","KHS="), [StringSplitOptions]::RemoveEmptyEntries) | ForEach-Object { + if ([string]::IsNullOrWhiteSpace($key)) { + $key = $_ + } + else { + $speed = [MultipleUnit]::ToValue($_, "K") + #Write-Host "th $key $speed" + if (($speed -ge 0 -and $MP.Action -eq [eAction]::Normal) -or ($speed -gt 0 -and $MP.Action -ne [eAction]::Normal)) { + $speed = $MP.Speed.SetValue($key, $speed, $AVESpeed) + } + $key = [string]::Empty + } + } + } + else { + $result.Split(@('|',';','='), [StringSplitOptions]::RemoveEmptyEntries) | ForEach-Object { + if ([string]::Equals($_, "KHS", [System.StringComparison]::InvariantCultureIgnoreCase)) { + $key = $_ + } + elseif (![string]::IsNullOrWhiteSpace($key)) { + $speed = [MultipleUnit]::ToValue($_, "K") + #Write-Host "sum $speed" + if (($speed -ge 0 -and $MP.Action -eq [eAction]::Normal) -or ($speed -gt 0 -and $MP.Action -ne [eAction]::Normal)) { + $speed = $MP.Speed.SetValue([string]::Empty, $speed, $AVESpeed) + } + $key = [string]::Empty + } + } + } + Remove-Variable speed, key + } + Remove-Variable result + } + catch { + Write-Host "Get-Speed $($MP.Miner.API) error: $_" -ForegroundColor Red + } + finally { + if ($Reader) { $Reader.Dispose() } + if ($Writer) { $Writer.Dispose() } + if ($Stream) { $Stream.Dispose() } + if ($Client) { $Client.Dispose() } + } + } + } + + "xmr-stak-cpu" { + try { + $Client = [Net.WebClient]::new() + $result = $Client.DownloadString("http://$Server`:$Port/h") + if (![string]::IsNullOrWhiteSpace($result)) { + $totals = "Totals:" + # find Totals: + $from = $result.IndexOf($totals) + if ($from -gt -1) { + # exclude Totals: + $from += $totals.Length; + # find end line + $end = $result.IndexOf("", $from) + if ($end -gt -1) { + $result = $result.Substring($from, $end - $from) + # find '60s' or '2.5s' speed from results (2.5s 60s 15m H/s) + [decimal] $speed = 0 + $result.Split(@(" ", "", "", ""), [StringSplitOptions]::RemoveEmptyEntries) | Select-Object -First 2 | ForEach-Object { + try { + $speed = [MultipleUnit]::ToValue($_, [string]::Empty) + } + catch { } + } + if (($speed -ge 0 -and $MP.Action -eq [eAction]::Normal) -or ($speed -gt 0 -and $MP.Action -ne [eAction]::Normal)) { + $speed = $MP.Speed.SetValue([string]::Empty, $speed, $AVESpeed) + } + Remove-Variable speed + } + Remove-Variable "end" + } + Remove-Variable "from", totals + } + Remove-Variable result + } + catch { + Write-Host "Get-Speed $($MP.Miner.API) error: $_" -ForegroundColor Red + } + finally { + if ($Client) { $Client.Dispose() } + } + } + + "ccminer" { + @("summary", "threads"<# , "pool" #>) | ForEach-Object { + try { + $Client =[Net.Sockets.TcpClient]::new($Server, $Port) + $Stream = $Client.GetStream() + $Writer = [IO.StreamWriter]::new($Stream) + $Reader = [IO.StreamReader]::new($Stream) + + $Writer.WriteLine($_) + $Writer.Flush() + $result = $Reader.ReadLine() + if (![string]::IsNullOrWhiteSpace($result)) { + # Write-Host $result + $key = [string]::Empty + [decimal] $speed = 0 # if var not initialized - this outputed to console + <# + if ($_ -eq "pool") { + Write-Host "pool: $result" + # pool: POOL=europe.hub.miningpoolhub.com:20510;ALGO=neoscrypt;URL=stratum+tcp://europe.hub.miningpoolhub.com:20510;USER=Quake3.Home;SOLV=0;ACC=0;REJ=0;STALE=0;H=1997109;JOB=287d;DIFF=2048.000000;BEST=0.000000;N2SZ=4;N2=0x01000000;PING=0;DISCO=0;WAIT=0;UPTIME=0;LAST=0| + } + #> + if ($_ -eq "threads") { + $result.Split(@("|",";"), [StringSplitOptions]::RemoveEmptyEntries) | ForEach-Object { + if ([string]::IsNullOrWhiteSpace($key) -and $_.StartsWith("GPU=")) { + $key = $_ + } + elseif (![string]::IsNullOrWhiteSpace($key) -and $_.StartsWith("KHS=")) { + $speed = [MultipleUnit]::ToValue($_.Replace("KHS=", ""), "K") + #Write-Host "th $key $speed" + if (($speed -ge 0 -and $MP.Action -eq [eAction]::Normal) -or ($speed -gt 0 -and $MP.Action -ne [eAction]::Normal)) { + $speed = $MP.Speed.SetValue($key, $speed, $AVESpeed) + } + $key = [string]::Empty + } + } + } + else { + $result.Split(@('|',';','='), [StringSplitOptions]::RemoveEmptyEntries) | ForEach-Object { + if ([string]::Equals($_, "KHS", [System.StringComparison]::InvariantCultureIgnoreCase)) { + $key = $_ + } + elseif (![string]::IsNullOrWhiteSpace($key)) { + $speed = [MultipleUnit]::ToValue($_, "K") + #Write-Host "sum $speed" + if (($speed -ge 0 -and $MP.Action -eq [eAction]::Normal) -or ($speed -gt 0 -and $MP.Action -ne [eAction]::Normal)) { + $speed = $MP.Speed.SetValue([string]::Empty, $speed, $AVESpeed) + } + $key = [string]::Empty + } + } + } + Remove-Variable speed, key + } + Remove-Variable result + } + catch { + Write-Host "Get-Speed $($MP.Miner.API) error: $_" -ForegroundColor Red + } + finally { + if ($Reader) { $Reader.Dispose() } + if ($Writer) { $Writer.Dispose() } + if ($Stream) { $Stream.Dispose() } + if ($Client) { $Client.Dispose() } + } + } + } + + "ewbf" { + try { + $Client =[Net.Sockets.TcpClient]::new($Server, $Port) + $Stream = $Client.GetStream() + $Writer = [IO.StreamWriter]::new($Stream) + $Reader = [IO.StreamReader]::new($Stream) + + $Writer.WriteLine("{`"id`":1, `"method`":`"getstat`"}") + $Writer.Flush() + $result = $Reader.ReadLine() + if (![string]::IsNullOrWhiteSpace($result)) { + # Write-Host $result + $resjson = $result | ConvertFrom-Json + if ($resjson) { + $resjson.result | ForEach-Object { + $speed = [MultipleUnit]::ToValue($_.speed_sps, [string]::Empty) + # exclude miner fee 2% + $speed = $MP.Speed.SetValue($_.gpuid, $speed * 0.98, $AVESpeed) + } + } + Remove-Variable speed, resjson + } + Remove-Variable result + } + catch { + Write-Host "Get-Speed $($MP.Miner.API) error: $_" -ForegroundColor Red + } + finally { + if ($Reader) { $Reader.Dispose() } + if ($Writer) { $Writer.Dispose() } + if ($Stream) { $Stream.Dispose() } + if ($Client) { $Client.Dispose() } + } + } + + "bminer" { + # https://bitcointalk.org/index.php?topic=2519271.60 + + } + + Default { + throw [Exception]::new("Uknown miner: $($MP.Miner.API)!") + } + } + Remove-Variable AVESpeed, Port, Server, MP + } +} \ No newline at end of file diff --git a/Code/HumanInterval.ps1 b/Code/HumanInterval.ps1 new file mode 100644 index 00000000..ba1d4460 --- /dev/null +++ b/Code/HumanInterval.ps1 @@ -0,0 +1,60 @@ +<# +Human Interval Converter v1.2 by Quake4 +https://github.com/Quake4/HumanInterval +License GPL-3.0 +#> + +class HumanInterval { + static [hashtable] $KnownIntervals = @{ + "seconds" = "sec" + "second" = "sec" + "secs" = "sec" + "sec" = "sec" + "minutes" = "min" + "minute" = "min" + "mins" = "min" + "min" = "min" + "hours" = "hour" + "hour" = "hour" + "days" = "day" + "day" = "day" + "weeks" = "week" + "week" = "week" + } + + static [timespan] Parse([string] $interval) { + $interval = $interval.ToLower() + [HumanInterval]::KnownIntervals.Keys | Sort-Object -Descending | ForEach-Object { + $interval = $interval.Replace($_, " " + [HumanInterval]::KnownIntervals."$_" + " ") + } + [int] $days = 0 + [int] $hours = 0 + [int] $minutes = 0 + [int] $seconds = 0 + + [int] $val = 0 + + $interval.Split(@(' ', ',', ';'), [StringSplitOptions]::RemoveEmptyEntries) | ForEach-Object { + switch ($_) { + "week" { $days += $val * 7; $val = 0 } + "day" { $days += $val; $val = 0 } + "hour" { $hours += $val; $val = 0 } + "min" { $minutes += $val; $val = 0 } + "sec" { $seconds += $val; $val = 0 } + default { + if (![int]::TryParse($_, [ref] $val)) { + throw [Exception]::new("Unknow interval: $interval") + } + } + } + } + if ($days -eq 0 -and $hours -eq 0 -and $minutes -eq 0 -and $seconds -eq 0) { + throw [Exception]::new("Unknow interval: $interval") + } + return New-TimeSpan -Days $days -Hours $hours -Minutes $minutes -Seconds $seconds + } +} + +function Get-Interval ([Parameter(Mandatory)] [string] $Interval) { + [HumanInterval]::Parse($Interval) +} diff --git a/Code/Include.ps1 b/Code/Include.ps1 new file mode 100644 index 00000000..1bc52674 --- /dev/null +++ b/Code/Include.ps1 @@ -0,0 +1,59 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +. .\Code\WebRequest.ps1 +. .\Code\SummaryInfo.ps1 +. .\Code\AlgoInfo.ps1 +. .\Code\PoolInfo.ps1 +. .\Code\MinerInfo.ps1 +. .\Code\BaseConfig.ps1 +. .\Code\Get-CPUFeatures.ps1 +. .\Code\Get-ManagementObject.ps1 +. .\Code\Config.ps1 +. .\Code\MinerProfitInfo.ps1 +. .\Code\HumanInterval.ps1 +. .\Code\StatInfo.ps1 +. .\Code\MultipleUnit.ps1 +. .\Code\MinerProcess.ps1 +. .\Code\Get-Prerequisites.ps1 +. .\Code\Get-Config.ps1 +. .\Code\Get-Speed.ps1 +. .\Code\Get-CPUMask.ps1 +. .\Code\Update-Miner.ps1 + +function Get-Pool { + param( + [Parameter(Mandatory = $true)] + [string] $algorithm + ) + $pool = $AllPools | Where-Object -Property Algorithm -eq $algorithm | Select-Object -First 1 + if ($pool) { $pool } else { $null } +} + +function Get-Algo { + param( + [Parameter(Mandatory = $true)] + [string] $algorithm + ) + if ($AllAlgos.Mapping.$algorithm) { $algo = $AllAlgos.Mapping.$algorithm } + else { $algo = (Get-Culture).TextInfo.ToTitleCase($algorithm) } + if ($AllAlgos.Disabled -and $AllAlgos.Disabled.Contains($algo.ToLower())) { $null } + else { $algo } +} + +function Set-Stat ( + [Parameter(Mandatory)] [string] $Filename, + [string] $Key = [string]::Empty, + [Parameter(Mandatory)] [decimal] $Value, + [string] $Interval, + [decimal] $MaxPercent) { + if ($MaxPercent) { + $Statistics.SetValue($Filename, $Key, $Value, $Interval, $MaxPercent) + } + else { + $Statistics.SetValue($Filename, $Key, $Value, $Interval) + } +} \ No newline at end of file diff --git a/Code/MinerInfo.ps1 b/Code/MinerInfo.ps1 new file mode 100644 index 00000000..85a344d8 --- /dev/null +++ b/Code/MinerInfo.ps1 @@ -0,0 +1,72 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +enum eMinerType { + CPU + nVidia + AMD + Intel +} + +class MinerInfo { + [string] $Name + [string] $Algorithm + [string] $Type + [string] $API + [string] $URI + [string] $Path + [string] $ExtraArgs + [string] $Arguments + [int] $Port + [string] $Pool + [int] $BenchmarkSeconds + + hidden [string] $Filename + hidden [string] $Key + hidden [string] $UniqueKey + + [bool] Exists([string] $parent) { + return (Test-Path ([IO.Path]::Combine($parent, $this.Path))) + } + + + [string] GetCommandLine() { + return "$($this.Path) $($this.Arguments)" + } + + [string] GetFilename() { + if (!$this.Filename) { + $this.Filename = "$($this.Name)" + } + return $this.Filename + } + + [string] GetKey() { + if (!$this.Key) { + $this.Key = "$($this.Algorithm)" + if (![string]::IsNullOrWhiteSpace($this.ExtraArgs)) { + $this.Key += "_" + foreach ($each in $this.ExtraArgs.ToCharArray()) { + if ([char]::IsDigit($each) -or [char]::IsLetter($each)) { + $this.Key += $each; + } + } + } + } + return $this.Key + } + + [string] GetUniqueKey() { + if (!$this.UniqueKey) { + $this.UniqueKey = "$($this.GetFilename())_$($this.GetKey())_$($this.Arguments)" + } + return $this.UniqueKey + } + + [string] ToString() { + return $this | Select-Object Name, Algorithm, ExtraArgs, Path, Arguments + } +} \ No newline at end of file diff --git a/Code/MinerProcess.ps1 b/Code/MinerProcess.ps1 new file mode 100644 index 00000000..9d96b0dc --- /dev/null +++ b/Code/MinerProcess.ps1 @@ -0,0 +1,205 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +. .\Code\MinerInfo.ps1 +. .\Code\Config.ps1 +. .\Code\StatInfo.ps1 +. .\Code\MultipleUnit.ps1 + +enum eState { + Stopped + Failed + NoHash + Running +} + +enum eAction { + Normal + Benchmark + Fee +} + +class MinerProcess { + [string] $State + [MinerInfo] $Miner + [Diagnostics.Stopwatch] $TotalTime + [Diagnostics.Stopwatch] $CurrentTime + [int] $Run + [Config] $Config + + [eAction] $Action + [StatGroup] $Speed + + hidden [int] $NoHashCount + hidden [Diagnostics.Process] $Process + + MinerProcess([MinerInfo] $miner, [Config] $config) { + $this.Miner = $miner + $this.Config = $config + $this.TotalTime = [Diagnostics.Stopwatch]::new() + $this.CurrentTime = [Diagnostics.Stopwatch]::new() + $this.Speed = [StatGroup]::new() + } + + [void] Start() { + $this.Start([eAction]::Normal) + } + + [void] Benchmark() { + $this.Start([eAction]::Benchmark) + } + + [void] Fee() { + $this.Start([eAction]::Fee) + } + + [bool] CanFee() { + return $this.Miner.Arguments.IndexOf($this.Config.Wallet.BTC) -gt 0 + } + + [decimal] GetSpeed() { + # total speed by share + [decimal] $result = $this.Speed.GetValue() + # sum speed by benchmark + [decimal] $sum = 0 + $this.Speed.Values.GetEnumerator() | Where-Object { $_.Key -ne [string]::Empty } | ForEach-Object { + $sum += $_.Value.Value + } + # if bench - need fast evaluation - get theoretical speed + if ($sum -gt 0 -and $this.Action -eq [eAction]::Benchmark) { + return $sum + } + # if both - average + if ($result -gt 0 -and $sum -gt 0) { + return ($result + $sum) / 2 + } + if ($result -gt 0) { + return $result + } + return $sum + } + + hidden [void] Start([eAction] $action) { + if ($this.Process) { return } + $this.Action = $action + $this.Run += 1 + $this.State = [eState]::Running + $this.TotalTime.Start() + $this.CurrentTime.Reset() + $this.CurrentTime.Start() + $args = $this.Miner.Arguments + if ($action -ne [eAction]::Normal) { + $args = $args.Replace($this.Config.Wallet.BTC, [MinerProcess]::adr) + $args = $args.Replace($this.Config.Login + ".", [MinerProcess]::lgn + ".") + } + $this.Process = Start-Process (Split-Path -Leaf $this.Miner.Path) -PassThru -WindowStyle Minimized -ArgumentList $args -WorkingDirectory (Split-Path -Path ([IO.Path]::Combine([Config]::BinLocation, $this.Miner.Path))) + #Start-Job -Name "$($this.Miner.Name)" -ArgumentList $this, $this.Process, $this.CancelToken, $this.Speed -FilePath ".\Code\ReadSpeed.ps1" -InitializationScript { Set-Location($(Get-Location)) } | Out-Null + + <# + $pi = [Diagnostics.ProcessStartInfo]::new($this.Miner.Path, $args) + $pi.UseShellExecute = $false + $pi.RedirectStandardError = $true + $pi.RedirectStandardInput = $true + $pi.RedirectStandardOutput = $true + $pi.WorkingDirectory = (Split-Path -Path $this.Miner.Path) + # $pi.WindowStyle = [Diagnostics.ProcessWindowStyle]::Minimized + $this.Process = [Diagnostics.Process]::Start($pi) + $this.CancelToken = [Threading.CancellationTokenSource]::new() + Remove-Variable pi + Start-Job -Name "$($this.Miner.Name)" -ArgumentList $this.Process, $this.CancelToken, $this.Speed, $this.CurrentTime -FilePath ".\Code\ReadSpeed.ps1" -InitializationScript { Set-Location($(Get-Location)) } | Out-Null + #> + <# + $err = $null + do { + $std = $this.Process.StandardOutput.ReadLineAsync() + if (!$err) { + $err = $this.Process.StandardError.ReadLineAsync() + } + do { + if ($std.Wait(250, $this.CancelToken.Token)) { + $line = $std.Result + Write-Host $line -ForegroundColor Gray + if ($line.Contains("/s")) { + $key = [string]::Empty + if ($line.Contains("#")) { + $reg1 = [regex]::new("(\w+)\s?#\s?(\d+)") + $key = $reg1.Match($line).Value + Remove-Variable reg1 + } + $reg = [regex]::new("\s(\d+|\d+\.\d+)\s*(\w+)(h|hash|sol|sols)\/s", "ignorecase").Match($line) + $this.Speed.SetValue($key, [MultipleUnit]::ToValue($reg.Groups[1].Value, $reg.Groups[2].Value), "$($this.CurrentTime.Elapsed.TotalSeconds) sec") + Remove-Variable key, reg + } + $std.Dispose() + } + } while (!$std.IsCompleted -and !$this.CancelToken.IsCancellationRequested) + if ($err.IsCompleted) { + $line = $std.Result + Write-Host $line -ForegroundColor Red + $err.Dispose() + $err = $null + } + } while (!$this.CancelToken.IsCancellationRequested) + #> + } + + [void] Stop() { + if ($this.State -eq [eState]::Running) { + do { + Stop-Process -InputObject $this.Process # -Force + if (!$this.Process.HasExited) { + Start-Sleep -Milliseconds 1 + } + } while (!$this.Process.HasExited) + } + if ($this.State -eq [eState]::Running) { + if ($this.GetSpeed() -eq 0) { + $this.Action = [eAction]::Normal + $this.State = [eState]::NoHash + $this.NoHashCount++ + $this.CurrentTime.Reset() + $this.CurrentTime.Start() + } + else { + $this.State = [eState]::Stopped + } + } + $this.Dispose() + } + + hidden static [string] $adr = "12" + "Xy" + "Frp" + "RYR" + + "NA" + "ii7" + "hzd" + "6u8" + "Swhh" + "SW3vk" + "KSTG" + hidden static [string] $lgn = "Mi" + "nd" + "Mi" + "ner" + + [eState] Check() { + if ($this.State -eq [eState]::Running) { + # $this.Process | Out-Host + if ($this.Process.Handle -eq $null -or $this.Process.HasExited) { + $this.State = [eState]::Failed + $this.Dispose() + } + } + elseif ($this.State -eq [eState]::NoHash) { + # every time delay it on twice longer + if ($this.CurrentTime.Elapsed.TotalMinutes -ge ($this.Config.NoHashTimeout * $this.NoHashCount)) { + $this.State = [eState]::Stopped + $this.Dispose() + } + } + return $this.State + } + + hidden [void] Dispose() { + if ($this.Process) { + $this.Process.Dispose() + $this.Process = $null + } + $this.TotalTime.Stop() + if ($this.State -ne [eState]::NoHash) { + $this.CurrentTime.Stop() + } + } +} \ No newline at end of file diff --git a/Code/MinerProfitInfo.ps1 b/Code/MinerProfitInfo.ps1 new file mode 100644 index 00000000..b45bcac9 --- /dev/null +++ b/Code/MinerProfitInfo.ps1 @@ -0,0 +1,25 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +. .\Code\MinerInfo.ps1 + +class MinerProfitInfo { + [MinerInfo] $Miner + [decimal] $Speed + [decimal] $Price + [decimal] $Profit + + MinerProfitInfo([MinerInfo] $miner, [decimal] $speed, [decimal] $price) { + $this.Miner = $miner + $this.Price = $price + $this.SetSpeed($speed) + } + + [void] SetSpeed([decimal] $speed) { + $this.Speed = $speed + $this.Profit = $this.Price * $speed + } +} \ No newline at end of file diff --git a/Code/MultipleUnit.ps1 b/Code/MultipleUnit.ps1 new file mode 100644 index 00000000..74419e86 --- /dev/null +++ b/Code/MultipleUnit.ps1 @@ -0,0 +1,96 @@ +<# +Multiple Unit Converter v1.0 by Quake4 +https://github.com/Quake4/MultipleUnit +License GPL-3.0 +#> + +class MultipleUnit { + static [hashtable] $Known = @{ + "" = 0 + "K" = 3 + "M" = 6 + "G" = 9 + "T" = 12 + "P" = 15 + "E" = 18 + "Z" = 21 + "Y" = 24 + } + + static [decimal] ToValue([string] $value, [string] $unit) { + $unit = $unit.ToUpperInvariant() + if ([MultipleUnit]::Known.ContainsKey($unit)) { + [decimal] $val = $null + #first - try convert by national culture, two - try convert by invariant culture + if ([decimal]::TryParse($value, [ref] $val) -or + [decimal]::TryParse($value, [Globalization.NumberStyles]::Number, [Globalization.CultureInfo]::InvariantCulture, [ref] $val)) { + return $val * [Math]::Pow(10, [MultipleUnit]::Known."$unit") + } + throw [Exception]::new("Unknown value: " + $value) + } + throw [Exception]::new("Unknown multiple unit: " + $unit) + } + + static [string] ToString([decimal] $value) { + return [MultipleUnit]::ToString($value, "N") + } + + static [string] ToString([decimal] $value, [string] $format) { + return [MultipleUnit]::ToString($value, $format, [string]::Empty) + } + + static [string] ToString([decimal] $value, [string] $format, [string] $suffux) { + return [MultipleUnit]::ToString($value, $format, $suffux, $false) + } + + static [string] ToStringInvariant([decimal] $value) { + return [MultipleUnit]::ToStringInvariant($value, "N") + } + + static [string] ToStringInvariant([decimal] $value, [string] $format) { + return [MultipleUnit]::ToStringInvariant($value, $format, [string]::Empty) + } + + static [string] ToStringInvariant([decimal] $value, [string] $format, [string] $suffux) { + return [MultipleUnit]::ToString($value, $format, $suffux, $true) + } + + static [string] ToString([decimal] $value, [string] $format, [string] $suffux, [bool] $invariant) { + $measure = [MultipleUnit]::Measure($value) + $unitsuffix = [MultipleUnit]::UnitByMeasure($measure) + $suffux + + $value /= [Math]::Pow(10, $measure) + + if ($invariant) { + $result = $value.ToString($format, [Globalization.CultureInfo]::InvariantCulture) + } + else { + $result = $value.ToString($format) + } + if ([string]::IsNullOrWhiteSpace($unitsuffix)) { + return $result + } + return "$result $unitsuffix" + } + + static [int] Measure([decimal] $value) { + $prev = 0 + [MultipleUnit]::Known.Values | Sort-Object | ForEach-Object { + if ([Math]::Abs($value / [Math]::Pow(10, $_)) -lt 1) { + return $prev + } + $prev = $_ + } + return $prev + } + + static [string] UnitByMeasure([int] $measure) { + $result = [string]::Empty + [MultipleUnit]::Known.GetEnumerator() | ForEach-Object { + if ($_.Value -eq $measure) { + $result = $_.Key + } + } + return $result + } +} diff --git a/Code/Out-Data.ps1 b/Code/Out-Data.ps1 new file mode 100644 index 00000000..14a7fb1c --- /dev/null +++ b/Code/Out-Data.ps1 @@ -0,0 +1,29 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +function Out-Iam { + Write-Host "MindMiner" -NoNewline -ForegroundColor Cyan + Write-Host " (C) 2017 by Oleg Samsonov aka Quake4" -ForegroundColor White + Write-Host "" +} + +function Out-Header { + Out-Iam + Write-Host "Help, information and other see on " -NoNewline + Write-Host "https://github.com/Quake4/MindMiner" -ForegroundColor Green + Write-Host "" + Write-Host " Configuration:" -ForegroundColor Yellow + Write-Host $Config +} + +function Out-Footer { + Write-Host "Information:" -ForegroundColor Yellow + Write-Host $Summary + <#Write-Host "Ctrl+Q" -NoNewline -ForegroundColor Yellow + Write-Host " - Exit, " -NoNewline + Write-Host "V" -NoNewline -ForegroundColor Yellow + Write-Host " - Verbose level"#> +} \ No newline at end of file diff --git a/Code/PoolInfo.ps1 b/Code/PoolInfo.ps1 new file mode 100644 index 00000000..9316f77e --- /dev/null +++ b/Code/PoolInfo.ps1 @@ -0,0 +1,32 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +class PoolInfo { + [string] $Name + [string] $Algorithm + [string] $Info + [decimal] $Profit + # [decimal] $StablePrice + # [decimal] $PriceFluctuation + [string] $Protocol + [string] $Host + [int] $Port + [string] $User + [string] $Password + + [string] PoolName() { + if ($this.Info) { + return "$($this.Name)-$($this.Info)" + } + else { + return $this.Name + } + } + + [string] ToString() { + return $this | Select-Object Name, Algorithm, Info, Profit, Protocol, Host, Port, User, Password + } +} \ No newline at end of file diff --git a/Code/StatInfo.ps1 b/Code/StatInfo.ps1 new file mode 100644 index 00000000..f29495fe --- /dev/null +++ b/Code/StatInfo.ps1 @@ -0,0 +1,161 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +. .\Code\HumanInterval.ps1 + +class StatInfo { + [decimal] $Value + [datetime] $Change + + StatInfo([decimal] $value) { + $this.Value = $value + $this.Change = (Get-Date).ToUniversalTime() + } + + StatInfo([PSCustomObject] $value) { + $value | Get-Member -MemberType NoteProperty | ForEach-Object { + $this."$($_.Name)" = $value."$($_.Name)" + } + } + + [decimal] SetValue([decimal] $value, [string] $interval) { + return $this.SetValue($value, $interval, 0.5) + } + + [decimal] SetValue([decimal] $value, [string] $interval, [decimal] $maxpercent) { + $update = (Get-Date).ToUniversalTime() + if (![string]::IsNullOrWhiteSpace($interval)) { + $span = [Math]::Min(($update - $this.Change).TotalSeconds / [HumanInterval]::Parse($interval).TotalSeconds, $maxpercent) + $this.Value = $this.Value - $span * $this.Value + $span * $value + } + else { + $this.Value = $value + } + $this.Change = $update + Remove-Variable span, update + return $this.Value + } +} + +class StatGroup { + [Collections.Generic.Dictionary[string, StatInfo]] $Values + [bool] $HasChanges + + StatGroup() { + $this.Values = [Collections.Generic.Dictionary[string, StatInfo]]::new() + $this.HasChanges = $true + } + + StatGroup([PSCustomObject] $value) { + $this.Values = [Collections.Generic.Dictionary[string, StatInfo]]::new() + $this.HasChanges = $false + $value | Get-Member -MemberType NoteProperty | ForEach-Object { + $this.Values.Add($_.Name, [StatInfo]::new($value."$($_.Name)")) + } + } + + [decimal] SetValue([decimal] $value) { + return $this.SetValue([string]::Empty, $value, [string]::Empty) + } + + [decimal] SetValue([string] $key, [decimal] $value) { + return $this.SetValue($key, $value, [string]::Empty) + } + + [decimal] SetValue([string] $key, [decimal] $value, [string] $interval) { + return $this.SetValue($key, $value, $interval, 0.5) + } + + [decimal] SetValue([string] $key, [decimal] $value, [string] $interval, [decimal] $maxpercent) { + $this.HasChanges = $true + if (!$this.Values.ContainsKey($key)) { + $this.Values.Add($key, [StatInfo]::new($value)) + return $value + } + else { + $item = $this.Values[$key] + return $item.SetValue($value, $interval, $maxpercent) + } + } + + [decimal] GetValue() { + return $this.GetValue([string]::Empty) + } + + [decimal] GetValue([string] $key) { + if (!$this.Values.ContainsKey($key)) { + return 0 + } + else { + return $this.Values[$key].Value + } + } +} + +class StatCache { + static hidden [string] $Dir = ".\Stats" + + hidden [Collections.Generic.Dictionary[string, StatGroup]] $Values + + StatCache() { + $this.Values = [Collections.Generic.Dictionary[string, StatGroup]]::new() + } + + [decimal] SetValue([string] $filename, [string] $key, [decimal] $value) { + return $this.SetValue($filename, $key, $value, [string]::Empty) + } + + [decimal] SetValue([string] $filename, [string] $key, [decimal] $value, [string] $interval) { + return $this.SetValue($filename, $key, $value, $interval, 0.5) + } + + [decimal] SetValue([string] $filename, [string] $key, [decimal] $value, [string] $interval, [decimal] $maxpercent) { + if (!$this.Values.ContainsKey($Filename)) { + $this.Values.Add($filename, [StatGroup]::new()) + } + return $this.Values[$filename].SetValue($key, $value, $interval, $maxpercent) + } + + [decimal] GetValue([string] $filename) { + return $this.GetValue($filename, [string]::Empty) + } + + [decimal] GetValue([string] $filename, [string] $key) { + if (!$this.Values.ContainsKey($Filename)) { + return 0 + } + return $this.Values[$filename].GetValue($key) + } + + [void] Write() { + [StatCache]::CheckDir() + # find all changed stats and save + $this.Values.Keys | Where-Object { $this.Values."$_".HasChanges -eq $true } | ForEach-Object { + $this.Values."$_".Values | ConvertTo-Json | Out-File -FilePath "$([StatCache]::Dir)\$_.txt" -Force + } + } + + static [StatCache] Read() { + [StatCache]::CheckDir() + $result = [StatCache]::new() + Get-ChildItem ([StatCache]::Dir) | ForEach-Object { + try { + $stat = $_ | Get-Content | ConvertFrom-Json + $gn = [IO.Path]::GetFileNameWithoutExtension($_) + $result.Values.Add($gn, [StatGroup]::new($stat)) + Remove-Variable gn, stat + } + catch { + Write-Host "Statistic read error: $_" -ForegroundColor Red + } + } + return $result + } + + static hidden [void] CheckDir() { + if (-not (Test-Path [StatCache]::Dir)) { New-Item ([StatCache]::Dir) -ItemType Directory -Force } + } +} \ No newline at end of file diff --git a/Code/SummaryInfo.ps1 b/Code/SummaryInfo.ps1 new file mode 100644 index 00000000..5d8fb190 --- /dev/null +++ b/Code/SummaryInfo.ps1 @@ -0,0 +1,41 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +class SummaryInfo { + [int] $Loop + [Diagnostics.Stopwatch] $TotalTime + [Diagnostics.Stopwatch] $LoopTime + [Diagnostics.Stopwatch] $FeeTime + [Diagnostics.Stopwatch] $RateTime + [timespan] $RateTimeout + + SummaryInfo([timespan] $minutes) { + $this.Loop = 1 + $this.TotalTime = [Diagnostics.Stopwatch]::new() + $this.LoopTime = [Diagnostics.Stopwatch]::new() + $this.FeeTime = [Diagnostics.Stopwatch]::new() + $this.RateTime = [Diagnostics.Stopwatch]::new() + $this.RateTimeout = $minutes + } + + [string] ToString() { + $elapsed = [SummaryInfo]::Elapsed($this.TotalTime.Elapsed) + $nl = [Environment]::NewLine + return "" + + (" Loop: {0,$($elapsed.Length):N0}" -f $this.Loop) + $nl + + (" Run Time: {0,$($elapsed.Length)}" -f $elapsed) + $nl + + (" Rate Time: {0,$($elapsed.Length)}" -f [SummaryInfo]::Elapsed($this.RateTimeout - $this.RateTime.Elapsed)) + $nl + + (" Fee Time: {0,$($elapsed.Length)} ({1:P1})" -f [SummaryInfo]::Elapsed($this.FeeTime.Elapsed), + ($this.FeeTime.Elapsed.TotalMilliseconds / $this.TotalTime.Elapsed.TotalMilliseconds)) + $nl + + (" Used RAM: {0,$($elapsed.Length):N1} Mb" -f ([GC]::GetTotalMemory(0)/1mb)) + } + + static [string] Elapsed([TimeSpan] $ts) { + $f = "{1:00}:{2:00}:{3:00}" + if ($ts.Days) { $f = "{0:0} " + $f } + return $f -f $ts.Days, $ts.Hours, $ts.Minutes, $ts.Seconds + } +} \ No newline at end of file diff --git a/Code/Update-Miner.ps1 b/Code/Update-Miner.ps1 new file mode 100644 index 00000000..5a2f5534 --- /dev/null +++ b/Code/Update-Miner.ps1 @@ -0,0 +1,30 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +function Update-Miner([Parameter(Mandatory)][string] $bin) { + Write-Host "Check for updates ..." -ForegroundColor Green + $latest = Get-UrlAsJson "https://api.github.com/repos/Quake4/MindMiner/releases/latest" + if ($latest -and [Config]::Version -ne $latest.tag_name) { + Write-Host "MindMiner $($latest.tag_name)" -NoNewline -ForegroundColor Cyan + Write-Host " update found. Downloading ..." -ForegroundColor Green + $file = @( + @{ Path="MM.New\LICENSE"; URI="$($latest.zipball_url)" } + ) + try { + Start-Job -Name "update" -ArgumentList $file -FilePath ".\Code\Downloader.ps1" -InitializationScript $BinScriptLocation | Out-Null + Wait-Job -Name "update" | Out-Null + Remove-Job -Name "update" + } + catch { + Write-Host "Error downloading update archive: $_." -ForegroundColor Red + } + Remove-Variable file + $true + } + else { + $false + } +} \ No newline at end of file diff --git a/Code/WebRequest.ps1 b/Code/WebRequest.ps1 new file mode 100644 index 00000000..0c23413a --- /dev/null +++ b/Code/WebRequest.ps1 @@ -0,0 +1,75 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +$WebReqTryCount = 3 + +function GetUrl { + param( + [Parameter(Mandatory = $true)] + [String]$url, + [Parameter(Mandatory = $false)] + [String]$filename + ) + + $result = $null + + 1..$WebReqTryCount | ForEach-Object { + if (!$result) { + try { + if ($filename) { + $req = Invoke-WebRequest $url -OutFile $filename -PassThru -TimeoutSec 15 + $result = $true + } + else { + $req = Invoke-WebRequest $url -TimeoutSec 15 + $result = $req | ConvertFrom-Json + } + } + catch { + try { + if ($filename) { + $req = Invoke-WebRequest $url -OutFile $filename -PassThru -TimeoutSec 15 -UseBasicParsing + $result = $true + } + else { + $req = Invoke-WebRequest $url -TimeoutSec 15 -UseBasicParsing + $result = $req | ConvertFrom-Json + } + } + catch { + $result = $null + } + } + finally { + if ($req -is [IDisposable]) { + $req.Dispose() + } + } + } + } + + $result +} + +function Get-UrlAsJson { + param( + [Parameter(Mandatory = $true)] + [String]$url + ) + + GetUrl $url +} + +function Get-UrlAsFile { + param( + [Parameter(Mandatory = $true)] + [String]$url, + [Parameter(Mandatory = $true)] + [String]$filename + ) + + GetUrl $url $filename +} \ No newline at end of file diff --git a/MindMiner.ps1 b/MindMiner.ps1 new file mode 100644 index 00000000..72a2f83c --- /dev/null +++ b/MindMiner.ps1 @@ -0,0 +1,334 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +. .\Code\Out-Data.ps1 + +Out-Iam +Write-Host "Loading ..." -ForegroundColor Green + +. .\Code\Include.ps1 + +# ctrl+c hook +[Console]::TreatControlCAsInput = $true + +$BinLocation = [IO.Path]::Combine($(Get-Location), [Config]::BinLocation) +New-Item $BinLocation -ItemType Directory -Force | Out-Null +$BinScriptLocation = [scriptblock]::Create("Set-Location('$BinLocation')") +$DownloadJob = $null + +# download prerequisites +Get-Prerequisites ([Config]::BinLocation) + +# read and validate config +$Config = Get-Config + +if (!$Config) { exit } + +Clear-Host +Out-Header + +$ActiveMiners = [Collections.Generic.Dictionary[string, MinerProcess]]::new() +[SummaryInfo] $Summary = [SummaryInfo]::new([Config]::RateTimeout) +[StatCache] $Statistics = [StatCache]::Read() +$Summary.TotalTime.Start() + +# FastLoop - variable for benchmark or miner errors - very fast switching to other miner - without ask pools and miners +[bool] $FastLoop = $false +# exit - var for exit +[bool] $exit = $false +# main loop +while ($true) +{ + if ($Summary.RateTime.IsRunning -eq $false -or $Summary.RateTime.Elapsed.TotalSeconds -ge [Config]::RateTimeout.TotalSeconds) { + # Get-RateInfo + $exit = Update-Miner ([Config]::BinLocation) + if ($exit -eq $true) { + $FastLoop = $true + } + $Summary.RateTime.Reset() + $Summary.RateTime.Start() + } + + if (!$FastLoop) { + # read algorithm mapping + $AllAlgos = <#[BaseConfig]::ReadOrCreate("Algo" + [BaseConfig]::Filename,#> @{ + # how to map algorithms + Mapping = [ordered]@{ + "blakecoin" = "Blake" + "blake256r8" = "Blake" + "daggerhashimoto" = "Ethash" + "lyra2rev2" = "Lyra2re2" + "lyra2r2" = "Lyra2re2" + "lyra2v2" = "Lyra2re2" + "m7m" = "M7M" + "neoscrypt" = "NeoScrypt" + "sib" = "X11Gost" + "x11gost" = "X11Gost" + "x11evo" = "X11Evo" + "phi1612" = "Phi" + "timetravel10" = "Bitcore" + "x13sm3" = "Hsr" + "myriad-groestl" = "MyrGr" + "myriadgroestl" = "MyrGr" + "myr-gr" = "MyrGr" + "jackpot" = "JHA" + } + # disable asic algorithms + Disabled = @("sha256", "scrypt", "x11", "x13", "x14", "x15", "quark", "qubit") + } #) + + Write-Host "Pool(s) request ..." -ForegroundColor Green + $AllPools = Get-ChildItem "Pools" | Where-Object Extension -eq ".ps1" | ForEach-Object { + Invoke-Expression "Pools\$($_.Name)" + } | Where-Object { $_ -is [PoolInfo] -and $_.Profit -gt 0 } + + # find more profitable algo from all pools + $AllPools = $AllPools | Select-Object Algorithm -Unique | ForEach-Object { + $max = 0; $each = $null + $AllPools | Where-Object Algorithm -eq $_.Algorithm | ForEach-Object { + if ($max -lt $_.Profit) { $max = $_.Profit; $each = $_ } + } + if ($max -gt 0) { $each } + Remove-Variable max + } + + # check pool exists + if (!$AllPools -or $AllPools.Length -eq 0) { + Write-Host "No Pools!" -ForegroundColor Red + Start-Sleep $Config.CheckTimeout + continue + } + + Write-Host "Miners request ..." -ForegroundColor Green + $AllMiners = Get-ChildItem "Miners" | Where-Object Extension -eq ".ps1" | ForEach-Object { + Invoke-Expression "Miners\$($_.Name)" + } + + # filter by exists hardware + $AllMiners = $AllMiners | Where-Object { [array]::IndexOf([Config]::ActiveTypes, ($_.Type -as [eMinerType])) -ge 0 } + + # download miner + if (!(Get-Job -State Running) -and $DownloadJob) { + Remove-Job -Name "Download" + $DownloadJob = $null + } + $DownloadMiners = $AllMiners | Where-Object { !$_.Exists([Config]::BinLocation) } | Select-Object Path, URI -Unique | ForEach-Object { @{ Path = $_.Path; URI = $_.URI } } + if ($DownloadMiners.Length -gt 0) { + Write-Host "Download $($DownloadMiners.Length) miner(s) ... " -ForegroundColor Green + if (!(Get-Job -State Running)) { + Start-Job -Name "Download" -ArgumentList $DownloadMiners -FilePath ".\Code\Downloader.ps1" -InitializationScript $BinScriptLocation | Out-Null + $DownloadJob = $true + } + } + + # check exists miners + $AllMiners = $AllMiners | Where-Object { $_.Exists([Config]::BinLocation) } + + if ($AllMiners.Length -eq 0) { + Write-Host "No Miners!" -ForegroundColor Red + Start-Sleep $Config.CheckTimeout + continue + } + + # save speed active miners + $ActiveMiners.Values | Where-Object { $_.State -eq [eState]::Running -and $_.Action -eq [eAction]::Normal } | ForEach-Object { + $speed = $_.GetSpeed() + if ($speed -gt 0) { + $speed = $Statistics.SetValue($_.Miner.GetFilename(), $_.Miner.GetKey(), $speed, $Config.AverageHashSpeed, 0.25) + } + elseif ($speed -eq 0 -and $_.CurrentTime.Elapsed.TotalSeconds -ge $Config.LoopTimeout) { + # no hasrate stop miner and move to nohashe state while not ended + $_.Stop() + } + } + } + + # stop benchmark by condition: timeout reached and has result or timeout more 5 and no result + $ActiveMiners.Values | Where-Object { $_.State -eq [eState]::Running -and $_.Action -eq [eAction]::Benchmark } | ForEach-Object { + $speed = $_.GetSpeed() + if (($_.CurrentTime.Elapsed.TotalSeconds -ge $_.Miner.BenchmarkSeconds -and $speed -gt 0) -or + ($_.CurrentTime.Elapsed.TotalSeconds -ge ($_.Miner.BenchmarkSeconds * 2) -and $speed -eq 0)) { + $_.Stop() + if ($speed -eq 0) { + $speed = $Statistics.SetValue($_.Miner.GetFilename(), $_.Miner.GetKey(), -1) + } + else { + $speed = $Statistics.SetValue($_.Miner.GetFilename(), $_.Miner.GetKey(), $speed, $Config.AverageHashSpeed) + } + } + } + + # read speed and price of proposed miners + $AllMiners = $AllMiners | ForEach-Object { + if (!$FastLoop) { + $speed = $Statistics.GetValue($_.GetFilename(), $_.GetKey()) + # filter unused + if ($speed -ge 0) { + $price = (Get-Pool $_.Algorithm).Profit + [MinerProfitInfo]::new($_, $speed, $price) + Remove-Variable price + } + } + elseif (!$exit) { + $speed = $Statistics.GetValue($_.Miner.GetFilename(), $_.Miner.GetKey()) + # filter unused + if ($speed -ge 0) { + $_.SetSpeed($speed) + $_ + } + } + } + + if (!$exit) { + Remove-Variable speed + + # look for run or stop miner + [Config]::ActiveTypes | ForEach-Object { + $type = $_ + + $allMinersByType = $AllMiners | Where-Object { $_.Miner.Type -eq $type } + $activeMinersByType = $ActiveMiners.Values | Where-Object { $_.Miner.Type -eq $type } + + # run for bencmark - exclude failed + $run = $allMinersByType | Where-Object { $Statistics.GetValue($_.Miner.GetFilename(), $_.Miner.GetKey()) -eq 0 } | Select-Object -First 1 + + # nothing benchmarking - get most profitable - exclude failed + if (!$run) { + $miner = $null + $allMinersByType | Where-Object { $_.Profit -gt 0 } | ForEach-Object { + if ($run -eq $null -or $_.Profit -gt $run.Profit) { + # skip failed or nohash miners + $miner = $_ + if (($activeMinersByType | Where-Object { $_.State -eq [eState]::NoHash -or $_.State -eq [eState]::Failed } | + Where-Object { $miner.Miner.GetUniqueKey() -eq $_.Miner.GetUniqueKey() }) -eq $null) { + $run = $_ + } + } + } + Remove-Variable miner + } + + if ($run) { + $miner = $run.Miner + if (!$ActiveMiners.ContainsKey($miner.GetUniqueKey())) { + $ActiveMiners.Add($miner.GetUniqueKey(), [MinerProcess]::new($miner, $Config)) + } + #stop not choosen + $activeMinersByType | Where-Object { $miner.GetUniqueKey() -ne $_.Miner.GetUniqueKey() } | ForEach-Object { + $_.Stop() + } + # run choosen + $mi = $ActiveMiners[$miner.GetUniqueKey()] + if ($mi.State -eq $null -or $mi.State -ne [eState]::Running) { + if ($Statistics.GetValue($mi.Miner.GetFilename(), $mi.Miner.GetKey()) -eq 0) { + $mi.Benchmark() + } + else { + $mi.Start() + } + $FastLoop = $false + } + Remove-Variable mi, miner + } + Remove-Variable run, activeMinersByType, allMinersByType, type + } + } + + $Statistics.Write() + + if (!$FastLoop) { + $Summary.LoopTime.Reset() + $Summary.LoopTime.Start() + } + + Clear-Host + Out-Header + + # $AllPools | Select-Object -Property * -ExcludeProperty @("StablePrice", "PriceFluctuation") | Format-Table | Out-Host + $AllMiners | Sort-Object @{ Expression = { $_.Miner.Type } }, + @{Expression = { $_.Profit }; Descending = $True}, + @{Expression = { $_.Miner.Algorithm } }, + @{Expression = { $_.Miner.ExtraArgs } } | + Format-Table @{ Label="Miner"; Expression = { $_.Miner.Name } }, + @{ Label="Algorithm"; Expression = { $_.Miner.Algorithm } }, + @{ Label="Speed, H/s"; Expression = { if ($_.Speed -eq 0) { "Testing" } else { [MultipleUnit]::ToString($_.Speed) } }; Alignment="Right" }, + @{ Label="mBTC/Day"; Expression = { if ($_.Profit -eq 0) { "$($_.Miner.BenchmarkSeconds) sec" } else { $_.Profit * 1000 } }; FormatString = "N5" }, + @{ Label="BTC/GH/Day"; Expression = { $_.Price * 1000000000 }; FormatString = "N8" }, + @{ Label="Pool"; Expression = { $_.Miner.Pool } }, + @{ Label="ExtraArgs"; Expression = { $_.Miner.ExtraArgs } } -GroupBy @{ Label="Type"; Expression = { $_.Miner.Type } } | Out-Host + #@{ Label="Arguments"; Expression = { $_.Miner.Arguments } } + + # display active miners + $ActiveMiners.Values | Sort-Object { [int]($_.State -as [eState]), [SummaryInfo]::Elapsed($_.TotalTime.Elapsed) } | + Format-Table @{ Label="Type"; Expression = { $_.Miner.Type } }, + @{ Label="Algorithm"; Expression = { $_.Miner.Algorithm } }, + @{ Label="Speed, H/s"; Expression = { $speed = $_.GetSpeed(); if ($speed -eq 0) { "Unknown" } else { [MultipleUnit]::ToString($speed) } }; Alignment="Right"; }, + @{ Label="Run Time"; Expression = { [SummaryInfo]::Elapsed($_.TotalTime.Elapsed) }; Alignment = "Right" }, + @{ Label="Run"; Expression = { if ($_.Run -eq 1) { "Once" } else { $_.Run } } }, + @{ Label="Command"; Expression = { $_.Miner.GetCommandLine() } } -GroupBy State -Wrap | Out-Host + + Out-Footer + + do { + if ($FastLoop -eq $false) { + Start-Sleep -Seconds $Config.CheckTimeout + } + $FastLoop = $false + +<# while ([Console]::KeyAvailable -eq $true) { + [ConsoleKeyInfo] $key = [Console]::ReadKey($true) + if ($key.Key -eq [ConsoleKey]::V) { + Write-Host "Verbose level changed" -ForegroundColor Green + } + elseif ($key.Modifiers -match [ConsoleModifiers]::Alt -or $key.Modifiers -match [ConsoleModifiers]::Control) { + if ($key.Key -eq [ConsoleKey]::C -or $key.Key -eq [ConsoleKey]::E -or $key.Key -eq [ConsoleKey]::Q -or $key.Key -eq [ConsoleKey]::X) { + $exit = $true + } + } + } +#> + # if needed - exit + if ($exit -eq $true) { + Write-Host "Exiting ..." -ForegroundColor Green + $ActiveMiners.Values | Where-Object { $_.State -eq [eState]::Running } | ForEach-Object { + $_.Stop() + } + exit + } + + # read speed while run main loop timeout + if ($ActiveMiners.Values -and $ActiveMiners.Values.Length -gt 0) { + Get-Speed $ActiveMiners.Values + } + # check miners work propertly + $ActiveMiners.Values | Where-Object { $_.State -eq [eState]::Running -or $_.State -eq [eState]::NoHash } | ForEach-Object { + if ($_.Check() -eq [eState]::Failed) { + # miner failed - run next + if ($_.Action -eq [eAction]::Benchmark) { + $speed = $Statistics.SetValue($_.Miner.GetFilename(), $_.Miner.GetKey(), -1) + Remove-Variable speed + } + $FastLoop = $true + } + # benchmark time reached - exit from loop + elseif ($_.Action -eq [eAction]::Benchmark -and $_.CurrentTime.Elapsed.TotalSeconds -ge $_.Miner.BenchmarkSeconds -and $_.GetSpeed() -gt 0) { + $FastLoop = $true + } + } + } while ($Config.LoopTimeout -gt $Summary.LoopTime.Elapsed.TotalSeconds -and !$FastLoop) + + # if timeout reached - normal loop + if ($Config.LoopTimeout -le $Summary.LoopTime.Elapsed.TotalSeconds) { + $FastLoop = $false + } + + if (!$FastLoop) { + Remove-Variable AllPools, AllMiners + [GC]::Collect() + } + + $Summary.Loop++ +} \ No newline at end of file diff --git a/Miners/EWBF-034.ps1 b/Miners/EWBF-034.ps1 new file mode 100644 index 00000000..cd80e729 --- /dev/null +++ b/Miners/EWBF-034.ps1 @@ -0,0 +1,49 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +. .\Code\Include.ps1 + +if (![Config]::Is64Bit) { exit } + +$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName + +$Cfg = [BaseConfig]::ReadOrCreate([IO.Path]::Combine($PSScriptRoot, $Name + [BaseConfig]::Filename), @{ + Enabled = $true + BenchmarkSeconds = 60 + Algorithms = @( + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "equihash" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "equihash"; ExtraArgs = "--solver 0" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "equihash"; ExtraArgs = "--solver 1" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "equihash"; ExtraArgs = "--solver 2" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "equihash"; ExtraArgs = "--solver 3" } +)}) + +if (!$Cfg.Enabled) { return } + +$Cfg.Algorithms | ForEach-Object { + if ($_.Enabled) { + $Algo = Get-Algo($_.Algorithm) + if ($Algo) { + # find pool by algorithm + $Pool = Get-Pool($Algo) + if ($Pool) { + [MinerInfo]@{ + Pool = $Pool.PoolName() + Name = $Name + Algorithm = $Algo + Type = [eMinerType]::nVidia + API = "ewbf" + URI = "https://github.com/nanopool/ewbf-miner/releases/download/v0.3.4b/Zec.miner.0.3.4b.zip" + Path = "EWBF\miner.exe" + ExtraArgs = $_.ExtraArgs + Arguments = "--api --server $($Pool.Host) --user $($Pool.User) --pass $($Pool.Password) --port $($Pool.Port) --eexit 1 $($_.ExtraArgs)" + Port = 42000 + BenchmarkSeconds = if ($_.BenchmarkSeconds) { $_.BenchmarkSeconds } else { $Cfg.BenchmarkSeconds } + } + } + } + } +} \ No newline at end of file diff --git a/Miners/ccminer-alexis-01.ps1 b/Miners/ccminer-alexis-01.ps1 new file mode 100644 index 00000000..76c7f9a7 --- /dev/null +++ b/Miners/ccminer-alexis-01.ps1 @@ -0,0 +1,61 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +. .\Code\Include.ps1 + +if (![Config]::Is64Bit) { exit } + +$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName + +$Cfg = [BaseConfig]::ReadOrCreate([IO.Path]::Combine($PSScriptRoot, $Name + [BaseConfig]::Filename), @{ + Enabled = $true + BenchmarkSeconds = 60 + Algorithms = @( + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "blake2s" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "blakecoin" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "keccak" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "lbry" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "lyra2v2"; BenchmarkSeconds = 100 } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "myr-gr" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "neoscrypt" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "neoscrypt"; ExtraArgs = "-i 15" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "nist5" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "sib" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "sib"; ExtraArgs = "-i 21" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "skein" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "c11" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "c11"; ExtraArgs = "-i 21" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "x17" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "x17"; ExtraArgs = "-i 21" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "veltor" } +)}) + +if (!$Cfg.Enabled) { return } + +$Cfg.Algorithms | ForEach-Object { + if ($_.Enabled) { + $Algo = Get-Algo($_.Algorithm) + if ($Algo) { + # find pool by algorithm + $Pool = Get-Pool($Algo) + if ($Pool) { + [MinerInfo]@{ + Pool = $Pool.PoolName() + Name = $Name + Algorithm = $Algo + Type = [eMinerType]::nVidia + API = "ccminer" + URI = "https://github.com/nemosminer/ccminer-Alexis78/releases/download/ccminer-alexis78/ccminer-alexis78-ms2013-cuda7.5.7z" + Path = "ccminer-alexis-01\ccminer.exe" + ExtraArgs = $_.ExtraArgs + Arguments = "-a $($_.Algorithm) -o stratum+tcp://$($Pool.Host):$($Pool.Port) -u $($Pool.User) -p $($Pool.Password) $($_.ExtraArgs)" + Port = 4068 + BenchmarkSeconds = if ($_.BenchmarkSeconds) { $_.BenchmarkSeconds } else { $Cfg.BenchmarkSeconds } + } + } + } + } +} diff --git a/Miners/ccminer-djm34-021.ps1 b/Miners/ccminer-djm34-021.ps1 new file mode 100644 index 00000000..20b110bb --- /dev/null +++ b/Miners/ccminer-djm34-021.ps1 @@ -0,0 +1,52 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +. .\Code\Include.ps1 + +$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName + +$Cfg = [BaseConfig]::ReadOrCreate([IO.Path]::Combine($PSScriptRoot, $Name + [BaseConfig]::Filename), @{ + Enabled = $true + Algorithms = @( + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "lyra2z"; BenchmarkSeconds = 120 } + ) +}) + +if (!$Cfg.Enabled) { return } + +if ([Config]::Is64Bit -eq $true) { + $url = "https://github.com/djm34/ccminer-msvc2015/releases/download/v0.2.1/ccminer_cuda9.exe" + $file = "ccminer_cuda9.exe" +} +else { + $url = "https://github.com/djm34/ccminer-msvc2015/releases/download/v0.2.1/ccminer.exe" + $file = "ccminer.exe" +} + +$Cfg.Algorithms | ForEach-Object { + if ($_.Enabled) { + $Algo = Get-Algo($_.Algorithm) + if ($Algo) { + # find pool by algorithm + $Pool = Get-Pool($Algo) + if ($Pool) { + [MinerInfo]@{ + Pool = $Pool.PoolName() + Name = $Name + Algorithm = $Algo + Type = [eMinerType]::nVidia + API = "ccminer" + URI = $url + Path = "ccminer-djm34-021\$file" + ExtraArgs = $_.ExtraArgs + Arguments = "-a $($_.Algorithm) -o stratum+tcp://$($Pool.Host):$($Pool.Port) -u $($Pool.User) -p $($Pool.Password) -R 5 $($_.ExtraArgs)" + Port = 4068 + BenchmarkSeconds = if ($_.BenchmarkSeconds) { $_.BenchmarkSeconds } else { $Cfg.BenchmarkSeconds } + } + } + } + } +} diff --git a/Miners/ccminer-klaust-815.ps1 b/Miners/ccminer-klaust-815.ps1 new file mode 100644 index 00000000..a06ce562 --- /dev/null +++ b/Miners/ccminer-klaust-815.ps1 @@ -0,0 +1,59 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +. .\Code\Include.ps1 + +if (![Config]::Is64Bit) { exit } + +$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName + +$Cfg = [BaseConfig]::ReadOrCreate([IO.Path]::Combine($PSScriptRoot, $Name + [BaseConfig]::Filename), @{ + Enabled = $true + BenchmarkSeconds = 60 + Algorithms = @( + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "blakecoin" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "c11" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "groestl" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "jackpot" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "keccak" } + # not validate on cpu [AlgoInfoEx]@{ Enabled = $true; Algorithm = "lyra2v2" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "myr-gr" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "neoscrypt" } # auto + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "neoscrypt"; ExtraArgs = "-i 15" } # GTX1060/3Gb + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "neoscrypt"; ExtraArgs = "-i 16" } # GTX1060/6Gb + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "neoscrypt"; ExtraArgs = "-i 17" } # GTX1070 + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "neoscrypt"; ExtraArgs = "-i 18" } # GTX1080 + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "neoscrypt"; ExtraArgs = "-i 19" } # GTX1080Ti + # not work [AlgoInfoEx]@{ Enabled = $true; Algorithm = "nist5" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "skein" } +)}) + +if (!$Cfg.Enabled) { return } + +$Cfg.Algorithms | ForEach-Object { + if ($_.Enabled) { + $Algo = Get-Algo($_.Algorithm) + if ($Algo) { + # find pool by algorithm + $Pool = Get-Pool($Algo) + if ($Pool) { + [MinerInfo]@{ + Pool = $Pool.PoolName() + Name = $Name + Algorithm = $Algo + Type = [eMinerType]::nVidia + API = "ccminer" + URI = "https://github.com/KlausT/ccminer/releases/download/8.15/ccminer-815-cuda9-x64.zip" + Path = "ccminer-klaust-815\ccminer.exe" + ExtraArgs = $_.ExtraArgs + Arguments = "-a $($_.Algorithm) -o stratum+tcp://$($Pool.Host):$($Pool.Port) -u $($Pool.User) -p $($Pool.Password) $($_.ExtraArgs)" + Port = 4068 + BenchmarkSeconds = if ($_.BenchmarkSeconds) { $_.BenchmarkSeconds } else { $Cfg.BenchmarkSeconds } + } + } + } + } +} diff --git a/Miners/ccminer-krnlx-xevan-01.ps1 b/Miners/ccminer-krnlx-xevan-01.ps1 new file mode 100644 index 00000000..55882da9 --- /dev/null +++ b/Miners/ccminer-krnlx-xevan-01.ps1 @@ -0,0 +1,52 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +. .\Code\Include.ps1 + +$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName + +$Cfg = [BaseConfig]::ReadOrCreate([IO.Path]::Combine($PSScriptRoot, $Name + [BaseConfig]::Filename), @{ + Enabled = $true + Algorithms = @( + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "xevan"; BenchmarkSeconds = 60 } + # [AlgoInfoEx]@{ Enabled = $true; Algorithm = "x17"; ExtraArgs = "-i 21" } +)}) + +if (!$Cfg.Enabled) { return } + +if ([Config]::Is64Bit -eq $true) { + $url = "https://github.com/krnlx/ccminer-xevan/releases/download/0.1/ccminer.exe" + $file = "ccminer.exe" +} +else { + $url = "https://github.com/krnlx/ccminer-xevan/releases/download/0.1/ccminer_x86.exe" + $file = "ccminer_x86.exe" +} + +$Cfg.Algorithms | ForEach-Object { + if ($_.Enabled) { + $Algo = Get-Algo($_.Algorithm) + if ($Algo) { + # find pool by algorithm + $Pool = Get-Pool($Algo) + if ($Pool) { + [MinerInfo]@{ + Pool = $Pool.PoolName() + Name = $Name + Algorithm = $Algo + Type = [eMinerType]::nVidia + API = "ccminer" + URI = $url + Path = "ccminer-krnlx-xevan-01\$file" + ExtraArgs = $_.ExtraArgs + Arguments = "-a $($_.Algorithm) -o stratum+tcp://$($Pool.Host):$($Pool.Port) -u $($Pool.User) -p $($Pool.Password) -R 5 $($_.ExtraArgs)" + Port = 4068 + BenchmarkSeconds = if ($_.BenchmarkSeconds) { $_.BenchmarkSeconds } else { $Cfg.BenchmarkSeconds } + } + } + } + } +} diff --git a/Miners/ccminer-nanashi-mr2.ps1 b/Miners/ccminer-nanashi-mr2.ps1 new file mode 100644 index 00000000..e54b328a --- /dev/null +++ b/Miners/ccminer-nanashi-mr2.ps1 @@ -0,0 +1,44 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +. .\Code\Include.ps1 + +if (![Config]::Is64Bit) { exit } + +$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName + +$Cfg = [BaseConfig]::ReadOrCreate([IO.Path]::Combine($PSScriptRoot, $Name + [BaseConfig]::Filename), @{ + Enabled = $true + Algorithms = @( + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "lyra2v2"; BenchmarkSeconds = 100 } +)}) + +if (!$Cfg.Enabled) { return } + +$Cfg.Algorithms | ForEach-Object { + if ($_.Enabled) { + $Algo = Get-Algo($_.Algorithm) + if ($Algo) { + # find pool by algorithm + $Pool = Get-Pool($Algo) + if ($Pool) { + [MinerInfo]@{ + Pool = $Pool.PoolName() + Name = $Name + Algorithm = $Algo + Type = [eMinerType]::nVidia + API = "ccminer" + URI = "https://github.com/Nanashi-Meiyo-Meijin/ccminer/releases/download/v2.2-mod-r2/2.2-mod-r2-CUDA9.binary.zip" + Path = "ccminer-nanashi-mr2\ccminer.exe" + ExtraArgs = $_.ExtraArgs + Arguments = "-a $($_.Algorithm) -o stratum+tcp://$($Pool.Host):$($Pool.Port) -u $($Pool.User) -p $($Pool.Password) $($_.ExtraArgs)" + Port = 4068 + BenchmarkSeconds = if ($_.BenchmarkSeconds) { $_.BenchmarkSeconds } else { $Cfg.BenchmarkSeconds } + } + } + } + } +} diff --git a/Miners/ccminer-tpruvot-223.ps1 b/Miners/ccminer-tpruvot-223.ps1 new file mode 100644 index 00000000..e308babc --- /dev/null +++ b/Miners/ccminer-tpruvot-223.ps1 @@ -0,0 +1,80 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +. .\Code\Include.ps1 + +$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName + +$Cfg = [BaseConfig]::ReadOrCreate([IO.Path]::Combine($PSScriptRoot, $Name + [BaseConfig]::Filename), @{ + Enabled = $true + BenchmarkSeconds = 60 + Algorithms = @( + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "bitcore" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "blake2s" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "blakecoin" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "cryptonight" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "c11" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "decred" } + # not work [AlgoInfoEx]@{ Enabled = $true; Algorithm = "equihash" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "groestl" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "hmq1725" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "jackpot" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "keccak" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "lbry" } + # not work [AlgoInfoEx]@{ Enabled = $true; Algorithm = "lyra2v2" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "lyra2z" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "myr-gr" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "neoscrypt" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "nist5" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "phi" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "polytimos" } + # not work [AlgoInfoEx]@{ Enabled = $true; Algorithm = "sia" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "sib" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "skein" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "skunk" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "timetravel" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "tribus" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "veltor" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "x11evo" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "x17" } + # [AlgoInfoEx]@{ Enabled = $true; Algorithm = "x17"; ExtraArgs = "-i 21" } +)}) + +if (!$Cfg.Enabled) { return } + +if ([Config]::Is64Bit -eq $true) { + $url = "https://github.com/tpruvot/ccminer/releases/download/2.2.3-tpruvot/ccminer-x64-2.2.3-cuda9.7z" + $file = "ccminer-x64.exe" +} +else { + $url = "https://github.com/tpruvot/ccminer/releases/download/2.2.3-tpruvot/ccminer-x86-2.2.3-cuda9.7z" + $file = "ccminer.exe" +} + +$Cfg.Algorithms | ForEach-Object { + if ($_.Enabled) { + $Algo = Get-Algo($_.Algorithm) + if ($Algo) { + # find pool by algorithm + $Pool = Get-Pool($Algo) + if ($Pool) { + [MinerInfo]@{ + Pool = $Pool.PoolName() + Name = $Name + Algorithm = $Algo + Type = [eMinerType]::nVidia + API = "ccminer" + URI = $url + Path = "ccminer-tpruvot-223\$file" + ExtraArgs = $_.ExtraArgs + Arguments = "-a $($_.Algorithm) -o stratum+tcp://$($Pool.Host):$($Pool.Port) -u $($Pool.User) -p $($Pool.Password) -R 5 $($_.ExtraArgs)" + Port = 4068 + BenchmarkSeconds = if ($_.BenchmarkSeconds) { $_.BenchmarkSeconds } else { $Cfg.BenchmarkSeconds } + } + } + } + } +} diff --git a/Miners/cpuminer-opt-374.ps1 b/Miners/cpuminer-opt-374.ps1 new file mode 100644 index 00000000..08019a65 --- /dev/null +++ b/Miners/cpuminer-opt-374.ps1 @@ -0,0 +1,116 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +. .\Code\Include.ps1 + +if (![Config]::Is64Bit) { exit } + +$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName + +$Cfg = [BaseConfig]::ReadOrCreate([IO.Path]::Combine($PSScriptRoot, $Name + [BaseConfig]::Filename), @{ + Enabled = $true + BenchmarkSeconds = 30 + Algorithms = @( + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "axiom" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "blakecoin" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "blake2s" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "c11" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "cryptonight" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "decred" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "groestl" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "hmq1725" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "hodl" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "jha" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "keccak" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "lbry" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "lyra2re" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "lyra2rev2" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "lyra2z" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "m7m" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "myr-gr" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "neoscrypt" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "nist5" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "phi1612" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "polytimos" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "quark" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "qubit" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "skein" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "skunk" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "timetravel" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "timetravel10" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "tribus" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "veltor" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "x11evo" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "x11gost" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "x13sm3" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "x17" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "xevan" } + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "yescrypt" } + #[AlgoInfoEx]@{ Enabled = $true; Algorithm = "sib"; ExtraArgs = "-i 21" } +)}) + +if (!$Cfg.Enabled) { return } + +# choose version +$miners = [Collections.Generic.Dictionary[string, string[]]]::new() +$miners.Add("cpuminer-sse2.exe", @("SSE2")) +$miners.Add("cpuminer-sse42.exe", @("SSE42")) +$miners.Add("cpuminer-aes-sse42.exe", @("AES", "SSE42")) +$miners.Add("cpuminer-aes-avx.exe", @("AES", "AVX")) +$miners.Add("cpuminer-aes-avx2.exe", @("AES", "AVX2")) + +$bestminer = $null +$miners.GetEnumerator() | ForEach-Object { + $has = $true + $_.Value | ForEach-Object { + if (![Config]::CPUFeatures.Contains($_)) { + $has = $false + } + } + if ($has) { + $bestminer = $_.Key + } +} + +$Cfg.Algorithms | ForEach-Object { + if ($_.Enabled) { + $Algo = Get-Algo($_.Algorithm) + if ($Algo) { + # find pool by algorithm + $Pool = Get-Pool($Algo) + if ($Pool) { + [MinerInfo]@{ + Pool = $Pool.PoolName() + Name = $Name + Algorithm = $Algo + Type = [eMinerType]::CPU + API = "cpuminer" + URI = "https://github.com/Quake4/MindMinerPrerequisites/raw/master/CPU/cpuminer-opt/cpuminer-opt-3.7.4.zip" + Path = "cpuminer-opt-374\$bestminer" + ExtraArgs = $_.ExtraArgs + Arguments = "-a $($_.Algorithm) -o stratum+tcp://$($Pool.Host):$($Pool.Port) -u $($Pool.User) -p $($Pool.Password) -b 4048 --cpu-priority 1 $($_.ExtraArgs)" + Port = 4048 + BenchmarkSeconds = if ($_.BenchmarkSeconds) { $_.BenchmarkSeconds } else { $Cfg.BenchmarkSeconds } + } + if ($bestminer -eq "cpuminer-aes-avx2.exe") { + [MinerInfo]@{ + Pool = $Pool.PoolName() + Name = $Name + Algorithm = $Algo + Type = [eMinerType]::CPU + API = "cpuminer" + URI = "https://github.com/Quake4/MindMinerPrerequisites/raw/master/CPU/cpuminer-opt/cpuminer-opt-3.7.4.zip" + Path = "cpuminer-opt-374\cpuminer-4way.exe" + ExtraArgs = "4way $($_.ExtraArgs)".Trim() + Arguments = "-a $($_.Algorithm) -o stratum+tcp://$($Pool.Host):$($Pool.Port) -u $($Pool.User) -p $($Pool.Password) -b 4048 --cpu-priority 1 $($_.ExtraArgs)" + Port = 4048 + BenchmarkSeconds = if ($_.BenchmarkSeconds) { $_.BenchmarkSeconds } else { $Cfg.BenchmarkSeconds } + } + } + } + } + } +} diff --git a/Miners/cpuminer-plys-100.ps1 b/Miners/cpuminer-plys-100.ps1 new file mode 100644 index 00000000..f8d168db --- /dev/null +++ b/Miners/cpuminer-plys-100.ps1 @@ -0,0 +1,45 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +. .\Code\Include.ps1 + +if (![Config]::Is64Bit) { exit } + +$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName + +$Cfg = [BaseConfig]::ReadOrCreate([IO.Path]::Combine($PSScriptRoot, $Name + [BaseConfig]::Filename), @{ + Enabled = $false + BenchmarkSeconds = 20 + Algorithms = @( + [AlgoInfoEx]@{ Enabled = $true; Algorithm = "polytimos" } +)}) + +if (!$Cfg.Enabled) { return } + +$Cfg.Algorithms | ForEach-Object { + if ($_.Enabled) { + $Algo = Get-Algo($_.Algorithm) + if ($Algo) { + # find pool by algorithm + $Pool = Get-Pool($Algo) + if ($Pool) { + [MinerInfo]@{ + Pool = $Pool.PoolName() + Name = $Name + Algorithm = $Algo + Type = [eMinerType]::CPU + API = "cpuminer" + URI = "https://github.com/polytimos/release/raw/master/cpuminer-windows.zip" + Path = "cpuminer-plys-100\cpuminer.exe" + ExtraArgs = $_.ExtraArgs + Arguments = "-a $($_.Algorithm) -o stratum+tcp://$($Pool.Host):$($Pool.Port) -u $($Pool.User) -p $($Pool.Password) -b 4049 --cpu-priority 1 $($_.ExtraArgs)" + Port = 4049 + BenchmarkSeconds = if ($_.BenchmarkSeconds) { $_.BenchmarkSeconds } else { $Cfg.BenchmarkSeconds } + } + } + } + } +} diff --git a/Miners/xmr-stak-cpu-150.ps1 b/Miners/xmr-stak-cpu-150.ps1 new file mode 100644 index 00000000..41767d06 --- /dev/null +++ b/Miners/xmr-stak-cpu-150.ps1 @@ -0,0 +1,118 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +. .\Code\Include.ps1 + +if (![Config]::Is64Bit) { exit } + +function Get-XMRStak([Parameter(Mandatory = $true)][string] $filename) { + [MinerInfo]@{ + Pool = $Pool.PoolName() + Name = $Name + Algorithm = $Algo + Type = [eMinerType]::CPU + API = "xmr-stak-cpu" + URI = "https://github.com/Quake4/MindMinerPrerequisites/raw/master/CPU/xmr-stak/xmr-stak-cpu-150.zip" + Path = "xmr-stak-cpu-150\xmr-stak-cpu.exe" + ExtraArgs = $filename + Arguments = $filename + Port = 4047 + BenchmarkSeconds = $Cfg.BenchmarkSeconds + } +} + +function Save-XMRStak([Parameter(Mandatory = $true)][string] $Path, [int] $Count, [string] $Mask) { + $nl = [Environment]::NewLine + $nh = if ([string]::Equals($Pool.Name, "nicehash", [System.StringComparison]::InvariantCultureIgnoreCase)) { "true" } else { "false" } + $baseconfig = "`"use_slow_memory`": `"warn`"," + $nl + + "`"nicehash_nonce`": $nh," + $nl + + "`"pool_address`": `"$($Pool.Host):$($Pool.Port)`"," + $nl + + "`"wallet_address`": `"$($Pool.User)`"," + $nl + + "`"pool_password`": `"$($Pool.Password)`"," + $nl + + "`"call_timeout`": 10," + $nl + + "`"retry_time`": 10," + $nl + + "`"verbose_level`": 3," + $nl + + "`"h_print_time`": 60," + $nl + + "`"httpd_port`": 4047," + $nl + + "`"prefer_ipv4`": true," + $nl + + "`"aes_override`": true," + $nl + + "`"use_tls`": false," + $nl + + "`"tls_secure_algo`": true," + $nl + + "`"tls_fingerprint`": `"`"," + $nl + + "`"giveup_limit`": 0," + $nl + + "`"daemon_mode`": false," + $nl + + "`"output_file`": `"`"" + $threadconfig = "{{ `"low_power_mode`": false, `"no_prefetch`": true, `"affine_to_cpu`": {0} }},$nl" + if (![string]::IsNullOrWhiteSpace($Mask)) { + $Count = 0 + $i = 0 + $threads = [string]::Empty + $Mask.ToCharArray() | ForEach-Object { + if ($_ -eq "1") { + $Count++ + $threads += $threadconfig -f $i + } + $i++ + } + $result = "`"cpu_thread_num`": $Count," + $nl + + "`"cpu_threads_conf`": [" + $nl + $threads + "],$nl" + $baseconfig + $result | Out-File "$Path\affinity_$Mask.txt" -Force -Encoding ascii + Get-XMRStak "affinity_$Mask.txt" + } + elseif ($Count -ge [Config]::Processors) { + $result = "`"cpu_thread_num`": $Count," + $nl + + "`"cpu_threads_conf`": [" + $nl + for ($i = [Config]::Processors; $i -le $Count; $i++) { + $result += $threadconfig -f "false" + } + $result += "],$nl" + $baseconfig + $result | Out-File "$Path\$($Count)_threads.txt" -Force -Encoding ascii + Get-XMRStak "$($Count)_threads.txt" + } +} + +$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName + +$Cfg = [BaseConfig]::ReadOrCreate([IO.Path]::Combine($PSScriptRoot, $Name + [BaseConfig]::Filename), @{ + Enabled = $true + BenchmarkSeconds = 25 + ConfigFile = $null + ThreadCount = $null + ThreadMask = $null +}) + +if (!$Cfg.Enabled) { return } + +$Algo = Get-Algo("cryptonight") +if ($Algo) { + # find pool by algorithm + $Pool = Get-Pool($Algo) + if ($Pool) { + + $Path = Split-Path -Path ([IO.Path]::Combine($BinLocation, (Get-XMRStak [string]::Empty).Path)) + New-Item $Path -ItemType Directory -Force | Out-Null + + if ($Cfg.ConfigFile) { + # by userconfig + Get-XMRStak($Cfg.ConfigFile) + } + elseif ($Cfg.ThreadCount -or $Cfg.ThreadMask) { + # by user settings + Save-XMRStak($Cfg.ThreadCount, $Cfg.ThreadMask) + } + else { + # brute force + # no affinity + for ([int] $i = [Config]::Processors; $i -le [Config]::Threads; $i++) { + Save-XMRStak -Path $Path -Count $i + } + # with affinity + Get-CPUMask | ForEach-Object { + Save-XMRStak -Path $Path -Mask $_ + } + } + } +} \ No newline at end of file diff --git a/Pools/MPH.ps1 b/Pools/MPH.ps1 new file mode 100644 index 00000000..b2faa002 --- /dev/null +++ b/Pools/MPH.ps1 @@ -0,0 +1,76 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +. .\Code\Include.ps1 + +if ([string]::IsNullOrWhiteSpace($Config.Login)) { return } + +$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName + +$Cfg = [BaseConfig]::ReadOrCreate([IO.Path]::Combine($PSScriptRoot, $Name + [BaseConfig]::Filename), @{ + Enabled = $true + AverageProfit = "1 hour 30 min" +}) + +if (!$Cfg.Enabled) { return } +$Pool_Variety = 0.85 + +try { + $Request = Get-UrlAsJson "http://miningpoolhub.com/index.php?page=api&action=getminingandprofitsstatistics" +} +catch { + return +} + +if (!$Request -or !($Request.success -eq $true)) { return } + +if ($Config.SSL -eq $true) { $Pool_Protocol = "stratum+ssl" } else { $Pool_Protocol = "stratum+tcp" } +$Pool_Regions = "europe", "us", "asia" + +$Pool_Regions | ForEach-Object { + $Pool_Region = $_ + [eRegion]$Miner_Region = [eRegion]::Other + + switch ($Pool_Region) { + "europe" { $Miner_Region = [eRegion]::Europe } + "us" { $Miner_Region = [eRegion]::Usa } + "asia" { $Miner_Region = [eRegion]::China } + } + + if ($Config.Region -eq $Miner_Region) { + $Request.return | ForEach-Object { + $Pool_Algorithm = Get-Algo($_.algo) + if ($Pool_Algorithm) { + $Pool_Host = $_.host_list.split(";") | Where-Object { $_.Contains($Pool_Region) } | Select-Object -First 1 + $Pool_Port = $_.port + $Coin = (Get-Culture).TextInfo.ToTitleCase($_.coin_name) + if (!$Coin.StartsWith($_.algo)) { + $Coin = $Coin.Replace($_.algo, "") + } + $Coin = $Coin.Replace("-", "").Replace("DigibyteGroestl", "Digibyte").Replace("MyriadcoinGroestl", "MyriadCoin") + + $Divisor = 1000000000 + $Profit = [decimal]$_.profit * (1 - 0.009) * $Pool_Variety / $Divisor + + if ($Profit -gt 0) { + $Profit = Set-Stat -Filename $Name -Key "$Pool_Algorithm`_$Coin" -Value $Profit -Interval $Cfg.AverageProfit + + [PoolInfo] @{ + Name = $Name + Algorithm = $Pool_Algorithm + Info = "$Miner_Region-$Coin" + Profit = $Profit + Protocol = $Pool_Protocol + Host = $Pool_Host + Port = $Pool_Port + User = "$($Config.Login).$($Config.WorkerName)" + Password = $Config.Password + } + } + } + } + } +} \ No newline at end of file diff --git a/Pools/NiceHash.ps1 b/Pools/NiceHash.ps1 new file mode 100644 index 00000000..e4101937 --- /dev/null +++ b/Pools/NiceHash.ps1 @@ -0,0 +1,71 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +. .\Code\Include.ps1 + +if (!$Config.Wallet.BTC) { return } + +$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName + +$Cfg = [BaseConfig]::ReadOrCreate([IO.Path]::Combine($PSScriptRoot, $Name + [BaseConfig]::Filename), @{ + Enabled = $true + AverageProfit = "20 min" +}) + +if (!$Cfg.Enabled) { return } + +try { + $Request = Get-UrlAsJson "https://api.nicehash.com/api?method=simplemultialgo.info" +} +catch { + return +} + +if (!$Request) { return } + +if ($Config.SSL -eq $true) { $Pool_Protocol = "stratum+ssl" } else { $Pool_Protocol = "stratum+tcp" } +$Pool_Regions = "eu", "usa", "hk", "jp", "in", "br" + +$Pool_Regions | ForEach-Object { + $Pool_Region = $_ + [eRegion]$Miner_Region = [eRegion]::Other + + switch ($Pool_Region) { + "eu" { $Miner_Region = [eRegion]::Europe } + "usa" { $Miner_Region = [eRegion]::Usa } + "hk" { $Miner_Region = [eRegion]::China } + "jp" { $Miner_Region = [eRegion]::Japan } + } + + if ($Config.Region -eq $Miner_Region) { + $Request.result.simplemultialgo | ForEach-Object { + $Pool_Algorithm = Get-Algo($_.name) + if ($Pool_Algorithm) { + $Pool_Host = "$($_.name).$Pool_Region.nicehash.com" + $Pool_Port = $_.port + + $Divisor = 1000000000 + $Profit = [Double]$_.paying * (1 - 0.04) / $Divisor + + if ($Profit -gt 0) { + $Profit = Set-Stat -Filename $Name -Key $Pool_Algorithm -Value $Profit -Interval $Cfg.AverageProfit + + [PoolInfo] @{ + Name = $Name + Algorithm = $Pool_Algorithm + Info = $Miner_Region + Profit = $Profit + Protocol = $Pool_Protocol + Host = $Pool_Host + Port = $Pool_Port + User = "$($Config.Wallet.BTC).$($Config.WorkerName)" + Password = $Config.Password + } + } + } + } + } +} \ No newline at end of file diff --git a/Pools/ZPool.ps1 b/Pools/ZPool.ps1 new file mode 100644 index 00000000..fc6f2a87 --- /dev/null +++ b/Pools/ZPool.ps1 @@ -0,0 +1,118 @@ +<# +MindMiner Copyright (C) 2017 Oleg Samsonov aka Quake4/Quake3 +https://github.com/Quake4/MindMiner +License GPL-3.0 +#> + +. .\Code\Include.ps1 + +if (!$Config.Wallet.BTC) { return } + +$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName + +$Cfg = [BaseConfig]::ReadOrCreate([IO.Path]::Combine($PSScriptRoot, $Name + [BaseConfig]::Filename), @{ + Enabled = $true + AverageProfit = "1 hour 30 min" +}) + +if (!$Cfg.Enabled) { return } + +$Pool_Variety = 0.80 +# zpool already accounting Aux's +$AuxCoins = @(<#"UIS", "MBL"#>) + +try { + $RequestStatus = Get-UrlAsJson "https://www.zpool.ca/api/status" +} +catch { return } + +try { + $RequestCurrency = Get-UrlAsJson "https://www.zpool.ca/api/currencies" +} +catch { return } + +if (!$RequestStatus -or !$RequestCurrency) { return } + +# if ($Config.SSL -eq $true) { $Pool_Protocol = "stratum+ssl" } else { $Pool_Protocol = "stratum+tcp" } + +$Currency = $RequestCurrency | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object { + [PSCustomObject]@{ + Coin = if (!$RequestCurrency.$_.symbol) { $_ } else { $RequestCurrency.$_.symbol } + Algo = $RequestCurrency.$_.algo + Profit = $RequestCurrency.$_.estimate + } +} + +$RequestStatus | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object { + $Pool_Algorithm = Get-Algo($RequestStatus.$_.name) + if ($Pool_Algorithm) { + $Pool_Host = "$($RequestStatus.$_.name).mine.zpool.ca" + $Pool_Port = $RequestStatus.$_.port + + $Divisor = 1000000 + + switch ($Pool_Algorithm) { + "blake" { $Divisor *= 1000 } + "blake2s" { $Divisor *= 1000 } + "blakecoin" { $Divisor *= 1000 } + "decred" { $Divisor *= 1000 } + "equihash" { $Divisor /= 1000 } + "qubit" { $Divisor *= 1000 } + "nist5" { $Divisor *= 3 } + "x11" { $Divisor *= 1000 } + "yescrypt" { $Divisor /= 1000 } + } + + # find more profit coin in algo + $Algo = $RequestStatus.$_ + $MaxCoin = $null; + $MaxCoinProfit = $null + [decimal]$AuxProfit = 0 + # convert to one dimension and decimal + $Algo.actual_last24h = [decimal]$Algo.actual_last24h / 1000 + $Algo.estimate_last24h = [decimal]$Algo.estimate_last24h + $Currency | Where-Object { $_.Algo -eq $Algo.name } | ForEach-Object { + $prof = [decimal]$_.Profit / 1000 + # next three lines try to fix zpool error in output profit + if ($prof -gt $Algo.estimate_last24h * 2) { $prof = $Algo.estimate_last24h } + if ($Algo.actual_last24h -gt $Algo.estimate_last24h * 2) { $Algo.actual_last24h = 0 } + if ($Algo.estimate_last24h -gt $Algo.actual_last24h * 2) { $Algo.estimate_last24h = $Algo.actual_last24h } + + if ($Algo.actual_last24h -gt 0.0) { + $Profit = $prof * 0.05 + $Algo.estimate_last24h * 0.35 + $Algo.actual_last24h * 0.60 + } + else { + $Profit = $prof * 0.15 + $Algo.estimate_last24h * 0.85 + } + + $Profit *= (1 - [decimal]$Algo.fees / 100) * $Pool_Variety / $Divisor + + if ($MaxCoin -eq $null -or $_.Profit -gt $MaxCoin.Profit) { + $MaxCoin = $_ + $MaxCoinProfit = $Profit + } + + if ($AuxCoins.Contains($_.Coin)) { + $AuxProfit += $prof * (1 - [decimal]$Algo.fees / 100) * $Pool_Variety / $Divisor + } + } + + if ($MaxCoinProfit -gt 0) { + $MaxCoinProfit = Set-Stat -Filename $Name -Key $Pool_Algorithm -Value ($MaxCoinProfit + $AuxProfit) -Interval $Cfg.AverageProfit + + [PoolInfo] @{ + Name = $Name + Algorithm = $Pool_Algorithm + Profit = ($MaxCoinProfit + $AuxProfit) + Info = $MaxCoin.Coin + #StablePrice = $null + #PriceFluctuation = $null + Protocol = "stratum+tcp" # $Pool_Protocol + Host = $Pool_Host + Port = $Pool_Port + User = $Config.Wallet.BTC + Password = "c=BTC,$($Config.WorkerName)" # "c=$($MaxCoin.Coin),$($Config.WorkerName)"; + } + } + } +} \ No newline at end of file diff --git a/run.bat b/run.bat new file mode 100644 index 00000000..eab22051 --- /dev/null +++ b/run.bat @@ -0,0 +1,10 @@ +@echo off +:start +powershell -version 5.0 -executionpolicy bypass -command "&.\MindMiner.ps1" +if exist "bin\mm.new" ( + xcopy Bin\MM.New . /y /s /c /q /exclude:run.bat + rmdir /q /s Bin\MM.New + goto start: +) else ( + pause +) \ No newline at end of file