-
Notifications
You must be signed in to change notification settings - Fork 37.7k
test: add functional test for XORed block/undo files (-blocksxor
option)
#30657
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. Code CoverageFor detailed information about the code coverage, see the test coverage report. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. |
-blockxor
option)-blocksxor
option)
86b80ce
to
fb2ea1e
Compare
fb2ea1e
to
faa1b9b
Compare
Concept ACK |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approach ACK.
Nice additions.
Left a comment and a nit.
@@ -311,6 +311,13 @@ def sha256sum_file(filename): | |||
return h.digest() | |||
|
|||
|
|||
def util_xor(data, key, *, offset): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitty nit: Since this is being moved, could update to use a more descriptive function name (e.g. xor_bytes
). Feel free to ignore.
self.start_node(0, extra_args=['-blocksxor=0']) | ||
# checklevel=2 -> verify block validity + undo data | ||
# nblocks=0 -> verify all blocks | ||
node.verifychain(checklevel=2, nblocks=0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The help for -blocksxor
mentions The created XOR-key will be zeros for an existing blocksdir or when
-blocksxor=0 is set
.
After the verifychain
, could test that a new xor.dat
is created (consisting of all zeros) when the node is started with no xor.dat
and with -blocksxor=0
. Something like:
assert read_xor_key(node=node) == bytes(8)
or maybe lift NUM_XOR_BYTES
out of read_xor_key
to enable
assert read_xor_key(node=node) == bytes(NUM_XOR_BYTES)
or even add a constant in util.py
NULL_BLK_XOR_KEY = bytes(NUM_XOR_BYTES) # all-0 xor key
to enable
assert read_xor_key(node=node) == NULL_BLK_XOR_KEY
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK faa1b9b
@@ -508,6 +515,12 @@ def check_node_connections(*, node, num_in, num_out): | |||
assert_equal(info["connections_out"], num_out) | |||
|
|||
|
|||
def read_xor_key(*, node): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Any reason to make this a global function and pass a node to it? Seems clearer to just make it a member function on the node, like blocks_path()
, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Any reason to make this a global function and pass a node to it? Seems clearer to just make it a member function on the node, like
blocks_path()
, no?
No strong reason. Personally I first look into util.py for helpers and tend to forget that there are also some implemented as TestNode
methods, but I agree that the latter makes sense. Could be picked up in a follow-up, e.g. #30669.
self.log.info("Check that restarting with 'blocksxor=0' fails if XOR key is present") | ||
node.assert_start_raises_init_error(['-blocksxor=0'], | ||
'The blocksdir XOR-key can not be disabled when a random key was already stored!', | ||
match=ErrorMatch.PARTIAL_REGEX) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This fails for me locally, because somehow I have 0000000000000000 as my xor key... but it fails consistently. Unsure if that's supposed to be possible?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe a leftover previous bitcoind
was used? Can you try make clean
, just to double check? Otherwise, the combined log could be useful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a if (opts.use_xor) assert(xor_key != decltype(xor_key){});
which hit, so not an old bitcoind. Attaching combined log.
node0 2024-08-15T16:40:41.093882Z [init] [node/blockstorage.cpp:1184] [InitBlocksdirXorKey] Using obfuscation key for blocksdir *.dat files (/tmp/bitcoin_func_test__c38k83u/node0/regtest/blocks): '0000000000000000'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a
if (opts.use_xor) assert(xor_key != decltype(xor_key){});
which hit, so not an old bitcoind. Attaching combined log.
Can you also print/log/debug the result of fs::is_empty(opts.blocks_dir)
and fs::exists(xor_key_path)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah interesting, fs::is_empty(opts.blocks_dir)
is 0
^so clearly this isn't a problem with the test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess fs::is_empty(opts.blocks_dir)
could be replaced by not fs::exists("blk0000.dat")
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fwiw the sleepy version doesn't seem to use 0 as xor key when I start a node (tried a few times with mainnet, regtest) normally. I also never have problems when I use a non-tmp folder. So maybe your guess about temp directory paranormal activity is correct.
Going to merge this test since there's not a problem with it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Found this here because I saw #30833 and it got me to look into blocksxor
for the first time. I see the same failures @glozow describes (also on macos) and I can confirm the findings here about the use of the temp folders because it does not happen when the test uses a clean chain, e.g. using a clean chain like this made the test robust for me: fjahr@ef00b8e I didn't find anything new beyond that so far but I thought it should be noted that it's not on @glozow 's machine alone.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
made the test robust for me: fjahr@ef00b8e
Thanks for checking. Using a clean chain means that the cache won't be used, which normally lives on the storage unit where the build dir lives, so only the temp dir should be used. However, given the prior result that a non-tmp folder was generally fine, I would have expected the opposite result (Test would be less fragile by using the persisted cache on a non-tmp dir). However, I don't have a macOS to test this, so I don't know for sure what is going on. Also, if this "fixes" the test, it will just silence the symptoms, but it may be better to fix the underlying issue itself. The suggested replacement in #30657 (comment) may be a good try.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess fs::is_empty(opts.blocks_dir) could be replaced by not fs::exists("blk0000.dat")?
I think that alone wouldn't work if the user upgrades a pruned node to v28?
Anyway, I was going to revisit this today but I simply don't see the failures anymore currently 🤷♂️ I will get back to it if I see them occur again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested ACK faa1b9b
ACK faa1b9b |
e1d5dd7 test: check xor.dat recreated when missing (tdb3) d161096 test: add null block xor key (tdb3) 1ad999b refactor: lift NUM_XOR_BYTES (tdb3) d839958 refactor: move read_xor_key() to TestNode (tdb3) d43948c refactor: use unlink rather than os.remove (tdb3) c8176f7 test: add blocks_key_path (tdb3) Pull request description: Builds on PR #30657. Refactors `read_xor_key()` from `util.py` to `test_node.py` (comment #30657 (comment)) Adds a check that `xor.dat` is created when missing (comment #30657 (comment)) Help states: ``` -blocksxor Whether an XOR-key applies to blocksdir *.dat files. The created XOR-key will be zeros for an existing blocksdir or when `-blocksxor=0` is set, and random for a freshly initialized blocksdir. (default: 1) ``` ACKs for top commit: maflcko: ACK e1d5dd7 achow101: ACK e1d5dd7 theStack: re-ACK e1d5dd7 brunoerg: reACK e1d5dd7 Tree-SHA512: 325912ef646ec88e0a58e1ece263a2b04cbc06497e8fe5fcd603e509e80c6bcf84b09dd52dfac60e23013f07fc2b2f6db851ed0598649c3593f452c4a1424bd9
This PR adds a dedicated functional test for XORed block data/undo file support (bitcoind option
-blocksxor
, see PR #28052). In order to verify that the XOR pattern has been applied, the {blk,rev}*.dat files are rewritten un-XORed manually by the test while the node is shut down; the node is then started again with-blocksxor=0
, and both the data and undo files are verified via theverifychain
RPC (with checklevel=2). Note that starting bitcoind with-blocksxor=0
fails if a xor key is present already, which is also tested explicitly.Fixes #30599.