def __init__(self, data, coinbase_output_address, testnet = False, coinbase_message = "", extranonce1 = "00000000", extranonce1_size = 4, extranonce2_size = 4): self.testnet = testnet self.version = hexlify(data["version"].to_bytes(4, "big")).decode() self.previous_block_hash = hexlify(reverse_hash(s2rh(data["previousblockhash"]))).decode() self.time = hexlify(data["curtime"].to_bytes(4, "big")).decode() self.bits = data["bits"] self.height = data["height"] self.block_reward = 50 * 100000000 >> data["height"] // 210000 self.coinbasevalue = self.block_reward self.extranonce1 = extranonce1 self.extranonce1_size = extranonce1_size self.extranonce2 = "00000000" self.extranonce2_size = extranonce2_size self.coinbase_output_address = coinbase_output_address self.sigoplimit = data["sigoplimit"] self.weightlimit = data["weightlimit"] self.sigop= 0 self.weight = 0 if type(coinbase_message) == bytes: coinbase_message = hexlify(coinbase_message).decode() self.coinbase_message = coinbase_message self.transactions = list(data["transactions"]) self.txid_list = list() self.scan_tx_list() self.coinbase_tx = self.create_coinbase_transaction() self.coinb1, self.coinb2 = self.split_coinbase() self.target = bits_to_target(self.bits) self.difficulty = target_to_difficulty(self.target) self.merkle_branches = [i for i in merkle_branches([self.coinbase_tx["txId"],] + self.txid_list)]
def merkle_proof(merkle_tree, index, return_hex=True, receive_hex=False): if receive_hex == True: _merkle_tree = dict() for i in merkle_tree: _merkle_tree[i] = dict() for k in range(len(merkle_tree[i])): h = merkle_tree[i][k] _merkle_tree[i][k] = s2rh(h) if isinstance(h, str) else h merkle_tree = _merkle_tree mp = deque() mp_append = mp.append c = len(merkle_tree) - 1 while c: if index % 2: mp_append(merkle_tree[c][index - 1]) else: if len(merkle_tree[c]) > index + 1: mp_append(merkle_tree[c][index + 1]) else: mp_append(merkle_tree[c][index]) c -= 1 index = index//2 if return_hex: return [rh2s(h) for h in mp] else: return mp
def merkle_root(tx_hash_list, return_hex=True, receive_hex=True): """ Calculate merkle root from transaction hash list :param tx_hash_list: list of transaction hashes in bytes or HEX encoded string. :param return_hex: (optional) If set to True return result in HEX format, by default is True. :param receive_hex: (optional) If set to False no internal check or decode from hex to bytes, by default is True. :return: merkle root in bytes or HEX encoded string corresponding hex flag. """ if receive_hex: tx_hash_list = deque([h if isinstance(h, bytes) else s2rh(h) for h in tx_hash_list]) else: tx_hash_list = deque(tx_hash_list) if len(tx_hash_list) == 1: return rh2s(tx_hash_list[0]) if return_hex else tx_hash_list[0] while True: new_hash_list = deque() append = new_hash_list.append while tx_hash_list: h1 = tx_hash_list.popleft() try: h2 = tx_hash_list.popleft() except: h2 = h1 append(double_sha256(b"".join((h1, h2)))) if len(new_hash_list) > 1: tx_hash_list = new_hash_list else: return new_hash_list[0] if not return_hex else rh2s(new_hash_list[0])
def merkle_tree(tx_hash_list, return_hex=False, receive_hex=False): if receive_hex: tx_hash_deque = deque() tx_hash_deque_append = tx_hash_deque.append for h in tx_hash_list: tx_hash_deque_append(h if isinstance(h, bytes) else s2rh(h)) else: tx_hash_deque = deque(tx_hash_list) c = merkle_tree_depth(len(tx_hash_deque)) m = {c: deque(tx_hash_deque)} while len(tx_hash_deque) > 1: new_deque = deque() new_deque_append = new_deque.append while tx_hash_deque: h1 = tx_hash_deque.popleft() try: h2 = tx_hash_deque.popleft() except: h2 = h1 hs = double_sha256(b"".join((h1, h2))) new_deque_append(hs) tx_hash_deque = new_deque c -= 1 m[c] = deque(tx_hash_deque) if return_hex: for i in m: for k in range(len(m[i])): m[i][k] = rh2s(m[i][k]) return m
def merkle_branches(tx_hash_list, hex=True): """ Calculate merkle branches for coinbase transacton :param tx_hash_list: list of transaction hashes in bytes or HEX encoded string. :param hex: (optional) If set to True return result in HEX format, by default is True. :return: list of merkle branches in bytes or HEX encoded string corresponding hex flag. """ tx_hash_list = [h if isinstance(h, bytes) else s2rh(h) for h in tx_hash_list] branches = [] if len(tx_hash_list) == 1: return [] tx_hash_list.pop(0) while True: branches.append(tx_hash_list.pop(0)) new_hash_list = list() while tx_hash_list: h1 = tx_hash_list.pop(0) try: h2 = tx_hash_list.pop(0) except: h2 = h1 new_hash_list.append(double_sha256(h1 + h2)) if len(new_hash_list) > 1: tx_hash_list = new_hash_list else: if new_hash_list: branches.append(new_hash_list.pop(0)) return branches if not hex else [h.hex() for h in branches]
def calculate_commitment(self, witness_reserved_value): # print("calculate_commitment") wtxid_list = [b"\x00" * 32,] if self.transactions: for tx in self.transactions: wtxid_list.append(s2rh(tx["hash"])) # print("wtxid_list", wtxid_list) # print("wtxid_list", wtxid_list) # print("commitment ", double_sha256(merkle_root_double_sha256(wtxid_list, return_hex=0) + witness_reserved_value)) return double_sha256(merkle_root_double_sha256(wtxid_list, return_hex=0) + witness_reserved_value)
def scan_tx_list(self): self.coinbasevalue = self.block_reward self.sigop = 0 self.weight = 0 self.txid_list = list() for tx in self.transactions: txid = s2rh(tx["txid"]) self.coinbasevalue += tx["fee"] self.weight += tx["weight"] self.sigop += tx["sigops"] self.txid_list.append(txid)
def build_orphan(self, hash, ntime): self.previous_block_hash = hexlify(reverse_hash(s2rh(hash))).decode() self.time = hexlify(ntime.to_bytes(4, "big")).decode() self.height += 1 self.transactions = list() self.txid_list = list() self.scan_tx_list() self.coinbase_tx = self.create_coinbase_transaction() self.coinb1, self.coinb2 = self.split_coinbase() self.target = bits_to_target(self.bits) self.difficulty = target_to_difficulty(self.target) self.merkle_branches = [i for i in merkle_branches([self.coinbase_tx["txId"], ] + self.txid_list)]
def merkle_root_from_proof(merkle_proof, tx_id, index, return_hex=True, receive_hex=True): if isinstance(merkle_proof, str): merkle_proof = bytes_from_hex(merkle_proof) if isinstance(merkle_proof, bytes): merkle_proof = [merkle_proof[y - 32:y] for y in range(32, len(merkle_proof) + 32, 32)] if receive_hex: _merkle_proof = deque() _merkle_proof_append = _merkle_proof.append for h in merkle_proof: _merkle_proof_append(s2rh(h) if isinstance(h, str) else h) merkle_proof = _merkle_proof tx_id = s2rh(tx_id) if isinstance(tx_id, str) else tx_id root = tx_id for h in merkle_proof: root = double_sha256(b"".join((h, root) if index % 2 else (root, h))) index = index // 2 if return_hex: return rh2s(root) return root
def submit_job(self, extra_nonce_1, extra_nonce_2, nonce, time): version = s2rh(self.version) prev_hash = s2rh_step4(self.previous_block_hash) cb = self.coinb1 + extra_nonce_1 + extra_nonce_2 + self.coinb2 time = s2rh(time) bits = s2rh(self.bits) nonce = s2rh(nonce) c = Transaction(cb) cbh = s2rh(c["txId"]) merkle_root = merkle_root_from_branches(self.merkle_branches, cbh) # print("version ", version.hex()) # print("prev_hash ", self.previous_block_hash) # print("cbh ", cbh.hex()) # print("cbh2 ", s2rh(c["txId"])) # print("merkle_root ", merkle_root.hex()) # print("merkle_root ", s2rh(c["txId"])) # print("branches ", self.merkle_branches) header = version + prev_hash + merkle_root + time + bits + nonce block = hexlify(header).decode() block += hexlify(int_to_var_int(len (self.transactions) + 1)).decode() block += cb for t in self.transactions: block += t["data"] return double_sha256(header,1), block