Skip to content

Conversation

TheQuantumPhysicist
Copy link
Contributor

Test with block 47 in the feature_block.py creates a block with a hash higher than the target, which is supposed to fail. Now two issues exist there, and both have low probability of showing up:

  1. The creation is done with while (hash < target), which is wrong, because hash = target is a valid mined value based on the code in the function CheckProofOfWork() that validates the mining target:
    if (UintToArith256(hash) > bnTarget)
        return false;
  1. As we know the hash stored in CBlock class in Python is stateful, unlike how it's in C++, where calling CBlock::GetHash() will actively calculate the hash and not cache it anywhere. With this, blocks that come out of the method next_block can have incorrect hash value when solve=False. This is because the next_block is mostly used with solve=True, and solving does call the function rehash() which calculates the hash of the block, but with solve=False, nothing calls that method. And since the work to be done in regtests is very low, the probably of this problem showing up is very low, but it practically happens (well, with much higher probability compared to issue No. 1 above).

This PR fixes both these issues.

@TheQuantumPhysicist TheQuantumPhysicist changed the title Fix mining to an invalid target + ensure that a new block has the correct hash internally Regtest: Fix mining to an invalid target + ensure that a new block has the correct hash internally Mar 14, 2020
@DrahtBot DrahtBot added the Tests label Mar 14, 2020
@maflcko maflcko changed the title Regtest: Fix mining to an invalid target + ensure that a new block has the correct hash internally test: Fix mining to an invalid target + ensure that a new block has the correct hash internally Mar 14, 2020
@maflcko
Copy link
Member

maflcko commented Mar 14, 2020

If this was ever the cause of a test failure, it probably means our assumption about hash functions is broken.

Still, ACK. I don't mind fixing it.

@jnewbery
Copy link
Contributor

Concept ACK fixing issue 1. Like @MarcoFalke says, the probability of this ever causing a failure is negligible, but it's better that the test's assumptions are accurate.

For issue 2 (next_block not recalculating the digest if solve is False), I think we can just remove the solve parameter from that function and always solve the block. The function is only called with solve=False in two places, and in both cases the nonce is recalculated (to be invalid for block 47, and resolved for block 48).

@TheQuantumPhysicist
Copy link
Contributor Author

TheQuantumPhysicist commented Mar 14, 2020

If this was ever the cause of a test failure, it probably means our assumption about hash functions is broken.

Actually you're right about the first fix, but the second one has a much higher likelihood to happen. I was able to simulate it by putting it on the tip of the block 1 and it happened always within a loop of 1000 tests that repeat b47's test case.

@maflcko
Copy link
Member

maflcko commented Mar 16, 2020

@TheQuantumPhysicist let me know if you want to address @jnewbery 's feedback or not

@TheQuantumPhysicist
Copy link
Contributor Author

@MarcoFalke Do you mean implement it? If so, I don't mind. I just need a confirmation that this is the solution we wanna go for.

In my opinion, the solve option should remain, because solving and hashing are different requirements. But I don't mind either way.

@maflcko
Copy link
Member

maflcko commented Mar 16, 2020

I think in tests we aim for simplicity, even if that comes at a trivial cost like a few hashes. So I see @jnewbery 's point. I am happy to merge either version.

@TheQuantumPhysicist
Copy link
Contributor Author

If you don't mind either way, please merge it as it's, and anyone is welcome to change it, since it's correct in its current form.

If I see the majority over here insisting on changing it to remove solve, I'm all for it. I'm just too lazy to run more and test more spontaneously 😄

@maflcko maflcko merged commit 7060d2d into bitcoin:master Mar 16, 2020
@jnewbery
Copy link
Contributor

I really don't like the second commit. I think it adds complexity for no good reason, and without commenting it makes the code less clear instead of more.

@maflcko
Copy link
Member

maflcko commented Mar 17, 2020

This has been merged, but anyone who feels that the logic needs commenting or a refactor, may open a follow-up pull request.

sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Mar 17, 2020
…hat a new block has the correct hash internally

7a6627a Fix mining to an invalid target + ensure that a new block has the correct hash internally in Python tests (Samer Afach)

Pull request description:

  Test with block 47 in the `feature_block.py` creates a block with a hash higher than the target, which is supposed to fail. Now two issues exist there, and both have low probability of showing up:

  1. The creation is done with `while (hash < target)`, which is wrong, because hash = target is a valid mined value based on the code in the function `CheckProofOfWork()` that validates the mining target:
  ```
      if (UintToArith256(hash) > bnTarget)
          return false;
  ```
  2. As we know the hash stored in CBlock class in Python is stateful, unlike how it's in C++, where calling `CBlock::GetHash()` will actively calculate the hash and not cache it anywhere. With this, blocks that come out of the method `next_block` can have incorrect hash value when `solve=False`. This is because the `next_block` is mostly used with `solve=True`, and solving does call the function `rehash()` which calculates the hash of the block, but with `solve=False`, nothing calls that method. And since the work to be done in regtests is very low, the probably of this problem showing up is very low, but it practically happens (well, with much higher probability compared to issue No. 1 above).

  This PR fixes both these issues.

Top commit has no ACKs.

Tree-SHA512: f3b54d18f5073d6f1c26eab89bfec78620dda4ac1e4dde4f1d69543f1b85a7989d64c907e091db63f3f062408f5ed1e111018b842819ba1a5f8348c7b01ade96
MarkLTZ added a commit to litecoinz-core/litecoinz that referenced this pull request Apr 7, 2020
- doc: fix git add argument bitcoin#18513
- build: Fix libevent linking for bench_bitcoin binary bitcoin#18397
- script: fix SCRIPT_ERR_SIG_PUSHONLY error string bitcoin#18412
- doc: Comment fix merkle.cpp bitcoin#18379
- log: Fix UB with bench on genesis block bitcoin#15283
- test: Fix mining to an invalid target + ensure that a new block has the correct hash internally bitcoin#18350
- Fix missing header in sync.h bitcoin#18357
- refactor: Fix implicit value conversion in formatPingTime bitcoin#18260
- Fix .gitignore policy in build_msvc directory bitcoin#18108
- build: Fix behavior when ALLOW_HOST_PACKAGES unset bitcoin#18051
- test: Fix p2p_invalid_messages failing in Python 3.8 because of warning bitcoin#17931
- qa: Fix double-negative arg test bitcoin#17893
- build: Fix configure report about qr bitcoin#17547
- log: Fix log message for -par=1 bitcoin#17325
- bench: Fix negative values and zero for -evals flag bitcoin#17267
- depends: fix boost mac cross build with clang 9+ bitcoin#17231
- doc: Fix broken bitcoin-cli examples bitcoin#17119
- doc: fix Makefile target in benchmarking.md bitcoin#17081
- contrib: fix minor typos in makeseeds.py bitcoin#17042
- test: Fix Python Docstring to include all Args. bitcoin#17030
- doc: Fix some misspellings bitcoin#17351
- doc: Doxygen-friendly script/descriptor.h comments bitcoin#16947
- doc: Fix doxygen errors bitcoin#17945
- doc: Doxygen-friendly CuckooCache comments bitcoin#16986
- doc: Add to Doxygen documentation guidelines bitcoin#17873
MarkLTZ added a commit to litecoinz-core/litecoinz that referenced this pull request Apr 7, 2020
- doc: fix git add argument bitcoin#18513
- build: Fix libevent linking for bench_bitcoin binary bitcoin#18397
- script: fix SCRIPT_ERR_SIG_PUSHONLY error string bitcoin#18412
- doc: Comment fix merkle.cpp bitcoin#18379
- log: Fix UB with bench on genesis block bitcoin#15283
- test: Fix mining to an invalid target + ensure that a new block has the correct hash internally bitcoin#18350
- Fix missing header in sync.h bitcoin#18357
- refactor: Fix implicit value conversion in formatPingTime bitcoin#18260
- Fix .gitignore policy in build_msvc directory bitcoin#18108
- build: Fix behavior when ALLOW_HOST_PACKAGES unset bitcoin#18051
- test: Fix p2p_invalid_messages failing in Python 3.8 because of warning bitcoin#17931
- qa: Fix double-negative arg test bitcoin#17893
- build: Fix configure report about qr bitcoin#17547
- log: Fix log message for -par=1 bitcoin#17325
- bench: Fix negative values and zero for -evals flag bitcoin#17267
- depends: fix boost mac cross build with clang 9+ bitcoin#17231
- doc: Fix broken bitcoin-cli examples bitcoin#17119
- doc: fix Makefile target in benchmarking.md bitcoin#17081
- contrib: fix minor typos in makeseeds.py bitcoin#17042
- test: Fix Python Docstring to include all Args. bitcoin#17030
- doc: Fix some misspellings bitcoin#17351
- doc: Doxygen-friendly script/descriptor.h comments bitcoin#16947
- doc: Fix doxygen errors bitcoin#17945
- doc: Doxygen-friendly CuckooCache comments bitcoin#16986
- doc: Add to Doxygen documentation guidelines bitcoin#17873
- depends: Consistent use of package variable bitcoin#17928
- init: Replace URL_WEBSITE with PACKAGE_URL bitcoin#18503
- doc: Add missed copyright headers bitcoin#17691
sidhujag pushed a commit to syscoin-core/syscoin that referenced this pull request Nov 10, 2020
…hat a new block has the correct hash internally

7a6627a Fix mining to an invalid target + ensure that a new block has the correct hash internally in Python tests (Samer Afach)

Pull request description:

  Test with block 47 in the `feature_block.py` creates a block with a hash higher than the target, which is supposed to fail. Now two issues exist there, and both have low probability of showing up:

  1. The creation is done with `while (hash < target)`, which is wrong, because hash = target is a valid mined value based on the code in the function `CheckProofOfWork()` that validates the mining target:
  ```
      if (UintToArith256(hash) > bnTarget)
          return false;
  ```
  2. As we know the hash stored in CBlock class in Python is stateful, unlike how it's in C++, where calling `CBlock::GetHash()` will actively calculate the hash and not cache it anywhere. With this, blocks that come out of the method `next_block` can have incorrect hash value when `solve=False`. This is because the `next_block` is mostly used with `solve=True`, and solving does call the function `rehash()` which calculates the hash of the block, but with `solve=False`, nothing calls that method. And since the work to be done in regtests is very low, the probably of this problem showing up is very low, but it practically happens (well, with much higher probability compared to issue No. 1 above).

  This PR fixes both these issues.

Top commit has no ACKs.

Tree-SHA512: f3b54d18f5073d6f1c26eab89bfec78620dda4ac1e4dde4f1d69543f1b85a7989d64c907e091db63f3f062408f5ed1e111018b842819ba1a5f8348c7b01ade96
Fabcien pushed a commit to Bitcoin-ABC/bitcoin-abc that referenced this pull request Jan 8, 2021
…rect hash internally in Python tests

Summary:
> Test with block 47 in the feature_block.py creates a block with a hash higher than the target, which is supposed to fail. Now two issues exist there, and both have low probability of showing up:
>
>   -  The creation is done with while (hash < target), which is wrong, because hash = target is a valid mined value based on the code in the function CheckProofOfWork() that validates the mining target
>   - As we know the hash stored in CBlock class in Python is stateful, unlike how it's in C++, where calling CBlock::GetHash() will actively calculate the hash and not cache it anywhere. With this, blocks that come out of the method next_block can have incorrect hash value when solve=False. This is because the next_block is mostly used with solve=True, and solving does call the function rehash() which calculates the hash of the block, but with solve=False, nothing calls that method. And since the work to be done in regtests is very low, the probably of this problem showing up is very low, but it practically happens (well, with much higher probability compared to issue No. 1 above).
>
> This PR fixes both these issues.

This is a backport of Core [[bitcoin/bitcoin#18350 | PR18350]]

Test Plan: ninja && test/functional/test_runner.py feature_block

Reviewers: #bitcoin_abc, deadalnix

Reviewed By: #bitcoin_abc, deadalnix

Differential Revision: https://reviews.bitcoinabc.org/D8846
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jun 27, 2021
…hat a new block has the correct hash internally

7a6627a Fix mining to an invalid target + ensure that a new block has the correct hash internally in Python tests (Samer Afach)

Pull request description:

  Test with block 47 in the `feature_block.py` creates a block with a hash higher than the target, which is supposed to fail. Now two issues exist there, and both have low probability of showing up:

  1. The creation is done with `while (hash < target)`, which is wrong, because hash = target is a valid mined value based on the code in the function `CheckProofOfWork()` that validates the mining target:
  ```
      if (UintToArith256(hash) > bnTarget)
          return false;
  ```
  2. As we know the hash stored in CBlock class in Python is stateful, unlike how it's in C++, where calling `CBlock::GetHash()` will actively calculate the hash and not cache it anywhere. With this, blocks that come out of the method `next_block` can have incorrect hash value when `solve=False`. This is because the `next_block` is mostly used with `solve=True`, and solving does call the function `rehash()` which calculates the hash of the block, but with `solve=False`, nothing calls that method. And since the work to be done in regtests is very low, the probably of this problem showing up is very low, but it practically happens (well, with much higher probability compared to issue No. 1 above).

  This PR fixes both these issues.

Top commit has no ACKs.

Tree-SHA512: f3b54d18f5073d6f1c26eab89bfec78620dda4ac1e4dde4f1d69543f1b85a7989d64c907e091db63f3f062408f5ed1e111018b842819ba1a5f8348c7b01ade96
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jun 28, 2021
…hat a new block has the correct hash internally

7a6627a Fix mining to an invalid target + ensure that a new block has the correct hash internally in Python tests (Samer Afach)

Pull request description:

  Test with block 47 in the `feature_block.py` creates a block with a hash higher than the target, which is supposed to fail. Now two issues exist there, and both have low probability of showing up:

  1. The creation is done with `while (hash < target)`, which is wrong, because hash = target is a valid mined value based on the code in the function `CheckProofOfWork()` that validates the mining target:
  ```
      if (UintToArith256(hash) > bnTarget)
          return false;
  ```
  2. As we know the hash stored in CBlock class in Python is stateful, unlike how it's in C++, where calling `CBlock::GetHash()` will actively calculate the hash and not cache it anywhere. With this, blocks that come out of the method `next_block` can have incorrect hash value when `solve=False`. This is because the `next_block` is mostly used with `solve=True`, and solving does call the function `rehash()` which calculates the hash of the block, but with `solve=False`, nothing calls that method. And since the work to be done in regtests is very low, the probably of this problem showing up is very low, but it practically happens (well, with much higher probability compared to issue No. 1 above).

  This PR fixes both these issues.

Top commit has no ACKs.

Tree-SHA512: f3b54d18f5073d6f1c26eab89bfec78620dda4ac1e4dde4f1d69543f1b85a7989d64c907e091db63f3f062408f5ed1e111018b842819ba1a5f8348c7b01ade96
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jun 29, 2021
…hat a new block has the correct hash internally

7a6627a Fix mining to an invalid target + ensure that a new block has the correct hash internally in Python tests (Samer Afach)

Pull request description:

  Test with block 47 in the `feature_block.py` creates a block with a hash higher than the target, which is supposed to fail. Now two issues exist there, and both have low probability of showing up:

  1. The creation is done with `while (hash < target)`, which is wrong, because hash = target is a valid mined value based on the code in the function `CheckProofOfWork()` that validates the mining target:
  ```
      if (UintToArith256(hash) > bnTarget)
          return false;
  ```
  2. As we know the hash stored in CBlock class in Python is stateful, unlike how it's in C++, where calling `CBlock::GetHash()` will actively calculate the hash and not cache it anywhere. With this, blocks that come out of the method `next_block` can have incorrect hash value when `solve=False`. This is because the `next_block` is mostly used with `solve=True`, and solving does call the function `rehash()` which calculates the hash of the block, but with `solve=False`, nothing calls that method. And since the work to be done in regtests is very low, the probably of this problem showing up is very low, but it practically happens (well, with much higher probability compared to issue No. 1 above).

  This PR fixes both these issues.

Top commit has no ACKs.

Tree-SHA512: f3b54d18f5073d6f1c26eab89bfec78620dda4ac1e4dde4f1d69543f1b85a7989d64c907e091db63f3f062408f5ed1e111018b842819ba1a5f8348c7b01ade96
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jul 1, 2021
…hat a new block has the correct hash internally

7a6627a Fix mining to an invalid target + ensure that a new block has the correct hash internally in Python tests (Samer Afach)

Pull request description:

  Test with block 47 in the `feature_block.py` creates a block with a hash higher than the target, which is supposed to fail. Now two issues exist there, and both have low probability of showing up:

  1. The creation is done with `while (hash < target)`, which is wrong, because hash = target is a valid mined value based on the code in the function `CheckProofOfWork()` that validates the mining target:
  ```
      if (UintToArith256(hash) > bnTarget)
          return false;
  ```
  2. As we know the hash stored in CBlock class in Python is stateful, unlike how it's in C++, where calling `CBlock::GetHash()` will actively calculate the hash and not cache it anywhere. With this, blocks that come out of the method `next_block` can have incorrect hash value when `solve=False`. This is because the `next_block` is mostly used with `solve=True`, and solving does call the function `rehash()` which calculates the hash of the block, but with `solve=False`, nothing calls that method. And since the work to be done in regtests is very low, the probably of this problem showing up is very low, but it practically happens (well, with much higher probability compared to issue No. 1 above).

  This PR fixes both these issues.

Top commit has no ACKs.

Tree-SHA512: f3b54d18f5073d6f1c26eab89bfec78620dda4ac1e4dde4f1d69543f1b85a7989d64c907e091db63f3f062408f5ed1e111018b842819ba1a5f8348c7b01ade96
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jul 1, 2021
…hat a new block has the correct hash internally

7a6627a Fix mining to an invalid target + ensure that a new block has the correct hash internally in Python tests (Samer Afach)

Pull request description:

  Test with block 47 in the `feature_block.py` creates a block with a hash higher than the target, which is supposed to fail. Now two issues exist there, and both have low probability of showing up:

  1. The creation is done with `while (hash < target)`, which is wrong, because hash = target is a valid mined value based on the code in the function `CheckProofOfWork()` that validates the mining target:
  ```
      if (UintToArith256(hash) > bnTarget)
          return false;
  ```
  2. As we know the hash stored in CBlock class in Python is stateful, unlike how it's in C++, where calling `CBlock::GetHash()` will actively calculate the hash and not cache it anywhere. With this, blocks that come out of the method `next_block` can have incorrect hash value when `solve=False`. This is because the `next_block` is mostly used with `solve=True`, and solving does call the function `rehash()` which calculates the hash of the block, but with `solve=False`, nothing calls that method. And since the work to be done in regtests is very low, the probably of this problem showing up is very low, but it practically happens (well, with much higher probability compared to issue No. 1 above).

  This PR fixes both these issues.

Top commit has no ACKs.

Tree-SHA512: f3b54d18f5073d6f1c26eab89bfec78620dda4ac1e4dde4f1d69543f1b85a7989d64c907e091db63f3f062408f5ed1e111018b842819ba1a5f8348c7b01ade96
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jul 14, 2021
…hat a new block has the correct hash internally

7a6627a Fix mining to an invalid target + ensure that a new block has the correct hash internally in Python tests (Samer Afach)

Pull request description:

  Test with block 47 in the `feature_block.py` creates a block with a hash higher than the target, which is supposed to fail. Now two issues exist there, and both have low probability of showing up:

  1. The creation is done with `while (hash < target)`, which is wrong, because hash = target is a valid mined value based on the code in the function `CheckProofOfWork()` that validates the mining target:
  ```
      if (UintToArith256(hash) > bnTarget)
          return false;
  ```
  2. As we know the hash stored in CBlock class in Python is stateful, unlike how it's in C++, where calling `CBlock::GetHash()` will actively calculate the hash and not cache it anywhere. With this, blocks that come out of the method `next_block` can have incorrect hash value when `solve=False`. This is because the `next_block` is mostly used with `solve=True`, and solving does call the function `rehash()` which calculates the hash of the block, but with `solve=False`, nothing calls that method. And since the work to be done in regtests is very low, the probably of this problem showing up is very low, but it practically happens (well, with much higher probability compared to issue No. 1 above).

  This PR fixes both these issues.

Top commit has no ACKs.

Tree-SHA512: f3b54d18f5073d6f1c26eab89bfec78620dda4ac1e4dde4f1d69543f1b85a7989d64c907e091db63f3f062408f5ed1e111018b842819ba1a5f8348c7b01ade96
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Feb 15, 2022
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.

4 participants