Beispiel #1
0
    def add_output(self, amount, address=None, script_pub_key=None):
        if address is None and script_pub_key is None:
            raise Exception("unable to add output, address or script required")
        if type(amount) != int:
            raise TypeError("unable to add output, amount type error")
        if amount < 0 or amount > MAX_AMOUNT:
            raise Exception("unable to add output, amount value error")
        if script_pub_key:
            if isinstance(script_pub_key, str):
                script_pub_key = bytes_from_hex(script_pub_key)
            if not isinstance(script_pub_key, bytes):
                raise TypeError("unable to add output, script_pub_key type error")
        else:
            if type(address) == Address:
                address = address.address
            script_pub_key = address_to_script(address)

        k = len(self["vOut"])
        self["vOut"][k] = dict()
        self["vOut"][k]["value"] = amount
        segwit = True if "segwit" in self else False
        s = parse_script(script_pub_key, segwit)
        self["vOut"][k]["nType"] = s["nType"]
        self["vOut"][k]["type"] = s["type"]

        if self["format"] == "raw":
            self["vOut"][k]["scriptPubKey"] = script_pub_key
            if self["data"] is None:
                if s["nType"] == 3:
                    self["data"] = s["data"]
            if s["nType"] not in (3, 4, 7, 8):
                self["vOut"][k]["addressHash"] = s["addressHash"]
                self["vOut"][k]["reqSigs"] = s["reqSigs"]
        else:
            self["vOut"][k]["scriptPubKey"] = script_pub_key.hex()
            if self["data"] is None:
                if s["nType"] == 3:
                    self["data"] = s["data"].hex()
            if s["nType"] not in (3, 4, 7, 8):
                self["vOut"][k]["addressHash"] = s["addressHash"].hex()
                self["vOut"][k]["reqSigs"] = s["reqSigs"]
            self["vOut"][k]["scriptPubKeyOpcodes"] = decode_script(script_pub_key)
            self["vOut"][k]["scriptPubKeyAsm"] = decode_script(script_pub_key, 1)
            sh = True if self["vOut"][k]["nType"] in (1, 5) else False
            witness_version = None if self["vOut"][k]["nType"] < 5 else 0
            if "addressHash" in self["vOut"][k]:
                self["vOut"][k]["address"] = hash_to_address(self["vOut"][k]["addressHash"],
                                                             self["testnet"],
                                                             sh,
                                                             witness_version)
        if self.auto_commit:
            self.commit()
        return self
Beispiel #2
0
 def __init__(self, script, testnet=False, witness_version=0):
     self.witness_version = witness_version
     self.testnet = testnet
     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)
Beispiel #3
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.
    """

    return __parent__.decode_script(script, asm=asm)
Beispiel #4
0
    def sign_input(self, n, private_key=None, script_pub_key=None,
                   redeem_script=None,
                   sighash_type=SIGHASH_ALL,
                   address=None, amount=None, witness_version=0,
                   p2sh_p2wsh=False):
        # private key
        if not private_key:
            try:
                private_key = self["vIn"][n]["private_key"].key
            except:
                raise RuntimeError("no private key")
        if isinstance(private_key, list):
            public_key = [PublicKey(p).key for p in private_key]
            private_key = [p.key if isinstance(p, PrivateKey) else PrivateKey(p).key for p in private_key]
        else:
            if not isinstance(private_key, PrivateKey):
                private_key = PrivateKey(private_key)
            public_key = [PublicKey(private_key).key]
            private_key = [private_key.key]

        if address is not None:
            if isinstance(address, str):
                net = True if address_net_type(address) == 'mainnet' else False
                if not net != self["testnet"]:
                    raise TypeError("address invalid")
                script_pub_key = address_to_script(address)
            elif type(address) in (Address, ScriptAddress):
                script_pub_key = address_to_script(address.address)
        # script pub key
        if script_pub_key is None:

            if "scriptPubKey" in self["vIn"][n]:
                script_pub_key = self["vIn"][n]["scriptPubKey"]
                st = parse_script(script_pub_key)
            elif redeem_script or "redeemScript" in self["vIn"][n]:
                if witness_version is None or p2sh_p2wsh:
                    st = {"type": "P2SH"}
                elif witness_version == 0:
                    st = {"type": "P2WSH"}
                else:
                    raise RuntimeError("not implemented")
            else:
                raise RuntimeError("no scriptPubKey key")
        else:
            st = parse_script(script_pub_key)
        if isinstance(script_pub_key, str):
            script_pub_key = bytes.fromhex(script_pub_key)

        # sign input
        if st["type"] == "PUBKEY":
            script_sig = self.__sign_pubkey__(n, private_key, script_pub_key, sighash_type)
        elif st["type"] == "P2PKH":
            script_sig = self.__sign_p2pkh__(n, private_key, public_key, script_pub_key, sighash_type)
        elif st["type"] == "P2SH":
            script_sig = self.__sign_p2sh(n, private_key, public_key, redeem_script, sighash_type, amount, p2sh_p2wsh)
        elif st["type"] == "P2WPKH":
            script_sig = self.__sign_p2wpkh(n, private_key, public_key, script_pub_key, sighash_type, amount)
        elif st["type"] == "P2WSH":
            script_sig = self.__sign_p2wsh(n, private_key, public_key, script_pub_key,
                                           redeem_script, sighash_type, amount)
        elif st["type"] == "MULTISIG":
            script_sig = self.__sign_bare_multisig__(n, private_key, public_key, script_pub_key, sighash_type)
        else:
            raise RuntimeError("not implemented")

        if self["format"] == "raw":
            self["vIn"][n]["scriptSig"] = script_sig
        else:
            self["vIn"][n]["scriptSig"] = script_sig.hex()
            self["vIn"][n]["scriptSigOpcodes"] = decode_script(script_sig)
            self["vIn"][n]["scriptSigAsm"] = decode_script(script_sig, 1)
        if self.auto_commit:
            self.commit()
        return self
Beispiel #5
0
    def add_input(self, tx_id=None, v_out=0, sequence=0xffffffff,
                  script_sig=b"", tx_in_witness=None, amount=None,
                  script_pub_key=None, address=None, private_key=None,
                  redeem_script=None, input_verify = True):
        if tx_id is None:
            tx_id = b"\x00" * 32
            v_out = 0xffffffff
            if (sequence != 0xffffffff or self["vIn"]) and input_verify:
                raise RuntimeError("invalid coinbase transaction")

        if isinstance(tx_id, str):
            tx_id = s2rh(tx_id)
        if not isinstance(tx_id, bytes) or len(tx_id) != 32:
            raise TypeError("tx_id invalid")

        if isinstance(script_sig, str):
            script_sig = bytes_from_hex(script_sig)
        if not isinstance(script_sig, bytes) or (len(script_sig) > 520 and input_verify):
            raise TypeError("script_sig invalid")

        if not isinstance(v_out, int) or not (v_out <= 0xffffffff and v_out >= 0):
            raise TypeError("v_out invalid")
        if not isinstance(sequence, int) or not (sequence <= 0xffffffff and sequence >= 0):
            raise TypeError("sequence invalid")

        if private_key:
            if not isinstance(private_key, PrivateKey):
                private_key = PrivateKey(private_key)
        if amount:
            if not isinstance(amount, int) or not amount >= 0 and amount <= MAX_AMOUNT:
                raise TypeError("amount invalid")

        if tx_in_witness:
            if not isinstance(tx_in_witness, list):
                raise TypeError("tx_in_witness invalid")
            l = 0
            witness = []
            for w in tx_in_witness:
                if isinstance(w, str):
                    witness.append(bytes_from_hex(w) if self["format"] == "raw" else w)
                else:
                    witness.append(w if self["format"] == "raw" else bytes_from_hex(w))
                l += 1 + len(w)
                if len(w) >= 0x4c:
                    l += 1
                if len(w) > 0xff:
                    l += 1
            # witness script limit
            if not l <= 10000:
                raise TypeError("tx_in_witness invalid")

        if tx_id == b"\x00" * 32:
            if not (v_out == 0xffffffff and sequence == 0xffffffff and len(script_sig) <= 100):
                if input_verify:
                    raise TypeError("coinbase tx invalid")
            self["coinbase"] = True

        # script_pub_key
        if script_pub_key:
            if isinstance(script_pub_key, str):
                script_pub_key = bytes_from_hex(script_pub_key)
            if not isinstance(script_pub_key, bytes):
                raise TypeError("script_pub_key tx invalid")

        if redeem_script:
            if isinstance(redeem_script, str):
                redeem_script = bytes_from_hex(redeem_script)
            if not isinstance(redeem_script, bytes):
                raise TypeError("redeem_script tx invalid")

        if address is not None:
            if isinstance(address, str):
                net = True if address_net_type(address) == 'mainnet' else False
                if not net != self["testnet"]:
                    raise TypeError("address invalid")
                script = address_to_script(address)
            elif type(address) in (Address, ScriptAddress):
                script = address_to_script(address.address)
            else:
                raise TypeError("address invalid")
            if script_pub_key:
                if  script_pub_key != script:
                    raise Exception("address not match script")
            else:
                script_pub_key = script

        k = len(self["vIn"])
        self["vIn"][k] = dict()
        self["vIn"][k]["vOut"] = v_out
        self["vIn"][k]["sequence"] = sequence
        if self["format"] == "raw":
            self["vIn"][k]["txId"] = tx_id
            self["vIn"][k]["scriptSig"] = script_sig
            if script_pub_key:
                self["vIn"][k]["scriptPubKey"] = script_pub_key
            if redeem_script:
                self["vIn"][k]["redeemScript"] = redeem_script
        else:
            self["vIn"][k]["txId"] = rh2s(tx_id)
            self["vIn"][k]["scriptSig"] = script_sig.hex()
            self["vIn"][k]["scriptSigOpcodes"] = decode_script(script_sig)
            self["vIn"][k]["scriptSigAsm"] = decode_script(script_sig, 1)
            if script_pub_key:
                self["vIn"][k]["scriptPubKey"] = script_pub_key.hex()
                self["vIn"][k]["scriptPubKeyOpcodes"] = decode_script(script_pub_key)
                self["vIn"][k]["scriptPubKeyAsm"] = decode_script(script_pub_key, 1)
            if redeem_script:
                self["vIn"][k]["redeemScript"] = redeem_script.hex()
                self["vIn"][k]["redeemScriptOpcodes"] = decode_script(redeem_script)
                self["vIn"][k]["redeemScriptAsm"] = decode_script(script_pub_key, 1)
        if tx_in_witness:
            self["segwit"] = True
            self["vIn"][k]["txInWitness"] = witness
        if amount:
            self["vIn"][k]["value"] = amount
        if private_key:
            self["vIn"][k]["private_key"] = private_key
        if self.auto_commit:
            self.commit()
        return self
Beispiel #6
0
    def decode(self, testnet=None):
        """
        change Transaction object representation to "decoded" human readable format

        :param bool testnet: (optional) address type for "decoded" transaction representation, by default None.
                            if None used type from transaction property "format".
        """
        if self["format"] == "decoded":
            self.encode()
        self["format"] = "decoded"
        if testnet is not None:
            self["testnet"] = testnet
        if type(self["txId"]) == bytes:
            self["txId"] = rh2s(self["txId"])
        if "flag" in self:
            if type(self["flag"]) == bytes:
                self["flag"] = rh2s(self["flag"])
        if type(self["hash"]) == bytes:
            self["hash"] = rh2s(self["hash"])
        if type(self["rawTx"]) == bytes:
            self["rawTx"] = self["rawTx"].hex()
        for i in self["vIn"]:
            if type(self["vIn"][i]["txId"]) == bytes:
                self["vIn"][i]["txId"] = rh2s(self["vIn"][i]["txId"])
            if type(self["vIn"][i]["scriptSig"]) == bytes:
                self["vIn"][i]["scriptSig"] = self["vIn"][i]["scriptSig"].hex()
            try:
                t = list()
                append = t.append
                for w in self["vIn"][i]["txInWitness"]:
                    if type(w) == bytes:
                        w = w.hex()
                    append(w)
                self["vIn"][i]["txInWitness"] = t

            except:
                pass
            try:
                if type(self["vIn"][i]["addressHash"]) == bytes:
                    self["vIn"][i]["addressHash"] = self["vIn"][i]["addressHash"].hex()
                sh = True if self["vIn"][i]["nType"] in (1, 5) else False
                witness_version = None if self["vIn"][i]["nType"] < 5 else 0
                self["vIn"][i]["address"] = hash_to_address(self["vIn"][i]["addressHash"],
                                                            self["testnet"],
                                                            sh,
                                                            witness_version)
            except:
                pass
            if "scriptPubKey" in self["vIn"][i]:
                if type(self["vIn"][i]["scriptPubKey"]) == bytes:
                    self["vIn"][i]["scriptPubKey"] = self["vIn"][i]["scriptPubKey"].hex()
                self["vIn"][i]["scriptPubKeyOpcodes"] = decode_script(self["vIn"][i]["scriptPubKey"])
                self["vIn"][i]["scriptPubKeyAsm"] = decode_script(self["vIn"][i]["scriptPubKey"], 1)
            if "redeemScript" in self["vIn"][i]:
                if type(self["vIn"][i]["redeemScript"]) == bytes:
                    self["vIn"][i]["redeemScript"] = self["vIn"][i]["redeemScript"].hex()
                self["vIn"][i]["redeemScriptOpcodes"] = decode_script(self["vIn"][i]["redeemScript"])
                self["vIn"][i]["redeemScriptAsm"] = decode_script(self["vIn"][i]["redeemScript"], 1)
            if not self["coinbase"]:
                if type(self["vIn"][i]["scriptSig"]) == bytes:
                    self["vIn"][i]["scriptSig"] = self["vIn"][i]["scriptSig"].hex()
                self["vIn"][i]["scriptSigOpcodes"] = decode_script(self["vIn"][i]["scriptSig"])
                self["vIn"][i]["scriptSigAsm"] = decode_script(self["vIn"][i]["scriptSig"], 1)

        for i in self["vOut"]:
            if type(self["vOut"][i]["scriptPubKey"]) == bytes:
                self["vOut"][i]["scriptPubKey"] = self["vOut"][i]["scriptPubKey"].hex()
            try:
                if type(self["vOut"][i]["addressHash"]) == bytes:
                    self["vOut"][i]["addressHash"] = self["vOut"][i]["addressHash"].hex()
                sh = True if self["vOut"][i]["nType"] in (1, 5) else False
                witness_version = None if self["vOut"][i]["nType"] < 5 else 0
                self["vOut"][i]["address"] = hash_to_address(self["vOut"][i]["addressHash"],
                                                             self["testnet"],
                                                             sh,
                                                             witness_version)
            except:
                pass
            self["vOut"][i]["scriptPubKeyOpcodes"] = decode_script(self["vOut"][i]["scriptPubKey"])
            self["vOut"][i]["scriptPubKeyAsm"] = decode_script(self["vOut"][i]["scriptPubKey"], 1)
        if "data" in self:
            if type(self["data"]) == bytes:
                self["data"] = self["data"].hex()
        return self
Beispiel #7
0
def test_decode_script():
    assert decode_script("76a9143520dd524f6ca66f63182bb23efff6cc8ee3ee6388ac") == \
           "OP_DUP OP_HASH160 [20] OP_EQUALVERIFY OP_CHECKSIG"
    assert decode_script("76a9143520dd524f6ca66f63182bb23efff6cc8ee3ee6388ac", asm=True) == \
           "OP_DUP OP_HASH160 OP_PUSHBYTES[20] 3520dd524f6ca66f63182bb23efff6cc8ee3ee63 OP_EQUALVERIFY OP_CHECKSIG"
    assert decode_script("a91469f37572ab1b69f304f987b119e2450e0b71bf5c87") == \
           "OP_HASH160 [20] OP_EQUAL"
    assert decode_script("a91469f37572ab1b69f304f987b119e2450e0b71bf5c87", asm=True) == \
           "OP_HASH160 OP_PUSHBYTES[20] 69f37572ab1b69f304f987b119e2450e0b71bf5c OP_EQUAL"
    assert decode_script(
        "6a144279b52d6ee8393a9a755e8c6f633b5dd034bd67") == "OP_RETURN [20]"
    assert decode_script("6a144279b52d6ee8393a9a755e8c6f633b5dd034bd67", asm=True) == \
           "OP_RETURN OP_PUSHBYTES[20] 4279b52d6ee8393a9a755e8c6f633b5dd034bd67"

    s = "6a4c5100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" \
        "0000000000000000000000000000000000000000000000000000000000000000000"
    assert decode_script(s) == "OP_RETURN OP_PUSHDATA1 [81]"
    assert decode_script(s, asm=True) == "OP_RETURN OP_PUSHDATA1[81] 00000000000000000000000000000000000000000" \
                                         "00000000000000000000000000000000000000000000000000000000000000000000" \
                                         "00000000000000000000000000000000000000000000000000000"
    s = "5f210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71210378d430274f8c5ec1321338151e9" \
        "f27f4c676a008bdf8638d07c0b6be9ab35c71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab3" \
        "5c71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71210378d430274f8c5ec1321338151" \
        "e9f27f4c676a008bdf8638d07c0b6be9ab35c71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9a" \
        "b35c71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71210378d430274f8c5ec13213381" \
        "51e9f27f4c676a008bdf8638d07c0b6be9ab35c71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be" \
        "9ab35c71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71210378d430274f8c5ec132133" \
        "8151e9f27f4c676a008bdf8638d07c0b6be9ab35c71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6" \
        "be9ab35c71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71210378d430274f8c5ec1321" \
        "338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0" \
        "b6be9ab35c715fae"

    assert decode_script(s) == "OP_15 [33] [33] [33] [33] [33] [33] [33] [33] [33] [33] [33] [33] [33] [33] " \
                               "[33] OP_15 OP_CHECKMULTISIG"
    assert decode_script(s, asm=True) == 'OP_15 OP_PUSHBYTES[33] 0378d430274f8c5ec1321338151e9f27f4c676a008b' \
                                         'df8638d07c0b6be9ab35c71 OP_PUSHBYTES[33] 0378d430274f8c5ec13213381' \
                                         '51e9f27f4c676a008bdf8638d07c0b6be9ab35c71 OP_PUSHBYTES[33] 0378d43' \
                                         '0274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 ' \
                                         'OP_PUSHBYTES[33] 0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638' \
                                         'd07c0b6be9ab35c71 OP_PUSHBYTES[33] 0378d430274f8c5ec1321338151e9f2' \
                                         '7f4c676a008bdf8638d07c0b6be9ab35c71 OP_PUSHBYTES[33] 0378d430274f8' \
                                         'c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 ' \
                                         'OP_PUSHBYTES[33] 0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638' \
                                         'd07c0b6be9ab35c71 OP_PUSHBYTES[33] 0378d430274f8c5ec1321338151e9f2' \
                                         '7f4c676a008bdf8638d07c0b6be9ab35c71 OP_PUSHBYTES[33] 0378d430274f8' \
                                         'c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 ' \
                                         'OP_PUSHBYTES[33] 0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638' \
                                         'd07c0b6be9ab35c71 OP_PUSHBYTES[33] 0378d430274f8c5ec1321338151e9f2' \
                                         '7f4c676a008bdf8638d07c0b6be9ab35c71 OP_PUSHBYTES[33] 0378d430274f8' \
                                         'c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 ' \
                                         'OP_PUSHBYTES[33] 0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638' \
                                         'd07c0b6be9ab35c71 OP_PUSHBYTES[33] 0378d430274f8c5ec1321338151e9f2' \
                                         '7f4c676a008bdf8638d07c0b6be9ab35c71 OP_PUSHBYTES[33] 0378d430274f8' \
                                         'c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 OP_15 ' \
                                         'OP_CHECKMULTISIG'
    assert decode_script(
        "00144160bb1870159a08724557f75c7bb665a3a132e0") == "OP_0 [20]"
    assert decode_script(
        "0020cdbf909e935c855d3e8d1b61aeb9c5e3c03ae8021b286839b1a72f2e48fdba70"
    ) == "OP_0 [32]"
    assert decode_script(
        [OP_PUSHDATA2, pack('<H', 20),
         b"12345678901234567890"]) == "OP_PUSHDATA2 [20]"
    assert decode_script([OP_PUSHDATA2, pack('<H', 20),b"12345678901234567890"], asm=True) == "OP_PUSHDATA2[20] "+ \
           b"12345678901234567890".hex()
    assert decode_script(
        [OP_PUSHDATA4, pack('<L', 20),
         b"12345678901234567890"]) == "OP_PUSHDATA4 [20]"
    assert decode_script([OP_PUSHDATA4, pack('<L', 20),b"12345678901234567890"], asm=True) == "OP_PUSHDATA4[20] "+ \
           b"12345678901234567890".hex()
    assert decode_script([OP_PUSHDATA2]) == "[SCRIPT_DECODE_FAILED]"