Skip to content

Commit

Permalink
Merge #6106: feat: create new composite quorum-command platformsign
Browse files Browse the repository at this point in the history
2db69d7 chore: add release notes for "quorum platformsign" (Konstantin Akimov)
283c5f8 feat: create new composite command "quorum platformsign" (Konstantin Akimov)

Pull request description:

  ## Issue being fixed or feature implemented
  It splits from #6100
  With just whitelist it is impossible to limit the RPC `quorum sign` to use only one specific quorum type, this PR aim to provide ability for quorum signing for platform quorum only.

  ## What was done?
  Implemented a new composite command "quorum platformsign"

  This composite command let to limit quorum type for signing for case of whitelist.
  After that old way to limit platform commands can be deprecated - #6105

  ## How Has This Been Tested?
  Updated a functional tests to use platform signing for Asset Unlocks feature.

  ## Breaking Changes
  N/A

  ## Checklist:
  - [x] I have performed a self-review of my own code
  - [x] I have commented my code, particularly in hard-to-understand areas
  - [x] I have added or updated relevant unit/integration/functional/e2e tests
  - [ ] I have made corresponding changes to the documentation
  - [x] I have assigned this pull request to a milestone

ACKs for top commit:
  UdjinM6:
    utACK 2db69d7
  PastaPastaPasta:
    utACK 2db69d7

Tree-SHA512: b0dff9934137c4faa85664058e1e77f85067cc8d931e6d76ee5b9e610164ac8b0609736d5f09475256cb78d65bf92466624d784f0b13d20136df7e75613662cb
  • Loading branch information
PastaPastaPasta committed Jul 15, 2024
1 parent a45e6df commit db82817
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 25 deletions.
6 changes: 6 additions & 0 deletions doc/release-notes-6106.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
## Remote Procedure Call (RPC) Changes

### The new RPCs are:

- `quorum signplatform` This RPC is added for Platform needs. This composite command let to limit quorum type for signing by platform. It is equivalent of `quorum sign <platform type>`.

77 changes: 55 additions & 22 deletions src/rpc/quorums.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -427,42 +427,27 @@ static RPCHelpMan quorum_memberof()
};
}

static RPCHelpMan quorum_sign()
{
return RPCHelpMan{"quorum sign",
"Threshold-sign a message\n",
{
{"llmqType", RPCArg::Type::NUM, RPCArg::Optional::NO, "LLMQ type."},
{"id", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "Request id."},
{"msgHash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "Message hash."},
{"quorumHash", RPCArg::Type::STR_HEX, /* default */ "", "The quorum identifier."},
{"submit", RPCArg::Type::BOOL, /* default */ "true", "Submits the signature share to the network if this is true. "
"Returns an object containing the signature share if this is false."},
},
RPCResults{},
RPCExamples{""},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
static UniValue quorum_sign_helper(const JSONRPCRequest& request, Consensus::LLMQType llmqType)
{
const NodeContext& node = EnsureAnyNodeContext(request.context);
const ChainstateManager& chainman = EnsureChainman(node);
const LLMQContext& llmq_ctx = EnsureLLMQContext(node);

const Consensus::LLMQType llmqType{static_cast<Consensus::LLMQType>(ParseInt32V(request.params[0], "llmqType"))};
const auto llmq_params_opt = Params().GetLLMQ(llmqType);
if (!llmq_params_opt.has_value()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid LLMQ type");
}

const uint256 id(ParseHashV(request.params[1], "id"));
const uint256 msgHash(ParseHashV(request.params[2], "msgHash"));
const uint256 id(ParseHashV(request.params[0], "id"));
const uint256 msgHash(ParseHashV(request.params[1], "msgHash"));

uint256 quorumHash;
if (!request.params[3].isNull() && !request.params[3].get_str().empty()) {
quorumHash = ParseHashV(request.params[3], "quorumHash");
if (!request.params[2].isNull() && !request.params[2].get_str().empty()) {
quorumHash = ParseHashV(request.params[2], "quorumHash");
}
bool fSubmit{true};
if (!request.params[4].isNull()) {
fSubmit = ParseBoolV(request.params[4], "submit");
if (!request.params[3].isNull()) {
fSubmit = ParseBoolV(request.params[3], "submit");
}
if (fSubmit) {
return llmq_ctx.sigman->AsyncSignIfMember(llmqType, *llmq_ctx.shareman, id, msgHash, quorumHash);
Expand Down Expand Up @@ -496,6 +481,53 @@ static RPCHelpMan quorum_sign()

return obj;
}
}

static RPCHelpMan quorum_sign()
{
return RPCHelpMan{"quorum sign",
"Threshold-sign a message\n",
{
{"llmqType", RPCArg::Type::NUM, RPCArg::Optional::NO, "LLMQ type."},
{"id", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "Request id."},
{"msgHash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "Message hash."},
{"quorumHash", RPCArg::Type::STR_HEX, /* default */ "", "The quorum identifier."},
{"submit", RPCArg::Type::BOOL, /* default */ "true", "Submits the signature share to the network if this is true. "
"Returns an object containing the signature share if this is false."},
},
RPCResults{},
RPCExamples{""},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
const Consensus::LLMQType llmqType{static_cast<Consensus::LLMQType>(ParseInt32V(request.params[0], "llmqType"))};

JSONRPCRequest new_request{request};
new_request.params.setArray();
for (unsigned int i = 1; i < request.params.size(); ++i) {
new_request.params.push_back(request.params[i]);
}
return quorum_sign_helper(new_request, llmqType);
},
};
}

static RPCHelpMan quorum_platformsign()
{
return RPCHelpMan{"quorum platformsign",
"Threshold-sign a message. It signs messages only for platform quorums\n",
{
{"id", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "Request id."},
{"msgHash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "Message hash."},
{"quorumHash", RPCArg::Type::STR_HEX, /* default */ "", "The quorum identifier."},
{"submit", RPCArg::Type::BOOL, /* default */ "true", "Submits the signature share to the network if this is true. "
"Returns an object containing the signature share if this is false."},
},
RPCResults{},
RPCExamples{""},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
const Consensus::LLMQType llmqType{Params().GetConsensus().llmqTypePlatform};
return quorum_sign_helper(request, llmqType);
},
};
}
Expand Down Expand Up @@ -1110,6 +1142,7 @@ static const CRPCCommand commands[] =
{ "evo", "quorum", "dkgstatus", &quorum_dkgstatus, {"detail_level"} },
{ "evo", "quorum", "memberof", &quorum_memberof, {"proTxHash", "scanQuorumsCount"} },
{ "evo", "quorum", "sign", &quorum_sign, {"llmqType", "id", "msgHash", "quorumHash", "submit"} },
{ "evo", "quorum", "platformsign", &quorum_platformsign, {"id", "msgHash", "quorumHash", "submit"} },
{ "evo", "quorum", "verify", &quorum_verify, {"llmqType", "id", "msgHash", "signature", "quorumHash", "signHeight"} },
{ "evo", "quorum", "hasrecsig", &quorum_hasrecsig, {"llmqType", "id", "msgHash"} },
{ "evo", "quorum", "getrecsig", &quorum_getrecsig, {"llmqType", "id", "msgHash"} },
Expand Down
2 changes: 1 addition & 1 deletion test/functional/feature_asset_locks.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def create_assetunlock(self, index, withdrawal, pubkey=None, fee=tiny_amount):
unlock_tx.calc_sha256()
msgHash = format(unlock_tx.sha256, '064x')

recsig = self.get_recovered_sig(request_id, msgHash, llmq_type=llmq_type_test)
recsig = self.get_recovered_sig(request_id, msgHash, llmq_type=llmq_type_test, use_platformsign=True)

unlockTx_payload.quorumSig = bytearray.fromhex(recsig["sig"])
unlock_tx.vExtraPayload = unlockTx_payload.serialize()
Expand Down
7 changes: 5 additions & 2 deletions test/functional/test_framework/test_framework.py
Original file line number Diff line number Diff line change
Expand Up @@ -2033,13 +2033,16 @@ def check_recovered_sig():
return True
wait_until_helper(check_recovered_sig, timeout=timeout, sleep=1)

def get_recovered_sig(self, rec_sig_id, rec_sig_msg_hash, llmq_type=100):
def get_recovered_sig(self, rec_sig_id, rec_sig_msg_hash, llmq_type=100, use_platformsign=False):
# Note: recsigs aren't relayed to regular nodes by default,
# make sure to pick a mn as a node to query for recsigs.
try:
quorumHash = self.mninfo[0].node.quorum("selectquorum", llmq_type, rec_sig_id)["quorumHash"]
for mn in self.mninfo:
mn.node.quorum("sign", llmq_type, rec_sig_id, rec_sig_msg_hash, quorumHash)
if use_platformsign:
mn.node.quorum("platformsign", rec_sig_id, rec_sig_msg_hash, quorumHash)
else:
mn.node.quorum("sign", llmq_type, rec_sig_id, rec_sig_msg_hash, quorumHash)
self.wait_for_recovered_sig(rec_sig_id, rec_sig_msg_hash, llmq_type, 10)
return self.mninfo[0].node.quorum("getrecsig", llmq_type, rec_sig_id, rec_sig_msg_hash)
except JSONRPCException as e:
Expand Down

0 comments on commit db82817

Please sign in to comment.