diff --git a/configure.ac b/configure.ac index 65826aeb4c..f0de25f903 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 0) define(_CLIENT_VERSION_MINOR, 14) define(_CLIENT_VERSION_REVISION, 9) -define(_CLIENT_VERSION_BUILD, 2) +define(_CLIENT_VERSION_BUILD, 3) define(_CLIENT_VERSION_IS_RELEASE, true) define(_COPYRIGHT_YEAR, 2022) define(_COPYRIGHT_HOLDERS,[The %s developers]) diff --git a/src/clientversion.h b/src/clientversion.h index 271cb68887..47b943efd0 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -17,7 +17,7 @@ #define CLIENT_VERSION_MAJOR 0 #define CLIENT_VERSION_MINOR 14 #define CLIENT_VERSION_REVISION 9 -#define CLIENT_VERSION_BUILD 2 +#define CLIENT_VERSION_BUILD 3 //! Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index 1f5111681c..c9d9e519b3 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -839,6 +839,10 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C for (const auto& in : tx.vin) { auto dmn = newList.GetMNByCollateral(in.prevout); if (dmn && dmn->collateralOutpoint == in.prevout) { + // can't spend collateral funded by proreg tx in the same block + if (dmn->pdmnState && dmn->collateralOutpoint.hash == dmn->proTxHash && dmn->pdmnState->nRegisteredHeight == nHeight) + return _state.DoS(100, false, REJECT_CONFLICT, "bad-protx-collateral-spend"); + newList.RemoveMN(dmn->proTxHash); if (debugLogs) { diff --git a/src/miner.cpp b/src/miner.cpp index 15e8731ee8..89c5d57e93 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -904,12 +904,27 @@ void BlockAssembler::FillBlackListForBlockTemplate() { if (tx.nVersion >= 3 && tx.nType == TRANSACTION_PROVIDER_REGISTER) { CProRegTx proTx; - if (GetTxPayload(tx, proTx) && !proTx.collateralOutpoint.hash.IsNull() && - // ProRegTx referencing external collateral can't be in same block with the collateral itself - (mempool.get(proTx.collateralOutpoint.hash) || - // ProRegTx cannot be in the same block as transaction spending external collateral - mempool.isSpent(proTx.collateralOutpoint))) - mempool.CalculateDescendants(mi, txBlackList); + if (GetTxPayload(tx, proTx)) { + if (!proTx.collateralOutpoint.hash.IsNull()) { + if ( + // ProRegTx referencing external collateral can't be in same block with the collateral itself + mempool.get(proTx.collateralOutpoint.hash) || + // ProRegTx cannot be in the same block as transaction spending external collateral + mempool.isSpent(proTx.collateralOutpoint)) + mempool.CalculateDescendants(mi, txBlackList); + } + else { + COutPoint fundedCollateral(mi->GetTx().GetHash(), proTx.collateralOutpoint.n); + if (mempool.isSpent(fundedCollateral)) { + // Transaction spending collateral funded by ProRegTx cannot be in the same block + // We need to blacklist spending tx otherwise two transactions will stuck in the mempool forever. + // Easiest way to do it is to block all the descendants (spending transaction is technically a + // descendant here) but let the ProRegTx into the block. + mempool.CalculateDescendants(mi, txBlackList); + txBlackList.erase(mi); + } + } + } } if (tx.nVersion >= 3 && tx.nType == TRANSACTION_SPORK) {