Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

External signer support - Wallet Box edition #16546

Merged
merged 15 commits into from
Feb 23, 2021

Conversation

Sjors
Copy link
Member

@Sjors Sjors commented Aug 4, 2019

Big picture overview in this gist.

This PR lets bitcoind call an arbitrary command -signer=<cmd>, e.g. a hardware wallet driver, where it can fetch public keys, ask to display an address, and sign a transaction (using PSBT under the hood).

It's design to work with https://github.com/bitcoin-core/HWI, which supports multiple hardware wallets. Any command with the same arguments and return values will work. It simplifies the manual procedure described here.

Usage is documented in doc/external-signer.md, which also describes what protocol a different signer binary should conform to.

Use --enable-external-signer to opt in, requires Boost::Process:

Options used to compile and link:
  with wallet     = yes
  with gui / qt   = no
  external signer = yes

It adds the following RPC methods:

  • enumeratesigners: asks for a list of signers (e.g. devices) and their master key fingerprint
  • signerdisplayaddress <address>: asks to display an address

It enhances the following RPC methods:

  • createwallet: takes an additional external_signer argument and fetches keys from device
  • send: automatically sends transaction to device and waits

Usage TL&DR:

  • clone HWI repo somewhere and launch bitcoind -signer=../HWI/hwi.py
  • check if you can see your hardware device: bitcoin-cli enumeratesigners
  • create wallet and auto import keys bitcoin-cli createwallet "hww" true true "" true true true
  • display address on device: bitcoin-cli signerdisplayaddress ...
  • to spend, use send RPC and approve transaction on device

Prerequisites:

Potentially useful followups:

@DrahtBot
Copy link
Contributor

DrahtBot commented Aug 4, 2019

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Conflicts

Reviewers, this pull request conflicts with the following ones:

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

@@ -2653,6 +2673,8 @@ static UniValue createwallet(const JSONRPCRequest& request)
{"blank", RPCArg::Type::BOOL, /* default */ "false", "Create a blank wallet. A blank wallet has no keys or HD seed. One can be set using sethdseed."},
{"passphrase", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Encrypt the wallet with this passphrase."},
{"avoid_reuse", RPCArg::Type::BOOL, /* default */ "false", "Keep track of coin reuse, and treat dirty and clean coins differently with privacy considerations in mind."},
{"descriptors", RPCArg::Type::BOOL, /* default */ "false", "Create a native descriptor wallet. The wallet will use descriptors internally to handle address creation"},
{"external_signer", RPCArg::Type::BOOL, /* default */ "false", "Use an external signer such as a hardware wallet. Requires -signer to be configured. Wallet creation will fail if keys cannot be fetched. Requires disable_private_keys and descriptors set to true."},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This list-of-bools thing seems like a terrible idea...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, I was complaining about that when blank was added :-)


if (pwallet->IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER)) {
const std::string command = gArgs.GetArg("-signer", DEFAULT_EXTERNAL_SIGNER);
if (command == "") throw std::runtime_error(std::string(__func__) + ": restart bitcoind with -signer=<cmd>");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if there are multiple wallets, with different signers?

IMO -signer needs to be replaced with either a wallet-stored path, or a path provided when the wallet is loaded...

Copy link
Member Author

@Sjors Sjors Aug 5, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Storing signer in the wallet makes sense, but I also think it can wait for a later PR. In practice afaik the only tool that currently works is HWI and it can handle multiple wallets. In the long run however I do hope that wallet manufactures provide their own software that just uses the same commands / responses.

@Relaxo143
Copy link

Can we expect this to be merged and included in 0.19? It's a really useful and requested feature! Thanks to everyone who is working on it.

@Sjors
Copy link
Member Author

Sjors commented Sep 16, 2019

@Relaxo143 not a chance; this is still work in progress and there's several pull requests that need to be reviewed and merged first. There's also a feature freeze on 0.19.

@Sjors
Copy link
Member Author

Sjors commented Sep 16, 2019

I dropped the dependency on my new send RPC proposal #16378, in favor of just tweaking sendmany and sendtoaddress. It's less powerful, but should reduce the review burden once native descriptors are merged.

@Sjors Sjors mentioned this pull request Sep 17, 2019
2 tasks
@laanwj
Copy link
Member

laanwj commented Feb 23, 2021

re-ACK f75e0c1

@laanwj laanwj merged commit a9335e4 into bitcoin:master Feb 23, 2021
Create a wallet, this automatically imports the public keys:

```sh
$ bitcoin-cli createwallet "hww" true true "" true true true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Would be nice to use named args

},
RPCExamples{""},
[](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why does this rpc require a wallet?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might get rid of that requirement in a followup.

sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Feb 23, 2021
@Sjors Sjors deleted the 2019/08/hww-box2 branch February 23, 2021 19:35
maflcko pushed a commit to maflcko/bitcoin-core that referenced this pull request Feb 24, 2021
…ion and typos

8b08d0f build, doc: Fix configure script output indentation and typos (Hennadii Stepanov)

Pull request description:

  This PR is follow up of bitcoin#16546, that breaks the `configure` script output indentation for gui/qt/qr lines:
  ```
  Options used to compile and link:
    external signer = no
    multiprocess    = no
    with libs       = yes
    with wallet     = yes
      with sqlite   = yes
      with bdb      = yes
      with gui / qt = yes
    with qr         = yes
    with zmq        = yes
    with test       = yes
  ...
  ```

  With this PR:
  ```
  Options used to compile and link:
    external signer = no
    multiprocess    = no
    with libs       = yes
    with wallet     = yes
      with sqlite   = yes
      with bdb      = yes
    with gui / qt   = yes
      with qr       = yes
    with zmq        = yes
    with test       = yes
  ...
  ```

  Also typos are fixed.

ACKs for top commit:
  Sjors:
    utACK 8b08d0f
  vasild:
    ACK 8b08d0f

Tree-SHA512: 46dfcfb754192dbcc080348781327d1714e2f9a696f3ed9252746b426e3afc628d84adb197ba3b8080eacaa6053ccac07e670998930ae92cef8ed713dd457c10
@hebasto
Copy link
Member

hebasto commented Mar 2, 2021

There is a buggy execution path in the configure script. Fixed in #21339.

fanquake added a commit that referenced this pull request Mar 3, 2021
…conditional

a412813 build: Make AM_CONDITIONAL([ENABLE_EXTERNAL_SIGNER]) unconditional (Hennadii Stepanov)
9fef209 build, refactor: Fix indentation for if..then..fi (Hennadii Stepanov)

Pull request description:

  #16546 introduced a regression in the `configure`:

  ```
  $ ./autogen.sh
  $ ./configure --disable-wallet --without-utils --without-daemon --without-gui --disable-tests --disable-bench
  ...
  checking whether to build test_bitcoin... no
  checking whether to reduce exports... no
  checking that generated files are newer than configure... done
  configure: error: conditional "ENABLE_EXTERNAL_SIGNER" was never defined.
  Usually this means the macro was only invoked conditionally.
  ```

  This PR fixes this bug, and refactors indentation to make easier to spot similar bugs in the future.

ACKs for top commit:
  Sjors:
    utACK a412813
  fanquake:
    ACK a412813 - this fixes the bug described, and improves readability.

Tree-SHA512: 4469dcc006690f38f93c3cdf8d15b76f5fc8ea76e87a1b5db5ee891dc9851f6ec539f2a6fd02a361aa76baa4f4b2b9fe8289137f5d9734ee5984f265cb131ef5
fanquake added a commit that referenced this pull request Mar 17, 2021
57ff5a4 doc: specify minimum HWI version (Sjors Provoost)
03308b2 rpc: don't require wallet for enumeratesigners (Sjors Provoost)

Pull request description:

  HWI just released 2.0. See https://github.com/bitcoin-core/HWI/releases/tag/2.0.0

  As of #16546 we already rely on features that are in 2.0 and not in the previous 1.* releases:
  * `--chain` param

  This shouldn't be a problem, because HWI 2.0 has been released before we release v22.

  Misc improvements:
  * document that HWI 2.0 is required
  * drop wallet requirement for `enumeratesigners`

ACKs for top commit:
  achow101:
    Code Review ACK 57ff5a4

Tree-SHA512: 3fb6ba20894e52a116f89525a5f5a1f61d363ccd904e1cffd0e6d095640fc6d2edf0388cd6ae20f83bbc31e5f458255ec090b6e823798d426eba3e45b4336bf9
Sjors added a commit to Sjors/bitcoin that referenced this pull request Mar 18, 2021
An earlier version of bitcoin#16546 used both --with-boost-process and --enable-external-signer, which was simplified to only use the latter. However I forgot to update CI, so the external signer tests were not run.
Sjors added a commit to Sjors/bitcoin that referenced this pull request Mar 18, 2021
An earlier version of bitcoin#16546 used both --with-boost-process and --enable-external-signer, which was simplified to only use the latter. However I forgot to update CI, so the external signer tests were not run.
Sjors added a commit to Sjors/bitcoin that referenced this pull request Mar 19, 2021
An earlier version of bitcoin#16546 used both --with-boost-process and --enable-external-signer, which was simplified to only use the latter. However I forgot to update CI, so the external signer tests were not run.
Sjors added a commit to Sjors/bitcoin that referenced this pull request Mar 22, 2021
An earlier version of bitcoin#16546 used both --with-boost-process and --enable-external-signer, which was simplified to only use the latter. However I forgot to update CI, so the external signer tests were not run.
Sjors added a commit to Sjors/bitcoin that referenced this pull request Apr 1, 2021
An earlier version of bitcoin#16546 used both --with-boost-process and --enable-external-signer, which was simplified to only use the latter. However I forgot to update CI, so the external signer tests were not run.
Sjors added a commit to Sjors/bitcoin that referenced this pull request Apr 2, 2021
An earlier version of bitcoin#16546 used both --with-boost-process and --enable-external-signer, which was simplified to only use the latter. However I forgot to update CI, so the external signer tests were not run.
Sjors added a commit to Sjors/bitcoin that referenced this pull request Apr 7, 2021
An earlier version of bitcoin#16546 used both --with-boost-process and --enable-external-signer, which was simplified to only use the latter. However I forgot to update CI, so the external signer tests were not run.
Sjors added a commit to Sjors/bitcoin that referenced this pull request Apr 8, 2021
An earlier version of bitcoin#16546 used both --with-boost-process and --enable-external-signer, which was simplified to only use the latter. However I forgot to update CI, so the external signer tests were not run.
Sjors added a commit to Sjors/bitcoin that referenced this pull request Apr 8, 2021
An earlier version of bitcoin#16546 used both --with-boost-process and --enable-external-signer, which was simplified to only use the latter. However I forgot to update CI, so the external signer tests were not run.
@bitcoin bitcoin deleted a comment from mariosanchezgarcia Apr 8, 2021
@bitcoin bitcoin locked and limited conversation to collaborators Apr 8, 2021
@@ -23,3 +23,4 @@ RPCAUTH=@abs_top_srcdir@/share/rpcauth/rpcauth.py
@BUILD_BITCOIND_TRUE@ENABLE_BITCOIND=true
@ENABLE_FUZZ_TRUE@ENABLE_FUZZ=true
@ENABLE_ZMQ_TRUE@ENABLE_ZMQ=true
@ENABLE_EXTERNAL_SIGNER_TRUE@ENABLE_EXTERNAL_SIGNER=true
Copy link
Member

@hebasto hebasto Jun 11, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems the @ENABLE_EXTERNAL_SIGNER_TRUE@ substitution does not work for some reasons.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nm, forgot to run ./autogen.sh

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.