diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp --- a/src/node/blockstorage.cpp +++ b/src/node/blockstorage.cpp @@ -600,9 +600,22 @@ bool finalize_undo = false; if (!fKnown) { - while (m_blockfile_info[nFile].nSize + nAddSize >= - (gArgs.GetBoolArg("-fastprune", false) ? 0x10000 /* 64kb */ - : MAX_BLOCKFILE_SIZE)) { + unsigned int max_blockfile_size{MAX_BLOCKFILE_SIZE}; + // Use smaller blockfiles in test-only -fastprune mode - but avoid + // the possibility of having a block not fit into the block file. + if (gArgs.GetBoolArg("-fastprune", false)) { + max_blockfile_size = 0x10000; // 64kiB + if (nAddSize >= max_blockfile_size) { + // dynamically adjust the blockfile size to be larger than the + // added size + max_blockfile_size = nAddSize + 1; + } + } + // TODO: we will also need to dynamically adjust the blockfile size + // or raise MAX_BLOCKFILE_SIZE when we reach block sizes larger than + // 128 MiB + assert(nAddSize < max_blockfile_size); + while (m_blockfile_info[nFile].nSize + nAddSize >= max_blockfile_size) { // when the undo file is keeping up with the block file, we want to // flush it explicitly when it is lagging behind (more blocks arrive // than are being connected), we let the undo block write case diff --git a/test/functional/feature_fastprune.py b/test/functional/feature_fastprune.py new file mode 100644 --- /dev/null +++ b/test/functional/feature_fastprune.py @@ -0,0 +1,28 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +"""Test fastprune mode.""" +from test_framework.test_framework import BitcoinTestFramework +from test_framework.txtools import pad_tx +from test_framework.util import assert_equal +from test_framework.wallet import MiniWallet + + +class FeatureFastpruneTest(BitcoinTestFramework): + def set_test_params(self): + self.num_nodes = 1 + self.extra_args = [["-fastprune"]] + + def run_test(self): + self.log.info("ensure that large blocks don't crash or freeze in -fastprune") + wallet = MiniWallet(self.nodes[0]) + tx = wallet.create_self_transfer()["tx"] + pad_tx(tx, 0x10001) + self.generateblock( + self.nodes[0], output="raw(55)", transactions=[tx.serialize().hex()] + ) + assert_equal(self.nodes[0].getblockcount(), 201) + + +if __name__ == "__main__": + FeatureFastpruneTest().main()