PageRenderTime 55ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/v1.9/transclerk.php

https://bitbucket.org/rev22/timekoin
PHP | 861 lines | 587 code | 154 blank | 120 comment | 144 complexity | d4c07af276778cfc87447029e4cdedbf MD5 | raw file
  1. <?PHP
  2. include 'configuration.php';
  3. include 'function.php';
  4. set_time_limit(120);
  5. //***********************************************************************************
  6. //***********************************************************************************
  7. if(TRANSCLERK_DISABLED == TRUE || TIMEKOIN_DISABLED == TRUE)
  8. {
  9. // This has been disabled
  10. exit;
  11. }
  12. //***********************************************************************************
  13. //***********************************************************************************
  14. // Open persistent connection to database
  15. mysql_connect(MYSQL_IP,MYSQL_USERNAME,MYSQL_PASSWORD);
  16. mysql_select_db(MYSQL_DATABASE);
  17. // Check for banned IP address
  18. $ip = mysql_result(mysql_query("SELECT * FROM `ip_banlist` WHERE `ip` = '" . $_SERVER['REMOTE_ADDR'] . "' LIMIT 1"),0,0);
  19. if(empty($ip) == FALSE)
  20. {
  21. // Sorry, your IP address has been banned :(
  22. exit;
  23. }
  24. //***********************************************************************************
  25. //***********************************************************************************
  26. // Answer transaction history hash poll
  27. if($_GET["action"] == "history_hash")
  28. {
  29. $current_history_hash = mysql_result(mysql_query("SELECT * FROM `options` WHERE `field_name` = 'transaction_history_hash' LIMIT 1"),0,"field_data");
  30. echo $current_history_hash;
  31. // Log inbound IP activity
  32. mysql_query("INSERT INTO `ip_activity` (`timestamp` ,`ip`, `attribute`)VALUES ('" . time() . "', '" . $_SERVER['REMOTE_ADDR'] . "', 'TR')");
  33. exit;
  34. }
  35. //***********************************************************************************
  36. //***********************************************************************************
  37. // Answer block hash poll
  38. if($_GET["action"] == "block_hash" && $_GET["block_number"] >= 0)
  39. {
  40. $block_number = intval($_GET["block_number"]);
  41. $current_generation_block = transaction_cycle(0, TRUE);
  42. $time1 = transaction_cycle(0 - $current_generation_block + 1 + $block_number);
  43. $time2 = transaction_cycle(0 - $current_generation_block + 2 + $block_number);
  44. $hash = mysql_result(mysql_query("SELECT * FROM `transaction_history` WHERE `timestamp` >= $time1 AND `timestamp` < $time2 AND `attribute` = 'H' LIMIT 1"),0,"hash");
  45. echo $hash;
  46. // Log inbound IP activity
  47. mysql_query("INSERT INTO `ip_activity` (`timestamp` ,`ip`, `attribute`)VALUES ('" . time() . "', '" . $_SERVER['REMOTE_ADDR'] . "', 'TR')");
  48. exit;
  49. }
  50. //***********************************************************************************
  51. //***********************************************************************************
  52. // Answer transaction data poll
  53. if($_GET["action"] == "transaction_data" && $_GET["block_number"] >= 0)
  54. {
  55. $block_number = intval($_GET["block_number"]);
  56. $current_generation_block = transaction_cycle(0, TRUE);
  57. $time1 = transaction_cycle(0 - $current_generation_block + $block_number);
  58. $time2 = transaction_cycle(0 - $current_generation_block + 1 + $block_number);
  59. $sql = "SELECT * FROM `transaction_history` WHERE `timestamp` >= $time1 AND `timestamp` < $time2";
  60. $sql_result = mysql_query($sql);
  61. $sql_num_results = mysql_num_rows($sql_result);
  62. $c = 1;
  63. if($sql_num_results > 0)
  64. {
  65. for ($i = 0; $i < $sql_num_results; $i++)
  66. {
  67. $sql_row = mysql_fetch_array($sql_result);
  68. echo "-----timestamp$c=" , $sql_row["timestamp"] , "-----public_key_from$c=" , base64_encode($sql_row["public_key_from"]) , "-----public_key_to$c=" , base64_encode($sql_row["public_key_to"]);
  69. echo "-----crypt1data$c=" , $sql_row["crypt_data1"] , "-----crypt2data$c=" , $sql_row["crypt_data2"] , "-----crypt3data$c=" , $sql_row["crypt_data3"] , "-----hash$c=" , $sql_row["hash"];
  70. echo "-----attribute$c=" , $sql_row["attribute"] , "-----end$c";
  71. $c++;
  72. }
  73. }
  74. // Log inbound IP activity
  75. mysql_query("INSERT INTO `ip_activity` (`timestamp` ,`ip`, `attribute`)VALUES ('" . time() . "', '" . $_SERVER['REMOTE_ADDR'] . "', 'TR')");
  76. exit;
  77. }
  78. //***********************************************************************************
  79. //***********************************************************************************
  80. $loop_active = intval(mysql_result(mysql_query("SELECT * FROM `main_loop_status` WHERE `field_name` = 'transclerk_heartbeat_active' LIMIT 1"),0,"field_data"));
  81. // Check if loop is already running
  82. if($loop_active == 0)
  83. {
  84. // Set the working status of 1
  85. $sql = "UPDATE `main_loop_status` SET `field_data` = '1' WHERE `main_loop_status`.`field_name` = 'transclerk_heartbeat_active' LIMIT 1";
  86. mysql_query($sql);
  87. }
  88. else
  89. {
  90. // Loop called while still working
  91. exit;
  92. }
  93. //***********************************************************************************
  94. //***********************************************************************************
  95. $current_generation_cycle = transaction_cycle(0);
  96. $next_generation_cycle = transaction_cycle(1);
  97. $current_generation_block = transaction_cycle(0, TRUE);
  98. $foundation_active = intval(mysql_result(mysql_query("SELECT * FROM `main_loop_status` WHERE `field_name` = 'foundation_heartbeat_active' LIMIT 1"),0,"field_data"));
  99. // Can we work on the transactions in the database?
  100. // Not allowed 30 seconds before and 30 seconds after generation cycle.
  101. if(($next_generation_cycle - time()) > 30 && (time() - $current_generation_cycle) > 30 && $foundation_active == 0)
  102. {
  103. // Check if the transaction history is blank or not (either from reset or new setup)
  104. $sql = "SELECT * FROM `transaction_history` LIMIT 5";
  105. $sql_result = mysql_query($sql);
  106. $sql_num_results = mysql_num_rows($sql_result);
  107. $generation_arbitrary = ARBITRARY_KEY;
  108. //***********************************************************************************
  109. if($sql_num_results == 0 && $sql_result !== FALSE) //New or blank transaction history
  110. {
  111. // Start by inserting the beginning arbitrary transaction from which all others will hash against
  112. $sql = "INSERT INTO `transaction_history` (`timestamp` ,`public_key_from` ,`public_key_to` ,`crypt_data1` ,`crypt_data2` ,`crypt_data3` ,`hash` ,`attribute`)
  113. VALUES ('" . TRANSACTION_EPOCH . "', '$generation_arbitrary', '$generation_arbitrary', '$generation_arbitrary', '$generation_arbitrary', '$generation_arbitrary', '$generation_arbitrary', 'B')";
  114. mysql_query($sql);
  115. // Lock Treasurer script to prevent database chaos during the initial phase
  116. activate(TREASURER, 0);
  117. }
  118. //***********************************************************************************
  119. if($sql_num_results > 0 && $sql_num_results < 4) // Write out some test hashes and compare to verify sha256 accuracy
  120. {
  121. // Beginning transaction should be in, check to make sure
  122. $beginning_transaction = mysql_result(mysql_query("SELECT * FROM `transaction_history` WHERE `public_key_from` = '$generation_arbitrary' AND `hash` = '$generation_arbitrary' LIMIT 1"),0,"timestamp");
  123. if($beginning_transaction == TRANSACTION_EPOCH)
  124. {
  125. // First transaction complete, continue processing
  126. $current_generation_block = transaction_cycle(0, TRUE);
  127. $cycles = 0;
  128. while($cycles < 3)
  129. {
  130. $first_generation_cycle = transaction_cycle((0 - $current_generation_block));
  131. $second_generation_cycle = transaction_cycle((0 - $current_generation_block + 1));
  132. // Build Hash
  133. $sql = "SELECT * FROM `transaction_history` WHERE `timestamp` >= $first_generation_cycle AND `timestamp` < $second_generation_cycle";
  134. $sql_result = mysql_query($sql);
  135. $sql_num_results = mysql_num_rows($sql_result);
  136. $hash = 0;
  137. for ($i = 0; $i < $sql_num_results; $i++)
  138. {
  139. $sql_row = mysql_fetch_array($sql_result);
  140. $hash .= $sql_row["hash"];
  141. }
  142. // Transaction hash
  143. $hash = hash('sha256', $hash);
  144. $sql = "INSERT INTO `transaction_history` (`timestamp` ,`public_key_from` ,`public_key_to` ,`crypt_data1` ,`crypt_data2` ,`crypt_data3` ,`hash` ,`attribute`)
  145. VALUES ('$second_generation_cycle', '$generation_arbitrary', '$generation_arbitrary', '$generation_arbitrary', '$generation_arbitrary', '$generation_arbitrary', '$hash', 'H')";
  146. mysql_query($sql);
  147. $current_generation_block--;
  148. $cycles++;
  149. }
  150. $current_generation_block++;
  151. $second_generation_cycle = transaction_cycle((0 - $current_generation_block + 1));
  152. $hash_check = mysql_result(mysql_query("SELECT * FROM `transaction_history` WHERE `timestamp` = '$second_generation_cycle' AND `attribute` = 'H' LIMIT 1"),0,"hash");
  153. // Now let's check the results to make sure they match what should be expected
  154. if($hash_check == SHA256TEST)
  155. {
  156. // Passed final hash checking.
  157. // Unlock Treasurer script to allow live processing
  158. activate(TREASURER, 1);
  159. // Start a block rebuild from this since a new database is going to be far
  160. // behind the history of the other active peers
  161. $sql = "UPDATE `options` SET `field_data` = '3' WHERE `options`.`field_name` = 'block_check_start' LIMIT 1";
  162. mysql_query($sql);
  163. }
  164. else
  165. {
  166. write_log("Server Failed Initial Encryption Generation and Verification Testing", "TR");
  167. }
  168. }
  169. } // End database preparation and hash testing
  170. //***********************************************************************************
  171. // Check the transaction hash generation
  172. if($sql_num_results > 3) // 4 or more transactions on a live database, let the magic begin
  173. {
  174. //***********************************************************************************
  175. // Update transaction history hash
  176. $current_history_hash = mysql_result(mysql_query("SELECT * FROM `options` WHERE `field_name` = 'transaction_history_hash' LIMIT 1"),0,"field_data");
  177. $transaction_history_block_check = intval(mysql_result(mysql_query("SELECT * FROM `options` WHERE `field_name` = 'transaction_history_block_check' LIMIT 1"),0,"field_data"));
  178. $foundation_block_check = intval(mysql_result(mysql_query("SELECT * FROM `options` WHERE `field_name` = 'foundation_block_check' LIMIT 1"),0,"field_data"));
  179. if($transaction_history_block_check != 0 || $foundation_block_check == 1)
  180. {
  181. //A random block check came up wrong, do a single error check sweep
  182. $error_check_active = TRUE;
  183. // Change hash to mismatch on purpose
  184. $current_history_hash = "ERROR_CHECK";
  185. if($transaction_history_block_check > 0 && $foundation_block_check == 0)
  186. {
  187. write_log("Starting History Check from Block #$transaction_history_block_check", "TC");
  188. }
  189. else
  190. {
  191. $foundation_block_check_start = intval(mysql_result(mysql_query("SELECT * FROM `options` WHERE `field_name` = 'foundation_block_check_start' LIMIT 1"),0,"field_data"));
  192. write_log("Resuming History Check from Block #$foundation_block_check_start", "TC");
  193. }
  194. // Update database with ERROR_CHECK hash
  195. $sql = "UPDATE `options` SET `field_data` = '$current_history_hash' WHERE `field_name` = 'transaction_history_hash' LIMIT 1";
  196. mysql_query($sql);
  197. }
  198. else
  199. {
  200. $total = mysql_query("SELECT COUNT(*) FROM `transaction_history`");
  201. $total = mysql_fetch_array($total);
  202. $hash = $total[0];
  203. $previous_foundation_block = foundation_cycle(-1, TRUE);
  204. $current_foundation_cycle = foundation_cycle(0);
  205. $next_foundation_cycle = foundation_cycle(1);
  206. $current_history_foundation = mysql_result(mysql_query("SELECT * FROM `transaction_foundation` WHERE `block` = $previous_foundation_block LIMIT 1"),0,"hash");
  207. $hash .= $current_history_foundation;
  208. $sql = "SELECT * FROM `transaction_history` WHERE `timestamp` >= $current_foundation_cycle AND `timestamp` < $next_foundation_cycle AND `attribute` = 'H' ORDER BY `timestamp`";
  209. $sql_result = mysql_query($sql);
  210. $sql_num_results = mysql_num_rows($sql_result);
  211. for ($i = 0; $i < $sql_num_results; $i++)
  212. {
  213. $sql_row = mysql_fetch_array($sql_result);
  214. $hash .= $sql_row["hash"];
  215. }
  216. $history_hash = hash('md5', $hash);
  217. if($history_hash == $current_history_hash)
  218. {
  219. // Already in database, no need to update
  220. }
  221. else
  222. {
  223. $current_history_hash = $history_hash;
  224. // Update database with new hash
  225. $sql = "UPDATE `options` SET `field_data` = '$history_hash' WHERE `field_name` = 'transaction_history_hash' LIMIT 1";
  226. mysql_query($sql);
  227. }
  228. }
  229. //***********************************************************************************
  230. //***********************************************************************************
  231. // Does my current history hash match all my peers?
  232. // Ask all of my active peers
  233. ini_set('default_socket_timeout', 3); // Timeout for request in seconds
  234. ini_set('user_agent', 'Timekoin Server (Transclerk) v' . TIMEKOIN_VERSION);
  235. $context = stream_context_create(array('http' => array('header'=>'Connection: close'))); // Force close socket after complete
  236. $sql = "SELECT * FROM `active_peer_list`";
  237. $sql_result = mysql_query($sql);
  238. $sql_num_results = mysql_num_rows($sql_result);
  239. $trans_list_hash_match = 0;
  240. $trans_list_hash_different = 0;
  241. $site_address;
  242. if($sql_num_results > 0)
  243. {
  244. $hash_different = array();
  245. for ($i = 0; $i < $sql_num_results; $i++)
  246. {
  247. $sql_row = mysql_fetch_array($sql_result);
  248. $ip_address = $sql_row["IP_Address"];
  249. $domain = $sql_row["domain"];
  250. $subfolder = $sql_row["subfolder"];
  251. $port_number = $sql_row["port_number"];
  252. if(empty($domain) == TRUE)
  253. {
  254. $site_address = $ip_address;
  255. }
  256. else
  257. {
  258. $site_address = $domain;
  259. }
  260. if($port_number == 443)
  261. {
  262. $ssl = "s";
  263. }
  264. else
  265. {
  266. $ssl = NULL;
  267. }
  268. $poll_peer = filter_sql(file_get_contents("http$ssl://$site_address:$port_number/$subfolder/transclerk.php?action=history_hash", FALSE, $context, NULL, 65));
  269. if($current_history_hash === $poll_peer)
  270. {
  271. $trans_list_hash_match++;
  272. }
  273. else
  274. {
  275. if(empty($poll_peer) == FALSE && strlen($poll_peer) > 5 && $poll_peer != "ERROR_CHECK")
  276. {
  277. $trans_list_hash_different++;
  278. $hash_different["ip_address$trans_list_hash_different"] = $ip_address;
  279. $hash_different["domain$trans_list_hash_different"] = $domain;
  280. $hash_different["subfolder$trans_list_hash_different"] = $subfolder;
  281. $hash_different["port_number$trans_list_hash_different"] = $port_number;
  282. }
  283. }
  284. } // End for Loop
  285. } // End number of results check
  286. //***********************************************************************************
  287. // Compare tallies
  288. if($trans_list_hash_different > $trans_list_hash_match)
  289. {
  290. //More than 50% of the active peers have a different transaction history list, start comparing your
  291. //transaction list with one that is different
  292. $hash_check_counter = 15; // How many blocks to check at each cycle (default)
  293. if($error_check_active == FALSE)
  294. {
  295. $hash_number = intval(mysql_result(mysql_query("SELECT * FROM `options` WHERE `field_name` = 'block_check_start' LIMIT 1"),0,"field_data"));
  296. if($hash_number == 0)
  297. {
  298. // A new check, start just 10 blocks from the end to avoid checking the entire history
  299. // from the beginning
  300. $hash_number = transaction_cycle(-10, TRUE);
  301. }
  302. else
  303. {
  304. write_log("Resuming History Check from Block #$hash_number", "TC");
  305. }
  306. }
  307. else
  308. {
  309. if($foundation_block_check == 1)
  310. {
  311. // Start from the block that the foundation begins
  312. $foundation_block_check_start = mysql_result(mysql_query("SELECT * FROM `options` WHERE `field_name` = 'foundation_block_check_start' LIMIT 1"),0,"field_data");
  313. $foundation_block_check_end = mysql_result(mysql_query("SELECT * FROM `options` WHERE `field_name` = 'foundation_block_check_end' LIMIT 1"),0,"field_data");
  314. if($foundation_block_check_start > $foundation_block_check_end)
  315. {
  316. // Check is finished
  317. $sql = "UPDATE `options` SET `field_data` = '0' WHERE `options`.`field_name` = 'foundation_block_check' LIMIT 1";
  318. mysql_query($sql);
  319. // Push forward any previous block checks that were in progress
  320. $sql = "UPDATE `options` SET `field_data` = '$foundation_block_check_start' WHERE `options`.`field_name` = 'block_check_start' LIMIT 1";
  321. mysql_query($sql);
  322. // Reset block back counter
  323. $sql = "UPDATE `options` SET `field_data` = '1' WHERE `options`.`field_name` = 'block_check_back' LIMIT 1";
  324. mysql_query($sql);
  325. $hash_number = $foundation_block_check_start;
  326. }
  327. else
  328. {
  329. $hash_check_counter = 20;
  330. $hash_number = $foundation_block_check_start;
  331. }
  332. }
  333. else
  334. {
  335. $hash_number = ($transaction_history_block_check - 1); // Start back 1 block from the error section
  336. }
  337. }
  338. $double_check_counter = 0;
  339. $sync_block = 0;
  340. if(($hash_number + $hash_check_counter) >= $current_generation_block)
  341. {
  342. // Adjust for when near the end of the transaction history
  343. $hash_check_counter = $hash_check_counter - (($hash_number + $hash_check_counter) - $current_generation_block);
  344. if($hash_check_counter == 0)
  345. {
  346. // Reached the end, delete the most current block to allow an auto-recorrect
  347. $sql = "DELETE FROM `transaction_history` WHERE `timestamp` >= $current_generation_cycle AND `timestamp` < $next_generation_cycle";
  348. mysql_query($sql);
  349. // How many times have this checked reached the end and still not fixed the transaction history?
  350. $hash_number_back_database = mysql_result(mysql_query("SELECT * FROM `options` WHERE `field_name` = 'block_check_back' LIMIT 1"),0,"field_data");
  351. $hash_number_back = $hash_number_back_database * 10;
  352. // Every time we reach the end and still the problem exist, go back another 10 blocks until eventually
  353. // we reach a point in history where the problem can be repaired
  354. $hash_number = $current_generation_block - $hash_number_back;
  355. $foundation_to_cycles = foundation_cycle(0, TRUE) * 500;
  356. if($current_generation_block - $hash_number < $foundation_to_cycles)
  357. {
  358. // Restart a check so that it doesn't dig into a valid
  359. // transaction foundation by accident
  360. $hash_number = $foundation_to_cycles;
  361. }
  362. if($hash_number_back > 30)
  363. {
  364. // More than 30 blocks back, start from the beginning of the current
  365. // transaction foundation as something might be wrong deeper in the history
  366. $hash_number = $foundation_to_cycles;
  367. mysql_query("UPDATE `options` SET `field_data` = '1' WHERE `options`.`field_name` = 'block_check_back' LIMIT 1");
  368. }
  369. else
  370. {
  371. // Increment back counter in case this was not far back enough
  372. // and it reaches this point again
  373. $hash_number_back_database++;
  374. mysql_query("UPDATE `options` SET `field_data` = '$hash_number_back_database' WHERE `options`.`field_name` = 'block_check_back' LIMIT 1");
  375. }
  376. $hash_check_counter = 10; // Reset to check another 10 blocks forward
  377. }
  378. }
  379. $hash_disagree_peers = array();
  380. for ($h = 0; $h < $hash_check_counter; $h++)
  381. {
  382. $hash_agree = 0;
  383. $hash_disagree = 0;
  384. $double_check_block = FALSE;
  385. $time1 = transaction_cycle(0 - $current_generation_block + $hash_number);
  386. $time2 = transaction_cycle(0 - $current_generation_block + 1 + $hash_number);
  387. $sql = "SELECT * FROM `transaction_history` WHERE `timestamp` >= $time1 AND `timestamp` < $time2 ORDER BY `timestamp`, `hash`";
  388. $sql_result = mysql_query($sql);
  389. $sql_num_results = mysql_num_rows($sql_result);
  390. $my_hash = 0;
  391. for ($i = 0; $i < $sql_num_results; $i++)
  392. {
  393. $sql_row = mysql_fetch_array($sql_result);
  394. $my_hash .= $sql_row["hash"];
  395. }
  396. $my_hash = hash('sha256', $my_hash);
  397. for ($i = 1; $i < $trans_list_hash_different + 1; $i++)
  398. {
  399. $ip_address = $hash_different["ip_address$i"];
  400. $domain = $hash_different["domain$i"];
  401. $subfolder = $hash_different["subfolder$i"];
  402. $port_number = $hash_different["port_number$i"];
  403. if(empty($domain) == TRUE)
  404. {
  405. $site_address = $ip_address;
  406. }
  407. else
  408. {
  409. $site_address = $domain;
  410. }
  411. if($port_number == 443)
  412. {
  413. $ssl = "s";
  414. }
  415. else
  416. {
  417. $ssl = NULL;
  418. }
  419. // Start with the first hash and work our way up
  420. $poll_peer = filter_sql(file_get_contents("http$ssl://$site_address:$port_number/$subfolder/transclerk.php?action=block_hash&block_number=$hash_number", FALSE, $context, NULL, 65));
  421. if($my_hash === $poll_peer)
  422. {
  423. $hash_agree++;
  424. }
  425. else if($my_hash !== $poll_peer && empty($poll_peer) == FALSE)
  426. {
  427. $hash_disagree++;
  428. $hash_disagree_peers["ip_address$hash_disagree"] = $ip_address;
  429. $hash_disagree_peers["domain$hash_disagree"] = $domain;
  430. $hash_disagree_peers["subfolder$hash_disagree"] = $subfolder;
  431. $hash_disagree_peers["port_number$hash_disagree"] = $port_number;
  432. }
  433. } // End For Loop
  434. //***********************************************************************************
  435. // Compare peers that agree and disagree
  436. if($hash_disagree > $hash_agree)
  437. {
  438. //More than 50% of the active peers disagree on the hash value
  439. //so poll the transaction data from one them randomly
  440. // Clear out transaction block to allow the new one to be
  441. // inserted in place
  442. $sql = "DELETE FROM `transaction_history` WHERE `timestamp` >= $time1 AND `timestamp` < $time2";
  443. if(mysql_query($sql) == FALSE)
  444. {
  445. //Something didn't work
  446. }
  447. else
  448. {
  449. $peer_number = rand(1,$hash_disagree);// Random peer from array
  450. $ip_address = $hash_disagree_peers["ip_address$peer_number"];
  451. $domain = $hash_disagree_peers["domain$peer_number"];
  452. $subfolder = $hash_disagree_peers["subfolder$peer_number"];
  453. $port_number = $hash_disagree_peers["port_number$peer_number"];
  454. $block_number = $hash_number;
  455. if(empty($domain) == TRUE)
  456. {
  457. $site_address = $ip_address;
  458. }
  459. else
  460. {
  461. $site_address = $domain;
  462. }
  463. if($port_number == 443)
  464. {
  465. $ssl = "s";
  466. }
  467. else
  468. {
  469. $ssl = NULL;
  470. }
  471. $poll_peer = filter_sql(file_get_contents("http$ssl://$site_address:$port_number/$subfolder/transclerk.php?action=transaction_data&block_number=$block_number", FALSE, $context, NULL, 200000));
  472. $tc = 1;
  473. while(empty($poll_peer) == FALSE)
  474. {
  475. $transaction_timestamp = find_string("-----timestamp$tc=", "-----public_key_from$tc", $poll_peer);
  476. $transaction_public_key_from = find_string("-----public_key_from$tc=", "-----public_key_to$tc", $poll_peer);
  477. $transaction_public_key_to = find_string("-----public_key_to$tc=", "-----crypt1data$tc", $poll_peer);
  478. $transaction_crypt1 = find_string("-----crypt1data$tc=", "-----crypt2data$tc", $poll_peer);
  479. $transaction_crypt2 = find_string("-----crypt2data$tc=", "-----crypt3data$tc", $poll_peer);
  480. $transaction_crypt3 = find_string("-----crypt3data$tc=", "-----hash$tc", $poll_peer);
  481. $transaction_hash = find_string("-----hash$tc=", "-----attribute$tc", $poll_peer);
  482. $transaction_attribute = find_string("-----attribute$tc=", "-----end$tc", $poll_peer);
  483. if(empty($transaction_public_key_from) == TRUE && empty($transaction_public_key_to) == TRUE)
  484. {
  485. // No more data, break while loop
  486. break;
  487. }
  488. $transaction_public_key_from = base64_decode($transaction_public_key_from);
  489. $transaction_public_key_to = base64_decode($transaction_public_key_to);
  490. $found_duplicate = mysql_result(mysql_query("SELECT * FROM `transaction_history` WHERE `timestamp` = '$transaction_timestamp' AND `public_key_from` = '$transaction_public_key_from' AND `hash` = '$transaction_hash' LIMIT 1"),0,0);
  491. // Check for valid attribute
  492. if($transaction_attribute == "G" || $transaction_attribute == "T" || $transaction_attribute == "H")
  493. {
  494. if(empty($found_duplicate) == TRUE)
  495. {
  496. $sql = "INSERT INTO `transaction_history` (`timestamp`,`public_key_from`,`public_key_to`,`crypt_data1`,`crypt_data2`,`crypt_data3`, `hash`, `attribute`)
  497. VALUES ('$transaction_timestamp', '$transaction_public_key_from', '$transaction_public_key_to', '$transaction_crypt1', '$transaction_crypt2' , '$transaction_crypt3', '$transaction_hash' , '$transaction_attribute')";
  498. if(mysql_query($sql) == TRUE)
  499. {
  500. // Flag for a re-check afterwards
  501. $double_check_block = TRUE;
  502. }
  503. }
  504. }
  505. $tc++;
  506. } // End while loop
  507. }//End Database clear block check
  508. // Double check the new hash against the last block transanstion(s) in case of tampering
  509. $time3 = transaction_cycle(0 - $current_generation_block + 1 + $hash_number);
  510. $time4 = transaction_cycle(0 - $current_generation_block + 2 + $hash_number);
  511. $double_check_hash = mysql_result(mysql_query("SELECT * FROM `transaction_history` WHERE `timestamp` >= $time3 AND `timestamp` < $time4 AND `attribute` = 'H' LIMIT 1"),0,"hash");
  512. // Build Hash from previous transaction block data
  513. $sql = "SELECT * FROM `transaction_history` WHERE `timestamp` >= $time1 AND `timestamp` < $time2 ORDER BY `timestamp`, `hash`";
  514. $sql_result = mysql_query($sql);
  515. $sql_num_results = mysql_num_rows($sql_result);
  516. $build_hash = 0;
  517. for ($i = 0; $i < $sql_num_results; $i++)
  518. {
  519. $sql_row = mysql_fetch_array($sql_result);
  520. $build_hash .= $sql_row["hash"];
  521. }
  522. // Transaction(s) hash
  523. $build_hash = hash('sha256', $build_hash);
  524. if($double_check_hash == $build_hash)
  525. {
  526. // Hash matches up to previous transaction data
  527. }
  528. else
  529. {
  530. // Hash is invalid, something is wrong, trigger another double check
  531. $double_check_block = TRUE;
  532. }
  533. } // End Hash agree/disagree
  534. else
  535. {
  536. // Majority peers agree +1 to sync blocks
  537. $sync_block++;
  538. }
  539. if($double_check_block == TRUE && $double_check_counter < 2)
  540. {
  541. //Reset to run loop again
  542. $hash_number--;
  543. $h--;
  544. $double_check_counter++;
  545. }
  546. else if($double_check_block == TRUE && $double_check_counter >= 2)
  547. {
  548. // There is too much conflict between the peers
  549. $double_check_counter = 0;
  550. // Wipe this block and hope that a future check
  551. // will have the peer conflict resolved
  552. $sql = "DELETE FROM `transaction_history` WHERE `timestamp` >= $time1 AND `timestamp` < $time2";
  553. mysql_query($sql);
  554. write_log("Too Much Peer Conflict for Block #$block_number. This block will remain empty until repaired.", "TC");
  555. }
  556. else
  557. {
  558. //Reset failsafe counter
  559. $double_check_counter = 0;
  560. }
  561. $hash_number++;
  562. } // End for Loop - Hash check cycling
  563. //***********************************************************************************
  564. if($sync_block == $hash_check_counter)
  565. {
  566. if($error_check_active == FALSE)
  567. {
  568. write_log("Automatic History Check Complete. No Errors Found with Block #" . ($hash_number - ($hash_check_counter - 1)) . " to Block #" . $hash_number, "TC");
  569. }
  570. // The number of block checks equals the number in sync
  571. // so store the last block number in the database so that
  572. // the server will know where to start from on the next cycle
  573. if($foundation_block_check == 1)
  574. {
  575. $sql = "UPDATE `options` SET `field_data` = '$hash_number' WHERE `options`.`field_name` = 'foundation_block_check_start' LIMIT 1";
  576. mysql_query($sql);
  577. }
  578. else
  579. {
  580. $sql = "UPDATE `options` SET `field_data` = '$hash_number' WHERE `options`.`field_name` = 'block_check_start' LIMIT 1";
  581. mysql_query($sql);
  582. }
  583. }
  584. if($error_check_active == TRUE
  585. && $foundation_block_check != 1
  586. && $sync_block == $hash_check_counter) // Reset transaction history hash after error check completes
  587. {
  588. $total = mysql_query("SELECT COUNT(*) FROM `transaction_history`");
  589. $total = mysql_fetch_array($total);
  590. $hash = $total[0];
  591. $previous_foundation_block = foundation_cycle(-1, TRUE);
  592. $current_foundation_cycle = foundation_cycle(0);
  593. $next_foundation_cycle = foundation_cycle(1);
  594. $current_history_foundation = mysql_result(mysql_query("SELECT * FROM `transaction_foundation` WHERE `block` = $previous_foundation_block LIMIT 1"),0,"hash");
  595. $hash = $hash . $current_history_foundation;
  596. $sql = "SELECT * FROM `transaction_history` WHERE `timestamp` >= $current_foundation_cycle AND `timestamp` < $next_foundation_cycle AND `attribute` = 'H' ORDER BY `timestamp`";
  597. $sql_result = mysql_query($sql);
  598. $sql_num_results = mysql_num_rows($sql_result);
  599. for ($i = 0; $i < $sql_num_results; $i++)
  600. {
  601. $sql_row = mysql_fetch_array($sql_result);
  602. $hash .= $sql_row["hash"];
  603. }
  604. $history_hash = hash('md5', $hash);
  605. // Update database with new hash
  606. $sql = "UPDATE `options` SET `field_data` = '$history_hash' WHERE `field_name` = 'transaction_history_hash' LIMIT 1";
  607. mysql_query($sql);
  608. // Reset error block
  609. $sql = "UPDATE `options` SET `field_data` = '0' WHERE `field_name` = 'transaction_history_block_check' LIMIT 1";
  610. mysql_query($sql);
  611. write_log("Manual History Check Complete. No Errors Found with Block #$transaction_history_block_check to Block #" . ($transaction_history_block_check + $hash_check_counter - 1), "TC");
  612. }
  613. //***********************************************************************************
  614. } // End Compare Tallies
  615. else
  616. {
  617. // Entire Transaction History in sync, reset block check start to 0
  618. $block_check_start = mysql_result(mysql_query("SELECT * FROM `options` WHERE `field_name` = 'block_check_start' LIMIT 1"),0,"field_data");
  619. if($block_check_start > 0)
  620. {
  621. $sql = "UPDATE `options` SET `field_data` = '0' WHERE `options`.`field_name` = 'block_check_start' LIMIT 1";
  622. mysql_query($sql);
  623. $sql = "UPDATE `options` SET `field_data` = '1' WHERE `options`.`field_name` = 'block_check_back' LIMIT 1";
  624. mysql_query($sql);
  625. }
  626. if(rand(1,4) == 2)
  627. {
  628. // Poll a random block from a random peer for random accuracy :)
  629. // Within the range of the current foundation block to now
  630. $current_foundation_block = foundation_cycle(0, TRUE) * 500;
  631. $random_block = rand($current_foundation_block, transaction_cycle(-1, TRUE));
  632. $sql = "SELECT * FROM `active_peer_list` ORDER BY RAND()";
  633. $sql_result = mysql_query($sql);
  634. $sql_num_results = mysql_num_rows($sql_result);
  635. if($sql_num_results > 0)
  636. {
  637. $sql_row = mysql_fetch_array($sql_result);
  638. $ip_address = $sql_row["IP_Address"];
  639. $domain = $sql_row["domain"];
  640. $subfolder = $sql_row["subfolder"];
  641. $port_number = $sql_row["port_number"];
  642. if(empty($domain) == TRUE)
  643. {
  644. $site_address = $ip_address;
  645. }
  646. else
  647. {
  648. $site_address = $domain;
  649. }
  650. if($port_number == 443)
  651. {
  652. $ssl = "s";
  653. }
  654. else
  655. {
  656. $ssl = NULL;
  657. }
  658. // Start with this hash
  659. $poll_peer = filter_sql(file_get_contents("http$ssl://$site_address:$port_number/$subfolder/transclerk.php?action=block_hash&block_number=$random_block", FALSE, $context, NULL, 65));
  660. if(empty($poll_peer) == FALSE && strlen($poll_peer) > 32)
  661. {
  662. // Do a real hash compare
  663. $current_generation_block = transaction_cycle(0, TRUE);
  664. $time1 = transaction_cycle(0 - $current_generation_block + $random_block);
  665. $time2 = transaction_cycle(0 - $current_generation_block + 1 + $random_block);
  666. $sql = "SELECT * FROM `transaction_history` WHERE `timestamp` >= $time1 AND `timestamp` < $time2 ORDER BY `timestamp`, `hash`";
  667. $sql_result = mysql_query($sql);
  668. $sql_num_results = mysql_num_rows($sql_result);
  669. $random_hash_build = 0;
  670. if($sql_num_results > 0)
  671. {
  672. for ($i = 0; $i < $sql_num_results; $i++)
  673. {
  674. $sql_row = mysql_fetch_array($sql_result);
  675. $random_hash_build .= $sql_row["hash"];
  676. }
  677. }
  678. $random_hash_build = hash('sha256', $random_hash_build);
  679. if($poll_peer === $random_hash_build)
  680. {
  681. // All is well in the transaction history
  682. }
  683. else if($poll_peer !== $random_hash_build && empty($poll_peer) == FALSE)
  684. {
  685. // Something is wrong, transaction history has an error.
  686. // Schedule a check in case the peer has an error and not us.
  687. $sql = "UPDATE `options` SET `field_data` = '$random_block' WHERE `field_name` = 'transaction_history_block_check' LIMIT 1";
  688. mysql_query($sql);
  689. write_log("One of my Peers ($site_address) Reports that My Block #$random_block is Wrong. Will Double Check with other Peers before making any corrections.", "TC");
  690. }
  691. } // End empty poll check
  692. } // End if/then record count check
  693. } // Random chance check
  694. } // End else
  695. //***********************************************************************************
  696. } // End if/then check for processing for more than 3 records
  697. //***********************************************************************************
  698. } // End if/then time check
  699. //***********************************************************************************
  700. //***********************************************************************************
  701. // Script finished, set status to 0
  702. $sql = "UPDATE `main_loop_status` SET `field_data` = '0' WHERE `main_loop_status`.`field_name` = 'transclerk_heartbeat_active' LIMIT 1";
  703. mysql_query($sql);
  704. // Record when this script finished
  705. $sql = "UPDATE `main_loop_status` SET `field_data` = '" . time() . "' WHERE `main_loop_status`.`field_name` = 'transclerk_last_heartbeat' LIMIT 1";
  706. mysql_query($sql);
  707. ?>