Exemplo n.º 1
0
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
Exemplo n.º 2
0
    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
Exemplo n.º 3
0
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')
Exemplo n.º 4
0
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
Exemplo n.º 5
0
def bech32_to_scripthash(address):
    bech32 = CBech32Data(address)
    return bytes(bech32)
Exemplo n.º 6
0
def pubkey_to_p2whash(pubkey):
    """Convert public key to PayToWitness."""
    pubkeyhash = hash160(pubkey)
    pubkey = CBech32Data.from_bytes(0, pubkeyhash)
    return str(pubkey)
Exemplo n.º 7
0
def is_bech32(address):
    try:
        b32data = CBech32Data(address)
        return True
    except:
        return False
Exemplo n.º 8
0
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