Skip to content

Commit 6a9c429

Browse files
committed
Move direct calls to MessageSign into new SignMessage functions in CWallet and ScriptPubKeyMan
Instead of getting a SigningProvider and then going to MessageSign, have ScriptPubKeyMan handle the message signing internally.
1 parent 82a30fa commit 6a9c429

File tree

10 files changed

+84
-25
lines changed

10 files changed

+84
-25
lines changed

src/interfaces/wallet.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ class WalletImpl : public Wallet
132132
}
133133
return false;
134134
}
135+
SigningResult signMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) override
136+
{
137+
return m_wallet->SignMessage(message, pkhash, str_sig);
138+
}
135139
bool isSpendable(const CTxDestination& dest) override { return m_wallet->IsMine(dest) & ISMINE_SPENDABLE; }
136140
bool haveWatchOnly() override
137141
{

src/interfaces/wallet.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <script/standard.h> // For CTxDestination
1111
#include <support/allocators/secure.h> // For SecureString
1212
#include <ui_interface.h> // For ChangeType
13+
#include <util/message.h>
1314

1415
#include <functional>
1516
#include <map>
@@ -87,6 +88,9 @@ class Wallet
8788
//! Get private key.
8889
virtual bool getPrivKey(const CScript& script, const CKeyID& address, CKey& key) = 0;
8990

91+
//! Sign message
92+
virtual SigningResult signMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) = 0;
93+
9094
//! Return whether wallet has private key.
9195
virtual bool isSpendable(const CTxDestination& dest) = 0;
9296

src/qt/signverifymessagedialog.cpp

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -133,20 +133,27 @@ void SignVerifyMessageDialog::on_signMessageButton_SM_clicked()
133133
return;
134134
}
135135

136-
CKey key;
137-
if (!model->wallet().getPrivKey(GetScriptForDestination(destination), CKeyID(*pkhash), key))
138-
{
139-
ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
140-
ui->statusLabel_SM->setText(tr("Private key for the entered address is not available."));
141-
return;
142-
}
143-
144136
const std::string& message = ui->messageIn_SM->document()->toPlainText().toStdString();
145137
std::string signature;
138+
SigningResult res = model->wallet().signMessage(message, *pkhash, signature);
139+
140+
QString error;
141+
switch (res) {
142+
case SigningResult::OK:
143+
error = tr("No error");
144+
break;
145+
case SigningResult::PRIVATE_KEY_NOT_AVAILABLE:
146+
error = tr("Private key for the entered address is not available.");
147+
break;
148+
case SigningResult::SIGNING_FAILED:
149+
error = tr("Message signing failed.");
150+
break;
151+
// no default case, so the compiler can warn about missing cases
152+
}
146153

147-
if (!MessageSign(key, message, signature)) {
154+
if (res != SigningResult::OK) {
148155
ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
149-
ui->statusLabel_SM->setText(QString("<nobr>") + tr("Message signing failed.") + QString("</nobr>"));
156+
ui->statusLabel_SM->setText(QString("<nobr>") + error + QString("</nobr>"));
150157
return;
151158
}
152159

src/util/message.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,17 @@ uint256 MessageHash(const std::string& message)
7676

7777
return hasher.GetHash();
7878
}
79+
80+
std::string SigningResultString(const SigningResult res)
81+
{
82+
switch (res) {
83+
case SigningResult::OK:
84+
return "No error";
85+
case SigningResult::PRIVATE_KEY_NOT_AVAILABLE:
86+
return "Private key not available";
87+
case SigningResult::SIGNING_FAILED:
88+
return "Sign failed";
89+
// no default case, so the compiler can warn about missing cases
90+
}
91+
assert(false);
92+
}

src/util/message.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ enum class MessageVerificationResult {
3939
OK
4040
};
4141

42+
enum class SigningResult {
43+
OK, //!< No error
44+
PRIVATE_KEY_NOT_AVAILABLE,
45+
SIGNING_FAILED,
46+
};
47+
4248
/** Verify a signed message.
4349
* @param[in] address Signer's bitcoin address, it must refer to a public key.
4450
* @param[in] signature The signature in base64 format.
@@ -65,4 +71,6 @@ bool MessageSign(
6571
*/
6672
uint256 MessageHash(const std::string& message);
6773

74+
std::string SigningResultString(const SigningResult res);
75+
6876
#endif // BITCOIN_UTIL_MESSAGE_H

src/wallet/rpcwallet.cpp

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -565,22 +565,12 @@ static UniValue signmessage(const JSONRPCRequest& request)
565565
throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
566566
}
567567

568-
CScript script_pub_key = GetScriptForDestination(*pkhash);
569-
std::unique_ptr<SigningProvider> provider = pwallet->GetSigningProvider(script_pub_key);
570-
if (!provider) {
571-
throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available");
572-
}
573-
574-
CKey key;
575-
CKeyID keyID(*pkhash);
576-
if (!provider->GetKey(keyID, key)) {
577-
throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available");
578-
}
579-
580568
std::string signature;
581-
582-
if (!MessageSign(key, strMessage, signature)) {
583-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
569+
SigningResult err = pwallet->SignMessage(strMessage, *pkhash, signature);
570+
if (err == SigningResult::SIGNING_FAILED) {
571+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, SigningResultString(err));
572+
} else if (err != SigningResult::OK){
573+
throw JSONRPCError(RPC_WALLET_ERROR, SigningResultString(err));
584574
}
585575

586576
return signature;

src/wallet/scriptpubkeyman.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,20 @@ bool LegacyScriptPubKeyMan::SignTransaction(CMutableTransaction& tx, const std::
511511
return ::SignTransaction(tx, this, coins, sighash, input_errors);
512512
}
513513

514+
SigningResult LegacyScriptPubKeyMan::SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const
515+
{
516+
CKeyID key_id(pkhash);
517+
CKey key;
518+
if (!GetKey(key_id, key)) {
519+
return SigningResult::PRIVATE_KEY_NOT_AVAILABLE;
520+
}
521+
522+
if (MessageSign(key, message, str_sig)) {
523+
return SigningResult::OK;
524+
}
525+
return SigningResult::SIGNING_FAILED;
526+
}
527+
514528
TransactionError LegacyScriptPubKeyMan::FillPSBT(PartiallySignedTransaction& psbtx, int sighash_type, bool sign, bool bip32derivs) const
515529
{
516530
for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {

src/wallet/scriptpubkeyman.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <script/signingprovider.h>
1010
#include <script/standard.h>
1111
#include <util/error.h>
12+
#include <util/message.h>
1213
#include <wallet/crypter.h>
1314
#include <wallet/ismine.h>
1415
#include <wallet/walletdb.h>
@@ -214,6 +215,8 @@ class ScriptPubKeyMan
214215

215216
/** Creates new signatures and adds them to the transaction. Returns whether all inputs were signed */
216217
virtual bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors) const { return false; }
218+
/** Sign a message with the given script */
219+
virtual SigningResult SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const { return SigningResult::SIGNING_FAILED; };
217220
/** Adds script and derivation path information to a PSBT, and optionally signs it. */
218221
virtual TransactionError FillPSBT(PartiallySignedTransaction& psbt, int sighash_type = 1 /* SIGHASH_ALL */, bool sign = true, bool bip32derivs = false) const { return TransactionError::INVALID_PSBT; }
219222

@@ -358,6 +361,7 @@ class LegacyScriptPubKeyMan : public ScriptPubKeyMan, public FillableSigningProv
358361
bool CanProvide(const CScript& script, SignatureData& sigdata) override;
359362

360363
bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors) const override;
364+
SigningResult SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const override;
361365
TransactionError FillPSBT(PartiallySignedTransaction& psbt, int sighash_type = 1 /* SIGHASH_ALL */, bool sign = true, bool bip32derivs = false) const override;
362366

363367
uint256 GetID() const override;

src/wallet/wallet.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2566,6 +2566,18 @@ TransactionError CWallet::FillPSBT(PartiallySignedTransaction& psbtx, bool& comp
25662566
return TransactionError::OK;
25672567
}
25682568

2569+
SigningResult CWallet::SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const
2570+
{
2571+
SignatureData sigdata;
2572+
CScript script_pub_key = GetScriptForDestination(pkhash);
2573+
for (const auto& spk_man_pair : m_spk_managers) {
2574+
if (spk_man_pair.second->CanProvide(script_pub_key, sigdata)) {
2575+
return spk_man_pair.second->SignMessage(message, pkhash, str_sig);
2576+
}
2577+
}
2578+
return SigningResult::PRIVATE_KEY_NOT_AVAILABLE;
2579+
}
2580+
25692581
bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, CCoinControl coinControl)
25702582
{
25712583
std::vector<CRecipient> vecSend;

src/wallet/wallet.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <psbt.h>
1515
#include <tinyformat.h>
1616
#include <ui_interface.h>
17+
#include <util/message.h>
1718
#include <util/strencodings.h>
1819
#include <util/system.h>
1920
#include <validationinterface.h>
@@ -921,6 +922,7 @@ class CWallet final : public WalletStorage, private interfaces::Chain::Notificat
921922
bool SignTransaction(CMutableTransaction& tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
922923
// Sign the tx given the input coins and sighash.
923924
bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors) const;
925+
SigningResult SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const;
924926

925927
/**
926928
* Fills out a PSBT with information from the wallet. Fills in UTXOs if we have

0 commit comments

Comments
 (0)