From 9127c12fa3e88f6ba33fc778f05381f4c3cc9c9d Mon Sep 17 00:00:00 2001 From: SomberNight Date: Tue, 28 Feb 2023 17:05:19 +0000 Subject: [PATCH] descriptor.py: do more validation in PubkeyProvider, and add tests --- electrum/descriptor.py | 4 ++++ electrum/tests/test_descriptor.py | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/electrum/descriptor.py b/electrum/descriptor.py index 909c9de2c..824fe75fe 100644 --- a/electrum/descriptor.py +++ b/electrum/descriptor.py @@ -186,6 +186,8 @@ class PubkeyProvider(object): if wildcard_count == 1: if deriv_path[-1] != "*": raise ValueError("wildcard in descriptor only allowed in last position") + if deriv_path[0] != "/": + raise ValueError(f"deriv_path suffix must start with a '/'. got {deriv_path!r}") # Make ExtendedKey from pubkey if it isn't hex self.extkey = None try: @@ -194,6 +196,8 @@ class PubkeyProvider(object): except Exception: # Not hex, maybe xpub (but don't allow ypub/zpub) self.extkey = BIP32Node.from_xkey(pubkey, allow_custom_headers=False) + if deriv_path and self.extkey is None: + raise ValueError("deriv_path suffix present for simple pubkey") @classmethod def parse(cls, s: str) -> 'PubkeyProvider': diff --git a/electrum/tests/test_descriptor.py b/electrum/tests/test_descriptor.py index 096f48f74..a27367592 100644 --- a/electrum/tests/test_descriptor.py +++ b/electrum/tests/test_descriptor.py @@ -16,6 +16,7 @@ from electrum.descriptor import ( PKHDescriptor, WPKHDescriptor, WSHDescriptor, + PubkeyProvider, ) from electrum import ecc from electrum.util import bfh @@ -335,3 +336,27 @@ class TestDescriptor(ElectrumTestCase): desc = parse_descriptor("wpkh([535e473f/0h]ypub6TLJVy4mZfqBJhoQBTgDR1TzM7s91WbVnMhZj31swV6xxPiwCqeGYrBn2dNHbDrP86qqxbM6FNTX3VjhRjNoXYyBAR5G3o75D3r2djmhZwM/0/*)") with self.assertRaises(ValueError): # only standard xpub/xprv allowed desc = parse_descriptor("wpkh([535e473f/0h]zpub6nAZodjgiMNf9zzX1pTqd6ZVX61ax8azhUDnWRumKVUr1VYATVoqAuqv3qKsb8WJXjxei4wei2p4vnMG9RnpKnen2kmgdhvZUmug2NnHNsr/0/*)") + + def test_pubkey_provider_deriv_path(self): + xpub = "xpub68W3CJPrQzHhTQcHM6tbCvNVB9ih4tbzsFBLwe7zZUj5uHuhxBUhvnXe1RQhbKCTiTj3D7kXni6yAD88i2xnjKHaJ5NqTtHawKnPFCDnmo4" + # valid: + pp = PubkeyProvider(origin=None, pubkey=xpub, deriv_path="/1/7") + pp = PubkeyProvider(origin=None, pubkey=xpub, deriv_path="/1/*") + # invalid: + with self.assertRaises(ValueError): + pp = PubkeyProvider(origin=None, pubkey=xpub, deriv_path="1") + with self.assertRaises(ValueError): + pp = PubkeyProvider(origin=None, pubkey=xpub, deriv_path="1/7") + with self.assertRaises(ValueError): + pp = PubkeyProvider(origin=None, pubkey=xpub, deriv_path="m/1/7") + with self.assertRaises(ValueError): + pp = PubkeyProvider(origin=None, pubkey=xpub, deriv_path="*/7") + with self.assertRaises(ValueError): + pp = PubkeyProvider(origin=None, pubkey=xpub, deriv_path="*/*") + + pubkey_hex = "02a0507c8bb3d96dfd7731bafb0ae30e6ed10bbadd6a9f9f88eaf0602b9cc99adc" + # valid: + pp = PubkeyProvider(origin=None, pubkey=pubkey_hex, deriv_path=None) + # invalid: + with self.assertRaises(ValueError): + pp = PubkeyProvider(origin=None, pubkey=pubkey_hex, deriv_path="/1/7")