Skip to content

Commit 21ef9ed

Browse files
committed
bip32: add a specific error for invalid inputs
This is not exhaustive, but should be enough to cover the usual type errors. Signed-off-by: Antoine Poinsot <darosior@protonmail.com>
1 parent 4a29247 commit 21ef9ed

3 files changed

Lines changed: 31 additions & 6 deletions

File tree

bip32/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from .bip32 import BIP32, PrivateDerivationError
1+
from .bip32 import BIP32, PrivateDerivationError, InvalidInputError
22
from .utils import BIP32DerivationError, HARDENED_INDEX
33

44
__version__ = "0.0.8"
@@ -7,5 +7,6 @@
77
"BIP32",
88
"BIP32DerivationError",
99
"PrivateDerivationError",
10+
"InvalidInputError",
1011
"HARDENED_INDEX",
1112
]

bip32/bip32.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ class PrivateDerivationError(ValueError):
1717
pass
1818

1919

20+
class InvalidInputError(ValueError):
21+
def __init__(self, message):
22+
self.message = message
23+
24+
2025
class BIP32:
2126
def __init__(self, chaincode, privkey=None, pubkey=None, fingerprint=None,
2227
depth=0, index=0, network="main"):
@@ -37,14 +42,21 @@ def __init__(self, chaincode, privkey=None, pubkey=None, fingerprint=None,
3742
need this for serialization.
3843
:param network: Either "main" or "test".
3944
"""
40-
assert isinstance(chaincode, bytes)
41-
assert privkey is not None or pubkey is not None
45+
if network not in ["main", "test"]:
46+
raise InvalidInputError("'network' must be one of 'main' or 'test'")
47+
if not isinstance(chaincode, bytes):
48+
raise InvalidInputError("'chaincode' must be bytes")
49+
if privkey is None and pubkey is None:
50+
raise InvalidInputError("Need at least a 'pubkey' or a 'privkey'")
4251
if privkey is not None:
43-
assert isinstance(privkey, bytes)
52+
if not isinstance(privkey, bytes):
53+
raise InvalidInputError("'privkey' must be bytes")
4454
if pubkey is not None:
45-
assert isinstance(pubkey, bytes)
55+
if not isinstance(pubkey, bytes):
56+
raise InvalidInputError("'pubkey' must be bytes")
4657
else:
4758
pubkey = _privkey_to_pubkey(privkey)
59+
4860
self.master_chaincode = chaincode
4961
self.master_privkey = privkey
5062
self.master_pubkey = pubkey
@@ -213,6 +225,9 @@ def from_xpriv(cls, xpriv):
213225
214226
:param xpriv: (str) The encoded serialized extended private key.
215227
"""
228+
if not isinstance(xpriv, str):
229+
raise InvalidInputError("'xpriv' must be a string")
230+
216231
extended_key = base58.b58decode_check(xpriv)
217232
(network, depth, fingerprint,
218233
index, chaincode, key) = _unserialize_extended_key(extended_key)
@@ -226,6 +241,9 @@ def from_xpub(cls, xpub):
226241
227242
:param xpub: (str) The encoded serialized extended public key.
228243
"""
244+
if not isinstance(xpub, str):
245+
raise InvalidInputError("'xpub' must be a string")
246+
229247
extended_key = base58.b58decode_check(xpub)
230248
(network, depth, fingerprint,
231249
index, chaincode, key) = _unserialize_extended_key(extended_key)

tests/test_bip32.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
import os
33
import pytest
44

5-
from bip32 import BIP32, HARDENED_INDEX, PrivateDerivationError
5+
from bip32 import (
6+
BIP32, HARDENED_INDEX, PrivateDerivationError, InvalidInputError
7+
)
68

79

810
def test_vector_1():
@@ -174,3 +176,7 @@ def test_sanity_checks():
174176
bip32.get_privkey_from_path([9, 8])
175177
bip32.get_pubkey_from_path("m/0'/1")
176178
bip32.get_xpub_from_path("m/10000'/18")
179+
180+
# We can't create a BIP32 for an unknown network (to test InvalidInputError)
181+
with pytest.raises(InvalidInputError, match="'network' must be one of"):
182+
BIP32.from_seed(os.urandom(32), network="invalid_net")

0 commit comments

Comments
 (0)