diff --git a/src/blockindex.cpp b/src/blockindex.cpp
index 0bb45e117..7a0b1453f 100644
--- a/src/blockindex.cpp
+++ b/src/blockindex.cpp
@@ -1,87 +1,84 @@
 // Copyright (c) 2009-2020 The Bitcoin developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 #include <blockindex.h>
 #include <tinyformat.h>
 
 /**
  * Turn the lowest '1' bit in the binary representation of a number into a '0'.
  */
 static inline int InvertLowestOne(int n) {
     return n & (n - 1);
 }
 
 /** Compute what height to jump back to with the CBlockIndex::pskip pointer. */
 static inline int GetSkipHeight(int height) {
     if (height < 2) {
         return 0;
     }
 
     // Determine which height to jump back to. Any number strictly lower than
     // height is acceptable, but the following expression seems to perform well
     // in simulations (max 110 steps to go back up to 2**18 blocks).
     return (height & 1) ? InvertLowestOne(InvertLowestOne(height - 1)) + 1
                         : InvertLowestOne(height);
 }
 
 std::string CBlockIndex::ToString() const {
     return strprintf(
         "CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)", pprev,
         nHeight, hashMerkleRoot.ToString(), GetBlockHash().ToString());
 }
 
 bool CBlockIndex::UpdateChainStats() {
     if (pprev == nullptr) {
         nChainTx = nTx;
-        nChainSize = nSize;
         return true;
     }
 
     if (pprev->nChainTx > 0) {
         nChainTx = pprev->nChainTx + nTx;
-        nChainSize = pprev->nChainSize + nSize;
         return true;
     }
 
     nChainTx = 0;
-    nChainSize = 0;
     return false;
 }
 
 const CBlockIndex *CBlockIndex::GetAncestor(int height) const {
     if (height > nHeight || height < 0) {
         return nullptr;
     }
 
     const CBlockIndex *pindexWalk = this;
     int heightWalk = nHeight;
     while (heightWalk > height) {
         int heightSkip = GetSkipHeight(heightWalk);
         int heightSkipPrev = GetSkipHeight(heightWalk - 1);
         if (pindexWalk->pskip != nullptr &&
             (heightSkip == height ||
              (heightSkip > height && !(heightSkipPrev < heightSkip - 2 &&
                                        heightSkipPrev >= height)))) {
             // Only follow pskip if pprev->pskip isn't better than pskip->pprev.
             pindexWalk = pindexWalk->pskip;
             heightWalk = heightSkip;
         } else {
             assert(pindexWalk->pprev);
             pindexWalk = pindexWalk->pprev;
             heightWalk--;
         }
     }
     return pindexWalk;
 }
 
 CBlockIndex *CBlockIndex::GetAncestor(int height) {
     return const_cast<CBlockIndex *>(
         const_cast<const CBlockIndex *>(this)->GetAncestor(height));
 }
 
 void CBlockIndex::BuildSkip() {
     if (pprev) {
         pskip = pprev->GetAncestor(GetSkipHeight(nHeight));
     }
 }
diff --git a/src/blockindex.h b/src/blockindex.h
index edc4ff97b..15eb265db 100644
--- a/src/blockindex.h
+++ b/src/blockindex.h
@@ -1,261 +1,249 @@
 // Copyright (c) 2009-2020 The Bitcoin developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 #ifndef BITCOIN_BLOCKINDEX_H
 #define BITCOIN_BLOCKINDEX_H
 
 #include <arith_uint256.h>
 #include <blockstatus.h>
 #include <flatfile.h>
 #include <kernel/cs_main.h>
 #include <primitives/block.h>
 #include <sync.h>
 #include <uint256.h>
 #include <util/time.h>
 
 struct BlockHash;
 
 /**
  * The block chain is a tree shaped structure starting with the genesis block at
  * the root, with each block potentially having multiple candidates to be the
  * next block. A blockindex may have multiple pprev pointing to it, but at most
  * one of them can be part of the currently active branch.
  */
 class CBlockIndex {
 public:
     //! pointer to the hash of the block, if any. Memory is owned by this
     //! CBlockIndex
     const BlockHash *phashBlock{nullptr};
 
     //! pointer to the index of the predecessor of this block
     CBlockIndex *pprev{nullptr};
 
     //! pointer to the index of some further predecessor of this block
     CBlockIndex *pskip{nullptr};
 
     //! height of the entry in the chain. The genesis block has height 0
     int nHeight{0};
 
     //! Which # file this block is stored in (blk?????.dat)
     int nFile GUARDED_BY(::cs_main){0};
 
     //! Byte offset within blk?????.dat where this block's data is stored
     unsigned int nDataPos GUARDED_BY(::cs_main){0};
 
     //! Byte offset within rev?????.dat where this block's undo data is stored
     unsigned int nUndoPos GUARDED_BY(::cs_main){0};
 
     //! (memory only) Total amount of work (expected number of hashes) in the
     //! chain up to and including this block
     arith_uint256 nChainWork{};
 
     //! Number of transactions in this block.
     //! Note: in a potential headers-first mode, this number cannot be relied
     //! upon
     //! Note: this value is faked during UTXO snapshot load to ensure that
     //! LoadBlockIndex() will load index entries for blocks that we lack data
     //! for.
     //! @sa ActivateSnapshot
     unsigned int nTx{0};
 
     //! Size of this block.
     //! Note: in a potential headers-first mode, this number cannot be relied
     //! upon
     unsigned int nSize{0};
 
     //! (memory only) Number of transactions in the chain up to and including
     //! this block.
     //! This value will be non-zero only if and only if transactions for this
     //! block and all its parents are available. Change to 64-bit type when
     //! necessary; won't happen before 2030
     //!
     //! Note: this value is faked during use of a UTXO snapshot because we don't
     //! have the underlying block data available during snapshot load.
     //! @sa AssumeutxoData
     //! @sa ActivateSnapshot
     unsigned int nChainTx{0};
 
-private:
-    //! (memory only) Size of all blocks in the chain up to and including this
-    //! block. This value will be non-zero only if and only if transactions for
-    //! this block and all its parents are available.
-    uint64_t nChainSize{0};
-
-public:
     //! Verification status of this block. See enum BlockStatus
     BlockStatus nStatus GUARDED_BY(::cs_main){};
 
     //! block header
     int32_t nVersion{0};
     uint256 hashMerkleRoot{};
     uint32_t nTime{0};
     uint32_t nBits{0};
     uint32_t nNonce{0};
 
     //! (memory only) Sequential id assigned to distinguish order in which
     //! blocks are received.
     int32_t nSequenceId{0};
 
     //! (memory only) block header metadata
     int64_t nTimeReceived{0};
 
     //! (memory only) Maximum nTime in the chain up to and including this block.
     unsigned int nTimeMax{0};
 
     explicit CBlockIndex() = default;
 
     explicit CBlockIndex(const CBlockHeader &block)
         : nVersion{block.nVersion}, hashMerkleRoot{block.hashMerkleRoot},
           nTime{block.nTime}, nBits{block.nBits}, nNonce{block.nNonce},
           nTimeReceived{0} {}
 
     FlatFilePos GetBlockPos() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
         AssertLockHeld(::cs_main);
         FlatFilePos ret;
         if (nStatus.hasData()) {
             ret.nFile = nFile;
             ret.nPos = nDataPos;
         }
         return ret;
     }
 
     FlatFilePos GetUndoPos() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
         AssertLockHeld(::cs_main);
         FlatFilePos ret;
         if (nStatus.hasUndo()) {
             ret.nFile = nFile;
             ret.nPos = nUndoPos;
         }
         return ret;
     }
 
     CBlockHeader GetBlockHeader() const {
         CBlockHeader block;
         block.nVersion = nVersion;
         if (pprev) {
             block.hashPrevBlock = pprev->GetBlockHash();
         }
         block.hashMerkleRoot = hashMerkleRoot;
         block.nTime = nTime;
         block.nBits = nBits;
         block.nNonce = nNonce;
         return block;
     }
 
     BlockHash GetBlockHash() const {
         assert(phashBlock != nullptr);
         return *phashBlock;
     }
 
     /**
      * Get the number of transaction in the chain so far.
      */
     int64_t GetChainTxCount() const { return nChainTx; }
 
-    /**
-     * Get the size of all the blocks in the chain so far.
-     */
-    uint64_t GetChainSize() const { return nChainSize; }
-
     /**
      * Update chain tx stats.
      */
     bool UpdateChainStats();
 
     /**
      * Check whether this block's and all previous blocks' transactions have
      * been downloaded (and stored to disk) at some point.
      *
      * Does not imply the transactions are consensus-valid (ConnectTip might
      * fail) Does not imply the transactions are still stored on disk.
      * (IsBlockPruned might return true)
      *
      * Note that this will be true for the snapshot base block, if one is
      * loaded (and all subsequent assumed-valid blocks) since its nChainTx
      * value will have been set manually based on the related AssumeutxoData
      * entry.
      */
     bool HaveNumChainTxs() const { return GetChainTxCount() != 0; }
 
     NodeSeconds Time() const {
         return NodeSeconds{std::chrono::seconds{nTime}};
     }
 
     int64_t GetBlockTime() const { return int64_t(nTime); }
 
     int64_t GetBlockTimeMax() const { return int64_t(nTimeMax); }
 
     int64_t GetHeaderReceivedTime() const { return nTimeReceived; }
 
     int64_t GetReceivedTimeDiff() const {
         return GetHeaderReceivedTime() - GetBlockTime();
     }
 
     static constexpr int nMedianTimeSpan = 11;
 
     int64_t GetMedianTimePast() const {
         int64_t pmedian[nMedianTimeSpan];
         int64_t *pbegin = &pmedian[nMedianTimeSpan];
         int64_t *pend = &pmedian[nMedianTimeSpan];
 
         const CBlockIndex *pindex = this;
         for (int i = 0; i < nMedianTimeSpan && pindex;
              i++, pindex = pindex->pprev) {
             *(--pbegin) = pindex->GetBlockTime();
         }
 
         std::sort(pbegin, pend);
         return pbegin[(pend - pbegin) / 2];
     }
 
     std::string ToString() const;
 
     //! Check whether this block index entry is valid up to the passed validity
     //! level.
     bool IsValid(enum BlockValidity nUpTo = BlockValidity::TRANSACTIONS) const
         EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
         AssertLockHeld(::cs_main);
         return nStatus.isValid(nUpTo);
     }
 
     //! @returns true if the block is assumed-valid; this means it is queued
     //! to be validated by a background chainstate.
     bool IsAssumedValid() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
         AssertLockHeld(::cs_main);
         return nStatus.isAssumedValid();
     }
 
     //! Raise the validity level of this block index entry.
     //! Returns true if the validity was changed.
     bool RaiseValidity(enum BlockValidity nUpTo)
         EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
         AssertLockHeld(::cs_main);
         // Only validity flags allowed.
         if (nStatus.isInvalid()) {
             return false;
         }
 
         if (nStatus.getValidity() >= nUpTo) {
             return false;
         }
 
         // If this block had been marked assumed-valid and we're raising
         // its validity to a certain point, there is no longer an assumption.
         if (IsAssumedValid() && nUpTo >= BlockValidity::SCRIPTS) {
             nStatus = nStatus.withClearedAssumedValidFlags();
         }
 
         nStatus = nStatus.withValidity(nUpTo);
         return true;
     }
 
     //! Build the skiplist pointer for this entry.
     void BuildSkip();
 
     //! Efficiently find an ancestor of this block.
     CBlockIndex *GetAncestor(int height);
     const CBlockIndex *GetAncestor(int height) const;
 };
 
 #endif // BITCOIN_BLOCKINDEX_H
diff --git a/src/blockvalidity.h b/src/blockvalidity.h
index cb130866e..8f1551ec6 100644
--- a/src/blockvalidity.h
+++ b/src/blockvalidity.h
@@ -1,50 +1,50 @@
 // Copyright (c) 2018 The Bitcoin developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 #ifndef BITCOIN_BLOCKVALIDITY_H
 #define BITCOIN_BLOCKVALIDITY_H
 
 #include <cstdint>
 
 enum class BlockValidity : uint32_t {
     /**
      * Unused.
      */
     UNKNOWN = 0,
 
     /**
      * Reserved (was HEADER).
      */
     RESERVED = 1,
 
     /**
      * All parent headers found, difficulty matches, timestamp >= median
      * previous, checkpoint. Implies all parents are also at least TREE.
      */
     TREE = 2,
 
     /**
      * Only first tx is coinbase, 2 <= coinbase input script length <= 100,
      * transactions valid, no duplicate txids, size, merkle root.
      * Implies all parents are at least TREE but not necessarily TRANSACTIONS.
-     * When all parent blocks also have TRANSACTIONS, CBlockIndex::nChainTx and
-     * CBlockIndex::nChainSize will be set.
+     * When all parent blocks also have TRANSACTIONS, and CBlockIndex::nChainTx
+     * will be set.
      */
     TRANSACTIONS = 3,
 
     /**
      * Outputs do not overspend inputs, no double spends, coinbase output ok, no
      * immature coinbase spends, BIP30.
      * Implies all parents are at least CHAIN, or are ASSUMED_VALID.
      */
     CHAIN = 4,
 
     /**
      * Scripts & signatures ok. Implies all parents are either at least SCRIPTS,
      * or are ASSUMED_VALID.
      */
     SCRIPTS = 5,
 };
 
 #endif // BITCOIN_BLOCKVALIDITY_H
diff --git a/src/test/fuzz/chain.cpp b/src/test/fuzz/chain.cpp
index 70784108e..5a0db72e1 100644
--- a/src/test/fuzz/chain.cpp
+++ b/src/test/fuzz/chain.cpp
@@ -1,108 +1,107 @@
 // Copyright (c) 2020 The Bitcoin Core developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 #include <chain.h>
 #include <primitives/blockhash.h>
 
 #include <test/fuzz/FuzzedDataProvider.h>
 #include <test/fuzz/fuzz.h>
 #include <test/fuzz/util.h>
 
 #include <cstdint>
 #include <optional>
 #include <vector>
 
 FUZZ_TARGET(chain) {
     FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
     std::optional<CDiskBlockIndex> disk_block_index =
         ConsumeDeserializable<CDiskBlockIndex>(fuzzed_data_provider);
     if (!disk_block_index) {
         return;
     }
 
     const BlockHash zero{};
     disk_block_index->phashBlock = &zero;
     {
         LOCK(::cs_main);
         (void)disk_block_index->ConstructBlockHash();
         (void)disk_block_index->GetBlockPos();
         (void)disk_block_index->GetBlockTime();
         (void)disk_block_index->GetBlockTimeMax();
-        (void)disk_block_index->GetChainSize();
         (void)disk_block_index->GetChainTxCount();
         (void)disk_block_index->GetHeaderReceivedTime();
         (void)disk_block_index->GetMedianTimePast();
         (void)disk_block_index->GetReceivedTimeDiff();
         (void)disk_block_index->GetUndoPos();
         (void)disk_block_index->HaveNumChainTxs();
         (void)disk_block_index->IsValid();
         (void)disk_block_index->UpdateChainStats();
     }
 
     const CBlockHeader block_header = disk_block_index->GetBlockHeader();
     (void)CDiskBlockIndex{*disk_block_index};
     (void)disk_block_index->BuildSkip();
 
     while (fuzzed_data_provider.ConsumeBool()) {
         const BlockValidity block_validity =
             fuzzed_data_provider.PickValueInArray({
                 BlockValidity::UNKNOWN,
                 BlockValidity::RESERVED,
                 BlockValidity::TREE,
                 BlockValidity::TRANSACTIONS,
                 BlockValidity::CHAIN,
                 BlockValidity::SCRIPTS,
             });
         const BlockStatus base;
         bool has_data = fuzzed_data_provider.ConsumeBool();
         bool has_undo = fuzzed_data_provider.ConsumeBool();
         bool has_failed = fuzzed_data_provider.ConsumeBool();
         bool has_failed_parent = fuzzed_data_provider.ConsumeBool();
         bool is_parked = fuzzed_data_provider.ConsumeBool();
         bool has_parked_parent = fuzzed_data_provider.ConsumeBool();
         bool is_assumed_valid = fuzzed_data_provider.ConsumeBool();
         const BlockStatus block_status =
             base.withValidity(block_validity)
                 .withData(has_data)
                 .withUndo(has_undo)
                 .withFailed(has_failed)
                 .withFailedParent(has_failed_parent)
                 .withParked(is_parked)
                 .withParkedParent(has_parked_parent)
                 .withAssumedValid(is_assumed_valid);
 
         assert(block_status.hasData() == has_data);
         assert(block_status.hasUndo() == has_undo);
         assert(block_status.hasFailed() == has_failed);
         assert(block_status.hasFailedParent() == has_failed_parent);
         assert(block_status.isParked() == is_parked);
         assert(block_status.hasParkedParent() == has_parked_parent);
         assert(block_status.isAssumedValid() == is_assumed_valid);
 
         assert(block_status.isInvalid() == has_failed || has_failed_parent);
         const BlockStatus valid_block = block_status.withClearedFailureFlags();
         assert(!valid_block.isInvalid());
 
         assert(block_status.isOnParkedChain() == is_parked ||
                has_parked_parent);
         const BlockStatus unparked_block =
             block_status.withClearedParkedFlags();
         assert(!unparked_block.isOnParkedChain());
 
         const BlockStatus unassumed_valid_block =
             block_status.withClearedAssumedValidFlags();
         assert(!unassumed_valid_block.isAssumedValid());
 
         if (!block_status.isValid()) {
             continue;
         }
         WITH_LOCK(::cs_main,
                   (void)disk_block_index->RaiseValidity(block_validity));
     }
 
     CBlockIndex block_index{block_header};
     block_index.phashBlock = &zero;
     (void)block_index.GetBlockHash();
     (void)block_index.ToString();
 }