diff options
Diffstat (limited to 'src/test/script_tests.cpp')
-rw-r--r-- | src/test/script_tests.cpp | 82 |
1 files changed, 79 insertions, 3 deletions
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 2c39cbffb9..f1304dfc82 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> @@ -283,7 +284,7 @@ public: CScript scriptPubKey = script; if (wm == WitnessMode::PKH) { uint160 hash; - CHash160().Write(MakeSpan(script).subspan(1)).Finalize(hash); + CHash160().Write(Span{script}.subspan(1)).Finalize(hash); script = CScript() << OP_DUP << OP_HASH160 << ToByteVector(hash) << OP_EQUALVERIFY << OP_CHECKSIG; scriptPubKey = CScript() << witnessversion << ToByteVector(hash); } else if (wm == WitnessMode::SH) { @@ -1472,7 +1473,7 @@ BOOST_AUTO_TEST_CASE(script_HasValidOps) static CMutableTransaction TxFromHex(const std::string& str) { CMutableTransaction tx; - VectorReader(SER_DISK, SERIALIZE_TRANSACTION_NO_WITNESS, ParseHex(str), 0) >> tx; + SpanReader{SER_DISK, SERIALIZE_TRANSACTION_NO_WITNESS, ParseHex(str)} >> tx; return tx; } @@ -1482,7 +1483,7 @@ static std::vector<CTxOut> TxOutsFromJSON(const UniValue& univalue) std::vector<CTxOut> prevouts; for (size_t i = 0; i < univalue.size(); ++i) { CTxOut txout; - VectorReader(SER_DISK, 0, ParseHex(univalue[i].get_str()), 0) >> txout; + SpanReader{SER_DISK, 0, ParseHex(univalue[i].get_str())} >> txout; prevouts.push_back(std::move(txout)); } return prevouts; @@ -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; + SpanReader{SER_NETWORK, PROTOCOL_VERSION, txhex} >> 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) << Span{ParseHex(input["intermediary"]["sigMsg"].get_str())}).GetSHA256()), input["intermediary"]["sigHash"].get_str()); + } + + } + +} + BOOST_AUTO_TEST_SUITE_END() |