This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | $defflip = (!cfip()) ? exit(header('HTTP/1.1 401 Unauthorized')) : 1; |
||
3 | |||
4 | class Share Extends Base { |
||
5 | protected $table = 'shares'; |
||
6 | protected $tableArchive = 'shares_archive'; |
||
7 | private $oUpstream; |
||
8 | private $iLastUpstreamId; |
||
9 | // This defines each share |
||
10 | public $rem_host, $username, $our_result, $upstream_result, $reason, $solution, $time, $difficulty; |
||
11 | |||
12 | /** |
||
13 | * Fetch archive tables name for this class |
||
14 | * @param none |
||
15 | * @return data string Table name |
||
16 | **/ |
||
17 | public function getArchiveTableName() { |
||
18 | return $this->tableArchive; |
||
19 | } |
||
20 | |||
21 | /** |
||
22 | * Fetch a single share by ID |
||
23 | * @param id int Share ID |
||
24 | * @return array Share data |
||
25 | **/ |
||
26 | public function getShareById($id) { |
||
27 | return $this->getSingleAssoc($id); |
||
28 | } |
||
29 | |||
30 | /** |
||
31 | * Update an entire shares data |
||
32 | **/ |
||
33 | public function updateShareById($id, $data) { |
||
34 | $this->debug->append("STA " . __METHOD__, 4); |
||
35 | $sql = "UPDATE $this->table SET"; |
||
36 | $start = true; |
||
37 | // Remove ID column |
||
38 | unset($data['id']); |
||
39 | foreach ($data as $column => $value) { |
||
40 | $start == true ? $sql .= " $column = ? " : $sql .= ", $column = ?"; |
||
0 ignored issues
–
show
|
|||
41 | $start = false; |
||
42 | switch($column) { |
||
43 | case 'difficulty': |
||
44 | $this->addParam('d', $value); |
||
45 | break; |
||
46 | default: |
||
47 | $this->addParam('s', $value); |
||
48 | break; |
||
49 | } |
||
50 | } |
||
51 | $sql .= " WHERE id = ? LIMIT 1"; |
||
52 | $this->addParam('i', $id); |
||
53 | $stmt = $this->mysqli->prepare($sql); |
||
54 | View Code Duplication | if ($this->checkStmt($stmt) && call_user_func_array( array($stmt, 'bind_param'), $this->getParam()) && $stmt->execute()) |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
55 | return true; |
||
56 | return $this->sqlError(); |
||
57 | } |
||
58 | |||
59 | /** |
||
60 | * Get last inserted Share ID from Database |
||
61 | * Used for PPS calculations without moving to archive |
||
62 | **/ |
||
63 | public function getLastInsertedShareId() { |
||
64 | $stmt = $this->mysqli->prepare("SELECT MAX(id) AS id FROM $this->table"); |
||
65 | if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result()) |
||
66 | return $result->fetch_object()->id; |
||
67 | return $this->sqlError(); |
||
68 | } |
||
69 | |||
70 | /** |
||
71 | * Get all valid shares for this round |
||
72 | * @param previous_upstream int Previous found share accepted by upstream to limit results |
||
73 | * @param current_upstream int Current upstream accepted share |
||
74 | * @return data int Total amount of counted shares |
||
75 | **/ |
||
76 | public function getRoundShares($previous_upstream=0, $current_upstream) { |
||
77 | $stmt = $this->mysqli->prepare("SELECT |
||
78 | IFNULL(SUM(IF(s.difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty)), 0) AS total |
||
0 ignored issues
–
show
The property
config does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
79 | FROM $this->table AS s |
||
80 | LEFT JOIN " . $this->user->getTableName() . " AS a |
||
0 ignored issues
–
show
The property
user does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
81 | ON a.username = SUBSTRING_INDEX( s.username , '.', 1 ) |
||
82 | WHERE s.id > ? AND s.id <= ? AND s.our_result = 'Y' AND a.is_locked != 2 |
||
83 | "); |
||
84 | if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $previous_upstream, $current_upstream) && $stmt->execute() && $result = $stmt->get_result()) |
||
85 | return $result->fetch_object()->total; |
||
86 | return $this->sqlError(); |
||
0 ignored issues
–
show
The return type of
return $this->sqlError(); (boolean ) is incompatible with the return type documented by Share::getRoundShares of type data .
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design. Let’s take a look at an example: class Author {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
abstract class Post {
public function getAuthor() {
return 'Johannes';
}
}
class BlogPost extends Post {
public function getAuthor() {
return new Author('Johannes');
}
}
class ForumPost extends Post { /* ... */ }
function my_function(Post $post) {
echo strtoupper($post->getAuthor());
}
Our function ![]() |
|||
87 | } |
||
88 | |||
89 | /** |
||
90 | * Fetch all shares grouped by accounts to count share per account |
||
91 | * @param previous_upstream int Previous found share accepted by upstream to limit results |
||
92 | * @param current_upstream int Current upstream accepted share |
||
93 | * @param limit int Limit to this amount of shares for PPLNS |
||
94 | * @return data array username, valid and invalid shares from account |
||
95 | **/ |
||
96 | public function getSharesForAccounts($previous_upstream=0, $current_upstream) { |
||
97 | $stmt = $this->mysqli->prepare(" |
||
98 | SELECT |
||
99 | a.id, |
||
100 | SUBSTRING_INDEX( s.username , '.', 1 ) as username, |
||
101 | a.no_fees AS no_fees, |
||
102 | IFNULL(SUM(IF(our_result='Y', IF(s.difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty), 0)), 0) AS valid, |
||
103 | IFNULL(SUM(IF(our_result='N', IF(s.difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty), 0)), 0) AS invalid |
||
104 | FROM $this->table AS s |
||
105 | LEFT JOIN " . $this->user->getTableName() . " AS a |
||
106 | ON a.username = SUBSTRING_INDEX( s.username , '.', 1 ) |
||
107 | WHERE s.id > ? AND s.id <= ? AND a.is_locked != 2 |
||
108 | GROUP BY username DESC |
||
109 | "); |
||
110 | if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $previous_upstream, $current_upstream) && $stmt->execute() && $result = $stmt->get_result()) |
||
111 | return $result->fetch_all(MYSQLI_ASSOC); |
||
112 | return $this->sqlError(); |
||
0 ignored issues
–
show
The return type of
return $this->sqlError(); (boolean ) is incompatible with the return type documented by Share::getSharesForAccounts of type data .
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design. Let’s take a look at an example: class Author {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
abstract class Post {
public function getAuthor() {
return 'Johannes';
}
}
class BlogPost extends Post {
public function getAuthor() {
return new Author('Johannes');
}
}
class ForumPost extends Post { /* ... */ }
function my_function(Post $post) {
echo strtoupper($post->getAuthor());
}
Our function ![]() |
|||
113 | } |
||
114 | |||
115 | /** |
||
116 | * Fetch the highest available share ID from archive |
||
117 | **/ |
||
118 | function getMaxArchiveShareId() { |
||
0 ignored issues
–
show
|
|||
119 | $stmt = $this->mysqli->prepare("SELECT MAX(share_id) AS share_id FROM $this->tableArchive"); |
||
120 | if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result()) |
||
121 | return $result->fetch_object()->share_id; |
||
122 | return $this->sqlError(); |
||
123 | } |
||
124 | |||
125 | /** |
||
126 | * We need a certain amount of valid archived shares |
||
127 | * param left int Left/lowest share ID |
||
128 | * param right int Right/highest share ID |
||
129 | * return array data Returns an array with usernames as keys for easy access |
||
130 | **/ |
||
131 | function getArchiveShares($iCount) { |
||
0 ignored issues
–
show
|
|||
132 | $iMaxId = $this->getMaxArchiveShareId(); |
||
133 | $iMinId = $this->getMinArchiveShareId($iCount); |
||
134 | $stmt = $this->mysqli->prepare(" |
||
135 | SELECT |
||
136 | a.id, |
||
137 | SUBSTRING_INDEX( s.username , '.', 1 ) as account, |
||
138 | a.no_fees AS no_fees, |
||
139 | IFNULL(SUM(IF(our_result='Y', IF(s.difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty), 0)), 0) AS valid, |
||
140 | IFNULL(SUM(IF(our_result='N', IF(s.difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty), 0)), 0) AS invalid |
||
141 | FROM $this->tableArchive AS s |
||
142 | LEFT JOIN " . $this->user->getTableName() . " AS a |
||
143 | ON a.username = SUBSTRING_INDEX( s.username , '.', 1 ) |
||
144 | WHERE s.share_id > ? AND s.share_id <= ? AND a.is_locked != 2 |
||
145 | GROUP BY account DESC"); |
||
146 | if ($this->checkStmt($stmt) && $stmt->bind_param("ii", $iMinId, $iMaxId) && $stmt->execute() && $result = $stmt->get_result()) { |
||
147 | $aData = NULL; |
||
148 | while ($row = $result->fetch_assoc()) { |
||
149 | $aData[strtolower($row['account'])] = $row; |
||
150 | } |
||
151 | if (is_array($aData)) return $aData; |
||
152 | } |
||
153 | return $this->sqlError(); |
||
154 | } |
||
155 | |||
156 | /** |
||
157 | * We keep shares only up to a certain point |
||
158 | * This can be configured by the user. |
||
159 | * @return return bool true or false |
||
160 | **/ |
||
161 | public function purgeArchive() { |
||
162 | // Fallbacks if unset |
||
163 | if (!isset($this->config['archive']['purge'])) $this->config['archive']['purge'] = 5; |
||
164 | |||
165 | $stmt = $this->mysqli->prepare("SELECT CEIL(COUNT(id) / 100 * ?) AS count FROM $this->tableArchive"); |
||
166 | View Code Duplication | if ($this->checkStmt($stmt) && $stmt->bind_param('i', $this->config['archive']['purge']) && $stmt->execute() && $result = $stmt->get_result()) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
167 | $limit = $result->fetch_object()->count; |
||
168 | } else { |
||
169 | return $this->sqlError(); |
||
0 ignored issues
–
show
The return type of
return $this->sqlError(); (boolean ) is incompatible with the return type documented by Share::purgeArchive of type Return .
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design. Let’s take a look at an example: class Author {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
abstract class Post {
public function getAuthor() {
return 'Johannes';
}
}
class BlogPost extends Post {
public function getAuthor() {
return new Author('Johannes');
}
}
class ForumPost extends Post { /* ... */ }
function my_function(Post $post) {
echo strtoupper($post->getAuthor());
}
Our function ![]() |
|||
170 | } |
||
171 | $stmt->close(); |
||
172 | $stmt = $this->mysqli->prepare(" |
||
173 | DELETE FROM $this->tableArchive WHERE time < ( |
||
174 | SELECT MIN(time) FROM ( |
||
175 | SELECT MIN(time) AS time |
||
176 | FROM $this->tableArchive |
||
177 | WHERE block_id = ( |
||
178 | SELECT MIN(id) AS minid FROM ( |
||
179 | SELECT id FROM " . $this->block->getTableName() . " ORDER BY height DESC LIMIT ? |
||
0 ignored issues
–
show
The property
block does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
180 | ) AS minheight |
||
181 | ) UNION SELECT DATE_SUB(now(), INTERVAL ? MINUTE) AS time |
||
182 | ) AS mintime |
||
183 | ) LIMIT $limit |
||
184 | "); |
||
185 | if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $this->config['archive']['maxrounds'], $this->config['archive']['maxage']) && $stmt->execute()) |
||
186 | return $stmt->affected_rows; |
||
187 | return $this->sqlError(); |
||
0 ignored issues
–
show
The return type of
return $this->sqlError(); (boolean ) is incompatible with the return type documented by Share::purgeArchive of type Return .
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design. Let’s take a look at an example: class Author {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
abstract class Post {
public function getAuthor() {
return 'Johannes';
}
}
class BlogPost extends Post {
public function getAuthor() {
return new Author('Johannes');
}
}
class ForumPost extends Post { /* ... */ }
function my_function(Post $post) {
echo strtoupper($post->getAuthor());
}
Our function ![]() |
|||
188 | } |
||
189 | |||
190 | /** |
||
191 | * Move accounted shares to archive table, this step is optional |
||
192 | * @param previous_upstream int Previous found share accepted by upstream to limit results |
||
193 | * @param current_upstream int Current upstream accepted share |
||
194 | * @param block_id int Block ID to assign shares to a specific block |
||
195 | * @return bool |
||
196 | **/ |
||
197 | public function moveArchive($current_upstream, $block_id, $previous_upstream=0) { |
||
198 | if ($this->config['payout_system'] != 'pplns') { |
||
199 | // We don't need archived shares that much, so only archive as much as configured |
||
200 | $sql = " |
||
201 | INSERT INTO $this->tableArchive (share_id, username, our_result, upstream_result, block_id, time, difficulty) |
||
202 | SELECT id, username, our_result, upstream_result, ?, time, IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty) AS difficulty |
||
203 | FROM $this->table |
||
204 | WHERE id > ? AND id <= ? |
||
205 | AND time >= DATE_SUB(now(), INTERVAL " . $this->config['archive']['maxage'] . " MINUTE)"; |
||
206 | } else { |
||
207 | // PPLNS needs archived shares for later rounds, so we have to copy them all |
||
208 | $sql = " |
||
209 | INSERT INTO $this->tableArchive (share_id, username, our_result, upstream_result, block_id, time, difficulty) |
||
210 | SELECT id, username, our_result, upstream_result, ?, time, IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty) AS difficulty |
||
211 | FROM $this->table |
||
212 | WHERE id > ? AND id <= ?"; |
||
213 | } |
||
214 | $archive_stmt = $this->mysqli->prepare($sql); |
||
215 | if ($this->checkStmt($archive_stmt) && $archive_stmt->bind_param('iii', $block_id, $previous_upstream, $current_upstream) && $archive_stmt->execute()) |
||
216 | return true; |
||
217 | return $this->sqlError(); |
||
218 | } |
||
219 | |||
220 | /** |
||
221 | * Delete accounted shares from shares table |
||
222 | * @param current_upstream int Current highest upstream ID |
||
223 | * @param previous_upstream int Previous upstream ID |
||
224 | * @return bool true or false |
||
225 | **/ |
||
226 | public function deleteAccountedShares($current_upstream, $previous_upstream=0) { |
||
227 | // Fallbacks if unset |
||
228 | if (!isset($this->config['purge']['shares'])) $this->config['purge']['shares'] = 25000; |
||
229 | if (!isset($this->config['purge']['sleep'])) $this->config['purge']['sleep'] = 1; |
||
230 | |||
231 | $affected = 1; |
||
232 | while ($affected > 0) { |
||
233 | // Sleep first to allow any IO to cleanup |
||
234 | sleep($this->config['purge']['sleep']); |
||
235 | $stmt = $this->mysqli->prepare("DELETE FROM $this->table WHERE id > ? AND id <= ? ORDER BY id LIMIT " . $this->config['purge']['shares']); |
||
236 | $start = microtime(true); |
||
0 ignored issues
–
show
$start is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
237 | View Code Duplication | if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $previous_upstream, $current_upstream) && $stmt->execute()) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
238 | $affected = $stmt->affected_rows; |
||
239 | } else { |
||
240 | return $this->sqlError(); |
||
241 | } |
||
242 | } |
||
243 | return true; |
||
244 | } |
||
245 | |||
246 | /** |
||
247 | * Set/get last found share accepted by upstream: id and accounts |
||
248 | **/ |
||
249 | public function setLastUpstreamId() { |
||
250 | $this->iLastUpstreamId = @$this->oUpstream->id ? $this->oUpstream->id : 0; |
||
251 | } |
||
252 | public function getLastUpstreamId() { |
||
253 | return @$this->iLastUpstreamId ? @$this->iLastUpstreamId : 0; |
||
254 | } |
||
255 | public function getUpstreamFinder() { |
||
256 | return @$this->oUpstream->account; |
||
257 | } |
||
258 | public function getUpstreamWorker() { |
||
259 | return @$this->oUpstream->worker; |
||
260 | } |
||
261 | public function getUpstreamShareId() { |
||
262 | return @$this->oUpstream->id; |
||
263 | } |
||
264 | /** |
||
265 | * Find upstream accepted share that should be valid for a specific block |
||
266 | * Assumptions: |
||
267 | * * Shares are matching blocks in ASC order |
||
268 | * * We can skip all upstream shares of previously found ones used in a block |
||
269 | * @param last int Skips all shares up to last to find new share |
||
270 | * @return bool |
||
271 | **/ |
||
272 | public function findUpstreamShare($aBlock, $last=0) { |
||
273 | // Many use stratum, so we create our stratum check first |
||
274 | $version = pack("I*", sprintf('%08d', $aBlock['version'])); |
||
275 | $previousblockhash = pack("H*", swapEndian($aBlock['previousblockhash'])); |
||
276 | $merkleroot = pack("H*", swapEndian($aBlock['merkleroot']) ); |
||
277 | $time = pack("I*", $aBlock['time']); |
||
278 | $bits = pack("H*", swapEndian($aBlock['bits'])); |
||
279 | $nonce = pack("I*", $aBlock['nonce']); |
||
280 | $header_bin = $version . $previousblockhash . $merkleroot . $time . $bits . $nonce; |
||
281 | $header_hex = implode(unpack("H*", $header_bin)); |
||
0 ignored issues
–
show
$header_hex is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
282 | |||
283 | // Stratum supported blockhash solution entry |
||
284 | $stmt = $this->mysqli->prepare("SELECT SUBSTRING_INDEX( `username` , '.', 1 ) AS account, username as worker, id FROM $this->table WHERE solution = ? LIMIT 1"); |
||
285 | View Code Duplication | if ($this->checkStmt($stmt) && $stmt->bind_param('s', $aBlock['hash']) && $stmt->execute() && $result = $stmt->get_result()) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
286 | $this->oUpstream = $result->fetch_object(); |
||
287 | $this->share_type = 'stratum_blockhash'; |
||
0 ignored issues
–
show
The property
share_type does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
288 | if (!empty($this->oUpstream->account) && !empty($this->oUpstream->worker) && is_int($this->oUpstream->id)) |
||
289 | return true; |
||
290 | } |
||
291 | |||
292 | // Stratum scrypt hash check |
||
293 | $scrypt_hash = swapEndian(bin2hex(Scrypt::calc($header_bin, $header_bin, 1024, 1, 1, 32))); |
||
294 | $stmt = $this->mysqli->prepare("SELECT SUBSTRING_INDEX( `username` , '.', 1 ) AS account, username as worker, id FROM $this->table WHERE solution = ? LIMIT 1"); |
||
295 | View Code Duplication | if ($this->checkStmt($stmt) && $stmt->bind_param('s', $scrypt_hash) && $stmt->execute() && $result = $stmt->get_result()) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
296 | $this->oUpstream = $result->fetch_object(); |
||
297 | $this->share_type = 'stratum_solution'; |
||
298 | if (!empty($this->oUpstream->account) && !empty($this->oUpstream->worker) && is_int($this->oUpstream->id)) |
||
299 | return true; |
||
300 | } |
||
301 | |||
302 | // Failed to fetch via startum solution, try pushpoold |
||
303 | // Fallback to pushpoold solution type |
||
304 | $ppheader = sprintf('%08d', $aBlock['version']) . word_reverse($aBlock['previousblockhash']) . word_reverse($aBlock['merkleroot']) . dechex($aBlock['time']) . $aBlock['bits'] . dechex($aBlock['nonce']); |
||
305 | $stmt = $this->mysqli->prepare("SELECT SUBSTRING_INDEX( `username` , '.', 1 ) AS account, username as worker, id FROM $this->table WHERE solution LIKE CONCAT(?, '%') LIMIT 1"); |
||
306 | View Code Duplication | if ($this->checkStmt($stmt) && $stmt->bind_param('s', $ppheader) && $stmt->execute() && $result = $stmt->get_result()) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
307 | $this->oUpstream = $result->fetch_object(); |
||
308 | $this->share_type = 'pp_solution'; |
||
309 | if (!empty($this->oUpstream->account) && !empty($this->oUpstream->worker) && is_int($this->oUpstream->id)) |
||
310 | return true; |
||
311 | } |
||
312 | |||
313 | // Still no match, try upstream result with timerange |
||
314 | $stmt = $this->mysqli->prepare(" |
||
315 | SELECT |
||
316 | SUBSTRING_INDEX( `username` , '.', 1 ) AS account, username as worker, id |
||
317 | FROM $this->table |
||
318 | WHERE upstream_result = 'Y' |
||
319 | AND id > ? |
||
320 | AND UNIX_TIMESTAMP(time) >= ? |
||
321 | AND UNIX_TIMESTAMP(time) <= ( ? + 60 ) |
||
322 | ORDER BY id ASC LIMIT 1"); |
||
323 | View Code Duplication | if ($this->checkStmt($stmt) && $stmt->bind_param('iii', $last, $aBlock['time'], $aBlock['time']) && $stmt->execute() && $result = $stmt->get_result()) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
324 | $this->oUpstream = $result->fetch_object(); |
||
325 | $this->share_type = 'upstream_share'; |
||
326 | if (!empty($this->oUpstream->account) && !empty($this->oUpstream->worker) && is_int($this->oUpstream->id)) |
||
327 | return true; |
||
328 | } |
||
329 | |||
330 | // We failed again, now we take ANY result matching the timestamp |
||
331 | $stmt = $this->mysqli->prepare(" |
||
332 | SELECT |
||
333 | SUBSTRING_INDEX( `username` , '.', 1 ) AS account, username as worker, id |
||
334 | FROM $this->table |
||
335 | WHERE our_result = 'Y' |
||
336 | AND id > ? |
||
337 | AND UNIX_TIMESTAMP(time) >= ? |
||
338 | ORDER BY id ASC LIMIT 1"); |
||
339 | View Code Duplication | if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $last, $aBlock['time']) && $stmt->execute() && $result = $stmt->get_result()) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
340 | $this->oUpstream = $result->fetch_object(); |
||
341 | $this->share_type = 'any_share'; |
||
342 | if (!empty($this->oUpstream->account) && !empty($this->oUpstream->worker) && is_int($this->oUpstream->id)) |
||
343 | return true; |
||
344 | } |
||
345 | $this->setErrorMessage($this->getErrorMsg('E0052', $aBlock['height'])); |
||
346 | return false; |
||
347 | } |
||
348 | |||
349 | /** |
||
350 | * Fetch the lowest needed share ID from shares |
||
351 | **/ |
||
352 | View Code Duplication | function getMinimumShareId($iCount, $current_upstream) { |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
353 | $stmt = $this->mysqli->prepare(" |
||
354 | SELECT MIN(b.id) AS id FROM |
||
355 | ( |
||
356 | SELECT id, @total := @total + IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty) AS total |
||
357 | FROM $this->table, (SELECT @total := 0) AS a |
||
358 | WHERE our_result = 'Y' |
||
359 | AND id <= ? AND @total < ? |
||
360 | ORDER BY id DESC |
||
361 | ) AS b |
||
362 | WHERE total <= ?"); |
||
363 | if ($this->checkStmt($stmt) && $stmt->bind_param('iii', $current_upstream, $iCount, $iCount) && $stmt->execute() && $result = $stmt->get_result()) |
||
364 | return $result->fetch_object()->id; |
||
365 | return $this->sqlError(); |
||
366 | } |
||
367 | |||
368 | /** |
||
369 | * Fetch the lowest needed share ID from archive |
||
370 | **/ |
||
371 | View Code Duplication | function getMinArchiveShareId($iCount) { |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
372 | $stmt = $this->mysqli->prepare(" |
||
373 | SELECT MIN(b.share_id) AS share_id FROM |
||
374 | ( |
||
375 | SELECT share_id, @total := @total + IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty) AS total |
||
376 | FROM $this->tableArchive, (SELECT @total := 0) AS a |
||
377 | WHERE our_result = 'Y' |
||
378 | AND @total < ? |
||
379 | ORDER BY share_id DESC |
||
380 | ) AS b |
||
381 | WHERE total <= ? |
||
382 | "); |
||
383 | if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $iCount, $iCount) && $stmt->execute() && $result = $stmt->get_result()) |
||
384 | return $result->fetch_object()->share_id; |
||
385 | return $this->sqlError(); |
||
386 | } |
||
387 | } |
||
388 | |||
389 | $share = new Share(); |
||
390 | $share->setDebug($debug); |
||
391 | $share->setMysql($mysqli); |
||
392 | $share->setConfig($config); |
||
393 | $share->setUser($user); |
||
394 | $share->setBlock($block); |
||
395 | $share->setErrorCodes($aErrorCodes); |
||
396 |
When comparing two booleans, it is generally considered safer to use the strict comparison operator.