示例#1
0
 def __init__(self, net, peer_addr, contents):
     self.net = net
     self.peer_addr = peer_addr
     self.contents = contents
     
     self.min_header = contents['min_header']
     self.share_info = contents['share_info']
     self.hash_link = contents['hash_link']
     self.merkle_link = contents['merkle_link']
     
     if not (2 <= len(self.share_info['share_data']['coinbase']) <= 100):
         raise ValueError('''bad coinbase size! %i bytes''' % (len(self.share_info['share_data']['coinbase']),))
     
     if len(self.merkle_link['branch']) > 16:
         raise ValueError('merkle branch too long!')
     
     assert not self.hash_link['extra_data'], repr(self.hash_link['extra_data'])
     
     self.share_data = self.share_info['share_data']
     self.max_target = self.share_info['max_bits'].target
     self.target = self.share_info['bits'].target
     self.timestamp = self.share_info['timestamp']
     self.previous_hash = self.share_data['previous_share_hash']
     self.new_script = bitcoin_data.pubkey_hash_to_script2(self.share_data['pubkey_hash'])
     self.desired_version = self.share_data['desired_version']
     self.absheight = self.share_info['absheight']
     self.abswork = self.share_info['abswork']
     
     n = set()
     for share_count, tx_count in self.iter_transaction_hash_refs():
         assert share_count < 110
         if share_count == 0:
             n.add(tx_count)
     assert n == set(range(len(self.share_info['new_transaction_hashes'])))
     
     self.gentx_hash = check_hash_link(
         self.hash_link,
         self.get_ref_hash(net, self.share_info, contents['ref_merkle_link']) + pack.IntType(64).pack(self.contents['last_txout_nonce']) + pack.IntType(32).pack(0),
         self.gentx_before_refhash,
     )
     merkle_root = bitcoin_data.check_merkle_link(self.gentx_hash, self.merkle_link)
     self.header = dict(self.min_header, merkle_root=merkle_root)
     self.pow_hash = net.PARENT.POW_FUNC(bitcoin_data.block_header_type.pack(self.header))
     self.hash = self.header_hash = skeinhash.getPoWHash(bitcoin_data.block_header_type.pack(self.header))
     
     if self.target > net.MAX_TARGET:
         from p2pool import p2p
         raise p2p.PeerMisbehavingError('share target invalid')
     
     if self.pow_hash > self.target:
         from p2pool import p2p
         raise p2p.PeerMisbehavingError('share PoW invalid')
     
     self.new_transaction_hashes = self.share_info['new_transaction_hashes']
     
     # XXX eww
     self.time_seen = time.time()
示例#2
0
def SkeinHash(x):
    return skeinhash.getPoWHash(x)
示例#3
0
def skeinhash256(data):
    return pack.IntType(256).unpack(skeinhash.getPoWHash(data))
示例#4
0
def SkeinHash(x):
    return skeinhash.getPoWHash(x)
    def submit_share(self, job_id, worker_name, session, extranonce1_bin, extranonce2, ntime, nonce,
                     difficulty):
        '''Check parameters and finalize block template. If it leads
           to valid block candidate, asynchronously submits the block
           back to the bitcoin network.
        
            - extranonce1_bin is binary. No checks performed, it should be from session data
            - job_id, extranonce2, ntime, nonce - in hex form sent by the client
            - difficulty - decimal number from session, again no checks performed
            - submitblock_callback - reference to method which receive result of submitblock()
        '''
        
        # 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 for job
        job = self.get_job(job_id)
        if job == None:
            raise SubmitException("Job '%s' not found" % job_id)
                
        # Check if ntime looks correct
        if settings.COINDAEMON_ALGO == 'riecoin':
            if len(ntime) != 16:
                raise SubmitException("Incorrect size of ntime. Expected 16 chars")
        else:
            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 settings.COINDAEMON_ALGO == 'riecoin':
            if len(nonce) != 64:
                 raise SubmitException("Incorrect size of nonce. Expected 64 chars")
        else:
            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")
        
        # Now let's do the hard work!
        # ---------------------------
        
        # 0. Some sugar
        extranonce2_bin = binascii.unhexlify(extranonce2)
        ntime_bin = binascii.unhexlify(ntime)
        nonce_bin = binascii.unhexlify(nonce)
        if settings.COINDAEMON_ALGO == 'riecoin':
            ntime_bin = (''.join([ ntime_bin[(1-i)*4:(1-i)*4+4] for i in range(0, 2) ]))
            nonce_bin = (''.join([ nonce_bin[(7-i)*4:(7-i)*4+4] for i in range(0, 8) ]))
                
        # 1. Build coinbase
        coinbase_bin = job.serialize_coinbase(extranonce1_bin, extranonce2_bin)
        coinbase_hash = util.doublesha(coinbase_bin)
        
        # 2. Calculate merkle root
        merkle_root_bin = job.merkletree.withFirst(coinbase_hash)
        merkle_root_int = util.uint256_from_str(merkle_root_bin)
                
        # 3. Serialize header with given merkle, ntime and nonce
        header_bin = job.serialize_header(merkle_root_int, ntime_bin, nonce_bin)
    
        # 4. Reverse header and compare it with target of the user
        if settings.COINDAEMON_ALGO == 'scrypt':
            hash_bin = ltc_scrypt.getPoWHash(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]))
        elif settings.COINDAEMON_ALGO  == 'scrypt-jane':
            hash_bin = yac_scrypt.getPoWHash(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]), int(ntime, 16))
        elif settings.COINDAEMON_ALGO == 'quark':
            hash_bin = quark_hash.getPoWHash(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]))
	elif settings.COINDAEMON_ALGO == 'skeinhash':
            hash_bin = skeinhash.getPoWHash(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]))
        else:
            hash_bin = util.doublesha(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]))

        hash_int = util.uint256_from_str(hash_bin)
        scrypt_hash_hex = "%064x" % hash_int

        if settings.COINDAEMON_ALGO == 'riecoin':
            # this is kind of an ugly hack: we use hash_int to store the number of primes
            hash_int = util.riecoinPoW( hash_int, job.target, int(nonce, 16) )

        header_hex = binascii.hexlify(header_bin)
        if settings.COINDAEMON_ALGO == 'scrypt' or settings.COINDAEMON_ALGO == 'scrypt-jane':
            header_hex = header_hex+"000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000"
        elif settings.COINDAEMON_ALGO == 'quark':
            header_hex = header_hex+"000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000"
        elif settings.COINDAEMON_ALGO == 'riecoin':
            header_hex = header_hex+"00000080000000000000000080030000"
        else: pass
                 
        target_user = self.diff_to_target(difficulty)
        if settings.COINDAEMON_ALGO == 'riecoin':
	    if hash_int < target_user:
                raise SubmitException("Share does not meet target")
        else:
	    if hash_int > target_user:
                raise SubmitException("Share is above target")
            # Mostly for debugging purposes
            target_info = self.diff_to_target(100000)
            if hash_int <= target_info:
                log.info("Yay, share with diff above 100000")

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

        # 5. Compare hash with target of the network
        isBlockCandidate = False
        if settings.COINDAEMON_ALGO == 'riecoin':
            if hash_int == 6:
                isBlockCandidate = True
        else:
            if hash_int <= job.target:
                isBlockCandidate = True

        if isBlockCandidate == True:
            # Yay! It is block candidate! 
            log.info("We found a block candidate! %s" % scrypt_hash_hex)

            # Reverse the header and get the potential block hash (for scrypt only) 
            if settings.COINDAEMON_ALGO == 'riecoin':
            	block_hash_bin = util.doublesha(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 28) ]))
            else:
            	block_hash_bin = util.doublesha(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]))
            block_hash_hex = block_hash_bin[::-1].encode('hex_codec')

            # 6. 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.exception("FINAL JOB VALIDATION FAILED!(Try enabling/disabling tx messages)")
                            
            # 7. Submit block to the network
            serialized = binascii.hexlify(job.serialize())
	    on_submit = self.bitcoin_rpc.submitblock(serialized, block_hash_hex, scrypt_hash_hex)
            if on_submit:
                self.update_block()

            if settings.SOLUTION_BLOCK_HASH:
                return (header_hex, block_hash_hex, share_diff, on_submit)
            else:
                return (header_hex, scrypt_hash_hex, share_diff, on_submit)
        
        if settings.SOLUTION_BLOCK_HASH:
        # Reverse the header and get the potential block hash (for scrypt only) only do this if we want to send in the block hash to the shares table
            if settings.COINDAEMON_ALGO == 'riecoin':
                block_hash_bin = util.doublesha(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 28) ]))
            else:
	        block_hash_bin = util.doublesha(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]))
            block_hash_hex = block_hash_bin[::-1].encode('hex_codec')
            return (header_hex, block_hash_hex, share_diff, None)
        else:
            return (header_hex, scrypt_hash_hex, share_diff, None)