-
Notifications
You must be signed in to change notification settings - Fork 1.2k
fix: exempt a MN's own ProRegTx from collateral-reuse mempool conflicts #7638
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1431,6 +1431,16 @@ bool CTxMemPool::existsProviderTxConflict(const CTransaction &tx) const { | |
| return false; | ||
| }; | ||
|
|
||
| // A pending ProRegTx claiming a live MN's collateral replaces (deletes) that MN when | ||
| // mined, so an update targeting the MN could never be mined afterwards. The MN's own | ||
| // ProRegTx (same hash, e.g. resubmitted while a reorg is being processed) replaces | ||
| // nothing and is not a conflict. | ||
| auto collateralReusedInMempool = [&](const CDeterministicMN& dmn) EXCLUSIVE_LOCKS_REQUIRED(cs) { | ||
| AssertLockHeld(cs); | ||
| auto it = mapProTxCollaterals.find(dmn.collateralOutpoint); | ||
| return it != mapProTxCollaterals.end() && it->second != dmn.proTxHash; | ||
| }; | ||
|
|
||
| const uint256 tx_hash{tx.GetHash()}; | ||
| if (tx.nType == TRANSACTION_PROVIDER_REGISTER) { | ||
| const auto opt_proTx = GetTxPayload<CProRegTx>(tx); | ||
|
|
@@ -1462,10 +1472,12 @@ bool CTxMemPool::existsProviderTxConflict(const CTransaction &tx) const { | |
| // A replacement ProRegTx deletes the live MN backed by this collateral. Any | ||
| // in-mempool update that still targets that MN's proTxHash would then fail | ||
| // BuildNewListFromBlock with bad-protx-hash if both were mined in one block. | ||
| if (auto dmn = m_dmnman.GetListAtChainTip().GetMNByCollateral(proTx.collateralOutpoint)) { | ||
| if (mapProTxRefs.find(dmn->proTxHash) != mapProTxRefs.end()) { | ||
| return true; | ||
| } | ||
| // Exempt the MN's own registration: while a reorg is being processed the tip | ||
| // list can still contain the MN whose ProRegTx is being resubmitted, and | ||
| // re-registering the same MN replaces nothing. | ||
| if (auto dmn = m_dmnman.GetListAtChainTip().GetMNByCollateral(proTx.collateralOutpoint); | ||
| dmn && dmn->proTxHash != tx_hash && mapProTxRefs.count(dmn->proTxHash)) { | ||
|
Comment on lines
+1478
to
+1479
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When the pending update is a AGENTS.md reference: AGENTS.md:L193-L211 Useful? React with 👍 / 👎.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct observation, but it is a different, pre-existing check: 🤖 Posted autonomously by Claude on behalf of pasta.
Comment on lines
+1478
to
+1479
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When the pending transaction is a AGENTS.md reference: AGENTS.md:L198-L211 Useful? React with 👍 / 👎. |
||
| return true; | ||
| } | ||
| } | ||
| return false; | ||
|
|
@@ -1487,11 +1499,8 @@ bool CTxMemPool::existsProviderTxConflict(const CTransaction &tx) const { | |
| return true; | ||
| } | ||
| } | ||
| // Conflict with a replacement ProRegTx that reuses this MN's external collateral. | ||
| if (auto dmn = m_dmnman.GetListAtChainTip().GetMN(opt_proTx->proTxHash)) { | ||
| if (mapProTxCollaterals.count(dmn->collateralOutpoint)) { | ||
| return true; | ||
| } | ||
| if (auto dmn = m_dmnman.GetListAtChainTip().GetMN(opt_proTx->proTxHash); dmn && collateralReusedInMempool(*dmn)) { | ||
| return true; | ||
| } | ||
| } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REGISTRAR) { | ||
| const auto opt_proTx = GetTxPayload<CProUpRegTx>(tx); | ||
|
|
@@ -1507,8 +1516,7 @@ bool CTxMemPool::existsProviderTxConflict(const CTransaction &tx) const { | |
| LogPrint(BCLog::MEMPOOL, "%s: ERROR: Masternode is not in the list, proTxHash: %s\n", __func__, proTx.proTxHash.ToString()); | ||
| return true; // i.e. failed to find validated ProTx == conflict | ||
| } | ||
| // Conflict with a replacement ProRegTx that reuses this MN's external collateral. | ||
| if (mapProTxCollaterals.count(dmn->collateralOutpoint)) { | ||
| if (collateralReusedInMempool(*dmn)) { | ||
| return true; | ||
| } | ||
| // only allow one operator key change in the mempool | ||
|
|
@@ -1533,8 +1541,7 @@ bool CTxMemPool::existsProviderTxConflict(const CTransaction &tx) const { | |
| LogPrint(BCLog::MEMPOOL, "%s: ERROR: Masternode is not in the list, proTxHash: %s\n", __func__, proTx.proTxHash.ToString()); | ||
| return true; // i.e. failed to find validated ProTx == conflict | ||
| } | ||
| // Conflict with a replacement ProRegTx that reuses this MN's external collateral. | ||
| if (mapProTxCollaterals.count(dmn->collateralOutpoint)) { | ||
| if (collateralReusedInMempool(*dmn)) { | ||
| return true; | ||
| } | ||
| // only allow one operator key change in the mempool | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.