def is_bech32(address): if address.startswith('bc') or address.startswith('tb'): # Should check if it's valid bech32 data try: b32data = CBech32Data(address) return True except: return False else: return False
def address(self): """Returns the encoded representation of this address. If SegWit, it's encoded using bech32, otherwise using base58 """ if self._address is None: if self.type != "bech32": version = b'\x00' if self.type == "normal" else b'\x05' checksum = double_sha256(version + self.hash) self._address = base58.encode(version + self.hash + checksum[:4]) else: bech_encoded = CBech32Data.from_bytes(self._segwit_version, self._hash) self._address = str(bech_encoded) return self._address
def get_p2w_script(address): # Construct script. scripthash = bytes(CBech32Data(address)) if len(scripthash) == 20: # P2WPKH encoding tx_script = OP_0 tx_script += b'\x14' tx_script += scripthash witness_script = OP_HASH160 witness_script += op_push(len(scripthash)) witness_script += scripthash witness_script += OP_EQUAL return (witness_script, tx_script) elif len(scripthash) == 32: # P2WSH encoding raise Exception('P2WSH encoding not yet supported')
def serialise(encoding, inputs, destination_outputs, data_output=None, change_output=None, dust_return_pubkey=None): s = (1).to_bytes(4, byteorder='little') # Version use_segwit = False for i in range(len(inputs)): txin = inputs[i] spk = txin['scriptPubKey'] if spk[0:2] == '00': # Witness version 0 datalen = binascii.unhexlify(spk[2:4])[0] if datalen == 20 or datalen == 32: # 20 is for P2WPKH and 32 is for P2WSH use_segwit = True s = (2).to_bytes(4, byteorder='little') # Rewrite version break if use_segwit: s += b'\x00' # marker s += b'\x01' # flag # Number of inputs. s += var_int(int(len(inputs))) witness_txins = [] witness_data = {} # List of Inputs. for i in range(len(inputs)): txin = inputs[i] this_is_segwit = False witness_program = None if use_segwit: spk = txin['scriptPubKey'] witver = binascii.unhexlify(spk[0:2])[0] datalen = binascii.unhexlify(spk[2:4])[0] if witver == 0 and (datalen == 20 or datalen == 32): witprog = binascii.unhexlify(spk[4:]) address = str((CBech32Data.from_bytes(witver, witprog))) witness_data[address] = [] witness_txins.append(address) this_is_segwit = True witness_program = witprog else: witness_txins.append(None) s += binascii.unhexlify(bytes(txin['txid'], 'utf-8'))[::-1] # TxOutHash s += txin['vout'].to_bytes(4, byteorder='little') # TxOutIndex if this_is_segwit: tx_script = b'\x00' + bytes(chr(len(witness_program)), 'utf8') + witness_program else: tx_script = binascii.unhexlify(bytes(txin['scriptPubKey'], 'utf-8')) s += var_int(int(len(tx_script))) # Script length s += tx_script # Script s += b'\xff' * 4 # Sequence # Number of outputs. n = 0 n += len(destination_outputs) if data_output: data_array, value = data_output for data_chunk in data_array: n += 1 else: data_array = [] if change_output: n += 1 s += var_int(n) # Destination output. for destination, value in destination_outputs: s += value.to_bytes(8, byteorder='little') # Value tx_script, witness_script = get_script(destination) #if use_segwit and destination in witness_data: # We will need this for P2WSH # witness_data[destination].append(witness_script) # tx_script = witness_script if witness_script: tx_script = witness_script s += var_int(int(len(tx_script))) # Script length s += tx_script # Data output. for data_chunk in data_array: data_array, value = data_output s += value.to_bytes(8, byteorder='little') # Value data_chunk = config.PREFIX + data_chunk # Initialise encryption key (once per output). key = arc4.init_arc4( inputs[0]['txid']) # Arbitrary, easy‐to‐find, unique key. if encoding == 'multisig': assert dust_return_pubkey # Get data (fake) public key. pad_length = (33 * 2) - 1 - 2 - 2 - len(data_chunk) assert pad_length >= 0 data_chunk = bytes([len(data_chunk) ]) + data_chunk + (pad_length * b'\x00') data_chunk = key.encrypt(data_chunk) data_pubkey_1 = make_fully_valid(data_chunk[:31]) data_pubkey_2 = make_fully_valid(data_chunk[31:]) # Construct script. tx_script = OP_1 # OP_1 tx_script += op_push( 33) # Push bytes of data chunk (fake) public key (1/2) tx_script += data_pubkey_1 # (Fake) public key (1/2) tx_script += op_push( 33) # Push bytes of data chunk (fake) public key (2/2) tx_script += data_pubkey_2 # (Fake) public key (2/2) tx_script += op_push( len(dust_return_pubkey)) # Push bytes of source public key tx_script += dust_return_pubkey # Source public key tx_script += OP_3 # OP_3 tx_script += OP_CHECKMULTISIG # OP_CHECKMULTISIG elif encoding == 'opreturn': data_chunk = key.encrypt(data_chunk) tx_script = OP_RETURN # OP_RETURN tx_script += op_push(len( data_chunk)) # Push bytes of data chunk (NOTE: OP_SMALLDATA?) tx_script += data_chunk # Data elif encoding == 'pubkeyhash': pad_length = 20 - 1 - len(data_chunk) assert pad_length >= 0 data_chunk = bytes([len(data_chunk) ]) + data_chunk + (pad_length * b'\x00') data_chunk = key.encrypt(data_chunk) # Construct script. tx_script = OP_DUP # OP_DUP tx_script += OP_HASH160 # OP_HASH160 tx_script += op_push(20) # Push 0x14 bytes tx_script += data_chunk # (Fake) pubKeyHash tx_script += OP_EQUALVERIFY # OP_EQUALVERIFY tx_script += OP_CHECKSIG # OP_CHECKSIG else: raise exceptions.TransactionError('Unknown encoding‐scheme.') s += var_int(int(len(tx_script))) # Script length s += tx_script # Change output. if change_output: change_address, change_value = change_output s += change_value.to_bytes(8, byteorder='little') # Value tx_script, witness_script = get_script(change_address) if use_segwit and change_address in witness_data: witness_data[change_address].append(witness_script) tx_script = witness_script s += var_int(int(len(tx_script))) # Script length s += tx_script if use_segwit: for address in witness_txins: if address is None: s += var_int(int(0)) else: empty_witness = [b'\x00\x00\x00\x00', b'\x00\x00\x00\x00'] s += var_int(int(len(empty_witness))) # Script length for item in empty_witness: s += var_int(int(len(item))) s += item s += (0).to_bytes(4, byteorder='little') # LockTime return s
def bech32_to_scripthash(address): bech32 = CBech32Data(address) return bytes(bech32)
def pubkey_to_p2whash(pubkey): """Convert public key to PayToWitness.""" pubkeyhash = hash160(pubkey) pubkey = CBech32Data.from_bytes(0, pubkeyhash) return str(pubkey)
def is_bech32(address): try: b32data = CBech32Data(address) return True except: return False
def tobechaddress(s): """ convert bytes to bech32 address """ return CBech32BitcoinAddress.from_bytes(0, CBech32Data(s))
def serialise (encoding, inputs, destination_outputs, data_output=None, change_output=None, dust_return_pubkey=None): s = (1).to_bytes(4, byteorder='little') # Version use_segwit = False for i in range(len(inputs)): txin = inputs[i] spk = txin['scriptPubKey'] if spk[0:2] == '00': # Witness version 0 datalen = binascii.unhexlify(spk[2:4])[0] if datalen == 20 or datalen == 32: # 20 is for P2WPKH and 32 is for P2WSH use_segwit = True s = (2).to_bytes(4, byteorder='little') # Rewrite version break if use_segwit: s += b'\x00' # marker s += b'\x01' # flag # Number of inputs. s += var_int(int(len(inputs))) witness_txins = [] witness_data = {} # List of Inputs. for i in range(len(inputs)): txin = inputs[i] this_is_segwit = False witness_program = None if use_segwit: spk = txin['scriptPubKey'] witver = binascii.unhexlify(spk[0:2])[0] datalen = binascii.unhexlify(spk[2:4])[0] if witver == 0 and (datalen == 20 or datalen == 32): witprog = binascii.unhexlify(spk[4:]) address = str((CBech32Data.from_bytes(witver, witprog))) witness_data[address] = [] witness_txins.append(address) this_is_segwit = True witness_program = witprog else: witness_txins.append(None) s += binascii.unhexlify(bytes(txin['txid'], 'utf-8'))[::-1] # TxOutHash s += txin['vout'].to_bytes(4, byteorder='little') # TxOutIndex if this_is_segwit: tx_script = b'\x00' + bytes(chr(len(witness_program)), 'utf8') + witness_program else: tx_script = binascii.unhexlify(bytes(txin['scriptPubKey'], 'utf-8')) s += var_int(int(len(tx_script))) # Script length s += tx_script # Script s += b'\xff' * 4 # Sequence # Number of outputs. n = 0 n += len(destination_outputs) if data_output: data_array, value = data_output for data_chunk in data_array: n += 1 else: data_array = [] if change_output: n += 1 s += var_int(n) # Destination output. for destination, value in destination_outputs: s += value.to_bytes(8, byteorder='little') # Value tx_script, witness_script = get_script(destination) #if use_segwit and destination in witness_data: # We will need this for P2WSH # witness_data[destination].append(witness_script) # tx_script = witness_script if witness_script: tx_script = witness_script s += var_int(int(len(tx_script))) # Script length s += tx_script # Data output. for data_chunk in data_array: data_array, value = data_output s += value.to_bytes(8, byteorder='little') # Value data_chunk = config.PREFIX + data_chunk # Initialise encryption key (once per output). key = arc4.init_arc4(inputs[0]['txid']) # Arbitrary, easy‐to‐find, unique key. if encoding == 'multisig': assert dust_return_pubkey # Get data (fake) public key. pad_length = (33 * 2) - 1 - 2 - 2 - len(data_chunk) assert pad_length >= 0 data_chunk = bytes([len(data_chunk)]) + data_chunk + (pad_length * b'\x00') data_chunk = key.encrypt(data_chunk) data_pubkey_1 = make_fully_valid(data_chunk[:31]) data_pubkey_2 = make_fully_valid(data_chunk[31:]) # Construct script. tx_script = OP_1 # OP_1 tx_script += op_push(33) # Push bytes of data chunk (fake) public key (1/2) tx_script += data_pubkey_1 # (Fake) public key (1/2) tx_script += op_push(33) # Push bytes of data chunk (fake) public key (2/2) tx_script += data_pubkey_2 # (Fake) public key (2/2) tx_script += op_push(len(dust_return_pubkey)) # Push bytes of source public key tx_script += dust_return_pubkey # Source public key tx_script += OP_3 # OP_3 tx_script += OP_CHECKMULTISIG # OP_CHECKMULTISIG elif encoding == 'opreturn': data_chunk = key.encrypt(data_chunk) tx_script = OP_RETURN # OP_RETURN tx_script += op_push(len(data_chunk)) # Push bytes of data chunk (NOTE: OP_SMALLDATA?) tx_script += data_chunk # Data elif encoding == 'pubkeyhash': pad_length = 20 - 1 - len(data_chunk) assert pad_length >= 0 data_chunk = bytes([len(data_chunk)]) + data_chunk + (pad_length * b'\x00') data_chunk = key.encrypt(data_chunk) # Construct script. tx_script = OP_DUP # OP_DUP tx_script += OP_HASH160 # OP_HASH160 tx_script += op_push(20) # Push 0x14 bytes tx_script += data_chunk # (Fake) pubKeyHash tx_script += OP_EQUALVERIFY # OP_EQUALVERIFY tx_script += OP_CHECKSIG # OP_CHECKSIG else: raise exceptions.TransactionError('Unknown encoding‐scheme.') s += var_int(int(len(tx_script))) # Script length s += tx_script # Change output. if change_output: change_address, change_value = change_output s += change_value.to_bytes(8, byteorder='little') # Value tx_script, witness_script = get_script(change_address) if use_segwit and change_address in witness_data: witness_data[change_address].append(witness_script) tx_script = witness_script s += var_int(int(len(tx_script))) # Script length s += tx_script if use_segwit: for address in witness_txins: if address is None: s += var_int(int(0)) else: empty_witness = [b'\x00\x00\x00\x00', b'\x00\x00\x00\x00'] s += var_int(int(len(empty_witness))) # Script length for item in empty_witness: s += var_int(int(len(item))) s += item s += (0).to_bytes(4, byteorder='little') # LockTime return s