Skip to content

In "external signer mode", invalid descriptors will crash Bitcoin Core  #23627

@sstone

Description

@sstone

In "external signer" mode, when creating a new wallet, if descriptors returned by the external signer module are not valid bitcoin will crash instead of ignoring them and/or reporting an error.

This can be reproduced by running bitcoin core with the badsigner.py script below and creating a new wallet.

#! /usr/bin/env python3

import sys
import json
import shlex
import argparse
from enum import Enum

class chain(Enum):
    """
    The blockchain network to use
    """
    MAIN = 0 #: Bitcoin Main network
    TEST = 1 #: Bitcoin Test network
    REGTEST = 2 #: Bitcoin Core Regression Test network
    SIGNET = 3 #: Bitcoin Signet

    def __str__(self) -> str:
        return self.name.lower()

    def __repr__(self) -> str:
        return str(self)

    @staticmethod
    def argparse(s: str) :
        try:
            return chain[s.upper()]
        except KeyError:
            return s

def handler_enumerate(args):
    return [{"type": "badsigner", "model": "badsigner", "needs_pin_sent": False, "needs_passphrase_sent": False, "fingerprint": "b3c19bfc"}]

def handler_getdescriptors(args):
    return {"receive": ["pkh([b3c19bfc/44h/1h/0h]xpub6CRhJvXV8x2AKWvqi1ZSMFU6cbxzQiYrv3dxSUXCawjMJ1JzpqVsveH4way1yCmJm29KzH1zrVZmVwes4Qo6oXVE1HFn4fdiKrYJngqFFc6/0/*)#h26nxtl9", "sh(wpkh([b3c19bfc/49h/1h/0h]xpub6CoNoq3Tg4tGSpom2BSwL42gy864KHo3TXkHxLxBbhvCkgmdVXADQmiHbLZhX3Me1cYhRx7s25Lpm4LnT5zu395ANHsXB2QvT9tqJDAibTN/0/*))#32ry02yp", "wpkh([b3c19bfc/84h/1h/0h]xpub6DUcLgY1DfgDy2RV6q4djwwsLitaoZDumbribqrR8mP78fEtgZa1XEsqT5MWQ7gwLwKsTQPT28XLoVE5A97rDNTwMXjmzPaNijoCApCbWvp/0/*)#jftn8ppv"], "internal": ["pkh([b3c19bfc/44h/1h/0h]xpub6CRhJvXV8x2AKWvqi1ZSMFU6cbxzQiYrv3dxSUXCawjMJ1JzpqVsveH4way1yCmJm29KzH1zrVZmVwes4Qo6oXVE1HFn4fdiKrYJngqFFc6/1/*)#x7ljm70a", "sh(wpkh([b3c19bfc/49h/1h/0h]xpub6CoNoq3Tg4tGSpom2BSwL42gy864KHo3TXkHxLxBbhvCkgmdVXADQmiHbLZhX3Me1cYhRx7s25Lpm4LnT5zu395ANHsXB2QvT9tqJDAibTN/1/*))#ytdjh437", "wpkh([b3c19bfc/84h/1h/0h]xpub6DUcLgY1DfgDy2RV6q4djwwsLitaoZDumbribqrR8mP78fEtgZa1XEsqT5MWQ7gwLwKsTQPT28XLoVE5A97rDNTwMXjmzPaNijoCApCbWvp/1/*)#rawj6535"]}

def process_commands(cli_args):
    parser = argparse.ArgumentParser()
    parser.add_argument('--chain', help='Select chain to work with', type=chain.argparse, choices=list(chain), default=chain.MAIN)
    parser.add_argument('--fingerprint', '-f', help='Specify the device to connect to using the first 4 bytes of the hash160 of the master public key. It will connect to the first device that matches this fingerprint.')
    parser.add_argument("--ping", "-ping", action="store_true", help="Ping HSM and exit", default=None)

    subparsers = parser.add_subparsers(description='Commands', dest='command')
    subparsers.required = True

    enumerate_parser = subparsers.add_parser('enumerate', help='List all available devices')
    enumerate_parser.set_defaults(func=handler_enumerate)

    getdescriptors_parser = subparsers.add_parser('getdescriptors', help='Return receive and change descriptors for each supported address type, for import into a wallet.')
    getdescriptors_parser.add_argument('--account', help='BIP43 account', type=int, default=0)
    getdescriptors_parser.set_defaults(func=handler_getdescriptors)

    if any(arg == '--stdin' for arg in cli_args):
        while True:
            try:
                line = input()
                if line == '':
                    break
                cli_args.extend(shlex.split(line))
            except EOFError:
                break
    args = parser.parse_args(cli_args)
    return args.func(args)

if __name__ == '__main__':
    data = process_commands(sys.argv[1:])
    if data is not None:
        print(json.dumps(data))

This happens with the latest official 22.0 release, and also when using the latest master.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions