@@ -1957,11 +1957,21 @@ DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockI
19571957 return DISCONNECT_FAILED;
19581958 }
19591959
1960+ // Ignore blocks that contain transactions which are 'overwritten' by later transactions,
1961+ // unless those are already completely spent.
1962+ // See https://github.com/bitcoin/bitcoin/issues/22596 for additional information.
1963+ // Note: the blocks specified here are different than the ones used in ConnectBlock because DisconnectBlock
1964+ // unwinds the blocks in reverse. As a result, the inconsistency is not discovered until the earlier
1965+ // blocks with the duplicate coinbase transactions are disconnected.
1966+ bool fEnforceBIP30 = !((pindex->nHeight ==91722 && pindex->GetBlockHash () == uint256S (" 0x00000000000271a2dc26e7667f8419f2e15416dc6955e5a6c6cdf3f2574dd08e" )) ||
1967+ (pindex->nHeight ==91812 && pindex->GetBlockHash () == uint256S (" 0x00000000000af0aed4792b1acee3d966af36cf5def14935db8de83d6f9306f2f" )));
1968+
19601969 // undo transactions in reverse order
19611970 for (int i = block.vtx .size () - 1 ; i >= 0 ; i--) {
19621971 const CTransaction &tx = *(block.vtx [i]);
19631972 uint256 hash = tx.GetHash ();
19641973 bool is_coinbase = tx.IsCoinBase ();
1974+ bool is_bip30_exception = (is_coinbase && !fEnforceBIP30 );
19651975
19661976 if (fAddressIndex ) {
19671977 for (unsigned int k = tx.vout .size (); k-- > 0 ;) {
@@ -1990,7 +2000,9 @@ DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockI
19902000 Coin coin;
19912001 bool is_spent = view.SpendCoin (out, &coin);
19922002 if (!is_spent || tx.vout [o] != coin.out || pindex->nHeight != coin.nHeight || is_coinbase != coin.fCoinBase ) {
1993- fClean = false ; // transaction output mismatch
2003+ if (!is_bip30_exception) {
2004+ fClean = false ; // transaction output mismatch
2005+ }
19942006 }
19952007 }
19962008 }
0 commit comments