Blockchain – How to Calculate Block/Share Difficulty Using EthereumJS

blockchaindifficultyethereumjsshares

Introduction

I am trying to obtain the share difficulty sent from my mining rig to the pool; I have captured the following stratum data:

Work from pool sent to miner:

{"id":0,"jsonrpc":"2.0","result":["0xbafb9b219bb51e0b47abf28e6044322a0f181926496528bbf137eef718a6623b","0x78255e703ddc0c08a70aba14dafca75ff40401240c1622d2f80b398919451e14","0x7e00000007e00000007e00000007e00000007e00000007e00000007e","0xe65d91"]}

Miner with share solution, sent to pool:

{"id":24140800,"method":"eth_submitWork","params":["0x605f42c3367bd64a","0xbafb9b219bb51e0b47abf28e6044322a0f181926496528bbf137eef718a6623b","0x6d8320a2471edc0ef2c8a41fa1d6d9e5e50fbeff8771ed1e58960765b0e7131f"],"worker":"rig"}

My mining software [T-Rex miner] has reported that this share difficulty was 18.33 G, not enough for an actual block solution, but valid as a share for the pool.

My approach

After many hours of reading and investigating, I know that to calculate the share diff (18.33 G) what I need is the blockhash and nonce and then Ethash(nonce + blockhash) it, but I am failing to obtain the correct share value.
This is what I have come up to using Node.js and ethereumjs

const Ethash = require('@ethereumjs/ethash').default;
const { MemoryLevel } = require('memory-level');

const cacheDB = new MemoryLevel();
const ethash = new Ethash(cacheDB);

var seed = '0x78255e703ddc0c08a70aba14dafca75ff40401240c1622d2f80b398919451e14';
var blockheader = '0xbafb9b219bb51e0b47abf28e6044322a0f181926496528bbf137eef718a6623b';
var nonce = '0x605f42c3367bd64a';

var seedBuffer = Buffer.from(seed, 'hex');
var nonceBuffer = Buffer.from(nonce, 'hex');
var blockheaderBuffer = Buffer.from(blockheader, 'hex');

ethash.mkcache(1024, seedBuffer);
var result = ethash.run(blockheaderBuffer, nonceBuffer, 1024 * 32);

var dHexHash = '0x' + result.hash.toString('hex');
console.log(dHexHash / 1000000 + ' M');
var dHexMix = '0x' + result.mix.toString('hex');
console.log(dHexMix);

The problem(s)

• Firstly, ethash.run(val, nonce, fullSize?) as stated here returns a hash and a mix, I do not know which one I should use to compute the difficulty, so I used the two – neverless none of the two gave me a correct value.

The third argument – fullSize – I also don't know what corresponds to, I used 503 since that is the epoch when the share was computed, but I might be wrong – also changing this to another random number, the hashes change completely so it has to be a very correct value.

• Secondly and last, mkcache(cacheSize, seed) needs a – cacheSize – that I also don't know to what corresponds to, asumed to be epoch when share was computed, it may be wrong too.

Thanks for your help!

Best Answer

After 2 days of reading and investigating, I made the code work. The main issue is that there is no clear documentation on how to use ethereumjs

ethash.run(val, nonce, fullSize?)
mkcache(cacheSize, seed)

fullSize corresponds to get_cachesize and cacheSize corresponds to get_datasize, references for both are here.

This is my final working test code:

import { get_datasize, get_cachesize } from './dag.js';
import Ethash from '@ethereumjs/ethash';
import { MemoryLevel } from 'memory-level';

const ethash = new Ethash.default(new MemoryLevel());

const block_number = 0xe68326
const nonce = '922349db156ce3e0'
const header = 'dc4db678c8a6bf1b521320ed0b03c77d5d460b3eca5730b6d8f058647dccb158'
const seed = '78255e703ddc0c08a70aba14dafca75ff40401240c1622d2f80b398919451e14'
const mix_digest = '0x045f0cb0561619fecfe21893a17ebe409fee608211630a09ce085ff899910570'

var seedBuffer = Buffer.from(seed, 'hex');
var nonceBuffer = Buffer.from(nonce, 'hex');
var headerBuffer =  Buffer.from(header, 'hex');

var cache = ethash.mkcache(get_cachesize(block_number), seedBuffer);
var result = ethash.run(headerBuffer, nonceBuffer, get_datasize(block_number));

var hash = '0x' + result.hash.toString('hex');
var mix = '0x' + result.mix.toString('hex');

console.log(diff2(hash));
console.log(mix);

if(mix == mix_digest)
    console.log('Valid PoW');
else
    console.log('Invalid PoW, try again');

function diff2(d) {
    return Math.ceil((Math.pow(2, 256) / parseInt(d, 16)));
}

// prints 'Valid PoW'
Related Topic