Merge bitcoin/bitcoin#31674: init: Lock blocksdir in addition to datadir

2656a5658c tests: add a test for the new blocksdir lock (Cory Fields)
bdc0a68e67 init: lock blocksdir in addition to datadir (Cory Fields)
cabb2e5c24 refactor: introduce a more general LockDirectories for init (Cory Fields)
1db331ba76 init: allow a new xor key to be written if the blocksdir is newly created (Cory Fields)

Pull request description:

  This probably should've been included in #12653 when `-blocksdir` was introduced. Credit TheCharlatan for noticing that it's missing.

  This guards against 2 processes running with separate datadirs but the same blocksdir. I didn't add `walletdir` as I assume sqlite has us covered there.

  It's not likely to happen currently, but may be more relevant in the future with applications using the kernel. Note that the kernel does not currently do any dir locking, but it should.

ACKs for top commit:
  maflcko:
    review ACK 2656a5658c 🏼
  kevkevinpal:
    ACK [2656a56](2656a5658c)
  achow101:
    ACK 2656a5658c
  tdb3:
    Code review and light test ACK 2656a5658c

Tree-SHA512: 3ba17dc670126adda104148e14d1322ea4f67d671c84aaa9c08c760ef778ca1936832c0dc843cd6367e09939f64c6f0a682b0fa23a5967e821b899dff1fff961
This commit is contained in:
Ava Chow
2025-01-24 18:15:00 -05:00
6 changed files with 46 additions and 24 deletions

View File

@@ -1117,7 +1117,19 @@ static auto InitBlocksdirXorKey(const BlockManager::Options& opts)
// size of the XOR-key file.
std::array<std::byte, 8> xor_key{};
if (opts.use_xor && fs::is_empty(opts.blocks_dir)) {
// Consider this to be the first run if the blocksdir contains only hidden
// files (those which start with a .). Checking for a fully-empty dir would
// be too aggressive as a .lock file may have already been written.
bool first_run = true;
for (const auto& entry : fs::directory_iterator(opts.blocks_dir)) {
const std::string path = fs::PathToString(entry.path().filename());
if (!entry.is_regular_file() || !path.starts_with('.')) {
first_run = false;
break;
}
}
if (opts.use_xor && first_run) {
// Only use random fresh key when the boolean option is set and on the
// very first start of the program.
FastRandomContext{}.fillrand(xor_key);