mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 20:12:57 +01:00
Remove ProTxs from mempool that refer to a ProRegTx for which the collateral was spent (#2539)
* Track TXs in mempool which refer to an existing ProTx * When a block is added, remove TXs that refer to ProTxs with spent collaterals * Initalize evoDb and deterministicMNManager in BasicTestingSetup instead of TestingSetup. Now that the mempool uses deterministicMNManager, we need to initialize it for all tests that might use the mempool.
This commit is contained in:
parent
cbd0303529
commit
511dc3714c
@ -50,11 +50,16 @@ BasicTestingSetup::BasicTestingSetup(const std::string& chainName)
|
|||||||
fPrintToDebugLog = false; // don't want to write to debug.log file
|
fPrintToDebugLog = false; // don't want to write to debug.log file
|
||||||
fCheckBlockIndex = true;
|
fCheckBlockIndex = true;
|
||||||
SelectParams(chainName);
|
SelectParams(chainName);
|
||||||
|
evoDb = new CEvoDB(1 << 20, true, true);
|
||||||
|
deterministicMNManager = new CDeterministicMNManager(*evoDb);
|
||||||
noui_connect();
|
noui_connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicTestingSetup::~BasicTestingSetup()
|
BasicTestingSetup::~BasicTestingSetup()
|
||||||
{
|
{
|
||||||
|
delete deterministicMNManager;
|
||||||
|
delete evoDb;
|
||||||
|
|
||||||
ECC_Stop();
|
ECC_Stop();
|
||||||
g_connman.reset();
|
g_connman.reset();
|
||||||
}
|
}
|
||||||
@ -70,10 +75,8 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha
|
|||||||
boost::filesystem::create_directories(pathTemp);
|
boost::filesystem::create_directories(pathTemp);
|
||||||
ForceSetArg("-datadir", pathTemp.string());
|
ForceSetArg("-datadir", pathTemp.string());
|
||||||
mempool.setSanityCheck(1.0);
|
mempool.setSanityCheck(1.0);
|
||||||
evoDb = new CEvoDB(1 << 20, true, true);
|
|
||||||
pblocktree = new CBlockTreeDB(1 << 20, true);
|
pblocktree = new CBlockTreeDB(1 << 20, true);
|
||||||
pcoinsdbview = new CCoinsViewDB(1 << 23, true);
|
pcoinsdbview = new CCoinsViewDB(1 << 23, true);
|
||||||
deterministicMNManager = new CDeterministicMNManager(*evoDb);
|
|
||||||
llmq::InitLLMQSystem(*evoDb);
|
llmq::InitLLMQSystem(*evoDb);
|
||||||
pcoinsTip = new CCoinsViewCache(pcoinsdbview);
|
pcoinsTip = new CCoinsViewCache(pcoinsdbview);
|
||||||
InitBlockIndex(chainparams);
|
InitBlockIndex(chainparams);
|
||||||
@ -98,10 +101,8 @@ TestingSetup::~TestingSetup()
|
|||||||
UnloadBlockIndex();
|
UnloadBlockIndex();
|
||||||
delete pcoinsTip;
|
delete pcoinsTip;
|
||||||
llmq::DestroyLLMQSystem();
|
llmq::DestroyLLMQSystem();
|
||||||
delete deterministicMNManager;
|
|
||||||
delete pcoinsdbview;
|
delete pcoinsdbview;
|
||||||
delete pblocktree;
|
delete pblocktree;
|
||||||
delete evoDb;
|
|
||||||
boost::filesystem::remove_all(pathTemp);
|
boost::filesystem::remove_all(pathTemp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -447,6 +447,9 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry,
|
|||||||
LogPrintf("%s: ERROR: Invalid transaction payload, tx: %s", __func__, tx.ToString());
|
LogPrintf("%s: ERROR: Invalid transaction payload, tx: %s", __func__, tx.ToString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!proTx.collateralOutpoint.hash.IsNull()) {
|
||||||
|
mapProTxRefs.emplace(tx.GetHash(), proTx.collateralOutpoint.hash);
|
||||||
|
}
|
||||||
mapProTxAddresses.emplace(proTx.addr, tx.GetHash());
|
mapProTxAddresses.emplace(proTx.addr, tx.GetHash());
|
||||||
mapProTxPubKeyIDs.emplace(proTx.keyIDOwner, tx.GetHash());
|
mapProTxPubKeyIDs.emplace(proTx.keyIDOwner, tx.GetHash());
|
||||||
mapProTxBlsPubKeyHashes.emplace(proTx.pubKeyOperator.GetHash(), tx.GetHash());
|
mapProTxBlsPubKeyHashes.emplace(proTx.pubKeyOperator.GetHash(), tx.GetHash());
|
||||||
@ -459,6 +462,7 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry,
|
|||||||
LogPrintf("%s: ERROR: Invalid transaction payload, tx: %s", __func__, tx.ToString());
|
LogPrintf("%s: ERROR: Invalid transaction payload, tx: %s", __func__, tx.ToString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
mapProTxRefs.emplace(proTx.proTxHash, tx.GetHash());
|
||||||
mapProTxAddresses.emplace(proTx.addr, tx.GetHash());
|
mapProTxAddresses.emplace(proTx.addr, tx.GetHash());
|
||||||
} else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REGISTRAR) {
|
} else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REGISTRAR) {
|
||||||
CProUpRegTx proTx;
|
CProUpRegTx proTx;
|
||||||
@ -466,7 +470,15 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry,
|
|||||||
LogPrintf("%s: ERROR: Invalid transaction payload, tx: %s", __func__, tx.ToString());
|
LogPrintf("%s: ERROR: Invalid transaction payload, tx: %s", __func__, tx.ToString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
mapProTxRefs.emplace(proTx.proTxHash, tx.GetHash());
|
||||||
mapProTxBlsPubKeyHashes.emplace(proTx.pubKeyOperator.GetHash(), tx.GetHash());
|
mapProTxBlsPubKeyHashes.emplace(proTx.pubKeyOperator.GetHash(), tx.GetHash());
|
||||||
|
} else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REVOKE) {
|
||||||
|
CProUpRevTx proTx;
|
||||||
|
if (!GetTxPayload(tx, proTx)) {
|
||||||
|
LogPrintf("%s: ERROR: Invalid transaction payload, tx: %s", __func__, tx.ToString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
mapProTxRefs.emplace(proTx.proTxHash, tx.GetHash());
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -644,11 +656,25 @@ void CTxMemPool::removeUnchecked(txiter it, MemPoolRemovalReason reason)
|
|||||||
} else
|
} else
|
||||||
vTxHashes.clear();
|
vTxHashes.clear();
|
||||||
|
|
||||||
|
auto eraseProTxRef = [&](const uint256& proTxHash, const uint256& txHash) {
|
||||||
|
auto its = mapProTxRefs.equal_range(proTxHash);
|
||||||
|
for (auto it = its.first; it != its.second;) {
|
||||||
|
if (it->second == txHash) {
|
||||||
|
it = mapProTxRefs.erase(it);
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (it->GetTx().nType == TRANSACTION_PROVIDER_REGISTER) {
|
if (it->GetTx().nType == TRANSACTION_PROVIDER_REGISTER) {
|
||||||
CProRegTx proTx;
|
CProRegTx proTx;
|
||||||
if (!GetTxPayload(it->GetTx(), proTx)) {
|
if (!GetTxPayload(it->GetTx(), proTx)) {
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
if (!proTx.collateralOutpoint.IsNull()) {
|
||||||
|
eraseProTxRef(it->GetTx().GetHash(), proTx.collateralOutpoint.hash);
|
||||||
|
}
|
||||||
mapProTxAddresses.erase(proTx.addr);
|
mapProTxAddresses.erase(proTx.addr);
|
||||||
mapProTxPubKeyIDs.erase(proTx.keyIDOwner);
|
mapProTxPubKeyIDs.erase(proTx.keyIDOwner);
|
||||||
mapProTxBlsPubKeyHashes.erase(proTx.pubKeyOperator.GetHash());
|
mapProTxBlsPubKeyHashes.erase(proTx.pubKeyOperator.GetHash());
|
||||||
@ -658,13 +684,21 @@ void CTxMemPool::removeUnchecked(txiter it, MemPoolRemovalReason reason)
|
|||||||
if (!GetTxPayload(it->GetTx(), proTx)) {
|
if (!GetTxPayload(it->GetTx(), proTx)) {
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
eraseProTxRef(proTx.proTxHash, it->GetTx().GetHash());
|
||||||
mapProTxAddresses.erase(proTx.addr);
|
mapProTxAddresses.erase(proTx.addr);
|
||||||
} else if (it->GetTx().nType == TRANSACTION_PROVIDER_UPDATE_REGISTRAR) {
|
} else if (it->GetTx().nType == TRANSACTION_PROVIDER_UPDATE_REGISTRAR) {
|
||||||
CProUpRegTx proTx;
|
CProUpRegTx proTx;
|
||||||
if (!GetTxPayload(it->GetTx(), proTx)) {
|
if (!GetTxPayload(it->GetTx(), proTx)) {
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
eraseProTxRef(proTx.proTxHash, it->GetTx().GetHash());
|
||||||
mapProTxBlsPubKeyHashes.erase(proTx.pubKeyOperator.GetHash());
|
mapProTxBlsPubKeyHashes.erase(proTx.pubKeyOperator.GetHash());
|
||||||
|
} else if (it->GetTx().nType == TRANSACTION_PROVIDER_UPDATE_REVOKE) {
|
||||||
|
CProUpRevTx proTx;
|
||||||
|
if (!GetTxPayload(it->GetTx(), proTx)) {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
eraseProTxRef(proTx.proTxHash, it->GetTx().GetHash());
|
||||||
}
|
}
|
||||||
|
|
||||||
totalTxSize -= it->GetTxSize();
|
totalTxSize -= it->GetTxSize();
|
||||||
@ -823,8 +857,46 @@ void CTxMemPool::removeProTxCollateralConflicts(const CTransaction &tx, const CO
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CTxMemPool::removeProTxSpentCollateralConflicts(const CTransaction &tx)
|
||||||
|
{
|
||||||
|
// Remove TXs that refer to a MN for which the collateral was spent
|
||||||
|
auto removeSpentCollateralConflict = [&](const uint256& proTxHash) {
|
||||||
|
// Can't use equal_range here as every call to removeRecursive might invalidate iterators
|
||||||
|
while (true) {
|
||||||
|
auto it = mapProTxRefs.find(proTxHash);
|
||||||
|
if (it == mapProTxRefs.end()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
auto conflictIt = mapTx.find(it->second);
|
||||||
|
if (conflictIt != mapTx.end()) {
|
||||||
|
removeRecursive(conflictIt->GetTx(), MemPoolRemovalReason::CONFLICT);
|
||||||
|
} else {
|
||||||
|
// Should not happen as we track referencing TXs in addUnchecked/removeUnchecked.
|
||||||
|
// But lets be on the safe side and not run into an endless loop...
|
||||||
|
LogPrintf("%s: ERROR: found invalid TX ref in mapProTxRefs, proTxHash=%s, txHash=%s", __func__, proTxHash.ToString(), it->second.ToString());
|
||||||
|
mapProTxRefs.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||||
|
for (const auto& in : tx.vin) {
|
||||||
|
auto collateralIt = mapProTxCollaterals.find(in.prevout);
|
||||||
|
if (collateralIt != mapProTxCollaterals.end()) {
|
||||||
|
// These are not yet mined ProRegTxs
|
||||||
|
removeSpentCollateralConflict(collateralIt->second);
|
||||||
|
}
|
||||||
|
auto dmn = mnList.GetMNByCollateral(in.prevout);
|
||||||
|
if (dmn) {
|
||||||
|
// These are updates refering to a mined ProRegTx
|
||||||
|
removeSpentCollateralConflict(dmn->proTxHash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CTxMemPool::removeProTxConflicts(const CTransaction &tx)
|
void CTxMemPool::removeProTxConflicts(const CTransaction &tx)
|
||||||
{
|
{
|
||||||
|
removeProTxSpentCollateralConflicts(tx);
|
||||||
|
|
||||||
if (tx.nType == TRANSACTION_PROVIDER_REGISTER) {
|
if (tx.nType == TRANSACTION_PROVIDER_REGISTER) {
|
||||||
CProRegTx proTx;
|
CProRegTx proTx;
|
||||||
if (!GetTxPayload(tx, proTx)) {
|
if (!GetTxPayload(tx, proTx)) {
|
||||||
|
@ -534,6 +534,7 @@ private:
|
|||||||
typedef std::map<uint256, std::vector<CSpentIndexKey> > mapSpentIndexInserted;
|
typedef std::map<uint256, std::vector<CSpentIndexKey> > mapSpentIndexInserted;
|
||||||
mapSpentIndexInserted mapSpentInserted;
|
mapSpentIndexInserted mapSpentInserted;
|
||||||
|
|
||||||
|
std::multimap<uint256, uint256> mapProTxRefs; // proTxHash -> transaction (all TXs that refer to an existing proTx)
|
||||||
std::map<CService, uint256> mapProTxAddresses;
|
std::map<CService, uint256> mapProTxAddresses;
|
||||||
std::map<CKeyID, uint256> mapProTxPubKeyIDs;
|
std::map<CKeyID, uint256> mapProTxPubKeyIDs;
|
||||||
std::map<uint256, uint256> mapProTxBlsPubKeyHashes;
|
std::map<uint256, uint256> mapProTxBlsPubKeyHashes;
|
||||||
@ -584,6 +585,7 @@ public:
|
|||||||
void removeProTxPubKeyConflicts(const CTransaction &tx, const CKeyID &keyId);
|
void removeProTxPubKeyConflicts(const CTransaction &tx, const CKeyID &keyId);
|
||||||
void removeProTxPubKeyConflicts(const CTransaction &tx, const CBLSPublicKey &pubKey);
|
void removeProTxPubKeyConflicts(const CTransaction &tx, const CBLSPublicKey &pubKey);
|
||||||
void removeProTxCollateralConflicts(const CTransaction &tx, const COutPoint &collateralOutpoint);
|
void removeProTxCollateralConflicts(const CTransaction &tx, const COutPoint &collateralOutpoint);
|
||||||
|
void removeProTxSpentCollateralConflicts(const CTransaction &tx);
|
||||||
void removeProTxConflicts(const CTransaction &tx);
|
void removeProTxConflicts(const CTransaction &tx);
|
||||||
void removeForBlock(const std::vector<CTransactionRef>& vtx, unsigned int nBlockHeight);
|
void removeForBlock(const std::vector<CTransactionRef>& vtx, unsigned int nBlockHeight);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user