Skip to content
This repository has been archived by the owner on Nov 22, 2022. It is now read-only.

Commit

Permalink
Use cross-platform JS randomization implementation instead of Linux-s…
Browse files Browse the repository at this point in the history
…pecific C implementation
  • Loading branch information
theoreticalbts committed Sep 21, 2020
1 parent ef9da38 commit e6f3f25
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 57 deletions.
43 changes: 41 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
var Web3 = require('web3');
var Tx = require('ethereumjs-tx').Transaction;
const os = require('os');
const abi = require('./abi.js')
const abi = require('./abi.js');
const crypto = require('crypto');

module.exports = class KoinosMiner {
powHeight = 0;
Expand Down Expand Up @@ -280,6 +281,43 @@ module.exports = class KoinosMiner {
}
}

bufToBigInt(buf) {
let result = 0n;
if( buf.length == 0 )
return result;
let s = BigInt(8*(buf.length - 1));
for( let i=0; i<buf.length; i++ )
{
result |= BigInt(buf[i]) << s;
s -= 8n;
}
return result;
}

getNonceOffset() {
// At most 2^128 - hashLimit
let maxOffset = (1n << 128n) - BigInt(Math.trunc(this.hashLimit));
let maxOffsetStr = maxOffset.toString(16);
maxOffsetStr = "0x" + "0".repeat(64 - maxOffsetStr.length) + maxOffsetStr;

console.log("[JS] maxOffset:", maxOffsetStr);
while( true )
{
// Reroll until we get something less than maxOffset
// Probability of needing a reroll is pretty tiny though
let rdata = crypto.randomBytes(16);
console.log("[JS] rdata:", rdata);
let x = this.bufToBigInt(rdata);
console.log("[JS] x:", x.toString(16));
if( x < maxOffset )
{
let xStr = x.toString(16);
xStr = "0x" + "0".repeat(64 - xStr.length) + xStr;
return xStr;
}
}
}

writeMiningRequest(block) {
var difficultyStr = this.difficulty.toString(16);
difficultyStr = "0x" + "0".repeat(64 - difficultyStr.length) + difficultyStr;
Expand All @@ -295,7 +333,8 @@ module.exports = class KoinosMiner {
this.tip + " " +
this.powHeight + " " +
Math.trunc(this.threadIterations) + " " +
Math.trunc(this.hashLimit) + ";\n");
Math.trunc(this.hashLimit) + " " +
this.getNonceOffset() + ";\n");
}

async updateLatestBlock() {
Expand Down
68 changes: 13 additions & 55 deletions miner/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@
#include <unistd.h>
#endif

#ifdef __linux__
#include <sys/random.h>
#endif

#define WORD_BUFFER_BYTES (2 << 20) // 2 MB
#define WORD_BUFFER_LENGTH (WORD_BUFFER_BYTES / sizeof(struct bn))

Expand Down Expand Up @@ -141,6 +137,7 @@ struct input_data
uint64_t pow_height;
uint64_t thread_iterations;
uint64_t hash_limit;
char nonce_offset[ETH_HASH_SIZE + 1];
};

void read_data( struct input_data* d )
Expand All @@ -165,14 +162,15 @@ void read_data( struct input_data* d )
} while ( strlen(buf) == 0 || buf[strlen(buf)-1] != ';' );

fprintf(stderr, "[C] Buffer: %s\n", buf);
sscanf(buf, "%66s %" SCNu64 " %66s %" SCNu64 " %" SCNu64 " %" SCNu64 " %" SCNu64,
sscanf(buf, "%66s %" SCNu64 " %66s %" SCNu64 " %" SCNu64 " %" SCNu64 " %" SCNu64 " %66s",
d->block_hash,
&d->block_num,
d->difficulty_str,
&d->tip,
&d->pow_height,
&d->thread_iterations,
&d->hash_limit);
&d->hash_limit,
d->nonce_offset);

fprintf(stderr, "[C] Ethereum Block Hash: %s\n", d->block_hash );
fprintf(stderr, "[C] Ethereum Block Number: %" PRIu64 "\n", d->block_num );
Expand All @@ -181,6 +179,7 @@ void read_data( struct input_data* d )
fprintf(stderr, "[C] PoW Height: %" PRIu64 "\n", d->pow_height );
fprintf(stderr, "[C] Thread Iterations: %" PRIu64 "\n", d->thread_iterations );
fprintf(stderr, "[C] Hash Limit: %" PRIu64 "\n", d->hash_limit );
fprintf(stderr, "[C] Nonce Offset: %s\n", d->nonce_offset );
fflush(stderr);
}

Expand Down Expand Up @@ -324,54 +323,6 @@ int words_are_unique( struct bn* secured_struct_hash, struct bn* nonce, struct b
}


void get_max_random_offset( struct bn* max_offset )
{
struct bn one;
struct bn bn_2_64;
struct bn bn_2_128;
bignum_from_int( &one, 1 );
bignum_lshift( &one, &bn_2_64 , 64 );
bignum_lshift( &one, &bn_2_128, 128 );
bignum_sub( &bn_2_128, &bn_2_64, max_offset );
}

void get_random_offset( struct bn* result )
{
#ifdef __linux__
/*
Construct a random offset between 0 and 2^128 - 2^64.
The purpose of this is to reduce possibility of collision when mining to the same addresses using multiple machines.
*/
struct bn max_offset;
const size_t buflen = 128/8;
bignum_from_int( result, 0 );

get_max_random_offset( &max_offset );
while(1)
{
ssize_t num_bytes = getrandom( result, buflen, 0 );
if( num_bytes != buflen )
{
/* Bail if random bytes weren't available */
fprintf(stderr, "[C] getrandom() returned %d, expected %d\n", (int)num_bytes, (int)buflen );
return;
}

/* Reject if we get within 2^64 of the end */
if( bignum_cmp( result, &max_offset ) >= 0 )
{
fprintf(stderr, "[C] Generated offset greater than max_offset, retrying\n");
continue;
}

break;
}
#else
bignum_from_int( result, 0 );
#endif
}


int main( int argc, char** argv )
{
struct bn* word_buffer = malloc( WORD_BUFFER_BYTES );
Expand Down Expand Up @@ -493,7 +444,14 @@ int main( int argc, char** argv )
bignum_endian_swap( &nonce );

struct bn nonce_offset;
get_random_offset( &nonce_offset );
if( is_hex_prefixed( input.nonce_offset ) )
{
bignum_from_string( &nonce_offset, input.nonce_offset + 2, ETH_HASH_SIZE - 2 );
}
else
{
bignum_from_string( &nonce_offset, input.nonce_offset, ETH_HASH_SIZE - 2 );
}
bignum_add( &nonce, &nonce_offset, &nonce );

bignum_to_string( &nonce, bn_str, sizeof(bn_str), true );
Expand Down

0 comments on commit e6f3f25

Please sign in to comment.