text:
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2021 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_VALIDATION_H
#define BITCOIN_VALIDATION_H

#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h>
#endif

#include <arith_uint256.h>
#include <attributes.h>
#include <chain.h>
#include <chainparams.h>
#include <kernel/chainstatemanager_opts.h>
#include <consensus/amount.h>
#include <deploymentstatus.h>
#include <fs.h>
#include <node/blockstorage.h>
#include <policy/feerate.h>
#include <policy/packages.h>
#include <script/script_error.h>
#include <sync.h>
#include <txdb.h>
#include <txmempool.h> // For CTxMemPool::cs
#include <uint256.h>
#include <util/check.h>
#include <util/hasher.h>
#include <util/translation.h>
#include <versionbits.h>

#include <atomic>
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <stdint.h>
#include <string>
#include <thread>
#include <utility>
#include <vector>

class CChainState;
class CBlockTreeDB;
class CTxMemPool;
class ChainstateManager;
struct ChainTxData;
struct DisconnectedBlockTransactions;
struct PrecomputedTransactionData;
struct LockPoints;
struct AssumeutxoData;
namespace node {
class SnapshotMetadata;
} // namespace node
namespace Consensus {
struct Params;
} // namespace Consensus

/** Default for -minrelaytxfee, minimum relay fee for transactions */
static const unsigned int DEFAULT_MIN_RELAY_TX_FEE = 1000;
/** Default for -limitancestorcount, max number of in-mempool ancestors */
static const unsigned int DEFAULT_ANCESTOR_LIMIT = 25;
/** Default for -limitancestorsize, maximum kilobytes of tx + all in-mempool ancestors */
static const unsigned int DEFAULT_ANCESTOR_SIZE_LIMIT = 101;
/** Default for -limitdescendantcount, max number of in-mempool descendants */
static const unsigned int DEFAULT_DESCENDANT_LIMIT = 25;
/** Default for -limitdescendantsize, maximum kilobytes of in-mempool descendants */
static const unsigned int DEFAULT_DESCENDANT_SIZE_LIMIT = 101;

// If a package is submitted, it must be within the mempool's ancestor/descendant limits. Since a
// submitted package must be child-with-unconfirmed-parents (all of the transactions are an ancestor
// of the child), package limits are ultimately bounded by mempool package limits. Ensure that the
// defaults reflect this constraint.
static_assert(DEFAULT_DESCENDANT_LIMIT >= MAX_PACKAGE_COUNT);
static_assert(DEFAULT_ANCESTOR_LIMIT >= MAX_PACKAGE_COUNT);
static_assert(DEFAULT_ANCESTOR_SIZE_LIMIT >= MAX_PACKAGE_SIZE);
static_assert(DEFAULT_DESCENDANT_SIZE_LIMIT >= MAX_PACKAGE_SIZE);

/** Default for -mempoolexpiry, expiration time for mempool transactions in hours */
static const unsigned int DEFAULT_MEMPOOL_EXPIRY = 336;
/** Maximum number of dedicated script-checking threads allowed */
static const int MAX_SCRIPTCHECK_THREADS = 15;
/** -par default (number of script-checking threads, 0 = auto) */
static const int DEFAULT_SCRIPTCHECK_THREADS = 0;
static const int64_t DEFAULT_MAX_TIP_AGE = 24 * 60 * 60;
static const bool DEFAULT_CHECKPOINTS_ENABLED = true;
static const bool DEFAULT_TXINDEX = false;
static constexpr bool DEFAULT_COINSTATSINDEX{false};
static const char* const DEFAULT_BLOCKFILTERINDEX = "0";
/** Default for -persistmempool */
static const bool DEFAULT_PERSIST_MEMPOOL = true;
/** Default for -stopatheight */
static const int DEFAULT_STOPATHEIGHT = 0;
/** Block files containing a block-height within MIN_BLOCKS_TO_KEEP of ActiveChain().Tip() will not be pruned. */
static const unsigned int MIN_BLOCKS_TO_KEEP = 288;
static const signed int DEFAULT_CHECKBLOCKS = 6;
static constexpr int DEFAULT_CHECKLEVEL{3};
// Require that user allocate at least 550 MiB for block & undo files (blk???.dat and rev???.dat)
// At 1MB per block, 288 blocks = 288MB.
// Add 15% for Undo data = 331MB
// Add 20% for Orphan block rate = 397MB
// We want the low water mark after pruning to be at least 397 MB and since we prune in
// full block file chunks, we need the high water mark which triggers the prune to be
// one 128MB block file + added 15% undo data = 147MB greater for a total of 545MB
// Setting the target to >= 550 MiB will make it likely we can respect the target.
static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024;

/** Current sync state passed to tip changed callbacks. */
enum class SynchronizationState {
    INIT_REINDEX,
    INIT_DOWNLOAD,
    POST_INIT
};

extern RecursiveMutex cs_main;
extern Mutex g_best_block_mutex;
extern std::condition_variable g_best_block_cv;
/** Used to notify getblocktemplate RPC of new tips. */
extern uint256 g_best_block;
/** Whether there are dedicated script-checking threads running.
 * False indicates all script checking is done on the main threadMessageHandler thread.
 */
extern bool g_parallel_script_checks;
extern bool fRequireStandard;
extern bool fCheckBlockIndex;
extern bool fCheckpointsEnabled;
/** A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation) */
extern CFeeRate minRelayTxFee;
/** If the tip is older than this (in seconds), the node is considered to be in initial block download. */
extern int64_t nMaxTipAge;

/** Block hash whose ancestors we will assume to have valid scripts without checking them. */
extern uint256 hashAssumeValid;

/** Minimum work we will assume exists on some valid chain. */
extern arith_uint256 nMinimumChainWork;

/** Documentation for argument 'checklevel'. */
extern const std::vector<std::string> CHECKLEVEL_DOC;

/** Run instances of script checking worker threads */
void StartScriptCheckWorkerThreads(int threads_num);
/** Stop all of the script checking worker threads */
void StopScriptCheckWorkerThreads();

CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams);

bool AbortNode(BlockValidationState& state, const std::string& strMessage, const bilingual_str& userMessage = bilingual_str{});

/** Guess verification progress (as a fraction between 0.0=genesis and 1.0=current tip). */
double GuessVerificationProgress(const ChainTxData& data, const CBlockIndex* pindex);

/** Prune block files up to a given height */
void PruneBlockFilesManual(CChainState& active_chainstate, int nManualPruneHeight);

/**
* Validation result for a single transaction mempool acceptance.
*/
struct MempoolAcceptResult {
    /** Used to indicate the results of mempool validation. */
    enum class ResultType {
        VALID, //!> Fully validated, valid.
        INVALID, //!> Invalid.
        MEMPOOL_ENTRY, //!> Valid, transaction was already in the mempool.
        DIFFERENT_WITNESS, //!> Not validated. A same-txid-different-witness tx (see m_other_wtxid) already exists in the mempool and was not replaced.
    };
    /** Result type. Present in all MempoolAcceptResults. */
    const ResultType m_result_type;

    /** Contains information about why the transaction failed. */
    const TxValidationState m_state;

    // The following fields are only present when m_result_type = ResultType::VALID or MEMPOOL_ENTRY
    /** Mempool transactions replaced by the tx per BIP 125 rules. */
    const std::optional<std::list<CTransactionRef>> m_replaced_transactions;
    /** Virtual size as used by the mempool, calculated using serialized size and sigops. */
    const std::optional<int64_t> m_vsize;
    /** Raw base fees in satoshis. */
    const std::optional<CAmount> m_base_fees;

    // The following field is only present when m_result_type = ResultType::DIFFERENT_WITNESS
    /** The wtxid of the transaction in the mempool which has the same txid but different witness. */
    const std::optional<uint256> m_other_wtxid;

    static MempoolAcceptResult Failure(TxValidationState state) {
        return MempoolAcceptResult(state);
    }

    static MempoolAcceptResult Success(std::list<CTransactionRef>&& replaced_txns, int64_t vsize, CAmount fees) {
        return MempoolAcceptResult(std::move(replaced_txns), vsize, fees);
    }

    static MempoolAcceptResult MempoolTx(int64_t vsize, CAmount fees) {
        return MempoolAcceptResult(vsize, fees);
    }

    static MempoolAcceptResult MempoolTxDifferentWitness(const uint256& other_wtxid) {
        return MempoolAcceptResult(other_wtxid);
    }

// Private constructors. Use static methods MempoolAcceptResult::Success, etc. to construct.
private:
    /** Constructor for failure case */
    explicit MempoolAcceptResult(TxValidationState state)
        : m_result_type(ResultType::INVALID), m_state(state) {
            Assume(!state.IsValid()); // Can be invalid or error
        }

    /** Constructor for success case */
    explicit MempoolAcceptResult(std::list<CTransactionRef>&& replaced_txns, int64_t vsize, CAmount fees)
        : m_result_type(ResultType::VALID),
        m_replaced_transactions(std::move(replaced_txns)), m_vsize{vsize}, m_base_fees(fees) {}

    /** Constructor for already-in-mempool case. It wouldn't replace any transactions. */
    explicit MempoolAcceptResult(int64_t vsize, CAmount fees)
        : m_result_type(ResultType::MEMPOOL_ENTRY), m_vsize{vsize}, m_base_fees(fees) {}

    /** Constructor for witness-swapped case. */
    explicit MempoolAcceptResult(const uint256& other_wtxid)
        : m_result_type(ResultType::DIFFERENT_WITNESS), m_other_wtxid(other_wtxid) {}
};

/**
* Validation result for package mempool acceptance.
*/
struct PackageMempoolAcceptResult
{
    const PackageValidationState m_state;
    /**
    * Map from wtxid to finished MempoolAcceptResults. The client is responsible
    * for keeping track of the transaction objects themselves. If a result is not
    * present, it means validation was unfinished for that transaction. If there
    * was a package-wide error (see result in m_state), m_tx_results will be empty.
    */
    std::map<const uint256, const MempoolAcceptResult> m_tx_results;
    /** Package feerate, defined as the aggregated modified fees divided by the total virtual size
     * of all transactions in the package.  May be unavailable if some inputs were not available or
     * a transaction failure caused validation to terminate early. */
    std::optional<CFeeRate> m_package_feerate;

    explicit PackageMempoolAcceptResult(PackageValidationState state,
                                        std::map<const uint256, const MempoolAcceptResult>&& results)
        : m_state{state}, m_tx_results(std::move(results)) {}

    explicit PackageMempoolAcceptResult(PackageValidationState state, CFeeRate feerate,
                                        std::map<const uint256, const MempoolAcceptResult>&& results)
        : m_state{state}, m_tx_results(std::move(results)), m_package_feerate{feerate} {}

    /** Constructor to create a PackageMempoolAcceptResult from a single MempoolAcceptResult */
    explicit PackageMempoolAcceptResult(const uint256& wtxid, const MempoolAcceptResult& result)
        : m_tx_results{ {wtxid, result} } {}
};

/**
 * Try to add a transaction to the mempool. This is an internal function and is exposed only for testing.
 * Client code should use ChainstateManager::ProcessTransaction()
 *
 * @param[in]  active_chainstate  Reference to the active chainstate.
 * @param[in]  tx                 The transaction to submit for mempool acceptance.
 * @param[in]  accept_time        The timestamp for adding the transaction to the mempool.
 *                                It is also used to determine when the entry expires.
 * @param[in]  bypass_limits      When true, don't enforce mempool fee and capacity limits.
 * @param[in]  test_accept        When true, run validation checks but don't submit to mempool.
 *
 * @returns a MempoolAcceptResult indicating whether the transaction was accepted/rejected with reason.
 */
MempoolAcceptResult AcceptToMemoryPool(CChainState& active_chainstate, const CTransactionRef& tx,
                                       int64_t accept_time, bool bypass_limits, bool test_accept)
    EXCLUSIVE_LOCKS_REQUIRED(cs_main);

/**
* Validate (and maybe submit) a package to the mempool. See doc/policy/packages.md for full details
* on package validation rules.
* @param[in]    test_accept     When true, run validation checks but don't submit to mempool.
* @returns a PackageMempoolAcceptResult which includes a MempoolAcceptResult for each transaction.
* If a transaction fails, validation will exit early and some results may be missing. It is also
* possible for the package to be partially submitted.
*/
PackageMempoolAcceptResult ProcessNewPackage(CChainState& active_chainstate, CTxMemPool& pool,
                                                   const Package& txns, bool test_accept)
                                                   EXCLUSIVE_LOCKS_REQUIRED(cs_main);

/* Transaction policy functions */

/**
 * Check if transaction will be final in the next block to be created.
 */
bool CheckFinalTxAtTip(const CBlockIndex* active_chain_tip, const CTransaction& tx) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);

/**
 * Check if transaction will be BIP68 final in the next block to be created on top of tip.
 * @param[in]   tip             Chain tip to check tx sequence locks against. For example,
 *                              the tip of the current active chain.
 * @param[in]   coins_view      Any CCoinsView that provides access to the relevant coins for
 *                              checking sequence locks. For example, it can be a CCoinsViewCache
 *                              that isn't connected to anything but contains all the relevant
 *                              coins, or a CCoinsViewMemPool that is connected to the
 *                              mempool and chainstate UTXO set. In the latter case, the caller is
 *                              responsible for holding the appropriate locks to ensure that
 *                              calls to GetCoin() return correct coins.
 * Simulates calling SequenceLocks() with data from the tip passed in.
 * Optionally stores in LockPoints the resulting height and time calculated and the hash
 * of the block needed for calculation or skips the calculation and uses the LockPoints
 * passed in for evaluation.
 * The LockPoints should not be considered valid if CheckSequenceLocksAtTip returns false.
 */
bool CheckSequenceLocksAtTip(CBlockIndex* tip,
                        const CCoinsView& coins_view,
                        const CTransaction& tx,
                        LockPoints* lp = nullptr,
                        bool useExistingLockPoints = false);

/**
 * Closure representing one script verification
 * Note that this stores references to the spending transaction
 */
class CScriptCheck
{
private:
    CTxOut m_tx_out;
    const CTransaction *ptxTo;
    unsigned int nIn;
    unsigned int nFlags;
    bool cacheStore;
    ScriptError error;
    PrecomputedTransactionData *txdata;

public:
    CScriptCheck(): ptxTo(nullptr), nIn(0), nFlags(0), cacheStore(false), error(SCRIPT_ERR_UNKNOWN_ERROR) {}
    CScriptCheck(const CTxOut& outIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn, PrecomputedTransactionData* txdataIn) :
        m_tx_out(outIn), ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), error(SCRIPT_ERR_UNKNOWN_ERROR), txdata(txdataIn) { }

    bool operator()();

    void swap(CScriptCheck& check) noexcept
    {
        std::swap(ptxTo, check.ptxTo);
        std::swap(m_tx_out, check.m_tx_out);
        std::swap(nIn, check.nIn);
        std::swap(nFlags, check.nFlags);
        std::swap(cacheStore, check.cacheStore);
        std::swap(error, check.error);
        std::swap(txdata, check.txdata);
    }

    ScriptError GetScriptError() const { return error; }
};

/** Initializes the script-execution cache */
void InitScriptExecutionCache();

/** Functions for validating blocks and updating the block tree */

/** Context-independent validity checks */
bool CheckBlock(const CBlock& block, BlockValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW = true, bool fCheckMerkleRoot = true);

/** Check a block is completely valid from start to finish (only works on top of our current best block) */
bool TestBlockValidity(BlockValidationState& state,
                       const CChainParams& chainparams,
                       CChainState& chainstate,
                       const CBlock& block,
                       CBlockIndex* pindexPrev,
                       const std::function<int64_t()>& adjusted_time_callback,
                       bool fCheckPOW = true,
                       bool fCheckMerkleRoot = true) EXCLUSIVE_LOCKS_REQUIRED(cs_main);

/** RAII wrapper for VerifyDB: Verify consistency of the block and coin databases */
class CVerifyDB {
public:
    CVerifyDB();
    ~CVerifyDB();
    bool VerifyDB(
        CChainState& chainstate,
        const Consensus::Params& consensus_params,
        CCoinsView& coinsview,
        int nCheckLevel,
        int nCheckDepth) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
};

enum DisconnectResult
{
    DISCONNECT_OK,      // All good.
    DISCONNECT_UNCLEAN, // Rolled back, but UTXO set was inconsistent with block.
    DISCONNECT_FAILED   // Something else went wrong.
};

class ConnectTrace;

/** @see CChainState::FlushStateToDisk */
enum class FlushStateMode {
    NONE,
    IF_NEEDED,
    PERIODIC,
    ALWAYS
};

/**
 * A convenience class for constructing the CCoinsView* hierarchy used
 * to facilitate access to the UTXO set.
 *
 * This class consists of an arrangement of layered CCoinsView objects,
 * preferring to store and retrieve coins in memory via `m_cacheview` but
 * ultimately falling back on cache misses to the canonical store of UTXOs on
 * disk, `m_dbview`.
 */
class CoinsViews {

public:
    //! The lowest level of the CoinsViews cache hierarchy sits in a leveldb database on disk.
    //! All unspent coins reside in this store.
    CCoinsViewDB m_dbview GUARDED_BY(cs_main);

    //! This view wraps access to the leveldb instance and handles read errors gracefully.
    CCoinsViewErrorCatcher m_catcherview GUARDED_BY(cs_main);

    //! This is the top layer of the cache hierarchy - it keeps as many coins in memory as
    //! can fit per the dbcache setting.
    std::unique_ptr<CCoinsViewCache> m_cacheview GUARDED_BY(cs_main);

    //! This constructor initializes CCoinsViewDB and CCoinsViewErrorCatcher instances, but it
    //! *does not* create a CCoinsViewCache instance by default. This is done separately because the
    //! presence of the cache has implications on whether or not we're allowed to flush the cache's
    //! state to disk, which should not be done until the health of the database is verified.
    //!
    //! All arguments forwarded onto CCoinsViewDB.
    CoinsViews(fs::path ldb_name, size_t cache_size_bytes, bool in_memory, bool should_wipe);

    //! Initialize the CCoinsViewCache member.
    void InitCache() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
};

enum class CoinsCacheSizeState
{
    //! The coins cache is in immediate need of a flush.
    CRITICAL = 2,
    //! The cache is at >= 90% capacity.
    LARGE = 1,
    OK = 0
};

/**
 * CChainState stores and provides an API to update our local knowledge of the
 * current best chain.
 *
 * Eventually, the API here is targeted at being exposed externally as a
 * consumable libconsensus library, so any functions added must only call
 * other class member functions, pure functions in other parts of the consensus
 * library, callbacks via the validation interface, or read/write-to-disk
 * functions (eventually this will also be via callbacks).
 *
 * Anything that is contingent on the current tip of the chain is stored here,
 * whereas block information and metadata independent of the current tip is
 * kept in `BlockManager`.
 */
class CChainState
{
protected:
    /**
     * Every received block is assigned a unique and increasing identifier, so we
     * know which one to give priority in case of a fork.
     */
    /** Blocks loaded from disk are assigned id 0, so start the counter at 1. */
    int32_t nBlockSequenceId GUARDED_BY(::cs_main) = 1;
    /** Decreasing counter (used by subsequent preciousblock calls). */
    int32_t nBlockReverseSequenceId = -1;
    /** chainwork for the last block that preciousblock has been applied to. */
    arith_uint256 nLastPreciousChainwork = 0;

    /**
     * The ChainState Mutex
     * A lock that must be held when modifying this ChainState - held in ActivateBestChain() and
     * InvalidateBlock()
     */
    Mutex m_chainstate_mutex;

    /**
     * Whether this chainstate is undergoing initial block download.
     *
     * Mutable because we need to be able to mark IsInitialBlockDownload()
     * const, which latches this for caching purposes.
     */
    mutable std::atomic<bool> m_cached_finished_ibd{false};

    //! Optional mempool that is kept in sync with the chain.
    //! Only the active chainstate has a mempool.
    CTxMemPool* m_mempool;

    //! Manages the UTXO set, which is a reflection of the contents of `m_chain`.
    std::unique_ptr<CoinsViews> m_coins_views;

public:
    //! Reference to a BlockManager instance which itself is shared across all
    //! CChainState instances.
    node::BlockManager& m_blockman;

    /** Chain parameters for this chainstate */
    /* TODO: replace with m_chainman.GetParams() */
    const CChainParams& m_params;

    //! The chainstate manager that owns this chainstate. The reference is
    //! necessary so that this instance can check whether it is the active
    //! chainstate within deeply nested method calls.
    ChainstateManager& m_chainman;

    explicit CChainState(
        CTxMemPool* mempool,
        node::BlockManager& blockman,
        ChainstateManager& chainman,
        std::optional<uint256> from_snapshot_blockhash = std::nullopt);

    /**
     * Initialize the CoinsViews UTXO set database management data structures. The in-memory
     * cache is initialized separately.
     *
     * All parameters forwarded to CoinsViews.
     */
    void InitCoinsDB(
        size_t cache_size_bytes,
        bool in_memory,
        bool should_wipe,
        fs::path leveldb_name = "chainstate");

    //! Initialize the in-memory coins cache (to be done after the health of the on-disk database
    //! is verified).
    void InitCoinsCache(size_t cache_size_bytes) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);

    //! @returns whether or not the CoinsViews object has been fully initialized and we can
    //!          safely flush this object to disk.
    bool CanFlushToDisk() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
    {
        AssertLockHeld(::cs_main);
        return m_coins_views && m_coins_views->m_cacheview;
    }

    //! The current chain of blockheaders we consult and build on.
    //! @see CChain, CBlockIndex.
    CChain m_chain;

    /**
     * The blockhash which is the base of the snapshot this chainstate was created from.
     *
     * std::nullopt if this chainstate was not created from a snapshot.
     */
    const std::optional<uint256> m_from_snapshot_blockhash;

    //! Return true if this chainstate relies on blocks that are assumed-valid. In
    //! practice this means it was created based on a UTXO snapshot.
    bool reliesOnAssumedValid() { return m_from_snapshot_blockhash.has_value(); }

    /**
     * The set of all CBlockIndex entries with either BLOCK_VALID_TRANSACTIONS (for
     * itself and all ancestors) *or* BLOCK_ASSUMED_VALID (if using background
     * chainstates) and as good as our current tip or better. Entries may be failed,
     * though, and pruning nodes may be missing the data for the block.
     */
    std::set<CBlockIndex*, node::CBlockIndexWorkComparator> setBlockIndexCandidates;

    //! @returns A reference to the in-memory cache of the UTXO set.
    CCoinsViewCache& CoinsTip() EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
    {
        AssertLockHeld(::cs_main);
        assert(m_coins_views->m_cacheview);
        return *m_coins_views->m_cacheview.get();
    }

    //! @returns A reference to the on-disk UTXO set database.
    CCoinsViewDB& CoinsDB() EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
    {
        AssertLockHeld(::cs_main);
        return m_coins_views->m_dbview;
    }

    //! @returns A pointer to the mempool.
    CTxMemPool* GetMempool()
    {
        return m_mempool;
    }

    //! @returns A reference to a wrapped view of the in-memory UTXO set that
    //!     handles disk read errors gracefully.
    CCoinsViewErrorCatcher& CoinsErrorCatcher() EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
    {
        AssertLockHeld(::cs_main);
        return m_coins_views->m_catcherview;
    }

    //! Destructs all objects related to accessing the UTXO set.
    void ResetCoinsViews() { m_coins_views.reset(); }

    //! The cache size of the on-disk coins view.
    size_t m_coinsdb_cache_size_bytes{0};

    //! The cache size of the in-memory coins view.
    size_t m_coinstip_cache_size_bytes{0};

    //! Resize the CoinsViews caches dynamically and flush state to disk.
    //! @returns true unless an error occurred during the flush.
    bool ResizeCoinsCaches(size_t coinstip_size, size_t coinsdb_size)
        EXCLUSIVE_LOCKS_REQUIRED(::cs_main);

    /** Import blocks from an external file */
    void LoadExternalBlockFile(FILE* fileIn, FlatFilePos* dbp = nullptr)
        EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex);

    /**
     * Update the on-disk chain state.
     * The caches and indexes are flushed depending on the mode we're called with
     * if they're too large, if it's been a while since the last write,
     * or always and in all cases if we're in prune mode and are deleting files.
     *
     * If FlushStateMode::NONE is used, then FlushStateToDisk(...) won't do anything
     * besides checking if we need to prune.
     *
     * @returns true unless a system error occurred
     */
    bool FlushStateToDisk(
        BlockValidationState& state,
        FlushStateMode mode,
        int nManualPruneHeight = 0);

    //! Unconditionally flush all changes to disk.
    void ForceFlushStateToDisk();

    //! Prune blockfiles from the disk if necessary and then flush chainstate changes
    //! if we pruned.
    void PruneAndFlush();

    /**
     * Find the best known block, and make it the tip of the block chain. The
     * result is either failure or an activated best chain. pblock is either
     * nullptr or a pointer to a block that is already loaded (to avoid loading
     * it again from disk).
     *
     * ActivateBestChain is split into steps (see ActivateBestChainStep) so that
     * we avoid holding cs_main for an extended period of time; the length of this
     * call may be quite long during reindexing or a substantial reorg.
     *
     * May not be called with cs_main held. May not be called in a
     * validationinterface callback.
     *
     * @returns true unless a system error occurred
     */
    bool ActivateBestChain(
        BlockValidationState& state,
        std::shared_ptr<const CBlock> pblock = nullptr)
        EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex)
        LOCKS_EXCLUDED(::cs_main);

    bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockValidationState& state, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock) EXCLUSIVE_LOCKS_REQUIRED(cs_main);

    // Block (dis)connection on a given view:
    DisconnectResult DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view)
        EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
    bool ConnectBlock(const CBlock& block, BlockValidationState& state, CBlockIndex* pindex,
                      CCoinsViewCache& view, bool fJustCheck = false) EXCLUSIVE_LOCKS_REQUIRED(cs_main);

    // Apply the effects of a block disconnection on the UTXO set.
    bool DisconnectTip(BlockValidationState& state, DisconnectedBlockTransactions* disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_mempool->cs);

    // Manual block validity manipulation:
    /** Mark a block as precious and reorganize.
     *
     * May not be called in a validationinterface callback.
     */
    bool PreciousBlock(BlockValidationState& state, CBlockIndex* pindex)
        EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex)
        LOCKS_EXCLUDED(::cs_main);

    /** Mark a block as invalid. */
    bool InvalidateBlock(BlockValidationState& state, CBlockIndex* pindex)
        EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex)
        LOCKS_EXCLUDED(::cs_main);

    /** Remove invalidity status from a block and its descendants. */
    void ResetBlockFailureFlags(CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);

    /** Replay blocks that aren't fully applied to the database. */
    bool ReplayBlocks();

    /** Whether the chain state needs to be redownloaded due to lack of witness data */
    [[nodiscard]] bool NeedsRedownload() const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
    /** Ensures we have a genesis block in the block tree, possibly writing one to disk. */
    bool LoadGenesisBlock();

    void PruneBlockIndexCandidates();

    void UnloadBlockIndex() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);

    /** Check whether we are doing an initial block download (synchronizing from disk or network) */
    bool IsInitialBlockDownload() const;

    /** Find the last common block of this chain and a locator. */
    const CBlockIndex* FindForkInGlobalIndex(const CBlockLocator& locator) const EXCLUSIVE_LOCKS_REQUIRED(cs_main);

    /**
     * Make various assertions about the state of the block index.
     *
     * By default this only executes fully when using the Regtest chain; see: fCheckBlockIndex.
     */
    void CheckBlockIndex();

    /** Load the persisted mempool from disk */
    void LoadMempool(const ArgsManager& args);

    /** Update the chain tip based on database information, i.e. CoinsTip()'s best block. */
    bool LoadChainTip() EXCLUSIVE_LOCKS_REQUIRED(cs_main);

    //! Dictates whether we need to flush the cache to disk or not.
    //!
    //! @return the state of the size of the coins cache.
    CoinsCacheSizeState GetCoinsCacheSizeState() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);

    CoinsCacheSizeState GetCoinsCacheSizeState(
        size_t max_coins_cache_size_bytes,
        size_t max_mempool_size_bytes) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);

    std::string ToString() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);

private:
    bool ActivateBestChainStep(BlockValidationState& state, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, ConnectTrace& connectTrace) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_mempool->cs);
    bool ConnectTip(BlockValidationState& state, CBlockIndex* pindexNew, const std::shared_ptr<const CBlock>& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions& disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_mempool->cs);

    void InvalidBlockFound(CBlockIndex* pindex, const BlockValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
    CBlockIndex* FindMostWorkChain() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
    void ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const FlatFilePos& pos) EXCLUSIVE_LOCKS_REQUIRED(cs_main);

    bool RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs) EXCLUSIVE_LOCKS_REQUIRED(cs_main);

    void CheckForkWarningConditions() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
    void InvalidChainFound(CBlockIndex* pindexNew) EXCLUSIVE_LOCKS_REQUIRED(cs_main);

    //! Indirection necessary to make lock annotations work with an optional mempool.
    RecursiveMutex* MempoolMutex() const LOCK_RETURNED(m_mempool->cs)
    {
        return m_mempool ? &m_mempool->cs : nullptr;
    }

    /**
     * Make mempool consistent after a reorg, by re-adding or recursively erasing
     * disconnected block transactions from the mempool, and also removing any
     * other transactions from the mempool that are no longer valid given the new
     * tip/height.
     *
     * Note: we assume that disconnectpool only contains transactions that are NOT
     * confirmed in the current chain nor already in the mempool (otherwise,
     * in-mempool descendants of such transactions would be removed).
     *
     * Passing fAddToMempool=false will skip trying to add the transactions back,
     * and instead just erase from the mempool as needed.
     */
    void MaybeUpdateMempoolForReorg(
        DisconnectedBlockTransactions& disconnectpool,
        bool fAddToMempool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_mempool->cs);

    /** Check warning conditions and do some notifications on new chain tip set. */
    void UpdateTip(const CBlockIndex* pindexNew)
        EXCLUSIVE_LOCKS_REQUIRED(::cs_main);

    friend ChainstateManager;
};

/**
 * Provides an interface for creating and interacting with one or two
 * chainstates: an IBD chainstate generated by downloading blocks, and
 * an optional snapshot chainstate loaded from a UTXO snapshot. Managed
 * chainstates can be maintained at different heights simultaneously.
 *
 * This class provides abstractions that allow the retrieval of the current
 * most-work chainstate ("Active") as well as chainstates which may be in
 * background use to validate UTXO snapshots.
 *
 * Definitions:
 *
 * *IBD chainstate*: a chainstate whose current state has been "fully"
 *   validated by the initial block download process.
 *
 * *Snapshot chainstate*: a chainstate populated by loading in an
 *    assumeutxo UTXO snapshot.
 *
 * *Active chainstate*: the chainstate containing the current most-work
 *    chain. Consulted by most parts of the system (net_processing,
 *    wallet) as a reflection of the current chain and UTXO set.
 *    This may either be an IBD chainstate or a snapshot chainstate.
 *
 * *Background IBD chainstate*: an IBD chainstate for which the
 *    IBD process is happening in the background while use of the
 *    active (snapshot) chainstate allows the rest of the system to function.
 */
class ChainstateManager
{
private:
    //! The chainstate used under normal operation (i.e. "regular" IBD) or, if
    //! a snapshot is in use, for background validation.
    //!
    //! Its contents (including on-disk data) will be deleted *upon shutdown*
    //! after background validation of the snapshot has completed. We do not
    //! free the chainstate contents immediately after it finishes validation
    //! to cautiously avoid a case where some other part of the system is still
    //! using this pointer (e.g. net_processing).
    //!
    //! Once this pointer is set to a corresponding chainstate, it will not
    //! be reset until init.cpp:Shutdown().
    //!
    //! This is especially important when, e.g., calling ActivateBestChain()
    //! on all chainstates because we are not able to hold ::cs_main going into
    //! that call.
    std::unique_ptr<CChainState> m_ibd_chainstate GUARDED_BY(::cs_main);

    //! A chainstate initialized on the basis of a UTXO snapshot. If this is
    //! non-null, it is always our active chainstate.
    //!
    //! Once this pointer is set to a corresponding chainstate, it will not
    //! be reset until init.cpp:Shutdown().
    //!
    //! This is especially important when, e.g., calling ActivateBestChain()
    //! on all chainstates because we are not able to hold ::cs_main going into
    //! that call.
    std::unique_ptr<CChainState> m_snapshot_chainstate GUARDED_BY(::cs_main);

    //! Points to either the ibd or snapshot chainstate; indicates our
    //! most-work chain.
    //!
    //! Once this pointer is set to a corresponding chainstate, it will not
    //! be reset until init.cpp:Shutdown().
    //!
    //! This is especially important when, e.g., calling ActivateBestChain()
    //! on all chainstates because we are not able to hold ::cs_main going into
    //! that call.
    CChainState* m_active_chainstate GUARDED_BY(::cs_main) {nullptr};

    //! If true, the assumed-valid chainstate has been fully validated
    //! by the background validation chainstate.
    bool m_snapshot_validated GUARDED_BY(::cs_main){false};

    CBlockIndex* m_best_invalid GUARDED_BY(::cs_main){nullptr};

    const CChainParams m_chainparams;

    const std::function<int64_t()> m_adjusted_time_callback;

    //! Internal helper for ActivateSnapshot().
    [[nodiscard]] bool PopulateAndValidateSnapshot(
        CChainState& snapshot_chainstate,
        CAutoFile& coins_file,
        const node::SnapshotMetadata& metadata);

    /**
     * If a block header hasn't already been seen, call CheckBlockHeader on it, ensure
     * that it doesn't descend from an invalid block, and then add it to m_block_index.
     */
    bool AcceptBlockHeader(
        const CBlockHeader& block,
        BlockValidationState& state,
        CBlockIndex** ppindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
    friend CChainState;

public:
    using Options = ChainstateManagerOpts;

    explicit ChainstateManager(const Options& opts)
        : m_chainparams{opts.chainparams},
          m_adjusted_time_callback{Assert(opts.adjusted_time_callback)} {};

    const CChainParams& GetParams() const { return m_chainparams; }
    const Consensus::Params& GetConsensus() const { return m_chainparams.GetConsensus(); }

    std::thread m_load_block;
    //! A single BlockManager instance is shared across each constructed
    //! chainstate to avoid duplicating block metadata.
    node::BlockManager m_blockman;

    /**
     * In order to efficiently track invalidity of headers, we keep the set of
     * blocks which we tried to connect and found to be invalid here (ie which
     * were set to BLOCK_FAILED_VALID since the last restart). We can then
     * walk this set and check if a new header is a descendant of something in
     * this set, preventing us from having to walk m_block_index when we try
     * to connect a bad block and fail.
     *
     * While this is more complicated than marking everything which descends
     * from an invalid block as invalid at the time we discover it to be
     * invalid, doing so would require walking all of m_block_index to find all
     * descendants. Since this case should be very rare, keeping track of all
     * BLOCK_FAILED_VALID blocks in a set should be just fine and work just as
     * well.
     *
     * Because we already walk m_block_index in height-order at startup, we go
     * ahead and mark descendants of invalid blocks as FAILED_CHILD at that time,
     * instead of putting things in this set.
     */
    std::set<CBlockIndex*> m_failed_blocks;

    /** Best header we've seen so far (used for getheaders queries' starting points). */
    CBlockIndex* m_best_header = nullptr;

    //! The total number of bytes available for us to use across all in-memory
    //! coins caches. This will be split somehow across chainstates.
    int64_t m_total_coinstip_cache{0};
    //
    //! The total number of bytes available for us to use across all leveldb
    //! coins databases. This will be split somehow across chainstates.
    int64_t m_total_coinsdb_cache{0};

    //! Instantiate a new chainstate and assign it based upon whether it is
    //! from a snapshot.
    //!
    //! @param[in] mempool              The mempool to pass to the chainstate
    //                                  constructor
    //! @param[in] snapshot_blockhash   If given, signify that this chainstate
    //!                                 is based on a snapshot.
    CChainState& InitializeChainstate(
        CTxMemPool* mempool,
        const std::optional<uint256>& snapshot_blockhash = std::nullopt)
        LIFETIMEBOUND EXCLUSIVE_LOCKS_REQUIRED(::cs_main);

    //! Get all chainstates currently being used.
    std::vector<CChainState*> GetAll();

    //! Construct and activate a Chainstate on the basis of UTXO snapshot data.
    //!
    //! Steps:
    //!
    //! - Initialize an unused CChainState.
    //! - Load its `CoinsViews` contents from `coins_file`.
    //! - Verify that the hash of the resulting coinsdb matches the expected hash
    //!   per assumeutxo chain parameters.
    //! - Wait for our headers chain to include the base block of the snapshot.
    //! - "Fast forward" the tip of the new chainstate to the base of the snapshot,
    //!   faking nTx* block index data along the way.
    //! - Move the new chainstate to `m_snapshot_chainstate` and make it our
    //!   ChainstateActive().
    [[nodiscard]] bool ActivateSnapshot(
        CAutoFile& coins_file, const node::SnapshotMetadata& metadata, bool in_memory);

    //! The most-work chain.
    CChainState& ActiveChainstate() const;
    CChain& ActiveChain() const { return ActiveChainstate().m_chain; }
    int ActiveHeight() const { return ActiveChain().Height(); }
    CBlockIndex* ActiveTip() const { return ActiveChain().Tip(); }

    node::BlockMap& BlockIndex() EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
    {
        AssertLockHeld(::cs_main);
        return m_blockman.m_block_index;
    }

    /**
     * Track versionbit status
     */
    mutable VersionBitsCache m_versionbitscache;

    //! @returns true if a snapshot-based chainstate is in use. Also implies
    //!          that a background validation chainstate is also in use.
    bool IsSnapshotActive() const;

    std::optional<uint256> SnapshotBlockhash() const;

    //! Is there a snapshot in use and has it been fully validated?
    bool IsSnapshotValidated() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { return m_snapshot_validated; }

    /**
     * Process an incoming block. This only returns after the best known valid
     * block is made active. Note that it does not, however, guarantee that the
     * specific block passed to it has been checked for validity!
     *
     * If you want to *possibly* get feedback on whether block is valid, you must
     * install a CValidationInterface (see validationinterface.h) - this will have
     * its BlockChecked method called whenever *any* block completes validation.
     *
     * Note that we guarantee that either the proof-of-work is valid on block, or
     * (and possibly also) BlockChecked will have been called.
     *
     * May not be called in a validationinterface callback.
     *
     * @param[in]   block The block we want to process.
     * @param[in]   force_processing Process this block even if unrequested; used for non-network block sources.
     * @param[out]  new_block A boolean which is set to indicate if the block was first received via this call
     * @returns     If the block was processed, independently of block validity
     */
    bool ProcessNewBlock(const std::shared_ptr<const CBlock>& block, bool force_processing, bool* new_block) LOCKS_EXCLUDED(cs_main);

    /**
     * Process incoming block headers.
     *
     * May not be called in a
     * validationinterface callback.
     *
     * @param[in]  block The block headers themselves
     * @param[out] state This may be set to an Error state if any error occurred processing them
     * @param[out] ppindex If set, the pointer will be set to point to the last new block index object for the given headers
     */
    bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& block, BlockValidationState& state, const CBlockIndex** ppindex = nullptr) LOCKS_EXCLUDED(cs_main);

    /**
     * Try to add a transaction to the memory pool.
     *
     * @param[in]  tx              The transaction to submit for mempool acceptance.
     * @param[in]  test_accept     When true, run validation checks but don't submit to mempool.
     */
    [[nodiscard]] MempoolAcceptResult ProcessTransaction(const CTransactionRef& tx, bool test_accept=false)
        EXCLUSIVE_LOCKS_REQUIRED(cs_main);

    //! Load the block tree and coins database from disk, initializing state if we're running with -reindex
    bool LoadBlockIndex() EXCLUSIVE_LOCKS_REQUIRED(cs_main);

    //! Check to see if caches are out of balance and if so, call
    //! ResizeCoinsCaches() as needed.
    void MaybeRebalanceCaches() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);

    /** Update uncommitted block structures (currently: only the witness reserved value). This is safe for submitted blocks. */
    void UpdateUncommittedBlockStructures(CBlock& block, const CBlockIndex* pindexPrev) const;

    /** Produce the necessary coinbase commitment for a block (modifies the hash, don't call for mined blocks). */
    std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBlockIndex* pindexPrev) const;

    ~ChainstateManager();
};

/** Deployment* info via ChainstateManager */
template<typename DEP>
bool DeploymentActiveAfter(const CBlockIndex* pindexPrev, const ChainstateManager& chainman, DEP dep)
{
    return DeploymentActiveAfter(pindexPrev, chainman.GetConsensus(), dep, chainman.m_versionbitscache);
}

template<typename DEP>
bool DeploymentActiveAt(const CBlockIndex& index, const ChainstateManager& chainman, DEP dep)
{
    return DeploymentActiveAt(index, chainman.GetConsensus(), dep, chainman.m_versionbitscache);
}

template<typename DEP>
bool DeploymentEnabled(const ChainstateManager& chainman, DEP dep)
{
    return DeploymentEnabled(chainman.GetConsensus(), dep);
}

using FopenFn = std::function<FILE*(const fs::path&, const char*)>;

/** Dump the mempool to disk. */
bool DumpMempool(const CTxMemPool& pool, FopenFn mockable_fopen_function = fsbridge::fopen, bool skip_file_commit = false);

/** Load the mempool from disk. */
bool LoadMempool(CTxMemPool& pool, CChainState& active_chainstate, FopenFn mockable_fopen_function = fsbridge::fopen);

/**
 * Return the expected assumeutxo value for a given height, if one exists.
 *
 * @param[in] height Get the assumeutxo value for this height.
 *
 * @returns empty if no assumeutxo configuration exists for the given height.
 */
const AssumeutxoData* ExpectedAssumeutxo(const int height, const CChainParams& params);

#endif // BITCOIN_VALIDATION_H

redpajama_set_name: RedPajamaGithub


text:
Oak Hill community garden group sets organizing meeting
A community garden, like this one being built in Hyde Park, could soon be a reality in Oak Hill.
By Tony Tucci
Support for a community garden in Oak Hill is taking root, and interested gardeners are invited to attend a meeting Saturday, Jan. 21, to discuss possible locations.
Patrick Hamilton, an Oak Hill resident who is spearheading the effort, said the meeting will be held from 2 to 3:30 p.m at the Hampton Branch Library on Convict Hill Road. The library is one of the sites being mentioned for a garden. While no decision has been made, Hamilton said other sites that have been mentioned are Small Middle School, Bowie High School, and a three-quarter acre privately owned plot near Waldorf School.
"I think it's really taking off," said Hamilton, an experienced organic farmer who has worked mostly with orchards and wants to include some fruit trees in the community garden plan. "I'm hoping to be planting this spring, even if it's only planting fences and water lines."
Austin has 26 community gardens, but none in Oak Hill. The closest is Sunset Valley. Jake Stewart, head of the Austin community gardens program, said he will support any effort to locate a garden in Oak Hill.
Hamilton said he received about a dozen e-mails from people interested in a community garden as a result of a story published in the Oak Hill Gazette last month. His e-mail address is pfh33@yahoo.com, or he can be telephoned at (804) 615-0709.
Meanwhile, Hamilton said he has visited with a number of people to discuss a location for the garden.
"Small Middle School would be a great partner," he said. The school has two environmental science teachers and a gardening program for students. However, he said the school could provide only several small spaces scattered around the campus rather than one contiguous space.
Chris Brooks, a Deer Park at Maple Run resident and one of the teachers at Small, said he thinks the school would welcome a community garden on school grounds. "It would be a great opportunity to promote closer ties between the community and the school," he said.
Jo Ann Kugle said she is very interested in having a community garden on about three-quarters of an acre of land near her home on Southview Road, about two and a half miles west of the Oak Hill 'Y' off U.S. Highway 290.
"We have about 10 acres of land here, most of it heavy forest, but this parcel gets full sun and would be ideal for a garden," she said. She has lived on the property with her family for 35 years, and she has always wanted to put a garden there.
"I think a lot of people are thinking about being sustainable and self-sufficient," she said, adding that she and her husband started raising chickens last year and now have four hens that produce about two eggs a day.
She said it would be great to get some expert advice to teach her and others about gardening. "The first thing we'd have to do is build a fence to keep out the deer and the rabbits," she said.
Dwight Littleton, 66, is an old hand at gardening. He can't garden at his home in Granada Hills, however, because of the deer. "There are only a few plants that the deer won't eat," he said.
For about 10 years, he leased some land for a garden on South Lamar Boulevard from the Salvation Army. The land was sold about a year ago to a developer, and Littleton and other gardeners were forced out. Littleton said he managed to get another space behind the It's About Thyme nursery at Manchaca and Frate Barker roads because he's friends with the owner.
"I'll be at the meeting (Jan. 21), and I'll bring a bunch of my friends who want to garden, too," he said.
Hamilton, who lives in the Scenic Brook neighborhood and has worked professionally on six organic farms, said he sees the community garden as an opportunity for residents to learn about growing their own food organically. He said both the Sustainable Food Center and Austin Community Gardens have offered to help.
"It's all kind of up in the air right now, but I'm excited about the response I've been getting," Hamilton said.

redpajama_set_name: RedPajamaCommonCrawl


text:
College Dropouts Cost Taxpayers Billions, Report Says
By Eric Kelderman
State and federal governments spent an estimated $9-billion between 2003 and 2008 on students who dropped out of college during their freshman year, according to a report scheduled for release on Monday.
While that sum may be a small portion of the overall amount that governments spent on higher education during that time, it's still a high cost for failing to keep students in college, said Mark S. Schneider, vice president for education, human development, and the work force at the American Institutes for Research, which compiled the data for the report.
And since the report considered only first-time, full-time freshmen at four-year colleges, the $9-billion total is also just a portion of the overall cost of dropouts, Mr. Schneider said on Thursday during a conference call with reporters.
Because the report is based on data from the U.S. Education Department, it does not take account of students who attend part time, who leave college in order to transfer to another institution, or who drop out but return later to receive their degrees. So the report's conclusions are incomplete.
The report makes no recommendations about how to better retain college students, but Mr. Schneider said that states should base a much larger percentage of their higher-education spending on the number of students who complete degrees, not the number enrolled, at a given institution.
In addition to the report, the institute is unveiling a new Web site that allows users to compare a variety of performance measures for more than 1,500 public and private colleges and universities and all 50 states, including the percentage of freshmen who drop out of college, the amount spent on those who drop out, and the amount spent on instruction and administration.
The Web site also wades into the controversial area of "gainful employment" by providing some data on the ratio of student-loan repayments to earnings for recent graduates at each of the 1,500 institutions. The U.S. Department of Education is formulating a new regulation that could disqualify some institutions, in particular for-profit colleges, from receiving federal financial aid if their students incur too much student-loan debt in comparison to their earnings.
The Web site is meant to provide accountability and openness for consumers and policy makers about how well a state or a particular institution is performing, said Larry Giammo, managing director of Matrix Knowledge Group, an international consulting company that works with nonprofit and government groups and that helped to create the new site.
Law & PolicyPolitical Influence & Activism
Eric Kelderman
Eric Kelderman covers issues of power, politics, and purse strings in higher education. You can email him at eric.kelderman@chronicle.com, or find him on Twitter @etkeld.


The Midwifery and Maternity Providers Organisation (MMPO), established by the New Zealand College of Midwives, is the largest organization in New Zealand dedicated to supporting self-employed midwives to meet their service, professional and financial commitments. Clevermed have been working closely with the MMPO to design an electronic system (referred to as the MMPO Midwifery Information System by its staff and members)to support the midwives in managing their care and practice.
Following a successful 5 month pilot phase, the system is now being phased to a full roll-out across the MMPO midwifery members. With benefits such as in-built claiming rules, off-line mode allowing midwives to enter information in the community, and sharing information and records easily between practice partners, the feedback has been very positive to date.
The MMPO have a dynamic team which have been great to work with. We are looking forward to an on-going relationship as part of our managed service to ensure the inbuilt features of the BadgerNet Platform continue to evolve and improve in supporting midwives' needs.


David Haxton - Cut To: Paper and Film.
Gavlak Los Angeles has just opened Cut To: Paint and Film, a solo exhibition of recent and vintage works by David Haxton.
Sacré 101: An Exhibition Based on The Rite of Spring.


Gulf Shores, Alabama experienced significant flooding.
A Pensacola hospital was damaged by the storm.
MOBILE, Alabama (CNN) -- Remnants of Hurricane Ivan soaked the Southeast Thursday evening after the storm came ashore with full force in Alabama and spawned tornadoes that killed eight people.
Florida Gov. Jeb Bush called the storm "devastating" and said his heart went out to the families of those who died and to all residents on the Gulf Coast whose homes were damaged.
The insurance forecasting firm Eqecat estimated Ivan caused between $4 billion and $10 billion in damage and that 30 percent to 50 percent of Ivan's insured losses occurred in and around Pensacola.
President Bush declared Florida, Alabama, Louisiana and Mississippi disaster areas, making federal funding and aid available. The declaration for Florida was the third in a month, following those issued for hurricanes Charley and Frances.
More than 2,000 National Guard troops were moving into northwest Florida to assist with assessment and cleanup operations, Gov. Bush said.
"Entire houses were taken off their foundations and disappeared because of the storm surge on the barrier islands," Gov. Bush said. "These are newly built luxury homes that don't exist right now. That's pretty powerful."
In Pensacola, winds sheared off the exterior of a section of West Florida Hospital, said a spokeswoman, but patient wings were undamaged. Three other hospitals in the area also were damaged, officials reported.
Storm damage made travel from Pensacola difficult. Highway 90 was closed, as was Interstate 10 over Escambia Bay, where an 18-wheel truck plunged into the water and trapped the driver in the rig.
Winds throughout the west Florida area bent billboard signs, damaged trees, ripped roofs off buildings and scattered debris.
"As I have said before, man gets put in his place when he understands that at a particular point in time when it comes to nature, all he is is an observer," said Panama City Beach Mayor Lee Sullivan.
Damage was heavy in other spots as well. Downed trees and power lines were reported all along the coast.
In Biloxi, Mississippi, a few restaurants and a church lost parts of their roofs, and in Jackson County, along the Alabama state line, some gas station awnings -- and even the pumps themselves -- were blown over.
As of 11 p.m. ET, the National Hurricane Center in Miami said the storm was centered 25 miles (40 kilometers) north-northwest of Gadsen, Alabama, and headed north-northeast at about 14 mph (55 kph) with sustained winds around 35 mph (97 kph) and higher gusts.
The hurricane center said rainfall amounts of 8 to 12 inches were possible through Saturday in the Southeast.
Storm-related tornadoes in the Florida Panhandle ahead of Ivan's landfall killed at least two people Wednesday in the resort town of Panama City Beach.
Early Thursday, a powerful tornado leveled homes in Blountstown, west of Tallahassee, killing four people.
A young girl in Milton died when a tree fell on her house, said a spokesman for Santa Rosa County.
One person southwest Georgia died when a tree fell on a car Thursday afternoon, possibly the result of a tornado, a Franklin County official said.
Ivan made landfall on the east side of Mobile Bay in Alabama at 1:50 a.m. (2:50 a.m. ET) Thursday as a slightly weakened Category 3 hurricane with winds of 130 mph (208 kph).
The mayor of Mobile breathed a sigh of relief and said it appeared damage to his city was less extensive than feared. "I think we caught a bullet with our teeth," said Mayor Michael Dow.
It was a different story in nearby Gulf Shores, Alabama, where water as high as 6 feet covered much of the barrier island.
An emergency services representative from Baldwin County, Alabama, toured the Gulf Shores area and expressed dismay.
"Orange Beach [east of Gulf Shores] all the way down to what was the FloraBama, it is no longer there. I just can't express the devastation that's there. Just every single condo or hotel, rental unit, had some extensive damage," she told reporters.
Authorities in Gulf Shores were looking for at least 13 deer and six alligators that were not evacuated from a local zoo and were seen wading and swimming through the floodwaters.
One of the alligators on the loose is named Chuckie, which measures 12 feet long and weighs 1,000 pounds, authorities said.
Another alligator was shot and killed, but authorities said they planned to only tranquilize the deer they manage to find.
Oil companies were assessing damage after hundreds of oil rigs were evacuated in the Gulf of Mexico.
Transocean Inc. reported an oil rig missing, but the Deepwater Nautilus was later found 73 miles northeast of its original location. Diamond Offshore Drilling also reported a rig afloat, but it was located and the company reported no apparent damage or pollution.
A spokesman for the Minerals Management Service said it was not unusual for drilling rigs to break free during a storm of Ivan's intensity.
But spokesman Curtis Carey said the potential danger is from damaged pipelines since the rigs' anchors drag on the gulf floor. He said there have been no reports of damage to pipelines so far.
The Gulf of Mexico is home to about 25 percent of U.S. oil and gas production and there was concern about sustained disruptions to the flow of oil and gas.
Oil companies evacuated 545 offshore rigs as the storm approached, disrupting 83 percent of daily production -- about 1.7 million barrels of oil a day, the service said.
In addition, more than half of natural gas production was disrupted, the service reported.
Hurricane Jeanne lost some of its strength Thursday, after it scraped the northern coast of the Dominican Republic and appeared headed for the Bahamas.
Jeanne had sustained winds of 70 mph (110 kph), the National Hurricane Center in Miami said.
CNN's Kathleen Koch and Susan Candiotti in Biloxi, Mississippi, Rick Sanchez in Panama City Beach, Florida, Gary Tuchman in Gulf Shores, Alabama, and Sara Dorsey in Pensacola, Florida, contributed to this report.


text:
Through this process I have come to learn that the butterfly doesn't contradict the caterpillar. The butterfly is the next stage of the caterpillar's development after it has surrendered to its next level. And much like the caterpillar, I was resistant to that transformation but you can only resist for so long before nature/God pulls you, the caterpillar, the rest of the way. Because what the caterpillar and the butterfly want are two totally different things. The caterpillar is ok with walking around slowly, from place to place, living a somewhat mundane life eating leaves all day. But the butterfly wants to spread its wings and fly, showing off the silent beauty that has been created.
I've spent my life doing everything and getting everything I wanted never having to use anger or violence and I think that speaks volumes about who I am and the power that lies within me. I am a natural born agent of change, though it took some time to come to know that, and now I know the proper use for my life and my gifts, to heal people through my work be it comedy or acting or writing. We're all here to leave our marks and heal the world, leaving it a better place than we found it. Unfortunately we all don't wake up to that fact in this lifetime. I now know that it doesn't matter if I am black, white, blue, green, straight, gay, bisexual, or a motorcycle, as long as I live my life according to the will of God/the universe as I understand it and it's intention for me.
At this point, I am no longer concerned with acceptance. My life will be my life and I have to live it for me. I will not fight to change anyone's beliefs; I merely offer up an alternative way of seeing things, something not traditionally done in the black community, seeing how religiously we're set in very old ways. Believe for me what you want, wish for me what you will but I already know the great things that are in store for me. You don't have to like who I am, you don't have to love who I am, but regardless of how you feel, I'm going to be me. You can choose to stay a part of me life or if you disagree with who I am then don't. I would much rather you be truthful about your feelings for me as a friend than to be fake. I'm four years from 30; I'm a big boy now I can take it.
I'm not telling anyone how to run their family, raise their children or what to teach is acceptable to them, but I know for a fact, my child will never be taught to hate or dislike anyone simply because of who they are or claim to be, or what some book tells them. Hate and separation has never solved anything in this world but love, unity, and equality has created the world as we know it today. I do know that when blacks were fighting for equal rights the Bible was used to defend not giving those rights and left up to the people to vote and decide, blacks still wouldn't have rights today. But it took a brave man in President Lyndon Johnson to recognize that telling people they weren't equal because they were born a different color was wrong and what was being done to black people was wrong and he signed the civil rights act on his own volition.
Today people like myself all over the world are in the middle of our very own civil rights movement fighting once again, against religion and the bible to be seen as societal equals and 50 years from now when history books tell the tale, those young people will read in disbelief that the same wrongs were perpetrated twice when the example was already laid forth on how to prevent it. A lot of people will find themselves on the wrong side of history. Ironically even after the civil rights movement only 50 years ago, the entire black community might find itself there as a whole.
Some may wonder why I chose today to do this, though I've been hard pressed to do so in the wake of all the bullying and suicides taking place. Well as funny and trivial as it may seem, I had been receiving a lot of "signs" if you will, pushing me to this point. So today when I received an email from WordPress for the "post a day 2011? challenge and todays topic was "write about something you've never told anyone and explain why", it seemed pretty compelling that today was the day don't you think?
So to my friends and family, including my awesome sister and mother who have already had the privilege of knowing this information, I would like to say thank you very much for you love and support throughout this process because I couldn't have done it without you. And to my friends and family just learning of this, I just say accept me as I am, as you've known me my whole life, or don't. Because if I have proved nothing to you, I have proved that LGBT people are just as normal, kind and talented as anyone else in the world and who you love makes no difference in how you live.
How does this affect my comedy and acting career? Will it stop me from booking clubs or getting hired for acting jobs? who knows for sure. But I believe the added element of truth will make it a whole lot easier to be myself, write funnier material, write truthful material, and that's good enough for me. Hopefully my story, work, and life can serve as hope to someone else because the world could use a lot less people in the closet that's for sure. I just pray that my ultimate truth takes me to the place and places where I truly belong. The photos you see are in no particular place for a particular reason; just different moments of my life in all its many different forms its taken.
Hopefully I can be one more chip at the wall of homophobia in the world and especially the black community, where so many other people like myself suffer in silence or are banished from their homes and disowned by family because of who they are. It's a very big problem and I will spend my life doing what I can with the talents I've been given to strip the black community of this illness. We can't continue to be moral, ethical, and historical hypocrites in black America toward the LGBT community.
Dr. Seuss said "Be who you are and say what you feel, because those who mind don't matter and those who matter don't mind" and this is a lesson I now take to heart, because I have just committed to doing just that. If you want to stop being my friend then by all means do just that, but if you want to continue the friendship that we have, then by all means, do that as well. I will no longer life my life for other people or for the wrong reasons. I'm no longer letting my real life pass me by. I hope this finds you all well and I wish you all the most high blessings and love. Both supporters and haters, I love all you guys. No Homo.
This post originally appeared on FREEdom Of Speech and is republished here with permission.
Performance - Film
Eva Reign Anything's Possible
Stephanie Hsu Everything Everywhere All At Once
Janelle Monáe Glass Onion: A Knives Out Mystery
Billy Eichner Bros
Conrad Ricamora Fire Island
Jeremy Pope The Inspection
Jamie Clayton Hellraiser
Troye Sivan Three Months
Amandla Stenberg Bodies Bodies Bodies
Ben Aldridge Spoiler Alert
Doja Cat is our premiere gender critic
bop after bop
Tyler Posey puckering up, Jordy's 'absolute' jam & more: Your weekly bop roundup
tops of sundance
Ben Whishaw shows his sexy side (and backside) in this intimate and honest Sundance favorite
TikTok priest says he 'went to hell' and saw men on all fours listening to Rihanna songs
serving face
Dylan Mulvaney unveils her post-surgery visage in stunning "face reveal" video
armchuleta
David Archuleta enters his thirst trap era just in time for #FlexFriday