예제 #1
0
def sign_message(msg, private_key, hex=True):
        """
        Sign message

        :param msg:  message to sign  bytes or HEX encoded string.
        :param private_key:  private key (bytes, hex encoded string or WIF format)
        :param hex:  (optional) If set to True return key in HEX format, by default is True.
        :return:  DER encoded signature in bytes or HEX encoded string.
        """
        if isinstance(msg, bytearray):
            msg = bytes(msg)
        if isinstance(msg, str):
            try:
                msg = bytes_from_hex(msg)
            except:
                pass
        if not isinstance(msg, bytes):
            raise TypeError("message must be a bytes or hex encoded string")

        if isinstance(private_key, bytearray):
            private_key = bytes(private_key)
        if isinstance(private_key, str):
            try:
                private_key = bytes_from_hex(private_key)
            except:
                if is_wif_valid(private_key):
                    private_key = wif_to_private_key(private_key, hex=False)
        if not isinstance(private_key, bytes):
            raise TypeError("private key must be a bytes, hex encoded string or in WIF format")

        signature = __secp256k1_ecdsa_sign__(msg, private_key)
        return signature.hex() if hex else signature
예제 #2
0
def public_key_recovery(signature, messsage, rec_id, compressed=True, hex=True):
    if isinstance(signature, str):
        signature = bytes_from_hex(signature)
    if isinstance(messsage, str):
        messsage = bytes_from_hex(messsage)

    pub = __secp256k1_ecdsa_recover__(signature, messsage, rec_id, compressed)
    if isinstance(pub, int):
        if pub == 0:
            return None
        else:
            raise RuntimeError("signature recovery error %s" % pub)
    return pub.hex() if hex else pub
예제 #3
0
파일: block.py 프로젝트: madnadyka/pybfl
def merkle_root_from_branches(merkle_branches, coinbase_hash, hex=True):
    """
    Calculate merkle root from merkle branches and coinbase transacton hash
    :param merkle_branches: list merkle branches in bytes or HEX encoded string.
    :param coinbase_hash: list coinbase transaction hash in bytes or HEX encoded string.
    :param hex:  (optional) If set to True return result in HEX format, by default is True.
    :return: merkle root in bytes or HEX encoded string corresponding hex flag.
    """
    merkle_root = coinbase_hash if not isinstance(coinbase_hash, str) else bytes_from_hex(coinbase_hash)
    for h in merkle_branches:
        if type(h) == str:
            h = bytes_from_hex(h)
        merkle_root = double_sha256(merkle_root + h)
    return bytes_from_hex(merkle_root) if not hex else merkle_root
예제 #4
0
def hash_to_script(address_hash, script_type, hex=False):
    """
    Get public key script from hash.

    :param address: h in base58 or bech32 format.
    :param hex:  (optional) If set to True return key in HEX format, by default is True.
    :return: public key script in HEX or bytes string.
    """
    if isinstance(address_hash, str):
        address_hash = bytes_from_hex(address_hash)
    if not isinstance(address_hash, bytes):
        raise TypeError("address hash must be HEX encoded string or bytes")

    if script_type == 1:
        s = [OP_HASH160, b'\x14', address_hash, OP_EQUAL]
    elif script_type == 0:
        s = [
            OP_DUP, OP_HASH160, b'\x14', address_hash, OP_EQUALVERIFY,
            OP_CHECKSIG
        ]
    elif script_type in (5, 6):
        s = [OP_0, bytes([len(address_hash)]), address_hash]
    else:
        raise ValueError("address type invalid")
    s = b''.join(s)
    return s.hex() if hex else s
예제 #5
0
파일: address.py 프로젝트: madnadyka/pybfl
    def __init__(self, key, compressed=True, testnet=False):
        if isinstance(key, str):
            try:
                key = bytes_from_hex(key)
            except:
                key = PrivateKey(key)

        if isinstance(key, bytes):
            if len(key) == 32:
                key = PrivateKey(key, compressed=compressed, testnet=testnet)
            elif is_public_key_valid(key):
                public_key = key
                self.testnet = testnet
                self.compressed = True if len(key) == 33 else False
            else:
                raise TypeError("key invalid")

        if isinstance(key, PrivateKey):
            #: flag for testnet network private key  (boolean)
            self.testnet = key.testnet
            #: flag for compressed type of corresponding public key (boolean)
            self.compressed = key.compressed
            public_key = private_to_public_key(key.key,
                                               compressed=key.compressed,
                                               hex=False)

        #: public key in  bytes (bytes)
        self.key = public_key
        #: public key in HEX (string)
        self.hex = self.key.hex()
예제 #6
0
def hash_to_address(address_hash,
                    testnet=False,
                    script_hash=False,
                    witness_version=0):
    """
    Get address from public key/script hash. In case PUBKEY, P2PKH, P2PKH public key/script hash is SHA256+RIPEMD160,
    P2WSH script hash is SHA256.


    :param address_hash: public key hash or script hash in HEX or bytes string format.
    :param testnet: (optional) flag for testnet network, by default is False.
    :param script_hash: (optional) flag for script hash (P2SH address), by default is False.
    :param witness_version: (optional) witness program version, by default is 0, for legacy
                            address format use None.
    :return: address in base58 or bech32 format.
    """
    if isinstance(address_hash, str):
        address_hash = bytes_from_hex(address_hash)
    if not isinstance(address_hash, bytes):
        raise TypeError("address hash must be HEX encoded string or bytes")

    if not script_hash:
        if witness_version is None:
            if len(address_hash) != 20:
                raise ValueError("address hash length incorrect")
            if testnet:
                prefix = TESTNET_ADDRESS_BYTE_PREFIX
            else:
                prefix = MAINNET_ADDRESS_BYTE_PREFIX
            address_hash = b"%s%s" % (prefix, address_hash)
            address_hash += double_sha256(address_hash)[:4]
            return encode_base58(address_hash)
        else:
            if len(address_hash) not in (20, 32):
                raise ValueError("address hash length incorrect")

    if witness_version is None:
        if testnet:
            prefix = TESTNET_SCRIPT_ADDRESS_BYTE_PREFIX
        else:
            prefix = MAINNET_SCRIPT_ADDRESS_BYTE_PREFIX
        address_hash = b"%s%s" % (prefix, address_hash)
        address_hash += double_sha256(address_hash)[:4]
        return encode_base58(address_hash)

    if testnet:
        prefix = TESTNET_SEGWIT_ADDRESS_BYTE_PREFIX
        hrp = TESTNET_SEGWIT_ADDRESS_PREFIX
    else:
        prefix = MAINNET_SEGWIT_ADDRESS_BYTE_PREFIX
        hrp = MAINNET_SEGWIT_ADDRESS_PREFIX

    address_hash = b"%s%s" % (witness_version.to_bytes(
        1, "big"), rebase_8_to_5(address_hash))
    checksum = bech32_polymod(b"%s%s%s" % (prefix, address_hash, b"\x00" * 6))
    checksum = rebase_8_to_5(checksum.to_bytes(5, "big"))[2:]
    return "%s1%s" % (hrp, rebase_5_to_32(address_hash + checksum).decode())
예제 #7
0
파일: block.py 프로젝트: madnadyka/pybfl
def bits_to_target(bits):
    """
    Calculate target from bits

    :param bits: HEX string, bytes string or integer representation of bits.
    :return: integer.
    """
    if type(bits) == str:
        bits = bytes_from_hex(bits)
    if type(bits) == bytes:
        return int_from_bytes(bits[1:], 'big') * (2 ** (8 * (bits[0] - 3)))
    else:
        shift = bits >> 24
        target = (bits & 0xffffff) * (1 << (8 * (shift - 3)))
        return target
예제 #8
0
def script_to_hash(script, witness=False, hex=True):
    """
    Encode script to hash HASH160 or SHA256 in dependency of the witness.

    :param script: script in bytes or HEX encoded string.
    :param witness:  (optional) If set to True return SHA256 hash for P2WSH, by default is False.
    :param hex:  (optional) If set to True return key in HEX format, by default is True.
    :param sub_script:  sub_script which is necessary to remove from target script in bytes or HEX encoded string.
    :return: script in bytes or HEX encoded string corresponding to the format of target script.
    """
    if isinstance(script, str):
        s = bytes_from_hex(script)
    if witness:
        return sha256(script, hex)
    else:
        return hash160(script, hex)
예제 #9
0
파일: address.py 프로젝트: madnadyka/pybfl
    def __init__(self, key=None, compressed=True, testnet=False):

        if key is None:

            #: flag for compressed type of corresponding public key (boolean)
            self.compressed = compressed
            #: flag for testnet network private key  (boolean)
            self.testnet = testnet

            #: private key in  bytes (bytes)
            self.key = create_private_key(wif=False)
            #: private key in HEX (string)
            self.hex = self.key.hex()
            #: private key in WIF format (string)
            self.wif = private_key_to_wif(self.key, compressed, testnet)

        else:
            if isinstance(key, str):
                try:
                    key = bytes_from_hex(key)
                except:
                    pass
            if isinstance(key, bytes):
                if len(key) != 32:
                    raise TypeError("private key invalid length")
                self.key = key
                self.compressed = compressed
                self.testnet = testnet
                self.hex = self.key.hex()
                self.wif = private_key_to_wif(self.key, compressed, testnet)
                return
            if not isinstance(key, str):
                raise TypeError("private key invalid")
            self.key = wif_to_private_key(key, hex=False)
            self.hex = self.key.hex()
            if key[0] in (MAINNET_PRIVATE_KEY_UNCOMPRESSED_PREFIX,
                          TESTNET_PRIVATE_KEY_UNCOMPRESSED_PREFIX):
                self.compressed = False
            else:
                self.compressed = True
            self.testnet = True if key[0] in (TESTNET_PRIVATE_KEY_UNCOMPRESSED_PREFIX,
                                              TESTNET_PRIVATE_KEY_COMPRESSED_PREFIX) else False

            self.wif = key
예제 #10
0
파일: block.py 프로젝트: madnadyka/pybfl
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
예제 #11
0
def delete_from_script(script, sub_script):
    """
    Decode OP_CODE or subscript from script.

    :param script: target script in bytes or HEX encoded string.
    :param sub_script:  sub_script which is necessary to remove from target script in bytes or HEX encoded string.
    :return: script in bytes or HEX encoded string corresponding to the format of target script.
    """
    if not sub_script:
        return script
    s_hex = False
    if isinstance(script, str):
        try:
            script = bytes_from_hex(script)
            s_hex = True
        except:
            pass
    if isinstance(sub_script, str):
        try:
            sub_script = bytes_from_hex(sub_script)
        except:
            pass

    if not isinstance(script, bytes):
        raise TypeError("script invalid")
    if not isinstance(sub_script, bytes):
        raise TypeError("sub_script invalid")

    l = len(script)
    ls = len(sub_script)
    s = 0
    k = 0
    stack = []
    stack_append = stack.append
    result = []
    result_append = result.append
    while l - s > 0:
        if script[s] < 0x4c and script[s]:
            stack_append(script[s] + 1)
            s += script[s] + 1
        elif script[s] == OPCODE["OP_PUSHDATA1"]:
            stack_append(1 + script[s + 1])
            s += 1 + script[s + 1]
        elif script[s] == OPCODE["OP_PUSHDATA2"]:
            stack_append(2 + unpack('<H', script[s: s + 2])[0])
            s += 2 + unpack('<H', script[s: s + 2])[0]
        elif script[s] == OPCODE["OP_PUSHDATA4"]:
            stack_append(4 + unpack('<L', script[s: s + 4])[0])
            s += 4 + unpack('<L', script[s: s + 4])[0]
        else:
            stack_append(1)
            s += 1
        if s - k >= ls:
            if script[k:s][:ls] == sub_script:
                if s - k > ls:
                    result_append(script[k + ls:s])
                t = 0
                while t != s - k:
                    t += stack.pop(0)
                k = s
            else:
                t = stack.pop(0)
                result_append(script[k:k + t])
                k += t
    if script[k:s][:ls] == sub_script:
        if s - k > ls:
            result_append(script[k + ls:s])
    else:
        result_append(script[k:k + ls])

    return b''.join(result) if not s_hex else b''.join(result).hex()
예제 #12
0
def parse_script(script, segwit=True):
    """
    Parse script and return script type, script address and required signatures count.

    :param script: script in bytes string or HEX encoded string format.
    :param segwit:  (optional) If set to True recognize P2WPKH and P2WSH sripts, by default set to True.

    :return: dictionary:

            - nType - numeric script type
            - type  - script type
            - addressHash - address hash in case address recognized
            - script - script if no address recognized
            - reqSigs - required signatures count
    """
    if not script:
        return {"nType": 7, "type": "NON_STANDARD", "reqSigs": 0, "script": b""}
    if isinstance(script, str):
        try:
            script = bytes_from_hex(script)
        except:
            raise ValueError("hex encoded string required")
    l = len(script)
    if segwit:
        if l == 22 and script[0] == 0:
            return {"nType": 5, "type": "P2WPKH", "reqSigs": 1, "addressHash": script[2:]}
        if l == 34 and script[0] == 0:
            return {"nType": 6, "type": "P2WSH", "reqSigs": None, "addressHash": script[2:]}
    if l == 25 and \
       script[:2] == b"\x76\xa9" and \
       script[-2:] == b"\x88\xac":
        return {"nType": 0, "type": "P2PKH", "reqSigs": 1, "addressHash": script[3:-2]}
    if l == 23 and \
       script[0] == 169 and \
       script[-1] == 135:
        return {"nType": 1, "type": "P2SH", "reqSigs": None, "addressHash": script[2:-1]}
    if l == 67 and script[-1] == 172:
        return {"nType": 2, "type": "PUBKEY", "reqSigs": 1, "addressHash": hash160(script[1:-1])}
    if l == 35 and script[-1] == 172:
        return {"nType": 2, "type": "PUBKEY", "reqSigs": 1, "addressHash": hash160(script[1:-1])}
    if script[0] == OPCODE["OP_RETURN"]:
        if l == 1:
            return {"nType": 3, "type": "NULL_DATA", "reqSigs": 0, "data": b""}
        elif script[1] < OPCODE["OP_PUSHDATA1"]:
            if script[1] == l - 2:
                return {"nType": 3, "type": "NULL_DATA", "reqSigs": 0, "data": script[2:]}
        elif script[1] == OPCODE["OP_PUSHDATA1"]:
            if l > 2:
                if script[2] == l - 3 and script[2] <= 80:
                    return {"nType": 3, "type": "NULL_DATA", "reqSigs": 0, "data": script[3:]}
        return {"nType": 8, "type": "NULL_DATA_NON_STANDARD", "reqSigs": 0, "script": script}
    if script[0] >= 81 and script[0] <= 96:
        if script[-1] == 174:
            if script[-2] >= 81 and script[-2] <= 96:
                if script[-2] >= script[0]:
                    c, s = 0, 1
                    while l - 2 - s > 0:
                        if script[s] < 0x4c:
                            s += script[s]
                            c += 1
                        else:
                            c = 0
                            break
                        s += 1
                    if c == script[-2] - 80:
                        return {"nType": 4, "type": "MULTISIG", "reqSigs": script[0] - 80,
                                "pubKeys": c, "script": script}

    s, m, n, last, req_sigs = 0, 0, 0, 0, 0
    while l - s > 0:
        if script[s] >= 81 and script[s] <= 96:
            if not n:
                n = script[s] - 80
            else:
                if m == 0:
                    n, m = script[s] - 80, 0
                elif n > m:
                    n, m = script[s] - 80, 0
                elif m == script[s] - 80:
                    last = 0 if last else 2
        elif script[s] < 0x4c:
            s += script[s]
            m += 1
            if m > 16:
                n, m = 0, 0
        elif script[s] == OPCODE["OP_PUSHDATA1"]:
            try:
                s += 1 + script[s + 1]
            except:
                break
        elif script[s] == OPCODE["OP_PUSHDATA2"]:
            try:
                s += 2 + unpack('<H', script[s: s + 2])[0]
            except:
                break
        elif script[s] == OPCODE["OP_PUSHDATA4"]:
            try:
                s += 4 + unpack('<L', script[s: s + 4])[0]
            except:
                break
        else:
            if script[s] == OPCODE["OP_CHECKSIG"]:
                req_sigs += 1
            elif script[s] == OPCODE["OP_CHECKSIGVERIFY"]:
                req_sigs += 1
            elif script[s] in (OPCODE["OP_CHECKMULTISIG"], OPCODE["OP_CHECKMULTISIGVERIFY"]):
                if last:
                    req_sigs += n
                else:
                    req_sigs += 20
            n, m = 0, 0
        if last:
            last -= 1
        s += 1
    return {"nType": 7, "type": "NON_STANDARD", "reqSigs": req_sigs, "script": script}
예제 #13
0
def decode_script(script, asm=False):
    """
    Decode script to ASM format or to human readable OPCODES string.

    :param script: script in bytes string or HEX encoded string format.
    :param asm:  (optional) If set to True decode to ASM format, by default set to False.
    :return: script in ASM format string or OPCODES string.
    """

    if isinstance(script, str):
        try:
            script = bytes_from_hex(script)
        except:
            pass
    if not isinstance(script, bytes):
        raise TypeError("script invalid")
    l = len(script)
    s = 0
    result = []
    append = result.append
    try:
        while l - s > 0:
            if script[s] < 0x4c and script[s]:
                if asm:
                    append("OP_PUSHBYTES[%s]" % script[s] )
                    append(script[s + 1:s + 1 + script[s]].hex())
                else:
                    append('[%s]' % script[s])
                s += script[s] + 1
                continue

            if script[s] == OPCODE["OP_PUSHDATA1"]:
                if asm:
                    ld = script[s + 1]
                    append("OP_PUSHDATA1[%s]" % ld)
                    append(script[s + 2:s + 2 + ld].hex())
                else:
                    append(RAW_OPCODE[script[s]])
                    ld = script[s + 1]
                    append('[%s]' % ld)
                s += 1 + script[s + 1] + 1
            elif script[s] == OPCODE["OP_PUSHDATA2"]:
                if asm:

                    ld = unpack('<H', script[s + 1: s + 3])[0]
                    append("OP_PUSHDATA2[%s]" % ld)
                    append(script[s + 3:s + 3 + ld].hex())
                else:
                    ld = unpack('<H', script[s + 1: s + 3])[0]
                    append(RAW_OPCODE[script[s]])
                    append('[%s]' % ld)
                s += 2 + 1 + ld
            elif script[s] == OPCODE["OP_PUSHDATA4"]:
                if asm:
                    ld = unpack('<L', script[s + 1: s + 5])[0]
                    append("OP_PUSHDATA4[%s]" % ld)
                    append(script[s + 5:s + 5 + ld].hex())
                else:
                    ld = unpack('<L', script[s + 1: s + 5])[0]
                    append(RAW_OPCODE[script[s]])
                    append('[%s]' % ld)
                s += 5 + 1 + ld
            else:
                append(RAW_OPCODE[script[s]])
                s += 1
    except:
        append("[SCRIPT_DECODE_FAILED]")
    return ' '.join(result)
예제 #14
0
def public_key_to_pubkey_script(key, hex=True):
    if isinstance(key, str):
        key = bytes_from_hex(key)
    s = b"%s%s%s" % (bytes([len(key)]), key, OP_CHECKSIG)
    return s.hex() if hex else s