Skip to content
Merged
14 changes: 13 additions & 1 deletion src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1957,11 +1957,21 @@ DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockI
return DISCONNECT_FAILED;
}

// Ignore blocks that contain transactions which are 'overwritten' by later transactions,
// unless those are already completely spent.
// See https://github.com/bitcoin/bitcoin/issues/22596 for additional information.
// Note: the blocks specified here are different than the ones used in ConnectBlock because DisconnectBlock
// unwinds the blocks in reverse. As a result, the inconsistency is not discovered until the earlier
// blocks with the duplicate coinbase transactions are disconnected.
bool fEnforceBIP30 = !((pindex->nHeight==91722 && pindex->GetBlockHash() == uint256S("0x00000000000271a2dc26e7667f8419f2e15416dc6955e5a6c6cdf3f2574dd08e")) ||

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: these hard-coded blocks should not be backported IMO

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@UdjinM6 said we may as well backport them

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the reindex fails -> need to backport that specific blocks which fails. If re-index doesn't fail -> no need to backport any exception

(pindex->nHeight==91812 && pindex->GetBlockHash() == uint256S("0x00000000000af0aed4792b1acee3d966af36cf5def14935db8de83d6f9306f2f")));

// undo transactions in reverse order
for (int i = block.vtx.size() - 1; i >= 0; i--) {
const CTransaction &tx = *(block.vtx[i]);
uint256 hash = tx.GetHash();
bool is_coinbase = tx.IsCoinBase();
bool is_bip30_exception = (is_coinbase && !fEnforceBIP30);

if (fAddressIndex) {
for (unsigned int k = tx.vout.size(); k-- > 0;) {
Expand Down Expand Up @@ -1990,7 +2000,9 @@ DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockI
Coin coin;
bool is_spent = view.SpendCoin(out, &coin);
if (!is_spent || tx.vout[o] != coin.out || pindex->nHeight != coin.nHeight || is_coinbase != coin.fCoinBase) {
fClean = false; // transaction output mismatch
if (!is_bip30_exception) {
fClean = false; // transaction output mismatch
}
}
}
}
Expand Down