resync if stale

This commit is contained in:
admin@arionum.com
2019-12-26 14:52:12 +02:00
parent 8a9715f306
commit 16d205ff06
3 changed files with 72 additions and 64 deletions

14
api.php
View File

@@ -664,12 +664,18 @@ if ($q == "getAddress") {
* @apiGroup API * @apiGroup API
* @apiDescription Returns all the masternode data * @apiDescription Returns all the masternode data
* *
* @apiParam {string} [public_key] Optional public key
* *
* * @apiSuccess {json} data masternode date
* @apiSuccess {boolean} data masternode date
*/ */
$bind=[];
$res=$db->run("SELECT * FROM masternode ORDER by public_key ASC"); $whr='';
$public_key=san($data['public_key']);
if(!empty($public_key)){
$whr="WHERE public_key=:public_key";
$bind[':public_key']=$public_key;
}
$res=$db->run("SELECT * FROM masternode $whr ORDER by public_key ASC",$bind);
api_echo(["masternodes"=>$res, "hash"=>md5(json_encode($res))]); api_echo(["masternodes"=>$res, "hash"=>md5(json_encode($res))]);
} elseif ($q == "getAlias") { } elseif ($q == "getAlias") {

View File

@@ -1320,12 +1320,13 @@ class Block
public function pop($no = 1) public function pop($no = 1)
{ {
$current = $this->current(); $current = $this->current();
$this->delete($current['height'] - $no + 1); return $this->delete($current['height'] - $no + 1);
} }
// delete all blocks >= height // delete all blocks >= height
public function delete($height) public function delete($height)
{ {
global $_config;
if ($height < 2) { if ($height < 2) {
$height = 2; $height = 2;
} }
@@ -1335,7 +1336,7 @@ class Block
$r = $db->run("SELECT * FROM blocks WHERE height>=:height ORDER by height DESC", [":height" => $height]); $r = $db->run("SELECT * FROM blocks WHERE height>=:height ORDER by height DESC", [":height" => $height]);
if (count($r) == 0) { if (count($r) == 0) {
return; return true;
} }
$db->beginTransaction(); $db->beginTransaction();
$db->exec("LOCK TABLES blocks WRITE, accounts WRITE, transactions WRITE, mempool WRITE, masternode WRITE, peers write, config WRITE, assets WRITE, assets_balance WRITE, assets_market WRITE, votes WRITE,logs WRITE"); $db->exec("LOCK TABLES blocks WRITE, accounts WRITE, transactions WRITE, mempool WRITE, masternode WRITE, peers write, config WRITE, assets WRITE, assets_balance WRITE, assets_market WRITE, votes WRITE,logs WRITE");
@@ -1345,6 +1346,25 @@ class Block
if ($res === false) { if ($res === false) {
_log("A transaction could not be reversed. Delete block failed."); _log("A transaction could not be reversed. Delete block failed.");
$db->rollback(); $db->rollback();
// the blockchain has some flaw, we should resync from scratch
$current = $this->current();
if (($current['date']<time()-(3600*48)) && $_config['auto_resync']!==false) {
_log("Blockchain corrupted. Resyncing from scratch.");
$db->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;");
$db->exec("UNLOCK TABLES");
$db->run("UPDATE config SET val=0 WHERE cfg='sanity_sync'");
@unlink(SANITY_LOCK_PATH);
system("php sanity.php > /dev/null 2>&1 &");
exit;
}
$db->exec("UNLOCK TABLES"); $db->exec("UNLOCK TABLES");
return false; return false;
} }

View File

@@ -47,8 +47,8 @@ if (file_exists(SANITY_LOCK_PATH)) {
} }
$pid_time = filemtime(SANITY_LOCK_PATH); $pid_time = filemtime(SANITY_LOCK_PATH);
// If the process died, restart after 10 times the sanity interval // If the process died, restart after 60 times the sanity interval
if (time() - $pid_time > ($_config['sanity_interval'] * 20 ?? 900 * 20)) { if (time() - $pid_time > ($_config['sanity_interval'] * 60 ?? 900 * 60)) {
@unlink(SANITY_LOCK_PATH); @unlink(SANITY_LOCK_PATH);
} }
@@ -387,9 +387,9 @@ foreach ($r as $x) {
_log("Peer $x[hostname] unresponsive"); _log("Peer $x[hostname] unresponsive");
// if the peer is unresponsive, mark it as failed and blacklist it for a while // if the peer is unresponsive, mark it as failed and blacklist it for a while
$db->run( $db->run(
"UPDATE peers SET fails=fails+1, blacklisted=UNIX_TIMESTAMP()+((fails+1)*3600) WHERE id=:id", "UPDATE peers SET fails=fails+1, blacklisted=UNIX_TIMESTAMP()+((fails+1)*3600) WHERE id=:id",
[":id" => $x['id']] [":id" => $x['id']]
); );
continue; continue;
} }
@@ -457,6 +457,8 @@ echo "Most common block: $most_common_size\n";
echo "Max height: $largest_height\n"; echo "Max height: $largest_height\n";
echo "Current block: $current[height]\n"; echo "Current block: $current[height]\n";
$block_parse_failed=false; $block_parse_failed=false;
$failed_syncs=0;
// if we're not on the largest height // if we're not on the largest height
if ($current['height'] < $largest_height && $largest_height > 1) { if ($current['height'] < $largest_height && $largest_height > 1) {
// start sanity sync / block all other transactions/blocks // start sanity sync / block all other transactions/blocks
@@ -510,7 +512,11 @@ if ($current['height'] < $largest_height && $largest_height > 1) {
} }
} }
if ($last_good==$current['height']-1) { if ($last_good==$current['height']-1) {
$block->pop(1); $try_pop=$block->pop(1);
if($try_pop==false){
// we can't pop the last block, we should resync
$block_parse_failed=true;
}
} }
// if last 10 blocks are good, verify all the blocks // if last 10 blocks are good, verify all the blocks
if ($invalid == false) { if ($invalid == false) {
@@ -545,7 +551,11 @@ if ($current['height'] < $largest_height && $largest_height > 1) {
// if the blockchain proves ok, delete until the last block // if the blockchain proves ok, delete until the last block
if ($invalid == false) { if ($invalid == false) {
_log("Changing fork, deleting $last_good", 1); _log("Changing fork, deleting $last_good", 1);
$block->delete($last_good); $res=$block->delete($last_good);
if($res==false){
$block_parse_failed=true;
break;
}
$current = $block->current(); $current = $block->current();
$data = $current; $data = $current;
} }
@@ -571,6 +581,7 @@ if ($current['height'] < $largest_height && $largest_height > 1) {
$block_parse_failed=true; $block_parse_failed=true;
_log("Block check: could not add block - $b[id] - $b[height]"); _log("Block check: could not add block - $b[id] - $b[height]");
$good_peer = false; $good_peer = false;
$failed_syncs++;
break; break;
} }
$res = $block->add( $res = $block->add(
@@ -588,6 +599,7 @@ if ($current['height'] < $largest_height && $largest_height > 1) {
$block_parse_failed=true; $block_parse_failed=true;
_log("Block add: could not add block - $b[id] - $b[height]"); _log("Block add: could not add block - $b[id] - $b[height]");
$good_peer = false; $good_peer = false;
$failed_syncs++;
break; break;
} }
@@ -601,26 +613,15 @@ if ($current['height'] < $largest_height && $largest_height > 1) {
if ($good_peer) { if ($good_peer) {
break; break;
} }
} if ($failed_syncs>5) {
break;
$resyncing=false;
if ($block_parse_failed==true&&$current['date']<time()-(3600*24)) {
_log("Rechecking reward transactions");
$current = $block->current();
$rwpb=$db->single("SELECT COUNT(1) FROM transactions WHERE version=0 AND message=''");
if ($rwpb!=$current['height']) {
$failed=$db->single("SELECT blocks.height FROM blocks LEFT JOIN transactions ON transactions.block=blocks.id and transactions.version=0 and transactions.message='' WHERE transactions.height is NULL ORDER by blocks.height ASC LIMIT 1");
if ($failed>1) {
_log("Found failed block - $faield");
$block->delete($failed);
$block_parse_failed==false;
}
} }
} }
if ($block_parse_failed==true||$argv[1]=="resync") { if ($block_parse_failed==true||$argv[1]=="resync") {
$last_resync=$db->single("SELECT val FROM config WHERE cfg='last_resync'"); $last_resync=$db->single("SELECT val FROM config WHERE cfg='last_resync'");
if ($last_resync<time()-(3600*24)||$argv[1]=="resync") { if ($last_resync<time()-(3600*24)||$argv[1]=="resync") {
if ((( ($current['date']<time()-(3600*72) ) && $_config['auto_resync'])!==false ) || $argv[1]=="resync" ) { if ((($current['date']<time()-(3600*72)) && $_config['auto_resync']!==false) || $argv[1]=="resync") {
$db->run("SET foreign_key_checks=0;"); $db->run("SET foreign_key_checks=0;");
$tables = ["accounts", "transactions", "mempool", "masternode","blocks"]; $tables = ["accounts", "transactions", "mempool", "masternode","blocks"];
foreach ($tables as $table) { foreach ($tables as $table) {
@@ -641,42 +642,6 @@ if ($current['height'] < $largest_height && $largest_height > 1) {
$resyncing=true; $resyncing=true;
} }
// needs to be redone due to the assets
// if ($resyncing==true) {
// _log("Resyncing accounts");
// $db->run("INSERT into config SET val=UNIX_TIMESTAMP(), cfg='last_resync' ON DUPLICATE KEY UPDATE val=UNIX_TIMESTAMP()");
// $db->exec("LOCK TABLES blocks WRITE, accounts WRITE, transactions WRITE, mempool WRITE, masternode WRITE, peers write, config WRITE, assets WRITE, assets_balance WRITE, assets_market 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<111", [":id"=>$x['id'], ":alias"=>$alias]);
// $releases=$db->single("SELECT COUNT(1) FROM transactions WHERE dst=:id AND version=103", [":id"=>$x['id']]);
// if ($releases>0) { //masternode releases
// $rec+=$releases*100000;
// }
// $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]);
// }
// }
// }
// $current = $block->current();
// $db->run("DELETE FROM masternode WHERE height>:h", [":h"=>$current['height']]);
// $db->exec("UNLOCK TABLES");
// }
} }
} }
@@ -685,6 +650,23 @@ if ($current['height'] < $largest_height && $largest_height > 1) {
} }
$resyncing=false;
if ($block_parse_failed==true&&$current['date']<time()-(3600*24)) {
_log("Rechecking reward transactions");
$current = $block->current();
$rwpb=$db->single("SELECT COUNT(1) FROM transactions WHERE version=0 AND message=''");
if ($rwpb!=$current['height']) {
$failed=$db->single("SELECT blocks.height FROM blocks LEFT JOIN transactions ON transactions.block=blocks.id and transactions.version=0 and transactions.message='' WHERE transactions.height is NULL ORDER by blocks.height ASC LIMIT 1");
if ($failed>1) {
_log("Found failed block - $faield");
$block->delete($failed);
$block_parse_failed==false;
}
}
}
// deleting mempool transactions older than 14 days // deleting mempool transactions older than 14 days
$db->run("DELETE FROM `mempool` WHERE `date` < UNIX_TIMESTAMP()-(3600*24*14)"); $db->run("DELETE FROM `mempool` WHERE `date` < UNIX_TIMESTAMP()-(3600*24*14)");