diff --git a/api.php b/api.php index c523bd3..dd74f26 100755 --- a/api.php +++ b/api.php @@ -422,12 +422,20 @@ if ($q == "getAddress") { } } - + $public_key = san($data['public_key']); if (!$acc->valid_key($public_key)) { api_err("Invalid public key"); } + if ($_config['use_official_blacklist']!==false) { + $blacklisted=["PZ8Tyr4Nx8MHsRAGMpZmZ6TWY63dXWSCvVQcHHCNLfiP9LmzWhhpCHx39Bhc67P5HMQM9cctEFvcsUdgrkGqy18taz9ZMrAGtq7NhBYpQ4ZTHkKYiZDaSUqQ", //faucet abuser + "PZ8Tyr4Nx8MHsRAGMpZmZ6TWY63dXWSCxYDeQHk7Ke66UB2Un3UMmMoJ7RF5vDZXihdEXi8gk8ZBRAi35aFrER2ZLX1mgND7sLFXKETGTjRYjoHcuRNiJN1g" // octaex + ]; + if (in_array($public_key, $blacklisted)) { + api_err("Blacklisted account"); + } + } $private_key = san($data['private_key']); if (!$acc->valid_key($private_key)) { api_err("Invalid private key"); @@ -559,6 +567,7 @@ if ($q == "getAddress") { $trx->add_mempool($transaction, "local"); + $hash=escapeshellarg(san($hash)); system("php propagate.php transaction $hash > /dev/null 2>&1 &"); api_echo($hash); } elseif ($q == "mempoolSize") { diff --git a/include/block.inc.php b/include/block.inc.php index fb3ab87..c6b5a83 100755 --- a/include/block.inc.php +++ b/include/block.inc.php @@ -276,7 +276,7 @@ class Block // before mnn hf if ($height<80000) { // elapsed time between the last 20 blocks - $first = $db->row("SELECT `date` FROM blocks ORDER by height DESC LIMIT $limit,1"); + $first = $db->row("SELECT `date` FROM blocks ORDER by height DESC LIMIT :limit,1",[":limit"=>$limit]); $time = $current['date'] - $first['date']; // avg block time @@ -566,8 +566,8 @@ class Block } _log("We have masternodes to blacklist - $tem", 2); $ban=$db->run( - "SELECT public_key, blacklist, fails, last_won FROM masternode WHERE status=1 AND blacklist<:current AND height<:start ORDER by last_won ASC, public_key ASC LIMIT 0,$tem", - [":current"=>$last['height'], ":start"=>$last['height']-360] + "SELECT public_key, blacklist, fails, last_won FROM masternode WHERE status=1 AND blacklist<:current AND height<:start ORDER by last_won ASC, public_key ASC LIMIT 0,:limit", + [":current"=>$last['height'], ":start"=>$last['height']-360, ":limit"=>$tem] ); _log(json_encode($ban)); $i=0; @@ -689,8 +689,8 @@ class Block $tem=floor(($time-$last_time)/600); } $winner=$db->single( - "SELECT public_key FROM masternode WHERE status=1 AND blacklist<:current AND height<:start ORDER by last_won ASC, public_key ASC LIMIT $tem,1", - [":current"=>$current_height, ":start"=>$current_height-360] + "SELECT public_key FROM masternode WHERE status=1 AND blacklist<:current AND height<:start ORDER by last_won ASC, public_key ASC LIMIT :tem,1", + [":current"=>$current_height, ":start"=>$current_height-360, ":tem"=>$tem] ); _log("Moving to the next masternode - $tem - $winner", 1); // if all masternodes are dead, give the block to gpu diff --git a/include/config-sample.inc.php b/include/config-sample.inc.php index 296006e..b0b467c 100755 --- a/include/config-sample.inc.php +++ b/include/config-sample.inc.php @@ -38,6 +38,10 @@ $_config['allowed_hosts'] = [ '127.0.0.1', ]; +// Disable transactions and block repropagation +$_config['disable_repropagation'] = false; + + /* |-------------------------------------------------------------------------- | Peer Configuration @@ -65,6 +69,9 @@ $_config['max_mempool_rebroadcast'] = 5000; // The number of blocks between rebroadcasting transactions $_config['sanity_rebroadcast_height'] = 30; +// Block accepting transfers from addresses blacklisted by the Arionum devs +$_config['use_official_blacklist'] = true; + /* |-------------------------------------------------------------------------- | Sanity Configuration diff --git a/include/transaction.inc.php b/include/transaction.inc.php index 52482c0..858a1f2 100755 --- a/include/transaction.inc.php +++ b/include/transaction.inc.php @@ -218,10 +218,21 @@ class Transaction public function add_mempool($x, $peer = "") { global $db; + global $_config; $block = new Block(); if ($x['version']>110) { return true; } + + if ($_config['use_official_blacklist']!==false) { + $blacklisted=[ + "PZ8Tyr4Nx8MHsRAGMpZmZ6TWY63dXWSCvVQcHHCNLfiP9LmzWhhpCHx39Bhc67P5HMQM9cctEFvcsUdgrkGqy18taz9ZMrAGtq7NhBYpQ4ZTHkKYiZDaSUqQ", //faucet abuser + "PZ8Tyr4Nx8MHsRAGMpZmZ6TWY63dXWSCxYDeQHk7Ke66UB2Un3UMmMoJ7RF5vDZXihdEXi8gk8ZBRAi35aFrER2ZLX1mgND7sLFXKETGTjRYjoHcuRNiJN1g" // octaex + ]; + if (in_array($public_key, $blacklisted)) { + return true; + } + } $current = $block->current(); $height = $current['height']; $x['id'] = san($x['id']); diff --git a/mine.php b/mine.php index 2818848..616b87f 100755 --- a/mine.php +++ b/mine.php @@ -118,6 +118,7 @@ if ($q == "info") { if ($res) { //if the new block is generated, propagate it to all peers in background $current = $block->current(); + $current['id']=escapeshellarg(san($current['id'])); system("php propagate.php block $current[id] > /dev/null 2>&1 &"); api_echo("accepted"); } @@ -193,6 +194,7 @@ if ($q == "info") { if ($res) { //if the new block is generated, propagate it to all peers in background $current = $block->current(); + $current['id']=escapeshellarg(san($current['id'])); system("php propagate.php block $current[id] > /dev/null 2>&1 &"); api_echo("accepted"); } else { diff --git a/peer.php b/peer.php index 1f8a3fd..ea686a7 100755 --- a/peer.php +++ b/peer.php @@ -150,6 +150,7 @@ if ($q == "peer") { // rebroadcast the transaction to some peers unless the transaction is smaller than the average size of transactions in mempool - protect against garbage data flooding $res = $db->row("SELECT COUNT(1) as c, sum(val) as v FROM mempool ", [":src" => $data['src']]); if ($res['c'] < $_config['max_mempool_rebroadcast'] && $res['v'] / $res['c'] < $data['val']) { + $data['id']=escapeshellarg(san($data['id'])); system("php propagate.php transaction '$data[id]' > /dev/null 2>&1 &"); } api_echo("transaction-ok"); @@ -185,6 +186,7 @@ if ($q == "peer") { if ($accept_new) { // if the new block is accepted, run a microsanity to sync it _log('['.$ip."] Starting microsanity - $data[height]"); + $ip=escapeshellarg($ip); system("php sanity.php microsanity '$ip' > /dev/null 2>&1 &"); api_echo("microsanity"); } else { @@ -200,7 +202,7 @@ if ($q == "peer") { if (!$pr) { api_err("block-too-old"); } - $peer_host = base58_encode($pr['hostname']); + $peer_host = escapeshellcmd(base58_encode($pr['hostname'])); $pr['ip'] = escapeshellcmd(san_ip($pr['ip'])); system("php propagate.php block current '$peer_host' '$pr[ip]' > /dev/null 2>&1 &"); _log('['.$ip."] block too old, sending our current block - $data[height]"); @@ -243,6 +245,7 @@ if ($q == "peer") { _log('['.$ip."] block ok, repropagating - $data[height]"); // send it to all our peers + $data['id']=escapeshellcmd(san($data['id'])); system("php propagate.php block '$data[id]' all all linear > /dev/null 2>&1 &"); api_echo("block-ok"); } // return the current block, used in syncing diff --git a/propagate.php b/propagate.php index f9c7114..03636b9 100755 --- a/propagate.php +++ b/propagate.php @@ -69,9 +69,13 @@ if ((empty($peer) || $peer == 'all') && $type == "block") { foreach ($r as $x) { if($x['hostname']==$_config['hostname']) continue; // encode the hostname in base58 and sanitize the IP to avoid any second order shell injections - $host = base58_encode($x['hostname']); - $ip = filter_var($x['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE); + $host = escapeshellcmd(base58_encode($x['hostname'])); + $ip = escapeshellcmd(filter_var($x['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)); // fork a new process to send the blocks async + $type=escapeshellcmd(san($type)); + $id=escapeshellcmd(san($id)); + + if ($debug) { system("php propagate.php '$type' '$id' '$host' '$ip' debug"); } elseif ($linear) { @@ -166,7 +170,8 @@ if ($type == "transaction") { if ($data['peer'] == "local") { $r = $db->run("SELECT hostname FROM peers WHERE blacklisted < UNIX_TIMESTAMP()"); } else { - $r = $db->run("SELECT hostname FROM peers WHERE blacklisted < UNIX_TIMESTAMP() AND reserve=0 ORDER by RAND() LIMIT ".intval($_config['transaction_propagation_peers'])); + + $r = $db->run("SELECT hostname FROM peers WHERE blacklisted < UNIX_TIMESTAMP() AND reserve=0 ORDER by RAND() LIMIT :limit",["limit"=>intval($_config['transaction_propagation_peers'])]); } foreach ($r as $x) { $res = peer_post($x['hostname']."/peer.php?q=submitTransaction", $data); diff --git a/sanity.php b/sanity.php index 69d7426..736e0cc 100755 --- a/sanity.php +++ b/sanity.php @@ -670,14 +670,14 @@ $db->run("DELETE FROM `mempool` WHERE `date` < UNIX_TIMESTAMP()-(3600*24*14)"); //rebroadcasting local transactions -if ($_config['sanity_rebroadcast_locals'] == true) { +if ($_config['sanity_rebroadcast_locals'] == true && $_config['disable_repropagation'] == false) { $r = $db->run( "SELECT id FROM mempool WHERE height>=:current and peer='local' order by `height` asc LIMIT 20", [":current" => $current['height']] ); _log("Rebroadcasting local transactions - ".count($r)); foreach ($r as $x) { - $x['id'] = san($x['id']); + $x['id'] = escapeshellarg(san($x['id'])); // i know it's redundant due to san(), but some people are too scared of any exec system("php propagate.php transaction $x[id] > /dev/null 2>&1 &"); $db->run( "UPDATE mempool SET height=:current WHERE id=:id", @@ -687,21 +687,22 @@ if ($_config['sanity_rebroadcast_locals'] == true) { } //rebroadcasting transactions -$forgotten = $current['height'] - $_config['sanity_rebroadcast_height']; -$r = $db->run( +if ($_config['disable_repropagation'] == false) { + $forgotten = $current['height'] - $_config['sanity_rebroadcast_height']; + $r = $db->run( "SELECT id FROM mempool WHERE height<:forgotten ORDER by val DESC LIMIT 10", [":forgotten" => $forgotten] ); -_log("Rebroadcasting external transactions - ".count($r)); + _log("Rebroadcasting external transactions - ".count($r)); -foreach ($r as $x) { - $x['id'] = san($x['id']); - system("php propagate.php transaction $x[id] > /dev/null 2>&1 &"); - $db->run("UPDATE mempool SET height=:current WHERE id=:id", [":id" => $x['id'], ":current" => $current['height']]); + foreach ($r as $x) { + $x['id'] = escapeshellarg(san($x['id'])); // i know it's redundant due to san(), but some people are too scared of any exec + system("php propagate.php transaction $x[id] > /dev/null 2>&1 &"); + $db->run("UPDATE mempool SET height=:current WHERE id=:id", [":id" => $x['id'], ":current" => $current['height']]); + } } - //add new peers if there aren't enough active if ($total_peers < $_config['max_peers'] * 0.7) { $res = $_config['max_peers'] - $total_peers; @@ -709,7 +710,7 @@ if ($total_peers < $_config['max_peers'] * 0.7) { } //random peer check -$r = $db->run("SELECT * FROM peers WHERE blacklistedrun("SELECT * FROM peers WHERE blacklistedintval($_config['max_test_peers'])]); foreach ($r as $x) { $url = $x['hostname']."/peer.php?q="; $data = peer_post($url."ping", [], 5); diff --git a/util.php b/util.php index 251561f..5a39822 100755 --- a/util.php +++ b/util.php @@ -193,7 +193,7 @@ elseif ($cmd == "blocks") { if ($limit < 1) { $limit = 100; } - $r = $db->run("SELECT * FROM blocks WHERE height>:height ORDER by height ASC LIMIT $limit", [":height" => $height]); + $r = $db->run("SELECT * FROM blocks WHERE height>:height ORDER by height ASC LIMIT :limit", [":height" => $height, ":limit"=>$limit]); foreach ($r as $x) { echo "$x[height]\t$x[id]\n"; } @@ -458,7 +458,10 @@ elseif ($cmd == 'get-address') { echo "All the peers have been removed from the blacklist\n"; } elseif ($cmd == 'resync-accounts') { // resyncs the balance on all accounts - + if (file_exists("tmp/sanity-lock")) { + die("Sanity running. Wait for it to finish"); + } + touch("tmp/sanity-lock"); // lock table to avoid race conditions on blocks $db->exec("LOCK TABLES blocks WRITE, accounts WRITE, transactions WRITE, mempool WRITE"); @@ -483,6 +486,7 @@ elseif ($cmd == 'get-address') { } $db->exec("UNLOCK TABLES"); echo "All done"; + unlink("tmp/sanity-lock"); } elseif ($cmd=="compare-blocks") { $block=new Block(); @@ -526,15 +530,67 @@ elseif ($cmd == 'get-address') { $current=$block->current(); echo "Height:\t\t$current[height]\n"; echo "Hash:\t\t".md5(json_encode($res))."\n\n"; - } elseif ($cmd=='accounts-hash') { - $res=$db->run("SELECT * FROM accounts ORDER by public_key ASC"); + $res=$db->run("SELECT * FROM accounts ORDER by id 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"; +} elseif ($cmd == "sendblock"){ + $peer=trim($argv[3]); + if (!filter_var($peer, FILTER_VALIDATE_URL)) { + die("Invalid peer hostname"); + } + $peer = filter_var($peer, FILTER_SANITIZE_URL); + $height=intval($argv[2]); + $block=new Block(); + $data = $block->export("", $height); + + + if($data===false){ + die("Could not find this block"); + } + $response = peer_post($peer."/peer.php?q=submitBlock", $data, 60, true); + var_dump($response); + +}elseif ($cmd == "recheck-external-blocks") { + $peer=trim($argv[2]); + if (!filter_var($peer, FILTER_VALIDATE_URL)) { + die("Invalid peer hostname"); + } + $peer = filter_var($peer, FILTER_SANITIZE_URL); + + + $blocks = []; + $block = new Block(); + $height=intval($argv[3]); + + $last=peer_post($peer."/peer.php?q=currentBlock"); + + $b=peer_post($peer."/peer.php?q=getBlock",["height"=>$height]); + + for ($i = $height+1; $i <= $last['height']; $i++) { + $c=peer_post($peer."/peer.php?q=getBlock",["height"=>$i]); + + if (!$block->mine( + $c['public_key'], + $c['nonce'], + $c['argon'], + $c['difficulty'], + $b['id'], + $b['height'], + $c['date'] + )) { + print("Invalid block detected. $c[height] - $c[id]\n"); + break; + } + echo "Block $i -> ok\n"; + $b=$c; + } + + } else { echo "Invalid command\n"; }