def __init__(self, bip32: Bip32Base, coin_conf: BipCoinConf) -> None: """ Construct class. Args: bip32 (Bip32Base object): Bip32Base object coin_conf (BipCoinConf) : BipCoinConf object Returns: Bip44DepthError: If the Bip32 object depth is not valid """ depth = bip32.Depth() # If the Bip32 is public-only, the depth shall start from the account level because hardened derivation is # used below it, which is not possible with public keys if bip32.IsPublicOnly(): if depth < Bip44Levels.ACCOUNT or depth > Bip44Levels.ADDRESS_INDEX: raise Bip44DepthError( f"Depth of the public-only Bip32 object ({depth}) is below account level or " f"beyond address index level") # If the Bip32 object is not public-only, any depth is fine as long as it is not greater # than address index level else: if depth < 0 or depth > Bip44Levels.ADDRESS_INDEX: raise Bip44DepthError( f"Depth of the Bip32 object ({depth}) is invalid or beyond address index level" ) # Finally, initialize class self.m_bip32 = bip32 self.m_coin_conf = coin_conf
def _AddressIndexGeneric(cls, bip_obj: Bip44Base, addr_idx: int) -> Bip44Base: """ Derive a child key from the specified address index and return a new Bip44Base object. It shall be called from a child class. Args: bip_obj (Bip44Base object): Bip44Base object addr_idx (int) : Address index Returns: Bip44Base object: Bip44Base object Raises: Bip44DepthError: If the current depth is not suitable for deriving keys Bip32KeyError: If the derivation results in an invalid key """ if not cls.IsLevel(bip_obj, Bip44Levels.CHANGE): raise Bip44DepthError( f"Current depth ({bip_obj.m_bip32.Depth().ToInt()}) is not suitable for deriving address" ) # Use hardened derivation if not-hardended is not supported if not bip_obj.m_bip32.IsPrivateUnhardenedDerivationSupported(): addr_idx = Bip32Utils.HardenIndex(addr_idx) return cls(bip_obj.m_bip32.ChildKey(addr_idx), bip_obj.m_coin_conf)
def _ChangeGeneric(cls, bip_obj: Bip44Base, change_type: Bip44Changes) -> Bip44Base: """ Derive a child key from the specified chain type and return a new Bip44Base object. It shall be called from a child class. Args: bip_obj (Bip44Base object): Bip44Base object change_type (Bip44Changes): Change type, must a Bip44Changes enum Returns: Bip44Base object: Bip44Base object Raises: TypeError: If chain index is not a Bip44Changes enum Bip44DepthError: If the current depth is not suitable for deriving keys Bip32KeyError: If the derivation results in an invalid key """ if not isinstance(change_type, Bip44Changes): raise TypeError( "Change index is not an enumerative of Bip44Changes") if not cls.IsLevel(bip_obj, Bip44Levels.ACCOUNT): raise Bip44DepthError( f"Current depth ({bip_obj.m_bip32.Depth().ToInt()}) is not suitable for deriving change" ) # Use hardened derivation if not-hardended is not supported if not bip_obj.m_bip32.IsPrivateUnhardenedDerivationSupported(): change_idx = Bip32Utils.HardenIndex(int(change_type)) else: change_idx = int(change_type) return cls(bip_obj.m_bip32.ChildKey(change_idx), bip_obj.m_coin_conf)
def _DeriveDefaultPathGeneric(cls, bip_obj: Bip44Base, purpose: int) -> Bip44Base: """ Derive the default coin path and return a new Bip44Base object. It shall be called from a child class. Args: bip_obj (Bip44Base object): Bip44Base object purpose (int) : Purpose Returns: Bip44Base object: Bip44Base object Raises: Bip44DepthError: If the current depth is not suitable for deriving keys Bip32KeyError: If the derivation results in an invalid key """ if not cls.IsLevel(bip_obj, Bip44Levels.MASTER): raise Bip44DepthError( f"Current depth ({bip_obj.m_bip32.Depth().ToInt()}) is not suitable for deriving default path" ) # Derive purpose and coin by default bip_obj = cls._PurposeGeneric(bip_obj, purpose) bip_obj = cls._CoinGeneric(bip_obj) # Derive the remaining path return cls( bip_obj.m_bip32.DerivePath(bip_obj.m_coin_conf.DefaultPath()), bip_obj.m_coin_conf)
def _PurposeGeneric(cls, bip_obj: Bip44Base, purpose: int) -> Bip44Base: """ Derive a child key from the purpose and return a new Bip44Base object. It shall be called from a child class. Args: bip_obj (Bip44Base object): Bip44Base object purpose (int) : Purpose Returns: Bip44Base object: Bip44Base object Raises: Bip44DepthError: If the current depth is not suitable for deriving keys Bip32KeyError: If the derivation results in an invalid key """ if not cls.IsLevel(bip_obj, Bip44Levels.MASTER): raise Bip44DepthError( f"Current depth ({bip_obj.m_bip32.Depth().ToInt()}) is not suitable for deriving purpose" ) return cls(bip_obj.m_bip32.ChildKey(purpose), bip_obj.m_coin_conf)
def _AccountGeneric(cls, bip_obj: Bip44Base, acc_idx: int) -> Bip44Base: """ Derive a child key from the specified account index and return a new Bip44Base object. It shall be called from a child class. Args: bip_obj (Bip44Base object): Bip44Base object acc_idx (int) : Account index Returns: Bip44Base object: Bip44Base object Raises: Bip44DepthError: If the current depth is not suitable for deriving keys Bip32KeyError: If the derivation results in an invalid key """ if not cls.IsLevel(bip_obj, Bip44Levels.COIN): raise Bip44DepthError( f"Current depth ({bip_obj.m_bip32.Depth().ToInt()}) is not suitable for deriving account" ) return cls(bip_obj.m_bip32.ChildKey(Bip32Utils.HardenIndex(acc_idx)), bip_obj.m_coin_conf)
def _CoinGeneric(cls, bip_obj: Bip44Base) -> Bip44Base: """ Derive a child key from the coin type specified at construction and return a new Bip44Base object. It shall be called from a child class. Args: bip_obj (Bip44Base object): Bip44Base object Returns: Bip44Base object: Bip44Base object Raises: Bip44DepthError: If the current depth is not suitable for deriving keys Bip32KeyError: If the derivation results in an invalid key """ if not cls.IsLevel(bip_obj, Bip44Levels.PURPOSE): raise Bip44DepthError( f"Current depth ({bip_obj.m_bip32.Depth().ToInt()}) is not suitable for deriving coin" ) coin_idx = bip_obj.m_coin_conf.CoinIndex() return cls(bip_obj.m_bip32.ChildKey(Bip32Utils.HardenIndex(coin_idx)), bip_obj.m_coin_conf)