@@ -404,7 +404,37 @@ static RPCHelpMan gobject_submit()
404404 };
405405}
406406
407- static UniValue VoteWithMasternodes (const JSONRPCRequest& request, const std::map<uint256, CKey>& keys,
407+ #ifdef ENABLE_WALLET
408+ static bool SignVote (const CWallet& wallet, const CKeyID& keyID, CGovernanceVote& vote)
409+ {
410+ // Special implementation for testnet (Harden Spork6 that has not been deployed to other networks)
411+ if (Params ().NetworkIDString () == CBaseChainParams::TESTNET) {
412+ std::vector<unsigned char > signature;
413+ if (!wallet.SignSpecialTxPayload (vote.GetSignatureHash (), keyID, signature)) {
414+ LogPrintf (" SignVote -- SignHash() failed\n " );
415+ return false ;
416+ }
417+ vote.SetSignature (signature);
418+ return true ;
419+ } // end of testnet implementation
420+
421+ std::string strMessage{vote.GetSignatureString ()};
422+ std::string signature;
423+ SigningResult err = wallet.SignMessage (strMessage, PKHash{keyID}, signature);
424+ if (err != SigningResult::OK) {
425+ LogPrintf (" SignVote failed due to: %s\n " , SigningResultString (err));
426+ return false ;
427+ }
428+ bool ret = true ;
429+ const auto decoded = DecodeBase64 (signature, &ret);
430+ assert (!ret); // it should not fail
431+
432+ vote.SetSignature (std::vector<unsigned char >(decoded.data (), decoded.data () + decoded.size ()));
433+ return true ;
434+ }
435+
436+ static UniValue VoteWithMasternodes (const JSONRPCRequest& request, const CWallet& wallet,
437+ const std::map<uint256, CKeyID>& votingKeys,
408438 const uint256& hash, vote_signal_enum_t eVoteSignal,
409439 vote_outcome_enum_t eVoteOutcome)
410440{
@@ -425,9 +455,9 @@ static UniValue VoteWithMasternodes(const JSONRPCRequest& request, const std::ma
425455
426456 UniValue resultsObj (UniValue::VOBJ);
427457
428- for (const auto & p : keys ) {
458+ for (const auto & p : votingKeys ) {
429459 const auto & proTxHash = p.first ;
430- const auto & key = p.second ;
460+ const auto & keyID = p.second ;
431461
432462 UniValue statusObj (UniValue::VOBJ);
433463
@@ -441,7 +471,8 @@ static UniValue VoteWithMasternodes(const JSONRPCRequest& request, const std::ma
441471 }
442472
443473 CGovernanceVote vote (dmn->collateralOutpoint , hash, eVoteSignal, eVoteOutcome);
444- if (!vote.Sign (key, key.GetPubKey ().GetID ())) {
474+
475+ if (!SignVote (wallet, keyID, vote) || !vote.CheckSignature (keyID)) {
445476 nFailed++;
446477 statusObj.pushKV (" result" , " failed" );
447478 statusObj.pushKV (" errorMessage" , " Failure to sign." );
@@ -471,7 +502,14 @@ static UniValue VoteWithMasternodes(const JSONRPCRequest& request, const std::ma
471502 return returnObj;
472503}
473504
474- #ifdef ENABLE_WALLET
505+ static bool CheckWalletOwnsKey (const CWallet& wallet, const CKeyID& keyid)
506+ {
507+ const CScript script{GetScriptForDestination (PKHash (keyid))};
508+ LOCK (wallet.cs_wallet );
509+
510+ return wallet.IsMine (script) == isminetype::ISMINE_SPENDABLE;
511+ }
512+
475513static RPCHelpMan gobject_vote_many ()
476514{
477515 return RPCHelpMan{" gobject vote-many" ,
@@ -510,22 +548,17 @@ static RPCHelpMan gobject_vote_many()
510548
511549 EnsureWalletIsUnlocked (wallet.get ());
512550
513- LegacyScriptPubKeyMan* spk_man = wallet->GetLegacyScriptPubKeyMan ();
514- if (!spk_man) {
515- throw JSONRPCError (RPC_WALLET_ERROR, " This type of wallet does not support this command" );
516- }
517-
518- std::map<uint256, CKey> votingKeys;
551+ std::map<uint256, CKeyID> votingKeys;
519552
520553 auto mnList = node.dmnman ->GetListAtChainTip ();
521554 mnList.ForEachMN (true , [&](auto & dmn) {
522- CKey votingKey ;
523- if (spk_man-> GetKey (dmn. pdmnState -> keyIDVoting , votingKey) ) {
524- votingKeys.emplace (dmn.proTxHash , votingKey );
555+ const bool is_mine = CheckWalletOwnsKey (*wallet, dmn. pdmnState -> keyIDVoting ) ;
556+ if (is_mine ) {
557+ votingKeys.emplace (dmn.proTxHash , dmn. pdmnState -> keyIDVoting );
525558 }
526559 });
527560
528- return VoteWithMasternodes (request, votingKeys, hash, eVoteSignal, eVoteOutcome);
561+ return VoteWithMasternodes (request, *wallet, votingKeys, hash, eVoteSignal, eVoteOutcome);
529562},
530563 };
531564}
@@ -575,20 +608,16 @@ static RPCHelpMan gobject_vote_alias()
575608 throw JSONRPCError (RPC_INVALID_PARAMETER, " Invalid or unknown proTxHash" );
576609 }
577610
578- LegacyScriptPubKeyMan* spk_man = wallet->GetLegacyScriptPubKeyMan ();
579- if (!spk_man) {
580- throw JSONRPCError (RPC_WALLET_ERROR, " This type of wallet does not support this command" );
581- }
582611
583- CKey votingKey ;
584- if (!spk_man-> GetKey (dmn-> pdmnState -> keyIDVoting , votingKey) ) {
612+ const bool is_mine = CheckWalletOwnsKey (*wallet, dmn-> pdmnState -> keyIDVoting ) ;
613+ if (!is_mine ) {
585614 throw JSONRPCError (RPC_INVALID_PARAMETER, strprintf (" Private key for voting address %s not known by wallet" , EncodeDestination (PKHash (dmn->pdmnState ->keyIDVoting ))));
586615 }
587616
588- std::map<uint256, CKey > votingKeys;
589- votingKeys.emplace (proTxHash, votingKey );
617+ std::map<uint256, CKeyID > votingKeys;
618+ votingKeys.emplace (proTxHash, dmn-> pdmnState -> keyIDVoting );
590619
591- return VoteWithMasternodes (request, votingKeys, hash, eVoteSignal, eVoteOutcome);
620+ return VoteWithMasternodes (request, *wallet, votingKeys, hash, eVoteSignal, eVoteOutcome);
592621},
593622 };
594623}
0 commit comments