From 99f17a3e7d2a886ad2935ffcaba875a5a4c8a7d2 Mon Sep 17 00:00:00 2001 From: Arionum Date: Thu, 30 Aug 2018 01:28:57 +0300 Subject: [PATCH] util tools --- util.php | 533 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 533 insertions(+) create mode 100755 util.php diff --git a/util.php b/util.php new file mode 100755 index 0000000..d1de2f5 --- /dev/null +++ b/util.php @@ -0,0 +1,533 @@ +run("SET foreign_key_checks=0;"); + $tables = ["accounts", "transactions", "mempool", "masternode","blocks"]; + foreach ($tables as $table) { + $db->run("TRUNCATE TABLE {$table}"); + } + $db->run("SET foreign_key_checks=1;"); + + echo "\n The database has been cleared\n"; + unlink("tmp/sanity-lock"); +} /** + * @api {php util.php} pop Pop + * @apiName pop + * @apiGroup UTIL + * @apiDescription Cleans the entire database + * + * @apiParam {Number} arg2 Number of blocks to delete + * + * @apiExample {cli} Example usage: + * php util.php pop 1 + */ + +elseif ($cmd == 'pop') { + if (file_exists("tmp/sanity-lock")) { + die("Sanity running. Wait for it to finish"); + } + touch("tmp/sanity-lock"); + $no = intval($argv[2]); + $block = new Block(); + $block->pop($no); + unlink("tmp/sanity-lock"); +} /** + * @api {php util.php} block-time Block-time + * @apiName block-time + * @apiGroup UTIL + * @apiDescription Shows the block time of the last 100 blocks + * + * @apiExample {cli} Example usage: + * php util.php block-time + * + * @apiSuccessExample {text} Success-Response: + * 16830 -> 323 + * ... + * 16731 -> 302 + * Average block time: 217 seconds + */ + +elseif ($cmd == 'block-time') { + $t = time(); + $r = $db->run("SELECT * FROM blocks ORDER by height DESC LIMIT 100"); + $start = 0; + foreach ($r as $x) { + if ($start == 0) { + $start = $x['date']; + } + $time = $t - $x['date']; + $t = $x['date']; + echo "$x[height]\t\t$time\t\t$x[difficulty]\n"; + $end = $x['date']; + } + echo "Average block time: ".ceil(($start - $end) / 100)." seconds\n"; +} /** + * @api {php util.php} peer Peer + * @apiName peer + * @apiGroup UTIL + * @apiDescription Creates a peering session with another node + * + * @apiParam {text} arg2 The Hostname of the other node + * + * @apiExample {cli} Example usage: + * php util.php peer http://peer1.arionum.com + * + * @apiSuccessExample {text} Success-Response: + * Peering OK + */ + + +elseif ($cmd == "peer") { + $res = peer_post($argv[2]."/peer.php?q=peer", ["hostname" => $_config['hostname']]); + if ($res !== false) { + echo "Peering OK\n"; + } else { + echo "Peering FAIL\n"; + } +} /** + * @api {php util.php} current Current + * @apiName current + * @apiGroup UTIL + * @apiDescription Prints the current block in var_dump + * + * @apiExample {cli} Example usage: + * php util.php current + * + * @apiSuccessExample {text} Success-Response: + * array(9) { + * ["id"]=> + * string(88) "4khstc1AknzDXg8h2v12rX42vDrzBaai6Rz53mbaBsghYN4DnfPhfG7oLZS24Q92MuusdYmwvDuiZiuHHWgdELLR" + * ["generator"]=> + * string(88) "5ADfrJUnLefPsaYjMTR4KmvQ79eHo2rYWnKBRCXConYKYJVAw2adtzb38oUG5EnsXEbTct3p7GagT2VVZ9hfVTVn" + * ["height"]=> + * int(16833) + * ["date"]=> + * int(1519312385) + * ["nonce"]=> + * string(41) "EwtJ1EigKrLurlXROuuiozrR6ICervJDF2KFl4qEY" + * ["signature"]=> + * string(97) "AN1rKpqit8UYv6uvf79GnbjyihCPE1UZu4CGRx7saZ68g396yjHFmzkzuBV69Hcr7TF2egTsEwVsRA3CETiqXVqet58MCM6tu" + * ["difficulty"]=> + * string(8) "61982809" + * ["argon"]=> + * string(68) "$SfghIBNSHoOJDlMthVcUtg$WTJMrQWHHqDA6FowzaZJ+O9JC8DPZTjTxNE4Pj/ggwg" + * ["transactions"]=> + * int(0) + * } + * + */ + +elseif ($cmd == "current") { + $block = new Block(); + var_dump($block->current()); +} /** + * @api {php util.php} blocks Blocks + * @apiName blocks + * @apiGroup UTIL + * @apiDescription Prints the id and the height of the blocks >=arg2, max 100 or arg3 + * + * @apiParam {number} arg2 Starting height + * + * @apiParam {number} [arg3] Block Limit + * + * @apiExample {cli} Example usage: + * php util.php blocks 10800 5 + * + * @apiSuccessExample {text} Success-Response: + * 10801 2yAHaZ3ghNnThaNK6BJcup2zq7EXuFsruMb5qqXaHP9M6JfBfstAag1n1PX7SMKGcuYGZddMzU7hW87S5ZSayeKX + * 10802 wNa4mRvRPCMHzsgLdseMdJCvmeBaCNibRJCDhsuTeznJh8C1aSpGuXRDPYMbqKiVtmGAaYYb9Ze2NJdmK1HY9zM + * 10803 3eW3B8jCFBauw8EoKN4SXgrn33UBPw7n8kvDDpyQBw1uQcmJQEzecAvwBk5sVfQxUqgzv31JdNHK45JxUFcupVot + * 10804 4mWK1f8ch2Ji3D6aw1BsCJavLNBhQgpUHBCHihnrLDuh8Bjwsou5bQDj7D7nV4RsEPmP2ZbjUUMZwqywpRc8r6dR + * 10805 5RBeWXo2c9NZ7UF2ubztk53PZpiA4tsk3bhXNXbcBk89cNqorNj771Qu4kthQN5hXLtu1hzUnv7nkH33hDxBM34m + * + */ +elseif ($cmd == "blocks") { + $height = intval($argv[2]); + $limit = intval($argv[3]); + if ($limit < 1) { + $limit = 100; + } + $r = $db->run("SELECT * FROM blocks WHERE height>:height ORDER by height ASC LIMIT $limit", [":height" => $height]); + foreach ($r as $x) { + echo "$x[height]\t$x[id]\n"; + } +} /** + * @api {php util.php} recheck-blocks Recheck-Blocks + * @apiName recheck-blocks + * @apiGroup UTIL + * @apiDescription Recheck all the blocks to make sure the blockchain is correct + * + * @apiExample {cli} Example usage: + * php util.php recheck-blocks + * + */ +elseif ($cmd == "recheck-blocks") { + $blocks = []; + $block = new Block(); + $r = $db->run("SELECT * FROM blocks ORDER by height ASC"); + foreach ($r as $x) { + $blocks[$x['height']] = $x; + $max_height = $x['height']; + } + for ($i = 2; $i <= $max_height; $i++) { + $data = $blocks[$i]; + + $key = $db->single("SELECT public_key FROM accounts WHERE id=:id", [":id" => $data['generator']]); + + if (!$block->mine( + $key, + $data['nonce'], + $data['argon'], + $data['difficulty'], + $blocks[$i - 1]['id'], + $blocks[$i - 1]['height'], + $data['date'] + )) { + _log("Invalid block detected. We should delete everything after $data[height] - $data[id]"); + break; + } + } +} /** + * @api {php util.php} peers Peers + * @apiName peers + * @apiGroup UTIL + * @apiDescription Prints all the peers and their status + * + * @apiExample {cli} Example usage: + * php util.php peers + * + * @apiSuccessExample {text} Success-Response: + * http://35.190.160.142 active + * ... + * http://aro.master.hashpi.com active + */ +elseif ($cmd == "peers") { + $r = $db->run("SELECT * FROM peers ORDER by reserve ASC"); + $status = "active"; + if ($x['reserve'] == 1) { + $status = "reserve"; + } + foreach ($r as $x) { + echo "$x[hostname]\t$status\n"; + } +} /** + * @api {php util.php} mempool Mempool + * @apiName mempool + * @apiGroup UTIL + * @apiDescription Prints the number of transactions in mempool + * + * @apiExample {cli} Example usage: + * php util.php mempool + * + * @apiSuccessExample {text} Success-Response: + * Mempool size: 12 + */ +elseif ($cmd == "mempool") { + $res = $db->single("SELECT COUNT(1) from mempool"); + echo "Mempool size: $res\n"; +} /** + * @api {php util.php} delete-peer Delete-peer + * @apiName delete-peer + * @apiGroup UTIL + * @apiDescription Removes a peer from the peerlist + * + * @apiParam {text} arg2 Peer's hostname + * + * @apiExample {cli} Example usage: + * php util.php delete-peer http://peer1.arionum.com + * + * @apiSuccessExample {text} Success-Response: + * Peer removed + */ +elseif ($cmd == "delete-peer") { + $peer = trim($argv[2]); + if (empty($peer)) { + die("Invalid peer"); + } + $db->run("DELETE FROM peers WHERE ip=:ip", [":ip" => $peer]); + echo "Peer removed\n"; +} elseif ($cmd == "recheck-peers") { + $r = $db->run("SELECT * FROM peers"); + foreach ($r as $x) { + $a = peer_post($x['hostname']."/peer.php?q=ping"); + if ($a != "pong") { + echo "$x[hostname] -> failed\n"; + $db->run("DELETE FROM peers WHERE id=:id", [":id" => $x['id']]); + } else { + echo "$x[hostname] ->ok \n"; + } + } +} /** + * @api {php util.php} peers-block Peers-Block + * @apiName peers-block + * @apiGroup UTIL + * @apiDescription Prints the current height of all the peers + * + * @apiExample {cli} Example usage: + * php util.php peers-block + * + * @apiSuccessExample {text} Success-Response: + * http://peer5.arionum.com 16849 + * ... + * http://peer10.arionum.com 16849 + */ +elseif ($cmd == "peers-block") { + $only_diff = false; + if ($argv[2] == "diff") { + $current = $db->single("SELECT height FROM blocks ORDER by height DESC LIMIT 1"); + $only_diff = true; + } + $r = $db->run("SELECT * FROM peers WHERE blacklistedsingle( + "SELECT balance FROM accounts WHERE id=:id OR public_key=:id2 LIMIT 1", + [":id" => $id, ":id2" => $id] + ); + + echo "Balance: ".number_format($res)."\n"; +} /** + * @api {php util.php} block Block + * @apiName block + * @apiGroup UTIL + * @apiDescription Returns a specific block + * + * @apiParam {text} arg2 block id + * + * @apiExample {cli} Example usage: + * php util.php block 4khstc1AknzDXg8h2v12rX42vDrzBaai6Rz53mbaBsghYN4DnfPhfG7oLZS24Q92MuusdYmwvDuiZiuHHWgdELLR + * + * @apiSuccessExample {text} Success-Response: + * array(9) { + * ["id"]=> + * string(88) "4khstc1AknzDXg8h2v12rX42vDrzBaai6Rz53mbaBsghYN4DnfPhfG7oLZS24Q92MuusdYmwvDuiZiuHHWgdELLR" + * ["generator"]=> + * string(88) "5ADfrJUnLefPsaYjMTR4KmvQ79eHo2rYWnKBRCXConYKYJVAw2adtzb38oUG5EnsXEbTct3p7GagT2VVZ9hfVTVn" + * ["height"]=> + * int(16833) + * ["date"]=> + * int(1519312385) + * ["nonce"]=> + * string(41) "EwtJ1EigKrLurlXROuuiozrR6ICervJDF2KFl4qEY" + * ["signature"]=> + * string(97) "AN1rKpqit8UYv6uvf79GnbjyihCPE1UZu4CGRx7saZ68g396yjHFmzkzuBV69Hcr7TF2egTsEwVsRA3CETiqXVqet58MCM6tu" + * ["difficulty"]=> + * string(8) "61982809" + * ["argon"]=> + * string(68) "$SfghIBNSHoOJDlMthVcUtg$WTJMrQWHHqDA6FowzaZJ+O9JC8DPZTjTxNE4Pj/ggwg" + * ["transactions"]=> + * int(0) + * } + */ +elseif ($cmd == "block") { + $id = san($argv[2]); + $res = $db->row("SELECT * FROM blocks WHERE id=:id OR height=:id2 LIMIT 1", [":id" => $id, ":id2" => $id]); + + var_dump($res); +} /** + * @api {php util.php} check-address Check-Address + * @apiName check-address + * @apiGroup UTIL + * @apiDescription Checks a specific address for validity + * + * @apiParam {text} arg2 block id + * + * @apiExample {cli} Example usage: + * php util.php check-address 4khstc1AknzDXg8h2v12rX42vDrzBaai6Rz53mbaBsghYN4DnfPhfG7oLZS24Q92MuusdYmwvDuiZiuHHWgdELLR + * + * @apiSuccessExample {text} Success-Response: + * The address is valid + */ +elseif ($cmd == "check-address") { + $dst = trim($argv[2]); + $acc = new Account(); + if (!$acc->valid($dst)) { + die("Invalid address"); + } + $dst_b = base58_decode($dst); + if (strlen($dst_b) != 64) { + die("Invalid address - ".strlen($dst_b)." bytes"); + } + + echo "The address is valid\n"; +} +/** + * @api {php util.php} get-address Get-Address + * @apiName get-address + * @apiGroup UTIL + * @apiDescription Converts a public key into an address + * + * @apiParam {text} arg2 public key + * + * @apiExample {cli} Example usage: + * php util.php get-address PZ8Tyr4Nx8MHsRAGMpZmZ6TWY63dXWSCwQr8cE5s6APWAE1SWAmH6NM1nJTryBURULEsifA2hLVuW5GXFD1XU6s6REG1iPK7qGaRDkGpQwJjDhQKVoSVkSNp + * + * @apiSuccessExample {text} Success-Response: + * 5WuRMXGM7Pf8NqEArVz1NxgSBptkimSpvuSaYC79g1yo3RDQc8TjVtGH5chQWQV7CHbJEuq9DmW5fbmCEW4AghQr + */ + +elseif ($cmd == 'get-address') { + $public_key = trim($argv2); + if (strlen($public_key) < 32) { + die("Invalid public key"); + } + print($acc->get_address($public_key)); +/** + * @api {php util.php} clean-blacklist Clean-Blacklist + * @apiName clean-blacklist + * @apiGroup UTIL + * @apiDescription Removes all the peers from blacklist + * + * @apiExample {cli} Example usage: + * php util.php clean-blacklist + * + */ +} elseif ($cmd == 'clean-blacklist') { + $db->run("UPDATE peers SET blacklisted=0, fails=0, stuckfail=0"); + echo "All the peers have been removed from the blacklist\n"; +} elseif ($cmd == 'resync-accounts') { + // resyncs the balance on all accounts + + // lock table to avoid race conditions on blocks + $db->exec("LOCK TABLES blocks WRITE, accounts WRITE, transactions WRITE, mempool WRITE"); + + $r=$db->run("SELECT * FROM accounts"); + foreach ($r as $x) { + $alias=$x['alias']; + if (empty($alias)) { + $alias="A"; + } + $rec=$db->single("SELECT SUM(val) FROM transactions WHERE (dst=:id or dst=:alias) AND (height<80000 OR (version!=100 AND version!=103)) and version<111", [":id"=>$x['id'], ":alias"=>$alias]); + $spent=$db->single("SELECT SUM(val+fee) FROM transactions WHERE public_key=:pub AND version>0", [":pub"=>$x['public_key']]); + if ($spent==false) { + $spent=0; + } + $balance=round(($rec-$spent), 8); + if ($x['balance']!=$balance) { + echo "rec: $rec, spent: $spent, bal: $x[balance], should be: $balance - $x[id] $x[public_key]\n"; + if (trim($argv[2])!="check") { + $db->run("UPDATE accounts SET balance=:bal WHERE id=:id", [":id"=>$x['id'], ":bal"=>$balance]); + } + } + } + $db->exec("UNLOCK TABLES"); + echo "All done"; +} elseif ($cmd=="compare-blocks") { + $block=new Block(); + + $current=$block->current(); + $peer=trim($argv[2]); + $limit=intval($argv[3]); + if ($limit==0) { + $limit=5000; + } + for ($i=$current['height']-$limit;$i<=$current['height'];$i++) { + $data=peer_post($peer."/peer.php?q=getBlock", ["height" => $i]); + if ($data==false) { + continue; + } + $our=$block->export(false, $i); + if ($data!=$our) { + echo "Failed block -> $i\n"; + if ($argv[4]=="dump") { + echo "\n\n ---- Internal ----\n\n"; + var_dump($our); + echo "\n\n ---- External ----\n\n"; + var_dump($data); + } + } + } +} elseif ($cmd=='compare-accounts') { + $peer=trim($argv[2]); + $r=$db->run("SELECT id,balance FROM accounts"); + foreach ($r as $x) { + $data=peer_post($peer."/api.php?q=getBalance", ["account" => $x['id']]); + if ($data==false) { + continue; + } + if ($data!=$x['balance']) { + echo "$x[id]\t\t$x[balance]\t$data\n"; + } + } +} elseif ($cmd=='masternode-hash') { + $res=$db->run("SELECT * FROM masternode ORDER by public_key ASC"); + $block=new Block(); + $current=$block->current(); + echo "Height:\t\t$current[height]\n"; + echo "Hash:\t\t".md5(json_encode($res))."\n\n"; +} elseif ($cmd == "version") { + echo "\n\n".VERSION."\n\n"; +} else { + echo "Invalid command\n"; +}