Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(rpc): protx listdiff rpc #5338

Merged
merged 3 commits into from
Apr 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions doc/release-notes-5338.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Added RPCs
--------

- `protx listdiff` RPC returns a full deterministic masternode list diff between two heigts.
62 changes: 62 additions & 0 deletions src/evo/dmnstate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
2 changes: 2 additions & 0 deletions src/evo/dmnstate.h
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,8 @@ class CDeterministicMNStateDiff
#undef DMN_STATE_DIFF_LINE
}

void ToJson(UniValue& obj, MnType nType) const;

SERIALIZE_METHODS(CDeterministicMNStateDiff, obj)
{
READWRITE(VARINT(obj.fields));
Expand Down
94 changes: 92 additions & 2 deletions src/rpc/evo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down Expand Up @@ -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"},
},
Expand Down Expand Up @@ -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();
}
}
Expand Down