async def load_utxo_from_daemon(self): # # load missed utxo from bitcoind daemon # if not self.missed_failed: return missed = chunks_by_count(self.missed_failed, 50) for m in missed: result = await self.rpc.batch([["getrawtransaction", rh2s(i[:32]), 1] for i in m]) hash_list = set() for r in result: if r["result"]["blockhash"] not in self.restore_blocks_cache: hash_list.add(r["result"]["blockhash"]) result2 = await self.rpc.batch([["getblock", r] for r in hash_list]) for r in result2: self.restore_blocks_cache[r["result"]["hash"]] = r["result"] for key, r in zip(m, result): out_index = bytes_to_int(key[32:]) tx=r["result"] amount = int(tx["vout"][out_index]["value"] * 100000000) script = parse_script(tx["vout"][out_index]["scriptPubKey"]["hex"]) try: address = b"".join((bytes([script["nType"]]), script["addressHash"])) except: address = b"".join((bytes([script["nType"]]), script["script"])) block = self.restore_blocks_cache[tx["blockhash"]] tx_index = block["tx"].index(tx["txid"]) block_height = block["height"] pointer = (block_height << 39) + (tx_index << 20) + (1 << 19) + out_index self.loaded[key] = (pointer, amount, address) self.missed_failed = list() while len(self.restore_blocks_cache) > 1000: self.restore_blocks_cache.pop()
def __sign_p2sh_p2wsh(self, n, private_key, public_key, redeem_script, sighash_type, amount): rst = parse_script(redeem_script) if rst["type"] == "MULTISIG": return self.__sign_p2sh_p2wsh_multisig(n, private_key, public_key, redeem_script, sighash_type, amount) else: raise RuntimeError("not implemented")
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
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 """ return __parent__.parse_script(script, segwit=segwit)
def __sign_p2sh(self, n, private_key, public_key, redeem_script, sighash_type, amount, p2sh_p2wsh): if not redeem_script: if "redeemScript" in self["vIn"][n]: redeem_script = self["vIn"][n]["redeemScript"] else: raise RuntimeError("no redeem script") if isinstance(redeem_script, str): redeem_script = bytes.fromhex(redeem_script) rst = parse_script(redeem_script) if p2sh_p2wsh: return self.__sign_p2sh_p2wsh(n, private_key, public_key, redeem_script, sighash_type, amount) if rst["type"] == "MULTISIG": return self.__sign_p2sh_multisig(n, private_key, public_key, redeem_script, sighash_type) elif rst["type"] == "P2WPKH": return self.__sign_p2sh_p2wpkh(n, private_key, public_key, redeem_script, sighash_type, amount) else: return self.__sign_p2sh_custom(n, private_key, public_key, redeem_script, sighash_type, amount)
def __sign_p2wsh(self, n, private_key, public_key, script_pub_key, redeem_script, sighash_type, amount): self["segwit"] = True if not redeem_script: if "redeemScript" in self["vIn"][n]: redeem_script = self["vIn"][n]["redeemScript"] else: raise RuntimeError("no redeem script") if isinstance(redeem_script, str): redeem_script = bytes.fromhex(redeem_script) rst = parse_script(redeem_script) if amount is None: try: amount = self["vIn"][n]["value"] except: raise RuntimeError("no input amount") if rst["type"] == "MULTISIG": return self.__sign_p2wsh_multisig(n, private_key, public_key, script_pub_key, redeem_script, sighash_type, amount) else: return self.__sign_p2wsh_custom(n, private_key, public_key, script_pub_key, redeem_script, sighash_type, amount)
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
def __init__(self, raw_tx=None, format="decoded", version=1, lock_time=0, testnet=False, auto_commit=True): if format not in ("decoded", "raw"): raise ValueError("format error, raw or decoded allowed") self.auto_commit = auto_commit self["format"] = format self["testnet"] = testnet self["segwit"] = False self["txId"] = None self["hash"] = None self["version"] = version self["size"] = 0 self["vSize"] = 0 self["bSize"] = 0 self["lockTime"] = lock_time self["vIn"] = dict() self["vOut"] = dict() self["rawTx"] = None self["blockHash"] = None self["confirmations"] = None self["time"] = None self["blockTime"] = None self["blockIndex"] = None self["coinbase"] = False self["fee"] = None self["data"] = None self["amount"] = None if raw_tx is None: return self["amount"] = 0 sw = sw_len = 0 stream = self.get_stream(raw_tx) start = stream.tell() read = stream.read tell = stream.tell seek = stream.seek # start deserialization self["version"] = unpack('<L', read(4))[0] n = read_var_int(stream) if n == b'\x00': # segwit format sw = 1 self["flag"] = read(1) n = read_var_int(stream) # inputs ic = var_int_to_int(n) for k in range(ic): self["vIn"][k] = dict() self["vIn"][k]["txId"] = read(32) self["vIn"][k]["vOut"] = unpack('<L', read(4))[0] self["vIn"][k]["scriptSig"] = read(var_int_to_int(read_var_int(stream))) self["vIn"][k]["sequence"] = unpack('<L', read(4))[0] # outputs for k in range(var_int_to_int(read_var_int(stream))): self["vOut"][k] = dict() self["vOut"][k]["value"] = unpack('<Q', read(8))[0] self["amount"] += self["vOut"][k]["value"] self["vOut"][k]["scriptPubKey"] = read(var_int_to_int(read_var_int(stream))) s = parse_script(self["vOut"][k]["scriptPubKey"]) self["vOut"][k]["nType"] = s["nType"] self["vOut"][k]["type"] = s["type"] 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"] # witness if sw: sw = tell() - start for k in range(ic): self["vIn"][k]["txInWitness"] = [read(var_int_to_int(read_var_int(stream))) \ for c in range(var_int_to_int(read_var_int(stream)))] sw_len = (stream.tell() - start) - sw + 2 self["lockTime"] = unpack('<L', read(4))[0] end = tell() seek(start) b = read(end - start) self["rawTx"] = b self["size"] = end - start self["bSize"] = end - start - sw_len self["weight"] = self["bSize"] * 3 + self["size"] self["vSize"] = ceil(self["weight"] / 4) if ic == 1 and \ self["vIn"][0]["txId"] == b'\x00' * 32 and \ self["vIn"][0]["vOut"] == 0xffffffff: self["coinbase"] = True else: self["coinbase"] = False if sw: self["segwit"] = True self["hash"] = double_sha256(b) self["txId"] = double_sha256(b"%s%s%s" % (b[:4], b[6:sw],b[-4:])) else: self["segwit"] = False self["txId"] = double_sha256(b) self["hash"] = self["txId"] if self["format"] == "decoded": self.decode()
def test_parse_script(): assert parse_script(b"")["type"] == "NON_STANDARD" assert parse_script(b"".join([OP_RETURN, b"\x00"]))["type"] == "NULL_DATA" assert parse_script(b"".join([OP_RETURN, b""]))["type"] == "NULL_DATA" assert parse_script(b"".join([ OP_RETURN, b2h("20313233343536373839303132333435363738393" "0313233343536373839303132") ]))["type"] == "NULL_DATA" assert parse_script(b"".join([OP_RETURN, b2h("20313233343536373839303132333435363" "7383930313233343536373839303132")]))["data"].hex() == \ "3132333435363738393031323334353637383930313233343536373839303132" assert parse_script(b"".join([ OP_RETURN, b2h("203132333435363738393031323334353637383930" "3132333435363738393031323131") ]))["type"] == "NULL_DATA_NON_STANDARD" assert parse_script(b"".join([OP_RETURN, OP_PUSHDATA1, b"\x00"]))["type"] == "NULL_DATA" assert parse_script(b"".join([OP_RETURN, OP_PUSHDATA1, b"\x00"]))["data"] == b"" assert parse_script(b"".join([OP_RETURN, OP_PUSHDATA1, b2h("2031323334353637383930313233343536373839303" "13233343536373839303132")]))["data"].hex() == "3132333435363738393031323334353" \ "637383930313233343536373839303132" assert parse_script(b"".join([ OP_RETURN, OP_PUSHDATA1, b2h("20313233343536373839303132333435363738393031323334353637" "3839303132") ]))["type"] == "NULL_DATA" assert parse_script(b"".join([ OP_RETURN, OP_PUSHDATA1, b2h("20313233343536373839303132333435363738393031323334353637" "38393031323131") ]))["type"] == "NULL_DATA_NON_STANDARD" assert parse_script(b"".join( [OP_RETURN, OP_PUSHDATA1, b"\x1412345678901234567890"]))["type"] == "NULL_DATA" assert parse_script(b"".join( [OP_RETURN, OP_PUSHDATA1, b"\x14123456789012345678901"]))["type"] == "NULL_DATA_NON_STANDARD" assert parse_script(b"".join([OP_RETURN, OP_PUSHDATA1 ]))["type"] == "NULL_DATA_NON_STANDARD" assert parse_script(b"".join([ OP_RETURN, OP_PUSHDATA2, b2h("20313233343536373839303132333435363738393031323334353637" "38393031323131") ]))["type"] == "NULL_DATA_NON_STANDARD" assert parse_script(b"".join([ OP_RETURN, OP_PUSHDATA1, b2h("20313233343536373839303132333435363738393031323334353637" "383930313231313131") ]))["type"] == "NULL_DATA_NON_STANDARD" assert parse_script(b"".join([ OP_RETURN, OP_PUSHDATA1, b2h("50313233343536373839303132333435363738393031323334353637383930313" "23334353637383930313233343536373839303132333435363738393031323334" "35363738393031323334353637383930") ]))["type"] == "NULL_DATA" assert parse_script(b"".join([OP_RETURN, OP_PUSHDATA1, b2h("50313233343536373839303132333435363738393031323334353637383930313" "23334353637383930313233343536373839303132333435363738393031323334" "353637383930313233343536" "37383930")]))["data"].hex() == "3132333435363738393031323334353637" \ "3839303132333435363738393031323334" \ "3536373839303132333435363738393031" \ "3233343536373839303132333435363738" \ "393031323334353637383930" assert parse_script(b"".join([ OP_RETURN, OP_PUSHDATA1, b2h("5131323334353637383930313233343536373839303132333435363738393031323" "3343536373839303132333435363738393031323334353637383930313233343536" "373839303132333435363738" "393031") ]))["type"] == "NULL_DATA_NON_STANDARD" assert parse_script(b2h( "a914546fbecb877edbe5777bc0ce4c8be6989d8edd9387"))["type"] == "P2SH" assert parse_script( b2h("a914546fbecb877edbe5777bc0ce4c8be6989d8edd9387"))["nType"] == 1 assert parse_script( b2h("a914546fbecb877edbe5777bc0c" "e4c8be6989d8edd9387"))["addressHash"].hex( ) == "546fbecb877edbe5777bc0ce4c8be6989d8edd93" assert parse_script(b2h( "a914546fbecb877edbe5777bc0ce4c8be6989d8edd9387"))["reqSigs"] == None assert parse_script( b2h("76a9143053ef41e2106fb5fea261c8ee3fd44f007b5ee688ac") )["type"] == "P2PKH" assert parse_script( b2h("76a9143053ef41e2106fb5fea261c8ee3fd44f007b5ee688ac") )["nType"] == 0 assert parse_script( b2h("76a9143053ef41e2106fb5fea261c8ee3fd44f007b5ee688ac") )["reqSigs"] == 1 assert parse_script(b2h("76a9143053ef41e2106fb5fea261" "c8ee3fd44f007b5ee688ac"))["addressHash"].hex() == \ "3053ef41e2106fb5fea261c8ee3fd44f007b5ee6" p = "410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604" \ "f8141781e62294721166bf621e73a82cbf2342c858eeac" assert parse_script(p)["type"] == "PUBKEY" assert parse_script(p)["nType"] == 2 assert parse_script(p)["reqSigs"] == 1 assert parse_script( p)["addressHash"].hex() == "119b098e2e980a229e139a9ed01a469e518e6f26" p = b"".join([ b"\x33", b2h("03295ba1e53005b622b5c959a66185fe9ad4564597c99d43d99e7824add7d755de" ), OP_CHECKSIG ]) assert parse_script(p)["type"] == "PUBKEY" assert parse_script(p)["nType"] == 2 assert parse_script(p)["reqSigs"] == 1 p = "00142ac50173769ba101bb2a2e7b32f158eb8c77d8a4" assert parse_script(p)["type"] == "P2WPKH" assert parse_script(p)["nType"] == 5 assert parse_script(p)["reqSigs"] == 1 assert parse_script( p)["addressHash"].hex() == "2ac50173769ba101bb2a2e7b32f158eb8c77d8a4" p = "00142ac50173769ba101bb2a2e7b32f158eb8c77d8a4" assert parse_script(p, False)["type"] == "NON_STANDARD" assert parse_script(p, False)["nType"] == 7 assert parse_script(p, False)["reqSigs"] == 0 p = "0020701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d" assert parse_script(b2h(p))["type"] == "P2WSH" assert parse_script(b2h(p))["nType"] == 6 assert parse_script(b2h(p))["reqSigs"] is None assert parse_script(b2h(p))["addressHash"].hex() == "701a8d401c84fb13e6baf169d59684e17ab" \ "d9fa216c8cc5b9fc63d622ff8c58d" s = "512102953397b893148acec2a9da8341159e9e7fb3d32987c3563e8bdf22116213623" s += "441048da561da64584fb1457e906bc2840a1f963b401b632ab98761d12d74dd795bbf" s += "410c7b6d6fd39acf9d870cb9726578eaf8ba430bb296eac24957f3fb3395b8b042060" s += "466616fb675310aeb024f957b4387298dc28305bc7276bf1f7f662a6764bcdffb6a97" s += "40de596f89ad8000f8fa6741d65ff1338f53eb39e98179dd18c6e6be8e3953ae" assert parse_script(b2h(s))["type"] == "MULTISIG" assert parse_script(b2h(s))["nType"] == 4 assert parse_script(b2h(s))["reqSigs"] == 1 s = "5f210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c" s += "71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c" s += "71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c" s += "71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c" s += "71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c" s += "71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c" s += "71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c" s += "71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c" s += "71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c" s += "71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c" s += "71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c" s += "71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c" s += "71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c" s += "71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c" s += "71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c" s += "715fae" assert parse_script(b2h(s))["type"] == "MULTISIG" assert parse_script(b2h(s))["nType"] == 4 assert parse_script(b2h(s))["reqSigs"] == 15 s = "0114410478d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35" s += "c71a1518063243acd4dfe96b66e3f2ec8013c8e072cd09b3834a19f81f659cc345541" s += "0478d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71a15" s += "18063243acd4dfe96b66e3f2ec8013c8e072cd09b3834a19f81f659cc3455410478d4" s += "30274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71a15180632" s += "43acd4dfe96b66e3f2ec8013c8e072cd09b3834a19f81f659cc3455410478d430274f" s += "8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71a1518063243acd4" s += "dfe96b66e3f2ec8013c8e072cd09b3834a19f81f659cc3455410478d430274f8c5ec1" s += "321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71a1518063243acd4dfe96b" s += "66e3f2ec8013c8e072cd09b3834a19f81f659cc3455410478d430274f8c5ec1321338" s += "151e9f27f4c676a008bdf8638d07c0b6be9ab35c71a1518063243acd4dfe96b66e3f2" s += "ec8013c8e072cd09b3834a19f81f659cc3455410478d430274f8c5ec1321338151e9f" s += "27f4c676a008bdf8638d07c0b6be9ab35c71a1518063243acd4dfe96b66e3f2ec8013" s += "c8e072cd09b3834a19f81f659cc3455410478d430274f8c5ec1321338151e9f27f4c6" s += "76a008bdf8638d07c0b6be9ab35c71a1518063243acd4dfe96b66e3f2ec8013c8e072" s += "cd09b3834a19f81f659cc3455410478d430274f8c5ec1321338151e9f27f4c676a008" s += "bdf8638d07c0b6be9ab35c71a1518063243acd4dfe96b66e3f2ec8013c8e072cd09b3" s += "834a19f81f659cc3455410478d430274f8c5ec1321338151e9f27f4c676a008bdf863" s += "8d07c0b6be9ab35c71a1518063243acd4dfe96b66e3f2ec8013c8e072cd09b3834a19" s += "f81f659cc3455410478d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0" s += "b6be9ab35c71a1518063243acd4dfe96b66e3f2ec8013c8e072cd09b3834a19f81f65" s += "9cc3455410478d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9a" s += "b35c71a1518063243acd4dfe96b66e3f2ec8013c8e072cd09b3834a19f81f659cc345" s += "5410478d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71" s += "a1518063243acd4dfe96b66e3f2ec8013c8e072cd09b3834a19f81f659cc345541047" s += "8d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71a15180" s += "63243acd4dfe96b66e3f2ec8013c8e072cd09b3834a19f81f659cc3455410478d4302" s += "74f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71a1518063243a" s += "cd4dfe96b66e3f2ec8013c8e072cd09b3834a19f81f659cc3455410478d430274f8c5" s += "ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71a1518063243acd4dfe" s += "96b66e3f2ec8013c8e072cd09b3834a19f81f659cc3455410478d430274f8c5ec1321" s += "338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71a1518063243acd4dfe96b66e" s += "3f2ec8013c8e072cd09b3834a19f81f659cc3455410478d430274f8c5ec1321338151" s += "e9f27f4c676a008bdf8638d07c0b6be9ab35c71a1518063243acd4dfe96b66e3f2ec8" s += "013c8e072cd09b3834a19f81f659cc3455410478d430274f8c5ec1321338151e9f27f" s += "4c676a008bdf8638d07c0b6be9ab35c71a1518063243acd4dfe96b66e3f2ec8013c8e" s += "072cd09b3834a19f81f659cc3455410478d430274f8c5ec1321338151e9f27f4c676a" s += "008bdf8638d07c0b6be9ab35c71a1518063243acd4dfe96b66e3f2ec8013c8e072cd0" s += "9b3834a19f81f659cc34550114ae" assert parse_script(b2h(s))["type"] == "NON_STANDARD" assert parse_script(b2h(s))["nType"] == 7 assert parse_script(b2h(s))["reqSigs"] == 20 s = "512102953397b893148acec2a9da8341159e9e7fb3d32987c3563e8bdf22116213623" s += "441048da561da64584fb1457e906bc2840a1f963b401b632ab98761d12d74dd795bbf" s += "410c7b6d6fd39acf9d870cb9726578eaf8ba430bb296eac24957f3fb3395b8b042060" s += "466616fb675310aeb024f957b4387298dc28305bc7276bf1f7f662a6764bcdffb6a97" s += "40de596f89ad8000f8fa6741d65ff1338f53eb39e98179dd18c6e6be8e3953" assert parse_script(b2h(s))["type"] == "NON_STANDARD" s = "512102953397b893148acec2a9da8341159e9e7fb3d32987c3563e8bdf22116213623" s += "441048da561da64584fb1457e906bc2840a1f963b401b632ab98761d12d74dd795bbf" s += "410c7b6d6fd39acf9d870cb9726578eaf8ba430bb296eac24957f3fb3395b8b042060" s += "466616fb675310aeb024f957b4387298dc28305bc7276bf1f7f662a6764bcdffb6a97" s += "40de596f89ad8000f8fa6741d65ff1338f53eb39e98179dd18c6e6be8e39ffae" assert parse_script(b2h(s))["type"] == "NON_STANDARD" s = "522102953397b893148acec2a9da8341159e9e7fb3d32987c3563e8bdf22116213623" s += "441048da561da64584fb1457e906bc2840a1f963b401b632ab98761d12d74dd795bbf" s += "410c7b6d6fd39acf9d870cb9726578eaf8ba430bb296eac24957f3fb3395b8b042060" s += "466616fb675310aeb024f957b4387298dc28305bc7276bf1f7f662a6764bcdffb6a97" s += "40de596f89ad8000f8fa6741d65ff1338f53eb39e98179dd18c6e6be8e3951ae" assert parse_script(b2h(s))["type"] == "NON_STANDARD" s = "518102953397b893148acec2a9da8341159e9e7fb3d32987c3563e8bdf22116213623" s += "441048da561da64584fb1457e906bc2840a1f963b401b632ab98761d12d74dd795bbf" s += "410c7b6d6fd39acf9d870cb9726578eaf8ba430bb296eac24957f3fb3395b8b042060" s += "466616fb675310aeb024f957b4387298dc28305bc7276bf1f7f662a6764bcdffb6a97" s += "40de596f89ad8000f8fa6741d65ff1338f53eb39e98179dd18c6e6be8e3953ae" assert parse_script(b2h(s))["type"] == "NON_STANDARD" assert parse_script([ OP_1, "3303295ba1e53005b622b5c959a66185fe9ad4564597c99d43d99e7824add7d755de", "3303295ba1e53005b622b5c959a66185fe9ad4564597c99d43d99e7824add7d755de", OP_2, OP_CHECKMULTISIGVERIFY ])["type"] == "NON_STANDARD" assert parse_script([ OP_1, b"\x21", "03295ba1e53005b622b5c959a66185fe9ad4564597c99d43d99e7824add7d755de", b"\x21", "03295ba1e53005b622b5c959a66185fe9ad4564597c99d43d99e7824add7d755de", OP_2, OP_CHECKMULTISIGVERIFY ])["reqSigs"] == 1 assert parse_script([ OP_3, OP_1, b"\x21", "03295ba1e53005b622b5c959a66185fe9ad4564597c99d43d99e7824add7d755de", b"\x21", "03295ba1e53005b622b5c959a66185fe9ad4564597c99d43d99e7824add7d755de", OP_2, OP_CHECKMULTISIGVERIFY ])["reqSigs"] == 1 assert parse_script([ OP_3, b"\x21", "03295ba1e53005b622b5c959a66185fe9ad4564597c99d43d99e7824add7d755de", b"\x21", "03295ba1e53005b622b5c959a66185fe9ad4564597c99d43d99e7824add7d755de", OP_2, OP_CHECKMULTISIGVERIFY ])["reqSigs"] == 20 assert parse_script([ OP_1, OP_PUSHDATA1, b"\x21", "03295ba1e53005b622b5c959a66185fe9ad4564597c99d43d99e7824add7d755de", b"\x21", "03295ba1e53005b622b5c959a66185fe9ad4564597c99d43d99e7824add7d755de", OP_2, OP_CHECKMULTISIGVERIFY ])["reqSigs"] == 20 assert parse_script([ OP_1, OP_PUSHDATA2, pack('<H', 33), "03295ba1e53005b622b5c959a66185fe9ad4564597c99d43d99e7824add7d755de", b"\x21", "03295ba1e53005b622b5c959a66185fe9ad4564597c99d43d99e7824add7d755de", OP_2, OP_CHECKMULTISIGVERIFY ])["reqSigs"] == 20 assert parse_script([OP_1, OP_PUSHDATA1])["reqSigs"] == 0 assert parse_script([OP_1, OP_PUSHDATA2])["reqSigs"] == 0 assert parse_script([OP_1, OP_PUSHDATA4])["reqSigs"] == 0 assert parse_script([OP_1, OP_CHECKSIG])["reqSigs"] == 1 assert parse_script([OP_1, OP_CHECKSIGVERIFY])["reqSigs"] == 1 assert parse_script([OP_1, OP_0])["type"] == "NON_STANDARD" assert parse_script([OP_3, OP_1, OP_1])["type"] == "NON_STANDARD"
def test_parse_script(self): k = tools.parse_script( "76a9144b2832feeda5692c96c0594a6314136a998f515788ac") address = functions.hash_to_address(k["addressHash"], witness_version=None) self.assertEqual(address, "17rPqUf4Hqu6Lvpgfsavt1CzRy2GL19GD3") self.assertEqual(k["type"], "P2PKH") self.assertEqual(k["nType"], 0) self.assertEqual(k["reqSigs"], 1) self.assertEqual(functions.address_to_script(address, 1), "76a9144b2832feeda5692c96c0594a6314136a998f515788ac") k = tools.parse_script( "76a914a307d67484911deee457779b17505cedd20e1fe988ac") address = functions.hash_to_address(k["addressHash"], testnet=True, witness_version=None) self.assertEqual(address, "mvNyptwisQTmwL3vN8VMaVUrA3swVCX83c") self.assertEqual(k["type"], "P2PKH") self.assertEqual(k["nType"], 0) self.assertEqual(k["reqSigs"], 1) self.assertEqual(functions.address_to_script(address, 1), "76a914a307d67484911deee457779b17505cedd20e1fe988ac") k = tools.parse_script( "a914b316ac9bdd0816ecdec6773d1192c0eaf52ae66487") address = functions.hash_to_address(k["addressHash"], script_hash=True, witness_version=None) self.assertEqual(address, "3J1x3KHjgjoTjqHjrwKax2zeT8LSDkZJae") self.assertEqual(k["type"], "P2SH") self.assertEqual(k["nType"], 1) self.assertEqual(k["reqSigs"], None) self.assertEqual(functions.address_to_script(address, 1), "a914b316ac9bdd0816ecdec6773d1192c0eaf52ae66487") k = tools.parse_script("0014751e76e8199196d454941c45d1b3a323f1433bd6") address = functions.hash_to_address(k["addressHash"], script_hash=False, witness_version=0, testnet=False) self.assertEqual(address, "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4") self.assertEqual(k["type"], "P2WPKH") self.assertEqual(k["nType"], 5) self.assertEqual(k["reqSigs"], 1) self.assertEqual(functions.address_to_script(address, 1), "0014751e76e8199196d454941c45d1b3a323f1433bd6") s = [ HEX_OPCODE['OP_HASH160'], '14', '92c2f2da37093971ca335824edae06468e60ea20', HEX_OPCODE['OP_EQUAL'] ] h = ''.join(s) s = unhexlify(h) k = tools.parse_script(s) address = functions.hash_to_address(k["addressHash"], script_hash=True, witness_version=None, testnet=False) self.assertEqual(address, "3F527pX8o2pgr6FuNdNvngA2Do2wVvDoZi") self.assertEqual(k["type"], "P2SH") self.assertEqual(k["nType"], 1) self.assertEqual(k["reqSigs"], None) self.assertEqual(functions.address_to_script(address, 1), h) s = [ HEX_OPCODE['OP_3'], '21', '021ecd2e5eb5dbd7c8e59f66e37da2ae95f7d61a07f4b2567c3bb10bbb1b2ec953', '21', '023bd78b0e7606fc1205721e4403355dfc0dbe4f1b15712cbbb17b1dc323cc8c0b', '21', '02afa49972b95496b39e7adc13437239ded698d81c85e9d029debb88641733528d', '21', '02b63fe474a5daac88eb74fdc9ce0ec69a8f8b81d2d89ac8d518a2f54d4bcaf4a5', '21', '02fb394aaf232e114c06b1d1ca15f97602d2377c33e6fe5a1287421b09b08a5a3e', '21', '03fedb540dd71a0211170b1857a3888d9f950231ecd0fcc7a37ffe094721ca151f', HEX_OPCODE['OP_6'], HEX_OPCODE['OP_CHECKMULTISIG'] ] h = ''.join(s) s = unhexlify(h) k = tools.parse_script(s) sh = tools.script_to_hash(h, 0, 0) address = functions.hash_to_address(sh, script_hash=True, witness_version=None, testnet=False) self.assertEqual(address, "3D2oetdNuZUqQHPJmcMDDHYoqkyNVsFk9r") self.assertEqual(k["type"], "MULTISIG") self.assertEqual(k["nType"], 4) self.assertEqual(k["reqSigs"], 3) s = [ HEX_OPCODE['OP_0'], '21', '021ecd2e5eb5dbd7c8e59f66e37da2ae95f7d61a07f4b2567c3bb10bbb1b2ec953', '21', '023bd78b0e7606fc1205721e4403355dfc0dbe4f1b15712cbbb17b1dc323cc8c0b', '21', '02afa49972b95496b39e7adc13437239ded698d81c85e9d029debb88641733528d', '21', '02b63fe474a5daac88eb74fdc9ce0ec69a8f8b81d2d89ac8d518a2f54d4bcaf4a5', '21', '02fb394aaf232e114c06b1d1ca15f97602d2377c33e6fe5a1287421b09b08a5a3e', '21', '03fedb540dd71a0211170b1857a3888d9f950231ecd0fcc7a37ffe094721ca151f', HEX_OPCODE['OP_6'], HEX_OPCODE['OP_CHECKMULTISIG'] ] h = ''.join(s) s = unhexlify(h) k = tools.parse_script(s) sh = tools.script_to_hash(h, 0, 0) self.assertEqual(k["type"], "NON_STANDARD") self.assertEqual(k["nType"], 7) self.assertEqual(k["reqSigs"], 20) s = [ HEX_OPCODE['OP_1'], '21', '021ecd2e5eb5dbd7c8e59f66e37da2ae95f7d61a07f4b2567c3bb10bbb1b2ec953', '21', '023bd78b0e7606fc1205721e4403355dfc0dbe4f1b15712cbbb17b1dc323cc8c0b', '21', '02afa49972b95496b39e7adc13437239ded698d81c85e9d029debb88641733528d', '21', '02b63fe474a5daac88eb74fdc9ce0ec69a8f8b81d2d89ac8d518a2f54d4bcaf4a5', '21', '02fb394aaf232e114c06b1d1ca15f97602d2377c33e6fe5a1287421b09b08a5a3e', '21', '03fedb540dd71a0211170b1857a3888d9f950231ecd0fcc7a37ffe094721ca151f', HEX_OPCODE['OP_6'], HEX_OPCODE['OP_CHECKMULTISIG'] ] h = ''.join(s) s = unhexlify(h) k = tools.parse_script(s) self.assertEqual(k["type"], "MULTISIG") self.assertEqual(k["nType"], 4) self.assertEqual(k["reqSigs"], 1) s = [ HEX_OPCODE['OP_1'], HEX_OPCODE['OP_1'], '21', '021ecd2e5eb5dbd7c8e59f66e37da2ae95f7d61a07f4b2567c3bb10bbb1b2ec953', '21', '023bd78b0e7606fc1205721e4403355dfc0dbe4f1b15712cbbb17b1dc323cc8c0b', '21', '02afa49972b95496b39e7adc13437239ded698d81c85e9d029debb88641733528d', '21', '02b63fe474a5daac88eb74fdc9ce0ec69a8f8b81d2d89ac8d518a2f54d4bcaf4a5', '21', '02fb394aaf232e114c06b1d1ca15f97602d2377c33e6fe5a1287421b09b08a5a3e', '21', '03fedb540dd71a0211170b1857a3888d9f950231ecd0fcc7a37ffe094721ca151f', HEX_OPCODE['OP_6'], HEX_OPCODE['OP_CHECKMULTISIG'] ] h = ''.join(s) s = unhexlify(h) k = tools.parse_script(s) sh = tools.script_to_hash(h, 0, 0) self.assertEqual(k["type"], "NON_STANDARD") self.assertEqual(k["nType"], 7) self.assertEqual(k["reqSigs"], 1) s = [ HEX_OPCODE['OP_1'], HEX_OPCODE['OP_6'], '21', '021ecd2e5eb5dbd7c8e59f66e37da2ae95f7d61a07f4b2567c3bb10bbb1b2ec953', '21', '023bd78b0e7606fc1205721e4403355dfc0dbe4f1b15712cbbb17b1dc323cc8c0b', '21', '02afa49972b95496b39e7adc13437239ded698d81c85e9d029debb88641733528d', '21', '02b63fe474a5daac88eb74fdc9ce0ec69a8f8b81d2d89ac8d518a2f54d4bcaf4a5', '21', '02fb394aaf232e114c06b1d1ca15f97602d2377c33e6fe5a1287421b09b08a5a3e', '21', '03fedb540dd71a0211170b1857a3888d9f950231ecd0fcc7a37ffe094721ca151f', HEX_OPCODE['OP_6'], HEX_OPCODE['OP_CHECKMULTISIG'] ] h = ''.join(s) s = unhexlify(h) k = tools.parse_script(s) self.assertEqual(k["type"], "NON_STANDARD") self.assertEqual(k["nType"], 7) self.assertEqual(k["reqSigs"], 6) s = [ HEX_OPCODE['OP_1'], HEX_OPCODE['OP_6'], '21', '021ecd2e5eb5dbd7c8e59f66e37da2ae95f7d61a07f4b2567c3bb10bbb1b2ec953', '21', '023bd78b0e7606fc1205721e4403355dfc0dbe4f1b15712cbbb17b1dc323cc8c0b', '21', '02afa49972b95496b39e7adc13437239ded698d81c85e9d029debb88641733528d', '21', '02b63fe474a5daac88eb74fdc9ce0ec69a8f8b81d2d89ac8d518a2f54d4bcaf4a5', '21', '02fb394aaf232e114c06b1d1ca15f97602d2377c33e6fe5a1287421b09b08a5a3e', '21', '03fedb540dd71a0211170b1857a3888d9f950231ecd0fcc7a37ffe094721ca151f', HEX_OPCODE['OP_6'], HEX_OPCODE['OP_6'], HEX_OPCODE['OP_CHECKMULTISIG'] ] h = ''.join(s) s = unhexlify(h) k = tools.parse_script(s) self.assertEqual(k["type"], "NON_STANDARD") self.assertEqual(k["nType"], 7) self.assertEqual(k["reqSigs"], 20) s = [ HEX_OPCODE['OP_1'], HEX_OPCODE['OP_6'], '21', '021ecd2e5eb5dbd7c8e59f66e37da2ae95f7d61a07f4b2567c3bb10bbb1b2ec953', '21', '023bd78b0e7606fc1205721e4403355dfc0dbe4f1b15712cbbb17b1dc323cc8c0b', '21', '02afa49972b95496b39e7adc13437239ded698d81c85e9d029debb88641733528d', '21', '02b63fe474a5daac88eb74fdc9ce0ec69a8f8b81d2d89ac8d518a2f54d4bcaf4a5', '21', '02fb394aaf232e114c06b1d1ca15f97602d2377c33e6fe5a1287421b09b08a5a3e', '21', '03fedb540dd71a0211170b1857a3888d9f950231ecd0fcc7a37ffe094721ca151f', HEX_OPCODE['OP_6'], HEX_OPCODE['OP_CHECKSIG'], HEX_OPCODE['OP_CHECKMULTISIG'] ] h = ''.join(s) s = unhexlify(h) k = tools.parse_script(s) self.assertEqual(k["type"], "NON_STANDARD") self.assertEqual(k["nType"], 7) self.assertEqual(k["reqSigs"], 21) s = [ HEX_OPCODE['OP_1'], HEX_OPCODE['OP_6'], '21', '021ecd2e5eb5dbd7c8e59f66e37da2ae95f7d61a07f4b2567c3bb10bbb1b2ec953', '21', '023bd78b0e7606fc1205721e4403355dfc0dbe4f1b15712cbbb17b1dc323cc8c0b', '21', '02afa49972b95496b39e7adc13437239ded698d81c85e9d029debb88641733528d', '21', '02b63fe474a5daac88eb74fdc9ce0ec69a8f8b81d2d89ac8d518a2f54d4bcaf4a5', '21', '02fb394aaf232e114c06b1d1ca15f97602d2377c33e6fe5a1287421b09b08a5a3e', '21', '03fedb540dd71a0211170b1857a3888d9f950231ecd0fcc7a37ffe094721ca151f', '21', '02fb394aaf232e114c06b1d1ca15f97602d2377c33e6fe5a1287421b09b08a5a3e', HEX_OPCODE['OP_6'], HEX_OPCODE['OP_CHECKMULTISIG'] ] h = ''.join(s) s = unhexlify(h) k = tools.parse_script(s) self.assertEqual(k["type"], "NON_STANDARD") self.assertEqual(k["nType"], 7) self.assertEqual(k["reqSigs"], 20) s = [ HEX_OPCODE['OP_6'], '21', '021ecd2e5eb5dbd7c8e59f66e37da2ae95f7d61a07f4b2567c3bb10bbb1b2ec953', '21', '023bd78b0e7606fc1205721e4403355dfc0dbe4f1b15712cbbb17b1dc323cc8c0b', '21', '02afa49972b95496b39e7adc13437239ded698d81c85e9d029debb88641733528d', '21', '02b63fe474a5daac88eb74fdc9ce0ec69a8f8b81d2d89ac8d518a2f54d4bcaf4a5', '21', '02fb394aaf232e114c06b1d1ca15f97602d2377c33e6fe5a1287421b09b08a5a3e', '21', '03fedb540dd71a0211170b1857a3888d9f950231ecd0fcc7a37ffe094721ca151f', '21', '02fb394aaf232e114c06b1d1ca15f97602d2377c33e6fe5a1287421b09b08a5a3e', HEX_OPCODE['OP_6'], HEX_OPCODE['OP_CHECKMULTISIG'] ] h = ''.join(s) s = unhexlify(h) k = tools.parse_script(s) self.assertEqual(k["type"], "NON_STANDARD") self.assertEqual(k["nType"], 7) self.assertEqual(k["reqSigs"], 20) s = [ HEX_OPCODE['OP_6'], '21', '023bd78b0e7606fc1205721e4403355dfc0dbe4f1b15712cbbb17b1dc323cc8c0b', '21', '02afa49972b95496b39e7adc13437239ded698d81c85e9d029debb88641733528d', '21', '02b63fe474a5daac88eb74fdc9ce0ec69a8f8b81d2d89ac8d518a2f54d4bcaf4a5', '21', '02fb394aaf232e114c06b1d1ca15f97602d2377c33e6fe5a1287421b09b08a5a3e', '21', '03fedb540dd71a0211170b1857a3888d9f950231ecd0fcc7a37ffe094721ca151f', '21', '02fb394aaf232e114c06b1d1ca15f97602d2377c33e6fe5a1287421b09b08a5a3e', HEX_OPCODE['OP_6'], HEX_OPCODE['OP_CHECKMULTISIG'] ] h = ''.join(s) s = unhexlify(h) k = tools.parse_script(s) self.assertEqual(k["type"], "MULTISIG") self.assertEqual(k["nType"], 4) self.assertEqual(k["reqSigs"], 6) s = [ HEX_OPCODE['OP_1'], '21', '023bd78b0e7606fc1205721e4403355dfc0dbe4f1b15712cbbb17b1dc323cc8c0b', '21', '02afa49972b95496b39e7adc13437239ded698d81c85e9d029debb88641733528d', '21', '02b63fe474a5daac88eb74fdc9ce0ec69a8f8b81d2d89ac8d518a2f54d4bcaf4a5', '21', '02fb394aaf232e114c06b1d1ca15f97602d2377c33e6fe5a1287421b09b08a5a3e', '21', '03fedb540dd71a0211170b1857a3888d9f950231ecd0fcc7a37ffe094721ca151f', '21', '02fb394aaf232e114c06b1d1ca15f97602d2377c33e6fe5a1287421b09b08a5a3e', HEX_OPCODE['OP_6'], HEX_OPCODE['OP_CHECKMULTISIG'] ] h = ''.join(s) s = unhexlify(h) k = tools.parse_script(s) self.assertEqual(k["type"], "MULTISIG") self.assertEqual(k["nType"], 4) self.assertEqual(k["reqSigs"], 1) s = [ HEX_OPCODE['OP_1'], '21', '02afa49972b95496b39e7adc13437239ded698d81c85e9d029debb88641733528d', '21', '02b63fe474a5daac88eb74fdc9ce0ec69a8f8b81d2d89ac8d518a2f54d4bcaf4a5', '21', '02fb394aaf232e114c06b1d1ca15f97602d2377c33e6fe5a1287421b09b08a5a3e', '21', '03fedb540dd71a0211170b1857a3888d9f950231ecd0fcc7a37ffe094721ca151f', '21', '02fb394aaf232e114c06b1d1ca15f97602d2377c33e6fe5a1287421b09b08a5a3e', HEX_OPCODE['OP_6'], HEX_OPCODE['OP_CHECKMULTISIG'] ] h = ''.join(s) s = unhexlify(h) k = tools.parse_script(s) self.assertEqual(k["type"], "NON_STANDARD") self.assertEqual(k["nType"], 7) self.assertEqual(k["reqSigs"], 20) s = [ HEX_OPCODE['OP_1'], '21', '023bd78b0e7606fc1205721e4403355dfc0dbe4f1b15712cbbb17b1dc323cc8c0b', '21', '02afa49972b95496b39e7adc13437239ded698d81c85e9d029debb88641733528d', HEX_OPCODE['OP_DUP'], '21', '02fb394aaf232e114c06b1d1ca15f97602d2377c33e6fe5a1287421b09b08a5a3e', '21', '03fedb540dd71a0211170b1857a3888d9f950231ecd0fcc7a37ffe094721ca151f', '21', '02fb394aaf232e114c06b1d1ca15f97602d2377c33e6fe5a1287421b09b08a5a3e', HEX_OPCODE['OP_6'], HEX_OPCODE['OP_CHECKMULTISIG'] ] h = ''.join(s) s = unhexlify(h) k = tools.parse_script(s) self.assertEqual(k["type"], "NON_STANDARD") self.assertEqual(k["nType"], 7) self.assertEqual(k["reqSigs"], 20)