Exemple #1
0
def public_key_to_address(pubkey, testnet=False, p2sh_p2wpkh=False, witness_version=0, regtest=False):
    """
    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 pubkey: public key HEX or bytes string format.
    :param testnet: (optional) flag for testnet network, by default is False.
    :param p2sh_p2wpkh: (optional) flag for P2WPKH inside 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.
    """
    pubkey = get_bytes(pubkey, encoding='hex')
    if p2sh_p2wpkh:
        if len(pubkey) != 33:
            raise ValueError("public key invalid")
        h = hash160(b'\x00\x14%s' % hash160(pubkey))
        witness_version = None
    else:
        if witness_version is not None:
            if len(pubkey) != 33:
                raise ValueError("public key invalid")
        h = hash160(pubkey)
    return hash_to_address(h, testnet=testnet,
                           script_hash=p2sh_p2wpkh,
                           witness_version=witness_version, regtest=regtest)
Exemple #2
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: hash HASH160 or SHA256 of script in bytes or HEX encoded.
    """
    script = get_bytes(script)
    return sha256(script, hex) if witness else hash160(script, hex)
Exemple #3
0
def derive_child_xpublic_key(xpublic_key, i):
    c = xpublic_key[13:45]
    k = xpublic_key[45:]
    fingerprint = hash160(k)[:4]
    depth = xpublic_key[4] + 1
    if depth > 255:
        raise ValueError("path depth should be <= 255")  # pragma: no cover
    if i >= HARDENED_KEY:
        raise ValueError("derivation from extended public key impossible")
    s = hmac_sha512(c, k + pack(">L", i))
    if int.from_bytes(
            s[:32],
            byteorder='big') >= ECDSA_SEC256K1_ORDER:  # pragma: no cover
        return None

    pk = __secp256k1_ec_pubkey_tweak_add__(k, s[:32])
    if isinstance(pk, int):  # pragma: no cover
        raise RuntimeError("pubkey_tweak_add error %s" % pk)
    return b"".join([
        xpublic_key[:4],
        bytes([depth]), fingerprint,
        pack(">L", i), s[32:], pk
    ])
Exemple #4
0
 def __init__(self,
              script,
              testnet=False,
              witness_version=0,
              regtest=False):
     self.witness_version = witness_version
     self.testnet = testnet
     self.regtest = regtest
     if isinstance(script, str):
         script = bytes.fromhex(script)
     self.script = script
     self.script_hex = self.script.hex()
     if witness_version is None:
         self.hash = hash160(self.script)
     else:
         self.hash = sha256(self.script)
     self.script_opcodes = decode_script(self.script)
     self.script_opcodes_asm = decode_script(self.script, 1)
     self.address = hash_to_address(self.hash,
                                    script_hash=True,
                                    witness_version=self.witness_version,
                                    testnet=self.testnet,
                                    regtest=self.regtest)
Exemple #5
0
def derive_child_xprivate_key(xprivate_key, i):
    c = xprivate_key[13:45]
    k = xprivate_key[45:]
    depth = xprivate_key[4] + 1

    if depth > 255:
        raise ValueError("path depth should be <= 255")  # pragma: no cover
    pub = private_to_public_key(k[1:], hex=False)
    fingerprint = hash160(pub)[:4]
    s = hmac_sha512(c,
                    b"%s%s" % (k if i >= HARDENED_KEY else pub, pack(">L", i)))
    p_int = int.from_bytes(s[:32], byteorder='big')
    if p_int >= ECDSA_SEC256K1_ORDER:  # pragma: no cover
        return None
    k_int = (int.from_bytes(k[1:], byteorder='big') +
             p_int) % ECDSA_SEC256K1_ORDER
    if not k_int:  # pragma: no cover
        return None
    key = int.to_bytes(k_int, byteorder="big", length=32)
    return b"".join([
        xprivate_key[:4],
        bytes([depth]), fingerprint,
        pack(">L", i), s[32:], b'\x00', key
    ])
Exemple #6
0
def public_key_to_p2sh_p2wpkh_script(pubkey, hex=False):
    pubkey = get_bytes(pubkey)
    if len(pubkey) != 33:
        raise ValueError("public key len invalid")
    r = b'\x00\x14%s' % hash160(pubkey)
    return r.hex() if hex else r
Exemple #7
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 is 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""
        }
    script = get_bytes(script)
    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:
        # OP_1 -> OP_16
        if script[s] >= 81 and script[s] <= 96:
            if not n:
                n = script[s] - 80
            elif not m:
                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 + 1:s + 3])[0]
            except:
                break
        elif script[s] == OPCODE["OP_PUSHDATA4"]:
            try:
                s += 4 + unpack('<L', script[s + 1:s + 5])[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
    }
Exemple #8
0
    def __init__(self,
                 key=None,
                 address_type="P2WPKH",
                 testnet=False,
                 compressed=True,
                 regtest=False):
        self.regtest = regtest
        if key is None:
            #: instance of ``PrivateKey`` class
            self.private_key = PrivateKey(testnet=testnet,
                                          compressed=compressed)
            #: instance of ``PublicKey`` class
            self.public_key = PublicKey(self.private_key)
            #: flag for testnet network address  (boolean)
            self.testnet = testnet
        if isinstance(key, str) or isinstance(key, bytes):
            key = PrivateKey(key, testnet=testnet, compressed=compressed)
        if isinstance(key, PrivateKey):
            self.private_key = key
            self.testnet = key.testnet
            compressed = key.compressed
            self.public_key = PublicKey(self.private_key)
        elif isinstance(key, PublicKey):
            self.public_key = key
            self.testnet = testnet
            compressed = key.compressed
        if address_type not in ("P2PKH", "PUBKEY", "P2WPKH", "P2SH_P2WPKH"):
            raise TypeError("address type invalid")
        if not compressed:
            if address_type not in ("P2PKH", "PUBKEY", "P2SH"):
                raise TypeError("compressed public key invalid")
        #: address type (string)
        self.type = address_type

        if address_type == "PUBKEY":
            self.pubkey_script = b"%s%s" % (op_push_data(
                self.public_key.key), OP_CHECKSIG)
            self.pubkey_script_hex = self.pubkey_script.hex()
            #: version of witness program for SEGWIT address (string)
        self.witness_version = 0 if address_type == "P2WPKH" else None
        self.compressed = compressed
        if address_type == "P2SH_P2WPKH":
            #: flag for script hash address (boolean)
            self.script_hash = True
            #: redeeem script, only for P2SH_P2WPKH (bytes)
            self.redeem_script = public_key_to_p2sh_p2wpkh_script(
                self.public_key.key)
            #: redeeem script HEX, only for P2SH_P2WPKH (string)
            self.redeem_script_hex = self.redeem_script.hex()
            #: address hash
            self.hash = hash160(self.redeem_script)
            self.witness_version = None
        else:
            self.script_hash = False
            self.hash = hash160(self.public_key.key)
        #: address hash HEX (string)
        self.hash_hex = self.hash.hex()
        #: address in base58 or bech32 encoding (string)
        self.address = hash_to_address(self.hash,
                                       script_hash=self.script_hash,
                                       witness_version=self.witness_version,
                                       testnet=self.testnet,
                                       regtest=self.regtest)