Skip to content
Open
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
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -931,6 +931,7 @@ libbitcoin_common_a_SOURCES = \
deploymentinfo.cpp \
evo/core_write.cpp \
evo/netinfo.cpp \
evo/providertx_util.cpp \
external_signer.cpp \
governance/common.cpp \
governance/core_write.cpp \
Expand Down Expand Up @@ -1200,6 +1201,7 @@ dash_chainstate_SOURCES = \
evo/netinfo.cpp \
evo/mnhftx.cpp \
evo/providertx.cpp \
evo/providertx_util.cpp \
evo/simplifiedmns.cpp \
evo/smldiff.cpp \
evo/specialtx.cpp \
Expand Down
10 changes: 8 additions & 2 deletions src/common/bloom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,10 +132,13 @@ bool CBloomFilter::CheckSpecialTransactionMatchesAndUpdate(const CTransaction &t
switch(tx.nType) {
case(TRANSACTION_PROVIDER_REGISTER): {
if (const auto opt_proTx = GetTxPayload<CProRegTx>(tx)) {
const auto owner_payouts = GetOwnerPayouts(opt_proTx->nVersion, opt_proTx->scriptPayout, opt_proTx->payouts);
const bool found_payout = std::any_of(owner_payouts.begin(), owner_payouts.end(),
[&](const auto& payout) { return CheckScript(payout.scriptPayout); });
if(contains(opt_proTx->collateralOutpoint) ||
contains(opt_proTx->keyIDOwner) ||
contains(opt_proTx->keyIDVoting) ||
CheckScript(opt_proTx->scriptPayout)) {
found_payout) {
if ((nFlags & BLOOM_UPDATE_MASK) == BLOOM_UPDATE_ALL)
insert(tx.GetHash());
return true;
Expand All @@ -160,8 +163,11 @@ bool CBloomFilter::CheckSpecialTransactionMatchesAndUpdate(const CTransaction &t
if (const auto opt_proTx = GetTxPayload<CProUpRegTx>(tx)) {
if(contains(opt_proTx->proTxHash))
return true;
const auto owner_payouts = GetOwnerPayouts(opt_proTx->nVersion, opt_proTx->scriptPayout, opt_proTx->payouts);
const bool found_payout = std::any_of(owner_payouts.begin(), owner_payouts.end(),
[&](const auto& payout) { return CheckScript(payout.scriptPayout); });
if(contains(opt_proTx->keyIDVoting) ||
CheckScript(opt_proTx->scriptPayout)) {
found_payout) {
if ((nFlags & BLOOM_UPDATE_MASK) == BLOOM_UPDATE_ALL)
insert(opt_proTx->proTxHash);
return true;
Expand Down
31 changes: 27 additions & 4 deletions src/evo/core_write.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,16 @@ const std::map<std::string, RPCResult> RPCRESULT_MAP{{
RESULT_MAP_ENTRY("outpoint", RPCResult::Type::STR_HEX,"The outpoint of the masternode"),
RESULT_MAP_ENTRY("ownerAddress", RPCResult::Type::STR, "Dash address used for payee updates and proposal voting"),
RESULT_MAP_ENTRY("payoutAddress", RPCResult::Type::STR, "Dash address used for masternode reward payments"),
{"payouts",
{RPCResult::Type::ARR, "payouts", "Owner masternode reward payout shares",
{
{RPCResult::Type::OBJ, "", "",
{
{RPCResult::Type::STR, "address", "Dash address used for this owner payout"},
{RPCResult::Type::STR_HEX, "script", "Owner payout scriptPubKey"},
{RPCResult::Type::NUM, "reward", "Owner payout share in basis points"},
}},
}}},
RESULT_MAP_ENTRY("platformHTTPPort", RPCResult::Type::NUM, "TCP port of Platform HTTP API (DEPRECATED, returned only if config option -deprecatedrpc=service is passed)"),
RESULT_MAP_ENTRY("platformNodeID", RPCResult::Type::STR_HEX, "Node ID derived from P2P public key for Platform P2P"),
RESULT_MAP_ENTRY("platformP2PPort", RPCResult::Type::NUM, "TCP port of Platform P2P (DEPRECATED, returned only if config option -deprecatedrpc=service is passed)"),
Expand Down Expand Up @@ -212,6 +222,7 @@ RPCResult CDeterministicMNState::GetJsonHelp(const std::string& key, bool option
GetRpcResult("platformP2PPort", /*optional=*/true),
GetRpcResult("platformHTTPPort", /*optional=*/true),
GetRpcResult("payoutAddress", /*optional=*/true),
GetRpcResult("payouts", /*optional=*/true),
GetRpcResult("pubKeyOperator"),
GetRpcResult("operatorPayoutAddress", /*optional=*/true),
}};
Expand Down Expand Up @@ -243,7 +254,9 @@ UniValue CDeterministicMNState::ToJson(MnType nType) const
}

CTxDestination dest;
if (ExtractDestination(scriptPayout, dest)) {
if (nVersion >= ProTxVersion::MultiPayout) {
obj.pushKV("payouts", PayoutListToJson(payouts));
} else if (ExtractDestination(scriptPayout, dest)) {
obj.pushKV("payoutAddress", EncodeDestination(dest));
}
obj.pushKV("pubKeyOperator", pubKeyOperator.ToString());
Expand All @@ -270,6 +283,7 @@ RPCResult CDeterministicMNStateDiff::GetJsonHelp(const std::string& key, bool op
GetRpcResult("ownerAddress", /*optional=*/true),
GetRpcResult("votingAddress", /*optional=*/true),
GetRpcResult("payoutAddress", /*optional=*/true),
GetRpcResult("payouts", /*optional=*/true),
GetRpcResult("operatorPayoutAddress", /*optional=*/true),
GetRpcResult("pubKeyOperator", /*optional=*/true),
GetRpcResult("platformNodeID", /*optional=*/true),
Expand All @@ -292,6 +306,7 @@ RPCResult CProRegTx::GetJsonHelp(const std::string& key, bool optional)
GetRpcResult("ownerAddress"),
GetRpcResult("votingAddress"),
GetRpcResult("payoutAddress", /*optional=*/true),
GetRpcResult("payouts", /*optional=*/true),
GetRpcResult("pubKeyOperator"),
GetRpcResult("operatorReward"),
GetRpcResult("platformNodeID", /*optional=*/true),
Expand All @@ -314,7 +329,9 @@ UniValue CProRegTx::ToJson() const
ret.pushKV("addresses", GetNetInfoWithLegacyFields(*this, nType));
ret.pushKV("ownerAddress", EncodeDestination(PKHash(keyIDOwner)));
ret.pushKV("votingAddress", EncodeDestination(PKHash(keyIDVoting)));
if (CTxDestination dest; ExtractDestination(scriptPayout, dest)) {
if (nVersion >= ProTxVersion::MultiPayout) {
ret.pushKV("payouts", PayoutListToJson(payouts));
} else if (CTxDestination dest; ExtractDestination(scriptPayout, dest)) {
ret.pushKV("payoutAddress", EncodeDestination(dest));
}
ret.pushKV("pubKeyOperator", pubKeyOperator.ToString());
Expand All @@ -338,6 +355,7 @@ RPCResult CProUpRegTx::GetJsonHelp(const std::string& key, bool optional)
GetRpcResult("proTxHash"),
GetRpcResult("votingAddress"),
GetRpcResult("payoutAddress", /*optional=*/true),
GetRpcResult("payouts", /*optional=*/true),
GetRpcResult("pubKeyOperator"),
GetRpcResult("inputsHash"),
}};
Expand All @@ -349,7 +367,9 @@ UniValue CProUpRegTx::ToJson() const
ret.pushKV("version", nVersion);
ret.pushKV("proTxHash", proTxHash.ToString());
ret.pushKV("votingAddress", EncodeDestination(PKHash(keyIDVoting)));
if (CTxDestination dest; ExtractDestination(scriptPayout, dest)) {
if (nVersion >= ProTxVersion::MultiPayout) {
ret.pushKV("payouts", PayoutListToJson(payouts));
} else if (CTxDestination dest; ExtractDestination(scriptPayout, dest)) {
ret.pushKV("payoutAddress", EncodeDestination(dest));
}
ret.pushKV("pubKeyOperator", pubKeyOperator.ToString());
Expand Down Expand Up @@ -528,6 +548,7 @@ RPCResult CSimplifiedMNListEntry::GetJsonHelp(const std::string& key, bool optio
GetRpcResult("platformHTTPPort", /*optional=*/true),
GetRpcResult("platformNodeID", /*optional=*/true),
GetRpcResult("payoutAddress", /*optional=*/true),
GetRpcResult("payouts", /*optional=*/true),
GetRpcResult("operatorPayoutAddress", /*optional=*/true),
}};
}
Expand Down Expand Up @@ -555,7 +576,9 @@ UniValue CSimplifiedMNListEntry::ToJson(bool extended) const

if (extended) {
CTxDestination dest;
if (ExtractDestination(scriptPayout, dest)) {
if (nVersion >= ProTxVersion::MultiPayout) {
obj.pushKV("payouts", PayoutListToJson(payouts));
} else if (ExtractDestination(scriptPayout, dest)) {
obj.pushKV("payoutAddress", EncodeDestination(dest));
}
if (ExtractDestination(scriptOperatorPayout, dest)) {
Expand Down
3 changes: 2 additions & 1 deletion src/evo/deterministicmns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ CSimplifiedMNListEntry CDeterministicMN::to_sml_entry() const
const CDeterministicMNState& state{*pdmnState};
return CSimplifiedMNListEntry(proTxHash, state.confirmedHash, state.netInfo, state.pubKeyOperator,
state.keyIDVoting, !state.IsBanned(), state.platformHTTPPort, state.platformNodeID,
state.scriptPayout, state.scriptOperatorPayout, state.nVersion, nType);
state.scriptPayout, GetOwnerPayouts(state.nVersion, state.scriptPayout, state.payouts),
state.scriptOperatorPayout, state.nVersion, nType);
}

std::string CDeterministicMN::ToString() const
Expand Down
9 changes: 7 additions & 2 deletions src/evo/dmnstate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,19 @@ std::string CDeterministicMNState::ToString() const
if (ExtractDestination(scriptPayout, dest)) {
payoutAddress = EncodeDestination(dest);
}
const auto owner_payouts = GetOwnerPayouts(nVersion, scriptPayout, payouts);
const std::string payoutList = PayoutListToString(owner_payouts);
if (ExtractDestination(scriptOperatorPayout, dest)) {
operatorPayoutAddress = EncodeDestination(dest);
}

return strprintf("CDeterministicMNState(nVersion=%d, nRegisteredHeight=%d, nLastPaidHeight=%d, nPoSePenalty=%d, "
"nPoSeRevivedHeight=%d, nPoSeBanHeight=%d, nRevocationReason=%d, "
"ownerAddress=%s, pubKeyOperator=%s, votingAddress=%s, netInfo=%s, payoutAddress=%s, "
"ownerAddress=%s, pubKeyOperator=%s, votingAddress=%s, netInfo=%s, payoutAddress=%s, payouts=%s, "
"operatorPayoutAddress=%s)\n",
nVersion, nRegisteredHeight, nLastPaidHeight, nPoSePenalty, nPoSeRevivedHeight, nPoSeBanHeight,
nRevocationReason, EncodeDestination(PKHash(keyIDOwner)), pubKeyOperator.ToString(),
EncodeDestination(PKHash(keyIDVoting)), netInfo->ToString(), payoutAddress, operatorPayoutAddress);
EncodeDestination(PKHash(keyIDVoting)), netInfo->ToString(), payoutAddress, payoutList, operatorPayoutAddress);
}

UniValue CDeterministicMNStateDiff::ToJson(MnType nType) const
Expand Down Expand Up @@ -73,6 +75,9 @@ UniValue CDeterministicMNStateDiff::ToJson(MnType nType) const
obj.pushKV("payoutAddress", EncodeDestination(dest));
}
}
if (fields & Field_payouts) {
obj.pushKV("payouts", PayoutListToJson(state.payouts));
}
if (fields & Field_scriptOperatorPayout) {
CTxDestination dest;
if (ExtractDestination(state.scriptOperatorPayout, dest)) {
Expand Down
13 changes: 11 additions & 2 deletions src/evo/dmnstate.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class CDeterministicMNState
CKeyID keyIDVoting;
std::shared_ptr<NetInfoInterface> netInfo{nullptr};
CScript scriptPayout;
MasternodePayoutShares payouts;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve v4 payout shares across revocation

For a v4 masternode registered with payout shares, a later ProUpRevTx still calls ResetOperatorFields(), which downgrades nVersion to LegacyBLS; since v4 registrations do not serialize a legacy scriptPayout, the added payouts state becomes ignored by GetOwnerPayouts() and is lost on state serialization. In that revoked state, RPC flows such as protx update_registrar with an empty payout can no longer reuse the existing payout shares and instead try to reuse an empty legacy script, so revocation unexpectedly discards the configured owner payouts.

Useful? React with 👍 / 👎.

CScript scriptOperatorPayout;

uint160 platformNodeID{};
Expand All @@ -72,6 +73,7 @@ class CDeterministicMNState
keyIDVoting(proTx.keyIDVoting),
netInfo(proTx.netInfo),
scriptPayout(proTx.scriptPayout),
payouts(proTx.payouts),
platformNodeID(proTx.platformNodeID),
platformP2PPort(proTx.platformP2PPort),
platformHTTPPort(proTx.platformHTTPPort)
Expand All @@ -98,8 +100,13 @@ class CDeterministicMNState
READWRITE(
obj.keyIDVoting,
NetInfoSerWrapper(const_cast<std::shared_ptr<NetInfoInterface>&>(obj.netInfo),
obj.nVersion >= ProTxVersion::ExtAddr),
obj.scriptPayout,
obj.nVersion >= ProTxVersion::ExtAddr));
if (obj.nVersion >= ProTxVersion::MultiPayout) {
READWRITE(obj.payouts);
} else {
READWRITE(obj.scriptPayout);
}
READWRITE(
obj.scriptOperatorPayout,
obj.platformNodeID);
if (obj.nVersion < ProTxVersion::ExtAddr) {
Expand Down Expand Up @@ -176,6 +183,7 @@ class CDeterministicMNStateDiff
Field_platformNodeID = 0x10000,
Field_platformP2PPort = 0x20000,
Field_platformHTTPPort = 0x40000,
Field_payouts = 0x80000,
};

private:
Expand Down Expand Up @@ -203,6 +211,7 @@ class CDeterministicMNStateDiff
DMN_STATE_MEMBER(keyIDVoting),
DMN_STATE_MEMBER(netInfo),
DMN_STATE_MEMBER(scriptPayout),
DMN_STATE_MEMBER(payouts),
DMN_STATE_MEMBER(scriptOperatorPayout),
DMN_STATE_MEMBER(nConsecutivePayments),
DMN_STATE_MEMBER(platformNodeID),
Expand Down
Loading
Loading