2

Bitcoin pools need to check data returned with getwork for validity (proper hashing result, etc.). Bitcoind that issues the initial getworks is also able to perform some data checking, but it might not be enough for pools (for example, it might not validate difficulty 1 shares used for crediting miners).

What getwork data checking is usually done on the bitcoind side, and which on the pool side? This would include:

  • Checking message validity
  • Checking if submitted work originated from the pool (whether block data was tempered with)
  • Checking what difficulty the work solves (for generating shares and solving blocks)
  • Check if work is acceptable as a block (for example, if timestamp is not too big)

3 Answers 3

3

The GetWork request includes only the block header, containing exactly the fields shown here and no others. This is all the miner ever sees. Notice that the transactions are not in the block header -- just their (Merkle) hash. The miner doesn't actually know what transactions it is mining.

The pool checks that the block header of the submitted work exactly matches the header of some GetWork previously issued by the pool. Some pools (Eligius) give the miner permission to alter the timestamp field only, and only according to very strict rules.

The pool always checks that the block's hash ends with 32 zeroes (note that this is "below" difficulty zero! Every block in the chain has more than 32 trailing zeroes in its hash).

Some pools check other things (for example, that you didn't request work using one account and submit it using a different one), but the checks above are the only ones that are both mandatory and universal.

1

When miners submit a proof of work to a pool, you will first want to check that the proof of work is valid. The proof of work consists only of a bitcoin block header. You need to check that each part is valid. You can see the layout of a bitcoin block header at https://en.bitcoin.it/wiki/Block_hashing_algorithm.

  • the version should be the same that bitcoind gave you earlier when you created this work
  • the parent (previous) hash should be the hash of the block you are trying to build upon (you get this also from bitcoind when you create work)
  • the merkleroot should be the merkleroot for one of the merkle trees you have built (if you build the block data yourself), or a merkleroot you got from bitcoind (if you let bitcoind construct the blocks)
  • the timestamp should be one you sent to the worker earlier (that you got from bitcoind), OR if you allow rollntime, it should be within the limits you accept
  • nbits should be correct for the current difficulty (you get this too from bitcoind)

In short, the data miners send in should be the same work you sent them except for modifying the nonce. Additionally the timestamp can be modified if the server supports rollntime. You can read about rollntime and other getwork extensions here: https://en.bitcoin.it/wiki/Getwork.

If it looks valid so far, hash the block.

  • If the hash meets pool difficulty, credit the miner for the work
  • If the hash meets bitcoin network difficulty, attempt to create a new bitcoin block

Note: If you get merkleroots you have never seen before from miners, it's probably from a different pool. There are some broken proxies and other software that grab work from one pool and send the result to a different pool.

1

Pools must also check for duplicates in submitted work.

A miner could submit a valid result more than once, even with some other user credentials. Thus, a pool will likely want to maintain a global (not per-user) history of received work, and check every submitted item against it. Ideally, that history would be flushed when the block changes, not before.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.