From 238c23a83e89124e5e0177962ea2f34291b7360a Mon Sep 17 00:00:00 2001 From: Ario Date: Thu, 6 Dec 2018 22:20:43 +0000 Subject: [PATCH 001/134] detail account view --- .gitignore | 1 + cache/info.txt | 0 composer.lock | 19 +++++--- config.php | 70 ---------------------------- index.php | 23 +++++++++ template/account.html | 106 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 142 insertions(+), 77 deletions(-) mode change 100644 => 100755 cache/info.txt delete mode 100644 config.php create mode 100755 template/account.html diff --git a/.gitignore b/.gitignore index 46e1de7..2a2e2e8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /vendor /cache/template +config.php diff --git a/cache/info.txt b/cache/info.txt old mode 100644 new mode 100755 diff --git a/composer.lock b/composer.lock index 125f3bf..dd59138 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "4d41c56a619c079b1370689ed4a5980f", + "content-hash": "48490d1ee52afda34388c89bc7556b5a", "packages": [ { "name": "rain/raintpl", @@ -51,16 +51,16 @@ "packages-dev": [ { "name": "squizlabs/php_codesniffer", - "version": "3.2.3", + "version": "3.3.2", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "4842476c434e375f9d3182ff7b89059583aa8b27" + "reference": "6ad28354c04b364c3c71a34e4a18b629cc3b231e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/4842476c434e375f9d3182ff7b89059583aa8b27", - "reference": "4842476c434e375f9d3182ff7b89059583aa8b27", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/6ad28354c04b364c3c71a34e4a18b629cc3b231e", + "reference": "6ad28354c04b364c3c71a34e4a18b629cc3b231e", "shasum": "" }, "require": { @@ -98,7 +98,7 @@ "phpcs", "standards" ], - "time": "2018-02-20T21:35:23+00:00" + "time": "2018-09-23T23:08:17+00:00" } ], "aliases": [], @@ -106,6 +106,11 @@ "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, - "platform": [], + "platform": { + "php": "^7.2", + "ext-bcmath": "*", + "ext-gmp": "*", + "ext-openssl": "*" + }, "platform-dev": [] } diff --git a/config.php b/config.php deleted file mode 100644 index b1a1c6d..0000000 --- a/config.php +++ /dev/null @@ -1,70 +0,0 @@ -assign("q", $q); +$tpl->assign("id", $id); $tpl->draw('header'); if ($q == "") { @@ -92,6 +94,27 @@ $tpl->assign("difficulty", 200000000 - $current['difficulty']); $tpl->draw("index"); +} elseif ($q == 'acc') { + + $r = $db->run("SELECT concat(id) AS id, sum(hashrate) AS hashrate, sum(gpuhr) as gpuhr, updated FROM workers WHERE miner=:miner GROUP BY id", [":miner" => $id] ); + //var_dump($r); + $b = []; + foreach ($r as $x) { + //$x['reward'] = number_format($x['reward'], 2); + $b[] = $x; + } + + $r = $db->run("SELECT * FROM miners WHERE id=:miner", [":miner" => $id] ); + + $tpl->assign("account", $r); + + $r = $db->run("SELECT sum(hashrate) AS cpuhr, sum(gpuhr) as gpuhr FROM workers WHERE miner=:miner GROUP BY id", [":miner" => $id]); + + $tpl->assign("hashrate", $r); + + $tpl->assign("workers", $b); + $tpl->draw("account"); + } elseif ($q == "blocks") { $r = $db->run("SELECT * FROM blocks ORDER by height DESC LIMIT 100"); $b = []; diff --git a/template/account.html b/template/account.html new file mode 100755 index 0000000..0902fbc --- /dev/null +++ b/template/account.html @@ -0,0 +1,106 @@ + +
+
+
+
+

Miner: {$id}

+
+
+
+ + + + + {loop="$hashrate"} + + + + + + + + + + + + {/loop} + {loop="$account"} + + + + + + + + + + + + + + + + + + + + + + + + + + {/loop} +
 
CPU hashrate:{$value.cpuhr}
GPU hashrate:{$value.gpuhr}
 
Pending balance:{$value.pending}
Total paid:{$value.total_paid}
 
Shares for current block:{$value.shares}
Total historic shares:{$value.historic}
Best nonce for current block (best DL):{$value.bestdl}
+
+
+
+
+
+ + +
+
+
+
+ Miner's workers +
+
+
+ + + + + + + + + + + + + + + + + + + + + {loop="$workers"} + + + + + + + {/loop} + +
IDCPU hrGPU hrUpdated
IDCPU hrGPU hrUpdated
{$value.id}{$value.hashrate}{$value.gpuhr}{$value.updated}
+
+
+
+
+
+ + From d2bca1060dd21888763863b462ea88373453b245 Mon Sep 17 00:00:00 2001 From: Ario Date: Thu, 6 Dec 2018 22:21:55 +0000 Subject: [PATCH 002/134] sample config --- config-sample.php | 70 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 config-sample.php diff --git a/config-sample.php b/config-sample.php new file mode 100644 index 0000000..b1a1c6d --- /dev/null +++ b/config-sample.php @@ -0,0 +1,70 @@ + Date: Thu, 6 Dec 2018 22:27:35 +0000 Subject: [PATCH 003/134] link to account from dashboard --- template/index.html | 55 +++++++++++++++++---------------------------- 1 file changed, 20 insertions(+), 35 deletions(-) diff --git a/template/index.html b/template/index.html index 33893f6..c83ca7c 100755 --- a/template/index.html +++ b/template/index.html @@ -10,7 +10,6 @@

{$height}

Current Block
-
@@ -71,7 +70,6 @@
ARO

{$total_gpu}

GPU Hash Rate ({$gpu_ext})
-

{$total_hr}

@@ -82,16 +80,10 @@
CPU Hash Rate ({$hr_ext})
- - - -
- -
Current Shares @@ -105,7 +97,7 @@
CPU Hash Rate ({$hr_ext})
Shares % Best DL - Miner + Miner @@ -114,30 +106,26 @@
CPU Hash Rate ({$hr_ext})
Shares % Best DL - Miner + Miner - -{loop="$shares"} + {loop="$shares"} {$value.shares} {$value.percent} % {$value.bestdl} - {$value.id} + {$value.id} -{/loop} + {/loop}
-
- -
Historic Shares @@ -151,46 +139,43 @@
CPU Hash Rate ({$hr_ext})
Shares % - CPU HR + CPU HR GPU HR - Pending + Pending Total paid - Miner - + Miner + Shares - % - CPU HR + % + CPU HR GPU HR - Pending + Pending Total paid - Miner + Miner -{loop="$historic"} + {loop="$historic"} {$value.historic} {$value.percent} % - {$value.hashrate} - {$value.gpuhr} - {$value.pending} + {$value.hashrate} + {$value.gpuhr} + {$value.pending} {$value.total_paid} - {$value.id} + {$value.id} -{/loop} + {/loop}
-
- - - + \ No newline at end of file From dcc6186742932b33d0f9fa4a174a23388cb06ff9 Mon Sep 17 00:00:00 2001 From: Ario Date: Thu, 6 Dec 2018 23:43:07 +0000 Subject: [PATCH 004/134] labels --- template/account.html | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/template/account.html b/template/account.html index 0902fbc..33138fa 100755 --- a/template/account.html +++ b/template/account.html @@ -63,26 +63,26 @@
- Miner's workers + Workers
- - - - + + + + - - - - + + + + From 1b171ca9c7cb37b35f1aa8e6b8810d3253c7b858 Mon Sep 17 00:00:00 2001 From: Ario <44259996+ariochain@users.noreply.github.com> Date: Fri, 7 Dec 2018 01:40:23 +0100 Subject: [PATCH 005/134] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 97ab790..c79826e 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,8 @@ The requirements are the same as for the arionum node: - php-gmp - php-bcmath +after cloning repository do `composer update` - it will download required code + ## Usage 1. Create a new database for the pool (separate from the node one). From 353c8ca7a1b49f98ed41f93386d5ac3cf2b9a6f7 Mon Sep 17 00:00:00 2001 From: Ario Date: Fri, 7 Dec 2018 10:55:56 +0000 Subject: [PATCH 006/134] formating variables --- index.php | 35 ++++++++++++++++++++++++++++------- template/index.html | 2 +- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/index.php b/index.php index c819c6f..5fd7e41 100755 --- a/index.php +++ b/index.php @@ -97,22 +97,43 @@ } elseif ($q == 'acc') { $r = $db->run("SELECT concat(id) AS id, sum(hashrate) AS hashrate, sum(gpuhr) as gpuhr, updated FROM workers WHERE miner=:miner GROUP BY id", [":miner" => $id] ); - //var_dump($r); $b = []; foreach ($r as $x) { - //$x['reward'] = number_format($x['reward'], 2); + $x['hashrate'] = number_format($x['hashrate'], 2); + $x['gpuhr'] = number_format($x['gpuhr'], 2); + + $x['updated'] = date('Y/m/d H:i:s', $x['updated']); + $b[] = $x; } + $tpl->assign("workers", $b); + $r = $db->run("SELECT * FROM miners WHERE id=:miner", [":miner" => $id] ); - - $tpl->assign("account", $r); + $b = []; + foreach ($r as $x) { + $x['hashrate'] = number_format($x['hashrate'], 2); + $x['gpuhr'] = number_format($x['gpuhr'], 2); + + $x['pending'] = number_format($x['pending'], 2); + $x['total_paid'] = number_format($x['total_paid'], 2); + + $x['updated'] = date('Y/m/d H:i:s', $x['updated']); + $b[] = $x; + } + $tpl->assign("account", $b); + $r = $db->run("SELECT sum(hashrate) AS cpuhr, sum(gpuhr) as gpuhr FROM workers WHERE miner=:miner GROUP BY id", [":miner" => $id]); - - $tpl->assign("hashrate", $r); + $c = []; + foreach ($r as $x) { + $x['cpuhr'] = number_format($x['cpuhr'], 2); + $x['gpuhr'] = number_format($x['gpuhr'], 2); + $c[] = $x; + } + $tpl->assign("hashrate", $c); + - $tpl->assign("workers", $b); $tpl->draw("account"); } elseif ($q == "blocks") { diff --git a/template/index.html b/template/index.html index c83ca7c..65397f9 100755 --- a/template/index.html +++ b/template/index.html @@ -126,7 +126,7 @@
CPU Hash Rate ({$hr_ext})
-
+
Historic Shares Total Historic Shares: {$total_historic} From e13772a65f8bc66f5ba2b2af99bade3e9e9259ad Mon Sep 17 00:00:00 2001 From: Ario Date: Fri, 7 Dec 2018 11:12:57 +0000 Subject: [PATCH 007/134] account - added "ARO" text --- template/account.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/template/account.html b/template/account.html index 33138fa..2f175de 100755 --- a/template/account.html +++ b/template/account.html @@ -27,11 +27,11 @@ {loop="$account"}
- + - + From d7f0f38a496451fddaab1a72b2b247f92e174030 Mon Sep 17 00:00:00 2001 From: Ario Date: Fri, 7 Dec 2018 11:16:01 +0000 Subject: [PATCH 008/134] account - added "h/s" text --- index.php | 8 ++++---- template/account.html | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/index.php b/index.php index 5fd7e41..cf803bb 100755 --- a/index.php +++ b/index.php @@ -112,8 +112,8 @@ $r = $db->run("SELECT * FROM miners WHERE id=:miner", [":miner" => $id] ); $b = []; foreach ($r as $x) { - $x['hashrate'] = number_format($x['hashrate'], 2); - $x['gpuhr'] = number_format($x['gpuhr'], 2); + $x['hashrate'] = number_format($x['hashrate'], 0); + $x['gpuhr'] = number_format($x['gpuhr'], 0); $x['pending'] = number_format($x['pending'], 2); $x['total_paid'] = number_format($x['total_paid'], 2); @@ -127,8 +127,8 @@ $r = $db->run("SELECT sum(hashrate) AS cpuhr, sum(gpuhr) as gpuhr FROM workers WHERE miner=:miner GROUP BY id", [":miner" => $id]); $c = []; foreach ($r as $x) { - $x['cpuhr'] = number_format($x['cpuhr'], 2); - $x['gpuhr'] = number_format($x['gpuhr'], 2); + $x['cpuhr'] = number_format($x['cpuhr'], 0); + $x['gpuhr'] = number_format($x['gpuhr'], 0); $c[] = $x; } $tpl->assign("hashrate", $c); diff --git a/template/account.html b/template/account.html index 2f175de..c5562a6 100755 --- a/template/account.html +++ b/template/account.html @@ -14,11 +14,11 @@ {loop="$hashrate"} - + - + From 77d193f2ebe7e5ff32510a45999a8bf79cd4fece Mon Sep 17 00:00:00 2001 From: Ario Date: Fri, 7 Dec 2018 11:31:32 +0000 Subject: [PATCH 009/134] get correct reward value --- mine.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mine.php b/mine.php index 5f2002d..41372e9 100644 --- a/mine.php +++ b/mine.php @@ -131,7 +131,7 @@ function curl_post($url, $post) if ($bl['generator'] == $pool_config['address'] && $added == 0) { $reward = $aro->single( - "SELECT val FROM transactions WHERE block=:bl AND version=0", + "SELECT val FROM transactions WHERE block=:bl AND message="" AND version=0", [":bl" => $bl['id']] ); if ($reward == 0) { From f9828448b93ea37d4712d3e068544f29732b3901 Mon Sep 17 00:00:00 2001 From: Ario Date: Fri, 7 Dec 2018 12:40:37 +0000 Subject: [PATCH 010/134] get correct reward value / bugfix --- mine.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mine.php b/mine.php index 41372e9..de36fd6 100644 --- a/mine.php +++ b/mine.php @@ -131,7 +131,7 @@ function curl_post($url, $post) if ($bl['generator'] == $pool_config['address'] && $added == 0) { $reward = $aro->single( - "SELECT val FROM transactions WHERE block=:bl AND message="" AND version=0", + "SELECT val FROM transactions WHERE block=:bl AND message='' AND version=0", [":bl" => $bl['id']] ); if ($reward == 0) { From aae8e7d88597f4bd5d3b6602bf0f94b47448f7e2 Mon Sep 17 00:00:00 2001 From: Ario Date: Fri, 7 Dec 2018 12:42:02 +0000 Subject: [PATCH 011/134] formating variables --- index.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.php b/index.php index cf803bb..86028b1 100755 --- a/index.php +++ b/index.php @@ -99,8 +99,8 @@ $r = $db->run("SELECT concat(id) AS id, sum(hashrate) AS hashrate, sum(gpuhr) as gpuhr, updated FROM workers WHERE miner=:miner GROUP BY id", [":miner" => $id] ); $b = []; foreach ($r as $x) { - $x['hashrate'] = number_format($x['hashrate'], 2); - $x['gpuhr'] = number_format($x['gpuhr'], 2); + $x['hashrate'] = number_format($x['hashrate'], 0); + $x['gpuhr'] = number_format($x['gpuhr'], 0); $x['updated'] = date('Y/m/d H:i:s', $x['updated']); From ebebba4594f020f7882bfc08ac2eb21d5e04296d Mon Sep 17 00:00:00 2001 From: Ario Date: Fri, 7 Dec 2018 14:56:10 +0000 Subject: [PATCH 012/134] payout message to config + manual payout --- cache/info.txt | 2 +- config-sample.php | 3 + manualpayment-sendall.php | 176 ++++++++++++++++++++++++++++++++++++++ payments.php | 1 + 4 files changed, 181 insertions(+), 1 deletion(-) create mode 100644 manualpayment-sendall.php diff --git a/cache/info.txt b/cache/info.txt index dd78695..05f5324 100755 --- a/cache/info.txt +++ b/cache/info.txt @@ -1 +1 @@ -{"status":"ok","data":{"difficulty":"45669041","block":"ReoyrSmEHtkHkSTowE4opskgow9hWx9nwbjcTqWtac68MNnaQYygW417sa7nrXZtvKc66McLfQfH8BEginMvNJC","height":19515,"public_key":"your public key","limit":1000000},"coin":"arionum"} \ No newline at end of file +{"status":"ok","data":{"difficulty":"1049987","block":"3XpbXXhVpPdDr4ZioJvGdgy8VfAETuqZCW6EpNncKGNrDGHSYbjXBs9jMmBPiF3J2b9hXBBd1jxcAnmBLWkSdnbn","height":120025,"public_key":"PZ8Tyr4Nx8MHsRAGMpZmZ6TWY63dXWSCzf2cu1NM6Ayxc1WpzmhMLECvtVyYngF4xaZu4HyPFZytotVJ5ATTaPz9gsH7pauTRkipzzgYNekAjMVAbTr6etGx","limit":240000,"recommendation":"mine","argon_mem":16384,"argon_threads":4,"argon_time":4},"coin":"arionum"} \ No newline at end of file diff --git a/config-sample.php b/config-sample.php index b1a1c6d..74e8f1e 100644 --- a/config-sample.php +++ b/config-sample.php @@ -68,3 +68,6 @@ // The minimum payout that is required $pool_config['min_payout'] = 3; + +// The message included in payments +$pool_config['payout_message'] = ""; diff --git a/manualpayment-sendall.php b/manualpayment-sendall.php new file mode 100644 index 0000000..745f0eb --- /dev/null +++ b/manualpayment-sendall.php @@ -0,0 +1,176 @@ + 3600) { + system("rm -rf $pid112"); + } + die("\n\n### RUNNING ### -- PID: $pid112\n\n"); +} +system("touch $pid112"); +function shut_down() +{ + global $pid112; + system("rm -rf $pid112"); + echo "\n# ShutDown #\n"; +} + +register_shutdown_function("shut_down"); +############################################### + +set_time_limit(0); +if (php_sapi_name() !== 'cli') { + die("This should only be run as cli"); +} + +require_once("db.php"); + +function pay_post($url, $data = []) +{ + global $pool_config; + $peer = $pool_config['node_url']; + $postdata = http_build_query( + [ + 'data' => json_encode($data), + "coin" => " arionum", + ] + ); + + $opts = [ + 'http' => + [ + 'timeout' => "300", + 'method' => 'POST', + 'header' => 'Content-type: application/x-www-form-urlencoded', + 'content' => $postdata, + ], + ]; + + $context = stream_context_create($opts); + + $result = file_get_contents($peer.$url, false, $context); + $res = json_decode($result, true); + return $res; +} + +$pool_config['min_payout'] = 0; + + +$hour = date("H"); +$min = date("i"); + +$blocks_paid = 50000; + + +echo "\n----------------------------------------------------------------------------------\n"; +$current = $aro->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); +echo "Current block $current\n"; + + +$db->run("DELETE FROM miners WHERE historic+shares<=20"); +$db->run("UPDATE miners SET gpuhr=(SELECT SUM(gpuhr) FROM workers WHERE miner=miners.id AND updated>UNIX_TIMESTAMP()-3600)"); +$db->run("UPDATE miners SET hashrate=(SELECT SUM(hashrate) FROM workers WHERE miner=miners.id AND updated>UNIX_TIMESTAMP()-3600)"); +$db->run( + "UPDATE miners SET pending=(SELECT SUM(val) FROM payments WHERE done=0 AND payments.address=miners.id AND height>=:h)", + [":h" => $current - $blocks_paid] +); + + +$r = $db->run( + "SELECT DISTINCT block FROM payments WHERE height<:h AND done=0 AND height>=:h2", + [":h" => $current - 10, ":h2" => $current - $blocks_paid] +); +if (count($r) == 0) { + die("No payments pending\n"); +} + +$db->run("DELETE FROM miners WHERE shares=0 AND historic=0 AND updatedrun("DELETE FROM workers WHERE updatedsingle("SELECT COUNT(1) FROM blocks WHERE id=:id", [":id" => $x['block']]); + if ($s == 0) { + $db->run("DELETE FROM blocks WHERE id=:id", [":id" => $x['block']]); + $db->run("DELETE FROM payments WHERE block=:id", [":id" => $x['block']]); + echo "Deleted block: $x[block]\n"; + } +} + + +$total_paid = 0; +$r = $db->run( + "SELECT SUM(val) as v, address FROM payments WHERE height<:h AND height>=:h2 AND done=0 GROUP by address", + [":h" => $current - 10, ":h2" => $current - $blocks_paid] +); +foreach ($r as $x) { + if ($x['v'] < $pool_config['min_payout']) { + continue; + } + $fee = $x['v'] * 0.0025; + if ($fee < 0.00000001) { + $fee = 0.00000001; + } + if ($fee > 10) { + $fee = 10; + } + $val = number_format($x['v'] - $fee, 8, ".", ""); + #$val=intval($val); + $public_key = $pool_config['public_key']; + $private_key = $pool_config['private_key']; + + $res = pay_post("/api.php?q=send", [ + "dst" => $x['address'], + "val" => $val, + "private_key" => $private_key, + "public_key" => $public_key, + "version" => 1, + "message" => $pool_config['payout_message'] + ]); + echo "$val\n"; + echo "$x[address]\n"; + if ($res['status'] != "ok") { + print("ERROR: $res[data]\n"); + } else { + $total_paid += $x['v']; + + echo "Transaction sent - $x[address] - $val! Transaction id: $res[data]\n"; + $db->run( + "UPDATE payments SET txn=:txn, done=1 WHERE address=:address AND height<:h AND done=0 AND height>=:h2", + [ + ":h" => $current - 10, + ":h2" => $current - $blocks_paid, + ":txn" => $res['data'], + ":address" => $x['address'], + ] + ); + $db->run("UPDATE miners SET total_paid=total_paid + :h WHERE id=:p", [":h" => $x['v'], ":p" => $x['address']]); + echo "DB updated\n"; + } +} + +$old = $db->single("SELECT val FROM info WHERE id='total_paid'"); +$new = $old + $total_paid; +echo "Total paid: $new\n"; + +$db->run("UPDATE info SET val=:s WHERE id='total_paid'", [":s" => $new]); +$not = $db->single("SELECT SUM(val) FROM payments WHERE done=0"); +echo "Pending balance: $not\n"; + + +$db->run( + "UPDATE miners SET pending=(SELECT SUM(val) FROM payments WHERE done=0 AND payments.address=miners.id AND height>=:h)", + [":h" => $current - $blocks_paid] +); + +$db->run("DELETE FROM payments WHERE done=1 AND height<:h", [":h" => $current - 1000]); diff --git a/payments.php b/payments.php index 66832b7..6c32fec 100644 --- a/payments.php +++ b/payments.php @@ -135,6 +135,7 @@ function pay_post($url, $data = []) "private_key" => $private_key, "public_key" => $public_key, "version" => 1, + "message" => $pool_config['payout_message'] ]); echo "$val\n"; echo "$x[address]\n"; From b50e9632d7256fe900e7240145eacef755a1ab28 Mon Sep 17 00:00:00 2001 From: Ario Date: Fri, 7 Dec 2018 15:13:43 +0000 Subject: [PATCH 013/134] save real worker name --- index.php | 2 +- mine.php | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/index.php b/index.php index 86028b1..46410b1 100755 --- a/index.php +++ b/index.php @@ -124,7 +124,7 @@ $tpl->assign("account", $b); - $r = $db->run("SELECT sum(hashrate) AS cpuhr, sum(gpuhr) as gpuhr FROM workers WHERE miner=:miner GROUP BY id", [":miner" => $id]); + $r = $db->run("SELECT count(id) as count, sum(hashrate) AS cpuhr, sum(gpuhr) as gpuhr FROM workers WHERE miner=:miner GROUP BY id", [":miner" => $id]); $c = []; foreach ($r as $x) { $x['cpuhr'] = number_format($x['cpuhr'], 0); diff --git a/mine.php b/mine.php index de36fd6..df38b09 100644 --- a/mine.php +++ b/mine.php @@ -22,6 +22,7 @@ function curl_post($url, $post) $ip = $_SERVER['REMOTE_ADDR']; $q = san($_GET['q']); +$worker = san($_GET['worker']); $max_dl = $pool_config['max_deadline']; @@ -33,7 +34,7 @@ function curl_post($url, $post) die("invalid wallet address. This address comes from a broken wallet file!"); } - $worker = md5($miner.$_GET['worker'].$ip); + //$worker = md5($miner.$_GET['worker'].$ip); $hr = intval($_GET['hashrate']); $gpuhr=intval($_GET['gpuhr']+$_GET['hrgpu']); $bind = [":id" => $worker, ":hr" => $hr, ":hr2" => $hr, ":miner" => $miner, ":ip" => $ip, ":ip2" => $ip, ":gpuhr"=>$gpuhr, ":gpuhr2"=>$gpuhr]; From 5f99411dede95133d7b5c7eaf44f16a782a1ed09 Mon Sep 17 00:00:00 2001 From: Ario Date: Fri, 7 Dec 2018 15:29:52 +0000 Subject: [PATCH 014/134] summary same workers hashrate --- cache/info.txt | 2 +- index.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cache/info.txt b/cache/info.txt index 05f5324..7b0f1b2 100755 --- a/cache/info.txt +++ b/cache/info.txt @@ -1 +1 @@ -{"status":"ok","data":{"difficulty":"1049987","block":"3XpbXXhVpPdDr4ZioJvGdgy8VfAETuqZCW6EpNncKGNrDGHSYbjXBs9jMmBPiF3J2b9hXBBd1jxcAnmBLWkSdnbn","height":120025,"public_key":"PZ8Tyr4Nx8MHsRAGMpZmZ6TWY63dXWSCzf2cu1NM6Ayxc1WpzmhMLECvtVyYngF4xaZu4HyPFZytotVJ5ATTaPz9gsH7pauTRkipzzgYNekAjMVAbTr6etGx","limit":240000,"recommendation":"mine","argon_mem":16384,"argon_threads":4,"argon_time":4},"coin":"arionum"} \ No newline at end of file +{"status":"ok","data":{"difficulty":"18683414","block":"5StajejGkTrfAeVrMZckfcwnkfE8zEPwoG3MZUcYD5SnjEv1jZMMRV71BSDiUvS1s2DVCBNZtwY669dVMo6QwX9F","height":120030,"public_key":"PZ8Tyr4Nx8MHsRAGMpZmZ6TWY63dXWSCzf2cu1NM6Ayxc1WpzmhMLECvtVyYngF4xaZu4HyPFZytotVJ5ATTaPz9gsH7pauTRkipzzgYNekAjMVAbTr6etGx","limit":2240000,"recommendation":"mine","argon_mem":524288,"argon_threads":1,"argon_time":1},"coin":"arionum"} \ No newline at end of file diff --git a/index.php b/index.php index 46410b1..67e62a2 100755 --- a/index.php +++ b/index.php @@ -124,7 +124,7 @@ $tpl->assign("account", $b); - $r = $db->run("SELECT count(id) as count, sum(hashrate) AS cpuhr, sum(gpuhr) as gpuhr FROM workers WHERE miner=:miner GROUP BY id", [":miner" => $id]); + $r = $db->run("SELECT sum(hashrate) / count(id) AS cpuhr, sum(gpuhr) / count(id) as gpuhr FROM workers WHERE miner=:miner GROUP BY id", [":miner" => $id]); $c = []; foreach ($r as $x) { $x['cpuhr'] = number_format($x['cpuhr'], 0); From eeebb3892638edded2e2afbd051e73c3bedf7e74 Mon Sep 17 00:00:00 2001 From: Ario Date: Fri, 7 Dec 2018 15:31:56 +0000 Subject: [PATCH 015/134] git ignore info.txt --- .gitignore | 1 + cache/info.txt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 2a2e2e8..d79bed8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /vendor /cache/template +/cache/info.txt config.php diff --git a/cache/info.txt b/cache/info.txt index 7b0f1b2..0f6a792 100755 --- a/cache/info.txt +++ b/cache/info.txt @@ -1 +1 @@ -{"status":"ok","data":{"difficulty":"18683414","block":"5StajejGkTrfAeVrMZckfcwnkfE8zEPwoG3MZUcYD5SnjEv1jZMMRV71BSDiUvS1s2DVCBNZtwY669dVMo6QwX9F","height":120030,"public_key":"PZ8Tyr4Nx8MHsRAGMpZmZ6TWY63dXWSCzf2cu1NM6Ayxc1WpzmhMLECvtVyYngF4xaZu4HyPFZytotVJ5ATTaPz9gsH7pauTRkipzzgYNekAjMVAbTr6etGx","limit":2240000,"recommendation":"mine","argon_mem":524288,"argon_threads":1,"argon_time":1},"coin":"arionum"} \ No newline at end of file +{"status":"ok","data":{"difficulty":"19617584","block":"wrTzZPgCqMU13xT3TpkChFXGFu9PRynCx46TDJvMFWGwnKtpaJnPSjYSu9PCZ4o2aPt8L3rxoLp3VpiC9kJtDNk","height":120032,"public_key":"PZ8Tyr4Nx8MHsRAGMpZmZ6TWY63dXWSCzf2cu1NM6Ayxc1WpzmhMLECvtVyYngF4xaZu4HyPFZytotVJ5ATTaPz9gsH7pauTRkipzzgYNekAjMVAbTr6etGx","limit":2240000,"recommendation":"mine","argon_mem":524288,"argon_threads":1,"argon_time":1},"coin":"arionum"} \ No newline at end of file From 718bb31223efafbe37f10b0f6af7750413c78268 Mon Sep 17 00:00:00 2001 From: Ario Date: Fri, 7 Dec 2018 15:34:57 +0000 Subject: [PATCH 016/134] remove info.txt --- cache/info.txt | 1 - 1 file changed, 1 deletion(-) delete mode 100755 cache/info.txt diff --git a/cache/info.txt b/cache/info.txt deleted file mode 100755 index 0f6a792..0000000 --- a/cache/info.txt +++ /dev/null @@ -1 +0,0 @@ -{"status":"ok","data":{"difficulty":"19617584","block":"wrTzZPgCqMU13xT3TpkChFXGFu9PRynCx46TDJvMFWGwnKtpaJnPSjYSu9PCZ4o2aPt8L3rxoLp3VpiC9kJtDNk","height":120032,"public_key":"PZ8Tyr4Nx8MHsRAGMpZmZ6TWY63dXWSCzf2cu1NM6Ayxc1WpzmhMLECvtVyYngF4xaZu4HyPFZytotVJ5ATTaPz9gsH7pauTRkipzzgYNekAjMVAbTr6etGx","limit":2240000,"recommendation":"mine","argon_mem":524288,"argon_threads":1,"argon_time":1},"coin":"arionum"} \ No newline at end of file From 912b59da358f08bc8a4b4901310763db093f7d8f Mon Sep 17 00:00:00 2001 From: Ario Date: Fri, 7 Dec 2018 16:20:19 +0000 Subject: [PATCH 017/134] different DL for CPU and GPU block types --- config-sample.php | 5 ++++- index.php | 9 ++++++++- poolsanity.php | 3 ++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/config-sample.php b/config-sample.php index 74e8f1e..990cac5 100644 --- a/config-sample.php +++ b/config-sample.php @@ -12,9 +12,12 @@ // The access URL for node $pool_config['node_url'] = 'http://127.0.0.1:30000'; -// The maximum deadline that is allowed for pool miners +// The maximum deadline that is allowed for pool miners // cpu block type $pool_config['max_deadline'] = 1000000; +// The maximum deadline that is allowed for pool miners // gpu block type +$pool_config['max_deadline_gpu'] = 1000000; + /* |-------------------------------------------------------------------------- | Database Configuration diff --git a/index.php b/index.php index 67e62a2..383f6a4 100755 --- a/index.php +++ b/index.php @@ -78,7 +78,10 @@ $tpl->assign("gpu_ext",$total_gpu_ext); $tpl->assign("total_gpu",$total_gpu_text); - + $agem = time(); + $agem = $current['date']; + + $agem = ( time() - $current['date']) ; $tpl->assign("avg_hr", $avg_hr); $tpl->assign("hr_ext", $total_hr_ext); @@ -92,6 +95,10 @@ $tpl->assign("shares", $shares); $tpl->assign("historic", $historic); $tpl->assign("difficulty", 200000000 - $current['difficulty']); + if ($current['height'] % 2) $blocktype = "GPU"; else $blocktype = "CPU"; + $tpl->assign("blocktype", $blocktype); + $tpl->assign("agem", $agem); + $tpl->draw("index"); } elseif ($q == 'acc') { diff --git a/poolsanity.php b/poolsanity.php index 5bcbd93..afa00d5 100644 --- a/poolsanity.php +++ b/poolsanity.php @@ -64,8 +64,9 @@ function shut_down() } + if ($current % 2) $max_dl = $pool_config['max_deadline_gpu']; else $max_dl = $pool_config['max_deadline']; - $max_dl = $pool_config['max_deadline']; + $cache_file = "cache/info.txt"; $f = file_get_contents($pool_config['node_url']."/mine.php?q=info"); From 3537af7c4983add866d204d53da67a0e980bd515 Mon Sep 17 00:00:00 2001 From: Ario Date: Fri, 7 Dec 2018 17:01:39 +0000 Subject: [PATCH 018/134] worker name fix? --- index.php | 2 +- mine.php | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/index.php b/index.php index 383f6a4..1049760 100755 --- a/index.php +++ b/index.php @@ -6,7 +6,7 @@ use Rain\Tpl; -Tpl::configure('tpl_dir', 'template/'); +Tpl::configure('tpl_dir', 'template2/'); Tpl::configure('debug', true); Tpl::configure('cache_dir', 'cache/template/'); Tpl::configure('path_replace', false); diff --git a/mine.php b/mine.php index df38b09..9a57ce4 100644 --- a/mine.php +++ b/mine.php @@ -22,7 +22,6 @@ function curl_post($url, $post) $ip = $_SERVER['REMOTE_ADDR']; $q = san($_GET['q']); -$worker = san($_GET['worker']); $max_dl = $pool_config['max_deadline']; @@ -34,7 +33,7 @@ function curl_post($url, $post) die("invalid wallet address. This address comes from a broken wallet file!"); } - //$worker = md5($miner.$_GET['worker'].$ip); + $worker = $_GET['worker']; $hr = intval($_GET['hashrate']); $gpuhr=intval($_GET['gpuhr']+$_GET['hrgpu']); $bind = [":id" => $worker, ":hr" => $hr, ":hr2" => $hr, ":miner" => $miner, ":ip" => $ip, ":ip2" => $ip, ":gpuhr"=>$gpuhr, ":gpuhr2"=>$gpuhr]; From d2268cbfa579c93ccdf1802e5f64a621e17b26cf Mon Sep 17 00:00:00 2001 From: Ario Date: Fri, 7 Dec 2018 17:02:26 +0000 Subject: [PATCH 019/134] template --- index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.php b/index.php index 1049760..383f6a4 100755 --- a/index.php +++ b/index.php @@ -6,7 +6,7 @@ use Rain\Tpl; -Tpl::configure('tpl_dir', 'template2/'); +Tpl::configure('tpl_dir', 'template/'); Tpl::configure('debug', true); Tpl::configure('cache_dir', 'cache/template/'); Tpl::configure('path_replace', false); From f0a57abe14d39f4e833915954d9f3260138cd499 Mon Sep 17 00:00:00 2001 From: Ario Date: Fri, 7 Dec 2018 23:47:53 +0000 Subject: [PATCH 020/134] global hashrate fix --- index.php | 9 +++++++-- template/account.html | 6 ++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/index.php b/index.php index 383f6a4..b584785 100755 --- a/index.php +++ b/index.php @@ -132,12 +132,17 @@ $r = $db->run("SELECT sum(hashrate) / count(id) AS cpuhr, sum(gpuhr) / count(id) as gpuhr FROM workers WHERE miner=:miner GROUP BY id", [":miner" => $id]); - $c = []; + $c['cpuhr'] = 0; + $c['gpuhr'] = 0; foreach ($r as $x) { $x['cpuhr'] = number_format($x['cpuhr'], 0); $x['gpuhr'] = number_format($x['gpuhr'], 0); - $c[] = $x; + $c['cpuhr'] = $c['cpuhr'] + $x['cpuhr']; + $c['gpuhr'] = $c['gpuhr'] + $x['gpuhr']; } + + var_dump($c); + $tpl->assign("hashrate", $c); diff --git a/template/account.html b/template/account.html index c5562a6..ca31611 100755 --- a/template/account.html +++ b/template/account.html @@ -11,19 +11,17 @@ - {loop="$hashrate"} - + - + - {/loop} {loop="$account"} From 6ca50ce0d9c21e30bf0c9dee8e57b10860c9dc8b Mon Sep 17 00:00:00 2001 From: Ario Date: Fri, 7 Dec 2018 23:49:02 +0000 Subject: [PATCH 021/134] remove var_dump :) --- index.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/index.php b/index.php index b584785..4f3a29f 100755 --- a/index.php +++ b/index.php @@ -140,9 +140,7 @@ $c['cpuhr'] = $c['cpuhr'] + $x['cpuhr']; $c['gpuhr'] = $c['gpuhr'] + $x['gpuhr']; } - - var_dump($c); - + $tpl->assign("hashrate", $c); From 845f71a16de68f71be388a30556c4e6156d528c6 Mon Sep 17 00:00:00 2001 From: Ario Date: Sat, 8 Dec 2018 00:04:23 +0000 Subject: [PATCH 022/134] gpu hashrate bug fix --- index.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/index.php b/index.php index 4f3a29f..49fdde4 100755 --- a/index.php +++ b/index.php @@ -135,12 +135,10 @@ $c['cpuhr'] = 0; $c['gpuhr'] = 0; foreach ($r as $x) { - $x['cpuhr'] = number_format($x['cpuhr'], 0); - $x['gpuhr'] = number_format($x['gpuhr'], 0); $c['cpuhr'] = $c['cpuhr'] + $x['cpuhr']; $c['gpuhr'] = $c['gpuhr'] + $x['gpuhr']; } - + $tpl->assign("hashrate", $c); From c67bbc4107751da32aa66b192a426fed6a926930 Mon Sep 17 00:00:00 2001 From: pxgamer Date: Mon, 10 Dec 2018 10:36:14 +0000 Subject: [PATCH 023/134] Update index to use a short ternary operator --- index.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/index.php b/index.php index 49fdde4..2f02219 100755 --- a/index.php +++ b/index.php @@ -78,11 +78,11 @@ $tpl->assign("gpu_ext",$total_gpu_ext); $tpl->assign("total_gpu",$total_gpu_text); - $agem = time(); + $agem = time(); $agem = $current['date']; - $agem = ( time() - $current['date']) ; - + $agem = (time() - $current['date']); + $tpl->assign("avg_hr", $avg_hr); $tpl->assign("hr_ext", $total_hr_ext); $tpl->assign("total_hr", $total_hr_text); @@ -95,8 +95,8 @@ $tpl->assign("shares", $shares); $tpl->assign("historic", $historic); $tpl->assign("difficulty", 200000000 - $current['difficulty']); - if ($current['height'] % 2) $blocktype = "GPU"; else $blocktype = "CPU"; - $tpl->assign("blocktype", $blocktype); + $blocktype = ($current['height'] % 2) ? 'GPU' : 'CPU'; + $tpl->assign("blocktype", $blocktype); $tpl->assign("agem", $agem); @@ -110,7 +110,7 @@ $x['gpuhr'] = number_format($x['gpuhr'], 0); $x['updated'] = date('Y/m/d H:i:s', $x['updated']); - + $b[] = $x; } $tpl->assign("workers", $b); From bcd8528c3c68fd4f4ec6dced53f49658e997fdbf Mon Sep 17 00:00:00 2001 From: pxgamer Date: Mon, 10 Dec 2018 10:38:12 +0000 Subject: [PATCH 024/134] Update poolsanity to use a short ternary operator --- poolsanity.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/poolsanity.php b/poolsanity.php index afa00d5..4b6cf6b 100644 --- a/poolsanity.php +++ b/poolsanity.php @@ -64,9 +64,8 @@ function shut_down() } - if ($current % 2) $max_dl = $pool_config['max_deadline_gpu']; else $max_dl = $pool_config['max_deadline']; + $max_dl = ($current % 2) ? $pool_config['max_deadline_gpu'] : $pool_config['max_deadline']; - $cache_file = "cache/info.txt"; $f = file_get_contents($pool_config['node_url']."/mine.php?q=info"); From 5993738c11744f2e125288d0a08db328bb23f7fc Mon Sep 17 00:00:00 2001 From: pxgamer Date: Tue, 11 Dec 2018 11:42:29 +0000 Subject: [PATCH 025/134] Update index to follow PSR-2 --- index.php | 55 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/index.php b/index.php index 49fdde4..1521f0f 100755 --- a/index.php +++ b/index.php @@ -61,28 +61,27 @@ $total_hr_ext = "H/s"; } - $total_hr=$db->single("SELECT val FROM info WHERE id='total_gpu_hr'"); + $total_hr = $db->single("SELECT val FROM info WHERE id='total_gpu_hr'"); - if($total_hr>=1000000){ - $total_gpu_text=number_format($total_hr/1000000,2); - $total_gpu_ext="MH/s"; - } - elseif($total_hr>1000&&$total_hr<1000000) { - $total_gpu_text=number_format($total_hr/1000,2); - $total_gpu_ext="KH/s"; + if ($total_hr >= 1000000) { + $total_gpu_text = number_format($total_hr / 1000000, 2); + $total_gpu_ext = "MH/s"; + } elseif ($total_hr > 1000 && $total_hr < 1000000) { + $total_gpu_text = number_format($total_hr / 1000, 2); + $total_gpu_ext = "KH/s"; } else { - $total_gpu_text=number_format($total_hr)." H/s"; - $total_gpu_ext="H/s"; + $total_gpu_text = number_format($total_hr)." H/s"; + $total_gpu_ext = "H/s"; } - $tpl->assign("gpu_ext",$total_gpu_ext); - $tpl->assign("total_gpu",$total_gpu_text); + $tpl->assign("gpu_ext", $total_gpu_ext); + $tpl->assign("total_gpu", $total_gpu_text); - $agem = time(); + $agem = time(); $agem = $current['date']; - $agem = ( time() - $current['date']) ; - + $agem = (time() - $current['date']); + $tpl->assign("avg_hr", $avg_hr); $tpl->assign("hr_ext", $total_hr_ext); $tpl->assign("total_hr", $total_hr_text); @@ -95,28 +94,34 @@ $tpl->assign("shares", $shares); $tpl->assign("historic", $historic); $tpl->assign("difficulty", 200000000 - $current['difficulty']); - if ($current['height'] % 2) $blocktype = "GPU"; else $blocktype = "CPU"; - $tpl->assign("blocktype", $blocktype); + if ($current['height'] % 2) { + $blocktype = "GPU"; + } else { + $blocktype = "CPU"; + } + $tpl->assign("blocktype", $blocktype); $tpl->assign("agem", $agem); $tpl->draw("index"); } elseif ($q == 'acc') { - - $r = $db->run("SELECT concat(id) AS id, sum(hashrate) AS hashrate, sum(gpuhr) as gpuhr, updated FROM workers WHERE miner=:miner GROUP BY id", [":miner" => $id] ); + $r = $db->run( + "SELECT concat(id) AS id, sum(hashrate) AS hashrate, sum(gpuhr) as gpuhr, updated FROM workers WHERE miner=:miner GROUP BY id", + [":miner" => $id] + ); $b = []; foreach ($r as $x) { $x['hashrate'] = number_format($x['hashrate'], 0); $x['gpuhr'] = number_format($x['gpuhr'], 0); $x['updated'] = date('Y/m/d H:i:s', $x['updated']); - + $b[] = $x; } $tpl->assign("workers", $b); - $r = $db->run("SELECT * FROM miners WHERE id=:miner", [":miner" => $id] ); + $r = $db->run("SELECT * FROM miners WHERE id=:miner", [":miner" => $id]); $b = []; foreach ($r as $x) { $x['hashrate'] = number_format($x['hashrate'], 0); @@ -125,13 +130,16 @@ $x['pending'] = number_format($x['pending'], 2); $x['total_paid'] = number_format($x['total_paid'], 2); - $x['updated'] = date('Y/m/d H:i:s', $x['updated']); + $x['updated'] = date('Y/m/d H:i:s', $x['updated']); $b[] = $x; } $tpl->assign("account", $b); - $r = $db->run("SELECT sum(hashrate) / count(id) AS cpuhr, sum(gpuhr) / count(id) as gpuhr FROM workers WHERE miner=:miner GROUP BY id", [":miner" => $id]); + $r = $db->run( + "SELECT sum(hashrate) / count(id) AS cpuhr, sum(gpuhr) / count(id) as gpuhr FROM workers WHERE miner=:miner GROUP BY id", + [":miner" => $id] + ); $c['cpuhr'] = 0; $c['gpuhr'] = 0; foreach ($r as $x) { @@ -143,7 +151,6 @@ $tpl->draw("account"); - } elseif ($q == "blocks") { $r = $db->run("SELECT * FROM blocks ORDER by height DESC LIMIT 100"); $b = []; From 7b5eda96624d24aebdc7a94761ed8ad14afdf488 Mon Sep 17 00:00:00 2001 From: pxgamer Date: Tue, 11 Dec 2018 11:42:45 +0000 Subject: [PATCH 026/134] Update manualpayment-sendall to follow PSR-2 --- manualpayment-sendall.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/manualpayment-sendall.php b/manualpayment-sendall.php index 745f0eb..02a93d9 100644 --- a/manualpayment-sendall.php +++ b/manualpayment-sendall.php @@ -49,8 +49,8 @@ function pay_post($url, $data = []) 'http' => [ 'timeout' => "300", - 'method' => 'POST', - 'header' => 'Content-type: application/x-www-form-urlencoded', + 'method' => 'POST', + 'header' => 'Content-type: application/x-www-form-urlencoded', 'content' => $postdata, ], ]; @@ -130,12 +130,12 @@ function pay_post($url, $data = []) $private_key = $pool_config['private_key']; $res = pay_post("/api.php?q=send", [ - "dst" => $x['address'], - "val" => $val, + "dst" => $x['address'], + "val" => $val, "private_key" => $private_key, - "public_key" => $public_key, - "version" => 1, - "message" => $pool_config['payout_message'] + "public_key" => $public_key, + "version" => 1, + "message" => $pool_config['payout_message'], ]); echo "$val\n"; echo "$x[address]\n"; @@ -148,9 +148,9 @@ function pay_post($url, $data = []) $db->run( "UPDATE payments SET txn=:txn, done=1 WHERE address=:address AND height<:h AND done=0 AND height>=:h2", [ - ":h" => $current - 10, - ":h2" => $current - $blocks_paid, - ":txn" => $res['data'], + ":h" => $current - 10, + ":h2" => $current - $blocks_paid, + ":txn" => $res['data'], ":address" => $x['address'], ] ); From d94b20bab8c379cbc1af7ba4db668351e8172141 Mon Sep 17 00:00:00 2001 From: pxgamer Date: Tue, 11 Dec 2018 11:43:36 +0000 Subject: [PATCH 027/134] Update mine to follow PSR-2 --- mine.php | 45 ++++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/mine.php b/mine.php index 9a57ce4..d7a3c95 100644 --- a/mine.php +++ b/mine.php @@ -8,10 +8,10 @@ function curl_post($url, $post) curl_setopt_array($curl, [ CURLOPT_RETURNTRANSFER => 1, CURLOPT_CONNECTTIMEOUT => 5, - CURLOPT_TIMEOUT => 20, - CURLOPT_URL => $url, - CURLOPT_POST => 1, - CURLOPT_POSTFIELDS => $post, + CURLOPT_TIMEOUT => 20, + CURLOPT_URL => $url, + CURLOPT_POST => 1, + CURLOPT_POSTFIELDS => $post, ]); $resp = curl_exec($curl); @@ -35,8 +35,17 @@ function curl_post($url, $post) $worker = $_GET['worker']; $hr = intval($_GET['hashrate']); - $gpuhr=intval($_GET['gpuhr']+$_GET['hrgpu']); - $bind = [":id" => $worker, ":hr" => $hr, ":hr2" => $hr, ":miner" => $miner, ":ip" => $ip, ":ip2" => $ip, ":gpuhr"=>$gpuhr, ":gpuhr2"=>$gpuhr]; + $gpuhr = intval($_GET['gpuhr'] + $_GET['hrgpu']); + $bind = [ + ":id" => $worker, + ":hr" => $hr, + ":hr2" => $hr, + ":miner" => $miner, + ":ip" => $ip, + ":ip2" => $ip, + ":gpuhr" => $gpuhr, + ":gpuhr2" => $gpuhr, + ]; $db->run( "INSERT into workers SET id=:id, hashrate=:hr,updated=UNIX_TIMESTAMP(), miner=:miner, ip=:ip, gpuhr=:gpuhr ON DUPLICATE KEY UPDATE updated=UNIX_TIMESTAMP(), hashrate=:hr2, ip=:ip2, gpuhr=:gpuhr2", $bind @@ -77,7 +86,9 @@ function curl_post($url, $post) $argon2 = '$argon2i$v=19$m=524288,t=1,p=1'.$argon; - if($g['data']['height']>=80000&&$g['data']['height']%2!=0) $argon2='$argon2i$v=19$m=16384,t=4,p=4'.$argon; + if ($g['data']['height'] >= 80000 && $g['data']['height'] % 2 != 0) { + $argon2 = '$argon2i$v=19$m=16384,t=4,p=4'.$argon; + } $base = "$public_key-$nonce-".$g['data']['block']."-".$g['data']['difficulty']; @@ -104,18 +115,18 @@ function curl_post($url, $post) $private_key = $pool_config['private_key']; $postdata = http_build_query( [ - 'argon' => $argon, - 'nonce' => $nonce, + 'argon' => $argon, + 'nonce' => $nonce, 'private_key' => $private_key, - 'public_key' => $public_key, + 'public_key' => $public_key, ] ); $opts = [ 'http' => [ - 'method' => 'POST', - 'header' => 'Content-type: application/x-www-form-urlencoded', + 'method' => 'POST', + 'header' => 'Content-type: application/x-www-form-urlencoded', 'content' => $postdata, 'timeout' => 120, ], @@ -165,15 +176,15 @@ function curl_post($url, $post) ); } $db->run("INSERT into payments SET address=:to, block=:bl, height=:height, val=:val, txn='',done=0", [ - ":val" => $original_reward * $pool_config['fee'], + ":val" => $original_reward * $pool_config['fee'], ":height" => $bl['height'], - ":bl" => $bl['id'], - ":to" => $pool_config['fee_address'], + ":bl" => $bl['id'], + ":to" => $pool_config['fee_address'], ]); $db->run("INSERT IGNORE into blocks SET reward=:reward, id=:id, height=:height, miner=:miner", [ - ":id" => $bl['id'], - ":miner" => $address, + ":id" => $bl['id'], + ":miner" => $address, ":height" => $bl['height'], ":reward" => $original_reward, ]); From 0f76e57ca5f2f46fbe4f43e6dedcbc800d6f9a05 Mon Sep 17 00:00:00 2001 From: pxgamer Date: Tue, 11 Dec 2018 11:43:53 +0000 Subject: [PATCH 028/134] Update payments to follow PSR-2 --- payments.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/payments.php b/payments.php index 6c32fec..999969e 100644 --- a/payments.php +++ b/payments.php @@ -49,8 +49,8 @@ function pay_post($url, $data = []) 'http' => [ 'timeout' => "300", - 'method' => 'POST', - 'header' => 'Content-type: application/x-www-form-urlencoded', + 'method' => 'POST', + 'header' => 'Content-type: application/x-www-form-urlencoded', 'content' => $postdata, ], ]; @@ -130,12 +130,12 @@ function pay_post($url, $data = []) $private_key = $pool_config['private_key']; $res = pay_post("/api.php?q=send", [ - "dst" => $x['address'], - "val" => $val, + "dst" => $x['address'], + "val" => $val, "private_key" => $private_key, - "public_key" => $public_key, - "version" => 1, - "message" => $pool_config['payout_message'] + "public_key" => $public_key, + "version" => 1, + "message" => $pool_config['payout_message'], ]); echo "$val\n"; echo "$x[address]\n"; @@ -148,9 +148,9 @@ function pay_post($url, $data = []) $db->run( "UPDATE payments SET txn=:txn, done=1 WHERE address=:address AND height<:h AND done=0 AND height>=:h2", [ - ":h" => $current - 10, - ":h2" => $current - $blocks_paid, - ":txn" => $res['data'], + ":h" => $current - 10, + ":h2" => $current - $blocks_paid, + ":txn" => $res['data'], ":address" => $x['address'], ] ); From fb21b43d7544a27db77266dd3f3873df56cf6c96 Mon Sep 17 00:00:00 2001 From: pxgamer Date: Tue, 11 Dec 2018 11:44:06 +0000 Subject: [PATCH 029/134] Update poolsanity to follow PSR-2 --- poolsanity.php | 60 +++++++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/poolsanity.php b/poolsanity.php index afa00d5..9fc770f 100644 --- a/poolsanity.php +++ b/poolsanity.php @@ -45,43 +45,49 @@ function shut_down() $db->run("UPDATE miners SET historic=historic*0.95+shares, shares=0,bestdl=1000000"); $db->run("TRUNCATE table nonces"); - $r=$db->run("SELECT * FROM miners WHERE historic>0"); - $total_hr=0; - $total_gpu=0; - foreach($r as $x){ - $thr=$db->row("SELECT SUM(hashrate) as cpu, SUM(gpuhr) as gpu FROM workers WHERE miner=:m AND updated>UNIX_TIMESTAMP()-3600",array(":m"=>$x['id'])); - if($x['historic']/$thr['cpu']<2||$x['historic']/$thr['gpu']<2) { - $thr['cpu']=0; - $thr['gpu']=0; - echo "$x[id] [$x[historic]] -> ".$x['historic']/$thr[cpu]."\n"; - } - $total_hr+=$thr['cpu']; - $total_gpu+=$thr['gpu']; - } - echo "Total hr: $total_hr\n"; - $db->run("UPDATE info SET val=:thr WHERE id='total_hash_rate'",array(":thr"=>$total_hr)); - $db->run("UPDATE info SET val=:thr WHERE id='total_gpu_hr'",array(":thr"=>$total_gpu)); + $r = $db->run("SELECT * FROM miners WHERE historic>0"); + $total_hr = 0; + $total_gpu = 0; + foreach ($r as $x) { + $thr = $db->row( + "SELECT SUM(hashrate) as cpu, SUM(gpuhr) as gpu FROM workers WHERE miner=:m AND updated>UNIX_TIMESTAMP()-3600", + [":m" => $x['id']] + ); + if ($x['historic'] / $thr['cpu'] < 2 || $x['historic'] / $thr['gpu'] < 2) { + $thr['cpu'] = 0; + $thr['gpu'] = 0; + echo "$x[id] [$x[historic]] -> ".$x['historic'] / $thr[cpu]."\n"; + } + $total_hr += $thr['cpu']; + $total_gpu += $thr['gpu']; + } + echo "Total hr: $total_hr\n"; + $db->run("UPDATE info SET val=:thr WHERE id='total_hash_rate'", [":thr" => $total_hr]); + $db->run("UPDATE info SET val=:thr WHERE id='total_gpu_hr'", [":thr" => $total_gpu]); + } + if ($current % 2) { + $max_dl = $pool_config['max_deadline_gpu']; + } else { + $max_dl = $pool_config['max_deadline']; } - if ($current % 2) $max_dl = $pool_config['max_deadline_gpu']; else $max_dl = $pool_config['max_deadline']; - $cache_file = "cache/info.txt"; $f = file_get_contents($pool_config['node_url']."/mine.php?q=info"); $g = json_decode($f, true); $res = [ - "difficulty" => $g['data']['difficulty'], - "block" => $g['data']['block'], - "height" => $g['data']['height'], - "public_key" => $pool_config['public_key'], - "limit" => $max_dl, - "recommendation"=> $g['data']['recommendation'], - "argon_mem" => $g['data']['argon_mem'], - "argon_threads" => $g['data']['argon_threads'], - "argon_time" => $g['data']['argon_time'], + "difficulty" => $g['data']['difficulty'], + "block" => $g['data']['block'], + "height" => $g['data']['height'], + "public_key" => $pool_config['public_key'], + "limit" => $max_dl, + "recommendation" => $g['data']['recommendation'], + "argon_mem" => $g['data']['argon_mem'], + "argon_threads" => $g['data']['argon_threads'], + "argon_time" => $g['data']['argon_time'], ]; $fin = json_encode(["status" => "ok", "data" => $res, "coin" => "arionum"]); echo "\n$fin\n"; From f4d973f50476faddaef91a6d5697a8a7cb9e8b64 Mon Sep 17 00:00:00 2001 From: pxgamer Date: Tue, 11 Dec 2018 11:44:59 +0000 Subject: [PATCH 030/134] Change to only ignore the root config --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index d79bed8..31e5b4d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ /vendor /cache/template /cache/info.txt -config.php +/config.php From ecbfb1e250646b0838dde4b75e1147864f7fc302 Mon Sep 17 00:00:00 2001 From: pxgamer Date: Tue, 11 Dec 2018 11:48:16 +0000 Subject: [PATCH 031/134] Update to use short syntax for incrementals --- index.php | 4 ++-- mine.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/index.php b/index.php index 1521f0f..252ac52 100755 --- a/index.php +++ b/index.php @@ -143,8 +143,8 @@ $c['cpuhr'] = 0; $c['gpuhr'] = 0; foreach ($r as $x) { - $c['cpuhr'] = $c['cpuhr'] + $x['cpuhr']; - $c['gpuhr'] = $c['gpuhr'] + $x['gpuhr']; + $c['cpuhr'] += $x['cpuhr']; + $c['gpuhr'] += $x['gpuhr']; } $tpl->assign("hashrate", $c); diff --git a/mine.php b/mine.php index d7a3c95..aeca27e 100644 --- a/mine.php +++ b/mine.php @@ -154,7 +154,7 @@ function curl_post($url, $post) $total_shares += $x['shares']; $total_historic += $x['historic']; } - $reward = $reward * (1 - $pool_config['fee']); + $reward *= (1 - $pool_config['fee']); $miner_reward = $pool_config['miner_reward'] * $reward; $historic_reward = $pool_config['historic_reward'] * $reward; $current_reward = $pool_config['current_reward'] * $reward; From c1e6764aa47018235d26fc027c4d2ccf8adc9463 Mon Sep 17 00:00:00 2001 From: pxgamer Date: Tue, 11 Dec 2018 11:49:45 +0000 Subject: [PATCH 032/134] Fix non-optimal if conditions --- mine.php | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/mine.php b/mine.php index aeca27e..98599b0 100644 --- a/mine.php +++ b/mine.php @@ -78,7 +78,7 @@ function curl_post($url, $post) $f = file_get_contents($pool_config['node_url']."/mine.php?q=info"); $g = json_decode($f, true); - if ($g['data']['height'] != $_POST['height'] && $_POST['height'] > 1) { + if ($_POST['height'] > 1 && $g['data']['height'] != $_POST['height']) { api_err('stale block'); } @@ -114,12 +114,7 @@ function curl_post($url, $post) if ($result > 0 && $result <= 240) { $private_key = $pool_config['private_key']; $postdata = http_build_query( - [ - 'argon' => $argon, - 'nonce' => $nonce, - 'private_key' => $private_key, - 'public_key' => $public_key, - ] + compact('argon', 'nonce', 'private_key', 'public_key') ); $opts = [ @@ -140,7 +135,7 @@ function curl_post($url, $post) $bl = $aro->row("SELECT * FROM blocks ORDER by height DESC LIMIT 1"); $added = $db->single("SELECT COUNT(1) FROM blocks WHERE id=:id", [":id" => $bl['id']]); - if ($bl['generator'] == $pool_config['address'] && $added == 0) { + if ($added == 0 && $bl['generator'] == $pool_config['address']) { $reward = $aro->single( "SELECT val FROM transactions WHERE block=:bl AND message='' AND version=0", [":bl" => $bl['id']] From dd25447b00a2cfb8eb02cc5222ceb9a4bd14ca49 Mon Sep 17 00:00:00 2001 From: pxgamer Date: Tue, 11 Dec 2018 11:50:53 +0000 Subject: [PATCH 033/134] Optimise one-time-use variable usage --- composer.json | 1 + manualpayment-sendall.php | 3 +-- payments.php | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index df233e2..0792226 100644 --- a/composer.json +++ b/composer.json @@ -6,6 +6,7 @@ "php": "^7.2", "ext-bcmath": "*", "ext-gmp": "*", + "ext-json": "*", "ext-openssl": "*", "rain/raintpl": "^3.1" }, diff --git a/manualpayment-sendall.php b/manualpayment-sendall.php index 02a93d9..49d83d1 100644 --- a/manualpayment-sendall.php +++ b/manualpayment-sendall.php @@ -58,8 +58,7 @@ function pay_post($url, $data = []) $context = stream_context_create($opts); $result = file_get_contents($peer.$url, false, $context); - $res = json_decode($result, true); - return $res; + return json_decode($result, true); } $pool_config['min_payout'] = 0; diff --git a/payments.php b/payments.php index 999969e..41b7a20 100644 --- a/payments.php +++ b/payments.php @@ -58,8 +58,7 @@ function pay_post($url, $data = []) $context = stream_context_create($opts); $result = file_get_contents($peer.$url, false, $context); - $res = json_decode($result, true); - return $res; + return json_decode($result, true); } From cb1cb2f31b818a61763390b197a4c896015aed89 Mon Sep 17 00:00:00 2001 From: pxgamer Date: Tue, 11 Dec 2018 11:51:38 +0000 Subject: [PATCH 034/134] Fix redundant if/else sequences --- mine.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/mine.php b/mine.php index 98599b0..4e7e0d2 100644 --- a/mine.php +++ b/mine.php @@ -56,7 +56,9 @@ function curl_post($url, $post) readfile("cache/info.txt"); exit; -} elseif ($q == "submitNonce") { +} + +if ($q == "submitNonce") { $reject = $db->single("SELECT COUNT(1) FROM rejects WHERE ip=:ip AND data>UNIX_TIMESTAMP()-20", [":ip" => $ip]); if ($reject == 1) { api_err("rejected"); @@ -212,6 +214,6 @@ function curl_post($url, $post) } api_err("rejected - block changed"); -} else { - api_err("invalid command"); } + +api_err("invalid command"); \ No newline at end of file From 080d444ae0020037168da95ddcaaf7d98fe0b8a3 Mon Sep 17 00:00:00 2001 From: pxgamer Date: Tue, 11 Dec 2018 11:52:05 +0000 Subject: [PATCH 035/134] Update to use the PHP_SAPI constant The PHP_SAPI constant is much faster to use than the function. --- manualpayment-sendall.php | 2 +- payments.php | 2 +- poolsanity.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/manualpayment-sendall.php b/manualpayment-sendall.php index 49d83d1..624ff74 100644 --- a/manualpayment-sendall.php +++ b/manualpayment-sendall.php @@ -28,7 +28,7 @@ function shut_down() ############################################### set_time_limit(0); -if (php_sapi_name() !== 'cli') { +if (PHP_SAPI !== 'cli') { die("This should only be run as cli"); } diff --git a/payments.php b/payments.php index 41b7a20..f894aab 100644 --- a/payments.php +++ b/payments.php @@ -28,7 +28,7 @@ function shut_down() ############################################### set_time_limit(0); -if (php_sapi_name() !== 'cli') { +if (PHP_SAPI !== 'cli') { die("This should only be run as cli"); } diff --git a/poolsanity.php b/poolsanity.php index 9fc770f..8830b93 100644 --- a/poolsanity.php +++ b/poolsanity.php @@ -31,7 +31,7 @@ function shut_down() set_time_limit(0); -if (php_sapi_name() !== 'cli') { +if (PHP_SAPI !== 'cli') { die("This should only be run as cli"); } From 2efa06a7b1f8f13f934a9f89d6d51515e949e29e Mon Sep 17 00:00:00 2001 From: pxgamer Date: Tue, 11 Dec 2018 11:53:06 +0000 Subject: [PATCH 036/134] Use type casting instead of `*val` functions --- mine.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mine.php b/mine.php index 4e7e0d2..6673ddd 100644 --- a/mine.php +++ b/mine.php @@ -34,8 +34,8 @@ function curl_post($url, $post) } $worker = $_GET['worker']; - $hr = intval($_GET['hashrate']); - $gpuhr = intval($_GET['gpuhr'] + $_GET['hrgpu']); + $hr = (int)$_GET['hashrate']; + $gpuhr = (int)($_GET['gpuhr'] + $_GET['hrgpu']); $bind = [ ":id" => $worker, ":hr" => $hr, @@ -196,11 +196,11 @@ function curl_post($url, $post) $db->run( "INSERT INTO miners SET id=:id, shares=shares+:sh, updated=UNIX_TIMESTAMP(),bestdl=:bdl ON DUPLICATE KEY UPDATE shares=shares+:sh2, updated=UNIX_TIMESTAMP()", - [":id" => $address, ":sh" => $share, ":sh2" => $share, ":bdl" => intval($result)] + [":id" => $address, ":sh" => $share, ":sh2" => $share, ":bdl" => (int)$result] ); $db->run( "UPDATE miners SET bestdl=:bdl WHERE id=:id AND bestdl>:bdl2", - [":id" => $address, ":bdl" => intval($result), ":bdl2" => intval($result)] + [":id" => $address, ":bdl" => (int)$result, ":bdl2" => (int)$result] ); api_echo("accepted"); } else { From 147e415211cc73d813b52226df7fb555131ba422 Mon Sep 17 00:00:00 2001 From: pxgamer Date: Tue, 11 Dec 2018 11:54:36 +0000 Subject: [PATCH 037/134] Update variable that is immediately overridden --- index.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/index.php b/index.php index 252ac52..2bfea5c 100755 --- a/index.php +++ b/index.php @@ -77,9 +77,6 @@ $tpl->assign("gpu_ext", $total_gpu_ext); $tpl->assign("total_gpu", $total_gpu_text); - $agem = time(); - $agem = $current['date']; - $agem = (time() - $current['date']); $tpl->assign("avg_hr", $avg_hr); From bfe098435a38084cee144c994e9fea50c892bf4b Mon Sep 17 00:00:00 2001 From: pxgamer Date: Tue, 11 Dec 2018 11:57:35 +0000 Subject: [PATCH 038/134] Fix untrusted require/include usage These are dependent on the environment path, therefore this has been updated to use the `__DIR__` constant. --- db.php | 16 ++++++++-------- index.php | 3 ++- manualpayment-sendall.php | 2 +- mine.php | 3 ++- payments.php | 2 +- poolsanity.php | 5 ++--- 6 files changed, 16 insertions(+), 15 deletions(-) diff --git a/db.php b/db.php index 8422090..f0eb0e9 100644 --- a/db.php +++ b/db.php @@ -1,20 +1,20 @@ Date: Tue, 11 Dec 2018 12:00:42 +0000 Subject: [PATCH 039/134] Update to use strict type comparisons --- index.php | 18 +++++++++--------- manualpayment-sendall.php | 6 +++--- mine.php | 22 +++++++++++----------- payments.php | 8 ++++---- poolsanity.php | 2 +- 5 files changed, 28 insertions(+), 28 deletions(-) diff --git a/index.php b/index.php index a5c2989..ca1a3f4 100755 --- a/index.php +++ b/index.php @@ -18,7 +18,7 @@ $tpl->assign("id", $id); $tpl->draw('header'); -if ($q == "") { +if ($q === '') { $current = $aro->row("SELECT * FROM blocks ORDER by height DESC LIMIT 1"); $last_won = $db->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); @@ -48,7 +48,7 @@ $total_hr = $db->single("SELECT val FROM info WHERE id='total_hash_rate'"); $avg_hr = floor($total_hr / $miners); - if ($miners == 0) { + if ($miners === 0) { $avg_hr = 0; } if ($total_hr >= 1000000) { @@ -102,7 +102,7 @@ $tpl->draw("index"); -} elseif ($q == 'acc') { +} elseif ($q === 'acc') { $r = $db->run( "SELECT concat(id) AS id, sum(hashrate) AS hashrate, sum(gpuhr) as gpuhr, updated FROM workers WHERE miner=:miner GROUP BY id", [":miner" => $id] @@ -149,7 +149,7 @@ $tpl->draw("account"); -} elseif ($q == "blocks") { +} elseif ($q === "blocks") { $r = $db->run("SELECT * FROM blocks ORDER by height DESC LIMIT 100"); $b = []; foreach ($r as $x) { @@ -159,21 +159,21 @@ $tpl->assign("blocks", $b); $tpl->draw("blocks"); -} elseif ($q == "payments") { +} elseif ($q === "payments") { $r = $db->run("SELECT id,address,val,done,txn FROM payments ORDER by id DESC LIMIT 5000"); $b = []; foreach ($r as $x) { - if ($x['done'] == 0) { - $x['txn'] = "Pending"; + if ($x['done'] === 0) { + $x['txn'] = 'Pending'; } $b[] = $x; } $tpl->assign("payments", $b); $tpl->draw("payments"); -} elseif ($q == "benchmarks") { +} elseif ($q === "benchmarks") { $tpl->draw("benchmarks"); -} elseif ($q == "info") { +} elseif ($q === "info") { $tpl->draw("info"); } diff --git a/manualpayment-sendall.php b/manualpayment-sendall.php index 9ed7f0a..a3bc4cd 100644 --- a/manualpayment-sendall.php +++ b/manualpayment-sendall.php @@ -88,7 +88,7 @@ function pay_post($url, $data = []) "SELECT DISTINCT block FROM payments WHERE height<:h AND done=0 AND height>=:h2", [":h" => $current - 10, ":h2" => $current - $blocks_paid] ); -if (count($r) == 0) { +if (count($r) === 0) { die("No payments pending\n"); } @@ -99,7 +99,7 @@ function pay_post($url, $data = []) foreach ($r as $x) { echo "Checking $x[block]\n"; $s = $aro->single("SELECT COUNT(1) FROM blocks WHERE id=:id", [":id" => $x['block']]); - if ($s == 0) { + if ($s === 0) { $db->run("DELETE FROM blocks WHERE id=:id", [":id" => $x['block']]); $db->run("DELETE FROM payments WHERE block=:id", [":id" => $x['block']]); echo "Deleted block: $x[block]\n"; @@ -138,7 +138,7 @@ function pay_post($url, $data = []) ]); echo "$val\n"; echo "$x[address]\n"; - if ($res['status'] != "ok") { + if ($res['status'] !== "ok") { print("ERROR: $res[data]\n"); } else { $total_paid += $x['v']; diff --git a/mine.php b/mine.php index 7a27011..51ca7b1 100644 --- a/mine.php +++ b/mine.php @@ -26,11 +26,11 @@ function curl_post($url, $post) $max_dl = $pool_config['max_deadline']; -if ($q == "info") { +if ($q === "info") { $time = time(); if ($_GET['hashrate'] > 0) { $miner = san($_GET['address']); - if ($miner == '3uj7kyCcy5q6A1s1DQkgb58zXz6mLsjHpaoEkYxL6TjzkRP7muGZaXeGNcqk1bTgpQTVDuwPoKh49dGQn8bMwdBZ' || $miner == '4EtWPLwbUAs2JNnqb8yprvAKYCfA4dU3bJTRm2KjnM6f811MAh9qr7wrHABCHrnWPTdgmEF8iXqRBu2XSPHMuHnR') { + if ($miner === '3uj7kyCcy5q6A1s1DQkgb58zXz6mLsjHpaoEkYxL6TjzkRP7muGZaXeGNcqk1bTgpQTVDuwPoKh49dGQn8bMwdBZ' || $miner === '4EtWPLwbUAs2JNnqb8yprvAKYCfA4dU3bJTRm2KjnM6f811MAh9qr7wrHABCHrnWPTdgmEF8iXqRBu2XSPHMuHnR') { die("invalid wallet address. This address comes from a broken wallet file!"); } @@ -59,9 +59,9 @@ function curl_post($url, $post) exit; } -if ($q == "submitNonce") { +if ($q === "submitNonce") { $reject = $db->single("SELECT COUNT(1) FROM rejects WHERE ip=:ip AND data>UNIX_TIMESTAMP()-20", [":ip" => $ip]); - if ($reject == 1) { + if ($reject === 1) { api_err("rejected"); } @@ -70,7 +70,7 @@ function curl_post($url, $post) $address = san($_POST['address']); $chk = $db->single("SELECT count(1) FROM nonces WHERE nonce=:nonce", [":nonce" => $nonce]); - if ($chk != 0) { + if ($chk !== 0) { $db->run("INSERT into abusers SET miner=:miner, nonce=:nonce", [":miner" => $address, ":nonce" => $nonce]); api_err("duplicate"); exit; @@ -81,7 +81,7 @@ function curl_post($url, $post) $f = file_get_contents($pool_config['node_url']."/mine.php?q=info"); $g = json_decode($f, true); - if ($_POST['height'] > 1 && $g['data']['height'] != $_POST['height']) { + if ($_POST['height'] > 1 && $g['data']['height'] !== $_POST['height']) { api_err('stale block'); } @@ -89,7 +89,7 @@ function curl_post($url, $post) $argon2 = '$argon2i$v=19$m=524288,t=1,p=1'.$argon; - if ($g['data']['height'] >= 80000 && $g['data']['height'] % 2 != 0) { + if ($g['data']['height'] >= 80000 && $g['data']['height'] % 2 !== 0) { $argon2 = '$argon2i$v=19$m=16384,t=4,p=4'.$argon; } @@ -134,16 +134,16 @@ function curl_post($url, $post) $res = file_get_contents($pool_config['node_url']."/mine.php?q=submitNonce", false, $context); $data = json_decode($res, true); - if ($data['status'] == "ok") { + if ($data['status'] === "ok") { $bl = $aro->row("SELECT * FROM blocks ORDER by height DESC LIMIT 1"); $added = $db->single("SELECT COUNT(1) FROM blocks WHERE id=:id", [":id" => $bl['id']]); - if ($added == 0 && $bl['generator'] == $pool_config['address']) { + if ($added === 0 && $bl['generator'] === $pool_config['address']) { $reward = $aro->single( "SELECT val FROM transactions WHERE block=:bl AND message='' AND version=0", [":bl" => $bl['id']] ); - if ($reward == 0) { + if ($reward === 0) { api_err("something went wrong"); } $original_reward = $reward; @@ -165,7 +165,7 @@ function curl_post($url, $post) if ($x['historic'] > 0) { $crw += ($x['historic'] / $total_historic) * $historic_reward; } - if ($x['id'] == $address) { + if ($x['id'] === $address) { $crw += $miner_reward; } $db->run( diff --git a/payments.php b/payments.php index eadc0ce..6fa32ef 100644 --- a/payments.php +++ b/payments.php @@ -66,7 +66,7 @@ function pay_post($url, $data = []) $min = date("i"); $blocks_paid = 500; -if ($hour == 10 && $min < 20) { +if ($hour === 10 && $min < 20) { $blocks_paid = 5000; } @@ -88,7 +88,7 @@ function pay_post($url, $data = []) "SELECT DISTINCT block FROM payments WHERE height<:h AND done=0 AND height>=:h2", [":h" => $current - 10, ":h2" => $current - $blocks_paid] ); -if (count($r) == 0) { +if (count($r) === 0) { die("No payments pending\n"); } @@ -99,7 +99,7 @@ function pay_post($url, $data = []) foreach ($r as $x) { echo "Checking $x[block]\n"; $s = $aro->single("SELECT COUNT(1) FROM blocks WHERE id=:id", [":id" => $x['block']]); - if ($s == 0) { + if ($s === 0) { $db->run("DELETE FROM blocks WHERE id=:id", [":id" => $x['block']]); $db->run("DELETE FROM payments WHERE block=:id", [":id" => $x['block']]); echo "Deleted block: $x[block]\n"; @@ -138,7 +138,7 @@ function pay_post($url, $data = []) ]); echo "$val\n"; echo "$x[address]\n"; - if ($res['status'] != "ok") { + if ($res['status'] !== "ok") { print("ERROR: $res[data]\n"); } else { $total_paid += $x['v']; diff --git a/poolsanity.php b/poolsanity.php index 61f330c..a1ec87c 100644 --- a/poolsanity.php +++ b/poolsanity.php @@ -39,7 +39,7 @@ function shut_down() while (1) { $ticks++; $ck = $aro->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); - if ($ck != $current && $ck) { + if ($ck !== $current && $ck) { $current = $ck; $db->run("UPDATE miners SET historic=historic*0.95+shares, shares=0,bestdl=1000000"); $db->run("TRUNCATE table nonces"); From 0aa62a94d60bbc2c6c3d6938cfa88dd96c605eba Mon Sep 17 00:00:00 2001 From: pxgamer Date: Tue, 11 Dec 2018 12:01:00 +0000 Subject: [PATCH 040/134] Remove unnecessary optional function parameters --- index.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/index.php b/index.php index ca1a3f4..78fd159 100755 --- a/index.php +++ b/index.php @@ -109,8 +109,8 @@ ); $b = []; foreach ($r as $x) { - $x['hashrate'] = number_format($x['hashrate'], 0); - $x['gpuhr'] = number_format($x['gpuhr'], 0); + $x['hashrate'] = number_format($x['hashrate']); + $x['gpuhr'] = number_format($x['gpuhr']); $x['updated'] = date('Y/m/d H:i:s', $x['updated']); @@ -122,8 +122,8 @@ $r = $db->run("SELECT * FROM miners WHERE id=:miner", [":miner" => $id]); $b = []; foreach ($r as $x) { - $x['hashrate'] = number_format($x['hashrate'], 0); - $x['gpuhr'] = number_format($x['gpuhr'], 0); + $x['hashrate'] = number_format($x['hashrate']); + $x['gpuhr'] = number_format($x['gpuhr']); $x['pending'] = number_format($x['pending'], 2); $x['total_paid'] = number_format($x['total_paid'], 2); From 3f1a7684ac24a742bb9376f7f3ca49f921ba7607 Mon Sep 17 00:00:00 2001 From: pxgamer Date: Tue, 11 Dec 2018 12:03:25 +0000 Subject: [PATCH 041/134] Standardise quote usage where possible --- config-sample.php | 2 +- index.php | 110 +++++++++++++++++++------------------- manualpayment-sendall.php | 82 ++++++++++++++-------------- mine.php | 106 ++++++++++++++++++------------------ payments.php | 82 ++++++++++++++-------------- poolsanity.php | 44 +++++++-------- 6 files changed, 213 insertions(+), 213 deletions(-) diff --git a/config-sample.php b/config-sample.php index 990cac5..9adb7e9 100644 --- a/config-sample.php +++ b/config-sample.php @@ -73,4 +73,4 @@ $pool_config['min_payout'] = 3; // The message included in payments -$pool_config['payout_message'] = ""; +$pool_config['payout_message'] = ''; diff --git a/index.php b/index.php index 78fd159..6178dbd 100755 --- a/index.php +++ b/index.php @@ -14,18 +14,18 @@ Tpl::configure('php_enabled', false); $tpl = new Tpl(); -$tpl->assign("q", $q); -$tpl->assign("id", $id); +$tpl->assign('q', $q); +$tpl->assign('id', $id); $tpl->draw('header'); if ($q === '') { - $current = $aro->row("SELECT * FROM blocks ORDER by height DESC LIMIT 1"); - $last_won = $db->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); + $current = $aro->row('SELECT * FROM blocks ORDER by height DESC LIMIT 1'); + $last_won = $db->single('SELECT height FROM blocks ORDER by height DESC LIMIT 1'); $total_shares = 0; $shares = []; - $r = $db->run("SELECT * FROM miners "); + $r = $db->run('SELECT * FROM miners '); $miners = count($r); $total_historic = 0; @@ -53,59 +53,59 @@ } if ($total_hr >= 1000000) { $total_hr_text = number_format($total_hr / 1000000, 2); - $total_hr_ext = "MH/s"; + $total_hr_ext = 'MH/s'; } elseif ($total_hr > 1000 && $total_hr < 1000000) { $total_hr_text = number_format($total_hr / 1000, 2); - $total_hr_ext = "KH/s"; + $total_hr_ext = 'KH/s'; } else { - $total_hr_text = number_format($total_hr)." H/s"; - $total_hr_ext = "H/s"; + $total_hr_text = number_format($total_hr).' H/s'; + $total_hr_ext = 'H/s'; } $total_hr = $db->single("SELECT val FROM info WHERE id='total_gpu_hr'"); if ($total_hr >= 1000000) { $total_gpu_text = number_format($total_hr / 1000000, 2); - $total_gpu_ext = "MH/s"; + $total_gpu_ext = 'MH/s'; } elseif ($total_hr > 1000 && $total_hr < 1000000) { $total_gpu_text = number_format($total_hr / 1000, 2); - $total_gpu_ext = "KH/s"; + $total_gpu_ext = 'KH/s'; } else { - $total_gpu_text = number_format($total_hr)." H/s"; - $total_gpu_ext = "H/s"; + $total_gpu_text = number_format($total_hr).' H/s'; + $total_gpu_ext = 'H/s'; } - $tpl->assign("gpu_ext", $total_gpu_ext); - $tpl->assign("total_gpu", $total_gpu_text); + $tpl->assign('gpu_ext', $total_gpu_ext); + $tpl->assign('total_gpu', $total_gpu_text); $agem = (time() - $current['date']); - $tpl->assign("avg_hr", $avg_hr); - $tpl->assign("hr_ext", $total_hr_ext); - $tpl->assign("total_hr", $total_hr_text); - $tpl->assign("miners", $miners); - $tpl->assign("total_shares", $total_shares); - $tpl->assign("total_historic", $total_historic); - $tpl->assign("height", $current['height']); - $tpl->assign("lastwon", $last_won); - $tpl->assign("total_paid", number_format($db->single("SELECT val FROM info WHERE id='total_paid'") / 1000000, 2)); - $tpl->assign("shares", $shares); - $tpl->assign("historic", $historic); - $tpl->assign("difficulty", 200000000 - $current['difficulty']); + $tpl->assign('avg_hr', $avg_hr); + $tpl->assign('hr_ext', $total_hr_ext); + $tpl->assign('total_hr', $total_hr_text); + $tpl->assign('miners', $miners); + $tpl->assign('total_shares', $total_shares); + $tpl->assign('total_historic', $total_historic); + $tpl->assign('height', $current['height']); + $tpl->assign('lastwon', $last_won); + $tpl->assign('total_paid', number_format($db->single("SELECT val FROM info WHERE id='total_paid'") / 1000000, 2)); + $tpl->assign('shares', $shares); + $tpl->assign('historic', $historic); + $tpl->assign('difficulty', 200000000 - $current['difficulty']); if ($current['height'] % 2) { - $blocktype = "GPU"; + $blocktype = 'GPU'; } else { - $blocktype = "CPU"; + $blocktype = 'CPU'; } - $tpl->assign("blocktype", $blocktype); - $tpl->assign("agem", $agem); + $tpl->assign('blocktype', $blocktype); + $tpl->assign('agem', $agem); - $tpl->draw("index"); + $tpl->draw('index'); } elseif ($q === 'acc') { $r = $db->run( - "SELECT concat(id) AS id, sum(hashrate) AS hashrate, sum(gpuhr) as gpuhr, updated FROM workers WHERE miner=:miner GROUP BY id", - [":miner" => $id] + 'SELECT concat(id) AS id, sum(hashrate) AS hashrate, sum(gpuhr) as gpuhr, updated FROM workers WHERE miner=:miner GROUP BY id', + [':miner' => $id] ); $b = []; foreach ($r as $x) { @@ -116,10 +116,10 @@ $b[] = $x; } - $tpl->assign("workers", $b); + $tpl->assign('workers', $b); - $r = $db->run("SELECT * FROM miners WHERE id=:miner", [":miner" => $id]); + $r = $db->run('SELECT * FROM miners WHERE id=:miner', [':miner' => $id]); $b = []; foreach ($r as $x) { $x['hashrate'] = number_format($x['hashrate']); @@ -131,12 +131,12 @@ $x['updated'] = date('Y/m/d H:i:s', $x['updated']); $b[] = $x; } - $tpl->assign("account", $b); + $tpl->assign('account', $b); $r = $db->run( - "SELECT sum(hashrate) / count(id) AS cpuhr, sum(gpuhr) / count(id) as gpuhr FROM workers WHERE miner=:miner GROUP BY id", - [":miner" => $id] + 'SELECT sum(hashrate) / count(id) AS cpuhr, sum(gpuhr) / count(id) as gpuhr FROM workers WHERE miner=:miner GROUP BY id', + [':miner' => $id] ); $c['cpuhr'] = 0; $c['gpuhr'] = 0; @@ -145,22 +145,22 @@ $c['gpuhr'] += $x['gpuhr']; } - $tpl->assign("hashrate", $c); + $tpl->assign('hashrate', $c); - $tpl->draw("account"); -} elseif ($q === "blocks") { - $r = $db->run("SELECT * FROM blocks ORDER by height DESC LIMIT 100"); + $tpl->draw('account'); +} elseif ($q === 'blocks') { + $r = $db->run('SELECT * FROM blocks ORDER by height DESC LIMIT 100'); $b = []; foreach ($r as $x) { $x['reward'] = number_format($x['reward'], 2); $b[] = $x; } - $tpl->assign("blocks", $b); - $tpl->draw("blocks"); -} elseif ($q === "payments") { - $r = $db->run("SELECT id,address,val,done,txn FROM payments ORDER by id DESC LIMIT 5000"); + $tpl->assign('blocks', $b); + $tpl->draw('blocks'); +} elseif ($q === 'payments') { + $r = $db->run('SELECT id,address,val,done,txn FROM payments ORDER by id DESC LIMIT 5000'); $b = []; foreach ($r as $x) { if ($x['done'] === 0) { @@ -169,14 +169,14 @@ $b[] = $x; } - $tpl->assign("payments", $b); - $tpl->draw("payments"); -} elseif ($q === "benchmarks") { - $tpl->draw("benchmarks"); -} elseif ($q === "info") { - $tpl->draw("info"); + $tpl->assign('payments', $b); + $tpl->draw('payments'); +} elseif ($q === 'benchmarks') { + $tpl->draw('benchmarks'); +} elseif ($q === 'info') { + $tpl->draw('info'); } $tpl = new Tpl(); -$tpl->assign("q", $q); -$tpl->draw("footer"); +$tpl->assign('q', $q); +$tpl->draw('footer'); diff --git a/manualpayment-sendall.php b/manualpayment-sendall.php index a3bc4cd..39904e2 100644 --- a/manualpayment-sendall.php +++ b/manualpayment-sendall.php @@ -24,12 +24,12 @@ function shut_down() echo "\n# ShutDown #\n"; } -register_shutdown_function("shut_down"); +register_shutdown_function('shut_down'); ############################################### set_time_limit(0); if (PHP_SAPI !== 'cli') { - die("This should only be run as cli"); + die('This should only be run as cli'); } require_once __DIR__.'/db.php'; @@ -41,14 +41,14 @@ function pay_post($url, $data = []) $postdata = http_build_query( [ 'data' => json_encode($data), - "coin" => " arionum", + 'coin' => ' arionum', ] ); $opts = [ 'http' => [ - 'timeout' => "300", + 'timeout' => '300', 'method' => 'POST', 'header' => 'Content-type: application/x-www-form-urlencoded', 'content' => $postdata, @@ -64,44 +64,44 @@ function pay_post($url, $data = []) $pool_config['min_payout'] = 0; -$hour = date("H"); -$min = date("i"); +$hour = date('H'); +$min = date('i'); $blocks_paid = 50000; echo "\n----------------------------------------------------------------------------------\n"; -$current = $aro->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); +$current = $aro->single('SELECT height FROM blocks ORDER by height DESC LIMIT 1'); echo "Current block $current\n"; -$db->run("DELETE FROM miners WHERE historic+shares<=20"); -$db->run("UPDATE miners SET gpuhr=(SELECT SUM(gpuhr) FROM workers WHERE miner=miners.id AND updated>UNIX_TIMESTAMP()-3600)"); -$db->run("UPDATE miners SET hashrate=(SELECT SUM(hashrate) FROM workers WHERE miner=miners.id AND updated>UNIX_TIMESTAMP()-3600)"); +$db->run('DELETE FROM miners WHERE historic+shares<=20'); +$db->run('UPDATE miners SET gpuhr=(SELECT SUM(gpuhr) FROM workers WHERE miner=miners.id AND updated>UNIX_TIMESTAMP()-3600)'); +$db->run('UPDATE miners SET hashrate=(SELECT SUM(hashrate) FROM workers WHERE miner=miners.id AND updated>UNIX_TIMESTAMP()-3600)'); $db->run( - "UPDATE miners SET pending=(SELECT SUM(val) FROM payments WHERE done=0 AND payments.address=miners.id AND height>=:h)", - [":h" => $current - $blocks_paid] + 'UPDATE miners SET pending=(SELECT SUM(val) FROM payments WHERE done=0 AND payments.address=miners.id AND height>=:h)', + [':h' => $current - $blocks_paid] ); $r = $db->run( - "SELECT DISTINCT block FROM payments WHERE height<:h AND done=0 AND height>=:h2", - [":h" => $current - 10, ":h2" => $current - $blocks_paid] + 'SELECT DISTINCT block FROM payments WHERE height<:h AND done=0 AND height>=:h2', + [':h' => $current - 10, ':h2' => $current - $blocks_paid] ); if (count($r) === 0) { die("No payments pending\n"); } -$db->run("DELETE FROM miners WHERE shares=0 AND historic=0 AND updatedrun("DELETE FROM workers WHERE updatedrun('DELETE FROM miners WHERE shares=0 AND historic=0 AND updatedrun('DELETE FROM workers WHERE updatedsingle("SELECT COUNT(1) FROM blocks WHERE id=:id", [":id" => $x['block']]); + $s = $aro->single('SELECT COUNT(1) FROM blocks WHERE id=:id', [':id' => $x['block']]); if ($s === 0) { - $db->run("DELETE FROM blocks WHERE id=:id", [":id" => $x['block']]); - $db->run("DELETE FROM payments WHERE block=:id", [":id" => $x['block']]); + $db->run('DELETE FROM blocks WHERE id=:id', [':id' => $x['block']]); + $db->run('DELETE FROM payments WHERE block=:id', [':id' => $x['block']]); echo "Deleted block: $x[block]\n"; } } @@ -109,8 +109,8 @@ function pay_post($url, $data = []) $total_paid = 0; $r = $db->run( - "SELECT SUM(val) as v, address FROM payments WHERE height<:h AND height>=:h2 AND done=0 GROUP by address", - [":h" => $current - 10, ":h2" => $current - $blocks_paid] + 'SELECT SUM(val) as v, address FROM payments WHERE height<:h AND height>=:h2 AND done=0 GROUP by address', + [':h' => $current - 10, ':h2' => $current - $blocks_paid] ); foreach ($r as $x) { if ($x['v'] < $pool_config['min_payout']) { @@ -123,37 +123,37 @@ function pay_post($url, $data = []) if ($fee > 10) { $fee = 10; } - $val = number_format($x['v'] - $fee, 8, ".", ""); + $val = number_format($x['v'] - $fee, 8, '.', ''); #$val=intval($val); $public_key = $pool_config['public_key']; $private_key = $pool_config['private_key']; - $res = pay_post("/api.php?q=send", [ - "dst" => $x['address'], - "val" => $val, - "private_key" => $private_key, - "public_key" => $public_key, - "version" => 1, - "message" => $pool_config['payout_message'], + $res = pay_post('/api.php?q=send', [ + 'dst' => $x['address'], + 'val' => $val, + 'private_key' => $private_key, + 'public_key' => $public_key, + 'version' => 1, + 'message' => $pool_config['payout_message'], ]); echo "$val\n"; echo "$x[address]\n"; - if ($res['status'] !== "ok") { + if ($res['status'] !== 'ok') { print("ERROR: $res[data]\n"); } else { $total_paid += $x['v']; echo "Transaction sent - $x[address] - $val! Transaction id: $res[data]\n"; $db->run( - "UPDATE payments SET txn=:txn, done=1 WHERE address=:address AND height<:h AND done=0 AND height>=:h2", + 'UPDATE payments SET txn=:txn, done=1 WHERE address=:address AND height<:h AND done=0 AND height>=:h2', [ - ":h" => $current - 10, - ":h2" => $current - $blocks_paid, - ":txn" => $res['data'], - ":address" => $x['address'], + ':h' => $current - 10, + ':h2' => $current - $blocks_paid, + ':txn' => $res['data'], + ':address' => $x['address'], ] ); - $db->run("UPDATE miners SET total_paid=total_paid + :h WHERE id=:p", [":h" => $x['v'], ":p" => $x['address']]); + $db->run('UPDATE miners SET total_paid=total_paid + :h WHERE id=:p', [':h' => $x['v'], ':p' => $x['address']]); echo "DB updated\n"; } } @@ -162,14 +162,14 @@ function pay_post($url, $data = []) $new = $old + $total_paid; echo "Total paid: $new\n"; -$db->run("UPDATE info SET val=:s WHERE id='total_paid'", [":s" => $new]); -$not = $db->single("SELECT SUM(val) FROM payments WHERE done=0"); +$db->run("UPDATE info SET val=:s WHERE id='total_paid'", [':s' => $new]); +$not = $db->single('SELECT SUM(val) FROM payments WHERE done=0'); echo "Pending balance: $not\n"; $db->run( - "UPDATE miners SET pending=(SELECT SUM(val) FROM payments WHERE done=0 AND payments.address=miners.id AND height>=:h)", - [":h" => $current - $blocks_paid] + 'UPDATE miners SET pending=(SELECT SUM(val) FROM payments WHERE done=0 AND payments.address=miners.id AND height>=:h)', + [':h' => $current - $blocks_paid] ); -$db->run("DELETE FROM payments WHERE done=1 AND height<:h", [":h" => $current - 1000]); +$db->run('DELETE FROM payments WHERE done=1 AND height<:h', [':h' => $current - 1000]); diff --git a/mine.php b/mine.php index 51ca7b1..6e362e8 100644 --- a/mine.php +++ b/mine.php @@ -26,59 +26,59 @@ function curl_post($url, $post) $max_dl = $pool_config['max_deadline']; -if ($q === "info") { +if ($q === 'info') { $time = time(); if ($_GET['hashrate'] > 0) { $miner = san($_GET['address']); if ($miner === '3uj7kyCcy5q6A1s1DQkgb58zXz6mLsjHpaoEkYxL6TjzkRP7muGZaXeGNcqk1bTgpQTVDuwPoKh49dGQn8bMwdBZ' || $miner === '4EtWPLwbUAs2JNnqb8yprvAKYCfA4dU3bJTRm2KjnM6f811MAh9qr7wrHABCHrnWPTdgmEF8iXqRBu2XSPHMuHnR') { - die("invalid wallet address. This address comes from a broken wallet file!"); + die('invalid wallet address. This address comes from a broken wallet file!'); } $worker = $_GET['worker']; $hr = (int)$_GET['hashrate']; $gpuhr = (int)($_GET['gpuhr'] + $_GET['hrgpu']); $bind = [ - ":id" => $worker, - ":hr" => $hr, - ":hr2" => $hr, - ":miner" => $miner, - ":ip" => $ip, - ":ip2" => $ip, - ":gpuhr" => $gpuhr, - ":gpuhr2" => $gpuhr, + ':id' => $worker, + ':hr' => $hr, + ':hr2' => $hr, + ':miner' => $miner, + ':ip' => $ip, + ':ip2' => $ip, + ':gpuhr' => $gpuhr, + ':gpuhr2' => $gpuhr, ]; $db->run( - "INSERT into workers SET id=:id, hashrate=:hr,updated=UNIX_TIMESTAMP(), miner=:miner, ip=:ip, gpuhr=:gpuhr ON DUPLICATE KEY UPDATE updated=UNIX_TIMESTAMP(), hashrate=:hr2, ip=:ip2, gpuhr=:gpuhr2", + 'INSERT into workers SET id=:id, hashrate=:hr,updated=UNIX_TIMESTAMP(), miner=:miner, ip=:ip, gpuhr=:gpuhr ON DUPLICATE KEY UPDATE updated=UNIX_TIMESTAMP(), hashrate=:hr2, ip=:ip2, gpuhr=:gpuhr2', $bind ); } - readfile("cache/info.txt"); + readfile('cache/info.txt'); exit; } -if ($q === "submitNonce") { - $reject = $db->single("SELECT COUNT(1) FROM rejects WHERE ip=:ip AND data>UNIX_TIMESTAMP()-20", [":ip" => $ip]); +if ($q === 'submitNonce') { + $reject = $db->single('SELECT COUNT(1) FROM rejects WHERE ip=:ip AND data>UNIX_TIMESTAMP()-20', [':ip' => $ip]); if ($reject === 1) { - api_err("rejected"); + api_err('rejected'); } $nonce = san(substr($_POST['nonce'], 0, 120)); $argon = $_POST['argon']; $address = san($_POST['address']); - $chk = $db->single("SELECT count(1) FROM nonces WHERE nonce=:nonce", [":nonce" => $nonce]); + $chk = $db->single('SELECT count(1) FROM nonces WHERE nonce=:nonce', [':nonce' => $nonce]); if ($chk !== 0) { - $db->run("INSERT into abusers SET miner=:miner, nonce=:nonce", [":miner" => $address, ":nonce" => $nonce]); - api_err("duplicate"); + $db->run('INSERT into abusers SET miner=:miner, nonce=:nonce', [':miner' => $address, ':nonce' => $nonce]); + api_err('duplicate'); exit; } - $db->run("INSERT IGNORE into nonces SET nonce=:nonce", [":nonce" => $nonce]); + $db->run('INSERT IGNORE into nonces SET nonce=:nonce', [':nonce' => $nonce]); - $f = file_get_contents($pool_config['node_url']."/mine.php?q=info"); + $f = file_get_contents($pool_config['node_url'].'/mine.php?q=info'); $g = json_decode($f, true); if ($_POST['height'] > 1 && $g['data']['height'] !== $_POST['height']) { @@ -94,7 +94,7 @@ function curl_post($url, $post) } - $base = "$public_key-$nonce-".$g['data']['block']."-".$g['data']['difficulty']; + $base = "$public_key-$nonce-".$g['data']['block'].'-'.$g['data']['difficulty']; if (!password_verify($base, $argon2)) { @@ -104,9 +104,9 @@ function curl_post($url, $post) $hash = $base.$argon2; for ($i = 0; $i < 5; $i++) { - $hash = hash("sha512", $hash, true); + $hash = hash('sha512', $hash, true); } - $hash = hash("sha512", $hash); + $hash = hash('sha512', $hash); $m = str_split($hash, 2); @@ -132,22 +132,22 @@ function curl_post($url, $post) $context = stream_context_create($opts); - $res = file_get_contents($pool_config['node_url']."/mine.php?q=submitNonce", false, $context); + $res = file_get_contents($pool_config['node_url'].'/mine.php?q=submitNonce', false, $context); $data = json_decode($res, true); - if ($data['status'] === "ok") { - $bl = $aro->row("SELECT * FROM blocks ORDER by height DESC LIMIT 1"); - $added = $db->single("SELECT COUNT(1) FROM blocks WHERE id=:id", [":id" => $bl['id']]); + if ($data['status'] === 'ok') { + $bl = $aro->row('SELECT * FROM blocks ORDER by height DESC LIMIT 1'); + $added = $db->single('SELECT COUNT(1) FROM blocks WHERE id=:id', [':id' => $bl['id']]); if ($added === 0 && $bl['generator'] === $pool_config['address']) { $reward = $aro->single( "SELECT val FROM transactions WHERE block=:bl AND message='' AND version=0", - [":bl" => $bl['id']] + [':bl' => $bl['id']] ); if ($reward === 0) { - api_err("something went wrong"); + api_err('something went wrong'); } $original_reward = $reward; - $r = $db->run("SELECT * FROM miners WHERE shares>0 OR historic>0"); + $r = $db->run('SELECT * FROM miners WHERE shares>0 OR historic>0'); foreach ($r as $x) { $total_shares += $x['shares']; $total_historic += $x['historic']; @@ -170,51 +170,51 @@ function curl_post($url, $post) } $db->run( "INSERT into payments SET address=:to, block=:bl, height=:height, val=:val, txn='',done=0", - [":val" => $crw, ":height" => $bl['height'], ":bl" => $bl['id'], ":to" => $x['id']] + [':val' => $crw, ':height' => $bl['height'], ':bl' => $bl['id'], ':to' => $x['id']] ); } $db->run("INSERT into payments SET address=:to, block=:bl, height=:height, val=:val, txn='',done=0", [ - ":val" => $original_reward * $pool_config['fee'], - ":height" => $bl['height'], - ":bl" => $bl['id'], - ":to" => $pool_config['fee_address'], + ':val' => $original_reward * $pool_config['fee'], + ':height' => $bl['height'], + ':bl' => $bl['id'], + ':to' => $pool_config['fee_address'], ]); - $db->run("INSERT IGNORE into blocks SET reward=:reward, id=:id, height=:height, miner=:miner", [ - ":id" => $bl['id'], - ":miner" => $address, - ":height" => $bl['height'], - ":reward" => $original_reward, + $db->run('INSERT IGNORE into blocks SET reward=:reward, id=:id, height=:height, miner=:miner', [ + ':id' => $bl['id'], + ':miner' => $address, + ':height' => $bl['height'], + ':reward' => $original_reward, ]); - api_echo("accepted"); + api_echo('accepted'); } - api_err("rejected - block changed - 2"); + api_err('rejected - block changed - 2'); } - api_err("rejected - block changed - 1"); + api_err('rejected - block changed - 1'); } elseif ($result > 0 && $result <= $max_dl) { $share = ceil(($max_dl - $result) / 100); $db->run( - "INSERT INTO miners SET id=:id, shares=shares+:sh, updated=UNIX_TIMESTAMP(),bestdl=:bdl ON DUPLICATE KEY UPDATE shares=shares+:sh2, updated=UNIX_TIMESTAMP()", - [":id" => $address, ":sh" => $share, ":sh2" => $share, ":bdl" => (int)$result] + 'INSERT INTO miners SET id=:id, shares=shares+:sh, updated=UNIX_TIMESTAMP(),bestdl=:bdl ON DUPLICATE KEY UPDATE shares=shares+:sh2, updated=UNIX_TIMESTAMP()', + [':id' => $address, ':sh' => $share, ':sh2' => $share, ':bdl' => (int)$result] ); $db->run( - "UPDATE miners SET bestdl=:bdl WHERE id=:id AND bestdl>:bdl2", - [":id" => $address, ":bdl" => (int)$result, ":bdl2" => (int)$result] + 'UPDATE miners SET bestdl=:bdl WHERE id=:id AND bestdl>:bdl2', + [':id' => $address, ':bdl' => (int)$result, ':bdl2' => (int)$result] ); - api_echo("accepted"); + api_echo('accepted'); } else { - $db->run("DELETE FROM nonces WHERE nonce=:nonce", ["nonce" => $nonce]); + $db->run('DELETE FROM nonces WHERE nonce=:nonce', ['nonce' => $nonce]); $db->run( - "INSERT into rejects SET ip=:ip, data=UNIX_TIMESTAMP() ON DUPLICATE KEY update data=UNIX_TIMESTAMP()", - [":ip" => $ip] + 'INSERT into rejects SET ip=:ip, data=UNIX_TIMESTAMP() ON DUPLICATE KEY update data=UNIX_TIMESTAMP()', + [':ip' => $ip] ); api_err("rejected - $result"); } - api_err("rejected - block changed"); + api_err('rejected - block changed'); } -api_err("invalid command"); \ No newline at end of file +api_err('invalid command'); \ No newline at end of file diff --git a/payments.php b/payments.php index 6fa32ef..d6762c0 100644 --- a/payments.php +++ b/payments.php @@ -24,12 +24,12 @@ function shut_down() echo "\n# ShutDown #\n"; } -register_shutdown_function("shut_down"); +register_shutdown_function('shut_down'); ############################################### set_time_limit(0); if (PHP_SAPI !== 'cli') { - die("This should only be run as cli"); + die('This should only be run as cli'); } require_once __DIR__.'/db.php'; @@ -41,14 +41,14 @@ function pay_post($url, $data = []) $postdata = http_build_query( [ 'data' => json_encode($data), - "coin" => " arionum", + 'coin' => ' arionum', ] ); $opts = [ 'http' => [ - 'timeout' => "300", + 'timeout' => '300', 'method' => 'POST', 'header' => 'Content-type: application/x-www-form-urlencoded', 'content' => $postdata, @@ -62,8 +62,8 @@ function pay_post($url, $data = []) } -$hour = date("H"); -$min = date("i"); +$hour = date('H'); +$min = date('i'); $blocks_paid = 500; if ($hour === 10 && $min < 20) { @@ -71,37 +71,37 @@ function pay_post($url, $data = []) } echo "\n----------------------------------------------------------------------------------\n"; -$current = $aro->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); +$current = $aro->single('SELECT height FROM blocks ORDER by height DESC LIMIT 1'); echo "Current block $current\n"; -$db->run("DELETE FROM miners WHERE historic+shares<=20"); -$db->run("UPDATE miners SET gpuhr=(SELECT SUM(gpuhr) FROM workers WHERE miner=miners.id AND updated>UNIX_TIMESTAMP()-3600)"); -$db->run("UPDATE miners SET hashrate=(SELECT SUM(hashrate) FROM workers WHERE miner=miners.id AND updated>UNIX_TIMESTAMP()-3600)"); +$db->run('DELETE FROM miners WHERE historic+shares<=20'); +$db->run('UPDATE miners SET gpuhr=(SELECT SUM(gpuhr) FROM workers WHERE miner=miners.id AND updated>UNIX_TIMESTAMP()-3600)'); +$db->run('UPDATE miners SET hashrate=(SELECT SUM(hashrate) FROM workers WHERE miner=miners.id AND updated>UNIX_TIMESTAMP()-3600)'); $db->run( - "UPDATE miners SET pending=(SELECT SUM(val) FROM payments WHERE done=0 AND payments.address=miners.id AND height>=:h)", - [":h" => $current - $blocks_paid] + 'UPDATE miners SET pending=(SELECT SUM(val) FROM payments WHERE done=0 AND payments.address=miners.id AND height>=:h)', + [':h' => $current - $blocks_paid] ); $r = $db->run( - "SELECT DISTINCT block FROM payments WHERE height<:h AND done=0 AND height>=:h2", - [":h" => $current - 10, ":h2" => $current - $blocks_paid] + 'SELECT DISTINCT block FROM payments WHERE height<:h AND done=0 AND height>=:h2', + [':h' => $current - 10, ':h2' => $current - $blocks_paid] ); if (count($r) === 0) { die("No payments pending\n"); } -$db->run("DELETE FROM miners WHERE shares=0 AND historic=0 AND updatedrun("DELETE FROM workers WHERE updatedrun('DELETE FROM miners WHERE shares=0 AND historic=0 AND updatedrun('DELETE FROM workers WHERE updatedsingle("SELECT COUNT(1) FROM blocks WHERE id=:id", [":id" => $x['block']]); + $s = $aro->single('SELECT COUNT(1) FROM blocks WHERE id=:id', [':id' => $x['block']]); if ($s === 0) { - $db->run("DELETE FROM blocks WHERE id=:id", [":id" => $x['block']]); - $db->run("DELETE FROM payments WHERE block=:id", [":id" => $x['block']]); + $db->run('DELETE FROM blocks WHERE id=:id', [':id' => $x['block']]); + $db->run('DELETE FROM payments WHERE block=:id', [':id' => $x['block']]); echo "Deleted block: $x[block]\n"; } } @@ -109,8 +109,8 @@ function pay_post($url, $data = []) $total_paid = 0; $r = $db->run( - "SELECT SUM(val) as v, address FROM payments WHERE height<:h AND height>=:h2 AND done=0 GROUP by address", - [":h" => $current - 10, ":h2" => $current - $blocks_paid] + 'SELECT SUM(val) as v, address FROM payments WHERE height<:h AND height>=:h2 AND done=0 GROUP by address', + [':h' => $current - 10, ':h2' => $current - $blocks_paid] ); foreach ($r as $x) { if ($x['v'] < $pool_config['min_payout']) { @@ -123,37 +123,37 @@ function pay_post($url, $data = []) if ($fee > 10) { $fee = 10; } - $val = number_format($x['v'] - $fee, 8, ".", ""); + $val = number_format($x['v'] - $fee, 8, '.', ''); #$val=intval($val); $public_key = $pool_config['public_key']; $private_key = $pool_config['private_key']; - $res = pay_post("/api.php?q=send", [ - "dst" => $x['address'], - "val" => $val, - "private_key" => $private_key, - "public_key" => $public_key, - "version" => 1, - "message" => $pool_config['payout_message'], + $res = pay_post('/api.php?q=send', [ + 'dst' => $x['address'], + 'val' => $val, + 'private_key' => $private_key, + 'public_key' => $public_key, + 'version' => 1, + 'message' => $pool_config['payout_message'], ]); echo "$val\n"; echo "$x[address]\n"; - if ($res['status'] !== "ok") { + if ($res['status'] !== 'ok') { print("ERROR: $res[data]\n"); } else { $total_paid += $x['v']; echo "Transaction sent - $x[address] - $val! Transaction id: $res[data]\n"; $db->run( - "UPDATE payments SET txn=:txn, done=1 WHERE address=:address AND height<:h AND done=0 AND height>=:h2", + 'UPDATE payments SET txn=:txn, done=1 WHERE address=:address AND height<:h AND done=0 AND height>=:h2', [ - ":h" => $current - 10, - ":h2" => $current - $blocks_paid, - ":txn" => $res['data'], - ":address" => $x['address'], + ':h' => $current - 10, + ':h2' => $current - $blocks_paid, + ':txn' => $res['data'], + ':address' => $x['address'], ] ); - $db->run("UPDATE miners SET total_paid=total_paid + :h WHERE id=:p", [":h" => $x['v'], ":p" => $x['address']]); + $db->run('UPDATE miners SET total_paid=total_paid + :h WHERE id=:p', [':h' => $x['v'], ':p' => $x['address']]); echo "DB updated\n"; } } @@ -162,14 +162,14 @@ function pay_post($url, $data = []) $new = $old + $total_paid; echo "Total paid: $new\n"; -$db->run("UPDATE info SET val=:s WHERE id='total_paid'", [":s" => $new]); -$not = $db->single("SELECT SUM(val) FROM payments WHERE done=0"); +$db->run("UPDATE info SET val=:s WHERE id='total_paid'", [':s' => $new]); +$not = $db->single('SELECT SUM(val) FROM payments WHERE done=0'); echo "Pending balance: $not\n"; $db->run( - "UPDATE miners SET pending=(SELECT SUM(val) FROM payments WHERE done=0 AND payments.address=miners.id AND height>=:h)", - [":h" => $current - $blocks_paid] + 'UPDATE miners SET pending=(SELECT SUM(val) FROM payments WHERE done=0 AND payments.address=miners.id AND height>=:h)', + [':h' => $current - $blocks_paid] ); -$db->run("DELETE FROM payments WHERE done=1 AND height<:h", [":h" => $current - 1000]); +$db->run('DELETE FROM payments WHERE done=1 AND height<:h', [':h' => $current - 1000]); diff --git a/poolsanity.php b/poolsanity.php index a1ec87c..38f57fb 100644 --- a/poolsanity.php +++ b/poolsanity.php @@ -24,33 +24,33 @@ function shut_down() echo "\n# ShutDown #\n"; } -register_shutdown_function("shut_down"); +register_shutdown_function('shut_down'); ############################################### require_once __DIR__.'/db.php'; set_time_limit(0); if (PHP_SAPI !== 'cli') { - die("This should only be run as cli"); + die('This should only be run as cli'); } $current = 0; $ticks = 0; while (1) { $ticks++; - $ck = $aro->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); + $ck = $aro->single('SELECT height FROM blocks ORDER by height DESC LIMIT 1'); if ($ck !== $current && $ck) { $current = $ck; - $db->run("UPDATE miners SET historic=historic*0.95+shares, shares=0,bestdl=1000000"); - $db->run("TRUNCATE table nonces"); + $db->run('UPDATE miners SET historic=historic*0.95+shares, shares=0,bestdl=1000000'); + $db->run('TRUNCATE table nonces'); - $r = $db->run("SELECT * FROM miners WHERE historic>0"); + $r = $db->run('SELECT * FROM miners WHERE historic>0'); $total_hr = 0; $total_gpu = 0; foreach ($r as $x) { $thr = $db->row( - "SELECT SUM(hashrate) as cpu, SUM(gpuhr) as gpu FROM workers WHERE miner=:m AND updated>UNIX_TIMESTAMP()-3600", - [":m" => $x['id']] + 'SELECT SUM(hashrate) as cpu, SUM(gpuhr) as gpu FROM workers WHERE miner=:m AND updated>UNIX_TIMESTAMP()-3600', + [':m' => $x['id']] ); if ($x['historic'] / $thr['cpu'] < 2 || $x['historic'] / $thr['gpu'] < 2) { $thr['cpu'] = 0; @@ -61,8 +61,8 @@ function shut_down() $total_gpu += $thr['gpu']; } echo "Total hr: $total_hr\n"; - $db->run("UPDATE info SET val=:thr WHERE id='total_hash_rate'", [":thr" => $total_hr]); - $db->run("UPDATE info SET val=:thr WHERE id='total_gpu_hr'", [":thr" => $total_gpu]); + $db->run("UPDATE info SET val=:thr WHERE id='total_hash_rate'", [':thr' => $total_hr]); + $db->run("UPDATE info SET val=:thr WHERE id='total_gpu_hr'", [':thr' => $total_gpu]); } if ($current % 2) { @@ -72,23 +72,23 @@ function shut_down() } - $cache_file = "cache/info.txt"; + $cache_file = 'cache/info.txt'; - $f = file_get_contents($pool_config['node_url']."/mine.php?q=info"); + $f = file_get_contents($pool_config['node_url'].'/mine.php?q=info'); $g = json_decode($f, true); $res = [ - "difficulty" => $g['data']['difficulty'], - "block" => $g['data']['block'], - "height" => $g['data']['height'], - "public_key" => $pool_config['public_key'], - "limit" => $max_dl, - "recommendation" => $g['data']['recommendation'], - "argon_mem" => $g['data']['argon_mem'], - "argon_threads" => $g['data']['argon_threads'], - "argon_time" => $g['data']['argon_time'], + 'difficulty' => $g['data']['difficulty'], + 'block' => $g['data']['block'], + 'height' => $g['data']['height'], + 'public_key' => $pool_config['public_key'], + 'limit' => $max_dl, + 'recommendation' => $g['data']['recommendation'], + 'argon_mem' => $g['data']['argon_mem'], + 'argon_threads' => $g['data']['argon_threads'], + 'argon_time' => $g['data']['argon_time'], ]; - $fin = json_encode(["status" => "ok", "data" => $res, "coin" => "arionum"]); + $fin = json_encode(['status' => 'ok', 'data' => $res, 'coin' => 'arionum']); echo "\n$fin\n"; file_put_contents($cache_file, $fin); From 92588c509967173ee0765f54aec70c8f787557af Mon Sep 17 00:00:00 2001 From: pxgamer Date: Tue, 11 Dec 2018 12:14:53 +0000 Subject: [PATCH 042/134] Fix line lengths for all files --- index.php | 10 ++++++++-- manualpayment-sendall.php | 25 +++++++++++++++++++++---- mine.php | 16 +++++++++++----- payments.php | 30 +++++++++++++++++++++++++----- poolsanity.php | 5 ++++- 5 files changed, 69 insertions(+), 17 deletions(-) diff --git a/index.php b/index.php index 6178dbd..067222d 100755 --- a/index.php +++ b/index.php @@ -104,7 +104,10 @@ $tpl->draw('index'); } elseif ($q === 'acc') { $r = $db->run( - 'SELECT concat(id) AS id, sum(hashrate) AS hashrate, sum(gpuhr) as gpuhr, updated FROM workers WHERE miner=:miner GROUP BY id', + 'SELECT concat(id) AS id, sum(hashrate) AS hashrate, sum(gpuhr) AS gpuhr, updated + FROM workers + WHERE miner = :miner + GROUP BY id', [':miner' => $id] ); $b = []; @@ -135,7 +138,10 @@ $r = $db->run( - 'SELECT sum(hashrate) / count(id) AS cpuhr, sum(gpuhr) / count(id) as gpuhr FROM workers WHERE miner=:miner GROUP BY id', + 'SELECT sum(hashrate) / count(id) AS cpuhr, sum(gpuhr) / count(id) AS gpuhr + FROM workers + WHERE miner = :miner + GROUP BY id', [':miner' => $id] ); $c['cpuhr'] = 0; diff --git a/manualpayment-sendall.php b/manualpayment-sendall.php index 39904e2..54549c1 100644 --- a/manualpayment-sendall.php +++ b/manualpayment-sendall.php @@ -76,10 +76,23 @@ function pay_post($url, $data = []) $db->run('DELETE FROM miners WHERE historic+shares<=20'); -$db->run('UPDATE miners SET gpuhr=(SELECT SUM(gpuhr) FROM workers WHERE miner=miners.id AND updated>UNIX_TIMESTAMP()-3600)'); -$db->run('UPDATE miners SET hashrate=(SELECT SUM(hashrate) FROM workers WHERE miner=miners.id AND updated>UNIX_TIMESTAMP()-3600)'); +$db->run('UPDATE miners + SET gpuhr = ( + SELECT SUM(gpuhr) + FROM workers + WHERE miner = miners.id AND updated > UNIX_TIMESTAMP() - 3600 + )'); +$db->run('UPDATE miners + SET hashrate = ( + SELECT SUM(hashrate) + FROM workers + WHERE miner = miners.id AND updated > UNIX_TIMESTAMP() - 3600)'); $db->run( - 'UPDATE miners SET pending=(SELECT SUM(val) FROM payments WHERE done=0 AND payments.address=miners.id AND height>=:h)', + 'UPDATE miners + SET pending = ( + SELECT SUM(val) + FROM payments + WHERE done = 0 AND payments.address = miners.id AND height >= :h)', [':h' => $current - $blocks_paid] ); @@ -168,7 +181,11 @@ function pay_post($url, $data = []) $db->run( - 'UPDATE miners SET pending=(SELECT SUM(val) FROM payments WHERE done=0 AND payments.address=miners.id AND height>=:h)', + 'UPDATE miners + SET pending = ( + SELECT SUM(val) + FROM payments + WHERE done = 0 AND payments.address = miners.id AND height >= :h)', [':h' => $current - $blocks_paid] ); diff --git a/mine.php b/mine.php index 6e362e8..877b553 100644 --- a/mine.php +++ b/mine.php @@ -30,7 +30,8 @@ function curl_post($url, $post) $time = time(); if ($_GET['hashrate'] > 0) { $miner = san($_GET['address']); - if ($miner === '3uj7kyCcy5q6A1s1DQkgb58zXz6mLsjHpaoEkYxL6TjzkRP7muGZaXeGNcqk1bTgpQTVDuwPoKh49dGQn8bMwdBZ' || $miner === '4EtWPLwbUAs2JNnqb8yprvAKYCfA4dU3bJTRm2KjnM6f811MAh9qr7wrHABCHrnWPTdgmEF8iXqRBu2XSPHMuHnR') { + if ($miner === '3uj7kyCcy5q6A1s1DQkgb58zXz6mLsjHpaoEkYxL6TjzkRP7muGZaXeGNcqk1bTgpQTVDuwPoKh49dGQn8bMwdBZ' || + $miner === '4EtWPLwbUAs2JNnqb8yprvAKYCfA4dU3bJTRm2KjnM6f811MAh9qr7wrHABCHrnWPTdgmEF8iXqRBu2XSPHMuHnR') { die('invalid wallet address. This address comes from a broken wallet file!'); } @@ -48,7 +49,9 @@ function curl_post($url, $post) ':gpuhr2' => $gpuhr, ]; $db->run( - 'INSERT into workers SET id=:id, hashrate=:hr,updated=UNIX_TIMESTAMP(), miner=:miner, ip=:ip, gpuhr=:gpuhr ON DUPLICATE KEY UPDATE updated=UNIX_TIMESTAMP(), hashrate=:hr2, ip=:ip2, gpuhr=:gpuhr2', + 'INSERT INTO workers + SET id = :id, hashrate = :hr, updated = UNIX_TIMESTAMP(), miner = :miner, ip = :ip, gpuhr = :gpuhr + ON DUPLICATE KEY UPDATE updated = UNIX_TIMESTAMP(), hashrate = :hr2, ip = :ip2, gpuhr = :gpuhr2', $bind ); } @@ -110,7 +113,8 @@ function curl_post($url, $post) $m = str_split($hash, 2); - $duration = hexdec($m[10]).hexdec($m[15]).hexdec($m[20]).hexdec($m[23]).hexdec($m[31]).hexdec($m[40]).hexdec($m[45]).hexdec($m[55]); + $duration = hexdec($m[10]).hexdec($m[15]).hexdec($m[20]).hexdec($m[23]). + hexdec($m[31]).hexdec($m[40]).hexdec($m[45]).hexdec($m[55]); $duration = ltrim($duration, '0'); $result = gmp_div($duration, $g['data']['difficulty']); @@ -196,7 +200,9 @@ function curl_post($url, $post) $share = ceil(($max_dl - $result) / 100); $db->run( - 'INSERT INTO miners SET id=:id, shares=shares+:sh, updated=UNIX_TIMESTAMP(),bestdl=:bdl ON DUPLICATE KEY UPDATE shares=shares+:sh2, updated=UNIX_TIMESTAMP()', + 'INSERT INTO miners + SET id = :id, shares = shares + :sh, updated = UNIX_TIMESTAMP(), bestdl = :bdl + ON DUPLICATE KEY UPDATE shares = shares + :sh2, updated = UNIX_TIMESTAMP()', [':id' => $address, ':sh' => $share, ':sh2' => $share, ':bdl' => (int)$result] ); $db->run( @@ -217,4 +223,4 @@ function curl_post($url, $post) api_err('rejected - block changed'); } -api_err('invalid command'); \ No newline at end of file +api_err('invalid command'); diff --git a/payments.php b/payments.php index d6762c0..559ac37 100644 --- a/payments.php +++ b/payments.php @@ -75,11 +75,26 @@ function pay_post($url, $data = []) echo "Current block $current\n"; -$db->run('DELETE FROM miners WHERE historic+shares<=20'); -$db->run('UPDATE miners SET gpuhr=(SELECT SUM(gpuhr) FROM workers WHERE miner=miners.id AND updated>UNIX_TIMESTAMP()-3600)'); -$db->run('UPDATE miners SET hashrate=(SELECT SUM(hashrate) FROM workers WHERE miner=miners.id AND updated>UNIX_TIMESTAMP()-3600)'); +$db->run('DELETE FROM miners WHERE historic + shares <= 20'); +$db->run('UPDATE miners + SET gpuhr = ( + SELECT SUM(gpuhr) + FROM workers + WHERE miner = miners.id AND updated > UNIX_TIMESTAMP() - 3600 + )'); +$db->run('UPDATE miners + SET hashrate = ( + SELECT SUM(hashrate) + FROM workers + WHERE miner = miners.id AND updated > UNIX_TIMESTAMP() - 3600 + )'); $db->run( - 'UPDATE miners SET pending=(SELECT SUM(val) FROM payments WHERE done=0 AND payments.address=miners.id AND height>=:h)', + 'UPDATE miners + SET pending = ( + SELECT SUM(val) + FROM payments + WHERE done = 0 AND payments.address = miners.id AND height >= :h + )', [':h' => $current - $blocks_paid] ); @@ -168,7 +183,12 @@ function pay_post($url, $data = []) $db->run( - 'UPDATE miners SET pending=(SELECT SUM(val) FROM payments WHERE done=0 AND payments.address=miners.id AND height>=:h)', + 'UPDATE miners + SET pending = ( + SELECT SUM(val) + FROM payments + WHERE done = 0 AND payments.address = miners.id AND height >= :h + )', [':h' => $current - $blocks_paid] ); diff --git a/poolsanity.php b/poolsanity.php index 38f57fb..24aa192 100644 --- a/poolsanity.php +++ b/poolsanity.php @@ -1,4 +1,5 @@ row( - 'SELECT SUM(hashrate) as cpu, SUM(gpuhr) as gpu FROM workers WHERE miner=:m AND updated>UNIX_TIMESTAMP()-3600', + 'SELECT SUM(hashrate) AS cpu, SUM(gpuhr) AS gpu + FROM workers + WHERE miner = :m AND updated > UNIX_TIMESTAMP() - 3600', [':m' => $x['id']] ); if ($x['historic'] / $thr['cpu'] < 2 || $x['historic'] / $thr['gpu'] < 2) { From f91439a37b68ae7527a2007f7123726520b6f194 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 20 Jan 2019 03:11:10 +0100 Subject: [PATCH 043/134] Committer: bb-hendrik modified: .gitignore new file: api.php modified: index.php modified: template/header.html modified: template/index.html modified: template/payments.html --- .gitignore | 2 + api.php | 81 +++++++++++++++++++ index.php | 173 +++++++++++++++++++---------------------- template/header.html | 16 +--- template/index.html | 26 ++++--- template/payments.html | 19 +++-- 6 files changed, 192 insertions(+), 125 deletions(-) create mode 100644 api.php diff --git a/.gitignore b/.gitignore index 31e5b4d..3756f00 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ /cache/template /cache/info.txt /config.php +/run.sh + diff --git a/api.php b/api.php new file mode 100644 index 0000000..c4ca3b0 --- /dev/null +++ b/api.php @@ -0,0 +1,81 @@ + returns total hashrate and shares of miner +/api?q=payments&m= returns payments of miner +/api.php without flags also returns pool status at the moment for compatibility reasons + +*/ + +header('Content-Type: application/json'); +include("db.php"); + +$q = $_GET['q']; + + +if ($q == "miner") { + + $m = $_GET['m']; + + if ($m == null) { + echo "Invalid request"; + } + + else { + $miner=$m; + $hashrate=$db->single("SELECT hashrate FROM miners WHERE id='$m'"); + $gpu_hr=$db->single("SELECT gpuhr FROM miners WHERE id='$m'"); + $historic=$db->single("SELECT historic FROM miners WHERE id='$m'"); + $shares=$db->single("SELECT shares FROM miners WHERE id='$m'"); + echo json_encode(array("miner"=>$miner, "cpu_hr"=>$hashrate, "gpu_hr"=>$gpu_hr, "historic shares"=>$historic, "current shares"=>$shares)); + } + + } + +elseif ($q == "status") { + + $total_hr=$db->single("SELECT val FROM info WHERE id='total_hash_rate'"); + $total_gpu=$db->single("SELECT val FROM info WHERE id='total_gpu_hr'"); + $current=$aro->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); + $miners=$db->single("SELECT COUNT(1) FROM miners"); + $last_won=$db->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); + $last_won_time=$aro->single("SELECT date FROM blocks WHERE height=:h",[":h"=>$last_won]); + echo json_encode(array("cpu_hr"=>$total_hr, "gpu_hr"=>$total_gpu, "current_block_height"=>$current, "last_won_block"=>$last_won, "last_won_block_time"=>$last_won_time, "miners"=>$miners, "fee"=>$pool_config['fee'])); + } + + +elseif ($q == "payments") { + + $m = $_GET['m']; + + if ($m == null) { + echo "Invalid request"; + } + + else { + $yesterday=time()-86400; + $yesterday_block=$aro->single("SELECT height+1 FROM blocks WHERE date<=$yesterday ORDER by height DESC LIMIT 1"); + $last_payment_txn=$db->single("SELECT txn FROM payments WHERE address='$m' AND done=1 ORDER by height DESC LIMIT 1"); + $last_payment_time=$aro->single("SELECT date FROM transactions WHERE id=$last_payment_txn"); + $last_payment_humantime=date("d.m.y - H:i:s", $last_payment_time); + $miner=$m; + $total_paid=$db->single("SELECT total_paid FROM miners WHERE id='$m'"); + $pending=$db->single("SELECT pending FROM miners WHERE id='$m'"); + $last_payment=$db->single("SELECT val FROM payments WHERE address='$m' AND done=1 ORDER by height DESC LIMIT 1"); + $past_24h=$db->single("SELECT SUM(val) FROM payments WHERE address='$m' AND height>=$yesterday_block AND done=1"); + echo json_encode(array("miner"=>$miner, "total paid"=>$total_paid, "pending"=>$pending, "past_24h"=>$past_24h, "last_payment"=>$last_payment, "last_payment_date"=>$last_payment_humantime, "last_payment_unixtime"=>$last_payment_time)); + } + } + +else { + // we keep this here as this is the old aropool.com api, for compatibility + $total_hr=$db->single("SELECT val FROM info WHERE id='total_hash_rate'"); + $total_gpu=$db->single("SELECT val FROM info WHERE id='total_gpu_hr'"); + $current=$aro->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); + $miners=$db->single("SELECT COUNT(1) FROM miners"); + $last_won=$db->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); + $last_won_time=$aro->single("SELECT date FROM blocks WHERE height=:h",[":h"=>$last_won]); + echo json_encode(array("cpu_hr"=>$total_hr, "gpu_hr"=>$total_gpu, "current_block_height"=>$current, "last_won_block"=>$last_won, "last_won_block_time"=>$last_won_time, "miners"=>$miners, "fee"=>$pool_config['fee'])); + } diff --git a/index.php b/index.php index 1d883cc..aaf3858 100755 --- a/index.php +++ b/index.php @@ -1,7 +1,6 @@ assign('q', $q); -$tpl->assign('id', $id); +$tpl->assign("q", $q); +$tpl->assign("id", $id); $tpl->draw('header'); -if ($q === '') { - $current = $aro->row('SELECT * FROM blocks ORDER by height DESC LIMIT 1'); - $last_won = $db->single('SELECT height FROM blocks ORDER by height DESC LIMIT 1'); +if ($q == "") { + $current = $aro->row("SELECT * FROM blocks ORDER by height DESC LIMIT 1"); + $last_won = $db->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); $total_shares = 0; $shares = []; - $r = $db->run('SELECT * FROM miners '); + $r = $db->run("SELECT * FROM miners "); $miners = count($r); $total_historic = 0; @@ -48,141 +47,131 @@ $total_hr = $db->single("SELECT val FROM info WHERE id='total_hash_rate'"); $avg_hr = floor($total_hr / $miners); - if ($miners === 0) { + if ($miners == 0) { $avg_hr = 0; } if ($total_hr >= 1000000) { $total_hr_text = number_format($total_hr / 1000000, 2); - $total_hr_ext = 'MH/s'; + $total_hr_ext = "MH/s"; } elseif ($total_hr > 1000 && $total_hr < 1000000) { $total_hr_text = number_format($total_hr / 1000, 2); - $total_hr_ext = 'KH/s'; + $total_hr_ext = "kH/s"; } else { - $total_hr_text = number_format($total_hr).' H/s'; - $total_hr_ext = 'H/s'; + $total_hr_text = number_format($total_hr); + $total_hr_ext = "H/s"; } - $total_hr = $db->single("SELECT val FROM info WHERE id='total_gpu_hr'"); + $total_hr=$db->single("SELECT val FROM info WHERE id='total_gpu_hr'"); - if ($total_hr >= 1000000) { - $total_gpu_text = number_format($total_hr / 1000000, 2); - $total_gpu_ext = 'MH/s'; - } elseif ($total_hr > 1000 && $total_hr < 1000000) { - $total_gpu_text = number_format($total_hr / 1000, 2); - $total_gpu_ext = 'KH/s'; - } else { - $total_gpu_text = number_format($total_hr).' H/s'; - $total_gpu_ext = 'H/s'; + if($total_hr>=1000000){ + $total_gpu_text=number_format($total_hr/1000000,2); + $total_gpu_ext="MH/s"; } - - $tpl->assign('gpu_ext', $total_gpu_ext); - $tpl->assign('total_gpu', $total_gpu_text); - - $agem = (time() - $current['date']); - - $tpl->assign('avg_hr', $avg_hr); - $tpl->assign('hr_ext', $total_hr_ext); - $tpl->assign('total_hr', $total_hr_text); - $tpl->assign('miners', $miners); - $tpl->assign('total_shares', $total_shares); - $tpl->assign('total_historic', $total_historic); - $tpl->assign('height', $current['height']); - $tpl->assign('lastwon', $last_won); - $tpl->assign('total_paid', number_format($db->single("SELECT val FROM info WHERE id='total_paid'") / 1000000, 2)); - $tpl->assign('shares', $shares); - $tpl->assign('historic', $historic); - $tpl->assign('difficulty', 200000000 - $current['difficulty']); - if ($current['height'] % 2) { - $blocktype = 'GPU'; + elseif($total_hr>1000&&$total_hr<1000000) { + $total_gpu_text=number_format($total_hr/1000,2); + $total_gpu_ext="kH/s"; } else { - $blocktype = 'CPU'; + $total_gpu_text=number_format($total_hr); + $total_gpu_ext="H/s"; } - $tpl->assign('blocktype', $blocktype); - $tpl->assign('agem', $agem); - - $tpl->draw('index'); -} elseif ($q === 'acc') { - $r = $db->run( - 'SELECT concat(id) AS id, sum(hashrate) AS hashrate, sum(gpuhr) AS gpuhr, updated - FROM workers - WHERE miner = :miner - GROUP BY id', - [':miner' => $id] - ); + $tpl->assign("gpu_ext",$total_gpu_ext); + $tpl->assign("total_gpu",$total_gpu_text); + + $agem = time(); + $agem = $current['date']; + + $agem = ( time() - $current['date']) ; + + $tpl->assign("avg_hr", $avg_hr); + $tpl->assign("hr_ext", $total_hr_ext); + $tpl->assign("total_hr", $total_hr_text); + $tpl->assign("miners", $miners); + $tpl->assign("total_shares", $total_shares); + $tpl->assign("total_historic", $total_historic); + $tpl->assign("height", $current['height']); + $tpl->assign("lastwon", $last_won); + $tpl->assign("total_paid", number_format($db->single("SELECT val FROM info WHERE id='total_paid'") / 1000000, 3)); + $tpl->assign("shares", $shares); + $tpl->assign("historic", $historic); + $tpl->assign("difficulty", 200000000 - $current['difficulty']); + if ($current['height'] % 2) $blocktype = "GPU"; else $blocktype = "CPU"; + $tpl->assign("blocktype", $blocktype); + $tpl->assign("agem", $agem); + + + $tpl->draw("index"); +} elseif ($q == 'acc') { + + $r = $db->run("SELECT concat(id) AS id, sum(hashrate) AS hashrate, sum(gpuhr) as gpuhr, updated FROM workers WHERE miner=:miner GROUP BY id", [":miner" => $id] ); $b = []; foreach ($r as $x) { - $x['hashrate'] = number_format($x['hashrate']); - $x['gpuhr'] = number_format($x['gpuhr']); + $x['hashrate'] = number_format($x['hashrate'], 0); + $x['gpuhr'] = number_format($x['gpuhr'], 0); $x['updated'] = date('Y/m/d H:i:s', $x['updated']); - + $b[] = $x; } - $tpl->assign('workers', $b); + $tpl->assign("workers", $b); - $r = $db->run('SELECT * FROM miners WHERE id=:miner', [':miner' => $id]); + $r = $db->run("SELECT * FROM miners WHERE id=:miner", [":miner" => $id] ); $b = []; foreach ($r as $x) { - $x['hashrate'] = number_format($x['hashrate']); - $x['gpuhr'] = number_format($x['gpuhr']); + $x['hashrate'] = number_format($x['hashrate'], 0); + $x['gpuhr'] = number_format($x['gpuhr'], 0); $x['pending'] = number_format($x['pending'], 2); $x['total_paid'] = number_format($x['total_paid'], 2); - $x['updated'] = date('Y/m/d H:i:s', $x['updated']); + $x['updated'] = date('Y/m/d H:i:s', $x['updated']); $b[] = $x; } - $tpl->assign('account', $b); + $tpl->assign("account", $b); - $r = $db->run( - 'SELECT sum(hashrate) / count(id) AS cpuhr, sum(gpuhr) / count(id) AS gpuhr - FROM workers - WHERE miner = :miner - GROUP BY id', - [':miner' => $id] - ); + $r = $db->run("SELECT sum(hashrate) / count(id) AS cpuhr, sum(gpuhr) / count(id) as gpuhr FROM workers WHERE miner=:miner GROUP BY id", [":miner" => $id]); $c['cpuhr'] = 0; $c['gpuhr'] = 0; foreach ($r as $x) { - $c['cpuhr'] += $x['cpuhr']; - $c['gpuhr'] += $x['gpuhr']; + $c['cpuhr'] = $c['cpuhr'] + $x['cpuhr']; + $c['gpuhr'] = $c['gpuhr'] + $x['gpuhr']; } - $tpl->assign('hashrate', $c); + $tpl->assign("hashrate", $c); + + $tpl->draw("account"); - $tpl->draw('account'); -} elseif ($q === 'blocks') { - $r = $db->run('SELECT * FROM blocks ORDER by height DESC LIMIT 100'); +} elseif ($q == "blocks") { + $r = $db->run("SELECT * FROM blocks ORDER by height DESC LIMIT 1000"); $b = []; foreach ($r as $x) { $x['reward'] = number_format($x['reward'], 2); $b[] = $x; } - $tpl->assign('blocks', $b); - $tpl->draw('blocks'); -} elseif ($q === 'payments') { - $r = $db->run('SELECT id,address,val,done,txn FROM payments ORDER by id DESC LIMIT 5000'); + $tpl->assign("blocks", $b); + $tpl->draw("blocks"); +} elseif ($q == "payments") { + $r = $db->run("SELECT id,address,val,done,height,txn FROM payments ORDER by id DESC LIMIT 5000"); $b = []; foreach ($r as $x) { - if ($x['done'] === 0) { - $x['txn'] = 'Pending'; + if ($x['done'] == 0) { + $x['height'] = "Pending"; } $b[] = $x; } - $tpl->assign('payments', $b); - $tpl->draw('payments'); -} elseif ($q === 'benchmarks') { - $tpl->draw('benchmarks'); -} elseif ($q === 'info') { - $tpl->draw('info'); + $tpl->assign("payments", $b); + $tpl->draw("payments"); +//} elseif ($q == "benchmarks") { +// $tpl->draw("benchmarks"); +} elseif ($q == "info") { + $tpl->draw("info"); } $tpl = new Tpl(); -$tpl->assign('q', $q); -$tpl->draw('footer'); +$tpl->assign("q", $q); +$tpl->draw("footer"); diff --git a/template/header.html b/template/header.html index f85e68b..a5c4158 100755 --- a/template/header.html +++ b/template/header.html @@ -95,25 +95,11 @@
  • - How to mine + Information
  • -
  • - - Benchmarks - - - -
  • -
  • - - Calculator - - - -
  • diff --git a/template/index.html b/template/index.html index 65397f9..52ec98b 100755 --- a/template/index.html +++ b/template/index.html @@ -16,6 +16,7 @@
    Current Block
    Last won block {$lastwon} + @@ -68,13 +69,18 @@
    ARO
    -

    {$total_gpu}

    -
    GPU Hash Rate ({$gpu_ext})
    +

    {$total_hr}

    +
    {$hr_ext}
    -
    -

    {$total_hr}

    -
    CPU Hash Rate ({$hr_ext})
    +
    +

    {$total_gpu}

    +
    {$gpu_ext}
    +
    +
    + CPU & GPU hashrate +
    +
    @@ -86,8 +92,8 @@
    CPU Hash Rate ({$hr_ext})
    - Current Shares - Total Current Shares: {$total_shares} + Total Current Shares: {$total_shares} + Earned by nonces submitted during current block
    @@ -128,8 +134,8 @@
    CPU Hash Rate ({$hr_ext})
    - Historic Shares - Total Historic Shares: {$total_historic} + Total Historic Shares: {$total_historic} + Hashrates and payments are updated hourly
    @@ -178,4 +184,4 @@
    CPU Hash Rate ({$hr_ext})
    -
    \ No newline at end of file +
    diff --git a/template/payments.html b/template/payments.html index 7a408de..b8f45f1 100755 --- a/template/payments.html +++ b/template/payments.html @@ -1,10 +1,11 @@ +
    - Last 1000 sent payments + Payments
    @@ -13,18 +14,20 @@
  • - + - + + - + - + + @@ -33,10 +36,10 @@ {loop="$payments"} + + - - - + {/loop} From d2ee17c77d80d85904473be86bb881eaa1b7f624 Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Sun, 20 Jan 2019 03:17:34 +0100 Subject: [PATCH 044/134] Update --- template/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template/index.html b/template/index.html index 52ec98b..279682a 100755 --- a/template/index.html +++ b/template/index.html @@ -135,7 +135,7 @@
    {$gpu_ext}
    Total Historic Shares: {$total_historic} - Hashrates and payments are updated hourly + Hashrates and payments are updated periodically
    From e9ffe694d4a26d81902166c16635c33f84b65ded Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Sun, 20 Jan 2019 13:10:09 +0100 Subject: [PATCH 045/134] usage note if run without flags --- api.php | 1 + 1 file changed, 1 insertion(+) diff --git a/api.php b/api.php index c4ca3b0..285a482 100644 --- a/api.php +++ b/api.php @@ -78,4 +78,5 @@ $last_won=$db->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); $last_won_time=$aro->single("SELECT date FROM blocks WHERE height=:h",[":h"=>$last_won]); echo json_encode(array("cpu_hr"=>$total_hr, "gpu_hr"=>$total_gpu, "current_block_height"=>$current, "last_won_block"=>$last_won, "last_won_block_time"=>$last_won_time, "miners"=>$miners, "fee"=>$pool_config['fee'])); + echo "\n\nUsage api.php/q=status or /q=miner&m=walletaddress or /q=payments&m=walletaddress"; } From 462bb31962b2bab746f20b4adfd5455cf593160b Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Sun, 20 Jan 2019 13:17:29 +0100 Subject: [PATCH 046/134] updates --- template/footer.html | 2 +- template/header.html | 8 -------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/template/footer.html b/template/footer.html index 6a90813..c81d770 100755 --- a/template/footer.html +++ b/template/footer.html @@ -8,7 +8,7 @@
    diff --git a/template/header.html b/template/header.html index a5c4158..0e120eb 100755 --- a/template/header.html +++ b/template/header.html @@ -101,14 +101,6 @@ -
  • - - Discord - - - -
  • - From af060c932f0fa16f692c8183006a5925e4b233bf Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Sun, 20 Jan 2019 14:05:06 +0100 Subject: [PATCH 047/134] update pool info from config --- index.php | 12 ++++++++++ template/info.html | 57 +++++++++++++--------------------------------- 2 files changed, 28 insertions(+), 41 deletions(-) diff --git a/index.php b/index.php index aaf3858..16b5ee1 100755 --- a/index.php +++ b/index.php @@ -169,6 +169,18 @@ //} elseif ($q == "benchmarks") { // $tpl->draw("benchmarks"); } elseif ($q == "info") { + + $tpl->assign("minpayout", number_format($pool_config['min_payout'],2)); + $tpl->assign("fee", number_format($pool_config['fee']*100,1)); + $tpl->assign("cpu_deadline", number_format($pool_config['max_deadline'])); + $tpl->assign("gpu_deadline", number_format($pool_config['max_deadline_gpu'])); + $tpl->assign("poolwallet", $pool_config['address']); + $tpl->assign("current_reward", $pool_config['current_reward']*100); + $tpl->assign("miner_reward", $pool_config['miner_reward']*100); + $tpl->assign("historic_reward", $pool_config['historic_reward']*100); + $tpl->assign("server", gethostname()); + + $tpl->draw("info"); } diff --git a/template/info.html b/template/info.html index 730f485..25dfca2 100755 --- a/template/info.html +++ b/template/info.html @@ -4,50 +4,25 @@
    - Mining Info + Information:
    -

    Pool Address: http://aropool.com

    -

    Pool Fee: 2%

    -

    Min Payment: 3 ARO

    +

    Pool address: http://pool.arionum.nl

    +

    DL: {$cpu_deadline} (CBlocks) / {$gpu_deadline} (GBlocks)

    +

    Degradation of historic shares: 2% +

    Pool fee: {$fee}%

    +

    Minimum payout: {$minpayout} aro

    Block confirmation: 10 blocks

    -

    Reward split: 40% miner, 30% current shares, 30% historic shares

    - -

    - - -

    How to mine:

    -
    Windows
    -

    In order to mine on our pool, you will need to download the Arionum Wallet from arionum.com

    -

    Install the LightArionum app, search for the integrated "Miner" tab and click "Start Mining". This is all, you are now mining on our pool!

    -

    If you are a power user and you would like to get maximum mining performance, you should use Dan's java miner which is available here. -
    - -
    -
    -

    Linux/Mac
    -

    Under linux and mac, we recommend using Dan's java Miner, which is available here.

    -

    A full guide can be found on the above url.

    - - -




    -

    How to mine: (old version)

    -

    In order to mine on our pool you will need to first create a wallet. You can download our bundled miner + cli wallet from here.

    -

    Extract the archive exactly in c:\, it is absolutely necessary that the files are located in this directory as php has absolute paths.

    -

    Download and install the windows openssl binaries located here (x64 light version). After the installation it's necessary to reboot the computer! -

    The Windows version on your computer must be installed using the x64 architecture

    -

    Run the file Start-Wallet.bat, enter "balance" as the first command and follow the on-screen instructions. Copy your wallet address when printed.

    -

    Edit Auto-Miner.bat and replace CHANGE-ADDRESS with the address generated above.

    -

    Execute Auto-Miner.bat and it should start mining on our pool.

    -

    The miner uses by default 4 cores. If you'd like to mine with more cores, simply start the Auto-Miner.bat again.

    -
    -

    In case you get an error regarding a missing DLL, you will need the Microsoft Visual C++ Runtime package. This can be done downloaded here: https://www.microsoft.com/en-us/download/details.aspx?id=48145> -

    -For linux: -

    Install php 7.2 and php-gmp

    -

    Download the latest miner from https://github.com/arionum/miner

    -

    Change permissions to 755: chmod 755 miner

    -

    Run it in the format: ./miner pool http://aropool.com (replace YOUR-ADDRESS with your actual address)

    +

    Reward split: {$historic_reward}% historic shares, {$current_reward}% current shares and {$miner_reward}% for block finder

    +

    Payout schedule: every hour

    +

    Pool balance: Block Explorer

    +
    +

    This is an independent pool, which means you will only receive a payment when the pool finds a block.

    +
    +

    This service is provided as is.
    + For more information: See the ARO discord.

    +
    + Server: {$server}
    From 9a6ca8b27bdb04f2a1bf961d9dd18114a5dd685f Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Sun, 20 Jan 2019 14:15:36 +0100 Subject: [PATCH 048/134] addition pool info --- config-sample.php | 6 ++++++ index.php | 9 ++++++--- template/info.html | 4 ++-- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/config-sample.php b/config-sample.php index 9adb7e9..b98788d 100644 --- a/config-sample.php +++ b/config-sample.php @@ -74,3 +74,9 @@ // The message included in payments $pool_config['payout_message'] = ''; + + +// Additional poolinfo +$pool_config['pool_url'] = 'http://pooladdress.here'; +$pool_config['pool_deprecation'] = 0.02; + diff --git a/index.php b/index.php index 16b5ee1..7db7ccc 100755 --- a/index.php +++ b/index.php @@ -175,10 +175,13 @@ $tpl->assign("cpu_deadline", number_format($pool_config['max_deadline'])); $tpl->assign("gpu_deadline", number_format($pool_config['max_deadline_gpu'])); $tpl->assign("poolwallet", $pool_config['address']); - $tpl->assign("current_reward", $pool_config['current_reward']*100); - $tpl->assign("miner_reward", $pool_config['miner_reward']*100); - $tpl->assign("historic_reward", $pool_config['historic_reward']*100); + $tpl->assign("current_reward", $pool_config['current_reward']*100,0); + $tpl->assign("miner_reward", $pool_config['miner_reward']*100,0); + $tpl->assign("historic_reward", $pool_config['historic_reward']*100,0); $tpl->assign("server", gethostname()); + $tpl->assign("pool_url", $pool_config['pool_url']); + $tpl->assign("pool_deprecation", number_format($pool_config['pool_deprecation']*100,1)); + $tpl->draw("info"); diff --git a/template/info.html b/template/info.html index 25dfca2..70fe066 100755 --- a/template/info.html +++ b/template/info.html @@ -7,9 +7,9 @@ Information:
    -

    Pool address: http://pool.arionum.nl

    +

    Pool address: {$pool_url}

    DL: {$cpu_deadline} (CBlocks) / {$gpu_deadline} (GBlocks)

    -

    Degradation of historic shares: 2% +

    Degradation of historic shares: {$pool_deprecation}%

    Pool fee: {$fee}%

    Minimum payout: {$minpayout} aro

    Block confirmation: 10 blocks

    From 012be344d5d0e505630b653f77269791a4e10ed4 Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Sun, 20 Jan 2019 14:45:32 +0100 Subject: [PATCH 049/134] pool name to config --- config-sample.php | 1 + index.php | 1 + template/header.html | 8 ++++---- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/config-sample.php b/config-sample.php index b98788d..161de32 100644 --- a/config-sample.php +++ b/config-sample.php @@ -79,4 +79,5 @@ // Additional poolinfo $pool_config['pool_url'] = 'http://pooladdress.here'; $pool_config['pool_deprecation'] = 0.02; +$pool_config['pool_name'] = 'Your Poolname here'; diff --git a/index.php b/index.php index 7db7ccc..29749d7 100755 --- a/index.php +++ b/index.php @@ -15,6 +15,7 @@ $tpl = new Tpl(); $tpl->assign("q", $q); $tpl->assign("id", $id); +$tpl->assign("pool_name", $pool_config['pool_name']); $tpl->draw('header'); if ($q == "") { diff --git a/template/header.html b/template/header.html index 0e120eb..d7b18be 100755 --- a/template/header.html +++ b/template/header.html @@ -4,9 +4,9 @@ - Arionum Pool - - + {$pool_name} + + @@ -54,7 +54,7 @@
    + + + + + + + + + + + + From a57f49c6835ac7356933d4e89ca1fb090cc5d9bf Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Sun, 20 Jan 2019 17:09:23 +0100 Subject: [PATCH 052/134] fix for multiple payments in one batch, tx-link in account page --- api.php | 2 +- index.php | 3 ++- template/account.html | 4 ++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/api.php b/api.php index 285a482..661e1ab 100644 --- a/api.php +++ b/api.php @@ -63,7 +63,7 @@ $miner=$m; $total_paid=$db->single("SELECT total_paid FROM miners WHERE id='$m'"); $pending=$db->single("SELECT pending FROM miners WHERE id='$m'"); - $last_payment=$db->single("SELECT val FROM payments WHERE address='$m' AND done=1 ORDER by height DESC LIMIT 1"); + $last_payment=$db->single("SELECT SUM(val) FROM payments WHERE txn=:lasttxn",[":lasttxn"=>$last_payment_txn]); $past_24h=$db->single("SELECT SUM(val) FROM payments WHERE address='$m' AND height>=$yesterday_block AND done=1"); echo json_encode(array("miner"=>$miner, "total paid"=>$total_paid, "pending"=>$pending, "past_24h"=>$past_24h, "last_payment"=>$last_payment, "last_payment_date"=>$last_payment_humantime, "last_payment_unixtime"=>$last_payment_time)); } diff --git a/index.php b/index.php index b497f83..4a7f73c 100755 --- a/index.php +++ b/index.php @@ -120,7 +120,7 @@ $yesterday_block=$aro->single("SELECT height+1 FROM blocks WHERE date<=$yesterday ORDER by height DESC LIMIT 1"); $last_payment_txn=$db->single("SELECT txn FROM payments WHERE address=:miner AND done=1 ORDER by height DESC LIMIT 1", [":miner" => $id]); $last_payment_time=$aro->single("SELECT date FROM transactions WHERE id=$last_payment_txn"); - $last_payment=$db->single("SELECT val FROM payments WHERE address=:miner AND done=1 ORDER by height DESC LIMIT 1", [":miner" => $id]); + $last_payment=$db->single("SELECT SUM(val) FROM payments WHERE txn=:lasttxn", [":lasttxn" => $last_payment_txn]); $past_24h=$db->single("SELECT SUM(val) FROM payments WHERE address=:miner AND height>=$yesterday_block AND done=1", [":miner" => $id]); $r = $db->run("SELECT * FROM miners WHERE id=:miner", [":miner" => $id] ); @@ -133,6 +133,7 @@ $x['total_paid'] = number_format($x['total_paid'], 2); $x['last_payment'] = number_format($last_payment, 2); $x['last_paid'] = date('Y/m/d H:i:s', $last_payment_time); + $x['last_txn'] = $last_payment_txn; $x['24h_paid'] = number_format($past_24h,2); $x['updated'] = date('Y/m/d H:i:s', $x['updated']); $b[] = $x; diff --git a/template/account.html b/template/account.html index 4b7826d..5dfa3ff 100755 --- a/template/account.html +++ b/template/account.html @@ -43,6 +43,10 @@ + + + + From e4a5f37611d72fdde4c0547ff6ef134e53a1a27a Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Sun, 20 Jan 2019 17:28:13 +0100 Subject: [PATCH 053/134] check if degradation rate is set in config --- poolsanity.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/poolsanity.php b/poolsanity.php index d82e5af..819ce24 100644 --- a/poolsanity.php +++ b/poolsanity.php @@ -35,6 +35,8 @@ function shut_down() die('This should only be run as cli'); } +if ($pool_config['pool_degradation']==null) {die('Degradation rate not set in config');} + $current = 0; $ticks = 0; while (1) { From ca5bb164ad09ec06618093ffc2d84b591a0b0793 Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Sun, 20 Jan 2019 17:40:58 +0100 Subject: [PATCH 054/134] fix --- poolsanity.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poolsanity.php b/poolsanity.php index 819ce24..7ec6d25 100644 --- a/poolsanity.php +++ b/poolsanity.php @@ -44,7 +44,7 @@ function shut_down() $ck = $aro->single('SELECT height FROM blocks ORDER by height DESC LIMIT 1'); if ($ck !== $current && $ck) { $current = $ck; - $db->run('UPDATE miners SET historic=historic-historic*:dr+shares, shares=0,bestdl=1000000', [':dr' => $pool_config['pool_degradation']]); + $db->run('UPDATE miners SET historic=historic+shares-historic*:dr, shares=0,bestdl=1000000', [':dr' => $pool_config['pool_degradation']]); $db->run('TRUNCATE table nonces'); $r = $db->run('SELECT * FROM miners WHERE historic>0'); From 0c3819b93ff12b6d655c13bedced37c054f46494 Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Sun, 20 Jan 2019 17:47:03 +0100 Subject: [PATCH 055/134] revert deg in poolsanity --- poolsanity.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/poolsanity.php b/poolsanity.php index 7ec6d25..bccf16e 100644 --- a/poolsanity.php +++ b/poolsanity.php @@ -44,7 +44,9 @@ function shut_down() $ck = $aro->single('SELECT height FROM blocks ORDER by height DESC LIMIT 1'); if ($ck !== $current && $ck) { $current = $ck; - $db->run('UPDATE miners SET historic=historic+shares-historic*:dr, shares=0,bestdl=1000000', [':dr' => $pool_config['pool_degradation']]); + $db->run('UPDATE miners SET historic=historic*0.98+shares, shares=0,bestdl=1000000'); +// revert +// $db->run('UPDATE miners SET historic=historic+shares-historic*:dr, shares=0,bestdl=1000000', [':dr' => $pool_config['pool_degradation']]); $db->run('TRUNCATE table nonces'); $r = $db->run('SELECT * FROM miners WHERE historic>0'); From ff4955acd14bb2fcbcce348223806f63e7f44b28 Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Sun, 20 Jan 2019 18:20:41 +0100 Subject: [PATCH 056/134] fixed --- poolsanity.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/poolsanity.php b/poolsanity.php index bccf16e..7ec6d25 100644 --- a/poolsanity.php +++ b/poolsanity.php @@ -44,9 +44,7 @@ function shut_down() $ck = $aro->single('SELECT height FROM blocks ORDER by height DESC LIMIT 1'); if ($ck !== $current && $ck) { $current = $ck; - $db->run('UPDATE miners SET historic=historic*0.98+shares, shares=0,bestdl=1000000'); -// revert -// $db->run('UPDATE miners SET historic=historic+shares-historic*:dr, shares=0,bestdl=1000000', [':dr' => $pool_config['pool_degradation']]); + $db->run('UPDATE miners SET historic=historic+shares-historic*:dr, shares=0,bestdl=1000000', [':dr' => $pool_config['pool_degradation']]); $db->run('TRUNCATE table nonces'); $r = $db->run('SELECT * FROM miners WHERE historic>0'); From 3d84bd6a3ad5b50bb25d6b2c96867bd30a92b351 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 20 Jan 2019 19:59:41 +0100 Subject: [PATCH 057/134] simplied block page + links --- template/header.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template/header.html b/template/header.html index d7b18be..6d7c8f7 100755 --- a/template/header.html +++ b/template/header.html @@ -54,7 +54,7 @@
    IDCPU hrGPU hrUpdatedNameCPU hashrateGPU hashrateLast Update
    IDCPU hrGPU hrUpdatedNameCPU hashrateGPU hashrateLast Update
    Pending balance:{$value.pending}{$value.pending} ARO
    Total paid:{$value.total_paid}{$value.total_paid} ARO
     
    CPU hashrate:{$value.cpuhr}{$value.cpuhr} h/s
    GPU hashrate:{$value.gpuhr}{$value.gpuhr} h/s
     
     
    CPU hashrate:{$value.cpuhr} h/s{$hashrate['cpuhr']} h/s
    GPU hashrate:{$value.gpuhr} h/s{$hashrate['gpuhr']} h/s
     
    Pending balance:
    IDAddressBlock Height ValueTransaction IDAddressTX
    IDAddressBlock Height ValueTransaction IDAddressTX
    {$value.id}{$value.height}
    {$value.val}
    {$value.address}{$value.val}{$value.txn}Link
    Total paid: {$value.total_paid} ARO
    Paid last 24 hours:{$value.24h_paid} ARO
    Last payment:{$value.last_payment} ARO
    Last paid:{$value.last_paid}
     
    Last paid: {$value.last_paid}
    Check last transaction:Link
     
    - - - + + - - - + + @@ -31,10 +29,9 @@ {loop="$blocks"} - - - + + {/loop} diff --git a/template/header.html b/template/header.html index d7b18be..ce4b724 100755 --- a/template/header.html +++ b/template/header.html @@ -2,7 +2,6 @@ - {$pool_name} From ae32fc50759a2f98c560dabcc8e30d1997fba8d8 Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Sun, 20 Jan 2019 22:10:41 +0100 Subject: [PATCH 060/134] header --- template/header.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template/header.html b/template/header.html index e807305..ce4b724 100755 --- a/template/header.html +++ b/template/header.html @@ -53,7 +53,7 @@ - + - + diff --git a/template/index.html b/template/index.html index 279682a..96b01c5 100755 --- a/template/index.html +++ b/template/index.html @@ -78,7 +78,7 @@
    {$gpu_ext}
    - CPU & GPU hashrate + CPU & GPU blocks
    @@ -145,8 +145,8 @@
    {$gpu_ext}
    - - + + @@ -158,8 +158,8 @@
    {$gpu_ext}
    - - + + From 9546fe7c45122dd8ce4caf290024e8bc5248cc0d Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Sun, 20 Jan 2019 23:40:26 +0100 Subject: [PATCH 063/134] unit h/s --- template/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/template/index.html b/template/index.html index 96b01c5..567f837 100755 --- a/template/index.html +++ b/template/index.html @@ -171,8 +171,8 @@
    {$gpu_ext}
    - - + + From 81ba73a36d1af48a62e8f540ec0d2fdcb1c204d3 Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Sun, 20 Jan 2019 23:43:38 +0100 Subject: [PATCH 064/134] legend --- template/index.html | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/template/index.html b/template/index.html index 567f837..c0e7d8b 100755 --- a/template/index.html +++ b/template/index.html @@ -145,8 +145,8 @@
    {$gpu_ext}
    - - + + @@ -158,8 +158,8 @@
    {$gpu_ext}
    - - + + @@ -171,8 +171,8 @@
    {$gpu_ext}
    - - + + From b76557f2dbfd48ea0633d9033741a8c09fe7c640 Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Mon, 21 Jan 2019 11:01:24 +0100 Subject: [PATCH 065/134] distinguish between no payment history or pending payment --- api.php | 1 - index.php | 3 +++ template/account.html | 16 ++++++++-------- template/index.html | 8 ++++---- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/api.php b/api.php index a4ef752..3c7e73d 100644 --- a/api.php +++ b/api.php @@ -77,5 +77,4 @@ $last_won=$db->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); $last_won_time=$aro->single("SELECT date FROM blocks WHERE height=:h",[":h"=>$last_won]); echo json_encode(array("cpu_hr"=>$total_hr, "gpu_hr"=>$total_gpu, "current_block_height"=>$current, "last_won_block"=>$last_won, "last_won_block_time"=>$last_won_time, "miners"=>$miners, "fee"=>$pool_config['fee'])); - echo "\n\nUsage api.php/q=status or /q=miner&m=walletaddress or /q=payments&m=walletaddress"; } diff --git a/index.php b/index.php index 38b25c8..5b0a6b9 100755 --- a/index.php +++ b/index.php @@ -136,6 +136,9 @@ $x['last_payment'] = number_format($last_payment, 2); $x['last_paid'] = date('Y/m/d H:i:s', $last_payment_time); if ($last_payment_time == false) { + $x['last_paid'] = "Payment in process"; + } + if ($last_payment == 0 ) { $x['last_paid'] = "No payment yet"; } $x['last_txn'] = $last_payment_txn; diff --git a/template/account.html b/template/account.html index 4b5f458..caba389 100755 --- a/template/account.html +++ b/template/account.html @@ -12,11 +12,11 @@ - + - + @@ -32,7 +32,7 @@ - + @@ -40,7 +40,7 @@ - + @@ -85,8 +85,8 @@ - - + + @@ -94,8 +94,8 @@ - - + + diff --git a/template/index.html b/template/index.html index c0e7d8b..b6c2e1f 100755 --- a/template/index.html +++ b/template/index.html @@ -145,8 +145,8 @@
    {$gpu_ext}
    - - + + @@ -158,8 +158,8 @@
    {$gpu_ext}
    - - + + From 59cc733b087ba4047a3f4b5f470420f30dd80792 Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Mon, 21 Jan 2019 11:06:11 +0100 Subject: [PATCH 066/134] no payment time vs payment in mempool fixed in api --- api.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/api.php b/api.php index 3c7e73d..87ac49b 100644 --- a/api.php +++ b/api.php @@ -63,6 +63,12 @@ $total_paid=$db->single("SELECT total_paid FROM miners WHERE id='$m'"); $pending=$db->single("SELECT pending FROM miners WHERE id='$m'"); $last_payment=$db->single("SELECT SUM(val) FROM payments WHERE txn=:lasttxn",[":lasttxn"=>$last_payment_txn]); + if ($last_payment_time == false) { + $last_payment_time = "Payment in process"; + } + if ($last_payment == 0 ) { + $last_payment_time = "No payment yet"; + } $past_24h=$db->single("SELECT SUM(val) FROM payments WHERE address='$m' AND height>=$yesterday_block AND done=1"); echo json_encode(array("miner"=>$miner, "total paid"=>$total_paid, "pending"=>$pending, "past_24h"=>$past_24h, "last_payment"=>$last_payment, "last_payment_date"=>$last_payment_time)); } From c96d912bb5e5bb8338d0403ce5faf017fdec352b Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Tue, 22 Jan 2019 23:12:54 +0100 Subject: [PATCH 067/134] bugfix last payment during pending --- .gitignore | 1 + api.php | 2 +- index.php | 2 +- payments.php | 17 ++++++++++++----- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index d1f5879..eac5cdc 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ /config.php /run.sh /dood.sh +/todo.txt diff --git a/api.php b/api.php index 87ac49b..2caf906 100644 --- a/api.php +++ b/api.php @@ -62,7 +62,7 @@ $miner=$m; $total_paid=$db->single("SELECT total_paid FROM miners WHERE id='$m'"); $pending=$db->single("SELECT pending FROM miners WHERE id='$m'"); - $last_payment=$db->single("SELECT SUM(val) FROM payments WHERE txn=:lasttxn",[":lasttxn"=>$last_payment_txn]); + $last_payment=$db->single("SELECT SUM(val) FROM payments WHERE txn=:lasttxn AND done=1",[":lasttxn"=>$last_payment_txn]); if ($last_payment_time == false) { $last_payment_time = "Payment in process"; } diff --git a/index.php b/index.php index 5b0a6b9..6c6a798 100755 --- a/index.php +++ b/index.php @@ -119,7 +119,7 @@ $yesterday_block=$aro->single("SELECT height+1 FROM blocks WHERE date<=$yesterday ORDER by height DESC LIMIT 1"); $last_payment_txn=$db->single("SELECT txn FROM payments WHERE address=:miner AND done=1 ORDER by height DESC LIMIT 1", [":miner" => $id]); $last_payment_time=$aro->single("SELECT date FROM transactions WHERE id=$last_payment_txn"); - $last_payment=$db->single("SELECT SUM(val) FROM payments WHERE txn=:lasttxn", [":lasttxn" => $last_payment_txn]); + $last_payment=$db->single("SELECT SUM(val) FROM payments WHERE txn=:lasttxn AND done=1", [":lasttxn" => $last_payment_txn]); $past_24h=$db->single("SELECT SUM(val) FROM payments WHERE address=:miner AND height>=$yesterday_block AND done=1", [":miner" => $id]); $r = $db->run("SELECT * FROM miners WHERE id=:miner", [":miner" => $id] ); diff --git a/payments.php b/payments.php index 559ac37..1d9a410 100644 --- a/payments.php +++ b/payments.php @@ -74,8 +74,8 @@ function pay_post($url, $data = []) $current = $aro->single('SELECT height FROM blocks ORDER by height DESC LIMIT 1'); echo "Current block $current\n"; - -$db->run('DELETE FROM miners WHERE historic + shares <= 20'); +// dit hele stuk kan naar update +$db->run('DELETE FROM miners WHERE historic + shares <= 50'); $db->run('UPDATE miners SET gpuhr = ( SELECT SUM(gpuhr) @@ -88,6 +88,7 @@ function pay_post($url, $data = []) FROM workers WHERE miner = miners.id AND updated > UNIX_TIMESTAMP() - 3600 )'); +// als de payment gerund wordt zet hij de totale pending die op de dashboard staat, dit kan naar update $db->run( 'UPDATE miners SET pending = ( @@ -98,7 +99,7 @@ function pay_post($url, $data = []) [':h' => $current - $blocks_paid] ); - +// r wordt dus opgebouwd uit 500 oude blocks tot t-minus 10 die niet zijn uitbetaald $r = $db->run( 'SELECT DISTINCT block FROM payments WHERE height<:h AND done=0 AND height>=:h2', [':h' => $current - 10, ':h2' => $current - $blocks_paid] @@ -107,6 +108,7 @@ function pay_post($url, $data = []) die("No payments pending\n"); } +// dit kan naar update $db->run('DELETE FROM miners WHERE shares=0 AND historic=0 AND updatedrun('DELETE FROM workers WHERE updatedsingle('SELECT COUNT(1) FROM blocks WHERE id=:id', [':id' => $x['block']]); if ($s === 0) { +// dit kunnen we dus aanpassen naar orphaned. block wordt niet nog een keer meegenomen want verdwijnt uit payments $db->run('DELETE FROM blocks WHERE id=:id', [':id' => $x['block']]); +// nu halen we de payments weg en wordt het block niet opnieuw geselecteerd bij de volgende payment cycle $db->run('DELETE FROM payments WHERE block=:id', [':id' => $x['block']]); echo "Deleted block: $x[block]\n"; } } - +// vanaf hier begint het echte payment gedeelte $total_paid = 0; $r = $db->run( 'SELECT SUM(val) as v, address FROM payments WHERE height<:h AND height>=:h2 AND done=0 GROUP by address', @@ -149,6 +153,7 @@ function pay_post($url, $data = []) 'private_key' => $private_key, 'public_key' => $public_key, 'version' => 1, +// hier kunnen we eventueel toevoegen dat als geen payout message dat ie dan domeinnaam pakt 'message' => $pool_config['payout_message'], ]); echo "$val\n"; @@ -181,7 +186,7 @@ function pay_post($url, $data = []) $not = $db->single('SELECT SUM(val) FROM payments WHERE done=0'); echo "Pending balance: $not\n"; - +// hier wordt het pending op de dashboard aangepast $db->run( 'UPDATE miners SET pending = ( @@ -192,4 +197,6 @@ function pay_post($url, $data = []) [':h' => $current - $blocks_paid] ); +// dit is aan te passen voor als je dat juist niet wilt. uitbetaald en 1000 blocks geleden betekent delete $db->run('DELETE FROM payments WHERE done=1 AND height<:h', [':h' => $current - 1000]); + From c73594330b730852dd071f5aeaf8a556957cfe62 Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Wed, 6 Feb 2019 23:05:41 +0100 Subject: [PATCH 068/134] split updating hr from payments/sanity --- update.php | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 update.php diff --git a/update.php b/update.php new file mode 100644 index 0000000..bfaacfc --- /dev/null +++ b/update.php @@ -0,0 +1,93 @@ + 3600) { + system("rm -rf $pid112"); + } + die("\n\n### RUNNING ### -- PID: $pid112\n\n"); +} +system("touch $pid112"); +function shut_down() +{ + global $pid112; + system("rm -rf $pid112"); + echo "\n# ShutDown #\n"; +} + +register_shutdown_function('shut_down'); +############################################### + +set_time_limit(0); +if (PHP_SAPI !== 'cli') { + die('This should only be run as cli'); +} + +require_once __DIR__.'/db.php'; + +echo "\n----------------------------------------------------------------------------------\n"; +$current = $aro->single('SELECT height FROM blocks ORDER by height DESC LIMIT 1'); +echo "Current block $current\n"; + +$db->run('DELETE FROM miners WHERE historic + shares <= 50'); +$db->run('UPDATE miners + SET gpuhr = ( + SELECT SUM(gpuhr) + FROM workers + WHERE miner = miners.id AND updated > UNIX_TIMESTAMP() - 750 + )'); +$db->run('UPDATE miners + SET hashrate = ( + SELECT SUM(hashrate) + FROM workers + WHERE miner = miners.id AND updated > UNIX_TIMESTAMP() - 750 + )'); +//uit sanity + + $r = $db->run('SELECT * FROM miners WHERE historic + shares >0'); + $total_hr = 0; + $total_gpu = 0; + foreach ($r as $x) { + $thr = $db->row( + 'SELECT SUM(hashrate) AS cpu, SUM(gpuhr) AS gpu + FROM workers + WHERE miner = :m AND updated > UNIX_TIMESTAMP() - 750', + [':m' => $x['id']] + ); + if ($x['historic'] / $thr['cpu'] < 2 || $x['historic'] / $thr['gpu'] < 2) { + $thr['cpu'] = 0; + $thr['gpu'] = 0; + } + $total_hr += $thr['cpu']; + $total_gpu += $thr['gpu']; + } + echo "Total hr: $total_hr, total gpuhr: $total_gpu\n"; + $db->run("UPDATE info SET val=:thr WHERE id='total_hash_rate'", [':thr' => $total_hr]); + $db->run("UPDATE info SET val=:thr WHERE id='total_gpu_hr'", [':thr' => $total_gpu]); + +//cleanup + +$db->run('DELETE FROM miners WHERE shares=0 AND historic=0 AND updatedrun('DELETE FROM workers WHERE updatedrun( + 'UPDATE miners + SET pending = ( + SELECT SUM(val) + FROM payments + WHERE done = 0 AND payments.address = miners.id AND height >= :h + )', + [':h' => $current - $blocks_paid] +); + + From 45146e59a48c4ee73790e72de65395bc9cbad742 Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Wed, 6 Feb 2019 23:07:06 +0100 Subject: [PATCH 069/134] split reporting from payments/sanity --- README.md | 89 ++++++++++++++++++++++----------------------- payments.php | 29 --------------- poolsanity.php | 22 ----------- template/index.html | 2 +- template/info.html | 2 +- update.php | 2 +- 6 files changed, 47 insertions(+), 99 deletions(-) diff --git a/README.md b/README.md index c79826e..785d7bc 100644 --- a/README.md +++ b/README.md @@ -1,46 +1,45 @@ -# pool +# Modifications + +This repository is based on ario's fork of the official arionum pool code. +System requirements are indentical to the official pool code. + +Warning: because of additions to the config file, do not simply replace the php-files without making sure all variables are added to the config. + +## Bigger changes: +- Hashreporting has been removed from payments/poolsanity to a seperate updater. Updating hashrates on the website can be done independently of payment-cycle, and db is no longer only updated when moving to next block. Be aware that the 10minute update interval from the clients is fixed. As is the 'first appearance' in the db after submitting first nonce +- Api.php has been expanded with more options +- Last payment, payment date, payments in 24h included on individual miner page and api +- TODO: Orphaned blocks are no longer removed from the list but marked as orphaned. Pending payments are removed. +- TODO: Workerid is changed to workername+address to create a unique key without having to alter the database. It prevents changes to client (new address/new workername) not being updated in the workerlist and it also prevents 2 miners using the same workername to be misreported as one. It will NOT change the fact that miners using one single name for many workers causing their hashrate being reported as once worker. This would require a uniqueID being send from the worker +- TODO: implement the possible external argon2 validation through config file +- TODO: restructure api.php +- TODO: either update miner hr more often or insert sum workerHR into dashboard/individual pages/api + +## Medium changes: +- The 'last-update' values of workers has been reduced from 1hr to 720s to keep the calculation of total hashrate more precise +- The 'time-out' value of miners has been enlarged to have miners remain in history when they are away for a while. For individual workers it's set to 30minutes +- The 'cut-off' of last remaining historical shares has been changed to prevent ghost miners remaining in the list indefinely (hist.shares would never reach zero) +- TODO: The last payments / last blocks 'truncation' has been moved to config in order to be able to adapt it to the size of the pool: small pool wants to keep history longer + +Minor changes: + +- Small update to dashboard layout based on reoccuring questions in discord +- To remove the constant confusion we are going to be consequent and call it GPU-*blocks* HR and NOT "GPU HR" (and CPU-*blocks* HR instead of "CPU HR") everywhere on the site. +- Removal of long TX addresses in payout page, replaced with links to block explorer +- Bugfix to make poolsanity being able to be started as service +- Bugfix in template/index.html of html code the purple box showing hashrates. Also: C-HR is shown left, G-HR right, just as in all tables. +- Degradation, last-payments-variable, poolname etc. have been moved to config +- Info page: old mining info removed, pool details (rewards/degradation/payout/DL) are read from the config file +- Templates: pool name set in config +- On individual miner page: best DL is 1000000 replaced with No Nonce submitted yet +- On individual miner page: when last payment is still in mempool it's shown as Payment In Process +- On individual miner page: when no payment ever last payment date is shown as No Payment Yet +- TODO: Info page: discord handle can be set in config +- TODO: If no payment message is set in config it takes the pool hostname from config + + +With the current setup payments are split from updates +Run payments to crontab every x hours, min payment can remain low, but it will prevent big miners from massive small payments +Run update in seperate crontab every 1 minute. +Optional: Run poolsanity as systemd-service -A proof of concept pool for Arionum - -Live version: http://aropool.com - -The pool requires a full node running on the same server (on a different subdomain) as it uses it's libraries and db connection. - -## Install - -The requirements are the same as for the arionum node: - -- php 7.2 (with argon2) -- php-openssl -- php-gmp -- php-bcmath - -after cloning repository do `composer update` - it will download required code - -## Usage - -1. Create a new database for the pool (separate from the node one). -2. Edit the `config.php` and follow the instructions inside. -3. Import the `contrib/pool.sql` to your NEW mysql database. -4. Chmod the cache directory using `chmod 777 cache -R`. -5. Create a cron entry using the following format: - ```bash - */10 * * * * user php /path/to/pool/payments.php - ``` - -Start the poolsanity by running: - -```bash -php /path/to/pool/poolsanity.php &>/dev/null & -``` - -## Notes - -For the template system, we use [raintpl3]. - -Please use a new name instead of [aropool] to avoid user confusion! - -This project is early alpha, bugs may be found, functions might not work properly etc. - -[aropool]: https://aropool.com -[raintpl3]: https://github.com/feulf/raintpl3 diff --git a/payments.php b/payments.php index 1d9a410..520b655 100644 --- a/payments.php +++ b/payments.php @@ -74,20 +74,6 @@ function pay_post($url, $data = []) $current = $aro->single('SELECT height FROM blocks ORDER by height DESC LIMIT 1'); echo "Current block $current\n"; -// dit hele stuk kan naar update -$db->run('DELETE FROM miners WHERE historic + shares <= 50'); -$db->run('UPDATE miners - SET gpuhr = ( - SELECT SUM(gpuhr) - FROM workers - WHERE miner = miners.id AND updated > UNIX_TIMESTAMP() - 3600 - )'); -$db->run('UPDATE miners - SET hashrate = ( - SELECT SUM(hashrate) - FROM workers - WHERE miner = miners.id AND updated > UNIX_TIMESTAMP() - 3600 - )'); // als de payment gerund wordt zet hij de totale pending die op de dashboard staat, dit kan naar update $db->run( 'UPDATE miners @@ -108,10 +94,6 @@ function pay_post($url, $data = []) die("No payments pending\n"); } -// dit kan naar update -$db->run('DELETE FROM miners WHERE shares=0 AND historic=0 AND updatedrun('DELETE FROM workers WHERE updatedsingle('SELECT SUM(val) FROM payments WHERE done=0'); echo "Pending balance: $not\n"; -// hier wordt het pending op de dashboard aangepast -$db->run( - 'UPDATE miners - SET pending = ( - SELECT SUM(val) - FROM payments - WHERE done = 0 AND payments.address = miners.id AND height >= :h - )', - [':h' => $current - $blocks_paid] -); - // dit is aan te passen voor als je dat juist niet wilt. uitbetaald en 1000 blocks geleden betekent delete $db->run('DELETE FROM payments WHERE done=1 AND height<:h', [':h' => $current - 1000]); diff --git a/poolsanity.php b/poolsanity.php index 7ec6d25..b6b0b26 100644 --- a/poolsanity.php +++ b/poolsanity.php @@ -46,28 +46,6 @@ function shut_down() $current = $ck; $db->run('UPDATE miners SET historic=historic+shares-historic*:dr, shares=0,bestdl=1000000', [':dr' => $pool_config['pool_degradation']]); $db->run('TRUNCATE table nonces'); - - $r = $db->run('SELECT * FROM miners WHERE historic>0'); - $total_hr = 0; - $total_gpu = 0; - foreach ($r as $x) { - $thr = $db->row( - 'SELECT SUM(hashrate) AS cpu, SUM(gpuhr) AS gpu - FROM workers - WHERE miner = :m AND updated > UNIX_TIMESTAMP() - 3600', - [':m' => $x['id']] - ); - if ($x['historic'] / $thr['cpu'] < 2 || $x['historic'] / $thr['gpu'] < 2) { - $thr['cpu'] = 0; - $thr['gpu'] = 0; - echo "$x[id] [$x[historic]] -> ".$x['historic'] / $thr[cpu]."\n"; - } - $total_hr += $thr['cpu']; - $total_gpu += $thr['gpu']; - } - echo "Total hr: $total_hr\n"; - $db->run("UPDATE info SET val=:thr WHERE id='total_hash_rate'", [':thr' => $total_hr]); - $db->run("UPDATE info SET val=:thr WHERE id='total_gpu_hr'", [':thr' => $total_gpu]); } $max_dl = ($current % 2) ? $pool_config['max_deadline_gpu'] : $pool_config['max_deadline']; diff --git a/template/index.html b/template/index.html index b6c2e1f..85a0b6d 100755 --- a/template/index.html +++ b/template/index.html @@ -135,7 +135,7 @@
    {$gpu_ext}
    Total Historic Shares: {$total_historic} - Hashrates and payments are updated periodically + Updated periodically
    diff --git a/template/info.html b/template/info.html index e46dcdb..e7f996c 100755 --- a/template/info.html +++ b/template/info.html @@ -20,7 +20,7 @@

    Pool balance: Block Exp

    This is an independent pool, which means you will only receive a payment when the pool finds a block.


    This service is provided as is.
    - For more information: See the
    ARO discord.

    + For information and support: hendrik@ARO discord.


    Server: {$server} diff --git a/update.php b/update.php index bfaacfc..80fe2e7 100644 --- a/update.php +++ b/update.php @@ -77,7 +77,7 @@ function shut_down() //cleanup $db->run('DELETE FROM miners WHERE shares=0 AND historic=0 AND updatedrun('DELETE FROM workers WHERE updatedrun('DELETE FROM workers WHERE updatedrun( From 8651c234dad8a99a50c22fd295491e99ee23aad3 Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Wed, 6 Feb 2019 23:42:11 +0100 Subject: [PATCH 070/134] miner removal parameters set --- README.md | 4 ++-- template/blocks.html | 2 +- update.php | 5 +++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 785d7bc..1f591ed 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,8 @@ Warning: because of additions to the config file, do not simply replace the php- - TODO: either update miner hr more often or insert sum workerHR into dashboard/individual pages/api ## Medium changes: -- The 'last-update' values of workers has been reduced from 1hr to 720s to keep the calculation of total hashrate more precise -- The 'time-out' value of miners has been enlarged to have miners remain in history when they are away for a while. For individual workers it's set to 30minutes +- The 'last-update' values of workers has been reduced from 1hr to 720s to keep the calculation of total hashrate more precise, this means workers not having reported in during the last 12 minutes are not used int he calculation +- The 'time-out' value of miners has been enlarged to have miners remain in history when they are away for a while (max 24h). For individual workers it's set to 30minutes. A miner will be deleted from history if the historical share rate drops below 50 AND he has not submitted a nonce in the last 24h - The 'cut-off' of last remaining historical shares has been changed to prevent ghost miners remaining in the list indefinely (hist.shares would never reach zero) - TODO: The last payments / last blocks 'truncation' has been moved to config in order to be able to adapt it to the size of the pool: small pool wants to keep history longer diff --git a/template/blocks.html b/template/blocks.html index 40eb1f5..63c937b 100755 --- a/template/blocks.html +++ b/template/blocks.html @@ -4,7 +4,7 @@
    - Last 100 won blocks + Last 1000 won blocks
    diff --git a/update.php b/update.php index 80fe2e7..1d7c02b 100644 --- a/update.php +++ b/update.php @@ -38,7 +38,7 @@ function shut_down() $current = $aro->single('SELECT height FROM blocks ORDER by height DESC LIMIT 1'); echo "Current block $current\n"; -$db->run('DELETE FROM miners WHERE historic + shares <= 50'); +//$db->run('DELETE FROM miners WHERE historic + shares <= 50'); $db->run('UPDATE miners SET gpuhr = ( SELECT SUM(gpuhr) @@ -76,7 +76,8 @@ function shut_down() //cleanup -$db->run('DELETE FROM miners WHERE shares=0 AND historic=0 AND updatedrun('DELETE FROM miners WHERE shares=0 AND historic=0 AND updatedrun('DELETE FROM miners WHERE shares + historic <=50 AND updatedrun('DELETE FROM workers WHERE updated Date: Wed, 6 Feb 2019 23:47:14 +0100 Subject: [PATCH 071/134] readme updated --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1f591ed..8fd3fb6 100644 --- a/README.md +++ b/README.md @@ -16,12 +16,12 @@ Warning: because of additions to the config file, do not simply replace the php- - TODO: either update miner hr more often or insert sum workerHR into dashboard/individual pages/api ## Medium changes: -- The 'last-update' values of workers has been reduced from 1hr to 720s to keep the calculation of total hashrate more precise, this means workers not having reported in during the last 12 minutes are not used int he calculation +- The 'last-update' values of workers has been reduced from 1hr to 720s to keep the calculation of total hashrate more precise, this means workers not having reported in during the last 12 minutes are not added to the miner total hr and pool hr - The 'time-out' value of miners has been enlarged to have miners remain in history when they are away for a while (max 24h). For individual workers it's set to 30minutes. A miner will be deleted from history if the historical share rate drops below 50 AND he has not submitted a nonce in the last 24h - The 'cut-off' of last remaining historical shares has been changed to prevent ghost miners remaining in the list indefinely (hist.shares would never reach zero) - TODO: The last payments / last blocks 'truncation' has been moved to config in order to be able to adapt it to the size of the pool: small pool wants to keep history longer -Minor changes: +## Minor changes: - Small update to dashboard layout based on reoccuring questions in discord - To remove the constant confusion we are going to be consequent and call it GPU-*blocks* HR and NOT "GPU HR" (and CPU-*blocks* HR instead of "CPU HR") everywhere on the site. From 8fd55f9175be3183795ee41116d39cd680b3269d Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Thu, 7 Feb 2019 00:10:02 +0100 Subject: [PATCH 072/134] sample config updated with new parameter --- README.md | 7 +++++-- config-sample.php | 5 ++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8fd3fb6..68c8e94 100644 --- a/README.md +++ b/README.md @@ -38,8 +38,11 @@ Warning: because of additions to the config file, do not simply replace the php- - TODO: If no payment message is set in config it takes the pool hostname from config -With the current setup payments are split from updates -Run payments to crontab every x hours, min payment can remain low, but it will prevent big miners from massive small payments +With the current setup payments are split from updates. + +Run payments to crontab every x hours, min payment can remain low, but it will prevent big miners from massive small payments. + Run update in seperate crontab every 1 minute. + Optional: Run poolsanity as systemd-service diff --git a/config-sample.php b/config-sample.php index 443701d..2dab9a0 100644 --- a/config-sample.php +++ b/config-sample.php @@ -78,14 +78,17 @@ $pool_config['min_payout'] = 3; // The message included in payments +// If no message is set the poolname will be used $pool_config['payout_message'] = ''; /* |-------------------------------------------------------------------------- -| Addiontal Pool Information +| Addiontal Pool Information / Settings |-------------------------------------------------------------------------- */ $pool_config['pool_url'] = 'http://pooladdress.here'; $pool_config['pool_name'] = 'Your Poolname here'; +// percentage of historical share degradation per block. 0.05 is best for pool with big miners, 0.02 for pool with small miners +$pool_config['pool_degradation'] = 0.05; From 60436d51e83c01f2d2751cfb8611581f771a7ae1 Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Thu, 7 Feb 2019 15:51:57 +0100 Subject: [PATCH 073/134] avergage gpu-hr and last nonce submitted by miner --- README.md | 3 +++ index.php | 34 +++++++++++++++++++++------------- template/account.html | 5 +++++ template/index.html | 2 +- 4 files changed, 30 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 68c8e94..173f9d3 100644 --- a/README.md +++ b/README.md @@ -25,13 +25,16 @@ Warning: because of additions to the config file, do not simply replace the php- - Small update to dashboard layout based on reoccuring questions in discord - To remove the constant confusion we are going to be consequent and call it GPU-*blocks* HR and NOT "GPU HR" (and CPU-*blocks* HR instead of "CPU HR") everywhere on the site. +- Added Average GPU Blocks HR next to CPU Blocks HR - Removal of long TX addresses in payout page, replaced with links to block explorer +- Blocks in Blocks Won are veryfiable on Block Explorer, for transparency - Bugfix to make poolsanity being able to be started as service - Bugfix in template/index.html of html code the purple box showing hashrates. Also: C-HR is shown left, G-HR right, just as in all tables. - Degradation, last-payments-variable, poolname etc. have been moved to config - Info page: old mining info removed, pool details (rewards/degradation/payout/DL) are read from the config file - Templates: pool name set in config - On individual miner page: best DL is 1000000 replaced with No Nonce submitted yet +- On individual miner page: added time of last submitted nonce - On individual miner page: when last payment is still in mempool it's shown as Payment In Process - On individual miner page: when no payment ever last payment date is shown as No Payment Yet - TODO: Info page: discord handle can be set in config diff --git a/index.php b/index.php index 6c6a798..1e54290 100755 --- a/index.php +++ b/index.php @@ -46,11 +46,12 @@ $historic[] = $x; } - $total_hr = $db->single("SELECT val FROM info WHERE id='total_hash_rate'"); - $avg_hr = floor($total_hr / $miners); + $total_hr=$db->single("SELECT val FROM info WHERE id='total_hash_rate'"); + $avg_hr = number_format(($total_hr / $miners), 0); if ($miners == 0) { $avg_hr = 0; } + if ($total_hr >= 1000000) { $total_hr_text = number_format($total_hr / 1000000, 2); $total_hr_ext = "MH/s"; @@ -62,31 +63,38 @@ $total_hr_ext = "H/s"; } - $total_hr=$db->single("SELECT val FROM info WHERE id='total_gpu_hr'"); + $tpl->assign("hr_ext", $total_hr_ext); + $tpl->assign("total_hr", $total_hr_text); - if($total_hr>=1000000){ - $total_gpu_text=number_format($total_hr/1000000,2); + + $total_gpuhr = $db->single("SELECT val FROM info WHERE id='total_gpu_hr'"); + $avg_gpuhr = number_format($total_gpuhr / $miners, 0); + if ($miners == 0) { + $avg_gpuhr = 0; + } + + if($total_gpuhr>=1000000){ + $total_gpu_text=number_format($total_gpuhr/1000000,2); $total_gpu_ext="MH/s"; } - elseif($total_hr>1000&&$total_hr<1000000) { - $total_gpu_text=number_format($total_hr/1000,2); + elseif($total_gpuhr>1000&&$total_gpuhr<1000000) { + $total_gpu_text=number_format($total_gpuhr/1000,2); $total_gpu_ext="kH/s"; } else { - $total_gpu_text=number_format($total_hr); + $total_gpu_text=number_format($total_gpuhr); $total_gpu_ext="H/s"; } - $tpl->assign("gpu_ext",$total_gpu_ext); - $tpl->assign("total_gpu",$total_gpu_text); + $tpl->assign("gpu_ext",$total_gpu_ext); + $tpl->assign("total_gpu",$total_gpu_text); $agem = time(); $agem = $current['date']; - $agem = ( time() - $current['date']) ; + $agem = ( time() - $current['date']); $tpl->assign("avg_hr", $avg_hr); - $tpl->assign("hr_ext", $total_hr_ext); - $tpl->assign("total_hr", $total_hr_text); + $tpl->assign("avg_gpuhr", $avg_gpuhr); $tpl->assign("miners", $miners); $tpl->assign("total_shares", $total_shares); $tpl->assign("total_historic", $total_historic); diff --git a/template/account.html b/template/account.html index caba389..55f1f56 100755 --- a/template/account.html +++ b/template/account.html @@ -64,6 +64,11 @@
    + + + + + {/loop}
    IDHeight RewardMinerHeight
    Miner
    IDHeight RewardMinerHeight
    Miner
    {$value.id}{$value.height} {$value.reward}{$value.miner}{$value.height}
    {$value.miner}
     
    CPU hashrate:CPU-blocks hashrate: {$hashrate['cpuhr']} h/s
    GPU hashrate:GPU-blocks hashrate: {$hashrate['gpuhr']} h/s
    Shares %CPU HRGPU HRCPU blocksGPU blocks Pending Total paid Miner
    Shares %CPU HRGPU HRCPU blocksGPU blocks Pending Total paid Miner
    {$value.historic} {$value.percent} %{$value.hashrate}{$value.gpuhr}{$value.hashrate} h/s{$value.gpuhr} h/s {$value.pending} {$value.total_paid} {$value.id}
    Shares %CPU blocksGPU blocksCPU-Bl. HRGPU-Bl. HR Pending Total paid Miner
    Shares %CPU blocksGPU blocksCPU-Bl. HRGPU-Bl. HR Pending Total paid Miner
    {$value.historic} {$value.percent} %{$value.hashrate} h/s{$value.gpuhr} h/s{$value.hashrate}{$value.gpuhr} {$value.pending} {$value.total_paid} {$value.id} 
    CPU-blocks hashrate:CPU blocks hashrate: {$hashrate['cpuhr']} h/s
    GPU-blocks hashrate:GPU blocks hashrate: {$hashrate['gpuhr']} h/s
    {$value.total_paid} ARO
    Paid last 24 hours:Paid in last 24 hours: {$value.24h_paid} ARO
    {$value.last_payment} ARO
    Last paid:Time of last payment: {$value.last_paid}
    NameCPU hashrateGPU hashrateCPU blocks hashrateGPU blocks hashrate Last Update
    NameCPU hashrateGPU hashrateCPU blocks hashrateGPU blocks hashrate Last Update
    Shares %CPU-Bl. HRGPU-Bl. HRCPU bl. HRGPU bl. HR Pending Total paid Miner
    Shares %CPU-Bl. HRGPU-Bl. HRCPU bl. HRGPU bl. HR Pending Total paid MinerBest nonce for current block (best DL): {$value.bestdl}
    Last nonce submitted:{$value.updated}
    diff --git a/template/index.html b/template/index.html index 85a0b6d..b9f1162 100755 --- a/template/index.html +++ b/template/index.html @@ -135,7 +135,7 @@
    {$gpu_ext}
    Total Historic Shares: {$total_historic} - Updated periodically + Average hashrate: {$avg_hr} H/s - {$avg_gpuhr} H/s
    From b3b7d7a5a95d415333f72a297f73b74bed44b02d Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Thu, 7 Feb 2019 16:36:49 +0100 Subject: [PATCH 074/134] Only active miners are counted for average/pool-total --- README.md | 2 ++ index.php | 6 ++++-- template/index.html | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 173f9d3..3a4536f 100644 --- a/README.md +++ b/README.md @@ -14,11 +14,13 @@ Warning: because of additions to the config file, do not simply replace the php- - TODO: implement the possible external argon2 validation through config file - TODO: restructure api.php - TODO: either update miner hr more often or insert sum workerHR into dashboard/individual pages/api +- TODO: workaround for misreporting Dan's miner ## Medium changes: - The 'last-update' values of workers has been reduced from 1hr to 720s to keep the calculation of total hashrate more precise, this means workers not having reported in during the last 12 minutes are not added to the miner total hr and pool hr - The 'time-out' value of miners has been enlarged to have miners remain in history when they are away for a while (max 24h). For individual workers it's set to 30minutes. A miner will be deleted from history if the historical share rate drops below 50 AND he has not submitted a nonce in the last 24h - The 'cut-off' of last remaining historical shares has been changed to prevent ghost miners remaining in the list indefinely (hist.shares would never reach zero) +- Only 'active miners' are counted in total miners and average hr - TODO: The last payments / last blocks 'truncation' has been moved to config in order to be able to adapt it to the size of the pool: small pool wants to keep history longer ## Minor changes: diff --git a/index.php b/index.php index 1e54290..c46fc29 100755 --- a/index.php +++ b/index.php @@ -25,8 +25,10 @@ $total_shares = 0; $shares = []; - $r = $db->run("SELECT * FROM miners "); - $miners = count($r); + $p = $db->run("SELECT * FROM miners WHERE hashrate>0 OR gpuhr>0"); + $miners = count($p); + + $r = $db->run("SELECT * FROM miners"); $total_historic = 0; $historic = []; diff --git a/template/index.html b/template/index.html index b9f1162..867baea 100755 --- a/template/index.html +++ b/template/index.html @@ -31,7 +31,7 @@
    Current Block

    {$miners}

    -
    Miners
    +
    Active Miners
    From d37d9e87ec3c90732705e4f8f857438f85ded34b Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Thu, 7 Feb 2019 23:45:32 +0100 Subject: [PATCH 075/134] moved parameters to config, payment.php cleanup --- README.md | 29 ++++++++++++++++------------- config-sample.php | 8 ++++++++ index.php | 1 + payments.php | 35 ++++++++--------------------------- template/info.html | 2 +- update.php | 2 +- 6 files changed, 35 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index 3a4536f..50d6cf2 100644 --- a/README.md +++ b/README.md @@ -16,31 +16,34 @@ Warning: because of additions to the config file, do not simply replace the php- - TODO: either update miner hr more often or insert sum workerHR into dashboard/individual pages/api - TODO: workaround for misreporting Dan's miner -## Medium changes: +## Smaller changes: - The 'last-update' values of workers has been reduced from 1hr to 720s to keep the calculation of total hashrate more precise, this means workers not having reported in during the last 12 minutes are not added to the miner total hr and pool hr - The 'time-out' value of miners has been enlarged to have miners remain in history when they are away for a while (max 24h). For individual workers it's set to 30minutes. A miner will be deleted from history if the historical share rate drops below 50 AND he has not submitted a nonce in the last 24h - The 'cut-off' of last remaining historical shares has been changed to prevent ghost miners remaining in the list indefinely (hist.shares would never reach zero) -- Only 'active miners' are counted in total miners and average hr -- TODO: The last payments / last blocks 'truncation' has been moved to config in order to be able to adapt it to the size of the pool: small pool wants to keep history longer +- Only 'active miners' are counted to calculate total HR: those with miner HR > 0 +- Besides average CPU Blocks HR we now also calculate average GPU blocks HR. Both only based on active miners. +- How long last payments are shown on payments page is moved to config +- How far back is searched for small pending payments is moved to config +- If no payment message is set in config it takes the pool hostname from config +- Degradation, last-payments-variable, poolname etc. have been moved to config +- Bugfix to make poolsanity being able to be started as service +- TODO last blocks 'truncation' has been moved to config in order to be able to adapt it to the size of the pool: small pool wants to keep history longer -## Minor changes: +## Display changes: - Small update to dashboard layout based on reoccuring questions in discord - To remove the constant confusion we are going to be consequent and call it GPU-*blocks* HR and NOT "GPU HR" (and CPU-*blocks* HR instead of "CPU HR") everywhere on the site. -- Added Average GPU Blocks HR next to CPU Blocks HR -- Removal of long TX addresses in payout page, replaced with links to block explorer -- Blocks in Blocks Won are veryfiable on Block Explorer, for transparency -- Bugfix to make poolsanity being able to be started as service - Bugfix in template/index.html of html code the purple box showing hashrates. Also: C-HR is shown left, G-HR right, just as in all tables. -- Degradation, last-payments-variable, poolname etc. have been moved to config -- Info page: old mining info removed, pool details (rewards/degradation/payout/DL) are read from the config file -- Templates: pool name set in config +- Template/Header page: pool name set in config +- On dashboard: average h/s shown on page +- On payments page: Removal of long TX addresses in payout page, replaced with links to block explorer +- On blocks won page: Blocks are veryfiable through link to Block Explorer, for transparency - On individual miner page: best DL is 1000000 replaced with No Nonce submitted yet - On individual miner page: added time of last submitted nonce - On individual miner page: when last payment is still in mempool it's shown as Payment In Process - On individual miner page: when no payment ever last payment date is shown as No Payment Yet -- TODO: Info page: discord handle can be set in config -- TODO: If no payment message is set in config it takes the pool hostname from config +- On info page: old mining info removed, pool details (rewards/degradation/payout/DL) are read from the config file +- On info page: discord handle can be set in config With the current setup payments are split from updates. diff --git a/config-sample.php b/config-sample.php index 2dab9a0..456cf4c 100644 --- a/config-sample.php +++ b/config-sample.php @@ -89,6 +89,14 @@ $pool_config['pool_url'] = 'http://pooladdress.here'; $pool_config['pool_name'] = 'Your Poolname here'; +$pool_config['handle'] = 'your Discord name here'; // percentage of historical share degradation per block. 0.05 is best for pool with big miners, 0.02 for pool with small miners $pool_config['pool_degradation'] = 0.05; + +// how many blocks to look back for pending payments. large pool: set at 500, small pool >2000 +$pool_config['blocks_paid'] = 3000; + +// how long are old payments shown on the website. Delete after x blocks, default 2000. Small pool set much higher +$pool_config['payout_history'] = 2000; + diff --git a/index.php b/index.php index c46fc29..5e20007 100755 --- a/index.php +++ b/index.php @@ -209,6 +209,7 @@ $tpl->assign("server", gethostname()); $tpl->assign("pool_url", $pool_config['pool_url']); $tpl->assign("pool_degradation", number_format($pool_config['pool_degradation']*100,1)); + $tpl->assign("handle", $pool_config['handle']); diff --git a/payments.php b/payments.php index 520b655..515e445 100644 --- a/payments.php +++ b/payments.php @@ -22,6 +22,7 @@ function shut_down() global $pid112; system("rm -rf $pid112"); echo "\n# ShutDown #\n"; + } register_shutdown_function('shut_down'); @@ -62,33 +63,13 @@ function pay_post($url, $data = []) } -$hour = date('H'); -$min = date('i'); - -$blocks_paid = 500; -if ($hour === 10 && $min < 20) { - $blocks_paid = 5000; -} - echo "\n----------------------------------------------------------------------------------\n"; $current = $aro->single('SELECT height FROM blocks ORDER by height DESC LIMIT 1'); echo "Current block $current\n"; -// als de payment gerund wordt zet hij de totale pending die op de dashboard staat, dit kan naar update -$db->run( - 'UPDATE miners - SET pending = ( - SELECT SUM(val) - FROM payments - WHERE done = 0 AND payments.address = miners.id AND height >= :h - )', - [':h' => $current - $blocks_paid] -); - -// r wordt dus opgebouwd uit 500 oude blocks tot t-minus 10 die niet zijn uitbetaald $r = $db->run( 'SELECT DISTINCT block FROM payments WHERE height<:h AND done=0 AND height>=:h2', - [':h' => $current - 10, ':h2' => $current - $blocks_paid] + [':h' => $current - 10, ':h2' => $current - $pool_config['blocks_paid']] ); if (count($r) === 0) { die("No payments pending\n"); @@ -107,7 +88,6 @@ function pay_post($url, $data = []) } } -// vanaf hier begint het echte payment gedeelte $total_paid = 0; $r = $db->run( 'SELECT SUM(val) as v, address FROM payments WHERE height<:h AND height>=:h2 AND done=0 GROUP by address', @@ -128,15 +108,17 @@ function pay_post($url, $data = []) #$val=intval($val); $public_key = $pool_config['public_key']; $private_key = $pool_config['private_key']; - + $message = $pool_config['payout_message']; + if ($message == null) { + $message = $pool_config['pool_name']; + } $res = pay_post('/api.php?q=send', [ 'dst' => $x['address'], 'val' => $val, 'private_key' => $private_key, 'public_key' => $public_key, 'version' => 1, -// hier kunnen we eventueel toevoegen dat als geen payout message dat ie dan domeinnaam pakt - 'message' => $pool_config['payout_message'], + 'message' => $message, ]); echo "$val\n"; echo "$x[address]\n"; @@ -168,6 +150,5 @@ function pay_post($url, $data = []) $not = $db->single('SELECT SUM(val) FROM payments WHERE done=0'); echo "Pending balance: $not\n"; -// dit is aan te passen voor als je dat juist niet wilt. uitbetaald en 1000 blocks geleden betekent delete -$db->run('DELETE FROM payments WHERE done=1 AND height<:h', [':h' => $current - 1000]); +$db->run('DELETE FROM payments WHERE done=1 AND height<:h', [':h' => $current - $pool_config['payout_history']]); diff --git a/template/info.html b/template/info.html index e7f996c..a078724 100755 --- a/template/info.html +++ b/template/info.html @@ -20,7 +20,7 @@

    Pool balance: Block Exp

    This is an independent pool, which means you will only receive a payment when the pool finds a block.


    This service is provided as is.
    - For information and support: hendrik@
    ARO discord.

    + For information and support: {$handle}@ARO discord.


    Server: {$server} diff --git a/update.php b/update.php index 1d7c02b..a57622c 100644 --- a/update.php +++ b/update.php @@ -88,7 +88,7 @@ function shut_down() FROM payments WHERE done = 0 AND payments.address = miners.id AND height >= :h )', - [':h' => $current - $blocks_paid] + [':h' => $current - $pool_config['blocks_paid']] ); From eb6d8b03327954b8cc99ee516e19ca17b38a375f Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Fri, 8 Feb 2019 00:32:34 +0100 Subject: [PATCH 076/134] fixed manualpayment to send ALL --- manualpayment-sendall.php | 72 +++++++++++---------------------------- payments.php | 12 +++++-- update.php | 4 +++ 3 files changed, 33 insertions(+), 55 deletions(-) diff --git a/manualpayment-sendall.php b/manualpayment-sendall.php index 54549c1..ba97b1e 100644 --- a/manualpayment-sendall.php +++ b/manualpayment-sendall.php @@ -22,6 +22,7 @@ function shut_down() global $pid112; system("rm -rf $pid112"); echo "\n# ShutDown #\n"; + } register_shutdown_function('shut_down'); @@ -34,6 +35,11 @@ function shut_down() require_once __DIR__.'/db.php'; +if ($pool_config['payout_history'] == null) { + die('Payout History variable not set in config'); +} + + function pay_post($url, $data = []) { global $pool_config; @@ -61,69 +67,36 @@ function pay_post($url, $data = []) return json_decode($result, true); } -$pool_config['min_payout'] = 0; - - -$hour = date('H'); -$min = date('i'); - -$blocks_paid = 50000; - echo "\n----------------------------------------------------------------------------------\n"; $current = $aro->single('SELECT height FROM blocks ORDER by height DESC LIMIT 1'); echo "Current block $current\n"; - -$db->run('DELETE FROM miners WHERE historic+shares<=20'); -$db->run('UPDATE miners - SET gpuhr = ( - SELECT SUM(gpuhr) - FROM workers - WHERE miner = miners.id AND updated > UNIX_TIMESTAMP() - 3600 - )'); -$db->run('UPDATE miners - SET hashrate = ( - SELECT SUM(hashrate) - FROM workers - WHERE miner = miners.id AND updated > UNIX_TIMESTAMP() - 3600)'); -$db->run( - 'UPDATE miners - SET pending = ( - SELECT SUM(val) - FROM payments - WHERE done = 0 AND payments.address = miners.id AND height >= :h)', - [':h' => $current - $blocks_paid] -); - - $r = $db->run( - 'SELECT DISTINCT block FROM payments WHERE height<:h AND done=0 AND height>=:h2', - [':h' => $current - 10, ':h2' => $current - $blocks_paid] + 'SELECT DISTINCT block FROM payments WHERE height<:h AND done=0', + [':h' => $current - 10] ); if (count($r) === 0) { die("No payments pending\n"); } -$db->run('DELETE FROM miners WHERE shares=0 AND historic=0 AND updatedrun('DELETE FROM workers WHERE updatedsingle('SELECT COUNT(1) FROM blocks WHERE id=:id', [':id' => $x['block']]); if ($s === 0) { +// dit kunnen we dus aanpassen naar orphaned. block wordt niet nog een keer meegenomen want verdwijnt uit payments $db->run('DELETE FROM blocks WHERE id=:id', [':id' => $x['block']]); +// nu halen we de payments weg en wordt het block niet opnieuw geselecteerd bij de volgende payment cycle $db->run('DELETE FROM payments WHERE block=:id', [':id' => $x['block']]); echo "Deleted block: $x[block]\n"; } } - $total_paid = 0; $r = $db->run( - 'SELECT SUM(val) as v, address FROM payments WHERE height<:h AND height>=:h2 AND done=0 GROUP by address', - [':h' => $current - 10, ':h2' => $current - $blocks_paid] + 'SELECT SUM(val) as v, address FROM payments WHERE height<:h AND done=0 GROUP by address', + [':h' => $current - 10] ); foreach ($r as $x) { if ($x['v'] < $pool_config['min_payout']) { @@ -140,14 +113,17 @@ function pay_post($url, $data = []) #$val=intval($val); $public_key = $pool_config['public_key']; $private_key = $pool_config['private_key']; - + $message = $pool_config['payout_message']; + if ($message == null) { + $message = $pool_config['pool_name']; + } $res = pay_post('/api.php?q=send', [ 'dst' => $x['address'], 'val' => $val, 'private_key' => $private_key, 'public_key' => $public_key, 'version' => 1, - 'message' => $pool_config['payout_message'], + 'message' => $message, ]); echo "$val\n"; echo "$x[address]\n"; @@ -158,10 +134,9 @@ function pay_post($url, $data = []) echo "Transaction sent - $x[address] - $val! Transaction id: $res[data]\n"; $db->run( - 'UPDATE payments SET txn=:txn, done=1 WHERE address=:address AND height<:h AND done=0 AND height>=:h2', + 'UPDATE payments SET txn=:txn, done=1 WHERE address=:address AND height<:h AND done=0', [ ':h' => $current - 10, - ':h2' => $current - $blocks_paid, ':txn' => $res['data'], ':address' => $x['address'], ] @@ -179,14 +154,5 @@ function pay_post($url, $data = []) $not = $db->single('SELECT SUM(val) FROM payments WHERE done=0'); echo "Pending balance: $not\n"; +$db->run('DELETE FROM payments WHERE done=1 AND height<:h', [':h' => $current - $pool_config['payout_history']]); -$db->run( - 'UPDATE miners - SET pending = ( - SELECT SUM(val) - FROM payments - WHERE done = 0 AND payments.address = miners.id AND height >= :h)', - [':h' => $current - $blocks_paid] -); - -$db->run('DELETE FROM payments WHERE done=1 AND height<:h', [':h' => $current - 1000]); diff --git a/payments.php b/payments.php index 515e445..57c3edc 100644 --- a/payments.php +++ b/payments.php @@ -35,6 +35,14 @@ function shut_down() require_once __DIR__.'/db.php'; +if ($pool_config['payout_history'] == null) { + die('Payout History variable not set in config'); +} +if ($pool_config['blocks_paid'] == null) { + die('Blocks Paid variable not set in config'); +} + + function pay_post($url, $data = []) { global $pool_config; @@ -91,7 +99,7 @@ function pay_post($url, $data = []) $total_paid = 0; $r = $db->run( 'SELECT SUM(val) as v, address FROM payments WHERE height<:h AND height>=:h2 AND done=0 GROUP by address', - [':h' => $current - 10, ':h2' => $current - $blocks_paid] + [':h' => $current - 10, ':h2' => $current - $pool_config['blocks_paid']] ); foreach ($r as $x) { if ($x['v'] < $pool_config['min_payout']) { @@ -132,7 +140,7 @@ function pay_post($url, $data = []) 'UPDATE payments SET txn=:txn, done=1 WHERE address=:address AND height<:h AND done=0 AND height>=:h2', [ ':h' => $current - 10, - ':h2' => $current - $blocks_paid, + ':h2' => $current - $pool_config['blocks_paid'], ':txn' => $res['data'], ':address' => $x['address'], ] diff --git a/update.php b/update.php index a57622c..afb9f6f 100644 --- a/update.php +++ b/update.php @@ -34,6 +34,10 @@ function shut_down() require_once __DIR__.'/db.php'; +if ($pool_config['blocks_paid'] == null) { + die('Blocks Paid variable not set in config'); +} + echo "\n----------------------------------------------------------------------------------\n"; $current = $aro->single('SELECT height FROM blocks ORDER by height DESC LIMIT 1'); echo "Current block $current\n"; From fda2e0d88c920e650ad90a2bae9bc88ab974b3ab Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Sat, 9 Feb 2019 22:57:05 +0100 Subject: [PATCH 077/134] api restructuring --- README.md | 6 +-- api.php | 105 ++++++++++++++++++++++++++++++++++++++++------ config-sample.php | 7 ++-- 3 files changed, 100 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 50d6cf2..3d813be 100644 --- a/README.md +++ b/README.md @@ -7,12 +7,11 @@ Warning: because of additions to the config file, do not simply replace the php- ## Bigger changes: - Hashreporting has been removed from payments/poolsanity to a seperate updater. Updating hashrates on the website can be done independently of payment-cycle, and db is no longer only updated when moving to next block. Be aware that the 10minute update interval from the clients is fixed. As is the 'first appearance' in the db after submitting first nonce -- Api.php has been expanded with more options -- Last payment, payment date, payments in 24h included on individual miner page and api +- Api.php has been expanded and restructured with more options +- Last payment, payment date, payments in 24h, time of last submitted nonce included on individual miner page and api - TODO: Orphaned blocks are no longer removed from the list but marked as orphaned. Pending payments are removed. - TODO: Workerid is changed to workername+address to create a unique key without having to alter the database. It prevents changes to client (new address/new workername) not being updated in the workerlist and it also prevents 2 miners using the same workername to be misreported as one. It will NOT change the fact that miners using one single name for many workers causing their hashrate being reported as once worker. This would require a uniqueID being send from the worker - TODO: implement the possible external argon2 validation through config file -- TODO: restructure api.php - TODO: either update miner hr more often or insert sum workerHR into dashboard/individual pages/api - TODO: workaround for misreporting Dan's miner @@ -27,6 +26,7 @@ Warning: because of additions to the config file, do not simply replace the php- - If no payment message is set in config it takes the pool hostname from config - Degradation, last-payments-variable, poolname etc. have been moved to config - Bugfix to make poolsanity being able to be started as service +- Bugfix in hashrate extension determination - TODO last blocks 'truncation' has been moved to config in order to be able to adapt it to the size of the pool: small pool wants to keep history longer ## Display changes: diff --git a/api.php b/api.php index 2caf906..ed2a9ce 100644 --- a/api.php +++ b/api.php @@ -5,6 +5,7 @@ /api?q=status returns current status of the pool /api?q=miner&m= returns total hashrate and shares of miner /api?q=payments&m= returns payments of miner +/api?m= returns total hashrate and shares and payments of miner /api.php without flags also returns pool status at the moment for compatibility reasons */ @@ -28,8 +29,25 @@ $hashrate=$db->single("SELECT hashrate FROM miners WHERE id='$m'"); $gpu_hr=$db->single("SELECT gpuhr FROM miners WHERE id='$m'"); $historic=$db->single("SELECT historic FROM miners WHERE id='$m'"); - $shares=$db->single("SELECT shares FROM miners WHERE id='$m'"); - echo json_encode(array("miner"=>$miner, "cpu_hr"=>$hashrate, "gpu_hr"=>$gpu_hr, "historic shares"=>$historic, "current shares"=>$shares)); + $shares=$db->single("SELECT (shares FROM miners WHERE id='$m'"); + $update=$db->single("SELECT updated FROM MINERS where id='$m'"); + if ($update == false) { + $update = "No nonce submitted"; + } + if ($shares == false) { + $shares = "0"; + } + if ($historic == false) { + $historic = "0"; + } + if ($hashrate == false) { + $hashrate = "0"; + } + if ($gpu_hr == false) { + $gpu_hr = "0"; + } + + echo json_encode(array("miner"=>$miner, "cpu_hr"=>$hashrate, "gpu_hr"=>$gpu_hr, "historic shares"=>$historic, "current shares"=>$shares, "last nonce submite"=>$update)); } } @@ -39,10 +57,22 @@ $total_hr=$db->single("SELECT val FROM info WHERE id='total_hash_rate'"); $total_gpu=$db->single("SELECT val FROM info WHERE id='total_gpu_hr'"); $current=$aro->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); - $miners=$db->single("SELECT COUNT(1) FROM miners"); + $miners=$db->single("SELECT COUNT(1) FROM miners WHERE hashrate>0 OR gpuhr>0"); $last_won=$db->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); $last_won_time=$aro->single("SELECT date FROM blocks WHERE height=:h",[":h"=>$last_won]); - echo json_encode(array("cpu_hr"=>$total_hr, "gpu_hr"=>$total_gpu, "current_block_height"=>$current, "last_won_block"=>$last_won, "last_won_block_time"=>$last_won_time, "miners"=>$miners, "fee"=>$pool_config['fee'])); + if ($last_won_time == false) { + $last_won_time = "Never"; + } + $avg_gpuhr = number_format($total_gpu / $miners, 0); + $avg_hr = number_format(($total_hr / $miners), 0); + if ($miners == 0) { + $avg_gpuhr = 0; + $avg_hr = 0; + } + + + + echo json_encode(array("cpu_hr"=>$total_hr, "gpu_hr"=>$total_gpu, "current_block_height"=>$current, "last_won_block"=>$last_won, "last_won_block_time"=>$last_won_time, "active miners"=>$miners, "avg_hr"=>$avg_hr, "avg_gpuhr"=>$avg_gpuhr, "fee"=>$pool_config['fee'])); } @@ -74,13 +104,64 @@ } } + else { - // we keep this here as this is the old aropool.com api, for compatibility - $total_hr=$db->single("SELECT val FROM info WHERE id='total_hash_rate'"); - $total_gpu=$db->single("SELECT val FROM info WHERE id='total_gpu_hr'"); - $current=$aro->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); - $miners=$db->single("SELECT COUNT(1) FROM miners"); - $last_won=$db->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); - $last_won_time=$aro->single("SELECT date FROM blocks WHERE height=:h",[":h"=>$last_won]); - echo json_encode(array("cpu_hr"=>$total_hr, "gpu_hr"=>$total_gpu, "current_block_height"=>$current, "last_won_block"=>$last_won, "last_won_block_time"=>$last_won_time, "miners"=>$miners, "fee"=>$pool_config['fee'])); + + $m = $_GET['m']; + + if ($m == null) { + + // we keep this here as this is the old aropool.com api, for compatibility + $total_hr=$db->single("SELECT val FROM info WHERE id='total_hash_rate'"); + $total_gpu=$db->single("SELECT val FROM info WHERE id='total_gpu_hr'"); + $current=$aro->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); + $miners=$db->single("SELECT COUNT(1) FROM miners"); + $last_won=$db->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); + $last_won_time=$aro->single("SELECT date FROM blocks WHERE height=:h",[":h"=>$last_won]); + echo json_encode(array("cpu_hr"=>$total_hr, "gpu_hr"=>$total_gpu, "current_block_height"=>$current, "last_won_block"=>$last_won, "last_won_block_time"=>$last_won_time, "miners"=>$miners, "fee"=>$pool_config['fee'])); } + + $miner=$m; + $hashrate=$db->single("SELECT hashrate FROM miners WHERE id='$m'"); + $gpu_hr=$db->single("SELECT gpuhr FROM miners WHERE id='$m'"); + $historic=$db->single("SELECT historic FROM miners WHERE id='$m'"); + $shares=$db->single("SELECT shares FROM miners WHERE id='$m'"); + $update=$db->single("SELECT updated FROM MINERS where id='$m'"); + if ($update == false) { + $update = "No nonce submitted"; + } + if ($shares == false) { + $shares = "0"; + } + if ($historic == false) { + $historic = "0"; + } + if ($hashrate == false) { + $hashrate = "0"; + } + if ($gpu_hr == false) { + $gpu_hr = "0"; + } + + $yesterday=time()-86400; + $yesterday_block=$aro->single("SELECT height+1 FROM blocks WHERE date<=$yesterday ORDER by height DESC LIMIT 1"); + $last_payment_txn=$db->single("SELECT txn FROM payments WHERE address='$m' AND done=1 ORDER by height DESC LIMIT 1"); + $last_payment_time=$aro->single("SELECT date FROM transactions WHERE id=$last_payment_txn"); + $total_paid=$db->single("SELECT total_paid FROM miners WHERE id='$m'"); + $pending=$db->single("SELECT pending FROM miners WHERE id='$m'"); + $last_payment=$db->single("SELECT SUM(val) FROM payments WHERE txn=:lasttxn AND done=1",[":lasttxn"=>$last_payment_txn]); + if ($last_payment_time == false) { + $last_payment_time = "Payment in process"; + } + if ($last_payment == 0 ) { + $last_payment_time = "No payment yet"; + } + $past_24h=$db->single("SELECT SUM(val) FROM payments WHERE address='$m' AND height>=$yesterday_block AND done=1"); + + echo json_encode(array("miner"=>$miner, "cpu_hr"=>$hashrate, "gpu_hr"=>$gpu_hr, "historic shares"=>$historic, "current shares"=>$shares, "last nonce submite"=>$update, "total paid"=>$total_paid, "pending"=>$pending, "past_24h"=>$past_24h, "last_payment"=>$last_payment, "last_payment_date"=>$last_payment_time)); + + + + +} + diff --git a/config-sample.php b/config-sample.php index 456cf4c..a159f8e 100644 --- a/config-sample.php +++ b/config-sample.php @@ -95,8 +95,9 @@ $pool_config['pool_degradation'] = 0.05; // how many blocks to look back for pending payments. large pool: set at 500, small pool >2000 -$pool_config['blocks_paid'] = 3000; +// do not forget to occasionally run a manual payment to clear old payments +$pool_config['blocks_paid'] = 5000; -// how long are old payments shown on the website. Delete after x blocks, default 2000. Small pool set much higher -$pool_config['payout_history'] = 2000; +// how long are old payments shown on the website. Delete after x blocks, default 1000. Small pool set much higher +$pool_config['payout_history'] = 1000; From 3cf63c4be195b401d783f0986dc4bfc14e2809ba Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Sat, 9 Feb 2019 22:59:26 +0100 Subject: [PATCH 078/134] typo --- api.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api.php b/api.php index ed2a9ce..579e6ff 100644 --- a/api.php +++ b/api.php @@ -47,7 +47,7 @@ $gpu_hr = "0"; } - echo json_encode(array("miner"=>$miner, "cpu_hr"=>$hashrate, "gpu_hr"=>$gpu_hr, "historic shares"=>$historic, "current shares"=>$shares, "last nonce submite"=>$update)); + echo json_encode(array("miner"=>$miner, "cpu_hr"=>$hashrate, "gpu_hr"=>$gpu_hr, "historic shares"=>$historic, "current shares"=>$shares, "last nonce submitted"=>$update)); } } From 3db43e9ea5e02ddda74195277721534e6a80578b Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Sun, 10 Feb 2019 17:37:17 +0100 Subject: [PATCH 079/134] bugfix stale blocks --- README.md | 2 +- mine.php | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3d813be..86221ef 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ Warning: because of additions to the config file, do not simply replace the php- - Hashreporting has been removed from payments/poolsanity to a seperate updater. Updating hashrates on the website can be done independently of payment-cycle, and db is no longer only updated when moving to next block. Be aware that the 10minute update interval from the clients is fixed. As is the 'first appearance' in the db after submitting first nonce - Api.php has been expanded and restructured with more options - Last payment, payment date, payments in 24h, time of last submitted nonce included on individual miner page and api +- Bugfix: False reporting of stale blocks submitted through Dan's/Cryptogone's miner. - TODO: Orphaned blocks are no longer removed from the list but marked as orphaned. Pending payments are removed. - TODO: Workerid is changed to workername+address to create a unique key without having to alter the database. It prevents changes to client (new address/new workername) not being updated in the workerlist and it also prevents 2 miners using the same workername to be misreported as one. It will NOT change the fact that miners using one single name for many workers causing their hashrate being reported as once worker. This would require a uniqueID being send from the worker - TODO: implement the possible external argon2 validation through config file @@ -27,7 +28,6 @@ Warning: because of additions to the config file, do not simply replace the php- - Degradation, last-payments-variable, poolname etc. have been moved to config - Bugfix to make poolsanity being able to be started as service - Bugfix in hashrate extension determination -- TODO last blocks 'truncation' has been moved to config in order to be able to adapt it to the size of the pool: small pool wants to keep history longer ## Display changes: diff --git a/mine.php b/mine.php index 877b553..2a5d371 100644 --- a/mine.php +++ b/mine.php @@ -83,8 +83,7 @@ function curl_post($url, $post) $f = file_get_contents($pool_config['node_url'].'/mine.php?q=info'); $g = json_decode($f, true); - - if ($_POST['height'] > 1 && $g['data']['height'] !== $_POST['height']) { +if ((int)$_POST['height'] > 1 && $g['data']['height'] !== (int)$_POST['height']) { api_err('stale block'); } From 2c6732d230953eae5c53522a0950a4477cb3798a Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Sun, 10 Feb 2019 21:05:39 +0100 Subject: [PATCH 080/134] possible fix Dan's hr reporting --- mine.php | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/mine.php b/mine.php index 2a5d371..238c8b8 100644 --- a/mine.php +++ b/mine.php @@ -37,7 +37,7 @@ function curl_post($url, $post) $worker = $_GET['worker']; $hr = (int)$_GET['hashrate']; - $gpuhr = (int)($_GET['gpuhr'] + $_GET['hrgpu']); + $gpuhr = (int)($_GET['gpuhr'] + (int)$_GET['hrgpu']); $bind = [ ':id' => $worker, ':hr' => $hr, @@ -48,12 +48,37 @@ function curl_post($url, $post) ':gpuhr' => $gpuhr, ':gpuhr2' => $gpuhr, ]; + +// fix Dan's misreporting + if ($gpuhr == 0){ + $f = file_get_contents($pool_config['node_url'].'/mine.php?q=info'); + $g = json_decode($f, true); + if ($g['data']['height'] % 2 == 1) { + $db->run( + 'INSERT INTO workers + SET id = :id, updated = UNIX_TIMESTAMP(), miner = :miner, ip = :ip, gpuhr = :hr + ON DUPLICATE KEY UPDATE updated = UNIX_TIMESTAMP(), ip = :ip2, gpuhr = :hr2', + $bind + ); + } + if ($g['data']['height'] % 2 == 0) { + $db->run( + 'INSERT INTO workers + SET id = :id, hashrate = :hr, updated = UNIX_TIMESTAMP(), miner = :miner, ip = :ip + ON DUPLICATE KEY UPDATE updated = UNIX_TIMESTAMP(), ip = :ip2, hashrate = :hr2', + $bind + ); + } + } + if ($gpuhr !== 0){ + $db->run( 'INSERT INTO workers SET id = :id, hashrate = :hr, updated = UNIX_TIMESTAMP(), miner = :miner, ip = :ip, gpuhr = :gpuhr ON DUPLICATE KEY UPDATE updated = UNIX_TIMESTAMP(), hashrate = :hr2, ip = :ip2, gpuhr = :gpuhr2', $bind ); + } } From 838abe4dd03dfb2be642ce342b74b422e52b73a7 Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Sun, 10 Feb 2019 23:11:58 +0100 Subject: [PATCH 081/134] updated todo list --- README.md | 60 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 86221ef..16e7c75 100644 --- a/README.md +++ b/README.md @@ -6,44 +6,46 @@ System requirements are indentical to the official pool code. Warning: because of additions to the config file, do not simply replace the php-files without making sure all variables are added to the config. ## Bigger changes: -- Hashreporting has been removed from payments/poolsanity to a seperate updater. Updating hashrates on the website can be done independently of payment-cycle, and db is no longer only updated when moving to next block. Be aware that the 10minute update interval from the clients is fixed. As is the 'first appearance' in the db after submitting first nonce -- Api.php has been expanded and restructured with more options -- Last payment, payment date, payments in 24h, time of last submitted nonce included on individual miner page and api -- Bugfix: False reporting of stale blocks submitted through Dan's/Cryptogone's miner. +- Change: Hashreporting has been removed from payments/poolsanity to a seperate updater. Updating hashrates on the website can be done independently of payment-cycle, and db is no longer only updated when moving to next block. Be aware that the 10minute update interval from the clients is fixed. As is the 'first appearance' in the db after submitting first nonce +- Added: Api.php has been expanded and restructured with more options +- Added: Last payment, payment date, payments in 24h, time of last submitted nonce included on individual miner page and api +- Bugfix: False rejects stale blocks submitted through Dan's Javaminer after PHP upgrade. +- Bugfix: Workaround for misreporting Dan's Java miner/Android miner - TODO: Orphaned blocks are no longer removed from the list but marked as orphaned. Pending payments are removed. - TODO: Workerid is changed to workername+address to create a unique key without having to alter the database. It prevents changes to client (new address/new workername) not being updated in the workerlist and it also prevents 2 miners using the same workername to be misreported as one. It will NOT change the fact that miners using one single name for many workers causing their hashrate being reported as once worker. This would require a uniqueID being send from the worker - TODO: implement the possible external argon2 validation through config file - TODO: either update miner hr more often or insert sum workerHR into dashboard/individual pages/api -- TODO: workaround for misreporting Dan's miner ## Smaller changes: -- The 'last-update' values of workers has been reduced from 1hr to 720s to keep the calculation of total hashrate more precise, this means workers not having reported in during the last 12 minutes are not added to the miner total hr and pool hr -- The 'time-out' value of miners has been enlarged to have miners remain in history when they are away for a while (max 24h). For individual workers it's set to 30minutes. A miner will be deleted from history if the historical share rate drops below 50 AND he has not submitted a nonce in the last 24h -- The 'cut-off' of last remaining historical shares has been changed to prevent ghost miners remaining in the list indefinely (hist.shares would never reach zero) -- Only 'active miners' are counted to calculate total HR: those with miner HR > 0 -- Besides average CPU Blocks HR we now also calculate average GPU blocks HR. Both only based on active miners. -- How long last payments are shown on payments page is moved to config -- How far back is searched for small pending payments is moved to config -- If no payment message is set in config it takes the pool hostname from config -- Degradation, last-payments-variable, poolname etc. have been moved to config -- Bugfix to make poolsanity being able to be started as service -- Bugfix in hashrate extension determination +- Change: The 'last-update' values of workers has been reduced from 1hr to 720s to keep the calculation of total hashrate more precise, this means workers not having reported in during the last 12 minutes are not added to the miner total hr and pool hr. +- Change: The 'time-out' value of miners has been enlarged to have miners remain in history when they are away for a while (max 24h). For individual workers it's set to 30minutes. A miner will be deleted from history if the historical share rate drops below 50 AND he has not submitted a nonce in the last 24h +- Change: Discard of last remaining historical shares has been added to prevent ghost miners remaining in the list indefinely (hist.shares would never reach zero) +- Change: Only 'active miners' are counted to calculate total HR: those with miner HR > 0 +- Added/Change: Nexte average CPU Blocks HR we now also calculate average GPU blocks HR. Both are now only based on active miners. +- Change: How far back last payments are displayed on payments page is moved to config +- Change: During payment cycle, how far back is searched for small pending payments is moved to config. +- Change: Manual payment request of all outstanding payments now looks through entire pool history. +- Change: If no payment message is set in config it takes the pool hostname from config +- Change: Degradation, poolname etc. have been moved to config +- Bugfix: to make poolsanity being able to be started as service through systemd +- Bugfix: fixed erros in hashrate extension determination +- TODO: Bugfix of Ario's total hr calc in indiv.miner page. ## Display changes: -- Small update to dashboard layout based on reoccuring questions in discord -- To remove the constant confusion we are going to be consequent and call it GPU-*blocks* HR and NOT "GPU HR" (and CPU-*blocks* HR instead of "CPU HR") everywhere on the site. -- Bugfix in template/index.html of html code the purple box showing hashrates. Also: C-HR is shown left, G-HR right, just as in all tables. -- Template/Header page: pool name set in config -- On dashboard: average h/s shown on page -- On payments page: Removal of long TX addresses in payout page, replaced with links to block explorer -- On blocks won page: Blocks are veryfiable through link to Block Explorer, for transparency -- On individual miner page: best DL is 1000000 replaced with No Nonce submitted yet -- On individual miner page: added time of last submitted nonce -- On individual miner page: when last payment is still in mempool it's shown as Payment In Process -- On individual miner page: when no payment ever last payment date is shown as No Payment Yet -- On info page: old mining info removed, pool details (rewards/degradation/payout/DL) are read from the config file -- On info page: discord handle can be set in config +- Change: Small updates to dashboard layout based on reoccuring questions in discord +- Change: On payments page: Removal of long TX addresses in payout page, replaced with links to block explorer +- Change: To remove the constant confusion we are going to be consequent and call it GPU-*blocks* HR and NOT "GPU HR" (and CPU-*blocks* HR instead of "CPU HR") everywhere on the site. +- Bugfix: template/index.html responsive html code of the purple box showing hashrates caused errors on android. Fixed. Also: C-HR is now displayed left, G-HR right, just as in all other tables. +- Change: Template/Header page: pool name set in config +- Added: On dashboard: average h/s displayed on page +- Added: On blocks won page - Blocks are veryfiable through link to Block Explorer, for transparency +- Change: On individual miner page - best DL is 1000000 replaced with No Nonce submitted yet +- Change: On individual miner page - added time of last submitted nonce +- Bugfix: On individual miner page - when last payment is still in mempool it's shown as Payment In Process +- Bugfix: On individual miner page - when no payment ever last payment date is shown as No Payment Yet +- Change: On info page - old mining info removed, pool details (rewards/degradation/payout/DL) are read from the config file +- Change: On info page - discord handle can be set in config With the current setup payments are split from updates. From f471f6b1a1e7afc1f8e1cad971f097675863eaa9 Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Mon, 11 Feb 2019 21:00:20 +0100 Subject: [PATCH 082/134] api bugfix --- README.md | 5 +++-- api.php | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 16e7c75..9a20d12 100644 --- a/README.md +++ b/README.md @@ -18,10 +18,11 @@ Warning: because of additions to the config file, do not simply replace the php- ## Smaller changes: - Change: The 'last-update' values of workers has been reduced from 1hr to 720s to keep the calculation of total hashrate more precise, this means workers not having reported in during the last 12 minutes are not added to the miner total hr and pool hr. -- Change: The 'time-out' value of miners has been enlarged to have miners remain in history when they are away for a while (max 24h). For individual workers it's set to 30minutes. A miner will be deleted from history if the historical share rate drops below 50 AND he has not submitted a nonce in the last 24h +- Change: The 'time-out' value of miners has been enlarged to have miners remain in history when they are away for a while (max 24h). For individual workers it's set to 30minutes. - Change: Discard of last remaining historical shares has been added to prevent ghost miners remaining in the list indefinely (hist.shares would never reach zero) +- Change: A miner will be deleted from history if the historical share rate drops below 50 AND he has not submitted a nonce in the last 24h - Change: Only 'active miners' are counted to calculate total HR: those with miner HR > 0 -- Added/Change: Nexte average CPU Blocks HR we now also calculate average GPU blocks HR. Both are now only based on active miners. +- Added/Change: Next average CPU Blocks HR we now also calculate average GPU blocks HR. Both are now only based on active miners. - Change: How far back last payments are displayed on payments page is moved to config - Change: During payment cycle, how far back is searched for small pending payments is moved to config. - Change: Manual payment request of all outstanding payments now looks through entire pool history. diff --git a/api.php b/api.php index 579e6ff..091393a 100644 --- a/api.php +++ b/api.php @@ -121,6 +121,7 @@ echo json_encode(array("cpu_hr"=>$total_hr, "gpu_hr"=>$total_gpu, "current_block_height"=>$current, "last_won_block"=>$last_won, "last_won_block_time"=>$last_won_time, "miners"=>$miners, "fee"=>$pool_config['fee'])); } + else{ $miner=$m; $hashrate=$db->single("SELECT hashrate FROM miners WHERE id='$m'"); $gpu_hr=$db->single("SELECT gpuhr FROM miners WHERE id='$m'"); @@ -160,7 +161,7 @@ echo json_encode(array("miner"=>$miner, "cpu_hr"=>$hashrate, "gpu_hr"=>$gpu_hr, "historic shares"=>$historic, "current shares"=>$shares, "last nonce submite"=>$update, "total paid"=>$total_paid, "pending"=>$pending, "past_24h"=>$past_24h, "last_payment"=>$last_payment, "last_payment_date"=>$last_payment_time)); - + } } From 773306a589284c51363f4ccbf35273e4ede5123f Mon Sep 17 00:00:00 2001 From: bb-hendrik Date: Wed, 13 Feb 2019 15:01:21 +0100 Subject: [PATCH 083/134] small fix rounding error hr --- README.md | 1 + mine.php | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9a20d12..36c016b 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ Warning: because of additions to the config file, do not simply replace the php- - Change: On payments page: Removal of long TX addresses in payout page, replaced with links to block explorer - Change: To remove the constant confusion we are going to be consequent and call it GPU-*blocks* HR and NOT "GPU HR" (and CPU-*blocks* HR instead of "CPU HR") everywhere on the site. - Bugfix: template/index.html responsive html code of the purple box showing hashrates caused errors on android. Fixed. Also: C-HR is now displayed left, G-HR right, just as in all other tables. +- Bugfix: Rounding error hashrates - Change: Template/Header page: pool name set in config - Added: On dashboard: average h/s displayed on page - Added: On blocks won page - Blocks are veryfiable through link to Block Explorer, for transparency diff --git a/mine.php b/mine.php index 238c8b8..59c786e 100644 --- a/mine.php +++ b/mine.php @@ -36,8 +36,8 @@ function curl_post($url, $post) } $worker = $_GET['worker']; - $hr = (int)$_GET['hashrate']; - $gpuhr = (int)($_GET['gpuhr'] + (int)$_GET['hrgpu']); + $hr = (int)round($_GET['hashrate'],0); + $gpuhr = (int)round($_GET['gpuhr'],0) + (int)round($_GET['hrgpu'],0); $bind = [ ':id' => $worker, ':hr' => $hr, From 8b338b8549082af15e5bbfe908958c6dcb7d2a27 Mon Sep 17 00:00:00 2001 From: Ario <44259996+ariochain@users.noreply.github.com> Date: Thu, 14 Feb 2019 21:05:11 +0100 Subject: [PATCH 084/134] Update api.php --- api.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api.php b/api.php index 091393a..7a229f2 100644 --- a/api.php +++ b/api.php @@ -11,9 +11,9 @@ */ header('Content-Type: application/json'); -include("db.php"); +require_once __DIR__.'/db.php'; -$q = $_GET['q']; +$q = san($_GET['q']); if ($q == "miner") { From 43c40cf784f2176d1ea5ed582985544aa3984c6e Mon Sep 17 00:00:00 2001 From: Ario Date: Thu, 14 Feb 2019 20:34:21 +0000 Subject: [PATCH 085/134] template directory can be changed in config.php --- config-sample.php | 11 +++++++++++ index.php | 4 ++-- template/index.html | 2 +- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/config-sample.php b/config-sample.php index a159f8e..b6757c9 100644 --- a/config-sample.php +++ b/config-sample.php @@ -101,3 +101,14 @@ // how long are old payments shown on the website. Delete after x blocks, default 1000. Small pool set much higher $pool_config['payout_history'] = 1000; + +/* +|-------------------------------------------------------------------------- +| Design Settings +|-------------------------------------------------------------------------- +*/ + + +$pool_config['template_directory'] = 'template/'; + + diff --git a/index.php b/index.php index 5e20007..2f7f615 100755 --- a/index.php +++ b/index.php @@ -1,12 +1,12 @@
    -
    +
    From 66bc7b76b49951d2671609531b777dbb50fcfef6 Mon Sep 17 00:00:00 2001 From: Ario Date: Thu, 14 Feb 2019 20:45:46 +0000 Subject: [PATCH 086/134] arionum.ico changed to favicon.ico --- index.php | 1 + arionum.ico => template/favicon.ico | Bin template/header.html | 2 +- template/index.html | 2 +- 4 files changed, 3 insertions(+), 2 deletions(-) rename arionum.ico => template/favicon.ico (100%) diff --git a/index.php b/index.php index 2f7f615..7f07505 100755 --- a/index.php +++ b/index.php @@ -16,6 +16,7 @@ $tpl->assign("q", $q); $tpl->assign("id", $id); $tpl->assign("pool_name", $pool_config['pool_name']); +$tpl->assign("template_directory", $pool_config['template_directory']); $tpl->draw('header'); if ($q == "") { diff --git a/arionum.ico b/template/favicon.ico similarity index 100% rename from arionum.ico rename to template/favicon.ico diff --git a/template/header.html b/template/header.html index ce4b724..985b1c2 100755 --- a/template/header.html +++ b/template/header.html @@ -31,7 +31,7 @@ - +
    -
    +
    From db087127b7e618d48aba276d65f41686c2224cc1 Mon Sep 17 00:00:00 2001 From: Ario Date: Thu, 14 Feb 2019 22:07:02 +0000 Subject: [PATCH 087/134] Change info.html --- config-sample.php | 1 + index.php | 1 + payments.php | 6 +- template/blocks.html | 2 +- template/info.html | 298 ++++++++++++++++++++++++++++++++++++++----- 5 files changed, 275 insertions(+), 33 deletions(-) diff --git a/config-sample.php b/config-sample.php index b6757c9..6cd4378 100644 --- a/config-sample.php +++ b/config-sample.php @@ -101,6 +101,7 @@ // how long are old payments shown on the website. Delete after x blocks, default 1000. Small pool set much higher $pool_config['payout_history'] = 1000; +$pool_config['payout_shedule'] = '1 hour'; /* |-------------------------------------------------------------------------- diff --git a/index.php b/index.php index 7f07505..3ee8451 100755 --- a/index.php +++ b/index.php @@ -204,6 +204,7 @@ $tpl->assign("cpu_deadline", number_format($pool_config['max_deadline'])); $tpl->assign("gpu_deadline", number_format($pool_config['max_deadline_gpu'])); $tpl->assign("poolwallet", $pool_config['address']); + $tpl->assign("payout_shedule", $pool_config['payout_shedule']); $tpl->assign("current_reward", $pool_config['current_reward']*100,0); $tpl->assign("miner_reward", $pool_config['miner_reward']*100,0); $tpl->assign("historic_reward", $pool_config['historic_reward']*100,0); diff --git a/payments.php b/payments.php index 57c3edc..e860c47 100644 --- a/payments.php +++ b/payments.php @@ -88,9 +88,11 @@ function pay_post($url, $data = []) echo "Checking $x[block]\n"; $s = $aro->single('SELECT COUNT(1) FROM blocks WHERE id=:id', [':id' => $x['block']]); if ($s === 0) { -// dit kunnen we dus aanpassen naar orphaned. block wordt niet nog een keer meegenomen want verdwijnt uit payments + + // dit kunnen we dus aanpassen naar orphaned. block wordt niet nog een keer meegenomen want verdwijnt uit payments $db->run('DELETE FROM blocks WHERE id=:id', [':id' => $x['block']]); -// nu halen we de payments weg en wordt het block niet opnieuw geselecteerd bij de volgende payment cycle + + // nu halen we de payments weg en wordt het block niet opnieuw geselecteerd bij de volgende payment cycle $db->run('DELETE FROM payments WHERE block=:id', [':id' => $x['block']]); echo "Deleted block: $x[block]\n"; } diff --git a/template/blocks.html b/template/blocks.html index 63c937b..2cc256c 100755 --- a/template/blocks.html +++ b/template/blocks.html @@ -30,7 +30,7 @@ {loop="$blocks"} {$value.reward} - {$value.height} + {$value.height}
    {$value.miner}
    {/loop} diff --git a/template/info.html b/template/info.html index a078724..9352cd2 100755 --- a/template/info.html +++ b/template/info.html @@ -1,32 +1,270 @@ -
    -
    - - -
    -
    - Information: -
    -
    -

    Pool address: {$pool_url}

    -

    DL: {$cpu_deadline} (CBlocks) / {$gpu_deadline} (GBlocks)

    -

    Degradation of historic shares: {$pool_degradation}% -

    Pool fee: {$fee}%

    -

    Minimum payout: {$minpayout} aro

    -

    Block confirmation: 10 blocks

    -

    Reward split: {$historic_reward}% historic shares, {$current_reward}% current shares and {$miner_reward}% for block finder

    -

    Payout schedule: every hour

    -

    Pool balance: Block Explorer

    -
    -

    This is an independent pool, which means you will only receive a payment when the pool finds a block.

    -
    -

    This service is provided as is.
    - For information and support: {$handle}@ARO discord.

    -
    - Server: {$server} - - -
    -
    +
    + +
    + +
    + +
    + + Information: + +
    + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +

    Pool mining address / url

    + +
    + +

    {$pool_url}

    +
    + +

    + +
    +

    {if="$handle"}For information and support:
    {$handle}@ARO discord{/if}

    +
    + +

    DeadLine CPU / CBlocks

    + +
    + +

    {$cpu_deadline}

    + +
    + +
    + +
    + +
    + +
    + +

    DeadLine GPU / GBlocks

    + +
    + +

    {$gpu_deadline}

    + +
    + + + + + +
    + +

    Degradation of historic shares

    + +
    + +

    {$pool_degradation}%

    + +
    + + + + + +
    + +

    Pool fee

    + +
    + +

    {$fee}%

    + +
    + + + +
    + +

    Minimum payout

    + +
    + +

    {$minpayout} ARO

    + +
    + + + +
    + +

    Block confirmation

    + +
    + +

    10 blocks

    + +
    + + + +
    + +

    Reward structure

    + +
    + +

    {$historic_reward}% historic shares

    + +
    +

    {$current_reward}% current shares

    + +
    +

    {$miner_reward}% block finder

    + +
    + +

    Payout schedule

    + +
    + +

    {$payout_shedule}

    + +
    + + + +
    + +

    Pool balance

    + +
    + +
    {$poolwallet}
    + +
    + +
    This is an independent pool, which means you will only receive a payment when the pool finds a block.
    +
    + -
    + +

    + + {if="$server"}{$server}{/if} + +

    + + +
    +
    + +
    From bff2068cd00b26265d42199b1765d682c673182a Mon Sep 17 00:00:00 2001 From: Ario Date: Thu, 14 Feb 2019 22:14:17 +0000 Subject: [PATCH 088/134] Change info.html --- template/info.html | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/template/info.html b/template/info.html index 9352cd2..5f49f8b 100755 --- a/template/info.html +++ b/template/info.html @@ -25,7 +25,7 @@

    Pool mining address / url

    -

    {$pool_url}

    +

    {$pool_url}

    @@ -49,7 +49,7 @@

    DeadLine CPU / CBlocks

    -

    {$cpu_deadline}

    +

    {$cpu_deadline}

    @@ -74,7 +74,7 @@

    DeadLine GPU / GBlocks

    -

    {$gpu_deadline}

    +

    {$gpu_deadline}

    @@ -97,7 +97,7 @@

    Degradation of historic shares

    -

    {$pool_degradation}%

    +

    {$pool_degradation}%

    @@ -122,7 +122,7 @@

    Pool fee

    -

    {$fee}%

    +

    {$fee}%

    @@ -143,7 +143,7 @@

    Minimum payout

    -

    {$minpayout} ARO

    +

    {$minpayout} ARO

    @@ -165,7 +165,7 @@

    Block confirmation

    -

    10 blocks

    +

    10 blocks

    @@ -187,17 +187,17 @@

    Reward structure

    -

    {$historic_reward}% historic shares

    +
    {$historic_reward}% historic shares
    -

    {$current_reward}% current shares

    +
    {$current_reward}% current shares
    -

    {$miner_reward}% block finder

    +
    {$miner_reward}% block finder
    @@ -211,7 +211,7 @@

    Payout schedule

    -

    {$payout_shedule}

    +

    {$payout_shedule}

    From 6221e838c17c6b209543946770e63f3db8b2ae6b Mon Sep 17 00:00:00 2001 From: Ario Date: Thu, 14 Feb 2019 22:27:47 +0000 Subject: [PATCH 089/134] links update --- template/account.html | 2 +- template/payments.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/template/account.html b/template/account.html index 55f1f56..1001cd6 100755 --- a/template/account.html +++ b/template/account.html @@ -45,7 +45,7 @@ Check last transaction: - Link + Link   diff --git a/template/payments.html b/template/payments.html index b8f45f1..dbbdd29 100755 --- a/template/payments.html +++ b/template/payments.html @@ -39,7 +39,7 @@ {$value.height}
    {$value.val}
    {$value.address} - Link + Link {/loop} From 66a8541e4aac9d6126a6466eb394e630c498c452 Mon Sep 17 00:00:00 2001 From: Ario Date: Thu, 14 Feb 2019 22:30:57 +0000 Subject: [PATCH 090/134] Change info.html - table class --- template/info.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template/info.html b/template/info.html index 5f49f8b..c79a042 100755 --- a/template/info.html +++ b/template/info.html @@ -13,7 +13,7 @@
    - +
    From ce2af5a4bc297ac4e04f465417cd4bedca3bcd88 Mon Sep 17 00:00:00 2001 From: Ario Date: Thu, 14 Feb 2019 22:33:12 +0000 Subject: [PATCH 091/134] Change api.php - sanitize input --- api.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api.php b/api.php index 7a229f2..6ac8b69 100644 --- a/api.php +++ b/api.php @@ -18,7 +18,7 @@ if ($q == "miner") { - $m = $_GET['m']; + $m = san($_GET['m']); if ($m == null) { echo "Invalid request"; From 30ea42432a21b4798fe8baa53041d99250ad1837 Mon Sep 17 00:00:00 2001 From: Ario Date: Thu, 14 Feb 2019 22:38:49 +0000 Subject: [PATCH 092/134] Change api.php - sanitize input --- api.php | 245 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 127 insertions(+), 118 deletions(-) diff --git a/api.php b/api.php index 6ac8b69..370fa3d 100644 --- a/api.php +++ b/api.php @@ -21,147 +21,156 @@ $m = san($_GET['m']); if ($m == null) { - echo "Invalid request"; - } - - else { - $miner=$m; - $hashrate=$db->single("SELECT hashrate FROM miners WHERE id='$m'"); - $gpu_hr=$db->single("SELECT gpuhr FROM miners WHERE id='$m'"); - $historic=$db->single("SELECT historic FROM miners WHERE id='$m'"); - $shares=$db->single("SELECT (shares FROM miners WHERE id='$m'"); - $update=$db->single("SELECT updated FROM MINERS where id='$m'"); - if ($update == false) { - $update = "No nonce submitted"; - } - if ($shares == false) { - $shares = "0"; - } - if ($historic == false) { - $historic = "0"; - } - if ($hashrate == false) { - $hashrate = "0"; - } - if ($gpu_hr == false) { - $gpu_hr = "0"; - } - - echo json_encode(array("miner"=>$miner, "cpu_hr"=>$hashrate, "gpu_hr"=>$gpu_hr, "historic shares"=>$historic, "current shares"=>$shares, "last nonce submitted"=>$update)); + + echo "Invalid request"; + + } else { + + $miner=$m; + $hashrate=$db->single("SELECT hashrate FROM miners WHERE id='$m'"); + $gpu_hr=$db->single("SELECT gpuhr FROM miners WHERE id='$m'"); + $historic=$db->single("SELECT historic FROM miners WHERE id='$m'"); + $shares=$db->single("SELECT (shares FROM miners WHERE id='$m'"); + $update=$db->single("SELECT updated FROM MINERS where id='$m'"); + if ($update == false) { + $update = "No nonce submitted"; + } + if ($shares == false) { + $shares = "0"; + } + if ($historic == false) { + $historic = "0"; + } + if ($hashrate == false) { + $hashrate = "0"; + } + if ($gpu_hr == false) { + $gpu_hr = "0"; + } + + echo json_encode(array("miner"=>$miner, "cpu_hr"=>$hashrate, "gpu_hr"=>$gpu_hr, "historic shares"=>$historic, "current shares"=>$shares, "last nonce submitted"=>$update)); } } elseif ($q == "status") { - $total_hr=$db->single("SELECT val FROM info WHERE id='total_hash_rate'"); - $total_gpu=$db->single("SELECT val FROM info WHERE id='total_gpu_hr'"); - $current=$aro->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); - $miners=$db->single("SELECT COUNT(1) FROM miners WHERE hashrate>0 OR gpuhr>0"); - $last_won=$db->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); - $last_won_time=$aro->single("SELECT date FROM blocks WHERE height=:h",[":h"=>$last_won]); - if ($last_won_time == false) { - $last_won_time = "Never"; - } - $avg_gpuhr = number_format($total_gpu / $miners, 0); - $avg_hr = number_format(($total_hr / $miners), 0); - if ($miners == 0) { - $avg_gpuhr = 0; - $avg_hr = 0; - } - - + $total_hr=$db->single("SELECT val FROM info WHERE id='total_hash_rate'"); + $total_gpu=$db->single("SELECT val FROM info WHERE id='total_gpu_hr'"); + $current=$aro->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); + $miners=$db->single("SELECT COUNT(1) FROM miners WHERE hashrate>0 OR gpuhr>0"); + $last_won=$db->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); + $last_won_time=$aro->single("SELECT date FROM blocks WHERE height=:h",[":h"=>$last_won]); - echo json_encode(array("cpu_hr"=>$total_hr, "gpu_hr"=>$total_gpu, "current_block_height"=>$current, "last_won_block"=>$last_won, "last_won_block_time"=>$last_won_time, "active miners"=>$miners, "avg_hr"=>$avg_hr, "avg_gpuhr"=>$avg_gpuhr, "fee"=>$pool_config['fee'])); - } + if ($last_won_time == false) { + $last_won_time = "Never"; + } + + $avg_gpuhr = number_format($total_gpu / $miners, 0); + $avg_hr = number_format(($total_hr / $miners), 0); + if ($miners == 0) { + $avg_gpuhr = 0; + $avg_hr = 0; + } -elseif ($q == "payments") { + echo json_encode(array("cpu_hr"=>$total_hr, "gpu_hr"=>$total_gpu, "current_block_height"=>$current, "last_won_block"=>$last_won, "last_won_block_time"=>$last_won_time, "active miners"=>$miners, "avg_hr"=>$avg_hr, "avg_gpuhr"=>$avg_gpuhr, "fee"=>$pool_config['fee'])); + + } elseif ($q == "payments") { - $m = $_GET['m']; + $m = san($_GET['m']); if ($m == null) { echo "Invalid request"; - } - - else { - $yesterday=time()-86400; - $yesterday_block=$aro->single("SELECT height+1 FROM blocks WHERE date<=$yesterday ORDER by height DESC LIMIT 1"); - $last_payment_txn=$db->single("SELECT txn FROM payments WHERE address='$m' AND done=1 ORDER by height DESC LIMIT 1"); - $last_payment_time=$aro->single("SELECT date FROM transactions WHERE id=$last_payment_txn"); - $miner=$m; - $total_paid=$db->single("SELECT total_paid FROM miners WHERE id='$m'"); - $pending=$db->single("SELECT pending FROM miners WHERE id='$m'"); - $last_payment=$db->single("SELECT SUM(val) FROM payments WHERE txn=:lasttxn AND done=1",[":lasttxn"=>$last_payment_txn]); - if ($last_payment_time == false) { - $last_payment_time = "Payment in process"; - } - if ($last_payment == 0 ) { - $last_payment_time = "No payment yet"; - } - $past_24h=$db->single("SELECT SUM(val) FROM payments WHERE address='$m' AND height>=$yesterday_block AND done=1"); - echo json_encode(array("miner"=>$miner, "total paid"=>$total_paid, "pending"=>$pending, "past_24h"=>$past_24h, "last_payment"=>$last_payment, "last_payment_date"=>$last_payment_time)); + } else { + $yesterday=time()-86400; + $yesterday_block=$aro->single("SELECT height+1 FROM blocks WHERE date<=$yesterday ORDER by height DESC LIMIT 1"); + $last_payment_txn=$db->single("SELECT txn FROM payments WHERE address='$m' AND done=1 ORDER by height DESC LIMIT 1"); + $last_payment_time=$aro->single("SELECT date FROM transactions WHERE id=$last_payment_txn"); + $miner=$m; + $total_paid=$db->single("SELECT total_paid FROM miners WHERE id='$m'"); + $pending=$db->single("SELECT pending FROM miners WHERE id='$m'"); + $last_payment=$db->single("SELECT SUM(val) FROM payments WHERE txn=:lasttxn AND done=1",[":lasttxn"=>$last_payment_txn]); + + if ($last_payment_time == false) { + $last_payment_time = "Payment in process"; + } + + if ($last_payment == 0 ) { + $last_payment_time = "No payment yet"; + } + + $past_24h=$db->single("SELECT SUM(val) FROM payments WHERE address='$m' AND height>=$yesterday_block AND done=1"); + echo json_encode(array("miner"=>$miner, "total paid"=>$total_paid, "pending"=>$pending, "past_24h"=>$past_24h, "last_payment"=>$last_payment, "last_payment_date"=>$last_payment_time)); } } else { - $m = $_GET['m']; + $m = san($_GET['m']); if ($m == null) { - // we keep this here as this is the old aropool.com api, for compatibility - $total_hr=$db->single("SELECT val FROM info WHERE id='total_hash_rate'"); - $total_gpu=$db->single("SELECT val FROM info WHERE id='total_gpu_hr'"); - $current=$aro->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); - $miners=$db->single("SELECT COUNT(1) FROM miners"); - $last_won=$db->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); - $last_won_time=$aro->single("SELECT date FROM blocks WHERE height=:h",[":h"=>$last_won]); - echo json_encode(array("cpu_hr"=>$total_hr, "gpu_hr"=>$total_gpu, "current_block_height"=>$current, "last_won_block"=>$last_won, "last_won_block_time"=>$last_won_time, "miners"=>$miners, "fee"=>$pool_config['fee'])); - } - - else{ - $miner=$m; - $hashrate=$db->single("SELECT hashrate FROM miners WHERE id='$m'"); - $gpu_hr=$db->single("SELECT gpuhr FROM miners WHERE id='$m'"); - $historic=$db->single("SELECT historic FROM miners WHERE id='$m'"); - $shares=$db->single("SELECT shares FROM miners WHERE id='$m'"); - $update=$db->single("SELECT updated FROM MINERS where id='$m'"); - if ($update == false) { - $update = "No nonce submitted"; - } - if ($shares == false) { - $shares = "0"; - } - if ($historic == false) { - $historic = "0"; - } - if ($hashrate == false) { - $hashrate = "0"; - } - if ($gpu_hr == false) { - $gpu_hr = "0"; - } - - $yesterday=time()-86400; - $yesterday_block=$aro->single("SELECT height+1 FROM blocks WHERE date<=$yesterday ORDER by height DESC LIMIT 1"); - $last_payment_txn=$db->single("SELECT txn FROM payments WHERE address='$m' AND done=1 ORDER by height DESC LIMIT 1"); - $last_payment_time=$aro->single("SELECT date FROM transactions WHERE id=$last_payment_txn"); - $total_paid=$db->single("SELECT total_paid FROM miners WHERE id='$m'"); - $pending=$db->single("SELECT pending FROM miners WHERE id='$m'"); - $last_payment=$db->single("SELECT SUM(val) FROM payments WHERE txn=:lasttxn AND done=1",[":lasttxn"=>$last_payment_txn]); - if ($last_payment_time == false) { - $last_payment_time = "Payment in process"; - } - if ($last_payment == 0 ) { - $last_payment_time = "No payment yet"; - } - $past_24h=$db->single("SELECT SUM(val) FROM payments WHERE address='$m' AND height>=$yesterday_block AND done=1"); - - echo json_encode(array("miner"=>$miner, "cpu_hr"=>$hashrate, "gpu_hr"=>$gpu_hr, "historic shares"=>$historic, "current shares"=>$shares, "last nonce submite"=>$update, "total paid"=>$total_paid, "pending"=>$pending, "past_24h"=>$past_24h, "last_payment"=>$last_payment, "last_payment_date"=>$last_payment_time)); + // we keep this here as this is the old aropool.com api, for compatibility + $total_hr=$db->single("SELECT val FROM info WHERE id='total_hash_rate'"); + $total_gpu=$db->single("SELECT val FROM info WHERE id='total_gpu_hr'"); + $current=$aro->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); + $miners=$db->single("SELECT COUNT(1) FROM miners"); + $last_won=$db->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); + $last_won_time=$aro->single("SELECT date FROM blocks WHERE height=:h",[":h"=>$last_won]); + echo json_encode(array("cpu_hr"=>$total_hr, "gpu_hr"=>$total_gpu, "current_block_height"=>$current, "last_won_block"=>$last_won, "last_won_block_time"=>$last_won_time, "miners"=>$miners, "fee"=>$pool_config['fee'])); - } + } else { + + $miner=$m; + $hashrate=$db->single("SELECT hashrate FROM miners WHERE id='$m'"); + $gpu_hr=$db->single("SELECT gpuhr FROM miners WHERE id='$m'"); + $historic=$db->single("SELECT historic FROM miners WHERE id='$m'"); + $shares=$db->single("SELECT shares FROM miners WHERE id='$m'"); + $update=$db->single("SELECT updated FROM MINERS where id='$m'"); + + if ($update == false) { + $update = "No nonce submitted"; + } + + if ($shares == false) { + $shares = "0"; + } + + if ($historic == false) { + $historic = "0"; + } + + if ($hashrate == false) { + $hashrate = "0"; + } + + if ($gpu_hr == false) { + $gpu_hr = "0"; + } + + $yesterday=time()-86400; + $yesterday_block=$aro->single("SELECT height+1 FROM blocks WHERE date<=$yesterday ORDER by height DESC LIMIT 1"); + $last_payment_txn=$db->single("SELECT txn FROM payments WHERE address='$m' AND done=1 ORDER by height DESC LIMIT 1"); + $last_payment_time=$aro->single("SELECT date FROM transactions WHERE id=$last_payment_txn"); + $total_paid=$db->single("SELECT total_paid FROM miners WHERE id='$m'"); + $pending=$db->single("SELECT pending FROM miners WHERE id='$m'"); + $last_payment=$db->single("SELECT SUM(val) FROM payments WHERE txn=:lasttxn AND done=1",[":lasttxn"=>$last_payment_txn]); + + if ($last_payment_time == false) { + $last_payment_time = "Payment in process"; + } + + if ($last_payment == 0 ) { + $last_payment_time = "No payment yet"; + } + + $past_24h=$db->single("SELECT SUM(val) FROM payments WHERE address='$m' AND height>=$yesterday_block AND done=1"); + + echo json_encode(array("miner"=>$miner, "cpu_hr"=>$hashrate, "gpu_hr"=>$gpu_hr, "historic shares"=>$historic, "current shares"=>$shares, "last nonce submite"=>$update, "total paid"=>$total_paid, "pending"=>$pending, "past_24h"=>$past_24h, "last_payment"=>$last_payment, "last_payment_date"=>$last_payment_time)); + + } } From f47f53db203260ff21c459812ec6d25fc49a8e71 Mon Sep 17 00:00:00 2001 From: Ario Date: Fri, 15 Feb 2019 01:26:00 +0000 Subject: [PATCH 093/134] Change info.html --- template/info.html | 527 +++++++++++++++++++++++---------------------- 1 file changed, 264 insertions(+), 263 deletions(-) diff --git a/template/info.html b/template/info.html index c79a042..1f4ec81 100755 --- a/template/info.html +++ b/template/info.html @@ -1,270 +1,271 @@
    -
    - -
    - -
    - - Information: - -
    - - -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
    + +
    + +
    + + Information: + +
    + + +
    + +
    - -

    Pool mining address / url

    - -
    - -

    {$pool_url}

    -
    - -

    - -
    -

    {if="$handle"}For information and support:
    {$handle}@ARO discord{/if}

    -
    - -

    DeadLine CPU / CBlocks

    - -
    - -

    {$cpu_deadline}

    - -
    - -
    - -
    - -
    - -
    - -

    DeadLine GPU / GBlocks

    - -
    - -

    {$gpu_deadline}

    - -
    - - - - - -
    - -

    Degradation of historic shares

    - -
    - -

    {$pool_degradation}%

    - -
    - - - - - -
    - -

    Pool fee

    - -
    - -

    {$fee}%

    - -
    - - - -
    - -

    Minimum payout

    - -
    - -

    {$minpayout} ARO

    - -
    - - - -
    - -

    Block confirmation

    - -
    - -

    10 blocks

    - -
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + +
    Pool mining address / url
    + +
    + +
    {$pool_url}
    +
    + +
    + +
    +

    {if="$handle"}For information and support:
    {$handle}@ARO discord{/if}

    +
    + +
    DeadLine CPU / CBlocks
    + +
    + +
    {$cpu_deadline}
    + +
    + +
    + +
    + +
    + +
    + +
    DeadLine GPU / GBlocks
    + +
    + +
    {$gpu_deadline}
    + +
    + + + + + +
    + +
    Degradation of historic shares
    + +
    + +
    {$pool_degradation}%
    + +
    + + + + + +
    + +
    Pool fee
    + +
    + +
    {$fee}%
    + +
    + + + +
    + +
    Minimum payout
    + +
    + +
    {$minpayout} ARO
    + +
    + + + +
    - - - -
    - -

    Reward structure

    - -
    - -
    {$historic_reward}% historic shares
    - -
    + +
    Block confirmation
    + +
    + +
    10 blocks
    + +
    + + + +
    + +
    Reward structure
    + +
    + +
    {$historic_reward}% historic shares
    + +
    +
    {$current_reward}% current shares
    + +
    +
    {$miner_reward}% block finder
    + +
    + +
    Payout schedule
    + +
    + +
    {$payout_shedule}
    + +
    + + + +
    + +
    Pool balance
    + +
    + +
    {$poolwallet}
    + +
    + +
    This is an independent pool, which means you will only receive a payment when the pool finds a block.
    +
    -
    {$current_reward}% current shares
    - -
    -
    {$miner_reward}% block finder
    - -
    - -

    Payout schedule

    - -
    - -

    {$payout_shedule}

    - -
    - - - -
    - -

    Pool balance

    - -
    - -
    {$poolwallet}
    - -
    - -
    This is an independent pool, which means you will only receive a payment when the pool finds a block.
    -
    - - - -

    - - {if="$server"}{$server}{/if} - -

    - - + + + + + +

    + + {if="$server"}{$server}{/if} + +

    + + +
    +
    -
    -
    + \ No newline at end of file From 7c53726fe6432fe9d3044d9171ca0b4449c96dca Mon Sep 17 00:00:00 2001 From: Ario Date: Fri, 15 Feb 2019 13:22:49 +0000 Subject: [PATCH 094/134] Change api.php - m changed to id --- api.php | 101 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 51 insertions(+), 50 deletions(-) diff --git a/api.php b/api.php index 370fa3d..8d292dc 100644 --- a/api.php +++ b/api.php @@ -3,9 +3,9 @@ Usage: /api?q=status returns current status of the pool -/api?q=miner&m= returns total hashrate and shares of miner -/api?q=payments&m= returns payments of miner -/api?m= returns total hashrate and shares and payments of miner +/api?q=miner&id= returns total hashrate and shares of miner +/api?q=payments&id= returns payments of miner +/api?id= returns total hashrate and shares and payments of miner // do we need this, want this? /api.php without flags also returns pool status at the moment for compatibility reasons */ @@ -18,20 +18,19 @@ if ($q == "miner") { - $m = san($_GET['m']); + $id = san($_GET['id']); - if ($m == null) { + if ($id == null) { - echo "Invalid request"; + api_err("Invalid request"); } else { - $miner=$m; - $hashrate=$db->single("SELECT hashrate FROM miners WHERE id='$m'"); - $gpu_hr=$db->single("SELECT gpuhr FROM miners WHERE id='$m'"); - $historic=$db->single("SELECT historic FROM miners WHERE id='$m'"); - $shares=$db->single("SELECT (shares FROM miners WHERE id='$m'"); - $update=$db->single("SELECT updated FROM MINERS where id='$m'"); + $hashrate=$db->single("SELECT hashrate FROM miners WHERE id=:id",[":id"=>$id]); + $gpu_hr=$db->single("SELECT gpuhr FROM miners WHERE id=:id",[":id"=>$id]); + $historic=$db->single("SELECT historic FROM miners WHERE id=:id",[":id"=>$id]); + $shares=$db->single("SELECT (shares FROM miners WHERE id=:id",[":id"=>$id]); + $update=$db->single("SELECT updated FROM miners WHERE id=:id",[":id"=>$id]); if ($update == false) { $update = "No nonce submitted"; } @@ -48,7 +47,7 @@ $gpu_hr = "0"; } - echo json_encode(array("miner"=>$miner, "cpu_hr"=>$hashrate, "gpu_hr"=>$gpu_hr, "historic shares"=>$historic, "current shares"=>$shares, "last nonce submitted"=>$update)); + echo json_encode(array("miner"=>$id, "cpu_hr"=>$hashrate, "gpu_hr"=>$gpu_hr, "historic shares"=>$historic, "current shares"=>$shares, "last nonce submitted"=>$update)); } } @@ -78,39 +77,42 @@ } elseif ($q == "payments") { - $m = san($_GET['m']); + $id = san($_GET['id']); - if ($m == null) { - echo "Invalid request"; - } else { - $yesterday=time()-86400; - $yesterday_block=$aro->single("SELECT height+1 FROM blocks WHERE date<=$yesterday ORDER by height DESC LIMIT 1"); - $last_payment_txn=$db->single("SELECT txn FROM payments WHERE address='$m' AND done=1 ORDER by height DESC LIMIT 1"); - $last_payment_time=$aro->single("SELECT date FROM transactions WHERE id=$last_payment_txn"); - $miner=$m; - $total_paid=$db->single("SELECT total_paid FROM miners WHERE id='$m'"); - $pending=$db->single("SELECT pending FROM miners WHERE id='$m'"); - $last_payment=$db->single("SELECT SUM(val) FROM payments WHERE txn=:lasttxn AND done=1",[":lasttxn"=>$last_payment_txn]); + if ($id == null) { - if ($last_payment_time == false) { - $last_payment_time = "Payment in process"; - } + api_err("Invalid request"); + + } else { + $yesterday=time()-86400; + $yesterday_block=$aro->single("SELECT height+1 FROM blocks WHERE date<=$yesterday ORDER by height DESC LIMIT 1"); + $last_payment_txn=$db->single("SELECT txn FROM payments WHERE address=:id AND done=1 ORDER by height DESC LIMIT 1",[":id"=>$id]); + $last_payment_time=$aro->single("SELECT date FROM transactions WHERE id=$last_payment_txn"); + $miner=$m; + $total_paid=$db->single("SELECT total_paid FROM miners WHERE id=:id",[":id"=>$id]); + $pending=$db->single("SELECT pending FROM miners WHERE id=:id",[":id"=>$id]); + $last_payment=$db->single("SELECT SUM(val) FROM payments WHERE txn=:lasttxn AND done=1",[":lasttxn"=>$last_payment_txn]); + + if ($last_payment_time == false) { + $last_payment_time = "Payment in process"; + } - if ($last_payment == 0 ) { - $last_payment_time = "No payment yet"; - } + if ($last_payment == 0 ) { + $last_payment_time = "No payment yet"; + } - $past_24h=$db->single("SELECT SUM(val) FROM payments WHERE address='$m' AND height>=$yesterday_block AND done=1"); - echo json_encode(array("miner"=>$miner, "total paid"=>$total_paid, "pending"=>$pending, "past_24h"=>$past_24h, "last_payment"=>$last_payment, "last_payment_date"=>$last_payment_time)); + $past_24h=$db->single("SELECT SUM(val) FROM payments WHERE address=:id AND height>=$yesterday_block AND done=1",[":id"=>$id]); + + echo json_encode(array("miner"=>$miner, "total paid"=>$total_paid, "pending"=>$pending, "past_24h"=>$past_24h, "last_payment"=>$last_payment, "last_payment_date"=>$last_payment_time)); + } } - } -else { + else { - $m = san($_GET['m']); + $id = san($_GET['id']); - if ($m == null) { + if ($id == null) { // we keep this here as this is the old aropool.com api, for compatibility $total_hr=$db->single("SELECT val FROM info WHERE id='total_hash_rate'"); @@ -123,12 +125,11 @@ } else { - $miner=$m; - $hashrate=$db->single("SELECT hashrate FROM miners WHERE id='$m'"); - $gpu_hr=$db->single("SELECT gpuhr FROM miners WHERE id='$m'"); - $historic=$db->single("SELECT historic FROM miners WHERE id='$m'"); - $shares=$db->single("SELECT shares FROM miners WHERE id='$m'"); - $update=$db->single("SELECT updated FROM MINERS where id='$m'"); + $hashrate=$db->single("SELECT hashrate FROM miners WHERE id=:id",[":id"=>$id]); + $gpu_hr=$db->single("SELECT gpuhr FROM miners WHERE id=:id",[":id"=>$id]); + $historic=$db->single("SELECT historic FROM miners WHERE id=:id",[":id"=>$id]); + $shares=$db->single("SELECT shares FROM miners WHERE id=:id",[":id"=>$id]); + $update=$db->single("SELECT updated FROM miners WHERE id=:id",[":id"=>$id]); if ($update == false) { $update = "No nonce submitted"; @@ -152,12 +153,12 @@ $yesterday=time()-86400; $yesterday_block=$aro->single("SELECT height+1 FROM blocks WHERE date<=$yesterday ORDER by height DESC LIMIT 1"); - $last_payment_txn=$db->single("SELECT txn FROM payments WHERE address='$m' AND done=1 ORDER by height DESC LIMIT 1"); + $last_payment_txn=$db->single("SELECT txn FROM payments WHERE address=:id AND done=1 ORDER by height DESC LIMIT 1",[":id"=>$id]); $last_payment_time=$aro->single("SELECT date FROM transactions WHERE id=$last_payment_txn"); - $total_paid=$db->single("SELECT total_paid FROM miners WHERE id='$m'"); - $pending=$db->single("SELECT pending FROM miners WHERE id='$m'"); + $total_paid=$db->single("SELECT total_paid FROM miners WHERE id=:id",[":id"=>$id]); + $pending=$db->single("SELECT pending FROM miners WHERE id=:id",[":id"=>$id]); $last_payment=$db->single("SELECT SUM(val) FROM payments WHERE txn=:lasttxn AND done=1",[":lasttxn"=>$last_payment_txn]); - + if ($last_payment_time == false) { $last_payment_time = "Payment in process"; } @@ -165,10 +166,10 @@ if ($last_payment == 0 ) { $last_payment_time = "No payment yet"; } - - $past_24h=$db->single("SELECT SUM(val) FROM payments WHERE address='$m' AND height>=$yesterday_block AND done=1"); - echo json_encode(array("miner"=>$miner, "cpu_hr"=>$hashrate, "gpu_hr"=>$gpu_hr, "historic shares"=>$historic, "current shares"=>$shares, "last nonce submite"=>$update, "total paid"=>$total_paid, "pending"=>$pending, "past_24h"=>$past_24h, "last_payment"=>$last_payment, "last_payment_date"=>$last_payment_time)); + $past_24h=$db->single("SELECT SUM(val) FROM payments WHERE address=:id AND height>=$yesterday_block AND done=1",[":id"=>$id]); + + echo json_encode(array("miner"=>$id, "cpu_hr"=>$hashrate, "gpu_hr"=>$gpu_hr, "historic shares"=>$historic, "current shares"=>$shares, "last nonce submited"=>$update, "total paid"=>$total_paid, "pending"=>$pending, "past_24h"=>$past_24h, "last_payment"=>$last_payment, "last_payment_date"=>$last_payment_time)); } From b9d0d7924be2c17b2c5a8df626d6452254306087 Mon Sep 17 00:00:00 2001 From: Ario Date: Fri, 15 Feb 2019 14:12:25 +0000 Subject: [PATCH 095/134] Change api.php - bugfix --- api.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api.php b/api.php index 8d292dc..e03acaa 100644 --- a/api.php +++ b/api.php @@ -103,7 +103,7 @@ $past_24h=$db->single("SELECT SUM(val) FROM payments WHERE address=:id AND height>=$yesterday_block AND done=1",[":id"=>$id]); - echo json_encode(array("miner"=>$miner, "total paid"=>$total_paid, "pending"=>$pending, "past_24h"=>$past_24h, "last_payment"=>$last_payment, "last_payment_date"=>$last_payment_time)); + echo json_encode(array("miner"=>$id, "total paid"=>$total_paid, "pending"=>$pending, "past_24h"=>$past_24h, "last_payment"=>$last_payment, "last_payment_date"=>$last_payment_time)); } } From c1fb45de7a53d9fc38d4aaa50445dd252ff5678d Mon Sep 17 00:00:00 2001 From: Ario Date: Fri, 15 Feb 2019 17:04:47 +0000 Subject: [PATCH 096/134] Change api.php - major changes --- api.php | 245 +++++++++++++++++++++++++++----------------------------- 1 file changed, 120 insertions(+), 125 deletions(-) diff --git a/api.php b/api.php index e03acaa..5ae56d3 100644 --- a/api.php +++ b/api.php @@ -2,10 +2,9 @@ /* Usage: -/api?q=status returns current status of the pool -/api?q=miner&id= returns total hashrate and shares of miner +/api?q=poolstatus returns current status of the pool +/api?q=minerstatus&id= returns total hashrate and shares of miner /api?q=payments&id= returns payments of miner -/api?id= returns total hashrate and shares and payments of miner // do we need this, want this? /api.php without flags also returns pool status at the moment for compatibility reasons */ @@ -16,163 +15,159 @@ $q = san($_GET['q']); -if ($q == "miner") { +if ($q == "minerstatus") { $id = san($_GET['id']); if ($id == null) { - api_err("Invalid request"); - - } else { - - $hashrate=$db->single("SELECT hashrate FROM miners WHERE id=:id",[":id"=>$id]); - $gpu_hr=$db->single("SELECT gpuhr FROM miners WHERE id=:id",[":id"=>$id]); - $historic=$db->single("SELECT historic FROM miners WHERE id=:id",[":id"=>$id]); - $shares=$db->single("SELECT (shares FROM miners WHERE id=:id",[":id"=>$id]); - $update=$db->single("SELECT updated FROM miners WHERE id=:id",[":id"=>$id]); - if ($update == false) { - $update = "No nonce submitted"; - } - if ($shares == false) { - $shares = "0"; - } - if ($historic == false) { - $historic = "0"; - } - if ($hashrate == false) { - $hashrate = "0"; - } - if ($gpu_hr == false) { - $gpu_hr = "0"; - } - - echo json_encode(array("miner"=>$id, "cpu_hr"=>$hashrate, "gpu_hr"=>$gpu_hr, "historic shares"=>$historic, "current shares"=>$shares, "last nonce submitted"=>$update)); - } + api_err("Invalid request"); - } + } else { -elseif ($q == "status") { + $cpu_hashrate = $db->single("SELECT hashrate FROM miners WHERE id=:id",[":id"=>$id]); - $total_hr=$db->single("SELECT val FROM info WHERE id='total_hash_rate'"); - $total_gpu=$db->single("SELECT val FROM info WHERE id='total_gpu_hr'"); - $current=$aro->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); - $miners=$db->single("SELECT COUNT(1) FROM miners WHERE hashrate>0 OR gpuhr>0"); - $last_won=$db->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); - $last_won_time=$aro->single("SELECT date FROM blocks WHERE height=:h",[":h"=>$last_won]); + if ($cpu_hashrate != 0) { // If there is result, we can load rest of values - if ($last_won_time == false) { - $last_won_time = "Never"; - } - - $avg_gpuhr = number_format($total_gpu / $miners, 0); - $avg_hr = number_format(($total_hr / $miners), 0); + $gpu_hashrate = $db->single("SELECT gpuhr FROM miners WHERE id=:id",[":id"=>$id]); + $historic = $db->single("SELECT historic FROM miners WHERE id=:id",[":id"=>$id]); + $shares = $db->single("SELECT (shares FROM miners WHERE id=:id",[":id"=>$id]); + $update = $db->single("SELECT updated FROM miners WHERE id=:id",[":id"=>$id]); - if ($miners == 0) { - $avg_gpuhr = 0; - $avg_hr = 0; - } + $yesterday = time()-86400; + $yesterday_block = $aro->single("SELECT height+1 FROM blocks WHERE date<=$yesterday ORDER by height DESC LIMIT 1"); + $last_payment_txn = $db->single("SELECT txn FROM payments WHERE address=:id AND done=1 ORDER by height DESC LIMIT 1",[":id"=>$id]); + $last_payment_time = $aro->single("SELECT date FROM transactions WHERE id=$last_payment_txn"); + $total_paid = (int)$db->single("SELECT total_paid FROM miners WHERE id=:id",[":id"=>$id]); + $pending = $db->single("SELECT pending FROM miners WHERE id=:id",[":id"=>$id]); + $last_payment = $db->single("SELECT SUM(val) FROM payments WHERE txn=:lasttxn AND done=1",[":lasttxn"=>$last_payment_txn]); + $past_24h = $db->single("SELECT SUM(val) FROM payments WHERE address=:id AND height>=$yesterday_block AND done=1",[":id"=>$id]); - echo json_encode(array("cpu_hr"=>$total_hr, "gpu_hr"=>$total_gpu, "current_block_height"=>$current, "last_won_block"=>$last_won, "last_won_block_time"=>$last_won_time, "active miners"=>$miners, "avg_hr"=>$avg_hr, "avg_gpuhr"=>$avg_gpuhr, "fee"=>$pool_config['fee'])); - - } elseif ($q == "payments") { + if ($update == null) { + $update = "No nonce submitted"; + } - $id = san($_GET['id']); + if ($shares == null) { + $shares = 0; + } - if ($id == null) { + if ($historic == null) { + $historic = 0; + } - api_err("Invalid request"); - - } else { - $yesterday=time()-86400; - $yesterday_block=$aro->single("SELECT height+1 FROM blocks WHERE date<=$yesterday ORDER by height DESC LIMIT 1"); - $last_payment_txn=$db->single("SELECT txn FROM payments WHERE address=:id AND done=1 ORDER by height DESC LIMIT 1",[":id"=>$id]); - $last_payment_time=$aro->single("SELECT date FROM transactions WHERE id=$last_payment_txn"); - $miner=$m; - $total_paid=$db->single("SELECT total_paid FROM miners WHERE id=:id",[":id"=>$id]); - $pending=$db->single("SELECT pending FROM miners WHERE id=:id",[":id"=>$id]); - $last_payment=$db->single("SELECT SUM(val) FROM payments WHERE txn=:lasttxn AND done=1",[":lasttxn"=>$last_payment_txn]); + if ($cpu_hashrate == null) { + $cpu_hashrate = 0; + } - if ($last_payment_time == false) { - $last_payment_time = "Payment in process"; - } + if ($gpu_hashrate == null) { + $gpu_hashrate = 0; + } - if ($last_payment == 0 ) { - $last_payment_time = "No payment yet"; - } + if ($last_payment_time == null) { + $last_payment_time = "Payment in process"; + } - $past_24h=$db->single("SELECT SUM(val) FROM payments WHERE address=:id AND height>=$yesterday_block AND done=1",[":id"=>$id]); + if ($last_payment == 0 ) { + $last_payment_time = "No payment yet"; + } - echo json_encode(array("miner"=>$id, "total paid"=>$total_paid, "pending"=>$pending, "past_24h"=>$past_24h, "last_payment"=>$last_payment, "last_payment_date"=>$last_payment_time)); + if ($pending == null) { + $pending = 0; } - } + if ($last_payment == null) { + $last_payment = 0; + } - else { + if ($past_24h == null) { + $past_24h = 0; + } - $id = san($_GET['id']); + echo json_encode(array("miner"=>$id, "cpu_hr"=>$cpu_hashrate, "gpu_hr"=>$gpu_hashrate, "historic shares"=>$historic, "current shares"=>$shares, "last nonce submited"=>$update, "total paid"=>$total_paid, "pending"=>$pending, "past_24h"=>$past_24h, "last_payment"=>$last_payment, "last_payment_date"=>$last_payment_time)); + + } else { // No result - we don't have record for this id in our miners table - if ($id == null) { + api_err("Account not found"); - // we keep this here as this is the old aropool.com api, for compatibility - $total_hr=$db->single("SELECT val FROM info WHERE id='total_hash_rate'"); - $total_gpu=$db->single("SELECT val FROM info WHERE id='total_gpu_hr'"); - $current=$aro->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); - $miners=$db->single("SELECT COUNT(1) FROM miners"); - $last_won=$db->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); - $last_won_time=$aro->single("SELECT date FROM blocks WHERE height=:h",[":h"=>$last_won]); - echo json_encode(array("cpu_hr"=>$total_hr, "gpu_hr"=>$total_gpu, "current_block_height"=>$current, "last_won_block"=>$last_won, "last_won_block_time"=>$last_won_time, "miners"=>$miners, "fee"=>$pool_config['fee'])); - - } else { + } + } - $hashrate=$db->single("SELECT hashrate FROM miners WHERE id=:id",[":id"=>$id]); - $gpu_hr=$db->single("SELECT gpuhr FROM miners WHERE id=:id",[":id"=>$id]); - $historic=$db->single("SELECT historic FROM miners WHERE id=:id",[":id"=>$id]); - $shares=$db->single("SELECT shares FROM miners WHERE id=:id",[":id"=>$id]); - $update=$db->single("SELECT updated FROM miners WHERE id=:id",[":id"=>$id]); +} elseif ($q == "poolstatus") { - if ($update == false) { - $update = "No nonce submitted"; - } + $total_hr = (int)$db->single("SELECT val FROM info WHERE id='total_hash_rate'"); + $total_gpu = (int)$db->single("SELECT val FROM info WHERE id='total_gpu_hr'"); + $current = $aro->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); + $miners = $db->single("SELECT COUNT(1) FROM miners WHERE hashrate>0 OR gpuhr>0"); + $last_won = (int)$db->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); + $last_won_time = $aro->single("SELECT date FROM blocks WHERE height=:h",[":h"=>$last_won]); + $avg_gpuhr = (int)number_format($total_gpu / $miners, 0); + $avg_hr = (int)number_format(($total_hr / $miners), 0); - if ($shares == false) { - $shares = "0"; - } + if ($last_won_time == null) { + $last_won_time = "Never"; + } - if ($historic == false) { - $historic = "0"; - } + if ($miners == 0) { + $avg_gpuhr = 0; + $avg_hr = 0; + } - if ($hashrate == false) { - $hashrate = "0"; - } + echo json_encode(array("cpu_hr"=>$total_hr, "gpu_hr"=>$total_gpu, "current_block_height"=>$current, "last_won_block"=>$last_won, "last_won_block_time"=>$last_won_time, "active miners"=>$miners, "avg_hr"=>$avg_hr, "avg_gpuhr"=>$avg_gpuhr, "fee"=>$pool_config['fee'])); + +} elseif ($q == "payments") { - if ($gpu_hr == false) { - $gpu_hr = "0"; - } - - $yesterday=time()-86400; - $yesterday_block=$aro->single("SELECT height+1 FROM blocks WHERE date<=$yesterday ORDER by height DESC LIMIT 1"); - $last_payment_txn=$db->single("SELECT txn FROM payments WHERE address=:id AND done=1 ORDER by height DESC LIMIT 1",[":id"=>$id]); - $last_payment_time=$aro->single("SELECT date FROM transactions WHERE id=$last_payment_txn"); - $total_paid=$db->single("SELECT total_paid FROM miners WHERE id=:id",[":id"=>$id]); - $pending=$db->single("SELECT pending FROM miners WHERE id=:id",[":id"=>$id]); - $last_payment=$db->single("SELECT SUM(val) FROM payments WHERE txn=:lasttxn AND done=1",[":lasttxn"=>$last_payment_txn]); - - if ($last_payment_time == false) { - $last_payment_time = "Payment in process"; - } + $id = san($_GET['id']); - if ($last_payment == 0 ) { - $last_payment_time = "No payment yet"; - } + if ($id == null) { - $past_24h=$db->single("SELECT SUM(val) FROM payments WHERE address=:id AND height>=$yesterday_block AND done=1",[":id"=>$id]); + api_err("Invalid request"); + + } else { + + $yesterday = time()-86400; + $yesterday_block = $aro->single("SELECT height+1 FROM blocks WHERE date<=$yesterday ORDER by height DESC LIMIT 1"); + $last_payment_txn = $db->single("SELECT txn FROM payments WHERE address=:id AND done=1 ORDER by height DESC LIMIT 1",[":id"=>$id]); + $last_payment_time = $aro->single("SELECT date FROM transactions WHERE id=$last_payment_txn"); + $total_paid = (int)$db->single("SELECT total_paid FROM miners WHERE id=:id",[":id"=>$id]); + $pending = $db->single("SELECT pending FROM miners WHERE id=:id",[":id"=>$id]); + $last_payment = $db->single("SELECT SUM(val) FROM payments WHERE txn=:lasttxn AND done=1",[":lasttxn"=>$last_payment_txn]); + $past_24h = $db->single("SELECT SUM(val) FROM payments WHERE address=:id AND height>=$yesterday_block AND done=1",[":id"=>$id]); + + if ($pending == null) { + $pending = 0; + } - echo json_encode(array("miner"=>$id, "cpu_hr"=>$hashrate, "gpu_hr"=>$gpu_hr, "historic shares"=>$historic, "current shares"=>$shares, "last nonce submited"=>$update, "total paid"=>$total_paid, "pending"=>$pending, "past_24h"=>$past_24h, "last_payment"=>$last_payment, "last_payment_date"=>$last_payment_time)); - + if ($last_payment == null) { + $last_payment = 0; + } + + if ($past_24h == null) { + $past_24h = 0; } + if ($last_payment_time == null) { + $last_payment_time = "Payment in process"; + } + + if ($last_payment == 0 ) { + $last_payment_time = "No payment yet"; + } + + echo json_encode(array("miner"=>$id, "total paid"=>$total_paid, "pending"=>$pending, "past_24h"=>$past_24h, "last_payment"=>$last_payment, "last_payment_date"=>$last_payment_time)); + + } + +} else { + + // we keep this here as this is the old aropool.com api, for compatibility + $total_hr = $db->single("SELECT val FROM info WHERE id='total_hash_rate'"); + $total_gpu = $db->single("SELECT val FROM info WHERE id='total_gpu_hr'"); + $current = $aro->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); + $miners = $db->single("SELECT COUNT(1) FROM miners"); + $last_won = $db->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); + $last_won_time = $aro->single("SELECT date FROM blocks WHERE height=:h",[":h"=>$last_won]); + + echo json_encode(array("cpu_hr"=>$total_hr, "gpu_hr"=>$total_gpu, "current_block_height"=>$current, "last_won_block"=>$last_won, "last_won_block_time"=>$last_won_time, "miners"=>$miners, "fee"=>$pool_config['fee'])); } From a8e2f315cbf7646e757daf98ad8c282c5322425d Mon Sep 17 00:00:00 2001 From: Ario Date: Fri, 15 Feb 2019 18:40:33 +0000 Subject: [PATCH 097/134] Change mine.php - save argon instead of nonce --- mine.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/mine.php b/mine.php index 59c786e..cfe04b2 100644 --- a/mine.php +++ b/mine.php @@ -49,9 +49,9 @@ function curl_post($url, $post) ':gpuhr2' => $gpuhr, ]; -// fix Dan's misreporting + // fix Dan's misreporting if ($gpuhr == 0){ - $f = file_get_contents($pool_config['node_url'].'/mine.php?q=info'); + $f = file_get_contents('cache/info.txt'); $g = json_decode($f, true); if ($g['data']['height'] % 2 == 1) { $db->run( @@ -97,18 +97,19 @@ function curl_post($url, $post) $argon = $_POST['argon']; $address = san($_POST['address']); - $chk = $db->single('SELECT count(1) FROM nonces WHERE nonce=:nonce', [':nonce' => $nonce]); + $chk = $db->single('SELECT count(1) FROM nonces WHERE nonce=:nonce', [':nonce' => $argon]); if ($chk !== 0) { - $db->run('INSERT into abusers SET miner=:miner, nonce=:nonce', [':miner' => $address, ':nonce' => $nonce]); + $db->run('INSERT into abusers SET miner=:miner, nonce=:nonce', [':miner' => $address, ':nonce' => $argon]); api_err('duplicate'); exit; } - $db->run('INSERT IGNORE into nonces SET nonce=:nonce', [':nonce' => $nonce]); + $db->run('INSERT IGNORE into nonces SET nonce=:nonce', [':nonce' => $argon]); $f = file_get_contents($pool_config['node_url'].'/mine.php?q=info'); $g = json_decode($f, true); -if ((int)$_POST['height'] > 1 && $g['data']['height'] !== (int)$_POST['height']) { + + if ((int)$_POST['height'] > 1 && $g['data']['height'] !== (int)$_POST['height']) { api_err('stale block'); } @@ -235,7 +236,7 @@ function curl_post($url, $post) ); api_echo('accepted'); } else { - $db->run('DELETE FROM nonces WHERE nonce=:nonce', ['nonce' => $nonce]); + $db->run('DELETE FROM nonces WHERE nonce=:nonce', ['nonce' => $argon]); $db->run( 'INSERT into rejects SET ip=:ip, data=UNIX_TIMESTAMP() ON DUPLICATE KEY update data=UNIX_TIMESTAMP()', From 758b7af85c578226d1e8b28d3fec6a9180b654a1 Mon Sep 17 00:00:00 2001 From: Ario Date: Fri, 15 Feb 2019 18:52:20 +0000 Subject: [PATCH 098/134] Change index.html - display current block type --- template/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template/index.html b/template/index.html index 867baea..821a316 100755 --- a/template/index.html +++ b/template/index.html @@ -9,7 +9,7 @@

    {$height}

    -
    Current Block
    +
    {if="$height % 2 == 0"}CPU / CBlock{else}GPU / GBlock{/if}
    From a2075a4f807a36c19d07ee87b373f7a0f63e2805 Mon Sep 17 00:00:00 2001 From: Ario Date: Fri, 15 Feb 2019 21:18:54 +0000 Subject: [PATCH 099/134] Change api.php - bugfix --- api.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api.php b/api.php index 5ae56d3..31e8b9b 100644 --- a/api.php +++ b/api.php @@ -31,7 +31,7 @@ $gpu_hashrate = $db->single("SELECT gpuhr FROM miners WHERE id=:id",[":id"=>$id]); $historic = $db->single("SELECT historic FROM miners WHERE id=:id",[":id"=>$id]); - $shares = $db->single("SELECT (shares FROM miners WHERE id=:id",[":id"=>$id]); + $shares = $db->single("SELECT shares FROM miners WHERE id=:id",[":id"=>$id]); $update = $db->single("SELECT updated FROM miners WHERE id=:id",[":id"=>$id]); $yesterday = time()-86400; From 7ec97eee76f103bea5b5ca9f293164a50124d95c Mon Sep 17 00:00:00 2001 From: Ario Date: Fri, 15 Feb 2019 21:23:20 +0000 Subject: [PATCH 100/134] Change api.php - change average --- api.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api.php b/api.php index 31e8b9b..c045de3 100644 --- a/api.php +++ b/api.php @@ -100,8 +100,8 @@ $miners = $db->single("SELECT COUNT(1) FROM miners WHERE hashrate>0 OR gpuhr>0"); $last_won = (int)$db->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); $last_won_time = $aro->single("SELECT date FROM blocks WHERE height=:h",[":h"=>$last_won]); - $avg_gpuhr = (int)number_format($total_gpu / $miners, 0); - $avg_hr = (int)number_format(($total_hr / $miners), 0); + $avg_gpuhr = (int)round($total_gpu / $miners, 0); + $avg_hr = (int)round($total_hr / $miners, 0); if ($last_won_time == null) { $last_won_time = "Never"; From 1eec8465181f25d72d7d6d2542a05000f4e5890d Mon Sep 17 00:00:00 2001 From: Ario Date: Sat, 16 Feb 2019 16:03:49 +0000 Subject: [PATCH 101/134] external validation --- config-sample.php | 2 ++ mine.php | 13 +++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/config-sample.php b/config-sample.php index 6cd4378..eabd6c3 100644 --- a/config-sample.php +++ b/config-sample.php @@ -57,6 +57,8 @@ // The fee that the pool takes from the funds (default is 2%) $pool_config['fee'] = 0.02; +// If value exists, pool will use it for external hash validation - https://github.com/bogdanadnan/ArgonValidationService +// pool_config['validator_url'] = 'http://localhost:2000'; /* diff --git a/mine.php b/mine.php index cfe04b2..e3f10c1 100644 --- a/mine.php +++ b/mine.php @@ -125,10 +125,19 @@ function curl_post($url, $post) $base = "$public_key-$nonce-".$g['data']['block'].'-'.$g['data']['difficulty']; - if (!password_verify($base, $argon2)) { - api_err("Invalid argon - $base - $argon2"); + + if (isset($pool_config['validator_url'])) { // If validator url exists, use it for hash validation + $res = file_get_contents($pool_config['validator_url'].'/validate?argon='. $argon2 . '&base=' . $base); + if ($res !== 'VALID') { + api_err("Invalid argon - $base - $argon2"); + } + } else { // Validate hash old fashion way + if (!password_verify($base, $argon2)) { + api_err("Invalid argon - $base - $argon2"); + } } + $hash = $base.$argon2; for ($i = 0; $i < 5; $i++) { From 70ba7eea3408f65affbb38432837899375f4de04 Mon Sep 17 00:00:00 2001 From: Ario Date: Sat, 16 Feb 2019 16:17:58 +0000 Subject: [PATCH 102/134] Change api.php - remove avg numbers // they can be easily calculated from results --- api.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/api.php b/api.php index c045de3..c4baab3 100644 --- a/api.php +++ b/api.php @@ -100,8 +100,6 @@ $miners = $db->single("SELECT COUNT(1) FROM miners WHERE hashrate>0 OR gpuhr>0"); $last_won = (int)$db->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); $last_won_time = $aro->single("SELECT date FROM blocks WHERE height=:h",[":h"=>$last_won]); - $avg_gpuhr = (int)round($total_gpu / $miners, 0); - $avg_hr = (int)round($total_hr / $miners, 0); if ($last_won_time == null) { $last_won_time = "Never"; @@ -112,7 +110,7 @@ $avg_hr = 0; } - echo json_encode(array("cpu_hr"=>$total_hr, "gpu_hr"=>$total_gpu, "current_block_height"=>$current, "last_won_block"=>$last_won, "last_won_block_time"=>$last_won_time, "active miners"=>$miners, "avg_hr"=>$avg_hr, "avg_gpuhr"=>$avg_gpuhr, "fee"=>$pool_config['fee'])); + echo json_encode(array("cpu_hr"=>$total_hr, "gpu_hr"=>$total_gpu, "current_block_height"=>$current, "last_won_block"=>$last_won, "last_won_block_time"=>$last_won_time, "active miners"=>$miners, "fee"=>$pool_config['fee'])); } elseif ($q == "payments") { From 0600b557307e5df2bdd12f6fec1c82ea4157faf0 Mon Sep 17 00:00:00 2001 From: Ario Date: Sat, 16 Feb 2019 16:32:40 +0000 Subject: [PATCH 103/134] Change api.php - add fee, reward structure, min payout, and workers to results --- api.php | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/api.php b/api.php index c4baab3..d58c135 100644 --- a/api.php +++ b/api.php @@ -42,6 +42,8 @@ $pending = $db->single("SELECT pending FROM miners WHERE id=:id",[":id"=>$id]); $last_payment = $db->single("SELECT SUM(val) FROM payments WHERE txn=:lasttxn AND done=1",[":lasttxn"=>$last_payment_txn]); $past_24h = $db->single("SELECT SUM(val) FROM payments WHERE address=:id AND height>=$yesterday_block AND done=1",[":id"=>$id]); + + $workers = $db->single("SELECT COUNT(1) FROM workers WHERE miner=:id",[":id"=>$id]); if ($update == null) { $update = "No nonce submitted"; @@ -83,7 +85,23 @@ $past_24h = 0; } - echo json_encode(array("miner"=>$id, "cpu_hr"=>$cpu_hashrate, "gpu_hr"=>$gpu_hashrate, "historic shares"=>$historic, "current shares"=>$shares, "last nonce submited"=>$update, "total paid"=>$total_paid, "pending"=>$pending, "past_24h"=>$past_24h, "last_payment"=>$last_payment, "last_payment_date"=>$last_payment_time)); + if ($workers == null) { + $workers = 0; + } + echo json_encode(array( + "miner" => $id, + "cpu_hr" => $cpu_hashrate, + "gpu_hr" => $gpu_hashrate, + "workers" => $workers, + "historic shares" => $historic, + "current shares" => $shares, + "last nonce submited" => $update, + "total paid" => $total_paid, + "pending" => $pending, + "past_24h" => $past_24h, + "last_payment" => $last_payment, + "last_payment_date" => $last_payment_time + )); } else { // No result - we don't have record for this id in our miners table @@ -110,7 +128,20 @@ $avg_hr = 0; } - echo json_encode(array("cpu_hr"=>$total_hr, "gpu_hr"=>$total_gpu, "current_block_height"=>$current, "last_won_block"=>$last_won, "last_won_block_time"=>$last_won_time, "active miners"=>$miners, "fee"=>$pool_config['fee'])); + echo json_encode( + array( + "cpu_hr" => $total_hr, + "gpu_hr" => $total_gpu, + "current_block_height" => $current, + "last_won_block" => $last_won, + "last_won_block_time" => $last_won_time, + "active miners" => $miners, + "fee" => $pool_config['fee'], + "historic_reward" => $pool_config['historic_reward'], + "current_reward" => $pool_config['current_reward'], + "miner_reward" => $pool_config['miner_reward'], + "min_payout" => $pool_config['min_payout'] + )); } elseif ($q == "payments") { From 6a6590e393ef9f7632903a714fe4d52855ef98fb Mon Sep 17 00:00:00 2001 From: Ario Date: Sat, 16 Feb 2019 16:36:20 +0000 Subject: [PATCH 104/134] Change api.php - small fix --- api.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/api.php b/api.php index d58c135..477d70d 100644 --- a/api.php +++ b/api.php @@ -90,13 +90,13 @@ } echo json_encode(array( "miner" => $id, - "cpu_hr" => $cpu_hashrate, - "gpu_hr" => $gpu_hashrate, + "cpu_hashrate" => $cpu_hashrate, + "gpu_hashrate" => $gpu_hashrate, "workers" => $workers, - "historic shares" => $historic, - "current shares" => $shares, - "last nonce submited" => $update, - "total paid" => $total_paid, + "historic_shares" => $historic, + "current_shares" => $shares, + "last_nonce_submited" => $update, + "total_paid" => $total_paid, "pending" => $pending, "past_24h" => $past_24h, "last_payment" => $last_payment, From f04580e10ac4b463ef5d33cbb61699ba3972227e Mon Sep 17 00:00:00 2001 From: Ario Date: Sat, 16 Feb 2019 16:36:58 +0000 Subject: [PATCH 105/134] Change api.php - small fix --- api.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api.php b/api.php index 477d70d..12605ea 100644 --- a/api.php +++ b/api.php @@ -90,8 +90,8 @@ } echo json_encode(array( "miner" => $id, - "cpu_hashrate" => $cpu_hashrate, - "gpu_hashrate" => $gpu_hashrate, + "cpu_hr" => $cpu_hashrate, + "gpu_hr" => $gpu_hashrate, "workers" => $workers, "historic_shares" => $historic, "current_shares" => $shares, From 231d11c32d213049be002839682c88aad4c95b99 Mon Sep 17 00:00:00 2001 From: Ario Date: Sat, 16 Feb 2019 16:49:55 +0000 Subject: [PATCH 106/134] Change api.php to follow PSR-2 --- api.php | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/api.php b/api.php index 12605ea..5378074 100644 --- a/api.php +++ b/api.php @@ -89,18 +89,18 @@ $workers = 0; } echo json_encode(array( - "miner" => $id, - "cpu_hr" => $cpu_hashrate, - "gpu_hr" => $gpu_hashrate, - "workers" => $workers, - "historic_shares" => $historic, - "current_shares" => $shares, - "last_nonce_submited" => $update, - "total_paid" => $total_paid, - "pending" => $pending, - "past_24h" => $past_24h, - "last_payment" => $last_payment, - "last_payment_date" => $last_payment_time + "miner" => $id, + "cpu_hr" => $cpu_hashrate, + "gpu_hr" => $gpu_hashrate, + "workers" => $workers, + "historic_shares" => $historic, + "current_shares" => $shares, + "last_nonce_submited" => $update, + "total_paid" => $total_paid, + "pending" => $pending, + "past_24h" => $past_24h, + "last_payment" => $last_payment, + "last_payment_date" => $last_payment_time )); } else { // No result - we don't have record for this id in our miners table @@ -130,17 +130,17 @@ echo json_encode( array( - "cpu_hr" => $total_hr, - "gpu_hr" => $total_gpu, - "current_block_height" => $current, - "last_won_block" => $last_won, - "last_won_block_time" => $last_won_time, - "active miners" => $miners, - "fee" => $pool_config['fee'], - "historic_reward" => $pool_config['historic_reward'], - "current_reward" => $pool_config['current_reward'], - "miner_reward" => $pool_config['miner_reward'], - "min_payout" => $pool_config['min_payout'] + "cpu_hr" => $total_hr, + "gpu_hr" => $total_gpu, + "current_block_height" => $current, + "last_won_block" => $last_won, + "last_won_block_time" => $last_won_time, + "active miners" => $miners, + "fee" => $pool_config['fee'], + "historic_reward" => $pool_config['historic_reward'], + "current_reward" => $pool_config['current_reward'], + "miner_reward" => $pool_config['miner_reward'], + "min_payout" => $pool_config['min_payout'] )); } elseif ($q == "payments") { From 82f992ab3e81a9c0747b5a412009c33ce7219791 Mon Sep 17 00:00:00 2001 From: Ario Date: Sat, 16 Feb 2019 17:09:53 +0000 Subject: [PATCH 107/134] Change payments.php - keep orphaned block in our table --- payments.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/payments.php b/payments.php index e860c47..b7547fb 100644 --- a/payments.php +++ b/payments.php @@ -90,11 +90,13 @@ function pay_post($url, $data = []) if ($s === 0) { // dit kunnen we dus aanpassen naar orphaned. block wordt niet nog een keer meegenomen want verdwijnt uit payments - $db->run('DELETE FROM blocks WHERE id=:id', [':id' => $x['block']]); + + // let's keep our block so we can display it as orphaned + // $db->run('DELETE FROM blocks WHERE id=:id', [':id' => $x['block']]); // nu halen we de payments weg en wordt het block niet opnieuw geselecteerd bij de volgende payment cycle $db->run('DELETE FROM payments WHERE block=:id', [':id' => $x['block']]); - echo "Deleted block: $x[block]\n"; + echo "Deleted payments for block: $x[block]\n"; } } From e27283de7ecba2ec67345de52b57322602a57e23 Mon Sep 17 00:00:00 2001 From: Ario Date: Sun, 17 Feb 2019 19:12:12 +0000 Subject: [PATCH 108/134] keep orphans if it's defined in config --- config-sample.php | 3 +++ index.php | 22 +++++++++++++++++++++- payments.php | 7 ++++--- template/blocks.html | 10 ++++++++-- 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/config-sample.php b/config-sample.php index eabd6c3..b647852 100644 --- a/config-sample.php +++ b/config-sample.php @@ -105,6 +105,9 @@ $pool_config['payout_shedule'] = '1 hour'; +// Defines if we should keep orphans or delete it instead // bit greedy for render as it will ask node for block details later +$pool_config['keep_orphans'] = false; + /* |-------------------------------------------------------------------------- | Design Settings diff --git a/index.php b/index.php index 3ee8451..d9d13ad 100755 --- a/index.php +++ b/index.php @@ -174,14 +174,34 @@ $tpl->draw("account"); } elseif ($q == "blocks") { - $r = $db->run("SELECT * FROM blocks ORDER by height DESC LIMIT 1000"); + $limit = 1000; + + if ($pool_config['keep_orphans'] == true) $limit = 100; + + $r = $db->run("SELECT * FROM blocks ORDER by height DESC LIMIT $limit"); $b = []; foreach ($r as $x) { $x['reward'] = number_format($x['reward'], 2); + + if ($pool_config['keep_orphans'] == true) { + $f = file_get_contents($pool_config['node_url'].'/api.php?q=getBlock&height='.$x['height']); + $g = json_decode($f, true); + + if ($g['data']['generator']) { + $x['generator'] = $g['data']['generator']; + if ( $pool_config['address'] != $g['data']['generator'] ) { + $x['orphan'] = true; + } else $x['orphan'] = false; + } + } else $x['orphan'] = false; + + + $b[] = $x; } $tpl->assign("blocks", $b); + $tpl->assign("limit", $limit); $tpl->draw("blocks"); } elseif ($q == "payments") { $r = $db->run("SELECT id,address,val,done,height,txn FROM payments ORDER by id DESC LIMIT 5000"); diff --git a/payments.php b/payments.php index b7547fb..9655ecc 100644 --- a/payments.php +++ b/payments.php @@ -91,9 +91,10 @@ function pay_post($url, $data = []) // dit kunnen we dus aanpassen naar orphaned. block wordt niet nog een keer meegenomen want verdwijnt uit payments - // let's keep our block so we can display it as orphaned - // $db->run('DELETE FROM blocks WHERE id=:id', [':id' => $x['block']]); - + // if defined, keep our block so we can display it as orphaned + if ($pool_config['keep_orphans'] !== true) { + $db->run('DELETE FROM blocks WHERE id=:id', [':id' => $x['block']]); + } // nu halen we de payments weg en wordt het block niet opnieuw geselecteerd bij de volgende payment cycle $db->run('DELETE FROM payments WHERE block=:id', [':id' => $x['block']]); echo "Deleted payments for block: $x[block]\n"; diff --git a/template/blocks.html b/template/blocks.html index 2cc256c..20fc900 100755 --- a/template/blocks.html +++ b/template/blocks.html @@ -4,7 +4,7 @@
    - Last 1000 won blocks + Last {$limit} won blocks
    @@ -30,7 +30,13 @@ {loop="$blocks"} {$value.reward} - {$value.height} + + {if="$value.orphan == false"} + {$value.height} + {else} +

    {$value.height}

    + {/if} +
    {$value.miner}
    {/loop} From 1dd1482ccaaeb07620c7c2d8816581874aa8b97f Mon Sep 17 00:00:00 2001 From: Ario Date: Tue, 19 Feb 2019 20:49:36 +0000 Subject: [PATCH 109/134] Change payments.html - show link for transaction only if exists --- template/blocks.html | 2 +- template/payments.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/template/blocks.html b/template/blocks.html index 20fc900..a5eb170 100755 --- a/template/blocks.html +++ b/template/blocks.html @@ -4,7 +4,7 @@
    - Last {$limit} won blocks + Last {$limit} found blocks
    diff --git a/template/payments.html b/template/payments.html index dbbdd29..27b8a12 100755 --- a/template/payments.html +++ b/template/payments.html @@ -39,7 +39,7 @@ {$value.height}
    {$value.val}
    {$value.address} - Link + {if="$value.txn"}Link{else}Pending{/if} {/loop} From b47c2e4d54566c20c40a0b235a540dd0fd9ce21d Mon Sep 17 00:00:00 2001 From: F0nzy Date: Tue, 14 May 2019 06:52:11 +0000 Subject: [PATCH 110/134] modified: README.md modified: index.php modified: manualpayment-sendall.php modified: mine.php modified: payments.php modified: poolsanity.php modified: template/header.html modified: template/index.html modified: update.php images/ pool.css template/links.html utils/ --- README.md | 18 ++++++++++- index.php | 7 +++- manualpayment-sendall.php | 0 mine.php | 3 +- payments.php | 0 poolsanity.php | 33 ++++++++++++++++--- template/header.html | 67 +++++++++++++++++++++++++++++++++++---- template/index.html | 45 ++++++++++++++------------ update.php | 6 ++-- 9 files changed, 142 insertions(+), 37 deletions(-) mode change 100644 => 100755 manualpayment-sendall.php mode change 100644 => 100755 payments.php mode change 100644 => 100755 poolsanity.php mode change 100644 => 100755 update.php diff --git a/README.md b/README.md index 36c016b..b52039c 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,26 @@ # Modifications -This repository is based on ario's fork of the official arionum pool code. +This repository is based on angelexevior's fork. System requirements are indentical to the official pool code. Warning: because of additions to the config file, do not simply replace the php-files without making sure all variables are added to the config. +## Mining +- Share count based on network min DL, 1.000.000, so pool Min DL don't affect share count +- Multiple pool can work together, (eg. different min DL for Cpu, GPU or other mining settings, but same reward policy) + +## Display +- Expanded informations on main page (need to run /utils/getinfo.sh) + -> passed blocks from last found + -> luck % (based on passed blocks and actual hashrate, need to finetune) + -> Arionum actual price (from arionum.info) + -> network hashrates (from arionum.info) +- Added some icons, and header +- Added links page (webpages, miners, wallets, pools...) +- Added Cuby's web wallet link + +### angelexevior's changes ### + ## Bigger changes: - Change: Hashreporting has been removed from payments/poolsanity to a seperate updater. Updating hashrates on the website can be done independently of payment-cycle, and db is no longer only updated when moving to next block. Be aware that the 10minute update interval from the clients is fixed. As is the 'first appearance' in the db after submitting first nonce - Added: Api.php has been expanded and restructured with more options diff --git a/index.php b/index.php index d9d13ad..5cc0a0f 100755 --- a/index.php +++ b/index.php @@ -103,7 +103,7 @@ $tpl->assign("total_historic", $total_historic); $tpl->assign("height", $current['height']); $tpl->assign("lastwon", $last_won); - $tpl->assign("total_paid", number_format($db->single("SELECT val FROM info WHERE id='total_paid'") / 1000000, 3)); + $tpl->assign("total_paid", number_format($db->single("SELECT val FROM info WHERE id='total_paid'") / 1000, 3)); $tpl->assign("shares", $shares); $tpl->assign("historic", $historic); $tpl->assign("difficulty", 200000000 - $current['difficulty']); @@ -236,8 +236,13 @@ $tpl->draw("info"); +} elseif ($q == "benchmarks") { + $tpl->draw("benchmarks"); +} elseif ($q == "links") { + $tpl->draw("links"); } $tpl = new Tpl(); $tpl->assign("q", $q); $tpl->draw("footer"); + diff --git a/manualpayment-sendall.php b/manualpayment-sendall.php old mode 100644 new mode 100755 diff --git a/mine.php b/mine.php index e3f10c1..7ac2daf 100644 --- a/mine.php +++ b/mine.php @@ -24,6 +24,7 @@ function curl_post($url, $post) $q = san($_GET['q']); $max_dl = $pool_config['max_deadline']; +$max_dl_network = $pool_config['max_deadline_network']; if ($q === 'info') { @@ -231,7 +232,7 @@ function curl_post($url, $post) } api_err('rejected - block changed - 1'); } elseif ($result > 0 && $result <= $max_dl) { - $share = ceil(($max_dl - $result) / 100); + $share = ceil(($max_dl_network - $result) / 1000); $db->run( 'INSERT INTO miners diff --git a/payments.php b/payments.php old mode 100644 new mode 100755 diff --git a/poolsanity.php b/poolsanity.php old mode 100644 new mode 100755 index b6b0b26..25274bc --- a/poolsanity.php +++ b/poolsanity.php @@ -28,6 +28,9 @@ function shut_down() register_shutdown_function('shut_down'); ############################################### +date_default_timezone_set('Europe/Budapest'); +//$datetime_akt = date('Y.m.d H:i:s', time()); + require_once __DIR__.'/db.php'; set_time_limit(0); @@ -41,11 +44,30 @@ function shut_down() $ticks = 0; while (1) { $ticks++; - $ck = $aro->single('SELECT height FROM blocks ORDER by height DESC LIMIT 1'); - if ($ck !== $current && $ck) { + //$ck = $aro->single('SELECT height FROM blocks ORDER by height DESC LIMIT 1'); + $ck = $aro->single('SELECT MAX(height) FROM blocks'); + //if ($ck !== $current && $ck) { + if ($ck !== $current) { $current = $ck; $db->run('UPDATE miners SET historic=historic+shares-historic*:dr, shares=0,bestdl=1000000', [':dr' => $pool_config['pool_degradation']]); $db->run('TRUNCATE table nonces'); + + $r=$db->run("SELECT * FROM miners WHERE historic>0"); + $total_hr=0; + $total_gpu=0; + foreach($r as $x){ + $thr=$db->row("SELECT SUM(hashrate) as cpu, SUM(gpuhr) as gpu FROM workers WHERE miner=:m AND updated>UNIX_TIMESTAMP()-3600",array(":m"=>$x['id'])); + if($x['historic']/$thr['cpu']<2||$x['historic']/$thr['gpu']<2) { + $thr['cpu']=0; + $thr['gpu']=0; + echo "$x[id] [$x[historic]] -> ".$x['historic']/$thr[cpu]."\n"; + } + $total_hr+=$thr['cpu']; + $total_gpu+=$thr['gpu']; + } + echo "Total hr: $total_hr\n"; + $db->run("UPDATE info SET val=:thr WHERE id='total_hash_rate'",array(":thr"=>$total_hr)); + $db->run("UPDATE info SET val=:thr WHERE id='total_gpu_hr'",array(":thr"=>$total_gpu)); } $max_dl = ($current % 2) ? $pool_config['max_deadline_gpu'] : $pool_config['max_deadline']; @@ -66,9 +88,12 @@ function shut_down() 'argon_threads' => $g['data']['argon_threads'], 'argon_time' => $g['data']['argon_time'], ]; - $fin = json_encode(['status' => 'ok', 'data' => $res, 'coin' => 'arionum']); + + $datetime_akt = date('Y.m.d H:i:s', time()); + $fin = json_encode(['status' => 'ok', 'data' => $res, 'coin' => 'arionum', 'lastupdate' => $datetime_akt]); + echo "\n$fin\n"; file_put_contents($cache_file, $fin); - sleep(5); + sleep(2); } diff --git a/template/header.html b/template/header.html index 985b1c2..0869e8d 100755 --- a/template/header.html +++ b/template/header.html @@ -2,13 +2,21 @@ + + {$pool_name} - - + + + + @@ -24,9 +32,12 @@ - + + + + @@ -39,8 +50,12 @@ @@ -50,7 +65,7 @@
    -
    +
    Pool: {$pool_name}
    diff --git a/template/index.html b/template/index.html index 821a316..7680941 100755 --- a/template/index.html +++ b/template/index.html @@ -4,17 +4,17 @@
    -
    - +
    +
    -
    +

    {$height}

    {if="$height % 2 == 0"}CPU / CBlock{else}GPU / GBlock{/if}
    -
    - Last won block - {$lastwon} +
    + Last won block: {$lastwon} + Passed: block
    @@ -27,16 +27,16 @@
    {if="$height % 2 == 0"}CPU / CBlock{else}GPU / GBlock{/if}
    - +

    {$miners}

    Active Miners
    -
    - Difficulty - {$difficulty} +
    + Difficulty: {$difficulty} + Luck: ~%
    @@ -47,17 +47,18 @@
    Active Miners
    -
    +
    +
    -
    -

    {$total_paid}M

    +
    +

    {$total_paid}T

    ARO
    -
    - Total paid - +
    + Total paid (Thousand) + Price: USD
    @@ -68,17 +69,21 @@
    ARO
    -
    +
    + +
    +

    {$total_hr}

    {$hr_ext}
    -
    +

    {$total_gpu}

    {$gpu_ext}
    -
    - CPU & GPU blocks +
    + CPU & GPU hashrate + kH/s
    diff --git a/update.php b/update.php old mode 100644 new mode 100755 index afb9f6f..60f8add --- a/update.php +++ b/update.php @@ -47,13 +47,13 @@ function shut_down() SET gpuhr = ( SELECT SUM(gpuhr) FROM workers - WHERE miner = miners.id AND updated > UNIX_TIMESTAMP() - 750 + WHERE miner = miners.id AND updated > UNIX_TIMESTAMP() - 1800 )'); $db->run('UPDATE miners SET hashrate = ( SELECT SUM(hashrate) FROM workers - WHERE miner = miners.id AND updated > UNIX_TIMESTAMP() - 750 + WHERE miner = miners.id AND updated > UNIX_TIMESTAMP() - 1800 )'); //uit sanity @@ -64,7 +64,7 @@ function shut_down() $thr = $db->row( 'SELECT SUM(hashrate) AS cpu, SUM(gpuhr) AS gpu FROM workers - WHERE miner = :m AND updated > UNIX_TIMESTAMP() - 750', + WHERE miner = :m AND updated > UNIX_TIMESTAMP() - 1800', [':m' => $x['id']] ); if ($x['historic'] / $thr['cpu'] < 2 || $x['historic'] / $thr['gpu'] < 2) { From 4a8fa92521ec0f0ca82a0d41dbb7903bdc1cc941 Mon Sep 17 00:00:00 2001 From: F0nzy Date: Tue, 14 May 2019 06:56:53 +0000 Subject: [PATCH 111/134] new file: images/arionum.png new file: images/cpu_icon.png new file: images/gpu_icon.png new file: images/gpu_icon.svg new file: images/link_icon.svg new file: images/node_icon.svg new file: images/rig_icon.png new file: images/solo_icon.svg new file: pool.css new file: template/links.html new file: utils/getprice.sh new file: utils/price.js --- images/arionum.png | Bin 0 -> 27099 bytes images/cpu_icon.png | Bin 0 -> 20294 bytes images/gpu_icon.png | Bin 0 -> 12674 bytes images/gpu_icon.svg | 1 + images/link_icon.svg | 59 ++++++++++++++++++++ images/node_icon.svg | 46 ++++++++++++++++ images/rig_icon.png | Bin 0 -> 23016 bytes images/solo_icon.svg | 58 ++++++++++++++++++++ pool.css | 13 +++++ template/links.html | 126 +++++++++++++++++++++++++++++++++++++++++++ utils/getprice.sh | 36 +++++++++++++ utils/price.js | 3 ++ 12 files changed, 342 insertions(+) create mode 100644 images/arionum.png create mode 100644 images/cpu_icon.png create mode 100644 images/gpu_icon.png create mode 100644 images/gpu_icon.svg create mode 100644 images/link_icon.svg create mode 100644 images/node_icon.svg create mode 100644 images/rig_icon.png create mode 100644 images/solo_icon.svg create mode 100644 pool.css create mode 100755 template/links.html create mode 100755 utils/getprice.sh create mode 100644 utils/price.js diff --git a/images/arionum.png b/images/arionum.png new file mode 100644 index 0000000000000000000000000000000000000000..dcfb197a70e13fde8c8b4637d92a51b32d437381 GIT binary patch literal 27099 zcmd421yo$$l0F&*LV~*l3l^Y(hNhcFg9Ue&K%i+H8kb-R1h){}g9mqacL>1=?(Qz( zb@G#Y=f0W$o%MgS-WpaPIA@>QRbN$oyLN3@1SrUfW1y3w-@A7YLsCLi3Hj3wd0C;M z+`D%l_Kchh`S8SALK8WNYya!IKW9YgeD5CiQ&SZUdkt9`9vH%sRo@U{0B3c!v_?wb zyT>Q!Y^@J7huc#bz>Q6<_-Xd*nrNs@4f$!*xn$X8twrD_rV{UL;mYsiRABGSVNgRF zK>;d0XC9;iOSrv0m9wRVl^u^WKh1BwJjnZB!)!EEzeViL`DuiH8KlyXRiF|<*utr} zSit}o5X3`)F63l#@D5W>a|VFPjk*nvFkU>;5=)t_H9NNcu+Mm$QQum7}# zeB!4uvA4J8VPkW0a$uKm8wUpfDFLu^v9i~923Xm>_)CK*+zw`I zYHe?du%h~6#8!wv}*_%}{#6NEj&&IDoo_mux&?C;mV{rd|YGPnP^_+NqeOVHlb=)dsd z*PH*K6YgyKUx@yC^S3B62Rxz(n8PnmBt`#Xl_3IVYRL09SRNxV6lMT{u>(L*h!Mch z00aaWa6&nd``WO_7>_M%>&+K)3+_YNQVW zz~CS*05_Zy2rz^}*pb|1ha<1Q=F8ifA{U0f#XqA03vocjxIvu3g~N^X8o&-#0fKpe zKprk`W_Au9_CL_`APtxrx%`VLM1_N$hm)I!3;G{Kk*n5F-(LT}CHxx#!d3-=u=s0z zEBr+?DiIMXMs-swLxhvvOB$+QMBtJ96#{irLwgf`8X)^GbpIHZfm<2>%lL0y$TDJU z3X`<5hud1)BEkJyw@8QooQli}k|BQ%A_MbVpR&HCwFTTx0dA{c>I_FhLx%SE3yoi^ z(8A#l6+jLo0(N$`UqJpsqWSLx{_$Sb$`qMYB#vLa?rz)bY5jN!;#hK+{p zzj6hJuyTak+W*5HYkgaNBrA~7=BF{TMOae(v9ipp;l@<chFf5C}H}{=Xye|JD^l zZX*sb2+R)P;N(IUCJ+dMEWaF302so-&dq5Ag+Vxs{tH(iDnMlA;pE}s_+P~#Bx`@=ZN+H)!x5N5e#Aggc%@rI0zRE4B+Ml=_A?3!42Tz z1haE;a2gnbK(PNEDf+jra6*l^IJl9!JC^}B7+?SdaRc=AjgV{uu^Vx5LxF}+&i^yp zK>vH#_HPLGKVHWEXYBpk6dAz{!JGyVLjb!0rvU(28$bYkZVn>=7qS`R(gz#DjX?VU zN4EX{mZE>_%73pl{9_mUm;Leo-B|rk?T>7~&MSZH`fUH&5d85h`p3@p`q#E-XOBEB z@cd_+|9^KW{hE*Lx&KWU4rDiAhe8aHY1Ze41EB24tQ&B%g8^`M5OR@nfk1E&vQ7E} z4dVZ%i~hBb|6P3lJ{AZeoB3beklmk+gRs8w-z|i|AE(fNJue_p8FGTSklQYh8wh|y zK?VSQC=>$FhjHoy4S^hB4lZ`S-$Ax8Me6!}_lH`x|Fiwy-KDUp{jZ+$kM8qNDF57| z32^_D?q8Wi8u>Rv|D5pu)W&ate>&0rg&KKG{&oBJ`5gK1_X!_vg>1NNk>_`Xmd}g# z?rAzoiVCSXC(brF)$4ZH+}$PfuWkLl$?yGN>ywiMyku zNp6RB&nB!cWU~XL{P^=HY_!vNK~@NPLAaBrC!f0T1O1PHofSyY1p1!c;1qwIouiZE z8YkybKnr!K*h6!XJ>KGwJo$a-n!`OOlc5r}n{y3|l3h{oi=nFn>%%y~wKw-M*4LQy zuBx^xr<&Z|CxFb>WYb#7hs#cmVN+$ixVBj-@ZC?>s6Qyk+9!<#_AzDglQlCL)z+n+ zA!hsPVgNCSe75PP`ix@|`8pyldH%5>2Fy~>SZiQQ+KqAQSRwh490Te(c$%t%pR7}G zY-ING@CBuse9`WiB>Y^XOLr9hbG_sw(Kmp-lmT_bVguk|p{X4HqE8Wv^3&AW=e5Lo z_hAocX3mk?>exjDB!$+pR!OaSGeqxF7l%n}CIr$mCDM@H&`Tca`YzLR zFej+mZWh+RDbZI`@o=e5O6gc9?(}oMj^5yxtUM;JKFl)rHDrA;MVf zC=BwvoNZriC=pFQMU2pzu19rN^$OLlJ=kV3cj}qEpZF}pU480Y4~EDmDuY{%53?Ne zV0k%qgvGgM!ql?%1MMe7r&Lykvm*Y z5i|))gzlyKIT9@2O{rPWxd}F4dluJdt>$zyHKrHPL}#lcfVY}z)8(ssx0R%!ZJj(S+{GjsfyX&*t{cb@|QHLPN*uaDG3@J2lwJV{2GEc`z-qh8d+XB9e%+q{|;*vyQd>V zGK_eH;OBLGnF~uCO5Z%7hiB&JW!0B8mvolHuI?x|$B^J~8AE6~ox#E@!SGY|+$blH zwZ6m(6T+IT%HA8Fg8GfNbDI68^I>BT|0dtY+Vmc!r&PIzhaE|21s=LX54&pwXI*9> zf+}*FX`iaV>#NrdFUC<+f8O-gw?A3Gl3zgvzN_*Kc{2&=^R%4&D&$-^aous?3udxbf#lQPfJ6oJk8CO*(GLr2P2Ny5^3o39? zuAZ(`4u7LHJ^_b!lQAk}OwQ~%pt3yp>THA(h z@H|H~FVSgJOk=^kNyj_@=Kp9ICzqT`NG4w-ny9Z`s9n3zBw7nlcx>-Bd&>9jPL?Hc zRd}eX%FOINmQd^BIoG@NmVH>#vTKtM9t*TCWBY;)sIk5A!3- z=_@8BnWxQ$!T7@^C%jT-OWhNN&s#CM7N3FBtqBTC1BN_Jy9GR!o9S}RF8!06XYC*I zqdJ22r;CFG_oZwlb3e>1G;(2`c2p9MO(%Xt)nFP^k{0*A8&ocPF8X6Ud>?lWta`bk zJxDtrM++UwTwKb0y7neg@)iUIUi;MuYq@)hXMOwn!|SoF!ZcyUET^&UN$3Zoj?Aa5 z?#AMkc4;+J%ddJ4x(~W7+u}N~oLulY@=W(Oj6JVnxq9hFCb_JXdJyjW0Xf?oA((OY zTj91PUaCN~lljagrL8n&t#hl$jxmnoYjsvVO+`u#qoXE11(%sT3{R60ffBss5uvp2 z{qAIxBVoHUA~m$2Oc4Qlt+t>pSMgjI$jvvr<*~z&A1`t`mO3Nasw*DIRT!*iEuI3L z5@$z2*RCmb>FhUaoJO~8h6E}*xauEE-g;r5?r=;3B^T7Ocs)6Ib5GfJa&P(k!>E~_ zqt=MHfm%KssA( ziQepG17O6*iR>!bQcMNL_4pG-EHv~6L1MT(n=<1t8@h|esqbVlX>+*P+#BaYm zN{;o94Q#6e&0n3^69Ru>w_SCSaCltgBs@WBK7agcs1y-Zv>@rWEFyz}zFMP#}C!YY`p&ZJ{K-tH|cWC(4pRr=18^?~+F1-`oMNu^bPIqK_)YJ-5! zDT1k4Z^VzRlp0PV8CRY#hgWt1*pQXV!2dE;jw($tyO@SP zp$Im}YUXz&1opD+lMhPO#%(*Q>`=aO{H*b%f?cLp)$L~S30d?*0c+b&e5U#w7cCIf z*Z~30brp4m0<*|a=T&G(SE8_4F%vn{1QvHwvjg?G+rf?nIHu2f7q3M20<&u7{KEYf z4|Qsp*{hSq*eKmeW1(+5hrjxT!D2_!C=JgT}(I)5E?+uzL8RS^M}w#GGo!KILS_ zV885QjZJD$%Fj%1F?F*yXT#HXRta~SCAxPoF!wSDl?ZZZ3OGaL18IdB>wH}n55yq* z;d&K5Tx#IxN9NrQrwfc1W_l(UJ^CUxl5Ei5YdW&B|TBosL&6C8#)X}6Gsl?26 zr2{Z{g7{{$6>Tnik>u^Iw07WrDHl;WJ-slQ_kH|8$)UH}W&6sKB2dhiUDR8PcP_!V zReQAG_Pi-l-=ncBi$=>v`&@;U3TLT~k)DmRK;{l)#|6uyzc$58^;~G%eTUb)Ra0C! zDB~0p^$&j-W+Z{-^oeY@*?|u=o6vUug?Hkv`sRV7i{3P(}(e4+W>glB$BWCaZagPrBW%gJ_fM z$-?wCK0hX8Cy4yQ883l&e#)$bK$LqEq*+~l+;(zW@7CBvHDxvH$g*U&r2V4p?)!?| zxwns<=)K{NNuVSl-?KDZ;aBf>H>;0aY8G{?IMlhKUmd%*2g3s_Gp}z(@1fsSo8FBV zW?2NqTQNCxqTUij$&5IqYfvPd85ihGl`q42;`lgONXD&pC>u92lzEb4&0ab(oUPlh z(+J!h=vv+O*SYjG&G&xRw2U-Y%zo>q)9c<8-#@T9Up{9P!Id-2SD;(RJ@P%NpL5Mn zv)FC*ZHfWQQD9u6Lnbz|?3VmBhfKH>Okx)#W zs=HBd|7jYVfWVYTGtqHU-Tv(1=aSr>V3#*?`rnma3X!+lp4CGwNQMTh#^(aZugz0y zUCz7jFKtS~=uvIFXgX|P!P18B4jaK_ol%1GN>h#R%AK&3f=W`;6!H|fP|Q?U5LhRa z=CT6R8Tf9SD424JTO5Q`88u%Zw>=#-s;k}gZ+9tzR>JmOmwa-FFOJ52%~n22mJ11o zaCvbM^o#b-Cr!}7Z|kvWn=Y^GokmWcDji}$@O}GmtF-fMXkrMtrg@dj;)9rIN;>7l zZ+4@~20YkS`gS2DJK(vsm!4DPp|yIJ(%- zU1bgiJFD5XR~BK?Eiv~W!C1V9kr-8C0DQ6lo>I}=iJKlgQH#DDY$MwDCD&mp*#`& zJTIF?<$J=g%T;mzjxL53!Skd;YrPU@uwpP5p>gj=&$F$y_NN`1F1u`D^M(i8jCr7W ziX=-hrb&%-sZ^J963vOpt7pOOwrX@D9ip$?t7=@kHW>EEiElDmya*Y`oX0d}16%+; z#)1!SeQEc99){v6DH0A4%}lAKp@YE+ob@)Lah^tV<${JiXYnP5Yy z--N4a*pH%FNqOn;9501IN4r5125K<-EzR@~Ie?^-ZE%n2;@d<+NAu)>52l6nrKl6f7wg+tGO0_x3SD0a2BMTMmpF-x zICI+fo6?^rcby&L%*e#M88#g`Q(wxZlbiz;g7>fhsQ?3u66>G|d=`^NWw71~wIRAW}%EVrR>=zgbW5*OA+m=b57n zv&b0Ye2gwj@a~(lAJcRaSG=j)-1yL=XeP8=;mzby!9{BRtQQ6Q17i2$CToV*!eJ%L zzCiT5=bj-UyQIAKWJLFjL!UREaG#9a}gkF87G2Xs>%PX-wf~2T>t| z99jg-G;+KNO|n6XB&6eu*+Rm554zxL7vfFkpW7+<{Xt~>O`#rcw{v=~Z3YeJdj`va@k#V`Ge-GuS|XVG+P)^`y-qgyft6@(dM1 zMOxkwf>E?3RloN6X_`6zgz<>4P33$=h;43!%fMm%^?B_zFCEo46f*7d50fTmQTgtx zBrg#{(rq?F+Ac#6uTxG96rV!QqyV-vqWI$64=VEq#Dao)Zd7QdJ&GlWHA~+N2u^{O zT;521;fA(cs|_3nR|4OQZD_`}5C@@U@O6kc+BHi>bo!!9JSvAl+;_%)GFehZoL_j} z6{oBo^XH1x)hq-?9bF>M;yNuJ6mS{bdya$uLf378dHqp|K%rfho5gh_O!uqWjcUq| zCBZUppby2+OHJcu|1{l%c}@X54A?=AE_ zI9i!kDK;)AN{aX98ViLYsdShr4wapJ>v7tKRm>%aGK-(ekJ?$i~YwZ3u8%@ zvT#F->NSG`A#>^ifN0=j4@&;H*swy`A1Z{nHX-E%7A4iYnPt02B1LbbgtPgI3B^IE zfd%`ubxuoU{#05pX6pgdL1+mk#U5GTLbjX1(>QF9z<@{s3FTM{zs4w~O-1K$;3R2j z=#=y7KCzj~N64EZ*=c~Q0PR~z8 zyp3m5cFY3~o*6tF->Uu2fZ0OY{+^49zCE5exC2PqrNswhCv+?5iH!{g;!8VT)nkr1 zR}10XxV^ZnJZrOzrgyEebYF}H4%Le;-6Q)DOH4o(44l;P2ESzy#bE+#m`ijJGL){^ ziweA#60&LOU0Ry5({?gf(+*myZP+`71x2HdQt0P4DtbX@`3|}- zyxxc@`E9x7YJ?g_KW3InFDM~EO>}E^m;c;g%`wGS1h9+5-bXpNG@kvyR5K2m5{@Fv zHX0e@?tl_8z(grfU8_COxj~yh?3?4ahzAOdc1_}+t}~f6V@XN!HIqsYyxSqhJ*o`L zb=$p>T^N*3WuVV&GlFYbQdhgh81UO6`uQI0}kg!1p=6mPwGPhwpN@ zVZP7lb(hP2l<`3vDvIU|HYc%z@zsm$otJH>MPB3mEPPR-+7~yLVT=APWzkf1iN1zW z6D(Xewr%%M#9|J-c@c~5U~kxCxG{@MGDr5z$UM1BM(NYqU8-4nBaVrqbF!=DoU$x0 zJsGBkv^6ucWN1+vsL_qvw(0p-U)gg$p4PB&3dW+?2=kppPuzl_q1M9@eDk%#pHd@L zM2<$18&8Z}bJm15$pg65J8VQNOGp685PW)iar)b&hiY;FMIO(xeAZLBX!ZK#V8TjE zogoOqxzueJ&+Jy#yzAoUn_Cc^6iYT&b1ZCr@y;=(c|Uo*kUOcOn=bn{?Oi?F|cCQI0F! zu3X~Dky6cU{CTLJRDYuk$v4&mcIKF4F9qU`i{tG~Pa5AX?XUv1ju%#lHKZ8>0w4p- zw#EiW3P0x4x>P1~Vte<d04 zls1`ly^*F-Qhy!&W79;#()>^;Fg$Cj-+-y`ZGJ`Jptc`z$D@)b8QA1s@Kq%Od>KX5 zMSRVs76$V(_kv>HSwaL80qbP-$(aMI;Y*Qpfm{*FFD{bSb+q$>^)`4!dtWo=9VjO= zmJpLaFgG5*FH1k+UGe5-m}G71&S|-FSoIjsvcwZNxtS=L98R&^^TAs2G%>UkKN}SO zIGubrw^62=+)IxbU)Y;=!(MAD-<(;`VNi0& z@%#>ymNf2iDG~Skt{w-u>yk{qMe`aP_O@=?Sy-XTvojYTbd+;vK3~n6Zrq>Yz8SzQ z=@MBMbC7CspvX3{&J4Qc4MMo=L*L;n?LyB4Zd$(``@$%lI-1q1KqlK7J|z-{&7IvE z?c(a$9h3b}zwecFpLTc(F|m$~(s4I>VHf+4I*8>eRwJk`*2nD1DBTN{I|I_zA3t&v zIGJTIgMFZ^h(%*x5XG6+_;x?I^~a#4nK|O1tAGDXN?}iioO5Pl+f1&yc?;tsZwAFr zgsMrUSvVg>gBE?e#KG=sTP}9!KI_>(FJ!yjZO;#$6nuLiFK6uOlSc*C_$W4B(*er$ zOd&0pLB%E(c^l_G!hfw-e-L=~Bi}=RYSVFOpD&dli@#%9cA5WPXvi>5Vq@;{Sj*%i zBc2i~C-MTY)-q!ZnPb@el^?TlfXj#VEV8g9?y@hB_gF_MRG55#s_oA9u8V7(CBT^z zP>@^+@;8#KC5FcA$Ga}$2;z%DxbezdVRFiL?=j7Jxn`GNA3sHJUG(*~fP%q~%7lZ!ao|cmo9GFE|`qbyrO7X9oGYM97$)dX#cm zxhFm0qKG$CdG5L{nT0`x&Y!!AAD7WpwKoUBUv&`2*Gimx_3~@|v271|U(u=Pwn-4o1$;WPH8nZY%5o-Vtx+YHVflkBRKv}sZ+{$ z8HIPmA^!q`Q<3~B@X9Ys;QcyI`+W_cyo?)-8u)H1U8WdZV`VT=H}F~VsA8j)YfEGA z1OL7OZDu{0ttIue`CgE{1&{vtws;;!)qY+MGwt}~KoX!?u`4Pi%+Sx*q{)%;gDMA0 zn%JNsmD=EL9uS7fdtp36p;veIWX@jkp~rU-(F5{6aSxo`LWy#P1ho9lluDnXM!E@h zO{h(F`m*gqZVEG7i!E{QN*Y{PMax8>d2JA4zo&Y>;{90k_Wq1)HWP>ECAyi`2ee(y zj`h7+a~py*A(>{=f}Xo-TX(#ou)d zJ~>^I0lV1ujVmz`x~!-tXo8BO&YNt{NSL0Lbar*dD=rtlvzQniO9d$cFXwY_95wKt zHtvVZ*5U`)N=IGsf(eKOA z+7wx3)D?95+}rI1W56ZJ6x2!#y=@oM*2&v~Uc|!nnN0j}$iS}MOhtulT3zO3nEgOk zC(2V=w5jRw{9*TyAdd!2*Uv5&ySR8ddwtQWekjpmf+?9plX+K=rC*ZJLm=g8sb=UwG$k3G+=`TXY8hRcxTQ;n7< zGv)4v_BRAl9gOMNnb^x;WTGM^1ss*k4@$@4v?{gwttSl#+q+9EQ_B7D@^muCqhv9p zA22&y)O#y%4rVeC(9f0!0LO*O-`ZIjT>qS|3+kZhFxYg7S@!BAXS~?SL#w+wFS8Xo z{;bEhxhs)P&XnsP*o=o}hM6?CQn70(U1&-zv8Mb)graf`{!6L1DXLkA_AK4 z8UsJBkM-Q5o)=D%oLJaIs2b3)e<_zw4`fg?rjNEv=13nH;I|JsO}$|{PM9{8bak_8 z3Z!xrDQNL!Cp}(-I7-6q&0mkZ8!8F6%FeRumKPn^*rfY^Gl{$pVLEiqB};p7Ok1+r zP^9%vD(B|rY;gIfP6TV2Q;!#bY57aZTLNN@4U9W$At|j+VcuGhb}LPLco3R%h%glA zu+)m5mxattTQ5f?V(6-?vk5jEd(5WQZV!AbXLXbt)u@{adn}ivnjDfN>B|{}x?Kob z?TLU`F&3F@l4jJvHmdtRl&BKOn%_bx$gWw)(wk zao>`QrA9Icx?;YyiCk^m-E49;V7igXf9Ma8G5z_oBZQeeydX}+>l)F3M{m31U#d&b ziU6b%xqQHmkJTU}6&~nR!R2)O6xO&a0~}h8P0LktuEc%H$CtD&?Ybn%mLz80qIJI@ z7EcsmCX;|5Wea;kZ{6`pAzmy0iMM|S1uA?)9qSdS&9g}_4B~j<)GS|@ZUWI!KdM6V(LJ_C6EK1|; zti;mK&two^IgESaUG*8RTenf~DaX@rC2fhHK5SVz)thsTx70j(_nE(ldg@rqmU*2M z;Sud}TxM8z?6$nDt+hGXyrFa+2(zr&3diT|O*0)b6Vki{JD}h1oov)c@ zEN+hZP7fuQMRc_;(&@BKj6-&}l!s~TgG*83LU$A7 zq^{nOFc3a{_!1TPNvhUu_v$$~TyB9hq(s2R<#SB(hyyWSlr8?Tb_0n#x4y|&o_*~m z(z&oAs!$t)z8sIk2sSPKyE&}`@`2}Mq%IvtHl2Rb_?>0>^NMfu?7TSn3$XE)P4wNE z3L7q3$5n{=QBn50*+B|1CiF}F=7^1`l%Q+HVUdG3^hT_0T;rS z&IXtAU^)J{!^h?zQ~aQa07T;W@MW?{NSdLruD`4xNo94)~yu9{F>POmFyfPh<|WYiDKT zgRhI;p?sLewjm3T0A2=plRd-&@tFvtcD?LT zb7bO~CJHDX*D%K!{uEq+DH<6?+_Y95 zUKr^swI;0Iv0^}NE<$Q}GXyw7+@lT*8e^B3eJK%eFtRzQ_dGbB6^A(D3<1 zoqM`kxw5!CO-3u}2V*LfJpPYp_Q4f|1g6hWh=Ry8`N*(;#Hv_yoB7DU5;5F+#40%2 zi9DE=JCswZaby$RbU8RZrjIy$0xKpJ4r*;74iN=15z6R@$jlPF2z+cWp^pDelk1Ua zuuKc{kka?zxaG|itHK?D8^6bDaHaVUztLD5&uChT1KjG|=4qyQWD;bJeb zbimsrl20kG#R4D84o-xXmyDx0E<06V4}GM}3s|bJDUjaV2J90F7Gh;!uvg9r-5 z<`D`9#>jVCWSm_VIPJn4W=iz*3h_V!4vK8Kl;pslU=Ve92quxb8_^I!tL>u)ss-Fl zHC4vBT8UKx7QF_cedCs4Hz`!?wsL-gi}?MV3Pf=h56|Z>@v?BAIzclEL-kXmg!ng_N#IS_N2FBHV&)zB+Z>^9cw1BH1ro1o8j!y zaajFF-OfZmP?En)$I_24RAUxGj$djqs=x5s0<9;X+ZHyg8r7>j{`#GT)wt+cO|^Sq zS)KHav-XRyQy0!6n6bU2_{q+?8n$P_wlQoPz0T!yCh z$lNliFZ6-?32qMNE#9K8273Qs3SRo!*94-WIkfe!yUqB+D<1&D{}#m zqzdPj50_74MoJH!<&R&W7g=z4t}0ce+Mt+EyO&&pe5d2oS+=rIOn{q*=LL!Z3!@o8rJfUv6o!ANeHPFAe=i*E6YLgo6Qzyk?`esqI@Z= z2f)FQf1RVhi9Dk8bRy;^Qb?wCgWtJT9nwXJO=VPuPEx`-d$6KJZo?T1uk{|s1EbJ! zx4XJLGTI9V7)C~qRKGj&)KI$|eRFw=i@S9}s0?xKdZi*=86kZUEEo zF<&w>QNGHUDUY(o_2lr(*UCc2faPrUm^n)=HO=!0oy#jc&$p7xC#aNL&#%8sOtwzk zU8vR{tx$xd=a)oFVcUutQa^ob%@|?fEOwl%nG3$fW3CX?iaWb3gCyTXkHnOFLKnB1 zG`}rc**mH7vR!x+gdqIAS*@5xF-i-IYK%5n__`8pX7Nz{M${s5`We3ch@cdxi?=`| z^-b@(`>DDY`V5TWoberY$ILq&?Ucpmuc~7Pn|^z(5m}WOSvoC4gY@HCR?)0Lj+pap=DI>q8pG`4p59&8P8Lkg&k;Gm0BInab;lC(58N0S=316Q zmP)nfJPW`z=n+$Aie?o#sv%DZYc^}`%Y=*V>RibRR^g~@i8SI*Pzkh=P^aC!H@vLs zg|2S~E*wjE--mJymd4<|R*m$}HI@BV?O)}2)O5I>oMuF4z}zchv@}0D^_4x%23yBw zSF~990|&7WLkWl;i3&rX>s6OpjnC4_1KVX$Fg>yP7ib;{N%C6xB_V2?74vv?pby@C zo)H7e`8v$}j-je?@yGsj9iKPA@9?CV^T;|IWN2h9SYS1@V_tAL4Ab1lx;~z*+$p4c z?zw;Ni$M%R0@dWBV;t)WdYdzr?~2hmIi~H5@f-Abpf94%yRL5gz2UKmd^8?4LE7U2^x1WR=Gk)BPPy`K0nrZsw*SP-}ZBrH({iK5K#IBtK_gTEiQLVQ2Sp+#Ymi+orJ9AmX#NG#9Y7ShLLB(cH3Br9NckdJe1o zXii`N(5f+6HL$@X60$DP*K@>4vK$sf1hQW30puf1Wt?ZAd=fK?y$lvPcaemttm~9D zkSC<6tO`7S&@J8Jfr$AT?yC<4J)tJLOpOF9F)uz`cRB5b9zDqc5j?P5`ew^sbMK8V zgOBOsaa?0#@b!b-4U#xaawA?})xky|vM%lYiEl8#ygj}h1gjIlXIFSfNWPyv(&j!Y zp@7aW9`d~SwYH8n(I`3HBQd}W#rC`%4<;p#oyOF55!EUOC6Z&dMh+s6+YhZl^9>xU z(QTiEsUq!J(vsdihGVB2iiYJfa)|cR(7qOcx)}&HG%@2omP6y6@HM`vM_lp3SM!^z zzld17{ylwybc{1eXhwjO&?X$I_q`=XR z!lL5vFLc5N3Y8R^T_zu-y5q`j_8ZE(T(sZfqpyE;IKGo#0UOH6%tXx-1iY`v@F*!; zp3YIwlSzA>4`9T2-Mm%X%?|69UwIBbnV93@p-4Wd?Ep-y)St|0-LzhUZv`ah?2Zf9 z8@D}iUXnWuy}xUi9i7V{4;r_6lgXVv9nnpN);W1ql2}~$n#GIkQTm*DcJy$0PmuRAZW5#V%M0r~Zj2BM;#~JK%ZcXiQEzI(cmSHqw4=%` z=0C9_n12SGxA6{VJo1%3>;i`zbIoEOVNRNaUTj4eGs%B;)c4TCc+Td$U zId?5m0^yH1sOAI`B-va`zJIcs3tz}t`rKFZt z=Wy8MZ~H2yZ*K)Ey+?1`h(C@=oQ;*W$W^&RaH~ecPebfPCy$* z3F-`cZm%+ycf4AZSk-)&{(^w_bq#GU-U|J>L1H!y3+Nq=;E(y6xNB6NJK=gXl>)05 zoTuE1R0_o`CeN${>^y!tlo?%*&AShI^4ex+>&1S;Z2~@_9hR=bCu>p^8BmoA9$%CJ z0fMsmTe*wvIOfjP%eg7z;{`~azle34ill!|KjB-&X4Uw7A>H(H?xZ>T!2EtdzEpIJ z)EjmVQU#rlR~*))FJ8T59*M2_&>SOD6BEu{s}kl)O~wy-JB7%d4kQZCJE28}A4$U*rS1 z)nE#f@$@7;C-A5JWbX3~T#K7`c<8S*&-N#78|N1pkJ18v%)75yMoeAC;NWAEc_#yh zOo;S|PN(MD%_!>*H6D^{ibNc77nB6)WG!x{R&QA{_9*}&E>aw{_efbolNjPe-FreX zzHGDde-IOEUuTtfJDcek7H1aX51qI(3JI@2t@Li%cj6AT?X^|svS|x_)$qWeeUxs3 zhZ6($>a28pt4q6KVMKPWM0reW^=&Vm5rb5JTvWQsSi7Rzq%|Ukvz#tsVH+#z=k;FF zVVxwMf>MFVn8ou*hLR3BvbBn@+iZfex)r%E1`zRe2TnqzYn~qb_`6QB6wx?`dSzV> zcf4w#z^pxNBg@-hiAPcI%i@z#n&8Rxy4wBWSpakDl;f#d#Aj`a9hgUD^Ndl7CIf(B z@ntI&cfX2wOLJt~oXs%<)(*v0OmoG{jKb|Gl8{doC|M8I*2dBiP1TF_8T+X6;?h46 z)R!@U2&AXZC|uPCK{%)KPCEgDf!R3l5*`$0=gv?5fJ|RD)2_827(s8P37 z-~LN`Rt2gJM{BE2fYu5Jmtsp_hDNm+*Dl7Bz)WF}%181vrbriU?0AdlFS{{C0e8dag9!ZaWs<~75g zU+XfD8dSc&h-KxdhsAm;3lDr`>5cj7i&>GIxprjNRTc7$Bt zzb9sEVAw>mgV^aO_9bTpEm!J4GJnK1fNgEKl=!1)7nIhDd9HS3JGoo0G&8zV&PhVY zgz561ck~C+#s+>I*GX1UBHr1~ewma-ooQ+%8*$=}{TZ_N^^Kr{ZJ`7$OnBEo_R%;^ zXNxFdRyK4ya=fU~Z7d%vSWX>l=wKdF^IA?p3A@A}mt1`@4O=k-m*RqONRgHgbroHT z{3e5X@kw$vT7|xwMSMx%CyUeS#cu8UdUP zTb6{QCUz_@W?Z1Wzwu_!weoI&?R=_9z2;sJ_*p*Bj0o8jq)2zoWO zJH_`eaktvN#I=Whjw~**ANS#L%YE+Zig?RKLul_mriLXS-CMFD)mxe_w302g!k`?H zIc$dEanaTVb%@4GvQs)2?B5FxTU^yl5tg7o~E|*$wmt5MwR(SxS&d5_Pr(j{9nv~se z_AeZLQ(o{zj9L!OCgi6~vVtaI6um@%I3tSr;}-&7yK!XZ#^eOP_Y5kg1ucEMW_wbg z`dGO)b2T|1ybPjF{J0yCkMc8RH1>*U!zX-$!Q z^6zS#uJtJaGEbFz$S3c~Zv`GtqHFlTgkOI)&6>qW{?ntRc)V9abJVAI{hw=}df@~m zwKxO@X>6~V>AQ^$2G;b_DxJisd@HTkpO3i+Ac!jLl(*bZy8056pNb_mHs+P_Y#idY zPV{1azHAKo{{(9ul;LaD{Kh{s2ueL?lIjyq#}$#`c*qgU-suFRm5>q%v@Wr4XbgPI z(vCL9ri!e{8?4InivzquqS61|>1RcF0RKp3r7w zO489}V}7{{ZfJzq#z<`Hj54OqSmm-Z?B9_epC0ZvndR28tq!VwJvJz%>+bv7B3eLH z{cLG8t_7nVv4S7HZCC9xrC!>9_*QP|v)h>uEnMIH)>?*+66kFE+T=OeC^)W2-Ix zXi=E@{*aljHTy0Vo98XpoXN;kwCpoC?|-PQXu<`F^b9ivA;tz(QaZ`yE7I@IOb&c= zVyr@33PnZovM7^!%g|JOW-XE)V2n;$C5xyS zC$6Gn!MYw44GqQ)Ua+`yWi}l=QK|jz?4vIzGxraTf*YTlO!a)@$uYfJWi=QdV?vY- zF=A1%!nY1u8KN-8H03hW*1e7a*TxtHy1&Yrh0YDDS7hEk+FO{?v7x1!Vqfnd`>O>O z=BslLmc2hN$Bl2Ug~_h0S3#K?61!+c-Pzu1jM4Rg;t1(Dq$oc75(#QpM8}AUF`*Bo zD(Ciezx0x`yKhY-)iZo-UkG|Z_DsQ&bnLQeY5LZfYG32jN;qj-2hvFutimEVV$fo- zL{KR{aY;wx`%+2w;fca1L1dYXJW^hQ#LOP|R0Be-su|rgiW2BncCsni{OXEM|MAYk zz<;=TfHas28jXnruiNM0f#|A7_7Cs-(3^T*vV4By!zD+MhkbTlznMxvufh3??uL=S zn4OCK4F@tGN_egBC`hm(5nFIH+9;GY7!e$5R2+piu&i9fA!5IiVBAfCXORYnhj#C| zCEHm0^QGP0pKorBjdEVtS$e`}W+eqh*a?koo{@lqNq2_h6k@r;{pfEb0XL4%~i z1r5Qc<6!Wg4wNKZ(%eQ@#jX!zm%~C8YTDj7=w!C;(4%S2o~ypLX1@R7S>2R9 z*J3OT9vouF+P!SrpJsJilF7;_LrxFP$tv^n@v6tiqOVL$xo34IJt7lhw8hvu2-_Ho zwt{N}Plrq^=uc(Q(`A~;_PyzXuJc@1^;KUW!ASmc{WHV-94{qZ!=|Ae`*dd2?$NQI z*Q}ba{JKxFjq4g35sPaf3N6iUW%{I~d~n~O{o(0d<1{zUW&5Z@$yQj=D(oAaU~5S@ zzrCH&;_w$b8VbEjXV3nE5kIz1=O}{2X)@t6L(3|__g#L~TmHv;_fG$<%4ZM@TF*$X zu|kO@E?4MEn0+69W$u#JM)yFeYOoek8K1Bianl#JQIjc#-1+3aDm{%6*7X@1i5dqc z%iqza;VM*_r01d|sS9+b9zPPb(7gohfcXI=?b-yusFpXr_67BOKUPUqU_UL=`AEg)0#3oefd(3 zf?AaggW*+o9CUtMGnJ$y1sge_V-9<68c-9ldFi6^%Pv`yxy|zw#?}L5iNMrwh5k{8 zM}9TI@~)UjB^WwTr7bhS+2<@!zj`wJjrE(x-_e>kxSl1B>isvy9F~F|twcJKb@`9wW1<%Cfu-P5mrJ{379NfNMzdQwXRqDYz=QQ*=f z+}@IkU)$DRF16LbiCrGp8l2Dn7tr}eum*#NT*yz2Syiv|DK_r_UX)NP6nt2=tGDC-)ST9DojHHbyUy;a5uKo*^71!N9{|o`lJ)`#G_KaY0z-W}Qb$zY{Z8f4j!s(D%ZPC52 zyJF$R;R(uxAb*O@s2ZeaC9S&lz&F19VhZ+#RBXujuU$*wH)s<|lijua@vLPSRi_g`pl8 z%8M0|Hl%D^c;{)si9b#IbiB>?+-GLId_K&4&%?hy zgEZ7*pZO|mxw|+2<>@L>Ng)Nvax6l z={#Y!5gi9dg?&<3a!JJ`pb6}X(KY#0sTy*=hV}LA>cUAZPB0tzttX-tif{A73imI#RLdZsX z_|I48&VQno7#lCuT0E_dnn{!^%pflgF;gS1!X_hY6Opx6LD5464kV1VnJ}VOZt$*H z$gW#^_kQY*o#ta{w+=~httMeDzEya(?mQ&6wkJ+ZoCWfXj#Q$ElN)oaY-yn|qqBYL zBZWc@h6<%WSlgHWY&Genl~l1t)de{fp|oH^OH!o^UC!9Q8C(9@l6lLfGMQ$#7!+0H zIwG;gk1W2C`nkqfuu6>4SXHAczG`T18p-r-Idk*Feb>8M<*f3Etwmyp)l5!dZ5b+z z(bL{?(ysKEjEeL24h2>nh6$PEG9Cm3#gfV*Sa3r0~>NU_MlNDofKZah7-C-1j>o=3?z)gB|@ws z9U5k->h~?Y_BD?B_^;5T0jOq}tZcY=!%r+t@iR-IN zB@3kq(1rRK#54ZB%=E)pFmWA`0AQSYUxOIjBsBWCR%i$f?NNYpDCmyXXlwD6%h*Uv zN25G;-l^Hwd7j#x&->3fc0DUIFT3s8^SO8;Ovb?lj~C4?Rpn(xs&$O87{GbzFu5o+$#;zh4KM36 ziCK}gf!NsCLte~A|F+DuM=;YKVy3kg-x!oJs=>Fa(I&RLrHLPRC-n_(Dl^pL9_=Lb zbTVO$)a*qhy5?ZQ2#1iM77*!~(3gjp*;iqBBxG^x6sKkbd7wCdUb3-#@j!3x(n4kI zv`N=?gn`i*WgMgHC#TTO9_#RCNwj2{#b=Za{falaB>}dlEgEj`&O)yX%;mKRR zO%#PBY{1^^`JB?3P z9tT0(6N~wo*_cpP5CeWvGg)vcPbOqm(np8ChMA^V!)PdtS4l*g1N&WWynice(iMg? zEj$)9u%<^?wk*NK)S>2n%NG`x&bZ3zV1l#$!2klB9%yxkcb=a+zbs#7Wlhq ziJLj)tSiWyEr_v)2UW0WM-eAnx*d<2=P)N*PFpNW!1EQ3@6=_Ms^y_A0bBP?v4|av)>5=~S=zf@ zCM8Q)2x)wB1I49Fs5Ug?VQ~fCp{o3BTR+owh-le)SSvI}A(vGLsEYx0K$mANk*L{5 zB5T!R~z=XzZphnZ=0ExoI6CiZ`5lI<2`h<;Y^S#Rk)~Klw{eZ(77d(>XS} z71Gm_j3#EIOo)Sh)fDb8N|l(Fy|uqulCOQHqU%Q=YYgXl9uFKSQgb`-nhgen)*5RC zrCt~$xhSaABHVJ3*Ic-a?`$3;)P^vI)4Lt}hBZyjuQsF>-T&}dwIS#A9=U!b1y;Ag zwzB4$%THoKdzM(&ZKdCQc$Ddykm*h$SUl=^KeeAnpS=WE6^OAY-y@L<5l@K90jIuV z5%HWg9Nhf~dTb1H2$S?QdImFRL>4?{loHyp(ufrhRdvM-Dr|U6Tb#_GU*(w#@uBF& zP*?jowF2{VqqHyU!6&|M{jRd40>i@23^u4E;B6d`?Kz#{X-iG7KfE_NVsX%-a9S-+ zGolb|*%31;*k?H3J{MWQ5rZ$5gbSW}s&|pGG$kGWd`$;~<%sWW8mBxy!IO{d*KJvU zN8_o@Ji4>YoWwZs5kpz3g}m|N(^%MQD9+k{{CE+$ftU?QGSXMyYtV znwpy*4HNUK!9;iLm7l0+``UynJL|#Zg(!-Mq8Jech!Shwqm=_LWdEW_T z?V%+iHilWvIWh^KrzPm}fpdZVGv&}`qXfIiQ{*bu+ER=A@9XwVx8J|h(3EJVu{Qp7 zt<;~kWc|v4K&?T!Kl;(O!o2v21ld#)KQ8_-1D_CKm+LzgN2I&IlKJJd$#=AnzdBXj z`Sula3_6)+^k4-?L329Kf{bCubcKE6wxOmRn%LCJYkqZWCYfQ3j+{N{LW_9H8#`~PQ za=nw9SoQL@)>p=H^@a;Bzk+lo&4#u2)0j<|jFhf=wpw zqJEsVWeimt$hIcV>+Sb8eCoFC`&TV?PYbk=v6`#TT|q2D*0nq`k@)21k!ok7E9Y8E z1oh?lrK?V&t2s|KJnBr_4Ez}Qs)bJ|tj$P-65|%4>IX)M|7_9Ho-Z_r+tL4IKZ|BH zqN^q5&p!R-n|9O=?)~Wx8m_$N>~E~;=~?#Vp21qFSR*3OBCqkZM@Pc7UW44~ZrYzd zbK|gmaK-ZUe|H<_595SFRWnQn5&7g(%c+PZh%E`5Am?TFwr8i8BwX)pd&bJ&$!PsV zKH&zT2IW-20mson%8oTXG}8Tzm#xYF(^oH8;_V$P@ZWcBB^1N73*I4-apqrZAtk~f z4x>6EUzu2O+vAhJTGpEV*|H|Nux#RhluIc(`dlg0mHAUuhi)(GzvjHrGkSx0uf5@( zf$RH{BcD2}XYSvP9UQ_*`WS1aR0-P`Eo{GWb#wKNg8}85qiA5Lu51@gLK~c#Jh(Jh zU4BsKHaxUr`hjfq;Q4bJ61?WplUUf(LsL?y-q~k2ZhgYi#o=&mhtHeOzL&>`E(LLf zvf3%BO!vah)~#1&^`8b&jU{JvbI%0qo~$shR=z1cJAbX~%zvk=Dqm{PCu-ZNkW1ZvcksKn_0D};-yZ+`N>E8^D@^(>Hsw+gNt8`4Ja4J~dV}YD;+NYes6`q{ zrx~9vlCsV-dYSWGZtELk&qRUNq|04X?$*C4QyDzRS>!0*$5kl1S*X& z5%U`=%u3e?OZ!2kS)3U7nctQE)cxhok5@vuNgK5;VF4@F6O1-N`iUUzYOP6nQ0+RG zq}qbD9W*z(fJJ3xx;fMj75ayk%r-;B(>|a7NgrV)#M4zq+fQ}#3+GrV9k5E(g*K&B z-80)B@}PMp9r_T}OnwH@)@l>GaYNEA2VR^{I5ZauR4bMT3}`9XJP97#7RttL!-TQN z8B6kDg`gH=Eg4KKZe_B)F_GVM%U|v9JEAcmtt>5x1d&V-xoOJnXY-4JD#8AfFs3d= z8Y?uU(HXbbF=42z6&gcDYv56i1UC}~efvfp8JMwui-pJ)5^3j{$JJsr;*3S@tjW(J zm-PJF&0CuWg6!T+;#Z*QPh!iN@?Rb`mm1Jv1KINQMXi>`toQ+L|fx%5gWJ(tOzxynPQ?1*93%q z6Rxg`QJ&bDEM`{Rnc&2lUz<V%na0172_VA>(k z$epkD-nhTI@TxyLee_Sm*aT_cr5e?EXvAaBWD8B<0A8j6%4Hfy_Hpr2O-rMtQi*8J z2-ohNogIu4g?usihIBGO8%xg9PFzS{ zyf4n|Yn|10e|2~}wc0q&%nW+ox(^E`QY1P8k|&MeQIo;_sRTnUL0eNfij0E=Ix@l| zy8}987G2pSwRmRyu{Ga$09zFwD_CXg`Ie6&d0KgX^M&6au2OZmn;Pq%)^F?| zE4gQ{==`bgIkr}-v3K_*Pfuj?+mM?pPfWk0$Gvc}5}o(+yEi>)lO3Z8xBPJtzJII- z8dJ`tkB`>A^w5tVU)r9FFI~25cHj75;dSFxosF$flPsai5-6=)QzaQG`_xiliCqVi zP=^n_s_q4CG>#Lfgqk)H^P5{()lwx%#4F}4y84bsww`j|=t+0@wj;Ap?fXO~p}qt> z!~EeYdy!VzuRS(gTDYud^lw%#pL>Z3hnbunrB)ilcM~{-A~@oj$oP@9@e!%}l!}i! z5GoOrGFGUY>}(XEGD#A17h>XwIga_bO^*-XvnzE|qm-{#BJYWejEPth$|XRNu<@eX zcTE0pu$(yawI?Mm$tTU`Y7nrtcRxx|7rM|WbUm-)OmV1Np`3cgg&BtqJ9C=XfP=-y z)&rP>c({(y_>K^`JeU-no12buJq?+c+`p&#SlP3uOnB!^F;%mTUTbqCJLS1%juXkXKA_8JETR88648tNywJ*BRhCjPyEBsbnZO-@d>C{;nlo)0ygS% zrP$!zv9wjvt$Mh4C}h0C5?K$lMVaV{H66~Z-Ib9{Q&;CD<)XQLY<&0X2S$>S_S#L> z8%?w)(}Uw$eX(gyux4&Kn4CnY#?YavbhNny&9ec)A-1z^%XPUnHIhl%nmJ;kmdaI* z1X~L>4DoNAlbYQzud1oVE^Tcwi9Wz&T(VvW`YUDR_WCs&LlOxwHk)sz`(^y@J?&aVAW(?dCh(&4_Ncg1zP zf+-oHHco+Yhs^j8JB;58t*;O7%isPYuF;#m((>bebBEMZl^45fpSM>+eT?)!`T6tm zUu#PV1II@Kp;~q#Ma#>G=I&}#< zezq~Q$!*3_T3#M@l{Y(wr*Hi^n)F#+8yn6Ubuw3DZ*!@&X)jG9&NusbqM7z6qMetJ z6CX(3RT193Dpt6!E7kYfksmH&M42Kj&?a>K~J5`tcMqBz?+kifkEP8n{ z+j6TfNuSU!!DH`~Hfqx=w!NU#W2j>KGtI4W zYO$=hX+8jXC@S-si|J<0(TAGm=0Wr$@;282WLcD@c-@{^R$^(!>~Q>}8DVj*&$VwV zmb*hYaarA@Dg88zbf9PFaHG$tv&hZ8dkf>D@bbl;@7sBV!f0(AX$AmL+P>`LOx3gR zH6nyHne608q9aTC+iU3#weq{q48!V&I-kh%wf+9aNQmE8^tm z#Ryj~yg?|<;BL$`>Tm2U<dKOsF)rdZ4Bk_GCO9gmw*IWpMD~PGD{H2*IH!szV zn3~PM>zO7h8pD25LruXgLjgObQw=YI`mY;7_=11=C&;6)8w!~kS0^NvH z&Tl9b#H0Ghm#d?Y65XlA6=NJ^Hh4j0!E!->aC105VF6d0Iy2*Bf31Sv*njB9c2A=u zA^u6m&@G5BN-gaaOm}7QMG&8;fdGS@zYoqh&Q3L+@|y+y+K++#)73K&j#eYwF-A1# zEYWM%Q0L53km`smW|HH1m{W@(2n{{Td@mc%3NumvM*b{$RGNxCK=fvGb~{hieT?NQB=t8{N~|3T z7n=I#bjGUUkP(U_X3T<6b>d}?h}JZ7VK4dHSK-uIiuI0}%CA`W2Jikb$|)lD6iXfH zIp=idV%y-Q35r9Zg4j)$qEv4F?$k7_8=(QfiTQpckN@rU# zN!fHtpYGYF{)Qj8wSBc*H{#JdR-3kfPPACJd{5*+bU5~z=MBK@B#7R9E?YqYm)K2aXP7MpK90WKO2RQACnxvX`z+AGr>63z8@kP(^-<( zv0d$FlFth3WsO}Srs1jf>i+Ubs&&GA1;X!}%iG(?;3jR%IMAOvZ;W^sU7pFb{dHGw zJVBT?00#e{onw?Pf{*T4ra=3wFgL_j1%n=9GOYNSXr+_*x>lO}+t)Vp17quzO6>Zc zaW)>~k%ioB@i1nfZr0Wlgg^)^{ZRoIy@}{)sihn7VAqkBoropy#s1Ei*e*I#M7)Cd z$C)*`607_q3NTdH_Y>MOm!s+15NcjDnN!klGc-1w2cNk=KEGPt$3|+D++#|_E3NfI zSek%Q>(SNiX=7J;8_@}+r0+6QD$*!f`h4effcdEJm`5(7ZbLlXiwVZO6An)X)H~EM zfqH3b@B4`w8!m{-d=n>3L7fn0Bq7|v;7{KN-{)o>m&8oNyZxXWy8MiBiJn&RTE$(9 zini)k`N1*&rDFXe{tk2Yu}bNZZD=p$%0?z3dy?w5{`S%+W9ClWYPs|wS5AIgxed9T zT8=T5+jE;$!;)q@24t5-scW;}(lgzr7U^PMNG#6Ht)qX?F%16D|D@Tq-GWhkA)XUxJJiu=Y6J?H2(OhU;;x0McHK&kHyn)RGZ zHX%|0wRj5VQ1$mKFJgrkRbT9WZq-p5rA~EYyI&@SuWA+@lpJ05^X(Vm26xnsOh+2S z8^%I5T^_5rxV~~W4j5g0{u%O+^d=!6r{$6LxPL$J&O_6$#OPtiFt9w_(Gq;YbuU2 zG@ktX!J_K+WaQFs{-$o)kzj@Jy`yym8KTgGcpSLVLY5vrrZq;PD%w%z~NP%E( zf3Y)KYj^&C zDrR!2-{O5@#Tw@a)uKv~SYZK$kn+~XqW)A+{ww)d8yFIMAxW?ssPZ_k24g5^d zZpSB+-(M-d@fA!&69xu?+%8s0%;fphs{CXCs5eonCfvE!E>N0iL~(=%tqrwq^~Q&-orfPc*ZLDlo?n@J7W&p?NBYpS8CY0=%{YK zm1DrSpX)EwVy5jt(4n)LI&lGuk$N!ozjRKEE^}GBTHZ;g462kAtqtJFz-P!|Y}fjV zny04PX+KpbiK$@xyp?;Ptv&1?Vynmy=tWbgR_JQyv?uyv;l(2Xk zVyhRI6Wm<-IutuyDylxb3#NDGbz~01zDULWu=7y2G2(Xn%8heR$dG!7(u&c2r0S-S zLHVaI{4k6oM&4O*MCKQ7Dw!+iKx(pE%Tbc?u%3hAUqrF3f6X)0U~Yxhjw@R_;g0# zbjam|Z2Q6@)U|dcfP*Zws8}hP;Q=}7ez`kCMH|3=>{GSnv=@?@Y2=0MD;K_via(Rg z7|fdfw0Eh70l-cDt3*8VQG+BZSZ=#A{)F|8Z=15F?DmmidGhup8xvzHuK3w)?~ed% zv_Ipd;jBAcirQiXoA{#s-(SvgaW{lc8HneWK7B3n)gGt*XxXDX4s&a?ZHg$N^%x`S zZG*h8))Ocko#`g?Zd?6;MX#^yR=Fg!j#Wic-hFM^iBOG_Mf*>chwjn)u|}-Or;Zh; zvLGvDt0~Yq(vvH6__p>xfK%n-epVS*oIZ88v*_OValsb4`HY$W5+8fg7@uNzhD6SZXC1Qg-2prI1^OIn^Pc;BjW52NZXP_?%XKFrv@Kc{ za`6L9&>EMjAa5@Ei_MB;#&N&|9pj+h{{%oSl{lx7uTK7UJ`=|RZA~uqgCudwbL1Mu z*2jrpYg6)jE@jb+aa1|gBm!zQ{f9ID5kFbFnoJdtPbS{nUf%gK@Ajf`tUcF`+Y62B zB*!Lxp;C4X9})e%>8IyrPWA-C7k1jIil6+$0RsI$&rQ|R34BSC7{&;W%$}+y-yACv z-k>B%zbT*FA9enqAirC7?SSF+H%Eu~e~_Uo#!hHtz6^`vlbS@f$%BMiU1I8TADsZM83!(hKWd0@lR5{sF zF5i~II2Wj~V}F?Kg7~B3yR@%u@Z{9hQ|NazAo5#@+&Y@Y+!R;9s?dU^GDOgp?8%t7HqRkfPDzPmQ13PGS;0rtol~ z957#C+0-2o2x@i_K^jfFNlb;(3!Rfs5<*liQZrXeB%8m4uZ<(a_ou?$v*-f%rZ1 z)hyBP-^$UpAioDG&~%}1r;@M zylBW(hQO;*RVLX?NP(b*O4}Z0=v)L3u(9{4Ewzk=@Pt^OH1V@Gowq}?6rd+Yi=yB4 z_YyQpZuT^gzpgsFQ0b)yxpLug*Z~qcnZBJVhlUuE>kMo^pNt z%pUIVSt?h0%zl&?keOITR_3+ zwNNlPTOopPS@#k=Ky6Z2CV2864w}jZ#50xT{MoeBQ*SStd!zA{ssrIeX>}hxk~&P9 zMjJ;%h&+rJ%tM{w!{?-bG-GL0n^fb(GUBT4)P0}rkW)XND|PSx)NyiT+jTE~(eMY~ z$B&_y_PIz$G@d!cKfWl}JkI6RG~FIV`~ zYv0{X10$`p(?l>h4i(q z^76)=w(}8?reoXv8^fs4379Mh(s(Edh?1|?0 z^C-;=07@!C4^0Ia!9` zmTUw^Uzw2=UWz$nPDUxcOc(M6!xS-hq0*B{*>gK}(5c;RL!-3^Q23%KaJ)EL`z|fX zZ5xOdJm{l`5XukoIo3_xS26AuN>2*G;=h5#53=oKgn)*c_jUmF1%zRDL&@#mu&3KQ z0+^U!HY4}}XD7_+pR=4#lys@~Pd2C>WJ~&L51}$Co}`X19nDVC{)DXr*?h^1dLOn= z5hlOgMST>w#5l?Ti}Uz;ywqZg0e1 zL97^pG}RLjbm^I7avGq8IlT(^vfkxz4w2_onvY=eFVKsiE@ zp$}8^vt8SD&|kZqS0lejLJsa$FOjH)L5!XYTyEnMC3ZT3dt1#w_FF|x2KnBgDOfrg zES)6$Op6MM3nq?M~(R z+9gUsnBP1s0o~q}i7%NCWFcFwUl*AeGWsK0C0KbPv#J2Fh&_baug{nrZXN;zMI9FH zsGmLeBfx5hs=u`5o?x)SI+^oypzECUL0GjYmplo|UZ*WT%FC1Muq5>lRNSdcN+eg+ zFN*ke!^o{YbBHPl0%AhA@lhV9GArp}f+@r6V>z;`TX+WJVbjpjVQB9nrYy}6Swn`; z_b3b>*d70;)w~-P3<=u95{RisEX}4-S~l;~PymyEYrvfLip8%5IN<@D+)b6-7^ID^ z#TcfT4e3T?t%3~GvOO!yFMbJZEE;@(#q%s0F(VhPw|`dlpjLyms^GQW@a}XTM&$A; zmdo_gabn9R#yMW_8UtDON`55N38Ex;fwg2Uh7Xn%YivjnwTyZ4oLQPX`W7|eY}S0d zYve(z&8h_8)t%VfM(N!^S|r=@CxXQ{ORp;My??y`r_EHJSz<%sS4hysDf1^GHl z2G(prBVQLS;+c4pe?0E9e5UB6$SYJfn8MQr;Av0Y@BO2-p)Ewj%tz1nX-mVoOnoUR zT;wPViEI9aB^Ra6Wz50XH874oJcoRzbnh^VUq~&4#4`2gq@+*PIJ}v-W%a%DteuFx z_FTN&!~kt7|3nPPli4zykKWbV@F^twqA$LuPl6SuqQg5w4>M|>bWv%^QWJ$s^4=

    {LnQdm~iW(dQ<6=iC-RIuY42&zgPK%t%?ydu)|W3OKD%6!q$s9(_2$oy+aTK@&Mlc>R|EjjaGIN& zzxBA>-1Fanyj5hRIuL62HHFWNQ#smV6T}oV(eLWj*UU;?p0yPf z;@V__{aYBVY$&Xv&qiN!xLTU~f@v*A~aBt>`y(NtbTZG%{|8hfdHXf#-_`B23cE;16 z@$Wtx;^5$bsIoyD+~7z}XlSS}M1^kHuXIp(be32fA!7cOpJ% z-{AYDsn#8xGs_n(5M<2wGrY)+MaL1bFBX!OAurH9H}-m#=Y{`*7< z;b_qY-`V~4KZ$6vy0t_O9fzbHUy;0P9|0WaJdiD@ui?7hZ zjZI95r{`wt!L3{?o>)62AdsQD-b9tkDUGEfN}E^gltUz@FzUC`fFt6a1J`NC%RIv1 zkQCN!C(;y6_Bi7}$5I}L!CQnnb+nUV+7F3h3LU&f54!dllIuc0$mFt$=JV<4|E1ziGSck*m%%yV6ShZu@woV|<;(l#zY;1(Uc&&mj6NMpi3bNuV z+C8^ZQs@sA@()YM^HF8oWp_h1zEdu8Rfs__95y@sqbae6Ac$t7yl^gJ0A`m$HGW zw8MJpa(ca#elsHuq44r{OT(7LbcPe#MojIk=y}R;Qk`pmPAWyKQ4I2EP*>a0=jd(1 z`Ab4htMAiz&t)5`?NX6t$-SAP!g6wFAahuXs5)$IudAy&TDT_FyX~Z$Epp-fhu~>} z12zZC-)szeOt@d(+C4(YH359x^>uZ(ye>cC!>$~zO?S$CID~$Xqpe#~-;@$|OSwAJ z<&L~o_+oavd!VwRB_vh%DL30BqImvK-bde}dqhG^Ik0#2&-3$sQ?SL>H8eC2h^tt9 z2GMM?Elknc#zqUnzyC(dU}|$w1V*0gi|gy<2g69xtPGOQv-#gVeGIwrw(WVWBWo<} zYv}IxH8nMnY5H>gEYM=HJqU8|OEBZZH;WJgN}Z>O;fQ$+U_A2wuKX_3>N$(x5;$(@ zx+5j6F>G&YdS-ANl_Pcg!N!Jv#vuYB!Evn@3~_*4AHkQ>==1gX3V2Wq?dO21r>Ysq+!Vp1$1|%#muv_&&ivpl#xy z$hTwEJbL>Syb#RxS9oOhwCDI!pG>bkH!r^h3JV3m5-kX?iCa{~YYJ+@Eg32KDZi$g z^s1f09xVzSKhH>hxP)*YWPhNWVo!bojxq(-lfQFQe7+3?0z`ZMUBvG4ebc&2Rzx~to5O|efw zDP7aWVBQjmf~uY)=iv)*0O_g;QkAr(Xf%InT3W=Pit6?Sc0*jJ+P}%~oH8h7n5aPB zivWi!AN<#2gyqlq9KP;hINEt|Xl3qb_xkUYQPEJr1}@LuJy7Nk8}D?Onn%ww?#*?4 zd@O64_2fwdHWqb~u%dpuV%)Ib@Y?d}l=Gpp&B1Ts8DTW4YAq$mQRG9i>g;Ip6)_Ya zFRu-8PGz7#dD|*QcT2F<=qf(b5Vs0woxRCp7W-}+wTxNUDKsL#%e6n6_EFluF-^*1 zBa-Rb8(SfC*rj~`2t#?`8Lz?uy`kk!ZZOl-$uukL);Rq-qWk3FHKEsg{^56Cx-g``jT<-Wsi>%w zh3hhB+-lWY!^ne0pnwj&?jzgO%|B+?I6kwtu8S1OZ}e%&xw+2}?HGbj)_Z#9L@I-j zcB~G%ku>?mO7p_I?mss>z77;J=C}?+@N9B=n%4li)8R2hVD<>Qx2BBpRDs7rA~CTTR^t?KC2B~U#dowKGR2# zp?uGC;N9QoaGjo(&8=prZ82L>2yVIi{m@zY0H2y|` z@@kwu{s|WneVQpm6v8?svZz0kH@lVj^gr&ieo1?M} z&nLnthaXN!iw+;SvpU`#$+8pN`wQFY0j}auLStlsCb{EyjS$lR_aSLlD%f=ViP063 z)dyWcAUgy0`^wdjTlNA9GPVrAByw zboF@p4J}HvH0kKx-1oq_EYjsA=Gw*k{XAFYjwa$*5HLDXHq51w{&%ISjfG6^;Ewk8 z#Ryiu;)(Owq3MjrMOp5r7$V3qkqXfTv##Mqg zDT#sEc+R{32cLRcqgpB^+KJ?q(xl$r5DLB})v62r`q6}T}(6%hjZku9O zRc6R<@3^Gh-H_qze@gDnVM;~ICWgHYKGRZ*_mAYub)P1KSQ4njM^;o+{1LwNsC!Vv zvcoE3FpF*V@T?kbYR|T{o$vac;j!}3oWA8YK=opEMNkjSi*eUx*txn=ym2f_Qp^f@ zpGv4j?j854MlBs`FdgftI%bkXp!HZJNY66J#WBcL#rdu){6JiikyVnEm6eoHxFvI0 u<&uJmj57RRMMh@WcvJEJT;Sv9;^~I@|1T&$eKi#>KwQ-`(yh{Vi2Wb8C9yLA literal 0 HcmV?d00001 diff --git a/images/solo_icon.svg b/images/solo_icon.svg new file mode 100644 index 0000000..70735cf --- /dev/null +++ b/images/solo_icon.svg @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pool.css b/pool.css new file mode 100644 index 0000000..05e9499 --- /dev/null +++ b/pool.css @@ -0,0 +1,13 @@ +.odd{ + background-color:snow !important; +} + +.even{ + --background-color:antiquewhite; + background-color:linen; +} +a { + color: #0199E2 !important; +} + + diff --git a/template/links.html b/template/links.html new file mode 100755 index 0000000..d258f4d --- /dev/null +++ b/template/links.html @@ -0,0 +1,126 @@ +

    + + + diff --git a/utils/getprice.sh b/utils/getprice.sh new file mode 100755 index 0000000..1864c5f --- /dev/null +++ b/utils/getprice.sh @@ -0,0 +1,36 @@ +#extract infos from arionum.info + +dir=/var/www/__POOL__/utils/ +cd $dir +rm index.html* +wget arionum.info # index.html + +#line numbers +priceline=$(grep -n 'Last Price' index.html | cut -f1 -d:) +priceline=$((priceline+1)) + +gpuline=$(grep -n 'GPU hashrate' index.html | cut -f1 -d:) +gpuline=$((gpuline+1)) + +cpuline=$(grep -n 'CPU hashrate' index.html | cut -f1 -d:) +cpuline=$((cpuline+2)) + + +#extract price value +price=$(sed -n $priceline'p' index.html | sed 's/

    //' | sed 's/<[/]h3>//' | sed 's/^[[:blank:]]*//') + +#extract GPU value +gpuhashrate=$(sed -n $gpuline'p' index.html | sed 's/

    //' | sed 's/<[/]h3>//' | sed 's/^[[:blank:]]*//' | sed 's/[[:blank:]]*$//' | sed 's/,/./' ) + +#extract CPU value +cpuhashrate=$(sed -n $cpuline'p' index.html | sed 's/

    //' | sed 's/<[/]h3>//' | sed 's/^[[:blank:]]*//' | sed 's/

    KH[/]s<[/]h5>//' | sed 's/[[:blank:]]*$//' | sed 's/,/./' ) + + +#Write to file +echo "var aro_price=$price;" > price.js +echo "var aro_gpu_hashrate=$gpuhashrate;" >> price.js +echo "var aro_cpu_hashrate=$cpuhashrate;" >> price.js + +#spread file to other pool +cp price.js /var/www/___OTHERPOOLS___/utils + diff --git a/utils/price.js b/utils/price.js new file mode 100644 index 0000000..68fed61 --- /dev/null +++ b/utils/price.js @@ -0,0 +1,3 @@ +var aro_price=0.0041; +var aro_gpu_hashrate=1.643; +var aro_cpu_hashrate=211; From 2b46b05d3efceb965ad5f88ac800ce2b719b5159 Mon Sep 17 00:00:00 2001 From: F0nzy Date: Tue, 14 May 2019 13:16:02 +0000 Subject: [PATCH 112/134] modified: images/link_icon.svg modified: images/rig_icon.png modified: pool.css modified: template/header.html images/cpu_icon.svg images/rig_icon.svg --- images/link_icon.svg | 92 +++++++++++++++++++++++++++++++------------ images/rig_icon.png | Bin 23016 -> 27169 bytes pool.css | 34 +++++++++++++++- template/header.html | 4 -- 4 files changed, 100 insertions(+), 30 deletions(-) diff --git a/images/link_icon.svg b/images/link_icon.svg index ab046a4..ca81e46 100644 --- a/images/link_icon.svg +++ b/images/link_icon.svg @@ -1,31 +1,73 @@ - - - - - - - - - - + viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve"> + + + + + + diff --git a/images/rig_icon.png b/images/rig_icon.png index 27bd49ef8d39c0f348273fa10ea0416d89afa97d..041885002efa53dd581b9f2e4e732906521ffd41 100644 GIT binary patch literal 27169 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 hoUgxMu!kGMQ!XIL`}L}(02lNy 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 diff --git a/pool.css b/pool.css index 05e9499..a8c608e 100644 --- a/pool.css +++ b/pool.css @@ -1,7 +1,31 @@ +@media only screen and (max-width: 600px) { + .cbox {float:left;width:100%;padding:10px;margin:10px;border:5px solid snow;} + + .cbox-text {height:100%;width:50%;float:left;background-color:salmon;text-align:center;color:white;padding-top:10%;padding-bottom:10%;} + .cbox-text span {border:1px solid silver;border-radius:10px;padding:5px;background-color:#212F3C;} + .cbox-image {width:40%;max-width:40%;float:left;border-width:0px;right:1px;position:relative;padding-left:5px;} + + .welcome-info {display:none;} + .welcome-name {font-size:25px; color:brown;} +} +@media only screen and (max-width: 800px) { + .welcome-info {display:none;} + .welcome-name {font-size:25px; color:brown;} +} +@media only screen and (min-width: 600px) { + .cbox {float:left;width:45%;padding:10px;margin:10px;border:5px solid snow;} + + .cbox-text {height:100%;min-height:170px;width:50%;float:left;background-color:salmon;text-align:center;color:white;padding-top:10%;padding-bottom:10%;} + .cbox-text span {border:1px solid silver;border-radius:10px;padding:5px;background-color:#212F3C;} + .cbox-image {width:30%;float:left;border-width:0px;right:1px;position:relative;padding-left:5px;} + + .welcome-info {float:left;margin-left:20px;} + .welcome-name {float:left;font-size:25px; color:brown;} +} + .odd{ background-color:snow !important; } - .even{ --background-color:antiquewhite; background-color:linen; @@ -10,4 +34,12 @@ a { color: #0199E2 !important; } + .navbar-logo-image {font-size:16px !important;} + .welcome {padding-left:50px;font-size:25px; color:brown;height:100%;font-weight:bold;} + .counter {padding-left:50px;top:0px;} + .link {cursor:pointer;} +#update +.sidebar-left-content{ + background-color:#3d3f48 !important; +} diff --git a/template/header.html b/template/header.html index 0869e8d..21afe79 100755 --- a/template/header.html +++ b/template/header.html @@ -52,10 +52,6 @@ From 5d6d1aa0bcde7a884b072fce405ebec87346adb9 Mon Sep 17 00:00:00 2001 From: F0nzy Date: Tue, 14 May 2019 13:16:37 +0000 Subject: [PATCH 113/134] new file: images/cpu_icon.svg new file: images/rig_icon.svg --- images/cpu_icon.svg | 1 + images/rig_icon.svg | 1 + 2 files changed, 2 insertions(+) create mode 100644 images/cpu_icon.svg create mode 100644 images/rig_icon.svg diff --git a/images/cpu_icon.svg b/images/cpu_icon.svg new file mode 100644 index 0000000..0bf53bb --- /dev/null +++ b/images/cpu_icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/rig_icon.svg b/images/rig_icon.svg new file mode 100644 index 0000000..3873a42 --- /dev/null +++ b/images/rig_icon.svg @@ -0,0 +1 @@ + \ No newline at end of file From 384262ee21ecc5c0efccda7584b807eb5efb17f0 Mon Sep 17 00:00:00 2001 From: F0nzy Date: Thu, 13 Jun 2019 15:02:04 +0000 Subject: [PATCH 114/134] update database --- contrib/pool.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/pool.sql b/contrib/pool.sql index 639d531..182b645 100644 --- a/contrib/pool.sql +++ b/contrib/pool.sql @@ -52,6 +52,7 @@ CREATE TABLE `rejects` ( CREATE TABLE `workers` ( `id` varchar(32) NOT NULL, + `workername` varchar(32) NOT NULL, `hashrate` int(11) NOT NULL, `updated` int(11) NOT NULL, `miner` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '', From a1b8376e08a48e47a681031ecdafd289937522bc Mon Sep 17 00:00:00 2001 From: F0nzy Date: Thu, 13 Jun 2019 15:02:19 +0000 Subject: [PATCH 115/134] update database --- contrib/upgrade-gpu-hr.sql | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contrib/upgrade-gpu-hr.sql b/contrib/upgrade-gpu-hr.sql index 7ca97e8..ed3b9e7 100644 --- a/contrib/upgrade-gpu-hr.sql +++ b/contrib/upgrade-gpu-hr.sql @@ -1,3 +1,6 @@ ALTER TABLE `miners` ADD `gpuhr` INT NULL DEFAULT '0' AFTER `hashrate`; ALTER TABLE `workers` ADD `gpuhr` INT NULL DEFAULT '0' AFTER `hashrate`; INSERT INTO `info` (`id`, `val`) VALUES ('total_gpu_hr', ''); + +ALTER TABLE `workers` ADD `workername` varchar(32) NULL AFTER `id`; + From f1aecddcf6fb2a1152a1ccca485ba984d4c5355a Mon Sep 17 00:00:00 2001 From: F0nzy Date: Thu, 13 Jun 2019 15:02:50 +0000 Subject: [PATCH 116/134] workers info --- index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.php b/index.php index 5cc0a0f..cd36ef3 100755 --- a/index.php +++ b/index.php @@ -115,7 +115,7 @@ $tpl->draw("index"); } elseif ($q == 'acc') { - $r = $db->run("SELECT concat(id) AS id, sum(hashrate) AS hashrate, sum(gpuhr) as gpuhr, updated FROM workers WHERE miner=:miner GROUP BY id", [":miner" => $id] ); + $r = $db->run("SELECT concat(id) AS id, workername, sum(hashrate) AS hashrate, sum(gpuhr) as gpuhr, updated FROM workers WHERE miner=:miner GROUP BY id", [":miner" => $id] ); $b = []; foreach ($r as $x) { $x['hashrate'] = number_format($x['hashrate'], 0); From 78694b2479a2ef1deda2f358164560b8ca325d41 Mon Sep 17 00:00:00 2001 From: F0nzy Date: Thu, 13 Jun 2019 15:03:09 +0000 Subject: [PATCH 117/134] share count, worker info --- mine.php | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/mine.php b/mine.php index 7ac2daf..b9163af 100644 --- a/mine.php +++ b/mine.php @@ -37,10 +37,21 @@ function curl_post($url, $post) } $worker = $_GET['worker']; + $minerid = $_GET['id']; + $hr = (int)round($_GET['hashrate'],0); $gpuhr = (int)round($_GET['gpuhr'],0) + (int)round($_GET['hrgpu'],0); + + if (trim($minerid) === '') { + $workerid = substr(substr($miner,0,15) . '.' . substr($worker,0,15),0,31); + } else { + $workerid = substr($minerid . '.' . substr($worker,0,15),0,31); + } + $bind = [ - ':id' => $worker, + ':id' => $workerid, + ':workername' => $worker, + ':workername2' => $worker, ':hr' => $hr, ':hr2' => $hr, ':miner' => $miner, @@ -50,6 +61,13 @@ function curl_post($url, $post) ':gpuhr2' => $gpuhr, ]; + //fix not unique rows + $db->run( + 'UPDATE workers SET + id = :id, workername = :workername where id = :workername2', + $bind + ); + // fix Dan's misreporting if ($gpuhr == 0){ $f = file_get_contents('cache/info.txt'); @@ -75,8 +93,8 @@ function curl_post($url, $post) $db->run( 'INSERT INTO workers - SET id = :id, hashrate = :hr, updated = UNIX_TIMESTAMP(), miner = :miner, ip = :ip, gpuhr = :gpuhr - ON DUPLICATE KEY UPDATE updated = UNIX_TIMESTAMP(), hashrate = :hr2, ip = :ip2, gpuhr = :gpuhr2', + SET id = :id, workername = :workername, hashrate = :hr, updated = UNIX_TIMESTAMP(), miner = :miner, ip = :ip, gpuhr = :gpuhr + ON DUPLICATE KEY UPDATE updated = UNIX_TIMESTAMP(), workername = :workername2, hashrate = :hr2, ip = :ip2, gpuhr = :gpuhr2', $bind ); } @@ -232,7 +250,8 @@ function curl_post($url, $post) } api_err('rejected - block changed - 1'); } elseif ($result > 0 && $result <= $max_dl) { - $share = ceil(($max_dl_network - $result) / 1000); + //$share = ceil(($max_dl_network - $result) / 1000); + $share = ceil(($max_dl_network / $max_dl) * 100); $db->run( 'INSERT INTO miners From 9ae6cab50a647740dc21e21cc8a5b507c8174354 Mon Sep 17 00:00:00 2001 From: F0nzy Date: Thu, 13 Jun 2019 15:03:34 +0000 Subject: [PATCH 118/134] handle orphans --- manualpayment-sendall.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/manualpayment-sendall.php b/manualpayment-sendall.php index ba97b1e..9104c6e 100755 --- a/manualpayment-sendall.php +++ b/manualpayment-sendall.php @@ -86,7 +86,9 @@ function pay_post($url, $data = []) $s = $aro->single('SELECT COUNT(1) FROM blocks WHERE id=:id', [':id' => $x['block']]); if ($s === 0) { // dit kunnen we dus aanpassen naar orphaned. block wordt niet nog een keer meegenomen want verdwijnt uit payments - $db->run('DELETE FROM blocks WHERE id=:id', [':id' => $x['block']]); + if ($pool_config['keep_orphans'] !== true) { + $db->run('DELETE FROM blocks WHERE id=:id', [':id' => $x['block']]); + } // nu halen we de payments weg en wordt het block niet opnieuw geselecteerd bij de volgende payment cycle $db->run('DELETE FROM payments WHERE block=:id', [':id' => $x['block']]); echo "Deleted block: $x[block]\n"; From 80efac5b8ba20955e9103865406e96a0e1c389d2 Mon Sep 17 00:00:00 2001 From: F0nzy Date: Thu, 13 Jun 2019 15:04:02 +0000 Subject: [PATCH 119/134] show new worker name --- template/account.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template/account.html b/template/account.html index 1001cd6..3404590 100755 --- a/template/account.html +++ b/template/account.html @@ -108,7 +108,7 @@ {loop="$workers"} - {$value.id} + {$value.workername} {$value.hashrate} {$value.gpuhr} {$value.updated} From 2ea2564480d065e937a0c9f425648e7f8294cb1c Mon Sep 17 00:00:00 2001 From: F0nzy Date: Sun, 16 Jun 2019 16:00:12 +0000 Subject: [PATCH 120/134] orphans info --- index.php | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/index.php b/index.php index cd36ef3..6fa456e 100755 --- a/index.php +++ b/index.php @@ -23,6 +23,13 @@ $current = $aro->row("SELECT * FROM blocks ORDER by height DESC LIMIT 1"); $last_won = $db->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); + $orphancount = $db->single("select sum(orphan) from (SELECT orphan FROM blocks ORDER by height DESC LIMIT 100) ol"); + $oblockcount = 100; + //$oblockcount = $db->single("SELECT count(*) FROM blocks ORDER by height DESC LIMIT 100"); //comment out on new pool + //$oblockcount = min($oblockcount, 100); + $orphanpercent = round( ($orphancount / $oblockcount) * 100, 1) ; + $tpl->assign("orphanpercent", $orphanpercent); + $total_shares = 0; $shares = []; @@ -182,21 +189,6 @@ $b = []; foreach ($r as $x) { $x['reward'] = number_format($x['reward'], 2); - - if ($pool_config['keep_orphans'] == true) { - $f = file_get_contents($pool_config['node_url'].'/api.php?q=getBlock&height='.$x['height']); - $g = json_decode($f, true); - - if ($g['data']['generator']) { - $x['generator'] = $g['data']['generator']; - if ( $pool_config['address'] != $g['data']['generator'] ) { - $x['orphan'] = true; - } else $x['orphan'] = false; - } - } else $x['orphan'] = false; - - - $b[] = $x; } @@ -233,8 +225,6 @@ $tpl->assign("pool_degradation", number_format($pool_config['pool_degradation']*100,1)); $tpl->assign("handle", $pool_config['handle']); - - $tpl->draw("info"); } elseif ($q == "benchmarks") { $tpl->draw("benchmarks"); From 936bdc6287431268705d7318f502621b8f17e46c Mon Sep 17 00:00:00 2001 From: F0nzy Date: Sun, 16 Jun 2019 16:00:25 +0000 Subject: [PATCH 121/134] orphans info --- update.php | 45 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/update.php b/update.php index 60f8add..135fece 100755 --- a/update.php +++ b/update.php @@ -42,18 +42,18 @@ function shut_down() $current = $aro->single('SELECT height FROM blocks ORDER by height DESC LIMIT 1'); echo "Current block $current\n"; -//$db->run('DELETE FROM miners WHERE historic + shares <= 50'); +$db->run('DELETE FROM miners WHERE historic + shares <= 30'); $db->run('UPDATE miners SET gpuhr = ( SELECT SUM(gpuhr) FROM workers - WHERE miner = miners.id AND updated > UNIX_TIMESTAMP() - 1800 + WHERE miner = miners.id AND updated > UNIX_TIMESTAMP() - 1000 )'); $db->run('UPDATE miners SET hashrate = ( SELECT SUM(hashrate) FROM workers - WHERE miner = miners.id AND updated > UNIX_TIMESTAMP() - 1800 + WHERE miner = miners.id AND updated > UNIX_TIMESTAMP() - 1000 )'); //uit sanity @@ -64,7 +64,7 @@ function shut_down() $thr = $db->row( 'SELECT SUM(hashrate) AS cpu, SUM(gpuhr) AS gpu FROM workers - WHERE miner = :m AND updated > UNIX_TIMESTAMP() - 1800', + WHERE miner = :m AND updated > UNIX_TIMESTAMP() - 1000', [':m' => $x['id']] ); if ($x['historic'] / $thr['cpu'] < 2 || $x['historic'] / $thr['gpu'] < 2) { @@ -82,7 +82,7 @@ function shut_down() //$db->run('DELETE FROM miners WHERE shares=0 AND historic=0 AND updatedrun('DELETE FROM miners WHERE shares + historic <=50 AND updatedrun('DELETE FROM workers WHERE updatedrun('DELETE FROM workers WHERE updatedrun( @@ -96,3 +96,38 @@ function shut_down() ); +//count orphans + $r = $db->run("SELECT * FROM blocks ORDER by height DESC LIMIT 100"); + foreach ($r as $x) { + if ($pool_config['keep_orphans'] == true) { + $f = file_get_contents($pool_config['node_url'].'/api.php?q=getBlock&height='.$x['height']); + $g = json_decode($f, true); + $oheight = $x['height']; + + if ($g['data']['generator']) { + $x['generator'] = $g['data']['generator']; + if ( $pool_config['address'] != $g['data']['generator'] ) { + + //stealer alias + $fa = file_get_contents($pool_config['node_url'].'/api.php?q=getAlias&account='.$g['data']['generator']); + $ga = json_decode($fa, true); + + if ( trim($ga['data']) !== '' ){ + $x['stealer'] = $ga['data']; + }else{ + $x['stealer'] = $g['data']['generator']; + } + + $bind = [ + ':height' => $x['height'], + ':miner' => $x['stealer'] + ]; + + $db->run("UPDATE blocks SET orphan=1, miner = :miner where height = :height",$bind); + } + } + } + } + + + From e0481615096e7aba080289099a63512b59fbd31a Mon Sep 17 00:00:00 2001 From: F0nzy Date: Sun, 16 Jun 2019 16:00:52 +0000 Subject: [PATCH 122/134] orphans info --- template/blocks.html | 8 +++++++- template/index.html | 3 ++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/template/blocks.html b/template/blocks.html index a5eb170..ce704c9 100755 --- a/template/blocks.html +++ b/template/blocks.html @@ -37,7 +37,13 @@

    {$value.height}

    {/if} -
    {$value.miner}
    + + {if="$value.orphan == 0"} +
    {$value.miner}
    + {else} +

    Stealer: {$value.miner}

    + {/if} + {/loop} diff --git a/template/index.html b/template/index.html index 7680941..0090a15 100755 --- a/template/index.html +++ b/template/index.html @@ -36,7 +36,8 @@
    Active Miners
    Difficulty: {$difficulty} - Luck: ~% + + Orphans: {$orphanpercent} %

    67h*0pmc>n8k@2`k`X>wymMrO-FVRz$< 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 literal 0 HcmV?d00001 diff --git a/images/gpu_icon.svg b/images/gpu_icon.svg new file mode 100644 index 0000000..e09bd43 --- /dev/null +++ b/images/gpu_icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/link_icon.svg b/images/link_icon.svg new file mode 100644 index 0000000..ab046a4 --- /dev/null +++ b/images/link_icon.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/node_icon.svg b/images/node_icon.svg new file mode 100644 index 0000000..73f5ddd --- /dev/null +++ b/images/node_icon.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/rig_icon.png b/images/rig_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..27bd49ef8d39c0f348273fa10ea0416d89afa97d GIT binary patch literal 23016 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

    From c29943311b034f39fbfb6ade00e40b278662df0f Mon Sep 17 00:00:00 2001 From: F0nzy Date: Sun, 16 Jun 2019 16:01:21 +0000 Subject: [PATCH 123/134] updates --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b52039c..7ea53d3 100644 --- a/README.md +++ b/README.md @@ -6,10 +6,15 @@ System requirements are indentical to the official pool code. Warning: because of additions to the config file, do not simply replace the php-files without making sure all variables are added to the config. ## Mining -- Share count based on network min DL, 1.000.000, so pool Min DL don't affect share count +- Share count based on accepted share and pool min DL and networm maximum min DL rate - Multiple pool can work together, (eg. different min DL for Cpu, GPU or other mining settings, but same reward policy) +## Utils +- Update.php: calculate orphan blocks, and overwriter (stealer)'s alias or address + ## Display +- Show Orphans % (basen on last 100 block) +- Show Orphan block overwriter ("stealer") - Expanded informations on main page (need to run /utils/getinfo.sh) -> passed blocks from last found -> luck % (based on passed blocks and actual hashrate, need to finetune) From 983189dbf21d83e980964e3c875ff5b91dacc6ea Mon Sep 17 00:00:00 2001 From: F0nzy Date: Sun, 23 Jun 2019 21:14:47 +0000 Subject: [PATCH 124/134] new links --- index.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/index.php b/index.php index 6fa456e..3f6fda6 100755 --- a/index.php +++ b/index.php @@ -23,7 +23,7 @@ $current = $aro->row("SELECT * FROM blocks ORDER by height DESC LIMIT 1"); $last_won = $db->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); - $orphancount = $db->single("select sum(orphan) from (SELECT orphan FROM blocks ORDER by height DESC LIMIT 100) ol"); + $orphancount = $db->single("select sum(orphan) from (SELECT orphan FROM blocks ORDER by height DESC LIMIT 100) ol where orphan>0"); $oblockcount = 100; //$oblockcount = $db->single("SELECT count(*) FROM blocks ORDER by height DESC LIMIT 100"); //comment out on new pool //$oblockcount = min($oblockcount, 100); @@ -230,6 +230,8 @@ $tpl->draw("benchmarks"); } elseif ($q == "links") { $tpl->draw("links"); +} elseif ($q == "news") { + $tpl->draw("news"); } $tpl = new Tpl(); From 4332dd64f7894b80f65aec0c3675e7f8679d4d1e Mon Sep 17 00:00:00 2001 From: F0nzy Date: Sun, 23 Jun 2019 21:15:28 +0000 Subject: [PATCH 125/134] improved performance --- poolsanity.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/poolsanity.php b/poolsanity.php index 25274bc..51c19e1 100755 --- a/poolsanity.php +++ b/poolsanity.php @@ -96,4 +96,14 @@ function shut_down() file_put_contents($cache_file, $fin); sleep(2); + + //refresh PID + $pid_exists = file_exists($pid112); + $pid_time = 0; + if ($pid_exists) { + $pid_time = filemtime($pid112); + } + if (time() - $pid_time > 60) { + system("touch $pid112"); + } } From 617eafbe895947d8f421d587ee73e15bcb11b44c Mon Sep 17 00:00:00 2001 From: F0nzy Date: Sun, 23 Jun 2019 21:16:33 +0000 Subject: [PATCH 126/134] orphan info --- template/blocks.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/template/blocks.html b/template/blocks.html index ce704c9..40194b6 100755 --- a/template/blocks.html +++ b/template/blocks.html @@ -31,14 +31,14 @@ {$value.reward} - {if="$value.orphan == false"} + {if="$value.orphan <= 0"} {$value.height} {else}

    {$value.height}

    {/if} - {if="$value.orphan == 0"} + {if="$value.orphan <= 0"}
    {$value.miner}
    {else}

    Stealer: {$value.miner}

    From 4a23600ac72a791ac25fce14dc266f1bec48db0e Mon Sep 17 00:00:00 2001 From: F0nzy Date: Sun, 23 Jun 2019 21:17:01 +0000 Subject: [PATCH 127/134] personalized --- template/favicon.ico | Bin 133143 -> 204862 bytes 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 template/favicon.ico diff --git a/template/favicon.ico b/template/favicon.ico old mode 100755 new mode 100644 index ecd5cecb9182fc5b1beea730dd7af0df73ff417a..604ec12f8e265285aaafb32b5b2375318f673ced GIT binary patch literal 204862 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�m;8c z@~)|u7N_QR*j(Ng0@(k0J-!kkFTi{&!Cm%_1!q0dKMM(3fD-zj>B%b4vDzxSkycKzSC z|KlI`e@yy!qgBv?`02{85&-=Jm#AvTku_!`%cP@Yo%jJEfB+u=MZ%*b(E^-}8muL2m18(?8NYVky~p znrxz7DF7xT!h8gte+zZ~ssDrck3d`tv$d7qd`7hSj3gGECL8tx`SLxAWqT~&8?1Nt zz`BeVI)~@~VX0a#*BP|$Pqz$=a~WCaKj~BdNjv-}SNct^^qB;z{Kjtwrupwv{eS4+ zeKcJHL!tJ+ylaFJct@54U39H-bR8ds?XdHtVYy}@xytTSBnpj4`c~|j^85pJ|0j8k zh1~NU`M`0~#CkEdpKjOxk9-CAiBkR}Uw(@%r}`&lnEyV|KUZ>tgZ@jt2c-BG5F4*Z z3NDHl7{y~Y@ZE+o8Y@QjO4k}ORhf+em^m1<1_PE%-aqp<{Q}LDFdvb-1n9%&YR7LO zo6nFfXV~;Mz$BgnRQ4wEKdOIrYpZDUX&{L`C5de%>kb0-M^$EXD|Eg+b@m3a{Pi~$ z=EX9gcIa;A+S{_*$hzNuLBvuJfN<1t5N(iB*0RYQgj9AD)jpmOzdy3y3TP zu2B^(QI+cG?XuBzTx2mBktZLXq8l8m@{5A_kz;t%m*b7Tzs%CcIc$pk*d?UuF5oMX z7q}`b`BPr}pM2RJw)`i-|G6&cpZY&^B0!;SQb^Htz!nM^ud&9fZ0R+&{2DhuPtp5QvZ%yDXs!;Cu5Y1_L_p>&yC z7cgnN@5EX_?*cHP8a!$LQT*TzMpvTX0SPa}d4R{LQlO09E|0Eb$Lu5^yp#kNXnK8Y z=Qj|4_sv~`4tr;GO>`Io}v%Yg!!@|4Zo~mLK}} zi!AbuLJO2Kpcq{T%g>J9L85oCVa0rKo~Gw4Yp-4!>yFMszOL*0; zW!GfoSH;*DhWbB3E(|umExG2{^9u} z`E>@BZ_L&fCa!_qwx8XKU47fw)u*f`X9G;(m_qQ|khz)CEl5?vI$~#G3m&Z2yt}5>jBa5Y7YHF(iVcD}AEMyhfI} zL}Tt;CK+D`$mCs=&@vKOtRIr>IylzMsn1(}1z+^^I`#kXh;{1!|26$1FNUBfuvl0K zIO9b){Cw$MQR#171?r+v2#4Z_pE#QNy(%ib#*|+N1i?=Vodqz(-!aA4M8>P){3~4k zRg!;IRB%yMbY30zwKjN~X27V21@_jyR=D_T-{~)#mc}K2%cp)TO1~&d`&N{4j!!v9 zQrZBPx=<3%QsPkpdR7SjG!m?Q2dInN*urjTmaaT5UA#}@;tOD?U+?EdL5BT1VfOEj zbf2&t_)OX1J7uTW%v!HmH9pg~`wEu7>y)}KQ|kPuZ1$%>Ja{qqm&-*{P7a#0<>M;AI%Gida4oyI@?LrNDv-Ma(j zGcwrJ%Us%}7tw#?J^i<~>wn2!jguF6mEypsjt3Sn+P^!(p~q;CNxJ~V54>Mo|1J;d zKS0obfS`YyaTV;OO3<$V=!f+08K~8}N#!qD>-E%+^R^s>gUT>+x2}L)Sj(>6$7Ee( zimr1NSNNI>;;PH&3o5So0TEFS88K57sNMhnfhqif6n;kvuQ7#Jn8M49@hXFk69rdU z<7GDI9JlS5Xyb0H;fsN(|G?Ywksmq_sm4sMvrq*s(#$B4U^m{R@A%Y<(yUXGj5ap; z5}SPSp8Y??AOw`qMyT;`W8&J-vzJY1VK4>QdY)`LOIEdtmmY8$yUs9jIfAI*wRrw0 zY!Hd1N*fQmK2seAFL0kw>OQf|d)lYKcls{iJ-v=Hjp8?z8h=3j|9ke|Yhn$!@BgC; z+GA{m`c{72W3z#=lN&}Q&_$3at- zHg2e@e(g`Rhpxjv{8DOZ57=2H?6NOO#yL{>Jy&s2RC7*TeNkF@O;U*f(T^Nzq@SUG zQgnqBJdck<9aaVw3HdZQ!ldKia%2Ev?lN8`KLv7q4p~iQhy2vMg*je40(Z zj9cJY`e)-$qYw`F0@?a4i8)7Bwn`T5b04|TC2aOt54*pI-%bdeDdQATm z_)Met&e#RKr|)>W{_o9yAJ)HV6#(?_F{Z+Iba|K2SPoq7G`37Xu2MWUdE~GXPm5F9unb3%-X=;r&!k*qQm(Yef7<>3 zGfey$YX7%kB7lt8d1mW5vhggM*(&E$tHvg)9lcZzucstZEK|ufmRk3|)_v#M1#NJe zTF&y1ZAzt{9SpJ{bI)c@bnb@C1b|NYzJKeXo4+r;=9Zy+>0 z@gGwjfQCO~%3PuR36-)bwUWs@*omL96TmKZ{7zQBlA^$o8AH?-vKO#p(|pH-$VaQ zyZ$c|Bc1}6*n*3=3rPO=Ox|}=bT!XDr=On*BsNYWmFBJL5?~!R!!T{VJZ2wByTqrq zNmH98si(wg=P>_eQomzTuin%D877%l{xI>U@9F;nlXQ{Ua-OU^1J6f0HAgdIHFP3+ zO?$}7R64b#LEn9p)5sjB@ug04cDv2~^8FcA@6D+8o%I=j_yNRk(!VhO-O+9G&MuQt z|FGSU+W!ao_ZnXde8$#*E@R5OjV|>VTV@znW;UssOy5DKenKXG$xQr$8~+J6ZWoEl z2hx7I(muHo3s1332{-J8g!FIv!$^RNR9bDnNXv-1s+BvX>6awA--${P{J9}61vlB! zJAf&=Nx_0*3bp(KSMS?@Hvd~L|Dvei5@JEpyt6>QWiL>US)z)VEp_n|Ypt=g@Shze zY__7Xb63vJz{+|Ndbnj=!L%3qYe>?*<Rk9y<%RKW#A0$ha;eqSC@*~!pYp;&+6SMo52elM#Q^Js&SvP-DlRPzOz2@ zpS=tC&7wT;f2Qpa{QvE~)3*Ch-HzZ7lE41Q|4yg@o)c?<|F}vJFt#FKY`Ocm3YT#e zmJ_Q~ld2_?>&Vny%#=^qNuRJ2cd-+y+40pRA|EKaPFDs@5h?YUg1r4JTwbG=v<64L zmydQvf-0#=l6{es{LGg8Brd%U{qrTi0H*LZ#rQo|1T#gKn4*jK^p9HrQ{c;N-nV@I z1*!2IrQj?e+2?^Kc9(8b4R-5OIC#H-#ORBSfw^CAi+}aPeATN#&_tgE7oE3)(} zlJu)w`geTVWpV0hQR?YO^-qJJqJ*=O#Iqb81aYlc4K3erP(3Tl`n~?-GR5u2T7*SgI5#BJtR-ZMYzK6885Svx%De&I3qbN^X&z@&elY5zZa?;RG^)rEcU zQ>IsX2LL1#Mldn6e%K21O>5y6zN^SiULYkK>>TE*+A^wX!1O7`O15J z|9$tK!Neq*XksB|yndIN;4pK}KKEH??X}lls|;wopzY3{r7oV^+~$=In!Vk97W7~0 zGPBfS)($XudI=aZtq54p++;Fqi)2nInYV+?Ehlq!F>`kEv&;C|+u2zq?95{FWiC+I zk5<`^;za)n&*yRJNYr`?V^h_KQ`K`;Ng~Uc+#a^zDpzusFS)~G3uF;2KZVV|%HkG4 z*yq>!$K;pExqwH2Apb1j^UeV#`#caQHc8htNM^5)eC{tDJWg)ufRuyBzxvg@*5(fw zOb9moJd%%VA}Q^(3`<5ApN1MQm-*C7Y-$fn?SDI$(*A4x!~S;)*R^9847chO6LVY? zUaJl$P<<1su(Fey{Pm7eLa`JmY=$cB-nRU}zyHMLb~AGa_?9{P>~vmG<+fngVDB<_ z?+QoXYA2uSfnH_6b$&T;@t`<+Zg-;M-|FVMdEmUQ?z4Be&EBrH{7$pBgCWz4f#Zx~ z`x(Usvr83ob_k&Sc@TdEnO(umF6U-r3b37-R>Dp#l7F@ah>ab@1~#v z-lpk3c8*Q!A*t6$>SfFY2=)Ivf!6>3#s5j@5Up#KB%bC`(mdj@)ThW~YN+a+&!6uY ze)n#Lff2C$IN0X%nEoE+wto8@7S=c~tZ?(K80@`skk8J6zB}D~cRBmifPwSNf$MzS z0`Pn)D4sC>+uS@h4e}^uq z2ynNyij{`G(V?m1Cxf zZ3kojBPW);nl=^)VxvtkP(Ov;(Z^p7b3 zvY^|Tb*+MgRw2qBMjhfq_e*Cc>5chT<}&iRl>wKUW$`4E7?=V>xADO8>jdlXGwr>~ z9ewLu{Hk32sOAUyR8o9#3+!_BsdDwM`j!4Y%bn>X03o1KH;=7@=52PHx6OHOnbVvd z4zss9BL9EZCg3=03(%jlLp7(2pSO#drxpKBjr}jDVgH$>%=E3?S4I36xuzq(2me~j z|M;a8>KiHS-6Z4ZvPs9-ls1z41IfG3l$-;C4LyL%yUyj((m>=<{8MB9spjzrpyc8f zIM3&tqhxpU*%z6t9+KH3$T){qN2=I5Q@^#dH=9LbfSu%KL@t~RcKrycxu%7#f zXA|R5!+Pvu@D!L`M&^_g`eFx}wwax>Q9Ln6@@cBRX@BqruXa8A#S$p>q}Bt(?|&tT z+`-4x^SSr<+`G(%Zon5&xV&pz?sbj+d*eSO4-U_h^)JZo7Gz)Kval|2Ntkh7oN-36 zve9sHiQbGD`JnfuPQ!VHKCjTDE2l3yZ4##p$q6J<6!6!Zu@127+nEfs8>ae4%QFtE z-o5&V_#f9l&Huz4nNE|FPO(YY>Uf%oJuL~WPv*!VZP`IZmy**e&#d=T{STjk_i>*8BY_3!gU{g-LtpJkd`pxkX< zh0DBh2P_BAEgdv#ll!bqPP2=E%%cjho(+s=BkNJk&fCer|NmM4vv!cFTi9=lr5`28 z#>OcPEdZWR&#sd<`<()%O6@XG?}M+5Gp`tCTqSAu0bAV8mbCH(m-u`{L9b{Q!m$3O z@%(eoGcfzT_MhGhZ1x!-%Do`Y?UH6)k!4MN#BVWZh}m233eavfrIU6U$m)<~T##pU2{L+^j7x<2KX?TEtp9VGM?fn{ zX=RcT2tva1IkM(Fx9kMJ^oZ)KP?Oa>2!2Jt- z*9p&iMsNK41q!9g(MA2K~5)?c(nr>;JMW^Qt(b zN2C994D`RgRh@iDFQ(FH5}LBjWzfbQa6DZpdr=PpOnap=i{Ycp-X8my{yU+686rO! z7oVno2IBu&|7*^Y)#v!=Bf=#usxN|#hF}|bzh}Anc=X_org0~MNNi-Kc6;CC-S1pH zvYb2%to@sSvu`7S{@nvh2U7iSe=hwyc~bp5;zrQufB4MJLy+@1r((d|of5BI;OY9u zQvmwk!A#!Df0m)|Hc`*{<7YXef8l!sQmOgSVP+%W(~sK&m~3P_U*Ynv@~NP$Lz zbip-2?kyfa%sa>Cog?`gw7wA1fpWUItP6n8ZWrXV@;U8%j;7B`8uAS~$@;St++0Z= zs^C1J9Qu)R;AqsZrw`)4cNfqsGSt4Xb}|erGzc#t>D@q-c1@Iaoy+KA;rVO9DnRN* zhE4%4FsWT^>P0TKOO|{Ja47Yk)J9@Z|MrBLSE}vID24qqb;HprUt!kYV8CFj_rGfct?lu=@fBTR*Ti=?!*?smlyV>RDb9ZtJY5?)A2aIPq z;62I!>siJCj~x^Qf4(mleY3%M{0jYde2{H~q52nU`&mv|r+=OPpG7Bc?0aB{H5C#h z7Pdebv{e|ki-GCR!Je0MqWn&2Znr%9niws^@~||9h|oETW)`4b|6(%FFqxg2ztQdG ztT5{w+Fqj(44OX*GCKsQf1chUOz&Wm+kt3pi)d}LL12!tPqKR4Eai}oMW(jYBf_S_ z=lp|WR+ircn9Pb{65E)>c9L^d!$p){XVNb+X+4Pi1EfHZG;RE+n?ci=)DAwiQ=Hrd zXp-~lv+D2){m@c{`)HY==~MH37zRbEf#HC+jU3;z`gEbqml6HuW%u*jX6;{T5xB=T zXpeKy9+#kc*G1L9X;B?;45$IF3#;7xD&4fE-nYsfOT9joZZrx+gFh6F{de)&1>8J# zf}wMF49AAwd8GsAZL{?#Gxgl1=T$BAt`m6IFy0k_onH zObY4$ZESz<;{J;&trzXKShT*QQt*Zm^Q~mos zhyJl}X6#w1@~Y;2>N%gg=fm64>c8qq`Y)1>TViDAs`vbJ`97`Gmv(U4`~kk7 zJ8wJK#Cx4ZWQjEKD3f`S&B1cOB|f)@&%s_u%|sZnP)r0s4u#1&3$QhY&FVzAFBpGn z|23Vjwf%o3>7A5}4j@iDBThXdU2{?zcT5^vCygnWElQJnL@K`YPz@a|cN)ga^?B)^ zG#nJG4fF@NsK?GwMmNh)jTT9*8FYsZKzcUGLf8k7fNnPZB6!UHcftO1DVzf)uXabF<# zvl9&TtN?>Nb^@9LF~7`eL79nnnZmn@_pax>>zM_6SnqnFcO~Gxb^-!}59aRzjAtbv z({_=`yQC8{j6VofyM2WR7PbMtG|9YyAIvHAuzlWgR-|okx_s>+NDDJ!Yyso)E(&tG zc&zqnHUd1C{-x=i02SJSIPDw|C7czlJu6N*AxS?hUtO+TnyvO+s{g?ks-YhURmOrp ztF9w8GBX}HLVu!1zA_4BN4@?fo->WmvsM_#W$!7MsNf z`z_wze{rKjaJ6f2nQKsmYe1!IU^Sis;0gL)_%!`jYW45#Spf!n>;yCg+N<2mr(Dms zT-30nyP%rYX0s^mH;0gMlT1mdDlz+0`;vGMIhfm%>fxhHZVz41jAe7iR z$?OLkOb#~jO;fCDf-p^#pYSU?nR-Q%H^Wo}L0Ef^@htMjA#d{nU z@3jlrYa6n6KuE2_;!4LwRW1;JV2x|gZkM3lPt-r11yEn88tcCUy=&aPD+l|O4e~(> z9DM`~onH!Ey|%k}Z8!C)H1w^OF02;%*KmHdj87foT~8M5W)|$`7SwWHwY=v}0Jn#F zK3+Q+uL|sNB-6Kxr)*YCE>gbhueKT@GkgK%i(j(b`t-*ezdfPf%mQ~N>ubzDF_39M%p z*0I#>uY>;SE#Otpc-8S9I|1>m0qlYbc0oBaeH)pwMLwm_@Vji)h#69qvFOj-$UZH; zK5%eSb6b_;F!`sRQqN>j$W}J-B-V^b_Bkd83jr5^Fslo2S)E*F2lUT8#r{9i{~2le z8AWQlBDGDC)(WJlZIaY>X-b2(7mdsdrdh=MY@$xTw}Spw>CC)+MO!iT=MEjRI8-^rQ1%dw_$NAK-K8XC_E~q67 zY8kH@)^jI?=KR!9W_FuBE ze|QsKJ4H1(Ep2d$XrzSf1CAkez#)v{7+Q-P!8y3jc~PBnP~Btt$4`Dc|JCZ>-M4bE zCg$nvyUWqH($=Ti-luvn)&DLBZ;EhXHNUW$31}dJ`PdvhABl!pRpTcLJ2M|A#-Jy;D;EvGV6u2)C2>P}D+hu8h-UZUsc1dan+C)m% zw<%Iup?`JCDRs&Tb@B;yVkM`8qBhd$_Qj3>Csl~d`zeQi+;8c2%jLV6%x-`O z0eu!^bkj_mY((JOss1z12{O;|ndi97bC?luS!cESmmvfM(kRlj4hnjtrnbsbPs>tI zDb_>zr}a`!8De!H`Giq&JFtmw1x~B>I69YlGM96Y&BL~ZD}wxPWnQ~H z?+l-N4Un8GlqcAK=>H;F-%V1G1$Tkqz|zl}#J7VHp$))3YQJrClWSD7dsK^CbdyW; zK9}f5*Qf^9r46o28eJnAoWu42hcL)~w|(edpm|;I7+R;X|Fte~eiqd_;Sms2=Ng15 zfaZ?C`j>w#aH0CI9^}7ku>VdMp9+Ts<#zMSZ9FP$zu(~a;R?r(R}T1Yo$dF@Oz?g{ z0-6EizZaelzp!55SI<-Z*HZiMT?t_P=_6o%9bgyi0AywrnNcnMY_;N(P=V#37kk}x zpQarF6n{pY6RG`B)9F!0b5;st8v&bk1|Zo6w*aKhWcSAZAG7~h0;7{(&>IDPvi?si z*2DN~^?w5TH%@K^{o+pn`!)L=RySHCpEgeIlxAIJ^X{_wH`szpf`V>o{#i*rb|qg0 z1djmlWc@!{|3&^!#(81dS?krO!0_;Wz%jbXep$0ybhCRj{@zdZAN7m=U6%Yt|9k91 zaWBCB|4RQZ&^+uv6+is{NA};p+R4A##lOlWpo-3a7b5Mm!V&tPU2OARy3K?*>tUYO z@AzANpK38JlUdXV;PwDE08fE>=%4r7{Yd}t|F!-Py#-j$TEJl1yP%w%zLTB0Q!+MK zK5C}Gm<_kt4OjTW3tZtvX2Vss@Cu)c<+)2tP7l!PpJZGlSouotVd+9}H-pG0 zb^%~HEUjC-{(>U;?2zRLz~JZ>FfgXYEv9AQ@_p{h8r`Vnr?@O_phPyhENOHK-wPbW z_5g>_-IQMcpUwrGgJJ)%>{X*#|HAxtFK|W(G-$W0|4!f>SOEt3R@r*jz{97HfG=0{ z8~T;0!+Royk=SyG6#Lduu_T}lFhMnd3#jG;sx{8fUe>1`@gL3n7molK|6PpNE|Eti zAb1>LIqcglqHi`y9L7qGtU^9!}*f~J5q!I`ckMb!e_%v)b zJP*%Dkd631&BGUGv`f?4CF$)N@k9Ug^>gXpHvR~(PC99obW)Lf`7!-p;g;g;nKPxe*MJGVauDruk^oc|Ihk&iPDJwIrZ-nfcQW3uUY>> z2owv!aCo5q0Nes7_)v~ah5@sS9A;$q|7ekg>qkZd-jSNvOYJ`p&)zPcvz-a3rS$5* zMx+0F&Ueof^uJ)2(1SweWAS&VbaJ8m>wJmbyI3f}9-J3)p>-efEF++_834>YBF+8R ziq|%=X`M_uvW~k1>F1?sXJzT`>*`G6|GEUE)+KrQQE%lOqWzBKZwh4F^{$1GSg z5%$`_c8Qt?hv6+z4~ORpQl+*n7yPon_K52-42I zX#JmkA^MkT^zZuW^p9Jh(#f~V8P3m_2{xZZ>BCEb{!wz7VI-EW=HJ8`YW45^*Yv-c ze7)IbLePNm-ckdL7kFiLAN3p~pxM|fb{HfZHbyx+Mio^iU9%4>V!{jre9p+zJ5`yd zfjr|3(E2~pG&}+j{GmLu|62e5v_1_1owQCk2&@uM17X1fuIRrEiZpIQ+nP(HunV=R zN&YpGca_P#40>n2z4o6j0VDYb4nLcE0ijL?&w}h*DEw%Ygn-iVcb3(@y{vvn>;d2& z(?VIk9}HYZaf{yfJpO;JBYgx=`|rG{#wn=UF|gV$;1?{uPXLCFqYZ3^3B+`jS^Gy~ zY-2d+L-jacvELq{e;rv|Mi!Topk_+I9>Dn5F|hv&Yw!qQY5e~&|KCTm?Q429nO?1& zlmWy>{lp5@->*>j=;(C+ea;ck>0hV+=akHw_jU&LBn2W)sn4SmvHQEGpU*X(y-aU; zy&|p&vray(8`~j)1T$hpezc@w3GB3VeJhZsv?`O^)XArfl8ynh#6v)ui%w*h*^-B3 z<4;V{9XS6i0zMlqF@@Nef0g7v%6Z74J-Z+I|J44I3`Bbn>c2!XuL{$8WGP)139Uop znue`t9uae3c+3I!*cLD-rU|$&r%>Zh{eK$#q&yb?aSq=LoI>^h$I#utKCF%sQfH4W zpr9K2fa(GMHFgW@Y!{T<%*eL+F3Du@1i;Jm0LzOIHA6}%F1k=6lc^09BPQt0iI>gK zVFLHEfqTWl`v4oX8<3!Sz#tHWN5Dc%0cu$~1<&gMH79USG{XRr5x<(n>pxK9YQJ9K~5YMRpqo#?6fH?muV6^(* zaEC3_>L2AvpHcsq4qt=*<;fSU;!nS|V&90^rr|M%hQ%Cuf%+d1R5QT8+HPTutzTV# z=zm&<_2hVCr}qG|sCzdQJi3Y^sa&paq#X5y+ACG&vw=YWK@F1NCQ0yqHmDvvi~f=4 zuhqZVka6I(*BpLya=QPb91jc;%Za5TJwu_XjnIC$*nN!Zn?*1L6OWZl8qJN>w4?Y^p8I>aCP$sF}vT1X&kuX_`nrM z2d`)bkK2FuWliqUO#`F$xkWZomNbBYOZK`h*=xU~(LSQFUpQqzXyt&=UACdMwjp)4 zi|T9x>TEp6+72^$`#a^A%Xyy)&cBKc zY2<<%#Q_v10BH}qNnjn&`2Te*b^fb4-x}Vhj`ykId@EVx{L^CQrN&<@2ST|XKv4RZ zFVMZ}Gb4aqjjTj2G&DDS|4YNM-ZqD zGDtaOwf2x@!cn7)i-2r<2xu?k4VT%1>s0>*n#dk{-1p(~y7yulT;oo-#T|dD{+I3>7}*H4;&)%N$8E{p0ZaA)s|bo+=uW%P zivA%r{X^>d2SNY!{by&|ejQ=)!A!ONP`QNzdJnh_MYH(lL=(ZG(fPJn@_G9JO zF=DqvM18;TI?z9?7TEf3wDT>onHq2N?Fy4IUIuS{uXY|Iw|0}7*b0>f)aF0M6_@Fm zC{1kSqZdf0WePmD5r1TOHZUO#%;E+va1S8J_SYo*Bj=wWCxI^IA`ri-z4~gD8G-{7Ka^9BibB)~Zx}?cz zNuymvy=_FDRah0UrEbqIThBbZdAZi(1Fgo+R}XkgYGkAFbN+k?^ehIL*bk9>7EL^N z5g#}?`$$kDS=>N^_Yyko-TgHE3w&$ERR8si_iomsO89Mw=(A*GpnyOBR^2=L%m`>| zMzI1zbD@!i%;jDApmB;1XDUAPm3_Zd;t{X#&M;iG$sn@QAoZMHW|y$^K43T9095~I zPoQngq_zCL_Fo(Sf&NjR{h}cA65z6KYPim4T{lTO+b{m~z*R>^t)R*u8GCSe>_PVx zhuv3T{(BH0^M``q|8hirkonf+y0j5#pDs)GxP;d`g;Wg)*lO!nY&AR4YF2{T1b<*K z>`VQjU#JF*RQ4Y#*0&JI)PG)4oNgy(RD;GFj+rN(nnir~!uT_bHR7lGZy-T?C~*F% z|4;XPQR7eTKaKyu{}=dF^9!)&rIw$*S@L0|_#I!dObYtUwbdQSUl{>jt`zDUiXGgg zqdwCA=zE(fVP*?bWLP`S>|(e52XH0Vz%TlL-1(vY&(HctJ&G<=-vuP+F3Gtk%)BAW zxNaNYJ}B_11`(KwM0 z3EfM@PxX&S022Ox(Z6>7i=B^*AKad5)_WH_e-}HaQt(Z-e9%`iXWhp3KOXXb#=oLF z054YvOs#}=uBsuUEk2%MG9y}=-7UeY?&kjhuH-uSQ~k5F69=vK2}tHGph)Xcr*=E8 zX&t%(`ad!}=HRfH1H)Fd42|ve_6J7o1#S`5z;RKjL(sPVJ|)%*if!j**v(Gr_x%dX zFT*V+2APbRYy94H{effjTt`a`EC7~SH6cwJ%zwr|QUg<&k%fFxw0v%f&=(nQEzIKI z>;G5&e{cL}VLj_t&m!%4emReRj?+rS6IV(4jSySB^7bOnc&fU${nZgbNgqQecfIkm zBt_T6)ZzIrV2f`8QiNN8cBTB))}f`Yi?$C9+>XM_&I`9XEi7^N%X9Y4 zb@j<~U6AfHYbEIabvQ8pXo1;>o`xg8HW)TZ-{pNh`(bkP0oq^=#7}F}{nbCT@T@>+ zG-|Txm^s2Zo5;dOZc!s2vJYWTjsFAZ=PCNvtpC!@zkYjIuS#a_4)K&s{ZGS`Bc|e( zM5VI7dPKV4>vJQ3#WHlS5RaZJU42NLa+=wCkKJ-dSkeQ?#v7C(2}h%5Io} z!%%%Yce%bHpoLG-w)>@J4#?s57+FXr=SXIju?TpEv~Zz&1Yy-&$Zit6kBa|S^WRz$ zP)h~q&ocR+t{1bDexY-%I^*h8Ff3@zH( zt@k*p|4ZPR^?wbw0H1LWn9q)}n7+hx=vWh{q2>eMvlu+q)a^YZ=ePCkhs&+q6*dF) zYzL}soMmc#Kp#C=t9ohrS6bNv$+!99SruFWqW$oEp#Pd*>mQR}ZT#nV`uDCO^Q#3O z6_R;7loO&19Y?Axo&Mfn>wde>jezQ{Pc6LG=tWnOVoZ1+$~WDXZMrQgxdUiddfJ%& ziT;l^{{h>6uMm{FP3<;`+6jaz12m)fP1eopI_G{fq5;34j`%bQ7w;B_)e1uPa*Ow~ zi?CiEb) zxQSiVz##I!7)tclwC_ja^3p64D6%hW2$Q8dW$W9?#vhr@Kd@Wxuv_o4c(M5&v*{WjCATP=_z&4| z9q=2j3O8I4=U7tu1$@y6>z(3?YBDqYgQX0%&WxA$CmeoZz{YbVvV7A>w@RQkmpP~A{0($jN zYd!#E!BPE-He8Y9Uzg?F648QJ?ZS2Y`b`bB{>HyAoH|sB4oX4;OZ^$?fCL@};?P5q zutR+KK{osVL-mi9uRT=%Ay3plo&S=VXkb@rI6laF%w(mtV_!Hm-7&nt5m1i)LjUu5 zvK70<1vdmGciAlunJqt%E%yjjKDf(lyahW{8 zz(W6sbmfWHhh|ohG?Czo(v)r<{k4z3}84g%SG! zEI$F%`0sn9f7}Rr@d#j${0|oG0nDOW%A9&;_HOli^N@@o(ldV{$EN#`zB2;qkz@7V z{e)k0l*zj*F1aDwd`-0V4qpoWKOmdwE%3AW@#2yGkpg{<*+BKrzHP zBs`SfW4BS~M`Qn~=YwijwBVK2|EDRSH=%#J|10MP$-F68ds@DvS}`q7Wo|Dwwtf-E z_jf--WI90o?li@OU_sDse$ieo{2&m7?+3ruKlT6VwnrF${2km#3EBg+E|cQh4CUlh zsm)-Co+&33|J}pV{eIsV0R%=wXfAAEB3W52N!-sBUS>*e^P3+ExBQpe_5)LTo7r}o zY`H@=L;3drTXF|z^Bm>b#G@{Dn`$*M0U-ylZqemgM8>Rd{NjfW= z1XiPfr*P>Jz=t&hCSo7ZxIp_EDt;RIVHd;UZ^S|vYW^cNh(mVVT#ET556g)&g)05N zb85OH`THY)Whp(k5kQo1P?&m}ExE~TzRPWS$Z!3Lh5onQVYc3RT>o4#R)p{JCATO= zw*g8$lY+~FjPv58PPuQc{s-U7UEcZo2ln?rfs-hNdZywblcaO=L|z-o;(92YUwQ~| z;Z1Vo~{LVI#Y+fuFex7>=4?^wx*GO!4;*O!o1N*`gLzHow43rB-t6Xlb_*u}f)mX^q7z-S_3|I6 z@}I7M+yY$DeV{1138V$r0eaA5le;3W&N#F{_0e?X!=MrB>m4DS7*=LwwnOzt&yY`! zg{m2Z_n)eN8vkLi^ChH#h4@3E{{|HQ!HyWlr;%N-NA<;8fc#Y~j_X!?U+HQDT`=u4knDV7A()NE%p9mK-3F2bd^|_AYp2|7i$Rv+}Er z0yW__;lfe;s*YV$$puvke5-_B+f9ak2>L?)(qA4B-7o%r1Q47T8=6b39L@61gXhw} zwD>*{6j1$h8R*{9rI@kIXyk`7E4$x+(X0Q7M5(VZvQ&QPsq`(81nqo&{iEP#6&F}3 z@~IGcZZR74KG5m^)nCV#`i-2@Q2D8s;)_7C{YOgq50o8n{vR@M{vWshaQ+bj-E?0A zo&pE~-2x>4Cds>L5maD5ccsd4_)9(7=lXEhOm z`%f2t8`#jjeCTct%U(W>0?!JwFG5Ww^ojhX=Q@4eo1bL_bo!^x&(HpkPXEs$nm6b@ zoUyfDP_8g}Ci&>|a*1DikYCv>ANje`azGzRgI8G$ zFti&e{w9I-+lyj8WJwDGK5SGIAW++8m*n{diT<%u;Y@7wf(zAQ8~>925%cWfS0CWx_REHkSD0A$k(j5Rm4nfM!J_Yy ziT{3@>hMVaOjPr8>0jbmCi`x^p3MNYmF;6=rhEA&i~wf7s7@~)FvMVGz5bd8Qt>}1 zWj|4NJRm!;?E859hbF(#{0A%nZ@Nos{ukfi^L_xz?;_Qo`3Oz=;R9*8hS&NB(Oh8k zk-zzOYb1W;D+Qcnu;-U_+k;mDkN13H9fJ8P?dgK3E{|7aH8Z@f_&16wC@oN&! zDl!;1Pd)NW?3V`){#Kx8^5PHi`9D#sf8#HrE#~D*kg*m)eI9;!6Bm7mjXcRl9{Ushhc=PW782A# zd|O1*^Nrs9N^kI(=RXSFZ~OyB0EK;|c7tW_e67wqugdQt<^KijjvoPy|Ll11Tl=rs z|AMd&LFRwqJz%uF4v6gr3k@y)yv*_|84?q>w@e4UBcGiu@!QEqw6M`9*yv+i^ik-a zi^3ED#vk#Y7P16RQ8VH~8j%0Ik01poqLD0WBz}z|?`rk@QpIOcQnUUD4!@EE*L}&W z9syouD0h8NK5mwB;|;~8o22|F!0q@EFjW7)iGSYL?EgakgGT=a4@tp8%iw&#tBqdo zuHMH7uK$=X?LM9&TCf=v`{C_yF>UO!(`?j9HtH}J-M~ie>y3YE^&f_`2iyXh{AcKY z$vzT*R@ZxE^UI7qHt2oiFObN1vE=d3*S&sYMu1lv%LacaAMYXGen(b%hwS_Tusa^G zNPeLD|MAK3|Bd$uQb3Cz0+Vlp0oNDO;2B1wPywUwB8{iV3Kmt9@MbRRm|)o{ZrKTD z*)azGPxOBHLcjKZsM$vf9Lk<>p%mKT$frvBeX`NVUaG;L(49MfqrT`HBb7JuM0h<@ z+3-(glNQK!-IMORM|Rx>?DikPQ}vIUKO64@X46ApF#0RNzV199Tpcv9P?%T%nOA{q z;TCpD6Nx^;M;{YLALo`GCCd+!We1t)X2gG(rIg%-D228C8+qMzC#4+$PR~R#>?6r%UecZSB{2TG9s*{^AL^g3|Na0N4eEC$ zfj*&sPGB@_JP`S969w*Kq7RUmBkb~{5I?)@$Rqu?Fx3C2$)8&NGfNtQDExpp>>wZ1 z#0BgZ&)+Pcoh~0eOK#p@tZ%H7${RcaoSw0G=veVYPjSUVQ3b^RKLLYj?+&f~|Be5T z;HM`4VKX*DKA_yn-1>hrq)utJH=^fiE8gt`s;NbF&<@+gVbD1Z4O0$~4< z`G(1FB-X+(|7`+n~ zxco=5^M8X!`lnNXC;R_e`(J_-(7Sr?e*svr?4=*;)4u@yOhpOmRp(HuHZ87KQi2O#;HuW>HA9VBucgw_f$-GUNBB$ouOWxIBHt z-;{rW{-wh{lzui}R`wrh8FHTg4?yGxw}58->o@UF?fw^y|6g(s32!v#?TdMUlfKT) zPy&h4%zd26u+KVbk^2A>aR|_U zb^*0g|1!nG?eY;{OZ7~IeWO~-nZfi>U%2mG1-@6!1% z)&DJEF(m--DE<0csv6R^jjTYfXEyR{llP{Ph-M&+IRO4p{|EtL@fWuMwmlvMw4R}V zy?nt&_53{f;0Y3?AuoE(J9ql1V&1I75@2u0&@rm(aZ_fHkfle+(!*?I3qa)uTKvJUh4>sW{nW4jJD(wi>CL*xy0dxe2vGeG z`9L*(j(YPA)s~xoMgPmotd^IdUog68!4yCBn_kX8ATlqIDkN6UW_|@GejBulxqm_b zjBhjJ-E8`?Prp$U6vkFB=U{c8+UG`q6U)RVHj+VOl&MD)>Brf!2SBjnA@~FPudRPV zU7(VCVpRJqylOmtmf5=#gldCVe1-yJ3)R?fYSoC2w8pR(P0a@4r45z1&}F?&c%+vP%vE&SwwMA2iO;ai~Doz~VK_@%4PY(AdgqQHEt`KH2{NQOf@( zZh=43{}24eYe3uiS{hy^U$l|4c70_hAW`WX_IFf$FkKYYB8-B2(~es}5Z43<#J{rj zk^Zsrb>K1mAJgc+UJ$v5U2+I;KD&XQ>wAX%odgnH%;%L|z&`Xv0+oU3qj0+GHcn!>#Hojb2!+;m^@`w`$3dd6eFF&aOM+xEWz6+hL#W(&ZR^-uSI2}*Da z+!JiL4Vdh1lGP>qVxemIIK+Z}{}nI%Co;FuCUaM-eTzs`2NT`FtvJK2=wu;&s{g}4 zGxPne{<$U4KYau+k%x%?F<|+XH$d&L7k-4g5B#T$04o&B`Z>y+hAIlr18&O?==LJm z{*!R~e>jvqFTIb-&*=Qcp!ng>`(HNQ<%=HzVbOKKgKX>pto$-G_(S9W%(6p(i$2Il9poYp zlCVQeNQ=a4Cr~>M0jxmyQjb~p;eB}o@Z9GWDuJ=NLCz7tm)zkt-WQktN3#9Dg33we7U2f}bbiN~7G+Tf-q387-uIMKqEWQF5>>bOyU>Ld8A|O-d`tD0TSy_KqgSW=Z zr>^0axAHM3g>i=jaYwjSrvO=X0RV6eVuBcJI|BY0oCwK{arg)(cA1fR2xoYxK$%2i{ zvUV=ERj}#=zv?)%l0q~vv4=Eh_5ZW|KgdQOV51JOsDHTlFc+{#Z(=aO2ZC3>a@WTt z@h?0)Mj$l)#tX2B>XhCWZoexATYnU9`LAH>f7xySWwxR&=%fA@=zp~FCJ=1656~T( z6yBBQUQlFr=zZaBXl*N1zxeX_=*KEm>%sGp2bKxZrDa(M6Wh+OZsS%X;B$l$cZ`Cx zhuEVq{u=vFGe5Qd4}&lf+;T6fA%907(G=)F502y)KyMOTDd ze-M`bB;NKDZUMp8pO|ewF|j(q7MTsBFqgal~F>)Db?mlV8!!uRP7IJVjIe!4vf#LzDjz0z%FY2|dgP@00j! zm(0nL_j3hL917hJ|BWNSup%QfAVtI9l+%KZ|KYa%AJMj-B-_yZ4pGntWGkG11V1&& zZ^(bcEMU`ZY0-TkF1Rf&xP_i~Bf*T2^P zIYLu_Vh%Ae2k9y>R(`_|ae)WK^GgjUc%e7VKl@_oj{c>MfaN!Ht*3emGcJ-%|2J3q zU%`$ad3p;V1d7G4+hjA!KEwE9^7{keH}(Kg(QVO&yIk%)Hv7Iby;GHXNI89p+{#XD z@M0=rsjVCg`nw5c<&%(u{IZk6Rc*pGt)hfeg7_0;%@ML1p3iX&cyW~Aaj@b97ju+u z0a$jJUv>ypP)NiHL0GdqxJofIQQhB8X=U@$#!vUb|LhU4m^9Vun>pgNbL__diRNGY z_J@Mf9|YU(aZlF&C4S>2VbN{jhC5XMIrk(P=agwj6|!YTgA`ae!q9LMG_!SW-5W%L%nnlA}ICS2U0@ZYAK5(n`s%wNSK z-9K9g|JI{7=x=9aXKxr&X_#|Hgnp(acLnfsw%idsTK{6u|BJQ&)Am38x&QTbvf&0P zyh-wJkh~k>hzk9$7t7z8^g>3_cus;@V37!$7MCAmR-Rap`_F+-8AWA$s4)j#H|Ex!x2^GoO2dcDl)pvbM61GEFaGNW>gOxAjzp?E|&&eXnttQPdeSgC9o(j6_N({|_EMOC0V~>$lZEQk2 zm)Oq4YmEPs?LUqGa4{zVv*Iwb;t&ZxK!RJ8lUJIL`ciE>nC3aWmO2&Bd;YrjzwQx` zoA*=ocaj8e5#`-NpZ7=lzx}NG&%8|5cgdov`hV+XKJM%1Jsb2`l$u&m!gc{B?j%{& zs?mQ3lh8(;pFh(7X)fk8^iNhCB;hUSWT8SYfWc$cR=Ng8&wCyIz3=BlVqPLseiyDE zRUt_|K{nrl&(Cdo$YJv%rURSrk*zl=B^ruuk_|VR4cC|rSNXi_f}9&%_H~kVRg`eT zIIP%UP8=K$!SmF}<)m`s39|vW;t&w5X%)t|aS0u4LMId7M&h5Mf6Xcw6MK@0Jw=rt z+NAa=HuFeTkN8}q(C1%kk-C4clK#nOuA1m&5|k@TY$2O&vdH=0^b@z~M|Sgl7IWd! z>lCg2H)!-W9!wvndk*CdY;|2oLpr-BOH)5CxIxT zO$_HJzJrPHB!8xV5_^(@o?k)xOguAeXDwH|z1)=SfASU99s3`RfMUovg9)Cp$Wngu zEe>nGn|@+9{m5`L|fi0`e|%S>58KHfcnq zfy+pJ$Dx1pO^^N!%_h`V{Z!6F)M3tsQ*L2FaAH40Dc|+S#_KMYW=`X^@Nk37;IO762I z*TC=f&lcWbkqcCKjVZXu9*fvqM%BNf0=CPM7gnX#rIGW5&3D==)bks`KR;W z$L+s1|3~vTx;idtQp`a0$yRpfI z6ruCWf0&Iw@f%S5;ZCprUwnfU)AcVXpWASi+i+P}cu88&Bg((ZBBB|{l%b)_&#aqbA9w1tG5pYQzY*IVbf5Pd<^#9oU*Gi;7pCAa6g2lBY zxW?eiAk$A~qq^N+IBVUn=te+00vg3~%HbcG&0CJVXlBD*rWotL51EY*_@X=DSNezL zFSyPXUf~KaLI2`{%R=Zs_XeNQrH-mmg`!NZB_K~J6UxcdA`2(!@JR*{m3onN?3xQe zn0Owri5-AR&=`Mh@aIwdlUaEJu-Nts{YN9u`LHOkTpUoYdha{+pbvy-%%}UK8-c$! z0umc1{dXqGJQLWGyFi=yhD8CoF7WvLx8ORHe~l}+#20k)1(yYdmVX$gqpg88V5Y-D4TPZ2+l*A6eB(wuf6}scCcw$nF!+yKW~qs_q3bBs=ZnQFPHFVtMv~f|u77RvCxSoF|4FL< z)yHVJub6|PMZ19B;L-YSBe8h>{3ojW4c!Plbp#|91B}N_Q_qMY1wW9&`|Rdh0FDrN z%>G~382_s%2Smxgf>kgk_cF=s0et3lpdK_v&uKVHumAi_vXP$~dZ)@GwvzRSne`_H zDVO+^9+KPv7=%4Rul>g(pq;Em{ts?}lgyf9?CN8JRY&=_6C|>W4ezj=vj&{(CPm#51sB8-+&Q7JqL+_iEPM6`l}DA5{{7#w*a&0I-vOv$bakg{~sBD zYX9N?(w*cbthog^d90nl^rQCl`mZ=coC|Lx#S^hMw6nwDZ$5{>|j#4H$Xd zDfERAKt`xoZ6F&oR)5t2_1dG)um6iA5>%=RR68Cy85khEM7g ztj8@t_0Rp0{^|bT$Mr9WJY?)sXylP0RqBDqXBK^7+;qqAW{iMl7R*U3Y^`U8n|rO+ z_CIAxZi1)y|JOA3|1zck!rUHVP7j-L4d^eg*N?8zA2!yYzk|^P52M*}vhYe~T{n|- zkxN0Ow3|se14wc^1ry<l0U1C$NFqrvj9utr2pQHLe%g3Ka!5t~M-W_L zHf)UPAYGDk-;~T7byNbmQr~Ta-rEx;$?ZU!`HbWr8Wg4e|8L?y$bX>mA3paAmwScH zx(dXpr^Klz6d}b*|15b_wG2(W;#-;Iii8} z>K~;+DcP3+pVh%67;KhYs>mMOdEPYpTaQWCK!d`cL9 zN*sS0l@A4L+JvzuMUjW)^NUR0os8~{e}3G$cj!jo#f<>ga82ec1)A{YRa*89;n2bx zn%jZ)!uW;!D+Kz_?goO49u1cT8JC%~>m=<4lX{t5kL)<;{~U6JesBLD=^q&pr?Hz@ z8h;#>54lxsqUe+I(4)%lQ}wOwm8RA&?#y(bq#J=h9|7d>=zshj5N34)CJ$u~Z!v{f z0zeiJc79y}n)P2z{tvbP7Xg=r9g&y0ObVNRiIR4aP3>maQ?sw(_x8VoBy}+BFa>Cb z+atjgcx4+K(xnD+Kuuxjh=L67&ejx(v9C^L)lxF8us@g6|cof6%M{OC%TIUbv#s|0Oo#0&W2=y^BlhruwJ10L1@f{WA$?krB44`iSawnnaZEln(Qw3gh26{THL1Jax)J!}5ipps9B}DpNd7fZ!9__ymw@j7!WMYU zg=zkq#`s^RDbRr40+&cu4<)0Ar1voC7uocS3~mAX6zIY&Kz?oinZ!0g)}0~i&eHad zaYv<*jq1fUvJbt4G9~(A{PE%G{#7>uFLeYAz77J&TVV693iEq#3kYEU3vXg0-7x-I`%lIHB>nfU0@KYe?acC1 zOw9bJ&F2nxGV0)lRY>7D;RoBfCL zpVCdR{=5DRS>MTE+j~lzAfXE|tI*!=u*rf9n;CKP0mGks5W1i0M&LD#fKLCfY2bBV z+b2fA^sVr>z=5qbWQc=<=x-|fEVa@)>-uRC;^8dT|590rn zw2LGaU=@t6f3YcNxRf)3c2~K3-mDSyPb~ly>t1IqKM;o z&-CohzSseF5eSh+i4hZ`Bu0&j4jOMJCd5RIW)B1t@o`cQup!KdD6bXRo!!-luf#_@ zc=2GO@iHNbh(=hJ$LzurZv%n|){dar@um8b!MEYYFN_Yv}*xBOP znd0bK|HyfIBh3COeA-FZ-V->NKJgmPQtuM^FwdJjo6_91Ik4!Vr7_L`=c~^y5q>%(tG%YcdEGO zRR7z@a1PvcKTi45-fNo+QQdq8y6?QV^4K$dTMqQ>IbI(5ojwct!N;r*%j`Om~`apHV&;#_Hbrel28Z_E{Nj!t`rfAtQW^md-~ z-}rvXhD|sZ!ic4h;y~;`v9nz2UDUh&@qx|t{;iXpdyjV>IN?v8@h7JX6BlvPEC1=q zKVJWN-fzs{7Vz;Z(9xOFp{efuKb7l0`Y(OaF*M${_8y#ZT*-+83&#Qcp~~;->$&5B z5Jr z{iXA*W0mdS-TLb1E1uhf#ox19Uf$nosa!8m2Z~*Ned{(ZTEA)8&`zAoU;kwJo1fjX z^UGzsz8c)NZ*XXM@X4149)7-m-6Q3`B^}-JUA+r*o~7Gv2W0)beUVaeKpYSU!~t(DL-vszW))N6Pa+qjqv~RGX)Xa_Onua8B*`fznaA z?rtKEm%>dP9*=I<=uOHCr-s0~J>!E(ZBB7)Td7&9$MFehj^fBq;yhk0Y~q@@i9=}` zH}zcH#G#bA?l7)-omr{!l{gH+&jiP{;L`Fm$441FUv@IsNiaNF>j)N7N@Z68#1cUPUPXaAm{SK84@n(Q56bB>iKyM0xb3&Pcr=D!{%y8 z%*%!cMoej)OB3G_kl<>}#1}jD+7rVlP3TnzZOo4y)HEMi+{{@V!L|n>>M>Ed79L(F z*K1Zs*<|h)-F+mj@e}rgH?0aZ2UpA0J*9%sJhbY~vY{Fq@h^zG#5UPpZ5H42nse-5tffnH@OSbRXAkB6pWtfgF} zPvK1?tD8(x4<6aCGFQ!&Ylxqs4=7?h&sW5cIA@ZWZtC2;)}p0LqmSmPrA`jc<3qjV zW0#JDavnBP*Yr~RdAZ9zTi=$WdrppVb9o!i{m#LI7VG#@ufOOvYps)mo2OvT_!PLN zo}#se=Ii|2wK+xmL({!^p^3WZ1!<2h)PvmIvAHDlDLmu}^qiX$>2vXv%`MWWY;Kwt z(l$Thyswd-E*uAQbn-g5SF5+xGj~s~-nXGo~JA>#l5 literal 133143 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 From b529dfa0ea77774deb8a418dae6c60cc5e8b07b2 Mon Sep 17 00:00:00 2001 From: F0nzy Date: Sun, 23 Jun 2019 21:17:23 +0000 Subject: [PATCH 128/134] Server info --- template/header.html | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/template/header.html b/template/header.html index 21afe79..d80f74a 100755 --- a/template/header.html +++ b/template/header.html @@ -16,6 +16,8 @@ + + @@ -55,7 +57,7 @@ - +
    @@ -80,7 +82,17 @@ This pool for home miners: Gpu, multiple CPU min DL: [300.000]
    Work together with another arionum.tk pools
    -
    +
    + Server Processor:
    + Server Memory:
    + Server Load:
    +
    +
    +
    +
    +
    +
    +
    From ba0e1c4f0c4861eba2f9b18192f8d31af7beb0fe Mon Sep 17 00:00:00 2001 From: F0nzy Date: Sun, 23 Jun 2019 21:18:00 +0000 Subject: [PATCH 129/134] Orphan handling --- update.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/update.php b/update.php index 135fece..3d4415c 100755 --- a/update.php +++ b/update.php @@ -97,9 +97,12 @@ function shut_down() //count orphans - $r = $db->run("SELECT * FROM blocks ORDER by height DESC LIMIT 100"); + $r = $db->run("SELECT * FROM blocks where orphan=0 ORDER by height DESC LIMIT 100"); foreach ($r as $x) { - if ($pool_config['keep_orphans'] == true) { + echo("Processing block height:".$x['height'].", orphan:".$x['orphan']." \n"); + if (($pool_config['keep_orphans'] == true) && ($x['orphan'] == 0)) { + echo("Updating block height:".$x['height'].", orphan:".$x['orphan']." \n"); + $f = file_get_contents($pool_config['node_url'].'/api.php?q=getBlock&height='.$x['height']); $g = json_decode($f, true); $oheight = $x['height']; @@ -124,6 +127,12 @@ function shut_down() ]; $db->run("UPDATE blocks SET orphan=1, miner = :miner where height = :height",$bind); + } else { + $bind = [ + ':height' => $x['height'] + ]; + + $db->run("UPDATE blocks SET orphan=-1 where height = :height",$bind); } } } @@ -131,3 +140,4 @@ function shut_down() + From b66de0c4fddb62323a4acfeca88a1450b6912695 Mon Sep 17 00:00:00 2001 From: F0nzy Date: Sun, 23 Jun 2019 21:24:45 +0000 Subject: [PATCH 130/134] Update new developments --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 7ea53d3..66305e8 100644 --- a/README.md +++ b/README.md @@ -8,11 +8,18 @@ Warning: because of additions to the config file, do not simply replace the php- ## Mining - Share count based on accepted share and pool min DL and networm maximum min DL rate - Multiple pool can work together, (eg. different min DL for Cpu, GPU or other mining settings, but same reward policy) +- Database updated with orphan info +- Poolsanity.php: improved peering to other pools (send and get infos) ## Utils - Update.php: calculate orphan blocks, and overwriter (stealer)'s alias or address +- Poolsanity.php: modified, to update PID every minute +- Poolsanity.service: Made a system service for poolsanity, copy to /etc/systemd/sytem +- getserverinfo.sh: update server resources +- services: system services for automated jobs (sanity, poolsanity, serverinfo) ## Display +- Show Server resources (CPU, Memory, Server load) - Show Orphans % (basen on last 100 block) - Show Orphan block overwriter ("stealer") - Expanded informations on main page (need to run /utils/getinfo.sh) @@ -23,6 +30,7 @@ Warning: because of additions to the config file, do not simply replace the php- - Added some icons, and header - Added links page (webpages, miners, wallets, pools...) - Added Cuby's web wallet link +- Added News info ### angelexevior's changes ### From ac42a7975f0b97718a493ae572d00396c5c8975d Mon Sep 17 00:00:00 2001 From: F0nzy Date: Sun, 23 Jun 2019 21:27:34 +0000 Subject: [PATCH 131/134] new file: poolsanity.service new file: serverinfo.html new file: showorphans.php new file: template/news.html new file: update-manual.php new file: utils/ServerinfoUpdate.service new file: utils/getserverinfo.sh new file: utils/plusinfo.js new file: utils/serverinfo.html new file: utils/serverinfo.js --- poolsanity.service | 27 +++++++ serverinfo.html | 10 +++ showorphans.php | 89 ++++++++++++++++++++ template/news.html | 35 ++++++++ update-manual.php | 144 +++++++++++++++++++++++++++++++++ utils/ServerinfoUpdate.service | 29 +++++++ utils/getserverinfo.sh | 96 ++++++++++++++++++++++ utils/plusinfo.js | 52 ++++++++++++ utils/serverinfo.html | 10 +++ utils/serverinfo.js | 6 ++ 10 files changed, 498 insertions(+) create mode 100644 poolsanity.service create mode 100644 serverinfo.html create mode 100755 showorphans.php create mode 100755 template/news.html create mode 100755 update-manual.php create mode 100644 utils/ServerinfoUpdate.service create mode 100755 utils/getserverinfo.sh create mode 100644 utils/plusinfo.js create mode 100644 utils/serverinfo.html create mode 100644 utils/serverinfo.js diff --git a/poolsanity.service b/poolsanity.service new file mode 100644 index 0000000..2717819 --- /dev/null +++ b/poolsanity.service @@ -0,0 +1,27 @@ +[Unit] +Description=mine.arionum.tk poolsanity service +#May your script needs MySQL or other services to run, eg. MySQL Memcached +Requires=mysqld.service +After=mysqld.service + +[Service] +User=root +Type=simple +TimeoutSec=0 +PIDFile=/var/run/poolsanity.php.pid +ExecStart=/usr/bin/php -f /var/www/mine.arionum.tk/poolsanity.php > /dev/null 2>/dev/null +#ExecStop=/bin/kill -HUP $MAINPID #It's the default you can change whats happens on stop command +#ExecReload=/bin/kill -HUP $MAINPID +KillMode=process + +#Restart=on-failure +Restart=always +RestartSec=30s + +#If you don't want to make toms of logs you can set it null if you sent a file or some other options it will send all php output to this one. +StandardOutput=/var/log/poolsanity.log +StandardError=/var/log/poolsanity.err + +[Install] +WantedBy=default.target + diff --git a/serverinfo.html b/serverinfo.html new file mode 100644 index 0000000..405d784 --- /dev/null +++ b/serverinfo.html @@ -0,0 +1,10 @@ +
    + Server Processor: 1 %
    + Server Memory: 10 %
    + Server Load: 3.75 %
    +
    +
    + #
    + #
    + #
    +
    diff --git a/showorphans.php b/showorphans.php new file mode 100755 index 0000000..03d4bd3 --- /dev/null +++ b/showorphans.php @@ -0,0 +1,89 @@ + 3600) { + system("rm -rf $pid112"); + } + die("\n\n### RUNNING ### -- PID: $pid112\n\n"); +} +system("touch $pid112"); +function shut_down() +{ + global $pid112; + system("rm -rf $pid112"); + echo "\n# ShutDown #\n"; +} + +register_shutdown_function('shut_down'); +############################################### + +set_time_limit(0); +if (PHP_SAPI !== 'cli') { + die('This should only be run as cli'); +} + +require_once __DIR__.'/db.php'; + +if ($pool_config['blocks_paid'] == null) { + die('Blocks Paid variable not set in config'); +} + +//count orphans + $r = $db->run("SELECT * FROM blocks ORDER by height DESC LIMIT 100"); + $oc = 0; + foreach ($r as $x) { + echo("Processing block height:".$x['height'].", orphan:".$x['orphan']." \n"); + if (($pool_config['keep_orphans'] == true) && ($x['orphan'] < 2)) { + echo("Updating block height:".$x['height'].", orphan:".$x['orphan']." \n"); + + $f = file_get_contents($pool_config['node_url'].'/api.php?q=getBlock&height='.$x['height']); + $g = json_decode($f, true); + $oheight = $x['height']; + + if ($g['data']['generator']) { + $x['generator'] = $g['data']['generator']; + if ( $pool_config['address'] != $g['data']['generator'] ) { + + //stealer alias + $fa = file_get_contents($pool_config['node_url'].'/api.php?q=getAlias&account='.$g['data']['generator']); + $ga = json_decode($fa, true); + + if ( trim($ga['data']) !== '' ){ + $x['stealer'] = $ga['data']; + }else{ + $x['stealer'] = $g['data']['generator']; + } + + $bind = [ + ':height' => $x['height'], + ':miner' => $x['stealer'] + ]; + + //$db->run("UPDATE blocks SET orphan=1, miner = :miner where height = :height",$bind); + $oc = $oc + 1; + echo("ORPHAN:".$x['height']." \n"); + } else { + $bind = [ + ':height' => $x['height'] + ]; + + //$db->run("UPDATE blocks SET orphan=-1 where height = :height",$bind); + } + } + } + } +echo("ORPHAN COUNT: $oc \n"); + + + + diff --git a/template/news.html b/template/news.html new file mode 100755 index 0000000..0f5d0a3 --- /dev/null +++ b/template/news.html @@ -0,0 +1,35 @@ +
    +
    +
    +
    + News: +
    + +
    + ⭐2019-06-24: Advanced server informations +
    +
    +
      +
    • Added server informations to pools header
    • +
    • Processor, Memory and server load percentage, and progress bar
    • +
    + Wish many blocks! 😊 +
    + +
    + ⭐2019-06-22: Reconfigured server, node and pools. +
    +
    +
      +
    • Now sync with other pools and to network is working fast. That cause minimal wrong (orphan) blocks, spread new block fastly.
    • +
    • Lowered min DLs, reduced server load (don't influence block founds, and shres)
    • +
    • Share validation moved to an another validation server (share works between each other)
    • +
    • Improved some node functions. Now work faster.
    • +
    + Wish happy mining! 😃 +
    + +
    +
    +
    + diff --git a/update-manual.php b/update-manual.php new file mode 100755 index 0000000..78d997a --- /dev/null +++ b/update-manual.php @@ -0,0 +1,144 @@ + 3600) { + system("rm -rf $pid112"); + } + die("\n\n### RUNNING ### -- PID: $pid112\n\n"); +} +system("touch $pid112"); +function shut_down() +{ + global $pid112; + system("rm -rf $pid112"); + echo "\n# ShutDown #\n"; +} + +register_shutdown_function('shut_down'); +############################################### + +set_time_limit(0); +if (PHP_SAPI !== 'cli') { + die('This should only be run as cli'); +} + +require_once __DIR__.'/db.php'; + +if ($pool_config['blocks_paid'] == null) { + die('Blocks Paid variable not set in config'); +} + +echo "\n----------------------------------------------------------------------------------\n"; +$current = $aro->single('SELECT height FROM blocks ORDER by height DESC LIMIT 1'); +echo "Current block $current\n"; + +$db->run('DELETE FROM miners WHERE historic + shares <= 50'); +$db->run('UPDATE miners + SET gpuhr = ( + SELECT SUM(gpuhr) + FROM workers + WHERE miner = miners.id AND updated > UNIX_TIMESTAMP() - 1000 + )'); +$db->run('UPDATE miners + SET hashrate = ( + SELECT SUM(hashrate) + FROM workers + WHERE miner = miners.id AND updated > UNIX_TIMESTAMP() - 1000 + )'); +//uit sanity + + $r = $db->run('SELECT * FROM miners WHERE historic + shares >0'); + $total_hr = 0; + $total_gpu = 0; + foreach ($r as $x) { + $thr = $db->row( + 'SELECT SUM(hashrate) AS cpu, SUM(gpuhr) AS gpu + FROM workers + WHERE miner = :m AND updated > UNIX_TIMESTAMP() - 1000', + [':m' => $x['id']] + ); + if ($x['historic'] / $thr['cpu'] < 2 || $x['historic'] / $thr['gpu'] < 2) { + $thr['cpu'] = 0; + $thr['gpu'] = 0; + } + $total_hr += $thr['cpu']; + $total_gpu += $thr['gpu']; + } + echo "Total hr: $total_hr, total gpuhr: $total_gpu\n"; + $db->run("UPDATE info SET val=:thr WHERE id='total_hash_rate'", [':thr' => $total_hr]); + $db->run("UPDATE info SET val=:thr WHERE id='total_gpu_hr'", [':thr' => $total_gpu]); + +//cleanup + +//$db->run('DELETE FROM miners WHERE shares=0 AND historic=0 AND updatedrun('DELETE FROM miners WHERE shares + historic <=50 AND updatedrun('DELETE FROM workers WHERE updatedrun( + 'UPDATE miners + SET pending = ( + SELECT SUM(val) + FROM payments + WHERE done = 0 AND payments.address = miners.id AND height >= :h + )', + [':h' => $current - $pool_config['blocks_paid']] +); + + +//count orphans + $r = $db->run("SELECT * FROM blocks ORDER by height DESC LIMIT 20"); + foreach ($r as $x) { + echo("Processing block height:".$x['height'].", orphan:".$x['orphan']." \n"); + if (($pool_config['keep_orphans'] == true) && ($x['orphan'] < 2)) { + echo("Updating block height:".$x['height'].", orphan:".$x['orphan']." \n"); + + $f = file_get_contents($pool_config['node_url'].'/api.php?q=getBlock&height='.$x['height']); + $g = json_decode($f, true); + $oheight = $x['height']; + + if ($g['data']['generator']) { + $x['generator'] = $g['data']['generator']; + if ( $pool_config['address'] != $g['data']['generator'] ) { + + //stealer alias + $fa = file_get_contents($pool_config['node_url'].'/api.php?q=getAlias&account='.$g['data']['generator']); + $ga = json_decode($fa, true); + + if ( trim($ga['data']) !== '' ){ + $x['stealer'] = $ga['data']; + }else{ + $x['stealer'] = $g['data']['generator']; + } + + $bind = [ + ':height' => $x['height'], + ':miner' => $x['stealer'] + ]; + + $db->run("UPDATE blocks SET orphan=1, miner = :miner where height = :height",$bind); + echo("Set ORPHAN:".$x['height']." \n"); + } else { + $bind = [ + ':height' => $x['height'] + ]; + + $db->run("UPDATE blocks SET orphan=-1 where height = :height",$bind); + } + } + } + } + + + + diff --git a/utils/ServerinfoUpdate.service b/utils/ServerinfoUpdate.service new file mode 100644 index 0000000..9d3865e --- /dev/null +++ b/utils/ServerinfoUpdate.service @@ -0,0 +1,29 @@ +#serverinfoUpdate.service + +[Unit] +Description=Serverinfo Update +#Requires=mysqld.service +After=network.target + +[Service] +User=root +Type=simple +TimeoutSec=0 +PIDFile=/var/run/ServerinfoUpdate.pid +ExecStart=/bin/bash /var/www/arionum.tk/utils/serverinfo.sh > /dev/null 2>/dev/null +#ExecStop=/bin/kill -HUP $MAINPID #It's the default you can change whats happens on stop command +#ExecReload=/bin/kill -HUP $MAINPID +KillMode=process + +#Restart=on-failure +Restart=always +RestartSec=30s + +#If you don't want to make toms of logs you can set it null if you sent a file or some other options it will send all php output to this one. +StandardOutput=/var/log/ServerinfoUpdate.log +StandardError=/var/log/ServerinfoUpdate.err + +[Install] +WantedBy=default.target + + diff --git a/utils/getserverinfo.sh b/utils/getserverinfo.sh new file mode 100755 index 0000000..944b77a --- /dev/null +++ b/utils/getserverinfo.sh @@ -0,0 +1,96 @@ +#Gather Server info + +dir=/var/www/arionum.tk/utils/ +cd $dir + +PREV_TOTAL=0 +PREV_IDLE=0 + +while true; do + + ############## CPU INFO ############# + CPU=(`cat /proc/stat | grep '^cpu '`) # Get the total CPU statistics. + unset CPU[0] # Discard the "cpu" prefix. + IDLE=${CPU[4]} # Get the idle CPU time. + + # Calculate the total CPU time. + TOTAL=0 + + for VALUE in "${CPU[@]:0:4}"; do + let "TOTAL=$TOTAL+$VALUE" + done + + # Calculate the CPU usage since we last checked. + let "DIFF_IDLE=$IDLE-$PREV_IDLE" + let "DIFF_TOTAL=$TOTAL-$PREV_TOTAL" + let "DIFF_USAGE=(1000*($DIFF_TOTAL-$DIFF_IDLE)/$DIFF_TOTAL+5)/10" + CPUUSAGE=$(( DIFF_USAGE )); + #echo -en "\rCPU: $DIFF_USAGE% \b\b" + + # Remember the total and idle CPU times for the next check. + PREV_TOTAL="$TOTAL" + PREV_IDLE="$IDLE" + + ############## MEMORY INFO ############# + MEM=(`cat /proc/meminfo | grep Mem`) # Get the total MEM. + unset MEM[0] # Discard the "mem" prefix. + TotalMEM=${MEM[1]} # Get the MEM. + FreeMEM=${MEM[4]} + AvailMEM=${MEM[7]} + UsedMEM=$(( (100 * ($TotalMEM - $FreeMEM) / $TotalMEM) )); + + LOAD=(`uptime`) # Get the serverLOAD. + L1M=${LOAD[9]/,/} # Get the MEMs. + L5M=${LOAD[10]/,/} + L15M=${LOAD[11]/,/} + L1P=$(echo "scale=2; (($L1M * 100)/4)" | bc -l); + L5P=$(echo "scale=2; (($L5M * 100)/4)" | bc -l); + L15P=$(echo "scale=2; (($L15M * 100)/4)" | bc -l); + #echo -en "\r Load 1m: $L1M, Load 5m: $L5M, Load 15m: $L15M, Load 1 percent: $L1PERCENT \b\b" + + #Write to file + echo "var srv_cpu=$CPUUSAGE;" > serverinfo.js + echo "var srv_mem=$UsedMEM;" >> serverinfo.js + echo "var srv_load=$L1P;" >> serverinfo.js + echo "var srv_load1m=$L1P;" >> serverinfo.js + echo "var srv_load5m=$L5P;" >> serverinfo.js + echo "var srv_load15m=$L15P;" >> serverinfo.js + + #spread file + cp serverinfo.js /var/www/mine-arionum.tk/utils + cp serverinfo.js /var/www/smallminers-arionum.tk/utils + cp serverinfo.js /var/www/bigminers-arionum.tk/utils + cp serverinfo.js /var/www/solo-arionum.tk/utils + cp serverinfo.js /var/www/pool-arionum.tk/utils + + #serverinfo.html + echo "
    " > serverinfo.html +# echo "" >> serverinfo.html + echo " Server Processor: $CPUUSAGE %
    " >> serverinfo.html + echo " Server Memory: $UsedMEM %
    " >> serverinfo.html + echo " Server Load: $L1P %
    " >> serverinfo.html + echo "
    " >> serverinfo.html + echo "
    " >> serverinfo.html +# echo " " >> serverinfo.html +# echo " " >> serverinfo.html +# echo " " >> serverinfo.html + echo " #
    " >> serverinfo.html + echo " #
    " >> serverinfo.html + echo " #
    " >> serverinfo.html + echo "
    " >> serverinfo.html + + #spread file + cp serverinfo.html /var/www/arionum.tk/ + cp serverinfo.html /var/www/mine-arionum.tk/ + cp serverinfo.html /var/www/smallminers-arionum.tk/ + cp serverinfo.html /var/www/bigminers-arionum.tk/ + cp serverinfo.html /var/www/solo-arionum.tk/ + cp serverinfo.html /var/www/pool-arionum.tk/ + + # Wait before checking again. + sleep 5 +done diff --git a/utils/plusinfo.js b/utils/plusinfo.js new file mode 100644 index 0000000..565ea1a --- /dev/null +++ b/utils/plusinfo.js @@ -0,0 +1,52 @@ +//Extra functions + function automat(){ + setInterval(function(){ $("#srvinfo").load("serverinfo.html #serverinfo") }, 1000); + setInterval(function(){ scheduleProgress() }, 1000); + } + function scheduleProgress(){ + $("#srvprogress").load("serverinfo.html #serverprogress", function(){ + $("#progCPU").html( drawprogress ($("#progCPU").attr("value") ) ); + $("#progMEM").html( drawprogress( $("#progMEM").attr("value") ) ); + $("#progLOAD").html( drawprogress( $("#progLOAD").attr("value") ) ); + }); + } + function drawprogress(pval){ + var progress = "#"; + var pc = ""; + var p10 = ""; + var p20 = ""; + var p30 = ""; + var p40 = ""; + var p50 = ""; + var p60 = ""; + var p70 = ""; + var p80 = ""; + var p90 = ""; + var p100= ""; + + var ival = (parseInt(pval)); + switch (true){ + case (ival<5): progress = p10+"#"; break; + case (ival<10): progress = p10+"##"; break; + case (ival<15): progress = p10+"##"+p20+"#"; break; + case (ival<20): progress = p10+"##"+p20+"##"; break; + case (ival<25): progress = p10+"##"+p20+"##"+p30+"#"; break; + case (ival<30): progress = p10+"##"+p20+"##"+p30+"##"; break; + case (ival<35): progress = p10+"##"+p20+"##"+p30+"##"+p40+"#"; break; + case (ival<40): progress = p10+"##"+p20+"##"+p30+"##"+p40+"##"; break; + case (ival<45): progress = p10+"##"+p20+"##"+p30+"##"+p40+"##"+p50+"#"; break; + case (ival<50): progress = p10+"##"+p20+"##"+p30+"##"+p40+"##"+p50+"##"; break; + case (ival<55): progress = p10+"##"+p20+"##"+p30+"##"+p40+"##"+p50+"##"+p60+"#"; break; + case (ival<60): progress = p10+"##"+p20+"##"+p30+"##"+p40+"##"+p50+"##"+p60+"##"; break; + case (ival<65): progress = p10+"##"+p20+"##"+p30+"##"+p40+"##"+p50+"##"+p60+"##"+p70+"#"; break; + case (ival<70): progress = p10+"##"+p20+"##"+p30+"##"+p40+"##"+p50+"##"+p60+"##"+p70+"##"; break; + case (ival<75): progress = p10+"##"+p20+"##"+p30+"##"+p40+"##"+p50+"##"+p60+"##"+p70+"##"+p80+"#"; break; + case (ival<80): progress = p10+"##"+p20+"##"+p30+"##"+p40+"##"+p50+"##"+p60+"##"+p70+"##"+p80+"##"; break; + case (ival<85): progress = p10+"##"+p20+"##"+p30+"##"+p40+"##"+p50+"##"+p60+"##"+p70+"##"+p80+"##"+p90+"#"; break; + case (ival<90): progress = p10+"##"+p20+"##"+p30+"##"+p40+"##"+p50+"##"+p60+"##"+p70+"##"+p80+"##"+p90+"##"; break; + case (ival<95): progress = p10+"##"+p20+"##"+p30+"##"+p40+"##"+p50+"##"+p60+"##"+p70+"##"+p80+"##"+p90+"##"+p100+"#"; break; + case (ival<100):progress = p10+"##"+p20+"##"+p30+"##"+p40+"##"+p50+"##"+p60+"##"+p70+"##"+p80+"##"+p90+"##"+p100+"##"; break; + } + return progress+pc; + } + diff --git a/utils/serverinfo.html b/utils/serverinfo.html new file mode 100644 index 0000000..6cff1e6 --- /dev/null +++ b/utils/serverinfo.html @@ -0,0 +1,10 @@ +
    + Server Processor: 27 %
    + Server Memory: 10 %
    + Server Load: 10.00 %
    +
    +
    + #
    + #
    + #
    +
    diff --git a/utils/serverinfo.js b/utils/serverinfo.js new file mode 100644 index 0000000..dd89746 --- /dev/null +++ b/utils/serverinfo.js @@ -0,0 +1,6 @@ +var srv_cpu=1; +var srv_mem=10; +var srv_load=5.75; +var srv_load1m=5.75; +var srv_load5m=7.75; +var srv_load15m=8.50; From e2a364de7d8f56ce018dfdbb623caca6291b7309 Mon Sep 17 00:00:00 2001 From: F0nzy Date: Mon, 24 Jun 2019 12:02:28 +0000 Subject: [PATCH 132/134] modified: README.md modified: template/header.html modified: template/news.html new file: utils/PoolinfoUpdate.service modified: utils/ServerinfoUpdate.service new file: utils/getpoolinfo.sh modified: utils/getprice.sh modified: utils/getserverinfo.sh new file: utils/poolinfo.js modified: utils/price.js new file: utils/reuirements.txt modified: utils/serverinfo.html modified: utils/serverinfo.js --- README.md | 7 +- template/header.html | 121 ++++++++++++++++++++++----------- template/news.html | 14 +++- utils/PoolinfoUpdate.service | 29 ++++++++ utils/ServerinfoUpdate.service | 2 +- utils/getpoolinfo.sh | 77 +++++++++++++++++++++ utils/getprice.sh | 10 ++- utils/getserverinfo.sh | 15 ++-- utils/poolinfo.js | 6 ++ utils/price.js | 6 +- utils/reuirements.txt | 2 + utils/serverinfo.html | 8 +-- utils/serverinfo.js | 13 ++-- 13 files changed, 243 insertions(+), 67 deletions(-) create mode 100644 utils/PoolinfoUpdate.service create mode 100755 utils/getpoolinfo.sh create mode 100644 utils/poolinfo.js create mode 100644 utils/reuirements.txt diff --git a/README.md b/README.md index 66305e8..c14b97c 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ Warning: because of additions to the config file, do not simply replace the php- - Multiple pool can work together, (eg. different min DL for Cpu, GPU or other mining settings, but same reward policy) - Database updated with orphan info - Poolsanity.php: improved peering to other pools (send and get infos) +- Workers unique ID based on miner's session ID, or the address first 15 char ## Utils - Update.php: calculate orphan blocks, and overwriter (stealer)'s alias or address @@ -17,8 +18,11 @@ Warning: because of additions to the config file, do not simply replace the php- - Poolsanity.service: Made a system service for poolsanity, copy to /etc/systemd/sytem - getserverinfo.sh: update server resources - services: system services for automated jobs (sanity, poolsanity, serverinfo) +- Added pool info service: Watching another pool's block height (Aropool.com, Aro.cool, Arionumpool.com, Arionum.info) + -> if our height lower, then force sanity ## Display +- Show another pool's block heights - Show Server resources (CPU, Memory, Server load) - Show Orphans % (basen on last 100 block) - Show Orphan block overwriter ("stealer") @@ -40,9 +44,6 @@ Warning: because of additions to the config file, do not simply replace the php- - Added: Last payment, payment date, payments in 24h, time of last submitted nonce included on individual miner page and api - Bugfix: False rejects stale blocks submitted through Dan's Javaminer after PHP upgrade. - Bugfix: Workaround for misreporting Dan's Java miner/Android miner -- TODO: Orphaned blocks are no longer removed from the list but marked as orphaned. Pending payments are removed. -- TODO: Workerid is changed to workername+address to create a unique key without having to alter the database. It prevents changes to client (new address/new workername) not being updated in the workerlist and it also prevents 2 miners using the same workername to be misreported as one. It will NOT change the fact that miners using one single name for many workers causing their hashrate being reported as once worker. This would require a uniqueID being send from the worker -- TODO: implement the possible external argon2 validation through config file - TODO: either update miner hr more often or insert sum workerHR into dashboard/individual pages/api ## Smaller changes: diff --git a/template/header.html b/template/header.html index d80f74a..c16a636 100755 --- a/template/header.html +++ b/template/header.html @@ -7,17 +7,17 @@ location.href = 'https:' + window.location.href.substring(window.location.protocol.length); } - + {$pool_name} - + @@ -32,7 +32,7 @@ - + @@ -55,6 +55,7 @@ .info-block h2 { font-size: 32px; } .info-block i { font-size: 16px; } + @@ -65,22 +66,24 @@
    @@ -107,62 +127,81 @@ - - +
    + + + +
    + +
    Pool: {$pool_name}
    diff --git a/template/news.html b/template/news.html index 0f5d0a3..73cf35e 100755 --- a/template/news.html +++ b/template/news.html @@ -6,7 +6,19 @@
    - ⭐2019-06-24: Advanced server informations + ⭐2019-06-24: Another informations +
    +
    +
      +
    • Added Aropool.com, Aro.cool, Arionumpool.com, Arionum.info acual block height (refresh: 10 sec)
    • +
    • If our pool block height smaller, then force sanity
    • +
    • Automated jobs, and watchers for better performance
    • +
    + Come and join Arionum.TK pool! 👍 +
    + +
    + ⭐2019-06-23: Advanced server informations
      diff --git a/utils/PoolinfoUpdate.service b/utils/PoolinfoUpdate.service new file mode 100644 index 0000000..4268424 --- /dev/null +++ b/utils/PoolinfoUpdate.service @@ -0,0 +1,29 @@ +#PoolinfoUpdate.service + +[Unit] +Description=Poolinfo Update +#Requires=mysqld.service +After=network.target + +[Service] +User=root +Type=simple +TimeoutSec=0 +PIDFile=/var/run/PoolinfoUpdate.pid +ExecStart=/bin/bash /var/www/arionum.tk/utils/getpoolinfo.sh > /dev/null 2>/dev/null +#ExecStop=/bin/kill -HUP $MAINPID #It's the default you can change whats happens on stop command +#ExecReload=/bin/kill -HUP $MAINPID +KillMode=process + +#Restart=on-failure +Restart=always +RestartSec=30s + +#If you don't want to make toms of logs you can set it null if you sent a file or some other options it will send all php output to this one. +StandardOutput=/var/log/PoolinfoUpdate.log +StandardError=/var/log/PoolinfoUpdate.err + +[Install] +WantedBy=default.target + + diff --git a/utils/ServerinfoUpdate.service b/utils/ServerinfoUpdate.service index 9d3865e..40af07b 100644 --- a/utils/ServerinfoUpdate.service +++ b/utils/ServerinfoUpdate.service @@ -10,7 +10,7 @@ User=root Type=simple TimeoutSec=0 PIDFile=/var/run/ServerinfoUpdate.pid -ExecStart=/bin/bash /var/www/arionum.tk/utils/serverinfo.sh > /dev/null 2>/dev/null +ExecStart=/bin/bash /var/www/arionum.tk/utils/getserverinfo.sh > /dev/null 2>/dev/null #ExecStop=/bin/kill -HUP $MAINPID #It's the default you can change whats happens on stop command #ExecReload=/bin/kill -HUP $MAINPID KillMode=process diff --git a/utils/getpoolinfo.sh b/utils/getpoolinfo.sh new file mode 100755 index 0000000..4a8bbd3 --- /dev/null +++ b/utils/getpoolinfo.sh @@ -0,0 +1,77 @@ +#extract infos from POOLs +while true; do + +dir=/var/www/arionum.tk/utils/ +cd $dir + +echo "//Generated: getpoolinfo.sh" > poolinfo.js + +######### POOLS ########## +AropoolBlock=$( curl -H 'user-agent: Mozilla/5.0' -s 'http://aropool.com:80/api.php?q=currentBlock' | jq -r '.current_block_height') +ArocoolBlock=$( curl -H 'user-agent: Mozilla/5.0' -s 'http://aro.cool:80/api.php?q=currentBlock' | jq -r '.current_block_height') +ArionumpoolBlock=$( curl -H 'user-agent: Mozilla/5.0' -s 'https://arionumpool.com/api.php?q=currentBlock' | jq -r '.current_block_height') +#ArionumtkBlock=$( curl -H 'user-agent: Mozilla/5.0' -s 'http://arionum.tk/api.php?q=currentBlock' | jq -r '.current_block_height') +ArionumtkBlock=$( curl -H 'user-agent: Mozilla/5.0' -s 'http://127.0.0.1:80/api.php?q=currentBlock' | jq -r '.current_block_height') + +#Write to file +echo "var aropool_block=$AropoolBlock;" >> poolinfo.js +echo "var arocool_block=$ArocoolBlock;" >> poolinfo.js +echo "var arionumpool_block=$ArionumpoolBlock;" >> poolinfo.js +echo "var arionumtk_block=$ArionumtkBlock;" >> poolinfo.js + +########## ARIONUM INFO ########### +rm index.html* +wget -O index.html --header 'user-agent: Mozilla/5.0' 'http://arionum.info/' + +#line numbers +blockline=$(grep -n '>Current block<' index.html | cut -f1 -d:) +blockline=$((blockline+1)) +ArionumInfo=$(sed -n $blockline'p' index.html | sed 's/

      //' | sed 's/<[/]h3>//' | sed 's/^[[:blank:]]*//') +#Write to file +echo "var arionuminfo_block=$ArionumInfo;" >> poolinfo.js + +############## spread file ################ +cp poolinfo.js /var/www/mine-arionum.tk/utils +cp poolinfo.js /var/www/smallminers-arionum.tk/utils +cp poolinfo.js /var/www/bigminers-arionum.tk/utils +cp poolinfo.js /var/www/solo-arionum.tk/utils +cp poolinfo.js /var/www/pool-arionum.tk/utils + +#check Max block height - Force SANITY +needSanity="false" +if [ $ArionumtkBlock -lt $AropoolBlock ] +then + needSanity="true" + #echo "$AropoolBlock" > maxBlockHeight.txt +elif [ $ArionumtkBlock -lt $ArocoolBlock ] +then + needSanity="true" + #echo "$ArocoolBlock" > maxBlockHeight.txt +elif [ $ArionumtkBlock -lt $ArionumpoolBlock ] +then + needSanity="true" + #echo "$ArionumpoolBlock" > maxBlockHeight.txt +elif [ $ArionumtkBlock -lt $ArionumInfo ] +then + needSanity="true" + #echo "$ArionumInfo" > maxBlockHeight.txt +else + needSanity="false" + #rm maxBlockHeight.txt + #rm /var/www/node-arionum.tk/maxBlockHeight.txt + #echo "$ArionumtkBlock" > maxBlockHeight.txt +fi +#cp maxBlockHeight.txt /var/www/node-arionum.tk/ #indirect + +#Call Sanity direct +if [ $needSanity = "true" ] +then + #echo "$ArionumtkBlock" > callSanity.txt + php /var/www/node-arionum.tk/sanity.php +fi + +#WAIT FOR NEXT RUN +sleep 10 + +done + diff --git a/utils/getprice.sh b/utils/getprice.sh index 1864c5f..4e55953 100755 --- a/utils/getprice.sh +++ b/utils/getprice.sh @@ -1,6 +1,6 @@ #extract infos from arionum.info -dir=/var/www/__POOL__/utils/ +dir=/var/www/arionum.tk/utils/ cd $dir rm index.html* wget arionum.info # index.html @@ -31,6 +31,10 @@ echo "var aro_price=$price;" > price.js echo "var aro_gpu_hashrate=$gpuhashrate;" >> price.js echo "var aro_cpu_hashrate=$cpuhashrate;" >> price.js -#spread file to other pool -cp price.js /var/www/___OTHERPOOLS___/utils +#spread file +cp price.js /var/www/mine-arionum.tk/utils +cp price.js /var/www/smallminers-arionum.tk/utils +cp price.js /var/www/bigminers-arionum.tk/utils +cp price.js /var/www/solo-arionum.tk/utils +cp price.js /var/www/pool-arionum.tk/utils diff --git a/utils/getserverinfo.sh b/utils/getserverinfo.sh index 944b77a..d7b3108 100755 --- a/utils/getserverinfo.sh +++ b/utils/getserverinfo.sh @@ -40,9 +40,9 @@ while true; do UsedMEM=$(( (100 * ($TotalMEM - $FreeMEM) / $TotalMEM) )); LOAD=(`uptime`) # Get the serverLOAD. - L1M=${LOAD[9]/,/} # Get the MEMs. - L5M=${LOAD[10]/,/} - L15M=${LOAD[11]/,/} + L1M=${LOAD[10]/,/} # Get the Loads. + L5M=${LOAD[11]/,/} + L15M=${LOAD[12]/,/} L1P=$(echo "scale=2; (($L1M * 100)/4)" | bc -l); L5P=$(echo "scale=2; (($L5M * 100)/4)" | bc -l); L15P=$(echo "scale=2; (($L15M * 100)/4)" | bc -l); @@ -52,9 +52,12 @@ while true; do echo "var srv_cpu=$CPUUSAGE;" > serverinfo.js echo "var srv_mem=$UsedMEM;" >> serverinfo.js echo "var srv_load=$L1P;" >> serverinfo.js - echo "var srv_load1m=$L1P;" >> serverinfo.js - echo "var srv_load5m=$L5P;" >> serverinfo.js - echo "var srv_load15m=$L15P;" >> serverinfo.js + echo "var srv_load1p=$L1P;" >> serverinfo.js + echo "var srv_load5p=$L5P;" >> serverinfo.js + echo "var srv_load15p=$L15P;" >> serverinfo.js + echo "var srv_load1m=$L1M;" >> serverinfo.js + echo "var srv_load5m=$L5M;" >> serverinfo.js + echo "var srv_load15m=$L15M;" >> serverinfo.js #spread file cp serverinfo.js /var/www/mine-arionum.tk/utils diff --git a/utils/poolinfo.js b/utils/poolinfo.js new file mode 100644 index 0000000..0bf33d2 --- /dev/null +++ b/utils/poolinfo.js @@ -0,0 +1,6 @@ +//Generated: getpoolinfo.sh +var aropool_block=187240; +var arocool_block=187241; +var arionumpool_block=187241; +var arionumtk_block=187241; +var arionuminfo_block=187241; diff --git a/utils/price.js b/utils/price.js index 68fed61..e7464f2 100644 --- a/utils/price.js +++ b/utils/price.js @@ -1,3 +1,3 @@ -var aro_price=0.0041; -var aro_gpu_hashrate=1.643; -var aro_cpu_hashrate=211; +var aro_price=0.0029; +var aro_gpu_hashrate=937; +var aro_cpu_hashrate=125; diff --git a/utils/reuirements.txt b/utils/reuirements.txt new file mode 100644 index 0000000..a3fe469 --- /dev/null +++ b/utils/reuirements.txt @@ -0,0 +1,2 @@ +#Requirements +curl, bc, jq, cputool, cpulimit diff --git a/utils/serverinfo.html b/utils/serverinfo.html index 6cff1e6..357c3d0 100644 --- a/utils/serverinfo.html +++ b/utils/serverinfo.html @@ -1,10 +1,10 @@
      - Server Processor: 27 %
      + Server Processor: 2 %
      Server Memory: 10 %
      - Server Load: 10.00 %
      + Server Load: 5.00 %
      - #
      + #
      #
      - #
      + #
      diff --git a/utils/serverinfo.js b/utils/serverinfo.js index dd89746..706928b 100644 --- a/utils/serverinfo.js +++ b/utils/serverinfo.js @@ -1,6 +1,9 @@ -var srv_cpu=1; +var srv_cpu=2; var srv_mem=10; -var srv_load=5.75; -var srv_load1m=5.75; -var srv_load5m=7.75; -var srv_load15m=8.50; +var srv_load=5.00; +var srv_load1p=5.00; +var srv_load5p=5.75; +var srv_load15p=; +var srv_load1m=0.20; +var srv_load5m=0.23; +var srv_load15m=; From f8671edc8e92e6c0016b7882c9f4fc06f8ea339d Mon Sep 17 00:00:00 2001 From: Ario Date: Sat, 27 Jul 2019 12:23:38 +0000 Subject: [PATCH 133/134] remove hardcoded links --- index.php | 1 + template/header.html | 68 ++++---------------------------------------- 2 files changed, 6 insertions(+), 63 deletions(-) diff --git a/index.php b/index.php index 3f6fda6..971238a 100755 --- a/index.php +++ b/index.php @@ -16,6 +16,7 @@ $tpl->assign("q", $q); $tpl->assign("id", $id); $tpl->assign("pool_name", $pool_config['pool_name']); +$tpl->assign("pool_url", $pool_config['pool_url']); $tpl->assign("template_directory", $pool_config['template_directory']); $tpl->draw('header'); diff --git a/template/header.html b/template/header.html index c16a636..aa01024 100755 --- a/template/header.html +++ b/template/header.html @@ -2,11 +2,6 @@ - {$pool_name} @@ -66,7 +61,7 @@

    @@ -143,51 +129,7 @@ -
  • - - - CPU pool - - - -
  • - -
  • - - - GPU pool - - - -
  • - -
  • - - - Farm pool - - - -
  • - -
  • - - - SOLO pool - - - -
  • - -
  • - - - Arionum Node - - - -
  • - +
  • Price: USD From f5b3c4e28458bab00cdc1479a6abbb124afa068d Mon Sep 17 00:00:00 2001 From: Ario Sius <44259996+ariochain@users.noreply.github.com> Date: Sat, 27 Jul 2019 14:28:56 +0200 Subject: [PATCH 134/134] Update README.md --- README.md | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index c14b97c..4068128 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,16 @@ Warning: because of additions to the config file, do not simply replace the php- - Added Cuby's web wallet link - Added News info -### angelexevior's changes ### +With the current setup payments are split from updates. + +Run payments to crontab every x hours, min payment can remain low, but it will prevent big miners from massive small payments. + +Run update in seperate crontab every 1 minute. + +Optional: Run poolsanity as systemd-service + + +### hendrik's changes ### ## Bigger changes: - Change: Hashreporting has been removed from payments/poolsanity to a seperate updater. Updating hashrates on the website can be done independently of payment-cycle, and db is no longer only updated when moving to next block. Be aware that the 10minute update interval from the clients is fixed. As is the 'first appearance' in the db after submitting first nonce @@ -78,13 +87,3 @@ Warning: because of additions to the config file, do not simply replace the php- - Bugfix: On individual miner page - when no payment ever last payment date is shown as No Payment Yet - Change: On info page - old mining info removed, pool details (rewards/degradation/payout/DL) are read from the config file - Change: On info page - discord handle can be set in config - - -With the current setup payments are split from updates. - -Run payments to crontab every x hours, min payment can remain low, but it will prevent big miners from massive small payments. - -Run update in seperate crontab every 1 minute. - -Optional: Run poolsanity as systemd-service -