[Unit tests are not complete to resolve #23279 - yet. But those additional tests - see this space for future developments! - will not change the code presented here.]
This PR provides unit tests for Taproot functionality in script/interpreter.cpp
, #23279.
Goal is to show correctness vs specifications in BIPs 341/342, and to improve code coverage in Taproot functionality there.
Intent is to unit test completely without changing interpreter.cpp
itself to provide visibility into static functions/private methods. Thus some of the tests must be “indirect”, testing the unit-under-test by probing a visible caller. This makes those specific tests somewhat fragile as they depend on code paths in the caller, which may change in the future. However, such tests are written so they will fail if the unit-under-test isn’t actually called. This is noted in the code of those specific tests.
No changes to Bitcoin Core are made - just unit tests added. The Boost Test framework file boost/test/execution_monitor.hpp
was added to the lint whitelist - this is acceptable because it is a documented public header of the Boost Test framework, which is already part of the project.
-
EvalChecksigTapscript
-
HandleMissingData
-
SignatureHashSchnorr
- now with full path coverage -
GenericTransactionSignatureChecker<T>::VerifySchnorrSignature
-
GenericTransactionSignatureChecker<T>::CheckSchnorrSignature
-
ComputeTaprootMerkleRoot
-
SigVersion::TAPSCRIPT
code paths inExecuteWitnessScript
- Taproot code paths in
VerifyWitnessProgram
- Tapscript code paths in
VerifyWitnessProgram
TODO: Full Tapscript (BIP-342) unit tests yet to be completed.
TODO: Does anything need to be done with libconsensus
? Please advise!
2 commits:
- Add new utility functions to
src/test/util
that are not only used in these tests but may also be useful for future unit tests. Also, refactor some existing utility functions from current tests (mainly,script_tests.cpp
) intosrc/test/util
so they can be more widely used too. All of these new test utility functions have unit tests themselves, insrc/test/test_utils_tests.cpp
. - All the tests for Taproot/Tapscript functionality requested by #23279 in a new file
src/test/script_tapscript_tests.cpp
. Code coverage runs show 100% coverage of lines and near 100% coverage of branches.
DEATH TRAP AHEAD!: These unit tests include “death tests” (name comes from Googletest framework): Tests that check that an assert
actually fails. These are handled with a Boost execution_monitor
(mentioned above) but the asserts still issue messages even when correctly trapped by the Boost Test framework. You’ll see the following in the logs:
0gitpod /workspace/bitcoin/src/test (23279-taproot-unit-tests) $ ./test_bitcoin
1Running 527 test cases...
2test_bitcoin: script/interpreter.cpp:1495: bool SignatureHashSchnorr(uint256 &, ScriptExecutionData &, const T &, uint32_t, uint8_t, SigVersion, const PrecomputedTransactionData &, MissingDataBehavior) [T = CMutableTransaction]: Assertion `false' failed.
3test_bitcoin: script/interpreter.cpp:1497: bool SignatureHashSchnorr(uint256 &, ScriptExecutionData &, const T &, uint32_t, uint8_t, SigVersion, const PrecomputedTransactionData &, MissingDataBehavior) [T = CMutableTransaction]: Assertion `in_pos < tx_to.vin.size()' failed.
4test_bitcoin: script/interpreter.cpp:1528: bool SignatureHashSchnorr(uint256 &, ScriptExecutionData &, const T &, uint32_t, uint8_t, SigVersion, const PrecomputedTransactionData &, MissingDataBehavior) [T = CMutableTransaction]: Assertion `execdata.m_annex_init' failed.
5test_bitcoin: script/interpreter.cpp:1556: bool SignatureHashSchnorr(uint256 &, ScriptExecutionData &, const T &, uint32_t, uint8_t, SigVersion, const PrecomputedTransactionData &, MissingDataBehavior) [T = CMutableTransaction]: Assertion `execdata.m_tapleaf_hash_init' failed.
6test_bitcoin: script/interpreter.cpp:1559: bool SignatureHashSchnorr(uint256 &, ScriptExecutionData &, const T &, uint32_t, uint8_t, SigVersion, const PrecomputedTransactionData &, MissingDataBehavior) [T = CMutableTransaction]: Assertion `execdata.m_codeseparator_pos_init' failed.
7test_bitcoin: script/interpreter.cpp:1469: bool HandleMissingData(MissingDataBehavior): Assertion `!"Missing data"' failed.
8test_bitcoin: script/interpreter.cpp:1474: bool HandleMissingData(MissingDataBehavior): Assertion `!"Unknown MissingDataBehavior value"' failed.
9
10*** No errors detected
11gitpod /workspace/bitcoin/src/test (23279-taproot-unit-tests) $
These specific Assertion ... failed
messages are expected. The tests triggering them properly pass iff the assert
(and no other) is triggered.
Coverage results 2022-06-05 showing Taproot coverage (Tapscript tests not yet complete) when only running script_tapscript_tests.cpp
:
EvalChecksigTapscript |
|
HandleMissingData |
|
SignatureHashSchnorr |
|
GenericTransaction- SignatureChecker<T>:: CheckSchnorrSignature |
|
ComputeTaprootMerkleRoot |
|
VerifyWitnessProgram (Taproot only) |