Merge bitcoin/bitcoin#23004: multiprocess: add interfaces::ExternalSigner class

a032fa30d2 multiprocess: add interfaces::ExternalSigner class (Russell Yanofsky)

Pull request description:

  Add `interfaces::ExternalSigner` class to let signer objects be passed between processes and let signer code run in the original process where the object was created.

  ---

  This PR is part of the [process separation project](https://github.com/bitcoin/bitcoin/projects/10).

ACKs for top commit:
  laanwj:
    Concept and code review ACK a032fa30d2
  hebasto:
    re-ACK a032fa30d2

Tree-SHA512: 99a729fb3a64d010e142cc778a9f1f358e58345b77faaf2664de7d2277715d59df3352326e8f0f2a6628038670eaa4556310a549079fb28af6d2eeb05aea1460
This commit is contained in:
W. J. van der Laan
2021-11-15 17:12:05 +01:00
5 changed files with 41 additions and 12 deletions

View File

@@ -6,7 +6,6 @@
#define BITCOIN_INTERFACES_NODE_H #define BITCOIN_INTERFACES_NODE_H
#include <consensus/amount.h> #include <consensus/amount.h>
#include <external_signer.h>
#include <net.h> // For NodeId #include <net.h> // For NodeId
#include <net_types.h> // For banmap_t #include <net_types.h> // For banmap_t
#include <netaddress.h> // For Network #include <netaddress.h> // For Network
@@ -50,6 +49,16 @@ struct BlockAndHeaderTipInfo
double verification_progress; double verification_progress;
}; };
//! External signer interface used by the GUI.
class ExternalSigner
{
public:
virtual ~ExternalSigner() {};
//! Get signer display name
virtual std::string getName() = 0;
};
//! Top-level interface for a bitcoin node (bitcoind process). //! Top-level interface for a bitcoin node (bitcoind process).
class Node class Node
{ {
@@ -111,8 +120,8 @@ public:
//! Disconnect node by id. //! Disconnect node by id.
virtual bool disconnectById(NodeId id) = 0; virtual bool disconnectById(NodeId id) = 0;
//! List external signers //! Return list of external signers (attached devices which can sign transactions).
virtual std::vector<ExternalSigner> externalSigners() = 0; virtual std::vector<std::unique_ptr<ExternalSigner>> listExternalSigners() = 0;
//! Get total bytes recv. //! Get total bytes recv.
virtual int64_t getTotalBytesRecv() = 0; virtual int64_t getTotalBytesRecv() = 0;

View File

@@ -67,6 +67,17 @@ using interfaces::WalletClient;
namespace node { namespace node {
namespace { namespace {
#ifdef ENABLE_EXTERNAL_SIGNER
class ExternalSignerImpl : public interfaces::ExternalSigner
{
public:
ExternalSignerImpl(::ExternalSigner signer) : m_signer(std::move(signer)) {}
std::string getName() override { return m_signer.m_name; }
private:
::ExternalSigner m_signer;
};
#endif
class NodeImpl : public Node class NodeImpl : public Node
{ {
private: private:
@@ -172,14 +183,18 @@ public:
} }
return false; return false;
} }
std::vector<ExternalSigner> externalSigners() override std::vector<std::unique_ptr<interfaces::ExternalSigner>> listExternalSigners() override
{ {
#ifdef ENABLE_EXTERNAL_SIGNER #ifdef ENABLE_EXTERNAL_SIGNER
std::vector<ExternalSigner> signers = {}; std::vector<ExternalSigner> signers = {};
const std::string command = gArgs.GetArg("-signer", ""); const std::string command = gArgs.GetArg("-signer", "");
if (command == "") return signers; if (command == "") return {};
ExternalSigner::Enumerate(command, signers, Params().NetworkIDString()); ExternalSigner::Enumerate(command, signers, Params().NetworkIDString());
return signers; std::vector<std::unique_ptr<interfaces::ExternalSigner>> result;
for (auto& signer : signers) {
result.emplace_back(std::make_unique<ExternalSignerImpl>(std::move(signer)));
}
return result;
#else #else
// This result is indistinguishable from a successful call that returns // This result is indistinguishable from a successful call that returns
// no signers. For the current GUI this doesn't matter, because the wallet // no signers. For the current GUI this doesn't matter, because the wallet

View File

@@ -6,7 +6,7 @@
#include <config/bitcoin-config.h> #include <config/bitcoin-config.h>
#endif #endif
#include <external_signer.h> #include <interfaces/node.h>
#include <qt/createwalletdialog.h> #include <qt/createwalletdialog.h>
#include <qt/forms/ui_createwalletdialog.h> #include <qt/forms/ui_createwalletdialog.h>
@@ -113,7 +113,7 @@ CreateWalletDialog::~CreateWalletDialog()
delete ui; delete ui;
} }
void CreateWalletDialog::setSigners(const std::vector<ExternalSigner>& signers) void CreateWalletDialog::setSigners(const std::vector<std::unique_ptr<interfaces::ExternalSigner>>& signers)
{ {
m_has_signers = !signers.empty(); m_has_signers = !signers.empty();
if (m_has_signers) { if (m_has_signers) {
@@ -126,7 +126,7 @@ void CreateWalletDialog::setSigners(const std::vector<ExternalSigner>& signers)
ui->blank_wallet_checkbox->setChecked(false); ui->blank_wallet_checkbox->setChecked(false);
ui->disable_privkeys_checkbox->setEnabled(false); ui->disable_privkeys_checkbox->setEnabled(false);
ui->disable_privkeys_checkbox->setChecked(true); ui->disable_privkeys_checkbox->setChecked(true);
const std::string label = signers[0].m_name; const std::string label = signers[0]->getName();
ui->wallet_name_line_edit->setText(QString::fromStdString(label)); ui->wallet_name_line_edit->setText(QString::fromStdString(label));
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
} else { } else {

View File

@@ -7,7 +7,12 @@
#include <QDialog> #include <QDialog>
#include <memory>
namespace interfaces {
class ExternalSigner; class ExternalSigner;
} // namespace interfaces
class WalletModel; class WalletModel;
namespace Ui { namespace Ui {
@@ -24,7 +29,7 @@ public:
explicit CreateWalletDialog(QWidget* parent); explicit CreateWalletDialog(QWidget* parent);
virtual ~CreateWalletDialog(); virtual ~CreateWalletDialog();
void setSigners(const std::vector<ExternalSigner>& signers); void setSigners(const std::vector<std::unique_ptr<interfaces::ExternalSigner>>& signers);
QString walletName() const; QString walletName() const;
bool isEncryptWalletChecked() const; bool isEncryptWalletChecked() const;

View File

@@ -280,9 +280,9 @@ void CreateWalletActivity::create()
{ {
m_create_wallet_dialog = new CreateWalletDialog(m_parent_widget); m_create_wallet_dialog = new CreateWalletDialog(m_parent_widget);
std::vector<ExternalSigner> signers; std::vector<std::unique_ptr<interfaces::ExternalSigner>> signers;
try { try {
signers = node().externalSigners(); signers = node().listExternalSigners();
} catch (const std::runtime_error& e) { } catch (const std::runtime_error& e) {
QMessageBox::critical(nullptr, tr("Can't list signers"), e.what()); QMessageBox::critical(nullptr, tr("Can't list signers"), e.what());
} }