-
Notifications
You must be signed in to change notification settings - Fork 36.5k
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
Default to NODE_WITNESS in nLocalServices #21090
Conversation
0ef4395
to
743286d
Compare
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
d831e71 [validation] RewindBlockIndex no longer needed (Dhruv Mehta) Pull request description: Closes #17862 Context from [original comment](#17862 (comment)) (minor edits): `RewindBlockIndex()` is a mechanism to allow nodes to be upgraded after segwit activation, while still keeping their chainstate/datadir in a consistent state. It works as follows: - A pre-segwit (i.e. v0.13.0 or older) node is running. - Segwit activates. The pre-segwit node remains sync'ed to the tip, but is not enforcing the new segwit rules. - The user upgrades the node to a segwit-aware version (v0.13.1 or newer). - On startup, in `AppInitMain()`, `RewindBlockIndex()` is called. This walks the chain backwards from the tip, disconnecting and erasing blocks that from after segwit activation that weren't validated with segwit rules. - those blocks are then redownloaded (with witness data) and validated with segwit rules. This logic probably isn't required any more since: - Segwit activated at height 481824, when the block chain was 130GB and the total number of txs was 250 million. Today, we're at height 667704, the blockchain is over 315GB and the total number of txs is over 600 million. Even if 20% of that added data is witness data (a high estimate), then around 150GB of transactions would need to be rewound to get back to segwit activation height. It'd probably be faster to simply validate from genesis, especially since we won't be validating any scripts before the assumevalid block. It's also unclear whether rewinding 150GB of transactions would even work. It's certainly never been tested. - Bitcoin Core v0.13 is hardly used any more. https://luke.dashjr.org/programs/bitcoin/files/charts/software.html shows less than 50 nodes running it. The software was EOL on Aug 1st 2018. It's very unlikely that anyone is running 0.13 and will want to upgrade to 0.22. This PR introduces `NeedsRedownload()` which merely checks for insufficiently validated segwit blocks and requests that the user restarts the node with `-reindex`. Reindexing the block files upon restart will make the node rebuild chain state and block index from the `blk*.dat` files on disk. The node won't be able to index the blocks with `BLOCK_OPT_WITNESS`, so they will be missing from the chain and be re-downloaded, with witness data. Removing this code allows the following (done in follow-up #21090): - removal of tests using `segwitheight=-1` in `p2p_segwit.py`. - in turn, that allows us to drop support for `-segwitheight=-1`, which is only supported for that test. - that allows us to always set `NODE_WITNESS` in our local services. The only reason we don't do that is to support `-segwitheight=-1`. - that in turn allows us to drop all of the `GetLocalServices() & NODE_WITNESS` checks inside `net_processing.cpp`, since our local services would always include `NODE_WITNESS` ACKs for top commit: jnewbery: utACK d831e71 jamesob: ACK d831e71 laanwj: Cursory code review ACK d831e71. Agree with the direction of the change, thanks for simplifying the logic here. glozow: utACK d831e71 Tree-SHA512: 3eddf5121ccd081ad7f15a5c6478ef867083edc8ba0bf1ee759e87bc070ee3d2f0698a3feba8db8dc087987c8452887b6f72cff05b3e178f41cb10a515fb8053
This needs rebase now that #21009 is merged. I did my own rebase here: https://github.com/jnewbery/bitcoin/tree/pr21090.1 since I need it for #20799. Feel free to take that if it's helpful. I think it might make sense to remove the |
d831e71 [validation] RewindBlockIndex no longer needed (Dhruv Mehta) Pull request description: Closes bitcoin#17862 Context from [original comment](bitcoin#17862 (comment)) (minor edits): `RewindBlockIndex()` is a mechanism to allow nodes to be upgraded after segwit activation, while still keeping their chainstate/datadir in a consistent state. It works as follows: - A pre-segwit (i.e. v0.13.0 or older) node is running. - Segwit activates. The pre-segwit node remains sync'ed to the tip, but is not enforcing the new segwit rules. - The user upgrades the node to a segwit-aware version (v0.13.1 or newer). - On startup, in `AppInitMain()`, `RewindBlockIndex()` is called. This walks the chain backwards from the tip, disconnecting and erasing blocks that from after segwit activation that weren't validated with segwit rules. - those blocks are then redownloaded (with witness data) and validated with segwit rules. This logic probably isn't required any more since: - Segwit activated at height 481824, when the block chain was 130GB and the total number of txs was 250 million. Today, we're at height 667704, the blockchain is over 315GB and the total number of txs is over 600 million. Even if 20% of that added data is witness data (a high estimate), then around 150GB of transactions would need to be rewound to get back to segwit activation height. It'd probably be faster to simply validate from genesis, especially since we won't be validating any scripts before the assumevalid block. It's also unclear whether rewinding 150GB of transactions would even work. It's certainly never been tested. - Bitcoin Core v0.13 is hardly used any more. https://luke.dashjr.org/programs/bitcoin/files/charts/software.html shows less than 50 nodes running it. The software was EOL on Aug 1st 2018. It's very unlikely that anyone is running 0.13 and will want to upgrade to 0.22. This PR introduces `NeedsRedownload()` which merely checks for insufficiently validated segwit blocks and requests that the user restarts the node with `-reindex`. Reindexing the block files upon restart will make the node rebuild chain state and block index from the `blk*.dat` files on disk. The node won't be able to index the blocks with `BLOCK_OPT_WITNESS`, so they will be missing from the chain and be re-downloaded, with witness data. Removing this code allows the following (done in follow-up bitcoin#21090): - removal of tests using `segwitheight=-1` in `p2p_segwit.py`. - in turn, that allows us to drop support for `-segwitheight=-1`, which is only supported for that test. - that allows us to always set `NODE_WITNESS` in our local services. The only reason we don't do that is to support `-segwitheight=-1`. - that in turn allows us to drop all of the `GetLocalServices() & NODE_WITNESS` checks inside `net_processing.cpp`, since our local services would always include `NODE_WITNESS` ACKs for top commit: jnewbery: utACK d831e71 jamesob: ACK bitcoin@d831e71 laanwj: Cursory code review ACK d831e71. Agree with the direction of the change, thanks for simplifying the logic here. glozow: utACK d831e71 Tree-SHA512: 3eddf5121ccd081ad7f15a5c6478ef867083edc8ba0bf1ee759e87bc070ee3d2f0698a3feba8db8dc087987c8452887b6f72cff05b3e178f41cb10a515fb8053
e889ad4
to
117ae3f
Compare
Rebased against master, ready for review. @jnewbery it does make a ton of sense to extract |
bf325dd
to
f43a127
Compare
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.
Rebased with master. Weirdly DrahtBot didn't mention it was needed (but the CI did).
Ready for further review with one question below.
f43a127
to
86608da
Compare
Comments addressed. Ready for further review. |
🕵️ @sipa has been requested to review this pull request as specified in the REVIEWERS file. |
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.
Concept ACK.
0dd10cc
to
c44bac1
Compare
Addressed comments from @mzumsande. Ready for further review. |
utACK c44bac1 |
witness_root = CBlock.get_merkle_root([ser_uint256(0), | ||
ser_uint256(txid)]) | ||
script = get_witness_script(witness_root, 0) | ||
assert_equal(witness_commitment, script.hex()) |
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.
why is the test for default_witness_commitment removed?
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.
Segwit is a buried deployment. There are no miners calling getblocktemplate
before the segwit activation is locked in.
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 commitment is produced regardless of whether segwit locked in or not.
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.
Oh, I see now that default_witness_commitment
is not tested anywhere else. Perhaps it should be tested in mining_basic.py?
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.
Thank you for the catch, @MarcoFalke ! Test is now moved into mining_basic.py
@dhruv - do you plan to rebase this? |
@jnewbery I do. Been on break for a long weekend where I live. |
Concept ACK |
This also lets us default to NODE_WITNESS in nLocalServices
nLocalServices defaults to NODE_WITNESS and these checks are obsolete
c44bac1
to
a806647
Compare
Rebased. Addressed comments. Ready for further review. |
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.
utACK a806647
Thanks for rebasing!
def skip_test_if_missing_module(self): | ||
self.skip_if_no_wallet() |
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 is ok for now, but it'd be nice to rework this test so that it doesn't require a wallet.
We could also update the test to verify that the witness commitment commits to the wtxids of the transactions in the block rather than the txids. Currently the block being tested contains only the coinbase transaction and one transaction that spends from a P2PKH output, so the txid is the same as wtxid. It could be updated to include transactions that spend segwit outputs so that the txid and wtxid are different.
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 can do those in a follow-up PR. Can you tell me more about how I could remove the wallet dependency? My understanding is that to have getblocktemplate
include a transaction that the witness root commits to, I need a valid transaction in the mempool, and to create that valid tx, I need a wallet. I feel like I am missing something about the test framework perhaps?
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.
@dhruv: Luckily we have a minimalistic wallet implementation for the functional test framework (first introduced by MarcoFalke last year, see #19800). Look for modules importing MiniWallet
for example usage, see also issue #20078. Also, feel free to tag me in your follow-up PR, will be happy to review.
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.
Agree
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 a806647
Thanks to the PR review club log the changes were straight-forward to review. Built and ran tests locally, also checked via git grep DeploymentEnabled.*SEGWIT
and git grep GetLocalServices.*WITNESS
that all occurences of now-superfluous is-segwit-enabled checks were tackled.
Code-Review ACK a806647 |
Code review ACK a806647, nice cleanup |
witness_root = CBlock.get_merkle_root([ser_uint256(0), | ||
ser_uint256(txid)]) | ||
script = get_witness_script(witness_root, 0) | ||
assert_equal(witness_commitment, script.hex()) |
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.
Python will throw key-error, so you don't need the "# Check that default_witness_commitment is present." section.
See:
>>> {'b':1}['a']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'a'
Suggestion:
assert_equal(tmpl['default_witness_commitment'], script.hex())
def skip_test_if_missing_module(self): | ||
self.skip_if_no_wallet() |
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.
Agree
Builds on #21009 and makes progress on remaining items in #17862
Removing
RewindBlockIndex()
in #21009 allows the following:segwitheight=-1
inp2p_segwit.py
.test_upgrade_after_activation()
out ofp2p_segwit.py
reducing runtime-segwitheight=-1
, which is only supported for that test.NODE_WITNESS
in our local services. The only reason we don't do that is to support-segwitheight=-1
.GetLocalServices() & NODE_WITNESS
checks insidenet_processing.cpp
, since our local services would always includeNODE_WITNESS