mirror of
https://github.com/dashpay/dash.git
synced 2024-12-24 19:42:46 +01:00
feat(rpc): protx listdiff rpc (#5338)
## Issue being fixed or feature implemented ## What was done? Feature requested by @QuantumExplorer and @iammadab. This PR introduces `protx listdiff`: a more rich alternative of `protx diff` RPC. Currently, `protx diff` is returning data only required from SPV for SML Coinbase MerkleMNListRoot calculation. Platform team needed a similar RPC returning all the MNs data in order to calculate the identities. ## How Has This Been Tested? ## Breaking Changes ## Checklist: _Go over all the following points, and put an `x` in all the boxes that apply._ - [x] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have added or updated relevant unit/integration/functional/e2e tests - [x] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_
This commit is contained in:
parent
c5dee4107f
commit
6499917a83
4
doc/release-notes-5338.md
Normal file
4
doc/release-notes-5338.md
Normal file
@ -0,0 +1,4 @@
|
||||
Added RPCs
|
||||
--------
|
||||
|
||||
- `protx listdiff` RPC returns a full deterministic masternode list diff between two heigts.
|
@ -61,3 +61,65 @@ void CDeterministicMNState::ToJson(UniValue& obj, MnType nType) const
|
||||
obj.pushKV("operatorPayoutAddress", EncodeDestination(dest));
|
||||
}
|
||||
}
|
||||
|
||||
void CDeterministicMNStateDiff::ToJson(UniValue& obj, MnType nType) const
|
||||
{
|
||||
obj.clear();
|
||||
obj.setObject();
|
||||
if (fields & Field_addr) {
|
||||
obj.pushKV("service", state.addr.ToStringIPPort(false));
|
||||
}
|
||||
if (fields & Field_nRegisteredHeight) {
|
||||
obj.pushKV("registeredHeight", state.nRegisteredHeight);
|
||||
}
|
||||
if (fields & Field_nLastPaidHeight) {
|
||||
obj.pushKV("lastPaidHeight", state.nLastPaidHeight);
|
||||
}
|
||||
if (fields & Field_nConsecutivePayments) {
|
||||
obj.pushKV("consecutivePayments", state.nConsecutivePayments);
|
||||
}
|
||||
if (fields & Field_nPoSePenalty) {
|
||||
obj.pushKV("PoSePenalty", state.nPoSePenalty);
|
||||
}
|
||||
if (fields & Field_nPoSeRevivedHeight) {
|
||||
obj.pushKV("PoSeRevivedHeight", state.nPoSeRevivedHeight);
|
||||
}
|
||||
if (fields & Field_nPoSeBanHeight) {
|
||||
obj.pushKV("PoSeBanHeight", state.nPoSeBanHeight);
|
||||
}
|
||||
if (fields & Field_nRevocationReason) {
|
||||
obj.pushKV("revocationReason", state.nRevocationReason);
|
||||
}
|
||||
if (fields & Field_keyIDOwner) {
|
||||
obj.pushKV("ownerAddress", EncodeDestination(PKHash(state.keyIDOwner)));
|
||||
}
|
||||
if (fields & Field_keyIDVoting) {
|
||||
obj.pushKV("votingAddress", EncodeDestination(PKHash(state.keyIDVoting)));
|
||||
}
|
||||
if (fields & Field_scriptPayout) {
|
||||
CTxDestination dest;
|
||||
if (ExtractDestination(state.scriptPayout, dest)) {
|
||||
obj.pushKV("payoutAddress", EncodeDestination(dest));
|
||||
}
|
||||
}
|
||||
if (fields & Field_scriptOperatorPayout) {
|
||||
CTxDestination dest;
|
||||
if (ExtractDestination(state.scriptOperatorPayout, dest)) {
|
||||
obj.pushKV("operatorPayoutAddress", EncodeDestination(dest));
|
||||
}
|
||||
}
|
||||
if (fields & Field_pubKeyOperator) {
|
||||
obj.pushKV("pubKeyOperator", state.pubKeyOperator.Get().ToString());
|
||||
}
|
||||
if (nType == MnType::HighPerformance) {
|
||||
if (fields & Field_platformNodeID) {
|
||||
obj.pushKV("platformNodeID", state.platformNodeID.ToString());
|
||||
}
|
||||
if (fields & Field_platformP2PPort) {
|
||||
obj.pushKV("platformP2PPort", state.platformP2PPort);
|
||||
}
|
||||
if (fields & Field_platformHTTPPort) {
|
||||
obj.pushKV("platformHTTPPort", state.platformHTTPPort);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -261,6 +261,8 @@ public:
|
||||
#undef DMN_STATE_DIFF_LINE
|
||||
}
|
||||
|
||||
void ToJson(UniValue& obj, MnType nType) const;
|
||||
|
||||
SERIALIZE_METHODS(CDeterministicMNStateDiff, obj)
|
||||
{
|
||||
READWRITE(VARINT(obj.fields));
|
||||
|
@ -1467,6 +1467,92 @@ static UniValue protx_diff(const JSONRPCRequest& request)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void protx_listdiff_help(const JSONRPCRequest& request)
|
||||
{
|
||||
RPCHelpMan{"protx listdiff",
|
||||
"\nCalculate a full MN list diff between two masternode lists.\n",
|
||||
{
|
||||
{"baseBlock", RPCArg::Type::NUM, RPCArg::Optional::NO, "The starting block height."},
|
||||
{"block", RPCArg::Type::NUM, RPCArg::Optional::NO, "The ending block height."},
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""},
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static const CBlockIndex* ParseBlockIndex(const UniValue& v, std::string strName) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
|
||||
try {
|
||||
uint256 hash = ParseHashV(v, strName);
|
||||
const CBlockIndex* pblockindex = g_chainman.m_blockman.LookupBlockIndex(hash);
|
||||
if (!pblockindex)
|
||||
throw std::runtime_error(strprintf("Block %s with hash %s not found", strName, v.getValStr()));
|
||||
return pblockindex;
|
||||
} catch (...) {
|
||||
int h = ParseInt32V(v, strName);
|
||||
if (h < 1 || h > ::ChainActive().Height())
|
||||
throw std::runtime_error(strprintf("%s must be a chain height and not %s", strName, v.getValStr()));
|
||||
return ::ChainActive()[h];
|
||||
}
|
||||
}
|
||||
|
||||
static UniValue protx_listdiff(const JSONRPCRequest& request)
|
||||
{
|
||||
protx_listdiff_help(request);
|
||||
|
||||
LOCK(cs_main);
|
||||
UniValue ret(UniValue::VOBJ);
|
||||
|
||||
const CBlockIndex* pBaseBlockIndex = ParseBlockIndex(request.params[0], "baseBlock");
|
||||
const CBlockIndex* pTargetBlockIndex = ParseBlockIndex(request.params[1], "block");
|
||||
|
||||
if (pBaseBlockIndex == nullptr) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Base block not found");
|
||||
}
|
||||
|
||||
if (pTargetBlockIndex == nullptr) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
|
||||
}
|
||||
|
||||
ret.pushKV("baseHeight", pBaseBlockIndex->nHeight);
|
||||
ret.pushKV("blockHeight", pTargetBlockIndex->nHeight);
|
||||
|
||||
auto baseBlockMNList = deterministicMNManager->GetListForBlock(pBaseBlockIndex);
|
||||
auto blockMNList = deterministicMNManager->GetListForBlock(pTargetBlockIndex);
|
||||
|
||||
auto mnDiff = baseBlockMNList.BuildDiff(blockMNList);
|
||||
|
||||
UniValue jaddedMNs(UniValue::VARR);
|
||||
for(const auto& mn : mnDiff.addedMNs) {
|
||||
UniValue obj;
|
||||
mn->ToJson(obj);
|
||||
jaddedMNs.push_back(obj);
|
||||
}
|
||||
ret.pushKV("addedMNs", jaddedMNs);
|
||||
|
||||
UniValue jremovedMNs(UniValue::VARR);
|
||||
for(const auto& internal_id : mnDiff.removedMns) {
|
||||
auto dmn = baseBlockMNList.GetMNByInternalId(internal_id);
|
||||
jremovedMNs.push_back(dmn->proTxHash.ToString());
|
||||
}
|
||||
ret.pushKV("removedMNs", jremovedMNs);
|
||||
|
||||
UniValue jupdatedMNs(UniValue::VARR);
|
||||
for(const auto& [internal_id, stateDiff] : mnDiff.updatedMNs) {
|
||||
auto dmn = baseBlockMNList.GetMNByInternalId(internal_id);
|
||||
UniValue s(UniValue::VOBJ);
|
||||
stateDiff.ToJson(s, dmn->nType);
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
obj.pushKV(dmn->proTxHash.ToString(), s);
|
||||
jupdatedMNs.push_back(obj);
|
||||
}
|
||||
ret.pushKV("updatedMNs", jupdatedMNs);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
[[ noreturn ]] static void protx_help()
|
||||
{
|
||||
RPCHelpMan{
|
||||
@ -1495,7 +1581,8 @@ static UniValue protx_diff(const JSONRPCRequest& request)
|
||||
" update_registrar_legacy - Create ProUpRegTx by parsing BLS using the legacy scheme, then send it to network\n"
|
||||
" revoke - Create and send ProUpRevTx to network\n"
|
||||
#endif
|
||||
" diff - Calculate a diff and a proof between two masternode lists\n",
|
||||
" diff - Calculate a diff and a proof between two masternode lists\n"
|
||||
" listdiff - Calculate a full MN list diff between two masternode lists\n",
|
||||
{
|
||||
{"command", RPCArg::Type::STR, RPCArg::Optional::NO, "The command to execute"},
|
||||
},
|
||||
@ -1536,7 +1623,10 @@ static UniValue protx(const JSONRPCRequest& request)
|
||||
return protx_info(new_request);
|
||||
} else if (command == "protxdiff") {
|
||||
return protx_diff(new_request);
|
||||
} else {
|
||||
} else if (command == "protxlistdiff") {
|
||||
return protx_listdiff(new_request);
|
||||
}
|
||||
else {
|
||||
protx_help();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user