|
3 | 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. |
4 | 4 |
|
5 | 5 | #include <test/data/script_tests.json.h> |
| 6 | +#include <test/data/bip341_wallet_vectors.json.h> |
6 | 7 |
|
7 | 8 | #include <core_io.h> |
8 | 9 | #include <fs.h> |
@@ -1743,4 +1744,79 @@ BOOST_AUTO_TEST_CASE(script_assets_test) |
1743 | 1744 | file.close(); |
1744 | 1745 | } |
1745 | 1746 |
|
| 1747 | +BOOST_AUTO_TEST_CASE(bip341_keypath_test_vectors) |
| 1748 | +{ |
| 1749 | + UniValue tests; |
| 1750 | + tests.read((const char*)json_tests::bip341_wallet_vectors, sizeof(json_tests::bip341_wallet_vectors)); |
| 1751 | + |
| 1752 | + const auto& vectors = tests["keyPathSpending"]; |
| 1753 | + |
| 1754 | + for (const auto& vec : vectors.getValues()) { |
| 1755 | + auto txhex = ParseHex(vec["given"]["rawUnsignedTx"].get_str()); |
| 1756 | + CMutableTransaction tx; |
| 1757 | + VectorReader(SER_NETWORK, PROTOCOL_VERSION, txhex, 0) >> tx; |
| 1758 | + std::vector<CTxOut> utxos; |
| 1759 | + for (const auto& utxo_spent : vec["given"]["utxosSpent"].getValues()) { |
| 1760 | + auto script_bytes = ParseHex(utxo_spent["scriptPubKey"].get_str()); |
| 1761 | + CScript script{script_bytes.begin(), script_bytes.end()}; |
| 1762 | + CAmount amount{utxo_spent["amountSats"].get_int()}; |
| 1763 | + utxos.emplace_back(amount, script); |
| 1764 | + } |
| 1765 | + |
| 1766 | + PrecomputedTransactionData txdata; |
| 1767 | + txdata.Init(tx, std::vector<CTxOut>{utxos}, true); |
| 1768 | + |
| 1769 | + BOOST_CHECK(txdata.m_bip341_taproot_ready); |
| 1770 | + BOOST_CHECK_EQUAL(HexStr(txdata.m_spent_amounts_single_hash), vec["intermediary"]["hashAmounts"].get_str()); |
| 1771 | + BOOST_CHECK_EQUAL(HexStr(txdata.m_outputs_single_hash), vec["intermediary"]["hashOutputs"].get_str()); |
| 1772 | + BOOST_CHECK_EQUAL(HexStr(txdata.m_prevouts_single_hash), vec["intermediary"]["hashPrevouts"].get_str()); |
| 1773 | + BOOST_CHECK_EQUAL(HexStr(txdata.m_spent_scripts_single_hash), vec["intermediary"]["hashScriptPubkeys"].get_str()); |
| 1774 | + BOOST_CHECK_EQUAL(HexStr(txdata.m_sequences_single_hash), vec["intermediary"]["hashSequences"].get_str()); |
| 1775 | + |
| 1776 | + for (const auto& input : vec["inputSpending"].getValues()) { |
| 1777 | + int txinpos = input["given"]["txinIndex"].get_int(); |
| 1778 | + int hashtype = input["given"]["hashType"].get_int(); |
| 1779 | + |
| 1780 | + // Load key. |
| 1781 | + auto privkey = ParseHex(input["given"]["internalPrivkey"].get_str()); |
| 1782 | + CKey key; |
| 1783 | + key.Set(privkey.begin(), privkey.end(), true); |
| 1784 | + |
| 1785 | + // Load Merkle root. |
| 1786 | + uint256 merkle_root; |
| 1787 | + if (!input["given"]["merkleRoot"].isNull()) { |
| 1788 | + merkle_root = uint256{ParseHex(input["given"]["merkleRoot"].get_str())}; |
| 1789 | + } |
| 1790 | + |
| 1791 | + // Compute and verify (internal) public key. |
| 1792 | + XOnlyPubKey pubkey{key.GetPubKey()}; |
| 1793 | + BOOST_CHECK_EQUAL(HexStr(pubkey), input["intermediary"]["internalPubkey"].get_str()); |
| 1794 | + |
| 1795 | + // Sign and verify signature. |
| 1796 | + FlatSigningProvider provider; |
| 1797 | + provider.keys[key.GetPubKey().GetID()] = key; |
| 1798 | + MutableTransactionSignatureCreator creator(&tx, txinpos, utxos[txinpos].nValue, &txdata, hashtype); |
| 1799 | + std::vector<unsigned char> signature; |
| 1800 | + BOOST_CHECK(creator.CreateSchnorrSig(provider, signature, pubkey, nullptr, &merkle_root, SigVersion::TAPROOT)); |
| 1801 | + BOOST_CHECK_EQUAL(HexStr(signature), input["expected"]["witness"][0].get_str()); |
| 1802 | + |
| 1803 | + // We can't observe the tweak used inside the signing logic, so verify by recomputing it. |
| 1804 | + BOOST_CHECK_EQUAL(HexStr(pubkey.ComputeTapTweakHash(merkle_root.IsNull() ? nullptr : &merkle_root)), input["intermediary"]["tweak"].get_str()); |
| 1805 | + |
| 1806 | + // We can't observe the sighash used inside the signing logic, so verify by recomputing it. |
| 1807 | + ScriptExecutionData sed; |
| 1808 | + sed.m_annex_init = true; |
| 1809 | + sed.m_annex_present = false; |
| 1810 | + uint256 sighash; |
| 1811 | + BOOST_CHECK(SignatureHashSchnorr(sighash, sed, tx, txinpos, hashtype, SigVersion::TAPROOT, txdata, MissingDataBehavior::FAIL)); |
| 1812 | + BOOST_CHECK_EQUAL(HexStr(sighash), input["intermediary"]["sigHash"].get_str()); |
| 1813 | + |
| 1814 | + // To verify the sigmsg, hash the expected sigmsg, and compare it with the (expected) sighash. |
| 1815 | + BOOST_CHECK_EQUAL(HexStr((CHashWriter(HASHER_TAPSIGHASH) << MakeSpan(ParseHex(input["intermediary"]["sigMsg"].get_str()))).GetSHA256()), input["intermediary"]["sigHash"].get_str()); |
| 1816 | + } |
| 1817 | + |
| 1818 | + } |
| 1819 | + |
| 1820 | +} |
| 1821 | + |
1746 | 1822 | BOOST_AUTO_TEST_SUITE_END() |
0 commit comments