def _Address2PKH(addr): try: addr = b58decode(addr, 25) except: return None if addr is None: return None ver = addr[0] cksumA = addr[-4:] cksumB = blakehash(addr[:-4])[:4] if cksumA != cksumB: return None return (ver, addr[1:-4])
def checkShare(share): shareTime = share['time'] = time() username = share['username'] if 'data' in share: # getwork/GBT checkData(share) data = share['data'] if username not in workLog: raise RejectedShare('unknown-user') MWL = workLog[username] shareMerkleRoot = data[36:68] if 'blkdata' in share: pl = share['blkdata'] (txncount, pl) = varlenDecode(pl) cbtxn = bitcoin.txn.Txn(pl) othertxndata = cbtxn.disassemble(retExtra=True) coinbase = cbtxn.getCoinbase() wliPos = coinbase[0] + 2 wliLen = coinbase[wliPos - 1] wli = coinbase[wliPos:wliPos+wliLen] mode = 'MC' moden = 1 else: wli = shareMerkleRoot mode = 'MRD' moden = 0 coinbase = None else: # Stratum MWL = workLog[None] wli = share['jobid'] buildStratumData(share, b'\0' * 32) mode = 'MC' moden = 1 othertxndata = b'' if wli not in MWL: raise RejectedShare('unknown-work') (wld, issueT) = MWL[wli] share[mode] = wld share['issuetime'] = issueT (workMerkleTree, workCoinbase) = wld[1:3] share['merkletree'] = workMerkleTree if 'jobid' in share: cbtxn = deepcopy(workMerkleTree.data[0]) coinbase = workCoinbase + share['extranonce1'] + share['extranonce2'] cbtxn.setCoinbase(coinbase) cbtxn.assemble() data = buildStratumData(share, workMerkleTree.withFirst(cbtxn)) shareMerkleRoot = data[36:68] if data in DupeShareHACK: raise RejectedShare('duplicate') DupeShareHACK[data] = None blkhash = blakehash(data) if blkhash[28:] != b'\0\0\0\0': print('H-not-zero (%s)' % (username,)) raise RejectedShare('H-not-zero') blkhashn = LEhash2int(blkhash) global networkTarget logfunc = getattr(checkShare.logger, 'info' if blkhashn <= networkTarget else 'debug') logfunc('BLKHASH: %64x' % (blkhashn,)) logfunc(' TARGET: %64x' % (networkTarget,)) # NOTE: this isn't actually needed for MC mode, but we're abusing it for a trivial share check... txlist = workMerkleTree.data txlist = [deepcopy(txlist[0]),] + txlist[1:] cbtxn = txlist[0] cbtxn.setCoinbase(coinbase or workCoinbase) cbtxn.assemble() if blkhashn <= networkTarget: logfunc("Submitting upstream") RBDs.append( deepcopy( (data, txlist, share.get('blkdata', None), workMerkleTree, share, wld) ) ) if not moden: payload = assembleBlock(data, txlist) else: payload = share['data'] if len(othertxndata): payload += share['blkdata'] else: payload += assembleBlock(data, txlist)[80:] logfunc('Real block payload: %s' % (b2a_hex(payload).decode('utf8'),)) RBPs.append(payload) threading.Thread(target=blockSubmissionThread, args=(payload, blkhash, share)).start() bcnode.submitBlock(payload) if config.DelayLogForUpstream: share['upstreamRejectReason'] = PendingUpstream else: share['upstreamRejectReason'] = None share['upstreamResult'] = True MM.updateBlock(blkhash) # Gotwork hack... if gotwork and blkhashn <= config.GotWorkTarget: try: coinbaseMrkl = cbtxn.data coinbaseMrkl += blkhash steps = workMerkleTree._steps coinbaseMrkl += pack('B', len(steps)) for step in steps: coinbaseMrkl += step coinbaseMrkl += b"\0\0\0\0" info = {} info['hash'] = b2a_hex(blkhash).decode('ascii') info['header'] = b2a_hex(data).decode('ascii') info['coinbaseMrkl'] = b2a_hex(coinbaseMrkl).decode('ascii') thr = threading.Thread(target=submitGotwork, args=(info,)) thr.daemon = True thr.start() except: checkShare.logger.warning('Failed to build gotwork request') if 'target' in share: workTarget = share['target'] elif len(wld) > 6: workTarget = wld[6] else: workTarget = None if workTarget is None: workTarget = config.ShareTarget if blkhashn > workTarget: raise RejectedShare('high-hash') share['target'] = workTarget share['_targethex'] = '%064x' % (workTarget,) shareTimestamp = unpack('<L', data[68:72])[0] if shareTime < issueT - 120: raise RejectedShare('stale-work') if shareTimestamp < shareTime - 300: raise RejectedShare('time-too-old') if shareTimestamp > shareTime + 7200: raise RejectedShare('time-too-new') if moden: cbpre = workCoinbase cbpreLen = len(cbpre) if coinbase[:cbpreLen] != cbpre: raise RejectedShare('bad-cb-prefix') # Filter out known "I support" flags, to prevent exploits for ff in (b'/P2SH/', b'NOP2SH', b'p2sh/CHV', b'p2sh/NOCHV'): if coinbase.find(ff) > max(-1, cbpreLen - len(ff)): raise RejectedShare('bad-cb-flag') if len(coinbase) > 100: raise RejectedShare('bad-cb-length') if shareMerkleRoot != workMerkleTree.withFirst(cbtxn): raise RejectedShare('bad-txnmrklroot') if len(othertxndata): allowed = assembleBlock(data, txlist)[80:] if allowed != share['blkdata']: raise RejectedShare('bad-txns') if config.DynamicTargetting and username in userStatus: # NOTE: userStatus[username] only doesn't exist across restarts status = userStatus[username] target = status[0] or config.ShareTarget if target == workTarget: userStatus[username][2] += 1 else: userStatus[username][2] += float(target) / workTarget