Ejemplo n.º 1
0
 def recalculate(self, detailed=False):
     L = self.data
     steps = []
     if detailed:
         detail = []
         PreL = []
         StartL = 0
     else:
         detail = None
         PreL = [None]
         StartL = 2
     Ll = len(L)
     if detailed or Ll > 1:
         while True:
             if detailed:
                 detail += L
             if Ll == 1:
                 break
             steps.append(L[1])
             if Ll % 2:
                 L += [L[-1]]
             L = PreL + [
                 kshake320_hash.getHash320(L[i] + L[i + 1])
                 for i in range(StartL, Ll, 2)
             ]
             Ll = len(L)
     self._steps = steps
     self.detail = detail
Ejemplo n.º 2
0
    def is_valid(self):
        self.calc_powhash320()
        #target = self.nBits
        target = self.target

        if self.powhash320 > target:
            return False

        hashes = []
        for tx in self.vtx:
            tx.hash320 = None
            if not tx.is_valid():
                return False
            tx.calc_hash320()
            hashes.append(ser_uint320(tx.hash320))

        while len(hashes) > 1:
            newhashes = []
            for i in xrange(0, len(hashes), 2):
                i2 = min(i + 1, len(hashes) - 1)
                newhashes.append(
                    kshake320_hash.getHash320(hashes[i] + hashes[i2]))
            hashes = newhashes

        if uint320_from_str(hashes[0]) != self.hashMerkleRoot:
            return False
        return True
Ejemplo n.º 3
0
 def withFirst(self, f):
     steps = self._steps
     for s in steps:
         f = kshake320_hash.getHash320(f + s)
     return f
Ejemplo n.º 4
0
 def hash_steps(self):
     if self._hash_steps == None:
         self._hash_steps = kshake320_hash.getHash320(''.join(self._steps))
     return self._hash_steps
Ejemplo n.º 5
0
 def calc_hash320(self):
     if self.hash320 is None:
         self.hash320 = uint320_from_str(
             kshake320_hash.getHash320(self.serialize()))
     return self.hash320
Ejemplo n.º 6
0
    def submit_share(self, job_id, worker_name, session, extranonce1_bin,
                     extranonce2, ntime, nonce, difficulty):

        # Check for job
        job = self.get_job(job_id)
        if job == None:
            raise SubmitException("Job '%s' not found" % job_id)

        nonce = util.rev(nonce)
        ntime = util.rev(ntime)
        extranonce2_bin = binascii.unhexlify(extranonce2)
        ntime_bin = binascii.unhexlify(ntime)
        nonce_bin = binascii.unhexlify(nonce)

        # Check if extranonce2 looks correctly. extranonce2 is in hex form...
        if len(extranonce2) != self.extranonce2_size * 2:
            raise SubmitException(
                "Incorrect size of extranonce2. Expected %d chars" %
                (self.extranonce2_size * 2))

        # Check if ntime looks correct
        if len(ntime) != 8:
            raise SubmitException("Incorrect size of ntime. Expected 8 chars")

        if not job.check_ntime(int(ntime, 16)):
            raise SubmitException("Ntime out of range")

        # Check nonce
        if len(nonce) != 8:
            raise SubmitException("Incorrect size of nonce. Expected 8 chars")

        # Check for duplicated submit
        if not job.register_submit(extranonce1_bin, extranonce2, ntime, nonce):
            log.info("Duplicate from %s, (%s %s %s %s)" % \
                    (worker_name, binascii.hexlify(extranonce1_bin), extranonce2, ntime, nonce))
            raise SubmitException("Duplicate share")

        # 1. Build coinbase
        coinbase_bin = job.serialize_coinbase(extranonce1_bin, extranonce2_bin)
        coinbase_hash = kshake320_hash.getHash320(coinbase_bin)

        # 2. Calculate merkle root
        merkle_root_bin = job.merkletree.withFirst(coinbase_hash)
        merkle_root_int = util.uint320_from_str(merkle_root_bin)

        # 3. Serialize header with given merkle, ntime and nonce
        header_bin = job.serialize_header(merkle_root_bin, int(ntime, 16),
                                          int(nonce, 16))

        header_hex = binascii.hexlify(header_bin)
        header_hex = header_hex + "0000000000000000"

        # 4. Reverse header and compare it with target of the user
        hash_bin = kshake320_hash.getPoWHash(header_bin)
        hash_int = util.uint320_from_str(hash_bin)
        hash_hex = "%080x" % hash_int
        block_hash_hex = hash_bin[::-1].encode('hex_codec')

        target_user = float(self.diff_to_target(difficulty))
        if hash_int > target_user:
            log.info("ABOVE TARGET!")
            raise SubmitException("Share above target")

        target_info = self.diff_to_target(50)
        if hash_int <= target_info:
            log.info("YAY, share with diff above 50")

        # Algebra tells us the diff_to_target is the same as hash_to_diff
        share_diff = float(self.diff_to_target(hash_int))

        if hash_int <= job.target:
            # Yay! It is block candidate!
            log.info("BLOCK CANDIDATE! %s" % block_hash_hex)

            # Finalize and serialize block object
            job.finalize(merkle_root_int, extranonce1_bin, extranonce2_bin,
                         int(ntime, 16), int(nonce, 16))

            if not job.is_valid():
                # Should not happen
                log.info("FINAL JOB VALIDATION FAILED!")

            # Submit block to the network
            '''serialized = binascii.hexlify(job.serialize())
            on_submit = self.bitcoin_rpc.submitblock(str(serialized), block_hash_hex)'''

            job.vtx[0].set_extranonce(extranonce1_bin + extranonce2_bin)
            txs = binascii.hexlify(util.ser_vector(job.vtx))
            on_submit = self.bitcoin_rpc.submitblock_wtxs(
                str(header_hex), str(txs), block_hash_hex)
            '''if on_submit:
                self.update_block()'''

            return (block_hash_hex, share_diff, on_submit)

        return (block_hash_hex, share_diff, None)