aboutsummaryrefslogtreecommitdiff
path: root/src/rpc
diff options
context:
space:
mode:
authorAndrew Chow <github@achow101.com>2022-10-26 11:20:13 -0400
committerAndrew Chow <github@achow101.com>2022-10-26 11:27:31 -0400
commit88502ecf08c960864ff0c6ddedcd44ef50a4028d (patch)
tree3caea4f3c3c9a2228549444ff7be945a830701a1 /src/rpc
parent48af307481af3b3e9455596b515e8ecb001672ef (diff)
parent5826bf546e83478947edbdf49978414f0b69eb1a (diff)
downloadbitcoin-88502ecf08c960864ff0c6ddedcd44ef50a4028d.tar.xz
Merge bitcoin/bitcoin#23927: rpc: Pruning nodes can not fetch blocks before syncing past their height
5826bf546e83478947edbdf49978414f0b69eb1a test: Add test for getblockfrompeer on syncing pruned nodes (Fabian Jahr) 7fa851fba8570ef256317f7d5759aa3de9088bf1 rpc: Pruned nodes can not fetch unsynced blocks (Fabian Jahr) Pull request description: This PR prevents `getblockfrompeer` from getting used on blocks that the node has not synced past yet if the node is in running in prune mode. ### Problem While a node is still catching up to the tip that it is aware of via the headers, the user can currently use to fetch blocks close to or at the tip. These blocks are stored in the block/rev file that otherwise contains blocks the node is receiving as part of the syncing process. This creates a problem for pruned nodes: The files containing a fetched block are not pruned during syncing because they contain a block close to the tip. This means the entire file (~130MB) will not be pruned until the tip has moved on far enough from the fetched block. In extreme cases with heavy pruning (like 550) and multiple blocks being fetched this could mean that the disc usage far exceeds what the user expects, potentially running out of space. ### Approach There would be certainly other approaches that could fix the problem while still allowing the current behavior, but all of the ideas I came up with seemed like overkill for a niche problem on a new RPC where it's still unclear how and how much it will be used. ### Testing So far I did not see a simple enough way to test this I am still looking into it and if it's complex will potentially add it in a follow-up. What would be needed is a way to have a node fetch headers but not sync the blocks yet, that seems like a pattern that could be generally useful. To manually reproduce the problematic behavior: 1. Start a node with current `master` with `-prune=550` and an empty/new datadir, Testnet and Mainnet should both work. 2. While the node is syncing run `getblockfrompeer` on the current tip and a few other recent blocks. 3. Go to your datadir and observe the blocks folder: There should be a few full `blk*.dat` and `rev*.dat` files that are not being pruned. When you "pinned" a few of these files the blocks folder should be significantly above the target size of 550MB. ACKs for top commit: Sjors: utACK 5826bf546e83478947edbdf49978414f0b69eb1a achow101: ACK 5826bf546e83478947edbdf49978414f0b69eb1a aureleoules: tACK 5826bf546e83478947edbdf49978414f0b69eb1a Tree-SHA512: aa3f477ec755a9df2331c047cb10b3cd08292522bf6ad7a36a7ea36d7eba4894b84de8bd23003c9baea5ac0c53b77142c3c2819ae7528cece9d10a0d06c850d8
Diffstat (limited to 'src/rpc')
-rw-r--r--src/rpc/blockchain.cpp6
1 files changed, 6 insertions, 0 deletions
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index f8ba822f54..39ee95b939 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -459,6 +459,12 @@ static RPCHelpMan getblockfrompeer()
throw JSONRPCError(RPC_MISC_ERROR, "Block header missing");
}
+ // Fetching blocks before the node has syncing past their height can prevent block files from
+ // being pruned, so we avoid it if the node is in prune mode.
+ if (index->nHeight > chainman.ActiveChain().Tip()->nHeight && node::fPruneMode) {
+ throw JSONRPCError(RPC_MISC_ERROR, "In prune mode, only blocks that the node has already synced previously can be fetched from a peer");
+ }
+
const bool block_has_data = WITH_LOCK(::cs_main, return index->nStatus & BLOCK_HAVE_DATA);
if (block_has_data) {
throw JSONRPCError(RPC_MISC_ERROR, "Block already downloaded");