1111
1212
1313class BIP32 :
14- def __init__ (self , chaincode , privkey = None , pubkey = None ):
14+ def __init__ (self , chaincode , privkey = None , pubkey = None , fingerprint = None ,
15+ depth = 0 , index = 0 ):
1516 """
1617 :param chaincode: The master chaincode, used to derive keys. As bytes.
1718 :param privkey: The master private key for this index (default 0).
@@ -20,6 +21,13 @@ def __init__(self, chaincode, privkey=None, pubkey=None):
2021 :param pubkey: The master public key for this index (default 0).
2122 Can be None if private key is specified.
2223 Compressed format. As bytes.
24+ :param fingeprint: If we are instanciated from an xpub/xpriv, we need
25+ to remember the parent's pubkey fingerprint to
26+ reserialize !
27+ :param depth: If we are instanciated from an existing extended key, we
28+ need this for serialization.
29+ :param index: If we are instanciated from an existing extended key, we
30+ need this for serialization.
2331 """
2432 assert isinstance (chaincode , bytes )
2533 assert privkey is not None or pubkey is not None
@@ -32,6 +40,9 @@ def __init__(self, chaincode, privkey=None, pubkey=None):
3240 self .master_chaincode = chaincode
3341 self .master_privkey = privkey
3442 self .master_pubkey = pubkey
43+ self .parent_fingerprint = fingerprint
44+ self .depth = depth
45+ self .index = index
3546
3647 def get_extended_privkey_from_path (self , path ):
3748 """Get an extended privkey from a list of indexes (path).
@@ -111,7 +122,7 @@ def get_xpriv_from_path(self, path):
111122 else :
112123 parent_pubkey = self .get_pubkey_from_path (path [:- 1 ])
113124 chaincode , privkey = self .get_extended_privkey_from_path (path )
114- extended_key = _serialize_extended_key (privkey , len (path ),
125+ extended_key = _serialize_extended_key (privkey , self . depth + len (path ),
115126 parent_pubkey ,
116127 path [- 1 ], chaincode )
117128 return base58 .b58encode_check (extended_key ).decode ()
@@ -130,21 +141,27 @@ def get_xpub_from_path(self, path):
130141 else :
131142 parent_pubkey = self .get_pubkey_from_path (path [:- 1 ])
132143 chaincode , pubkey = self .get_extended_pubkey_from_path (path )
133- extended_key = _serialize_extended_key (pubkey , len (path ),
144+ extended_key = _serialize_extended_key (pubkey , self . depth + len (path ),
134145 parent_pubkey ,
135146 path [- 1 ], chaincode )
136147 return base58 .b58encode_check (extended_key ).decode ()
137148
138149 def get_master_xpriv (self ):
139150 """Get the encoded extended private key of the master private key"""
140- extended_key = _serialize_extended_key (self .master_privkey , 0 ,
141- None , 0 , self .master_chaincode )
151+ extended_key = _serialize_extended_key (self .master_privkey , self .depth ,
152+ self .parent_fingerprint ,
153+ self .index ,
154+ self .master_chaincode )
155+ print (extended_key )
156+ print (base58 .b58encode_check (extended_key ))
142157 return base58 .b58encode_check (extended_key ).decode ()
143158
144159 def get_master_xpub (self ):
145160 """Get the encoded extended public key of the master public key"""
146- extended_key = _serialize_extended_key (self .master_pubkey , 0 ,
147- None , 0 , self .master_chaincode )
161+ extended_key = _serialize_extended_key (self .master_pubkey , self .depth ,
162+ self .parent_fingerprint ,
163+ self .index ,
164+ self .master_chaincode )
148165 return base58 .b58encode_check (extended_key ).decode ()
149166
150167 @classmethod
@@ -153,11 +170,16 @@ def from_xpriv(cls, xpriv):
153170
154171 :param xpriv: (str) The encoded serialized extended private key.
155172 """
173+ print (xpriv )
156174 extended_key = base58 .b58decode_check (xpriv )
157175 (prefix , depth , fingerprint ,
158176 index , chaincode , key ) = _unserialize_extended_key (extended_key )
177+ serialized = _serialize_extended_key (key [1 :], depth , fingerprint , index ,
178+ chaincode )
179+ print (extended_key , serialized , extended_key == serialized )
180+ print (base58 .b58encode_check (extended_key ), base58 .b58encode_check (serialized ), extended_key == serialized )
159181 # We need to remove the trailing `0` before the actual private key !!
160- return BIP32 (chaincode , privkey = key [1 :], pubkey = None )
182+ return BIP32 (chaincode , key [1 :], None , fingerprint , depth , index )
161183
162184 @classmethod
163185 def from_xpub (cls , xpub ):
@@ -168,7 +190,7 @@ def from_xpub(cls, xpub):
168190 extended_key = base58 .b58decode_check (xpub )
169191 (prefix , depth , fingerprint ,
170192 index , chaincode , key ) = _unserialize_extended_key (extended_key )
171- return BIP32 (chaincode , privkey = None , pubkey = key )
193+ return BIP32 (chaincode , None , key , fingerprint , depth , index )
172194
173195 @classmethod
174196 def from_seed (cls , seed ):
@@ -178,4 +200,4 @@ def from_seed(cls, seed):
178200 """
179201 secret = hmac .new ("Bitcoin seed" .encode (), seed ,
180202 hashlib .sha512 ).digest ()
181- return BIP32 (secret [32 :], secret [:32 ], None )
203+ return BIP32 (secret [32 :], secret [:32 ])
0 commit comments