Continued:
[core.git] / contrib / chash / chash.php
1 <?php
2 error_reporting(E_ALL | E_STRICT);
3
4 // Load scrypt
5 require 'lib/functions.php';
6 require 'lib/scrypt.php';
7
8 define('START_TIME'            , microtime(true));
9 define('CHECKPOINT_FILE'           , 'chash.pos');
10
11 // Hashes needed to complete a "block"
12 $GLOBALS['block_size']          = 100;
13 $GLOBALS['none_increment']      = (1 / pow(10, 20));
14
15 // Automatic saving interval in seconds
16 $GLOBALS['flush_file_time']     = 30;
17
18 /*
19  * How long (in seconds) to try to find a proper hash until the best root hash
20  * is taken.
21  */
22 $GLOBALS['restart_search_time'] = 1800;
23
24 // Hashes per call
25 $GLOBALS['hash_cycles'] = 2;
26
27 // Total restarts
28 $GLOBALS['total_restarts'] = 0;
29
30 // Initial salt (may be overwritten by loading checkpoint file)
31 $GLOBALS['salt'] = Scrypt::generateSalt();
32
33 // Starting difficulty
34 $GLOBALS['difficulty'] = 2;
35
36 // Found hashes
37 $GLOBALS['found_hashes'] = array([]);
38
39 /**
40  * Continued-hashing
41  *
42  * @author              Roland Haeder <roland@mxchange.org>
43  * @copyright   Copyright (c) 2013 by Core Developer Team
44  * @license             See LICENSE (public-domain)
45  */
46
47 // Is the check point there?
48 if (is_readable(CHECKPOINT_FILE)) {
49         // Load it
50         loadCheckpointFile();
51 } else {
52         // Create nonce (very small)
53         initNonce();
54 }
55
56 /*
57  * Calculate "genesis" hashes, please note that these "genesis strings" are now
58  * known to the public as you can read them here in source code and therefore I
59  * will not use them for the real genesis hashes.
60  */
61 $gensisHashes = array(
62         // A famous quote from Deus Ex 2 - Invisible War
63         multiplehashString('"Informations must be free." - AI Helios from Deus Ex'),
64         // My name + URL of my GNUSocial instance
65         multipleHashString('Roland Haeder, https://social.mxchange.org'),
66         // A famous quote from Linus Torwalds
67         multipleHashString('"Software is like sex. Its better when its free." - Linus Torwalds'),
68         // Well ...
69         multipleHashString('September 11 is a big lie.'),
70
71         // GNU is not Uni*
72         multipleHashString('GNU is Not Uni*.'),
73         // WINE is not an emulator
74         multipleHashString('WINE Is Not an Emulator.'),
75         // FlightGear - Fly free!
76         multipleHashString('FlightGear - Fly free!'),
77         // Quote from Linus Torwalds
78         multipleHashString('Your code is shit. Your argument is shit.'),
79 );
80
81 // Calculate first "block"
82 $genesisBlock = array(
83         hashString($gensisHashes[0] . $gensisHashes[3]),
84         hashString($gensisHashes[1] . $gensisHashes[2]),
85         hashString($gensisHashes[4] . $gensisHashes[7]),
86         hashString($gensisHashes[5] . $gensisHashes[6]),
87 );
88
89 // Calulcate final "genesis" hash
90 $genesisHash = hashString(
91         $genesisBlock[3] .
92         $genesisBlock[0] .
93         $genesisBlock[2] .
94         $genesisBlock[1]
95 );
96
97 // Get all elements to get the last part out
98 $elements = explode('$', $genesisHash);
99
100 // This is also the "genesis" hash and first root hash
101 $GLOBALS['current_hash'] = $genesisHash;
102 $GLOBALS['root_hash']    = $genesisHash;
103 $GLOBALS['sum_genesis']  = sumHash($elements[4]);
104
105 // Output results
106 print ('hashes=' . print_r($gensisHashes, true));
107
108 // Total reward + hashes
109 $GLOBALS['total_reward']   = 0;
110 $GLOBALS['total_hashes']   = 0;
111 $GLOBALS['total_found']    = 0;
112 $GLOBALS['total_blocks']   = 0;
113 $GLOBALS['found_time']     = microtime(true);
114
115 // Output again
116 print ('nonce=' . $GLOBALS['nonce'] . PHP_EOL);
117 print ('found=' . count($GLOBALS['found_hashes'][$GLOBALS['total_blocks']]) . PHP_EOL);
118 print ('salt=' . $GLOBALS['salt'] . PHP_EOL);
119 print ('difficulty=' . $GLOBALS['difficulty'] . PHP_EOL);
120
121 // Start "mining"
122 while (true) {
123         // Init hash-per-block counter and hashrate
124         $GLOBALS['hashes_block'] = 0;
125         $hashRate = 1;
126
127         // Wait for block_size iterations (= found hashes). This is one block
128         $timeBlock   = microtime(true);
129         $timeDisplay = $timeBlock;
130         $GLOBALS['time_flush'] = $timeBlock;
131
132         // Time waited for a good block again (no iteration)
133         $timeBadHashes = 0;
134
135         while (count($GLOBALS['found_hashes'][$GLOBALS['total_blocks']]) <= $GLOBALS['block_size']) {
136                 // Create hash from modulaHash ("genesis hash") and nonce
137                 $nonceHash = multipleHashString($GLOBALS['nonce'] . $GLOBALS['current_hash']);
138
139                 // Calculate sums
140                 $sumNonce  = calculateSumFromHash($nonceHash);
141
142                 // Init counter
143                 $GLOBALS['iteration'] = 0;
144                 $GLOBALS['iteration_second'] = 0;
145
146                 // Now start the "mining" ...
147                 $timeHash = microtime(true);
148                 while ($sumNonce < $GLOBALS['sum_genesis']) {
149                         // Calculate new nonce
150                         calculateNonce();
151
152                         // And hash again
153                         $nonceHash = multipleHashString($GLOBALS['nonce'] . $GLOBALS['current_hash']);
154
155                         // Calculate sums
156                         $sumNonce  = calculateSumFromHash($nonceHash);
157
158                         // Time spend in loop
159                         $testTime = abs(microtime(true) - $timeDisplay);
160
161                         // Calculate hashrate/sec
162                         $hashRate = 1 / $testTime * $GLOBALS['iteration_second'] * $GLOBALS['hash_cycles'];
163
164                         // Only every second
165                         if ($testTime >= 1) {
166                                 // Display hash rate
167                                 print ('hashrate=' . round($hashRate) . ' hashes/sec,iterSecond=' . $GLOBALS['iteration_second'] . ' iterations/sec,difficulty=' . $GLOBALS['difficulty'] . PHP_EOL);
168
169                                 // Reset timer
170                                 $timeDisplay = microtime(true);
171                                 $GLOBALS['iteration_second']  = 0;
172                         }
173
174                         // Time spend from last flush
175                         $testTime = abs(microtime(true) - $GLOBALS['time_flush']);
176
177                         // Only once per 10 seconds
178                         if ($testTime >= $GLOBALS['flush_file_time']) {
179                                 // Flush check-point file
180                                 flushCheckPointFile($GLOBALS['current_hash']);
181                         }
182
183                         // Time spend from last found block
184                         $testTime = abs(microtime(true) - $GLOBALS['found_time']);
185
186                         // Is the last found time to far away?
187                         if ($testTime >= $GLOBALS['restart_search_time']) {
188                                 // Count up restart and reduce difficulty, but never below 2
189                                 $GLOBALS['total_restarts']++;
190                                 $GLOBALS['difficulty'] = max(2, ($GLOBALS['difficulty'] / 2));
191
192                                 // Output message
193                                 print('total_restarts=' . $GLOBALS['total_restarts'] . ' - Restarting ...');
194
195                                 // Count all root (genesis) hashes
196                                 $rootHashes = [];
197                                 foreach ($GLOBALS['found_hashes'] as $block) {
198                                         // "Walk" through all blocks
199                                         foreach ($block as $hash) {
200                                                 if (!isset($hash['root_hash'])) {
201                                                         // Bad file
202                                                         die('INCONSISTENCY: hash=' . print_r($hash, true));
203                                                 }
204
205                                                 if (isset($rootHashes[$hash['root_hash']])) {
206                                                         // Count up
207                                                         $rootHashes[$hash['root_hash']]++;
208                                                 } else {
209                                                         // First entry found
210                                                         $rootHashes[$hash['root_hash']] = 1;
211                                                 }
212                                         }
213                                 }
214
215                                 // Find best root hash
216                                 $bestRootHash = '';
217                                 $bestRootCount = 0;
218                                 foreach ($rootHashes as $hash => $count) {
219                                         // Is a better one found?
220                                         //* NOISY-DEBUG: */ print ('hash=' . $hash . ',count=' . $count . ',bestRootHash=' . $bestRootHash . ',bestRootCount=' . $bestRootCount . PHP_EOL);
221                                         if ($count > $bestRootCount) {
222                                                 // Remember it
223                                                 $bestRootHash  = $hash;
224                                                 $bestRootCount = $count;
225                                         }
226                                 }
227
228                                 // Output message
229                                 print ('bestRootHash=' . $bestRootHash . ',bestRootCount=' . $bestRootCount . PHP_EOL);
230
231                                 // Search for latest best root hash
232                                 foreach ($GLOBALS['found_hashes'] as $block) {
233                                         // "Walk" through whole block and search for first appearance of best root hash
234                                         foreach ($block as $idx => $hash) {
235                                                 // Is the root hash there?
236                                                 if ($hash['root_hash'] == $bestRootHash) {
237                                                         // Set found modula hash as new root and current modula hash
238                                                         $GLOBALS['root_hash']   = $hash['nonce_hash'];
239                                                         setModulaHash($hash['nonce_hash']);
240                                                         print ('idx=' . $idx . ',modulaHash=' . $GLOBALS['root_hash'] . ' - Is now new root hash!' . PHP_EOL);
241
242                                                         // Reset "found time" (when a hash was found)
243                                                         $GLOBALS['found_time'] = microtime(true);
244
245                                                         // Re-initialize nonce
246                                                         initNonce();
247
248                                                         // Abort search
249                                                         break;
250                                                 }
251                                         }
252                                 }
253                         }
254
255                         // Next round
256                         $GLOBALS['iteration']++;
257                         $GLOBALS['iteration_second']++;
258                         //* NOISY-DEBUG: */ print('nonce=' . $GLOBALS['nonce'] . ',iteration=' . $GLOBALS['iteration'] . PHP_EOL);
259                         //* NOISY-DEBUG: */ print('nonceHash=' . $nonceHash . PHP_EOL);
260                         //* NOISY-DEBUG: */ print('sumNonce=' . $sumNonce . PHP_EOL);
261                         //* NOISY-DEBUG: */ print('sumGenesis=' . $GLOBALS['sum_genesis'] . PHP_EOL);
262                 }
263
264                 // If the iteration is zero, then no hash is found
265                 if ($GLOBALS['iteration'] == 0) {
266                         // Bad hash found
267                         $timeBadHashes += abs(microtime(true) - $timeHash);
268
269                         // Nothing found, so calculate new nonce
270                         //* NOISY-DEBUG: */ print('BAD:nonce=' . $GLOBALS['nonce'] . PHP_EOL);
271                         calculateNonce();
272                         continue;
273                 }
274
275                 // Add amount of hashes per block (multiple-hash)
276                 $GLOBALS['hashes_block'] += $GLOBALS['iteration'] * $GLOBALS['hash_cycles'] + $GLOBALS['hash_cycles'];
277
278                 // Push found hash
279                 addFoundHash($nonceHash);
280         }
281
282         // Flush check-point file
283         flushCheckPointFile($GLOBALS['current_hash']);
284
285         // Time taken for one
286         $timeBlock = abs(microtime(true) - $timeBlock);
287
288         // Calculate reward
289         $reward = abs($timeBlock - $timeBadHashes) / max(1, $hashRate) * $GLOBALS['hashes_block'] / max(1, $GLOBALS['block_size']) * 1000;
290         print('timeBlock=' . $timeBlock . ',timeBadHashes=' . $timeBadHashes . ',hashesPerBlock=' . $GLOBALS['hashes_block'] .',reward=' . $reward . PHP_EOL);
291
292         // Increase difficulty
293         $GLOBALS['difficulty'] = $GLOBALS['difficulty']++;
294
295         // Block completed
296         $GLOBALS['total_hashes'] += $GLOBALS['hashes_block'];
297         $GLOBALS['total_blocks']++;
298         $GLOBALS['hashes_block'] = 0;
299
300         // Init next block
301         $GLOBALS['found_hashes'][$GLOBALS['total_blocks']] = [];
302
303         // Calculate new nonce
304         calculateNonce();
305
306         // Add reward to total
307         $GLOBALS['total_reward'] += $reward;
308
309         // Calculate average block value
310         $blockValue = $GLOBALS['total_reward'] / $GLOBALS['total_blocks'] * $GLOBALS['total_hashes'] / ($GLOBALS['block_size'] * $GLOBALS['total_blocks']);
311
312         // Calculate reward per hour (= 3600 seconds)
313         $rewardPerHour = $GLOBALS['total_reward'] / abs(microtime(true) - START_TIME) * 3600;
314
315         print ('totalReward=' . $GLOBALS['total_reward'] . ',blockValue=' . $blockValue . ',rewardPerHour=' . $rewardPerHour . PHP_EOL);
316 }