Skip to content

Commit cae6ceb

Browse files
fix: preserve multipayout state across revocation
1 parent 57a70f2 commit cae6ceb

4 files changed

Lines changed: 19 additions & 1 deletion

File tree

src/evo/providertx.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ bool IsPayoutListTriviallyValid(const MasternodePayoutShares& payouts, const CKe
7676
if (!ExtractDestination(payout.scriptPayout, payout_dest)) {
7777
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-payee-dest");
7878
}
79-
if (payout_dest == CTxDestination(PKHash(keyIDOwner)) || payout_dest == CTxDestination(PKHash(keyIDVoting))) {
79+
if ((!keyIDOwner.IsNull() && payout_dest == CTxDestination(PKHash(keyIDOwner))) ||
80+
payout_dest == CTxDestination(PKHash(keyIDVoting))) {
8081
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-payee-reuse");
8182
}
8283
}

src/evo/specialtxman.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,11 @@ bool CSpecialTxProcessor::RebuildListFromBlock(const CBlock& block, gsl::not_nul
492492
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-hash");
493493
}
494494
auto newState = std::make_shared<CDeterministicMNState>(*dmn->pdmnState);
495+
const uint16_t old_version{static_cast<uint16_t>(newState->nVersion)};
495496
newState->ResetOperatorFields();
497+
if (old_version >= ProTxVersion::MultiPayout && !SetStateVersion(*newState, old_version, dmn->nType, state)) {
498+
return false;
499+
}
496500
newState->BanIfNotBanned(nHeight);
497501
newState->nRevocationReason = opt_proTx->nReason;
498502

src/test/evo_trivialvalidation.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ BOOST_AUTO_TEST_CASE(multipayout_list_validation)
180180
CheckPayouts({{CScript() << OP_RETURN, 10000}}, owner_id, voting_id, "bad-protx-payee");
181181
CheckPayouts({{GetScriptForDestination(PKHash(owner_id)), 10000}}, owner_id, voting_id, "bad-protx-payee-reuse");
182182
CheckPayouts({{GetScriptForDestination(PKHash(voting_id)), 10000}}, owner_id, voting_id, "bad-protx-payee-reuse");
183+
CheckPayouts({{GetScriptForDestination(PKHash(CKeyID{})), 10000}}, CKeyID{}, voting_id, std::nullopt);
183184

184185
TxValidationState state;
185186
BOOST_CHECK(!IsPayoutListKeySafe({{payout1, 10000}}, CTxDestination(PKHash(payout_key1.GetPubKey().GetID())),

test/functional/feature_masternode_payout_shares.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,18 @@ def shortpay_payout2(coinbase):
216216
assert_equal(payee["amount"], expected_amount)
217217
paid_owner_total += payee["amount"]
218218

219+
node.sendtoaddress(mn.fundsAddr, 1)
220+
self.bump_mocktime(10 * 60 + 1)
221+
self.generate(node, 1, sync_fun=self.no_op)
222+
revoke_hash = mn.revoke(node, submit=True, reason=1, fundsAddr=mn.fundsAddr)
223+
assert revoke_hash is not None
224+
self.bump_mocktime(10 * 60 + 1)
225+
self.generate(node, 1, sync_fun=self.no_op)
226+
227+
info = node.protx("info", protx_hash)
228+
assert_equal(info["state"]["version"], 4)
229+
assert_equal(payout_address_rewards(info["state"]["payouts"]), updated_payouts)
230+
219231

220232
if __name__ == '__main__':
221233
MasternodePayoutSharesTest().main()

0 commit comments

Comments
 (0)