tested hf
This commit is contained in:
		
							
								
								
									
										2
									
								
								api.php
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								api.php
									
									
									
									
									
								
							| @@ -487,7 +487,7 @@ if ($q == "getAddress") { | |||||||
|     if ($fee > 10 && $current['height'] > 10800) { |     if ($fee > 10 && $current['height'] > 10800) { | ||||||
|         $fee = 10; //10800 |         $fee = 10; //10800 | ||||||
|     } |     } | ||||||
|     if ($val < 0.00000001) { |     if ($val < 0) { | ||||||
|         api_err("Invalid value"); |         api_err("Invalid value"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,6 +2,33 @@ | |||||||
|  |  | ||||||
| class Block | class Block | ||||||
| { | { | ||||||
|  |     public function add_log($hash, $log) | ||||||
|  |     { | ||||||
|  |         global $db; | ||||||
|  |         $hash=san($hash); | ||||||
|  |         //$json=["table"=>"masternode", "key"=>"public_key","id"=>$x['public_key'], "vals"=>['ip'=>$current_ip] ]; | ||||||
|  |         $db->run("INSERT into logs SET block=:id, json=:json", [':id'=>$hash, ":json"=>json_encode($log)]); | ||||||
|  |     } | ||||||
|  |     public function reverse_log($hash) | ||||||
|  |     { | ||||||
|  |         global $db; | ||||||
|  |         $r=$db->run("SELECT json, id FROM logs WHERE block=:id ORDER by id DESC", [":id"=>$hash]); | ||||||
|  |         foreach ($r as $json) { | ||||||
|  |             $old=json_decode($json['json'], true); | ||||||
|  |             if ($old!==false&&is_array($old)) { | ||||||
|  |                 //making sure there's no sql injection here, as the table name and keys are sanitized to A-Za-z0-9_ | ||||||
|  |                 $table=san($old['table']); | ||||||
|  |                 $key=san($old['key'], '_'); | ||||||
|  |                 $id=san($old['id'], '_'); | ||||||
|  |                 foreach ($old['vals'] as $v=>$l) { | ||||||
|  |                     $v=san($v, '_'); | ||||||
|  |                     $db->run("UPDATE `$table` SET `$v`=:val WHERE `$key`=:keyid", [":keyid"=>$id, ":val"=>$l]); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             $db->run("DELETE FROM logs WHERE id=:id", [":id"=>$json['id']]); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     public function add($height, $public_key, $nonce, $data, $date, $signature, $difficulty, $reward_signature, $argon, $bootstrapping=false) |     public function add($height, $public_key, $nonce, $data, $date, $signature, $difficulty, $reward_signature, $argon, $bootstrapping=false) | ||||||
|     { |     { | ||||||
|         global $db; |         global $db; | ||||||
| @@ -37,7 +64,7 @@ class Block | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         // lock table to avoid race conditions on blocks |         // lock table to avoid race conditions on blocks | ||||||
|         $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"); |         $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"); | ||||||
|  |  | ||||||
|         $reward = $this->reward($height, $data); |         $reward = $this->reward($height, $data); | ||||||
|  |  | ||||||
| @@ -46,25 +73,24 @@ class Block | |||||||
|         $mn_reward_rate=0.33; |         $mn_reward_rate=0.33; | ||||||
|    |    | ||||||
|         // hf |         // hf | ||||||
|         if($height>212000){ |         if ($height>216000) { | ||||||
|             $votes=[]; |             $votes=[]; | ||||||
|             $r=$db->run("SELECT id,val FROM votes"); |             $r=$db->run("SELECT id,val FROM votes"); | ||||||
|             foreach($r as $vote){ |             foreach ($r as $vote) { | ||||||
|                 $votes[$vote['id']]=$vote['val']; |                 $votes[$vote['id']]=$vote['val']; | ||||||
|             } |             } | ||||||
|             // emission cut by 30% |             // emission cut by 30% | ||||||
|             if($votes['emission30']==1){ |             if ($votes['emission30']==1) { | ||||||
|                 $reward=round($reward*0.7); |                 $reward=round($reward*0.7); | ||||||
|             } |             } | ||||||
|             // 50% to masternodes |             // 50% to masternodes | ||||||
|             if($votes['masternodereward50']==1){ |             if ($votes['masternodereward50']==1) { | ||||||
|                 $mn_reward_rate=0.5; |                 $mn_reward_rate=0.5; | ||||||
|             } |             } | ||||||
|             // minimum reward to always be 50 aro |             // minimum reward to always be 10 aro | ||||||
|             if($votes['endless50reward']==1&&$reward<50){ |             if ($votes['endless10reward']==1&&$reward<10) { | ||||||
|                 $reward=50; |                 $reward=10; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -84,7 +110,21 @@ class Block | |||||||
|                 _log("MN Reward: $mn_reward", 2); |                 _log("MN Reward: $mn_reward", 2); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |         $cold_winner=false; | ||||||
|  |         $cold_reward=0; | ||||||
|  |         if ($height>216000) { | ||||||
|  |             if ($votes['coldstacking']==1) { | ||||||
|  |                 $cold_reward=round($mn_reward*0.2, 8); | ||||||
|  |                 $mn_reward=$mn_reward-$cold_reward; | ||||||
|  |                 $mn_reward=number_format($mn_reward, 8, ".", ""); | ||||||
|  |                 $cold_reward=number_format($cold_reward, 8, ".", ""); | ||||||
|  |                 $cold_winner=$db->single( | ||||||
|  |                         "SELECT public_key FROM masternode WHERE height<:start ORDER by cold_last_won ASC, public_key ASC LIMIT 1", | ||||||
|  |                         [":current"=>$height, ":start"=>$height-360] | ||||||
|  |                     ); | ||||||
|  |                 _log("Cold MN Winner: $mn_winner", 2); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|          |          | ||||||
|  |  | ||||||
| @@ -147,7 +187,39 @@ class Block | |||||||
|             $db->exec("UNLOCK TABLES"); |             $db->exec("UNLOCK TABLES"); | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
|  |         //masternode rewards | ||||||
|         if ($mn_winner!==false&&$height>=80458&&$mn_reward>0) { |         if ($mn_winner!==false&&$height>=80458&&$mn_reward>0) { | ||||||
|  |             //cold stacking rewards | ||||||
|  |             if ($cold_winner!==false&&$height>216000&&$cold_reward>0) { | ||||||
|  |                 $db->run("UPDATE accounts SET balance=balance+:bal WHERE public_key=:pub", [":pub"=>$cold_winner, ":bal"=>$cold_reward]); | ||||||
|  |              | ||||||
|  |                 $bind = [ | ||||||
|  |             ":id"         => hex2coin(hash("sha512", "cold".$hash.$height.$cold_winner)), | ||||||
|  |             ":public_key" => $public_key, | ||||||
|  |             ":height"     => $height, | ||||||
|  |             ":block"      => $hash, | ||||||
|  |             ":dst"        => $acc->get_address($cold_winner), | ||||||
|  |             ":val"        => $cold_reward, | ||||||
|  |             ":fee"        => 0, | ||||||
|  |             ":signature"  => $reward_signature, | ||||||
|  |             ":version"    => 0, | ||||||
|  |             ":date"       => $date, | ||||||
|  |             ":message"    => 'masternode-cold', | ||||||
|  |         ]; | ||||||
|  |                 $res = $db->run( | ||||||
|  |                 "INSERT into transactions SET id=:id, public_key=:public_key, block=:block,  height=:height, dst=:dst, val=:val, fee=:fee, signature=:signature, version=:version, message=:message, `date`=:date", | ||||||
|  |                 $bind | ||||||
|  |         ); | ||||||
|  |                 if ($res != 1) { | ||||||
|  |                     // rollback and exit if it fails | ||||||
|  |                     _log("Masternode Cold reward DB insert failed"); | ||||||
|  |                     $db->rollback(); | ||||||
|  |                     $db->exec("UNLOCK TABLES"); | ||||||
|  |                     return false; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |  | ||||||
|             $db->run("UPDATE accounts SET balance=balance+:bal WHERE public_key=:pub", [":pub"=>$mn_winner, ":bal"=>$mn_reward]); |             $db->run("UPDATE accounts SET balance=balance+:bal WHERE public_key=:pub", [":pub"=>$mn_winner, ":bal"=>$mn_reward]); | ||||||
|             $bind = [ |             $bind = [ | ||||||
|             ":id"         => hex2coin(hash("sha512", "mn".$hash.$height.$mn_winner)), |             ":id"         => hex2coin(hash("sha512", "mn".$hash.$height.$mn_winner)), | ||||||
| @@ -163,8 +235,8 @@ class Block | |||||||
|             ":message"    => 'masternode', |             ":message"    => 'masternode', | ||||||
|         ]; |         ]; | ||||||
|             $res = $db->run( |             $res = $db->run( | ||||||
|             "INSERT into transactions SET id=:id, public_key=:public_key, block=:block,  height=:height, dst=:dst, val=:val, fee=:fee, signature=:signature, version=:version, message=:message, `date`=:date", |                 "INSERT into transactions SET id=:id, public_key=:public_key, block=:block,  height=:height, dst=:dst, val=:val, fee=:fee, signature=:signature, version=:version, message=:message, `date`=:date", | ||||||
|             $bind |                 $bind | ||||||
|         ); |         ); | ||||||
|             if ($res != 1) { |             if ($res != 1) { | ||||||
|                 // rollback and exit if it fails |                 // rollback and exit if it fails | ||||||
| @@ -185,9 +257,6 @@ class Block | |||||||
|              |              | ||||||
|  |  | ||||||
|             $this->do_hard_forks($height, $hash); |             $this->do_hard_forks($height, $hash); | ||||||
|  |  | ||||||
|  |  | ||||||
|   |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // parse the block's transactions and insert them to db |         // parse the block's transactions and insert them to db | ||||||
| @@ -198,19 +267,26 @@ class Block | |||||||
|             $this->reset_fails_masternodes($public_key, $height, $hash); |             $this->reset_fails_masternodes($public_key, $height, $hash); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|            // automated asset distribution, checked only every 1000 blocks to reduce load. Payouts every 10000 blocks. |         // automated asset distribution, checked only every 1000 blocks to reduce load. Payouts every 10000 blocks. | ||||||
|  |  | ||||||
|         if($height>11111  && $height%50==1 && $res==true){ //  every 50 for testing. No initial height set yet. |         if ($height>216000  && $height%50==1 && $res==true) { //  every 50 for testing. No initial height set yet. | ||||||
|             $res=$this->asset_distribute_dividends($height, $hash, $public_key, $date, $signature); |             $res=$this->asset_distribute_dividends($height, $hash, $public_key, $date, $signature); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if($height>11111 && $res==true){ |         if ($height>216000 && $res==true) { | ||||||
|             $res=$this->asset_market_orders($height, $hash, $public_key, $date, $signature); |             $res=$this->asset_market_orders($height, $hash, $public_key, $date, $signature); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         if ($height>216000 && $height%10000==0) { | ||||||
|  |             $res=$this->masternode_votes($public_key, $height, $hash); | ||||||
|  |         } | ||||||
|  |          | ||||||
|         // if any fails, rollback |         // if any fails, rollback | ||||||
|         if ($res == false) { |         if ($res == false) { | ||||||
|  |             _log("Rollback block",3); | ||||||
|             $db->rollback(); |             $db->rollback(); | ||||||
|         } else { |         } else { | ||||||
|  |             _log("Commiting block",3); | ||||||
|             $db->commit(); |             $db->commit(); | ||||||
|         } |         } | ||||||
|         // relese the locking as everything is finished |         // relese the locking as everything is finished | ||||||
| @@ -218,38 +294,131 @@ class Block | |||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     public function masternode_votes($public_key, $height, $hash) | ||||||
|  |     { | ||||||
|  |         global $db; | ||||||
|  |  | ||||||
|  |         $arodev='PZ8Tyr4Nx8MHsRAGMpZmZ6TWY63dXWSCvcUb8x4p38GFbZWaJKcncEWqUbe7YJtrDXomwn7DtDYuyYnN2j6s4nQxP1u9BiwCA8U4TjtC9Z21j3R3STLJSFyL'; | ||||||
|  |         //testnet | ||||||
|  |         $arodev='PZ8Tyr4Nx8MHsRAGMpZmZ6TWY63dXWSD1AyyUtViMXaRS1cLfRRwBgUYzDgqhHcssWSutK966KwBKTPJNpNxcb8snJomuL6jdNd9x53udEzHcq3ooL3MhYtB';  | ||||||
|  |  | ||||||
|  |         // masternode votes | ||||||
|  |         if ($height%10000==0) { | ||||||
|  |             _log("Checking masternode votes", 3); | ||||||
|  |             $blacklist=[]; | ||||||
|  |             $total_mns=$db->single("SELECT COUNT(1) FROM masternode"); | ||||||
|  |             $total_mns_with_key=$db->single("SELECT COUNT(1) FROM masternode WHERE vote_key IS NOT NULL"); | ||||||
|  |              | ||||||
|  |             // only if at least 50% of the masternodes have voting keys | ||||||
|  |             if ($total_mns_with_key/$total_mns>0.50) { | ||||||
|  |                 _log("Counting the votes from other masternodes", 3); | ||||||
|  |                 $r=$db->run("SELECT message, count(message) as c FROM transactions WHERE version=106 AND height>:height group by message", [':height'=>$height-10000]); | ||||||
|  |                 foreach ($r as $x) { | ||||||
|  |                     if ($x['c']>$total_mns/2) { | ||||||
|  |                         $blacklist[]=san($x['message']); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } else { | ||||||
|  |                 // If less than 50% of the mns have voting key, AroDev's votes are used | ||||||
|  |                 _log("Counting AroDev votes", 3); | ||||||
|  |                 $r=$db->run("SELECT message FROM transactions WHERE version=106 AND height>:height AND public_key=:pub", [':height'=>$height-10000, ":pub"=>$arodev]); | ||||||
|  |                 foreach ($r as $x) { | ||||||
|  |                     $blacklist[]=san($x['message']); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             $r=$db->run("SELECT public_key FROM masternode WHERE voted=1"); | ||||||
|  |             foreach ($r as $masternode) { | ||||||
|  |                 if (!in_array($masternode, $blacklist)) { | ||||||
|  |                     _log("Masternode removed from voting blacklist - $masternode", 3); | ||||||
|  |                     $this->add_log($hash, ["table"=>"masternode", "key"=>"public_key","id"=>$masternode, "vals"=>['voted'=>1]]); | ||||||
|  |                     $db->run("UPDATE masternode SET voted=0 WHERE public_key=:pub", [":pub"=>$masternode]); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             foreach ($blacklist as $masternode) { | ||||||
|  |                 $res=$db->single("SELECT voted FROM masternode WHERE public_key=:pub", [":pub"=>$masternode]); | ||||||
|  |                 if ($res==0) { | ||||||
|  |                     _log("Masternode blacklist voted - $masternode", 3); | ||||||
|  |                     $db->run("UPDATE masternode SET voted=1 WHERE public_key=:pub", [":pub"=>$masternode]); | ||||||
|  |                     $this->add_log($hash, ["table"=>"masternode", "key"=>"public_key","id"=>$masternode, "vals"=>['voted'=>0]]); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // blockchain votes | ||||||
|  |         $voted=[]; | ||||||
|  |         if ($height%100000==0) { | ||||||
|  |  | ||||||
|  |              // only if at least 50% of the masternodes have voting keys | ||||||
|  |             if ($total_mns_with_key/$total_mns>0.50) { | ||||||
|  |                 _log("Counting masternode blockchain votes", 3); | ||||||
|  |                 $r=$db->run("SELECT message, count(message) as c FROM transactions WHERE version=107 AND height>:height group by message", [':height'=>$height-100000]); | ||||||
|  |                 foreach ($r as $x) { | ||||||
|  |                     if ($x['c']>$total_mns/1.5) { | ||||||
|  |                         $voted[]=san($x['message']); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } else { | ||||||
|  |                 _log("Counting AroDev blockchain votes", 3); | ||||||
|  |                 // If less than 50% of the mns have voting key, AroDev's votes are used | ||||||
|  |                 $r=$db->run("SELECT message FROM transactions WHERE version=107 AND height>:height AND public_key=:pub", [':height'=>$height-100000, ":pub"=>$arodev]); | ||||||
|  |                 foreach ($r as $x) { | ||||||
|  |                     $voted[]=san($x['message']); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |             foreach ($voted as $vote) { | ||||||
|  |                 $v=$db->row("SELECT id, val FROM votes WHERE id=:id", [":id"=>$vote]); | ||||||
|  |                 if ($v) { | ||||||
|  |                     if ($v['val']==0) { | ||||||
|  |                         _log("Blockchain vote - $v[id] = 1", 3); | ||||||
|  |                         $db->run("UPDATE votes SET val=1 WHERE id=:id", [":id"=>$v['id']]); | ||||||
|  |                         $this->add_log($hash, ["table"=>"votes", "key"=>"id","id"=>$v['id'], "vals"=>['val'=>0]]); | ||||||
|  |                     } else { | ||||||
|  |                         _log("Blockchain vote - $v[id] = 0", 3); | ||||||
|  |                         $db->run("UPDATE votes SET val=0 WHERE id=:id", [":id"=>$v['id']]); | ||||||
|  |                         $this->add_log($hash, ["table"=>"votes", "key"=>"id","id"=>$v['id'], "vals"=>['val'=>1]]); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     public function asset_market_orders($height, $hash, $public_key, $date, $signature) |     public function asset_market_orders($height, $hash, $public_key, $date, $signature) | ||||||
|     { |     { | ||||||
|         global $db; |         global $db; | ||||||
|         $trx=new Transaction; |         $trx=new Transaction; | ||||||
|         // checks all bid market orders ordered in the same way on all nodes |         // checks all bid market orders ordered in the same way on all nodes | ||||||
|         $r=$db->run("SELECT * FROM assets_market WHERE status=0 and val_done<val AND type='bid' ORDER by asset ASC, id ASC"); |         $r=$db->run("SELECT * FROM assets_market WHERE status=0 and val_done<val AND type='bid' ORDER by asset ASC, id ASC"); | ||||||
|         foreach($r as $x){ |         foreach ($r as $x) { | ||||||
|             $finished=0; |             $finished=0; | ||||||
|             //remaining part of the order |             //remaining part of the order | ||||||
|             $val=$x['val']-$x['val_done']; |             $val=$x['val']-$x['val_done']; | ||||||
|                 // starts checking all ask orders that are still valid and are on the same price. should probably adapt this to allow lower price as well in the future. |             // starts checking all ask orders that are still valid and are on the same price. should probably adapt this to allow lower price as well in the future. | ||||||
|                 $asks=$db->run("SELECT * FROM assets_market WHERE status=0 and val_done<val AND asset=:asset AND price=:price AND type='ask' ORDER by price ASC, id ASC", [":asset"=>$x['asset'], ":price"=>$x['price']]);  |             $asks=$db->run("SELECT * FROM assets_market WHERE status=0 and val_done<val AND asset=:asset AND price=:price AND type='ask' ORDER by price ASC, id ASC", [":asset"=>$x['asset'], ":price"=>$x['price']]); | ||||||
|                 foreach($asks as $ask){ |             foreach ($asks as $ask) { | ||||||
|                     //remaining part of the order |                 //remaining part of the order | ||||||
|                     $remaining=$ask['val']-$ask['val_done']; |                 $remaining=$ask['val']-$ask['val_done']; | ||||||
|                     // how much of the ask should we use to fill the bid order |                 // how much of the ask should we use to fill the bid order | ||||||
|                     $use=0; |                 $use=0; | ||||||
|                     if($remaining>$val){  |                 if ($remaining>$val) { | ||||||
|                         $use=$val; |                     $use=$val; | ||||||
|                     } else { |                 } else { | ||||||
|                         $use=$remaining; |                     $use=$remaining; | ||||||
|                     } |                 } | ||||||
|                     $val-=$use; |                 $val-=$use; | ||||||
|                     $db->run("UPDATE assets_market SET val_done=val_done+:done WHERE id=:id",[":id"=>$ask['id'], ":done"=>$use]); |                 $db->run("UPDATE assets_market SET val_done=val_done+:done WHERE id=:id", [":id"=>$ask['id'], ":done"=>$use]); | ||||||
|                     $db->run("UPDATE assets_market SET val_done=val_done+:done WHERE id=:id",[":id"=>$x['id'], ":done"=>$use]); |                 $db->run("UPDATE assets_market SET val_done=val_done+:done WHERE id=:id", [":id"=>$x['id'], ":done"=>$use]); | ||||||
|                     // if we filled the order, we should exit the loop |                 // if we filled the order, we should exit the loop | ||||||
|                     $db->run("INSERT into assets_balance SET account=:account, asset=:asset, balance=:balance ON DUPLICATE KEY UPDATE balance=balance+:balance2",[":account"=>$x['account'], ":asset"=>$x['asset'], ":balance"=>$use, ":balance2"=>$use]); |                 $db->run("INSERT into assets_balance SET account=:account, asset=:asset, balance=:balance ON DUPLICATE KEY UPDATE balance=balance+:balance2", [":account"=>$x['account'], ":asset"=>$x['asset'], ":balance"=>$use, ":balance2"=>$use]); | ||||||
|                     $aro=$use*$x['price']; |                 $aro=$use*$x['price']; | ||||||
|                     $db->run("UPDATE accounts SET balance=balance+:balance WHERE id=:id",[":balance"=>$aro, ":id"=>$ask['account']]); |                 $db->run("UPDATE accounts SET balance=balance+:balance WHERE id=:id", [":balance"=>$aro, ":id"=>$ask['account']]); | ||||||
|  |  | ||||||
|                     $random = hex2coin(hash("sha512", $x['id'].$ask['id'].$val.$hash)); |                 $random = hex2coin(hash("sha512", $x['id'].$ask['id'].$val.$hash)); | ||||||
|                     $new = [ |                 $new = [ | ||||||
|                         "id"         => $random, |                         "id"         => $random, | ||||||
|                         "public_key" => $x['id'], |                         "public_key" => $x['id'], | ||||||
|                         "dst"        => $ask['id'], |                         "dst"        => $ask['id'], | ||||||
| @@ -261,14 +430,14 @@ class Block | |||||||
|                         "message"    => $use |                         "message"    => $use | ||||||
|                     ]; |                     ]; | ||||||
|                      |                      | ||||||
|                     $res=$trx->add($hash,$height,$new); |                 $res=$trx->add($hash, $height, $new); | ||||||
|                     if(!$res){ |                 if (!$res) { | ||||||
|                         return false; |                     return false; | ||||||
|                     } |  | ||||||
|                     if($val<=0){ |  | ||||||
|                         break; |  | ||||||
|                     } |  | ||||||
|                 } |                 } | ||||||
|  |                 if ($val<=0) { | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -281,24 +450,24 @@ class Block | |||||||
|     { |     { | ||||||
|         global $db; |         global $db; | ||||||
|         $trx=new Transaction; |         $trx=new Transaction; | ||||||
|         _log("Starting automated dividend distribution",3); |         _log("Starting automated dividend distribution", 3); | ||||||
|         // just the assets with autodividend |         // just the assets with autodividend | ||||||
|         $r=$db->run("SELECT * FROM assets WHERE auto_dividend=1"); |         $r=$db->run("SELECT * FROM assets WHERE auto_dividend=1"); | ||||||
|          |          | ||||||
|         if($r===false){ |         if ($r===false) { | ||||||
|             return true; |             return true; | ||||||
|         } |         } | ||||||
|         foreach($r as $x){ |         foreach ($r as $x) { | ||||||
|             $asset=$db->row("SELECT id, public_key, balance FROM accounts WHERE id=:id",[":id"=>$x['id']]); |             $asset=$db->row("SELECT id, public_key, balance FROM accounts WHERE id=:id", [":id"=>$x['id']]); | ||||||
|             // minimum balance 1 aro |             // minimum balance 1 aro | ||||||
|             if($asset['balance']<1) { |             if ($asset['balance']<1) { | ||||||
|                 _log("Asset $asset[id] not enough balance",3); |                 _log("Asset $asset[id] not enough balance", 3); | ||||||
|                 continue; |                 continue; | ||||||
|             } |             } | ||||||
|             _log("Autodividend $asset[id] - $asset[balance] ARO",3); |             _log("Autodividend $asset[id] - $asset[balance] ARO", 3); | ||||||
|             // every 10000 blocks and at minimum 10000 of asset creation or last distribution, manual or automated |             // every 10000 blocks and at minimum 10000 of asset creation or last distribution, manual or automated | ||||||
|             $last=$db->single("SELECT height FROM transactions WHERE (version=54 OR version=50 or version=57) AND public_key=:pub ORDER by height DESC LIMIT 1",[":pub"=>$asset['public_key']]); |             $last=$db->single("SELECT height FROM transactions WHERE (version=54 OR version=50 or version=57) AND public_key=:pub ORDER by height DESC LIMIT 1", [":pub"=>$asset['public_key']]); | ||||||
|             if($height<$last+100){ // 100 for testnet |             if ($height<$last+100) { // 100 for testnet | ||||||
|                 continue; |                 continue; | ||||||
|             } |             } | ||||||
|             // generate a pseudorandom id  and version 54 transaction for automated dividend distribution. No fees for such automated distributions to encourage the system |             // generate a pseudorandom id  and version 54 transaction for automated dividend distribution. No fees for such automated distributions to encourage the system | ||||||
| @@ -315,8 +484,8 @@ class Block | |||||||
|                 "src"        => $asset['id'], |                 "src"        => $asset['id'], | ||||||
|                 "message"    => '', |                 "message"    => '', | ||||||
|             ]; |             ]; | ||||||
|             $res=$trx->add($hash,$height,$new); |             $res=$trx->add($hash, $height, $new); | ||||||
|             if(!$res){ |             if (!$res) { | ||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @@ -382,8 +551,8 @@ class Block | |||||||
|             // their locked coins are added to dev's safewallet |             // their locked coins are added to dev's safewallet | ||||||
|             $id=hex2coin(hash("sha512", "hf".$block.$height.'compromised-masternodes')); |             $id=hex2coin(hash("sha512", "hf".$block.$height.'compromised-masternodes')); | ||||||
|             $res=$db->run( |             $res=$db->run( | ||||||
|                         "INSERT into transactions SET id=:id, block=:block, height=:height, dst=:dst, val=4700000, fee=0, signature=:sig, version=0, message=:msg, date=:date, public_key=:public_key", |                 "INSERT into transactions SET id=:id, block=:block, height=:height, dst=:dst, val=4700000, fee=0, signature=:sig, version=0, message=:msg, date=:date, public_key=:public_key", | ||||||
|             [":id"=>$id, ":block"=>$block, ":height"=>$height, ":dst"=>'4kWXV4HMuogUcjZBEzmmQdtc1dHzta6VykhCV1HWyEXK7kRWEMJLNoMWbuDwFMTfBrq5a9VthkZfmkMkamTfwRBP', ":sig"=>$id, ":msg"=>'compromised-masternodes-hf', ":date"=>time(), ":public_key"=>'4kWXV4HMuogUcjZBEzmmQdtc1dHzta6VykhCV1HWyEXK7kRWEMJLNoMWbuDwFMTfBrq5a9VthkZfmkMkamTfwRBP'] |                 [":id"=>$id, ":block"=>$block, ":height"=>$height, ":dst"=>'4kWXV4HMuogUcjZBEzmmQdtc1dHzta6VykhCV1HWyEXK7kRWEMJLNoMWbuDwFMTfBrq5a9VthkZfmkMkamTfwRBP', ":sig"=>$id, ":msg"=>'compromised-masternodes-hf', ":date"=>time(), ":public_key"=>'4kWXV4HMuogUcjZBEzmmQdtc1dHzta6VykhCV1HWyEXK7kRWEMJLNoMWbuDwFMTfBrq5a9VthkZfmkMkamTfwRBP'] | ||||||
|             ); |             ); | ||||||
|             $db->run("UPDATE accounts SET balance=balance+4700000 where id='4kWXV4HMuogUcjZBEzmmQdtc1dHzta6VykhCV1HWyEXK7kRWEMJLNoMWbuDwFMTfBrq5a9VthkZfmkMkamTfwRBP' LIMIT 1"); |             $db->run("UPDATE accounts SET balance=balance+4700000 where id='4kWXV4HMuogUcjZBEzmmQdtc1dHzta6VykhCV1HWyEXK7kRWEMJLNoMWbuDwFMTfBrq5a9VthkZfmkMkamTfwRBP' LIMIT 1"); | ||||||
|         } |         } | ||||||
| @@ -424,9 +593,8 @@ class Block | |||||||
|         $msg="$mn[blacklist],$mn[last_won],$mn[fails]"; |         $msg="$mn[blacklist],$mn[last_won],$mn[fails]"; | ||||||
|          |          | ||||||
|         $res=$db->run( |         $res=$db->run( | ||||||
|          |  | ||||||
|             "INSERT into transactions SET id=:id, block=:block, height=:height, dst=:dst, val=0, fee=0, signature=:sig, version=111, message=:msg, date=:date, public_key=:public_key", |             "INSERT into transactions SET id=:id, block=:block, height=:height, dst=:dst, val=0, fee=0, signature=:sig, version=111, message=:msg, date=:date, public_key=:public_key", | ||||||
|         [":id"=>$id, ":block"=>$hash, ":height"=>$height, ":dst"=>$hash, ":sig"=>$hash, ":msg"=>$msg, ":date"=>time(), ":public_key"=>$public_key] |             [":id"=>$id, ":block"=>$hash, ":height"=>$height, ":dst"=>$hash, ":sig"=>$hash, ":msg"=>$msg, ":date"=>time(), ":public_key"=>$public_key] | ||||||
|          |          | ||||||
|         ); |         ); | ||||||
|         if ($res!=1) { |         if ($res!=1) { | ||||||
| @@ -524,14 +692,28 @@ class Block | |||||||
|             } |             } | ||||||
|             $result=ceil($total_time/$blks); |             $result=ceil($total_time/$blks); | ||||||
|             _log("Block time: $result", 3); |             _log("Block time: $result", 3); | ||||||
|             if ($result > 260) { |             // 1 minute blocktime | ||||||
|                 $dif = bcmul($current['difficulty'], 1.05); |             if ($height>216000) { | ||||||
|             } elseif ($result < 220) { |                 if ($result > 65) { | ||||||
|                 // if lower, decrease by 5% |                     $dif = bcmul($current['difficulty'], 1.05); | ||||||
|                 $dif = bcmul($current['difficulty'], 0.95); |                 } elseif ($result < 55) { | ||||||
|  |                     // if lower, decrease by 5% | ||||||
|  |                     $dif = bcmul($current['difficulty'], 0.95); | ||||||
|  |                 } else { | ||||||
|  |                     // keep current difficulty | ||||||
|  |                     $dif = $current['difficulty']; | ||||||
|  |                 } | ||||||
|             } else { |             } else { | ||||||
|                 // keep current difficulty |                 // 4 minutes blocktime | ||||||
|                 $dif = $current['difficulty']; |                 if ($result > 260) { | ||||||
|  |                     $dif = bcmul($current['difficulty'], 1.05); | ||||||
|  |                 } elseif ($result < 220) { | ||||||
|  |                     // if lower, decrease by 5% | ||||||
|  |                     $dif = bcmul($current['difficulty'], 0.95); | ||||||
|  |                 } else { | ||||||
|  |                     // keep current difficulty | ||||||
|  |                     $dif = $current['difficulty']; | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
|             // hardfork 80000, fix difficulty targetting |             // hardfork 80000, fix difficulty targetting | ||||||
| @@ -607,17 +789,22 @@ class Block | |||||||
|     // calculate the reward for each block |     // calculate the reward for each block | ||||||
|     public function reward($id, $data = []) |     public function reward($id, $data = []) | ||||||
|     { |     { | ||||||
|         // starting reward |         if ($id>216000) { | ||||||
|         $reward = 1000; |             // 1min block time | ||||||
|  |             $reward=200; | ||||||
|  |             $factor = floor(($id-216000) / 43200) / 100; | ||||||
|  |             $reward -= $reward * $factor; | ||||||
|  |         } else { | ||||||
|  |             // starting reward | ||||||
|  |             $reward = 1000; | ||||||
|  |             // decrease by 1% each 10800 blocks (approx 1 month) | ||||||
|  |             $factor = floor($id / 10800) / 100; | ||||||
|  |             $reward -= $reward * $factor; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         // decrease by 1% each 10800 blocks (approx 1 month) |  | ||||||
|  |  | ||||||
|         $factor = floor($id / 10800) / 100; |  | ||||||
|         $reward -= $reward * $factor; |  | ||||||
|         if ($reward < 0) { |         if ($reward < 0) { | ||||||
|             $reward = 0; |             $reward = 0; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // calculate the transaction fees |         // calculate the transaction fees | ||||||
|         $fees = 0; |         $fees = 0; | ||||||
|         if (count($data) > 0) { |         if (count($data) > 0) { | ||||||
| @@ -702,26 +889,25 @@ class Block | |||||||
|         $mn_reward_rate=0.33; |         $mn_reward_rate=0.33; | ||||||
|         global $db; |         global $db; | ||||||
|         // hf |         // hf | ||||||
|         if($height>212000){ |         if ($height>216000) { | ||||||
|             $votes=[]; |             $votes=[]; | ||||||
|             $r=$db->run("SELECT id,val FROM votes"); |             $r=$db->run("SELECT id,val FROM votes"); | ||||||
|             foreach($r as $vote){ |             foreach ($r as $vote) { | ||||||
|                 $votes[$vote['id']]=$vote['val']; |                 $votes[$vote['id']]=$vote['val']; | ||||||
|             } |             } | ||||||
|             // emission cut by 30% |             // emission cut by 30% | ||||||
|             if($votes['emission30']==1){ |             if ($votes['emission30']==1) { | ||||||
|                 $reward=round($reward*0.7); |                 $reward=round($reward*0.7); | ||||||
|             } |             } | ||||||
|             // 50% to masternodes |             // 50% to masternodes | ||||||
|             if($votes['masternodereward50']==1){ |             if ($votes['masternodereward50']==1) { | ||||||
|                 $mn_reward_rate=0.5; |                 $mn_reward_rate=0.5; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             // minimum reward to always be 50 aro |             // minimum reward to always be 10 aro | ||||||
|             if($votes['endless50reward']==1&&$reward<50){ |             if ($votes['endless10reward']==1&&$reward<10) { | ||||||
|                 $reward=50; |                 $reward=10; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if ($height>=80458) { |         if ($height>=80458) { | ||||||
| @@ -1029,10 +1215,12 @@ class Block | |||||||
|                     _log("Transaction check failed - $x[id]", 3); |                     _log("Transaction check failed - $x[id]", 3); | ||||||
|                     return false; |                     return false; | ||||||
|                 } |                 } | ||||||
|                 if ($x['version']>=100&&$x['version']<110) { |                 if ($x['version']>=100&&$x['version']<110&&$x['version']!=106&&$x['version']!=107) { | ||||||
|                     $mns[] = $x['public_key']; |                     $mns[] = $x['public_key']; | ||||||
|                 } |                 } | ||||||
|                  |                 if($x['version']==106||$x['version']==107){ | ||||||
|  |                     $mns[]=$x['public_key'].$x['message']; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|                 // prepare total balance |                 // prepare total balance | ||||||
|                 $balance[$x['src']] += $x['val'] + $x['fee']; |                 $balance[$x['src']] += $x['val'] + $x['fee']; | ||||||
| @@ -1054,8 +1242,8 @@ class Block | |||||||
|             // check if the account has enough balance to perform the transaction |             // check if the account has enough balance to perform the transaction | ||||||
|             foreach ($balance as $id => $bal) { |             foreach ($balance as $id => $bal) { | ||||||
|                 $res = $db->single( |                 $res = $db->single( | ||||||
|                 "SELECT COUNT(1) FROM accounts WHERE id=:id AND balance>=:balance", |                     "SELECT COUNT(1) FROM accounts WHERE id=:id AND balance>=:balance", | ||||||
|                 [":id" => $id, ":balance" => $bal] |                     [":id" => $id, ":balance" => $bal] | ||||||
|             ); |             ); | ||||||
|                 if ($res == 0) { |                 if ($res == 0) { | ||||||
|                     _log("Not enough balance for transaction - $id", 3); |                     _log("Not enough balance for transaction - $id", 3); | ||||||
| @@ -1132,7 +1320,7 @@ class Block | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|         $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"); |         $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"); | ||||||
|  |  | ||||||
|         foreach ($r as $x) { |         foreach ($r as $x) { | ||||||
|             $res = $trx->reverse($x['id']); |             $res = $trx->reverse($x['id']); | ||||||
| @@ -1149,8 +1337,11 @@ class Block | |||||||
|                 $db->exec("UNLOCK TABLES"); |                 $db->exec("UNLOCK TABLES"); | ||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
|  |             $this->reverse_log($x['id']); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |        | ||||||
|  |  | ||||||
|         $db->commit(); |         $db->commit(); | ||||||
|         $db->exec("UNLOCK TABLES"); |         $db->exec("UNLOCK TABLES"); | ||||||
|         return true; |         return true; | ||||||
| @@ -1170,7 +1361,7 @@ class Block | |||||||
|         } |         } | ||||||
|         // avoid race conditions on blockchain manipulations |         // avoid race conditions on blockchain manipulations | ||||||
|         $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"); |         $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"); | ||||||
|  |  | ||||||
|         // reverse all transactions of the block |         // reverse all transactions of the block | ||||||
|         $res = $trx->reverse($x['id']); |         $res = $trx->reverse($x['id']); | ||||||
|   | |||||||
| @@ -154,3 +154,5 @@ $_config['masternode'] = false; | |||||||
|  |  | ||||||
| // The public key for the masternode | // The public key for the masternode | ||||||
| $_config['masternode_public_key'] = ''; | $_config['masternode_public_key'] = ''; | ||||||
|  | $_config['masternode_voting_public_key'] = ''; | ||||||
|  | $_config['masternode_voting_private_key'] = ''; | ||||||
| @@ -165,11 +165,11 @@ if ($dbversion == 8) { | |||||||
|   ADD KEY `height` (`height`);"); |   ADD KEY `height` (`height`);"); | ||||||
|     $dbversion++; |     $dbversion++; | ||||||
| } | } | ||||||
| if ($dbversion = 9) { | if ($dbversion == 9) { | ||||||
|     //dev only |     //dev only | ||||||
|     $dbversion++; |     $dbversion++; | ||||||
| } | } | ||||||
| if ($dbversion = 10) { | if ($dbversion == 10) { | ||||||
|     //assets system |     //assets system | ||||||
|     $db->run(" |     $db->run(" | ||||||
|   CREATE TABLE `assets` ( |   CREATE TABLE `assets` ( | ||||||
| @@ -220,22 +220,44 @@ if ($dbversion = 10) { | |||||||
|     $dbversion++; |     $dbversion++; | ||||||
| } | } | ||||||
|  |  | ||||||
| if ($dbversion = 11) { | if ($dbversion == 11) {  | ||||||
|     $db->run("ALTER TABLE `transactions` ADD INDEX(`version`); "); |     $db->run("ALTER TABLE `transactions` ADD INDEX(`version`); "); | ||||||
|     $db->run("ALTER TABLE `transactions` ADD INDEX(`message`); "); |     $db->run("ALTER TABLE `transactions` ADD INDEX(`message`); "); | ||||||
|     $db->run(" |     $db->run(" | ||||||
|     CREATE TABLE `logs` ( |     CREATE TABLE `logs` ( | ||||||
|       `id` int(11) NOT NULL, |       `id` int(11) NOT NULL, | ||||||
|       `transaction` varbinary(128) NOT NULL, |       `transaction` varbinary(128) NULL DEFAULT NULL, | ||||||
|  |       `block` VARBINARY(128) NULL DEFAULT NULL, | ||||||
|       `json` text DEFAULT NULL |       `json` text DEFAULT NULL | ||||||
|     ) ENGINE=InnoDB DEFAULT CHARSET=latin1;"); |     ) ENGINE=InnoDB DEFAULT CHARSET=latin1;"); | ||||||
|     $db->run("ALTER TABLE `logs` |     $db->run("ALTER TABLE `logs` | ||||||
|     ADD PRIMARY KEY (`id`), |     ADD PRIMARY KEY (`id`), | ||||||
|     ADD KEY `transaction` (`transaction`);"); |     ADD INDEX(`transaction`), | ||||||
|  |     ADD INDEX(`block`);"); | ||||||
|     $db->run("ALTER TABLE `logs` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;"); |     $db->run("ALTER TABLE `logs` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;"); | ||||||
|  |  | ||||||
|     $db->run("ALTER TABLE `masternode` ADD `vote_key` VARCHAR(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL AFTER `status`; "); |     $db->run("ALTER TABLE `masternode` ADD `vote_key` VARCHAR(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL AFTER `status`, ADD INDEX(`vote_key`);"); | ||||||
|  |     $db->run("ALTER TABLE `masternode` ADD `cold_last_won` INT NOT NULL DEFAULT '0' AFTER `vote_key`, ADD INDEX(`cold_last_won`);  "); | ||||||
|  |     $db->run("ALTER TABLE `masternode` ADD `voted` TINYINT NOT NULL DEFAULT '0' AFTER `cold_last_won`, ADD INDEX (`voted`); "); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     $db->run("CREATE TABLE `votes` ( | ||||||
|  |       `id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL, | ||||||
|  |       `nfo` varchar(64) NOT NULL, | ||||||
|  |       `val` int(11) NOT NULL DEFAULT 0 | ||||||
|  |     ) ENGINE=InnoDB DEFAULT CHARSET=latin1;"); | ||||||
|      |      | ||||||
|  |    | ||||||
|  |      | ||||||
|  |     $db->run("INSERT INTO `votes` (`id`, `nfo`, `val`) VALUES | ||||||
|  |     ('coldstacking', 'Enable cold stacking for inactive masternodes', 1), | ||||||
|  |     ('emission30', 'Emission reduction by 30 percent', 1), | ||||||
|  |     ('endless10reward', 'Minimum reward to be 10 aro forever', 0), | ||||||
|  |     ('masternodereward50', 'Masternode reward to be 50 percent of the block reward', 1);"); | ||||||
|  |      | ||||||
|  |     $db->run("ALTER TABLE `votes`  ADD PRIMARY KEY (`id`);"); | ||||||
|  |  | ||||||
|     $dbversion++; |     $dbversion++; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -26,6 +26,7 @@ class Transaction | |||||||
|                     $db->run("UPDATE `$table` SET `$v`=:val WHERE `$key`=:keyid", [":keyid"=>$id, ":val"=>$l]); |                     $db->run("UPDATE `$table` SET `$v`=:val WHERE `$key`=:keyid", [":keyid"=>$id, ":val"=>$l]); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |             $db->run("DELETE FROM logs WHERE id=:id",[":id"=>$json['id']]); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     // reverse and remove all transactions from a block |     // reverse and remove all transactions from a block | ||||||
| @@ -53,19 +54,19 @@ class Transaction | |||||||
|             } else { |             } else { | ||||||
|                 // other type of transactions |                 // other type of transactions | ||||||
|         |         | ||||||
|                 if ($x['version']!=100 && $x['version']<111 && $x['version'] != 54 && $x['version'] != 57 && $x['version'] != 58) { |                 if ($x['version']!=100 && $x['version']<111 && $x['version'] != 54 && $x['version'] != 57 && $x['version'] != 58 && $x['val']>0) { | ||||||
|                     $rez=$db->run( |                     $rez=$db->run( | ||||||
|                         "UPDATE accounts SET balance=balance-:val WHERE id=:id", |                         "UPDATE accounts SET balance=balance-:val WHERE id=:id", | ||||||
|                         [":id" => $x['dst'], ":val" => $x['val']] |                         [":id" => $x['dst'], ":val" => $x['val']] | ||||||
|                     ); |                     ); | ||||||
|                     if ($rez!=1) { |                     if ($rez!=1) { | ||||||
|                         _log("Update accounts balance minus failed ", 3); |                         _log("Update accounts balance minus failed - $x[id]", 3); | ||||||
|                         return false; |                         return false; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             // on version 0 / reward transaction, don't credit anyone |             // on version 0 / reward transaction, don't credit anyone | ||||||
|             if ($x['version'] > 0 && $x['version']<111 && $x['version'] != 54 && $x['version'] != 57 && $x['version'] != 58) { |             if ($x['version'] > 0 && $x['version']<111 && $x['version'] != 54 && $x['version'] != 57 && $x['version'] != 58 && ($x['val']+$x['fee'])>0) { | ||||||
|                 $rez=$db->run( |                 $rez=$db->run( | ||||||
|                     "UPDATE accounts SET balance=balance+:val WHERE id=:id", |                     "UPDATE accounts SET balance=balance+:val WHERE id=:id", | ||||||
|                     [":id" => $x['src'], ":val" => $x['val'] + $x['fee']] |                     [":id" => $x['src'], ":val" => $x['val'] + $x['fee']] | ||||||
| @@ -283,7 +284,16 @@ class Transaction | |||||||
|                         continue; |                         continue; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  |                 // single blockchain vote per block | ||||||
|  |                 | ||||||
|  |                 if ($x['version']==106||$x['version']==107) { | ||||||
|  |                     $tid=$x['public_key'].$x['message']; | ||||||
|  |                     if ($exists[$tid]==1) { | ||||||
|  |                         continue; | ||||||
|  |                     } | ||||||
|  |                     $exists[$tid]=1; | ||||||
|  |                 } | ||||||
|  |     | ||||||
|  |  | ||||||
|                 if (empty($x['public_key'])) { |                 if (empty($x['public_key'])) { | ||||||
|                     _log("$x[id] - Transaction has empty public_key"); |                     _log("$x[id] - Transaction has empty public_key"); | ||||||
| @@ -358,7 +368,7 @@ class Transaction | |||||||
|         ]; |         ]; | ||||||
|  |  | ||||||
|         //only a single masternode command of same type, per block |         //only a single masternode command of same type, per block | ||||||
|         if ($x['version']>=100&&$x['version']<110) { |         if ($x['version']>=100&&$x['version']<110&&$x['version']!=106&&$x['version']!=107) { | ||||||
|             $check=$db->single("SELECT COUNT(1) FROM mempool WHERE public_key=:public_key", [":public_key"=>$x['public_key']]); |             $check=$db->single("SELECT COUNT(1) FROM mempool WHERE public_key=:public_key", [":public_key"=>$x['public_key']]); | ||||||
|             if ($check!=0) { |             if ($check!=0) { | ||||||
|                 _log("Masternode transaction already in mempool", 3); |                 _log("Masternode transaction already in mempool", 3); | ||||||
| @@ -603,6 +613,8 @@ class Transaction | |||||||
|     { |     { | ||||||
|         $info = $x['val']."-".$x['fee']."-".$x['dst']."-".$x['message']."-".$x['version']."-".$x['public_key']."-".$x['date']."-".$x['signature']; |         $info = $x['val']."-".$x['fee']."-".$x['dst']."-".$x['message']."-".$x['version']."-".$x['public_key']."-".$x['date']."-".$x['signature']; | ||||||
|         $hash = hash("sha512", $info); |         $hash = hash("sha512", $info); | ||||||
|  |         //_log("Hashing: ".$info,3); | ||||||
|  |         //_log("Hash: $hash",3); | ||||||
|         return hex2coin($hash); |         return hex2coin($hash); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -610,6 +622,11 @@ class Transaction | |||||||
|     public function check($x, $height = 0) |     public function check($x, $height = 0) | ||||||
|     { |     { | ||||||
|         global $db; |         global $db; | ||||||
|  |         // blocktime lowered by 1 minute after 216000 | ||||||
|  |         $blocktime_factor=1; | ||||||
|  |         if($height>216000){ | ||||||
|  |             $blocktime_factor=4; | ||||||
|  |         } | ||||||
|         // if no specific block, use current |         // if no specific block, use current | ||||||
|         if ($height === 0) { |         if ($height === 0) { | ||||||
|             $block = new Block(); |             $block = new Block(); | ||||||
| @@ -694,7 +711,7 @@ class Transaction | |||||||
|             } elseif ($x['version']!=100) { |             } elseif ($x['version']!=100) { | ||||||
|                 $mn=$acc->get_masternode($x['public_key']); |                 $mn=$acc->get_masternode($x['public_key']); | ||||||
|  |  | ||||||
|                 if ($x['dst']!=$src) { |                 if ($x['dst']!=$src&&$x['version']!=106) { | ||||||
|                     // just to prevent some bypasses in the future |                     // just to prevent some bypasses in the future | ||||||
|                     _log("DST must be SRC for this transaction", 3); |                     _log("DST must be SRC for this transaction", 3); | ||||||
|                     return false; |                     return false; | ||||||
| @@ -713,20 +730,20 @@ class Transaction | |||||||
|                     if ($mn['status']!=0) { |                     if ($mn['status']!=0) { | ||||||
|                         _log("The masternode is not paused", 3); |                         _log("The masternode is not paused", 3); | ||||||
|                         return false; |                         return false; | ||||||
|                     } elseif ($height-$mn['last_won']<10800) { //10800 |                     } elseif ($height-$mn['last_won']<10800*$blocktime_factor) { //10800 | ||||||
|                         _log("The masternode last won block is less than 10800 blocks", 3); |                         _log("The masternode last won block is less than 10800 blocks", 3); | ||||||
|                         return false; |                         return false; | ||||||
|                     } elseif ($height-$mn['height']<32400) { //32400 |                     } elseif ($height-$mn['height']<32400*$blocktime_factor) { //32400 | ||||||
|                         _log("The masternode start height is less than 32400 blocks! $height - $mn[height]", 3); |                         _log("The masternode start height is less than 32400 blocks! $height - $mn[height]", 3); | ||||||
|                         return false; |                         return false; | ||||||
|                     } |                     } | ||||||
|                 } elseif ($x['version']==104) { |                 } elseif ($x['version']==104) { | ||||||
|                     //only once per month (every 10800 blocks) |                     //only once per month (every 43200 blocks) | ||||||
|                     $res=$db->single("SELECT COUNT(1) FROM transactions WHERE public_key=:public_key AND version=104 AND height>:height", [':public_key'=>$x['public_key'], ":height"=>$height-10800]); |                     $res=$db->single("SELECT COUNT(1) FROM transactions WHERE public_key=:public_key AND version=104 AND height>:height", [':public_key'=>$x['public_key'], ":height"=>$height-43200]); | ||||||
|                     if ($res!=0) { |                     if ($res!=0) { | ||||||
|                         return false; |                         return false; | ||||||
|                     } |                     } | ||||||
|                 } elseif ($x['version']==105) { |                  | ||||||
|                     // already using this ip |                     // already using this ip | ||||||
|                     if ($message==$mn['ip']) { |                     if ($message==$mn['ip']) { | ||||||
|                         return false; |                         return false; | ||||||
| @@ -744,15 +761,22 @@ class Transaction | |||||||
|                     if ($existing!=0) { |                     if ($existing!=0) { | ||||||
|                         return false; |                         return false; | ||||||
|                     } |                     } | ||||||
|  |                  | ||||||
|  |                 } elseif ($x['version']==105) { | ||||||
|  |                     // masternode voting key can only be set once | ||||||
|  |                     if(!empty($mn['vote_key'])){ | ||||||
|  |                         return false; | ||||||
|  |                     } | ||||||
|                 }         |                 }         | ||||||
|  |                  | ||||||
|                 // masternode votes |                 // masternode votes | ||||||
|                 elseif ($x['version']==106) { |                 elseif ($x['version']==106) { | ||||||
|                     // value always 0 |                     // value always 0 | ||||||
|                     if ($x['val']!=0) { |                     if ($x['val']!=0) { | ||||||
|                         return false; |                         return false; | ||||||
|                     } |                     } | ||||||
|                     // one vote to each mn per 10800 blocks |                     // one vote to each mn per 43200 blocks | ||||||
|                     $res=$db->single("SELECT COUNT(1) FROM transactions WHERE dst=:dst AND version=106 AND public_key=:id AND height>:height", [':dst'=>$x['dst'], ":id"=>$x['public_key'], ":height"=>$height-10800]); |                     $res=$db->single("SELECT COUNT(1) FROM transactions WHERE dst=:dst AND version=106 AND public_key=:id AND height>:height", [':dst'=>$x['dst'], ":id"=>$x['public_key'], ":height"=>$height-43200]); | ||||||
|                     if ($res>0) { |                     if ($res>0) { | ||||||
|                         return false; |                         return false; | ||||||
|                     } |                     } | ||||||
| @@ -761,17 +785,28 @@ class Transaction | |||||||
|                 elseif ($x['version']==107) { |                 elseif ($x['version']==107) { | ||||||
|                     // value always 0 |                     // value always 0 | ||||||
|                     if ($x['val']!=0) { |                     if ($x['val']!=0) { | ||||||
|  |                         _log("The value should be 0 for this transaction type - $x[val]",3); | ||||||
|                         return false; |                         return false; | ||||||
|                     } |                     } | ||||||
|          |          | ||||||
|                     // one vote to each mn per 32400 blocks |                     // one vote to each mn per 129600 blocks | ||||||
|                     $res=$db->single("SELECT COUNT(1) FROM transactions WHERE message=:message AND version=107 AND public_key=:id AND height>:height", [':message'=>$x['message'], ":id"=>$x['public_key'], ":height"=>$height-32400]); |                     $res=$db->single("SELECT COUNT(1) FROM transactions WHERE message=:message AND version=107 AND public_key=:id AND height>:height", [':message'=>$x['message'], ":id"=>$x['public_key'], ":height"=>$height-129600]); | ||||||
|                     if ($res>0) { |                     if ($res>0) { | ||||||
|  |                         _log("There is already a vote in the last 129600 blocks",3); | ||||||
|                         return false; |                         return false; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         // no asset transactions prior to 216000 | ||||||
|  |         if($x['version']>=50&&$x['version']<=55&&$height<=216000){ | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         // no masternode voting prior to 216000 | ||||||
|  |         if(($x['version']==106||$x['version']==107)&&$height<=216000){ | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|         // assets |         // assets | ||||||
|         if ($x['version']==50) { |         if ($x['version']==50) { | ||||||
|             // asset creation |             // asset creation | ||||||
| @@ -862,7 +897,7 @@ class Transaction | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         // make sure the dividend only function is not bypassed after height X |         // make sure the dividend only function is not bypassed after height X | ||||||
|         if (($x['version']==1||$x['version']==2)&&$height>11111) { |         if (($x['version']==1||$x['version']==2)&&$height>216000) { | ||||||
|             $check=$db->single("SELECT COUNT(1) FROM assets WHERE id=:id AND dividend_only=1", [":id"=>$src]); |             $check=$db->single("SELECT COUNT(1) FROM assets WHERE id=:id AND dividend_only=1", [":id"=>$src]); | ||||||
|             if ($check==1) { |             if ($check==1) { | ||||||
|                 _log("This asset wallet cannot send funds directly", 3); |                 _log("This asset wallet cannot send funds directly", 3); | ||||||
|   | |||||||
							
								
								
									
										135
									
								
								sanity.php
									
									
									
									
									
								
							
							
						
						
									
										135
									
								
								sanity.php
									
									
									
									
									
								
							| @@ -84,8 +84,9 @@ ini_set('memory_limit', '2G'); | |||||||
|  |  | ||||||
| $block = new Block(); | $block = new Block(); | ||||||
| $acc = new Account(); | $acc = new Account(); | ||||||
| $current = $block->current(); | $trx= new Transaction(); | ||||||
|  |  | ||||||
|  | $current = $block->current(); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -646,40 +647,41 @@ if ($current['height'] < $largest_height && $largest_height > 1) { | |||||||
|  |  | ||||||
|                 $resyncing=true; |                 $resyncing=true; | ||||||
|             } |             } | ||||||
|             if ($resyncing==true) { |             // needs to be redone due to the assets | ||||||
|                 _log("Resyncing accounts"); |             // if ($resyncing==true) { | ||||||
|                 $db->run("INSERT into config SET val=UNIX_TIMESTAMP(), cfg='last_resync' ON DUPLICATE KEY UPDATE val=UNIX_TIMESTAMP()"); |             //     _log("Resyncing accounts"); | ||||||
|                 $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"); |             //     $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"); |             //     $r=$db->run("SELECT * FROM accounts"); | ||||||
|                 foreach ($r as $x) { |             //     foreach ($r as $x) { | ||||||
|                     $alias=$x['alias']; |             //         $alias=$x['alias']; | ||||||
|                     if (empty($alias)) { |             //         if (empty($alias)) { | ||||||
|                         $alias="A"; |             //             $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]); |             //         $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']]); |             //         $releases=$db->single("SELECT COUNT(1) FROM transactions WHERE dst=:id AND version=103", [":id"=>$x['id']]); | ||||||
|                     if ($releases>0) { //masternode releases |             //         if ($releases>0) { //masternode releases | ||||||
|                         $rec+=$releases*100000; |             //             $rec+=$releases*100000; | ||||||
|                     } |             //         } | ||||||
|                      |                      | ||||||
|                     $spent=$db->single("SELECT SUM(val+fee) FROM transactions WHERE public_key=:pub AND version>0", [":pub"=>$x['public_key']]); |             //         $spent=$db->single("SELECT SUM(val+fee) FROM transactions WHERE public_key=:pub AND version>0", [":pub"=>$x['public_key']]); | ||||||
|                     if ($spent==false) { |             //         if ($spent==false) { | ||||||
|                         $spent=0; |             //             $spent=0; | ||||||
|                     } |             //         } | ||||||
|                     $balance=round(($rec-$spent), 8); |             //         $balance=round(($rec-$spent), 8); | ||||||
|                     if ($x['balance']!=$balance) { |             //         if ($x['balance']!=$balance) { | ||||||
|                         // echo "rec: $rec, spent: $spent, bal: $x[balance], should be: $balance - $x[id] $x[public_key]\n"; |             //             // echo "rec: $rec, spent: $spent, bal: $x[balance], should be: $balance - $x[id] $x[public_key]\n"; | ||||||
|                         if (trim($argv[2])!="check") { |             //             if (trim($argv[2])!="check") { | ||||||
|                             $db->run("UPDATE accounts SET balance=:bal WHERE id=:id", [":id"=>$x['id'], ":bal"=>$balance]); |             //                 $db->run("UPDATE accounts SET balance=:bal WHERE id=:id", [":id"=>$x['id'], ":bal"=>$balance]); | ||||||
|                         } |             //             } | ||||||
|                     } |             //         } | ||||||
|                 } |             //     } | ||||||
|                 $current = $block->current(); |             //     $current = $block->current(); | ||||||
|                 $db->run("DELETE FROM masternode WHERE height>:h", [":h"=>$current['height']]); |             //     $db->run("DELETE FROM masternode WHERE height>:h", [":h"=>$current['height']]); | ||||||
|                 $db->exec("UNLOCK TABLES"); |             //     $db->exec("UNLOCK TABLES"); | ||||||
|             } |             // } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -830,6 +832,75 @@ if (rand(0, 10)==1) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | if($_config['masternode']==true&&!empty($_config['masternode_public_key'])&&!empty($_config['masternode_voting_public_key'])&&!empty($_config['masternode_voting_private_key'])){ | ||||||
|  | echo "Masternode votes\n"; | ||||||
|  |     $r=$db->run("SELECT * FROM masternode WHERE status=1 ORDER by RAND() LIMIT 3"); | ||||||
|  |     foreach($r as $x){ | ||||||
|  |         $blacklist=0; | ||||||
|  |         $x['ip']=san_ip($x['ip']); | ||||||
|  |         echo "Testing masternode: $x[ip]\n"; | ||||||
|  |         $f=file_get_contents("http://$x[ip]/api.php?q=currentBlock"); | ||||||
|  |         if($f){ | ||||||
|  |             $res=json_decode($f,true); | ||||||
|  |             $res=$res['data']; | ||||||
|  |             if($res['height']<$current['height']-50){ | ||||||
|  |                 $blacklist=1; | ||||||
|  |             } | ||||||
|  |             echo "Masternode Height: ".$res['height']."\n"; | ||||||
|  |         } else { | ||||||
|  |             echo "---> Unresponsive\n"; | ||||||
|  |             $blacklist=1; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if($blacklist){ | ||||||
|  |             echo "Blacklisting masternode $x[public_key]\n"; | ||||||
|  |             $val='0.00000000'; | ||||||
|  |             $fee='0.00000001'; | ||||||
|  |             $date=time(); | ||||||
|  |             $version=106; | ||||||
|  |             $msg=san($x['public_key']); | ||||||
|  |             $address=$acc->get_address($x['public_key']); | ||||||
|  |             $public_key=$_config['masternode_public_key']; | ||||||
|  |             $private_key=$_config['masternode_voting_private_key']; | ||||||
|  |             $info=$val."-".$fee."-".$address."-".$msg."-$version-".$public_key."-".$date; | ||||||
|  |             $signature=ec_sign($info, $private_key); | ||||||
|  |      | ||||||
|  |  | ||||||
|  |             $transaction = [ | ||||||
|  |                 "src"        => $acc->get_address($_config['masternode_public_key']), | ||||||
|  |                 "val"        => $val, | ||||||
|  |                 "fee"        => $fee, | ||||||
|  |                 "dst"        => $address, | ||||||
|  |                 "public_key" => $public_key, | ||||||
|  |                 "date"       => $date, | ||||||
|  |                 "version"    => $version, | ||||||
|  |                 "message"    => $msg, | ||||||
|  |                 "signature"  => $signature, | ||||||
|  |             ]; | ||||||
|  |                  | ||||||
|  |             $hash = $trx->hash($transaction); | ||||||
|  |             $transaction['id'] = $hash; | ||||||
|  |             if (!$trx->check($transaction)) { | ||||||
|  |                 print("Blacklist transaction signature failed\n"); | ||||||
|  |             } | ||||||
|  |             $res = $db->single("SELECT COUNT(1) FROM mempool WHERE id=:id", [":id" => $hash]); | ||||||
|  |             if ($res != 0) { | ||||||
|  |                 print("Blacklist transaction already in mempool\n"); | ||||||
|  |             } | ||||||
|  |             $trx->add_mempool($transaction, "local"); | ||||||
|  |             $hash=escapeshellarg(san($hash)); | ||||||
|  |             system("php propagate.php transaction $hash > /dev/null 2>&1  &"); | ||||||
|  |             echo "Blacklist Hash: $hash\n"; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| _log("Finishing sanity"); | _log("Finishing sanity"); | ||||||
|  |  | ||||||
| @unlink(SANITY_LOCK_PATH); | @unlink(SANITY_LOCK_PATH); | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								util.php
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								util.php
									
									
									
									
									
								
							| @@ -457,6 +457,7 @@ elseif ($cmd == 'get-address') { | |||||||
|     $db->run("UPDATE peers SET blacklisted=0, fails=0, stuckfail=0"); |     $db->run("UPDATE peers SET blacklisted=0, fails=0, stuckfail=0"); | ||||||
|     echo "All the peers have been removed from the blacklist\n"; |     echo "All the peers have been removed from the blacklist\n"; | ||||||
| } elseif ($cmd == 'resync-accounts') { | } elseif ($cmd == 'resync-accounts') { | ||||||
|  |     die("Currently disabled due to asset implementation."); | ||||||
|     // resyncs the balance on all accounts |     // resyncs the balance on all accounts | ||||||
|     if (file_exists("tmp/sanity-lock")) { |     if (file_exists("tmp/sanity-lock")) { | ||||||
|         die("Sanity running. Wait for it to finish"); |         die("Sanity running. Wait for it to finish"); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 admin@arionum.com
					admin@arionum.com