예제 #1
0
    def _ProcessGBT(self, MP, TS=None):
        oMP = MP
        MP = deepcopy(MP)

        prevBlock = bytes.fromhex(MP['previousblockhash'])[::-1]
        if 'height' not in MP:
            MP['height'] = TS['access'].getinfo()['blocks'] + 1
        height = MP['height']
        bits = bytes.fromhex(MP['bits'])[::-1]
        (MP['_bits'], MP['_prevBlock']) = (bits, prevBlock)
        if (prevBlock, height, bits) != self.currentBlock and (
                self.currentBlock[1] is None or height > self.currentBlock[1]):
            self.updateBlock(prevBlock,
                             height,
                             bits,
                             _HBH=(MP['previousblockhash'], MP['bits']))

        txnlist = MP['transactions']
        if len(txnlist) and isinstance(txnlist[0], dict):
            txninfo = txnlist
            txnlist = tuple(a['data'] for a in txnlist)
        elif 'transactionfees' in MP:
            # Backward compatibility with pre-BIP22 gmp_fees branch
            txninfo = [{'fee': a} for a in MP['transactionfees']]
        else:
            # Backward compatibility with pre-BIP22 hex-only (bitcoind <0.7, Eloipool <future)
            txninfo = [{}] * len(txnlist)
        # TODO: cache Txn or at least txid from previous merkle roots?
        txnlist = [a for a in map(bytes.fromhex, txnlist)]

        self._makeBlockSafe(MP, txnlist, txninfo)

        cbtxn = self.makeCoinbaseTxn(MP['coinbasevalue'],
                                     prevBlockHex=MP['previousblockhash'])
        cbtxn.setCoinbase(b'\0\0')
        cbtxn.assemble()
        txnlist.insert(0, cbtxn.data)
        txninfo.insert(0, {})

        txnlist = [a for a in map(Txn, txnlist[1:])]
        txnlist.insert(0, cbtxn)
        txnlist = list(txnlist)
        newMerkleTree = MerkleTree(txnlist)
        newMerkleTree.POTInfo = MP.get('POTInfo')
        newMerkleTree.MP = MP
        newMerkleTree.oMP = oMP

        return newMerkleTree
예제 #2
0
	def _ProcessGBT(self, MP, TS = None):
		oMP = MP
		MP = deepcopy(MP)
		
		prevBlock = bytes.fromhex(MP['previousblockhash'])[::-1]
		if 'height' not in MP:
			MP['height'] = TS['access'].getinfo()['blocks'] + 1
		height = MP['height']
		bits = bytes.fromhex(MP['bits'])[::-1]
		(MP['_bits'], MP['_prevBlock']) = (bits, prevBlock)
		if (prevBlock, height, bits) != self.currentBlock and (self.currentBlock[1] is None or height > self.currentBlock[1]):
			self.updateBlock(prevBlock, height, bits, _HBH=(MP['previousblockhash'], MP['bits']))
		
		txnlist = MP['transactions']
		if len(txnlist) and isinstance(txnlist[0], dict):
			txninfo = txnlist
			txnlist = tuple(a['data'] for a in txnlist)
		elif 'transactionfees' in MP:
			# Backward compatibility with pre-BIP22 gmp_fees branch
			txninfo = [{'fee':a} for a in MP['transactionfees']]
		else:
			# Backward compatibility with pre-BIP22 hex-only (bitcoind <0.7, Eloipool <future)
			txninfo = [{}] * len(txnlist)
		# TODO: cache Txn or at least txid from previous merkle roots?
		txnlist = [a for a in map(bytes.fromhex, txnlist)]
		
		self._makeBlockSafe(MP, txnlist, txninfo)
		
		cbtxn = self.makeCoinbaseTxn(MP['coinbasevalue'], prevBlockHex = MP['previousblockhash'])
		cbtxn.setCoinbase(b'\0\0')
		cbtxn.assemble()
		txnlist.insert(0, cbtxn.data)
		txninfo.insert(0, {
		})
		
		txnlist = [a for a in map(Txn, txnlist[1:])]
		txnlist.insert(0, cbtxn)
		txnlist = list(txnlist)
		newMerkleTree = MerkleTree(txnlist)
		newMerkleTree.POTInfo = MP.get('POTInfo')
		newMerkleTree.MP = MP
		newMerkleTree.oMP = oMP
		
		return newMerkleTree
    def updateMerkleTree(self):
        global now
        self.logger.debug('Polling bitcoind for memorypool')
        self.nextMerkleUpdate = now + self.TxnUpdateRetryWait

        try:
            # First, try BIP 22 standard getblocktemplate :)
            MP = self.access.getblocktemplate(self.GBTReq)
            self.OldGMP = False
        except:
            try:
                # Failing that, give BIP 22 draft (2012-02 through 2012-07) getmemorypool a chance
                MP = self.access.getmemorypool(self.GMPReq)
            except:
                try:
                    # Finally, fall back to bitcoind 0.5/0.6 getmemorypool
                    MP = self.access.getmemorypool()
                except:
                    MP = False
            if MP is False:
                # This way, we get the error from the BIP22 call if the old one fails too
                raise

            # Pre-BIP22 server (bitcoind <0.7 or Eloipool <20120513)
            if not self.OldGMP:
                self.OldGMP = True
                self.logger.warning('Upstream server is not BIP 22 compatible')

        oMP = deepcopy(MP)

        prevBlock = bytes.fromhex(MP['previousblockhash'])[::-1]
        if 'height' in MP:
            height = MP['height']
        else:
            height = self.access.getinfo()['blocks'] + 1
        bits = bytes.fromhex(MP['bits'])[::-1]
        if (prevBlock, height, bits) != self.currentBlock:
            self.updateBlock(prevBlock,
                             height,
                             bits,
                             _HBH=(MP['previousblockhash'], MP['bits']))

        txnlist = MP['transactions']
        if len(txnlist) and isinstance(txnlist[0], dict):
            txninfo = txnlist
            txnlist = tuple(a['data'] for a in txnlist)
            txninfo.insert(0, {})
        elif 'transactionfees' in MP:
            # Backward compatibility with pre-BIP22 gmp_fees branch
            txninfo = [{'fee': a} for a in MP['transactionfees']]
        else:
            # Backward compatibility with pre-BIP22 hex-only (bitcoind <0.7, Eloipool <future)
            txninfo = [{}] * len(txnlist)
        # TODO: cache Txn or at least txid from previous merkle roots?
        txnlist = [a for a in map(bytes.fromhex, txnlist)]

        self._makeBlockSafe(MP, txnlist, txninfo)

        cbtxn = self.makeCoinbaseTxn(MP['coinbasevalue'])
        cbtxn.setCoinbase(b'\0\0')
        cbtxn.assemble()
        txnlist.insert(0, cbtxn.data)

        txnlist = [a for a in map(Txn, txnlist[1:])]
        txnlist.insert(0, cbtxn)
        txnlist = list(txnlist)
        newMerkleTree = MerkleTree(txnlist)
        if newMerkleTree.merkleRoot() != self.currentMerkleTree.merkleRoot():
            newMerkleTree.POTInfo = MP.get('POTInfo')
            newMerkleTree.oMP = oMP

            if (not self.OldGMP) and 'proposal' in MP.get('capabilities', ()):
                (prevBlock, height, bits) = self.currentBlock
                coinbase = self.makeCoinbase(height=height)
                cbtxn.setCoinbase(coinbase)
                cbtxn.assemble()
                merkleRoot = newMerkleTree.merkleRoot()
                MRD = (merkleRoot, newMerkleTree, coinbase, prevBlock, bits)
                blkhdr = MakeBlockHeader(MRD)
                data = assembleBlock(blkhdr, txnlist)
                propose = self.access.getblocktemplate({
                    "mode":
                    "proposal",
                    "data":
                    b2a_hex(data).decode('utf8'),
                })
                if propose is None:
                    self.logger.debug(
                        'Updating merkle tree (upstream accepted proposal)')
                    self.currentMerkleTree = newMerkleTree
                else:
                    self.RejectedProposal = (newMerkleTree, propose)
                    try:
                        propose = propose['reject-reason']
                    except:
                        pass
                    self.logger.error('Upstream rejected proposed block: %s' %
                                      (propose, ))
            else:
                self.logger.debug('Updating merkle tree (no proposal support)')
                self.currentMerkleTree = newMerkleTree

        self.lastMerkleUpdate = now
        self.nextMerkleUpdate = now + self.MinimumTxnUpdateWait

        if self.needMerkle == 2:
            self.needMerkle = 1
            self.needMerkleSince = now
	def updateMerkleTree(self):
		global now
		self.logger.debug('Polling bitcoind for memorypool')
		self.nextMerkleUpdate = now + self.TxnUpdateRetryWait
		
		try:
			# First, try BIP 22 standard getblocktemplate :)
			MP = self.access.getblocktemplate(self.GBTReq)
			self.OldGMP = False
		except:
			try:
				# Failing that, give BIP 22 draft (2012-02 through 2012-07) getmemorypool a chance
				MP = self.access.getmemorypool(self.GMPReq)
			except:
				try:
					# Finally, fall back to bitcoind 0.5/0.6 getmemorypool
					MP = self.access.getmemorypool()
				except:
					MP = False
			if MP is False:
				# This way, we get the error from the BIP22 call if the old one fails too
				raise
			
			# Pre-BIP22 server (bitcoind <0.7 or Eloipool <20120513)
			if not self.OldGMP:
				self.OldGMP = True
				self.logger.warning('Upstream server is not BIP 22 compatible')
		
		oMP = deepcopy(MP)
		
		prevBlock = bytes.fromhex(MP['previousblockhash'])[::-1]
		if 'height' in MP:
			height = MP['height']
		else:
			height = self.access.getinfo()['blocks'] + 1
		bits = bytes.fromhex(MP['bits'])[::-1]
		if (prevBlock, height, bits) != self.currentBlock:
			self.updateBlock(prevBlock, height, bits, _HBH=(MP['previousblockhash'], MP['bits']))
		
		txnlist = MP['transactions']
		if len(txnlist) and isinstance(txnlist[0], dict):
			txninfo = txnlist
			txnlist = tuple(a['data'] for a in txnlist)
			txninfo.insert(0, {
			})
		elif 'transactionfees' in MP:
			# Backward compatibility with pre-BIP22 gmp_fees branch
			txninfo = [{'fee':a} for a in MP['transactionfees']]
		else:
			# Backward compatibility with pre-BIP22 hex-only (bitcoind <0.7, Eloipool <future)
			txninfo = [{}] * len(txnlist)
		# TODO: cache Txn or at least txid from previous merkle roots?
		txnlist = [a for a in map(bytes.fromhex, txnlist)]
		
		self._makeBlockSafe(MP, txnlist, txninfo)
		
		cbtxn = self.makeCoinbaseTxn(MP['coinbasevalue'])
		cbtxn.setCoinbase(b'\0\0')
		cbtxn.assemble()
		txnlist.insert(0, cbtxn.data)
		
		txnlist = [a for a in map(Txn, txnlist[1:])]
		txnlist.insert(0, cbtxn)
		txnlist = list(txnlist)
		newMerkleTree = MerkleTree(txnlist)
		if newMerkleTree.merkleRoot() != self.currentMerkleTree.merkleRoot():
			newMerkleTree.POTInfo = MP.get('POTInfo')
			newMerkleTree.oMP = oMP
			
			if (not self.OldGMP) and 'proposal' in MP.get('capabilities', ()):
				(prevBlock, height, bits) = self.currentBlock
				coinbase = self.makeCoinbase(height=height)
				cbtxn.setCoinbase(coinbase)
				cbtxn.assemble()
				merkleRoot = newMerkleTree.merkleRoot()
				MRD = (merkleRoot, newMerkleTree, coinbase, prevBlock, bits)
				blkhdr = MakeBlockHeader(MRD)
				data = assembleBlock(blkhdr, txnlist)
				propose = self.access.getblocktemplate({
					"mode": "proposal",
					"data": b2a_hex(data).decode('utf8'),
				})
				if propose is None:
					self.logger.debug('Updating merkle tree (upstream accepted proposal)')
					self.currentMerkleTree = newMerkleTree
				else:
					self.RejectedProposal = (newMerkleTree, propose)
					try:
						propose = propose['reject-reason']
					except:
						pass
					self.logger.error('Upstream rejected proposed block: %s' % (propose,))
			else:
				self.logger.debug('Updating merkle tree (no proposal support)')
				self.currentMerkleTree = newMerkleTree
		
		self.lastMerkleUpdate = now
		self.nextMerkleUpdate = now + self.MinimumTxnUpdateWait
		
		if self.needMerkle == 2:
			self.needMerkle = 1
			self.needMerkleSince = now
예제 #5
0
	def _ProcessGBT(self, MP, TS = None):
		oMP = MP
		MP = deepcopy(MP)
		
		if MP['version'] & 0xe0000000 != 0x20000000:
			self.logger.error('Template from \'%s\' has non-BIP9 block version (%x)' % (TS['name'], MP['version']))
			return None
		
		ISupportAllRules = True
		for ruleflag in MP['rules']:
			(MandatoryRule, rule) = SplitRuleFlag(ruleflag)
			if rule not in SupportedRules:
				ISupportAllRules = False
				if MandatoryRule:
					self.logger.error('Template from \'%s\' strictly requires unsupported rule \'%s\'', TS['name'], rule)
					return None
				else:
					self.logger.warning('Template from \'%s\' loosely requires unsupported rule \'%s\'', TS['name'], rule)
		
		MP['_filtered_vbavailable'] = {}
		for ruleflag in MP['vbavailable']:
			rulebit = MP['vbavailable'][ruleflag]
			rulemask = (1 << rulebit)
			if MP['version'] & rulemask:
				MP['_filtered_vbavailable'][ruleflag] = rulebit
		
		prevBlock = bytes.fromhex(MP['previousblockhash'])[::-1]
		if 'height' not in MP:
			MP['height'] = TS['access'].getinfo()['blocks'] + 1
		height = MP['height']
		bits = bytes.fromhex(MP['bits'])[::-1]
		(MP['_bits'], MP['_prevBlock']) = (bits, prevBlock)
		MP['_BlockVersionBytes'] = struct.pack('<L', MP['version'])
		if (prevBlock, height, bits) != self.currentBlock and (self.currentBlock[1] is None or height > self.currentBlock[1]):
			self.updateBlock(prevBlock, height, bits, _HBH=(MP['previousblockhash'], MP['bits']))
		
		txnlist = MP['transactions']
		if len(txnlist) and isinstance(txnlist[0], dict):
			txninfo = txnlist
			txnlist = tuple(a['data'] for a in txnlist)
		elif 'transactionfees' in MP:
			# Backward compatibility with pre-BIP22 gmp_fees branch
			txninfo = [{'fee':a} for a in MP['transactionfees']]
		else:
			# Backward compatibility with pre-BIP22 hex-only (bitcoind <0.7, Eloipool <future)
			txninfo = [{}] * len(txnlist)
		# TODO: cache Txn or at least txid from previous merkle roots?
		txnlist = [a for a in map(bytes.fromhex, txnlist)]
		
		self._makeBlockSafe(MP, txnlist, txninfo)
		if len(MP['transactions']) != len(txnlist) and not ISupportAllRules:
			self.logger.error('Template from \'%s\' should be trimmed, but requires unsupported rule(s)', TS['name'])
			return None
		
		txnobjs = [None]
		for i in range(len(txnlist)):
			iinfo = txninfo[i]
			ka = {}
			if 'txid' in iinfo:
				ka['txid'] = bytes.fromhex(iinfo['txid'])[::-1]
			txnobjs.append(Txn(data=txnlist[i], **ka))
		
		witness_commitment = CalculateWitnessCommitment(txnobjs, self.WitnessNonce, force=self.ForceWitnessCommitment)
		
		cbtxn = self.makeCoinbaseTxn(MP['coinbasevalue'], prevBlockHex = MP['previousblockhash'], witness_commitment=witness_commitment)
		cbtxn.setCoinbase(b'\0\0')
		cbtxn.assemble()
		txnobjs[0] = cbtxn
		
		txnobjs = list(txnobjs)
		newMerkleTree = MerkleTree(txnobjs)
		newMerkleTree.POTInfo = MP.get('POTInfo')
		newMerkleTree.MP = MP
		newMerkleTree.oMP = oMP
		newMerkleTree.witness_commitment = witness_commitment
		
		return newMerkleTree