class ZcashdMiner(object): def __init__(self, zcashd_url): self.solver = Solver() self.server = Server(zcashd_url) def get_cb_tx(self, template, mining_address=None): orig = hex_to_bin(template['coinbasetxn']['data']) if not mining_address: return orig orig_decoded = self.server.decoderawtransaction( template['coinbasetxn']['data']) founder_tax_address = orig_decoded['vout'][1]['scriptPubKey'][ 'addresses'][0] founder_tax_amount = orig_decoded['vout'][1]['value'] reward = orig_decoded['vout'][0]['value'] new_out_tx = hex_to_bin( self.server.createrawtransaction( [], { mining_address: reward, founder_tax_address: founder_tax_amount })) return replace_output(orig, new_out_tx) @staticmethod def get_header_from_templete(t, cb_tx, nonce): version = t['version'] previous_block_hash = hex_to_bin(t['previousblockhash']) cb_hash = double_sha256_digest(cb_tx) #[::-1] # cb_hash = hex_to_bin(t['coinbasetxn']['hash'])[::-1] hashes = [ cb_hash, ] + txs_hashes(get_txs_from_template(t)) hash_merkle_root = MerkleTree(hashes).tree_digest() time = t['curtime'] bits = t['bits'] return ''.join(( struct.pack("<i", version), previous_block_hash[::-1], hash_merkle_root, '\x00' * 32, struct.pack("<I", time), hex_to_bin(bits)[::-1], nonce, )) def submit_block(self, template, cb_tx, header_with_solution_bin): txs = get_txs_from_template(template) block_bin = ''.join(( header_with_solution_bin, pack_varint(len(txs) + 1), # hex_to_bin(template['coinbasetxn']['data']), cb_tx, ''.join(txs), )) block_hex = bin_to_hex(block_bin) result = self.server.submitblock(block_hex) return bin_to_hex( double_sha256_digest(header_with_solution_bin)[::-1]), result def mine_block(self, mining_address=None): template = self.server.getblocktemplate() target = long(template['target'], 16) nonce_counter = 0 while True: nonce_counter += 1 nonce_bin = '%32x' % nonce_counter cb_tx = self.get_cb_tx(template, mining_address) header_bin = self.get_header_from_templete(template, cb_tx, nonce_bin) sol_num = self.solver.find_solutions(header_bin) for i in range(sol_num): solution_bin = self.solver.get_solution(i) header_with_solution_bin = header_bin + '\xfd\x40\x05' + solution_bin hash_bin = double_sha256_digest(header_with_solution_bin) hash_int = sha256_digest_to_int(hash_bin) if hash_int < target: return self.submit_block(template, cb_tx, header_with_solution_bin) def mine_n_blocks(self, n, mining_address=None): for _ in range(n): yield self.mine_block(mining_address) time.sleep(2)