Can anyone see what the issue is? When the pool tries to submit a block, this happens:
2014-03-23 10:56:13,518 DEBUG mining # badman74.1 (528, 31, False, False, 1395586095) 5.87% work_id(1b17) job_id(a52) diff(1.000000)
2014-03-23 10:56:13,519 DEBUG interfaces # d9282a8334a2285b58ebd76a72d2c738fec2bf70e3fe6ec6afbc89a65f6b15d7 (2) valid badman74.1
2014-03-23 10:56:13,539 DEBUG DBInterface # run_import_thread current size: 1
2014-03-23 10:56:13,545 DEBUG DBInterface # run_import_thread current size: 1
2014-03-23 10:56:13,625 DEBUG mining # badman74.1 (529, 31, False, False, 1395586095) 5.86% work_id(1b17) job_id(a52) diff(1.000000)
2014-03-23 10:56:13,626 INFO template_registry # Yay, share with diff above 100000
2014-03-23 10:56:13,626 INFO template_registry # We found a block candidate! 000000000000002000000000000000200000000002de4ba000007fa6806477c8
2014-03-23 10:56:13,626 ERROR template_registry # FINAL JOB VALIDATION FAILED!(Try enabling/disabling tx messages)
None
2014-03-23 10:56:13,627 DEBUG bitcoin_rpc # Submitting Block with submitblock: attempt #1
2014-03-23 10:56:13,627 DEBUG bitcoin_rpc # ['700000003807193b8b4a75824a9b87c9b5d956091dbe9ff461f6d58f2ed13702000000001c88c56 21bd9608fdb9bb9b27bc20aff7a1e043e9d5b932b280125f6137a71c10bf62e531ea9071cc53726 000101000000010000000000000000000000000000000000000000000000000000000000000000f fffffff2602db04062f503253482f040cf62e5308f800000ae30000000d2f7374726174756d506f 6f6c2f00000000010000c2eb0b0000001976a91421df89453a23acd63c166d78252f41389a45a1c 388ac00000000']
2014-03-23 10:56:13,628 DEBUG interfaces # 6a05c80637648a7ebc42a623b13ad4f5fa5ccf9abf1c5b98caf050f6b2b9dc61 (8795958804479) valid badman74.1
2014-03-23 10:56:13,633 DEBUG bitcoin_rpc # SUBMITBLOCK RESULT: {"result":"rejected","error":null,"id":"1"}
2014-03-23 10:56:13,633 INFO interfaces # Block 6a05c80637648a7ebc42a623b13ad4f5fa5ccf9abf1c5b98caf050f6b2b9dc61 REJECTED
Dev: can you look at the code my pool uses for submitting blocks and see what is wrong with it?
Preparing the share:
def submit_share(self, job_id, worker_name, session, extranonce1_bin, extranonce2, ntime, nonce,
difficulty, ip=False):
'''Check parameters and finalize block template. If it leads
to valid block candidate, asynchronously submits the block
back to the bitcoin network.
- extranonce1_bin is binary. No checks performed, it should be from session data
- job_id, extranonce2, ntime, nonce - in hex form sent by the client
- difficulty - decimal number from session
- submitblock_callback - reference to method which receive result of submitblock()
- difficulty is checked to see if its lower than the vardiff minimum target or pool target
from conf/config.py and if it is the share is rejected due to it not meeting the requirements for a share
'''
# Share Diff Should never be 0
if difficulty < settings.POOL_TARGET:
log.exception("Worker %s @ IP: %s seems to be submitting Fake Shares"%(worker_name,ip))
raise SubmitException("Diff is %s Share Rejected Reporting to Admin"%(difficulty))
# Check if extranonce2 looks correctly. extranonce2 is in hex form...
if len(extranonce2) != self.extranonce2_size * 2:
raise SubmitException("Incorrect size of extranonce2. Expected %d chars" % (self.extranonce2_size*2))
# Check for job
job = self.get_job(job_id, worker_name, ip)
if job == None:
raise SubmitException("Job '%s' not found" % job_id)
# Check if ntime looks correct
if len(ntime) != 8:
raise SubmitException("Incorrect size of ntime. Expected 8 chars")
if not job.check_ntime(int(ntime, 16)):
raise SubmitException("Ntime out of range")
# Check nonce
if len(nonce) != 8:
raise SubmitException("Incorrect size of nonce. Expected 8 chars")
# Check for duplicated submit
if not job.register_submit(extranonce1_bin, extranonce2, ntime, nonce):
log.info("Duplicate from %s, (%s %s %s %s)" % \
(worker_name, binascii.hexlify(extranonce1_bin), extranonce2, ntime, nonce))
raise SubmitException("Duplicate share")
# Now let's do the hard work!
# ---------------------------
# 0. Some sugar
extranonce2_bin = binascii.unhexlify(extranonce2)
ntime_bin = binascii.unhexlify(ntime)
nonce_bin = binascii.unhexlify(nonce)
# 1. Build coinbase
coinbase_bin = job.serialize_coinbase(extranonce1_bin, extranonce2_bin)
coinbase_hash = util.doublesha(coinbase_bin)
# 2. Calculate merkle root
merkle_root_bin = job.merkletree.withFirst(coinbase_hash)
merkle_root_int = util.uint256_from_str(merkle_root_bin)
# 3. Serialize header with given merkle, ntime and nonce
header_bin = job.serialize_header(merkle_root_int, ntime_bin, nonce_bin)
# 4. Reverse header and compare it with target of the user
if settings.COINDAEMON_ALGO == 'scrypt':
hash_bin = ltc_scrypt.getPoWHash(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]))
elif settings.COINDAEMON_ALGO == 'scrypt-jane':
if settings.SCRYPTJANE_NAME == 'vtc_scrypt':
hash_bin = scryptjane.getPoWHash(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]))
else:
hash_bin = scryptjane.getPoWHash(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]), int(ntime, 16))
elif settings.COINDAEMON_ALGO == 'quark':
hash_bin = quark_hash.getPoWHash(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]))
elif settings.COINDAEMON_ALGO == 'skein_hash':
hash_bin = skein_hash.getPoWHash(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]))
elif settings.COINDAEMON_ALGO == 'groestl':
hash_bin = groestl_hash.getPoWHash(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]))
else:
hash_bin = util.doublesha(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]))
hash_int = util.uint256_from_str(hash_bin)
scrypt_hash_hex = "%064x" % hash_int
header_hex = binascii.hexlify(header_bin)
if settings.COINDAEMON_ALGO == 'scrypt' or settings.COINDAEMON_ALGO == 'scrypt-jane':
header_hex = header_hex+"000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000"
else: pass
target_user = self.diff_to_target(difficulty)
if hash_int > target_user:
raise SubmitException("Share is above target")
# Mostly for debugging purposes
target_info = self.diff_to_target(100000)
if hash_int <= target_info:
log.info("Yay, share with diff above 100000")
# Algebra tells us the diff_to_target is the same as hash_to_diff
share_diff = int(self.diff_to_target(hash_int))
# 5. Compare hash with target of the network
if hash_int <= job.target:
# Yay! It is block candidate!
log.info("We found a block candidate! %s" % scrypt_hash_hex)
# Reverse the header and get the potential block hash (for scrypt only)
#if settings.COINDAEMON_ALGO == 'scrypt' or settings.COINDAEMON_ALGO == 'sha256d':
# if settings.COINDAEMON_Reward == 'POW':
block_hash_bin = util.doublesha(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]))
block_hash_hex = block_hash_bin[::-1].encode('hex_codec')
#else: block_hash_hex = hash_bin[::-1].encode('hex_codec')
#else: block_hash_hex = hash_bin[::-1].encode('hex_codec')
# 6. Finalize and serialize block object
job.finalize(merkle_root_int, extranonce1_bin, extranonce2_bin, int(ntime, 16), int(nonce, 16))
if not job.is_valid():
# Should not happen
log.exception("FINAL JOB VALIDATION FAILED!(Try enabling/disabling tx messages)")
# 7. Submit block to the network
serialized = binascii.hexlify(job.serialize())
on_submit = self.bitcoin_rpc.submitblock(serialized, block_hash_hex, scrypt_hash_hex)
if on_submit:
self.update_block()
if settings.SOLUTION_BLOCK_HASH:
return (header_hex, block_hash_hex, share_diff, on_submit)
else:
return (header_hex, scrypt_hash_hex, share_diff, on_submit)
Submiting the block:
def submitblock(self, block_hex, hash_hex, scrypt_hex):
#try 5 times? 500 Internal Server Error could mean random error or that TX messages setting is wrong
attempts = 0
while True:
attempts += 1
if self.has_submitblock == True:
try:
log.debug("Submitting Block with submitblock: attempt #"+str(attempts))
log.debug([block_hex,])
resp = (yield self._call('submitblock', [block_hex,]))
log.debug("SUBMITBLOCK RESULT: %s", resp)
break
except Exception as e:
if attempts > 4:
log.exception("submitblock failed. Problem Submitting block %s" % str(e))
log.exception("Try Enabling TX Messages in config.py!")
raise
else:
continue
elif self.has_submitblock == False:
try:
log.debug("Submitting Block with getblocktemplate submit: attempt #"+str(attempts))
log.debug([block_hex,])
resp = (yield self._call('getblocktemplate', [{'mode': 'submit', 'data': block_hex}]))
break
except Exception as e:
if attempts > 4:
log.exception("getblocktemplate submit failed. Problem Submitting block %s" % str(e))
log.exception("Try Enabling TX Messages in config.py!")
raise
else:
continue
else: # self.has_submitblock = None; unable to detect submitblock, try both
try:
log.debug("Submitting Block with submitblock")
log.debug([block_hex,])
resp = (yield self._call('submitblock', [block_hex,]))
break
except Exception as e:
try:
log.exception("submitblock Failed, does the coind have submitblock?")
log.exception("Trying GetBlockTemplate")
resp = (yield self._call('getblocktemplate', [{'mode': 'submit', 'data': block_hex}]))
break
except Exception as e:
if attempts > 4:
log.exception("submitblock failed. Problem Submitting block %s" % str(e))
log.exception("Try Enabling TX Messages in config.py!")
raise
else:
continue
if json.loads(resp)['result'] == None:
# make sure the block was created.
log.info("CHECKING FOR BLOCK AFTER SUBMITBLOCK")
defer.returnValue((yield self.blockexists(hash_hex, scrypt_hex)))
else:
defer.returnValue(False)
Every time a share is submitted, stratum-mining says the share difficulty is above 100,000.