@@ -181,6 +181,28 @@ static CMutableTransaction CreateProUpRegTx(SimpleUTXOMap& utxos, const uint256&
181181 return tx;
182182}
183183
184+ static CMutableTransaction CreateProUpRevTx (SimpleUTXOMap& utxos, const uint256& proTxHash, ProUpRevPL::RevocationReason reason, const CKey& operatorKey, const CKey& coinbaseKey)
185+ {
186+ CAmount change;
187+ auto inputs = SelectUTXOs (utxos, 1 * COIN, change);
188+
189+ ProUpRevPL pl;
190+ pl.proTxHash = proTxHash;
191+ pl.nReason = reason;
192+
193+ CMutableTransaction tx;
194+ tx.nVersion = CTransaction::TxVersion::SAPLING;
195+ tx.nType = CTransaction::TxType::PROUPREV;
196+ const CScript& s = GetScriptForDestination (coinbaseKey.GetPubKey ().GetID ());
197+ FundTransaction (tx, utxos, s, s, 1 * COIN);
198+ pl.inputsHash = CalcTxInputsHash (tx);
199+ BOOST_ASSERT (CHashSigner::SignHash (::SerializeHash (pl), operatorKey, pl.vchSig ));
200+ SetTxPayload (tx, pl);
201+ SignTransaction (tx, coinbaseKey);
202+
203+ return tx;
204+ }
205+
184206static CScript GenerateRandomAddress ()
185207{
186208 CKey key;
@@ -212,6 +234,17 @@ static CMutableTransaction MalleateProUpServTx(const CMutableTransaction& tx)
212234 return tx2;
213235}
214236
237+ static CMutableTransaction MalleateProUpRevTx (const CMutableTransaction& tx)
238+ {
239+ ProUpRevPL pl;
240+ GetTxPayload (tx, pl);
241+ BOOST_ASSERT (pl.nReason != ProUpRevPL::RevocationReason::REASON_CHANGE_OF_KEYS);
242+ pl.nReason = ProUpRevPL::RevocationReason::REASON_CHANGE_OF_KEYS;
243+ CMutableTransaction tx2 = tx;
244+ SetTxPayload (tx2, pl);
245+ return tx2;
246+ }
247+
215248static bool CheckTransactionSignature (const CMutableTransaction& tx)
216249{
217250 for (unsigned int i = 0 ; i < tx.vin .size (); i++) {
@@ -583,7 +616,8 @@ BOOST_FIXTURE_TEST_CASE(dip3_protx, TestChain400Setup)
583616 }
584617
585618 // ProUpReg: change voting key, operator key and payout address
586- { const uint256& proTx = dmnHashes[InsecureRandRange (dmnHashes.size ())]; // pick one at random
619+ {
620+ const uint256& proTx = dmnHashes[InsecureRandRange (dmnHashes.size ())]; // pick one at random
587621 const CKey& new_operatorKey = GetRandomKey ();
588622 const CKey& new_votingKey = GetRandomKey ();
589623 const CScript& new_payee = GenerateRandomAddress ();
@@ -686,6 +720,39 @@ BOOST_FIXTURE_TEST_CASE(dip3_protx, TestChain400Setup)
686720 BOOST_CHECK_EQUAL (chainActive.Height (), nHeight); // bad block not connected
687721 }
688722
723+ // ProUpRev: revoke masternode service
724+ {
725+ const uint256& proTx = dmnHashes[InsecureRandRange (dmnHashes.size ())]; // pick one at random
726+ ProUpRevPL::RevocationReason reason = ProUpRevPL::RevocationReason::REASON_TERMINATION_OF_SERVICE;
727+ // try first with wrong operator key
728+ CValidationState state;
729+ auto tx = CreateProUpRevTx (utxos, proTx, reason, GetRandomKey (), coinbaseKey);
730+ BOOST_CHECK_MESSAGE (!CheckProUpRevTx (tx, chainTip, state), " ProUpReg verifies with wrong owner key" );
731+ BOOST_CHECK_EQUAL (state.GetRejectReason (), " bad-protx-sig" );
732+ // then use the proper key
733+ state = CValidationState ();
734+ tx = CreateProUpRevTx (utxos, proTx, reason, operatorKeys.at (proTx), coinbaseKey);
735+ BOOST_CHECK_MESSAGE (CheckProUpRevTx (tx, chainTip, state), state.GetRejectReason ());
736+ BOOST_CHECK_MESSAGE (CheckTransactionSignature (tx), " ProUpReg signature verification failed" );
737+ // also verify that payloads are not malleable after they have been signed
738+ auto tx2 = MalleateProUpRevTx (tx);
739+ BOOST_CHECK_MESSAGE (!CheckSpecialTx (tx2, chainTip, state), " Malleated ProUpReg accepted" );
740+ BOOST_CHECK_EQUAL (state.GetRejectReason (), " bad-protx-sig" );
741+
742+ CreateAndProcessBlock ({tx}, coinbaseKey);
743+ chainTip = chainActive.Tip ();
744+ BOOST_CHECK_EQUAL (chainTip->nHeight , ++nHeight);
745+
746+ SyncWithValidationInterfaceQueue ();
747+ auto dmn = deterministicMNManager->GetListAtChainTip ().GetMN (proTx);
748+ BOOST_ASSERT (dmn != nullptr );
749+ BOOST_CHECK_MESSAGE (dmn->pdmnState ->keyIDOperator == CKeyID (), " mn operator key not removed" );
750+ BOOST_CHECK_MESSAGE (dmn->pdmnState ->addr == CService (), " mn IP address not removed" );
751+ BOOST_CHECK_MESSAGE (dmn->pdmnState ->scriptOperatorPayout .empty (), " mn operator payout not removed" );
752+ BOOST_CHECK_EQUAL (dmn->pdmnState ->nRevocationReason , reason);
753+ BOOST_CHECK_EQUAL (dmn->pdmnState ->nPoSeBanHeight , nHeight);
754+ }
755+
689756 UpdateNetworkUpgradeParameters (Consensus::UPGRADE_V6_0, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT);
690757}
691758
0 commit comments