Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,12 @@ if(ENABLE_WALLET)
if(VCPKG_TARGET_TRIPLET)
# Use of the `unofficial::` namespace is a vcpkg package manager convention.
find_package(unofficial-sqlite3 CONFIG REQUIRED)
add_library(SQLite3::SQLite3 ALIAS unofficial::sqlite3::sqlite3)
else()
find_package(SQLite3 3.7.17 REQUIRED)
if(NOT TARGET SQLite3::SQLite3) # CMake < 4.3
add_library(SQLite3::SQLite3 ALIAS SQLite::SQLite3)
endif()
endif()
endif()
cmake_dependent_option(BUILD_WALLET_TOOL "Build bitcoin-wallet tool." ${BUILD_TESTS} "ENABLE_WALLET" OFF)
Expand Down
17 changes: 11 additions & 6 deletions src/kernel/coinstats.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,8 @@ static void ApplyStats(CCoinsStats& stats, const std::map<uint32_t, Coin>& outpu

//! Calculate statistics about the unspent transaction output set
template <typename T>
static bool ComputeUTXOStats(CCoinsView* view, CCoinsStats& stats, T hash_obj, const std::function<void()>& interruption_point)
static bool ComputeUTXOStats(CCoinsView* view, CCoinsStats& stats, T hash_obj, const std::function<void()>& interruption_point, std::unique_ptr<CCoinsViewCursor> pcursor)
{
std::unique_ptr<CCoinsViewCursor> pcursor(view->Cursor());
assert(pcursor);

Txid prevkey;
Expand Down Expand Up @@ -149,21 +148,27 @@ static bool ComputeUTXOStats(CCoinsView* view, CCoinsStats& stats, T hash_obj, c

std::optional<CCoinsStats> ComputeUTXOStats(CoinStatsHashType hash_type, CCoinsView* view, node::BlockManager& blockman, const std::function<void()>& interruption_point)
{
CBlockIndex* pindex = WITH_LOCK(::cs_main, return blockman.LookupBlockIndex(view->GetBestBlock()));
std::unique_ptr<CCoinsViewCursor> pcursor;
CBlockIndex* pindex;
{
LOCK(::cs_main);
pcursor = view->Cursor();
pindex = blockman.LookupBlockIndex(pcursor->GetBestBlock());
}
CCoinsStats stats{Assert(pindex)->nHeight, pindex->GetBlockHash()};

bool success = [&]() -> bool {
switch (hash_type) {
case(CoinStatsHashType::HASH_SERIALIZED): {
HashWriter ss{};
return ComputeUTXOStats(view, stats, ss, interruption_point);
return ComputeUTXOStats(view, stats, ss, interruption_point, std::move(pcursor));
}
case(CoinStatsHashType::MUHASH): {
MuHash3072 muhash;
return ComputeUTXOStats(view, stats, muhash, interruption_point);
return ComputeUTXOStats(view, stats, muhash, interruption_point, std::move(pcursor));
}
case(CoinStatsHashType::NONE): {
return ComputeUTXOStats(view, stats, nullptr, interruption_point);
return ComputeUTXOStats(view, stats, nullptr, interruption_point, std::move(pcursor));
}
} // no default case, so the compiler can warn about missing cases
assert(false);
Expand Down
8 changes: 4 additions & 4 deletions src/rpc/blockchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1080,7 +1080,6 @@ static RPCHelpMan gettxoutsetinfo()
LOCK(::cs_main);
coins_view = &active_chainstate.CoinsDB();
blockman = &active_chainstate.m_blockman;
pindex = blockman->LookupBlockIndex(coins_view->GetBestBlock());
}

if (!request.params[1].isNull()) {
Expand All @@ -1104,7 +1103,7 @@ static RPCHelpMan gettxoutsetinfo()

// If a specific block was requested and the index has already synced past that height, we can return the
// data already even though the index is not fully synced yet.
if (pindex->nHeight > summary.best_block_height) {
if (pindex && pindex->nHeight > summary.best_block_height) {
throw JSONRPCError(RPC_INTERNAL_ERROR, strprintf("Unable to get data because coinstatsindex is still syncing. Current height: %d", summary.best_block_height));
}
}
Expand All @@ -1130,8 +1129,9 @@ static RPCHelpMan gettxoutsetinfo()
ret.pushKV("disk_size", stats.nDiskSize);
} else {
CCoinsStats prev_stats{};
if (pindex->nHeight > 0) {
const std::optional<CCoinsStats> maybe_prev_stats = GetUTXOStats(coins_view, *blockman, hash_type, node.rpc_interruption_point, pindex->pprev, index_requested);
if (stats.nHeight > 0) {
const CBlockIndex& block_index = *CHECK_NONFATAL(WITH_LOCK(::cs_main, return blockman->LookupBlockIndex(stats.hashBlock)));
const std::optional<CCoinsStats> maybe_prev_stats = GetUTXOStats(coins_view, *blockman, hash_type, node.rpc_interruption_point, block_index.pprev, index_requested);
if (!maybe_prev_stats) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "Unable to read UTXO set");
}
Expand Down
3 changes: 1 addition & 2 deletions src/wallet/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ target_link_libraries(bitcoin_wallet
PRIVATE
core_interface
bitcoin_common
$<TARGET_NAME_IF_EXISTS:unofficial::sqlite3::sqlite3>
$<TARGET_NAME_IF_EXISTS:SQLite::SQLite3>
SQLite3::SQLite3
univalue
Boost::headers
$<TARGET_NAME_IF_EXISTS:USDT::headers>
Expand Down
22 changes: 5 additions & 17 deletions test/functional/feature_assumeutxo.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
assert_equal,
assert_not_equal,
assert_raises_rpc_error,
dumb_sync_blocks,
ensure_for,
sha256sum_file,
try_rpc,
Expand Down Expand Up @@ -631,30 +632,17 @@ def check_tx_counts(final: bool) -> None:

PAUSE_HEIGHT = FINAL_HEIGHT - 40

self.log.info("Restarting node to stop at height %d", PAUSE_HEIGHT)
self.restart_node(1, extra_args=[
f"-stopatheight={PAUSE_HEIGHT}", *self.extra_args[1]])

# Upon restart during snapshot tip sync, the node must remain in 'limited' mode.
self.log.info(f"Sync node up to height {PAUSE_HEIGHT}")
# During snapshot tip sync, the node must remain in 'limited' mode.
self.assert_only_network_limited_service(n1)

# Finally connect the nodes and let them sync.
#
# Set `wait_for_connect=False` to avoid a race between performing connection
# assertions and the -stopatheight tripping.
self.connect_nodes(0, 1, wait_for_connect=False)

n1.wait_until_stopped(timeout=5)
dumb_sync_blocks(src=n0, dst=n1, height=PAUSE_HEIGHT)

self.log.info("Checking that blocks are segmented on disk")
assert self.has_blockfile(n1, "00000"), "normal blockfile missing"
assert self.has_blockfile(n1, "00001"), "assumed blockfile missing"
assert not self.has_blockfile(n1, "00002"), "too many blockfiles"

self.log.info("Restarted node before snapshot validation completed, reloading...")
self.restart_node(1, extra_args=self.extra_args[1])

# Upon restart, the node must remain in 'limited' mode
# The node must remain in 'limited' mode
self.assert_only_network_limited_service(n1)

# Send snapshot block to n1 out of order. This makes the test less
Expand Down
2 changes: 1 addition & 1 deletion test/functional/test_framework/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -729,7 +729,7 @@ def dumb_sync_blocks(*, src, dst, height=None):
height = height or src.getblockcount()
for i in range(dst.getblockcount() + 1, height + 1):
block_hash = src.getblockhash(i)
block = src.getblock(blockhash=block_hash, verbose=0)
block = src.getblock(blockhash=block_hash, verbosity=0)
dst.submitblock(block)
assert_equal(dst.getblockcount(), height)

Expand Down
Loading