Skip to content

Commit e3c4d66

Browse files
committed
refactor: quorum sign methods
They are separated to own commit because the code move is not trivial to review
1 parent 2af9d86 commit e3c4d66

File tree

1 file changed

+157
-118
lines changed

1 file changed

+157
-118
lines changed

src/rpc/quorums.cpp

Lines changed: 157 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -436,12 +436,68 @@ static RPCHelpMan quorum_sign()
436436
},
437437
RPCResults{},
438438
RPCExamples{""},
439-
}.Check(request);
439+
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
440+
{
441+
const NodeContext& node = EnsureAnyNodeContext(request.context);
442+
const LLMQContext& llmq_ctx = EnsureLLMQContext(node);
443+
444+
Consensus::LLMQType llmqType = (Consensus::LLMQType)ParseInt32V(request.params[0], "llmqType");
445+
446+
const auto& llmq_params_opt = Params().GetLLMQ(llmqType);
447+
if (!llmq_params_opt.has_value()) {
448+
throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid LLMQ type");
449+
}
450+
451+
uint256 id(ParseHashV(request.params[1], "id"));
452+
uint256 msgHash(ParseHashV(request.params[2], "msgHash"));
453+
454+
uint256 quorumHash;
455+
if (!request.params[3].isNull() && !request.params[3].get_str().empty()) {
456+
quorumHash = ParseHashV(request.params[3], "quorumHash");
457+
}
458+
bool fSubmit{true};
459+
if (!request.params[4].isNull()) {
460+
fSubmit = ParseBoolV(request.params[4], "submit");
461+
}
462+
if (fSubmit) {
463+
return llmq_ctx.sigman->AsyncSignIfMember(llmqType, *llmq_ctx.shareman, id, msgHash, quorumHash);
464+
} else {
465+
llmq::CQuorumCPtr pQuorum;
466+
467+
if (quorumHash.IsNull()) {
468+
pQuorum = llmq::SelectQuorumForSigning(llmq_params_opt.value(), *llmq_ctx.qman, id);
469+
} else {
470+
pQuorum = llmq_ctx.qman->GetQuorum(llmqType, quorumHash);
471+
}
472+
473+
if (pQuorum == nullptr) {
474+
throw JSONRPCError(RPC_INVALID_PARAMETER, "quorum not found");
475+
}
476+
477+
auto sigShare = llmq_ctx.shareman->CreateSigShare(pQuorum, id, msgHash);
478+
479+
if (!sigShare.has_value() || !sigShare->sigShare.Get().IsValid()) {
480+
throw JSONRPCError(RPC_INVALID_PARAMETER, "failed to create sigShare");
481+
}
482+
483+
UniValue obj(UniValue::VOBJ);
484+
obj.pushKV("llmqType", static_cast<uint8_t>(llmqType));
485+
obj.pushKV("quorumHash", sigShare->getQuorumHash().ToString());
486+
obj.pushKV("quorumMember", sigShare->getQuorumMember());
487+
obj.pushKV("id", id.ToString());
488+
obj.pushKV("msgHash", msgHash.ToString());
489+
obj.pushKV("signHash", sigShare->GetSignHash().ToString());
490+
obj.pushKV("signature", sigShare->sigShare.Get().ToString());
491+
492+
return obj;
493+
}
494+
},
495+
};
440496
}
441497

442-
static void quorum_verify_help(const JSONRPCRequest& request)
498+
static RPCHelpMan quorum_verify()
443499
{
444-
RPCHelpMan{"quorum verify",
500+
return RPCHelpMan{"quorum verify",
445501
"Test if a quorum signature is valid for a request id and a message hash\n",
446502
{
447503
{"llmqType", RPCArg::Type::NUM, RPCArg::Optional::NO, "LLMQ type."},
@@ -457,12 +513,54 @@ static void quorum_verify_help(const JSONRPCRequest& request)
457513
},
458514
RPCResults{},
459515
RPCExamples{""},
460-
}.Check(request);
516+
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
517+
{
518+
const NodeContext& node = EnsureAnyNodeContext(request.context);
519+
const LLMQContext& llmq_ctx = EnsureLLMQContext(node);
520+
521+
Consensus::LLMQType llmqType = (Consensus::LLMQType)ParseInt32V(request.params[0], "llmqType");
522+
523+
const auto& llmq_params_opt = Params().GetLLMQ(llmqType);
524+
if (!llmq_params_opt.has_value()) {
525+
throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid LLMQ type");
526+
}
527+
528+
uint256 id(ParseHashV(request.params[1], "id"));
529+
uint256 msgHash(ParseHashV(request.params[2], "msgHash"));
530+
531+
const bool use_bls_legacy = bls::bls_legacy_scheme.load();
532+
CBLSSignature sig;
533+
if (!sig.SetHexStr(request.params[3].get_str(), use_bls_legacy)) {
534+
throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid signature format");
535+
}
536+
537+
if (request.params[4].isNull() || (request.params[4].get_str().empty() && !request.params[5].isNull())) {
538+
int signHeight{-1};
539+
if (!request.params[5].isNull()) {
540+
signHeight = ParseInt32V(request.params[5], "signHeight");
541+
}
542+
// First check against the current active set, if it fails check against the last active set
543+
int signOffset{llmq_params_opt->dkgInterval};
544+
return llmq::VerifyRecoveredSig(llmqType, *llmq_ctx.qman, signHeight, id, msgHash, sig, 0) ||
545+
llmq::VerifyRecoveredSig(llmqType, *llmq_ctx.qman, signHeight, id, msgHash, sig, signOffset);
546+
}
547+
548+
uint256 quorumHash(ParseHashV(request.params[4], "quorumHash"));
549+
llmq::CQuorumCPtr quorum = llmq_ctx.qman->GetQuorum(llmqType, quorumHash);
550+
551+
if (!quorum) {
552+
throw JSONRPCError(RPC_INVALID_PARAMETER, "quorum not found");
553+
}
554+
555+
uint256 signHash = llmq::BuildSignHash(llmqType, quorum->qc->quorumHash, id, msgHash);
556+
return sig.VerifyInsecure(quorum->qc->quorumPublicKey, signHash);
557+
},
558+
};
461559
}
462560

463-
static void quorum_hasrecsig_help(const JSONRPCRequest& request)
561+
static RPCHelpMan quorum_hasrecsig()
464562
{
465-
RPCHelpMan{"quorum hasrecsig",
563+
return RPCHelpMan{"quorum hasrecsig",
466564
"Test if a valid recovered signature is present\n",
467565
{
468566
{"llmqType", RPCArg::Type::NUM, RPCArg::Optional::NO, "LLMQ type."},
@@ -471,12 +569,29 @@ static void quorum_hasrecsig_help(const JSONRPCRequest& request)
471569
},
472570
RPCResults{},
473571
RPCExamples{""},
474-
}.Check(request);
572+
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
573+
{
574+
const NodeContext& node = EnsureAnyNodeContext(request.context);
575+
const LLMQContext& llmq_ctx = EnsureLLMQContext(node);
576+
577+
Consensus::LLMQType llmqType = (Consensus::LLMQType)ParseInt32V(request.params[0], "llmqType");
578+
579+
const auto& llmq_params_opt = Params().GetLLMQ(llmqType);
580+
if (!llmq_params_opt.has_value()) {
581+
throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid LLMQ type");
582+
}
583+
584+
uint256 id(ParseHashV(request.params[1], "id"));
585+
uint256 msgHash(ParseHashV(request.params[2], "msgHash"));
586+
587+
return llmq_ctx.sigman->HasRecoveredSig(llmqType, id, msgHash);
588+
},
589+
};
475590
}
476591

477-
static void quorum_getrecsig_help(const JSONRPCRequest& request)
592+
static RPCHelpMan quorum_getrecsig()
478593
{
479-
RPCHelpMan{"quorum getrecsig",
594+
return RPCHelpMan{"quorum getrecsig",
480595
"Get a recovered signature\n",
481596
{
482597
{"llmqType", RPCArg::Type::NUM, RPCArg::Optional::NO, "LLMQ type."},
@@ -485,12 +600,36 @@ static void quorum_getrecsig_help(const JSONRPCRequest& request)
485600
},
486601
RPCResults{},
487602
RPCExamples{""},
488-
}.Check(request);
603+
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
604+
{
605+
const NodeContext& node = EnsureAnyNodeContext(request.context);
606+
const LLMQContext& llmq_ctx = EnsureLLMQContext(node);
607+
608+
Consensus::LLMQType llmqType = (Consensus::LLMQType)ParseInt32V(request.params[0], "llmqType");
609+
610+
const auto& llmq_params_opt = Params().GetLLMQ(llmqType);
611+
if (!llmq_params_opt.has_value()) {
612+
throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid LLMQ type");
613+
}
614+
615+
uint256 id(ParseHashV(request.params[1], "id"));
616+
uint256 msgHash(ParseHashV(request.params[2], "msgHash"));
617+
618+
llmq::CRecoveredSig recSig;
619+
if (!llmq_ctx.sigman->GetRecoveredSigForId(llmqType, id, recSig)) {
620+
throw JSONRPCError(RPC_INVALID_PARAMETER, "recovered signature not found");
621+
}
622+
if (recSig.getMsgHash() != msgHash) {
623+
throw JSONRPCError(RPC_INVALID_PARAMETER, "recovered signature not found");
624+
}
625+
return recSig.ToJson();
626+
},
627+
};
489628
}
490629

491-
static void quorum_isconflicting_help(const JSONRPCRequest& request)
630+
static RPCHelpMan quorum_isconflicting()
492631
{
493-
RPCHelpMan{"quorum isconflicting",
632+
return RPCHelpMan{"quorum isconflicting",
494633
"Test if a conflict exists\n",
495634
{
496635
{"llmqType", RPCArg::Type::NUM, RPCArg::Optional::NO, "LLMQ type."},
@@ -499,28 +638,10 @@ static void quorum_isconflicting_help(const JSONRPCRequest& request)
499638
},
500639
RPCResults{},
501640
RPCExamples{""},
502-
}.Check(request);
503-
}
504-
505-
static UniValue quorum_sigs_cmd(const JSONRPCRequest& request, const LLMQContext& llmq_ctx)
641+
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
506642
{
507-
auto cmd = request.strMethod;
508-
if (request.fHelp || (request.params.size() != 3)) {
509-
if (cmd == "quorumsign") {
510-
quorum_sign_help(request);
511-
} else if (cmd == "quorumverify") {
512-
quorum_verify_help(request);
513-
} else if (cmd == "quorumhasrecsig") {
514-
quorum_hasrecsig_help(request);
515-
} else if (cmd == "quorumgetrecsig") {
516-
quorum_getrecsig_help(request);
517-
} else if (cmd == "quorumisconflicting") {
518-
quorum_isconflicting_help(request);
519-
} else {
520-
// shouldn't happen as it's already handled by the caller
521-
throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid cmd");
522-
}
523-
}
643+
const NodeContext& node = EnsureAnyNodeContext(request.context);
644+
const LLMQContext& llmq_ctx = EnsureLLMQContext(node);
524645

525646
Consensus::LLMQType llmqType = (Consensus::LLMQType)ParseInt32V(request.params[0], "llmqType");
526647

@@ -532,91 +653,9 @@ static UniValue quorum_sigs_cmd(const JSONRPCRequest& request, const LLMQContext
532653
uint256 id(ParseHashV(request.params[1], "id"));
533654
uint256 msgHash(ParseHashV(request.params[2], "msgHash"));
534655

535-
if (cmd == "quorumsign") {
536-
uint256 quorumHash;
537-
if (!request.params[3].isNull() && !request.params[3].get_str().empty()) {
538-
quorumHash = ParseHashV(request.params[3], "quorumHash");
539-
}
540-
bool fSubmit{true};
541-
if (!request.params[4].isNull()) {
542-
fSubmit = ParseBoolV(request.params[4], "submit");
543-
}
544-
if (fSubmit) {
545-
return llmq_ctx.sigman->AsyncSignIfMember(llmqType, *llmq_ctx.shareman, id, msgHash, quorumHash);
546-
} else {
547-
llmq::CQuorumCPtr pQuorum;
548-
549-
if (quorumHash.IsNull()) {
550-
pQuorum = llmq::SelectQuorumForSigning(llmq_params_opt.value(), *llmq_ctx.qman, id);
551-
} else {
552-
pQuorum = llmq_ctx.qman->GetQuorum(llmqType, quorumHash);
553-
}
554-
555-
if (pQuorum == nullptr) {
556-
throw JSONRPCError(RPC_INVALID_PARAMETER, "quorum not found");
557-
}
558-
559-
auto sigShare = llmq_ctx.shareman->CreateSigShare(pQuorum, id, msgHash);
560-
561-
if (!sigShare.has_value() || !sigShare->sigShare.Get().IsValid()) {
562-
throw JSONRPCError(RPC_INVALID_PARAMETER, "failed to create sigShare");
563-
}
564-
565-
UniValue obj(UniValue::VOBJ);
566-
obj.pushKV("llmqType", static_cast<uint8_t>(llmqType));
567-
obj.pushKV("quorumHash", sigShare->getQuorumHash().ToString());
568-
obj.pushKV("quorumMember", sigShare->getQuorumMember());
569-
obj.pushKV("id", id.ToString());
570-
obj.pushKV("msgHash", msgHash.ToString());
571-
obj.pushKV("signHash", sigShare->GetSignHash().ToString());
572-
obj.pushKV("signature", sigShare->sigShare.Get().ToString());
573-
574-
return obj;
575-
}
576-
} else if (cmd == "quorumverify") {
577-
const bool use_bls_legacy = bls::bls_legacy_scheme.load();
578-
CBLSSignature sig;
579-
if (!sig.SetHexStr(request.params[3].get_str(), use_bls_legacy)) {
580-
throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid signature format");
581-
}
582-
583-
if (request.params[4].isNull() || (request.params[4].get_str().empty() && !request.params[5].isNull())) {
584-
int signHeight{-1};
585-
if (!request.params[5].isNull()) {
586-
signHeight = ParseInt32V(request.params[5], "signHeight");
587-
}
588-
// First check against the current active set, if it fails check against the last active set
589-
int signOffset{llmq_params_opt->dkgInterval};
590-
return llmq::VerifyRecoveredSig(llmqType, *llmq_ctx.qman, signHeight, id, msgHash, sig, 0) ||
591-
llmq::VerifyRecoveredSig(llmqType, *llmq_ctx.qman, signHeight, id, msgHash, sig, signOffset);
592-
} else {
593-
uint256 quorumHash(ParseHashV(request.params[4], "quorumHash"));
594-
llmq::CQuorumCPtr quorum = llmq_ctx.qman->GetQuorum(llmqType, quorumHash);
595-
596-
if (!quorum) {
597-
throw JSONRPCError(RPC_INVALID_PARAMETER, "quorum not found");
598-
}
599-
600-
uint256 signHash = llmq::BuildSignHash(llmqType, quorum->qc->quorumHash, id, msgHash);
601-
return sig.VerifyInsecure(quorum->qc->quorumPublicKey, signHash);
602-
}
603-
} else if (cmd == "quorumhasrecsig") {
604-
return llmq_ctx.sigman->HasRecoveredSig(llmqType, id, msgHash);
605-
} else if (cmd == "quorumgetrecsig") {
606-
llmq::CRecoveredSig recSig;
607-
if (!llmq_ctx.sigman->GetRecoveredSigForId(llmqType, id, recSig)) {
608-
throw JSONRPCError(RPC_INVALID_PARAMETER, "recovered signature not found");
609-
}
610-
if (recSig.getMsgHash() != msgHash) {
611-
throw JSONRPCError(RPC_INVALID_PARAMETER, "recovered signature not found");
612-
}
613-
return recSig.ToJson();
614-
} else if (cmd == "quorumisconflicting") {
615-
return llmq_ctx.sigman->IsConflicting(llmqType, id, msgHash);
616-
} else {
617-
// shouldn't happen as it's already handled by the caller
618-
throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid cmd");
619-
}
656+
return llmq_ctx.sigman->IsConflicting(llmqType, id, msgHash);
657+
},
658+
};
620659
}
621660

622661
static RPCHelpMan quorum_selectquorum()

0 commit comments

Comments
 (0)