aboutsummaryrefslogtreecommitdiff
path: root/src/test/script_tests.cpp
diff options
context:
space:
mode:
authorPieter Wuille <pieter@wuille.net>2021-10-27 19:16:01 -0400
committerPieter Wuille <pieter@wuille.net>2021-11-12 12:05:00 -0500
commitf1c33ee4ac1056289f2e67b75755388549ada4ca (patch)
tree65f8ecc6d94ef47124c96cd80e3bd918d05599fa /src/test/script_tests.cpp
parentac3037df1196b1d95ade2dfad4699ad3a6074903 (diff)
downloadbitcoin-f1c33ee4ac1056289f2e67b75755388549ada4ca.tar.xz
tests: implement BIP341 test vectors
Diffstat (limited to 'src/test/script_tests.cpp')
-rw-r--r--src/test/script_tests.cpp76
1 files changed, 76 insertions, 0 deletions
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index 2c39cbffb9..a89eab68e9 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -3,6 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <test/data/script_tests.json.h>
+#include <test/data/bip341_wallet_vectors.json.h>
#include <core_io.h>
#include <fs.h>
@@ -1743,4 +1744,79 @@ BOOST_AUTO_TEST_CASE(script_assets_test)
file.close();
}
+BOOST_AUTO_TEST_CASE(bip341_keypath_test_vectors)
+{
+ UniValue tests;
+ tests.read((const char*)json_tests::bip341_wallet_vectors, sizeof(json_tests::bip341_wallet_vectors));
+
+ const auto& vectors = tests["keyPathSpending"];
+
+ for (const auto& vec : vectors.getValues()) {
+ auto txhex = ParseHex(vec["given"]["rawUnsignedTx"].get_str());
+ CMutableTransaction tx;
+ VectorReader(SER_NETWORK, PROTOCOL_VERSION, txhex, 0) >> tx;
+ std::vector<CTxOut> utxos;
+ for (const auto& utxo_spent : vec["given"]["utxosSpent"].getValues()) {
+ auto script_bytes = ParseHex(utxo_spent["scriptPubKey"].get_str());
+ CScript script{script_bytes.begin(), script_bytes.end()};
+ CAmount amount{utxo_spent["amountSats"].get_int()};
+ utxos.emplace_back(amount, script);
+ }
+
+ PrecomputedTransactionData txdata;
+ txdata.Init(tx, std::vector<CTxOut>{utxos}, true);
+
+ BOOST_CHECK(txdata.m_bip341_taproot_ready);
+ BOOST_CHECK_EQUAL(HexStr(txdata.m_spent_amounts_single_hash), vec["intermediary"]["hashAmounts"].get_str());
+ BOOST_CHECK_EQUAL(HexStr(txdata.m_outputs_single_hash), vec["intermediary"]["hashOutputs"].get_str());
+ BOOST_CHECK_EQUAL(HexStr(txdata.m_prevouts_single_hash), vec["intermediary"]["hashPrevouts"].get_str());
+ BOOST_CHECK_EQUAL(HexStr(txdata.m_spent_scripts_single_hash), vec["intermediary"]["hashScriptPubkeys"].get_str());
+ BOOST_CHECK_EQUAL(HexStr(txdata.m_sequences_single_hash), vec["intermediary"]["hashSequences"].get_str());
+
+ for (const auto& input : vec["inputSpending"].getValues()) {
+ int txinpos = input["given"]["txinIndex"].get_int();
+ int hashtype = input["given"]["hashType"].get_int();
+
+ // Load key.
+ auto privkey = ParseHex(input["given"]["internalPrivkey"].get_str());
+ CKey key;
+ key.Set(privkey.begin(), privkey.end(), true);
+
+ // Load Merkle root.
+ uint256 merkle_root;
+ if (!input["given"]["merkleRoot"].isNull()) {
+ merkle_root = uint256{ParseHex(input["given"]["merkleRoot"].get_str())};
+ }
+
+ // Compute and verify (internal) public key.
+ XOnlyPubKey pubkey{key.GetPubKey()};
+ BOOST_CHECK_EQUAL(HexStr(pubkey), input["intermediary"]["internalPubkey"].get_str());
+
+ // Sign and verify signature.
+ FlatSigningProvider provider;
+ provider.keys[key.GetPubKey().GetID()] = key;
+ MutableTransactionSignatureCreator creator(&tx, txinpos, utxos[txinpos].nValue, &txdata, hashtype);
+ std::vector<unsigned char> signature;
+ BOOST_CHECK(creator.CreateSchnorrSig(provider, signature, pubkey, nullptr, &merkle_root, SigVersion::TAPROOT));
+ BOOST_CHECK_EQUAL(HexStr(signature), input["expected"]["witness"][0].get_str());
+
+ // We can't observe the tweak used inside the signing logic, so verify by recomputing it.
+ BOOST_CHECK_EQUAL(HexStr(pubkey.ComputeTapTweakHash(merkle_root.IsNull() ? nullptr : &merkle_root)), input["intermediary"]["tweak"].get_str());
+
+ // We can't observe the sighash used inside the signing logic, so verify by recomputing it.
+ ScriptExecutionData sed;
+ sed.m_annex_init = true;
+ sed.m_annex_present = false;
+ uint256 sighash;
+ BOOST_CHECK(SignatureHashSchnorr(sighash, sed, tx, txinpos, hashtype, SigVersion::TAPROOT, txdata, MissingDataBehavior::FAIL));
+ BOOST_CHECK_EQUAL(HexStr(sighash), input["intermediary"]["sigHash"].get_str());
+
+ // To verify the sigmsg, hash the expected sigmsg, and compare it with the (expected) sighash.
+ BOOST_CHECK_EQUAL(HexStr((CHashWriter(HASHER_TAPSIGHASH) << MakeSpan(ParseHex(input["intermediary"]["sigMsg"].get_str()))).GetSHA256()), input["intermediary"]["sigHash"].get_str());
+ }
+
+ }
+
+}
+
BOOST_AUTO_TEST_SUITE_END()