示例#1
0
    def workable_block_header(self, template):
        """Takes a block template and creates a block header from it that
        is pre-processed into the SHA-256 message format.
        """
        gen_tx, gen_tx_hash, _gen_tx_full_hash = self.generation_tx_for_template(template)
        tx_hashes = (
            [gen_tx_hash]
            + [unhexlify(tx['txid'])[::-1] for tx in
               template['transactions']]
        )
        merkle_root = tx_merkle_root(tx_hashes)
        merkle_root_words = bytearray()
        for word in chunks(merkle_root, 4):
            merkle_root_words += word[::-1]

        prev_block_hash_words = bytearray()
        for word in chunks(unhexlify(template['previousblockhash']), 4):
            # Prepend because template items are in RPC byte order.
            prev_block_hash_words[0:0] = word

        header_words = b''.join((
            # Version
            pack(">L", template['version']),
            # Previous Block Hash
            prev_block_hash_words,
            # Merkle Root Hash
            merkle_root_words,
            # Time
            pack(">L", template['curtime']),
            # Target Bits
            unhexlify(template['bits']),
            # Nonce
            pack(">L", 0)  # Will be replaced by nonce as iterated.
        ))
        return header_words, gen_tx
示例#2
0
    def workable_block_header(self, template):
        """Takes a block template and creates a block header from it that
        is pre-processed into the SHA-256 message format.
        """
        gen_tx, gen_tx_hash, _gen_tx_full_hash = self.generation_tx_for_template(
            template)
        tx_hashes = (
            [gen_tx_hash] +
            [unhexlify(tx['txid'])[::-1] for tx in template['transactions']])
        merkle_root = tx_merkle_root(tx_hashes)
        merkle_root_words = bytearray()
        for word in chunks(merkle_root, 4):
            merkle_root_words += word[::-1]

        prev_block_hash_words = bytearray()
        for word in chunks(unhexlify(template['previousblockhash']), 4):
            # Prepend because template items are in RPC byte order.
            prev_block_hash_words[0:0] = word

        header_words = b''.join((
            # Version
            pack(">L", template['version']),
            # Previous Block Hash
            prev_block_hash_words,
            # Merkle Root Hash
            merkle_root_words,
            # Time
            pack(">L", template['curtime']),
            # Target Bits
            unhexlify(template['bits']),
            # Nonce
            pack(">L", 0)  # Will be replaced by nonce as iterated.
        ))
        return header_words, gen_tx
示例#3
0
 def set_difficulty(self, difficulty):
     self.difficulty = difficulty
     bits = '%08x' % bytereverse(difficulty)
     true_target = '%064x' % (
     int(bits[2:], 16) * 2 ** (8 * (int(bits[:2], 16) - 3)),)
     true_target = ''.join(list(chunks(true_target, 2))[::-1])
     self.true_target = unpack('<8I', unhexlify(true_target))
示例#4
0
 def submittable_block_header(self, result, nonce):
     header = bytearray()
     # Un-reverse the SHA-2 message words.
     for word in chunks(result.header, 4):
         header += word[::-1]
     header += pack('>3I', int(result.time), int(result.difficulty),
                    int(nonce))
     return header
示例#5
0
 def submittable_block_header(self, result, nonce):
     header = bytearray()
     # Un-reverse the SHA-2 message words.
     for word in chunks(result.header, 4):
         header += word[::-1]
     header += pack('>3I',
                    int(result.time), int(result.difficulty), int(nonce))
     return header
示例#6
0
    def refresh_job(self, j):
        j.extranonce2 = self.increment_nonce(j.extranonce2)
        coinbase = j.coinbase1 + self.extranonce + j.extranonce2 + j.coinbase2
        merkle_root = sha256(sha256(unhexlify(coinbase)).digest()).digest()
        for hash_ in j.merkle_branch:
            merkle_root = sha256(
                sha256(merkle_root + unhexlify(hash_)).digest()).digest()
        merkle_root_bak = ''.join(['%02x' % b for b in merkle_root])
        merkle_root_reversed = b''
        for word in chunks(merkle_root, 4):
            merkle_root_reversed += word[::-1]
        merkle_root = merkle_root_reversed.hex()

        j.block_header = ''.join(
            [j.version, j.prevhash, merkle_root, j.ntime, j.nbits])
        j.time = time()
        return j
示例#7
0
    def refresh_job(self, j):
        j.extranonce2 = self.increment_nonce(j.extranonce2)
        coinbase = j.coinbase1 + self.extranonce + j.extranonce2 + j.coinbase2
        merkle_root = sha256(sha256(unhexlify(coinbase)).digest()).digest()

        for hash_ in j.merkle_branch:
            merkle_root = sha256(
                sha256(merkle_root + unhexlify(hash_)).digest()).digest()
        merkle_root_reversed = b''
        for word in chunks(merkle_root, 4):
            merkle_root_reversed += word[::-1]
        merkle_root = merkle_root_reversed.hex()

        j.block_header = ''.join(
            [j.version, j.prevhash, merkle_root, j.ntime, j.nbits])
        j.time = time()
        return j
示例#8
0
    def decode(self, server, block_header, target, job_id=None,
               extranonce2=None):
        if block_header:
            job = Object()

            binary_data = unhexlify(block_header)
            data0 = list(unpack('<16I', binary_data[:64])) + ([0] * 48)

            job.target = unpack('<8I', unhexlify(target))
            job.header = binary_data[:68]
            job.merkle_end = uint32(unpack('<I', binary_data[64:68])[0])
            job.time = uint32(unpack('<I', binary_data[68:72])[0])
            job.difficulty = uint32(unpack('<I', binary_data[72:76])[0])
            job.state = sha256(STATE, data0)
            job.targetQ = 2 ** 256 // int(''.join(list(chunks(target, 2))[::-1]),
                                         16)
            job.job_id = job_id
            job.extranonce2 = extranonce2
            job.server = server

            if job.difficulty != self.difficulty:
                self.set_difficulty(job.difficulty)

            return job
示例#9
0
 def queue_work(self, work, miner=None):
     target = ''.join(
         list(chunks('%064x' % self.server_difficulty, 2))[::-1])
     self.switch.queue_work(self, work.block_header, target, work.job_id,
                            work.extranonce2, miner)
示例#10
0
    def handle_message(self, message):

        # Miner API
        if 'method' in message:

            # mining.notify
            if message['method'] == 'mining.notify':
                params = message['params']

                j = Object()

                j.job_id = params[0]
                j.prevhash = params[1]

                #john
                j.prevhash = ''.join([
                    j.prevhash[i] + j.prevhash[i + 1]
                    for i in range(0, len(j.prevhash), 2)
                ][::-1])
                prev_block_hash_words = bytearray()
                for word in chunks(unhexlify(j.prevhash), 4):
                    # Prepend because template items are in RPC byte order.
                    prev_block_hash_words[0:0] = word
                j.prevhash = ''.join(
                    ['%02x' % b for b in prev_block_hash_words])

                j.coinbase1 = params[2]
                j.coinbase2 = params[3]
                j.merkle_branch = params[4]
                j.version = params[5]
                j.nbits = params[6]
                j.ntime = params[7]
                clear_jobs = params[8]
                if clear_jobs:
                    self.jobs.clear()
                j.extranonce2 = self.extranonce2_size * '00'

                j = self.refresh_job(j)

                self.jobs[j.job_id] = j
                self.current_job = j

                self.queue_work(j)
                self.switch.connection_ok()

            # mining.get_version
            if message['method'] == 'mining.get_version':
                with self.send_lock:
                    self.send_message({
                        "error": None,
                        "id": message['id'],
                        "result": self.user_agent
                    })

            # mining.set_difficulty
            elif message['method'] == 'mining.set_difficulty':
                say_line("Setting new difficulty: %s", message['params'][0])
                self.server_difficulty = min(
                    MIN_DIFFICULTY,
                    int(BASE_DIFFICULTY // message['params'][0]))

            # client.reconnect
            elif message['method'] == 'client.reconnect':
                address, port = self.server().host.split(':', 1)
                (new_address, new_port, timeout) = message['params'][:3]
                if new_address:
                    address = new_address
                if new_port is not None:
                    port = new_port
                say_line("%s asked us to reconnect to %s:%d in %d seconds",
                         (self.server().name, address, port, timeout))
                self.server().host = address + ':' + str(port)
                Timer(timeout, self.reconnect).start()

            # client.add_peers
            elif message['method'] == 'client.add_peers':
                hosts = [{
                    'host': host[0],
                    'port': host[1]
                } for host in message['params'][0]]
                self.switch.add_servers(hosts)

        # responses to server API requests
        elif 'result' in message:

            # response to mining.subscribe
            # store extranonce and extranonce2_size
            if message['id'] == 's':
                self.extranonce = message['result'][1]
                self.extranonce2_size = message['result'][2]
                self.subscribed = True

            # check if this is submit confirmation (message id should be in submits dictionary)
            # cleanup if necessary
            elif message['id'] in self.submits:
                miner, nonce = self.submits[message['id']][:2]
                accepted = message['result']
                self.switch.report(miner, nonce, accepted)
                del self.submits[message['id']]
                if monotonic() - self.last_submits_cleanup > 3600:
                    now = monotonic()
                    for key, value in self.submits.items():
                        if now - value[2] > 3600:
                            del self.submits[key]
                    self.last_submits_cleanup = now

            # response to mining.authorize
            elif message['id'] == self.server().user:
                if not message['result']:
                    say_line('authorization failed with %s:%s@%s',
                             (self.server().user, self.server().pwd,
                              self.server().host))
                    self.authorized = False
                else:
                    self.authorized = True
示例#11
0
 def queue_work(self, work, miner=None):
     target = ''.join(
         list(chunks('%064x' % self.server_difficulty, 2))[::-1])
     self.switch.queue_work(self, work.block_header, target, work.job_id,
                            work.extranonce2, miner)