Skip to content
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

miner: always assume we can build witness blocks #24421

Merged
merged 1 commit into from
Mar 11, 2022

Conversation

glozow
Copy link
Member

@glozow glozow commented Feb 22, 2022

Given the low possibility of a reorg reverting the segwit soft fork, there is no longer a need to check whether segwit is active to see if it's okay to add to the block template (see also #23512, #21009, etc). TestBlockValidity() is also run on the block template at the end of CreateNewBlock(), so any invalid block would be caught there.

@glozow glozow added the Mining label Feb 22, 2022
@glozow glozow force-pushed the 2022-02-miner-fincludewitness branch from 5ead13f to 03c37cc Compare February 22, 2022 17:05
@laanwj
Copy link
Member

laanwj commented Feb 22, 2022

Concept and code review ACK 03c37cc

@jamesob
Copy link
Contributor

jamesob commented Feb 22, 2022

Concept ACK

1 similar comment
@theStack
Copy link
Contributor

Concept ACK

self.skip_mine(self.nodes[2], wit_ids[NODE_2][P2WSH][0], True) # block 425
self.skip_mine(self.nodes[2], p2sh_ids[NODE_2][P2WPKH][0], True) # block 426
self.skip_mine(self.nodes[2], p2sh_ids[NODE_2][P2WSH][0], True) # block 427
self.generate(self.nodes[0], 264) # block 427
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really a fan of removing this test. Why not keep it to make the change in behaviour explicit and clarify that mining before segwit is active will result in a json exception?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disagree. Why do we need to test that a miner on a pre-segwit chain with segwit transactions in its mempool fails to mine a block? If we think that this scenario is possible (and so needs testing), then we shouldn't make the change in this PR, since failing to mine a block is strictly worse behaviour than mining a block without the segwit transaction.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this way we have test coverage for "unexpected witness"

Copy link
Contributor

@jnewbery jnewbery Mar 10, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this way we have test coverage for "unexpected witness"

That's a very indirect way of testing a failure condition in ContextualCheckBlock(). If we want a test for that condition, then we should have a functional test where a non-witness block (which is possible to create even after segwit activation) is stuffed with witness data. That's a condition that could happen on mainnet, and so isn't relying on impossible-to-hit-in-production mining code. Even better would be a unit test for ContextualCheckBlock().

I think it's inconsistent to remove production code that is "impossible to hit" and then add a test that hits that exact condition.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see the point why this practically doesn't need test coverage. I also think the changes here are safe to make. However, I think we should still think about the case where our assumptions fail or our expectations aren't met. It is minimally useful for the test to remind reviewers what will happen in the unexpected case.

For example, I disagree about:

failing to mine a block is strictly worse behaviour than mining a block without the segwit transaction.

If this code path were to be triggerable by an attacker, it would be a strictly better outcome to fail to mine a block before witness than to mine a block. First, a block mined far behind the tip will never be accepted into the main chain and thus never financially rewarded, so there is no benefit of mining it. Second, returning an error early may tell the attacked miner that they have been eclipsed earlier. Third, mining a block (and submitting it, then later reorging it (if it was accepted)) is going to execute more code during the eclipse attack than not mining a block. If there are bugs in the executed code, it gives more tools to the attacker for no benefit. So I think it also serves as a belt-and-suspender.

Another example (unrelated to this pull request):

If an attacker could make the blocksdir unusable (until a manual -reindex) by executing a reorg that is large enough that we think it won't happen, I still think we should fix the bug so that the blocksdir remains usable after any states the software went through.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing this test would also fix the "unexpected witness" CI failures

Given the low possibility of a reorg reverting the segwit soft fork,
there is no need to check whether segwit is active here. Also,
TestBlockValidity is run on the block template after it has been
created.
@glozow glozow force-pushed the 2022-02-miner-fincludewitness branch from 03c37cc to 40e871d Compare February 23, 2022 10:57
Copy link
Contributor

@theStack theStack left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code-review ACK 40e871d

@fanquake fanquake added this to the 24.0 milestone Feb 24, 2022
@ccdle12
Copy link
Contributor

ccdle12 commented Mar 2, 2022

Concept ACK

@gruve-p
Copy link
Contributor

gruve-p commented Mar 6, 2022

ACK 40e871d

@luke-jr
Copy link
Member

luke-jr commented Mar 7, 2022

(See also #19391 for more dead code)

@jnewbery
Copy link
Contributor

jnewbery commented Mar 9, 2022

utACK 40e871d, although I disagree about changing the test for segwit transaction in mempool before activagtion, instead of just removing it: #24421 (comment).

@glozow glozow requested a review from maflcko March 11, 2022 10:48
Copy link
Member

@maflcko maflcko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

I think there is a small theoretical concern that this will make Bitcoin Core internally minimally more inconsistent. See the comment why I initially held back on proposing this pull.

It is safe to make the changes here, because we assume that the nMinimumChainWork bundled in any release that will include this patch is sufficiently large to make reorg-attacks during IBD while eclipsed prohibitively expensive. The same assumption was made in commit 0a8b7b4 and #23536

self.skip_mine(self.nodes[2], wit_ids[NODE_2][P2WSH][0], True) # block 425
self.skip_mine(self.nodes[2], p2sh_ids[NODE_2][P2WPKH][0], True) # block 426
self.skip_mine(self.nodes[2], p2sh_ids[NODE_2][P2WSH][0], True) # block 427
self.generate(self.nodes[0], 264) # block 427
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see the point why this practically doesn't need test coverage. I also think the changes here are safe to make. However, I think we should still think about the case where our assumptions fail or our expectations aren't met. It is minimally useful for the test to remind reviewers what will happen in the unexpected case.

For example, I disagree about:

failing to mine a block is strictly worse behaviour than mining a block without the segwit transaction.

If this code path were to be triggerable by an attacker, it would be a strictly better outcome to fail to mine a block before witness than to mine a block. First, a block mined far behind the tip will never be accepted into the main chain and thus never financially rewarded, so there is no benefit of mining it. Second, returning an error early may tell the attacked miner that they have been eclipsed earlier. Third, mining a block (and submitting it, then later reorging it (if it was accepted)) is going to execute more code during the eclipse attack than not mining a block. If there are bugs in the executed code, it gives more tools to the attacker for no benefit. So I think it also serves as a belt-and-suspender.

Another example (unrelated to this pull request):

If an attacker could make the blocksdir unusable (until a manual -reindex) by executing a reorg that is large enough that we think it won't happen, I still think we should fix the bug so that the blocksdir remains usable after any states the software went through.

@achow101
Copy link
Member

ACK 40e871d

@fanquake fanquake merged commit 23e8c70 into bitcoin:master Mar 11, 2022
@glozow glozow deleted the 2022-02-miner-fincludewitness branch March 11, 2022 17:14
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Mar 11, 2022
@ajtowns
Copy link
Contributor

ajtowns commented Mar 15, 2022

I'm sometimes seeing

test_framework.authproxy.JSONRPCException: CreateNewBlock: TestBlockValidity failed: unexpected-witness, ContextualCheckBlock : unexpected witness data found (-1)

from feature_segwit.py, generated by

  File "/home/aj/P/bitcoin/bitcoin/chk/test/functional/./feature_segwit.py", line 210, in run_test
    self.generate(self.nodes[0], 4)  # blocks 428-431

that looks like it might be due to this PR? (Took about 80 runs to reproduce)

@maflcko
Copy link
Member

maflcko commented Mar 15, 2022

Probably happens because the witness txs from node 2 are sent to node 0? You can check this by adding a sync_mempools call or maybe even just with the noban permission flag for faster relay.

@ajtowns
Copy link
Contributor

ajtowns commented Mar 15, 2022

The problem doesn't appear to get hit prior to this PR (after ~250 runs). Adding self.sync_mempools() prior to generate for blocks 428 appears to make it fail reliably with this PR, while the same change prior to this PR doesn't seem to cause failures. Adding -whitelist=127.0.0.1 makes the failure more frequent but not quite reliable.

Seems to me that random test suite failures makes this worth reverting...

@glozow
Copy link
Member Author

glozow commented Mar 15, 2022

Probably happens because the witness txs from node 2 are sent to node 0?

That's my guess as well. Can probably fix by disconnecting node0/node2 before generate, and then reconnecting after 431 is mined. But definitely feel free to revert, sorry for missing this!

@maflcko
Copy link
Member

maflcko commented Mar 15, 2022

I think there are two options:

78877i referenced this pull request Mar 15, 2022
In order to determine whether to download or process a relayed transaction, we
try to determine if we already have the transaction, either in the mempool, in
our recently rejected filter, in our orphan pool, or already confirmed in the
chain itself.

Prior to this commit, the heuristic for checking the chain is based on whether
there's an output corresponding to the 0- or 1-index vout in our coin cache.
While that is a quick check, it is very imprecise (say if those outputs were
already spent in a block) -- we can do better by just keeping a rolling bloom
filter of the transactions in recent blocks, which will capture the case of a
transaction which has been confirmed and then fully spent already.

To avoid relay problems for transactions which have been included in a recent
block but then reorged out of the chain, we clear the bloom filter whenever a
block is disconnected.
@jnewbery
Copy link
Contributor

I think there are two options:

My vote would be for removing the invalid test :)

@maflcko
Copy link
Member

maflcko commented Mar 17, 2022

##24578 ;)

maflcko pushed a commit to bitcoin-core/gui that referenced this pull request Mar 18, 2022
…e_segwit

d6b24e1 test: Fix intermittent failure in feature_segwit (DrahtBot)

Pull request description:

  There are intermittent failures on current master (bitcoin/bitcoin#24421 (comment)) as the witness txs occasionally make it into other node's mempools when they shouldn't.

  Fix this by removing the test as suggested earlier in bitcoin/bitcoin#24421 (comment).

  Fixes bitcoin/bitcoin#24590

ACKs for top commit:
  aureleoules:
    tACK d6b24e1.
  jnewbery:
    Code review ACK d6b24e1

Tree-SHA512: ef7be52bdbde97b6921b44824e7fbc2dd92b77b8f076794867259f2b0bff08e0def06f4b2576f63a8ccb737a15cd8441fb7db20fa1f0d4fa9c7c76d5b83388ef
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Mar 18, 2022
d6b24e1 test: Fix intermittent failure in feature_segwit (DrahtBot)

Pull request description:

  There are intermittent failures on current master (bitcoin#24421 (comment)) as the witness txs occasionally make it into other node's mempools when they shouldn't.

  Fix this by removing the test as suggested earlier in bitcoin#24421 (comment).

  Fixes bitcoin#24590

ACKs for top commit:
  aureleoules:
    tACK d6b24e1.
  jnewbery:
    Code review ACK d6b24e1

Tree-SHA512: ef7be52bdbde97b6921b44824e7fbc2dd92b77b8f076794867259f2b0bff08e0def06f4b2576f63a8ccb737a15cd8441fb7db20fa1f0d4fa9c7c76d5b83388ef
@bitcoin bitcoin locked and limited conversation to collaborators Mar 17, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.