Skip to content

Commit 8299b3b

Browse files
committed
feat: protxregistar implementation for descriptor wallets
1 parent 6f45432 commit 8299b3b

File tree

7 files changed

+59
-13
lines changed

7 files changed

+59
-13
lines changed

src/Makefile.am

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,6 @@ libbitcoin_server_a_SOURCES = \
480480
masternode/payments.cpp \
481481
masternode/sync.cpp \
482482
masternode/utils.cpp \
483-
messagesigner.cpp \
484483
miner.cpp \
485484
net.cpp \
486485
netfulfilledman.cpp \
@@ -690,6 +689,7 @@ libbitcoin_consensus_a_SOURCES = \
690689
consensus/validation.h \
691690
hash.cpp \
692691
hash.h \
692+
messagesigner.cpp \
693693
prevector.h \
694694
primitives/block.cpp \
695695
primitives/block.h \

src/rpc/evo.cpp

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -294,13 +294,13 @@ static void UpdateSpecialTxInputsHash(const CMutableTransaction& tx, SpecialTxPa
294294
}
295295

296296
template<typename SpecialTxPayload>
297-
static void SignSpecialTxPayloadByHash(const CMutableTransaction& tx, SpecialTxPayload& payload, const CKey& key)
297+
static void SignSpecialTxPayloadByHash(const CMutableTransaction& tx, SpecialTxPayload& payload, const CKeyID& keyID, const CWallet& wallet)
298298
{
299299
UpdateSpecialTxInputsHash(tx, payload);
300300
payload.vchSig.clear();
301301

302-
uint256 hash = ::SerializeHash(payload);
303-
if (!CHashSigner::SignHash(hash, key, payload.vchSig)) {
302+
const uint256 hash = ::SerializeHash(payload);
303+
if (!wallet.SignSpecialTxPayload(hash, keyID, payload.vchSig)) {
304304
throw JSONRPCError(RPC_INTERNAL_ERROR, "failed to sign special tx");
305305
}
306306
}
@@ -1099,14 +1099,12 @@ static UniValue protx_update_registrar_wrapper(const JSONRPCRequest& request, CC
10991099
ptx.scriptPayout = GetScriptForDestination(payoutDest);
11001100
}
11011101

1102-
LegacyScriptPubKeyMan* spk_man = wallet->GetLegacyScriptPubKeyMan();
1103-
if (!spk_man) {
1104-
throw JSONRPCError(RPC_WALLET_ERROR, "This type of wallet does not support this command");
1105-
}
1106-
1107-
CKey keyOwner;
1108-
if (!spk_man->GetKey(dmn->pdmnState->keyIDOwner, keyOwner)) {
1109-
throw std::runtime_error(strprintf("Private key for owner address %s not found in your wallet", EncodeDestination(PKHash(dmn->pdmnState->keyIDOwner))));
1102+
{
1103+
const auto pkhash{PKHash(dmn->pdmnState->keyIDOwner)};
1104+
LOCK(wallet->cs_wallet);
1105+
if (wallet->IsMine(GetScriptForDestination(pkhash)) != isminetype::ISMINE_SPENDABLE) {
1106+
throw std::runtime_error(strprintf("Private key for owner address %s not found in your wallet", EncodeDestination(pkhash)));
1107+
}
11101108
}
11111109

11121110
CMutableTransaction tx;
@@ -1124,7 +1122,7 @@ static UniValue protx_update_registrar_wrapper(const JSONRPCRequest& request, CC
11241122
}
11251123

11261124
FundSpecialTx(wallet.get(), tx, ptx, feeSourceDest);
1127-
SignSpecialTxPayloadByHash(tx, ptx, keyOwner);
1125+
SignSpecialTxPayloadByHash(tx, ptx, dmn->pdmnState->keyIDOwner, *wallet);
11281126
SetTxPayload(tx, ptx);
11291127

11301128
return SignAndSendSpecialTx(request, chain_helper, chainman, tx);

src/wallet/scriptpubkeyman.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <key_io.h>
66
#include <chainparams.h>
77
#include <logging.h>
8+
#include <messagesigner.h>
89
#include <script/descriptor.h>
910
#include <script/sign.h>
1011
#include <shutdown.h>
@@ -726,6 +727,16 @@ SigningResult LegacyScriptPubKeyMan::SignMessage(const std::string& message, con
726727
return SigningResult::SIGNING_FAILED;
727728
}
728729

730+
bool LegacyScriptPubKeyMan::SignSpecialTxPayload(const uint256& hash, const CKeyID& keyid, std::vector<unsigned char>& vchSig) const
731+
{
732+
CKey key;
733+
if (!GetKey(keyid, key)) {
734+
return false;
735+
}
736+
737+
return CHashSigner::SignHash(hash, key, vchSig);
738+
}
739+
729740
TransactionError LegacyScriptPubKeyMan::FillPSBT(PartiallySignedTransaction& psbtx, int sighash_type, bool sign, bool bip32derivs, int* n_signed) const
730741
{
731742
if (n_signed) {
@@ -2196,6 +2207,21 @@ SigningResult DescriptorScriptPubKeyMan::SignMessage(const std::string& message,
21962207
return SigningResult::OK;
21972208
}
21982209

2210+
bool DescriptorScriptPubKeyMan::SignSpecialTxPayload(const uint256& hash, const CKeyID& keyid, std::vector<unsigned char>& vchSig) const
2211+
{
2212+
std::unique_ptr<FlatSigningProvider> keys = GetSigningProvider(GetScriptForDestination(PKHash(keyid)), true);
2213+
if (!keys) {
2214+
return false;
2215+
}
2216+
2217+
CKey key;
2218+
if (!keys->GetKey(keyid, key)) {
2219+
return false;
2220+
}
2221+
2222+
return CHashSigner::SignHash(hash, key, vchSig);
2223+
}
2224+
21992225
TransactionError DescriptorScriptPubKeyMan::FillPSBT(PartiallySignedTransaction& psbtx, int sighash_type, bool sign, bool bip32derivs, int* n_signed) const
22002226
{
22012227
if (n_signed) {

src/wallet/scriptpubkeyman.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ class ScriptPubKeyMan
211211
virtual bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors) const { return false; }
212212
/** Sign a message with the given script */
213213
virtual SigningResult SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const { return SigningResult::SIGNING_FAILED; };
214+
virtual bool SignSpecialTxPayload(const uint256& hash, const CKeyID& keyid, std::vector<unsigned char>& vchSig) const { return false; }
214215
/** Adds script and derivation path information to a PSBT, and optionally signs it. */
215216
virtual TransactionError FillPSBT(PartiallySignedTransaction& psbt, int sighash_type = 1 /* SIGHASH_ALL */, bool sign = true, bool bip32derivs = false, int* n_signed = nullptr) const { return TransactionError::INVALID_PSBT; }
216217

@@ -358,6 +359,7 @@ class LegacyScriptPubKeyMan : public ScriptPubKeyMan, public FillableSigningProv
358359

359360
bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors) const override;
360361
SigningResult SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const override;
362+
bool SignSpecialTxPayload(const uint256& hash, const CKeyID& keyid, std::vector<unsigned char>& vchSig) const override;
361363
TransactionError FillPSBT(PartiallySignedTransaction& psbt, int sighash_type = 1 /* SIGHASH_ALL */, bool sign = true, bool bip32derivs = false, int* n_signed = nullptr) const override;
362364

363365
uint256 GetID() const override;
@@ -588,6 +590,7 @@ class DescriptorScriptPubKeyMan : public ScriptPubKeyMan
588590

589591
bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors) const override;
590592
SigningResult SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const override;
593+
bool SignSpecialTxPayload(const uint256& hash, const CKeyID& keyid, std::vector<unsigned char>& vchSig) const override;
591594
TransactionError FillPSBT(PartiallySignedTransaction& psbt, int sighash_type = 1 /* SIGHASH_ALL */, bool sign = true, bool bip32derivs = false, int* n_signed = nullptr) const override;
592595

593596
uint256 GetID() const override;

src/wallet/wallet.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3063,6 +3063,19 @@ SigningResult CWallet::SignMessage(const std::string& message, const PKHash& pkh
30633063
return SigningResult::PRIVATE_KEY_NOT_AVAILABLE;
30643064
}
30653065

3066+
bool CWallet::SignSpecialTxPayload(const uint256& hash, const CKeyID& keyid, std::vector<unsigned char>& vchSig) const
3067+
{
3068+
SignatureData sigdata;
3069+
CScript script_pub_key = GetScriptForDestination(PKHash(keyid));
3070+
for (const auto& spk_man_pair : m_spk_managers) {
3071+
if (spk_man_pair.second->CanProvide(script_pub_key, sigdata)) {
3072+
LOCK(cs_wallet); // DescriptorScriptPubKeyMan calls IsLocked which can lock cs_wallet in a deadlocking order
3073+
return spk_man_pair.second->SignSpecialTxPayload(hash, keyid, vchSig);
3074+
}
3075+
}
3076+
return false;
3077+
}
3078+
30663079
bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, bilingual_str& error, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, CCoinControl coinControl)
30673080
{
30683081
std::vector<CRecipient> vecSend;

src/wallet/wallet.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1107,6 +1107,11 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
11071107
/** Sign the tx given the input coins and sighash. */
11081108
bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors) const;
11091109
SigningResult SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const;
1110+
/** Sign the payload of special transaction.
1111+
* Because wallet is not aware about special transactions entity,
1112+
* but it should work for any its type, we pass there directly a hash of payload.
1113+
*/
1114+
bool SignSpecialTxPayload(const uint256& hash, const CKeyID& keyid, std::vector<unsigned char>& vchSig) const;
11101115

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

test/functional/test_runner.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
# Scripts that are run by default.
9494
# Longest test should go first, to favor running tests in parallel
9595
'feature_dip3_deterministicmns.py --legacy-wallet', # NOTE: needs dash_hash to pass
96+
'feature_dip3_deterministicmns.py --descriptors', # NOTE: needs dash_hash to pass
9697
'feature_llmq_data_recovery.py',
9798
'wallet_hd.py --legacy-wallet',
9899
'wallet_hd.py --descriptors',

0 commit comments

Comments
 (0)