2 error_reporting(E_ALL | E_STRICT);
5 require 'lib/functions.php';
6 require 'lib/scrypt.php';
8 define('START_TIME' , microtime(true));
9 define('CHECK_POINT' , 'chash.pos');
11 // Hashes needed to complete a "block"
12 $GLOBALS['block_size'] = 100;
13 $GLOBALS['none_increment'] = (1 / pow(10, 20));
15 // Automatic saving interval in seconds
16 $GLOBALS['flush_file_time'] = 30;
19 * How long (in seconds) to try to find a proper hash until the best root hash
22 $GLOBALS['restart_search_time'] = 1800;
25 $GLOBALS['hash_cycles'] = 2;
28 $GLOBALS['total_restarts'] = 0;
30 // Initial salt (may be overwritten by loading checkpoint file)
31 $GLOBALS['salt'] = Scrypt::generateSalt();
33 // Starting difficulty
34 $GLOBALS['difficulty'] = 2;
37 $GLOBALS['found_hashes'] = array(0 => array());
42 * @author Roland Haeder <roland@mxchange.org>
43 * @copyright Copyright (c) 2013 by Core Developer Team
44 * @license See LICENSE (public-domain)
47 // Is the check point there?
48 if (is_readable(CHECK_POINT)) {
52 // Create nonce (very small)
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.
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'),
69 multipleHashString('September 11 is a big lie.'),
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.'),
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]),
89 // Calulcate final "genesis" hash
90 $genesisHash = hashString(
97 // Get all elements to get the last part out
98 $elements = explode('$', $genesisHash);
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]);
106 print ('hashes=' . print_r($gensisHashes, true));
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);
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);
123 // Init hash-per-block counter and hashrate
124 $GLOBALS['hashes_block'] = 0;
127 // Wait for block_size iterations (= found hashes). This is one block
128 $timeBlock = microtime(true);
129 $timeDisplay = $timeBlock;
130 $GLOBALS['time_flush'] = $timeBlock;
132 // Time waited for a good block again (no iteration)
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']);
140 $sumNonce = calculateSumFromHash($nonceHash);
143 $GLOBALS['iteration'] = 0;
144 $GLOBALS['iteration_second'] = 0;
146 // Now start the "mining" ...
147 $timeHash = microtime(true);
148 while ($sumNonce < $GLOBALS['sum_genesis']) {
149 // Calculate new nonce
153 $nonceHash = multipleHashString($GLOBALS['nonce'] . $GLOBALS['current_hash']);
156 $sumNonce = calculateSumFromHash($nonceHash);
158 // Time spend in loop
159 $testTime = abs(microtime(true) - $timeDisplay);
161 // Calculate hashrate/sec
162 $hashRate = 1 / $testTime * $GLOBALS['iteration_second'] * $GLOBALS['hash_cycles'];
165 if ($testTime >= 1) {
167 print ('hashrate=' . round($hashRate) . ' hashes/sec,iterSecond=' . $GLOBALS['iteration_second'] . ' iterations/sec,difficulty=' . $GLOBALS['difficulty'] . PHP_EOL);
170 $timeDisplay = microtime(true);
171 $GLOBALS['iteration_second'] = 0;
174 // Time spend from last flush
175 $testTime = abs(microtime(true) - $GLOBALS['time_flush']);
177 // Only once per 10 seconds
178 if ($testTime >= $GLOBALS['flush_file_time']) {
179 // Flush check-point file
180 flushCheckPointFile($GLOBALS['current_hash']);
183 // Time spend from last found block
184 $testTime = abs(microtime(true) - $GLOBALS['found_time']);
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));
193 print('total_restarts=' . $GLOBALS['total_restarts'] . ' - Restarting ...');
195 // Count all root (genesis) hashes
196 $rootHashes = array();
197 foreach ($GLOBALS['found_hashes'] as $block) {
198 // "Walk" through all blocks
199 foreach ($block as $hash) {
200 if (!isset($hash['root_hash'])) {
202 die('INCONSISTENCY: hash=' . print_r($hash, true));
205 if (isset($rootHashes[$hash['root_hash']])) {
207 $rootHashes[$hash['root_hash']]++;
210 $rootHashes[$hash['root_hash']] = 1;
215 // Find best root hash
218 foreach ($rootHashes as $hash => $count) {
220 //* NOISY-DEBUG: */ print ('hash=' . $hash . ',count=' . $count . ',bestRootHash=' . $bestRootHash . ',bestRootCount=' . $bestRootCount . PHP_EOL);
222 // Is a better one found?
223 if ($count > $bestRootCount) {
225 $bestRootHash = $hash;
226 $bestRootCount = $count;
231 print ('bestRootHash=' . $bestRootHash . ',bestRootCount=' . $bestRootCount . PHP_EOL);
233 // Search for latest best root hash
234 foreach ($GLOBALS['found_hashes'] as $block) {
235 // "Walk" through whole block and search for first appearance of best root hash
236 foreach ($block as $idx => $hash) {
237 // Is the root hash there?
238 if ($hash['root_hash'] == $bestRootHash) {
239 // Set found modula hash as new root and current modula hash
240 $GLOBALS['root_hash'] = $hash['nonce_hash'];
241 setModulaHash($hash['nonce_hash']);
242 print ('idx=' . $idx . ',modulaHash=' . $GLOBALS['root_hash'] . ' - Is now new root hash!' . PHP_EOL);
244 // Reset "found time" (when a hash was found)
245 $GLOBALS['found_time'] = microtime(true);
247 // Re-initialize nonce
258 $GLOBALS['iteration']++;
259 $GLOBALS['iteration_second']++;
260 //print ('nonce=' . $GLOBALS['nonce'] . ',iteration=' . $GLOBALS['iteration'] . PHP_EOL);
261 //print ('nonceHash=' . $nonceHash . PHP_EOL);
262 //print ('sumNonce=' . $sumNonce . PHP_EOL);
263 //print ('sumGenesis=' . $GLOBALS['sum_genesis'] . PHP_EOL);
266 // If the iteration is zero, then no hash is found
267 if ($GLOBALS['iteration'] == 0) {
269 $timeBadHashes += abs(microtime(true) - $timeHash);
272 print('BAD:nonce=' . $GLOBALS['nonce'] . PHP_EOL);
274 // Nothing found, so calculate new nonce
279 // Add amount of hashes per block (multiple-hash)
280 $GLOBALS['hashes_block'] += $GLOBALS['iteration'] * $GLOBALS['hash_cycles'] + $GLOBALS['hash_cycles'];
283 addFoundHash($nonceHash);
286 // Time taken for one
287 $timeBlock = abs(microtime(true) - $timeBlock);
290 $reward = abs($timeBlock - $timeBadHashes) / $hashRate * $GLOBALS['hashes_block'] / $GLOBALS['block_size'] * 1000;
291 print('timeBlock=' . $timeBlock . ',timeBadHashes=' . $timeBadHashes . ',hashesPerBlock=' . $GLOBALS['hashes_block'] .',reward=' . $reward . PHP_EOL);
294 $GLOBALS['difficulty'] = $GLOBALS['difficulty'] * 2;
297 $GLOBALS['total_hashes'] += $GLOBALS['hashes_block'];
298 $GLOBALS['total_blocks']++;
299 $GLOBALS['hashes_block'] = 0;
302 $GLOBALS['found_hashes'][$GLOBALS['total_blocks']] = array();
304 // Calculate new nonce
307 // Add reward to total
308 $GLOBALS['total_reward'] += $reward;
310 // Calculate average block value
311 $blockValue = $GLOBALS['total_reward'] / $GLOBALS['total_blocks'] * $GLOBALS['total_hashes'] / ($GLOBALS['block_size'] * $GLOBALS['total_blocks']);
313 // Calculate reward per hour (= 3600 seconds)
314 $rewardPerHour = $GLOBALS['total_reward'] / abs(microtime(true) - START_TIME) * 3600;
316 print ('totalReward=' . $GLOBALS['total_reward'] . ',blockValue=' . $blockValue . ',rewardPerHour=' . $rewardPerHour . PHP_EOL);