PageRenderTime 52ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/public/include/classes/worker.class.php

https://github.com/usrio/php-mmcfe-ng
PHP | 300 lines | 232 code | 14 blank | 54 comment | 40 complexity | 5c8c5aaf8d5243157a629a631dc4a6e1 MD5 | raw file
Possible License(s): Apache-2.0
  1. <?php
  2. // Make sure we are called from index.php
  3. if (!defined('SECURITY'))
  4. die('Hacking attempt');
  5. class Worker {
  6. private $sError = '';
  7. private $table = 'pool_worker';
  8. public function __construct($debug, $mysqli, $user, $share, $config) {
  9. $this->debug = $debug;
  10. $this->mysqli = $mysqli;
  11. $this->user = $user;
  12. $this->share = $share;
  13. $this->config = $config;
  14. $this->debug->append("Instantiated Worker class", 2);
  15. }
  16. // get and set methods
  17. private function setErrorMessage($msg) {
  18. $this->sError = $msg;
  19. }
  20. public function getError() {
  21. return $this->sError;
  22. }
  23. private function checkStmt($bState) {
  24. if ($bState ===! true) {
  25. $this->debug->append("Failed to prepare statement: " . $this->mysqli->error);
  26. $this->setErrorMessage('Internal application Error');
  27. return false;
  28. }
  29. return true;
  30. }
  31. /**
  32. * Update worker list for a user
  33. * @param account_id int User ID
  34. * @param data array All workers and their settings
  35. * @return bool
  36. **/
  37. public function updateWorkers($account_id, $data) {
  38. $this->debug->append("STA " . __METHOD__, 4);
  39. if (!is_array($data)) {
  40. $this->setErrorMessage('No workers to update');
  41. return false;
  42. }
  43. $username = $this->user->getUserName($account_id);
  44. $iFailed = 0;
  45. foreach ($data as $key => $value) {
  46. if ('' === $value['username'] || '' === $value['password']) {
  47. $iFailed++;
  48. } else {
  49. // Prefix the WebUser to Worker name
  50. $value['username'] = "$username." . $value['username'];
  51. $stmt = $this->mysqli->prepare("UPDATE $this->table SET password = ?, username = ?, monitor = ? WHERE account_id = ? AND id = ?");
  52. if ( ! ( $this->checkStmt($stmt) && $stmt->bind_param('ssiii', $value['password'], $value['username'], $value['monitor'], $account_id, $key) && $stmt->execute()) )
  53. $iFailed++;
  54. }
  55. }
  56. if ($iFailed == 0)
  57. return true;
  58. // Catchall
  59. $this->setErrorMessage('Failed to update ' . $iFailed . ' worker.');
  60. return false;
  61. }
  62. /**
  63. * Fetch all IDLE workers that have monitoring enabled
  64. * @param none
  65. * @return data array Workers in IDLE state and monitoring enabled
  66. **/
  67. public function getAllIdleWorkers() {
  68. $this->debug->append("STA " . __METHOD__, 4);
  69. $stmt = $this->mysqli->prepare("
  70. SELECT account_id, id, username
  71. FROM " . $this->table . " AS w
  72. WHERE monitor = 1
  73. AND (
  74. SELECT IFNULL(SUM(IF(our_result = 'Y', 1, 0)), 0) FROM " . $this->share->getTableName() . " WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)
  75. ) = 0");
  76. if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
  77. return $result->fetch_all(MYSQLI_ASSOC);
  78. // Catchall
  79. $this->setErrorMessage("Unable to fetch IDLE, monitored workers");
  80. return false;
  81. }
  82. /**
  83. * Fetch a specific worker and its status
  84. * @param id int Worker ID
  85. * @return mixed array Worker details
  86. **/
  87. public function getWorker($id) {
  88. $this->debug->append("STA " . __METHOD__, 4);
  89. $stmt = $this->mysqli->prepare("
  90. SELECT id, username, password, monitor,
  91. ( SELECT COUNT(id) FROM " . $this->share->getTableName() . " WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)) AS count_all,
  92. ( SELECT COUNT(id) FROM " . $this->share->getArchiveTableName() . " WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)) AS count_all_archive,
  93. (
  94. SELECT
  95. IFNULL(IF(our_result='Y', ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * POW(2, " . $this->config['target_bits'] . ") / 600 / 1000), 0), 0) AS hashrate
  96. FROM " . $this->share->getTableName() . "
  97. WHERE
  98. username = w.username
  99. AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)
  100. ) + (
  101. SELECT
  102. IFNULL(IF(our_result='Y', ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * POW(2, " . $this->config['target_bits'] . ") / 600 / 1000), 0), 0) AS hashrate
  103. FROM " . $this->share->getArchiveTableName() . "
  104. WHERE
  105. username = w.username
  106. AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)
  107. ) AS hashrate,
  108. (
  109. SELECT IFNULL(ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) / count_all, 2), 0)
  110. FROM " . $this->share->getTableName() . "
  111. WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)
  112. ) + (
  113. SELECT IFNULL(ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) / count_all_archive, 2), 0)
  114. FROM " . $this->share->getArchiveTableName() . "
  115. WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)
  116. ) AS difficulty
  117. FROM $this->table AS w
  118. WHERE id = ?
  119. ");
  120. if ($this->checkStmt($stmt) && $stmt->bind_param('i', $id) && $stmt->execute() && $result = $stmt->get_result())
  121. return $result->fetch_assoc();
  122. // Catchall
  123. return false;
  124. }
  125. /**
  126. * Fetch all workers for an account
  127. * @param account_id int User ID
  128. * @return mixed array Workers and their settings or false
  129. **/
  130. public function getWorkers($account_id, $interval=600) {
  131. $this->debug->append("STA " . __METHOD__, 4);
  132. $stmt = $this->mysqli->prepare("
  133. SELECT id, username, password, monitor,
  134. ( SELECT COUNT(id) FROM " . $this->share->getTableName() . " WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL ? SECOND)) AS count_all,
  135. ( SELECT COUNT(id) FROM " . $this->share->getArchiveTableName() . " WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL ? SECOND)) AS count_all_archive,
  136. (
  137. SELECT
  138. IFNULL(IF(our_result='Y', ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * 65536 / ? / 1000), 0), 0) AS hashrate
  139. FROM " . $this->share->getTableName() . "
  140. WHERE
  141. username = w.username
  142. AND time > DATE_SUB(now(), INTERVAL ? SECOND)
  143. ) + (
  144. SELECT
  145. IFNULL(IF(our_result='Y', ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * 65536 / ? / 1000), 0), 0) AS hashrate
  146. FROM " . $this->share->getArchiveTableName() . "
  147. WHERE
  148. username = w.username
  149. AND time > DATE_SUB(now(), INTERVAL ? SECOND)
  150. ) AS hashrate,
  151. (
  152. SELECT IFNULL(ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) / count_all, 2), 0)
  153. FROM " . $this->share->getTableName() . "
  154. WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL ? SECOND)
  155. ) + (
  156. SELECT IFNULL(ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) / count_all_archive, 2), 0)
  157. FROM " . $this->share->getArchiveTableName() . "
  158. WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL ? SECOND)
  159. ) AS difficulty
  160. FROM $this->table AS w
  161. WHERE account_id = ?");
  162. if ($this->checkStmt($stmt) && $stmt->bind_param('iiiiiiiii', $interval, $interval, $interval, $interval, $interval, $interval, $interval, $interval, $account_id) && $stmt->execute() && $result = $stmt->get_result())
  163. return $result->fetch_all(MYSQLI_ASSOC);
  164. // Catchall
  165. $this->setErrorMessage('Failed to fetch workers for your account');
  166. $this->debug->append('Fetching workers failed: ' . $this->mysqli->error);
  167. return false;
  168. }
  169. /**
  170. * Fetch all workers for admin panel
  171. * @param limit int
  172. * @return mixed array Workers and their settings or false
  173. **/
  174. public function getAllWorkers($iLimit=0, $interval=600) {
  175. $this->debug->append("STA " . __METHOD__, 4);
  176. $stmt = $this->mysqli->prepare("
  177. SELECT id, username, password, monitor,
  178. IFNULL(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty), 0) AS difficulty,
  179. (
  180. SELECT
  181. IFNULL(IF(our_result='Y', ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * 65536 / ? / 1000), 0), 0) AS hashrate
  182. FROM " . $this->share->getTableName() . "
  183. WHERE
  184. username = w.username
  185. AND time > DATE_SUB(now(), INTERVAL ? SECOND)
  186. ) + (
  187. SELECT
  188. IFNULL(IF(our_result='Y', ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * 65536 / ? / 1000), 0), 0) AS hashrate
  189. FROM " . $this->share->getArchiveTableName() . "
  190. WHERE
  191. username = w.username
  192. AND time > DATE_SUB(now(), INTERVAL ? SECOND)
  193. ) AS hashrate,
  194. ((
  195. SELECT IFNULL(ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)), 2), 0)
  196. FROM " . $this->share->getTableName() . "
  197. WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL ? SECOND)
  198. ) + (
  199. SELECT IFNULL(ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)), 2), 0)
  200. FROM " . $this->share->getArchiveTableName() . "
  201. WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL ? SECOND)
  202. )) / ((
  203. SELECT COUNT(id)
  204. FROM " . $this->share->getTableName() . "
  205. WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL ? SECOND)
  206. ) + (
  207. SELECT COUNT(id)
  208. FROM " . $this->share->getArchiveTableName() . "
  209. WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL ? SECOND)
  210. )) AS avg_difficulty
  211. FROM $this->table AS w
  212. ORDER BY hashrate DESC LIMIT ?");
  213. if ($this->checkStmt($stmt) && $stmt->bind_param('iiiiiiiii', $interval, $interval, $interval, $interval, $interval, $interval, $interval, $interval, $iLimit) && $stmt->execute() && $result = $stmt->get_result())
  214. return $result->fetch_all(MYSQLI_ASSOC);
  215. // Catchall
  216. $this->setErrorMessage('Failed to fetch workers');
  217. $this->debug->append('Fetching workers failed: ' . $this->mysqli->error);
  218. return false;
  219. }
  220. /**
  221. * Get all currently active workers in the past 10 minutes
  222. * @param none
  223. * @return data mixed int count if any workers are active, false otherwise
  224. **/
  225. public function getCountAllActiveWorkers() {
  226. $this->debug->append("STA " . __METHOD__, 4);
  227. $stmt = $this->mysqli->prepare("
  228. SELECT COUNT(DISTINCT(username)) AS total
  229. FROM " . $this->share->getTableName() . "
  230. WHERE our_result = 'Y'
  231. AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)
  232. ");
  233. if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
  234. return $result->fetch_object()->total;
  235. return false;
  236. }
  237. /**
  238. * Add new worker to an existing web account
  239. * The webuser name is prefixed to the worker name
  240. * Passwords are plain text for pushpoold
  241. * @param account_id int User ID
  242. * @param workerName string Worker name
  243. * @param workerPassword string Worker password
  244. * @return bool
  245. **/
  246. public function addWorker($account_id, $workerName, $workerPassword) {
  247. $this->debug->append("STA " . __METHOD__, 4);
  248. if ('' === $workerName || '' === $workerPassword) {
  249. $this->setErrorMessage('Worker name and/or password may not be empty');
  250. return false;
  251. }
  252. $username = $this->user->getUserName($account_id);
  253. $workerName = "$username.$workerName";
  254. $stmt = $this->mysqli->prepare("INSERT INTO $this->table (account_id, username, password) VALUES(?, ?, ?)");
  255. if ($this->checkStmt($stmt)) {
  256. $stmt->bind_param('iss', $account_id, $workerName, $workerPassword);
  257. if (!$stmt->execute()) {
  258. $this->setErrorMessage( 'Failed to add worker' );
  259. if ($stmt->sqlstate == '23000') $this->setErrorMessage( 'Worker already exists' );
  260. return false;
  261. }
  262. return true;
  263. }
  264. return false;
  265. }
  266. /**
  267. * Delete existing worker from account
  268. * @param account_id int User ID
  269. * @param id int Worker ID
  270. * @return bool
  271. **/
  272. public function deleteWorker($account_id, $id) {
  273. $this->debug->append("STA " . __METHOD__, 4);
  274. $stmt = $this->mysqli->prepare("DELETE FROM $this->table WHERE account_id = ? AND id = ?");
  275. if ($this->checkStmt($stmt)) {
  276. $stmt->bind_param('ii', $account_id, $id);
  277. if ($stmt->execute() && $stmt->affected_rows == 1) {
  278. return true;
  279. } else {
  280. $this->setErrorMessage( 'Unable to delete worker' );
  281. }
  282. }
  283. return false;
  284. }
  285. }
  286. $worker = new Worker($debug, $mysqli, $user, $share, $config);