[WIP] External signer support (e.g. hardware wallet)#14912
[WIP] External signer support (e.g. hardware wallet)#14912Sjors wants to merge 21 commits intobitcoin:masterfrom
Conversation
e021812 to
a2b018d
Compare
|
Now that #14491 has been rebased, the See also the wallet meeting notes. |
a2b018d to
9ec4aac
Compare
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsReviewers, 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. |
src/wallet/externalsigner.cpp
Outdated
There was a problem hiding this comment.
ExternalSigner signer shadows UniValue signer :-)
src/wallet/rpcdump.cpp
Outdated
There was a problem hiding this comment.
Make signedness changing implicit conversion explicit? Also, remove redundant initialization to zero on the line above? Merge the two lines.
There was a problem hiding this comment.
The compiler didn't like it when I initialized using gArgs.GetArg.
src/util/system.cpp
Outdated
There was a problem hiding this comment.
Initialize to zero?
src/wallet/rpcwallet.cpp
Outdated
There was a problem hiding this comment.
Should be "fingerprint" :-)
src/util/system.cpp
Outdated
There was a problem hiding this comment.
I haven't reviewed this use of popen(…) closer, but please note the recommendations/risks with regards to popen(…) used described in the CERT secure coding guidelines (more specifically rule ENV33-C).
There was a problem hiding this comment.
This is straight from stack overflow, so certainly needs more review... I'm surprised how complicated it is to just read some JSON from stdout.
There was a problem hiding this comment.
popen and pclose are unix-like only. You can't use them on Windows. IMO you could use boost process instead.
There was a problem hiding this comment.
I think we don't depend on boost process.
There was a problem hiding this comment.
I know. But this is the simplest way if this is really necessary to call another process. I don't think that any one here know how to use Windows CreateProcess API.
There was a problem hiding this comment.
It would be reasonable to call _popen function here on windows or #define popen _popen: https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/system-wsystem.
You do need to be very careful about special characters passed in the command string, but it should be ok if you stick to hex/base64.
There was a problem hiding this comment.
_popen would only work in console program. See https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/popen-wpopen. So it doesn't work in Qt.
src/util/strencodings.cpp
Outdated
There was a problem hiding this comment.
keypath should be const reference?
src/wallet/rpcwallet.cpp
Outdated
There was a problem hiding this comment.
Nit: Could use command.empty()? :-)
src/wallet/externalsigner.cpp
Outdated
There was a problem hiding this comment.
Should be const reference? :-)
src/wallet/externalsigner.cpp
Outdated
There was a problem hiding this comment.
Should be const reference? :-)
src/wallet/externalsigner.cpp
Outdated
There was a problem hiding this comment.
Use string equality operator instead of compare :-)
src/wallet/rpcwallet.cpp
Outdated
There was a problem hiding this comment.
signer can be nullptr here if the check on L4016 is correct?
src/wallet/rpcwallet.cpp
Outdated
There was a problem hiding this comment.
Same here: signer can be nullptr here if the check on L4016 is correct?
src/util/strencodings.h
Outdated
There was a problem hiding this comment.
keypath should be const reference?
src/wallet/rpcdump.cpp
Outdated
There was a problem hiding this comment.
Nit: Could use std::copy instead?
src/wallet/rpcdump.cpp
Outdated
There was a problem hiding this comment.
Same here: Could you std::copy?
src/wallet/rpcdump.cpp
Outdated
There was a problem hiding this comment.
Missing space before (. Consider running new code through clang-format :-)
src/wallet/rpcdump.cpp
Outdated
There was a problem hiding this comment.
Same here: Missing whitespace before (.
|
Rebased and dropped |
|
I'm considering rebasing* this on top of #16341 (aka "box"), by introducing a
* = later though, I'd rather not have a PR with 110 commits |
* AppVeyor boost-process vcpkg package. * Add HAVE_BOOST_PROCESS for MSVC build (bitcoin_config.h) * Tell Boost linter to ignore it
Create basic ExternalSigner class with contructor. A Signer(<cmd>) is added to CWallet on load if -signer=<cmd> is set.
|
Rebased now that #15911 is merged. Dropped a few commits that should have been in #15876 and aren't needed anyway after #15713. Removed the need for the unit test to add private keys to the keypool (closing #15414). I'll keep this and the convenience methods in #15876 up to date and work on a "boxed" version in a separate PR. |
|
Here's a simple rebase on top of a native descriptor wallet #16528 (benefit: gives access to full BIP44/49/84 address tree): https://github.com/Sjors/bitcoin/tree/2019/08/hww-box |
Includes a mock to mimick the HWI interace.
|
Closing in favor of the native descriptor edition in #16546. |
This PR lets
bitcoindto 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 PSBT.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.
It adds the following RPC methods:
enumeratesigners: asks for a list of signers (e.g. devices) and their master key fingerprintsignerfetchkeys(needs Add getdescriptors command bitcoin-core/HWI#137): asks for descriptors and then fills the keypool (no private keys)signerdisplayaddress <address>: asks to display an addresssignerprocesspsbt <psbt>to send the<psbt>to<cmd>to sign and wait for the resultUsage TL&DR:
bitcoind -signer=../HWI/hwi.pybitcoin-cli createwallet hww truebitcoin-cli enumeratesignersbitcoin-cli -rpcwallet=hww signerfetchkeysFor easier review, this builds on the following PRs:
Potentially useful followups: