Search code examples
ethereumshareblock

Calculate block/share difficulty


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!


Solution

  • 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'