def __init__(self, key=None, address_type="P2WPKH", testnet=False, compressed=True): 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") #: flag for testnet network address (boolean) 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)
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 script_to_address(script, testnet=False): """ Decode script to address (base58/bech32 format). :param script: script in bytes string or HEX encoded string format. :param testnet: (optional) flag for testnet network, by default is False. :return: address in base58/bech32 format or None. """ d = parse_script(script) if "addressHash" in d: witness_version = 0 if d["nType"] in (5, 6) else None script_hash = True if d["nType"] in (1, 6) else False return hash_to_address(d["addressHash"], testnet=testnet, script_hash=script_hash, witness_version=witness_version) return None
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)
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
def test_hash_to_address(): pc = "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" h = hash160(pc) s = bytes([len(bytes_from_hex(pc)) ]) + bytes_from_hex(pc) + BYTE_OPCODE["OP_CHECKSIG"] assert hash_to_address(h) == "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4" assert hash_to_address( h, testnet=True) == "tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx" h = script_to_hash(s, witness=True, hex=hex) assert hash_to_address( h) == "bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3" assert hash_to_address( h, testnet=True ) == "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7" pk = "03b635dbdc16dbdf4bb9cf5b55e7d03e514fb04dcef34208155c7d3ec88e9045f4" h = hash160(pk) assert hash_to_address( h, witness_version=None) == "1Fs2Xqrk4P2XADaJeZWykaGXJ4HEb6RyT1" assert hash_to_address( h, witness_version=None, testnet=True) == "mvNyptwisQTmwL3vN8VMaVUrA3swVCX83c" # p2wpkh inside p2sh p = "L32a8Mo1LgvjrVDbzcc3NkuUfkpoLsf2Y2oEWkV4t1KpQdFzuyff" pk = private_to_public_key(p) script = b'\x00\x14' + hash160(pk) script_hash = hash160(script) assert hash_to_address( script_hash, script_hash=1, witness_version=None) == "33am12q3Bncnn3BfvLYHczyv23Sq2Wbwjw" assert hash_to_address(script_hash, script_hash=1, witness_version=None, testnet=1) == "2Mu8y4mm4oF88yppDbUAAEwyBEPezrx7CLh" with pytest.raises(ValueError): hash_to_address(29023) with pytest.raises(ValueError): hash_to_address(h + b"33", witness_version=None) with pytest.raises(ValueError): hash_to_address(h + b"33", witness_version=0)