@@ -76,6 +76,41 @@ void quorum_info_help()
7676 );
7777}
7878
79+ UniValue BuildQuorumInfo (const llmq::CQuorumCPtr& quorum, bool includeMembers, bool includeSkShare)
80+ {
81+ UniValue ret (UniValue::VOBJ);
82+
83+ ret.push_back (Pair (" height" , quorum->height ));
84+ ret.push_back (Pair (" type" , quorum->params .name ));
85+ ret.push_back (Pair (" quorumHash" , quorum->qc .quorumHash .ToString ()));
86+ ret.push_back (Pair (" minedBlock" , quorum->minedBlockHash .ToString ()));
87+
88+ if (includeMembers) {
89+ UniValue membersArr (UniValue::VARR);
90+ for (size_t i = 0 ; i < quorum->members .size (); i++) {
91+ auto & dmn = quorum->members [i];
92+ UniValue mo (UniValue::VOBJ);
93+ mo.push_back (Pair (" proTxHash" , dmn->proTxHash .ToString ()));
94+ mo.push_back (Pair (" valid" , quorum->qc .validMembers [i]));
95+ if (quorum->qc .validMembers [i]) {
96+ CBLSPublicKey pubKey = quorum->GetPubKeyShare (i);
97+ if (pubKey.IsValid ()) {
98+ mo.push_back (Pair (" pubKeyShare" , pubKey.ToString ()));
99+ }
100+ }
101+ membersArr.push_back (mo);
102+ }
103+
104+ ret.push_back (Pair (" members" , membersArr));
105+ }
106+ ret.push_back (Pair (" quorumPublicKey" , quorum->qc .quorumPublicKey .ToString ()));
107+ CBLSSecretKey skShare = quorum->GetSkShare ();
108+ if (includeSkShare && skShare.IsValid ()) {
109+ ret.push_back (Pair (" secretKeyShare" , skShare.ToString ()));
110+ }
111+ return ret;
112+ }
113+
79114UniValue quorum_info (const JSONRPCRequest& request)
80115{
81116 if (request.fHelp || (request.params .size () != 3 && request.params .size () != 4 ))
@@ -101,35 +136,7 @@ UniValue quorum_info(const JSONRPCRequest& request)
101136 throw JSONRPCError (RPC_INVALID_PARAMETER, " quorum not found" );
102137 }
103138
104- UniValue ret (UniValue::VOBJ);
105-
106- ret.push_back (Pair (" height" , quorum->height ));
107- ret.push_back (Pair (" quorumHash" , quorum->qc .quorumHash .ToString ()));
108- ret.push_back (Pair (" minedBlock" , quorum->minedBlockHash .ToString ()));
109-
110- UniValue membersArr (UniValue::VARR);
111- for (size_t i = 0 ; i < quorum->members .size (); i++) {
112- auto & dmn = quorum->members [i];
113- UniValue mo (UniValue::VOBJ);
114- mo.push_back (Pair (" proTxHash" , dmn->proTxHash .ToString ()));
115- mo.push_back (Pair (" valid" , quorum->qc .validMembers [i]));
116- if (quorum->qc .validMembers [i]) {
117- CBLSPublicKey pubKey = quorum->GetPubKeyShare (i);
118- if (pubKey.IsValid ()) {
119- mo.push_back (Pair (" pubKeyShare" , pubKey.ToString ()));
120- }
121- }
122- membersArr.push_back (mo);
123- }
124-
125- ret.push_back (Pair (" members" , membersArr));
126- ret.push_back (Pair (" quorumPublicKey" , quorum->qc .quorumPublicKey .ToString ()));
127- CBLSSecretKey skShare = quorum->GetSkShare ();
128- if (includeSkShare && skShare.IsValid ()) {
129- ret.push_back (Pair (" secretKeyShare" , skShare.ToString ()));
130- }
131-
132- return ret;
139+ return BuildQuorumInfo (quorum, true , includeSkShare);
133140}
134141
135142void quorum_dkgstatus_help ()
@@ -182,6 +189,59 @@ UniValue quorum_dkgstatus(const JSONRPCRequest& request)
182189 return ret;
183190}
184191
192+ void quorum_memberof_help ()
193+ {
194+ throw std::runtime_error (
195+ " quorum memberof \" proTxHash\"\n "
196+ " Checks which quorums the given masternode is a member of.\n "
197+ " \n Arguments:\n "
198+ " 1. \" proTxHash\" (string, required) ProTxHash of the masternode.\n "
199+ );
200+ }
201+
202+ UniValue quorum_memberof (const JSONRPCRequest& request)
203+ {
204+ if (request.fHelp || (request.params .size () != 2 )) {
205+ quorum_memberof_help ();
206+ }
207+
208+ uint256 protxHash = ParseHashV (request.params [1 ], " proTxHash" );
209+
210+ const CBlockIndex* pindexTip;
211+ {
212+ LOCK (cs_main);
213+ pindexTip = chainActive.Tip ();
214+ }
215+
216+ auto mnList = deterministicMNManager->GetListForBlock (pindexTip->GetBlockHash ());
217+ auto dmn = mnList.GetMN (protxHash);
218+ if (!dmn) {
219+ throw JSONRPCError (RPC_INVALID_PARAMETER, " masternode not found" );
220+ }
221+
222+ std::set<std::pair<Consensus::LLMQType, uint256>> quorumHashes;
223+ for (const auto & p : Params ().GetConsensus ().llmqs ) {
224+ auto & params = p.second ;
225+ auto quorums = llmq::quorumManager->ScanQuorums (params.type , params.signingActiveQuorumCount );
226+ for (auto & quorum : quorums) {
227+ for (auto & m : quorum->members ) {
228+ if (m->proTxHash == dmn->proTxHash ) {
229+ quorumHashes.emplace (params.type , quorum->qc .quorumHash );
230+ }
231+ }
232+ }
233+ }
234+
235+ UniValue result (UniValue::VARR);
236+ for (auto & p : quorumHashes) {
237+ auto quorum = llmq::quorumManager->GetQuorum (p.first , p.second );
238+ assert (quorum);
239+ result.push_back (BuildQuorumInfo (quorum, false , false ));
240+ }
241+
242+ return result;
243+ }
244+
185245void quorum_sign_help ()
186246{
187247 throw std::runtime_error (
@@ -318,6 +378,7 @@ UniValue quorum_dkgsimerror(const JSONRPCRequest& request)
318378 " info - Return information about a quorum\n "
319379 " dkgsimerror - Simulates DKG errors and malicious behavior.\n "
320380 " dkgstatus - Return the status of the current DKG process\n "
381+ " memberof - Checks which quorums the given masternode is a member of\n "
321382 " sign - Threshold-sign a message\n "
322383 " hasrecsig - Test if a valid recovered signature is present\n "
323384 " getrecsig - Get a recovered signature\n "
@@ -342,6 +403,8 @@ UniValue quorum(const JSONRPCRequest& request)
342403 return quorum_info (request);
343404 } else if (command == " dkgstatus" ) {
344405 return quorum_dkgstatus (request);
406+ } else if (command == " memberof" ) {
407+ return quorum_memberof (request);
345408 } else if (command == " sign" || command == " hasrecsig" || command == " getrecsig" || command == " isconflicting" ) {
346409 return quorum_sigs_cmd (request);
347410 } else if (command == " dkgsimerror" ) {
0 commit comments