def process_block(self, block, auth): logger.debug('process_block %s' % util.b2h(block)) hash = self.net.hash_block_header(block[:80]) target = self._get_target(auth['difficulty']) logger.debug('hash %s' % util.b2h(hash)) logger.debug('target %s' % util.b2h(target)) hash_long = util.bytes_to_long(hash) target_long = util.bytes_to_long(target) if hash_long > target_long: logger.debug("Hash is bigger than target") return False real_target = util.bytes_to_long( util.h2b(self.block_template['target'])) logger.debug('real target %s' % self.block_template['target']) database.share_accepted(auth['id']) if hash_long < real_target: logger.debug("Found block candidate") for i in self.tx: block += i.raw_tx logger.debug("Submitting %s" % util.b2h(block)) result = self.net.submitblock(util.b2h(block)) if result is None: database.block_found(auth['id'], self.block_template['height']) self.block_event.set() return True
def getwork(self, params, uri, auth): if len(params) > 0: block = util.h2b(params[0]) merkle_root = block[36:68] if merkle_root not in self.work_data: logger.error("Unknown worker submission") return False coinbase_tx = self.work_data[merkle_root].raw_tx block += util.encode_size(len(self.tx) + 1) block += coinbase_tx result = self.process_block(block, auth) del self.work_data[merkle_root] return result if uri == config.longpoll_uri: event = gevent.event.Event() self.add_longpoll_event(event) event.wait() coinbase_tx = self.create_coinbase_tx( util.h2b(self.get_work_id()), b'') merkle_root = MerkleTree.merkle_root_from_branch( coinbase_tx.raw_tx, self.merkle_branches) ntime = struct.pack(b'<I', self.block_template['curtime']) block_header = self.create_block_header(merkle_root, ntime, b'\x00\x00\x00\x00') block_header += (b"\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x80") self.work_data[merkle_root] = coinbase_tx # To little endian block_header = b''.join([block_header[x:x+4][::-1] for x in range(0, len(block_header), 4)]) target = util.b2h(self._get_target(auth['difficulty'])[::-1]) block_header = util.b2h(block_header) #TODO midstate, hash1 (deprecated) return {'data': block_header, 'target': target}
def getwork(self, params, uri, auth): if len(params) > 0: block = util.h2b(params[0]) merkle_root = block[36:68] if merkle_root not in self.work_data: logger.error("Unknown worker submission") return False coinbase_tx = self.work_data[merkle_root].raw_tx block += util.encode_size(len(self.tx) + 1) block += coinbase_tx result = self.process_block(block, auth) del self.work_data[merkle_root] return result if uri == config.longpoll_uri: event = gevent.event.Event() self.add_longpoll_event(event) event.wait() coinbase_tx = self.create_coinbase_tx(util.h2b(self.get_work_id()), b'') merkle_root = MerkleTree.merkle_root_from_branch( coinbase_tx.raw_tx, self.merkle_branches) ntime = struct.pack(b'<I', self.block_template['curtime']) block_header = self.create_block_header(merkle_root, ntime, b'\x00\x00\x00\x00') block_header += (b"\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x80") self.work_data[merkle_root] = coinbase_tx # To little endian block_header = b''.join([ block_header[x:x + 4][::-1] for x in range(0, len(block_header), 4) ]) target = util.b2h(self._get_target(auth['difficulty'])[::-1]) block_header = util.b2h(block_header) #TODO midstate, hash1 (deprecated) return {'data': block_header, 'target': target}
def getblocktemplate(self, params, uri, auth): """For worker""" longpollid = 'init' mode = 'template' # For older client data = None for i in params: if 'longpollid' in i: longpollid = i['longpollid'] if 'mode' in i: mode = i['mode'] if 'data' in i: data = i['data'] if mode == 'submit': try: block = util.h2b(data) sizelen, tx_size = util.decode_size(block[80:89]) ptr = 80 + sizelen txlen = CoinbaseTransaction.verify(block[ptr:], self.generation_pubkey) result = self.process_block(block[:ptr + txlen], auth) if result: return None except: logger.error("Exception while processing block") logger.error(traceback.format_exc()) return 'Rejected' if longpollid != 'init' or uri == config.longpoll_uri: event = gevent.event.Event() self.add_longpoll_event(event) event.wait() longpollid = self.get_work_id() coinbase_tx = self.create_coinbase_tx(b'', b'') block_template = { k: self.block_template[k] for k in self.block_template if k not in ['coinbasevalue', 'coinbaseaux', 'coinbaseflags'] } block_template['target'] = util.b2h( self._get_target(auth['difficulty'])) block_template['mutable'] = ["coinbase/append", "submit/coinbase"] block_template['transactions'] = [x.serialize() for x in self.tx] block_template['coinbasetxn'] = coinbase_tx.serialize() #Long polling extension block_template['longpollid'] = longpollid block_template['expires'] = 120 block_template['submitold'] = True block_template['longpolluri'] = config.longpoll_uri return block_template
def getblocktemplate(self, params, uri, auth): """For worker""" longpollid = 'init' mode = 'template' # For older client data = None for i in params: if 'longpollid' in i: longpollid = i['longpollid'] if 'mode' in i: mode = i['mode'] if 'data' in i: data = i['data'] if mode == 'submit': try: block = util.h2b(data) sizelen, tx_size = util.decode_size(block[80:89]) ptr = 80 + sizelen txlen = CoinbaseTransaction.verify(block[ptr:], self.generation_pubkey) result = self.process_block(block[:ptr+txlen], auth) if result: return None except: logger.error("Exception while processing block") logger.error(traceback.format_exc()) return 'Rejected' if longpollid != 'init' or uri == config.longpoll_uri: event = gevent.event.Event() self.add_longpoll_event(event) event.wait() longpollid = self.get_work_id() coinbase_tx = self.create_coinbase_tx(b'', b'') block_template = {k: self.block_template[k] for k in self.block_template if k not in ['coinbasevalue', 'coinbaseaux', 'coinbaseflags']} block_template['target'] = util.b2h( self._get_target(auth['difficulty'])) block_template['mutable'] = ["coinbase/append", "submit/coinbase"] block_template['transactions'] = [x.serialize() for x in self.tx] block_template['coinbasetxn'] = coinbase_tx.serialize() #Long polling extension block_template['longpollid'] = longpollid block_template['expires'] = 120 block_template['submitold'] = True block_template['longpolluri'] = config.longpoll_uri return block_template
def get_stratum_work(self, extranonce1): result = [] result.append(self.get_work_id()) # Job id prevblockhash = util.h2b( self.block_template['previousblockhash'])[::-1] prevblockhash = b''.join([prevblockhash[x:x+4][::-1] for x in range(0, len(prevblockhash), 4)]) result.append(util.b2h(prevblockhash)) coinbase_tx = self.create_coinbase_tx( extranonce1, b'\x00\x00\x00\x00') coinbase_data = bytearray(coinbase_tx.raw_tx) orig_len = coinbase_data[41] firstpart_len = orig_len - 4 - config.extranonce2_size result.append(util.b2h(coinbase_data[:42+firstpart_len])) result.append(util.b2h(coinbase_data[42+orig_len:])) result.append([util.b2h(x) for x in self.merkle_branches]) result.append(util.b2h( struct.pack(b'>I', self.block_template['version']))) result.append(self.block_template['bits']) result.append(util.b2h( struct.pack(b'>I', self.block_template['curtime']))) result.append(True) return result
def get_stratum_work(self, extranonce1): result = [] result.append(self.get_work_id()) # Job id prevblockhash = util.h2b( self.block_template['previousblockhash'])[::-1] prevblockhash = b''.join([ prevblockhash[x:x + 4][::-1] for x in range(0, len(prevblockhash), 4) ]) result.append(util.b2h(prevblockhash)) coinbase_tx = self.create_coinbase_tx(extranonce1, b'\x00\x00\x00\x00') coinbase_data = bytearray(coinbase_tx.raw_tx) orig_len = coinbase_data[41] firstpart_len = orig_len - 4 - config.extranonce2_size result.append(util.b2h(coinbase_data[:42 + firstpart_len])) result.append(util.b2h(coinbase_data[42 + orig_len:])) result.append([util.b2h(x) for x in self.merkle_branches]) result.append( util.b2h(struct.pack(b'>I', self.block_template['version']))) result.append(self.block_template['bits']) result.append( util.b2h(struct.pack(b'>I', self.block_template['curtime']))) result.append(True) return result
def __init__(self, block_template, generation_pubkey, extranonce1, extranonce2): #BIP 0034 coinbase_script = util.encode_height(block_template['height']) if 'coinbaseaux' in block_template: for i in block_template['coinbaseaux']: data = util.h2b(block_template['coinbaseaux'][i]) coinbase_script += data if 'coinbaseflags' in block_template: data = util.h2b(block_template['coinbaseflags']) coinbase_script += data coinbase_script += extranonce1 coinbase_script += extranonce2 if 'coinbasevalue' in block_template: coinbase_value = block_template['coinbasevalue'] else: tx = Transaction(block_template['coinbasetxn']) coinbase_value = tx.output[0]['value'] output_script = b'\x76\xa9\x14' + generation_pubkey + b'\x88\xac' result = b'\x01\x00\x00\x00' # Version result += b'\x01' # In counter(1) result += b'\x00' * 32 # Input(None) result += b'\xff\xff\xff\xff' # Input Index (None) result += util.encode_size(len(coinbase_script)) result += coinbase_script result += b'\xff\xff\xff\xff' # Sequence result += b'\x01' # Out counter(1) result += struct.pack(b'<Q', coinbase_value) result += util.encode_size(len(output_script)) result += output_script result += b'\x00\x00\x00\x00' # Lock time self.raw_tx = result logger.debug('Generated coinbase transaction %s' % util.b2h(self.raw_tx))
def get_work_id(self): self.seq += 1 return util.b2h(struct.pack(b'<I', self.seq))
def serialize(self): return {'data': util.b2h(self.raw_tx)}
def mining_subscribe(self, params, uri, auth): self.pusher = gevent.spawn(self.block_pusher) nonce1 = util.b2h(self.extranonce1) return [['mining.notify', 'ae6812eb4cd7735a302a8a9dd95cf71f'], nonce1, config.extranonce2_size]
def mining_get_transactions(self, params, uri, auth): return [util.b2h(x.raw_tx) for x in self.work.tx]