chainparams: add blockhash to AssumeutxoData

This allows us to reference assumeutxo configuration by blockhash as
well as height; this is helpful in future changes when we want to
reference assumeutxo configurations before the block index is loaded.
This commit is contained in:
James O'Beirne 2023-05-25 13:05:27 -04:00
parent c711ca186f
commit 434495a8c1
7 changed files with 49 additions and 49 deletions

View file

@ -172,8 +172,8 @@ public:
}
};
m_assumeutxo_data = MapAssumeutxo{
// TODO to be specified in a future patch.
m_assumeutxo_data = {
// TODO to be specified in a future patch.
};
chainTxData = ChainTxData{
@ -266,7 +266,7 @@ public:
}
};
m_assumeutxo_data = MapAssumeutxo{
m_assumeutxo_data = {
// TODO to be specified in a future patch.
};
@ -477,14 +477,12 @@ public:
}
};
m_assumeutxo_data = MapAssumeutxo{
m_assumeutxo_data = {
{
110,
{AssumeutxoHash{uint256S("0x1ebbf5850204c0bdb15bf030f47c7fe91d45c44c712697e4509ba67adb01c618")}, 110},
},
{
200,
{AssumeutxoHash{uint256S("0x51c8d11d8b5c1de51543c579736e786aa2736206d1e11e627568029ce092cf62")}, 200},
.height = 110,
.hash_serialized = AssumeutxoHash{uint256S("0x1ebbf5850204c0bdb15bf030f47c7fe91d45c44c712697e4509ba67adb01c618")},
.nChainTx = 110,
.blockhash = uint256S("0x696e92821f65549c7ee134edceeeeaaa4105647a3c4fd9f298c0aec0ab50425c")
},
};

View file

@ -12,6 +12,7 @@
#include <uint256.h>
#include <util/chaintype.h>
#include <util/hash_type.h>
#include <util/vector.h>
#include <cstdint>
#include <iterator>
@ -44,17 +45,21 @@ struct AssumeutxoHash : public BaseHash<uint256> {
* as valid.
*/
struct AssumeutxoData {
int height;
//! The expected hash of the deserialized UTXO set.
const AssumeutxoHash hash_serialized;
AssumeutxoHash hash_serialized;
//! Used to populate the nChainTx value, which is used during BlockManager::LoadBlockIndex().
//!
//! We need to hardcode the value here because this is computed cumulatively using block data,
//! which we do not necessarily have at the time of snapshot load.
const unsigned int nChainTx;
};
unsigned int nChainTx;
using MapAssumeutxo = std::map<int, const AssumeutxoData>;
//! The hash of the base block for this snapshot. Used to refer to assumeutxo data
//! prior to having a loaded blockindex.
uint256 blockhash;
};
/**
* Holds various statistics on transactions within a chain. Used to estimate
@ -114,9 +119,14 @@ public:
const std::vector<uint8_t>& FixedSeeds() const { return vFixedSeeds; }
const CCheckpointData& Checkpoints() const { return checkpointData; }
//! Get allowed assumeutxo configuration.
//! @see ChainstateManager
const MapAssumeutxo& Assumeutxo() const { return m_assumeutxo_data; }
std::optional<AssumeutxoData> AssumeutxoForHeight(int height) const
{
return FindFirst(m_assumeutxo_data, [&](const auto& d) { return d.height == height; });
}
std::optional<AssumeutxoData> AssumeutxoForBlockhash(const uint256& blockhash) const
{
return FindFirst(m_assumeutxo_data, [&](const auto& d) { return d.blockhash == blockhash; });
}
const ChainTxData& TxData() const { return chainTxData; }
@ -169,7 +179,7 @@ protected:
bool fDefaultConsistencyChecks;
bool m_is_mockable_chain;
CCheckpointData checkpointData;
MapAssumeutxo m_assumeutxo_data;
std::vector<AssumeutxoData> m_assumeutxo_data;
ChainTxData chainTxData;
};

View file

@ -289,10 +289,10 @@ struct SnapshotTestSetup : TestChain100Setup {
BOOST_CHECK(!chainman.ActiveChain().Genesis()->IsAssumedValid());
}
const AssumeutxoData& au_data = *ExpectedAssumeutxo(snapshot_height, ::Params());
const auto& au_data = ::Params().AssumeutxoForHeight(snapshot_height);
const CBlockIndex* tip = WITH_LOCK(chainman.GetMutex(), return chainman.ActiveTip());
BOOST_CHECK_EQUAL(tip->nChainTx, au_data.nChainTx);
BOOST_CHECK_EQUAL(tip->nChainTx, au_data->nChainTx);
// To be checked against later when we try loading a subsequent snapshot.
uint256 loaded_snapshot_blockhash{*chainman.SnapshotBlockhash()};

View file

@ -132,17 +132,17 @@ BOOST_AUTO_TEST_CASE(test_assumeutxo)
std::vector<int> bad_heights{0, 100, 111, 115, 209, 211};
for (auto empty : bad_heights) {
const auto out = ExpectedAssumeutxo(empty, *params);
const auto out = params->AssumeutxoForHeight(empty);
BOOST_CHECK(!out);
}
const auto out110 = *ExpectedAssumeutxo(110, *params);
const auto out110 = *params->AssumeutxoForHeight(110);
BOOST_CHECK_EQUAL(out110.hash_serialized.ToString(), "1ebbf5850204c0bdb15bf030f47c7fe91d45c44c712697e4509ba67adb01c618");
BOOST_CHECK_EQUAL(out110.nChainTx, 110U);
const auto out210 = *ExpectedAssumeutxo(200, *params);
BOOST_CHECK_EQUAL(out210.hash_serialized.ToString(), "51c8d11d8b5c1de51543c579736e786aa2736206d1e11e627568029ce092cf62");
BOOST_CHECK_EQUAL(out210.nChainTx, 200U);
const auto out110_2 = *params->AssumeutxoForBlockhash(uint256S("0x696e92821f65549c7ee134edceeeeaaa4105647a3c4fd9f298c0aec0ab50425c"));
BOOST_CHECK_EQUAL(out110_2.hash_serialized.ToString(), "1ebbf5850204c0bdb15bf030f47c7fe91d45c44c712697e4509ba67adb01c618");
BOOST_CHECK_EQUAL(out110_2.nChainTx, 110U);
}
BOOST_AUTO_TEST_SUITE_END()

View file

@ -5,7 +5,9 @@
#ifndef BITCOIN_UTIL_VECTOR_H
#define BITCOIN_UTIL_VECTOR_H
#include <functional>
#include <initializer_list>
#include <optional>
#include <type_traits>
#include <utility>
#include <vector>
@ -67,4 +69,15 @@ inline void ClearShrink(V& v) noexcept
V{}.swap(v);
}
template<typename V, typename L>
inline std::optional<V> FindFirst(const std::vector<V>& vec, const L fnc)
{
for (const auto& el : vec) {
if (fnc(el)) {
return el;
}
}
return std::nullopt;
}
#endif // BITCOIN_UTIL_VECTOR_H

View file

@ -5099,18 +5099,6 @@ Chainstate& ChainstateManager::InitializeChainstate(CTxMemPool* mempool)
return *m_active_chainstate;
}
const AssumeutxoData* ExpectedAssumeutxo(
const int height, const CChainParams& chainparams)
{
const MapAssumeutxo& valid_assumeutxos_map = chainparams.Assumeutxo();
const auto assumeutxo_found = valid_assumeutxos_map.find(height);
if (assumeutxo_found != valid_assumeutxos_map.end()) {
return &assumeutxo_found->second;
}
return nullptr;
}
[[nodiscard]] static bool DeleteCoinsDBFromDisk(const fs::path db_path, bool is_snapshot)
EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
{
@ -5295,7 +5283,7 @@ bool ChainstateManager::PopulateAndValidateSnapshot(
CBlockIndex* snapshot_start_block = WITH_LOCK(::cs_main, return m_blockman.LookupBlockIndex(base_blockhash));
if (!snapshot_start_block) {
// Needed for ComputeUTXOStats and ExpectedAssumeutxo to determine the
// Needed for ComputeUTXOStats to determine the
// height and to avoid a crash when base_blockhash.IsNull()
LogPrintf("[snapshot] Did not find snapshot start blockheader %s\n",
base_blockhash.ToString());
@ -5303,7 +5291,7 @@ bool ChainstateManager::PopulateAndValidateSnapshot(
}
int base_height = snapshot_start_block->nHeight;
auto maybe_au_data = ExpectedAssumeutxo(base_height, GetParams());
const auto& maybe_au_data = GetParams().AssumeutxoForHeight(base_height);
if (!maybe_au_data) {
LogPrintf("[snapshot] assumeutxo height in snapshot metadata not recognized "
@ -5572,7 +5560,7 @@ SnapshotCompletionResult ChainstateManager::MaybeCompleteSnapshotValidation()
CCoinsViewDB& ibd_coins_db = m_ibd_chainstate->CoinsDB();
m_ibd_chainstate->ForceFlushStateToDisk();
auto maybe_au_data = ExpectedAssumeutxo(curr_height, m_options.chainparams);
const auto& maybe_au_data = m_options.chainparams.AssumeutxoForHeight(curr_height);
if (!maybe_au_data) {
LogPrintf("[snapshot] assumeutxo data not found for height "
"(%d) - refusing to validate snapshot\n", curr_height);

View file

@ -1242,15 +1242,6 @@ bool DeploymentEnabled(const ChainstateManager& chainman, DEP dep)
return DeploymentEnabled(chainman.GetConsensus(), dep);
}
/**
* 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);
/** Identifies blocks that overwrote an existing coinbase output in the UTXO set (see BIP30) */
bool IsBIP30Repeat(const CBlockIndex& block_index);