// Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2022 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_NODE_UTXO_SNAPSHOT_H #define BITCOIN_NODE_UTXO_SNAPSHOT_H #include #include #include #include #include #include #include #include #include #include #include // UTXO set snapshot magic bytes static constexpr std::array SNAPSHOT_MAGIC_BYTES = {'u', 't', 'x', 'o', 0xff}; class Chainstate; namespace node { //! Metadata describing a serialized version of a UTXO set from which an //! assumeutxo Chainstate can be constructed. class SnapshotMetadata { const uint16_t m_version{1}; const std::set m_supported_versions{1}; public: //! The hash of the block that reflects the tip of the chain for the //! UTXO set contained in this snapshot. uint256 m_base_blockhash; uint32_t m_base_blockheight; //! The number of coins in the UTXO set contained in this snapshot. Used //! during snapshot load to estimate progress of UTXO set reconstruction. uint64_t m_coins_count = 0; SnapshotMetadata() { } SnapshotMetadata( const uint256& base_blockhash, const int base_blockheight, uint64_t coins_count) : m_base_blockhash(base_blockhash), m_base_blockheight(base_blockheight), m_coins_count(coins_count) { } template inline void Serialize(Stream& s) const { s << SNAPSHOT_MAGIC_BYTES; s << m_version; s << Params().MessageStart(); s << m_base_blockheight; s << m_base_blockhash; s << m_coins_count; } template inline void Unserialize(Stream& s) { // Read the snapshot magic bytes std::array snapshot_magic; s >> snapshot_magic; if (snapshot_magic != SNAPSHOT_MAGIC_BYTES) { throw std::ios_base::failure("Invalid UTXO set snapshot magic bytes. Please check if this is indeed a snapshot file or if you are using an outdated snapshot format."); } // Read the version uint16_t version; s >> version; if (m_supported_versions.find(version) == m_supported_versions.end()) { throw std::ios_base::failure(strprintf("Version of snapshot %s does not match any of the supported versions.", version)); } // Read the network magic (pchMessageStart) MessageStartChars message; s >> message; if (!std::equal(message.begin(), message.end(), Params().MessageStart().data())) { auto metadata_network = GetNetworkForMagic(message); if (metadata_network) { std::string network_string{ChainTypeToString(metadata_network.value())}; throw std::ios_base::failure(strprintf("The network of the snapshot (%s) does not match the network of this node (%s).", network_string, Params().GetChainTypeString())); } else { throw std::ios_base::failure("This snapshot has been created for an unrecognized network. This could be a custom signet, a new testnet or possibly caused by data corruption."); } } s >> m_base_blockheight; s >> m_base_blockhash; s >> m_coins_count; } }; //! The file in the snapshot chainstate dir which stores the base blockhash. This is //! needed to reconstruct snapshot chainstates on init. //! //! Because we only allow loading a single snapshot at a time, there will only be one //! chainstate directory with this filename present within it. const fs::path SNAPSHOT_BLOCKHASH_FILENAME{"base_blockhash"}; //! Write out the blockhash of the snapshot base block that was used to construct //! this chainstate. This value is read in during subsequent initializations and //! used to reconstruct snapshot-based chainstates. bool WriteSnapshotBaseBlockhash(Chainstate& snapshot_chainstate) EXCLUSIVE_LOCKS_REQUIRED(::cs_main); //! Read the blockhash of the snapshot base block that was used to construct the //! chainstate. std::optional ReadSnapshotBaseBlockhash(fs::path chaindir) EXCLUSIVE_LOCKS_REQUIRED(::cs_main); //! Suffix appended to the chainstate (leveldb) dir when created based upon //! a snapshot. constexpr std::string_view SNAPSHOT_CHAINSTATE_SUFFIX = "_snapshot"; //! Return a path to the snapshot-based chainstate dir, if one exists. std::optional FindSnapshotChainstateDir(const fs::path& data_dir); } // namespace node #endif // BITCOIN_NODE_UTXO_SNAPSHOT_H