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 _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
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