Exemplo n.º 1
0
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 = dblsha(data)
	if blkhash[28:] != b'\0\0\0\0':
		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 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
	
	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')
Exemplo n.º 2
0
def checkShare(share):
    shareTime = share["time"] = time()

    username = share["username"]
    isstratum = False
    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
        isstratum = True
        wli = share["jobid"]
        buildStratumData(share, b"\0" * 32)
        mode = "MC"
        moden = 1
        othertxndata = b""
        if None not in workLog:
            # We haven't yet sent any stratum work for this block
            raise RejectedShare("unknown-work")
        MWL = workLog[None]

    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 = dblsha(data)
    if blkhash[28:] != b"\0\0\0\0":
        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
        if isstratum and userStatus[username][2] > config.DynamicTargetGoal * 2:
            stratumsrv.quickDifficultyUpdate(username)
Exemplo n.º 3
0
def checkShare(share):
    global rskLastReceivedShareTime
    global rskSubmittedShares

    shareTime = share['time'] = time()

    username = share['username']
    checkQuickDiffAdjustment = False
    if 'data' in share:
        # getwork/GBT
        data = share['data']

        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

        (wld, issueT) = LookupWork(username, wli)
        checkData(share, wld)
    else:
        # Stratum
        checkQuickDiffAdjustment = config.DynamicTargetQuick
        wli = share['jobid']
        (wld, issueT) = LookupWork(None, wli)
        mode = 'MC'
        moden = 1
        othertxndata = b''

    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),
                                workMerkleTree.MP['_BlockVersionBytes'])
        shareMerkleRoot = data[36:68]

    if data in DupeShareHACK:
        raise RejectedShare('duplicate')
    DupeShareHACK[data] = None

    blkhash = dblsha(data)

    if not hasattr(config, 'DEV_MODE_ON') or not config.DEV_MODE_ON:
        if not _reachesLowestDifficulty(blkhash):

            if len(share[mode]) >= 4:
                # currentblock may be changed, so we retry looking up some previous block saved (in RKS could be usefull prev blocks).
                blockToUse = (share[mode][3], share[mode][0], share[mode][4])
                retryData = buildStratumData(
                    share, workMerkleTree.withFirst(cbtxn),
                    workMerkleTree.MP['_BlockVersionBytes'], blockToUse)

                shareMerkleRoot = retryData[36:68]

                blkhash = dblsha(retryData)

                # retryData could be equal than data so we check again previous conditions
                if retryData == data or not _reachesLowestDifficulty(blkhash):
                    raise RejectedShare('H-not-zero')

                data = retryData
                DupeShareHACK[data] = None

            else:
                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()

    rootstockBlockHash = None
    rootstockTarget = None

    if hasattr(workMerkleTree, "rootstockBlockInfo"
               ) and workMerkleTree.rootstockBlockInfo is not None:
        rootstockBlockHash = workMerkleTree.rootstockBlockInfo[0]
        if hasattr(config, 'DEV_MODE_ON') and config.DEV_MODE_ON:
            rootstockTarget = bdiff2target(config.RSK_ELOIPOOL_DIFF)
        else:
            rootstockTarget = workMerkleTree.rootstockBlockInfo[1]

    submitRootstock = rootstockTarget is not None and blkhashn <= rootstockTarget

    if rskLastReceivedShareTime is None:
        rskLastReceivedShareTime = int(round(time() * 1000))
        rskSubmittedShares = 0
    lastReceivedShareTimeNow = int(round(time() * 1000))

    if lastReceivedShareTimeNow - rskLastReceivedShareTime >= 1000:
        rskSubmittedShares = 0
        rskLastReceivedShareTime = lastReceivedShareTimeNow

    checkShare.logger.info(
        "ROOTSTOCK_DEBUG: RSKValidShare: {0} {1} {2}".format(
            blkhashn, rootstockTarget, submitRootstock))
    if lastReceivedShareTimeNow - rskLastReceivedShareTime < 1000 and rskSubmittedShares < 1 and submitRootstock:
        rskSubmittedShares += 1
    else:
        submitRootstock = False

    submitBitcoin = blkhashn <= networkTarget
    #checkShare.logger.info("ROOTSTOCK_DEBUG: BTCValidShare: {0} {1} {2}".format(blkhashn, networkTarget, submitBitcoin))

    if submitBitcoin or submitRootstock:
        if submitBitcoin:
            share['BTC_SOLUTION'] = True
            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:]

        if submitRootstock:
            share['RSK_SOLUTION'] = True

            blockhashHexRskSubmit = b2a_hex(blkhash).decode('ascii')
            blockheaderHexRskSubmit = b2a_hex(share['data']).decode('ascii')
            coinbaseHexRskSubmit = b2a_hex(cbtxn.data).decode('ascii')

            coinbaseHashHexRskSubmit = b2a_hex(cbtxn.txid).decode('ascii')
            merkleHashesRskSubmit = [
                b2a_hex(x).decode('ascii') for x in workMerkleTree._steps
            ]
            merkleHashesRskSubmit.insert(0, coinbaseHashHexRskSubmit)
            merkleHashesRskSubmit = ' '.join(merkleHashesRskSubmit)

            txnCountRskSubmit = hex(len(txlist))[2:]
            threading.Thread(target=rootstockSubmissionThread,
                             args=(blockhashHexRskSubmit,
                                   blockheaderHexRskSubmit,
                                   coinbaseHexRskSubmit, merkleHashesRskSubmit,
                                   txnCountRskSubmit, share)).start()

        if not submitBitcoin:
            return

        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 - config.StaleWorkTimeout:
        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
        if checkQuickDiffAdjustment and userStatus[username][
                2] > config.DynamicTargetGoal * 2:
            stratumsrv.quickDifficultyUpdate(username)
Exemplo n.º 4
0
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]
	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 = PoWHash(data)
	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['difficulty'] = config.ShareTarget / 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 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
	
	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')
Exemplo n.º 5
0
def checkShare(share):
    shareTime = share['time'] = time()

    data = share['data']
    data = data[:80]
    (prevBlock, height, bits) = MM.currentBlock
    sharePrevBlock = data[4:36]
    if sharePrevBlock != prevBlock:
        if sharePrevBlock == MM.lastBlock[0]:
            raise RejectedShare('stale-prevblk')
        raise RejectedShare('bad-prevblk')

    # TODO: use userid
    username = share['username']
    if username not in workLog:
        raise RejectedShare('unknown-user')

    if data[72:76] != bits:
        raise RejectedShare('bad-diffbits')

    # Note that we should accept miners reducing version to 1 if they don't understand 2 yet
    # FIXME: When the supermajority is upgraded to version 2, stop accepting 1!
    if data[1:4] != b'\0\0\0' or data[0] > 2:
        raise RejectedShare('bad-version')

    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

    MWL = workLog[username]
    if wli not in MWL:
        raise RejectedShare('unknown-work')
    (wld, issueT) = MWL[wli]
    share[mode] = wld

    if data in DupeShareHACK:
        raise RejectedShare('duplicate')
    DupeShareHACK[data] = None

    blkhash = dblsha(data)
    if blkhash[28:] != b'\0\0\0\0':
        raise RejectedShare('H-not-zero')
    blkhashn = hash2int(blkhash)

    global networkTarget
    logfunc = getattr(checkShare.logger,
                      'info' if blkhashn <= networkTarget else 'debug')
    logfunc('BLKHASH: %64x' % (blkhashn, ))
    logfunc(' TARGET: %64x' % (networkTarget, ))

    workMerkleTree = wld[1]
    workCoinbase = wld[2]
    workTarget = wld[6] if len(wld) > 6 else None

    # 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)
        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 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 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

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