@@ -2259,15 +2259,17 @@ bool FatalError(Notifications& notifications, BlockValidationState& state, const
22592259 * @param undo The Coin to be restored.
22602260 * @param view The coins view to which to apply the changes.
22612261 * @param out The out point that corresponds to the tx input.
2262+ * @param genesisTxid The genesis coinbase transaction id which lacks undo metadata.
22622263 * @return A DisconnectResult as an int
22632264 */
2264- int ApplyTxInUndo (Coin&& undo, CCoinsViewCache& view, const COutPoint& out)
2265+ int ApplyTxInUndo (Coin&& undo, CCoinsViewCache& view, const COutPoint& out, const uint256& genesisTxid = uint256::ZERO )
22652266{
22662267 bool fClean = true ;
22672268
22682269 if (view.HaveCoin (out)) fClean = false ; // overwriting transaction output
22692270
2270- if (undo.nHeight == 0 ) {
2271+ // We have to exclude the genesis coinbase from this check because its height actually is zero and the wallet will think there is database corruption otherwise
2272+ if (undo.nHeight == 0 && out.hash != genesisTxid) {
22712273 // Missing undo metadata (height and coinbase). Older versions included this
22722274 // information only in undo records for the last spend of a transactions'
22732275 // outputs. This implies that it must be present for some other output of the same tx.
@@ -2348,7 +2350,7 @@ DisconnectResult Chainstate::DisconnectBlock(const CBlock& block, const CBlockIn
23482350 for (unsigned int j = tx.vin .size (); j > 0 ;) {
23492351 --j;
23502352 const COutPoint& out = tx.vin [j].prevout ;
2351- int res = ApplyTxInUndo (std::move (txundo.vprevout [j]), view, out);
2353+ int res = ApplyTxInUndo (std::move (txundo.vprevout [j]), view, out, m_chainman. GetParams (). GenesisBlock (). hashMerkleRoot );
23522354 if (res == DISCONNECT_FAILED) return DISCONNECT_FAILED;
23532355 fClean = fClean && res != DISCONNECT_UNCLEAN;
23542356 }
@@ -2476,14 +2478,6 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
24762478
24772479 m_chainman.num_blocks_total ++;
24782480
2479- // Special case for the genesis block, skipping connection of its transactions
2480- // (its coinbase is unspendable)
2481- if (block_hash == params.GetConsensus ().hashGenesisBlock ) {
2482- if (!fJustCheck )
2483- view.SetBestBlock (pindex->GetBlockHash ());
2484- return true ;
2485- }
2486-
24872481 bool fScriptChecks = true ;
24882482 if (!m_chainman.AssumedValidBlock ().IsNull ()) {
24892483 // We've been configured with the hash of a block which has been externally verified to have a valid history.
@@ -2560,7 +2554,7 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
25602554 // future consensus change to do a new and improved version of BIP34 that
25612555 // will actually prevent ever creating any duplicate coinbases in the
25622556 // future.
2563- static constexpr int BIP34_IMPLIES_BIP30_LIMIT = 1983702 ;
2557+ static constexpr int BIP34_IMPLIES_BIP30_LIMIT = std::numeric_limits< int >:: max () ;
25642558
25652559 // There is no potential to create a duplicate coinbase at block 209,921
25662560 // because this is still before the BIP34 height and so explicit BIP30
@@ -2589,8 +2583,13 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
25892583 // testnet3 has no blocks before the BIP34 height with indicated heights
25902584 // post BIP34 before approximately height 486,000,000. After block
25912585 // 1,983,702 testnet3 starts doing unnecessary BIP30 checking again.
2592- assert (pindex->pprev );
2593- CBlockIndex* pindexBIP34height = pindex->pprev ->GetAncestor (params.GetConsensus ().BIP34Height );
2586+ CBlockIndex* pindexBIP34height = nullptr ;
2587+ if (pindex->GetBlockHash () != params.GetConsensus ().hashGenesisBlock ) {
2588+ assert (pindex->pprev );
2589+ pindexBIP34height = pindex->pprev ->GetAncestor (params.GetConsensus ().BIP34Height );
2590+ } else {
2591+ fEnforceBIP30 = false ;
2592+ }
25942593 // Only continue to enforce if we're below BIP34 activation height or the block hash at that height doesn't correspond.
25952594 fEnforceBIP30 = fEnforceBIP30 && (!pindexBIP34height || !(pindexBIP34height->GetBlockHash () == params.GetConsensus ().BIP34Hash ));
25962595
@@ -2743,7 +2742,7 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
27432742 return true ;
27442743 }
27452744
2746- if (!m_blockman.WriteBlockUndo (blockundo, state, *pindex)) {
2745+ if (pindex-> GetBlockHash () != params. GetConsensus (). hashGenesisBlock && !m_blockman.WriteBlockUndo (blockundo, state, *pindex)) {
27472746 return false ;
27482747 }
27492748
0 commit comments