PageRenderTime 53ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/v1.9/genpeer.php

https://bitbucket.org/rev22/timekoin
PHP | 405 lines | 269 code | 74 blank | 62 comment | 63 complexity | 471f55357f11b8be01807334ac41cb4a MD5 | raw file
  1. <?PHP
  2. include 'configuration.php';
  3. include 'function.php';
  4. set_time_limit(90);
  5. //***********************************************************************************
  6. //***********************************************************************************
  7. if(GENPEER_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 generation hash poll
  27. if($_GET["action"] == "gen_hash")
  28. {
  29. $transaction_queue_hash = mysql_result(mysql_query("SELECT * FROM `options` WHERE `field_name` = 'generating_peers_hash' LIMIT 1"),0,"field_data");
  30. echo $transaction_queue_hash;
  31. // Log inbound IP activity
  32. mysql_query("INSERT INTO `ip_activity` (`timestamp` ,`ip`, `attribute`)VALUES ('" . time() . "', '" . $_SERVER['REMOTE_ADDR'] . "', 'GP')");
  33. exit;
  34. }
  35. //***********************************************************************************
  36. //***********************************************************************************
  37. // Answer generation peer list poll
  38. if($_GET["action"] == "gen_peer_list")
  39. {
  40. $sql = "SELECT * FROM `generating_peer_list` ORDER BY RAND() LIMIT 50";
  41. $sql_result = mysql_query($sql);
  42. $sql_num_results = mysql_num_rows($sql_result);
  43. $queue_number = 1;
  44. if($sql_num_results > 0)
  45. {
  46. for ($i = 0; $i < $sql_num_results; $i++)
  47. {
  48. $sql_row = mysql_fetch_array($sql_result);
  49. echo "-----public_key$queue_number=" , base64_encode($sql_row["public_key"]) , "-----join$queue_number=" , $sql_row["join_peer_list"] , "-----last$queue_number=" , $sql_row["last_generation"] , "-----END$queue_number";
  50. $queue_number++;
  51. }
  52. }
  53. // Log inbound IP activity
  54. mysql_query("INSERT INTO `ip_activity` (`timestamp` ,`ip`, `attribute`)VALUES ('" . time() . "', '" . $_SERVER['REMOTE_ADDR'] . "', 'GP')");
  55. exit;
  56. }
  57. //***********************************************************************************
  58. //***********************************************************************************
  59. $loop_active = mysql_result(mysql_query("SELECT * FROM `main_loop_status` WHERE `field_name` = 'genpeer_heartbeat_active' LIMIT 1"),0,"field_data");
  60. // Check if loop is already running
  61. if($loop_active == 0)
  62. {
  63. // Set the working status of 1
  64. $sql = "UPDATE `main_loop_status` SET `field_data` = '1' WHERE `main_loop_status`.`field_name` = 'genpeer_heartbeat_active' LIMIT 1";
  65. mysql_query($sql);
  66. }
  67. else
  68. {
  69. // Loop called while still working
  70. exit;
  71. }
  72. //***********************************************************************************
  73. //***********************************************************************************
  74. $next_generation_cycle = transaction_cycle(1);
  75. $current_generation_cycle = transaction_cycle(0);
  76. // Can we work on the transactions in the database?
  77. // Not allowed 35 seconds before and 35 seconds after generation cycle.
  78. if(($next_generation_cycle - time()) > 35 && (time() - $current_generation_cycle) > 35)
  79. {
  80. //***********************************************************************************
  81. // Determine when to run this by comparing the last digit the current block and
  82. // the 3rd digit the generation time; when they match, run the gen key scoring.
  83. $str = strval($current_generation_cycle);
  84. $last3_gen = $str[strlen($str)-3];
  85. $current_generation_block = transaction_cycle(0, TRUE);
  86. TKRandom::seed($current_generation_block);
  87. $tk_random_number = TKRandom::num(0, 9);
  88. if($last3_gen + $tk_random_number > 14)
  89. {
  90. // Find all transactions between the Previous Transaction Cycle and the Current
  91. $sql = "SELECT * FROM `generating_peer_queue` WHERE `timestamp` < $current_generation_cycle ORDER BY `timestamp`";
  92. $sql_result = mysql_query($sql);
  93. $sql_num_results = mysql_num_rows($sql_result);
  94. if($sql_num_results > 0)
  95. {
  96. if($sql_num_results == 1)
  97. {
  98. // Winner by default
  99. $sql_row = mysql_fetch_array($sql_result);
  100. $public_key = $sql_row["public_key"];
  101. $sql = "INSERT INTO `generating_peer_list` (`public_key` ,`join_peer_list` ,`last_generation`)VALUES ('$public_key', '$current_generation_cycle', '$current_generation_cycle')";
  102. mysql_query($sql);
  103. write_log("Generation Peer Elected for Public Key: " . base64_encode($public_key), "GP");
  104. }
  105. else
  106. {
  107. // More than 1 peer request, start a scoring of all public keys,
  108. // the public key with the most points win
  109. $highest_score = 0;
  110. $public_key_winner = "";
  111. for ($i = 0; $i < $sql_num_results; $i++)
  112. {
  113. $sql_row = mysql_fetch_array($sql_result);
  114. $public_key = $sql_row["public_key"];
  115. $public_key_score = scorePublicKey($public_key);
  116. if($public_key_score > $highest_score)
  117. {
  118. $public_key_winner = $public_key;
  119. $highest_score = $public_key_score;
  120. }
  121. }
  122. $sql = "INSERT INTO `generating_peer_list` (`public_key` ,`join_peer_list` ,`last_generation`)VALUES ('$public_key_winner', '$current_generation_cycle', '$current_generation_cycle')";
  123. mysql_query($sql);
  124. write_log("Generation Peer Elected for Public Key: " . base64_encode($public_key_winner), "GP");
  125. } // End if/then winner check
  126. // Clear out queue for next round
  127. $sql = "TRUNCATE TABLE `generating_peer_queue`";
  128. mysql_query($sql);
  129. // Wait after generation election for sanity reasons
  130. sleep(2);
  131. } //End if/then results check
  132. } // End if/then timing comparison check
  133. //***********************************************************************************
  134. // Store a hash of the current list of generating peers
  135. $sql = "SELECT * FROM `generating_peer_list` ORDER BY `join_peer_list`";
  136. $sql_result = mysql_query($sql);
  137. $sql_num_results = mysql_num_rows($sql_result);
  138. $generating_hash = 0;
  139. if($sql_num_results > 0)
  140. {
  141. for ($i = 0; $i < $sql_num_results; $i++)
  142. {
  143. $sql_row = mysql_fetch_array($sql_result);
  144. $generating_hash .= $sql_row["public_key"] . $sql_row["join_peer_list"];
  145. }
  146. $generating_hash = hash('md5', $generating_hash);
  147. }
  148. $generation_peer_hash = mysql_result(mysql_query("SELECT * FROM `options` WHERE `field_name` = 'generating_peers_hash' LIMIT 1"),0,"field_data");
  149. if($generating_hash == $generation_peer_hash)
  150. {
  151. // Both match, no need to update database
  152. }
  153. else
  154. {
  155. // Store in database for quick reference from database
  156. $sql = "UPDATE `options` SET `field_data` = '$generating_hash' WHERE `options`.`field_name` = 'generating_peers_hash' LIMIT 1";
  157. mysql_query($sql);
  158. }
  159. //***********************************************************************************
  160. //***********************************************************************************
  161. // How does my generation peer list compare to others?
  162. // Ask all of my active peers
  163. ini_set('user_agent', 'Timekoin Server (Genpeer) v' . TIMEKOIN_VERSION);
  164. ini_set('default_socket_timeout', 3); // Timeout for request in seconds
  165. $context = stream_context_create(array('http' => array('header'=>'Connection: close'))); // Force close socket after complete
  166. $sql = "SELECT * FROM `active_peer_list` ORDER BY RAND()";
  167. $sql_result = mysql_query($sql);
  168. $sql_num_results = mysql_num_rows($sql_result);
  169. $gen_list_hash_match = 0;
  170. $gen_list_hash_different = 0;
  171. $site_address;
  172. if($sql_num_results > 0)
  173. {
  174. $hash_different = array();
  175. for ($i = 0; $i < $sql_num_results; $i++)
  176. {
  177. $sql_row = mysql_fetch_array($sql_result);
  178. $ip_address = $sql_row["IP_Address"];
  179. $domain = $sql_row["domain"];
  180. $subfolder = $sql_row["subfolder"];
  181. $port_number = $sql_row["port_number"];
  182. if(empty($domain) == TRUE)
  183. {
  184. $site_address = $ip_address;
  185. }
  186. else
  187. {
  188. $site_address = $domain;
  189. }
  190. if($port_number == 443)
  191. {
  192. $ssl = "s";
  193. }
  194. else
  195. {
  196. $ssl = NULL;
  197. }
  198. $poll_peer = filter_sql(file_get_contents("http$ssl://$site_address:$port_number/$subfolder/genpeer.php?action=gen_hash", FALSE, $context, NULL, 100));
  199. if($generating_hash === $poll_peer)
  200. {
  201. $gen_list_hash_match++;
  202. }
  203. else
  204. {
  205. // Make sure both the response exist and that no connectoin error occurred
  206. if(empty($poll_peer) == FALSE && $poll_peer !== FALSE)
  207. {
  208. $gen_list_hash_different++;
  209. $hash_different["ip_address$gen_list_hash_different"] = $ip_address;
  210. $hash_different["domain$gen_list_hash_different"] = $domain;
  211. $hash_different["subfolder$gen_list_hash_different"] = $subfolder;
  212. $hash_different["port_number$gen_list_hash_different"] = $port_number;
  213. }
  214. }
  215. } // End for Loop
  216. } // End number of results check
  217. // Compare tallies
  218. if($gen_list_hash_different > $gen_list_hash_match)
  219. {
  220. //50% over more of the active peers have a different gen list, start comparing your
  221. //gen list with one that is different
  222. $generation_peer_list_no_sync = intval(mysql_result(mysql_query("SELECT * FROM `options` WHERE `field_name` = 'generation_peer_list_no_sync' LIMIT 1"),0,"field_data"));
  223. if($generation_peer_list_no_sync > 20)
  224. {
  225. // Our generation peer list is out of sync for a long time, clear to list to start over
  226. mysql_query("TRUNCATE TABLE `generating_peer_list`");
  227. // Reset out of sync counter
  228. mysql_query("UPDATE `options` SET `field_data` = '0' WHERE `options`.`field_name` = 'generation_peer_list_no_sync' LIMIT 1");
  229. write_log("Generation Peer List has Become Stale, Attemping to Purge and Rebuild.", "GP");
  230. }
  231. else
  232. {
  233. $generation_peer_list_no_sync++;
  234. mysql_query("UPDATE `options` SET `field_data` = '$generation_peer_list_no_sync' WHERE `options`.`field_name` = 'generation_peer_list_no_sync' LIMIT 1");
  235. }
  236. $i = rand(1, $gen_list_hash_different); // Select Random Peer from Disagree List
  237. $ip_address = $hash_different["ip_address$i"];
  238. $domain = $hash_different["domain$i"];
  239. $subfolder = $hash_different["subfolder$i"];
  240. $port_number = $hash_different["port_number$i"];
  241. if(empty($domain) == TRUE)
  242. {
  243. $site_address = $ip_address;
  244. }
  245. else
  246. {
  247. $site_address = $domain;
  248. }
  249. if($port_number == 443)
  250. {
  251. $ssl = "s";
  252. }
  253. else
  254. {
  255. $ssl = NULL;
  256. }
  257. $poll_peer = filter_sql(file_get_contents("http$ssl://$site_address:$port_number/$subfolder/genpeer.php?action=gen_peer_list", FALSE, $context, NULL, 100000));
  258. $match_number = 1;
  259. $gen_peer_public_key = "Start";
  260. while(empty($gen_peer_public_key) == FALSE)
  261. {
  262. $gen_peer_public_key = find_string("-----public_key$match_number=", "-----join$match_number", $poll_peer);
  263. $gen_peer_join_peer_list = find_string("-----join$match_number=", "-----last$match_number", $poll_peer);
  264. $gen_peer_last_generation = find_string("-----last$match_number=", "-----END$match_number", $poll_peer);
  265. $gen_peer_public_key = base64_decode($gen_peer_public_key);
  266. //Check if this public key is already in our peer list
  267. $public_key_match = mysql_result(mysql_query("SELECT * FROM `generating_peer_list` WHERE `public_key` = '$gen_peer_public_key' LIMIT 1"),0,0);
  268. if(empty($public_key_match) == TRUE)
  269. {
  270. // No match in database to this public key
  271. if(strlen($gen_peer_public_key) > 256 && empty($gen_peer_public_key) == FALSE && $gen_peer_join_peer_list <= $current_generation_cycle && $gen_peer_join_peer_list > TRANSACTION_EPOCH)
  272. {
  273. $sql = "INSERT INTO `generating_peer_list` (`public_key`,`join_peer_list`,`last_generation`)
  274. VALUES ('$gen_peer_public_key', '$gen_peer_join_peer_list', '$gen_peer_last_generation')";
  275. mysql_query($sql);
  276. }
  277. }
  278. $match_number++;
  279. } // End While Loop
  280. } // End Compare Tallies
  281. else
  282. {
  283. // Clear out any out of sync counts once the list is in sync
  284. if(rand(1,60) == 30) // Randomize to avoid spamming the DB
  285. {
  286. // Reset out of sync counter
  287. mysql_query("UPDATE `options` SET `field_data` = '0' WHERE `options`.`field_name` = 'generation_peer_list_no_sync' LIMIT 1");
  288. }
  289. }
  290. //***********************************************************************************
  291. // Scan for new request of generating peers
  292. $sql = "SELECT * FROM `transaction_queue` WHERE `attribute` = 'R'";
  293. $sql_result = mysql_query($sql);
  294. $sql_num_results = mysql_num_rows($sql_result);
  295. if($sql_num_results > 0)
  296. {
  297. for ($i = 0; $i < $sql_num_results; $i++)
  298. {
  299. $sql_row = mysql_fetch_array($sql_result);
  300. $public_key = $sql_row["public_key"];
  301. $timestamp = $sql_row["timestamp"];
  302. $crypt1 = $sql_row["crypt_data1"];
  303. $crypt2 = $sql_row["crypt_data2"];
  304. //Valid Public Key
  305. $public_key_found_peer = mysql_result(mysql_query("SELECT * FROM `generating_peer_list` WHERE `public_key` = '$public_key' LIMIT 1"),0,"join_peer_list");
  306. $public_key_found_timestamp = mysql_result(mysql_query("SELECT * FROM `generating_peer_queue` WHERE `public_key` = '$public_key' LIMIT 1"),0,"timestamp");
  307. if(empty($public_key_found_timestamp) == TRUE && empty($public_key_found_peer) == TRUE && $timestamp >= $current_generation_cycle)
  308. {
  309. // Not found, add to queue
  310. // Check to make sure this public key isn't forged or made up to win the list
  311. openssl_public_decrypt(base64_decode($crypt1), $transaction_info, $public_key);
  312. if($transaction_info == $crypt2)
  313. {
  314. $sql = "INSERT INTO `generating_peer_queue` (`timestamp` ,`public_key`)VALUES ('$timestamp', '$public_key')";
  315. mysql_query($sql);
  316. write_log("Generation Peer Queue List was updated with Public Key: " . base64_encode($public_key), "GP");
  317. }
  318. }
  319. } // End for loop
  320. } // Empty results check
  321. //***********************************************************************************
  322. } // End If/then Time Check
  323. //***********************************************************************************
  324. //***********************************************************************************
  325. // Script finished, set status to 0
  326. $sql = "UPDATE `main_loop_status` SET `field_data` = '0' WHERE `main_loop_status`.`field_name` = 'genpeer_heartbeat_active' LIMIT 1";
  327. mysql_query($sql);
  328. // Record when this script finished
  329. $sql = "UPDATE `main_loop_status` SET `field_data` = '" . time() . "' WHERE `main_loop_status`.`field_name` = 'genpeer_last_heartbeat' LIMIT 1";
  330. mysql_query($sql);
  331. ?>