Source code for pybgl.classes.address

from pybgl.constants import *
from pybgl.opcodes import *
from pybgl.functions.tools import bytes_from_hex, int_to_var_int
from pybgl.functions.script import op_push_data, decode_script
from pybgl.functions.hash import hash160, sha256
from pybgl.functions.address import  hash_to_address, public_key_to_p2sh_p2wpkh_script
from pybgl.functions.key import (create_private_key,
                                 private_key_to_wif,
                                 is_wif_valid,
                                 wif_to_private_key,
                                 is_public_key_valid,
                                 private_to_public_key)

[docs]class PrivateKey(): """ The class for creating private key object. :param key: (optional) private key in HEX, bytes string or WIF format. In case no key specified new random private key will be created. :param compressed: (optional) if set to True private key corresponding compressed public key, by default is True. Recommended use only compressed public key. :param testnet: (optional) flag for testnet network, by default is False. """ 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 def __str__(self): return self.wif
[docs]class PublicKey(): """ The class for public key object. :param key: one of this types allowed: - private key is instance of ``PrivateKey`` class - private key HEX encoded string - private key 32 bytes string - private key in WIF format - public key in HEX encoded string - public key [33/65] bytes string In case no key specified with HEX or bytes string you have to provide flag for testnet and compressed key. WIF format and ``PrivateKey`` instance already contain this flags. For HEX or bytes public key only testnet flag has the meaning, comressed flag is determined according to the length of key. :param compressed: (optional) if set to True private key corresponding compressed public key, by default is True. Recommended use only compressed public key. :param testnet: (optional) flag for testnet network, by default is False. """ 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() def __str__(self): return self.hex
[docs]class Address(): """ The class for Address object. :param key: (optional) one of this types allowed: - private key WIF format - instance of ``PrivateKey`` - private key HEX encoded string - instance of ``PublicKey`` In case no key specified new Address will be created with random keys. :param address_type: (optional) P2PKH, PUBKEY, P2WPKH, P2SH_P2WPKH, by default is P2WPKH. :param testnet: (optional) flag for testnet network, by default is False. :param compressed: (optional) if set to True private key corresponding compressed public key, by default is True. Recommended use only compressed public key. In case instance is created from WIF private key, ``PrivateKey`` or ``PublicKey`` compressed and testnet flags already contain in initial key parameter and will be ignored. """ 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") #: 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) def __str__(self): return self.address
class ScriptAddress(): 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) @classmethod def multisig(cls, n, m, public_key_list, testnet=False, witness_version=0): """ The class method for creating a multisig address. :param n: count of required signatures (max 15). :param m: count of total addresses of participants (max 15). :param list address_list: addresses list, allowed types: - bytes or HEX encoded private key - private key in WIF format - PrivateKey instance, - bytes or HEX encoded public key - PublicKey instance """ if n > 15 or m > 15 or n > m or n < 1 or m < 1: raise TypeError("invalid n of m maximum 15 of 15 multisig allowed") if len(public_key_list) != m: raise TypeError("invalid address list count") script = bytes([0x50 + n]) for a in list(public_key_list): if isinstance(a, str): try: a = bytes.fromhex(a) except: if is_wif_valid(a): a = private_to_public_key(a, hex=False) pass if isinstance(a, Address): a = a.public_key.key elif isinstance(a, PublicKey): a = a.key elif isinstance(a, PrivateKey): a = private_to_public_key(a.key) if not isinstance(a, bytes): raise TypeError("invalid public key list element") if len(a) == 32: a = private_to_public_key(a) if len(a) != 33: raise TypeError("invalid public key list element size") script += b"%s%s" % (int_to_var_int(len(a)), a) script += b"%s%s" % (bytes([0x50 + m]),OP_CHECKMULTISIG) return cls(script, testnet=testnet, witness_version=witness_version)